H.264 HW Encoder - Issues with Constant bit rate (CBR)

Hello Every one,

I am trying to set constant-bit rate mode, in H.264 encoder in Jetson TK1 for encoding a 720P video. Below is my encoder configuration.

mOutputFormat->setInt32(
            "color-format", OMX_COLOR_FormatYUV420Planar);
    mOutputFormat->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
    mOutputFormat->setInt32("width", width);
    mOutputFormat->setInt32("height", height);


    mOutputFormat->setInt32("bitrate", 768000);
    mOutputFormat->setInt32("bitrate-mode", OMX_Video_ControlRateConstant);
    mOutputFormat->setInt32("frame-rate", mFrameRate);
    mOutputFormat->setInt32("i-frame-interval", 1);  // Iframes every 1 secs
    mOutputFormat->setInt32("profile", OMX_VIDEO_AVCProfileBaseline);
    mOutputFormat->setInt32("level", OMX_VIDEO_AVCLevel13);

Here I used “OMX_Video_ControlRateConstant” as bitrate-mode. But the output bitrate from the hardware encoder is not constant. There is no difference between in setting “OMX_Video_ControlRateConstant” and “OMX_Video_ControlRateVariable”.

The bitrate output is always varying. Do you have any ideas about this issue?

Thanks.

Hi Gopinath,
Please try to set 1Mbps, 2Mbps. Probably 768kbps is too low for 720p case.

Hi DaneLLL,

Thanks for the reply. I have changed the bitrate to 2Mbps. But still I am getting the same results.

This is how, I am checking and printing the bitrate(size).

// get output
        size_t index;
        size_t offset;
        size_t size;
        int64_t presentationTimeUs;
        uint32_t flags;
        status_t err = mCodec->dequeueOutputBuffer(
                &index, &offset, &size, &presentationTimeUs, &flags,
                kTimeout);

        if (err == OK) {
            ALOGE("draining output buffer %d, time = %lld us Size = %d ",
                  index, presentationTimeUs,size);

            if (mNumBuffersEncoded == 0) {
                int64_t timeUs = ALooper::GetNowUs();
                fprintf(stderr, "enc latency = %llu us", timeUs - startTimeUs);
            }

I am expecting the output of dequeue buffer (i.e) size to be same all the time. But In some cases I am getting different size. Please see the below output.

E/AEncode ( 1412): draining output buffer 0, time = 0 us Size = 22 
E/AEncode ( 1412): draining output buffer 1, time = 0 us Size = <b>2728</b> 
E/AEncode ( 1412): draining output buffer 2, time = 33333 us Size = 4097 
E/AEncode ( 1412): draining output buffer 3, time = 66666 us Size = 4098 
E/AEncode ( 1412): draining output buffer 4, time = 100000 us Size = 4093 
E/AEncode ( 1412): draining output buffer 5, time = 133333 us Size = 4096 
E/AEncode ( 1412): draining output buffer 0, time = 166666 us Size = 4096 
E/AEncode ( 1412): draining output buffer 1, time = 200000 us Size = 4096 
E/AEncode ( 1412): draining output buffer 2, time = 233333 us Size = 4096 
E/AEncode ( 1412): draining output buffer 3, time = 266666 us Size = 4096 
E/AEncode ( 1412): draining output buffer 4, time = 300000 us Size = 4096 
E/AEncode ( 1412): draining output buffer 5, time = 333333 us Size = 4095 
E/AEncode ( 1412): draining output buffer 0, time = 366666 us Size = 4097 
E/AEncode ( 1412): draining output buffer 1, time = 400000 us Size = 4097 
E/AEncode ( 1412): draining output buffer 2, time = 433333 us Size = 4090 
E/AEncode ( 1412): draining output buffer 3, time = 466666 us Size = 4097 
E/AEncode ( 1412): draining output buffer 4, time = 500000 us Size = 4097 
E/AEncode ( 1412): draining output buffer 5, time = 533333 us Size = 4097 
E/AEncode ( 1412): draining output buffer 0, time = 566666 us Size = 4097 
E/AEncode ( 1412): draining output buffer 1, time = 600000 us Size = 4097 
E/AEncode ( 1412): draining output buffer 2, time = 633333 us Size = 4097 
E/AEncode ( 1412): draining output buffer 3, time = 666666 us Size = 4097 
E/AEncode ( 1412): draining output buffer 4, time = 700000 us Size = 4097 
E/AEncode ( 1412): draining output buffer 5, time = 733333 us Size = 4097 
E/AEncode ( 1412): draining output buffer 0, time = 766666 us Size = 4097 
E/AEncode ( 1412): draining output buffer 1, time = 800000 us Size = 4097 
E/AEncode ( 1412): draining output buffer 2, time = 833333 us Size = 4097 
E/AEncode ( 1412): draining output buffer 3, time = 866666 us Size = 4097 
E/AEncode ( 1412): draining output buffer 4, time = 900000 us Size = <b>4141</b>

So can you please say, why I am not getting constant bit rate here?

Hi Gopinath,
You have to check the bitrate in period, not frame by frame. Since H264 is encoded in I/P/B frames and there are dependency between frames, you will not see all frames with same size.

Hi DaneLL,

Thank-you for support. Now I calculated the birrate in period. Now I have two questions.

  1. For 640 x 480, I set bitrate around 700 Kbps and constant bit rate mode. Now I am getting bitrate around 700 Kbps. But my question is, I am seeing bitrate accelerates between 550 Kbps to 800 Kbps. Why I am not getting constant 700 Kbps. (Or this is tolerance range in my period calculation ?) Or else some-other settings like i-frame-interval is creating this issue?

  2. Why Android framework API (MediaCodecInfo.EncoderCapabilities )returns only it supports BITRATE_MODE_VBR for this H.264 encoder?

Hi Gopinath,

  1. For 640 x 480, I set bitrate around 700 Kbps and constant bit rate mode. Now I am getting bitrate around 700 Kbps. But my question is, I am seeing bitrate accelerates between 550 Kbps to 800 Kbps. Why I am not getting constant 700 Kbps. (Or this is tolerance range in my period calculation ?) Or else some-other settings like i-frame-interval is creating this issue?
    It is within tolerance. Maybe you can also try the skip-frame modes:
    OMX_Video_ControlRateVariableSkipFrames
    OMX_Video_ControlRateConstantSkipFrames

  2. Why Android framework API (MediaCodecInfo.EncoderCapabilities )returns only it supports BITRATE_MODE_VBR for this H.264 encoder?
    This looks to be about integrating with Android. Need to trace Android frameworks.

Hi DaneLLL,

Thank-You.Regarding the second point, the same problem is occurring in Shield tablet (TK1) too (Android Version 5.1.1).