Skip to content

Commit

Permalink
Fix textures on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
jnschulze committed Aug 11, 2021
1 parent 185d383 commit 9373971
Show file tree
Hide file tree
Showing 4 changed files with 243 additions and 163 deletions.
3 changes: 3 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
BasedOnStyle: Google
DerivePointerAlignment: false
PointerAlignment: Left
23 changes: 17 additions & 6 deletions lib/dart_vlc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// ignore_for_file: implementation_imports
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

import 'package:dart_vlc/src/widgets/video.dart';
Expand Down Expand Up @@ -47,7 +48,7 @@ final MethodChannel _channel = MethodChannel('dart_vlc');
/// Use various methods & event streams avaiable to control & listen to events of the playback.
///
class Player extends FFI.Player {
int? textureId;
final ValueNotifier<int?> textureId = ValueNotifier<int?>(null);

Player(
{required int id,
Expand All @@ -59,16 +60,26 @@ class Player extends FFI.Player {
videoWidth: videoWidth,
videoHeight: videoHeight,
commandlineArguments: commandlineArguments) {
if (this.videoHeight > 0 && this.videoWidth > 0 && Platform.isWindows) {
if (videoHeight > 0 && videoWidth > 0 && Platform.isWindows) {
() async {
this.textureId = await _channel.invokeMethod('Player.onVideo', {
'playerId': this.id,
'videoWidth': this.videoWidth,
'videoHeight': this.videoHeight
textureId.value = await _channel.invokeMethod('createTexture', {
'playerId': id,
'videoWidth': videoWidth,
'videoHeight': videoHeight
});
}();
}
}

@override
void dispose() async {
if (textureId.value != null) {
await _channel.invokeMethod('disposeTexture', {'playerId': id});
textureId.value = null;
}

super.dispose();
}
}

/// Initializes the DartVLC plugin.
Expand Down
162 changes: 84 additions & 78 deletions lib/src/widgets/video.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ class VideoFrame {
/// A global [Key] may be used for this purpose.
///
class Video extends StatefulWidget {
/// Id of the [Player] whose [Video] output should be shown.
final int playerId;
/// The [Player] whose [Video] output should be shown.
final Player player;

/// Width of the viewport.
final double width;
Expand Down Expand Up @@ -115,7 +115,8 @@ class Video extends StatefulWidget {
final bool showTimeLeft;

Video({
required this.playerId,
@Deprecated('playerId is deprecated. Use player instead.') int? playerId,
Player? player,
required this.width,
required this.height,
this.scale: 1.0,
Expand All @@ -134,15 +135,74 @@ class Video extends StatefulWidget {
this.progressBarTextStyle = const TextStyle(),
this.filterQuality = FilterQuality.low,
Key? key,
}) : super(key: key);
}) : player = player ?? players[playerId]! as Player,
super(key: key);

VideoState createState() => VideoState();
_VideoStateBase createState() =>
Platform.isWindows ? _VideoStateTexture() : _VideoStateFallback();
}

class VideoState extends State<Video> {
Widget? videoFrameRawImage;
abstract class _VideoStateBase extends State<Video> {
GlobalKey<ControlState> controlKey = new GlobalKey<ControlState>();

int get playerId => widget.player.id;

@override
void initState() {
if (widget.showControls) controls[playerId] = controlKey;
super.initState();
}

@override
Widget build(BuildContext context) {
if (widget.showControls) {
return Control(
key: controlKey,
playerId: 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: present());
}
return present();
}

Widget present();
}

class _VideoStateTexture extends _VideoStateBase {
Widget present() {
return ValueListenableBuilder<int?>(
valueListenable: widget.player.textureId,
builder: (context, textureId, _) {
return Container(
width: widget.width,
height: widget.height,
color: Colors.black,
child: textureId != null
? Texture(
textureId: textureId,
filterQuality: widget.filterQuality,
)
: null);
});
}
}

class _VideoStateFallback extends _VideoStateBase {
Widget? videoFrameRawImage;

Future<RawImage> getVideoFrameRawImage(VideoFrame videoFrame) async {
Completer<ui.Image> imageCompleter = new Completer<ui.Image>();
ui.decodeImageFromPixels(
Expand All @@ -156,7 +216,7 @@ class VideoState extends State<Video> {
targetHeight: widget.height.toInt(),
);
ui.Image image = await imageCompleter.future;
return new RawImage(
return RawImage(
image: image,
height: widget.height,
width: widget.width,
Expand All @@ -167,86 +227,32 @@ class VideoState extends State<Video> {

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

@override
void initState() {
videoStreamControllers[playerId] = StreamController<VideoFrame>.broadcast();
videoStreamControllers[playerId]
?.stream
.listen((VideoFrame videoFrame) async {
videoFrameRawImage = await getVideoFrameRawImage(videoFrame);
});

super.initState();
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(() {});
}
});

if (mounted) {
setState(() {});
}
}

@override
Widget build(BuildContext context) {
if (widget.showControls) {
return Control(
key: this.controlKey,
playerId: widget.playerId,
Widget present() {
return videoFrameRawImage ??
Container(
color: Colors.black,
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(
color: Colors.black,
height: widget.height,
width: widget.width,
);
}
);
}
}
Loading

0 comments on commit 9373971

Please sign in to comment.