Commit 7408b435 by aquilescanta Committed by Oliver Woodman

Add DRM format support checks for MediaSource provided DRM

PiperOrigin-RevId: 256161522
parent 16bf7f91
......@@ -77,12 +77,17 @@ public final class LibopusAudioRenderer extends SimpleDecoderAudioRenderer {
@Override
protected int supportsFormatInternal(DrmSessionManager<ExoMediaCrypto> drmSessionManager,
Format format) {
boolean drmIsSupported =
format.drmInitData == null
|| OpusLibrary.matchesExpectedExoMediaCryptoType(format.exoMediaCryptoType)
|| (format.exoMediaCryptoType == null
&& supportsFormatDrm(drmSessionManager, format.drmInitData));
if (!OpusLibrary.isAvailable()
|| !MimeTypes.AUDIO_OPUS.equalsIgnoreCase(format.sampleMimeType)) {
return FORMAT_UNSUPPORTED_TYPE;
} else if (!supportsOutput(format.channelCount, C.ENCODING_PCM_16BIT)) {
return FORMAT_UNSUPPORTED_SUBTYPE;
} else if (!supportsFormatDrm(drmSessionManager, format.drmInitData)) {
} else if (!drmIsSupported) {
return FORMAT_UNSUPPORTED_DRM;
} else {
return FORMAT_HANDLED;
......@@ -110,5 +115,4 @@ public final class LibopusAudioRenderer extends SimpleDecoderAudioRenderer {
Format.NO_VALUE, decoder.getChannelCount(), decoder.getSampleRate(), C.ENCODING_PCM_16BIT,
null, null, 0, null);
}
}
......@@ -16,7 +16,9 @@
package com.google.android.exoplayer2.ext.opus;
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.util.LibraryLoader;
import com.google.android.exoplayer2.util.Util;
/**
* Configures and queries the underlying native library.
......@@ -28,6 +30,7 @@ public final class OpusLibrary {
}
private static final LibraryLoader LOADER = new LibraryLoader("opusV2JNI");
private static Class<? extends ExoMediaCrypto> exoMediaCryptoType;
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
* {@link LibopusAudioRenderer} instance.
*
* @param exoMediaCryptoType The {@link ExoMediaCrypto} type expected for decoding protected
* content.
* @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);
OpusLibrary.exoMediaCryptoType = exoMediaCryptoType;
}
/**
......@@ -56,6 +63,15 @@ public final class OpusLibrary {
return isAvailable() ? opusGetVersion() : null;
}
/**
* Returns whether the given {@link ExoMediaCrypto} type matches the one required for decoding
* protected content.
*/
public static boolean matchesExpectedExoMediaCryptoType(
Class<? extends ExoMediaCrypto> exoMediaCryptoType) {
return Util.areEqual(OpusLibrary.exoMediaCryptoType, exoMediaCryptoType);
}
public static native String opusGetVersion();
public static native boolean opusIsSecureDecodeSupported();
}
......@@ -284,7 +284,13 @@ public class LibvpxVideoRenderer extends BaseRenderer {
public int supportsFormat(Format format) {
if (!VpxLibrary.isAvailable() || !MimeTypes.VIDEO_VP9.equalsIgnoreCase(format.sampleMimeType)) {
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_HANDLED | ADAPTIVE_SEAMLESS;
......
......@@ -16,7 +16,9 @@
package com.google.android.exoplayer2.ext.vp9;
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.util.LibraryLoader;
import com.google.android.exoplayer2.util.Util;
/**
* Configures and queries the underlying native library.
......@@ -28,6 +30,7 @@ public final class VpxLibrary {
}
private static final LibraryLoader LOADER = new LibraryLoader("vpx", "vpxV2JNI");
private static Class<? extends ExoMediaCrypto> exoMediaCryptoType;
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
* {@link LibvpxVideoRenderer} instance.
*
* @param exoMediaCryptoType The {@link ExoMediaCrypto} type required for decoding protected
* content.
* @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);
VpxLibrary.exoMediaCryptoType = exoMediaCryptoType;
}
/**
......@@ -74,6 +81,15 @@ public final class VpxLibrary {
return indexHbd >= 0;
}
/**
* Returns whether the given {@link ExoMediaCrypto} type matches the one required for decoding
* protected content.
*/
public static boolean matchesExpectedExoMediaCryptoType(
Class<? extends ExoMediaCrypto> exoMediaCryptoType) {
return Util.areEqual(VpxLibrary.exoMediaCryptoType, exoMediaCryptoType);
}
private static native String vpxGetVersion();
private static native String vpxGetBuildConfig();
public static native boolean vpxIsSecureDecodeSupported();
......
......@@ -308,7 +308,11 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
return FORMAT_UNSUPPORTED_TYPE;
}
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
&& allowPassthrough(format.channelCount, mimeType)
&& mediaCodecSelector.getPassthroughDecoderInfo() != null) {
......
......@@ -436,6 +436,12 @@ public class DefaultDrmSessionManager<T extends ExoMediaCrypto>
return session;
}
@Override
@Nullable
public Class<T> getExoMediaCryptoType(DrmInitData drmInitData) {
return canAcquireSession(drmInitData) ? mediaDrm.getExoMediaCryptoType() : null;
}
// ProvisioningManager implementation.
@Override
......
......@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.drm;
import android.os.Looper;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
......@@ -49,6 +50,12 @@ public interface DrmSessionManager<T extends ExoMediaCrypto> {
new DrmSession.DrmSessionException(
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. */
......@@ -99,4 +106,11 @@ public interface DrmSessionManager<T extends ExoMediaCrypto> {
default int getFlags() {
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.
*/
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);
}
@Override
public Class<FrameworkMediaCrypto> getExoMediaCryptoType() {
return FrameworkMediaCrypto.class;
}
private static SchemeData getSchemeData(UUID uuid, List<SchemeData> schemeDatas) {
if (!C.WIDEVINE_UUID.equals(uuid)) {
// For non-Widevine CDMs always use the first scheme data.
......
......@@ -336,7 +336,12 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
if (decoderInfos.isEmpty()) {
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;
}
// Check capabilities for the first decoder in the list, which takes priority.
......
......@@ -91,7 +91,8 @@ public final class FormatTest {
/* encoderDelay= */ 1001,
/* encoderPadding= */ 1002,
"language",
/* accessibilityChannel= */ Format.NO_VALUE);
/* accessibilityChannel= */ Format.NO_VALUE,
/* exoMediaCryptoType= */ null);
Parcel parcel = Parcel.obtain();
formatToParcel.writeToParcel(parcel, 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment