Flutter Windows通过嵌入Native窗口实现渲染视频

Flutter视频渲染系列

第一章 Android使用Texture渲染视频
第二章 Windows使用Texture渲染视频
第三章 Linux使用Texture渲染视频
第四章 全平台FFI+CustomPainter渲染视频
第五章 Windows使用Native窗口渲染视频(本章)


文章目录

  • Flutter视频渲染系列
  • 前言
  • 一、有何优势?
    • 1、支持任意渲染技术
    • 2、解决空域问题
  • 二、如何实现
    • 1、添加flutter_native_view 插件
      • (1)添加依赖
      • (2)添加native初始化代码
      • (3)添加dart初始化代码
      • 使用示例
    • 2、创建win32窗口
      • (1)、问题
        • ①Windows消息循环在主线程
        • ②flutter ui线程不是主线程
      • (2)、解决方法
        • ①Isolate运行消息循环
        • ②PostThreadMessage通信
        • ③消息循环中创建窗口
    • 3、封装成Native控件
    • 4、ffi使用句柄渲染视频
  • 三、完整代码
  • 四、效果预览
  • 总结


前言

使用flutter在Windows上渲染视频,目前掌握的至少有2种方法(第二章、第四章),但是性能都不是最佳,而且需要将数据转换成rgba才能渲染。如果能使用win32窗口,直接通过句柄渲染,那就可以达到与原生Windows渲染使用一致的效果,可以使用sdl渲染yuv,以及dxva2解码后d3d9表面直接渲染到窗口全程在gpu上操作。本文将介绍如何在flutter程序嵌入win32窗口并且渲染视频。但是需要注意的是目前的实现只支持win10及以上版本


一、有何优势?

1、支持任意渲染技术

因为是win32窗口,我们拿到hWnd句柄后可以有多种渲染视频的方法,比如使用sdl渲染yuv、或者opengl渲染yuv、还可以使用d3d9渲染yuv,以及最佳性能的dxva2+d3d9渲染也能使用。

2、解决空域问题

空域问题是两种不同的渲染技术在同个窗口不能兼容,只能相互覆盖。本文的实现方法不存在此问题,嵌入的win32窗口上面可以渲染flutter界面。


二、如何实现

1、添加flutter_native_view 插件

flutter_native_view 实现了win32窗口嵌入的容器。只需要提供窗口句柄,flutter_native_view就能将窗口作为控件加入到flutter界面。
具体添加方法使用方法需要查看https://pub-web.flutter-io.cn/packages/flutter_native_view
添加插件有一定的步骤请仔细阅读上述链接的指引,或flutter_native_view: ^0.0.2 版本的添加示例如下

(1)添加依赖

在pubspec.yaml添加依赖

flutter_native_view: ^0.0.2

在这里插入图片描述

(2)添加native初始化代码

在Windows主函数添加初始化代码如下如图:

#include "flutter_native_view/flutter_native_view_plugin.h"
flutternativeview::NativeViewContainer::GetInstance()->Create();

在这里插入图片描述

(3)添加dart初始化代码

在main.dart添加初始化代码

import 'package:flutter_native_view/flutter_native_view.dart';
WidgetsFlutterBinding.ensureInitialized();
await FlutterNativeView.ensureInitialized();

在这里插入图片描述

使用示例

创建controller,关联窗口句柄

