Nvidia视频解码200ms延迟定位(解决)

文章讲述了在使用Nvidia解码器时遇到的视频解码延迟问题,通过调整显示缓存参数、启用帧标识符以及避免设置pfnDecodePicture回调,作者解决了实时RTSP流的解码延迟问题,特别是针对不包含B帧的情况。
摘要由CSDN通过智能技术生成

1、问题描述

在进行推理延迟定位的时候,发现了视频解码延迟问题,使用相同的拉流SDK,最后的解码视频显示不能保持一致。流程如下图所示:
解码流程

2、解决尝试

查阅资料,Nvidia提供了如下的减少延迟的参数:
由于SDK接口封装的很好,能操作的没啥东西。

// 减少显示缓存数量
videoParserParameters.ulMaxDisplayDelay = bLowLatency ? 0 : 2;
// 添加一帧标识符
packet.flags = CUVID_PKT_TIMESTAMP | CUVID_PKT_ENDOFPICTURE;

// 手动取出,原谅我这里什么都取不出来,timestamp号也没有
if (m_bForce_zero_latency && ((!pPicParams->field_pic_flag) || (pPicParams->second_field)))
{
	CUVIDPARSERDISPINFO dispInfo;
	memset(&dispInfo, 0, sizeof(dispInfo));
	dispInfo.picture_index = pPicParams->CurrPicIdx;
	dispInfo.progressive_frame = !pPicParams->field_pic_flag;
	dispInfo.top_field_first = pPicParams->bottom_field_flag ^ 1;
	LOG_INFO("come into HandlePictureDisplay. timestamp={0}?", dispInfo.timestamp);
	HandlePictureDisplay(&dispInfo);
}

也查了一些官网的帖子,也没有任何发现什么解决方案。
查阅官方文档,发现了这么一句话:
在这里插入图片描述
大致意思是,Nvidia解码是数据驱动的,输入会将数据输入到一个队列里面,输出会将数据进行解码,队列的大小是4,只要不满,就一直向里面塞数据。

文档地址

此时,我已经高度怀疑是这个队列导致的200ms的延迟了。可惜的是,这个队列没有任何接口可以控制,唯一可以刷新的是发送EOS流,而发送EOS流意味着解码器不再工作。

3、运行测试

运行日志中显示,第5帧的时候才触发了第一帧的输出,即输入队列塞满不再工作后,触发了解码操作。
在这里插入图片描述
目前,定位到了问题所在,但是没有解决方案!!!

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

更新 2024-05-28

参考连接(大佬):
https://forums.developer.nvidia.com/t/video-sdk-decoder-or-encoder-have-always-5-frames-buffer-dpb-buffer-or-some-other-frame-buffer/65848/4
之前一直怀疑是nvidia解码中内部缓存机制造成的解码延迟,今天再次对问题进行解决尝试,才发现问题在nvcuvid的显示回调pfnDisplayPicture的触发上。
在配置pfnDecodePicture 回调函数后,ulMaxDisplayDelay 即使设置为0,也会导致解码有3-4帧的延迟。

测试环境, CPU:i7 9700KF,GPU:3080TI
修改代码部分如下

关闭解码显示回调函数:

if (m_bForce_zero_latency)
{
	bLowLatency = true;
}
videoParserParameters.ulMaxNumDecodeSurfaces = 1;
videoParserParameters.ulClockRate = 10000;
videoParserParameters.ulMaxDisplayDelay = bLowLatency ? 0 : 2;  // 这里如果设置为2,则会由1到2帧的延迟
videoParserParameters.pUserData = this;
videoParserParameters.pfnSequenceCallback = HandleVideoSequenceProc;
videoParserParameters.pfnDecodePicture = HandlePictureDecodeProc;
// 如果是实时RTSP,没有B帧,可以直接关闭pfnDisplayPicture,设置为NULL,如果这里设置了回调函数,至少有3-4帧的延迟
videoParserParameters.pfnDisplayPicture = m_bForce_zero_latency ? NULL : HandlePictureDisplayProc;

对裸码流添加如下符号:

CUVIDSOURCEDATAPACKET packet = { 0 };
packet.flags = CUVID_PKT_TIMESTAMP | CUVID_PKT_ENDOFPICTURE;  // 不设置CUVID_PKT_ENDOFPICTURE,会有一帧延迟

在HandlePictureDecode回调最后添加:

if (m_bForce_zero_latency && ((!pPicParams->field_pic_flag))) //  || (pPicParams->second_field)))
{
	CUVIDPARSERDISPINFO dispInfo;
	memset(&dispInfo, 0, sizeof(dispInfo));
	dispInfo.picture_index = pPicParams->CurrPicIdx;
	dispInfo.progressive_frame = !pPicParams->field_pic_flag;
	dispInfo.top_field_first = pPicParams->bottom_field_flag ^ 1;
	std::unique_lock<std::shared_mutex> lk(thread_mutex);
	// TODO 这里直接使用最新的时间戳,正常情况下这个时间戳是正确的,异常情况下,时间戳对不对不重要了
	dispInfo.timestamp = m_push_date_node;
	lk.unlock();
	HandlePictureDisplay(&dispInfo);  // 取数据函数,对应pfnDisplayPicture函数,这里自己触发
}

配置上述三处地方,就可以解决解码延迟问题,需要注意的是,这里只适合实时的RTSP流,每一帧码流数据都能解出一帧图像,不包含B帧。

至此,通过避开设置pfnDecodePicture回调方式,nvidia解码延迟问题解决。

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值