From 9777945ce2ef84248738c24652aacb39a53b086a Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 15 Mar 2016 08:39:17 -0700 Subject: [PATCH] Fix the 0 sample count ctts entry bug When the ctts contained an entry that had a 0-valued entry count, the parser would miss every other entry, failing the final assertion. The standard does not seem to prevent the value 0 in the sample_count field, so we need to allow it. Issue: #1326 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=117241945 --- .../exoplayer/extractor/mp4/AtomParsers.java | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/library/src/main/java/com/google/android/exoplayer/extractor/mp4/AtomParsers.java b/library/src/main/java/com/google/android/exoplayer/extractor/mp4/AtomParsers.java index 97bd4f63c1..8081922708 100644 --- a/library/src/main/java/com/google/android/exoplayer/extractor/mp4/AtomParsers.java +++ b/library/src/main/java/com/google/android/exoplayer/extractor/mp4/AtomParsers.java @@ -152,14 +152,7 @@ import java.util.List; int timestampOffset = 0; if (ctts != null) { ctts.setPosition(Atom.FULL_HEADER_SIZE); - remainingTimestampOffsetChanges = ctts.readUnsignedIntToInt() - 1; - remainingSamplesAtTimestampOffset = ctts.readUnsignedIntToInt(); - // The BMFF spec (ISO 14496-12) states that sample offsets should be unsigned integers in - // version 0 ctts boxes, however some streams violate the spec and use signed integers - // instead. It's safe to always parse sample offsets as signed integers here, because - // unsigned integers will still be parsed correctly (unless their top bit is set, which - // is never true in practice because sample offsets are always small). - timestampOffset = ctts.readInt(); + remainingTimestampOffsetChanges = ctts.readUnsignedIntToInt(); } int nextSynchronizationSampleIndex = -1; @@ -180,6 +173,21 @@ import java.util.List; long timestampTimeUnits = 0; for (int i = 0; i < sampleCount; i++) { + // Add on the timestamp offset if ctts is present. + if (ctts != null) { + while (remainingSamplesAtTimestampOffset == 0 && remainingTimestampOffsetChanges > 0) { + remainingSamplesAtTimestampOffset = ctts.readUnsignedIntToInt(); + // The BMFF spec (ISO 14496-12) states that sample offsets should be unsigned integers in + // version 0 ctts boxes, however some streams violate the spec and use signed integers + // instead. It's safe to always parse sample offsets as signed integers here, because + // unsigned integers will still be parsed correctly (unless their top bit is set, which is + // never true in practice because sample offsets are always small). + timestampOffset = ctts.readInt(); + remainingTimestampOffsetChanges--; + } + remainingSamplesAtTimestampOffset--; + } + offsets[i] = offsetBytes; sizes[i] = fixedSampleSize == 0 ? stsz.readUnsignedIntToInt() : fixedSampleSize; if (sizes[i] > maximumSize) { @@ -206,17 +214,6 @@ import java.util.List; remainingTimestampDeltaChanges--; } - // Add on the timestamp offset if ctts is present. - if (ctts != null) { - remainingSamplesAtTimestampOffset--; - if (remainingSamplesAtTimestampOffset == 0 && remainingTimestampOffsetChanges > 0) { - remainingSamplesAtTimestampOffset = ctts.readUnsignedIntToInt(); - // Read a signed offset even for version 0 ctts boxes (see comment above). - timestampOffset = ctts.readInt(); - remainingTimestampOffsetChanges--; - } - } - // If we're at the last sample in this chunk, move to the next chunk. remainingSamplesInChunk--; if (remainingSamplesInChunk == 0) {