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