diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/FrameworkCryptoConfig.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/FrameworkCryptoConfig.java index ee66d07b0a2..4766202a8be 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/FrameworkCryptoConfig.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/FrameworkCryptoConfig.java @@ -47,10 +47,10 @@ public final class FrameworkCryptoConfig implements CryptoConfig { public final byte[] sessionId; /** - * Whether to allow use of insecure decoder components even if the underlying platform says - * otherwise. + * @deprecated Use {@link ExoMediaDrm#requiresSecureDecoder} instead, which incorporates this + * logic. */ - public final boolean forceAllowInsecureDecoderComponents; + @Deprecated public final boolean forceAllowInsecureDecoderComponents; /** * @param uuid The DRM scheme UUID. @@ -58,6 +58,7 @@ public final class FrameworkCryptoConfig implements CryptoConfig { * @param forceAllowInsecureDecoderComponents Whether to allow use of insecure decoder components * even if the underlying platform says otherwise. */ + @SuppressWarnings("deprecation") // Setting deprecated field public FrameworkCryptoConfig( UUID uuid, byte[] sessionId, boolean forceAllowInsecureDecoderComponents) { this.uuid = uuid; diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/FrameworkMediaDrm.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/FrameworkMediaDrm.java index d0a5e48e87f..da3fa692105 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/FrameworkMediaDrm.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/drm/FrameworkMediaDrm.java @@ -287,22 +287,24 @@ public Map queryKeyStatus(byte[] sessionId) { @UnstableApi @Override public boolean requiresSecureDecoder(byte[] sessionId, String mimeType) { + boolean result; if (Util.SDK_INT >= 31) { - return Api31.requiresSecureDecoder(mediaDrm, mimeType); - } - - MediaCrypto mediaCrypto; - try { - mediaCrypto = new MediaCrypto(uuid, sessionId); - } catch (MediaCryptoException e) { - // This shouldn't happen, but if it does then assume that a secure decoder may be required. - return true; - } - try { - return mediaCrypto.requiresSecureDecoderComponent(mimeType); - } finally { - mediaCrypto.release(); + result = Api31.requiresSecureDecoder(mediaDrm, mimeType); + } else { + MediaCrypto mediaCrypto = null; + try { + mediaCrypto = new MediaCrypto(uuid, sessionId); + result = mediaCrypto.requiresSecureDecoderComponent(mimeType); + } catch (MediaCryptoException e) { + // This shouldn't happen, but if it does then assume that a secure decoder may be required. + result = true; + } finally { + if (mediaCrypto != null) { + mediaCrypto.release(); + } + } } + return result && !shouldForceAllowInsecureDecoderComponents(); } @UnstableApi @@ -383,16 +385,19 @@ public void setPropertyByteArray(String propertyName, byte[] value) { @UnstableApi @Override public FrameworkCryptoConfig createCryptoConfig(byte[] sessionId) throws MediaCryptoException { - // Work around a bug prior to Lollipop where L1 Widevine forced into L3 mode would still - // indicate that it required secure video decoders [Internal ref: b/11428937]. - boolean forceAllowInsecureDecoderComponents = - Util.SDK_INT < 21 - && C.WIDEVINE_UUID.equals(uuid) - && "L3".equals(getPropertyString("securityLevel")); + boolean forceAllowInsecureDecoderComponents = shouldForceAllowInsecureDecoderComponents(); return new FrameworkCryptoConfig( adjustUuid(uuid), sessionId, forceAllowInsecureDecoderComponents); } + // Work around a bug prior to Lollipop where L1 Widevine forced into L3 mode would still + // indicate that it required secure video decoders [Internal ref: b/11428937]. + private boolean shouldForceAllowInsecureDecoderComponents() { + return Util.SDK_INT < 21 + && C.WIDEVINE_UUID.equals(uuid) + && "L3".equals(getPropertyString("securityLevel")); + } + @UnstableApi @Override public @C.CryptoType int getCryptoType() { diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecRenderer.java index 7225ad0deb2..a0efd57c2f5 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecRenderer.java @@ -360,7 +360,6 @@ private static String buildCustomDiagnosticInfo(int errorCode) { */ @Nullable private MediaCrypto mediaCrypto; - private boolean mediaCryptoRequiresSecureDecoder; private long renderTimeLimitMs; private float currentPlaybackSpeed; private float targetPlaybackSpeed; @@ -539,6 +538,7 @@ protected final void maybeInitCodecOrBypass() throws ExoPlaybackException { // We have a codec, are bypassing it, or don't have a format to decide how to render. return; } + Format inputFormat = this.inputFormat; if (isBypassPossible(inputFormat)) { initBypass(inputFormat); @@ -548,6 +548,10 @@ protected final void maybeInitCodecOrBypass() throws ExoPlaybackException { setCodecDrmSession(sourceDrmSession); if (codecDrmSession == null || initMediaCryptoIfDrmSessionReady()) { try { + boolean mediaCryptoRequiresSecureDecoder = + codecDrmSession != null + && codecDrmSession.requiresSecureDecoder( + checkStateNotNull(inputFormat.sampleMimeType)); maybeInitCodecWithFallback(mediaCrypto, mediaCryptoRequiresSecureDecoder); } catch (DecoderInitializationException e) { throw createRendererException( @@ -558,7 +562,6 @@ protected final void maybeInitCodecOrBypass() throws ExoPlaybackException { // mediaCrypto was created, but a codec wasn't, so release the mediaCrypto before returning. mediaCrypto.release(); mediaCrypto = null; - mediaCryptoRequiresSecureDecoder = false; } } @@ -968,7 +971,6 @@ protected void resetCodecStateForRelease() { codecNeedsEosPropagation = false; codecReconfigured = false; codecReconfigurationState = RECONFIGURATION_STATE_NONE; - mediaCryptoRequiresSecureDecoder = false; } protected MediaCodecDecoderException createDecoderException( @@ -1011,7 +1013,6 @@ private boolean readSourceOmittingSampleData(@SampleStream.ReadFlags int readFla private boolean initMediaCryptoIfDrmSessionReady() throws ExoPlaybackException { checkState(mediaCrypto == null); DrmSession codecDrmSession = this.codecDrmSession; - String mimeType = checkNotNull(inputFormat).sampleMimeType; @Nullable CryptoConfig cryptoConfig = codecDrmSession.getCryptoConfig(); if (FrameworkCryptoConfig.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC && cryptoConfig instanceof FrameworkCryptoConfig) { @@ -1044,9 +1045,6 @@ private boolean initMediaCryptoIfDrmSessionReady() throws ExoPlaybackException { throw createRendererException( e, inputFormat, PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR); } - mediaCryptoRequiresSecureDecoder = - !frameworkCryptoConfig.forceAllowInsecureDecoderComponents - && mediaCrypto.requiresSecureDecoderComponent(checkStateNotNull(mimeType)); } return true; } @@ -2228,8 +2226,6 @@ private boolean drmNeedsCodecReinitialization( return false; } - FrameworkCryptoConfig newFrameworkCryptoConfig = (FrameworkCryptoConfig) newCryptoConfig; - // Note: Both oldSession and newSession are non-null, and they are different sessions. if (!newSession.getSchemeUuid().equals(oldSession.getSchemeUuid())) { @@ -2250,20 +2246,10 @@ private boolean drmNeedsCodecReinitialization( return true; } - boolean requiresSecureDecoder; - if (newFrameworkCryptoConfig.forceAllowInsecureDecoderComponents) { - requiresSecureDecoder = false; - } else { - requiresSecureDecoder = - newSession.requiresSecureDecoder(checkNotNull(newFormat.sampleMimeType)); - } - if (!codecInfo.secure && requiresSecureDecoder) { - // Re-initialization is required because newSession might require switching to the secure - // output path. - return true; - } - - return false; + // Re-initialization is required if newSession might require switching to the secure output + // path. + return !codecInfo.secure + && newSession.requiresSecureDecoder(checkNotNull(newFormat.sampleMimeType)); } private void reinitializeCodec() throws ExoPlaybackException {