From d3f4da749c8313b78d0526cacdf4ad593a774506 Mon Sep 17 00:00:00 2001 From: olly Date: Fri, 3 Feb 2017 07:06:58 -0800 Subject: [PATCH] Propagate track type through ExtractorOutput.track This allows binding by track type in ChunkExtractorWrapper, which allows the EMSG and 608 tracks to be enabled on FragmentedMp4Extractor in DefaultDashChunkSource. ChunkExtractorWrapper currently binds these to DummyTrackOutputs. Note: I wanted to pass the mimeType instead, since it's a more specific, but unfortunately there's at least one place where it's not known at the point of invoking track() (FlvExtractor). Issue #2176 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=146471082 --- .../exoplayer2/ext/flac/FlacExtractor.java | 2 +- .../extractor/ts/AdtsReaderTest.java | 4 +-- .../extractor/ts/TsExtractorTest.java | 3 ++- .../exoplayer2/drm/OfflineLicenseHelper.java | 8 +++--- .../exoplayer2/extractor/ExtractorOutput.java | 11 ++++---- .../extractor/flv/FlvExtractor.java | 7 +++-- .../extractor/mkv/MatroskaExtractor.java | 7 ++++- .../extractor/mp3/Mp3Extractor.java | 2 +- .../extractor/mp4/FragmentedMp4Extractor.java | 27 ++++++++++++------- .../extractor/mp4/Mp4Extractor.java | 3 ++- .../extractor/ogg/OggExtractor.java | 3 ++- .../extractor/rawcc/RawCcExtractor.java | 2 +- .../exoplayer2/extractor/ts/Ac3Reader.java | 2 +- .../exoplayer2/extractor/ts/AdtsReader.java | 4 +-- .../exoplayer2/extractor/ts/DtsReader.java | 2 +- .../exoplayer2/extractor/ts/H262Reader.java | 2 +- .../exoplayer2/extractor/ts/H264Reader.java | 2 +- .../exoplayer2/extractor/ts/H265Reader.java | 2 +- .../exoplayer2/extractor/ts/Id3Reader.java | 2 +- .../extractor/ts/MpegAudioReader.java | 2 +- .../exoplayer2/extractor/ts/SeiReader.java | 3 ++- .../extractor/ts/SpliceInfoSectionReader.java | 2 +- .../extractor/wav/WavExtractor.java | 2 +- .../source/ExtractorMediaPeriod.java | 2 +- .../source/chunk/ChunkExtractorWrapper.java | 12 +++++++-- .../source/dash/DefaultDashChunkSource.java | 23 ++++++++++------ .../source/hls/HlsSampleStreamWrapper.java | 4 +-- .../source/hls/WebvttExtractor.java | 2 +- .../smoothstreaming/DefaultSsChunkSource.java | 5 ++-- .../testutil/FakeExtractorOutput.java | 6 ++--- 30 files changed, 98 insertions(+), 60 deletions(-) diff --git a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java index 42c59086196..d13194793eb 100644 --- a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java +++ b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java @@ -67,7 +67,7 @@ public Extractor[] createExtractors() { @Override public void init(ExtractorOutput output) { extractorOutput = output; - trackOutput = extractorOutput.track(0); + trackOutput = extractorOutput.track(0, C.TRACK_TYPE_AUDIO); extractorOutput.endTracks(); try { decoderJni = new FlacDecoderJni(); diff --git a/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/AdtsReaderTest.java b/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/AdtsReaderTest.java index ebb547810bb..bcfa90a565d 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/AdtsReaderTest.java +++ b/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/AdtsReaderTest.java @@ -69,8 +69,8 @@ public class AdtsReaderTest extends TestCase { @Override protected void setUp() throws Exception { FakeExtractorOutput fakeExtractorOutput = new FakeExtractorOutput(); - adtsOutput = fakeExtractorOutput.track(0); - id3Output = fakeExtractorOutput.track(1); + adtsOutput = fakeExtractorOutput.track(0, C.TRACK_TYPE_AUDIO); + id3Output = fakeExtractorOutput.track(1, C.TRACK_TYPE_METADATA); adtsReader = new AdtsReader(true); TrackIdGenerator idGenerator = new TrackIdGenerator(0, 1); adtsReader.createTracks(fakeExtractorOutput, idGenerator); diff --git a/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java b/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java index 74e07481198..9bcb1c2377f 100644 --- a/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java +++ b/library/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java @@ -17,6 +17,7 @@ import android.test.InstrumentationTestCase; import android.util.SparseArray; +import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.ExtractorOutput; @@ -179,7 +180,7 @@ public void seek() { @Override public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { idGenerator.generateNewId(); - output = extractorOutput.track(idGenerator.getTrackId()); + output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_UNKNOWN); output.format(Format.createTextSampleFormat(idGenerator.getFormatId(), "mime", null, 0, 0, language, null, 0)); } diff --git a/library/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java b/library/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java index 0f979d6a4f5..8d057230ca7 100644 --- a/library/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java +++ b/library/src/main/java/com/google/android/exoplayer2/drm/OfflineLicenseHelper.java @@ -210,7 +210,8 @@ public byte[] download(HttpDataSource dataSource, DashManifest dashManifest) Representation representation = adaptationSet.representations.get(0); DrmInitData drmInitData = representation.format.drmInitData; if (drmInitData == null) { - ChunkExtractorWrapper extractorWrapper = newWrappedExtractor(representation.format); + ChunkExtractorWrapper extractorWrapper = newWrappedExtractor(representation.format, + adaptationSet.type); InitializationChunk initializationChunk = loadInitializationChunk(dataSource, representation, extractorWrapper); if (initializationChunk == null) { @@ -306,12 +307,13 @@ private static InitializationChunk loadInitializationChunk(DataSource dataSource return initializationChunk; } - private static ChunkExtractorWrapper newWrappedExtractor(final Format format) { + private static ChunkExtractorWrapper newWrappedExtractor(Format format, int trackType) { final String mimeType = format.containerMimeType; final boolean isWebm = mimeType.startsWith(MimeTypes.VIDEO_WEBM) || mimeType.startsWith(MimeTypes.AUDIO_WEBM); final Extractor extractor = isWebm ? new MatroskaExtractor() : new FragmentedMp4Extractor(); - return new ChunkExtractorWrapper(extractor, format, false /* preferManifestDrmInitData */); + return new ChunkExtractorWrapper(extractor, format, trackType, + false /* preferManifestDrmInitData */); } } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ExtractorOutput.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ExtractorOutput.java index a547f745ca1..a59cb1d1f24 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ExtractorOutput.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ExtractorOutput.java @@ -23,17 +23,18 @@ public interface ExtractorOutput { /** * Called by the {@link Extractor} to get the {@link TrackOutput} for a specific track. *

