From abdb8ddb6ebf1b785f3b17ae462c9542c08bb1d4 Mon Sep 17 00:00:00 2001 From: aquilescanta Date: Mon, 22 Aug 2016 05:07:42 -0700 Subject: [PATCH] Remove 1 track per type limitation in TsExtractor Mainly, this allows the extractor to expose multiple audio tracks. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=130928152 --- .../androidTest/assets/ts/sample.ts.0.dump | 29 ++---------- .../exoplayer2/extractor/ts/TsExtractor.java | 45 +++++++++++-------- .../exoplayer2/source/hls/HlsChunkSource.java | 3 +- 3 files changed, 31 insertions(+), 46 deletions(-) diff --git a/library/src/androidTest/assets/ts/sample.ts.0.dump b/library/src/androidTest/assets/ts/sample.ts.0.dump index 3944516e01..586931b28c 100644 --- a/library/src/androidTest/assets/ts/sample.ts.0.dump +++ b/library/src/androidTest/assets/ts/sample.ts.0.dump @@ -2,8 +2,8 @@ seekMap: isSeekable = false duration = UNSET TIME getPosition(0) = 0 -numberOfTracks = 3 -track 2: +numberOfTracks = 2 +track 256: format: bitrate = -1 id = null @@ -35,7 +35,7 @@ track 2: time = 66733 flags = 0 data = length 18112, hash EC44B35B -track 3: +track 257: format: bitrate = -1 id = null @@ -74,27 +74,4 @@ track 3: time = 100822 flags = 1 data = length 1254, hash 73FB07B8 -track 21: - format: - bitrate = -1 - id = null - containerMimeType = null - sampleMimeType = application/id3 - maxInputSize = -1 - width = -1 - height = -1 - frameRate = -1.0 - rotationDegrees = -1 - pixelWidthHeightRatio = -1.0 - channelCount = -1 - sampleRate = -1 - pcmEncoding = -1 - encoderDelay = -1 - encoderPadding = -1 - subsampleOffsetUs = 9223372036854775807 - selectionFlags = 0 - language = null - drmInitData = - - initializationData: - sample count = 0 tracksEnded = true diff --git a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java index e2df3d58e8..db1e7ca4e0 100644 --- a/library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java +++ b/library/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java @@ -53,6 +53,7 @@ public final class TsExtractor implements Extractor { public static final int WORKAROUND_IGNORE_AAC_STREAM = 2; public static final int WORKAROUND_IGNORE_H264_STREAM = 4; public static final int WORKAROUND_DETECT_ACCESS_UNITS = 8; + public static final int WORKAROUND_MAP_BY_TYPE = 16; private static final String TAG = "TsExtractor"; @@ -71,7 +72,7 @@ public final class TsExtractor implements Extractor { private static final int TS_STREAM_TYPE_H264 = 0x1B; private static final int TS_STREAM_TYPE_H265 = 0x24; private static final int TS_STREAM_TYPE_ID3 = 0x15; - private static final int TS_STREAM_TYPE_EIA608 = 0x100; // 0xFF + 1 + private static final int BASE_EMBEDDED_TRACK_ID = 0x2000; // 0xFF + 1 private static final long AC3_FORMAT_IDENTIFIER = Util.getIntegerCodeForString("AC-3"); private static final long E_AC3_FORMAT_IDENTIFIER = Util.getIntegerCodeForString("EAC3"); @@ -85,10 +86,11 @@ public final class TsExtractor implements Extractor { private final ParsableByteArray tsPacketBuffer; private final ParsableBitArray tsScratch; /* package */ final SparseArray tsPayloadReaders; // Indexed by pid - /* package */ final SparseBooleanArray streamTypes; + /* package */ final SparseBooleanArray trackIds; // Accessed only by the loading thread. private ExtractorOutput output; + private int nextEmbeddedTrackId; /* package */ Id3Reader id3Reader; public TsExtractor() { @@ -106,7 +108,8 @@ public final class TsExtractor implements Extractor { tsScratch = new ParsableBitArray(new byte[3]); tsPayloadReaders = new SparseArray<>(); tsPayloadReaders.put(TS_PAT_PID, new PatReader()); - streamTypes = new SparseBooleanArray(); + trackIds = new SparseBooleanArray(); + nextEmbeddedTrackId = BASE_EMBEDDED_TRACK_ID; } // Extractor implementation. @@ -359,7 +362,7 @@ public final class TsExtractor implements Extractor { // Skip the descriptors. sectionData.skipBytes(programInfoLength); - if (id3Reader == null) { + if ((workaroundFlags & WORKAROUND_MAP_BY_TYPE) != 0 && id3Reader == null) { // Setup an ID3 track regardless of whether there's a corresponding entry, in case one // appears intermittently during playback. See b/20261500. id3Reader = new Id3Reader(output.track(TS_STREAM_TYPE_ID3)); @@ -381,48 +384,52 @@ public final class TsExtractor implements Extractor { sectionData.skipBytes(esInfoLength); } remainingEntriesLength -= esInfoLength + 5; - if (streamTypes.get(streamType)) { + int trackId = (workaroundFlags & WORKAROUND_MAP_BY_TYPE) != 0 ? streamType : elementaryPid; + if (trackIds.get(trackId)) { continue; } - ElementaryStreamReader pesPayloadReader; switch (streamType) { case TS_STREAM_TYPE_MPA: - pesPayloadReader = new MpegAudioReader(output.track(TS_STREAM_TYPE_MPA)); + pesPayloadReader = new MpegAudioReader(output.track(trackId)); break; case TS_STREAM_TYPE_MPA_LSF: - pesPayloadReader = new MpegAudioReader(output.track(TS_STREAM_TYPE_MPA_LSF)); + pesPayloadReader = new MpegAudioReader(output.track(trackId)); break; case TS_STREAM_TYPE_AAC: pesPayloadReader = (workaroundFlags & WORKAROUND_IGNORE_AAC_STREAM) != 0 ? null - : new AdtsReader(output.track(TS_STREAM_TYPE_AAC), new DummyTrackOutput()); + : new AdtsReader(output.track(trackId), new DummyTrackOutput()); break; case TS_STREAM_TYPE_AC3: - pesPayloadReader = new Ac3Reader(output.track(TS_STREAM_TYPE_AC3), false); + pesPayloadReader = new Ac3Reader(output.track(trackId), false); break; case TS_STREAM_TYPE_E_AC3: - pesPayloadReader = new Ac3Reader(output.track(TS_STREAM_TYPE_E_AC3), true); + pesPayloadReader = new Ac3Reader(output.track(trackId), true); break; case TS_STREAM_TYPE_DTS: case TS_STREAM_TYPE_HDMV_DTS: - pesPayloadReader = new DtsReader(output.track(TS_STREAM_TYPE_DTS)); + pesPayloadReader = new DtsReader(output.track(trackId)); break; case TS_STREAM_TYPE_H262: - pesPayloadReader = new H262Reader(output.track(TS_STREAM_TYPE_H262)); + pesPayloadReader = new H262Reader(output.track(trackId)); break; case TS_STREAM_TYPE_H264: pesPayloadReader = (workaroundFlags & WORKAROUND_IGNORE_H264_STREAM) != 0 ? null - : new H264Reader(output.track(TS_STREAM_TYPE_H264), - new SeiReader(output.track(TS_STREAM_TYPE_EIA608)), + : new H264Reader(output.track(trackId), + new SeiReader(output.track(nextEmbeddedTrackId++)), (workaroundFlags & WORKAROUND_ALLOW_NON_IDR_KEYFRAMES) != 0, (workaroundFlags & WORKAROUND_DETECT_ACCESS_UNITS) != 0); break; case TS_STREAM_TYPE_H265: - pesPayloadReader = new H265Reader(output.track(TS_STREAM_TYPE_H265), - new SeiReader(output.track(TS_STREAM_TYPE_EIA608))); + pesPayloadReader = new H265Reader(output.track(trackId), + new SeiReader(output.track(nextEmbeddedTrackId++))); break; case TS_STREAM_TYPE_ID3: - pesPayloadReader = id3Reader; + if ((workaroundFlags & WORKAROUND_MAP_BY_TYPE) != 0) { + pesPayloadReader = id3Reader; + } else { + pesPayloadReader = new Id3Reader(output.track(nextEmbeddedTrackId++)); + } break; default: pesPayloadReader = null; @@ -430,7 +437,7 @@ public final class TsExtractor implements Extractor { } if (pesPayloadReader != null) { - streamTypes.put(streamType, true); + trackIds.put(trackId, true); tsPayloadReaders.put(elementaryPid, new PesReader(pesPayloadReader, ptsTimestampAdjuster)); } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java index d4d3aa71bc..b151802b2c 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsChunkSource.java @@ -309,7 +309,8 @@ public class HlsChunkSource { // The master source has yet to instantiate an adjuster for the discontinuity sequence. return; } - int workaroundFlags = 0; + // This flag ensures the change of pid between streams does not affect the sample queues. + int workaroundFlags = TsExtractor.WORKAROUND_MAP_BY_TYPE; String codecs = variants[newVariantIndex].codecs; if (!TextUtils.isEmpty(codecs)) { // Sometimes AAC and H264 streams are declared in TS chunks even though they don't really