From 2516e94eb9f7ff5670d0f6ed129a131408d2e4b0 Mon Sep 17 00:00:00 2001 From: andrewlewis Date: Thu, 3 Dec 2020 09:56:22 +0000 Subject: [PATCH] Fix `SonicAudioProcessor` end of stream behavior The `AudioProcessor` interface requires that no more input is queued after queueing end of stream, but `DefaultAudioSink` did queue more input and the implementation of `SonicAudioProcessor` actually relied on this to drain output at the end of the stream. Fix this behavior by getting `Sonic` output in `getOutput` and having `DefaultAudioSink` only queue input to processors that are not draining. Also add TODOs to clean up audio processor implementations where the code handles interaction that doesn't conform to the interface. PiperOrigin-RevId: 345406478 --- .../exoplayer2/ext/gvr/GvrAudioProcessor.java | 1 + .../exoplayer2/audio/DefaultAudioSink.java | 4 +- .../exoplayer2/audio/SonicAudioProcessor.java | 47 ++++++++++--------- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java b/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java index 14570759c3..041ca09db4 100644 --- a/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java +++ b/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrAudioProcessor.java @@ -135,6 +135,7 @@ public class GvrAudioProcessor implements AudioProcessor { @Override public void queueEndOfStream() { + // TODO(internal b/174554082): assert gvrAudioSurround is non-null here and in getOutput. if (gvrAudioSurround != null) { gvrAudioSurround.triggerProcessing(); } 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 26ec4b94c2..691580143a 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 @@ -869,7 +869,9 @@ public final class DefaultAudioSink implements AudioSink { writeBuffer(input, avSyncPresentationTimeUs); } else { AudioProcessor audioProcessor = activeAudioProcessors[index]; - audioProcessor.queueInput(input); + if (index > drainingAudioProcessorIndex) { + audioProcessor.queueInput(input); + } ByteBuffer output = audioProcessor.getOutput(); outputBuffers[index] = output; if (output.hasRemaining()) { 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 ef5bbbc078..f859761954 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 @@ -165,32 +165,20 @@ public final class SonicAudioProcessor implements AudioProcessor { @Override public void queueInput(ByteBuffer inputBuffer) { + if (!inputBuffer.hasRemaining()) { + return; + } Sonic sonic = checkNotNull(this.sonic); - if (inputBuffer.hasRemaining()) { - ShortBuffer shortBuffer = inputBuffer.asShortBuffer(); - int inputSize = inputBuffer.remaining(); - inputBytes += inputSize; - sonic.queueInput(shortBuffer); - inputBuffer.position(inputBuffer.position() + inputSize); - } - int outputSize = sonic.getOutputSize(); - if (outputSize > 0) { - if (buffer.capacity() < outputSize) { - buffer = ByteBuffer.allocateDirect(outputSize).order(ByteOrder.nativeOrder()); - shortBuffer = buffer.asShortBuffer(); - } else { - buffer.clear(); - shortBuffer.clear(); - } - sonic.getOutput(shortBuffer); - outputBytes += outputSize; - buffer.limit(outputSize); - outputBuffer = buffer; - } + ShortBuffer shortBuffer = inputBuffer.asShortBuffer(); + int inputSize = inputBuffer.remaining(); + inputBytes += inputSize; + sonic.queueInput(shortBuffer); + inputBuffer.position(inputBuffer.position() + inputSize); } @Override public void queueEndOfStream() { + // TODO(internal b/174554082): assert sonic is non-null here and in getOutput. if (sonic != null) { sonic.queueEndOfStream(); } @@ -199,6 +187,23 @@ public final class SonicAudioProcessor implements AudioProcessor { @Override public ByteBuffer getOutput() { + @Nullable Sonic sonic = this.sonic; + if (sonic != null) { + int outputSize = sonic.getOutputSize(); + if (outputSize > 0) { + if (buffer.capacity() < outputSize) { + buffer = ByteBuffer.allocateDirect(outputSize).order(ByteOrder.nativeOrder()); + shortBuffer = buffer.asShortBuffer(); + } else { + buffer.clear(); + shortBuffer.clear(); + } + sonic.getOutput(shortBuffer); + outputBytes += outputSize; + buffer.limit(outputSize); + outputBuffer = buffer; + } + } ByteBuffer outputBuffer = this.outputBuffer; this.outputBuffer = EMPTY_BUFFER; return outputBuffer;