Skip to content

Commit 7f37ed5

Browse files
jtmcdoleChris Yang
authored and
Chris Yang
committed
[video_player] Added formatHint to to override video format on Android (flutter#2003)
Solve: flutter/flutter#39076
1 parent 18352b2 commit 7f37ed5

File tree

5 files changed

+68
-10
lines changed

5 files changed

+68
-10
lines changed

packages/video_player/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.10.2
2+
3+
* **Android Only** Adds optional VideoFormat used to signal what format the plugin should try.
4+
15
## 0.10.1+7
26

37
* Fix tests by ignoring deprecated member use.

packages/video_player/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerPlugin.java

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@
5353
public class VideoPlayerPlugin implements MethodCallHandler {
5454

5555
private static class VideoPlayer {
56+
private static final String FORMAT_SS = "ss";
57+
private static final String FORMAT_DASH = "dash";
58+
private static final String FORMAT_HLS = "hls";
59+
private static final String FORMAT_OTHER = "other";
5660

5761
private SimpleExoPlayer exoPlayer;
5862

@@ -71,7 +75,8 @@ private static class VideoPlayer {
7175
EventChannel eventChannel,
7276
TextureRegistry.SurfaceTextureEntry textureEntry,
7377
String dataSource,
74-
Result result) {
78+
Result result,
79+
String formatHint) {
7580
this.eventChannel = eventChannel;
7681
this.textureEntry = textureEntry;
7782

@@ -93,7 +98,7 @@ private static class VideoPlayer {
9398
true);
9499
}
95100

96-
MediaSource mediaSource = buildMediaSource(uri, dataSourceFactory, context);
101+
MediaSource mediaSource = buildMediaSource(uri, dataSourceFactory, formatHint, context);
97102
exoPlayer.prepare(mediaSource);
98103

99104
setupVideoPlayer(eventChannel, textureEntry, result);
@@ -108,8 +113,29 @@ private static boolean isFileOrAsset(Uri uri) {
108113
}
109114

110115
private MediaSource buildMediaSource(
111-
Uri uri, DataSource.Factory mediaDataSourceFactory, Context context) {
112-
int type = Util.inferContentType(uri.getLastPathSegment());
116+
Uri uri, DataSource.Factory mediaDataSourceFactory, String formatHint, Context context) {
117+
int type;
118+
if (formatHint == null) {
119+
type = Util.inferContentType(uri.getLastPathSegment());
120+
} else {
121+
switch (formatHint) {
122+
case FORMAT_SS:
123+
type = C.TYPE_SS;
124+
break;
125+
case FORMAT_DASH:
126+
type = C.TYPE_DASH;
127+
break;
128+
case FORMAT_HLS:
129+
type = C.TYPE_HLS;
130+
break;
131+
case FORMAT_OTHER:
132+
type = C.TYPE_OTHER;
133+
break;
134+
default:
135+
type = -1;
136+
break;
137+
}
138+
}
113139
switch (type) {
114140
case C.TYPE_SS:
115141
return new SsMediaSource.Factory(
@@ -303,7 +329,8 @@ private void disposeAllPlayers() {
303329
}
304330

305331
private void onDestroy() {
306-
// The whole FlutterView is being destroyed. Here we release resources acquired for all instances
332+
// The whole FlutterView is being destroyed. Here we release resources acquired for all
333+
// instances
307334
// of VideoPlayer. Once https://github.com/flutter/flutter/issues/19358 is resolved this may
308335
// be replaced with just asserting that videoPlayers.isEmpty().
309336
// https://github.com/flutter/flutter/issues/20989 tracks this.
@@ -343,12 +370,18 @@ public void onMethodCall(MethodCall call, Result result) {
343370
eventChannel,
344371
handle,
345372
"asset:///" + assetLookupKey,
346-
result);
373+
result,
374+
null);
347375
videoPlayers.put(handle.id(), player);
348376
} else {
349377
player =
350378
new VideoPlayer(
351-
registrar.context(), eventChannel, handle, call.argument("uri"), result);
379+
registrar.context(),
380+
eventChannel,
381+
handle,
382+
call.argument("uri"),
383+
result,
384+
call.argument("formatHint"));
352385
videoPlayers.put(handle.id(), player);
353386
}
354387
break;

packages/video_player/lib/video_player.dart

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class DurationRange {
3232
String toString() => '$runtimeType(start: $start, end: $end)';
3333
}
3434

35+
enum VideoFormat { dash, hls, ss, other }
36+
3537
/// The duration, current position, buffering state, error state and settings
3638
/// of a [VideoPlayerController].
3739
class VideoPlayerValue {
@@ -148,14 +150,17 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
148150
/// package and null otherwise.
149151
VideoPlayerController.asset(this.dataSource, {this.package})
150152
: dataSourceType = DataSourceType.asset,
153+
formatHint = null,
151154
super(VideoPlayerValue(duration: null));
152155

153156
/// Constructs a [VideoPlayerController] playing a video from obtained from
154157
/// the network.
155158
///
156159
/// The URI for the video is given by the [dataSource] argument and must not be
157160
/// null.
158-
VideoPlayerController.network(this.dataSource)
161+
/// **Android only**: The [formatHint] option allows the caller to override
162+
/// the video format detection code.
163+
VideoPlayerController.network(this.dataSource, {this.formatHint})
159164
: dataSourceType = DataSourceType.network,
160165
package = null,
161166
super(VideoPlayerValue(duration: null));
@@ -168,10 +173,12 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
168173
: dataSource = 'file://${file.path}',
169174
dataSourceType = DataSourceType.file,
170175
package = null,
176+
formatHint = null,
171177
super(VideoPlayerValue(duration: null));
172178

173179
int _textureId;
174180
final String dataSource;
181+
final VideoFormat formatHint;
175182

176183
/// Describes the type of data source this [VideoPlayerController]
177184
/// is constructed with.
@@ -203,7 +210,10 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
203210
dataSourceDescription = <String, dynamic>{'uri': dataSource};
204211
break;
205212
case DataSourceType.file:
206-
dataSourceDescription = <String, dynamic>{'uri': dataSource};
213+
dataSourceDescription = <String, dynamic>{
214+
'uri': dataSource,
215+
'formatHint': _videoFormatStringMap[formatHint]
216+
};
207217
}
208218
final Map<String, dynamic> response =
209219
await _channel.invokeMapMethod<String, dynamic>(
@@ -397,6 +407,14 @@ class VideoPlayerController extends ValueNotifier<VideoPlayerValue> {
397407
value = value.copyWith(volume: volume.clamp(0.0, 1.0));
398408
await _applyVolume();
399409
}
410+
411+
static const Map<VideoFormat, String> _videoFormatStringMap =
412+
<VideoFormat, String>{
413+
VideoFormat.ss: 'ss',
414+
VideoFormat.hls: 'hls',
415+
VideoFormat.dash: 'dash',
416+
VideoFormat.other: 'other',
417+
};
400418
}
401419

402420
class _VideoAppLifeCycleObserver extends Object with WidgetsBindingObserver {

packages/video_player/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: video_player
22
description: Flutter plugin for displaying inline video with other Flutter
33
widgets on Android and iOS.
44
author: Flutter Team <[email protected]>
5-
version: 0.10.1+7
5+
version: 0.10.2
66
homepage: https://github.com/flutter/plugins/tree/master/packages/video_player
77

88
flutter:

packages/video_player/test/video_player_test.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ class FakeController extends ValueNotifier<VideoPlayerValue>
4141
Future<void> play() async {}
4242
@override
4343
Future<void> setLooping(bool looping) async {}
44+
45+
@override
46+
VideoFormat get formatHint => null;
4447
}
4548

4649
void main() {

0 commit comments

Comments
 (0)