blob: 7e40e4ff233a2831696ca917ce4b9a9ee4da3ba7 [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,
Marco Nelissenb65990f2015-11-09 15:39:49 -080039 READ,
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,
47 INLINE_BUFFER
48};
49
50class RemoteMediaBufferReleaser : public BBinder {
51public:
Wei Jiae9a5b962016-02-12 11:38:27 -080052 RemoteMediaBufferReleaser(MediaBuffer *buf, sp<BnMediaSource> owner) {
Marco Nelissenb65990f2015-11-09 15:39:49 -080053 mBuf = buf;
Wei Jiae9a5b962016-02-12 11:38:27 -080054 mOwner = owner;
Marco Nelissenb65990f2015-11-09 15:39:49 -080055 }
56 ~RemoteMediaBufferReleaser() {
57 if (mBuf) {
58 ALOGW("RemoteMediaBufferReleaser dtor called while still holding buffer");
59 mBuf->release();
60 }
61 }
62 virtual status_t onTransact( uint32_t code,
63 const Parcel& data,
64 Parcel* reply,
65 uint32_t flags = 0) {
66 if (code == RELEASE_BUFFER) {
67 mBuf->release();
68 mBuf = NULL;
69 return OK;
70 } else {
71 return BBinder::onTransact(code, data, reply, flags);
72 }
73 }
74private:
75 MediaBuffer *mBuf;
Wei Jiae9a5b962016-02-12 11:38:27 -080076 // Keep a ref to ensure MediaBuffer is released before the owner, i.e., BnMediaSource,
77 // because BnMediaSource needs to delete MediaBufferGroup in its dtor and
78 // MediaBufferGroup dtor requires all MediaBuffer's have 0 ref count.
79 sp<BnMediaSource> mOwner;
Marco Nelissenb65990f2015-11-09 15:39:49 -080080};
81
82
83class RemoteMediaBufferWrapper : public MediaBuffer {
84public:
85 RemoteMediaBufferWrapper(sp<IMemory> mem, sp<IBinder> source);
86protected:
87 virtual ~RemoteMediaBufferWrapper();
88private:
89 sp<IMemory> mMemory;
90 sp<IBinder> mRemoteSource;
91};
92
93RemoteMediaBufferWrapper::RemoteMediaBufferWrapper(sp<IMemory> mem, sp<IBinder> source)
94: MediaBuffer(mem->pointer(), mem->size()) {
95 mMemory = mem;
96 mRemoteSource = source;
97}
98
99RemoteMediaBufferWrapper::~RemoteMediaBufferWrapper() {
100 mMemory.clear();
101 // Explicitly ask the remote side to release the buffer. We could also just clear
102 // mRemoteSource, but that doesn't immediately release the reference on the remote side.
103 Parcel data, reply;
104 mRemoteSource->transact(RELEASE_BUFFER, data, &reply);
105 mRemoteSource.clear();
106}
107
Marco Nelissenb2487f02015-09-01 13:23:23 -0700108class BpMediaSource : public BpInterface<IMediaSource> {
109public:
110 BpMediaSource(const sp<IBinder>& impl)
111 : BpInterface<IMediaSource>(impl)
112 {
113 }
114
115 virtual status_t start(MetaData *params) {
116 ALOGV("start");
117 Parcel data, reply;
118 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
119 if (params) {
120 params->writeToParcel(data);
121 }
122 status_t ret = remote()->transact(START, data, &reply);
123 if (ret == NO_ERROR && params) {
124 ALOGW("ignoring potentially modified MetaData from start");
125 ALOGW("input:");
126 params->dumpToLog();
127 sp<MetaData> meta = MetaData::createFromParcel(reply);
128 ALOGW("output:");
129 meta->dumpToLog();
130 }
131 return ret;
132 }
133
134 virtual status_t stop() {
135 ALOGV("stop");
136 Parcel data, reply;
137 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
138 return remote()->transact(STOP, data, &reply);
139 }
140
141 virtual sp<MetaData> getFormat() {
142 ALOGV("getFormat");
143 Parcel data, reply;
144 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
145 status_t ret = remote()->transact(GETFORMAT, data, &reply);
146 if (ret == NO_ERROR) {
147 mMetaData = MetaData::createFromParcel(reply);
148 return mMetaData;
149 }
150 return NULL;
151 }
152
153 virtual status_t read(MediaBuffer **buffer, const ReadOptions *options) {
154 ALOGV("read");
155 Parcel data, reply;
156 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
157 if (options) {
158 data.writeByteArray(sizeof(*options), (uint8_t*) options);
159 }
160 status_t ret = remote()->transact(READ, data, &reply);
161 if (ret != NO_ERROR) {
162 return ret;
163 }
164 // wrap the returned data in a MediaBuffer
Marco Nelissenb2487f02015-09-01 13:23:23 -0700165 ret = reply.readInt32();
Marco Nelissenb65990f2015-11-09 15:39:49 -0800166 int32_t buftype = reply.readInt32();
167 if (buftype == SHARED_BUFFER) {
168 sp<IBinder> remote = reply.readStrongBinder();
169 sp<IBinder> binder = reply.readStrongBinder();
170 sp<IMemory> mem = interface_cast<IMemory>(binder);
171 if (mem == NULL) {
172 ALOGE("received NULL IMemory for shared buffer");
173 }
174 size_t offset = reply.readInt32();
175 size_t length = reply.readInt32();
176 MediaBuffer *buf = new RemoteMediaBufferWrapper(mem, remote);
177 buf->set_range(offset, length);
178 buf->meta_data()->updateFromParcel(reply);
179 *buffer = buf;
180 } else if (buftype == NULL_BUFFER) {
181 ALOGV("got status %d and NULL buffer", ret);
Marco Nelissenb2487f02015-09-01 13:23:23 -0700182 *buffer = NULL;
183 } else {
Marco Nelissenb65990f2015-11-09 15:39:49 -0800184 int32_t len = reply.readInt32();
Marco Nelissenb2487f02015-09-01 13:23:23 -0700185 ALOGV("got status %d and len %d", ret, len);
186 *buffer = new MediaBuffer(len);
187 reply.read((*buffer)->data(), len);
188 (*buffer)->meta_data()->updateFromParcel(reply);
189 }
190 return ret;
191 }
192
Wei Jia1f1fc452016-05-11 16:17:22 -0700193 virtual status_t readMultiple(Vector<MediaBuffer *> *buffers, uint32_t maxNumBuffers) {
194 ALOGV("readMultiple");
195 if (buffers == NULL || !buffers->isEmpty()) {
196 return BAD_VALUE;
197 }
198 Parcel data, reply;
199 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
200 data.writeUint32(maxNumBuffers);
201 status_t ret = remote()->transact(READMULTIPLE, data, &reply);
202 if (ret != NO_ERROR) {
203 return ret;
204 }
205 // wrap the returned data in a vector of MediaBuffers
206 int32_t bufCount = 0;
207 while (1) {
208 if (reply.readInt32() == 0) {
209 break;
210 }
211 int32_t len = reply.readInt32();
212 ALOGV("got len %d", len);
213 MediaBuffer *buf = new MediaBuffer(len);
214 reply.read(buf->data(), len);
215 buf->meta_data()->updateFromParcel(reply);
216 buffers->push_back(buf);
217 ++bufCount;
218 }
219 ret = reply.readInt32();
220 ALOGV("got status %d, bufCount %d", ret, bufCount);
221 return ret;
222 }
223
Marco Nelissenb2487f02015-09-01 13:23:23 -0700224 virtual status_t pause() {
225 ALOGV("pause");
226 Parcel data, reply;
227 data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
228 return remote()->transact(PAUSE, data, &reply);
229 }
230
231 virtual status_t setBuffers(const Vector<MediaBuffer *> & buffers __unused) {
232 ALOGV("setBuffers NOT IMPLEMENTED");
233 return ERROR_UNSUPPORTED; // default
234 }
235
236private:
237 // NuPlayer passes pointers-to-metadata around, so we use this to keep the metadata alive
238 // XXX: could we use this for caching, or does metadata change on the fly?
239 sp<MetaData> mMetaData;
Marco Nelissene7d8e712016-03-14 09:29:42 -0700240
Marco Nelissenb2487f02015-09-01 13:23:23 -0700241};
242
243IMPLEMENT_META_INTERFACE(MediaSource, "android.media.IMediaSource");
244
245#undef LOG_TAG
246#define LOG_TAG "BnMediaSource"
247
Wei Jiae9a5b962016-02-12 11:38:27 -0800248BnMediaSource::BnMediaSource()
249 : mGroup(NULL) {
250}
251
252BnMediaSource::~BnMediaSource() {
253 delete mGroup;
254 mGroup = NULL;
255}
256
Marco Nelissenb2487f02015-09-01 13:23:23 -0700257status_t BnMediaSource::onTransact(
258 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
259{
260 switch (code) {
261 case START: {
262 ALOGV("start");
263 CHECK_INTERFACE(IMediaSource, data, reply);
264 sp<MetaData> meta;
265 if (data.dataAvail()) {
266 meta = MetaData::createFromParcel(data);
267 }
268 status_t ret = start(meta.get());
269 if (ret == NO_ERROR && meta != NULL) {
270 meta->writeToParcel(*reply);
271 }
272 return ret;
273 }
274 case STOP: {
275 ALOGV("stop");
276 CHECK_INTERFACE(IMediaSource, data, reply);
277 return stop();
278 }
279 case PAUSE: {
280 ALOGV("pause");
281 CHECK_INTERFACE(IMediaSource, data, reply);
282 return pause();
283 }
284 case GETFORMAT: {
285 ALOGV("getFormat");
286 CHECK_INTERFACE(IMediaSource, data, reply);
287 sp<MetaData> meta = getFormat();
288 if (meta != NULL) {
289 meta->writeToParcel(*reply);
290 return NO_ERROR;
291 }
292 return UNKNOWN_ERROR;
293 }
294 case READ: {
295 ALOGV("read");
296 CHECK_INTERFACE(IMediaSource, data, reply);
297 status_t ret;
298 MediaBuffer *buf = NULL;
299 ReadOptions opts;
300 uint32_t len;
301 if (data.readUint32(&len) == NO_ERROR &&
302 len == sizeof(opts) && data.read((void*)&opts, len) == NO_ERROR) {
303 ret = read(&buf, &opts);
304 } else {
305 ret = read(&buf, NULL);
306 }
Marco Nelissenb65990f2015-11-09 15:39:49 -0800307
Marco Nelissenb2487f02015-09-01 13:23:23 -0700308 reply->writeInt32(ret);
309 if (buf != NULL) {
Marco Nelissenb65990f2015-11-09 15:39:49 -0800310 size_t usedSize = buf->range_length();
311 // even if we're using shared memory, we might not want to use it, since for small
312 // sizes it's faster to copy data through the Binder transaction
Wei Jiae9a5b962016-02-12 11:38:27 -0800313 // On the other hand, if the data size is large enough, it's better to use shared
314 // memory. When data is too large, binder can't handle it.
315 if (usedSize >= MediaBuffer::kSharedMemThreshold) {
316 ALOGV("use shared memory: %zu", usedSize);
317
318 MediaBuffer *transferBuf = buf;
319 size_t offset = buf->range_offset();
320 if (transferBuf->mMemory == NULL) {
321 if (mGroup == NULL) {
322 mGroup = new MediaBufferGroup;
323 size_t allocateSize = usedSize;
324 if (usedSize < SIZE_MAX / 3) {
325 allocateSize = usedSize * 3 / 2;
326 }
327 mGroup->add_buffer(new MediaBuffer(allocateSize));
328 }
329
Wei Jia027b8112016-04-04 09:50:14 -0700330 MediaBuffer *newBuf = NULL;
Wei Jiae9a5b962016-02-12 11:38:27 -0800331 ret = mGroup->acquire_buffer(
Wei Jia027b8112016-04-04 09:50:14 -0700332 &newBuf, false /* nonBlocking */, usedSize);
333 if (ret != OK || newBuf == NULL || newBuf->mMemory == NULL) {
Wei Jiae9a5b962016-02-12 11:38:27 -0800334 ALOGW("failed to acquire shared memory, ret %d", ret);
Wei Jia027b8112016-04-04 09:50:14 -0700335 buf->release();
336 if (newBuf != NULL) {
337 newBuf->release();
338 }
Wei Jiae9a5b962016-02-12 11:38:27 -0800339 reply->writeInt32(NULL_BUFFER);
340 return NO_ERROR;
341 }
Wei Jia027b8112016-04-04 09:50:14 -0700342 transferBuf = newBuf;
Wei Jiae9a5b962016-02-12 11:38:27 -0800343 memcpy(transferBuf->data(), (uint8_t*)buf->data() + buf->range_offset(),
344 buf->range_length());
345 offset = 0;
346 }
347
Marco Nelissenb65990f2015-11-09 15:39:49 -0800348 reply->writeInt32(SHARED_BUFFER);
Wei Jiae9a5b962016-02-12 11:38:27 -0800349 RemoteMediaBufferReleaser *wrapper =
350 new RemoteMediaBufferReleaser(transferBuf, this);
Marco Nelissenb65990f2015-11-09 15:39:49 -0800351 reply->writeStrongBinder(wrapper);
Wei Jiae9a5b962016-02-12 11:38:27 -0800352 reply->writeStrongBinder(IInterface::asBinder(transferBuf->mMemory));
353 reply->writeInt32(offset);
Marco Nelissenb65990f2015-11-09 15:39:49 -0800354 reply->writeInt32(usedSize);
355 buf->meta_data()->writeToParcel(*reply);
Wei Jia1d5a3062016-02-29 09:47:27 -0800356 if (buf->mMemory == NULL) {
357 buf->release();
358 }
Marco Nelissenb65990f2015-11-09 15:39:49 -0800359 } else {
Wei Jiae9a5b962016-02-12 11:38:27 -0800360 // buffer is small: copy it
Marco Nelissenb65990f2015-11-09 15:39:49 -0800361 if (buf->mMemory != NULL) {
362 ALOGV("%zu shared mem available, but only %zu used", buf->mMemory->size(), buf->range_length());
363 }
364 reply->writeInt32(INLINE_BUFFER);
365 reply->writeByteArray(buf->range_length(), (uint8_t*)buf->data() + buf->range_offset());
366 buf->meta_data()->writeToParcel(*reply);
367 buf->release();
368 }
Marco Nelissenb2487f02015-09-01 13:23:23 -0700369 } else {
370 ALOGV("ret %d, buf %p", ret, buf);
Marco Nelissenb65990f2015-11-09 15:39:49 -0800371 reply->writeInt32(NULL_BUFFER);
Marco Nelissenb2487f02015-09-01 13:23:23 -0700372 }
373 return NO_ERROR;
374 }
Wei Jia1f1fc452016-05-11 16:17:22 -0700375 case READMULTIPLE: {
376 ALOGV("readmultiple");
377 CHECK_INTERFACE(IMediaSource, data, reply);
378 uint32_t maxNumBuffers;
379 data.readUint32(&maxNumBuffers);
380 status_t ret = NO_ERROR;
381 uint32_t bufferCount = 0;
382 if (maxNumBuffers > kMaxNumReadMultiple) {
383 maxNumBuffers = kMaxNumReadMultiple;
384 }
385 while (bufferCount < maxNumBuffers) {
386 if (reply->dataSize() >= MediaBuffer::kSharedMemThreshold) {
387 break;
388 }
389
390 MediaBuffer *buf = NULL;
391 ret = read(&buf, NULL);
392 if (ret != NO_ERROR || buf == NULL) {
393 break;
394 }
395 ++bufferCount;
396 reply->writeInt32(1); // indicate one more MediaBuffer.
397 reply->writeByteArray(
398 buf->range_length(), (uint8_t*)buf->data() + buf->range_offset());
399 buf->meta_data()->writeToParcel(*reply);
400 buf->release();
401 }
402 reply->writeInt32(0); // indicate no more MediaBuffer.
403 reply->writeInt32(ret);
404 return NO_ERROR;
405 }
Marco Nelissenb2487f02015-09-01 13:23:23 -0700406 default:
407 return BBinder::onTransact(code, data, reply, flags);
408 }
409}
410
411////////////////////////////////////////////////////////////////////////////////
412
413IMediaSource::ReadOptions::ReadOptions() {
414 reset();
415}
416
417void IMediaSource::ReadOptions::reset() {
418 mOptions = 0;
419 mSeekTimeUs = 0;
420 mLatenessUs = 0;
421 mNonBlocking = false;
422}
423
424void IMediaSource::ReadOptions::setNonBlocking() {
425 mNonBlocking = true;
426}
427
428void IMediaSource::ReadOptions::clearNonBlocking() {
429 mNonBlocking = false;
430}
431
432bool IMediaSource::ReadOptions::getNonBlocking() const {
433 return mNonBlocking;
434}
435
436void IMediaSource::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
437 mOptions |= kSeekTo_Option;
438 mSeekTimeUs = time_us;
439 mSeekMode = mode;
440}
441
442void IMediaSource::ReadOptions::clearSeekTo() {
443 mOptions &= ~kSeekTo_Option;
444 mSeekTimeUs = 0;
445 mSeekMode = SEEK_CLOSEST_SYNC;
446}
447
448bool IMediaSource::ReadOptions::getSeekTo(
449 int64_t *time_us, SeekMode *mode) const {
450 *time_us = mSeekTimeUs;
451 *mode = mSeekMode;
452 return (mOptions & kSeekTo_Option) != 0;
453}
454
455void IMediaSource::ReadOptions::setLateBy(int64_t lateness_us) {
456 mLatenessUs = lateness_us;
457}
458
459int64_t IMediaSource::ReadOptions::getLateBy() const {
460 return mLatenessUs;
461}
462
463
464} // namespace android
465