当前位置: 首页 > news >正文

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窗口渲染视频&#xff08;本章&#xff09; 文章目录 Flutter视频渲染系列前言…...

MySQL学习笔记 ------ 库和表的管理

#DDL /* 数据定义语言 库和表的管理 一、库的管理 创建、修改、删除 二、表的管理 创建、修改、删除 创建&#xff1a; create 修改&#xff1a; alter 删除&#xff1a; drop */ #一、库的管理 #1、库的创建 /* 语法&#xff1a; create database [if not exists]库名;…...

python中去除字符串中指定的字符

去除字符串中特定字符&#xff08;但是只能删除头、尾指定字符&#xff09;&#xff1a; a 你好\n我是xx。\n\n\n print(a.strip(\n))# 你好 # 我是xx。 去除中间字符&#xff0c;可使用replace()函数&#xff1a; a 你好\n我是xx。\n\n\n print(a.replace(\n, ))# 你好我…...

Java实现商品ID获取京东商品详情Desc商品描述数据方法

要通过京东的API获取商品详情商品描述&#xff0c;您可以使用京东开放平台提供的接口来实现。以下是一种使用Java编程语言实现的示例&#xff0c;展示如何通过京东开放平台API获取商品详情&#xff1a; 首先&#xff0c;确保您已注册成为京东开放平台的开发者&#xff0c;并创…...

1-高性能计算研究

高性能计算研究 E级计算机系统研制高性能计算应用软件研发并行编程框架应用协同开发优化平台和工具软件示例 高性能计算环境研发 E级计算机系统研制 高性能互联计算、编程、运行模型 应用驱动的新型可扩展基础算法&#xff08;适用于E级计算的可计算物理建模与新型计算方法&a…...

swagger快速升级方案

背景 在使用SpringBoot 2.6以前去创建API文档工具一般会采用SpringFox提供的Swagger库&#xff0c;但是由于SpringBoot版本的不断升级和SpringFox摆烂不更新&#xff0c;导致了SpringBoot2.6之后的项目无法使用SpringFox去生成API文档&#xff0c;或者可以使用但是有很多的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的应用组件

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 掌握Zookeeper的Canal消费组件&#xff1b; ⚪ 掌握Zookeeper的Dubbo分布式服务框架&#xff1b; ⚪ 掌握Zookeeper的Metamorphosis消息中间件&#xff1b; ⚪ 掌握Zo…...

Redisson实现简单消息队列:优雅解决缓存清理冲突

在项目中&#xff0c;缓存是提高应用性能和响应速度的关键手段之一。然而&#xff0c;当多个模块在短时间内发布工单并且需要清理同一个接口的缓存时&#xff0c;容易引发缓存清理冲突&#xff0c;导致缓存失效的问题。为了解决这一难题&#xff0c;我们采用Redisson的消息队列…...

php-golang-rpc 简单的jsonrpc实践

golang代码&#xff1a; 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配置的各种环境变量只能在右上角环境管理中查看&#xff0c;很多小伙伴希望能有一种更好的解决方案用以快速复制变量值&#xff0c;快速查看变量的当前值和初始值&#xff0c;于是在Apipost 7.1.7中我们推出环境变量高亮展示功能来满足用户的使用需求。 功能描述&a…...

SSIS对SQL Server向Mysql数据转发表数据 (完结)

1、对于根据主键进行更新和插入新的数据&#xff0c;根据前面的文章&#xff0c;对于组件已经很熟悉了&#xff0c;我们直接加入一个 查找 组件 &#xff0c;如下所示 2、右键点击"查找"&#xff0c;然后“编辑” &#xff0c;选择“连接”,选中我们的目标连接器&…...

vue+Element-ui实现树形组件、表格树

需求 要做出如下图所示的 树形表格&#xff0c;也就是数据之间有父子类关系的这种&#xff0c;可以点击展开、收缩 像上图这样的表格树 实现 1.使用树形组件 在学习树形表格之前&#xff0c;肯定得先搞懂普通的树形组件是怎么搞的&#xff0c;然后将其套到表格中就好了&…...

【iPadOS 开发】打开 iPad 的开发者模式的方法

文章目录 1. 前提条件2. 具体方法 1. 前提条件 iPad 通过 Type-C 线连接到 Mac Mac上已经安装 Xcode 2. 具体方法 在 Xcode 顶栏中的 Window 中打开 Devices and Simulators &#xff0c;可以看到自己的设备&#xff1a; 接着在 iPad 上进入 设置 > 隐私与安全性 > 开…...

矩阵对角线元素的和

题目&#xff1a; 给你一个正方形矩阵 mat&#xff0c;请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 示例&#xff1a; 输入&#xff1a;mat [[1,2,3], [4,5,6], [7,8,9]] 输出&#xff…...

看了这篇文章,我也会用grid布局了

grid网格布局 网格布局是由一系列水平及垂直的线构成的一种布局模式&#xff0c;使用网格&#xff0c;我们能够将设计元素进行排列&#xff0c;帮助我们设计一系列具有固定位置以及宽度的元素的页面&#xff0c;使我们的网站页面更加统一。 它将网页划分成一个个网格&#xff…...

