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