From ba2b9b3d67d1133e77c402978ed10bb8f9e791fa Mon Sep 17 00:00:00 2001 From: tonihei Date: Tue, 7 Feb 2023 12:06:49 +0000 Subject: [PATCH] Fix AudioTrackPositionTracker logic for playback speed adjustments The AudioTrackPositionTracker needs to correct positions by the speed set on the AudioTrack itself whenever it makes estimations based on real-time (=the real-time playout duration is not equal to the media duration played). This happens for the main playback path already, but not for the mode in which the position is estimated from the playback head position and also not in the phase after the track has been stopped. Both cases are not very noticeable during normal playback, but become relevant when playing in offload mode. PiperOrigin-RevId: 507736408 (cherry picked from commit 01d7bc72794b98d19cad2be5c70de2f755bff9f1) --- .../exoplayer/audio/AudioTrackPositionTracker.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioTrackPositionTracker.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioTrackPositionTracker.java index 952c5fb8b6..417d0fb027 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioTrackPositionTracker.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/AudioTrackPositionTracker.java @@ -253,6 +253,7 @@ import java.lang.reflect.Method; if (audioTimestampPoller != null) { audioTimestampPoller.reset(); } + resetSyncParams(); } public long getCurrentPositionUs(boolean sourceEnded) { @@ -282,7 +283,9 @@ import java.lang.reflect.Method; // getPlaybackHeadPositionUs() only has a granularity of ~20 ms, so we base the position off // the system clock (and a smoothed offset between it and the playhead position) so as to // prevent jitter in the reported positions. - positionUs = systemTimeUs + smoothedPlayheadOffsetUs; + positionUs = + Util.getMediaDurationForPlayoutDuration( + systemTimeUs + smoothedPlayheadOffsetUs, audioTrackPlaybackSpeed); } if (!sourceEnded) { positionUs = max(0, positionUs - latencyUs); @@ -452,7 +455,9 @@ import java.lang.reflect.Method; long systemTimeUs = System.nanoTime() / 1000; if (systemTimeUs - lastPlayheadSampleTimeUs >= MIN_PLAYHEAD_OFFSET_SAMPLE_INTERVAL_US) { // Take a new sample and update the smoothed offset between the system clock and the playhead. - playheadOffsets[nextPlayheadOffsetIndex] = playbackPositionUs - systemTimeUs; + playheadOffsets[nextPlayheadOffsetIndex] = + Util.getPlayoutDurationForMediaDuration(playbackPositionUs, audioTrackPlaybackSpeed) + - systemTimeUs; nextPlayheadOffsetIndex = (nextPlayheadOffsetIndex + 1) % MAX_PLAYHEAD_OFFSET_COUNT; if (playheadOffsetCount < MAX_PLAYHEAD_OFFSET_COUNT) { playheadOffsetCount++; @@ -580,7 +585,9 @@ import java.lang.reflect.Method; if (stopTimestampUs != C.TIME_UNSET) { // Simulate the playback head position up to the total number of frames submitted. long elapsedTimeSinceStopUs = (SystemClock.elapsedRealtime() * 1000) - stopTimestampUs; - long framesSinceStop = (elapsedTimeSinceStopUs * outputSampleRate) / C.MICROS_PER_SECOND; + long mediaTimeSinceStopUs = + Util.getMediaDurationForPlayoutDuration(elapsedTimeSinceStopUs, audioTrackPlaybackSpeed); + long framesSinceStop = (mediaTimeSinceStopUs * outputSampleRate) / C.MICROS_PER_SECOND; return min(endPlaybackHeadPosition, stopPlaybackHeadPosition + framesSinceStop); }