From 48e3c6fd750cdcb61fb5d00aab4eb293595d0444 Mon Sep 17 00:00:00 2001 From: ivanbuper Date: Tue, 31 Dec 2024 10:23:36 -0800 Subject: [PATCH] Rollback of https://github.com/androidx/media/commit/f60d2b41467d9fcc7562bece1b0297a3d9d85b06 PiperOrigin-RevId: 710998501 --- .../audio/SpeedChangingAudioProcessor.java | 58 ++++++++++++------- .../SpeedChangingAudioProcessorTest.java | 22 +++++++ 2 files changed, 60 insertions(+), 20 deletions(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/audio/SpeedChangingAudioProcessor.java b/libraries/common/src/main/java/androidx/media3/common/audio/SpeedChangingAudioProcessor.java index e6545e16d2..83e9cf598e 100644 --- a/libraries/common/src/main/java/androidx/media3/common/audio/SpeedChangingAudioProcessor.java +++ b/libraries/common/src/main/java/androidx/media3/common/audio/SpeedChangingAudioProcessor.java @@ -24,7 +24,6 @@ import static androidx.media3.common.util.Util.sampleCountToDurationUs; import static java.lang.Math.min; import static java.lang.Math.round; -import android.annotation.SuppressLint; import androidx.annotation.GuardedBy; import androidx.annotation.IntRange; import androidx.media3.common.C; @@ -45,10 +44,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; /** * An {@link AudioProcessor} that changes the speed of audio samples depending on their timestamp. */ -// TODO(b/288221200): Consider making the processor inactive and skipping it in the processor chain -// when speed is 1. @UnstableApi -public final class SpeedChangingAudioProcessor extends BaseAudioProcessor { +public final class SpeedChangingAudioProcessor implements AudioProcessor { private final Object lock; @@ -97,7 +94,18 @@ public final class SpeedChangingAudioProcessor extends BaseAudioProcessor { private boolean endOfStreamQueuedToSonic; + /** The current input audio format. */ + private AudioFormat inputAudioFormat; + + private AudioFormat pendingInputAudioFormat; + private AudioFormat pendingOutputAudioFormat; + private boolean inputEnded; + public SpeedChangingAudioProcessor(SpeedProvider speedProvider) { + pendingInputAudioFormat = AudioFormat.NOT_SET; + pendingOutputAudioFormat = AudioFormat.NOT_SET; + inputAudioFormat = AudioFormat.NOT_SET; + this.speedProvider = speedProvider; lock = new Object(); sonicAudioProcessor = @@ -105,7 +113,7 @@ public final class SpeedChangingAudioProcessor extends BaseAudioProcessor { pendingCallbackInputTimesUs = new LongArrayQueue(); pendingCallbacks = new ArrayDeque<>(); speedAdjustedTimeAsyncInputTimeUs = C.TIME_UNSET; - resetState(/* shouldResetSpeed= */ true); + resetInternalState(/* shouldResetSpeed= */ true); } /** Returns the estimated number of samples output given the provided parameters. */ @@ -145,14 +153,20 @@ public final class SpeedChangingAudioProcessor extends BaseAudioProcessor { } @Override - public long getDurationAfterProcessorApplied(long durationUs) { - return SpeedProviderUtil.getDurationAfterSpeedProviderApplied(speedProvider, durationUs); + public AudioFormat configure(AudioFormat inputAudioFormat) throws UnhandledAudioFormatException { + pendingInputAudioFormat = inputAudioFormat; + pendingOutputAudioFormat = sonicAudioProcessor.configure(inputAudioFormat); + return pendingOutputAudioFormat; } @Override - public AudioFormat onConfigure(AudioFormat inputAudioFormat) - throws UnhandledAudioFormatException { - return sonicAudioProcessor.configure(inputAudioFormat); + public boolean isActive() { + return !pendingOutputAudioFormat.equals(AudioFormat.NOT_SET); + } + + @Override + public long getDurationAfterProcessorApplied(long durationUs) { + return SpeedProviderUtil.getDurationAfterSpeedProviderApplied(speedProvider, durationUs); } @Override @@ -191,15 +205,14 @@ public final class SpeedChangingAudioProcessor extends BaseAudioProcessor { } @Override - protected void onQueueEndOfStream() { + public void queueEndOfStream() { + inputEnded = true; if (!endOfStreamQueuedToSonic) { sonicAudioProcessor.queueEndOfStream(); endOfStreamQueuedToSonic = true; } } - // Not using BaseAudioProcessor's buffers. - @SuppressLint("MissingSuperCall") @Override public ByteBuffer getOutput() { ByteBuffer output = sonicAudioProcessor.getOutput(); @@ -209,18 +222,24 @@ public final class SpeedChangingAudioProcessor extends BaseAudioProcessor { @Override public boolean isEnded() { - return super.isEnded() && sonicAudioProcessor.isEnded(); + return inputEnded && sonicAudioProcessor.isEnded(); } @Override - protected void onFlush() { - resetState(/* shouldResetSpeed= */ false); + public void flush() { + inputEnded = false; + inputAudioFormat = pendingInputAudioFormat; + resetInternalState(/* shouldResetSpeed= */ false); sonicAudioProcessor.flush(); } @Override - protected void onReset() { - resetState(/* shouldResetSpeed= */ true); + public void reset() { + flush(); + pendingInputAudioFormat = AudioFormat.NOT_SET; + pendingOutputAudioFormat = AudioFormat.NOT_SET; + inputAudioFormat = AudioFormat.NOT_SET; + resetInternalState(/* shouldResetSpeed= */ true); sonicAudioProcessor.reset(); } @@ -352,7 +371,6 @@ public final class SpeedChangingAudioProcessor extends BaseAudioProcessor { // Invalidate any previously created buffers in SonicAudioProcessor and the base class. sonicAudioProcessor.flush(); endOfStreamQueuedToSonic = false; - super.getOutput(); } } } @@ -404,7 +422,7 @@ public final class SpeedChangingAudioProcessor extends BaseAudioProcessor { */ @EnsuresNonNull({"inputSegmentStartTimesUs", "outputSegmentStartTimesUs"}) @RequiresNonNull("lock") - private void resetState( + private void resetInternalState( @UnknownInitialization SpeedChangingAudioProcessor this, boolean shouldResetSpeed) { synchronized (lock) { inputSegmentStartTimesUs = new LongArray(); diff --git a/libraries/common/src/test/java/androidx/media3/common/audio/SpeedChangingAudioProcessorTest.java b/libraries/common/src/test/java/androidx/media3/common/audio/SpeedChangingAudioProcessorTest.java index 2ab63e423e..1e1bf0560b 100644 --- a/libraries/common/src/test/java/androidx/media3/common/audio/SpeedChangingAudioProcessorTest.java +++ b/libraries/common/src/test/java/androidx/media3/common/audio/SpeedChangingAudioProcessorTest.java @@ -779,6 +779,28 @@ public class SpeedChangingAudioProcessorTest { /* speedProvider= */ null, AUDIO_FORMAT.sampleRate, /* inputSamples= */ 1000L)); } + @Test + public void isActive_beforeConfigure_returnsFalse() { + SpeedProvider speedProvider = + TestSpeedProvider.createWithFrameCounts( + AUDIO_FORMAT, /* frameCounts= */ new int[] {1000}, /* speeds= */ new float[] {2f}); + + SpeedChangingAudioProcessor processor = new SpeedChangingAudioProcessor(speedProvider); + assertThat(processor.isActive()).isFalse(); + } + + @Test + public void isActive_afterConfigure_returnsTrue() + throws AudioProcessor.UnhandledAudioFormatException { + SpeedProvider speedProvider = + TestSpeedProvider.createWithFrameCounts( + AUDIO_FORMAT, /* frameCounts= */ new int[] {1000}, /* speeds= */ new float[] {2f}); + + SpeedChangingAudioProcessor processor = new SpeedChangingAudioProcessor(speedProvider); + processor.configure(AUDIO_FORMAT); + assertThat(processor.isActive()).isTrue(); + } + private static SpeedChangingAudioProcessor getConfiguredSpeedChangingAudioProcessor( SpeedProvider speedProvider) throws AudioProcessor.UnhandledAudioFormatException { SpeedChangingAudioProcessor speedChangingAudioProcessor =