diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/gen9_avc_encoder.c | 442 |
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; +} |