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