Skip to content

Commit 0044a15

Browse files
theandi666Android (Google) Code Review
authored andcommitted
Merge "Support multiple NAL fragments per .mkv payload"
2 parents cbbecdf + 2378341 commit 0044a15

File tree

1 file changed

+61
-47
lines changed

1 file changed

+61
-47
lines changed

media/libstagefright/matroska/MatroskaExtractor.cpp

Lines changed: 61 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -423,74 +423,88 @@ status_t MatroskaSource::read(
423423
MediaBuffer *frame = *mPendingFrames.begin();
424424
mPendingFrames.erase(mPendingFrames.begin());
425425

426-
size_t size = frame->range_length();
427-
428426
if (mType != AVC) {
429427
*out = frame;
430428

431429
return OK;
432430
}
433431

434-
if (size < mNALSizeLen) {
435-
frame->release();
436-
frame = NULL;
432+
// Each input frame contains one or more NAL fragments, each fragment
433+
// is prefixed by mNALSizeLen bytes giving the fragment length,
434+
// followed by a corresponding number of bytes containing the fragment.
435+
// We output all these fragments into a single large buffer separated
436+
// by startcodes (0x00 0x00 0x00 0x01).
437+
438+
const uint8_t *srcPtr =
439+
(const uint8_t *)frame->data() + frame->range_offset();
440+
441+
size_t srcSize = frame->range_length();
442+
443+
size_t dstSize = 0;
444+
MediaBuffer *buffer = NULL;
445+
uint8_t *dstPtr = NULL;
446+
447+
for (int32_t pass = 0; pass < 2; ++pass) {
448+
size_t srcOffset = 0;
449+
size_t dstOffset = 0;
450+
while (srcOffset + mNALSizeLen <= srcSize) {
451+
size_t NALsize;
452+
switch (mNALSizeLen) {
453+
case 1: NALsize = srcPtr[srcOffset]; break;
454+
case 2: NALsize = U16_AT(srcPtr + srcOffset); break;
455+
case 3: NALsize = U24_AT(srcPtr + srcOffset); break;
456+
case 4: NALsize = U32_AT(srcPtr + srcOffset); break;
457+
default:
458+
TRESPASS();
459+
}
437460

438-
return ERROR_MALFORMED;
439-
}
461+
if (srcOffset + mNALSizeLen + NALsize > srcSize) {
462+
break;
463+
}
440464

441-
// In the case of AVC content, each NAL unit is prefixed by
442-
// mNALSizeLen bytes of length. We want to prefix the data with
443-
// a four-byte 0x00000001 startcode instead of the length prefix.
444-
// mNALSizeLen ranges from 1 through 4 bytes, so add an extra
445-
// 3 bytes of padding to the buffer start.
446-
static const size_t kPadding = 3;
465+
if (pass == 1) {
466+
memcpy(&dstPtr[dstOffset], "\x00\x00\x00\x01", 4);
447467

448-
MediaBuffer *buffer = new MediaBuffer(size + kPadding);
468+
memcpy(&dstPtr[dstOffset + 4],
469+
&srcPtr[srcOffset + mNALSizeLen],
470+
NALsize);
471+
}
449472

450-
int64_t timeUs;
451-
CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs));
452-
int32_t isSync;
453-
CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync));
473+
dstOffset += 4; // 0x00 00 00 01
474+
dstOffset += NALsize;
454475

455-
buffer->meta_data()->setInt64(kKeyTime, timeUs);
456-
buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
476+
srcOffset += mNALSizeLen + NALsize;
477+
}
457478

458-
memcpy((uint8_t *)buffer->data() + kPadding,
459-
(const uint8_t *)frame->data() + frame->range_offset(),
460-
size);
479+
if (srcOffset < srcSize) {
480+
// There were trailing bytes or not enough data to complete
481+
// a fragment.
461482

462-
buffer->set_range(kPadding, size);
483+
frame->release();
484+
frame = NULL;
463485

464-
frame->release();
465-
frame = NULL;
486+
return ERROR_MALFORMED;
487+
}
466488

467-
uint8_t *data = (uint8_t *)buffer->data();
489+
if (pass == 0) {
490+
dstSize = dstOffset;
468491

469-
size_t NALsize;
470-
switch (mNALSizeLen) {
471-
case 1: NALsize = data[kPadding]; break;
472-
case 2: NALsize = U16_AT(&data[kPadding]); break;
473-
case 3: NALsize = U24_AT(&data[kPadding]); break;
474-
case 4: NALsize = U32_AT(&data[kPadding]); break;
475-
default:
476-
TRESPASS();
477-
}
492+
buffer = new MediaBuffer(dstSize);
478493

479-
if (size < NALsize + mNALSizeLen) {
480-
buffer->release();
481-
buffer = NULL;
494+
int64_t timeUs;
495+
CHECK(frame->meta_data()->findInt64(kKeyTime, &timeUs));
496+
int32_t isSync;
497+
CHECK(frame->meta_data()->findInt32(kKeyIsSyncFrame, &isSync));
482498

483-
return ERROR_MALFORMED;
484-
}
499+
buffer->meta_data()->setInt64(kKeyTime, timeUs);
500+
buffer->meta_data()->setInt32(kKeyIsSyncFrame, isSync);
485501

486-
if (size > NALsize + mNALSizeLen) {
487-
LOGW("discarding %d bytes of data.", size - NALsize - mNALSizeLen);
502+
dstPtr = (uint8_t *)buffer->data();
503+
}
488504
}
489505

490-
// actual data starts at &data[kPadding + mNALSizeLen]
491-
492-
memcpy(&data[mNALSizeLen - 1], "\x00\x00\x00\x01", 4);
493-
buffer->set_range(mNALSizeLen - 1, NALsize + 4);
506+
frame->release();
507+
frame = NULL;
494508

495509
*out = buffer;
496510

0 commit comments

Comments
 (0)