blob: f6b925553b19ffcee6d6cc3334572ed8252cef17 [file] [log] [blame]
Marco Nelissenb2487f02015-09-01 13:23:23 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "BpMediaSource"
19#include <utils/Log.h>
20
Marco Nelissenb65990f2015-11-09 15:39:49 -080021#include <inttypes.h>
Marco Nelissenb2487f02015-09-01 13:23:23 -070022#include <stdint.h>
23#include <sys/types.h>
24
25#include <binder/Parcel.h>
26#include <media/IMediaSource.h>
27#include <media/stagefright/MediaBuffer.h>
Wei Jiae9a5b962016-02-12 11:38:27 -080028#include <media/stagefright/MediaBufferGroup.h>
Dongwon Kangd91dc5a2017-10-10 00:07:09 -070029#include <media/MediaSource.h>
Marco Nelissenb2487f02015-09-01 13:23:23 -070030#include <media/stagefright/MetaData.h>
31
32namespace android {
33
34enum {
35 START = IBinder::FIRST_CALL_TRANSACTION,
36 STOP,
37 PAUSE,
38 GETFORMAT,
Andy Hungf59c0ba2016-06-15 17:59:30 -070039 // READ, deprecated
Wei Jia1f1fc452016-05-11 16:17:22 -070040 READMULTIPLE,
Andy Hungcdeb6602016-06-28 17:21:44 -070041 RELEASE_BUFFER,
42 SUPPORT_NONBLOCKING_READ,
Marco Nelissenb2487f02015-09-01 13:23:23 -070043};
44
Marco Nelissenb65990f2015-11-09 15:39:49 -080045enum {
46 NULL_BUFFER,
47 SHARED_BUFFER,
Andy Hungf59c0ba2016-06-15 17:59:30 -070048 INLINE_BUFFER,
49 SHARED_BUFFER_INDEX,
Marco Nelissenb65990f2015-11-09 15:39:49 -080050};
51
Marco Nelissenb65990f2015-11-09 15:39:49 -080052class RemoteMediaBufferWrapper : public MediaBuffer {
53public:
Andy Hungf59c0ba2016-06-15 17:59:30 -070054 RemoteMediaBufferWrapper(const sp<IMemory> &mem)
55 : MediaBuffer(mem) {
56 ALOGV("RemoteMediaBufferWrapper: creating %p", this);
57 }
58
Marco Nelissenb65990f2015-11-09 15:39:49 -080059protected:
Andy Hungf59c0ba2016-06-15 17:59:30 -070060 virtual ~RemoteMediaBufferWrapper() {
Andy Hung9bd3c9b2016-09-07 14:42:55 -070061 // Release our interest in the MediaBuffer's shared memory.
62 int32_t old = addRemoteRefcount(-1);
63 ALOGV("RemoteMediaBufferWrapper: releasing %p, refcount %d", this, old - 1);
Andy Hungf59c0ba2016-06-15 17:59:30 -070064 mMemory.clear(); // don't set the dead object flag.
65 }
Marco Nelissenb65990f2015-11-09 15:39:49 -080066};
67
Marco Nelissenb2487f02015-09-01 13:23:23 -070068class BpMediaSource : public BpInterface<IMediaSource> {
69public:
Chih-Hung Hsieh64a28702016-05-03 09:52:51 -070070 explicit BpMediaSource(const sp<IBinder>& impl)
Andy Hungf59c0ba2016-06-15 17:59:30 -070071 : BpInterface<IMediaSource>(impl), mBuffersSinceStop(0)
Marco Nelissenb2487f02015-09-01 13:23:23 -070072 {
73 }
74
75 virtual status_t start(MetaData *params) {
76 ALOGV("start");
77 Parcel data, reply;
78 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
79 if (params) {
80 params->writeToParcel(data);
81 }
82 status_t ret = remote()->transact(START, data, &reply);
83 if (ret == NO_ERROR && params) {
84 ALOGW("ignoring potentially modified MetaData from start");
85 ALOGW("input:");
86 params->dumpToLog();
87 sp<MetaData> meta = MetaData::createFromParcel(reply);
88 ALOGW("output:");
89 meta->dumpToLog();
90 }
91 return ret;
92 }
93
94 virtual status_t stop() {
95 ALOGV("stop");
96 Parcel data, reply;
97 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
Andy Hungf59c0ba2016-06-15 17:59:30 -070098 status_t status = remote()->transact(STOP, data, &reply);
99 mMemoryCache.reset();
100 mBuffersSinceStop = 0;
101 return status;
Marco Nelissenb2487f02015-09-01 13:23:23 -0700102 }
103
104 virtual sp<MetaData> getFormat() {
105 ALOGV("getFormat");
106 Parcel data, reply;
107 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
108 status_t ret = remote()->transact(GETFORMAT, data, &reply);
109 if (ret == NO_ERROR) {
110 mMetaData = MetaData::createFromParcel(reply);
111 return mMetaData;
112 }
113 return NULL;
114 }
115
Dongwon Kang1889c3e2018-02-01 13:44:57 -0800116 virtual status_t read(MediaBufferBase **buffer,
Dongwon Kangd91dc5a2017-10-10 00:07:09 -0700117 const MediaSource::ReadOptions *options) {
Dongwon Kang1889c3e2018-02-01 13:44:57 -0800118 Vector<MediaBufferBase *> buffers;
Andy Hungf59c0ba2016-06-15 17:59:30 -0700119 status_t ret = readMultiple(&buffers, 1 /* maxNumBuffers */, options);
120 *buffer = buffers.size() == 0 ? nullptr : buffers[0];
121 ALOGV("read status %d, bufferCount %u, sinceStop %u",
122 ret, *buffer != nullptr, mBuffersSinceStop);
Marco Nelissenb2487f02015-09-01 13:23:23 -0700123 return ret;
124 }
125
Andy Hungf59c0ba2016-06-15 17:59:30 -0700126 virtual status_t readMultiple(
Dongwon Kang1889c3e2018-02-01 13:44:57 -0800127 Vector<MediaBufferBase *> *buffers, uint32_t maxNumBuffers,
Dongwon Kangd91dc5a2017-10-10 00:07:09 -0700128 const MediaSource::ReadOptions *options) {
Wei Jia1f1fc452016-05-11 16:17:22 -0700129 ALOGV("readMultiple");
130 if (buffers == NULL || !buffers->isEmpty()) {
131 return BAD_VALUE;
132 }
133 Parcel data, reply;
134 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
135 data.writeUint32(maxNumBuffers);
Andy Hungf59c0ba2016-06-15 17:59:30 -0700136 if (options != nullptr) {
137 data.writeByteArray(sizeof(*options), (uint8_t*) options);
138 }
Wei Jia1f1fc452016-05-11 16:17:22 -0700139 status_t ret = remote()->transact(READMULTIPLE, data, &reply);
Andy Hungf59c0ba2016-06-15 17:59:30 -0700140 mMemoryCache.gc();
Wei Jia1f1fc452016-05-11 16:17:22 -0700141 if (ret != NO_ERROR) {
142 return ret;
143 }
144 // wrap the returned data in a vector of MediaBuffers
Andy Hungf59c0ba2016-06-15 17:59:30 -0700145 int32_t buftype;
146 uint32_t bufferCount = 0;
147 while ((buftype = reply.readInt32()) != NULL_BUFFER) {
148 LOG_ALWAYS_FATAL_IF(bufferCount >= maxNumBuffers,
149 "Received %u+ buffers and requested %u buffers",
150 bufferCount + 1, maxNumBuffers);
151 MediaBuffer *buf;
152 if (buftype == SHARED_BUFFER || buftype == SHARED_BUFFER_INDEX) {
153 uint64_t index = reply.readUint64();
154 ALOGV("Received %s index %llu",
155 buftype == SHARED_BUFFER ? "SHARED_BUFFER" : "SHARED_BUFFER_INDEX",
156 (unsigned long long) index);
157 sp<IMemory> mem;
158 if (buftype == SHARED_BUFFER) {
159 sp<IBinder> binder = reply.readStrongBinder();
160 mem = interface_cast<IMemory>(binder);
161 LOG_ALWAYS_FATAL_IF(mem.get() == nullptr,
162 "Received NULL IMemory for shared buffer");
163 mMemoryCache.insert(index, mem);
164 } else {
165 mem = mMemoryCache.lookup(index);
166 LOG_ALWAYS_FATAL_IF(mem.get() == nullptr,
167 "Received invalid IMemory index for shared buffer: %llu",
168 (unsigned long long)index);
169 }
170 size_t offset = reply.readInt32();
171 size_t length = reply.readInt32();
172 buf = new RemoteMediaBufferWrapper(mem);
173 buf->set_range(offset, length);
174 buf->meta_data()->updateFromParcel(reply);
175 } else { // INLINE_BUFFER
176 int32_t len = reply.readInt32();
177 ALOGV("INLINE_BUFFER status %d and len %d", ret, len);
178 buf = new MediaBuffer(len);
179 reply.read(buf->data(), len);
180 buf->meta_data()->updateFromParcel(reply);
Wei Jia1f1fc452016-05-11 16:17:22 -0700181 }
Wei Jia1f1fc452016-05-11 16:17:22 -0700182 buffers->push_back(buf);
Andy Hungf59c0ba2016-06-15 17:59:30 -0700183 ++bufferCount;
184 ++mBuffersSinceStop;
Wei Jia1f1fc452016-05-11 16:17:22 -0700185 }
186 ret = reply.readInt32();
Andy Hungf59c0ba2016-06-15 17:59:30 -0700187 ALOGV("readMultiple status %d, bufferCount %u, sinceStop %u",
188 ret, bufferCount, mBuffersSinceStop);
Wei Jia1f1fc452016-05-11 16:17:22 -0700189 return ret;
190 }
191
Andy Hungcdeb6602016-06-28 17:21:44 -0700192 // Binder proxy adds readMultiple support.
193 virtual bool supportReadMultiple() {
Wei Jiad3f4e142016-06-13 14:51:43 -0700194 return true;
195 }
196
Andy Hungcdeb6602016-06-28 17:21:44 -0700197 virtual bool supportNonblockingRead() {
198 ALOGV("supportNonblockingRead");
199 Parcel data, reply;
200 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
201 status_t ret = remote()->transact(SUPPORT_NONBLOCKING_READ, data, &reply);
202 if (ret == NO_ERROR) {
203 return reply.readInt32() != 0;
204 }
205 return false;
206 }
207
Marco Nelissenb2487f02015-09-01 13:23:23 -0700208 virtual status_t pause() {
209 ALOGV("pause");
210 Parcel data, reply;
211 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
212 return remote()->transact(PAUSE, data, &reply);
213 }
214
Marco Nelissenb2487f02015-09-01 13:23:23 -0700215private:
Andy Hungf59c0ba2016-06-15 17:59:30 -0700216
217 uint32_t mBuffersSinceStop; // Buffer tracking variable
218
Marco Nelissenb2487f02015-09-01 13:23:23 -0700219 // NuPlayer passes pointers-to-metadata around, so we use this to keep the metadata alive
220 // XXX: could we use this for caching, or does metadata change on the fly?
221 sp<MetaData> mMetaData;
Marco Nelissene7d8e712016-03-14 09:29:42 -0700222
Andy Hungf59c0ba2016-06-15 17:59:30 -0700223 // Cache all IMemory objects received from MediaExtractor.
224 // We gc IMemory objects that are no longer active (referenced by a MediaBuffer).
225
226 struct MemoryCache {
227 sp<IMemory> lookup(uint64_t index) {
228 auto p = mIndexToMemory.find(index);
229 if (p == mIndexToMemory.end()) {
230 ALOGE("cannot find index!");
231 return nullptr;
232 }
233 return p->second;
234 }
235
236 void insert(uint64_t index, const sp<IMemory> &mem) {
237 if (mIndexToMemory.find(index) != mIndexToMemory.end()) {
238 ALOGE("index %llu already present", (unsigned long long)index);
239 return;
240 }
241 (void)mIndexToMemory.emplace(index, mem);
242 }
243
244 void reset() {
245 mIndexToMemory.clear();
246 }
247
248 void gc() {
249 for (auto it = mIndexToMemory.begin(); it != mIndexToMemory.end(); ) {
250 if (MediaBuffer::isDeadObject(it->second)) {
251 it = mIndexToMemory.erase(it);
252 } else {
253 ++it;
254 }
255 }
256 }
257 private:
258 // C++14 unordered_map erase on iterator is stable; C++11 has no guarantee.
259 std::map<uint64_t, sp<IMemory>> mIndexToMemory;
260 } mMemoryCache;
Marco Nelissenb2487f02015-09-01 13:23:23 -0700261};
262
263IMPLEMENT_META_INTERFACE(MediaSource, "android.media.IMediaSource");
264
265#undef LOG_TAG
266#define LOG_TAG "BnMediaSource"
267
Wei Jiae9a5b962016-02-12 11:38:27 -0800268BnMediaSource::BnMediaSource()
Andy Hungf59c0ba2016-06-15 17:59:30 -0700269 : mBuffersSinceStop(0)
270 , mGroup(new MediaBufferGroup(kBinderMediaBuffers /* growthLimit */)) {
Wei Jiae9a5b962016-02-12 11:38:27 -0800271}
272
273BnMediaSource::~BnMediaSource() {
Wei Jiae9a5b962016-02-12 11:38:27 -0800274}
275
Marco Nelissenb2487f02015-09-01 13:23:23 -0700276status_t BnMediaSource::onTransact(
277 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
278{
279 switch (code) {
280 case START: {
281 ALOGV("start");
282 CHECK_INTERFACE(IMediaSource, data, reply);
283 sp<MetaData> meta;
284 if (data.dataAvail()) {
285 meta = MetaData::createFromParcel(data);
286 }
287 status_t ret = start(meta.get());
288 if (ret == NO_ERROR && meta != NULL) {
289 meta->writeToParcel(*reply);
290 }
291 return ret;
292 }
293 case STOP: {
294 ALOGV("stop");
295 CHECK_INTERFACE(IMediaSource, data, reply);
Andy Hung9bd3c9b2016-09-07 14:42:55 -0700296 mGroup->signalBufferReturned(nullptr);
Andy Hungf59c0ba2016-06-15 17:59:30 -0700297 status_t status = stop();
Andy Hungf59c0ba2016-06-15 17:59:30 -0700298 mIndexCache.reset();
299 mBuffersSinceStop = 0;
300 return status;
Marco Nelissenb2487f02015-09-01 13:23:23 -0700301 }
302 case PAUSE: {
303 ALOGV("pause");
304 CHECK_INTERFACE(IMediaSource, data, reply);
Andy Hung9bd3c9b2016-09-07 14:42:55 -0700305 mGroup->signalBufferReturned(nullptr);
Marco Nelissenb2487f02015-09-01 13:23:23 -0700306 return pause();
307 }
308 case GETFORMAT: {
309 ALOGV("getFormat");
310 CHECK_INTERFACE(IMediaSource, data, reply);
311 sp<MetaData> meta = getFormat();
312 if (meta != NULL) {
313 meta->writeToParcel(*reply);
314 return NO_ERROR;
315 }
316 return UNKNOWN_ERROR;
317 }
Wei Jia1f1fc452016-05-11 16:17:22 -0700318 case READMULTIPLE: {
Andy Hungf59c0ba2016-06-15 17:59:30 -0700319 ALOGV("readMultiple");
Wei Jia1f1fc452016-05-11 16:17:22 -0700320 CHECK_INTERFACE(IMediaSource, data, reply);
Andy Hungf59c0ba2016-06-15 17:59:30 -0700321
322 // Get max number of buffers to read.
Wei Jia1f1fc452016-05-11 16:17:22 -0700323 uint32_t maxNumBuffers;
324 data.readUint32(&maxNumBuffers);
Wei Jia1f1fc452016-05-11 16:17:22 -0700325 if (maxNumBuffers > kMaxNumReadMultiple) {
326 maxNumBuffers = kMaxNumReadMultiple;
327 }
Andy Hungf59c0ba2016-06-15 17:59:30 -0700328
329 // Get read options, if any.
Dongwon Kangd91dc5a2017-10-10 00:07:09 -0700330 MediaSource::ReadOptions opts;
Andy Hungf59c0ba2016-06-15 17:59:30 -0700331 uint32_t len;
332 const bool useOptions =
333 data.readUint32(&len) == NO_ERROR
334 && len == sizeof(opts)
335 && data.read((void *)&opts, len) == NO_ERROR;
336
Andy Hung9bd3c9b2016-09-07 14:42:55 -0700337 mGroup->signalBufferReturned(nullptr);
Andy Hungf59c0ba2016-06-15 17:59:30 -0700338 mIndexCache.gc();
Andy Hungcdeb6602016-06-28 17:21:44 -0700339 size_t inlineTransferSize = 0;
Andy Hungf59c0ba2016-06-15 17:59:30 -0700340 status_t ret = NO_ERROR;
341 uint32_t bufferCount = 0;
342 for (; bufferCount < maxNumBuffers; ++bufferCount, ++mBuffersSinceStop) {
343 MediaBuffer *buf = nullptr;
Dongwon Kang1889c3e2018-02-01 13:44:57 -0800344 ret = read((MediaBufferBase **)&buf, useOptions ? &opts : nullptr);
Andy Hungf59c0ba2016-06-15 17:59:30 -0700345 opts.clearNonPersistent(); // Remove options that only apply to first buffer.
346 if (ret != NO_ERROR || buf == nullptr) {
Wei Jia1f1fc452016-05-11 16:17:22 -0700347 break;
348 }
349
Andy Hungf59c0ba2016-06-15 17:59:30 -0700350 // Even if we're using shared memory, we might not want to use it, since for small
351 // sizes it's faster to copy data through the Binder transaction
352 // On the other hand, if the data size is large enough, it's better to use shared
353 // memory. When data is too large, binder can't handle it.
354 //
355 // TODO: reduce MediaBuffer::kSharedMemThreshold
356 MediaBuffer *transferBuf = nullptr;
357 const size_t length = buf->range_length();
358 size_t offset = buf->range_offset();
Andy Hungcdeb6602016-06-28 17:21:44 -0700359 if (length >= (supportNonblockingRead() && buf->mMemory != nullptr ?
360 kTransferSharedAsSharedThreshold : kTransferInlineAsSharedThreshold)) {
Andy Hungf59c0ba2016-06-15 17:59:30 -0700361 if (buf->mMemory != nullptr) {
362 ALOGV("Use shared memory: %zu", length);
363 transferBuf = buf;
364 } else {
365 ALOGD("Large buffer %zu without IMemory!", length);
366 ret = mGroup->acquire_buffer(
Dongwon Kang1889c3e2018-02-01 13:44:57 -0800367 (MediaBufferBase **)&transferBuf, false /* nonBlocking */, length);
Andy Hungf59c0ba2016-06-15 17:59:30 -0700368 if (ret != OK
369 || transferBuf == nullptr
370 || transferBuf->mMemory == nullptr) {
371 ALOGW("Failed to acquire shared memory, size %zu, ret %d",
372 length, ret);
373 if (transferBuf != nullptr) {
374 transferBuf->release();
375 transferBuf = nullptr;
376 }
377 // Current buffer transmit inline; no more additional buffers.
378 maxNumBuffers = 0;
379 } else {
380 memcpy(transferBuf->data(), (uint8_t*)buf->data() + offset, length);
381 offset = 0;
Andy Hungcdeb6602016-06-28 17:21:44 -0700382 if (!mGroup->has_buffers()) {
383 maxNumBuffers = 0; // No more MediaBuffers, stop readMultiple.
384 }
Andy Hungf59c0ba2016-06-15 17:59:30 -0700385 }
386 }
Wei Jia1f1fc452016-05-11 16:17:22 -0700387 }
Andy Hungf59c0ba2016-06-15 17:59:30 -0700388 if (transferBuf != nullptr) { // Using shared buffers.
yuedl188454e42017-03-13 18:07:26 +0800389 if (!transferBuf->isObserved() && transferBuf != buf) {
Andy Hungf59c0ba2016-06-15 17:59:30 -0700390 // Transfer buffer must be part of a MediaBufferGroup.
391 ALOGV("adding shared memory buffer %p to local group", transferBuf);
392 mGroup->add_buffer(transferBuf);
393 transferBuf->add_ref(); // We have already acquired buffer.
394 }
395 uint64_t index = mIndexCache.lookup(transferBuf->mMemory);
396 if (index == 0) {
397 index = mIndexCache.insert(transferBuf->mMemory);
398 reply->writeInt32(SHARED_BUFFER);
399 reply->writeUint64(index);
400 reply->writeStrongBinder(IInterface::asBinder(transferBuf->mMemory));
401 ALOGV("SHARED_BUFFER(%p) %llu",
402 transferBuf, (unsigned long long)index);
403 } else {
404 reply->writeInt32(SHARED_BUFFER_INDEX);
405 reply->writeUint64(index);
406 ALOGV("SHARED_BUFFER_INDEX(%p) %llu",
407 transferBuf, (unsigned long long)index);
408 }
409 reply->writeInt32(offset);
410 reply->writeInt32(length);
411 buf->meta_data()->writeToParcel(*reply);
Andy Hung9996d9d2016-09-15 18:19:49 -0700412 transferBuf->addRemoteRefcount(1);
413 if (transferBuf != buf) {
414 transferBuf->release(); // release local ref
415 } else if (!supportNonblockingRead()) {
416 maxNumBuffers = 0; // stop readMultiple with one shared buffer.
Andy Hungf59c0ba2016-06-15 17:59:30 -0700417 }
418 } else {
419 ALOGV_IF(buf->mMemory != nullptr,
420 "INLINE(%p) %zu shared mem available, but only %zu used",
421 buf, buf->mMemory->size(), length);
422 reply->writeInt32(INLINE_BUFFER);
423 reply->writeByteArray(length, (uint8_t*)buf->data() + offset);
424 buf->meta_data()->writeToParcel(*reply);
Andy Hungcdeb6602016-06-28 17:21:44 -0700425 inlineTransferSize += length;
426 if (inlineTransferSize > kInlineMaxTransfer) {
427 maxNumBuffers = 0; // stop readMultiple if inline transfer is too large.
428 }
Andy Hungf59c0ba2016-06-15 17:59:30 -0700429 }
Andy Hung9bd3c9b2016-09-07 14:42:55 -0700430 buf->release();
Wei Jia1f1fc452016-05-11 16:17:22 -0700431 }
Andy Hungf59c0ba2016-06-15 17:59:30 -0700432 reply->writeInt32(NULL_BUFFER); // Indicate no more MediaBuffers.
Wei Jia1f1fc452016-05-11 16:17:22 -0700433 reply->writeInt32(ret);
Andy Hungf59c0ba2016-06-15 17:59:30 -0700434 ALOGV("readMultiple status %d, bufferCount %u, sinceStop %u",
435 ret, bufferCount, mBuffersSinceStop);
Wei Jia1f1fc452016-05-11 16:17:22 -0700436 return NO_ERROR;
437 }
Andy Hungcdeb6602016-06-28 17:21:44 -0700438 case SUPPORT_NONBLOCKING_READ: {
439 ALOGV("supportNonblockingRead");
440 CHECK_INTERFACE(IMediaSource, data, reply);
441 reply->writeInt32((int32_t)supportNonblockingRead());
442 return NO_ERROR;
443 }
Marco Nelissenb2487f02015-09-01 13:23:23 -0700444 default:
445 return BBinder::onTransact(code, data, reply, flags);
446 }
447}
448
Marco Nelissenb2487f02015-09-01 13:23:23 -0700449} // namespace android
450