IMediaSource: add readMultiple API to speed up inter-process reading.
GenericSource: use readMultiple for audio track.
Bug: 28545177
Bug: 22775369
Change-Id: If26b80e75eba4212105d51140c4bfce85ec664f8
diff --git a/media/libmedia/IMediaSource.cpp b/media/libmedia/IMediaSource.cpp
index 84f1181..7e40e4f 100644
--- a/media/libmedia/IMediaSource.cpp
+++ b/media/libmedia/IMediaSource.cpp
@@ -37,6 +37,7 @@
PAUSE,
GETFORMAT,
READ,
+ READMULTIPLE,
RELEASE_BUFFER
};
@@ -189,6 +190,37 @@
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;
@@ -340,6 +372,37 @@
}
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);
}
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 9e33cb5..56042d4 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -1420,14 +1420,28 @@
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);
@@ -1450,7 +1464,16 @@
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
@@ -1459,7 +1482,7 @@
NULL,
false /* discard */);
#endif
- } else {
+ } else if (err != OK) {
queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
track->mPackets->signalEOS(err);
break;