MPEG4Writer: Handle writing multiple NAL units in a video sample
Encoder may prepend extension NALs (eg: AVC SVC extension NAL
for temporal layer info) to the VCL NAL.
Look out for non-VCL NALUs preceeding the slice NALs and write
them out separately.
Search for a limited size since such NALs are of small size.
Bug: 27596987
Change-Id: I434c5252098faca99c0ee18e6bc5f43a67718eba
(cherry picked from commit 7941196cf2f21c1a59c5cb2e8b93bbb6f7ff463c)
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index a6901a8..fc97665 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -187,6 +187,7 @@
// Acquire lock before calling these methods
off64_t addSample_l(MediaBuffer *buffer);
off64_t addLengthPrefixedSample_l(MediaBuffer *buffer);
+ off64_t addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer);
bool exceedsFileSizeLimit();
bool use32BitFileOffset() const;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 24fb987..0209f59 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -43,6 +43,7 @@
#include "include/ESDS.h"
#include "include/HevcUtils.h"
+#include "include/avc_utils.h"
#ifndef __predict_false
#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
@@ -1162,6 +1163,37 @@
}
}
+off64_t MPEG4Writer::addMultipleLengthPrefixedSamples_l(MediaBuffer *buffer) {
+ off64_t old_offset = mOffset;
+
+ const size_t kExtensionNALSearchRange = 64; // bytes to look for non-VCL NALUs
+
+ const uint8_t *dataStart = (const uint8_t *)buffer->data() + buffer->range_offset();
+ const uint8_t *currentNalStart = dataStart;
+ const uint8_t *nextNalStart;
+ const uint8_t *data = dataStart;
+ size_t nextNalSize;
+ size_t searchSize = buffer->range_length() > kExtensionNALSearchRange ?
+ kExtensionNALSearchRange : buffer->range_length();
+
+ while (getNextNALUnit(&data, &searchSize, &nextNalStart,
+ &nextNalSize, true) == OK) {
+ size_t currentNalSize = nextNalStart - currentNalStart - 3 /* strip start-code */;
+ MediaBuffer *nalBuf = new MediaBuffer((void *)currentNalStart, currentNalSize);
+ addLengthPrefixedSample_l(nalBuf);
+ nalBuf->release();
+
+ currentNalStart = nextNalStart;
+ }
+
+ size_t currentNalOffset = currentNalStart - dataStart;
+ buffer->set_range(buffer->range_offset() + currentNalOffset,
+ buffer->range_length() - currentNalOffset);
+ addLengthPrefixedSample_l(buffer);
+
+ return old_offset;
+}
+
off64_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
off64_t old_offset = mOffset;
@@ -1684,7 +1716,7 @@
List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHevc())
- ? addLengthPrefixedSample_l(*it)
+ ? addMultipleLengthPrefixedSamples_l(*it)
: addSample_l(*it);
if (isFirstSample) {
@@ -2593,7 +2625,7 @@
trackProgressStatus(timestampUs);
}
if (!hasMultipleTracks) {
- off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addLengthPrefixedSample_l(copy)
+ off64_t offset = (mIsAvc || mIsHevc) ? mOwner->addMultipleLengthPrefixedSamples_l(copy)
: mOwner->addSample_l(copy);
uint32_t count = (mOwner->use32BitFileOffset()