[Libva] [Libva-intel-driver][PATCH v3 04/18] Check bitrate control related parameters in sequence and misc parameters

Xiang, Haihao haihao.xiang at intel.com
Tue Sep 13 08:02:33 UTC 2016


Currently only used for H.264 encoding

v2: rebased

Signed-off-by: Xiang, Haihao <haihao.xiang at intel.com>
Tested-by: Luo, Focus <focus.luo at intel.com>
---
 src/i965_encoder.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/i965_encoder.h |  12 ++++
 2 files changed, 190 insertions(+), 6 deletions(-)

diff --git a/src/i965_encoder.c b/src/i965_encoder.c
index 7eee29c..ec5dd2f 100644
--- a/src/i965_encoder.c
+++ b/src/i965_encoder.c
@@ -299,10 +299,179 @@ intel_encoder_check_jpeg_yuv_surface(VADriverContextP ctx,
 }
 
 static VAStatus
+intel_encoder_check_brc_h264_sequence_parameter(VADriverContextP ctx,
+                                                struct encode_state *encode_state,
+                                                struct intel_encoder_context *encoder_context)
+{
+    VAEncSequenceParameterBufferH264 *seq_param = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
+    unsigned short num_pframes_in_gop, num_bframes_in_gop;
+    unsigned int bits_per_second, framerate_per_100s;
+
+    if (!encoder_context->is_new_sequence)
+        return VA_STATUS_SUCCESS;
+
+    assert(seq_param);
+    bits_per_second = seq_param->bits_per_second;
+    framerate_per_100s = seq_param->time_scale * 100 / (2 * seq_param->num_units_in_tick);
+    encoder_context->brc.num_iframes_in_gop = 1; // Always 1
+
+    if (seq_param->intra_period == 0) { // E.g. IDRPP... / IDR(PBB)... (no IDR/I any more)
+        if (seq_param->ip_period == 0)
+            goto error;
+
+        encoder_context->brc.gop_size = (unsigned int)(framerate_per_100s / 100.0 + 0.5); // fake
+        num_pframes_in_gop = (encoder_context->brc.gop_size +
+                              seq_param->ip_period - 1) / seq_param->ip_period - 1;
+    } else if (seq_param->intra_period == 1) { // E.g. IDRIII...
+        encoder_context->brc.gop_size = 1;
+        num_pframes_in_gop = 0;
+    } else {
+        if (seq_param->ip_period == 0)
+            goto error;
+
+        encoder_context->brc.gop_size = seq_param->intra_period;
+        num_pframes_in_gop = (encoder_context->brc.gop_size +
+                              seq_param->ip_period - 1) / seq_param->ip_period - 1;
+    }
+
+    num_bframes_in_gop = (encoder_context->brc.gop_size -
+                          encoder_context->brc.num_iframes_in_gop - num_pframes_in_gop);
+
+    if (num_pframes_in_gop != encoder_context->brc.num_pframes_in_gop ||
+        num_bframes_in_gop != encoder_context->brc.num_bframes_in_gop ||
+        bits_per_second != encoder_context->brc.bits_per_second ||
+        framerate_per_100s != encoder_context->brc.framerate_per_100s) {
+        encoder_context->brc.num_pframes_in_gop = num_pframes_in_gop;
+        encoder_context->brc.num_bframes_in_gop = num_bframes_in_gop;
+        encoder_context->brc.bits_per_second = bits_per_second;
+        encoder_context->brc.framerate_per_100s = framerate_per_100s;
+        encoder_context->brc.need_reset = 1;
+    }
+
+    if (!encoder_context->brc.hrd_buffer_size ||
+        !encoder_context->brc.hrd_initial_buffer_fullness) {
+        encoder_context->brc.hrd_buffer_size = seq_param->bits_per_second << 1;
+        encoder_context->brc.hrd_initial_buffer_fullness = seq_param->bits_per_second;
+    }
+
+    return VA_STATUS_SUCCESS;
+
+error:
+    return VA_STATUS_ERROR_INVALID_PARAMETER;
+}
+
+static VAStatus
+intel_encoder_check_brc_sequence_parameter(VADriverContextP ctx,
+                                           struct encode_state *encode_state,
+                                           struct intel_encoder_context *encoder_context)
+{
+    if (encoder_context->codec == CODEC_H264 ||
+        encoder_context->codec == CODEC_H264_MVC)
+        return intel_encoder_check_brc_h264_sequence_parameter(ctx, encode_state, encoder_context);
+
+    // TODO: other codecs
+    return VA_STATUS_SUCCESS;
+}
+
+static void
+intel_encoder_check_rate_control_parameter(VADriverContextP ctx,
+                                           struct intel_encoder_context *encoder_context,
+                                           VAEncMiscParameterRateControl *misc)
+{
+    // TODO: for VBR
+    if (encoder_context->brc.bits_per_second != misc->bits_per_second) {
+        encoder_context->brc.bits_per_second = misc->bits_per_second;
+        encoder_context->brc.need_reset = 1;
+    }
+}
+
+static void
+intel_encoder_check_hrd_parameter(VADriverContextP ctx,
+                                  struct intel_encoder_context *encoder_context,
+                                  VAEncMiscParameterHRD *misc)
+{
+    if (encoder_context->brc.hrd_buffer_size != misc->buffer_size ||
+        encoder_context->brc.hrd_initial_buffer_fullness != misc->initial_buffer_fullness) {
+        encoder_context->brc.hrd_buffer_size = misc->buffer_size;
+        encoder_context->brc.hrd_initial_buffer_fullness = misc->initial_buffer_fullness;
+        encoder_context->brc.need_reset = 1;
+    }
+}
+
+static void
+intel_encoder_check_framerate_parameter(VADriverContextP ctx,
+                                        struct intel_encoder_context *encoder_context,
+                                        VAEncMiscParameterFrameRate *misc)
+{
+    int framerate_per_100s;
+
+    if (misc->framerate & 0xffff0000)
+        framerate_per_100s = (misc->framerate & 0xffff) * 100 / ((misc->framerate >> 16) & 0xffff);
+    else
+        framerate_per_100s = misc->framerate * 100;
+
+    if (encoder_context->brc.framerate_per_100s != framerate_per_100s) {
+        encoder_context->brc.framerate_per_100s = framerate_per_100s;
+        encoder_context->brc.need_reset = 1;
+    }
+}
+
+static VAStatus
+intel_encoder_check_brc_parameter(VADriverContextP ctx,
+                                  struct encode_state *encode_state,
+                                  struct intel_encoder_context *encoder_context)
+{
+    VAStatus ret;
+    VAEncMiscParameterBuffer *misc_param;
+    int i;
+
+    if (!(encoder_context->rate_control_mode & (VA_RC_CBR | VA_RC_VBR)))
+        return VA_STATUS_SUCCESS;
+
+    ret = intel_encoder_check_brc_sequence_parameter(ctx, encode_state, encoder_context);
+
+    if (ret)
+        return ret;
+
+    for (i = 0; i < ARRAY_ELEMS(encode_state->misc_param); i++) {
+        if (!encode_state->misc_param[i] || !encode_state->misc_param[i]->buffer)
+            continue;
+
+        misc_param = (VAEncMiscParameterBuffer *)encode_state->misc_param[i]->buffer;
+
+        switch (misc_param->type) {
+        case VAEncMiscParameterTypeFrameRate:
+            intel_encoder_check_framerate_parameter(ctx,
+                                                    encoder_context,
+                                                    (VAEncMiscParameterFrameRate *)misc_param->data);
+            break;
+
+        case VAEncMiscParameterTypeRateControl:
+            intel_encoder_check_rate_control_parameter(ctx,
+                                                       encoder_context,
+                                                       (VAEncMiscParameterRateControl *)misc_param->data);
+            break;
+
+        case VAEncMiscParameterTypeHRD:
+            intel_encoder_check_hrd_parameter(ctx,
+                                              encoder_context,
+                                              (VAEncMiscParameterHRD *)misc_param->data);
+            break;
+
+        default:
+            break;
+        }
+    }
+
+    return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
 intel_encoder_check_misc_parameter(VADriverContextP ctx,
                                   struct encode_state *encode_state,
                                   struct intel_encoder_context *encoder_context)
 {
+    VAStatus ret = VA_STATUS_SUCCESS;
 
     if (encode_state->misc_param[VAEncMiscParameterTypeQualityLevel] &&
         encode_state->misc_param[VAEncMiscParameterTypeQualityLevel]->buffer) {
@@ -312,14 +481,16 @@ intel_encoder_check_misc_parameter(VADriverContextP ctx,
 
         if (encoder_context->quality_level == 0)
             encoder_context->quality_level = ENCODER_DEFAULT_QUALITY;
-        else if (encoder_context->quality_level > encoder_context->quality_range)
-            goto error;
-   }
+        else if (encoder_context->quality_level > encoder_context->quality_range) {
+            ret = VA_STATUS_ERROR_INVALID_PARAMETER;
+            goto out;
+        }
+    }
 
-    return VA_STATUS_SUCCESS;
+    ret = intel_encoder_check_brc_parameter(ctx, encode_state, encoder_context);
 
-error:
-    return VA_STATUS_ERROR_INVALID_PARAMETER;
+out:
+    return ret;
 }
 
 static VAStatus
@@ -789,6 +960,7 @@ intel_encoder_end_picture(VADriverContextP ctx,
 
     encoder_context->mfc_pipeline(ctx, profile, encode_state, encoder_context);
     encoder_context->num_frames_in_sequence++;
+    encoder_context->brc.need_reset = 0;
 
     return VA_STATUS_SUCCESS;
 }
diff --git a/src/i965_encoder.h b/src/i965_encoder.h
index 79bfa4b..7d5b15a 100644
--- a/src/i965_encoder.h
+++ b/src/i965_encoder.h
@@ -66,6 +66,18 @@ struct intel_encoder_context
     unsigned int frame_width_in_pixel;
     unsigned int frame_height_in_pixel;
 
+    struct {
+        unsigned short gop_size;
+        unsigned short num_iframes_in_gop;
+        unsigned short num_pframes_in_gop;
+        unsigned short num_bframes_in_gop;
+        unsigned int bits_per_second;
+        unsigned int framerate_per_100s;
+        unsigned int hrd_buffer_size;
+        unsigned int hrd_initial_buffer_fullness;
+        unsigned int need_reset;
+    } brc;
+
     void *vme_context;
     void *mfc_context;
     void *enc_priv_state;
-- 
1.9.1



More information about the Libva mailing list