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