summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2011-09-28 16:08:59 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-09-28 16:08:59 -0700
commitfea8f6217455d8cfc957e5b30f4eb2349859518f (patch)
treef264d4ead8fd230576c8b74a2effe6c581fd838b /media
parent5530493f9abcd8f1f0b06cccecd6900e86a99778 (diff)
parent792e33fd19e57e0d615d401a54ab567d04f16251 (diff)
downloadframeworks_av-fea8f6217455d8cfc957e5b30f4eb2349859518f.zip
frameworks_av-fea8f6217455d8cfc957e5b30f4eb2349859518f.tar.gz
frameworks_av-fea8f6217455d8cfc957e5b30f4eb2349859518f.tar.bz2
Merge "Support multiple NAL fragments per .mkv payload"
Diffstat (limited to 'media')
-rw-r--r--media/libstagefright/matroska/MatroskaExtractor.cpp108
1 files changed, 61 insertions, 47 deletions
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index ffa3356..20a25d7d 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -423,74 +423,88 @@ again:
MediaBuffer *frame = *mPendingFrames.begin();
mPendingFrames.erase(mPendingFrames.begin());
- size_t size = frame->range_length();
-
if (mType != AVC) {
*out = frame;
return OK;
}
- if (size < mNALSizeLen) {
- frame->release();
- frame = NULL;
+ // Each input frame contains one or more NAL fragments, each fragment
+ // is prefixed by mNALSizeLen bytes giving the fragment length,
+ // followed by a corresponding number of bytes containing the fragment.
+ // We output all these fragments into a single large buffer separated
+ // by startcodes (0x00 0x00 0x00 0x01).
+
+ const uint8_t *srcPtr =
+ (const uint8_t *)frame->data() + frame->range_offset();
+
+ size_t srcSize = frame->range_length();
+
+ size_t dstSize = 0;
+ MediaBuffer *buffer = NULL;
+ uint8_t *dstPtr = NULL;
+
+ for (int32_t pass = 0; pass < 2; ++pass) {
+ size_t srcOffset = 0;
+ size_t dstOffset = 0;
+ while (srcOffset + mNALSizeLen <= srcSize) {
+ size_t NALsize;
+ switch (mNALSizeLen) {
+ case 1: NALsize = srcPtr[srcOffset]; break;
+ case 2: NALsize = U16_AT(srcPtr + srcOffset); break;
+ case 3: NALsize = U24_AT(srcPtr + srcOffset); break;
+ case 4: NALsize = U32_AT(srcPtr + srcOffset); break;
+ default:
+ TRESPASS();
+ }
- return ERROR_MALFORMED;
- }
+ if (srcOffset + mNALSizeLen + NALsize > srcSize) {
+ break;
+ }
- // In the case of AVC content, each NAL unit is prefixed by
- // mNALSizeLen bytes of length. We want to prefix the data with
- // a four-byte 0x00000001 startcode instead of the length prefix.
- // mNALSizeLen ranges from 1 through 4 bytes, so add an extra
- // 3 bytes of padding to the buffer start.
- static const size_t kPadding = 3;
+ if (pass == 1) {
+ memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4);
- MediaBuffer *buffer = new MediaBuffer(size + kPadding);
+ memcpy(&dstPtr[dstOffset + 4],
+ &srcPtr[srcOffset + mNALSizeLen],
+ NALsize);
+ }
- int64_t timeUs;
- CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs));
- int32_t isSync;
- CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync));
+ dstOffset += 4; // 0x00 00 00 01
+ dstOffset += NALsize;
- buffer->meta_data()->setInt64(kKeyTime, timeUs);
- buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
+ srcOffset += mNALSizeLen + NALsize;
+ }
- memcpy((uint8_t *)buffer->data() + kPadding,
- (const uint8_t *)frame->data() + frame->range_offset(),
- size);
+ if (srcOffset < srcSize) {
+ // There were trailing bytes or not enough data to complete
+ // a fragment.
- buffer->set_range(kPadding, size);
+ frame->release();
+ frame = NULL;
- frame->release();
- frame = NULL;
+ return ERROR_MALFORMED;
+ }
- uint8_t *data = (uint8_t *)buffer->data();
+ if (pass == 0) {
+ dstSize = dstOffset;
- size_t NALsize;
- switch (mNALSizeLen) {
- case 1: NALsize = data[kPadding]; break;
- case 2: NALsize = U16_AT(&data[kPadding]); break;
- case 3: NALsize = U24_AT(&data[kPadding]); break;
- case 4: NALsize = U32_AT(&data[kPadding]); break;
- default:
- TRESPASS();
- }
+ buffer = new MediaBuffer(dstSize);
- if (size < NALsize + mNALSizeLen) {
- buffer->release();
- buffer = NULL;
+ int64_t timeUs;
+ CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs));
+ int32_t isSync;
+ CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync));
- return ERROR_MALFORMED;
- }
+ buffer->meta_data()->setInt64(kKeyTime, timeUs);
+ buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
- if (size > NALsize + mNALSizeLen) {
- LOGW("discarding %d bytes of data.", size - NALsize - mNALSizeLen);
+ dstPtr = (uint8_t *)buffer->data();
+ }
}
- // actual data starts at &data[kPadding + mNALSizeLen]
-
- memcpy(&data[mNALSizeLen - 1], "\x00\x00\x00\x01", 4);
- buffer->set_range(mNALSizeLen - 1, NALsize + 4);
+ frame->release();
+ frame = NULL;
*out = buffer;