From 820433de06dc6f86fb2c1e2a922400ae6ee6e32f Mon Sep 17 00:00:00 2001 From: Oliver Woodman Date: Thu, 10 Sep 2015 18:17:13 +0100 Subject: [PATCH] Call stop() to fully play out remaining audio! Issue: #707 --- .../ext/opus/LibopusAudioTrackRenderer.java | 4 ++-- .../MediaCodecAudioTrackRenderer.java | 10 ++++++---- .../exoplayer/MediaCodecTrackRenderer.java | 12 ++++++++++++ .../android/exoplayer/audio/AudioTrack.java | 18 +++++++++++------- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/extensions/opus/src/main/java/com/google/android/exoplayer/ext/opus/LibopusAudioTrackRenderer.java b/extensions/opus/src/main/java/com/google/android/exoplayer/ext/opus/LibopusAudioTrackRenderer.java index ee4de64fac..e8fd8c8306 100644 --- a/extensions/opus/src/main/java/com/google/android/exoplayer/ext/opus/LibopusAudioTrackRenderer.java +++ b/extensions/opus/src/main/java/com/google/android/exoplayer/ext/opus/LibopusAudioTrackRenderer.java @@ -212,6 +212,7 @@ public final class LibopusAudioTrackRenderer extends SampleSourceTrackRenderer if (outputBuffer.getFlag(OpusDecoderWrapper.FLAG_END_OF_STREAM)) { outputStreamEnded = true; + audioTrack.handleEndOfStream(); decoder.releaseOutputBuffer(outputBuffer); outputBuffer = null; return; @@ -304,8 +305,7 @@ public final class LibopusAudioTrackRenderer extends SampleSourceTrackRenderer @Override protected boolean isEnded() { - return outputStreamEnded && (!audioTrack.hasPendingData() - || !audioTrack.hasEnoughDataToBeginPlayback()); + return outputStreamEnded && !audioTrack.hasPendingData(); } @Override diff --git a/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java index c49227e6d4..501bdf5567 100644 --- a/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java @@ -265,10 +265,7 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem @Override protected boolean isEnded() { - // We've exhausted the output stream, and the AudioTrack has either played all of the data - // submitted, or has been fed insufficient data to begin playback. - return super.isEnded() && (!audioTrack.hasPendingData() - || !audioTrack.hasEnoughDataToBeginPlayback()); + return super.isEnded() && !audioTrack.hasPendingData(); } @Override @@ -366,6 +363,11 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem return false; } + @Override + protected void onOutputStreamEnded() { + audioTrack.handleEndOfStream(); + } + protected void handleDiscontinuity() { // Do nothing } diff --git a/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java index 193cd0d48d..118ee4dd68 100644 --- a/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java @@ -719,6 +719,17 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer // Do nothing. } + /** + * Invoked when the output stream ends, meaning that the last output buffer has been processed + * and the {@link MediaCodec#BUFFER_FLAG_END_OF_STREAM} flag has been propagated through the + * decoder. + *

+ * The default implementation is a no-op. + */ + protected void onOutputStreamEnded() { + // Do nothing. + } + /** * Determines whether the existing {@link MediaCodec} should be reconfigured for a new format by * sending codec specific initialization data at the start of the next input buffer. If true is @@ -846,6 +857,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer maybeInitCodec(); } else { outputStreamEnded = true; + onOutputStreamEnded(); } } diff --git a/library/src/main/java/com/google/android/exoplayer/audio/AudioTrack.java b/library/src/main/java/com/google/android/exoplayer/audio/AudioTrack.java index ee3a9fb6b8..b326590fde 100644 --- a/library/src/main/java/com/google/android/exoplayer/audio/AudioTrack.java +++ b/library/src/main/java/com/google/android/exoplayer/audio/AudioTrack.java @@ -562,6 +562,17 @@ public final class AudioTrack { return result; } + /** + * Ensures that the last data passed to {@link #handleBuffer(ByteBuffer, int, int, long)} is + * played out in full. + */ + public void handleEndOfStream() { + if (audioTrack != null) { + // Required to ensure that the media written to the AudioTrack is played out in full. + audioTrack.stop(); + } + } + @TargetApi(21) private static int writeNonBlockingV21( android.media.AudioTrack audioTrack, ByteBuffer buffer, int size) { @@ -575,13 +586,6 @@ public final class AudioTrack { || audioTrackUtil.overrideHasPendingData()); } - /** Returns whether enough data has been supplied via {@link #handleBuffer} to begin playback. */ - public boolean hasEnoughDataToBeginPlayback() { - // The value of minBufferSize can be slightly less than what's actually required for playback - // to start, hence the multiplication factor. - return submittedBytes > (minBufferSize * 3) / 2; - } - /** Sets the playback volume. */ public void setVolume(float volume) { if (this.volume != volume) {