Search code examples
exoplayerexoplayer2.x

Why Exoplayer does not switch HLS tracks when bandwidth change


I have this simple .m3u8 file

#EXTM3U
#EXT-X-VERSION:5

#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="English stereo",LANGUAGE="en"

#EXT-X-STREAM-INF:BANDWIDTH=1728000,CODECS="avc1.42c00d,mp4a.40.2",RESOLUTION=640x360,AUDIO="audio"
https://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa_video_360_800000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=628000,CODECS="avc1.42c00d,mp4a.40.2",RESOLUTION=320x180,AUDIO="audio"
https://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa_video_180_250000.m3u8

With simpleExoplayer i load this stream like this :

// 1. Create a default TrackSelector
Handler mainHandler = new Handler();
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory =
    new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector =
    new DefaultTrackSelector(videoTrackSelectionFactory);

// 2. Create the player
SimpleExoPlayer player =
    ExoPlayerFactory.newSimpleInstance(context, trackSelector);

// Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context,
    Util.getUserAgent(context, "yourApplicationName"), bandwidthMeter);
// This is the MediaSource representing the media to be played.
MediaSource videoSource = new HlsMediaSource.Factory(dataSourceFactory)
    .createMediaSource(mp4VideoUri);
// Prepare the player with the source.
player.prepare(videoSource);
player.setPlayWhenReady(true);

but even on high WIFI internet it's will always select the 2nd track with have a resolution of 320x180 and never switch to the higher track with have a resolution of 640x360.

If i replace DEFAULT_MAX_INITIAL_BITRATE by maxInt then it's will select correctly the 1rt track (640x360) but if in the middle of the playback i cut off the wifi to let the mobile use only the low 3G connection, then it's will never switch to the 2nd track (320x180) and playing will stuck every time

Is also check MediaCodecUtil.getDecoderInfo("video/avc", false).adaptive and it's return TRUE

What did i do wrong? does hls work properly in simpleExoPlayer ?


Solution

  • DefaultBandwidthMeter is the component to meter network capacity. The DefaultBandwidthMeter implements the BandwidthMeter and the TransferListener interface.

    You should only use one instance of DefaultBandwidthMeter and pass it to both, the AdaptiveTrackSelection.Factory (as a BandwidthMeter) and the DefaultDataSourceFactory (as a TransferListener). This way the metering done in the data source takes effect in the track selector.

    With your code above the instance you pass to the AdaptiveTrackSelection.Factory is not aware of what is metered, which apparently does not work according to what you describe.

    Also note that if you create a new DefaultBandwidthMeter instance the metering done so far is lost. So you may want to have the DefaultBandwidthMeter as static variable or the like to retain the metering from earlier playbacks.

    TrackSelection.Factory videoTrackSelectionFactory =
        new AdaptiveTrackSelection.Factory(DEFAULT_BANDWIDTH_METER);
    TrackSelector trackSelector =
        new DefaultTrackSelector(videoTrackSelectionFactory);
    
    DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context,
        Util.getUserAgent(context, "yourApplicationName"), DEFAULT_BANDWIDTH_METER);
    

    See also how the PlayerActivity of the demo application does it.