Flutter视频渲染系列

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


文章目录

  • Flutter视频渲染系列
  • 前言
  • 一、如何实现?
    • 1、定义Texture控件
    • 2、创建Texture对象
      • (1)继承FlPixelBufferTexture
      • (2)注册Texture
    • 3、关联TextureId
    • 4、写入rgba
  • 二、示例
    • 1.使用ffmpeg解码播放
  • 三、完整代码
  • 总结

前言

flutter渲染视频的方法有多种,比如texture、platformview、ffi,其中texture是通过flutter自己提供的一个texture对象与dart界面关联后进行渲染,很容易搜索到android和ios的相关资料,但是Linux上却几乎找不到任何资料。通过查看一些开源库的代码,才找到Linux上使用flutter texture的方法,在这里做一个简单的介绍。


一、如何实现?

1、定义Texture控件

在界面中定义一个Texture

Container(width: 640,height: 360,child: Texture(textureId: textureId,
))

2、创建Texture对象

(1)继承FlPixelBufferTexture

此处代码为dart_vlc源码,因为是一个独立对象所有可以直接拿来用,自己继承实现也基本差不多,所以就没必要造轮子了。

#ifndef VIDEO_OUTLET_H_
#define VIDEO_OUTLET_H_
#include <flutter_linux/flutter_linux.h>
#include <gtk/gtk.h>
struct _VideoOutletClass {FlPixelBufferTextureClass parent_class;
};
struct VideoOutletPrivate {int64_t texture_id = 0;uint8_t* buffer = nullptr;int32_t video_width = 0;int32_t video_height = 0;
};
G_DECLARE_DERIVABLE_TYPE(VideoOutlet, video_outlet, DART_VLC, VIDEO_OUTLET,FlPixelBufferTexture)
G_DEFINE_TYPE_WITH_CODE(VideoOutlet, video_outlet,fl_pixel_buffer_texture_get_type(),G_ADD_PRIVATE(VideoOutlet))
static gboolean video_outlet_copy_pixels(FlPixelBufferTexture* texture,const uint8_t** out_buffer,uint32_t* width, uint32_t* height,GError** error) {auto video_outlet_private =(VideoOutletPrivate*)video_outlet_get_instance_private(DART_VLC_VIDEO_OUTLET(texture));*out_buffer = video_outlet_private->buffer;*width = video_outlet_private->video_width;*height = video_outlet_private->video_height;return TRUE;
}
static VideoOutlet* video_outlet_new() {return DART_VLC_VIDEO_OUTLET(g_object_new(video_outlet_get_type(), nullptr));
}
static void video_outlet_class_init(VideoOutletClass* klass) {FL_PIXEL_BUFFER_TEXTURE_CLASS(klass)->copy_pixels = video_outlet_copy_pixels;
}
static void video_outlet_init(VideoOutlet* self) {}
#endif

(2)注册Texture

static FlTextureRegistrar* _registrar;
//创建自定义的texture对象auto  texture=video_outlet_new();//注册对象fl_texture_registrar_register_texture(_registrar,FL_TEXTURE(texture));

3、关联TextureId

dart

  int textureId = -1;if (textureId < 0) {//调用本地方法获取textureId methodChannel.invokeMethod('startPreview',<String,dynamic>{'path':'test.mov'}).then((value) {textureId = value;setState(() {print('textureId ==== $textureId');});});}

c++

 //methodchannel的startPreview方法实现,此处略//texure指针的地址即为textureIdg_autoptr(FlValue) result = fl_value_new_int((int64_t)texture);//设置返回值response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));

4、写入rgba

static FlTextureRegistrar* _registrar;
//取得自定义的内部对象
auto video_outlet_private =(VideoOutletPrivate*)video_outlet_get_instance_private(texture);
//设置视频帧宽高
video_outlet_private->video_width = width;
video_outlet_private->video_height = height;
//设置rgba数据
video_outlet_private->buffer = data[0];
//通知渲染
fl_texture_registrar_mark_texture_frame_available(_registrar, FL_TEXTURE(texture));

注:FlTextureRegistrar的获取方法为:

//定义TextureRegistrar对象
static FlTextureRegistrar* _registrar;
//插件注册代码,这里的插件名为ffplay_plugin,此方法为官方生成代码
void ffplay_plugin_register_with_registrar(FlPluginRegistrar* registrar) {FfplayPlugin* plugin = FFPLAY_PLUGIN(g_object_new(ffplay_plugin_get_type(), nullptr));g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();g_autoptr(FlMethodChannel) channel =fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar),"ffplay_plugin",FL_METHOD_CODEC(codec));   //获取TextureRegistrar对象                                             _registrar=fl_plugin_registrar_get_texture_registrar(registrar);                                                                     fl_method_channel_set_method_call_handler(channel, method_call_cb,g_object_ref(plugin),g_object_unref);g_object_unref(plugin);
}

