mirror of
https://github.com/androidx/media.git
synced 2025-05-17 12:39:52 +08:00
DRM refactor / cleanup
PiperOrigin-RevId: 391403236
This commit is contained in:
parent
cd297b048a
commit
85142be9a4
@ -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 =
|
||||||
|
@ -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 =
|
||||||
|
@ -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
|
||||||
|
@ -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 =
|
||||||
|
@ -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();
|
||||||
|
@ -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,
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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();
|
||||||
|
@ -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}.
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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 {}
|
@ -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 {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
||||||
* 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.
|
||||||
* @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(
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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) {
|
||||||
|
@ -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 {
|
||||||
|
@ -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(
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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]) {
|
||||||
|
@ -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]);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
@ -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 {
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user