MediaMuxer:Unblock writeSampleData,gate pushBuffer
As MediaMuxer's writeSampleData handles inputs from multiple tracks,
limited the scope of mMuxerLock to an inner block so that the
current track's buffer does not wait until the completion
of processing of previous buffer of the same or another track.
It's the responsibility of individual track - MediaAdapter object
to gate its buffers. When interleaving is enabled and data
is written in chunks, the delay was very much noticeable.
For example, when video buffers were getting written to the file,
no new audio buffer was queued to it's thread.
This change has decreased the time required
to complete muxing data from multiple tracks by as much as 35%.
Bug: 157373376
Test: atest android.media.cts.MediaMuxerTest \
android.mediav2.cts.MuxerTest \
android.mediav2.cts.MuxerUnitTest
Change-Id: If02f60441292afcf29d01939b09a80bbba43e6b6
diff --git a/media/libstagefright/MediaAdapter.cpp b/media/libstagefright/MediaAdapter.cpp
index f1b6e8c..5a2a910 100644
--- a/media/libstagefright/MediaAdapter.cpp
+++ b/media/libstagefright/MediaAdapter.cpp
@@ -114,6 +114,13 @@
return -EINVAL;
}
+ /* As mAdapterLock is unlocked while waiting for signalBufferReturned,
+ * a new buffer for the same track could be pushed from another thread
+ * in the client process, mBufferGatingMutex will help to hold that
+ * until the previous buffer is processed.
+ */
+ std::unique_lock<std::mutex> lk(mBufferGatingMutex);
+
Mutex::Autolock autoLock(mAdapterLock);
if (!mStarted) {
ALOGE("pushBuffer called before start");
diff --git a/media/libstagefright/MediaMuxer.cpp b/media/libstagefright/MediaMuxer.cpp
index cab4ebd..6ab65c9 100644
--- a/media/libstagefright/MediaMuxer.cpp
+++ b/media/libstagefright/MediaMuxer.cpp
@@ -175,21 +175,28 @@
status_t MediaMuxer::writeSampleData(const sp<ABuffer> &buffer, size_t trackIndex,
int64_t timeUs, uint32_t flags) {
- Mutex::Autolock autoLock(mMuxerLock);
-
if (buffer.get() == NULL) {
ALOGE("WriteSampleData() get an NULL buffer.");
return -EINVAL;
}
+ {
+ /* As MediaMuxer's writeSampleData handles inputs from multiple tracks,
+ * limited the scope of mMuxerLock to this inner block so that the
+ * current track's buffer does not wait until the completion
+ * of processing of previous buffer of the same or another track.
+ * It's the responsibility of individual track - MediaAdapter object
+ * to gate its buffers.
+ */
+ Mutex::Autolock autoLock(mMuxerLock);
+ if (mState != STARTED) {
+ ALOGE("WriteSampleData() is called in invalid state %d", mState);
+ return INVALID_OPERATION;
+ }
- if (mState != STARTED) {
- ALOGE("WriteSampleData() is called in invalid state %d", mState);
- return INVALID_OPERATION;
- }
-
- if (trackIndex >= mTrackList.size()) {
- ALOGE("WriteSampleData() get an invalid index %zu", trackIndex);
- return -EINVAL;
+ if (trackIndex >= mTrackList.size()) {
+ ALOGE("WriteSampleData() get an invalid index %zu", trackIndex);
+ return -EINVAL;
+ }
}
MediaBuffer* mediaBuffer = new MediaBuffer(buffer);
diff --git a/media/libstagefright/include/media/stagefright/MediaAdapter.h b/media/libstagefright/include/media/stagefright/MediaAdapter.h
index 177a9e9..c7d7765 100644
--- a/media/libstagefright/include/media/stagefright/MediaAdapter.h
+++ b/media/libstagefright/include/media/stagefright/MediaAdapter.h
@@ -58,6 +58,7 @@
private:
Mutex mAdapterLock;
+ std::mutex mBufferGatingMutex;
// Make sure the read() wait for the incoming buffer.
Condition mBufferReadCond;
// Make sure the pushBuffer() wait for the current buffer consumed.