diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 3304423334..8f8dd5756c 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -17,6 +17,8 @@
(the CBR equivalent of the `Xing` header). Previously we used the seek
table from the `Info` header, but this results in less precise seeking
than if we ignore it and assume the file is CBR.
+ * MPEG2-TS: Add DTS, DTS-LBR and DTS:X Profile2 support
+ ([#275](https://github.com/androidx/media/pull/275)).
* Audio:
* Video:
* Text:
diff --git a/libraries/common/src/main/java/androidx/media3/common/util/Util.java b/libraries/common/src/main/java/androidx/media3/common/util/Util.java
index 561d878043..8ef7669962 100644
--- a/libraries/common/src/main/java/androidx/media3/common/util/Util.java
+++ b/libraries/common/src/main/java/androidx/media3/common/util/Util.java
@@ -94,6 +94,7 @@ import com.google.common.base.Ascii;
import com.google.common.base.Charsets;
import com.google.common.math.DoubleMath;
import com.google.common.math.LongMath;
+import com.google.common.primitives.UnsignedBytes;
import com.google.common.util.concurrent.AsyncFunction;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@@ -2825,6 +2826,50 @@ public final class Util {
return initialValue;
}
+ /**
+ * Returns the result of updating a CRC-16 with the specified bytes in a "most significant bit
+ * first" order.
+ *
+ * @param bytes Array containing the bytes to update the crc value with.
+ * @param start The start index (inclusive) of the byte range to update the crc with.
+ * @param end The end index (exclusive) of the byte range to update the crc with.
+ * @param initialValue The initial value for the crc calculation. The lower 16 bits of this 32-bit
+ * integer are used for the CRC computation.
+ * @return The result of updating the initial value with the specified bytes.
+ */
+ @UnstableApi
+ public static int crc16(byte[] bytes, int start, int end, int initialValue) {
+ for (int i = start; i < end; i++) {
+ int value = UnsignedBytes.toInt(bytes[i]);
+ // Process one message byte to update the current CRC-16 value.
+ initialValue = crc16UpdateFourBits(value >> 4, initialValue); // High nibble first.
+ initialValue = crc16UpdateFourBits(value & 0x0F, initialValue); // Low nibble.
+ }
+ return initialValue;
+ }
+
+ /**
+ * Process 4 bits of the message to update the CRC Value. Note that the data will be in the low
+ * nibble of value.
+ *
+ * @param value The 4-bit message data to be processed.
+ * @param crc16Register The current CRC-16 register to be updated. Only the lower 16 bits of this
+ * 32-bit integer are used for the CRC computation.
+ * @return The result of updating the CRC-16 register with the specified 4-bit message data.
+ */
+ private static int crc16UpdateFourBits(int value, int crc16Register) {
+ // Step one, extract the most significant 4 bits of the CRC register.
+ int mostSignificant4Bits = (crc16Register >> 12) & 0xFF;
+ // XOR in the Message Data into the extracted bits.
+ mostSignificant4Bits = (mostSignificant4Bits ^ value) & 0xFF;
+ // Shift the CRC register left 4 bits.
+ crc16Register = (crc16Register << 4) & 0xFFFF; // Handle as 16 bit, discard any sign extension.
+ // Do the table look-ups and XOR the result into the CRC tables.
+ crc16Register = (crc16Register ^ CRC16_BYTES_MSBF[mostSignificant4Bits]) & 0xFFFF;
+
+ return crc16Register;
+ }
+
/**
* Returns the result of updating a CRC-8 with the specified bytes in a "most significant bit
* first" order.
@@ -3810,6 +3855,16 @@ public final class Util {
0XBCB4666D, 0XB8757BDA, 0XB5365D03, 0XB1F740B4
};
+ /**
+ * Allows the CRC-16 calculation to be done byte by byte instead of bit per bit in the order "most
+ * significant bit first".
+ */
+ private static final int[] CRC16_BYTES_MSBF =
+ new int[] {
+ 0x0000, 0x01021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
+ 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF
+ };
+
/**
* Allows the CRC-8 calculation to be done byte by byte instead of bit per bit in the order "most
* significant bit first".
diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/DtsUtil.java b/libraries/extractor/src/main/java/androidx/media3/extractor/DtsUtil.java
index 9bda1c9f30..2c2b8cf0bd 100644
--- a/libraries/extractor/src/main/java/androidx/media3/extractor/DtsUtil.java
+++ b/libraries/extractor/src/main/java/androidx/media3/extractor/DtsUtil.java
@@ -15,19 +15,124 @@
*/
package androidx.media3.extractor;
+import static java.lang.annotation.ElementType.TYPE_USE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
+import androidx.annotation.StringDef;
+import androidx.media3.common.C;
import androidx.media3.common.DrmInitData;
import androidx.media3.common.Format;
import androidx.media3.common.MimeTypes;
+import androidx.media3.common.ParserException;
import androidx.media3.common.util.ParsableBitArray;
import androidx.media3.common.util.UnstableApi;
+import androidx.media3.common.util.Util;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
import java.nio.ByteBuffer;
import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicInteger;
/** Utility methods for parsing DTS frames. */
@UnstableApi
public final class DtsUtil {
+ /** Information parsed from a DTS frame header. */
+ public static final class DtsHeader {
+ /** The mime type of the DTS bitstream. */
+ public final @DtsAudioMimeType String mimeType;
+
+ /** The audio sampling rate in Hertz, or {@link C#RATE_UNSET_INT} if unknown. */
+ public final int sampleRate;
+
+ /** The number of channels, or {@link C#LENGTH_UNSET} if unknown. */
+ public final int channelCount;
+
+ /** The size of the DTS frame (compressed), in bytes. */
+ public final int frameSize;
+
+ /** The duration of the DTS frame in microseconds, or {@link C#TIME_UNSET} if unknown. */
+ public final long frameDurationUs;
+
+ /** The bitrate of compressed stream. */
+ public final int bitrate;
+
+ private DtsHeader(
+ String mimeType,
+ int channelCount,
+ int sampleRate,
+ int frameSize,
+ long frameDurationUs,
+ int bitrate) {
+ this.mimeType = mimeType;
+ this.channelCount = channelCount;
+ this.sampleRate = sampleRate;
+ this.frameSize = frameSize;
+ this.frameDurationUs = frameDurationUs;
+ this.bitrate = bitrate;
+ }
+ }
+
+ /**
+ * The possible MIME types for DTS that can be used.
+ *
+ *
One of:
+ *
+ *
+ * - {@link MimeTypes#AUDIO_DTS}
+ *
- {@link MimeTypes#AUDIO_DTS_EXPRESS}
+ *
- {@link MimeTypes#AUDIO_DTS_X}
+ *
+ */
+ @Documented
+ @Retention(SOURCE)
+ @Target(TYPE_USE)
+ @StringDef({MimeTypes.AUDIO_DTS, MimeTypes.AUDIO_DTS_EXPRESS, MimeTypes.AUDIO_DTS_X})
+ public @interface DtsAudioMimeType {}
+
+ /**
+ * Frame types for a DTS stream.
+ *
+ * One of:
+ *
+ *
+ * - {@link #FRAME_TYPE_UNKNOWN}
+ *
- {@link #FRAME_TYPE_CORE}
+ *
- {@link #FRAME_TYPE_EXTENSION_SUBSTREAM}
+ *
- {@link #FRAME_TYPE_UHD_SYNC}
+ *
- {@link #FRAME_TYPE_UHD_NON_SYNC}
+ *
+ */
+ @Documented
+ @Retention(SOURCE)
+ @Target(TYPE_USE)
+ @IntDef({
+ FRAME_TYPE_UNKNOWN,
+ FRAME_TYPE_CORE,
+ FRAME_TYPE_EXTENSION_SUBSTREAM,
+ FRAME_TYPE_UHD_SYNC,
+ FRAME_TYPE_UHD_NON_SYNC
+ })
+ public @interface FrameType {}
+
+ /** Represents a DTS frame for which type is unknown. */
+ public static final int FRAME_TYPE_UNKNOWN = 0;
+
+ /** Represents a DTS core frame. */
+ public static final int FRAME_TYPE_CORE = 1;
+
+ /** Represents a DTS extension substream frame. */
+ public static final int FRAME_TYPE_EXTENSION_SUBSTREAM = 2;
+
+ /** Represents a DTS UHD sync frame. */
+ public static final int FRAME_TYPE_UHD_SYNC = 3;
+
+ /** Represents a DTS UHD non-sync frame. */
+ public static final int FRAME_TYPE_UHD_NON_SYNC = 4;
+
/**
* Maximum rate for a DTS audio stream, in bytes per second.
*
@@ -38,7 +143,11 @@ public final class DtsUtil {
/** Maximum rate for a DTS-HD audio stream, in bytes per second. */
public static final int DTS_HD_MAX_RATE_BYTES_PER_SECOND = 18000 * 1000 / 8;
+ /**
+ * DTS Core Syncword (in different Endianness). See ETSI TS 102 114 V1.6.1 (2019-08), Section 5.3.
+ */
private static final int SYNC_VALUE_BE = 0x7FFE8001;
+
private static final int SYNC_VALUE_14B_BE = 0x1FFFE800;
private static final int SYNC_VALUE_LE = 0xFE7F0180;
private static final int SYNC_VALUE_14B_LE = 0xFF1F00E8;
@@ -47,18 +156,34 @@ public final class DtsUtil {
* DTS Extension Substream Syncword (in different Endianness). See ETSI TS 102 114 (V1.6.1)
* Section 7.4.1.
*/
- private static final int SYNC_EXT_SUB_LE = 0x25205864;
+ private static final int SYNC_VALUE_EXTSS_BE = 0x64582025;
+
+ private static final int SYNC_VALUE_EXTSS_LE = 0x25205864;
/**
- * DTS FTOC Sync words (in different Endianness). See ETSI TS 103 491 (V1.2.1) Section 6.4.4.1.
+ * DTS UHD FTOC Sync words (in different Endianness). See ETSI TS 103 491 (V1.2.1) Section
+ * 6.4.4.1.
*/
- private static final int SYNC_FTOC_LE = 0xF21B4140;
+ private static final int SYNC_VALUE_UHD_FTOC_SYNC_BE = 0x40411BF2;
+
+ private static final int SYNC_VALUE_UHD_FTOC_SYNC_LE = 0xF21B4140;
+ private static final int SYNC_VALUE_UHD_FTOC_NONSYNC_BE = 0x71C442E8;
+ private static final int SYNC_VALUE_UHD_FTOC_NONSYNC_LE = 0xE842C471;
- private static final int SYNC_FTOC_NON_SYNC_LE = 0xE842C471;
private static final byte FIRST_BYTE_BE = (byte) (SYNC_VALUE_BE >>> 24);
private static final byte FIRST_BYTE_14B_BE = (byte) (SYNC_VALUE_14B_BE >>> 24);
private static final byte FIRST_BYTE_LE = (byte) (SYNC_VALUE_LE >>> 24);
private static final byte FIRST_BYTE_14B_LE = (byte) (SYNC_VALUE_14B_LE >>> 24);
+ private static final byte FIRST_BYTE_EXTSS_BE = (byte) (SYNC_VALUE_EXTSS_BE >>> 24);
+ private static final byte FIRST_BYTE_EXTSS_LE = (byte) (SYNC_VALUE_EXTSS_LE >>> 24);
+ private static final byte FIRST_BYTE_UHD_FTOC_SYNC_BE =
+ (byte) (SYNC_VALUE_UHD_FTOC_SYNC_BE >>> 24);
+ private static final byte FIRST_BYTE_UHD_FTOC_SYNC_LE =
+ (byte) (SYNC_VALUE_UHD_FTOC_SYNC_LE >>> 24);
+ private static final byte FIRST_BYTE_UHD_FTOC_NONSYNC_BE =
+ (byte) (SYNC_VALUE_UHD_FTOC_NONSYNC_BE >>> 24);
+ private static final byte FIRST_BYTE_UHD_FTOC_NONSYNC_LE =
+ (byte) (SYNC_VALUE_UHD_FTOC_NONSYNC_LE >>> 24);
/** Maps AMODE to the number of channels. See ETSI TS 102 114 table 5-4. */
private static final int[] CHANNELS_BY_AMODE =
@@ -79,24 +204,58 @@ public final class DtsUtil {
};
/**
- * Returns whether a given integer matches a DTS sync word. Synchronization and storage modes are
- * defined in ETSI TS 102 114 V1.1.1 (2002-08), Section 5.3.
- *
- * @param word An integer.
- * @return Whether a given integer matches a DTS sync word.
+ * Maps MaxSampleRate index to sampling frequency in Hz. See ETSI TS 102 114 V1.6.1 (2019-08)
+ * Table 7-9.
*/
- public static boolean isSyncWord(int word) {
- return word == SYNC_VALUE_BE
+ private static final int[] SAMPLE_RATE_BY_INDEX =
+ new int[] {
+ 8_000, 16_000, 32_000, 64_000, 128_000, 22_050, 44_100, 88_200, 176_400, 352_800, 12_000,
+ 24_000, 48_000, 96_000, 192_000, 384_000
+ };
+
+ /**
+ * Payload length table for DTS UHD FTOC messages. See ETSI TS 103 491 V1.2.1 (2019-05), Section
+ * 6.4.3.
+ */
+ private static final int[] UHD_FTOC_PAYLOAD_LENGTH_TABLE = new int[] {5, 8, 10, 12};
+
+ /** Metadata chunk size length table for DTS UHD. See ETSI TS 103 491 V1.2.1, Table 6-20. */
+ private static final int[] UHD_METADATA_CHUNK_SIZE_LENGTH_TABLE = new int[] {6, 9, 12, 15};
+
+ /** Audio chunk ID length table for DTS UHD. See ETSI TS 103 491 V1.2.1, Section 6.4.14.4. */
+ private static final int[] UHD_AUDIO_CHUNK_ID_LENGTH_TABLE = new int[] {2, 4, 6, 8};
+
+ /** Audio chunk size length table for DTS UHD. See ETSI TS 103 491 V1.2.1, Section 6.4.14.4. */
+ private static final int[] UHD_AUDIO_CHUNK_SIZE_LENGTH_TABLE = new int[] {9, 11, 13, 16};
+
+ /** Header size length table for DTS UHD. See ETSI TS 103 491 V1.2.1 (2019-05), Section 6.4.3. */
+ private static final int[] UHD_HEADER_SIZE_LENGTH_TABLE = new int[] {5, 8, 10, 12};
+
+ /**
+ * Returns the {@link FrameType} if {@code word} is a DTS sync word, otherwise {@link
+ * #FRAME_TYPE_UNKNOWN}.
+ */
+ public static @FrameType int getFrameType(int word) {
+ if (word == SYNC_VALUE_BE
|| word == SYNC_VALUE_LE
|| word == SYNC_VALUE_14B_BE
- || word == SYNC_VALUE_14B_LE;
+ || word == SYNC_VALUE_14B_LE) {
+ return FRAME_TYPE_CORE;
+ } else if (word == SYNC_VALUE_EXTSS_BE || word == SYNC_VALUE_EXTSS_LE) {
+ return FRAME_TYPE_EXTENSION_SUBSTREAM;
+ } else if (word == SYNC_VALUE_UHD_FTOC_SYNC_BE || word == SYNC_VALUE_UHD_FTOC_SYNC_LE) {
+ return FRAME_TYPE_UHD_SYNC;
+ } else if (word == SYNC_VALUE_UHD_FTOC_NONSYNC_BE || word == SYNC_VALUE_UHD_FTOC_NONSYNC_LE) {
+ return FRAME_TYPE_UHD_NON_SYNC;
+ }
+ return FRAME_TYPE_UNKNOWN;
}
/**
- * Returns the DTS format given {@code data} containing the DTS frame according to ETSI TS 102 114
- * subsections 5.3/5.4.
+ * Returns the DTS format given {@code data} containing the DTS Core frame according to ETSI TS
+ * 102 114 V1.6.1 (2019-08) subsections 5.3/5.4.
*
- * @param frame The DTS frame to parse.
+ * @param frame The DTS Core frame to parse.
* @param trackId The track identifier to set on the format.
* @param language The language to set on the format.
* @param drmInitData {@link DrmInitData} to be included in the format.
@@ -107,7 +266,7 @@ public final class DtsUtil {
@Nullable String trackId,
@Nullable String language,
@Nullable DrmInitData drmInitData) {
- ParsableBitArray frameBits = getNormalizedFrameHeader(frame);
+ ParsableBitArray frameBits = getNormalizedFrame(frame);
frameBits.skipBits(32 + 1 + 5 + 1 + 7 + 14); // SYNC, FTYPE, SHORT, CPF, NBLKS, FSIZE
int amode = frameBits.readBits(6);
int channelCount = CHANNELS_BY_AMODE[amode];
@@ -132,7 +291,7 @@ public final class DtsUtil {
}
/**
- * Returns the number of audio samples represented by the given DTS frame.
+ * Returns the number of audio samples represented by the given DTS Core frame.
*
* @param data The frame to parse.
* @return The number of audio samples represented by the frame.
@@ -164,11 +323,12 @@ public final class DtsUtil {
* @return The number of audio samples represented by the syncframe.
*/
public static int parseDtsAudioSampleCount(ByteBuffer buffer) {
- if ((buffer.getInt(0) == SYNC_FTOC_LE) || (buffer.getInt(0) == SYNC_FTOC_NON_SYNC_LE)) {
+ if ((buffer.getInt(0) == SYNC_VALUE_UHD_FTOC_SYNC_LE)
+ || (buffer.getInt(0) == SYNC_VALUE_UHD_FTOC_NONSYNC_LE)) {
// Check for DTS:X Profile 2 sync or non sync word and return 1024 if found. This is the only
// audio sample count that is used by DTS:X Streaming Encoder.
return 1024;
- } else if (buffer.getInt(0) == SYNC_EXT_SUB_LE) {
+ } else if (buffer.getInt(0) == SYNC_VALUE_EXTSS_LE) {
// Check for DTS Express sync word and return 4096 if found. This is the only audio sample
// count that is used by DTS Streaming Encoder.
return 4096;
@@ -195,7 +355,7 @@ public final class DtsUtil {
}
/**
- * Returns the size in bytes of the given DTS frame.
+ * Returns the size in bytes of the given DTS Core frame.
*
* @param data The frame to parse.
* @return The frame's size in bytes.
@@ -224,36 +384,369 @@ public final class DtsUtil {
return uses14BitPerWord ? fsize * 16 / 14 : fsize;
}
- private static ParsableBitArray getNormalizedFrameHeader(byte[] frameHeader) {
- if (frameHeader[0] == FIRST_BYTE_BE) {
- // The frame is already 16-bit mode, big endian.
- return new ParsableBitArray(frameHeader);
+ /**
+ * Parses the {@link DtsHeader} data from the extension substream header of a DTS-HD frame
+ * according to ETSI TS 102 114 V1.6.1 (2019-08), Section 7.5.2.
+ *
+ * @param header The DTS-HD extension substream header to parse.
+ * @return The {@link DtsHeader} data extracted from the header.
+ */
+ public static DtsHeader parseDtsHdHeader(byte[] header) throws ParserException {
+ ParsableBitArray headerBits = getNormalizedFrame(header);
+ headerBits.skipBits(32 + 8); // SYNCEXTSSH, UserDefinedBits
+
+ int extensionSubstreamIndex = headerBits.readBits(2); // nExtSSIndex
+ int headerSizeInBits; // nuBits4Header
+ int extensionSubstreamFrameSizeBits; // nuBits4ExSSFsize
+ if (!headerBits.readBit()) { // bHeaderSizeType
+ headerSizeInBits = 8;
+ extensionSubstreamFrameSizeBits = 16;
+ } else {
+ headerSizeInBits = 12;
+ extensionSubstreamFrameSizeBits = 20;
}
- // Data is not normalized, but we don't want to modify frameHeader.
- frameHeader = Arrays.copyOf(frameHeader, frameHeader.length);
- if (isLittleEndianFrameHeader(frameHeader)) {
- // Change endianness.
- for (int i = 0; i < frameHeader.length - 1; i += 2) {
- byte temp = frameHeader[i];
- frameHeader[i] = frameHeader[i + 1];
- frameHeader[i + 1] = temp;
+ headerBits.skipBits(headerSizeInBits); // nuExtSSHeaderSize
+ int extensionSubstreamFrameSize =
+ headerBits.readBits(extensionSubstreamFrameSizeBits) + 1; // nuExtSSFsize
+
+ int assetsCount; // nuNumAssets
+ int referenceClockCode; // nuRefClockCode
+ int extensionSubstreamFrameDurationCode; // nuExSSFrameDurationCode
+
+ boolean staticFieldsPresent = headerBits.readBit(); // bStaticFieldsPresent
+ if (staticFieldsPresent) {
+ referenceClockCode = headerBits.readBits(2);
+ extensionSubstreamFrameDurationCode = 512 * (headerBits.readBits(3) + 1);
+
+ if (headerBits.readBit()) { // bTimeStampFlag
+ headerBits.skipBits(32 + 4); // nuTimeStamp, nLSB
+ }
+
+ int audioPresentationsCount = headerBits.readBits(3) + 1; // nuNumAudioPresnt
+ assetsCount = headerBits.readBits(3) + 1;
+ if (audioPresentationsCount != 1 || assetsCount != 1) {
+ throw ParserException.createForUnsupportedContainerFeature(
+ /* message= */ "Multiple audio presentations or assets not supported");
+ }
+
+ // We've already asserted audioPresentationsCount = 1.
+ int activeExtensionSubstreamMask =
+ headerBits.readBits(extensionSubstreamIndex + 1); // nuActiveExSSMask
+
+ for (int i = 0; i < extensionSubstreamIndex + 1; i++) {
+ if (((activeExtensionSubstreamMask >> i) & 0x1) == 1) {
+ headerBits.skipBits(8); // nuActiveAssetMask
+ }
+ }
+
+ if (headerBits.readBit()) { // bMixMetadataEnbl
+ headerBits.skipBits(2); // nuMixMetadataAdjLevel
+ int mixerOutputMaskBits = (headerBits.readBits(2) + 1) << 2; // nuBits4MixOutMask
+ int mixerOutputConfigurationCount = headerBits.readBits(2) + 1; // nuNumMixOutConfigs
+ // Output Mixing Configuration Loop
+ for (int i = 0; i < mixerOutputConfigurationCount; i++) {
+ headerBits.skipBits(mixerOutputMaskBits); // nuMixOutChMask
+ }
+ }
+ } else {
+ // Assignments below are placeholders and will never be used as they are only relevant when
+ // staticFieldsPresent == true. Initialised here to keep the compiler happy.
+ referenceClockCode = C.INDEX_UNSET;
+ extensionSubstreamFrameDurationCode = 0;
+ }
+
+ // We've already asserted assetsCount = 1.
+ headerBits.skipBits(extensionSubstreamFrameSizeBits); // nuAssetFsize
+ int sampleRate = C.RATE_UNSET_INT;
+ int channelCount = C.LENGTH_UNSET; // nuTotalNumChs
+
+ // Asset descriptor, see ETSI TS 102 114 V1.6.1 (2019-08) Table 7-5.
+ headerBits.skipBits(9 + 3); // nuAssetDescriptFsize, nuAssetIndex
+ if (staticFieldsPresent) {
+ if (headerBits.readBit()) { // bAssetTypeDescrPresent
+ headerBits.skipBits(4); // nuAssetTypeDescriptor
+ }
+ if (headerBits.readBit()) { // bLanguageDescrPresent
+ headerBits.skipBits(24); // LanguageDescriptor
+ }
+ if (headerBits.readBit()) { // bInfoTextPresent
+ int infoTextByteSize = headerBits.readBits(10) + 1; // nuInfoTextByteSize
+ headerBits.skipBytes(infoTextByteSize); // InfoTextString
+ }
+ headerBits.skipBits(5); // nuBitResolution
+ sampleRate = SAMPLE_RATE_BY_INDEX[headerBits.readBits(4)]; // nuMaxSampleRate
+ channelCount = headerBits.readBits(8) + 1;
+ // Done reading necessary bits, ignoring the rest.
+ }
+
+ long frameDurationUs = C.TIME_UNSET;
+ if (staticFieldsPresent) {
+ int referenceClockFrequency;
+ // ETSI TS 102 114 V1.6.1 (2019-08) Table 7-3.
+ switch (referenceClockCode) {
+ case 0:
+ referenceClockFrequency = 32_000;
+ break;
+ case 1:
+ referenceClockFrequency = 44_100;
+ break;
+ case 2:
+ referenceClockFrequency = 48_000;
+ break;
+ default:
+ throw ParserException.createForMalformedContainer(
+ /* message= */ "Unsupported reference clock code in DTS HD header: "
+ + referenceClockCode,
+ /* cause= */ null);
+ }
+ frameDurationUs =
+ Util.scaleLargeTimestamp(
+ extensionSubstreamFrameDurationCode, C.MICROS_PER_SECOND, referenceClockFrequency);
+ }
+ return new DtsHeader(
+ MimeTypes.AUDIO_DTS_EXPRESS,
+ channelCount,
+ sampleRate,
+ extensionSubstreamFrameSize,
+ frameDurationUs,
+ /* bitrate= */ 0);
+ }
+
+ /**
+ * Returns the size of the extension substream header in a DTS-HD frame according to ETSI TS 102
+ * 114 V1.6.1 (2019-08), Section 7.5.2.
+ *
+ * @param headerPrefix A byte array containing at least the first 55 bits of a DTS-HD frame.
+ * @return Size of the DTS-HD frame header in bytes.
+ */
+ public static int parseDtsHdHeaderSize(byte[] headerPrefix) {
+ ParsableBitArray headerPrefixBits = getNormalizedFrame(headerPrefix);
+ headerPrefixBits.skipBits(32 + 8 + 2); // SYNCEXTSSH, UserDefinedBits, nExtSSIndex
+ // Unpack the num of bits to be used to read header size
+ int headerBits = headerPrefixBits.readBit() ? 12 : 8; // bHeaderSizeType
+ // Unpack the substream header size
+ return headerPrefixBits.readBits(headerBits) + 1; // nuExtSSHeaderSize
+ }
+
+ /**
+ * Parses the {@link DtsHeader} data from the headers of a DTS-UHD(Profile 2) frame according to
+ * ETSI TS 103 491 V1.2.1 (2019-05), Section 6.4.3.
+ *
+ * @param header The DTS-UHD header to parse.
+ * @param uhdAudioChunkId An {@link AtomicInteger} containing the last read UHD audio chunk ID
+ * from a synchronized frame, or zero if unset. This parameter is both an input and output
+ * parameter. In synchronized frames, the input value is not used; instead, the parameter is
+ * set to the current UHD audio chunk ID, which becomes the output value. For non-synchronized
+ * frames, it is used without any modification.
+ * @return The {@link DtsHeader} data extracted from the header.
+ */
+ public static DtsHeader parseDtsUhdHeader(byte[] header, AtomicInteger uhdAudioChunkId)
+ throws ParserException {
+ ParsableBitArray headerBits = getNormalizedFrame(header);
+ int syncWord = headerBits.readBits(32);
+ boolean syncFrameFlag = syncWord == SYNC_VALUE_UHD_FTOC_SYNC_BE;
+
+ int ftocPayloadInBytes =
+ parseUnsignedVarInt(
+ headerBits, UHD_FTOC_PAYLOAD_LENGTH_TABLE, /* extractAndAddFlag= */ true)
+ + 1;
+
+ // ETSI TS 103 491 V1.2.1, Section 6.4.5.
+ int sampleRate = C.RATE_UNSET_INT; // m_unAudioSamplRate
+ long frameDurationUs = C.TIME_UNSET;
+ if (syncFrameFlag) {
+ // ETSI TS 103 491 V1.2.1, Section 6.4.6.1.
+ if (!headerBits.readBit()) { // m_bFullChannelBasedMixFlag
+ throw ParserException.createForUnsupportedContainerFeature(
+ /* message= */ "Only supports full channel mask-based audio presentation");
+ }
+
+ // ETSI TS 103 491 V1.2.1, Section 6.4.6.2.
+ checkCrc(header, ftocPayloadInBytes);
+
+ int baseDurationIndex = headerBits.readBits(2);
+ int baseDuration; // m_unBaseDuration
+ // ETSI TS 103 491 V1.2.1 (2019-05) Table 6-13.
+ switch (baseDurationIndex) {
+ case 0:
+ baseDuration = 512;
+ break;
+ case 1:
+ baseDuration = 480;
+ break;
+ case 2:
+ baseDuration = 384;
+ break;
+ default:
+ throw ParserException.createForMalformedContainer(
+ /* message= */ "Unsupported base duration index in DTS UHD header: "
+ + baseDurationIndex,
+ /* cause= */ null);
+ }
+ int frameDurationInClockPeriods =
+ baseDuration * (headerBits.readBits(3) + 1); // m_unFrameDuration
+ int clockRateIndex = headerBits.readBits(2);
+ int clockRateHertz; // m_unClockRateInHz
+ switch (clockRateIndex) {
+ case 0:
+ clockRateHertz = 32_000;
+ break;
+ case 1:
+ clockRateHertz = 44_100;
+ break;
+ case 2:
+ clockRateHertz = 48_000;
+ break;
+ default:
+ throw ParserException.createForMalformedContainer(
+ /* message= */ "Unsupported clock rate index in DTS UHD header: " + clockRateIndex,
+ /* cause= */ null);
+ }
+ // Skip time stamp information if present, see section 5.2.3.2.
+ if (headerBits.readBit()) { // m_bParamPresent
+ // m_bUpdateFlag == true as m_bSyncFramePredefValueExists is set to false in the encoder.
+ headerBits.skipBits(32 + 4); // m_TimeStamp
+ }
+ int sampleRateMultiplier = (1 << headerBits.readBits(2));
+ sampleRate = clockRateHertz * sampleRateMultiplier;
+ frameDurationUs =
+ Util.scaleLargeTimestamp(
+ frameDurationInClockPeriods, C.MICROS_PER_SECOND, clockRateHertz);
+ }
+
+ // ETSI TS 103 491 V1.2.1, Table 6-20.
+ // m_bFullChannelBasedMixFlag == true as we throw unsupported container feature otherwise.
+ int chunkPayloadBytes = 0;
+ int numOfMetadataChunks = syncFrameFlag ? 1 : 0; // Metadata chunks
+ for (int i = 0; i < numOfMetadataChunks; i++) {
+ int metadataChunkSize =
+ parseUnsignedVarInt(
+ headerBits, UHD_METADATA_CHUNK_SIZE_LENGTH_TABLE, /* extractAndAddFlag= */ true);
+ chunkPayloadBytes += metadataChunkSize;
+ }
+
+ // See ETSI TS 103 491 V1.2.1, Section 6.4.14.4.
+ // m_bFullChannelBasedMixFlag == true as we throw unsupported container feature otherwise.
+ int numAudioChunks = 1;
+ for (int i = 0; i < numAudioChunks; i++) {
+ // If syncFrameFlag is true the audio chunk ID will be present.
+ if (syncFrameFlag) {
+ uhdAudioChunkId.set(
+ parseUnsignedVarInt(
+ headerBits, UHD_AUDIO_CHUNK_ID_LENGTH_TABLE, /* extractAndAddFlag= */ true));
+ }
+ int audioChunkSize =
+ uhdAudioChunkId.get() != 0
+ ? parseUnsignedVarInt(
+ headerBits, UHD_AUDIO_CHUNK_SIZE_LENGTH_TABLE, /* extractAndAddFlag= */ true)
+ : 0;
+ chunkPayloadBytes += audioChunkSize;
+ }
+
+ int frameSize = ftocPayloadInBytes + chunkPayloadBytes;
+ return new DtsHeader(
+ MimeTypes.AUDIO_DTS_X,
+ // To determine the actual number of channels from a bit stream, we need to read the
+ // metadata chunk bytes. If defining a constant channel count causes problems, we can
+ // consider adding additional parsing logic for UHD frames.
+ // For now, using the estimated number of channels for DTS UHD bitstreams as 2.
+ /* channelCount= */ 2,
+ sampleRate,
+ frameSize,
+ frameDurationUs,
+ /* bitrate= */ 0);
+ }
+
+ /**
+ * Returns the size of frame header in a DTS-UHD(Profile 2) frame according to ETSI TS 103 491
+ * V1.2.1 (2019-05), Section 6.4.3.
+ *
+ * @param headerPrefix A byte array containing at least the first 47 bits of a DTS-UHD frame.
+ * @return Size of the DTS-UHD frame header in bytes.
+ */
+ public static int parseDtsUhdHeaderSize(byte[] headerPrefix) {
+ ParsableBitArray headerPrefixBits = getNormalizedFrame(headerPrefix);
+ headerPrefixBits.skipBits(32); // SYNC
+ return parseUnsignedVarInt(
+ headerPrefixBits, UHD_HEADER_SIZE_LENGTH_TABLE, /* extractAndAddFlag= */ true)
+ + 1;
+ }
+
+ /**
+ * Check if calculated and extracted CRC-16 words match. See ETSI TS 103 491 V1.2.1, Table 6-8.
+ */
+ private static void checkCrc(byte[] frame, int sizeInBytes) throws ParserException {
+ int initialValue = 0xFFFF;
+ int extractedCrc =
+ (((frame[sizeInBytes - 2] << 8) & initialValue) | (frame[sizeInBytes - 1] & 0xFF));
+ int calculatedCrc = Util.crc16(frame, /* start= */ 0, /* end= */ sizeInBytes - 2, initialValue);
+ if (extractedCrc != calculatedCrc) {
+ throw ParserException.createForMalformedContainer(
+ /* message= */ "CRC check failed", /* cause= */ null);
+ }
+ }
+
+ /**
+ * Helper function for the DTS UHD header parsing. Used to extract a field of variable length. See
+ * ETSI TS 103 491 V1.2.1, Section 5.2.3.1.
+ */
+ private static int parseUnsignedVarInt(
+ ParsableBitArray frameBits, int[] lengths, boolean extractAndAddFlag) {
+ int index = 0;
+ for (int i = 0; i < 3; i++) {
+ if (frameBits.readBit()) {
+ index++;
+ } else {
+ break;
}
}
- ParsableBitArray frameBits = new ParsableBitArray(frameHeader);
- if (frameHeader[0] == (byte) (SYNC_VALUE_14B_BE >> 24)) {
+
+ int value = 0;
+ if (extractAndAddFlag) {
+ for (int i = 0; i < index; i++) {
+ value += (1 << lengths[i]);
+ }
+ }
+ return value + frameBits.readBits(lengths[index]);
+ }
+
+ private static ParsableBitArray getNormalizedFrame(byte[] frame) {
+ if (frame[0] == FIRST_BYTE_BE
+ || frame[0] == FIRST_BYTE_EXTSS_BE
+ || frame[0] == FIRST_BYTE_UHD_FTOC_SYNC_BE
+ || frame[0] == FIRST_BYTE_UHD_FTOC_NONSYNC_BE) {
+ // The frame is already 16-bit mode, big endian.
+ return new ParsableBitArray(frame);
+ }
+ // Data is not normalized, but we don't want to modify frame.
+ frame = Arrays.copyOf(frame, frame.length);
+ if (isLittleEndianFrameHeader(frame)) {
+ // Change endianness.
+ for (int i = 0; i < frame.length - 1; i += 2) {
+ byte temp = frame[i];
+ frame[i] = frame[i + 1];
+ frame[i + 1] = temp;
+ }
+ }
+ ParsableBitArray frameBits = new ParsableBitArray(frame);
+ if (frame[0] == (byte) (SYNC_VALUE_14B_BE >> 24)) {
// Discard the 2 most significant bits of each 16 bit word.
- ParsableBitArray scratchBits = new ParsableBitArray(frameHeader);
+ ParsableBitArray scratchBits = new ParsableBitArray(frame);
while (scratchBits.bitsLeft() >= 16) {
scratchBits.skipBits(2);
frameBits.putInt(scratchBits.readBits(14), 14);
}
}
- frameBits.reset(frameHeader);
+ frameBits.reset(frame);
return frameBits;
}
private static boolean isLittleEndianFrameHeader(byte[] frameHeader) {
- return frameHeader[0] == FIRST_BYTE_LE || frameHeader[0] == FIRST_BYTE_14B_LE;
+ return frameHeader[0] == FIRST_BYTE_LE
+ || frameHeader[0] == FIRST_BYTE_14B_LE
+ || frameHeader[0] == FIRST_BYTE_EXTSS_LE
+ || frameHeader[0] == FIRST_BYTE_UHD_FTOC_SYNC_LE
+ || frameHeader[0] == FIRST_BYTE_UHD_FTOC_NONSYNC_LE;
}
private DtsUtil() {}
diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/ts/DefaultTsPayloadReaderFactory.java b/libraries/extractor/src/main/java/androidx/media3/extractor/ts/DefaultTsPayloadReaderFactory.java
index b55157081e..73454eb07e 100644
--- a/libraries/extractor/src/main/java/androidx/media3/extractor/ts/DefaultTsPayloadReaderFactory.java
+++ b/libraries/extractor/src/main/java/androidx/media3/extractor/ts/DefaultTsPayloadReaderFactory.java
@@ -171,7 +171,10 @@ public final class DefaultTsPayloadReaderFactory implements TsPayloadReader.Fact
}
// Fall through.
case TsExtractor.TS_STREAM_TYPE_DTS:
- return new PesReader(new DtsReader(esInfo.language));
+ case TsExtractor.TS_STREAM_TYPE_DTS_HD:
+ return new PesReader(new DtsReader(esInfo.language, DtsReader.EXTSS_HEADER_SIZE_MAX));
+ case TsExtractor.TS_STREAM_TYPE_DTS_UHD:
+ return new PesReader(new DtsReader(esInfo.language, DtsReader.FTOC_MAX_HEADER_SIZE));
case TsExtractor.TS_STREAM_TYPE_H262:
case TsExtractor.TS_STREAM_TYPE_DC2_H262:
return new PesReader(new H262Reader(buildUserDataReader(esInfo)));
diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/ts/DtsReader.java b/libraries/extractor/src/main/java/androidx/media3/extractor/ts/DtsReader.java
index 7dd515ce66..9c2237fb93 100644
--- a/libraries/extractor/src/main/java/androidx/media3/extractor/ts/DtsReader.java
+++ b/libraries/extractor/src/main/java/androidx/media3/extractor/ts/DtsReader.java
@@ -16,32 +16,57 @@
package androidx.media3.extractor.ts;
import static androidx.media3.common.util.Assertions.checkState;
+import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static java.lang.Math.min;
import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.common.Format;
-import androidx.media3.common.util.Assertions;
+import androidx.media3.common.ParserException;
import androidx.media3.common.util.ParsableByteArray;
import androidx.media3.common.util.UnstableApi;
+import androidx.media3.common.util.Util;
import androidx.media3.extractor.DtsUtil;
import androidx.media3.extractor.ExtractorOutput;
import androidx.media3.extractor.TrackOutput;
import androidx.media3.extractor.ts.TsPayloadReader.TrackIdGenerator;
+import com.google.common.primitives.Ints;
+import java.util.concurrent.atomic.AtomicInteger;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
-/** Parses a continuous DTS byte stream and extracts individual samples. */
+/** Parses a continuous DTS or DTS UHD byte stream and extracts individual samples. */
@UnstableApi
public final class DtsReader implements ElementaryStreamReader {
private static final int STATE_FINDING_SYNC = 0;
- private static final int STATE_READING_HEADER = 1;
- private static final int STATE_READING_SAMPLE = 2;
+ private static final int STATE_READING_CORE_HEADER = 1;
+ private static final int STATE_FINDING_EXTSS_HEADER_SIZE = 2;
+ private static final int STATE_READING_EXTSS_HEADER = 3;
+ private static final int STATE_FINDING_UHD_HEADER_SIZE = 4;
+ private static final int STATE_READING_UHD_HEADER = 5;
+ private static final int STATE_READING_SAMPLE = 6;
- private static final int HEADER_SIZE = 18;
+ /** Size of core header, in bytes. */
+ private static final int CORE_HEADER_SIZE = 18;
+
+ /**
+ * Maximum possible size of extension sub-stream header, in bytes. See See ETSI TS 102 114 V1.6.1
+ * (2019-08) Section 7.5.2.
+ */
+ /* package */ static final int EXTSS_HEADER_SIZE_MAX = 4096;
+
+ /**
+ * Maximum size of DTS UHD(DTS:X) frame header, in bytes. See ETSI TS 103 491 V1.2.1 (2019-05)
+ * Section 6.4.4.3.
+ */
+ /* package */ static final int FTOC_MAX_HEADER_SIZE = 5408;
private final ParsableByteArray headerScratchBytes;
+
+ /** The chunk ID is read in synchronized frames and re-used in non-synchronized frames. */
+ private final AtomicInteger uhdAudioChunkId;
+
@Nullable private final String language;
private @MonotonicNonNull String formatId;
@@ -50,13 +75,16 @@ public final class DtsReader implements ElementaryStreamReader {
private int state;
private int bytesRead;
- // Used to find the header.
+ /** Used to find the header. */
private int syncBytes;
// Used when parsing the header.
private long sampleDurationUs;
private @MonotonicNonNull Format format;
private int sampleSize;
+ private @DtsUtil.FrameType int frameType;
+ private int extensionSubstreamHeaderSize;
+ private int uhdHeaderSize;
// Used when reading the samples.
private long timeUs;
@@ -65,11 +93,15 @@ public final class DtsReader implements ElementaryStreamReader {
* Constructs a new reader for DTS elementary streams.
*
* @param language Track language.
+ * @param maxHeaderSize Maximum size of the header in a frame.
*/
- public DtsReader(@Nullable String language) {
- headerScratchBytes = new ParsableByteArray(new byte[HEADER_SIZE]);
+ public DtsReader(@Nullable String language, int maxHeaderSize) {
+ headerScratchBytes = new ParsableByteArray(new byte[maxHeaderSize]);
state = STATE_FINDING_SYNC;
timeUs = C.TIME_UNSET;
+ uhdAudioChunkId = new AtomicInteger();
+ extensionSubstreamHeaderSize = C.LENGTH_UNSET;
+ uhdHeaderSize = C.LENGTH_UNSET;
this.language = language;
}
@@ -79,6 +111,7 @@ public final class DtsReader implements ElementaryStreamReader {
bytesRead = 0;
syncBytes = 0;
timeUs = C.TIME_UNSET;
+ uhdAudioChunkId.set(0);
}
@Override
@@ -94,20 +127,64 @@ public final class DtsReader implements ElementaryStreamReader {
}
@Override
- public void consume(ParsableByteArray data) {
- Assertions.checkStateNotNull(output); // Asserts that createTracks has been called.
+ public void consume(ParsableByteArray data) throws ParserException {
+ checkStateNotNull(output); // Asserts that createTracks has been called.
while (data.bytesLeft() > 0) {
switch (state) {
case STATE_FINDING_SYNC:
- if (skipToNextSync(data)) {
- state = STATE_READING_HEADER;
+ if (skipToNextSyncWord(data)) {
+ if (frameType == DtsUtil.FRAME_TYPE_UHD_SYNC
+ || frameType == DtsUtil.FRAME_TYPE_UHD_NON_SYNC) {
+ state = STATE_FINDING_UHD_HEADER_SIZE;
+ } else if (frameType == DtsUtil.FRAME_TYPE_CORE) {
+ state = STATE_READING_CORE_HEADER;
+ } else {
+ state = STATE_FINDING_EXTSS_HEADER_SIZE;
+ }
}
break;
- case STATE_READING_HEADER:
- if (continueRead(data, headerScratchBytes.getData(), HEADER_SIZE)) {
- parseHeader();
+ case STATE_READING_CORE_HEADER:
+ if (continueRead(data, headerScratchBytes.getData(), CORE_HEADER_SIZE)) {
+ parseCoreHeader();
headerScratchBytes.setPosition(0);
- output.sampleData(headerScratchBytes, HEADER_SIZE);
+ output.sampleData(headerScratchBytes, CORE_HEADER_SIZE);
+ state = STATE_READING_SAMPLE;
+ }
+ break;
+ case STATE_FINDING_EXTSS_HEADER_SIZE:
+ // Read enough bytes to parse the header size information.
+ if (continueRead(data, headerScratchBytes.getData(), /* targetLength= */ 7)) {
+ extensionSubstreamHeaderSize =
+ DtsUtil.parseDtsHdHeaderSize(headerScratchBytes.getData());
+ state = STATE_READING_EXTSS_HEADER;
+ }
+ break;
+ case STATE_READING_EXTSS_HEADER:
+ if (continueRead(data, headerScratchBytes.getData(), extensionSubstreamHeaderSize)) {
+ parseExtensionSubstreamHeader();
+ headerScratchBytes.setPosition(0);
+ output.sampleData(headerScratchBytes, extensionSubstreamHeaderSize);
+ state = STATE_READING_SAMPLE;
+ }
+ break;
+ case STATE_FINDING_UHD_HEADER_SIZE:
+ // Read enough bytes to parse the header size information.
+ if (continueRead(data, headerScratchBytes.getData(), /* targetLength= */ 6)) {
+ uhdHeaderSize = DtsUtil.parseDtsUhdHeaderSize(headerScratchBytes.getData());
+ // Adjust the array read position if data read is more than the actual header size.
+ if (bytesRead > uhdHeaderSize) {
+ int extraBytes = bytesRead - uhdHeaderSize;
+ bytesRead -= extraBytes;
+ data.setPosition(data.getPosition() - extraBytes);
+ }
+ state = STATE_READING_UHD_HEADER;
+ }
+ break;
+ case STATE_READING_UHD_HEADER:
+ if (continueRead(data, headerScratchBytes.getData(), uhdHeaderSize)) {
+ parseUhdHeader();
+ headerScratchBytes.setPosition(0);
+ output.sampleData(headerScratchBytes, uhdHeaderSize);
state = STATE_READING_SAMPLE;
}
break;
@@ -118,7 +195,12 @@ public final class DtsReader implements ElementaryStreamReader {
if (bytesRead == sampleSize) {
// packetStarted method must be called before consuming samples.
checkState(timeUs != C.TIME_UNSET);
- output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
+ output.sampleMetadata(
+ timeUs,
+ frameType == DtsUtil.FRAME_TYPE_UHD_NON_SYNC ? 0 : C.BUFFER_FLAG_KEY_FRAME,
+ sampleSize,
+ 0,
+ null);
timeUs += sampleDurationUs;
state = STATE_FINDING_SYNC;
}
@@ -151,17 +233,18 @@ public final class DtsReader implements ElementaryStreamReader {
}
/**
- * Locates the next SYNC value in the buffer, advancing the position to the byte that immediately
- * follows it. If SYNC was not located, the position is advanced to the limit.
+ * Locates the next SYNC word value in the buffer, advancing the position to the byte that
+ * immediately follows it. If SYNC was not located, the position is advanced to the limit.
*
* @param pesBuffer The buffer whose position should be advanced.
- * @return Whether SYNC was found.
+ * @return Whether SYNC word was found.
*/
- private boolean skipToNextSync(ParsableByteArray pesBuffer) {
+ private boolean skipToNextSyncWord(ParsableByteArray pesBuffer) {
while (pesBuffer.bytesLeft() > 0) {
syncBytes <<= 8;
syncBytes |= pesBuffer.readUnsignedByte();
- if (DtsUtil.isSyncWord(syncBytes)) {
+ frameType = DtsUtil.getFrameType(syncBytes);
+ if (frameType != DtsUtil.FRAME_TYPE_UNKNOWN) {
byte[] headerData = headerScratchBytes.getData();
headerData[0] = (byte) ((syncBytes >> 24) & 0xFF);
headerData[1] = (byte) ((syncBytes >> 16) & 0xFF);
@@ -175,9 +258,9 @@ public final class DtsReader implements ElementaryStreamReader {
return false;
}
- /** Parses the sample header. */
+ /** Parses the DTS Core Sub-stream header. */
@RequiresNonNull("output")
- private void parseHeader() {
+ private void parseCoreHeader() {
byte[] frameData = headerScratchBytes.getData();
if (format == null) {
format = DtsUtil.parseDtsFormat(frameData, formatId, language, null);
@@ -187,7 +270,52 @@ public final class DtsReader implements ElementaryStreamReader {
// In this class a sample is an access unit (frame in DTS), but the format's sample rate
// specifies the number of PCM audio samples per second.
sampleDurationUs =
- (int)
- (C.MICROS_PER_SECOND * DtsUtil.parseDtsAudioSampleCount(frameData) / format.sampleRate);
+ Ints.checkedCast(
+ Util.sampleCountToDurationUs(
+ DtsUtil.parseDtsAudioSampleCount(frameData), format.sampleRate));
+ }
+
+ /** Parses the DTS Extension Sub-stream header. */
+ @RequiresNonNull("output")
+ private void parseExtensionSubstreamHeader() throws ParserException {
+ DtsUtil.DtsHeader dtsHeader = DtsUtil.parseDtsHdHeader(headerScratchBytes.getData());
+ updateFormatWithDtsHeaderInfo(dtsHeader);
+ sampleSize = dtsHeader.frameSize;
+ sampleDurationUs = dtsHeader.frameDurationUs == C.TIME_UNSET ? 0 : dtsHeader.frameDurationUs;
+ }
+
+ /** Parses the UHD frame header. */
+ @RequiresNonNull({"output"})
+ private void parseUhdHeader() throws ParserException {
+ DtsUtil.DtsHeader dtsHeader =
+ DtsUtil.parseDtsUhdHeader(headerScratchBytes.getData(), uhdAudioChunkId);
+ // Format updates will happen only in FTOC sync frames.
+ if (frameType == DtsUtil.FRAME_TYPE_UHD_SYNC) {
+ updateFormatWithDtsHeaderInfo(dtsHeader);
+ }
+ sampleSize = dtsHeader.frameSize;
+ sampleDurationUs = dtsHeader.frameDurationUs == C.TIME_UNSET ? 0 : dtsHeader.frameDurationUs;
+ }
+
+ @RequiresNonNull({"output"})
+ private void updateFormatWithDtsHeaderInfo(DtsUtil.DtsHeader dtsHeader) {
+ if (dtsHeader.sampleRate == C.RATE_UNSET_INT || dtsHeader.channelCount == C.LENGTH_UNSET) {
+ return;
+ }
+ if (format == null
+ || dtsHeader.channelCount != format.channelCount
+ || dtsHeader.sampleRate != format.sampleRate
+ || !Util.areEqual(dtsHeader.mimeType, format.sampleMimeType)) {
+ Format.Builder formatBuilder = format == null ? new Format.Builder() : format.buildUpon();
+ format =
+ formatBuilder
+ .setId(formatId)
+ .setSampleMimeType(dtsHeader.mimeType)
+ .setChannelCount(dtsHeader.channelCount)
+ .setSampleRate(dtsHeader.sampleRate)
+ .setLanguage(language)
+ .build();
+ output.format(format);
+ }
}
}
diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/ts/TsExtractor.java b/libraries/extractor/src/main/java/androidx/media3/extractor/ts/TsExtractor.java
index 7ff5fa4a60..fd994de56d 100644
--- a/libraries/extractor/src/main/java/androidx/media3/extractor/ts/TsExtractor.java
+++ b/libraries/extractor/src/main/java/androidx/media3/extractor/ts/TsExtractor.java
@@ -133,6 +133,8 @@ public final class TsExtractor implements Extractor {
public static final int TS_STREAM_TYPE_ID3 = 0x15;
public static final int TS_STREAM_TYPE_SPLICE_INFO = 0x86;
public static final int TS_STREAM_TYPE_DVBSUBS = 0x59;
+ public static final int TS_STREAM_TYPE_DTS_HD = 0x88; // As per ATSC Code Point Registry
+ public static final int TS_STREAM_TYPE_DTS_UHD = 0x8B;
// Stream types that aren't defined by the MPEG-2 TS specification.
public static final int TS_STREAM_TYPE_DC2_H262 = 0x80;
@@ -679,6 +681,8 @@ public final class TsExtractor implements Extractor {
private static final int TS_PMT_DESC_DVBSUBS = 0x59;
private static final int TS_PMT_DESC_DVB_EXT_AC4 = 0x15;
+ private static final int TS_PMT_DESC_DVB_EXT_DTS_HD = 0x0E;
+ private static final int TS_PMT_DESC_DVB_EXT_DTS_UHD = 0x21;
private final ParsableBitArray pmtScratch;
private final SparseArray<@NullableType TsPayloadReader> trackIdToReaderScratch;
@@ -868,6 +872,12 @@ public final class TsExtractor implements Extractor {
if (descriptorTagExt == TS_PMT_DESC_DVB_EXT_AC4) {
// AC-4_descriptor in DVB (ETSI EN 300 468).
streamType = TS_STREAM_TYPE_AC4;
+ } else if (descriptorTagExt == TS_PMT_DESC_DVB_EXT_DTS_HD) {
+ // DTS-HD descriptor in DVB (ETSI EN 300 468).
+ streamType = TS_STREAM_TYPE_DTS_HD;
+ } else if (descriptorTagExt == TS_PMT_DESC_DVB_EXT_DTS_UHD) {
+ // DTS-UHD descriptor in DVB (ETSI EN 300 468).
+ streamType = TS_STREAM_TYPE_DTS_UHD;
}
} else if (descriptorTag == TS_PMT_DESC_DTS) { // DTS_descriptor
streamType = TS_STREAM_TYPE_DTS;
diff --git a/libraries/extractor/src/test/java/androidx/media3/extractor/ts/TsExtractorTest.java b/libraries/extractor/src/test/java/androidx/media3/extractor/ts/TsExtractorTest.java
index 61e2633446..5658523dca 100644
--- a/libraries/extractor/src/test/java/androidx/media3/extractor/ts/TsExtractorTest.java
+++ b/libraries/extractor/src/test/java/androidx/media3/extractor/ts/TsExtractorTest.java
@@ -165,6 +165,30 @@ public final class TsExtractorTest {
simulationConfig);
}
+ @Test
+ public void sampleWithDts() throws Exception {
+ ExtractorAsserts.assertBehavior(
+ getExtractorFactory(subtitlesParsedDuringExtraction),
+ "media/ts/sample_dts.ts",
+ simulationConfig);
+ }
+
+ @Test
+ public void sampleWithDtsHd() throws Exception {
+ ExtractorAsserts.assertBehavior(
+ getExtractorFactory(subtitlesParsedDuringExtraction),
+ "media/ts/sample_dts_hd.ts",
+ simulationConfig);
+ }
+
+ @Test
+ public void sampleWithDtsUhd() throws Exception {
+ ExtractorAsserts.assertBehavior(
+ getExtractorFactory(subtitlesParsedDuringExtraction),
+ "media/ts/sample_dts_uhd.ts",
+ simulationConfig);
+ }
+
@Test
public void sampleWithAc3() throws Exception {
ExtractorAsserts.assertBehavior(
diff --git a/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts.ts.0.dump b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts.ts.0.dump
new file mode 100644
index 0000000000..c365cd4e31
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts.ts.0.dump
@@ -0,0 +1,194 @@
+seekMap:
+ isSeekable = true
+ duration = 458666
+ getPosition(0) = [[timeUs=0, position=0]]
+ getPosition(1) = [[timeUs=1, position=0]]
+ getPosition(229333) = [[timeUs=229333, position=23565]]
+ getPosition(458666) = [[timeUs=458666, position=47319]]
+numberOfTracks = 1
+track 257:
+ total output bytes = 45056
+ sample count = 44
+ format 0:
+ averageBitrate = 768000
+ id = 1/257
+ sampleMimeType = audio/vnd.dts
+ channelCount = 6
+ sampleRate = 48000
+ sample 0:
+ time = 0
+ flags = 1
+ data = length 1024, hash 76A741FC
+ sample 1:
+ time = 10666
+ flags = 1
+ data = length 1024, hash 2DB2026F
+ sample 2:
+ time = 21333
+ flags = 1
+ data = length 1024, hash AB0CA0C0
+ sample 3:
+ time = 32000
+ flags = 1
+ data = length 1024, hash 5E448BFF
+ sample 4:
+ time = 42666
+ flags = 1
+ data = length 1024, hash 64919D7
+ sample 5:
+ time = 53333
+ flags = 1
+ data = length 1024, hash 50BF95B1
+ sample 6:
+ time = 64000
+ flags = 1
+ data = length 1024, hash AFF14A6A
+ sample 7:
+ time = 74666
+ flags = 1
+ data = length 1024, hash B0905902
+ sample 8:
+ time = 85333
+ flags = 1
+ data = length 1024, hash C09014B3
+ sample 9:
+ time = 96000
+ flags = 1
+ data = length 1024, hash 7D918717
+ sample 10:
+ time = 106666
+ flags = 1
+ data = length 1024, hash DEE7A9AA
+ sample 11:
+ time = 117333
+ flags = 1
+ data = length 1024, hash 2905D4DB
+ sample 12:
+ time = 128000
+ flags = 1
+ data = length 1024, hash 80615D30
+ sample 13:
+ time = 138666
+ flags = 1
+ data = length 1024, hash 9949F1C
+ sample 14:
+ time = 149333
+ flags = 1
+ data = length 1024, hash 322284E0
+ sample 15:
+ time = 160000
+ flags = 1
+ data = length 1024, hash F2D0A402
+ sample 16:
+ time = 170666
+ flags = 1
+ data = length 1024, hash FF8E5254
+ sample 17:
+ time = 181333
+ flags = 1
+ data = length 1024, hash 1D0A5685
+ sample 18:
+ time = 192000
+ flags = 1
+ data = length 1024, hash A7B5783E
+ sample 19:
+ time = 202666
+ flags = 1
+ data = length 1024, hash FFFA8F6A
+ sample 20:
+ time = 213333
+ flags = 1
+ data = length 1024, hash 7EEF1A48
+ sample 21:
+ time = 224000
+ flags = 1
+ data = length 1024, hash 465956B4
+ sample 22:
+ time = 234666
+ flags = 1
+ data = length 1024, hash D1987449
+ sample 23:
+ time = 245333
+ flags = 1
+ data = length 1024, hash 33001B39
+ sample 24:
+ time = 256000
+ flags = 1
+ data = length 1024, hash F1B2E5B2
+ sample 25:
+ time = 266666
+ flags = 1
+ data = length 1024, hash F3F55C7C
+ sample 26:
+ time = 277333
+ flags = 1
+ data = length 1024, hash C965813F
+ sample 27:
+ time = 288000
+ flags = 1
+ data = length 1024, hash 611AD82C
+ sample 28:
+ time = 298666
+ flags = 1
+ data = length 1024, hash 6A630F21
+ sample 29:
+ time = 309333
+ flags = 1
+ data = length 1024, hash 7B52C0BF
+ sample 30:
+ time = 320000
+ flags = 1
+ data = length 1024, hash F9105AD9
+ sample 31:
+ time = 330666
+ flags = 1
+ data = length 1024, hash 14046870
+ sample 32:
+ time = 341333
+ flags = 1
+ data = length 1024, hash 17365B01
+ sample 33:
+ time = 352000
+ flags = 1
+ data = length 1024, hash 71BE4CC6
+ sample 34:
+ time = 362666
+ flags = 1
+ data = length 1024, hash 9C9B421C
+ sample 35:
+ time = 373333
+ flags = 1
+ data = length 1024, hash 52A90B15
+ sample 36:
+ time = 384000
+ flags = 1
+ data = length 1024, hash D4722243
+ sample 37:
+ time = 394666
+ flags = 1
+ data = length 1024, hash 50819265
+ sample 38:
+ time = 405333
+ flags = 1
+ data = length 1024, hash E80B3D7B
+ sample 39:
+ time = 416000
+ flags = 1
+ data = length 1024, hash 5E48841A
+ sample 40:
+ time = 426666
+ flags = 1
+ data = length 1024, hash C52E7744
+ sample 41:
+ time = 437333
+ flags = 1
+ data = length 1024, hash 1B1EADC1
+ sample 42:
+ time = 448000
+ flags = 1
+ data = length 1024, hash 7F8F62BB
+ sample 43:
+ time = 458666
+ flags = 1
+ data = length 1024, hash 4DF51924
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts.ts.1.dump b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts.ts.1.dump
new file mode 100644
index 0000000000..3971920a3f
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts.ts.1.dump
@@ -0,0 +1,138 @@
+seekMap:
+ isSeekable = true
+ duration = 458666
+ getPosition(0) = [[timeUs=0, position=0]]
+ getPosition(1) = [[timeUs=1, position=0]]
+ getPosition(229333) = [[timeUs=229333, position=23565]]
+ getPosition(458666) = [[timeUs=458666, position=47319]]
+numberOfTracks = 1
+track 257:
+ total output bytes = 30720
+ sample count = 30
+ format 0:
+ averageBitrate = 768000
+ id = 1/257
+ sampleMimeType = audio/vnd.dts
+ channelCount = 6
+ sampleRate = 48000
+ sample 0:
+ time = 149333
+ flags = 1
+ data = length 1024, hash 322284E0
+ sample 1:
+ time = 160000
+ flags = 1
+ data = length 1024, hash F2D0A402
+ sample 2:
+ time = 170666
+ flags = 1
+ data = length 1024, hash FF8E5254
+ sample 3:
+ time = 181333
+ flags = 1
+ data = length 1024, hash 1D0A5685
+ sample 4:
+ time = 192000
+ flags = 1
+ data = length 1024, hash A7B5783E
+ sample 5:
+ time = 202666
+ flags = 1
+ data = length 1024, hash FFFA8F6A
+ sample 6:
+ time = 213333
+ flags = 1
+ data = length 1024, hash 7EEF1A48
+ sample 7:
+ time = 224000
+ flags = 1
+ data = length 1024, hash 465956B4
+ sample 8:
+ time = 234666
+ flags = 1
+ data = length 1024, hash D1987449
+ sample 9:
+ time = 245333
+ flags = 1
+ data = length 1024, hash 33001B39
+ sample 10:
+ time = 256000
+ flags = 1
+ data = length 1024, hash F1B2E5B2
+ sample 11:
+ time = 266666
+ flags = 1
+ data = length 1024, hash F3F55C7C
+ sample 12:
+ time = 277333
+ flags = 1
+ data = length 1024, hash C965813F
+ sample 13:
+ time = 288000
+ flags = 1
+ data = length 1024, hash 611AD82C
+ sample 14:
+ time = 298666
+ flags = 1
+ data = length 1024, hash 6A630F21
+ sample 15:
+ time = 309333
+ flags = 1
+ data = length 1024, hash 7B52C0BF
+ sample 16:
+ time = 320000
+ flags = 1
+ data = length 1024, hash F9105AD9
+ sample 17:
+ time = 330666
+ flags = 1
+ data = length 1024, hash 14046870
+ sample 18:
+ time = 341333
+ flags = 1
+ data = length 1024, hash 17365B01
+ sample 19:
+ time = 352000
+ flags = 1
+ data = length 1024, hash 71BE4CC6
+ sample 20:
+ time = 362666
+ flags = 1
+ data = length 1024, hash 9C9B421C
+ sample 21:
+ time = 373333
+ flags = 1
+ data = length 1024, hash 52A90B15
+ sample 22:
+ time = 384000
+ flags = 1
+ data = length 1024, hash D4722243
+ sample 23:
+ time = 394666
+ flags = 1
+ data = length 1024, hash 50819265
+ sample 24:
+ time = 405333
+ flags = 1
+ data = length 1024, hash E80B3D7B
+ sample 25:
+ time = 416000
+ flags = 1
+ data = length 1024, hash 5E48841A
+ sample 26:
+ time = 426666
+ flags = 1
+ data = length 1024, hash C52E7744
+ sample 27:
+ time = 437333
+ flags = 1
+ data = length 1024, hash 1B1EADC1
+ sample 28:
+ time = 448000
+ flags = 1
+ data = length 1024, hash 7F8F62BB
+ sample 29:
+ time = 458666
+ flags = 1
+ data = length 1024, hash 4DF51924
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts.ts.2.dump b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts.ts.2.dump
new file mode 100644
index 0000000000..96942653e0
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts.ts.2.dump
@@ -0,0 +1,82 @@
+seekMap:
+ isSeekable = true
+ duration = 458666
+ getPosition(0) = [[timeUs=0, position=0]]
+ getPosition(1) = [[timeUs=1, position=0]]
+ getPosition(229333) = [[timeUs=229333, position=23565]]
+ getPosition(458666) = [[timeUs=458666, position=47319]]
+numberOfTracks = 1
+track 257:
+ total output bytes = 16384
+ sample count = 16
+ format 0:
+ averageBitrate = 768000
+ id = 1/257
+ sampleMimeType = audio/vnd.dts
+ channelCount = 6
+ sampleRate = 48000
+ sample 0:
+ time = 298666
+ flags = 1
+ data = length 1024, hash 6A630F21
+ sample 1:
+ time = 309333
+ flags = 1
+ data = length 1024, hash 7B52C0BF
+ sample 2:
+ time = 320000
+ flags = 1
+ data = length 1024, hash F9105AD9
+ sample 3:
+ time = 330666
+ flags = 1
+ data = length 1024, hash 14046870
+ sample 4:
+ time = 341333
+ flags = 1
+ data = length 1024, hash 17365B01
+ sample 5:
+ time = 352000
+ flags = 1
+ data = length 1024, hash 71BE4CC6
+ sample 6:
+ time = 362666
+ flags = 1
+ data = length 1024, hash 9C9B421C
+ sample 7:
+ time = 373333
+ flags = 1
+ data = length 1024, hash 52A90B15
+ sample 8:
+ time = 384000
+ flags = 1
+ data = length 1024, hash D4722243
+ sample 9:
+ time = 394666
+ flags = 1
+ data = length 1024, hash 50819265
+ sample 10:
+ time = 405333
+ flags = 1
+ data = length 1024, hash E80B3D7B
+ sample 11:
+ time = 416000
+ flags = 1
+ data = length 1024, hash 5E48841A
+ sample 12:
+ time = 426666
+ flags = 1
+ data = length 1024, hash C52E7744
+ sample 13:
+ time = 437333
+ flags = 1
+ data = length 1024, hash 1B1EADC1
+ sample 14:
+ time = 448000
+ flags = 1
+ data = length 1024, hash 7F8F62BB
+ sample 15:
+ time = 458666
+ flags = 1
+ data = length 1024, hash 4DF51924
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts.ts.3.dump b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts.ts.3.dump
new file mode 100644
index 0000000000..ab45b1bd00
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts.ts.3.dump
@@ -0,0 +1,26 @@
+seekMap:
+ isSeekable = true
+ duration = 458666
+ getPosition(0) = [[timeUs=0, position=0]]
+ getPosition(1) = [[timeUs=1, position=0]]
+ getPosition(229333) = [[timeUs=229333, position=23565]]
+ getPosition(458666) = [[timeUs=458666, position=47319]]
+numberOfTracks = 1
+track 257:
+ total output bytes = 2048
+ sample count = 2
+ format 0:
+ averageBitrate = 768000
+ id = 1/257
+ sampleMimeType = audio/vnd.dts
+ channelCount = 6
+ sampleRate = 48000
+ sample 0:
+ time = 448000
+ flags = 1
+ data = length 1024, hash 7F8F62BB
+ sample 1:
+ time = 458666
+ flags = 1
+ data = length 1024, hash 4DF51924
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts.ts.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts.ts.unknown_length.dump
new file mode 100644
index 0000000000..1150cbacfb
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts.ts.unknown_length.dump
@@ -0,0 +1,191 @@
+seekMap:
+ isSeekable = false
+ duration = UNSET TIME
+ getPosition(0) = [[timeUs=0, position=0]]
+numberOfTracks = 1
+track 257:
+ total output bytes = 45056
+ sample count = 44
+ format 0:
+ averageBitrate = 768000
+ id = 1/257
+ sampleMimeType = audio/vnd.dts
+ channelCount = 6
+ sampleRate = 48000
+ sample 0:
+ time = 0
+ flags = 1
+ data = length 1024, hash 76A741FC
+ sample 1:
+ time = 10666
+ flags = 1
+ data = length 1024, hash 2DB2026F
+ sample 2:
+ time = 21333
+ flags = 1
+ data = length 1024, hash AB0CA0C0
+ sample 3:
+ time = 32000
+ flags = 1
+ data = length 1024, hash 5E448BFF
+ sample 4:
+ time = 42666
+ flags = 1
+ data = length 1024, hash 64919D7
+ sample 5:
+ time = 53333
+ flags = 1
+ data = length 1024, hash 50BF95B1
+ sample 6:
+ time = 64000
+ flags = 1
+ data = length 1024, hash AFF14A6A
+ sample 7:
+ time = 74666
+ flags = 1
+ data = length 1024, hash B0905902
+ sample 8:
+ time = 85333
+ flags = 1
+ data = length 1024, hash C09014B3
+ sample 9:
+ time = 96000
+ flags = 1
+ data = length 1024, hash 7D918717
+ sample 10:
+ time = 106666
+ flags = 1
+ data = length 1024, hash DEE7A9AA
+ sample 11:
+ time = 117333
+ flags = 1
+ data = length 1024, hash 2905D4DB
+ sample 12:
+ time = 128000
+ flags = 1
+ data = length 1024, hash 80615D30
+ sample 13:
+ time = 138666
+ flags = 1
+ data = length 1024, hash 9949F1C
+ sample 14:
+ time = 149333
+ flags = 1
+ data = length 1024, hash 322284E0
+ sample 15:
+ time = 160000
+ flags = 1
+ data = length 1024, hash F2D0A402
+ sample 16:
+ time = 170666
+ flags = 1
+ data = length 1024, hash FF8E5254
+ sample 17:
+ time = 181333
+ flags = 1
+ data = length 1024, hash 1D0A5685
+ sample 18:
+ time = 192000
+ flags = 1
+ data = length 1024, hash A7B5783E
+ sample 19:
+ time = 202666
+ flags = 1
+ data = length 1024, hash FFFA8F6A
+ sample 20:
+ time = 213333
+ flags = 1
+ data = length 1024, hash 7EEF1A48
+ sample 21:
+ time = 224000
+ flags = 1
+ data = length 1024, hash 465956B4
+ sample 22:
+ time = 234666
+ flags = 1
+ data = length 1024, hash D1987449
+ sample 23:
+ time = 245333
+ flags = 1
+ data = length 1024, hash 33001B39
+ sample 24:
+ time = 256000
+ flags = 1
+ data = length 1024, hash F1B2E5B2
+ sample 25:
+ time = 266666
+ flags = 1
+ data = length 1024, hash F3F55C7C
+ sample 26:
+ time = 277333
+ flags = 1
+ data = length 1024, hash C965813F
+ sample 27:
+ time = 288000
+ flags = 1
+ data = length 1024, hash 611AD82C
+ sample 28:
+ time = 298666
+ flags = 1
+ data = length 1024, hash 6A630F21
+ sample 29:
+ time = 309333
+ flags = 1
+ data = length 1024, hash 7B52C0BF
+ sample 30:
+ time = 320000
+ flags = 1
+ data = length 1024, hash F9105AD9
+ sample 31:
+ time = 330666
+ flags = 1
+ data = length 1024, hash 14046870
+ sample 32:
+ time = 341333
+ flags = 1
+ data = length 1024, hash 17365B01
+ sample 33:
+ time = 352000
+ flags = 1
+ data = length 1024, hash 71BE4CC6
+ sample 34:
+ time = 362666
+ flags = 1
+ data = length 1024, hash 9C9B421C
+ sample 35:
+ time = 373333
+ flags = 1
+ data = length 1024, hash 52A90B15
+ sample 36:
+ time = 384000
+ flags = 1
+ data = length 1024, hash D4722243
+ sample 37:
+ time = 394666
+ flags = 1
+ data = length 1024, hash 50819265
+ sample 38:
+ time = 405333
+ flags = 1
+ data = length 1024, hash E80B3D7B
+ sample 39:
+ time = 416000
+ flags = 1
+ data = length 1024, hash 5E48841A
+ sample 40:
+ time = 426666
+ flags = 1
+ data = length 1024, hash C52E7744
+ sample 41:
+ time = 437333
+ flags = 1
+ data = length 1024, hash 1B1EADC1
+ sample 42:
+ time = 448000
+ flags = 1
+ data = length 1024, hash 7F8F62BB
+ sample 43:
+ time = 458666
+ flags = 1
+ data = length 1024, hash 4DF51924
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_hd.ts.0.dump b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_hd.ts.0.dump
new file mode 100644
index 0000000000..7d6271f027
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_hd.ts.0.dump
@@ -0,0 +1,61 @@
+seekMap:
+ isSeekable = true
+ duration = 853333
+ getPosition(0) = [[timeUs=0, position=0]]
+ getPosition(1) = [[timeUs=1, position=0]]
+ getPosition(426666) = [[timeUs=426666, position=22583]]
+ getPosition(853333) = [[timeUs=853333, position=45355]]
+numberOfTracks = 1
+track 257:
+ total output bytes = 45056
+ sample count = 11
+ format 0:
+ id = 1/257
+ sampleMimeType = audio/vnd.dts.hd;profile=lbr
+ channelCount = 6
+ sampleRate = 48000
+ sample 0:
+ time = 0
+ flags = 1
+ data = length 4096, hash 1F0B79C5
+ sample 1:
+ time = 85333
+ flags = 1
+ data = length 4096, hash 2EC282A1
+ sample 2:
+ time = 170666
+ flags = 1
+ data = length 4096, hash 6B7902F0
+ sample 3:
+ time = 256000
+ flags = 1
+ data = length 4096, hash 8FC4EE2C
+ sample 4:
+ time = 341333
+ flags = 1
+ data = length 4096, hash 67899547
+ sample 5:
+ time = 426666
+ flags = 1
+ data = length 4096, hash 1BE4CF1C
+ sample 6:
+ time = 512000
+ flags = 1
+ data = length 4096, hash 620F5E51
+ sample 7:
+ time = 597333
+ flags = 1
+ data = length 4096, hash 4D3E0644
+ sample 8:
+ time = 682666
+ flags = 1
+ data = length 4096, hash F69B5FED
+ sample 9:
+ time = 768000
+ flags = 1
+ data = length 4096, hash 93D31EA7
+ sample 10:
+ time = 853333
+ flags = 1
+ data = length 4096, hash 41F1D921
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_hd.ts.1.dump b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_hd.ts.1.dump
new file mode 100644
index 0000000000..affd4f713b
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_hd.ts.1.dump
@@ -0,0 +1,49 @@
+seekMap:
+ isSeekable = true
+ duration = 853333
+ getPosition(0) = [[timeUs=0, position=0]]
+ getPosition(1) = [[timeUs=1, position=0]]
+ getPosition(426666) = [[timeUs=426666, position=22583]]
+ getPosition(853333) = [[timeUs=853333, position=45355]]
+numberOfTracks = 1
+track 257:
+ total output bytes = 32768
+ sample count = 8
+ format 0:
+ id = 1/257
+ sampleMimeType = audio/vnd.dts.hd;profile=lbr
+ channelCount = 6
+ sampleRate = 48000
+ sample 0:
+ time = 256000
+ flags = 1
+ data = length 4096, hash 8FC4EE2C
+ sample 1:
+ time = 341333
+ flags = 1
+ data = length 4096, hash 67899547
+ sample 2:
+ time = 426666
+ flags = 1
+ data = length 4096, hash 1BE4CF1C
+ sample 3:
+ time = 512000
+ flags = 1
+ data = length 4096, hash 620F5E51
+ sample 4:
+ time = 597333
+ flags = 1
+ data = length 4096, hash 4D3E0644
+ sample 5:
+ time = 682666
+ flags = 1
+ data = length 4096, hash F69B5FED
+ sample 6:
+ time = 768000
+ flags = 1
+ data = length 4096, hash 93D31EA7
+ sample 7:
+ time = 853333
+ flags = 1
+ data = length 4096, hash 41F1D921
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_hd.ts.2.dump b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_hd.ts.2.dump
new file mode 100644
index 0000000000..d9803a8904
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_hd.ts.2.dump
@@ -0,0 +1,37 @@
+seekMap:
+ isSeekable = true
+ duration = 853333
+ getPosition(0) = [[timeUs=0, position=0]]
+ getPosition(1) = [[timeUs=1, position=0]]
+ getPosition(426666) = [[timeUs=426666, position=22583]]
+ getPosition(853333) = [[timeUs=853333, position=45355]]
+numberOfTracks = 1
+track 257:
+ total output bytes = 20480
+ sample count = 5
+ format 0:
+ id = 1/257
+ sampleMimeType = audio/vnd.dts.hd;profile=lbr
+ channelCount = 6
+ sampleRate = 48000
+ sample 0:
+ time = 512000
+ flags = 1
+ data = length 4096, hash 620F5E51
+ sample 1:
+ time = 597333
+ flags = 1
+ data = length 4096, hash 4D3E0644
+ sample 2:
+ time = 682666
+ flags = 1
+ data = length 4096, hash F69B5FED
+ sample 3:
+ time = 768000
+ flags = 1
+ data = length 4096, hash 93D31EA7
+ sample 4:
+ time = 853333
+ flags = 1
+ data = length 4096, hash 41F1D921
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_hd.ts.3.dump b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_hd.ts.3.dump
new file mode 100644
index 0000000000..7c2f06ab6b
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_hd.ts.3.dump
@@ -0,0 +1,17 @@
+seekMap:
+ isSeekable = true
+ duration = 853333
+ getPosition(0) = [[timeUs=0, position=0]]
+ getPosition(1) = [[timeUs=1, position=0]]
+ getPosition(426666) = [[timeUs=426666, position=22583]]
+ getPosition(853333) = [[timeUs=853333, position=45355]]
+numberOfTracks = 1
+track 257:
+ total output bytes = 0
+ sample count = 0
+ format 0:
+ id = 1/257
+ sampleMimeType = audio/vnd.dts.hd;profile=lbr
+ channelCount = 6
+ sampleRate = 48000
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_hd.ts.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_hd.ts.unknown_length.dump
new file mode 100644
index 0000000000..00eb0c5d24
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_hd.ts.unknown_length.dump
@@ -0,0 +1,58 @@
+seekMap:
+ isSeekable = false
+ duration = UNSET TIME
+ getPosition(0) = [[timeUs=0, position=0]]
+numberOfTracks = 1
+track 257:
+ total output bytes = 45056
+ sample count = 11
+ format 0:
+ id = 1/257
+ sampleMimeType = audio/vnd.dts.hd;profile=lbr
+ channelCount = 6
+ sampleRate = 48000
+ sample 0:
+ time = 0
+ flags = 1
+ data = length 4096, hash 1F0B79C5
+ sample 1:
+ time = 85333
+ flags = 1
+ data = length 4096, hash 2EC282A1
+ sample 2:
+ time = 170666
+ flags = 1
+ data = length 4096, hash 6B7902F0
+ sample 3:
+ time = 256000
+ flags = 1
+ data = length 4096, hash 8FC4EE2C
+ sample 4:
+ time = 341333
+ flags = 1
+ data = length 4096, hash 67899547
+ sample 5:
+ time = 426666
+ flags = 1
+ data = length 4096, hash 1BE4CF1C
+ sample 6:
+ time = 512000
+ flags = 1
+ data = length 4096, hash 620F5E51
+ sample 7:
+ time = 597333
+ flags = 1
+ data = length 4096, hash 4D3E0644
+ sample 8:
+ time = 682666
+ flags = 1
+ data = length 4096, hash F69B5FED
+ sample 9:
+ time = 768000
+ flags = 1
+ data = length 4096, hash 93D31EA7
+ sample 10:
+ time = 853333
+ flags = 1
+ data = length 4096, hash 41F1D921
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_uhd.ts.0.dump b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_uhd.ts.0.dump
new file mode 100644
index 0000000000..a87dc4b897
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_uhd.ts.0.dump
@@ -0,0 +1,953 @@
+seekMap:
+ isSeekable = true
+ duration = 4970666
+ getPosition(0) = [[timeUs=0, position=0]]
+ getPosition(1) = [[timeUs=1, position=0]]
+ getPosition(2485333) = [[timeUs=2485333, position=102149]]
+ getPosition(4970666) = [[timeUs=4970666, position=204487]]
+numberOfTracks = 1
+track 257:
+ total output bytes = 179682
+ sample count = 234
+ format 0:
+ id = 1/257
+ sampleMimeType = audio/vnd.dts.uhd;profile=p2
+ channelCount = 2
+ sampleRate = 48000
+ sample 0:
+ time = 0
+ flags = 1
+ data = length 776, hash E68E7565
+ sample 1:
+ time = 21333
+ flags = 0
+ data = length 765, hash 713DA83C
+ sample 2:
+ time = 42666
+ flags = 0
+ data = length 771, hash E672DC
+ sample 3:
+ time = 64000
+ flags = 0
+ data = length 769, hash 83F90436
+ sample 4:
+ time = 85333
+ flags = 0
+ data = length 765, hash 5C8A17D1
+ sample 5:
+ time = 106666
+ flags = 0
+ data = length 771, hash 5528EC74
+ sample 6:
+ time = 128000
+ flags = 0
+ data = length 767, hash 954FC4B5
+ sample 7:
+ time = 149333
+ flags = 0
+ data = length 767, hash 5C2089BB
+ sample 8:
+ time = 170666
+ flags = 0
+ data = length 771, hash 21AF360B
+ sample 9:
+ time = 192000
+ flags = 0
+ data = length 766, hash 2C363E9B
+ sample 10:
+ time = 213333
+ flags = 0
+ data = length 767, hash 812E9BF7
+ sample 11:
+ time = 234666
+ flags = 0
+ data = length 770, hash ED9D5378
+ sample 12:
+ time = 256000
+ flags = 0
+ data = length 769, hash FBF9DD0E
+ sample 13:
+ time = 277333
+ flags = 0
+ data = length 767, hash 5E7822E9
+ sample 14:
+ time = 298666
+ flags = 0
+ data = length 770, hash 97EDBA77
+ sample 15:
+ time = 320000
+ flags = 0
+ data = length 767, hash 1739FF77
+ sample 16:
+ time = 341333
+ flags = 0
+ data = length 766, hash 99225978
+ sample 17:
+ time = 362666
+ flags = 0
+ data = length 772, hash 1971320D
+ sample 18:
+ time = 384000
+ flags = 0
+ data = length 768, hash F8C4F6A2
+ sample 19:
+ time = 405333
+ flags = 0
+ data = length 765, hash 225434F4
+ sample 20:
+ time = 426666
+ flags = 0
+ data = length 770, hash E232FA0D
+ sample 21:
+ time = 448000
+ flags = 0
+ data = length 767, hash 721418FA
+ sample 22:
+ time = 469333
+ flags = 0
+ data = length 768, hash E52E3AD0
+ sample 23:
+ time = 490666
+ flags = 0
+ data = length 772, hash 9D0F9C8C
+ sample 24:
+ time = 512000
+ flags = 0
+ data = length 767, hash EAFEDC
+ sample 25:
+ time = 533333
+ flags = 0
+ data = length 766, hash CAFCB522
+ sample 26:
+ time = 554666
+ flags = 0
+ data = length 770, hash EB1806AF
+ sample 27:
+ time = 576000
+ flags = 0
+ data = length 768, hash F022F870
+ sample 28:
+ time = 597333
+ flags = 0
+ data = length 767, hash 2DB31DD6
+ sample 29:
+ time = 618666
+ flags = 0
+ data = length 770, hash 3168DE65
+ sample 30:
+ time = 640000
+ flags = 0
+ data = length 767, hash 1D25591B
+ sample 31:
+ time = 661333
+ flags = 0
+ data = length 766, hash 2DB4AF54
+ sample 32:
+ time = 682666
+ flags = 0
+ data = length 772, hash 9B9176A8
+ sample 33:
+ time = 704000
+ flags = 0
+ data = length 768, hash F49BD7C2
+ sample 34:
+ time = 725333
+ flags = 0
+ data = length 765, hash 4D1A1A5B
+ sample 35:
+ time = 746666
+ flags = 0
+ data = length 771, hash EED28144
+ sample 36:
+ time = 768000
+ flags = 0
+ data = length 767, hash DE09C384
+ sample 37:
+ time = 789333
+ flags = 0
+ data = length 767, hash 5B154F22
+ sample 38:
+ time = 810666
+ flags = 0
+ data = length 772, hash 7621AB2B
+ sample 39:
+ time = 832000
+ flags = 0
+ data = length 767, hash 3B503329
+ sample 40:
+ time = 853333
+ flags = 0
+ data = length 766, hash 6D5F86F0
+ sample 41:
+ time = 874666
+ flags = 0
+ data = length 770, hash 122B33CF
+ sample 42:
+ time = 896000
+ flags = 0
+ data = length 769, hash 701BED85
+ sample 43:
+ time = 917333
+ flags = 0
+ data = length 767, hash 66F75279
+ sample 44:
+ time = 938666
+ flags = 0
+ data = length 769, hash 8EB616E3
+ sample 45:
+ time = 960000
+ flags = 0
+ data = length 767, hash C04E8FCB
+ sample 46:
+ time = 981333
+ flags = 0
+ data = length 765, hash 568E8728
+ sample 47:
+ time = 1002666
+ flags = 0
+ data = length 772, hash C23993F0
+ sample 48:
+ time = 1024000
+ flags = 0
+ data = length 768, hash 518ACD0D
+ sample 49:
+ time = 1045333
+ flags = 0
+ data = length 765, hash 297ACB8E
+ sample 50:
+ time = 1066666
+ flags = 0
+ data = length 770, hash 676ED3C1
+ sample 51:
+ time = 1088000
+ flags = 0
+ data = length 767, hash 836598AA
+ sample 52:
+ time = 1109333
+ flags = 0
+ data = length 767, hash F1536245
+ sample 53:
+ time = 1130666
+ flags = 0
+ data = length 772, hash 12AC3BCE
+ sample 54:
+ time = 1152000
+ flags = 0
+ data = length 766, hash 9948C9C
+ sample 55:
+ time = 1173333
+ flags = 0
+ data = length 766, hash B42ADF4E
+ sample 56:
+ time = 1194666
+ flags = 0
+ data = length 770, hash 67AC576F
+ sample 57:
+ time = 1216000
+ flags = 0
+ data = length 769, hash B843E663
+ sample 58:
+ time = 1237333
+ flags = 0
+ data = length 767, hash 432AD19
+ sample 59:
+ time = 1258666
+ flags = 0
+ data = length 770, hash 14BA5FE6
+ sample 60:
+ time = 1280000
+ flags = 0
+ data = length 768, hash A0D32F30
+ sample 61:
+ time = 1301333
+ flags = 0
+ data = length 765, hash 4BF180A9
+ sample 62:
+ time = 1322666
+ flags = 0
+ data = length 772, hash 1C613DF7
+ sample 63:
+ time = 1344000
+ flags = 0
+ data = length 768, hash F30F6A09
+ sample 64:
+ time = 1365333
+ flags = 0
+ data = length 765, hash D40AC240
+ sample 65:
+ time = 1386666
+ flags = 0
+ data = length 770, hash 1E64D8FE
+ sample 66:
+ time = 1408000
+ flags = 0
+ data = length 767, hash 5DFE9BC3
+ sample 67:
+ time = 1429333
+ flags = 0
+ data = length 767, hash 19A018BD
+ sample 68:
+ time = 1450666
+ flags = 0
+ data = length 772, hash 363BF537
+ sample 69:
+ time = 1472000
+ flags = 0
+ data = length 766, hash 4832AF5B
+ sample 70:
+ time = 1493333
+ flags = 0
+ data = length 766, hash 3CBED44A
+ sample 71:
+ time = 1514666
+ flags = 0
+ data = length 771, hash C5E800AD
+ sample 72:
+ time = 1536000
+ flags = 0
+ data = length 786, hash DA64F1EE
+ sample 73:
+ time = 1557333
+ flags = 0
+ data = length 785, hash 4771990A
+ sample 74:
+ time = 1578666
+ flags = 0
+ data = length 788, hash CBB53C84
+ sample 75:
+ time = 1600000
+ flags = 0
+ data = length 786, hash AF107053
+ sample 76:
+ time = 1621333
+ flags = 0
+ data = length 784, hash 7418BBD7
+ sample 77:
+ time = 1642666
+ flags = 0
+ data = length 790, hash 35A5E570
+ sample 78:
+ time = 1664000
+ flags = 0
+ data = length 787, hash 4F662158
+ sample 79:
+ time = 1685333
+ flags = 0
+ data = length 783, hash A574B045
+ sample 80:
+ time = 1706666
+ flags = 0
+ data = length 789, hash 211311A9
+ sample 81:
+ time = 1728000
+ flags = 0
+ data = length 785, hash 4A7E6F21
+ sample 82:
+ time = 1749333
+ flags = 0
+ data = length 786, hash DE8047C6
+ sample 83:
+ time = 1770666
+ flags = 0
+ data = length 789, hash E778E75A
+ sample 84:
+ time = 1792000
+ flags = 0
+ data = length 785, hash AD3A50F8
+ sample 85:
+ time = 1813333
+ flags = 0
+ data = length 783, hash 6DCEAA5C
+ sample 86:
+ time = 1834666
+ flags = 0
+ data = length 787, hash D5E2A255
+ sample 87:
+ time = 1856000
+ flags = 0
+ data = length 787, hash E9138642
+ sample 88:
+ time = 1877333
+ flags = 0
+ data = length 785, hash B2D94BAF
+ sample 89:
+ time = 1898666
+ flags = 0
+ data = length 789, hash F0F3BBDB
+ sample 90:
+ time = 1920000
+ flags = 0
+ data = length 786, hash B0D62A20
+ sample 91:
+ time = 1941333
+ flags = 0
+ data = length 767, hash 710CB0E4
+ sample 92:
+ time = 1962666
+ flags = 0
+ data = length 400, hash 8A0182CB
+ sample 93:
+ time = 1984000
+ flags = 1
+ data = length 402, hash E60D79A1
+ sample 94:
+ time = 2005333
+ flags = 0
+ data = length 394, hash 585703B6
+ sample 95:
+ time = 2026666
+ flags = 0
+ data = length 394, hash 50CA225B
+ sample 96:
+ time = 2048000
+ flags = 0
+ data = length 395, hash E0229BF0
+ sample 97:
+ time = 2069333
+ flags = 0
+ data = length 501, hash F8930C9C
+ sample 98:
+ time = 2090666
+ flags = 0
+ data = length 667, hash C05CCFA2
+ sample 99:
+ time = 2112000
+ flags = 0
+ data = length 918, hash 5832371D
+ sample 100:
+ time = 2133333
+ flags = 0
+ data = length 1101, hash 1F97D86E
+ sample 101:
+ time = 2154666
+ flags = 0
+ data = length 1006, hash 974AC450
+ sample 102:
+ time = 2176000
+ flags = 0
+ data = length 1153, hash 22CA9C79
+ sample 103:
+ time = 2197333
+ flags = 0
+ data = length 959, hash 2011C476
+ sample 104:
+ time = 2218666
+ flags = 0
+ data = length 735, hash C2F6C1F9
+ sample 105:
+ time = 2240000
+ flags = 0
+ data = length 865, hash 394C4481
+ sample 106:
+ time = 2261333
+ flags = 0
+ data = length 825, hash 611B513C
+ sample 107:
+ time = 2282666
+ flags = 0
+ data = length 952, hash 5B24AEC2
+ sample 108:
+ time = 2304000
+ flags = 0
+ data = length 984, hash 172B469
+ sample 109:
+ time = 2325333
+ flags = 0
+ data = length 1010, hash D3BBA580
+ sample 110:
+ time = 2346666
+ flags = 0
+ data = length 1067, hash E09AD57F
+ sample 111:
+ time = 2368000
+ flags = 0
+ data = length 1060, hash 5332E90B
+ sample 112:
+ time = 2389333
+ flags = 0
+ data = length 991, hash 48B80B00
+ sample 113:
+ time = 2410666
+ flags = 0
+ data = length 873, hash 696FBD43
+ sample 114:
+ time = 2432000
+ flags = 0
+ data = length 810, hash 7D3D7B29
+ sample 115:
+ time = 2453333
+ flags = 0
+ data = length 897, hash D41D4CB7
+ sample 116:
+ time = 2474666
+ flags = 0
+ data = length 781, hash A589A312
+ sample 117:
+ time = 2496000
+ flags = 0
+ data = length 705, hash FDC5698B
+ sample 118:
+ time = 2517333
+ flags = 0
+ data = length 608, hash F929EDA6
+ sample 119:
+ time = 2538666
+ flags = 0
+ data = length 546, hash A141CD5E
+ sample 120:
+ time = 2560000
+ flags = 0
+ data = length 639, hash BABD5C9F
+ sample 121:
+ time = 2581333
+ flags = 0
+ data = length 561, hash B1AF4D92
+ sample 122:
+ time = 2602666
+ flags = 0
+ data = length 529, hash D0E0EF42
+ sample 123:
+ time = 2624000
+ flags = 0
+ data = length 441, hash E0B1DB1
+ sample 124:
+ time = 2645333
+ flags = 0
+ data = length 393, hash 5A34D1B0
+ sample 125:
+ time = 2666666
+ flags = 0
+ data = length 393, hash B792EA44
+ sample 126:
+ time = 2688000
+ flags = 0
+ data = length 393, hash 7CCE0C94
+ sample 127:
+ time = 2709333
+ flags = 0
+ data = length 393, hash C80E41E0
+ sample 128:
+ time = 2730666
+ flags = 0
+ data = length 393, hash 2C5B4860
+ sample 129:
+ time = 2752000
+ flags = 0
+ data = length 393, hash 9930B5F0
+ sample 130:
+ time = 2773333
+ flags = 0
+ data = length 393, hash B78D1FDA
+ sample 131:
+ time = 2794666
+ flags = 0
+ data = length 393, hash 817AB352
+ sample 132:
+ time = 2816000
+ flags = 0
+ data = length 393, hash EA7D83DF
+ sample 133:
+ time = 2837333
+ flags = 0
+ data = length 393, hash E76873B0
+ sample 134:
+ time = 2858666
+ flags = 0
+ data = length 393, hash 2F48A520
+ sample 135:
+ time = 2880000
+ flags = 0
+ data = length 393, hash C0CBB3EF
+ sample 136:
+ time = 2901333
+ flags = 0
+ data = length 393, hash 255B0E50
+ sample 137:
+ time = 2922666
+ flags = 0
+ data = length 393, hash 9A49C63D
+ sample 138:
+ time = 2944000
+ flags = 0
+ data = length 1516, hash 4994C5B
+ sample 139:
+ time = 2965333
+ flags = 0
+ data = length 1519, hash 5514C06F
+ sample 140:
+ time = 2986666
+ flags = 0
+ data = length 1007, hash F994B3FC
+ sample 141:
+ time = 3008000
+ flags = 0
+ data = length 946, hash 7714E7B1
+ sample 142:
+ time = 3029333
+ flags = 0
+ data = length 985, hash C0E4D841
+ sample 143:
+ time = 3050666
+ flags = 0
+ data = length 1018, hash A18F6981
+ sample 144:
+ time = 3072000
+ flags = 0
+ data = length 790, hash 9F884211
+ sample 145:
+ time = 3093333
+ flags = 0
+ data = length 809, hash 1E0978C9
+ sample 146:
+ time = 3114666
+ flags = 0
+ data = length 791, hash 9BC34342
+ sample 147:
+ time = 3136000
+ flags = 0
+ data = length 806, hash C64EDB12
+ sample 148:
+ time = 3157333
+ flags = 0
+ data = length 757, hash 6C971B85
+ sample 149:
+ time = 3178666
+ flags = 0
+ data = length 950, hash 5509778D
+ sample 150:
+ time = 3200000
+ flags = 0
+ data = length 713, hash 2BD954C8
+ sample 151:
+ time = 3221333
+ flags = 0
+ data = length 800, hash 1C71F2EF
+ sample 152:
+ time = 3242666
+ flags = 0
+ data = length 804, hash BFCCE7C
+ sample 153:
+ time = 3264000
+ flags = 0
+ data = length 876, hash AB1137D9
+ sample 154:
+ time = 3285333
+ flags = 0
+ data = length 957, hash 1CC9B8CA
+ sample 155:
+ time = 3306666
+ flags = 0
+ data = length 563, hash A6FF9D2B
+ sample 156:
+ time = 3328000
+ flags = 0
+ data = length 796, hash B0110276
+ sample 157:
+ time = 3349333
+ flags = 0
+ data = length 863, hash 55EDF24F
+ sample 158:
+ time = 3370666
+ flags = 0
+ data = length 701, hash 3AE3C48F
+ sample 159:
+ time = 3392000
+ flags = 0
+ data = length 934, hash 2CC1C6E9
+ sample 160:
+ time = 3413333
+ flags = 0
+ data = length 967, hash 34E61D20
+ sample 161:
+ time = 3434666
+ flags = 0
+ data = length 1518, hash C0EC5B50
+ sample 162:
+ time = 3456000
+ flags = 0
+ data = length 1474, hash 6EC36C24
+ sample 163:
+ time = 3477333
+ flags = 0
+ data = length 1475, hash 6F1FD2AB
+ sample 164:
+ time = 3498666
+ flags = 0
+ data = length 1451, hash B58F4D31
+ sample 165:
+ time = 3520000
+ flags = 0
+ data = length 526, hash FC424B78
+ sample 166:
+ time = 3541333
+ flags = 0
+ data = length 598, hash 4BDB2753
+ sample 167:
+ time = 3562666
+ flags = 0
+ data = length 627, hash 48327C83
+ sample 168:
+ time = 3584000
+ flags = 0
+ data = length 551, hash 691D6CB2
+ sample 169:
+ time = 3605333
+ flags = 0
+ data = length 594, hash 86D1E249
+ sample 170:
+ time = 3626666
+ flags = 0
+ data = length 760, hash AF4B774F
+ sample 171:
+ time = 3648000
+ flags = 0
+ data = length 568, hash F4765276
+ sample 172:
+ time = 3669333
+ flags = 0
+ data = length 722, hash 2A72C44B
+ sample 173:
+ time = 3690666
+ flags = 0
+ data = length 602, hash 5D7135BB
+ sample 174:
+ time = 3712000
+ flags = 0
+ data = length 694, hash 8C5CE9CF
+ sample 175:
+ time = 3733333
+ flags = 0
+ data = length 725, hash 4EBFA7A8
+ sample 176:
+ time = 3754666
+ flags = 0
+ data = length 666, hash 2B1379B
+ sample 177:
+ time = 3776000
+ flags = 0
+ data = length 846, hash 57FC9178
+ sample 178:
+ time = 3797333
+ flags = 0
+ data = length 881, hash 19FDF109
+ sample 179:
+ time = 3818666
+ flags = 0
+ data = length 512, hash 49FD56DF
+ sample 180:
+ time = 3840000
+ flags = 0
+ data = length 840, hash FC78237B
+ sample 181:
+ time = 3861333
+ flags = 0
+ data = length 1075, hash 5031D568
+ sample 182:
+ time = 3882666
+ flags = 0
+ data = length 716, hash A509900D
+ sample 183:
+ time = 3904000
+ flags = 0
+ data = length 798, hash 386EB6B5
+ sample 184:
+ time = 3925333
+ flags = 0
+ data = length 969, hash 1E781925
+ sample 185:
+ time = 3946666
+ flags = 0
+ data = length 1444, hash F2DD1E7C
+ sample 186:
+ time = 3968000
+ flags = 0
+ data = length 399, hash 3FE1EAB6
+ sample 187:
+ time = 3989333
+ flags = 1
+ data = length 776, hash BEA73ED6
+ sample 188:
+ time = 4010666
+ flags = 0
+ data = length 875, hash 173C290C
+ sample 189:
+ time = 4032000
+ flags = 0
+ data = length 787, hash 531B9CB3
+ sample 190:
+ time = 4053333
+ flags = 0
+ data = length 737, hash 75CB4A48
+ sample 191:
+ time = 4074666
+ flags = 0
+ data = length 603, hash DDE525EE
+ sample 192:
+ time = 4096000
+ flags = 0
+ data = length 645, hash F4666418
+ sample 193:
+ time = 4117333
+ flags = 0
+ data = length 704, hash F7E18921
+ sample 194:
+ time = 4138666
+ flags = 0
+ data = length 802, hash 822433B5
+ sample 195:
+ time = 4160000
+ flags = 0
+ data = length 990, hash E4712448
+ sample 196:
+ time = 4181333
+ flags = 0
+ data = length 602, hash 3265AF8E
+ sample 197:
+ time = 4202666
+ flags = 0
+ data = length 790, hash 6EF432BA
+ sample 198:
+ time = 4224000
+ flags = 0
+ data = length 746, hash E20E7B36
+ sample 199:
+ time = 4245333
+ flags = 0
+ data = length 439, hash 8C32DDA0
+ sample 200:
+ time = 4266666
+ flags = 0
+ data = length 932, hash AF323520
+ sample 201:
+ time = 4288000
+ flags = 0
+ data = length 1003, hash 3D70121B
+ sample 202:
+ time = 4309333
+ flags = 0
+ data = length 1158, hash 1215442E
+ sample 203:
+ time = 4330666
+ flags = 0
+ data = length 1047, hash 2A517450
+ sample 204:
+ time = 4352000
+ flags = 0
+ data = length 1123, hash 33387B5F
+ sample 205:
+ time = 4373333
+ flags = 0
+ data = length 1033, hash D82CF575
+ sample 206:
+ time = 4394666
+ flags = 0
+ data = length 1009, hash 30DC6A02
+ sample 207:
+ time = 4416000
+ flags = 0
+ data = length 1033, hash 82127054
+ sample 208:
+ time = 4437333
+ flags = 0
+ data = length 761, hash 4A5EA11F
+ sample 209:
+ time = 4458666
+ flags = 0
+ data = length 708, hash 53FA04E4
+ sample 210:
+ time = 4480000
+ flags = 0
+ data = length 750, hash 44F541A6
+ sample 211:
+ time = 4501333
+ flags = 0
+ data = length 902, hash 6688117A
+ sample 212:
+ time = 4522666
+ flags = 0
+ data = length 716, hash A19D938D
+ sample 213:
+ time = 4544000
+ flags = 0
+ data = length 395, hash 4EF7E6DE
+ sample 214:
+ time = 4565333
+ flags = 0
+ data = length 677, hash 57DF6F41
+ sample 215:
+ time = 4586666
+ flags = 0
+ data = length 566, hash 515BD3F0
+ sample 216:
+ time = 4608000
+ flags = 0
+ data = length 772, hash 957617C9
+ sample 217:
+ time = 4629333
+ flags = 0
+ data = length 777, hash 6BB742A3
+ sample 218:
+ time = 4650666
+ flags = 0
+ data = length 672, hash 97BA98A3
+ sample 219:
+ time = 4672000
+ flags = 0
+ data = length 695, hash F8190CDE
+ sample 220:
+ time = 4693333
+ flags = 0
+ data = length 668, hash 6D62BE54
+ sample 221:
+ time = 4714666
+ flags = 0
+ data = length 662, hash 36D886CD
+ sample 222:
+ time = 4736000
+ flags = 0
+ data = length 678, hash 87772FCA
+ sample 223:
+ time = 4757333
+ flags = 0
+ data = length 946, hash BBFB4C98
+ sample 224:
+ time = 4778666
+ flags = 0
+ data = length 594, hash CEDCD36C
+ sample 225:
+ time = 4800000
+ flags = 0
+ data = length 499, hash 3B933D5B
+ sample 226:
+ time = 4821333
+ flags = 0
+ data = length 784, hash 97BC8486
+ sample 227:
+ time = 4842666
+ flags = 0
+ data = length 510, hash 9A082552
+ sample 228:
+ time = 4864000
+ flags = 0
+ data = length 741, hash E17DAE88
+ sample 229:
+ time = 4885333
+ flags = 0
+ data = length 656, hash C8CC5738
+ sample 230:
+ time = 4906666
+ flags = 0
+ data = length 672, hash 84C28F77
+ sample 231:
+ time = 4928000
+ flags = 0
+ data = length 559, hash B563D0ED
+ sample 232:
+ time = 4949333
+ flags = 0
+ data = length 1503, hash 183821B0
+ sample 233:
+ time = 4970666
+ flags = 0
+ data = length 393, hash D807573D
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_uhd.ts.1.dump b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_uhd.ts.1.dump
new file mode 100644
index 0000000000..1c4379b259
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_uhd.ts.1.dump
@@ -0,0 +1,661 @@
+seekMap:
+ isSeekable = true
+ duration = 4970666
+ getPosition(0) = [[timeUs=0, position=0]]
+ getPosition(1) = [[timeUs=1, position=0]]
+ getPosition(2485333) = [[timeUs=2485333, position=102149]]
+ getPosition(4970666) = [[timeUs=4970666, position=204487]]
+numberOfTracks = 1
+track 257:
+ total output bytes = 108399
+ sample count = 161
+ format 0:
+ id = 1/257
+ sampleMimeType = audio/vnd.dts.uhd;profile=p2
+ channelCount = 2
+ sampleRate = 48000
+ sample 0:
+ time = 1557333
+ flags = 0
+ data = length 7, hash 5EB61B7F
+ sample 1:
+ time = 1578666
+ flags = 0
+ data = length 7, hash 5EB61ADF
+ sample 2:
+ time = 1600000
+ flags = 0
+ data = length 7, hash 5EB61B9F
+ sample 3:
+ time = 1621333
+ flags = 0
+ data = length 7, hash 5EB61B5F
+ sample 4:
+ time = 1642666
+ flags = 0
+ data = length 7, hash 5EB61B1F
+ sample 5:
+ time = 1664000
+ flags = 0
+ data = length 7, hash 5EB61ABF
+ sample 6:
+ time = 1685333
+ flags = 0
+ data = length 7, hash 5EB61B3F
+ sample 7:
+ time = 1706666
+ flags = 0
+ data = length 7, hash 5EB61AFF
+ sample 8:
+ time = 1728000
+ flags = 0
+ data = length 7, hash 5EB61B7F
+ sample 9:
+ time = 1749333
+ flags = 0
+ data = length 7, hash 5EB61B9F
+ sample 10:
+ time = 1770666
+ flags = 0
+ data = length 7, hash 5EB61AFF
+ sample 11:
+ time = 1792000
+ flags = 0
+ data = length 7, hash 5EB61B7F
+ sample 12:
+ time = 1813333
+ flags = 0
+ data = length 7, hash 5EB61B3F
+ sample 13:
+ time = 1834666
+ flags = 0
+ data = length 7, hash 5EB61ABF
+ sample 14:
+ time = 1856000
+ flags = 0
+ data = length 7, hash 5EB61ABF
+ sample 15:
+ time = 1877333
+ flags = 0
+ data = length 7, hash 5EB61B7F
+ sample 16:
+ time = 1898666
+ flags = 0
+ data = length 7, hash 5EB61AFF
+ sample 17:
+ time = 1920000
+ flags = 0
+ data = length 7, hash 5EB61B9F
+ sample 18:
+ time = 1941333
+ flags = 0
+ data = length 7, hash 5EB61B01
+ sample 19:
+ time = 1962666
+ flags = 0
+ data = length 6, hash F289FFAF
+ sample 20:
+ time = 1984000
+ flags = 1
+ data = length 402, hash E60D79A1
+ sample 21:
+ time = 2005333
+ flags = 0
+ data = length 394, hash 585703B6
+ sample 22:
+ time = 2026666
+ flags = 0
+ data = length 394, hash 50CA225B
+ sample 23:
+ time = 2048000
+ flags = 0
+ data = length 395, hash E0229BF0
+ sample 24:
+ time = 2069333
+ flags = 0
+ data = length 501, hash F8930C9C
+ sample 25:
+ time = 2090666
+ flags = 0
+ data = length 667, hash C05CCFA2
+ sample 26:
+ time = 2112000
+ flags = 0
+ data = length 918, hash 5832371D
+ sample 27:
+ time = 2133333
+ flags = 0
+ data = length 1101, hash 1F97D86E
+ sample 28:
+ time = 2154666
+ flags = 0
+ data = length 1006, hash 974AC450
+ sample 29:
+ time = 2176000
+ flags = 0
+ data = length 1153, hash 22CA9C79
+ sample 30:
+ time = 2197333
+ flags = 0
+ data = length 959, hash 2011C476
+ sample 31:
+ time = 2218666
+ flags = 0
+ data = length 735, hash C2F6C1F9
+ sample 32:
+ time = 2240000
+ flags = 0
+ data = length 865, hash 394C4481
+ sample 33:
+ time = 2261333
+ flags = 0
+ data = length 825, hash 611B513C
+ sample 34:
+ time = 2282666
+ flags = 0
+ data = length 952, hash 5B24AEC2
+ sample 35:
+ time = 2304000
+ flags = 0
+ data = length 984, hash 172B469
+ sample 36:
+ time = 2325333
+ flags = 0
+ data = length 1010, hash D3BBA580
+ sample 37:
+ time = 2346666
+ flags = 0
+ data = length 1067, hash E09AD57F
+ sample 38:
+ time = 2368000
+ flags = 0
+ data = length 1060, hash 5332E90B
+ sample 39:
+ time = 2389333
+ flags = 0
+ data = length 991, hash 48B80B00
+ sample 40:
+ time = 2410666
+ flags = 0
+ data = length 873, hash 696FBD43
+ sample 41:
+ time = 2432000
+ flags = 0
+ data = length 810, hash 7D3D7B29
+ sample 42:
+ time = 2453333
+ flags = 0
+ data = length 897, hash D41D4CB7
+ sample 43:
+ time = 2474666
+ flags = 0
+ data = length 781, hash A589A312
+ sample 44:
+ time = 2496000
+ flags = 0
+ data = length 705, hash FDC5698B
+ sample 45:
+ time = 2517333
+ flags = 0
+ data = length 608, hash F929EDA6
+ sample 46:
+ time = 2538666
+ flags = 0
+ data = length 546, hash A141CD5E
+ sample 47:
+ time = 2560000
+ flags = 0
+ data = length 639, hash BABD5C9F
+ sample 48:
+ time = 2581333
+ flags = 0
+ data = length 561, hash B1AF4D92
+ sample 49:
+ time = 2602666
+ flags = 0
+ data = length 529, hash D0E0EF42
+ sample 50:
+ time = 2624000
+ flags = 0
+ data = length 441, hash E0B1DB1
+ sample 51:
+ time = 2645333
+ flags = 0
+ data = length 393, hash 5A34D1B0
+ sample 52:
+ time = 2666666
+ flags = 0
+ data = length 393, hash B792EA44
+ sample 53:
+ time = 2688000
+ flags = 0
+ data = length 393, hash 7CCE0C94
+ sample 54:
+ time = 2709333
+ flags = 0
+ data = length 393, hash C80E41E0
+ sample 55:
+ time = 2730666
+ flags = 0
+ data = length 393, hash 2C5B4860
+ sample 56:
+ time = 2752000
+ flags = 0
+ data = length 393, hash 9930B5F0
+ sample 57:
+ time = 2773333
+ flags = 0
+ data = length 393, hash B78D1FDA
+ sample 58:
+ time = 2794666
+ flags = 0
+ data = length 393, hash 817AB352
+ sample 59:
+ time = 2816000
+ flags = 0
+ data = length 393, hash EA7D83DF
+ sample 60:
+ time = 2837333
+ flags = 0
+ data = length 393, hash E76873B0
+ sample 61:
+ time = 2858666
+ flags = 0
+ data = length 393, hash 2F48A520
+ sample 62:
+ time = 2880000
+ flags = 0
+ data = length 393, hash C0CBB3EF
+ sample 63:
+ time = 2901333
+ flags = 0
+ data = length 393, hash 255B0E50
+ sample 64:
+ time = 2922666
+ flags = 0
+ data = length 393, hash 9A49C63D
+ sample 65:
+ time = 2944000
+ flags = 0
+ data = length 1516, hash 4994C5B
+ sample 66:
+ time = 2965333
+ flags = 0
+ data = length 1519, hash 5514C06F
+ sample 67:
+ time = 2986666
+ flags = 0
+ data = length 1007, hash F994B3FC
+ sample 68:
+ time = 3008000
+ flags = 0
+ data = length 946, hash 7714E7B1
+ sample 69:
+ time = 3029333
+ flags = 0
+ data = length 985, hash C0E4D841
+ sample 70:
+ time = 3050666
+ flags = 0
+ data = length 1018, hash A18F6981
+ sample 71:
+ time = 3072000
+ flags = 0
+ data = length 790, hash 9F884211
+ sample 72:
+ time = 3093333
+ flags = 0
+ data = length 809, hash 1E0978C9
+ sample 73:
+ time = 3114666
+ flags = 0
+ data = length 791, hash 9BC34342
+ sample 74:
+ time = 3136000
+ flags = 0
+ data = length 806, hash C64EDB12
+ sample 75:
+ time = 3157333
+ flags = 0
+ data = length 757, hash 6C971B85
+ sample 76:
+ time = 3178666
+ flags = 0
+ data = length 950, hash 5509778D
+ sample 77:
+ time = 3200000
+ flags = 0
+ data = length 713, hash 2BD954C8
+ sample 78:
+ time = 3221333
+ flags = 0
+ data = length 800, hash 1C71F2EF
+ sample 79:
+ time = 3242666
+ flags = 0
+ data = length 804, hash BFCCE7C
+ sample 80:
+ time = 3264000
+ flags = 0
+ data = length 876, hash AB1137D9
+ sample 81:
+ time = 3285333
+ flags = 0
+ data = length 957, hash 1CC9B8CA
+ sample 82:
+ time = 3306666
+ flags = 0
+ data = length 563, hash A6FF9D2B
+ sample 83:
+ time = 3328000
+ flags = 0
+ data = length 796, hash B0110276
+ sample 84:
+ time = 3349333
+ flags = 0
+ data = length 863, hash 55EDF24F
+ sample 85:
+ time = 3370666
+ flags = 0
+ data = length 701, hash 3AE3C48F
+ sample 86:
+ time = 3392000
+ flags = 0
+ data = length 934, hash 2CC1C6E9
+ sample 87:
+ time = 3413333
+ flags = 0
+ data = length 967, hash 34E61D20
+ sample 88:
+ time = 3434666
+ flags = 0
+ data = length 1518, hash C0EC5B50
+ sample 89:
+ time = 3456000
+ flags = 0
+ data = length 1474, hash 6EC36C24
+ sample 90:
+ time = 3477333
+ flags = 0
+ data = length 1475, hash 6F1FD2AB
+ sample 91:
+ time = 3498666
+ flags = 0
+ data = length 1451, hash B58F4D31
+ sample 92:
+ time = 3520000
+ flags = 0
+ data = length 526, hash FC424B78
+ sample 93:
+ time = 3541333
+ flags = 0
+ data = length 598, hash 4BDB2753
+ sample 94:
+ time = 3562666
+ flags = 0
+ data = length 627, hash 48327C83
+ sample 95:
+ time = 3584000
+ flags = 0
+ data = length 551, hash 691D6CB2
+ sample 96:
+ time = 3605333
+ flags = 0
+ data = length 594, hash 86D1E249
+ sample 97:
+ time = 3626666
+ flags = 0
+ data = length 760, hash AF4B774F
+ sample 98:
+ time = 3648000
+ flags = 0
+ data = length 568, hash F4765276
+ sample 99:
+ time = 3669333
+ flags = 0
+ data = length 722, hash 2A72C44B
+ sample 100:
+ time = 3690666
+ flags = 0
+ data = length 602, hash 5D7135BB
+ sample 101:
+ time = 3712000
+ flags = 0
+ data = length 694, hash 8C5CE9CF
+ sample 102:
+ time = 3733333
+ flags = 0
+ data = length 725, hash 4EBFA7A8
+ sample 103:
+ time = 3754666
+ flags = 0
+ data = length 666, hash 2B1379B
+ sample 104:
+ time = 3776000
+ flags = 0
+ data = length 846, hash 57FC9178
+ sample 105:
+ time = 3797333
+ flags = 0
+ data = length 881, hash 19FDF109
+ sample 106:
+ time = 3818666
+ flags = 0
+ data = length 512, hash 49FD56DF
+ sample 107:
+ time = 3840000
+ flags = 0
+ data = length 840, hash FC78237B
+ sample 108:
+ time = 3861333
+ flags = 0
+ data = length 1075, hash 5031D568
+ sample 109:
+ time = 3882666
+ flags = 0
+ data = length 716, hash A509900D
+ sample 110:
+ time = 3904000
+ flags = 0
+ data = length 798, hash 386EB6B5
+ sample 111:
+ time = 3925333
+ flags = 0
+ data = length 969, hash 1E781925
+ sample 112:
+ time = 3946666
+ flags = 0
+ data = length 1444, hash F2DD1E7C
+ sample 113:
+ time = 3968000
+ flags = 0
+ data = length 399, hash 3FE1EAB6
+ sample 114:
+ time = 3989333
+ flags = 1
+ data = length 776, hash BEA73ED6
+ sample 115:
+ time = 4010666
+ flags = 0
+ data = length 875, hash 173C290C
+ sample 116:
+ time = 4032000
+ flags = 0
+ data = length 787, hash 531B9CB3
+ sample 117:
+ time = 4053333
+ flags = 0
+ data = length 737, hash 75CB4A48
+ sample 118:
+ time = 4074666
+ flags = 0
+ data = length 603, hash DDE525EE
+ sample 119:
+ time = 4096000
+ flags = 0
+ data = length 645, hash F4666418
+ sample 120:
+ time = 4117333
+ flags = 0
+ data = length 704, hash F7E18921
+ sample 121:
+ time = 4138666
+ flags = 0
+ data = length 802, hash 822433B5
+ sample 122:
+ time = 4160000
+ flags = 0
+ data = length 990, hash E4712448
+ sample 123:
+ time = 4181333
+ flags = 0
+ data = length 602, hash 3265AF8E
+ sample 124:
+ time = 4202666
+ flags = 0
+ data = length 790, hash 6EF432BA
+ sample 125:
+ time = 4224000
+ flags = 0
+ data = length 746, hash E20E7B36
+ sample 126:
+ time = 4245333
+ flags = 0
+ data = length 439, hash 8C32DDA0
+ sample 127:
+ time = 4266666
+ flags = 0
+ data = length 932, hash AF323520
+ sample 128:
+ time = 4288000
+ flags = 0
+ data = length 1003, hash 3D70121B
+ sample 129:
+ time = 4309333
+ flags = 0
+ data = length 1158, hash 1215442E
+ sample 130:
+ time = 4330666
+ flags = 0
+ data = length 1047, hash 2A517450
+ sample 131:
+ time = 4352000
+ flags = 0
+ data = length 1123, hash 33387B5F
+ sample 132:
+ time = 4373333
+ flags = 0
+ data = length 1033, hash D82CF575
+ sample 133:
+ time = 4394666
+ flags = 0
+ data = length 1009, hash 30DC6A02
+ sample 134:
+ time = 4416000
+ flags = 0
+ data = length 1033, hash 82127054
+ sample 135:
+ time = 4437333
+ flags = 0
+ data = length 761, hash 4A5EA11F
+ sample 136:
+ time = 4458666
+ flags = 0
+ data = length 708, hash 53FA04E4
+ sample 137:
+ time = 4480000
+ flags = 0
+ data = length 750, hash 44F541A6
+ sample 138:
+ time = 4501333
+ flags = 0
+ data = length 902, hash 6688117A
+ sample 139:
+ time = 4522666
+ flags = 0
+ data = length 716, hash A19D938D
+ sample 140:
+ time = 4544000
+ flags = 0
+ data = length 395, hash 4EF7E6DE
+ sample 141:
+ time = 4565333
+ flags = 0
+ data = length 677, hash 57DF6F41
+ sample 142:
+ time = 4586666
+ flags = 0
+ data = length 566, hash 515BD3F0
+ sample 143:
+ time = 4608000
+ flags = 0
+ data = length 772, hash 957617C9
+ sample 144:
+ time = 4629333
+ flags = 0
+ data = length 777, hash 6BB742A3
+ sample 145:
+ time = 4650666
+ flags = 0
+ data = length 672, hash 97BA98A3
+ sample 146:
+ time = 4672000
+ flags = 0
+ data = length 695, hash F8190CDE
+ sample 147:
+ time = 4693333
+ flags = 0
+ data = length 668, hash 6D62BE54
+ sample 148:
+ time = 4714666
+ flags = 0
+ data = length 662, hash 36D886CD
+ sample 149:
+ time = 4736000
+ flags = 0
+ data = length 678, hash 87772FCA
+ sample 150:
+ time = 4757333
+ flags = 0
+ data = length 946, hash BBFB4C98
+ sample 151:
+ time = 4778666
+ flags = 0
+ data = length 594, hash CEDCD36C
+ sample 152:
+ time = 4800000
+ flags = 0
+ data = length 499, hash 3B933D5B
+ sample 153:
+ time = 4821333
+ flags = 0
+ data = length 784, hash 97BC8486
+ sample 154:
+ time = 4842666
+ flags = 0
+ data = length 510, hash 9A082552
+ sample 155:
+ time = 4864000
+ flags = 0
+ data = length 741, hash E17DAE88
+ sample 156:
+ time = 4885333
+ flags = 0
+ data = length 656, hash C8CC5738
+ sample 157:
+ time = 4906666
+ flags = 0
+ data = length 672, hash 84C28F77
+ sample 158:
+ time = 4928000
+ flags = 0
+ data = length 559, hash B563D0ED
+ sample 159:
+ time = 4949333
+ flags = 0
+ data = length 1503, hash 183821B0
+ sample 160:
+ time = 4970666
+ flags = 0
+ data = length 393, hash D807573D
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_uhd.ts.2.dump b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_uhd.ts.2.dump
new file mode 100644
index 0000000000..d4f5dcac85
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_uhd.ts.2.dump
@@ -0,0 +1,349 @@
+seekMap:
+ isSeekable = true
+ duration = 4970666
+ getPosition(0) = [[timeUs=0, position=0]]
+ getPosition(1) = [[timeUs=1, position=0]]
+ getPosition(2485333) = [[timeUs=2485333, position=102149]]
+ getPosition(4970666) = [[timeUs=4970666, position=204487]]
+numberOfTracks = 1
+track 257:
+ total output bytes = 36340
+ sample count = 83
+ format 0:
+ id = 1/257
+ sampleMimeType = audio/vnd.dts.uhd;profile=p2
+ channelCount = 2
+ sampleRate = 48000
+ sample 0:
+ time = 3221333
+ flags = 0
+ data = length 7, hash 5EB61B9D
+ sample 1:
+ time = 3242666
+ flags = 0
+ data = length 7, hash 5EB61B1D
+ sample 2:
+ time = 3264000
+ flags = 0
+ data = length 7, hash 5EB61C34
+ sample 3:
+ time = 3285333
+ flags = 0
+ data = length 7, hash 5EB61D8A
+ sample 4:
+ time = 3306666
+ flags = 0
+ data = length 7, hash 5EB6175B
+ sample 5:
+ time = 3328000
+ flags = 0
+ data = length 7, hash 5EB61AFE
+ sample 6:
+ time = 3349333
+ flags = 0
+ data = length 7, hash 5EB61C75
+ sample 7:
+ time = 3370666
+ flags = 0
+ data = length 7, hash 5EB619AA
+ sample 8:
+ time = 3392000
+ flags = 0
+ data = length 7, hash 5EB61D4D
+ sample 9:
+ time = 3413333
+ flags = 0
+ data = length 7, hash 5EB61E08
+ sample 10:
+ time = 3434666
+ flags = 0
+ data = length 7, hash 5EB62624
+ sample 11:
+ time = 3456000
+ flags = 0
+ data = length 7, hash 5EB62609
+ sample 12:
+ time = 3477333
+ flags = 0
+ data = length 7, hash 5EB62529
+ sample 13:
+ time = 3498666
+ flags = 0
+ data = length 7, hash 5EB624CC
+ sample 14:
+ time = 3520000
+ flags = 0
+ data = length 7, hash 5EB61720
+ sample 15:
+ time = 3541333
+ flags = 0
+ data = length 7, hash 5EB61837
+ sample 16:
+ time = 3562666
+ flags = 0
+ data = length 7, hash 5EB61853
+ sample 17:
+ time = 3584000
+ flags = 0
+ data = length 7, hash 5EB617BC
+ sample 18:
+ time = 3605333
+ flags = 0
+ data = length 7, hash 5EB618B7
+ sample 19:
+ time = 3626666
+ flags = 0
+ data = length 7, hash 5EB61B02
+ sample 20:
+ time = 3648000
+ flags = 0
+ data = length 7, hash 5EB6181A
+ sample 21:
+ time = 3669333
+ flags = 0
+ data = length 7, hash 5EB61AA7
+ sample 22:
+ time = 3690666
+ flags = 0
+ data = length 7, hash 5EB618D6
+ sample 23:
+ time = 3712000
+ flags = 0
+ data = length 7, hash 5EB619AB
+ sample 24:
+ time = 3733333
+ flags = 0
+ data = length 7, hash 5EB61A07
+ sample 25:
+ time = 3754666
+ flags = 0
+ data = length 7, hash 5EB619CE
+ sample 26:
+ time = 3776000
+ flags = 0
+ data = length 7, hash 5EB61BF8
+ sample 27:
+ time = 3797333
+ flags = 0
+ data = length 7, hash 5EB61CF3
+ sample 28:
+ time = 3818666
+ flags = 0
+ data = length 6, hash F28A001F
+ sample 29:
+ time = 3840000
+ flags = 0
+ data = length 7, hash 5EB61C38
+ sample 30:
+ time = 3861333
+ flags = 0
+ data = length 7, hash 5EB61F1B
+ sample 31:
+ time = 3882666
+ flags = 0
+ data = length 7, hash 5EB619C8
+ sample 32:
+ time = 3904000
+ flags = 0
+ data = length 7, hash 5EB61B3E
+ sample 33:
+ time = 3925333
+ flags = 0
+ data = length 7, hash 5EB61E48
+ sample 34:
+ time = 3946666
+ flags = 0
+ data = length 7, hash 5EB624CD
+ sample 35:
+ time = 3968000
+ flags = 0
+ data = length 6, hash F289FFAE
+ sample 36:
+ time = 3989333
+ flags = 1
+ data = length 776, hash BEA73ED6
+ sample 37:
+ time = 4010666
+ flags = 0
+ data = length 875, hash 173C290C
+ sample 38:
+ time = 4032000
+ flags = 0
+ data = length 787, hash 531B9CB3
+ sample 39:
+ time = 4053333
+ flags = 0
+ data = length 737, hash 75CB4A48
+ sample 40:
+ time = 4074666
+ flags = 0
+ data = length 603, hash DDE525EE
+ sample 41:
+ time = 4096000
+ flags = 0
+ data = length 645, hash F4666418
+ sample 42:
+ time = 4117333
+ flags = 0
+ data = length 704, hash F7E18921
+ sample 43:
+ time = 4138666
+ flags = 0
+ data = length 802, hash 822433B5
+ sample 44:
+ time = 4160000
+ flags = 0
+ data = length 990, hash E4712448
+ sample 45:
+ time = 4181333
+ flags = 0
+ data = length 602, hash 3265AF8E
+ sample 46:
+ time = 4202666
+ flags = 0
+ data = length 790, hash 6EF432BA
+ sample 47:
+ time = 4224000
+ flags = 0
+ data = length 746, hash E20E7B36
+ sample 48:
+ time = 4245333
+ flags = 0
+ data = length 439, hash 8C32DDA0
+ sample 49:
+ time = 4266666
+ flags = 0
+ data = length 932, hash AF323520
+ sample 50:
+ time = 4288000
+ flags = 0
+ data = length 1003, hash 3D70121B
+ sample 51:
+ time = 4309333
+ flags = 0
+ data = length 1158, hash 1215442E
+ sample 52:
+ time = 4330666
+ flags = 0
+ data = length 1047, hash 2A517450
+ sample 53:
+ time = 4352000
+ flags = 0
+ data = length 1123, hash 33387B5F
+ sample 54:
+ time = 4373333
+ flags = 0
+ data = length 1033, hash D82CF575
+ sample 55:
+ time = 4394666
+ flags = 0
+ data = length 1009, hash 30DC6A02
+ sample 56:
+ time = 4416000
+ flags = 0
+ data = length 1033, hash 82127054
+ sample 57:
+ time = 4437333
+ flags = 0
+ data = length 761, hash 4A5EA11F
+ sample 58:
+ time = 4458666
+ flags = 0
+ data = length 708, hash 53FA04E4
+ sample 59:
+ time = 4480000
+ flags = 0
+ data = length 750, hash 44F541A6
+ sample 60:
+ time = 4501333
+ flags = 0
+ data = length 902, hash 6688117A
+ sample 61:
+ time = 4522666
+ flags = 0
+ data = length 716, hash A19D938D
+ sample 62:
+ time = 4544000
+ flags = 0
+ data = length 395, hash 4EF7E6DE
+ sample 63:
+ time = 4565333
+ flags = 0
+ data = length 677, hash 57DF6F41
+ sample 64:
+ time = 4586666
+ flags = 0
+ data = length 566, hash 515BD3F0
+ sample 65:
+ time = 4608000
+ flags = 0
+ data = length 772, hash 957617C9
+ sample 66:
+ time = 4629333
+ flags = 0
+ data = length 777, hash 6BB742A3
+ sample 67:
+ time = 4650666
+ flags = 0
+ data = length 672, hash 97BA98A3
+ sample 68:
+ time = 4672000
+ flags = 0
+ data = length 695, hash F8190CDE
+ sample 69:
+ time = 4693333
+ flags = 0
+ data = length 668, hash 6D62BE54
+ sample 70:
+ time = 4714666
+ flags = 0
+ data = length 662, hash 36D886CD
+ sample 71:
+ time = 4736000
+ flags = 0
+ data = length 678, hash 87772FCA
+ sample 72:
+ time = 4757333
+ flags = 0
+ data = length 946, hash BBFB4C98
+ sample 73:
+ time = 4778666
+ flags = 0
+ data = length 594, hash CEDCD36C
+ sample 74:
+ time = 4800000
+ flags = 0
+ data = length 499, hash 3B933D5B
+ sample 75:
+ time = 4821333
+ flags = 0
+ data = length 784, hash 97BC8486
+ sample 76:
+ time = 4842666
+ flags = 0
+ data = length 510, hash 9A082552
+ sample 77:
+ time = 4864000
+ flags = 0
+ data = length 741, hash E17DAE88
+ sample 78:
+ time = 4885333
+ flags = 0
+ data = length 656, hash C8CC5738
+ sample 79:
+ time = 4906666
+ flags = 0
+ data = length 672, hash 84C28F77
+ sample 80:
+ time = 4928000
+ flags = 0
+ data = length 559, hash B563D0ED
+ sample 81:
+ time = 4949333
+ flags = 0
+ data = length 1503, hash 183821B0
+ sample 82:
+ time = 4970666
+ flags = 0
+ data = length 393, hash D807573D
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_uhd.ts.3.dump b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_uhd.ts.3.dump
new file mode 100644
index 0000000000..7250b07952
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_uhd.ts.3.dump
@@ -0,0 +1,37 @@
+seekMap:
+ isSeekable = true
+ duration = 4970666
+ getPosition(0) = [[timeUs=0, position=0]]
+ getPosition(1) = [[timeUs=1, position=0]]
+ getPosition(2485333) = [[timeUs=2485333, position=102149]]
+ getPosition(4970666) = [[timeUs=4970666, position=204487]]
+numberOfTracks = 1
+track 257:
+ total output bytes = 34
+ sample count = 5
+ format 0:
+ id = 1/257
+ sampleMimeType = audio/vnd.dts.uhd;profile=p2
+ channelCount = 2
+ sampleRate = 48000
+ sample 0:
+ time = 4885333
+ flags = 0
+ data = length 7, hash 5EB6196F
+ sample 1:
+ time = 4906666
+ flags = 0
+ data = length 7, hash 5EB619AD
+ sample 2:
+ time = 4928000
+ flags = 0
+ data = length 7, hash 5EB617DB
+ sample 3:
+ time = 4949333
+ flags = 0
+ data = length 7, hash 5EB62625
+ sample 4:
+ time = 4970666
+ flags = 0
+ data = length 6, hash F289FFA8
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_uhd.ts.unknown_length.dump b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_uhd.ts.unknown_length.dump
new file mode 100644
index 0000000000..0900c65dc1
--- /dev/null
+++ b/libraries/test_data/src/test/assets/extractordumps/ts/sample_dts_uhd.ts.unknown_length.dump
@@ -0,0 +1,950 @@
+seekMap:
+ isSeekable = false
+ duration = UNSET TIME
+ getPosition(0) = [[timeUs=0, position=0]]
+numberOfTracks = 1
+track 257:
+ total output bytes = 179682
+ sample count = 234
+ format 0:
+ id = 1/257
+ sampleMimeType = audio/vnd.dts.uhd;profile=p2
+ channelCount = 2
+ sampleRate = 48000
+ sample 0:
+ time = 0
+ flags = 1
+ data = length 776, hash E68E7565
+ sample 1:
+ time = 21333
+ flags = 0
+ data = length 765, hash 713DA83C
+ sample 2:
+ time = 42666
+ flags = 0
+ data = length 771, hash E672DC
+ sample 3:
+ time = 64000
+ flags = 0
+ data = length 769, hash 83F90436
+ sample 4:
+ time = 85333
+ flags = 0
+ data = length 765, hash 5C8A17D1
+ sample 5:
+ time = 106666
+ flags = 0
+ data = length 771, hash 5528EC74
+ sample 6:
+ time = 128000
+ flags = 0
+ data = length 767, hash 954FC4B5
+ sample 7:
+ time = 149333
+ flags = 0
+ data = length 767, hash 5C2089BB
+ sample 8:
+ time = 170666
+ flags = 0
+ data = length 771, hash 21AF360B
+ sample 9:
+ time = 192000
+ flags = 0
+ data = length 766, hash 2C363E9B
+ sample 10:
+ time = 213333
+ flags = 0
+ data = length 767, hash 812E9BF7
+ sample 11:
+ time = 234666
+ flags = 0
+ data = length 770, hash ED9D5378
+ sample 12:
+ time = 256000
+ flags = 0
+ data = length 769, hash FBF9DD0E
+ sample 13:
+ time = 277333
+ flags = 0
+ data = length 767, hash 5E7822E9
+ sample 14:
+ time = 298666
+ flags = 0
+ data = length 770, hash 97EDBA77
+ sample 15:
+ time = 320000
+ flags = 0
+ data = length 767, hash 1739FF77
+ sample 16:
+ time = 341333
+ flags = 0
+ data = length 766, hash 99225978
+ sample 17:
+ time = 362666
+ flags = 0
+ data = length 772, hash 1971320D
+ sample 18:
+ time = 384000
+ flags = 0
+ data = length 768, hash F8C4F6A2
+ sample 19:
+ time = 405333
+ flags = 0
+ data = length 765, hash 225434F4
+ sample 20:
+ time = 426666
+ flags = 0
+ data = length 770, hash E232FA0D
+ sample 21:
+ time = 448000
+ flags = 0
+ data = length 767, hash 721418FA
+ sample 22:
+ time = 469333
+ flags = 0
+ data = length 768, hash E52E3AD0
+ sample 23:
+ time = 490666
+ flags = 0
+ data = length 772, hash 9D0F9C8C
+ sample 24:
+ time = 512000
+ flags = 0
+ data = length 767, hash EAFEDC
+ sample 25:
+ time = 533333
+ flags = 0
+ data = length 766, hash CAFCB522
+ sample 26:
+ time = 554666
+ flags = 0
+ data = length 770, hash EB1806AF
+ sample 27:
+ time = 576000
+ flags = 0
+ data = length 768, hash F022F870
+ sample 28:
+ time = 597333
+ flags = 0
+ data = length 767, hash 2DB31DD6
+ sample 29:
+ time = 618666
+ flags = 0
+ data = length 770, hash 3168DE65
+ sample 30:
+ time = 640000
+ flags = 0
+ data = length 767, hash 1D25591B
+ sample 31:
+ time = 661333
+ flags = 0
+ data = length 766, hash 2DB4AF54
+ sample 32:
+ time = 682666
+ flags = 0
+ data = length 772, hash 9B9176A8
+ sample 33:
+ time = 704000
+ flags = 0
+ data = length 768, hash F49BD7C2
+ sample 34:
+ time = 725333
+ flags = 0
+ data = length 765, hash 4D1A1A5B
+ sample 35:
+ time = 746666
+ flags = 0
+ data = length 771, hash EED28144
+ sample 36:
+ time = 768000
+ flags = 0
+ data = length 767, hash DE09C384
+ sample 37:
+ time = 789333
+ flags = 0
+ data = length 767, hash 5B154F22
+ sample 38:
+ time = 810666
+ flags = 0
+ data = length 772, hash 7621AB2B
+ sample 39:
+ time = 832000
+ flags = 0
+ data = length 767, hash 3B503329
+ sample 40:
+ time = 853333
+ flags = 0
+ data = length 766, hash 6D5F86F0
+ sample 41:
+ time = 874666
+ flags = 0
+ data = length 770, hash 122B33CF
+ sample 42:
+ time = 896000
+ flags = 0
+ data = length 769, hash 701BED85
+ sample 43:
+ time = 917333
+ flags = 0
+ data = length 767, hash 66F75279
+ sample 44:
+ time = 938666
+ flags = 0
+ data = length 769, hash 8EB616E3
+ sample 45:
+ time = 960000
+ flags = 0
+ data = length 767, hash C04E8FCB
+ sample 46:
+ time = 981333
+ flags = 0
+ data = length 765, hash 568E8728
+ sample 47:
+ time = 1002666
+ flags = 0
+ data = length 772, hash C23993F0
+ sample 48:
+ time = 1024000
+ flags = 0
+ data = length 768, hash 518ACD0D
+ sample 49:
+ time = 1045333
+ flags = 0
+ data = length 765, hash 297ACB8E
+ sample 50:
+ time = 1066666
+ flags = 0
+ data = length 770, hash 676ED3C1
+ sample 51:
+ time = 1088000
+ flags = 0
+ data = length 767, hash 836598AA
+ sample 52:
+ time = 1109333
+ flags = 0
+ data = length 767, hash F1536245
+ sample 53:
+ time = 1130666
+ flags = 0
+ data = length 772, hash 12AC3BCE
+ sample 54:
+ time = 1152000
+ flags = 0
+ data = length 766, hash 9948C9C
+ sample 55:
+ time = 1173333
+ flags = 0
+ data = length 766, hash B42ADF4E
+ sample 56:
+ time = 1194666
+ flags = 0
+ data = length 770, hash 67AC576F
+ sample 57:
+ time = 1216000
+ flags = 0
+ data = length 769, hash B843E663
+ sample 58:
+ time = 1237333
+ flags = 0
+ data = length 767, hash 432AD19
+ sample 59:
+ time = 1258666
+ flags = 0
+ data = length 770, hash 14BA5FE6
+ sample 60:
+ time = 1280000
+ flags = 0
+ data = length 768, hash A0D32F30
+ sample 61:
+ time = 1301333
+ flags = 0
+ data = length 765, hash 4BF180A9
+ sample 62:
+ time = 1322666
+ flags = 0
+ data = length 772, hash 1C613DF7
+ sample 63:
+ time = 1344000
+ flags = 0
+ data = length 768, hash F30F6A09
+ sample 64:
+ time = 1365333
+ flags = 0
+ data = length 765, hash D40AC240
+ sample 65:
+ time = 1386666
+ flags = 0
+ data = length 770, hash 1E64D8FE
+ sample 66:
+ time = 1408000
+ flags = 0
+ data = length 767, hash 5DFE9BC3
+ sample 67:
+ time = 1429333
+ flags = 0
+ data = length 767, hash 19A018BD
+ sample 68:
+ time = 1450666
+ flags = 0
+ data = length 772, hash 363BF537
+ sample 69:
+ time = 1472000
+ flags = 0
+ data = length 766, hash 4832AF5B
+ sample 70:
+ time = 1493333
+ flags = 0
+ data = length 766, hash 3CBED44A
+ sample 71:
+ time = 1514666
+ flags = 0
+ data = length 771, hash C5E800AD
+ sample 72:
+ time = 1536000
+ flags = 0
+ data = length 786, hash DA64F1EE
+ sample 73:
+ time = 1557333
+ flags = 0
+ data = length 785, hash 4771990A
+ sample 74:
+ time = 1578666
+ flags = 0
+ data = length 788, hash CBB53C84
+ sample 75:
+ time = 1600000
+ flags = 0
+ data = length 786, hash AF107053
+ sample 76:
+ time = 1621333
+ flags = 0
+ data = length 784, hash 7418BBD7
+ sample 77:
+ time = 1642666
+ flags = 0
+ data = length 790, hash 35A5E570
+ sample 78:
+ time = 1664000
+ flags = 0
+ data = length 787, hash 4F662158
+ sample 79:
+ time = 1685333
+ flags = 0
+ data = length 783, hash A574B045
+ sample 80:
+ time = 1706666
+ flags = 0
+ data = length 789, hash 211311A9
+ sample 81:
+ time = 1728000
+ flags = 0
+ data = length 785, hash 4A7E6F21
+ sample 82:
+ time = 1749333
+ flags = 0
+ data = length 786, hash DE8047C6
+ sample 83:
+ time = 1770666
+ flags = 0
+ data = length 789, hash E778E75A
+ sample 84:
+ time = 1792000
+ flags = 0
+ data = length 785, hash AD3A50F8
+ sample 85:
+ time = 1813333
+ flags = 0
+ data = length 783, hash 6DCEAA5C
+ sample 86:
+ time = 1834666
+ flags = 0
+ data = length 787, hash D5E2A255
+ sample 87:
+ time = 1856000
+ flags = 0
+ data = length 787, hash E9138642
+ sample 88:
+ time = 1877333
+ flags = 0
+ data = length 785, hash B2D94BAF
+ sample 89:
+ time = 1898666
+ flags = 0
+ data = length 789, hash F0F3BBDB
+ sample 90:
+ time = 1920000
+ flags = 0
+ data = length 786, hash B0D62A20
+ sample 91:
+ time = 1941333
+ flags = 0
+ data = length 767, hash 710CB0E4
+ sample 92:
+ time = 1962666
+ flags = 0
+ data = length 400, hash 8A0182CB
+ sample 93:
+ time = 1984000
+ flags = 1
+ data = length 402, hash E60D79A1
+ sample 94:
+ time = 2005333
+ flags = 0
+ data = length 394, hash 585703B6
+ sample 95:
+ time = 2026666
+ flags = 0
+ data = length 394, hash 50CA225B
+ sample 96:
+ time = 2048000
+ flags = 0
+ data = length 395, hash E0229BF0
+ sample 97:
+ time = 2069333
+ flags = 0
+ data = length 501, hash F8930C9C
+ sample 98:
+ time = 2090666
+ flags = 0
+ data = length 667, hash C05CCFA2
+ sample 99:
+ time = 2112000
+ flags = 0
+ data = length 918, hash 5832371D
+ sample 100:
+ time = 2133333
+ flags = 0
+ data = length 1101, hash 1F97D86E
+ sample 101:
+ time = 2154666
+ flags = 0
+ data = length 1006, hash 974AC450
+ sample 102:
+ time = 2176000
+ flags = 0
+ data = length 1153, hash 22CA9C79
+ sample 103:
+ time = 2197333
+ flags = 0
+ data = length 959, hash 2011C476
+ sample 104:
+ time = 2218666
+ flags = 0
+ data = length 735, hash C2F6C1F9
+ sample 105:
+ time = 2240000
+ flags = 0
+ data = length 865, hash 394C4481
+ sample 106:
+ time = 2261333
+ flags = 0
+ data = length 825, hash 611B513C
+ sample 107:
+ time = 2282666
+ flags = 0
+ data = length 952, hash 5B24AEC2
+ sample 108:
+ time = 2304000
+ flags = 0
+ data = length 984, hash 172B469
+ sample 109:
+ time = 2325333
+ flags = 0
+ data = length 1010, hash D3BBA580
+ sample 110:
+ time = 2346666
+ flags = 0
+ data = length 1067, hash E09AD57F
+ sample 111:
+ time = 2368000
+ flags = 0
+ data = length 1060, hash 5332E90B
+ sample 112:
+ time = 2389333
+ flags = 0
+ data = length 991, hash 48B80B00
+ sample 113:
+ time = 2410666
+ flags = 0
+ data = length 873, hash 696FBD43
+ sample 114:
+ time = 2432000
+ flags = 0
+ data = length 810, hash 7D3D7B29
+ sample 115:
+ time = 2453333
+ flags = 0
+ data = length 897, hash D41D4CB7
+ sample 116:
+ time = 2474666
+ flags = 0
+ data = length 781, hash A589A312
+ sample 117:
+ time = 2496000
+ flags = 0
+ data = length 705, hash FDC5698B
+ sample 118:
+ time = 2517333
+ flags = 0
+ data = length 608, hash F929EDA6
+ sample 119:
+ time = 2538666
+ flags = 0
+ data = length 546, hash A141CD5E
+ sample 120:
+ time = 2560000
+ flags = 0
+ data = length 639, hash BABD5C9F
+ sample 121:
+ time = 2581333
+ flags = 0
+ data = length 561, hash B1AF4D92
+ sample 122:
+ time = 2602666
+ flags = 0
+ data = length 529, hash D0E0EF42
+ sample 123:
+ time = 2624000
+ flags = 0
+ data = length 441, hash E0B1DB1
+ sample 124:
+ time = 2645333
+ flags = 0
+ data = length 393, hash 5A34D1B0
+ sample 125:
+ time = 2666666
+ flags = 0
+ data = length 393, hash B792EA44
+ sample 126:
+ time = 2688000
+ flags = 0
+ data = length 393, hash 7CCE0C94
+ sample 127:
+ time = 2709333
+ flags = 0
+ data = length 393, hash C80E41E0
+ sample 128:
+ time = 2730666
+ flags = 0
+ data = length 393, hash 2C5B4860
+ sample 129:
+ time = 2752000
+ flags = 0
+ data = length 393, hash 9930B5F0
+ sample 130:
+ time = 2773333
+ flags = 0
+ data = length 393, hash B78D1FDA
+ sample 131:
+ time = 2794666
+ flags = 0
+ data = length 393, hash 817AB352
+ sample 132:
+ time = 2816000
+ flags = 0
+ data = length 393, hash EA7D83DF
+ sample 133:
+ time = 2837333
+ flags = 0
+ data = length 393, hash E76873B0
+ sample 134:
+ time = 2858666
+ flags = 0
+ data = length 393, hash 2F48A520
+ sample 135:
+ time = 2880000
+ flags = 0
+ data = length 393, hash C0CBB3EF
+ sample 136:
+ time = 2901333
+ flags = 0
+ data = length 393, hash 255B0E50
+ sample 137:
+ time = 2922666
+ flags = 0
+ data = length 393, hash 9A49C63D
+ sample 138:
+ time = 2944000
+ flags = 0
+ data = length 1516, hash 4994C5B
+ sample 139:
+ time = 2965333
+ flags = 0
+ data = length 1519, hash 5514C06F
+ sample 140:
+ time = 2986666
+ flags = 0
+ data = length 1007, hash F994B3FC
+ sample 141:
+ time = 3008000
+ flags = 0
+ data = length 946, hash 7714E7B1
+ sample 142:
+ time = 3029333
+ flags = 0
+ data = length 985, hash C0E4D841
+ sample 143:
+ time = 3050666
+ flags = 0
+ data = length 1018, hash A18F6981
+ sample 144:
+ time = 3072000
+ flags = 0
+ data = length 790, hash 9F884211
+ sample 145:
+ time = 3093333
+ flags = 0
+ data = length 809, hash 1E0978C9
+ sample 146:
+ time = 3114666
+ flags = 0
+ data = length 791, hash 9BC34342
+ sample 147:
+ time = 3136000
+ flags = 0
+ data = length 806, hash C64EDB12
+ sample 148:
+ time = 3157333
+ flags = 0
+ data = length 757, hash 6C971B85
+ sample 149:
+ time = 3178666
+ flags = 0
+ data = length 950, hash 5509778D
+ sample 150:
+ time = 3200000
+ flags = 0
+ data = length 713, hash 2BD954C8
+ sample 151:
+ time = 3221333
+ flags = 0
+ data = length 800, hash 1C71F2EF
+ sample 152:
+ time = 3242666
+ flags = 0
+ data = length 804, hash BFCCE7C
+ sample 153:
+ time = 3264000
+ flags = 0
+ data = length 876, hash AB1137D9
+ sample 154:
+ time = 3285333
+ flags = 0
+ data = length 957, hash 1CC9B8CA
+ sample 155:
+ time = 3306666
+ flags = 0
+ data = length 563, hash A6FF9D2B
+ sample 156:
+ time = 3328000
+ flags = 0
+ data = length 796, hash B0110276
+ sample 157:
+ time = 3349333
+ flags = 0
+ data = length 863, hash 55EDF24F
+ sample 158:
+ time = 3370666
+ flags = 0
+ data = length 701, hash 3AE3C48F
+ sample 159:
+ time = 3392000
+ flags = 0
+ data = length 934, hash 2CC1C6E9
+ sample 160:
+ time = 3413333
+ flags = 0
+ data = length 967, hash 34E61D20
+ sample 161:
+ time = 3434666
+ flags = 0
+ data = length 1518, hash C0EC5B50
+ sample 162:
+ time = 3456000
+ flags = 0
+ data = length 1474, hash 6EC36C24
+ sample 163:
+ time = 3477333
+ flags = 0
+ data = length 1475, hash 6F1FD2AB
+ sample 164:
+ time = 3498666
+ flags = 0
+ data = length 1451, hash B58F4D31
+ sample 165:
+ time = 3520000
+ flags = 0
+ data = length 526, hash FC424B78
+ sample 166:
+ time = 3541333
+ flags = 0
+ data = length 598, hash 4BDB2753
+ sample 167:
+ time = 3562666
+ flags = 0
+ data = length 627, hash 48327C83
+ sample 168:
+ time = 3584000
+ flags = 0
+ data = length 551, hash 691D6CB2
+ sample 169:
+ time = 3605333
+ flags = 0
+ data = length 594, hash 86D1E249
+ sample 170:
+ time = 3626666
+ flags = 0
+ data = length 760, hash AF4B774F
+ sample 171:
+ time = 3648000
+ flags = 0
+ data = length 568, hash F4765276
+ sample 172:
+ time = 3669333
+ flags = 0
+ data = length 722, hash 2A72C44B
+ sample 173:
+ time = 3690666
+ flags = 0
+ data = length 602, hash 5D7135BB
+ sample 174:
+ time = 3712000
+ flags = 0
+ data = length 694, hash 8C5CE9CF
+ sample 175:
+ time = 3733333
+ flags = 0
+ data = length 725, hash 4EBFA7A8
+ sample 176:
+ time = 3754666
+ flags = 0
+ data = length 666, hash 2B1379B
+ sample 177:
+ time = 3776000
+ flags = 0
+ data = length 846, hash 57FC9178
+ sample 178:
+ time = 3797333
+ flags = 0
+ data = length 881, hash 19FDF109
+ sample 179:
+ time = 3818666
+ flags = 0
+ data = length 512, hash 49FD56DF
+ sample 180:
+ time = 3840000
+ flags = 0
+ data = length 840, hash FC78237B
+ sample 181:
+ time = 3861333
+ flags = 0
+ data = length 1075, hash 5031D568
+ sample 182:
+ time = 3882666
+ flags = 0
+ data = length 716, hash A509900D
+ sample 183:
+ time = 3904000
+ flags = 0
+ data = length 798, hash 386EB6B5
+ sample 184:
+ time = 3925333
+ flags = 0
+ data = length 969, hash 1E781925
+ sample 185:
+ time = 3946666
+ flags = 0
+ data = length 1444, hash F2DD1E7C
+ sample 186:
+ time = 3968000
+ flags = 0
+ data = length 399, hash 3FE1EAB6
+ sample 187:
+ time = 3989333
+ flags = 1
+ data = length 776, hash BEA73ED6
+ sample 188:
+ time = 4010666
+ flags = 0
+ data = length 875, hash 173C290C
+ sample 189:
+ time = 4032000
+ flags = 0
+ data = length 787, hash 531B9CB3
+ sample 190:
+ time = 4053333
+ flags = 0
+ data = length 737, hash 75CB4A48
+ sample 191:
+ time = 4074666
+ flags = 0
+ data = length 603, hash DDE525EE
+ sample 192:
+ time = 4096000
+ flags = 0
+ data = length 645, hash F4666418
+ sample 193:
+ time = 4117333
+ flags = 0
+ data = length 704, hash F7E18921
+ sample 194:
+ time = 4138666
+ flags = 0
+ data = length 802, hash 822433B5
+ sample 195:
+ time = 4160000
+ flags = 0
+ data = length 990, hash E4712448
+ sample 196:
+ time = 4181333
+ flags = 0
+ data = length 602, hash 3265AF8E
+ sample 197:
+ time = 4202666
+ flags = 0
+ data = length 790, hash 6EF432BA
+ sample 198:
+ time = 4224000
+ flags = 0
+ data = length 746, hash E20E7B36
+ sample 199:
+ time = 4245333
+ flags = 0
+ data = length 439, hash 8C32DDA0
+ sample 200:
+ time = 4266666
+ flags = 0
+ data = length 932, hash AF323520
+ sample 201:
+ time = 4288000
+ flags = 0
+ data = length 1003, hash 3D70121B
+ sample 202:
+ time = 4309333
+ flags = 0
+ data = length 1158, hash 1215442E
+ sample 203:
+ time = 4330666
+ flags = 0
+ data = length 1047, hash 2A517450
+ sample 204:
+ time = 4352000
+ flags = 0
+ data = length 1123, hash 33387B5F
+ sample 205:
+ time = 4373333
+ flags = 0
+ data = length 1033, hash D82CF575
+ sample 206:
+ time = 4394666
+ flags = 0
+ data = length 1009, hash 30DC6A02
+ sample 207:
+ time = 4416000
+ flags = 0
+ data = length 1033, hash 82127054
+ sample 208:
+ time = 4437333
+ flags = 0
+ data = length 761, hash 4A5EA11F
+ sample 209:
+ time = 4458666
+ flags = 0
+ data = length 708, hash 53FA04E4
+ sample 210:
+ time = 4480000
+ flags = 0
+ data = length 750, hash 44F541A6
+ sample 211:
+ time = 4501333
+ flags = 0
+ data = length 902, hash 6688117A
+ sample 212:
+ time = 4522666
+ flags = 0
+ data = length 716, hash A19D938D
+ sample 213:
+ time = 4544000
+ flags = 0
+ data = length 395, hash 4EF7E6DE
+ sample 214:
+ time = 4565333
+ flags = 0
+ data = length 677, hash 57DF6F41
+ sample 215:
+ time = 4586666
+ flags = 0
+ data = length 566, hash 515BD3F0
+ sample 216:
+ time = 4608000
+ flags = 0
+ data = length 772, hash 957617C9
+ sample 217:
+ time = 4629333
+ flags = 0
+ data = length 777, hash 6BB742A3
+ sample 218:
+ time = 4650666
+ flags = 0
+ data = length 672, hash 97BA98A3
+ sample 219:
+ time = 4672000
+ flags = 0
+ data = length 695, hash F8190CDE
+ sample 220:
+ time = 4693333
+ flags = 0
+ data = length 668, hash 6D62BE54
+ sample 221:
+ time = 4714666
+ flags = 0
+ data = length 662, hash 36D886CD
+ sample 222:
+ time = 4736000
+ flags = 0
+ data = length 678, hash 87772FCA
+ sample 223:
+ time = 4757333
+ flags = 0
+ data = length 946, hash BBFB4C98
+ sample 224:
+ time = 4778666
+ flags = 0
+ data = length 594, hash CEDCD36C
+ sample 225:
+ time = 4800000
+ flags = 0
+ data = length 499, hash 3B933D5B
+ sample 226:
+ time = 4821333
+ flags = 0
+ data = length 784, hash 97BC8486
+ sample 227:
+ time = 4842666
+ flags = 0
+ data = length 510, hash 9A082552
+ sample 228:
+ time = 4864000
+ flags = 0
+ data = length 741, hash E17DAE88
+ sample 229:
+ time = 4885333
+ flags = 0
+ data = length 656, hash C8CC5738
+ sample 230:
+ time = 4906666
+ flags = 0
+ data = length 672, hash 84C28F77
+ sample 231:
+ time = 4928000
+ flags = 0
+ data = length 559, hash B563D0ED
+ sample 232:
+ time = 4949333
+ flags = 0
+ data = length 1503, hash 183821B0
+ sample 233:
+ time = 4970666
+ flags = 0
+ data = length 393, hash D807573D
+tracksEnded = true
diff --git a/libraries/test_data/src/test/assets/media/ts/sample_dts.ts b/libraries/test_data/src/test/assets/media/ts/sample_dts.ts
new file mode 100644
index 0000000000..48ca8263ea
Binary files /dev/null and b/libraries/test_data/src/test/assets/media/ts/sample_dts.ts differ
diff --git a/libraries/test_data/src/test/assets/media/ts/sample_dts_hd.ts b/libraries/test_data/src/test/assets/media/ts/sample_dts_hd.ts
new file mode 100644
index 0000000000..8c88207f0a
Binary files /dev/null and b/libraries/test_data/src/test/assets/media/ts/sample_dts_hd.ts differ
diff --git a/libraries/test_data/src/test/assets/media/ts/sample_dts_uhd.ts b/libraries/test_data/src/test/assets/media/ts/sample_dts_uhd.ts
new file mode 100644
index 0000000000..7d1b3380a4
Binary files /dev/null and b/libraries/test_data/src/test/assets/media/ts/sample_dts_uhd.ts differ