二、示例

1.使用ffmpeg解码播放

main.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
MethodChannel methodChannel = MethodChannel('ffplay_plugin');
void main() {runApp(MyApp());
}
class MyApp extends StatelessWidget {// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: MyHomePage(title: 'Flutter Demo Home Page'),);}
}class MyHomePage extends StatefulWidget {MyHomePage({Key? key, required this.title}) : super(key: key);final String title;@override_MyHomePageState createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {int _counter = 0;int textureId = -1;Future<void> _createTexture() async {print('textureId = $textureId');//调用本地方法播放视频if (textureId < 0) {methodChannel.invokeMethod('startPreview',<String,dynamic>{'path':'https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv'}).then((value) {textureId = value;setState(() {print('textureId ==== $textureId');});});}}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(widget.title),),//控件布局body: Center(child: Row(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[if (textureId > -1)ClipRect (child: Container(width: 640,height: 360,child: Texture(textureId: textureId,)),),],),),floatingActionButton: FloatingActionButton(onPressed: _createTexture,tooltip: 'createTexture',child: Icon(Icons.add),),);}
}

定义一个插件我这里是fflay_plugin。
fflay_plugin.cc
相关对象的定义

static FlTextureRegistrar* _registrar;
class PlayData {public://Play中封装了ffmpegPlay* play;VideoOutlet* flutter_pixel_buffer;int64_t texture_id;
};
static std::map<int64_t, PlayData*> playMap;

获取FlTextureRegistrar对象

//插件注册代码,这里的插件名为ffplay_plugin,此方法为官方生成代码
void ffplay_plugin_register_with_registrar(FlPluginRegistrar* registrar) {FfplayPlugin* plugin = FFPLAY_PLUGIN(g_object_new(ffplay_plugin_get_type(), nullptr));g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();g_autoptr(FlMethodChannel) channel =fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar),"ffplay_plugin",FL_METHOD_CODEC(codec));   //获取TextureRegistrar对象                                             _registrar=fl_plugin_registrar_get_texture_registrar(registrar);                                                                     fl_method_channel_set_method_call_handler(channel, method_call_cb,g_object_ref(plugin),g_object_unref);g_object_unref(plugin);
}

