Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ExoPlayer ClearKey Issue #777

Closed
flashworldnet opened this issue Oct 28, 2023 · 11 comments
Closed

ExoPlayer ClearKey Issue #777

flashworldnet opened this issue Oct 28, 2023 · 11 comments
Assignees
Labels

Comments

@flashworldnet
Copy link

I have a sample dash video stream which does not work with the ExoPlayer with ClearKey. But it does work without an issue in the JW Stream Tester (Link) with ClearKey. I have mentioned below the stream link and the keys.

Stream Link: https://cdnapisec.kaltura.com/p/2433871/sp/243387100/playManifest/protocol/https//entryId/1_pgssezc1/format/mpegdash/tags/mbr/f/a.mpd

Key ID: a07c5d499dcead0fb416fed5913967be
Key: caee457911302478487e6680bf0b3d1b

Hoping for a solution.

Thank you

@icbaker
Copy link
Collaborator

icbaker commented Oct 30, 2023

Please provide the code you're using to configure ExoPlayer for this clearkey playback.

Note that you need to be careful to use URL safe base64 when encoding your keys (see also google/ExoPlayer#4075 (comment)). In particular your Key ID converts to the following non-URL-safe base64 (source) oHxdSZ3OrQ+0Fv7VkTlnvg==, but the + should be a - in a URL-safe base64 string (and the padding = are not required/should be removed).

@flashworldnet
Copy link
Author

Thanks for the reply.

This is my code. I tried the Key ID both ways.

val drmCallback = LocalMediaDrmCallback("{\"keys\":[{\"kty\":\"oct\",\"k\":\"yu5FeREwJHhIfmaAvws9Gw\",\"kid\":\"oHxdSZ3OrQ-0Fv7VkTlnvg\"}],'type':\"temporary\"}".toByteArray())
val drmSessionManager = DefaultDrmSessionManager.Builder()
    .setPlayClearSamplesWithoutKeys(true)
    .setMultiSession(false)
    .setKeyRequestParameters(HashMap())
    .setUuidAndExoMediaDrmProvider(C.CLEARKEY_UUID, FrameworkMediaDrm.DEFAULT_PROVIDER)
    .build(drmCallback)
DashMediaSource.Factory(DownloadUtil.getHttpDataSourceFactory(requireContext()))
    .setDrmSessionManagerProvider { drmSessionManager }
    .createMediaSource(dashMediaItem)

The error I'm getting is this.

WVCdm-DrmFactory     E  Widevine Drm HAL: failed to create drm plugin, invalid crypto scheme
DrmHalAidl           E  uuid=[e2719d58a985b3c9 781ab030af78d30e] Failed to make drm plugin: 4

@icbaker
Copy link
Collaborator

icbaker commented Oct 31, 2023

The provided code is incomplete - please also include the interactions with ExoPlayer and details of what dashMediaItem looks like.

@icbaker
Copy link
Collaborator

icbaker commented Oct 31, 2023

You may also want to take a look at this (untested) example: #780 (comment)

@flashworldnet
Copy link
Author

The provided code is incomplete - please also include the interactions with ExoPlayer and details of what dashMediaItem looks like.

This is the complete code.

val dashMediaItem = MediaItem.Builder()
     .setUri("https://cdnapisec.kaltura.com/p/2433871/sp/243387100/playManifest/protocol/https//entryId/1_pgssezc1/format/mpegdash/tags/mbr/f/a.mpd")
     .setMimeType(MimeTypes.APPLICATION_MPD)
     .setMediaMetadata(MediaMetadata.Builder().setTitle(defaultVideoTitle).build())
     .setTag(MediaItemTag(-1, defaultVideoTitle))
     .build()

val trackSelector = DefaultTrackSelector(requireContext())
val loadControl = DefaultLoadControl()

val drmCallback = LocalMediaDrmCallback("{\"keys\":[{\"kty\":\"oct\",\"k\":\"yu5FeREwJHhIfmaAvws9Gw\",\"kid\":\"oHxdSZ3OrQ-0Fv7VkTlnvg\"}],'type':\"temporary\"}".toByteArray())
val drmSessionManager = DefaultDrmSessionManager.Builder()
    .setPlayClearSamplesWithoutKeys(true)
    .setMultiSession(false)
    .setKeyRequestParameters(HashMap())
    .setUuidAndExoMediaDrmProvider(C.CLEARKEY_UUID, FrameworkMediaDrm.DEFAULT_PROVIDER)
    .build(drmCallback)
val mediaSource = DashMediaSource.Factory(DownloadUtil.getHttpDataSourceFactory(requireContext()))
    .setDrmSessionManagerProvider { drmSessionManager }
    .createMediaSource(dashMediaItem)

val simpleExoPlayer = ExoPlayer.Builder(requireContext())
    .setTrackSelector(trackSelector)
    .setLoadControl(loadControl)
    .setSeekForwardIncrementMs(10000L)
    .setSeekBackIncrementMs(10000L)
    .build()

val playerView = view.findViewById(R.id.player_view)
playerView.player = simpleExoPlayer
simpleExoPlayer.setMediaSource(mediaSource, true)
simpleExoPlayer.prepare()
simpleExoPlayer.play()

@icbaker
Copy link
Collaborator

icbaker commented Nov 1, 2023

Some observations:

In the DASH manifest you've linked, the ClearKey <ContentProtection schemeIdUri="urn:mpeg:dash:mp4protection:2011" value="cenc"/> nodes are missing the required default_KID parameter. See google/ExoPlayer#9169 (comment).


In your JSON clearkey response you're using single quotes around type. I believe JSON requires double-quotes around keys:

Property names must be double-quoted strings

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON#objects_and_arrays

copybara-service bot pushed a commit that referenced this issue Nov 1, 2023
Unfortunately we can't fail any more obviously at this point, because
manifests often contain config for multiple DRM schemes, and when
parsing the manifest we don't know which scheme is going to be used for
playback. It would be unreasonable to fail playback due to incomplete
ClearKey config if playback was otherwise going to succeed using e.g.
Widevine.

* Issue: #777
* Issue: #563
* Issue: google/ExoPlayer#9169

#minor-release

PiperOrigin-RevId: 578491484
copybara-service bot pushed a commit to google/ExoPlayer that referenced this issue Nov 1, 2023
Unfortunately we can't fail any more obviously at this point, because
manifests often contain config for multiple DRM schemes, and when
parsing the manifest we don't know which scheme is going to be used for
playback. It would be unreasonable to fail playback due to incomplete
ClearKey config if playback was otherwise going to succeed using e.g.
Widevine.

* Issue: androidx/media#777
* Issue: androidx/media#563
* Issue: #9169

#minor-release

PiperOrigin-RevId: 578491484
@trinme
Copy link

trinme commented Nov 4, 2023

For those who have issue playing dash media with clearkey cause by no supported DRM or no default_KID can try this out. Create CustomDashManifetParser class that extend to DashManifestParser. Then override parseContentProtection value. Add your code to feed default_KID if no default value found. Then on player activity create mediasource using DashMediaSource and setManifetParser with CustomDashManifestParser earlier.

@flashworldnet
Copy link
Author

flashworldnet commented Nov 4, 2023

For those who have issue playing dash media with clearkey cause by no supported DRM or no default_KID can try this out. Create CustomDashManifetParser class that extend to DashManifestParser. Then override parseContentProtection value. Add your code to feed default_KID if no default value found. Then on player activity create mediasource using DashMediaSource and setManifetParser with CustomDashManifestParser earlier.

Thanks for the reply. I will try this

Is there any example like this which I can refer?

@trinme
Copy link

trinme commented Nov 4, 2023

You may also want to take a look at this (untested) example: #780 (comment)

Just as the example given above, add something like this.

String defaultKid = "TODO"
String clearkeyJsonResponse = "TODO";
DrmSessionManager clearkeyDrmSessionManager =
    new DefaultDrmSessionManager.Builder()
        .setUuidAndExoMediaDrmProvider(C.CLEARKEY_UUID, FrameworkMediaDrm.DEFAULT_PROVIDER)
        .build(
            new LocalMediaDrmCallback(clearkeyJsonResponse.getBytes(StandardCharsets.UTF_8)));
ExoPlayer player =
    new ExoPlayer.Builder(/* context= */ this)
        .setMediaSourceFactory(
            new DashMediaSource.Factory(new DefaultDashChunkSource.Factory(dataSourceFactory), dataSourceFactory)
                        .setManifestParser(new ClearkeyDashManifestParser(defaultKid))
                        .setDrmSessionManagerProvider(mediaItem -> clearkeyDrmSessionManager))
        .build();

String mpdUrl = "TODO";
player.addMediaItem(
    new MediaItem.Builder()
        .setUri(mpdUrl)
        .setDrmConfiguration(new MediaItem.DrmConfiguration.Builder(C.CLEARKEY_UUID).build())
        .build());

@AmarnathCJD
Copy link

#780 (comment)

please check this:)

