提示:阅读此文章之前需要有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++的人来说可能有点难懂。代码只有最关键的部分,如果有疑问,可以回复留言交流。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)