Loading include/media/IMediaSource.h +23 −1 Original line number Diff line number Diff line Loading @@ -32,6 +32,11 @@ class IMediaSource : public IInterface { public: DECLARE_META_INTERFACE(MediaSource); enum { // Maximum number of buffers would be read in readMultiple. kMaxNumReadMultiple = 128, }; // To be called before any other methods on this object, except // getFormat(). virtual status_t start(MetaData *params = NULL) = 0; Loading Loading @@ -87,7 +92,7 @@ public: }; // Returns a new buffer of data. Call blocks until a // buffer is available, an error is encountered of the end of the stream // buffer is available, an error is encountered or the end of the stream // is reached. // End of stream is signalled by a result of ERROR_END_OF_STREAM. // A result of INFO_FORMAT_CHANGED indicates that the format of this Loading @@ -96,6 +101,19 @@ public: virtual status_t read( MediaBuffer **buffer, const ReadOptions *options = NULL) = 0; // Returns a vector of new buffers of data. The vector size could be // <= |maxNumBuffers|. Used for buffers with small size // since all buffer data are passed back by binder, not shared memory. // Call blocks until an error is encountered, or the end of the stream is // reached, or format change is hit, or |kMaxNumReadMultiple| buffers have // been read. // End of stream is signalled by a result of ERROR_END_OF_STREAM. // A result of INFO_FORMAT_CHANGED indicates that the format of this // MediaSource has changed mid-stream, the client can continue reading // but should be prepared for buffers of the new configuration. virtual status_t readMultiple( Vector<MediaBuffer *> *buffers, uint32_t maxNumBuffers = 1) = 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 @@ -126,6 +144,10 @@ public: return ERROR_UNSUPPORTED; } virtual status_t readMultiple( Vector<MediaBuffer *> * /* buffers */, uint32_t /* maxNumBuffers = 1 */) { return ERROR_UNSUPPORTED; } protected: virtual ~BnMediaSource(); Loading media/libmedia/IMediaSource.cpp +63 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ enum { PAUSE, GETFORMAT, READ, READMULTIPLE, RELEASE_BUFFER }; Loading Loading @@ -189,6 +190,37 @@ public: return ret; } virtual status_t readMultiple(Vector<MediaBuffer *> *buffers, uint32_t maxNumBuffers) { ALOGV("readMultiple"); if (buffers == NULL || !buffers->isEmpty()) { return BAD_VALUE; } Parcel data, reply; data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor()); data.writeUint32(maxNumBuffers); status_t ret = remote()->transact(READMULTIPLE, data, &reply); if (ret != NO_ERROR) { return ret; } // wrap the returned data in a vector of MediaBuffers int32_t bufCount = 0; while (1) { if (reply.readInt32() == 0) { break; } int32_t len = reply.readInt32(); ALOGV("got len %d", len); MediaBuffer *buf = new MediaBuffer(len); reply.read(buf->data(), len); buf->meta_data()->updateFromParcel(reply); buffers->push_back(buf); ++bufCount; } ret = reply.readInt32(); ALOGV("got status %d, bufCount %d", ret, bufCount); return ret; } virtual status_t pause() { ALOGV("pause"); Parcel data, reply; Loading Loading @@ -340,6 +372,37 @@ status_t BnMediaSource::onTransact( } return NO_ERROR; } case READMULTIPLE: { ALOGV("readmultiple"); CHECK_INTERFACE(IMediaSource, data, reply); uint32_t maxNumBuffers; data.readUint32(&maxNumBuffers); status_t ret = NO_ERROR; uint32_t bufferCount = 0; if (maxNumBuffers > kMaxNumReadMultiple) { maxNumBuffers = kMaxNumReadMultiple; } while (bufferCount < maxNumBuffers) { if (reply->dataSize() >= MediaBuffer::kSharedMemThreshold) { break; } MediaBuffer *buf = NULL; ret = read(&buf, NULL); if (ret != NO_ERROR || buf == NULL) { break; } ++bufferCount; reply->writeInt32(1); // indicate one more MediaBuffer. reply->writeByteArray( buf->range_length(), (uint8_t*)buf->data() + buf->range_offset()); buf->meta_data()->writeToParcel(*reply); buf->release(); } reply->writeInt32(0); // indicate no more MediaBuffer. reply->writeInt32(ret); return NO_ERROR; } default: return BBinder::onTransact(code, data, reply, flags); } Loading media/libmediaplayerservice/nuplayer/GenericSource.cpp +28 −5 Original line number Diff line number Diff line Loading @@ -1420,14 +1420,28 @@ void NuPlayer::GenericSource::readBuffer( options.setNonBlocking(); } bool couldReadMultiple = (!mIsWidevine && trackType == MEDIA_TRACK_TYPE_AUDIO); for (size_t numBuffers = 0; numBuffers < maxBuffers; ) { MediaBuffer *mbuf; status_t err = track->mSource->read(&mbuf, &options); Vector<MediaBuffer *> mediaBuffers; status_t err = NO_ERROR; if (!seeking && couldReadMultiple) { err = track->mSource->readMultiple(&mediaBuffers, (maxBuffers - numBuffers)); } else { MediaBuffer *mbuf = NULL; err = track->mSource->read(&mbuf, &options); if (err == OK && mbuf != NULL) { mediaBuffers.push_back(mbuf); } } options.clearSeekTo(); if (err == OK) { size_t id = 0; size_t count = mediaBuffers.size(); for (; id < count; ++id) { int64_t timeUs; MediaBuffer *mbuf = mediaBuffers[id]; if (!mbuf->meta_data()->findInt64(kKeyTime, &timeUs)) { mbuf->meta_data()->dumpToLog(); track->mPackets->signalEOS(ERROR_MALFORMED); Loading @@ -1450,7 +1464,16 @@ void NuPlayer::GenericSource::readBuffer( formatChange = false; seeking = false; ++numBuffers; } else if (err == WOULD_BLOCK) { } if (id < count) { // Error, some mediaBuffer doesn't have kKeyTime. for (; id < count; ++id) { mediaBuffers[id]->release(); } break; } if (err == WOULD_BLOCK) { break; } else if (err == INFO_FORMAT_CHANGED) { #if 0 Loading @@ -1459,7 +1482,7 @@ void NuPlayer::GenericSource::readBuffer( NULL, false /* discard */); #endif } else { } else if (err != OK) { queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track); track->mPackets->signalEOS(err); break; Loading Loading
include/media/IMediaSource.h +23 −1 Original line number Diff line number Diff line Loading @@ -32,6 +32,11 @@ class IMediaSource : public IInterface { public: DECLARE_META_INTERFACE(MediaSource); enum { // Maximum number of buffers would be read in readMultiple. kMaxNumReadMultiple = 128, }; // To be called before any other methods on this object, except // getFormat(). virtual status_t start(MetaData *params = NULL) = 0; Loading Loading @@ -87,7 +92,7 @@ public: }; // Returns a new buffer of data. Call blocks until a // buffer is available, an error is encountered of the end of the stream // buffer is available, an error is encountered or the end of the stream // is reached. // End of stream is signalled by a result of ERROR_END_OF_STREAM. // A result of INFO_FORMAT_CHANGED indicates that the format of this Loading @@ -96,6 +101,19 @@ public: virtual status_t read( MediaBuffer **buffer, const ReadOptions *options = NULL) = 0; // Returns a vector of new buffers of data. The vector size could be // <= |maxNumBuffers|. Used for buffers with small size // since all buffer data are passed back by binder, not shared memory. // Call blocks until an error is encountered, or the end of the stream is // reached, or format change is hit, or |kMaxNumReadMultiple| buffers have // been read. // End of stream is signalled by a result of ERROR_END_OF_STREAM. // A result of INFO_FORMAT_CHANGED indicates that the format of this // MediaSource has changed mid-stream, the client can continue reading // but should be prepared for buffers of the new configuration. virtual status_t readMultiple( Vector<MediaBuffer *> *buffers, uint32_t maxNumBuffers = 1) = 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 @@ -126,6 +144,10 @@ public: return ERROR_UNSUPPORTED; } virtual status_t readMultiple( Vector<MediaBuffer *> * /* buffers */, uint32_t /* maxNumBuffers = 1 */) { return ERROR_UNSUPPORTED; } protected: virtual ~BnMediaSource(); Loading
media/libmedia/IMediaSource.cpp +63 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ enum { PAUSE, GETFORMAT, READ, READMULTIPLE, RELEASE_BUFFER }; Loading Loading @@ -189,6 +190,37 @@ public: return ret; } virtual status_t readMultiple(Vector<MediaBuffer *> *buffers, uint32_t maxNumBuffers) { ALOGV("readMultiple"); if (buffers == NULL || !buffers->isEmpty()) { return BAD_VALUE; } Parcel data, reply; data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor()); data.writeUint32(maxNumBuffers); status_t ret = remote()->transact(READMULTIPLE, data, &reply); if (ret != NO_ERROR) { return ret; } // wrap the returned data in a vector of MediaBuffers int32_t bufCount = 0; while (1) { if (reply.readInt32() == 0) { break; } int32_t len = reply.readInt32(); ALOGV("got len %d", len); MediaBuffer *buf = new MediaBuffer(len); reply.read(buf->data(), len); buf->meta_data()->updateFromParcel(reply); buffers->push_back(buf); ++bufCount; } ret = reply.readInt32(); ALOGV("got status %d, bufCount %d", ret, bufCount); return ret; } virtual status_t pause() { ALOGV("pause"); Parcel data, reply; Loading Loading @@ -340,6 +372,37 @@ status_t BnMediaSource::onTransact( } return NO_ERROR; } case READMULTIPLE: { ALOGV("readmultiple"); CHECK_INTERFACE(IMediaSource, data, reply); uint32_t maxNumBuffers; data.readUint32(&maxNumBuffers); status_t ret = NO_ERROR; uint32_t bufferCount = 0; if (maxNumBuffers > kMaxNumReadMultiple) { maxNumBuffers = kMaxNumReadMultiple; } while (bufferCount < maxNumBuffers) { if (reply->dataSize() >= MediaBuffer::kSharedMemThreshold) { break; } MediaBuffer *buf = NULL; ret = read(&buf, NULL); if (ret != NO_ERROR || buf == NULL) { break; } ++bufferCount; reply->writeInt32(1); // indicate one more MediaBuffer. reply->writeByteArray( buf->range_length(), (uint8_t*)buf->data() + buf->range_offset()); buf->meta_data()->writeToParcel(*reply); buf->release(); } reply->writeInt32(0); // indicate no more MediaBuffer. reply->writeInt32(ret); return NO_ERROR; } default: return BBinder::onTransact(code, data, reply, flags); } Loading
media/libmediaplayerservice/nuplayer/GenericSource.cpp +28 −5 Original line number Diff line number Diff line Loading @@ -1420,14 +1420,28 @@ void NuPlayer::GenericSource::readBuffer( options.setNonBlocking(); } bool couldReadMultiple = (!mIsWidevine && trackType == MEDIA_TRACK_TYPE_AUDIO); for (size_t numBuffers = 0; numBuffers < maxBuffers; ) { MediaBuffer *mbuf; status_t err = track->mSource->read(&mbuf, &options); Vector<MediaBuffer *> mediaBuffers; status_t err = NO_ERROR; if (!seeking && couldReadMultiple) { err = track->mSource->readMultiple(&mediaBuffers, (maxBuffers - numBuffers)); } else { MediaBuffer *mbuf = NULL; err = track->mSource->read(&mbuf, &options); if (err == OK && mbuf != NULL) { mediaBuffers.push_back(mbuf); } } options.clearSeekTo(); if (err == OK) { size_t id = 0; size_t count = mediaBuffers.size(); for (; id < count; ++id) { int64_t timeUs; MediaBuffer *mbuf = mediaBuffers[id]; if (!mbuf->meta_data()->findInt64(kKeyTime, &timeUs)) { mbuf->meta_data()->dumpToLog(); track->mPackets->signalEOS(ERROR_MALFORMED); Loading @@ -1450,7 +1464,16 @@ void NuPlayer::GenericSource::readBuffer( formatChange = false; seeking = false; ++numBuffers; } else if (err == WOULD_BLOCK) { } if (id < count) { // Error, some mediaBuffer doesn't have kKeyTime. for (; id < count; ++id) { mediaBuffers[id]->release(); } break; } if (err == WOULD_BLOCK) { break; } else if (err == INFO_FORMAT_CHANGED) { #if 0 Loading @@ -1459,7 +1482,7 @@ void NuPlayer::GenericSource::readBuffer( NULL, false /* discard */); #endif } else { } else if (err != OK) { queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track); track->mPackets->signalEOS(err); break; Loading