Progressive

Streams in the following container formats can be played directly by ExoPlayer. The contained audio and video sample formats must also be supported (see the sample formats section for details).

Container format Supported Comment
MP4 YES  
M4A YES  
FMP4 YES  
WebM YES  
Matroska YES  
MP3 YES Some streams only seekable using constant bitrate seeking**
Ogg YES Containing Vorbis, Opus and Flac
WAV YES  
MPEG-TS YES  
MPEG-PS YES  
FLV YES Not seekable*
ADTS (AAC) YES Only seekable using constant bitrate seeking**
Flac YES Using the Flac extension only
AMR YES Only seekable using constant bitrate seeking**

* Seeking is unsupported because the container does not provide metadata (e.g., a sample index) to allow a media player to perform a seek in an efficient way. If seeking is required, we suggest using a more appropriate container format.

** These extractors have FLAG_ENABLE_CONSTANT_BITRATE_SEEKING flags for enabling approximate seeking using a constant bitrate assumption. This functionality is not enabled by default. The simplest way to enable this functionality for all extractors that support it is to use DefaultExtractorsFactory.setConstantBitrateSeekingEnabled, as described here.

Creating a MediaSource

To play a progressive stream, create a ProgressiveMediaSource and prepare the player with it as usual.

// Create a data source factory.
DataSource.Factory dataSourceFactory =
    new DefaultHttpDataSourceFactory(Util.getUserAgent(context, "app-name"));
// Create a progressive media source pointing to a stream uri.
MediaSource mediaSource = new ProgressiveMediaSource.Factory(dataSourceFactory)
    .createMediaSource(progressiveUri);
// Create a player instance.
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(context);
// Prepare the player with the progressive media source.
player.prepare(mediaSource);

Customizing progressive playbacks

ExoPlayer provides multiple ways for you to tailor playback experience to your app’s needs. The following sections briefly document some of the customization options available when building a ProgressiveMediaSource. See the Customization page for more general customization options.

Setting extractor flags

Extractor flags can be used to control how individual formats are extracted. They can be set on a DefaultExtractorsFactory, which can then be used when instantiating a ProgressiveMediaSource.Factory. The following example passes a flag which disables edit list parsing for the MP4 streams.

DefaultExtractorsFactory extractorsFactory =
    new DefaultExtractorsFactory()
        .setMp4ExtractorFlags(Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS);
ProgressiveMediaSource progressiveMediaSource =
    new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory)
        .createMediaSource(progressiveUri);

Enabling constant bitrate seeking

For MP3, ADTS and AMR streams, you can enable approximate seeking using a constant bitrate assumption with FLAG_ENABLE_CONSTANT_BITRATE_SEEKING flags. These flags can be set for individual extractors using the approach described above. To enable constant bitrate seeking for all extractors that support it, use DefaultExtractorsFactory.setConstantBitrateSeekingEnabled.

DefaultExtractorsFactory extractorsFactory =
    new DefaultExtractorsFactory().setConstantBitrateSeekingEnabled(true);
ProgressiveMediaSource progressiveMediaSource =
    new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory)
        .createMediaSource(progressiveUri);

Customizing server interactions

Some apps may want to intercept HTTP requests and responses. You may want to inject custom request headers, read the server’s response headers, modify the requests’ URIs, etc. For example, your app may authenticate itself by injecting a token as a header when requesting the media segments. You can achieve these behaviors by injecting custom HttpDataSources into the ProgressiveMediaSource you create. The following snippet shows an example of header injection:

ProgressiveMediaSource progressiveMediaSource =
    new ProgressiveMediaSource.Factory(
            () -> {
              HttpDataSource dataSource =
                  new DefaultHttpDataSource(userAgent);
              // Set a custom authentication request header.
              dataSource.setRequestProperty("Header", "Value");
              return dataSource;
            })
        .createMediaSource(progressiveUri);

Customizing error handling

Implementing a custom LoadErrorHandlingPolicy allows apps to customize the way ExoPlayer reacts to load errors. For example, an app may want fail fast instead of retrying many times, or may want to customize the back-off logic that controls how long the player waits between each retry. The following snippet shows how to implement custom back-off logic when creating a ProgressiveMediaSource:

ProgressiveMediaSource progressiveMediaSource =
    new ProgressiveMediaSource.Factory(dataSourceFactory)
        .setLoadErrorHandlingPolicy(
            new DefaultLoadErrorHandlingPolicy() {
              @Override
              public long getRetryDelayMsFor(...) {
                // Implement custom back-off logic here.
              }
            })
        .createMediaSource(progressiveUri);

You will find more information in our Medium post about error handling.