mirror of
https://github.com/samsonjs/media.git
synced 2026-03-26 09:35:47 +00:00
Remove Sample from SampleChooserActivity
Unmarshal from json to MediaItem instead of Sample. Further the playlist of MediaItems is converted to Intent extras which are read by the PlayerActivity. PiperOrigin-RevId: 308141231
This commit is contained in:
parent
7c3b461b64
commit
1323dd63d5
6 changed files with 289 additions and 349 deletions
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.demo;
|
||||
|
||||
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.net.Uri;
|
||||
|
|
@ -23,8 +25,8 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
import com.google.android.exoplayer2.RenderersFactory;
|
||||
import com.google.android.exoplayer2.demo.Sample.UriSample;
|
||||
import com.google.android.exoplayer2.offline.Download;
|
||||
import com.google.android.exoplayer2.offline.DownloadCursor;
|
||||
import com.google.android.exoplayer2.offline.DownloadHelper;
|
||||
|
|
@ -82,8 +84,8 @@ public class DownloadTracker {
|
|||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
public boolean isDownloaded(Uri uri) {
|
||||
Download download = downloads.get(uri);
|
||||
public boolean isDownloaded(MediaItem mediaItem) {
|
||||
Download download = downloads.get(checkNotNull(mediaItem.playbackProperties).sourceUri);
|
||||
return download != null && download.state != Download.STATE_FAILED;
|
||||
}
|
||||
|
||||
|
|
@ -93,8 +95,8 @@ public class DownloadTracker {
|
|||
}
|
||||
|
||||
public void toggleDownload(
|
||||
FragmentManager fragmentManager, UriSample sample, RenderersFactory renderersFactory) {
|
||||
Download download = downloads.get(sample.uri);
|
||||
FragmentManager fragmentManager, MediaItem mediaItem, RenderersFactory renderersFactory) {
|
||||
Download download = downloads.get(checkNotNull(mediaItem.playbackProperties).sourceUri);
|
||||
if (download != null) {
|
||||
DownloadService.sendRemoveDownload(
|
||||
context, DemoDownloadService.class, download.request.id, /* foreground= */ false);
|
||||
|
|
@ -104,9 +106,7 @@ public class DownloadTracker {
|
|||
}
|
||||
startDownloadDialogHelper =
|
||||
new StartDownloadDialogHelper(
|
||||
fragmentManager,
|
||||
getDownloadHelper(sample.uri, sample.extension, renderersFactory),
|
||||
sample);
|
||||
fragmentManager, getDownloadHelper(mediaItem, renderersFactory), mediaItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -121,18 +121,24 @@ public class DownloadTracker {
|
|||
}
|
||||
}
|
||||
|
||||
private DownloadHelper getDownloadHelper(
|
||||
Uri uri, String extension, RenderersFactory renderersFactory) {
|
||||
int type = Util.inferContentType(uri, extension);
|
||||
private DownloadHelper getDownloadHelper(MediaItem mediaItem, RenderersFactory renderersFactory) {
|
||||
MediaItem.PlaybackProperties playbackProperties = checkNotNull(mediaItem.playbackProperties);
|
||||
@C.ContentType
|
||||
int type =
|
||||
Util.inferContentTypeWithMimeType(
|
||||
playbackProperties.sourceUri, playbackProperties.mimeType);
|
||||
switch (type) {
|
||||
case C.TYPE_DASH:
|
||||
return DownloadHelper.forDash(context, uri, dataSourceFactory, renderersFactory);
|
||||
return DownloadHelper.forDash(
|
||||
context, playbackProperties.sourceUri, dataSourceFactory, renderersFactory);
|
||||
case C.TYPE_SS:
|
||||
return DownloadHelper.forSmoothStreaming(context, uri, dataSourceFactory, renderersFactory);
|
||||
return DownloadHelper.forSmoothStreaming(
|
||||
context, playbackProperties.sourceUri, dataSourceFactory, renderersFactory);
|
||||
case C.TYPE_HLS:
|
||||
return DownloadHelper.forHls(context, uri, dataSourceFactory, renderersFactory);
|
||||
return DownloadHelper.forHls(
|
||||
context, playbackProperties.sourceUri, dataSourceFactory, renderersFactory);
|
||||
case C.TYPE_OTHER:
|
||||
return DownloadHelper.forProgressive(context, uri);
|
||||
return DownloadHelper.forProgressive(context, playbackProperties.sourceUri);
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported type: " + type);
|
||||
}
|
||||
|
|
@ -166,16 +172,16 @@ public class DownloadTracker {
|
|||
|
||||
private final FragmentManager fragmentManager;
|
||||
private final DownloadHelper downloadHelper;
|
||||
private final UriSample sample;
|
||||
private final MediaItem mediaItem;
|
||||
|
||||
private TrackSelectionDialog trackSelectionDialog;
|
||||
private MappedTrackInfo mappedTrackInfo;
|
||||
|
||||
public StartDownloadDialogHelper(
|
||||
FragmentManager fragmentManager, DownloadHelper downloadHelper, UriSample sample) {
|
||||
FragmentManager fragmentManager, DownloadHelper downloadHelper, MediaItem mediaItem) {
|
||||
this.fragmentManager = fragmentManager;
|
||||
this.downloadHelper = downloadHelper;
|
||||
this.sample = sample;
|
||||
this.mediaItem = mediaItem;
|
||||
downloadHelper.prepare(this);
|
||||
}
|
||||
|
||||
|
|
@ -270,7 +276,8 @@ public class DownloadTracker {
|
|||
}
|
||||
|
||||
private DownloadRequest buildDownloadRequest() {
|
||||
return downloadHelper.getDownloadRequest(Util.getUtf8Bytes(sample.name));
|
||||
return downloadHelper.getDownloadRequest(
|
||||
Util.getUtf8Bytes(checkNotNull(mediaItem.mediaMetadata.title)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
package com.google.android.exoplayer2.demo;
|
||||
|
||||
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
|
||||
import static com.google.android.exoplayer2.util.Assertions.checkState;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
|
@ -23,6 +24,7 @@ import androidx.annotation.Nullable;
|
|||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
import com.google.android.exoplayer2.offline.DownloadRequest;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -32,9 +34,24 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** Util to read from an intent. */
|
||||
/** Util to read from and populate an intent. */
|
||||
public class IntentUtil {
|
||||
|
||||
/** A tag to hold custom playback configuration attributes. */
|
||||
public static class Tag {
|
||||
|
||||
/** Whether the stream is a live stream. */
|
||||
public final boolean isLive;
|
||||
/** The spherical stereo mode or null. */
|
||||
@Nullable public final String sphericalStereoMode;
|
||||
|
||||
/** Creates an instance. */
|
||||
public Tag(boolean isLive, @Nullable String sphericalStereoMode) {
|
||||
this.isLive = isLive;
|
||||
this.sphericalStereoMode = sphericalStereoMode;
|
||||
}
|
||||
}
|
||||
|
||||
// Actions.
|
||||
|
||||
public static final String ACTION_VIEW = "com.google.android.exoplayer.demo.action.VIEW";
|
||||
|
|
@ -57,8 +74,10 @@ public class IntentUtil {
|
|||
// Media item configuration extras.
|
||||
|
||||
public static final String URI_EXTRA = "uri";
|
||||
public static final String EXTENSION_EXTRA = "extension";
|
||||
public static final String IS_LIVE_EXTRA = "is_live";
|
||||
public static final String MIME_TYPE_EXTRA = "mime_type";
|
||||
// For backwards compatibility only.
|
||||
public static final String EXTENSION_EXTRA = "extension";
|
||||
|
||||
public static final String DRM_SCHEME_EXTRA = "drm_scheme";
|
||||
public static final String DRM_LICENSE_URL_EXTRA = "drm_license_url";
|
||||
|
|
@ -100,15 +119,56 @@ public class IntentUtil {
|
|||
return mediaItems;
|
||||
}
|
||||
|
||||
/** Populates the intent with the given list of {@link MediaItem media items}. */
|
||||
public static void addToIntent(List<MediaItem> mediaItems, Intent intent) {
|
||||
Assertions.checkArgument(!mediaItems.isEmpty());
|
||||
if (mediaItems.size() == 1) {
|
||||
MediaItem.PlaybackProperties playbackProperties =
|
||||
checkNotNull(mediaItems.get(0).playbackProperties);
|
||||
intent.setAction(IntentUtil.ACTION_VIEW).setData(playbackProperties.sourceUri);
|
||||
addPlaybackPropertiesToIntent(playbackProperties, intent, /* extrasKeySuffix= */ "");
|
||||
} else {
|
||||
intent.setAction(IntentUtil.ACTION_VIEW_LIST);
|
||||
for (int i = 0; i < mediaItems.size(); i++) {
|
||||
MediaItem.PlaybackProperties playbackProperties =
|
||||
checkNotNull(mediaItems.get(i).playbackProperties);
|
||||
intent.putExtra(IntentUtil.URI_EXTRA + ("_" + i), playbackProperties.sourceUri.toString());
|
||||
addPlaybackPropertiesToIntent(playbackProperties, intent, /* extrasKeySuffix= */ "_" + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Makes a best guess to infer the MIME type from a {@link Uri} and an optional extension. */
|
||||
@Nullable
|
||||
public static String inferAdaptiveStreamMimeType(Uri uri, @Nullable String extension) {
|
||||
@C.ContentType int contentType = Util.inferContentType(uri, extension);
|
||||
switch (contentType) {
|
||||
case C.TYPE_DASH:
|
||||
return MimeTypes.APPLICATION_MPD;
|
||||
case C.TYPE_HLS:
|
||||
return MimeTypes.APPLICATION_M3U8;
|
||||
case C.TYPE_SS:
|
||||
return MimeTypes.APPLICATION_SS;
|
||||
case C.TYPE_OTHER:
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static MediaItem createMediaItemFromIntent(
|
||||
Uri uri, Intent intent, String extrasKeySuffix, @Nullable DownloadRequest downloadRequest) {
|
||||
String extension = intent.getStringExtra(EXTENSION_EXTRA + extrasKeySuffix);
|
||||
String mimeType = intent.getStringExtra(MIME_TYPE_EXTRA + extrasKeySuffix);
|
||||
if (mimeType == null) {
|
||||
// Try to use extension for backwards compatibility.
|
||||
String extension = intent.getStringExtra(EXTENSION_EXTRA + extrasKeySuffix);
|
||||
mimeType = inferAdaptiveStreamMimeType(uri, extension);
|
||||
}
|
||||
MediaItem.Builder builder =
|
||||
new MediaItem.Builder()
|
||||
.setSourceUri(uri)
|
||||
.setStreamKeys(downloadRequest != null ? downloadRequest.streamKeys : null)
|
||||
.setCustomCacheKey(downloadRequest != null ? downloadRequest.customCacheKey : null)
|
||||
.setMimeType(inferAdaptiveStreamMimeType(uri, extension))
|
||||
.setMimeType(mimeType)
|
||||
.setAdTagUri(intent.getStringExtra(AD_TAG_URI_EXTRA + extrasKeySuffix))
|
||||
.setSubtitles(createSubtitlesFromIntent(intent, extrasKeySuffix));
|
||||
return populateDrmPropertiesFromIntent(builder, intent, extrasKeySuffix).build();
|
||||
|
|
@ -178,19 +238,57 @@ public class IntentUtil {
|
|||
return new ArrayList<>(trackTypes);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String inferAdaptiveStreamMimeType(Uri uri, @Nullable String extension) {
|
||||
@C.ContentType int contentType = Util.inferContentType(uri, extension);
|
||||
switch (contentType) {
|
||||
case C.TYPE_DASH:
|
||||
return MimeTypes.APPLICATION_MPD;
|
||||
case C.TYPE_HLS:
|
||||
return MimeTypes.APPLICATION_M3U8;
|
||||
case C.TYPE_SS:
|
||||
return MimeTypes.APPLICATION_SS;
|
||||
case C.TYPE_OTHER:
|
||||
default:
|
||||
return null;
|
||||
private static void addPlaybackPropertiesToIntent(
|
||||
MediaItem.PlaybackProperties playbackProperties, Intent intent, String extrasKeySuffix) {
|
||||
boolean isLive = false;
|
||||
String sphericalStereoMode = null;
|
||||
if (playbackProperties.tag instanceof Tag) {
|
||||
Tag tag = (Tag) playbackProperties.tag;
|
||||
isLive = tag.isLive;
|
||||
sphericalStereoMode = tag.sphericalStereoMode;
|
||||
}
|
||||
intent
|
||||
.putExtra(MIME_TYPE_EXTRA + extrasKeySuffix, playbackProperties.mimeType)
|
||||
.putExtra(
|
||||
AD_TAG_URI_EXTRA + extrasKeySuffix,
|
||||
playbackProperties.adTagUri != null ? playbackProperties.adTagUri.toString() : null)
|
||||
.putExtra(IS_LIVE_EXTRA + extrasKeySuffix, isLive)
|
||||
.putExtra(SPHERICAL_STEREO_MODE_EXTRA, sphericalStereoMode);
|
||||
if (playbackProperties.drmConfiguration != null) {
|
||||
addDrmConfigurationToIntent(playbackProperties.drmConfiguration, intent, extrasKeySuffix);
|
||||
}
|
||||
if (!playbackProperties.subtitles.isEmpty()) {
|
||||
checkState(playbackProperties.subtitles.size() == 1);
|
||||
MediaItem.Subtitle subtitle = playbackProperties.subtitles.get(0);
|
||||
intent.putExtra(SUBTITLE_URI_EXTRA + extrasKeySuffix, subtitle.uri.toString());
|
||||
intent.putExtra(SUBTITLE_MIME_TYPE_EXTRA + extrasKeySuffix, subtitle.mimeType);
|
||||
intent.putExtra(SUBTITLE_LANGUAGE_EXTRA + extrasKeySuffix, subtitle.language);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addDrmConfigurationToIntent(
|
||||
MediaItem.DrmConfiguration drmConfiguration, Intent intent, String extrasKeySuffix) {
|
||||
intent.putExtra(DRM_SCHEME_EXTRA + extrasKeySuffix, drmConfiguration.uuid.toString());
|
||||
intent.putExtra(
|
||||
DRM_LICENSE_URL_EXTRA + extrasKeySuffix,
|
||||
checkNotNull(drmConfiguration.licenseUri).toString());
|
||||
intent.putExtra(DRM_MULTI_SESSION_EXTRA + extrasKeySuffix, drmConfiguration.multiSession);
|
||||
|
||||
String[] drmKeyRequestProperties = new String[drmConfiguration.requestHeaders.size() * 2];
|
||||
int index = 0;
|
||||
for (Map.Entry<String, String> entry : drmConfiguration.requestHeaders.entrySet()) {
|
||||
drmKeyRequestProperties[index++] = entry.getKey();
|
||||
drmKeyRequestProperties[index++] = entry.getValue();
|
||||
}
|
||||
intent.putExtra(DRM_KEY_REQUEST_PROPERTIES_EXTRA + extrasKeySuffix, drmKeyRequestProperties);
|
||||
|
||||
ArrayList<String> typeStrings = new ArrayList<>();
|
||||
for (int type : drmConfiguration.sessionForClearTypes) {
|
||||
// Only audio and video are supported.
|
||||
Assertions.checkState(type == C.TRACK_TYPE_AUDIO || type == C.TRACK_TYPE_VIDEO);
|
||||
typeStrings.add(type == C.TRACK_TYPE_AUDIO ? "audio" : "video");
|
||||
}
|
||||
intent.putExtra(
|
||||
DRM_SESSION_FOR_CLEAR_TYPES_EXTRA + extrasKeySuffix, typeStrings.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,191 +0,0 @@
|
|||
/*
|
||||
* 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.demo;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.UUID;
|
||||
|
||||
/* package */ abstract class Sample {
|
||||
|
||||
public static final class UriSample extends Sample {
|
||||
|
||||
public final Uri uri;
|
||||
public final String extension;
|
||||
public final boolean isLive;
|
||||
public final DrmInfo drmInfo;
|
||||
public final Uri adTagUri;
|
||||
@Nullable public final String sphericalStereoMode;
|
||||
@Nullable SubtitleInfo subtitleInfo;
|
||||
|
||||
public UriSample(
|
||||
String name,
|
||||
Uri uri,
|
||||
String extension,
|
||||
boolean isLive,
|
||||
DrmInfo drmInfo,
|
||||
Uri adTagUri,
|
||||
@Nullable String sphericalStereoMode,
|
||||
@Nullable SubtitleInfo subtitleInfo) {
|
||||
super(name);
|
||||
this.uri = uri;
|
||||
this.extension = extension;
|
||||
this.isLive = isLive;
|
||||
this.drmInfo = drmInfo;
|
||||
this.adTagUri = adTagUri;
|
||||
this.sphericalStereoMode = sphericalStereoMode;
|
||||
this.subtitleInfo = subtitleInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToIntent(Intent intent) {
|
||||
intent.setAction(IntentUtil.ACTION_VIEW).setData(uri);
|
||||
intent.putExtra(IntentUtil.IS_LIVE_EXTRA, isLive);
|
||||
intent.putExtra(IntentUtil.SPHERICAL_STEREO_MODE_EXTRA, sphericalStereoMode);
|
||||
addPlayerConfigToIntent(intent, /* extrasKeySuffix= */ "");
|
||||
}
|
||||
|
||||
public void addToPlaylistIntent(Intent intent, String extrasKeySuffix) {
|
||||
intent.putExtra(IntentUtil.URI_EXTRA + extrasKeySuffix, uri.toString());
|
||||
intent.putExtra(IntentUtil.IS_LIVE_EXTRA + extrasKeySuffix, isLive);
|
||||
addPlayerConfigToIntent(intent, extrasKeySuffix);
|
||||
}
|
||||
|
||||
private void addPlayerConfigToIntent(Intent intent, String extrasKeySuffix) {
|
||||
intent
|
||||
.putExtra(IntentUtil.EXTENSION_EXTRA + extrasKeySuffix, extension)
|
||||
.putExtra(
|
||||
IntentUtil.AD_TAG_URI_EXTRA + extrasKeySuffix,
|
||||
adTagUri != null ? adTagUri.toString() : null);
|
||||
if (drmInfo != null) {
|
||||
drmInfo.addToIntent(intent, extrasKeySuffix);
|
||||
}
|
||||
if (subtitleInfo != null) {
|
||||
subtitleInfo.addToIntent(intent, extrasKeySuffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PlaylistSample extends Sample {
|
||||
|
||||
public final UriSample[] children;
|
||||
|
||||
public PlaylistSample(String name, UriSample... children) {
|
||||
super(name);
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToIntent(Intent intent) {
|
||||
intent.setAction(IntentUtil.ACTION_VIEW_LIST);
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
children[i].addToPlaylistIntent(intent, /* extrasKeySuffix= */ "_" + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class DrmInfo {
|
||||
|
||||
public final UUID drmScheme;
|
||||
public final String drmLicenseUrl;
|
||||
public final String[] drmKeyRequestProperties;
|
||||
public final int[] drmSessionForClearTypes;
|
||||
public final boolean drmMultiSession;
|
||||
|
||||
public DrmInfo(
|
||||
UUID drmScheme,
|
||||
String drmLicenseUrl,
|
||||
String[] drmKeyRequestProperties,
|
||||
int[] drmSessionForClearTypes,
|
||||
boolean drmMultiSession) {
|
||||
this.drmScheme = drmScheme;
|
||||
this.drmLicenseUrl = drmLicenseUrl;
|
||||
this.drmKeyRequestProperties = drmKeyRequestProperties;
|
||||
this.drmSessionForClearTypes = drmSessionForClearTypes;
|
||||
this.drmMultiSession = drmMultiSession;
|
||||
}
|
||||
|
||||
public void addToIntent(Intent intent, String extrasKeySuffix) {
|
||||
Assertions.checkNotNull(intent);
|
||||
intent.putExtra(IntentUtil.DRM_SCHEME_EXTRA + extrasKeySuffix, drmScheme.toString());
|
||||
intent.putExtra(IntentUtil.DRM_LICENSE_URL_EXTRA + extrasKeySuffix, drmLicenseUrl);
|
||||
intent.putExtra(
|
||||
IntentUtil.DRM_KEY_REQUEST_PROPERTIES_EXTRA + extrasKeySuffix, drmKeyRequestProperties);
|
||||
ArrayList<String> typeStrings = new ArrayList<>();
|
||||
for (int type : drmSessionForClearTypes) {
|
||||
// Only audio and video are supported.
|
||||
typeStrings.add(type == C.TRACK_TYPE_AUDIO ? "audio" : "video");
|
||||
}
|
||||
intent.putExtra(
|
||||
IntentUtil.DRM_SESSION_FOR_CLEAR_TYPES_EXTRA + extrasKeySuffix,
|
||||
typeStrings.toArray(new String[0]));
|
||||
intent.putExtra(IntentUtil.DRM_MULTI_SESSION_EXTRA + extrasKeySuffix, drmMultiSession);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SubtitleInfo {
|
||||
|
||||
public final Uri uri;
|
||||
public final String mimeType;
|
||||
@Nullable public final String language;
|
||||
|
||||
public SubtitleInfo(Uri uri, String mimeType, @Nullable String language) {
|
||||
this.uri = Assertions.checkNotNull(uri);
|
||||
this.mimeType = Assertions.checkNotNull(mimeType);
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
public void addToIntent(Intent intent, String extrasKeySuffix) {
|
||||
intent.putExtra(IntentUtil.SUBTITLE_URI_EXTRA + extrasKeySuffix, uri.toString());
|
||||
intent.putExtra(IntentUtil.SUBTITLE_MIME_TYPE_EXTRA + extrasKeySuffix, mimeType);
|
||||
intent.putExtra(IntentUtil.SUBTITLE_LANGUAGE_EXTRA + extrasKeySuffix, language);
|
||||
}
|
||||
}
|
||||
|
||||
public static int[] toTrackTypeArray(@Nullable String[] trackTypeStringsArray) {
|
||||
if (trackTypeStringsArray == null) {
|
||||
return new int[0];
|
||||
}
|
||||
HashSet<Integer> trackTypes = new HashSet<>();
|
||||
for (String trackTypeString : trackTypeStringsArray) {
|
||||
switch (Util.toLowerInvariant(trackTypeString)) {
|
||||
case "audio":
|
||||
trackTypes.add(C.TRACK_TYPE_AUDIO);
|
||||
break;
|
||||
case "video":
|
||||
trackTypes.add(C.TRACK_TYPE_VIDEO);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid track type: " + trackTypeString);
|
||||
}
|
||||
}
|
||||
return Util.toArray(new ArrayList<>(trackTypes));
|
||||
}
|
||||
|
||||
public final String name;
|
||||
|
||||
public Sample(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public abstract void addToIntent(Intent intent);
|
||||
}
|
||||
|
|
@ -15,10 +15,13 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.demo;
|
||||
|
||||
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.AssetManager;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
|
|
@ -39,11 +42,11 @@ import android.widget.Toast;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.MediaItem;
|
||||
import com.google.android.exoplayer2.MediaMetadata;
|
||||
import com.google.android.exoplayer2.ParserException;
|
||||
import com.google.android.exoplayer2.RenderersFactory;
|
||||
import com.google.android.exoplayer2.demo.Sample.DrmInfo;
|
||||
import com.google.android.exoplayer2.demo.Sample.PlaylistSample;
|
||||
import com.google.android.exoplayer2.demo.Sample.UriSample;
|
||||
import com.google.android.exoplayer2.offline.DownloadService;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DataSourceInputStream;
|
||||
|
|
@ -58,7 +61,10 @@ import java.io.InputStreamReader;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** An activity for selecting from a list of media samples. */
|
||||
public class SampleChooserActivity extends AppCompatActivity
|
||||
|
|
@ -182,7 +188,7 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
}
|
||||
|
||||
private void loadSample() {
|
||||
Assertions.checkNotNull(uris);
|
||||
checkNotNull(uris);
|
||||
|
||||
for (int i = 0; i < uris.length; i++) {
|
||||
Uri uri = Uri.parse(uris[i]);
|
||||
|
|
@ -195,12 +201,12 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
loaderTask.execute(uris);
|
||||
}
|
||||
|
||||
private void onSampleGroups(final List<SampleGroup> groups, boolean sawError) {
|
||||
private void onPlaylistGroups(final List<PlaylistGroup> groups, boolean sawError) {
|
||||
if (sawError) {
|
||||
Toast.makeText(getApplicationContext(), R.string.sample_list_load_error, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
sampleAdapter.setSampleGroups(groups);
|
||||
sampleAdapter.setPlaylistGroups(groups);
|
||||
|
||||
SharedPreferences preferences = getPreferences(MODE_PRIVATE);
|
||||
|
||||
|
|
@ -227,7 +233,7 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
prefEditor.putInt(CHILD_POSITION_PREFERENCE_KEY, childPosition);
|
||||
prefEditor.apply();
|
||||
|
||||
Sample sample = (Sample) view.getTag();
|
||||
PlaylistHolder playlistHolder = (PlaylistHolder) view.getTag();
|
||||
Intent intent = new Intent(this, PlayerActivity.class);
|
||||
intent.putExtra(
|
||||
IntentUtil.PREFER_EXTENSION_DECODERS_EXTRA,
|
||||
|
|
@ -238,13 +244,13 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
: IntentUtil.ABR_ALGORITHM_DEFAULT;
|
||||
intent.putExtra(IntentUtil.ABR_ALGORITHM_EXTRA, abrAlgorithm);
|
||||
intent.putExtra(IntentUtil.TUNNELING_EXTRA, isNonNullAndChecked(tunnelingMenuItem));
|
||||
sample.addToIntent(intent);
|
||||
IntentUtil.addToIntent(playlistHolder.mediaItems, intent);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onSampleDownloadButtonClicked(Sample sample) {
|
||||
int downloadUnsupportedStringId = getDownloadUnsupportedStringId(sample);
|
||||
private void onSampleDownloadButtonClicked(PlaylistHolder playlistHolder) {
|
||||
int downloadUnsupportedStringId = getDownloadUnsupportedStringId(playlistHolder);
|
||||
if (downloadUnsupportedStringId != 0) {
|
||||
Toast.makeText(getApplicationContext(), downloadUnsupportedStringId, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
|
|
@ -253,25 +259,26 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
((DemoApplication) getApplication())
|
||||
.buildRenderersFactory(isNonNullAndChecked(preferExtensionDecodersMenuItem));
|
||||
downloadTracker.toggleDownload(
|
||||
getSupportFragmentManager(), (UriSample) sample, renderersFactory);
|
||||
getSupportFragmentManager(), playlistHolder.mediaItems.get(0), renderersFactory);
|
||||
}
|
||||
}
|
||||
|
||||
private int getDownloadUnsupportedStringId(Sample sample) {
|
||||
if (sample instanceof PlaylistSample) {
|
||||
private int getDownloadUnsupportedStringId(PlaylistHolder playlistHolder) {
|
||||
if (playlistHolder.mediaItems.size() > 1) {
|
||||
return R.string.download_playlist_unsupported;
|
||||
}
|
||||
UriSample uriSample = (UriSample) sample;
|
||||
if (uriSample.drmInfo != null) {
|
||||
MediaItem.PlaybackProperties playbackProperties =
|
||||
checkNotNull(playlistHolder.mediaItems.get(0).playbackProperties);
|
||||
if (playbackProperties.drmConfiguration != null) {
|
||||
return R.string.download_drm_unsupported;
|
||||
}
|
||||
if (uriSample.isLive) {
|
||||
if (((IntentUtil.Tag) checkNotNull(playbackProperties.tag)).isLive) {
|
||||
return R.string.download_live_unsupported;
|
||||
}
|
||||
if (uriSample.adTagUri != null) {
|
||||
if (playbackProperties.adTagUri != null) {
|
||||
return R.string.download_ads_unsupported;
|
||||
}
|
||||
String scheme = uriSample.uri.getScheme();
|
||||
String scheme = playbackProperties.sourceUri.getScheme();
|
||||
if (!("http".equals(scheme) || "https".equals(scheme))) {
|
||||
return R.string.download_scheme_unsupported;
|
||||
}
|
||||
|
|
@ -283,13 +290,13 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
return menuItem != null && menuItem.isChecked();
|
||||
}
|
||||
|
||||
private final class SampleListLoader extends AsyncTask<String, Void, List<SampleGroup>> {
|
||||
private final class SampleListLoader extends AsyncTask<String, Void, List<PlaylistGroup>> {
|
||||
|
||||
private boolean sawError;
|
||||
|
||||
@Override
|
||||
protected List<SampleGroup> doInBackground(String... uris) {
|
||||
List<SampleGroup> result = new ArrayList<>();
|
||||
protected List<PlaylistGroup> doInBackground(String... uris) {
|
||||
List<PlaylistGroup> result = new ArrayList<>();
|
||||
Context context = getApplicationContext();
|
||||
String userAgent = Util.getUserAgent(context, "ExoPlayerDemo");
|
||||
DataSource dataSource =
|
||||
|
|
@ -298,7 +305,7 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
DataSpec dataSpec = new DataSpec(Uri.parse(uri));
|
||||
InputStream inputStream = new DataSourceInputStream(dataSource, dataSpec);
|
||||
try {
|
||||
readSampleGroups(new JsonReader(new InputStreamReader(inputStream, "UTF-8")), result);
|
||||
readPlaylistGroups(new JsonReader(new InputStreamReader(inputStream, "UTF-8")), result);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error loading sample list: " + uri, e);
|
||||
sawError = true;
|
||||
|
|
@ -310,21 +317,23 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<SampleGroup> result) {
|
||||
onSampleGroups(result, sawError);
|
||||
protected void onPostExecute(List<PlaylistGroup> result) {
|
||||
onPlaylistGroups(result, sawError);
|
||||
}
|
||||
|
||||
private void readSampleGroups(JsonReader reader, List<SampleGroup> groups) throws IOException {
|
||||
private void readPlaylistGroups(JsonReader reader, List<PlaylistGroup> groups)
|
||||
throws IOException {
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
readSampleGroup(reader, groups);
|
||||
readPlaylistGroup(reader, groups);
|
||||
}
|
||||
reader.endArray();
|
||||
}
|
||||
|
||||
private void readSampleGroup(JsonReader reader, List<SampleGroup> groups) throws IOException {
|
||||
private void readPlaylistGroup(JsonReader reader, List<PlaylistGroup> groups)
|
||||
throws IOException {
|
||||
String groupName = "";
|
||||
ArrayList<Sample> samples = new ArrayList<>();
|
||||
ArrayList<PlaylistHolder> playlistHolders = new ArrayList<>();
|
||||
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
|
|
@ -336,7 +345,7 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
case "samples":
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
samples.add(readEntry(reader, false));
|
||||
playlistHolders.add(readEntry(reader, false));
|
||||
}
|
||||
reader.endArray();
|
||||
break;
|
||||
|
|
@ -349,34 +358,28 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
}
|
||||
reader.endObject();
|
||||
|
||||
SampleGroup group = getGroup(groupName, groups);
|
||||
group.samples.addAll(samples);
|
||||
PlaylistGroup group = getGroup(groupName, groups);
|
||||
group.playlists.addAll(playlistHolders);
|
||||
}
|
||||
|
||||
private Sample readEntry(JsonReader reader, boolean insidePlaylist) throws IOException {
|
||||
String sampleName = null;
|
||||
private PlaylistHolder readEntry(JsonReader reader, boolean insidePlaylist) throws IOException {
|
||||
Uri uri = null;
|
||||
String extension = null;
|
||||
String title = null;
|
||||
boolean isLive = false;
|
||||
String drmScheme = null;
|
||||
String drmLicenseUrl = null;
|
||||
String[] drmKeyRequestProperties = null;
|
||||
String[] drmSessionForClearTypes = null;
|
||||
boolean drmMultiSession = false;
|
||||
ArrayList<UriSample> playlistSamples = null;
|
||||
String adTagUri = null;
|
||||
String sphericalStereoMode = null;
|
||||
List<Sample.SubtitleInfo> subtitleInfos = new ArrayList<>();
|
||||
ArrayList<PlaylistHolder> children = null;
|
||||
Uri subtitleUri = null;
|
||||
String subtitleMimeType = null;
|
||||
String subtitleLanguage = null;
|
||||
|
||||
MediaItem.Builder mediaItem = new MediaItem.Builder();
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
String name = reader.nextName();
|
||||
switch (name) {
|
||||
case "name":
|
||||
sampleName = reader.nextString();
|
||||
title = reader.nextString();
|
||||
break;
|
||||
case "uri":
|
||||
uri = Uri.parse(reader.nextString());
|
||||
|
|
@ -385,47 +388,46 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
extension = reader.nextString();
|
||||
break;
|
||||
case "drm_scheme":
|
||||
drmScheme = reader.nextString();
|
||||
mediaItem.setDrmUuid(Util.getDrmUuid(reader.nextString()));
|
||||
break;
|
||||
case "is_live":
|
||||
isLive = reader.nextBoolean();
|
||||
break;
|
||||
case "drm_license_url":
|
||||
drmLicenseUrl = reader.nextString();
|
||||
mediaItem.setDrmLicenseUri(reader.nextString());
|
||||
break;
|
||||
case "drm_key_request_properties":
|
||||
ArrayList<String> drmKeyRequestPropertiesList = new ArrayList<>();
|
||||
Map<String, String> requestHeaders = new HashMap<>();
|
||||
reader.beginObject();
|
||||
while (reader.hasNext()) {
|
||||
drmKeyRequestPropertiesList.add(reader.nextName());
|
||||
drmKeyRequestPropertiesList.add(reader.nextString());
|
||||
requestHeaders.put(reader.nextName(), reader.nextString());
|
||||
}
|
||||
reader.endObject();
|
||||
drmKeyRequestProperties = drmKeyRequestPropertiesList.toArray(new String[0]);
|
||||
mediaItem.setDrmLicenseRequestHeaders(requestHeaders);
|
||||
break;
|
||||
case "drm_session_for_clear_types":
|
||||
ArrayList<String> drmSessionForClearTypesList = new ArrayList<>();
|
||||
HashSet<Integer> drmSessionForClearTypes = new HashSet<>();
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
drmSessionForClearTypesList.add(reader.nextString());
|
||||
drmSessionForClearTypes.add(toTrackType(reader.nextString()));
|
||||
}
|
||||
reader.endArray();
|
||||
drmSessionForClearTypes = drmSessionForClearTypesList.toArray(new String[0]);
|
||||
mediaItem.setDrmSessionForClearTypes(new ArrayList<>(drmSessionForClearTypes));
|
||||
break;
|
||||
case "drm_multi_session":
|
||||
drmMultiSession = reader.nextBoolean();
|
||||
mediaItem.setDrmMultiSession(reader.nextBoolean());
|
||||
break;
|
||||
case "playlist":
|
||||
Assertions.checkState(!insidePlaylist, "Invalid nesting of playlists");
|
||||
playlistSamples = new ArrayList<>();
|
||||
children = new ArrayList<>();
|
||||
reader.beginArray();
|
||||
while (reader.hasNext()) {
|
||||
playlistSamples.add((UriSample) readEntry(reader, /* insidePlaylist= */ true));
|
||||
children.add(readEntry(reader, /* insidePlaylist= */ true));
|
||||
}
|
||||
reader.endArray();
|
||||
break;
|
||||
case "ad_tag_uri":
|
||||
adTagUri = reader.nextString();
|
||||
mediaItem.setAdTagUri(reader.nextString());
|
||||
break;
|
||||
case "spherical_stereo_mode":
|
||||
Assertions.checkState(
|
||||
|
|
@ -446,67 +448,71 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
}
|
||||
}
|
||||
reader.endObject();
|
||||
DrmInfo drmInfo =
|
||||
drmScheme == null
|
||||
? null
|
||||
: new DrmInfo(
|
||||
Util.getDrmUuid(drmScheme),
|
||||
drmLicenseUrl,
|
||||
drmKeyRequestProperties,
|
||||
Sample.toTrackTypeArray(drmSessionForClearTypes),
|
||||
drmMultiSession);
|
||||
Sample.SubtitleInfo subtitleInfo =
|
||||
subtitleUri == null
|
||||
? null
|
||||
: new Sample.SubtitleInfo(
|
||||
|
||||
if (children != null) {
|
||||
List<MediaItem> mediaItems = new ArrayList<>();
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
mediaItems.addAll(children.get(i).mediaItems);
|
||||
}
|
||||
return new PlaylistHolder(title, mediaItems);
|
||||
} else {
|
||||
mediaItem
|
||||
.setSourceUri(uri)
|
||||
.setMediaMetadata(new MediaMetadata.Builder().setTitle(title).build())
|
||||
.setMimeType(IntentUtil.inferAdaptiveStreamMimeType(uri, extension))
|
||||
.setTag(new IntentUtil.Tag(isLive, sphericalStereoMode));
|
||||
if (subtitleUri != null) {
|
||||
MediaItem.Subtitle subtitle =
|
||||
new MediaItem.Subtitle(
|
||||
subtitleUri,
|
||||
Assertions.checkNotNull(
|
||||
checkNotNull(
|
||||
subtitleMimeType, "subtitle_mime_type is required if subtitle_uri is set."),
|
||||
subtitleLanguage);
|
||||
if (playlistSamples != null) {
|
||||
UriSample[] playlistSamplesArray = playlistSamples.toArray(new UriSample[0]);
|
||||
return new PlaylistSample(sampleName, playlistSamplesArray);
|
||||
} else {
|
||||
return new UriSample(
|
||||
sampleName,
|
||||
uri,
|
||||
extension,
|
||||
isLive,
|
||||
drmInfo,
|
||||
adTagUri != null ? Uri.parse(adTagUri) : null,
|
||||
sphericalStereoMode,
|
||||
subtitleInfo);
|
||||
mediaItem.setSubtitles(Collections.singletonList(subtitle));
|
||||
}
|
||||
return new PlaylistHolder(title, Collections.singletonList(mediaItem.build()));
|
||||
}
|
||||
}
|
||||
|
||||
private SampleGroup getGroup(String groupName, List<SampleGroup> groups) {
|
||||
private PlaylistGroup getGroup(String groupName, List<PlaylistGroup> groups) {
|
||||
for (int i = 0; i < groups.size(); i++) {
|
||||
if (Util.areEqual(groupName, groups.get(i).title)) {
|
||||
return groups.get(i);
|
||||
}
|
||||
}
|
||||
SampleGroup group = new SampleGroup(groupName);
|
||||
PlaylistGroup group = new PlaylistGroup(groupName);
|
||||
groups.add(group);
|
||||
return group;
|
||||
}
|
||||
|
||||
private int toTrackType(String trackTypeString) {
|
||||
switch (Util.toLowerInvariant(trackTypeString)) {
|
||||
case "audio":
|
||||
return C.TRACK_TYPE_AUDIO;
|
||||
case "video":
|
||||
return C.TRACK_TYPE_VIDEO;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid track type: " + trackTypeString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class SampleAdapter extends BaseExpandableListAdapter implements OnClickListener {
|
||||
|
||||
private List<SampleGroup> sampleGroups;
|
||||
private List<PlaylistGroup> playlistGroups;
|
||||
|
||||
public SampleAdapter() {
|
||||
sampleGroups = Collections.emptyList();
|
||||
playlistGroups = Collections.emptyList();
|
||||
}
|
||||
|
||||
public void setSampleGroups(List<SampleGroup> sampleGroups) {
|
||||
this.sampleGroups = sampleGroups;
|
||||
public void setPlaylistGroups(List<PlaylistGroup> playlistGroups) {
|
||||
this.playlistGroups = playlistGroups;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Sample getChild(int groupPosition, int childPosition) {
|
||||
return getGroup(groupPosition).samples.get(childPosition);
|
||||
public PlaylistHolder getChild(int groupPosition, int childPosition) {
|
||||
return getGroup(groupPosition).playlists.get(childPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -534,12 +540,12 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
|
||||
@Override
|
||||
public int getChildrenCount(int groupPosition) {
|
||||
return getGroup(groupPosition).samples.size();
|
||||
return getGroup(groupPosition).playlists.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SampleGroup getGroup(int groupPosition) {
|
||||
return sampleGroups.get(groupPosition);
|
||||
public PlaylistGroup getGroup(int groupPosition) {
|
||||
return playlistGroups.get(groupPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -562,7 +568,7 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
|
||||
@Override
|
||||
public int getGroupCount() {
|
||||
return sampleGroups.size();
|
||||
return playlistGroups.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -577,18 +583,19 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
onSampleDownloadButtonClicked((Sample) view.getTag());
|
||||
onSampleDownloadButtonClicked((PlaylistHolder) view.getTag());
|
||||
}
|
||||
|
||||
private void initializeChildView(View view, Sample sample) {
|
||||
view.setTag(sample);
|
||||
private void initializeChildView(View view, PlaylistHolder playlistHolder) {
|
||||
view.setTag(playlistHolder);
|
||||
TextView sampleTitle = view.findViewById(R.id.sample_title);
|
||||
sampleTitle.setText(sample.name);
|
||||
sampleTitle.setText(playlistHolder.title);
|
||||
|
||||
boolean canDownload = getDownloadUnsupportedStringId(sample) == 0;
|
||||
boolean isDownloaded = canDownload && downloadTracker.isDownloaded(((UriSample) sample).uri);
|
||||
boolean canDownload = getDownloadUnsupportedStringId(playlistHolder) == 0;
|
||||
boolean isDownloaded =
|
||||
canDownload && downloadTracker.isDownloaded(playlistHolder.mediaItems.get(0));
|
||||
ImageButton downloadButton = view.findViewById(R.id.download_button);
|
||||
downloadButton.setTag(sample);
|
||||
downloadButton.setTag(playlistHolder);
|
||||
downloadButton.setColorFilter(
|
||||
canDownload ? (isDownloaded ? 0xFF42A5F5 : 0xFFBDBDBD) : 0xFF666666);
|
||||
downloadButton.setImageResource(
|
||||
|
|
@ -596,14 +603,26 @@ public class SampleChooserActivity extends AppCompatActivity
|
|||
}
|
||||
}
|
||||
|
||||
private static final class SampleGroup {
|
||||
private static final class PlaylistHolder {
|
||||
|
||||
public final String title;
|
||||
public final List<Sample> samples;
|
||||
public final List<MediaItem> mediaItems;
|
||||
|
||||
public SampleGroup(String title) {
|
||||
private PlaylistHolder(String title, List<MediaItem> mediaItems) {
|
||||
Assertions.checkArgument(!mediaItems.isEmpty());
|
||||
this.title = title;
|
||||
this.samples = new ArrayList<>();
|
||||
this.mediaItems = Collections.unmodifiableList(new ArrayList<>(mediaItems));
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PlaylistGroup {
|
||||
|
||||
public final String title;
|
||||
public final List<PlaylistHolder> playlists;
|
||||
|
||||
public PlaylistGroup(String title) {
|
||||
this.title = title;
|
||||
this.playlists = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1668,6 +1668,29 @@ public final class Util {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a best guess to infer the type from a {@link Uri} and MIME type.
|
||||
*
|
||||
* @param uri The {@link Uri}.
|
||||
* @param mimeType If not null, used to infer the type.
|
||||
* @return The content type.
|
||||
*/
|
||||
public static int inferContentTypeWithMimeType(Uri uri, @Nullable String mimeType) {
|
||||
if (mimeType == null) {
|
||||
return Util.inferContentType(uri);
|
||||
}
|
||||
switch (mimeType) {
|
||||
case MimeTypes.APPLICATION_MPD:
|
||||
return C.TYPE_DASH;
|
||||
case MimeTypes.APPLICATION_M3U8:
|
||||
return C.TYPE_HLS;
|
||||
case MimeTypes.APPLICATION_SS:
|
||||
return C.TYPE_SS;
|
||||
default:
|
||||
return Util.inferContentType(uri);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the specified millisecond time formatted as a string.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
|
|||
Assertions.checkNotNull(mediaItem.playbackProperties);
|
||||
@C.ContentType
|
||||
int type =
|
||||
inferContentType(
|
||||
Util.inferContentTypeWithMimeType(
|
||||
mediaItem.playbackProperties.sourceUri, mediaItem.playbackProperties.mimeType);
|
||||
@Nullable MediaSourceFactory mediaSourceFactory = mediaSourceFactories.get(type);
|
||||
Assertions.checkNotNull(
|
||||
|
|
@ -396,20 +396,4 @@ public final class DefaultMediaSourceFactory implements MediaSourceFactory {
|
|||
factories.put(C.TYPE_OTHER, new ProgressiveMediaSource.Factory(dataSourceFactory));
|
||||
return factories;
|
||||
}
|
||||
|
||||
private static int inferContentType(Uri sourceUri, @Nullable String mimeType) {
|
||||
if (mimeType == null) {
|
||||
return Util.inferContentType(sourceUri);
|
||||
}
|
||||
switch (mimeType) {
|
||||
case MimeTypes.APPLICATION_MPD:
|
||||
return C.TYPE_DASH;
|
||||
case MimeTypes.APPLICATION_M3U8:
|
||||
return C.TYPE_HLS;
|
||||
case MimeTypes.APPLICATION_SS:
|
||||
return C.TYPE_SS;
|
||||
default:
|
||||
return Util.inferContentType(sourceUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue