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