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
相关推荐
进击ing小白3 分钟前
FFmpeg的基本概述(二)
ffmpeg
小曾同学.com8 小时前
【每天学点‘音视频’】前向纠错 和 漏包重传
音视频·fec·前向纠错
胖虎18 小时前
(二十)深入了解 AVFoundation-编辑:使用 AVMutableVideoComposition 实现视频加水印与图层合成(下)——实战篇
音视频·视频编辑·视频添加水印
AI浩9 小时前
跟踪不稳定目标:基于外观引导的运动建模实现无人机视频中的鲁棒多目标跟踪
目标跟踪·音视频·无人机
小学生波波11 小时前
如何免费给视频加字幕
音视频·免费字幕·加字幕·剪映加字幕
0x000717 小时前
C#项目集成海康SDK指南:从搭建环境到实现视频预览、录制、截屏
音视频
音视频牛哥18 小时前
如何计算 PCM 音频与 YUV/RGB 原始视频文件大小?
音视频·pcm·大牛直播sdk·rtsp播放器·rtmp播放器·yuv rgb计算大小·pcm计算大小
音视频牛哥20 小时前
从H.264到AV1:音视频技术演进与模块化SDK架构全解析
人工智能·音视频·大牛直播sdk·rtsp h.265·h.264 h.265 av1·h.265和h.266·enhenced rtmp
Antonio91521 小时前
【音视频】WebRTC 一对一通话 peerconnection_client 分析
音视频·webrtc
恒拓高科WorkPlus1 天前
局域网视频软件BeeWorks,内网顺畅沟通
音视频