Flutter 用Texture控件在Windows平台实现视频渲染
Posted 施强教育科技
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter 用Texture控件在Windows平台实现视频渲染相关的知识,希望对你有一定的参考价值。
提示:阅读此文章之前需要有C++开发经验,知道如何利用channel在C++和Dart之间做通信。
1.在Flutter需要显示视频的地方声明Texture组件
2.在Windows插件代码里面创建TextureRenderer类
3.Flutter通过channel调用Windows插件创建Texture
4.Windows插件部分C++更新视频RGBA,并通知flutter刷新界面
前言
Flutter渲染视频在移动端比较容易,可以用PlatformView,Texture等,但在Windows平台无法使用PlatformView,原因是Windows的每一个窗口都是一个窗口句柄(HWND),如果强行的增加一 个PlatformView,那以后想在PlatformView所占据的位置弹出其他Flutter控件,会被遮盖,因此Windows平台视频渲染只能用Texture,效率并不像网上提到的那么并。目前Windows平台的示例代码几乎搜索不到,笔者在对接声网和网易两家公司RTC SDK的过程中,成功渲染了两家公司的多媒体播放器和RTC提供的视频,确定了Windows平台使用Texture渲染视频的方法,写下此文章,希望对后来的开发者有些许帮助。
一、PlatformView与Texture是什么?
PlatformView主要适用于原生已经很成熟的组件,嵌入到Flutter中,节省开发时间,例如WebView,视频播放器等。由于Windows窗口机制的原因,在Windows平台并不支持PlatformView。
Texture是一个颜色数据缓存区,只要平台将缓存区更新后,通知Flutter刷新界面即可。例如视频渲染,只需要将当前视频帧的RGBA缓存区拷贝到Texture的缓存区,然后Flutter刷新界面即可实现视频渲染,这种方式更dart。
二、使用步骤
1.在Flutter需要显示视频的地方声明Texture组件
代码如下:
Container( color: Colors.black, child: Texture(textureId: (widget.viewModel.textureId)) );
2.在Windows插件代码里面创建TextureRenderer类
代码如下:
class TextureRenderer
public:
TextureRenderer(flutter::BinaryMessenger* messenger,
flutter::TextureRegistrar* registrar);
bool TextureRenderer::onRenderVideoFrame(unsigned int uid, agora::media::IVideoFrameObserver::VideoFrame& videoFrame);
private:
flutter::BinaryMessenger* messenger_ = nullptr;
flutter::TextureRegistrar* registrar_ = nullptr;
std::unique_ptr<TextureRenderer> fullScreenTextureRenderer_; //全员看他纹理
std::map<int64_t, std::unique_ptr<TextureRenderer>> renderers_; //通用的直播渲染纹理
TextureRenderer::TextureRenderer(flutter::BinaryMessenger *messenger,
flutter::TextureRegistrar *registrar)
: registrar_(registrar),
texture_(PixelBufferTexture(std::bind(&TextureRenderer::CopyPixelBuffer,
this, std::placeholders::_1,
std::placeholders::_2))),
uid_(0), pixel_buffer_(new FlutterDesktopPixelBuffernullptr, 0, 0)
texture_id_ = registrar->RegisterTexture(&texture_);
channel_ = std::make_unique<MethodChannel<EncodableValue>>(
messenger,
"strong_live_player/texture_render_" + std::to_string(texture_id_),
&flutter::StandardMethodCodec::GetInstance());
channel_->SetMethodCallHandler([this](const auto &call, auto result)
this->HandleMethodCall(call, std::move(result));
);
3.Flutter通过channel调用Windows插件创建Texture
Flutter层面通过channel调用C++的createTextureRender函数后,会创建上面提到的第二步提到的TextureRender类实例,并与第一步提到的Flutter层面的Texture控件绑定。
PlayerViewModel init(var callback)
AgoraMediaPlayerKit.channel.invokeMethod('createTextureRender',
).then((value)
textureId = value;
_channel = MethodChannel('agora_media_player_kit/texture_render_$value');
_channel?.setMethodCallHandler(_platformCallHandler);
callback();
refresh();
);
return this;
4.Windows插件部分C++更新视频RGBA,并通知flutter刷新界面
这一步是收到播放器的视频帧回调后,通知Flutter层面进行渲染。所做的工作就是把视频帧的RGBA缓存区拷贝到Flutter底层提供的pixel_buffer。 并通知刷新,至此,视频渲染工作完成。缓存区的大小为 视频宽度 * 视频高度 * 4,之所以要乘以4,是因为每个颜色点由一个32位整数组成,每个颜色点的每一BIT排列顺序为 RGBA,分别代表红、绿、蓝、透明度,值为0~255。 代码如下:
bool TextureRenderer::onRenderVideoFrame(unsigned int uid, agora::media::IVideoFrameObserver::VideoFrame& videoFrame)
std::lock_guard<std::mutex> lock_guard(mutex_);
if (pixel_buffer_->width != videoFrame.width ||
pixel_buffer_->height != videoFrame.height)
if (pixel_buffer_->buffer)
delete[] pixel_buffer_->buffer;
pixel_buffer_->buffer = new uint8_t[videoFrame.width * videoFrame.height * 4];
memcpy((void*)pixel_buffer_->buffer, videoFrame.yBuffer,
videoFrame.width * videoFrame.height * 4);
pixel_buffer_->width = videoFrame.width;
pixel_buffer_->height = videoFrame.height;
registrar_->MarkTextureFrameAvailable(texture_id_);
return true;
三、运行效果演示
20220924-100136
总结
以上就是今天要讲的内容,Flutter在Windows上使用Texture进行视频渲染,对于不懂C++的人来说可能有点难懂。代码只有最关键的部分,如果有疑问,可以回复留言交流。
flutter widget:Row
参考技术A row : 在水平方向上排列子widget的列表.Row 是继承 Flex => MultiChildRenderObjectWidget => RenderObjectWidget => Widget .
所以 Row 具有动态布局的特点,可以让子控件展开以填充可水平的可用空间,用一个 Expanded 的控件包裹子控件。
Row 不支持滚动(通常认为一行的子控件超过可以容纳空间是错误的)。如果有一行控件控件比较多,希望可以滑动的时候,可以采用 ListView 。
同样,如果是垂直方向方面和 Row 对应的是 Column 。
小demo
这里需要注意的地方:
因为在 Row 里面有text,但是因为text的长度过长,一行肯定是放不下的,所以这里考虑用Expanded包裹一个Text,这样文字会自动换行,填充剩余部分。
效果图如下
修改下Row的 内容:
效果如下:可见多个Expanded 具有平分剩余空间的功能。和android 的weight 属性很相像。
以上是关于Flutter 用Texture控件在Windows平台实现视频渲染的主要内容,如果未能解决你的问题,请参考以下文章