How do you reconfigure the bitrate during encoding?


In the past few weeks, I have been trying to change the bitrate of an encoded video on the fly. I am doing real-time game live streaming, and being able to do this would be helpful.

I have not found any solution to this, but I found this in NvEncodeAPI.h:

 * Indicates Dynamic Encode Bitrate Change Support.
 * Support added from NvEncodeAPI version 2.0.
 * \n 0 : Dynamic Encode bitrate change not supported.
 * \n 1 : Dynamic Encode bitrate change supported.

I have not found this usage of NV_ENC_CAPS_SUPPORT_DYN_BITRATE_CHANGE anywhere else in the whole Video SDK, so I am wondering: is this available for us to use? How would I get around to using it?

I found a function called NvEncReconfigureEncoder that allows the bitrate and resolution of the encoded video to change during encoding.

I gave it a shot, and reconfiguring the bitrate does not work. Reconfiguring the resolution works (though not perfectly - it ends up cropped if reducing resolution).

I also went to check the capabilities via NvEncGetEncodeCaps. NV_ENC_CAPS_SUPPORT_DYN_BITRATE_CHANGE is supported.

I used the NvEncoder sample. What I did was call NvEncReconfigureEncoder in the CNvEncoder::EncodeMain function in NvEncoder.cpp, where the encoding loop occurs (line 20-30 below):

for (int frm = encodeConfig.startFrameIdx; frm <= encodeConfig.endFrameIdx; frm++)
    numBytesRead = 0;
    loadframe(yuv, hInput, frm, encodeConfig.width, encodeConfig.height, numBytesRead, encodeConfig.isYuv444);
    if (numBytesRead == 0)

    EncodeFrameConfig stEncodeFrame;
    memset(&stEncodeFrame, 0, sizeof(stEncodeFrame));
    stEncodeFrame.yuv[0] = yuv[0];
    stEncodeFrame.yuv[1] = yuv[1];
    stEncodeFrame.yuv[2] = yuv[2];

    stEncodeFrame.stride[0] = encodeConfig.width;
    stEncodeFrame.stride[1] = (encodeConfig.isYuv444) ? encodeConfig.width : encodeConfig.width / 2;
    stEncodeFrame.stride[2] = (encodeConfig.isYuv444) ? encodeConfig.width : encodeConfig.width / 2;
    stEncodeFrame.width = encodeConfig.width;
    stEncodeFrame.height = encodeConfig.height;
    // ... original stuff above ...
    if (frm == encodeConfig.endFrameIdx / 2)
        NvEncPictureCommand encPicCommand;
        encPicCommand.bBitrateChangePending = true;
        encPicCommand.newVBVSize = encodeConfig.vbvSize;
        encPicCommand.newBitrate = 250000;
        NVENCSTATUS status = m_pNvHWEncoder->NvEncReconfigureEncoder(&encPicCommand);
        // status returns NV_ENC_SUCCESS
    // ... original stuff below ...
    EncodeFrame(&stEncodeFrame, false, encodeConfig.width, encodeConfig.height);

Did anyone else manage to get NvEncReconfigureEncoder to work? Maybe I did it wrongly?


A few questions:

  1. What is the SDK package version that you are using?
  2. What driver version are you using?
  3. Can you try reconfiguring the bitrate only? What is the result?



  1. I am using Video Codec SDK 6.0.1
  2. 369.49. This is the latest driver for the GRID K520.
  3. I have done that in my 2nd post and it has no effect. The file size of the video with and without the reconfiguration is exactly the same.

Edit: I gave the wrong SDK version earlier


It turns out that the rate control mode is the culprit. The default setting without any -options is “constant QP”, which ignores any bitrate settings.

Changing the -rcmode to “Single pass VBR” solves this issue.