From 906ef1e630e0c115a7ec894d9e4345146f67811f Mon Sep 17 00:00:00 2001 From: John McDole Date: Thu, 22 Aug 2019 13:22:29 -0700 Subject: [PATCH 1/7] Pass down the format #39076 --- .../videoplayer/VideoPlayerPlugin.java | 57 ++++++++++--------- packages/video_player/lib/video_player.dart | 27 ++++++++- 2 files changed, 56 insertions(+), 28 deletions(-) diff --git a/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java b/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java index 0be5e770101c..8923ed7484d0 100644 --- a/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java +++ b/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java @@ -71,7 +71,8 @@ private static class VideoPlayer { EventChannel eventChannel, TextureRegistry.SurfaceTextureEntry textureEntry, String dataSource, - Result result) { + Result result, + String formatHint) { this.eventChannel = eventChannel; this.textureEntry = textureEntry; @@ -93,7 +94,7 @@ private static class VideoPlayer { true); } - MediaSource mediaSource = buildMediaSource(uri, dataSourceFactory, context); + MediaSource mediaSource = buildMediaSource(uri, dataSourceFactory, formatHint, context); exoPlayer.prepare(mediaSource); setupVideoPlayer(eventChannel, textureEntry, result); @@ -108,29 +109,27 @@ private static boolean isFileOrAsset(Uri uri) { } private MediaSource buildMediaSource( - Uri uri, DataSource.Factory mediaDataSourceFactory, Context context) { + Uri uri, DataSource.Factory mediaDataSourceFactory, String formatHint, Context context) { int type = Util.inferContentType(uri.getLastPathSegment()); - switch (type) { - case C.TYPE_SS: - return new SsMediaSource.Factory( - new DefaultSsChunkSource.Factory(mediaDataSourceFactory), - new DefaultDataSourceFactory(context, null, mediaDataSourceFactory)) - .createMediaSource(uri); - case C.TYPE_DASH: - return new DashMediaSource.Factory( - new DefaultDashChunkSource.Factory(mediaDataSourceFactory), - new DefaultDataSourceFactory(context, null, mediaDataSourceFactory)) - .createMediaSource(uri); - case C.TYPE_HLS: - return new HlsMediaSource.Factory(mediaDataSourceFactory).createMediaSource(uri); - case C.TYPE_OTHER: - return new ExtractorMediaSource.Factory(mediaDataSourceFactory) - .setExtractorsFactory(new DefaultExtractorsFactory()) - .createMediaSource(uri); - default: - { - throw new IllegalStateException("Unsupported type: " + type); - } + if (type == C.TYPE_SS || "ss".equals(formatHint)) { + return new SsMediaSource.Factory( + new DefaultSsChunkSource.Factory(mediaDataSourceFactory), + new DefaultDataSourceFactory(context, null, mediaDataSourceFactory)) + .createMediaSource(uri); + } else if (type == C.TYPE_DASH || "dash".equals(formatHint)) { + return new DashMediaSource.Factory( + new DefaultDashChunkSource.Factory(mediaDataSourceFactory), + new DefaultDataSourceFactory(context, null, mediaDataSourceFactory)) + .createMediaSource(uri); + + } else if (type == C.TYPE_HLS || "hsl".equals(formatHint)) { + return new HlsMediaSource.Factory(mediaDataSourceFactory).createMediaSource(uri); + } else if (type == C.TYPE_OTHER || "other".equals(formatHint)) { + return new ExtractorMediaSource.Factory(mediaDataSourceFactory) + .setExtractorsFactory(new DefaultExtractorsFactory()) + .createMediaSource(uri); + } else { + throw new IllegalStateException("Unsupported type: " + type); } } @@ -343,12 +342,18 @@ public void onMethodCall(MethodCall call, Result result) { eventChannel, handle, "asset:///" + assetLookupKey, - result); + result, + null); videoPlayers.put(handle.id(), player); } else { player = new VideoPlayer( - registrar.context(), eventChannel, handle, call.argument("uri"), result); + registrar.context(), + eventChannel, + handle, + call.argument("uri"), + result, + call.argument("formatHint")); videoPlayers.put(handle.id(), player); } break; diff --git a/packages/video_player/lib/video_player.dart b/packages/video_player/lib/video_player.dart index 3990f53f0d1d..d7c9371d4181 100644 --- a/packages/video_player/lib/video_player.dart +++ b/packages/video_player/lib/video_player.dart @@ -32,6 +32,8 @@ class DurationRange { String toString() => '$runtimeType(start: $start, end: $end)'; } +enum VideoFormat { dash, hls, ss, other } + /// The duration, current position, buffering state, error state and settings /// of a [VideoPlayerController]. class VideoPlayerValue { @@ -148,6 +150,7 @@ class VideoPlayerController extends ValueNotifier { /// package and null otherwise. VideoPlayerController.asset(this.dataSource, {this.package}) : dataSourceType = DataSourceType.asset, + formatHint = null, super(VideoPlayerValue(duration: null)); /// Constructs a [VideoPlayerController] playing a video from obtained from @@ -155,7 +158,7 @@ class VideoPlayerController extends ValueNotifier { /// /// The URI for the video is given by the [dataSource] argument and must not be /// null. - VideoPlayerController.network(this.dataSource) + VideoPlayerController.network(this.dataSource, {this.formatHint}) : dataSourceType = DataSourceType.network, package = null, super(VideoPlayerValue(duration: null)); @@ -168,10 +171,12 @@ class VideoPlayerController extends ValueNotifier { : dataSource = 'file://${file.path}', dataSourceType = DataSourceType.file, package = null, + formatHint = null, super(VideoPlayerValue(duration: null)); int _textureId; final String dataSource; + final VideoFormat formatHint; /// Describes the type of data source this [VideoPlayerController] /// is constructed with. @@ -203,7 +208,10 @@ class VideoPlayerController extends ValueNotifier { dataSourceDescription = {'uri': dataSource}; break; case DataSourceType.file: - dataSourceDescription = {'uri': dataSource}; + dataSourceDescription = { + 'uri': dataSource, + 'formatHint': _nameOf(formatHint) + }; } final Map response = await _channel.invokeMapMethod( @@ -397,6 +405,21 @@ class VideoPlayerController extends ValueNotifier { value = value.copyWith(volume: volume.clamp(0.0, 1.0)); await _applyVolume(); } + + static String _nameOf(VideoFormat format) { + switch (format) { + case VideoFormat.ss: + return 'ss'; + case VideoFormat.hls: + return 'hls'; + case VideoFormat.dash: + return 'dash'; + case VideoFormat.other: + return 'other'; + default: + return null; + } + } } class _VideoAppLifeCycleObserver extends Object with WidgetsBindingObserver { From 683b2a1b0b3c43a35469f7baf919b00d326bb287 Mon Sep 17 00:00:00 2001 From: John McDole Date: Thu, 22 Aug 2019 13:28:23 -0700 Subject: [PATCH 2/7] Changelog --- packages/video_player/CHANGELOG.md | 4 ++++ packages/video_player/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/video_player/CHANGELOG.md b/packages/video_player/CHANGELOG.md index 795d97fdb960..ebc3adba93f3 100644 --- a/packages/video_player/CHANGELOG.md +++ b/packages/video_player/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.10.2 + +* Adds optional VideoFormat used to signal what format the plugin should try. + ## 0.10.1+7 * Fix tests by ignoring deprecated member use. diff --git a/packages/video_player/pubspec.yaml b/packages/video_player/pubspec.yaml index 72ec7fa55b62..3c18e734c964 100644 --- a/packages/video_player/pubspec.yaml +++ b/packages/video_player/pubspec.yaml @@ -2,7 +2,7 @@ name: video_player description: Flutter plugin for displaying inline video with other Flutter widgets on Android and iOS. author: Flutter Team -version: 0.10.1+7 +version: 0.10.2 homepage: https://github.com/flutter/plugins/tree/master/packages/video_player flutter: From 8d41400172988e409d831e6567889ce0364a8d61 Mon Sep 17 00:00:00 2001 From: John McDole Date: Thu, 22 Aug 2019 14:11:46 -0700 Subject: [PATCH 3/7] Add fake override --- packages/video_player/test/video_player_test.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/video_player/test/video_player_test.dart b/packages/video_player/test/video_player_test.dart index 0bdcb756b711..f482f0b63cd3 100644 --- a/packages/video_player/test/video_player_test.dart +++ b/packages/video_player/test/video_player_test.dart @@ -41,6 +41,9 @@ class FakeController extends ValueNotifier Future play() async {} @override Future setLooping(bool looping) async {} + + @override + VideoFormat get formatHint => null; } void main() { From bd75c0b80af5899950c53ef01930f2892801820c Mon Sep 17 00:00:00 2001 From: John McDole Date: Thu, 22 Aug 2019 18:32:43 -0700 Subject: [PATCH 4/7] wip --- packages/video_player/CHANGELOG.md | 2 +- .../videoplayer/VideoPlayerPlugin.java | 13 +++++++--- packages/video_player/lib/video_player.dart | 26 +++++++------------ 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/packages/video_player/CHANGELOG.md b/packages/video_player/CHANGELOG.md index ebc3adba93f3..abf41afcfbb0 100644 --- a/packages/video_player/CHANGELOG.md +++ b/packages/video_player/CHANGELOG.md @@ -1,6 +1,6 @@ ## 0.10.2 -* Adds optional VideoFormat used to signal what format the plugin should try. +* **Android Only** Adds optional VideoFormat used to signal what format the plugin should try. ## 0.10.1+7 diff --git a/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java b/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java index 8923ed7484d0..fec1fa6cf4a3 100644 --- a/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java +++ b/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java @@ -108,23 +108,28 @@ private static boolean isFileOrAsset(Uri uri) { return scheme.equals("file") || scheme.equals("asset"); } + private static final FORMAT_SS = "ss"; + private static final FORMAT_DASH = "dash"; + private static final FORMAT_HLS = "hls"; + private static final FORMAT_OTHER = "other"; + private MediaSource buildMediaSource( Uri uri, DataSource.Factory mediaDataSourceFactory, String formatHint, Context context) { int type = Util.inferContentType(uri.getLastPathSegment()); - if (type == C.TYPE_SS || "ss".equals(formatHint)) { + if (type == C.TYPE_SS || FORMAT_SS.equals(formatHint)) { return new SsMediaSource.Factory( new DefaultSsChunkSource.Factory(mediaDataSourceFactory), new DefaultDataSourceFactory(context, null, mediaDataSourceFactory)) .createMediaSource(uri); - } else if (type == C.TYPE_DASH || "dash".equals(formatHint)) { + } else if (type == C.TYPE_DASH || FORMAT_DASH.equals(formatHint)) { return new DashMediaSource.Factory( new DefaultDashChunkSource.Factory(mediaDataSourceFactory), new DefaultDataSourceFactory(context, null, mediaDataSourceFactory)) .createMediaSource(uri); - } else if (type == C.TYPE_HLS || "hsl".equals(formatHint)) { + } else if (type == C.TYPE_HLS || FORMAT_HLS.equals(formatHint)) { return new HlsMediaSource.Factory(mediaDataSourceFactory).createMediaSource(uri); - } else if (type == C.TYPE_OTHER || "other".equals(formatHint)) { + } else if (type == C.TYPE_OTHER || FORMAT_OTHER.equals(formatHint)) { return new ExtractorMediaSource.Factory(mediaDataSourceFactory) .setExtractorsFactory(new DefaultExtractorsFactory()) .createMediaSource(uri); diff --git a/packages/video_player/lib/video_player.dart b/packages/video_player/lib/video_player.dart index d7c9371d4181..64de15ff70a9 100644 --- a/packages/video_player/lib/video_player.dart +++ b/packages/video_player/lib/video_player.dart @@ -157,7 +157,8 @@ class VideoPlayerController extends ValueNotifier { /// the network. /// /// The URI for the video is given by the [dataSource] argument and must not be - /// null. + /// null. The [formatHint] option allows the caller to specify the video + /// format in the case where it cannot be detected via url (Android only). VideoPlayerController.network(this.dataSource, {this.formatHint}) : dataSourceType = DataSourceType.network, package = null, @@ -210,7 +211,7 @@ class VideoPlayerController extends ValueNotifier { case DataSourceType.file: dataSourceDescription = { 'uri': dataSource, - 'formatHint': _nameOf(formatHint) + 'formatHint': _videoFormatStringMap[formatHint] }; } final Map response = @@ -406,20 +407,13 @@ class VideoPlayerController extends ValueNotifier { await _applyVolume(); } - static String _nameOf(VideoFormat format) { - switch (format) { - case VideoFormat.ss: - return 'ss'; - case VideoFormat.hls: - return 'hls'; - case VideoFormat.dash: - return 'dash'; - case VideoFormat.other: - return 'other'; - default: - return null; - } - } + static const Map _videoFormatStringMap = + { + VideoFormat.ss: 'ss', + VideoFormat.hls: 'hls', + VideoFormat.dash: 'dash', + VideoFormat.other: 'other', + }; } class _VideoAppLifeCycleObserver extends Object with WidgetsBindingObserver { From 37ca30674806b4d229f3058b983ec40f4ca87609 Mon Sep 17 00:00:00 2001 From: John McDole Date: Fri, 23 Aug 2019 09:03:19 -0700 Subject: [PATCH 5/7] Make formatHint override --- .../videoplayer/VideoPlayerPlugin.java | 61 +++++++++++++------ 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java b/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java index fec1fa6cf4a3..f1d4dbfd1a5b 100644 --- a/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java +++ b/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java @@ -115,26 +115,49 @@ private static boolean isFileOrAsset(Uri uri) { private MediaSource buildMediaSource( Uri uri, DataSource.Factory mediaDataSourceFactory, String formatHint, Context context) { - int type = Util.inferContentType(uri.getLastPathSegment()); - if (type == C.TYPE_SS || FORMAT_SS.equals(formatHint)) { - return new SsMediaSource.Factory( - new DefaultSsChunkSource.Factory(mediaDataSourceFactory), - new DefaultDataSourceFactory(context, null, mediaDataSourceFactory)) - .createMediaSource(uri); - } else if (type == C.TYPE_DASH || FORMAT_DASH.equals(formatHint)) { - return new DashMediaSource.Factory( - new DefaultDashChunkSource.Factory(mediaDataSourceFactory), - new DefaultDataSourceFactory(context, null, mediaDataSourceFactory)) - .createMediaSource(uri); - - } else if (type == C.TYPE_HLS || FORMAT_HLS.equals(formatHint)) { - return new HlsMediaSource.Factory(mediaDataSourceFactory).createMediaSource(uri); - } else if (type == C.TYPE_OTHER || FORMAT_OTHER.equals(formatHint)) { - return new ExtractorMediaSource.Factory(mediaDataSourceFactory) - .setExtractorsFactory(new DefaultExtractorsFactory()) - .createMediaSource(uri); + int type; + if (formatHint == null) { + type = Util.inferContentType(uri.getLastPathSegment()); } else { - throw new IllegalStateException("Unsupported type: " + type); + switch (formatHint) { + case FORMAT_SS: + type = C.TYPE_SS; + break; + case FORMAT_DASH: + type = C.TYPE_DASH; + break; + case FORMAT_HLS: + type = C.TYPE_HLS; + break; + case FORMAT_OTHER: + type = C.TYPE_OTHER; + break; + default: + type = -1; + break; + } + } + switch (type) { + case C.TYPE_SS: + return new SsMediaSource.Factory( + new DefaultSsChunkSource.Factory(mediaDataSourceFactory), + new DefaultDataSourceFactory(context, null, mediaDataSourceFactory)) + .createMediaSource(uri); + case C.TYPE_DASH: + return new DashMediaSource.Factory( + new DefaultDashChunkSource.Factory(mediaDataSourceFactory), + new DefaultDataSourceFactory(context, null, mediaDataSourceFactory)) + .createMediaSource(uri); + case C.TYPE_HLS: + return new HlsMediaSource.Factory(mediaDataSourceFactory).createMediaSource(uri); + case C.TYPE_OTHER: + return new ExtractorMediaSource.Factory(mediaDataSourceFactory) + .setExtractorsFactory(new DefaultExtractorsFactory()) + .createMediaSource(uri); + default: + { + throw new IllegalStateException("Unsupported type: " + type); + } } } From 217cfccc9a3cbf7b03b55ac5adc45bb9894c35cf Mon Sep 17 00:00:00 2001 From: John McDole Date: Fri, 23 Aug 2019 09:12:32 -0700 Subject: [PATCH 6/7] google-java-format --- .../plugins/videoplayer/VideoPlayerPlugin.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java b/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java index f1d4dbfd1a5b..50c26d460fb3 100644 --- a/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java +++ b/packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java @@ -53,6 +53,10 @@ public class VideoPlayerPlugin implements MethodCallHandler { private static class VideoPlayer { + private static final String FORMAT_SS = "ss"; + private static final String FORMAT_DASH = "dash"; + private static final String FORMAT_HLS = "hls"; + private static final String FORMAT_OTHER = "other"; private SimpleExoPlayer exoPlayer; @@ -108,11 +112,6 @@ private static boolean isFileOrAsset(Uri uri) { return scheme.equals("file") || scheme.equals("asset"); } - private static final FORMAT_SS = "ss"; - private static final FORMAT_DASH = "dash"; - private static final FORMAT_HLS = "hls"; - private static final FORMAT_OTHER = "other"; - private MediaSource buildMediaSource( Uri uri, DataSource.Factory mediaDataSourceFactory, String formatHint, Context context) { int type; @@ -330,7 +329,8 @@ private void disposeAllPlayers() { } private void onDestroy() { - // The whole FlutterView is being destroyed. Here we release resources acquired for all instances + // The whole FlutterView is being destroyed. Here we release resources acquired for all + // instances // of VideoPlayer. Once https://github.com/flutter/flutter/issues/19358 is resolved this may // be replaced with just asserting that videoPlayers.isEmpty(). // https://github.com/flutter/flutter/issues/20989 tracks this. From 7ac0d6abf40ea8a57c8543ff2b3c042f480e8980 Mon Sep 17 00:00:00 2001 From: John McDole Date: Fri, 23 Aug 2019 10:23:23 -0700 Subject: [PATCH 7/7] Move commment --- packages/video_player/lib/video_player.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/video_player/lib/video_player.dart b/packages/video_player/lib/video_player.dart index 64de15ff70a9..059799b017b3 100644 --- a/packages/video_player/lib/video_player.dart +++ b/packages/video_player/lib/video_player.dart @@ -157,8 +157,9 @@ class VideoPlayerController extends ValueNotifier { /// the network. /// /// The URI for the video is given by the [dataSource] argument and must not be - /// null. The [formatHint] option allows the caller to specify the video - /// format in the case where it cannot be detected via url (Android only). + /// null. + /// **Android only**: The [formatHint] option allows the caller to override + /// the video format detection code. VideoPlayerController.network(this.dataSource, {this.formatHint}) : dataSourceType = DataSourceType.network, package = null,