Always treat composition time offsets as signed

Even for version 0 ctts atoms that technically should contain only
unsigned values.
This commit is contained in:
trav90 2019-01-28 08:52:36 -06:00 committed by Roy Tam
commit a137fdb1c1
3 changed files with 49 additions and 14 deletions

View file

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

View file

@ -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);
}

View file

@ -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 *);