Merge pull request #9496 from DolbyLaboratories:dev-v2-truehd
PiperOrigin-RevId: 403081883
This commit is contained in:
commit
059dfaef7c
@ -8,8 +8,8 @@
|
|||||||
`DefaultRenderersFactory` to force enable or force disable asynchronous
|
`DefaultRenderersFactory` to force enable or force disable asynchronous
|
||||||
queueing ([6348](https://github.com/google/ExoPlayer/issues/6348)).
|
queueing ([6348](https://github.com/google/ExoPlayer/issues/6348)).
|
||||||
* Add 12 public method headers to `ExoPlayer` that exist in
|
* Add 12 public method headers to `ExoPlayer` that exist in
|
||||||
`SimpleExoPlayer`, such that all public methods in `SimpleExoPlayer`
|
`SimpleExoPlayer`, such that all public methods in `SimpleExoPlayer` are
|
||||||
are overrides.
|
overrides.
|
||||||
* Move `com.google.android.exoplayer2.device.DeviceInfo` to
|
* Move `com.google.android.exoplayer2.device.DeviceInfo` to
|
||||||
`com.google.android.exoplayer2.DeviceInfo`.
|
`com.google.android.exoplayer2.DeviceInfo`.
|
||||||
* Move `com.google.android.exoplayer2.drm.DecryptionException` to
|
* Move `com.google.android.exoplayer2.drm.DecryptionException` to
|
||||||
@ -51,6 +51,8 @@
|
|||||||
([#9452](https://github.com/google/ExoPlayer/issues/9452)).
|
([#9452](https://github.com/google/ExoPlayer/issues/9452)).
|
||||||
* Extractors:
|
* Extractors:
|
||||||
* MP4: Correctly handle HEVC tracks with pixel aspect ratios other than 1.
|
* MP4: Correctly handle HEVC tracks with pixel aspect ratios other than 1.
|
||||||
|
* MP4: Add support for Dolby TrueHD (only for unfragmented streams)
|
||||||
|
([#9496](https://github.com/google/ExoPlayer/issues/9496)).
|
||||||
* TS: Correctly handle HEVC tracks with pixel aspect ratios other than 1.
|
* TS: Correctly handle HEVC tracks with pixel aspect ratios other than 1.
|
||||||
* TS: Map stream type 0x80 to H262
|
* TS: Map stream type 0x80 to H262
|
||||||
([#9472](https://github.com/google/ExoPlayer/issues/9472)).
|
([#9472](https://github.com/google/ExoPlayer/issues/9472)).
|
||||||
|
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.android.exoplayer2.extractor;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.util.Assertions.checkState;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import com.google.android.exoplayer2.C;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rechunks TrueHD sample data into groups of {@link Ac3Util#TRUEHD_RECHUNK_SAMPLE_COUNT} samples.
|
||||||
|
*/
|
||||||
|
public final class TrueHdSampleRechunker {
|
||||||
|
|
||||||
|
private final byte[] syncframePrefix;
|
||||||
|
|
||||||
|
private boolean foundSyncframe;
|
||||||
|
private int chunkSampleCount;
|
||||||
|
private long chunkTimeUs;
|
||||||
|
@C.BufferFlags private int chunkFlags;
|
||||||
|
private int chunkSize;
|
||||||
|
private int chunkOffset;
|
||||||
|
|
||||||
|
public TrueHdSampleRechunker() {
|
||||||
|
syncframePrefix = new byte[Ac3Util.TRUEHD_SYNCFRAME_PREFIX_LENGTH];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
foundSyncframe = false;
|
||||||
|
chunkSampleCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startSample(ExtractorInput input) throws IOException {
|
||||||
|
if (foundSyncframe) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
input.peekFully(syncframePrefix, 0, Ac3Util.TRUEHD_SYNCFRAME_PREFIX_LENGTH);
|
||||||
|
input.resetPeekPosition();
|
||||||
|
if (Ac3Util.parseTrueHdSyncframeAudioSampleCount(syncframePrefix) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foundSyncframe = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sampleMetadata(
|
||||||
|
TrackOutput trackOutput,
|
||||||
|
long timeUs,
|
||||||
|
@C.BufferFlags int flags,
|
||||||
|
int size,
|
||||||
|
int offset,
|
||||||
|
@Nullable TrackOutput.CryptoData cryptoData) {
|
||||||
|
checkState(
|
||||||
|
chunkOffset <= size + offset,
|
||||||
|
"TrueHD chunk samples must be contiguous in the sample queue.");
|
||||||
|
if (!foundSyncframe) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (chunkSampleCount++ == 0) {
|
||||||
|
// This is the first sample in the chunk.
|
||||||
|
chunkTimeUs = timeUs;
|
||||||
|
chunkFlags = flags;
|
||||||
|
chunkSize = 0;
|
||||||
|
}
|
||||||
|
chunkSize += size;
|
||||||
|
chunkOffset = offset; // The offset is to the end of the sample.
|
||||||
|
if (chunkSampleCount >= Ac3Util.TRUEHD_RECHUNK_SAMPLE_COUNT) {
|
||||||
|
outputPendingSampleMetadata(trackOutput, cryptoData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void outputPendingSampleMetadata(
|
||||||
|
TrackOutput trackOutput, @Nullable TrackOutput.CryptoData cryptoData) {
|
||||||
|
if (chunkSampleCount > 0) {
|
||||||
|
trackOutput.sampleMetadata(chunkTimeUs, chunkFlags, chunkSize, chunkOffset, cryptoData);
|
||||||
|
chunkSampleCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -31,7 +31,6 @@ import com.google.android.exoplayer2.C;
|
|||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.ParserException;
|
import com.google.android.exoplayer2.ParserException;
|
||||||
import com.google.android.exoplayer2.audio.AacUtil;
|
import com.google.android.exoplayer2.audio.AacUtil;
|
||||||
import com.google.android.exoplayer2.audio.Ac3Util;
|
|
||||||
import com.google.android.exoplayer2.audio.MpegAudioUtil;
|
import com.google.android.exoplayer2.audio.MpegAudioUtil;
|
||||||
import com.google.android.exoplayer2.drm.DrmInitData;
|
import com.google.android.exoplayer2.drm.DrmInitData;
|
||||||
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
|
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
|
||||||
@ -43,6 +42,7 @@ import com.google.android.exoplayer2.extractor.ExtractorsFactory;
|
|||||||
import com.google.android.exoplayer2.extractor.PositionHolder;
|
import com.google.android.exoplayer2.extractor.PositionHolder;
|
||||||
import com.google.android.exoplayer2.extractor.SeekMap;
|
import com.google.android.exoplayer2.extractor.SeekMap;
|
||||||
import com.google.android.exoplayer2.extractor.TrackOutput;
|
import com.google.android.exoplayer2.extractor.TrackOutput;
|
||||||
|
import com.google.android.exoplayer2.extractor.TrueHdSampleRechunker;
|
||||||
import com.google.android.exoplayer2.util.Log;
|
import com.google.android.exoplayer2.util.Log;
|
||||||
import com.google.android.exoplayer2.util.LongArray;
|
import com.google.android.exoplayer2.util.LongArray;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
@ -1334,7 +1334,8 @@ public class MatroskaExtractor implements Extractor {
|
|||||||
private void commitSampleToOutput(
|
private void commitSampleToOutput(
|
||||||
Track track, long timeUs, @C.BufferFlags int flags, int size, int offset) {
|
Track track, long timeUs, @C.BufferFlags int flags, int size, int offset) {
|
||||||
if (track.trueHdSampleRechunker != null) {
|
if (track.trueHdSampleRechunker != null) {
|
||||||
track.trueHdSampleRechunker.sampleMetadata(track, timeUs, flags, size, offset);
|
track.trueHdSampleRechunker.sampleMetadata(
|
||||||
|
track.output, timeUs, flags, size, offset, track.cryptoData);
|
||||||
} else {
|
} else {
|
||||||
if (CODEC_ID_SUBRIP.equals(track.codecId) || CODEC_ID_ASS.equals(track.codecId)) {
|
if (CODEC_ID_SUBRIP.equals(track.codecId) || CODEC_ID_ASS.equals(track.codecId)) {
|
||||||
if (blockSampleCount > 1) {
|
if (blockSampleCount > 1) {
|
||||||
@ -1899,70 +1900,6 @@ public class MatroskaExtractor implements Extractor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Rechunks TrueHD sample data into groups of {@link Ac3Util#TRUEHD_RECHUNK_SAMPLE_COUNT} samples.
|
|
||||||
*/
|
|
||||||
private static final class TrueHdSampleRechunker {
|
|
||||||
|
|
||||||
private final byte[] syncframePrefix;
|
|
||||||
|
|
||||||
private boolean foundSyncframe;
|
|
||||||
private int chunkSampleCount;
|
|
||||||
private long chunkTimeUs;
|
|
||||||
private @C.BufferFlags int chunkFlags;
|
|
||||||
private int chunkSize;
|
|
||||||
private int chunkOffset;
|
|
||||||
|
|
||||||
public TrueHdSampleRechunker() {
|
|
||||||
syncframePrefix = new byte[Ac3Util.TRUEHD_SYNCFRAME_PREFIX_LENGTH];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reset() {
|
|
||||||
foundSyncframe = false;
|
|
||||||
chunkSampleCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startSample(ExtractorInput input) throws IOException {
|
|
||||||
if (foundSyncframe) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
input.peekFully(syncframePrefix, 0, Ac3Util.TRUEHD_SYNCFRAME_PREFIX_LENGTH);
|
|
||||||
input.resetPeekPosition();
|
|
||||||
if (Ac3Util.parseTrueHdSyncframeAudioSampleCount(syncframePrefix) == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
foundSyncframe = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresNonNull("#1.output")
|
|
||||||
public void sampleMetadata(
|
|
||||||
Track track, long timeUs, @C.BufferFlags int flags, int size, int offset) {
|
|
||||||
if (!foundSyncframe) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (chunkSampleCount++ == 0) {
|
|
||||||
// This is the first sample in the chunk.
|
|
||||||
chunkTimeUs = timeUs;
|
|
||||||
chunkFlags = flags;
|
|
||||||
chunkSize = 0;
|
|
||||||
}
|
|
||||||
chunkSize += size;
|
|
||||||
chunkOffset = offset; // The offset is to the end of the sample.
|
|
||||||
if (chunkSampleCount >= Ac3Util.TRUEHD_RECHUNK_SAMPLE_COUNT) {
|
|
||||||
outputPendingSampleMetadata(track);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresNonNull("#1.output")
|
|
||||||
public void outputPendingSampleMetadata(Track track) {
|
|
||||||
if (chunkSampleCount > 0) {
|
|
||||||
track.output.sampleMetadata(
|
|
||||||
chunkTimeUs, chunkFlags, chunkSize, chunkOffset, track.cryptoData);
|
|
||||||
chunkSampleCount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class Track {
|
private static final class Track {
|
||||||
|
|
||||||
private static final int DISPLAY_UNIT_PIXELS = 0;
|
private static final int DISPLAY_UNIT_PIXELS = 0;
|
||||||
@ -2335,7 +2272,7 @@ public class MatroskaExtractor implements Extractor {
|
|||||||
@RequiresNonNull("output")
|
@RequiresNonNull("output")
|
||||||
public void outputPendingSampleMetadata() {
|
public void outputPendingSampleMetadata() {
|
||||||
if (trueHdSampleRechunker != null) {
|
if (trueHdSampleRechunker != null) {
|
||||||
trueHdSampleRechunker.outputPendingSampleMetadata(this);
|
trueHdSampleRechunker.outputPendingSampleMetadata(output, cryptoData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +152,12 @@ import java.util.List;
|
|||||||
@SuppressWarnings("ConstantCaseForConstants")
|
@SuppressWarnings("ConstantCaseForConstants")
|
||||||
public static final int TYPE_dac4 = 0x64616334;
|
public static final int TYPE_dac4 = 0x64616334;
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantCaseForConstants")
|
||||||
|
public static final int TYPE_mlpa = 0x6d6c7061;
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantCaseForConstants")
|
||||||
|
public static final int TYPE_dmlp = 0x646d6c70;
|
||||||
|
|
||||||
@SuppressWarnings("ConstantCaseForConstants")
|
@SuppressWarnings("ConstantCaseForConstants")
|
||||||
public static final int TYPE_dtsc = 0x64747363;
|
public static final int TYPE_dtsc = 0x64747363;
|
||||||
|
|
||||||
|
@ -962,6 +962,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
|| childAtomType == Atom.TYPE_ac_3
|
|| childAtomType == Atom.TYPE_ac_3
|
||||||
|| childAtomType == Atom.TYPE_ec_3
|
|| childAtomType == Atom.TYPE_ec_3
|
||||||
|| childAtomType == Atom.TYPE_ac_4
|
|| childAtomType == Atom.TYPE_ac_4
|
||||||
|
|| childAtomType == Atom.TYPE_mlpa
|
||||||
|| childAtomType == Atom.TYPE_dtsc
|
|| childAtomType == Atom.TYPE_dtsc
|
||||||
|| childAtomType == Atom.TYPE_dtse
|
|| childAtomType == Atom.TYPE_dtse
|
||||||
|| childAtomType == Atom.TYPE_dtsh
|
|| childAtomType == Atom.TYPE_dtsh
|
||||||
@ -1317,13 +1318,18 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
|
|
||||||
int channelCount;
|
int channelCount;
|
||||||
int sampleRate;
|
int sampleRate;
|
||||||
|
int sampleRateMlp = 0;
|
||||||
@C.PcmEncoding int pcmEncoding = Format.NO_VALUE;
|
@C.PcmEncoding int pcmEncoding = Format.NO_VALUE;
|
||||||
@Nullable String codecs = null;
|
@Nullable String codecs = null;
|
||||||
|
|
||||||
if (quickTimeSoundDescriptionVersion == 0 || quickTimeSoundDescriptionVersion == 1) {
|
if (quickTimeSoundDescriptionVersion == 0 || quickTimeSoundDescriptionVersion == 1) {
|
||||||
channelCount = parent.readUnsignedShort();
|
channelCount = parent.readUnsignedShort();
|
||||||
parent.skipBytes(6); // sampleSize, compressionId, packetSize.
|
parent.skipBytes(6); // sampleSize, compressionId, packetSize.
|
||||||
|
|
||||||
sampleRate = parent.readUnsignedFixedPoint1616();
|
sampleRate = parent.readUnsignedFixedPoint1616();
|
||||||
|
parent.skipBytes(-4);
|
||||||
|
// The sample rate has been redefined as a 32-bit value for Dolby TrueHD (MLP) streams.
|
||||||
|
sampleRateMlp = parent.readInt();
|
||||||
|
|
||||||
if (quickTimeSoundDescriptionVersion == 1) {
|
if (quickTimeSoundDescriptionVersion == 1) {
|
||||||
parent.skipBytes(16);
|
parent.skipBytes(16);
|
||||||
@ -1404,6 +1410,8 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
mimeType = MimeTypes.AUDIO_OPUS;
|
mimeType = MimeTypes.AUDIO_OPUS;
|
||||||
} else if (atomType == Atom.TYPE_fLaC) {
|
} else if (atomType == Atom.TYPE_fLaC) {
|
||||||
mimeType = MimeTypes.AUDIO_FLAC;
|
mimeType = MimeTypes.AUDIO_FLAC;
|
||||||
|
} else if (atomType == Atom.TYPE_mlpa) {
|
||||||
|
mimeType = MimeTypes.AUDIO_TRUEHD;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable List<byte[]> initializationData = null;
|
@Nullable List<byte[]> initializationData = null;
|
||||||
@ -1457,6 +1465,17 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|||||||
parent.setPosition(Atom.HEADER_SIZE + childPosition);
|
parent.setPosition(Atom.HEADER_SIZE + childPosition);
|
||||||
out.format =
|
out.format =
|
||||||
Ac4Util.parseAc4AnnexEFormat(parent, Integer.toString(trackId), language, drmInitData);
|
Ac4Util.parseAc4AnnexEFormat(parent, Integer.toString(trackId), language, drmInitData);
|
||||||
|
} else if (childAtomType == Atom.TYPE_dmlp) {
|
||||||
|
if (sampleRateMlp <= 0) {
|
||||||
|
throw ParserException.createForMalformedContainer(
|
||||||
|
"Invalid sample rate for Dolby TrueHD MLP stream: " + sampleRateMlp,
|
||||||
|
/* cause= */ null);
|
||||||
|
}
|
||||||
|
sampleRate = sampleRateMlp;
|
||||||
|
// The channel count from the sample entry must be ignored for Dolby TrueHD (MLP) streams
|
||||||
|
// because these streams can carry simultaneously multiple representations of the same
|
||||||
|
// audio. Use stereo by default.
|
||||||
|
channelCount = 2;
|
||||||
} else if (childAtomType == Atom.TYPE_ddts) {
|
} else if (childAtomType == Atom.TYPE_ddts) {
|
||||||
out.format =
|
out.format =
|
||||||
new Format.Builder()
|
new Format.Builder()
|
||||||
|
@ -29,6 +29,7 @@ import androidx.annotation.Nullable;
|
|||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.ParserException;
|
import com.google.android.exoplayer2.ParserException;
|
||||||
|
import com.google.android.exoplayer2.audio.Ac3Util;
|
||||||
import com.google.android.exoplayer2.audio.Ac4Util;
|
import com.google.android.exoplayer2.audio.Ac4Util;
|
||||||
import com.google.android.exoplayer2.extractor.Extractor;
|
import com.google.android.exoplayer2.extractor.Extractor;
|
||||||
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
||||||
@ -39,6 +40,7 @@ import com.google.android.exoplayer2.extractor.PositionHolder;
|
|||||||
import com.google.android.exoplayer2.extractor.SeekMap;
|
import com.google.android.exoplayer2.extractor.SeekMap;
|
||||||
import com.google.android.exoplayer2.extractor.SeekPoint;
|
import com.google.android.exoplayer2.extractor.SeekPoint;
|
||||||
import com.google.android.exoplayer2.extractor.TrackOutput;
|
import com.google.android.exoplayer2.extractor.TrackOutput;
|
||||||
|
import com.google.android.exoplayer2.extractor.TrueHdSampleRechunker;
|
||||||
import com.google.android.exoplayer2.extractor.mp4.Atom.ContainerAtom;
|
import com.google.android.exoplayer2.extractor.mp4.Atom.ContainerAtom;
|
||||||
import com.google.android.exoplayer2.metadata.Metadata;
|
import com.google.android.exoplayer2.metadata.Metadata;
|
||||||
import com.google.android.exoplayer2.metadata.mp4.MotionPhotoMetadata;
|
import com.google.android.exoplayer2.metadata.mp4.MotionPhotoMetadata;
|
||||||
@ -56,7 +58,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
|
||||||
|
|
||||||
/** Extracts data from the MP4 container format. */
|
/** Extracts data from the MP4 container format. */
|
||||||
public final class Mp4Extractor implements Extractor, SeekMap {
|
public final class Mp4Extractor implements Extractor, SeekMap {
|
||||||
@ -220,7 +221,12 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
slowMotionMetadataEntries.clear();
|
slowMotionMetadataEntries.clear();
|
||||||
}
|
}
|
||||||
} else if (tracks != null) {
|
} else if (tracks != null) {
|
||||||
updateSampleIndices(timeUs);
|
for (Mp4Track track : tracks) {
|
||||||
|
updateSampleIndex(track, timeUs);
|
||||||
|
if (track.trueHdSampleRechunker != null) {
|
||||||
|
track.trueHdSampleRechunker.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,9 +509,16 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
Mp4Track mp4Track =
|
Mp4Track mp4Track =
|
||||||
new Mp4Track(track, trackSampleTable, extractorOutput.track(i, track.type));
|
new Mp4Track(track, trackSampleTable, extractorOutput.track(i, track.type));
|
||||||
|
|
||||||
// Each sample has up to three bytes of overhead for the start code that replaces its length.
|
int maxInputSize;
|
||||||
// Allow ten source samples per output sample, like the platform extractor.
|
if (MimeTypes.AUDIO_TRUEHD.equals(track.format.sampleMimeType)) {
|
||||||
int maxInputSize = trackSampleTable.maximumSize + 3 * 10;
|
// TrueHD groups samples per chunks of TRUEHD_RECHUNK_SAMPLE_COUNT samples.
|
||||||
|
maxInputSize = trackSampleTable.maximumSize * Ac3Util.TRUEHD_RECHUNK_SAMPLE_COUNT;
|
||||||
|
} else {
|
||||||
|
// Each sample has up to three bytes of overhead for the start code that replaces its
|
||||||
|
// length. Allow ten source samples per output sample, like the platform extractor.
|
||||||
|
maxInputSize = trackSampleTable.maximumSize + 3 * 10;
|
||||||
|
}
|
||||||
|
|
||||||
Format.Builder formatBuilder = track.format.buildUpon();
|
Format.Builder formatBuilder = track.format.buildUpon();
|
||||||
formatBuilder.setMaxInputSize(maxInputSize);
|
formatBuilder.setMaxInputSize(maxInputSize);
|
||||||
if (track.type == C.TRACK_TYPE_VIDEO
|
if (track.type == C.TRACK_TYPE_VIDEO
|
||||||
@ -567,6 +580,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
int sampleIndex = track.sampleIndex;
|
int sampleIndex = track.sampleIndex;
|
||||||
long position = track.sampleTable.offsets[sampleIndex];
|
long position = track.sampleTable.offsets[sampleIndex];
|
||||||
int sampleSize = track.sampleTable.sizes[sampleIndex];
|
int sampleSize = track.sampleTable.sizes[sampleIndex];
|
||||||
|
@Nullable TrueHdSampleRechunker trueHdSampleRechunker = track.trueHdSampleRechunker;
|
||||||
long skipAmount = position - inputPosition + sampleBytesRead;
|
long skipAmount = position - inputPosition + sampleBytesRead;
|
||||||
if (skipAmount < 0 || skipAmount >= RELOAD_MINIMUM_SEEK_DISTANCE) {
|
if (skipAmount < 0 || skipAmount >= RELOAD_MINIMUM_SEEK_DISTANCE) {
|
||||||
positionHolder.position = position;
|
positionHolder.position = position;
|
||||||
@ -624,7 +638,10 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
sampleBytesWritten += Ac4Util.SAMPLE_HEADER_SIZE;
|
sampleBytesWritten += Ac4Util.SAMPLE_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
sampleSize += Ac4Util.SAMPLE_HEADER_SIZE;
|
sampleSize += Ac4Util.SAMPLE_HEADER_SIZE;
|
||||||
|
} else if (trueHdSampleRechunker != null) {
|
||||||
|
trueHdSampleRechunker.startSample(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (sampleBytesWritten < sampleSize) {
|
while (sampleBytesWritten < sampleSize) {
|
||||||
int writtenBytes = trackOutput.sampleData(input, sampleSize - sampleBytesWritten, false);
|
int writtenBytes = trackOutput.sampleData(input, sampleSize - sampleBytesWritten, false);
|
||||||
sampleBytesRead += writtenBytes;
|
sampleBytesRead += writtenBytes;
|
||||||
@ -632,12 +649,20 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
sampleCurrentNalBytesRemaining -= writtenBytes;
|
sampleCurrentNalBytesRemaining -= writtenBytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long timeUs = track.sampleTable.timestampsUs[sampleIndex];
|
||||||
|
@C.BufferFlags int flags = track.sampleTable.flags[sampleIndex];
|
||||||
|
if (trueHdSampleRechunker != null) {
|
||||||
|
trueHdSampleRechunker.sampleMetadata(
|
||||||
|
trackOutput, timeUs, flags, sampleSize, /* offset= */ 0, /* cryptoData= */ null);
|
||||||
|
if (sampleIndex + 1 == track.sampleTable.sampleCount) {
|
||||||
|
trueHdSampleRechunker.outputPendingSampleMetadata(trackOutput, /* cryptoData= */ null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
trackOutput.sampleMetadata(
|
trackOutput.sampleMetadata(
|
||||||
track.sampleTable.timestampsUs[sampleIndex],
|
timeUs, flags, sampleSize, /* offset= */ 0, /* cryptoData= */ null);
|
||||||
track.sampleTable.flags[sampleIndex],
|
}
|
||||||
sampleSize,
|
|
||||||
0,
|
|
||||||
null);
|
|
||||||
track.sampleIndex++;
|
track.sampleIndex++;
|
||||||
sampleTrackIndex = C.INDEX_UNSET;
|
sampleTrackIndex = C.INDEX_UNSET;
|
||||||
sampleBytesRead = 0;
|
sampleBytesRead = 0;
|
||||||
@ -697,12 +722,8 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
: minAccumulatedBytesTrackIndex;
|
: minAccumulatedBytesTrackIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Updates a track's sample index to point its latest sync sample before/at {@code timeUs}. */
|
||||||
* Updates every track's sample index to point its latest sync sample before/at {@code timeUs}.
|
private void updateSampleIndex(Mp4Track track, long timeUs) {
|
||||||
*/
|
|
||||||
@RequiresNonNull("tracks")
|
|
||||||
private void updateSampleIndices(long timeUs) {
|
|
||||||
for (Mp4Track track : tracks) {
|
|
||||||
TrackSampleTable sampleTable = track.sampleTable;
|
TrackSampleTable sampleTable = track.sampleTable;
|
||||||
int sampleIndex = sampleTable.getIndexOfEarlierOrEqualSynchronizationSample(timeUs);
|
int sampleIndex = sampleTable.getIndexOfEarlierOrEqualSynchronizationSample(timeUs);
|
||||||
if (sampleIndex == C.INDEX_UNSET) {
|
if (sampleIndex == C.INDEX_UNSET) {
|
||||||
@ -711,7 +732,6 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
}
|
}
|
||||||
track.sampleIndex = sampleIndex;
|
track.sampleIndex = sampleIndex;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/** Processes the end of stream in case there is not atom left to read. */
|
/** Processes the end of stream in case there is not atom left to read. */
|
||||||
private void processEndOfStreamReadingAtomHeader() {
|
private void processEndOfStreamReadingAtomHeader() {
|
||||||
@ -902,6 +922,7 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
public final Track track;
|
public final Track track;
|
||||||
public final TrackSampleTable sampleTable;
|
public final TrackSampleTable sampleTable;
|
||||||
public final TrackOutput trackOutput;
|
public final TrackOutput trackOutput;
|
||||||
|
@Nullable public final TrueHdSampleRechunker trueHdSampleRechunker;
|
||||||
|
|
||||||
public int sampleIndex;
|
public int sampleIndex;
|
||||||
|
|
||||||
@ -909,6 +930,10 @@ public final class Mp4Extractor implements Extractor, SeekMap {
|
|||||||
this.track = track;
|
this.track = track;
|
||||||
this.sampleTable = sampleTable;
|
this.sampleTable = sampleTable;
|
||||||
this.trackOutput = trackOutput;
|
this.trackOutput = trackOutput;
|
||||||
|
trueHdSampleRechunker =
|
||||||
|
MimeTypes.AUDIO_TRUEHD.equals(track.format.sampleMimeType)
|
||||||
|
? new TrueHdSampleRechunker()
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,4 +102,10 @@ public final class Mp4ExtractorTest {
|
|||||||
ExtractorAsserts.assertBehavior(
|
ExtractorAsserts.assertBehavior(
|
||||||
Mp4Extractor::new, "media/mp4/sample_with_color_info.mp4", simulationConfig);
|
Mp4Extractor::new, "media/mp4/sample_with_color_info.mp4", simulationConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mp4SampleWithDolbyTrueHDTrack() throws Exception {
|
||||||
|
ExtractorAsserts.assertBehavior(
|
||||||
|
Mp4Extractor::new, "media/mp4/sample_dthd.mp4", simulationConfig);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
147
testdata/src/test/assets/extractordumps/mp4/sample_dthd.mp4.0.dump
vendored
Normal file
147
testdata/src/test/assets/extractordumps/mp4/sample_dthd.mp4.0.dump
vendored
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
seekMap:
|
||||||
|
isSeekable = true
|
||||||
|
duration = 418333
|
||||||
|
getPosition(0) = [[timeUs=0, position=3447]]
|
||||||
|
getPosition(1) = [[timeUs=1, position=3447]]
|
||||||
|
getPosition(209166) = [[timeUs=209166, position=27035]]
|
||||||
|
getPosition(418333) = [[timeUs=418333, position=75365]]
|
||||||
|
numberOfTracks = 1
|
||||||
|
track 0:
|
||||||
|
total output bytes = 94656
|
||||||
|
sample count = 32
|
||||||
|
format 0:
|
||||||
|
id = 1
|
||||||
|
sampleMimeType = audio/true-hd
|
||||||
|
maxInputSize = 12480
|
||||||
|
channelCount = 2
|
||||||
|
sampleRate = 48000
|
||||||
|
language = und
|
||||||
|
sample 0:
|
||||||
|
time = 0
|
||||||
|
flags = 1
|
||||||
|
data = length 3512, hash B77F1117
|
||||||
|
sample 1:
|
||||||
|
time = 13333
|
||||||
|
flags = 0
|
||||||
|
data = length 2830, hash 4B19B7D5
|
||||||
|
sample 2:
|
||||||
|
time = 26666
|
||||||
|
flags = 0
|
||||||
|
data = length 2868, hash BC04A38E
|
||||||
|
sample 3:
|
||||||
|
time = 40000
|
||||||
|
flags = 0
|
||||||
|
data = length 2834, hash D2AF8AF9
|
||||||
|
sample 4:
|
||||||
|
time = 53333
|
||||||
|
flags = 0
|
||||||
|
data = length 2898, hash 5C9B3119
|
||||||
|
sample 5:
|
||||||
|
time = 66666
|
||||||
|
flags = 0
|
||||||
|
data = length 2800, hash 31B9C93F
|
||||||
|
sample 6:
|
||||||
|
time = 80000
|
||||||
|
flags = 0
|
||||||
|
data = length 2866, hash 7FCABDBC
|
||||||
|
sample 7:
|
||||||
|
time = 93333
|
||||||
|
flags = 0
|
||||||
|
data = length 2980, hash FC2CCBDA
|
||||||
|
sample 8:
|
||||||
|
time = 106666
|
||||||
|
flags = 1
|
||||||
|
data = length 3432, hash 17F43166
|
||||||
|
sample 9:
|
||||||
|
time = 120000
|
||||||
|
flags = 0
|
||||||
|
data = length 2974, hash 69EDFD38
|
||||||
|
sample 10:
|
||||||
|
time = 133333
|
||||||
|
flags = 0
|
||||||
|
data = length 2898, hash 60E09542
|
||||||
|
sample 11:
|
||||||
|
time = 146666
|
||||||
|
flags = 0
|
||||||
|
data = length 2896, hash 94A43D4A
|
||||||
|
sample 12:
|
||||||
|
time = 160000
|
||||||
|
flags = 0
|
||||||
|
data = length 3008, hash 82D706BB
|
||||||
|
sample 13:
|
||||||
|
time = 173333
|
||||||
|
flags = 0
|
||||||
|
data = length 2918, hash 22DE72A8
|
||||||
|
sample 14:
|
||||||
|
time = 186666
|
||||||
|
flags = 0
|
||||||
|
data = length 2990, hash E478A008
|
||||||
|
sample 15:
|
||||||
|
time = 200000
|
||||||
|
flags = 0
|
||||||
|
data = length 2860, hash B5C3DE40
|
||||||
|
sample 16:
|
||||||
|
time = 213333
|
||||||
|
flags = 1
|
||||||
|
data = length 3638, hash 3FCD885B
|
||||||
|
sample 17:
|
||||||
|
time = 226666
|
||||||
|
flags = 0
|
||||||
|
data = length 2968, hash A3692382
|
||||||
|
sample 18:
|
||||||
|
time = 240000
|
||||||
|
flags = 0
|
||||||
|
data = length 2940, hash 72A71C81
|
||||||
|
sample 19:
|
||||||
|
time = 253333
|
||||||
|
flags = 0
|
||||||
|
data = length 3010, hash A826B2C3
|
||||||
|
sample 20:
|
||||||
|
time = 266666
|
||||||
|
flags = 0
|
||||||
|
data = length 2952, hash BCEA8C02
|
||||||
|
sample 21:
|
||||||
|
time = 280000
|
||||||
|
flags = 0
|
||||||
|
data = length 3018, hash C313A53F
|
||||||
|
sample 22:
|
||||||
|
time = 293333
|
||||||
|
flags = 0
|
||||||
|
data = length 2930, hash 4AAB358
|
||||||
|
sample 23:
|
||||||
|
time = 306666
|
||||||
|
flags = 0
|
||||||
|
data = length 2898, hash C2C22662
|
||||||
|
sample 24:
|
||||||
|
time = 320000
|
||||||
|
flags = 1
|
||||||
|
data = length 3680, hash 354DF989
|
||||||
|
sample 25:
|
||||||
|
time = 333333
|
||||||
|
flags = 0
|
||||||
|
data = length 2970, hash 3191F764
|
||||||
|
sample 26:
|
||||||
|
time = 346666
|
||||||
|
flags = 0
|
||||||
|
data = length 3044, hash 9E115802
|
||||||
|
sample 27:
|
||||||
|
time = 360000
|
||||||
|
flags = 0
|
||||||
|
data = length 2946, hash B1341399
|
||||||
|
sample 28:
|
||||||
|
time = 373333
|
||||||
|
flags = 0
|
||||||
|
data = length 2992, hash 4DA27845
|
||||||
|
sample 29:
|
||||||
|
time = 386666
|
||||||
|
flags = 0
|
||||||
|
data = length 2930, hash 140DC44C
|
||||||
|
sample 30:
|
||||||
|
time = 400000
|
||||||
|
flags = 0
|
||||||
|
data = length 2960, hash 5287EBF8
|
||||||
|
sample 31:
|
||||||
|
time = 413333
|
||||||
|
flags = 0
|
||||||
|
data = length 1216, hash B83FE151
|
||||||
|
tracksEnded = true
|
115
testdata/src/test/assets/extractordumps/mp4/sample_dthd.mp4.1.dump
vendored
Normal file
115
testdata/src/test/assets/extractordumps/mp4/sample_dthd.mp4.1.dump
vendored
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
seekMap:
|
||||||
|
isSeekable = true
|
||||||
|
duration = 418333
|
||||||
|
getPosition(0) = [[timeUs=0, position=3447]]
|
||||||
|
getPosition(1) = [[timeUs=1, position=3447]]
|
||||||
|
getPosition(209166) = [[timeUs=209166, position=27035]]
|
||||||
|
getPosition(418333) = [[timeUs=418333, position=75365]]
|
||||||
|
numberOfTracks = 1
|
||||||
|
track 0:
|
||||||
|
total output bytes = 71068
|
||||||
|
sample count = 24
|
||||||
|
format 0:
|
||||||
|
id = 1
|
||||||
|
sampleMimeType = audio/true-hd
|
||||||
|
maxInputSize = 12480
|
||||||
|
channelCount = 2
|
||||||
|
sampleRate = 48000
|
||||||
|
language = und
|
||||||
|
sample 0:
|
||||||
|
time = 106666
|
||||||
|
flags = 1
|
||||||
|
data = length 3432, hash 17F43166
|
||||||
|
sample 1:
|
||||||
|
time = 120000
|
||||||
|
flags = 0
|
||||||
|
data = length 2974, hash 69EDFD38
|
||||||
|
sample 2:
|
||||||
|
time = 133333
|
||||||
|
flags = 0
|
||||||
|
data = length 2898, hash 60E09542
|
||||||
|
sample 3:
|
||||||
|
time = 146666
|
||||||
|
flags = 0
|
||||||
|
data = length 2896, hash 94A43D4A
|
||||||
|
sample 4:
|
||||||
|
time = 160000
|
||||||
|
flags = 0
|
||||||
|
data = length 3008, hash 82D706BB
|
||||||
|
sample 5:
|
||||||
|
time = 173333
|
||||||
|
flags = 0
|
||||||
|
data = length 2918, hash 22DE72A8
|
||||||
|
sample 6:
|
||||||
|
time = 186666
|
||||||
|
flags = 0
|
||||||
|
data = length 2990, hash E478A008
|
||||||
|
sample 7:
|
||||||
|
time = 200000
|
||||||
|
flags = 0
|
||||||
|
data = length 2860, hash B5C3DE40
|
||||||
|
sample 8:
|
||||||
|
time = 213333
|
||||||
|
flags = 1
|
||||||
|
data = length 3638, hash 3FCD885B
|
||||||
|
sample 9:
|
||||||
|
time = 226666
|
||||||
|
flags = 0
|
||||||
|
data = length 2968, hash A3692382
|
||||||
|
sample 10:
|
||||||
|
time = 240000
|
||||||
|
flags = 0
|
||||||
|
data = length 2940, hash 72A71C81
|
||||||
|
sample 11:
|
||||||
|
time = 253333
|
||||||
|
flags = 0
|
||||||
|
data = length 3010, hash A826B2C3
|
||||||
|
sample 12:
|
||||||
|
time = 266666
|
||||||
|
flags = 0
|
||||||
|
data = length 2952, hash BCEA8C02
|
||||||
|
sample 13:
|
||||||
|
time = 280000
|
||||||
|
flags = 0
|
||||||
|
data = length 3018, hash C313A53F
|
||||||
|
sample 14:
|
||||||
|
time = 293333
|
||||||
|
flags = 0
|
||||||
|
data = length 2930, hash 4AAB358
|
||||||
|
sample 15:
|
||||||
|
time = 306666
|
||||||
|
flags = 0
|
||||||
|
data = length 2898, hash C2C22662
|
||||||
|
sample 16:
|
||||||
|
time = 320000
|
||||||
|
flags = 1
|
||||||
|
data = length 3680, hash 354DF989
|
||||||
|
sample 17:
|
||||||
|
time = 333333
|
||||||
|
flags = 0
|
||||||
|
data = length 2970, hash 3191F764
|
||||||
|
sample 18:
|
||||||
|
time = 346666
|
||||||
|
flags = 0
|
||||||
|
data = length 3044, hash 9E115802
|
||||||
|
sample 19:
|
||||||
|
time = 360000
|
||||||
|
flags = 0
|
||||||
|
data = length 2946, hash B1341399
|
||||||
|
sample 20:
|
||||||
|
time = 373333
|
||||||
|
flags = 0
|
||||||
|
data = length 2992, hash 4DA27845
|
||||||
|
sample 21:
|
||||||
|
time = 386666
|
||||||
|
flags = 0
|
||||||
|
data = length 2930, hash 140DC44C
|
||||||
|
sample 22:
|
||||||
|
time = 400000
|
||||||
|
flags = 0
|
||||||
|
data = length 2960, hash 5287EBF8
|
||||||
|
sample 23:
|
||||||
|
time = 413333
|
||||||
|
flags = 0
|
||||||
|
data = length 1216, hash B83FE151
|
||||||
|
tracksEnded = true
|
83
testdata/src/test/assets/extractordumps/mp4/sample_dthd.mp4.2.dump
vendored
Normal file
83
testdata/src/test/assets/extractordumps/mp4/sample_dthd.mp4.2.dump
vendored
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
seekMap:
|
||||||
|
isSeekable = true
|
||||||
|
duration = 418333
|
||||||
|
getPosition(0) = [[timeUs=0, position=3447]]
|
||||||
|
getPosition(1) = [[timeUs=1, position=3447]]
|
||||||
|
getPosition(209166) = [[timeUs=209166, position=27035]]
|
||||||
|
getPosition(418333) = [[timeUs=418333, position=75365]]
|
||||||
|
numberOfTracks = 1
|
||||||
|
track 0:
|
||||||
|
total output bytes = 47092
|
||||||
|
sample count = 16
|
||||||
|
format 0:
|
||||||
|
id = 1
|
||||||
|
sampleMimeType = audio/true-hd
|
||||||
|
maxInputSize = 12480
|
||||||
|
channelCount = 2
|
||||||
|
sampleRate = 48000
|
||||||
|
language = und
|
||||||
|
sample 0:
|
||||||
|
time = 213333
|
||||||
|
flags = 1
|
||||||
|
data = length 3638, hash 3FCD885B
|
||||||
|
sample 1:
|
||||||
|
time = 226666
|
||||||
|
flags = 0
|
||||||
|
data = length 2968, hash A3692382
|
||||||
|
sample 2:
|
||||||
|
time = 240000
|
||||||
|
flags = 0
|
||||||
|
data = length 2940, hash 72A71C81
|
||||||
|
sample 3:
|
||||||
|
time = 253333
|
||||||
|
flags = 0
|
||||||
|
data = length 3010, hash A826B2C3
|
||||||
|
sample 4:
|
||||||
|
time = 266666
|
||||||
|
flags = 0
|
||||||
|
data = length 2952, hash BCEA8C02
|
||||||
|
sample 5:
|
||||||
|
time = 280000
|
||||||
|
flags = 0
|
||||||
|
data = length 3018, hash C313A53F
|
||||||
|
sample 6:
|
||||||
|
time = 293333
|
||||||
|
flags = 0
|
||||||
|
data = length 2930, hash 4AAB358
|
||||||
|
sample 7:
|
||||||
|
time = 306666
|
||||||
|
flags = 0
|
||||||
|
data = length 2898, hash C2C22662
|
||||||
|
sample 8:
|
||||||
|
time = 320000
|
||||||
|
flags = 1
|
||||||
|
data = length 3680, hash 354DF989
|
||||||
|
sample 9:
|
||||||
|
time = 333333
|
||||||
|
flags = 0
|
||||||
|
data = length 2970, hash 3191F764
|
||||||
|
sample 10:
|
||||||
|
time = 346666
|
||||||
|
flags = 0
|
||||||
|
data = length 3044, hash 9E115802
|
||||||
|
sample 11:
|
||||||
|
time = 360000
|
||||||
|
flags = 0
|
||||||
|
data = length 2946, hash B1341399
|
||||||
|
sample 12:
|
||||||
|
time = 373333
|
||||||
|
flags = 0
|
||||||
|
data = length 2992, hash 4DA27845
|
||||||
|
sample 13:
|
||||||
|
time = 386666
|
||||||
|
flags = 0
|
||||||
|
data = length 2930, hash 140DC44C
|
||||||
|
sample 14:
|
||||||
|
time = 400000
|
||||||
|
flags = 0
|
||||||
|
data = length 2960, hash 5287EBF8
|
||||||
|
sample 15:
|
||||||
|
time = 413333
|
||||||
|
flags = 0
|
||||||
|
data = length 1216, hash B83FE151
|
||||||
|
tracksEnded = true
|
51
testdata/src/test/assets/extractordumps/mp4/sample_dthd.mp4.3.dump
vendored
Normal file
51
testdata/src/test/assets/extractordumps/mp4/sample_dthd.mp4.3.dump
vendored
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
seekMap:
|
||||||
|
isSeekable = true
|
||||||
|
duration = 418333
|
||||||
|
getPosition(0) = [[timeUs=0, position=3447]]
|
||||||
|
getPosition(1) = [[timeUs=1, position=3447]]
|
||||||
|
getPosition(209166) = [[timeUs=209166, position=27035]]
|
||||||
|
getPosition(418333) = [[timeUs=418333, position=75365]]
|
||||||
|
numberOfTracks = 1
|
||||||
|
track 0:
|
||||||
|
total output bytes = 22738
|
||||||
|
sample count = 8
|
||||||
|
format 0:
|
||||||
|
id = 1
|
||||||
|
sampleMimeType = audio/true-hd
|
||||||
|
maxInputSize = 12480
|
||||||
|
channelCount = 2
|
||||||
|
sampleRate = 48000
|
||||||
|
language = und
|
||||||
|
sample 0:
|
||||||
|
time = 320000
|
||||||
|
flags = 1
|
||||||
|
data = length 3680, hash 354DF989
|
||||||
|
sample 1:
|
||||||
|
time = 333333
|
||||||
|
flags = 0
|
||||||
|
data = length 2970, hash 3191F764
|
||||||
|
sample 2:
|
||||||
|
time = 346666
|
||||||
|
flags = 0
|
||||||
|
data = length 3044, hash 9E115802
|
||||||
|
sample 3:
|
||||||
|
time = 360000
|
||||||
|
flags = 0
|
||||||
|
data = length 2946, hash B1341399
|
||||||
|
sample 4:
|
||||||
|
time = 373333
|
||||||
|
flags = 0
|
||||||
|
data = length 2992, hash 4DA27845
|
||||||
|
sample 5:
|
||||||
|
time = 386666
|
||||||
|
flags = 0
|
||||||
|
data = length 2930, hash 140DC44C
|
||||||
|
sample 6:
|
||||||
|
time = 400000
|
||||||
|
flags = 0
|
||||||
|
data = length 2960, hash 5287EBF8
|
||||||
|
sample 7:
|
||||||
|
time = 413333
|
||||||
|
flags = 0
|
||||||
|
data = length 1216, hash B83FE151
|
||||||
|
tracksEnded = true
|
147
testdata/src/test/assets/extractordumps/mp4/sample_dthd.mp4.unknown_length.dump
vendored
Normal file
147
testdata/src/test/assets/extractordumps/mp4/sample_dthd.mp4.unknown_length.dump
vendored
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
seekMap:
|
||||||
|
isSeekable = true
|
||||||
|
duration = 418333
|
||||||
|
getPosition(0) = [[timeUs=0, position=3447]]
|
||||||
|
getPosition(1) = [[timeUs=1, position=3447]]
|
||||||
|
getPosition(209166) = [[timeUs=209166, position=27035]]
|
||||||
|
getPosition(418333) = [[timeUs=418333, position=75365]]
|
||||||
|
numberOfTracks = 1
|
||||||
|
track 0:
|
||||||
|
total output bytes = 94656
|
||||||
|
sample count = 32
|
||||||
|
format 0:
|
||||||
|
id = 1
|
||||||
|
sampleMimeType = audio/true-hd
|
||||||
|
maxInputSize = 12480
|
||||||
|
channelCount = 2
|
||||||
|
sampleRate = 48000
|
||||||
|
language = und
|
||||||
|
sample 0:
|
||||||
|
time = 0
|
||||||
|
flags = 1
|
||||||
|
data = length 3512, hash B77F1117
|
||||||
|
sample 1:
|
||||||
|
time = 13333
|
||||||
|
flags = 0
|
||||||
|
data = length 2830, hash 4B19B7D5
|
||||||
|
sample 2:
|
||||||
|
time = 26666
|
||||||
|
flags = 0
|
||||||
|
data = length 2868, hash BC04A38E
|
||||||
|
sample 3:
|
||||||
|
time = 40000
|
||||||
|
flags = 0
|
||||||
|
data = length 2834, hash D2AF8AF9
|
||||||
|
sample 4:
|
||||||
|
time = 53333
|
||||||
|
flags = 0
|
||||||
|
data = length 2898, hash 5C9B3119
|
||||||
|
sample 5:
|
||||||
|
time = 66666
|
||||||
|
flags = 0
|
||||||
|
data = length 2800, hash 31B9C93F
|
||||||
|
sample 6:
|
||||||
|
time = 80000
|
||||||
|
flags = 0
|
||||||
|
data = length 2866, hash 7FCABDBC
|
||||||
|
sample 7:
|
||||||
|
time = 93333
|
||||||
|
flags = 0
|
||||||
|
data = length 2980, hash FC2CCBDA
|
||||||
|
sample 8:
|
||||||
|
time = 106666
|
||||||
|
flags = 1
|
||||||
|
data = length 3432, hash 17F43166
|
||||||
|
sample 9:
|
||||||
|
time = 120000
|
||||||
|
flags = 0
|
||||||
|
data = length 2974, hash 69EDFD38
|
||||||
|
sample 10:
|
||||||
|
time = 133333
|
||||||
|
flags = 0
|
||||||
|
data = length 2898, hash 60E09542
|
||||||
|
sample 11:
|
||||||
|
time = 146666
|
||||||
|
flags = 0
|
||||||
|
data = length 2896, hash 94A43D4A
|
||||||
|
sample 12:
|
||||||
|
time = 160000
|
||||||
|
flags = 0
|
||||||
|
data = length 3008, hash 82D706BB
|
||||||
|
sample 13:
|
||||||
|
time = 173333
|
||||||
|
flags = 0
|
||||||
|
data = length 2918, hash 22DE72A8
|
||||||
|
sample 14:
|
||||||
|
time = 186666
|
||||||
|
flags = 0
|
||||||
|
data = length 2990, hash E478A008
|
||||||
|
sample 15:
|
||||||
|
time = 200000
|
||||||
|
flags = 0
|
||||||
|
data = length 2860, hash B5C3DE40
|
||||||
|
sample 16:
|
||||||
|
time = 213333
|
||||||
|
flags = 1
|
||||||
|
data = length 3638, hash 3FCD885B
|
||||||
|
sample 17:
|
||||||
|
time = 226666
|
||||||
|
flags = 0
|
||||||
|
data = length 2968, hash A3692382
|
||||||
|
sample 18:
|
||||||
|
time = 240000
|
||||||
|
flags = 0
|
||||||
|
data = length 2940, hash 72A71C81
|
||||||
|
sample 19:
|
||||||
|
time = 253333
|
||||||
|
flags = 0
|
||||||
|
data = length 3010, hash A826B2C3
|
||||||
|
sample 20:
|
||||||
|
time = 266666
|
||||||
|
flags = 0
|
||||||
|
data = length 2952, hash BCEA8C02
|
||||||
|
sample 21:
|
||||||
|
time = 280000
|
||||||
|
flags = 0
|
||||||
|
data = length 3018, hash C313A53F
|
||||||
|
sample 22:
|
||||||
|
time = 293333
|
||||||
|
flags = 0
|
||||||
|
data = length 2930, hash 4AAB358
|
||||||
|
sample 23:
|
||||||
|
time = 306666
|
||||||
|
flags = 0
|
||||||
|
data = length 2898, hash C2C22662
|
||||||
|
sample 24:
|
||||||
|
time = 320000
|
||||||
|
flags = 1
|
||||||
|
data = length 3680, hash 354DF989
|
||||||
|
sample 25:
|
||||||
|
time = 333333
|
||||||
|
flags = 0
|
||||||
|
data = length 2970, hash 3191F764
|
||||||
|
sample 26:
|
||||||
|
time = 346666
|
||||||
|
flags = 0
|
||||||
|
data = length 3044, hash 9E115802
|
||||||
|
sample 27:
|
||||||
|
time = 360000
|
||||||
|
flags = 0
|
||||||
|
data = length 2946, hash B1341399
|
||||||
|
sample 28:
|
||||||
|
time = 373333
|
||||||
|
flags = 0
|
||||||
|
data = length 2992, hash 4DA27845
|
||||||
|
sample 29:
|
||||||
|
time = 386666
|
||||||
|
flags = 0
|
||||||
|
data = length 2930, hash 140DC44C
|
||||||
|
sample 30:
|
||||||
|
time = 400000
|
||||||
|
flags = 0
|
||||||
|
data = length 2960, hash 5287EBF8
|
||||||
|
sample 31:
|
||||||
|
time = 413333
|
||||||
|
flags = 0
|
||||||
|
data = length 1216, hash B83FE151
|
||||||
|
tracksEnded = true
|
BIN
testdata/src/test/assets/media/mp4/sample_dthd.mp4
vendored
Normal file
BIN
testdata/src/test/assets/media/mp4/sample_dthd.mp4
vendored
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user