From 0cd05362a8c9f3fa438bcd2b1def6f4903537545 Mon Sep 17 00:00:00 2001 From: Eugene Makar Date: Mon, 15 Apr 2024 13:46:04 +0300 Subject: [PATCH 1/9] issue/130272: upgrade to 2.19.1 as per migration guide recommendation --- packages/video_player/video_player_android/android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/video_player/video_player_android/android/build.gradle b/packages/video_player/video_player_android/android/build.gradle index 9d4d8376de2..65095f3f0fa 100644 --- a/packages/video_player/video_player_android/android/build.gradle +++ b/packages/video_player/video_player_android/android/build.gradle @@ -48,7 +48,7 @@ android { } dependencies { - def exoplayer_version = "2.18.7" + def exoplayer_version = "2.19.1" implementation "com.google.android.exoplayer:exoplayer-core:${exoplayer_version}" implementation "com.google.android.exoplayer:exoplayer-hls:${exoplayer_version}" implementation "com.google.android.exoplayer:exoplayer-dash:${exoplayer_version}" From 2351f3bda53c14d1fbdaf1d968a129cedcb05448 Mon Sep 17 00:00:00 2001 From: Eugene Makar Date: Mon, 15 Apr 2024 13:54:35 +0300 Subject: [PATCH 2/9] issue/130272: exoplayer 2.19.1 to media3-exoplayer 1.1.1 --- .../video_player_android/android/build.gradle | 10 ++--- .../plugins/videoplayer/VideoPlayer.java | 44 +++++++++---------- .../plugins/videoplayer/VideoPlayerTest.java | 10 ++--- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/packages/video_player/video_player_android/android/build.gradle b/packages/video_player/video_player_android/android/build.gradle index 65095f3f0fa..8ad00e5eda8 100644 --- a/packages/video_player/video_player_android/android/build.gradle +++ b/packages/video_player/video_player_android/android/build.gradle @@ -48,11 +48,11 @@ android { } dependencies { - def exoplayer_version = "2.19.1" - implementation "com.google.android.exoplayer:exoplayer-core:${exoplayer_version}" - implementation "com.google.android.exoplayer:exoplayer-hls:${exoplayer_version}" - implementation "com.google.android.exoplayer:exoplayer-dash:${exoplayer_version}" - implementation "com.google.android.exoplayer:exoplayer-smoothstreaming:${exoplayer_version}" + def exoplayer_version = "1.1.1" + implementation "androidx.media3:media3-exoplayer:${exoplayer_version}" + implementation "androidx.media3:media3-exoplayer-hls:${exoplayer_version}" + implementation "androidx.media3:media3-exoplayer-dash:${exoplayer_version}" + implementation "androidx.media3:media3-exoplayer-smoothstreaming:${exoplayer_version}" testImplementation 'junit:junit:4.13.2' testImplementation 'androidx.test:core:1.3.0' testImplementation 'org.mockito:mockito-inline:5.0.0' diff --git a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java index b8b78191230..79af6f4610a 100644 --- a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java +++ b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java @@ -4,34 +4,34 @@ package io.flutter.plugins.videoplayer; -import static com.google.android.exoplayer2.Player.REPEAT_MODE_ALL; -import static com.google.android.exoplayer2.Player.REPEAT_MODE_OFF; +import static androidx.media3.common.Player.REPEAT_MODE_ALL; +import static androidx.media3.common.Player.REPEAT_MODE_OFF; import android.content.Context; import android.net.Uri; import android.view.Surface; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.Format; -import com.google.android.exoplayer2.MediaItem; -import com.google.android.exoplayer2.PlaybackException; -import com.google.android.exoplayer2.PlaybackParameters; -import com.google.android.exoplayer2.Player; -import com.google.android.exoplayer2.Player.Listener; -import com.google.android.exoplayer2.audio.AudioAttributes; -import com.google.android.exoplayer2.source.MediaSource; -import com.google.android.exoplayer2.source.ProgressiveMediaSource; -import com.google.android.exoplayer2.source.dash.DashMediaSource; -import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource; -import com.google.android.exoplayer2.source.hls.HlsMediaSource; -import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource; -import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource; -import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DefaultDataSource; -import com.google.android.exoplayer2.upstream.DefaultHttpDataSource; -import com.google.android.exoplayer2.util.Util; +import androidx.media3.common.AudioAttributes; +import androidx.media3.common.C; +import androidx.media3.common.Format; +import androidx.media3.common.MediaItem; +import androidx.media3.common.PlaybackException; +import androidx.media3.common.PlaybackParameters; +import androidx.media3.common.Player; +import androidx.media3.common.Player.Listener; +import androidx.media3.common.util.Util; +import androidx.media3.datasource.DataSource; +import androidx.media3.datasource.DefaultDataSource; +import androidx.media3.datasource.DefaultHttpDataSource; +import androidx.media3.exoplayer.ExoPlayer; +import androidx.media3.exoplayer.dash.DashMediaSource; +import androidx.media3.exoplayer.dash.DefaultDashChunkSource; +import androidx.media3.exoplayer.hls.HlsMediaSource; +import androidx.media3.exoplayer.smoothstreaming.DefaultSsChunkSource; +import androidx.media3.exoplayer.smoothstreaming.SsMediaSource; +import androidx.media3.exoplayer.source.MediaSource; +import androidx.media3.exoplayer.source.ProgressiveMediaSource; import io.flutter.plugin.common.EventChannel; import io.flutter.view.TextureRegistry; import java.util.Arrays; diff --git a/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java b/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java index 7ff5000d3cf..d0fdd411bd1 100644 --- a/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java +++ b/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java @@ -14,11 +14,11 @@ import static org.mockito.Mockito.times; import android.graphics.SurfaceTexture; -import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.Format; -import com.google.android.exoplayer2.PlaybackException; -import com.google.android.exoplayer2.Player; -import com.google.android.exoplayer2.upstream.DefaultHttpDataSource; +import androidx.media3.common.Format; +import androidx.media3.common.PlaybackException; +import androidx.media3.common.Player; +import androidx.media3.datasource.DefaultHttpDataSource; +import androidx.media3.exoplayer.ExoPlayer; import io.flutter.plugin.common.EventChannel; import io.flutter.view.TextureRegistry; import java.util.HashMap; From b8c5e21451fdd615c5bc161818f62c5cb785e211 Mon Sep 17 00:00:00 2001 From: Eugene Makar Date: Mon, 15 Apr 2024 15:20:38 +0300 Subject: [PATCH 3/9] issue/130272: explicitly bump annotation-experimental and opt-in into UnstableApi --- .../video_player/video_player_android/android/build.gradle | 1 + .../java/io/flutter/plugins/videoplayer/VideoPlayer.java | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/packages/video_player/video_player_android/android/build.gradle b/packages/video_player/video_player_android/android/build.gradle index 8ad00e5eda8..b841a74ebfe 100644 --- a/packages/video_player/video_player_android/android/build.gradle +++ b/packages/video_player/video_player_android/android/build.gradle @@ -53,6 +53,7 @@ android { implementation "androidx.media3:media3-exoplayer-hls:${exoplayer_version}" implementation "androidx.media3:media3-exoplayer-dash:${exoplayer_version}" implementation "androidx.media3:media3-exoplayer-smoothstreaming:${exoplayer_version}" + debugImplementation "androidx.annotation:annotation-experimental:1.3.0" testImplementation 'junit:junit:4.13.2' testImplementation 'androidx.test:core:1.3.0' testImplementation 'org.mockito:mockito-inline:5.0.0' diff --git a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java index 79af6f4610a..2bd24546d06 100644 --- a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java +++ b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java @@ -11,6 +11,7 @@ import android.net.Uri; import android.view.Surface; import androidx.annotation.NonNull; +import androidx.annotation.OptIn; import androidx.annotation.VisibleForTesting; import androidx.media3.common.AudioAttributes; import androidx.media3.common.C; @@ -20,6 +21,7 @@ import androidx.media3.common.PlaybackParameters; import androidx.media3.common.Player; import androidx.media3.common.Player.Listener; +import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DefaultDataSource; @@ -40,6 +42,9 @@ import java.util.List; import java.util.Map; +// API marked with UnstableApi is safe to use, it is only delicate when targeting stable ABI +// https://developer.android.com/media/media3/exoplayer/migration-guide#unstableapi +@OptIn(markerClass = UnstableApi.class) final class VideoPlayer { private static final String FORMAT_SS = "ss"; private static final String FORMAT_DASH = "dash"; From a057633c6f0c281e1806005808b88c13d91c9156 Mon Sep 17 00:00:00 2001 From: Eugene Makar Date: Mon, 15 Apr 2024 21:09:27 +0300 Subject: [PATCH 4/9] issue/130272: bump media3-exoplayer to 1.3.1 --- .../video_player/video_player_android/android/build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/video_player/video_player_android/android/build.gradle b/packages/video_player/video_player_android/android/build.gradle index b841a74ebfe..77f504de422 100644 --- a/packages/video_player/video_player_android/android/build.gradle +++ b/packages/video_player/video_player_android/android/build.gradle @@ -48,12 +48,11 @@ android { } dependencies { - def exoplayer_version = "1.1.1" + def exoplayer_version = "1.3.1" implementation "androidx.media3:media3-exoplayer:${exoplayer_version}" implementation "androidx.media3:media3-exoplayer-hls:${exoplayer_version}" implementation "androidx.media3:media3-exoplayer-dash:${exoplayer_version}" implementation "androidx.media3:media3-exoplayer-smoothstreaming:${exoplayer_version}" - debugImplementation "androidx.annotation:annotation-experimental:1.3.0" testImplementation 'junit:junit:4.13.2' testImplementation 'androidx.test:core:1.3.0' testImplementation 'org.mockito:mockito-inline:5.0.0' From c8b6c0d42d363c1be0b87e1380e395e9193bb234 Mon Sep 17 00:00:00 2001 From: Eugene Makar Date: Mon, 15 Apr 2024 23:30:06 +0300 Subject: [PATCH 5/9] issue/130272: explicitly mark unstable api --- .../plugins/videoplayer/VideoPlayer.java | 103 ++++++++++++------ 1 file changed, 69 insertions(+), 34 deletions(-) diff --git a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java index 2bd24546d06..f05e67fd05f 100644 --- a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java +++ b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java @@ -11,6 +11,7 @@ import android.net.Uri; import android.view.Surface; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.OptIn; import androidx.annotation.VisibleForTesting; import androidx.media3.common.AudioAttributes; @@ -42,9 +43,6 @@ import java.util.List; import java.util.Map; -// API marked with UnstableApi is safe to use, it is only delicate when targeting stable ABI -// https://developer.android.com/media/media3/exoplayer/migration-guide#unstableapi -@OptIn(markerClass = UnstableApi.class) final class VideoPlayer { private static final String FORMAT_SS = "ss"; private static final String FORMAT_DASH = "dash"; @@ -90,7 +88,7 @@ final class VideoPlayer { MediaSource mediaSource = buildMediaSource(uri, dataSourceFactory, formatHint); - exoPlayer.setMediaSource(mediaSource); + unstableSetMediaSource(exoPlayer, mediaSource); exoPlayer.prepare(); setUpVideoPlayer(exoPlayer, new QueuingEventSink()); @@ -121,11 +119,8 @@ public void buildHttpDataSourceFactory(@NonNull Map httpHeaders) ? httpHeaders.get(USER_AGENT) : "ExoPlayer"; - httpDataSourceFactory.setUserAgent(userAgent).setAllowCrossProtocolRedirects(true); - - if (httpHeadersNotEmpty) { - httpDataSourceFactory.setDefaultRequestProperties(httpHeaders); - } + unstableUpdateDataSourceFactory( + httpDataSourceFactory, httpHeaders, userAgent, httpHeadersNotEmpty); } private MediaSource buildMediaSource( @@ -152,26 +147,7 @@ private MediaSource buildMediaSource( break; } } - switch (type) { - case C.CONTENT_TYPE_SS: - return new SsMediaSource.Factory( - new DefaultSsChunkSource.Factory(mediaDataSourceFactory), mediaDataSourceFactory) - .createMediaSource(MediaItem.fromUri(uri)); - case C.CONTENT_TYPE_DASH: - return new DashMediaSource.Factory( - new DefaultDashChunkSource.Factory(mediaDataSourceFactory), mediaDataSourceFactory) - .createMediaSource(MediaItem.fromUri(uri)); - case C.CONTENT_TYPE_HLS: - return new HlsMediaSource.Factory(mediaDataSourceFactory) - .createMediaSource(MediaItem.fromUri(uri)); - case C.CONTENT_TYPE_OTHER: - return new ProgressiveMediaSource.Factory(mediaDataSourceFactory) - .createMediaSource(MediaItem.fromUri(uri)); - default: - { - throw new IllegalStateException("Unsupported type: " + type); - } - } + return unstableBuildMediaSource(uri, mediaDataSourceFactory, type); } private void setUpVideoPlayer(ExoPlayer exoPlayer, QueuingEventSink eventSink) { @@ -309,15 +285,15 @@ void sendInitialized() { event.put("event", "initialized"); event.put("duration", exoPlayer.getDuration()); - if (exoPlayer.getVideoFormat() != null) { - Format videoFormat = exoPlayer.getVideoFormat(); + Format videoFormat = unstableGetVideoFormat(exoPlayer); + if (videoFormat != null) { int width = videoFormat.width; int height = videoFormat.height; - int rotationDegrees = videoFormat.rotationDegrees; + int rotationDegrees = unstableGetRotationDegrees(videoFormat); // Switch the width/height if video was taken in portrait mode if (rotationDegrees == 90 || rotationDegrees == 270) { - width = exoPlayer.getVideoFormat().height; - height = exoPlayer.getVideoFormat().width; + width = videoFormat.height; + height = videoFormat.width; } event.put("width", width); event.put("height", height); @@ -348,4 +324,63 @@ void dispose() { exoPlayer.release(); } } + + // TODO: migrate to stable API, see https://github.com/flutter/flutter/issues/147039 + @OptIn(markerClass = UnstableApi.class) + private static void unstableSetMediaSource(ExoPlayer exoPlayer, MediaSource mediaSource) { + exoPlayer.setMediaSource(mediaSource); + } + + // TODO: migrate to stable API, see https://github.com/flutter/flutter/issues/147039 + @OptIn(markerClass = UnstableApi.class) + private static void unstableUpdateDataSourceFactory( + DefaultHttpDataSource.Factory factory, + @NonNull Map httpHeaders, + String userAgent, + boolean httpHeadersNotEmpty) { + factory.setUserAgent(userAgent).setAllowCrossProtocolRedirects(true); + + if (httpHeadersNotEmpty) { + factory.setDefaultRequestProperties(httpHeaders); + } + } + + // TODO: migrate to stable API, see https://github.com/flutter/flutter/issues/147039 + @OptIn(markerClass = UnstableApi.class) + private static MediaSource unstableBuildMediaSource( + Uri uri, DataSource.Factory mediaDataSourceFactory, int type) { + switch (type) { + case C.CONTENT_TYPE_SS: + return new SsMediaSource.Factory( + new DefaultSsChunkSource.Factory(mediaDataSourceFactory), mediaDataSourceFactory) + .createMediaSource(MediaItem.fromUri(uri)); + case C.CONTENT_TYPE_DASH: + return new DashMediaSource.Factory( + new DefaultDashChunkSource.Factory(mediaDataSourceFactory), mediaDataSourceFactory) + .createMediaSource(MediaItem.fromUri(uri)); + case C.CONTENT_TYPE_HLS: + return new HlsMediaSource.Factory(mediaDataSourceFactory) + .createMediaSource(MediaItem.fromUri(uri)); + case C.CONTENT_TYPE_OTHER: + return new ProgressiveMediaSource.Factory(mediaDataSourceFactory) + .createMediaSource(MediaItem.fromUri(uri)); + default: + { + throw new IllegalStateException("Unsupported type: " + type); + } + } + } + + // TODO: migrate to stable API, see https://github.com/flutter/flutter/issues/147039 + @OptIn(markerClass = UnstableApi.class) + @Nullable + private static Format unstableGetVideoFormat(ExoPlayer exoPlayer) { + return exoPlayer.getVideoFormat(); + } + + // TODO: migrate to stable API, see https://github.com/flutter/flutter/issues/147039 + @OptIn(markerClass = UnstableApi.class) + private static int unstableGetRotationDegrees(Format videoFormat) { + return videoFormat.rotationDegrees; + } } From c191e85da34d41f35b603ba617c5b405a54e7dd0 Mon Sep 17 00:00:00 2001 From: Eugene Makar Date: Mon, 15 Apr 2024 14:00:08 +0300 Subject: [PATCH 6/9] issue/130272: migrate ExoPlayer to Media3-ExoPlayer 1.3.1 --- packages/video_player/video_player_android/CHANGELOG.md | 4 ++++ packages/video_player/video_player_android/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/video_player/video_player_android/CHANGELOG.md b/packages/video_player/video_player_android/CHANGELOG.md index e2b39f8f44f..949ed92597e 100644 --- a/packages/video_player/video_player_android/CHANGELOG.md +++ b/packages/video_player/video_player_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.5.0 + +* Migrates ExoPlayer to Media3-ExoPlayer 1.3.1. + ## 2.4.17 * Revert Impeller support. diff --git a/packages/video_player/video_player_android/pubspec.yaml b/packages/video_player/video_player_android/pubspec.yaml index 864c3ec8efa..4fbd2a88fbe 100644 --- a/packages/video_player/video_player_android/pubspec.yaml +++ b/packages/video_player/video_player_android/pubspec.yaml @@ -2,7 +2,7 @@ name: video_player_android description: Android implementation of the video_player plugin. repository: https://github.com/flutter/packages/tree/main/packages/video_player/video_player_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22 -version: 2.4.17 +version: 2.5.0 environment: sdk: ^3.4.0 From 9216f1706a081c6519630ee4a181b1da467dcb81 Mon Sep 17 00:00:00 2001 From: emakar Date: Tue, 4 Jun 2024 22:40:42 +0300 Subject: [PATCH 7/9] issue/130272: migrate unstable api: replace MediaSource with MediaItem --- .../plugins/videoplayer/VideoPlayer.java | 102 ++++++------------ 1 file changed, 32 insertions(+), 70 deletions(-) diff --git a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java index f05e67fd05f..a77dd9ef285 100644 --- a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java +++ b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java @@ -8,7 +8,6 @@ import static androidx.media3.common.Player.REPEAT_MODE_OFF; import android.content.Context; -import android.net.Uri; import android.view.Surface; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -18,23 +17,17 @@ import androidx.media3.common.C; import androidx.media3.common.Format; import androidx.media3.common.MediaItem; +import androidx.media3.common.MimeTypes; import androidx.media3.common.PlaybackException; import androidx.media3.common.PlaybackParameters; import androidx.media3.common.Player; import androidx.media3.common.Player.Listener; import androidx.media3.common.util.UnstableApi; -import androidx.media3.common.util.Util; import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DefaultDataSource; import androidx.media3.datasource.DefaultHttpDataSource; import androidx.media3.exoplayer.ExoPlayer; -import androidx.media3.exoplayer.dash.DashMediaSource; -import androidx.media3.exoplayer.dash.DefaultDashChunkSource; -import androidx.media3.exoplayer.hls.HlsMediaSource; -import androidx.media3.exoplayer.smoothstreaming.DefaultSsChunkSource; -import androidx.media3.exoplayer.smoothstreaming.SsMediaSource; -import androidx.media3.exoplayer.source.MediaSource; -import androidx.media3.exoplayer.source.ProgressiveMediaSource; +import androidx.media3.exoplayer.source.DefaultMediaSourceFactory; import io.flutter.plugin.common.EventChannel; import io.flutter.view.TextureRegistry; import java.util.Arrays; @@ -79,16 +72,17 @@ final class VideoPlayer { this.textureEntry = textureEntry; this.options = options; - ExoPlayer exoPlayer = new ExoPlayer.Builder(context).build(); - Uri uri = Uri.parse(dataSource); + MediaItem mediaItem = + new MediaItem.Builder() + .setUri(dataSource) + .setMimeType(mimeFromFormatHint(formatHint)) + .build(); buildHttpDataSourceFactory(httpHeaders); - DataSource.Factory dataSourceFactory = - new DefaultDataSource.Factory(context, httpDataSourceFactory); - MediaSource mediaSource = buildMediaSource(uri, dataSourceFactory, formatHint); + ExoPlayer exoPlayer = buildExoPlayer(context); - unstableSetMediaSource(exoPlayer, mediaSource); + exoPlayer.setMediaItem(mediaItem); exoPlayer.prepare(); setUpVideoPlayer(exoPlayer, new QueuingEventSink()); @@ -123,31 +117,13 @@ public void buildHttpDataSourceFactory(@NonNull Map httpHeaders) httpDataSourceFactory, httpHeaders, userAgent, httpHeadersNotEmpty); } - private MediaSource buildMediaSource( - Uri uri, DataSource.Factory mediaDataSourceFactory, String formatHint) { - int type; - if (formatHint == null) { - type = Util.inferContentType(uri); - } else { - switch (formatHint) { - case FORMAT_SS: - type = C.CONTENT_TYPE_SS; - break; - case FORMAT_DASH: - type = C.CONTENT_TYPE_DASH; - break; - case FORMAT_HLS: - type = C.CONTENT_TYPE_HLS; - break; - case FORMAT_OTHER: - type = C.CONTENT_TYPE_OTHER; - break; - default: - type = -1; - break; - } - } - return unstableBuildMediaSource(uri, mediaDataSourceFactory, type); + @NonNull + private ExoPlayer buildExoPlayer(Context context) { + DataSource.Factory dataSourceFactory = + new DefaultDataSource.Factory(context, httpDataSourceFactory); + DefaultMediaSourceFactory mediaSourceFactory = + new DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory); + return new ExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build(); } private void setUpVideoPlayer(ExoPlayer exoPlayer, QueuingEventSink eventSink) { @@ -325,10 +301,22 @@ void dispose() { } } - // TODO: migrate to stable API, see https://github.com/flutter/flutter/issues/147039 - @OptIn(markerClass = UnstableApi.class) - private static void unstableSetMediaSource(ExoPlayer exoPlayer, MediaSource mediaSource) { - exoPlayer.setMediaSource(mediaSource); + @Nullable + private static String mimeFromFormatHint(@Nullable String formatHint) { + if (formatHint == null) { + return null; + } + switch (formatHint) { + case FORMAT_SS: + return MimeTypes.APPLICATION_SS; + case FORMAT_DASH: + return MimeTypes.APPLICATION_MPD; + case FORMAT_HLS: + return MimeTypes.APPLICATION_M3U8; + case FORMAT_OTHER: + default: + return null; + } } // TODO: migrate to stable API, see https://github.com/flutter/flutter/issues/147039 @@ -345,32 +333,6 @@ private static void unstableUpdateDataSourceFactory( } } - // TODO: migrate to stable API, see https://github.com/flutter/flutter/issues/147039 - @OptIn(markerClass = UnstableApi.class) - private static MediaSource unstableBuildMediaSource( - Uri uri, DataSource.Factory mediaDataSourceFactory, int type) { - switch (type) { - case C.CONTENT_TYPE_SS: - return new SsMediaSource.Factory( - new DefaultSsChunkSource.Factory(mediaDataSourceFactory), mediaDataSourceFactory) - .createMediaSource(MediaItem.fromUri(uri)); - case C.CONTENT_TYPE_DASH: - return new DashMediaSource.Factory( - new DefaultDashChunkSource.Factory(mediaDataSourceFactory), mediaDataSourceFactory) - .createMediaSource(MediaItem.fromUri(uri)); - case C.CONTENT_TYPE_HLS: - return new HlsMediaSource.Factory(mediaDataSourceFactory) - .createMediaSource(MediaItem.fromUri(uri)); - case C.CONTENT_TYPE_OTHER: - return new ProgressiveMediaSource.Factory(mediaDataSourceFactory) - .createMediaSource(MediaItem.fromUri(uri)); - default: - { - throw new IllegalStateException("Unsupported type: " + type); - } - } - } - // TODO: migrate to stable API, see https://github.com/flutter/flutter/issues/147039 @OptIn(markerClass = UnstableApi.class) @Nullable From 6befcaab83e88d23dc06592299dac025ab58cfb2 Mon Sep 17 00:00:00 2001 From: emakar Date: Tue, 4 Jun 2024 23:03:38 +0300 Subject: [PATCH 8/9] issue/130272: migrate unstable api: replace video Format with VideoSize --- .../plugins/videoplayer/VideoPlayer.java | 29 +++++-------------- .../plugins/videoplayer/VideoPlayerTest.java | 22 ++++++-------- 2 files changed, 17 insertions(+), 34 deletions(-) diff --git a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java index a77dd9ef285..cb8a97736a2 100644 --- a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java +++ b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java @@ -15,13 +15,13 @@ import androidx.annotation.VisibleForTesting; import androidx.media3.common.AudioAttributes; import androidx.media3.common.C; -import androidx.media3.common.Format; import androidx.media3.common.MediaItem; import androidx.media3.common.MimeTypes; import androidx.media3.common.PlaybackException; import androidx.media3.common.PlaybackParameters; import androidx.media3.common.Player; import androidx.media3.common.Player.Listener; +import androidx.media3.common.VideoSize; import androidx.media3.common.util.UnstableApi; import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DefaultDataSource; @@ -261,15 +261,15 @@ void sendInitialized() { event.put("event", "initialized"); event.put("duration", exoPlayer.getDuration()); - Format videoFormat = unstableGetVideoFormat(exoPlayer); - if (videoFormat != null) { - int width = videoFormat.width; - int height = videoFormat.height; - int rotationDegrees = unstableGetRotationDegrees(videoFormat); + VideoSize videoSize = exoPlayer.getVideoSize(); + int width = videoSize.width; + int height = videoSize.height; + if (width != 0 && height != 0) { + int rotationDegrees = videoSize.unappliedRotationDegrees; // Switch the width/height if video was taken in portrait mode if (rotationDegrees == 90 || rotationDegrees == 270) { - width = videoFormat.height; - height = videoFormat.width; + width = videoSize.height; + height = videoSize.width; } event.put("width", width); event.put("height", height); @@ -332,17 +332,4 @@ private static void unstableUpdateDataSourceFactory( factory.setDefaultRequestProperties(httpHeaders); } } - - // TODO: migrate to stable API, see https://github.com/flutter/flutter/issues/147039 - @OptIn(markerClass = UnstableApi.class) - @Nullable - private static Format unstableGetVideoFormat(ExoPlayer exoPlayer) { - return exoPlayer.getVideoFormat(); - } - - // TODO: migrate to stable API, see https://github.com/flutter/flutter/issues/147039 - @OptIn(markerClass = UnstableApi.class) - private static int unstableGetRotationDegrees(Format videoFormat) { - return videoFormat.rotationDegrees; - } } diff --git a/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java b/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java index d0fdd411bd1..aabd7ce1fea 100644 --- a/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java +++ b/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java @@ -14,9 +14,9 @@ import static org.mockito.Mockito.times; import android.graphics.SurfaceTexture; -import androidx.media3.common.Format; import androidx.media3.common.PlaybackException; import androidx.media3.common.Player; +import androidx.media3.common.VideoSize; import androidx.media3.datasource.DefaultHttpDataSource; import androidx.media3.exoplayer.ExoPlayer; import io.flutter.plugin.common.EventChannel; @@ -139,10 +139,9 @@ public void sendInitializedSendsExpectedEvent_90RotationDegrees() { fakeVideoPlayerOptions, fakeEventSink, httpDataSourceFactorySpy); - Format testFormat = - new Format.Builder().setWidth(100).setHeight(200).setRotationDegrees(90).build(); + VideoSize testVideoSize = new VideoSize(100, 200, 90, 1f); - when(fakeExoPlayer.getVideoFormat()).thenReturn(testFormat); + when(fakeExoPlayer.getVideoSize()).thenReturn(testVideoSize); when(fakeExoPlayer.getDuration()).thenReturn(10L); videoPlayer.isInitialized = true; @@ -168,10 +167,9 @@ public void sendInitializedSendsExpectedEvent_270RotationDegrees() { fakeVideoPlayerOptions, fakeEventSink, httpDataSourceFactorySpy); - Format testFormat = - new Format.Builder().setWidth(100).setHeight(200).setRotationDegrees(270).build(); + VideoSize testVideoSize = new VideoSize(100, 200, 270, 1f); - when(fakeExoPlayer.getVideoFormat()).thenReturn(testFormat); + when(fakeExoPlayer.getVideoSize()).thenReturn(testVideoSize); when(fakeExoPlayer.getDuration()).thenReturn(10L); videoPlayer.isInitialized = true; @@ -197,10 +195,9 @@ public void sendInitializedSendsExpectedEvent_0RotationDegrees() { fakeVideoPlayerOptions, fakeEventSink, httpDataSourceFactorySpy); - Format testFormat = - new Format.Builder().setWidth(100).setHeight(200).setRotationDegrees(0).build(); + VideoSize testVideoSize = new VideoSize(100, 200, 0, 1f); - when(fakeExoPlayer.getVideoFormat()).thenReturn(testFormat); + when(fakeExoPlayer.getVideoSize()).thenReturn(testVideoSize); when(fakeExoPlayer.getDuration()).thenReturn(10L); videoPlayer.isInitialized = true; @@ -226,10 +223,9 @@ public void sendInitializedSendsExpectedEvent_180RotationDegrees() { fakeVideoPlayerOptions, fakeEventSink, httpDataSourceFactorySpy); - Format testFormat = - new Format.Builder().setWidth(100).setHeight(200).setRotationDegrees(180).build(); + VideoSize testVideoSize = new VideoSize(100, 200, 180, 1f); - when(fakeExoPlayer.getVideoFormat()).thenReturn(testFormat); + when(fakeExoPlayer.getVideoSize()).thenReturn(testVideoSize); when(fakeExoPlayer.getDuration()).thenReturn(10L); videoPlayer.isInitialized = true; From a134c806b25275190e53b671b370f383de10f6d9 Mon Sep 17 00:00:00 2001 From: emakar Date: Fri, 7 Jun 2024 00:06:29 +0300 Subject: [PATCH 9/9] issue/130272: make httpDataSourceFactory usage clear --- .../plugins/videoplayer/VideoPlayer.java | 28 ++++++++++--------- .../plugins/videoplayer/VideoPlayerTest.java | 6 ++-- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java index cb8a97736a2..4529db72d86 100644 --- a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java +++ b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java @@ -58,7 +58,7 @@ final class VideoPlayer { private final VideoPlayerOptions options; - private DefaultHttpDataSource.Factory httpDataSourceFactory = new DefaultHttpDataSource.Factory(); + private final DefaultHttpDataSource.Factory httpDataSourceFactory; VideoPlayer( Context context, @@ -78,9 +78,10 @@ final class VideoPlayer { .setMimeType(mimeFromFormatHint(formatHint)) .build(); - buildHttpDataSourceFactory(httpHeaders); + httpDataSourceFactory = new DefaultHttpDataSource.Factory(); + configureHttpDataSourceFactory(httpHeaders); - ExoPlayer exoPlayer = buildExoPlayer(context); + ExoPlayer exoPlayer = buildExoPlayer(context, httpDataSourceFactory); exoPlayer.setMediaItem(mediaItem); exoPlayer.prepare(); @@ -106,7 +107,7 @@ final class VideoPlayer { } @VisibleForTesting - public void buildHttpDataSourceFactory(@NonNull Map httpHeaders) { + public void configureHttpDataSourceFactory(@NonNull Map httpHeaders) { final boolean httpHeadersNotEmpty = !httpHeaders.isEmpty(); final String userAgent = httpHeadersNotEmpty && httpHeaders.containsKey(USER_AGENT) @@ -117,15 +118,6 @@ public void buildHttpDataSourceFactory(@NonNull Map httpHeaders) httpDataSourceFactory, httpHeaders, userAgent, httpHeadersNotEmpty); } - @NonNull - private ExoPlayer buildExoPlayer(Context context) { - DataSource.Factory dataSourceFactory = - new DefaultDataSource.Factory(context, httpDataSourceFactory); - DefaultMediaSourceFactory mediaSourceFactory = - new DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory); - return new ExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build(); - } - private void setUpVideoPlayer(ExoPlayer exoPlayer, QueuingEventSink eventSink) { this.exoPlayer = exoPlayer; this.eventSink = eventSink; @@ -301,6 +293,16 @@ void dispose() { } } + @NonNull + private static ExoPlayer buildExoPlayer( + Context context, DataSource.Factory baseDataSourceFactory) { + DataSource.Factory dataSourceFactory = + new DefaultDataSource.Factory(context, baseDataSourceFactory); + DefaultMediaSourceFactory mediaSourceFactory = + new DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory); + return new ExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build(); + } + @Nullable private static String mimeFromFormatHint(@Nullable String formatHint) { if (formatHint == null) { diff --git a/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java b/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java index aabd7ce1fea..a7a03e9e1ed 100644 --- a/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java +++ b/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/VideoPlayerTest.java @@ -71,7 +71,7 @@ public void videoPlayer_buildsHttpDataSourceFactoryProperlyWhenHttpHeadersNull() fakeEventSink, httpDataSourceFactorySpy); - videoPlayer.buildHttpDataSourceFactory(new HashMap<>()); + videoPlayer.configureHttpDataSourceFactory(new HashMap<>()); verify(httpDataSourceFactorySpy).setUserAgent("ExoPlayer"); verify(httpDataSourceFactorySpy).setAllowCrossProtocolRedirects(true); @@ -97,7 +97,7 @@ public void videoPlayer_buildsHttpDataSourceFactoryProperlyWhenHttpHeadersNull() } }; - videoPlayer.buildHttpDataSourceFactory(httpHeaders); + videoPlayer.configureHttpDataSourceFactory(httpHeaders); verify(httpDataSourceFactorySpy).setUserAgent("userAgent"); verify(httpDataSourceFactorySpy).setAllowCrossProtocolRedirects(true); @@ -122,7 +122,7 @@ public void videoPlayer_buildsHttpDataSourceFactoryProperlyWhenHttpHeadersNull() } }; - videoPlayer.buildHttpDataSourceFactory(httpHeaders); + videoPlayer.configureHttpDataSourceFactory(httpHeaders); verify(httpDataSourceFactorySpy).setUserAgent("ExoPlayer"); verify(httpDataSourceFactorySpy).setAllowCrossProtocolRedirects(true);