Commit 152d1c7d by kimvde Committed by Christos Tsilopoulos

TsExtractor: handle packets without PTS

Issue: #9294
PiperOrigin-RevId: 392844983
parent 66d1e2cc
......@@ -5,6 +5,9 @@
* Core Library:
* Fix track selection in `StyledPlayerControlView` when using
`ForwardingPlayer`.
* Extractors:
* Support TS packets without PTS flag
([#9294](https://github.com/google/ExoPlayer/issues/9294)).
* Video
* Request smaller decoder input buffers for Dolby Vision. This fixes an
issue that could cause UHD Dolby Vision playbacks to fail on some
......
......@@ -102,12 +102,14 @@ public final class CeaUtil {
for (TrackOutput output : outputs) {
ccDataBuffer.setPosition(sampleStartPosition);
output.sampleData(ccDataBuffer, sampleLength);
output.sampleMetadata(
presentationTimeUs,
C.BUFFER_FLAG_KEY_FRAME,
sampleLength,
/* offset= */ 0,
/* encryptionData= */ null);
if (presentationTimeUs != C.TIME_UNSET) {
output.sampleMetadata(
presentationTimeUs,
C.BUFFER_FLAG_KEY_FRAME,
sampleLength,
/* offset= */ 0,
/* cryptoData= */ null);
}
}
}
......
......@@ -85,6 +85,7 @@ public final class Ac3Reader implements ElementaryStreamReader {
headerScratchBits = new ParsableBitArray(new byte[HEADER_SIZE]);
headerScratchBytes = new ParsableByteArray(headerScratchBits.data);
state = STATE_FINDING_SYNC;
timeUs = C.TIME_UNSET;
this.language = language;
}
......@@ -93,6 +94,7 @@ public final class Ac3Reader implements ElementaryStreamReader {
state = STATE_FINDING_SYNC;
bytesRead = 0;
lastByteWas0B = false;
timeUs = C.TIME_UNSET;
}
@Override
......@@ -104,7 +106,9 @@ public final class Ac3Reader implements ElementaryStreamReader {
@Override
public void packetStarted(long pesTimeUs, @TsPayloadReader.Flags int flags) {
timeUs = pesTimeUs;
if (pesTimeUs != C.TIME_UNSET) {
timeUs = pesTimeUs;
}
}
@Override
......@@ -133,8 +137,10 @@ public final class Ac3Reader implements ElementaryStreamReader {
output.sampleData(data, bytesToRead);
bytesRead += bytesToRead;
if (bytesRead == sampleSize) {
output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
timeUs += sampleDurationUs;
if (timeUs != C.TIME_UNSET) {
output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
timeUs += sampleDurationUs;
}
state = STATE_FINDING_SYNC;
}
break;
......
......@@ -87,6 +87,7 @@ public final class Ac4Reader implements ElementaryStreamReader {
bytesRead = 0;
lastByteWasAC = false;
hasCRC = false;
timeUs = C.TIME_UNSET;
this.language = language;
}
......@@ -96,6 +97,7 @@ public final class Ac4Reader implements ElementaryStreamReader {
bytesRead = 0;
lastByteWasAC = false;
hasCRC = false;
timeUs = C.TIME_UNSET;
}
@Override
......@@ -107,7 +109,9 @@ public final class Ac4Reader implements ElementaryStreamReader {
@Override
public void packetStarted(long pesTimeUs, @TsPayloadReader.Flags int flags) {
timeUs = pesTimeUs;
if (pesTimeUs != C.TIME_UNSET) {
timeUs = pesTimeUs;
}
}
@Override
......@@ -136,8 +140,10 @@ public final class Ac4Reader implements ElementaryStreamReader {
output.sampleData(data, bytesToRead);
bytesRead += bytesToRead;
if (bytesRead == sampleSize) {
output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
timeUs += sampleDurationUs;
if (timeUs != C.TIME_UNSET) {
output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
timeUs += sampleDurationUs;
}
state = STATE_FINDING_SYNC;
}
break;
......
......@@ -114,6 +114,7 @@ public final class AdtsReader implements ElementaryStreamReader {
firstFrameVersion = VERSION_UNSET;
firstFrameSampleRateIndex = C.INDEX_UNSET;
sampleDurationUs = C.TIME_UNSET;
timeUs = C.TIME_UNSET;
this.exposeId3 = exposeId3;
this.language = language;
}
......@@ -125,6 +126,7 @@ public final class AdtsReader implements ElementaryStreamReader {
@Override
public void seek() {
timeUs = C.TIME_UNSET;
resetSync();
}
......@@ -149,7 +151,9 @@ public final class AdtsReader implements ElementaryStreamReader {
@Override
public void packetStarted(long pesTimeUs, @TsPayloadReader.Flags int flags) {
timeUs = pesTimeUs;
if (pesTimeUs != C.TIME_UNSET) {
timeUs = pesTimeUs;
}
}
@Override
......@@ -529,8 +533,10 @@ public final class AdtsReader implements ElementaryStreamReader {
currentOutput.sampleData(data, bytesToRead);
bytesRead += bytesToRead;
if (bytesRead == sampleSize) {
currentOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
timeUs += currentSampleDuration;
if (timeUs != C.TIME_UNSET) {
currentOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
timeUs += currentSampleDuration;
}
setFindingSampleState();
}
}
......
......@@ -66,6 +66,7 @@ public final class DtsReader implements ElementaryStreamReader {
public DtsReader(@Nullable String language) {
headerScratchBytes = new ParsableByteArray(new byte[HEADER_SIZE]);
state = STATE_FINDING_SYNC;
timeUs = C.TIME_UNSET;
this.language = language;
}
......@@ -74,6 +75,7 @@ public final class DtsReader implements ElementaryStreamReader {
state = STATE_FINDING_SYNC;
bytesRead = 0;
syncBytes = 0;
timeUs = C.TIME_UNSET;
}
@Override
......@@ -85,7 +87,9 @@ public final class DtsReader implements ElementaryStreamReader {
@Override
public void packetStarted(long pesTimeUs, @TsPayloadReader.Flags int flags) {
timeUs = pesTimeUs;
if (pesTimeUs != C.TIME_UNSET) {
timeUs = pesTimeUs;
}
}
@Override
......@@ -111,8 +115,10 @@ public final class DtsReader implements ElementaryStreamReader {
output.sampleData(data, bytesToRead);
bytesRead += bytesToRead;
if (bytesRead == sampleSize) {
output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
timeUs += sampleDurationUs;
if (timeUs != C.TIME_UNSET) {
output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
timeUs += sampleDurationUs;
}
state = STATE_FINDING_SYNC;
}
break;
......
......@@ -43,11 +43,13 @@ public final class DvbSubtitleReader implements ElementaryStreamReader {
public DvbSubtitleReader(List<DvbSubtitleInfo> subtitleInfos) {
this.subtitleInfos = subtitleInfos;
outputs = new TrackOutput[subtitleInfos.size()];
sampleTimeUs = C.TIME_UNSET;
}
@Override
public void seek() {
writingSample = false;
sampleTimeUs = C.TIME_UNSET;
}
@Override
......@@ -73,7 +75,9 @@ public final class DvbSubtitleReader implements ElementaryStreamReader {
return;
}
writingSample = true;
sampleTimeUs = pesTimeUs;
if (pesTimeUs != C.TIME_UNSET) {
sampleTimeUs = pesTimeUs;
}
sampleBytesWritten = 0;
bytesToCheck = 2;
}
......@@ -81,8 +85,10 @@ public final class DvbSubtitleReader implements ElementaryStreamReader {
@Override
public void packetFinished() {
if (writingSample) {
for (TrackOutput output : outputs) {
output.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleBytesWritten, 0, null);
if (sampleTimeUs != C.TIME_UNSET) {
for (TrackOutput output : outputs) {
output.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleBytesWritten, 0, null);
}
}
writingSample = false;
}
......
......@@ -87,6 +87,8 @@ public final class H262Reader implements ElementaryStreamReader {
userData = null;
userDataParsable = null;
}
pesTimeUs = C.TIME_UNSET;
sampleTimeUs = C.TIME_UNSET;
}
@Override
......@@ -98,6 +100,8 @@ public final class H262Reader implements ElementaryStreamReader {
}
totalBytesWritten = 0;
startedFirstSample = false;
pesTimeUs = C.TIME_UNSET;
sampleTimeUs = C.TIME_UNSET;
}
@Override
......@@ -182,7 +186,7 @@ public final class H262Reader implements ElementaryStreamReader {
}
if (startCodeValue == START_PICTURE || startCodeValue == START_SEQUENCE_HEADER) {
int bytesWrittenPastStartCode = limit - startCodeOffset;
if (startedFirstSample && sampleHasPicture && hasOutputFormat) {
if (sampleHasPicture && hasOutputFormat && sampleTimeUs != C.TIME_UNSET) {
// Output the sample.
@C.BufferFlags int flags = sampleIsKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
int size = (int) (totalBytesWritten - samplePosition) - bytesWrittenPastStartCode;
......@@ -194,7 +198,9 @@ public final class H262Reader implements ElementaryStreamReader {
sampleTimeUs =
pesTimeUs != C.TIME_UNSET
? pesTimeUs
: (startedFirstSample ? (sampleTimeUs + frameDurationUs) : 0);
: (sampleTimeUs != C.TIME_UNSET
? (sampleTimeUs + frameDurationUs)
: C.TIME_UNSET);
sampleIsKeyframe = false;
pesTimeUs = C.TIME_UNSET;
startedFirstSample = true;
......
......@@ -87,6 +87,7 @@ public final class H263Reader implements ElementaryStreamReader {
this.userDataReader = userDataReader;
prefixFlags = new boolean[4];
csdBuffer = new CsdBuffer(128);
pesTimeUs = C.TIME_UNSET;
if (userDataReader != null) {
userData = new NalUnitTargetBuffer(START_CODE_VALUE_USER_DATA, 128);
userDataParsable = new ParsableByteArray();
......@@ -107,6 +108,7 @@ public final class H263Reader implements ElementaryStreamReader {
userData.reset();
}
totalBytesWritten = 0;
pesTimeUs = C.TIME_UNSET;
}
@Override
......@@ -123,7 +125,9 @@ public final class H263Reader implements ElementaryStreamReader {
@Override
public void packetStarted(long pesTimeUs, @TsPayloadReader.Flags int flags) {
// TODO (Internal b/32267012): Consider using random access indicator.
this.pesTimeUs = pesTimeUs;
if (pesTimeUs != C.TIME_UNSET) {
this.pesTimeUs = pesTimeUs;
}
}
@Override
......@@ -462,7 +466,10 @@ public final class H263Reader implements ElementaryStreamReader {
}
public void onDataEnd(long position, int bytesWrittenPastPosition, boolean hasOutputFormat) {
if (startCodeValue == START_CODE_VALUE_VOP && hasOutputFormat && readingSample) {
if (startCodeValue == START_CODE_VALUE_VOP
&& hasOutputFormat
&& readingSample
&& sampleTimeUs != C.TIME_UNSET) {
int size = (int) (position - samplePosition);
@C.BufferFlags int flags = sampleIsKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
output.sampleMetadata(
......
......@@ -86,6 +86,7 @@ public final class H264Reader implements ElementaryStreamReader {
sps = new NalUnitTargetBuffer(NAL_UNIT_TYPE_SPS, 128);
pps = new NalUnitTargetBuffer(NAL_UNIT_TYPE_PPS, 128);
sei = new NalUnitTargetBuffer(NAL_UNIT_TYPE_SEI, 128);
pesTimeUs = C.TIME_UNSET;
seiWrapper = new ParsableByteArray();
}
......@@ -93,6 +94,7 @@ public final class H264Reader implements ElementaryStreamReader {
public void seek() {
totalBytesWritten = 0;
randomAccessIndicator = false;
pesTimeUs = C.TIME_UNSET;
NalUnitUtil.clearPrefixFlags(prefixFlags);
sps.reset();
pps.reset();
......@@ -113,7 +115,9 @@ public final class H264Reader implements ElementaryStreamReader {
@Override
public void packetStarted(long pesTimeUs, @TsPayloadReader.Flags int flags) {
this.pesTimeUs = pesTimeUs;
if (pesTimeUs != C.TIME_UNSET) {
this.pesTimeUs = pesTimeUs;
}
randomAccessIndicator |= (flags & FLAG_RANDOM_ACCESS_INDICATOR) != 0;
}
......@@ -495,6 +499,9 @@ public final class H264Reader implements ElementaryStreamReader {
}
private void outputSample(int offset) {
if (sampleTimeUs == C.TIME_UNSET) {
return;
}
@C.BufferFlags int flags = sampleIsKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
int size = (int) (nalUnitStartPosition - samplePosition);
output.sampleMetadata(sampleTimeUs, flags, size, offset, null);
......
......@@ -85,12 +85,14 @@ public final class H265Reader implements ElementaryStreamReader {
pps = new NalUnitTargetBuffer(PPS_NUT, 128);
prefixSei = new NalUnitTargetBuffer(PREFIX_SEI_NUT, 128);
suffixSei = new NalUnitTargetBuffer(SUFFIX_SEI_NUT, 128);
pesTimeUs = C.TIME_UNSET;
seiWrapper = new ParsableByteArray();
}
@Override
public void seek() {
totalBytesWritten = 0;
pesTimeUs = C.TIME_UNSET;
NalUnitUtil.clearPrefixFlags(prefixFlags);
vps.reset();
sps.reset();
......@@ -114,7 +116,9 @@ public final class H265Reader implements ElementaryStreamReader {
@Override
public void packetStarted(long pesTimeUs, @TsPayloadReader.Flags int flags) {
// TODO (Internal b/32267012): Consider using random access indicator.
this.pesTimeUs = pesTimeUs;
if (pesTimeUs != C.TIME_UNSET) {
this.pesTimeUs = pesTimeUs;
}
}
@Override
......@@ -536,6 +540,9 @@ public final class H265Reader implements ElementaryStreamReader {
}
private void outputSample(int offset) {
if (sampleTimeUs == C.TIME_UNSET) {
return;
}
@C.BufferFlags int flags = sampleIsKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
int size = (int) (nalUnitPosition - samplePosition);
output.sampleMetadata(sampleTimeUs, flags, size, offset, null);
......
......@@ -49,11 +49,13 @@ public final class Id3Reader implements ElementaryStreamReader {
public Id3Reader() {
id3Header = new ParsableByteArray(ID3_HEADER_LENGTH);
sampleTimeUs = C.TIME_UNSET;
}
@Override
public void seek() {
writingSample = false;
sampleTimeUs = C.TIME_UNSET;
}
@Override
......@@ -73,7 +75,9 @@ public final class Id3Reader implements ElementaryStreamReader {
return;
}
writingSample = true;
sampleTimeUs = pesTimeUs;
if (pesTimeUs != C.TIME_UNSET) {
sampleTimeUs = pesTimeUs;
}
sampleSize = 0;
sampleBytesRead = 0;
}
......@@ -120,7 +124,9 @@ public final class Id3Reader implements ElementaryStreamReader {
if (!writingSample || sampleSize == 0 || sampleBytesRead != sampleSize) {
return;
}
output.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
if (sampleTimeUs != C.TIME_UNSET) {
output.sampleMetadata(sampleTimeUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
}
writingSample = false;
}
}
......@@ -78,11 +78,13 @@ public final class LatmReader implements ElementaryStreamReader {
this.language = language;
sampleDataBuffer = new ParsableByteArray(INITIAL_BUFFER_SIZE);
sampleBitArray = new ParsableBitArray(sampleDataBuffer.getData());
timeUs = C.TIME_UNSET;
}
@Override
public void seek() {
state = STATE_FINDING_SYNC_1;
timeUs = C.TIME_UNSET;
streamMuxRead = false;
}
......@@ -95,7 +97,9 @@ public final class LatmReader implements ElementaryStreamReader {
@Override
public void packetStarted(long pesTimeUs, @TsPayloadReader.Flags int flags) {
timeUs = pesTimeUs;
if (pesTimeUs != C.TIME_UNSET) {
timeUs = pesTimeUs;
}
}
@Override
......@@ -306,8 +310,10 @@ public final class LatmReader implements ElementaryStreamReader {
sampleDataBuffer.setPosition(0);
}
output.sampleData(sampleDataBuffer, muxLengthBytes);
output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, muxLengthBytes, 0, null);
timeUs += sampleDurationUs;
if (timeUs != C.TIME_UNSET) {
output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, muxLengthBytes, 0, null);
timeUs += sampleDurationUs;
}
}
private void resetBufferForSize(int newSize) {
......
......@@ -69,6 +69,7 @@ public final class MpegAudioReader implements ElementaryStreamReader {
headerScratch = new ParsableByteArray(4);
headerScratch.getData()[0] = (byte) 0xFF;
header = new MpegAudioUtil.Header();
timeUs = C.TIME_UNSET;
this.language = language;
}
......@@ -77,6 +78,7 @@ public final class MpegAudioReader implements ElementaryStreamReader {
state = STATE_FINDING_HEADER;
frameBytesRead = 0;
lastByteWasFF = false;
timeUs = C.TIME_UNSET;
}
@Override
......@@ -88,7 +90,9 @@ public final class MpegAudioReader implements ElementaryStreamReader {
@Override
public void packetStarted(long pesTimeUs, @TsPayloadReader.Flags int flags) {
timeUs = pesTimeUs;
if (pesTimeUs != C.TIME_UNSET) {
timeUs = pesTimeUs;
}
}
@Override
......@@ -227,8 +231,10 @@ public final class MpegAudioReader implements ElementaryStreamReader {
return;
}
output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, frameSize, 0, null);
timeUs += frameDurationUs;
if (timeUs != C.TIME_UNSET) {
output.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, frameSize, 0, null);
timeUs += frameDurationUs;
}
frameBytesRead = 0;
state = STATE_FINDING_HEADER;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment