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。总的来说,是可以在项目中使用的,需要的只是在此基础上继续优化。
相关文章:
Flutter Windows通过嵌入Native窗口实现渲染视频
Flutter视频渲染系列 第一章 Android使用Texture渲染视频 第二章 Windows使用Texture渲染视频 第三章 Linux使用Texture渲染视频 第四章 全平台FFICustomPainter渲染视频 第五章 Windows使用Native窗口渲染视频(本章) 文章目录 Flutter视频渲染系列前言…...
MySQL学习笔记 ------ 库和表的管理
#DDL /* 数据定义语言 库和表的管理 一、库的管理 创建、修改、删除 二、表的管理 创建、修改、删除 创建: create 修改: alter 删除: drop */ #一、库的管理 #1、库的创建 /* 语法: create database [if not exists]库名;…...
python中去除字符串中指定的字符
去除字符串中特定字符(但是只能删除头、尾指定字符): a 你好\n我是xx。\n\n\n print(a.strip(\n))# 你好 # 我是xx。 去除中间字符,可使用replace()函数: a 你好\n我是xx。\n\n\n print(a.replace(\n, ))# 你好我…...
Java实现商品ID获取京东商品详情Desc商品描述数据方法
要通过京东的API获取商品详情商品描述,您可以使用京东开放平台提供的接口来实现。以下是一种使用Java编程语言实现的示例,展示如何通过京东开放平台API获取商品详情: 首先,确保您已注册成为京东开放平台的开发者,并创…...
1-高性能计算研究
高性能计算研究 E级计算机系统研制高性能计算应用软件研发并行编程框架应用协同开发优化平台和工具软件示例 高性能计算环境研发 E级计算机系统研制 高性能互联计算、编程、运行模型 应用驱动的新型可扩展基础算法(适用于E级计算的可计算物理建模与新型计算方法&a…...
swagger快速升级方案
背景 在使用SpringBoot 2.6以前去创建API文档工具一般会采用SpringFox提供的Swagger库,但是由于SpringBoot版本的不断升级和SpringFox摆烂不更新,导致了SpringBoot2.6之后的项目无法使用SpringFox去生成API文档,或者可以使用但是有很多的bug…...
sql中with as用法/with-as 性能调优/with用法
文章目录 一、概述二、基本语法三、使用场景3.1、定义CTE,并为每列重命名3.2、多次引用/多次定义3.3、with与union all联合使用3.4、with返回多种结果的值3.5、with与insert使用 四、递归查询4.1、语法4.2、使用场景4.2.1、用with递归构造1-10的数据4.2.2、with与insert递归造数…...
大数据课程C5——ZooKeeper的应用组件
文章作者邮箱:yugongshiyesina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 掌握Zookeeper的Canal消费组件; ⚪ 掌握Zookeeper的Dubbo分布式服务框架; ⚪ 掌握Zookeeper的Metamorphosis消息中间件; ⚪ 掌握Zo…...
Redisson实现简单消息队列:优雅解决缓存清理冲突
在项目中,缓存是提高应用性能和响应速度的关键手段之一。然而,当多个模块在短时间内发布工单并且需要清理同一个接口的缓存时,容易引发缓存清理冲突,导致缓存失效的问题。为了解决这一难题,我们采用Redisson的消息队列…...
php-golang-rpc 简单的jsonrpc实践
golang代码: package main import ( "net" "net/rpc" "net/rpc/jsonrpc" ) type App struct{} type Res struct { Code int json:"code" Msg string json:"msg" Data any json:"data" } fun…...
Apipost变量高亮展示,变量操作更流畅
之前Apipost配置的各种环境变量只能在右上角环境管理中查看,很多小伙伴希望能有一种更好的解决方案用以快速复制变量值,快速查看变量的当前值和初始值,于是在Apipost 7.1.7中我们推出环境变量高亮展示功能来满足用户的使用需求。 功能描述&a…...
SSIS对SQL Server向Mysql数据转发表数据 (完结)
1、对于根据主键进行更新和插入新的数据,根据前面的文章,对于组件已经很熟悉了,我们直接加入一个 查找 组件 ,如下所示 2、右键点击"查找",然后“编辑” ,选择“连接”,选中我们的目标连接器&…...
vue+Element-ui实现树形组件、表格树
需求 要做出如下图所示的 树形表格,也就是数据之间有父子类关系的这种,可以点击展开、收缩 像上图这样的表格树 实现 1.使用树形组件 在学习树形表格之前,肯定得先搞懂普通的树形组件是怎么搞的,然后将其套到表格中就好了&…...
【iPadOS 开发】打开 iPad 的开发者模式的方法
文章目录 1. 前提条件2. 具体方法 1. 前提条件 iPad 通过 Type-C 线连接到 Mac Mac上已经安装 Xcode 2. 具体方法 在 Xcode 顶栏中的 Window 中打开 Devices and Simulators ,可以看到自己的设备: 接着在 iPad 上进入 设置 > 隐私与安全性 > 开…...
矩阵对角线元素的和
题目: 给你一个正方形矩阵 mat,请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 示例: 输入:mat [[1,2,3], [4,5,6], [7,8,9]] 输出ÿ…...
看了这篇文章,我也会用grid布局了
grid网格布局 网格布局是由一系列水平及垂直的线构成的一种布局模式,使用网格,我们能够将设计元素进行排列,帮助我们设计一系列具有固定位置以及宽度的元素的页面,使我们的网站页面更加统一。 它将网页划分成一个个网格ÿ…...
{“msg“:“invalid token“,“code“:401}
项目场景: 提示:这里简述项目相关背景: {“msg“:“invalid token“,“code“:401} 前端请求 后端接口时, 请求失败,控制台出现如下所示报错信息 问题描述 问题: 控制台报错信息如下所示: …...
Qt Qml自定义模态对话框
自带的messagedialog不好使,自定义一个,简单的: DialogPop.qml /*** brief 功能:此文件实现了模态框* author lanmanck* date 2023-07-25* CopyRight (C) lanmanck*/ import QtQuick 2.1 import QtQuick.Window 2.0 import QtQu…...
【前端知识】React 基础巩固(三十)——CSS编写方式
React 基础巩固(三十)——CSS编写方式 1.内联样式 Style 接受一个采用小驼峰命名属性的JS对象,而不是CSS字符串 可以引用state中的状态来设置相关的样式 优点:样式之间不会有冲突;可以动态获取当前state中的状态 缺点:需要使用…...
Langchain 集成 FAISS
Langchain 集成 FAISS 1. FAISS2. Similarity Search with score3. Saving and loading4. Merging5. Similarity Search with filtering 1. FAISS Facebook AI Similarity Search (Faiss)是一个用于高效相似性搜索和密集向量聚类的库。它包含的算法可以搜索任意大小的向量集&a…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