methodChannel部分

 if (strcmp(method, "startPreview") == 0){//获取参数auto arguments = fl_method_call_get_args(method_call);auto path =  fl_value_get_string(fl_value_lookup_string(arguments, "path"));  //创建textureauto  texture=video_outlet_new();//注册texturefl_texture_registrar_register_texture(_registrar,FL_TEXTURE(texture));PlayData* pd = new PlayData;  //初始化播放器        pd->play = new Play;pd->flutter_pixel_buffer=texture;pd->texture_id = (int64_t)texture;playMap[pd->texture_id] = pd;//播放视频回调pd->play->Display = [=](unsigned char* data[8], int linesize[8], int width, int height, AVPixelFormat format) {//设置视频数据auto video_outlet_private =(VideoOutletPrivate*)video_outlet_get_instance_private(pd->flutter_pixel_buffer);video_outlet_private->video_width = width;video_outlet_private->video_height = height;video_outlet_private->buffer = data[0];//通知渲染fl_texture_registrar_mark_texture_frame_available(_registrar, FL_TEXTURE(pd->flutter_pixel_buffer));};//开始播放视频pd->play->Start(path, AV_PIX_FMT_RGBA);//返回textureIdg_autoptr(FlValue) result = fl_value_new_int((int64_t)texture);response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));}

效果预览


三、完整代码

https://download.csdn.net/download/u013113678/87096317
包含完整代码的flutter项目,版本3.0.4、3.3.8都成功运行,需要自行安装ffmpeg库版本最好为4.3或5.0.1。目录说明如下。
注:由于笔者在Ubuntu上采用静态加载ffmpeg so库出现了glibc冲突问题没有解决,所以采用了动态加载so的方式,DllImportUtils的作用只是动态加载so,具体可查看《C++ 使用宏加载动态库》。


总结

以上就是今天要讲的内容,flutter在linux上渲染视频,还是有点不容易的,一是缺乏相关资料,二是flutter在Linux上的本地代码是另外一套封装与windows完全不相同。而且采用的是c语言自定义一套面向对象规则的方式,当然编译器是clang++我们可以使用c++的方式编码。总的来说,flutter是可以在Linux实现视频渲染的,如果要进一步优化则需要用gltexture或者本地窗口渲染。

Flutter 使用Texture实现Linux渲染视频相关推荐

  1. Flutter 使用Texture实现Windows渲染视频

    Flutter视频渲染系列 第一章 Android使用Texture渲染视频 第二章 Windows使用Texture渲染视频(本章) 第三章 Linux使用Texture渲染视频 第四章 全平台FF ...

  2. Flutter 使用Texture实现Android渲染视频

    Flutter视频渲染系列 第一章 Android使用Texture渲染视频(本章) 第二章 Windows使用Texture渲染视频 第三章 Linux使用Texture渲染视频 第四章 全平台FF ...

  3. D3D Surface/Texture SDL DDraw渲染视频的区别和疑问

    1  D3D  Surface用起来比较简单,窗口改变时视频模糊,貌似是初始化窗口过小.全屏时有锯齿. StretchRect的Rect是显示区域宽高,这个值固定是初始值.改成随窗口变化,失败. 2  ...

  4. Flutter 用Texture控件在Windows平台实现视频渲染

    提示:阅读此文章之前需要有C++开发经验,知道如何利用channel在C++和Dart之间做通信. 前言 一.PlatformView与Texture是什么? 二.使用步骤 1.在Flutter需要显 ...

  5. 打造Flutter高性能富文本编辑器——渲染篇

    本系列文章主要介绍Flutter富文本编辑的设计和实现,从协议层.渲染层.自定义扩展以及体验优化等方面,详细介绍如何实现一个功能完善.可扩展.高性能的Flutter富文本编辑器,以及闲鱼在实践过程中遇 ...

  6. OpenGL渲染视频(二)

    目录 一.前言 二.openGL渲染介绍 1.OpenGl渲染管线的流程 2.顶点着色器的介绍 3.片元着色器的介绍 三.openGL着色器语言GLSL介绍 1.数据类型 2.限定符 3.二维图像渲染 ...

  7. 基于Linux的视频传输系统(上大学时參加的一个大赛的论文)

    文件夹<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 1原创性 ...

  8. linux自学视频资料第四讲:目录

    大家下午好! 今天linux自学视频第四讲:目录 这一讲大家要记住linux中的文件的权限(这在第三讲中有讲到)和目录的权限 首先大家要记住:u g o 这三个字母的定义  然后是 r w x 这三个 ...

  9. php实现视频转gif,在Linux上将视频转换成动态gif图片

    本文记录一下在linux上将视频转换成动态gif图片的方法. 首先,需要在Linux系统上安装FFmpeg,我会用这个工具去解压从视频中解压出视频帧. 下面的指令会解压出独立的视频帧,将它们保存为GI ...

最新文章

  1. 面试问题-使用Java线程做数学运算
  2. Hibernate的命名查询(NamedQuery)
  3. 让 CPU 告诉你硬盘和网络到底有多慢
  4. 九十九、Python所学经验分享
  5. ux.form.field.Verify 验证码控件
  6. 为什么unity 安装完模块还是找不到sdk_Unity填坑笔记(四)——移植UWP平台
  7. 诗与远方:无题(三十七)- 凿壁偷光
  8. HUAS 1482 lsy的后宫(DP+矩阵快速幂)
  9. 【转】Java杂谈(九)--Struts
  10. 在线密码管理器LastPass遭入侵 官方建议修改主密码
  11. MySQL5.7创建数据库与添加用户、删除用户及授权、保证数据库账号安全
  12. 图片标注工具labeling的安装和使用
  13. 基于Python实现网页版之复杂图片去水印
  14. 如何在iconfont.cn 下载ttf格式的图标
  15. jquery.countdown.js一个时间倒计时的插件
  16. 爱思助手 for Mac(苹果手机助手)中文版
  17. 怎样关闭计算机自动开机,电脑定时开机,教您电脑定时开机怎么取消
  18. 51单片机程序加密c语言,51单片机24C04密码锁(C程序+Proteus仿真)
  19. python爬虫经典段子_Python爬虫实战:爬取内涵段子
  20. 防病毒Clamav使用及API调用测试

热门文章

  1. 自考本科和全日制本科有什么区别?
  2. 一天一个蛋,刀斧靠边站
  3. 金和JCS协同平台套件系统怎么样?
  4. AMBA AHB面试题连载(五)
  5. 利用GPT2生成莎士比亚写作风格的文本(python实现)
  6. OpenGL基础图形编程(十)真实感图形基本概念
  7. Android 系统开发系列(1):Android 12 源代码下载、编译和刷机
  8. 2017总结与2018梦想目标
  9. WeCode在线少儿编程|创交会三大领域机器人各显神通
  10. 基于支持向量机的文本分类算法研究(三)—— 核函数文本分类性能评价指标(stitp项目)