diff --git a/extensions/av1/src/main/java/com/google/android/exoplayer2/ext/av1/Libgav1VideoRenderer.java b/extensions/av1/src/main/java/com/google/android/exoplayer2/ext/av1/Libgav1VideoRenderer.java index a083cd8414..fc7d6b6091 100644 --- a/extensions/av1/src/main/java/com/google/android/exoplayer2/ext/av1/Libgav1VideoRenderer.java +++ b/extensions/av1/src/main/java/com/google/android/exoplayer2/ext/av1/Libgav1VideoRenderer.java @@ -23,8 +23,8 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; 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.drm.ExoMediaCrypto; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.TraceUtil; import com.google.android.exoplayer2.util.Util; @@ -132,7 +132,7 @@ public class Libgav1VideoRenderer extends DecoderVideoRenderer { || !Gav1Library.isAvailable()) { 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( @@ -140,7 +140,7 @@ public class Libgav1VideoRenderer extends DecoderVideoRenderer { } @Override - protected Gav1Decoder createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) + protected Gav1Decoder createDecoder(Format format, @Nullable CryptoConfig cryptoConfig) throws Gav1DecoderException { TraceUtil.beginSection("createGav1Decoder"); int initialInputBufferSize = diff --git a/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java b/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java index 3991f53a38..a124c679c4 100644 --- a/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java +++ b/extensions/ffmpeg/src/main/java/com/google/android/exoplayer2/ext/ffmpeg/FfmpegAudioRenderer.java @@ -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.DecoderAudioRenderer; 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.MimeTypes; import com.google.android.exoplayer2.util.TraceUtil; @@ -97,7 +97,7 @@ public final class FfmpegAudioRenderer extends DecoderAudioRenderer - createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) + createDecoder(Format format, @Nullable CryptoConfig cryptoConfig) throws FfmpegDecoderException { TraceUtil.beginSection("createFfmpegVideoDecoder"); // TODO: Implement, remove the SuppressWarnings annotation, and update the return type to use diff --git a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/LibflacAudioRenderer.java b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/LibflacAudioRenderer.java index 7b74d3bfd7..4c6d9f4c5b 100644 --- a/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/LibflacAudioRenderer.java +++ b/extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/LibflacAudioRenderer.java @@ -23,7 +23,7 @@ import com.google.android.exoplayer2.audio.AudioProcessor; import com.google.android.exoplayer2.audio.AudioRendererEventListener; import com.google.android.exoplayer2.audio.AudioSink; 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.util.FlacConstants; import com.google.android.exoplayer2.util.MimeTypes; @@ -100,7 +100,7 @@ public final class LibflacAudioRenderer extends DecoderAudioRenderer { @Override @C.FormatSupport protected int supportsFormatInternal(Format format) { - boolean drmIsSupported = - format.exoMediaCryptoType == null - || OpusLibrary.matchesExpectedExoMediaCryptoType(format.exoMediaCryptoType); + boolean drmIsSupported = OpusLibrary.supportsCryptoType(format.cryptoType); if (!OpusLibrary.isAvailable() || !MimeTypes.AUDIO_OPUS.equalsIgnoreCase(format.sampleMimeType)) { return C.FORMAT_UNSUPPORTED_TYPE; @@ -98,7 +96,7 @@ public class LibopusAudioRenderer extends DecoderAudioRenderer { } @Override - protected OpusDecoder createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) + protected OpusDecoder createDecoder(Format format, @Nullable CryptoConfig cryptoConfig) throws OpusDecoderException { TraceUtil.beginSection("createOpusDecoder"); @SinkFormatSupport @@ -115,7 +113,7 @@ public class LibopusAudioRenderer extends DecoderAudioRenderer { NUM_BUFFERS, initialInputBufferSize, format.initializationData, - mediaCrypto, + cryptoConfig, outputFloat); TraceUtil.endSection(); diff --git a/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoder.java b/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoder.java index cb81ea7f97..2cea08df14 100644 --- a/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoder.java +++ b/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusDecoder.java @@ -21,12 +21,12 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.google.android.exoplayer2.C; 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.CryptoInfo; import com.google.android.exoplayer2.decoder.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.SimpleDecoder; 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.Util; import java.nio.ByteBuffer; @@ -44,7 +44,7 @@ public final class OpusDecoder public final boolean outputFloat; public final int channelCount; - @Nullable private final ExoMediaCrypto exoMediaCrypto; + @Nullable private final CryptoConfig cryptoConfig; private final int preSkipSamples; private final int seekPreRollSamples; private final long nativeDecoderContext; @@ -60,8 +60,8 @@ public final class OpusDecoder * @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 * the encoder delay and seek pre roll values in nanoseconds, encoded as longs. - * @param exoMediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted - * content. Maybe null and can be ignored if decoder does not handle 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. * @param outputFloat Forces the decoder to output float PCM samples when set * @throws OpusDecoderException Thrown if an exception occurs when initializing the decoder. */ @@ -70,15 +70,15 @@ public final class OpusDecoder int numOutputBuffers, int initialInputBufferSize, List initializationData, - @Nullable ExoMediaCrypto exoMediaCrypto, + @Nullable CryptoConfig cryptoConfig, boolean outputFloat) throws OpusDecoderException { super(new DecoderInputBuffer[numInputBuffers], new SimpleOutputBuffer[numOutputBuffers]); if (!OpusLibrary.isAvailable()) { throw new OpusDecoderException("Failed to load decoder native libraries"); } - this.exoMediaCrypto = exoMediaCrypto; - if (exoMediaCrypto != null && !OpusLibrary.opusIsSecureDecodeSupported()) { + this.cryptoConfig = cryptoConfig; + if (cryptoConfig != null && !OpusLibrary.opusIsSecureDecodeSupported()) { throw new OpusDecoderException("Opus decoder does not support secure decode"); } int initializationDataSize = initializationData.size(); @@ -177,7 +177,7 @@ public final class OpusDecoder inputData.limit(), outputBuffer, OpusUtil.SAMPLE_RATE, - exoMediaCrypto, + cryptoConfig, cryptoInfo.mode, Assertions.checkNotNull(cryptoInfo.key), Assertions.checkNotNull(cryptoInfo.iv), @@ -248,7 +248,7 @@ public final class OpusDecoder int inputSize, SimpleOutputBuffer outputBuffer, int sampleRate, - @Nullable ExoMediaCrypto mediaCrypto, + @Nullable CryptoConfig mediaCrypto, int inputMode, byte[] key, byte[] iv, diff --git a/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusLibrary.java b/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusLibrary.java index 47b1cef657..01162bf365 100644 --- a/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusLibrary.java +++ b/extensions/opus/src/main/java/com/google/android/exoplayer2/ext/opus/OpusLibrary.java @@ -16,10 +16,9 @@ package com.google.android.exoplayer2.ext.opus; import androidx.annotation.Nullable; +import com.google.android.exoplayer2.C; 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.Util; /** Configures and queries the underlying native library. */ public final class OpusLibrary { @@ -29,7 +28,7 @@ public final class OpusLibrary { } private static final LibraryLoader LOADER = new LibraryLoader("opusV2JNI"); - @Nullable private static Class exoMediaCryptoType; + @C.CryptoType private static int cryptoType = C.CRYPTO_TYPE_UNSUPPORTED; 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 * {@link LibopusAudioRenderer} instance. * - * @param exoMediaCryptoType The {@link ExoMediaCrypto} type expected for decoding protected - * content. + * @param cryptoType The {@link C.CryptoType} for which the decoder library supports decrypting + * protected content, or {@link C#CRYPTO_TYPE_UNSUPPORTED} if the library does not support + * decryption. * @param libraries The names of the Opus native libraries. */ - public static void setLibraries( - Class exoMediaCryptoType, String... libraries) { + public static void setLibraries(@C.CryptoType int cryptoType, String... libraries) { + OpusLibrary.cryptoType = cryptoType; LOADER.setLibraries(libraries); - OpusLibrary.exoMediaCryptoType = exoMediaCryptoType; } /** Returns whether the underlying library is available, loading it if necessary. */ @@ -59,13 +58,10 @@ public final class OpusLibrary { return isAvailable() ? opusGetVersion() : null; } - /** - * Returns whether the given {@link ExoMediaCrypto} type matches the one required for decoding - * protected content. - */ - public static boolean matchesExpectedExoMediaCryptoType( - Class exoMediaCryptoType) { - return Util.areEqual(OpusLibrary.exoMediaCryptoType, exoMediaCryptoType); + /** Returns whether the library supports the given {@link C.CryptoType}. */ + public static boolean supportsCryptoType(@C.CryptoType int cryptoType) { + return cryptoType == C.CRYPTO_TYPE_NONE + || (cryptoType != C.CRYPTO_TYPE_UNSUPPORTED && cryptoType == OpusLibrary.cryptoType); } public static native String opusGetVersion(); diff --git a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java index 610f2f84e4..218b3b779e 100644 --- a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java +++ b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java @@ -24,8 +24,8 @@ import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; 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.drm.ExoMediaCrypto; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.TraceUtil; 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)) { return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE); } - boolean drmIsSupported = - format.exoMediaCryptoType == null - || VpxLibrary.matchesExpectedExoMediaCryptoType(format.exoMediaCryptoType); + boolean drmIsSupported = VpxLibrary.supportsCryptoType(format.cryptoType); if (!drmIsSupported) { return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_DRM); } @@ -140,14 +138,14 @@ public class LibvpxVideoRenderer extends DecoderVideoRenderer { } @Override - protected VpxDecoder createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) + protected VpxDecoder createDecoder(Format format, @Nullable CryptoConfig cryptoConfig) throws VpxDecoderException { TraceUtil.beginSection("createVpxDecoder"); int initialInputBufferSize = format.maxInputSize != Format.NO_VALUE ? format.maxInputSize : DEFAULT_INPUT_BUFFER_SIZE; VpxDecoder decoder = new VpxDecoder( - numInputBuffers, numOutputBuffers, initialInputBufferSize, mediaCrypto, threads); + numInputBuffers, numOutputBuffers, initialInputBufferSize, cryptoConfig, threads); this.decoder = decoder; TraceUtil.endSection(); return decoder; diff --git a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxDecoder.java b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxDecoder.java index 06d8020a2d..78b9c96e37 100644 --- a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxDecoder.java +++ b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxDecoder.java @@ -21,11 +21,11 @@ import android.view.Surface; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; 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.CryptoInfo; import com.google.android.exoplayer2.decoder.DecoderInputBuffer; 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.Util; 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 DRM_ERROR = -2; - @Nullable private final ExoMediaCrypto exoMediaCrypto; + @Nullable private final CryptoConfig cryptoConfig; private final long vpxDecContext; @Nullable private ByteBuffer lastSupplementalData; @@ -56,8 +56,8 @@ public final class VpxDecoder * @param numInputBuffers The number of input buffers. * @param numOutputBuffers The number of output buffers. * @param initialInputBufferSize The initial size of each input buffer. - * @param exoMediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted - * content. Maybe null and can be ignored if decoder does not handle 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. * @param threads Number of threads libvpx will use to decode. * @throws VpxDecoderException Thrown if an exception occurs when initializing the decoder. */ @@ -65,7 +65,7 @@ public final class VpxDecoder int numInputBuffers, int numOutputBuffers, int initialInputBufferSize, - @Nullable ExoMediaCrypto exoMediaCrypto, + @Nullable CryptoConfig cryptoConfig, int threads) throws VpxDecoderException { super( @@ -74,8 +74,8 @@ public final class VpxDecoder if (!VpxLibrary.isAvailable()) { throw new VpxDecoderException("Failed to load decoder native libraries."); } - this.exoMediaCrypto = exoMediaCrypto; - if (exoMediaCrypto != null && !VpxLibrary.vpxIsSecureDecodeSupported()) { + this.cryptoConfig = cryptoConfig; + if (cryptoConfig != null && !VpxLibrary.vpxIsSecureDecodeSupported()) { throw new VpxDecoderException("Vpx decoder does not support secure decode."); } vpxDecContext = @@ -134,7 +134,7 @@ public final class VpxDecoder vpxDecContext, inputData, inputSize, - exoMediaCrypto, + cryptoConfig, cryptoInfo.mode, Assertions.checkNotNull(cryptoInfo.key), Assertions.checkNotNull(cryptoInfo.iv), @@ -215,7 +215,7 @@ public final class VpxDecoder long context, ByteBuffer encoded, int length, - @Nullable ExoMediaCrypto mediaCrypto, + @Nullable CryptoConfig mediaCrypto, int inputMode, byte[] key, byte[] iv, diff --git a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxLibrary.java b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxLibrary.java index 8325265685..ebaa16fa73 100644 --- a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxLibrary.java +++ b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/VpxLibrary.java @@ -16,10 +16,9 @@ package com.google.android.exoplayer2.ext.vp9; import androidx.annotation.Nullable; +import com.google.android.exoplayer2.C; 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.Util; /** Configures and queries the underlying native library. */ public final class VpxLibrary { @@ -29,7 +28,7 @@ public final class VpxLibrary { } private static final LibraryLoader LOADER = new LibraryLoader("vpx", "vpxV2JNI"); - @Nullable private static Class exoMediaCryptoType; + @C.CryptoType private static int cryptoType = C.CRYPTO_TYPE_UNSUPPORTED; 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 * {@link LibvpxVideoRenderer} instance. * - * @param exoMediaCryptoType The {@link ExoMediaCrypto} type required for decoding protected - * content. + * @param cryptoType The {@link C.CryptoType} for which the decoder library supports decrypting + * protected content, or {@link C#CRYPTO_TYPE_UNSUPPORTED} if the library does not support + * decryption. * @param libraries The names of the Vpx native libraries. */ - public static void setLibraries( - Class exoMediaCryptoType, String... libraries) { + public static void setLibraries(@C.CryptoType int cryptoType, String... libraries) { + VpxLibrary.cryptoType = cryptoType; LOADER.setLibraries(libraries); - VpxLibrary.exoMediaCryptoType = exoMediaCryptoType; } /** Returns whether the underlying library is available, loading it if necessary. */ @@ -75,13 +74,10 @@ public final class VpxLibrary { return indexHbd >= 0; } - /** - * Returns whether the given {@link ExoMediaCrypto} type matches the one required for decoding - * protected content. - */ - public static boolean matchesExpectedExoMediaCryptoType( - Class exoMediaCryptoType) { - return Util.areEqual(VpxLibrary.exoMediaCryptoType, exoMediaCryptoType); + /** Returns whether the library supports the given {@link C.CryptoType}. */ + public static boolean supportsCryptoType(@C.CryptoType int cryptoType) { + return cryptoType == C.CRYPTO_TYPE_NONE + || (cryptoType != C.CRYPTO_TYPE_UNSUPPORTED && cryptoType == VpxLibrary.cryptoType); } private static native String vpxGetVersion(); diff --git a/library/common/src/main/java/com/google/android/exoplayer2/C.java b/library/common/src/main/java/com/google/android/exoplayer2/C.java index 5c7cdca992..35c61faf81 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/C.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/C.java @@ -20,6 +20,7 @@ import android.media.AudioAttributes; import android.media.AudioFormat; import android.media.AudioManager; import android.media.MediaCodec; +import android.media.MediaCrypto; import android.media.MediaFormat; import android.view.Surface; import androidx.annotation.IntDef; @@ -116,6 +117,33 @@ public final class C { /** The name of the sans-serif font family. */ 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} * or {@link #CRYPTO_MODE_AES_CBC}. diff --git a/library/common/src/main/java/com/google/android/exoplayer2/Format.java b/library/common/src/main/java/com/google/android/exoplayer2/Format.java index 6fcc34b11f..18f2c5b0b8 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/Format.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/Format.java @@ -19,8 +19,6 @@ import android.os.Bundle; import androidx.annotation.IntDef; import androidx.annotation.Nullable; 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.util.BundleableUtils; import com.google.android.exoplayer2.util.MimeTypes; @@ -174,7 +172,7 @@ public final class Format implements Bundleable { // Provided by the source. - @Nullable private Class exoMediaCryptoType; + @C.CryptoType private int cryptoType; /** Creates a new instance with default values. */ public Builder() { @@ -195,6 +193,8 @@ public final class Format implements Bundleable { pcmEncoding = NO_VALUE; // Text specific. accessibilityChannel = NO_VALUE; + // Provided by the source. + cryptoType = C.CRYPTO_TYPE_NONE; } /** @@ -238,7 +238,7 @@ public final class Format implements Bundleable { // Text specific. this.accessibilityChannel = format.accessibilityChannel; // 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. /** - * 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. */ - public Builder setExoMediaCryptoType( - @Nullable Class exoMediaCryptoType) { - this.exoMediaCryptoType = exoMediaCryptoType; + public Builder setCryptoType(@C.CryptoType int cryptoType) { + this.cryptoType = cryptoType; return this; } @@ -756,11 +755,12 @@ public final class Format implements Bundleable { // Provided by source. /** - * The type of {@link ExoMediaCrypto} that will be associated with the content this format - * describes, or {@code null} if the content is not encrypted. Cannot be null if {@link - * #drmInitData} is non-null. + * The type of crypto that must be used to decode samples associated with this format, or {@link + * C#CRYPTO_TYPE_NONE} if the content is not encrypted. Cannot be {@link C#CRYPTO_TYPE_NONE} if + * {@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 exoMediaCryptoType; + @C.CryptoType public final int cryptoType; // Lazily initialized hashcode. private int hashCode; @@ -964,11 +964,11 @@ public final class Format implements Bundleable { // Text specific. accessibilityChannel = builder.accessibilityChannel; // Provided by source. - if (builder.exoMediaCryptoType == null && drmInitData != null) { - // Encrypted content must always have a non-null exoMediaCryptoType. - exoMediaCryptoType = UnsupportedMediaCrypto.class; + if (builder.cryptoType == C.CRYPTO_TYPE_NONE && drmInitData != null) { + // Encrypted content cannot use CRYPTO_TYPE_NONE. + cryptoType = C.CRYPTO_TYPE_UNSUPPORTED; } else { - exoMediaCryptoType = builder.exoMediaCryptoType; + cryptoType = builder.cryptoType; } } @@ -1113,10 +1113,9 @@ public final class Format implements Bundleable { return buildUpon().setWidth(width).setHeight(height).build(); } - /** Returns a copy of this format with the specified {@link #exoMediaCryptoType}. */ - public Format copyWithExoMediaCryptoType( - @Nullable Class exoMediaCryptoType) { - return buildUpon().setExoMediaCryptoType(exoMediaCryptoType).build(); + /** Returns a copy of this format with the specified {@link #cryptoType}. */ + public Format copyWithCryptoType(@C.CryptoType int cryptoType) { + return buildUpon().setCryptoType(cryptoType).build(); } /** @@ -1197,7 +1196,7 @@ public final class Format implements Bundleable { // Text specific. result = 31 * result + accessibilityChannel; // Provided by the source. - result = 31 * result + (exoMediaCryptoType == null ? 0 : exoMediaCryptoType.hashCode()); + result = 31 * result + cryptoType; hashCode = result; } return hashCode; @@ -1232,9 +1231,9 @@ public final class Format implements Bundleable { && encoderDelay == other.encoderDelay && encoderPadding == other.encoderPadding && accessibilityChannel == other.accessibilityChannel + && cryptoType == other.cryptoType && Float.compare(frameRate, other.frameRate) == 0 && Float.compare(pixelWidthHeightRatio, other.pixelWidthHeightRatio) == 0 - && Util.areEqual(exoMediaCryptoType, other.exoMediaCryptoType) && Util.areEqual(id, other.id) && Util.areEqual(label, other.label) && Util.areEqual(codecs, other.codecs) @@ -1360,6 +1359,7 @@ public final class Format implements Bundleable { FIELD_ENCODER_DELAY, FIELD_ENCODER_PADDING, FIELD_ACCESSIBILITY_CHANNEL, + FIELD_CRYPTO_TYPE, }) 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_PADDING = 27; private static final int FIELD_ACCESSIBILITY_CHANNEL = 28; + private static final int FIELD_CRYPTO_TYPE = 29; - /** - * {@inheritDoc} - * - *

Omits the {@link #exoMediaCryptoType} field. The {@link #exoMediaCryptoType} of an instance - * restored by {@link #CREATOR} will always be {@link UnsupportedMediaCrypto}. - */ @Override public Bundle toBundle() { Bundle bundle = new Bundle(); @@ -1443,6 +1438,8 @@ public final class Format implements Bundleable { bundle.putInt(keyForField(FIELD_ENCODER_PADDING), encoderPadding); // Text specific. bundle.putInt(keyForField(FIELD_ACCESSIBILITY_CHANNEL), accessibilityChannel); + // Source specific. + bundle.putInt(keyForField(FIELD_CRYPTO_TYPE), cryptoType); return bundle; } @@ -1512,7 +1509,9 @@ public final class Format implements Bundleable { bundle.getInt(keyForField(FIELD_ENCODER_PADDING), DEFAULT.encoderPadding)) // Text specific. .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(); } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/drm/ExoMediaCrypto.java b/library/common/src/main/java/com/google/android/exoplayer2/decoder/CryptoConfig.java similarity index 70% rename from library/common/src/main/java/com/google/android/exoplayer2/drm/ExoMediaCrypto.java rename to library/common/src/main/java/com/google/android/exoplayer2/decoder/CryptoConfig.java index 27730c14b3..bc592b26a1 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/drm/ExoMediaCrypto.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/decoder/CryptoConfig.java @@ -13,7 +13,12 @@ * See the License for the specific language governing permissions and * 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. */ -public interface ExoMediaCrypto {} +import com.google.android.exoplayer2.C; + +/** + * Configuration for a decoder to allow it to decode encrypted media data. The configuration is + * {@link C.CryptoType} specific. + */ +public interface CryptoConfig {} diff --git a/library/common/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java b/library/common/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java index b4e04afe42..f4c57f061c 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/decoder/CryptoInfo.java @@ -21,7 +21,11 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Util; -/** Compatibility wrapper for {@link android.media.MediaCodec.CryptoInfo}. */ +/** + * Metadata describing the structure of an encrypted input sample. + * + *

This class is a compatibility wrapper for {@link android.media.MediaCodec.CryptoInfo}. + */ public final class CryptoInfo { /** diff --git a/library/common/src/test/java/com/google/android/exoplayer2/FormatTest.java b/library/common/src/test/java/com/google/android/exoplayer2/FormatTest.java index 87fc725029..fbc40afd12 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/FormatTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/FormatTest.java @@ -22,8 +22,6 @@ import static com.google.common.truth.Truth.assertThat; import androidx.test.ext.junit.runners.AndroidJUnit4; 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.id3.TextInformationFrame; import com.google.android.exoplayer2.util.MimeTypes; @@ -45,15 +43,11 @@ public final class FormatTest { } @Test - public void roundTripViaBundle_ofParameters_yieldsEqualInstanceExceptExoMediaCryptoType() { + public void roundTripViaBundle_ofParameters_yieldsEqualInstance() { Format formatToBundle = createTestFormat(); - Format formatFromBundle = Format.CREATOR.fromBundle(formatToBundle.toBundle()); - assertThat(formatFromBundle.exoMediaCryptoType).isEqualTo(UnsupportedMediaCrypto.class); - assertThat(formatFromBundle) - .isEqualTo( - formatToBundle.buildUpon().setExoMediaCryptoType(UnsupportedMediaCrypto.class).build()); + assertThat(formatFromBundle).isEqualTo(formatToBundle); } private static Format createTestFormat() { @@ -93,7 +87,7 @@ public final class FormatTest { .setPeakBitrate(2048) .setCodecs("codec") .setMetadata(metadata) - .setContainerMimeType(MimeTypes.VIDEO_MP4) + .setContainerMimeType(VIDEO_MP4) .setSampleMimeType(MimeTypes.VIDEO_H264) .setMaxInputSize(5000) .setInitializationData(initializationData) @@ -113,7 +107,7 @@ public final class FormatTest { .setEncoderDelay(1001) .setEncoderPadding(1002) .setAccessibilityChannel(2) - .setExoMediaCryptoType(ExoMediaCrypto.class) + .setCryptoType(C.CRYPTO_TYPE_CUSTOM_BASE) .build(); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java index 3c8d25e70f..e5b306aff1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/DecoderAudioRenderer.java @@ -38,6 +38,7 @@ import com.google.android.exoplayer2.PlayerMessage.Target; import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.audio.AudioRendererEventListener.EventDispatcher; 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.DecoderCounters; 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.drm.DrmSession; 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.util.Assertions; import com.google.android.exoplayer2.util.Log; @@ -330,12 +330,12 @@ public abstract class DecoderAudioRenderer< * Creates a decoder for the given format. * * @param format The format for which a decoder is required. - * @param mediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted content. - * Maybe null and can be ignored if decoder does not handle 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. * @return The 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; /** @@ -603,10 +603,10 @@ public abstract class DecoderAudioRenderer< setDecoderDrmSession(sourceDrmSession); - ExoMediaCrypto mediaCrypto = null; + CryptoConfig cryptoConfig = null; if (decoderDrmSession != null) { - mediaCrypto = decoderDrmSession.getMediaCrypto(); - if (mediaCrypto == null) { + cryptoConfig = decoderDrmSession.getCryptoConfig(); + if (cryptoConfig == null) { DrmSessionException drmError = decoderDrmSession.getError(); if (drmError != null) { // 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 { long codecInitializingTimestamp = SystemClock.elapsedRealtime(); TraceUtil.beginSection("createAudioDecoder"); - decoder = createDecoder(inputFormat, mediaCrypto); + decoder = createDecoder(inputFormat, cryptoConfig); TraceUtil.endSection(); long codecInitializedTimestamp = SystemClock.elapsedRealtime(); eventDispatcher.decoderInitialized( diff --git a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java index db00fd1121..b3de393abb 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/audio/MediaCodecAudioRenderer.java @@ -272,7 +272,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media } @TunnelingSupport 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); // 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. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java index 47483a027d..5e5bce8340 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSession.java @@ -31,6 +31,7 @@ import androidx.annotation.GuardedBy; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; 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.ExoMediaDrm.KeyRequest; import com.google.android.exoplayer2.drm.ExoMediaDrm.ProvisionRequest; @@ -141,7 +142,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; private int referenceCount; @Nullable private HandlerThread requestHandlerThread; @Nullable private RequestHandler requestHandler; - @Nullable private ExoMediaCrypto mediaCrypto; + @Nullable private CryptoConfig cryptoConfig; @Nullable private DrmSessionException lastException; @Nullable private byte[] sessionId; private byte @MonotonicNonNull [] offlineLicenseKeySetId; @@ -260,7 +261,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } @Override - public final @Nullable DrmSessionException getError() { + @Nullable + public final DrmSessionException getError() { return state == STATE_ERROR ? lastException : null; } @@ -270,8 +272,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } @Override - public final @Nullable ExoMediaCrypto getMediaCrypto() { - return mediaCrypto; + @Nullable + public final CryptoConfig getCryptoConfig() { + return cryptoConfig; } @Override @@ -326,7 +329,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; requestHandler = null; Util.castNonNull(requestHandlerThread).quit(); requestHandlerThread = null; - mediaCrypto = null; + cryptoConfig = null; lastException = null; currentKeyRequest = null; currentProvisionRequest = null; @@ -361,7 +364,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; try { sessionId = mediaDrm.openSession(); - mediaCrypto = mediaDrm.createMediaCrypto(sessionId); + cryptoConfig = mediaDrm.createCryptoConfig(sessionId); state = STATE_OPENED; // Capture state into a local so a consistent value is seen by the lambda. int localState = state; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java index 774e91eee8..1ea5fed05e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java @@ -579,19 +579,16 @@ public class DefaultDrmSessionManager implements DrmSessionManager { } @Override - @Nullable - public Class getExoMediaCryptoType(Format format) { - Class exoMediaCryptoType = - checkNotNull(exoMediaDrm).getExoMediaCryptoType(); + @C.CryptoType + public int getCryptoType(Format format) { + @C.CryptoType int cryptoType = checkNotNull(exoMediaDrm).getCryptoType(); if (format.drmInitData == null) { int trackType = MimeTypes.getTrackType(format.sampleMimeType); return Util.linearSearch(useDrmSessionsForClearContentTrackTypes, trackType) != C.INDEX_UNSET - ? exoMediaCryptoType - : null; + ? cryptoType + : C.CRYPTO_TYPE_NONE; } else { - return canAcquireSession(format.drmInitData) - ? exoMediaCryptoType - : UnsupportedMediaCrypto.class; + return canAcquireSession(format.drmInitData) ? cryptoType : C.CRYPTO_TYPE_UNSUPPORTED; } } @@ -602,12 +599,12 @@ public class DefaultDrmSessionManager implements DrmSessionManager { int trackType, boolean shouldReleasePreacquiredSessionsBeforeRetrying) { ExoMediaDrm exoMediaDrm = checkNotNull(this.exoMediaDrm); boolean avoidPlaceholderDrmSessions = - FrameworkMediaCrypto.class.equals(exoMediaDrm.getExoMediaCryptoType()) - && FrameworkMediaCrypto.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC; + exoMediaDrm.getCryptoType() == C.CRYPTO_TYPE_FRAMEWORK + && FrameworkCryptoConfig.WORKAROUND_DEVICE_NEEDS_KEYS_TO_CONFIGURE_CODEC; // Avoid attaching a session to sparse formats. if (avoidPlaceholderDrmSessions || Util.linearSearch(useDrmSessionsForClearContentTrackTypes, trackType) == C.INDEX_UNSET - || UnsupportedMediaCrypto.class.equals(exoMediaDrm.getExoMediaCryptoType())) { + || exoMediaDrm.getCryptoType() == C.CRYPTO_TYPE_UNSUPPORTED) { return null; } if (placeholderDrmSession == null) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java index 7f07fd9c66..7582b0c848 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSession.java @@ -19,6 +19,7 @@ import android.media.MediaDrm; import androidx.annotation.IntDef; import androidx.annotation.Nullable; import com.google.android.exoplayer2.PlaybackException; +import com.google.android.exoplayer2.decoder.CryptoConfig; import java.io.IOException; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -109,11 +110,11 @@ public interface DrmSession { UUID getSchemeUuid(); /** - * Returns an {@link ExoMediaCrypto} for the open session, or null if called before the session - * has been opened or after it's been released. + * Returns a {@link CryptoConfig} for the open session, or null if called before the session has + * been opened or after it's been released. */ @Nullable - ExoMediaCrypto getMediaCrypto(); + CryptoConfig getCryptoConfig(); /** * Returns a map describing the key status for the session, or null if called before the session diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSessionManager.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSessionManager.java index b056f6ab0d..59f9a37982 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSessionManager.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DrmSessionManager.java @@ -17,6 +17,7 @@ package com.google.android.exoplayer2.drm; import android.os.Looper; import androidx.annotation.Nullable; +import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.PlaybackException; @@ -61,9 +62,9 @@ public interface DrmSessionManager { } @Override - @Nullable - public Class getExoMediaCryptoType(Format format) { - return format.drmInitData != null ? UnsupportedMediaCrypto.class : null; + @C.CryptoType + public int getCryptoType(Format format) { + return format.drmInitData != null ? C.CRYPTO_TYPE_UNSUPPORTED : C.CRYPTO_TYPE_NONE; } }; @@ -171,19 +172,18 @@ public interface DrmSessionManager { Format format); /** - * Returns the {@link ExoMediaCrypto} type associated to sessions acquired for the given {@link - * Format}. Returns the {@link UnsupportedMediaCrypto} type if this DRM session manager does not - * support any of the DRM schemes defined in the given {@link Format}. Returns null if {@link - * Format#drmInitData} is null and {@link #acquireSession} would return null for the given {@link - * Format}. + * Returns the {@link C.CryptoType} that the DRM session manager will use for a given {@link + * Format}. Returns {@link C#CRYPTO_TYPE_UNSUPPORTED} if the manager does not support any of the + * DRM schemes defined in the {@link Format}. Returns {@link C#CRYPTO_TYPE_NONE} if {@link + * Format#drmInitData} is null and {@link #acquireSession} will return {@code null} for the given + * {@link 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}. + * @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 - Class getExoMediaCryptoType(Format format); + @C.CryptoType + int getCryptoType(Format format); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DummyExoMediaDrm.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DummyExoMediaDrm.java index b5c7692ab8..796ea15169 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DummyExoMediaDrm.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DummyExoMediaDrm.java @@ -19,6 +19,8 @@ import android.media.MediaDrmException; import android.os.PersistableBundle; import androidx.annotation.Nullable; 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 java.util.HashMap; import java.util.List; @@ -142,13 +144,14 @@ public final class DummyExoMediaDrm implements ExoMediaDrm { } @Override - public ExoMediaCrypto createMediaCrypto(byte[] sessionId) { + public CryptoConfig createCryptoConfig(byte[] sessionId) { // Should not be invoked. No session should exist. throw new IllegalStateException(); } @Override - public Class getExoMediaCryptoType() { - return UnsupportedMediaCrypto.class; + @C.CryptoType + public int getCryptoType() { + return C.CRYPTO_TYPE_UNSUPPORTED; } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/ErrorStateDrmSession.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/ErrorStateDrmSession.java index 51cb019432..239a62327d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/ErrorStateDrmSession.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/ErrorStateDrmSession.java @@ -17,6 +17,7 @@ package com.google.android.exoplayer2.drm; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.decoder.CryptoConfig; import com.google.android.exoplayer2.util.Assertions; import java.util.Map; import java.util.UUID; @@ -53,7 +54,7 @@ public final class ErrorStateDrmSession implements DrmSession { @Override @Nullable - public ExoMediaCrypto getMediaCrypto() { + public CryptoConfig getCryptoConfig() { return null; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java index 583fcf979a..6d6a0a821a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/ExoMediaDrm.java @@ -25,6 +25,8 @@ import android.os.Handler; import android.os.PersistableBundle; import androidx.annotation.IntDef; 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 java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -538,14 +540,19 @@ public interface ExoMediaDrm { 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. - * @return An {@link ExoMediaCrypto} for the given session. - * @throws MediaCryptoException If an {@link ExoMediaCrypto} could not be created. + * @return A {@link CryptoConfig} for the given session. + * @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 getExoMediaCryptoType(); + /** + * Returns the {@link C.CryptoType type} of {@link CryptoConfig} instances returned by {@link + * #createCryptoConfig}. + */ + @C.CryptoType + int getCryptoType(); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaCrypto.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkCryptoConfig.java similarity index 81% rename from library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaCrypto.java rename to library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkCryptoConfig.java index c139b522e9..4d824bec22 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaCrypto.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkCryptoConfig.java @@ -15,15 +15,19 @@ */ package com.google.android.exoplayer2.drm; +import android.media.MediaCodec; 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 java.util.UUID; /** - * An {@link ExoMediaCrypto} implementation that contains the necessary information to build or - * update a framework {@link MediaCrypto}. + * A {@link CryptoConfig} for {@link C#CRYPTO_TYPE_FRAMEWORK}. Contains the necessary information to + * 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 @@ -50,7 +54,7 @@ public final class FrameworkMediaCrypto implements ExoMediaCrypto { * @param forceAllowInsecureDecoderComponents Whether to allow use of insecure decoder components * even if the underlying platform says otherwise. */ - public FrameworkMediaCrypto( + public FrameworkCryptoConfig( UUID uuid, byte[] sessionId, boolean forceAllowInsecureDecoderComponents) { this.uuid = uuid; this.sessionId = sessionId; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java index 8c2b1c3a62..e4ccaf1853 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/FrameworkMediaDrm.java @@ -314,20 +314,21 @@ public final class FrameworkMediaDrm implements ExoMediaDrm { } @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 // indicate that it required secure video decoders [Internal ref: b/11428937]. boolean forceAllowInsecureDecoderComponents = Util.SDK_INT < 21 && C.WIDEVINE_UUID.equals(uuid) && "L3".equals(getPropertyString("securityLevel")); - return new FrameworkMediaCrypto( + return new FrameworkCryptoConfig( adjustUuid(uuid), sessionId, forceAllowInsecureDecoderComponents); } @Override - public Class getExoMediaCryptoType() { - return FrameworkMediaCrypto.class; + @C.CryptoType + public int getCryptoType() { + return C.CRYPTO_TYPE_FRAMEWORK; } private static SchemeData getSchemeData(UUID uuid, List schemeDatas) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java index 2100847c7b..ead65ded66 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java @@ -50,6 +50,7 @@ import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; 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.DecoderInputBuffer; 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.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException; -import com.google.android.exoplayer2.drm.ExoMediaCrypto; -import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; +import com.google.android.exoplayer2.drm.FrameworkCryptoConfig; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException; import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.SampleStream; @@ -545,8 +545,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer { if (codecDrmSession != null) { if (mediaCrypto == null) { @Nullable - FrameworkMediaCrypto sessionMediaCrypto = getFrameworkMediaCrypto(codecDrmSession); - if (sessionMediaCrypto == null) { + FrameworkCryptoConfig sessionCryptoConfig = getFrameworkCryptoConfig(codecDrmSession); + if (sessionCryptoConfig == null) { @Nullable DrmSessionException drmError = codecDrmSession.getError(); if (drmError != null) { // 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 { try { - mediaCrypto = new MediaCrypto(sessionMediaCrypto.uuid, sessionMediaCrypto.sessionId); + mediaCrypto = new MediaCrypto(sessionCryptoConfig.uuid, sessionCryptoConfig.sessionId); } catch (MediaCryptoException e) { throw createRendererException( e, inputFormat, PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR); } mediaCryptoRequiresSecureDecoder = - !sessionMediaCrypto.forceAllowInsecureDecoderComponents + !sessionCryptoConfig.forceAllowInsecureDecoderComponents && 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(); if (drmSessionState == DrmSession.STATE_ERROR) { DrmSessionException drmSessionException = @@ -1074,11 +1074,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { return codecInfos; } - /** - * Configures rendering where no codec is used. Called instead of {@link - * #configureCodec(MediaCodecInfo, MediaCodecAdapter, Format, MediaCrypto, float)} when no codec - * is used to render. - */ + /** Configures rendering where no codec is used. */ private void initBypass(Format format) { 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. */ protected static boolean supportsFormatDrm(Format format) { - return format.exoMediaCryptoType == null - || FrameworkMediaCrypto.class.equals(format.exoMediaCryptoType); + return format.cryptoType == C.CRYPTO_TYPE_NONE || format.cryptoType == C.CRYPTO_TYPE_FRAMEWORK; } /** @@ -2088,8 +2083,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer { // TODO: Add an API check once [Internal ref: b/128835874] is fixed. return true; } - @Nullable FrameworkMediaCrypto newMediaCrypto = getFrameworkMediaCrypto(newSession); - if (newMediaCrypto == null) { + @Nullable FrameworkCryptoConfig newCryptoConfig = getFrameworkCryptoConfig(newSession); + if (newCryptoConfig == null) { // 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 // 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; - if (newMediaCrypto.forceAllowInsecureDecoderComponents) { + if (newCryptoConfig.forceAllowInsecureDecoderComponents) { requiresSecureDecoder = false; } else { requiresSecureDecoder = newSession.requiresSecureDecoder(newFormat.sampleMimeType); @@ -2136,7 +2131,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { @RequiresApi(23) private void updateDrmSessionV23() throws ExoPlaybackException { try { - mediaCrypto.setMediaDrmSession(getFrameworkMediaCrypto(sourceDrmSession).sessionId); + mediaCrypto.setMediaDrmSession(getFrameworkCryptoConfig(sourceDrmSession).sessionId); } catch (MediaCryptoException e) { throw createRendererException(e, inputFormat, PlaybackException.ERROR_CODE_DRM_SYSTEM_ERROR); } @@ -2146,18 +2141,19 @@ public abstract class MediaCodecRenderer extends BaseRenderer { } @Nullable - private FrameworkMediaCrypto getFrameworkMediaCrypto(DrmSession drmSession) + private FrameworkCryptoConfig getFrameworkCryptoConfig(DrmSession drmSession) throws ExoPlaybackException { - @Nullable ExoMediaCrypto mediaCrypto = drmSession.getMediaCrypto(); - if (mediaCrypto != null && !(mediaCrypto instanceof FrameworkMediaCrypto)) { + @Nullable CryptoConfig cryptoConfig = drmSession.getCryptoConfig(); + if (cryptoConfig != null && !(cryptoConfig instanceof FrameworkCryptoConfig)) { // This should not happen if the track went through a supportsFormatDrm() check, during track // selection. throw createRendererException( - new IllegalArgumentException("Expecting FrameworkMediaCrypto but found: " + mediaCrypto), + new IllegalArgumentException( + "Expecting FrameworkCryptoConfig but found: " + cryptoConfig), inputFormat, PlaybackException.ERROR_CODE_DRM_SCHEME_UNSUPPORTED); } - return (FrameworkMediaCrypto) mediaCrypto; + return (FrameworkCryptoConfig) cryptoConfig; } /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java index afb32ee211..491bb59939 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/metadata/MetadataRenderer.java @@ -93,7 +93,7 @@ public final class MetadataRenderer extends BaseRenderer implements Callback { public int supportsFormat(Format format) { if (decoderFactory.supportsFormat(format)) { 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 { return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java index 2ffe134fa4..654b2212ec 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java @@ -783,9 +783,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; trackFormat = trackFormat.buildUpon().setAverageBitrate(icyHeaders.bitrate).build(); } } - trackFormat = - trackFormat.copyWithExoMediaCryptoType( - drmSessionManager.getExoMediaCryptoType(trackFormat)); + trackFormat = trackFormat.copyWithCryptoType(drmSessionManager.getCryptoType(trackFormat)); trackArray[i] = new TrackGroup(trackFormat); } trackState = new TrackState(new TrackGroupArray(trackArray), trackIsAudioVideoFlags); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java index 7b5c6a35f7..4207fcfbae 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java @@ -899,8 +899,7 @@ public class SampleQueue implements TrackOutput { outputFormatHolder.format = drmSessionManager != null - ? newFormat.copyWithExoMediaCryptoType( - drmSessionManager.getExoMediaCryptoType(newFormat)) + ? newFormat.copyWithCryptoType(drmSessionManager.getCryptoType(newFormat)) : newFormat; outputFormatHolder.drmSession = currentDrmSession; if (drmSessionManager == null) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java index 5a27d5bb3a..71cb716ca8 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/text/TextRenderer.java @@ -134,7 +134,7 @@ public final class TextRenderer extends BaseRenderer implements Callback { public int supportsFormat(Format format) { if (decoderFactory.supportsFormat(format)) { 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)) { return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE); } else { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/DecoderVideoRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/video/DecoderVideoRenderer.java index 6628330338..30630bf878 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/DecoderVideoRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/DecoderVideoRenderer.java @@ -36,6 +36,7 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.PlaybackException; 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.DecoderCounters; 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.drm.DrmSession; 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.util.Assertions; import com.google.android.exoplayer2.util.Log; @@ -529,14 +529,14 @@ public abstract class DecoderVideoRenderer extends BaseRenderer { * Creates a decoder for the given format. * * @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. * @return The decoder. * @throws DecoderException If an error occurred creating a suitable decoder. */ protected abstract Decoder< 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. @@ -664,10 +664,10 @@ public abstract class DecoderVideoRenderer extends BaseRenderer { setDecoderDrmSession(sourceDrmSession); - ExoMediaCrypto mediaCrypto = null; + CryptoConfig cryptoConfig = null; if (decoderDrmSession != null) { - mediaCrypto = decoderDrmSession.getMediaCrypto(); - if (mediaCrypto == null) { + cryptoConfig = decoderDrmSession.getCryptoConfig(); + if (cryptoConfig == null) { DrmSessionException drmError = decoderDrmSession.getError(); if (drmError != null) { // 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 { long decoderInitializingTimestamp = SystemClock.elapsedRealtime(); - decoder = createDecoder(inputFormat, mediaCrypto); + decoder = createDecoder(inputFormat, cryptoConfig); setDecoderOutputMode(outputMode); long decoderInitializedTimestamp = SystemClock.elapsedRealtime(); eventDispatcher.decoderInitialized( diff --git a/library/core/src/test/java/com/google/android/exoplayer2/audio/DecoderAudioRendererTest.java b/library/core/src/test/java/com/google/android/exoplayer2/audio/DecoderAudioRendererTest.java index 7a6fe531af..23161aef05 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/audio/DecoderAudioRendererTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/audio/DecoderAudioRendererTest.java @@ -30,13 +30,13 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; 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.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.SimpleDecoder; import com.google.android.exoplayer2.decoder.SimpleOutputBuffer; import com.google.android.exoplayer2.drm.DrmSessionEventListener; 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.upstream.DefaultAllocator; import com.google.android.exoplayer2.util.MimeTypes; @@ -75,7 +75,7 @@ public class DecoderAudioRendererTest { } @Override - protected FakeDecoder createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) { + protected FakeDecoder createDecoder(Format format, @Nullable CryptoConfig cryptoConfig) { return new FakeDecoder(); } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java index 0b812ba14f..132be88688 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/source/SampleQueueTest.java @@ -41,8 +41,8 @@ import com.google.android.exoplayer2.drm.DrmInitData; import com.google.android.exoplayer2.drm.DrmSession; import com.google.android.exoplayer2.drm.DrmSessionEventListener; 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.testutil.FakeCryptoConfig; import com.google.android.exoplayer2.testutil.TestUtil; import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.DefaultAllocator; @@ -73,7 +73,7 @@ public final class SampleQueueTest { private static final Format FORMAT_ENCRYPTED = new Format.Builder().setId(/* id= */ "encrypted").setDrmInitData(new DrmInitData()).build(); 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); /* @@ -1761,8 +1761,6 @@ public final class SampleQueueTest { return format.buildUpon().setLabel(label).build(); } - private static final class MockExoMediaCrypto implements ExoMediaCrypto {} - private static final class MockDrmSessionManager implements DrmSessionManager { private final DrmSession mockDrmSession; @@ -1772,8 +1770,8 @@ public final class SampleQueueTest { this.mockDrmSession = mockDrmSession; } - @Nullable @Override + @Nullable public DrmSession acquireSession( Looper playbackLooper, @Nullable DrmSessionEventListener.EventDispatcher eventDispatcher, @@ -1781,12 +1779,12 @@ public final class SampleQueueTest { return format.drmInitData != null ? mockDrmSession : mockPlaceholderDrmSession; } - @Nullable @Override - public Class getExoMediaCryptoType(Format format) { + @C.CryptoType + public int getCryptoType(Format format) { return mockPlaceholderDrmSession != null || format.drmInitData != null - ? MockExoMediaCrypto.class - : null; + ? FakeCryptoConfig.TYPE + : C.CRYPTO_TYPE_NONE; } } } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/video/DecoderVideoRendererTest.java b/library/core/src/test/java/com/google/android/exoplayer2/video/DecoderVideoRendererTest.java index cf37eed42f..fcaf93bd7e 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/video/DecoderVideoRendererTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/video/DecoderVideoRendererTest.java @@ -34,12 +34,12 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Renderer; import com.google.android.exoplayer2.RendererCapabilities; 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.DecoderInputBuffer; import com.google.android.exoplayer2.decoder.SimpleDecoder; import com.google.android.exoplayer2.drm.DrmSessionEventListener; 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.upstream.DefaultAllocator; import com.google.android.exoplayer2.util.MimeTypes; @@ -128,7 +128,7 @@ public final class DecoderVideoRendererTest { VideoDecoderInputBuffer, ? extends VideoDecoderOutputBuffer, ? extends DecoderException> - createDecoder(Format format, @Nullable ExoMediaCrypto mediaCrypto) { + createDecoder(Format format, @Nullable CryptoConfig cryptoConfig) { return new SimpleDecoder< VideoDecoderInputBuffer, VideoDecoderOutputBuffer, DecoderException>( new VideoDecoderInputBuffer[10], new VideoDecoderOutputBuffer[10]) { diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java index 38205a4621..058fca8aa8 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java @@ -667,8 +667,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; Format[] formats = new Format[representations.size()]; for (int j = 0; j < formats.length; j++) { Format format = representations.get(j).format; - formats[j] = - format.copyWithExoMediaCryptoType(drmSessionManager.getExoMediaCryptoType(format)); + formats[j] = format.copyWithCryptoType(drmSessionManager.getCryptoType(format)); } AdaptationSet firstAdaptationSet = adaptationSets.get(adaptationSetIndices[0]); diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java index 05f7a7f8cc..afe6cdd34f 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java @@ -1411,8 +1411,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; Format[] exposedFormats = new Format[trackGroup.length]; for (int j = 0; j < trackGroup.length; j++) { Format format = trackGroup.getFormat(j); - exposedFormats[j] = - format.copyWithExoMediaCryptoType(drmSessionManager.getExoMediaCryptoType(format)); + exposedFormats[j] = format.copyWithCryptoType(drmSessionManager.getCryptoType(format)); } trackGroups[i] = new TrackGroup(exposedFormats); } diff --git a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java index ae96b941d2..cc3b17cf99 100644 --- a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java +++ b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java @@ -261,8 +261,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; for (int j = 0; j < manifestFormats.length; j++) { Format manifestFormat = manifestFormats[j]; exposedFormats[j] = - manifestFormat.copyWithExoMediaCryptoType( - drmSessionManager.getExoMediaCryptoType(manifestFormat)); + manifestFormat.copyWithCryptoType(drmSessionManager.getCryptoType(manifestFormat)); } trackGroups[i] = new TrackGroup(exposedFormats); } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/drm/UnsupportedMediaCrypto.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeCryptoConfig.java similarity index 61% rename from library/common/src/main/java/com/google/android/exoplayer2/drm/UnsupportedMediaCrypto.java rename to testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeCryptoConfig.java index e8e6d6074b..dfcbee3484 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/drm/UnsupportedMediaCrypto.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeCryptoConfig.java @@ -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"); * 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 * 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. */ -public final class UnsupportedMediaCrypto implements ExoMediaCrypto {} +import com.google.android.exoplayer2.C; +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; +} diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExoMediaDrm.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExoMediaDrm.java index 0f8d3dc348..fef3f67b10 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExoMediaDrm.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeExoMediaDrm.java @@ -26,8 +26,9 @@ import android.os.Parcelable; import android.os.PersistableBundle; import androidx.annotation.Nullable; 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.ExoMediaCrypto; import com.google.android.exoplayer2.drm.ExoMediaDrm; import com.google.android.exoplayer2.drm.MediaDrmCallback; import com.google.android.exoplayer2.drm.MediaDrmCallbackException; @@ -334,15 +335,16 @@ public final class FakeExoMediaDrm implements ExoMediaDrm { } @Override - public ExoMediaCrypto createMediaCrypto(byte[] sessionId) throws MediaCryptoException { + public CryptoConfig createCryptoConfig(byte[] sessionId) throws MediaCryptoException { Assertions.checkState(referenceCount > 0); Assertions.checkState(openSessionIds.contains(toByteList(sessionId))); - return new FakeExoMediaCrypto(); + return new FakeCryptoConfig(); } @Override - public Class getExoMediaCryptoType() { - return FakeExoMediaCrypto.class; + @C.CryptoType + public int getCryptoType() { + return FakeCryptoConfig.TYPE; } // Methods to facilitate testing @@ -389,8 +391,6 @@ public final class FakeExoMediaDrm implements ExoMediaDrm { return ImmutableList.copyOf(Bytes.asList(byteArray)); } - private static class FakeExoMediaCrypto implements ExoMediaCrypto {} - /** An license server implementation to interact with {@link FakeExoMediaDrm}. */ public static class LicenseServer implements MediaDrmCallback {