Skip to content

Commit

Permalink
Retry creating a MediaCodec instance in MediaCodecRenderer
Browse files Browse the repository at this point in the history
It's been observed that some devices fail when releasing a secure codec
attached to a surface and immediately trying to create a new codec
(secure or insecure) attached to the same surface. This change catches
all exceptions thrown during codec creation, sleeps for a short time,
and then retries the codec creation. This is observed to fix the problem
(we believe this is because it allows enough time for some background
part of the previous codec release operation to complete).

This change should have no effect on the control flow when codec
creation succeeds first time. It will introduce a slight delay when
creating the preferred codec fails (while we sleep and retry), which
will either delay propagating a permanent error or attempting to
initialize a fallback decoder. We can't avoid the extra delay to
instantiating the fallback decoder because we can't know whether we
expect the second attempt to create the preferred decoder to succeed or
fail. The benefit to always retrying the preferred decoder creation
(fixing playback failures) outweighs the unfortunate additional delay
to instantiating fallback decoders.

Issue: google#8696
PiperOrigin-RevId: 414671743
  • Loading branch information
icbaker authored and fpitterstv2 committed Jan 12, 2022
1 parent 029a2b2 commit 187eed5
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 2 deletions.
7 changes: 7 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Release notes

### 2.16.1 - superfix

* Sleep and retry when creating a `MediaCodec` instance fails. This works
around an issue that occurs on some devices when switching a surface
from a secure codec to another codec
(#8696)[https://github.com/google/ExoPlayer/issues/8696].

### 2.16.1 (2021-11-18)

* Core Library:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -973,13 +973,27 @@ private void maybeInitCodecWithFallback(
DecoderInitializationException.NO_SUITABLE_DECODER_ERROR);
}

MediaCodecInfo preferredCodecInfo = availableCodecInfos.peekFirst();
while (codec == null) {
MediaCodecInfo codecInfo = availableCodecInfos.peekFirst();
if (!shouldInitCodec(codecInfo)) {
return;
}
try {
initCodec(codecInfo, crypto);
try {
initCodec(codecInfo, crypto);
} catch (Exception e) {
if (codecInfo == preferredCodecInfo) {
// If creating the preferred decoder failed then sleep briefly before retrying.
// Workaround for [internal b/191966399].
// See also https://github.com/google/ExoPlayer/issues/8696.
Log.w(TAG, "Preferred decoder instantiation failed. Sleeping for 50ms then retrying.");
Thread.sleep(/* millis= */ 50);
initCodec(codecInfo, crypto);
} else {
throw e;
}
}
} catch (Exception e) {
Log.w(TAG, "Failed to initialize decoder: " + codecInfo, e);
// This codec failed to initialize, so fall back to the next codec in the list (if any). We
Expand Down Expand Up @@ -1057,7 +1071,6 @@ private void initCodec(MediaCodecInfo codecInfo, MediaCrypto crypto) throws Exce
codecOperatingRate = CODEC_OPERATING_RATE_UNSET;
}
codecInitializingTimestamp = SystemClock.elapsedRealtime();
TraceUtil.beginSection("createCodec:" + codecName);
MediaCodecAdapter.Configuration configuration =
getMediaCodecConfiguration(codecInfo, inputFormat, crypto, codecOperatingRate);
codec = codecAdapterFactory.createAdapter(configuration);
Expand Down

0 comments on commit 187eed5

Please sign in to comment.