[Libva] [PATCH] HEVC ENC:add CBR feature.

Pengfei Qu pengfei.qu at intel.com
Sun Nov 8 20:04:27 PST 2015


Signed-off-by: Pengfei Qu <pengfei.qu at intel.com>
---
 src/gen6_mfc_common.c |  34 ++++++++++---
 src/gen9_mfc_hevc.c   | 132 +++++++++++++++++++++++++++++++-------------------
 2 files changed, 108 insertions(+), 58 deletions(-)

diff --git a/src/gen6_mfc_common.c b/src/gen6_mfc_common.c
index 663d197..83a2c7c 100644
--- a/src/gen6_mfc_common.c
+++ b/src/gen6_mfc_common.c
@@ -41,6 +41,7 @@
 #include "i965_encoder_utils.h"
 #include "gen6_mfc.h"
 #include "gen6_vme.h"
+#include "gen9_mfc.h"
 #include "intel_media.h"
 
 #ifndef HAVE_LOG2F
@@ -1227,6 +1228,9 @@ intel_mfc_avc_ref_idx_state(VADriverContextP ctx,
             fref_entry &= ~(0xFF << ref_idx_l0_shift);
             fref_entry += (intel_get_ref_idx_state_1(vme_context->used_references[0], frame_index) << ref_idx_l0_shift);
         }
