浏览代码

播放器划分

gavin.chen 2 年之前
父节点
当前提交
b638ea6330

+ 1 - 0
lib/main.dart

@@ -1,6 +1,7 @@
 import 'package:fis_common/index.dart';
 import 'package:fis_vid/common/env.dart';
 import 'package:flutter/material.dart';
+import 'package:get/get.dart';
 import 'package:vid_player_demo/pages/single_image.dart/view.dart';
 import 'package:vid_player_demo/widgets/image_cache.dart';
 

+ 4 - 49
lib/pages/canvas_player/view.dart

@@ -1,10 +1,5 @@
-import 'package:fis_measure/view/player/control_board/control_board.dart';
-import 'package:fis_measure/view/player/controller.dart';
-import 'package:fis_measure/view/player/player.dart';
 import 'package:flutter/material.dart';
 
-import 'package:fis_vid/data_host/data_host.dart';
-
 class CanvasPlayerView extends StatefulWidget {
   const CanvasPlayerView({Key? key}) : super(key: key);
 
@@ -13,57 +8,19 @@ class CanvasPlayerView extends StatefulWidget {
 }
 
 class _CanvasPlayerViewState extends State<CanvasPlayerView> {
-  late final _dataHost = VidDataHost(
-      "http://cdn-bj.fis.plus/093BE20682B14BFB95D811F221A2B2FD.vid");
-  late final _playerController = VidPlayerController(dataHost: _dataHost);
-
   @override
   Widget build(BuildContext context) {
-    // _playerController.load().then((value) {
-    //   _playerController.play();
-    // });
-    return FutureBuilder(
-      future: _playerController.load(),
-      builder: (context, snapshot) {
-        if (snapshot.connectionState == ConnectionState.done) {
-          if (_playerController.canPlay) {
-            _playerController.play();
-            return buildPage(context);
-          } else {
-            return const Material(child: Center(child: Text("Load fail")));
-          }
-        } else {
-          return const Material(
-              child: Center(child: CircularProgressIndicator()));
-        }
-      },
-    );
-  }
-
-  Widget buildPage(BuildContext context) {
-    // const borderSide = BorderSide(color: Colors.grey);
-    final size = MediaQuery.of(context).size;
-    final w = size.width;
-    final h = w / 16 * 9;
     return Scaffold(
-      appBar: AppBar(),
+      appBar: AppBar(
+        title: const Text('基于Canvas的播放器'),
+      ),
       body: Center(
         child: Column(
           mainAxisSize: MainAxisSize.max,
           children: [
-            VidPlayer(
-              _playerController,
-              width: w,
-              height: h,
-            ),
             SizedBox(
               height: 160,
-              child: _playerController.totalFramesCount > 1
-                  ? VidPlayerControlBoard(
-                      _playerController,
-                      false,
-                    )
-                  : Container(),
+              child: Container(),
             ),
           ],
         ),
@@ -73,8 +30,6 @@ class _CanvasPlayerViewState extends State<CanvasPlayerView> {
 
   @override
   void dispose() {
-    _playerController.dispose();
-    _dataHost.release();
     super.dispose();
   }
 }

+ 128 - 0
lib/pages/canvas_player/widgets/canvas_player.dart

@@ -0,0 +1,128 @@
+import 'dart:typed_data';
+import 'package:fis_measure/view/frame_view/native/frame_view.dart';
+import 'package:fis_measure/view/player/controller.dart';
+import 'package:fis_measure/view/player/enums.dart';
+import 'package:fis_measure/view/player/events.dart';
+import 'package:flutter/material.dart';
+
+///基于Canvas组件的播放器
+class VidCanvasPlayer extends StatefulWidget {
+  const VidCanvasPlayer(
+    this.controller, {
+    Key? key,
+    this.width,
+    this.height,
+  }) : super(key: key);
+
+  final VidPlayerController controller;
+
+  final double? width;
+  final double? height;
+
+  @override
+  State<StatefulWidget> createState() => _VidCanvasPlayerState();
+}
+
+class _VidCanvasPlayerState extends State<VidCanvasPlayer> {
+  Uint8List? frameBytes;
+
+  @override
+  void initState() {
+    widget.controller.eventHandler.addListener(onControllerEvent);
+    super.initState();
+  }
+
+  @override
+  void didUpdateWidget(covariant VidCanvasPlayer oldWidget) {
+    if (oldWidget.controller != widget.controller) {
+      throw UnsupportedError("[VidTestPlayer] unsupport replace controller.");
+    }
+    super.didUpdateWidget(oldWidget);
+  }
+
+  void onControllerEvent(Object sender, VidPlayerEvent e) {
+    if (e is VidPlayerStatusChangeEvent) {
+      if (!widget.controller.hasView) {
+        setState(() {});
+      }
+    }
+    if (e is VidPlayerFrameIndexChangeEvent) {
+      onFrameChanged(e);
+    }
+    if (e is VidPlayerBrightnessChangeEvent) {
+      updateFrame();
+    }
+    if (e is VidPlayerContrastChangeEvent) {
+      updateFrame();
+    }
+  }
+
+  void onFrameChanged(VidPlayerFrameIndexChangeEvent e) {
+    setState(() {
+      frameBytes = e.bytes;
+    });
+  }
+
+  void updateFrame() {
+    setState(() {});
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    Widget? child;
+    switch (widget.controller.status) {
+      case VidPlayStatus.init:
+        child = Container(child: const Text("Loading"));
+        break;
+      case VidPlayStatus.ready:
+        child = Container(child: const Text("Ready"));
+        break;
+      case VidPlayStatus.loadFail:
+        child = Container(child: const Text("Load fail"));
+        break;
+      case VidPlayStatus.play:
+      case VidPlayStatus.pause:
+        // return buildFrameView(context);
+        // child = Container(
+        //   child: Text(
+        //     widget.controller.currentFrameIndex.toString(),
+        //   ),
+        // );
+        child = buildFrameView(context);
+        break;
+      case VidPlayStatus.stop:
+      case VidPlayStatus.dispose:
+        child = Container(child: const Text("Closed"));
+        break;
+    }
+    return buildBox(context, child);
+  }
+
+  Widget buildBox(BuildContext context, Widget child) {
+    return Container(
+      alignment: Alignment.center,
+      child: child,
+    );
+  }
+
+  Widget buildFrameView(BuildContext context) {
+    if (frameBytes != null) {
+      final size = MediaQuery.of(context).size;
+      return VidFrameView(
+        frameBytes!,
+        // width: widget.width,
+        // height: widget.height,
+        width: size.width,
+        height: size.height,
+      );
+    } else {
+      return Container();
+    }
+  }
+
+  @override
+  void dispose() {
+    widget.controller.eventHandler.removeListener(onControllerEvent);
+    super.dispose();
+  }
+}

+ 18 - 6
lib/pages/image_player/view.dart

@@ -1,9 +1,10 @@
-// ignore_for_file: avoid_print
-
 import 'package:fis_measure/index.dart';
 import 'package:fis_measure/interfaces/process/player/play_controller.dart';
 import 'package:fis_vid/data_host/data_host.dart';
 import 'package:flutter/material.dart';
+import 'package:vid_player_demo/widgets/image_cache.dart';
+
+import 'widgets/image_player.dart';
 
 class ImagePlayerView extends StatefulWidget {
   const ImagePlayerView({Key? key}) : super(key: key);
@@ -28,7 +29,7 @@ class _ImagePlayerViewState extends State<ImagePlayerView> {
     _playerController = VidPlayerController(dataHost: dataHost);
   }
 
-  void startPlay() {
+  void clickPlay() {
     print("${DateTime.now()} Click play");
     if (_ifInit) {
       playerController.play();
@@ -48,6 +49,11 @@ class _ImagePlayerViewState extends State<ImagePlayerView> {
     }
   }
 
+  void clickPause() {
+    print("${DateTime.now()} Click pause");
+    playerController.pause();
+  }
+
   @override
   void initState() {
     super.initState();
@@ -58,22 +64,28 @@ class _ImagePlayerViewState extends State<ImagePlayerView> {
   Widget build(BuildContext context) {
     return Scaffold(
       appBar: AppBar(
-        title: const Text('Image Player'),
+        title: const Text('基于Image的播放器'),
       ),
       body: Center(
         child: Column(
           mainAxisAlignment: MainAxisAlignment.spaceEvenly,
           children: [
+            const ShowImageCache(),
             ElevatedButton(
                 onPressed: () {
-                  startPlay();
+                  clickPlay();
                 },
                 child: const Text('Play')),
+            ElevatedButton(
+                onPressed: () {
+                  clickPause();
+                },
+                child: const Text('Pause')),
             SizedBox(
               width: 500,
               height: 500,
               child: RepaintBoundary(
-                child: VidPlayer(
+                child: VidImagePlayer(
                   _playerController as VidPlayerController,
                 ),
               ),

+ 128 - 0
lib/pages/image_player/widgets/image_player.dart

@@ -0,0 +1,128 @@
+import 'dart:typed_data';
+import 'package:fis_measure/view/frame_view/native/frame_view.dart';
+import 'package:fis_measure/view/player/controller.dart';
+import 'package:fis_measure/view/player/enums.dart';
+import 'package:fis_measure/view/player/events.dart';
+import 'package:flutter/material.dart';
+
+///基于图片组件的播放器
+class VidImagePlayer extends StatefulWidget {
+  const VidImagePlayer(
+    this.controller, {
+    Key? key,
+    this.width,
+    this.height,
+  }) : super(key: key);
+
+  final VidPlayerController controller;
+
+  final double? width;
+  final double? height;
+
+  @override
+  State<StatefulWidget> createState() => _VidImagePlayerState();
+}
+
+class _VidImagePlayerState extends State<VidImagePlayer> {
+  Uint8List? frameBytes;
+
+  @override
+  void initState() {
+    widget.controller.eventHandler.addListener(onControllerEvent);
+    super.initState();
+  }
+
+  @override
+  void didUpdateWidget(covariant VidImagePlayer oldWidget) {
+    if (oldWidget.controller != widget.controller) {
+      throw UnsupportedError("[VidTestPlayer] unsupport replace controller.");
+    }
+    super.didUpdateWidget(oldWidget);
+  }
+
+  void onControllerEvent(Object sender, VidPlayerEvent e) {
+    if (e is VidPlayerStatusChangeEvent) {
+      if (!widget.controller.hasView) {
+        setState(() {});
+      }
+    }
+    if (e is VidPlayerFrameIndexChangeEvent) {
+      onFrameChanged(e);
+    }
+    if (e is VidPlayerBrightnessChangeEvent) {
+      updateFrame();
+    }
+    if (e is VidPlayerContrastChangeEvent) {
+      updateFrame();
+    }
+  }
+
+  void onFrameChanged(VidPlayerFrameIndexChangeEvent e) {
+    setState(() {
+      frameBytes = e.bytes;
+    });
+  }
+
+  void updateFrame() {
+    setState(() {});
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    Widget? child;
+    switch (widget.controller.status) {
+      case VidPlayStatus.init:
+        child = Container(child: const Text("Loading"));
+        break;
+      case VidPlayStatus.ready:
+        child = Container(child: const Text("Ready"));
+        break;
+      case VidPlayStatus.loadFail:
+        child = Container(child: const Text("Load fail"));
+        break;
+      case VidPlayStatus.play:
+      case VidPlayStatus.pause:
+        // return buildFrameView(context);
+        // child = Container(
+        //   child: Text(
+        //     widget.controller.currentFrameIndex.toString(),
+        //   ),
+        // );
+        child = buildFrameView(context);
+        break;
+      case VidPlayStatus.stop:
+      case VidPlayStatus.dispose:
+        child = Container(child: const Text("Closed"));
+        break;
+    }
+    return buildBox(context, child);
+  }
+
+  Widget buildBox(BuildContext context, Widget child) {
+    return Container(
+      alignment: Alignment.center,
+      child: child,
+    );
+  }
+
+  Widget buildFrameView(BuildContext context) {
+    if (frameBytes != null) {
+      final size = MediaQuery.of(context).size;
+      return VidFrameView(
+        frameBytes!,
+        // width: widget.width,
+        // height: widget.height,
+        width: size.width,
+        height: size.height,
+      );
+    } else {
+      return Container();
+    }
+  }
+
+  @override
+  void dispose() {
+    widget.controller.eventHandler.removeListener(onControllerEvent);
+    super.dispose();
+  }
+}

+ 38 - 7
lib/widgets/image_cache.dart

@@ -2,24 +2,55 @@ import 'package:flutter/material.dart';
 
 import '../utils/utils.dart';
 
-class ShowImageCache extends StatelessWidget {
+class ShowImageCache extends StatefulWidget {
   const ShowImageCache({Key? key}) : super(key: key);
-  ImageCache? get imageCache => PaintingBinding.instance?.imageCache;
+
+  @override
+  _ShowImageCacheState createState() => _ShowImageCacheState();
+}
+
+class _ShowImageCacheState extends State<ShowImageCache> {
+  ImageCache? get imageCache => _imageCache;
+  ImageCache? _imageCache = PaintingBinding.instance?.imageCache;
+  @override
+  void initState() {
+    super.initState();
+    _imageCache = PaintingBinding.instance?.imageCache;
+  }
+
+  void refresh() {
+    setState(() {});
+  }
 
   @override
   Widget build(BuildContext context) {
     return Column(mainAxisAlignment: MainAxisAlignment.center, children: [
       const SizedBox(height: 8),
-      Text(
-        '当前图像缓存数量: ${imageCache?.currentSize ?? 0}',
-        style: const TextStyle(fontSize: 12),
-      ),
+      ElevatedButton(onPressed: refresh, child: const Text('刷新缓存信息')),
       const SizedBox(height: 8),
       Text(
-        '当前图像缓存大小: ${imageCache?.currentSizeBytes ?? 0}bytes = ${byte2MB(imageCache?.currentSizeBytes ?? 0)}MB',
+        '当前图像缓存数量: ${imageCache?.currentSize ?? 0} 大小: ${imageCache?.currentSizeBytes ?? 0}bytes = ${byte2MB(imageCache?.currentSizeBytes ?? 0)}MB',
         style: const TextStyle(fontSize: 12),
       ),
       const SizedBox(height: 8),
     ]);
   }
 }
+
+// ImageCache? get imageCache => PaintingBinding.instance?.imageCache;
+// @override
+//   Widget build(BuildContext context) {
+//     return Column(mainAxisAlignment: MainAxisAlignment.center, children: [
+//       const SizedBox(height: 8),
+//       Text(
+//         '当前图像缓存数量: ${imageCache?.currentSize ?? 0}',
+//         style: const TextStyle(fontSize: 12),
+//       ),
+//       const SizedBox(height: 8),
+//       Text(
+//         '当前图像缓存大小: ${imageCache?.currentSizeBytes ?? 0}bytes = ${byte2MB(imageCache?.currentSizeBytes ?? 0)}MB',
+//         style: const TextStyle(fontSize: 12),
+//       ),
+//       const SizedBox(height: 8),
+//     ]);
+//   }