Browse Source

add(vid canvas player): 播放器改用canvas,提升性能

gavin.chen 2 years ago
parent
commit
76260910e8
2 changed files with 70 additions and 13 deletions
  1. 43 13
      lib/view/player/player.dart
  2. 27 0
      lib/view/vid_painter/vid_painter.dart

+ 43 - 13
lib/view/player/player.dart

@@ -1,7 +1,10 @@
+import 'dart:async';
 import 'dart:typed_data';
 
-import 'package:fis_measure/view/frame_view/native/frame_view.dart';
-import 'package:flutter/material.dart';
+// import 'package:fis_measure/view/frame_view/native/frame_view.dart';
+import 'package:fis_measure/view/vid_painter/vid_painter.dart';
+import 'package:flutter/material.dart' hide Image, decodeImageFromList;
+import 'dart:ui';
 
 import 'controller.dart';
 import 'enums.dart';
@@ -26,7 +29,8 @@ class VidPlayer extends StatefulWidget {
 
 class _VidPlayerState extends State<VidPlayer> {
   Uint8List? frameBytes;
-
+  Image? image;
+  int frameIndex = 0;
   @override
   void initState() {
     widget.controller.eventHandler.addListener(onControllerEvent);
@@ -59,15 +63,41 @@ class _VidPlayerState extends State<VidPlayer> {
   }
 
   void onFrameChanged(VidPlayerFrameIndexChangeEvent e) {
-    setState(() {
-      frameBytes = e.bytes;
-    });
+    loadFrame(e);
+  }
+
+  void loadFrame(VidPlayerFrameIndexChangeEvent e) async {
+    frameIndex = e.index;
+    image = await _loadImage(e.bytes);
+    setState(() {});
   }
 
   void updateFrame() {
     setState(() {});
   }
 
+  Future<Image> _loadImage(Uint8List bytes) async {
+    final Completer<Image> completer = Completer<Image>();
+    decodeVidFromList(bytes, (Image image) => completer.complete(image));
+    // decodeImageFromList(bytes, (Image image) => completer.complete(image));
+    return completer.future;
+  }
+
+  void decodeVidFromList(Uint8List bytes, ImageDecoderCallback callback) async {
+    ImmutableBuffer.fromUint8List(bytes).then((ImmutableBuffer buffer) async {
+      final ImageDescriptor descriptor = await ImageDescriptor.encoded(buffer);
+      descriptor.instantiateCodec().then((Codec codec) {
+        final Future<FrameInfo> frameInfo = codec.getNextFrame();
+        codec.dispose();
+        return frameInfo;
+      }).then((FrameInfo frameInfo) {
+        buffer.dispose();
+        descriptor.dispose();
+        return callback(frameInfo.image);
+      });
+    });
+  }
+
   @override
   Widget build(BuildContext context) {
     Widget? child;
@@ -107,14 +137,14 @@ class _VidPlayerState extends State<VidPlayer> {
   }
 
   Widget buildFrameView(BuildContext context) {
-    if (frameBytes != null) {
+    if (image != null) {
       final size = MediaQuery.of(context).size;
-      return VidFrameView(
-        frameBytes!,
-        // width: widget.width,
-        // height: widget.height,
-        width: size.width,
-        height: size.height,
+      return RepaintBoundary(
+        child: CustomPaint(
+          painter: VidPainter(image: image!, frameIndex: frameIndex),
+          isComplex: false, //是否为复杂图像(true会缓存)
+          size: size,
+        ),
       );
     } else {
       return Container();

+ 27 - 0
lib/view/vid_painter/vid_painter.dart

@@ -0,0 +1,27 @@
+import 'package:flutter/material.dart';
+import 'dart:ui' as ui;
+
+class VidPainter extends CustomPainter {
+  VidPainter({required this.image, required this.frameIndex});
+  ui.Image image;
+  int frameIndex;
+
+  @override
+  void paint(Canvas canvas, Size size) async {
+    final double scale = size.width / image.width;
+    final double offsetY = (size.height - image.height * scale) / 2;
+    canvas.save();
+    canvas.drawImageRect(
+        image,
+        Rect.fromLTWH(0, 0, image.width.toDouble(), image.height.toDouble()),
+        Rect.fromLTWH(0, offsetY, size.width, image.height * scale),
+        Paint());
+    canvas.restore();
+    image.dispose();
+  }
+
+  @override
+  bool shouldRepaint(covariant VidPainter oldDelegate) {
+    return oldDelegate.frameIndex != frameIndex;
+  }
+}