summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPengfei Qu <Pengfei.Qu@intel.com>2016-12-28 13:44:03 +0800
committerSean V Kelley <seanvk@posteo.de>2017-01-10 15:22:20 -0800
commitee4adf3a2ada440bbf4da4650df47f61416b7741 (patch)
treef5a4ba47285bdd5f7e99e37ab140841eb025ad00
parentf2c0e543fd0a195ab505eb6becffe7b2076faf39 (diff)
ENC: VME pipeline init/prepare/run function for AVC encoder
Signed-off-by: Pengfei Qu <Pengfei.Qu@intel.com> Reviewed-by: Sean V Kelley <seanvk@posteo.de>
-rwxr-xr-xsrc/gen9_avc_encoder.c442
1 files changed, 442 insertions, 0 deletions
diff --git a/src/gen9_avc_encoder.c b/src/gen9_avc_encoder.c
index 04cf30f..629a0da 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;
+}