Bug 1410565 - check mTimescale to avoid dividing by zero. r?kinetik
MozReview-Commit-ID: 7uxgaVAbQds
--- a/media/libstagefright/binding/MoofParser.cpp
+++ b/media/libstagefright/binding/MoofParser.cpp
@@ -437,19 +437,20 @@ Moof::Moof(Box& aBox, Trex& aTrex, Mvhd&
// In MP4, the duration of a sample is defined as the delta between two decode
// timestamps. The operation above has updated the duration of each sample
// as a Sample's duration is mCompositionRange.end - mCompositionRange.start
// MSE's TrackBuffersManager expects dts that increased by the sample's
// duration, so we rewrite the dts accordingly.
int64_t presentationDuration =
ctsOrder.LastElement()->mCompositionRange.end
- ctsOrder[0]->mCompositionRange.start;
- int64_t endDecodeTime =
- aMdhd.ToMicroseconds((int64_t)*aDecodeTime - aEdts.mMediaStart)
- + aMvhd.ToMicroseconds(aEdts.mEmptyOffset);
+ auto decodeOffset = aMdhd.ToMicroseconds((int64_t)*aDecodeTime - aEdts.mMediaStart);
+ auto offsetOffset = aMvhd.ToMicroseconds(aEdts.mEmptyOffset);
+ int64_t endDecodeTime = decodeOffset.isOk() & offsetOffset.isOk() ?
+ decodeOffset.unwrap() + offsetOffset.unwrap() : 0;
int64_t decodeDuration = endDecodeTime - mIndex[0].mDecodeTime;
double adjust = (double)decodeDuration / presentationDuration;
int64_t dtsOffset = mIndex[0].mDecodeTime;
int64_t compositionDuration = 0;
// Adjust the dts, ensuring that the new adjusted dts will never be greater
// than decodeTime (the next moof's decode start time).
for (auto& sample : mIndex) {
sample.mDecodeTime = dtsOffset + int64_t(compositionDuration * adjust);
@@ -675,34 +676,37 @@ Moof::ParseTrun(Box& aBox, Tfhd& aTfhd,
MOZ_TRY_VAR(ctsOffset, reader->Read32());
}
if (sampleSize) {
Sample sample;
sample.mByteRange = MediaByteRange(offset, offset + sampleSize);
offset += sampleSize;
- sample.mDecodeTime =
- aMdhd.ToMicroseconds((int64_t)decodeTime - aEdts.mMediaStart) + aMvhd.ToMicroseconds(aEdts.mEmptyOffset);
- sample.mCompositionRange = Interval<Microseconds>(
- aMdhd.ToMicroseconds((int64_t)decodeTime + ctsOffset - aEdts.mMediaStart) + aMvhd.ToMicroseconds(aEdts.mEmptyOffset),
- aMdhd.ToMicroseconds((int64_t)decodeTime + ctsOffset + sampleDuration - aEdts.mMediaStart) + aMvhd.ToMicroseconds(aEdts.mEmptyOffset));
-
+ Microseconds decodeOffset, emptyOffset, startCts, endCts;
+ MOZ_TRY_VAR(decodeOffset, aMdhd.ToMicroseconds((int64_t)decodeTime - aEdts.mMediaStart));
+ MOZ_TRY_VAR(emptyOffset, aMvhd.ToMicroseconds(aEdts.mEmptyOffset));
+ sample.mDecodeTime = decodeOffset + emptyOffset;
+ MOZ_TRY_VAR(startCts, aMdhd.ToMicroseconds((int64_t)decodeTime + ctsOffset - aEdts.mMediaStart));
+ MOZ_TRY_VAR(endCts, aMdhd.ToMicroseconds((int64_t)decodeTime + ctsOffset + sampleDuration - aEdts.mMediaStart));
+ sample.mCompositionRange = Interval<Microseconds>(startCts + emptyOffset, endCts + emptyOffset);
// Sometimes audio streams don't properly mark their samples as keyframes,
// because every audio sample is a keyframe.
sample.mSync = !(sampleFlags & 0x1010000) || aIsAudio;
// FIXME: Make this infallible after bug 968520 is done.
MOZ_ALWAYS_TRUE(mIndex.AppendElement(sample, fallible));
mMdatRange = mMdatRange.Span(sample.mByteRange);
}
decodeTime += sampleDuration;
}
- mMaxRoundingError += aMdhd.ToMicroseconds(sampleCount);
+ Microseconds roundTime;
+ MOZ_TRY_VAR(roundTime, aMdhd.ToMicroseconds(sampleCount));
+ mMaxRoundingError += roundTime;
*aDecodeTime = decodeTime;
return Ok();
}
Tkhd::Tkhd(Box& aBox)
{
--- a/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
@@ -28,18 +28,22 @@ public:
: mCreationTime(0)
, mModificationTime(0)
, mTimescale(0)
, mDuration(0)
{
}
explicit Mvhd(Box& aBox);
- Microseconds ToMicroseconds(int64_t aTimescaleUnits)
+ Result<Microseconds, nsresult> ToMicroseconds(int64_t aTimescaleUnits)
{
+ if (!mTimescale) {
+ NS_WARNING("invalid mTimescale");
+ return Err(NS_ERROR_FAILURE);
+ }
int64_t major = aTimescaleUnits / mTimescale;
int64_t remainder = aTimescaleUnits % mTimescale;
return major * 1000000ll + remainder * 1000000ll / mTimescale;
}
uint64_t mCreationTime;
uint64_t mModificationTime;
uint32_t mTimescale;