From 08dc70b6f43bc261b32945b3a644d77a7a8f335e Mon Sep 17 00:00:00 2001 From: He Junyan Date: Fri, 21 May 2021 23:21:12 +0800 Subject: [PATCH] va: h265dec: Set range extension for picture and slice parameters. We already declare the support of HEVC range extension profiles in the profile mapping list, but we fail to generate the correct VA picture and slice parameters buffers. This may cause the GPU hang. We need to fill the buffer of VAPictureParameterBufferHEVCExtension and VASliceParameterBufferHEVCExtension correctly. Part-of: --- sys/va/gstvah265dec.c | 98 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) diff --git a/sys/va/gstvah265dec.c b/sys/va/gstvah265dec.c index 51bc2e3c53..d30ed2c34a 100644 --- a/sys/va/gstvah265dec.c +++ b/sys/va/gstvah265dec.c @@ -110,6 +110,19 @@ static const gchar *src_caps_str = GST_VIDEO_CAPS_MAKE_WITH_FEATURES ("memory:VA static const gchar *sink_caps_str = "video/x-h265"; +static gboolean +_is_range_extension_profile (VAProfile profile) +{ + if (profile == VAProfileHEVCMain422_10 + || profile == VAProfileHEVCMain444 + || profile == VAProfileHEVCMain444_10 + || profile == VAProfileHEVCMain12 + || profile == VAProfileHEVCMain444_12 + || profile == VAProfileHEVCMain422_12) + return TRUE; + return FALSE; +} + static inline void _set_last_slice_flag (GstVaH265Dec * self) { @@ -145,6 +158,7 @@ _submit_previous_slice (GstVaBaseDec * base, GstVaDecodePicture * va_pic) GstVaH265Dec *self = GST_VA_H265_DEC (base); struct slice *slice; gboolean ret; + gsize param_size; slice = &self->prev_slice; if (!slice->data && slice->size == 0) @@ -152,8 +166,10 @@ _submit_previous_slice (GstVaBaseDec * base, GstVaDecodePicture * va_pic) if (!slice->data || slice->size == 0) return FALSE; + param_size = _is_range_extension_profile (self->parent.profile) ? + sizeof (slice->param) : sizeof (slice->param.base); ret = gst_va_decoder_add_slice_buffer (base->decoder, va_pic, &slice->param, - sizeof (slice->param.base), slice->data, slice->size); + param_size, slice->data, slice->size); return ret; } @@ -316,6 +332,7 @@ _fill_pred_weight_table (GstVaH265Dec * self, GstH265SliceHdr * header, gint chroma_weight, chroma_log2_weight_denom; gint i, j; GstH265PPS *pps = header->pps; + gboolean is_rext = _is_range_extension_profile (self->parent.profile); if (GST_H265_IS_I_SLICE (header) || (!pps->weighted_pred_flag && GST_H265_IS_P_SLICE (header)) || @@ -337,6 +354,11 @@ _fill_pred_weight_table (GstVaH265Dec * self, GstH265SliceHdr * header, header->pred_weight_table.delta_luma_weight_l0[i]; slice_param->base.luma_offset_l0[i] = header->pred_weight_table.luma_offset_l0[i]; + + if (is_rext) { + slice_param->rext.luma_offset_l0[i] = + header->pred_weight_table.luma_offset_l0[i]; + } } chroma_log2_weight_denom = slice_param->base.luma_log2_weight_denom + @@ -364,6 +386,11 @@ _fill_pred_weight_table (GstVaH265Dec * self, GstH265SliceHdr * header, /* 7-56 */ slice_param->base.ChromaOffsetL0[i][j] = CLAMP (chroma_offset, -self->WpOffsetHalfRangeC, self->WpOffsetHalfRangeC - 1); + + if (is_rext) { + slice_param->rext.ChromaOffsetL0[i][j] = + slice_param->base.ChromaOffsetL0[i][j]; + } } } @@ -379,6 +406,11 @@ _fill_pred_weight_table (GstVaH265Dec * self, GstH265SliceHdr * header, header->pred_weight_table.delta_luma_weight_l1[i]; slice_param->base.luma_offset_l1[i] = header->pred_weight_table.luma_offset_l1[i]; + + if (is_rext) { + slice_param->rext.luma_offset_l1[i] = + header->pred_weight_table.luma_offset_l1[i]; + } } for (i = 0; i <= header->num_ref_idx_l1_active_minus1; i++) { @@ -405,6 +437,10 @@ _fill_pred_weight_table (GstVaH265Dec * self, GstH265SliceHdr * header, slice_param->base.ChromaOffsetL1[i][j] = CLAMP (chroma_offset, -self->WpOffsetHalfRangeC, self->WpOffsetHalfRangeC - 1); + if (is_rext) { + slice_param->rext.ChromaOffsetL1[i][j] = + slice_param->base.ChromaOffsetL1[i][j]; + } } } } @@ -478,6 +514,20 @@ gst_va_h265_dec_decode_slice (GstH265Decoder * decoder, }; /* *INDENT-ON* */ + if (_is_range_extension_profile (base->profile)) { + /* *INDENT-OFF* */ + slice_param->rext = (VASliceParameterBufferHEVCRext) { + .slice_ext_flags.bits = { + .cu_chroma_qp_offset_enabled_flag = header->cu_chroma_qp_offset_enabled_flag, + .use_integer_mv_flag = header->use_integer_mv_flag, + }, + .slice_act_y_qp_offset = header->slice_act_y_qp_offset, + .slice_act_cb_qp_offset = header->slice_act_cb_qp_offset, + .slice_act_cr_qp_offset = header->slice_act_cr_qp_offset, + }; + /* *INDENT-ON* */ + } + _fill_ref_pic_list (decoder, picture, slice_param->base.RefPicList[0], ref_pic_list0); _fill_ref_pic_list (decoder, picture, slice_param->base.RefPicList[1], @@ -491,6 +541,44 @@ gst_va_h265_dec_decode_slice (GstH265Decoder * decoder, return TRUE; } +static void +_fill_picture_range_ext_parameter (GstVaH265Dec * decoder, + GstH265SPS * sps, GstH265PPS * pps) +{ + VAPictureParameterBufferHEVCRext *pic_param = &decoder->pic_param.rext; + + GstH265SPSExtensionParams *sps_ext = &sps->sps_extnsion_params; + GstH265PPSExtensionParams *pps_ext = &pps->pps_extension_params; + + /* *INDENT-OFF* */ + *pic_param = (VAPictureParameterBufferHEVCRext) { + .range_extension_pic_fields.bits = { + .transform_skip_rotation_enabled_flag = sps_ext->transform_skip_rotation_enabled_flag, + .transform_skip_context_enabled_flag = sps_ext->transform_skip_context_enabled_flag, + .implicit_rdpcm_enabled_flag = sps_ext->implicit_rdpcm_enabled_flag, + .explicit_rdpcm_enabled_flag = sps_ext->explicit_rdpcm_enabled_flag, + .extended_precision_processing_flag = sps_ext->extended_precision_processing_flag, + .intra_smoothing_disabled_flag = sps_ext->intra_smoothing_disabled_flag, + .high_precision_offsets_enabled_flag = sps_ext->high_precision_offsets_enabled_flag, + .persistent_rice_adaptation_enabled_flag = sps_ext->persistent_rice_adaptation_enabled_flag, + .cabac_bypass_alignment_enabled_flag = sps_ext->cabac_bypass_alignment_enabled_flag, + .cross_component_prediction_enabled_flag = pps_ext->cross_component_prediction_enabled_flag, + .chroma_qp_offset_list_enabled_flag = pps_ext->chroma_qp_offset_list_enabled_flag, + }, + .diff_cu_chroma_qp_offset_depth = pps_ext->diff_cu_chroma_qp_offset_depth, + .chroma_qp_offset_list_len_minus1 = pps_ext->chroma_qp_offset_list_len_minus1, + .log2_sao_offset_scale_luma = pps_ext->log2_sao_offset_scale_luma, + .log2_sao_offset_scale_chroma = pps_ext->log2_sao_offset_scale_chroma, + .log2_max_transform_skip_block_size_minus2 = pps_ext->log2_max_transform_skip_block_size_minus2, + }; + /* *INDENT-ON* */ + + memcpy (pic_param->cb_qp_offset_list, pps_ext->cb_qp_offset_list, + sizeof (pic_param->cb_qp_offset_list)); + memcpy (pic_param->cr_qp_offset_list, pps_ext->cr_qp_offset_list, + sizeof (pic_param->cr_qp_offset_list)); +} + static gboolean gst_va_h265_dec_start_picture (GstH265Decoder * decoder, GstH265Picture * picture, GstH265Slice * slice, GstH265Dpb * dpb) @@ -503,6 +591,7 @@ gst_va_h265_dec_start_picture (GstH265Decoder * decoder, GstH265ScalingList *scaling_list = NULL; VAIQMatrixBufferHEVC iq_matrix = { 0, }; VAPictureParameterBufferHEVCExtension *pic_param = &self->pic_param; + gsize pic_param_size; guint i; va_pic = gst_h265_picture_get_user_data (picture); @@ -585,6 +674,9 @@ gst_va_h265_dec_start_picture (GstH265Decoder * decoder, }; /* *INDENT-ON* */ + if (_is_range_extension_profile (self->parent.profile)) + _fill_picture_range_ext_parameter (self, sps, pps); + for (i = 0; i <= pps->num_tile_columns_minus1; i++) pic_param->base.column_width_minus1[i] = pps->column_width_minus1[i]; @@ -606,8 +698,10 @@ gst_va_h265_dec_start_picture (GstH265Decoder * decoder, _init_vaapi_pic (&pic_param->base.ReferenceFrames[i]); } + pic_param_size = _is_range_extension_profile (self->parent.profile) ? + sizeof (*pic_param) : sizeof (pic_param->base); if (!gst_va_decoder_add_param_buffer (base->decoder, va_pic, - VAPictureParameterBufferType, pic_param, sizeof (pic_param->base))) + VAPictureParameterBufferType, pic_param, pic_param_size)) return FALSE; if (pps->scaling_list_data_present_flag ||