Commit 58953d37 by olly Committed by Oliver Woodman

Simplify DemoPlayer + misc surrounding components.

1. Properly split out listening responsibilities so that
   DemoPlayer only listens to its own components.
2. Revert StreamingDrmSessionManager UnsupportedDrmScheme
   exceptions back to how they worked in V1, and inject
   a DrmSessionManager rather than a MediaDrmCallback into
   DemoPlayer.

This much better prepares DemoPlayer for promotion into
the core ExoPlayer library, since it removes assumptions
such as what SampleSource and DrmSessionManager impls
might be used with it.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=122980952
parent ddde6edb
......@@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer.demo;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.DefaultTrackSelector.TrackInfo;
import com.google.android.exoplayer.ExoPlaybackException;
import com.google.android.exoplayer.ExoPlayer;
......@@ -23,7 +24,10 @@ import com.google.android.exoplayer.TrackGroup;
import com.google.android.exoplayer.TrackGroupArray;
import com.google.android.exoplayer.TrackRenderer;
import com.google.android.exoplayer.TrackSelection;
import com.google.android.exoplayer.chunk.ChunkTrackStreamEventListener;
import com.google.android.exoplayer.demo.player.DemoPlayer;
import com.google.android.exoplayer.drm.StreamingDrmSessionManager;
import com.google.android.exoplayer.extractor.ExtractorSampleSource;
import android.os.SystemClock;
import android.util.Log;
......@@ -36,7 +40,8 @@ import java.util.Locale;
* Logs player events using {@link Log}.
*/
public class EventLogger implements DemoPlayer.Listener, DemoPlayer.InfoListener,
DemoPlayer.InternalErrorListener {
ChunkTrackStreamEventListener, ExtractorSampleSource.EventListener,
StreamingDrmSessionManager.EventListener {
private static final String TAG = "EventLogger";
private static final NumberFormat TIME_FORMAT;
......@@ -140,26 +145,30 @@ public class EventLogger implements DemoPlayer.Listener, DemoPlayer.InfoListener
}
@Override
public void onAudioFormatEnabled(Format format, int trigger, long mediaTimeMs) {
Log.d(TAG, "audioFormat [" + getSessionTimeString() + ", " + format.id + ", " + trigger + "]");
public void onDroppedFrames(int count, long elapsed) {
Log.d(TAG, "droppedFrames [" + getSessionTimeString() + ", " + count + "]");
}
@Override
public void onVideoFormatEnabled(Format format, int trigger, long mediaTimeMs) {
Log.d(TAG, "videoFormat [" + getSessionTimeString() + ", " + format.id + ", " + trigger + "]");
public void onAudioTrackUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
printInternalError("audioTrackUnderrun [" + bufferSize + ", " + bufferSizeMs + ", "
+ elapsedSinceLastFeedMs + "]", null);
}
// StreamingDrmSessionManager.EventListener
@Override
public void onBandwidthSample(int elapsedMs, long bytes, long bitrateEstimate) {
Log.d(TAG, "bandwidth [" + getSessionTimeString() + ", " + bytes + ", "
+ getTimeString(elapsedMs) + ", " + bitrateEstimate + "]");
public void onDrmSessionManagerError(Exception e) {
printInternalError("drmSessionManagerError", e);
}
@Override
public void onDroppedFrames(int count, long elapsed) {
Log.d(TAG, "droppedFrames [" + getSessionTimeString() + ", " + count + "]");
public void onDrmKeysLoaded() {
Log.d(TAG, "drmKeysLoaded [" + getSessionTimeString() + "]");
}
// SampleSource listeners
@Override
public void onLoadStarted(int sourceId, long length, int type, int trigger, Format format,
long mediaStartTimeMs, long mediaEndTimeMs) {
......@@ -167,29 +176,36 @@ public class EventLogger implements DemoPlayer.Listener, DemoPlayer.InfoListener
}
@Override
public void onLoadCompleted(int sourceId, long bytesLoaded, int type, int trigger, Format format,
long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs) {
// Do nothing.
public void onLoadError(int sourceId, IOException e) {
printInternalError("loadError", e);
}
// DemoPlayer.InternalErrorListener
@Override
public void onLoadCanceled(int sourceId, long bytesLoaded) {
// Do nothing.
}
@Override
public void onLoadError(int sourceId, IOException e) {
printInternalError("loadError", e);
public void onLoadCompleted(int sourceId, long bytesLoaded, int type, int trigger, Format format,
long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs) {
// Do nothing.
}
@Override
public void onDrmSessionManagerError(Exception e) {
printInternalError("drmSessionManagerError", e);
public void onUpstreamDiscarded(int sourceId, long mediaStartTimeMs, long mediaEndTimeMs) {
// Do nothing.
}
@Override
public void onAudioTrackUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
printInternalError("audioTrackUnderrun [" + bufferSize + ", " + bufferSizeMs + ", "
+ elapsedSinceLastFeedMs + "]", null);
public void onDownstreamFormatChanged(int sourceId, Format format, int trigger,
long mediaTimeMs) {
if (sourceId == C.TRACK_TYPE_VIDEO) {
Log.d(TAG, "videoFormatChanged [" + getSessionTimeString() + ", " + format.id + "]");
}
}
// Internal methods
private void printInternalError(String type, Exception e) {
Log.e(TAG, "internalError [" + getSessionTimeString() + ", " + type + "]", e);
}
......
......@@ -27,7 +27,8 @@ import com.google.android.exoplayer.TrackGroupArray;
import com.google.android.exoplayer.dash.DashSampleSource;
import com.google.android.exoplayer.demo.player.DemoPlayer;
import com.google.android.exoplayer.demo.ui.TrackSelectionHelper;
import com.google.android.exoplayer.drm.MediaDrmCallback;
import com.google.android.exoplayer.drm.DrmSessionManager;
import com.google.android.exoplayer.drm.StreamingDrmSessionManager;
import com.google.android.exoplayer.drm.UnsupportedDrmException;
import com.google.android.exoplayer.extractor.ExtractorSampleSource;
import com.google.android.exoplayer.hls.HlsSampleSource;
......@@ -55,6 +56,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
......@@ -76,6 +78,7 @@ import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.util.List;
import java.util.UUID;
/**
* An activity that plays media using {@link DemoPlayer}.
......@@ -84,9 +87,10 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
DemoPlayer.Listener, DemoPlayer.CaptionListener, DemoPlayer.Id3MetadataListener {
// For use within demo app code.
public static final String CONTENT_ID_EXTRA = "content_id";
public static final String CONTENT_TYPE_EXTRA = "content_type";
public static final String PROVIDER_EXTRA = "provider";
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_PROVIDER_EXTRA = "drm_provider";
public static final String USE_EXTENSION_DECODERS = "use_extension_decoders";
// For use when launching the demo app using adb.
......@@ -101,8 +105,10 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
defaultCookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER);
}
private Handler mainHandler;
private EventLogger eventLogger;
private MediaController mediaController;
private View rootView;
private LinearLayout debugRootView;
private View shutterView;
private AspectRatioFrameLayout videoFrame;
......@@ -127,10 +133,11 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
super.onCreate(savedInstanceState);
String userAgent = Util.getUserAgent(this, "ExoPlayerDemo");
dataSourceFactory = new DefaultDataSourceFactory(this, userAgent);
mainHandler = new Handler();
setContentView(R.layout.player_activity);
View root = findViewById(R.id.root);
root.setOnTouchListener(new OnTouchListener() {
rootView = findViewById(R.id.root);
rootView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
......@@ -141,7 +148,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
return true;
}
});
root.setOnKeyListener(new OnKeyListener() {
rootView.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
return keyCode != KeyEvent.KEYCODE_BACK && keyCode != KeyEvent.KEYCODE_ESCAPE
......@@ -161,7 +168,6 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
subtitleLayout = (SubtitleLayout) findViewById(R.id.subtitles);
mediaController = new KeyCompatibleMediaController(this);
mediaController.setAnchorView(root);
retryButton = (Button) findViewById(R.id.retry_button);
retryButton.setOnClickListener(this);
......@@ -273,27 +279,36 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
int type = intent.getIntExtra(CONTENT_TYPE_EXTRA,
inferContentType(uri, intent.getStringExtra(CONTENT_EXT_EXTRA)));
if (player == null) {
String id = intent.getStringExtra(CONTENT_ID_EXTRA);
String provider = intent.getStringExtra(PROVIDER_EXTRA);
UUID drmSchemeUuid = (UUID) intent.getSerializableExtra(DRM_SCHEME_UUID_EXTRA);
DrmSessionManager drmSessionManager = null;
if (drmSchemeUuid != null) {
String drmContentId = intent.getStringExtra(DRM_CONTENT_ID_EXTRA);
String drmProvider = intent.getStringExtra(DRM_PROVIDER_EXTRA);
try {
drmSessionManager = buildDrmSessionManager(drmSchemeUuid, drmContentId, drmProvider);
} catch (UnsupportedDrmException e) {
onUnsupportedDrmError(e);
return;
}
}
boolean useExtensionDecoders = intent.getBooleanExtra(USE_EXTENSION_DECODERS, false);
player = new DemoPlayer(this, buildDrmCallback(type, id, provider), useExtensionDecoders);
player.addListener(this);
player.setCaptionListener(this);
player.setMetadataListener(this);
player.seekTo(playerPosition);
trackSelectionHelper = new TrackSelectionHelper(player.getTrackSelector());
playerNeedsSource = true;
mediaController.setMediaPlayer(player.getPlayerControl());
mediaController.setEnabled(true);
eventLogger = new EventLogger();
eventLogger.startSession();
player = new DemoPlayer(this, drmSessionManager, useExtensionDecoders);
player.addListener(this);
player.addListener(eventLogger);
player.setInfoListener(eventLogger);
player.setInternalErrorListener(eventLogger);
player.setCaptionListener(this);
player.setMetadataListener(this);
player.seekTo(playerPosition);
player.setSurface(surfaceView.getHolder().getSurface());
player.setPlayWhenReady(true);
trackSelectionHelper = new TrackSelectionHelper(player.getTrackSelector());
mediaController.setMediaPlayer(player.getPlayerControl());
mediaController.setAnchorView(rootView);
debugViewHelper = new DebugTextViewHelper(player, debugTextView);
debugViewHelper.start();
playerNeedsSource = true;
}
if (playerNeedsSource) {
if (maybeRequestPermission(uri)) {
......@@ -306,36 +321,45 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
}
}
private MediaDrmCallback buildDrmCallback(int type, String id, String provider) {
private DrmSessionManager buildDrmSessionManager(UUID uuid, String id, String provider)
throws UnsupportedDrmException {
if (Util.SDK_INT < 18) {
return null;
}
switch (type) {
case Util.TYPE_SS:
return new SmoothStreamingTestMediaDrmCallback();
case Util.TYPE_DASH:
return new WidevineTestMediaDrmCallback(id, provider);
default:
return null;
if (C.PLAYREADY_UUID.equals(uuid)) {
return StreamingDrmSessionManager.newPlayReadyInstance(
new SmoothStreamingTestMediaDrmCallback(), null, mainHandler, eventLogger);
} else if (C.WIDEVINE_UUID.equals(uuid)) {
return StreamingDrmSessionManager.newWidevineInstance(
new WidevineTestMediaDrmCallback(id, provider), null, mainHandler, eventLogger);
} else {
throw new UnsupportedDrmException(UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME);
}
}
private void onUnsupportedDrmError(UnsupportedDrmException e) {
String errorString = getString(Util.SDK_INT < 18 ? R.string.error_drm_not_supported
: e.reason == UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME
? R.string.error_drm_unsupported_scheme : R.string.error_drm_unknown);
Toast.makeText(getApplicationContext(), errorString, Toast.LENGTH_LONG).show();
}
private SampleSource buildSource(int type, Uri uri) {
switch (type) {
case Util.TYPE_SS:
return new SmoothStreamingSampleSource(uri, dataSourceFactory, player.getBandwidthMeter(),
player.getMainHandler(), player);
mainHandler, eventLogger);
case Util.TYPE_DASH:
return new DashSampleSource(uri, dataSourceFactory, player.getBandwidthMeter(),
player.getMainHandler(), player);
return new DashSampleSource(uri, dataSourceFactory, player.getBandwidthMeter(), mainHandler,
eventLogger);
case Util.TYPE_HLS:
return new HlsSampleSource(uri, dataSourceFactory, player.getBandwidthMeter(),
player.getMainHandler(), player);
return new HlsSampleSource(uri, dataSourceFactory, player.getBandwidthMeter(), mainHandler,
eventLogger);
case Util.TYPE_OTHER:
Allocator allocator = new DefaultAllocator(C.DEFAULT_BUFFER_SEGMENT_SIZE);
DataSource dataSource = dataSourceFactory.createDataSource(player.getBandwidthMeter());
return new ExtractorSampleSource(uri, dataSource, allocator, C.DEFAULT_MUXED_BUFFER_SIZE,
player.getMainHandler(), player, 0, ExtractorSampleSource.newDefaultExtractors());
mainHandler, eventLogger, 0, ExtractorSampleSource.newDefaultExtractors());
default:
throw new IllegalStateException("Unsupported type: " + type);
}
......@@ -411,12 +435,6 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
errorString = getString(R.string.error_instantiating_decoder,
decoderInitializationException.decoderName);
}
} else if (cause instanceof UnsupportedDrmException) {
// Special case DRM failures.
UnsupportedDrmException unsupportedDrmException = (UnsupportedDrmException) cause;
errorString = getString(Util.SDK_INT < 18 ? R.string.error_drm_not_supported
: unsupportedDrmException.reason == UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME
? R.string.error_drm_unsupported_scheme : R.string.error_drm_unknown);
}
}
if (errorString != null) {
......
......@@ -94,9 +94,10 @@ public class SampleChooserActivity extends Activity {
private void onSampleSelected(Sample sample) {
Intent intent = new Intent(this, PlayerActivity.class)
.setData(Uri.parse(sample.uri))
.putExtra(PlayerActivity.CONTENT_ID_EXTRA, sample.contentId)
.putExtra(PlayerActivity.CONTENT_TYPE_EXTRA, sample.type)
.putExtra(PlayerActivity.PROVIDER_EXTRA, sample.provider)
.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.USE_EXTENSION_DECODERS, sample.useExtensionDecoders);
startActivity(intent);
}
......
......@@ -15,9 +15,10 @@
*/
package com.google.android.exoplayer.demo;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.util.Util;
import java.util.Locale;
import java.util.UUID;
/**
* Holds statically defined sample definitions.
......@@ -27,44 +28,46 @@ import java.util.Locale;
public static class Sample {
public final String name;
public final String contentId;
public final String provider;
public final String uri;
public final int type;
public final UUID drmSchemeUuid;
public final String drmContentId;
public final String drmProvider;
public final boolean useExtensionDecoders;
public Sample(String name, String uri, int type) {
this(name, uri, type, false);
public static Sample newSample(String name, String uri, int type) {
return new Sample(name, uri, type, null, null, null, false);
}
public Sample(String name, String uri, int type, boolean useExtensionDecoders) {
this(name, name.toLowerCase(Locale.US).replaceAll("\\s", ""), "", uri, type,
useExtensionDecoders);
public static Sample newExtensionSample(String name, String uri, int type) {
return new Sample(name, uri, type, null, null, null, true);
}
public Sample(String name, String contentId, String provider, String uri, int type) {
this(name, contentId, provider, uri, type, false);
public static Sample newDrmProtectedSample(String name, String uri, int type, UUID drmScheme,
String drmContentId, String drmProvider) {
return new Sample(name, uri, type, drmScheme, drmContentId, drmProvider, false);
}
public Sample(String name, String contentId, String provider, String uri, int type,
boolean useExtensionDecoders) {
private Sample(String name, String uri, int type, UUID drmSchemeUuid, String drmContentId,
String drmProvider, boolean useExtensionDecoders) {
this.name = name;
this.contentId = contentId;
this.provider = provider;
this.uri = uri;
this.type = type;
this.drmSchemeUuid = drmSchemeUuid;
this.drmContentId = drmContentId;
this.drmProvider = drmProvider;
this.useExtensionDecoders = useExtensionDecoders;
}
}
public static final Sample[] YOUTUBE_DASH_MP4 = new Sample[] {
new Sample("Google Glass (MP4,H264)",
Sample.newSample("Google Glass (MP4,H264)",
"http://www.youtube.com/api/manifest/dash/id/bf5bb2419360daf1/source/youtube?"
+ "as=fmp4_audio_clear,fmp4_sd_hd_clear&sparams=ip,ipbits,expire,source,id,as&ip=0.0.0.0&"
+ "ipbits=0&expire=19000000000&signature=51AF5F39AB0CEC3E5497CD9C900EBFEAECCCB5C7."
+ "8506521BFC350652163895D4C26DEE124209AA9E&key=ik0", Util.TYPE_DASH),
new Sample("Google Play (MP4,H264)",
Sample.newSample("Google Play (MP4,H264)",
"http://www.youtube.com/api/manifest/dash/id/3aa39fa2cc27967f/source/youtube?"
+ "as=fmp4_audio_clear,fmp4_sd_hd_clear&sparams=ip,ipbits,expire,source,id,as&ip=0.0.0.0&"
+ "ipbits=0&expire=19000000000&signature=A2716F75795F5D2AF0E88962FFCD10DB79384F29."
......@@ -72,12 +75,12 @@ import java.util.Locale;
};
public static final Sample[] YOUTUBE_DASH_WEBM = new Sample[] {
new Sample("Google Glass (WebM,VP9)",
Sample.newSample("Google Glass (WebM,VP9)",
"http://www.youtube.com/api/manifest/dash/id/bf5bb2419360daf1/source/youtube?"
+ "as=fmp4_audio_clear,webm2_sd_hd_clear&sparams=ip,ipbits,expire,source,id,as&ip=0.0.0.0&"
+ "ipbits=0&expire=19000000000&signature=249B04F79E984D7F86B4D8DB48AE6FAF41C17AB3."
+ "7B9F0EC0505E1566E59B8E488E9419F253DDF413&key=ik0", Util.TYPE_DASH),
new Sample("Google Play (WebM,VP9)",
Sample.newSample("Google Play (WebM,VP9)",
"http://www.youtube.com/api/manifest/dash/id/3aa39fa2cc27967f/source/youtube?"
+ "as=fmp4_audio_clear,webm2_sd_hd_clear&sparams=ip,ipbits,expire,source,id,as&ip=0.0.0.0&"
+ "ipbits=0&expire=19000000000&signature=B1C2A74783AC1CC4865EB312D7DD2D48230CC9FD."
......@@ -85,208 +88,206 @@ import java.util.Locale;
};
public static final Sample[] SMOOTHSTREAMING = new Sample[] {
new Sample("Super speed",
Sample.newSample("Super speed",
"http://playready.directtaps.net/smoothstreaming/SSWSS720H264/SuperSpeedway_720.ism",
Util.TYPE_SS),
new Sample("Super speed (PlayReady)",
Sample.newDrmProtectedSample("Super speed (PlayReady)",
"http://playready.directtaps.net/smoothstreaming/SSWSS720H264PR/SuperSpeedway_720.ism",
Util.TYPE_SS),
Util.TYPE_SS, C.PLAYREADY_UUID, null, null),
};
private static final String WIDEVINE_GTS_MPD =
private static final String WIDEVINE_GTS_H264_MPD =
"https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears.mpd";
private static final String WIDEVINE_GTS_VP9_MPD =
"https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears.mpd";
private static final String WIDEVINE_GTS_H265_MPD =
"https://storage.googleapis.com/wvmedia/cenc/hevc/tears/tears.mpd";
public static final Sample[] WIDEVINE_GTS = new Sample[] {
new Sample("WV: HDCP not specified", "d286538032258a1c", "widevine_test",
WIDEVINE_GTS_MPD, Util.TYPE_DASH),
new Sample("WV: HDCP not required", "48fcc369939ac96c", "widevine_test",
WIDEVINE_GTS_MPD, Util.TYPE_DASH),
new Sample("WV: HDCP required", "e06c39f1151da3df", "widevine_test",
WIDEVINE_GTS_MPD, Util.TYPE_DASH),
new Sample("WV: Secure video path required (MP4,H264)", "0894c7c8719b28a0", "widevine_test",
WIDEVINE_GTS_MPD, Util.TYPE_DASH),
new Sample("WV: Secure video path required (WebM,VP9)", "0894c7c8719b28a0", "widevine_test",
"https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears.mpd",
Util.TYPE_DASH),
new Sample("WV: Secure video path required (MP4,H265)", "0894c7c8719b28a0", "widevine_test",
"https://storage.googleapis.com/wvmedia/cenc/hevc/tears/tears.mpd",
Util.TYPE_DASH),
new Sample("WV: HDCP + secure video path required", "efd045b1eb61888a", "widevine_test",
WIDEVINE_GTS_MPD, Util.TYPE_DASH),
new Sample("WV: 30s license duration (fails at ~30s)", "f9a34cab7b05881a", "widevine_test",
WIDEVINE_GTS_MPD, Util.TYPE_DASH),
Sample.newDrmProtectedSample("WV: HDCP not specified", WIDEVINE_GTS_H264_MPD, Util.TYPE_DASH,
C.WIDEVINE_UUID, "d286538032258a1c", "widevine_test"),
Sample.newDrmProtectedSample("WV: HDCP not required", WIDEVINE_GTS_H264_MPD, Util.TYPE_DASH,
C.WIDEVINE_UUID, "48fcc369939ac96c", "widevine_test"),
Sample.newDrmProtectedSample("WV: HDCP required", WIDEVINE_GTS_H264_MPD, Util.TYPE_DASH,
C.WIDEVINE_UUID, "e06c39f1151da3df", "widevine_test"),
Sample.newDrmProtectedSample("WV: Secure video path required (MP4,H264)", WIDEVINE_GTS_H264_MPD,
Util.TYPE_DASH, C.WIDEVINE_UUID, "0894c7c8719b28a0", "widevine_test"),
Sample.newDrmProtectedSample("WV: Secure video path required (WebM,VP9)", WIDEVINE_GTS_VP9_MPD,
Util.TYPE_DASH, C.WIDEVINE_UUID, "0894c7c8719b28a0", "widevine_test"),
Sample.newDrmProtectedSample("WV: Secure video path required (MP4,H265)", WIDEVINE_GTS_H265_MPD,
Util.TYPE_DASH, C.WIDEVINE_UUID, "0894c7c8719b28a0", "widevine_test"),
Sample.newDrmProtectedSample("WV: HDCP + secure video path required", WIDEVINE_GTS_H264_MPD,
Util.TYPE_DASH, C.WIDEVINE_UUID, "efd045b1eb61888a", "widevine_test"),
Sample.newDrmProtectedSample("WV: 30s license duration (fails at ~30s)", WIDEVINE_GTS_H264_MPD,
Util.TYPE_DASH, C.WIDEVINE_UUID, "f9a34cab7b05881a", "widevine_test"),
};
public static final Sample[] WIDEVINE_HDCP = new Sample[] {
new Sample("WV: HDCP: None (not required)", "HDCP_None", "widevine_test",
WIDEVINE_GTS_MPD, Util.TYPE_DASH),
new Sample("WV: HDCP: 1.0 required", "HDCP_V1", "widevine_test",
WIDEVINE_GTS_MPD, Util.TYPE_DASH),
new Sample("WV: HDCP: 2.0 required", "HDCP_V2", "widevine_test",
WIDEVINE_GTS_MPD, Util.TYPE_DASH),
new Sample("WV: HDCP: 2.1 required", "HDCP_V2_1", "widevine_test",
WIDEVINE_GTS_MPD, Util.TYPE_DASH),
new Sample("WV: HDCP: 2.2 required", "HDCP_V2_2", "widevine_test",
WIDEVINE_GTS_MPD, Util.TYPE_DASH),
new Sample("WV: HDCP: No digital output", "HDCP_NO_DIGTAL_OUTPUT", "widevine_test",
WIDEVINE_GTS_MPD, Util.TYPE_DASH),
Sample.newDrmProtectedSample("WV: HDCP: None (not required)", WIDEVINE_GTS_H264_MPD,
Util.TYPE_DASH, C.WIDEVINE_UUID, "HDCP_None", "widevine_test"),
Sample.newDrmProtectedSample("WV: HDCP: 1.0 required", WIDEVINE_GTS_H264_MPD, Util.TYPE_DASH,
C.WIDEVINE_UUID, "HDCP_V1", "widevine_test"),
Sample.newDrmProtectedSample("WV: HDCP: 2.0 required", WIDEVINE_GTS_H264_MPD, Util.TYPE_DASH,
C.WIDEVINE_UUID, "HDCP_V2", "widevine_test"),
Sample.newDrmProtectedSample("WV: HDCP: 2.1 required", WIDEVINE_GTS_H264_MPD, Util.TYPE_DASH,
C.WIDEVINE_UUID, "HDCP_V2_1", "widevine_test"),
Sample.newDrmProtectedSample("WV: HDCP: 2.2 required", WIDEVINE_GTS_H264_MPD, Util.TYPE_DASH,
C.WIDEVINE_UUID, "HDCP_V2_2", "widevine_test"),
Sample.newDrmProtectedSample("WV: HDCP: No digital output", WIDEVINE_GTS_H264_MPD,
Util.TYPE_DASH, C.WIDEVINE_UUID, "HDCP_NO_DIGTAL_OUTPUT", "widevine_test"),
};
public static final Sample[] WIDEVINE_H264_MP4_CLEAR = new Sample[] {
new Sample("WV: Clear SD & HD (MP4,H264)",
Sample.newSample("WV: Clear SD & HD (MP4,H264)",
"https://storage.googleapis.com/wvmedia/clear/h264/tears/tears.mpd",
Util.TYPE_DASH),
new Sample("WV: Clear SD (MP4,H264)",
Sample.newSample("WV: Clear SD (MP4,H264)",
"https://storage.googleapis.com/wvmedia/clear/h264/tears/tears_sd.mpd",
Util.TYPE_DASH),
new Sample("WV: Clear HD (MP4,H264)",
Sample.newSample("WV: Clear HD (MP4,H264)",
"https://storage.googleapis.com/wvmedia/clear/h264/tears/tears_hd.mpd",
Util.TYPE_DASH),
new Sample("WV: Clear UHD (MP4,H264)",
Sample.newSample("WV: Clear UHD (MP4,H264)",
"https://storage.googleapis.com/wvmedia/clear/h264/tears/tears_uhd.mpd",
Util.TYPE_DASH),
};
public static final Sample[] WIDEVINE_H264_MP4_SECURE = new Sample[] {
new Sample("WV: Secure SD & HD (MP4,H264)", "", "widevine_test",
"https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears.mpd",
Util.TYPE_DASH),
new Sample("WV: Secure SD (MP4,H264)", "", "widevine_test",
"https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears_sd.mpd",
Util.TYPE_DASH),
new Sample("WV: Secure HD (MP4,H264)", "", "widevine_test",
"https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears_hd.mpd",
Util.TYPE_DASH),
new Sample("WV: Secure UHD (MP4,H264)", "", "widevine_test",
"https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears_uhd.mpd",
Util.TYPE_DASH),
Sample.newDrmProtectedSample("WV: Secure SD & HD (MP4,H264)", WIDEVINE_GTS_H264_MPD,
Util.TYPE_DASH, C.WIDEVINE_UUID, "", "widevine_test"),
Sample.newDrmProtectedSample("WV: Secure SD (MP4,H264)",
"https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears_sd.mpd", Util.TYPE_DASH,
C.WIDEVINE_UUID, "", "widevine_test"),
Sample.newDrmProtectedSample("WV: Secure HD (MP4,H264)",
"https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears_hd.mpd", Util.TYPE_DASH,
C.WIDEVINE_UUID, "", "widevine_test"),
Sample.newDrmProtectedSample("WV: Secure UHD (MP4,H264)",
"https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears_uhd.mpd", Util.TYPE_DASH,
C.WIDEVINE_UUID, "", "widevine_test"),
};
public static final Sample[] WIDEVINE_VP9_WEBM_CLEAR = new Sample[] {
new Sample("WV: Clear SD & HD (WebM,VP9)",
Sample.newSample("WV: Clear SD & HD (WebM,VP9)",
"https://storage.googleapis.com/wvmedia/clear/vp9/tears/tears.mpd",
Util.TYPE_DASH),
new Sample("WV: Clear SD (WebM,VP9)",
Sample.newSample("WV: Clear SD (WebM,VP9)",
"https://storage.googleapis.com/wvmedia/clear/vp9/tears/tears_sd.mpd",
Util.TYPE_DASH),
new Sample("WV: Clear HD (WebM,VP9)",
Sample.newSample("WV: Clear HD (WebM,VP9)",
"https://storage.googleapis.com/wvmedia/clear/vp9/tears/tears_hd.mpd",
Util.TYPE_DASH),
new Sample("WV: Clear UHD (WebM,VP9)",
Sample.newSample("WV: Clear UHD (WebM,VP9)",
"https://storage.googleapis.com/wvmedia/clear/vp9/tears/tears_uhd.mpd",
Util.TYPE_DASH),
};
public static final Sample[] WIDEVINE_VP9_WEBM_SECURE = new Sample[] {
new Sample("WV: Secure SD & HD (WebM,VP9)", "", "widevine_test",
"https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears.mpd",
Util.TYPE_DASH),
new Sample("WV: Secure SD (WebM,VP9)", "", "widevine_test",
"https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears_sd.mpd",
Util.TYPE_DASH),
new Sample("WV: Secure HD (WebM,VP9)", "", "widevine_test",
"https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears_hd.mpd",
Util.TYPE_DASH),
new Sample("WV: Secure UHD (WebM,VP9)", "", "widevine_test",
"https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears_uhd.mpd",
Util.TYPE_DASH),
Sample.newDrmProtectedSample("WV: Secure SD & HD (WebM,VP9)", WIDEVINE_GTS_VP9_MPD,
Util.TYPE_DASH, C.WIDEVINE_UUID, "", "widevine_test"),
Sample.newDrmProtectedSample("WV: Secure SD (WebM,VP9)",
"https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears_sd.mpd", Util.TYPE_DASH,
C.WIDEVINE_UUID, "", "widevine_test"),
Sample.newDrmProtectedSample("WV: Secure HD (WebM,VP9)",
"https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears_hd.mpd", Util.TYPE_DASH,
C.WIDEVINE_UUID, "", "widevine_test"),
Sample.newDrmProtectedSample("WV: Secure UHD (WebM,VP9)",
"https://storage.googleapis.com/wvmedia/cenc/vp9/tears/tears_uhd.mpd", Util.TYPE_DASH,
C.WIDEVINE_UUID, "", "widevine_test"),
};
public static final Sample[] WIDEVINE_H265_MP4_CLEAR = new Sample[] {
new Sample("WV: Clear SD & HD (MP4,H265)",
Sample.newSample("WV: Clear SD & HD (MP4,H265)",
"https://storage.googleapis.com/wvmedia/clear/hevc/tears/tears.mpd",
Util.TYPE_DASH),
new Sample("WV: Clear SD (MP4,H265)",
Sample.newSample("WV: Clear SD (MP4,H265)",
"https://storage.googleapis.com/wvmedia/clear/hevc/tears/tears_sd.mpd",
Util.TYPE_DASH),
new Sample("WV: Clear HD (MP4,H265)",
Sample.newSample("WV: Clear HD (MP4,H265)",
"https://storage.googleapis.com/wvmedia/clear/hevc/tears/tears_hd.mpd",
Util.TYPE_DASH),
new Sample("WV: Clear UHD (MP4,H265)",
Sample.newSample("WV: Clear UHD (MP4,H265)",
"https://storage.googleapis.com/wvmedia/clear/hevc/tears/tears_uhd.mpd",
Util.TYPE_DASH),
};
public static final Sample[] WIDEVINE_H265_MP4_SECURE = new Sample[] {
new Sample("WV: Secure SD & HD (MP4,H265)", "", "widevine_test",
"https://storage.googleapis.com/wvmedia/cenc/hevc/tears/tears.mpd",
Util.TYPE_DASH),
new Sample("WV: Secure SD (MP4,H265)", "", "widevine_test",
"https://storage.googleapis.com/wvmedia/cenc/hevc/tears/tears_sd.mpd",
Util.TYPE_DASH),
new Sample("WV: Secure HD (MP4,H265)", "", "widevine_test",
"https://storage.googleapis.com/wvmedia/cenc/hevc/tears/tears_hd.mpd",
Util.TYPE_DASH),
new Sample("WV: Secure UHD (MP4,H265)", "", "widevine_test",
"https://storage.googleapis.com/wvmedia/cenc/hevc/tears/tears_uhd.mpd",
Util.TYPE_DASH),
Sample.newDrmProtectedSample("WV: Secure SD & HD (MP4,H265)", WIDEVINE_GTS_H265_MPD,
Util.TYPE_DASH, C.WIDEVINE_UUID, "", "widevine_test"),
Sample.newDrmProtectedSample("WV: Secure SD (MP4,H265)",
"https://storage.googleapis.com/wvmedia/cenc/hevc/tears/tears_sd.mpd", Util.TYPE_DASH,
C.WIDEVINE_UUID, "", "widevine_test"),
Sample.newDrmProtectedSample("WV: Secure HD (MP4,H265)",
"https://storage.googleapis.com/wvmedia/cenc/hevc/tears/tears_hd.mpd", Util.TYPE_DASH,
C.WIDEVINE_UUID, "", "widevine_test"),
Sample.newDrmProtectedSample("WV: Secure UHD (MP4,H265)",
"https://storage.googleapis.com/wvmedia/cenc/hevc/tears/tears_uhd.mpd", Util.TYPE_DASH,
C.WIDEVINE_UUID, "", "widevine_test"),
};
public static final Sample[] HLS = new Sample[] {
new Sample("Apple master playlist",
Sample.newSample("Apple master playlist",
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/"
+ "bipbop_4x3_variant.m3u8", Util.TYPE_HLS),
new Sample("Apple master playlist advanced",
Sample.newSample("Apple master playlist advanced",
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_16x9/"
+ "bipbop_16x9_variant.m3u8", Util.TYPE_HLS),
new Sample("Apple TS media playlist",
Sample.newSample("Apple TS media playlist",
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear1/"
+ "prog_index.m3u8", Util.TYPE_HLS),
new Sample("Apple AAC media playlist",
Sample.newSample("Apple AAC media playlist",
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear0/"
+ "prog_index.m3u8", Util.TYPE_HLS),
new Sample("Apple ID3 metadata", "http://devimages.apple.com/samplecode/adDemo/ad.m3u8",
Sample.newSample("Apple ID3 metadata", "http://devimages.apple.com/samplecode/adDemo/ad.m3u8",
Util.TYPE_HLS),
};
public static final Sample[] MISC = new Sample[] {
new Sample("Dizzy", "http://html5demos.com/assets/dizzy.mp4", Util.TYPE_OTHER),
new Sample("Apple AAC 10s", "https://devimages.apple.com.edgekey.net/"
Sample.newSample("Dizzy", "http://html5demos.com/assets/dizzy.mp4", Util.TYPE_OTHER),
Sample.newSample("Apple AAC 10s", "https://devimages.apple.com.edgekey.net/"
+ "streaming/examples/bipbop_4x3/gear0/fileSequence0.aac", Util.TYPE_OTHER),
new Sample("Apple TS 10s", "https://devimages.apple.com.edgekey.net/streaming/examples/"
Sample.newSample("Apple TS 10s", "https://devimages.apple.com.edgekey.net/streaming/examples/"
+ "bipbop_4x3/gear1/fileSequence0.ts", Util.TYPE_OTHER),
new Sample("Android screens (Matroska)", "http://storage.googleapis.com/exoplayer-test-media-1/"
+ "mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv",
Util.TYPE_OTHER),
new Sample("Big Buck Bunny (MP4 Video)",
Sample.newSample("Android screens (Matroska)", "http://storage.googleapis.com/exoplayer-test-me"
+ "dia-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv", Util.TYPE_OTHER),
Sample.newSample("Big Buck Bunny (MP4 Video)",
"http://redirector.c.youtube.com/videoplayback?id=604ed5ce52eda7ee&itag=22&source=youtube&"
+ "sparams=ip,ipbits,expire,source,id&ip=0.0.0.0&ipbits=0&expire=19000000000&signature="
+ "513F28C7FDCBEC60A66C86C9A393556C99DC47FB.04C88036EEE12565A1ED864A875A58F15D8B5300"
+ "&key=ik0", Util.TYPE_OTHER),
new Sample("Screens 360P (WebM,VP9,No Audio)",
Sample.newSample("Screens 360P (WebM,VP9,No Audio)",
"https://storage.googleapis.com/exoplayer-test-media-1/gen-3/screens/dash-vod-single-segmen"
+ "t/video-vp9-360.webm", Util.TYPE_OTHER),
new Sample("Screens 480p (FMP4,H264,No Audio)",
Sample.newSample("Screens 480p (FMP4,H264,No Audio)",
"https://storage.googleapis.com/exoplayer-test-media-1/gen-3/screens/dash-vod-single-segmen"
+ "t/video-avc-baseline-480.mp4", Util.TYPE_OTHER),
new Sample("Screens 1080p (FMP4,H264, No Audio)",
Sample.newSample("Screens 1080p (FMP4,H264, No Audio)",
"https://storage.googleapis.com/exoplayer-test-media-1/gen-3/screens/dash-vod-single-segmen"
+ "t/video-137.mp4", Util.TYPE_OTHER),
new Sample("Screens (FMP4,AAC Audio)",
Sample.newSample("Screens (FMP4,AAC Audio)",
"https://storage.googleapis.com/exoplayer-test-media-1/gen-3/screens/dash-vod-single-segmen"
+ "t/audio-141.mp4", Util.TYPE_OTHER),
new Sample("Google Play (MP3 Audio)",
Sample.newSample("Google Play (MP3 Audio)",
"http://storage.googleapis.com/exoplayer-test-media-0/play.mp3", Util.TYPE_OTHER),
new Sample("Google Play (Ogg/Vorbis Audio)",
Sample.newSample("Google Play (Ogg/Vorbis Audio)",
"https://storage.googleapis.com/exoplayer-test-media-1/ogg/play.ogg", Util.TYPE_OTHER),
new Sample("Google Glass (WebM Video with Vorbis Audio)",
Sample.newSample("Google Glass (WebM Video with Vorbis Audio)",
"http://demos.webmproject.org/exoplayer/glass_vp9_vorbis.webm", Util.TYPE_OTHER),
new Sample("Google Glass DASH - VP9 and Opus",
Sample.newSample("Google Glass DASH - VP9 and Opus",
"http://demos.webmproject.org/dash/201410/vp9_glass/manifest_vp9_opus.mpd",
Util.TYPE_DASH),
new Sample("Big Buck Bunny (FLV Video)",
Sample.newSample("Big Buck Bunny (FLV Video)",
"http://vod.leasewebcdn.com/bbb.flv?ri=1024&rs=150&start=0", Util.TYPE_OTHER),
};
public static final Sample[] EXTENSION = new Sample[] {
new Sample("Google Glass DASH - VP9 Only",
Sample.newExtensionSample("Google Glass DASH - VP9 Only",
"http://demos.webmproject.org/dash/201410/vp9_glass/manifest_vp9.mpd",
Util.TYPE_DASH, true),
new Sample("Google Glass DASH - VP9 and Vorbis",
Util.TYPE_DASH),
Sample.newExtensionSample("Google Glass DASH - VP9 and Vorbis",
"http://demos.webmproject.org/dash/201410/vp9_glass/manifest_vp9_vorbis.mpd",
Util.TYPE_DASH, true),
new Sample("Google Glass DASH - VP9 and Opus",
Util.TYPE_DASH),
Sample.newExtensionSample("Google Glass DASH - VP9 and Opus",
"http://demos.webmproject.org/dash/201410/vp9_glass/manifest_vp9_opus.mpd",
Util.TYPE_DASH, true),
Util.TYPE_DASH),
};
private Samples() {}
......
......@@ -15,7 +15,6 @@
*/
package com.google.android.exoplayer.demo;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.drm.MediaDrmCallback;
import com.google.android.exoplayer.drm.StreamingDrmSessionManager;
import com.google.android.exoplayer.util.Util;
......@@ -48,11 +47,6 @@ public final class SmoothStreamingTestMediaDrmCallback implements MediaDrmCallba
}
@Override
public UUID getUuid() {
return C.PLAYREADY_UUID;
}
@Override
public byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request) throws IOException {
String url = request.getDefaultUrl() + "&signedRequest=" + new String(request.getData());
return Util.executePost(url, null, null);
......
......@@ -15,7 +15,6 @@
*/
package com.google.android.exoplayer.demo;
import com.google.android.exoplayer.C;
import com.google.android.exoplayer.drm.MediaDrmCallback;
import com.google.android.exoplayer.util.Util;
......@@ -44,11 +43,6 @@ public final class WidevineTestMediaDrmCallback implements MediaDrmCallback {
}
@Override
public UUID getUuid() {
return C.WIDEVINE_UUID;
}
@Override
public byte[] executeProvisionRequest(UUID uuid, ProvisionRequest request) throws IOException {
String url = request.getDefaultUrl() + "&signedRequest=" + new String(request.getData());
return Util.executePost(url, null, null);
......
......@@ -28,15 +28,10 @@ import com.google.android.exoplayer.MediaCodecAudioTrackRenderer;
import com.google.android.exoplayer.MediaCodecSelector;
import com.google.android.exoplayer.MediaCodecVideoTrackRenderer;
import com.google.android.exoplayer.SampleSource;
import com.google.android.exoplayer.SingleSampleSource;
import com.google.android.exoplayer.TrackRenderer;
import com.google.android.exoplayer.VideoTrackRendererEventListener;
import com.google.android.exoplayer.audio.AudioCapabilities;
import com.google.android.exoplayer.chunk.ChunkTrackStreamEventListener;
import com.google.android.exoplayer.drm.DrmSessionManager;
import com.google.android.exoplayer.drm.MediaDrmCallback;
import com.google.android.exoplayer.drm.StreamingDrmSessionManager;
import com.google.android.exoplayer.extractor.ExtractorSampleSource;
import com.google.android.exoplayer.metadata.MetadataTrackRenderer;
import com.google.android.exoplayer.metadata.MetadataTrackRenderer.MetadataRenderer;
import com.google.android.exoplayer.metadata.id3.Id3Frame;
......@@ -56,7 +51,6 @@ import android.os.Handler;
import android.util.Log;
import android.view.Surface;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
......@@ -66,11 +60,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
* A wrapper around {@link ExoPlayer} that provides a higher level interface.
*/
public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.EventListener,
ChunkTrackStreamEventListener, ExtractorSampleSource.EventListener,
SingleSampleSource.EventListener, DefaultBandwidthMeter.EventListener,
VideoTrackRendererEventListener, AudioTrackRendererEventListener,
StreamingDrmSessionManager.EventListener, TextRenderer, MetadataRenderer<List<Id3Frame>>,
DebugTextViewHelper.Provider {
VideoTrackRendererEventListener, AudioTrackRendererEventListener, TextRenderer,
MetadataRenderer<List<Id3Frame>>, DebugTextViewHelper.Provider {
/**
* A listener for core events.
......@@ -84,20 +75,6 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
}
/**
* A listener for internal errors.
* <p>
* These errors are not visible to the user, and hence this listener is provided for
* informational purposes only. Note however that an internal error may cause a fatal
* error if the player fails to recover. If this happens,
* {@link Listener#onError(ExoPlaybackException)} will be invoked.
*/
public interface InternalErrorListener {
void onAudioTrackUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs);
void onLoadError(int sourceId, IOException e);
void onDrmSessionManagerError(Exception e);
}
/**
* A listener for debugging information.
*/
public interface InfoListener {
......@@ -105,14 +82,8 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
long initializationDurationMs);
void onVideoDecoderInitialized(String decoderName, long elapsedRealtimeMs,
long initializationDurationMs);
void onAudioFormatEnabled(Format format, int trigger, long mediaTimeMs);
void onVideoFormatEnabled(Format format, int trigger, long mediaTimeMs);
void onDroppedFrames(int count, long elapsed);
void onBandwidthSample(int elapsedMs, long bytes, long bitrateEstimate);
void onLoadStarted(int sourceId, long length, int type, int trigger, Format format,
long mediaStartTimeMs, long mediaEndTimeMs);
void onLoadCompleted(int sourceId, long bytesLoaded, int type, int trigger, Format format,
long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs);
void onAudioTrackUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs);
}
/**
......@@ -129,12 +100,6 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
void onId3Metadata(List<Id3Frame> id3Frames);
}
// Constants pulled into this class for convenience.
public static final int STATE_IDLE = ExoPlayer.STATE_IDLE;
public static final int STATE_BUFFERING = ExoPlayer.STATE_BUFFERING;
public static final int STATE_READY = ExoPlayer.STATE_READY;
public static final int STATE_ENDED = ExoPlayer.STATE_ENDED;
private static final String TAG = "DemoPlayer";
private final ExoPlayer player;
......@@ -151,11 +116,11 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
private CaptionListener captionListener;
private Id3MetadataListener id3MetadataListener;
private InternalErrorListener internalErrorListener;
private InfoListener infoListener;
private CodecCounters videoCodecCounters;
public DemoPlayer(Context context, MediaDrmCallback drmCallback, boolean useExtensionDecoders) {
public DemoPlayer(Context context, DrmSessionManager drmSessionManager,
boolean useExtensionDecoders) {
mainHandler = new Handler();
bandwidthMeter = new DefaultBandwidthMeter();
listeners = new CopyOnWriteArrayList<>();
......@@ -165,7 +130,7 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
if (useExtensionDecoders) {
buildExtensionRenderers(renderersList);
}
buildRenderers(context, drmCallback, renderersList);
buildRenderers(context, drmSessionManager, renderersList);
renderers = renderersList.toArray(new TrackRenderer[renderersList.size()]);
// Build the player and associated objects.
......@@ -191,10 +156,6 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
listeners.remove(listener);
}
public void setInternalErrorListener(InternalErrorListener listener) {
internalErrorListener = listener;
}
public void setInfoListener(InfoListener listener) {
infoListener = listener;
}
......@@ -212,10 +173,6 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
pushSurface(false);
}
public Surface getSurface() {
return surface;
}
public void blockingClearSurface() {
surface = null;
pushSurface(true);
......@@ -278,10 +235,6 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
return player.getPlayWhenReady();
}
public Handler getMainHandler() {
return mainHandler;
}
@Override
public void onPlayerStateChanged(boolean playWhenReady, int state) {
for (Listener listener : listeners) {
......@@ -320,48 +273,15 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
}
@Override
public void onBandwidthSample(int elapsedMs, long bytes, long bitrateEstimate) {
if (infoListener != null) {
infoListener.onBandwidthSample(elapsedMs, bytes, bitrateEstimate);
}
}
@Override
public void onDownstreamFormatChanged(int sourceId, Format format, int trigger,
long mediaTimeMs) {
if (infoListener == null) {
return;
}
if (sourceId == C.TRACK_TYPE_VIDEO) {
videoFormat = format;
infoListener.onVideoFormatEnabled(format, trigger, mediaTimeMs);
} else if (sourceId == C.TRACK_TYPE_AUDIO) {
infoListener.onAudioFormatEnabled(format, trigger, mediaTimeMs);
}
}
@Override
public void onDrmKeysLoaded() {
// Do nothing.
}
@Override
public void onDrmSessionManagerError(Exception e) {
if (internalErrorListener != null) {
internalErrorListener.onDrmSessionManagerError(e);
}
}
@Override
public void onAudioTrackUnderrun(int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
if (internalErrorListener != null) {
internalErrorListener.onAudioTrackUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs);
if (infoListener != null) {
infoListener.onAudioTrackUnderrun(bufferSize, bufferSizeMs, elapsedSinceLastFeedMs);
}
}
@Override
public void onAudioCodecCounters(CodecCounters counters) {
// do nothing
// Do nothing.
}
@Override
......@@ -374,10 +294,8 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
}
@Override
public void onLoadError(int sourceId, IOException e) {
if (internalErrorListener != null) {
internalErrorListener.onLoadError(sourceId, e);
}
public void onAudioInputFormatChanged(Format format) {
// Do nothing.
}
@Override
......@@ -419,31 +337,8 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
}
@Override
public void onLoadStarted(int sourceId, long length, int type, int trigger, Format format,
long mediaStartTimeMs, long mediaEndTimeMs) {
if (infoListener != null) {
infoListener.onLoadStarted(sourceId, length, type, trigger, format, mediaStartTimeMs,
mediaEndTimeMs);
}
}
@Override
public void onLoadCompleted(int sourceId, long bytesLoaded, int type, int trigger, Format format,
long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs) {
if (infoListener != null) {
infoListener.onLoadCompleted(sourceId, bytesLoaded, type, trigger, format, mediaStartTimeMs,
mediaEndTimeMs, elapsedRealtimeMs, loadDurationMs);
}
}
@Override
public void onLoadCanceled(int sourceId, long bytesLoaded) {
// Do nothing.
}
@Override
public void onUpstreamDiscarded(int sourceId, long mediaStartTimeMs, long mediaEndTimeMs) {
// Do nothing.
public void onVideoInputFormatChanged(Format format) {
videoFormat = format;
}
public int getRendererType(int index) {
......@@ -462,11 +357,8 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even
}
}
private void buildRenderers(Context context, MediaDrmCallback drmCallback,
private void buildRenderers(Context context, DrmSessionManager drmSessionManager,
ArrayList<TrackRenderer> renderersList) {
DrmSessionManager drmSessionManager = drmCallback == null ? null
: new StreamingDrmSessionManager(drmCallback, null, mainHandler, this);
MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(context,
MediaCodecSelector.DEFAULT, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 5000,
drmSessionManager, false, mainHandler, this, 50);
......
......@@ -281,7 +281,7 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
return false;
}
if (result == TrackStream.FORMAT_READ) {
format = formatHolder.format;
onInputFormatChanged(formatHolder.format);
return true;
}
if (inputBuffer.isEndOfStream()) {
......@@ -366,12 +366,17 @@ public final class LibvpxVideoTrackRenderer extends TrackRenderer {
private boolean readFormat() {
int result = readSource(formatHolder, null);
if (result == TrackStream.FORMAT_READ) {
format = formatHolder.format;
onInputFormatChanged(formatHolder.format);
return true;
}
return false;
}
private void onInputFormatChanged(Format newFormat) {
format = newFormat;
eventDispatcher.inputFormatChanged(format);
}
@Override
public void handleMessage(int messageType, Object message) throws ExoPlaybackException {
if (messageType == C.MSG_SET_SURFACE) {
......
......@@ -45,6 +45,13 @@ public interface AudioTrackRendererEventListener {
long initializationDurationMs);
/**
* Invoked when the format of the media being consumed by the renderer changes.
*
* @param format The new format.
*/
void onAudioInputFormatChanged(Format format);
/**
* Invoked when an {@link AudioTrack} underrun occurs.
*
* @param bufferSize The size of the {@link AudioTrack}'s buffer, in bytes.
......@@ -92,6 +99,17 @@ public interface AudioTrackRendererEventListener {
}
}
public void inputFormatChanged(final Format format) {
if (listener != null) {
handler.post(new Runnable() {
@Override
public void run() {
listener.onAudioInputFormatChanged(format);
}
});
}
}
public void audioTrackUnderrun(final int bufferSize, final long bufferSizeMs,
final long elapsedSinceLastFeedMs) {
if (listener != null) {
......
......@@ -233,12 +233,13 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem
}
@Override
protected void onInputFormatChanged(FormatHolder holder) throws ExoPlaybackException {
super.onInputFormatChanged(holder);
protected void onInputFormatChanged(Format newFormat) throws ExoPlaybackException {
super.onInputFormatChanged(newFormat);
eventDispatcher.inputFormatChanged(newFormat);
// If the input format is anything other than PCM then we assume that the audio decoder will
// output 16-bit PCM.
pcmEncoding = MimeTypes.AUDIO_RAW.equals(holder.format.sampleMimeType)
? holder.format.pcmEncoding : C.ENCODING_PCM_16BIT;
pcmEncoding = MimeTypes.AUDIO_RAW.equals(newFormat.sampleMimeType) ? newFormat.pcmEncoding
: C.ENCODING_PCM_16BIT;
}
@Override
......
......@@ -430,7 +430,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
private void readFormat() throws ExoPlaybackException {
int result = readSource(formatHolder, null);
if (result == TrackStream.FORMAT_READ) {
onInputFormatChanged(formatHolder);
onInputFormatChanged(formatHolder.format);
}
}
......@@ -526,7 +526,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
buffer.clear();
codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING;
}
onInputFormatChanged(formatHolder);
onInputFormatChanged(formatHolder.format);
return true;
}
......@@ -641,12 +641,12 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
/**
* Invoked when a new format is read from the upstream {@link SampleSource}.
*
* @param formatHolder Holds the new format.
* @param newFormat The new format.
* @throws ExoPlaybackException If an error occurs reinitializing the {@link MediaCodec}.
*/
protected void onInputFormatChanged(FormatHolder formatHolder) throws ExoPlaybackException {
protected void onInputFormatChanged(Format newFormat) throws ExoPlaybackException {
Format oldFormat = format;
format = formatHolder.format;
format = newFormat;
if (codec != null && canReconfigureCodec(codec, codecIsAdaptive, oldFormat, format)) {
codecReconfigured = true;
codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING;
......
......@@ -329,12 +329,13 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
}
@Override
protected void onInputFormatChanged(FormatHolder holder) throws ExoPlaybackException {
super.onInputFormatChanged(holder);
pendingPixelWidthHeightRatio = holder.format.pixelWidthHeightRatio == Format.NO_VALUE ? 1
: holder.format.pixelWidthHeightRatio;
pendingRotationDegrees = holder.format.rotationDegrees == Format.NO_VALUE ? 0
: holder.format.rotationDegrees;
protected void onInputFormatChanged(Format newFormat) throws ExoPlaybackException {
super.onInputFormatChanged(newFormat);
eventDispatcher.inputFormatChanged(newFormat);
pendingPixelWidthHeightRatio = newFormat.pixelWidthHeightRatio == Format.NO_VALUE ? 1
: newFormat.pixelWidthHeightRatio;
pendingRotationDegrees = newFormat.rotationDegrees == Format.NO_VALUE ? 0
: newFormat.rotationDegrees;
}
/**
......
......@@ -46,6 +46,13 @@ public interface VideoTrackRendererEventListener {
long initializationDurationMs);
/**
* Invoked when the format of the media being consumed by the renderer changes.
*
* @param format The new format.
*/
void onVideoInputFormatChanged(Format format);
/**
* Invoked to report the number of frames dropped by the renderer. Dropped frames are reported
* whenever the renderer is stopped having dropped frames, and optionally, whenever the count
* reaches a specified threshold whilst the renderer is started.
......@@ -122,6 +129,17 @@ public interface VideoTrackRendererEventListener {
}
}
public void inputFormatChanged(final Format format) {
if (listener != null) {
handler.post(new Runnable() {
@Override
public void run() {
listener.onVideoInputFormatChanged(format);
}
});
}
}
public void droppedFrameCount(final int droppedFrameCount, final long elapsedMs) {
if (listener != null) {
handler.post(new Runnable() {
......
......@@ -27,13 +27,6 @@ import java.util.UUID;
public interface MediaDrmCallback {
/**
* Returns the {@link UUID} of the DRM scheme that this callback supports.
*
* @return The DRM scheme {@link UUID}.
*/
UUID getUuid();
/**
* Executes a provisioning request.
*
* @param uuid The UUID of the content protection scheme.
......
......@@ -35,6 +35,7 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import java.util.HashMap;
import java.util.UUID;
......@@ -98,37 +99,77 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
private byte[] sessionId;
/**
* Instantiates a new instance using the Widevine scheme.
*
* @param callback Performs key and provisioning requests.
* @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument
* to {@link MediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
* null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required.
* @throws UnsupportedDrmException If the specified DRM scheme is not supported.
*/
public StreamingDrmSessionManager(MediaDrmCallback callback,
public static StreamingDrmSessionManager newWidevineInstance(MediaDrmCallback callback,
HashMap<String, String> optionalKeyRequestParameters, Handler eventHandler,
EventListener eventListener) {
EventListener eventListener) throws UnsupportedDrmException {
return new StreamingDrmSessionManager(C.WIDEVINE_UUID, callback, optionalKeyRequestParameters,
eventHandler, eventListener);
}
/**
* Instantiates a new instance using the PlayReady scheme.
* <p>
* Note that PlayReady is unsupported by most Android devices, with the exception of Android TV
* devices, which do provide support.
*
* @param callback Performs key and provisioning requests.
* @param customData Optional custom data to include in requests generated by the instance.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
* null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required.
* @throws UnsupportedDrmException If the specified DRM scheme is not supported.
*/
public static StreamingDrmSessionManager newPlayReadyInstance(MediaDrmCallback callback,
String customData, Handler eventHandler, EventListener eventListener)
throws UnsupportedDrmException {
HashMap<String, String> optionalKeyRequestParameters;
if (!TextUtils.isEmpty(customData)) {
optionalKeyRequestParameters = new HashMap<>();
optionalKeyRequestParameters.put(PLAYREADY_CUSTOM_DATA_KEY, customData);
} else {
optionalKeyRequestParameters = null;
}
return new StreamingDrmSessionManager(C.PLAYREADY_UUID, callback, optionalKeyRequestParameters,
eventHandler, eventListener);
}
/**
* @param uuid The UUID of the drm scheme.
* @param callback Performs key and provisioning requests.
* @param optionalKeyRequestParameters An optional map of parameters to pass as the last argument
* to {@link MediaDrm#getKeyRequest(byte[], byte[], String, int, HashMap)}. May be null.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
* null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required.
* @throws UnsupportedDrmException If the specified DRM scheme is not supported.
*/
public StreamingDrmSessionManager(UUID uuid, MediaDrmCallback callback,
HashMap<String, String> optionalKeyRequestParameters, Handler eventHandler,
EventListener eventListener) throws UnsupportedDrmException {
this.uuid = uuid;
this.callback = callback;
this.optionalKeyRequestParameters = optionalKeyRequestParameters;
this.eventHandler = eventHandler;
this.eventListener = eventListener;
uuid = callback.getUuid();
MediaDrm mediaDrm = null;
try {
mediaDrm = new MediaDrm(uuid);
mediaDrm.setOnEventListener(new MediaDrmEventListener());
state = STATE_CLOSED;
} catch (UnsupportedSchemeException e) {
lastException = new UnsupportedDrmException(
UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME, e);
state = STATE_ERROR;
throw new UnsupportedDrmException(UnsupportedDrmException.REASON_UNSUPPORTED_SCHEME, e);
} catch (Exception e) {
lastException = new UnsupportedDrmException(
UnsupportedDrmException.REASON_INSTANTIATION_ERROR, e);
state = STATE_ERROR;
} finally {
this.mediaDrm = mediaDrm;
throw new UnsupportedDrmException(UnsupportedDrmException.REASON_INSTANTIATION_ERROR, e);
}
mediaDrm.setOnEventListener(new MediaDrmEventListener());
state = STATE_CLOSED;
}
@Override
......
......@@ -232,7 +232,7 @@ public abstract class AudioDecoderTrackRenderer extends TrackRenderer implements
return false;
}
if (result == TrackStream.FORMAT_READ) {
inputFormat = formatHolder.format;
onInputFormatChanged(formatHolder.format);
return true;
}
if (inputBuffer.isEndOfStream()) {
......@@ -340,12 +340,17 @@ public abstract class AudioDecoderTrackRenderer extends TrackRenderer implements
private boolean readFormat() {
int result = readSource(formatHolder, null);
if (result == TrackStream.FORMAT_READ) {
inputFormat = formatHolder.format;
onInputFormatChanged(formatHolder.format);
return true;
}
return false;
}
private void onInputFormatChanged(Format newFormat) {
inputFormat = newFormat;
eventDispatcher.inputFormatChanged(newFormat);
}
@Override
public void handleMessage(int messageType, Object message) throws ExoPlaybackException {
if (messageType == MSG_SET_VOLUME) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment