diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/BaseRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/BaseRenderer.java index 5fc84bd1aa..198b674dce 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/BaseRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/BaseRenderer.java @@ -418,6 +418,15 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { return lastResetPositionUs; } + /** + * Returns the offset added to timestamps of buffers read from the {@link SampleStream}. + * + *
Must only be called if the renderer is at least {@link #STATE_ENABLED}.
+ */
+ protected final long getStreamOffsetUs() {
+ return streamOffsetUs;
+ }
+
/** Returns a clear {@link FormatHolder}. */
protected final FormatHolder getFormatHolder() {
formatHolder.clear();
diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextRenderer.java
index 29af0d4f7b..cc25bee7f7 100644
--- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextRenderer.java
+++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/text/TextRenderer.java
@@ -119,7 +119,6 @@ public final class TextRenderer extends BaseRenderer implements Callback {
private boolean inputStreamEnded;
private boolean outputStreamEnded;
@Nullable private Format streamFormat;
- private long outputStreamOffsetUs;
private long lastRendererPositionUs;
private long finalStreamEndPositionUs;
private boolean legacyDecodingEnabled;
@@ -159,7 +158,6 @@ public final class TextRenderer extends BaseRenderer implements Callback {
new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
formatHolder = new FormatHolder();
finalStreamEndPositionUs = C.TIME_UNSET;
- outputStreamOffsetUs = C.TIME_UNSET;
lastRendererPositionUs = C.TIME_UNSET;
legacyDecodingEnabled = false;
}
@@ -206,7 +204,6 @@ public final class TextRenderer extends BaseRenderer implements Callback {
long startPositionUs,
long offsetUs,
MediaSource.MediaPeriodId mediaPeriodId) {
- outputStreamOffsetUs = offsetUs;
streamFormat = formats[0];
if (!isCuesWithTiming(streamFormat)) {
assertLegacyDecodingEnabledIfRequired();
@@ -462,7 +459,6 @@ public final class TextRenderer extends BaseRenderer implements Callback {
streamFormat = null;
finalStreamEndPositionUs = C.TIME_UNSET;
clearOutput();
- outputStreamOffsetUs = C.TIME_UNSET;
lastRendererPositionUs = C.TIME_UNSET;
if (subtitleDecoder != null) {
releaseSubtitleDecoder();
@@ -579,9 +575,7 @@ public final class TextRenderer extends BaseRenderer implements Callback {
@SideEffectFree
private long getPresentationTimeUs(long positionUs) {
checkState(positionUs != C.TIME_UNSET);
- checkState(outputStreamOffsetUs != C.TIME_UNSET);
-
- return positionUs - outputStreamOffsetUs;
+ return positionUs - getStreamOffsetUs();
}
@RequiresNonNull("streamFormat")
diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/DecoderVideoRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/DecoderVideoRenderer.java
index e128285879..5bb81f91ca 100644
--- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/DecoderVideoRenderer.java
+++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/DecoderVideoRenderer.java
@@ -153,7 +153,6 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
private int consecutiveDroppedFrameCount;
private int buffersInCodecCount;
private long lastRenderTimeUs;
- private long outputStreamOffsetUs;
/** Decoder event counters used for debugging purposes. */
protected DecoderCounters decoderCounters;
@@ -342,10 +341,8 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
long offsetUs,
MediaSource.MediaPeriodId mediaPeriodId)
throws ExoPlaybackException {
- // TODO: This shouldn't just update the output stream offset as long as there are still buffers
- // of the previous stream in the decoder. It should also make sure to render the first frame of
- // the next stream if the playback position reached the new stream.
- outputStreamOffsetUs = offsetUs;
+ // TODO: This code should make sure to render the first frame of the next stream if the playback
+ // position reached the new stream.
super.onStreamChanged(formats, startPositionUs, offsetUs, mediaPeriodId);
}
@@ -875,7 +872,9 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
outputFormat = formatQueue.pollFirst();
}
- long presentationTimeUs = bufferTimeUs - outputStreamOffsetUs;
+ // TODO: This shouldn't just use the input stream offset and we should correctly track the
+ // output stream offset after decoding instead.
+ long presentationTimeUs = bufferTimeUs - getStreamOffsetUs();
if (shouldForceRender(earlyUs)) {
renderOutputBuffer(outputBuffer, presentationTimeUs, checkNotNull(outputFormat));
return true;
diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/spherical/CameraMotionRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/spherical/CameraMotionRenderer.java
index 7f02fdefe4..ffbdfe0db8 100644
--- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/spherical/CameraMotionRenderer.java
+++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/spherical/CameraMotionRenderer.java
@@ -28,7 +28,6 @@ import androidx.media3.exoplayer.ExoPlaybackException;
import androidx.media3.exoplayer.FormatHolder;
import androidx.media3.exoplayer.Renderer;
import androidx.media3.exoplayer.RendererCapabilities;
-import androidx.media3.exoplayer.source.MediaSource;
import androidx.media3.exoplayer.source.SampleStream.ReadDataResult;
import java.nio.ByteBuffer;
@@ -43,7 +42,6 @@ public final class CameraMotionRenderer extends BaseRenderer {
private final DecoderInputBuffer buffer;
private final ParsableByteArray scratch;
- private long offsetUs;
@Nullable private CameraMotionListener listener;
private long lastTimestampUs;
@@ -75,15 +73,6 @@ public final class CameraMotionRenderer extends BaseRenderer {
}
}
- @Override
- protected void onStreamChanged(
- Format[] formats,
- long startPositionUs,
- long offsetUs,
- MediaSource.MediaPeriodId mediaPeriodId) {
- this.offsetUs = offsetUs;
- }
-
@Override
protected void onPositionReset(long positionUs, boolean joining) {
lastTimestampUs = Long.MIN_VALUE;
@@ -118,7 +107,7 @@ public final class CameraMotionRenderer extends BaseRenderer {
continue;
}
- Util.castNonNull(listener).onCameraMotion(lastTimestampUs - offsetUs, rotation);
+ Util.castNonNull(listener).onCameraMotion(lastTimestampUs - getStreamOffsetUs(), rotation);
}
}
diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/FakeVideoRenderer.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/FakeVideoRenderer.java
index 6df5063b58..4490c66329 100644
--- a/libraries/test_utils/src/main/java/androidx/media3/test/utils/FakeVideoRenderer.java
+++ b/libraries/test_utils/src/main/java/androidx/media3/test/utils/FakeVideoRenderer.java
@@ -43,7 +43,6 @@ public class FakeVideoRenderer extends FakeRenderer {
private final AtomicReference