NVENC HEVC and intra refresh

I am trying to use a Quadro P6000 on CentOS 7 using driver version 390.59 and video codec SDK 8.2.16 to encode HEVC video. If I have intra refresh disabled it works fine. As soon as I enable intra refresh (NV_ENC_CONFIG_HEVC::enableIntraRefresh = true), it fails with error code 8 (NV_ENC_ERR_INVALID_PARAM) on the encoder initialization call on line 273 in NvEncoder.cpp.

I have verified that intra refresh is supported in HEVC on the card by checking the capabilities. I have also tried changing other parameters to see if maybe I have some invalid combination of parameters. I have not been able to get it to work. Also, using the exact same parameters, including enabling intra refresh, with H264 works just fine.

Does anyone have any idea what I may be doing wrong or how to further toubleshoot this?

HEVC + interlaced encoding is not supported anywhere…

Thanks for the reply. I’m new to video codecs. Is interlaced encoding the same as intra refresh?

Assuming the answer is yes, why would the NV_ENC_CONFIG_HEVC struct even have the enableIntraRefresh field? Why would calling NvEncoderCudaInstance.GetCapabilityValue(NV_ENC_CODEC_HEVC_GUID, NV_ENC_CAPS_SUPPORT_INTRA_REFRESH) return 1?

EDIT: Assuming the answer is no, my original question still applies.

Interlaced is completely different from intra refresh. Interlaced content is where a single frame has 2 fields of data. HEVC spec doesn’t support field/interlaced encoding. H.264 spec does support it.

However, intra refresh is an error resiliency feature used in streaming scenarios. Let’s say during a game streaming session, a frame gets corrupted due to errors introduced when the frame is getting transmitted. You can send an IDR frame, but sending an IDR across a low bandwidth transmission medium may not be possible. With intra refresh, you send waves of intra MBs across multiple frames and hence help client recover from error scenarios.

Could you let us know what exactly you are trying to achieve, we can then help you better. Why are you trying to use intra refresh? What is your use-case?

Also, which drivers are you using, and which GPU are you working on?

Thanks,
Ryan Park

Ryan, thank you for your reply and explanations. That matches what I thought but the original reply caused me to doubt my understanding.

I am attempting to generate a low latency real time stream over low bandwidth links as you described. I am attempting to enable intra refresh for the reasons you outlined. Unfortunately I keep getting the error listed in my original post when using HEVC (intra refresh works fine for H264).

As mentioned in my original post, I’m using a Quadro P6000 with driver version 390.59 and video codec version 8.2.16 on CentOS 7. Eventually this will need to work on other GPUs and driver versions, but I need to get intra refresh working first.

Hi,

Have you tried downloading the latest version of the driver version for Linux? Driver version 396.24 or higher is required for Video Codec 8.2.

Thanks,
Ryan Park

I was finally able to get some time to get get back to this. I updated to driver version 410.93 but I still get the same error. Any other ideas?

To summarize, H.264 encoding with or without intra-refresh works fine, but H.265 encoding works only when intra-refresh is turned off.

Can you post the code where you are setting up various NVENC structures? If you have modified the sample app from the SDK, please post the code or send it to me via a PM.

I am able to reproduce the problem with the AppEncCuda sample program with the following modifications.

In the EncodeCuda() function, between these two lines

pEncodeCLIOptions->SetInitParams(&initializeParams, eFormat);

enc.CreateEncoder(&initializeParams);

add the following lines to force intra refresh for both H264 and HEVC.

encodeConfig.gopLength = NVENC_INFINITE_GOPLENGTH;
encodeConfig.frameIntervalP = 1;
encodeConfig.encodeCodecConfig.h264Config.enableIntraRefresh = 1;
encodeConfig.encodeCodecConfig.h264Config.intraRefreshCnt = 30;
encodeConfig.encodeCodecConfig.h264Config.intraRefreshPeriod = 30 * 5;
encodeConfig.encodeCodecConfig.hevcConfig.enableIntraRefresh = 1;
encodeConfig.encodeCodecConfig.hevcConfig.intraRefreshCnt = 30;
encodeConfig.encodeCodecConfig.hevcConfig.intraRefreshPeriod = 30 * 5;

After compiling, I ran it with the following parameters.

./AppEncCuda -i HeavyHand_1080p.yuv -o HeavyHand_1080p.h264 -if iyuv -codec h264 -preset ll -rc constqp -fps 30 -constqp 28
./AppEncCuda -i HeavyHand_1080p.yuv -o HeavyHand_1080p.hevc -if iyuv -codec hevc -preset ll -rc constqp -fps 30 -constqp 28

The first run succeeds while the second run reports this error:

CreateEncoder : m_nvenc.nvEncInitializeEncoder(m_hEncoder, &m_initializeParams) returned error 8 at ../../NvCodec/NvEncoder/NvEncoder.cpp:273

Thanks for taking the time to look at this. Hopefully this will allow you to reproduce the problem as well or to tell me that I am doing something incorrectly.