背景:项目开发需要,通过TCP协议与视频板进行通信,获取图像数据,对图像数据进行解码后显示。
关键词:C#、FFmpeg、FFmpeg.AutoGen.dll、WriteableBitmap、H265、HEVC
1. 初设计
网上查阅相关资料,C#关于H265解码的资料很少,找到的也不是很全,以C++、QT相关最多。
找到C# FFmpeg.AutoGen.dll解码参考及实例,Github可下载。
参考:
一切准备就绪,根据协议获取数据、解码、显示,结果显示界面经常花屏,不同电脑配置花屏频率不同。
2. 解花屏
通过将项目设置为控制台程序,通过FFmpeg打印日志,发现每花屏一次,控制台打印:
Could not find ref with POC 26
网上找了很多资料均无效果:
A 尝试是否视频渲染引起,网上找到WriteableBitmap、D3DSurface,问题依然存在;
B 只解码数据,不进行渲染显示,是否依然存在?结果控制台依然会输出解码报错;
C 尝试Winform为主窗体,解码显示测试。依然花屏;
D 尝试下图FFmpeg硬解码模式,稳定性有所提高,仅2、4可用,但问题依然存在:
3. 寻根源
前面的思路全部推倒,重新来过....
找问题的根源,控制台输出是关键。
第一,确认数据源,保证数据源是正确的。通过Wireshark抓包测试。数据源应该没问题。
第二,确认数据接收是否正确,协议中找到帧编号,打印帧编号。
发现,花屏时,帧编号有异常,丢帧了。通过Wireshark抓包测试,PC接收到的帧是完整的,软件接收到的帧是不连续的。软件接收帧异常。
终于找到突破点,持续控制台监控输出,参考QT源码发现:遇系统进程繁忙时,视频板持续发送视频帧,软件接收时由于系统进程影响,将多视频帧打包在一起,在解包时只解了第一个帧数据,导致后续多个帧数据未解码、显示,导致花屏现象。后续测试,证实了这一问题。
4. 终释然
问题找到后,对解码加了个while,将所有的数据包数据进行全部解析,再显示。数据保存到Stack,这里也出现了一个Bug。Stack是先进后出,并且软件逻辑中将Stack大于1的数据进行Clear,导致依然偶发花屏。随后采用List,取第一个,存入用Add。对数据源进行操作是加lock。
视频终于正常显示,花屏问题无再现。