Simplify TimestampAdjuster logic
- Use timestampOffsetUs == C.TIME_UNSET directly as the way of determining whether the adjuster has determined the offset, rather than relying on lastSampleTimestampUs checks for this. - Remove comment referring to lastSampleTimestampUs as holding the "adjusted PTS". Its value may not have originated from a PTS timestamp. It's also confusing to refer to it as "adjusted" given timestampOffsetUs has not been applied to it. - Fix PassthroughSectionPayloadReader to make sure it'll never output a sample with an unset timestamp. #minor-release PiperOrigin-RevId: 388226180
This commit is contained in:
parent
ff71425dca
commit
e95c42ef98
@ -46,7 +46,7 @@ public final class TimestampAdjuster {
|
|||||||
private long timestampOffsetUs;
|
private long timestampOffsetUs;
|
||||||
|
|
||||||
@GuardedBy("this")
|
@GuardedBy("this")
|
||||||
private long lastSampleTimestampUs;
|
private long lastUnadjustedTimestampUs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param firstSampleTimestampUs The desired value of the first adjusted sample timestamp in
|
* @param firstSampleTimestampUs The desired value of the first adjusted sample timestamp in
|
||||||
@ -91,7 +91,7 @@ public final class TimestampAdjuster {
|
|||||||
sharedInitializationStarted = true;
|
sharedInitializationStarted = true;
|
||||||
}
|
}
|
||||||
if (!canInitialize || this.firstSampleTimestampUs != firstSampleTimestampUs) {
|
if (!canInitialize || this.firstSampleTimestampUs != firstSampleTimestampUs) {
|
||||||
while (lastSampleTimestampUs == C.TIME_UNSET) {
|
while (timestampOffsetUs == C.TIME_UNSET) {
|
||||||
wait();
|
wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,28 +108,21 @@ public final class TimestampAdjuster {
|
|||||||
/**
|
/**
|
||||||
* Returns the last value obtained from {@link #adjustSampleTimestamp}. If {@link
|
* Returns the last value obtained from {@link #adjustSampleTimestamp}. If {@link
|
||||||
* #adjustSampleTimestamp} has not been called, returns the result of calling {@link
|
* #adjustSampleTimestamp} has not been called, returns the result of calling {@link
|
||||||
* #getFirstSampleTimestampUs()}. If this value is {@link #DO_NOT_OFFSET}, returns {@link
|
* #getFirstSampleTimestampUs()} unless that value is {@link #DO_NOT_OFFSET}, in which case {@link
|
||||||
* C#TIME_UNSET}.
|
* C#TIME_UNSET} is returned.
|
||||||
*/
|
*/
|
||||||
public synchronized long getLastAdjustedTimestampUs() {
|
public synchronized long getLastAdjustedTimestampUs() {
|
||||||
return lastSampleTimestampUs != C.TIME_UNSET
|
return lastUnadjustedTimestampUs != C.TIME_UNSET
|
||||||
? (lastSampleTimestampUs + timestampOffsetUs)
|
? lastUnadjustedTimestampUs + timestampOffsetUs
|
||||||
: firstSampleTimestampUs != DO_NOT_OFFSET ? firstSampleTimestampUs : C.TIME_UNSET;
|
: firstSampleTimestampUs != DO_NOT_OFFSET ? firstSampleTimestampUs : C.TIME_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the offset between the input of {@link #adjustSampleTimestamp(long)} and its output. If
|
* Returns the offset between the input of {@link #adjustSampleTimestamp(long)} and its output, or
|
||||||
* {@link #DO_NOT_OFFSET} was provided to the constructor, 0 is returned. If the timestamp
|
* {@link C#TIME_UNSET} if the offset has not yet been determined.
|
||||||
* adjuster is yet not initialized, {@link C#TIME_UNSET} is returned.
|
|
||||||
*
|
|
||||||
* @return The offset between {@link #adjustSampleTimestamp(long)}'s input and output. {@link
|
|
||||||
* C#TIME_UNSET} if the adjuster is not yet initialized and 0 if timestamps should not be
|
|
||||||
* offset.
|
|
||||||
*/
|
*/
|
||||||
public synchronized long getTimestampOffsetUs() {
|
public synchronized long getTimestampOffsetUs() {
|
||||||
return firstSampleTimestampUs == DO_NOT_OFFSET
|
return timestampOffsetUs;
|
||||||
? 0
|
|
||||||
: lastSampleTimestampUs == C.TIME_UNSET ? C.TIME_UNSET : timestampOffsetUs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -140,8 +133,8 @@ public final class TimestampAdjuster {
|
|||||||
*/
|
*/
|
||||||
public synchronized void reset(long firstSampleTimestampUs) {
|
public synchronized void reset(long firstSampleTimestampUs) {
|
||||||
this.firstSampleTimestampUs = firstSampleTimestampUs;
|
this.firstSampleTimestampUs = firstSampleTimestampUs;
|
||||||
lastSampleTimestampUs = C.TIME_UNSET;
|
timestampOffsetUs = firstSampleTimestampUs == DO_NOT_OFFSET ? 0 : C.TIME_UNSET;
|
||||||
timestampOffsetUs = 0;
|
lastUnadjustedTimestampUs = C.TIME_UNSET;
|
||||||
sharedInitializationStarted = false;
|
sharedInitializationStarted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,10 +148,10 @@ public final class TimestampAdjuster {
|
|||||||
if (pts90Khz == C.TIME_UNSET) {
|
if (pts90Khz == C.TIME_UNSET) {
|
||||||
return C.TIME_UNSET;
|
return C.TIME_UNSET;
|
||||||
}
|
}
|
||||||
if (lastSampleTimestampUs != C.TIME_UNSET) {
|
if (lastUnadjustedTimestampUs != C.TIME_UNSET) {
|
||||||
// The wrap count for the current PTS may be closestWrapCount or (closestWrapCount - 1),
|
// The wrap count for the current PTS may be closestWrapCount or (closestWrapCount - 1),
|
||||||
// and we need to snap to the one closest to lastSampleTimestampUs.
|
// and we need to snap to the one closest to lastSampleTimestampUs.
|
||||||
long lastPts = usToNonWrappedPts(lastSampleTimestampUs);
|
long lastPts = usToNonWrappedPts(lastUnadjustedTimestampUs);
|
||||||
long closestWrapCount = (lastPts + (MAX_PTS_PLUS_ONE / 2)) / MAX_PTS_PLUS_ONE;
|
long closestWrapCount = (lastPts + (MAX_PTS_PLUS_ONE / 2)) / MAX_PTS_PLUS_ONE;
|
||||||
long ptsWrapBelow = pts90Khz + (MAX_PTS_PLUS_ONE * (closestWrapCount - 1));
|
long ptsWrapBelow = pts90Khz + (MAX_PTS_PLUS_ONE * (closestWrapCount - 1));
|
||||||
long ptsWrapAbove = pts90Khz + (MAX_PTS_PLUS_ONE * closestWrapCount);
|
long ptsWrapAbove = pts90Khz + (MAX_PTS_PLUS_ONE * closestWrapCount);
|
||||||
@ -180,18 +173,12 @@ public final class TimestampAdjuster {
|
|||||||
if (timeUs == C.TIME_UNSET) {
|
if (timeUs == C.TIME_UNSET) {
|
||||||
return C.TIME_UNSET;
|
return C.TIME_UNSET;
|
||||||
}
|
}
|
||||||
// Record the adjusted PTS to adjust for wraparound next time.
|
if (timestampOffsetUs == C.TIME_UNSET) {
|
||||||
if (lastSampleTimestampUs != C.TIME_UNSET) {
|
timestampOffsetUs = firstSampleTimestampUs - timeUs;
|
||||||
lastSampleTimestampUs = timeUs;
|
// Notify threads waiting for the timestamp offset to be determined.
|
||||||
} else {
|
|
||||||
if (firstSampleTimestampUs != DO_NOT_OFFSET) {
|
|
||||||
// Calculate the timestamp offset.
|
|
||||||
timestampOffsetUs = firstSampleTimestampUs - timeUs;
|
|
||||||
}
|
|
||||||
lastSampleTimestampUs = timeUs;
|
|
||||||
// Notify threads waiting for this adjuster to be initialized.
|
|
||||||
notifyAll();
|
notifyAll();
|
||||||
}
|
}
|
||||||
|
lastUnadjustedTimestampUs = timeUs;
|
||||||
return timeUs + timestampOffsetUs;
|
return timeUs + timestampOffsetUs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,9 +62,10 @@ public final class PassthroughSectionPayloadReader implements SectionPayloadRead
|
|||||||
@Override
|
@Override
|
||||||
public void consume(ParsableByteArray sectionData) {
|
public void consume(ParsableByteArray sectionData) {
|
||||||
assertInitialized();
|
assertInitialized();
|
||||||
|
long sampleTimestampUs = timestampAdjuster.getLastAdjustedTimestampUs();
|
||||||
long subsampleOffsetUs = timestampAdjuster.getTimestampOffsetUs();
|
long subsampleOffsetUs = timestampAdjuster.getTimestampOffsetUs();
|
||||||
if (subsampleOffsetUs == C.TIME_UNSET) {
|
if (sampleTimestampUs == C.TIME_UNSET || subsampleOffsetUs == C.TIME_UNSET) {
|
||||||
// Don't output samples without a known subsample offset.
|
// Don't output samples without a known sample timestamp and subsample offset.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (subsampleOffsetUs != format.subsampleOffsetUs) {
|
if (subsampleOffsetUs != format.subsampleOffsetUs) {
|
||||||
@ -73,12 +74,7 @@ public final class PassthroughSectionPayloadReader implements SectionPayloadRead
|
|||||||
}
|
}
|
||||||
int sampleSize = sectionData.bytesLeft();
|
int sampleSize = sectionData.bytesLeft();
|
||||||
output.sampleData(sectionData, sampleSize);
|
output.sampleData(sectionData, sampleSize);
|
||||||
output.sampleMetadata(
|
output.sampleMetadata(sampleTimestampUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null);
|
||||||
timestampAdjuster.getLastAdjustedTimestampUs(),
|
|
||||||
C.BUFFER_FLAG_KEY_FRAME,
|
|
||||||
sampleSize,
|
|
||||||
0,
|
|
||||||
null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnsuresNonNull({"timestampAdjuster", "output"})
|
@EnsuresNonNull({"timestampAdjuster", "output"})
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
package com.google.android.exoplayer2.source.hls;
|
package com.google.android.exoplayer2.source.hls;
|
||||||
|
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.util.TimestampAdjuster;
|
import com.google.android.exoplayer2.util.TimestampAdjuster;
|
||||||
|
|
||||||
/** Provides {@link TimestampAdjuster} instances for use during HLS playbacks. */
|
/** Provides {@link TimestampAdjuster} instances for use during HLS playbacks. */
|
||||||
@ -37,9 +38,9 @@ public final class TimestampAdjusterProvider {
|
|||||||
* @return A {@link TimestampAdjuster}.
|
* @return A {@link TimestampAdjuster}.
|
||||||
*/
|
*/
|
||||||
public TimestampAdjuster getAdjuster(int discontinuitySequence) {
|
public TimestampAdjuster getAdjuster(int discontinuitySequence) {
|
||||||
TimestampAdjuster adjuster = timestampAdjusters.get(discontinuitySequence);
|
@Nullable TimestampAdjuster adjuster = timestampAdjusters.get(discontinuitySequence);
|
||||||
if (adjuster == null) {
|
if (adjuster == null) {
|
||||||
adjuster = new TimestampAdjuster(TimestampAdjuster.DO_NOT_OFFSET);
|
adjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ 0);
|
||||||
timestampAdjusters.put(discontinuitySequence, adjuster);
|
timestampAdjusters.put(discontinuitySequence, adjuster);
|
||||||
}
|
}
|
||||||
return adjuster;
|
return adjuster;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user