1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2009 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "BpMediaSource"
19*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
20*ec779b8eSAndroid Build Coastguard Worker
21*ec779b8eSAndroid Build Coastguard Worker #include <inttypes.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <stdint.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <sys/types.h>
24*ec779b8eSAndroid Build Coastguard Worker
25*ec779b8eSAndroid Build Coastguard Worker #include <binder/Parcel.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <media/IMediaSource.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaBuffer.h>
28*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaBufferGroup.h>
29*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaSource.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MetaData.h>
31*ec779b8eSAndroid Build Coastguard Worker
32*ec779b8eSAndroid Build Coastguard Worker namespace android {
33*ec779b8eSAndroid Build Coastguard Worker
34*ec779b8eSAndroid Build Coastguard Worker enum {
35*ec779b8eSAndroid Build Coastguard Worker START = IBinder::FIRST_CALL_TRANSACTION,
36*ec779b8eSAndroid Build Coastguard Worker STOP,
37*ec779b8eSAndroid Build Coastguard Worker PAUSE,
38*ec779b8eSAndroid Build Coastguard Worker GETFORMAT,
39*ec779b8eSAndroid Build Coastguard Worker // READ, deprecated
40*ec779b8eSAndroid Build Coastguard Worker READMULTIPLE,
41*ec779b8eSAndroid Build Coastguard Worker RELEASE_BUFFER,
42*ec779b8eSAndroid Build Coastguard Worker SUPPORT_NONBLOCKING_READ,
43*ec779b8eSAndroid Build Coastguard Worker };
44*ec779b8eSAndroid Build Coastguard Worker
45*ec779b8eSAndroid Build Coastguard Worker enum {
46*ec779b8eSAndroid Build Coastguard Worker NULL_BUFFER,
47*ec779b8eSAndroid Build Coastguard Worker SHARED_BUFFER,
48*ec779b8eSAndroid Build Coastguard Worker INLINE_BUFFER,
49*ec779b8eSAndroid Build Coastguard Worker SHARED_BUFFER_INDEX,
50*ec779b8eSAndroid Build Coastguard Worker };
51*ec779b8eSAndroid Build Coastguard Worker
52*ec779b8eSAndroid Build Coastguard Worker class RemoteMediaBufferWrapper : public MediaBuffer {
53*ec779b8eSAndroid Build Coastguard Worker public:
RemoteMediaBufferWrapper(const sp<IMemory> & mem)54*ec779b8eSAndroid Build Coastguard Worker RemoteMediaBufferWrapper(const sp<IMemory> &mem)
55*ec779b8eSAndroid Build Coastguard Worker : MediaBuffer(mem) {
56*ec779b8eSAndroid Build Coastguard Worker ALOGV("RemoteMediaBufferWrapper: creating %p", this);
57*ec779b8eSAndroid Build Coastguard Worker }
58*ec779b8eSAndroid Build Coastguard Worker
59*ec779b8eSAndroid Build Coastguard Worker protected:
~RemoteMediaBufferWrapper()60*ec779b8eSAndroid Build Coastguard Worker virtual ~RemoteMediaBufferWrapper() {
61*ec779b8eSAndroid Build Coastguard Worker // Release our interest in the MediaBuffer's shared memory.
62*ec779b8eSAndroid Build Coastguard Worker int32_t old = addRemoteRefcount(-1);
63*ec779b8eSAndroid Build Coastguard Worker ALOGV("RemoteMediaBufferWrapper: releasing %p, refcount %d", this, old - 1);
64*ec779b8eSAndroid Build Coastguard Worker mMemory.clear(); // don't set the dead object flag.
65*ec779b8eSAndroid Build Coastguard Worker }
66*ec779b8eSAndroid Build Coastguard Worker };
67*ec779b8eSAndroid Build Coastguard Worker
68*ec779b8eSAndroid Build Coastguard Worker class BpMediaSource : public BpInterface<IMediaSource> {
69*ec779b8eSAndroid Build Coastguard Worker public:
BpMediaSource(const sp<IBinder> & impl)70*ec779b8eSAndroid Build Coastguard Worker explicit BpMediaSource(const sp<IBinder>& impl)
71*ec779b8eSAndroid Build Coastguard Worker : BpInterface<IMediaSource>(impl), mBuffersSinceStop(0)
72*ec779b8eSAndroid Build Coastguard Worker {
73*ec779b8eSAndroid Build Coastguard Worker }
74*ec779b8eSAndroid Build Coastguard Worker
start(MetaData * params)75*ec779b8eSAndroid Build Coastguard Worker virtual status_t start(MetaData *params) {
76*ec779b8eSAndroid Build Coastguard Worker ALOGV("start");
77*ec779b8eSAndroid Build Coastguard Worker Parcel data, reply;
78*ec779b8eSAndroid Build Coastguard Worker data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
79*ec779b8eSAndroid Build Coastguard Worker if (params) {
80*ec779b8eSAndroid Build Coastguard Worker params->writeToParcel(data);
81*ec779b8eSAndroid Build Coastguard Worker }
82*ec779b8eSAndroid Build Coastguard Worker status_t ret = remote()->transact(START, data, &reply);
83*ec779b8eSAndroid Build Coastguard Worker if (ret == NO_ERROR && params) {
84*ec779b8eSAndroid Build Coastguard Worker ALOGW("ignoring potentially modified MetaData from start");
85*ec779b8eSAndroid Build Coastguard Worker ALOGW("input:");
86*ec779b8eSAndroid Build Coastguard Worker params->dumpToLog();
87*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> meta = MetaData::createFromParcel(reply);
88*ec779b8eSAndroid Build Coastguard Worker ALOGW("output:");
89*ec779b8eSAndroid Build Coastguard Worker meta->dumpToLog();
90*ec779b8eSAndroid Build Coastguard Worker }
91*ec779b8eSAndroid Build Coastguard Worker return ret;
92*ec779b8eSAndroid Build Coastguard Worker }
93*ec779b8eSAndroid Build Coastguard Worker
stop()94*ec779b8eSAndroid Build Coastguard Worker virtual status_t stop() {
95*ec779b8eSAndroid Build Coastguard Worker ALOGV("stop");
96*ec779b8eSAndroid Build Coastguard Worker Parcel data, reply;
97*ec779b8eSAndroid Build Coastguard Worker data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
98*ec779b8eSAndroid Build Coastguard Worker status_t status = remote()->transact(STOP, data, &reply);
99*ec779b8eSAndroid Build Coastguard Worker mMemoryCache.reset();
100*ec779b8eSAndroid Build Coastguard Worker mBuffersSinceStop = 0;
101*ec779b8eSAndroid Build Coastguard Worker return status;
102*ec779b8eSAndroid Build Coastguard Worker }
103*ec779b8eSAndroid Build Coastguard Worker
getFormat()104*ec779b8eSAndroid Build Coastguard Worker virtual sp<MetaData> getFormat() {
105*ec779b8eSAndroid Build Coastguard Worker ALOGV("getFormat");
106*ec779b8eSAndroid Build Coastguard Worker Parcel data, reply;
107*ec779b8eSAndroid Build Coastguard Worker data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
108*ec779b8eSAndroid Build Coastguard Worker status_t ret = remote()->transact(GETFORMAT, data, &reply);
109*ec779b8eSAndroid Build Coastguard Worker if (ret == NO_ERROR) {
110*ec779b8eSAndroid Build Coastguard Worker AutoMutex _l(mBpLock);
111*ec779b8eSAndroid Build Coastguard Worker mMetaData = MetaData::createFromParcel(reply);
112*ec779b8eSAndroid Build Coastguard Worker return mMetaData;
113*ec779b8eSAndroid Build Coastguard Worker }
114*ec779b8eSAndroid Build Coastguard Worker return NULL;
115*ec779b8eSAndroid Build Coastguard Worker }
116*ec779b8eSAndroid Build Coastguard Worker
read(MediaBufferBase ** buffer,const MediaSource::ReadOptions * options)117*ec779b8eSAndroid Build Coastguard Worker virtual status_t read(MediaBufferBase **buffer,
118*ec779b8eSAndroid Build Coastguard Worker const MediaSource::ReadOptions *options) {
119*ec779b8eSAndroid Build Coastguard Worker Vector<MediaBufferBase *> buffers;
120*ec779b8eSAndroid Build Coastguard Worker status_t ret = readMultiple(&buffers, 1 /* maxNumBuffers */, options);
121*ec779b8eSAndroid Build Coastguard Worker *buffer = buffers.size() == 0 ? nullptr : buffers[0];
122*ec779b8eSAndroid Build Coastguard Worker ALOGV("read status %d, bufferCount %u, sinceStop %u",
123*ec779b8eSAndroid Build Coastguard Worker ret, *buffer != nullptr, mBuffersSinceStop);
124*ec779b8eSAndroid Build Coastguard Worker return ret;
125*ec779b8eSAndroid Build Coastguard Worker }
126*ec779b8eSAndroid Build Coastguard Worker
readMultiple(Vector<MediaBufferBase * > * buffers,uint32_t maxNumBuffers,const MediaSource::ReadOptions * options)127*ec779b8eSAndroid Build Coastguard Worker virtual status_t readMultiple(
128*ec779b8eSAndroid Build Coastguard Worker Vector<MediaBufferBase *> *buffers, uint32_t maxNumBuffers,
129*ec779b8eSAndroid Build Coastguard Worker const MediaSource::ReadOptions *options) {
130*ec779b8eSAndroid Build Coastguard Worker ALOGV("readMultiple");
131*ec779b8eSAndroid Build Coastguard Worker if (buffers == NULL || !buffers->isEmpty()) {
132*ec779b8eSAndroid Build Coastguard Worker return BAD_VALUE;
133*ec779b8eSAndroid Build Coastguard Worker }
134*ec779b8eSAndroid Build Coastguard Worker Parcel data, reply;
135*ec779b8eSAndroid Build Coastguard Worker data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
136*ec779b8eSAndroid Build Coastguard Worker data.writeUint32(maxNumBuffers);
137*ec779b8eSAndroid Build Coastguard Worker if (options != nullptr) {
138*ec779b8eSAndroid Build Coastguard Worker data.writeByteArray(sizeof(*options), (uint8_t*) options);
139*ec779b8eSAndroid Build Coastguard Worker }
140*ec779b8eSAndroid Build Coastguard Worker status_t ret = remote()->transact(READMULTIPLE, data, &reply);
141*ec779b8eSAndroid Build Coastguard Worker mMemoryCache.gc();
142*ec779b8eSAndroid Build Coastguard Worker if (ret != NO_ERROR) {
143*ec779b8eSAndroid Build Coastguard Worker return ret;
144*ec779b8eSAndroid Build Coastguard Worker }
145*ec779b8eSAndroid Build Coastguard Worker // wrap the returned data in a vector of MediaBuffers
146*ec779b8eSAndroid Build Coastguard Worker int32_t buftype;
147*ec779b8eSAndroid Build Coastguard Worker uint32_t bufferCount = 0;
148*ec779b8eSAndroid Build Coastguard Worker while ((buftype = reply.readInt32()) != NULL_BUFFER) {
149*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(bufferCount >= maxNumBuffers,
150*ec779b8eSAndroid Build Coastguard Worker "Received %u+ buffers and requested %u buffers",
151*ec779b8eSAndroid Build Coastguard Worker bufferCount + 1, maxNumBuffers);
152*ec779b8eSAndroid Build Coastguard Worker MediaBuffer *buf;
153*ec779b8eSAndroid Build Coastguard Worker if (buftype == SHARED_BUFFER || buftype == SHARED_BUFFER_INDEX) {
154*ec779b8eSAndroid Build Coastguard Worker uint64_t index = reply.readUint64();
155*ec779b8eSAndroid Build Coastguard Worker ALOGV("Received %s index %llu",
156*ec779b8eSAndroid Build Coastguard Worker buftype == SHARED_BUFFER ? "SHARED_BUFFER" : "SHARED_BUFFER_INDEX",
157*ec779b8eSAndroid Build Coastguard Worker (unsigned long long) index);
158*ec779b8eSAndroid Build Coastguard Worker sp<IMemory> mem;
159*ec779b8eSAndroid Build Coastguard Worker if (buftype == SHARED_BUFFER) {
160*ec779b8eSAndroid Build Coastguard Worker sp<IBinder> binder = reply.readStrongBinder();
161*ec779b8eSAndroid Build Coastguard Worker mem = interface_cast<IMemory>(binder);
162*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mem.get() == nullptr,
163*ec779b8eSAndroid Build Coastguard Worker "Received NULL IMemory for shared buffer");
164*ec779b8eSAndroid Build Coastguard Worker mMemoryCache.insert(index, mem);
165*ec779b8eSAndroid Build Coastguard Worker } else {
166*ec779b8eSAndroid Build Coastguard Worker mem = mMemoryCache.lookup(index);
167*ec779b8eSAndroid Build Coastguard Worker LOG_ALWAYS_FATAL_IF(mem.get() == nullptr,
168*ec779b8eSAndroid Build Coastguard Worker "Received invalid IMemory index for shared buffer: %llu",
169*ec779b8eSAndroid Build Coastguard Worker (unsigned long long)index);
170*ec779b8eSAndroid Build Coastguard Worker }
171*ec779b8eSAndroid Build Coastguard Worker size_t offset = reply.readInt32();
172*ec779b8eSAndroid Build Coastguard Worker size_t length = reply.readInt32();
173*ec779b8eSAndroid Build Coastguard Worker buf = new RemoteMediaBufferWrapper(mem);
174*ec779b8eSAndroid Build Coastguard Worker buf->set_range(offset, length);
175*ec779b8eSAndroid Build Coastguard Worker buf->meta_data().updateFromParcel(reply);
176*ec779b8eSAndroid Build Coastguard Worker } else { // INLINE_BUFFER
177*ec779b8eSAndroid Build Coastguard Worker int32_t len = reply.readInt32();
178*ec779b8eSAndroid Build Coastguard Worker ALOGV("INLINE_BUFFER status %d and len %d", ret, len);
179*ec779b8eSAndroid Build Coastguard Worker buf = new MediaBuffer(len);
180*ec779b8eSAndroid Build Coastguard Worker reply.read(buf->data(), len);
181*ec779b8eSAndroid Build Coastguard Worker buf->meta_data().updateFromParcel(reply);
182*ec779b8eSAndroid Build Coastguard Worker }
183*ec779b8eSAndroid Build Coastguard Worker buffers->push_back(buf);
184*ec779b8eSAndroid Build Coastguard Worker ++bufferCount;
185*ec779b8eSAndroid Build Coastguard Worker ++mBuffersSinceStop;
186*ec779b8eSAndroid Build Coastguard Worker }
187*ec779b8eSAndroid Build Coastguard Worker ret = reply.readInt32();
188*ec779b8eSAndroid Build Coastguard Worker ALOGV("readMultiple status %d, bufferCount %u, sinceStop %u",
189*ec779b8eSAndroid Build Coastguard Worker ret, bufferCount, mBuffersSinceStop);
190*ec779b8eSAndroid Build Coastguard Worker if (bufferCount && ret == WOULD_BLOCK) {
191*ec779b8eSAndroid Build Coastguard Worker ret = OK;
192*ec779b8eSAndroid Build Coastguard Worker }
193*ec779b8eSAndroid Build Coastguard Worker return ret;
194*ec779b8eSAndroid Build Coastguard Worker }
195*ec779b8eSAndroid Build Coastguard Worker
196*ec779b8eSAndroid Build Coastguard Worker // Binder proxy adds readMultiple support.
supportReadMultiple()197*ec779b8eSAndroid Build Coastguard Worker virtual bool supportReadMultiple() {
198*ec779b8eSAndroid Build Coastguard Worker return true;
199*ec779b8eSAndroid Build Coastguard Worker }
200*ec779b8eSAndroid Build Coastguard Worker
supportNonblockingRead()201*ec779b8eSAndroid Build Coastguard Worker virtual bool supportNonblockingRead() {
202*ec779b8eSAndroid Build Coastguard Worker ALOGV("supportNonblockingRead");
203*ec779b8eSAndroid Build Coastguard Worker Parcel data, reply;
204*ec779b8eSAndroid Build Coastguard Worker data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
205*ec779b8eSAndroid Build Coastguard Worker status_t ret = remote()->transact(SUPPORT_NONBLOCKING_READ, data, &reply);
206*ec779b8eSAndroid Build Coastguard Worker if (ret == NO_ERROR) {
207*ec779b8eSAndroid Build Coastguard Worker return reply.readInt32() != 0;
208*ec779b8eSAndroid Build Coastguard Worker }
209*ec779b8eSAndroid Build Coastguard Worker return false;
210*ec779b8eSAndroid Build Coastguard Worker }
211*ec779b8eSAndroid Build Coastguard Worker
pause()212*ec779b8eSAndroid Build Coastguard Worker virtual status_t pause() {
213*ec779b8eSAndroid Build Coastguard Worker ALOGV("pause");
214*ec779b8eSAndroid Build Coastguard Worker Parcel data, reply;
215*ec779b8eSAndroid Build Coastguard Worker data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
216*ec779b8eSAndroid Build Coastguard Worker return remote()->transact(PAUSE, data, &reply);
217*ec779b8eSAndroid Build Coastguard Worker }
218*ec779b8eSAndroid Build Coastguard Worker
219*ec779b8eSAndroid Build Coastguard Worker private:
220*ec779b8eSAndroid Build Coastguard Worker
221*ec779b8eSAndroid Build Coastguard Worker uint32_t mBuffersSinceStop; // Buffer tracking variable
222*ec779b8eSAndroid Build Coastguard Worker
223*ec779b8eSAndroid Build Coastguard Worker // NuPlayer passes pointers-to-metadata around, so we use this to keep the metadata alive
224*ec779b8eSAndroid Build Coastguard Worker // XXX: could we use this for caching, or does metadata change on the fly?
225*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> mMetaData;
226*ec779b8eSAndroid Build Coastguard Worker // ensure synchronize access to mMetaData
227*ec779b8eSAndroid Build Coastguard Worker Mutex mBpLock;
228*ec779b8eSAndroid Build Coastguard Worker
229*ec779b8eSAndroid Build Coastguard Worker // Cache all IMemory objects received from MediaExtractor.
230*ec779b8eSAndroid Build Coastguard Worker // We gc IMemory objects that are no longer active (referenced by a MediaBuffer).
231*ec779b8eSAndroid Build Coastguard Worker
232*ec779b8eSAndroid Build Coastguard Worker struct MemoryCache {
lookupandroid::BpMediaSource::MemoryCache233*ec779b8eSAndroid Build Coastguard Worker sp<IMemory> lookup(uint64_t index) {
234*ec779b8eSAndroid Build Coastguard Worker auto p = mIndexToMemory.find(index);
235*ec779b8eSAndroid Build Coastguard Worker if (p == mIndexToMemory.end()) {
236*ec779b8eSAndroid Build Coastguard Worker ALOGE("cannot find index!");
237*ec779b8eSAndroid Build Coastguard Worker return nullptr;
238*ec779b8eSAndroid Build Coastguard Worker }
239*ec779b8eSAndroid Build Coastguard Worker return p->second;
240*ec779b8eSAndroid Build Coastguard Worker }
241*ec779b8eSAndroid Build Coastguard Worker
insertandroid::BpMediaSource::MemoryCache242*ec779b8eSAndroid Build Coastguard Worker void insert(uint64_t index, const sp<IMemory> &mem) {
243*ec779b8eSAndroid Build Coastguard Worker if (mIndexToMemory.find(index) != mIndexToMemory.end()) {
244*ec779b8eSAndroid Build Coastguard Worker ALOGE("index %llu already present", (unsigned long long)index);
245*ec779b8eSAndroid Build Coastguard Worker return;
246*ec779b8eSAndroid Build Coastguard Worker }
247*ec779b8eSAndroid Build Coastguard Worker (void)mIndexToMemory.emplace(index, mem);
248*ec779b8eSAndroid Build Coastguard Worker }
249*ec779b8eSAndroid Build Coastguard Worker
resetandroid::BpMediaSource::MemoryCache250*ec779b8eSAndroid Build Coastguard Worker void reset() {
251*ec779b8eSAndroid Build Coastguard Worker mIndexToMemory.clear();
252*ec779b8eSAndroid Build Coastguard Worker }
253*ec779b8eSAndroid Build Coastguard Worker
gcandroid::BpMediaSource::MemoryCache254*ec779b8eSAndroid Build Coastguard Worker void gc() {
255*ec779b8eSAndroid Build Coastguard Worker for (auto it = mIndexToMemory.begin(); it != mIndexToMemory.end(); ) {
256*ec779b8eSAndroid Build Coastguard Worker if (MediaBuffer::isDeadObject(it->second)) {
257*ec779b8eSAndroid Build Coastguard Worker it = mIndexToMemory.erase(it);
258*ec779b8eSAndroid Build Coastguard Worker } else {
259*ec779b8eSAndroid Build Coastguard Worker ++it;
260*ec779b8eSAndroid Build Coastguard Worker }
261*ec779b8eSAndroid Build Coastguard Worker }
262*ec779b8eSAndroid Build Coastguard Worker }
263*ec779b8eSAndroid Build Coastguard Worker private:
264*ec779b8eSAndroid Build Coastguard Worker // C++14 unordered_map erase on iterator is stable; C++11 has no guarantee.
265*ec779b8eSAndroid Build Coastguard Worker std::map<uint64_t, sp<IMemory>> mIndexToMemory;
266*ec779b8eSAndroid Build Coastguard Worker } mMemoryCache;
267*ec779b8eSAndroid Build Coastguard Worker };
268*ec779b8eSAndroid Build Coastguard Worker
269*ec779b8eSAndroid Build Coastguard Worker IMPLEMENT_META_INTERFACE(MediaSource, "android.media.IMediaSource");
270*ec779b8eSAndroid Build Coastguard Worker
271*ec779b8eSAndroid Build Coastguard Worker #undef LOG_TAG
272*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "BnMediaSource"
273*ec779b8eSAndroid Build Coastguard Worker
BnMediaSource()274*ec779b8eSAndroid Build Coastguard Worker BnMediaSource::BnMediaSource()
275*ec779b8eSAndroid Build Coastguard Worker : mBuffersSinceStop(0)
276*ec779b8eSAndroid Build Coastguard Worker , mGroup(new MediaBufferGroup(kBinderMediaBuffers /* growthLimit */)) {
277*ec779b8eSAndroid Build Coastguard Worker }
278*ec779b8eSAndroid Build Coastguard Worker
~BnMediaSource()279*ec779b8eSAndroid Build Coastguard Worker BnMediaSource::~BnMediaSource() {
280*ec779b8eSAndroid Build Coastguard Worker }
281*ec779b8eSAndroid Build Coastguard Worker
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)282*ec779b8eSAndroid Build Coastguard Worker status_t BnMediaSource::onTransact(
283*ec779b8eSAndroid Build Coastguard Worker uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
284*ec779b8eSAndroid Build Coastguard Worker {
285*ec779b8eSAndroid Build Coastguard Worker switch (code) {
286*ec779b8eSAndroid Build Coastguard Worker case START: {
287*ec779b8eSAndroid Build Coastguard Worker ALOGV("start");
288*ec779b8eSAndroid Build Coastguard Worker CHECK_INTERFACE(IMediaSource, data, reply);
289*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> meta;
290*ec779b8eSAndroid Build Coastguard Worker if (data.dataAvail()) {
291*ec779b8eSAndroid Build Coastguard Worker meta = MetaData::createFromParcel(data);
292*ec779b8eSAndroid Build Coastguard Worker }
293*ec779b8eSAndroid Build Coastguard Worker status_t ret = start(meta.get());
294*ec779b8eSAndroid Build Coastguard Worker if (ret == NO_ERROR && meta != NULL) {
295*ec779b8eSAndroid Build Coastguard Worker meta->writeToParcel(*reply);
296*ec779b8eSAndroid Build Coastguard Worker }
297*ec779b8eSAndroid Build Coastguard Worker return ret;
298*ec779b8eSAndroid Build Coastguard Worker }
299*ec779b8eSAndroid Build Coastguard Worker case STOP: {
300*ec779b8eSAndroid Build Coastguard Worker ALOGV("stop");
301*ec779b8eSAndroid Build Coastguard Worker CHECK_INTERFACE(IMediaSource, data, reply);
302*ec779b8eSAndroid Build Coastguard Worker mGroup->signalBufferReturned(nullptr);
303*ec779b8eSAndroid Build Coastguard Worker status_t status = stop();
304*ec779b8eSAndroid Build Coastguard Worker AutoMutex _l(mBnLock);
305*ec779b8eSAndroid Build Coastguard Worker mIndexCache.reset();
306*ec779b8eSAndroid Build Coastguard Worker mBuffersSinceStop = 0;
307*ec779b8eSAndroid Build Coastguard Worker return status;
308*ec779b8eSAndroid Build Coastguard Worker }
309*ec779b8eSAndroid Build Coastguard Worker case PAUSE: {
310*ec779b8eSAndroid Build Coastguard Worker ALOGV("pause");
311*ec779b8eSAndroid Build Coastguard Worker CHECK_INTERFACE(IMediaSource, data, reply);
312*ec779b8eSAndroid Build Coastguard Worker mGroup->signalBufferReturned(nullptr);
313*ec779b8eSAndroid Build Coastguard Worker return pause();
314*ec779b8eSAndroid Build Coastguard Worker }
315*ec779b8eSAndroid Build Coastguard Worker case GETFORMAT: {
316*ec779b8eSAndroid Build Coastguard Worker ALOGV("getFormat");
317*ec779b8eSAndroid Build Coastguard Worker CHECK_INTERFACE(IMediaSource, data, reply);
318*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> meta = getFormat();
319*ec779b8eSAndroid Build Coastguard Worker if (meta != NULL) {
320*ec779b8eSAndroid Build Coastguard Worker meta->writeToParcel(*reply);
321*ec779b8eSAndroid Build Coastguard Worker return NO_ERROR;
322*ec779b8eSAndroid Build Coastguard Worker }
323*ec779b8eSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
324*ec779b8eSAndroid Build Coastguard Worker }
325*ec779b8eSAndroid Build Coastguard Worker case READMULTIPLE: {
326*ec779b8eSAndroid Build Coastguard Worker ALOGV("readMultiple");
327*ec779b8eSAndroid Build Coastguard Worker CHECK_INTERFACE(IMediaSource, data, reply);
328*ec779b8eSAndroid Build Coastguard Worker
329*ec779b8eSAndroid Build Coastguard Worker // Get max number of buffers to read.
330*ec779b8eSAndroid Build Coastguard Worker uint32_t maxNumBuffers;
331*ec779b8eSAndroid Build Coastguard Worker data.readUint32(&maxNumBuffers);
332*ec779b8eSAndroid Build Coastguard Worker if (maxNumBuffers > kMaxNumReadMultiple) {
333*ec779b8eSAndroid Build Coastguard Worker maxNumBuffers = kMaxNumReadMultiple;
334*ec779b8eSAndroid Build Coastguard Worker }
335*ec779b8eSAndroid Build Coastguard Worker
336*ec779b8eSAndroid Build Coastguard Worker // Get read options, if any.
337*ec779b8eSAndroid Build Coastguard Worker MediaSource::ReadOptions opts;
338*ec779b8eSAndroid Build Coastguard Worker uint32_t len;
339*ec779b8eSAndroid Build Coastguard Worker const bool useOptions =
340*ec779b8eSAndroid Build Coastguard Worker data.readUint32(&len) == NO_ERROR
341*ec779b8eSAndroid Build Coastguard Worker && len == sizeof(opts)
342*ec779b8eSAndroid Build Coastguard Worker && data.read((void *)&opts, len) == NO_ERROR;
343*ec779b8eSAndroid Build Coastguard Worker
344*ec779b8eSAndroid Build Coastguard Worker AutoMutex _l(mBnLock);
345*ec779b8eSAndroid Build Coastguard Worker mGroup->signalBufferReturned(nullptr);
346*ec779b8eSAndroid Build Coastguard Worker mIndexCache.gc();
347*ec779b8eSAndroid Build Coastguard Worker size_t inlineTransferSize = 0;
348*ec779b8eSAndroid Build Coastguard Worker status_t ret = NO_ERROR;
349*ec779b8eSAndroid Build Coastguard Worker uint32_t bufferCount = 0;
350*ec779b8eSAndroid Build Coastguard Worker for (; bufferCount < maxNumBuffers; ++bufferCount, ++mBuffersSinceStop) {
351*ec779b8eSAndroid Build Coastguard Worker MediaBuffer *buf = nullptr;
352*ec779b8eSAndroid Build Coastguard Worker ret = read((MediaBufferBase **)&buf, useOptions ? &opts : nullptr);
353*ec779b8eSAndroid Build Coastguard Worker opts.clearNonPersistent(); // Remove options that only apply to first buffer.
354*ec779b8eSAndroid Build Coastguard Worker if (ret != NO_ERROR || buf == nullptr) {
355*ec779b8eSAndroid Build Coastguard Worker break;
356*ec779b8eSAndroid Build Coastguard Worker }
357*ec779b8eSAndroid Build Coastguard Worker
358*ec779b8eSAndroid Build Coastguard Worker // Even if we're using shared memory, we might not want to use it, since for small
359*ec779b8eSAndroid Build Coastguard Worker // sizes it's faster to copy data through the Binder transaction
360*ec779b8eSAndroid Build Coastguard Worker // On the other hand, if the data size is large enough, it's better to use shared
361*ec779b8eSAndroid Build Coastguard Worker // memory. When data is too large, binder can't handle it.
362*ec779b8eSAndroid Build Coastguard Worker //
363*ec779b8eSAndroid Build Coastguard Worker // TODO: reduce MediaBuffer::kSharedMemThreshold
364*ec779b8eSAndroid Build Coastguard Worker MediaBuffer *transferBuf = nullptr;
365*ec779b8eSAndroid Build Coastguard Worker const size_t length = buf->range_length();
366*ec779b8eSAndroid Build Coastguard Worker size_t offset = buf->range_offset();
367*ec779b8eSAndroid Build Coastguard Worker if (length >= (supportNonblockingRead() && buf->mMemory != nullptr ?
368*ec779b8eSAndroid Build Coastguard Worker kTransferSharedAsSharedThreshold : kTransferInlineAsSharedThreshold)) {
369*ec779b8eSAndroid Build Coastguard Worker if (buf->mMemory != nullptr) {
370*ec779b8eSAndroid Build Coastguard Worker ALOGV("Use shared memory: %zu", length);
371*ec779b8eSAndroid Build Coastguard Worker transferBuf = buf;
372*ec779b8eSAndroid Build Coastguard Worker } else {
373*ec779b8eSAndroid Build Coastguard Worker ALOGV("Large buffer %zu without IMemory!", length);
374*ec779b8eSAndroid Build Coastguard Worker ret = mGroup->acquire_buffer(
375*ec779b8eSAndroid Build Coastguard Worker (MediaBufferBase **)&transferBuf, false /* nonBlocking */, length);
376*ec779b8eSAndroid Build Coastguard Worker if (ret != OK
377*ec779b8eSAndroid Build Coastguard Worker || transferBuf == nullptr
378*ec779b8eSAndroid Build Coastguard Worker || transferBuf->mMemory == nullptr) {
379*ec779b8eSAndroid Build Coastguard Worker ALOGV("Failed to acquire shared memory, size %zu, ret %d",
380*ec779b8eSAndroid Build Coastguard Worker length, ret);
381*ec779b8eSAndroid Build Coastguard Worker if (transferBuf != nullptr) {
382*ec779b8eSAndroid Build Coastguard Worker transferBuf->release();
383*ec779b8eSAndroid Build Coastguard Worker transferBuf = nullptr;
384*ec779b8eSAndroid Build Coastguard Worker }
385*ec779b8eSAndroid Build Coastguard Worker // Current buffer transmit inline; no more additional buffers.
386*ec779b8eSAndroid Build Coastguard Worker maxNumBuffers = 0;
387*ec779b8eSAndroid Build Coastguard Worker } else {
388*ec779b8eSAndroid Build Coastguard Worker memcpy(transferBuf->data(), (uint8_t*)buf->data() + offset, length);
389*ec779b8eSAndroid Build Coastguard Worker offset = 0;
390*ec779b8eSAndroid Build Coastguard Worker if (!mGroup->has_buffers()) {
391*ec779b8eSAndroid Build Coastguard Worker maxNumBuffers = 0; // No more MediaBuffers, stop readMultiple.
392*ec779b8eSAndroid Build Coastguard Worker }
393*ec779b8eSAndroid Build Coastguard Worker }
394*ec779b8eSAndroid Build Coastguard Worker }
395*ec779b8eSAndroid Build Coastguard Worker }
396*ec779b8eSAndroid Build Coastguard Worker if (transferBuf != nullptr) { // Using shared buffers.
397*ec779b8eSAndroid Build Coastguard Worker if (!transferBuf->isObserved() && transferBuf != buf) {
398*ec779b8eSAndroid Build Coastguard Worker // Transfer buffer must be part of a MediaBufferGroup.
399*ec779b8eSAndroid Build Coastguard Worker ALOGV("adding shared memory buffer %p to local group", transferBuf);
400*ec779b8eSAndroid Build Coastguard Worker mGroup->add_buffer(transferBuf);
401*ec779b8eSAndroid Build Coastguard Worker transferBuf->add_ref(); // We have already acquired buffer.
402*ec779b8eSAndroid Build Coastguard Worker }
403*ec779b8eSAndroid Build Coastguard Worker uint64_t index = mIndexCache.lookup(transferBuf->mMemory);
404*ec779b8eSAndroid Build Coastguard Worker if (index == 0) {
405*ec779b8eSAndroid Build Coastguard Worker index = mIndexCache.insert(transferBuf->mMemory);
406*ec779b8eSAndroid Build Coastguard Worker reply->writeInt32(SHARED_BUFFER);
407*ec779b8eSAndroid Build Coastguard Worker reply->writeUint64(index);
408*ec779b8eSAndroid Build Coastguard Worker reply->writeStrongBinder(IInterface::asBinder(transferBuf->mMemory));
409*ec779b8eSAndroid Build Coastguard Worker ALOGV("SHARED_BUFFER(%p) %llu",
410*ec779b8eSAndroid Build Coastguard Worker transferBuf, (unsigned long long)index);
411*ec779b8eSAndroid Build Coastguard Worker } else {
412*ec779b8eSAndroid Build Coastguard Worker reply->writeInt32(SHARED_BUFFER_INDEX);
413*ec779b8eSAndroid Build Coastguard Worker reply->writeUint64(index);
414*ec779b8eSAndroid Build Coastguard Worker ALOGV("SHARED_BUFFER_INDEX(%p) %llu",
415*ec779b8eSAndroid Build Coastguard Worker transferBuf, (unsigned long long)index);
416*ec779b8eSAndroid Build Coastguard Worker }
417*ec779b8eSAndroid Build Coastguard Worker reply->writeInt32(offset);
418*ec779b8eSAndroid Build Coastguard Worker reply->writeInt32(length);
419*ec779b8eSAndroid Build Coastguard Worker buf->meta_data().writeToParcel(*reply);
420*ec779b8eSAndroid Build Coastguard Worker transferBuf->addRemoteRefcount(1);
421*ec779b8eSAndroid Build Coastguard Worker if (transferBuf != buf) {
422*ec779b8eSAndroid Build Coastguard Worker transferBuf->release(); // release local ref
423*ec779b8eSAndroid Build Coastguard Worker } else if (!supportNonblockingRead()) {
424*ec779b8eSAndroid Build Coastguard Worker maxNumBuffers = 0; // stop readMultiple with one shared buffer.
425*ec779b8eSAndroid Build Coastguard Worker }
426*ec779b8eSAndroid Build Coastguard Worker } else {
427*ec779b8eSAndroid Build Coastguard Worker ALOGV_IF(buf->mMemory != nullptr,
428*ec779b8eSAndroid Build Coastguard Worker "INLINE(%p) %zu shared mem available, but only %zu used",
429*ec779b8eSAndroid Build Coastguard Worker buf, buf->mMemory->size(), length);
430*ec779b8eSAndroid Build Coastguard Worker reply->writeInt32(INLINE_BUFFER);
431*ec779b8eSAndroid Build Coastguard Worker reply->writeByteArray(length, (uint8_t*)buf->data() + offset);
432*ec779b8eSAndroid Build Coastguard Worker buf->meta_data().writeToParcel(*reply);
433*ec779b8eSAndroid Build Coastguard Worker inlineTransferSize += length;
434*ec779b8eSAndroid Build Coastguard Worker if (inlineTransferSize > kInlineMaxTransfer) {
435*ec779b8eSAndroid Build Coastguard Worker maxNumBuffers = 0; // stop readMultiple if inline transfer is too large.
436*ec779b8eSAndroid Build Coastguard Worker }
437*ec779b8eSAndroid Build Coastguard Worker }
438*ec779b8eSAndroid Build Coastguard Worker buf->release();
439*ec779b8eSAndroid Build Coastguard Worker }
440*ec779b8eSAndroid Build Coastguard Worker reply->writeInt32(NULL_BUFFER); // Indicate no more MediaBuffers.
441*ec779b8eSAndroid Build Coastguard Worker reply->writeInt32(ret);
442*ec779b8eSAndroid Build Coastguard Worker ALOGV("readMultiple status %d, bufferCount %u, sinceStop %u",
443*ec779b8eSAndroid Build Coastguard Worker ret, bufferCount, mBuffersSinceStop);
444*ec779b8eSAndroid Build Coastguard Worker return NO_ERROR;
445*ec779b8eSAndroid Build Coastguard Worker }
446*ec779b8eSAndroid Build Coastguard Worker case SUPPORT_NONBLOCKING_READ: {
447*ec779b8eSAndroid Build Coastguard Worker ALOGV("supportNonblockingRead");
448*ec779b8eSAndroid Build Coastguard Worker CHECK_INTERFACE(IMediaSource, data, reply);
449*ec779b8eSAndroid Build Coastguard Worker reply->writeInt32((int32_t)supportNonblockingRead());
450*ec779b8eSAndroid Build Coastguard Worker return NO_ERROR;
451*ec779b8eSAndroid Build Coastguard Worker }
452*ec779b8eSAndroid Build Coastguard Worker default:
453*ec779b8eSAndroid Build Coastguard Worker return BBinder::onTransact(code, data, reply, flags);
454*ec779b8eSAndroid Build Coastguard Worker }
455*ec779b8eSAndroid Build Coastguard Worker }
456*ec779b8eSAndroid Build Coastguard Worker
457*ec779b8eSAndroid Build Coastguard Worker } // namespace android
458*ec779b8eSAndroid Build Coastguard Worker
459