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