@@ -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