[Libva] [libva-intel-driver PATCH 08/10] VP9 HWDec: add VP9 HW decoding pipeline
Zhao Yakui
yakui.zhao at intel.com
Thu Dec 3 16:38:26 PST 2015
On 12/04/2015 02:14 AM, Xiang, Haihao wrote:
> From: Pengfei Qu<Pengfei.Qu at intel.com>
>
> v2: fix sengment feature in inter frame
>
> v3: update the prob buffer logic
>
> v4: fix intra-only feature issue
>
> Signed-off-by: Pengfei Qu<Pengfei.Qu at intel.com>
> Signed-off-by: Sirisha Muppavarapu<sirisha.muppavarapu at intel.com>
> Signed-off-by: peng.chen<peng.c.chen at intel.com>
This looks good to me.
Thanks
> ---
> src/gen9_mfd.c | 944 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> src/gen9_mfd.h | 26 ++
> 2 files changed, 968 insertions(+), 2 deletions(-)
>
> diff --git a/src/gen9_mfd.c b/src/gen9_mfd.c
> index 44b343f..5bad278 100644
> --- a/src/gen9_mfd.c
> +++ b/src/gen9_mfd.c
> @@ -39,6 +39,7 @@
>
> #include "gen9_mfd.h"
> #include "intel_media.h"
> +#include "vp9_probs.h"
>
> #define OUT_BUFFER(buf_bo, is_target, ma) do { \
> if (buf_bo) { \
> @@ -205,7 +206,7 @@ gen9_hcpd_pipe_mode_select(VADriverContextP ctx,
> {
> struct intel_batchbuffer *batch = gen9_hcpd_context->base.batch;
>
> - assert(codec == HCP_CODEC_HEVC);
> + assert((codec == HCP_CODEC_HEVC) || (codec == HCP_CODEC_VP9));
>
> BEGIN_BCS_BATCH(batch, 4);
>
> @@ -970,6 +971,915 @@ out:
> return vaStatus;
> }
>
> +/*********************************************************/
> +/* VP9 Code */
> +/*********************************************************/
> +
> +
> +#define VP9_PROB_BUFFER_FIRST_PART_SIZE 2010
> +#define VP9_PROB_BUFFER_SECOND_PART_SIZE 10
> +#define VP9_PROB_BUFFER_KEY_INTER_OFFSET 1667
> +#define VP9_PROB_BUFFER_KEY_INTER_SIZE 343
> +
> +#define VP9_PROB_BUFFER_UPDATE_NO 0
> +#define VP9_PROB_BUFFER_UPDATE_SECNE_1 1
> +#define VP9_PROB_BUFFER_UPDATE_SECNE_2 2
> +#define VP9_PROB_BUFFER_UPDATE_SECNE_3 3
> +#define VP9_PROB_BUFFER_UPDATE_SECNE_4 4
> +#define VP9_PROB_BUFFER_UPDATE_SECNE_5 5
> +
> +#define VP9_PROB_BUFFER_SAVED_NO 0
> +#define VP9_PROB_BUFFER_SAVED_SECNE_1 1
> +#define VP9_PROB_BUFFER_SAVED_SECNE_2 2
> +
> +#define VP9_PROB_BUFFER_RESTORED_NO 0
> +#define VP9_PROB_BUFFER_RESTORED_SECNE_1 1
> +#define VP9_PROB_BUFFER_RESTORED_SECNE_2 2
> +#define VP9_PROB_BUFFER_RESTORED_SECNE_MAX (VP9_PROB_BUFFER_RESTORED_SECNE_2 + 1)
> +
> +static void vp9_update_segmentId_buffer(VADriverContextP ctx,
> + struct decode_state *decode_state,
> + struct gen9_hcpd_context *gen9_hcpd_context, uint8_t isScaling)
> +{
> + VADecPictureParameterBufferVP9 *pic_param;
> +
> + assert(decode_state->pic_param&& decode_state->pic_param->buffer);
> + pic_param = (VADecPictureParameterBufferVP9 *)decode_state->pic_param->buffer;
> +
> + int size = 0;
> +
> + if((pic_param->pic_fields.bits.frame_type == HCP_VP9_KEY_FRAME) ||
> + pic_param->pic_fields.bits.error_resilient_mode ||
> + pic_param->pic_fields.bits.intra_only || isScaling) {
> +
> + size = (gen9_hcpd_context->picture_width_in_min_cb_minus1+2)*(gen9_hcpd_context->picture_height_in_min_cb_minus1 + 2) * 1;
> + size<<=6;
> + //VP9 Segment ID buffer needs to be zero
> + dri_bo_map(gen9_hcpd_context->vp9_segment_id_buffer.bo,1);
> + memset((unsigned char *)gen9_hcpd_context->vp9_segment_id_buffer.bo->virtual,0, size);
> + dri_bo_unmap(gen9_hcpd_context->vp9_segment_id_buffer.bo);
> + }
> +}
> +
> +static void
> +vp9_gen_default_probabilities(VADriverContextP ctx, struct gen9_hcpd_context *gen9_hcpd_context)
> +{
> + int i = 0;
> + uint32_t size = 0;
> +
> + size = sizeof(FRAME_CONTEXT);
> + memset(&gen9_hcpd_context->vp9_fc_key_default,0,size);
> + memset(&gen9_hcpd_context->vp9_fc_inter_default,0,size);
> + memset(&gen9_hcpd_context->vp9_frame_ctx,0,size*FRAME_CONTEXTS);
> + //more code to come here below
> +
> + //1. key default
> + gen9_hcpd_context->vp9_fc_key_default.tx_probs = default_tx_probs;
> + //dummy 52
> + vp9_copy(gen9_hcpd_context->vp9_fc_key_default.coeff_probs4x4, default_coef_probs_4x4);
> + vp9_copy(gen9_hcpd_context->vp9_fc_key_default.coeff_probs8x8, default_coef_probs_8x8);
> + vp9_copy(gen9_hcpd_context->vp9_fc_key_default.coeff_probs16x16, default_coef_probs_16x16);
> + vp9_copy(gen9_hcpd_context->vp9_fc_key_default.coeff_probs32x32, default_coef_probs_32x32);
> + //dummy 16
> + vp9_copy(gen9_hcpd_context->vp9_fc_key_default.skip_probs, default_skip_probs);
> + vp9_copy(gen9_hcpd_context->vp9_fc_key_default.partition_prob, vp9_kf_partition_probs);
> + //dummy 47
> + vp9_copy(gen9_hcpd_context->vp9_fc_key_default.uv_mode_prob, vp9_kf_uv_mode_prob);
> + vp9_copy(gen9_hcpd_context->vp9_fc_key_default.seg_tree_probs, default_seg_tree_probs);
> + vp9_copy(gen9_hcpd_context->vp9_fc_key_default.seg_pred_probs, default_seg_pred_probs);
> +
> + //2. inter default
> + gen9_hcpd_context->vp9_fc_inter_default.tx_probs = default_tx_probs;
> + //dummy 52
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.coeff_probs4x4, default_coef_probs_4x4);
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.coeff_probs8x8, default_coef_probs_8x8);
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.coeff_probs16x16, default_coef_probs_16x16);
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.coeff_probs32x32, default_coef_probs_32x32);
> + //dummy 16
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.skip_probs, default_skip_probs);
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.inter_mode_probs, default_inter_mode_probs);
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.switchable_interp_prob, default_switchable_interp_prob);
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.intra_inter_prob, default_intra_inter_p);
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.comp_inter_prob, default_comp_inter_p);
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.single_ref_prob, default_single_ref_p);
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.comp_ref_prob, default_comp_ref_p);
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.y_mode_prob, default_if_y_probs);
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.partition_prob, default_partition_probs);
> + gen9_hcpd_context->vp9_fc_inter_default.nmvc = default_nmv_context;
> + //dummy 47
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.uv_mode_prob, default_if_uv_probs);
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.seg_tree_probs, default_seg_tree_probs);
> + vp9_copy(gen9_hcpd_context->vp9_fc_inter_default.seg_pred_probs, default_seg_pred_probs);
> +
> + for(i = 0; i< FRAME_CONTEXTS; i++)
> + {
> + gen9_hcpd_context->vp9_frame_ctx[i] = gen9_hcpd_context->vp9_fc_inter_default;
> + }
> + gen9_hcpd_context->vp9_fc = gen9_hcpd_context->vp9_fc_inter_default;
> +
> +}
> +
> +static void
> +vp9_update_probabilities(VADriverContextP ctx,
> + struct decode_state *decode_state,
> + struct gen9_hcpd_context *gen9_hcpd_context)
> +{
> + VADecPictureParameterBufferVP9 *pic_param;
> + int i = 0;
> + uint8_t is_saved = VP9_PROB_BUFFER_SAVED_NO;
> + uint8_t is_restored = VP9_PROB_BUFFER_RESTORED_NO;
> +
> + uint8_t last_frame_type = gen9_hcpd_context->last_frame.frame_type;
> + uint8_t temp_frame_ctx_id;
> +
> + assert(decode_state->pic_param&& decode_state->pic_param->buffer);
> + pic_param = (VADecPictureParameterBufferVP9 *)decode_state->pic_param->buffer;
> + temp_frame_ctx_id = pic_param->pic_fields.bits.frame_context_idx;
> +
> + if(pic_param->pic_fields.bits.frame_type == HCP_VP9_KEY_FRAME)
> + {
> + gen9_hcpd_context->vp9_fc = gen9_hcpd_context->vp9_fc_key_default;
> + gen9_hcpd_context->last_frame.prob_buffer_saved_flag = VP9_PROB_BUFFER_SAVED_NO;
> + gen9_hcpd_context->last_frame.prob_buffer_restored_flag = VP9_PROB_BUFFER_RESTORED_NO;
> +
> + }else
> + {
> + gen9_hcpd_context->vp9_fc = gen9_hcpd_context->vp9_fc_inter_default;
> + }
> +
> + // restore?
> + if(gen9_hcpd_context->last_frame.prob_buffer_saved_flag == VP9_PROB_BUFFER_SAVED_SECNE_1)
> + {
> + if((pic_param->pic_fields.bits.frame_type == HCP_VP9_INTER_FRAME))
> + {
> + //save the inter frame values for the 343 bytes
> + //Update the 343 bytes of the buffer with Intra values
> + is_restored = VP9_PROB_BUFFER_RESTORED_SECNE_1;
> + }
> + }else if(gen9_hcpd_context->last_frame.prob_buffer_saved_flag == VP9_PROB_BUFFER_SAVED_SECNE_2)
> + {
> + if((pic_param->pic_fields.bits.frame_type == HCP_VP9_KEY_FRAME) ||pic_param->pic_fields.bits.intra_only|pic_param->pic_fields.bits.error_resilient_mode)
> + {
> + temp_frame_ctx_id = 0;
> + }
> +
> + if((pic_param->pic_fields.bits.frame_type == HCP_VP9_INTER_FRAME)&&
> + (temp_frame_ctx_id == 0))
> + {
> +
> + is_restored = VP9_PROB_BUFFER_RESTORED_SECNE_2;
> + }
> + }
> +
> + if(is_restored> VP9_PROB_BUFFER_RESTORED_NO&& is_restored< VP9_PROB_BUFFER_RESTORED_SECNE_MAX)
> + {
> + memcpy(gen9_hcpd_context->vp9_frame_ctx[gen9_hcpd_context->last_frame.frame_context_idx].inter_mode_probs,gen9_hcpd_context->vp9_saved_fc.inter_mode_probs,VP9_PROB_BUFFER_KEY_INTER_SIZE);
> + }
> +
> + if((gen9_hcpd_context->last_frame.prob_buffer_restored_flag == VP9_PROB_BUFFER_RESTORED_SECNE_MAX) ||
> + (gen9_hcpd_context->last_frame.refresh_frame_context&& last_frame_type == HCP_VP9_KEY_FRAME&& (pic_param->pic_fields.bits.frame_type == HCP_VP9_INTER_FRAME)))
> + {
> + if(pic_param->pic_fields.bits.frame_type == HCP_VP9_INTER_FRAME)
> + {
> + memcpy(gen9_hcpd_context->vp9_frame_ctx[gen9_hcpd_context->last_frame.frame_context_idx].inter_mode_probs,gen9_hcpd_context->vp9_fc_inter_default.inter_mode_probs,VP9_PROB_BUFFER_KEY_INTER_SIZE);
> + }
> + }
> + //first part buffer update: Case 1)Reset all 4 probablity buffers
> + if((pic_param->pic_fields.bits.frame_type == HCP_VP9_KEY_FRAME) ||pic_param->pic_fields.bits.intra_only|pic_param->pic_fields.bits.error_resilient_mode)
> + {
> + if((pic_param->pic_fields.bits.frame_type == HCP_VP9_KEY_FRAME) ||
> + (pic_param->pic_fields.bits.reset_frame_context == 3)||
> + pic_param->pic_fields.bits.error_resilient_mode)
> + {
> + //perform full buffer update
> + for(i = 0; i< FRAME_CONTEXTS; i++)
> + {
> + memcpy(&gen9_hcpd_context->vp9_frame_ctx[i],&gen9_hcpd_context->vp9_fc_inter_default,VP9_PROB_BUFFER_FIRST_PART_SIZE);
> + }
> + }else if(pic_param->pic_fields.bits.reset_frame_context == 2&&pic_param->pic_fields.bits.intra_only)
> + {
> + memcpy(&gen9_hcpd_context->vp9_frame_ctx[pic_param->pic_fields.bits.frame_context_idx],&gen9_hcpd_context->vp9_fc_inter_default,VP9_PROB_BUFFER_FIRST_PART_SIZE);
> + }
> + pic_param->pic_fields.bits.frame_context_idx = 0;
> + }
> +
> + //Full buffer update: Case 2.2)Reset only segmentation prob buffer
> + if(pic_param->pic_fields.bits.segmentation_enabled&&
> + pic_param->pic_fields.bits.segmentation_update_map)
> + {
> + for(i = 0; i< FRAME_CONTEXTS; i++)
> + {
> + //Reset only the segementation probability buffers
> + vp9_copy(gen9_hcpd_context->vp9_frame_ctx[i].seg_tree_probs, default_seg_tree_probs);
> + vp9_copy(gen9_hcpd_context->vp9_frame_ctx[i].seg_pred_probs, default_seg_pred_probs);
> + }
> + }
> +
> + //update vp9_fc according to frame_context_id
> + {
> + gen9_hcpd_context->vp9_fc = gen9_hcpd_context->vp9_frame_ctx[pic_param->pic_fields.bits.frame_context_idx];
> + }
> + //Partial Buffer Update
> + //Case 1) Update top 3 probabilities only
> + if(pic_param->pic_fields.bits.frame_type == HCP_VP9_KEY_FRAME)
> + {
> + memcpy(gen9_hcpd_context->vp9_fc.inter_mode_probs,gen9_hcpd_context->vp9_fc_key_default.inter_mode_probs,VP9_PROB_BUFFER_KEY_INTER_SIZE);
> + if((!pic_param->pic_fields.bits.segmentation_enabled ||
> + !pic_param->pic_fields.bits.segmentation_update_map)) {
> + //Update with key frame default probability values for only
> + //tx_probs, coef_probs, and the next 343 bytes
> + memcpy(&gen9_hcpd_context->vp9_fc,&gen9_hcpd_context->vp9_fc_key_default,VP9_PROB_BUFFER_FIRST_PART_SIZE);
> + }
> + }
> + //Case 2) Update 343 bytes for first inter following key frame
> + if( last_frame_type == HCP_VP9_KEY_FRAME&&
> + (pic_param->pic_fields.bits.frame_type == HCP_VP9_INTER_FRAME)) {
> + //Update with inter frame default values for the 343 bytes
> + memcpy(gen9_hcpd_context->vp9_fc.inter_mode_probs,gen9_hcpd_context->vp9_fc_inter_default.inter_mode_probs,VP9_PROB_BUFFER_KEY_INTER_SIZE);
> + }
> + //Case 2.1) Update 343 bytes for first intra-inly frame following key frame
> + if( last_frame_type == HCP_VP9_KEY_FRAME&&
> + pic_param->pic_fields.bits.intra_only) {
> + //Update with inter frame default values for the 343 bytes
> + memcpy(gen9_hcpd_context->vp9_fc.inter_mode_probs,gen9_hcpd_context->vp9_fc_key_default.inter_mode_probs,VP9_PROB_BUFFER_KEY_INTER_SIZE);
> + }
> + //Case 3) Update only segment probabilities
> + if((pic_param->pic_fields.bits.segmentation_enabled&&
> + pic_param->pic_fields.bits.segmentation_update_map))
> + {
> + //Update seg_tree_probs and seg_pred_probs accordingly
> + for (i=0; i<SEG_TREE_PROBS; i++)
> + {
> + gen9_hcpd_context->vp9_fc.seg_tree_probs[i] = pic_param->mb_segment_tree_probs[i];
> + }
> + for (i=0; i<PREDICTION_PROBS; i++)
> + {
> + gen9_hcpd_context->vp9_fc.seg_pred_probs[i] = pic_param->segment_pred_probs[i];
> + }
> + }
> +
> + //Case 4) Considering Intra only frame in the middle of Inter frames
> + if((pic_param->pic_fields.bits.intra_only&&
> + (pic_param->pic_fields.bits.frame_type == HCP_VP9_INTER_FRAME)&&
> + (pic_param->pic_fields.bits.reset_frame_context==0 ||
> + pic_param->pic_fields.bits.reset_frame_context==1||
> + pic_param->pic_fields.bits.reset_frame_context==2||
> + pic_param->pic_fields.bits.reset_frame_context==3))&&
> + (last_frame_type == HCP_VP9_INTER_FRAME))
> + {
> + //save the inter frame values for the 343 bytes
> + //Update the 343 bytes of the buffer with Intra values
> + is_saved = VP9_PROB_BUFFER_SAVED_SECNE_1;
> + }
> + //Case 5) Considering Intra only frame among 3 Inter frames
> + if((pic_param->pic_fields.bits.intra_only&&
> + (pic_param->pic_fields.bits.frame_type == HCP_VP9_INTER_FRAME)&&
> + (pic_param->pic_fields.bits.reset_frame_context==2 ||
> + pic_param->pic_fields.bits.frame_context_idx==1))&&
> + ((last_frame_type == HCP_VP9_INTER_FRAME)&&
> + (gen9_hcpd_context->last_frame.frame_context_idx==0)))
> + {
> + //save the inter frame values for the 343 bytes
> + //Update the 343 bytes of the buffer with Intra values
> + is_saved = VP9_PROB_BUFFER_SAVED_SECNE_2;
> + }
> +
> + if(is_saved> VP9_PROB_BUFFER_SAVED_NO)
> + {
> + gen9_hcpd_context->vp9_saved_fc = gen9_hcpd_context->vp9_fc;
> + memcpy(gen9_hcpd_context->vp9_fc.inter_mode_probs,gen9_hcpd_context->vp9_fc_key_default.inter_mode_probs,VP9_PROB_BUFFER_KEY_INTER_SIZE);
> + }else if(pic_param->pic_fields.bits.intra_only)
> + {
> + is_restored = VP9_PROB_BUFFER_RESTORED_SECNE_MAX;
> +
> + }
> +
> + // update after the restored
> + if(gen9_hcpd_context->last_frame.prob_buffer_restored_flag == VP9_PROB_BUFFER_RESTORED_SECNE_2)
> + {
> + if((pic_param->pic_fields.bits.frame_type == HCP_VP9_INTER_FRAME)&&
> + pic_param->pic_fields.bits.frame_context_idx==1)
> + {
> + memcpy(&gen9_hcpd_context->vp9_fc,&gen9_hcpd_context->vp9_fc_inter_default,VP9_PROB_BUFFER_FIRST_PART_SIZE);
> + }
> + }
> +
> + {
> + dri_bo_map(gen9_hcpd_context->vp9_probability_buffer.bo,1);
> + memcpy((unsigned char *)gen9_hcpd_context->vp9_probability_buffer.bo->virtual,&gen9_hcpd_context->vp9_fc,2048);
> + dri_bo_unmap(gen9_hcpd_context->vp9_probability_buffer.bo);
> + }
> + // save the flag in order to restore or update prob buffer
> + gen9_hcpd_context->last_frame.prob_buffer_saved_flag = is_saved;
> + gen9_hcpd_context->last_frame.prob_buffer_restored_flag = is_restored;
> +}
> +
> +static void
> +gen9_hcpd_init_vp9_surface(VADriverContextP ctx,
> + VADecPictureParameterBufferVP9 *pic_param,
> + struct object_surface *obj_surface,
> + struct gen9_hcpd_context *gen9_hcpd_context)
> +{
> + struct i965_driver_data *i965 = i965_driver_data(ctx);
> + GenVP9Surface *gen9_vp9_surface;
> + uint32_t size=0;
> +
> + if (!obj_surface)
> + return;
> +
> + obj_surface->free_private_data = gen_free_vp9_surface;
> + gen9_vp9_surface = obj_surface->private_data;
> +
> + if (!gen9_vp9_surface) {
> + gen9_vp9_surface = calloc(sizeof(GenVP9Surface), 1);
> + gen9_vp9_surface->base.frame_store_id = -1;
> + obj_surface->private_data = gen9_vp9_surface;
> + }
> +
> + //Super block size in VP9 is 64x64, size in SBs
> + size = gen9_hcpd_context->picture_width_in_ctbs * gen9_hcpd_context->picture_height_in_ctbs * 9 ;
> + size<<=6; //CL aligned
> +
> + if (gen9_vp9_surface->motion_vector_temporal_bo == NULL) {
> + gen9_vp9_surface->motion_vector_temporal_bo = dri_bo_alloc(i965->intel.bufmgr,
> + "current motion vector temporal buffer",
> + size,
> + 0x1000);
> + }
> + gen9_vp9_surface->frame_width = pic_param->frame_width;
> + gen9_vp9_surface->frame_height = pic_param->frame_height;
> +
> +}
> +
> +static VAStatus
> +gen9_hcpd_vp9_decode_init(VADriverContextP ctx,
> + struct decode_state *decode_state,
> + struct gen9_hcpd_context *gen9_hcpd_context)
> +{
> + struct i965_driver_data *i965 = i965_driver_data(ctx);
> + VADecPictureParameterBufferVP9 *pic_param;
> + struct object_surface *obj_surface;
> + uint32_t size;
> + int width_in_mbs=0, height_in_mbs=0;
> +
> + assert(decode_state->pic_param&& decode_state->pic_param->buffer);
> + pic_param = (VADecPictureParameterBufferVP9 *)decode_state->pic_param->buffer;
> +
> + width_in_mbs = (pic_param->frame_width + 15) / 16;
> + height_in_mbs = (pic_param->frame_height + 15) / 16;
> +
> + //For BXT, we support only till 4K
> + assert(width_in_mbs> 0&& width_in_mbs<= 256); /* 4K */
> + assert(height_in_mbs> 0&& height_in_mbs<= 256);
> +
> + //Update the frame store buffers with the reference frames information
> + intel_update_vp9_frame_store_index(ctx,
> + decode_state,
> + pic_param,
> + gen9_hcpd_context->reference_surfaces);
> +
> + /* Current decoded picture */
> + obj_surface = decode_state->render_object;
> + //Ensure there is a tiled render surface in NV12 format. If not, create one.
> + vp9_ensure_surface_bo(ctx, decode_state, obj_surface, pic_param);
> +
> +
> + //Super block in VP9 is 64x64
> + gen9_hcpd_context->ctb_size = 64;
> + gen9_hcpd_context->min_cb_size = 8; //Min block size is 4 or 8?
> +
> + //If picture width/height is not multiple of 64, needs to upsize it to the next 64 pixels
> + //before calculation below.
> + gen9_hcpd_context->picture_width_in_ctbs = ALIGN(pic_param->frame_width, gen9_hcpd_context->ctb_size) / gen9_hcpd_context->ctb_size;
> + gen9_hcpd_context->picture_height_in_ctbs = ALIGN(pic_param->frame_height, gen9_hcpd_context->ctb_size) / gen9_hcpd_context->ctb_size;
> +
> + gen9_hcpd_context->picture_width_in_min_cb_minus1 = ALIGN(pic_param->frame_width, gen9_hcpd_context->min_cb_size) / gen9_hcpd_context->min_cb_size - 1;
> + gen9_hcpd_context->picture_height_in_min_cb_minus1 = ALIGN(pic_param->frame_height, gen9_hcpd_context->min_cb_size) / gen9_hcpd_context->min_cb_size - 1;
> +
> + gen9_hcpd_context->picture_width_in_pixels = (gen9_hcpd_context->picture_width_in_min_cb_minus1 + 1) * gen9_hcpd_context->min_cb_size ;
> + gen9_hcpd_context->picture_height_in_pixels = (gen9_hcpd_context->picture_height_in_min_cb_minus1 + 1) * gen9_hcpd_context->min_cb_size ;
> +
> + gen9_hcpd_init_vp9_surface(ctx, pic_param, obj_surface, gen9_hcpd_context);
> +
> + size = gen9_hcpd_context->picture_width_in_ctbs*18; //num_width_in_SB * 18
> + size<<=6;
> + ALLOC_GEN_BUFFER((&gen9_hcpd_context->deblocking_filter_line_buffer), "line buffer", size);
> + ALLOC_GEN_BUFFER((&gen9_hcpd_context->deblocking_filter_tile_line_buffer), "tile line buffer", size);
> +
> + size = gen9_hcpd_context->picture_height_in_ctbs*17; //num_height_in_SB * 17
> + size<<=6;
> + ALLOC_GEN_BUFFER((&gen9_hcpd_context->deblocking_filter_tile_column_buffer), "tile column buffer", size);
> +
> + size = gen9_hcpd_context->picture_width_in_ctbs*5; //num_width_in_SB * 5
> + size<<=6;
> + ALLOC_GEN_BUFFER((&gen9_hcpd_context->metadata_line_buffer), "metadata line buffer", size);
> + ALLOC_GEN_BUFFER((&gen9_hcpd_context->metadata_tile_line_buffer), "metadata tile line buffer", size);
> +
> + size = gen9_hcpd_context->picture_height_in_ctbs*5; //num_height_in_SB * 5
> + size<<=6;
> + ALLOC_GEN_BUFFER((&gen9_hcpd_context->metadata_tile_column_buffer), "metadata tile column buffer", size);
> +
> + size =gen9_hcpd_context->picture_width_in_ctbs*1; //num_width_in_SB * 1
> + size<<=6;
> + ALLOC_GEN_BUFFER((&gen9_hcpd_context->hvd_line_rowstore_buffer), "hvd line rowstore buffer", size);
> + ALLOC_GEN_BUFFER((&gen9_hcpd_context->hvd_tile_rowstore_buffer), "hvd tile rowstore buffer", size);
> +
> + size = 32;
> + size<<=6;
> + ALLOC_GEN_BUFFER((&gen9_hcpd_context->vp9_probability_buffer), "vp9 probability buffer", size);
> +
> + size = (gen9_hcpd_context->picture_width_in_min_cb_minus1+2)*(gen9_hcpd_context->picture_height_in_min_cb_minus1 + 2) * 1;
> + size<<=6;
> + ALLOC_GEN_BUFFER((&gen9_hcpd_context->vp9_segment_id_buffer), "vp9 segment id buffer", size);
> +
> + gen9_hcpd_context->first_inter_slice_collocated_ref_idx = 0;
> + gen9_hcpd_context->first_inter_slice_collocated_from_l0_flag = 0;
> + gen9_hcpd_context->first_inter_slice_valid = 0;
> +
> + return VA_STATUS_SUCCESS;
> +}
> +
> +static void
> +gen9_hcpd_vp9_surface_state(VADriverContextP ctx,
> + struct decode_state *decode_state,
> + struct gen9_hcpd_context *gen9_hcpd_context)
> +{
> + struct intel_batchbuffer *batch = gen9_hcpd_context->base.batch;
> + struct object_surface *obj_surface = decode_state->render_object;
> + struct object_surface *tmp_obj_surface = NULL;
> + unsigned int y_cb_offset;
> + int i = 0;
> +
> + assert(obj_surface);
> +
> + y_cb_offset = obj_surface->y_cb_offset;
> +
> + BEGIN_BCS_BATCH(batch, 3);
> +
> + OUT_BCS_BATCH(batch, HCP_SURFACE_STATE | (3 - 2));
> + OUT_BCS_BATCH(batch,
> + (0<< 28) | /* surface id */
> + (obj_surface->width - 1)); /* pitch - 1 */
> + OUT_BCS_BATCH(batch,
> + (SURFACE_FORMAT_PLANAR_420_8<< 28) |
> + y_cb_offset);
> + ADVANCE_BCS_BATCH(batch);
> +
> + tmp_obj_surface = obj_surface;
> +
> + for(i = 0; i< 3; i++)
> + {
> + obj_surface = gen9_hcpd_context->reference_surfaces[i].obj_surface;
> + if (obj_surface&& obj_surface->private_data)
> + {
> + BEGIN_BCS_BATCH(batch, 3);
> +
> + OUT_BCS_BATCH(batch, HCP_SURFACE_STATE | (3 - 2));
> + OUT_BCS_BATCH(batch,
> + ((i + 2)<< 28) | /* surface id */
> + (obj_surface->width - 1)); /* pitch - 1 */
> + OUT_BCS_BATCH(batch,
> + (SURFACE_FORMAT_PLANAR_420_8<< 28) |
> + obj_surface->y_cb_offset);
> + ADVANCE_BCS_BATCH(batch);
> + }else
> + {
> + BEGIN_BCS_BATCH(batch, 3);
> +
> + OUT_BCS_BATCH(batch, HCP_SURFACE_STATE | (3 - 2));
> + OUT_BCS_BATCH(batch,
> + ((i + 2)<< 28) | /* surface id */
> + (tmp_obj_surface->width - 1)); /* pitch - 1 */
> + OUT_BCS_BATCH(batch,
> + (SURFACE_FORMAT_PLANAR_420_8<< 28) |
> + tmp_obj_surface->y_cb_offset);
> + ADVANCE_BCS_BATCH(batch);
> + }
> + }
> +}
> +
> +static void
> +gen9_hcpd_vp9_pipe_buf_addr_state(VADriverContextP ctx,
> + struct decode_state *decode_state,
> + struct gen9_hcpd_context *gen9_hcpd_context)
> +{
> + struct intel_batchbuffer *batch = gen9_hcpd_context->base.batch;
> + struct object_surface *obj_surface;
> + GenVP9Surface *gen9_vp9_surface;
> + int i=0;
> +
> + BEGIN_BCS_BATCH(batch, 95);
> +
> + OUT_BCS_BATCH(batch, HCP_PIPE_BUF_ADDR_STATE | (95 - 2));
> +
> + obj_surface = decode_state->render_object;
> + assert(obj_surface&& obj_surface->bo);
> + gen9_vp9_surface = obj_surface->private_data;
> + assert(gen9_vp9_surface&& gen9_vp9_surface->motion_vector_temporal_bo);
> +
> + OUT_BUFFER_MA_TARGET(obj_surface->bo); /* DW 1..3 */
> + OUT_BUFFER_MA_TARGET(gen9_hcpd_context->deblocking_filter_line_buffer.bo);/* DW 4..6 */
> + OUT_BUFFER_MA_TARGET(gen9_hcpd_context->deblocking_filter_tile_line_buffer.bo); /* DW 7..9 */
> + OUT_BUFFER_MA_TARGET(gen9_hcpd_context->deblocking_filter_tile_column_buffer.bo); /* DW 10..12 */
> + OUT_BUFFER_MA_TARGET(gen9_hcpd_context->metadata_line_buffer.bo); /* DW 13..15 */
> + OUT_BUFFER_MA_TARGET(gen9_hcpd_context->metadata_tile_line_buffer.bo); /* DW 16..18 */
> + OUT_BUFFER_MA_TARGET(gen9_hcpd_context->metadata_tile_column_buffer.bo); /* DW 19..21 */
> + OUT_BUFFER_MA_TARGET(NULL); /* DW 22..24, ignore for VP9 */
> + OUT_BUFFER_MA_TARGET(NULL); /* DW 25..27, ignore for VP9 */
> + OUT_BUFFER_MA_TARGET(NULL); /* DW 28..30, ignore for VP9 */
> + OUT_BUFFER_MA_TARGET(gen9_vp9_surface->motion_vector_temporal_bo); /* DW 31..33 */
> +
> + OUT_BUFFER_MA_TARGET(NULL); /* DW 34..36, reserved */
> +
> + /* DW 37..52 - Reference picture address */
> + for (i = 0; i< 3; i++)
> + {
> + obj_surface = gen9_hcpd_context->reference_surfaces[i].obj_surface;
> +
> + if (obj_surface)
> + {
> + OUT_BUFFER_NMA_REFERENCE(obj_surface->bo);
> + }
> + else
> + OUT_BUFFER_NMA_REFERENCE(NULL);
> + }
> + for (; i< ARRAY_ELEMS(gen9_hcpd_context->reference_surfaces); i++)
> + {
> + OUT_BUFFER_NMA_REFERENCE(NULL);
> + }
> + OUT_BCS_BATCH(batch, 0); /* DW 53, memory address attributes */
> +
> + OUT_BUFFER_MA_REFERENCE(NULL); /* DW 54..56, ignore for decoding mode */
> + OUT_BUFFER_MA_TARGET(NULL); /* DW 57..59, StreamOutEnable - used for transcoding */
> + OUT_BUFFER_MA_TARGET(NULL); /* DW 60..62, DecodedPictureStatusError, ignored */
> + OUT_BUFFER_MA_TARGET(NULL); /* DW 63..65, Ignored */
> +
> + /* DW 66..81 - for 8 Collocated motion vectors */
> + for (i = 0; i< 1; i++)
> + {
> + OUT_BUFFER_NMA_REFERENCE(gen9_hcpd_context->last_frame.mv_temporal_buffer_bo);
> + }
> + for (; i< ARRAY_ELEMS(gen9_hcpd_context->reference_surfaces); i++)
> + {
> + OUT_BUFFER_NMA_REFERENCE(NULL);
> + }
> +
> + OUT_BCS_BATCH(batch, 0); /* DW 82, memory address attributes */
> +
> + OUT_BUFFER_MA_TARGET(gen9_hcpd_context->vp9_probability_buffer.bo); /* DW 83..85, VP9 Probability bufffer */
> + OUT_BUFFER_MA_TARGET(gen9_hcpd_context->vp9_segment_id_buffer.bo); /* DW 86..88, VP9 Segment ID buffer */
> + OUT_BUFFER_MA_TARGET(gen9_hcpd_context->hvd_line_rowstore_buffer.bo);/* DW 89..91, VP9 HVD Line Rowstore buffer */
> + OUT_BUFFER_MA_TARGET(gen9_hcpd_context->hvd_tile_rowstore_buffer.bo);/* DW 92..94, VP9 HVD Tile Rowstore buffer */
> +
> + ADVANCE_BCS_BATCH(batch);
> + gen9_hcpd_context->last_frame.mv_temporal_buffer_bo = gen9_vp9_surface->motion_vector_temporal_bo;
> +}
> +
> +static inline int
> +gen9_hcpd_vp9_valid_ref_frame_size(int ref_width, int ref_height,
> + int cur_width, int cur_height) {
> + return 2 * cur_width>= ref_width&&
> + 2 * cur_height>= ref_height&&
> + cur_width<= 16 * ref_width&&
> + cur_height<= 16 * ref_height;
> +}
> +static void
> +gen9_hcpd_vp9_pic_state(VADriverContextP ctx,
> + struct decode_state *decode_state,
> + struct gen9_hcpd_context *gen9_hcpd_context)
> +{
> + struct intel_batchbuffer *batch = gen9_hcpd_context->base.batch;
> + VADecPictureParameterBufferVP9 *pic_param;
> + struct object_surface *obj_surface;
> + GenVP9Surface *gen9_vp9_surface;
> + uint16_t scale_h = 0;
> + uint16_t scale_w = 0;
> + uint16_t frame_width_in_pixel = 0;
> + uint16_t frame_height_in_pixel = 0;
> + uint16_t fwidth = 64;
> + uint16_t fheight = 64;
> + int i;
> +#define LEN_COMMAND_OWN 12
> + assert(decode_state->pic_param&& decode_state->pic_param->buffer);
> + pic_param = (VADecPictureParameterBufferVP9 *)decode_state->pic_param->buffer;
> +
> + uint8_t segmentIDStreamInEnable = 0;
> + uint8_t segmentIDStreamOutEnable = (pic_param->pic_fields.bits.segmentation_enabled&& pic_param->pic_fields.bits.segmentation_update_map);
> +
> + // For KEY_FRAME or INTRA_ONLY frame, this bit should be set to "0".
> + uint8_t segmentation_temporal_update =
> + ((pic_param->pic_fields.bits.frame_type == HCP_VP9_KEY_FRAME) || (pic_param->pic_fields.bits.intra_only)) ? 0 : pic_param->pic_fields.bits.segmentation_temporal_update;
> +
> +
> + if(pic_param->pic_fields.bits.intra_only || (pic_param->pic_fields.bits.frame_type == HCP_VP9_KEY_FRAME))
> + {
> + segmentIDStreamInEnable = 1;
> + }else if(pic_param->pic_fields.bits.segmentation_enabled)
> + {
> + if(!pic_param->pic_fields.bits.segmentation_update_map)
> + {
> + segmentIDStreamInEnable = 1;
> +
> + }else if( pic_param->pic_fields.bits.segmentation_temporal_update)
> + {
> + segmentIDStreamInEnable = 1;
> + }
> + }
> +
> + if(pic_param->pic_fields.bits.error_resilient_mode)
> + {
> + segmentIDStreamInEnable = 1;
> + }
> +
> + //frame type of previous frame (Key or Non-Key Frame).
> + uint8_t last_frame_type = gen9_hcpd_context->last_frame.frame_type;
> +
> + uint8_t use_pre_frame_mvs = 0;
> + use_pre_frame_mvs = !((pic_param->pic_fields.bits.error_resilient_mode) ||
> + (pic_param->frame_width != gen9_hcpd_context->last_frame.frame_width) ||
> + (pic_param->frame_height != gen9_hcpd_context->last_frame.frame_height) ||
> + (pic_param->pic_fields.bits.intra_only) ||
> + (pic_param->pic_fields.bits.frame_type == HCP_VP9_KEY_FRAME)||
> + (gen9_hcpd_context->last_frame.intra_only)||
> + (last_frame_type == HCP_VP9_KEY_FRAME) ||
> + (!gen9_hcpd_context->last_frame.show_frame));
> +
> + uint8_t adapt_probabilities_flag = 0;
> + if((pic_param->pic_fields.bits.error_resilient_mode || pic_param->pic_fields.bits.frame_parallel_decoding_mode))
> + adapt_probabilities_flag = 0; //0: Do not adapt (error resilient or frame_parallel_mode are set)
> + else if(!(pic_param->pic_fields.bits.error_resilient_mode)&& !(pic_param->pic_fields.bits.frame_parallel_decoding_mode))
> + adapt_probabilities_flag = 1; //1: Adapt (not error resilient and not frame_ parallel_mode)
> +
> + frame_width_in_pixel = (gen9_hcpd_context->picture_width_in_min_cb_minus1 + 1) * gen9_hcpd_context->min_cb_size ;
> + frame_height_in_pixel = (gen9_hcpd_context->picture_height_in_min_cb_minus1 + 1) * gen9_hcpd_context->min_cb_size ;
> +
> + fwidth = (fwidth> frame_width_in_pixel)?frame_width_in_pixel:fwidth;
> + fheight = (fheight> frame_height_in_pixel)?frame_height_in_pixel:fheight;
> +
> + BEGIN_BCS_BATCH(batch, LEN_COMMAND_OWN);
> +
> + OUT_BCS_BATCH(batch, HCP_VP9_PIC_STATE | (LEN_COMMAND_OWN - 2));
> +
> + OUT_BCS_BATCH(batch,
> + (frame_height_in_pixel - 1)<< 16 |
> + (frame_width_in_pixel - 1)); /* DW 1 */
> + OUT_BCS_BATCH(batch,
> + segmentIDStreamInEnable<< 31 |
> + segmentIDStreamOutEnable<< 30 |
> + pic_param->pic_fields.bits.lossless_flag<< 29 |
> + segmentation_temporal_update<< 28 |
> + pic_param->pic_fields.bits.segmentation_update_map<< 27 |
> + pic_param->pic_fields.bits.segmentation_enabled<< 26 |
> + pic_param->sharpness_level<< 23 |
> + pic_param->filter_level<< 17 |
> + pic_param->pic_fields.bits.frame_parallel_decoding_mode<< 16 |
> + pic_param->pic_fields.bits.error_resilient_mode<< 15 |
> + pic_param->pic_fields.bits.refresh_frame_context<< 14 |
> + last_frame_type<< 13 |
> + 0<< 12 | /* tx select mode */
> + 0<< 11 | /* Hybrid Prediction Mode */
> + use_pre_frame_mvs<< 10 |
> + pic_param->pic_fields.bits.alt_ref_frame_sign_bias<< 9 |
> + pic_param->pic_fields.bits.golden_ref_frame_sign_bias<< 8 |
> + pic_param->pic_fields.bits.last_ref_frame_sign_bias<< 7 |
> + pic_param->pic_fields.bits.mcomp_filter_type<< 4 |
> + pic_param->pic_fields.bits.allow_high_precision_mv<< 3 |
> + pic_param->pic_fields.bits.intra_only<<2 |
> + adapt_probabilities_flag<< 1 |
> + pic_param->pic_fields.bits.frame_type<<0); /* DW 2 */
> + OUT_BCS_BATCH(batch,
> + HCP_VP9_PROFILE0<< 28 | /* Profile 0 only supports 8 bit 420 only */
> + pic_param->log2_tile_rows<< 8 |
> + pic_param->log2_tile_columns<<0); /* DW 3 */
> + // resolution change case
> +
> + // DW4-DW6
> + for(i = 0; i< 3; i++)
> + {
> + obj_surface = gen9_hcpd_context->reference_surfaces[i].obj_surface;
> + gen9_vp9_surface = NULL;
> + scale_w = 0;
> + scale_h = 0;
> + if (obj_surface&& obj_surface->private_data)
> + {
> + gen9_vp9_surface = obj_surface->private_data;
> + if(!gen9_hcpd_vp9_valid_ref_frame_size(gen9_vp9_surface->frame_width,gen9_vp9_surface->frame_height,pic_param->frame_width,pic_param->frame_height))
> + {
> + scale_w = -1;
> + scale_h = -1;
> + }else
> + {
> + scale_w = (gen9_vp9_surface->frame_width<< 14) /pic_param->frame_width ;
> + scale_h = (gen9_vp9_surface->frame_height<< 14) /pic_param->frame_height ;
> + }
> + OUT_BCS_BATCH(batch,
> + scale_w<<16 |
> + scale_h);
> + }else
> + {
> + OUT_BCS_BATCH(batch, 0);
> + }
> + }
> +
> + // DW7-DW9
> + for(i = 0; i< 3; i++)
> + {
> + obj_surface = gen9_hcpd_context->reference_surfaces[i].obj_surface;
> + gen9_vp9_surface = NULL;
> +
> + if (obj_surface&& obj_surface->private_data)
> + {
> + gen9_vp9_surface = obj_surface->private_data;
> + OUT_BCS_BATCH(batch,
> + ((gen9_vp9_surface->frame_height- 1)&0x3fff)<<16 |
> + ((gen9_vp9_surface->frame_width - 1)&0x3fff));
> + }else
> + {
> + OUT_BCS_BATCH(batch, 0);
> + }
> + }
> +
> + OUT_BCS_BATCH(batch,
> + pic_param->first_partition_size<< 16 |
> + pic_param->frame_header_length_in_bytes<<0); /* DW 10 */
> + OUT_BCS_BATCH(batch,
> + (0<< 3) |
> + (0<< 2) |
> + (1<< 1) |
> + (0<< 0)); /* DW 11, ignored */
> + //Rest of the DWs are not valid for BXT
> + for(i = 12; i< LEN_COMMAND_OWN; i++)
> + {
> + OUT_BCS_BATCH(batch, 0);
> + }
> +
> + ADVANCE_BCS_BATCH(batch);
> +
> +}
> +
> +static void
> +gen9_hcpd_vp9_segment_state(VADriverContextP ctx,
> + VADecPictureParameterBufferVP9 *pic_param,
> + VASegmentParameterVP9 *seg_param, uint8_t seg_id,
> + struct gen9_hcpd_context *gen9_hcpd_context)
> +{
> + struct intel_batchbuffer *batch = gen9_hcpd_context->base.batch;
> +
> + BEGIN_BCS_BATCH(batch, 7);
> +
> + OUT_BCS_BATCH(batch, HCP_VP9_SEGMENT_STATE | (7 - 2));
> + OUT_BCS_BATCH(batch, seg_id<< 0); /* DW 1 - SegmentID */
> + OUT_BCS_BATCH(batch,
> + seg_param->segment_flags.fields.segment_reference_enabled<< 3 |
> + seg_param->segment_flags.fields.segment_reference<< 1 |
> + seg_param->segment_flags.fields.segment_reference_skipped<<0 ); /* DW 2 */
> + OUT_BCS_BATCH(batch,
> + seg_param->filter_level[1][1]<< 24 | //FilterLevelRef1Mode1
> + seg_param->filter_level[1][0]<< 16 | //FilterLevelRef1Mode0
> + seg_param->filter_level[0][1]<< 8 | //FilterLevelRef0Mode1
> + seg_param->filter_level[0][0]<< 0 ); //FilterLevelRef0Mode0 /* DW 3 */
> + OUT_BCS_BATCH(batch,
> + seg_param->filter_level[3][1]<< 24 | //FilterLevelRef3Mode1
> + seg_param->filter_level[3][0]<< 16 | //FilterLevelRef3Mode0
> + seg_param->filter_level[2][1]<< 8 | //FilterLevelRef2Mode1
> + seg_param->filter_level[2][0]<< 0 ); //FilterLevelRef2Mode0 /* DW 4 */
> + OUT_BCS_BATCH(batch,
> + seg_param->luma_ac_quant_scale<< 16 |
> + seg_param->luma_dc_quant_scale<< 0 ); /* DW 5 */
> + OUT_BCS_BATCH(batch,
> + seg_param->chroma_ac_quant_scale<< 16 |
> + seg_param->chroma_dc_quant_scale<< 0 ); /* DW 6 */
> +
> + ADVANCE_BCS_BATCH(batch);
> +
> +}
> +
> +static void
> +gen9_hcpd_vp9_bsd_object(VADriverContextP ctx,
> + VADecPictureParameterBufferVP9 *pic_param,
> + VASliceParameterBufferVP9 *slice_param,
> + struct gen9_hcpd_context *gen9_hcpd_context)
> +{
> + struct intel_batchbuffer *batch = gen9_hcpd_context->base.batch;
> + int slice_data_size = slice_param->slice_data_size - pic_param->frame_header_length_in_bytes;
> + int slice_data_offset = slice_param->slice_data_offset + pic_param->frame_header_length_in_bytes;
> +
> + BEGIN_BCS_BATCH(batch, 3);
> +
> + OUT_BCS_BATCH(batch, HCP_BSD_OBJECT | (3 - 2));
> +
> + OUT_BCS_BATCH(batch, slice_data_size );
> + OUT_BCS_BATCH(batch, slice_data_offset);
> +
> + ADVANCE_BCS_BATCH(batch);
> +
> +}
> +
> +static VAStatus
> +gen9_hcpd_vp9_decode_picture(VADriverContextP ctx,
> + struct decode_state *decode_state,
> + struct gen9_hcpd_context *gen9_hcpd_context)
> +{
> + VAStatus vaStatus;
> + struct i965_driver_data *i965 = i965_driver_data(ctx);
> + struct intel_batchbuffer *batch = gen9_hcpd_context->base.batch;
> + VADecPictureParameterBufferVP9 *pic_param;
> + VASliceParameterBufferVP9 *slice_param;
> + dri_bo *slice_data_bo;
> + int i = 0, num_segments=0, isScaling=0;
> + struct object_surface *obj_surface;
> + GenVP9Surface *gen9_vp9_surface;
> + vaStatus = gen9_hcpd_vp9_decode_init(ctx, decode_state, gen9_hcpd_context);
> +
> + if (vaStatus != VA_STATUS_SUCCESS)
> + goto out;
> +
> + assert(decode_state->pic_param&& decode_state->pic_param->buffer);
> + pic_param = (VADecPictureParameterBufferVP9 *)decode_state->pic_param->buffer;
> +
> + //****And set the isScaling value accordingly******
> + isScaling = 0;
> + for(i = 0; i< 3; i++)
> + {
> + obj_surface = gen9_hcpd_context->reference_surfaces[i].obj_surface;
> + gen9_vp9_surface = NULL;
> + if (obj_surface&& obj_surface->private_data)
> + {
> + gen9_vp9_surface = obj_surface->private_data;
> + isScaling |= (gen9_vp9_surface->frame_width == pic_param->frame_width&&
> + gen9_vp9_surface->frame_height == pic_param->frame_height)? 0:1;
> + }
> + }
> +
> + //Update segment id buffer if needed
> + vp9_update_segmentId_buffer(ctx, decode_state, gen9_hcpd_context, isScaling);
> + //Update probability buffer if needed
> + vp9_update_probabilities(ctx, decode_state, gen9_hcpd_context);
> +
> + if (i965->intel.has_bsd2)
> + intel_batchbuffer_start_atomic_bcs_override(batch, 0x1000, BSD_RING0);
> + else
> + intel_batchbuffer_start_atomic_bcs(batch, 0x1000);
> + intel_batchbuffer_emit_mi_flush(batch);
> +
> + gen9_hcpd_pipe_mode_select(ctx, decode_state, HCP_CODEC_VP9, gen9_hcpd_context);
> + //Not sure what the surface id value should be: Gold? ALtRef? PrevRef? or Just RefPic?
> + gen9_hcpd_vp9_surface_state(ctx, decode_state, gen9_hcpd_context);
> +
> + //Only one VASliceParameterBufferVP9 should be sent per frame
> + assert(decode_state->slice_params&& decode_state->slice_params[0]->buffer);
> + slice_param = (VASliceParameterBufferVP9 *)decode_state->slice_params[0]->buffer;
> + slice_data_bo = decode_state->slice_datas[0]->bo;
> +
> + gen9_hcpd_ind_obj_base_addr_state(ctx, slice_data_bo, gen9_hcpd_context);
> +
> + gen9_hcpd_vp9_pipe_buf_addr_state(ctx, decode_state, gen9_hcpd_context);
> + //If segmentation is disabled, only SegParam[0] is valid,
> + //all others should be populated with 0
> + if(!pic_param->pic_fields.bits.segmentation_enabled)
> + num_segments = 1;
> + else //If segmentation is enabled, all 8 entries should be valid.
> + num_segments = 8;
> +
> + for(i=0; i<num_segments; i++) {
> + VASegmentParameterVP9 seg_param = slice_param->seg_param[i];
> + gen9_hcpd_vp9_segment_state(ctx, pic_param,&seg_param, i, gen9_hcpd_context);
> + }
> +
> + gen9_hcpd_vp9_pic_state(ctx, decode_state, gen9_hcpd_context);
> +
> + gen9_hcpd_vp9_bsd_object(ctx, pic_param, slice_param, gen9_hcpd_context);
> +
> + // keep track of the last frame status
> + gen9_hcpd_context->last_frame.frame_width = pic_param->frame_width;
> + gen9_hcpd_context->last_frame.frame_height = pic_param->frame_height;
> + gen9_hcpd_context->last_frame.show_frame = pic_param->pic_fields.bits.show_frame;
> + gen9_hcpd_context->last_frame.frame_type = pic_param->pic_fields.bits.frame_type;
> + gen9_hcpd_context->last_frame.refresh_frame_context = pic_param->pic_fields.bits.refresh_frame_context;
> + gen9_hcpd_context->last_frame.frame_context_idx = pic_param->pic_fields.bits.frame_context_idx;
> + gen9_hcpd_context->last_frame.intra_only = pic_param->pic_fields.bits.intra_only;
> +
> + // update prob buffer to vp9_fc;
> +
> + intel_batchbuffer_end_atomic(batch);
> + intel_batchbuffer_flush(batch);
> +
> + //update vp9_frame_ctx according to frame_context_id
> + if (pic_param->pic_fields.bits.refresh_frame_context)
> + {
> + //update vp9_fc to frame_context
> + dri_bo_map(gen9_hcpd_context->vp9_probability_buffer.bo,1);
> + memcpy(&gen9_hcpd_context->vp9_fc,(unsigned char *)gen9_hcpd_context->vp9_probability_buffer.bo->virtual,2048);
> + dri_bo_unmap(gen9_hcpd_context->vp9_probability_buffer.bo);
> + gen9_hcpd_context->vp9_frame_ctx[pic_param->pic_fields.bits.frame_context_idx] = gen9_hcpd_context->vp9_fc;
> +
> + }
> +
> +out:
> + return vaStatus;
> +}
> +
> +
> static VAStatus
> gen9_hcpd_decode_picture(VADriverContextP ctx,
> VAProfile profile,
> @@ -992,6 +1902,9 @@ gen9_hcpd_decode_picture(VADriverContextP ctx,
> case VAProfileHEVCMain10:
> vaStatus = gen9_hcpd_hevc_decode_picture(ctx, decode_state, gen9_hcpd_context);
> break;
> + case VAProfileVP9Profile0:
> + vaStatus = gen9_hcpd_vp9_decode_picture(ctx, decode_state, gen9_hcpd_context);
> + break;
>
> default:
> /* should never get here 1!! */
> @@ -1017,6 +1930,10 @@ gen9_hcpd_context_destroy(void *hw_context)
> FREE_GEN_BUFFER((&gen9_hcpd_context->sao_line_buffer));
> FREE_GEN_BUFFER((&gen9_hcpd_context->sao_tile_line_buffer));
> FREE_GEN_BUFFER((&gen9_hcpd_context->sao_tile_column_buffer));
> + FREE_GEN_BUFFER((&gen9_hcpd_context->hvd_line_rowstore_buffer));
> + FREE_GEN_BUFFER((&gen9_hcpd_context->hvd_tile_rowstore_buffer));
> + FREE_GEN_BUFFER((&gen9_hcpd_context->vp9_probability_buffer));
> + FREE_GEN_BUFFER((&gen9_hcpd_context->vp9_segment_id_buffer));
>
> intel_batchbuffer_free(gen9_hcpd_context->base.batch);
> free(gen9_hcpd_context);
> @@ -1029,6 +1946,25 @@ gen9_hcpd_hevc_context_init(VADriverContextP ctx,
> hevc_gen_default_iq_matrix(&gen9_hcpd_context->iq_matrix_hevc);
> }
>
> +static void
> +gen9_hcpd_vp9_context_init(VADriverContextP ctx,
> + struct gen9_hcpd_context *gen9_hcpd_context)
> +{
> + int default_value = 255;
> +
> + gen9_hcpd_context->last_frame.frame_height = 0;
> + gen9_hcpd_context->last_frame.show_frame = 0;
> + gen9_hcpd_context->last_frame.frame_type = 0;
> + gen9_hcpd_context->last_frame.refresh_frame_context = default_value;
> + gen9_hcpd_context->last_frame.frame_context_idx = default_value;
> + gen9_hcpd_context->last_frame.intra_only = 0;
> + gen9_hcpd_context->last_frame.prob_buffer_saved_flag = 0;
> + gen9_hcpd_context->last_frame.prob_buffer_restored_flag = 0;
> + gen9_hcpd_context->last_frame.mv_temporal_buffer_bo = NULL;
> +
> + vp9_gen_default_probabilities(ctx, gen9_hcpd_context);
> +}
> +
> static struct hw_context *
> gen9_hcpd_context_init(VADriverContextP ctx, struct object_config *object_config)
> {
> @@ -1054,6 +1990,9 @@ gen9_hcpd_context_init(VADriverContextP ctx, struct object_config *object_config
> case VAProfileHEVCMain10:
> gen9_hcpd_hevc_context_init(ctx, gen9_hcpd_context);
> break;
> + case VAProfileVP9Profile0:
> + gen9_hcpd_vp9_context_init(ctx, gen9_hcpd_context);
> + break;
>
> default:
> break;
> @@ -1066,7 +2005,8 @@ struct hw_context *
> gen9_dec_hw_context_init(VADriverContextP ctx, struct object_config *obj_config)
> {
> if (obj_config->profile == VAProfileHEVCMain ||
> - obj_config->profile == VAProfileHEVCMain10) {
> + obj_config->profile == VAProfileHEVCMain10 ||
> + obj_config->profile == VAProfileVP9Profile0) {
> return gen9_hcpd_context_init(ctx, obj_config);
> } else {
> return gen8_dec_hw_context_init(ctx, obj_config);
> diff --git a/src/gen9_mfd.h b/src/gen9_mfd.h
> index 6e9fa5d..c266dd4 100644
> --- a/src/gen9_mfd.h
> +++ b/src/gen9_mfd.h
> @@ -34,9 +34,24 @@
> #include<i915_drm.h>
> #include<intel_bufmgr.h>
> #include "i965_decoder.h"
> +#include "vp9_probs.h"
>
> struct hw_context;
>
> +typedef struct vp9_frame_status
> +{
> + uint16_t frame_width;
> + uint16_t frame_height;
> + uint8_t frame_type;
> + uint8_t show_frame;
> + uint8_t refresh_frame_context;
> + uint8_t frame_context_idx;
> + uint8_t intra_only;
> + uint8_t prob_buffer_saved_flag;
> + uint8_t prob_buffer_restored_flag;
> + dri_bo * mv_temporal_buffer_bo;
> +}vp9_last_frame_status;
> +
> struct gen9_hcpd_context
> {
> struct hw_context base;
> @@ -65,10 +80,21 @@ struct gen9_hcpd_context
> GenBuffer sao_line_buffer;
> GenBuffer sao_tile_line_buffer;
> GenBuffer sao_tile_column_buffer;
> + GenBuffer hvd_line_rowstore_buffer;
> + GenBuffer hvd_tile_rowstore_buffer;
> + GenBuffer vp9_probability_buffer;
> + GenBuffer vp9_segment_id_buffer;
>
> unsigned short first_inter_slice_collocated_ref_idx;
> unsigned short first_inter_slice_collocated_from_l0_flag;
> int first_inter_slice_valid;
> +
> + vp9_last_frame_status last_frame;
> + FRAME_CONTEXT vp9_frame_ctx[FRAME_CONTEXTS];
> + FRAME_CONTEXT vp9_fc_inter_default;
> + FRAME_CONTEXT vp9_fc_key_default;
> + FRAME_CONTEXT vp9_fc;
> + FRAME_CONTEXT vp9_saved_fc;
> };
>
> #endif /* GEN9_MFD_H */
More information about the Libva
mailing list