[Libva] [PATCH 26/31] ENC: add MFX command for AVC encoder

Sean V Kelley seanvk at posteo.de
Tue Jan 10 23:38:08 UTC 2017


From: Pengfei Qu <Pengfei.Qu at intel.com>

Signed-off-by: Pengfei Qu <Pengfei.Qu at intel.com>
Reviewed-by: Sean V Kelley <seanvk at posteo.de>
---
 src/gen9_avc_encoder.c | 561 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 561 insertions(+)

diff --git a/src/gen9_avc_encoder.c b/src/gen9_avc_encoder.c
index 8b11c5a3..ccbd26cc 100755
--- a/src/gen9_avc_encoder.c
+++ b/src/gen9_avc_encoder.c
@@ -6024,3 +6024,564 @@ gen9_mfc_avc_fqm_state(VADriverContextP ctx,
         gen9_mfc_fqm_state(ctx, MFX_QM_AVC_8x8_INTER_MATRIX, fqm, 32, encoder_context);
     }
 }
+
+static void
+gen9_mfc_avc_insert_object(VADriverContextP ctx,
+                           struct intel_encoder_context *encoder_context,
+                           unsigned int *insert_data, int lenght_in_dws, int data_bits_in_last_dw,
+                           int skip_emul_byte_count, int is_last_header, int is_end_of_slice, int emulation_flag,
+                           int slice_header_indicator)
+{
+    struct intel_batchbuffer *batch = encoder_context->base.batch;
+
+    if (data_bits_in_last_dw == 0)
+	data_bits_in_last_dw = 32;
+
+    BEGIN_BCS_BATCH(batch, lenght_in_dws + 2);
+
+    OUT_BCS_BATCH(batch, MFX_INSERT_OBJECT | (lenght_in_dws));
+    OUT_BCS_BATCH(batch,
+                  (0 << 16) |   /* always start at offset 0 */
+                  (slice_header_indicator << 14) |
+                  (data_bits_in_last_dw << 8) |
+                  (skip_emul_byte_count << 4) |
+                  (!!emulation_flag << 3) |
+                  ((!!is_last_header) << 2) |
+                  ((!!is_end_of_slice) << 1) |
+                  (0 << 0));    /* TODO: check this flag */
+    intel_batchbuffer_data(batch, insert_data, lenght_in_dws * 4);
+
+    ADVANCE_BCS_BATCH(batch);
+}
+
+static void
+gen9_mfc_avc_insert_slice_packed_data(VADriverContextP ctx,
+                                      struct encode_state *encode_state,
+                                      struct intel_encoder_context *encoder_context,
+                                      int slice_index)
+{
+    VAEncPackedHeaderParameterBuffer *param = NULL;
+    unsigned int length_in_bits;
+    unsigned int *header_data = NULL;
+    int count, i, start_index;
+    int slice_header_index;
+
+    if (encode_state->slice_header_index[slice_index] == 0)
+        slice_header_index = -1;
+    else
+        slice_header_index = (encode_state->slice_header_index[slice_index] & SLICE_PACKED_DATA_INDEX_MASK);
+
+    count = encode_state->slice_rawdata_count[slice_index];
+    start_index = (encode_state->slice_rawdata_index[slice_index] & SLICE_PACKED_DATA_INDEX_MASK);
+
+    for (i = 0; i < count; i++) {
+        unsigned int skip_emul_byte_cnt;
+
+        header_data = (unsigned int *)encode_state->packed_header_data_ext[start_index + i]->buffer;
+
+        param = (VAEncPackedHeaderParameterBuffer *)(encode_state->packed_header_params_ext[start_index + i]->buffer);
+
+        /* skip the slice header packed data type as it is lastly inserted */
+        if (param->type == VAEncPackedHeaderSlice)
+            continue;
+
+        length_in_bits = param->bit_length;
+
+        skip_emul_byte_cnt = intel_avc_find_skipemulcnt((unsigned char *)header_data, length_in_bits);
+
+        /* as the slice header is still required, the last header flag is set to
+         * zero.
+         */
+        gen9_mfc_avc_insert_object(ctx,
+                                   encoder_context,
+                                   header_data,
+                                   ALIGN(length_in_bits, 32) >> 5,
+                                   length_in_bits & 0x1f,
+                                   skip_emul_byte_cnt,
+                                   0,
+                                   0,
+                                   !param->has_emulation_bytes,
+                                   0);
+    }
+
+    if (slice_header_index == -1) {
+        VAEncSequenceParameterBufferH264 *seq_param = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
+        VAEncPictureParameterBufferH264 *pic_param = (VAEncPictureParameterBufferH264 *)encode_state->pic_param_ext->buffer;
+        VAEncSliceParameterBufferH264 *slice_params = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[slice_index]->buffer;
+        unsigned char *slice_header = NULL;
+        int slice_header_length_in_bits = 0;
+
+        /* No slice header data is passed. And the driver needs to generate it */
+        /* For the Normal H264 */
+        slice_header_length_in_bits = build_avc_slice_header(seq_param,
+                                                             pic_param,
+                                                             slice_params,
+                                                             &slice_header);
+        gen9_mfc_avc_insert_object(ctx,
+                                   encoder_context,
+                                   (unsigned int *)slice_header,
+                                   ALIGN(slice_header_length_in_bits, 32) >> 5,
+                                   slice_header_length_in_bits & 0x1f,
+                                   5,  /* first 5 bytes are start code + nal unit type */
+                                   1, 0, 1,
+                                   1);
+
+        free(slice_header);
+    } else {
+        unsigned int skip_emul_byte_cnt;
+
+        header_data = (unsigned int *)encode_state->packed_header_data_ext[slice_header_index]->buffer;
+
+        param = (VAEncPackedHeaderParameterBuffer *)(encode_state->packed_header_params_ext[slice_header_index]->buffer);
+        length_in_bits = param->bit_length;
+
+        /* as the slice header is the last header data for one slice,
+         * the last header flag is set to one.
+         */
+        skip_emul_byte_cnt = intel_avc_find_skipemulcnt((unsigned char *)header_data, length_in_bits);
+
+        gen9_mfc_avc_insert_object(ctx,
+                                   encoder_context,
+                                   header_data,
+                                   ALIGN(length_in_bits, 32) >> 5,
+                                   length_in_bits & 0x1f,
+                                   skip_emul_byte_cnt,
+                                   1,
+                                   0,
+                                   !param->has_emulation_bytes,
+                                   1);
+    }
+
+    return;
+}
+
+static void
+gen9_mfc_avc_inset_headers(VADriverContextP ctx,
+                           struct encode_state *encode_state,
+                           struct intel_encoder_context *encoder_context,
+                           VAEncSliceParameterBufferH264 *slice_param,
+                           int slice_index)
+{
+    struct encoder_vme_mfc_context * pak_context = (struct encoder_vme_mfc_context *)encoder_context->vme_context;
+    struct generic_enc_codec_state * generic_state = (struct generic_enc_codec_state * )pak_context->generic_enc_state;
+    int idx = va_enc_packed_type_to_idx(VAEncPackedHeaderH264_SPS);
+    unsigned int internal_rate_mode = generic_state->internal_rate_mode;
+    unsigned int skip_emul_byte_cnt;
+
+    if (slice_index == 0) {
+        if (encode_state->packed_header_data[idx]) {
+            VAEncPackedHeaderParameterBuffer *param = NULL;
+            unsigned int *header_data = (unsigned int *)encode_state->packed_header_data[idx]->buffer;
+            unsigned int length_in_bits;
+
+            assert(encode_state->packed_header_param[idx]);
+            param = (VAEncPackedHeaderParameterBuffer *)encode_state->packed_header_param[idx]->buffer;
+            length_in_bits = param->bit_length;
+
+            skip_emul_byte_cnt = intel_avc_find_skipemulcnt((unsigned char *)header_data, length_in_bits);
+            gen9_mfc_avc_insert_object(ctx,
+                                       encoder_context,
+                                       header_data,
+                                       ALIGN(length_in_bits, 32) >> 5,
+                                       length_in_bits & 0x1f,
+                                       skip_emul_byte_cnt,
+                                       0,
+                                       0,
+                                       !param->has_emulation_bytes,
+                                       0);
+        }
+
+        idx = va_enc_packed_type_to_idx(VAEncPackedHeaderH264_PPS);
+
+        if (encode_state->packed_header_data[idx]) {
+            VAEncPackedHeaderParameterBuffer *param = NULL;
+            unsigned int *header_data = (unsigned int *)encode_state->packed_header_data[idx]->buffer;
+            unsigned int length_in_bits;
+
+            assert(encode_state->packed_header_param[idx]);
+            param = (VAEncPackedHeaderParameterBuffer *)encode_state->packed_header_param[idx]->buffer;
+            length_in_bits = param->bit_length;
+
+            skip_emul_byte_cnt = intel_avc_find_skipemulcnt((unsigned char *)header_data, length_in_bits);
+
+            gen9_mfc_avc_insert_object(ctx,
+                                       encoder_context,
+                                       header_data,
+                                       ALIGN(length_in_bits, 32) >> 5,
+                                       length_in_bits & 0x1f,
+                                       skip_emul_byte_cnt,
+                                       0,
+                                       0,
+                                       !param->has_emulation_bytes,
+                                       0);
+        }
+
+        idx = va_enc_packed_type_to_idx(VAEncPackedHeaderH264_SEI);
+
+        if (encode_state->packed_header_data[idx]) {
+            VAEncPackedHeaderParameterBuffer *param = NULL;
+            unsigned int *header_data = (unsigned int *)encode_state->packed_header_data[idx]->buffer;
+            unsigned int length_in_bits;
+
+            assert(encode_state->packed_header_param[idx]);
+            param = (VAEncPackedHeaderParameterBuffer *)encode_state->packed_header_param[idx]->buffer;
+            length_in_bits = param->bit_length;
+
+            skip_emul_byte_cnt = intel_avc_find_skipemulcnt((unsigned char *)header_data, length_in_bits);
+            gen9_mfc_avc_insert_object(ctx,
+                                       encoder_context,
+                                       header_data,
+                                       ALIGN(length_in_bits, 32) >> 5,
+                                       length_in_bits & 0x1f,
+                                       skip_emul_byte_cnt,
+                                       0,
+                                       0,
+                                       !param->has_emulation_bytes,
+                                       0);
+        } else if (internal_rate_mode == INTEL_BRC_CBR) {
+            /* TODO: insert others */
+        }
+    }
+
+    gen9_mfc_avc_insert_slice_packed_data(ctx,
+                                          encode_state,
+                                          encoder_context,
+                                          slice_index);
+}
+
+static void
+gen9_mfc_avc_slice_state(VADriverContextP ctx,
+                         struct encode_state *encode_state,
+                         struct intel_encoder_context *encoder_context,
+                         VAEncPictureParameterBufferH264 *pic_param,
+                         VAEncSliceParameterBufferH264 *slice_param,
+                         VAEncSliceParameterBufferH264 *next_slice_param)
+{
+    struct encoder_vme_mfc_context * pak_context = (struct encoder_vme_mfc_context *)encoder_context->vme_context;
+    struct gen9_avc_encoder_context * avc_ctx = (struct gen9_avc_encoder_context * )pak_context->private_enc_ctx;
+    struct generic_enc_codec_state * generic_state = (struct generic_enc_codec_state * )pak_context->generic_enc_state;
+    struct avc_enc_state * avc_state = (struct avc_enc_state * )pak_context->private_enc_state;
+    struct intel_batchbuffer *batch = encoder_context->base.batch;
+    unsigned int luma_log2_weight_denom = slice_param->luma_log2_weight_denom;
+    unsigned int chroma_log2_weight_denom = slice_param->chroma_log2_weight_denom;
+    unsigned char correct[6], grow, shrink;
+    int slice_hor_pos, slice_ver_pos, next_slice_hor_pos, next_slice_ver_pos;
+    int max_qp_n, max_qp_p;
+    int i;
+    int weighted_pred_idc = 0;
+    int num_ref_l0 = 0, num_ref_l1 = 0;
+    int slice_type = intel_avc_enc_slice_type_fixup(slice_param->slice_type);
+    int slice_qp = pic_param->pic_init_qp + slice_param->slice_qp_delta;
+    unsigned int rounding_value = 0;
+    unsigned int rounding_inter_enable = 0;
+
+    //check the inter rounding
+    if(generic_state->frame_type == SLICE_TYPE_P)
+    {
+        if(avc_state->rounding_inter_p == AVC_INVALID_ROUNDING_VALUE)
+        {
+            if(avc_state->adaptive_rounding_inter_enable && !(generic_state->brc_enabled))
+            {
+                if(generic_state->gop_ref_distance == 1)
+                    avc_state->rounding_value = gen9_avc_adaptive_inter_rounding_p_without_b[slice_qp];
+                else
+                    avc_state->rounding_value = gen9_avc_adaptive_inter_rounding_p[slice_qp];
+            }
+            else
+            {
+                avc_state->rounding_value = gen9_avc_inter_rounding_p[generic_state->preset];
+            }
+
+        }else
+        {
+            avc_state->rounding_value = avc_state->rounding_inter_p;
+        }
+    }else if(generic_state->frame_type == SLICE_TYPE_B)
+    {
+        if(pic_param->pic_fields.bits.reference_pic_flag)
+        {
+            if(avc_state->rounding_inter_b_ref == AVC_INVALID_ROUNDING_VALUE)
+                avc_state->rounding_value = gen9_avc_inter_rounding_b_ref[generic_state->preset];
+            else
+                avc_state->rounding_value = avc_state->rounding_inter_b_ref;
+        }
+        else
+        {
+            if(avc_state->rounding_inter_b == AVC_INVALID_ROUNDING_VALUE)
+            {
+                if(avc_state->adaptive_rounding_inter_enable && !(generic_state->brc_enabled))
+                    avc_state->rounding_value = gen9_avc_adaptive_inter_rounding_b[slice_qp];
+                else
+                    avc_state->rounding_value = gen9_avc_inter_rounding_b[generic_state->preset];
+            }else
+            {
+                avc_state->rounding_value = avc_state->rounding_inter_b;
+            }
+        }
+    }
+
+    slice_hor_pos = slice_param->macroblock_address % generic_state->frame_width_in_mbs;
+    slice_ver_pos = slice_param->macroblock_address / generic_state->frame_height_in_mbs;
+
+    if (next_slice_param) {
+        next_slice_hor_pos = next_slice_param->macroblock_address % generic_state->frame_width_in_mbs;
+        next_slice_ver_pos = next_slice_param->macroblock_address / generic_state->frame_height_in_mbs;
+    } else {
+        next_slice_hor_pos = 0;
+        next_slice_ver_pos = generic_state->frame_height_in_mbs;
+    }
+
+    if (slice_type == SLICE_TYPE_I) {
+        luma_log2_weight_denom = 0;
+        chroma_log2_weight_denom = 0;
+    } else if (slice_type == SLICE_TYPE_P) {
+        weighted_pred_idc = pic_param->pic_fields.bits.weighted_pred_flag;
+        num_ref_l0 = pic_param->num_ref_idx_l0_active_minus1 + 1;
+        rounding_inter_enable = avc_state->rounding_inter_enable;
+        rounding_value = avc_state->rounding_value;
+
+        if (slice_param->num_ref_idx_active_override_flag)
+            num_ref_l0 = slice_param->num_ref_idx_l0_active_minus1 + 1;
+    } else if (slice_type == SLICE_TYPE_B) {
+        weighted_pred_idc = pic_param->pic_fields.bits.weighted_bipred_idc;
+        num_ref_l0 = pic_param->num_ref_idx_l0_active_minus1 + 1;
+        num_ref_l1 = pic_param->num_ref_idx_l1_active_minus1 + 1;
+        rounding_inter_enable = avc_state->rounding_inter_enable;
+        rounding_value = avc_state->rounding_value;
+
+        if (slice_param->num_ref_idx_active_override_flag) {
+            num_ref_l0 = slice_param->num_ref_idx_l0_active_minus1 + 1;
+            num_ref_l1 = slice_param->num_ref_idx_l1_active_minus1 + 1;
+        }
+
+        if (weighted_pred_idc == 2) {
+            /* 8.4.3 - Derivation process for prediction weights (8-279) */
+            luma_log2_weight_denom = 5;
+            chroma_log2_weight_denom = 5;
+        }
+    }
+
+    max_qp_n = 0;       /* TODO: update it */
+    max_qp_p = 0;       /* TODO: update it */
+    grow = 0;           /* TODO: update it */
+    shrink = 0;         /* TODO: update it */
+
+    for (i = 0; i < 6; i++)
+        correct[i] = 0; /* TODO: update it */
+
+    BEGIN_BCS_BATCH(batch, 11);
+
+    OUT_BCS_BATCH(batch, MFX_AVC_SLICE_STATE | (11 - 2) );
+    OUT_BCS_BATCH(batch, slice_type);
+    OUT_BCS_BATCH(batch,
+                  (num_ref_l1 << 24) |
+                  (num_ref_l0 << 16) |
+                  (chroma_log2_weight_denom << 8) |
+                  (luma_log2_weight_denom << 0));
+    OUT_BCS_BATCH(batch,
+                  (weighted_pred_idc << 30) |
+                  (((slice_type == SLICE_TYPE_B)?slice_param->direct_spatial_mv_pred_flag:0) << 29) |
+                  (slice_param->disable_deblocking_filter_idc << 27) |
+                  (slice_param->cabac_init_idc << 24) |
+                  (slice_qp << 16) |
+                  ((slice_param->slice_beta_offset_div2 & 0xf) << 8) |
+                  ((slice_param->slice_alpha_c0_offset_div2 & 0xf) << 0));
+
+    OUT_BCS_BATCH(batch,
+                  slice_ver_pos << 24 |
+                  slice_hor_pos << 16 |
+                  slice_param->macroblock_address);
+    OUT_BCS_BATCH(batch,
+                  next_slice_ver_pos << 16 |
+                  next_slice_hor_pos);
+
+    OUT_BCS_BATCH(batch,
+                  (0 << 31) |           /* TODO: ignore it for VDENC ??? */
+                  (1 << 30) |           /* ResetRateControlCounter */
+                  (2 << 28) |           /* Loose Rate Control */
+                  (0 << 24) |           /* RC Stable Tolerance */
+                  (0 << 23) |           /* RC Panic Enable */
+                  (1 << 22) |           /* CBP mode */
+                  (0 << 21) |           /* MB Type Direct Conversion, 0: Enable, 1: Disable */
+                  (0 << 20) |           /* MB Type Skip Conversion, 0: Enable, 1: Disable */
+                  (!next_slice_param << 19) |                   /* Is Last Slice */
+                  (0 << 18) | 	        /* BitstreamOutputFlag Compressed BitStream Output Disable Flag 0:enable 1:disable */
+                  (1 << 17) |	        /* HeaderPresentFlag */
+                  (1 << 16) |	        /* SliceData PresentFlag */
+                  (0 << 15) |	        /* TailPresentFlag, TODO: check it on VDEnc  */
+                  (1 << 13) |	        /* RBSP NAL TYPE */
+                  (1 << 12));           /* CabacZeroWordInsertionEnable */
+
+    OUT_BCS_BATCH(batch, avc_ctx->compressed_bitstream.start_offset);
+
+    OUT_BCS_BATCH(batch,
+                  (max_qp_n << 24) |     /*Target QP - 24 is lowest QP*/
+                  (max_qp_p << 16) |     /*Target QP + 20 is highest QP*/
+                  (shrink << 8) |
+                  (grow << 0));
+    OUT_BCS_BATCH(batch,
+                  (rounding_inter_enable << 31) |
+                  (rounding_value << 28) |
+                  (1 << 27) |
+                  (5 << 24) |
+                  (correct[5] << 20) |
+                  (correct[4] << 16) |
+                  (correct[3] << 12) |
+                  (correct[2] << 8) |
+                  (correct[1] << 4) |
+                  (correct[0] << 0));
+    OUT_BCS_BATCH(batch, 0);
+
+    ADVANCE_BCS_BATCH(batch);
+}
+
+static uint8_t
+gen9_mfc_avc_get_ref_idx_state(VAPictureH264 *va_pic, unsigned int frame_store_id)
+{
+    unsigned int is_long_term =
+        !!(va_pic->flags & VA_PICTURE_H264_LONG_TERM_REFERENCE);
+    unsigned int is_top_field =
+        !!(va_pic->flags & VA_PICTURE_H264_TOP_FIELD);
+    unsigned int is_bottom_field =
+        !!(va_pic->flags & VA_PICTURE_H264_BOTTOM_FIELD);
+
+    return ((is_long_term                         << 6) |
+            (0 << 5) |
+            (frame_store_id                       << 1) |
+            ((is_top_field ^ 1) & is_bottom_field));
+}
+
+static void
+gen9_mfc_avc_ref_idx_state(VADriverContextP ctx,
+                                 struct encode_state *encode_state,
+                                 struct intel_encoder_context *encoder_context,
+                                 VAEncSliceParameterBufferH264 *slice_param)
+{
+    struct encoder_vme_mfc_context * pak_context = (struct encoder_vme_mfc_context *)encoder_context->vme_context;
+    struct avc_enc_state * avc_state = (struct avc_enc_state * )pak_context->private_enc_state;
+    struct intel_batchbuffer *batch = encoder_context->base.batch;
+    VAPictureH264 *ref_pic;
+    int i, slice_type, ref_idx_shift;
+    unsigned int fwd_ref_entry;
+    unsigned int bwd_ref_entry;
+
+    /* max 4 ref frames are allowed for l0 and l1 */
+    fwd_ref_entry = 0x80808080;
+    slice_type = intel_avc_enc_slice_type_fixup(slice_param->slice_type);
+
+    if ((slice_type == SLICE_TYPE_P) ||
+        (slice_type == SLICE_TYPE_B)) {
+          for (i = 0; i < avc_state->num_refs[0]; i++) {
+              ref_pic = &slice_param->RefPicList0[i];
+              ref_idx_shift = i * 8;
+
+              fwd_ref_entry &= ~(0xFF << ref_idx_shift);
+              fwd_ref_entry += (gen9_mfc_avc_get_ref_idx_state(ref_pic, avc_state->list_ref_idx[0][i]) << ref_idx_shift);
+          }
+    }
+
+    bwd_ref_entry = 0x80808080;
+    if (slice_type == SLICE_TYPE_B) {
+        for (i = 0; i < avc_state->num_refs[1]; i++) {
+            ref_pic = &slice_param->RefPicList1[i];
+            ref_idx_shift = i * 8;
+
+            bwd_ref_entry &= ~(0xFF << ref_idx_shift);
+            bwd_ref_entry += (gen9_mfc_avc_get_ref_idx_state(ref_pic, avc_state->list_ref_idx[1][i]) << ref_idx_shift);
+        }
+    }
+
+    if ((slice_type == SLICE_TYPE_P) ||
+        (slice_type == SLICE_TYPE_B)) {
+        BEGIN_BCS_BATCH(batch, 10);
+        OUT_BCS_BATCH(batch, MFX_AVC_REF_IDX_STATE | 8);
+        OUT_BCS_BATCH(batch, 0);                        // L0
+        OUT_BCS_BATCH(batch, fwd_ref_entry);
+
+        for (i = 0; i < 7; i++) {
+            OUT_BCS_BATCH(batch, 0x80808080);
+        }
+
+        ADVANCE_BCS_BATCH(batch);
+    }
+
+    if (slice_type == SLICE_TYPE_B) {
+        BEGIN_BCS_BATCH(batch, 10);
+        OUT_BCS_BATCH(batch, MFX_AVC_REF_IDX_STATE | 8);
+        OUT_BCS_BATCH(batch, 1);                  //Select L1
+        OUT_BCS_BATCH(batch, bwd_ref_entry);      //max 4 reference allowed
+        for(i = 0; i < 7; i++) {
+            OUT_BCS_BATCH(batch, 0x80808080);
+        }
+        ADVANCE_BCS_BATCH(batch);
+    }
+}
+
+static void
+gen9_mfc_avc_weightoffset_state(VADriverContextP ctx,
+                                struct encode_state *encode_state,
+                                struct intel_encoder_context *encoder_context,
+                                VAEncPictureParameterBufferH264 *pic_param,
+                                VAEncSliceParameterBufferH264 *slice_param)
+{
+    struct intel_batchbuffer *batch = encoder_context->base.batch;
+    int i, slice_type;
+    short weightoffsets[32 * 6];
+
+    slice_type = intel_avc_enc_slice_type_fixup(slice_param->slice_type);
+
+    if (slice_type == SLICE_TYPE_P &&
+        pic_param->pic_fields.bits.weighted_pred_flag == 1) {
+        memset(weightoffsets,0,32*6 * sizeof(short));
+        for (i = 0; i < 32; i++) {
+            weightoffsets[i * 6 + 0] = slice_param->luma_weight_l0[i];
+            weightoffsets[i * 6 + 1] = slice_param->luma_offset_l0[i];
+            weightoffsets[i * 6 + 2] = slice_param->chroma_weight_l0[i][0];
+            weightoffsets[i * 6 + 3] = slice_param->chroma_offset_l0[i][0];
+            weightoffsets[i * 6 + 4] = slice_param->chroma_weight_l0[i][1];
+            weightoffsets[i * 6 + 5] = slice_param->chroma_offset_l0[i][1];
+        }
+
+        BEGIN_BCS_BATCH(batch, 98);
+        OUT_BCS_BATCH(batch, MFX_AVC_WEIGHTOFFSET_STATE | (98 - 2));
+        OUT_BCS_BATCH(batch, 0);
+        intel_batchbuffer_data(batch, weightoffsets, sizeof(weightoffsets));
+
+        ADVANCE_BCS_BATCH(batch);
+    }
+
+    if (slice_type == SLICE_TYPE_B &&
+        (pic_param->pic_fields.bits.weighted_bipred_idc == 1)) {
+        memset(weightoffsets,0,32*6 * sizeof(short));
+        for (i = 0; i < 32; i++) {
+            weightoffsets[i * 6 + 0] = slice_param->luma_weight_l0[i];
+            weightoffsets[i * 6 + 1] = slice_param->luma_offset_l0[i];
+            weightoffsets[i * 6 + 2] = slice_param->chroma_weight_l0[i][0];
+            weightoffsets[i * 6 + 3] = slice_param->chroma_offset_l0[i][0];
+            weightoffsets[i * 6 + 4] = slice_param->chroma_weight_l0[i][1];
+            weightoffsets[i * 6 + 5] = slice_param->chroma_offset_l0[i][1];
+        }
+
+        BEGIN_BCS_BATCH(batch, 98);
+        OUT_BCS_BATCH(batch, MFX_AVC_WEIGHTOFFSET_STATE | (98 - 2));
+        OUT_BCS_BATCH(batch, 0);
+        intel_batchbuffer_data(batch, weightoffsets, sizeof(weightoffsets));
+        ADVANCE_BCS_BATCH(batch);
+
+        memset(weightoffsets,0,32*6 * sizeof(short));
+        for (i = 0; i < 32; i++) {
+            weightoffsets[i * 6 + 0] = slice_param->luma_weight_l1[i];
+            weightoffsets[i * 6 + 1] = slice_param->luma_offset_l1[i];
+            weightoffsets[i * 6 + 2] = slice_param->chroma_weight_l1[i][0];
+            weightoffsets[i * 6 + 3] = slice_param->chroma_offset_l1[i][0];
+            weightoffsets[i * 6 + 4] = slice_param->chroma_weight_l1[i][1];
+            weightoffsets[i * 6 + 5] = slice_param->chroma_offset_l1[i][1];
+        }
+
+        BEGIN_BCS_BATCH(batch, 98);
+        OUT_BCS_BATCH(batch, MFX_AVC_WEIGHTOFFSET_STATE | (98 - 2));
+        OUT_BCS_BATCH(batch, 1);
+        intel_batchbuffer_data(batch, weightoffsets, sizeof(weightoffsets));
+        ADVANCE_BCS_BATCH(batch);
+    }
+}
-- 
2.11.0



More information about the Libva mailing list