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
相关推荐
ffyyhh99551131 分钟前
java进行音视频的拆分和拼接
java·音视频
易板2 小时前
ES7210高性能四通道音频ADC转换模拟麦克风为IIS数字咪头
单片机·嵌入式硬件·iis·音视频·麦克风
安步当歌11 小时前
【FFmpeg】av_write_trailer函数
c语言·c++·ffmpeg·视频编解码·video-codec
TMS320VC5257H14 小时前
ffmpeg在powershell和ubuntu终端下的不同格式
linux·ubuntu·ffmpeg
原来4515 小时前
rtpengine_mr12.0 基础建设&&容器运行
音视频·ims·rtpengine
万岳科技系统开发17 小时前
短视频商城系统源码揭秘:架构设计与实现
音视频
TSINGSEE1 天前
视频技术助力智慧城市一网统管:视频资源整合与智能化管理
人工智能·ai·音视频·智慧城市·城市安防监控系统
简鹿办公1 天前
M3U8 视频是一种什么格式,M3U8 视频怎么转成 MP4
音视频
打开官网1 天前
如何压缩视频大小,怎么压缩视频
音视频
小周爱学习€1 天前
OPENCV(视频入门笔记)
笔记·opencv·音视频