Search code examples
c++encodingh.264hevcnvenc

Nvidia NvEnc with HVEC causes Div by Zero


I'm trying to build a hardware encoder using Nvidias NvEnc API. This API provides the use of two codecs for encoding any given data: H264 and HEVC. So at first one has to choose one of the two codes, and afterwards configure the encoding session or use one of varios presets. I'm doing it like described in Nvidias NvEnc Programming Guide.

I have the following piece of code causing the problem when using HVEC codec:

//Create Init Params
InitParams* ip = new InitParams();

ip->encodeGUID = m_encoderGuid; //encoder GUID is either H264 or HEVC
ip->encodeWidth = width;
ip->encodeHeight = height;
ip->version = NV_ENC_INITIALIZE_PARAMS_VER;
ip->presetGUID = m_presetGuid; //One of the presets
ip->encodeConfig = NULL; //If using preset, further config should be set to NULL

//Async Encode
ip->enableEncodeAsync = 1;

//Send the InputBuffer in Display Order
ip->enablePTD = 1;

//Causing Div by Zero error if used with HEVC GUID:
CheckApiError(m_apiFunctions.nvEncInitializeEncoder(m_Encoder, ip));

So the thing is again: I'm using the H264 GUID and everything runs through. If i use HEVC I get a Div by Zero... I dont get some error code from the api call, just a plain div by zero error. So my question is: Does HEVC need more information that I do not provide by using a preset? If so, what kind of information?

Thanks a lot!

Edit: Solved it. The Programming Guide didn't state, that these fields must be set, but NV_ENC_INITIALIZE_PARAMS consist of frameRateNum and frameRateDen which caused the div by zero... Dunno why this doesn't happen when using H264. Someone may close this..


Solution

  • So this is the configuration i did, according to NVidias programming guide. As stated above, not providing values for frameRateNum and frameRateDen resulted in a Div by Zero error, especially after an initial memset.

    //Create Init Params
    InitParams* ip = new InitParams();
    m_initParams = ip;
    memset(ip, 0, sizeof(InitParams));
    
    //Set Struct Version
    ip->version = NV_ENC_INITIALIZE_PARAMS_VER;
    
    //Used Codec
    ip->encodeGUID = m_encoderGuid;
    
    //Size of the frames
    ip->encodeWidth = width;
    ip->encodeHeight = height;
    
    //Set to 0, no dynamic resolution changes!
    ip->maxEncodeWidth = 0;
    ip->maxEncodeHeight = 0;
    
    //Aspect Ratio
    ip->darWidth = width;
    ip->darHeight = height;
    
    // Frame rate
    ip->frameRateNum = 60;
    ip->frameRateDen = 1;
    
    //Misc
    ip->reportSliceOffsets = 0;
    ip->enableSubFrameWrite = 0;
    
    //Preset GUID
    ip->presetGUID = m_presetGuid;
    
    //Apply Preset
    NV_ENC_PRESET_CONFIG presetCfg;
    memset(&presetCfg, 0, sizeof(NV_ENC_PRESET_CONFIG));
    presetCfg.version = NV_ENC_PRESET_CONFIG_VER;
    presetCfg.presetCfg.version = NV_ENC_CONFIG_VER;
    CheckApiError(m_apiFunctions.nvEncGetEncodePresetConfig(m_Encoder,
        m_encoderGuid, m_presetGuid, &presetCfg));
    // Copy the Preset Config to member var
    memcpy(&m_encodingConfig, &presetCfg.presetCfg, sizeof(NV_ENC_CONFIG));
    /************************************************************************/
    /* Room for Config Adjustments                                          */
    /************************************************************************/
    
    //Set Init configs encoding config
    ip->encodeConfig = &m_encodingConfig;
    
    //Async Encode!
    ip->enableEncodeAsync = 1;
    
    //Send the InputBuffer in Display Order
    ip->enablePTD = 1;
    
    
    CheckApiError(m_apiFunctions.nvEncInitializeEncoder(m_Encoder, ip));