blob: 2adce192bd7ebfae2fc98b16a6cebf102c7d63b6 [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>
Marco Nelissenb2487f02015-09-01 13:23:23 -070029#include <media/stagefright/MediaSource.h>
30#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,
Marco Nelissenb65990f2015-11-09 15:39:49 -080041 RELEASE_BUFFER
Marco Nelissenb2487f02015-09-01 13:23:23 -070042};
43
Marco Nelissenb65990f2015-11-09 15:39:49 -080044enum {
45 NULL_BUFFER,
46 SHARED_BUFFER,
Andy Hungf59c0ba2016-06-15 17:59:30 -070047 INLINE_BUFFER,
48 SHARED_BUFFER_INDEX,
Marco Nelissenb65990f2015-11-09 15:39:49 -080049};
50
Marco Nelissenb65990f2015-11-09 15:39:49 -080051class RemoteMediaBufferWrapper : public MediaBuffer {
52public:
Andy Hungf59c0ba2016-06-15 17:59:30 -070053 RemoteMediaBufferWrapper(const sp<IMemory> &mem)
54 : MediaBuffer(mem) {
55 ALOGV("RemoteMediaBufferWrapper: creating %p", this);
56 }
57
Marco Nelissenb65990f2015-11-09 15:39:49 -080058protected:
Andy Hungf59c0ba2016-06-15 17:59:30 -070059 virtual ~RemoteMediaBufferWrapper() {
60 // Indicate to MediaBufferGroup to release.
61 int32_t old = addPendingRelease(1);
62 ALOGV("RemoteMediaBufferWrapper: releasing %p, old %d", this, old);
63 mMemory.clear(); // don't set the dead object flag.
64 }
Marco Nelissenb65990f2015-11-09 15:39:49 -080065};
66
Marco Nelissenb2487f02015-09-01 13:23:23 -070067class BpMediaSource : public BpInterface<IMediaSource> {
68public:
69 BpMediaSource(const sp<IBinder>& impl)
Andy Hungf59c0ba2016-06-15 17:59:30 -070070 : BpInterface<IMediaSource>(impl), mBuffersSinceStop(0)
Marco Nelissenb2487f02015-09-01 13:23:23 -070071 {
72 }
73
74 virtual status_t start(MetaData *params) {
75 ALOGV("start");
76 Parcel data, reply;
77 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
78 if (params) {
79 params->writeToParcel(data);
80 }
81 status_t ret = remote()->transact(START, data, &reply);
82 if (ret == NO_ERROR && params) {
83 ALOGW("ignoring potentially modified MetaData from start");
84 ALOGW("input:");
85 params->dumpToLog();
86 sp<MetaData> meta = MetaData::createFromParcel(reply);
87 ALOGW("output:");
88 meta->dumpToLog();
89 }
90 return ret;
91 }
92
93 virtual status_t stop() {
94 ALOGV("stop");
95 Parcel data, reply;
96 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
Andy Hungf59c0ba2016-06-15 17:59:30 -070097 status_t status = remote()->transact(STOP, data, &reply);
98 mMemoryCache.reset();
99 mBuffersSinceStop = 0;
100 return status;
Marco Nelissenb2487f02015-09-01 13:23:23 -0700101 }
102
103 virtual sp<MetaData> getFormat() {
104 ALOGV("getFormat");
105 Parcel data, reply;
106 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
107 status_t ret = remote()->transact(GETFORMAT, data, &reply);
108 if (ret == NO_ERROR) {
109 mMetaData = MetaData::createFromParcel(reply);
110 return mMetaData;
111 }
112 return NULL;
113 }
114
115 virtual status_t read(MediaBuffer **buffer, const ReadOptions *options) {
Andy Hungf59c0ba2016-06-15 17:59:30 -0700116 Vector<MediaBuffer *> buffers;
117 status_t ret = readMultiple(&buffers, 1 /* maxNumBuffers */, options);
118 *buffer = buffers.size() == 0 ? nullptr : buffers[0];
119 ALOGV("read status %d, bufferCount %u, sinceStop %u",
120 ret, *buffer != nullptr, mBuffersSinceStop);
Marco Nelissenb2487f02015-09-01 13:23:23 -0700121 return ret;
122 }
123
Andy Hungf59c0ba2016-06-15 17:59:30 -0700124 virtual status_t readMultiple(
125 Vector<MediaBuffer *> *buffers, uint32_t maxNumBuffers, const ReadOptions *options) {
Wei Jia1f1fc452016-05-11 16:17:22 -0700126 ALOGV("readMultiple");
127 if (buffers == NULL || !buffers->isEmpty()) {
128 return BAD_VALUE;
129 }
130 Parcel data, reply;
131 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
132 data.writeUint32(maxNumBuffers);
Andy Hungf59c0ba2016-06-15 17:59:30 -0700133 if (options != nullptr) {
134 data.writeByteArray(sizeof(*options), (uint8_t*) options);
135 }
Wei Jia1f1fc452016-05-11 16:17:22 -0700136 status_t ret = remote()->transact(READMULTIPLE, data, &reply);
Andy Hungf59c0ba2016-06-15 17:59:30 -0700137 mMemoryCache.gc();
Wei Jia1f1fc452016-05-11 16:17:22 -0700138 if (ret != NO_ERROR) {
139 return ret;
140 }
141 // wrap the returned data in a vector of MediaBuffers
Andy Hungf59c0ba2016-06-15 17:59:30 -0700142 int32_t buftype;
143 uint32_t bufferCount = 0;
144 while ((buftype = reply.readInt32()) != NULL_BUFFER) {
145 LOG_ALWAYS_FATAL_IF(bufferCount >= maxNumBuffers,
146 "Received %u+ buffers and requested %u buffers",
147 bufferCount + 1, maxNumBuffers);
148 MediaBuffer *buf;
149 if (buftype == SHARED_BUFFER || buftype == SHARED_BUFFER_INDEX) {
150 uint64_t index = reply.readUint64();
151 ALOGV("Received %s index %llu",
152 buftype == SHARED_BUFFER ? "SHARED_BUFFER" : "SHARED_BUFFER_INDEX",
153 (unsigned long long) index);
154 sp<IMemory> mem;
155 if (buftype == SHARED_BUFFER) {
156 sp<IBinder> binder = reply.readStrongBinder();
157 mem = interface_cast<IMemory>(binder);
158 LOG_ALWAYS_FATAL_IF(mem.get() == nullptr,
159 "Received NULL IMemory for shared buffer");
160 mMemoryCache.insert(index, mem);
161 } else {
162 mem = mMemoryCache.lookup(index);
163 LOG_ALWAYS_FATAL_IF(mem.get() == nullptr,
164 "Received invalid IMemory index for shared buffer: %llu",
165 (unsigned long long)index);
166 }
167 size_t offset = reply.readInt32();
168 size_t length = reply.readInt32();
169 buf = new RemoteMediaBufferWrapper(mem);
170 buf->set_range(offset, length);
171 buf->meta_data()->updateFromParcel(reply);
172 } else { // INLINE_BUFFER
173 int32_t len = reply.readInt32();
174 ALOGV("INLINE_BUFFER status %d and len %d", ret, len);
175 buf = new MediaBuffer(len);
176 reply.read(buf->data(), len);
177 buf->meta_data()->updateFromParcel(reply);
Wei Jia1f1fc452016-05-11 16:17:22 -0700178 }
Wei Jia1f1fc452016-05-11 16:17:22 -0700179 buffers->push_back(buf);
Andy Hungf59c0ba2016-06-15 17:59:30 -0700180 ++bufferCount;
181 ++mBuffersSinceStop;
Wei Jia1f1fc452016-05-11 16:17:22 -0700182 }
183 ret = reply.readInt32();
Andy Hungf59c0ba2016-06-15 17:59:30 -0700184 ALOGV("readMultiple status %d, bufferCount %u, sinceStop %u",
185 ret, bufferCount, mBuffersSinceStop);
Wei Jia1f1fc452016-05-11 16:17:22 -0700186 return ret;
187 }
188
Wei Jiad3f4e142016-06-13 14:51:43 -0700189 bool supportReadMultiple() {
190 return true;
191 }
192
Marco Nelissenb2487f02015-09-01 13:23:23 -0700193 virtual status_t pause() {
194 ALOGV("pause");
195 Parcel data, reply;
196 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
197 return remote()->transact(PAUSE, data, &reply);
198 }
199
200 virtual status_t setBuffers(const Vector<MediaBuffer *> & buffers __unused) {
201 ALOGV("setBuffers NOT IMPLEMENTED");
202 return ERROR_UNSUPPORTED; // default
203 }
204
205private:
Andy Hungf59c0ba2016-06-15 17:59:30 -0700206
207 uint32_t mBuffersSinceStop; // Buffer tracking variable
208
Marco Nelissenb2487f02015-09-01 13:23:23 -0700209 // NuPlayer passes pointers-to-metadata around, so we use this to keep the metadata alive
210 // XXX: could we use this for caching, or does metadata change on the fly?
211 sp<MetaData> mMetaData;
Marco Nelissene7d8e712016-03-14 09:29:42 -0700212
Andy Hungf59c0ba2016-06-15 17:59:30 -0700213 // Cache all IMemory objects received from MediaExtractor.
214 // We gc IMemory objects that are no longer active (referenced by a MediaBuffer).
215
216 struct MemoryCache {
217 sp<IMemory> lookup(uint64_t index) {
218 auto p = mIndexToMemory.find(index);
219 if (p == mIndexToMemory.end()) {
220 ALOGE("cannot find index!");
221 return nullptr;
222 }
223 return p->second;
224 }
225
226 void insert(uint64_t index, const sp<IMemory> &mem) {
227 if (mIndexToMemory.find(index) != mIndexToMemory.end()) {
228 ALOGE("index %llu already present", (unsigned long long)index);
229 return;
230 }
231 (void)mIndexToMemory.emplace(index, mem);
232 }
233
234 void reset() {
235 mIndexToMemory.clear();
236 }
237
238 void gc() {
239 for (auto it = mIndexToMemory.begin(); it != mIndexToMemory.end(); ) {
240 if (MediaBuffer::isDeadObject(it->second)) {
241 it = mIndexToMemory.erase(it);
242 } else {
243 ++it;
244 }
245 }
246 }
247 private:
248 // C++14 unordered_map erase on iterator is stable; C++11 has no guarantee.
249 std::map<uint64_t, sp<IMemory>> mIndexToMemory;
250 } mMemoryCache;
Marco Nelissenb2487f02015-09-01 13:23:23 -0700251};
252
253IMPLEMENT_META_INTERFACE(MediaSource, "android.media.IMediaSource");
254
255#undef LOG_TAG
256#define LOG_TAG "BnMediaSource"
257
Wei Jiae9a5b962016-02-12 11:38:27 -0800258BnMediaSource::BnMediaSource()
Andy Hungf59c0ba2016-06-15 17:59:30 -0700259 : mBuffersSinceStop(0)
260 , mGroup(new MediaBufferGroup(kBinderMediaBuffers /* growthLimit */)) {
Wei Jiae9a5b962016-02-12 11:38:27 -0800261}
262
263BnMediaSource::~BnMediaSource() {
Wei Jiae9a5b962016-02-12 11:38:27 -0800264}
265
Marco Nelissenb2487f02015-09-01 13:23:23 -0700266status_t BnMediaSource::onTransact(
267 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
268{
269 switch (code) {
270 case START: {
271 ALOGV("start");
272 CHECK_INTERFACE(IMediaSource, data, reply);
273 sp<MetaData> meta;
274 if (data.dataAvail()) {
275 meta = MetaData::createFromParcel(data);
276 }
277 status_t ret = start(meta.get());
278 if (ret == NO_ERROR && meta != NULL) {
279 meta->writeToParcel(*reply);
280 }
281 return ret;
282 }
283 case STOP: {
284 ALOGV("stop");
285 CHECK_INTERFACE(IMediaSource, data, reply);
Andy Hungf59c0ba2016-06-15 17:59:30 -0700286 status_t status = stop();
287 mGroup->gc();
288 mIndexCache.reset();
289 mBuffersSinceStop = 0;
290 return status;
Marco Nelissenb2487f02015-09-01 13:23:23 -0700291 }
292 case PAUSE: {
293 ALOGV("pause");
294 CHECK_INTERFACE(IMediaSource, data, reply);
295 return pause();
296 }
297 case GETFORMAT: {
298 ALOGV("getFormat");
299 CHECK_INTERFACE(IMediaSource, data, reply);
300 sp<MetaData> meta = getFormat();
301 if (meta != NULL) {
302 meta->writeToParcel(*reply);
303 return NO_ERROR;
304 }
305 return UNKNOWN_ERROR;
306 }
Wei Jia1f1fc452016-05-11 16:17:22 -0700307 case READMULTIPLE: {
Andy Hungf59c0ba2016-06-15 17:59:30 -0700308 ALOGV("readMultiple");
Wei Jia1f1fc452016-05-11 16:17:22 -0700309 CHECK_INTERFACE(IMediaSource, data, reply);
Andy Hungf59c0ba2016-06-15 17:59:30 -0700310
311 // Get max number of buffers to read.
Wei Jia1f1fc452016-05-11 16:17:22 -0700312 uint32_t maxNumBuffers;
313 data.readUint32(&maxNumBuffers);
Wei Jia1f1fc452016-05-11 16:17:22 -0700314 if (maxNumBuffers > kMaxNumReadMultiple) {
315 maxNumBuffers = kMaxNumReadMultiple;
316 }
Andy Hungf59c0ba2016-06-15 17:59:30 -0700317
318 // Get read options, if any.
319 ReadOptions opts;
320 uint32_t len;
321 const bool useOptions =
322 data.readUint32(&len) == NO_ERROR
323 && len == sizeof(opts)
324 && data.read((void *)&opts, len) == NO_ERROR;
325
326 mGroup->gc(kBinderMediaBuffers /* freeBuffers */);
327 mIndexCache.gc();
328 status_t ret = NO_ERROR;
329 uint32_t bufferCount = 0;
330 for (; bufferCount < maxNumBuffers; ++bufferCount, ++mBuffersSinceStop) {
331 MediaBuffer *buf = nullptr;
332 ret = read(&buf, useOptions ? &opts : nullptr);
333 opts.clearNonPersistent(); // Remove options that only apply to first buffer.
334 if (ret != NO_ERROR || buf == nullptr) {
Wei Jia1f1fc452016-05-11 16:17:22 -0700335 break;
336 }
337
Andy Hungf59c0ba2016-06-15 17:59:30 -0700338 // Even if we're using shared memory, we might not want to use it, since for small
339 // sizes it's faster to copy data through the Binder transaction
340 // On the other hand, if the data size is large enough, it's better to use shared
341 // memory. When data is too large, binder can't handle it.
342 //
343 // TODO: reduce MediaBuffer::kSharedMemThreshold
344 MediaBuffer *transferBuf = nullptr;
345 const size_t length = buf->range_length();
346 size_t offset = buf->range_offset();
347 if (length >= MediaBuffer::kSharedMemThreshold) {
348 if (buf->mMemory != nullptr) {
349 ALOGV("Use shared memory: %zu", length);
350 transferBuf = buf;
351 } else {
352 ALOGD("Large buffer %zu without IMemory!", length);
353 ret = mGroup->acquire_buffer(
354 &transferBuf, false /* nonBlocking */, length);
355 if (ret != OK
356 || transferBuf == nullptr
357 || transferBuf->mMemory == nullptr) {
358 ALOGW("Failed to acquire shared memory, size %zu, ret %d",
359 length, ret);
360 if (transferBuf != nullptr) {
361 transferBuf->release();
362 transferBuf = nullptr;
363 }
364 // Current buffer transmit inline; no more additional buffers.
365 maxNumBuffers = 0;
366 } else {
367 memcpy(transferBuf->data(), (uint8_t*)buf->data() + offset, length);
368 offset = 0;
369 }
370 }
Wei Jia1f1fc452016-05-11 16:17:22 -0700371 }
Andy Hungf59c0ba2016-06-15 17:59:30 -0700372 if (transferBuf != nullptr) { // Using shared buffers.
373 if (!transferBuf->isObserved()) {
374 // Transfer buffer must be part of a MediaBufferGroup.
375 ALOGV("adding shared memory buffer %p to local group", transferBuf);
376 mGroup->add_buffer(transferBuf);
377 transferBuf->add_ref(); // We have already acquired buffer.
378 }
379 uint64_t index = mIndexCache.lookup(transferBuf->mMemory);
380 if (index == 0) {
381 index = mIndexCache.insert(transferBuf->mMemory);
382 reply->writeInt32(SHARED_BUFFER);
383 reply->writeUint64(index);
384 reply->writeStrongBinder(IInterface::asBinder(transferBuf->mMemory));
385 ALOGV("SHARED_BUFFER(%p) %llu",
386 transferBuf, (unsigned long long)index);
387 } else {
388 reply->writeInt32(SHARED_BUFFER_INDEX);
389 reply->writeUint64(index);
390 ALOGV("SHARED_BUFFER_INDEX(%p) %llu",
391 transferBuf, (unsigned long long)index);
392 }
393 reply->writeInt32(offset);
394 reply->writeInt32(length);
395 buf->meta_data()->writeToParcel(*reply);
396 if (transferBuf != buf) {
397 buf->release();
398 }
399 } else {
400 ALOGV_IF(buf->mMemory != nullptr,
401 "INLINE(%p) %zu shared mem available, but only %zu used",
402 buf, buf->mMemory->size(), length);
403 reply->writeInt32(INLINE_BUFFER);
404 reply->writeByteArray(length, (uint8_t*)buf->data() + offset);
405 buf->meta_data()->writeToParcel(*reply);
406 buf->release();
407 }
Wei Jia1f1fc452016-05-11 16:17:22 -0700408 }
Andy Hungf59c0ba2016-06-15 17:59:30 -0700409 reply->writeInt32(NULL_BUFFER); // Indicate no more MediaBuffers.
Wei Jia1f1fc452016-05-11 16:17:22 -0700410 reply->writeInt32(ret);
Andy Hungf59c0ba2016-06-15 17:59:30 -0700411 ALOGV("readMultiple status %d, bufferCount %u, sinceStop %u",
412 ret, bufferCount, mBuffersSinceStop);
Wei Jia1f1fc452016-05-11 16:17:22 -0700413 return NO_ERROR;
414 }
Marco Nelissenb2487f02015-09-01 13:23:23 -0700415 default:
416 return BBinder::onTransact(code, data, reply, flags);
417 }
418}
419
420////////////////////////////////////////////////////////////////////////////////
421
422IMediaSource::ReadOptions::ReadOptions() {
423 reset();
424}
425
426void IMediaSource::ReadOptions::reset() {
427 mOptions = 0;
428 mSeekTimeUs = 0;
429 mLatenessUs = 0;
430 mNonBlocking = false;
431}
432
433void IMediaSource::ReadOptions::setNonBlocking() {
434 mNonBlocking = true;
435}
436
437void IMediaSource::ReadOptions::clearNonBlocking() {
438 mNonBlocking = false;
439}
440
441bool IMediaSource::ReadOptions::getNonBlocking() const {
442 return mNonBlocking;
443}
444
445void IMediaSource::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
446 mOptions |= kSeekTo_Option;
447 mSeekTimeUs = time_us;
448 mSeekMode = mode;
449}
450
451void IMediaSource::ReadOptions::clearSeekTo() {
452 mOptions &= ~kSeekTo_Option;
453 mSeekTimeUs = 0;
454 mSeekMode = SEEK_CLOSEST_SYNC;
455}
456
457bool IMediaSource::ReadOptions::getSeekTo(
458 int64_t *time_us, SeekMode *mode) const {
459 *time_us = mSeekTimeUs;
460 *mode = mSeekMode;
461 return (mOptions & kSeekTo_Option) != 0;
462}
463
464void IMediaSource::ReadOptions::setLateBy(int64_t lateness_us) {
465 mLatenessUs = lateness_us;
466}
467
468int64_t IMediaSource::ReadOptions::getLateBy() const {
469 return mLatenessUs;
470}
471
472
473} // namespace android
474