diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java index bb7ef22ef4..bf1dc3ca8a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/AudioSink.java @@ -23,29 +23,30 @@ import java.nio.ByteBuffer; /** * A sink that consumes audio data. - *

- * Before starting playback, specify the input audio format by calling - * {@link #configure(int, int, int, int, int[], int, int)}. - *

- * Call {@link #handleBuffer(ByteBuffer, long)} to write data, and {@link #handleDiscontinuity()} + * + *

Before starting playback, specify the input audio format by calling {@link #configure(int, + * int, int, int, int[], int, int)}. + * + *

Call {@link #handleBuffer(ByteBuffer, long)} to write data, and {@link #handleDiscontinuity()} * when the data being fed is discontinuous. Call {@link #play()} to start playing the written data. - *

- * Call {@link #configure(int, int, int, int, int[], int, int)} whenever the input format changes. - * The sink will be reinitialized on the next call to {@link #handleBuffer(ByteBuffer, long)}. - *

- * Call {@link #reset()} to prepare the sink to receive audio data from a new playback position. - *

- * Call {@link #playToEndOfStream()} repeatedly to play out all data when no more input buffers will - * be provided via {@link #handleBuffer(ByteBuffer, long)} until the next {@link #reset()}. Call - * {@link #release()} when the instance is no longer required. - *

- * The implementation may be backed by a platform {@link AudioTrack}. In this case, - * {@link #setAudioSessionId(int)}, {@link #setAudioAttributes(AudioAttributes)}, - * {@link #enableTunnelingV21(int)} and/or {@link #disableTunneling()} may be called before writing - * data to the sink. These methods may also be called after writing data to the sink, in which case - * it will be reinitialized as required. For implementations that are not based on platform - * {@link AudioTrack}s, calling methods relating to audio sessions, audio attributes, and tunneling - * may have no effect. + * + *

Call {@link #configure(int, int, int, int, int[], int, int)} whenever the input format + * changes. The sink will be reinitialized on the next call to {@link #handleBuffer(ByteBuffer, + * long)}. + * + *

Call {@link #flush()} to prepare the sink to receive audio data from a new playback position. + * + *

Call {@link #playToEndOfStream()} repeatedly to play out all data when no more input buffers + * will be provided via {@link #handleBuffer(ByteBuffer, long)} until the next {@link #flush()}. + * Call {@link #reset()} when the instance is no longer required. + * + *

The implementation may be backed by a platform {@link AudioTrack}. In this case, {@link + * #setAudioSessionId(int)}, {@link #setAudioAttributes(AudioAttributes)}, {@link + * #enableTunnelingV21(int)} and/or {@link #disableTunneling()} may be called before writing data to + * the sink. These methods may also be called after writing data to the sink, in which case it will + * be reinitialized as required. For implementations that are not based on platform {@link + * AudioTrack}s, calling methods relating to audio sessions, audio attributes, and tunneling may + * have no effect. */ public interface AudioSink { @@ -197,7 +198,7 @@ public interface AudioSink { * @param trimStartFrames The number of audio frames to trim from the start of data written to the * sink after this call. * @param trimEndFrames The number of audio frames to trim from data written to the sink - * immediately preceding the next call to {@link #reset()} or this method. + * immediately preceding the next call to {@link #flush()} or this method. * @throws ConfigurationException If an error occurs configuring the sink. */ void configure( @@ -223,11 +224,11 @@ public interface AudioSink { * ending at its limit (exclusive). The position of the {@link ByteBuffer} is advanced by the * number of bytes that were handled. {@link Listener#onPositionDiscontinuity()} will be called if * {@code presentationTimeUs} is discontinuous with the last buffer handled since the last reset. - *

- * Returns whether the data was handled in full. If the data was not handled in full then the same - * {@link ByteBuffer} must be provided to subsequent calls until it has been fully consumed, - * except in the case of an intervening call to {@link #reset()} (or to - * {@link #configure(int, int, int, int, int[], int, int)} that causes the sink to be reset). + * + *

Returns whether the data was handled in full. If the data was not handled in full then the + * same {@link ByteBuffer} must be provided to subsequent calls until it has been fully consumed, + * except in the case of an intervening call to {@link #flush()} (or to {@link #configure(int, + * int, int, int, int[], int, int)} that causes the sink to be flushed). * * @param buffer The buffer containing audio data. * @param presentationTimeUs The presentation timestamp of the buffer in microseconds. @@ -316,15 +317,12 @@ public interface AudioSink { void pause(); /** - * Resets the sink, after which it is ready to receive buffers from a new playback position. - *

- * The audio session may remain active until {@link #release()} is called. + * Flushes the sink, after which it is ready to receive buffers from a new playback position. + * + *

The audio session may remain active until {@link #reset()} is called. */ + void flush(); + + /** Resets the renderer, releasing any resources that it currently holds. */ void reset(); - - /** - * Releases any resources associated with this instance. - */ - void release(); - } 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 d29659b102..7ba060ad76 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 @@ -463,7 +463,7 @@ public final class DefaultAudioSink implements AudioSink { return; } - reset(); + flush(); this.processingEnabled = processingEnabled; outputSampleRate = sampleRate; @@ -681,7 +681,7 @@ public final class DefaultAudioSink implements AudioSink { if (audioTrackPositionTracker.isStalled(getWrittenFrames())) { Log.w(TAG, "Resetting stalled audio track"); - reset(); + flush(); return true; } @@ -871,7 +871,7 @@ public final class DefaultAudioSink implements AudioSink { // The audio attributes are ignored in tunneling mode, so no need to reset. return; } - reset(); + flush(); audioSessionId = C.AUDIO_SESSION_ID_UNSET; } @@ -879,7 +879,7 @@ public final class DefaultAudioSink implements AudioSink { public void setAudioSessionId(int audioSessionId) { if (this.audioSessionId != audioSessionId) { this.audioSessionId = audioSessionId; - reset(); + flush(); } } @@ -907,7 +907,7 @@ public final class DefaultAudioSink implements AudioSink { if (!tunneling || audioSessionId != tunnelingAudioSessionId) { tunneling = true; audioSessionId = tunnelingAudioSessionId; - reset(); + flush(); } } @@ -916,7 +916,7 @@ public final class DefaultAudioSink implements AudioSink { if (tunneling) { tunneling = false; audioSessionId = C.AUDIO_SESSION_ID_UNSET; - reset(); + flush(); } } @@ -947,7 +947,7 @@ public final class DefaultAudioSink implements AudioSink { } @Override - public void reset() { + public void flush() { if (isInitialized()) { submittedPcmBytes = 0; submittedEncodedFrames = 0; @@ -995,8 +995,8 @@ public final class DefaultAudioSink implements AudioSink { } @Override - public void release() { - reset(); + public void reset() { + flush(); releaseKeepSessionIdAudioTrack(); for (AudioProcessor audioProcessor : toIntPcmAvailableAudioProcessors) { audioProcessor.reset(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java index c90b815347..dbc25c8d42 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java @@ -511,7 +511,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media @Override protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException { super.onPositionReset(positionUs, joining); - audioSink.reset(); + audioSink.flush(); currentPositionUs = positionUs; allowFirstBufferPositionDiscontinuity = true; allowPositionDiscontinuity = true; @@ -537,7 +537,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media try { lastInputTimeUs = C.TIME_UNSET; pendingStreamChangeCount = 0; - audioSink.release(); + audioSink.flush(); } finally { try { super.onDisabled(); @@ -548,6 +548,15 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media } } + @Override + protected void onReset() { + try { + super.onReset(); + } finally { + audioSink.reset(); + } + } + @Override public boolean isEnded() { return super.isEnded() && audioSink.isEnded(); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java index cecb17d96c..3df38e3557 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRenderer.java @@ -538,7 +538,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements @Override protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException { - audioSink.reset(); + audioSink.flush(); currentPositionUs = positionUs; allowFirstBufferPositionDiscontinuity = true; allowPositionDiscontinuity = true; @@ -567,7 +567,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements waitingForKeys = false; try { releaseDecoder(); - audioSink.release(); + audioSink.reset(); } finally { try { if (drmSession != null) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java index a896bc2322..29a75f06e5 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java @@ -361,18 +361,13 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { @Override protected void onDisabled() { - currentWidth = Format.NO_VALUE; - currentHeight = Format.NO_VALUE; - currentPixelWidthHeightRatio = Format.NO_VALUE; - pendingPixelWidthHeightRatio = Format.NO_VALUE; - outputStreamOffsetUs = C.TIME_UNSET; lastInputTimeUs = C.TIME_UNSET; + outputStreamOffsetUs = C.TIME_UNSET; pendingOutputStreamOffsetCount = 0; clearReportedVideoSize(); clearRenderedFirstFrame(); frameReleaseTimeHelper.disable(); tunnelingOnFrameRenderedListener = null; - tunneling = false; try { super.onDisabled(); } finally { diff --git a/library/core/src/test/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRendererTest.java b/library/core/src/test/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRendererTest.java index 48e71c619c..3f28999820 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRendererTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/audio/SimpleDecoderAudioRendererTest.java @@ -104,7 +104,7 @@ public class SimpleDecoderAudioRendererTest { verify(mockAudioSink, times(1)).playToEndOfStream(); audioRenderer.disable(); audioRenderer.reset(); - verify(mockAudioSink, times(1)).release(); + verify(mockAudioSink, times(1)).reset(); } private static final class FakeDecoder