Skip to content

[video_player_android] Add adaptive bitrate streaming support#11323

Closed
sheershtehri7 wants to merge 1 commit intoflutter:mainfrom
sheershtehri7:abr-android
Closed

[video_player_android] Add adaptive bitrate streaming support#11323
sheershtehri7 wants to merge 1 commit intoflutter:mainfrom
sheershtehri7:abr-android

Conversation

@sheershtehri7
Copy link

Implements adaptive bitrate streaming support for the Android video player.

Changes

  • setBandwidthLimit — Implements the platform interface method via ExoPlayer's DefaultTrackSelector.setMaxVideoBitrate(). Values <= 0 remove the cap (Integer.MAX_VALUE).
  • ABR configuration — Configures AdaptiveTrackSelection.Factory and DefaultBandwidthMeter (initial estimate 1 Mbps) for both texture and platform view modes, enabling ExoPlayer's built-in bandwidth-adaptive track selection.
  • PlatformVideoView — Switches from SurfaceView to TextureView to support seamless resolution changes during quality transitions. SurfaceView operates on a separate window layer which can cause visual artifacts when the video resolution changes mid-playback during ABR.
  • onVideoSizeChanged no-op — Added to both TextureExoPlayerEventListener and PlatformViewExoPlayerEventListener to prevent re-initialization events during ABR quality switches.
  • Null-safety — Adds null check for videoFormat in PlatformViewExoPlayerEventListener.sendInitialized() to handle cases where format is not yet available.

Versioned as 2.10.0 — minor version bump. Requires video_player_platform_interface ^6.7.0.

Depends on PR #11322 (platform interface setBandwidthLimit).

Part of flutter/flutter#183941

AI Disclosure: This PR was developed with assistance from AI tools (GitHub Copilot / Claude). All code has been reviewed, tested, and validated by the author.

Pre-Review Checklist

Footnotes

  1. Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. 2

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for adaptive bitrate streaming on Android. The changes include implementing setBandwidthLimit, configuring ExoPlayer with AdaptiveTrackSelection.Factory and DefaultBandwidthMeter, and switching to TextureView for platform views to allow seamless resolution changes. The implementation is solid, but there is an opportunity to reduce code duplication in the ExoPlayer creation logic, which I've pointed out in a specific comment.

Comment on lines 62 to 90
() -> {
androidx.media3.exoplayer.trackselection.DefaultTrackSelector trackSelector =
new androidx.media3.exoplayer.trackselection.DefaultTrackSelector(context);
DefaultBandwidthMeter bandwidthMeter =
new DefaultBandwidthMeter.Builder(context)
.setInitialBitrateEstimate(1_000_000)
.build();

// AdaptiveTrackSelection.Factory enables ABR: ExoPlayer selects
// video tracks based on measured network bandwidth.
DefaultTrackSelector trackSelector =
new DefaultTrackSelector(
context, new AdaptiveTrackSelection.Factory());

trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setAllowVideoNonSeamlessAdaptiveness(true)
.setAllowVideoMixedDecoderSupportAdaptiveness(true)
.setForceLowestBitrate(false)
.setForceHighestSupportedBitrate(false)
.build());

ExoPlayer.Builder builder =
new ExoPlayer.Builder(context)
.setTrackSelector(trackSelector)
.setBandwidthMeter(bandwidthMeter)
.setMediaSourceFactory(asset.getMediaSourceFactory(context));

return builder.build();
});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The ExoPlayer creation logic within this lambda is nearly identical to the logic in TextureVideoPlayer.create(). To avoid code duplication and improve maintainability, consider extracting this logic into a shared helper method.

For example, you could create a private static method, perhaps in the VideoPlayer base class, that builds and returns a configured ExoPlayer instance:

@UnstableApi
private static ExoPlayer createExoPlayerWithAbr(Context context, VideoAsset asset) {
    // ... (setup for DefaultBandwidthMeter and DefaultTrackSelector)
    ExoPlayer.Builder builder = 
        new ExoPlayer.Builder(context)
            .setTrackSelector(trackSelector)
            .setBandwidthMeter(bandwidthMeter)
            .setMediaSourceFactory(asset.getMediaSourceFactory(context));
    return builder.build();
}

Then, both create methods could use this helper in their ExoPlayerProvider lambda: () -> createExoPlayerWithAbr(context, asset).

Implements setBandwidthLimit via ExoPlayer's DefaultTrackSelector.setMaxVideoBitrate().

Key changes:
- Configures AdaptiveTrackSelection.Factory and DefaultBandwidthMeter for ABR
- Switches PlatformVideoView from SurfaceView to TextureView for seamless
  resolution changes during quality transitions
- Adds onVideoSizeChanged no-op to prevent re-initialization during ABR switches
- Adds null-safety check for video format in PlatformViewExoPlayerEventListener

Requires video_player_platform_interface ^6.7.0.
Part of flutter/flutter#183941
@stuartmorgan-g
Copy link
Collaborator

Closing per #11322 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants