I write an android application for streaming video in MPEG-DASH protocol..
I'm using Exoplayer and for now I test on the demo
I read some questions on stackoverflow and issues on exoplayer and write this code for cache a video
in DashRendererBuilder(in demo):
Cache cache = new SimpleCache(context.getCacheDir(), new LeastRecentlyUsedCacheEvictor(1024 * 1024 * 10));
// Build the video renderer.
DataSource videoDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
CacheDataSource videoCacheDataSource= new CacheDataSource(cache, videoDataSource, false, false);
ChunkSource videoChunkSource= new DashChunkSource(manifestFetcher,
DefaultDashTrackSelector.newVideoInstance(context, true, filterHdContent),
videoCacheDataSource, new AdaptiveEvaluator(bandwidthMeter), LIVE_EDGE_LATENCY_MS,
elapsedRealtimeOffset, mainHandler, player);//*/
ChunkSampleSource videoSampleSource = new ChunkSampleSource(videoChunkSource, loadControl,
VIDEO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, mainHandler, player,
DemoPlayer.TYPE_VIDEO);
TrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(context, videoSampleSource,
MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 5000, drmSessionManager, true,
mainHandler, player, 50);
//cache audio
Cache cache2 = new SimpleCache(context.getCacheDir(), new LeastRecentlyUsedCacheEvictor(1024 * 1024 * 4));
// Build the audio renderer.
DataSource audioDataSource = new DefaultUriDataSource(context, bandwidthMeter, userAgent);
CacheDataSource audioCacheDataSource= new CacheDataSource(cache2, audioDataSource, false, false);
ChunkSource audioChunkSource = new DashChunkSource(manifestFetcher,
DefaultDashTrackSelector.newAudioInstance(), audioCacheDataSource, null, LIVE_EDGE_LATENCY_MS,
elapsedRealtimeOffset, mainHandler, player);
ChunkSampleSource audioSampleSource = new ChunkSampleSource(audioChunkSource, loadControl,
AUDIO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, mainHandler, player,
DemoPlayer.TYPE_AUDIO);
TrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(audioSampleSource,
drmSessionManager, true, mainHandler, player, AudioCapabilities.getCapabilities(context));
the problem is when I seek forward on the cached data it works well. but seems when I seek backward on the played data, data is lose and download vide again.
how I can fix this? for example I want to cache the last two minute or cache all the played data same as how youtube works when it uses html5.
Related
I am trying to play the encrypted video using .m3u8 file. I stored my video in AWS and created the .ts files and a master playlist. Aws provided me some keys for that encrypted video file. Now I have to use those keys in exoplayer. I have tried to use Aes128DataSource and DrmSessionManager but no luck.
The key types are:
Encryption Key: ####################################################################
Encryption Key MD5: ################
Encryption Initialization Vector : #############
Bellow the code I am using to play the hls video. Its plays the video smoothly without any problem. I just need to know where and how to use the keys to play the encrypted video.
String VIDEO_URL = "https://s3.amazonaws.com/######.###.##/videos/mobiletest/mobilemaster.m3u8";
//Create a default TrackSelector
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
// Create a default LoadControl
LoadControl loadControl = new DefaultLoadControl();
//Bis. Create a RenderFactory
RenderersFactory renderersFactory = new DefaultRenderersFactory(this);
//Create the player
player = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector, loadControl);
simpleExoPlayerView = new SimpleExoPlayerView(this);
simpleExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.player_view);
//Set media controller
simpleExoPlayerView.setUseController(true);
simpleExoPlayerView.requestFocus();
// Bind the player to the view.
simpleExoPlayerView.setPlayer(player);
// Set the media source
Uri mp4VideoUri = Uri.parse(VIDEO_URL);
//Measures bandwidth during playback. Can be null if not required.
DefaultBandwidthMeter bandwidthMeterA = new DefaultBandwidthMeter();
//Produces DataSource instances through which media data is loaded.
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "PiwikVideoApp"), bandwidthMeterA);
//Produces Extractor instances for parsing the media data.
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
//FOR LIVE STREAM LINK:
MediaSource videoSource = new HlsMediaSource(mp4VideoUri, dataSourceFactory, 1, null, null);
final MediaSource mediaSource = videoSource;
player.prepare(videoSource);
I have encrypted the video using AWS Elastic Transcoder, and using exoplayer version: 2.6.0
I have found a solution. The trick you need to do is to create your own custom data sources. You need to create a class that extends HttpDataSource.BaseFactory and add some code from DefaultHttpDataSourceFactory. I know it sounds crazy, but I have solved it this way. Don't worry, I am pasting here the whole code of that custom class.
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.upstream.TransferListener;
public class CustomDataSourcesFactory extends HttpDataSource.BaseFactory{
private final String userAgent;
private final #Nullable
TransferListener listener;
private final int connectTimeoutMillis;
private final int readTimeoutMillis;
private final boolean allowCrossProtocolRedirects;
/**
* Constructs a DefaultHttpDataSourceFactory. Sets {#link
* DefaultHttpDataSource#DEFAULT_CONNECT_TIMEOUT_MILLIS} as the connection timeout, {#link
* DefaultHttpDataSource#DEFAULT_READ_TIMEOUT_MILLIS} as the read timeout and disables
* cross-protocol redirects.
*
* #param userAgent The User-Agent string that should be used.
*/
public CustomDataSourcesFactory(String userAgent) {
this(userAgent, null);
}
/**
* Constructs a DefaultHttpDataSourceFactory. Sets {#link
* DefaultHttpDataSource#DEFAULT_CONNECT_TIMEOUT_MILLIS} as the connection timeout, {#link
* DefaultHttpDataSource#DEFAULT_READ_TIMEOUT_MILLIS} as the read timeout and disables
* cross-protocol redirects.
*
* #param userAgent The User-Agent string that should be used.
* #param listener An optional listener.
*/
public CustomDataSourcesFactory(String userAgent, #Nullable TransferListener listener) {
this(userAgent, listener, DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, false);
}
/**
* #param userAgent The User-Agent string that should be used.
* #param connectTimeoutMillis The connection timeout that should be used when requesting remote
* data, in milliseconds. A timeout of zero is interpreted as an infinite timeout.
* #param readTimeoutMillis The read timeout that should be used when requesting remote data, in
* milliseconds. A timeout of zero is interpreted as an infinite timeout.
* #param allowCrossProtocolRedirects Whether cross-protocol redirects (i.e. redirects from HTTP
* to HTTPS and vice versa) are enabled.
*/
public CustomDataSourcesFactory(
String userAgent,
int connectTimeoutMillis,
int readTimeoutMillis,
boolean allowCrossProtocolRedirects) {
this(
userAgent,
/* listener= */ null,
connectTimeoutMillis,
readTimeoutMillis,
allowCrossProtocolRedirects);
}
/**
* #param userAgent The User-Agent string that should be used.
* #param listener An optional listener.
* #param connectTimeoutMillis The connection timeout that should be used when requesting remote
* data, in milliseconds. A timeout of zero is interpreted as an infinite timeout.
* #param readTimeoutMillis The read timeout that should be used when requesting remote data, in
* milliseconds. A timeout of zero is interpreted as an infinite timeout.
* #param allowCrossProtocolRedirects Whether cross-protocol redirects (i.e. redirects from HTTP
* to HTTPS and vice versa) are enabled.
*/
public CustomDataSourcesFactory(
String userAgent,
#Nullable TransferListener listener,
int connectTimeoutMillis,
int readTimeoutMillis,
boolean allowCrossProtocolRedirects) {
this.userAgent = userAgent;
this.listener = listener;
this.connectTimeoutMillis = connectTimeoutMillis;
this.readTimeoutMillis = readTimeoutMillis;
this.allowCrossProtocolRedirects = allowCrossProtocolRedirects;
}
#Override
protected HttpDataSource createDataSourceInternal(
HttpDataSource.RequestProperties defaultRequestProperties) {
DefaultHttpDataSource defaultHttpDataSource = new DefaultHttpDataSource(userAgent, null, listener, connectTimeoutMillis,
readTimeoutMillis, allowCrossProtocolRedirects, defaultRequestProperties);
defaultHttpDataSource.setRequestProperty("your header", "your token");
return defaultHttpDataSource;
}}
Do you see the method createDataSourceInternal? I am returning a DefaultHttpDataSource object initialised with a header key and a token defaultHttpDataSource.setRequestProperty("your header", "your token");. So now your exoplayer will hit the accusation URL with this header key and token value which will be checked by your server side in order to verify the valid request. Your hls playlist(.m3u8) contains the accusation URL. Exoplayer uses this URL automatically. All you need to do is to tell the player to use the validation keys.
So again here is the usage code of Your custom data sources:
//ExoPlayer implementation
//Create a default TrackSelector
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
// Create a default LoadControl
LoadControl loadControl = new DefaultLoadControl();
//Bis. Create a RenderFactory
RenderersFactory renderersFactory = new DefaultRenderersFactory(this);
//Create the player
player = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector, loadControl);
simpleExoPlayerView = new SimpleExoPlayerView(this);
simpleExoPlayerView = (SimpleExoPlayerView) findViewById(R.id.player_view);
//Set media controller
simpleExoPlayerView.setUseController(true);
simpleExoPlayerView.requestFocus();
// Bind the player to the view.
simpleExoPlayerView.setPlayer(player);
// Set the media source
Uri mp4VideoUri = Uri.parse(VIDEO_URL);
//DefaultHttpDataSource source = new DefaultHttpDataSource(Util.getUserAgent(this, "appAgent"), null);
//source.setRequestProperty("header", "user token");
//Measures bandwidth during playback. Can be null if not required.
DefaultBandwidthMeter bandwidthMeterA = new DefaultBandwidthMeter();
//DefaultDataSourceFactory o = new DefaultDataSourceFactory(this, null, new DefaultHttpDataSourceFactory(Util.getUserAgent(this, "appAgent"), bandwidthMeterA));
CustomDataSourcesFactory o = new CustomDataSourcesFactory("Exoplayer");
//Produces DataSource instances through which media data is loaded.
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "PiwikVideoApp"), bandwidthMeterA);
//Produces Extractor instances for parsing the media data.
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
//FOR LIVE STREAM LINK:
MediaSource videoSource = new HlsMediaSource(mp4VideoUri, o, 1, null, null);
final MediaSource mediaSource = videoSource;
player.prepare(videoSource);
This problem was too much critical for me because I could not found any tutorial, resources or idea to solve this. I am writing this because I don't want other noob people like me to suffer from this.
If you are not clear enough, feel free to ask here. I will assist you further. I have also the server side code in order to generate the decryption key from AWS encrypted key.
I'm trying to caching HLS and DASH streaming video,
I have tried many solution but not working with Exoplayer v2.2
many issue redirect to below links but not getting any proper solution.
https://github.com/google/ExoPlayer/issues/420 and Using cache in ExoPlayer.
In the one solution 'ExtractorSampleSource' class is not found in Google Exoplayer 2.2
OkHttpClient okHttpClient = new OkHttpClient.Builder().cache(new okhttp3.Cache(context.getCacheDir(), 1024000)).build();
OkHttpDataSource okHttpDataSource = new OkHttpDataSource(okHttpClient, "android", null);
OkHttpDataSource ok2 = new OkHttpDataSource(okHttpClient, "android", null);
HttpDataSource dataSource = new CacheDataSource(context, okHttpDataSource, ok2);
ExtractorSampleSource sampleSource = new ExtractorSampleSource(
uri,
dataSource,
allocator,
buffer_segment_count * buffer_segment_size,
new Mp4Extractor(), new Mp3Extractor());
In other solution got same error 'DefaultUriDataSource' class not found in v2.2
DataSource dataSource = new DefaultUriDataSource(context, null, new OkHttpDataSource(getClient(context), userAgent, null, null/*, CacheControl.FORCE_CACHE*/));
all the solutions are 1 to 2 year older and it's not supported latest version of Google Exoplayer v2.2.
any one have idea or any sample or any solution to do caching with HLS and DASH stream?
Used below buildDataSourceFactory and its storing the cache
DataSource.Factory buildDataSourceFactory(boolean cache) {
if (!cache) {
return new DefaultDataSourceFactory(context, BANDWIDTH_METER,
buildHttpDataSourceFactory(BANDWIDTH_METER));
}else{
return new DataSource.Factory() {
#Override
public DataSource createDataSource() {
LeastRecentlyUsedCacheEvictor evictor = new LeastRecentlyUsedCacheEvictor(100 * 1024 * 1024);
SimpleCache simpleCache = new SimpleCache(new File(context.getCacheDir(), "media_cache"), evictor);
return new CacheDataSource(simpleCache, buildCachedHttpDataSourceFactory(BANDWIDTH_METER).createDataSource(),
new FileDataSource(), new CacheDataSink(simpleCache, 10 * 1024 * 1024),
CacheDataSource.FLAG_BLOCK_ON_CACHE | CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR, null);
}
};
}
}
private DefaultDataSource.Factory buildCachedHttpDataSourceFactory(DefaultBandwidthMeter bandwidthMeter) {
return new DefaultDataSourceFactory(context, bandwidthMeter, buildHttpDataSourceFactory(bandwidthMeter));
}
I started using ExoPlayer to stream some audio. All was well until I came across an URL that has a "301 Moved Permanently" redirect. ExoPlayer2 does not handle that by default.
I've already seen this thread: https://github.com/google/ExoPlayer/issues/423
There they say to add the new "allowCrossDomainRedirects" flag to either a HttpDataSource or UriDataSource. The problem is that I don't use either of those classes:
//I am NOT using SimpleExoPlayer because I need a different renderer.
exoPlayer = ExoPlayerFactory.newInstance(renderers, trackSelector, loadControl);
final DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(
context,
Util.getUserAgent(context, applicationInfo.getAppName())
);
// Produces Extractor instances for parsing the media data.
final ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
// This is the MediaSource representing the media to be played.
MediaSource mediaSource = new ExtractorMediaSource(
Uri.parse(media.getUriString()) /* uri */,
dataSourceFactory,
extractorsFactory,
10,
null /* eventHandler */,
null /* eventListener */);
exoPlayer.prepare(mediaSource);
See how the ExtractorMediaSource requires a dataSourceFactory instead of a DataSource. In fact I can't even find the classes HttpDataSource and UriDataSource on ExoPlayer2. Looks like they have been removed.
Therefore I can't find a way to add the flag mentioned on the post. Can somebody help me?
The problem described in the issue is about cross-protocol redirects (from http to https or vice versa). Exoplayer supports this, but you have to set allowCrossProtocolRedirects to true. Regular redirects (including 301 redirects) are supported by default. The redirect you're receiving is most likely a cross-protocol redirect.
To create the data source you're calling:
DefaultDataSourceFactory(Context context, String userAgent)
This constructor creates a DefaultHttpDataSourceFactory which has allowCrossProtocolRedirects set to false.
To change this, you need to call:
DefaultDataSourceFactory(Context context, TransferListener<? super DataSource> listener,
DataSource.Factory baseDataSourceFactory)
And use your own DefaultHttpDataSourceFactory with allowCrossProtocolRedirects set to true as the baseDataSourceFactory.
For example:
String userAgent = Util.getUserAgent(context, applicationInfo.getAppName());
// Default parameters, except allowCrossProtocolRedirects is true
DefaultHttpDataSourceFactory httpDataSourceFactory = new DefaultHttpDataSourceFactory(
userAgent,
null /* listener */,
DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS,
true /* allowCrossProtocolRedirects */
);
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(
context,
null /* listener */,
httpDataSourceFactory
);
If you need to do this more often you can also create a helper method:
public static DefaultDataSourceFactory createDataSourceFactory(Context context,
String userAgent, TransferListener<? super DataSource> listener) {
// Default parameters, except allowCrossProtocolRedirects is true
DefaultHttpDataSourceFactory httpDataSourceFactory = new DefaultHttpDataSourceFactory(
userAgent,
listener,
DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS,
true /* allowCrossProtocolRedirects */
);
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(
context,
listener,
httpDataSourceFactory
);
return dataSourceFactory;
}
This will allow cross-protocol redirects.
Sidenote: "301 Moved Permanently" means clients need to update their URL to the new one. "302 Found" is used for regular redirects. If possible, update the URLs that return "301 Moved Permanently".
it works
val httpDataSourceFactory = DefaultHttpDataSourceFactory(Util.getUserAgent(context, "Player"),null,DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS,
true)
val dataSourceFactory: DataSource.Factory = DefaultDataSourceFactory(context, null, httpDataSourceFactory)
try this:
// Build a HttpDataSource.Factory with cross-protocol redirects enabled.
HttpDataSource.Factory httpDataSourceFactory =
new DefaultHttpDataSource.Factory().setAllowCrossProtocolRedirects(true);
// Wrap the HttpDataSource.Factory in a DefaultDataSource.Factory, which adds in
// support for requesting data from other sources (e.g., files, resources, etc).
DefaultDataSource.Factory dataSourceFactory =
new DefaultDataSource.Factory(context, httpDataSourceFactory);
// Inject the DefaultDataSourceFactory when creating the player.
ExoPlayer player =
new ExoPlayer.Builder(context)
.setMediaSourceFactory(new DefaultMediaSourceFactory(dataSourceFactory))
.build();
It works for me.
The accepted answer looks a little bit outdated , because DefaultHttpDataSource class is deprecated and we suppose to replace it with DefaultHttpDataSource.Factory , see the official documentation.
So instead of
DefaultHttpDataSourceFactory httpDataSourceFactory = new DefaultHttpDataSourceFactory(
userAgent,
null /* listener */,
DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS,
DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS,
true /* allowCrossProtocolRedirects */
);
we could have
final DefaultHttpDataSource.Factory defaultDataSourceFactory = new DefaultHttpDataSource
.Factory()
.setUserAgent(userAgent)
.setTransferListener(listener)
.setConnectTimeoutMs(DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS)
.setReadTimeoutMs(DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS)
.setAllowCrossProtocolRedirects(true);
Also don't forget to use if you have to
final DefaultHttpDataSource defaultDataSource = defaultDataSourceFactory.createDataSource();
And finally guess what : DefaultDataSourceFactory is also deprecated and we should use DefaultDataSource.Factory instead.
In a video player project, I'd like to use LibVLC http streaming from a slow source.
However, I can not get it to stream FIRST, and then continuously download data. The player will always stop in-between.
I'm using vlc-android from GIT.
This is the media player setup code:
ArrayList<String> options = new ArrayList<>();
options.add("--no-sub-autodetect-file");
options.add("--swscale-mode=0");
options.add("--network-caching=60000");
if (BuildConfig.DEBUG) {
options.add("-vvv"); // verbosity
}
libVLC = new LibVLC(options);
mediaPlayer = new org.videolan.libvlc.MediaPlayer(libVLC);
mediaPlayer.setEventListener(this);
final IVLCVout vout = mediaPlayer.getVLCVout();
vout.setVideoView(videoView);
vout.setSubtitlesView(subtitleView);
vout.addCallback(this);
vout.attachViews();
final Media media = new Media(libVLC, getIntent().getData());
media.setHWDecoderEnabled(true, false);
media.addOption(":network-caching=60000");
media.addOption(":clock-jitter=0");
media.addOption(":clock-synchro=0");
mediaPlayer.setMedia(media);
mediaPlayer.play();
I was hoping that setting the :network-caching on the media object is enough, but it seems to still run out of data the whole time.
How to configure LibVLC so that the stutter is eliminated? Some buffer time is OK.
The stream type is a MOV file served via HTTP.
libvlc option try it:
ArrayList<String> options = new ArrayList<String>();
options.add("--audio-time-stretch"); // time stretching
options.add("-vvv"); // verbosity
options.add("--no-audio"); // no audio
options.add("--aout=none");
options.add("--no-sub-autodetect-file");
options.add("--swscale-mode=0");
options.add("--network-caching=400");
options.add("--no-drop-late-frames");
options.add("--no-skip-frames");
options.add("--avcodec-skip-frame");
options.add("--avcodec-hw=any");
media addOption try it:
Media m = new Media(libvlc, Uri.parse(URL));
m.setHWDecoderEnabled(true, true);
m.addOption(":network-caching=5000");
m.addOption(":clock-jitter=0");
m.addOption(":clock-synchro=0");
m.addOption(":codec=all");
mMediaPlayer.setMedia(m);
mMediaPlayer.play();
There is no mention on the internet what on earth is a userAgent, what do I pass as its value and what is it used for. No documentation, nothing.
Also, how do I obtain "videoRepresentations" and what is it?
// Build the video renderer.
DataSource videoDataSource = new HttpDataSource(userAgent, HttpDataSource.REJECT_PAYWALL_TYPES, bandwidthMeter);
ChunkSource videoChunkSource = new DashChunkSource(videoDataSource, new AdaptiveEvaluator(bandwidthMeter), videoRepresentations);
ChunkSampleSource videoSampleSource = new ChunkSampleSource(videoChunkSource, loadControl, VIDEO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true);
MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(videoSampleSource, null, true, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 0, mainHandler, playerActivity, 50);
// Build the audio renderer.
DataSource audioDataSource = new HttpDataSource(userAgent, HttpDataSource.REJECT_PAYWALL_TYPES, bandwidthMeter);
ChunkSource audioChunkSource = new DashChunkSource(audioDataSource, new FormatEvaluator.FixedEvaluator(), audioRepresentation);
SampleSource audioSampleSource = new ChunkSampleSource(audioChunkSource, loadControl, AUDIO_BUFFER_SEGMENTS * BUFFER_SEGMENT_SIZE, true);
MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(audioSampleSource, null, true);
Documentation is extremely insufficient
http://developer.android.com/guide/topics/media/exoplayer.html
userAgent
private RendererBuilder getRendererBuilder() {
String userAgent = DemoUtil.getUserAgent(this);
switch (contentType) {
case DemoUtil.TYPE_SS:
return new SmoothStreamingRendererBuilder(userAgent, contentUri.toString(), contentId,
new SmoothStreamingTestMediaDrmCallback(), debugTextView);
case DemoUtil.TYPE_DASH:
return new DashRendererBuilder(userAgent, contentUri.toString(), contentId,
new WidevineTestMediaDrmCallback(contentId), debugTextView);
default:
return new DefaultRendererBuilder(this, contentUri, debugTextView);
}
}
Above code from below link where whole code available with project you just download and use it.
https://raw.githubusercontent.com/google/ExoPlayer/master/demo/src/main/java/com/google/android/exoplayer/demo/full/FullPlayerActivity.java
https://raw.githubusercontent.com/google/ExoPlayer/master/demo/src/main/java/com/google/android/exoplayer/demo/simple/SimplePlayerActivity.java