Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.lang.annotation.Target;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

/** Utility methods for parsing DTS frames. */
Expand Down Expand Up @@ -875,31 +876,64 @@ public static int parseDtsUhdHeaderSize(byte[] headerPrefix) {
+ 1;
}

/** Returns whether the sample data at the current {@link ExtractorInput} is a DTS-HD sample. */
public static boolean isSampleDtsHd(ExtractorInput input, int sampleSize) throws IOException {
/**
* Returns a {@link Format} with an adjusted MIME type if the sample data at the current {@link
* ExtractorInput} is a DTS-HD sample with static fields, or the unmodified {@code format} if it
* is not.
*
* @param input The {@link ExtractorInput} to read from.
* @param sampleSize The size of the sample data.
* @param format The {@link Format} to build upon.
* @return The updated {@link Format}.
* @throws IOException If an error occurs reading from the input.
*/
public static Format updateFormatWithDtsHdInfo(
ExtractorInput input, int sampleSize, Format format) throws IOException {
ParsableByteArray sampleData = new ParsableByteArray(sampleSize);
if (!input.peekFully(
sampleData.getData(), /* offset= */ 0, sampleSize, /* allowEndOfInput= */ true)) {
return false;
return format;
}
input.resetPeekPosition();
int word = sampleData.peekInt();
// Skip the core frame if present (it doesn't have to be).
if (DtsUtil.getFrameType(word) == DtsUtil.FRAME_TYPE_CORE) {
if (sampleData.bytesLeft() < 10) {
return false;
return format;
}
byte[] header = new byte[10];
sampleData.readBytes(header, /* offset= */ 0, /* length= */ 10);
sampleData.setPosition(0);
int frameSize = DtsUtil.getDtsFrameSize(header);
if (frameSize <= 0 || sampleData.bytesLeft() < frameSize + 4) {
return false;
if (frameSize <= 0 || sampleData.limit() < frameSize + 4) {
return format;
}
sampleData.skipBytes(frameSize);
word = sampleData.readInt();
return DtsUtil.getFrameType(word) == DtsUtil.FRAME_TYPE_EXTENSION_SUBSTREAM;
}
return false;
sampleData.setPosition(frameSize);
word = sampleData.peekInt();
}
if (DtsUtil.getFrameType(word) != DtsUtil.FRAME_TYPE_EXTENSION_SUBSTREAM) {
return format;
}
if (sampleData.bytesLeft() < 7) {
return format;
}
int extHeaderOffset = sampleData.getPosition();
byte[] headerPrefix = new byte[7];
sampleData.readBytes(headerPrefix, /* offset= */ 0, /* length= */ 7);
sampleData.setPosition(extHeaderOffset);
int frameSize = parseDtsHdHeaderSize(headerPrefix);
if (frameSize <= 0 || sampleData.bytesLeft() < frameSize) {
return format;
}
byte[] header = new byte[frameSize];
sampleData.readBytes(header, /* offset= */ 0, /* length= */ frameSize);
DtsHeader dtsHeader = parseDtsHdHeader(header);
// If the MIME type was parsed successfully, use it. If it is null (e.g. because static
// fields were missing), there's nothing we can do other than assume it is DTS-HD.
String mimeType = dtsHeader.mimeType != null ? dtsHeader.mimeType : MimeTypes.AUDIO_DTS_HD;
if (Objects.equals(format.sampleMimeType, mimeType)) {
return format;
}
return format.buildUpon().setSampleMimeType(mimeType).build();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1846,9 +1846,7 @@ private int writeSampleData(ExtractorInput input, Track track, int size, boolean

if (track.waitingForDtsAnalysis) {
checkNotNull(track.format);
if (DtsUtil.isSampleDtsHd(input, size)) {
track.format = track.format.buildUpon().setSampleMimeType(MimeTypes.AUDIO_DTS_HD).build();
}
track.format = DtsUtil.updateFormatWithDtsHdInfo(input, size, track.format);
track.output.format(track.format);
track.waitingForDtsAnalysis = false;
maybeEndTracks();
Expand Down Expand Up @@ -2544,10 +2542,12 @@ public void initializeFormat(int trackId) throws ParserException {
trueHdSampleRechunker = new TrueHdSampleRechunker();
break;
case CODEC_ID_DTS:
case CODEC_ID_DTS_EXPRESS:
mimeType = MimeTypes.AUDIO_DTS; // temporary
waitingForDtsAnalysis = true;
break;
case CODEC_ID_DTS_EXPRESS:
mimeType = MimeTypes.AUDIO_DTS_EXPRESS;
break;
case CODEC_ID_DTS_LOSSLESS:
mimeType = MimeTypes.AUDIO_DTS_HD;
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,14 @@ public void mkvSample_withDts() throws Exception {
simulationConfig);
}

@Test
public void mkaSample_withDtsExpress() throws Exception {
ExtractorAsserts.assertBehavior(
getExtractorFactory(subtitlesParsedDuringExtraction),
"media/mka/sample_with_dts_express.mka",
simulationConfig);
}

@Test
public void mkvSample_withDtsHdMa() throws Exception {
ExtractorAsserts.assertBehavior(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
seekMap:
isSeekable = true
duration = 938000
getPosition(0) = [[timeUs=0, position=469]]
getPosition(1) = [[timeUs=0, position=469]]
getPosition(469000) = [[timeUs=0, position=469]]
getPosition(938000) = [[timeUs=0, position=469]]
numberOfTracks = 1
track 1:
total output bytes = 45056
sample count = 11
format 0:
id = 1
containerMimeType = video/x-matroska
sampleMimeType = audio/vnd.dts.hd;profile=lbr
channelCount = 6
sampleRate = 48000
language = und
sample 0:
time = 0
flags = 1
data = length 4096, hash 1F0B79C5
sample 1:
time = 85000
flags = 1
data = length 4096, hash 2EC282A1
sample 2:
time = 171000
flags = 1
data = length 4096, hash 6B7902F0
sample 3:
time = 256000
flags = 1
data = length 4096, hash 8FC4EE2C
sample 4:
time = 341000
flags = 1
data = length 4096, hash 67899547
sample 5:
time = 427000
flags = 1
data = length 4096, hash 1BE4CF1C
sample 6:
time = 512000
flags = 1
data = length 4096, hash 620F5E51
sample 7:
time = 597000
flags = 1
data = length 4096, hash 4D3E0644
sample 8:
time = 683000
flags = 1
data = length 4096, hash F69B5FED
sample 9:
time = 768000
flags = 1
data = length 4096, hash 93D31EA7
sample 10:
time = 853000
flags = 1
data = length 4096, hash 41F1D921
tracksEnded = true
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
seekMap:
isSeekable = true
duration = 938000
getPosition(0) = [[timeUs=0, position=469]]
getPosition(1) = [[timeUs=0, position=469]]
getPosition(469000) = [[timeUs=0, position=469]]
getPosition(938000) = [[timeUs=0, position=469]]
numberOfTracks = 1
track 1:
total output bytes = 45056
sample count = 11
format 0:
id = 1
containerMimeType = video/x-matroska
sampleMimeType = audio/vnd.dts.hd;profile=lbr
channelCount = 6
sampleRate = 48000
language = und
sample 0:
time = 0
flags = 1
data = length 4096, hash 1F0B79C5
sample 1:
time = 85000
flags = 1
data = length 4096, hash 2EC282A1
sample 2:
time = 171000
flags = 1
data = length 4096, hash 6B7902F0
sample 3:
time = 256000
flags = 1
data = length 4096, hash 8FC4EE2C
sample 4:
time = 341000
flags = 1
data = length 4096, hash 67899547
sample 5:
time = 427000
flags = 1
data = length 4096, hash 1BE4CF1C
sample 6:
time = 512000
flags = 1
data = length 4096, hash 620F5E51
sample 7:
time = 597000
flags = 1
data = length 4096, hash 4D3E0644
sample 8:
time = 683000
flags = 1
data = length 4096, hash F69B5FED
sample 9:
time = 768000
flags = 1
data = length 4096, hash 93D31EA7
sample 10:
time = 853000
flags = 1
data = length 4096, hash 41F1D921
tracksEnded = true
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
seekMap:
isSeekable = true
duration = 938000
getPosition(0) = [[timeUs=0, position=469]]
getPosition(1) = [[timeUs=0, position=469]]
getPosition(469000) = [[timeUs=0, position=469]]
getPosition(938000) = [[timeUs=0, position=469]]
numberOfTracks = 1
track 1:
total output bytes = 45056
sample count = 11
format 0:
id = 1
containerMimeType = video/x-matroska
sampleMimeType = audio/vnd.dts.hd;profile=lbr
channelCount = 6
sampleRate = 48000
language = und
sample 0:
time = 0
flags = 1
data = length 4096, hash 1F0B79C5
sample 1:
time = 85000
flags = 1
data = length 4096, hash 2EC282A1
sample 2:
time = 171000
flags = 1
data = length 4096, hash 6B7902F0
sample 3:
time = 256000
flags = 1
data = length 4096, hash 8FC4EE2C
sample 4:
time = 341000
flags = 1
data = length 4096, hash 67899547
sample 5:
time = 427000
flags = 1
data = length 4096, hash 1BE4CF1C
sample 6:
time = 512000
flags = 1
data = length 4096, hash 620F5E51
sample 7:
time = 597000
flags = 1
data = length 4096, hash 4D3E0644
sample 8:
time = 683000
flags = 1
data = length 4096, hash F69B5FED
sample 9:
time = 768000
flags = 1
data = length 4096, hash 93D31EA7
sample 10:
time = 853000
flags = 1
data = length 4096, hash 41F1D921
tracksEnded = true
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
seekMap:
isSeekable = true
duration = 938000
getPosition(0) = [[timeUs=0, position=469]]
getPosition(1) = [[timeUs=0, position=469]]
getPosition(469000) = [[timeUs=0, position=469]]
getPosition(938000) = [[timeUs=0, position=469]]
numberOfTracks = 1
track 1:
total output bytes = 45056
sample count = 11
format 0:
id = 1
containerMimeType = video/x-matroska
sampleMimeType = audio/vnd.dts.hd;profile=lbr
channelCount = 6
sampleRate = 48000
language = und
sample 0:
time = 0
flags = 1
data = length 4096, hash 1F0B79C5
sample 1:
time = 85000
flags = 1
data = length 4096, hash 2EC282A1
sample 2:
time = 171000
flags = 1
data = length 4096, hash 6B7902F0
sample 3:
time = 256000
flags = 1
data = length 4096, hash 8FC4EE2C
sample 4:
time = 341000
flags = 1
data = length 4096, hash 67899547
sample 5:
time = 427000
flags = 1
data = length 4096, hash 1BE4CF1C
sample 6:
time = 512000
flags = 1
data = length 4096, hash 620F5E51
sample 7:
time = 597000
flags = 1
data = length 4096, hash 4D3E0644
sample 8:
time = 683000
flags = 1
data = length 4096, hash F69B5FED
sample 9:
time = 768000
flags = 1
data = length 4096, hash 93D31EA7
sample 10:
time = 853000
flags = 1
data = length 4096, hash 41F1D921
tracksEnded = true
Loading