I'm using exoplayer 2, and have Repeat mode on, meaning it will keep playing the video once it reaches the end. However, after the video ends and plays again, it keeps rebuffering (reloading the video). How do I prevent this from happening?
player = new SimpleExoPlayer.Builder(mContext).build();
player.setPlayWhenReady(false);
player.setRepeatMode(Player.REPEAT_MODE_ONE);
Edit1:
Have tried using LoopingMediaSource, not sure if I am doing it correctly though?
Because it still rebuffers when it automatically replays the video.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(mContext,
Util.getUserAgent(mContext, "yourApplicationName"));
Uri uri = Uri.parse(mUrl);
MediaSource videoSource =
new ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(uri);
LoopingMediaSource loopingMediaSource = new LoopingMediaSource(videoSource);
player.prepare(loopingMediaSource);
When it comes to video buffering this is inevitable, as only a portion of the video is kept in memory.
What you can try is to adjust the buffering duration by setting a custom load control. Tune the setBufferDurationsMs parameters to achieve your expected results.
final DefaultTrackSelector trackSelector = new DefaultTrackSelector(context);
final DefaultLoadControl loadControl = new DefaultLoadControl
.Builder()
.setBufferDurationsMs(25000, 50000, 1500, 2000)
.build();
player = new SimpleExoPlayer
.Builder(context)
.setTrackSelector(trackSelector)
.setLoadControl(loadControl)
.build();
If by adjusting the parameters in setBufferDurationMs you can't still get the desired results, then you may need to implement the drip-feeding technique to improve rebuffering. Next a tutorial about how to implement such technique, targeted at ExoPlayer:
https://medium.com/#filipluch/how-to-improve-buffering-by-4-times-with-drip-feeding-technique-in-exoplayer-on-android-b59eb0c4d9cc
You need cache data in ExoPlayer
Create a custom cache data source factory
public class CacheDataSourceFactory implements DataSource.Factory {
private final Context context;
private final DefaultDataSourceFactory defaultDatasourceFactory;
private final long maxFileSize, maxCacheSize;
public CacheDataSourceFactory(Context context, long maxCacheSize, long maxFileSize) {
super();
this.context = context;
this.maxCacheSize = maxCacheSize;
this.maxFileSize = maxFileSize;
String userAgent = Util.getUserAgent(context, context.getString(R.string.app_name));
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
defaultDatasourceFactory = new DefaultDataSourceFactory(this.context,
bandwidthMeter,
new DefaultHttpDataSourceFactory(userAgent, bandwidthMeter));
}
#Override
public DataSource createDataSource() {
LeastRecentlyUsedCacheEvictor evictor = new LeastRecentlyUsedCacheEvictor(maxCacheSize);
SimpleCache simpleCache = new SimpleCache(new File(context.getCacheDir(), "media"), evictor);
return new CacheDataSource(simpleCache, defaultDatasourceFactory.createDataSource(),
new FileDataSource(), new CacheDataSink(simpleCache, maxFileSize),
CacheDataSource.FLAG_BLOCK_ON_CACHE | CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR, null);
}
}
And the player
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
SimpleExoPlayer exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector);
MediaSource audioSource = new ExtractorMediaSource(Uri.parse(url),
new CacheDataSourceFactory(context, 100 * 1024 * 1024, 5 * 1024 * 1024), new DefaultExtractorsFactory(), null, null);
exoPlayer.setPlayWhenReady(true);
exoPlayer.prepare(audioSource);
Try to use LoopingMediaSource and put it to player by:
player.prepare(loopingMediaSource)
Related
I am using ExoPlayer to play videos from URL. For some reason, my video keeps on buffering even it is low size video also. Please find the code snippet below which I have used to build ExoPlayer.
private MediaSource buildMediaStore(String mediaUrl) {
Uri videoUri = Uri.parse(mediaUrl);
DataSource.Factory dataSourceFactory = new DefaultHttpDataSourceFactory(Util.getUserAgent(this, getApplicationInfo().packageName), defaultBandwidthMeter);
DefaultExtractorsFactory extractorFactory = new DefaultExtractorsFactory();
return new ExtractorMediaSource(videoUri, dataSourceFactory, extractorFactory, null, null);
}
defaultBandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory trackSelectionFactory = new AdaptiveTrackSelection.Factory(defaultBandwidthMeter);
exoPlayer = ExoPlayerFactory.newSimpleInstance(new DefaultRenderersFactory(ViewVideoNewPotriateFullScreen.this),
new DefaultTrackSelector(trackSelectionFactory), new DefaultLoadControl());
MediaSource datasource = buildMediaStore(url);
exoPlayer.prepare(datasource, true, true);
simpleExoPlayer.setPlayer(exoPlayer);
simpleExoPlayer.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_ZOOM);
exoPlayer.setRepeatMode(Player.REPEAT_MODE_OFF);
exoPlayer.setPlayWhenReady(true);
exoPlayer.seekTo(getIntent().getLongExtra("position", 0));
//updateTimers();
exoPlayer.addListener(this);
I use Exoplayer library in my android app for playing some live HLS videos (.m3u8 format). The version is 2.8.4. I need to make functional in which the user can change video quality of live stream during watching it.
For this I use the followng method (I took it from exoplayer example project):
Pair<AlertDialog, TrackSelectionView> dialogPair = TrackSelectionView.getDialog(this, title, trackSelector, rendererIndex);
dialogPair.second.setShowDisableOption(true);
dialogPair.second.setAllowAdaptiveSelections(allowAdaptiveSelections);
dialogPair.first.show();
When I select some video quality, I see that new quality, but often (sometimes very often) after few seconds exoplayer throws an error in Player.EventListener in onPlayerError(ExoPlaybackException error) method. ExoPlaybackException always has TYPE_SOURCE and null messages. And I also noticed, when I see live videos in auto quality, it doesnt change quality to low when my internet connection goes down, I see the same exoplayer error with TYPE_SOURCE.
Here is my code for initializing player:
bandwidthMeter = new DefaultBandwidthMeter();
AdaptiveTrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
player = ExoPlayerFactory.newSimpleInstance(
new DefaultRenderersFactory(getActivity()),
trackSelector,
new DefaultLoadControl());
exoPlayerOnline.setPlayer(player);
MediaSource mediaSource = buildMediaSource(Uri.parse(videoStreamUrl));
player.prepare(mediaSource, true, false);
player.setPlayWhenReady(playWhenReady);
and method buildMediaSource():
private MediaSource buildMediaSource(Uri uri) {
DefaultHttpDataSourceFactory httpDataSourceFactory = new DefaultHttpDataSourceFactory(userAgent,
bandwidthMeter,
20 * 1000,
20 * 1000,
true);
DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(getActivity(),
bandwidthMeter,
httpDataSourceFactory);
OkHttpDataSourceFactory okHttpDataSourceFactory = new OkHttpDataSourceFactory(okHttpClient,
userAgent,
bandwidthMeter);
int type = Util.inferContentType(uri);
switch (type) {
case C.TYPE_SS:
return new SsMediaSource.Factory(new DefaultSsChunkSource.Factory(defaultDataSourceFactory), okHttpDataSourceFactory)
.createMediaSource(uri);
case C.TYPE_DASH:
return new DashMediaSource.Factory(new DefaultDashChunkSource.Factory(defaultDataSourceFactory), okHttpDataSourceFactory)
.createMediaSource(uri);
case C.TYPE_HLS:
return new HlsMediaSource.Factory(okHttpDataSourceFactory)
.createMediaSource(uri);
case C.TYPE_OTHER:
return new ExtractorMediaSource.Factory(okHttpDataSourceFactory)
.createMediaSource(uri);
default:
Toast.makeText(getActivity(), "Unsupported video type", Toast.LENGTH_LONG).show();
return null;
}
}
So, help me please, how to solve this problem?
I am using Exoplayer in my application and I want to show DashMediaSource.
I did it and the video will play this Code:
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "ExoPlayer"));
Uri uri = Uri.parse(videoUrl);
DashMediaSource dashMediaSource = new DashMediaSource(uri, dataSourceFactory,
new DefaultDashChunkSource.Factory(dataSourceFactory), null, null);
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelector trackSelector = new DefaultTrackSelector(new AdaptiveTrackSelection.Factory(bandwidthMeter));
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector);
simpleExoPlayerView.setPlayer(player);
player.prepare(dashMediaSource);
But I need to show the user a selector for the quality of this vide0.
I just want to get all available qualities from my dash file and show it to the use.
In ExoPlayer 1.5.8, I used getTrackCount() to get all available qualities but in ExoPlayer 2.5.3 it is not available anymore.
How can I do that?
I really appreciate your help.
Have you tried using AnalyticsListener?
player.addAnalyticsListener(new AnalyticsListener() {
#Override
public void onBandwidthEstimate(EventTime eventTime, int totalLoadTimeMs, long totalBytesLoaded, long bitrateEstimate) {
}
});
i have little problem with exoplayer. almost everything works fine when i try to play video from hls stream. hls stream contains 3 different sets of chunklists each for different bandwidth.
but hls adaptive streaming is not working and player works only with one chunklist and with slow internet connection is this solution unusable.
source code:
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
this.simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(getActivity(), trackSelector);
this.videoPlayer.setPlayer(this.simpleExoPlayer);
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this.getActivity(), Util.getUserAgent(this.getActivity(), "appName"));
MediaSource mediaSource = new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(Uri.parse(hlsUrl));
this.simpleExoPlayer.prepare(mediaSource);
this.simpleExoPlayer.setPlayWhenReady(true);
i tried to implement MediaSourceEventListener too and onDownstreamFormatChanged is called only once in the moment of player initialization.
thanks for any advices
The key here is you need to pass the same "bandwidthMeter" you passed in to AdaptiveTrackSelection.Factory to the dataSourceFactory too.
Only after these changes the Exoplayer does adaptive streaming as expected.
String userAgent = "XYZPLAYER";
DefaultHttpDataSourceFactory httpDataSourceFactory = new DefaultHttpDataSourceFactory(userAgent, bandwidthMeter, DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS, DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS, true);
DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(this, bandwidthMeter, httpDataSourceFactory);
I'm new on ExoPlayer , i'm currently heading to use it to play Native Udp Stream ( From french digital Television : 1080p 5-10 mbps in Variable bitrate )
I manage to play some udp stream with some tests videos from http://jell.yfish.us/ on different devices .
I have make some different video decoding test with HLS and Udp Streaming with this code for UDP :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myactivity);
sufaceview = (SurfaceView) findViewById(R.id.surfaceView2);
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector =
new DefaultTrackSelector(videoTrackSelectionFactory);
LoadControl loadControl = new DefaultLoadControl(
new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE),
15000, 60000, 2500, 6000);
player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);
Uri uri =
Uri.parse
("udp://#239.192.2.2:1234");
final DefaultBandwidthMeter bandwidthMeterA = new DefaultBandwidthMeter();
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,
Util.getUserAgent(this, "teveolauncher"), bandwidthMeterA);
extractorsFactory = new DefaultExtractorsFactory();
DataSource.Factory udsf = new UdpDataSource.Factory() {
#Override
public DataSource createDataSource() {
return new UdpDataSource(null, 3000, 100000);
}
};
ExtractorsFactory tsExtractorFactory = new ExtractorsFactory() {
#Override
public Extractor[] createExtractors() {
return new TsExtractor[]{new TsExtractor(MODE_SINGLE_PMT,
new TimestampAdjuster(0), new DefaultTsPayloadReaderFactory())};
}
};
MediaSource videoSource = new ExtractorMediaSource
(uri, udsf, tsExtractorFactory, null, null);
player.setVideoSurfaceView(sufaceview);
player.prepare(videoSource);
player.setPlayWhenReady(true);
}
For HLS I just Change the MediaSource and the datasourceFactory :
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,
Util.getUserAgent(this, "teveolauncher"), bandwidthMeterA);
MediaSource videoSource = new HlsMediaSource
(uri, dataSourceFactory, null, null);
I Know Udpstreaming is not officialy supported by ExoPlayer but the UdpDataSource class seems to work well.
After all the test , i noticed video with a variable biterate like french DTT can't be decoded correctly but with Constatnt biterate video like Jell yfish the decoding process is perfect .
There is some coding improvement to make VBR video decoded correctly ?
Thank you by advance :)
Sorry for my bad english :)
Uri uri = Uri.parse("udp://#239.192.2.2:1234");
I think UDP is not a protocol - it's a transport, (like TCP). You can't use a tcp://host:port/ URL either.
Or does it work?