Skip to content

Commit

Permalink
[plugin] Added Texture based Video widget for Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
alexmercerind committed Aug 10, 2021
1 parent 89ecd08 commit bb34431
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 95 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@ Under progress or planned features (irrespective of order)...

First of all, thanks to the [VideoLAN](https://www.videolan.org) team for creating [libVLC](https://github.com/videolan/vlc) & [libVLC++](https://github.com/videolan/libvlcpp). Really great guys really great at their work.

[@jnschulze](https://github.com/jnschulze) for his awesome contributions to Flutter engine like adding texture support.

Thanks to following members of libVLC community (irrespective of the order) to give me bit of look & advice about how things work:

- [@jeremyVignelles](https://github.com/jeremyVignelles)
Expand Down
37 changes: 18 additions & 19 deletions lib/dart_vlc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export 'package:dart_vlc/src/widgets/video.dart';
/// Platform channel for using [Texture] & flutter::TextureRegistrar on Windows.
final MethodChannel _channel = MethodChannel('dart_vlc');


/// A [Player] to open & play a [Media] or [Playlist] from file, network or asset.
///
/// Use [Player] constructor to create a new instance of a [Player].
Expand Down Expand Up @@ -50,28 +49,28 @@ final MethodChannel _channel = MethodChannel('dart_vlc');
class Player extends FFI.Player {
int? textureId;

Player({
required int id,
int videoWidth: 0,
int videoHeight: 0,
List<String>? commandlineArguments
}) : super(id: id, videoWidth: videoWidth, videoHeight: videoHeight, commandlineArguments: commandlineArguments) {
Player(
{required int id,
int videoWidth: 0,
int videoHeight: 0,
List<String>? commandlineArguments})
: super(
id: id,
videoWidth: videoWidth,
videoHeight: videoHeight,
commandlineArguments: commandlineArguments) {
if (this.videoHeight > 0 && this.videoWidth > 0 && Platform.isWindows) {
() async {
this.textureId = await _channel.invokeMethod(
'Player.onVideo',
{
'playerId': this.id,
'videoWidth': this.videoWidth,
'videoHeight': this.videoHeight
}
);
this.textureId = await _channel.invokeMethod('Player.onVideo', {
'playerId': this.id,
'videoWidth': this.videoWidth,
'videoHeight': this.videoHeight
});
}();
}
}
}


/// Initializes the DartVLC plugin.
///
/// ```dart
Expand All @@ -86,13 +85,13 @@ abstract class DartVLC {
FFI.videoFrameCallback = (int playerId, Uint8List videoFrame) {
if (videoStreamControllers[playerId] != null &&
FFI.players[playerId] != null) {
if (!videoStreamControllers[playerId]!.isClosed) {
videoStreamControllers[playerId]!.add(new VideoFrame(
if (!videoStreamControllers[playerId]!.isClosed) {
videoStreamControllers[playerId]!.add(new VideoFrame(
playerId: playerId,
videoWidth: FFI.players[playerId]!.videoWidth,
videoHeight: FFI.players[playerId]!.videoHeight,
byteArray: videoFrame));
}
}
}
};
if (Platform.isWindows) {
Expand Down
38 changes: 0 additions & 38 deletions lib/src/experimental/video.dart

This file was deleted.

7 changes: 5 additions & 2 deletions lib/src/widgets/controls.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@ class ControlState extends State<Control> with SingleTickerProviderStateMixin {
super.initState();
this.playPauseController = new AnimationController(
vsync: this, duration: Duration(milliseconds: 400));
this.playPauseStream = players[widget.playerId]!.playbackStream.listen((event) => this.setPlaybackMode(event.isPlaying));
if (players[widget.playerId]!.playback.isPlaying) this.playPauseController.forward();
this.playPauseStream = players[widget.playerId]!
.playbackStream
.listen((event) => this.setPlaybackMode(event.isPlaying));
if (players[widget.playerId]!.playback.isPlaying)
this.playPauseController.forward();
}

@override
Expand Down
105 changes: 69 additions & 36 deletions lib/src/widgets/video.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// ignore_for_file: implementation_imports
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:dart_vlc_ffi/src/player.dart';
import 'package:dart_vlc_ffi/src/player.dart' hide Player;
import 'package:dart_vlc/dart_vlc.dart';
import 'package:dart_vlc/src/widgets/controls.dart';

/// Internally used map to keep [GlobalKey]s for [Video]'s [ControlState]s.
Expand Down Expand Up @@ -69,6 +71,9 @@ class Video extends StatefulWidget {
/// Scale.
final double scale;

/// Filter quality.
final FilterQuality filterQuality;

// Built-In video controls.
final bool showControls;

Expand Down Expand Up @@ -127,6 +132,7 @@ class Video extends StatefulWidget {
this.progressBarThumbGlowRadius = 15.0,
this.showTimeLeft = false,
this.progressBarTextStyle = const TextStyle(),
this.filterQuality = FilterQuality.low,
Key? key,
}) : super(key: key);

Expand Down Expand Up @@ -155,58 +161,85 @@ class VideoState extends State<Video> {
height: widget.height,
width: widget.width,
scale: widget.scale,
filterQuality: FilterQuality.low,
filterQuality: widget.filterQuality,
);
}

@override
Future<void> dispose() async {
super.dispose();
await videoStreamControllers[widget.playerId]?.close();
if (Platform.isWindows) {
} else {
await videoStreamControllers[widget.playerId]?.close();
}
}

@override
void initState() {
super.initState();
if (widget.showControls) controls[widget.playerId] = this.controlKey;
videoStreamControllers[widget.playerId] =
new StreamController<VideoFrame>.broadcast();
videoStreamControllers[widget.playerId]?.stream
.listen((VideoFrame videoFrame) async {
this.videoFrameRawImage = await this.getVideoFrameRawImage(videoFrame);
if (this.mounted) {
this.setState(() {});
}
});
if (Platform.isWindows) {
} else {
if (widget.showControls) controls[widget.playerId] = this.controlKey;
videoStreamControllers[widget.playerId] =
new StreamController<VideoFrame>.broadcast();
videoStreamControllers[widget.playerId]
?.stream
.listen((VideoFrame videoFrame) async {
this.videoFrameRawImage = await this.getVideoFrameRawImage(videoFrame);
if (this.mounted) {
this.setState(() {});
}
});
}
}

@override
Widget build(BuildContext context) {
if (widget.showControls) {
return Control(
key: this.controlKey,
playerId: widget.playerId,
height: widget.height,
width: widget.width,
progressBarThumbRadius: widget.progressBarThumbRadius,
progressBarThumbGlowRadius: widget.progressBarThumbGlowRadius,
progressBarActiveColor: widget.progressBarActiveColor,
progressBarInactiveColor: widget.progressBarInactiveColor,
progressBarThumbColor: widget.progressBarThumbColor,
progressBarThumbGlowColor: widget.progressBarThumbGlowColor,
volumeActiveColor: widget.volumeActiveColor,
volumeInactiveColor: widget.volumeInactiveColor,
volumeBackgroundColor: widget.volumeBackgroundColor,
volumeThumbColor: widget.volumeThumbColor,
showTimeLeft: widget.showTimeLeft,
progressBarTextStyle: widget.progressBarTextStyle,
child: this.videoFrameRawImage ??
Container(
color: Colors.black,
height: widget.height,
width: widget.width,
),
);
key: this.controlKey,
playerId: widget.playerId,
height: widget.height,
width: widget.width,
progressBarThumbRadius: widget.progressBarThumbRadius,
progressBarThumbGlowRadius: widget.progressBarThumbGlowRadius,
progressBarActiveColor: widget.progressBarActiveColor,
progressBarInactiveColor: widget.progressBarInactiveColor,
progressBarThumbColor: widget.progressBarThumbColor,
progressBarThumbGlowColor: widget.progressBarThumbGlowColor,
volumeActiveColor: widget.volumeActiveColor,
volumeInactiveColor: widget.volumeInactiveColor,
volumeBackgroundColor: widget.volumeBackgroundColor,
volumeThumbColor: widget.volumeThumbColor,
showTimeLeft: widget.showTimeLeft,
progressBarTextStyle: widget.progressBarTextStyle,
child: Platform.isWindows
? (
/* Using flutter::TextureRegistrar for Windows. */
((players[widget.playerId]! as Player).textureId != null)
? Container(
width: widget.width,
height: widget.height,
color: Colors.black,
child: Texture(
textureId: (players[widget.playerId]! as Player)
.textureId!,
filterQuality: widget.filterQuality,
),
)
: Container(
width: widget.width,
height: widget.height,
color: Colors.black,
))
: (
/* Using NativePorts for Linux. */
this.videoFrameRawImage ??
Container(
color: Colors.black,
height: widget.height,
width: widget.width,
)));
} else {
return this.videoFrameRawImage ??
Container(
Expand Down

0 comments on commit bb34431

Please sign in to comment.