DRM refactor / cleanup

PiperOrigin-RevId: 391403236
This commit is contained in:
olly 2021-08-18 00:28:53 +01:00 committed by bachinger
parent cd297b048a
commit 85142be9a4
40 changed files with 274 additions and 246 deletions

View File

@ -23,8 +23,8 @@ import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.decoder.DecoderReuseEvaluation; import com.google.android.exoplayer2.decoder.DecoderReuseEvaluation;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.TraceUtil; import com.google.android.exoplayer2.util.TraceUtil;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
@ -132,7 +132,7 @@ public class Libgav1VideoRenderer extends DecoderVideoRenderer {
|| !Gav1Library.isAvailable()) { || !Gav1Library.isAvailable()) {
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE); return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE);
} }
if (format.exoMediaCryptoType != null) { if (format.cryptoType != C.CRYPTO_TYPE_NONE) {
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_DRM); return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_DRM);
} }
return RendererCapabilities.create( return RendererCapabilities.create(
@ -140,7 +140,7 @@ public class Libgav1VideoRenderer extends DecoderVideoRenderer {
} }
@Override @Override
protected Gav1Decoder createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) protected Gav1Decoder createDecoder(Format format, @Nullable CryptoConfig cryptoConfig)
throws Gav1DecoderException { throws Gav1DecoderException {
TraceUtil.beginSection("createGav1Decoder"); TraceUtil.beginSection("createGav1Decoder");
int initialInputBufferSize = int initialInputBufferSize =

View File

@ -29,7 +29,7 @@ import com.google.android.exoplayer2.audio.AudioSink;
import com.google.android.exoplayer2.audio.AudioSink.SinkFormatSupport; import com.google.android.exoplayer2.audio.AudioSink.SinkFormatSupport;
import com.google.android.exoplayer2.audio.DecoderAudioRenderer; import com.google.android.exoplayer2.audio.DecoderAudioRenderer;
import com.google.android.exoplayer2.audio.DefaultAudioSink; import com.google.android.exoplayer2.audio.DefaultAudioSink;
import com.google.android.exoplayer2.drm.ExoMediaCrypto; import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.TraceUtil; import com.google.android.exoplayer2.util.TraceUtil;
@ -97,7 +97,7 @@ public final class FfmpegAudioRenderer extends DecoderAudioRenderer<FfmpegAudioD
|| (!sinkSupportsFormat(format, C.ENCODING_PCM_16BIT) || (!sinkSupportsFormat(format, C.ENCODING_PCM_16BIT)
&& !sinkSupportsFormat(format, C.ENCODING_PCM_FLOAT))) { && !sinkSupportsFormat(format, C.ENCODING_PCM_FLOAT))) {
return C.FORMAT_UNSUPPORTED_SUBTYPE; return C.FORMAT_UNSUPPORTED_SUBTYPE;
} else if (format.exoMediaCryptoType != null) { } else if (format.cryptoType != C.CRYPTO_TYPE_NONE) {
return C.FORMAT_UNSUPPORTED_DRM; return C.FORMAT_UNSUPPORTED_DRM;
} else { } else {
return C.FORMAT_HANDLED; return C.FORMAT_HANDLED;
@ -111,7 +111,7 @@ public final class FfmpegAudioRenderer extends DecoderAudioRenderer<FfmpegAudioD
} }
@Override @Override
protected FfmpegAudioDecoder createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) protected FfmpegAudioDecoder createDecoder(Format format, @Nullable CryptoConfig cryptoConfig)
throws FfmpegDecoderException { throws FfmpegDecoderException {
TraceUtil.beginSection("createFfmpegAudioDecoder"); TraceUtil.beginSection("createFfmpegAudioDecoder");
int initialInputBufferSize = int initialInputBufferSize =

View File

@ -25,9 +25,9 @@ import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.decoder.Decoder; import com.google.android.exoplayer2.decoder.Decoder;
import com.google.android.exoplayer2.decoder.DecoderReuseEvaluation; import com.google.android.exoplayer2.decoder.DecoderReuseEvaluation;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.util.TraceUtil; import com.google.android.exoplayer2.util.TraceUtil;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.DecoderVideoRenderer; import com.google.android.exoplayer2.video.DecoderVideoRenderer;
@ -95,7 +95,7 @@ public final class FfmpegVideoRenderer extends DecoderVideoRenderer {
@SuppressWarnings("nullness:return") @SuppressWarnings("nullness:return")
@Override @Override
protected Decoder<VideoDecoderInputBuffer, VideoDecoderOutputBuffer, FfmpegDecoderException> protected Decoder<VideoDecoderInputBuffer, VideoDecoderOutputBuffer, FfmpegDecoderException>
createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) createDecoder(Format format, @Nullable CryptoConfig cryptoConfig)
throws FfmpegDecoderException { throws FfmpegDecoderException {
TraceUtil.beginSection("createFfmpegVideoDecoder"); TraceUtil.beginSection("createFfmpegVideoDecoder");
// TODO: Implement, remove the SuppressWarnings annotation, and update the return type to use // TODO: Implement, remove the SuppressWarnings annotation, and update the return type to use

View File

@ -23,7 +23,7 @@ import com.google.android.exoplayer2.audio.AudioProcessor;
import com.google.android.exoplayer2.audio.AudioRendererEventListener; import com.google.android.exoplayer2.audio.AudioRendererEventListener;
import com.google.android.exoplayer2.audio.AudioSink; import com.google.android.exoplayer2.audio.AudioSink;
import com.google.android.exoplayer2.audio.DecoderAudioRenderer; import com.google.android.exoplayer2.audio.DecoderAudioRenderer;
import com.google.android.exoplayer2.drm.ExoMediaCrypto; import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.extractor.FlacStreamMetadata; import com.google.android.exoplayer2.extractor.FlacStreamMetadata;
import com.google.android.exoplayer2.util.FlacConstants; import com.google.android.exoplayer2.util.FlacConstants;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
@ -100,7 +100,7 @@ public final class LibflacAudioRenderer extends DecoderAudioRenderer<FlacDecoder
} }
if (!sinkSupportsFormat(outputFormat)) { if (!sinkSupportsFormat(outputFormat)) {
return C.FORMAT_UNSUPPORTED_SUBTYPE; return C.FORMAT_UNSUPPORTED_SUBTYPE;
} else if (format.exoMediaCryptoType != null) { } else if (format.cryptoType != C.CRYPTO_TYPE_NONE) {
return C.FORMAT_UNSUPPORTED_DRM; return C.FORMAT_UNSUPPORTED_DRM;
} else { } else {
return C.FORMAT_HANDLED; return C.FORMAT_HANDLED;
@ -108,7 +108,7 @@ public final class LibflacAudioRenderer extends DecoderAudioRenderer<FlacDecoder
} }
@Override @Override
protected FlacDecoder createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) protected FlacDecoder createDecoder(Format format, @Nullable CryptoConfig cryptoConfig)
throws FlacDecoderException { throws FlacDecoderException {
TraceUtil.beginSection("createFlacDecoder"); TraceUtil.beginSection("createFlacDecoder");
FlacDecoder decoder = FlacDecoder decoder =

View File

@ -25,7 +25,7 @@ import com.google.android.exoplayer2.audio.AudioSink;
import com.google.android.exoplayer2.audio.AudioSink.SinkFormatSupport; import com.google.android.exoplayer2.audio.AudioSink.SinkFormatSupport;
import com.google.android.exoplayer2.audio.DecoderAudioRenderer; import com.google.android.exoplayer2.audio.DecoderAudioRenderer;
import com.google.android.exoplayer2.audio.OpusUtil; import com.google.android.exoplayer2.audio.OpusUtil;
import com.google.android.exoplayer2.drm.ExoMediaCrypto; import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.TraceUtil; import com.google.android.exoplayer2.util.TraceUtil;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
@ -81,9 +81,7 @@ public class LibopusAudioRenderer extends DecoderAudioRenderer<OpusDecoder> {
@Override @Override
@C.FormatSupport @C.FormatSupport
protected int supportsFormatInternal(Format format) { protected int supportsFormatInternal(Format format) {
boolean drmIsSupported = boolean drmIsSupported = OpusLibrary.supportsCryptoType(format.cryptoType);
format.exoMediaCryptoType == null
|| OpusLibrary.matchesExpectedExoMediaCryptoType(format.exoMediaCryptoType);
if (!OpusLibrary.isAvailable() if (!OpusLibrary.isAvailable()
|| !MimeTypes.AUDIO_OPUS.equalsIgnoreCase(format.sampleMimeType)) { || !MimeTypes.AUDIO_OPUS.equalsIgnoreCase(format.sampleMimeType)) {
return C.FORMAT_UNSUPPORTED_TYPE; return C.FORMAT_UNSUPPORTED_TYPE;
@ -98,7 +96,7 @@ public class LibopusAudioRenderer extends DecoderAudioRenderer<OpusDecoder> {
} }
@Override @Override
protected OpusDecoder createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) protected OpusDecoder createDecoder(Format format, @Nullable CryptoConfig cryptoConfig)
throws OpusDecoderException { throws OpusDecoderException {
TraceUtil.beginSection("createOpusDecoder"); TraceUtil.beginSection("createOpusDecoder");
@SinkFormatSupport @SinkFormatSupport
@ -115,7 +113,7 @@ public class LibopusAudioRenderer extends DecoderAudioRenderer<OpusDecoder> {
NUM_BUFFERS, NUM_BUFFERS,
initialInputBufferSize, initialInputBufferSize,
format.initializationData, format.initializationData,
mediaCrypto, cryptoConfig,
outputFloat); outputFloat);
TraceUtil.endSection(); TraceUtil.endSection();

View File

@ -21,12 +21,12 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.audio.OpusUtil; import com.google.android.exoplayer2.audio.OpusUtil;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.decoder.CryptoException; import com.google.android.exoplayer2.decoder.CryptoException;
import com.google.android.exoplayer2.decoder.CryptoInfo; import com.google.android.exoplayer2.decoder.CryptoInfo;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.decoder.SimpleDecoder; import com.google.android.exoplayer2.decoder.SimpleDecoder;
import com.google.android.exoplayer2.decoder.SimpleOutputBuffer; import com.google.android.exoplayer2.decoder.SimpleOutputBuffer;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -44,7 +44,7 @@ public final class OpusDecoder
public final boolean outputFloat; public final boolean outputFloat;
public final int channelCount; public final int channelCount;
@Nullable private final ExoMediaCrypto exoMediaCrypto; @Nullable private final CryptoConfig cryptoConfig;
private final int preSkipSamples; private final int preSkipSamples;
private final int seekPreRollSamples; private final int seekPreRollSamples;
private final long nativeDecoderContext; private final long nativeDecoderContext;
@ -60,8 +60,8 @@ public final class OpusDecoder
* @param initializationData Codec-specific initialization data. The first element must contain an * @param initializationData Codec-specific initialization data. The first element must contain an
* opus header. Optionally, the list may contain two additional buffers, which must contain * opus header. Optionally, the list may contain two additional buffers, which must contain
* the encoder delay and seek pre roll values in nanoseconds, encoded as longs. * the encoder delay and seek pre roll values in nanoseconds, encoded as longs.
* @param exoMediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted * @param cryptoConfig The {@link CryptoConfig} object required for decoding encrypted content.
* content. Maybe null and can be ignored if decoder does not handle encrypted content. * May be null and can be ignored if decoder does not handle encrypted content.
* @param outputFloat Forces the decoder to output float PCM samples when set * @param outputFloat Forces the decoder to output float PCM samples when set
* @throws OpusDecoderException Thrown if an exception occurs when initializing the decoder. * @throws OpusDecoderException Thrown if an exception occurs when initializing the decoder.
*/ */
@ -70,15 +70,15 @@ public final class OpusDecoder
int numOutputBuffers, int numOutputBuffers,
int initialInputBufferSize, int initialInputBufferSize,
List<byte[]> initializationData, List<byte[]> initializationData,
@Nullable ExoMediaCrypto exoMediaCrypto, @Nullable CryptoConfig cryptoConfig,
boolean outputFloat) boolean outputFloat)
throws OpusDecoderException { throws OpusDecoderException {
super(new DecoderInputBuffer[numInputBuffers], new SimpleOutputBuffer[numOutputBuffers]); super(new DecoderInputBuffer[numInputBuffers], new SimpleOutputBuffer[numOutputBuffers]);
if (!OpusLibrary.isAvailable()) { if (!OpusLibrary.isAvailable()) {
throw new OpusDecoderException("Failed to load decoder native libraries"); throw new OpusDecoderException("Failed to load decoder native libraries");
} }
this.exoMediaCrypto = exoMediaCrypto; this.cryptoConfig = cryptoConfig;
if (exoMediaCrypto != null && !OpusLibrary.opusIsSecureDecodeSupported()) { if (cryptoConfig != null && !OpusLibrary.opusIsSecureDecodeSupported()) {
throw new OpusDecoderException("Opus decoder does not support secure decode"); throw new OpusDecoderException("Opus decoder does not support secure decode");
} }
int initializationDataSize = initializationData.size(); int initializationDataSize = initializationData.size();
@ -177,7 +177,7 @@ public final class OpusDecoder
inputData.limit(), inputData.limit(),
outputBuffer, outputBuffer,
OpusUtil.SAMPLE_RATE, OpusUtil.SAMPLE_RATE,
exoMediaCrypto, cryptoConfig,
cryptoInfo.mode, cryptoInfo.mode,
Assertions.checkNotNull(cryptoInfo.key), Assertions.checkNotNull(cryptoInfo.key),
Assertions.checkNotNull(cryptoInfo.iv), Assertions.checkNotNull(cryptoInfo.iv),
@ -248,7 +248,7 @@ public final class OpusDecoder
int inputSize, int inputSize,
SimpleOutputBuffer outputBuffer, SimpleOutputBuffer outputBuffer,
int sampleRate, int sampleRate,
@Nullable ExoMediaCrypto mediaCrypto, @Nullable CryptoConfig mediaCrypto,
int inputMode, int inputMode,
byte[] key, byte[] key,
byte[] iv, byte[] iv,

View File

@ -16,10 +16,9 @@
package com.google.android.exoplayer2.ext.opus; package com.google.android.exoplayer2.ext.opus;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.util.LibraryLoader; import com.google.android.exoplayer2.util.LibraryLoader;
import com.google.android.exoplayer2.util.Util;
/** Configures and queries the underlying native library. */ /** Configures and queries the underlying native library. */
public final class OpusLibrary { public final class OpusLibrary {
@ -29,7 +28,7 @@ public final class OpusLibrary {
} }
private static final LibraryLoader LOADER = new LibraryLoader("opusV2JNI"); private static final LibraryLoader LOADER = new LibraryLoader("opusV2JNI");
@Nullable private static Class<? extends ExoMediaCrypto> exoMediaCryptoType; @C.CryptoType private static int cryptoType = C.CRYPTO_TYPE_UNSUPPORTED;
private OpusLibrary() {} private OpusLibrary() {}
@ -38,14 +37,14 @@ public final class OpusLibrary {
* it must do so before calling any other method defined by this class, and before instantiating a * it must do so before calling any other method defined by this class, and before instantiating a
* {@link LibopusAudioRenderer} instance. * {@link LibopusAudioRenderer} instance.
* *
* @param exoMediaCryptoType The {@link ExoMediaCrypto} type expected for decoding protected * @param cryptoType The {@link C.CryptoType} for which the decoder library supports decrypting
* content. * protected content, or {@link C#CRYPTO_TYPE_UNSUPPORTED} if the library does not support
* decryption.
* @param libraries The names of the Opus native libraries. * @param libraries The names of the Opus native libraries.
*/ */
public static void setLibraries( public static void setLibraries(@C.CryptoType int cryptoType, String... libraries) {
Class<? extends ExoMediaCrypto> exoMediaCryptoType, String... libraries) { OpusLibrary.cryptoType = cryptoType;
LOADER.setLibraries(libraries); LOADER.setLibraries(libraries);
OpusLibrary.exoMediaCryptoType = exoMediaCryptoType;
} }
/** Returns whether the underlying library is available, loading it if necessary. */ /** Returns whether the underlying library is available, loading it if necessary. */
@ -59,13 +58,10 @@ public final class OpusLibrary {
return isAvailable() ? opusGetVersion() : null; return isAvailable() ? opusGetVersion() : null;
} }
/** /** Returns whether the library supports the given {@link C.CryptoType}. */
* Returns whether the given {@link ExoMediaCrypto} type matches the one required for decoding public static boolean supportsCryptoType(@C.CryptoType int cryptoType) {
* protected content. return cryptoType == C.CRYPTO_TYPE_NONE
*/ || (cryptoType != C.CRYPTO_TYPE_UNSUPPORTED && cryptoType == OpusLibrary.cryptoType);
public static boolean matchesExpectedExoMediaCryptoType(
Class<? extends ExoMediaCrypto> exoMediaCryptoType) {
return Util.areEqual(OpusLibrary.exoMediaCryptoType, exoMediaCryptoType);
} }
public static native String opusGetVersion(); public static native String opusGetVersion();

View File

@ -24,8 +24,8 @@ import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.decoder.DecoderReuseEvaluation; import com.google.android.exoplayer2.decoder.DecoderReuseEvaluation;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.TraceUtil; import com.google.android.exoplayer2.util.TraceUtil;
import com.google.android.exoplayer2.video.DecoderVideoRenderer; import com.google.android.exoplayer2.video.DecoderVideoRenderer;
@ -129,9 +129,7 @@ public class LibvpxVideoRenderer extends DecoderVideoRenderer {
if (!VpxLibrary.isAvailable() || !MimeTypes.VIDEO_VP9.equalsIgnoreCase(format.sampleMimeType)) { if (!VpxLibrary.isAvailable() || !MimeTypes.VIDEO_VP9.equalsIgnoreCase(format.sampleMimeType)) {
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE); return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE);
} }
boolean drmIsSupported = boolean drmIsSupported = VpxLibrary.supportsCryptoType(format.cryptoType);
format.exoMediaCryptoType == null
|| VpxLibrary.matchesExpectedExoMediaCryptoType(format.exoMediaCryptoType);
if (!drmIsSupported) { if (!drmIsSupported) {
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_DRM); return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_DRM);
} }
@ -140,14 +138,14 @@ public class LibvpxVideoRenderer extends DecoderVideoRenderer {
} }
@Override @Override
protected VpxDecoder createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) protected VpxDecoder createDecoder(Format format, @Nullable CryptoConfig cryptoConfig)
throws VpxDecoderException { throws VpxDecoderException {
TraceUtil.beginSection("createVpxDecoder"); TraceUtil.beginSection("createVpxDecoder");
int initialInputBufferSize = int initialInputBufferSize =
format.maxInputSize != Format.NO_VALUE ? format.maxInputSize : DEFAULT_INPUT_BUFFER_SIZE; format.maxInputSize != Format.NO_VALUE ? format.maxInputSize : DEFAULT_INPUT_BUFFER_SIZE;
VpxDecoder decoder = VpxDecoder decoder =
new VpxDecoder( new VpxDecoder(
numInputBuffers, numOutputBuffers, initialInputBufferSize, mediaCrypto, threads); numInputBuffers, numOutputBuffers, initialInputBufferSize, cryptoConfig, threads);
this.decoder = decoder; this.decoder = decoder;
TraceUtil.endSection(); TraceUtil.endSection();
return decoder; return decoder;

View File

@ -21,11 +21,11 @@ import android.view.Surface;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.decoder.CryptoException; import com.google.android.exoplayer2.decoder.CryptoException;
import com.google.android.exoplayer2.decoder.CryptoInfo; import com.google.android.exoplayer2.decoder.CryptoInfo;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.decoder.SimpleDecoder; import com.google.android.exoplayer2.decoder.SimpleDecoder;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoDecoderInputBuffer; import com.google.android.exoplayer2.video.VideoDecoderInputBuffer;
@ -43,7 +43,7 @@ public final class VpxDecoder
private static final int DECODE_ERROR = -1; private static final int DECODE_ERROR = -1;
private static final int DRM_ERROR = -2; private static final int DRM_ERROR = -2;
@Nullable private final ExoMediaCrypto exoMediaCrypto; @Nullable private final CryptoConfig cryptoConfig;
private final long vpxDecContext; private final long vpxDecContext;
@Nullable private ByteBuffer lastSupplementalData; @Nullable private ByteBuffer lastSupplementalData;
@ -56,8 +56,8 @@ public final class VpxDecoder
* @param numInputBuffers The number of input buffers. * @param numInputBuffers The number of input buffers.
* @param numOutputBuffers The number of output buffers. * @param numOutputBuffers The number of output buffers.
* @param initialInputBufferSize The initial size of each input buffer. * @param initialInputBufferSize The initial size of each input buffer.
* @param exoMediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted * @param cryptoConfig The {@link CryptoConfig} object required for decoding encrypted content.
* content. Maybe null and can be ignored if decoder does not handle encrypted content. * May be null and can be ignored if decoder does not handle encrypted content.
* @param threads Number of threads libvpx will use to decode. * @param threads Number of threads libvpx will use to decode.
* @throws VpxDecoderException Thrown if an exception occurs when initializing the decoder. * @throws VpxDecoderException Thrown if an exception occurs when initializing the decoder.
*/ */
@ -65,7 +65,7 @@ public final class VpxDecoder
int numInputBuffers, int numInputBuffers,
int numOutputBuffers, int numOutputBuffers,
int initialInputBufferSize, int initialInputBufferSize,
@Nullable ExoMediaCrypto exoMediaCrypto, @Nullable CryptoConfig cryptoConfig,
int threads) int threads)
throws VpxDecoderException { throws VpxDecoderException {
super( super(
@ -74,8 +74,8 @@ public final class VpxDecoder
if (!VpxLibrary.isAvailable()) { if (!VpxLibrary.isAvailable()) {
throw new VpxDecoderException("Failed to load decoder native libraries."); throw new VpxDecoderException("Failed to load decoder native libraries.");
} }
this.exoMediaCrypto = exoMediaCrypto; this.cryptoConfig = cryptoConfig;
if (exoMediaCrypto != null && !VpxLibrary.vpxIsSecureDecodeSupported()) { if (cryptoConfig != null && !VpxLibrary.vpxIsSecureDecodeSupported()) {
throw new VpxDecoderException("Vpx decoder does not support secure decode."); throw new VpxDecoderException("Vpx decoder does not support secure decode.");
} }
vpxDecContext = vpxDecContext =
@ -134,7 +134,7 @@ public final class VpxDecoder
vpxDecContext, vpxDecContext,
inputData, inputData,
inputSize, inputSize,
exoMediaCrypto, cryptoConfig,
cryptoInfo.mode, cryptoInfo.mode,
Assertions.checkNotNull(cryptoInfo.key), Assertions.checkNotNull(cryptoInfo.key),
Assertions.checkNotNull(cryptoInfo.iv), Assertions.checkNotNull(cryptoInfo.iv),
@ -215,7 +215,7 @@ public final class VpxDecoder
long context, long context,
ByteBuffer encoded, ByteBuffer encoded,
int length, int length,
@Nullable ExoMediaCrypto mediaCrypto, @Nullable CryptoConfig mediaCrypto,
int inputMode, int inputMode,
byte[] key, byte[] key,
byte[] iv, byte[] iv,

View File

@ -16,10 +16,9 @@
package com.google.android.exoplayer2.ext.vp9; package com.google.android.exoplayer2.ext.vp9;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.util.LibraryLoader; import com.google.android.exoplayer2.util.LibraryLoader;
import com.google.android.exoplayer2.util.Util;
/** Configures and queries the underlying native library. */ /** Configures and queries the underlying native library. */
public final class VpxLibrary { public final class VpxLibrary {
@ -29,7 +28,7 @@ public final class VpxLibrary {
} }
private static final LibraryLoader LOADER = new LibraryLoader("vpx", "vpxV2JNI"); private static final LibraryLoader LOADER = new LibraryLoader("vpx", "vpxV2JNI");
@Nullable private static Class<? extends ExoMediaCrypto> exoMediaCryptoType; @C.CryptoType private static int cryptoType = C.CRYPTO_TYPE_UNSUPPORTED;
private VpxLibrary() {} private VpxLibrary() {}
@ -38,14 +37,14 @@ public final class VpxLibrary {
* it must do so before calling any other method defined by this class, and before instantiating a * it must do so before calling any other method defined by this class, and before instantiating a
* {@link LibvpxVideoRenderer} instance. * {@link LibvpxVideoRenderer} instance.
* *
* @param exoMediaCryptoType The {@link ExoMediaCrypto} type required for decoding protected * @param cryptoType The {@link C.CryptoType} for which the decoder library supports decrypting
* content. * protected content, or {@link C#CRYPTO_TYPE_UNSUPPORTED} if the library does not support
* decryption.
* @param libraries The names of the Vpx native libraries. * @param libraries The names of the Vpx native libraries.
*/ */
public static void setLibraries( public static void setLibraries(@C.CryptoType int cryptoType, String... libraries) {
Class<? extends ExoMediaCrypto> exoMediaCryptoType, String... libraries) { VpxLibrary.cryptoType = cryptoType;
LOADER.setLibraries(libraries); LOADER.setLibraries(libraries);
VpxLibrary.exoMediaCryptoType = exoMediaCryptoType;
} }
/** Returns whether the underlying library is available, loading it if necessary. */ /** Returns whether the underlying library is available, loading it if necessary. */
@ -75,13 +74,10 @@ public final class VpxLibrary {
return indexHbd >= 0; return indexHbd >= 0;
} }
/** /** Returns whether the library supports the given {@link C.CryptoType}. */
* Returns whether the given {@link ExoMediaCrypto} type matches the one required for decoding public static boolean supportsCryptoType(@C.CryptoType int cryptoType) {
* protected content. return cryptoType == C.CRYPTO_TYPE_NONE
*/ || (cryptoType != C.CRYPTO_TYPE_UNSUPPORTED && cryptoType == VpxLibrary.cryptoType);
public static boolean matchesExpectedExoMediaCryptoType(
Class<? extends ExoMediaCrypto> exoMediaCryptoType) {
return Util.areEqual(VpxLibrary.exoMediaCryptoType, exoMediaCryptoType);
} }
private static native String vpxGetVersion(); private static native String vpxGetVersion();

View File

@ -20,6 +20,7 @@ import android.media.AudioAttributes;
import android.media.AudioFormat; import android.media.AudioFormat;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.MediaCodec; import android.media.MediaCodec;
import android.media.MediaCrypto;
import android.media.MediaFormat; import android.media.MediaFormat;
import android.view.Surface; import android.view.Surface;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
@ -116,6 +117,33 @@ public final class C {
/** The name of the sans-serif font family. */ /** The name of the sans-serif font family. */
public static final String SANS_SERIF_NAME = "sans-serif"; public static final String SANS_SERIF_NAME = "sans-serif";
/**
* Types of crypto implementation. May be one of {@link #CRYPTO_TYPE_NONE}, {@link
* #CRYPTO_TYPE_UNSUPPORTED} or {@link #CRYPTO_TYPE_FRAMEWORK}. May also be an app-defined value
* (see {@link #CRYPTO_TYPE_CUSTOM_BASE}).
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef(
open = true,
value = {
CRYPTO_TYPE_UNSUPPORTED,
CRYPTO_TYPE_NONE,
CRYPTO_TYPE_FRAMEWORK,
})
public @interface CryptoType {}
/** No crypto. */
public static final int CRYPTO_TYPE_NONE = 0;
/** An unsupported crypto type. */
public static final int CRYPTO_TYPE_UNSUPPORTED = 1;
/** Framework crypto in which a {@link MediaCodec} is configured with a {@link MediaCrypto}. */
public static final int CRYPTO_TYPE_FRAMEWORK = 2;
/**
* Applications or extensions may define custom {@code CRYPTO_TYPE_*} constants greater than or
* equal to this value.
*/
public static final int CRYPTO_TYPE_CUSTOM_BASE = 10000;
/** /**
* Crypto modes for a codec. One of {@link #CRYPTO_MODE_UNENCRYPTED}, {@link #CRYPTO_MODE_AES_CTR} * Crypto modes for a codec. One of {@link #CRYPTO_MODE_UNENCRYPTED}, {@link #CRYPTO_MODE_AES_CTR}
* or {@link #CRYPTO_MODE_AES_CBC}. * or {@link #CRYPTO_MODE_AES_CBC}.

View File

@ -19,8 +19,6 @@ import android.os.Bundle;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.drm.UnsupportedMediaCrypto;
import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.util.BundleableUtils; import com.google.android.exoplayer2.util.BundleableUtils;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
@ -174,7 +172,7 @@ public final class Format implements Bundleable {
// Provided by the source. // Provided by the source.
@Nullable private Class<? extends ExoMediaCrypto> exoMediaCryptoType; @C.CryptoType private int cryptoType;
/** Creates a new instance with default values. */ /** Creates a new instance with default values. */
public Builder() { public Builder() {
@ -195,6 +193,8 @@ public final class Format implements Bundleable {
pcmEncoding = NO_VALUE; pcmEncoding = NO_VALUE;
// Text specific. // Text specific.
accessibilityChannel = NO_VALUE; accessibilityChannel = NO_VALUE;
// Provided by the source.
cryptoType = C.CRYPTO_TYPE_NONE;
} }
/** /**
@ -238,7 +238,7 @@ public final class Format implements Bundleable {
// Text specific. // Text specific.
this.accessibilityChannel = format.accessibilityChannel; this.accessibilityChannel = format.accessibilityChannel;
// Provided by the source. // Provided by the source.
this.exoMediaCryptoType = format.exoMediaCryptoType; this.cryptoType = format.cryptoType;
} }
/** /**
@ -585,14 +585,13 @@ public final class Format implements Bundleable {
// Provided by source. // Provided by source.
/** /**
* Sets {@link Format#exoMediaCryptoType}. The default value is {@code null}. * Sets {@link Format#cryptoType}. The default value is {@link C#CRYPTO_TYPE_NONE}.
* *
* @param exoMediaCryptoType The {@link Format#exoMediaCryptoType}. * @param cryptoType The {@link C.CryptoType}.
* @return The builder. * @return The builder.
*/ */
public Builder setExoMediaCryptoType( public Builder setCryptoType(@C.CryptoType int cryptoType) {
@Nullable Class<? extends ExoMediaCrypto> exoMediaCryptoType) { this.cryptoType = cryptoType;
this.exoMediaCryptoType = exoMediaCryptoType;
return this; return this;
} }
@ -756,11 +755,12 @@ public final class Format implements Bundleable {
// Provided by source. // Provided by source.
/** /**
* The type of {@link ExoMediaCrypto} that will be associated with the content this format * The type of crypto that must be used to decode samples associated with this format, or {@link
* describes, or {@code null} if the content is not encrypted. Cannot be null if {@link * C#CRYPTO_TYPE_NONE} if the content is not encrypted. Cannot be {@link C#CRYPTO_TYPE_NONE} if
* #drmInitData} is non-null. * {@link #drmInitData} is non-null, but may be {@link C#CRYPTO_TYPE_UNSUPPORTED} to indicate that
* the samples are encrypted using an unsupported crypto type.
*/ */
@Nullable public final Class<? extends ExoMediaCrypto> exoMediaCryptoType; @C.CryptoType public final int cryptoType;
// Lazily initialized hashcode. // Lazily initialized hashcode.
private int hashCode; private int hashCode;
@ -964,11 +964,11 @@ public final class Format implements Bundleable {
// Text specific. // Text specific.
accessibilityChannel = builder.accessibilityChannel; accessibilityChannel = builder.accessibilityChannel;
// Provided by source. // Provided by source.
if (builder.exoMediaCryptoType == null && drmInitData != null) { if (builder.cryptoType == C.CRYPTO_TYPE_NONE && drmInitData != null) {
// Encrypted content must always have a non-null exoMediaCryptoType. // Encrypted content cannot use CRYPTO_TYPE_NONE.
exoMediaCryptoType = UnsupportedMediaCrypto.class; cryptoType = C.CRYPTO_TYPE_UNSUPPORTED;
} else { } else {
exoMediaCryptoType = builder.exoMediaCryptoType; cryptoType = builder.cryptoType;
} }
} }
@ -1113,10 +1113,9 @@ public final class Format implements Bundleable {
return buildUpon().setWidth(width).setHeight(height).build(); return buildUpon().setWidth(width).setHeight(height).build();
} }
/** Returns a copy of this format with the specified {@link #exoMediaCryptoType}. */ /** Returns a copy of this format with the specified {@link #cryptoType}. */
public Format copyWithExoMediaCryptoType( public Format copyWithCryptoType(@C.CryptoType int cryptoType) {
@Nullable Class<? extends ExoMediaCrypto> exoMediaCryptoType) { return buildUpon().setCryptoType(cryptoType).build();
return buildUpon().setExoMediaCryptoType(exoMediaCryptoType).build();
} }
/** /**
@ -1197,7 +1196,7 @@ public final class Format implements Bundleable {
// Text specific. // Text specific.
result = 31 * result + accessibilityChannel; result = 31 * result + accessibilityChannel;
// Provided by the source. // Provided by the source.
result = 31 * result + (exoMediaCryptoType == null ? 0 : exoMediaCryptoType.hashCode()); result = 31 * result + cryptoType;
hashCode = result; hashCode = result;
} }
return hashCode; return hashCode;
@ -1232,9 +1231,9 @@ public final class Format implements Bundleable {
&& encoderDelay == other.encoderDelay && encoderDelay == other.encoderDelay
&& encoderPadding == other.encoderPadding && encoderPadding == other.encoderPadding
&& accessibilityChannel == other.accessibilityChannel && accessibilityChannel == other.accessibilityChannel
&& cryptoType == other.cryptoType
&& Float.compare(frameRate, other.frameRate) == 0 && Float.compare(frameRate, other.frameRate) == 0
&& Float.compare(pixelWidthHeightRatio, other.pixelWidthHeightRatio) == 0 && Float.compare(pixelWidthHeightRatio, other.pixelWidthHeightRatio) == 0
&& Util.areEqual(exoMediaCryptoType, other.exoMediaCryptoType)
&& Util.areEqual(id, other.id) && Util.areEqual(id, other.id)
&& Util.areEqual(label, other.label) && Util.areEqual(label, other.label)
&& Util.areEqual(codecs, other.codecs) && Util.areEqual(codecs, other.codecs)
@ -1360,6 +1359,7 @@ public final class Format implements Bundleable {
FIELD_ENCODER_DELAY, FIELD_ENCODER_DELAY,
FIELD_ENCODER_PADDING, FIELD_ENCODER_PADDING,
FIELD_ACCESSIBILITY_CHANNEL, FIELD_ACCESSIBILITY_CHANNEL,
FIELD_CRYPTO_TYPE,
}) })
private @interface FieldNumber {} private @interface FieldNumber {}
@ -1392,13 +1392,8 @@ public final class Format implements Bundleable {
private static final int FIELD_ENCODER_DELAY = 26; private static final int FIELD_ENCODER_DELAY = 26;
private static final int FIELD_ENCODER_PADDING = 27; private static final int FIELD_ENCODER_PADDING = 27;
private static final int FIELD_ACCESSIBILITY_CHANNEL = 28; private static final int FIELD_ACCESSIBILITY_CHANNEL = 28;
private static final int FIELD_CRYPTO_TYPE = 29;
/**
* {@inheritDoc}
*
* <p>Omits the {@link #exoMediaCryptoType} field. The {@link #exoMediaCryptoType} of an instance
* restored by {@link #CREATOR} will always be {@link UnsupportedMediaCrypto}.
*/
@Override @Override
public Bundle toBundle() { public Bundle toBundle() {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
@ -1443,6 +1438,8 @@ public final class Format implements Bundleable {
bundle.putInt(keyForField(FIELD_ENCODER_PADDING), encoderPadding); bundle.putInt(keyForField(FIELD_ENCODER_PADDING), encoderPadding);
// Text specific. // Text specific.
bundle.putInt(keyForField(FIELD_ACCESSIBILITY_CHANNEL), accessibilityChannel); bundle.putInt(keyForField(FIELD_ACCESSIBILITY_CHANNEL), accessibilityChannel);
// Source specific.
bundle.putInt(keyForField(FIELD_CRYPTO_TYPE), cryptoType);
return bundle; return bundle;
} }
@ -1512,7 +1509,9 @@ public final class Format implements Bundleable {
bundle.getInt(keyForField(FIELD_ENCODER_PADDING), DEFAULT.encoderPadding)) bundle.getInt(keyForField(FIELD_ENCODER_PADDING), DEFAULT.encoderPadding))
// Text specific. // Text specific.
.setAccessibilityChannel( .setAccessibilityChannel(
bundle.getInt(keyForField(FIELD_ACCESSIBILITY_CHANNEL), DEFAULT.accessibilityChannel)); bundle.getInt(keyForField(FIELD_ACCESSIBILITY_CHANNEL), DEFAULT.accessibilityChannel))
// Source specific.
.setCryptoType(bundle.getInt(keyForField(FIELD_CRYPTO_TYPE), DEFAULT.cryptoType));
return builder.build(); return builder.build();
} }

View File

@ -13,7 +13,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.android.exoplayer2.drm; package com.google.android.exoplayer2.decoder;
/** Enables decoding of encrypted data using keys in a DRM session. */ import com.google.android.exoplayer2.C;
public interface ExoMediaCrypto {}
/**
* Configuration for a decoder to allow it to decode encrypted media data. The configuration is
* {@link C.CryptoType} specific.
*/
public interface CryptoConfig {}

View File

@ -21,7 +21,11 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
/** Compatibility wrapper for {@link android.media.MediaCodec.CryptoInfo}. */ /**
* Metadata describing the structure of an encrypted input sample.
*
* <p>This class is a compatibility wrapper for {@link android.media.MediaCodec.CryptoInfo}.
*/
public final class CryptoInfo { public final class CryptoInfo {
/** /**

View File

@ -22,8 +22,6 @@ import static com.google.common.truth.Truth.assertThat;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.drm.UnsupportedMediaCrypto;
import com.google.android.exoplayer2.metadata.Metadata; import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame; import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
@ -45,15 +43,11 @@ public final class FormatTest {
} }
@Test @Test
public void roundTripViaBundle_ofParameters_yieldsEqualInstanceExceptExoMediaCryptoType() { public void roundTripViaBundle_ofParameters_yieldsEqualInstance() {
Format formatToBundle = createTestFormat(); Format formatToBundle = createTestFormat();
Format formatFromBundle = Format.CREATOR.fromBundle(formatToBundle.toBundle()); Format formatFromBundle = Format.CREATOR.fromBundle(formatToBundle.toBundle());
assertThat(formatFromBundle.exoMediaCryptoType).isEqualTo(UnsupportedMediaCrypto.class); assertThat(formatFromBundle).isEqualTo(formatToBundle);
assertThat(formatFromBundle)
.isEqualTo(
formatToBundle.buildUpon().setExoMediaCryptoType(UnsupportedMediaCrypto.class).build());
} }
private static Format createTestFormat() { private static Format createTestFormat() {
@ -93,7 +87,7 @@ public final class FormatTest {
.setPeakBitrate(2048) .setPeakBitrate(2048)
.setCodecs("codec") .setCodecs("codec")
.setMetadata(metadata) .setMetadata(metadata)
.setContainerMimeType(MimeTypes.VIDEO_MP4) .setContainerMimeType(VIDEO_MP4)
.setSampleMimeType(MimeTypes.VIDEO_H264) .setSampleMimeType(MimeTypes.VIDEO_H264)
.setMaxInputSize(5000) .setMaxInputSize(5000)
.setInitializationData(initializationData) .setInitializationData(initializationData)
@ -113,7 +107,7 @@ public final class FormatTest {
.setEncoderDelay(1001) .setEncoderDelay(1001)
.setEncoderPadding(1002) .setEncoderPadding(1002)
.setAccessibilityChannel(2) .setAccessibilityChannel(2)
.setExoMediaCryptoType(ExoMediaCrypto.class) .setCryptoType(C.CRYPTO_TYPE_CUSTOM_BASE)
.build(); .build();
} }

View File

@ -38,6 +38,7 @@ import com.google.android.exoplayer2.PlayerMessage.Target;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.audio.AudioRendererEventListener.EventDispatcher; import com.google.android.exoplayer2.audio.AudioRendererEventListener.EventDispatcher;
import com.google.android.exoplayer2.audio.AudioSink.SinkFormatSupport; import com.google.android.exoplayer2.audio.AudioSink.SinkFormatSupport;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.decoder.Decoder; import com.google.android.exoplayer2.decoder.Decoder;
import com.google.android.exoplayer2.decoder.DecoderCounters; import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.decoder.DecoderException; import com.google.android.exoplayer2.decoder.DecoderException;
@ -46,7 +47,6 @@ import com.google.android.exoplayer2.decoder.DecoderReuseEvaluation;
import com.google.android.exoplayer2.decoder.SimpleOutputBuffer; import com.google.android.exoplayer2.decoder.SimpleOutputBuffer;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException; import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.source.SampleStream.ReadDataResult; import com.google.android.exoplayer2.source.SampleStream.ReadDataResult;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
@ -330,12 +330,12 @@ public abstract class DecoderAudioRenderer<
* Creates a decoder for the given format. * Creates a decoder for the given format.
* *
* @param format The format for which a decoder is required. * @param format The format for which a decoder is required.
* @param mediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted content. * @param cryptoConfig The {@link CryptoConfig} object required for decoding encrypted content.
* May be null and can be ignored if decoder does not handle encrypted content. * May be null and can be ignored if decoder does not handle encrypted content.
* @return The decoder. * @return The decoder.
* @throws DecoderException If an error occurred creating a suitable decoder. * @throws DecoderException If an error occurred creating a suitable decoder.
*/ */
protected abstract T createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) protected abstract T createDecoder(Format format, @Nullable CryptoConfig cryptoConfig)
throws DecoderException; throws DecoderException;
/** /**
@ -603,10 +603,10 @@ public abstract class DecoderAudioRenderer<
setDecoderDrmSession(sourceDrmSession); setDecoderDrmSession(sourceDrmSession);
ExoMediaCrypto mediaCrypto = null; CryptoConfig cryptoConfig = null;
if (decoderDrmSession != null) { if (decoderDrmSession != null) {
mediaCrypto = decoderDrmSession.getMediaCrypto(); cryptoConfig = decoderDrmSession.getCryptoConfig();
if (mediaCrypto == null) { if (cryptoConfig == null) {
DrmSessionException drmError = decoderDrmSession.getError(); DrmSessionException drmError = decoderDrmSession.getError();
if (drmError != null) { if (drmError != null) {
// Continue for now. We may be able to avoid failure if a new input format causes the // Continue for now. We may be able to avoid failure if a new input format causes the
@ -621,7 +621,7 @@ public abstract class DecoderAudioRenderer<
try { try {
long codecInitializingTimestamp = SystemClock.elapsedRealtime(); long codecInitializingTimestamp = SystemClock.elapsedRealtime();
TraceUtil.beginSection("createAudioDecoder"); TraceUtil.beginSection("createAudioDecoder");
decoder = createDecoder(inputFormat, mediaCrypto); decoder = createDecoder(inputFormat, cryptoConfig);
TraceUtil.endSection(); TraceUtil.endSection();
long codecInitializedTimestamp = SystemClock.elapsedRealtime(); long codecInitializedTimestamp = SystemClock.elapsedRealtime();
eventDispatcher.decoderInitialized( eventDispatcher.decoderInitialized(

View File

@ -272,7 +272,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
} }
@TunnelingSupport @TunnelingSupport
int tunnelingSupport = Util.SDK_INT >= 21 ? TUNNELING_SUPPORTED : TUNNELING_NOT_SUPPORTED; int tunnelingSupport = Util.SDK_INT >= 21 ? TUNNELING_SUPPORTED : TUNNELING_NOT_SUPPORTED;
boolean formatHasDrm = format.exoMediaCryptoType != null; boolean formatHasDrm = format.cryptoType != C.CRYPTO_TYPE_NONE;
boolean supportsFormatDrm = supportsFormatDrm(format); boolean supportsFormatDrm = supportsFormatDrm(format);
// In direct mode, if the format has DRM then we need to use a decoder that only decrypts. // In direct mode, if the format has DRM then we need to use a decoder that only decrypts.
// Else we don't don't need a decoder at all. // Else we don't don't need a decoder at all.

View File

@ -31,6 +31,7 @@ import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
import com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest; import com.google.android.exoplayer2.drm.ExoMediaDrm.KeyRequest;
import com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest; import com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest;
@ -141,7 +142,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
private int referenceCount; private int referenceCount;
@Nullable private HandlerThread requestHandlerThread; @Nullable private HandlerThread requestHandlerThread;
@Nullable private RequestHandler requestHandler; @Nullable private RequestHandler requestHandler;
@Nullable private ExoMediaCrypto mediaCrypto; @Nullable private CryptoConfig cryptoConfig;
@Nullable private DrmSessionException lastException; @Nullable private DrmSessionException lastException;
@Nullable private byte[] sessionId; @Nullable private byte[] sessionId;
private byte @MonotonicNonNull [] offlineLicenseKeySetId; private byte @MonotonicNonNull [] offlineLicenseKeySetId;
@ -260,7 +261,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
} }
@Override @Override
public final @Nullable DrmSessionException getError() { @Nullable
public final DrmSessionException getError() {
return state == STATE_ERROR ? lastException : null; return state == STATE_ERROR ? lastException : null;
} }
@ -270,8 +272,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
} }
@Override @Override
public final @Nullable ExoMediaCrypto getMediaCrypto() { @Nullable
return mediaCrypto; public final CryptoConfig getCryptoConfig() {
return cryptoConfig;
} }
@Override @Override
@ -326,7 +329,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
requestHandler = null; requestHandler = null;
Util.castNonNull(requestHandlerThread).quit(); Util.castNonNull(requestHandlerThread).quit();
requestHandlerThread = null; requestHandlerThread = null;
mediaCrypto = null; cryptoConfig = null;
lastException = null; lastException = null;
currentKeyRequest = null; currentKeyRequest = null;
currentProvisionRequest = null; currentProvisionRequest = null;
@ -361,7 +364,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
try { try {
sessionId = mediaDrm.openSession(); sessionId = mediaDrm.openSession();
mediaCrypto = mediaDrm.createMediaCrypto(sessionId); cryptoConfig = mediaDrm.createCryptoConfig(sessionId);
state = STATE_OPENED; state = STATE_OPENED;
// Capture state into a local so a consistent value is seen by the lambda. // Capture state into a local so a consistent value is seen by the lambda.
int localState = state; int localState = state;

View File

@ -579,19 +579,16 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
} }
@Override @Override
@Nullable @C.CryptoType
public Class<? extends ExoMediaCrypto> getExoMediaCryptoType(Format format) { public int getCryptoType(Format format) {
Class<? extends ExoMediaCrypto> exoMediaCryptoType = @C.CryptoType int cryptoType = checkNotNull(exoMediaDrm).getCryptoType();
checkNotNull(exoMediaDrm).getExoMediaCryptoType();
if (format.drmInitData == null) { if (format.drmInitData == null) {
int trackType = MimeTypes.getTrackType(format.sampleMimeType); int trackType = MimeTypes.getTrackType(format.sampleMimeType);
return Util.linearSearch(useDrmSessionsForClearContentTrackTypes, trackType) != C.INDEX_UNSET return Util.linearSearch(useDrmSessionsForClearContentTrackTypes, trackType) != C.INDEX_UNSET
? exoMediaCryptoType ? cryptoType
: null; : C.CRYPTO_TYPE_NONE;
} else { } else {
return canAcquireSession(format.drmInitData) return canAcquireSession(format.drmInitData) ? cryptoType : C.CRYPTO_TYPE_UNSUPPORTED;
? exoMediaCryptoType
: UnsupportedMediaCrypto.class;
} }
} }
@ -602,12 +599,12 @@ public class DefaultDrmSessionManager implements DrmSessionManager {
int trackType, boolean shouldReleasePreacquiredSessionsBeforeRetrying) { int trackType, boolean shouldReleasePreacquiredSessionsBeforeRetrying) {
ExoMediaDrm exoMediaDrm = checkNotNull(this.exoMediaDrm); ExoMediaDrm exoMediaDrm = checkNotNull(this.exoMediaDrm);
boolean avoidPlaceholderDrmSessions = boolean avoidPlaceholderDrmSessions =
FrameworkMediaCrypto.class.equals(exoMediaDrm.getExoMediaCryptoType()) exoMediaDrm.getCryptoType() == C.CRYPTO_TYPE_FRAMEWORK
&& FrameworkMediaCrypto.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC; && FrameworkCryptoConfig.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC;
// Avoid attaching a session to sparse formats. // Avoid attaching a session to sparse formats.
if (avoidPlaceholderDrmSessions if (avoidPlaceholderDrmSessions
|| Util.linearSearch(useDrmSessionsForClearContentTrackTypes, trackType) == C.INDEX_UNSET || Util.linearSearch(useDrmSessionsForClearContentTrackTypes, trackType) == C.INDEX_UNSET
|| UnsupportedMediaCrypto.class.equals(exoMediaDrm.getExoMediaCryptoType())) { || exoMediaDrm.getCryptoType() == C.CRYPTO_TYPE_UNSUPPORTED) {
return null; return null;
} }
if (placeholderDrmSession == null) { if (placeholderDrmSession == null) {

View File

@ -19,6 +19,7 @@ import android.media.MediaDrm;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -109,11 +110,11 @@ public interface DrmSession {
UUID getSchemeUuid(); UUID getSchemeUuid();
/** /**
* Returns an {@link ExoMediaCrypto} for the open session, or null if called before the session * Returns a {@link CryptoConfig} for the open session, or null if called before the session has
* has been opened or after it's been released. * been opened or after it's been released.
*/ */
@Nullable @Nullable
ExoMediaCrypto getMediaCrypto(); CryptoConfig getCryptoConfig();
/** /**
* Returns a map describing the key status for the session, or null if called before the session * Returns a map describing the key status for the session, or null if called before the session

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2.drm;
import android.os.Looper; import android.os.Looper;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackException;
@ -61,9 +62,9 @@ public interface DrmSessionManager {
} }
@Override @Override
@Nullable @C.CryptoType
public Class<UnsupportedMediaCrypto> getExoMediaCryptoType(Format format) { public int getCryptoType(Format format) {
return format.drmInitData != null ? UnsupportedMediaCrypto.class : null; return format.drmInitData != null ? C.CRYPTO_TYPE_UNSUPPORTED : C.CRYPTO_TYPE_NONE;
} }
}; };
@ -171,19 +172,18 @@ public interface DrmSessionManager {
Format format); Format format);
/** /**
* Returns the {@link ExoMediaCrypto} type associated to sessions acquired for the given {@link * Returns the {@link C.CryptoType} that the DRM session manager will use for a given {@link
* Format}. Returns the {@link UnsupportedMediaCrypto} type if this DRM session manager does not * Format}. Returns {@link C#CRYPTO_TYPE_UNSUPPORTED} if the manager does not support any of the
* support any of the DRM schemes defined in the given {@link Format}. Returns null if {@link * DRM schemes defined in the {@link Format}. Returns {@link C#CRYPTO_TYPE_NONE} if {@link
* Format#drmInitData} is null and {@link #acquireSession} would return null for the given {@link * Format#drmInitData} is null and {@link #acquireSession} will return {@code null} for the given
* Format}.
*
* @param format The {@link Format} for which to return the {@link ExoMediaCrypto} type.
* @return The {@link ExoMediaCrypto} type associated to sessions acquired using the given {@link
* Format}, or {@link UnsupportedMediaCrypto} if this DRM session manager does not support any
* of the DRM schemes defined in the given {@link Format}. May be null if {@link
* Format#drmInitData} is null and {@link #acquireSession} would return null for the given
* {@link Format}. * {@link Format}.
*
* @param format The {@link Format}.
* @return The {@link C.CryptoType} that the manager will use, or @link C#CRYPTO_TYPE_UNSUPPORTED}
* if the manager does not support any of the DRM schemes defined in the {@link Format}. Will
* be {@link C#CRYPTO_TYPE_NONE} if {@link Format#drmInitData} is null and {@link
* #acquireSession} will return null for the given {@link Format}.
*/ */
@Nullable @C.CryptoType
Class<? extends ExoMediaCrypto> getExoMediaCryptoType(Format format); int getCryptoType(Format format);
} }

View File

@ -19,6 +19,8 @@ import android.media.MediaDrmException;
import android.os.PersistableBundle; import android.os.PersistableBundle;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -142,13 +144,14 @@ public final class DummyExoMediaDrm implements ExoMediaDrm {
} }
@Override @Override
public ExoMediaCrypto createMediaCrypto(byte[] sessionId) { public CryptoConfig createCryptoConfig(byte[] sessionId) {
// Should not be invoked. No session should exist. // Should not be invoked. No session should exist.
throw new IllegalStateException(); throw new IllegalStateException();
} }
@Override @Override
public Class<UnsupportedMediaCrypto> getExoMediaCryptoType() { @C.CryptoType
return UnsupportedMediaCrypto.class; public int getCryptoType() {
return C.CRYPTO_TYPE_UNSUPPORTED;
} }
} }

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2.drm;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@ -53,7 +54,7 @@ public final class ErrorStateDrmSession implements DrmSession {
@Override @Override
@Nullable @Nullable
public ExoMediaCrypto getMediaCrypto() { public CryptoConfig getCryptoConfig() {
return null; return null;
} }

View File

@ -25,6 +25,8 @@ import android.os.Handler;
import android.os.PersistableBundle; import android.os.PersistableBundle;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -538,14 +540,19 @@ public interface ExoMediaDrm {
void setPropertyByteArray(String propertyName, byte[] value); void setPropertyByteArray(String propertyName, byte[] value);
/** /**
* Creates an {@link ExoMediaCrypto} for a given session. * Creates a {@link CryptoConfig} that can be passed to a compatible decoder to allow decryption
* of protected content using the specified session.
* *
* @param sessionId The ID of the session. * @param sessionId The ID of the session.
* @return An {@link ExoMediaCrypto} for the given session. * @return A {@link CryptoConfig} for the given session.
* @throws MediaCryptoException If an {@link ExoMediaCrypto} could not be created. * @throws MediaCryptoException If a {@link CryptoConfig} could not be created.
*/ */
ExoMediaCrypto createMediaCrypto(byte[] sessionId) throws MediaCryptoException; CryptoConfig createCryptoConfig(byte[] sessionId) throws MediaCryptoException;
/** Returns the {@link ExoMediaCrypto} type created by {@link #createMediaCrypto(byte[])}. */ /**
Class<? extends ExoMediaCrypto> getExoMediaCryptoType(); * Returns the {@link C.CryptoType type} of {@link CryptoConfig} instances returned by {@link
* #createCryptoConfig}.
*/
@C.CryptoType
int getCryptoType();
} }

View File

@ -15,15 +15,19 @@
*/ */
package com.google.android.exoplayer2.drm; package com.google.android.exoplayer2.drm;
import android.media.MediaCodec;
import android.media.MediaCrypto; import android.media.MediaCrypto;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.util.UUID; import java.util.UUID;
/** /**
* An {@link ExoMediaCrypto} implementation that contains the necessary information to build or * A {@link CryptoConfig} for {@link C#CRYPTO_TYPE_FRAMEWORK}. Contains the necessary information to
* update a framework {@link MediaCrypto}. * build or update a framework {@link MediaCrypto} that can be used to configure a {@link
* MediaCodec}.
*/ */
public final class FrameworkMediaCrypto implements ExoMediaCrypto { public final class FrameworkCryptoConfig implements CryptoConfig {
/** /**
* Whether the device needs keys to have been loaded into the {@link DrmSession} before codec * Whether the device needs keys to have been loaded into the {@link DrmSession} before codec
@ -50,7 +54,7 @@ public final class FrameworkMediaCrypto implements ExoMediaCrypto {
* @param forceAllowInsecureDecoderComponents Whether to allow use of insecure decoder components * @param forceAllowInsecureDecoderComponents Whether to allow use of insecure decoder components
* even if the underlying platform says otherwise. * even if the underlying platform says otherwise.
*/ */
public FrameworkMediaCrypto( public FrameworkCryptoConfig(
UUID uuid, byte[] sessionId, boolean forceAllowInsecureDecoderComponents) { UUID uuid, byte[] sessionId, boolean forceAllowInsecureDecoderComponents) {
this.uuid = uuid; this.uuid = uuid;
this.sessionId = sessionId; this.sessionId = sessionId;

View File

@ -314,20 +314,21 @@ public final class FrameworkMediaDrm implements ExoMediaDrm {
} }
@Override @Override
public FrameworkMediaCrypto createMediaCrypto(byte[] sessionId) throws MediaCryptoException { public FrameworkCryptoConfig createCryptoConfig(byte[] sessionId) throws MediaCryptoException {
// Work around a bug prior to Lollipop where L1 Widevine forced into L3 mode would still // 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]. // indicate that it required secure video decoders [Internal ref: b/11428937].
boolean forceAllowInsecureDecoderComponents = boolean forceAllowInsecureDecoderComponents =
Util.SDK_INT < 21 Util.SDK_INT < 21
&& C.WIDEVINE_UUID.equals(uuid) && C.WIDEVINE_UUID.equals(uuid)
&& "L3".equals(getPropertyString("securityLevel")); && "L3".equals(getPropertyString("securityLevel"));
return new FrameworkMediaCrypto( return new FrameworkCryptoConfig(
adjustUuid(uuid), sessionId, forceAllowInsecureDecoderComponents); adjustUuid(uuid), sessionId, forceAllowInsecureDecoderComponents);
} }
@Override @Override
public Class<FrameworkMediaCrypto> getExoMediaCryptoType() { @C.CryptoType
return FrameworkMediaCrypto.class; public int getCryptoType() {
return C.CRYPTO_TYPE_FRAMEWORK;
} }
private static SchemeData getSchemeData(UUID uuid, List<SchemeData> schemeDatas) { private static SchemeData getSchemeData(UUID uuid, List<SchemeData> schemeDatas) {

View File

@ -50,6 +50,7 @@ import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.decoder.DecoderCounters; import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer.InsufficientCapacityException; import com.google.android.exoplayer2.decoder.DecoderInputBuffer.InsufficientCapacityException;
@ -57,8 +58,7 @@ import com.google.android.exoplayer2.decoder.DecoderReuseEvaluation;
import com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DecoderDiscardReasons; import com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DecoderDiscardReasons;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException; import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
import com.google.android.exoplayer2.drm.ExoMediaCrypto; import com.google.android.exoplayer2.drm.FrameworkCryptoConfig;
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
@ -545,8 +545,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
if (codecDrmSession != null) { if (codecDrmSession != null) {
if (mediaCrypto == null) { if (mediaCrypto == null) {
@Nullable @Nullable
FrameworkMediaCrypto sessionMediaCrypto = getFrameworkMediaCrypto(codecDrmSession); FrameworkCryptoConfig sessionCryptoConfig = getFrameworkCryptoConfig(codecDrmSession);
if (sessionMediaCrypto == null) { if (sessionCryptoConfig == null) {
@Nullable DrmSessionException drmError = codecDrmSession.getError(); @Nullable DrmSessionException drmError = codecDrmSession.getError();
if (drmError != null) { if (drmError != null) {
// Continue for now. We may be able to avoid failure if a new input format causes the // Continue for now. We may be able to avoid failure if a new input format causes the
@ -557,17 +557,17 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
} }
} else { } else {
try { try {
mediaCrypto = new MediaCrypto(sessionMediaCrypto.uuid, sessionMediaCrypto.sessionId); mediaCrypto = new MediaCrypto(sessionCryptoConfig.uuid, sessionCryptoConfig.sessionId);
} catch (MediaCryptoException e) { } catch (MediaCryptoException e) {
throw createRendererException( throw createRendererException(
e, inputFormat, PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR); e, inputFormat, PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR);
} }
mediaCryptoRequiresSecureDecoder = mediaCryptoRequiresSecureDecoder =
!sessionMediaCrypto.forceAllowInsecureDecoderComponents !sessionCryptoConfig.forceAllowInsecureDecoderComponents
&& mediaCrypto.requiresSecureDecoderComponent(mimeType); && mediaCrypto.requiresSecureDecoderComponent(mimeType);
} }
} }
if (FrameworkMediaCrypto.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC) { if (FrameworkCryptoConfig.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC) {
@DrmSession.State int drmSessionState = codecDrmSession.getState(); @DrmSession.State int drmSessionState = codecDrmSession.getState();
if (drmSessionState == DrmSession.STATE_ERROR) { if (drmSessionState == DrmSession.STATE_ERROR) {
DrmSessionException drmSessionException = DrmSessionException drmSessionException =
@ -1074,11 +1074,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
return codecInfos; return codecInfos;
} }
/** /** Configures rendering where no codec is used. */
* Configures rendering where no codec is used. Called instead of {@link
* #configureCodec(MediaCodecInfo, MediaCodecAdapter, Format, MediaCrypto, float)} when no codec
* is used to render.
*/
private void initBypass(Format format) { private void initBypass(Format format) {
disableBypass(); // In case of transition between 2 bypass formats. disableBypass(); // In case of transition between 2 bypass formats.
@ -2047,8 +2043,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
/** Returns whether this renderer supports the given {@link Format Format's} DRM scheme. */ /** Returns whether this renderer supports the given {@link Format Format's} DRM scheme. */
protected static boolean supportsFormatDrm(Format format) { protected static boolean supportsFormatDrm(Format format) {
return format.exoMediaCryptoType == null return format.cryptoType == C.CRYPTO_TYPE_NONE || format.cryptoType == C.CRYPTO_TYPE_FRAMEWORK;
|| FrameworkMediaCrypto.class.equals(format.exoMediaCryptoType);
} }
/** /**
@ -2088,8 +2083,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
// TODO: Add an API check once [Internal ref: b/128835874] is fixed. // TODO: Add an API check once [Internal ref: b/128835874] is fixed.
return true; return true;
} }
@Nullable FrameworkMediaCrypto newMediaCrypto = getFrameworkMediaCrypto(newSession); @Nullable FrameworkCryptoConfig newCryptoConfig = getFrameworkCryptoConfig(newSession);
if (newMediaCrypto == null) { if (newCryptoConfig == null) {
// We'd only expect this to happen if the CDM from which newSession is obtained needs // We'd only expect this to happen if the CDM from which newSession is obtained needs
// provisioning. This is unlikely to happen (it probably requires a switch from one DRM scheme // provisioning. This is unlikely to happen (it probably requires a switch from one DRM scheme
// to another, where the new CDM hasn't been used before and needs provisioning). It would be // to another, where the new CDM hasn't been used before and needs provisioning). It would be
@ -2101,7 +2096,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
} }
boolean requiresSecureDecoder; boolean requiresSecureDecoder;
if (newMediaCrypto.forceAllowInsecureDecoderComponents) { if (newCryptoConfig.forceAllowInsecureDecoderComponents) {
requiresSecureDecoder = false; requiresSecureDecoder = false;
} else { } else {
requiresSecureDecoder = newSession.requiresSecureDecoder(newFormat.sampleMimeType); requiresSecureDecoder = newSession.requiresSecureDecoder(newFormat.sampleMimeType);
@ -2136,7 +2131,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
@RequiresApi(23) @RequiresApi(23)
private void updateDrmSessionV23() throws ExoPlaybackException { private void updateDrmSessionV23() throws ExoPlaybackException {
try { try {
mediaCrypto.setMediaDrmSession(getFrameworkMediaCrypto(sourceDrmSession).sessionId); mediaCrypto.setMediaDrmSession(getFrameworkCryptoConfig(sourceDrmSession).sessionId);
} catch (MediaCryptoException e) { } catch (MediaCryptoException e) {
throw createRendererException(e, inputFormat, PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR); throw createRendererException(e, inputFormat, PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR);
} }
@ -2146,18 +2141,19 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
} }
@Nullable @Nullable
private FrameworkMediaCrypto getFrameworkMediaCrypto(DrmSession drmSession) private FrameworkCryptoConfig getFrameworkCryptoConfig(DrmSession drmSession)
throws ExoPlaybackException { throws ExoPlaybackException {
@Nullable ExoMediaCrypto mediaCrypto = drmSession.getMediaCrypto(); @Nullable CryptoConfig cryptoConfig = drmSession.getCryptoConfig();
if (mediaCrypto != null && !(mediaCrypto instanceof FrameworkMediaCrypto)) { if (cryptoConfig != null && !(cryptoConfig instanceof FrameworkCryptoConfig)) {
// This should not happen if the track went through a supportsFormatDrm() check, during track // This should not happen if the track went through a supportsFormatDrm() check, during track
// selection. // selection.
throw createRendererException( throw createRendererException(
new IllegalArgumentException("Expecting FrameworkMediaCrypto but found: " + mediaCrypto), new IllegalArgumentException(
"Expecting FrameworkCryptoConfig but found: " + cryptoConfig),
inputFormat, inputFormat,
PlaybackException.ERROR_CODE_DRM_SCHEME_UNSUPPORTED); PlaybackException.ERROR_CODE_DRM_SCHEME_UNSUPPORTED);
} }
return (FrameworkMediaCrypto) mediaCrypto; return (FrameworkCryptoConfig) cryptoConfig;
} }
/** /**

View File

@ -93,7 +93,7 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
public int supportsFormat(Format format) { public int supportsFormat(Format format) {
if (decoderFactory.supportsFormat(format)) { if (decoderFactory.supportsFormat(format)) {
return RendererCapabilities.create( return RendererCapabilities.create(
format.exoMediaCryptoType == null ? C.FORMAT_HANDLED : C.FORMAT_UNSUPPORTED_DRM); format.cryptoType == C.CRYPTO_TYPE_NONE ? C.FORMAT_HANDLED : C.FORMAT_UNSUPPORTED_DRM);
} else { } else {
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE); return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE);
} }

View File

@ -783,9 +783,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
trackFormat = trackFormat.buildUpon().setAverageBitrate(icyHeaders.bitrate).build(); trackFormat = trackFormat.buildUpon().setAverageBitrate(icyHeaders.bitrate).build();
} }
} }
trackFormat = trackFormat = trackFormat.copyWithCryptoType(drmSessionManager.getCryptoType(trackFormat));
trackFormat.copyWithExoMediaCryptoType(
drmSessionManager.getExoMediaCryptoType(trackFormat));
trackArray[i] = new TrackGroup(trackFormat); trackArray[i] = new TrackGroup(trackFormat);
} }
trackState = new TrackState(new TrackGroupArray(trackArray), trackIsAudioVideoFlags); trackState = new TrackState(new TrackGroupArray(trackArray), trackIsAudioVideoFlags);

View File

@ -899,8 +899,7 @@ public class SampleQueue implements TrackOutput {
outputFormatHolder.format = outputFormatHolder.format =
drmSessionManager != null drmSessionManager != null
? newFormat.copyWithExoMediaCryptoType( ? newFormat.copyWithCryptoType(drmSessionManager.getCryptoType(newFormat))
drmSessionManager.getExoMediaCryptoType(newFormat))
: newFormat; : newFormat;
outputFormatHolder.drmSession = currentDrmSession; outputFormatHolder.drmSession = currentDrmSession;
if (drmSessionManager == null) { if (drmSessionManager == null) {

View File

@ -134,7 +134,7 @@ public final class TextRenderer extends BaseRenderer implements Callback {
public int supportsFormat(Format format) { public int supportsFormat(Format format) {
if (decoderFactory.supportsFormat(format)) { if (decoderFactory.supportsFormat(format)) {
return RendererCapabilities.create( return RendererCapabilities.create(
format.exoMediaCryptoType == null ? C.FORMAT_HANDLED : C.FORMAT_UNSUPPORTED_DRM); format.cryptoType == C.CRYPTO_TYPE_NONE ? C.FORMAT_HANDLED : C.FORMAT_UNSUPPORTED_DRM);
} else if (MimeTypes.isText(format.sampleMimeType)) { } else if (MimeTypes.isText(format.sampleMimeType)) {
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE); return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE);
} else { } else {

View File

@ -36,6 +36,7 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.PlayerMessage.Target; import com.google.android.exoplayer2.PlayerMessage.Target;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.decoder.Decoder; import com.google.android.exoplayer2.decoder.Decoder;
import com.google.android.exoplayer2.decoder.DecoderCounters; import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.decoder.DecoderException; import com.google.android.exoplayer2.decoder.DecoderException;
@ -43,7 +44,6 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.decoder.DecoderReuseEvaluation; import com.google.android.exoplayer2.decoder.DecoderReuseEvaluation;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException; import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.source.SampleStream.ReadDataResult; import com.google.android.exoplayer2.source.SampleStream.ReadDataResult;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.Log;
@ -529,14 +529,14 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
* Creates a decoder for the given format. * Creates a decoder for the given format.
* *
* @param format The format for which a decoder is required. * @param format The format for which a decoder is required.
* @param mediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted content. * @param cryptoConfig The {@link CryptoConfig} object required for decoding encrypted content.
* May be null and can be ignored if decoder does not handle encrypted content. * May be null and can be ignored if decoder does not handle encrypted content.
* @return The decoder. * @return The decoder.
* @throws DecoderException If an error occurred creating a suitable decoder. * @throws DecoderException If an error occurred creating a suitable decoder.
*/ */
protected abstract Decoder< protected abstract Decoder<
VideoDecoderInputBuffer, ? extends VideoDecoderOutputBuffer, ? extends DecoderException> VideoDecoderInputBuffer, ? extends VideoDecoderOutputBuffer, ? extends DecoderException>
createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) throws DecoderException; createDecoder(Format format, @Nullable CryptoConfig cryptoConfig) throws DecoderException;
/** /**
* Renders the specified output buffer. * Renders the specified output buffer.
@ -664,10 +664,10 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
setDecoderDrmSession(sourceDrmSession); setDecoderDrmSession(sourceDrmSession);
ExoMediaCrypto mediaCrypto = null; CryptoConfig cryptoConfig = null;
if (decoderDrmSession != null) { if (decoderDrmSession != null) {
mediaCrypto = decoderDrmSession.getMediaCrypto(); cryptoConfig = decoderDrmSession.getCryptoConfig();
if (mediaCrypto == null) { if (cryptoConfig == null) {
DrmSessionException drmError = decoderDrmSession.getError(); DrmSessionException drmError = decoderDrmSession.getError();
if (drmError != null) { if (drmError != null) {
// Continue for now. We may be able to avoid failure if a new input format causes the // Continue for now. We may be able to avoid failure if a new input format causes the
@ -681,7 +681,7 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
try { try {
long decoderInitializingTimestamp = SystemClock.elapsedRealtime(); long decoderInitializingTimestamp = SystemClock.elapsedRealtime();
decoder = createDecoder(inputFormat, mediaCrypto); decoder = createDecoder(inputFormat, cryptoConfig);
setDecoderOutputMode(outputMode); setDecoderOutputMode(outputMode);
long decoderInitializedTimestamp = SystemClock.elapsedRealtime(); long decoderInitializedTimestamp = SystemClock.elapsedRealtime();
eventDispatcher.decoderInitialized( eventDispatcher.decoderInitialized(

View File

@ -30,13 +30,13 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.RendererConfiguration; import com.google.android.exoplayer2.RendererConfiguration;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.decoder.DecoderException; import com.google.android.exoplayer2.decoder.DecoderException;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.decoder.SimpleDecoder; import com.google.android.exoplayer2.decoder.SimpleDecoder;
import com.google.android.exoplayer2.decoder.SimpleOutputBuffer; import com.google.android.exoplayer2.decoder.SimpleOutputBuffer;
import com.google.android.exoplayer2.drm.DrmSessionEventListener; import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.testutil.FakeSampleStream; import com.google.android.exoplayer2.testutil.FakeSampleStream;
import com.google.android.exoplayer2.upstream.DefaultAllocator; import com.google.android.exoplayer2.upstream.DefaultAllocator;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
@ -75,7 +75,7 @@ public class DecoderAudioRendererTest {
} }
@Override @Override
protected FakeDecoder createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) { protected FakeDecoder createDecoder(Format format, @Nullable CryptoConfig cryptoConfig) {
return new FakeDecoder(); return new FakeDecoder();
} }

View File

@ -41,8 +41,8 @@ import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession;
import com.google.android.exoplayer2.drm.DrmSessionEventListener; import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.testutil.FakeCryptoConfig;
import com.google.android.exoplayer2.testutil.TestUtil; import com.google.android.exoplayer2.testutil.TestUtil;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DefaultAllocator; import com.google.android.exoplayer2.upstream.DefaultAllocator;
@ -73,7 +73,7 @@ public final class SampleQueueTest {
private static final Format FORMAT_ENCRYPTED = private static final Format FORMAT_ENCRYPTED =
new Format.Builder().setId(/* id= */ "encrypted").setDrmInitData(new DrmInitData()).build(); new Format.Builder().setId(/* id= */ "encrypted").setDrmInitData(new DrmInitData()).build();
private static final Format FORMAT_ENCRYPTED_WITH_EXO_MEDIA_CRYPTO_TYPE = private static final Format FORMAT_ENCRYPTED_WITH_EXO_MEDIA_CRYPTO_TYPE =
FORMAT_ENCRYPTED.copyWithExoMediaCryptoType(MockExoMediaCrypto.class); FORMAT_ENCRYPTED.copyWithCryptoType(FakeCryptoConfig.TYPE);
private static final byte[] DATA = TestUtil.buildTestData(ALLOCATION_SIZE * 10); private static final byte[] DATA = TestUtil.buildTestData(ALLOCATION_SIZE * 10);
/* /*
@ -1761,8 +1761,6 @@ public final class SampleQueueTest {
return format.buildUpon().setLabel(label).build(); return format.buildUpon().setLabel(label).build();
} }
private static final class MockExoMediaCrypto implements ExoMediaCrypto {}
private static final class MockDrmSessionManager implements DrmSessionManager { private static final class MockDrmSessionManager implements DrmSessionManager {
private final DrmSession mockDrmSession; private final DrmSession mockDrmSession;
@ -1772,8 +1770,8 @@ public final class SampleQueueTest {
this.mockDrmSession = mockDrmSession; this.mockDrmSession = mockDrmSession;
} }
@Nullable
@Override @Override
@Nullable
public DrmSession acquireSession( public DrmSession acquireSession(
Looper playbackLooper, Looper playbackLooper,
@Nullable DrmSessionEventListener.EventDispatcher eventDispatcher, @Nullable DrmSessionEventListener.EventDispatcher eventDispatcher,
@ -1781,12 +1779,12 @@ public final class SampleQueueTest {
return format.drmInitData != null ? mockDrmSession : mockPlaceholderDrmSession; return format.drmInitData != null ? mockDrmSession : mockPlaceholderDrmSession;
} }
@Nullable
@Override @Override
public Class<? extends ExoMediaCrypto> getExoMediaCryptoType(Format format) { @C.CryptoType
public int getCryptoType(Format format) {
return mockPlaceholderDrmSession != null || format.drmInitData != null return mockPlaceholderDrmSession != null || format.drmInitData != null
? MockExoMediaCrypto.class ? FakeCryptoConfig.TYPE
: null; : C.CRYPTO_TYPE_NONE;
} }
} }
} }

View File

@ -34,12 +34,12 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.RendererConfiguration; import com.google.android.exoplayer2.RendererConfiguration;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.decoder.DecoderException; import com.google.android.exoplayer2.decoder.DecoderException;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.decoder.SimpleDecoder; import com.google.android.exoplayer2.decoder.SimpleDecoder;
import com.google.android.exoplayer2.drm.DrmSessionEventListener; import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.testutil.FakeSampleStream; import com.google.android.exoplayer2.testutil.FakeSampleStream;
import com.google.android.exoplayer2.upstream.DefaultAllocator; import com.google.android.exoplayer2.upstream.DefaultAllocator;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
@ -128,7 +128,7 @@ public final class DecoderVideoRendererTest {
VideoDecoderInputBuffer, VideoDecoderInputBuffer,
? extends VideoDecoderOutputBuffer, ? extends VideoDecoderOutputBuffer,
? extends DecoderException> ? extends DecoderException>
createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) { createDecoder(Format format, @Nullable CryptoConfig cryptoConfig) {
return new SimpleDecoder< return new SimpleDecoder<
VideoDecoderInputBuffer, VideoDecoderOutputBuffer, DecoderException>( VideoDecoderInputBuffer, VideoDecoderOutputBuffer, DecoderException>(
new VideoDecoderInputBuffer[10], new VideoDecoderOutputBuffer[10]) { new VideoDecoderInputBuffer[10], new VideoDecoderOutputBuffer[10]) {

View File

@ -667,8 +667,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
Format[] formats = new Format[representations.size()]; Format[] formats = new Format[representations.size()];
for (int j = 0; j < formats.length; j++) { for (int j = 0; j < formats.length; j++) {
Format format = representations.get(j).format; Format format = representations.get(j).format;
formats[j] = formats[j] = format.copyWithCryptoType(drmSessionManager.getCryptoType(format));
format.copyWithExoMediaCryptoType(drmSessionManager.getExoMediaCryptoType(format));
} }
AdaptationSet firstAdaptationSet = adaptationSets.get(adaptationSetIndices[0]); AdaptationSet firstAdaptationSet = adaptationSets.get(adaptationSetIndices[0]);

View File

@ -1411,8 +1411,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
Format[] exposedFormats = new Format[trackGroup.length]; Format[] exposedFormats = new Format[trackGroup.length];
for (int j = 0; j < trackGroup.length; j++) { for (int j = 0; j < trackGroup.length; j++) {
Format format = trackGroup.getFormat(j); Format format = trackGroup.getFormat(j);
exposedFormats[j] = exposedFormats[j] = format.copyWithCryptoType(drmSessionManager.getCryptoType(format));
format.copyWithExoMediaCryptoType(drmSessionManager.getExoMediaCryptoType(format));
} }
trackGroups[i] = new TrackGroup(exposedFormats); trackGroups[i] = new TrackGroup(exposedFormats);
} }

View File

@ -261,8 +261,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
for (int j = 0; j < manifestFormats.length; j++) { for (int j = 0; j < manifestFormats.length; j++) {
Format manifestFormat = manifestFormats[j]; Format manifestFormat = manifestFormats[j];
exposedFormats[j] = exposedFormats[j] =
manifestFormat.copyWithExoMediaCryptoType( manifestFormat.copyWithCryptoType(drmSessionManager.getCryptoType(manifestFormat));
drmSessionManager.getExoMediaCryptoType(manifestFormat));
} }
trackGroups[i] = new TrackGroup(exposedFormats); trackGroups[i] = new TrackGroup(exposedFormats);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2020 The Android Open Source Project * Copyright (C) 2021 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -13,7 +13,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.android.exoplayer2.drm; package com.google.android.exoplayer2.testutil;
/** {@link ExoMediaCrypto} type that cannot be used to handle any type of protected content. */ import com.google.android.exoplayer2.C;
public final class UnsupportedMediaCrypto implements ExoMediaCrypto {} import com.google.android.exoplayer2.decoder.CryptoConfig;
/** Fake {@link CryptoConfig}. */
public final class FakeCryptoConfig implements CryptoConfig {
public static final int TYPE = C.CRYPTO_TYPE_CUSTOM_BASE;
}

View File

@ -26,8 +26,9 @@ import android.os.Parcelable;
import android.os.PersistableBundle; import android.os.PersistableBundle;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.decoder.CryptoConfig;
import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.drm.ExoMediaDrm; import com.google.android.exoplayer2.drm.ExoMediaDrm;
import com.google.android.exoplayer2.drm.MediaDrmCallback; import com.google.android.exoplayer2.drm.MediaDrmCallback;
import com.google.android.exoplayer2.drm.MediaDrmCallbackException; import com.google.android.exoplayer2.drm.MediaDrmCallbackException;
@ -334,15 +335,16 @@ public final class FakeExoMediaDrm implements ExoMediaDrm {
} }
@Override @Override
public ExoMediaCrypto createMediaCrypto(byte[] sessionId) throws MediaCryptoException { public CryptoConfig createCryptoConfig(byte[] sessionId) throws MediaCryptoException {
Assertions.checkState(referenceCount > 0); Assertions.checkState(referenceCount > 0);
Assertions.checkState(openSessionIds.contains(toByteList(sessionId))); Assertions.checkState(openSessionIds.contains(toByteList(sessionId)));
return new FakeExoMediaCrypto(); return new FakeCryptoConfig();
} }
@Override @Override
public Class<FakeExoMediaCrypto> getExoMediaCryptoType() { @C.CryptoType
return FakeExoMediaCrypto.class; public int getCryptoType() {
return FakeCryptoConfig.TYPE;
} }
// Methods to facilitate testing // Methods to facilitate testing
@ -389,8 +391,6 @@ public final class FakeExoMediaDrm implements ExoMediaDrm {
return ImmutableList.copyOf(Bytes.asList(byteArray)); return ImmutableList.copyOf(Bytes.asList(byteArray));
} }
private static class FakeExoMediaCrypto implements ExoMediaCrypto {}
/** An license server implementation to interact with {@link FakeExoMediaDrm}. */ /** An license server implementation to interact with {@link FakeExoMediaDrm}. */
public static class LicenseServer implements MediaDrmCallback { public static class LicenseServer implements MediaDrmCallback {