Part1前言
Invideo插件是一个UE5的rtsp视频播放插件,当然还可以播放主流的其他视频协议。其开源地址如下https://github.com/inveta/InVideo
。
前段时间有网页反馈使用该插件进行播放视频的时候会有偶发程序崩溃。
Part2问题排查
当看到留言之后,其实并没有什么排查思路。后续这位网友有加了我们qq技术交流群:681464378
给出了更加详细的信息描述。
并且强调在大分辨率的情况下,崩溃的概率会高很多。而且主要集中在视频打开和关闭的时候。
接下来找到虚幻的源码发现崩溃在第一个checkf里面。这里校验了传入参数UpdataRegion。
UpdataRegion这个参数类型是FUpdateTextureRegion2D,通过查看代码,发现是我们自己传入的。在UInVideoWidget::UpdateTextureRegions
函数中调用ENQUEUE_RENDER_COMMAND
传入到的渲染线程。
而传入的对象的值通过下面方法创建
m_VideoUpdateTextureRegion = new FUpdateTextureRegion2D(0, 0, 0, 0, m_VideoSize.X, m_VideoSize.Y);
通过比较我们创建时候的值和崩溃时候的值,我们发现明明我们初始化的值是0,但是在崩溃的时候,编程了一个非常大的值:-1861933592。这只能说明我们传入的对象被释放了,但是渲染线程还在使用。
我们释放的情况只有在执行视频关闭的时候,才会进行。相关代码在void UInVideoWidget::StopPlay()
中进行。释放方法如下
if (nullptr != m_VideoUpdateTextureRegion)
{
delete m_VideoUpdateTextureRegion;
m_VideoUpdateTextureRegion = nullptr;
}
那么为什么我们把视频释放了,渲染线程还会继续渲染呢?
这是一个多线程问题,因为分辨率设置过大,导致gpu显卡性能下降,然后这个bug就出来了。在视频释放之后,渲染队列之前的任务还没有执行完成,之后就会使用已经释放的指针。分辨率低的时候,渲染线程性能好,不会有延迟,所以就不会出现。
后续修改程序将每次传递这个值从新new一个出来RegionData->Regions = new FUpdateTextureRegion2D(*Regions);
再然后介绍之后再进行释放delete RegionData->Regions;
Part3后续反馈
按照这个思路修改之后,目前没有收到崩溃的问题。
所以后续推荐使用V1.4版本 https://github.com/inveta/InVideo/releases/tag/V1.4
Part4总结
本文针对InVideo播放rtsp视频崩溃的bug进行了复盘并进行了修复。