mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Add DRM format support checks for MediaSource provided DRM
PiperOrigin-RevId: 256161522
This commit is contained in:
parent
16bf7f9106
commit
7408b4355a
12 changed files with 184 additions and 30 deletions
|
|
@ -77,12 +77,17 @@ public final class LibopusAudioRenderer extends SimpleDecoderAudioRenderer {
|
||||||
@Override
|
@Override
|
||||||
protected int supportsFormatInternal(DrmSessionManager<ExoMediaCrypto> drmSessionManager,
|
protected int supportsFormatInternal(DrmSessionManager<ExoMediaCrypto> drmSessionManager,
|
||||||
Format format) {
|
Format format) {
|
||||||
|
boolean drmIsSupported =
|
||||||
|
format.drmInitData == null
|
||||||
|
|| OpusLibrary.matchesExpectedExoMediaCryptoType(format.exoMediaCryptoType)
|
||||||
|
|| (format.exoMediaCryptoType == null
|
||||||
|
&& supportsFormatDrm(drmSessionManager, format.drmInitData));
|
||||||
if (!OpusLibrary.isAvailable()
|
if (!OpusLibrary.isAvailable()
|
||||||
|| !MimeTypes.AUDIO_OPUS.equalsIgnoreCase(format.sampleMimeType)) {
|
|| !MimeTypes.AUDIO_OPUS.equalsIgnoreCase(format.sampleMimeType)) {
|
||||||
return FORMAT_UNSUPPORTED_TYPE;
|
return FORMAT_UNSUPPORTED_TYPE;
|
||||||
} else if (!supportsOutput(format.channelCount, C.ENCODING_PCM_16BIT)) {
|
} else if (!supportsOutput(format.channelCount, C.ENCODING_PCM_16BIT)) {
|
||||||
return FORMAT_UNSUPPORTED_SUBTYPE;
|
return FORMAT_UNSUPPORTED_SUBTYPE;
|
||||||
} else if (!supportsFormatDrm(drmSessionManager, format.drmInitData)) {
|
} else if (!drmIsSupported) {
|
||||||
return FORMAT_UNSUPPORTED_DRM;
|
return FORMAT_UNSUPPORTED_DRM;
|
||||||
} else {
|
} else {
|
||||||
return FORMAT_HANDLED;
|
return FORMAT_HANDLED;
|
||||||
|
|
@ -110,5 +115,4 @@ public final class LibopusAudioRenderer extends SimpleDecoderAudioRenderer {
|
||||||
Format.NO_VALUE, decoder.getChannelCount(), decoder.getSampleRate(), C.ENCODING_PCM_16BIT,
|
Format.NO_VALUE, decoder.getChannelCount(), decoder.getSampleRate(), C.ENCODING_PCM_16BIT,
|
||||||
null, null, 0, null);
|
null, null, 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,9 @@
|
||||||
package com.google.android.exoplayer2.ext.opus;
|
package com.google.android.exoplayer2.ext.opus;
|
||||||
|
|
||||||
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.
|
||||||
|
|
@ -28,6 +30,7 @@ public final class OpusLibrary {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final LibraryLoader LOADER = new LibraryLoader("opusV2JNI");
|
private static final LibraryLoader LOADER = new LibraryLoader("opusV2JNI");
|
||||||
|
private static Class<? extends ExoMediaCrypto> exoMediaCryptoType;
|
||||||
|
|
||||||
private OpusLibrary() {}
|
private OpusLibrary() {}
|
||||||
|
|
||||||
|
|
@ -36,10 +39,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
|
||||||
|
* content.
|
||||||
* @param libraries The names of the Opus native libraries.
|
* @param libraries The names of the Opus native libraries.
|
||||||
*/
|
*/
|
||||||
public static void setLibraries(String... libraries) {
|
public static void setLibraries(
|
||||||
|
Class<? extends ExoMediaCrypto> exoMediaCryptoType, String... libraries) {
|
||||||
LOADER.setLibraries(libraries);
|
LOADER.setLibraries(libraries);
|
||||||
|
OpusLibrary.exoMediaCryptoType = exoMediaCryptoType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -56,6 +63,15 @@ public final class OpusLibrary {
|
||||||
return isAvailable() ? opusGetVersion() : null;
|
return isAvailable() ? opusGetVersion() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given {@link ExoMediaCrypto} type matches the one required for decoding
|
||||||
|
* protected content.
|
||||||
|
*/
|
||||||
|
public static boolean matchesExpectedExoMediaCryptoType(
|
||||||
|
Class<? extends ExoMediaCrypto> exoMediaCryptoType) {
|
||||||
|
return Util.areEqual(OpusLibrary.exoMediaCryptoType, exoMediaCryptoType);
|
||||||
|
}
|
||||||
|
|
||||||
public static native String opusGetVersion();
|
public static native String opusGetVersion();
|
||||||
public static native boolean opusIsSecureDecodeSupported();
|
public static native boolean opusIsSecureDecodeSupported();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -284,7 +284,13 @@ public class LibvpxVideoRenderer extends BaseRenderer {
|
||||||
public int supportsFormat(Format format) {
|
public int supportsFormat(Format format) {
|
||||||
if (!VpxLibrary.isAvailable() || !MimeTypes.VIDEO_VP9.equalsIgnoreCase(format.sampleMimeType)) {
|
if (!VpxLibrary.isAvailable() || !MimeTypes.VIDEO_VP9.equalsIgnoreCase(format.sampleMimeType)) {
|
||||||
return FORMAT_UNSUPPORTED_TYPE;
|
return FORMAT_UNSUPPORTED_TYPE;
|
||||||
} else if (!supportsFormatDrm(drmSessionManager, format.drmInitData)) {
|
}
|
||||||
|
boolean drmIsSupported =
|
||||||
|
format.drmInitData == null
|
||||||
|
|| VpxLibrary.matchesExpectedExoMediaCryptoType(format.exoMediaCryptoType)
|
||||||
|
|| (format.exoMediaCryptoType == null
|
||||||
|
&& supportsFormatDrm(drmSessionManager, format.drmInitData));
|
||||||
|
if (!drmIsSupported) {
|
||||||
return FORMAT_UNSUPPORTED_DRM;
|
return FORMAT_UNSUPPORTED_DRM;
|
||||||
}
|
}
|
||||||
return FORMAT_HANDLED | ADAPTIVE_SEAMLESS;
|
return FORMAT_HANDLED | ADAPTIVE_SEAMLESS;
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,9 @@
|
||||||
package com.google.android.exoplayer2.ext.vp9;
|
package com.google.android.exoplayer2.ext.vp9;
|
||||||
|
|
||||||
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.
|
||||||
|
|
@ -28,6 +30,7 @@ public final class VpxLibrary {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final LibraryLoader LOADER = new LibraryLoader("vpx", "vpxV2JNI");
|
private static final LibraryLoader LOADER = new LibraryLoader("vpx", "vpxV2JNI");
|
||||||
|
private static Class<? extends ExoMediaCrypto> exoMediaCryptoType;
|
||||||
|
|
||||||
private VpxLibrary() {}
|
private VpxLibrary() {}
|
||||||
|
|
||||||
|
|
@ -36,10 +39,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
|
||||||
|
* content.
|
||||||
* @param libraries The names of the Vpx native libraries.
|
* @param libraries The names of the Vpx native libraries.
|
||||||
*/
|
*/
|
||||||
public static void setLibraries(String... libraries) {
|
public static void setLibraries(
|
||||||
|
Class<? extends ExoMediaCrypto> exoMediaCryptoType, String... libraries) {
|
||||||
LOADER.setLibraries(libraries);
|
LOADER.setLibraries(libraries);
|
||||||
|
VpxLibrary.exoMediaCryptoType = exoMediaCryptoType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -74,6 +81,15 @@ public final class VpxLibrary {
|
||||||
return indexHbd >= 0;
|
return indexHbd >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given {@link ExoMediaCrypto} type matches the one required for decoding
|
||||||
|
* protected content.
|
||||||
|
*/
|
||||||
|
public static boolean matchesExpectedExoMediaCryptoType(
|
||||||
|
Class<? extends ExoMediaCrypto> exoMediaCryptoType) {
|
||||||
|
return Util.areEqual(VpxLibrary.exoMediaCryptoType, exoMediaCryptoType);
|
||||||
|
}
|
||||||
|
|
||||||
private static native String vpxGetVersion();
|
private static native String vpxGetVersion();
|
||||||
private static native String vpxGetBuildConfig();
|
private static native String vpxGetBuildConfig();
|
||||||
public static native boolean vpxIsSecureDecodeSupported();
|
public static native boolean vpxIsSecureDecodeSupported();
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
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.DrmSession;
|
||||||
|
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
|
||||||
import com.google.android.exoplayer2.metadata.Metadata;
|
import com.google.android.exoplayer2.metadata.Metadata;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
|
|
@ -163,6 +165,15 @@ public final class Format implements Parcelable {
|
||||||
*/
|
*/
|
||||||
public final int accessibilityChannel;
|
public final int accessibilityChannel;
|
||||||
|
|
||||||
|
// Provided by source.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the {@link ExoMediaCrypto} provided by the media source, if the media source can
|
||||||
|
* acquire a {@link DrmSession} for {@link #drmInitData}. Null if the media source cannot acquire
|
||||||
|
* a session for {@link #drmInitData}, or if not applicable.
|
||||||
|
*/
|
||||||
|
@Nullable public final Class<? extends ExoMediaCrypto> exoMediaCryptoType;
|
||||||
|
|
||||||
// Lazily initialized hashcode.
|
// Lazily initialized hashcode.
|
||||||
private int hashCode;
|
private int hashCode;
|
||||||
|
|
||||||
|
|
@ -236,7 +247,8 @@ public final class Format implements Parcelable {
|
||||||
/* encoderDelay= */ NO_VALUE,
|
/* encoderDelay= */ NO_VALUE,
|
||||||
/* encoderPadding= */ NO_VALUE,
|
/* encoderPadding= */ NO_VALUE,
|
||||||
/* language= */ null,
|
/* language= */ null,
|
||||||
/* accessibilityChannel= */ NO_VALUE);
|
/* accessibilityChannel= */ NO_VALUE,
|
||||||
|
/* exoMediaCryptoType= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Format createVideoSampleFormat(
|
public static Format createVideoSampleFormat(
|
||||||
|
|
@ -340,7 +352,8 @@ public final class Format implements Parcelable {
|
||||||
/* encoderDelay= */ NO_VALUE,
|
/* encoderDelay= */ NO_VALUE,
|
||||||
/* encoderPadding= */ NO_VALUE,
|
/* encoderPadding= */ NO_VALUE,
|
||||||
/* language= */ null,
|
/* language= */ null,
|
||||||
/* accessibilityChannel= */ NO_VALUE);
|
/* accessibilityChannel= */ NO_VALUE,
|
||||||
|
/* exoMediaCryptoType= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio.
|
// Audio.
|
||||||
|
|
@ -413,7 +426,8 @@ public final class Format implements Parcelable {
|
||||||
/* encoderDelay= */ NO_VALUE,
|
/* encoderDelay= */ NO_VALUE,
|
||||||
/* encoderPadding= */ NO_VALUE,
|
/* encoderPadding= */ NO_VALUE,
|
||||||
language,
|
language,
|
||||||
/* accessibilityChannel= */ NO_VALUE);
|
/* accessibilityChannel= */ NO_VALUE,
|
||||||
|
/* exoMediaCryptoType= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Format createAudioSampleFormat(
|
public static Format createAudioSampleFormat(
|
||||||
|
|
@ -518,7 +532,8 @@ public final class Format implements Parcelable {
|
||||||
encoderDelay,
|
encoderDelay,
|
||||||
encoderPadding,
|
encoderPadding,
|
||||||
language,
|
language,
|
||||||
/* accessibilityChannel= */ NO_VALUE);
|
/* accessibilityChannel= */ NO_VALUE,
|
||||||
|
/* exoMediaCryptoType= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text.
|
// Text.
|
||||||
|
|
@ -585,7 +600,8 @@ public final class Format implements Parcelable {
|
||||||
/* encoderDelay= */ NO_VALUE,
|
/* encoderDelay= */ NO_VALUE,
|
||||||
/* encoderPadding= */ NO_VALUE,
|
/* encoderPadding= */ NO_VALUE,
|
||||||
language,
|
language,
|
||||||
accessibilityChannel);
|
accessibilityChannel,
|
||||||
|
/* exoMediaCryptoType= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Format createTextSampleFormat(
|
public static Format createTextSampleFormat(
|
||||||
|
|
@ -698,7 +714,8 @@ public final class Format implements Parcelable {
|
||||||
/* encoderDelay= */ NO_VALUE,
|
/* encoderDelay= */ NO_VALUE,
|
||||||
/* encoderPadding= */ NO_VALUE,
|
/* encoderPadding= */ NO_VALUE,
|
||||||
language,
|
language,
|
||||||
accessibilityChannel);
|
accessibilityChannel,
|
||||||
|
/* exoMediaCryptoType= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Image.
|
// Image.
|
||||||
|
|
@ -740,7 +757,8 @@ public final class Format implements Parcelable {
|
||||||
/* encoderDelay= */ NO_VALUE,
|
/* encoderDelay= */ NO_VALUE,
|
||||||
/* encoderPadding= */ NO_VALUE,
|
/* encoderPadding= */ NO_VALUE,
|
||||||
language,
|
language,
|
||||||
/* accessibilityChannel= */ NO_VALUE);
|
/* accessibilityChannel= */ NO_VALUE,
|
||||||
|
/* exoMediaCryptoType= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic.
|
// Generic.
|
||||||
|
|
@ -804,7 +822,8 @@ public final class Format implements Parcelable {
|
||||||
/* encoderDelay= */ NO_VALUE,
|
/* encoderDelay= */ NO_VALUE,
|
||||||
/* encoderPadding= */ NO_VALUE,
|
/* encoderPadding= */ NO_VALUE,
|
||||||
language,
|
language,
|
||||||
/* accessibilityChannel= */ NO_VALUE);
|
/* accessibilityChannel= */ NO_VALUE,
|
||||||
|
/* exoMediaCryptoType= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Format createSampleFormat(
|
public static Format createSampleFormat(
|
||||||
|
|
@ -837,7 +856,8 @@ public final class Format implements Parcelable {
|
||||||
/* encoderDelay= */ NO_VALUE,
|
/* encoderDelay= */ NO_VALUE,
|
||||||
/* encoderPadding= */ NO_VALUE,
|
/* encoderPadding= */ NO_VALUE,
|
||||||
/* language= */ null,
|
/* language= */ null,
|
||||||
/* accessibilityChannel= */ NO_VALUE);
|
/* accessibilityChannel= */ NO_VALUE,
|
||||||
|
/* exoMediaCryptoType= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Format createSampleFormat(
|
public static Format createSampleFormat(
|
||||||
|
|
@ -874,7 +894,8 @@ public final class Format implements Parcelable {
|
||||||
/* encoderDelay= */ NO_VALUE,
|
/* encoderDelay= */ NO_VALUE,
|
||||||
/* encoderPadding= */ NO_VALUE,
|
/* encoderPadding= */ NO_VALUE,
|
||||||
/* language= */ null,
|
/* language= */ null,
|
||||||
/* accessibilityChannel= */ NO_VALUE);
|
/* accessibilityChannel= */ NO_VALUE,
|
||||||
|
/* exoMediaCryptoType= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ Format(
|
/* package */ Format(
|
||||||
|
|
@ -910,7 +931,9 @@ public final class Format implements Parcelable {
|
||||||
int encoderPadding,
|
int encoderPadding,
|
||||||
// Audio and text specific.
|
// Audio and text specific.
|
||||||
@Nullable String language,
|
@Nullable String language,
|
||||||
int accessibilityChannel) {
|
int accessibilityChannel,
|
||||||
|
// Provided by source.
|
||||||
|
@Nullable Class<? extends ExoMediaCrypto> exoMediaCryptoType) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.label = label;
|
this.label = label;
|
||||||
this.selectionFlags = selectionFlags;
|
this.selectionFlags = selectionFlags;
|
||||||
|
|
@ -946,6 +969,8 @@ public final class Format implements Parcelable {
|
||||||
// Audio and text specific.
|
// Audio and text specific.
|
||||||
this.language = Util.normalizeLanguageCode(language);
|
this.language = Util.normalizeLanguageCode(language);
|
||||||
this.accessibilityChannel = accessibilityChannel;
|
this.accessibilityChannel = accessibilityChannel;
|
||||||
|
// Provided by source.
|
||||||
|
this.exoMediaCryptoType = exoMediaCryptoType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ResourceType")
|
@SuppressWarnings("ResourceType")
|
||||||
|
|
@ -988,6 +1013,8 @@ public final class Format implements Parcelable {
|
||||||
// Audio and text specific.
|
// Audio and text specific.
|
||||||
language = in.readString();
|
language = in.readString();
|
||||||
accessibilityChannel = in.readInt();
|
accessibilityChannel = in.readInt();
|
||||||
|
// Provided by source.
|
||||||
|
exoMediaCryptoType = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithMaxInputSize(int maxInputSize) {
|
public Format copyWithMaxInputSize(int maxInputSize) {
|
||||||
|
|
@ -1019,7 +1046,8 @@ public final class Format implements Parcelable {
|
||||||
encoderDelay,
|
encoderDelay,
|
||||||
encoderPadding,
|
encoderPadding,
|
||||||
language,
|
language,
|
||||||
accessibilityChannel);
|
accessibilityChannel,
|
||||||
|
exoMediaCryptoType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithSubsampleOffsetUs(long subsampleOffsetUs) {
|
public Format copyWithSubsampleOffsetUs(long subsampleOffsetUs) {
|
||||||
|
|
@ -1051,7 +1079,8 @@ public final class Format implements Parcelable {
|
||||||
encoderDelay,
|
encoderDelay,
|
||||||
encoderPadding,
|
encoderPadding,
|
||||||
language,
|
language,
|
||||||
accessibilityChannel);
|
accessibilityChannel,
|
||||||
|
exoMediaCryptoType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithContainerInfo(
|
public Format copyWithContainerInfo(
|
||||||
|
|
@ -1099,7 +1128,8 @@ public final class Format implements Parcelable {
|
||||||
encoderDelay,
|
encoderDelay,
|
||||||
encoderPadding,
|
encoderPadding,
|
||||||
language,
|
language,
|
||||||
accessibilityChannel);
|
accessibilityChannel,
|
||||||
|
exoMediaCryptoType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ReferenceEquality")
|
@SuppressWarnings("ReferenceEquality")
|
||||||
|
|
@ -1178,7 +1208,8 @@ public final class Format implements Parcelable {
|
||||||
encoderDelay,
|
encoderDelay,
|
||||||
encoderPadding,
|
encoderPadding,
|
||||||
language,
|
language,
|
||||||
accessibilityChannel);
|
accessibilityChannel,
|
||||||
|
exoMediaCryptoType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithGaplessInfo(int encoderDelay, int encoderPadding) {
|
public Format copyWithGaplessInfo(int encoderDelay, int encoderPadding) {
|
||||||
|
|
@ -1210,7 +1241,8 @@ public final class Format implements Parcelable {
|
||||||
encoderDelay,
|
encoderDelay,
|
||||||
encoderPadding,
|
encoderPadding,
|
||||||
language,
|
language,
|
||||||
accessibilityChannel);
|
accessibilityChannel,
|
||||||
|
exoMediaCryptoType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithFrameRate(float frameRate) {
|
public Format copyWithFrameRate(float frameRate) {
|
||||||
|
|
@ -1242,7 +1274,8 @@ public final class Format implements Parcelable {
|
||||||
encoderDelay,
|
encoderDelay,
|
||||||
encoderPadding,
|
encoderPadding,
|
||||||
language,
|
language,
|
||||||
accessibilityChannel);
|
accessibilityChannel,
|
||||||
|
exoMediaCryptoType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithDrmInitData(@Nullable DrmInitData drmInitData) {
|
public Format copyWithDrmInitData(@Nullable DrmInitData drmInitData) {
|
||||||
|
|
@ -1274,7 +1307,8 @@ public final class Format implements Parcelable {
|
||||||
encoderDelay,
|
encoderDelay,
|
||||||
encoderPadding,
|
encoderPadding,
|
||||||
language,
|
language,
|
||||||
accessibilityChannel);
|
accessibilityChannel,
|
||||||
|
exoMediaCryptoType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithMetadata(@Nullable Metadata metadata) {
|
public Format copyWithMetadata(@Nullable Metadata metadata) {
|
||||||
|
|
@ -1306,7 +1340,8 @@ public final class Format implements Parcelable {
|
||||||
encoderDelay,
|
encoderDelay,
|
||||||
encoderPadding,
|
encoderPadding,
|
||||||
language,
|
language,
|
||||||
accessibilityChannel);
|
accessibilityChannel,
|
||||||
|
exoMediaCryptoType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithRotationDegrees(int rotationDegrees) {
|
public Format copyWithRotationDegrees(int rotationDegrees) {
|
||||||
|
|
@ -1338,7 +1373,8 @@ public final class Format implements Parcelable {
|
||||||
encoderDelay,
|
encoderDelay,
|
||||||
encoderPadding,
|
encoderPadding,
|
||||||
language,
|
language,
|
||||||
accessibilityChannel);
|
accessibilityChannel,
|
||||||
|
exoMediaCryptoType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithBitrate(int bitrate) {
|
public Format copyWithBitrate(int bitrate) {
|
||||||
|
|
@ -1370,7 +1406,8 @@ public final class Format implements Parcelable {
|
||||||
encoderDelay,
|
encoderDelay,
|
||||||
encoderPadding,
|
encoderPadding,
|
||||||
language,
|
language,
|
||||||
accessibilityChannel);
|
accessibilityChannel,
|
||||||
|
exoMediaCryptoType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Format copyWithVideoSize(int width, int height) {
|
public Format copyWithVideoSize(int width, int height) {
|
||||||
|
|
@ -1402,7 +1439,41 @@ public final class Format implements Parcelable {
|
||||||
encoderDelay,
|
encoderDelay,
|
||||||
encoderPadding,
|
encoderPadding,
|
||||||
language,
|
language,
|
||||||
accessibilityChannel);
|
accessibilityChannel,
|
||||||
|
exoMediaCryptoType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Format copyWithExoMediaCryptoType(Class<? extends ExoMediaCrypto> exoMediaCryptoType) {
|
||||||
|
return new Format(
|
||||||
|
id,
|
||||||
|
label,
|
||||||
|
selectionFlags,
|
||||||
|
roleFlags,
|
||||||
|
bitrate,
|
||||||
|
codecs,
|
||||||
|
metadata,
|
||||||
|
containerMimeType,
|
||||||
|
sampleMimeType,
|
||||||
|
maxInputSize,
|
||||||
|
initializationData,
|
||||||
|
drmInitData,
|
||||||
|
subsampleOffsetUs,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
frameRate,
|
||||||
|
rotationDegrees,
|
||||||
|
pixelWidthHeightRatio,
|
||||||
|
projectionData,
|
||||||
|
stereoMode,
|
||||||
|
colorInfo,
|
||||||
|
channelCount,
|
||||||
|
sampleRate,
|
||||||
|
pcmEncoding,
|
||||||
|
encoderDelay,
|
||||||
|
encoderPadding,
|
||||||
|
language,
|
||||||
|
accessibilityChannel,
|
||||||
|
exoMediaCryptoType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1481,6 +1552,8 @@ public final class Format implements Parcelable {
|
||||||
// Audio and text specific.
|
// Audio and text specific.
|
||||||
result = 31 * result + (language == null ? 0 : language.hashCode());
|
result = 31 * result + (language == null ? 0 : language.hashCode());
|
||||||
result = 31 * result + accessibilityChannel;
|
result = 31 * result + accessibilityChannel;
|
||||||
|
// Provided by source.
|
||||||
|
result = 31 * result + (exoMediaCryptoType == null ? 0 : exoMediaCryptoType.hashCode());
|
||||||
hashCode = result;
|
hashCode = result;
|
||||||
}
|
}
|
||||||
return hashCode;
|
return hashCode;
|
||||||
|
|
@ -1516,6 +1589,7 @@ public final class Format implements Parcelable {
|
||||||
&& accessibilityChannel == other.accessibilityChannel
|
&& accessibilityChannel == other.accessibilityChannel
|
||||||
&& 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)
|
||||||
|
|
|
||||||
|
|
@ -308,7 +308,11 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
||||||
return FORMAT_UNSUPPORTED_TYPE;
|
return FORMAT_UNSUPPORTED_TYPE;
|
||||||
}
|
}
|
||||||
int tunnelingSupport = Util.SDK_INT >= 21 ? TUNNELING_SUPPORTED : TUNNELING_NOT_SUPPORTED;
|
int tunnelingSupport = Util.SDK_INT >= 21 ? TUNNELING_SUPPORTED : TUNNELING_NOT_SUPPORTED;
|
||||||
boolean supportsFormatDrm = supportsFormatDrm(drmSessionManager, format.drmInitData);
|
boolean supportsFormatDrm =
|
||||||
|
format.drmInitData == null
|
||||||
|
|| FrameworkMediaCrypto.class.equals(format.exoMediaCryptoType)
|
||||||
|
|| (format.exoMediaCryptoType == null
|
||||||
|
&& supportsFormatDrm(drmSessionManager, format.drmInitData));
|
||||||
if (supportsFormatDrm
|
if (supportsFormatDrm
|
||||||
&& allowPassthrough(format.channelCount, mimeType)
|
&& allowPassthrough(format.channelCount, mimeType)
|
||||||
&& mediaCodecSelector.getPassthroughDecoderInfo() != null) {
|
&& mediaCodecSelector.getPassthroughDecoderInfo() != null) {
|
||||||
|
|
|
||||||
|
|
@ -436,6 +436,12 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Class<T> getExoMediaCryptoType(DrmInitData drmInitData) {
|
||||||
|
return canAcquireSession(drmInitData) ? mediaDrm.getExoMediaCryptoType() : null;
|
||||||
|
}
|
||||||
|
|
||||||
// ProvisioningManager implementation.
|
// ProvisioningManager implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ package com.google.android.exoplayer2.drm;
|
||||||
|
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import androidx.annotation.IntDef;
|
import androidx.annotation.IntDef;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
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;
|
||||||
|
|
@ -49,6 +50,12 @@ public interface DrmSessionManager<T extends ExoMediaCrypto> {
|
||||||
new DrmSession.DrmSessionException(
|
new DrmSession.DrmSessionException(
|
||||||
new UnsupportedDrmException(UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME)));
|
new UnsupportedDrmException(UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Class<ExoMediaCrypto> getExoMediaCryptoType(DrmInitData drmInitData) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Flags that control the handling of DRM protected content. */
|
/** Flags that control the handling of DRM protected content. */
|
||||||
|
|
@ -99,4 +106,11 @@ public interface DrmSessionManager<T extends ExoMediaCrypto> {
|
||||||
default int getFlags() {
|
default int getFlags() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link ExoMediaCrypto} type returned by sessions acquired using the given {@link
|
||||||
|
* DrmInitData}, or null if a session cannot be acquired with the given {@link DrmInitData}.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
Class<? extends ExoMediaCrypto> getExoMediaCryptoType(DrmInitData drmInitData);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -271,4 +271,7 @@ public interface ExoMediaDrm<T extends ExoMediaCrypto> {
|
||||||
* @throws MediaCryptoException If the instance can't be created.
|
* @throws MediaCryptoException If the instance can't be created.
|
||||||
*/
|
*/
|
||||||
T createMediaCrypto(byte[] sessionId) throws MediaCryptoException;
|
T createMediaCrypto(byte[] sessionId) throws MediaCryptoException;
|
||||||
|
|
||||||
|
/** Returns the {@link ExoMediaCrypto} type created by {@link #createMediaCrypto(byte[])}. */
|
||||||
|
Class<T> getExoMediaCryptoType();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,11 @@ public final class FrameworkMediaDrm implements ExoMediaDrm<FrameworkMediaCrypto
|
||||||
adjustUuid(uuid), initData, forceAllowInsecureDecoderComponents);
|
adjustUuid(uuid), initData, forceAllowInsecureDecoderComponents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<FrameworkMediaCrypto> getExoMediaCryptoType() {
|
||||||
|
return FrameworkMediaCrypto.class;
|
||||||
|
}
|
||||||
|
|
||||||
private static SchemeData getSchemeData(UUID uuid, List<SchemeData> schemeDatas) {
|
private static SchemeData getSchemeData(UUID uuid, List<SchemeData> schemeDatas) {
|
||||||
if (!C.WIDEVINE_UUID.equals(uuid)) {
|
if (!C.WIDEVINE_UUID.equals(uuid)) {
|
||||||
// For non-Widevine CDMs always use the first scheme data.
|
// For non-Widevine CDMs always use the first scheme data.
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,12 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||||
if (decoderInfos.isEmpty()) {
|
if (decoderInfos.isEmpty()) {
|
||||||
return FORMAT_UNSUPPORTED_SUBTYPE;
|
return FORMAT_UNSUPPORTED_SUBTYPE;
|
||||||
}
|
}
|
||||||
if (!supportsFormatDrm(drmSessionManager, drmInitData)) {
|
boolean supportsFormatDrm =
|
||||||
|
format.drmInitData == null
|
||||||
|
|| FrameworkMediaCrypto.class.equals(format.exoMediaCryptoType)
|
||||||
|
|| (format.exoMediaCryptoType == null
|
||||||
|
&& supportsFormatDrm(drmSessionManager, format.drmInitData));
|
||||||
|
if (!supportsFormatDrm) {
|
||||||
return FORMAT_UNSUPPORTED_DRM;
|
return FORMAT_UNSUPPORTED_DRM;
|
||||||
}
|
}
|
||||||
// Check capabilities for the first decoder in the list, which takes priority.
|
// Check capabilities for the first decoder in the list, which takes priority.
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,8 @@ public final class FormatTest {
|
||||||
/* encoderDelay= */ 1001,
|
/* encoderDelay= */ 1001,
|
||||||
/* encoderPadding= */ 1002,
|
/* encoderPadding= */ 1002,
|
||||||
"language",
|
"language",
|
||||||
/* accessibilityChannel= */ Format.NO_VALUE);
|
/* accessibilityChannel= */ Format.NO_VALUE,
|
||||||
|
/* exoMediaCryptoType= */ null);
|
||||||
|
|
||||||
Parcel parcel = Parcel.obtain();
|
Parcel parcel = Parcel.obtain();
|
||||||
formatToParcel.writeToParcel(parcel, 0);
|
formatToParcel.writeToParcel(parcel, 0);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue