diff --git a/RELEASENOTES.md b/RELEASENOTES.md index f7c1ec23ba..b3c62c447b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -22,6 +22,9 @@ ([#5139](https://github.com/google/ExoPlayer/issues/5139)). * Fix issue where null `Metadata` was output when it failed to decode ([#5149](https://github.com/google/ExoPlayer/issues/5149)). +* Fix playback of some invalid but playable MP4 streams by replacing assertions + with logged warnings in sample table parsing code + ([#5162](https://github.com/google/ExoPlayer/issues/5162)). ### 2.9.1 ### diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java index e3d56489a6..d085156f2b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java @@ -236,8 +236,6 @@ import java.util.List; sizes = Arrays.copyOf(sizes, sampleCount); timestamps = Arrays.copyOf(timestamps, sampleCount); flags = Arrays.copyOf(flags, sampleCount); - remainingSamplesAtTimestampOffset = 0; - remainingTimestampOffsetChanges = 0; break; } @@ -293,23 +291,38 @@ import java.util.List; } duration = timestampTimeUnits + timestampOffset; - Assertions.checkArgument(remainingSamplesAtTimestampOffset == 0); - // Remove trailing ctts entries with 0-valued sample counts. + // If the stbl's child boxes are not consistent the container is malformed, but the stream may + // still be playable. + boolean isCttsValid = true; while (remainingTimestampOffsetChanges > 0) { - Assertions.checkArgument(ctts.readUnsignedIntToInt() == 0); + if (ctts.readUnsignedIntToInt() != 0) { + isCttsValid = false; + break; + } ctts.readInt(); // Ignore offset. remainingTimestampOffsetChanges--; } - - // If the stbl's child boxes are not consistent the container is malformed, but the stream may - // still be playable. - if (remainingSynchronizationSamples != 0 || remainingSamplesAtTimestampDelta != 0 - || remainingSamplesInChunk != 0 || remainingTimestampDeltaChanges != 0) { - Log.w(TAG, "Inconsistent stbl box for track " + track.id - + ": remainingSynchronizationSamples " + remainingSynchronizationSamples - + ", remainingSamplesAtTimestampDelta " + remainingSamplesAtTimestampDelta - + ", remainingSamplesInChunk " + remainingSamplesInChunk - + ", remainingTimestampDeltaChanges " + remainingTimestampDeltaChanges); + if (remainingSynchronizationSamples != 0 + || remainingSamplesAtTimestampDelta != 0 + || remainingSamplesInChunk != 0 + || remainingTimestampDeltaChanges != 0 + || remainingSamplesAtTimestampOffset != 0 + || !isCttsValid) { + Log.w( + TAG, + "Inconsistent stbl box for track " + + track.id + + ": remainingSynchronizationSamples " + + remainingSynchronizationSamples + + ", remainingSamplesAtTimestampDelta " + + remainingSamplesAtTimestampDelta + + ", remainingSamplesInChunk " + + remainingSamplesInChunk + + ", remainingTimestampDeltaChanges " + + remainingTimestampDeltaChanges + + ", remainingSamplesAtTimestampOffset " + + remainingSamplesAtTimestampOffset + + (!isCttsValid ? ", ctts invalid" : "")); } } else { long[] chunkOffsetsBytes = new long[chunkIterator.length];