[Question]: Failed to modify bitrate dynamically
bitrate parameter in amf supports dynamic change, but it is not implemented in ffmpeg. I imitated nvenc and wrote the following things.
static int reconfig_encoder(AVCodecContext *avctx)
{
AmfContext *ctx = avctx->priv_data;
AMF_RESULT res = AMF_OK;
if (avctx->codec->id == AV_CODEC_ID_H264) {
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_TARGET_BITRATE, avctx->bit_rate);
} else if (avctx->codec->id == AV_CODEC_ID_HEVC) {
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_TARGET_BITRATE, avctx->bit_rate);
}
return 0;
}
I call this code at the beginning of ff_amf_receive_packet. The bitrate has indeed changed, but the encoded file cannot be played or decoded. decode output
[hevc @ 0000020BF515BAC0] PPS id out of range: 0
[hevc @ 0000020BF515BAC0] Error parsing NAL unit #1.
avcodec_send_packet: Invalid data found when processing input
I think some state needs to be reset or saved, but don't know how to do it.
The change looks OK to me. There is no state or reset needed. The only thing to consider: bitrate cannot be changed at every frame, even if the value is the same. The reason is, that each call resets rate control statistics so it would not work properly. But should not cause corrupted stream. You can experiment with AMF sample TranscodeHW - for comparison reasons. BTW: many applications change AMF encoder bitrate on the fly, so there is something ffmpeg-specifc.
The change looks OK to me. There is no state or reset needed. The only thing to consider: bitrate cannot be changed at every frame, even if the value is the same. The reason is, that each call resets rate control statistics so it would not work properly. But should not cause corrupted stream. You can experiment with AMF sample TranscodeHW - for comparison reasons. BTW: many applications change AMF encoder bitrate on the fly, so there is something ffmpeg-specifc.
Thank you very much. I add this, and it works.
res = ctx->encoder->pVtbl->Terminate(ctx->encoder);
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Terminate() failed with error %d\n", res);
res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height);
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res);
Well... This approach resets all encoder parameters to default. I don't think it is a good idea. What is your OS, GPU and driver version?
Well... This approach resets all encoder parameters to default. I don't think it is a good idea. What is your OS, GPU and driver version?
OS: win11
CPU: AMD Ryzen 7 5800H
GPU: AMD Radeon(TM) Graphics
driver: 30.0.13014.11000
But it does work. Here is output:
[h264_amf @ 000002263080E700] change bitrate from 2000000 to -1
[2022-06-14T02:09:15Z INFO bitrate] bitrate:-1, 12294 us, 8385 byte
[h264_amf @ 000002263080E700] change bitrate from -1 to 1000
[2022-06-14T02:09:21Z INFO bitrate] bitrate:1000, 11909 us, 430 byte
[h264_amf @ 000002263080E700] change bitrate from 1000 to 8000
[2022-06-14T02:09:28Z INFO bitrate] bitrate:8000, 11733 us, 431 byte
[h264_amf @ 000002263080E700] change bitrate from 8000 to 200000
[2022-06-14T02:09:34Z INFO bitrate] bitrate:200000, 12344 us, 861 byte
[h264_amf @ 000002263080E700] change bitrate from 200000 to 1000000
[2022-06-14T02:09:41Z INFO bitrate] bitrate:1000000, 12742 us, 4187 byte
[h264_amf @ 000002263080E700] change bitrate from 1000000 to 1320000
[2022-06-14T02:09:48Z INFO bitrate] bitrate:1320000, 12788 us, 5522 byte
[h264_amf @ 000002263080E700] change bitrate from 1320000 to 2000000
[2022-06-14T02:09:54Z INFO bitrate] bitrate:2000000, 12674 us, 8385 byte
[h264_amf @ 000002263080E700] change bitrate from 2000000 to 4000000
[2022-06-14T02:10:01Z INFO bitrate] bitrate:4000000, 12413 us, 16672 byte
The bitrate change works but all other parameters are default. Check initialization of the encoder: many AMF parameters are set from command line of ffmpeg settings. All this is overwritten with such approach. To avoid this you can try to call ReInit() instead but it is still not right. Also, your driver is not the latest, It is older then Oct 2021. Could you please try to update driver: https://www.amd.com/en/support/apu/amd-ryzen-processors/amd-ryzen-7-mobile-processors-radeon-graphics/amd-ryzen-7-5800h
The bitrate change works but all other parameters are default. Check initialization of the encoder: many AMF parameters are set from command line of ffmpeg settings. All this is overwritten with such approach. To avoid this you can try to call ReInit() instead but it is still not right. Also, your driver is not the latest, It is older then Oct 2021. Could you please try to update driver: https://www.amd.com/en/support/apu/amd-ryzen-processors/amd-ryzen-7-mobile-processors-radeon-graphics/amd-ryzen-7-5800h
Thank you for your reply.
After updating the driver, it still works. version: 30.0.21017.1000 ,2022/5/17
Here is my ffmpeg commit on AMF. I terminate and init it after change bitrate. Here is my compiled lib hwcodec. Could you tell me how to verify your idea?
- Did you try your initial approach to just set bitrate with the updated driver? Again, many applications do it, should work.
- The ffmpeg patch duplicates a lot of code. Did you try just call ->ReInit() instead of Terminate()/Init()? it is designed for such cases.