[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