[Libva] [libva-intel-driver PATCH 08/10] VP9 HWDec: add VP9 HW decoding pipeline
Xiang, Haihao
haihao.xiang at intel.com
Thu Dec 3 10:14:01 PST 2015
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>
---
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 */
--
1.9.1
More information about the Libva
mailing list