mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Use MediaCodec.stop()
before release()
for surface switching bug
ExoPlayer used to call `stop()` before `release()`. This was removed in <unknown commit>. A framework bug introduced in Android 11 (API 30) resulted in some DRM -> clear transitions failing during `MediaCodec.configure()`. An investigation in Issue: google/ExoPlayer#8696 and b/191966399 identified that this was due to `release()` returning 'too early' and the subsequent `configure()` call was then trying to re-use a `Surface` that hadn't been fully detached from the previous codec. This was fixed in Android 13 (API 33) with http://r.android.com/2094347. ExoPlayer worked around the framework bug by adding an arbitrary 50ms sleep after a failed codec initialization, followed by retrying. This was enough to resolve the problem in the test scenario on a OnePlus AC2003. Issue: androidx/media#1497 points out that 50ms might not be the appropriate delay for all devices, so it's an incomplete fix. They suggested re-adding the `MediaCodec.stop()` call instead. This also reliably resolves the issue on the OnePlus AC2003 (with neither workaround in place, the problem repros almost immediately). PiperOrigin-RevId: 646461943
This commit is contained in:
parent
73bf852405
commit
5fcc7433a1
@ -259,11 +259,21 @@ import java.nio.ByteBuffer;
|
||||
state = STATE_SHUT_DOWN;
|
||||
} finally {
|
||||
if (!codecReleased) {
|
||||
try {
|
||||
// Stopping the codec before releasing it works around a bug on APIs 30, 31 and 32 where
|
||||
// MediaCodec.release() returns too early before fully detaching a Surface, and a
|
||||
// subsequent MediaCodec.configure() call using the same Surface then fails. See
|
||||
// https://github.com/google/ExoPlayer/issues/8696 and b/191966399.
|
||||
if (Util.SDK_INT >= 30 && Util.SDK_INT < 33) {
|
||||
codec.stop();
|
||||
}
|
||||
} finally {
|
||||
codec.release();
|
||||
codecReleased = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnFrameRenderedListener(OnFrameRenderedListener listener, Handler handler) {
|
||||
|
@ -1128,27 +1128,13 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
}
|
||||
|
||||
ArrayDeque<MediaCodecInfo> availableCodecInfos = checkNotNull(this.availableCodecInfos);
|
||||
MediaCodecInfo preferredCodecInfo = availableCodecInfos.peekFirst();
|
||||
while (codec == null) {
|
||||
MediaCodecInfo codecInfo = checkNotNull(availableCodecInfos.peekFirst());
|
||||
if (!shouldInitCodec(codecInfo)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
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
|
||||
|
@ -172,8 +172,18 @@ public final class SynchronousMediaCodecAdapter implements MediaCodecAdapter {
|
||||
public void release() {
|
||||
inputByteBuffers = null;
|
||||
outputByteBuffers = null;
|
||||
try {
|
||||
if (Util.SDK_INT >= 30 && Util.SDK_INT < 33) {
|
||||
// Stopping the codec before releasing it works around a bug on APIs 30, 31 and 32 where
|
||||
// MediaCodec.release() returns too early before fully detaching a Surface, and a
|
||||
// subsequent MediaCodec.configure() call using the same Surface then fails. See
|
||||
// https://github.com/google/ExoPlayer/issues/8696 and b/191966399.
|
||||
codec.stop();
|
||||
}
|
||||
} finally {
|
||||
codec.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@RequiresApi(23)
|
||||
|
Loading…
x
Reference in New Issue
Block a user