mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Support playlists in exolist.json.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=126622342
This commit is contained in:
parent
9f017d71ef
commit
f0f25aef83
3 changed files with 135 additions and 29 deletions
|
|
@ -330,5 +330,32 @@
|
||||||
"uri": "http://vod.leasewebcdn.com/bbb.flv?ri=1024&rs=150&start=0"
|
"uri": "http://vod.leasewebcdn.com/bbb.flv?ri=1024&rs=150&start=0"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Playlists",
|
||||||
|
"samples": [
|
||||||
|
{
|
||||||
|
"name": "Cats and dogs",
|
||||||
|
"playlist": [
|
||||||
|
{
|
||||||
|
"uri": "http://html5demos.com/assets/dizzy.mp4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "http://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Audio then Video",
|
||||||
|
"playlist": [
|
||||||
|
{
|
||||||
|
"uri": "https://storage.googleapis.com/exoplayer-test-media-1/gen-3/screens/dash-vod-single-segment/audio-141.mp4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "http://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -87,15 +87,18 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
||||||
ExoPlayer.EventListener, SimpleExoPlayer.VideoListener, SimpleExoPlayer.CaptionListener,
|
ExoPlayer.EventListener, SimpleExoPlayer.VideoListener, SimpleExoPlayer.CaptionListener,
|
||||||
SimpleExoPlayer.Id3MetadataListener, DefaultTrackSelector.EventListener {
|
SimpleExoPlayer.Id3MetadataListener, DefaultTrackSelector.EventListener {
|
||||||
|
|
||||||
public static final String URIS_LIST_EXTRA = "uris";
|
|
||||||
public static final String CONTENT_EXT_EXTRA = "extension";
|
|
||||||
public static final String DRM_SCHEME_UUID_EXTRA = "drm_scheme_uuid";
|
public static final String DRM_SCHEME_UUID_EXTRA = "drm_scheme_uuid";
|
||||||
public static final String DRM_CONTENT_ID_EXTRA = "drm_content_id";
|
public static final String DRM_CONTENT_ID_EXTRA = "drm_content_id";
|
||||||
public static final String DRM_PROVIDER_EXTRA = "drm_provider";
|
public static final String DRM_PROVIDER_EXTRA = "drm_provider";
|
||||||
public static final String PREFER_EXTENSION_DECODERS = "prefer_extension_decoders";
|
public static final String PREFER_EXTENSION_DECODERS = "prefer_extension_decoders";
|
||||||
|
|
||||||
public static final String ACTION_VIEW = "com.google.android.exoplayer.demo.action.VIEW";
|
public static final String ACTION_VIEW = "com.google.android.exoplayer.demo.action.VIEW";
|
||||||
|
public static final String EXTENSION_EXTRA = "extension";
|
||||||
|
|
||||||
public static final String ACTION_VIEW_LIST =
|
public static final String ACTION_VIEW_LIST =
|
||||||
"com.google.android.exoplayer.demo.action.VIEW_LIST";
|
"com.google.android.exoplayer.demo.action.VIEW_LIST";
|
||||||
|
public static final String URI_LIST_EXTRA = "uri_list";
|
||||||
|
public static final String EXTENSION_LIST_EXTRA = "extension_list";
|
||||||
|
|
||||||
private static final String TAG = "PlayerActivity";
|
private static final String TAG = "PlayerActivity";
|
||||||
|
|
||||||
|
|
@ -285,14 +288,20 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
||||||
if (playerNeedsSource) {
|
if (playerNeedsSource) {
|
||||||
String action = intent.getAction();
|
String action = intent.getAction();
|
||||||
Uri[] uris;
|
Uri[] uris;
|
||||||
|
String[] extensions;
|
||||||
if (ACTION_VIEW.equals(action)) {
|
if (ACTION_VIEW.equals(action)) {
|
||||||
uris = new Uri[] {intent.getData()};
|
uris = new Uri[] {intent.getData()};
|
||||||
|
extensions = new String[] {intent.getStringExtra(EXTENSION_EXTRA)};
|
||||||
} else if (ACTION_VIEW_LIST.equals(action)) {
|
} else if (ACTION_VIEW_LIST.equals(action)) {
|
||||||
String[] uriStrings = intent.getStringArrayExtra(URIS_LIST_EXTRA);
|
String[] uriStrings = intent.getStringArrayExtra(URI_LIST_EXTRA);
|
||||||
uris = new Uri[uriStrings.length];
|
uris = new Uri[uriStrings.length];
|
||||||
for (int i = 0; i < uriStrings.length; i++) {
|
for (int i = 0; i < uriStrings.length; i++) {
|
||||||
uris[i] = Uri.parse(uriStrings[i]);
|
uris[i] = Uri.parse(uriStrings[i]);
|
||||||
}
|
}
|
||||||
|
extensions = intent.getStringArrayExtra(EXTENSION_LIST_EXTRA);
|
||||||
|
if (extensions == null) {
|
||||||
|
extensions = new String[uriStrings.length];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Unexpected intent action: " + action);
|
Log.w(TAG, "Unexpected intent action: " + action);
|
||||||
return;
|
return;
|
||||||
|
|
@ -305,7 +314,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
||||||
UriSampleSourceProvider[] providers = new UriSampleSourceProvider[uris.length];
|
UriSampleSourceProvider[] providers = new UriSampleSourceProvider[uris.length];
|
||||||
for (int i = 0; i < uris.length; i++) {
|
for (int i = 0; i < uris.length; i++) {
|
||||||
providers[i] = new UriSampleSourceProvider(player.getBandwidthMeter(), dataSourceFactory,
|
providers[i] = new UriSampleSourceProvider(player.getBandwidthMeter(), dataSourceFactory,
|
||||||
uris[i], intent.getStringExtra(CONTENT_EXT_EXTRA), mainHandler, eventLogger);
|
uris[i], extensions[i], mainHandler, eventLogger);
|
||||||
}
|
}
|
||||||
SampleSourceProvider sourceProvider = providers.length == 1 ? providers[0]
|
SampleSourceProvider sourceProvider = providers.length == 1 ? providers[0]
|
||||||
: new ConcatenatingSampleSourceProvider(providers);
|
: new ConcatenatingSampleSourceProvider(providers);
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import com.google.android.exoplayer.upstream.DataSource;
|
||||||
import com.google.android.exoplayer.upstream.DataSourceInputStream;
|
import com.google.android.exoplayer.upstream.DataSourceInputStream;
|
||||||
import com.google.android.exoplayer.upstream.DataSpec;
|
import com.google.android.exoplayer.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer.upstream.DefaultDataSource;
|
import com.google.android.exoplayer.upstream.DefaultDataSource;
|
||||||
|
import com.google.android.exoplayer.util.Assertions;
|
||||||
import com.google.android.exoplayer.util.Util;
|
import com.google.android.exoplayer.util.Util;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
|
@ -90,15 +91,7 @@ public class SampleChooserActivity extends Activity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSampleSelected(Sample sample) {
|
private void onSampleSelected(Sample sample) {
|
||||||
Intent intent = new Intent(this, PlayerActivity.class)
|
startActivity(sample.buildIntent(this));
|
||||||
.setAction(PlayerActivity.ACTION_VIEW)
|
|
||||||
.setData(Uri.parse(sample.uri))
|
|
||||||
.putExtra(PlayerActivity.CONTENT_EXT_EXTRA, sample.extension)
|
|
||||||
.putExtra(PlayerActivity.DRM_SCHEME_UUID_EXTRA, sample.drmSchemeUuid)
|
|
||||||
.putExtra(PlayerActivity.DRM_CONTENT_ID_EXTRA, sample.drmContentId)
|
|
||||||
.putExtra(PlayerActivity.DRM_PROVIDER_EXTRA, sample.drmProvider)
|
|
||||||
.putExtra(PlayerActivity.PREFER_EXTENSION_DECODERS, sample.preferExtensionDecoders);
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class SampleListLoader extends AsyncTask<String, Void, List<SampleGroup>> {
|
private final class SampleListLoader extends AsyncTask<String, Void, List<SampleGroup>> {
|
||||||
|
|
@ -116,7 +109,7 @@ public class SampleChooserActivity extends Activity {
|
||||||
InputStream inputStream = new DataSourceInputStream(dataSource, dataSpec);
|
InputStream inputStream = new DataSourceInputStream(dataSource, dataSpec);
|
||||||
try {
|
try {
|
||||||
readSampleGroups(new JsonReader(new InputStreamReader(inputStream, "UTF-8")), result);
|
readSampleGroups(new JsonReader(new InputStreamReader(inputStream, "UTF-8")), result);
|
||||||
} catch (IOException e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Error loading sample list: " + uri, e);
|
Log.e(TAG, "Error loading sample list: " + uri, e);
|
||||||
sawError = true;
|
sawError = true;
|
||||||
} finally {
|
} finally {
|
||||||
|
|
@ -152,7 +145,7 @@ public class SampleChooserActivity extends Activity {
|
||||||
case "samples":
|
case "samples":
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
while (reader.hasNext()) {
|
while (reader.hasNext()) {
|
||||||
samples.add(readSample(reader));
|
samples.add(readEntry(reader, false));
|
||||||
}
|
}
|
||||||
reader.endArray();
|
reader.endArray();
|
||||||
break;
|
break;
|
||||||
|
|
@ -164,7 +157,7 @@ public class SampleChooserActivity extends Activity {
|
||||||
group.samples.addAll(samples);
|
group.samples.addAll(samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Sample readSample(JsonReader reader) throws IOException {
|
private Sample readEntry(JsonReader reader, boolean insidePlaylist) throws IOException {
|
||||||
String sampleName = null;
|
String sampleName = null;
|
||||||
String uri = null;
|
String uri = null;
|
||||||
String extension = null;
|
String extension = null;
|
||||||
|
|
@ -172,10 +165,12 @@ public class SampleChooserActivity extends Activity {
|
||||||
String drmContentId = null;
|
String drmContentId = null;
|
||||||
String drmProvider = null;
|
String drmProvider = null;
|
||||||
boolean preferExtensionDecoders = false;
|
boolean preferExtensionDecoders = false;
|
||||||
|
ArrayList<UriSample> playlistSamples = null;
|
||||||
|
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
while (reader.hasNext()) {
|
while (reader.hasNext()) {
|
||||||
switch (reader.nextName()) {
|
String name = reader.nextName();
|
||||||
|
switch (name) {
|
||||||
case "name":
|
case "name":
|
||||||
sampleName = reader.nextString();
|
sampleName = reader.nextString();
|
||||||
break;
|
break;
|
||||||
|
|
@ -194,15 +189,30 @@ public class SampleChooserActivity extends Activity {
|
||||||
case "prefer_extension_decoders":
|
case "prefer_extension_decoders":
|
||||||
preferExtensionDecoders = reader.nextBoolean();
|
preferExtensionDecoders = reader.nextBoolean();
|
||||||
break;
|
break;
|
||||||
|
case "playlist":
|
||||||
|
Assertions.checkState(!insidePlaylist, "Nested playlists are invalid");
|
||||||
|
playlistSamples = new ArrayList<>();
|
||||||
|
reader.beginArray();
|
||||||
|
while (reader.hasNext()) {
|
||||||
|
playlistSamples.add((UriSample) readEntry(reader, true));
|
||||||
|
}
|
||||||
|
reader.endArray();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ParserException("Unsupported attribute name: " + name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reader.endObject();
|
reader.endObject();
|
||||||
|
|
||||||
if (sampleName == null || uri == null) {
|
if (playlistSamples != null) {
|
||||||
throw new ParserException("Invalid sample (name or uri missing)");
|
UriSample[] playlistSamplesArray = playlistSamples.toArray(
|
||||||
|
new UriSample[playlistSamples.size()]);
|
||||||
|
return new PlaylistSample(sampleName, drmUuid, drmContentId, drmProvider,
|
||||||
|
preferExtensionDecoders, playlistSamplesArray);
|
||||||
|
} else {
|
||||||
|
return new UriSample(sampleName, drmUuid, drmContentId, drmProvider,
|
||||||
|
preferExtensionDecoders, uri, extension);
|
||||||
}
|
}
|
||||||
return new Sample(sampleName, uri, extension, drmUuid, drmContentId, drmProvider,
|
|
||||||
preferExtensionDecoders);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SampleGroup getGroup(String groupName, List<SampleGroup> groups) {
|
private SampleGroup getGroup(String groupName, List<SampleGroup> groups) {
|
||||||
|
|
@ -317,27 +327,87 @@ public class SampleChooserActivity extends Activity {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Sample {
|
private abstract static class Sample {
|
||||||
|
|
||||||
public final String name;
|
public final String name;
|
||||||
public final String uri;
|
public final boolean preferExtensionDecoders;
|
||||||
public final String extension;
|
|
||||||
|
// TODO: DRM properties should be specified on UriSample only. This requires changes to
|
||||||
|
// PlayerActivity and beyond to be able to handle playlists containing multiple DRM protected
|
||||||
|
// items that have different DRM properties.
|
||||||
public final UUID drmSchemeUuid;
|
public final UUID drmSchemeUuid;
|
||||||
public final String drmContentId;
|
public final String drmContentId;
|
||||||
public final String drmProvider;
|
public final String drmProvider;
|
||||||
public final boolean preferExtensionDecoders;
|
|
||||||
|
|
||||||
public Sample(String name, String uri, String extension, UUID drmSchemeUuid,
|
public Sample(String name, UUID drmSchemeUuid, String drmContentId, String drmProvider,
|
||||||
String drmContentId, String drmProvider, boolean preferExtensionDecoders) {
|
boolean preferExtensionDecoders) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.uri = uri;
|
|
||||||
this.extension = extension;
|
|
||||||
this.drmSchemeUuid = drmSchemeUuid;
|
this.drmSchemeUuid = drmSchemeUuid;
|
||||||
this.drmContentId = drmContentId;
|
this.drmContentId = drmContentId;
|
||||||
this.drmProvider = drmProvider;
|
this.drmProvider = drmProvider;
|
||||||
this.preferExtensionDecoders = preferExtensionDecoders;
|
this.preferExtensionDecoders = preferExtensionDecoders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract Intent buildIntent(Context context);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class UriSample extends Sample {
|
||||||
|
|
||||||
|
public final String uri;
|
||||||
|
public final String extension;
|
||||||
|
|
||||||
|
public UriSample(String name, UUID drmSchemeUuid, String drmContentId, String drmProvider,
|
||||||
|
boolean preferExtensionDecoders, String uri, String extension) {
|
||||||
|
super(name, drmSchemeUuid, drmContentId, drmProvider, preferExtensionDecoders);
|
||||||
|
this.uri = uri;
|
||||||
|
this.extension = extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Intent buildIntent(Context context) {
|
||||||
|
return new Intent(context, PlayerActivity.class)
|
||||||
|
.setAction(PlayerActivity.ACTION_VIEW)
|
||||||
|
.putExtra(PlayerActivity.DRM_SCHEME_UUID_EXTRA, drmSchemeUuid)
|
||||||
|
.putExtra(PlayerActivity.DRM_CONTENT_ID_EXTRA, drmContentId)
|
||||||
|
.putExtra(PlayerActivity.DRM_PROVIDER_EXTRA, drmProvider)
|
||||||
|
.putExtra(PlayerActivity.PREFER_EXTENSION_DECODERS, preferExtensionDecoders)
|
||||||
|
.setData(Uri.parse(uri))
|
||||||
|
.putExtra(PlayerActivity.EXTENSION_EXTRA, extension)
|
||||||
|
.setAction(PlayerActivity.ACTION_VIEW);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class PlaylistSample extends Sample {
|
||||||
|
|
||||||
|
public final UriSample[] children;
|
||||||
|
|
||||||
|
public PlaylistSample(String name, UUID drmSchemeUuid, String drmContentId, String drmProvider,
|
||||||
|
boolean preferExtensionDecoders, UriSample... children) {
|
||||||
|
super(name, drmSchemeUuid, drmContentId, drmProvider, preferExtensionDecoders);
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Intent buildIntent(Context context) {
|
||||||
|
String[] uris = new String[children.length];
|
||||||
|
String[] extensions = new String[children.length];
|
||||||
|
for (int i = 0; i < children.length; i++) {
|
||||||
|
uris[i] = children[i].uri;
|
||||||
|
extensions[i] = children[i].extension;
|
||||||
|
}
|
||||||
|
return new Intent(context, PlayerActivity.class)
|
||||||
|
.setAction(PlayerActivity.ACTION_VIEW)
|
||||||
|
.putExtra(PlayerActivity.DRM_SCHEME_UUID_EXTRA, drmSchemeUuid)
|
||||||
|
.putExtra(PlayerActivity.DRM_CONTENT_ID_EXTRA, drmContentId)
|
||||||
|
.putExtra(PlayerActivity.DRM_PROVIDER_EXTRA, drmProvider)
|
||||||
|
.putExtra(PlayerActivity.PREFER_EXTENSION_DECODERS, preferExtensionDecoders)
|
||||||
|
.putExtra(PlayerActivity.URI_LIST_EXTRA, uris)
|
||||||
|
.putExtra(PlayerActivity.EXTENSION_LIST_EXTRA, extensions)
|
||||||
|
.setAction(PlayerActivity.ACTION_VIEW_LIST);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue