Loading include/media/IMediaSource.h +13 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,10 @@ public: // Returns true if |readMultiple| is supported, otherwise false. virtual bool supportReadMultiple() = 0; // Returns true if |read| supports nonblocking option, otherwise false. // |readMultiple| if supported, always allows the nonblocking option. virtual bool supportNonblockingRead() = 0; // Causes this source to suspend pulling data from its upstream source // until a subsequent read-with-seek. Currently only supported by // OMXCodec. Loading Loading @@ -161,6 +165,7 @@ public: return ERROR_UNSUPPORTED; } // TODO: Implement this for local media sources. virtual status_t readMultiple( Vector<MediaBuffer *> * /* buffers */, uint32_t /* maxNumBuffers = 1 */, const ReadOptions * /* options = nullptr */) { Loading @@ -171,7 +176,15 @@ public: return false; } // Override in source if nonblocking reads are supported. virtual bool supportNonblockingRead() { return false; } static const size_t kBinderMediaBuffers = 4; // buffers managed by BnMediaSource static const size_t kTransferSharedAsSharedThreshold = 4 * 1024; // if >= shared, else inline static const size_t kTransferInlineAsSharedThreshold = 64 * 1024; // if >= shared, else inline static const size_t kInlineMaxTransfer = 256 * 1024; // Binder size limited to BINDER_VM_SIZE. protected: virtual ~BnMediaSource(); Loading include/media/stagefright/MediaBufferGroup.h +6 −0 Original line number Diff line number Diff line Loading @@ -30,10 +30,16 @@ class MetaData; class MediaBufferGroup : public MediaBufferObserver { public: MediaBufferGroup(size_t growthLimit = 0); // create a media buffer group with preallocated buffers MediaBufferGroup(size_t buffers, size_t buffer_size, size_t growthLimit = 0); ~MediaBufferGroup(); void add_buffer(MediaBuffer *buffer); bool has_buffers(); // If nonBlocking is false, it blocks until a buffer is available and // passes it to the caller in *buffer, while returning OK. // The returned buffer will have a reference count of 1. Loading media/libmedia/IMediaSource.cpp +33 −3 Original line number Diff line number Diff line Loading @@ -38,7 +38,8 @@ enum { GETFORMAT, // READ, deprecated READMULTIPLE, RELEASE_BUFFER RELEASE_BUFFER, SUPPORT_NONBLOCKING_READ, }; enum { Loading Loading @@ -186,10 +187,22 @@ public: return ret; } bool supportReadMultiple() { // Binder proxy adds readMultiple support. virtual bool supportReadMultiple() { return true; } virtual bool supportNonblockingRead() { ALOGV("supportNonblockingRead"); Parcel data, reply; data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor()); status_t ret = remote()->transact(SUPPORT_NONBLOCKING_READ, data, &reply); if (ret == NO_ERROR) { return reply.readInt32() != 0; } return false; } virtual status_t pause() { ALOGV("pause"); Parcel data, reply; Loading Loading @@ -325,6 +338,7 @@ status_t BnMediaSource::onTransact( mGroup->gc(kBinderMediaBuffers /* freeBuffers */); mIndexCache.gc(); size_t inlineTransferSize = 0; status_t ret = NO_ERROR; uint32_t bufferCount = 0; for (; bufferCount < maxNumBuffers; ++bufferCount, ++mBuffersSinceStop) { Loading @@ -344,7 +358,8 @@ status_t BnMediaSource::onTransact( MediaBuffer *transferBuf = nullptr; const size_t length = buf->range_length(); size_t offset = buf->range_offset(); if (length >= MediaBuffer::kSharedMemThreshold) { if (length >= (supportNonblockingRead() && buf->mMemory != nullptr ? kTransferSharedAsSharedThreshold : kTransferInlineAsSharedThreshold)) { if (buf->mMemory != nullptr) { ALOGV("Use shared memory: %zu", length); transferBuf = buf; Loading @@ -366,6 +381,9 @@ status_t BnMediaSource::onTransact( } else { memcpy(transferBuf->data(), (uint8_t*)buf->data() + offset, length); offset = 0; if (!mGroup->has_buffers()) { maxNumBuffers = 0; // No more MediaBuffers, stop readMultiple. } } } } Loading Loading @@ -395,6 +413,8 @@ status_t BnMediaSource::onTransact( buf->meta_data()->writeToParcel(*reply); if (transferBuf != buf) { buf->release(); } else if (!supportNonblockingRead()) { maxNumBuffers = 0; // stop readMultiple with one shared buffer. } } else { ALOGV_IF(buf->mMemory != nullptr, Loading @@ -404,6 +424,10 @@ status_t BnMediaSource::onTransact( reply->writeByteArray(length, (uint8_t*)buf->data() + offset); buf->meta_data()->writeToParcel(*reply); buf->release(); inlineTransferSize += length; if (inlineTransferSize > kInlineMaxTransfer) { maxNumBuffers = 0; // stop readMultiple if inline transfer is too large. } } } reply->writeInt32(NULL_BUFFER); // Indicate no more MediaBuffers. Loading @@ -412,6 +436,12 @@ status_t BnMediaSource::onTransact( ret, bufferCount, mBuffersSinceStop); return NO_ERROR; } case SUPPORT_NONBLOCKING_READ: { ALOGV("supportNonblockingRead"); CHECK_INTERFACE(IMediaSource, data, reply); reply->writeInt32((int32_t)supportNonblockingRead()); return NO_ERROR; } default: return BBinder::onTransact(code, data, reply, flags); } Loading media/libmediaplayerservice/nuplayer/GenericSource.cpp +7 −8 Original line number Diff line number Diff line Loading @@ -1385,7 +1385,7 @@ void NuPlayer::GenericSource::readBuffer( if (mIsWidevine) { maxBuffers = 2; } else { maxBuffers = 4; maxBuffers = 8; // too large of a number may influence seeks } break; case MEDIA_TRACK_TYPE_AUDIO: Loading Loading @@ -1417,25 +1417,24 @@ void NuPlayer::GenericSource::readBuffer( MediaSource::ReadOptions options; bool seeking = false; if (seekTimeUs >= 0) { options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC); seeking = true; } if (mIsWidevine) { const bool couldReadMultiple = (!mIsWidevine && track->mSource->supportReadMultiple()); if (mIsWidevine || couldReadMultiple) { options.setNonBlocking(); } bool couldReadMultiple = (!mIsWidevine && trackType == MEDIA_TRACK_TYPE_AUDIO && track->mSource->supportReadMultiple()); for (size_t numBuffers = 0; numBuffers < maxBuffers; ) { Vector<MediaBuffer *> mediaBuffers; status_t err = NO_ERROR; if (!seeking && couldReadMultiple) { err = track->mSource->readMultiple(&mediaBuffers, (maxBuffers - numBuffers)); if (couldReadMultiple) { err = track->mSource->readMultiple( &mediaBuffers, maxBuffers - numBuffers, &options); } else { MediaBuffer *mbuf = NULL; err = track->mSource->read(&mbuf, &options); Loading media/libstagefright/MPEG4Extractor.cpp +17 −4 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ public: virtual sp<MetaData> getFormat(); virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL); virtual bool supportNonblockingRead() { return true; } virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL); protected: Loading Loading @@ -3563,13 +3564,20 @@ status_t MPEG4Source::start(MetaData *params) { // A somewhat arbitrary limit that should be sufficient for 8k video frames // If you see the message below for a valid input stream: increase the limit if (max_size > 64 * 1024 * 1024) { ALOGE("bogus max input size: %zu", max_size); const size_t kMaxBufferSize = 64 * 1024 * 1024; if (max_size > kMaxBufferSize) { ALOGE("bogus max input size: %zu > %zu", max_size, kMaxBufferSize); return ERROR_MALFORMED; } if (max_size == 0) { ALOGE("zero max input size"); return ERROR_MALFORMED; } mGroup = new MediaBufferGroup; mGroup->add_buffer(new MediaBuffer(max_size)); // Allow up to kMaxBuffers, but not if the total exceeds kMaxBufferSize. const size_t kMaxBuffers = 8; const size_t buffers = min(kMaxBufferSize / max_size, kMaxBuffers); mGroup = new MediaBufferGroup(buffers, max_size); mSrcBuffer = new (std::nothrow) uint8_t[max_size]; if (mSrcBuffer == NULL) { // file probably specified a bad max size Loading Loading @@ -4196,6 +4204,11 @@ status_t MPEG4Source::read( CHECK(mStarted); if (options != nullptr && options->getNonBlocking() && !mGroup->has_buffers()) { *out = nullptr; return WOULD_BLOCK; } if (mFirstMoofOffset > 0) { return fragmentedRead(out, options); } Loading Loading
include/media/IMediaSource.h +13 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,10 @@ public: // Returns true if |readMultiple| is supported, otherwise false. virtual bool supportReadMultiple() = 0; // Returns true if |read| supports nonblocking option, otherwise false. // |readMultiple| if supported, always allows the nonblocking option. virtual bool supportNonblockingRead() = 0; // Causes this source to suspend pulling data from its upstream source // until a subsequent read-with-seek. Currently only supported by // OMXCodec. Loading Loading @@ -161,6 +165,7 @@ public: return ERROR_UNSUPPORTED; } // TODO: Implement this for local media sources. virtual status_t readMultiple( Vector<MediaBuffer *> * /* buffers */, uint32_t /* maxNumBuffers = 1 */, const ReadOptions * /* options = nullptr */) { Loading @@ -171,7 +176,15 @@ public: return false; } // Override in source if nonblocking reads are supported. virtual bool supportNonblockingRead() { return false; } static const size_t kBinderMediaBuffers = 4; // buffers managed by BnMediaSource static const size_t kTransferSharedAsSharedThreshold = 4 * 1024; // if >= shared, else inline static const size_t kTransferInlineAsSharedThreshold = 64 * 1024; // if >= shared, else inline static const size_t kInlineMaxTransfer = 256 * 1024; // Binder size limited to BINDER_VM_SIZE. protected: virtual ~BnMediaSource(); Loading
include/media/stagefright/MediaBufferGroup.h +6 −0 Original line number Diff line number Diff line Loading @@ -30,10 +30,16 @@ class MetaData; class MediaBufferGroup : public MediaBufferObserver { public: MediaBufferGroup(size_t growthLimit = 0); // create a media buffer group with preallocated buffers MediaBufferGroup(size_t buffers, size_t buffer_size, size_t growthLimit = 0); ~MediaBufferGroup(); void add_buffer(MediaBuffer *buffer); bool has_buffers(); // If nonBlocking is false, it blocks until a buffer is available and // passes it to the caller in *buffer, while returning OK. // The returned buffer will have a reference count of 1. Loading
media/libmedia/IMediaSource.cpp +33 −3 Original line number Diff line number Diff line Loading @@ -38,7 +38,8 @@ enum { GETFORMAT, // READ, deprecated READMULTIPLE, RELEASE_BUFFER RELEASE_BUFFER, SUPPORT_NONBLOCKING_READ, }; enum { Loading Loading @@ -186,10 +187,22 @@ public: return ret; } bool supportReadMultiple() { // Binder proxy adds readMultiple support. virtual bool supportReadMultiple() { return true; } virtual bool supportNonblockingRead() { ALOGV("supportNonblockingRead"); Parcel data, reply; data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor()); status_t ret = remote()->transact(SUPPORT_NONBLOCKING_READ, data, &reply); if (ret == NO_ERROR) { return reply.readInt32() != 0; } return false; } virtual status_t pause() { ALOGV("pause"); Parcel data, reply; Loading Loading @@ -325,6 +338,7 @@ status_t BnMediaSource::onTransact( mGroup->gc(kBinderMediaBuffers /* freeBuffers */); mIndexCache.gc(); size_t inlineTransferSize = 0; status_t ret = NO_ERROR; uint32_t bufferCount = 0; for (; bufferCount < maxNumBuffers; ++bufferCount, ++mBuffersSinceStop) { Loading @@ -344,7 +358,8 @@ status_t BnMediaSource::onTransact( MediaBuffer *transferBuf = nullptr; const size_t length = buf->range_length(); size_t offset = buf->range_offset(); if (length >= MediaBuffer::kSharedMemThreshold) { if (length >= (supportNonblockingRead() && buf->mMemory != nullptr ? kTransferSharedAsSharedThreshold : kTransferInlineAsSharedThreshold)) { if (buf->mMemory != nullptr) { ALOGV("Use shared memory: %zu", length); transferBuf = buf; Loading @@ -366,6 +381,9 @@ status_t BnMediaSource::onTransact( } else { memcpy(transferBuf->data(), (uint8_t*)buf->data() + offset, length); offset = 0; if (!mGroup->has_buffers()) { maxNumBuffers = 0; // No more MediaBuffers, stop readMultiple. } } } } Loading Loading @@ -395,6 +413,8 @@ status_t BnMediaSource::onTransact( buf->meta_data()->writeToParcel(*reply); if (transferBuf != buf) { buf->release(); } else if (!supportNonblockingRead()) { maxNumBuffers = 0; // stop readMultiple with one shared buffer. } } else { ALOGV_IF(buf->mMemory != nullptr, Loading @@ -404,6 +424,10 @@ status_t BnMediaSource::onTransact( reply->writeByteArray(length, (uint8_t*)buf->data() + offset); buf->meta_data()->writeToParcel(*reply); buf->release(); inlineTransferSize += length; if (inlineTransferSize > kInlineMaxTransfer) { maxNumBuffers = 0; // stop readMultiple if inline transfer is too large. } } } reply->writeInt32(NULL_BUFFER); // Indicate no more MediaBuffers. Loading @@ -412,6 +436,12 @@ status_t BnMediaSource::onTransact( ret, bufferCount, mBuffersSinceStop); return NO_ERROR; } case SUPPORT_NONBLOCKING_READ: { ALOGV("supportNonblockingRead"); CHECK_INTERFACE(IMediaSource, data, reply); reply->writeInt32((int32_t)supportNonblockingRead()); return NO_ERROR; } default: return BBinder::onTransact(code, data, reply, flags); } Loading
media/libmediaplayerservice/nuplayer/GenericSource.cpp +7 −8 Original line number Diff line number Diff line Loading @@ -1385,7 +1385,7 @@ void NuPlayer::GenericSource::readBuffer( if (mIsWidevine) { maxBuffers = 2; } else { maxBuffers = 4; maxBuffers = 8; // too large of a number may influence seeks } break; case MEDIA_TRACK_TYPE_AUDIO: Loading Loading @@ -1417,25 +1417,24 @@ void NuPlayer::GenericSource::readBuffer( MediaSource::ReadOptions options; bool seeking = false; if (seekTimeUs >= 0) { options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC); seeking = true; } if (mIsWidevine) { const bool couldReadMultiple = (!mIsWidevine && track->mSource->supportReadMultiple()); if (mIsWidevine || couldReadMultiple) { options.setNonBlocking(); } bool couldReadMultiple = (!mIsWidevine && trackType == MEDIA_TRACK_TYPE_AUDIO && track->mSource->supportReadMultiple()); for (size_t numBuffers = 0; numBuffers < maxBuffers; ) { Vector<MediaBuffer *> mediaBuffers; status_t err = NO_ERROR; if (!seeking && couldReadMultiple) { err = track->mSource->readMultiple(&mediaBuffers, (maxBuffers - numBuffers)); if (couldReadMultiple) { err = track->mSource->readMultiple( &mediaBuffers, maxBuffers - numBuffers, &options); } else { MediaBuffer *mbuf = NULL; err = track->mSource->read(&mbuf, &options); Loading
media/libstagefright/MPEG4Extractor.cpp +17 −4 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ public: virtual sp<MetaData> getFormat(); virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL); virtual bool supportNonblockingRead() { return true; } virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL); protected: Loading Loading @@ -3563,13 +3564,20 @@ status_t MPEG4Source::start(MetaData *params) { // A somewhat arbitrary limit that should be sufficient for 8k video frames // If you see the message below for a valid input stream: increase the limit if (max_size > 64 * 1024 * 1024) { ALOGE("bogus max input size: %zu", max_size); const size_t kMaxBufferSize = 64 * 1024 * 1024; if (max_size > kMaxBufferSize) { ALOGE("bogus max input size: %zu > %zu", max_size, kMaxBufferSize); return ERROR_MALFORMED; } if (max_size == 0) { ALOGE("zero max input size"); return ERROR_MALFORMED; } mGroup = new MediaBufferGroup; mGroup->add_buffer(new MediaBuffer(max_size)); // Allow up to kMaxBuffers, but not if the total exceeds kMaxBufferSize. const size_t kMaxBuffers = 8; const size_t buffers = min(kMaxBufferSize / max_size, kMaxBuffers); mGroup = new MediaBufferGroup(buffers, max_size); mSrcBuffer = new (std::nothrow) uint8_t[max_size]; if (mSrcBuffer == NULL) { // file probably specified a bad max size Loading Loading @@ -4196,6 +4204,11 @@ status_t MPEG4Source::read( CHECK(mStarted); if (options != nullptr && options->getNonBlocking() && !mGroup->has_buffers()) { *out = nullptr; return WOULD_BLOCK; } if (mFirstMoofOffset > 0) { return fragmentedRead(out, options); } Loading