mirror of
https://github.com/androidx/media.git
synced 2025-05-08 08:00:49 +08:00
DRM: Pass sessionId rather than MediaCrypto
ExoMediaCrypto.requiresSecureDecoderComponent() is removed, and FrameworkMediaCrypto.forceAllowInsecureDecoderComponents is made public to allow determining whether a secure decoder is required to be implemented in MediaCodecRenderer. PiperOrigin-RevId: 228909771
This commit is contained in:
parent
2d30d66746
commit
1f03093dc5
@ -15,14 +15,5 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.drm;
|
package com.google.android.exoplayer2.drm;
|
||||||
|
|
||||||
/**
|
/** An opaque {@link android.media.MediaCrypto} equivalent. */
|
||||||
* An opaque {@link android.media.MediaCrypto} equivalent.
|
public interface ExoMediaCrypto {}
|
||||||
*/
|
|
||||||
public interface ExoMediaCrypto {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see android.media.MediaCrypto#requiresSecureDecoderComponent(String)
|
|
||||||
*/
|
|
||||||
boolean requiresSecureDecoderComponent(String mimeType);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -265,11 +265,9 @@ public interface ExoMediaDrm<T extends ExoMediaCrypto> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @see android.media.MediaCrypto#MediaCrypto(UUID, byte[])
|
* @see android.media.MediaCrypto#MediaCrypto(UUID, byte[])
|
||||||
*
|
* @param sessionId The DRM session ID.
|
||||||
* @param initData Opaque initialization data specific to the crypto scheme.
|
|
||||||
* @return An object extends {@link ExoMediaCrypto}, using opaque crypto scheme specific data.
|
* @return An object extends {@link ExoMediaCrypto}, using opaque crypto scheme specific data.
|
||||||
* @throws MediaCryptoException If the instance can't be created.
|
* @throws MediaCryptoException If the instance can't be created.
|
||||||
*/
|
*/
|
||||||
T createMediaCrypto(byte[] initData) throws MediaCryptoException;
|
T createMediaCrypto(byte[] sessionId) throws MediaCryptoException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,48 +17,35 @@ package com.google.android.exoplayer2.drm;
|
|||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.media.MediaCrypto;
|
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)
|
@TargetApi(16)
|
||||||
public final class FrameworkMediaCrypto implements ExoMediaCrypto {
|
public final class FrameworkMediaCrypto implements ExoMediaCrypto {
|
||||||
|
|
||||||
private final MediaCrypto mediaCrypto;
|
/** The DRM scheme UUID. */
|
||||||
private final boolean forceAllowInsecureDecoderComponents;
|
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) {
|
public FrameworkMediaCrypto(
|
||||||
this(mediaCrypto, false);
|
UUID uuid, byte[] sessionId, boolean forceAllowInsecureDecoderComponents) {
|
||||||
}
|
this.uuid = uuid;
|
||||||
|
this.sessionId = sessionId;
|
||||||
/**
|
|
||||||
* @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);
|
|
||||||
this.forceAllowInsecureDecoderComponents = forceAllowInsecureDecoderComponents;
|
this.forceAllowInsecureDecoderComponents = forceAllowInsecureDecoderComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the wrapped {@link MediaCrypto}.
|
|
||||||
*/
|
|
||||||
public MediaCrypto getWrappedMediaCrypto() {
|
|
||||||
return mediaCrypto;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean requiresSecureDecoderComponent(String mimeType) {
|
|
||||||
return !forceAllowInsecureDecoderComponents
|
|
||||||
&& mediaCrypto.requiresSecureDecoderComponent(mimeType);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ package com.google.android.exoplayer2.drm;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.media.DeniedByServerException;
|
import android.media.DeniedByServerException;
|
||||||
import android.media.MediaCrypto;
|
|
||||||
import android.media.MediaCryptoException;
|
import android.media.MediaCryptoException;
|
||||||
import android.media.MediaDrm;
|
import android.media.MediaDrm;
|
||||||
import android.media.MediaDrmException;
|
import android.media.MediaDrmException;
|
||||||
@ -210,7 +209,7 @@ public final class FrameworkMediaDrm implements ExoMediaDrm<FrameworkMediaCrypto
|
|||||||
boolean forceAllowInsecureDecoderComponents = Util.SDK_INT < 21
|
boolean forceAllowInsecureDecoderComponents = Util.SDK_INT < 21
|
||||||
&& C.WIDEVINE_UUID.equals(uuid) && "L3".equals(getPropertyString("securityLevel"));
|
&& C.WIDEVINE_UUID.equals(uuid) && "L3".equals(getPropertyString("securityLevel"));
|
||||||
return new FrameworkMediaCrypto(
|
return new FrameworkMediaCrypto(
|
||||||
new MediaCrypto(adjustUuid(uuid), initData), forceAllowInsecureDecoderComponents);
|
adjustUuid(uuid), initData, forceAllowInsecureDecoderComponents);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SchemeData getSchemeData(UUID uuid, List<SchemeData> schemeDatas) {
|
private static SchemeData getSchemeData(UUID uuid, List<SchemeData> schemeDatas) {
|
||||||
|
@ -20,6 +20,7 @@ import android.media.MediaCodec;
|
|||||||
import android.media.MediaCodec.CodecException;
|
import android.media.MediaCodec.CodecException;
|
||||||
import android.media.MediaCodec.CryptoException;
|
import android.media.MediaCodec.CryptoException;
|
||||||
import android.media.MediaCrypto;
|
import android.media.MediaCrypto;
|
||||||
|
import android.media.MediaCryptoException;
|
||||||
import android.media.MediaFormat;
|
import android.media.MediaFormat;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@ -294,6 +295,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
private Format outputFormat;
|
private Format outputFormat;
|
||||||
@Nullable private DrmSession<FrameworkMediaCrypto> codecDrmSession;
|
@Nullable private DrmSession<FrameworkMediaCrypto> codecDrmSession;
|
||||||
@Nullable private DrmSession<FrameworkMediaCrypto> sourceDrmSession;
|
@Nullable private DrmSession<FrameworkMediaCrypto> sourceDrmSession;
|
||||||
|
@Nullable private MediaCrypto mediaCrypto;
|
||||||
|
private boolean drmSessionRequiresSecureDecoder;
|
||||||
private long renderTimeLimitMs;
|
private long renderTimeLimitMs;
|
||||||
private float rendererOperatingRate;
|
private float rendererOperatingRate;
|
||||||
@Nullable private MediaCodec codec;
|
@Nullable private MediaCodec codec;
|
||||||
@ -460,22 +463,28 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
setCodecDrmSession(sourceDrmSession);
|
setCodecDrmSession(sourceDrmSession);
|
||||||
|
|
||||||
String mimeType = inputFormat.sampleMimeType;
|
String mimeType = inputFormat.sampleMimeType;
|
||||||
MediaCrypto wrappedMediaCrypto = null;
|
|
||||||
boolean drmSessionRequiresSecureDecoder = false;
|
|
||||||
if (codecDrmSession != null) {
|
if (codecDrmSession != null) {
|
||||||
FrameworkMediaCrypto mediaCrypto = codecDrmSession.getMediaCrypto();
|
|
||||||
if (mediaCrypto == null) {
|
if (mediaCrypto == null) {
|
||||||
DrmSessionException drmError = codecDrmSession.getError();
|
FrameworkMediaCrypto sessionMediaCrypto = codecDrmSession.getMediaCrypto();
|
||||||
if (drmError != null) {
|
if (sessionMediaCrypto == null) {
|
||||||
// Continue for now. We may be able to avoid failure if the session recovers, or if a new
|
DrmSessionException drmError = codecDrmSession.getError();
|
||||||
// input format causes the session to be replaced before it's used.
|
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 {
|
} else {
|
||||||
// The drm session isn't open yet.
|
try {
|
||||||
return;
|
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()) {
|
if (deviceNeedsDrmKeysToConfigureCodecWorkaround()) {
|
||||||
@DrmSession.State int drmSessionState = codecDrmSession.getState();
|
@DrmSession.State int drmSessionState = codecDrmSession.getState();
|
||||||
@ -489,7 +498,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
maybeInitCodecWithFallback(wrappedMediaCrypto, drmSessionRequiresSecureDecoder);
|
maybeInitCodecWithFallback(mediaCrypto, drmSessionRequiresSecureDecoder);
|
||||||
} catch (DecoderInitializationException e) {
|
} catch (DecoderInitializationException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
||||||
}
|
}
|
||||||
@ -553,7 +562,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
@Override
|
@Override
|
||||||
protected void onDisabled() {
|
protected void onDisabled() {
|
||||||
inputFormat = null;
|
inputFormat = null;
|
||||||
if (codecDrmSession != null || sourceDrmSession != null) {
|
if (sourceDrmSession != null || codecDrmSession != null) {
|
||||||
// TODO: Do something better with this case.
|
// TODO: Do something better with this case.
|
||||||
onReset();
|
onReset();
|
||||||
} else {
|
} else {
|
||||||
@ -591,7 +600,14 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
codec = null;
|
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<FrameworkMediaCrypto> session) {
|
private void releaseDrmSessionIfUnused(@Nullable DrmSession<FrameworkMediaCrypto> session) {
|
||||||
if (session != null && session != codecDrmSession && session != sourceDrmSession) {
|
if (session != null && session != sourceDrmSession && session != codecDrmSession) {
|
||||||
drmSessionManager.releaseSession(session);
|
drmSessionManager.releaseSession(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1128,7 +1144,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
}
|
}
|
||||||
DrmSession<FrameworkMediaCrypto> session =
|
DrmSession<FrameworkMediaCrypto> session =
|
||||||
drmSessionManager.acquireSession(Looper.myLooper(), newFormat.drmInitData);
|
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
|
// 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.
|
// to get the count attributed to this renderer back down to 1.
|
||||||
drmSessionManager.releaseSession(session);
|
drmSessionManager.releaseSession(session);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user