mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Cast: Add JSON serialization/deserialization for MediaItem
This will allow the Cast extension to reconstruct MediaItems from MediaQueueItems obtained from the receiver's queue. PiperOrigin-RevId: 260554381
This commit is contained in:
parent
46855884f5
commit
8be78d47ac
3 changed files with 181 additions and 23 deletions
|
|
@ -15,41 +15,132 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.ext.cast;
|
package com.google.android.exoplayer2.ext.cast;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.ext.cast.MediaItem.DrmConfiguration;
|
||||||
import com.google.android.gms.cast.MediaInfo;
|
import com.google.android.gms.cast.MediaInfo;
|
||||||
import com.google.android.gms.cast.MediaMetadata;
|
import com.google.android.gms.cast.MediaMetadata;
|
||||||
import com.google.android.gms.cast.MediaQueueItem;
|
import com.google.android.gms.cast.MediaQueueItem;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.UUID;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
/** Default {@link MediaItemConverter} implementation. */
|
/** Default {@link MediaItemConverter} implementation. */
|
||||||
public final class DefaultMediaItemConverter implements MediaItemConverter {
|
public final class DefaultMediaItemConverter implements MediaItemConverter {
|
||||||
|
|
||||||
|
private static final String KEY_MEDIA_ITEM = "mediaItem";
|
||||||
|
private static final String KEY_PLAYER_CONFIG = "exoPlayerConfig";
|
||||||
|
private static final String KEY_URI = "uri";
|
||||||
|
private static final String KEY_TITLE = "title";
|
||||||
|
private static final String KEY_MIME_TYPE = "mimeType";
|
||||||
|
private static final String KEY_DRM_CONFIGURATION = "drmConfiguration";
|
||||||
|
private static final String KEY_UUID = "uuid";
|
||||||
|
private static final String KEY_LICENSE_URI = "licenseUri";
|
||||||
|
private static final String KEY_REQUEST_HEADERS = "requestHeaders";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MediaItem toMediaItem(MediaQueueItem item) {
|
||||||
|
return getMediaItem(item.getMedia().getCustomData());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MediaQueueItem toMediaQueueItem(MediaItem item) {
|
public MediaQueueItem toMediaQueueItem(MediaItem item) {
|
||||||
if (item.mimeType == null) {
|
if (item.mimeType == null) {
|
||||||
throw new IllegalArgumentException("The item must specify its mimeType");
|
throw new IllegalArgumentException("The item must specify its mimeType");
|
||||||
}
|
}
|
||||||
MediaMetadata movieMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE);
|
MediaMetadata metadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE);
|
||||||
if (item.title != null) {
|
if (item.title != null) {
|
||||||
movieMetadata.putString(MediaMetadata.KEY_TITLE, item.title);
|
metadata.putString(MediaMetadata.KEY_TITLE, item.title);
|
||||||
}
|
}
|
||||||
MediaInfo mediaInfo =
|
MediaInfo mediaInfo =
|
||||||
new MediaInfo.Builder(item.uri.toString())
|
new MediaInfo.Builder(item.uri.toString())
|
||||||
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
|
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
|
||||||
.setContentType(item.mimeType)
|
.setContentType(item.mimeType)
|
||||||
.setMetadata(movieMetadata)
|
.setMetadata(metadata)
|
||||||
.setCustomData(getCustomData(item))
|
.setCustomData(getCustomData(item))
|
||||||
.build();
|
.build();
|
||||||
return new MediaQueueItem.Builder(mediaInfo).build();
|
return new MediaQueueItem.Builder(mediaInfo).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JSONObject getCustomData(MediaItem item) {
|
// Deserialization.
|
||||||
JSONObject customData = new JSONObject();
|
|
||||||
|
|
||||||
MediaItem.DrmConfiguration drmConfiguration = item.drmConfiguration;
|
private static MediaItem getMediaItem(JSONObject customData) {
|
||||||
|
try {
|
||||||
|
JSONObject mediaItemJson = customData.getJSONObject(KEY_MEDIA_ITEM);
|
||||||
|
MediaItem.Builder builder = new MediaItem.Builder();
|
||||||
|
builder.setUri(Uri.parse(mediaItemJson.getString(KEY_URI)));
|
||||||
|
if (mediaItemJson.has(KEY_TITLE)) {
|
||||||
|
builder.setTitle(mediaItemJson.getString(KEY_TITLE));
|
||||||
|
}
|
||||||
|
if (mediaItemJson.has(KEY_MIME_TYPE)) {
|
||||||
|
builder.setMimeType(mediaItemJson.getString(KEY_MIME_TYPE));
|
||||||
|
}
|
||||||
|
if (mediaItemJson.has(KEY_DRM_CONFIGURATION)) {
|
||||||
|
builder.setDrmConfiguration(
|
||||||
|
getDrmConfiguration(mediaItemJson.getJSONObject(KEY_DRM_CONFIGURATION)));
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
} catch (JSONException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DrmConfiguration getDrmConfiguration(JSONObject json) throws JSONException {
|
||||||
|
UUID uuid = UUID.fromString(json.getString(KEY_UUID));
|
||||||
|
Uri licenseUri = Uri.parse(json.getString(KEY_LICENSE_URI));
|
||||||
|
JSONObject requestHeadersJson = json.getJSONObject(KEY_REQUEST_HEADERS);
|
||||||
|
HashMap<String, String> requestHeaders = new HashMap<>();
|
||||||
|
for (Iterator<String> iterator = requestHeadersJson.keys(); iterator.hasNext(); ) {
|
||||||
|
String key = iterator.next();
|
||||||
|
requestHeaders.put(key, requestHeadersJson.getString(key));
|
||||||
|
}
|
||||||
|
return new DrmConfiguration(uuid, licenseUri, requestHeaders);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialization.
|
||||||
|
|
||||||
|
private static JSONObject getCustomData(MediaItem item) {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
try {
|
||||||
|
json.put(KEY_MEDIA_ITEM, getMediaItemJson(item));
|
||||||
|
JSONObject playerConfigJson = getPlayerConfigJson(item);
|
||||||
|
if (playerConfigJson != null) {
|
||||||
|
json.put(KEY_PLAYER_CONFIG, playerConfigJson);
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JSONObject getMediaItemJson(MediaItem item) throws JSONException {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
json.put(KEY_URI, item.uri.toString());
|
||||||
|
json.put(KEY_TITLE, item.title);
|
||||||
|
json.put(KEY_MIME_TYPE, item.mimeType);
|
||||||
|
if (item.drmConfiguration != null) {
|
||||||
|
json.put(KEY_DRM_CONFIGURATION, getDrmConfigurationJson(item.drmConfiguration));
|
||||||
|
}
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JSONObject getDrmConfigurationJson(DrmConfiguration drmConfiguration)
|
||||||
|
throws JSONException {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
json.put(KEY_UUID, drmConfiguration.uuid);
|
||||||
|
json.put(KEY_LICENSE_URI, drmConfiguration.licenseUri);
|
||||||
|
json.put(KEY_REQUEST_HEADERS, new JSONObject(drmConfiguration.requestHeaders));
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static JSONObject getPlayerConfigJson(MediaItem item) throws JSONException {
|
||||||
|
DrmConfiguration drmConfiguration = item.drmConfiguration;
|
||||||
if (drmConfiguration == null) {
|
if (drmConfiguration == null) {
|
||||||
return customData;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String drmScheme;
|
String drmScheme;
|
||||||
|
|
@ -58,24 +149,19 @@ public final class DefaultMediaItemConverter implements MediaItemConverter {
|
||||||
} else if (C.PLAYREADY_UUID.equals(drmConfiguration.uuid)) {
|
} else if (C.PLAYREADY_UUID.equals(drmConfiguration.uuid)) {
|
||||||
drmScheme = "playready";
|
drmScheme = "playready";
|
||||||
} else {
|
} else {
|
||||||
return customData;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject exoPlayerConfig = new JSONObject();
|
JSONObject exoPlayerConfigJson = new JSONObject();
|
||||||
try {
|
exoPlayerConfigJson.put("withCredentials", false);
|
||||||
exoPlayerConfig.put("withCredentials", false);
|
exoPlayerConfigJson.put("protectionSystem", drmScheme);
|
||||||
exoPlayerConfig.put("protectionSystem", drmScheme);
|
if (drmConfiguration.licenseUri != null) {
|
||||||
if (drmConfiguration.licenseUri != null) {
|
exoPlayerConfigJson.put("licenseUrl", drmConfiguration.licenseUri);
|
||||||
exoPlayerConfig.put("licenseUrl", drmConfiguration.licenseUri);
|
}
|
||||||
}
|
if (!drmConfiguration.requestHeaders.isEmpty()) {
|
||||||
if (!drmConfiguration.requestHeaders.isEmpty()) {
|
exoPlayerConfigJson.put("headers", new JSONObject(drmConfiguration.requestHeaders));
|
||||||
exoPlayerConfig.put("headers", new JSONObject(drmConfiguration.requestHeaders));
|
|
||||||
}
|
|
||||||
customData.put("exoPlayerConfig", exoPlayerConfig);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return customData;
|
return exoPlayerConfigJson;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,5 +28,11 @@ public interface MediaItemConverter {
|
||||||
*/
|
*/
|
||||||
MediaQueueItem toMediaQueueItem(MediaItem mediaItem);
|
MediaQueueItem toMediaQueueItem(MediaItem mediaItem);
|
||||||
|
|
||||||
// TODO: Add toMediaItem to convert in the opposite direction.
|
/**
|
||||||
|
* Converts a {@link MediaQueueItem} to a {@link MediaItem}.
|
||||||
|
*
|
||||||
|
* @param mediaQueueItem The {@link MediaQueueItem}.
|
||||||
|
* @return The equivalent {@link MediaItem}.
|
||||||
|
*/
|
||||||
|
MediaItem toMediaItem(MediaQueueItem mediaQueueItem);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.google.android.exoplayer2.ext.cast;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.ext.cast.MediaItem.DrmConfiguration;
|
||||||
|
import com.google.android.gms.cast.MediaQueueItem;
|
||||||
|
import java.util.Collections;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
/** Test for {@link DefaultMediaItemConverter}. */
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class DefaultMediaItemConverterTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void serialize_deserialize_minimal() {
|
||||||
|
MediaItem.Builder builder = new MediaItem.Builder();
|
||||||
|
MediaItem item = builder.setUri(Uri.parse("http://example.com")).setMimeType("mime").build();
|
||||||
|
|
||||||
|
DefaultMediaItemConverter converter = new DefaultMediaItemConverter();
|
||||||
|
MediaQueueItem queueItem = converter.toMediaQueueItem(item);
|
||||||
|
MediaItem reconstructedItem = converter.toMediaItem(queueItem);
|
||||||
|
|
||||||
|
assertThat(reconstructedItem).isEqualTo(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void serialize_deserialize_complete() {
|
||||||
|
MediaItem.Builder builder = new MediaItem.Builder();
|
||||||
|
MediaItem item =
|
||||||
|
builder
|
||||||
|
.setUri(Uri.parse("http://example.com"))
|
||||||
|
.setTitle("title")
|
||||||
|
.setMimeType("mime")
|
||||||
|
.setDrmConfiguration(
|
||||||
|
new DrmConfiguration(
|
||||||
|
C.WIDEVINE_UUID,
|
||||||
|
Uri.parse("http://license.com"),
|
||||||
|
Collections.singletonMap("key", "value")))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
DefaultMediaItemConverter converter = new DefaultMediaItemConverter();
|
||||||
|
MediaQueueItem queueItem = converter.toMediaQueueItem(item);
|
||||||
|
MediaItem reconstructedItem = converter.toMediaItem(queueItem);
|
||||||
|
|
||||||
|
assertThat(reconstructedItem).isEqualTo(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue