blob: 34405a7a1a279fcbe295e99c97f7e0bb6c06a2eb [file] [log] [blame]
/*
* Copyright (C) 2016 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.ts;
import android.util.SparseArray;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.TimestampAdjuster;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.List;
/** Parses TS packet payload data. */
public interface TsPayloadReader {
/** Factory of {@link TsPayloadReader} instances. */
interface Factory {
/**
* Returns the initial mapping from PIDs to payload readers.
*
* <p>This method allows the injection of payload readers for reserved PIDs, excluding PID 0.
*
* @return A {@link SparseArray} that maps PIDs to payload readers.
*/
SparseArray<TsPayloadReader> createInitialPayloadReaders();
/**
* Returns a {@link TsPayloadReader} for a given stream type and elementary stream information.
* May return null if the stream type is not supported.
*
* @param streamType Stream type value as defined in the PMT entry or associated descriptors.
* @param esInfo Information associated to the elementary stream provided in the PMT.
* @return A {@link TsPayloadReader} for the packet stream carried by the provided pid, or
* {@code null} if the stream is not supported.
*/
@Nullable
TsPayloadReader createPayloadReader(int streamType, EsInfo esInfo);
}
/** Holds information associated with a PMT entry. */
final class EsInfo {
public final int streamType;
@Nullable public final String language;
public final List<DvbSubtitleInfo> dvbSubtitleInfos;
public final byte[] descriptorBytes;
/**
* @param streamType The type of the stream as defined by the {@link TsExtractor}{@code
* .TS_STREAM_TYPE_*}.
* @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,
@Nullable String language,
@Nullable List<DvbSubtitleInfo> dvbSubtitleInfos,
byte[] descriptorBytes) {
this.streamType = streamType;
this.language = language;
this.dvbSubtitleInfos =
dvbSubtitleInfos == null
? Collections.emptyList()
: Collections.unmodifiableList(dvbSubtitleInfos);
this.descriptorBytes = descriptorBytes;
}
}
/**
* Holds information about a DVB subtitle, as defined in ETSI EN 300 468 V1.11.1 section 6.2.41.
*/
final class DvbSubtitleInfo {
public final String language;
public final int type;
public final byte[] initializationData;
/**
* @param language The ISO 639-2 three-letter language code.
* @param type The subtitling type.
* @param initializationData The composition and ancillary page ids.
*/
public DvbSubtitleInfo(String language, int type, byte[] initializationData) {
this.language = language;
this.type = type;
this.initializationData = initializationData;
}
}
/** Generates track ids for initializing {@link TsPayloadReader}s' {@link TrackOutput}s. */
final class TrackIdGenerator {
private static final int ID_UNSET = Integer.MIN_VALUE;
private final String formatIdPrefix;
private final int firstTrackId;
private final int trackIdIncrement;
private int trackId;
private String formatId;
public TrackIdGenerator(int firstTrackId, int trackIdIncrement) {
this(ID_UNSET, firstTrackId, trackIdIncrement);
}
public TrackIdGenerator(int programNumber, int firstTrackId, int trackIdIncrement) {
this.formatIdPrefix = programNumber != ID_UNSET ? programNumber + "/" : "";
this.firstTrackId = firstTrackId;
this.trackIdIncrement = trackIdIncrement;
trackId = ID_UNSET;
formatId = "";
}
/**
* Generates a new set of track and track format ids. Must be called before {@code get*}
* methods.
*/
public void generateNewId() {
trackId = trackId == ID_UNSET ? firstTrackId : trackId + trackIdIncrement;
formatId = formatIdPrefix + trackId;
}
/**
* Returns the last generated track id. Must be called after the first {@link #generateNewId()}
* call.
*
* @return The last generated track id.
*/
public int getTrackId() {
maybeThrowUninitializedError();
return trackId;
}
/**
* Returns the last generated format id, with the format {@code "programNumber/trackId"}. If no
* {@code programNumber} was provided, the {@code trackId} alone is used as format id. Must be
* called after the first {@link #generateNewId()} call.
*
* @return The last generated format id, with the format {@code "programNumber/trackId"}. If no
* {@code programNumber} was provided, the {@code trackId} alone is used as format id.
*/
public String getFormatId() {
maybeThrowUninitializedError();
return formatId;
}
private void maybeThrowUninitializedError() {
if (trackId == ID_UNSET) {
throw new IllegalStateException("generateNewId() must be called before retrieving ids.");
}
}
}
/**
* Contextual flags indicating the presence of indicators in the TS packet or PES packet headers.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef(
flag = true,
value = {
FLAG_PAYLOAD_UNIT_START_INDICATOR,
FLAG_RANDOM_ACCESS_INDICATOR,
FLAG_DATA_ALIGNMENT_INDICATOR
})
@interface Flags {}
/** Indicates the presence of the payload_unit_start_indicator in the TS packet header. */
int FLAG_PAYLOAD_UNIT_START_INDICATOR = 1;
/**
* Indicates the presence of the random_access_indicator in the TS packet header adaptation field.
*/
int FLAG_RANDOM_ACCESS_INDICATOR = 1 << 1;
/** Indicates the presence of the data_alignment_indicator in the PES header. */
int FLAG_DATA_ALIGNMENT_INDICATOR = 1 << 2;
/**
* Initializes the payload reader.
*
* @param timestampAdjuster A timestamp adjuster for offsetting and scaling sample timestamps.
* @param extractorOutput The {@link ExtractorOutput} that receives the extracted data.
* @param idGenerator A {@link PesReader.TrackIdGenerator} that generates unique track ids for the
* {@link TrackOutput}s.
*/
void init(
TimestampAdjuster timestampAdjuster,
ExtractorOutput extractorOutput,
TrackIdGenerator idGenerator);
/**
* Notifies the reader that a seek has occurred.
*
* <p>Following a call to this method, the data passed to the next invocation of {@link #consume}
* will not be a continuation of the data that was previously passed. Hence the reader should
* reset any internal state.
*/
void seek();
/**
* Consumes the payload of a TS packet.
*
* @param data The TS packet. The position will be set to the start of the payload.
* @param flags See {@link Flags}.
* @throws ParserException If the payload could not be parsed.
*/
void consume(ParsableByteArray data, @Flags int flags) throws ParserException;
}