From 9046f2edb62f3dd9bc735405d2a58a98abd87064 Mon Sep 17 00:00:00 2001 From: michaelkatz Date: Thu, 22 Feb 2024 02:56:45 -0800 Subject: [PATCH] Allow renderer retry for audio track offload initialization failure If render error occurs due to AudioTrack initialization failure in offload mode, then ExoPlayer should allow retry as subsequent attempt will be with DefaultAudioSink disabling offload. PiperOrigin-RevId: 609304897 --- RELEASENOTES.md | 2 ++ .../java/androidx/media3/common/PlaybackException.java | 5 +++++ .../androidx/media3/exoplayer/ExoPlayerImplInternal.java | 1 + .../media3/exoplayer/audio/MediaCodecAudioRenderer.java | 8 +++++++- 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 77199435ca..d77693b562 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -17,6 +17,8 @@ * Track Selection: * Extractors: * Audio: + * Allow renderer recovery by disabling offload if audio track fails to + initialize in offload mode. * Video: * Text: * Metadata: diff --git a/libraries/common/src/main/java/androidx/media3/common/PlaybackException.java b/libraries/common/src/main/java/androidx/media3/common/PlaybackException.java index 8ebf665d39..5cdd8082f7 100644 --- a/libraries/common/src/main/java/androidx/media3/common/PlaybackException.java +++ b/libraries/common/src/main/java/androidx/media3/common/PlaybackException.java @@ -224,6 +224,9 @@ public class PlaybackException extends Exception implements Bundleable { /** Caused by an AudioTrack write operation failure in offload mode. */ @UnstableApi public static final int ERROR_CODE_AUDIO_TRACK_OFFLOAD_WRITE_FAILED = 5003; + /** Caused by an AudioTrack write operation failure in offload mode. */ + @UnstableApi public static final int ERROR_CODE_AUDIO_TRACK_OFFLOAD_INIT_FAILED = 5004; + // DRM errors (6xxx). /** Caused by an unspecified error related to DRM protection. */ @@ -330,6 +333,8 @@ public class PlaybackException extends Exception implements Bundleable { return "ERROR_CODE_AUDIO_TRACK_WRITE_FAILED"; case ERROR_CODE_AUDIO_TRACK_OFFLOAD_WRITE_FAILED: return "ERROR_CODE_AUDIO_TRACK_OFFLOAD_WRITE_FAILED"; + case ERROR_CODE_AUDIO_TRACK_OFFLOAD_INIT_FAILED: + return "ERROR_CODE_AUDIO_TRACK_OFFLOAD_INIT_FAILED"; case ERROR_CODE_DRM_UNSPECIFIED: return "ERROR_CODE_DRM_UNSPECIFIED"; case ERROR_CODE_DRM_SCHEME_UNSUPPORTED: diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java index 6d472853a8..f010a96606 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImplInternal.java @@ -622,6 +622,7 @@ import java.util.concurrent.atomic.AtomicBoolean; } if (e.isRecoverable && (pendingRecoverableRendererError == null + || e.errorCode == PlaybackException.ERROR_CODE_AUDIO_TRACK_OFFLOAD_INIT_FAILED || e.errorCode == PlaybackException.ERROR_CODE_AUDIO_TRACK_OFFLOAD_WRITE_FAILED)) { // If pendingRecoverableRendererError != null and error was // ERROR_CODE_AUDIO_TRACK_OFFLOAD_WRITE_FAILED then upon retry, renderer will attempt with diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java index 4a861e45e5..0c0765ea49 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/MediaCodecAudioRenderer.java @@ -743,7 +743,13 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media fullyConsumed = audioSink.handleBuffer(buffer, bufferPresentationTimeUs, sampleCount); } catch (InitializationException e) { throw createRendererException( - e, inputFormat, e.isRecoverable, PlaybackException.ERROR_CODE_AUDIO_TRACK_INIT_FAILED); + e, + inputFormat, + e.isRecoverable, + isBypassEnabled() + && getConfiguration().offloadModePreferred != AudioSink.OFFLOAD_MODE_DISABLED + ? PlaybackException.ERROR_CODE_AUDIO_TRACK_OFFLOAD_INIT_FAILED + : PlaybackException.ERROR_CODE_AUDIO_TRACK_INIT_FAILED); } catch (WriteException e) { throw createRendererException( e,