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

Flutter 用Texture控件在Windows平台实现视频渲染,第1张

提示:阅读此文章之前需要有C++开发经验,知道如何利用channel在C++和Dart之间做通信。

前言

一、PlatformView与Texture是什么?

二、使用步骤

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所占据的位置d出其他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 fullScreenTextureRenderer_;    //全员看他纹理
    std::map> 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 FlutterDesktopPixelBuffer{nullptr, 0, 0}) {
    texture_id_ = registrar->RegisterTexture(&texture_);
    channel_ = std::make_unique>(
      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 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++的人来说可能有点难懂。代码只有最关键的部分,如果有疑问,可以回复留言交流。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/3002916.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-27
下一篇 2022-09-27

发表评论

登录后才能评论

评论列表(0条)

保存