diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5839a0f7e4..de4e600978 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -51,6 +51,12 @@ * Allow `Mp4Extractor` and `FragmentedMp4Extractor` to identify H264 samples that are not used as reference by subsequent samples. * Add option to enable index-based seeking in `AmrExtractor`. + * Treat MP3 files with more than 128kB between valid frames as truncated + (instead of invalid). This means files with non-MP3 data at the end, + with no other metadata to indicate the length of the MP3 bytes, now stop + playback at the end of the MP3 data instead of failing with + `ParserException: Searched too many bytes.{contentIsMalformed=true, + dataType=1}` ([#1563](https://github.com/androidx/media/issues/1563)). * DataSource: * Update `HttpEngineDataSource` to allow use starting at version S extension 7 instead of API level 34 diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/ConstantBitrateSeeker.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/ConstantBitrateSeeker.java index 12f5761d99..6b4ceb5101 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/ConstantBitrateSeeker.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/ConstantBitrateSeeker.java @@ -24,7 +24,10 @@ import androidx.media3.extractor.MpegAudioUtil; */ /* package */ final class ConstantBitrateSeeker extends ConstantBitrateSeekMap implements Seeker { + private final long firstFramePosition; private final int bitrate; + private final int frameSize; + private final boolean allowSeeksIfLengthUnknown; private final long dataEndPosition; /** @@ -60,7 +63,10 @@ import androidx.media3.extractor.MpegAudioUtil; int frameSize, boolean allowSeeksIfLengthUnknown) { super(inputLength, firstFramePosition, bitrate, frameSize, allowSeeksIfLengthUnknown); + this.firstFramePosition = firstFramePosition; this.bitrate = bitrate; + this.frameSize = frameSize; + this.allowSeeksIfLengthUnknown = allowSeeksIfLengthUnknown; dataEndPosition = inputLength != C.LENGTH_UNSET ? inputLength : C.INDEX_UNSET; } @@ -78,4 +84,13 @@ import androidx.media3.extractor.MpegAudioUtil; public int getAverageBitrate() { return bitrate; } + + public ConstantBitrateSeeker copyWithNewDataEndPosition(long dataEndPosition) { + return new ConstantBitrateSeeker( + /* inputLength= */ dataEndPosition, + firstFramePosition, + bitrate, + frameSize, + allowSeeksIfLengthUnknown); + } } diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java index c64d26c648..0ae9c614d3 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/Mp3Extractor.java @@ -15,6 +15,7 @@ */ package androidx.media3.extractor.mp3; +import static androidx.media3.common.util.Assertions.checkNotNull; import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -23,7 +24,6 @@ import androidx.annotation.Nullable; import androidx.media3.common.C; import androidx.media3.common.Format; import androidx.media3.common.Metadata; -import androidx.media3.common.ParserException; import androidx.media3.common.PlaybackException; import androidx.media3.common.Player; import androidx.media3.common.util.Assertions; @@ -177,6 +177,7 @@ public final class Mp3Extractor implements Extractor { private long basisTimeUs; private long samplesRead; private long firstSamplePosition; + private long endPositionOfLastSampleRead; private int sampleBytesRemaining; private @MonotonicNonNull Seeker seeker; @@ -213,6 +214,7 @@ public final class Mp3Extractor implements Extractor { id3Peeker = new Id3Peeker(); skippingTrackOutput = new DiscardingTrackOutput(); currentTrackOutput = skippingTrackOutput; + endPositionOfLastSampleRead = C.INDEX_UNSET; } // Extractor implementation. @@ -335,13 +337,14 @@ public final class Mp3Extractor implements Extractor { } } sampleBytesRemaining = synchronizedHeader.frameSize; + endPositionOfLastSampleRead = extractorInput.getPosition() + synchronizedHeader.frameSize; if (seeker instanceof IndexSeeker) { IndexSeeker indexSeeker = (IndexSeeker) seeker; // Add seek point corresponding to the next frame instead of the current one to be able to // start writing to the realTrackOutput on time when a seek is in progress. indexSeeker.maybeAddSeekPoint( computeTimeUs(samplesRead + synchronizedHeader.samplesPerFrame), - extractorInput.getPosition() + synchronizedHeader.frameSize); + endPositionOfLastSampleRead); if (isSeekInProgress && indexSeeker.isTimeUsInIndex(seekTimeUs)) { isSeekInProgress = false; currentTrackOutput = realTrackOutput; @@ -395,6 +398,7 @@ public final class Mp3Extractor implements Extractor { // We reached the end of the stream but found at least one valid frame. break; } + maybeUpdateCbrDurationToLastSample(); throw new EOFException(); } scratch.setPosition(0); @@ -406,8 +410,8 @@ public final class Mp3Extractor implements Extractor { // The header doesn't match the candidate header or is invalid. Try the next byte offset. if (searchedBytes++ == searchLimitBytes) { if (!sniffing) { - throw ParserException.createForMalformedContainer( - "Searched too many bytes.", /* cause= */ null); + maybeUpdateCbrDurationToLastSample(); + throw new EOFException(); } return false; } @@ -636,6 +640,22 @@ public final class Mp3Extractor implements Extractor { /* allowSeeksIfLengthUnknown= */ false); } + /** + * If {@link #seeker} is a seekable {@link ConstantBitrateSeeker}, this updates it to end at the + * last sample we read (because we've failed to find a subsequent synchronization word so we + * assume the MP3 data has ended). + */ + private void maybeUpdateCbrDurationToLastSample() { + if (seeker instanceof ConstantBitrateSeeker + && seeker.isSeekable() + && endPositionOfLastSampleRead != C.INDEX_UNSET + && endPositionOfLastSampleRead != seeker.getDataEndPosition()) { + seeker = + ((ConstantBitrateSeeker) seeker).copyWithNewDataEndPosition(endPositionOfLastSampleRead); + checkNotNull(extractorOutput).seekMap(seeker); + } + } + @EnsuresNonNull({"extractorOutput", "realTrackOutput"}) private void assertInitialized() { Assertions.checkStateNotNull(realTrackOutput); diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/mp3/Mp3ExtractorTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/mp3/Mp3ExtractorTest.java index d18d7e678d..a5c3a9df88 100644 --- a/libraries/extractor/src/test/java/androidx/media3/extractor/mp3/Mp3ExtractorTest.java +++ b/libraries/extractor/src/test/java/androidx/media3/extractor/mp3/Mp3ExtractorTest.java @@ -15,6 +15,8 @@ */ package androidx.media3.extractor.mp3; +import static org.junit.Assume.assumeFalse; + import androidx.media3.test.utils.ExtractorAsserts; import androidx.media3.test.utils.ExtractorAsserts.AssertionConfig; import com.google.common.collect.ImmutableList; @@ -96,6 +98,18 @@ public final class Mp3ExtractorTest { simulationConfig); } + // https://github.com/androidx/media/issues/1563 + @Test + public void mp3CbrSampleWithNoSeekTableAndTrailingGarbage() throws Exception { + assumeFalse( + "Skipping I/O error testing with unknown length due to b/362727473", + simulationConfig.simulateIOErrors && simulationConfig.simulateUnknownLength); + ExtractorAsserts.assertBehavior( + Mp3Extractor::new, + "media/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3", + simulationConfig); + } + @Test public void trimmedMp3Sample() throws Exception { ExtractorAsserts.assertBehavior( diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3.0.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3.0.dump new file mode 100644 index 0000000000..b8b7af77d0 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3.0.dump @@ -0,0 +1,450 @@ +seekMap: + isSeekable = true + duration = 2821187 + getPosition(0) = [[timeUs=0, position=240]] + getPosition(1) = [[timeUs=0, position=240], [timeUs=26062, position=657]] + getPosition(1410593) = [[timeUs=1407375, position=22758], [timeUs=1433437, position=23175]] + getPosition(2821187) = [[timeUs=2795125, position=44962]] +numberOfTracks = 1 +track 0: + total output bytes = 45139 + sample count = 108 + format 0: + averageBitrate = 128000 + sampleMimeType = audio/mpeg + maxInputSize = 4096 + channelCount = 2 + sampleRate = 44100 + sample 0: + time = 0 + flags = 1 + data = length 417, hash C4565176 + sample 1: + time = 26122 + flags = 1 + data = length 418, hash 70AEC448 + sample 2: + time = 52244 + flags = 1 + data = length 418, hash 835A8FB9 + sample 3: + time = 78367 + flags = 1 + data = length 418, hash 3A9672BF + sample 4: + time = 104489 + flags = 1 + data = length 418, hash 8DBE60F9 + sample 5: + time = 130612 + flags = 1 + data = length 418, hash 23D0867B + sample 6: + time = 156734 + flags = 1 + data = length 418, hash 7780AAB9 + sample 7: + time = 182857 + flags = 1 + data = length 418, hash 3F63B2D1 + sample 8: + time = 208979 + flags = 1 + data = length 418, hash 7A33CEBD + sample 9: + time = 235102 + flags = 1 + data = length 418, hash DF31D514 + sample 10: + time = 261224 + flags = 1 + data = length 418, hash 26FA2C86 + sample 11: + time = 287346 + flags = 1 + data = length 418, hash D9C7FB1 + sample 12: + time = 313469 + flags = 1 + data = length 418, hash B1C40DC8 + sample 13: + time = 339591 + flags = 1 + data = length 418, hash 1C953BEE + sample 14: + time = 365714 + flags = 1 + data = length 418, hash A6053C6 + sample 15: + time = 391836 + flags = 1 + data = length 418, hash 2D90325A + sample 16: + time = 417959 + flags = 1 + data = length 418, hash 11A84918 + sample 17: + time = 444081 + flags = 1 + data = length 418, hash 30F1A19A + sample 18: + time = 470204 + flags = 1 + data = length 418, hash 70EC67FF + sample 19: + time = 496326 + flags = 1 + data = length 418, hash 7BAF5828 + sample 20: + time = 522448 + flags = 1 + data = length 418, hash 8E43B85E + sample 21: + time = 548571 + flags = 1 + data = length 418, hash E9A5EE78 + sample 22: + time = 574693 + flags = 1 + data = length 418, hash F79931F8 + sample 23: + time = 600816 + flags = 1 + data = length 418, hash C0308B40 + sample 24: + time = 626938 + flags = 1 + data = length 418, hash 3D2E55B + sample 25: + time = 653061 + flags = 1 + data = length 417, hash D74A61AF + sample 26: + time = 679183 + flags = 1 + data = length 418, hash 96F104B1 + sample 27: + time = 705306 + flags = 1 + data = length 418, hash CE12216 + sample 28: + time = 731428 + flags = 1 + data = length 418, hash 899EA46D + sample 29: + time = 757551 + flags = 1 + data = length 418, hash 1208BBC5 + sample 30: + time = 783673 + flags = 1 + data = length 418, hash 49F22D4D + sample 31: + time = 809795 + flags = 1 + data = length 418, hash 56D959B0 + sample 32: + time = 835918 + flags = 1 + data = length 418, hash 5EC6FF8C + sample 33: + time = 862040 + flags = 1 + data = length 418, hash 380B6E00 + sample 34: + time = 888163 + flags = 1 + data = length 418, hash 19494E6B + sample 35: + time = 914285 + flags = 1 + data = length 418, hash C751B033 + sample 36: + time = 940408 + flags = 1 + data = length 418, hash 5F7C6DBA + sample 37: + time = 966530 + flags = 1 + data = length 418, hash D77E6530 + sample 38: + time = 992653 + flags = 1 + data = length 418, hash 48A694AB + sample 39: + time = 1018775 + flags = 1 + data = length 418, hash A979850E + sample 40: + time = 1044897 + flags = 1 + data = length 418, hash 7688E4B1 + sample 41: + time = 1071020 + flags = 1 + data = length 418, hash 255AF933 + sample 42: + time = 1097142 + flags = 1 + data = length 418, hash D58AC838 + sample 43: + time = 1123265 + flags = 1 + data = length 418, hash A38DC7B + sample 44: + time = 1149387 + flags = 1 + data = length 418, hash EA0CA21 + sample 45: + time = 1175510 + flags = 1 + data = length 418, hash DF99B54B + sample 46: + time = 1201632 + flags = 1 + data = length 418, hash A1532134 + sample 47: + time = 1227755 + flags = 1 + data = length 418, hash 520EC187 + sample 48: + time = 1253877 + flags = 1 + data = length 418, hash 5E38E4F + sample 49: + time = 1280000 + flags = 1 + data = length 417, hash 4D3526FB + sample 50: + time = 1306122 + flags = 1 + data = length 418, hash D99092CA + sample 51: + time = 1332244 + flags = 1 + data = length 418, hash EDB10D8E + sample 52: + time = 1358367 + flags = 1 + data = length 418, hash 5B5F6439 + sample 53: + time = 1384489 + flags = 1 + data = length 418, hash 947E2739 + sample 54: + time = 1410612 + flags = 1 + data = length 418, hash 8C1FF29C + sample 55: + time = 1436734 + flags = 1 + data = length 418, hash FEADC9C3 + sample 56: + time = 1462857 + flags = 1 + data = length 418, hash BB82E0C8 + sample 57: + time = 1488979 + flags = 1 + data = length 418, hash 8D1494AF + sample 58: + time = 1515102 + flags = 1 + data = length 418, hash E8C4265C + sample 59: + time = 1541224 + flags = 1 + data = length 418, hash BC8F59AE + sample 60: + time = 1567346 + flags = 1 + data = length 418, hash C8C5DCBD + sample 61: + time = 1593469 + flags = 1 + data = length 418, hash 43C3D85B + sample 62: + time = 1619591 + flags = 1 + data = length 418, hash 238C1AFE + sample 63: + time = 1645714 + flags = 1 + data = length 418, hash F6099191 + sample 64: + time = 1671836 + flags = 1 + data = length 418, hash D236BB0E + sample 65: + time = 1697959 + flags = 1 + data = length 418, hash 58B5B714 + sample 66: + time = 1724081 + flags = 1 + data = length 418, hash A9DDDD52 + sample 67: + time = 1750204 + flags = 1 + data = length 418, hash 85E7D11E + sample 68: + time = 1776326 + flags = 1 + data = length 418, hash 9E9D8FF4 + sample 69: + time = 1802448 + flags = 1 + data = length 418, hash 6FF9060D + sample 70: + time = 1828571 + flags = 1 + data = length 418, hash 4F1FC4F5 + sample 71: + time = 1854693 + flags = 1 + data = length 418, hash EF9885AA + sample 72: + time = 1880816 + flags = 1 + data = length 418, hash 7872C242 + sample 73: + time = 1906938 + flags = 1 + data = length 418, hash EB6FEAED + sample 74: + time = 1933061 + flags = 1 + data = length 417, hash B02D8CF0 + sample 75: + time = 1959183 + flags = 1 + data = length 418, hash EFB6C2DD + sample 76: + time = 1985306 + flags = 1 + data = length 418, hash B733E449 + sample 77: + time = 2011428 + flags = 1 + data = length 418, hash 617B155E + sample 78: + time = 2037551 + flags = 1 + data = length 418, hash AE626B2E + sample 79: + time = 2063673 + flags = 1 + data = length 418, hash F5E232C + sample 80: + time = 2089795 + flags = 1 + data = length 418, hash B5F4DC29 + sample 81: + time = 2115918 + flags = 1 + data = length 418, hash C791E3B5 + sample 82: + time = 2142040 + flags = 1 + data = length 418, hash F42A6BDB + sample 83: + time = 2168163 + flags = 1 + data = length 418, hash FDAEEFE6 + sample 84: + time = 2194285 + flags = 1 + data = length 418, hash 62AC2513 + sample 85: + time = 2220408 + flags = 1 + data = length 418, hash A4B46783 + sample 86: + time = 2246530 + flags = 1 + data = length 418, hash 9B7DFEFE + sample 87: + time = 2272653 + flags = 1 + data = length 418, hash 4010F89A + sample 88: + time = 2298775 + flags = 1 + data = length 418, hash 33467FC1 + sample 89: + time = 2324897 + flags = 1 + data = length 418, hash 1DFAE1E9 + sample 90: + time = 2351020 + flags = 1 + data = length 418, hash C208D375 + sample 91: + time = 2377142 + flags = 1 + data = length 418, hash CD430C30 + sample 92: + time = 2403265 + flags = 1 + data = length 418, hash 5A6F8065 + sample 93: + time = 2429387 + flags = 1 + data = length 418, hash 7177BD8B + sample 94: + time = 2455510 + flags = 1 + data = length 418, hash 51C1F29B + sample 95: + time = 2481632 + flags = 1 + data = length 418, hash 868A0084 + sample 96: + time = 2507755 + flags = 1 + data = length 418, hash 1E9C03E1 + sample 97: + time = 2533877 + flags = 1 + data = length 418, hash 10069B68 + sample 98: + time = 2560000 + flags = 1 + data = length 417, hash CC5B751D + sample 99: + time = 2586122 + flags = 1 + data = length 418, hash 837D650 + sample 100: + time = 2612244 + flags = 1 + data = length 418, hash 43B75632 + sample 101: + time = 2638367 + flags = 1 + data = length 418, hash 86E0652 + sample 102: + time = 2664489 + flags = 1 + data = length 418, hash 4DEC63E7 + sample 103: + time = 2690612 + flags = 1 + data = length 418, hash F094F330 + sample 104: + time = 2716734 + flags = 1 + data = length 418, hash 2C9CAA4 + sample 105: + time = 2742857 + flags = 1 + data = length 418, hash 1E903FFE + sample 106: + time = 2768979 + flags = 1 + data = length 418, hash F276CF72 + sample 107: + time = 2795102 + flags = 1 + data = length 418, hash 1C081463 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3.1.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3.1.dump new file mode 100644 index 0000000000..02a784b9e7 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3.1.dump @@ -0,0 +1,306 @@ +seekMap: + isSeekable = true + duration = 2821187 + getPosition(0) = [[timeUs=0, position=240]] + getPosition(1) = [[timeUs=0, position=240], [timeUs=26062, position=657]] + getPosition(1410593) = [[timeUs=1407375, position=22758], [timeUs=1433437, position=23175]] + getPosition(2821187) = [[timeUs=2795125, position=44962]] +numberOfTracks = 1 +track 0: + total output bytes = 30093 + sample count = 72 + format 0: + averageBitrate = 128000 + sampleMimeType = audio/mpeg + maxInputSize = 4096 + channelCount = 2 + sampleRate = 44100 + sample 0: + time = 940375 + flags = 1 + data = length 418, hash 5F7C6DBA + sample 1: + time = 966497 + flags = 1 + data = length 418, hash D77E6530 + sample 2: + time = 992619 + flags = 1 + data = length 418, hash 48A694AB + sample 3: + time = 1018742 + flags = 1 + data = length 418, hash A979850E + sample 4: + time = 1044864 + flags = 1 + data = length 418, hash 7688E4B1 + sample 5: + time = 1070987 + flags = 1 + data = length 418, hash 255AF933 + sample 6: + time = 1097109 + flags = 1 + data = length 418, hash D58AC838 + sample 7: + time = 1123232 + flags = 1 + data = length 418, hash A38DC7B + sample 8: + time = 1149354 + flags = 1 + data = length 418, hash EA0CA21 + sample 9: + time = 1175477 + flags = 1 + data = length 418, hash DF99B54B + sample 10: + time = 1201599 + flags = 1 + data = length 418, hash A1532134 + sample 11: + time = 1227721 + flags = 1 + data = length 418, hash 520EC187 + sample 12: + time = 1253844 + flags = 1 + data = length 418, hash 5E38E4F + sample 13: + time = 1279966 + flags = 1 + data = length 417, hash 4D3526FB + sample 14: + time = 1306089 + flags = 1 + data = length 418, hash D99092CA + sample 15: + time = 1332211 + flags = 1 + data = length 418, hash EDB10D8E + sample 16: + time = 1358334 + flags = 1 + data = length 418, hash 5B5F6439 + sample 17: + time = 1384456 + flags = 1 + data = length 418, hash 947E2739 + sample 18: + time = 1410579 + flags = 1 + data = length 418, hash 8C1FF29C + sample 19: + time = 1436701 + flags = 1 + data = length 418, hash FEADC9C3 + sample 20: + time = 1462823 + flags = 1 + data = length 418, hash BB82E0C8 + sample 21: + time = 1488946 + flags = 1 + data = length 418, hash 8D1494AF + sample 22: + time = 1515068 + flags = 1 + data = length 418, hash E8C4265C + sample 23: + time = 1541191 + flags = 1 + data = length 418, hash BC8F59AE + sample 24: + time = 1567313 + flags = 1 + data = length 418, hash C8C5DCBD + sample 25: + time = 1593436 + flags = 1 + data = length 418, hash 43C3D85B + sample 26: + time = 1619558 + flags = 1 + data = length 418, hash 238C1AFE + sample 27: + time = 1645681 + flags = 1 + data = length 418, hash F6099191 + sample 28: + time = 1671803 + flags = 1 + data = length 418, hash D236BB0E + sample 29: + time = 1697926 + flags = 1 + data = length 418, hash 58B5B714 + sample 30: + time = 1724048 + flags = 1 + data = length 418, hash A9DDDD52 + sample 31: + time = 1750170 + flags = 1 + data = length 418, hash 85E7D11E + sample 32: + time = 1776293 + flags = 1 + data = length 418, hash 9E9D8FF4 + sample 33: + time = 1802415 + flags = 1 + data = length 418, hash 6FF9060D + sample 34: + time = 1828538 + flags = 1 + data = length 418, hash 4F1FC4F5 + sample 35: + time = 1854660 + flags = 1 + data = length 418, hash EF9885AA + sample 36: + time = 1880783 + flags = 1 + data = length 418, hash 7872C242 + sample 37: + time = 1906905 + flags = 1 + data = length 418, hash EB6FEAED + sample 38: + time = 1933028 + flags = 1 + data = length 417, hash B02D8CF0 + sample 39: + time = 1959150 + flags = 1 + data = length 418, hash EFB6C2DD + sample 40: + time = 1985272 + flags = 1 + data = length 418, hash B733E449 + sample 41: + time = 2011395 + flags = 1 + data = length 418, hash 617B155E + sample 42: + time = 2037517 + flags = 1 + data = length 418, hash AE626B2E + sample 43: + time = 2063640 + flags = 1 + data = length 418, hash F5E232C + sample 44: + time = 2089762 + flags = 1 + data = length 418, hash B5F4DC29 + sample 45: + time = 2115885 + flags = 1 + data = length 418, hash C791E3B5 + sample 46: + time = 2142007 + flags = 1 + data = length 418, hash F42A6BDB + sample 47: + time = 2168130 + flags = 1 + data = length 418, hash FDAEEFE6 + sample 48: + time = 2194252 + flags = 1 + data = length 418, hash 62AC2513 + sample 49: + time = 2220375 + flags = 1 + data = length 418, hash A4B46783 + sample 50: + time = 2246497 + flags = 1 + data = length 418, hash 9B7DFEFE + sample 51: + time = 2272619 + flags = 1 + data = length 418, hash 4010F89A + sample 52: + time = 2298742 + flags = 1 + data = length 418, hash 33467FC1 + sample 53: + time = 2324864 + flags = 1 + data = length 418, hash 1DFAE1E9 + sample 54: + time = 2350987 + flags = 1 + data = length 418, hash C208D375 + sample 55: + time = 2377109 + flags = 1 + data = length 418, hash CD430C30 + sample 56: + time = 2403232 + flags = 1 + data = length 418, hash 5A6F8065 + sample 57: + time = 2429354 + flags = 1 + data = length 418, hash 7177BD8B + sample 58: + time = 2455477 + flags = 1 + data = length 418, hash 51C1F29B + sample 59: + time = 2481599 + flags = 1 + data = length 418, hash 868A0084 + sample 60: + time = 2507721 + flags = 1 + data = length 418, hash 1E9C03E1 + sample 61: + time = 2533844 + flags = 1 + data = length 418, hash 10069B68 + sample 62: + time = 2559966 + flags = 1 + data = length 417, hash CC5B751D + sample 63: + time = 2586089 + flags = 1 + data = length 418, hash 837D650 + sample 64: + time = 2612211 + flags = 1 + data = length 418, hash 43B75632 + sample 65: + time = 2638334 + flags = 1 + data = length 418, hash 86E0652 + sample 66: + time = 2664456 + flags = 1 + data = length 418, hash 4DEC63E7 + sample 67: + time = 2690579 + flags = 1 + data = length 418, hash F094F330 + sample 68: + time = 2716701 + flags = 1 + data = length 418, hash 2C9CAA4 + sample 69: + time = 2742823 + flags = 1 + data = length 418, hash 1E903FFE + sample 70: + time = 2768946 + flags = 1 + data = length 418, hash F276CF72 + sample 71: + time = 2795068 + flags = 1 + data = length 418, hash 1C081463 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3.2.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3.2.dump new file mode 100644 index 0000000000..297c862c80 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3.2.dump @@ -0,0 +1,162 @@ +seekMap: + isSeekable = true + duration = 2821187 + getPosition(0) = [[timeUs=0, position=240]] + getPosition(1) = [[timeUs=0, position=240], [timeUs=26062, position=657]] + getPosition(1410593) = [[timeUs=1407375, position=22758], [timeUs=1433437, position=23175]] + getPosition(2821187) = [[timeUs=2795125, position=44962]] +numberOfTracks = 1 +track 0: + total output bytes = 15046 + sample count = 36 + format 0: + averageBitrate = 128000 + sampleMimeType = audio/mpeg + maxInputSize = 4096 + channelCount = 2 + sampleRate = 44100 + sample 0: + time = 1880812 + flags = 1 + data = length 418, hash 7872C242 + sample 1: + time = 1906934 + flags = 1 + data = length 418, hash EB6FEAED + sample 2: + time = 1933056 + flags = 1 + data = length 417, hash B02D8CF0 + sample 3: + time = 1959179 + flags = 1 + data = length 418, hash EFB6C2DD + sample 4: + time = 1985301 + flags = 1 + data = length 418, hash B733E449 + sample 5: + time = 2011424 + flags = 1 + data = length 418, hash 617B155E + sample 6: + time = 2037546 + flags = 1 + data = length 418, hash AE626B2E + sample 7: + time = 2063669 + flags = 1 + data = length 418, hash F5E232C + sample 8: + time = 2089791 + flags = 1 + data = length 418, hash B5F4DC29 + sample 9: + time = 2115914 + flags = 1 + data = length 418, hash C791E3B5 + sample 10: + time = 2142036 + flags = 1 + data = length 418, hash F42A6BDB + sample 11: + time = 2168158 + flags = 1 + data = length 418, hash FDAEEFE6 + sample 12: + time = 2194281 + flags = 1 + data = length 418, hash 62AC2513 + sample 13: + time = 2220403 + flags = 1 + data = length 418, hash A4B46783 + sample 14: + time = 2246526 + flags = 1 + data = length 418, hash 9B7DFEFE + sample 15: + time = 2272648 + flags = 1 + data = length 418, hash 4010F89A + sample 16: + time = 2298771 + flags = 1 + data = length 418, hash 33467FC1 + sample 17: + time = 2324893 + flags = 1 + data = length 418, hash 1DFAE1E9 + sample 18: + time = 2351016 + flags = 1 + data = length 418, hash C208D375 + sample 19: + time = 2377138 + flags = 1 + data = length 418, hash CD430C30 + sample 20: + time = 2403260 + flags = 1 + data = length 418, hash 5A6F8065 + sample 21: + time = 2429383 + flags = 1 + data = length 418, hash 7177BD8B + sample 22: + time = 2455505 + flags = 1 + data = length 418, hash 51C1F29B + sample 23: + time = 2481628 + flags = 1 + data = length 418, hash 868A0084 + sample 24: + time = 2507750 + flags = 1 + data = length 418, hash 1E9C03E1 + sample 25: + time = 2533873 + flags = 1 + data = length 418, hash 10069B68 + sample 26: + time = 2559995 + flags = 1 + data = length 417, hash CC5B751D + sample 27: + time = 2586118 + flags = 1 + data = length 418, hash 837D650 + sample 28: + time = 2612240 + flags = 1 + data = length 418, hash 43B75632 + sample 29: + time = 2638363 + flags = 1 + data = length 418, hash 86E0652 + sample 30: + time = 2664485 + flags = 1 + data = length 418, hash 4DEC63E7 + sample 31: + time = 2690607 + flags = 1 + data = length 418, hash F094F330 + sample 32: + time = 2716730 + flags = 1 + data = length 418, hash 2C9CAA4 + sample 33: + time = 2742852 + flags = 1 + data = length 418, hash 1E903FFE + sample 34: + time = 2768975 + flags = 1 + data = length 418, hash F276CF72 + sample 35: + time = 2795097 + flags = 1 + data = length 418, hash 1C081463 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3.3.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3.3.dump new file mode 100644 index 0000000000..bf484c7ee3 --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3.3.dump @@ -0,0 +1,18 @@ +seekMap: + isSeekable = true + duration = 2821187 + getPosition(0) = [[timeUs=0, position=240]] + getPosition(1) = [[timeUs=0, position=240], [timeUs=26062, position=657]] + getPosition(1410593) = [[timeUs=1407375, position=22758], [timeUs=1433437, position=23175]] + getPosition(2821187) = [[timeUs=2795125, position=44962]] +numberOfTracks = 1 +track 0: + total output bytes = 0 + sample count = 0 + format 0: + averageBitrate = 128000 + sampleMimeType = audio/mpeg + maxInputSize = 4096 + channelCount = 2 + sampleRate = 44100 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/extractordumps/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3.unknown_length.dump new file mode 100644 index 0000000000..024e90989a --- /dev/null +++ b/libraries/test_data/src/test/assets/extractordumps/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3.unknown_length.dump @@ -0,0 +1,447 @@ +seekMap: + isSeekable = false + duration = UNSET TIME + getPosition(0) = [[timeUs=0, position=240]] +numberOfTracks = 1 +track 0: + total output bytes = 45139 + sample count = 108 + format 0: + averageBitrate = 128000 + sampleMimeType = audio/mpeg + maxInputSize = 4096 + channelCount = 2 + sampleRate = 44100 + sample 0: + time = 0 + flags = 1 + data = length 417, hash C4565176 + sample 1: + time = 26122 + flags = 1 + data = length 418, hash 70AEC448 + sample 2: + time = 52244 + flags = 1 + data = length 418, hash 835A8FB9 + sample 3: + time = 78367 + flags = 1 + data = length 418, hash 3A9672BF + sample 4: + time = 104489 + flags = 1 + data = length 418, hash 8DBE60F9 + sample 5: + time = 130612 + flags = 1 + data = length 418, hash 23D0867B + sample 6: + time = 156734 + flags = 1 + data = length 418, hash 7780AAB9 + sample 7: + time = 182857 + flags = 1 + data = length 418, hash 3F63B2D1 + sample 8: + time = 208979 + flags = 1 + data = length 418, hash 7A33CEBD + sample 9: + time = 235102 + flags = 1 + data = length 418, hash DF31D514 + sample 10: + time = 261224 + flags = 1 + data = length 418, hash 26FA2C86 + sample 11: + time = 287346 + flags = 1 + data = length 418, hash D9C7FB1 + sample 12: + time = 313469 + flags = 1 + data = length 418, hash B1C40DC8 + sample 13: + time = 339591 + flags = 1 + data = length 418, hash 1C953BEE + sample 14: + time = 365714 + flags = 1 + data = length 418, hash A6053C6 + sample 15: + time = 391836 + flags = 1 + data = length 418, hash 2D90325A + sample 16: + time = 417959 + flags = 1 + data = length 418, hash 11A84918 + sample 17: + time = 444081 + flags = 1 + data = length 418, hash 30F1A19A + sample 18: + time = 470204 + flags = 1 + data = length 418, hash 70EC67FF + sample 19: + time = 496326 + flags = 1 + data = length 418, hash 7BAF5828 + sample 20: + time = 522448 + flags = 1 + data = length 418, hash 8E43B85E + sample 21: + time = 548571 + flags = 1 + data = length 418, hash E9A5EE78 + sample 22: + time = 574693 + flags = 1 + data = length 418, hash F79931F8 + sample 23: + time = 600816 + flags = 1 + data = length 418, hash C0308B40 + sample 24: + time = 626938 + flags = 1 + data = length 418, hash 3D2E55B + sample 25: + time = 653061 + flags = 1 + data = length 417, hash D74A61AF + sample 26: + time = 679183 + flags = 1 + data = length 418, hash 96F104B1 + sample 27: + time = 705306 + flags = 1 + data = length 418, hash CE12216 + sample 28: + time = 731428 + flags = 1 + data = length 418, hash 899EA46D + sample 29: + time = 757551 + flags = 1 + data = length 418, hash 1208BBC5 + sample 30: + time = 783673 + flags = 1 + data = length 418, hash 49F22D4D + sample 31: + time = 809795 + flags = 1 + data = length 418, hash 56D959B0 + sample 32: + time = 835918 + flags = 1 + data = length 418, hash 5EC6FF8C + sample 33: + time = 862040 + flags = 1 + data = length 418, hash 380B6E00 + sample 34: + time = 888163 + flags = 1 + data = length 418, hash 19494E6B + sample 35: + time = 914285 + flags = 1 + data = length 418, hash C751B033 + sample 36: + time = 940408 + flags = 1 + data = length 418, hash 5F7C6DBA + sample 37: + time = 966530 + flags = 1 + data = length 418, hash D77E6530 + sample 38: + time = 992653 + flags = 1 + data = length 418, hash 48A694AB + sample 39: + time = 1018775 + flags = 1 + data = length 418, hash A979850E + sample 40: + time = 1044897 + flags = 1 + data = length 418, hash 7688E4B1 + sample 41: + time = 1071020 + flags = 1 + data = length 418, hash 255AF933 + sample 42: + time = 1097142 + flags = 1 + data = length 418, hash D58AC838 + sample 43: + time = 1123265 + flags = 1 + data = length 418, hash A38DC7B + sample 44: + time = 1149387 + flags = 1 + data = length 418, hash EA0CA21 + sample 45: + time = 1175510 + flags = 1 + data = length 418, hash DF99B54B + sample 46: + time = 1201632 + flags = 1 + data = length 418, hash A1532134 + sample 47: + time = 1227755 + flags = 1 + data = length 418, hash 520EC187 + sample 48: + time = 1253877 + flags = 1 + data = length 418, hash 5E38E4F + sample 49: + time = 1280000 + flags = 1 + data = length 417, hash 4D3526FB + sample 50: + time = 1306122 + flags = 1 + data = length 418, hash D99092CA + sample 51: + time = 1332244 + flags = 1 + data = length 418, hash EDB10D8E + sample 52: + time = 1358367 + flags = 1 + data = length 418, hash 5B5F6439 + sample 53: + time = 1384489 + flags = 1 + data = length 418, hash 947E2739 + sample 54: + time = 1410612 + flags = 1 + data = length 418, hash 8C1FF29C + sample 55: + time = 1436734 + flags = 1 + data = length 418, hash FEADC9C3 + sample 56: + time = 1462857 + flags = 1 + data = length 418, hash BB82E0C8 + sample 57: + time = 1488979 + flags = 1 + data = length 418, hash 8D1494AF + sample 58: + time = 1515102 + flags = 1 + data = length 418, hash E8C4265C + sample 59: + time = 1541224 + flags = 1 + data = length 418, hash BC8F59AE + sample 60: + time = 1567346 + flags = 1 + data = length 418, hash C8C5DCBD + sample 61: + time = 1593469 + flags = 1 + data = length 418, hash 43C3D85B + sample 62: + time = 1619591 + flags = 1 + data = length 418, hash 238C1AFE + sample 63: + time = 1645714 + flags = 1 + data = length 418, hash F6099191 + sample 64: + time = 1671836 + flags = 1 + data = length 418, hash D236BB0E + sample 65: + time = 1697959 + flags = 1 + data = length 418, hash 58B5B714 + sample 66: + time = 1724081 + flags = 1 + data = length 418, hash A9DDDD52 + sample 67: + time = 1750204 + flags = 1 + data = length 418, hash 85E7D11E + sample 68: + time = 1776326 + flags = 1 + data = length 418, hash 9E9D8FF4 + sample 69: + time = 1802448 + flags = 1 + data = length 418, hash 6FF9060D + sample 70: + time = 1828571 + flags = 1 + data = length 418, hash 4F1FC4F5 + sample 71: + time = 1854693 + flags = 1 + data = length 418, hash EF9885AA + sample 72: + time = 1880816 + flags = 1 + data = length 418, hash 7872C242 + sample 73: + time = 1906938 + flags = 1 + data = length 418, hash EB6FEAED + sample 74: + time = 1933061 + flags = 1 + data = length 417, hash B02D8CF0 + sample 75: + time = 1959183 + flags = 1 + data = length 418, hash EFB6C2DD + sample 76: + time = 1985306 + flags = 1 + data = length 418, hash B733E449 + sample 77: + time = 2011428 + flags = 1 + data = length 418, hash 617B155E + sample 78: + time = 2037551 + flags = 1 + data = length 418, hash AE626B2E + sample 79: + time = 2063673 + flags = 1 + data = length 418, hash F5E232C + sample 80: + time = 2089795 + flags = 1 + data = length 418, hash B5F4DC29 + sample 81: + time = 2115918 + flags = 1 + data = length 418, hash C791E3B5 + sample 82: + time = 2142040 + flags = 1 + data = length 418, hash F42A6BDB + sample 83: + time = 2168163 + flags = 1 + data = length 418, hash FDAEEFE6 + sample 84: + time = 2194285 + flags = 1 + data = length 418, hash 62AC2513 + sample 85: + time = 2220408 + flags = 1 + data = length 418, hash A4B46783 + sample 86: + time = 2246530 + flags = 1 + data = length 418, hash 9B7DFEFE + sample 87: + time = 2272653 + flags = 1 + data = length 418, hash 4010F89A + sample 88: + time = 2298775 + flags = 1 + data = length 418, hash 33467FC1 + sample 89: + time = 2324897 + flags = 1 + data = length 418, hash 1DFAE1E9 + sample 90: + time = 2351020 + flags = 1 + data = length 418, hash C208D375 + sample 91: + time = 2377142 + flags = 1 + data = length 418, hash CD430C30 + sample 92: + time = 2403265 + flags = 1 + data = length 418, hash 5A6F8065 + sample 93: + time = 2429387 + flags = 1 + data = length 418, hash 7177BD8B + sample 94: + time = 2455510 + flags = 1 + data = length 418, hash 51C1F29B + sample 95: + time = 2481632 + flags = 1 + data = length 418, hash 868A0084 + sample 96: + time = 2507755 + flags = 1 + data = length 418, hash 1E9C03E1 + sample 97: + time = 2533877 + flags = 1 + data = length 418, hash 10069B68 + sample 98: + time = 2560000 + flags = 1 + data = length 417, hash CC5B751D + sample 99: + time = 2586122 + flags = 1 + data = length 418, hash 837D650 + sample 100: + time = 2612244 + flags = 1 + data = length 418, hash 43B75632 + sample 101: + time = 2638367 + flags = 1 + data = length 418, hash 86E0652 + sample 102: + time = 2664489 + flags = 1 + data = length 418, hash 4DEC63E7 + sample 103: + time = 2690612 + flags = 1 + data = length 418, hash F094F330 + sample 104: + time = 2716734 + flags = 1 + data = length 418, hash 2C9CAA4 + sample 105: + time = 2742857 + flags = 1 + data = length 418, hash 1E903FFE + sample 106: + time = 2768979 + flags = 1 + data = length 418, hash F276CF72 + sample 107: + time = 2795102 + flags = 1 + data = length 418, hash 1C081463 +tracksEnded = true diff --git a/libraries/test_data/src/test/assets/media/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3 b/libraries/test_data/src/test/assets/media/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3 new file mode 100644 index 0000000000..e09bf152f6 Binary files /dev/null and b/libraries/test_data/src/test/assets/media/mp3/bear-cbr-no-seek-table-trailing-garbage.mp3 differ