diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java index 145c92e94d..119f586a4d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/DefaultAudioSink.java @@ -115,6 +115,10 @@ public final class DefaultAudioSink implements AudioSink { * Returns the media duration corresponding to the specified playout duration, taking speed * adjustment due to audio processing into account. * + *

The scaling performed by this method will use the actual playback speed achieved by the + * audio processor chain, on average, since it was last flushed. This may differ very slightly + * from the target playback speed. + * * @param playoutDuration The playout duration to scale. * @return The corresponding media duration, in the same units as {@code duration}. */ diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/Sonic.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/Sonic.java index ae65eacd13..5ddedd7bd7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/Sonic.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/Sonic.java @@ -83,6 +83,14 @@ import java.util.Arrays; pitchBuffer = new short[maxRequiredFrameCount * channelCount]; } + /** + * Returns the number of bytes that have been input, but will not be processed until more input + * data is provided. + */ + public int getPendingInputBytes() { + return inputFrameCount * channelCount * BYTES_PER_SAMPLE; + } + /** * Queues remaining data from {@code buffer}, and advances its position by the number of bytes * consumed. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java index 3d11a4c7e3..7acc006bbe 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/SonicAudioProcessor.java @@ -15,10 +15,11 @@ */ package com.google.android.exoplayer2.audio; +import static com.google.android.exoplayer2.util.Assertions.checkNotNull; + import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; -import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -117,16 +118,21 @@ public final class SonicAudioProcessor implements AudioProcessor { * Returns the media duration corresponding to the specified playout duration, taking speed * adjustment into account. * + *

The scaling performed by this method will use the actual playback speed achieved by the + * audio processor, on average, since it was last flushed. This may differ very slightly from the + * target playback speed. + * * @param playoutDuration The playout duration to scale. * @return The corresponding media duration, in the same units as {@code duration}. */ public long getMediaDuration(long playoutDuration) { if (outputBytes >= MIN_BYTES_FOR_DURATION_SCALING_CALCULATION) { + long processedInputBytes = inputBytes - checkNotNull(sonic).getPendingInputBytes(); return outputAudioFormat.sampleRate == inputAudioFormat.sampleRate - ? Util.scaleLargeTimestamp(playoutDuration, inputBytes, outputBytes) + ? Util.scaleLargeTimestamp(playoutDuration, processedInputBytes, outputBytes) : Util.scaleLargeTimestamp( playoutDuration, - inputBytes * outputAudioFormat.sampleRate, + processedInputBytes * outputAudioFormat.sampleRate, outputBytes * inputAudioFormat.sampleRate); } else { return (long) ((double) speed * playoutDuration); @@ -159,7 +165,7 @@ public final class SonicAudioProcessor implements AudioProcessor { @Override public void queueInput(ByteBuffer inputBuffer) { - Sonic sonic = Assertions.checkNotNull(this.sonic); + Sonic sonic = checkNotNull(this.sonic); if (inputBuffer.hasRemaining()) { ShortBuffer shortBuffer = inputBuffer.asShortBuffer(); int inputSize = inputBuffer.remaining();