mirror of
https://github.com/samsonjs/media.git
synced 2026-03-26 09:35:47 +00:00
Simplify demo application.
- Remove simple variant. Maintaining both simple + full is unnecessary effort. - Remove need to specify content id in Sample definition, except where it's actually required (for DRM requests in the Widevine GTS samples)
This commit is contained in:
parent
bfa1de68d8
commit
147bbe6d55
22 changed files with 105 additions and 903 deletions
|
|
@ -42,12 +42,7 @@
|
|||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name="com.google.android.exoplayer.demo.simple.SimplePlayerActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/application_name"
|
||||
android:theme="@style/PlayerTheme"/>
|
||||
|
||||
<activity android:name="com.google.android.exoplayer.demo.full.FullPlayerActivity"
|
||||
<activity android:name="com.google.android.exoplayer.demo.PlayerActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/application_name"
|
||||
android:theme="@style/PlayerTheme"/>
|
||||
|
|
|
|||
|
|
@ -44,16 +44,11 @@ public class DemoUtil {
|
|||
|
||||
public static final UUID WIDEVINE_UUID = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL);
|
||||
|
||||
public static final String CONTENT_TYPE_EXTRA = "content_type";
|
||||
public static final String CONTENT_ID_EXTRA = "content_id";
|
||||
|
||||
public static final int TYPE_DASH = 0;
|
||||
public static final int TYPE_SS = 1;
|
||||
public static final int TYPE_OTHER = 2;
|
||||
public static final int TYPE_HLS = 3;
|
||||
|
||||
public static final boolean EXPOSE_EXPERIMENTAL_FEATURES = false;
|
||||
|
||||
private static final CookieManager defaultCookieManager;
|
||||
|
||||
static {
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer.demo.full;
|
||||
package com.google.android.exoplayer.demo;
|
||||
|
||||
import com.google.android.exoplayer.ExoPlayer;
|
||||
import com.google.android.exoplayer.MediaCodecTrackRenderer.DecoderInitializationException;
|
||||
import com.google.android.exoplayer.audio.AudioTrack;
|
||||
import com.google.android.exoplayer.demo.full.player.DemoPlayer;
|
||||
import com.google.android.exoplayer.demo.player.DemoPlayer;
|
||||
import com.google.android.exoplayer.util.VerboseLogUtil;
|
||||
|
||||
import android.media.MediaCodec.CryptoException;
|
||||
|
|
@ -63,8 +63,8 @@ public class EventLogger implements DemoPlayer.Listener, DemoPlayer.InfoListener
|
|||
|
||||
@Override
|
||||
public void onStateChanged(boolean playWhenReady, int state) {
|
||||
Log.d(TAG, "state [" + getSessionTimeString() + ", " + playWhenReady + ", " +
|
||||
getStateString(state) + "]");
|
||||
Log.d(TAG, "state [" + getSessionTimeString() + ", " + playWhenReady + ", "
|
||||
+ getStateString(state) + "]");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -81,8 +81,8 @@ public class EventLogger implements DemoPlayer.Listener, DemoPlayer.InfoListener
|
|||
|
||||
@Override
|
||||
public void onBandwidthSample(int elapsedMs, long bytes, long bitrateEstimate) {
|
||||
Log.d(TAG, "bandwidth [" + getSessionTimeString() + ", " + bytes +
|
||||
", " + getTimeString(elapsedMs) + ", " + bitrateEstimate + "]");
|
||||
Log.d(TAG, "bandwidth [" + getSessionTimeString() + ", " + bytes + ", "
|
||||
+ getTimeString(elapsedMs) + ", " + bitrateEstimate + "]");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -104,21 +104,21 @@ public class EventLogger implements DemoPlayer.Listener, DemoPlayer.InfoListener
|
|||
public void onLoadCompleted(int sourceId, long bytesLoaded) {
|
||||
if (VerboseLogUtil.isTagEnabled(TAG)) {
|
||||
long downloadTime = SystemClock.elapsedRealtime() - loadStartTimeMs[sourceId];
|
||||
Log.v(TAG, "loadEnd [" + getSessionTimeString() + ", " + sourceId + ", " +
|
||||
downloadTime + "]");
|
||||
Log.v(TAG, "loadEnd [" + getSessionTimeString() + ", " + sourceId + ", " + downloadTime
|
||||
+ "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVideoFormatEnabled(String formatId, int trigger, int mediaTimeMs) {
|
||||
Log.d(TAG, "videoFormat [" + getSessionTimeString() + ", " + formatId + ", " +
|
||||
Integer.toString(trigger) + "]");
|
||||
Log.d(TAG, "videoFormat [" + getSessionTimeString() + ", " + formatId + ", "
|
||||
+ Integer.toString(trigger) + "]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAudioFormatEnabled(String formatId, int trigger, int mediaTimeMs) {
|
||||
Log.d(TAG, "audioFormat [" + getSessionTimeString() + ", " + formatId + ", " +
|
||||
Integer.toString(trigger) + "]");
|
||||
Log.d(TAG, "audioFormat [" + getSessionTimeString() + ", " + formatId + ", "
|
||||
+ Integer.toString(trigger) + "]");
|
||||
}
|
||||
|
||||
// DemoPlayer.InternalErrorListener
|
||||
|
|
@ -13,21 +13,19 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer.demo.full;
|
||||
package com.google.android.exoplayer.demo;
|
||||
|
||||
import com.google.android.exoplayer.ExoPlayer;
|
||||
import com.google.android.exoplayer.VideoSurfaceView;
|
||||
import com.google.android.exoplayer.audio.AudioCapabilities;
|
||||
import com.google.android.exoplayer.audio.AudioCapabilitiesReceiver;
|
||||
import com.google.android.exoplayer.demo.DemoUtil;
|
||||
import com.google.android.exoplayer.demo.R;
|
||||
import com.google.android.exoplayer.demo.full.player.DashRendererBuilder;
|
||||
import com.google.android.exoplayer.demo.full.player.DefaultRendererBuilder;
|
||||
import com.google.android.exoplayer.demo.full.player.DemoPlayer;
|
||||
import com.google.android.exoplayer.demo.full.player.DemoPlayer.RendererBuilder;
|
||||
import com.google.android.exoplayer.demo.full.player.HlsRendererBuilder;
|
||||
import com.google.android.exoplayer.demo.full.player.SmoothStreamingRendererBuilder;
|
||||
import com.google.android.exoplayer.demo.full.player.UnsupportedDrmException;
|
||||
import com.google.android.exoplayer.demo.player.DashRendererBuilder;
|
||||
import com.google.android.exoplayer.demo.player.DefaultRendererBuilder;
|
||||
import com.google.android.exoplayer.demo.player.DemoPlayer;
|
||||
import com.google.android.exoplayer.demo.player.DemoPlayer.RendererBuilder;
|
||||
import com.google.android.exoplayer.demo.player.HlsRendererBuilder;
|
||||
import com.google.android.exoplayer.demo.player.SmoothStreamingRendererBuilder;
|
||||
import com.google.android.exoplayer.demo.player.UnsupportedDrmException;
|
||||
import com.google.android.exoplayer.metadata.TxxxMetadata;
|
||||
import com.google.android.exoplayer.text.CaptionStyleCompat;
|
||||
import com.google.android.exoplayer.text.SubtitleView;
|
||||
|
|
@ -65,11 +63,14 @@ import java.util.Map;
|
|||
/**
|
||||
* An activity that plays media using {@link DemoPlayer}.
|
||||
*/
|
||||
public class FullPlayerActivity extends Activity implements SurfaceHolder.Callback, OnClickListener,
|
||||
public class PlayerActivity extends Activity implements SurfaceHolder.Callback, OnClickListener,
|
||||
DemoPlayer.Listener, DemoPlayer.TextListener, DemoPlayer.Id3MetadataListener,
|
||||
AudioCapabilitiesReceiver.Listener {
|
||||
|
||||
private static final String TAG = "FullPlayerActivity";
|
||||
public static final String CONTENT_TYPE_EXTRA = "content_type";
|
||||
public static final String CONTENT_ID_EXTRA = "content_id";
|
||||
|
||||
private static final String TAG = "PlayerActivity";
|
||||
|
||||
private static final float CAPTION_LINE_HEIGHT_RATIO = 0.0533f;
|
||||
private static final int MENU_GROUP_TRACKS = 1;
|
||||
|
|
@ -110,10 +111,10 @@ public class FullPlayerActivity extends Activity implements SurfaceHolder.Callba
|
|||
|
||||
Intent intent = getIntent();
|
||||
contentUri = intent.getData();
|
||||
contentType = intent.getIntExtra(DemoUtil.CONTENT_TYPE_EXTRA, DemoUtil.TYPE_OTHER);
|
||||
contentId = intent.getStringExtra(DemoUtil.CONTENT_ID_EXTRA);
|
||||
contentType = intent.getIntExtra(CONTENT_TYPE_EXTRA, DemoUtil.TYPE_OTHER);
|
||||
contentId = intent.getStringExtra(CONTENT_ID_EXTRA);
|
||||
|
||||
setContentView(R.layout.player_activity_full);
|
||||
setContentView(R.layout.player_activity);
|
||||
View root = findViewById(R.id.root);
|
||||
root.setOnTouchListener(new OnTouchListener() {
|
||||
@Override
|
||||
|
|
@ -15,15 +15,17 @@
|
|||
*/
|
||||
package com.google.android.exoplayer.demo;
|
||||
|
||||
import com.google.android.exoplayer.MediaCodecUtil;
|
||||
import com.google.android.exoplayer.MediaCodecUtil.DecoderQueryException;
|
||||
import com.google.android.exoplayer.demo.Samples.Sample;
|
||||
import com.google.android.exoplayer.demo.full.FullPlayerActivity;
|
||||
import com.google.android.exoplayer.demo.simple.SimplePlayerActivity;
|
||||
import com.google.android.exoplayer.util.MimeTypes;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
|
@ -38,6 +40,8 @@ import android.widget.TextView;
|
|||
*/
|
||||
public class SampleChooserActivity extends Activity {
|
||||
|
||||
private static final String TAG = "SampleChooserActivity";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
|
@ -46,21 +50,25 @@ public class SampleChooserActivity extends Activity {
|
|||
ListView sampleList = (ListView) findViewById(R.id.sample_list);
|
||||
final SampleAdapter sampleAdapter = new SampleAdapter(this);
|
||||
|
||||
sampleAdapter.add(new Header("Simple player"));
|
||||
sampleAdapter.addAll((Object[]) Samples.SIMPLE);
|
||||
sampleAdapter.add(new Header("YouTube DASH"));
|
||||
sampleAdapter.addAll((Object[]) Samples.YOUTUBE_DASH_MP4);
|
||||
sampleAdapter.add(new Header("Widevine GTS DASH"));
|
||||
sampleAdapter.addAll((Object[]) Samples.WIDEVINE_GTS);
|
||||
sampleAdapter.add(new Header("SmoothStreaming"));
|
||||
sampleAdapter.addAll((Object[]) Samples.SMOOTHSTREAMING);
|
||||
sampleAdapter.add(new Header("Misc"));
|
||||
sampleAdapter.addAll((Object[]) Samples.MISC);
|
||||
sampleAdapter.add(new Header("HLS"));
|
||||
sampleAdapter.addAll((Object[]) Samples.HLS);
|
||||
if (DemoUtil.EXPOSE_EXPERIMENTAL_FEATURES) {
|
||||
sampleAdapter.add(new Header("YouTube WebM DASH (Experimental)"));
|
||||
sampleAdapter.addAll((Object[]) Samples.YOUTUBE_DASH_WEBM);
|
||||
sampleAdapter.add(new Header("Misc"));
|
||||
sampleAdapter.addAll((Object[]) Samples.MISC);
|
||||
|
||||
// Add WebM samples if the device has a VP9 decoder.
|
||||
try {
|
||||
if (MediaCodecUtil.getDecoderInfo(MimeTypes.VIDEO_VP9, false) != null) {
|
||||
sampleAdapter.add(new Header("YouTube WebM DASH (Experimental)"));
|
||||
sampleAdapter.addAll((Object[]) Samples.YOUTUBE_DASH_WEBM);
|
||||
}
|
||||
} catch (DecoderQueryException e) {
|
||||
Log.e(TAG, "Failed to query vp9 decoder", e);
|
||||
}
|
||||
|
||||
sampleList.setAdapter(sampleAdapter);
|
||||
|
|
@ -76,12 +84,10 @@ public class SampleChooserActivity extends Activity {
|
|||
}
|
||||
|
||||
private void onSampleSelected(Sample sample) {
|
||||
Class<?> playerActivityClass = sample.fullPlayer ? FullPlayerActivity.class
|
||||
: SimplePlayerActivity.class;
|
||||
Intent mpdIntent = new Intent(this, playerActivityClass)
|
||||
Intent mpdIntent = new Intent(this, PlayerActivity.class)
|
||||
.setData(Uri.parse(sample.uri))
|
||||
.putExtra(DemoUtil.CONTENT_ID_EXTRA, sample.contentId)
|
||||
.putExtra(DemoUtil.CONTENT_TYPE_EXTRA, sample.type);
|
||||
.putExtra(PlayerActivity.CONTENT_ID_EXTRA, sample.contentId)
|
||||
.putExtra(PlayerActivity.CONTENT_TYPE_EXTRA, sample.type);
|
||||
startActivity(mpdIntent);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package com.google.android.exoplayer.demo;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Holds statically defined sample definitions.
|
||||
*/
|
||||
|
|
@ -26,72 +28,53 @@ package com.google.android.exoplayer.demo;
|
|||
public final String contentId;
|
||||
public final String uri;
|
||||
public final int type;
|
||||
public final boolean fullPlayer;
|
||||
|
||||
public Sample(String name, String contentId, String uri, int type, boolean fullPlayer) {
|
||||
public Sample(String name, String uri, int type) {
|
||||
this(name, name.toLowerCase(Locale.US).replaceAll("\\s", ""), uri, type);
|
||||
}
|
||||
|
||||
public Sample(String name, String contentId, String uri, int type) {
|
||||
this.name = name;
|
||||
this.contentId = contentId;
|
||||
this.uri = uri;
|
||||
this.type = type;
|
||||
this.fullPlayer = fullPlayer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static final Sample[] SIMPLE = new Sample[] {
|
||||
new Sample("Google Glass (DASH)", "bf5bb2419360daf1",
|
||||
"http://www.youtube.com/api/manifest/dash/id/bf5bb2419360daf1/source/youtube?"
|
||||
+ "as=fmp4_audio_clear,fmp4_sd_hd_clear&sparams=ip,ipbits,expire,as&ip=0.0.0.0&"
|
||||
+ "ipbits=0&expire=19000000000&signature=255F6B3C07C753C88708C07EA31B7A1A10703C8D."
|
||||
+ "2D6A28B21F921D0B245CDCF36F7EB54A2B5ABFC2&key=ik0", DemoUtil.TYPE_DASH, false),
|
||||
new Sample("Google Play (DASH)", "3aa39fa2cc27967f",
|
||||
"http://www.youtube.com/api/manifest/dash/id/3aa39fa2cc27967f/source/youtube?"
|
||||
+ "as=fmp4_audio_clear,fmp4_sd_hd_clear&sparams=ip,ipbits,expire,as&ip=0.0.0.0&ipbits=0&"
|
||||
+ "expire=19000000000&signature=7181C59D0252B285D593E1B61D985D5B7C98DE2A."
|
||||
+ "5B445837F55A40E0F28AACAA047982E372D177E2&key=ik0", DemoUtil.TYPE_DASH, false),
|
||||
new Sample("Super speed (SmoothStreaming)", "uid:ss:superspeed",
|
||||
"http://playready.directtaps.net/smoothstreaming/SSWSS720H264/SuperSpeedway_720.ism",
|
||||
DemoUtil.TYPE_SS, false),
|
||||
new Sample("Apple master playlist (HLS)", "uid:hls:applemaster",
|
||||
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/"
|
||||
+ "bipbop_4x3_variant.m3u8", DemoUtil.TYPE_HLS, false),
|
||||
new Sample("Dizzy (Misc)", "uid:misc:dizzy",
|
||||
"http://html5demos.com/assets/dizzy.mp4", DemoUtil.TYPE_OTHER, false),
|
||||
};
|
||||
|
||||
public static final Sample[] YOUTUBE_DASH_MP4 = new Sample[] {
|
||||
new Sample("Google Glass", "bf5bb2419360daf1",
|
||||
new Sample("Google Glass",
|
||||
"http://www.youtube.com/api/manifest/dash/id/bf5bb2419360daf1/source/youtube?"
|
||||
+ "as=fmp4_audio_clear,fmp4_sd_hd_clear&sparams=ip,ipbits,expire,as&ip=0.0.0.0&"
|
||||
+ "ipbits=0&expire=19000000000&signature=255F6B3C07C753C88708C07EA31B7A1A10703C8D."
|
||||
+ "2D6A28B21F921D0B245CDCF36F7EB54A2B5ABFC2&key=ik0", DemoUtil.TYPE_DASH, true),
|
||||
new Sample("Google Play", "3aa39fa2cc27967f",
|
||||
+ "2D6A28B21F921D0B245CDCF36F7EB54A2B5ABFC2&key=ik0", DemoUtil.TYPE_DASH),
|
||||
new Sample("Google Play",
|
||||
"http://www.youtube.com/api/manifest/dash/id/3aa39fa2cc27967f/source/youtube?"
|
||||
+ "as=fmp4_audio_clear,fmp4_sd_hd_clear&sparams=ip,ipbits,expire,as&ip=0.0.0.0&ipbits=0&"
|
||||
+ "expire=19000000000&signature=7181C59D0252B285D593E1B61D985D5B7C98DE2A."
|
||||
+ "5B445837F55A40E0F28AACAA047982E372D177E2&key=ik0", DemoUtil.TYPE_DASH, true),
|
||||
+ "5B445837F55A40E0F28AACAA047982E372D177E2&key=ik0", DemoUtil.TYPE_DASH),
|
||||
};
|
||||
|
||||
public static final Sample[] YOUTUBE_DASH_WEBM = new Sample[] {
|
||||
new Sample("Google Glass", "bf5bb2419360daf1",
|
||||
new Sample("Google Glass",
|
||||
"http://www.youtube.com/api/manifest/dash/id/bf5bb2419360daf1/source/youtube?"
|
||||
+ "as=fmp4_audio_clear,webm2_sd_hd_clear&sparams=ip,ipbits,expire,as&ip=0.0.0.0&ipbits=0&"
|
||||
+ "expire=19000000000&signature=A3EC7EE53ABE601B357F7CAB8B54AD0702CA85A7."
|
||||
+ "446E9C38E47E3EDAF39E0163C390FF83A7944918&key=ik0", DemoUtil.TYPE_DASH, true),
|
||||
new Sample("Google Play", "3aa39fa2cc27967f",
|
||||
+ "446E9C38E47E3EDAF39E0163C390FF83A7944918&key=ik0", DemoUtil.TYPE_DASH),
|
||||
new Sample("Google Play",
|
||||
"http://www.youtube.com/api/manifest/dash/id/3aa39fa2cc27967f/source/youtube?"
|
||||
+ "as=fmp4_audio_clear,webm2_sd_hd_clear&sparams=ip,ipbits,expire,as&ip=0.0.0.0&ipbits=0&"
|
||||
+ "expire=19000000000&signature=B752B262C6D7262EC4E4EB67901E5D8F7058A81D."
|
||||
+ "C0358CE1E335417D9A8D88FF192F0D5D8F6DA1B6&key=ik0", DemoUtil.TYPE_DASH, true),
|
||||
+ "C0358CE1E335417D9A8D88FF192F0D5D8F6DA1B6&key=ik0", DemoUtil.TYPE_DASH),
|
||||
};
|
||||
|
||||
public static final Sample[] SMOOTHSTREAMING = new Sample[] {
|
||||
new Sample("Super speed", "uid:ss:superspeed",
|
||||
new Sample("Super speed",
|
||||
"http://playready.directtaps.net/smoothstreaming/SSWSS720H264/SuperSpeedway_720.ism",
|
||||
DemoUtil.TYPE_SS, true),
|
||||
new Sample("Super speed (PlayReady)", "uid:ss:pr:superspeed",
|
||||
DemoUtil.TYPE_SS),
|
||||
new Sample("Super speed (PlayReady)",
|
||||
"http://playready.directtaps.net/smoothstreaming/SSWSS720H264PR/SuperSpeedway_720.ism",
|
||||
DemoUtil.TYPE_SS, true),
|
||||
DemoUtil.TYPE_SS),
|
||||
};
|
||||
|
||||
public static final Sample[] WIDEVINE_GTS = new Sample[] {
|
||||
|
|
@ -99,54 +82,54 @@ package com.google.android.exoplayer.demo;
|
|||
"http://www.youtube.com/api/manifest/dash/id/d286538032258a1c/source/youtube?"
|
||||
+ "as=fmp4_audio_cenc,fmp4_sd_hd_cenc&sparams=ip,ipbits,expire,as&ip=0.0.0.0&ipbits=0"
|
||||
+ "&expire=19000000000&signature=41EA40A027A125A16292E0A5E3277A3B5FA9B938."
|
||||
+ "0BB075C396FFDDC97E526E8F77DC26FF9667D0D6&key=ik0", DemoUtil.TYPE_DASH, true),
|
||||
+ "0BB075C396FFDDC97E526E8F77DC26FF9667D0D6&key=ik0", DemoUtil.TYPE_DASH),
|
||||
new Sample("WV: HDCP not required", "48fcc369939ac96c",
|
||||
"http://www.youtube.com/api/manifest/dash/id/48fcc369939ac96c/source/youtube?"
|
||||
+ "as=fmp4_audio_cenc,fmp4_sd_hd_cenc&sparams=ip,ipbits,expire,as&ip=0.0.0.0&ipbits=0"
|
||||
+ "&expire=19000000000&signature=315911BDCEED0FB0C763455BDCC97449DAAFA9E8."
|
||||
+ "5B41E2EB411F797097A359D6671D2CDE26272373&key=ik0", DemoUtil.TYPE_DASH, true),
|
||||
+ "5B41E2EB411F797097A359D6671D2CDE26272373&key=ik0", DemoUtil.TYPE_DASH),
|
||||
new Sample("WV: HDCP required", "e06c39f1151da3df",
|
||||
"http://www.youtube.com/api/manifest/dash/id/e06c39f1151da3df/source/youtube?"
|
||||
+ "as=fmp4_audio_cenc,fmp4_sd_hd_cenc&sparams=ip,ipbits,expire,as&ip=0.0.0.0&ipbits=0"
|
||||
+ "&expire=19000000000&signature=A47A1E13E7243BD567601A75F79B34644D0DC592."
|
||||
+ "B09589A34FA23527EFC1552907754BB8033870BD&key=ik0", DemoUtil.TYPE_DASH, true),
|
||||
+ "B09589A34FA23527EFC1552907754BB8033870BD&key=ik0", DemoUtil.TYPE_DASH),
|
||||
new Sample("WV: Secure video path required", "0894c7c8719b28a0",
|
||||
"http://www.youtube.com/api/manifest/dash/id/0894c7c8719b28a0/source/youtube?"
|
||||
+ "as=fmp4_audio_cenc,fmp4_sd_hd_cenc&sparams=ip,ipbits,expire,as&ip=0.0.0.0&ipbits=0"
|
||||
+ "&expire=19000000000&signature=2847EE498970F6B45176766CD2802FEB4D4CB7B2."
|
||||
+ "A1CA51EC40A1C1039BA800C41500DD448C03EEDA&key=ik0", DemoUtil.TYPE_DASH, true),
|
||||
+ "A1CA51EC40A1C1039BA800C41500DD448C03EEDA&key=ik0", DemoUtil.TYPE_DASH),
|
||||
new Sample("WV: HDCP + secure video path required", "efd045b1eb61888a",
|
||||
"http://www.youtube.com/api/manifest/dash/id/efd045b1eb61888a/source/youtube?"
|
||||
+ "as=fmp4_audio_cenc,fmp4_sd_hd_cenc&sparams=ip,ipbits,expire,as&ip=0.0.0.0&ipbits=0"
|
||||
+ "&expire=19000000000&signature=61611F115EEEC7BADE5536827343FFFE2D83D14F."
|
||||
+ "2FDF4BFA502FB5865C5C86401314BDDEA4799BD0&key=ik0", DemoUtil.TYPE_DASH, true),
|
||||
+ "2FDF4BFA502FB5865C5C86401314BDDEA4799BD0&key=ik0", DemoUtil.TYPE_DASH),
|
||||
new Sample("WV: 30s license duration", "f9a34cab7b05881a",
|
||||
"http://www.youtube.com/api/manifest/dash/id/f9a34cab7b05881a/source/youtube?"
|
||||
+ "as=fmp4_audio_cenc,fmp4_sd_hd_cenc&sparams=ip,ipbits,expire,as&ip=0.0.0.0&ipbits=0"
|
||||
+ "&expire=19000000000&signature=88DC53943385CED8CF9F37ADD9E9843E3BF621E6."
|
||||
+ "22727BB612D24AA4FACE4EF62726F9461A9BF57A&key=ik0", DemoUtil.TYPE_DASH, true),
|
||||
+ "22727BB612D24AA4FACE4EF62726F9461A9BF57A&key=ik0", DemoUtil.TYPE_DASH),
|
||||
};
|
||||
|
||||
public static final Sample[] HLS = new Sample[] {
|
||||
new Sample("Apple master playlist", "uid:hls:applemaster",
|
||||
new Sample("Apple master playlist",
|
||||
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/"
|
||||
+ "bipbop_4x3_variant.m3u8", DemoUtil.TYPE_HLS, true),
|
||||
new Sample("Apple master playlist advanced", "uid:hls:applemasteradvanced",
|
||||
+ "bipbop_4x3_variant.m3u8", DemoUtil.TYPE_HLS),
|
||||
new Sample("Apple master playlist advanced",
|
||||
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_16x9/"
|
||||
+ "bipbop_16x9_variant.m3u8", DemoUtil.TYPE_HLS, true),
|
||||
new Sample("Apple single media playlist", "uid:hls:applesinglemedia",
|
||||
+ "bipbop_16x9_variant.m3u8", DemoUtil.TYPE_HLS),
|
||||
new Sample("Apple single media playlist",
|
||||
"https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear1/"
|
||||
+ "prog_index.m3u8", DemoUtil.TYPE_HLS, true),
|
||||
+ "prog_index.m3u8", DemoUtil.TYPE_HLS),
|
||||
};
|
||||
|
||||
public static final Sample[] MISC = new Sample[] {
|
||||
new Sample("Dizzy", "uid:misc:dizzy", "http://html5demos.com/assets/dizzy.mp4",
|
||||
DemoUtil.TYPE_OTHER, true),
|
||||
new Sample("Dizzy (https->http redirect)", "uid:misc:dizzy2", "https://goo.gl/MtUDEj",
|
||||
DemoUtil.TYPE_OTHER, true),
|
||||
new Sample("Apple AAC 10s", "uid:misc:appleaacseg", "https://devimages.apple.com.edgekey.net/"
|
||||
new Sample("Dizzy", "http://html5demos.com/assets/dizzy.mp4",
|
||||
DemoUtil.TYPE_OTHER),
|
||||
new Sample("Dizzy (https->http redirect)", "https://goo.gl/MtUDEj",
|
||||
DemoUtil.TYPE_OTHER),
|
||||
new Sample("Apple AAC 10s", "https://devimages.apple.com.edgekey.net/"
|
||||
+ "streaming/examples/bipbop_4x3/gear0/fileSequence0.aac",
|
||||
DemoUtil.TYPE_OTHER, true),
|
||||
DemoUtil.TYPE_OTHER),
|
||||
};
|
||||
|
||||
private Samples() {}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,8 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer.demo.full;
|
||||
package com.google.android.exoplayer.demo;
|
||||
|
||||
import com.google.android.exoplayer.demo.DemoUtil;
|
||||
import com.google.android.exoplayer.drm.MediaDrmCallback;
|
||||
import com.google.android.exoplayer.drm.StreamingDrmSessionManager;
|
||||
|
||||
|
|
@ -13,9 +13,8 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer.demo.full;
|
||||
package com.google.android.exoplayer.demo;
|
||||
|
||||
import com.google.android.exoplayer.demo.DemoUtil;
|
||||
import com.google.android.exoplayer.drm.MediaDrmCallback;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer.demo.full.player;
|
||||
package com.google.android.exoplayer.demo.player;
|
||||
|
||||
import com.google.android.exoplayer.Ac3PassthroughAudioTrackRenderer;
|
||||
import com.google.android.exoplayer.DefaultLoadControl;
|
||||
|
|
@ -38,8 +38,8 @@ import com.google.android.exoplayer.dash.mpd.MediaPresentationDescriptionParser;
|
|||
import com.google.android.exoplayer.dash.mpd.Period;
|
||||
import com.google.android.exoplayer.dash.mpd.Representation;
|
||||
import com.google.android.exoplayer.demo.DemoUtil;
|
||||
import com.google.android.exoplayer.demo.full.player.DemoPlayer.RendererBuilder;
|
||||
import com.google.android.exoplayer.demo.full.player.DemoPlayer.RendererBuilderCallback;
|
||||
import com.google.android.exoplayer.demo.player.DemoPlayer.RendererBuilder;
|
||||
import com.google.android.exoplayer.demo.player.DemoPlayer.RendererBuilderCallback;
|
||||
import com.google.android.exoplayer.drm.DrmSessionManager;
|
||||
import com.google.android.exoplayer.drm.MediaDrmCallback;
|
||||
import com.google.android.exoplayer.drm.StreamingDrmSessionManager;
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer.demo.full.player;
|
||||
package com.google.android.exoplayer.demo.player;
|
||||
|
||||
import com.google.android.exoplayer.ExoPlaybackException;
|
||||
import com.google.android.exoplayer.MediaCodecTrackRenderer;
|
||||
|
|
@ -82,8 +82,8 @@ import android.widget.TextView;
|
|||
}
|
||||
|
||||
private String getRenderString() {
|
||||
return "ms(" + (currentPositionUs / 1000) + "), " + getQualityString() +
|
||||
", " + renderer.codecCounters.getDebugString();
|
||||
return "ms(" + (currentPositionUs / 1000) + "), " + getQualityString()
|
||||
+ ", " + renderer.codecCounters.getDebugString();
|
||||
}
|
||||
|
||||
private String getQualityString() {
|
||||
|
|
@ -13,13 +13,13 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer.demo.full.player;
|
||||
package com.google.android.exoplayer.demo.player;
|
||||
|
||||
import com.google.android.exoplayer.MediaCodecAudioTrackRenderer;
|
||||
import com.google.android.exoplayer.MediaCodecVideoTrackRenderer;
|
||||
import com.google.android.exoplayer.TrackRenderer;
|
||||
import com.google.android.exoplayer.demo.full.player.DemoPlayer.RendererBuilder;
|
||||
import com.google.android.exoplayer.demo.full.player.DemoPlayer.RendererBuilderCallback;
|
||||
import com.google.android.exoplayer.demo.player.DemoPlayer.RendererBuilder;
|
||||
import com.google.android.exoplayer.demo.player.DemoPlayer.RendererBuilderCallback;
|
||||
import com.google.android.exoplayer.source.DefaultSampleSource;
|
||||
import com.google.android.exoplayer.source.FrameworkSampleExtractor;
|
||||
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer.demo.full.player;
|
||||
package com.google.android.exoplayer.demo.player;
|
||||
|
||||
import com.google.android.exoplayer.Ac3PassthroughAudioTrackRenderer;
|
||||
import com.google.android.exoplayer.DummyTrackRenderer;
|
||||
|
|
@ -13,13 +13,13 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer.demo.full.player;
|
||||
package com.google.android.exoplayer.demo.player;
|
||||
|
||||
import com.google.android.exoplayer.MediaCodecAudioTrackRenderer;
|
||||
import com.google.android.exoplayer.MediaCodecVideoTrackRenderer;
|
||||
import com.google.android.exoplayer.TrackRenderer;
|
||||
import com.google.android.exoplayer.demo.full.player.DemoPlayer.RendererBuilder;
|
||||
import com.google.android.exoplayer.demo.full.player.DemoPlayer.RendererBuilderCallback;
|
||||
import com.google.android.exoplayer.demo.player.DemoPlayer.RendererBuilder;
|
||||
import com.google.android.exoplayer.demo.player.DemoPlayer.RendererBuilderCallback;
|
||||
import com.google.android.exoplayer.hls.HlsChunkSource;
|
||||
import com.google.android.exoplayer.hls.HlsPlaylist;
|
||||
import com.google.android.exoplayer.hls.HlsPlaylistParser;
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer.demo.full.player;
|
||||
package com.google.android.exoplayer.demo.player;
|
||||
|
||||
import com.google.android.exoplayer.DefaultLoadControl;
|
||||
import com.google.android.exoplayer.LoadControl;
|
||||
|
|
@ -27,8 +27,8 @@ import com.google.android.exoplayer.chunk.ChunkSource;
|
|||
import com.google.android.exoplayer.chunk.FormatEvaluator;
|
||||
import com.google.android.exoplayer.chunk.FormatEvaluator.AdaptiveEvaluator;
|
||||
import com.google.android.exoplayer.chunk.MultiTrackChunkSource;
|
||||
import com.google.android.exoplayer.demo.full.player.DemoPlayer.RendererBuilder;
|
||||
import com.google.android.exoplayer.demo.full.player.DemoPlayer.RendererBuilderCallback;
|
||||
import com.google.android.exoplayer.demo.player.DemoPlayer.RendererBuilder;
|
||||
import com.google.android.exoplayer.demo.player.DemoPlayer.RendererBuilderCallback;
|
||||
import com.google.android.exoplayer.drm.DrmSessionManager;
|
||||
import com.google.android.exoplayer.drm.MediaDrmCallback;
|
||||
import com.google.android.exoplayer.drm.StreamingDrmSessionManager;
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer.demo.full.player;
|
||||
package com.google.android.exoplayer.demo.player;
|
||||
|
||||
/**
|
||||
* Exception thrown when the required level of DRM is not supported.
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 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.exoplayer.demo.simple;
|
||||
|
||||
import com.google.android.exoplayer.DefaultLoadControl;
|
||||
import com.google.android.exoplayer.LoadControl;
|
||||
import com.google.android.exoplayer.MediaCodecAudioTrackRenderer;
|
||||
import com.google.android.exoplayer.MediaCodecUtil;
|
||||
import com.google.android.exoplayer.MediaCodecUtil.DecoderQueryException;
|
||||
import com.google.android.exoplayer.MediaCodecVideoTrackRenderer;
|
||||
import com.google.android.exoplayer.SampleSource;
|
||||
import com.google.android.exoplayer.chunk.ChunkSampleSource;
|
||||
import com.google.android.exoplayer.chunk.ChunkSource;
|
||||
import com.google.android.exoplayer.chunk.Format;
|
||||
import com.google.android.exoplayer.chunk.FormatEvaluator;
|
||||
import com.google.android.exoplayer.chunk.FormatEvaluator.AdaptiveEvaluator;
|
||||
import com.google.android.exoplayer.dash.DashChunkSource;
|
||||
import com.google.android.exoplayer.dash.mpd.AdaptationSet;
|
||||
import com.google.android.exoplayer.dash.mpd.MediaPresentationDescription;
|
||||
import com.google.android.exoplayer.dash.mpd.MediaPresentationDescriptionParser;
|
||||
import com.google.android.exoplayer.dash.mpd.Period;
|
||||
import com.google.android.exoplayer.dash.mpd.Representation;
|
||||
import com.google.android.exoplayer.demo.simple.SimplePlayerActivity.RendererBuilder;
|
||||
import com.google.android.exoplayer.demo.simple.SimplePlayerActivity.RendererBuilderCallback;
|
||||
import com.google.android.exoplayer.upstream.BufferPool;
|
||||
import com.google.android.exoplayer.upstream.DataSource;
|
||||
import com.google.android.exoplayer.upstream.DefaultBandwidthMeter;
|
||||
import com.google.android.exoplayer.upstream.UriDataSource;
|
||||
import com.google.android.exoplayer.util.ManifestFetcher;
|
||||
import com.google.android.exoplayer.util.ManifestFetcher.ManifestCallback;
|
||||
import com.google.android.exoplayer.util.MimeTypes;
|
||||
import com.google.android.exoplayer.util.Util;
|
||||
|
||||
import android.media.MediaCodec;
|
||||
import android.os.Handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link RendererBuilder} for DASH.
|
||||
*/
|
||||
/* package */ class DashRendererBuilder implements RendererBuilder,
|
||||
ManifestCallback<MediaPresentationDescription> {
|
||||
|
||||
private static final int BUFFER_SEGMENT_SIZE = 64 * 1024;
|
||||
private static final int VIDEO_BUFFER_SEGMENTS = 200;
|
||||
private static final int AUDIO_BUFFER_SEGMENTS = 60;
|
||||
private static final int LIVE_EDGE_LATENCY_MS = 30000;
|
||||
|
||||
private final SimplePlayerActivity playerActivity;
|
||||
private final String userAgent;
|
||||
private final String url;
|
||||
private final String contentId;
|
||||
|
||||
private RendererBuilderCallback callback;
|
||||
private ManifestFetcher<MediaPresentationDescription> manifestFetcher;
|
||||
|
||||
public DashRendererBuilder(SimplePlayerActivity playerActivity, String userAgent, String url,
|
||||
String contentId) {
|
||||
this.playerActivity = playerActivity;
|
||||
this.userAgent = userAgent;
|
||||
this.url = url;
|
||||
this.contentId = contentId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildRenderers(RendererBuilderCallback callback) {
|
||||
this.callback = callback;
|
||||
MediaPresentationDescriptionParser parser = new MediaPresentationDescriptionParser();
|
||||
manifestFetcher = new ManifestFetcher<MediaPresentationDescription>(parser, contentId, url,
|
||||
userAgent);
|
||||
manifestFetcher.singleLoad(playerActivity.getMainLooper(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onManifestError(String contentId, IOException e) {
|
||||
callback.onRenderersError(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onManifest(String contentId, MediaPresentationDescription manifest) {
|
||||
Period period = manifest.periods.get(0);
|
||||
Handler mainHandler = playerActivity.getMainHandler();
|
||||
LoadControl loadControl = new DefaultLoadControl(new BufferPool(BUFFER_SEGMENT_SIZE));
|
||||
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
|
||||
|
||||
// Determine which video representations we should use for playback.
|
||||
int maxDecodableFrameSize;
|
||||
try {
|
||||
maxDecodableFrameSize = MediaCodecUtil.maxH264DecodableFrameSize();
|
||||
} catch (DecoderQueryException e) {
|
||||
callback.onRenderersError(e);
|
||||
return;
|
||||
}
|
||||
|
||||
int videoAdaptationSetIndex = period.getAdaptationSetIndex(AdaptationSet.TYPE_VIDEO);
|
||||
List<Representation> videoRepresentations =
|
||||
period.adaptationSets.get(videoAdaptationSetIndex).representations;
|
||||
ArrayList<Integer> videoRepresentationIndexList = new ArrayList<Integer>();
|
||||
for (int i = 0; i < videoRepresentations.size(); i++) {
|
||||
Format format = videoRepresentations.get(i).format;
|
||||
if (format.width * format.height > maxDecodableFrameSize) {
|
||||
// Filtering stream that device cannot play
|
||||
} else if (!format.mimeType.equals(MimeTypes.VIDEO_MP4)
|
||||
&& !format.mimeType.equals(MimeTypes.VIDEO_WEBM)) {
|
||||
// Filtering unsupported mime type
|
||||
} else {
|
||||
videoRepresentationIndexList.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Build the video renderer.
|
||||
final MediaCodecVideoTrackRenderer videoRenderer;
|
||||
if (videoRepresentationIndexList.isEmpty()) {
|
||||
videoRenderer = null;
|
||||
} else {
|
||||
int[] videoRepresentationIndices = Util.toArray(videoRepresentationIndexList);
|
||||
DataSource videoDataSource = new UriDataSource(userAgent, bandwidthMeter);
|
||||
ChunkSource videoChunkSource = new DashChunkSource(manifestFetcher, videoAdaptationSetIndex,
|
||||
videoRepresentationIndices, videoDataSource, new AdaptiveEvaluator(bandwidthMeter),
|
||||
LIVE_EDGE_LATENCY_MS);
|
||||
ChunkSampleSource videoSampleSource = new ChunkSampleSource(videoChunkSource, loadControl,
|
||||
VIDEO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true);
|
||||
videoRenderer = new MediaCodecVideoTrackRenderer(videoSampleSource,
|
||||
MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 0, mainHandler, playerActivity, 50);
|
||||
}
|
||||
|
||||
// Build the audio renderer.
|
||||
int audioAdaptationSetIndex = period.getAdaptationSetIndex(AdaptationSet.TYPE_AUDIO);
|
||||
DataSource audioDataSource = new UriDataSource(userAgent, bandwidthMeter);
|
||||
ChunkSource audioChunkSource = new DashChunkSource(manifestFetcher, audioAdaptationSetIndex,
|
||||
new int[] {0}, audioDataSource, new FormatEvaluator.FixedEvaluator(), LIVE_EDGE_LATENCY_MS);
|
||||
SampleSource audioSampleSource = new ChunkSampleSource(audioChunkSource, loadControl,
|
||||
AUDIO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true);
|
||||
MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(
|
||||
audioSampleSource);
|
||||
callback.onRenderers(videoRenderer, audioRenderer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 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.exoplayer.demo.simple;
|
||||
|
||||
import com.google.android.exoplayer.MediaCodecAudioTrackRenderer;
|
||||
import com.google.android.exoplayer.MediaCodecVideoTrackRenderer;
|
||||
import com.google.android.exoplayer.demo.simple.SimplePlayerActivity.RendererBuilder;
|
||||
import com.google.android.exoplayer.demo.simple.SimplePlayerActivity.RendererBuilderCallback;
|
||||
import com.google.android.exoplayer.source.DefaultSampleSource;
|
||||
import com.google.android.exoplayer.source.FrameworkSampleExtractor;
|
||||
|
||||
import android.media.MediaCodec;
|
||||
import android.net.Uri;
|
||||
|
||||
/**
|
||||
* A {@link RendererBuilder} for streams that can be read using
|
||||
* {@link android.media.MediaExtractor}.
|
||||
*/
|
||||
/* package */ class DefaultRendererBuilder implements RendererBuilder {
|
||||
|
||||
private final SimplePlayerActivity playerActivity;
|
||||
private final Uri uri;
|
||||
|
||||
public DefaultRendererBuilder(SimplePlayerActivity playerActivity, Uri uri) {
|
||||
this.playerActivity = playerActivity;
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildRenderers(RendererBuilderCallback callback) {
|
||||
// Build the video and audio renderers.
|
||||
DefaultSampleSource sampleSource =
|
||||
new DefaultSampleSource(new FrameworkSampleExtractor(playerActivity, uri, null), 2);
|
||||
MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(sampleSource,
|
||||
MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 0, playerActivity.getMainHandler(),
|
||||
playerActivity, 50);
|
||||
MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource);
|
||||
|
||||
// Invoke the callback.
|
||||
callback.onRenderers(videoRenderer, audioRenderer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 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.exoplayer.demo.simple;
|
||||
|
||||
import com.google.android.exoplayer.MediaCodecAudioTrackRenderer;
|
||||
import com.google.android.exoplayer.MediaCodecVideoTrackRenderer;
|
||||
import com.google.android.exoplayer.TrackRenderer;
|
||||
import com.google.android.exoplayer.demo.full.player.DemoPlayer;
|
||||
import com.google.android.exoplayer.demo.simple.SimplePlayerActivity.RendererBuilder;
|
||||
import com.google.android.exoplayer.demo.simple.SimplePlayerActivity.RendererBuilderCallback;
|
||||
import com.google.android.exoplayer.hls.HlsChunkSource;
|
||||
import com.google.android.exoplayer.hls.HlsPlaylist;
|
||||
import com.google.android.exoplayer.hls.HlsPlaylistParser;
|
||||
import com.google.android.exoplayer.hls.HlsSampleSource;
|
||||
import com.google.android.exoplayer.upstream.DataSource;
|
||||
import com.google.android.exoplayer.upstream.DefaultBandwidthMeter;
|
||||
import com.google.android.exoplayer.upstream.UriDataSource;
|
||||
import com.google.android.exoplayer.util.ManifestFetcher;
|
||||
import com.google.android.exoplayer.util.ManifestFetcher.ManifestCallback;
|
||||
|
||||
import android.media.MediaCodec;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A {@link RendererBuilder} for HLS.
|
||||
*/
|
||||
/* package */ class HlsRendererBuilder implements RendererBuilder,
|
||||
ManifestCallback<HlsPlaylist> {
|
||||
|
||||
private final SimplePlayerActivity playerActivity;
|
||||
private final String userAgent;
|
||||
private final String url;
|
||||
private final String contentId;
|
||||
|
||||
private RendererBuilderCallback callback;
|
||||
|
||||
public HlsRendererBuilder(SimplePlayerActivity playerActivity, String userAgent, String url,
|
||||
String contentId) {
|
||||
this.playerActivity = playerActivity;
|
||||
this.userAgent = userAgent;
|
||||
this.url = url;
|
||||
this.contentId = contentId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildRenderers(RendererBuilderCallback callback) {
|
||||
this.callback = callback;
|
||||
HlsPlaylistParser parser = new HlsPlaylistParser();
|
||||
ManifestFetcher<HlsPlaylist> playlistFetcher =
|
||||
new ManifestFetcher<HlsPlaylist>(parser, contentId, url, userAgent);
|
||||
playlistFetcher.singleLoad(playerActivity.getMainLooper(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onManifestError(String contentId, IOException e) {
|
||||
callback.onRenderersError(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onManifest(String contentId, HlsPlaylist manifest) {
|
||||
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
|
||||
|
||||
DataSource dataSource = new UriDataSource(userAgent, bandwidthMeter);
|
||||
HlsChunkSource chunkSource = new HlsChunkSource(dataSource, url, manifest, bandwidthMeter, null,
|
||||
HlsChunkSource.ADAPTIVE_MODE_SPLICE);
|
||||
HlsSampleSource sampleSource = new HlsSampleSource(chunkSource, true, 2);
|
||||
MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(sampleSource,
|
||||
MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 0, playerActivity.getMainHandler(),
|
||||
playerActivity, 50);
|
||||
MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource);
|
||||
|
||||
TrackRenderer[] renderers = new TrackRenderer[DemoPlayer.RENDERER_COUNT];
|
||||
renderers[DemoPlayer.TYPE_VIDEO] = videoRenderer;
|
||||
renderers[DemoPlayer.TYPE_AUDIO] = audioRenderer;
|
||||
callback.onRenderers(videoRenderer, audioRenderer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,291 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 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.exoplayer.demo.simple;
|
||||
|
||||
import com.google.android.exoplayer.ExoPlaybackException;
|
||||
import com.google.android.exoplayer.ExoPlayer;
|
||||
import com.google.android.exoplayer.MediaCodecAudioTrackRenderer;
|
||||
import com.google.android.exoplayer.MediaCodecTrackRenderer.DecoderInitializationException;
|
||||
import com.google.android.exoplayer.MediaCodecVideoTrackRenderer;
|
||||
import com.google.android.exoplayer.VideoSurfaceView;
|
||||
import com.google.android.exoplayer.demo.DemoUtil;
|
||||
import com.google.android.exoplayer.demo.R;
|
||||
import com.google.android.exoplayer.util.PlayerControl;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.media.MediaCodec.CryptoException;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.View;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.widget.MediaController;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* An activity that plays media using {@link ExoPlayer}.
|
||||
*/
|
||||
public class SimplePlayerActivity extends Activity implements SurfaceHolder.Callback,
|
||||
ExoPlayer.Listener, MediaCodecVideoTrackRenderer.EventListener {
|
||||
|
||||
/**
|
||||
* Builds renderers for the player.
|
||||
*/
|
||||
public interface RendererBuilder {
|
||||
|
||||
void buildRenderers(RendererBuilderCallback callback);
|
||||
|
||||
}
|
||||
|
||||
public static final int RENDERER_COUNT = 2;
|
||||
public static final int TYPE_VIDEO = 0;
|
||||
public static final int TYPE_AUDIO = 1;
|
||||
|
||||
private static final String TAG = "PlayerActivity";
|
||||
|
||||
private MediaController mediaController;
|
||||
private Handler mainHandler;
|
||||
private View shutterView;
|
||||
private VideoSurfaceView surfaceView;
|
||||
|
||||
private ExoPlayer player;
|
||||
private RendererBuilder builder;
|
||||
private RendererBuilderCallback callback;
|
||||
private MediaCodecVideoTrackRenderer videoRenderer;
|
||||
|
||||
private boolean autoPlay = true;
|
||||
private long playerPosition;
|
||||
|
||||
private Uri contentUri;
|
||||
private int contentType;
|
||||
private String contentId;
|
||||
|
||||
// Activity lifecycle
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Intent intent = getIntent();
|
||||
contentUri = intent.getData();
|
||||
contentType = intent.getIntExtra(DemoUtil.CONTENT_TYPE_EXTRA, DemoUtil.TYPE_OTHER);
|
||||
contentId = intent.getStringExtra(DemoUtil.CONTENT_ID_EXTRA);
|
||||
|
||||
mainHandler = new Handler(getMainLooper());
|
||||
builder = getRendererBuilder();
|
||||
|
||||
setContentView(R.layout.player_activity_simple);
|
||||
View root = findViewById(R.id.root);
|
||||
root.setOnTouchListener(new OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View arg0, MotionEvent arg1) {
|
||||
if (arg1.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
toggleControlsVisibility();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
mediaController = new MediaController(this);
|
||||
mediaController.setAnchorView(root);
|
||||
shutterView = findViewById(R.id.shutter);
|
||||
surfaceView = (VideoSurfaceView) findViewById(R.id.surface_view);
|
||||
surfaceView.getHolder().addCallback(this);
|
||||
|
||||
DemoUtil.setDefaultCookieManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
// Setup the player
|
||||
player = ExoPlayer.Factory.newInstance(RENDERER_COUNT, 1000, 5000);
|
||||
player.addListener(this);
|
||||
player.seekTo(playerPosition);
|
||||
// Build the player controls
|
||||
mediaController.setMediaPlayer(new PlayerControl(player));
|
||||
mediaController.setEnabled(true);
|
||||
// Request the renderers
|
||||
callback = new RendererBuilderCallback();
|
||||
builder.buildRenderers(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
// Release the player
|
||||
if (player != null) {
|
||||
playerPosition = player.getCurrentPosition();
|
||||
player.release();
|
||||
player = null;
|
||||
}
|
||||
callback = null;
|
||||
videoRenderer = null;
|
||||
shutterView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
// Public methods
|
||||
|
||||
public Handler getMainHandler() {
|
||||
return mainHandler;
|
||||
}
|
||||
|
||||
// Internal methods
|
||||
|
||||
private void toggleControlsVisibility() {
|
||||
if (mediaController.isShowing()) {
|
||||
mediaController.hide();
|
||||
} else {
|
||||
mediaController.show(0);
|
||||
}
|
||||
}
|
||||
|
||||
private RendererBuilder getRendererBuilder() {
|
||||
String userAgent = DemoUtil.getUserAgent(this);
|
||||
switch (contentType) {
|
||||
case DemoUtil.TYPE_SS:
|
||||
return new SmoothStreamingRendererBuilder(this, userAgent, contentUri.toString(),
|
||||
contentId);
|
||||
case DemoUtil.TYPE_DASH:
|
||||
return new DashRendererBuilder(this, userAgent, contentUri.toString(), contentId);
|
||||
case DemoUtil.TYPE_HLS:
|
||||
return new HlsRendererBuilder(this, userAgent, contentUri.toString(), contentId);
|
||||
default:
|
||||
return new DefaultRendererBuilder(this, contentUri);
|
||||
}
|
||||
}
|
||||
|
||||
private void onRenderers(RendererBuilderCallback callback,
|
||||
MediaCodecVideoTrackRenderer videoRenderer, MediaCodecAudioTrackRenderer audioRenderer) {
|
||||
if (this.callback != callback) {
|
||||
return;
|
||||
}
|
||||
this.callback = null;
|
||||
this.videoRenderer = videoRenderer;
|
||||
player.prepare(videoRenderer, audioRenderer);
|
||||
maybeStartPlayback();
|
||||
}
|
||||
|
||||
private void maybeStartPlayback() {
|
||||
Surface surface = surfaceView.getHolder().getSurface();
|
||||
if (videoRenderer == null || surface == null || !surface.isValid()) {
|
||||
// We're not ready yet.
|
||||
return;
|
||||
}
|
||||
player.sendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, surface);
|
||||
if (autoPlay) {
|
||||
player.setPlayWhenReady(true);
|
||||
autoPlay = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void onRenderersError(RendererBuilderCallback callback, Exception e) {
|
||||
if (this.callback != callback) {
|
||||
return;
|
||||
}
|
||||
this.callback = null;
|
||||
onError(e);
|
||||
}
|
||||
|
||||
private void onError(Exception e) {
|
||||
Log.e(TAG, "Playback failed", e);
|
||||
Toast.makeText(this, R.string.failed, Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
|
||||
// ExoPlayer.Listener implementation
|
||||
|
||||
@Override
|
||||
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayWhenReadyCommitted() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerError(ExoPlaybackException e) {
|
||||
onError(e);
|
||||
}
|
||||
|
||||
// MediaCodecVideoTrackRenderer.Listener
|
||||
|
||||
@Override
|
||||
public void onVideoSizeChanged(int width, int height, float pixelWidthHeightRatio) {
|
||||
surfaceView.setVideoWidthHeightRatio(
|
||||
height == 0 ? 1 : (pixelWidthHeightRatio * width) / height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawnToSurface(Surface surface) {
|
||||
shutterView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDroppedFrames(int count, long elapsed) {
|
||||
Log.d(TAG, "Dropped frames: " + count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDecoderInitializationError(DecoderInitializationException e) {
|
||||
// This is for informational purposes only. Do nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCryptoError(CryptoException e) {
|
||||
// This is for informational purposes only. Do nothing.
|
||||
}
|
||||
|
||||
// SurfaceHolder.Callback implementation
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
maybeStartPlayback();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
if (videoRenderer != null) {
|
||||
player.blockingSendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, null);
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ final class RendererBuilderCallback {
|
||||
|
||||
public void onRenderers(MediaCodecVideoTrackRenderer videoRenderer,
|
||||
MediaCodecAudioTrackRenderer audioRenderer) {
|
||||
SimplePlayerActivity.this.onRenderers(this, videoRenderer, audioRenderer);
|
||||
}
|
||||
|
||||
public void onRenderersError(Exception e) {
|
||||
SimplePlayerActivity.this.onRenderersError(this, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2014 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.exoplayer.demo.simple;
|
||||
|
||||
import com.google.android.exoplayer.DefaultLoadControl;
|
||||
import com.google.android.exoplayer.LoadControl;
|
||||
import com.google.android.exoplayer.MediaCodecAudioTrackRenderer;
|
||||
import com.google.android.exoplayer.MediaCodecUtil;
|
||||
import com.google.android.exoplayer.MediaCodecUtil.DecoderQueryException;
|
||||
import com.google.android.exoplayer.MediaCodecVideoTrackRenderer;
|
||||
import com.google.android.exoplayer.SampleSource;
|
||||
import com.google.android.exoplayer.chunk.ChunkSampleSource;
|
||||
import com.google.android.exoplayer.chunk.ChunkSource;
|
||||
import com.google.android.exoplayer.chunk.FormatEvaluator;
|
||||
import com.google.android.exoplayer.chunk.FormatEvaluator.AdaptiveEvaluator;
|
||||
import com.google.android.exoplayer.demo.simple.SimplePlayerActivity.RendererBuilder;
|
||||
import com.google.android.exoplayer.demo.simple.SimplePlayerActivity.RendererBuilderCallback;
|
||||
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingChunkSource;
|
||||
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifest;
|
||||
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifest.StreamElement;
|
||||
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifest.TrackElement;
|
||||
import com.google.android.exoplayer.smoothstreaming.SmoothStreamingManifestParser;
|
||||
import com.google.android.exoplayer.upstream.BufferPool;
|
||||
import com.google.android.exoplayer.upstream.DataSource;
|
||||
import com.google.android.exoplayer.upstream.DefaultBandwidthMeter;
|
||||
import com.google.android.exoplayer.upstream.UriDataSource;
|
||||
import com.google.android.exoplayer.util.ManifestFetcher;
|
||||
import com.google.android.exoplayer.util.ManifestFetcher.ManifestCallback;
|
||||
import com.google.android.exoplayer.util.Util;
|
||||
|
||||
import android.media.MediaCodec;
|
||||
import android.os.Handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A {@link RendererBuilder} for SmoothStreaming.
|
||||
*/
|
||||
/* package */ class SmoothStreamingRendererBuilder implements RendererBuilder,
|
||||
ManifestCallback<SmoothStreamingManifest> {
|
||||
|
||||
private static final int BUFFER_SEGMENT_SIZE = 64 * 1024;
|
||||
private static final int VIDEO_BUFFER_SEGMENTS = 200;
|
||||
private static final int AUDIO_BUFFER_SEGMENTS = 60;
|
||||
private static final int LIVE_EDGE_LATENCY_MS = 30000;
|
||||
|
||||
private final SimplePlayerActivity playerActivity;
|
||||
private final String userAgent;
|
||||
private final String url;
|
||||
private final String contentId;
|
||||
|
||||
private RendererBuilderCallback callback;
|
||||
private ManifestFetcher<SmoothStreamingManifest> manifestFetcher;
|
||||
|
||||
public SmoothStreamingRendererBuilder(SimplePlayerActivity playerActivity, String userAgent,
|
||||
String url, String contentId) {
|
||||
this.playerActivity = playerActivity;
|
||||
this.userAgent = userAgent;
|
||||
this.url = url;
|
||||
this.contentId = contentId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildRenderers(RendererBuilderCallback callback) {
|
||||
this.callback = callback;
|
||||
SmoothStreamingManifestParser parser = new SmoothStreamingManifestParser();
|
||||
manifestFetcher = new ManifestFetcher<SmoothStreamingManifest>(parser, contentId,
|
||||
url + "/Manifest", userAgent);
|
||||
manifestFetcher.singleLoad(playerActivity.getMainLooper(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onManifestError(String contentId, IOException e) {
|
||||
callback.onRenderersError(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onManifest(String contentId, SmoothStreamingManifest manifest) {
|
||||
Handler mainHandler = playerActivity.getMainHandler();
|
||||
LoadControl loadControl = new DefaultLoadControl(new BufferPool(BUFFER_SEGMENT_SIZE));
|
||||
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
|
||||
|
||||
// Obtain stream elements for playback.
|
||||
int maxDecodableFrameSize;
|
||||
try {
|
||||
maxDecodableFrameSize = MediaCodecUtil.maxH264DecodableFrameSize();
|
||||
} catch (DecoderQueryException e) {
|
||||
callback.onRenderersError(e);
|
||||
return;
|
||||
}
|
||||
int audioStreamElementIndex = -1;
|
||||
int videoStreamElementIndex = -1;
|
||||
ArrayList<Integer> videoTrackIndexList = new ArrayList<Integer>();
|
||||
for (int i = 0; i < manifest.streamElements.length; i++) {
|
||||
if (audioStreamElementIndex == -1
|
||||
&& manifest.streamElements[i].type == StreamElement.TYPE_AUDIO) {
|
||||
audioStreamElementIndex = i;
|
||||
} else if (videoStreamElementIndex == -1
|
||||
&& manifest.streamElements[i].type == StreamElement.TYPE_VIDEO) {
|
||||
videoStreamElementIndex = i;
|
||||
StreamElement streamElement = manifest.streamElements[i];
|
||||
for (int j = 0; j < streamElement.tracks.length; j++) {
|
||||
TrackElement trackElement = streamElement.tracks[j];
|
||||
if (trackElement.maxWidth * trackElement.maxHeight <= maxDecodableFrameSize) {
|
||||
videoTrackIndexList.add(j);
|
||||
} else {
|
||||
// The device isn't capable of playing this stream.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int[] videoTrackIndices = Util.toArray(videoTrackIndexList);
|
||||
|
||||
// Build the video renderer.
|
||||
DataSource videoDataSource = new UriDataSource(userAgent, bandwidthMeter);
|
||||
ChunkSource videoChunkSource = new SmoothStreamingChunkSource(manifestFetcher,
|
||||
videoStreamElementIndex, videoTrackIndices, videoDataSource,
|
||||
new AdaptiveEvaluator(bandwidthMeter), LIVE_EDGE_LATENCY_MS);
|
||||
ChunkSampleSource videoSampleSource = new ChunkSampleSource(videoChunkSource, loadControl,
|
||||
VIDEO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true);
|
||||
MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(videoSampleSource,
|
||||
MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 0, mainHandler, playerActivity, 50);
|
||||
|
||||
// Build the audio renderer.
|
||||
DataSource audioDataSource = new UriDataSource(userAgent, bandwidthMeter);
|
||||
ChunkSource audioChunkSource = new SmoothStreamingChunkSource(manifestFetcher,
|
||||
audioStreamElementIndex, new int[] {0}, audioDataSource,
|
||||
new FormatEvaluator.FixedEvaluator(), LIVE_EDGE_LATENCY_MS);
|
||||
SampleSource audioSampleSource = new ChunkSampleSource(audioChunkSource, loadControl,
|
||||
AUDIO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true);
|
||||
MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(
|
||||
audioSampleSource);
|
||||
callback.onRenderers(videoRenderer, audioRenderer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright (C) 2014 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.
|
||||
-->
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:keepScreenOn="true">
|
||||
|
||||
<com.google.android.exoplayer.VideoSurfaceView android:id="@+id/surface_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"/>
|
||||
|
||||
<View android:id="@+id/shutter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black"/>
|
||||
|
||||
</FrameLayout>
|
||||
Loading…
Reference in a new issue