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;
93 VAPictureParameterBufferHEVCExtension pic_param;
95 gint32 WpOffsetHalfRangeC;
97 struct slice prev_slice;
100 static GstElementClass *parent_class = NULL;
103 static const gchar *src_caps_str =
104 GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_VA,
105 "{ NV12, P010_10LE }") " ;"
106 GST_VIDEO_CAPS_MAKE ("{ NV12, P010_10LE }");
109 static const gchar *sink_caps_str = "video/x-h265";
112 _is_range_extension_profile (VAProfile profile)
114 if (profile == VAProfileHEVCMain422_10
115 || profile == VAProfileHEVCMain444
116 || profile == VAProfileHEVCMain444_10
117 || profile == VAProfileHEVCMain12
118 || profile == VAProfileHEVCMain444_12
119 || profile == VAProfileHEVCMain422_12)
125 _is_screen_content_ext_profile (VAProfile profile)
127 if (profile == VAProfileHEVCSccMain || profile == VAProfileHEVCSccMain10
128 || profile == VAProfileHEVCSccMain444
129 #if VA_CHECK_VERSION(1, 8, 0)
130 || profile == VAProfileHEVCSccMain444_10
139 _set_last_slice_flag (GstVaH265Dec * self)
141 self->prev_slice.param.base.LongSliceFlags.fields.LastSliceOfPic = 1;
145 _replace_previous_slice (GstVaH265Dec * self, guint8 * data, guint size)
147 struct slice *slice = &self->prev_slice;
148 gboolean do_reset = (slice->size < size);
150 if (!data || do_reset) {
151 g_clear_pointer (&slice->data, g_free);
159 GST_LOG_OBJECT (self, "allocating slice data %u", size);
160 slice->data = g_malloc (size);
163 memcpy (slice->data, data, size);
168 _submit_previous_slice (GstVaBaseDec * base, GstVaDecodePicture * va_pic)
170 GstVaH265Dec *self = GST_VA_H265_DEC (base);
175 slice = &self->prev_slice;
176 if (!slice->data && slice->size == 0)
178 if (!slice->data || slice->size == 0)
181 param_size = _is_range_extension_profile (self->parent.profile)
182 || _is_screen_content_ext_profile (self->parent.profile) ?
183 sizeof (slice->param) : sizeof (slice->param.base);
184 ret = gst_va_decoder_add_slice_buffer (base->decoder, va_pic, &slice->param,
185 param_size, slice->data, slice->size);
191 gst_va_h265_dec_end_picture (GstH265Decoder * decoder, GstH265Picture * picture)
193 GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
194 GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
195 GstVaDecodePicture *va_pic;
198 GST_LOG_OBJECT (base, "end picture %p, (poc %d)",
199 picture, picture->pic_order_cnt);
201 va_pic = gst_h265_picture_get_user_data (picture);
203 _set_last_slice_flag (self);
204 ret = _submit_previous_slice (base, va_pic);
206 /* TODO(victor): optimization: this could be done at decoder's
208 _replace_previous_slice (self, NULL, 0);
211 GST_ERROR_OBJECT (self, "Failed to submit the previous slice");
212 return GST_FLOW_ERROR;
215 ret = gst_va_decoder_decode (base->decoder, va_pic);
217 GST_ERROR_OBJECT (self, "Failed at end picture %p, (poc %d)",
218 picture, picture->pic_order_cnt);
219 return GST_FLOW_ERROR;
226 gst_va_h265_dec_output_picture (GstH265Decoder * decoder,
227 GstVideoCodecFrame * frame, GstH265Picture * picture)
229 GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
230 GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
231 GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
232 GstVaDecodePicture *va_pic;
235 va_pic = gst_h265_picture_get_user_data (picture);
236 g_assert (va_pic->gstbuffer);
238 GST_LOG_OBJECT (self,
239 "Outputting picture %p (poc %d)", picture, picture->pic_order_cnt);
241 gst_buffer_replace (&frame->output_buffer, va_pic->gstbuffer);
243 ret = gst_va_base_dec_process_output (base, frame, picture->discont_state,
244 picture->buffer_flags);
245 gst_h265_picture_unref (picture);
248 return gst_video_decoder_finish_frame (vdec, frame);
249 return GST_FLOW_ERROR;
253 _init_vaapi_pic (VAPictureHEVC * va_picture)
255 va_picture->picture_id = VA_INVALID_ID;
256 va_picture->flags = VA_PICTURE_HEVC_INVALID;
257 va_picture->pic_order_cnt = 0;
261 _find_frame_rps_type (GstH265Decoder * decoder, GstH265Picture * ref_pic)
265 for (i = 0; i < G_N_ELEMENTS (decoder->RefPicSetStCurrBefore); i++) {
266 if (ref_pic == decoder->RefPicSetStCurrBefore[i])
267 return VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE;
270 for (i = 0; i < G_N_ELEMENTS (decoder->RefPicSetStCurrAfter); i++) {
271 if (ref_pic == decoder->RefPicSetStCurrAfter[i])
272 return VA_PICTURE_HEVC_RPS_ST_CURR_AFTER;
275 for (i = 0; i < G_N_ELEMENTS (decoder->RefPicSetLtCurr); i++) {
276 if (ref_pic == decoder->RefPicSetLtCurr[i])
277 return VA_PICTURE_HEVC_RPS_LT_CURR;
285 _fill_vaapi_pic (GstH265Decoder * decoder, VAPictureHEVC * va_picture,
286 GstH265Picture * picture)
288 GstVaDecodePicture *va_pic;
290 va_pic = gst_h265_picture_get_user_data (picture);
293 _init_vaapi_pic (va_picture);
297 va_picture->picture_id = gst_va_decode_picture_get_surface (va_pic);
298 va_picture->pic_order_cnt = picture->pic_order_cnt;
299 va_picture->flags = 0;
301 if (picture->ref && picture->long_term)
302 va_picture->flags |= VA_PICTURE_HEVC_LONG_TERM_REFERENCE;
304 va_picture->flags |= _find_frame_rps_type (decoder, picture);
308 _get_reference_index (GstH265Decoder * decoder, GstH265Picture * picture)
310 GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
316 for (i = 0; i < 15; i++) {
317 VAPictureHEVC *ref_va_pic = &self->pic_param.base.ReferenceFrames[i];
319 if (ref_va_pic->picture_id == VA_INVALID_ID)
322 if (ref_va_pic->pic_order_cnt == picture->pic_order_cnt)
329 /* fill the VA API reference picture lists from the GstCodec reference
332 _fill_ref_pic_list (GstH265Decoder * decoder, GstH265Picture * cur_pic,
333 guint8 va_reflist[15], GArray * reflist)
337 for (i = 0; i < reflist->len && i < 15; i++) {
338 GstH265Picture *picture = g_array_index (reflist, GstH265Picture *, i);
339 va_reflist[i] = _get_reference_index (decoder, picture);
343 va_reflist[i] = 0xFF;
347 _fill_pred_weight_table (GstVaH265Dec * self, GstH265SliceHdr * header,
348 VASliceParameterBufferHEVCExtension * slice_param)
350 gint chroma_weight, chroma_log2_weight_denom;
352 GstH265PPS *pps = header->pps;
353 gboolean is_rext = _is_range_extension_profile (self->parent.profile);
355 if (GST_H265_IS_I_SLICE (header) ||
356 (!pps->weighted_pred_flag && GST_H265_IS_P_SLICE (header)) ||
357 (!pps->weighted_bipred_flag && GST_H265_IS_B_SLICE (header)))
360 slice_param->base.luma_log2_weight_denom =
361 header->pred_weight_table.luma_log2_weight_denom;
363 if (pps->sps->chroma_array_type != 0)
364 slice_param->base.delta_chroma_log2_weight_denom =
365 header->pred_weight_table.delta_chroma_log2_weight_denom;
367 for (i = 0; i <= header->num_ref_idx_l0_active_minus1; i++) {
368 if (!header->pred_weight_table.luma_weight_l0_flag[i])
371 slice_param->base.delta_luma_weight_l0[i] =
372 header->pred_weight_table.delta_luma_weight_l0[i];
373 slice_param->base.luma_offset_l0[i] =
374 header->pred_weight_table.luma_offset_l0[i];
377 slice_param->rext.luma_offset_l0[i] =
378 header->pred_weight_table.luma_offset_l0[i];
382 chroma_log2_weight_denom = slice_param->base.luma_log2_weight_denom +
383 slice_param->base.delta_chroma_log2_weight_denom;
385 for (i = 0; i <= header->num_ref_idx_l0_active_minus1; i++) {
386 if (!header->pred_weight_table.chroma_weight_l0_flag[i])
389 for (j = 0; j < 2; j++) {
390 gint16 delta_chroma_offset_l0 =
391 header->pred_weight_table.delta_chroma_offset_l0[i][j];
394 slice_param->base.delta_chroma_weight_l0[i][j] =
395 header->pred_weight_table.delta_chroma_weight_l0[i][j];
397 /* Find ChromaWeightL0 */
398 chroma_weight = (1 << chroma_log2_weight_denom) +
399 header->pred_weight_table.delta_chroma_weight_l0[i][j];
400 chroma_offset = self->WpOffsetHalfRangeC + delta_chroma_offset_l0
401 - ((self->WpOffsetHalfRangeC * chroma_weight)
402 >> chroma_log2_weight_denom);
405 slice_param->base.ChromaOffsetL0[i][j] = CLAMP (chroma_offset,
406 -self->WpOffsetHalfRangeC, self->WpOffsetHalfRangeC - 1);
409 slice_param->rext.ChromaOffsetL0[i][j] =
410 slice_param->base.ChromaOffsetL0[i][j];
415 /* Skip l1 if this is not a B-Frame. */
416 if (!GST_H265_IS_B_SLICE (header))
419 for (i = 0; i <= header->num_ref_idx_l1_active_minus1; i++) {
420 if (!header->pred_weight_table.luma_weight_l1_flag[i])
423 slice_param->base.delta_luma_weight_l1[i] =
424 header->pred_weight_table.delta_luma_weight_l1[i];
425 slice_param->base.luma_offset_l1[i] =
426 header->pred_weight_table.luma_offset_l1[i];
429 slice_param->rext.luma_offset_l1[i] =
430 header->pred_weight_table.luma_offset_l1[i];
434 for (i = 0; i <= header->num_ref_idx_l1_active_minus1; i++) {
435 if (!header->pred_weight_table.chroma_weight_l1_flag[i])
438 for (j = 0; j < 2; j++) {
439 gint16 delta_chroma_offset_l1 =
440 header->pred_weight_table.delta_chroma_offset_l1[i][j];
443 slice_param->base.delta_chroma_weight_l1[i][j] =
444 header->pred_weight_table.delta_chroma_weight_l1[i][j];
446 /* Find ChromaWeightL1 */
447 chroma_weight = (1 << chroma_log2_weight_denom) +
448 header->pred_weight_table.delta_chroma_weight_l1[i][j];
450 chroma_offset = self->WpOffsetHalfRangeC + delta_chroma_offset_l1
451 - ((self->WpOffsetHalfRangeC * chroma_weight)
452 >> chroma_log2_weight_denom);
455 slice_param->base.ChromaOffsetL1[i][j] = CLAMP (chroma_offset,
456 -self->WpOffsetHalfRangeC, self->WpOffsetHalfRangeC - 1);
459 slice_param->rext.ChromaOffsetL1[i][j] =
460 slice_param->base.ChromaOffsetL1[i][j];
467 _get_slice_data_byte_offset (GstH265SliceHdr * slice_hdr,
468 guint nal_header_bytes)
472 epb_count = slice_hdr->n_emulation_prevention_bytes;
473 return nal_header_bytes + (slice_hdr->header_size + 7) / 8 - epb_count;
477 gst_va_h265_dec_decode_slice (GstH265Decoder * decoder,
478 GstH265Picture * picture, GstH265Slice * slice, GArray * ref_pic_list0,
479 GArray * ref_pic_list1)
481 GstH265SliceHdr *header = &slice->header;
482 GstH265NalUnit *nalu = &slice->nalu;
483 GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
484 GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
485 GstVaDecodePicture *va_pic;
486 VASliceParameterBufferHEVCExtension *slice_param;
488 va_pic = gst_h265_picture_get_user_data (picture);
489 if (!_submit_previous_slice (base, va_pic)) {
490 _replace_previous_slice (self, NULL, 0);
491 GST_ERROR_OBJECT (base, "Failed to submit previous slice buffers");
492 return GST_FLOW_ERROR;
495 slice_param = &self->prev_slice.param;
498 slice_param->base = (VASliceParameterBufferHEVC) {
499 .slice_data_size = nalu->size,
500 .slice_data_offset = 0,
501 .slice_data_flag = VA_SLICE_DATA_FLAG_ALL,
502 .slice_data_byte_offset = _get_slice_data_byte_offset (header, nalu->header_bytes),
503 .slice_segment_address = header->segment_address,
504 .collocated_ref_idx = header->temporal_mvp_enabled_flag ? header->collocated_ref_idx : 0xFF,
505 .num_ref_idx_l0_active_minus1 = header->num_ref_idx_l0_active_minus1,
506 .num_ref_idx_l1_active_minus1 = header->num_ref_idx_l1_active_minus1,
507 .slice_qp_delta = header->qp_delta,
508 .slice_cb_qp_offset = header->cb_qp_offset,
509 .slice_cr_qp_offset = header->cr_qp_offset,
510 .slice_beta_offset_div2 = header->beta_offset_div2,
511 .slice_tc_offset_div2 = header->tc_offset_div2,
512 .five_minus_max_num_merge_cand = header->five_minus_max_num_merge_cand,
513 .num_entry_point_offsets = header->num_entry_point_offsets,
514 .entry_offset_to_subset_array = 0, /* does not exist in spec */
515 .slice_data_num_emu_prevn_bytes = header->n_emulation_prevention_bytes,
516 .LongSliceFlags.fields = {
517 .LastSliceOfPic = 0, /* the last one will be set on end_picture() */
518 .dependent_slice_segment_flag = header->dependent_slice_segment_flag,
519 .slice_type = header->type,
520 .color_plane_id = header->colour_plane_id,
521 .slice_sao_luma_flag = header->sao_luma_flag,
522 .slice_sao_chroma_flag = header->sao_chroma_flag,
523 .mvd_l1_zero_flag = header->mvd_l1_zero_flag,
524 .cabac_init_flag = header->cabac_init_flag,
525 .slice_temporal_mvp_enabled_flag = header->temporal_mvp_enabled_flag,
526 .slice_deblocking_filter_disabled_flag =
527 header->deblocking_filter_disabled_flag,
528 .collocated_from_l0_flag = header->collocated_from_l0_flag,
529 .slice_loop_filter_across_slices_enabled_flag =
530 header->loop_filter_across_slices_enabled_flag,
535 if (_is_range_extension_profile (base->profile)
536 || _is_screen_content_ext_profile (base->profile)) {
538 slice_param->rext = (VASliceParameterBufferHEVCRext) {
539 .slice_ext_flags.bits = {
540 .cu_chroma_qp_offset_enabled_flag = header->cu_chroma_qp_offset_enabled_flag,
541 .use_integer_mv_flag = header->use_integer_mv_flag,
543 .slice_act_y_qp_offset = header->slice_act_y_qp_offset,
544 .slice_act_cb_qp_offset = header->slice_act_cb_qp_offset,
545 .slice_act_cr_qp_offset = header->slice_act_cr_qp_offset,
550 _fill_ref_pic_list (decoder, picture, slice_param->base.RefPicList[0],
552 _fill_ref_pic_list (decoder, picture, slice_param->base.RefPicList[1],
555 _fill_pred_weight_table (GST_VA_H265_DEC (decoder), header, slice_param);
557 _replace_previous_slice (self, slice->nalu.data + slice->nalu.offset,
564 _fill_picture_range_ext_parameter (GstVaH265Dec * decoder,
565 GstH265SPS * sps, GstH265PPS * pps)
567 VAPictureParameterBufferHEVCRext *pic_param = &decoder->pic_param.rext;
569 GstH265SPSExtensionParams *sps_ext = &sps->sps_extension_params;
570 GstH265PPSExtensionParams *pps_ext = &pps->pps_extension_params;
573 *pic_param = (VAPictureParameterBufferHEVCRext) {
574 .range_extension_pic_fields.bits = {
575 .transform_skip_rotation_enabled_flag = sps_ext->transform_skip_rotation_enabled_flag,
576 .transform_skip_context_enabled_flag = sps_ext->transform_skip_context_enabled_flag,
577 .implicit_rdpcm_enabled_flag = sps_ext->implicit_rdpcm_enabled_flag,
578 .explicit_rdpcm_enabled_flag = sps_ext->explicit_rdpcm_enabled_flag,
579 .extended_precision_processing_flag = sps_ext->extended_precision_processing_flag,
580 .intra_smoothing_disabled_flag = sps_ext->intra_smoothing_disabled_flag,
581 .high_precision_offsets_enabled_flag = sps_ext->high_precision_offsets_enabled_flag,
582 .persistent_rice_adaptation_enabled_flag = sps_ext->persistent_rice_adaptation_enabled_flag,
583 .cabac_bypass_alignment_enabled_flag = sps_ext->cabac_bypass_alignment_enabled_flag,
584 .cross_component_prediction_enabled_flag = pps_ext->cross_component_prediction_enabled_flag,
585 .chroma_qp_offset_list_enabled_flag = pps_ext->chroma_qp_offset_list_enabled_flag,
587 .diff_cu_chroma_qp_offset_depth = pps_ext->diff_cu_chroma_qp_offset_depth,
588 .chroma_qp_offset_list_len_minus1 = pps_ext->chroma_qp_offset_list_len_minus1,
589 .log2_sao_offset_scale_luma = pps_ext->log2_sao_offset_scale_luma,
590 .log2_sao_offset_scale_chroma = pps_ext->log2_sao_offset_scale_chroma,
591 .log2_max_transform_skip_block_size_minus2 = pps_ext->log2_max_transform_skip_block_size_minus2,
595 memcpy (pic_param->cb_qp_offset_list, pps_ext->cb_qp_offset_list,
596 sizeof (pic_param->cb_qp_offset_list));
597 memcpy (pic_param->cr_qp_offset_list, pps_ext->cr_qp_offset_list,
598 sizeof (pic_param->cr_qp_offset_list));
602 _fill_screen_content_ext_parameter (GstVaH265Dec * decoder,
603 GstH265SPS * sps, GstH265PPS * pps)
605 VAPictureParameterBufferHEVCScc *pic_param = &decoder->pic_param.scc;
606 const GstH265PPSSccExtensionParams *pps_scc = &pps->pps_scc_extension_params;
607 const GstH265SPSSccExtensionParams *sps_scc = &sps->sps_scc_extension_params;
612 *pic_param = (VAPictureParameterBufferHEVCScc) {
613 .screen_content_pic_fields.bits = {
614 .pps_curr_pic_ref_enabled_flag = pps_scc->pps_curr_pic_ref_enabled_flag,
615 .palette_mode_enabled_flag = sps_scc->palette_mode_enabled_flag,
616 .motion_vector_resolution_control_idc = sps_scc->motion_vector_resolution_control_idc,
617 .intra_boundary_filtering_disabled_flag = sps_scc->intra_boundary_filtering_disabled_flag,
618 .residual_adaptive_colour_transform_enabled_flag = pps_scc->residual_adaptive_colour_transform_enabled_flag,
619 .pps_slice_act_qp_offsets_present_flag = pps_scc->pps_slice_act_qp_offsets_present_flag,
621 .palette_max_size = sps_scc->palette_max_size,
622 .delta_palette_max_predictor_size = sps_scc->delta_palette_max_predictor_size,
623 .pps_act_y_qp_offset_plus5 = pps_scc->pps_act_y_qp_offset_plus5,
624 .pps_act_cb_qp_offset_plus5 = pps_scc->pps_act_cb_qp_offset_plus5,
625 .pps_act_cr_qp_offset_plus3 = pps_scc->pps_act_cr_qp_offset_plus3,
629 /* firstly use the pps, then sps */
630 num_comps = sps->chroma_format_idc ? 3 : 1;
632 if (pps_scc->pps_palette_predictor_initializers_present_flag) {
633 pic_param->predictor_palette_size =
634 pps_scc->pps_num_palette_predictor_initializer;
635 for (n = 0; n < num_comps; n++)
636 for (i = 0; i < pps_scc->pps_num_palette_predictor_initializer; i++)
637 pic_param->predictor_palette_entries[n][i] =
638 (uint16_t) pps_scc->pps_palette_predictor_initializer[n][i];
639 } else if (sps_scc->sps_palette_predictor_initializers_present_flag) {
640 pic_param->predictor_palette_size =
641 sps_scc->sps_num_palette_predictor_initializer_minus1 + 1;
642 for (n = 0; n < num_comps; n++)
644 i < sps_scc->sps_num_palette_predictor_initializer_minus1 + 1; i++)
645 pic_param->predictor_palette_entries[n][i] =
646 (uint16_t) sps_scc->sps_palette_predictor_initializer[n][i];
651 gst_va_h265_dec_start_picture (GstH265Decoder * decoder,
652 GstH265Picture * picture, GstH265Slice * slice, GstH265Dpb * dpb)
656 GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
657 GstVaBaseDec *base = &self->parent;
658 GstVaDecodePicture *va_pic;
659 GstH265ScalingList *scaling_list = NULL;
660 VAIQMatrixBufferHEVC iq_matrix = { 0, };
661 VAPictureParameterBufferHEVCExtension *pic_param = &self->pic_param;
662 gsize pic_param_size;
665 va_pic = gst_h265_picture_get_user_data (picture);
667 pps = slice->header.pps;
671 pic_param->base = (VAPictureParameterBufferHEVC) {
672 .pic_width_in_luma_samples = sps->pic_width_in_luma_samples,
673 .pic_height_in_luma_samples = sps->pic_height_in_luma_samples,
674 .sps_max_dec_pic_buffering_minus1 = sps->max_dec_pic_buffering_minus1[sps->max_sub_layers_minus1],
675 .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8,
676 .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8,
677 .pcm_sample_bit_depth_luma_minus1 = sps->pcm_sample_bit_depth_luma_minus1,
678 .pcm_sample_bit_depth_chroma_minus1 = sps->pcm_sample_bit_depth_chroma_minus1,
679 .log2_min_luma_coding_block_size_minus3 = sps->log2_min_luma_coding_block_size_minus3,
680 .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_luma_coding_block_size,
681 .log2_min_transform_block_size_minus2 = sps->log2_min_transform_block_size_minus2,
682 .log2_diff_max_min_transform_block_size = sps->log2_diff_max_min_transform_block_size,
683 .log2_min_pcm_luma_coding_block_size_minus3 = sps->log2_min_pcm_luma_coding_block_size_minus3,
684 .log2_diff_max_min_pcm_luma_coding_block_size = sps->log2_diff_max_min_pcm_luma_coding_block_size,
685 .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra,
686 .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter,
687 .init_qp_minus26 = pps->init_qp_minus26,
688 .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth,
689 .pps_cb_qp_offset = pps->cb_qp_offset,
690 .pps_cr_qp_offset = pps->cr_qp_offset,
691 .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level_minus2,
692 .num_tile_columns_minus1 = pps->num_tile_columns_minus1,
693 .num_tile_rows_minus1 = pps->num_tile_rows_minus1,
694 .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4,
695 .num_short_term_ref_pic_sets = sps->num_short_term_ref_pic_sets,
696 .num_long_term_ref_pic_sps = sps->num_long_term_ref_pics_sps,
697 .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active_minus1,
698 .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active_minus1,
699 .pps_beta_offset_div2 = pps->beta_offset_div2,
700 .pps_tc_offset_div2 = pps->tc_offset_div2,
701 .num_extra_slice_header_bits = pps->num_extra_slice_header_bits,
702 .st_rps_bits = slice->header.short_term_ref_pic_set_size, /* FIXME missing emulation bits removal */
704 .chroma_format_idc = sps->chroma_format_idc,
705 .separate_colour_plane_flag = sps->separate_colour_plane_flag,
706 .pcm_enabled_flag = sps->pcm_enabled_flag,
707 .scaling_list_enabled_flag = sps->scaling_list_enabled_flag,
708 .transform_skip_enabled_flag = pps->transform_skip_enabled_flag,
709 .amp_enabled_flag = sps->amp_enabled_flag,
710 .strong_intra_smoothing_enabled_flag = sps->strong_intra_smoothing_enabled_flag,
711 .sign_data_hiding_enabled_flag = pps->sign_data_hiding_enabled_flag,
712 .constrained_intra_pred_flag = pps->constrained_intra_pred_flag,
713 .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag,
714 .weighted_pred_flag = pps->weighted_pred_flag,
715 .weighted_bipred_flag = pps->weighted_bipred_flag,
716 .transquant_bypass_enabled_flag = pps->transquant_bypass_enabled_flag,
717 .tiles_enabled_flag = pps->tiles_enabled_flag,
718 .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag,
719 .pps_loop_filter_across_slices_enabled_flag = pps->loop_filter_across_slices_enabled_flag,
720 .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag,
721 .pcm_loop_filter_disabled_flag = sps->pcm_loop_filter_disabled_flag,
722 /* Not set by FFMPEG either */
723 .NoPicReorderingFlag = 0,
726 .slice_parsing_fields.bits = {
727 .lists_modification_present_flag = pps->lists_modification_present_flag,
728 .long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag,
729 .sps_temporal_mvp_enabled_flag = sps->temporal_mvp_enabled_flag,
730 .cabac_init_present_flag = pps->cabac_init_present_flag,
731 .output_flag_present_flag = pps->output_flag_present_flag,
732 .dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag,
733 .pps_slice_chroma_qp_offsets_present_flag = pps->slice_chroma_qp_offsets_present_flag,
734 .sample_adaptive_offset_enabled_flag = sps->sample_adaptive_offset_enabled_flag,
735 .deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag,
736 .pps_disable_deblocking_filter_flag = pps->deblocking_filter_disabled_flag,
737 .slice_segment_header_extension_present_flag = pps->slice_segment_header_extension_present_flag,
738 .RapPicFlag = picture->RapPicFlag,
739 .IdrPicFlag = GST_H265_IS_NAL_TYPE_IDR (slice->nalu.type),
740 .IntraPicFlag = GST_H265_IS_NAL_TYPE_IRAP (slice->nalu.type),
745 if (_is_range_extension_profile (self->parent.profile)
746 || _is_screen_content_ext_profile (self->parent.profile)) {
747 _fill_picture_range_ext_parameter (self, sps, pps);
748 if (_is_screen_content_ext_profile (self->parent.profile))
749 _fill_screen_content_ext_parameter (self, sps, pps);
752 for (i = 0; i <= pps->num_tile_columns_minus1; i++)
753 pic_param->base.column_width_minus1[i] = pps->column_width_minus1[i];
755 for (i = 0; i <= pps->num_tile_rows_minus1; i++)
756 pic_param->base.row_height_minus1[i] = pps->row_height_minus1[i];
758 _fill_vaapi_pic (decoder, &pic_param->base.CurrPic, picture);
760 /* reference frames */
762 GArray *ref_list = gst_h265_dpb_get_pictures_all (dpb);
766 for (j = 0; j < 15 && j < ref_list->len; j++) {
767 GstH265Picture *pic = g_array_index (ref_list, GstH265Picture *, j);
770 _fill_vaapi_pic (decoder, &pic_param->base.ReferenceFrames[i], pic);
774 g_array_unref (ref_list);
776 /* 7.4.3.3.3, the current decoded picture is marked as "used for
777 long-term reference". Current picture is not in the DPB now. */
778 if (pps->pps_scc_extension_params.pps_curr_pic_ref_enabled_flag && i < 15) {
779 pic_param->base.ReferenceFrames[i].picture_id =
780 gst_va_decode_picture_get_surface (gst_h265_picture_get_user_data
782 pic_param->base.ReferenceFrames[i].pic_order_cnt = picture->pic_order_cnt;
783 pic_param->base.ReferenceFrames[i].flags |=
784 VA_PICTURE_HEVC_LONG_TERM_REFERENCE;
785 pic_param->base.ReferenceFrames[i].flags |=
786 _find_frame_rps_type (decoder, picture);
791 _init_vaapi_pic (&pic_param->base.ReferenceFrames[i]);
794 pic_param_size = _is_range_extension_profile (self->parent.profile)
795 || _is_screen_content_ext_profile (self->parent.profile) ?
796 sizeof (*pic_param) : sizeof (pic_param->base);
797 if (!gst_va_decoder_add_param_buffer (base->decoder, va_pic,
798 VAPictureParameterBufferType, pic_param, pic_param_size))
799 return GST_FLOW_ERROR;
801 if (pps->scaling_list_data_present_flag ||
802 (sps->scaling_list_enabled_flag
803 && !sps->scaling_list_data_present_flag)) {
804 scaling_list = &pps->scaling_list;
805 GST_DEBUG_OBJECT (decoder, "Passing scaling list from PPS");
806 } else if (sps->scaling_list_enabled_flag &&
807 sps->scaling_list_data_present_flag) {
808 scaling_list = &sps->scaling_list;
809 GST_DEBUG_OBJECT (decoder, "Passing scaling list from SPS");
813 for (i = 0; i < G_N_ELEMENTS (iq_matrix.ScalingList4x4); i++)
814 gst_h265_quant_matrix_4x4_get_raster_from_uprightdiagonal
815 (iq_matrix.ScalingList4x4[i], scaling_list->scaling_lists_4x4[i]);
817 for (i = 0; i < G_N_ELEMENTS (iq_matrix.ScalingList8x8); i++)
818 gst_h265_quant_matrix_8x8_get_raster_from_uprightdiagonal
819 (iq_matrix.ScalingList8x8[i], scaling_list->scaling_lists_8x8[i]);
821 for (i = 0; i < G_N_ELEMENTS (iq_matrix.ScalingList16x16); i++)
822 gst_h265_quant_matrix_16x16_get_raster_from_uprightdiagonal
823 (iq_matrix.ScalingList16x16[i], scaling_list->scaling_lists_16x16[i]);
825 for (i = 0; i < G_N_ELEMENTS (iq_matrix.ScalingList32x32); i++)
826 gst_h265_quant_matrix_32x32_get_raster_from_uprightdiagonal
827 (iq_matrix.ScalingList32x32[i], scaling_list->scaling_lists_32x32[i]);
829 for (i = 0; i < 6; i++)
830 iq_matrix.ScalingListDC16x16[i] =
831 scaling_list->scaling_list_dc_coef_minus8_16x16[i] + 8;
833 for (i = 0; i < 2; i++)
834 iq_matrix.ScalingListDC32x32[i] =
835 scaling_list->scaling_list_dc_coef_minus8_32x32[i] + 8;
837 if (!gst_va_decoder_add_param_buffer (base->decoder, va_pic,
838 VAIQMatrixBufferType, &iq_matrix, sizeof (iq_matrix))) {
839 return GST_FLOW_ERROR;
847 gst_va_h265_dec_new_picture (GstH265Decoder * decoder,
848 GstVideoCodecFrame * frame, GstH265Picture * picture)
850 GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
851 GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
852 GstVaDecodePicture *pic;
853 GstBuffer *output_buffer;
854 GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
855 GstFlowReturn ret = GST_FLOW_ERROR;
857 if (base->need_negotiation) {
858 if (!gst_video_decoder_negotiate (vdec)) {
859 GST_ERROR_OBJECT (self, "Failed to negotiate with downstream");
860 return GST_FLOW_NOT_NEGOTIATED;
864 output_buffer = gst_video_decoder_allocate_output_buffer (vdec);
868 pic = gst_va_decode_picture_new (base->decoder, output_buffer);
869 gst_buffer_unref (output_buffer);
871 gst_h265_picture_set_user_data (picture, pic,
872 (GDestroyNotify) gst_va_decode_picture_free);
874 GST_LOG_OBJECT (self, "New va decode picture %p - %#x", pic,
875 gst_va_decode_picture_get_surface (pic));
881 GST_WARNING_OBJECT (self,
882 "Failed to allocated output buffer, return %s",
883 gst_flow_get_name (ret));
889 _get_rtformat (GstVaH265Dec * self, guint8 bit_depth_luma,
890 guint8 bit_depth_chroma, guint8 chroma_format_idc)
892 guint8 bit_num = MAX (bit_depth_luma, bit_depth_chroma);
897 if (chroma_format_idc == 3)
898 return VA_RT_FORMAT_YUV444_12;
899 if (chroma_format_idc == 2)
900 return VA_RT_FORMAT_YUV422_12;
902 return VA_RT_FORMAT_YUV420_12;
906 if (chroma_format_idc == 3)
907 return VA_RT_FORMAT_YUV444_10;
908 if (chroma_format_idc == 2)
909 return VA_RT_FORMAT_YUV422_10;
911 return VA_RT_FORMAT_YUV420_10;
914 if (chroma_format_idc == 3)
915 return VA_RT_FORMAT_YUV444;
916 if (chroma_format_idc == 2)
917 return VA_RT_FORMAT_YUV422;
919 return VA_RT_FORMAT_YUV420;
922 GST_ERROR_OBJECT (self, "Unsupported chroma format: %d "
923 "(with depth luma: %d, with depth chroma: %d)",
924 chroma_format_idc, bit_depth_luma, bit_depth_chroma);
932 GstH265Profile profile;
933 VAProfile va_profile;
935 #define P(idc, va) { G_PASTE (GST_H265_PROFILE_, idc), G_PASTE (VAProfileHEVC, va) }
938 /*P (MAIN_STILL_PICTURE, ),
941 P (MONOCHROME_16, ),*/
943 P (MAIN_422_10, Main422_10),
944 P (MAIN_422_12, Main422_12),
945 P (MAIN_444, Main444),
946 P (MAIN_444_10, Main444_10),
947 P (MAIN_444_12, Main444_12),
951 P (MAIN_422_10_INTRA, ),
952 P (MAIN_422_12_INTRA, ),
953 P (MAIN_444_INTRA, ),
954 P (MAIN_444_10_INTRA, ),
955 P (MAIN_444_12_INTRA, ),
956 P (MAIN_444_16_INTRA, ),
957 P (MAIN_444_STILL_PICTURE, ),
958 P (MAIN_444_16_STILL_PICTURE, ),
960 P (HIGH_THROUGHPUT_444, ),
961 P (HIGH_THROUGHPUT_444_10, ),
962 P (HIGH_THROUGHPUT_444_14, ),
963 P (HIGH_THROUGHPUT_444_16_INTRA, ),*/
964 P (SCREEN_EXTENDED_MAIN, SccMain),
965 P (SCREEN_EXTENDED_MAIN_10, SccMain10),
966 P (SCREEN_EXTENDED_MAIN_444, SccMain444),
967 #if VA_CHECK_VERSION(1, 8, 0)
968 P (SCREEN_EXTENDED_MAIN_444_10, SccMain444_10),
970 /*P (SCREEN_EXTENDED_HIGH_THROUGHPUT_444, ),
971 P (SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10, ),
972 P (SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14, ),
973 P (MULTIVIEW_MAIN, ),
975 P (SCALABLE_MAIN_10, ),
976 P (SCALABLE_MONOCHROME, ),
977 P (SCALABLE_MONOCHROME_12, ),
978 P (SCALABLE_MONOCHROME_16, ),
979 P (SCALABLE_MAIN_444, ),
986 _get_profile (GstVaH265Dec * self, const GstH265SPS * sps, gint max_dpb_size)
988 GstH265Decoder *h265_decoder = GST_H265_DECODER (self);
989 GstVaBaseDec *base = GST_VA_BASE_DEC (self);
990 GstH265Profile profile = gst_h265_get_profile_from_sps ((GstH265SPS *) sps);
991 VAProfile profiles[4];
994 /* 1. The profile directly specified by the SPS should always be the
995 first choice. It is the exact one.
996 2. The profile in the input caps may contain the compatible profile
997 chosen by the upstream element. Upstream element such as the parse
998 may already decide the best compatible profile for us. We also need
999 to consider it as a choice. */
1001 for (j = 0; j < G_N_ELEMENTS (profile_map); j++) {
1002 if (profile_map[j].profile == profile) {
1003 profiles[i++] = profile_map[j].va_profile;
1008 if (h265_decoder->input_state->caps
1009 && gst_caps_is_fixed (h265_decoder->input_state->caps)) {
1010 GstH265Profile compatible_profile = GST_H265_PROFILE_INVALID;
1011 GstStructure *structure;
1012 const gchar *profile_str;
1014 structure = gst_caps_get_structure (h265_decoder->input_state->caps, 0);
1016 profile_str = gst_structure_get_string (structure, "profile");
1018 compatible_profile = gst_h265_profile_from_string (profile_str);
1020 if (compatible_profile != profile) {
1021 GST_INFO_OBJECT (self, "The upstream set the compatible profile %s, "
1022 "also consider it as a candidate.", profile_str);
1024 for (j = 0; j < G_N_ELEMENTS (profile_map); j++) {
1025 if (profile_map[j].profile == compatible_profile) {
1026 profiles[i++] = profile_map[j].va_profile;
1033 for (j = 0; j < i && j < G_N_ELEMENTS (profiles); j++) {
1034 if (gst_va_decoder_has_profile (base->decoder, profiles[j]))
1038 GST_ERROR_OBJECT (self, "Unsupported profile: %d", profile);
1040 return VAProfileNone;
1043 static GstFlowReturn
1044 gst_va_h265_dec_new_sequence (GstH265Decoder * decoder, const GstH265SPS * sps,
1047 GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
1048 GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
1049 GstVideoInfo *info = &base->output_info;
1052 gint display_height;
1053 gint padding_left, padding_right, padding_top, padding_bottom;
1055 gboolean negotiation_needed = FALSE;
1057 if (self->dpb_size < max_dpb_size)
1058 self->dpb_size = max_dpb_size;
1060 if (sps->conformance_window_flag) {
1061 display_width = sps->crop_rect_width;
1062 display_height = sps->crop_rect_height;
1063 padding_left = sps->crop_rect_x;
1064 padding_right = sps->width - sps->crop_rect_x - display_width;
1065 padding_top = sps->crop_rect_y;
1066 padding_bottom = sps->height - sps->crop_rect_y - display_height;
1068 display_width = sps->width;
1069 display_height = sps->height;
1070 padding_left = padding_right = padding_top = padding_bottom = 0;
1073 profile = _get_profile (self, sps, max_dpb_size);
1074 if (profile == VAProfileNone)
1075 return GST_FLOW_NOT_NEGOTIATED;
1077 rt_format = _get_rtformat (self, sps->bit_depth_luma_minus8 + 8,
1078 sps->bit_depth_chroma_minus8 + 8, sps->chroma_format_idc);
1080 return GST_FLOW_NOT_NEGOTIATED;
1082 if (!gst_va_decoder_config_is_equal (base->decoder, profile,
1083 rt_format, sps->width, sps->height)) {
1084 base->profile = profile;
1085 base->rt_format = rt_format;
1086 base->width = sps->width;
1087 base->height = sps->height;
1089 negotiation_needed = TRUE;
1090 GST_INFO_OBJECT (self, "Format changed to %s [%x] (%dx%d)",
1091 gst_va_profile_name (profile), rt_format, base->width, base->height);
1094 if (GST_VIDEO_INFO_WIDTH (info) != display_width ||
1095 GST_VIDEO_INFO_HEIGHT (info) != display_height) {
1096 GST_VIDEO_INFO_WIDTH (info) = display_width;
1097 GST_VIDEO_INFO_HEIGHT (info) = display_height;
1099 negotiation_needed = TRUE;
1100 GST_INFO_OBJECT (self, "Resolution changed to %dx%d",
1101 GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info));
1104 base->need_valign = GST_VIDEO_INFO_WIDTH (info) < base->width ||
1105 GST_VIDEO_INFO_HEIGHT (info) < base->height;
1106 if (base->need_valign) {
1108 if (base->valign.padding_left != padding_left ||
1109 base->valign.padding_right != padding_right ||
1110 base->valign.padding_top != padding_top ||
1111 base->valign.padding_bottom != padding_bottom) {
1112 negotiation_needed = TRUE;
1113 GST_INFO_OBJECT (self, "crop rect changed to (%d,%d)-->(%d,%d)",
1114 padding_left, padding_top, padding_right, padding_bottom);
1116 base->valign = (GstVideoAlignment) {
1117 .padding_left = padding_left,
1118 .padding_right = padding_right,
1119 .padding_top = padding_top,
1120 .padding_bottom = padding_bottom,
1125 base->min_buffers = self->dpb_size + 4; /* dpb size + scratch surfaces */
1126 base->need_negotiation = negotiation_needed;
1127 g_clear_pointer (&base->input_state, gst_video_codec_state_unref);
1128 base->input_state = gst_video_codec_state_ref (decoder->input_state);
1131 /* FIXME: We don't have parser API for sps_range_extension, so
1132 * assuming high_precision_offsets_enabled_flag as zero */
1133 guint high_precision_offsets_enabled_flag = 0, bitdepthC = 0;
1135 /* Calculate WpOffsetHalfRangeC: (7-34) */
1136 bitdepthC = sps->bit_depth_chroma_minus8 + 8;
1137 self->WpOffsetHalfRangeC =
1138 1 << (high_precision_offsets_enabled_flag ? (bitdepthC - 1) : 7);
1145 _complete_sink_caps (GstCaps * sinkcaps)
1147 GstCaps *caps = gst_caps_copy (sinkcaps);
1148 GValue val = G_VALUE_INIT;
1149 const gchar *streamformat[] = { "hvc1", "hev1", "byte-stream" };
1152 g_value_init (&val, G_TYPE_STRING);
1153 g_value_set_string (&val, "au");
1154 gst_caps_set_value (caps, "alignment", &val);
1155 g_value_unset (&val);
1157 gst_value_list_init (&val, G_N_ELEMENTS (streamformat));
1158 for (i = 0; i < G_N_ELEMENTS (streamformat); i++) {
1159 GValue v = G_VALUE_INIT;
1161 g_value_init (&v, G_TYPE_STRING);
1162 g_value_set_string (&v, streamformat[i]);
1163 gst_value_list_append_value (&val, &v);
1166 gst_caps_set_value (caps, "stream-format", &val);
1167 g_value_unset (&val);
1173 gst_va_h265_dec_getcaps (GstVideoDecoder * decoder, GstCaps * filter)
1175 GstCaps *sinkcaps, *caps = NULL, *tmp;
1176 GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
1179 caps = gst_va_decoder_get_sinkpad_caps (base->decoder);
1182 sinkcaps = _complete_sink_caps (caps);
1183 gst_caps_unref (caps);
1185 tmp = gst_caps_intersect_full (filter, sinkcaps,
1186 GST_CAPS_INTERSECT_FIRST);
1187 gst_caps_unref (sinkcaps);
1192 GST_LOG_OBJECT (base, "Returning caps %" GST_PTR_FORMAT, caps);
1194 caps = gst_video_decoder_proxy_getcaps (decoder, NULL, filter);
1201 gst_va_h265_dec_dispose (GObject * object)
1203 g_free (GST_VA_H265_DEC (object)->prev_slice.data);
1205 gst_va_base_dec_close (GST_VIDEO_DECODER (object));
1207 G_OBJECT_CLASS (parent_class)->dispose (object);
1211 gst_va_h265_dec_class_init (gpointer g_class, gpointer class_data)
1213 GstCaps *src_doc_caps, *sink_doc_caps;
1214 GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
1215 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
1216 GstH265DecoderClass *h265decoder_class = GST_H265_DECODER_CLASS (g_class);
1217 GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (g_class);
1218 struct CData *cdata = class_data;
1221 if (cdata->description) {
1222 long_name = g_strdup_printf ("VA-API H.265 Decoder in %s",
1223 cdata->description);
1225 long_name = g_strdup ("VA-API H.265 Decoder");
1228 gst_element_class_set_metadata (element_class, long_name,
1229 "Codec/Decoder/Video/Hardware",
1230 "VA-API based H.265 video decoder",
1231 "Nicolas Dufresne <nicolas.dufresne@collabora.com>");
1233 sink_doc_caps = gst_caps_from_string (sink_caps_str);
1234 src_doc_caps = gst_caps_from_string (src_caps_str);
1236 parent_class = g_type_class_peek_parent (g_class);
1239 * GstVaH265Dec:device-path:
1241 * It shows the DRM device path used for the VA operation, if any.
1245 gst_va_base_dec_class_init (GST_VA_BASE_DEC_CLASS (g_class), HEVC,
1246 cdata->render_device_path, cdata->sink_caps, cdata->src_caps,
1247 src_doc_caps, sink_doc_caps);
1249 gobject_class->dispose = gst_va_h265_dec_dispose;
1251 decoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_va_h265_dec_getcaps);
1253 h265decoder_class->new_sequence =
1254 GST_DEBUG_FUNCPTR (gst_va_h265_dec_new_sequence);
1255 h265decoder_class->decode_slice =
1256 GST_DEBUG_FUNCPTR (gst_va_h265_dec_decode_slice);
1258 h265decoder_class->new_picture =
1259 GST_DEBUG_FUNCPTR (gst_va_h265_dec_new_picture);
1260 h265decoder_class->output_picture =
1261 GST_DEBUG_FUNCPTR (gst_va_h265_dec_output_picture);
1262 h265decoder_class->start_picture =
1263 GST_DEBUG_FUNCPTR (gst_va_h265_dec_start_picture);
1264 h265decoder_class->end_picture =
1265 GST_DEBUG_FUNCPTR (gst_va_h265_dec_end_picture);
1268 g_free (cdata->description);
1269 g_free (cdata->render_device_path);
1270 gst_caps_unref (cdata->src_caps);
1271 gst_caps_unref (cdata->sink_caps);
1276 gst_va_h265_dec_init (GTypeInstance * instance, gpointer g_class)
1278 gst_va_base_dec_init (GST_VA_BASE_DEC (instance), GST_CAT_DEFAULT);
1279 gst_h265_decoder_set_process_ref_pic_lists (GST_H265_DECODER (instance),
1284 _register_debug_category (gpointer data)
1286 GST_DEBUG_CATEGORY_INIT (gst_va_h265dec_debug, "vah265dec", 0,
1293 gst_va_h265_dec_register (GstPlugin * plugin, GstVaDevice * device,
1294 GstCaps * sink_caps, GstCaps * src_caps, guint rank)
1296 static GOnce debug_once = G_ONCE_INIT;
1298 GTypeInfo type_info = {
1299 .class_size = sizeof (GstVaH265DecClass),
1300 .class_init = gst_va_h265_dec_class_init,
1301 .instance_size = sizeof (GstVaH265Dec),
1302 .instance_init = gst_va_h265_dec_init,
1304 struct CData *cdata;
1306 gchar *type_name, *feature_name;
1308 g_return_val_if_fail (GST_IS_PLUGIN (plugin), FALSE);
1309 g_return_val_if_fail (GST_IS_VA_DEVICE (device), FALSE);
1310 g_return_val_if_fail (GST_IS_CAPS (sink_caps), FALSE);
1311 g_return_val_if_fail (GST_IS_CAPS (src_caps), FALSE);
1313 cdata = g_new (struct CData, 1);
1314 cdata->description = NULL;
1315 cdata->render_device_path = g_strdup (device->render_device_path);
1316 cdata->sink_caps = _complete_sink_caps (sink_caps);
1317 cdata->src_caps = gst_caps_ref (src_caps);
1319 /* class data will be leaked if the element never gets instantiated */
1320 GST_MINI_OBJECT_FLAG_SET (cdata->sink_caps,
1321 GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
1322 GST_MINI_OBJECT_FLAG_SET (src_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
1324 type_info.class_data = cdata;
1326 /* The first decoder to be registered should use a constant name,
1327 * like vah265dec, for any additional decoders, we create unique
1328 * names, using inserting the render device name. */
1329 if (device->index == 0) {
1330 type_name = g_strdup ("GstVaH265Dec");
1331 feature_name = g_strdup ("vah265dec");
1333 gchar *basename = g_path_get_basename (device->render_device_path);
1334 type_name = g_strdup_printf ("GstVa%sH265Dec", basename);
1335 feature_name = g_strdup_printf ("va%sh265dec", basename);
1336 cdata->description = basename;
1338 /* lower rank for non-first device */
1343 g_once (&debug_once, _register_debug_category, NULL);
1345 type = g_type_register_static (GST_TYPE_H265_DECODER,
1346 type_name, &type_info, 0);
1348 ret = gst_element_register (plugin, feature_name, rank, type);
1351 g_free (feature_name);