final controller = NativeViewController(//需要嵌入的窗口句柄handle: hwnd,hitTestBehavior: HitTestBehavior.translucent,);

NativeView关联controller

//作为控件放在需要的地方
LayoutBuilder(builder: (context, constraints) = > NativeView(controller: controller,width : constraints.maxWidth,height : constraints.maxHeight,),),

2、创建win32窗口

需要自己实现win32窗口的创建,使用win32插件可以全程用dart实现。
具体的实现就是调用win32 api,这里就省略了,就说几个关键点吧。

win32: ^5.0.3 
import 'package:win32/win32.dart';

(1)、问题

①Windows消息循环在主线程

在这里插入图片描述

②flutter ui线程不是主线程

flutter ui线程是dart代码运行的线程,但是和主线程不是同一个线程。所以创建win32窗口时不能在dart ui线程,否则界面会卡死。

(2)、解决方法

本文使用的是比较简单的实现方式,全部用dart实现,单独开一个线程跑消息循环,并管理子窗口的创建销毁。要求较高的朋友,可以尝试实现在main.cpp的消息循环管理子窗口,或者通过钩子完全用dart实现主线程创建窗口。

①Isolate运行消息循环

isolateFuture函数,就是运行isolate的封装,略。_receivePort是ReceivePort

 final sendPort = _receivePort.sendPort;isolateFuture(() {//发送当前线程id给ui线程sendPort.send([msgID, GetCurrentThreadId()]);final msg = calloc.allocate<MSG>(sizeOf<MSG>()); while (true) {GetMessage(msg, NULL, 0, 0);TranslateMessage(msg);DispatchMessage(msg);}calloc.free(msg);});  

②PostThreadMessage通信

//通过消息循环的线程id发送消息
PostThreadMessage(_nativeWindowMsgLoopThread, WM_USER + 1, 0, 0);

③消息循环中创建窗口

if (msg.ref.message == WM_USER + 1) {final userData =calloc.allocate<WindowUserData>(sizeOf<WindowUserData>());final hwnd = CreateWindowEx(0,className,windowName,0,0,0,0,0,0,0,0,userData,);//将窗口句柄发送回ui线程    sendPort.send([msg.ref.wParam, hwnd]);
}

3、封装成Native控件

将上述的内容结合起来封装成一个可以直接使用的控件,控件实现略。

/// Windows原生窗口控件。依赖于flutter_native_view插件。
/// 可以当成普通控件使用,不会有空域问题,窗口区域上面可以显示flutter控件。
class WindowsNativeWidget extends StatelessWidget {final Color color;//窗口背景色final Function(int)? onHandleCreated;//句柄创建的回调WindowsNativeWidget({this.onHandleCreated, this.color = Colors.white});
}

4、ffi使用句柄渲染视频

通过封装的Native控件拿到窗口句柄,我们只需要通过ffi设置给c++,然后就可以直接使用窗口句柄渲染视频了。比如使用sdl或者opengl、或者d3d渲染都可以。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


三、完整代码

使用ffmpeg+sdl显示视频示例代项目码。
https://download.csdn.net/download/u013113678/88072835
注:示例代码的视频解码渲染在dll中不可见,而且也不是本文的关键,只要能拿到hWnd,渲染方式因人而异。


四、效果预览

嵌入的win32窗口(视频框)上可以显示flutter控件
在这里插入图片描述

和控件一样跟随窗口移动
在这里插入图片描述
i7 8750h核显使用dxva2解码播放1080p 30fps h264视频的性能。
在这里插入图片描述


总结

以上就是今天要讲述的内容,对于flutter在Windows上的视频渲染优化,这是一个很重要的方法。有了win32窗口就相当于支持Windows的所有视频渲染方式,笔者之前做的dxva2+d3d9解码渲染就可以直接复用了,而且性能直接拉满。但是当前实现并不算非常完美,配置较麻烦、背景渲染还有似乎点小问题、对于无边框窗口需要修改插件,而且只支持win10。总的来说,是可以在项目中使用的,需要的只是在此基础上继续优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/9876.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文心一言大模型测评

访问地址 文心一言服务请求地址&#xff1a;文心千帆大模型 (baidu.com) 新手可以先实名认证后再申请使用 测评 普通对话 这里先和他进行简单的问题讨论 编程相关 询问他有关代码的内容 确实可以生成代码&#xff0c;但不像chatgpt那样提供复制按钮 我们接下来让他生成…

3基本数据类型

文章目录 3.1. Java 中的几种基本数据类型是什么&#xff1f;对应的包装类型是什么&#xff1f;各自占用多少字节呢&#xff1f;3.2. 自动装箱与拆箱3.3. 八种基本类型的包装类和常量池 3.1. Java 中的几种基本数据类型是什么&#xff1f;对应的包装类型是什么&#xff1f;各自…

LeetCode45.Jump-Game-II<跳跃游戏II>

题目&#xff1a; 思路&#xff1a; 从上次大神那里获得的灵感 这题问的是次数,那么我们需要确保 1,能否跳到终点 2,得到次数. 第一次条获得的是nums[0],那么第一个数就是我们第一次能跳跃的范围.每次在范围里获得最大值.并且次数加一.然后进入下一次范围;即可得到次数; 代码…

明晚直播:可重构计算芯片的AI创新应用分享!

大模型技术的不断升级及应用落地&#xff0c;正在推动人工智能技术发展进入新的阶段&#xff0c;而智能化快速增长和发展的市场对芯片提出了更高的要求&#xff1a;高算力、高性能、灵活性、安全性。可重构计算区别于传统CPU、GPU&#xff0c;以指令驱动的串行执行方式&#xf…

丑数的求解

题目描述 我们把只包含质因子 2、3 和 5 的数称作丑数&#xff08;Ugly Number&#xff09;。求按从小到大的顺序的第 n 个丑数。 示例: 输入: n 10 输出: 12 解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。 算法思想 由题意可知一个丑数可以通过另一个丑数 * 2 …

一些关于设计原理和设计模式的问题

1.请解释一下单一职责原则&#xff08;SRP&#xff09;是什么&#xff0c;为什么它在软件设计中很重要&#xff1f; 2.能否举一个您在项目中应用开放封闭原则&#xff08;OCP&#xff09;的例子&#xff0c;并解释一下为什么该原则对于软件扩展很重要&#xff1f; 3.依赖倒置…

论文解读|Struck算法:基于结构化输出预测的自适应视觉目标跟踪框架

原创 | 文 BFT机器人 01 背景 本文的背景是关于自适应视觉目标跟踪的研究。在传统的跟踪方法中&#xff0c;通常采用基于检测的方式&#xff0c;即尝试学习一个分类器来区分目标对象和其周围的背景。然而&#xff0c;这种方法存在一些问题&#xff0c;例如需要手动选择特征和参…

深度神经网络基础——深度学习神经网络基础 Tensorflow在深度学习的应用

目录 一、二、Tesnsflow入门 & 环境配置 & 认识Tensorflow三、线程与队列与IO操作神经网络基础知识1.简单神经网络2.卷积神经网络卷积层新的激活函数-Relu池化层(Pooling)计算 案例&#xff1a;Mnist手写数字图片识别卷积网络案例 一、二、Tesnsflow入门 & 环境配置…

Unity facebook分享链接跳转app

facebook分享链接跳转app ##技术点分析 1、运用Android的深度链接技术实现。 安卓深度链接&#xff1a; https://developer.android.com/training/app-links/deep-linking 在安卓工程中的AndroidMainfest.xml配置&#xff0c;添加自定义的scheme&#xff0c;需要将intent-fil…

SQL AND OR 运算符

AND & OR 运算符用于基于一个以上的条件对记录进行过滤。 如果第一个条件和第二个条件都成立&#xff0c;则 AND 运算符显示一条记录。 如果第一个条件和第二个条件中只要有一个成立&#xff0c;则 OR 运算符显示一条记录。 下面是选自 "students" 表的数据&a…

java 支持jsonschema

入参校验产品化 schema_xsd可视化编辑器_个人渣记录仅为自己搜索用的博客-CSDN博客 jsonchema的生成 支持v4的jackson-jsonSchema GitHub - mbknor/mbknor-jackson-jsonSchema: Generate JSON Schema with Polymorphism using Jackson annotations jackson-module-jsonSchema …

yolov5 C++推理(libtorch和onnxruntime框架)

libtorch推理 #include <iostream> #include <algorithm> #include <opencv2/opencv.hpp> #include <torch/script.h> #include <torch/torch.h>std::vector<torch::Tensor> non_max_suppression(torch::Tensor preds, float score_thres…

网络专线如何改成SDWAN?

将网络专线改成SDWAN涉及一系列步骤和决策。下面是一个概括的指南&#xff0c;帮助您了解如何将网络专线迁移到SDWAN。 1.需求分析&#xff1a;首先&#xff0c;您需要对现有网络专线的性能、需求和限制进行全面分析。了解各个分支机构的带宽需求、网络延迟、丢包率以及关键应…

阿里云NVIDIA A100 GPU云服务器性能详解及租用费用

阿里云GPU服务器租用费用表包括包年包月、一个小时收费以及学生GPU服务器租用费用&#xff0c;阿里云GPU计算卡包括NVIDIA V100计算卡、T4计算卡、A10计算卡和A100计算卡&#xff0c;GPU云服务器gn6i可享受3折&#xff0c;阿里云百科分享阿里云GPU服务器租用表、GPU一个小时多少…

各种知名游戏的技术分析

介绍一个GitHub&#xff0c;里面包括了市面上的各种游戏的技术分析&#xff0c;包括渲染管线、工作流、技术文章等等&#xff0c;在做某个类型的游戏的时候&#xff0c;可以针对某个游戏去进行技术参考&#xff0c;特别实用。 GitHub - OTFCG/Awesome-Game-Analysis: a compre…

C++那些事之template disambiguator

template disambiguator 1.背景 最近看到一段代码&#xff1a; auto chunk_left first_sort_key.template GetChunk<ArrayType>(left); 请问&#xff0c;这里的.template代表什么意义&#xff1f; 本节将从实际例子出发&#xff0c;探讨这个意义。 2.template disambigu…

数仓学习---16、可视化报表(Superset)

星光下的赶路人star的个人主页 真正的才智是刚毅的志向 文章目录 1、Superset入门1.1 Superset概述1.2 环境说明 2、Superset安装2.1 安装Python环境2.1.1 安装Miniconda2.1.2 创建Python3.7 环境 2.2 Superset部署2.2.1 安装依赖2.2.2 安装Superset2.2.3 启动Superset2.2.4 Su…

【ARM Coresight 系列文章 10.2 - ARM Coresight STM Trace packets】

文章目录 Trace protocolpacket的种类Error packetsVERSION Packets同步 packet 上篇文章&#xff1a;ARM Coresight 系列文章 10.1 - ARM Coresight STM 介绍及使用 下篇文章&#xff1a;ARM Coresight 系列文章 10.3 - ARM Coresight STM 寄存器介绍 及STM DMA 传输介绍 Trac…

WPF实战学习笔记13-创建注册登录接口

创建注册登录接口 添加文件 创建文件 MyToDo.Api ​ ./Controllers/LoginController.cs ​ ./Service/ILoginService.cs ​ ./Service/LoginService.cs MyToDo.Share ./Dtos/UserDto.cs LoginController.cs using Microsoft.AspNetCore.Mvc; using MyToDo.Api.Context;…

vue-pdf 单列显示多个pdf页面

<template><div><pdfv-for"i in numPages":key"i":src"src":page"i"style"display: inline-block; width: 100%"></pdf> <!-- 宽度设置100% 一行只展示一页 --></div> </template&g…