diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java index e732a4c657..7bf722cd8f 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/extractor/ts/TsExtractorTest.java @@ -156,7 +156,7 @@ public final class TsExtractorTest extends InstrumentationTestCase { @Override public TsPayloadReader createPayloadReader(int streamType, EsInfo esInfo) { if (provideCustomEsReader && streamType == 3) { - esReader = new CustomEsReader(esInfo.languagesInfo.get(0).languageCode); + esReader = new CustomEsReader(esInfo.language); return new PesReader(esReader); } else { return defaultFactory.createPayloadReader(streamType, esInfo); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java index c36cbb1a07..4bc7f11c1a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/DefaultTsPayloadReaderFactory.java @@ -93,16 +93,16 @@ public final class DefaultTsPayloadReaderFactory implements TsPayloadReader.Fact switch (streamType) { case TsExtractor.TS_STREAM_TYPE_MPA: case TsExtractor.TS_STREAM_TYPE_MPA_LSF: - return new PesReader(new MpegAudioReader(esInfo.languagesInfo.get(0).languageCode)); + return new PesReader(new MpegAudioReader(esInfo.language)); case TsExtractor.TS_STREAM_TYPE_AAC: return isSet(FLAG_IGNORE_AAC_STREAM) - ? null : new PesReader(new AdtsReader(false, esInfo.languagesInfo.get(0).languageCode)); + ? null : new PesReader(new AdtsReader(false, esInfo.language)); case TsExtractor.TS_STREAM_TYPE_AC3: case TsExtractor.TS_STREAM_TYPE_E_AC3: - return new PesReader(new Ac3Reader(esInfo.languagesInfo.get(0).languageCode)); + return new PesReader(new Ac3Reader(esInfo.language)); case TsExtractor.TS_STREAM_TYPE_DTS: case TsExtractor.TS_STREAM_TYPE_HDMV_DTS: - return new PesReader(new DtsReader(esInfo.languagesInfo.get(0).languageCode)); + return new PesReader(new DtsReader(esInfo.language)); case TsExtractor.TS_STREAM_TYPE_H262: return new PesReader(new H262Reader()); case TsExtractor.TS_STREAM_TYPE_H264: @@ -118,7 +118,7 @@ public final class DefaultTsPayloadReaderFactory implements TsPayloadReader.Fact return new PesReader(new Id3Reader()); case TsExtractor.TS_STREAM_TYPE_DVBSUBS: return new PesReader( - new DvbSubtitleReader(esInfo)); + new DvbSubtitleReader(esInfo.dvbSubtitleInfos)); default: return null; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/DvbSubtitleReader.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/DvbSubtitleReader.java index 1f6c885984..87adfcea86 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/DvbSubtitleReader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/DvbSubtitleReader.java @@ -19,13 +19,10 @@ 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; +import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.DvbSubtitleInfo; import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator; -import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.EsInfo; -import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.LanguageInfo; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.ParsableByteArray; - -import java.util.ArrayList; import java.util.List; /** @@ -33,8 +30,8 @@ import java.util.List; */ public final class DvbSubtitleReader implements ElementaryStreamReader { - private final List languages; - private List outputTracks = new ArrayList<>(); + private final List subtitleInfos; + private final TrackOutput[] outputs; private boolean writingSample; private int bytesToCheck; @@ -42,10 +39,11 @@ public final class DvbSubtitleReader implements ElementaryStreamReader { private long sampleTimeUs; /** - * @param esInfo Information associated to the elementary stream. + * @param subtitleInfos Information about the DVB subtitles associated to the stream. */ - public DvbSubtitleReader(EsInfo esInfo) { - this.languages = esInfo.languagesInfo; + public DvbSubtitleReader(List subtitleInfos) { + this.subtitleInfos = subtitleInfos; + outputs = new TrackOutput[subtitleInfos.size()]; } @Override @@ -55,24 +53,14 @@ public final class DvbSubtitleReader implements ElementaryStreamReader { @Override public void createTracks(ExtractorOutput extractorOutput, TrackIdGenerator idGenerator) { - idGenerator.generateNewId(); - - TrackOutput output; - LanguageInfo language; - - for (int i = 0; i < languages.size(); i++) { - language = languages.get(i); + for (int i = 0; i < outputs.length; i++) { + DvbSubtitleInfo subtitleInfo = subtitleInfos.get(i); idGenerator.generateNewId(); - - if (((language.programElementType & 0xF0 ) >> 4 ) == 2 ) { - language.languageCode += " for hard of hearing"; - } - - output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_TEXT); + TrackOutput output = extractorOutput.track(idGenerator.getTrackId(), C.TRACK_TYPE_TEXT); output.format(Format.createImageSampleFormat(idGenerator.getFormatId(), - MimeTypes.APPLICATION_DVBSUBS, null, Format.NO_VALUE, - language.initializationData, language.languageCode, null)); - outputTracks.add(output); + MimeTypes.APPLICATION_DVBSUBS, null, Format.NO_VALUE, subtitleInfo.initializationData, + subtitleInfo.language, null)); + outputs[i] = output; } } @@ -90,10 +78,7 @@ public final class DvbSubtitleReader implements ElementaryStreamReader { @Override public void packetFinished() { if (writingSample) { - TrackOutput output; - - for (int i = 0; i < outputTracks.size(); i++) { - output = outputTracks.get(i); + for (TrackOutput output : outputs) { output.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleBytesWritten, 0, null); } writingSample = false; @@ -111,12 +96,10 @@ public final class DvbSubtitleReader implements ElementaryStreamReader { // Check and discard the subtitle_stream_id return; } - int bytesAvailable = data.bytesLeft(); - TrackOutput output; int dataPosition = data.getPosition(); - for (int i = 0; i < outputTracks.size(); i++) { + int bytesAvailable = data.bytesLeft(); + for (TrackOutput output : outputs) { data.setPosition(dataPosition); - output = outputTracks.get(i); output.sampleData(data, bytesAvailable); } sampleBytesWritten += bytesAvailable; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java index b9c794c1f8..adcdb7d9d7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsExtractor.java @@ -28,8 +28,8 @@ import com.google.android.exoplayer2.extractor.PositionHolder; import com.google.android.exoplayer2.extractor.SeekMap; import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.ts.DefaultTsPayloadReaderFactory.Flags; +import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.DvbSubtitleInfo; import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.EsInfo; -import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.LanguageInfo; import com.google.android.exoplayer2.extractor.ts.TsPayloadReader.TrackIdGenerator; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.ParsableBitArray; @@ -419,7 +419,7 @@ public final class TsExtractor implements Extractor { if (mode == MODE_HLS && id3Reader == null) { // Setup an ID3 track regardless of whether there's a corresponding entry, in case one // appears intermittently during playback. See [Internal: b/20261500]. - EsInfo dummyEsInfo = new EsInfo(TS_STREAM_TYPE_ID3, null, new byte[0]); + EsInfo dummyEsInfo = new EsInfo(TS_STREAM_TYPE_ID3, null, null, new byte[0]); id3Reader = payloadReaderFactory.createPayloadReader(TS_STREAM_TYPE_ID3, dummyEsInfo); id3Reader.init(timestampAdjuster, output, new TrackIdGenerator(programNumber, TS_STREAM_TYPE_ID3, MAX_PID_PLUS_ONE)); @@ -488,7 +488,8 @@ public final class TsExtractor implements Extractor { int descriptorsStartPosition = data.getPosition(); int descriptorsEndPosition = descriptorsStartPosition + length; int streamType = -1; - List languages = null; + String language = null; + List dvbSubtitleInfos = null; while (data.getPosition() < descriptorsEndPosition) { int descriptorTag = data.readUnsignedByte(); int descriptorLength = data.readUnsignedByte(); @@ -509,35 +510,25 @@ public final class TsExtractor implements Extractor { } else if (descriptorTag == TS_PMT_DESC_DTS) { // DTS_descriptor streamType = TS_STREAM_TYPE_DTS; } else if (descriptorTag == TS_PMT_DESC_ISO639_LANG) { - int position = data.getPosition(); - languages = Collections.singletonList( - new LanguageInfo(new String(new byte[] - {data.data[position++], data.data[position++], data.data[position++]}).trim(), - data.data[position], null)); + language = data.readString(3).trim(); + // Audio type is ignored. } else if (descriptorTag == TS_PMT_DESC_DVBSUBS) { streamType = TS_STREAM_TYPE_DVBSUBS; - int position = data.getPosition(); - String language; - byte programElementType; - byte[] buffer; - languages = new ArrayList<>(); - while (position < positionOfNextDescriptor) { - buffer = new byte[4]; - language = new String(new byte[] - {data.data[position++], data.data[position++], data.data[position++]}).trim(); - programElementType = data.data[position++]; - data.setPosition(position); - data.readBytes(buffer, 0,4); - languages.add( - new LanguageInfo(language, programElementType, Collections.singletonList(buffer))); - position += 4; + dvbSubtitleInfos = new ArrayList<>(); + while (data.getPosition() < positionOfNextDescriptor) { + String dvbLanguage = data.readString(3).trim(); + int dvbProgramElementType = data.readUnsignedByte(); + byte[] initializationData = new byte[4]; + data.readBytes(initializationData, 0, 4); + dvbSubtitleInfos.add(new DvbSubtitleInfo(dvbLanguage, dvbProgramElementType, + Collections.singletonList(initializationData))); } } // Skip unused bytes of current descriptor. data.skipBytes(positionOfNextDescriptor - data.getPosition()); } data.setPosition(descriptorsEndPosition); - return new EsInfo(streamType, languages, + return new EsInfo(streamType, language, dvbSubtitleInfos, Arrays.copyOfRange(data.data, descriptorsStartPosition, descriptorsEndPosition)); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.java index d5fe06ded7..ef3a6af085 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/ts/TsPayloadReader.java @@ -21,6 +21,7 @@ import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.util.ParsableByteArray; import com.google.android.exoplayer2.util.TimestampAdjuster; +import java.util.Collections; import java.util.List; /** @@ -61,33 +62,44 @@ public interface TsPayloadReader { final class EsInfo { public final int streamType; - public final List languagesInfo; + public final String language; + public final List dvbSubtitleInfos; public final byte[] descriptorBytes; /** * @param streamType The type of the stream as defined by the * {@link TsExtractor}{@code .TS_STREAM_TYPE_*}. - * @param languagesInfo Language or languages info of the associated program element + * @param language The language of the stream, as defined by ISO/IEC 13818-1, section 2.6.18. + * @param dvbSubtitleInfos Information about DVB subtitles associated to the stream. * @param descriptorBytes The descriptor bytes associated to the stream. */ - public EsInfo(int streamType, List languagesInfo, byte[] descriptorBytes) { + public EsInfo(int streamType, String language, List dvbSubtitleInfos, + byte[] descriptorBytes) { this.streamType = streamType; - this.languagesInfo = languagesInfo; + this.language = language; + this.dvbSubtitleInfos = dvbSubtitleInfos == null ? Collections.emptyList() + : Collections.unmodifiableList(dvbSubtitleInfos); this.descriptorBytes = descriptorBytes; } + } - final class LanguageInfo { + /** + * Holds information about a DVB subtitle. + */ + final class DvbSubtitleInfo { - public String languageCode; - public final byte programElementType; + public final String language; + public final int programElementType; public final List initializationData; - LanguageInfo (String languageCode, byte programElementType, List initializationData) { - this.languageCode = languageCode; + public DvbSubtitleInfo(String language, int programElementType, + List initializationData) { + this.language = language; this.programElementType = programElementType; this.initializationData = initializationData; } + } /**