Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question]: Actual bitrate did not reach target bitrate and the actual QP is higher than MIN_QP on CBR mode #517

Closed
MemeTao opened this issue Dec 2, 2024 · 7 comments
Labels

Comments

@MemeTao
Copy link

MemeTao commented Dec 2, 2024

Hey! I have a problem with image quality.

The actual bitrate is lower than target bitrate on document scenaria(scenes where the content does not change much), but the qp of output frame is higher than min_bp.

here is my parameters(pseudocode):

set_avc_property(amf_encoder_, RATE_CONTROL_METHOD, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR);
set_avc_property(amf_encoder_, FRAMESIZE, 720P);
set_avc_property(amf_encoder_, USAGE, AMF_VIDEO_ENCODER_USAGE_TRANSCODING);
set_avc_property(amf_encoder_, B_PIC_PATTERN, 0);
set_avc_property(amf_encoder_, QUALITY_PRESET, AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED);
set_avc_property(amf_encoder_, LOWLATENCY_MODE, true);
set_avc_property(amf_encoder_, PREENCODE_ENABLE, true);
set_avc_property(amf_encoder_, MIN_QP, 20);
set_avc_property(amf_encoder_, MAX_QP, 40);
set_avc_property(amf_encoder_, TARGET_BITRATE,  800kbps);
set_avc_property(amf_encoder_, PEAK_BITRATE,  800kbps);
set_avc_property(amf_encoder_, ENFORCE_HRD, true);
set_avc_property(amf_encoder_, IDR_PERIOD,  1000);
set_avc_property(amf_encoder_, AMFConstructRate(15, 1));
amf_encoder_->Init();

// after initialized, i will change target bitrate dynamic(during 600-1000kbps) based the network quality.
void onRequestChangeBitrate(uint32_t target_bitrate) {
      set_avc_property(amf_encoder_, TARGET_BITRATE, target_bitrate);
      set_avc_property(amf_encoder_, PEAK_BITRATE, target_bitrate);
}

I get some output like this:

//Format: {target bitrate|actual output bitrate, medium QP}, statistics once per second
{844|636kbps, 28}
{844|645kbps, 24}
{706|333kbps, 33}  // output bitrate is very low, but QP is higher than MIN_QP(20)
{822|502kbps, 33}

here is my code to get QP:

amf_surf->SetProperty(AMF_VIDEO_ENCODER_STATISTICS_FEEDBACK, true);
amf_encoder_->SubmitInput(amf_surf);
...
amf_encoder_->QueryOutput(&encoded_pkt_);
uint64_t average_qp = 0;
encoded_pkt_->GetProperty(AMF_VIDEO_ENCODER_STATISTIC_AVERAGE_QP, &average_qp);

What i want(Ideal situation):

  • When actual QP higher than MIN_QP, the output bitrate should close to target bitrate.
  • When actual bitrate lower than target bitrate, the actual QP should close to MIN_QP.

Is there any parameter to do this?

@MikhailAMD
Copy link
Collaborator

Couple of points:

  • Setting USAGE you overwrite most of previous settings including rate control method. So effectively you run PEAK_VBR.
  • For PEAK_VBR PEAK bitrate should be higher than TRAGET bitrate. If not, you will see undershot for bitrate, like the one you have.

@MemeTao
Copy link
Author

MemeTao commented Dec 3, 2024

Couple of points:

* Setting USAGE you overwrite most of previous settings including rate control method. So effectively you run PEAK_VBR.

* For PEAK_VBR PEAK bitrate should be higher than TRAGET bitrate. If not, you will see undershot for bitrate, like the one you have.

I changed my parameters, but the problem is still alive:

  set_avc_property(amf_encoder_, USAGE, AMF_VIDEO_ENCODER_USAGE_TRANSCODING); //using default parameters
  set_avc_property(amf_encoder_, RATE_CONTROL_METHOD, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR); //overwrite rc
  set_avc_property(amf_encoder_, FRAMESIZE, AMFConstructSize(width, height));
  //overwrite 'TRANSCODING' default values
  set_avc_property(amf_encoder_, B_PIC_PATTERN, 0);
  set_avc_property(amf_encoder_, LOWLATENCY_MODE, true);
  set_avc_property(amf_encoder_, MIN_QP, 20);
  set_avc_property(amf_encoder_, MAX_QP, 40);
  set_avc_property(amf_encoder_, ENFORCE_HRD, true);
  set_avc_property(amf_encoder_, IDR_PERIOD, 600);
  set_avc_property(amf_encoder_, QUERY_TIMEOUT, 200);
  set_avc_property(amf_encoder_, TARGET_BITRATE, bitrate);
  set_avc_property(amf_encoder_, PEAK_BITRATE, bitrate);
  set_avc_property(amf_encoder_, PROFILE, main);
  amf_encoder_->Init();

// after initialized, i will change target bitrate dynamic(during 600-1000kbps) based the network quality.
void onRequestChangeBitrate(uint32_t target_bitrate) {
      set_avc_property(amf_encoder_, TARGET_BITRATE, target_bitrate);
      set_avc_property(amf_encoder_, PEAK_BITRATE, target_bitrate);
}
{943|306kbps, 31}  //low bitrate and high QP
{997|528kbps, 34}
{997|683kbps, 26}

I tried many combinations of parameters but all failed, I'm confused and a little frustrated.

@MikhailAMD
Copy link
Collaborator

More points:

  • You can enable filler data. It will not improve quality but add empty data: AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE
  • You content can be simple enough that encoder cannot spend more QP - try ThanscodeHW sample to do the same, share your source and command line, we can take a look.
  • You may want to enable detailed AMF tracing and share full log so we can see what is really going on, especially with dynamic bitrate change - note: you cannot change it too often.
  • We will need your HW model and driver version

@MemeTao
Copy link
Author

MemeTao commented Dec 4, 2024

More points:

* You can enable filler data. It will not improve quality but add empty data: AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE

* You content can be simple enough that encoder cannot spend more QP - try ThanscodeHW sample to do the same, share your source and command line, we can take a look.

* You may want to enable detailed AMF tracing and share full log so we can see what is really going on, especially with dynamic bitrate change - note: you cannot change it too often.

* We will need your HW model and driver version

Thanks for your reply:

  • AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE only add empty data, is not i want
  • ThanscodeHW sample is not so flexible for this problem

So I immediately built a tool to reproduce the problem,and also uploaded the video file:
Very easy to use

I run the tool and reproduced the problem, and here is my log file:

HW: AMD Radeon RX 6950XT, Driver 32.0.11027.1003
System: Win11

@MikhailAMD
Copy link
Collaborator

From what I can tell, your app records Windows desktop and test video contains also Windows desktop. So, the encoder input has mostly flat areas with pure colors: white, black etc. With such content one cannot expect that codec can keep bitrate and spend QP on large single-color areas.
If you want, you can dump raw encoder input and output using AMFDump interface. Then you can feed dumped NV12 input into TranscodeHW and set every possible encoder parameter via command line. You should be able to get similar results. Then try to change input with more complex data and you should see proper bitrate.

@MemeTao
Copy link
Author

MemeTao commented Dec 5, 2024

Thank you for such a detailed reply.

As you said, it seems quite difficult to achieve high quality on such content.

There is a sample performance on intel MFX.

It seems that only NVENC perform well in my testing.

@MemeTao MemeTao closed this as completed Dec 5, 2024
@MemeTao
Copy link
Author

MemeTao commented Dec 5, 2024

Thanks again。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants