FFmpeg 解码 H.264 视频出现花屏和马赛克的解决办法

FFmpeg 解码 H.264 视频出现花屏和马赛克的解决办法

FFmpeg 解码 H.264 视频出现花屏和马赛克的解决办法

四个可能的原因

  1. 发送数据包太大,超过了 FFmpeg 的默认最大值。
  2. 网络情况较差时,因网络状况出现的丢包。
  3. 解码出错。
  4. 包乱序。

原因一的解决方法

一种方法是控制播放源的发送数据大小,但这极大浪费了当前的网络带宽,非优选方案。

更好的做法是扩大接收端的接收缓冲区,其修改方法为:

在 FFmpeg 的源码中,找到 udp.c 文件并修改 UDP_MAX_PKT_SIZE 默认值。

这里将 UDP_MAX_PKT_SIZE × 10,将缓冲区扩大了10倍。

原因二的解决方法

排查方法:

  1. 设全局变量:在丢包时将全局变量置为不同的值,最后在使用的地方根据全局变量的值来判断该帧是否完整,全局变量可在 FFmpeg 任意的头文件中设置(比如 avcodec.h)。
  2. 修改rtpdec.c文件包含 missed %d package 的地方,这里出现丢包,需修改代码,对帧序号作标记。

在接收端根据RTP包的SeqNumber来判断是否丢包,如果丢包就标记一下。在mark为1或时间戳改变的时候,说明一帧结束了,此时如果标记为丢包了,就扔掉数据,没有丢包就给解码器。如果丢包的帧为I帧,则不仅丢掉当前I帧,此I帧之后的P帧也要丢掉,也就是说在下一个I帧到来之前,所有过来的包都丢掉,然后开始判断收到的RTP包是不是I帧。

判断函数:

cpp 复制代码
static bool isH264iFrame(byte[] paket)
{
	int RTPHeaderBytes = 0;

	int fragment_type = paket[RTPHeaderBytes + 0] & 0x1F;
	int nal_type = paket[RTPHeaderBytes + 1] & 0x1F;
	int start_bit = paket[RTPHeaderBytes + 1] & 0x80;

	if (((fragment_type == 28 || fragment_type == 29) && nal_type == 5 && start_bit == 128) ||
		fragment_type == 5 || fragment_type == 7 || fragment_type == 8)
	{
		return true;
	}

	return false;
}

原因三的解决方法

排查方法:

  1. 设全局变量:在解码出错时将全局变量置为不同的值,最后在使用的地方根据全局变量的值来判断该帧是否完整,全局变量可在 FFmpeg 任意的头文件中设置(比如 avcodec.h)。
  2. 修改error_resilience.c文件 包含concealing %d DC, %d AC, %d MV errors in %c frame的地方。这里出现解包错误,需标记。
  3. 修改h264_cavlc.c文件中包含 Invalid level prefix处 这里出错,需标记。
    修改h264_cavlc.c文件中包含dquant out of range处,出错,需标记。
    修改h264_cavlc.c文件中包含corrupted macroblock处,出错,需标记。
    修改h264_cavlc.c文件中包含negative number of zero coeffs at处,出错,需标记。
    修改h264_cavlc.c文件中包含mb_type %d in %c slice too large at %d %d处,出错,需标记。
    修改h264_cavlc.c文件中包含cbp too large处,出错,需标记。
  4. 修改error_resilience.c文件中包含Cannot use previous picture in error concealment处,出错,需标记。
    修改error_resilience.c文件中包含Cannot use next picture in error concealment处,出错,需标记。
  5. 修改h264.c文件中包含out of range intra chroma pred mode at处,出错,需标记。
    修改h264.c文件中包含top block unavailable for requested intra mode at处,出错,需标记。
    修改h264.c文件中包含left block unavailable for requested intra mode at处,出错,需标记。
  6. 修改h264_slice.c文件中包含error while decoding MB处,出错,需标记。
  7. 修改svq3.c文件中包含error while decoding MB处,出错,需标记。

当我们从网络中接收到RTP包,去了包头,拿到Payload数据之后一般就会送去解码,但是如果直接送去解码器解码,很可能会出现花屏。这个问题我很早就遇到过,当时查阅过资料,发现送给H264解码器的必须是一个NALU单元,或者是完整的一帧数据(包含H264 StartCode),也就是说我们拿到Payload数据之后,还要将分片的数据组成一个NALU或完整的一帧之后才送给解码器。

原因四的解决方法

打印RTP包的SeqNumber看有没有不连续或乱序的问题,如果是用UDP传输,则RTP包容易发生乱序,需要对包按顺序进行重组再解码。

参考

  1. https://blog.csdn.net/zhoubotong2012/article/details/103002257
  2. https://blog.csdn.net/c_base_jin/article/details/106772949
  3. https://blog.csdn.net/sz76211822/article/details/87797475
  4. https://www.ebaina.com/articles/140000016765
相关推荐
ai产品老杨2 小时前
H264 H265视频分析常见问题和排查清单
人工智能·算法·音视频
“码”力全开2 小时前
AI视频分析API性能优化指南
人工智能·性能优化·音视频
美狐美颜SDK开放平台4 小时前
Android/iOS直播APP平台开发中的视频美颜SDK优化技巧
android·ios·音视频·美颜sdk·第三方美颜sdk
AI服务老曹6 小时前
视觉算法模型管理完整流程:多版本上线、灰度发布与回滚的落地实践
人工智能·docker·音视频
AaronZZH8 小时前
AAF 框架能力介绍:图文音视频一站式 AIGC 模块上线
aigc·音视频
Mister Leon9 小时前
视频时序数据处理:CNN+LSTM
cnn·音视频·lstm
俊哥工具10 小时前
解决文件正在使用无法删除,顽固文件清理工具超好用
智能手机·电脑·word·音视频·媒体
AI服务老曹11 小时前
AI视频平台登录无反应性能优化指南:从接口失效到服务自启动的排查全解
人工智能·性能优化·音视频
Digitally12 小时前
7 种方法将三星S26/S25/S24/S23手机视频传电脑
智能手机·电脑·音视频
luoyayun36113 小时前
Qt + FFmpeg 音频工具:重采样实现
qt·ffmpeg·重采样