From 692ab33640e77aa376b9dda60734f12dcef5ab7e Mon Sep 17 00:00:00 2001 From: Googler Date: Tue, 23 Jul 2024 07:36:53 -0700 Subject: [PATCH] Add support for Audio Vorbis codec in Mp4Muxer. Update esdsBox to support muxing of files encoded with Vorbis audio codec . PiperOrigin-RevId: 655159074 (cherry picked from commit b77f1d0f99b3e287bc82883054b8ce54bab95fee) --- .../androidx/media3/common/MimeTypes.java | 23 + ...MuxerEndToEndParameterizedAndroidTest.java | 16 +- .../java/androidx/media3/muxer/Boxes.java | 74 ++- .../media3/muxer/FragmentedMp4Muxer.java | 22 +- .../java/androidx/media3/muxer/Mp4Muxer.java | 22 +- .../java/androidx/media3/muxer/BoxesTest.java | 21 + .../media/mp4/bbb_1ch_16kHz_q10_vorbis.ogg | Bin 0 -> 28300 bytes .../audio_sample_entry_box_vorbis.dump | 2 + .../bbb_1ch_16kHz_q10_vorbis.ogg.dump | 436 ++++++++++++++++++ 9 files changed, 590 insertions(+), 26 deletions(-) create mode 100644 libraries/test_data/src/test/assets/media/mp4/bbb_1ch_16kHz_q10_vorbis.ogg create mode 100644 libraries/test_data/src/test/assets/muxerdumps/audio_sample_entry_box_vorbis.dump create mode 100644 libraries/test_data/src/test/assets/muxerdumps/bbb_1ch_16kHz_q10_vorbis.ogg.dump diff --git a/libraries/common/src/main/java/androidx/media3/common/MimeTypes.java b/libraries/common/src/main/java/androidx/media3/common/MimeTypes.java index 9f11899885..9223c7e955 100644 --- a/libraries/common/src/main/java/androidx/media3/common/MimeTypes.java +++ b/libraries/common/src/main/java/androidx/media3/common/MimeTypes.java @@ -488,6 +488,29 @@ public final class MimeTypes { } } + /** + * Returns the MP4 object type identifier corresponding to a MIME type, as defined in RFC 6381 and + * MPEG-4 Object Types. + * + * @param sampleMimeType The MIME type of the track. + * @return The corresponding MP4 object type identifier, or {@code null} if it could not be + * determined. + */ + @UnstableApi + @Nullable + public static Byte getMp4ObjectTypeFromMimeType(String sampleMimeType) { + switch (sampleMimeType) { + case MimeTypes.AUDIO_AAC: + return (byte) 0x40; + case MimeTypes.AUDIO_VORBIS: + return (byte) 0xDD; + case MimeTypes.VIDEO_MP4V: + return (byte) 0x20; + default: + return null; + } + } + /** * Returns the MIME type corresponding to an MP4 object type identifier, as defined in RFC 6381 * and https://mp4ra.org/#/object_types. diff --git a/libraries/muxer/src/androidTest/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedAndroidTest.java b/libraries/muxer/src/androidTest/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedAndroidTest.java index 7741e9bb1b..ece0392d9c 100644 --- a/libraries/muxer/src/androidTest/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedAndroidTest.java +++ b/libraries/muxer/src/androidTest/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedAndroidTest.java @@ -43,7 +43,7 @@ import org.junit.runners.Parameterized.Parameters; /** End to end parameterized instrumentation tests for {@link Mp4Muxer}. */ @RunWith(Parameterized.class) public class Mp4MuxerEndToEndParameterizedAndroidTest { - private static final String H263_GPP = "bbb_176x144_128kbps_15fps_h263.3gp"; + private static final String H263_3GP = "bbb_176x144_128kbps_15fps_h263.3gp"; private static final String H264_MP4 = "sample_no_bframes.mp4"; private static final String H264_WITH_NON_REFERENCE_B_FRAMES_MP4 = "bbb_800x640_768kbps_30fps_avc_non_reference_3b.mp4"; @@ -52,25 +52,27 @@ public class Mp4MuxerEndToEndParameterizedAndroidTest { private static final String H265_HDR10_MP4 = "hdr10-720p.mp4"; private static final String H265_WITH_METADATA_TRACK_MP4 = "h265_with_metadata_track.mp4"; private static final String AV1_MP4 = "sample_av1.mp4"; - private static final String AMR_NB = "bbb_mono_8kHz_12.2kbps_amrnb.3gp"; - private static final String AMR_WB = "bbb_mono_16kHz_23.05kbps_amrwb.3gp"; + private static final String AMR_NB_3GP = "bbb_mono_8kHz_12.2kbps_amrnb.3gp"; + private static final String AMR_WB_3GP = "bbb_mono_16kHz_23.05kbps_amrwb.3gp"; private static final String MPEG4_MP4 = "bbb_176x144_192kbps_15fps_mpeg4.mp4"; private static final String OPUS_OGG = "bbb_6ch_8kHz_opus.ogg"; + private static final String VORBIS_OGG = "bbb_1ch_16kHz_q10_vorbis.ogg"; @Parameters(name = "{0}") public static ImmutableList mediaSamples() { return ImmutableList.of( - H263_GPP, + H263_3GP, H264_MP4, H264_WITH_NON_REFERENCE_B_FRAMES_MP4, H264_WITH_PYRAMID_B_FRAMES_MP4, H265_HDR10_MP4, H265_WITH_METADATA_TRACK_MP4, AV1_MP4, - AMR_NB, - AMR_WB, + AMR_NB_3GP, + AMR_WB_3GP, MPEG4_MP4, - OPUS_OGG); + OPUS_OGG, + VORBIS_OGG); } @Parameter public @MonotonicNonNull String inputFile; diff --git a/libraries/muxer/src/main/java/androidx/media3/muxer/Boxes.java b/libraries/muxer/src/main/java/androidx/media3/muxer/Boxes.java index 872972ef80..98df5231ea 100644 --- a/libraries/muxer/src/main/java/androidx/media3/muxer/Boxes.java +++ b/libraries/muxer/src/main/java/androidx/media3/muxer/Boxes.java @@ -543,22 +543,24 @@ import java.util.Locale; String mimeType = checkNotNull(format.sampleMimeType); switch (mimeType) { case MimeTypes.AUDIO_AAC: - case MimeTypes.VIDEO_MP4V: + case MimeTypes.AUDIO_VORBIS: return esdsBox(format); case MimeTypes.AUDIO_AMR_NB: return damrBox(/* mode= */ (short) 0x81FF); // mode set: all enabled for AMR-NB case MimeTypes.AUDIO_AMR_WB: return damrBox(/* mode= */ (short) 0x83FF); // mode set: all enabled for AMR-WB - case MimeTypes.VIDEO_H263: - return d263Box(); case MimeTypes.AUDIO_OPUS: return dOpsBox(format); + case MimeTypes.VIDEO_H263: + return d263Box(); case MimeTypes.VIDEO_H264: return avcCBox(format); case MimeTypes.VIDEO_H265: return hvcCBox(format); case MimeTypes.VIDEO_AV1: return av1CBox(format); + case MimeTypes.VIDEO_MP4V: + return esdsBox(format); default: throw new IllegalArgumentException("Unsupported format: " + mimeType); } @@ -1343,6 +1345,7 @@ import java.util.Locale; String mimeType = checkNotNull(format.sampleMimeType); switch (mimeType) { case MimeTypes.AUDIO_AAC: + case MimeTypes.AUDIO_VORBIS: return "mp4a"; case MimeTypes.AUDIO_AMR_NB: return "samr"; @@ -1372,32 +1375,40 @@ import java.util.Locale; byte[] csd0 = format.initializationData.get(0); checkArgument(csd0.length > 0, "csd-0 is empty."); - ByteBuffer csd0ByteBuffer = ByteBuffer.wrap(csd0); + String mimeType = checkNotNull(format.sampleMimeType); + boolean isVorbis = mimeType.equals(MimeTypes.AUDIO_VORBIS); + ByteBuffer csdByteBuffer = + isVorbis ? getVorbisInitializationData(format) : ByteBuffer.wrap(csd0); + int peakBitrate = format.peakBitrate; int averageBitrate = format.averageBitrate; - boolean isVideo = MimeTypes.isVideo(format.sampleMimeType); + boolean isVideo = MimeTypes.isVideo(mimeType); - int csd0Size = csd0ByteBuffer.limit(); - ByteBuffer dsiSizeBuffer = getSizeBuffer(csd0Size); - ByteBuffer dcdSizeBuffer = getSizeBuffer(csd0Size + dsiSizeBuffer.remaining() + 14); + int csdSize = csdByteBuffer.remaining(); + ByteBuffer dsiSizeBuffer = getSizeBuffer(csdSize); + ByteBuffer dcdSizeBuffer = getSizeBuffer(csdSize + dsiSizeBuffer.remaining() + 14); ByteBuffer esdSizeBuffer = - getSizeBuffer(csd0Size + dsiSizeBuffer.remaining() + dcdSizeBuffer.remaining() + 21); + getSizeBuffer(csdSize + dsiSizeBuffer.remaining() + dcdSizeBuffer.remaining() + 21); - ByteBuffer contents = ByteBuffer.allocate(csd0Size + MAX_FIXED_LEAF_BOX_SIZE); + ByteBuffer contents = ByteBuffer.allocate(csdSize + MAX_FIXED_LEAF_BOX_SIZE); contents.putInt(0x00); // Version and flags. contents.put((byte) 0x03); // ES_DescrTag contents.put(esdSizeBuffer); - contents.putShort((short) 0x0000); // First 16 bits of ES_ID. - contents.put(isVideo ? (byte) 0x1f : (byte) 0x00); // Last 8 bits of ES_ID. + contents.putShort((short) 0x0000); // ES_ID + // streamDependenceFlag (1 bit) + URL_Flag (1 bit) + OCRstreamFlag (1 bit) + streamPriority (5 + // bits) + contents.put(isVideo ? (byte) 0x1f : (byte) 0x00); contents.put((byte) 0x04); // DecoderConfigDescrTag contents.put(dcdSizeBuffer); - contents.put(isVideo ? (byte) 0x20 : (byte) 0x40); // objectTypeIndication - // streamType (6 bits) | upStream (1 bit) | reserved = 1 (1 bit) - contents.put((byte) ((isVideo ? (0x04 << 2) : (0x05 << 2)) | 0x01)); // streamType + Byte objectType = checkNotNull(MimeTypes.getMp4ObjectTypeFromMimeType(mimeType)); + contents.put(objectType); // objectTypeIndication + + // streamType (6 bits) + upStream (1 bit) + reserved = 1 (1 bit) + contents.put((byte) ((isVideo ? (0x04 << 2) : (0x05 << 2)) | 0x01)); int size = isVideo ? 0x017700 : 0x000300; contents.putShort((short) ((size >> 8) & 0xFFFF)); // First 16 bits of buffer size. @@ -1408,8 +1419,8 @@ import java.util.Locale; contents.put((byte) 0x05); // DecoderSpecificInfoTag contents.put(dsiSizeBuffer); - contents.put(csd0ByteBuffer); - csd0ByteBuffer.rewind(); + contents.put(csdByteBuffer); + csdByteBuffer.rewind(); contents.put((byte) 0x06); // SLConfigDescriptorTag contents.put((byte) 0x01); @@ -1436,6 +1447,35 @@ import java.util.Locale; return sizeBuffer; } + /* Returns csd wrapped in ByteBuffer in vorbis codec initialization data format. */ + private static ByteBuffer getVorbisInitializationData(Format format) { + checkArgument( + format.initializationData.size() > 1, "csd-1 should contain setup header for Vorbis."); + byte[] csd0 = format.initializationData.get(0); // identification Header + + // csd0Size is represented using "Xiph lacing" style. + // The lacing size is split into 255 values, stored as unsigned octets – for example, 500 is + // coded 255;245 or [0xFF 0xF5]. A frame with a size multiple of 255 is coded with a 0 at the + // end of the size – for example, 765 is coded 255;255;255;0 or [0xFF 0xFF 0xFF 0x00]. + byte[] csd0Size = new byte[csd0.length / 255 + 1]; + Arrays.fill(csd0Size, (byte) 0xFF); + csd0Size[csd0Size.length - 1] = (byte) (csd0.length % 255); + + byte[] csd1 = format.initializationData.get(1); // setUp Header + checkArgument(csd1.length > 0, "csd-1 should be present and contain setup header for Vorbis."); + + // Add 2 bytes - 1 for Vorbis audio and 1 for comment header length. + ByteBuffer csd = ByteBuffer.allocate(csd0Size.length + csd0.length + csd1.length + 2); + csd.put((byte) 0x02); // Vorbis audio + csd.put(csd0Size); // Size of identification header + csd.put((byte) 0); // Length of comment header + csd.put(csd0); + csd.put(csd1); + csd.flip(); + + return csd; + } + /** Returns the audio damr box. */ private static ByteBuffer damrBox(short mode) { diff --git a/libraries/muxer/src/main/java/androidx/media3/muxer/FragmentedMp4Muxer.java b/libraries/muxer/src/main/java/androidx/media3/muxer/FragmentedMp4Muxer.java index fc56869723..fb41bf52b1 100644 --- a/libraries/muxer/src/main/java/androidx/media3/muxer/FragmentedMp4Muxer.java +++ b/libraries/muxer/src/main/java/androidx/media3/muxer/FragmentedMp4Muxer.java @@ -35,7 +35,27 @@ import java.nio.ByteBuffer; /** * A muxer for creating a fragmented MP4 file. * - *

The muxer supports writing H263, H264, H265 and AV1 video, AAC and Opus audio, and metadata. + *

Muxer supports muxing of: + * + *

* *

All the operations are performed on the caller thread. * diff --git a/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Muxer.java b/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Muxer.java index cc656dc46d..7ea5ea30b9 100644 --- a/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Muxer.java +++ b/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Muxer.java @@ -42,7 +42,27 @@ import java.nio.ByteBuffer; /** * A muxer for creating an MP4 container file. * - *

The muxer supports writing H263, H264, H265 and AV1 video, AAC and Opus audio, and metadata. + *

Muxer supports muxing of: + * + *

* *

All the operations are performed on the caller thread. * diff --git a/libraries/muxer/src/test/java/androidx/media3/muxer/BoxesTest.java b/libraries/muxer/src/test/java/androidx/media3/muxer/BoxesTest.java index 05793d3ef2..478a97dfc2 100644 --- a/libraries/muxer/src/test/java/androidx/media3/muxer/BoxesTest.java +++ b/libraries/muxer/src/test/java/androidx/media3/muxer/BoxesTest.java @@ -321,6 +321,27 @@ public class BoxesTest { context, dumpableBox, getExpectedDumpFilePath("audio_sample_entry_box_opus")); } + @Test + public void createAudioSampleEntryBox_forVorbis_matchesExpected() throws Exception { + Format format = + FAKE_AUDIO_FORMAT + .buildUpon() + .setSampleMimeType(MimeTypes.AUDIO_VORBIS) + .setInitializationData( + ImmutableList.of( + BaseEncoding.base16() + .decode("01766F726269730000000001803E0000000000009886010000000000A901"), + BaseEncoding.base16() + .decode("05766F726269732442435601004000001842102A05AD638E3A01"))) + .build(); + + ByteBuffer audioSampleEntryBox = Boxes.audioSampleEntry(format); + + DumpableMp4Box dumpableBox = new DumpableMp4Box(audioSampleEntryBox); + DumpFileAsserts.assertOutput( + context, dumpableBox, getExpectedDumpFilePath("audio_sample_entry_box_vorbis")); + } + @Test public void createAudioSampleEntryBox_withUnknownAudioFormat_throws() { // The audio format contains an unknown MIME type. diff --git a/libraries/test_data/src/test/assets/media/mp4/bbb_1ch_16kHz_q10_vorbis.ogg b/libraries/test_data/src/test/assets/media/mp4/bbb_1ch_16kHz_q10_vorbis.ogg new file mode 100644 index 0000000000000000000000000000000000000000..4e664197a35bb19111caecb357b688a739b251dc GIT binary patch literal 28300 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 TQ@LuzOI@i_bpH0%F}b4wfmTGD literal 0 HcmV?d00001 diff --git a/libraries/test_data/src/test/assets/muxerdumps/audio_sample_entry_box_vorbis.dump b/libraries/test_data/src/test/assets/muxerdumps/audio_sample_entry_box_vorbis.dump new file mode 100644 index 0000000000..eb8d4272f9 --- /dev/null +++ b/libraries/test_data/src/test/assets/muxerdumps/audio_sample_entry_box_vorbis.dump @@ -0,0 +1,2 @@ +mp4a (132 bytes): + Data = length 124, hash 1414ED96 diff --git a/libraries/test_data/src/test/assets/muxerdumps/bbb_1ch_16kHz_q10_vorbis.ogg.dump b/libraries/test_data/src/test/assets/muxerdumps/bbb_1ch_16kHz_q10_vorbis.ogg.dump new file mode 100644 index 0000000000..ef1d41a16b --- /dev/null +++ b/libraries/test_data/src/test/assets/muxerdumps/bbb_1ch_16kHz_q10_vorbis.ogg.dump @@ -0,0 +1,436 @@ +seekMap: + isSeekable = true + duration = 2992000 + getPosition(0) = [[timeUs=0, position=400052]] + getPosition(1) = [[timeUs=1, position=400241]] + getPosition(1496000) = [[timeUs=1496000, position=412467]] + getPosition(2992000) = [[timeUs=2992000, position=424658]] +numberOfTracks = 1 +track 0: + total output bytes = 24785 + sample count = 103 + format 0: + averageBitrate = 99992 + id = 1 + sampleMimeType = audio/vorbis + maxInputSize = 295 + channelCount = 1 + sampleRate = 16000 + language = ``` + metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000] + initializationData: + data = length 30, hash C22462B1 + data = length 3539, hash F8106892 + sample 0: + time = 0 + flags = 1 + data = length 189, hash 52080AE0 + sample 1: + time = 0 + flags = 1 + data = length 179, hash 8C37301 + sample 2: + time = 16000 + flags = 1 + data = length 242, hash 1582B575 + sample 3: + time = 40000 + flags = 1 + data = length 255, hash 98244FA3 + sample 4: + time = 72000 + flags = 1 + data = length 240, hash 71BDFCD9 + sample 5: + time = 104000 + flags = 1 + data = length 253, hash EFD3DBFF + sample 6: + time = 136000 + flags = 1 + data = length 242, hash AACF8258 + sample 7: + time = 168000 + flags = 1 + data = length 245, hash 1CC8835E + sample 8: + time = 200000 + flags = 1 + data = length 250, hash FD19F7C0 + sample 9: + time = 232000 + flags = 1 + data = length 250, hash 8AF27182 + sample 10: + time = 264000 + flags = 1 + data = length 242, hash B82131C5 + sample 11: + time = 296000 + flags = 1 + data = length 249, hash 38239C5F + sample 12: + time = 328000 + flags = 1 + data = length 245, hash D2FB1E64 + sample 13: + time = 360000 + flags = 1 + data = length 246, hash C1FC7B6A + sample 14: + time = 392000 + flags = 1 + data = length 247, hash 2598BCEB + sample 15: + time = 424000 + flags = 1 + data = length 248, hash 56C3B18C + sample 16: + time = 456000 + flags = 1 + data = length 253, hash A93E963E + sample 17: + time = 488000 + flags = 1 + data = length 250, hash B06DDB1E + sample 18: + time = 520000 + flags = 1 + data = length 242, hash 26EBF2C6 + sample 19: + time = 552000 + flags = 1 + data = length 258, hash 35393C2 + sample 20: + time = 584000 + flags = 1 + data = length 253, hash C4C2692F + sample 21: + time = 616000 + flags = 1 + data = length 254, hash 4796C450 + sample 22: + time = 648000 + flags = 1 + data = length 245, hash DDECF577 + sample 23: + time = 680000 + flags = 1 + data = length 252, hash 5D243245 + sample 24: + time = 712000 + flags = 1 + data = length 189, hash AA61F7FC + sample 25: + time = 736000 + flags = 1 + data = length 184, hash 87D9A9A6 + sample 26: + time = 752000 + flags = 1 + data = length 187, hash C94C11BE + sample 27: + time = 768000 + flags = 1 + data = length 256, hash 36CB9380 + sample 28: + time = 792000 + flags = 1 + data = length 262, hash B729F6C9 + sample 29: + time = 824000 + flags = 1 + data = length 252, hash 1AF3D36B + sample 30: + time = 856000 + flags = 1 + data = length 260, hash 9C2CA006 + sample 31: + time = 888000 + flags = 1 + data = length 257, hash CDC89AFD + sample 32: + time = 920000 + flags = 1 + data = length 247, hash 425DFE94 + sample 33: + time = 952000 + flags = 1 + data = length 254, hash 97F2A00F + sample 34: + time = 984000 + flags = 1 + data = length 259, hash 5CFD2BD1 + sample 35: + time = 1016000 + flags = 1 + data = length 262, hash A1B3B3A6 + sample 36: + time = 1048000 + flags = 1 + data = length 258, hash A54300B3 + sample 37: + time = 1080000 + flags = 1 + data = length 242, hash 1CCE647C + sample 38: + time = 1112000 + flags = 1 + data = length 249, hash 6B917E41 + sample 39: + time = 1144000 + flags = 1 + data = length 246, hash 86324731 + sample 40: + time = 1176000 + flags = 1 + data = length 263, hash 4B98FCB4 + sample 41: + time = 1208000 + flags = 1 + data = length 247, hash 16B758D0 + sample 42: + time = 1240000 + flags = 1 + data = length 189, hash CDA345D1 + sample 43: + time = 1264000 + flags = 1 + data = length 183, hash 1538735F + sample 44: + time = 1280000 + flags = 1 + data = length 183, hash 47117509 + sample 45: + time = 1296000 + flags = 1 + data = length 188, hash 7E7B0A91 + sample 46: + time = 1312000 + flags = 1 + data = length 185, hash 5A283C8F + sample 47: + time = 1328000 + flags = 1 + data = length 254, hash 7A56B0F0 + sample 48: + time = 1352000 + flags = 1 + data = length 257, hash 4180CACF + sample 49: + time = 1384000 + flags = 1 + data = length 256, hash 392BF996 + sample 50: + time = 1416000 + flags = 1 + data = length 259, hash 36E26615 + sample 51: + time = 1448000 + flags = 1 + data = length 258, hash E7A523F0 + sample 52: + time = 1480000 + flags = 1 + data = length 254, hash BB991F97 + sample 53: + time = 1512000 + flags = 1 + data = length 264, hash EBD1FD4F + sample 54: + time = 1544000 + flags = 1 + data = length 256, hash EF1FA741 + sample 55: + time = 1576000 + flags = 1 + data = length 253, hash AA10B2A + sample 56: + time = 1608000 + flags = 1 + data = length 258, hash C995778 + sample 57: + time = 1640000 + flags = 1 + data = length 243, hash 37667B06 + sample 58: + time = 1672000 + flags = 1 + data = length 254, hash A1263AA0 + sample 59: + time = 1704000 + flags = 1 + data = length 194, hash E7EB2AFD + sample 60: + time = 1728000 + flags = 1 + data = length 192, hash 9405895B + sample 61: + time = 1744000 + flags = 1 + data = length 254, hash A0F66B2E + sample 62: + time = 1768000 + flags = 1 + data = length 249, hash 2B815793 + sample 63: + time = 1800000 + flags = 1 + data = length 254, hash 8A845D4F + sample 64: + time = 1832000 + flags = 1 + data = length 247, hash 32E3FF95 + sample 65: + time = 1864000 + flags = 1 + data = length 185, hash DCD1005B + sample 66: + time = 1888000 + flags = 1 + data = length 191, hash 9EF9175D + sample 67: + time = 1904000 + flags = 1 + data = length 251, hash 8B20EFE4 + sample 68: + time = 1928000 + flags = 1 + data = length 251, hash 2A349E41 + sample 69: + time = 1960000 + flags = 1 + data = length 254, hash C4977BE + sample 70: + time = 1992000 + flags = 1 + data = length 240, hash 230286DE + sample 71: + time = 2024000 + flags = 1 + data = length 259, hash 19565AB6 + sample 72: + time = 2056000 + flags = 1 + data = length 248, hash 1EE00686 + sample 73: + time = 2088000 + flags = 1 + data = length 245, hash C5DA60D6 + sample 74: + time = 2120000 + flags = 1 + data = length 243, hash B5DF7416 + sample 75: + time = 2152000 + flags = 1 + data = length 263, hash 43CEE6FD + sample 76: + time = 2184000 + flags = 1 + data = length 257, hash 4B30653E + sample 77: + time = 2216000 + flags = 1 + data = length 262, hash 2C3B847A + sample 78: + time = 2248000 + flags = 1 + data = length 246, hash A5398B6D + sample 79: + time = 2280000 + flags = 1 + data = length 252, hash 54031889 + sample 80: + time = 2312000 + flags = 1 + data = length 243, hash CD416D89 + sample 81: + time = 2344000 + flags = 1 + data = length 247, hash 37940B14 + sample 82: + time = 2376000 + flags = 1 + data = length 255, hash E5973397 + sample 83: + time = 2408000 + flags = 1 + data = length 250, hash EEF7942C + sample 84: + time = 2440000 + flags = 1 + data = length 255, hash D3E3D314 + sample 85: + time = 2472000 + flags = 1 + data = length 250, hash 5CC231E2 + sample 86: + time = 2504000 + flags = 1 + data = length 252, hash 55453FFB + sample 87: + time = 2536000 + flags = 1 + data = length 265, hash 6653F47 + sample 88: + time = 2568000 + flags = 1 + data = length 264, hash A8029392 + sample 89: + time = 2600000 + flags = 1 + data = length 262, hash A0016CDE + sample 90: + time = 2632000 + flags = 1 + data = length 257, hash 64872E6A + sample 91: + time = 2664000 + flags = 1 + data = length 245, hash 29A516B2 + sample 92: + time = 2696000 + flags = 1 + data = length 250, hash 3A9E8EC3 + sample 93: + time = 2728000 + flags = 1 + data = length 252, hash 78D64CE9 + sample 94: + time = 2760000 + flags = 1 + data = length 250, hash 4CAB463A + sample 95: + time = 2792000 + flags = 1 + data = length 249, hash A1079906 + sample 96: + time = 2824000 + flags = 1 + data = length 255, hash EEAA6634 + sample 97: + time = 2856000 + flags = 1 + data = length 256, hash BFD77057 + sample 98: + time = 2888000 + flags = 1 + data = length 249, hash 9ED80271 + sample 99: + time = 2920000 + flags = 1 + data = length 252, hash 2C3206C8 + sample 100: + time = 2952000 + flags = 1 + data = length 134, hash AA8D9693 + sample 101: + time = 2976000 + flags = 1 + data = length 180, hash 63217EFD + sample 102: + time = 2992000 + flags = 536870913 + data = length 179, hash 8529BBE7 +tracksEnded = true