[Libva] [PATCH 4/4] VP9 encoder: use generic rate control parameters

Mark Thompson sw at jkqxz.net
Thu Dec 8 23:01:53 UTC 2016


Also adds support for fractional framerate.

Signed-off-by: Mark Thompson <sw at jkqxz.net>
---
 src/gen9_vp9_encoder.c | 240 +++++++++----------------------------------------
 src/gen9_vp9_encoder.h |  11 +--
 src/i965_drv_video.c   |  10 +--
 src/i965_encoder.c     |  36 ++++++++
 src/i965_encoder.h     |   1 +
 5 files changed, 80 insertions(+), 218 deletions(-)

diff --git a/src/gen9_vp9_encoder.c b/src/gen9_vp9_encoder.c
index 3ea1537..533bf81 100644
--- a/src/gen9_vp9_encoder.c
+++ b/src/gen9_vp9_encoder.c
@@ -1201,8 +1201,8 @@ void gen9_vp9_set_curbe_brc(VADriverContextP ctx,
                                                   VP9_BRC_KBPS;
             cmd->dw9.min_bit_rate           = (vp9_state->min_bit_rate  + VP9_BRC_KBPS - 1) / VP9_BRC_KBPS *
                                                   VP9_BRC_KBPS;
-            cmd->dw10.frame_ratem           = vp9_state->frame_rate;
-            cmd->dw11.frame_rated           = 1;
+            cmd->dw10.frame_ratem           = vp9_state->framerate_num;
+            cmd->dw11.frame_rated           = vp9_state->framerate_den;
 
             cmd->dw14.avbr_accuracy         = 30;
             cmd->dw14.avbr_convergence      = 150;
@@ -1235,8 +1235,8 @@ void gen9_vp9_set_curbe_brc(VADriverContextP ctx,
             cmd->dw17.enable_dynamic_scaling = vp9_state->dys_in_use;
             cmd->dw17.brc_overshoot_cbr_pct = 150;
 
-            dInputBitsPerFrame = (double)(cmd->dw8.max_bit_rate) / (vp9_state->frame_rate);
-            dbps_ratio         = dInputBitsPerFrame / ((double)(vp9_state->vbv_buffer_size_in_bit) / 30);
+            dInputBitsPerFrame = (double)cmd->dw8.max_bit_rate * (double)vp9_state->framerate_den / (double)vp9_state->framerate_num;
+            dbps_ratio         = dInputBitsPerFrame / (double)vp9_state->vbv_buffer_size_in_bit / 30.0;
             if (dbps_ratio < 0.1)
                 dbps_ratio = 0.1;
             if (dbps_ratio > 3.5)
@@ -1423,7 +1423,6 @@ gen9_vp9_brc_init_reset_kernel(VADriverContextP ctx,
     brc_initreset_curbe.initbrc            = !vp9_state->brc_inited;
     brc_initreset_curbe.mbbrc_enabled      = 0;
     brc_initreset_curbe.ref_frame_flag      = vp9_state->ref_frame_flag;
-    brc_initreset_curbe.frame_rate           = vp9_state->frame_rate;
 
     vme_context->pfn_set_curbe_brc(ctx, encode_state,
                                    gpe_context,
@@ -1523,7 +1522,6 @@ gen9_vp9_brc_intra_dist_kernel(VADriverContextP ctx,
     brc_intra_dist_curbe.initbrc            = !vp9_state->brc_inited;
     brc_intra_dist_curbe.mbbrc_enabled      = 0;
     brc_intra_dist_curbe.ref_frame_flag      = vp9_state->ref_frame_flag;
-    brc_intra_dist_curbe.frame_rate           = vp9_state->frame_rate;
 
     vme_context->pfn_set_curbe_brc(ctx, encode_state,
                                    gpe_context,
@@ -3926,168 +3924,51 @@ gen9_encode_vp9_check_parameter(VADriverContextP ctx,
         return VA_STATUS_ERROR_UNIMPLEMENTED;
 
     if (vp9_state->brc_enabled) {
-        if (vp9_state->brc_flag_check & VP9_BRC_FAILURE) {
-            WARN_ONCE("Rate control misc_parameter is required for BRC\n");
-            return VA_STATUS_ERROR_INVALID_PARAMETER;
-        }
-
-        if (vp9_state->first_frame) {
-            unsigned int brc_flag;
-            VAEncMiscParameterBuffer *misc_param;
-
-            brc_flag = VP9_BRC_SEQ | VP9_BRC_RC;
-            if ((vp9_state->brc_flag_check & brc_flag) != brc_flag) {
-                WARN_ONCE("SPS/RC misc is required for BRC\n");
-                return VA_STATUS_ERROR_INVALID_PARAMETER;
-            }
+        if (vp9_state->first_frame || vp9_state->picture_coding_type == KEY_FRAME) {
+            vp9_state->brc_reset = encoder_context->brc.need_reset || vp9_state->first_frame;
 
             /* check the corresponding BRC parameter for CBR and VBR */
             if (encoder_context->rate_control_mode == VA_RC_CBR) {
-                vp9_state->target_bit_rate = seq_param->bits_per_second;
-                vp9_state->gop_size = seq_param->intra_period;
-
-                if (vp9_state->brc_flag_check & VP9_BRC_HRD) {
-                    VAEncMiscParameterHRD *misc_param_hrd;
-
-                    misc_param = (VAEncMiscParameterBuffer *)
-                        encode_state->misc_param[VAEncMiscParameterTypeHRD][0]->buffer;
-                    misc_param_hrd = (VAEncMiscParameterHRD *)misc_param->data;
-
-                    vp9_state->init_vbv_buffer_fullness_in_bit = misc_param_hrd->initial_buffer_fullness;
-                    vp9_state->vbv_buffer_size_in_bit = misc_param_hrd->buffer_size;
-                }
-
-                if (vp9_state->brc_flag_check & VP9_BRC_FR) {
-                    VAEncMiscParameterFrameRate *misc_param_fr;
-
-                    misc_param = (VAEncMiscParameterBuffer *)
-                        encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
-                    misc_param_fr = (VAEncMiscParameterFrameRate *)misc_param->data;
-
-                    vp9_state->frame_rate = misc_param_fr->framerate;
-                } else {
-                    /* Assign the default frame rate */
-                    vp9_state->frame_rate = 30;
-                }
-
-                /* RC misc will override HRD parameter */
-                if (vp9_state->brc_flag_check & VP9_BRC_RC) {
-                    VAEncMiscParameterRateControl *misc_param_rc;
-
-                    misc_param = (VAEncMiscParameterBuffer *)
-                        encode_state->misc_param[VAEncMiscParameterTypeRateControl][0]->buffer;
-                    misc_param_rc = (VAEncMiscParameterRateControl *)misc_param->data;
-
-                    vp9_state->target_bit_rate = misc_param_rc->bits_per_second;
-                    vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
-                                                 misc_param_rc->window_size;
-                    vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
-                    vp9_state->window_size = misc_param_rc->window_size;
-                }
+                if (!encoder_context->brc.framerate_num[0] || !encoder_context->brc.framerate_den[0] ||
+                    !encoder_context->brc.bits_per_second[0])
+                    return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+                vp9_state->gop_size = encoder_context->brc.gop_size;
+
+                vp9_state->framerate_num = encoder_context->brc.framerate_num[0];
+                vp9_state->framerate_den = encoder_context->brc.framerate_den[0];
+
+                vp9_state->target_bit_rate = encoder_context->brc.bits_per_second[0];
                 vp9_state->max_bit_rate = vp9_state->target_bit_rate;
                 vp9_state->min_bit_rate = vp9_state->target_bit_rate;
+
+                vp9_state->vbv_buffer_size_in_bit = encoder_context->brc.hrd_buffer_size;
+                vp9_state->init_vbv_buffer_fullness_in_bit = encoder_context->brc.hrd_initial_buffer_fullness;
+
             } else {
                 /* VBR mode */
-                brc_flag = VP9_BRC_SEQ | VP9_BRC_RC;
-                vp9_state->target_bit_rate = seq_param->bits_per_second;
-                vp9_state->gop_size = seq_param->intra_period;
-
-                if (vp9_state->brc_flag_check & VP9_BRC_FR) {
-                    VAEncMiscParameterFrameRate *misc_param_fr;
-
-                    misc_param = (VAEncMiscParameterBuffer *)
-                        encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
-                    misc_param_fr = (VAEncMiscParameterFrameRate *)misc_param->data;
-
-                    vp9_state->frame_rate = misc_param_fr->framerate;
-                } else {
-                    /* Assign the default frame rate */
-                    vp9_state->frame_rate = 30;
-                }
-
-                if (vp9_state->brc_flag_check & VP9_BRC_RC) {
-                    VAEncMiscParameterRateControl *misc_param_rc;
-
-                    misc_param = (VAEncMiscParameterBuffer *)
-                        encode_state->misc_param[VAEncMiscParameterTypeRateControl][0]->buffer;
-                    misc_param_rc = (VAEncMiscParameterRateControl *)misc_param->data;
-
-                    vp9_state->max_bit_rate = misc_param_rc->bits_per_second;
-                    vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
-                                                 misc_param_rc->window_size;
-                    vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
-                    vp9_state->target_bit_rate = (misc_param_rc->bits_per_second / 100) *
-                                misc_param_rc->target_percentage;
-                    vp9_state->min_bit_rate = (misc_param_rc->bits_per_second / 100) *
-                         (2 * misc_param_rc->target_percentage - 100);
-                    vp9_state->target_percentage = misc_param_rc->target_percentage;
-                    vp9_state->window_size = misc_param_rc->window_size;
-                }
-            }
-        }
-        else if (vp9_state->picture_coding_type == KEY_FRAME){
-            VAEncMiscParameterBuffer *misc_param;
-            /* update the BRC parameter only when it is key-frame */
-            /* If the parameter related with RC is changed. Reset BRC */
-            if (vp9_state->brc_flag_check & VP9_BRC_FR) {
-               VAEncMiscParameterFrameRate *misc_param_fr;
-
-               misc_param = (VAEncMiscParameterBuffer *)
-                   encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer;
-               misc_param_fr = (VAEncMiscParameterFrameRate *)misc_param->data;
-
-               if (vp9_state->frame_rate != misc_param_fr->framerate) {
-                   vp9_state->brc_reset = 1;
-                   vp9_state->frame_rate = misc_param_fr->framerate;
-               }
-            }
+                if (!encoder_context->brc.framerate_num[0] || !encoder_context->brc.framerate_den[0] ||
+                    !encoder_context->brc.bits_per_second[0] || !encoder_context->brc.target_percentage[0] ||
+                    !encoder_context->brc.window_size)
+                    return VA_STATUS_ERROR_INVALID_PARAMETER;
 
-            /* check the GOP size. And bit_per_second in SPS is ignored */
-            if (vp9_state->brc_flag_check & VP9_BRC_SEQ) {
-                if (vp9_state->gop_size != seq_param->intra_period) {
-                    vp9_state->brc_reset = 1;
-                    vp9_state->gop_size = seq_param->intra_period;
-                }
-            }
+                vp9_state->gop_size = encoder_context->brc.gop_size;
+
+                vp9_state->framerate_num = encoder_context->brc.framerate_num[0];
+                vp9_state->framerate_den = encoder_context->brc.framerate_den[0];
 
-            /* update the bit_per_second */
-            if (vp9_state->brc_flag_check & VP9_BRC_RC) {
-                VAEncMiscParameterRateControl *misc_param_rc;
-
-                misc_param = (VAEncMiscParameterBuffer *)
-                    encode_state->misc_param[VAEncMiscParameterTypeRateControl][0]->buffer;
-                misc_param_rc = (VAEncMiscParameterRateControl *)misc_param->data;
-
-                if (encoder_context->rate_control_mode == VA_RC_CBR) {
-                    if (vp9_state->target_bit_rate != misc_param_rc->bits_per_second ||
-                        vp9_state->window_size != misc_param_rc->window_size) {
-                        vp9_state->target_bit_rate = misc_param_rc->bits_per_second;
-                        vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
-                                                 misc_param_rc->window_size;
-                        vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit * 2;
-                        vp9_state->window_size = misc_param_rc->window_size;
-                        vp9_state->max_bit_rate = vp9_state->target_bit_rate;
-                        vp9_state->min_bit_rate = vp9_state->target_bit_rate;
-                        vp9_state->brc_reset = 1;
-                    }
-                } else {
-                    /* VBR mode */
-                    if (vp9_state->max_bit_rate != misc_param_rc->bits_per_second ||
-                        vp9_state->target_percentage != misc_param_rc->target_percentage) {
-
-                        vp9_state->target_bit_rate = (misc_param_rc->bits_per_second / 100) *
-                                misc_param_rc->target_percentage;
-                        vp9_state->min_bit_rate = (misc_param_rc->bits_per_second / 100) *
-                             (2 * misc_param_rc->target_percentage - 100);
-                        vp9_state->max_bit_rate = misc_param_rc->bits_per_second;
-                        vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) *
-                                                 misc_param_rc->window_size;
-                        vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
-                        vp9_state->target_percentage = misc_param_rc->target_percentage;
-                        vp9_state->window_size = misc_param_rc->window_size;
-                        vp9_state->brc_reset = 1;
-                    }
-                }
+                vp9_state->max_bit_rate = encoder_context->brc.bits_per_second[0];
+                vp9_state->target_percentage = encoder_context->brc.target_percentage[0];
+                vp9_state->window_size = encoder_context->brc.window_size;
+
+                vp9_state->target_bit_rate = vp9_state->max_bit_rate * encoder_context->brc.target_percentage[0] / 100;
+                if (2 * vp9_state->target_bit_rate < vp9_state->max_bit_rate)
+                    vp9_state->min_bit_rate = 0;
+                else
+                    vp9_state->min_bit_rate = 2 * vp9_state->target_bit_rate - vp9_state->max_bit_rate;
+
+                vp9_state->vbv_buffer_size_in_bit = (vp9_state->max_bit_rate / 1000) * vp9_state->window_size;
+                vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2;
             }
         }
     }
@@ -5805,47 +5686,6 @@ static void
 gen9_vp9_pak_brc_prepare(struct encode_state *encode_state,
                           struct intel_encoder_context *encoder_context)
 {
-    struct gen9_encoder_context_vp9 *pak_context = encoder_context->mfc_context;
-    struct gen9_vp9_state *vp9_state;
-
-    vp9_state = (struct gen9_vp9_state *)(encoder_context->enc_priv_state);
-
-    if (!vp9_state || !pak_context)
-        return;
-
-    if (vp9_state->brc_enabled) {
-        /* check the buffer related with BRC */
-        vp9_state->brc_flag_check = 0;
-        if (encode_state->seq_param_ext && encode_state->seq_param_ext->buffer) {
-            vp9_state->brc_flag_check |= VP9_BRC_SEQ;
-        }
-
-        /* Frame_rate */
-        if (encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0] &&
-            encode_state->misc_param[VAEncMiscParameterTypeFrameRate][0]->buffer) {
-            vp9_state->brc_flag_check |= VP9_BRC_FR;
-        }
-
-        /* HRD */
-        if (encode_state->misc_param[VAEncMiscParameterTypeRateControl][0] &&
-            encode_state->misc_param[VAEncMiscParameterTypeRateControl][0]->buffer) {
-            vp9_state->brc_flag_check |= VP9_BRC_RC;
-        }
-
-        if (encode_state->misc_param[VAEncMiscParameterTypeHRD][0] &&
-            encode_state->misc_param[VAEncMiscParameterTypeHRD][0]->buffer) {
-            vp9_state->brc_flag_check |= VP9_BRC_HRD;
-        }
-
-        /*
-         * If user-app doesn't pass the buffer related with BRC for the first
-         * frame, the error flag is returned.
-         */
-        if (vp9_state->brc_flag_check == 0 && vp9_state->first_frame) {
-            vp9_state->brc_flag_check |= VP9_BRC_FAILURE;
-        }
-    }
-    return;
 }
 
 static void
diff --git a/src/gen9_vp9_encoder.h b/src/gen9_vp9_encoder.h
index ad2d875..3c47ba3 100644
--- a/src/gen9_vp9_encoder.h
+++ b/src/gen9_vp9_encoder.h
@@ -1552,7 +1552,6 @@ struct gen9_vp9_brc_curbe_param
     int32_t   brc_num_pak_passes;
     bool      multi_ref_qp_check;
     int16_t   frame_number;
-    int32_t   frame_rate;
     VP9_MEDIA_STATE_TYPE                       media_state_type;
 };
 
@@ -1649,12 +1648,6 @@ typedef struct _vp9_frame_status_
     uint8_t intra_only;
 } vp9_frame_status;
 
-#define VP9_BRC_SEQ         0x01
-#define VP9_BRC_HRD         0x02
-#define VP9_BRC_RC          0x04
-#define VP9_BRC_FR          0x08
-#define VP9_BRC_FAILURE     (1 << 31)
-
 struct gen9_hcpe_pipe_mode_select_param
 {
     uint32_t                    codec_mode;
@@ -1925,7 +1918,8 @@ struct gen9_vp9_state {
     unsigned long init_vbv_buffer_fullness_in_bit;
     unsigned long vbv_buffer_size_in_bit;
     int      frame_number;
-    uint32_t frame_rate;
+    uint32_t framerate_num;
+    uint32_t framerate_den;
     uint8_t  ref_frame_flag;
     uint8_t  dys_ref_frame_flag;
     uint8_t  picture_coding_type;
@@ -1936,7 +1930,6 @@ struct gen9_vp9_state {
     int      target_percentage;
     unsigned int mb_data_offset;
     int      curr_pak_pass;
-    unsigned int brc_flag_check;
     bool     first_frame;
     bool     dys_enabled;
     bool     dys_in_use;
diff --git a/src/i965_drv_video.c b/src/i965_drv_video.c
index e602b4e..15920f5 100644
--- a/src/i965_drv_video.c
+++ b/src/i965_drv_video.c
@@ -2794,7 +2794,7 @@ i965_BeginPicture(VADriverContextP ctx,
     struct object_surface *obj_surface = SURFACE(render_target);
     struct object_config *obj_config;
     VAStatus vaStatus = VA_STATUS_SUCCESS;
-    int i, j;
+    int i;
 
     ASSERT_RET(obj_context, VA_STATUS_ERROR_INVALID_CONTEXT);
     ASSERT_RET(obj_surface, VA_STATUS_ERROR_INVALID_SURFACE);
@@ -2848,14 +2848,6 @@ i965_BeginPicture(VADriverContextP ctx,
         i965_release_buffer_store(&obj_context->codec_state.encode.misc_param[VAEncMiscParameterTypeROI][0]);
 
         i965_release_buffer_store(&obj_context->codec_state.encode.encmb_map);
-
-        if (obj_config->profile == VAProfileVP9Profile0) {
-            for (i = 0; i < ARRAY_ELEMS(obj_context->codec_state.encode.misc_param); i++)
-                for (j = 0; j < ARRAY_ELEMS(obj_context->codec_state.encode.misc_param[0]); j++)
-                    i965_release_buffer_store(&obj_context->codec_state.encode.misc_param[i][j]);
-
-            i965_release_buffer_store(&obj_context->codec_state.encode.seq_param_ext);
-        }
     } else {
         obj_context->codec_state.decode.current_render_target = render_target;
         i965_release_buffer_store(&obj_context->codec_state.decode.pic_param);
diff --git a/src/i965_encoder.c b/src/i965_encoder.c
index fc2557a..8af0df5 100644
--- a/src/i965_encoder.c
+++ b/src/i965_encoder.c
@@ -498,6 +498,34 @@ intel_encoder_check_brc_hevc_sequence_parameter(VADriverContextP ctx,
 }
 
 static VAStatus
+intel_encoder_check_brc_vp9_sequence_parameter(VADriverContextP ctx,
+                                               struct encode_state *encode_state,
+                                               struct intel_encoder_context *encoder_context)
+{
+    VAEncSequenceParameterBufferVP9 *seq_param = (VAEncSequenceParameterBufferVP9*)encode_state->seq_param_ext->buffer;
+    unsigned int gop_size;
+
+    if (!encoder_context->is_new_sequence)
+        return VA_STATUS_SUCCESS;
+    if (!seq_param)
+        return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+    if (seq_param->intra_period == 0)
+        gop_size = -1; // Dummy value (infinity).
+    else
+        gop_size = seq_param->intra_period;
+
+    if (encoder_context->brc.bits_per_second[0] != seq_param->bits_per_second ||
+        encoder_context->brc.gop_size != gop_size) {
+        encoder_context->brc.bits_per_second[0] = seq_param->bits_per_second;
+        encoder_context->brc.gop_size = gop_size;
+        encoder_context->brc.need_reset = 1;
+    }
+
+    return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
 intel_encoder_check_brc_sequence_parameter(VADriverContextP ctx,
                                            struct encode_state *encode_state,
                                            struct intel_encoder_context *encoder_context)
@@ -513,6 +541,9 @@ intel_encoder_check_brc_sequence_parameter(VADriverContextP ctx,
     case CODEC_HEVC:
         return intel_encoder_check_brc_hevc_sequence_parameter(ctx, encode_state, encoder_context);
 
+    case CODEC_VP9:
+        return intel_encoder_check_brc_vp9_sequence_parameter(ctx, encode_state, encoder_context);
+
     default:
         // TODO: other codecs
         return VA_STATUS_SUCCESS;
@@ -549,6 +580,11 @@ intel_encoder_check_rate_control_parameter(VADriverContextP ctx,
         encoder_context->brc.target_percentage[temporal_id] = misc->target_percentage;
         encoder_context->brc.need_reset = 1;
     }
+
+    if (encoder_context->brc.window_size != misc->window_size) {
+        encoder_context->brc.window_size = misc->window_size;
+        encoder_context->brc.need_reset = 1;
+    }
 }
 
 static void
diff --git a/src/i965_encoder.h b/src/i965_encoder.h
index 4547849..f71031b 100644
--- a/src/i965_encoder.h
+++ b/src/i965_encoder.h
@@ -86,6 +86,7 @@ struct intel_encoder_context
         unsigned int target_percentage[MAX_TEMPORAL_LAYERS];
         unsigned int hrd_buffer_size;
         unsigned int hrd_initial_buffer_fullness;
+        unsigned int window_size;
         unsigned int need_reset;
 
         unsigned int num_roi;
-- 
2.10.2


More information about the Libva mailing list