2 * Copyright (C) 2020 Igalia, S.L.
3 * Author: Víctor Jáquez <vjaquez@igalia.com>
4 * Copyright (C) 2020 Collabora
5 * Author: Nicolas Dufresne <nicolas.dufresne@collabora.com>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the0
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
24 * SECTION:element-vah265dec
26 * @short_description: A VA-API based H265 video decoder
28 * vah265dec decodes H265 bitstreams to VA surfaces using the
29 * installed and chosen [VA-API](https://01.org/linuxmedia/vaapi)
32 * The decoding surfaces can be mapped onto main memory as video
35 * ## Example launch line
37 * gst-launch-1.0 filesrc location=big_buck_bunny.mov ! parsebin ! vah265dec ! autovideosink
46 * + interlaced streams
47 * + mutiview and stereo profiles
48 * + SCC extension buffer
56 #include "gstvah265dec.h"
58 #include "gstvabasedec.h"
60 GST_DEBUG_CATEGORY_STATIC (gst_va_h265dec_debug);
61 #ifndef GST_DISABLE_GST_DEBUG
62 #define GST_CAT_DEFAULT gst_va_h265dec_debug
64 #define GST_CAT_DEFAULT NULL
67 #define GST_VA_H265_DEC(obj) ((GstVaH265Dec *) obj)
68 #define GST_VA_H265_DEC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_FROM_INSTANCE (obj), GstVaH265DecClass))
69 #define GST_VA_H265_DEC_CLASS(klass) ((GstVaH265DecClass *) klass)
76 VASliceParameterBufferHEVCExtension param;
79 typedef struct _GstVaH265Dec GstVaH265Dec;
80 typedef struct _GstVaH265DecClass GstVaH265DecClass;
82 struct _GstVaH265DecClass
84 GstVaBaseDecClass parent_class;
91 GstFlowReturn last_ret;
97 VAPictureParameterBufferHEVCExtension pic_param;
99 gint32 WpOffsetHalfRangeC;
101 struct slice prev_slice;
104 static GstElementClass *parent_class = NULL;
107 static const gchar *src_caps_str =
108 GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_VA,
109 "{ NV12, P010_10LE }") " ;"
110 GST_VIDEO_CAPS_MAKE ("{ NV12, P010_10LE }");
113 static const gchar *sink_caps_str = "video/x-h265";
116 _is_range_extension_profile (VAProfile profile)
118 if (profile == VAProfileHEVCMain422_10
119 || profile == VAProfileHEVCMain444
120 || profile == VAProfileHEVCMain444_10
121 || profile == VAProfileHEVCMain12
122 || profile == VAProfileHEVCMain444_12
123 || profile == VAProfileHEVCMain422_12)
129 _is_screen_content_ext_profile (VAProfile profile)
131 if (profile == VAProfileHEVCSccMain || profile == VAProfileHEVCSccMain10
132 || profile == VAProfileHEVCSccMain444
133 #if VA_CHECK_VERSION(1, 8, 0)
134 || profile == VAProfileHEVCSccMain444_10
143 _set_last_slice_flag (GstVaH265Dec * self)
145 self->prev_slice.param.base.LongSliceFlags.fields.LastSliceOfPic = 1;
149 _replace_previous_slice (GstVaH265Dec * self, guint8 * data, guint size)
151 struct slice *slice = &self->prev_slice;
152 gboolean do_reset = (slice->size < size);
154 if (!data || do_reset) {
155 g_clear_pointer (&slice->data, g_free);
163 GST_LOG_OBJECT (self, "allocating slice data %u", size);
164 slice->data = g_malloc (size);
167 memcpy (slice->data, data, size);
172 _submit_previous_slice (GstVaBaseDec * base, GstVaDecodePicture * va_pic)
174 GstVaH265Dec *self = GST_VA_H265_DEC (base);
179 slice = &self->prev_slice;
180 if (!slice->data && slice->size == 0)
182 if (!slice->data || slice->size == 0)
185 param_size = _is_range_extension_profile (self->parent.profile)
186 || _is_screen_content_ext_profile (self->parent.profile) ?
187 sizeof (slice->param) : sizeof (slice->param.base);
188 ret = gst_va_decoder_add_slice_buffer (base->decoder, va_pic, &slice->param,
189 param_size, slice->data, slice->size);
195 gst_va_h265_dec_end_picture (GstH265Decoder * decoder, GstH265Picture * picture)
197 GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
198 GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
199 GstVaDecodePicture *va_pic;
202 GST_LOG_OBJECT (base, "end picture %p, (poc %d)",
203 picture, picture->pic_order_cnt);
205 va_pic = gst_h265_picture_get_user_data (picture);
207 _set_last_slice_flag (self);
208 ret = _submit_previous_slice (base, va_pic);
210 /* TODO(victor): optimization: this could be done at decoder's
212 _replace_previous_slice (self, NULL, 0);
215 GST_ERROR_OBJECT (self, "Failed to submit the previous slice");
216 return GST_FLOW_ERROR;
219 ret = gst_va_decoder_decode (base->decoder, va_pic);
221 GST_ERROR_OBJECT (self, "Failed at end picture %p, (poc %d)",
222 picture, picture->pic_order_cnt);
223 return GST_FLOW_ERROR;
230 gst_va_h265_dec_output_picture (GstH265Decoder * decoder,
231 GstVideoCodecFrame * frame, GstH265Picture * picture)
233 GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
234 GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
235 GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
236 GstVaDecodePicture *va_pic;
239 va_pic = gst_h265_picture_get_user_data (picture);
240 g_assert (va_pic->gstbuffer);
242 GST_LOG_OBJECT (self,
243 "Outputting picture %p (poc %d)", picture, picture->pic_order_cnt);
245 if (self->last_ret != GST_FLOW_OK) {
246 gst_h265_picture_unref (picture);
247 _replace_previous_slice (self, NULL, 0);
248 gst_video_decoder_drop_frame (vdec, frame);
249 return self->last_ret;
252 gst_buffer_replace (&frame->output_buffer, va_pic->gstbuffer);
254 ret = gst_va_base_dec_process_output (base, frame, picture->buffer_flags);
255 gst_h265_picture_unref (picture);
258 return gst_video_decoder_finish_frame (vdec, frame);
259 return GST_FLOW_ERROR;
263 _init_vaapi_pic (VAPictureHEVC * va_picture)
265 va_picture->picture_id = VA_INVALID_ID;
266 va_picture->flags = VA_PICTURE_HEVC_INVALID;
267 va_picture->pic_order_cnt = 0;
271 _find_frame_rps_type (GstH265Decoder * decoder, GstH265Picture * ref_pic)
275 for (i = 0; i < G_N_ELEMENTS (decoder->RefPicSetStCurrBefore); i++) {
276 if (ref_pic == decoder->RefPicSetStCurrBefore[i])
277 return VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE;
280 for (i = 0; i < G_N_ELEMENTS (decoder->RefPicSetStCurrAfter); i++) {
281 if (ref_pic == decoder->RefPicSetStCurrAfter[i])
282 return VA_PICTURE_HEVC_RPS_ST_CURR_AFTER;
285 for (i = 0; i < G_N_ELEMENTS (decoder->RefPicSetLtCurr); i++) {
286 if (ref_pic == decoder->RefPicSetLtCurr[i])
287 return VA_PICTURE_HEVC_RPS_LT_CURR;
295 _fill_vaapi_pic (GstH265Decoder * decoder, VAPictureHEVC * va_picture,
296 GstH265Picture * picture)
298 GstVaDecodePicture *va_pic;
300 va_pic = gst_h265_picture_get_user_data (picture);
303 _init_vaapi_pic (va_picture);
307 va_picture->picture_id = gst_va_decode_picture_get_surface (va_pic);
308 va_picture->pic_order_cnt = picture->pic_order_cnt;
309 va_picture->flags = 0;
311 if (picture->ref && picture->long_term)
312 va_picture->flags |= VA_PICTURE_HEVC_LONG_TERM_REFERENCE;
314 va_picture->flags |= _find_frame_rps_type (decoder, picture);
318 _get_reference_index (GstH265Decoder * decoder, GstH265Picture * picture)
320 GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
326 for (i = 0; i < 15; i++) {
327 VAPictureHEVC *ref_va_pic = &self->pic_param.base.ReferenceFrames[i];
329 if (ref_va_pic->picture_id == VA_INVALID_ID)
332 if (ref_va_pic->pic_order_cnt == picture->pic_order_cnt)
339 /* fill the VA API reference picture lists from the GstCodec reference
342 _fill_ref_pic_list (GstH265Decoder * decoder, GstH265Picture * cur_pic,
343 guint8 va_reflist[15], GArray * reflist)
347 for (i = 0; i < reflist->len && i < 15; i++) {
348 GstH265Picture *picture = g_array_index (reflist, GstH265Picture *, i);
349 va_reflist[i] = _get_reference_index (decoder, picture);
353 va_reflist[i] = 0xFF;
357 _fill_pred_weight_table (GstVaH265Dec * self, GstH265SliceHdr * header,
358 VASliceParameterBufferHEVCExtension * slice_param)
360 gint chroma_weight, chroma_log2_weight_denom;
362 GstH265PPS *pps = header->pps;
363 gboolean is_rext = _is_range_extension_profile (self->parent.profile);
365 if (GST_H265_IS_I_SLICE (header) ||
366 (!pps->weighted_pred_flag && GST_H265_IS_P_SLICE (header)) ||
367 (!pps->weighted_bipred_flag && GST_H265_IS_B_SLICE (header)))
370 slice_param->base.luma_log2_weight_denom =
371 header->pred_weight_table.luma_log2_weight_denom;
373 if (pps->sps->chroma_array_type != 0)
374 slice_param->base.delta_chroma_log2_weight_denom =
375 header->pred_weight_table.delta_chroma_log2_weight_denom;
377 for (i = 0; i <= header->num_ref_idx_l0_active_minus1; i++) {
378 if (!header->pred_weight_table.luma_weight_l0_flag[i])
381 slice_param->base.delta_luma_weight_l0[i] =
382 header->pred_weight_table.delta_luma_weight_l0[i];
383 slice_param->base.luma_offset_l0[i] =
384 header->pred_weight_table.luma_offset_l0[i];
387 slice_param->rext.luma_offset_l0[i] =
388 header->pred_weight_table.luma_offset_l0[i];
392 chroma_log2_weight_denom = slice_param->base.luma_log2_weight_denom +
393 slice_param->base.delta_chroma_log2_weight_denom;
395 for (i = 0; i <= header->num_ref_idx_l0_active_minus1; i++) {
396 if (!header->pred_weight_table.chroma_weight_l0_flag[i])
399 for (j = 0; j < 2; j++) {
400 gint16 delta_chroma_offset_l0 =
401 header->pred_weight_table.delta_chroma_offset_l0[i][j];
404 slice_param->base.delta_chroma_weight_l0[i][j] =
405 header->pred_weight_table.delta_chroma_weight_l0[i][j];
407 /* Find ChromaWeightL0 */
408 chroma_weight = (1 << chroma_log2_weight_denom) +
409 header->pred_weight_table.delta_chroma_weight_l0[i][j];
410 chroma_offset = self->WpOffsetHalfRangeC + delta_chroma_offset_l0
411 - ((self->WpOffsetHalfRangeC * chroma_weight)
412 >> chroma_log2_weight_denom);
415 slice_param->base.ChromaOffsetL0[i][j] = CLAMP (chroma_offset,
416 -self->WpOffsetHalfRangeC, self->WpOffsetHalfRangeC - 1);
419 slice_param->rext.ChromaOffsetL0[i][j] =
420 slice_param->base.ChromaOffsetL0[i][j];
425 /* Skip l1 if this is not a B-Frame. */
426 if (!GST_H265_IS_B_SLICE (header))
429 for (i = 0; i <= header->num_ref_idx_l1_active_minus1; i++) {
430 if (!header->pred_weight_table.luma_weight_l1_flag[i])
433 slice_param->base.delta_luma_weight_l1[i] =
434 header->pred_weight_table.delta_luma_weight_l1[i];
435 slice_param->base.luma_offset_l1[i] =
436 header->pred_weight_table.luma_offset_l1[i];
439 slice_param->rext.luma_offset_l1[i] =
440 header->pred_weight_table.luma_offset_l1[i];
444 for (i = 0; i <= header->num_ref_idx_l1_active_minus1; i++) {
445 if (!header->pred_weight_table.chroma_weight_l1_flag[i])
448 for (j = 0; j < 2; j++) {
449 gint16 delta_chroma_offset_l1 =
450 header->pred_weight_table.delta_chroma_offset_l1[i][j];
453 slice_param->base.delta_chroma_weight_l1[i][j] =
454 header->pred_weight_table.delta_chroma_weight_l1[i][j];
456 /* Find ChromaWeightL1 */
457 chroma_weight = (1 << chroma_log2_weight_denom) +
458 header->pred_weight_table.delta_chroma_weight_l1[i][j];
460 chroma_offset = self->WpOffsetHalfRangeC + delta_chroma_offset_l1
461 - ((self->WpOffsetHalfRangeC * chroma_weight)
462 >> chroma_log2_weight_denom);
465 slice_param->base.ChromaOffsetL1[i][j] = CLAMP (chroma_offset,
466 -self->WpOffsetHalfRangeC, self->WpOffsetHalfRangeC - 1);
469 slice_param->rext.ChromaOffsetL1[i][j] =
470 slice_param->base.ChromaOffsetL1[i][j];
477 _get_slice_data_byte_offset (GstH265SliceHdr * slice_hdr,
478 guint nal_header_bytes)
482 epb_count = slice_hdr->n_emulation_prevention_bytes;
483 return nal_header_bytes + (slice_hdr->header_size + 7) / 8 - epb_count;
487 gst_va_h265_dec_decode_slice (GstH265Decoder * decoder,
488 GstH265Picture * picture, GstH265Slice * slice, GArray * ref_pic_list0,
489 GArray * ref_pic_list1)
491 GstH265SliceHdr *header = &slice->header;
492 GstH265NalUnit *nalu = &slice->nalu;
493 GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
494 GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
495 GstVaDecodePicture *va_pic;
496 VASliceParameterBufferHEVCExtension *slice_param;
498 va_pic = gst_h265_picture_get_user_data (picture);
499 if (!_submit_previous_slice (base, va_pic)) {
500 _replace_previous_slice (self, NULL, 0);
501 GST_ERROR_OBJECT (base, "Failed to submit previous slice buffers");
502 return GST_FLOW_ERROR;
505 slice_param = &self->prev_slice.param;
508 slice_param->base = (VASliceParameterBufferHEVC) {
509 .slice_data_size = nalu->size,
510 .slice_data_offset = 0,
511 .slice_data_flag = VA_SLICE_DATA_FLAG_ALL,
512 .slice_data_byte_offset = _get_slice_data_byte_offset (header, nalu->header_bytes),
513 .slice_segment_address = header->segment_address,
514 .collocated_ref_idx = header->temporal_mvp_enabled_flag ? header->collocated_ref_idx : 0xFF,
515 .num_ref_idx_l0_active_minus1 = header->num_ref_idx_l0_active_minus1,
516 .num_ref_idx_l1_active_minus1 = header->num_ref_idx_l1_active_minus1,
517 .slice_qp_delta = header->qp_delta,
518 .slice_cb_qp_offset = header->cb_qp_offset,
519 .slice_cr_qp_offset = header->cr_qp_offset,
520 .slice_beta_offset_div2 = header->beta_offset_div2,
521 .slice_tc_offset_div2 = header->tc_offset_div2,
522 .five_minus_max_num_merge_cand = header->five_minus_max_num_merge_cand,
523 .num_entry_point_offsets = header->num_entry_point_offsets,
524 .entry_offset_to_subset_array = 0, /* does not exist in spec */
525 .slice_data_num_emu_prevn_bytes = header->n_emulation_prevention_bytes,
526 .LongSliceFlags.fields = {
527 .LastSliceOfPic = 0, /* the last one will be set on end_picture() */
528 .dependent_slice_segment_flag = header->dependent_slice_segment_flag,
529 .slice_type = header->type,
530 .color_plane_id = header->colour_plane_id,
531 .slice_sao_luma_flag = header->sao_luma_flag,
532 .slice_sao_chroma_flag = header->sao_chroma_flag,
533 .mvd_l1_zero_flag = header->mvd_l1_zero_flag,
534 .cabac_init_flag = header->cabac_init_flag,
535 .slice_temporal_mvp_enabled_flag = header->temporal_mvp_enabled_flag,
536 .slice_deblocking_filter_disabled_flag =
537 header->deblocking_filter_disabled_flag,
538 .collocated_from_l0_flag = header->collocated_from_l0_flag,
539 .slice_loop_filter_across_slices_enabled_flag =
540 header->loop_filter_across_slices_enabled_flag,
545 if (_is_range_extension_profile (base->profile)
546 || _is_screen_content_ext_profile (base->profile)) {
548 slice_param->rext = (VASliceParameterBufferHEVCRext) {
549 .slice_ext_flags.bits = {
550 .cu_chroma_qp_offset_enabled_flag = header->cu_chroma_qp_offset_enabled_flag,
551 .use_integer_mv_flag = header->use_integer_mv_flag,
553 .slice_act_y_qp_offset = header->slice_act_y_qp_offset,
554 .slice_act_cb_qp_offset = header->slice_act_cb_qp_offset,
555 .slice_act_cr_qp_offset = header->slice_act_cr_qp_offset,
560 _fill_ref_pic_list (decoder, picture, slice_param->base.RefPicList[0],
562 _fill_ref_pic_list (decoder, picture, slice_param->base.RefPicList[1],
565 _fill_pred_weight_table (GST_VA_H265_DEC (decoder), header, slice_param);
567 _replace_previous_slice (self, slice->nalu.data + slice->nalu.offset,
574 _fill_picture_range_ext_parameter (GstVaH265Dec * decoder,
575 GstH265SPS * sps, GstH265PPS * pps)
577 VAPictureParameterBufferHEVCRext *pic_param = &decoder->pic_param.rext;
579 GstH265SPSExtensionParams *sps_ext = &sps->sps_extension_params;
580 GstH265PPSExtensionParams *pps_ext = &pps->pps_extension_params;
583 *pic_param = (VAPictureParameterBufferHEVCRext) {
584 .range_extension_pic_fields.bits = {
585 .transform_skip_rotation_enabled_flag = sps_ext->transform_skip_rotation_enabled_flag,
586 .transform_skip_context_enabled_flag = sps_ext->transform_skip_context_enabled_flag,
587 .implicit_rdpcm_enabled_flag = sps_ext->implicit_rdpcm_enabled_flag,
588 .explicit_rdpcm_enabled_flag = sps_ext->explicit_rdpcm_enabled_flag,
589 .extended_precision_processing_flag = sps_ext->extended_precision_processing_flag,
590 .intra_smoothing_disabled_flag = sps_ext->intra_smoothing_disabled_flag,
591 .high_precision_offsets_enabled_flag = sps_ext->high_precision_offsets_enabled_flag,
592 .persistent_rice_adaptation_enabled_flag = sps_ext->persistent_rice_adaptation_enabled_flag,
593 .cabac_bypass_alignment_enabled_flag = sps_ext->cabac_bypass_alignment_enabled_flag,
594 .cross_component_prediction_enabled_flag = pps_ext->cross_component_prediction_enabled_flag,
595 .chroma_qp_offset_list_enabled_flag = pps_ext->chroma_qp_offset_list_enabled_flag,
597 .diff_cu_chroma_qp_offset_depth = pps_ext->diff_cu_chroma_qp_offset_depth,
598 .chroma_qp_offset_list_len_minus1 = pps_ext->chroma_qp_offset_list_len_minus1,
599 .log2_sao_offset_scale_luma = pps_ext->log2_sao_offset_scale_luma,
600 .log2_sao_offset_scale_chroma = pps_ext->log2_sao_offset_scale_chroma,
601 .log2_max_transform_skip_block_size_minus2 = pps_ext->log2_max_transform_skip_block_size_minus2,
605 memcpy (pic_param->cb_qp_offset_list, pps_ext->cb_qp_offset_list,
606 sizeof (pic_param->cb_qp_offset_list));
607 memcpy (pic_param->cr_qp_offset_list, pps_ext->cr_qp_offset_list,
608 sizeof (pic_param->cr_qp_offset_list));
612 _fill_screen_content_ext_parameter (GstVaH265Dec * decoder,
613 GstH265SPS * sps, GstH265PPS * pps)
615 VAPictureParameterBufferHEVCScc *pic_param = &decoder->pic_param.scc;
616 const GstH265PPSSccExtensionParams *pps_scc = &pps->pps_scc_extension_params;
617 const GstH265SPSSccExtensionParams *sps_scc = &sps->sps_scc_extension_params;
622 *pic_param = (VAPictureParameterBufferHEVCScc) {
623 .screen_content_pic_fields.bits = {
624 .pps_curr_pic_ref_enabled_flag = pps_scc->pps_curr_pic_ref_enabled_flag,
625 .palette_mode_enabled_flag = sps_scc->palette_mode_enabled_flag,
626 .motion_vector_resolution_control_idc = sps_scc->motion_vector_resolution_control_idc,
627 .intra_boundary_filtering_disabled_flag = sps_scc->intra_boundary_filtering_disabled_flag,
628 .residual_adaptive_colour_transform_enabled_flag = pps_scc->residual_adaptive_colour_transform_enabled_flag,
629 .pps_slice_act_qp_offsets_present_flag = pps_scc->pps_slice_act_qp_offsets_present_flag,
631 .palette_max_size = sps_scc->palette_max_size,
632 .delta_palette_max_predictor_size = sps_scc->delta_palette_max_predictor_size,
633 .pps_act_y_qp_offset_plus5 = pps_scc->pps_act_y_qp_offset_plus5,
634 .pps_act_cb_qp_offset_plus5 = pps_scc->pps_act_cb_qp_offset_plus5,
635 .pps_act_cr_qp_offset_plus3 = pps_scc->pps_act_cr_qp_offset_plus3,
639 /* firstly use the pps, then sps */
640 num_comps = sps->chroma_format_idc ? 3 : 1;
642 if (pps_scc->pps_palette_predictor_initializers_present_flag) {
643 pic_param->predictor_palette_size =
644 pps_scc->pps_num_palette_predictor_initializer;
645 for (n = 0; n < num_comps; n++)
646 for (i = 0; i < pps_scc->pps_num_palette_predictor_initializer; i++)
647 pic_param->predictor_palette_entries[n][i] =
648 (uint16_t) pps_scc->pps_palette_predictor_initializer[n][i];
649 } else if (sps_scc->sps_palette_predictor_initializers_present_flag) {
650 pic_param->predictor_palette_size =
651 sps_scc->sps_num_palette_predictor_initializer_minus1 + 1;
652 for (n = 0; n < num_comps; n++)
654 i < sps_scc->sps_num_palette_predictor_initializer_minus1 + 1; i++)
655 pic_param->predictor_palette_entries[n][i] =
656 (uint16_t) sps_scc->sps_palette_predictor_initializer[n][i];
661 gst_va_h265_dec_start_picture (GstH265Decoder * decoder,
662 GstH265Picture * picture, GstH265Slice * slice, GstH265Dpb * dpb)
666 GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
667 GstVaBaseDec *base = &self->parent;
668 GstVaDecodePicture *va_pic;
669 GstH265ScalingList *scaling_list = NULL;
670 VAIQMatrixBufferHEVC iq_matrix = { 0, };
671 VAPictureParameterBufferHEVCExtension *pic_param = &self->pic_param;
672 gsize pic_param_size;
675 va_pic = gst_h265_picture_get_user_data (picture);
677 pps = slice->header.pps;
681 pic_param->base = (VAPictureParameterBufferHEVC) {
682 .pic_width_in_luma_samples = sps->pic_width_in_luma_samples,
683 .pic_height_in_luma_samples = sps->pic_height_in_luma_samples,
684 .sps_max_dec_pic_buffering_minus1 = sps->max_dec_pic_buffering_minus1[sps->max_sub_layers_minus1],
685 .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8,
686 .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8,
687 .pcm_sample_bit_depth_luma_minus1 = sps->pcm_sample_bit_depth_luma_minus1,
688 .pcm_sample_bit_depth_chroma_minus1 = sps->pcm_sample_bit_depth_chroma_minus1,
689 .log2_min_luma_coding_block_size_minus3 = sps->log2_min_luma_coding_block_size_minus3,
690 .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_luma_coding_block_size,
691 .log2_min_transform_block_size_minus2 = sps->log2_min_transform_block_size_minus2,
692 .log2_diff_max_min_transform_block_size = sps->log2_diff_max_min_transform_block_size,
693 .log2_min_pcm_luma_coding_block_size_minus3 = sps->log2_min_pcm_luma_coding_block_size_minus3,
694 .log2_diff_max_min_pcm_luma_coding_block_size = sps->log2_diff_max_min_pcm_luma_coding_block_size,
695 .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra,
696 .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter,
697 .init_qp_minus26 = pps->init_qp_minus26,
698 .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth,
699 .pps_cb_qp_offset = pps->cb_qp_offset,
700 .pps_cr_qp_offset = pps->cr_qp_offset,
701 .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level_minus2,
702 .num_tile_columns_minus1 = pps->num_tile_columns_minus1,
703 .num_tile_rows_minus1 = pps->num_tile_rows_minus1,
704 .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4,
705 .num_short_term_ref_pic_sets = sps->num_short_term_ref_pic_sets,
706 .num_long_term_ref_pic_sps = sps->num_long_term_ref_pics_sps,
707 .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active_minus1,
708 .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active_minus1,
709 .pps_beta_offset_div2 = pps->beta_offset_div2,
710 .pps_tc_offset_div2 = pps->tc_offset_div2,
711 .num_extra_slice_header_bits = pps->num_extra_slice_header_bits,
712 .st_rps_bits = slice->header.short_term_ref_pic_set_size, /* FIXME missing emulation bits removal */
714 .chroma_format_idc = sps->chroma_format_idc,
715 .separate_colour_plane_flag = sps->separate_colour_plane_flag,
716 .pcm_enabled_flag = sps->pcm_enabled_flag,
717 .scaling_list_enabled_flag = sps->scaling_list_enabled_flag,
718 .transform_skip_enabled_flag = pps->transform_skip_enabled_flag,
719 .amp_enabled_flag = sps->amp_enabled_flag,
720 .strong_intra_smoothing_enabled_flag = sps->strong_intra_smoothing_enabled_flag,
721 .sign_data_hiding_enabled_flag = pps->sign_data_hiding_enabled_flag,
722 .constrained_intra_pred_flag = pps->constrained_intra_pred_flag,
723 .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag,
724 .weighted_pred_flag = pps->weighted_pred_flag,
725 .weighted_bipred_flag = pps->weighted_bipred_flag,
726 .transquant_bypass_enabled_flag = pps->transquant_bypass_enabled_flag,
727 .tiles_enabled_flag = pps->tiles_enabled_flag,
728 .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag,
729 .pps_loop_filter_across_slices_enabled_flag = pps->loop_filter_across_slices_enabled_flag,
730 .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag,
731 .pcm_loop_filter_disabled_flag = sps->pcm_loop_filter_disabled_flag,
732 /* Not set by FFMPEG either */
733 .NoPicReorderingFlag = 0,
736 .slice_parsing_fields.bits = {
737 .lists_modification_present_flag = pps->lists_modification_present_flag,
738 .long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag,
739 .sps_temporal_mvp_enabled_flag = sps->temporal_mvp_enabled_flag,
740 .cabac_init_present_flag = pps->cabac_init_present_flag,
741 .output_flag_present_flag = pps->output_flag_present_flag,
742 .dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag,
743 .pps_slice_chroma_qp_offsets_present_flag = pps->slice_chroma_qp_offsets_present_flag,
744 .sample_adaptive_offset_enabled_flag = sps->sample_adaptive_offset_enabled_flag,
745 .deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag,
746 .pps_disable_deblocking_filter_flag = pps->deblocking_filter_disabled_flag,
747 .slice_segment_header_extension_present_flag = pps->slice_segment_header_extension_present_flag,
748 .RapPicFlag = picture->RapPicFlag,
749 .IdrPicFlag = GST_H265_IS_NAL_TYPE_IDR (slice->nalu.type),
750 .IntraPicFlag = GST_H265_IS_NAL_TYPE_IRAP (slice->nalu.type),
755 if (_is_range_extension_profile (self->parent.profile)
756 || _is_screen_content_ext_profile (self->parent.profile)) {
757 _fill_picture_range_ext_parameter (self, sps, pps);
758 if (_is_screen_content_ext_profile (self->parent.profile))
759 _fill_screen_content_ext_parameter (self, sps, pps);
762 for (i = 0; i <= pps->num_tile_columns_minus1; i++)
763 pic_param->base.column_width_minus1[i] = pps->column_width_minus1[i];
765 for (i = 0; i <= pps->num_tile_rows_minus1; i++)
766 pic_param->base.row_height_minus1[i] = pps->row_height_minus1[i];
768 _fill_vaapi_pic (decoder, &pic_param->base.CurrPic, picture);
770 /* reference frames */
772 GArray *ref_list = gst_h265_dpb_get_pictures_all (dpb);
776 for (j = 0; j < 15 && j < ref_list->len; j++) {
777 GstH265Picture *pic = g_array_index (ref_list, GstH265Picture *, j);
780 _fill_vaapi_pic (decoder, &pic_param->base.ReferenceFrames[i], pic);
784 g_array_unref (ref_list);
786 /* 7.4.3.3.3, the current decoded picture is marked as "used for
787 long-term reference". Current picture is not in the DPB now. */
788 if (pps->pps_scc_extension_params.pps_curr_pic_ref_enabled_flag && i < 15) {
789 pic_param->base.ReferenceFrames[i].picture_id =
790 gst_va_decode_picture_get_surface (gst_h265_picture_get_user_data
792 pic_param->base.ReferenceFrames[i].pic_order_cnt = picture->pic_order_cnt;
793 pic_param->base.ReferenceFrames[i].flags |=
794 VA_PICTURE_HEVC_LONG_TERM_REFERENCE;
795 pic_param->base.ReferenceFrames[i].flags |=
796 _find_frame_rps_type (decoder, picture);
801 _init_vaapi_pic (&pic_param->base.ReferenceFrames[i]);
804 pic_param_size = _is_range_extension_profile (self->parent.profile)
805 || _is_screen_content_ext_profile (self->parent.profile) ?
806 sizeof (*pic_param) : sizeof (pic_param->base);
807 if (!gst_va_decoder_add_param_buffer (base->decoder, va_pic,
808 VAPictureParameterBufferType, pic_param, pic_param_size))
809 return GST_FLOW_ERROR;
811 if (pps->scaling_list_data_present_flag ||
812 (sps->scaling_list_enabled_flag
813 && !sps->scaling_list_data_present_flag)) {
814 scaling_list = &pps->scaling_list;
815 GST_DEBUG_OBJECT (decoder, "Passing scaling list from PPS");
816 } else if (sps->scaling_list_enabled_flag &&
817 sps->scaling_list_data_present_flag) {
818 scaling_list = &sps->scaling_list;
819 GST_DEBUG_OBJECT (decoder, "Passing scaling list from SPS");
823 for (i = 0; i < G_N_ELEMENTS (iq_matrix.ScalingList4x4); i++)
824 gst_h265_quant_matrix_4x4_get_raster_from_uprightdiagonal
825 (iq_matrix.ScalingList4x4[i], scaling_list->scaling_lists_4x4[i]);
827 for (i = 0; i < G_N_ELEMENTS (iq_matrix.ScalingList8x8); i++)
828 gst_h265_quant_matrix_8x8_get_raster_from_uprightdiagonal
829 (iq_matrix.ScalingList8x8[i], scaling_list->scaling_lists_8x8[i]);
831 for (i = 0; i < G_N_ELEMENTS (iq_matrix.ScalingList16x16); i++)
832 gst_h265_quant_matrix_16x16_get_raster_from_uprightdiagonal
833 (iq_matrix.ScalingList16x16[i], scaling_list->scaling_lists_16x16[i]);
835 for (i = 0; i < G_N_ELEMENTS (iq_matrix.ScalingList32x32); i++)
836 gst_h265_quant_matrix_32x32_get_raster_from_uprightdiagonal
837 (iq_matrix.ScalingList32x32[i], scaling_list->scaling_lists_32x32[i]);
839 for (i = 0; i < 6; i++)
840 iq_matrix.ScalingListDC16x16[i] =
841 scaling_list->scaling_list_dc_coef_minus8_16x16[i] + 8;
843 for (i = 0; i < 2; i++)
844 iq_matrix.ScalingListDC32x32[i] =
845 scaling_list->scaling_list_dc_coef_minus8_32x32[i] + 8;
847 if (!gst_va_decoder_add_param_buffer (base->decoder, va_pic,
848 VAIQMatrixBufferType, &iq_matrix, sizeof (iq_matrix))) {
849 return GST_FLOW_ERROR;
857 gst_va_h265_dec_new_picture (GstH265Decoder * decoder,
858 GstVideoCodecFrame * frame, GstH265Picture * picture)
860 GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
861 GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
862 GstVaDecodePicture *pic;
863 GstBuffer *output_buffer;
864 GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
866 if (base->need_negotiation) {
867 if (!gst_video_decoder_negotiate (vdec)) {
868 GST_ERROR_OBJECT (self, "Failed to negotiate with downstream");
869 return GST_FLOW_NOT_NEGOTIATED;
873 output_buffer = gst_video_decoder_allocate_output_buffer (vdec);
874 if (!output_buffer) {
875 self->last_ret = GST_FLOW_ERROR;
878 self->last_ret = GST_FLOW_OK;
880 pic = gst_va_decode_picture_new (base->decoder, output_buffer);
881 gst_buffer_unref (output_buffer);
883 gst_h265_picture_set_user_data (picture, pic,
884 (GDestroyNotify) gst_va_decode_picture_free);
886 GST_LOG_OBJECT (self, "New va decode picture %p - %#x", pic,
887 gst_va_decode_picture_get_surface (pic));
893 GST_WARNING_OBJECT (self,
894 "Failed to allocated output buffer, return %s",
895 gst_flow_get_name (self->last_ret));
896 return self->last_ret;
901 _get_rtformat (GstVaH265Dec * self, guint8 bit_depth_luma,
902 guint8 bit_depth_chroma, guint8 chroma_format_idc)
904 guint8 bit_num = MAX (bit_depth_luma, bit_depth_chroma);
909 if (chroma_format_idc == 3)
910 return VA_RT_FORMAT_YUV444_12;
911 if (chroma_format_idc == 2)
912 return VA_RT_FORMAT_YUV422_12;
914 return VA_RT_FORMAT_YUV420_12;
918 if (chroma_format_idc == 3)
919 return VA_RT_FORMAT_YUV444_10;
920 if (chroma_format_idc == 2)
921 return VA_RT_FORMAT_YUV422_10;
923 return VA_RT_FORMAT_YUV420_10;
926 if (chroma_format_idc == 3)
927 return VA_RT_FORMAT_YUV444;
928 if (chroma_format_idc == 2)
929 return VA_RT_FORMAT_YUV422;
931 return VA_RT_FORMAT_YUV420;
934 GST_ERROR_OBJECT (self, "Unsupported chroma format: %d "
935 "(with depth luma: %d, with depth chroma: %d)",
936 chroma_format_idc, bit_depth_luma, bit_depth_chroma);
944 GstH265Profile profile;
945 VAProfile va_profile;
947 #define P(idc, va) { G_PASTE (GST_H265_PROFILE_, idc), G_PASTE (VAProfileHEVC, va) }
950 /*P (MAIN_STILL_PICTURE, ),
953 P (MONOCHROME_16, ),*/
955 P (MAIN_422_10, Main422_10),
956 P (MAIN_422_12, Main422_12),
957 P (MAIN_444, Main444),
958 P (MAIN_444_10, Main444_10),
959 P (MAIN_444_12, Main444_12),
963 P (MAIN_422_10_INTRA, ),
964 P (MAIN_422_12_INTRA, ),
965 P (MAIN_444_INTRA, ),
966 P (MAIN_444_10_INTRA, ),
967 P (MAIN_444_12_INTRA, ),
968 P (MAIN_444_16_INTRA, ),
969 P (MAIN_444_STILL_PICTURE, ),
970 P (MAIN_444_16_STILL_PICTURE, ),
972 P (HIGH_THROUGHPUT_444, ),
973 P (HIGH_THROUGHPUT_444_10, ),
974 P (HIGH_THROUGHPUT_444_14, ),
975 P (HIGH_THROUGHPUT_444_16_INTRA, ),*/
976 P (SCREEN_EXTENDED_MAIN, SccMain),
977 P (SCREEN_EXTENDED_MAIN_10, SccMain10),
978 P (SCREEN_EXTENDED_MAIN_444, SccMain444),
979 #if VA_CHECK_VERSION(1, 8, 0)
980 P (SCREEN_EXTENDED_MAIN_444_10, SccMain444_10),
982 /*P (SCREEN_EXTENDED_HIGH_THROUGHPUT_444, ),
983 P (SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10, ),
984 P (SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14, ),
985 P (MULTIVIEW_MAIN, ),
987 P (SCALABLE_MAIN_10, ),
988 P (SCALABLE_MONOCHROME, ),
989 P (SCALABLE_MONOCHROME_12, ),
990 P (SCALABLE_MONOCHROME_16, ),
991 P (SCALABLE_MAIN_444, ),
998 _get_profile (GstVaH265Dec * self, const GstH265SPS * sps, gint max_dpb_size)
1000 GstH265Decoder *h265_decoder = GST_H265_DECODER (self);
1001 GstVaBaseDec *base = GST_VA_BASE_DEC (self);
1002 GstH265Profile profile = gst_h265_get_profile_from_sps ((GstH265SPS *) sps);
1003 VAProfile profiles[4];
1006 /* 1. The profile directly specified by the SPS should always be the
1007 first choice. It is the exact one.
1008 2. The profile in the input caps may contain the compatible profile
1009 chosen by the upstream element. Upstream element such as the parse
1010 may already decide the best compatible profile for us. We also need
1011 to consider it as a choice. */
1013 for (j = 0; j < G_N_ELEMENTS (profile_map); j++) {
1014 if (profile_map[j].profile == profile) {
1015 profiles[i++] = profile_map[j].va_profile;
1020 if (h265_decoder->input_state->caps
1021 && gst_caps_is_fixed (h265_decoder->input_state->caps)) {
1022 GstH265Profile compatible_profile = GST_H265_PROFILE_INVALID;
1023 GstStructure *structure;
1024 const gchar *profile_str;
1026 structure = gst_caps_get_structure (h265_decoder->input_state->caps, 0);
1028 profile_str = gst_structure_get_string (structure, "profile");
1030 compatible_profile = gst_h265_profile_from_string (profile_str);
1032 if (compatible_profile != profile) {
1033 GST_INFO_OBJECT (self, "The upstream set the compatible profile %s, "
1034 "also consider it as a candidate.", profile_str);
1036 for (j = 0; j < G_N_ELEMENTS (profile_map); j++) {
1037 if (profile_map[j].profile == compatible_profile) {
1038 profiles[i++] = profile_map[j].va_profile;
1045 for (j = 0; j < i && j < G_N_ELEMENTS (profiles); j++) {
1046 if (gst_va_decoder_has_profile (base->decoder, profiles[j]))
1050 GST_ERROR_OBJECT (self, "Unsupported profile: %d", profile);
1052 return VAProfileNone;
1055 static GstFlowReturn
1056 gst_va_h265_dec_new_sequence (GstH265Decoder * decoder, const GstH265SPS * sps,
1059 GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
1060 GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
1063 gint display_height;
1064 gint padding_left, padding_right, padding_top, padding_bottom;
1066 gboolean negotiation_needed = FALSE;
1068 if (self->dpb_size < max_dpb_size)
1069 self->dpb_size = max_dpb_size;
1071 if (sps->conformance_window_flag) {
1072 display_width = sps->crop_rect_width;
1073 display_height = sps->crop_rect_height;
1074 padding_left = sps->crop_rect_x;
1075 padding_right = sps->width - sps->crop_rect_x - display_width;
1076 padding_top = sps->crop_rect_y;
1077 padding_bottom = sps->height - sps->crop_rect_y - display_height;
1079 display_width = sps->width;
1080 display_height = sps->height;
1081 padding_left = padding_right = padding_top = padding_bottom = 0;
1084 profile = _get_profile (self, sps, max_dpb_size);
1085 if (profile == VAProfileNone)
1086 return GST_FLOW_NOT_NEGOTIATED;
1088 rt_format = _get_rtformat (self, sps->bit_depth_luma_minus8 + 8,
1089 sps->bit_depth_chroma_minus8 + 8, sps->chroma_format_idc);
1091 return GST_FLOW_NOT_NEGOTIATED;
1093 if (!gst_va_decoder_config_is_equal (base->decoder, profile,
1094 rt_format, sps->width, sps->height)) {
1095 base->profile = profile;
1096 base->rt_format = rt_format;
1097 self->coded_width = sps->width;
1098 self->coded_height = sps->height;
1100 negotiation_needed = TRUE;
1101 GST_INFO_OBJECT (self, "Format changed to %s [%x] (%dx%d)",
1102 gst_va_profile_name (profile), rt_format, self->coded_width,
1103 self->coded_height);
1106 if (base->width != display_width || base->height != display_height) {
1107 base->width = display_width;
1108 base->height = display_height;
1110 negotiation_needed = TRUE;
1111 GST_INFO_OBJECT (self, "Resolution changed to %dx%d", base->width,
1115 base->need_valign = base->width < self->coded_width
1116 || base->height < self->coded_height;
1117 if (base->need_valign) {
1119 if (base->valign.padding_left != padding_left ||
1120 base->valign.padding_right != padding_right ||
1121 base->valign.padding_top != padding_top ||
1122 base->valign.padding_bottom != padding_bottom) {
1123 negotiation_needed = TRUE;
1124 GST_INFO_OBJECT (self, "crop rect changed to (%d,%d)-->(%d,%d)",
1125 padding_left, padding_top, padding_right, padding_bottom);
1127 base->valign = (GstVideoAlignment) {
1128 .padding_left = padding_left,
1129 .padding_right = padding_right,
1130 .padding_top = padding_top,
1131 .padding_bottom = padding_bottom,
1136 base->min_buffers = self->dpb_size + 4; /* dpb size + scratch surfaces */
1138 base->need_negotiation = negotiation_needed;
1141 /* FIXME: We don't have parser API for sps_range_extension, so
1142 * assuming high_precision_offsets_enabled_flag as zero */
1143 guint high_precision_offsets_enabled_flag = 0, bitdepthC = 0;
1145 /* Calculate WpOffsetHalfRangeC: (7-34) */
1146 bitdepthC = sps->bit_depth_chroma_minus8 + 8;
1147 self->WpOffsetHalfRangeC =
1148 1 << (high_precision_offsets_enabled_flag ? (bitdepthC - 1) : 7);
1155 _complete_sink_caps (GstCaps * sinkcaps)
1157 GstCaps *caps = gst_caps_copy (sinkcaps);
1158 GValue val = G_VALUE_INIT;
1159 const gchar *streamformat[] = { "hvc1", "hev1", "byte-stream" };
1162 g_value_init (&val, G_TYPE_STRING);
1163 g_value_set_string (&val, "au");
1164 gst_caps_set_value (caps, "alignment", &val);
1165 g_value_unset (&val);
1167 gst_value_list_init (&val, G_N_ELEMENTS (streamformat));
1168 for (i = 0; i < G_N_ELEMENTS (streamformat); i++) {
1169 GValue v = G_VALUE_INIT;
1171 g_value_init (&v, G_TYPE_STRING);
1172 g_value_set_string (&v, streamformat[i]);
1173 gst_value_list_append_value (&val, &v);
1176 gst_caps_set_value (caps, "stream-format", &val);
1177 g_value_unset (&val);
1183 gst_va_h265_dec_getcaps (GstVideoDecoder * decoder, GstCaps * filter)
1185 GstCaps *sinkcaps, *caps = NULL, *tmp;
1186 GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
1189 caps = gst_va_decoder_get_sinkpad_caps (base->decoder);
1192 sinkcaps = _complete_sink_caps (caps);
1193 gst_caps_unref (caps);
1195 tmp = gst_caps_intersect_full (filter, sinkcaps,
1196 GST_CAPS_INTERSECT_FIRST);
1197 gst_caps_unref (sinkcaps);
1202 GST_LOG_OBJECT (base, "Returning caps %" GST_PTR_FORMAT, caps);
1204 caps = gst_video_decoder_proxy_getcaps (decoder, NULL, filter);
1211 gst_va_h265_dec_negotiate (GstVideoDecoder * decoder)
1213 GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
1214 GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
1215 GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
1216 GstCapsFeatures *capsfeatures = NULL;
1217 GstH265Decoder *h265dec = GST_H265_DECODER (decoder);
1219 /* Ignore downstream renegotiation request. */
1220 if (!base->need_negotiation)
1223 base->need_negotiation = FALSE;
1225 if (gst_va_decoder_is_open (base->decoder)
1226 && !gst_va_decoder_close (base->decoder))
1229 if (!gst_va_decoder_open (base->decoder, base->profile, base->rt_format))
1232 if (!gst_va_decoder_set_frame_size (base->decoder, self->coded_width,
1233 self->coded_height))
1236 if (base->output_state)
1237 gst_video_codec_state_unref (base->output_state);
1239 gst_va_base_dec_get_preferred_format_and_caps_features (base, &format,
1241 if (format == GST_VIDEO_FORMAT_UNKNOWN)
1244 base->output_state =
1245 gst_video_decoder_set_output_state (decoder, format,
1246 base->width, base->height, h265dec->input_state);
1248 base->output_state->caps = gst_video_info_to_caps (&base->output_state->info);
1250 gst_caps_set_features_simple (base->output_state->caps, capsfeatures);
1252 GST_INFO_OBJECT (self, "Negotiated caps %" GST_PTR_FORMAT,
1253 base->output_state->caps);
1255 return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
1259 gst_va_h265_dec_dispose (GObject * object)
1261 g_free (GST_VA_H265_DEC (object)->prev_slice.data);
1263 gst_va_base_dec_close (GST_VIDEO_DECODER (object));
1265 G_OBJECT_CLASS (parent_class)->dispose (object);
1269 gst_va_h265_dec_class_init (gpointer g_class, gpointer class_data)
1271 GstCaps *src_doc_caps, *sink_doc_caps;
1272 GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
1273 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
1274 GstH265DecoderClass *h265decoder_class = GST_H265_DECODER_CLASS (g_class);
1275 GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (g_class);
1276 struct CData *cdata = class_data;
1279 if (cdata->description) {
1280 long_name = g_strdup_printf ("VA-API H.265 Decoder in %s",
1281 cdata->description);
1283 long_name = g_strdup ("VA-API H.265 Decoder");
1286 gst_element_class_set_metadata (element_class, long_name,
1287 "Codec/Decoder/Video/Hardware",
1288 "VA-API based H.265 video decoder",
1289 "Nicolas Dufresne <nicolas.dufresne@collabora.com>");
1291 sink_doc_caps = gst_caps_from_string (sink_caps_str);
1292 src_doc_caps = gst_caps_from_string (src_caps_str);
1294 parent_class = g_type_class_peek_parent (g_class);
1297 * GstVaH265Dec:device-path:
1299 * It shows the DRM device path used for the VA operation, if any.
1303 gst_va_base_dec_class_init (GST_VA_BASE_DEC_CLASS (g_class), HEVC,
1304 cdata->render_device_path, cdata->sink_caps, cdata->src_caps,
1305 src_doc_caps, sink_doc_caps);
1307 gobject_class->dispose = gst_va_h265_dec_dispose;
1309 decoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_va_h265_dec_getcaps);
1310 decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_va_h265_dec_negotiate);
1312 h265decoder_class->new_sequence =
1313 GST_DEBUG_FUNCPTR (gst_va_h265_dec_new_sequence);
1314 h265decoder_class->decode_slice =
1315 GST_DEBUG_FUNCPTR (gst_va_h265_dec_decode_slice);
1317 h265decoder_class->new_picture =
1318 GST_DEBUG_FUNCPTR (gst_va_h265_dec_new_picture);
1319 h265decoder_class->output_picture =
1320 GST_DEBUG_FUNCPTR (gst_va_h265_dec_output_picture);
1321 h265decoder_class->start_picture =
1322 GST_DEBUG_FUNCPTR (gst_va_h265_dec_start_picture);
1323 h265decoder_class->end_picture =
1324 GST_DEBUG_FUNCPTR (gst_va_h265_dec_end_picture);
1327 g_free (cdata->description);
1328 g_free (cdata->render_device_path);
1329 gst_caps_unref (cdata->src_caps);
1330 gst_caps_unref (cdata->sink_caps);
1335 gst_va_h265_dec_init (GTypeInstance * instance, gpointer g_class)
1337 gst_va_base_dec_init (GST_VA_BASE_DEC (instance), GST_CAT_DEFAULT);
1338 gst_h265_decoder_set_process_ref_pic_lists (GST_H265_DECODER (instance),
1343 _register_debug_category (gpointer data)
1345 GST_DEBUG_CATEGORY_INIT (gst_va_h265dec_debug, "vah265dec", 0,
1352 gst_va_h265_dec_register (GstPlugin * plugin, GstVaDevice * device,
1353 GstCaps * sink_caps, GstCaps * src_caps, guint rank)
1355 static GOnce debug_once = G_ONCE_INIT;
1357 GTypeInfo type_info = {
1358 .class_size = sizeof (GstVaH265DecClass),
1359 .class_init = gst_va_h265_dec_class_init,
1360 .instance_size = sizeof (GstVaH265Dec),
1361 .instance_init = gst_va_h265_dec_init,
1363 struct CData *cdata;
1365 gchar *type_name, *feature_name;
1367 g_return_val_if_fail (GST_IS_PLUGIN (plugin), FALSE);
1368 g_return_val_if_fail (GST_IS_VA_DEVICE (device), FALSE);
1369 g_return_val_if_fail (GST_IS_CAPS (sink_caps), FALSE);
1370 g_return_val_if_fail (GST_IS_CAPS (src_caps), FALSE);
1372 cdata = g_new (struct CData, 1);
1373 cdata->description = NULL;
1374 cdata->render_device_path = g_strdup (device->render_device_path);
1375 cdata->sink_caps = _complete_sink_caps (sink_caps);
1376 cdata->src_caps = gst_caps_ref (src_caps);
1378 /* class data will be leaked if the element never gets instantiated */
1379 GST_MINI_OBJECT_FLAG_SET (cdata->sink_caps,
1380 GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
1381 GST_MINI_OBJECT_FLAG_SET (src_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
1383 type_info.class_data = cdata;
1385 /* The first decoder to be registered should use a constant name,
1386 * like vah265dec, for any additional decoders, we create unique
1387 * names, using inserting the render device name. */
1388 if (device->index == 0) {
1389 type_name = g_strdup ("GstVaH265Dec");
1390 feature_name = g_strdup ("vah265dec");
1392 gchar *basename = g_path_get_basename (device->render_device_path);
1393 type_name = g_strdup_printf ("GstVa%sH265Dec", basename);
1394 feature_name = g_strdup_printf ("va%sh265dec", basename);
1395 cdata->description = basename;
1397 /* lower rank for non-first device */
1402 g_once (&debug_once, _register_debug_category, NULL);
1404 type = g_type_register_static (GST_TYPE_H265_DECODER,
1405 type_name, &type_info, 0);
1407 ret = gst_element_register (plugin, feature_name, rank, type);
1410 g_free (feature_name);