---
 libavcodec/vaapi_encode_h264.c | 99 ++++++++++++++++++++++++++++++++----------
 1 file changed, 75 insertions(+), 24 deletions(-)

diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c
index 6a77ab1..a00d478 100644
--- a/libavcodec/vaapi_encode_h264.c
+++ b/libavcodec/vaapi_encode_h264.c
@@ -104,7 +104,15 @@ typedef struct VAAPIEncodeH264Context {
     int64_t idr_pic_count;
     int64_t last_idr_frame;

-    // RefPicList management.
+    // Rate control configuration.
+    struct {
+        VAEncMiscParameterBuffer misc;
+        VAEncMiscParameterRateControl rc;
+    } rc_params;
+    struct {
+        VAEncMiscParameterBuffer misc;
+        VAEncMiscParameterHRD hrd;
+    } hrd_params;
 } VAAPIEncodeH264Context;


@@ -506,6 +514,14 @@ static int 
vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx)
         } else {
             vseq->frame_cropping_flag = 0;
         }
+
+        vseq->bits_per_second   = avctx->bit_rate;
+        vseq->num_units_in_tick = avctx->time_base.num;
+        vseq->time_scale        = 2 * avctx->time_base.den;
+
+        vseq->intra_period     = ctx->p_per_i * (ctx->b_per_p + 1);
+        vseq->intra_idr_period = vseq->intra_period;
+        vseq->ip_period        = ctx->b_per_p + 1;
     }

     {
@@ -695,8 +711,6 @@ static av_cold int 
vaapi_encode_h264_init_internal(AVCodecContext *avctx)
     static const VAConfigAttrib default_config_attributes[] = {
         { .type  = VAConfigAttribRTFormat,
           .value = VA_RT_FORMAT_YUV420 },
-        { .type  = VAConfigAttribRateControl,
-          .value = VA_RC_CQP },
         { .type  = VAConfigAttribEncPackedHeaders,
           .value = (VA_ENC_PACKED_HEADER_SEQUENCE |
                     VA_ENC_PACKED_HEADER_SLICE) },
@@ -745,8 +759,6 @@ static av_cold int 
vaapi_encode_h264_init_internal(AVCodecContext *avctx)
     }
     ctx->va_entrypoint = VAEntrypointEncSlice;

-    ctx->va_rc_mode  = VA_RC_CQP;
-
     ctx->input_width    = avctx->width;
     ctx->input_height   = avctx->height;
     ctx->aligned_width  = FFALIGN(ctx->input_width,  16);
@@ -754,30 +766,69 @@ static av_cold int 
vaapi_encode_h264_init_internal(AVCodecContext *avctx)
     priv->mb_width      = ctx->aligned_width  / 16;
     priv->mb_height     = ctx->aligned_height / 16;

-    if (avctx->bit_rate > 0) {
-        av_log(avctx, AV_LOG_ERROR, "Constant bitrate encoding is not "
-               "supported!\n");
-        return AVERROR_PATCHWELCOME;
-    }
-
     for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) {
         ctx->config_attributes[ctx->nb_config_attributes++] =
             default_config_attributes[i];
     }

-    priv->fixed_qp_p = avctx->global_quality;
-    if (avctx->i_quant_factor > 0.0)
-        priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor +
-                                    avctx->i_quant_offset) + 0.5);
-    else
-        priv->fixed_qp_idr = priv->fixed_qp_p;
-    if (avctx->b_quant_factor > 0.0)
-        priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor +
-                                  avctx->b_quant_offset) + 0.5);
-    else
-        priv->fixed_qp_b = priv->fixed_qp_p;
-    av_log(avctx, AV_LOG_DEBUG, "QP = %d / %d / %d for IDR / P / B frames.\n",
-           priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b);
+    if (avctx->bit_rate > 0) {
+        ctx->va_rc_mode = VA_RC_CBR;
+
+        priv->rc_params.misc.type = VAEncMiscParameterTypeRateControl;
+        priv->rc_params.rc = (VAEncMiscParameterRateControl) {
+            .bits_per_second   = avctx->bit_rate,
+            .target_percentage = 66,
+            .window_size       = 1000,
+            .initial_qp        = (avctx->qmax >= 0 ? avctx->qmax : 40),
+            .min_qp            = (avctx->qmin >= 0 ? avctx->qmin : 18),
+            .basic_unit_size   = 0,
+        };
+        ctx->global_params[ctx->nb_global_params] =
+            &priv->rc_params.misc;
+        ctx->global_params_size[ctx->nb_global_params++] =
+            sizeof(priv->rc_params);
+
+        priv->hrd_params.misc.type = VAEncMiscParameterTypeHRD;
+        priv->hrd_params.hrd = (VAEncMiscParameterHRD) {
+            .initial_buffer_fullness = avctx->bit_rate,
+            .buffer_size             = avctx->bit_rate * 2,
+        };
+        ctx->global_params[ctx->nb_global_params] =
+            &priv->hrd_params.misc;
+        ctx->global_params_size[ctx->nb_global_params++] =
+            sizeof(priv->hrd_params);
+
+        // These still need to be  set for pic_init_qp/slice_qp_delta.
+        priv->fixed_qp_idr = 26;
+        priv->fixed_qp_p   = 26;
+        priv->fixed_qp_b   = 26;
+
+        av_log(avctx, AV_LOG_DEBUG, "Using constant-bitrate = %d bps.\n",
+               avctx->bit_rate);
+
+    } else {
+        ctx->va_rc_mode = VA_RC_CQP;
+
+        priv->fixed_qp_p = avctx->global_quality;
+        if (avctx->i_quant_factor > 0.0)
+            priv->fixed_qp_idr = (int)((priv->fixed_qp_p * 
avctx->i_quant_factor +
+                                        avctx->i_quant_offset) + 0.5);
+        else
+            priv->fixed_qp_idr = priv->fixed_qp_p;
+        if (avctx->b_quant_factor > 0.0)
+            priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor 
+
+                                      avctx->b_quant_offset) + 0.5);
+        else
+            priv->fixed_qp_b = priv->fixed_qp_p;
+
+        av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
+               "%d / %d / %d for IDR / P / B frames.\n",
+               priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b);
+    }
+    ctx->config_attributes[ctx->nb_config_attributes++] = (VAConfigAttrib) {
+        .type  = VAConfigAttribRateControl,
+        .value = ctx->va_rc_mode,
+    };

     ctx->nb_recon_frames = 20;

-- 
2.8.0.rc3

_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to