+        if(frame_index == 1){
+            WARN_ONCE("Input ref list is Wrong !\n");
+        }
     }
 
     if (slice_type == SLICE_TYPE_B) {
@@ -1797,10 +1801,11 @@ void intel_vme_hevc_update_mbmv_cost(VADriverContextP ctx,
                                      struct encode_state *encode_state,
                                      struct intel_encoder_context *encoder_context)
 {
-    //struct gen6_mfc_context *mfc_context = encoder_context->mfc_context;
+    struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
     struct gen6_vme_context *vme_context = encoder_context->vme_context;
     VAEncPictureParameterBufferHEVC *pic_param = (VAEncPictureParameterBufferHEVC *)encode_state->pic_param_ext->buffer;
     VAEncSliceParameterBufferHEVC *slice_param = (VAEncSliceParameterBufferHEVC *)encode_state->slice_params_ext[0]->buffer;
+    VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
     int qp, m_cost, j, mv_count;
     uint8_t *vme_state_message = (uint8_t *)(vme_context->vme_state_message);
     float   lambda, m_costf;
@@ -1810,10 +1815,24 @@ void intel_vme_hevc_update_mbmv_cost(VADriverContextP ctx,
 
 
     /* to do for CBR*/
-    //if (encoder_context->rate_control_mode == VA_RC_CQP)
-    qp = pic_param->pic_init_qp + slice_param->slice_qp_delta;
-    //else
-    //qp = mfc_context->bit_rate_control_context[slice_type].QpPrimeY;
+    if (encoder_context->rate_control_mode == VA_RC_CQP)
+        qp = pic_param->pic_init_qp + slice_param->slice_qp_delta;
+    else if(encoder_context->rate_control_mode == VA_RC_CBR)
+    {
+        qp = mfc_context->bit_rate_control_context[slice_type].QpPrimeY;
+        if(slice_type == HEVC_SLICE_B) {
+            if(pSequenceParameter->ip_period == 1)
+            {
+                slice_type = HEVC_SLICE_P;
+                qp = mfc_context->bit_rate_control_context[HEVC_SLICE_P].QpPrimeY;
+
+            }else if(mfc_context->vui_hrd.i_frame_number % pSequenceParameter->ip_period == 1){
+                slice_type = HEVC_SLICE_P;
+                qp = mfc_context->bit_rate_control_context[HEVC_SLICE_P].QpPrimeY;
+            }
+        }
+
+    }
 
     if (vme_state_message == NULL)
         return;
@@ -1884,7 +1903,8 @@ void intel_vme_hevc_update_mbmv_cost(VADriverContextP ctx,
             vme_state_message[MODE_INTER_4X4] = intel_format_lutvalue(m_cost, 0x6f);
             /* BWD is not used in P-frame */
             vme_state_message[MODE_INTER_BWD] = 0;
-        } else {
+        } 
+        else {
             m_costf = lambda * 2.5;
             m_cost = m_costf;
             vme_state_message[MODE_INTER_16X16] = intel_format_lutvalue(m_cost, 0x8f);
@@ -1903,6 +1923,6 @@ void intel_vme_hevc_update_mbmv_cost(VADriverContextP ctx,
             m_costf = lambda * 1.5;
             m_cost = m_costf;
             vme_state_message[MODE_INTER_BWD] = intel_format_lutvalue(m_cost, 0x6f);
-        }
+        } 
     }
 }
diff --git a/src/gen9_mfc_hevc.c b/src/gen9_mfc_hevc.c
index 2752bb8..57df613 100644
--- a/src/gen9_mfc_hevc.c
+++ b/src/gen9_mfc_hevc.c
@@ -481,7 +481,7 @@ gen9_hcpe_hevc_pic_state(VADriverContextP ctx, struct encode_state *encode_state
     int ctb_size = 1 << log2_ctb_size;
     double rawctubits = 8 * 3 * ctb_size * ctb_size / 2.0;
     int maxctubits = (int)(5 * rawctubits / 3) ;
-    double bitrate = seq_param->bits_per_second * 1000.0;
+    double bitrate = seq_param->bits_per_second * 1.0;
     double framebitrate = bitrate / 32 / 8; //32 byte unit
     int minframebitrate = 0;//(int) (framebitrate * 3 / 10);
     int maxframebitrate = (int)(framebitrate * 10 / 10);
@@ -663,6 +663,10 @@ gen9_hcpe_ref_idx_state_1(struct intel_batchbuffer *batch,
         WARN_ONCE("RefPicList 0 or 1 is not found in DPB!\n");
     }
 
+    if(num_ref_minus1 == 0 && frame_index == 1 && list == 0){
+        WARN_ONCE("Input ref list is Wrong !\n");
+    }
+
     BEGIN_BCS_BATCH(batch, 18);
 
     OUT_BCS_BATCH(batch, HCP_REF_IDX_STATE | (18 - 2));
@@ -827,6 +831,8 @@ static void gen9_hcpe_init(VADriverContextP ctx,
     struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
     VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
     VAEncSliceParameterBufferHEVC *slice_param = (VAEncSliceParameterBufferHEVC *)encode_state->slice_params_ext[0]->buffer;
+    VAEncPictureParameterBufferHEVC *pPicParameter = (VAEncPictureParameterBufferHEVC *)encode_state->pic_param_ext->buffer;
+    int qp = pPicParameter->pic_init_qp + slice_param->slice_qp_delta;
     dri_bo *bo;
     int i, size = 0;
     int slice_batchbuffer_size;
@@ -1574,7 +1580,7 @@ gen9_hcpe_hevc_pipeline_slice_programing(VADriverContextP ctx,
     VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
     VAEncPictureParameterBufferHEVC *pPicParameter = (VAEncPictureParameterBufferHEVC *)encode_state->pic_param_ext->buffer;
     VAEncSliceParameterBufferHEVC *pSliceParameter = (VAEncSliceParameterBufferHEVC *)encode_state->slice_params_ext[slice_index]->buffer;
-    int qp = pPicParameter->pic_init_qp + pSliceParameter->slice_qp_delta;
+    int qp_slice = pPicParameter->pic_init_qp + pSliceParameter->slice_qp_delta;
     unsigned int rate_control_mode = encoder_context->rate_control_mode;
     //unsigned char *slice_header = NULL;	  // for future use
     //int slice_header_length_in_bits = 0;
@@ -1605,13 +1611,27 @@ gen9_hcpe_hevc_pipeline_slice_programing(VADriverContextP ctx,
     int mb_addr = 0;
     int cu_index = 0;
     int inter_rdo, intra_rdo;
+    int qp;
 
     if (log2_ctb_size == 5) num_cu_record = 16;
     else if (log2_ctb_size == 4) num_cu_record = 4;
     else if (log2_ctb_size == 6) num_cu_record = 64;
+
+    qp = qp_slice;
     if (rate_control_mode == VA_RC_CBR) {
         qp = mfc_context->bit_rate_control_context[slice_type].QpPrimeY;
-        pSliceParameter->slice_qp_delta = qp - pPicParameter->pic_init_qp;
+        if(slice_type == HEVC_SLICE_B) {
+            if(pSequenceParameter->ip_period == 1)
+            {
+                qp = mfc_context->bit_rate_control_context[HEVC_SLICE_P].QpPrimeY;
+
+            }else if(mfc_context->vui_hrd.i_frame_number % pSequenceParameter->ip_period == 1){
+                qp = mfc_context->bit_rate_control_context[HEVC_SLICE_P].QpPrimeY;
+            }
+        }
+        if (encode_state->slice_header_index[slice_index] == 0) {
+            pSliceParameter->slice_qp_delta = qp - pPicParameter->pic_init_qp;
+        }
     }
 
     /* only support for 8-bit pixel bit-depth */
@@ -1821,7 +1841,6 @@ void intel_hcpe_hevc_pipeline_header_programing(VADriverContextP ctx,
 {
     struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
     int idx = va_enc_packed_type_to_idx(VAEncPackedHeaderHEVC_VPS);
-    unsigned int rate_control_mode = encoder_context->rate_control_mode;
     unsigned int skip_emul_byte_cnt;
 
     if (encode_state->packed_header_data[idx]) {
@@ -1917,33 +1936,7 @@ void intel_hcpe_hevc_pipeline_header_programing(VADriverContextP ctx,
                                    0,
                                    !param->has_emulation_bytes,
                                    slice_batch);
-    } else if (rate_control_mode == VA_RC_CBR) {
-        // this is frist AU
-        struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
-
-        unsigned char *sei_data = NULL;
-
-        int length_in_bits = build_hevc_idr_sei_buffer_timing(
-                                 mfc_context->vui_hrd.i_initial_cpb_removal_delay_length,
-                                 mfc_context->vui_hrd.i_initial_cpb_removal_delay,
-                                 0,
-                                 mfc_context->vui_hrd.i_cpb_removal_delay_length,
-                                 mfc_context->vui_hrd.i_cpb_removal_delay * mfc_context->vui_hrd.i_frame_number,
-                                 mfc_context->vui_hrd.i_dpb_output_delay_length,
-                                 0,
-                                 &sei_data);
-        mfc_context->insert_object(ctx,
-                                   encoder_context,
-                                   (unsigned int *)sei_data,
-                                   ALIGN(length_in_bits, 32) >> 5,
-                                   length_in_bits & 0x1f,
-                                   4, /* to do  as NALU header is 2 bytes ,it seems here just offset to start code and keep nalu header*/
-                                   0,
-                                   0,
-                                   1,
-                                   slice_batch);
-        free(sei_data);
-    }
+    } 
 }
 
 VAStatus intel_hcpe_hevc_prepare(VADriverContextP ctx,
@@ -2079,14 +2072,13 @@ intel_hcpe_bit_rate_control_context_init(struct encode_state *encode_state,
         struct gen9_hcpe_context *mfc_context)
 {
     VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
-    int log2_cu_size = pSequenceParameter->log2_min_luma_coding_block_size_minus3 + 3;
-    int log2_ctb_size = pSequenceParameter->log2_diff_max_min_luma_coding_block_size + log2_cu_size;
-    int ctb_size = 1 << log2_ctb_size;
+    int ctb_size = 16;
     int width_in_mbs = (pSequenceParameter->pic_width_in_luma_samples + ctb_size - 1) / ctb_size;
     int height_in_mbs = (pSequenceParameter->pic_height_in_luma_samples + ctb_size - 1) / ctb_size;
 
     float fps =  pSequenceParameter->vui_time_scale * 0.5 / pSequenceParameter->vui_num_units_in_tick ;
-    int inter_mb_size = pSequenceParameter->bits_per_second * 1.0 / (fps + 4.0) / width_in_mbs / height_in_mbs;
+    double bitrate = pSequenceParameter->bits_per_second * 1.0;
+    int inter_mb_size = bitrate * 1.0 / (fps + 4.0) / width_in_mbs / height_in_mbs;
     int intra_mb_size = inter_mb_size * 5.0;
     int i;
 
@@ -2128,24 +2120,27 @@ static void intel_hcpe_brc_init(struct encode_state *encode_state,
 {
     struct gen9_hcpe_context *mfc_context = encoder_context->mfc_context;
     VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
-    VAEncMiscParameterBuffer* pMiscParamHRD = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeHRD]->buffer;
-    VAEncMiscParameterHRD* pParameterHRD = (VAEncMiscParameterHRD*)pMiscParamHRD->data;
+    VAEncMiscParameterHRD* pParameterHRD = NULL;
+    VAEncMiscParameterBuffer* pMiscParamHRD = NULL;
 
-    int log2_cu_size = pSequenceParameter->log2_min_luma_coding_block_size_minus3 + 3;
-    int log2_ctb_size = pSequenceParameter->log2_diff_max_min_luma_coding_block_size + log2_cu_size;
-    int ctb_size = 1 << log2_ctb_size;
-    int width_in_ctb = (pSequenceParameter->pic_width_in_luma_samples + ctb_size - 1) / ctb_size;
-    int height_in_ctb = (pSequenceParameter->pic_height_in_luma_samples + ctb_size - 1) / ctb_size;
-
-
-    double bitrate = pSequenceParameter->bits_per_second;
+    double bitrate = pSequenceParameter->bits_per_second * 1.0;
     double framerate = (double)pSequenceParameter->vui_time_scale / (2 * (double)pSequenceParameter->vui_num_units_in_tick);
     int inum = 1, pnum = 0, bnum = 0; /* Gop structure: number of I, P, B frames in the Gop. */
     int intra_period = pSequenceParameter->intra_period;
     int ip_period = pSequenceParameter->ip_period;
-    double qp1_size = 0.1 * 8 * 3 * (width_in_ctb << 4) * (height_in_ctb << 4) / 2;
-    double qp51_size = 0.001 * 8 * 3 * (width_in_ctb << 4) * (height_in_ctb << 4) / 2;
+    double qp1_size = 0.1 * 8 * 3 * pSequenceParameter->pic_width_in_luma_samples * pSequenceParameter->pic_height_in_luma_samples / 2;
+    double qp51_size = 0.001 * 8 * 3 * pSequenceParameter->pic_width_in_luma_samples * pSequenceParameter->pic_height_in_luma_samples / 2;
     double bpf;
+    int ratio_min = 1;
+    int ratio_max = 32;
+    int ratio = 8;
+    double buffer_size = 0;
+
+    if (!encode_state->misc_param[VAEncMiscParameterTypeHRD] || !encode_state->misc_param[VAEncMiscParameterTypeHRD]->buffer)
+        return;
+
+    pMiscParamHRD = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeHRD]->buffer;
+    pParameterHRD = (VAEncMiscParameterHRD*)pMiscParamHRD->data;
 
     if (pSequenceParameter->ip_period) {
         pnum = (intra_period + ip_period - 1) / ip_period - 1;
@@ -2165,10 +2160,35 @@ static void intel_hcpe_brc_init(struct encode_state *encode_state,
 
     bpf = mfc_context->brc.bits_per_frame = bitrate / framerate;
 
-    mfc_context->hrd.buffer_size = (double)pParameterHRD->buffer_size;
-    mfc_context->hrd.current_buffer_fullness =
-        (double)(pParameterHRD->initial_buffer_fullness < mfc_context->hrd.buffer_size) ?
-        pParameterHRD->initial_buffer_fullness : mfc_context->hrd.buffer_size / 2.;
+    if (!pParameterHRD || pParameterHRD->buffer_size <= 0)
+    {
+        mfc_context->hrd.buffer_size = bitrate * ratio;
+        mfc_context->hrd.current_buffer_fullness =
+            (double)(bitrate * ratio/2 < mfc_context->hrd.buffer_size) ?
+            bitrate * ratio/2 : mfc_context->hrd.buffer_size / 2.;
+    }else
+    {
+        buffer_size = (double)pParameterHRD->buffer_size ;
+        if(buffer_size < bitrate * ratio_min)
+        {
+            buffer_size = bitrate * ratio_min;
+        }else if (buffer_size > bitrate * ratio_max)
+        {
+            buffer_size = bitrate * ratio_max ;
+        }
+        mfc_context->hrd.buffer_size =buffer_size;
+        if(pParameterHRD->initial_buffer_fullness > 0)
+        {
+            mfc_context->hrd.current_buffer_fullness =
+                (double)(pParameterHRD->initial_buffer_fullness < mfc_context->hrd.buffer_size) ?
+                pParameterHRD->initial_buffer_fullness : mfc_context->hrd.buffer_size / 2.;
+        }else
+        {
+            mfc_context->hrd.current_buffer_fullness = mfc_context->hrd.buffer_size / 2.;
+
+        }
+    }
+
     mfc_context->hrd.target_buffer_fullness = (double)mfc_context->hrd.buffer_size / 2.;
     mfc_context->hrd.buffer_capacity = (double)mfc_context->hrd.buffer_size / qp1_size;
     mfc_context->hrd.violation_noted = 0;
@@ -2218,6 +2238,7 @@ int intel_hcpe_brc_postpack(struct encode_state *encode_state,
                             int frame_bits)
 {
     gen6_brc_status sts = BRC_NO_HRD_VIOLATION;
+    VAEncSequenceParameterBufferHEVC *pSequenceParameter = (VAEncSequenceParameterBufferHEVC *)encode_state->seq_param_ext->buffer;
     VAEncSliceParameterBufferHEVC *pSliceParameter = (VAEncSliceParameterBufferHEVC *)encode_state->slice_params_ext[0]->buffer;
     int slicetype = pSliceParameter->slice_type;
     int qpi = mfc_context->bit_rate_control_context[HEVC_SLICE_I].QpPrimeY;
@@ -2235,6 +2256,15 @@ int intel_hcpe_brc_postpack(struct encode_state *encode_state,
     double x, y;
     double frame_size_alpha;
 
+    if(slicetype == HEVC_SLICE_B) {
+        if(pSequenceParameter->ip_period == 1)
+        {
+            slicetype = HEVC_SLICE_P;
+        }else if(mfc_context->vui_hrd.i_frame_number % pSequenceParameter->ip_period == 1){
+            slicetype = HEVC_SLICE_P;
+        }
+    }
+
     qp = mfc_context->bit_rate_control_context[slicetype].QpPrimeY;
 
     target_frame_size = mfc_context->brc.target_frame_size[slicetype];
-- 
1.9.1



More information about the Libva mailing list