This repository has been archived by the owner on Feb 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
/
video_player_platform_interface.dart
374 lines (314 loc) · 12.2 KB
/
video_player_platform_interface.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
/// The interface that implementations of video_player must implement.
///
/// Platform implementations should extend this class rather than implement it as `video_player`
/// does not consider newly added methods to be breaking changes. Extending this class
/// (using `extends`) ensures that the subclass will get the default implementation, while
/// platform implementations that `implements` this interface will be broken by newly added
/// [VideoPlayerPlatform] methods.
abstract class VideoPlayerPlatform extends PlatformInterface {
/// Constructs a VideoPlayerPlatform.
VideoPlayerPlatform() : super(token: _token);
static final Object _token = Object();
static VideoPlayerPlatform _instance = _PlaceholderImplementation();
/// The instance of [VideoPlayerPlatform] to use.
///
/// Defaults to a placeholder that does not override any methods, and thus
/// throws `UnimplementedError` in most cases.
static VideoPlayerPlatform get instance => _instance;
/// Platform-specific plugins should override this with their own
/// platform-specific class that extends [VideoPlayerPlatform] when they
/// register themselves.
static set instance(VideoPlayerPlatform instance) {
PlatformInterface.verify(instance, _token);
_instance = instance;
}
/// Initializes the platform interface and disposes all existing players.
///
/// This method is called when the plugin is first initialized
/// and on every full restart.
Future<void> init() {
throw UnimplementedError('init() has not been implemented.');
}
/// Clears one video.
Future<void> dispose(int textureId) {
throw UnimplementedError('dispose() has not been implemented.');
}
/// Creates an instance of a video player and returns its textureId.
Future<int?> create(DataSource dataSource) {
throw UnimplementedError('create() has not been implemented.');
}
/// Returns a Stream of [VideoEventType]s.
Stream<VideoEvent> videoEventsFor(int textureId) {
throw UnimplementedError('videoEventsFor() has not been implemented.');
}
/// Sets the looping attribute of the video.
Future<void> setLooping(int textureId, bool looping) {
throw UnimplementedError('setLooping() has not been implemented.');
}
/// Starts the video playback.
Future<void> play(int textureId) {
throw UnimplementedError('play() has not been implemented.');
}
/// Stops the video playback.
Future<void> pause(int textureId) {
throw UnimplementedError('pause() has not been implemented.');
}
/// Sets the volume to a range between 0.0 and 1.0.
Future<void> setVolume(int textureId, double volume) {
throw UnimplementedError('setVolume() has not been implemented.');
}
/// Sets the video position to a [Duration] from the start.
Future<void> seekTo(int textureId, Duration position) {
throw UnimplementedError('seekTo() has not been implemented.');
}
/// Sets the playback speed to a [speed] value indicating the playback rate.
Future<void> setPlaybackSpeed(int textureId, double speed) {
throw UnimplementedError('setPlaybackSpeed() has not been implemented.');
}
/// Gets the video position as [Duration] from the start.
Future<Duration> getPosition(int textureId) {
throw UnimplementedError('getPosition() has not been implemented.');
}
/// Returns a widget displaying the video with a given textureID.
Widget buildView(int textureId) {
throw UnimplementedError('buildView() has not been implemented.');
}
/// Sets the audio mode to mix with other sources
Future<void> setMixWithOthers(bool mixWithOthers) {
throw UnimplementedError('setMixWithOthers() has not been implemented.');
}
}
class _PlaceholderImplementation extends VideoPlayerPlatform {}
/// Description of the data source used to create an instance of
/// the video player.
class DataSource {
/// Constructs an instance of [DataSource].
///
/// The [sourceType] is always required.
///
/// The [uri] argument takes the form of `'https://example.com/video.mp4'` or
/// `'file:///absolute/path/to/local/video.mp4`.
///
/// The [formatHint] argument can be null.
///
/// The [asset] argument takes the form of `'assets/video.mp4'`.
///
/// The [package] argument must be non-null when the asset comes from a
/// package and null otherwise.
DataSource({
required this.sourceType,
this.uri,
this.formatHint,
this.asset,
this.package,
this.httpHeaders = const <String, String>{},
});
/// The way in which the video was originally loaded.
///
/// This has nothing to do with the video's file type. It's just the place
/// from which the video is fetched from.
final DataSourceType sourceType;
/// The URI to the video file.
///
/// This will be in different formats depending on the [DataSourceType] of
/// the original video.
final String? uri;
/// **Android only**. Will override the platform's generic file format
/// detection with whatever is set here.
final VideoFormat? formatHint;
/// HTTP headers used for the request to the [uri].
/// Only for [DataSourceType.network] videos.
/// Always empty for other video types.
Map<String, String> httpHeaders;
/// The name of the asset. Only set for [DataSourceType.asset] videos.
final String? asset;
/// The package that the asset was loaded from. Only set for
/// [DataSourceType.asset] videos.
final String? package;
}
/// The way in which the video was originally loaded.
///
/// This has nothing to do with the video's file type. It's just the place
/// from which the video is fetched from.
enum DataSourceType {
/// The video was included in the app's asset files.
asset,
/// The video was downloaded from the internet.
network,
/// The video was loaded off of the local filesystem.
file,
/// The video is available via contentUri. Android only.
contentUri,
}
/// The file format of the given video.
enum VideoFormat {
/// Dynamic Adaptive Streaming over HTTP, also known as MPEG-DASH.
dash,
/// HTTP Live Streaming.
hls,
/// Smooth Streaming.
ss,
/// Any format other than the other ones defined in this enum.
other,
}
/// Event emitted from the platform implementation.
@immutable
class VideoEvent {
/// Creates an instance of [VideoEvent].
///
/// The [eventType] argument is required.
///
/// Depending on the [eventType], the [duration], [size],
/// [rotationCorrection], and [buffered] arguments can be null.
// TODO(stuartmorgan): Temporarily suppress warnings about not using const
// in all of the other video player packages, fix this, and then update
// the other packages to use const.
// ignore: prefer_const_constructors_in_immutables
VideoEvent({
required this.eventType,
this.duration,
this.size,
this.rotationCorrection,
this.buffered,
});
/// The type of the event.
final VideoEventType eventType;
/// Duration of the video.
///
/// Only used if [eventType] is [VideoEventType.initialized].
final Duration? duration;
/// Size of the video.
///
/// Only used if [eventType] is [VideoEventType.initialized].
final Size? size;
/// Degrees to rotate the video (clockwise) so it is displayed correctly.
///
/// Only used if [eventType] is [VideoEventType.initialized].
final int? rotationCorrection;
/// Buffered parts of the video.
///
/// Only used if [eventType] is [VideoEventType.bufferingUpdate].
final List<DurationRange>? buffered;
@override
bool operator ==(Object other) {
return identical(this, other) ||
other is VideoEvent &&
runtimeType == other.runtimeType &&
eventType == other.eventType &&
duration == other.duration &&
size == other.size &&
rotationCorrection == other.rotationCorrection &&
listEquals(buffered, other.buffered);
}
@override
int get hashCode => Object.hash(
eventType,
duration,
size,
rotationCorrection,
buffered,
);
}
/// Type of the event.
///
/// Emitted by the platform implementation when the video is initialized or
/// completed or to communicate buffering events.
enum VideoEventType {
/// The video has been initialized.
initialized,
/// The playback has ended.
completed,
/// Updated information on the buffering state.
bufferingUpdate,
/// The video started to buffer.
bufferingStart,
/// The video stopped to buffer.
bufferingEnd,
/// An unknown event has been received.
unknown,
}
/// Describes a discrete segment of time within a video using a [start] and
/// [end] [Duration].
@immutable
class DurationRange {
/// Trusts that the given [start] and [end] are actually in order. They should
/// both be non-null.
// TODO(stuartmorgan): Temporarily suppress warnings about not using const
// in all of the other video player packages, fix this, and then update
// the other packages to use const.
// ignore: prefer_const_constructors_in_immutables
DurationRange(this.start, this.end);
/// The beginning of the segment described relative to the beginning of the
/// entire video. Should be shorter than or equal to [end].
///
/// For example, if the entire video is 4 minutes long and the range is from
/// 1:00-2:00, this should be a `Duration` of one minute.
final Duration start;
/// The end of the segment described as a duration relative to the beginning of
/// the entire video. This is expected to be non-null and longer than or equal
/// to [start].
///
/// For example, if the entire video is 4 minutes long and the range is from
/// 1:00-2:00, this should be a `Duration` of two minutes.
final Duration end;
/// Assumes that [duration] is the total length of the video that this
/// DurationRange is a segment form. It returns the percentage that [start] is
/// through the entire video.
///
/// For example, assume that the entire video is 4 minutes long. If [start] has
/// a duration of one minute, this will return `0.25` since the DurationRange
/// starts 25% of the way through the video's total length.
double startFraction(Duration duration) {
return start.inMilliseconds / duration.inMilliseconds;
}
/// Assumes that [duration] is the total length of the video that this
/// DurationRange is a segment form. It returns the percentage that [start] is
/// through the entire video.
///
/// For example, assume that the entire video is 4 minutes long. If [end] has a
/// duration of two minutes, this will return `0.5` since the DurationRange
/// ends 50% of the way through the video's total length.
double endFraction(Duration duration) {
return end.inMilliseconds / duration.inMilliseconds;
}
@override
String toString() =>
'${objectRuntimeType(this, 'DurationRange')}(start: $start, end: $end)';
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is DurationRange &&
runtimeType == other.runtimeType &&
start == other.start &&
end == other.end;
@override
int get hashCode => Object.hash(start, end);
}
/// [VideoPlayerOptions] can be optionally used to set additional player settings
@immutable
class VideoPlayerOptions {
/// set additional optional player settings
// TODO(stuartmorgan): Temporarily suppress warnings about not using const
// in all of the other video player packages, fix this, and then update
// the other packages to use const.
// ignore: prefer_const_constructors_in_immutables
VideoPlayerOptions({
this.mixWithOthers = false,
this.allowBackgroundPlayback = false,
});
/// Set this to true to keep playing video in background, when app goes in background.
/// The default value is false.
final bool allowBackgroundPlayback;
/// Set this to true to mix the video players audio with other audio sources.
/// The default value is false
///
/// Note: This option will be silently ignored in the web platform (there is
/// currently no way to implement this feature in this platform).
final bool mixWithOthers;
}