@flashworldnet
Copy link
Author

You may also want to take a look at this (untested) example: #780 (comment)

Just as the example given above, add something like this.

String defaultKid = "TODO"
String clearkeyJsonResponse = "TODO";
DrmSessionManager clearkeyDrmSessionManager =
    new DefaultDrmSessionManager.Builder()
        .setUuidAndExoMediaDrmProvider(C.CLEARKEY_UUID, FrameworkMediaDrm.DEFAULT_PROVIDER)
        .build(
            new LocalMediaDrmCallback(clearkeyJsonResponse.getBytes(StandardCharsets.UTF_8)));
ExoPlayer player =
    new ExoPlayer.Builder(/* context= */ this)
        .setMediaSourceFactory(
            new DashMediaSource.Factory(new DefaultDashChunkSource.Factory(dataSourceFactory), dataSourceFactory)
                        .setManifestParser(new ClearkeyDashManifestParser(defaultKid))
                        .setDrmSessionManagerProvider(mediaItem -> clearkeyDrmSessionManager))
        .build();

String mpdUrl = "TODO";
player.addMediaItem(
    new MediaItem.Builder()
        .setUri(mpdUrl)
        .setDrmConfiguration(new MediaItem.DrmConfiguration.Builder(C.CLEARKEY_UUID).build())
        .build());

I figured it out and it worked. Thanks for the help. Closing the issue.

@androidx androidx locked and limited conversation to collaborators Jan 4, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

5 participants