va: basedec: Select format from template or negotiated caps.
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / sys / va / gstvah265dec.c
1 /* GStreamer
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>
6  *
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.
11  *
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.
16  *
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.
21  */
22
23 /**
24  * SECTION:element-vah265dec
25  * @title: vah265dec
26  * @short_description: A VA-API based H265 video decoder
27  *
28  * vah265dec decodes H265 bitstreams to VA surfaces using the
29  * installed and chosen [VA-API](https://01.org/linuxmedia/vaapi)
30  * driver.
31  *
32  * The decoding surfaces can be mapped onto main memory as video
33  * frames.
34  *
35  * ## Example launch line
36  * ```
37  * gst-launch-1.0 filesrc location=big_buck_bunny.mov ! parsebin ! vah265dec ! autovideosink
38  * ```
39  *
40  * Since: 1.20
41  *
42  */
43
44 /* ToDo:
45  *
46  * + interlaced streams
47  * + mutiview and stereo profiles
48  * + SCC extension buffer
49  * + Add 10bit support
50  */
51
52 #ifdef HAVE_CONFIG_H
53 #include "config.h"
54 #endif
55
56 #include "gstvah265dec.h"
57
58 #include "gstvabasedec.h"
59
60 GST_DEBUG_CATEGORY_STATIC (gst_va_h265dec_debug);
61 #ifndef GST_DISABLE_GST_DEBUG
62 #define GST_CAT_DEFAULT gst_va_h265dec_debug
63 #else
64 #define GST_CAT_DEFAULT NULL
65 #endif
66
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)
70
71 struct slice
72 {
73   guint8 *data;
74   guint size;
75
76   VASliceParameterBufferHEVCExtension param;
77 };
78
79 typedef struct _GstVaH265Dec GstVaH265Dec;
80 typedef struct _GstVaH265DecClass GstVaH265DecClass;
81
82 struct _GstVaH265DecClass
83 {
84   GstVaBaseDecClass parent_class;
85 };
86
87 struct _GstVaH265Dec
88 {
89   GstVaBaseDec parent;
90
91   GstFlowReturn last_ret;
92
93   gint coded_width;
94   gint coded_height;
95   gint dpb_size;
96
97   VAPictureParameterBufferHEVCExtension pic_param;
98
99   gint32 WpOffsetHalfRangeC;
100
101   struct slice prev_slice;
102 };
103
104 static GstElementClass *parent_class = NULL;
105
106 /* *INDENT-OFF* */
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 }");
111 /* *INDENT-ON* */
112
113 static const gchar *sink_caps_str = "video/x-h265";
114
115 static gboolean
116 _is_range_extension_profile (VAProfile profile)
117 {
118   if (profile == VAProfileHEVCMain422_10
119       || profile == VAProfileHEVCMain444
120       || profile == VAProfileHEVCMain444_10
121       || profile == VAProfileHEVCMain12
122       || profile == VAProfileHEVCMain444_12
123       || profile == VAProfileHEVCMain422_12)
124     return TRUE;
125   return FALSE;
126 }
127
128 static gboolean
129 _is_screen_content_ext_profile (VAProfile profile)
130 {
131   if (profile == VAProfileHEVCSccMain
132       || profile == VAProfileHEVCSccMain10
133       || profile == VAProfileHEVCSccMain444)
134     return TRUE;
135
136   return FALSE;
137 }
138
139 static inline void
140 _set_last_slice_flag (GstVaH265Dec * self)
141 {
142   self->prev_slice.param.base.LongSliceFlags.fields.LastSliceOfPic = 1;
143 }
144
145 static void
146 _replace_previous_slice (GstVaH265Dec * self, guint8 * data, guint size)
147 {
148   struct slice *slice = &self->prev_slice;
149   gboolean do_reset = (slice->size < size);
150
151   if (!data || do_reset) {
152     g_clear_pointer (&slice->data, g_free);
153     slice->size = 0;
154   }
155
156   if (!data)
157     return;
158
159   if (do_reset) {
160     GST_LOG_OBJECT (self, "allocating slice data %u", size);
161     slice->data = g_malloc (size);
162   }
163
164   memcpy (slice->data, data, size);
165   slice->size = size;
166 }
167
168 static gboolean
169 _submit_previous_slice (GstVaBaseDec * base, GstVaDecodePicture * va_pic)
170 {
171   GstVaH265Dec *self = GST_VA_H265_DEC (base);
172   struct slice *slice;
173   gboolean ret;
174   gsize param_size;
175
176   slice = &self->prev_slice;
177   if (!slice->data && slice->size == 0)
178     return TRUE;
179   if (!slice->data || slice->size == 0)
180     return FALSE;
181
182   param_size = _is_range_extension_profile (self->parent.profile)
183       || _is_screen_content_ext_profile (self->parent.profile) ?
184       sizeof (slice->param) : sizeof (slice->param.base);
185   ret = gst_va_decoder_add_slice_buffer (base->decoder, va_pic, &slice->param,
186       param_size, slice->data, slice->size);
187
188   return ret;
189 }
190
191 static GstFlowReturn
192 gst_va_h265_dec_end_picture (GstH265Decoder * decoder, GstH265Picture * picture)
193 {
194   GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
195   GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
196   GstVaDecodePicture *va_pic;
197   gboolean ret;
198
199   GST_LOG_OBJECT (base, "end picture %p, (poc %d)",
200       picture, picture->pic_order_cnt);
201
202   va_pic = gst_h265_picture_get_user_data (picture);
203
204   _set_last_slice_flag (self);
205   ret = _submit_previous_slice (base, va_pic);
206
207   /* TODO(victor): optimization: this could be done at decoder's
208    * stop() vmethod */
209   _replace_previous_slice (self, NULL, 0);
210
211   if (!ret) {
212     GST_ERROR_OBJECT (self, "Failed to submit the previous slice");
213     return GST_FLOW_ERROR;
214   }
215
216   ret = gst_va_decoder_decode (base->decoder, va_pic);
217   if (!ret) {
218     GST_ERROR_OBJECT (self, "Failed at end picture %p, (poc %d)",
219         picture, picture->pic_order_cnt);
220     return GST_FLOW_ERROR;
221   }
222
223   return GST_FLOW_OK;
224 }
225
226 static GstFlowReturn
227 gst_va_h265_dec_output_picture (GstH265Decoder * decoder,
228     GstVideoCodecFrame * frame, GstH265Picture * picture)
229 {
230   GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
231   GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
232   GstVaDecodePicture *va_pic;
233
234   va_pic = gst_h265_picture_get_user_data (picture);
235   g_assert (va_pic->gstbuffer);
236
237   GST_LOG_OBJECT (self,
238       "Outputting picture %p (poc %d)", picture, picture->pic_order_cnt);
239
240   if (self->last_ret != GST_FLOW_OK) {
241     gst_h265_picture_unref (picture);
242     _replace_previous_slice (self, NULL, 0);
243     gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame);
244     return self->last_ret;
245   }
246
247   gst_buffer_replace (&frame->output_buffer, va_pic->gstbuffer);
248
249   if (base->copy_frames)
250     gst_va_base_dec_copy_output_buffer (base, frame);
251
252   gst_h265_picture_unref (picture);
253
254   return gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
255 }
256
257 static void
258 _init_vaapi_pic (VAPictureHEVC * va_picture)
259 {
260   va_picture->picture_id = VA_INVALID_ID;
261   va_picture->flags = VA_PICTURE_HEVC_INVALID;
262   va_picture->pic_order_cnt = 0;
263 }
264
265 static gint
266 _find_frame_rps_type (GstH265Decoder * decoder, GstH265Picture * ref_pic)
267 {
268   gint i;
269
270   for (i = 0; i < G_N_ELEMENTS (decoder->RefPicSetStCurrBefore); i++) {
271     if (ref_pic == decoder->RefPicSetStCurrBefore[i])
272       return VA_PICTURE_HEVC_RPS_ST_CURR_BEFORE;
273   }
274
275   for (i = 0; i < G_N_ELEMENTS (decoder->RefPicSetStCurrAfter); i++) {
276     if (ref_pic == decoder->RefPicSetStCurrAfter[i])
277       return VA_PICTURE_HEVC_RPS_ST_CURR_AFTER;
278   }
279
280   for (i = 0; i < G_N_ELEMENTS (decoder->RefPicSetLtCurr); i++) {
281     if (ref_pic == decoder->RefPicSetLtCurr[i])
282       return VA_PICTURE_HEVC_RPS_LT_CURR;
283   }
284
285   return 0;
286 }
287
288
289 static void
290 _fill_vaapi_pic (GstH265Decoder * decoder, VAPictureHEVC * va_picture,
291     GstH265Picture * picture)
292 {
293   GstVaDecodePicture *va_pic;
294
295   va_pic = gst_h265_picture_get_user_data (picture);
296
297   if (!va_pic) {
298     _init_vaapi_pic (va_picture);
299     return;
300   }
301
302   va_picture->picture_id = gst_va_decode_picture_get_surface (va_pic);
303   va_picture->pic_order_cnt = picture->pic_order_cnt;
304   va_picture->flags = 0;
305
306   if (picture->ref && picture->long_term)
307     va_picture->flags |= VA_PICTURE_HEVC_LONG_TERM_REFERENCE;
308
309   va_picture->flags |= _find_frame_rps_type (decoder, picture);
310 }
311
312 static guint8
313 _get_reference_index (GstH265Decoder * decoder, GstH265Picture * picture)
314 {
315   GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
316   guint8 i;
317
318   if (!picture)
319     return 0xFF;
320
321   for (i = 0; i < 15; i++) {
322     VAPictureHEVC *ref_va_pic = &self->pic_param.base.ReferenceFrames[i];
323
324     if (ref_va_pic->picture_id == VA_INVALID_ID)
325       break;
326
327     if (ref_va_pic->pic_order_cnt == picture->pic_order_cnt)
328       return i;
329   }
330
331   return 0xFF;
332 }
333
334 /* fill the VA API reference picture lists from the GstCodec reference
335  * picture list */
336 static void
337 _fill_ref_pic_list (GstH265Decoder * decoder, GstH265Picture * cur_pic,
338     guint8 va_reflist[15], GArray * reflist)
339 {
340   guint i;
341
342   for (i = 0; i < reflist->len && i < 15; i++) {
343     GstH265Picture *picture = g_array_index (reflist, GstH265Picture *, i);
344     va_reflist[i] = _get_reference_index (decoder, picture);
345   }
346
347   for (; i < 15; i++)
348     va_reflist[i] = 0xFF;
349 }
350
351 static void
352 _fill_pred_weight_table (GstVaH265Dec * self, GstH265SliceHdr * header,
353     VASliceParameterBufferHEVCExtension * slice_param)
354 {
355   gint chroma_weight, chroma_log2_weight_denom;
356   gint i, j;
357   GstH265PPS *pps = header->pps;
358   gboolean is_rext = _is_range_extension_profile (self->parent.profile);
359
360   if (GST_H265_IS_I_SLICE (header) ||
361       (!pps->weighted_pred_flag && GST_H265_IS_P_SLICE (header)) ||
362       (!pps->weighted_bipred_flag && GST_H265_IS_B_SLICE (header)))
363     return;
364
365   slice_param->base.luma_log2_weight_denom =
366       header->pred_weight_table.luma_log2_weight_denom;
367
368   if (pps->sps->chroma_array_type != 0)
369     slice_param->base.delta_chroma_log2_weight_denom =
370         header->pred_weight_table.delta_chroma_log2_weight_denom;
371
372   for (i = 0; i <= header->num_ref_idx_l0_active_minus1; i++) {
373     if (!header->pred_weight_table.luma_weight_l0_flag[i])
374       continue;
375
376     slice_param->base.delta_luma_weight_l0[i] =
377         header->pred_weight_table.delta_luma_weight_l0[i];
378     slice_param->base.luma_offset_l0[i] =
379         header->pred_weight_table.luma_offset_l0[i];
380
381     if (is_rext) {
382       slice_param->rext.luma_offset_l0[i] =
383           header->pred_weight_table.luma_offset_l0[i];
384     }
385   }
386
387   chroma_log2_weight_denom = slice_param->base.luma_log2_weight_denom +
388       slice_param->base.delta_chroma_log2_weight_denom;
389
390   for (i = 0; i <= header->num_ref_idx_l0_active_minus1; i++) {
391     if (!header->pred_weight_table.chroma_weight_l0_flag[i])
392       continue;
393
394     for (j = 0; j < 2; j++) {
395       gint16 delta_chroma_offset_l0 =
396           header->pred_weight_table.delta_chroma_offset_l0[i][j];
397       gint chroma_offset;
398
399       slice_param->base.delta_chroma_weight_l0[i][j] =
400           header->pred_weight_table.delta_chroma_weight_l0[i][j];
401
402       /* Find  ChromaWeightL0 */
403       chroma_weight = (1 << chroma_log2_weight_denom) +
404           header->pred_weight_table.delta_chroma_weight_l0[i][j];
405       chroma_offset = self->WpOffsetHalfRangeC + delta_chroma_offset_l0
406           - ((self->WpOffsetHalfRangeC * chroma_weight)
407           >> chroma_log2_weight_denom);
408
409       /* 7-56 */
410       slice_param->base.ChromaOffsetL0[i][j] = CLAMP (chroma_offset,
411           -self->WpOffsetHalfRangeC, self->WpOffsetHalfRangeC - 1);
412
413       if (is_rext) {
414         slice_param->rext.ChromaOffsetL0[i][j] =
415             slice_param->base.ChromaOffsetL0[i][j];
416       }
417     }
418   }
419
420   /* Skip l1 if this is not a B-Frame. */
421   if (!GST_H265_IS_B_SLICE (header))
422     return;
423
424   for (i = 0; i <= header->num_ref_idx_l1_active_minus1; i++) {
425     if (!header->pred_weight_table.luma_weight_l1_flag[i])
426       continue;
427
428     slice_param->base.delta_luma_weight_l1[i] =
429         header->pred_weight_table.delta_luma_weight_l1[i];
430     slice_param->base.luma_offset_l1[i] =
431         header->pred_weight_table.luma_offset_l1[i];
432
433     if (is_rext) {
434       slice_param->rext.luma_offset_l1[i] =
435           header->pred_weight_table.luma_offset_l1[i];
436     }
437   }
438
439   for (i = 0; i <= header->num_ref_idx_l1_active_minus1; i++) {
440     if (!header->pred_weight_table.chroma_weight_l1_flag[i])
441       continue;
442
443     for (j = 0; j < 2; j++) {
444       gint16 delta_chroma_offset_l1 =
445           header->pred_weight_table.delta_chroma_offset_l1[i][j];
446       gint chroma_offset;
447
448       slice_param->base.delta_chroma_weight_l1[i][j] =
449           header->pred_weight_table.delta_chroma_weight_l1[i][j];
450
451       /* Find  ChromaWeightL1 */
452       chroma_weight = (1 << chroma_log2_weight_denom) +
453           header->pred_weight_table.delta_chroma_weight_l1[i][j];
454
455       chroma_offset = self->WpOffsetHalfRangeC + delta_chroma_offset_l1
456           - ((self->WpOffsetHalfRangeC * chroma_weight)
457           >> chroma_log2_weight_denom);
458
459       /* 7-56 */
460       slice_param->base.ChromaOffsetL1[i][j] = CLAMP (chroma_offset,
461           -self->WpOffsetHalfRangeC, self->WpOffsetHalfRangeC - 1);
462
463       if (is_rext) {
464         slice_param->rext.ChromaOffsetL1[i][j] =
465             slice_param->base.ChromaOffsetL1[i][j];
466       }
467     }
468   }
469 }
470
471 static inline guint
472 _get_slice_data_byte_offset (GstH265SliceHdr * slice_hdr,
473     guint nal_header_bytes)
474 {
475   guint epb_count;
476
477   epb_count = slice_hdr->n_emulation_prevention_bytes;
478   return nal_header_bytes + (slice_hdr->header_size + 7) / 8 - epb_count;
479 }
480
481 static GstFlowReturn
482 gst_va_h265_dec_decode_slice (GstH265Decoder * decoder,
483     GstH265Picture * picture, GstH265Slice * slice, GArray * ref_pic_list0,
484     GArray * ref_pic_list1)
485 {
486   GstH265SliceHdr *header = &slice->header;
487   GstH265NalUnit *nalu = &slice->nalu;
488   GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
489   GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
490   GstVaDecodePicture *va_pic;
491   VASliceParameterBufferHEVCExtension *slice_param;
492
493   va_pic = gst_h265_picture_get_user_data (picture);
494   if (!_submit_previous_slice (base, va_pic)) {
495     _replace_previous_slice (self, NULL, 0);
496     GST_ERROR_OBJECT (base, "Failed to submit previous slice buffers");
497     return GST_FLOW_ERROR;
498   }
499
500   slice_param = &self->prev_slice.param;
501
502   /* *INDENT-OFF* */
503   slice_param->base = (VASliceParameterBufferHEVC) {
504     .slice_data_size = nalu->size,
505     .slice_data_offset = 0,
506     .slice_data_flag = VA_SLICE_DATA_FLAG_ALL,
507     .slice_data_byte_offset = _get_slice_data_byte_offset (header, nalu->header_bytes),
508     .slice_segment_address = header->segment_address,
509     .collocated_ref_idx = header->temporal_mvp_enabled_flag ? header->collocated_ref_idx : 0xFF,
510     .num_ref_idx_l0_active_minus1 = header->num_ref_idx_l0_active_minus1,
511     .num_ref_idx_l1_active_minus1 = header->num_ref_idx_l1_active_minus1,
512     .slice_qp_delta = header->qp_delta,
513     .slice_cb_qp_offset = header->cb_qp_offset,
514     .slice_cr_qp_offset = header->cr_qp_offset,
515     .slice_beta_offset_div2 = header->beta_offset_div2,
516     .slice_tc_offset_div2 = header->tc_offset_div2,
517     .five_minus_max_num_merge_cand = header->five_minus_max_num_merge_cand,
518     .num_entry_point_offsets = header->num_entry_point_offsets,
519     .entry_offset_to_subset_array = 0, /* does not exist in spec */
520     .slice_data_num_emu_prevn_bytes = header->n_emulation_prevention_bytes,
521     .LongSliceFlags.fields = {
522       .LastSliceOfPic = 0, /* the last one will be set on end_picture() */
523       .dependent_slice_segment_flag = header->dependent_slice_segment_flag,
524       .slice_type = header->type,
525       .color_plane_id = header->colour_plane_id,
526       .slice_sao_luma_flag = header->sao_luma_flag,
527       .slice_sao_chroma_flag = header->sao_chroma_flag,
528       .mvd_l1_zero_flag = header->mvd_l1_zero_flag,
529       .cabac_init_flag = header->cabac_init_flag,
530       .slice_temporal_mvp_enabled_flag = header->temporal_mvp_enabled_flag,
531       .slice_deblocking_filter_disabled_flag =
532           header->deblocking_filter_disabled_flag,
533       .collocated_from_l0_flag = header->collocated_from_l0_flag,
534       .slice_loop_filter_across_slices_enabled_flag =
535           header->loop_filter_across_slices_enabled_flag,
536     },
537   };
538   /* *INDENT-ON* */
539
540   if (_is_range_extension_profile (base->profile)
541       || _is_screen_content_ext_profile (base->profile)) {
542     /* *INDENT-OFF* */
543     slice_param->rext = (VASliceParameterBufferHEVCRext) {
544       .slice_ext_flags.bits = {
545         .cu_chroma_qp_offset_enabled_flag = header->cu_chroma_qp_offset_enabled_flag,
546         .use_integer_mv_flag = header->use_integer_mv_flag,
547       },
548       .slice_act_y_qp_offset = header->slice_act_y_qp_offset,
549       .slice_act_cb_qp_offset = header->slice_act_cb_qp_offset,
550       .slice_act_cr_qp_offset = header->slice_act_cr_qp_offset,
551     };
552     /* *INDENT-ON* */
553   }
554
555   _fill_ref_pic_list (decoder, picture, slice_param->base.RefPicList[0],
556       ref_pic_list0);
557   _fill_ref_pic_list (decoder, picture, slice_param->base.RefPicList[1],
558       ref_pic_list1);
559
560   _fill_pred_weight_table (GST_VA_H265_DEC (decoder), header, slice_param);
561
562   _replace_previous_slice (self, slice->nalu.data + slice->nalu.offset,
563       slice->nalu.size);
564
565   return GST_FLOW_OK;
566 }
567
568 static void
569 _fill_picture_range_ext_parameter (GstVaH265Dec * decoder,
570     GstH265SPS * sps, GstH265PPS * pps)
571 {
572   VAPictureParameterBufferHEVCRext *pic_param = &decoder->pic_param.rext;
573
574   GstH265SPSExtensionParams *sps_ext = &sps->sps_extnsion_params;
575   GstH265PPSExtensionParams *pps_ext = &pps->pps_extension_params;
576
577   /* *INDENT-OFF* */
578   *pic_param = (VAPictureParameterBufferHEVCRext) {
579     .range_extension_pic_fields.bits = {
580       .transform_skip_rotation_enabled_flag = sps_ext->transform_skip_rotation_enabled_flag,
581       .transform_skip_context_enabled_flag = sps_ext->transform_skip_context_enabled_flag,
582       .implicit_rdpcm_enabled_flag = sps_ext->implicit_rdpcm_enabled_flag,
583       .explicit_rdpcm_enabled_flag = sps_ext->explicit_rdpcm_enabled_flag,
584       .extended_precision_processing_flag = sps_ext->extended_precision_processing_flag,
585       .intra_smoothing_disabled_flag = sps_ext->intra_smoothing_disabled_flag,
586       .high_precision_offsets_enabled_flag = sps_ext->high_precision_offsets_enabled_flag,
587       .persistent_rice_adaptation_enabled_flag = sps_ext->persistent_rice_adaptation_enabled_flag,
588       .cabac_bypass_alignment_enabled_flag = sps_ext->cabac_bypass_alignment_enabled_flag,
589       .cross_component_prediction_enabled_flag = pps_ext->cross_component_prediction_enabled_flag,
590       .chroma_qp_offset_list_enabled_flag = pps_ext->chroma_qp_offset_list_enabled_flag,
591     },
592     .diff_cu_chroma_qp_offset_depth = pps_ext->diff_cu_chroma_qp_offset_depth,
593     .chroma_qp_offset_list_len_minus1 = pps_ext->chroma_qp_offset_list_len_minus1,
594     .log2_sao_offset_scale_luma = pps_ext->log2_sao_offset_scale_luma,
595     .log2_sao_offset_scale_chroma = pps_ext->log2_sao_offset_scale_chroma,
596     .log2_max_transform_skip_block_size_minus2 = pps_ext->log2_max_transform_skip_block_size_minus2,
597   };
598   /* *INDENT-ON* */
599
600   memcpy (pic_param->cb_qp_offset_list, pps_ext->cb_qp_offset_list,
601       sizeof (pic_param->cb_qp_offset_list));
602   memcpy (pic_param->cr_qp_offset_list, pps_ext->cr_qp_offset_list,
603       sizeof (pic_param->cr_qp_offset_list));
604 }
605
606 static void
607 _fill_screen_content_ext_parameter (GstVaH265Dec * decoder,
608     GstH265SPS * sps, GstH265PPS * pps)
609 {
610   VAPictureParameterBufferHEVCScc *pic_param = &decoder->pic_param.scc;
611   const GstH265PPSSccExtensionParams *pps_scc = &pps->pps_scc_extension_params;
612   const GstH265SPSSccExtensionParams *sps_scc = &sps->sps_scc_extension_params;
613   guint32 num_comps;
614   guint i, n;
615
616   /* *INDENT-OFF* */
617   *pic_param = (VAPictureParameterBufferHEVCScc) {
618     .screen_content_pic_fields.bits = {
619       .pps_curr_pic_ref_enabled_flag = pps_scc->pps_curr_pic_ref_enabled_flag,
620       .palette_mode_enabled_flag = sps_scc->palette_mode_enabled_flag,
621       .motion_vector_resolution_control_idc = sps_scc->motion_vector_resolution_control_idc,
622       .intra_boundary_filtering_disabled_flag = sps_scc->intra_boundary_filtering_disabled_flag,
623       .residual_adaptive_colour_transform_enabled_flag = pps_scc->residual_adaptive_colour_transform_enabled_flag,
624       .pps_slice_act_qp_offsets_present_flag = pps_scc->pps_slice_act_qp_offsets_present_flag,
625     },
626     .palette_max_size = sps_scc->palette_max_size,
627     .delta_palette_max_predictor_size = sps_scc->delta_palette_max_predictor_size,
628     .pps_act_y_qp_offset_plus5 = pps_scc->pps_act_y_qp_offset_plus5,
629     .pps_act_cb_qp_offset_plus5 = pps_scc->pps_act_cb_qp_offset_plus5,
630     .pps_act_cr_qp_offset_plus3 = pps_scc->pps_act_cr_qp_offset_plus3,
631   };
632   /* *INDENT-ON* */
633
634   /* firstly use the pps, then sps */
635   num_comps = sps->chroma_format_idc ? 3 : 1;
636
637   if (pps_scc->pps_palette_predictor_initializers_present_flag) {
638     pic_param->predictor_palette_size =
639         pps_scc->pps_num_palette_predictor_initializer;
640     for (n = 0; n < num_comps; n++)
641       for (i = 0; i < pps_scc->pps_num_palette_predictor_initializer; i++)
642         pic_param->predictor_palette_entries[n][i] =
643             (uint16_t) pps_scc->pps_palette_predictor_initializer[n][i];
644   } else if (sps_scc->sps_palette_predictor_initializers_present_flag) {
645     pic_param->predictor_palette_size =
646         sps_scc->sps_num_palette_predictor_initializer_minus1 + 1;
647     for (n = 0; n < num_comps; n++)
648       for (i = 0;
649           i < sps_scc->sps_num_palette_predictor_initializer_minus1 + 1; i++)
650         pic_param->predictor_palette_entries[n][i] =
651             (uint16_t) sps_scc->sps_palette_predictor_initializer[n][i];
652   }
653 }
654
655 static GstFlowReturn
656 gst_va_h265_dec_start_picture (GstH265Decoder * decoder,
657     GstH265Picture * picture, GstH265Slice * slice, GstH265Dpb * dpb)
658 {
659   GstH265PPS *pps;
660   GstH265SPS *sps;
661   GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
662   GstVaBaseDec *base = &self->parent;
663   GstVaDecodePicture *va_pic;
664   GstH265ScalingList *scaling_list = NULL;
665   VAIQMatrixBufferHEVC iq_matrix = { 0, };
666   VAPictureParameterBufferHEVCExtension *pic_param = &self->pic_param;
667   gsize pic_param_size;
668   guint i;
669
670   va_pic = gst_h265_picture_get_user_data (picture);
671
672   pps = slice->header.pps;
673   sps = pps->sps;
674
675   /* *INDENT-OFF* */
676   pic_param->base = (VAPictureParameterBufferHEVC) {
677     .pic_width_in_luma_samples = sps->pic_width_in_luma_samples,
678     .pic_height_in_luma_samples = sps->pic_height_in_luma_samples,
679     .sps_max_dec_pic_buffering_minus1 = sps->max_dec_pic_buffering_minus1[sps->max_sub_layers_minus1],
680     .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8,
681     .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8,
682     .pcm_sample_bit_depth_luma_minus1 = sps->pcm_sample_bit_depth_luma_minus1,
683     .pcm_sample_bit_depth_chroma_minus1 = sps->pcm_sample_bit_depth_chroma_minus1,
684     .log2_min_luma_coding_block_size_minus3 = sps->log2_min_luma_coding_block_size_minus3,
685     .log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_luma_coding_block_size,
686     .log2_min_transform_block_size_minus2 = sps->log2_min_transform_block_size_minus2,
687     .log2_diff_max_min_transform_block_size = sps->log2_diff_max_min_transform_block_size,
688     .log2_min_pcm_luma_coding_block_size_minus3 = sps->log2_min_pcm_luma_coding_block_size_minus3,
689     .log2_diff_max_min_pcm_luma_coding_block_size = sps->log2_diff_max_min_pcm_luma_coding_block_size,
690     .max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra,
691     .max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter,
692     .init_qp_minus26 = pps->init_qp_minus26,
693     .diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth,
694     .pps_cb_qp_offset = pps->cb_qp_offset,
695     .pps_cr_qp_offset = pps->cr_qp_offset,
696     .log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level_minus2,
697     .num_tile_columns_minus1 = pps->num_tile_columns_minus1,
698     .num_tile_rows_minus1 = pps->num_tile_rows_minus1,
699     .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4,
700     .num_short_term_ref_pic_sets = sps->num_short_term_ref_pic_sets,
701     .num_long_term_ref_pic_sps = sps->num_long_term_ref_pics_sps,
702     .num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active_minus1,
703     .num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active_minus1,
704     .pps_beta_offset_div2 = pps->beta_offset_div2,
705     .pps_tc_offset_div2 = pps->tc_offset_div2,
706     .num_extra_slice_header_bits = pps->num_extra_slice_header_bits,
707     .st_rps_bits = slice->header.short_term_ref_pic_set_size, /* FIXME missing emulation bits removal */
708     .pic_fields.bits = {
709       .chroma_format_idc = sps->chroma_format_idc,
710       .separate_colour_plane_flag = sps->separate_colour_plane_flag,
711       .pcm_enabled_flag = sps->pcm_enabled_flag,
712       .scaling_list_enabled_flag = sps->scaling_list_enabled_flag,
713       .transform_skip_enabled_flag = pps->transform_skip_enabled_flag,
714       .amp_enabled_flag = sps->amp_enabled_flag,
715       .strong_intra_smoothing_enabled_flag = sps->strong_intra_smoothing_enabled_flag,
716       .sign_data_hiding_enabled_flag = pps->sign_data_hiding_enabled_flag,
717       .constrained_intra_pred_flag = pps->constrained_intra_pred_flag,
718       .cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag,
719       .weighted_pred_flag = pps->weighted_pred_flag,
720       .weighted_bipred_flag = pps->weighted_bipred_flag,
721       .transquant_bypass_enabled_flag = pps->transquant_bypass_enabled_flag,
722       .tiles_enabled_flag = pps->tiles_enabled_flag,
723       .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag,
724       .pps_loop_filter_across_slices_enabled_flag = pps->loop_filter_across_slices_enabled_flag,
725       .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag,
726       .pcm_loop_filter_disabled_flag = sps->pcm_loop_filter_disabled_flag,
727       /* Not set by FFMPEG either */
728       .NoPicReorderingFlag = 0,
729       .NoBiPredFlag = 0,
730     },
731     .slice_parsing_fields.bits = {
732       .lists_modification_present_flag = pps->lists_modification_present_flag,
733       .long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag,
734       .sps_temporal_mvp_enabled_flag = sps->temporal_mvp_enabled_flag,
735       .cabac_init_present_flag = pps->cabac_init_present_flag,
736       .output_flag_present_flag = pps->output_flag_present_flag,
737       .dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag,
738       .pps_slice_chroma_qp_offsets_present_flag = pps->slice_chroma_qp_offsets_present_flag,
739       .sample_adaptive_offset_enabled_flag = sps->sample_adaptive_offset_enabled_flag,
740       .deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag,
741       .pps_disable_deblocking_filter_flag = pps->deblocking_filter_disabled_flag,
742       .slice_segment_header_extension_present_flag = pps->slice_segment_header_extension_present_flag,
743       .RapPicFlag = picture->RapPicFlag,
744       .IdrPicFlag = GST_H265_IS_NAL_TYPE_IDR (slice->nalu.type),
745       .IntraPicFlag = GST_H265_IS_NAL_TYPE_IRAP (slice->nalu.type),
746     },
747   };
748   /* *INDENT-ON* */
749
750   if (_is_range_extension_profile (self->parent.profile)
751       || _is_screen_content_ext_profile (self->parent.profile)) {
752     _fill_picture_range_ext_parameter (self, sps, pps);
753     if (_is_screen_content_ext_profile (self->parent.profile))
754       _fill_screen_content_ext_parameter (self, sps, pps);
755   }
756
757   for (i = 0; i <= pps->num_tile_columns_minus1; i++)
758     pic_param->base.column_width_minus1[i] = pps->column_width_minus1[i];
759
760   for (i = 0; i <= pps->num_tile_rows_minus1; i++)
761     pic_param->base.row_height_minus1[i] = pps->row_height_minus1[i];
762
763   _fill_vaapi_pic (decoder, &pic_param->base.CurrPic, picture);
764
765   /* reference frames */
766   {
767     GArray *ref_list = gst_h265_dpb_get_pictures_all (dpb);
768     guint j;
769
770     i = 0;
771     for (j = 0; j < 15 && j < ref_list->len; j++) {
772       GstH265Picture *pic = g_array_index (ref_list, GstH265Picture *, j);
773
774       if (pic->ref) {
775         _fill_vaapi_pic (decoder, &pic_param->base.ReferenceFrames[i], pic);
776         i++;
777       }
778     }
779     g_array_unref (ref_list);
780
781     /* 7.4.3.3.3, the current decoded picture is marked as "used for
782        long-term reference". Current picture is not in the DPB now. */
783     if (pps->pps_scc_extension_params.pps_curr_pic_ref_enabled_flag && i < 15) {
784       pic_param->base.ReferenceFrames[i].picture_id =
785           gst_va_decode_picture_get_surface (gst_h265_picture_get_user_data
786           (picture));
787       pic_param->base.ReferenceFrames[i].pic_order_cnt = picture->pic_order_cnt;
788       pic_param->base.ReferenceFrames[i].flags |=
789           VA_PICTURE_HEVC_LONG_TERM_REFERENCE;
790       pic_param->base.ReferenceFrames[i].flags |=
791           _find_frame_rps_type (decoder, picture);
792       i++;
793     }
794
795     for (; i < 15; i++)
796       _init_vaapi_pic (&pic_param->base.ReferenceFrames[i]);
797   }
798
799   pic_param_size = _is_range_extension_profile (self->parent.profile)
800       || _is_screen_content_ext_profile (self->parent.profile) ?
801       sizeof (*pic_param) : sizeof (pic_param->base);
802   if (!gst_va_decoder_add_param_buffer (base->decoder, va_pic,
803           VAPictureParameterBufferType, pic_param, pic_param_size))
804     return GST_FLOW_ERROR;
805
806   if (pps->scaling_list_data_present_flag ||
807       (sps->scaling_list_enabled_flag
808           && !sps->scaling_list_data_present_flag)) {
809     scaling_list = &pps->scaling_list;
810     GST_DEBUG_OBJECT (decoder, "Passing scaling list from PPS");
811   } else if (sps->scaling_list_enabled_flag &&
812       sps->scaling_list_data_present_flag) {
813     scaling_list = &sps->scaling_list;
814     GST_DEBUG_OBJECT (decoder, "Passing scaling list from SPS");
815   }
816
817   if (scaling_list) {
818     for (i = 0; i < G_N_ELEMENTS (iq_matrix.ScalingList4x4); i++)
819       gst_h265_quant_matrix_4x4_get_raster_from_uprightdiagonal
820           (iq_matrix.ScalingList4x4[i], scaling_list->scaling_lists_4x4[i]);
821
822     for (i = 0; i < G_N_ELEMENTS (iq_matrix.ScalingList8x8); i++)
823       gst_h265_quant_matrix_8x8_get_raster_from_uprightdiagonal
824           (iq_matrix.ScalingList8x8[i], scaling_list->scaling_lists_8x8[i]);
825
826     for (i = 0; i < G_N_ELEMENTS (iq_matrix.ScalingList16x16); i++)
827       gst_h265_quant_matrix_16x16_get_raster_from_uprightdiagonal
828           (iq_matrix.ScalingList16x16[i], scaling_list->scaling_lists_16x16[i]);
829
830     for (i = 0; i < G_N_ELEMENTS (iq_matrix.ScalingList32x32); i++)
831       gst_h265_quant_matrix_32x32_get_raster_from_uprightdiagonal
832           (iq_matrix.ScalingList32x32[i], scaling_list->scaling_lists_32x32[i]);
833
834     for (i = 0; i < 6; i++)
835       iq_matrix.ScalingListDC16x16[i] =
836           scaling_list->scaling_list_dc_coef_minus8_16x16[i] + 8;
837
838     for (i = 0; i < 2; i++)
839       iq_matrix.ScalingListDC32x32[i] =
840           scaling_list->scaling_list_dc_coef_minus8_32x32[i] + 8;
841
842     if (!gst_va_decoder_add_param_buffer (base->decoder, va_pic,
843             VAIQMatrixBufferType, &iq_matrix, sizeof (iq_matrix))) {
844       return GST_FLOW_ERROR;
845     }
846   }
847
848   return GST_FLOW_OK;
849 }
850
851 static GstFlowReturn
852 gst_va_h265_dec_new_picture (GstH265Decoder * decoder,
853     GstVideoCodecFrame * frame, GstH265Picture * picture)
854 {
855   GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
856   GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
857   GstVaDecodePicture *pic;
858   GstBuffer *output_buffer;
859   GstVideoDecoder *vdec = GST_VIDEO_DECODER (decoder);
860
861   if (base->need_negotiation) {
862     if (!gst_video_decoder_negotiate (vdec)) {
863       GST_ERROR_OBJECT (self, "Failed to negotiate with downstream");
864       return GST_FLOW_NOT_NEGOTIATED;
865     }
866   }
867
868   output_buffer = gst_video_decoder_allocate_output_buffer (vdec);
869   if (!output_buffer) {
870     self->last_ret = GST_FLOW_ERROR;
871     goto error;
872   }
873   self->last_ret = GST_FLOW_OK;
874
875   pic = gst_va_decode_picture_new (base->decoder, output_buffer);
876   gst_buffer_unref (output_buffer);
877
878   gst_h265_picture_set_user_data (picture, pic,
879       (GDestroyNotify) gst_va_decode_picture_free);
880
881   GST_LOG_OBJECT (self, "New va decode picture %p - %#x", pic,
882       gst_va_decode_picture_get_surface (pic));
883
884   return GST_FLOW_OK;
885
886 error:
887   {
888     GST_WARNING_OBJECT (self,
889         "Failed to allocated output buffer, return %s",
890         gst_flow_get_name (self->last_ret));
891     return self->last_ret;
892   }
893 }
894
895 static guint
896 _get_rtformat (GstVaH265Dec * self, guint8 bit_depth_luma,
897     guint8 bit_depth_chroma, guint8 chroma_format_idc)
898 {
899   guint8 bit_num = MAX (bit_depth_luma, bit_depth_chroma);
900
901   switch (bit_num) {
902     case 11:
903     case 12:
904       if (chroma_format_idc == 3)
905         return VA_RT_FORMAT_YUV444_12;
906       if (chroma_format_idc == 2)
907         return VA_RT_FORMAT_YUV422_12;
908       else
909         return VA_RT_FORMAT_YUV420_12;
910       break;
911     case 9:
912     case 10:
913       if (chroma_format_idc == 3)
914         return VA_RT_FORMAT_YUV444_10;
915       if (chroma_format_idc == 2)
916         return VA_RT_FORMAT_YUV422_10;
917       else
918         return VA_RT_FORMAT_YUV420_10;
919       break;
920     case 8:
921       if (chroma_format_idc == 3)
922         return VA_RT_FORMAT_YUV444;
923       if (chroma_format_idc == 2)
924         return VA_RT_FORMAT_YUV422;
925       else
926         return VA_RT_FORMAT_YUV420;
927       break;
928     default:
929       GST_ERROR_OBJECT (self, "Unsupported chroma format: %d "
930           "(with depth luma: %d, with depth chroma: %d)",
931           chroma_format_idc, bit_depth_luma, bit_depth_chroma);
932       return 0;
933   }
934 }
935
936 /* *INDENT-OFF* */
937 static const struct
938 {
939   GstH265Profile profile;
940   VAProfile va_profile;
941 } profile_map[] = {
942 #define P(idc, va) { G_PASTE (GST_H265_PROFILE_, idc), G_PASTE (VAProfileHEVC, va) }
943   P (MAIN, Main),
944   P (MAIN_10, Main10),
945   /*P (MAIN_STILL_PICTURE, ),
946   P (MONOCHROME, ),
947   P (MONOCHROME_12, ),
948   P (MONOCHROME_16, ),*/
949   P (MAIN_12, Main12),
950   P (MAIN_422_10, Main422_10),
951   P (MAIN_422_12, Main422_12),
952   P (MAIN_444, Main444),
953   P (MAIN_444_10, Main444_10),
954   P (MAIN_444_12, Main444_12),
955   /*P (MAIN_INTRA, ),
956   P (MAIN_10_INTRA, ),
957   P (MAIN_12_INTRA, ),
958   P (MAIN_422_10_INTRA, ),
959   P (MAIN_422_12_INTRA, ),
960   P (MAIN_444_INTRA, ),
961   P (MAIN_444_10_INTRA, ),
962   P (MAIN_444_12_INTRA, ),
963   P (MAIN_444_16_INTRA, ),
964   P (MAIN_444_STILL_PICTURE, ),
965   P (MAIN_444_16_STILL_PICTURE, ),
966   P (MONOCHROME_10, ),
967   P (HIGH_THROUGHPUT_444, ),
968   P (HIGH_THROUGHPUT_444_10, ),
969   P (HIGH_THROUGHPUT_444_14, ),
970   P (HIGH_THROUGHPUT_444_16_INTRA, ),*/
971   P (SCREEN_EXTENDED_MAIN, SccMain),
972   P (SCREEN_EXTENDED_MAIN_10, SccMain10),
973   P (SCREEN_EXTENDED_MAIN_444, SccMain444),
974   /*P (SCREEN_EXTENDED_MAIN_444_10, ),
975   P (SCREEN_EXTENDED_HIGH_THROUGHPUT_444, ),
976   P (SCREEN_EXTENDED_HIGH_THROUGHPUT_444_10, ),
977   P (SCREEN_EXTENDED_HIGH_THROUGHPUT_444_14, ),
978   P (MULTIVIEW_MAIN, ),
979   P (SCALABLE_MAIN, ),
980   P (SCALABLE_MAIN_10, ),
981   P (SCALABLE_MONOCHROME, ),
982   P (SCALABLE_MONOCHROME_12, ),
983   P (SCALABLE_MONOCHROME_16, ),
984   P (SCALABLE_MAIN_444, ),
985   P (3D_MAIN, ),*/
986 #undef P
987 };
988 /* *INDENT-ON* */
989
990 static VAProfile
991 _get_profile (GstVaH265Dec * self, const GstH265SPS * sps, gint max_dpb_size)
992 {
993   GstH265Decoder *h265_decoder = GST_H265_DECODER (self);
994   GstVaBaseDec *base = GST_VA_BASE_DEC (self);
995   GstH265Profile profile = gst_h265_get_profile_from_sps ((GstH265SPS *) sps);
996   VAProfile profiles[4];
997   gint i = 0, j;
998
999   /* 1. The profile directly specified by the SPS should always be the
1000      first choice. It is the exact one.
1001      2. The profile in the input caps may contain the compatible profile
1002      chosen by the upstream element. Upstream element such as the parse
1003      may already decide the best compatible profile for us. We also need
1004      to consider it as a choice. */
1005
1006   for (j = 0; j < G_N_ELEMENTS (profile_map); j++) {
1007     if (profile_map[j].profile == profile) {
1008       profiles[i++] = profile_map[j].va_profile;
1009       break;
1010     }
1011   }
1012
1013   if (h265_decoder->input_state->caps
1014       && gst_caps_is_fixed (h265_decoder->input_state->caps)) {
1015     GstH265Profile compatible_profile = GST_H265_PROFILE_INVALID;
1016     GstStructure *structure;
1017     const gchar *profile_str;
1018
1019     structure = gst_caps_get_structure (h265_decoder->input_state->caps, 0);
1020
1021     profile_str = gst_structure_get_string (structure, "profile");
1022     if (profile_str)
1023       compatible_profile = gst_h265_profile_from_string (profile_str);
1024
1025     if (compatible_profile != profile) {
1026       GST_INFO_OBJECT (self, "The upstream set the compatible profile %s, "
1027           "also consider it as a candidate.", profile_str);
1028
1029       for (j = 0; j < G_N_ELEMENTS (profile_map); j++) {
1030         if (profile_map[j].profile == compatible_profile) {
1031           profiles[i++] = profile_map[j].va_profile;
1032           break;
1033         }
1034       }
1035     }
1036   }
1037
1038   for (j = 0; j < i && j < G_N_ELEMENTS (profiles); j++) {
1039     if (gst_va_decoder_has_profile (base->decoder, profiles[j]))
1040       return profiles[j];
1041   }
1042
1043   GST_ERROR_OBJECT (self, "Unsupported profile: %d", profile);
1044
1045   return VAProfileNone;
1046 }
1047
1048 static GstFlowReturn
1049 gst_va_h265_dec_new_sequence (GstH265Decoder * decoder, const GstH265SPS * sps,
1050     gint max_dpb_size)
1051 {
1052   GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
1053   GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
1054   VAProfile profile;
1055   gint display_width;
1056   gint display_height;
1057   gint padding_left, padding_right, padding_top, padding_bottom;
1058   guint rt_format;
1059   gboolean negotiation_needed = FALSE;
1060
1061   if (self->dpb_size < max_dpb_size)
1062     self->dpb_size = max_dpb_size;
1063
1064   if (sps->conformance_window_flag) {
1065     display_width = sps->crop_rect_width;
1066     display_height = sps->crop_rect_height;
1067     padding_left = sps->crop_rect_x;
1068     padding_right = sps->width - sps->crop_rect_x - display_width;
1069     padding_top = sps->crop_rect_y;
1070     padding_bottom = sps->height - sps->crop_rect_y - display_height;
1071   } else {
1072     display_width = sps->width;
1073     display_height = sps->height;
1074     padding_left = padding_right = padding_top = padding_bottom = 0;
1075   }
1076
1077   profile = _get_profile (self, sps, max_dpb_size);
1078   if (profile == VAProfileNone)
1079     return GST_FLOW_NOT_NEGOTIATED;
1080
1081   rt_format = _get_rtformat (self, sps->bit_depth_luma_minus8 + 8,
1082       sps->bit_depth_chroma_minus8 + 8, sps->chroma_format_idc);
1083   if (rt_format == 0)
1084     return GST_FLOW_NOT_NEGOTIATED;
1085
1086   if (!gst_va_decoder_config_is_equal (base->decoder, profile,
1087           rt_format, sps->width, sps->height)) {
1088     base->profile = profile;
1089     base->rt_format = rt_format;
1090     self->coded_width = sps->width;
1091     self->coded_height = sps->height;
1092
1093     negotiation_needed = TRUE;
1094     GST_INFO_OBJECT (self, "Format changed to %s [%x] (%dx%d)",
1095         gst_va_profile_name (profile), rt_format, self->coded_width,
1096         self->coded_height);
1097   }
1098
1099   if (base->width != display_width || base->height != display_height) {
1100     base->width = display_width;
1101     base->height = display_height;
1102
1103     negotiation_needed = TRUE;
1104     GST_INFO_OBJECT (self, "Resolution changed to %dx%d", base->width,
1105         base->height);
1106   }
1107
1108   base->need_valign = base->width < self->coded_width
1109       || base->height < self->coded_height;
1110   if (base->need_valign) {
1111     /* *INDENT-OFF* */
1112     if (base->valign.padding_left != padding_left ||
1113         base->valign.padding_right != padding_right ||
1114         base->valign.padding_top != padding_top ||
1115         base->valign.padding_bottom != padding_bottom) {
1116       negotiation_needed = TRUE;
1117       GST_INFO_OBJECT (self, "crop rect changed to (%d,%d)-->(%d,%d)",
1118           padding_left, padding_top, padding_right, padding_bottom);
1119     }
1120     base->valign = (GstVideoAlignment) {
1121       .padding_left = padding_left,
1122       .padding_right = padding_right,
1123       .padding_top = padding_top,
1124       .padding_bottom = padding_bottom,
1125     };
1126     /* *INDENT-ON* */
1127   }
1128
1129   base->min_buffers = self->dpb_size + 4;       /* dpb size + scratch surfaces */
1130
1131   base->need_negotiation = negotiation_needed;
1132
1133   {
1134     /* FIXME: We don't have parser API for sps_range_extension, so
1135      * assuming high_precision_offsets_enabled_flag as zero */
1136     guint high_precision_offsets_enabled_flag = 0, bitdepthC = 0;
1137
1138     /* Calculate WpOffsetHalfRangeC: (7-34) */
1139     bitdepthC = sps->bit_depth_chroma_minus8 + 8;
1140     self->WpOffsetHalfRangeC =
1141         1 << (high_precision_offsets_enabled_flag ? (bitdepthC - 1) : 7);
1142   }
1143
1144   return GST_FLOW_OK;
1145 }
1146
1147 static GstCaps *
1148 _complete_sink_caps (GstCaps * sinkcaps)
1149 {
1150   GstCaps *caps = gst_caps_copy (sinkcaps);
1151   GValue val = G_VALUE_INIT;
1152   const gchar *streamformat[] = { "hvc1", "hev1", "byte-stream" };
1153   gint i;
1154
1155   g_value_init (&val, G_TYPE_STRING);
1156   g_value_set_string (&val, "au");
1157   gst_caps_set_value (caps, "alignment", &val);
1158   g_value_unset (&val);
1159
1160   gst_value_list_init (&val, G_N_ELEMENTS (streamformat));
1161   for (i = 0; i < G_N_ELEMENTS (streamformat); i++) {
1162     GValue v = G_VALUE_INIT;
1163
1164     g_value_init (&v, G_TYPE_STRING);
1165     g_value_set_string (&v, streamformat[i]);
1166     gst_value_list_append_value (&val, &v);
1167     g_value_unset (&v);
1168   }
1169   gst_caps_set_value (caps, "stream-format", &val);
1170   g_value_unset (&val);
1171
1172   return caps;
1173 }
1174
1175 static GstCaps *
1176 gst_va_h265_dec_getcaps (GstVideoDecoder * decoder, GstCaps * filter)
1177 {
1178   GstCaps *sinkcaps, *caps = NULL, *tmp;
1179   GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
1180
1181   if (base->decoder)
1182     caps = gst_va_decoder_get_sinkpad_caps (base->decoder);
1183
1184   if (caps) {
1185     sinkcaps = _complete_sink_caps (caps);
1186     gst_caps_unref (caps);
1187     if (filter) {
1188       tmp = gst_caps_intersect_full (filter, sinkcaps,
1189           GST_CAPS_INTERSECT_FIRST);
1190       gst_caps_unref (sinkcaps);
1191       caps = tmp;
1192     } else {
1193       caps = sinkcaps;
1194     }
1195     GST_LOG_OBJECT (base, "Returning caps %" GST_PTR_FORMAT, caps);
1196   } else if (!caps) {
1197     caps = gst_video_decoder_proxy_getcaps (decoder, NULL, filter);
1198   }
1199
1200   return caps;
1201 }
1202
1203 static gboolean
1204 gst_va_h265_dec_negotiate (GstVideoDecoder * decoder)
1205 {
1206   GstVaBaseDec *base = GST_VA_BASE_DEC (decoder);
1207   GstVaH265Dec *self = GST_VA_H265_DEC (decoder);
1208   GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
1209   GstCapsFeatures *capsfeatures = NULL;
1210   GstH265Decoder *h265dec = GST_H265_DECODER (decoder);
1211
1212   /* Ignore downstream renegotiation request. */
1213   if (!base->need_negotiation)
1214     return TRUE;
1215
1216   base->need_negotiation = FALSE;
1217
1218   if (gst_va_decoder_is_open (base->decoder)
1219       && !gst_va_decoder_close (base->decoder))
1220     return FALSE;
1221
1222   if (!gst_va_decoder_open (base->decoder, base->profile, base->rt_format))
1223     return FALSE;
1224
1225   if (!gst_va_decoder_set_frame_size (base->decoder, self->coded_width,
1226           self->coded_height))
1227     return FALSE;
1228
1229   if (base->output_state)
1230     gst_video_codec_state_unref (base->output_state);
1231
1232   gst_va_base_dec_get_preferred_format_and_caps_features (base, &format,
1233       &capsfeatures);
1234   if (format == GST_VIDEO_FORMAT_UNKNOWN)
1235     return FALSE;
1236
1237   base->output_state =
1238       gst_video_decoder_set_output_state (decoder, format,
1239       base->width, base->height, h265dec->input_state);
1240
1241   base->output_state->caps = gst_video_info_to_caps (&base->output_state->info);
1242   if (capsfeatures)
1243     gst_caps_set_features_simple (base->output_state->caps, capsfeatures);
1244
1245   GST_INFO_OBJECT (self, "Negotiated caps %" GST_PTR_FORMAT,
1246       base->output_state->caps);
1247
1248   return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
1249 }
1250
1251 static void
1252 gst_va_h265_dec_dispose (GObject * object)
1253 {
1254   g_free (GST_VA_H265_DEC (object)->prev_slice.data);
1255
1256   gst_va_base_dec_close (GST_VIDEO_DECODER (object));
1257
1258   G_OBJECT_CLASS (parent_class)->dispose (object);
1259 }
1260
1261 static void
1262 gst_va_h265_dec_class_init (gpointer g_class, gpointer class_data)
1263 {
1264   GstCaps *src_doc_caps, *sink_doc_caps;
1265   GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
1266   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
1267   GstH265DecoderClass *h265decoder_class = GST_H265_DECODER_CLASS (g_class);
1268   GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (g_class);
1269   struct CData *cdata = class_data;
1270   gchar *long_name;
1271
1272   if (cdata->description) {
1273     long_name = g_strdup_printf ("VA-API H.265 Decoder in %s",
1274         cdata->description);
1275   } else {
1276     long_name = g_strdup ("VA-API H.265 Decoder");
1277   }
1278
1279   gst_element_class_set_metadata (element_class, long_name,
1280       "Codec/Decoder/Video/Hardware",
1281       "VA-API based H.265 video decoder",
1282       "Nicolas Dufresne <nicolas.dufresne@collabora.com>");
1283
1284   sink_doc_caps = gst_caps_from_string (sink_caps_str);
1285   src_doc_caps = gst_caps_from_string (src_caps_str);
1286
1287   parent_class = g_type_class_peek_parent (g_class);
1288
1289   gst_va_base_dec_class_init (GST_VA_BASE_DEC_CLASS (g_class), HEVC,
1290       cdata->render_device_path, cdata->sink_caps, cdata->src_caps,
1291       src_doc_caps, sink_doc_caps);
1292
1293   gobject_class->dispose = gst_va_h265_dec_dispose;
1294
1295   decoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_va_h265_dec_getcaps);
1296   decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_va_h265_dec_negotiate);
1297
1298   h265decoder_class->new_sequence =
1299       GST_DEBUG_FUNCPTR (gst_va_h265_dec_new_sequence);
1300   h265decoder_class->decode_slice =
1301       GST_DEBUG_FUNCPTR (gst_va_h265_dec_decode_slice);
1302
1303   h265decoder_class->new_picture =
1304       GST_DEBUG_FUNCPTR (gst_va_h265_dec_new_picture);
1305   h265decoder_class->output_picture =
1306       GST_DEBUG_FUNCPTR (gst_va_h265_dec_output_picture);
1307   h265decoder_class->start_picture =
1308       GST_DEBUG_FUNCPTR (gst_va_h265_dec_start_picture);
1309   h265decoder_class->end_picture =
1310       GST_DEBUG_FUNCPTR (gst_va_h265_dec_end_picture);
1311
1312   g_free (long_name);
1313   g_free (cdata->description);
1314   g_free (cdata->render_device_path);
1315   gst_caps_unref (cdata->src_caps);
1316   gst_caps_unref (cdata->sink_caps);
1317   g_free (cdata);
1318 }
1319
1320 static void
1321 gst_va_h265_dec_init (GTypeInstance * instance, gpointer g_class)
1322 {
1323   gst_va_base_dec_init (GST_VA_BASE_DEC (instance), GST_CAT_DEFAULT);
1324   gst_h265_decoder_set_process_ref_pic_lists (GST_H265_DECODER (instance),
1325       TRUE);
1326 }
1327
1328 static gpointer
1329 _register_debug_category (gpointer data)
1330 {
1331   GST_DEBUG_CATEGORY_INIT (gst_va_h265dec_debug, "vah265dec", 0,
1332       "VA H265 decoder");
1333
1334   return NULL;
1335 }
1336
1337 gboolean
1338 gst_va_h265_dec_register (GstPlugin * plugin, GstVaDevice * device,
1339     GstCaps * sink_caps, GstCaps * src_caps, guint rank)
1340 {
1341   static GOnce debug_once = G_ONCE_INIT;
1342   GType type;
1343   GTypeInfo type_info = {
1344     .class_size = sizeof (GstVaH265DecClass),
1345     .class_init = gst_va_h265_dec_class_init,
1346     .instance_size = sizeof (GstVaH265Dec),
1347     .instance_init = gst_va_h265_dec_init,
1348   };
1349   struct CData *cdata;
1350   gboolean ret;
1351   gchar *type_name, *feature_name;
1352
1353   g_return_val_if_fail (GST_IS_PLUGIN (plugin), FALSE);
1354   g_return_val_if_fail (GST_IS_VA_DEVICE (device), FALSE);
1355   g_return_val_if_fail (GST_IS_CAPS (sink_caps), FALSE);
1356   g_return_val_if_fail (GST_IS_CAPS (src_caps), FALSE);
1357
1358   cdata = g_new (struct CData, 1);
1359   cdata->description = NULL;
1360   cdata->render_device_path = g_strdup (device->render_device_path);
1361   cdata->sink_caps = _complete_sink_caps (sink_caps);
1362   cdata->src_caps = gst_caps_ref (src_caps);
1363
1364   /* class data will be leaked if the element never gets instantiated */
1365   GST_MINI_OBJECT_FLAG_SET (cdata->sink_caps,
1366       GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
1367   GST_MINI_OBJECT_FLAG_SET (src_caps, GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
1368
1369   type_info.class_data = cdata;
1370
1371   type_name = g_strdup ("GstVaH265Dec");
1372   feature_name = g_strdup ("vah265dec");
1373
1374   /* The first decoder to be registered should use a constant name,
1375    * like vah265dec, for any additional decoders, we create unique
1376    * names, using inserting the render device name. */
1377   if (g_type_from_name (type_name)) {
1378     gchar *basename = g_path_get_basename (device->render_device_path);
1379     g_free (type_name);
1380     g_free (feature_name);
1381     type_name = g_strdup_printf ("GstVa%sH265Dec", basename);
1382     feature_name = g_strdup_printf ("va%sh265dec", basename);
1383     cdata->description = basename;
1384
1385     /* lower rank for non-first device */
1386     if (rank > 0)
1387       rank--;
1388   }
1389
1390   g_once (&debug_once, _register_debug_category, NULL);
1391
1392   type = g_type_register_static (GST_TYPE_H265_DECODER,
1393       type_name, &type_info, 0);
1394
1395   ret = gst_element_register (plugin, feature_name, rank, type);
1396
1397   g_free (type_name);
1398   g_free (feature_name);
1399
1400   return ret;
1401 }