diff --git a/packages/video_player/CHANGELOG.md b/packages/video_player/CHANGELOG.md index 795d97fdb960..abf41afcfbb0 100644 --- a/packages/video_player/CHANGELOG.md +++ b/packages/video_player/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.10.2 + +* **Android Only** 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/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..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; @@ -71,7 +75,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 +98,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,8 +113,29 @@ private static boolean isFileOrAsset(Uri uri) { } private MediaSource buildMediaSource( - Uri uri, DataSource.Factory mediaDataSourceFactory, Context context) { - int type = Util.inferContentType(uri.getLastPathSegment()); + Uri uri, DataSource.Factory mediaDataSourceFactory, String formatHint, Context context) { + int type; + if (formatHint == null) { + type = Util.inferContentType(uri.getLastPathSegment()); + } else { + 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( @@ -303,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. @@ -343,12 +370,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..059799b017b3 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,9 @@ class VideoPlayerController extends ValueNotifier { /// /// The URI for the video is given by the [dataSource] argument and must not be /// null. - VideoPlayerController.network(this.dataSource) + /// **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, super(VideoPlayerValue(duration: null)); @@ -168,10 +173,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 +210,10 @@ class VideoPlayerController extends ValueNotifier { dataSourceDescription = {'uri': dataSource}; break; case DataSourceType.file: - dataSourceDescription = {'uri': dataSource}; + dataSourceDescription = { + 'uri': dataSource, + 'formatHint': _videoFormatStringMap[formatHint] + }; } final Map response = await _channel.invokeMapMethod( @@ -397,6 +407,14 @@ class VideoPlayerController extends ValueNotifier { value = value.copyWith(volume: volume.clamp(0.0, 1.0)); await _applyVolume(); } + + static const Map _videoFormatStringMap = + { + VideoFormat.ss: 'ss', + VideoFormat.hls: 'hls', + VideoFormat.dash: 'dash', + VideoFormat.other: 'other', + }; } class _VideoAppLifeCycleObserver extends Object with WidgetsBindingObserver { 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: 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() {