androidx / media

Jetpack Media3 support libraries for media use cases, including ExoPlayer, an extensible media player for Android
https://developer.android.com/media/media3
Apache License 2.0
1.6k stars 379 forks source link

Drm clearkey (KEY,KID) to MAIN demo #1283

Closed U3Goliath closed 1 month ago

U3Goliath commented 5 months ago

Hello everyone.

I have taken the "MAIN" demo as a base.

I am trying to add the reading of KEY and KID values, to play mpd content with CLEARKEY. But no work...

Test response: "One or more sample lists failed to load"

I'm starting to program in android studio, if anyone could help me I would appreciate it.

Key/Kid reading code: https://github.com/androidx/media/issues/1208

The implemented code:

 1 file changed, 42 insertions(+), 8 deletions(-)

diff --git a/demos/main/src/main/java/androidx/media3/demo/main/SampleChooserActivity.java b/demos/main/src/main/java/androidx/media3/demo/main/SampleChooserActivity.java
index 7d10a65966..8013b4823d 100644
--- a/demos/main/src/main/java/androidx/media3/demo/main/SampleChooserActivity.java
+++ b/demos/main/src/main/java/androidx/media3/demo/main/SampleChooserActivity.java
@@ -383,6 +383,12 @@ public class SampleChooserActivity extends AppCompatActivity
             break;
           case "extension":
             extension = reader.nextString();
+            break;
+         case "kid":
+            kid = reader.nextString();
+            break;
+          case "key":
+            key = reader.nextString();
             break;
           case "clip_start_position_ms":
             clippingConfiguration.setStartPositionMs(reader.nextLong());
@@ -462,14 +468,42 @@ public class SampleChooserActivity extends AppCompatActivity
             .setMimeType(adaptiveMimeType)
             .setClippingConfiguration(clippingConfiguration.build());
         if (drmUuid != null) {
-          mediaItem.setDrmConfiguration(
-              new MediaItem.DrmConfiguration.Builder(drmUuid)
-                  .setLicenseUri(drmLicenseUri)
-                  .setLicenseRequestHeaders(drmLicenseRequestHeaders)
-                  .setForceSessionsForAudioAndVideoTracks(drmSessionForClearContent)
-                  .setMultiSession(drmMultiSession)
-                  .setForceDefaultLicenseUri(drmForceDefaultLicenseUri)
-                  .build());
+          if ((kid != null) && (key != null))
+          {
+            final byte[] drmKeyBytes = hexStringToByteArray(key);
+            final String encodedDrmKey = Base64.encodeToString(drmKeyBytes, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP);
+
+            final byte[] drmKeyIdBytes = hexStringToByteArray(kid);
+            final String encodedDrmKeyId = Base64.encodeToString(drmKeyIdBytes, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP);
+
+            final String drmBody = "{\"keys\":[{\"kty\":\"oct\",\"k\":\"" + encodedDrmKey + "\",\"kid\":\"" + encodedDrmKeyId + "\"}],\"type\":\"temporary\"}";
+
+            final byte[] drmBodyBytes = drmBody.getBytes();
+            final LocalMediaDrmCallback drmCallback = new LocalMediaDrmCallback(drmBodyBytes);
+
+            final DefaultDrmSessionManager drmSessionManager = new DefaultDrmSessionManager.Builder()
+                    .setPlayClearSamplesWithoutKeys(true)
+                    .setMultiSession(false)
+                    .setKeyRequestParameters(new HashMap<>())
+                    .setUuidAndExoMediaDrmProvider(C.CLEARKEY_UUID, FrameworkMediaDrm.DEFAULT_PROVIDER)
+                    .build(drmCallback);
+
+            final DrmSessionManager customDrmSessionManager = drmSessionManager;
+            final MediaSource.Factory mediaSourceFactory = (MediaSource.Factory) new DefaultMediaSourceFactory(getApplicationContext())
+                    .setDrmSessionManagerProvider(drmSessionManagerProvider -> customDrmSessionManager)
+                    .createMediaSource(mediaItem.build());
+          }
+          else
+          {
+            mediaItem.setDrmConfiguration(
+                    new MediaItem.DrmConfiguration.Builder(drmUuid)
+                            .setLicenseUri(drmLicenseUri)
+                            .setLicenseRequestHeaders(drmLicenseRequestHeaders)
+                            .setForceSessionsForAudioAndVideoTracks(drmSessionForClearContent)
+                            .setMultiSession(drmMultiSession)
+                            .setForceDefaultLicenseUri(drmForceDefaultLicenseUri)
+                            .build());
+          }
         } else {
           checkState(drmLicenseUri == null, "drm_uuid is required if drm_license_uri is set.");
           checkState(
icbaker commented 5 months ago

Test response: "One or more sample lists failed to load"

This is coming from here in SampleChooserActivity and is likely due to malformed JSON (e.g. the parser is very picky about whether trailing commas are present or absent in specific places). I suggest you log the IOException e that's available there and see if it helps resolve your issue: https://github.com/androidx/media/blob/1c0345e69f240ccabb20cbce7701fb536032623b/demos/main/src/main/java/androidx/media3/demo/main/SampleChooserActivity.java#L120-L123


final MediaSource.Factory mediaSourceFactory = [...]

This part looks problematic, because you don't seem to do anything with this MediaSource.Factory. Ultimately you need to pass it to ExoPlayer.Builder.setMediaSourceFactory (see examples in https://developer.android.com/media/media3/exoplayer/customization#player-customization), but in the demo app this would happen in PlayerActivity.initializePlayer, which is the other side of an Intent connection from SampleChooserActivity, and you can't pass a MediaSource.Factory (or DefaultDrmSessionManager(Provider)) via the Intent:

https://github.com/androidx/media/blob/1c0345e69f240ccabb20cbce7701fb536032623b/demos/main/src/main/java/androidx/media3/demo/main/PlayerActivity.java#L264-L298

I would suggest changing your logic so you can either pass the kid and key (or the complete drmBody string) via the Intent, and do the rest of the logic in PlayerActivity.

icbaker commented 5 months ago

I suggest you log the IOException e that's available there and see if it helps resolve your issue

I've just submitted a change that does this, so you can rebase your local changes to pick it up instead: https://github.com/androidx/media/commit/c01babe9bb15a6031b618d8085294c558d8124d2

U3Goliath commented 3 months ago

Sorry but, need help for this...

I have tried several ways but it doesn't work.

Please, could someone help me develop it?

icbaker commented 1 month ago

I'm afraid we don't have capacity to provide detailed help beyond what I've already explained above, so I'm closing this.