AMF icon indicating copy to clipboard operation
AMF copied to clipboard

[Question]: Failed to modify bitrate dynamically

Open 21pages opened this issue 3 years ago • 7 comments

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.

21pages avatar Jun 10 '22 07:06 21pages

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.

MikhailAMD avatar Jun 10 '22 15:06 MikhailAMD

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);

21pages avatar Jun 11 '22 08:06 21pages

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?

MikhailAMD avatar Jun 13 '22 13:06 MikhailAMD

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

21pages avatar Jun 14 '22 02:06 21pages

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

MikhailAMD avatar Jun 14 '22 13:06 MikhailAMD

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?

21pages avatar Jun 15 '22 01:06 21pages

  1. Did you try your initial approach to just set bitrate with the updated driver? Again, many applications do it, should work.
  2. The ffmpeg patch duplicates a lot of code. Did you try just call ->ReInit() instead of Terminate()/Init()? it is designed for such cases.

MikhailAMD avatar Jun 15 '22 13:06 MikhailAMD