This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

H.264 encoding with near constant bitrate

Hello all,

we have our application (basically single stream H.264 encoding based directly on LINKAPI) running fine on DVRRDK 4.0 and 4.1.

We want to achieve a sort of constant bitrate behaviour of the encoder. We do not expect every frame to have exact fixed sized especially not as we want and must use I- and P-Frames (and later even B-Frames). Setting the target bitrate works as expected and long term bitrate is well within expected limits. With usual slow moving footage everything is ok. However in extremely dynamic scenes we can observe bitrate peaks of over 50 percent above target bitrate over 2 GOP lengths.

I have played a lot with encodingPreset, rateControlPreset and rcAlg parameters of the encoder link but either the encoder did not accept my parameter combination or the datarate behaviour was not as desired. Increasing qpMax to 51 has already helped a bit but we still see the above mentioned bitrate peaks.

Is there some way that we can force the encoder to limit the bitrate on short term (e.g. GOP length) so that is does not exceed target bitrate by a certain amount? Strong visual degradation in extremely dynamic situations would be acceptable.

Best regards,
Michael

  • Michael,

    Increasing qPMax will certainly help to some extent to control the bitrate peaks. Similar will be the role of qPMin. If you set a higher value for qPMin, you can restrict the variation in quantization to a lesser range. So higher the qP value, lesser will be the bit consumption. But this may affect the visual quality. But since you have mentioned, strong visual degradation would be acceptable, this should be an exercise worth doing.

  • Hello Mohammed,

    thanks for your input. But what I meant with strong visual degradation being acceptable is that the degradation is only acceptable when otherwise the datarate would peak. Increasing qpMin in general and thus limiting visual quality overall is not acceptable.

    Basically I want to tell the encoder to give bitrate constraints higher priority than visual quality.

    Best regards,

    Michael

  • Are you setting maxBitRate param ? Can you share print of static and dynamic params and  attach the encoded h264 bitstream showing the issue.

  • Hello Badri,

    setting maxBitRate to e.g. 9Mbps with targetBitrate of 8Mbps did not change anything. You can download a sample stream that shows the behavior from our website. I have also plotted the moving averag bitrate over one GOP size so that you can easily see the bitrate peaks. Target bitrate was set to 8Mbps for that stream and GOP length is 15 frames (as it is interlaced this will be 30 fields). You can see that the rate control algorithm is trying hard to maintain average bitrate but worst case is almost 50 percent above target bitrate for a GOP. If you look at 2 GOP length average it looks already a lot better.

    The content of the video of course is very constructed but that was an easy way to bring the encoder into the problematic behavior. We have observed those bitrate peaks as well with real application content (though not that often).

    I hope I did not miss any of the important static/dynamic parameters.

    Best regards,

    Michael

    [m3video] H.264 Static params
    [m3video] =============================
    [m3video] videnc2Params.size 312
    [m3video] encodingPreset 3 # User Defined
    [m3video] rateControlPreset 5 # User Defined
    [m3video] videnc2Params.maxHeight 540
    [m3video] videnc2Params.maxWidth 1920
    [m3video] videnc2Params.dataEndianness 1
    [m3video] videnc2Params.maxInterFrameInterval 1
    [m3video] videnc2Params.maxBitRate 4294967295
    [m3video] videnc2Params.minBitRate 0
    [m3video] videnc2Params.inputChromaFormat 9
    [m3video] videnc2Params.inputContentType 1
    [m3video] videnc2Params.operatingMode 1
    [m3video] videnc2Params.profile 100
    [m3video] videnc2Params.level 40
    [m3video] videnc2Params.inputDataMode 3
    [m3video] videnc2Params.outputDataMode 3
    [m3video] videnc2Params.numInputDataUnits 1
    [m3video] videnc2Params.numOutputDataUnits 1
    [m3video] =============================
    [m3video] rateControlParams.rateControlParamsPreset 1
    [m3video] rateControlParams.scalingMatrixPreset 0
    [m3video] rateControlParams.rcAlgo 0
    [m3video] rateControlParams.qpI 4294967295
    [m3video] rateControlParams.qpMaxI 36
    [m3video] rateControlParams.qpMinI 10
    [m3video] rateControlParams.qpP 4294967295
    [m3video] rateControlParams.qpMaxP 40
    [m3video] rateControlParams.qpMinP 10
    [m3video] rateControlParams.qpOffsetB 4
    [m3video] rateControlParams.qpMaxB 44
    [m3video] rateControlParams.qpMinB 10
    [m3video] rateControlParams.allowFrameSkip 0
    [m3video] rateControlParams.removeExpensiveCoeff 0
    [m3video] rateControlParams.chromaQPIndexOffset 0
    [m3video] rateControlParams.IPQualityFactor 0
    [m3video] rateControlParams.initialBufferLevel 2400000
    [m3video] rateControlParams.HRDBufferSize 2400000
    [m3video] rateControlParams.minPicSizeRatioI 0
    [m3video] rateControlParams.maxPicSizeRatioI 640
    [m3video] rateControlParams.minPicSizeRatioP 0
    [m3video] rateControlParams.maxPicSizeRatioP 0
    [m3video] rateControlParams.minPicSizeRatioB 0
    [m3video] rateControlParams.maxPicSizeRatioB 0
    [m3video] rateControlParams.enablePRC 1
    [m3video] rateControlParams.enablePartialFrameSkip 0
    [m3video] rateControlParams.discardSavedBits 0
    [m3video] rateControlParams.VBRDuration 8
    [m3video] rateControlParams.VBRsensitivity 0
    [m3video] rateControlParams.skipDistributionWindowLength 5
    [m3video] rateControlParams.numSkipInDistributionWindow 1
    [m3video] rateControlParams.enableHRDComplianceMode 1
    [m3video] rateControlParams.frameSkipThMulQ5 0
    [m3video] rateControlParams.vbvUseLevelThQ5 0
    [m3video] =============================
    [m3video] interCodingParams.interCodingPreset 0
    [m3video] interCodingParams.searchRangeHorP 144
    [m3video] interCodingParams.searchRangeVerP 32
    [m3video] interCodingParams.searchRangeHorB 144
    [m3video] interCodingParams.searchRangeVerB 16
    [m3video] interCodingParams.interCodingBias 1
    [m3video] interCodingParams.skipMVCodingBias 1
    [m3video] interCodingParams.minBlockSizeP 0
    [m3video] interCodingParams.minBlockSizeB 0
    [m3video] interCodingParams.meAlgoMode 0
    [m3video] =============================
    [m3video] intraCodingParams.intraCodingPreset 0
    [m3video] intraCodingParams.lumaIntra4x4Enable 0
    [m3video] intraCodingParams.lumaIntra8x8Enable 255
    [m3video] intraCodingParams.lumaIntra16x16Enable 15
    [m3video] intraCodingParams.chromaIntra8x8Enable 15
    [m3video] intraCodingParams.chromaComponentEnable 1
    [m3video] intraCodingParams.intraRefreshMethod 0
    [m3video] intraCodingParams.intraRefreshRate 0
    [m3video] intraCodingParams.gdrOverlapRowsBtwFrames 0
    [m3video] intraCodingParams.constrainedIntraPredEnable 0
    [m3video] =============================
    [m3video] nalUnitControlParams.naluControlPreset 1
    [m3video] nalUnitControlParams.naluPresentMaskStartOfSequence 8608
    [m3video] nalUnitControlParams.naluPresentMaskIDRPicture 8672
    [m3video] nalUnitControlParams.naluPresentMaskIntraPicture 8450
    [m3video] nalUnitControlParams.naluPresentMaskNonIntraPicture 2

    [m3video] H.264 Dynamic params
    [m3video] =============================
    [m3video] videnc2DynamicParams.size 236
    [m3video] videnc2DynamicParams.inputHeight 540
    [m3video] videnc2DynamicParams.inputWidth 1920
    [m3video] videnc2DynamicParams.refFrameRate 25000
    [m3video] videnc2DynamicParams.targetFrameRate 25000
    [m3video] videnc2DynamicParams.targetBitRate 8000000
    [m3video] videnc2DynamicParams.intraFrameInterval 15
    [m3video] videnc2DynamicParams.generateHeader 0
    [m3video] videnc2DynamicParams.captureWidth 1920
    [m3video] videnc2DynamicParams.forceFrame 4294967295
    [m3video] videnc2DynamicParams.interFrameInterval 1
    [m3video] videnc2DynamicParams.mvAccuracy 2
    [m3video] videnc2DynamicParams.sampleAspectRatioHeight 1
    [m3video] videnc2DynamicParams.sampleAspectRatioWidth 1
    [m3video] videnc2DynamicParams.ignoreOutbufSizeFlag 1
    [m3video] videnc2DynamicParams.putDataFxn 0
    [m3video] videnc2DynamicParams.putDataHandle 0
    [m3video] videnc2DynamicParams.getDataFxn 0
    [m3video] videnc2DynamicParams.getDataHandle 0
    [m3video] videnc2DynamicParams.getBufferFxn 2378726017
    [m3video] videnc2DynamicParams.getBufferHandle 0
    [m3video] videnc2DynamicParams.lateAcquireArg 4294967295
    [m3video] =============================
    [m3video] rateControlParams.rateControlParamsPreset 1
    [m3video] rateControlParams.scalingMatrixPreset 0
    [m3video] rateControlParams.rcAlgo 0
    [m3video] rateControlParams.qpI 4294967295
    [m3video] rateControlParams.qpMaxI 51
    [m3video] rateControlParams.qpMinI 10
    [m3video] rateControlParams.qpP 4294967295
    [m3video] rateControlParams.qpMaxP 51
    [m3video] rateControlParams.qpMinP 10
    [m3video] rateControlParams.qpOffsetB 4
    [m3video] rateControlParams.qpMaxB 44
    [m3video] rateControlParams.qpMinB 10
    [m3video] rateControlParams.allowFrameSkip 0
    [m3video] rateControlParams.removeExpensiveCoeff 1
    [m3video] rateControlParams.chromaQPIndexOffset 0
    [m3video] rateControlParams.IPQualityFactor 0
    [m3video] rateControlParams.initialBufferLevel 2400000
    [m3video] rateControlParams.HRDBufferSize 2400000
    [m3video] rateControlParams.minPicSizeRatioI 0
    [m3video] rateControlParams.maxPicSizeRatioI 0
    [m3video] rateControlParams.minPicSizeRatioP 0
    [m3video] rateControlParams.maxPicSizeRatioP 0
    [m3video] rateControlParams.minPicSizeRatioB 0
    [m3video] rateControlParams.maxPicSizeRatioB 0
    [m3video] rateControlParams.enablePRC 1
    [m3video] rateControlParams.enablePartialFrameSkip 0
    [m3video] rateControlParams.discardSavedBits 1
    [m3video] rateControlParams.VBRDuration 8
    [m3video] rateControlParams.VBRsensitivity 0
    [m3video] rateControlParams.skipDistributionWindowLength 0
    [m3video] rateControlParams.numSkipInDistributionWindow 0
    [m3video] rateControlParams.enableHRDComplianceMode 1
    [m3video] rateControlParams.frameSkipThMulQ5 0
    [m3video] rateControlParams.vbvUseLevelThQ5 0
    [m3video] =============================
    [m3video] interCodingParams.interCodingPreset 0
    [m3video] interCodingParams.searchRangeHorP 144
    [m3video] interCodingParams.searchRangeVerP 32
    [m3video] interCodingParams.searchRangeHorB 144
    [m3video] interCodingParams.searchRangeVerB 16
    [m3video] interCodingParams.interCodingBias 1
    [m3video] interCodingParams.skipMVCodingBias 1
    [m3video] interCodingParams.minBlockSizeP 0
    [m3video] interCodingParams.minBlockSizeB 0
    [m3video] interCodingParams.meAlgoMode 0
    [m3video] =============================
    [m3video] intraCodingParams.intraCodingPreset 0
    [m3video] intraCodingParams.lumaIntra4x4Enable 0
    [m3video] intraCodingParams.lumaIntra8x8Enable 255
    [m3video] intraCodingParams.lumaIntra16x16Enable 15
    [m3video] intraCodingParams.chromaIntra8x8Enable 15
    [m3video] intraCodingParams.chromaComponentEnable 1
    [m3video] intraCodingParams.intraRefreshMethod 0
    [m3video] intraCodingParams.intraRefreshRate 0
    [m3video] intraCodingParams.gdrOverlapRowsBtwFrames 0
    [m3video] intraCodingParams.constrainedIntraPredEnable 0
    [m3video] intraCodingParams.intraCodingBias 0
    [m3video] =============================
    [m3video] sliceCodingParams.sliceCodingPreset 0
    [m3video] sliceCodingParams.sliceMode 0
    [m3video] sliceCodingParams.sliceUnitSize 0
    [m3video] sliceCodingParams.sliceStartOffset[0] 0
    [m3video] sliceCodingParams.sliceStartOffset[1] 0
    [m3video] sliceCodingParams.sliceStartOffset[2] 0
    [m3video] sliceCodingParams.streamFormat 0
    [m3video] =============================
    [m3video] sliceGroupChangeCycle 0
    [m3video] searchCenter.x 32767
    [m3video] searchCenter.y 32767
    [m3video] enableStaticMBCount 0
    [m3video] enableROI 0
    [m3video] =============================

  • Are you intentionally disabling frameSkip ?

    allowFrameSkip = 1

    enablePartialFrameSkip = 1

    numSkipInDistributionWindow = 2

    skipDistributionWindowLength = 5

    should be enabled if your application allows frame skip and strictly meeting targetBitrate is critical

  • Hello Badri,

    we are using Link API and those parameters are not exposed by EncLink_ChCreateParams. I will modify the Link API to expose those parameters and give it a try. I will let you know if that helps and the resulting stream is suitable for our needs.

    Best regards,

    Michael

  • The encoded bitstream you shared is interlaced field picture content. Can you confirm that you are encoding interlaced and not progressive content ?

    Only VBR is supported when doing interlaced encoding so bitrate variation is expected.skipFrame are also not supported when doing VBR encoding of field pictures.

  • Hello Badri,

    it is correct and intended that the stream is interlaced. We must support a variety of picture formats including PAL/576i50, 720p50, 1080i50 and in future also the 60Hz variants and NTSC.

    We know that we will not achieve real CBR but we want to come as close as possible. Is there anything that we can do to prevent those larger bitrate peaks.

    Best regards,

    Michael

  • Michael,

    It seems like the issue is happening particularly in your test case. With the test streams at our side, rate control behavior was as expected and we were unable to reproduce the issue.

    Can you please share the original content (where you observe the issue) encoded at a very high bitrate so that we will take the same and try out the required experiments with the same content ?

    Meanwhile, you can try enabling the scaling matrix in the encoder configuration. This might help you to reduce the bitrate peaks to some extent.

  • Michael, 

    Another suggestion is to reduce the HRDBufferSize. This may reduce the bitrate peaks you are observing. But the visual quality will have to be compromised to some extent.

    For example,

    Current parameters are 

    targetBitRate                   =     8000000
    HRDBufferSize               =     2400000   (= 0.3 x targetBitRate)
    initialBufferLevel            =     2400000

    Suggested change of parameters are

    targetBitRate                   =     8000000
    HRDBufferSize               =     800000    (= 0.1 x targetBitRate)
    initialBufferLevel            =     800000

     

  • Hello Mohammed,

    I have uploaded a sample source stream to our website. This was captured with a consumer HD camcorder and we can observe the bitrate peaks when encoding the playback of the camera. I hope this stream helps to reproduce our issue.

    We have also experimented with reduction of HRDBufferSize but this also imposes quite strong quality reduction in scenes that were perfectly well int terms of bit rate with larger HRDBufferSize. But at least we can use that as a fallback if we really need to guarantee bit rate limits.

    Thanks for looking into it.

    Best regards,

    Michael