Intel-Media-SDK / MediaSDK

The Intel® Media SDK
MIT License
926 stars 457 forks source link

Dynamic change bitrate failed #2947

Open 21pages opened 2 years ago

21pages commented 2 years ago

The doc says that it supports dynamic change of bitrate,

I added the following code to ffmpeg qsvenc, and call it at the top of ff_qsv_encode, but check_enc_param failed, and bitrate change can't effect.

static int reconfig_encoder(AVCodecContext *avctx, QSVEncContext *q)
{
    if (q->av_bitrate != avctx->bit_rate) {
        float quant;
        int target_bitrate_kbps, max_bitrate_kbps, brc_param_multiplier;
        int buffer_size_in_kilobytes, initial_delay_in_kilobytes;
        AVCPBProperties *cpb_props;

        av_log(avctx, AV_LOG_INFO, "change bitrate from %d to %d.\n", q->av_bitrate, avctx->bit_rate);
        q->av_bitrate = avctx->bit_rate;

        //libmfx BRC parameters are 16 bits thus maybe overflow, then BRCParamMultiplier is needed
        buffer_size_in_kilobytes   = avctx->rc_buffer_size / 8000;
        initial_delay_in_kilobytes = avctx->rc_initial_buffer_occupancy / 8000;
        target_bitrate_kbps        = avctx->bit_rate / 1000;
        max_bitrate_kbps           = avctx->rc_max_rate / 1000;
        brc_param_multiplier       = (FFMAX(FFMAX3(target_bitrate_kbps, max_bitrate_kbps, buffer_size_in_kilobytes),
                                      initial_delay_in_kilobytes) + 0x10000) / 0x10000;

        switch (q->param.mfx.RateControlMethod) {
            case MFX_RATECONTROL_CBR:
            case MFX_RATECONTROL_VBR:
#if QSV_HAVE_LA
                if (q->extbrc) {
                    q->extco2.LookAheadDepth = q->look_ahead_depth;
                }
#endif
#if QSV_HAVE_VCM
            case MFX_RATECONTROL_VCM:
#endif
#if QSV_HAVE_QVBR
            case MFX_RATECONTROL_QVBR:
#endif
                q->param.mfx.BufferSizeInKB   = buffer_size_in_kilobytes / brc_param_multiplier;
                q->param.mfx.InitialDelayInKB = initial_delay_in_kilobytes / brc_param_multiplier;
                q->param.mfx.TargetKbps       = target_bitrate_kbps / brc_param_multiplier;
                q->param.mfx.MaxKbps          = max_bitrate_kbps / brc_param_multiplier;
                q->param.mfx.BRCParamMultiplier = brc_param_multiplier;
#if QSV_HAVE_QVBR
                if (q->param.mfx.RateControlMethod == MFX_RATECONTROL_QVBR)
                    q->extco3.QVBRQuality = av_clip(avctx->global_quality, 0, 51);
#endif
                break;
            case MFX_RATECONTROL_CQP:
                quant = avctx->global_quality / FF_QP2LAMBDA;

                q->param.mfx.QPI = av_clip(quant * fabs(avctx->i_quant_factor) + avctx->i_quant_offset, 0, 51);
                q->param.mfx.QPP = av_clip(quant, 0, 51);
                q->param.mfx.QPB = av_clip(quant * fabs(avctx->b_quant_factor) + avctx->b_quant_offset, 0, 51);

                break;
#if QSV_HAVE_AVBR
            case MFX_RATECONTROL_AVBR:
                q->param.mfx.TargetKbps  = target_bitrate_kbps / brc_param_multiplier;
                q->param.mfx.Convergence = q->avbr_convergence;
                q->param.mfx.Accuracy    = q->avbr_accuracy;
                q->param.mfx.BRCParamMultiplier = brc_param_multiplier;
                break;
#endif
#if QSV_HAVE_LA
            case MFX_RATECONTROL_LA:
                q->param.mfx.TargetKbps  = target_bitrate_kbps / brc_param_multiplier;
                q->extco2.LookAheadDepth = q->look_ahead_depth;
                q->param.mfx.BRCParamMultiplier = brc_param_multiplier;
                break;
#if QSV_HAVE_ICQ
            case MFX_RATECONTROL_LA_ICQ:
                q->extco2.LookAheadDepth = q->look_ahead_depth;
            case MFX_RATECONTROL_ICQ:
                q->param.mfx.ICQQuality  = av_clip(avctx->global_quality, 1, 51);
                break;
#endif
#endif
            }

        if (!check_enc_param(avctx,q)) {
            av_log(avctx, AV_LOG_ERROR,
                   "some encoding parameters are not supported by the QSV "
                   "runtime. Please double check the input parameters.\n");
            // return AVERROR(ENOSYS);
        }

        cpb_props = (AVCPBProperties *)avctx->coded_side_data[avctx->nb_coded_side_data - 1].data;
        if (!cpb_props)
            return AVERROR(ENOMEM);
        cpb_props->max_bitrate = avctx->rc_max_rate;
        cpb_props->min_bitrate = avctx->rc_min_rate;
        cpb_props->avg_bitrate = avctx->bit_rate;
        cpb_props->buffer_size = avctx->rc_buffer_size;

        av_log(avctx, AV_LOG_INFO, "change bitrate ok.\n");
    }

    return 0;
}