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