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 05a1cd4f2db..c702bc6dd6d 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 @@ -29,7 +29,6 @@ import android.media.AudioTrack; import android.media.PlaybackParams; import android.media.metrics.LogSessionId; -import android.os.ConditionVariable; import android.os.Handler; import android.os.SystemClock; import android.util.Pair; @@ -43,6 +42,8 @@ import com.google.android.exoplayer2.analytics.PlayerId; import com.google.android.exoplayer2.audio.AudioProcessor.UnhandledAudioFormatException; import com.google.android.exoplayer2.util.Assertions; +import com.google.android.exoplayer2.util.Clock; +import com.google.android.exoplayer2.util.ConditionVariable; import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; @@ -606,7 +607,8 @@ private DefaultAudioSink(Builder builder) { enableAudioTrackPlaybackParams = Util.SDK_INT >= 23 && builder.enableAudioTrackPlaybackParams; offloadMode = Util.SDK_INT >= 29 ? builder.offloadMode : OFFLOAD_MODE_DISABLED; audioTrackBufferSizeProvider = builder.audioTrackBufferSizeProvider; - releasingConditionVariable = new ConditionVariable(true); + releasingConditionVariable = new ConditionVariable(Clock.DEFAULT); + releasingConditionVariable.open(); audioTrackPositionTracker = new AudioTrackPositionTracker(new PositionTrackerListener()); channelMappingAudioProcessor = new ChannelMappingAudioProcessor(); trimmingAudioProcessor = new TrimmingAudioProcessor(); @@ -831,13 +833,15 @@ private void flushAudioProcessors() { } } - private void initializeAudioTrack() throws InitializationException { - // If we're asynchronously releasing a previous audio track then we block until it has been + private boolean initializeAudioTrack() throws InitializationException { + // If we're asynchronously releasing a previous audio track then we wait until it has been // released. This guarantees that we cannot end up in a state where we have multiple audio // track instances. Without this guarantee it would be possible, in extreme cases, to exhaust // the shared memory that's available for audio track buffers. This would in turn cause the // initialization of the audio track to fail. - releasingConditionVariable.block(); + if (!releasingConditionVariable.isOpen()) { + return false; + } audioTrack = buildAudioTrackWithRetry(); if (isOffloadedPlayback(audioTrack)) { @@ -865,6 +869,7 @@ private void initializeAudioTrack() throws InitializationException { } startMediaTimeUsNeedsInit = true; + return true; } @Override @@ -921,7 +926,10 @@ public boolean handleBuffer( if (!isAudioTrackInitialized()) { try { - initializeAudioTrack(); + if (!initializeAudioTrack()) { + // Not yet ready for initialization of a new AudioTrack. + return false; + } } catch (InitializationException e) { if (e.isRecoverable) { throw e; // Do not delay the exception if it can be recovered at higher level.