CUDA H.265解码器初始化失败:cuvidCreateDecoder返回无效值
使用NVIDIA Video Codec SDK解码192x168 H.265帧时cuvidCreateDecoder返回CUDA_ERROR_INVALID_VALUE的问题排查
调用cuvidCreateDecoder初始化解码器时触发断言,返回CUDA_ERROR_INVALID_VALUE错误,当前解码目标是分辨率192x168的H.265帧。
相关代码
int NvDecoder::HandleVideoSequence(CUVIDEOFORMAT* pVideoFormat) { int nDecodeSurface = pVideoFormat->min_num_decode_surfaces; // eCodec has been set in the constructor (for parser). Here it's set again // for potential correction m_eCodec = pVideoFormat->codec; m_eChromaFormat = pVideoFormat->chroma_format; m_nBitDepthMinus8 = pVideoFormat->bit_depth_luma_minus8; m_nBPP = m_nBitDepthMinus8 > 0 ? 2 : 1; m_eOutputFormat = cudaVideoSurfaceFormat_NV12; m_videoFormat = *pVideoFormat; CUVIDDECODECREATEINFO videoDecodeCreateInfo = {0}; videoDecodeCreateInfo.CodecType = pVideoFormat->codec; videoDecodeCreateInfo.ChromaFormat = pVideoFormat->chroma_format; videoDecodeCreateInfo.OutputFormat = m_eOutputFormat; videoDecodeCreateInfo.bitDepthMinus8 = pVideoFormat->bit_depth_luma_minus8; if (pVideoFormat->progressive_sequence) videoDecodeCreateInfo.DeinterlaceMode = cudaVideoDeinterlaceMode_Weave; else videoDecodeCreateInfo.DeinterlaceMode = cudaVideoDeinterlaceMode_Adaptive; videoDecodeCreateInfo.ulNumOutputSurfaces = 2; // With PreferCUVID, JPEG is still decoded by CUDA while video is decoded by // NVDEC hardware videoDecodeCreateInfo.ulCreationFlags = cudaVideoCreate_PreferCUVID; videoDecodeCreateInfo.ulNumDecodeSurfaces = nDecodeSurface; videoDecodeCreateInfo.vidLock = m_ctxLock; videoDecodeCreateInfo.ulWidth = pVideoFormat->coded_width; videoDecodeCreateInfo.ulHeight = pVideoFormat->coded_height; if (m_nMaxWidth < (int)pVideoFormat->coded_width) m_nMaxWidth = pVideoFormat->coded_width; if (m_nMaxHeight < (int)pVideoFormat->coded_height) m_nMaxHeight = pVideoFormat->coded_height; videoDecodeCreateInfo.ulMaxWidth = m_nMaxWidth; videoDecodeCreateInfo.ulMaxHeight = m_nMaxHeight; videoDecodeCreateInfo.ulTargetWidth = m_nWidth; videoDecodeCreateInfo.ulTargetHeight = m_nLumaHeight; m_nChromaHeight = (int)(ceil(m_nLumaHeight * GetChromaHeightFactor(m_eOutputFormat))); m_nNumChromaPlanes = GetChromaPlaneCount(m_eOutputFormat); m_nSurfaceHeight = videoDecodeCreateInfo.ulTargetHeight; m_nSurfaceWidth = videoDecodeCreateInfo.ulTargetWidth; m_displayRect.b = videoDecodeCreateInfo.display_area.bottom; m_displayRect.t = videoDecodeCreateInfo.display_area.top; m_displayRect.l = videoDecodeCreateInfo.display_area.left; m_displayRect.r = videoDecodeCreateInfo.display_area.right; videoDecodeCreateInfo.ulIntraDecodeOnly = 1; CUDA_DRVAPI_CALL(cuCtxPushCurrent(m_cuContext)); NVDEC_API_CALL(cuvidCreateDecoder(&m_hDecoder, &videoDecodeCreateInfo)); // asserts fail, return 1 CUDA_DRVAPI_CALL(cuCtxPopCurrent(NULL)); return nDecodeSurface; }
环境信息
- NVIDIA GeForce RTX 3060
- NVIDIA-SMI 470.141.03,驱动版本:470.141.03,CUDA版本:11.4
- nvidia_video_codec_sdk 11.1.5
排查方向与解决办法
1. 分辨率对齐问题(最可能原因)
NVDEC硬件解码对H.265的分辨率有严格对齐要求:编码宽度和高度必须是16的倍数。当前目标分辨率192x168中,168不是16的整数倍(16×10=160,16×11=176),这会直接触发CUDA_ERROR_INVALID_VALUE。
解决:
- 确认输入视频流的编码分辨率是否确实为192x168,若是,需要先将视频流的编码分辨率调整为符合16x16对齐的数值(比如192x176);
- 若无法修改输入流,可在初始化解码器时,将
videoDecodeCreateInfo.ulWidth和videoDecodeCreateInfo.ulHeight手动设置为对齐后的分辨率(注意需确保与实际流的编码参数兼容)。
2. 输出分辨率参数检查
ulTargetWidth和ulTargetHeight(对应代码中的m_nWidth和m_nLumaHeight)是解码器输出的目标分辨率,NV12格式要求:
- 宽度必须是16的倍数;
- 高度必须是2的倍数。
解决:
- 打印
m_nWidth和m_nLumaHeight的值,确认是否符合上述要求,若不符合则调整为合法值。
3. 解码表面数量参数验证
ulNumDecodeSurfaces直接使用pVideoFormat->min_num_decode_surfaces,部分场景下该值可能不符合硬件实际要求(过小或过大)。
解决:
- 尝试手动设置一个合理值(比如4)替代
nDecodeSurface,测试是否能正常初始化解码器。
4. 仅解码I帧参数检查
代码中videoDecodeCreateInfo.ulIntraDecodeOnly = 1,表示解码器仅解码I帧。若输入流中包含P/B帧,会导致参数不匹配。
解决:
- 暂时将该值设为0,排除该参数的影响,测试解码器是否能正常初始化。
内容的提问来源于stack exchange,提问作者375
相关产品推荐
相关产品推荐