{“msg“:“invalid token“,“code“:401}

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; {“msg“:“invalid token“,“code“:401} 前端请求 后端接口时&#xff0c; 请求失败&#xff0c;控制台出现如下所示报错信息 问题描述 问题&#xff1a; 控制台报错信息如下所示&#xff1a; …...

Qt Qml自定义模态对话框

自带的messagedialog不好使&#xff0c;自定义一个&#xff0c;简单的&#xff1a; DialogPop.qml /*** brief 功能&#xff1a;此文件实现了模态框* 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对象&#xff0c;而不是CSS字符串 可以引用state中的状态来设置相关的样式 优点&#xff1a;样式之间不会有冲突&#xff1b;可以动态获取当前state中的状态 缺点&#xff1a;需要使用…...

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…...

保姆级教程:在ArcGIS Pro插件中集成你的自定义工具箱(以‘消除重复要素’为例)

从脚本到按钮&#xff1a;ArcGIS Pro插件开发实战指南 在GIS日常工作中&#xff0c;我们常常会遇到一些重复性的数据处理任务。比如数据质检环节的"消除重复要素"操作&#xff0c;虽然可以通过Python脚本实现&#xff0c;但每次都需要打开IDE或Python窗口执行代码&am…...

机器学习结合基因无关通路映射:从临床数据挖掘新药靶点

1. 项目概述&#xff1a;当机器学习遇见代谢通路&#xff0c;如何从数据中“挖”出新药靶点&#xff1f;在生物医学研究的前沿&#xff0c;我们正面临一个核心矛盾&#xff1a;一方面&#xff0c;我们拥有海量的临床数据&#xff0c;比如血糖、血压、BMI等指标&#xff1b;另一…...

App Inventor蓝牙调试避坑指南:从连接失败到数据乱码,一次讲清所有常见问题

App Inventor蓝牙调试避坑指南&#xff1a;从连接失败到数据乱码的实战解决方案在移动应用开发领域&#xff0c;蓝牙通信一直是实现设备间短距离数据交换的核心技术之一。对于使用App Inventor的开发者而言&#xff0c;蓝牙模块提供了无需复杂编码即可实现无线通信的便捷途径。…...

ThinkPad开机报错0183/0253?别慌,手把手教你搞定EFI变量错误(附BIOS重置教程)

ThinkPad开机报错0183/0253&#xff1f;EFI变量错误全面解决方案当你按下ThinkPad的电源键&#xff0c;期待熟悉的开机画面时&#xff0c;屏幕上却突然跳出一串神秘代码——"0183: Bad CRC of Security Settings in EFI Variable"或"0253: EFI Variable Block D…...

如何高效批量下载音乐歌词:智能歌词管理完整指南

如何高效批量下载音乐歌词&#xff1a;智能歌词管理完整指南 【免费下载链接】ZonyLrcToolsX ZonyLrcToolsX 是一个能够方便地下载歌词的小软件。 项目地址: https://gitcode.com/gh_mirrors/zo/ZonyLrcToolsX ZonyLrcToolsX 是一款专业的跨平台歌词下载工具&#xff0c…...

‌2026智慧校园规划必读:如何在预算吃紧下选到高性价比方案‌

✅作者简介&#xff1a;合肥自友科技 &#x1f4cc;核心产品&#xff1a;智慧校园平台(包括教工管理、学工管理、教务管理、考务管理、后勤管理、德育管理、资产管理、公寓管理、实习管理、就业管理、离校管理、科研平台、档案管理、学生平台等26个子平台) 。公司所有人员均有多…...

AI学习 - 大模型基础入门

AI学习 - 大模型基础入门 从零开始&#xff1a;Ollama 安装 → 本地模型运行 → Python 代码接入 → 理解核心概念 摘要 本文记录了在 Windows 上使用 Ollama 部署本地大模型、并通过 Python 代码接入调用的完整过程。内容涵盖&#xff1a;Ollama 安装与模型拉取、大模型基础概…...

PCB的常规机械通孔与HDI工艺钻孔差异

结合常规 4 层通孔 PCB&#xff08;非 HDI&#xff09; 标准制程&#xff0c;分步骤讲清钻孔时机、先后顺序&#xff0c;区分机械通孔与板件结构&#xff0c;专业且贴合工厂实际流程。一、先明确 4 层通孔板基础结构4 层板结构&#xff1a;L1 → PP 半固化片 → L2/L3&#xff…...

Codex使用API Key授权无法使用插件?

小伙伴们&#xff0c;大家好&#xff0c;我是小溪&#xff0c;见字如面。对于没有ChatGPT账号的小伙伴来说&#xff0c;虽然可以通过API Key授权的方式使用Codex桌面端&#xff0c;但是会有一些限制。比如无法使用插件功能&#xff0c;无法使用Codex移动端进行远程控制等。为了…...

告别Postman!用APIfox搞定接口测试+自动化,这份保姆级教程带你从环境配置到报告生成

从Postman到APIfox&#xff1a;接口测试自动化的高效迁移指南如果你还在为接口测试中的重复劳动和多环境切换头疼&#xff0c;是时候考虑从Postman迁移到APIfox了。作为一名经历过这个转型过程的开发者&#xff0c;我想分享一些实战经验&#xff0c;帮助你平滑过渡并最大化利用…...