diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaCrypto.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaCrypto.java index d5a4f6add5..feba7eaaf4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaCrypto.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaCrypto.java @@ -15,14 +15,5 @@ */ package com.google.android.exoplayer2.drm; -/** - * An opaque {@link android.media.MediaCrypto} equivalent. - */ -public interface ExoMediaCrypto { - - /** - * @see android.media.MediaCrypto#requiresSecureDecoderComponent(String) - */ - boolean requiresSecureDecoderComponent(String mimeType); - -} +/** An opaque {@link android.media.MediaCrypto} equivalent. */ +public interface ExoMediaCrypto {} diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java index 24c3ddbbd0..aca56139de 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java @@ -265,11 +265,9 @@ public interface ExoMediaDrm { /** * @see android.media.MediaCrypto#MediaCrypto(UUID, byte[]) - * - * @param initData Opaque initialization data specific to the crypto scheme. + * @param sessionId The DRM session ID. * @return An object extends {@link ExoMediaCrypto}, using opaque crypto scheme specific data. * @throws MediaCryptoException If the instance can't be created. */ - T createMediaCrypto(byte[] initData) throws MediaCryptoException; - + T createMediaCrypto(byte[] sessionId) throws MediaCryptoException; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaCrypto.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaCrypto.java index 4e58ed6a31..156138ab9b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaCrypto.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaCrypto.java @@ -17,48 +17,35 @@ package com.google.android.exoplayer2.drm; import android.annotation.TargetApi; import android.media.MediaCrypto; -import com.google.android.exoplayer2.util.Assertions; +import java.util.UUID; /** - * An {@link ExoMediaCrypto} implementation that wraps the framework {@link MediaCrypto}. + * An {@link ExoMediaCrypto} implementation that contains the necessary information to build or + * update a framework {@link MediaCrypto}. */ @TargetApi(16) public final class FrameworkMediaCrypto implements ExoMediaCrypto { - private final MediaCrypto mediaCrypto; - private final boolean forceAllowInsecureDecoderComponents; + /** The DRM scheme UUID. */ + public final UUID uuid; + /** The DRM session id. */ + public final byte[] sessionId; + /** + * Whether to allow use of insecure decoder components even if the underlying platform says + * otherwise. + */ + public final boolean forceAllowInsecureDecoderComponents; /** - * @param mediaCrypto The {@link MediaCrypto} to wrap. + * @param uuid The DRM scheme UUID. + * @param sessionId The DRM session id. + * @param forceAllowInsecureDecoderComponents Whether to allow use of insecure decoder components + * even if the underlying platform says otherwise. */ - public FrameworkMediaCrypto(MediaCrypto mediaCrypto) { - this(mediaCrypto, false); - } - - /** - * @param mediaCrypto The {@link MediaCrypto} to wrap. - * @param forceAllowInsecureDecoderComponents Whether to force - * {@link #requiresSecureDecoderComponent(String)} to return {@code false}, rather than - * {@link MediaCrypto#requiresSecureDecoderComponent(String)} of the wrapped - * {@link MediaCrypto}. - */ - public FrameworkMediaCrypto(MediaCrypto mediaCrypto, - boolean forceAllowInsecureDecoderComponents) { - this.mediaCrypto = Assertions.checkNotNull(mediaCrypto); + public FrameworkMediaCrypto( + UUID uuid, byte[] sessionId, boolean forceAllowInsecureDecoderComponents) { + this.uuid = uuid; + this.sessionId = sessionId; this.forceAllowInsecureDecoderComponents = forceAllowInsecureDecoderComponents; } - - /** - * Returns the wrapped {@link MediaCrypto}. - */ - public MediaCrypto getWrappedMediaCrypto() { - return mediaCrypto; - } - - @Override - public boolean requiresSecureDecoderComponent(String mimeType) { - return !forceAllowInsecureDecoderComponents - && mediaCrypto.requiresSecureDecoderComponent(mimeType); - } - } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java index fda85a759c..b139288f98 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java @@ -18,7 +18,6 @@ package com.google.android.exoplayer2.drm; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.media.DeniedByServerException; -import android.media.MediaCrypto; import android.media.MediaCryptoException; import android.media.MediaDrm; import android.media.MediaDrmException; @@ -210,7 +209,7 @@ public final class FrameworkMediaDrm implements ExoMediaDrm schemeDatas) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java index a538bca4b2..4736811841 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java @@ -20,6 +20,7 @@ import android.media.MediaCodec; import android.media.MediaCodec.CodecException; import android.media.MediaCodec.CryptoException; import android.media.MediaCrypto; +import android.media.MediaCryptoException; import android.media.MediaFormat; import android.os.Bundle; import android.os.Looper; @@ -294,6 +295,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer { private Format outputFormat; @Nullable private DrmSession codecDrmSession; @Nullable private DrmSession sourceDrmSession; + @Nullable private MediaCrypto mediaCrypto; + private boolean drmSessionRequiresSecureDecoder; private long renderTimeLimitMs; private float rendererOperatingRate; @Nullable private MediaCodec codec; @@ -460,22 +463,28 @@ public abstract class MediaCodecRenderer extends BaseRenderer { setCodecDrmSession(sourceDrmSession); String mimeType = inputFormat.sampleMimeType; - MediaCrypto wrappedMediaCrypto = null; - boolean drmSessionRequiresSecureDecoder = false; if (codecDrmSession != null) { - FrameworkMediaCrypto mediaCrypto = codecDrmSession.getMediaCrypto(); if (mediaCrypto == null) { - DrmSessionException drmError = codecDrmSession.getError(); - if (drmError != null) { - // Continue for now. We may be able to avoid failure if the session recovers, or if a new - // input format causes the session to be replaced before it's used. + FrameworkMediaCrypto sessionMediaCrypto = codecDrmSession.getMediaCrypto(); + if (sessionMediaCrypto == null) { + DrmSessionException drmError = codecDrmSession.getError(); + if (drmError != null) { + // Continue for now. We may be able to avoid failure if the session recovers, or if a + // new input format causes the session to be replaced before it's used. + } else { + // The drm session isn't open yet. + return; + } } else { - // The drm session isn't open yet. - return; + try { + mediaCrypto = new MediaCrypto(sessionMediaCrypto.uuid, sessionMediaCrypto.sessionId); + } catch (MediaCryptoException e) { + throw ExoPlaybackException.createForRenderer(e, getIndex()); + } + drmSessionRequiresSecureDecoder = + !sessionMediaCrypto.forceAllowInsecureDecoderComponents + && mediaCrypto.requiresSecureDecoderComponent(mimeType); } - } else { - wrappedMediaCrypto = mediaCrypto.getWrappedMediaCrypto(); - drmSessionRequiresSecureDecoder = mediaCrypto.requiresSecureDecoderComponent(mimeType); } if (deviceNeedsDrmKeysToConfigureCodecWorkaround()) { @DrmSession.State int drmSessionState = codecDrmSession.getState(); @@ -489,7 +498,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { } try { - maybeInitCodecWithFallback(wrappedMediaCrypto, drmSessionRequiresSecureDecoder); + maybeInitCodecWithFallback(mediaCrypto, drmSessionRequiresSecureDecoder); } catch (DecoderInitializationException e) { throw ExoPlaybackException.createForRenderer(e, getIndex()); } @@ -553,7 +562,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { @Override protected void onDisabled() { inputFormat = null; - if (codecDrmSession != null || sourceDrmSession != null) { + if (sourceDrmSession != null || codecDrmSession != null) { // TODO: Do something better with this case. onReset(); } else { @@ -591,7 +600,14 @@ public abstract class MediaCodecRenderer extends BaseRenderer { } } finally { codec = null; - setCodecDrmSession(null); + try { + if (mediaCrypto != null) { + mediaCrypto.release(); + } + } finally { + mediaCrypto = null; + setCodecDrmSession(null); + } } } @@ -923,7 +939,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { } private void releaseDrmSessionIfUnused(@Nullable DrmSession session) { - if (session != null && session != codecDrmSession && session != sourceDrmSession) { + if (session != null && session != sourceDrmSession && session != codecDrmSession) { drmSessionManager.releaseSession(session); } } @@ -1128,7 +1144,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { } DrmSession session = drmSessionManager.acquireSession(Looper.myLooper(), newFormat.drmInitData); - if (session == codecDrmSession || session == sourceDrmSession) { + if (session == sourceDrmSession || session == codecDrmSession) { // We already had this session. The manager must be reference counting, so release it once // to get the count attributed to this renderer back down to 1. drmSessionManager.releaseSession(session);