mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Fix SCTE-35 timestamp adjustment
Issue:#4573 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=206737252
This commit is contained in:
parent
e2bf474c1e
commit
9ec14d1ada
@ -4,8 +4,11 @@
|
||||
|
||||
* Add `AudioListener` for listening to changes in audio configuration during
|
||||
playback ([#3994](https://github.com/google/ExoPlayer/issues/3994)).
|
||||
* MPEG-TS: Support CEA-608/708 in H262
|
||||
([#2565](https://github.com/google/ExoPlayer/issues/2565)).
|
||||
* MPEG-TS:
|
||||
* Support CEA-608/708 in H262
|
||||
([#2565](https://github.com/google/ExoPlayer/issues/2565)).
|
||||
* Fix bug preventing SCTE-35 cues from being output
|
||||
([#4573](https://github.com/google/ExoPlayer/issues/4573)).
|
||||
* MPEG-PS: Support reading duration from MPEG-PS Streams
|
||||
([#4476](https://github.com/google/ExoPlayer/issues/4476)).
|
||||
* MediaSession extension:
|
||||
|
@ -30,7 +30,8 @@ public final class TimestampAdjuster {
|
||||
public static final long DO_NOT_OFFSET = Long.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* The value one greater than the largest representable (33 bit) MPEG-2 TS presentation timestamp.
|
||||
* The value one greater than the largest representable (33 bit) MPEG-2 TS 90 kHz clock
|
||||
* presentation timestamp.
|
||||
*/
|
||||
private static final long MAX_PTS_PLUS_ONE = 0x200000000L;
|
||||
|
||||
@ -38,13 +39,13 @@ public final class TimestampAdjuster {
|
||||
private long timestampOffsetUs;
|
||||
|
||||
// Volatile to allow isInitialized to be called on a different thread to adjustSampleTimestamp.
|
||||
private volatile long lastSampleTimestamp;
|
||||
private volatile long lastSampleTimestampUs;
|
||||
|
||||
/**
|
||||
* @param firstSampleTimestampUs See {@link #setFirstSampleTimestampUs(long)}.
|
||||
*/
|
||||
public TimestampAdjuster(long firstSampleTimestampUs) {
|
||||
lastSampleTimestamp = C.TIME_UNSET;
|
||||
lastSampleTimestampUs = C.TIME_UNSET;
|
||||
setFirstSampleTimestampUs(firstSampleTimestampUs);
|
||||
}
|
||||
|
||||
@ -56,30 +57,24 @@ public final class TimestampAdjuster {
|
||||
* {@link #DO_NOT_OFFSET} if presentation timestamps should not be offset.
|
||||
*/
|
||||
public synchronized void setFirstSampleTimestampUs(long firstSampleTimestampUs) {
|
||||
Assertions.checkState(lastSampleTimestamp == C.TIME_UNSET);
|
||||
Assertions.checkState(lastSampleTimestampUs == C.TIME_UNSET);
|
||||
this.firstSampleTimestampUs = firstSampleTimestampUs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first adjusted sample timestamp in microseconds.
|
||||
*
|
||||
* @return The first adjusted sample timestamp in microseconds.
|
||||
*/
|
||||
/** Returns the last value passed to {@link #setFirstSampleTimestampUs(long)}. */
|
||||
public long getFirstSampleTimestampUs() {
|
||||
return firstSampleTimestampUs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last adjusted timestamp. If no timestamp has been adjusted, returns
|
||||
* {@code firstSampleTimestampUs} as provided to the constructor. If this value is
|
||||
* {@link #DO_NOT_OFFSET}, returns {@link C#TIME_UNSET}.
|
||||
*
|
||||
* @return The last adjusted timestamp. If not present, {@code firstSampleTimestampUs} is
|
||||
* returned unless equal to {@link #DO_NOT_OFFSET}, in which case {@link C#TIME_UNSET} is
|
||||
* returned.
|
||||
* Returns the last value obtained from {@link #adjustSampleTimestamp}. If {@link
|
||||
* #adjustSampleTimestamp} has not been called, returns the result of calling {@link
|
||||
* #getFirstSampleTimestampUs()}. If this value is {@link #DO_NOT_OFFSET}, returns {@link
|
||||
* C#TIME_UNSET}.
|
||||
*/
|
||||
public long getLastAdjustedTimestampUs() {
|
||||
return lastSampleTimestamp != C.TIME_UNSET ? lastSampleTimestamp
|
||||
return lastSampleTimestampUs != C.TIME_UNSET
|
||||
? (lastSampleTimestampUs + timestampOffsetUs)
|
||||
: firstSampleTimestampUs != DO_NOT_OFFSET ? firstSampleTimestampUs : C.TIME_UNSET;
|
||||
}
|
||||
|
||||
@ -93,44 +88,47 @@ public final class TimestampAdjuster {
|
||||
* be offset.
|
||||
*/
|
||||
public long getTimestampOffsetUs() {
|
||||
return firstSampleTimestampUs == DO_NOT_OFFSET ? 0
|
||||
: lastSampleTimestamp == C.TIME_UNSET ? C.TIME_UNSET : timestampOffsetUs;
|
||||
return firstSampleTimestampUs == DO_NOT_OFFSET
|
||||
? 0
|
||||
: lastSampleTimestampUs == C.TIME_UNSET ? C.TIME_UNSET : timestampOffsetUs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the instance to its initial state.
|
||||
*/
|
||||
public void reset() {
|
||||
lastSampleTimestamp = C.TIME_UNSET;
|
||||
lastSampleTimestampUs = C.TIME_UNSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales and offsets an MPEG-2 TS presentation timestamp considering wraparound.
|
||||
*
|
||||
* @param pts The MPEG-2 TS presentation timestamp.
|
||||
* @param pts90Khz A 90 kHz clock MPEG-2 TS presentation timestamp.
|
||||
* @return The adjusted timestamp in microseconds.
|
||||
*/
|
||||
public long adjustTsTimestamp(long pts) {
|
||||
if (pts == C.TIME_UNSET) {
|
||||
public long adjustTsTimestamp(long pts90Khz) {
|
||||
if (pts90Khz == C.TIME_UNSET) {
|
||||
return C.TIME_UNSET;
|
||||
}
|
||||
if (lastSampleTimestamp != C.TIME_UNSET) {
|
||||
if (lastSampleTimestampUs != C.TIME_UNSET) {
|
||||
// The wrap count for the current PTS may be closestWrapCount or (closestWrapCount - 1),
|
||||
// and we need to snap to the one closest to lastSampleTimestamp.
|
||||
long lastPts = usToPts(lastSampleTimestamp);
|
||||
// and we need to snap to the one closest to lastSampleTimestampUs.
|
||||
long lastPts = usToPts(lastSampleTimestampUs);
|
||||
long closestWrapCount = (lastPts + (MAX_PTS_PLUS_ONE / 2)) / MAX_PTS_PLUS_ONE;
|
||||
long ptsWrapBelow = pts + (MAX_PTS_PLUS_ONE * (closestWrapCount - 1));
|
||||
long ptsWrapAbove = pts + (MAX_PTS_PLUS_ONE * closestWrapCount);
|
||||
pts = Math.abs(ptsWrapBelow - lastPts) < Math.abs(ptsWrapAbove - lastPts)
|
||||
? ptsWrapBelow : ptsWrapAbove;
|
||||
long ptsWrapBelow = pts90Khz + (MAX_PTS_PLUS_ONE * (closestWrapCount - 1));
|
||||
long ptsWrapAbove = pts90Khz + (MAX_PTS_PLUS_ONE * closestWrapCount);
|
||||
pts90Khz =
|
||||
Math.abs(ptsWrapBelow - lastPts) < Math.abs(ptsWrapAbove - lastPts)
|
||||
? ptsWrapBelow
|
||||
: ptsWrapAbove;
|
||||
}
|
||||
return adjustSampleTimestamp(ptsToUs(pts));
|
||||
return adjustSampleTimestamp(ptsToUs(pts90Khz));
|
||||
}
|
||||
|
||||
/**
|
||||
* Offsets a sample timestamp in microseconds.
|
||||
* Offsets a timestamp in microseconds.
|
||||
*
|
||||
* @param timeUs The timestamp of a sample to adjust.
|
||||
* @param timeUs The timestamp to adjust in microseconds.
|
||||
* @return The adjusted timestamp in microseconds.
|
||||
*/
|
||||
public long adjustSampleTimestamp(long timeUs) {
|
||||
@ -138,15 +136,15 @@ public final class TimestampAdjuster {
|
||||
return C.TIME_UNSET;
|
||||
}
|
||||
// Record the adjusted PTS to adjust for wraparound next time.
|
||||
if (lastSampleTimestamp != C.TIME_UNSET) {
|
||||
lastSampleTimestamp = timeUs;
|
||||
if (lastSampleTimestampUs != C.TIME_UNSET) {
|
||||
lastSampleTimestampUs = timeUs;
|
||||
} else {
|
||||
if (firstSampleTimestampUs != DO_NOT_OFFSET) {
|
||||
// Calculate the timestamp offset.
|
||||
timestampOffsetUs = firstSampleTimestampUs - timeUs;
|
||||
}
|
||||
synchronized (this) {
|
||||
lastSampleTimestamp = timeUs;
|
||||
lastSampleTimestampUs = timeUs;
|
||||
// Notify threads waiting for this adjuster to be initialized.
|
||||
notifyAll();
|
||||
}
|
||||
@ -160,15 +158,15 @@ public final class TimestampAdjuster {
|
||||
* @throws InterruptedException If the thread was interrupted.
|
||||
*/
|
||||
public synchronized void waitUntilInitialized() throws InterruptedException {
|
||||
while (lastSampleTimestamp == C.TIME_UNSET) {
|
||||
while (lastSampleTimestampUs == C.TIME_UNSET) {
|
||||
wait();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value in MPEG-2 timestamp units to the corresponding value in microseconds.
|
||||
* Converts a 90 kHz clock timestamp to a timestamp in microseconds.
|
||||
*
|
||||
* @param pts A value in MPEG-2 timestamp units.
|
||||
* @param pts A 90 kHz clock timestamp.
|
||||
* @return The corresponding value in microseconds.
|
||||
*/
|
||||
public static long ptsToUs(long pts) {
|
||||
@ -176,10 +174,10 @@ public final class TimestampAdjuster {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value in microseconds to the corresponding values in MPEG-2 timestamp units.
|
||||
* Converts a timestamp in microseconds to a 90 kHz clock timestamp.
|
||||
*
|
||||
* @param us A value in microseconds.
|
||||
* @return The corresponding value in MPEG-2 timestamp units.
|
||||
* @return The corresponding value as a 90 kHz clock timestamp.
|
||||
*/
|
||||
public static long usToPts(long us) {
|
||||
return (us * 90000) / C.MICROS_PER_SECOND;
|
||||
|
Loading…
x
Reference in New Issue
Block a user