mirror of
https://github.com/samsonjs/media.git
synced 2026-04-14 12:45:47 +00:00
Add basic DRM support to CastPlayer's demo app
PiperOrigin-RevId: 249624829
This commit is contained in:
parent
8d329fb41f
commit
3314391932
5 changed files with 108 additions and 34 deletions
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
### dev-v2 (not yet released) ###
|
||||
|
||||
* Add basic DRM support to the Cast demo app.
|
||||
* Add `ResolvingDataSource` for just-in-time resolution of `DataSpec`s
|
||||
([#5779](https://github.com/google/ExoPlayer/issues/5779)).
|
||||
* Assume that encrypted content requires secure decoders in renderer support
|
||||
|
|
|
|||
|
|
@ -44,11 +44,14 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
|
|||
import com.google.android.exoplayer2.ui.PlayerControlView;
|
||||
import com.google.android.exoplayer2.ui.PlayerView;
|
||||
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.gms.cast.MediaInfo;
|
||||
import com.google.android.gms.cast.MediaMetadata;
|
||||
import com.google.android.gms.cast.MediaQueueItem;
|
||||
import com.google.android.gms.cast.framework.CastContext;
|
||||
import java.util.ArrayList;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/** Manages players and an internal media queue for the ExoPlayer/Cast demo app. */
|
||||
/* package */ class DefaultReceiverPlayerManager
|
||||
|
|
@ -394,12 +397,47 @@ import java.util.ArrayList;
|
|||
private static MediaQueueItem buildMediaQueueItem(MediaItem item) {
|
||||
MediaMetadata movieMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE);
|
||||
movieMetadata.putString(MediaMetadata.KEY_TITLE, item.title);
|
||||
MediaInfo mediaInfo =
|
||||
MediaInfo.Builder mediaInfoBuilder =
|
||||
new MediaInfo.Builder(item.media.uri.toString())
|
||||
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
|
||||
.setContentType(item.mimeType)
|
||||
.setMetadata(movieMetadata)
|
||||
.build();
|
||||
return new MediaQueueItem.Builder(mediaInfo).build();
|
||||
.setMetadata(movieMetadata);
|
||||
if (!item.drmSchemes.isEmpty()) {
|
||||
MediaItem.DrmScheme scheme = item.drmSchemes.get(0);
|
||||
try {
|
||||
// This configuration is only intended for testing and should *not* be used in production
|
||||
// environments. See comment in the Cast Demo app's options provider.
|
||||
JSONObject drmConfiguration = getDrmConfigurationJson(scheme);
|
||||
if (drmConfiguration != null) {
|
||||
mediaInfoBuilder.setCustomData(drmConfiguration);
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return new MediaQueueItem.Builder(mediaInfoBuilder.build()).build();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JSONObject getDrmConfigurationJson(MediaItem.DrmScheme scheme)
|
||||
throws JSONException {
|
||||
String drmScheme;
|
||||
if (C.WIDEVINE_UUID.equals(scheme.uuid)) {
|
||||
drmScheme = "widevine";
|
||||
} else if (C.PLAYREADY_UUID.equals(scheme.uuid)) {
|
||||
drmScheme = "playready";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
MediaItem.UriBundle licenseServer = Assertions.checkNotNull(scheme.licenseServer);
|
||||
JSONObject exoplayerConfig =
|
||||
new JSONObject().put("withCredentials", false).put("protectionSystem", drmScheme);
|
||||
if (!licenseServer.uri.equals(Uri.EMPTY)) {
|
||||
exoplayerConfig.put("licenseUrl", licenseServer.uri.toString());
|
||||
}
|
||||
if (!licenseServer.requestHeaders.isEmpty()) {
|
||||
exoplayerConfig.put("headers", new JSONObject(licenseServer.requestHeaders));
|
||||
}
|
||||
return new JSONObject().put("exoPlayerConfig", exoplayerConfig);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.castdemo;
|
||||
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/** Utility methods and constants for the Cast demo application. */
|
||||
|
|
@ -30,44 +30,25 @@ import java.util.UUID;
|
|||
/** Represents a media sample. */
|
||||
public static final class Sample {
|
||||
|
||||
/** The uri of the media content. */
|
||||
/** The URI of the media content. */
|
||||
public final String uri;
|
||||
/** The name of the sample. */
|
||||
public final String name;
|
||||
/** The mime type of the sample media content. */
|
||||
public final String mimeType;
|
||||
/**
|
||||
* The {@link UUID} of the DRM scheme that protects the content, or null if the content is not
|
||||
* DRM-protected.
|
||||
*/
|
||||
@Nullable public final UUID drmSchemeUuid;
|
||||
/**
|
||||
* The url from which players should obtain DRM licenses, or null if the content is not
|
||||
* DRM-protected.
|
||||
*/
|
||||
@Nullable public final Uri licenseServerUri;
|
||||
/** Data to configure DRM license acquisition. May be null if content is not DRM-protected. */
|
||||
@Nullable public final DrmConfiguration drmConfiguration;
|
||||
|
||||
/**
|
||||
* @param uri See {@link #uri}.
|
||||
* @param name See {@link #name}.
|
||||
* @param mimeType See {@link #mimeType}.
|
||||
*/
|
||||
public Sample(String uri, String name, String mimeType) {
|
||||
this(uri, name, mimeType, /* drmSchemeUuid= */ null, /* licenseServerUriString= */ null);
|
||||
this(uri, name, mimeType, /* drmConfiguration= */ null);
|
||||
}
|
||||
|
||||
public Sample(
|
||||
String uri,
|
||||
String name,
|
||||
String mimeType,
|
||||
@Nullable UUID drmSchemeUuid,
|
||||
@Nullable String licenseServerUriString) {
|
||||
String uri, String name, String mimeType, @Nullable DrmConfiguration drmConfiguration) {
|
||||
this.uri = uri;
|
||||
this.name = name;
|
||||
this.mimeType = mimeType;
|
||||
this.drmSchemeUuid = drmSchemeUuid;
|
||||
this.licenseServerUri =
|
||||
licenseServerUriString != null ? Uri.parse(licenseServerUriString) : null;
|
||||
this.drmConfiguration = drmConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -76,6 +57,29 @@ import java.util.UUID;
|
|||
}
|
||||
}
|
||||
|
||||
/** Holds information required to play DRM-protected content. */
|
||||
public static final class DrmConfiguration {
|
||||
|
||||
/** The {@link UUID} of the DRM scheme that protects the content. */
|
||||
public final UUID drmSchemeUuid;
|
||||
/**
|
||||
* The URI from which players should obtain DRM licenses. May be null if the license server URI
|
||||
* is provided as part of the media.
|
||||
*/
|
||||
@Nullable public final String licenseServerUri;
|
||||
/** HTTP request headers to include the in DRM license requests. */
|
||||
public final Map<String, String> httpRequestHeaders;
|
||||
|
||||
public DrmConfiguration(
|
||||
UUID drmSchemeUuid,
|
||||
@Nullable String licenseServerUri,
|
||||
Map<String, String> httpRequestHeaders) {
|
||||
this.drmSchemeUuid = drmSchemeUuid;
|
||||
this.licenseServerUri = licenseServerUri;
|
||||
this.httpRequestHeaders = httpRequestHeaders;
|
||||
}
|
||||
}
|
||||
|
||||
public static final String MIME_TYPE_DASH = MimeTypes.APPLICATION_MPD;
|
||||
public static final String MIME_TYPE_HLS = MimeTypes.APPLICATION_M3U8;
|
||||
public static final String MIME_TYPE_SS = MimeTypes.APPLICATION_SS;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
package com.google.android.exoplayer2.castdemo;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
|
@ -36,6 +37,7 @@ import android.widget.TextView;
|
|||
import android.widget.Toast;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
import com.google.android.exoplayer2.ext.cast.DefaultCastOptionsProvider;
|
||||
import com.google.android.exoplayer2.ext.cast.MediaItem;
|
||||
import com.google.android.exoplayer2.ui.PlayerControlView;
|
||||
import com.google.android.exoplayer2.ui.PlayerView;
|
||||
|
|
@ -121,6 +123,7 @@ public class MainActivity extends AppCompatActivity
|
|||
String applicationId = castContext.getCastOptions().getReceiverApplicationId();
|
||||
switch (applicationId) {
|
||||
case CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID:
|
||||
case DefaultCastOptionsProvider.APP_ID_DEFAULT_RECEIVER_WITH_DRM:
|
||||
playerManager =
|
||||
new DefaultReceiverPlayerManager(
|
||||
/* listener= */ this,
|
||||
|
|
@ -202,11 +205,17 @@ public class MainActivity extends AppCompatActivity
|
|||
.setMedia(sample.uri)
|
||||
.setTitle(sample.name)
|
||||
.setMimeType(sample.mimeType);
|
||||
if (sample.drmSchemeUuid != null) {
|
||||
DemoUtil.DrmConfiguration drmConfiguration = sample.drmConfiguration;
|
||||
if (drmConfiguration != null) {
|
||||
mediaItemBuilder.setDrmSchemes(
|
||||
Collections.singletonList(
|
||||
new MediaItem.DrmScheme(
|
||||
sample.drmSchemeUuid, new MediaItem.UriBundle(sample.licenseServerUri))));
|
||||
drmConfiguration.drmSchemeUuid,
|
||||
new MediaItem.UriBundle(
|
||||
drmConfiguration.licenseServerUri != null
|
||||
? Uri.parse(drmConfiguration.licenseServerUri)
|
||||
: Uri.EMPTY,
|
||||
drmConfiguration.httpRequestHeaders))));
|
||||
}
|
||||
playerManager.addItem(mediaItemBuilder.build());
|
||||
mediaQueueListAdapter.notifyItemInserted(playerManager.getMediaQueueSize() - 1);
|
||||
|
|
|
|||
|
|
@ -27,11 +27,33 @@ import java.util.List;
|
|||
*/
|
||||
public final class DefaultCastOptionsProvider implements OptionsProvider {
|
||||
|
||||
/**
|
||||
* App id of the Default Media Receiver app. Apps that do not require DRM support may use this
|
||||
* receiver receiver app ID.
|
||||
*
|
||||
* <p>See https://developers.google.com/cast/docs/caf_receiver/#default_media_receiver.
|
||||
*/
|
||||
public static final String APP_ID_DEFAULT_RECEIVER =
|
||||
CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID;
|
||||
|
||||
/**
|
||||
* App id for receiver app with rudimentary support for DRM.
|
||||
*
|
||||
* <p>This app id is only suitable for ExoPlayer's Cast Demo app, and it is not intended for
|
||||
* production use. In order to use DRM, custom receiver apps should be used. For environments that
|
||||
* do not require DRM, the default receiver app should be used (see {@link
|
||||
* #APP_ID_DEFAULT_RECEIVER}).
|
||||
*/
|
||||
// TODO: Add a documentation resource link for DRM support in the receiver app [Internal ref:
|
||||
// b/128603245].
|
||||
public static final String APP_ID_DEFAULT_RECEIVER_WITH_DRM = "A12D4273";
|
||||
|
||||
@Override
|
||||
public CastOptions getCastOptions(Context context) {
|
||||
return new CastOptions.Builder()
|
||||
.setReceiverApplicationId(CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID)
|
||||
.setStopReceiverApplicationWhenEndingSession(true).build();
|
||||
.setReceiverApplicationId(APP_ID_DEFAULT_RECEIVER_WITH_DRM)
|
||||
.setStopReceiverApplicationWhenEndingSession(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in a new issue