From bed24fdb77193eb61392549b9d8d2f04c2eca081 Mon Sep 17 00:00:00 2001 From: trav90 Date: Mon, 28 Jan 2019 08:52:36 -0600 Subject: Always treat composition time offsets as signed Even for version 0 ctts atoms that technically should contain only unsigned values. --- .../av/media/libstagefright/SampleIterator.cpp | 13 +++++- .../av/media/libstagefright/SampleTable.cpp | 46 ++++++++++++++++------ .../av/media/libstagefright/include/SampleTable.h | 4 +- 3 files changed, 49 insertions(+), 14 deletions(-) (limited to 'media/libstagefright/frameworks') diff --git a/media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp b/media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp index 37bb2b7a5..f1c797c9a 100644 --- a/media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp +++ b/media/libstagefright/frameworks/av/media/libstagefright/SampleIterator.cpp @@ -321,7 +321,18 @@ status_t SampleIterator::findSampleTime( *time = mTTSSampleTime + mTTSDuration * (sampleIndex - mTTSSampleIndex); - *time += mTable->getCompositionTimeOffset(sampleIndex); + int32_t offset = mTable->getCompositionTimeOffset(sampleIndex); + if ((offset < 0 && *time < (offset == INT32_MIN ? + INT32_MAX : uint32_t(-offset))) || + (offset > 0 && *time > UINT32_MAX - offset)) { + ALOGE("%u + %d would overflow", *time, offset); + return ERROR_OUT_OF_RANGE; + } + if (offset > 0) { + *time += offset; + } else { + *time -= (offset == INT32_MIN ? INT32_MAX : (-offset)); + } return OK; } diff --git a/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp b/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp index bbb2227e7..bc991e8e1 100644 --- a/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp +++ b/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp @@ -52,14 +52,14 @@ struct SampleTable::CompositionDeltaLookup { CompositionDeltaLookup(); void setEntries( - const uint32_t *deltaEntries, size_t numDeltaEntries); + const int32_t *deltaEntries, size_t numDeltaEntries); - uint32_t getCompositionTimeOffset(uint32_t sampleIndex); + int32_t getCompositionTimeOffset(uint32_t sampleIndex); private: Mutex mLock; - const uint32_t *mDeltaEntries; + const int32_t *mDeltaEntries; size_t mNumDeltaEntries; size_t mCurrentDeltaEntry; @@ -76,7 +76,7 @@ SampleTable::CompositionDeltaLookup::CompositionDeltaLookup() } void SampleTable::CompositionDeltaLookup::setEntries( - const uint32_t *deltaEntries, size_t numDeltaEntries) { + const int32_t *deltaEntries, size_t numDeltaEntries) { Mutex::Autolock autolock(mLock); mDeltaEntries = deltaEntries; @@ -85,7 +85,7 @@ void SampleTable::CompositionDeltaLookup::setEntries( mCurrentEntrySampleIndex = 0; } -uint32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset( +int32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset( uint32_t sampleIndex) { Mutex::Autolock autolock(mLock); @@ -381,6 +381,10 @@ status_t SampleTable::setTimeToSampleParams( return OK; } +// NOTE: per 14996-12, version 0 ctts contains unsigned values, while version 1 +// contains signed values, however some software creates version 0 files that +// contain signed values, so we're always treating the values as signed, +// regardless of version. status_t SampleTable::setCompositionTimeToSampleParams( off64_t data_offset, size_t data_size) { ALOGV("There are reordered frames present."); @@ -398,8 +402,12 @@ status_t SampleTable::setCompositionTimeToSampleParams( uint32_t numEntries = U32_AT(&header[4]); - if (U32_AT(header) != 0 && numEntries) { - // Expected version = 0, flags = 0. + uint32_t flags = U32_AT(header); + uint32_t version = flags >> 24; + flags &= 0xffffff; + + if ((version != 0 && version != 1) || flags != 0) { + // Expected version = 0 or 1, flags = 0. return ERROR_MALFORMED; } @@ -408,7 +416,7 @@ status_t SampleTable::setCompositionTimeToSampleParams( } mNumCompositionTimeDeltaEntries = numEntries; - mCompositionTimeDeltaEntries = new (mozilla::fallible) uint32_t[2 * numEntries]; + mCompositionTimeDeltaEntries = new (mozilla::fallible) int32_t[2 * numEntries]; if (!mCompositionTimeDeltaEntries) { return ERROR_BUFFER_TOO_SMALL; } @@ -801,12 +809,28 @@ status_t SampleTable::buildSampleEntriesTable() { mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex; - uint32_t compTimeDelta = + int32_t compTimeDelta = mCompositionDeltaLookup->getCompositionTimeOffset( sampleIndex); + if ((compTimeDelta < 0 && sampleTime < + (compTimeDelta == INT32_MIN ? + INT32_MAX : uint32_t(-compTimeDelta))) + || (compTimeDelta > 0 && + sampleTime > UINT32_MAX - compTimeDelta)) { + ALOGE("%u + %d would overflow, clamping", + sampleTime, compTimeDelta); + if (compTimeDelta < 0) { + sampleTime = 0; + } else { + sampleTime = UINT32_MAX; + } + compTimeDelta = 0; + } + mSampleTimeEntries[sampleIndex].mCompositionTime = - sampleTime + compTimeDelta; + compTimeDelta > 0 ? sampleTime + compTimeDelta: + sampleTime - (-compTimeDelta); } ++sampleIndex; @@ -1136,7 +1160,7 @@ status_t SampleTable::getMetaDataForSample( return OK; } -uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) { +int32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) { return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex); } diff --git a/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h b/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h index e115c92bb..c235f281e 100644 --- a/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h +++ b/media/libstagefright/frameworks/av/media/libstagefright/include/SampleTable.h @@ -134,7 +134,7 @@ private: }; SampleTimeEntry *mSampleTimeEntries; - uint32_t *mCompositionTimeDeltaEntries; + int32_t *mCompositionTimeDeltaEntries; size_t mNumCompositionTimeDeltaEntries; CompositionDeltaLookup *mCompositionDeltaLookup; @@ -171,7 +171,7 @@ private: friend struct SampleIterator; status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size); - uint32_t getCompositionTimeOffset(uint32_t sampleIndex); + int32_t getCompositionTimeOffset(uint32_t sampleIndex); static int CompareIncreasingTime(const void *, const void *); -- cgit v1.2.3