[Libva] [PATCH 24/31] ENC: VME pipeline init/prepare/run function for AVC encoder

Sean V Kelley seanvk at posteo.de
Tue Jan 10 23:38:06 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 | 442 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 442 insertions(+)

diff --git a/src/gen9_avc_encoder.c b/src/gen9_avc_encoder.c
index 04cf30f0..629a0dab 100755
--- a/src/gen9_avc_encoder.c
+++ b/src/gen9_avc_encoder.c
@@ -5183,3 +5183,445 @@ gen9_avc_encode_check_parameter(VADriverContextP ctx,
 
     return VA_STATUS_SUCCESS;
 }
+
+static VAStatus
+gen9_avc_vme_gpe_kernel_prepare(VADriverContextP ctx,
+                                struct encode_state *encode_state,
+                                struct intel_encoder_context *encoder_context)
+{
+    VAStatus va_status;
+    struct encoder_vme_mfc_context * vme_context = (struct encoder_vme_mfc_context *)encoder_context->vme_context;
+    struct gen9_avc_encoder_context * avc_ctx = (struct gen9_avc_encoder_context * )vme_context->private_enc_ctx;
+    struct generic_enc_codec_state * generic_state = (struct generic_enc_codec_state * )vme_context->generic_enc_state;
+    struct avc_enc_state * avc_state = (struct avc_enc_state * )vme_context->private_enc_state;
+
+    struct object_surface *obj_surface;
+    struct object_buffer *obj_buffer;
+    VAEncSliceParameterBufferH264 * slice_param = avc_state->slice_param[0];
+    VAEncPictureParameterBufferH264  *pic_param = avc_state->pic_param;
+    struct i965_coded_buffer_segment *coded_buffer_segment;
+
+    struct gen9_surface_avc *avc_priv_surface;
+    dri_bo *bo;
+    struct avc_surface_param surface_param;
+    int i,j = 0;
+    unsigned char * pdata;
+
+    /* Setup current reconstruct frame */
+    obj_surface = encode_state->reconstructed_object;
+    va_status = i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
+
+    if (va_status != VA_STATUS_SUCCESS)
+        return va_status;
+    memset(&surface_param,0,sizeof(surface_param));
+    surface_param.frame_width = generic_state->frame_width_in_pixel;
+    surface_param.frame_height = generic_state->frame_height_in_pixel;
+    va_status = gen9_avc_init_check_surfaces(ctx,
+                                             obj_surface,
+                                             encoder_context,
+                                             &surface_param);
+    if (va_status != VA_STATUS_SUCCESS)
+        return va_status;
+    {
+    /* init the member of avc_priv_surface,frame_store_id,qp_value*/
+       avc_priv_surface = (struct gen9_surface_avc *)obj_surface->private_data;
+       avc_state->top_field_poc[NUM_MFC_AVC_DMV_BUFFERS-2] = 0;
+       avc_state->top_field_poc[NUM_MFC_AVC_DMV_BUFFERS-1] = 0;
+       i965_free_gpe_resource(&avc_ctx->res_direct_mv_buffersr[NUM_MFC_AVC_DMV_BUFFERS-2]);
+       i965_free_gpe_resource(&avc_ctx->res_direct_mv_buffersr[NUM_MFC_AVC_DMV_BUFFERS-1]);
+       i965_dri_object_to_buffer_gpe_resource(&avc_ctx->res_direct_mv_buffersr[NUM_MFC_AVC_DMV_BUFFERS-2],avc_priv_surface->dmv_top);
+       i965_dri_object_to_buffer_gpe_resource(&avc_ctx->res_direct_mv_buffersr[NUM_MFC_AVC_DMV_BUFFERS-1],avc_priv_surface->dmv_bottom);
+       dri_bo_reference(avc_priv_surface->dmv_top);
+       dri_bo_reference(avc_priv_surface->dmv_bottom);
+       avc_priv_surface->qp_value = pic_param->pic_init_qp + slice_param->slice_qp_delta;
+       avc_priv_surface->frame_store_id = 0;
+       avc_priv_surface->frame_idx = pic_param->CurrPic.frame_idx;
+       avc_priv_surface->top_field_order_cnt = pic_param->CurrPic.TopFieldOrderCnt;
+       avc_priv_surface->is_as_ref = pic_param->pic_fields.bits.reference_pic_flag;
+       avc_state->top_field_poc[NUM_MFC_AVC_DMV_BUFFERS-2] = avc_priv_surface->top_field_order_cnt;
+       avc_state->top_field_poc[NUM_MFC_AVC_DMV_BUFFERS-1] = avc_priv_surface->top_field_order_cnt + 1;
+    }
+    i965_free_gpe_resource(&avc_ctx->res_reconstructed_surface);
+    i965_object_surface_to_2d_gpe_resource(&avc_ctx->res_reconstructed_surface, obj_surface);
+
+    /* input YUV surface*/
+    obj_surface = encode_state->input_yuv_object;
+    va_status = i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
+
+    if (va_status != VA_STATUS_SUCCESS)
+        return va_status;
+    i965_free_gpe_resource(&avc_ctx->res_uncompressed_input_surface);
+    i965_object_surface_to_2d_gpe_resource(&avc_ctx->res_uncompressed_input_surface, obj_surface);
+
+    /* Reference surfaces */
+    for (i = 0; i < ARRAY_ELEMS(avc_ctx->list_reference_res); i++) {
+        i965_free_gpe_resource(&avc_ctx->list_reference_res[i]);
+        i965_free_gpe_resource(&avc_ctx->res_direct_mv_buffersr[i*2]);
+        i965_free_gpe_resource(&avc_ctx->res_direct_mv_buffersr[i*2 + 1]);
+        obj_surface = encode_state->reference_objects[i];
+        avc_state->top_field_poc[2*i] = 0;
+        avc_state->top_field_poc[2*i+1] = 0;
+
+        if (obj_surface && obj_surface->bo) {
+            i965_object_surface_to_2d_gpe_resource(&avc_ctx->list_reference_res[i], obj_surface);
+
+            /* actually it should be handled when it is reconstructed surface*/
+            va_status = gen9_avc_init_check_surfaces(ctx,
+                obj_surface,encoder_context,
+                &surface_param);
+            if (va_status != VA_STATUS_SUCCESS)
+                return va_status;
+            avc_priv_surface = (struct gen9_surface_avc *)obj_surface->private_data;
+            i965_dri_object_to_buffer_gpe_resource(&avc_ctx->res_direct_mv_buffersr[i*2],avc_priv_surface->dmv_top);
+            i965_dri_object_to_buffer_gpe_resource(&avc_ctx->res_direct_mv_buffersr[i*2 + 1],avc_priv_surface->dmv_bottom);
+            dri_bo_reference(avc_priv_surface->dmv_top);
+            dri_bo_reference(avc_priv_surface->dmv_bottom);
+            avc_state->top_field_poc[2*i] = avc_priv_surface->top_field_order_cnt;
+            avc_state->top_field_poc[2*i+1] = avc_priv_surface->top_field_order_cnt + 1;
+            avc_priv_surface->frame_store_id = i;
+        }else
+        {
+            break;
+        }
+    }
+
+    /* Encoded bitstream ?*/
+    obj_buffer = encode_state->coded_buf_object;
+    bo = obj_buffer->buffer_store->bo;
+    i965_free_gpe_resource(&avc_ctx->compressed_bitstream.res);
+    i965_dri_object_to_buffer_gpe_resource(&avc_ctx->compressed_bitstream.res, bo);
+    avc_ctx->compressed_bitstream.start_offset = I965_CODEDBUFFER_HEADER_SIZE;
+    avc_ctx->compressed_bitstream.end_offset = ALIGN(obj_buffer->size_element - 0x1000, 0x1000);
+
+    /*status buffer */
+    dri_bo_unreference(avc_ctx->status_buffer.bo);
+    avc_ctx->status_buffer.bo = bo;
+    dri_bo_reference(bo);
+
+    /* set the internal flag to 0 to indicate the coded size is unknown */
+    dri_bo_map(bo, 1);
+    coded_buffer_segment = (struct i965_coded_buffer_segment *)bo->virtual;
+    coded_buffer_segment->mapped = 0;
+    coded_buffer_segment->codec = encoder_context->codec;
+    coded_buffer_segment->status_support = 1;
+
+    pdata = bo->virtual + avc_ctx->status_buffer.base_offset;
+    memset(pdata,0,avc_ctx->status_buffer.status_buffer_size);
+    dri_bo_unmap(bo);
+
+    //frame id, it is the ref pic id in the reference_objects list.
+    avc_state->num_refs[0] = 0;
+    avc_state->num_refs[1] = 0;
+    if (generic_state->frame_type == SLICE_TYPE_P) {
+        avc_state->num_refs[0] = pic_param->num_ref_idx_l0_active_minus1 + 1;
+
+        if (slice_param->num_ref_idx_active_override_flag)
+            avc_state->num_refs[0] = slice_param->num_ref_idx_l0_active_minus1 + 1;
+    } else if (generic_state->frame_type == SLICE_TYPE_B) {
+        avc_state->num_refs[0] = pic_param->num_ref_idx_l0_active_minus1 + 1;
+        avc_state->num_refs[1] = pic_param->num_ref_idx_l1_active_minus1 + 1;
+
+        if (slice_param->num_ref_idx_active_override_flag) {
+            avc_state->num_refs[0] = slice_param->num_ref_idx_l0_active_minus1 + 1;
+            avc_state->num_refs[1] = slice_param->num_ref_idx_l1_active_minus1 + 1;
+        }
+    }
+
+    if (avc_state->num_refs[0] > ARRAY_ELEMS(avc_state->list_ref_idx[0]))
+        return VA_STATUS_ERROR_INVALID_VALUE;
+    if (avc_state->num_refs[1] > ARRAY_ELEMS(avc_state->list_ref_idx[1]))
+        return VA_STATUS_ERROR_INVALID_VALUE;
+
+    for (i = 0; i < ARRAY_ELEMS(avc_state->list_ref_idx[0]); i++) {
+        VAPictureH264 *va_pic;
+
+        assert(ARRAY_ELEMS(slice_param->RefPicList0) == ARRAY_ELEMS(avc_state->list_ref_idx[0]));
+        avc_state->list_ref_idx[0][i] = 0;
+
+        if (i >= avc_state->num_refs[0])
+            continue;
+
+        va_pic = &slice_param->RefPicList0[i];
+
+        for (j = 0; j < ARRAY_ELEMS(encode_state->reference_objects); j++) {
+            obj_surface = encode_state->reference_objects[j];
+
+            if (obj_surface &&
+                obj_surface->bo &&
+                obj_surface->base.id == va_pic->picture_id) {
+
+                assert(obj_surface->base.id != VA_INVALID_SURFACE);
+                avc_state->list_ref_idx[0][i] = j;
+
+                break;
+            }
+        }
+    }
+    for (i = 0; i < ARRAY_ELEMS(avc_state->list_ref_idx[1]); i++) {
+        VAPictureH264 *va_pic;
+
+        assert(ARRAY_ELEMS(slice_param->RefPicList1) == ARRAY_ELEMS(avc_state->list_ref_idx[1]));
+        avc_state->list_ref_idx[1][i] = 0;
+
+        if (i >= avc_state->num_refs[1])
+            continue;
+
+        va_pic = &slice_param->RefPicList1[i];
+
+        for (j = 0; j < ARRAY_ELEMS(encode_state->reference_objects); j++) {
+            obj_surface = encode_state->reference_objects[j];
+
+            if (obj_surface &&
+                obj_surface->bo &&
+                obj_surface->base.id == va_pic->picture_id) {
+
+                assert(obj_surface->base.id != VA_INVALID_SURFACE);
+                avc_state->list_ref_idx[1][i] = j;
+
+                break;
+            }
+        }
+    }
+
+    return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+gen9_avc_vme_gpe_kernel_init(VADriverContextP ctx,
+                             struct encode_state *encode_state,
+                             struct intel_encoder_context *encoder_context)
+{
+    return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+gen9_avc_vme_gpe_kernel_final(VADriverContextP ctx,
+                              struct encode_state *encode_state,
+                              struct intel_encoder_context *encoder_context)
+{
+
+    struct encoder_vme_mfc_context * vme_context = (struct encoder_vme_mfc_context *)encoder_context->vme_context;
+    struct generic_enc_codec_state * generic_state = (struct generic_enc_codec_state * )vme_context->generic_enc_state;
+    struct avc_enc_state * avc_state = (struct avc_enc_state * )vme_context->private_enc_state;
+
+    /*set this flag when all kernel is finished*/
+    if(generic_state->brc_enabled)
+    {
+        generic_state->brc_inited = 1;
+        generic_state->brc_need_reset = 0;
+        avc_state->mbenc_curbe_set_in_brc_update = 0;
+    }
+    return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+gen9_avc_vme_gpe_kernel_run(VADriverContextP ctx,
+                            struct encode_state *encode_state,
+                            struct intel_encoder_context *encoder_context)
+{
+    struct encoder_vme_mfc_context * vme_context = (struct encoder_vme_mfc_context *)encoder_context->vme_context;
+    struct generic_enc_codec_state * generic_state = (struct generic_enc_codec_state * )vme_context->generic_enc_state;
+    struct avc_enc_state * avc_state = (struct avc_enc_state * )vme_context->private_enc_state;
+
+    VAEncPictureParameterBufferH264  *pic_param = avc_state->pic_param;
+    VAEncSliceParameterBufferH264 *slice_param = avc_state->slice_param[0];
+    int sfd_in_use = 0;
+
+    /* BRC init/reset needs to be called before HME since it will reset the Brc Distortion surface*/
+    if(generic_state->brc_enabled &&(!generic_state->brc_inited || generic_state->brc_need_reset ))
+    {
+        gen9_avc_kernel_brc_init_reset(ctx,encode_state,encoder_context);
+    }
+
+    /*down scaling*/
+    if(generic_state->hme_supported)
+    {
+        gen9_avc_kernel_scaling(ctx,encode_state,encoder_context,INTEL_ENC_HME_4x);
+        if(generic_state->b16xme_supported)
+        {
+            gen9_avc_kernel_scaling(ctx,encode_state,encoder_context,INTEL_ENC_HME_16x);
+            if(generic_state->b32xme_supported)
+            {
+                gen9_avc_kernel_scaling(ctx,encode_state,encoder_context,INTEL_ENC_HME_32x);
+            }
+        }
+    }
+
+    /*me kernel*/
+    if(generic_state->hme_enabled)
+    {
+        if(generic_state->b16xme_enabled)
+        {
+            if(generic_state->b32xme_enabled)
+            {
+                gen9_avc_kernel_me(ctx,encode_state,encoder_context,INTEL_ENC_HME_32x);
+            }
+            gen9_avc_kernel_me(ctx,encode_state,encoder_context,INTEL_ENC_HME_16x);
+        }
+        gen9_avc_kernel_me(ctx,encode_state,encoder_context,INTEL_ENC_HME_4x);
+    }
+
+    /*call SFD kernel after HME in same command buffer*/
+    sfd_in_use = avc_state->sfd_enable && generic_state->hme_enabled;
+    sfd_in_use = sfd_in_use && !avc_state->sfd_mb_enable;
+    if(sfd_in_use)
+    {
+        gen9_avc_kernel_sfd(ctx,encode_state,encoder_context);
+    }
+
+    /* BRC and MbEnc are included in the same task phase*/
+    if(generic_state->brc_enabled)
+    {
+        if(avc_state->mbenc_i_frame_dist_in_use)
+        {
+            gen9_avc_kernel_mbenc(ctx,encode_state,encoder_context,true);
+        }
+        gen9_avc_kernel_brc_frame_update(ctx,encode_state,encoder_context);
+
+        if(generic_state->mb_brc_enabled)
+        {
+            gen9_avc_kernel_brc_mb_update(ctx,encode_state,encoder_context);
+        }
+    }
+
+    /*weight prediction,disable by now */
+    avc_state->weighted_ref_l0_enable = 0;
+    avc_state->weighted_ref_l1_enable = 0;
+    if(avc_state->weighted_prediction_supported &&
+        ((generic_state->frame_type == SLICE_TYPE_P && pic_param->pic_fields.bits.weighted_pred_flag) ||
+        (generic_state->frame_type == SLICE_TYPE_B && pic_param->pic_fields.bits.weighted_bipred_idc == INTEL_AVC_WP_MODE_EXPLICIT)))
+    {
+        if(slice_param->luma_weight_l0_flag & 1)
+        {
+            gen9_avc_kernel_wp(ctx,encode_state,encoder_context,0);
+
+        }else if(!(slice_param->chroma_weight_l0_flag & 1))
+        {
+            pic_param->pic_fields.bits.weighted_pred_flag = 0;// it should be handled in app
+        }
+
+        if(generic_state->frame_type == SLICE_TYPE_B && pic_param->pic_fields.bits.weighted_bipred_idc == INTEL_AVC_WP_MODE_EXPLICIT)
+        {
+            if(slice_param->luma_weight_l1_flag & 1)
+            {
+                gen9_avc_kernel_wp(ctx,encode_state,encoder_context,1);
+            }else if(!((slice_param->luma_weight_l0_flag & 1)||
+                       (slice_param->chroma_weight_l0_flag & 1)||
+                       (slice_param->chroma_weight_l1_flag & 1)))
+            {
+                pic_param->pic_fields.bits.weighted_bipred_idc = INTEL_AVC_WP_MODE_DEFAULT;// it should be handled in app
+            }
+        }
+    }
+
+    /*mbenc kernel*/
+    gen9_avc_kernel_mbenc(ctx,encode_state,encoder_context,false);
+
+    /*ignore the reset vertical line kernel*/
+
+    return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+gen9_avc_vme_pipeline(VADriverContextP ctx,
+                      VAProfile profile,
+                      struct encode_state *encode_state,
+                      struct intel_encoder_context *encoder_context)
+{
+    VAStatus va_status;
+
+    gen9_avc_update_parameters(ctx, profile, encode_state, encoder_context);
+
+    va_status = gen9_avc_encode_check_parameter(ctx, encode_state, encoder_context);
+    if (va_status != VA_STATUS_SUCCESS)
+        return va_status;
+
+    va_status = gen9_avc_allocate_resources(ctx, encode_state, encoder_context);
+    if (va_status != VA_STATUS_SUCCESS)
+        return va_status;
+
+    va_status = gen9_avc_vme_gpe_kernel_prepare(ctx, encode_state, encoder_context);
+    if (va_status != VA_STATUS_SUCCESS)
+        return va_status;
+
+    va_status = gen9_avc_vme_gpe_kernel_init(ctx, encode_state, encoder_context);
+    if (va_status != VA_STATUS_SUCCESS)
+        return va_status;
+
+    va_status = gen9_avc_vme_gpe_kernel_run(ctx, encode_state, encoder_context);
+    if (va_status != VA_STATUS_SUCCESS)
+        return va_status;
+
+    gen9_avc_vme_gpe_kernel_final(ctx, encode_state, encoder_context);
+
+    return VA_STATUS_SUCCESS;
+}
+
+static void
+gen9_avc_vme_context_destroy(void * context)
+{
+    struct encoder_vme_mfc_context *vme_context = (struct encoder_vme_mfc_context *)context;
+    struct generic_encoder_context * generic_ctx = (struct generic_encoder_context * )vme_context->generic_enc_ctx;
+    struct gen9_avc_encoder_context * avc_ctx = (struct gen9_avc_encoder_context * )vme_context->private_enc_ctx;
+    struct generic_enc_codec_state * generic_state = (struct generic_enc_codec_state * )vme_context->generic_enc_state;
+    struct avc_enc_state * avc_state = (struct avc_enc_state * )vme_context->private_enc_state;
+
+    if (!vme_context)
+        return;
+
+    gen9_avc_kernel_destroy(vme_context);
+
+    if(generic_ctx)
+        free(generic_ctx);
+
+    if(avc_ctx)
+        free(avc_ctx);
+
+    if(generic_state)
+        free(generic_state);
+
+    if(avc_state)
+        free(avc_state);
+
+    if(vme_context)
+        free(vme_context);
+    return;
+
+}
+
+static void
+gen9_avc_kernel_init(VADriverContextP ctx,
+                     struct intel_encoder_context *encoder_context)
+{
+    struct encoder_vme_mfc_context * vme_context = (struct encoder_vme_mfc_context *)encoder_context->vme_context;
+    struct gen9_avc_encoder_context * avc_ctx = (struct gen9_avc_encoder_context * )vme_context->private_enc_ctx;
+    struct generic_encoder_context * generic_ctx = (struct generic_encoder_context * )vme_context->generic_enc_ctx;
+
+
+    gen9_avc_kernel_init_scaling(ctx,generic_ctx,&avc_ctx->context_scaling);
+    gen9_avc_kernel_init_brc(ctx,generic_ctx,&avc_ctx->context_brc);
+    gen9_avc_kernel_init_me(ctx,generic_ctx,&avc_ctx->context_me);
+    gen9_avc_kernel_init_mbenc(ctx,generic_ctx,&avc_ctx->context_mbenc);
+    gen9_avc_kernel_init_wp(ctx,generic_ctx,&avc_ctx->context_wp);
+    gen9_avc_kernel_init_sfd(ctx,generic_ctx,&avc_ctx->context_sfd);
+
+    //function pointer
+    generic_ctx->pfn_set_curbe_scaling2x = gen9_avc_set_curbe_scaling2x;
+    generic_ctx->pfn_set_curbe_scaling4x = gen9_avc_set_curbe_scaling4x;
+    generic_ctx->pfn_set_curbe_me = gen9_avc_set_curbe_me;
+    generic_ctx->pfn_set_curbe_mbenc = gen9_avc_set_curbe_mbenc;
+    generic_ctx->pfn_set_curbe_brc_init_reset = gen9_avc_set_curbe_brc_init_reset;
+    generic_ctx->pfn_set_curbe_brc_frame_update = gen9_avc_set_curbe_brc_frame_update;
+    generic_ctx->pfn_set_curbe_brc_mb_update = gen9_avc_set_curbe_brc_mb_update;
+    generic_ctx->pfn_set_curbe_sfd = gen9_avc_set_curbe_sfd;
+    generic_ctx->pfn_set_curbe_wp = gen9_avc_set_curbe_wp;
+
+    generic_ctx->pfn_send_scaling_surface = gen9_avc_send_surface_scaling;
+    generic_ctx->pfn_send_me_surface = gen9_avc_send_surface_me;
+    generic_ctx->pfn_send_mbenc_surface = gen9_avc_send_surface_mbenc;
+    generic_ctx->pfn_send_brc_init_reset_surface = gen9_avc_send_surface_brc_init_reset;
+    generic_ctx->pfn_send_brc_frame_update_surface = gen9_avc_send_surface_brc_frame_update;
+    generic_ctx->pfn_send_brc_mb_update_surface = gen9_avc_send_surface_brc_mb_update;
+    generic_ctx->pfn_send_sfd_surface = gen9_avc_send_surface_sfd;
+    generic_ctx->pfn_send_wp_surface = gen9_avc_send_surface_wp;
+}
-- 
2.11.0



More information about the Libva mailing list