mirror of
https://github.com/samsonjs/media.git
synced 2026-03-26 09:35:47 +00:00
Add MODE_SINGLE_PMT to TsExtractor
This mode allows the extractor to support streams with multiple programs declared in the PAT, but only one PMT. This is necessary to support tuner-obtained media. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=148636312
This commit is contained in:
parent
35988395d2
commit
e26723cdc7
3 changed files with 47 additions and 21 deletions
|
|
@ -75,7 +75,8 @@ public final class TsExtractorTest extends InstrumentationTestCase {
|
|||
|
||||
public void testCustomPesReader() throws Exception {
|
||||
CustomTsPayloadReaderFactory factory = new CustomTsPayloadReaderFactory(true, false);
|
||||
TsExtractor tsExtractor = new TsExtractor(new TimestampAdjuster(0), factory, false);
|
||||
TsExtractor tsExtractor = new TsExtractor(TsExtractor.MODE_NORMAL, new TimestampAdjuster(0),
|
||||
factory);
|
||||
FakeExtractorInput input = new FakeExtractorInput.Builder()
|
||||
.setData(TestUtil.getByteArray(getInstrumentation(), "ts/sample.ts"))
|
||||
.setSimulateIOErrors(false)
|
||||
|
|
@ -99,7 +100,8 @@ public final class TsExtractorTest extends InstrumentationTestCase {
|
|||
|
||||
public void testCustomInitialSectionReader() throws Exception {
|
||||
CustomTsPayloadReaderFactory factory = new CustomTsPayloadReaderFactory(false, true);
|
||||
TsExtractor tsExtractor = new TsExtractor(new TimestampAdjuster(0), factory, false);
|
||||
TsExtractor tsExtractor = new TsExtractor(TsExtractor.MODE_NORMAL, new TimestampAdjuster(0),
|
||||
factory);
|
||||
FakeExtractorInput input = new FakeExtractorInput.Builder()
|
||||
.setData(TestUtil.getByteArray(getInstrumentation(), "ts/sample_with_sdt.ts"))
|
||||
.setSimulateIOErrors(false)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.extractor.ts;
|
||||
|
||||
import android.support.annotation.IntDef;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.util.SparseIntArray;
|
||||
|
|
@ -34,6 +35,8 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
|
|||
import com.google.android.exoplayer2.util.TimestampAdjuster;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
|
@ -56,6 +59,27 @@ public final class TsExtractor implements Extractor {
|
|||
|
||||
};
|
||||
|
||||
/**
|
||||
* Modes for the extractor.
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({MODE_NORMAL, MODE_SINGLE_PMT, MODE_HLS})
|
||||
public @interface Mode {}
|
||||
|
||||
/**
|
||||
* Behave as defined in ISO/IEC 13818-1.
|
||||
*/
|
||||
public static final int MODE_NORMAL = 0;
|
||||
/**
|
||||
* Assume only one PMT will be contained in the stream, even if more are declared by the PAT.
|
||||
*/
|
||||
public static final int MODE_SINGLE_PMT = 1;
|
||||
/**
|
||||
* Enable single PMT mode, map {@link TrackOutput}s by their type (instead of PID) and ignore
|
||||
* continuity counters.
|
||||
*/
|
||||
public static final int MODE_HLS = 2;
|
||||
|
||||
public static final int TS_STREAM_TYPE_MPA = 0x03;
|
||||
public static final int TS_STREAM_TYPE_MPA_LSF = 0x04;
|
||||
public static final int TS_STREAM_TYPE_AAC = 0x0F;
|
||||
|
|
@ -81,7 +105,7 @@ public final class TsExtractor implements Extractor {
|
|||
private static final int BUFFER_PACKET_COUNT = 5; // Should be at least 2
|
||||
private static final int BUFFER_SIZE = TS_PACKET_SIZE * BUFFER_PACKET_COUNT;
|
||||
|
||||
private final boolean hlsMode;
|
||||
@Mode private final int mode;
|
||||
private final List<TimestampAdjuster> timestampAdjusters;
|
||||
private final ParsableByteArray tsPacketBuffer;
|
||||
private final ParsableBitArray tsScratch;
|
||||
|
|
@ -97,25 +121,25 @@ public final class TsExtractor implements Extractor {
|
|||
private TsPayloadReader id3Reader;
|
||||
|
||||
public TsExtractor() {
|
||||
this(new TimestampAdjuster(0), new DefaultTsPayloadReaderFactory(), false);
|
||||
this(MODE_NORMAL, new TimestampAdjuster(0), new DefaultTsPayloadReaderFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mode Mode for the extractor. One of {@link #MODE_NORMAL}, {@link #MODE_SINGLE_PMT}
|
||||
* and {@link #MODE_HLS}.
|
||||
* @param timestampAdjuster A timestamp adjuster for offsetting and scaling sample timestamps.
|
||||
* @param payloadReaderFactory Factory for injecting a custom set of payload readers.
|
||||
* @param hlsMode Whether the extractor should be used in HLS mode. If true, {@link TrackOutput}s
|
||||
* are mapped by their type (instead of PID) and continuity counters are ignored.
|
||||
*/
|
||||
public TsExtractor(TimestampAdjuster timestampAdjuster,
|
||||
TsPayloadReader.Factory payloadReaderFactory, boolean hlsMode) {
|
||||
if (hlsMode) {
|
||||
public TsExtractor(@Mode int mode, TimestampAdjuster timestampAdjuster,
|
||||
TsPayloadReader.Factory payloadReaderFactory) {
|
||||
this.payloadReaderFactory = Assertions.checkNotNull(payloadReaderFactory);
|
||||
this.mode = mode;
|
||||
if (mode == MODE_SINGLE_PMT || mode == MODE_HLS) {
|
||||
timestampAdjusters = Collections.singletonList(timestampAdjuster);
|
||||
} else {
|
||||
timestampAdjusters = new ArrayList<>();
|
||||
timestampAdjusters.add(timestampAdjuster);
|
||||
}
|
||||
this.payloadReaderFactory = Assertions.checkNotNull(payloadReaderFactory);
|
||||
this.hlsMode = hlsMode;
|
||||
tsPacketBuffer = new ParsableByteArray(BUFFER_SIZE);
|
||||
tsScratch = new ParsableBitArray(new byte[3]);
|
||||
trackIds = new SparseBooleanArray();
|
||||
|
|
@ -220,7 +244,7 @@ public final class TsExtractor implements Extractor {
|
|||
// Discontinuity check.
|
||||
boolean discontinuityFound = false;
|
||||
int continuityCounter = tsScratch.readBits(4);
|
||||
if (!hlsMode) {
|
||||
if (mode != MODE_HLS) {
|
||||
int previousCounter = continuityCounters.get(pid, continuityCounter - 1);
|
||||
continuityCounters.put(pid, continuityCounter);
|
||||
if (previousCounter == continuityCounter) {
|
||||
|
|
@ -315,7 +339,7 @@ public final class TsExtractor implements Extractor {
|
|||
remainingPmts++;
|
||||
}
|
||||
}
|
||||
if (!hlsMode) {
|
||||
if (mode != MODE_HLS) {
|
||||
tsPayloadReaders.remove(TS_PAT_PID);
|
||||
}
|
||||
}
|
||||
|
|
@ -356,7 +380,7 @@ public final class TsExtractor implements Extractor {
|
|||
}
|
||||
// TimestampAdjuster assignment.
|
||||
TimestampAdjuster timestampAdjuster;
|
||||
if (hlsMode || remainingPmts == 1) {
|
||||
if (mode == MODE_SINGLE_PMT || mode == MODE_HLS || remainingPmts == 1) {
|
||||
timestampAdjuster = timestampAdjusters.get(0);
|
||||
} else {
|
||||
timestampAdjuster = new TimestampAdjuster(timestampAdjusters.get(0).firstSampleTimestampUs);
|
||||
|
|
@ -378,7 +402,7 @@ public final class TsExtractor implements Extractor {
|
|||
// Skip the descriptors.
|
||||
sectionData.skipBytes(programInfoLength);
|
||||
|
||||
if (hlsMode && id3Reader == null) {
|
||||
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]);
|
||||
|
|
@ -401,14 +425,14 @@ public final class TsExtractor implements Extractor {
|
|||
}
|
||||
remainingEntriesLength -= esInfoLength + 5;
|
||||
|
||||
int trackId = hlsMode ? streamType : elementaryPid;
|
||||
int trackId = mode == MODE_HLS ? streamType : elementaryPid;
|
||||
if (trackIds.get(trackId)) {
|
||||
continue;
|
||||
}
|
||||
trackIds.put(trackId, true);
|
||||
|
||||
TsPayloadReader reader;
|
||||
if (hlsMode && streamType == TS_STREAM_TYPE_ID3) {
|
||||
if (mode == MODE_HLS && streamType == TS_STREAM_TYPE_ID3) {
|
||||
reader = id3Reader;
|
||||
} else {
|
||||
reader = payloadReaderFactory.createPayloadReader(streamType, esInfo);
|
||||
|
|
@ -422,7 +446,7 @@ public final class TsExtractor implements Extractor {
|
|||
tsPayloadReaders.put(elementaryPid, reader);
|
||||
}
|
||||
}
|
||||
if (hlsMode) {
|
||||
if (mode == MODE_HLS) {
|
||||
if (!tracksEnded) {
|
||||
output.endTracks();
|
||||
remainingPmts = 0;
|
||||
|
|
@ -430,7 +454,7 @@ public final class TsExtractor implements Extractor {
|
|||
}
|
||||
} else {
|
||||
tsPayloadReaders.remove(pid);
|
||||
remainingPmts--;
|
||||
remainingPmts = mode == MODE_SINGLE_PMT ? 0 : remainingPmts - 1;
|
||||
if (remainingPmts == 0) {
|
||||
output.endTracks();
|
||||
tracksEnded = true;
|
||||
|
|
|
|||
|
|
@ -372,8 +372,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
esReaderFactoryFlags |= DefaultTsPayloadReaderFactory.FLAG_IGNORE_H264_STREAM;
|
||||
}
|
||||
}
|
||||
extractor = new TsExtractor(timestampAdjuster,
|
||||
new DefaultTsPayloadReaderFactory(esReaderFactoryFlags, muxedCaptionFormats), true);
|
||||
extractor = new TsExtractor(TsExtractor.MODE_HLS, timestampAdjuster,
|
||||
new DefaultTsPayloadReaderFactory(esReaderFactoryFlags, muxedCaptionFormats));
|
||||
}
|
||||
if (usingNewExtractor) {
|
||||
extractor.init(extractorOutput);
|
||||
|
|
|
|||
Loading…
Reference in a new issue