SonicAudioProcessor: Fix scaling to account for pending input bytes

PiperOrigin-RevId: 344420436
This commit is contained in:
olly 2020-11-26 15:21:35 +00:00 committed by Andrew Lewis
parent 3f6ec59868
commit 596dca6a86
3 changed files with 22 additions and 4 deletions

View File

@ -115,6 +115,10 @@ public final class DefaultAudioSink implements AudioSink {
* Returns the media duration corresponding to the specified playout duration, taking speed * Returns the media duration corresponding to the specified playout duration, taking speed
* adjustment due to audio processing into account. * adjustment due to audio processing into account.
* *
* <p>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. * @param playoutDuration The playout duration to scale.
* @return The corresponding media duration, in the same units as {@code duration}. * @return The corresponding media duration, in the same units as {@code duration}.
*/ */

View File

@ -83,6 +83,14 @@ import java.util.Arrays;
pitchBuffer = new short[maxRequiredFrameCount * channelCount]; 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 * Queues remaining data from {@code buffer}, and advances its position by the number of bytes
* consumed. * consumed.

View File

@ -15,10 +15,11 @@
*/ */
package com.google.android.exoplayer2.audio; package com.google.android.exoplayer2.audio;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; 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 * Returns the media duration corresponding to the specified playout duration, taking speed
* adjustment into account. * adjustment into account.
* *
* <p>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. * @param playoutDuration The playout duration to scale.
* @return The corresponding media duration, in the same units as {@code duration}. * @return The corresponding media duration, in the same units as {@code duration}.
*/ */
public long getMediaDuration(long playoutDuration) { public long getMediaDuration(long playoutDuration) {
if (outputBytes >= MIN_BYTES_FOR_DURATION_SCALING_CALCULATION) { if (outputBytes >= MIN_BYTES_FOR_DURATION_SCALING_CALCULATION) {
long processedInputBytes = inputBytes - checkNotNull(sonic).getPendingInputBytes();
return outputAudioFormat.sampleRate == inputAudioFormat.sampleRate return outputAudioFormat.sampleRate == inputAudioFormat.sampleRate
? Util.scaleLargeTimestamp(playoutDuration, inputBytes, outputBytes) ? Util.scaleLargeTimestamp(playoutDuration, processedInputBytes, outputBytes)
: Util.scaleLargeTimestamp( : Util.scaleLargeTimestamp(
playoutDuration, playoutDuration,
inputBytes * outputAudioFormat.sampleRate, processedInputBytes * outputAudioFormat.sampleRate,
outputBytes * inputAudioFormat.sampleRate); outputBytes * inputAudioFormat.sampleRate);
} else { } else {
return (long) ((double) speed * playoutDuration); return (long) ((double) speed * playoutDuration);
@ -159,7 +165,7 @@ public final class SonicAudioProcessor implements AudioProcessor {
@Override @Override
public void queueInput(ByteBuffer inputBuffer) { public void queueInput(ByteBuffer inputBuffer) {
Sonic sonic = Assertions.checkNotNull(this.sonic); Sonic sonic = checkNotNull(this.sonic);
if (inputBuffer.hasRemaining()) { if (inputBuffer.hasRemaining()) {
ShortBuffer shortBuffer = inputBuffer.asShortBuffer(); ShortBuffer shortBuffer = inputBuffer.asShortBuffer();
int inputSize = inputBuffer.remaining(); int inputSize = inputBuffer.remaining();