From: He Junyan Date: Tue, 18 May 2021 06:09:01 +0000 (+0800) Subject: va: h265dec: Set LastSliceOfPic for multi sliced frames. X-Git-Tag: 1.19.3~507^2~370 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3bca4045e53d6e0ed85f42ad27fbe938a8ec6fdb;p=platform%2Fupstream%2Fgstreamer.git va: h265dec: Set LastSliceOfPic for multi sliced frames. VA-API HEVC decoding needs to known which is the last slice of a picture, but slices are processed sequencially, so we know the last slice until all the slices are already pushed into the VABuffer array. In order to mark the last slice, they are pushed into the VABuffer array with a delay of one slice: the first slice is hold, and when the second slice come, the first one is pushed while holding the second, and so on. Finally, at end_picture(), the last slice is marked and pushed into the array. Co-author: Victor Jaquez Part-of: --- diff --git a/sys/va/gstvah265dec.c b/sys/va/gstvah265dec.c index 25f0d39..b9e65b7 100644 --- a/sys/va/gstvah265dec.c +++ b/sys/va/gstvah265dec.c @@ -68,6 +68,14 @@ GST_DEBUG_CATEGORY_STATIC (gst_va_h265dec_debug); #define GST_VA_H265_DEC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_FROM_INSTANCE (obj), GstVaH265DecClass)) #define GST_VA_H265_DEC_CLASS(klass) ((GstVaH265DecClass *) klass) +struct slice +{ + guint8 *data; + guint size; + + VASliceParameterBufferHEVC param; +}; + typedef struct _GstVaH265Dec GstVaH265Dec; typedef struct _GstVaH265DecClass GstVaH265DecClass; @@ -89,6 +97,8 @@ struct _GstVaH265Dec VAPictureParameterBufferHEVC pic_param; gint32 WpOffsetHalfRangeC; + struct slice prev_slice; + gboolean need_negotiation; }; @@ -99,18 +109,87 @@ static const gchar *src_caps_str = GST_VIDEO_CAPS_MAKE_WITH_FEATURES ("memory:VA static const gchar *sink_caps_str = "video/x-h265"; +static inline void +_set_last_slice_flag (GstVaH265Dec * self) +{ + self->prev_slice.param.LongSliceFlags.fields.LastSliceOfPic = 1; +} + +static void +_replace_previous_slice (GstVaH265Dec * self, guint8 * data, guint size) +{ + struct slice *slice = &self->prev_slice; + gboolean do_reset = (slice->size < size); + + if (!data || do_reset) { + g_clear_pointer (&slice->data, g_free); + slice->size = 0; + } + + if (!data) + return; + + if (do_reset) { + GST_LOG_OBJECT (self, "allocating slice data %u", size); + slice->data = g_malloc (size); + } + + memcpy (slice->data, data, size); + slice->size = size; +} + +static gboolean +_submit_previous_slice (GstVaBaseDec * base, GstVaDecodePicture * va_pic) +{ + GstVaH265Dec *self = GST_VA_H265_DEC (base); + struct slice *slice; + gboolean ret; + + slice = &self->prev_slice; + if (!slice->data && slice->size == 0) + return TRUE; + if (!slice->data || slice->size == 0) + return FALSE; + + ret = gst_va_decoder_add_slice_buffer (base->decoder, va_pic, &slice->param, + sizeof (slice->param), slice->data, slice->size); + + return ret; +} + static gboolean gst_va_h265_dec_end_picture (GstH265Decoder * decoder, GstH265Picture * picture) { GstVaBaseDec *base = GST_VA_BASE_DEC (decoder); + GstVaH265Dec *self = GST_VA_H265_DEC (decoder); GstVaDecodePicture *va_pic; + gboolean ret; GST_LOG_OBJECT (base, "end picture %p, (poc %d)", picture, picture->pic_order_cnt); va_pic = gst_h265_picture_get_user_data (picture); - return gst_va_decoder_decode (base->decoder, va_pic); + _set_last_slice_flag (self); + ret = _submit_previous_slice (base, va_pic); + + /* TODO(victor): optimization: this could be done at decoder's + * stop() vmethod */ + _replace_previous_slice (self, NULL, 0); + + if (!ret) { + GST_ERROR_OBJECT (self, "Failed to submit the previous slice"); + return FALSE; + } + + ret = gst_va_decoder_decode (base->decoder, va_pic); + if (!ret) { + GST_ERROR_OBJECT (self, "Failed at end picture %p, (poc %d)", + picture, picture->pic_order_cnt); + return FALSE; + } + + return TRUE; } static GstFlowReturn @@ -125,6 +204,7 @@ gst_va_h265_dec_output_picture (GstH265Decoder * decoder, if (self->last_ret != GST_FLOW_OK) { gst_h265_picture_unref (picture); + _replace_previous_slice (self, NULL, 0); gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame); return self->last_ret; } @@ -342,11 +422,21 @@ gst_va_h265_dec_decode_slice (GstH265Decoder * decoder, GstH265SliceHdr *header = &slice->header; GstH265NalUnit *nalu = &slice->nalu; GstVaBaseDec *base = GST_VA_BASE_DEC (decoder); + GstVaH265Dec *self = GST_VA_H265_DEC (decoder); GstVaDecodePicture *va_pic; - VASliceParameterBufferHEVC slice_param; + VASliceParameterBufferHEVC *slice_param; + + va_pic = gst_h265_picture_get_user_data (picture); + if (!_submit_previous_slice (base, va_pic)) { + _replace_previous_slice (self, NULL, 0); + GST_ERROR_OBJECT (base, "Failed to submit previous slice buffers"); + return FALSE; + } + + slice_param = &self->prev_slice.param; /* *INDENT-OFF* */ - slice_param = (VASliceParameterBufferHEVC) { + *slice_param = (VASliceParameterBufferHEVC) { .slice_data_size = nalu->size, .slice_data_offset = 0, .slice_data_flag = VA_SLICE_DATA_FLAG_ALL, @@ -364,43 +454,36 @@ gst_va_h265_dec_decode_slice (GstH265Decoder * decoder, .num_entry_point_offsets = header->num_entry_point_offsets, .entry_offset_to_subset_array = 0, /* does not exist in spec */ .slice_data_num_emu_prevn_bytes = header->n_emulation_prevention_bytes, + .LongSliceFlags.fields = { + .LastSliceOfPic = 0, /* the last one will be set on end_picture() */ + .dependent_slice_segment_flag = header->dependent_slice_segment_flag, + .slice_type = header->type, + .color_plane_id = header->colour_plane_id, + .slice_sao_luma_flag = header->sao_luma_flag, + .slice_sao_chroma_flag = header->sao_chroma_flag, + .mvd_l1_zero_flag = header->mvd_l1_zero_flag, + .cabac_init_flag = header->cabac_init_flag, + .slice_temporal_mvp_enabled_flag = header->temporal_mvp_enabled_flag, + .slice_deblocking_filter_disabled_flag = + header->deblocking_filter_disabled_flag, + .collocated_from_l0_flag = header->collocated_from_l0_flag, + .slice_loop_filter_across_slices_enabled_flag = + header->loop_filter_across_slices_enabled_flag, + }, }; /* *INDENT-ON* */ - /* FIXME to set this right, we'd need to delay writing this until we get - * called on end_picture(), which is all silly */ - slice_param.LongSliceFlags.fields.LastSliceOfPic = 0; - slice_param.LongSliceFlags.fields.dependent_slice_segment_flag = - header->dependent_slice_segment_flag; - slice_param.LongSliceFlags.fields.slice_type = header->type; - slice_param.LongSliceFlags.fields.color_plane_id = header->colour_plane_id; - slice_param.LongSliceFlags.fields.slice_sao_luma_flag = header->sao_luma_flag; - slice_param.LongSliceFlags.fields.slice_sao_chroma_flag = - header->sao_chroma_flag; - slice_param.LongSliceFlags.fields.mvd_l1_zero_flag = header->mvd_l1_zero_flag; - slice_param.LongSliceFlags.fields.cabac_init_flag = header->cabac_init_flag; - slice_param.LongSliceFlags.fields.slice_temporal_mvp_enabled_flag = - header->temporal_mvp_enabled_flag; - slice_param.LongSliceFlags.fields.slice_deblocking_filter_disabled_flag = - header->deblocking_filter_disabled_flag; - slice_param.LongSliceFlags.fields.collocated_from_l0_flag = - header->collocated_from_l0_flag; - slice_param.LongSliceFlags.fields. - slice_loop_filter_across_slices_enabled_flag = - header->loop_filter_across_slices_enabled_flag; - - _fill_ref_pic_list (decoder, picture, slice_param.RefPicList[0], + _fill_ref_pic_list (decoder, picture, slice_param->RefPicList[0], ref_pic_list0); - _fill_ref_pic_list (decoder, picture, slice_param.RefPicList[1], + _fill_ref_pic_list (decoder, picture, slice_param->RefPicList[1], ref_pic_list1); - _fill_pred_weight_table (GST_VA_H265_DEC (decoder), header, &slice_param); - - va_pic = gst_h265_picture_get_user_data (picture); + _fill_pred_weight_table (GST_VA_H265_DEC (decoder), header, slice_param); - return gst_va_decoder_add_slice_buffer (base->decoder, va_pic, &slice_param, - sizeof (slice_param), slice->nalu.data + slice->nalu.offset, + _replace_previous_slice (self, slice->nalu.data + slice->nalu.offset, slice->nalu.size); + + return TRUE; } static gboolean @@ -569,10 +652,10 @@ static gboolean gst_va_h265_dec_new_picture (GstH265Decoder * decoder, GstVideoCodecFrame * frame, GstH265Picture * picture) { + GstVaBaseDec *base = GST_VA_BASE_DEC (decoder); GstVaH265Dec *self = GST_VA_H265_DEC (decoder); GstVaDecodePicture *pic; GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder); - GstVaBaseDec *base = GST_VA_BASE_DEC (decoder); self->last_ret = gst_video_decoder_allocate_output_frame (vdec, frame); if (self->last_ret != GST_FLOW_OK) @@ -902,7 +985,10 @@ gst_va_h265_dec_negotiate (GstVideoDecoder * decoder) static void gst_va_h265_dec_dispose (GObject * object) { + g_free (GST_VA_H265_DEC (object)->prev_slice.data); + gst_va_base_dec_close (GST_VIDEO_DECODER (object)); + G_OBJECT_CLASS (GST_VA_BASE_DEC_GET_PARENT_CLASS (object))->dispose (object); }