From 0d6ac1003ce1c8aacdf6b6b5295db64cd30a766b Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Mon, 18 Aug 2014 13:02:22 +1200 Subject: [PATCH] Bug 1054144 - Support 'tfdt' in MP4 parser; r=edwin --- .../media/libstagefright/MPEG4Extractor.cpp | 65 ++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp index 93ac8e5cfe20..e5038812f8d0 100644 --- a/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/frameworks/av/media/libstagefright/MPEG4Extractor.cpp @@ -106,11 +106,20 @@ private: size_t parseNALSize(const uint8_t *data) const; status_t parseChunk(off64_t *offset); + status_t parseTrackFragmentData(off64_t offset, off64_t size); status_t parseTrackFragmentHeader(off64_t offset, off64_t size); status_t parseTrackFragmentRun(off64_t offset, off64_t size); status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size); status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size); + struct TrackFragmentData { + TrackFragmentData(): mPresent(false), mFlags(0), mBaseMediaDecodeTime(0) {} + bool mPresent; + uint32_t mFlags; + uint64_t mBaseMediaDecodeTime; + }; + TrackFragmentData mTrackFragmentData; + struct TrackFragmentHeaderInfo { enum Flags { kBaseDataOffsetPresent = 0x01, @@ -2572,6 +2581,16 @@ status_t MPEG4Source::parseChunk(off64_t *offset) { break; } + case FOURCC('t', 'f', 'd', 't'): + { + status_t err; + if ((err = parseTrackFragmentData(data_offset, chunk_data_size)) != OK) { + return err; + } + *offset += chunk_size; + break; + } + case FOURCC('t', 'f', 'h', 'd'): { status_t err; if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) { @@ -2786,6 +2805,41 @@ status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(off64_t offset, off return OK; } +status_t MPEG4Source::parseTrackFragmentData(off64_t offset, off64_t size) { + + if (size < 8) { + return -EINVAL; + } + + uint32_t flags; + if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags + return ERROR_MALFORMED; + } + + uint8_t version = flags >> 24; + mTrackFragmentData.mFlags = flags; + + if (version == 0) { + uint32_t time; + if (mDataSource->getUInt32(offset + 4, &time)) { + mTrackFragmentData.mBaseMediaDecodeTime = time; + mTrackFragmentData.mPresent = true; + return OK; + } + } else if (version == 1) { + if (size < 12) { + return -EINVAL; + } + if (mDataSource->getUInt64(offset + 4, + &mTrackFragmentData.mBaseMediaDecodeTime)) { + mTrackFragmentData.mPresent = true; + return OK; + } + } + + return ERROR_MALFORMED; +} + status_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) { if (size < 8) { @@ -3448,10 +3502,15 @@ status_t MPEG4Source::fragmentedRead( mCurrentMoofOffset = nextMoof; mCurrentSamples.clear(); mCurrentSampleIndex = 0; + mTrackFragmentData.mPresent = false; parseChunk(&nextMoof); - if (mCurrentSampleIndex >= mCurrentSamples.size()) { - return ERROR_END_OF_STREAM; - } + if (mCurrentSampleIndex >= mCurrentSamples.size()) { + return ERROR_END_OF_STREAM; + } + + if (mTrackFragmentData.mPresent) { + mCurrentTime = mTrackFragmentData.mBaseMediaDecodeTime; + } } const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];