- * The same {@link TrackOutput} is returned if multiple calls are made with the same - * {@code trackId}. + * The same {@link TrackOutput} is returned if multiple calls are made with the same {@code id}. * - * @param trackId A track identifier. + * @param id A track identifier. + * @param type The type of the track. Typically one of the {@link com.google.android.exoplayer2.C} + * {@code TRACK_TYPE_*} constants. * @return The {@link TrackOutput} for the given track identifier. */ - TrackOutput track(int trackId); + TrackOutput track(int id, int type); /** * Called when all tracks have been identified, meaning no new {@code trackId} values will be - * passed to {@link #track(int)}. + * passed to {@link #track(int, int)}. */ void endTracks(); diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java b/library/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java index 5b396749acc..218e6ffd82d 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/flv/FlvExtractor.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.extractor.flv; +import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.extractor.ExtractorOutput; @@ -183,10 +184,12 @@ private boolean readFlvHeader(ExtractorInput input) throws IOException, Interrup boolean hasAudio = (flags & 0x04) != 0; boolean hasVideo = (flags & 0x01) != 0; if (hasAudio && audioReader == null) { - audioReader = new AudioTagPayloadReader(extractorOutput.track(TAG_TYPE_AUDIO)); + audioReader = new AudioTagPayloadReader( + extractorOutput.track(TAG_TYPE_AUDIO, C.TRACK_TYPE_AUDIO)); } if (hasVideo && videoReader == null) { - videoReader = new VideoTagPayloadReader(extractorOutput.track(TAG_TYPE_VIDEO)); + videoReader = new VideoTagPayloadReader( + extractorOutput.track(TAG_TYPE_VIDEO, C.TRACK_TYPE_VIDEO)); } if (metadataReader == null) { metadataReader = new ScriptTagPayloadReader(null); diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java b/library/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java index 970335e9d25..ed1a86e6517 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java @@ -1462,6 +1462,7 @@ public void initializeOutput(ExtractorOutput output, int trackId) throws ParserE throw new ParserException("Unrecognized codec identifier."); } + int type; Format format; @C.SelectionFlags int selectionFlags = 0; selectionFlags |= flagDefault ? C.SELECTION_FLAG_DEFAULT : 0; @@ -1469,10 +1470,12 @@ public void initializeOutput(ExtractorOutput output, int trackId) throws ParserE // TODO: Consider reading the name elements of the tracks and, if present, incorporating them // into the trackId passed when creating the formats. if (MimeTypes.isAudio(mimeType)) { + type = C.TRACK_TYPE_AUDIO; format = Format.createAudioSampleFormat(Integer.toString(trackId), mimeType, null, Format.NO_VALUE, maxInputSize, channelCount, sampleRate, pcmEncoding, initializationData, drmInitData, selectionFlags, language); } else if (MimeTypes.isVideo(mimeType)) { + type = C.TRACK_TYPE_VIDEO; if (displayUnit == Track.DISPLAY_UNIT_PIXELS) { displayWidth = displayWidth == Format.NO_VALUE ? width : displayWidth; displayHeight = displayHeight == Format.NO_VALUE ? height : displayHeight; @@ -1485,17 +1488,19 @@ public void initializeOutput(ExtractorOutput output, int trackId) throws ParserE Format.NO_VALUE, maxInputSize, width, height, Format.NO_VALUE, initializationData, Format.NO_VALUE, pixelWidthHeightRatio, projectionData, stereoMode, drmInitData); } else if (MimeTypes.APPLICATION_SUBRIP.equals(mimeType)) { + type = C.TRACK_TYPE_TEXT; format = Format.createTextSampleFormat(Integer.toString(trackId), mimeType, null, Format.NO_VALUE, selectionFlags, language, drmInitData); } else if (MimeTypes.APPLICATION_VOBSUB.equals(mimeType) || MimeTypes.APPLICATION_PGS.equals(mimeType)) { + type = C.TRACK_TYPE_TEXT; format = Format.createImageSampleFormat(Integer.toString(trackId), mimeType, null, Format.NO_VALUE, initializationData, language, drmInitData); } else { throw new ParserException("Unexpected MIME type."); } - this.output = output.track(number); + this.output = output.track(number, type); this.output.format(format); } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java b/library/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java index 9bdefeceafd..ff84c7da253 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/mp3/Mp3Extractor.java @@ -118,7 +118,7 @@ public boolean sniff(ExtractorInput input) throws IOException, InterruptedExcept @Override public void init(ExtractorOutput output) { extractorOutput = output; - trackOutput = extractorOutput.track(0); + trackOutput = extractorOutput.track(0, C.TRACK_TYPE_AUDIO); extractorOutput.endTracks(); } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java b/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java index f7cc42c48f5..d72eb625096 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/FragmentedMp4Extractor.java @@ -164,7 +164,14 @@ public Extractor[] createExtractors() { private boolean haveOutputSeekMap; public FragmentedMp4Extractor() { - this(0, null); + this(0); + } + + /** + * @param flags Flags that control the extractor's behavior. + */ + public FragmentedMp4Extractor(@Flags int flags) { + this(flags, null); } /** @@ -172,20 +179,20 @@ public FragmentedMp4Extractor() { * @param timestampAdjuster Adjusts sample timestamps. May be null if no adjustment is needed. */ public FragmentedMp4Extractor(@Flags int flags, TimestampAdjuster timestampAdjuster) { - this(flags, null, timestampAdjuster); + this(flags, timestampAdjuster, null); } /** * @param flags Flags that control the extractor's behavior. + * @param timestampAdjuster Adjusts sample timestamps. May be null if no adjustment is needed. * @param sideloadedTrack Sideloaded track information, in the case that the extractor * will not receive a moov box in the input data. - * @param timestampAdjuster Adjusts sample timestamps. May be null if no adjustment is needed. */ - public FragmentedMp4Extractor(@Flags int flags, Track sideloadedTrack, - TimestampAdjuster timestampAdjuster) { - this.sideloadedTrack = sideloadedTrack; + public FragmentedMp4Extractor(@Flags int flags, TimestampAdjuster timestampAdjuster, + Track sideloadedTrack) { this.flags = flags | (sideloadedTrack != null ? FLAG_SIDELOADED : 0); this.timestampAdjuster = timestampAdjuster; + this.sideloadedTrack = sideloadedTrack; atomHeader = new ParsableByteArray(Atom.LONG_HEADER_SIZE); nalStartCode = new ParsableByteArray(NalUnitUtil.NAL_START_CODE); nalLength = new ParsableByteArray(4); @@ -209,7 +216,7 @@ public boolean sniff(ExtractorInput input) throws IOException, InterruptedExcept public void init(ExtractorOutput output) { extractorOutput = output; if (sideloadedTrack != null) { - TrackBundle bundle = new TrackBundle(output.track(0)); + TrackBundle bundle = new TrackBundle(output.track(0, sideloadedTrack.type)); bundle.init(sideloadedTrack, new DefaultSampleValues(0, 0, 0, 0)); trackBundles.put(0, bundle); maybeInitExtraTracks(); @@ -420,7 +427,7 @@ private void onMoovContainerAtomRead(ContainerAtom moov) throws ParserException // We need to create the track bundles. for (int i = 0; i < trackCount; i++) { Track track = tracks.valueAt(i); - TrackBundle trackBundle = new TrackBundle(extractorOutput.track(i)); + TrackBundle trackBundle = new TrackBundle(extractorOutput.track(i, track.type)); trackBundle.init(track, defaultSampleValuesArray.get(track.id)); trackBundles.put(track.id, trackBundle); durationUs = Math.max(durationUs, track.durationUs); @@ -449,12 +456,12 @@ private void onMoofContainerAtomRead(ContainerAtom moof) throws ParserException private void maybeInitExtraTracks() { if ((flags & FLAG_ENABLE_EMSG_TRACK) != 0 && eventMessageTrackOutput == null) { - eventMessageTrackOutput = extractorOutput.track(trackBundles.size()); + eventMessageTrackOutput = extractorOutput.track(trackBundles.size(), C.TRACK_TYPE_METADATA); eventMessageTrackOutput.format(Format.createSampleFormat(null, MimeTypes.APPLICATION_EMSG, Format.OFFSET_SAMPLE_RELATIVE)); } if ((flags & FLAG_ENABLE_CEA608_TRACK) != 0 && cea608TrackOutput == null) { - cea608TrackOutput = extractorOutput.track(trackBundles.size() + 1); + cea608TrackOutput = extractorOutput.track(trackBundles.size() + 1, C.TRACK_TYPE_TEXT); cea608TrackOutput.format(Format.createTextSampleFormat(null, MimeTypes.APPLICATION_CEA608, null, Format.NO_VALUE, 0, null, null)); } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java b/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java index 3759a80fd4c..0c990f57473 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java @@ -344,7 +344,8 @@ private void processMoovAtom(ContainerAtom moov) throws ParserException { continue; } - Mp4Track mp4Track = new Mp4Track(track, trackSampleTable, extractorOutput.track(i)); + Mp4Track mp4Track = 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. // Allow ten source samples per output sample, like the platform extractor. int maxInputSize = trackSampleTable.maximumSize + 3 * 10; diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java index 5f411267377..cc3c5de3112 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ogg/OggExtractor.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.extractor.ogg; +import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ParserException; import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.ExtractorInput; @@ -75,7 +76,7 @@ public boolean sniff(ExtractorInput input) throws IOException, InterruptedExcept @Override public void init(ExtractorOutput output) { - TrackOutput trackOutput = output.track(0); + TrackOutput trackOutput = output.track(0, C.TRACK_TYPE_AUDIO); output.endTracks(); // TODO: fix the case if sniff() isn't called streamReader.init(output, trackOutput); diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.java b/library/src/main/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.java index f9957aebe52..7840eafce65 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/rawcc/RawCcExtractor.java @@ -65,7 +65,7 @@ public RawCcExtractor(Format format) { @Override public void init(ExtractorOutput output) { output.seekMap(new SeekMap.Unseekable(C.TIME_UNSET)); - trackOutput = output.track(0); + trackOutput = output.track(0, C.TRACK_TYPE_TEXT); output.endTracks(); trackOutput.format(format); } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java index afef154ed4c..790c036f1d2 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/Ac3Reader.java @@ -87,7 +87,7 @@ public void seek() { public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator generator) { generator.generateNewId(); trackFormatId = generator.getFormatId(); - output = extractorOutput.track(generator.getTrackId()); + output = extractorOutput.track(generator.getTrackId(), C.TRACK_TYPE_AUDIO); } @Override diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsReader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsReader.java index 56793119e46..58318ea78d3 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsReader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/AdtsReader.java @@ -111,10 +111,10 @@ public void seek() { public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { idGenerator.generateNewId(); formatId = idGenerator.getFormatId(); - output = extractorOutput.track(idGenerator.getTrackId()); + output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_AUDIO); if (exposeId3) { idGenerator.generateNewId(); - id3Output = extractorOutput.track(idGenerator.getTrackId()); + id3Output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_METADATA); id3Output.format(Format.createSampleFormat(idGenerator.getFormatId(), MimeTypes.APPLICATION_ID3, null, Format.NO_VALUE, null)); } else { diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/DtsReader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/DtsReader.java index 50be258ae58..874de83b686 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/DtsReader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/DtsReader.java @@ -82,7 +82,7 @@ public void seek() { public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { idGenerator.generateNewId(); formatId = idGenerator.getFormatId(); - output = extractorOutput.track(idGenerator.getTrackId()); + output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_AUDIO); } @Override diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H262Reader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H262Reader.java index df6ba208c3d..ba515d31ed0 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H262Reader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H262Reader.java @@ -81,7 +81,7 @@ public void seek() { public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { idGenerator.generateNewId(); formatId = idGenerator.getFormatId(); - output = extractorOutput.track(idGenerator.getTrackId()); + output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_VIDEO); } @Override diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java index 5b9c2cdcea7..c1d24b7a33a 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H264Reader.java @@ -93,7 +93,7 @@ public void seek() { public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { idGenerator.generateNewId(); formatId = idGenerator.getFormatId(); - output = extractorOutput.track(idGenerator.getTrackId()); + output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_VIDEO); sampleReader = new SampleReader(output, allowNonIdrKeyframes, detectAccessUnits); seiReader.createTracks(extractorOutput, idGenerator); } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java index 93cfe9f5cbd..30a5bdc1fd4 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/H265Reader.java @@ -98,7 +98,7 @@ public void seek() { public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { idGenerator.generateNewId(); formatId = idGenerator.getFormatId(); - output = extractorOutput.track(idGenerator.getTrackId()); + output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_VIDEO); sampleReader = new SampleReader(output); seiReader.createTracks(extractorOutput, idGenerator); } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/Id3Reader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/Id3Reader.java index 27eb2a1bb42..7d2ecc4e74c 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/Id3Reader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/Id3Reader.java @@ -57,7 +57,7 @@ public void seek() { @Override public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { idGenerator.generateNewId(); - output = extractorOutput.track(idGenerator.getTrackId()); + output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_METADATA); output.format(Format.createSampleFormat(idGenerator.getFormatId(), MimeTypes.APPLICATION_ID3, null, Format.NO_VALUE, null)); } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/MpegAudioReader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/MpegAudioReader.java index ae7edc51e42..6301716286e 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/MpegAudioReader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/MpegAudioReader.java @@ -79,7 +79,7 @@ public void seek() { public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { idGenerator.generateNewId(); formatId = idGenerator.getFormatId(); - output = extractorOutput.track(idGenerator.getTrackId()); + output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_AUDIO); } @Override diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/SeiReader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/SeiReader.java index ced28c3b934..a3f4deffcb7 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/SeiReader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/SeiReader.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.extractor.ts; +import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.TrackOutput; @@ -32,7 +33,7 @@ public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { idGenerator.generateNewId(); - output = extractorOutput.track(idGenerator.getTrackId()); + output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_TEXT); output.format(Format.createTextSampleFormat(idGenerator.getFormatId(), MimeTypes.APPLICATION_CEA608, null, Format.NO_VALUE, 0, null, null)); } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/SpliceInfoSectionReader.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/SpliceInfoSectionReader.java index 625bb705609..27838d4c257 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/SpliceInfoSectionReader.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/SpliceInfoSectionReader.java @@ -37,7 +37,7 @@ public void init(TimestampAdjuster timestampAdjuster, ExtractorOutput extractorO TsPayloadReader.TrackIdGenerator idGenerator) { this.timestampAdjuster = timestampAdjuster; idGenerator.generateNewId(); - output = extractorOutput.track(idGenerator.getTrackId()); + output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_METADATA); output.format(Format.createSampleFormat(idGenerator.getFormatId(), MimeTypes.APPLICATION_SCTE35, null, Format.NO_VALUE, null)); } diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java b/library/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java index 3d9f8166ab3..cb46aa55195 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/wav/WavExtractor.java @@ -60,7 +60,7 @@ public boolean sniff(ExtractorInput input) throws IOException, InterruptedExcept @Override public void init(ExtractorOutput output) { extractorOutput = output; - trackOutput = output.track(0); + trackOutput = output.track(0, C.TRACK_TYPE_AUDIO); wavHeader = null; output.endTracks(); } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java b/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java index 52260435930..dc189058a69 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java @@ -381,7 +381,7 @@ public int onLoadError(ExtractingLoadable loadable, long elapsedRealtimeMs, // ExtractorOutput implementation. Called by the loading thread. @Override - public TrackOutput track(int id) { + public TrackOutput track(int id, int type) { DefaultTrackOutput trackOutput = sampleQueues.get(id); if (trackOutput == null) { trackOutput = new DefaultTrackOutput(allocator); diff --git a/library/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java b/library/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java index 51db1e2a17c..4984ed0ff02 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java @@ -18,6 +18,7 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.drm.DrmInitData; +import com.google.android.exoplayer2.extractor.DummyTrackOutput; import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.extractor.ExtractorOutput; @@ -37,6 +38,7 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput public final Extractor extractor; private final Format manifestFormat; + private final int primaryTrackType; private final boolean preferManifestDrmInitData; private boolean extractorInitialized; @@ -52,13 +54,16 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput * @param extractor The extractor to wrap. * @param manifestFormat A manifest defined {@link Format} whose data should be merged into any * sample {@link Format} output from the {@link Extractor}. + * @param primaryTrackType The type of the primary track. Typically one of the {@link C} + * {@code TRACK_TYPE_*} constants. * @param preferManifestDrmInitData Whether {@link DrmInitData} defined in {@code manifestFormat} * should be preferred when the sample and manifest {@link Format}s are merged. */ - public ChunkExtractorWrapper(Extractor extractor, Format manifestFormat, + public ChunkExtractorWrapper(Extractor extractor, Format manifestFormat, int primaryTrackType, boolean preferManifestDrmInitData) { this.extractor = extractor; this.manifestFormat = manifestFormat; + this.primaryTrackType = primaryTrackType; this.preferManifestDrmInitData = preferManifestDrmInitData; } @@ -98,7 +103,10 @@ public void init(TrackOutput trackOutput) { // ExtractorOutput implementation. @Override - public TrackOutput track(int id) { + public TrackOutput track(int id, int type) { + if (primaryTrackType != C.TRACK_TYPE_UNKNOWN && primaryTrackType != type) { + return new DummyTrackOutput(); + } Assertions.checkState(!seenTrack || seenTrackId == id); seenTrack = true; seenTrackId = id; diff --git a/library/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java b/library/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java index d264283b689..88dcdd50be1 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/dash/DefaultDashChunkSource.java @@ -34,6 +34,7 @@ import com.google.android.exoplayer2.source.chunk.InitializationChunk; import com.google.android.exoplayer2.source.chunk.MediaChunk; import com.google.android.exoplayer2.source.chunk.SingleSampleMediaChunk; +import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet; import com.google.android.exoplayer2.source.dash.manifest.DashManifest; import com.google.android.exoplayer2.source.dash.manifest.RangedUri; import com.google.android.exoplayer2.source.dash.manifest.Representation; @@ -119,11 +120,13 @@ public DefaultDashChunkSource(LoaderErrorThrower manifestLoaderErrorThrower, this.maxSegmentsPerLoad = maxSegmentsPerLoad; long periodDurationUs = manifest.getPeriodDurationUs(periodIndex); - List representations = getRepresentations(); + AdaptationSet adaptationSet = getAdaptationSet(); + List representations = adaptationSet.representations; representationHolders = new RepresentationHolder[trackSelection.length()]; for (int i = 0; i < representationHolders.length; i++) { Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i)); - representationHolders[i] = new RepresentationHolder(periodDurationUs, representation); + representationHolders[i] = new RepresentationHolder(periodDurationUs, representation, + adaptationSet.type); } } @@ -133,7 +136,7 @@ public void updateManifest(DashManifest newManifest, int newPeriodIndex) { manifest = newManifest; periodIndex = newPeriodIndex; long periodDurationUs = manifest.getPeriodDurationUs(periodIndex); - List representations = getRepresentations(); + List representations = getAdaptationSet().representations; for (int i = 0; i < representationHolders.length; i++) { Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i)); representationHolders[i].updateRepresentation(periodDurationUs, representation); @@ -278,8 +281,8 @@ public boolean onChunkLoadError(Chunk chunk, boolean cancelable, Exception e) { // Private methods. - private List getRepresentations() { - return manifest.getPeriod(periodIndex).adaptationSets.get(adaptationSetIndex).representations; + private AdaptationSet getAdaptationSet() { + return manifest.getPeriod(periodIndex).adaptationSets.get(adaptationSetIndex); } private long getNowUnixTimeUs() { @@ -350,6 +353,7 @@ private static Chunk newMediaChunk(RepresentationHolder representationHolder, protected static final class RepresentationHolder { + public final int trackType; public final ChunkExtractorWrapper extractorWrapper; public Representation representation; @@ -358,9 +362,11 @@ protected static final class RepresentationHolder { private long periodDurationUs; private int segmentNumShift; - public RepresentationHolder(long periodDurationUs, Representation representation) { + public RepresentationHolder(long periodDurationUs, Representation representation, + int trackType) { this.periodDurationUs = periodDurationUs; this.representation = representation; + this.trackType = trackType; String containerMimeType = representation.format.containerMimeType; if (mimeTypeIsRawText(containerMimeType)) { extractorWrapper = null; @@ -371,12 +377,13 @@ public RepresentationHolder(long periodDurationUs, Representation representation } else if (mimeTypeIsWebm(containerMimeType)) { extractor = new MatroskaExtractor(); } else { - extractor = new FragmentedMp4Extractor(); + extractor = new FragmentedMp4Extractor(FragmentedMp4Extractor.FLAG_ENABLE_CEA608_TRACK + | FragmentedMp4Extractor.FLAG_ENABLE_EMSG_TRACK); } // Prefer drmInitData obtained from the manifest over drmInitData obtained from the stream, // as per DASH IF Interoperability Recommendations V3.0, 7.5.3. extractorWrapper = new ChunkExtractorWrapper(extractor, representation.format, - true /* preferManifestDrmInitData */); + trackType, true /* preferManifestDrmInitData */); } segmentIndex = representation.getIndex(); } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java index bee38c59b50..538acbeabf5 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java @@ -156,7 +156,7 @@ public void continuePreparing() { * prepare. */ public void prepareSingleTrack(Format format) { - track(0).format(format); + track(0, C.TRACK_TYPE_UNKNOWN).format(format); sampleQueuesBuilt = true; maybeFinishPrepare(); } @@ -456,7 +456,7 @@ public void init(int chunkUid, boolean shouldSpliceIn) { // ExtractorOutput implementation. Called by the loading thread. @Override - public DefaultTrackOutput track(int id) { + public DefaultTrackOutput track(int id, int type) { if (sampleQueues.indexOfKey(id) >= 0) { return sampleQueues.get(id); } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java index c8928ce65dd..12ea2c16c71 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java @@ -167,7 +167,7 @@ private void processSample() throws ParserException { } private TrackOutput buildTrackOutput(long subsampleOffsetUs) { - TrackOutput trackOutput = output.track(0); + TrackOutput trackOutput = output.track(0, C.TRACK_TYPE_TEXT); trackOutput.format(Format.createTextSampleFormat(null, MimeTypes.TEXT_VTT, null, Format.NO_VALUE, 0, language, null, subsampleOffsetUs)); output.endTracks(); diff --git a/library/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java b/library/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java index 2116d852ecb..b0a583e8e5b 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/DefaultSsChunkSource.java @@ -101,8 +101,9 @@ public DefaultSsChunkSource(LoaderErrorThrower manifestLoaderErrorThrower, SsMan trackEncryptionBoxes, nalUnitLengthFieldLength, null, null); FragmentedMp4Extractor extractor = new FragmentedMp4Extractor( FragmentedMp4Extractor.FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME - | FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX, track, null); - extractorWrappers[i] = new ChunkExtractorWrapper(extractor, format, false); + | FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX, null, track); + extractorWrappers[i] = new ChunkExtractorWrapper(extractor, format, streamElement.type, + false); } } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExtractorOutput.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExtractorOutput.java index 3716c6d37fd..ee8927ea211 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExtractorOutput.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExtractorOutput.java @@ -47,13 +47,13 @@ public FakeExtractorOutput() { } @Override - public FakeTrackOutput track(int trackId) { - FakeTrackOutput output = trackOutputs.get(trackId); + public FakeTrackOutput track(int id, int type) { + FakeTrackOutput output = trackOutputs.get(id); if (output == null) { Assert.assertFalse(tracksEnded); numberOfTracks++; output = new FakeTrackOutput(); - trackOutputs.put(trackId, output); + trackOutputs.put(id, output); } return output; }