From 029071a3425a078ffc45b8f36dd1a2edae1be4fd Mon Sep 17 00:00:00 2001 From: samrobinson Date: Fri, 2 Feb 2024 08:10:58 -0800 Subject: [PATCH] Improve checks around AudioGraphInput configuring with requested format Also adds extra AudioGraphInputTest cases. PiperOrigin-RevId: 603690041 --- .../media3/transformer/AudioGraphInput.java | 8 +- .../transformer/AudioGraphInputTest.java | 83 ++++++++++++++++++- 2 files changed, 85 insertions(+), 6 deletions(-) diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/AudioGraphInput.java b/libraries/transformer/src/main/java/androidx/media3/transformer/AudioGraphInput.java index 5442bb9c27..04dffd04ff 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/AudioGraphInput.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/AudioGraphInput.java @@ -410,8 +410,12 @@ import java.util.concurrent.atomic.AtomicReference; AudioProcessingPipeline audioProcessingPipeline = new AudioProcessingPipeline(audioProcessors.build()); AudioFormat outputAudioFormat = audioProcessingPipeline.configure(inputAudioFormat); - if (!requiredOutputAudioFormat.equals(AudioFormat.NOT_SET) - && !outputAudioFormat.equals(requiredOutputAudioFormat)) { + if ((requiredOutputAudioFormat.sampleRate != Format.NO_VALUE + && requiredOutputAudioFormat.sampleRate != outputAudioFormat.sampleRate) + || (requiredOutputAudioFormat.channelCount != Format.NO_VALUE + && requiredOutputAudioFormat.channelCount != outputAudioFormat.channelCount) + || (requiredOutputAudioFormat.encoding != Format.NO_VALUE + && requiredOutputAudioFormat.encoding != outputAudioFormat.encoding)) { throw new UnhandledAudioFormatException( "Audio can not be modified to match downstream format", inputAudioFormat); } diff --git a/libraries/transformer/src/test/java/androidx/media3/transformer/AudioGraphInputTest.java b/libraries/transformer/src/test/java/androidx/media3/transformer/AudioGraphInputTest.java index ecbb18ae69..7907d0faca 100644 --- a/libraries/transformer/src/test/java/androidx/media3/transformer/AudioGraphInputTest.java +++ b/libraries/transformer/src/test/java/androidx/media3/transformer/AudioGraphInputTest.java @@ -20,9 +20,12 @@ import static androidx.media3.common.util.Util.getPcmFormat; import static com.google.common.truth.Truth.assertThat; import androidx.media3.common.C; +import androidx.media3.common.Format; import androidx.media3.common.MediaItem; import androidx.media3.common.audio.AudioProcessor.AudioFormat; +import androidx.media3.common.util.Util; import androidx.test.ext.junit.runners.AndroidJUnit4; +import java.nio.ByteBuffer; import org.junit.Test; import org.junit.runner.RunWith; @@ -31,19 +34,22 @@ import org.junit.runner.RunWith; public class AudioGraphInputTest { private static final EditedMediaItem FAKE_ITEM = new EditedMediaItem.Builder(MediaItem.EMPTY).build(); - + private static final AudioFormat MONO_44100 = + new AudioFormat(/* sampleRate= */ 44_100, /* channelCount= */ 1, C.ENCODING_PCM_16BIT); private static final AudioFormat MONO_48000 = new AudioFormat(/* sampleRate= */ 48_000, /* channelCount= */ 1, C.ENCODING_PCM_16BIT); private static final AudioFormat STEREO_44100 = new AudioFormat(/* sampleRate= */ 44_100, /* channelCount= */ 2, C.ENCODING_PCM_16BIT); + private static final AudioFormat STEREO_48000 = + new AudioFormat(/* sampleRate= */ 48_000, /* channelCount= */ 2, C.ENCODING_PCM_16BIT); @Test public void getOutputAudioFormat_withUnsetRequestedFormat_matchesInputFormat() throws Exception { AudioGraphInput audioGraphInput = new AudioGraphInput( /* requestedOutputAudioFormat= */ AudioFormat.NOT_SET, - FAKE_ITEM, - getPcmFormat(MONO_48000)); + /* editedMediaItem= */ FAKE_ITEM, + /* inputFormat= */ getPcmFormat(MONO_48000)); assertThat(audioGraphInput.getOutputAudioFormat()).isEqualTo(MONO_48000); } @@ -52,8 +58,77 @@ public class AudioGraphInputTest { public void getOutputAudioFormat_withRequestedFormat_matchesRequestedFormat() throws Exception { AudioGraphInput audioGraphInput = new AudioGraphInput( - /* requestedOutputAudioFormat= */ STEREO_44100, FAKE_ITEM, getPcmFormat(MONO_48000)); + /* requestedOutputAudioFormat= */ STEREO_44100, + /* editedMediaItem= */ FAKE_ITEM, + /* inputFormat= */ getPcmFormat(MONO_48000)); assertThat(audioGraphInput.getOutputAudioFormat()).isEqualTo(STEREO_44100); } + + @Test + public void getOutputAudioFormat_withRequestedSampleRate_combinesWithConfiguredFormat() + throws Exception { + AudioFormat requestedAudioFormat = + new AudioFormat( + /* sampleRate= */ MONO_48000.sampleRate, + /* channelCount= */ Format.NO_VALUE, + /* encoding= */ Format.NO_VALUE); + + AudioGraphInput audioGraphInput = + new AudioGraphInput( + /* requestedOutputAudioFormat= */ requestedAudioFormat, + /* editedMediaItem= */ FAKE_ITEM, + /* inputFormat= */ getPcmFormat(MONO_44100)); + + assertThat(audioGraphInput.getOutputAudioFormat()).isEqualTo(MONO_48000); + } + + @Test + public void getOutputAudioFormat_withRequestedChannelCount_combinesWithConfiguredFormat() + throws Exception { + AudioFormat requestedAudioFormat = + new AudioFormat( + /* sampleRate= */ Format.NO_VALUE, + /* channelCount= */ STEREO_48000.channelCount, + /* encoding= */ Format.NO_VALUE); + + AudioGraphInput audioGraphInput = + new AudioGraphInput( + /* requestedOutputAudioFormat= */ requestedAudioFormat, + /* editedMediaItem= */ FAKE_ITEM, + /* inputFormat= */ getPcmFormat(MONO_44100)); + + assertThat(audioGraphInput.getOutputAudioFormat()).isEqualTo(STEREO_44100); + } + + @Test + public void getOutput_withSilentMediaItemChange_outputsCorrectAmountOfSilentBytes() + throws Exception { + AudioGraphInput audioGraphInput = + new AudioGraphInput( + /* requestedOutputAudioFormat= */ AudioFormat.NOT_SET, + /* editedMediaItem= */ FAKE_ITEM, + /* inputFormat= */ getPcmFormat(STEREO_44100)); + + audioGraphInput.onMediaItemChanged( + /* editedMediaItem= */ FAKE_ITEM, + /* durationUs= */ 1_000_000, + /* decodedFormat= */ null, + /* isLast= */ true); + int bytesOutput = drainAudioGraphInput(audioGraphInput); + + long expectedSampleCount = Util.durationUsToSampleCount(1_000_000, STEREO_44100.sampleRate); + assertThat(bytesOutput).isEqualTo(expectedSampleCount * STEREO_44100.bytesPerFrame); + } + + /** Drains the graph and returns the number of bytes output. */ + private static int drainAudioGraphInput(AudioGraphInput audioGraphInput) throws Exception { + int bytesOutput = 0; + ByteBuffer output; + while ((output = audioGraphInput.getOutput()).hasRemaining() || !audioGraphInput.isEnded()) { + bytesOutput += output.remaining(); + output.position(output.limit()); + } + return bytesOutput; + } }