mirror of
https://github.com/androidx/media.git
synced 2025-05-07 15:40:37 +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;
|
||||
|
||||
/**
|
||||
* 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 {}
|
||||
|
@ -265,11 +265,9 @@ public interface ExoMediaDrm<T extends ExoMediaCrypto> {
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<FrameworkMediaCrypto
|
||||
boolean forceAllowInsecureDecoderComponents = Util.SDK_INT < 21
|
||||
&& C.WIDEVINE_UUID.equals(uuid) && "L3".equals(getPropertyString("securityLevel"));
|
||||
return new FrameworkMediaCrypto(
|
||||
new MediaCrypto(adjustUuid(uuid), initData), forceAllowInsecureDecoderComponents);
|
||||
adjustUuid(uuid), initData, forceAllowInsecureDecoderComponents);
|
||||
}
|
||||
|
||||
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.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<FrameworkMediaCrypto> codecDrmSession;
|
||||
@Nullable private DrmSession<FrameworkMediaCrypto> 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<FrameworkMediaCrypto> 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<FrameworkMediaCrypto> 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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user