From 7314e9bddc2635c9426cbe237b237f35f24bb15b Mon Sep 17 00:00:00 2001 From: olly Date: Wed, 3 Jan 2018 08:44:56 -0800 Subject: [PATCH] DRM fixes - Parse multiple kids from default_KID. It's specified as a whitespace separated list of UUIDs rather than a single UUID. - Opportunistically proceed with playback in cases where the manifest only defines a single SchemeData with the common PSSH UUID. In such cases the manifest isn't saying anything about which specific DRM schemes it supports. Issue: #3630 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=180675056 --- RELEASENOTES.md | 3 +++ .../exoplayer2/drm/DefaultDrmSessionManager.java | 15 ++++++++++++--- .../source/dash/manifest/DashManifestParser.java | 11 ++++++++--- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5d3d00a5449..25e4e841e30 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -26,6 +26,9 @@ positions. * Note: `SeekParameters` are only currently effective when playing `ExtractorMediaSource`s (i.e. progressive streams). +* DRM: Optimistically attempt playback of DRM protected content that does not + declare scheme specific init data + ([#3630](https://github.com/google/ExoPlayer/issues/3630)). * DASH: Support DASH manifest EventStream elements. * HLS: Add opt-in support for chunkless preparation in HLS. This allows an HLS source to finish preparation without downloading any chunks, which can diff --git a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java index 08defdcceec..9c134970ff3 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/drm/DefaultDrmSessionManager.java @@ -23,6 +23,7 @@ import android.support.annotation.IntDef; import android.support.annotation.NonNull; import android.text.TextUtils; +import android.util.Log; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.drm.DefaultDrmSession.ProvisioningManager; @@ -87,7 +88,6 @@ public interface EventListener { * The key to use when passing CustomData to a PlayReady instance in an optional parameter map. */ public static final String PLAYREADY_CUSTOM_DATA_KEY = "PRCustomData"; - private static final String CENC_SCHEME_MIME_TYPE = "cenc"; /** Determines the action to be done after a session acquired. */ @Retention(RetentionPolicy.SOURCE) @@ -109,6 +109,9 @@ public interface EventListener { /** Number of times to retry for initial provisioning and key request for reporting error. */ public static final int INITIAL_DRM_REQUEST_RETRY_COUNT = 3; + private static final String TAG = "DrmSessionManager"; + private static final String CENC_SCHEME_MIME_TYPE = "cenc"; + private final UUID uuid; private final ExoMediaDrm mediaDrm; private final MediaDrmCallback callback; @@ -350,8 +353,14 @@ public void setMode(@Mode int mode, byte[] offlineLicenseKeySetId) { public boolean canAcquireSession(@NonNull DrmInitData drmInitData) { SchemeData schemeData = getSchemeData(drmInitData, uuid, true); if (schemeData == null) { - // No data for this manager's scheme. - return false; + if (drmInitData.schemeDataCount == 1 && drmInitData.get(0).matches(C.COMMON_PSSH_UUID)) { + // Assume scheme specific data will be added before the session is opened. + Log.w( + TAG, "DrmInitData only contains common PSSH SchemeData. Assuming support for: " + uuid); + } else { + // No data for this manager's scheme. + return false; + } } String schemeType = drmInitData.schemeType; if (schemeType == null || C.CENC_TYPE_cenc.equals(schemeType)) { diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java index 73d234fa72a..bda2a1fb855 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/manifest/DashManifestParser.java @@ -365,9 +365,14 @@ protected Pair parseContentProtection(XmlPullParser xpp) case "urn:mpeg:dash:mp4protection:2011": schemeType = xpp.getAttributeValue(null, "value"); String defaultKid = xpp.getAttributeValue(null, "cenc:default_KID"); - if (defaultKid != null && !"00000000-0000-0000-0000-000000000000".equals(defaultKid)) { - UUID keyId = UUID.fromString(defaultKid); - data = PsshAtomUtil.buildPsshAtom(C.COMMON_PSSH_UUID, new UUID[] {keyId}, null); + if (!TextUtils.isEmpty(defaultKid) + && !"00000000-0000-0000-0000-000000000000".equals(defaultKid)) { + String[] defaultKidStrings = defaultKid.split("\\s+"); + UUID[] defaultKids = new UUID[defaultKidStrings.length]; + for (int i = 0; i < defaultKidStrings.length; i++) { + defaultKids[i] = UUID.fromString(defaultKidStrings[i]); + } + data = PsshAtomUtil.buildPsshAtom(C.COMMON_PSSH_UUID, defaultKids, null); uuid = C.COMMON_PSSH_UUID; } break;