va: Implement the vah265enc plugin for va HEVC encoding.
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-bad / sys / va / gstvah265enc.c
1 /* GStreamer
2  *  Copyright (C) 2022 Intel Corporation
3  *     Author: He Junyan <junyan.he@intel.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 /**
22  * SECTION:element-vah265enc
23  * @title: vah265enc
24  * @short_description: A VA-API based H265 video encoder
25  *
26  * vah265enc encodes raw video VA surfaces into H.265 bitstreams using
27  * the installed and chosen [VA-API](https://01.org/linuxmedia/vaapi)
28  * driver.
29  *
30  * The raw video frames in main memory can be imported into VA surfaces.
31  *
32  * ## Example launch line
33  * ```
34  * gst-launch-1.0 videotestsrc num-buffers=60 ! timeoverlay ! vah265enc ! h265parse ! mp4mux ! filesink location=test.mp4
35  * ```
36  *
37  * Since: 1.22
38  *
39  */
40
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
44
45 #include "gstvah265enc.h"
46
47 #include <gst/codecparsers/gsth265bitwriter.h>
48 #include <gst/va/gstva.h>
49 #include <gst/va/gstvavideoformat.h>
50 #include <gst/video/video.h>
51 #include <va/va_drmcommon.h>
52
53 #include "vacompat.h"
54 #include "gstvabaseenc.h"
55 #include "gstvaencoder.h"
56 #include "gstvacaps.h"
57 #include "gstvaprofile.h"
58 #include "gstvadisplay_priv.h"
59
60 GST_DEBUG_CATEGORY_STATIC (gst_va_h265enc_debug);
61 #define GST_CAT_DEFAULT gst_va_h265enc_debug
62
63 #define GST_VA_H265_ENC(obj)            ((GstVaH265Enc *) obj)
64 #define GST_VA_H265_ENC_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_FROM_INSTANCE (obj), GstVaH265EncClass))
65 #define GST_VA_H265_ENC_CLASS(klass)    ((GstVaH265EncClass *) klass)
66
67 typedef struct _GstVaH265Enc GstVaH265Enc;
68 typedef struct _GstVaH265EncClass GstVaH265EncClass;
69 typedef struct _GstVaH265EncFrame GstVaH265EncFrame;
70 typedef struct _GstVaH265LevelLimits GstVaH265LevelLimits;
71
72 enum
73 {
74   PROP_KEY_INT_MAX = 1,
75   PROP_BFRAMES,
76   PROP_IFRAMES,
77   PROP_NUM_REF_FRAMES,
78   PROP_B_PYRAMID,
79   PROP_NUM_SLICES,
80   PROP_MIN_QP,
81   PROP_MAX_QP,
82   PROP_QP_I,
83   PROP_QP_P,
84   PROP_QP_B,
85   PROP_TRELLIS,
86   PROP_MBBRC,
87   PROP_BITRATE,
88   PROP_TARGET_PERCENTAGE,
89   PROP_TARGET_USAGE,
90   PROP_RATE_CONTROL,
91   PROP_CPB_SIZE,
92   PROP_AUD,
93   N_PROPERTIES
94 };
95
96 static GParamSpec *properties[N_PROPERTIES];
97
98 static GstObjectClass *parent_class = NULL;
99
100 /* Scale factor for bitrate (HRD bit_rate_scale: min = 6) */
101 #define SX_BITRATE  6
102 /* Scale factor for CPB size (HRD cpb_size_scale: min = 4) */
103 #define SX_CPB_SIZE  4
104 /* Maximum sizes for common headers (in bits) */
105 #define MAX_PROFILE_TIER_LEVEL_SIZE 684
106 #define MAX_VPS_HDR_SIZE 13781
107 #define MAX_SPS_HDR_SIZE 615
108 #define MAX_SHORT_TERM_REFPICSET_SIZE 55
109 #define MAX_VUI_PARAMS_SIZE 267
110 #define MAX_HRD_PARAMS_SIZE 8196
111 #define MAX_PPS_HDR_SIZE 274
112 #define MAX_SLICE_HDR_SIZE 33660
113
114 #define MAX_GOP_SIZE  1024
115
116 /* *INDENT-OFF* */
117 struct _GstVaH265EncClass
118 {
119   GstVaBaseEncClass parent_class;
120
121   GType rate_control_type;
122   char rate_control_type_name[64];
123   GEnumValue rate_control[16];
124 };
125 /* *INDENT-ON* */
126
127 struct _GstVaH265Enc
128 {
129   /*< private > */
130   GstVaBaseEnc parent;
131
132   /* properties */
133   struct
134   {
135     /* kbps */
136     guint bitrate;
137     /* VA_RC_XXX */
138     guint32 rc_ctrl;
139     guint key_int_max;
140     guint32 num_ref_frames;
141     gboolean b_pyramid;
142     guint32 num_bframes;
143     guint32 num_iframes;
144     guint32 min_qp;
145     guint32 max_qp;
146     guint32 qp_i;
147     guint32 qp_p;
148     guint32 qp_b;
149     gboolean use_trellis;
150     gboolean aud;
151     guint32 mbbrc;
152     guint32 num_slices;
153     guint32 cpb_size;
154     guint32 target_percentage;
155     guint32 target_usage;
156   } prop;
157
158   /* H265 fields */
159   guint32 ctu_size;
160   guint32 min_coding_block_size;
161   guint32 ctu_width;            /* CTU == Coding Tree Unit */
162   guint32 ctu_height;
163   /* Aligned to 16 */
164   guint32 luma_width;
165   guint32 luma_height;
166   /* Crop rectangle */
167   gboolean conformance_window_flag;
168   guint32 conf_win_left_offset;
169   guint32 conf_win_right_offset;
170   guint32 conf_win_top_offset;
171   guint32 conf_win_bottom_offset;
172
173   guint bits_depth_luma_minus8;
174   guint bits_depth_chroma_minus8;
175
176   guint8 level_idc;
177   /* Set true if high tier */
178   gboolean tier_flag;
179   const gchar *level_str;
180   guint min_cr;
181
182   gboolean aud;
183   guint32 num_slices;
184   guint32 packed_headers;
185
186   struct
187   {
188     guint8 log2_min_luma_coding_block_size_minus3;
189     guint8 log2_diff_max_min_luma_coding_block_size;
190     guint8 log2_min_transform_block_size_minus2;
191     guint8 log2_diff_max_min_transform_block_size;
192     guint8 max_transform_hierarchy_depth_inter;
193     guint8 max_transform_hierarchy_depth_intra;
194
195     gboolean separate_colour_plane_flag;
196     guint8 colour_plane_id;
197
198     gboolean scaling_list_enabled_flag;
199     gboolean scaling_list_data_present_flag;
200
201     gboolean amp_enabled_flag;
202
203     gboolean sample_adaptive_offset_enabled_flag;
204     gboolean slice_sao_luma_flag;
205     gboolean slice_sao_chroma_flag;
206
207     gboolean pcm_enabled_flag;
208     guint8 pcm_sample_bit_depth_luma_minus1;
209     guint8 pcm_sample_bit_depth_chroma_minus1;
210     guint8 log2_min_pcm_luma_coding_block_size_minus3;
211     guint8 log2_max_pcm_luma_coding_block_size_minus3;
212     guint8 pcm_loop_filter_disabled_flag;
213
214     gboolean temporal_mvp_enabled_flag;
215     gboolean collocated_from_l0_flag;
216     guint8 collocated_ref_idx;
217
218     gboolean strong_intra_smoothing_enabled_flag;
219
220     gboolean dependent_slice_segment_flag;
221
222     gboolean sign_data_hiding_enabled_flag;
223
224     gboolean constrained_intra_pred_flag;
225
226     gboolean transform_skip_enabled_flag;
227
228     gboolean cu_qp_delta_enabled_flag;
229     uint32_t diff_cu_qp_delta_depth;
230
231     gboolean weighted_pred_flag;
232     gboolean weighted_bipred_flag;
233
234     gboolean transquant_bypass_enabled_flag;
235
236     gboolean use_trellis;
237   } features;
238
239   struct
240   {
241     /* frames between two IDR [idr, ...., idr) */
242     guint32 idr_period;
243     /* How may IDRs we have encoded */
244     guint32 total_idr_count;
245     /* frames between I/P and P frames [I, B, B, .., B, P) */
246     guint32 ip_period;
247     /* frames between I frames [I, B, B, .., B, P, ..., I), open GOP */
248     guint32 i_period;
249     /* B frames between I/P and P. */
250     guint32 num_bframes;
251     /* Use B pyramid structure in the GOP. */
252     gboolean b_pyramid;
253     /* Level 0 is the simple B not acting as ref. */
254     guint32 highest_pyramid_level;
255     /* If open GOP, I frames within a GOP. */
256     guint32 num_iframes;
257     /* A map of all frames types within a GOP. */
258     struct
259     {
260       guint8 slice_type;
261       gboolean is_ref;
262       guint8 pyramid_level;
263       /* Only for b pyramid */
264       gint left_ref_poc_diff;
265       gint right_ref_poc_diff;
266     } frame_types[MAX_GOP_SIZE];
267
268     /* Max poc within a GOP. */
269     guint32 max_pic_order_cnt;
270     guint32 log2_max_pic_order_cnt;
271     /* current index in the frames types map. */
272     guint cur_frame_index;
273
274     /* Total ref frames of forward and backward. */
275     guint32 num_ref_frames;
276     guint32 max_l0_num;
277     guint32 max_l1_num;
278     guint32 forward_ref_num;
279     guint32 backward_ref_num;
280
281     guint num_reorder_frames;
282     guint max_dpb_size;
283   } gop;
284
285   struct
286   {
287     guint target_usage;
288     guint32 rc_ctrl_mode;
289
290     guint32 min_qp;
291     guint32 max_qp;
292     guint32 qp_i;
293     guint32 qp_p;
294     guint32 qp_b;
295     /* macroblock bitrate control */
296     guint32 mbbrc;
297     guint target_bitrate;
298     guint target_percentage;
299     guint max_bitrate;
300     /* bitrate (bits) */
301     guint max_bitrate_bits;
302     guint target_bitrate_bits;
303     /* length of CPB buffer */
304     guint cpb_size;
305     /* length of CPB buffer (bits) */
306     guint cpb_length_bits;
307   } rc;
308
309   GstH265VPS vps_hdr;
310   GstH265SPS sps_hdr;
311 };
312
313 struct _GstVaH265EncFrame
314 {
315   GstVaEncodePicture *picture;
316   GstH265SliceType type;
317   gboolean is_ref;
318   guint pyramid_level;
319   /* Only for b pyramid */
320   gint left_ref_poc_diff;
321   gint right_ref_poc_diff;
322
323   gint poc;
324   gboolean last_frame;
325   /* The total frame count we handled. */
326   guint total_frame_count;
327 };
328
329 /**
330  * GstVaH265LevelLimits:
331  * @level_name: the level name
332  * @level_idc: the H.265 level_idc value
333  * @MaxLumaPs: the maximum luma picture size
334  * @MaxCPBTierMain: the maximum CPB size for Main tier(kbits)
335  * @MaxCPBTierHigh: the maximum CPB size for High tier(kbits)
336  * @MaxSliceSegPic: the maximum slice segments per picture
337  * @MaxTileRows: the maximum number of Tile Rows
338  * @MaxTileColumns: the maximum number of Tile Columns
339  * @MaxLumaSr: the maximum luma sample rate (samples/sec)
340  * @MaxBRTierMain: the maximum video bit rate for Main Tier(kbps)
341  * @MaxBRTierHigh: the maximum video bit rate for High Tier(kbps)
342  * @MinCr: the mimimum compression ratio
343  *
344  * The data structure that describes the limits of an H.265 level.
345  */
346 struct _GstVaH265LevelLimits
347 {
348   const gchar *level_name;
349   guint8 level_idc;
350   guint32 MaxLumaPs;
351   guint32 MaxCPBTierMain;
352   guint32 MaxCPBTierHigh;
353   guint32 MaxSliceSegPic;
354   guint32 MaxTileRows;
355   guint32 MaxTileColumns;
356   guint32 MaxLumaSr;
357   guint32 MaxBRTierMain;
358   guint32 MaxBRTierHigh;
359   guint32 MinCr;
360 };
361
362 /* Table A-1 - Level limits */
363 /* *INDENT-OFF* */
364 static const GstVaH265LevelLimits _va_h265_level_limits[] = {
365   /* level    idc   MaxLumaPs  MCPBMt  MCPBHt  MSlSeg MTR MTC  MaxLumaSr   MBRMt   MBRHt  MinCr */
366   {  "1",     30,    36864,    350,    0,       16,   1,  1,   552960,     128,    0,      2  },
367   {  "2",     60,    122880,   1500,   0,       16,   1,  1,   3686400,    1500,   0,      2  },
368   {  "2.1",   63,    245760,   3000,   0,       20,   1,  1,   7372800,    3000,   0,      2  },
369   {  "3",     90,    552960,   6000,   0,       30,   2,  2,   16588800,   6000,   0,      2  },
370   {  "3.1",   93,    983040,   10000,  0,       40,   3,  3,   33177600,   10000,  0,      2  },
371   {  "4",     120,   2228224,  12000,  30000,   75,   5,  5,   66846720,   12000,  30000,  4  },
372   {  "4.1",   123,   2228224,  20000,  50000,   75,   5,  5,   133693440,  20000,  50000,  4  },
373   {  "5",     150,   8912896,  25000,  100000,  200,  11, 10,  267386880,  25000,  100000, 6  },
374   {  "5.1",   153,   8912896,  40000,  160000,  200,  11, 10,  534773760,  40000,  160000, 8  },
375   {  "5.2",   156,   8912896,  60000,  240000,  200,  11, 10,  1069547520, 60000,  240000, 8  },
376   {  "6",     180,   35651584, 60000,  240000,  600,  22, 20,  1069547520, 60000,  240000, 8  },
377   {  "6.1",   183,   35651584, 120000, 480000,  600,  22, 20,  2139095040, 120000, 480000, 8  },
378   {  "6.2",   186,   35651584, 240000, 800000,  600,  22, 20,  4278190080, 240000, 800000, 6  },
379 };
380 /* *INDENT-ON* */
381
382 #ifndef GST_DISABLE_GST_DEBUG
383 static const gchar *
384 _h265_slice_type_name (GstH265SliceType type)
385 {
386   switch (type) {
387     case GST_H265_P_SLICE:
388       return "P";
389     case GST_H265_B_SLICE:
390       return "B";
391     case GST_H265_I_SLICE:
392       return "I";
393     default:
394       g_assert_not_reached ();
395   }
396
397   return NULL;
398 }
399
400 static const gchar *
401 _rate_control_get_name (guint32 rc_mode)
402 {
403   GParamSpecEnum *spec;
404   guint i;
405
406   if (!(properties[PROP_RATE_CONTROL]
407           && G_IS_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL])))
408     return NULL;
409
410   spec = G_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL]);
411   for (i = 0; i < spec->enum_class->n_values; i++) {
412     if (spec->enum_class->values[i].value == rc_mode)
413       return spec->enum_class->values[i].value_nick;
414   }
415
416   return NULL;
417 }
418 #endif /* end of GST_DISABLE_GST_DEBUG */
419
420 static GstVaH265EncFrame *
421 gst_va_h265_enc_frame_new (void)
422 {
423   GstVaH265EncFrame *frame;
424
425   frame = g_slice_new (GstVaH265EncFrame);
426   frame->last_frame = FALSE;
427   frame->picture = NULL;
428   frame->total_frame_count = 0;
429
430   return frame;
431 }
432
433 static void
434 gst_va_h265_enc_frame_free (gpointer pframe)
435 {
436   GstVaH265EncFrame *frame = pframe;
437   g_clear_pointer (&frame->picture, gst_va_encode_picture_free);
438   g_slice_free (GstVaH265EncFrame, frame);
439 }
440
441 static inline GstVaH265EncFrame *
442 _enc_frame (GstVideoCodecFrame * frame)
443 {
444   GstVaH265EncFrame *enc_frame = gst_video_codec_frame_get_user_data (frame);
445   g_assert (enc_frame);
446   return enc_frame;
447 }
448
449 static GstH265NalUnitType
450 _h265_nal_unit_type (GstVaH265EncFrame * frame)
451 {
452   GstH265NalUnitType nal_unit_type = -1;
453
454   switch (frame->type) {
455     case GST_H265_I_SLICE:
456       if (frame->poc == 0) {
457         nal_unit_type = GST_H265_NAL_SLICE_IDR_W_RADL;
458       } else {
459         nal_unit_type = GST_H265_NAL_SLICE_TRAIL_R;
460       }
461       break;
462     case GST_H265_P_SLICE:
463       nal_unit_type = GST_H265_NAL_SLICE_TRAIL_R;
464       break;
465     case GST_H265_B_SLICE:
466       if (frame->is_ref) {
467         nal_unit_type = GST_H265_NAL_SLICE_TRAIL_R;
468       } else {
469         nal_unit_type = GST_H265_NAL_SLICE_TRAIL_N;
470       }
471       break;
472     default:
473       break;
474   }
475
476   g_assert (nal_unit_type >= 0);
477   return nal_unit_type;
478 }
479
480 static gboolean
481 _h265_fill_ptl (GstVaH265Enc * self,
482     const VAEncSequenceParameterBufferHEVC * sequence,
483     GstH265ProfileTierLevel * ptl)
484 {
485   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
486
487   /* *INDENT-OFF* */
488   *ptl = (GstH265ProfileTierLevel) {
489     .profile_space = 0,
490     .tier_flag = sequence->general_tier_flag,
491     .profile_idc = sequence->general_profile_idc,
492     .profile_compatibility_flag = { },
493     .progressive_source_flag = 1,
494     .interlaced_source_flag = 0,
495     .non_packed_constraint_flag = 0,
496     .frame_only_constraint_flag = 1,
497
498     .level_idc = sequence->general_level_idc,
499   };
500   /* *INDENT-ON* */
501
502   if (sequence->general_profile_idc == 1        /* Main profile */
503       /* In A.3.4, NOTE: When general_profile_compatibility_flag[ 3 ] is equal
504          to 1, general_profile_compatibility_flag[ 1 ] and
505          general_profile_compatibility_flag[ 2 ] should also be equal to 1. */
506       || sequence->general_profile_idc == 3     /* Main Still Picture profile */
507       ) {
508     ptl->profile_compatibility_flag[1] = 1;
509   }
510
511   if (
512       /* In A.3.2, NOTE: When general_profile_compatibility_flag[ 1 ] is equal
513          to 1, general_profile_compatibility_flag[ 2 ] should also be equal to
514          1. */
515       sequence->general_profile_idc == 1        /* Main profile */
516       || sequence->general_profile_idc == 2     /* Main 10 profile */
517       /* In A.3.4, NOTE: When general_profile_compatibility_flag[ 3 ] is equal
518          to 1, general_profile_compatibility_flag[ 1 ] and
519          general_profile_compatibility_flag[ 2 ] should also be equal to 1. */
520       || sequence->general_profile_idc == 3     /* Main Still Picture profile */
521       ) {
522     ptl->profile_compatibility_flag[2] = 1;
523   }
524
525   if (sequence->general_profile_idc == 3)
526     ptl->profile_compatibility_flag[3] = 1;
527
528   if (sequence->general_profile_idc == 4)       /* format range extensions profiles */
529     ptl->profile_compatibility_flag[4] = 1;
530
531   if (sequence->general_profile_idc == 9)       /* screen content coding profiles */
532     ptl->profile_compatibility_flag[9] = 1;
533
534   /* additional indications specified for general_profile_idc from 4~10 */
535   if (sequence->general_profile_idc == 4) {
536     /* In A.3.5, Format range extensions profiles.
537        Just support main444, main444-10 and main422-10 profile now, may add
538        more profiles when needed. */
539     switch (base->profile) {
540       case VAProfileHEVCMain444:
541         ptl->max_12bit_constraint_flag = 1;
542         ptl->max_10bit_constraint_flag = 1;
543         ptl->max_8bit_constraint_flag = 1;
544         ptl->max_422chroma_constraint_flag = 0;
545         ptl->max_420chroma_constraint_flag = 0;
546         ptl->max_monochrome_constraint_flag = 0;
547         ptl->intra_constraint_flag = 0;
548         ptl->one_picture_only_constraint_flag = 0;
549         ptl->lower_bit_rate_constraint_flag = 1;
550         break;
551       case VAProfileHEVCMain444_10:
552         ptl->max_12bit_constraint_flag = 1;
553         ptl->max_10bit_constraint_flag = 1;
554         ptl->max_8bit_constraint_flag = 0;
555         ptl->max_422chroma_constraint_flag = 0;
556         ptl->max_420chroma_constraint_flag = 0;
557         ptl->max_monochrome_constraint_flag = 0;
558         ptl->intra_constraint_flag = 0;
559         ptl->one_picture_only_constraint_flag = 0;
560         ptl->lower_bit_rate_constraint_flag = 1;
561         break;
562       case VAProfileHEVCMain422_10:
563         ptl->max_12bit_constraint_flag = 1;
564         ptl->max_10bit_constraint_flag = 1;
565         ptl->max_8bit_constraint_flag = 0;
566         ptl->max_422chroma_constraint_flag = 1;
567         ptl->max_420chroma_constraint_flag = 0;
568         ptl->max_monochrome_constraint_flag = 0;
569         ptl->intra_constraint_flag = 0;
570         ptl->one_picture_only_constraint_flag = 0;
571         ptl->lower_bit_rate_constraint_flag = 1;
572         break;
573       case VAProfileHEVCMain12:
574         ptl->max_12bit_constraint_flag = 1;
575         ptl->max_10bit_constraint_flag = 0;
576         ptl->max_8bit_constraint_flag = 0;
577         ptl->max_422chroma_constraint_flag = 1;
578         ptl->max_420chroma_constraint_flag = 1;
579         ptl->max_monochrome_constraint_flag = 0;
580         ptl->intra_constraint_flag = 0;
581         ptl->one_picture_only_constraint_flag = 0;
582         ptl->lower_bit_rate_constraint_flag = 1;
583         break;
584       default:
585         GST_WARNING_OBJECT (self, "do not support the profile: %s of"
586             " range extensions.", gst_va_profile_name (base->profile));
587         goto error;
588     }
589   }
590
591   return TRUE;
592
593 error:
594   GST_WARNING_OBJECT (self, "Failed to write Profile Tier Level");
595   return FALSE;
596 }
597
598 /* By now, the VPS is not really used, we just fill all its fields
599    with the same info from the SPS. */
600 static gboolean
601 _h265_fill_vps (GstVaH265Enc * self,
602     const VAEncSequenceParameterBufferHEVC * seq_param)
603 {
604   guint max_dec_pic_buffering =
605       self->gop.num_ref_frames + 1 < self->gop.max_dpb_size ?
606       self->gop.num_ref_frames + 1 : self->gop.max_dpb_size;
607
608   /* *INDENT-OFF* */
609   self->vps_hdr = (GstH265VPS) {
610     .id = 0,
611     .base_layer_internal_flag = 1,
612     .base_layer_available_flag = 1,
613     .max_layers_minus1 = 0,
614     .max_sub_layers_minus1 = 0,
615     .temporal_id_nesting_flag = 1,
616
617     .sub_layer_ordering_info_present_flag = 0,
618     .max_dec_pic_buffering_minus1 = { max_dec_pic_buffering - 1, },
619     .max_num_reorder_pics = { self->gop.num_reorder_frames, },
620     .max_latency_increase_plus1 = { 0, },
621     .max_layer_id = 0,
622     .num_layer_sets_minus1 = 0,
623     .timing_info_present_flag = 0,
624     .vps_extension = 0,
625   };
626   /* *INDENT-ON* */
627
628   if (!_h265_fill_ptl (self, seq_param, &self->vps_hdr.profile_tier_level))
629     return FALSE;
630
631   return TRUE;
632 }
633
634 static gboolean
635 _h265_fill_sps (GstVaH265Enc * self,
636     const VAEncSequenceParameterBufferHEVC * seq_param)
637 {
638   guint max_dec_pic_buffering =
639       self->gop.num_ref_frames + 1 < self->gop.max_dpb_size ?
640       self->gop.num_ref_frames + 1 : self->gop.max_dpb_size;
641
642   g_assert (self->gop.log2_max_pic_order_cnt >= 4);
643   /* *INDENT-OFF* */
644   self->sps_hdr = (GstH265SPS) {
645     .id = 0,
646     .vps = &self->vps_hdr,
647     .max_sub_layers_minus1 = 0,
648     .temporal_id_nesting_flag = 1,
649
650     .chroma_format_idc = seq_param->seq_fields.bits.chroma_format_idc,
651     .separate_colour_plane_flag =
652         seq_param->seq_fields.bits.separate_colour_plane_flag,
653     .pic_width_in_luma_samples = seq_param->pic_width_in_luma_samples,
654     .pic_height_in_luma_samples = seq_param->pic_height_in_luma_samples,
655     .conformance_window_flag = self->conformance_window_flag,
656     .conf_win_left_offset = self->conf_win_left_offset,
657     .conf_win_right_offset = self->conf_win_right_offset,
658     .conf_win_top_offset = self->conf_win_top_offset,
659     .conf_win_bottom_offset = self->conf_win_bottom_offset,
660     .bit_depth_luma_minus8 = seq_param->seq_fields.bits.bit_depth_luma_minus8,
661     .bit_depth_chroma_minus8 =
662         seq_param->seq_fields.bits.bit_depth_chroma_minus8,
663     .log2_max_pic_order_cnt_lsb_minus4 = self->gop.log2_max_pic_order_cnt - 4,
664     .sub_layer_ordering_info_present_flag = 0,
665     .max_dec_pic_buffering_minus1 = { max_dec_pic_buffering - 1, },
666     .max_num_reorder_pics = { self->gop.num_reorder_frames, },
667     .max_latency_increase_plus1 = { 0, },
668     .log2_min_luma_coding_block_size_minus3 =
669         seq_param->log2_min_luma_coding_block_size_minus3,
670     .log2_diff_max_min_luma_coding_block_size =
671         seq_param->log2_diff_max_min_luma_coding_block_size,
672     .log2_min_transform_block_size_minus2 =
673         seq_param->log2_min_transform_block_size_minus2,
674     .log2_diff_max_min_transform_block_size =
675         seq_param->log2_diff_max_min_transform_block_size,
676     .max_transform_hierarchy_depth_inter =
677         seq_param->max_transform_hierarchy_depth_inter,
678     .max_transform_hierarchy_depth_intra =
679         seq_param->max_transform_hierarchy_depth_intra,
680     .scaling_list_enabled_flag =
681         seq_param->seq_fields.bits.scaling_list_enabled_flag,
682     .scaling_list_data_present_flag =
683         self->features.scaling_list_data_present_flag,
684     /* Do not change the scaling list now. */
685     /* .scaling_list, */
686     .amp_enabled_flag = seq_param->seq_fields.bits.amp_enabled_flag,
687     .sample_adaptive_offset_enabled_flag =
688         seq_param->seq_fields.bits.sample_adaptive_offset_enabled_flag,
689     .pcm_enabled_flag = seq_param->seq_fields.bits.pcm_enabled_flag,
690     .pcm_sample_bit_depth_luma_minus1 =
691         seq_param->pcm_sample_bit_depth_luma_minus1,
692     .pcm_sample_bit_depth_chroma_minus1 =
693         seq_param->pcm_sample_bit_depth_chroma_minus1,
694     .log2_min_pcm_luma_coding_block_size_minus3 =
695         seq_param->log2_min_pcm_luma_coding_block_size_minus3,
696     .log2_diff_max_min_pcm_luma_coding_block_size =
697         seq_param->log2_max_pcm_luma_coding_block_size_minus3 -
698         seq_param->log2_min_pcm_luma_coding_block_size_minus3,
699     .pcm_loop_filter_disabled_flag =
700         seq_param->seq_fields.bits.pcm_loop_filter_disabled_flag,
701     .num_short_term_ref_pic_sets = 0,
702     .long_term_ref_pics_present_flag = 0,
703     .temporal_mvp_enabled_flag =
704         seq_param->seq_fields.bits.sps_temporal_mvp_enabled_flag,
705     .strong_intra_smoothing_enabled_flag =
706         seq_param->seq_fields.bits.strong_intra_smoothing_enabled_flag,
707     .vui_parameters_present_flag =
708         seq_param->vui_parameters_present_flag,
709     .vui_params = {
710       .aspect_ratio_info_present_flag =
711           seq_param->vui_fields.bits.aspect_ratio_info_present_flag,
712       .aspect_ratio_idc = seq_param->aspect_ratio_idc,
713       .sar_width = seq_param->sar_width,
714       .sar_height = seq_param->sar_height,
715       .overscan_info_present_flag = 0,
716       .video_signal_type_present_flag = 0,
717       .chroma_loc_info_present_flag = 0,
718       .neutral_chroma_indication_flag =
719           seq_param->vui_fields.bits.neutral_chroma_indication_flag,
720       .field_seq_flag = seq_param->vui_fields.bits.field_seq_flag,
721       .frame_field_info_present_flag = 0,
722       .default_display_window_flag = 0,
723       .timing_info_present_flag =
724           seq_param->vui_fields.bits.vui_timing_info_present_flag,
725       .num_units_in_tick = seq_param->vui_num_units_in_tick,
726       .time_scale = seq_param->vui_time_scale,
727       .poc_proportional_to_timing_flag = 0,
728       /* TODO: provide HRD. */
729       .hrd_parameters_present_flag = 0,
730       /*
731       .hrd_parameters_present_flag = (seq_param->bits_per_second > 0),
732       .hrd_params = {
733         .nal_hrd_parameters_present_flag = 1,
734         .vcl_hrd_parameters_present_flag = 0,
735         .sub_pic_hrd_params_present_flag = 0,
736         .bit_rate_scale = (SX_BITRATE - 6),
737         .cpb_size_scale = (SX_CPB_SIZE - 4),
738         .initial_cpb_removal_delay_length_minus1 = 23,
739         .au_cpb_removal_delay_length_minus1 = 23,
740         .dpb_output_delay_length_minus1 = 23,
741         .fixed_pic_rate_general_flag  = { 0, },
742         .fixed_pic_rate_within_cvs_flag = { 0, },
743         .low_delay_hrd_flag = { 1, },
744         .cpb_cnt_minus1 = { 0, },
745         .sublayer_hrd_params = {
746           { .bit_rate_value_minus1 = { (seq_param->bits_per_second >> SX_BITRATE) - 1, },
747             .cpb_size_value_minus1 = { (hrd_params->buffer_size >> SX_CPB_SIZE) - 1, },
748             .cpb_size_du_value_minus1 = { 0, },
749             .bit_rate_du_value_minus1 = { 0, },
750             .cbr_flag = { self->rc_ctrl == VA_RC_CBR, },
751           },
752         }
753       }, */
754       .bitstream_restriction_flag =
755           seq_param->vui_fields.bits.bitstream_restriction_flag,
756       .tiles_fixed_structure_flag =
757           seq_param->vui_fields.bits.tiles_fixed_structure_flag,
758       .motion_vectors_over_pic_boundaries_flag =
759           seq_param->vui_fields.bits.motion_vectors_over_pic_boundaries_flag,
760       .restricted_ref_pic_lists_flag =
761           seq_param->vui_fields.bits.restricted_ref_pic_lists_flag,
762       .min_spatial_segmentation_idc = seq_param->min_spatial_segmentation_idc,
763       .max_bytes_per_pic_denom = seq_param->max_bytes_per_pic_denom,
764       .max_bits_per_min_cu_denom = seq_param->max_bits_per_min_cu_denom,
765       .log2_max_mv_length_horizontal =
766           seq_param->vui_fields.bits.log2_max_mv_length_horizontal,
767       .log2_max_mv_length_vertical =
768           seq_param->vui_fields.bits.log2_max_mv_length_vertical,
769     },
770   };
771   /* *INDENT-ON* */
772
773   if (!_h265_fill_ptl (self, seq_param, &self->sps_hdr.profile_tier_level))
774     return FALSE;
775
776   return TRUE;
777 }
778
779 static void
780 _h265_fill_pps (VAEncPictureParameterBufferHEVC * pic_param,
781     GstH265SPS * sps, GstH265PPS * pps)
782 {
783   /* *INDENT-OFF* */
784   *pps = (GstH265PPS) {
785     .id = 0,
786     .sps = sps,
787     .dependent_slice_segments_enabled_flag =
788         pic_param->pic_fields.bits.dependent_slice_segments_enabled_flag,
789     .output_flag_present_flag = 0,
790     .num_extra_slice_header_bits = 0,
791     .sign_data_hiding_enabled_flag =
792         pic_param->pic_fields.bits.sign_data_hiding_enabled_flag,
793     .cabac_init_present_flag = 0,
794     .num_ref_idx_l0_default_active_minus1 =
795         pic_param->num_ref_idx_l0_default_active_minus1,
796     .num_ref_idx_l1_default_active_minus1 =
797         pic_param->num_ref_idx_l1_default_active_minus1,
798     .init_qp_minus26 = pic_param->pic_init_qp - 26,
799     .constrained_intra_pred_flag =
800         pic_param->pic_fields.bits.constrained_intra_pred_flag,
801     .transform_skip_enabled_flag =
802         pic_param->pic_fields.bits.transform_skip_enabled_flag,
803     .cu_qp_delta_enabled_flag =
804         pic_param->pic_fields.bits.cu_qp_delta_enabled_flag,
805     .diff_cu_qp_delta_depth = pic_param->diff_cu_qp_delta_depth,
806     .cb_qp_offset = pic_param->pps_cb_qp_offset,
807     .cr_qp_offset = pic_param->pps_cr_qp_offset,
808     .slice_chroma_qp_offsets_present_flag = 0,
809     .weighted_pred_flag = pic_param->pic_fields.bits.weighted_pred_flag,
810     .weighted_bipred_flag = pic_param->pic_fields.bits.weighted_bipred_flag,
811     .transquant_bypass_enabled_flag =
812         pic_param->pic_fields.bits.transquant_bypass_enabled_flag,
813     .tiles_enabled_flag = pic_param->pic_fields.bits.tiles_enabled_flag,
814     .entropy_coding_sync_enabled_flag =
815         pic_param->pic_fields.bits.entropy_coding_sync_enabled_flag,
816     .num_tile_columns_minus1 = pic_param->num_tile_columns_minus1,
817     .num_tile_rows_minus1 = pic_param->num_tile_rows_minus1,
818     /* Only support uniform tile mode now. */
819     .uniform_spacing_flag = 1,
820     .loop_filter_across_tiles_enabled_flag =
821         pic_param->pic_fields.bits.loop_filter_across_tiles_enabled_flag,
822     .loop_filter_across_slices_enabled_flag =
823         pic_param->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag,
824     /* Do not change the default deblocking filter */
825     .deblocking_filter_control_present_flag = 0,
826     .deblocking_filter_override_enabled_flag = 0,
827     .deblocking_filter_disabled_flag = 0,
828     /* .beta_offset_div2,
829        .tc_offset_div2, */
830     .scaling_list_data_present_flag =
831         pic_param->pic_fields.bits.scaling_list_data_present_flag,
832     /* Do not change the scaling list now. */
833     /* .scaling_list, */
834     /* Do not change the ref list */
835     .lists_modification_present_flag = 0,
836     .log2_parallel_merge_level_minus2 =
837         pic_param->log2_parallel_merge_level_minus2,
838     .slice_segment_header_extension_present_flag = 0,
839     /* TODO: set for SCC */
840     .pps_extension_flag = 0,
841   };
842   /* *INDENT-ON* */
843 }
844
845 static gboolean
846 _h265_fill_slice_header (GstVaH265Enc * self, GstVaH265EncFrame * frame,
847     GstH265PPS * pps, VAEncSliceParameterBufferHEVC * slice_param,
848     gboolean first_slice_segment_in_pic,
849     guint list_forward_num, guint list_backward_num,
850     gint negative_pocs[16], guint num_negative_pics,
851     gint positive_pocs[16], guint num_positive_pics,
852     GstH265SliceHdr * slice_hdr)
853 {
854   gint i;
855   gint delta_poc;
856
857   /* *INDENT-OFF* */
858   *slice_hdr = (GstH265SliceHdr) {
859     .pps = pps,
860     .first_slice_segment_in_pic_flag = first_slice_segment_in_pic,
861     /* set if IDR. */
862     .no_output_of_prior_pics_flag = 0,
863     .dependent_slice_segment_flag =
864         slice_param->slice_fields.bits.dependent_slice_segment_flag,
865     .segment_address = slice_param->slice_segment_address,
866     .type = slice_param->slice_type,
867     /* pps->output_flag_present_flag is not set now. */
868     .pic_output_flag = 0,
869     .colour_plane_id = slice_param->slice_fields.bits.colour_plane_id,
870     /* Set the reference list fields later
871     .pic_order_cnt_lsb,
872     .short_term_ref_pic_set_sps_flag,
873     .short_term_ref_pic_sets,
874     .short_term_ref_pic_set_idx,
875     .num_long_term_sps,
876     .num_long_term_pics,
877     .lt_idx_sps[16],
878     .poc_lsb_lt[16],
879     .used_by_curr_pic_lt_flag[16],
880     .delta_poc_msb_present_flag[16],
881     .delta_poc_msb_cycle_lt[16], */
882     .temporal_mvp_enabled_flag =
883         slice_param->slice_fields.bits.slice_temporal_mvp_enabled_flag,
884     .sao_luma_flag =
885         slice_param->slice_fields.bits.slice_sao_luma_flag,
886     .sao_chroma_flag=
887         slice_param->slice_fields.bits.slice_sao_chroma_flag,
888     /* Set the ref num later
889     .num_ref_idx_active_override_flag,
890     .num_ref_idx_l0_active_minus1,
891     .num_ref_idx_l1_active_minus1,
892     .ref_pic_list_modification, */
893     .mvd_l1_zero_flag = slice_param->slice_fields.bits.mvd_l1_zero_flag,
894     .cabac_init_flag = slice_param->slice_fields.bits.cabac_init_flag,
895     .collocated_from_l0_flag =
896         slice_param->slice_fields.bits.collocated_from_l0_flag,
897     .collocated_ref_idx = (slice_param->slice_type == GST_H265_I_SLICE ?
898         0xFF : self->features.collocated_ref_idx),
899     /* not used now. */
900     .pred_weight_table = { },
901     .five_minus_max_num_merge_cand = 5 - slice_param->max_num_merge_cand,
902     .use_integer_mv_flag = 0,
903     .qp_delta = slice_param->slice_qp_delta,
904     .cb_qp_offset = slice_param->slice_cb_qp_offset,
905     .cr_qp_offset = slice_param->slice_cr_qp_offset,
906     /* SCC is not enabled. */
907     .slice_act_y_qp_offset = 0,
908     .slice_act_cb_qp_offset = 0,
909     .slice_act_cr_qp_offset = 0,
910
911     .cu_chroma_qp_offset_enabled_flag = 0,
912     /* Do not change deblocking filter setting. */
913     .deblocking_filter_override_flag = 0,
914     .deblocking_filter_disabled_flag = 0,
915     /* .beta_offset_div2,
916        .tc_offset_div2, */
917     .loop_filter_across_slices_enabled_flag =
918         slice_param->slice_fields.bits.slice_loop_filter_across_slices_enabled_flag,
919     .num_entry_point_offsets = 0,
920     /* .offset_len_minus1,
921        .entry_point_offset_minus1, */
922   };
923   /* *INDENT-ON* */
924
925   if (slice_hdr->dependent_slice_segment_flag)
926     return TRUE;
927
928   if (slice_param->slice_type == GST_H265_I_SLICE)
929     return TRUE;
930
931   slice_hdr->pic_order_cnt_lsb = frame->poc;
932
933   /* Write the ref set explicitly. */
934   slice_hdr->short_term_ref_pic_set_sps_flag = 0;
935   slice_hdr->short_term_ref_pic_sets.inter_ref_pic_set_prediction_flag = 0;
936   slice_hdr->short_term_ref_pic_sets.NumDeltaPocs =
937       num_negative_pics + num_positive_pics;
938
939   slice_hdr->short_term_ref_pic_sets.NumNegativePics = num_negative_pics;
940   for (i = 0; i < num_negative_pics; i++) {
941     delta_poc = negative_pocs[i] - frame->poc;
942     g_assert (delta_poc < 0);
943     slice_hdr->short_term_ref_pic_sets.DeltaPocS0[i] = delta_poc;
944
945     if (i < list_forward_num) {
946       slice_hdr->short_term_ref_pic_sets.UsedByCurrPicS0[i] = 1;
947     } else {
948       slice_hdr->short_term_ref_pic_sets.UsedByCurrPicS0[i] = 0;
949     }
950   }
951
952   slice_hdr->short_term_ref_pic_sets.NumPositivePics = num_positive_pics;
953   for (i = 0; i < num_positive_pics; i++) {
954     delta_poc = positive_pocs[i] - frame->poc;
955     g_assert (delta_poc > 0);
956     slice_hdr->short_term_ref_pic_sets.DeltaPocS1[i] = delta_poc;
957
958     if (i < list_backward_num) {
959       slice_hdr->short_term_ref_pic_sets.UsedByCurrPicS1[i] = 1;
960     } else {
961       slice_hdr->short_term_ref_pic_sets.UsedByCurrPicS1[i] = 0;
962     }
963   }
964
965   slice_hdr->num_ref_idx_active_override_flag =
966       slice_param->slice_fields.bits.num_ref_idx_active_override_flag;
967   if (slice_hdr->num_ref_idx_active_override_flag) {
968     slice_hdr->num_ref_idx_l0_active_minus1 =
969         slice_param->num_ref_idx_l0_active_minus1;
970
971     if (slice_param->slice_type == GST_H265_B_SLICE)
972       slice_hdr->num_ref_idx_l1_active_minus1 =
973           slice_param->num_ref_idx_l1_active_minus1;
974   }
975
976   return TRUE;
977 }
978
979 static gboolean
980 _h265_add_vps_header (GstVaH265Enc * self, GstVaH265EncFrame * frame)
981 {
982   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
983   guint size;
984 #define VPS_SIZE 4 + GST_ROUND_UP_8 (MAX_VPS_HDR_SIZE +  \
985       MAX_PROFILE_TIER_LEVEL_SIZE + MAX_HRD_PARAMS_SIZE) / 8
986   guint8 packed_vps[VPS_SIZE] = { 0, };
987 #undef VPS_SIZE
988
989   size = sizeof (packed_vps);
990   if (gst_h265_bit_writer_vps (&self->vps_hdr, TRUE, packed_vps, &size)
991       != GST_H265_BIT_WRITER_OK) {
992     GST_ERROR_OBJECT (self, "Failed to write VPS header.");
993     return FALSE;
994   }
995
996   /* VPS does not have its own packed header define, just reuse
997      VAEncPackedHeaderSequence */
998   if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
999           VAEncPackedHeaderSequence, packed_vps, size * 8, FALSE)) {
1000     GST_ERROR_OBJECT (self, "Failed to add packed VPS header.");
1001     return FALSE;
1002   }
1003
1004   return TRUE;
1005 }
1006
1007 static gboolean
1008 _h265_add_sps_header (GstVaH265Enc * self, GstVaH265EncFrame * frame)
1009 {
1010   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1011   guint size;
1012 #define SPS_SIZE 4 + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE +                  \
1013       MAX_PROFILE_TIER_LEVEL_SIZE + 64 * MAX_SHORT_TERM_REFPICSET_SIZE + \
1014       MAX_VUI_PARAMS_SIZE + MAX_HRD_PARAMS_SIZE) / 8
1015   guint8 packed_sps[SPS_SIZE] = { 0, };
1016 #undef SPS_SIZE
1017
1018   size = sizeof (packed_sps);
1019   if (gst_h265_bit_writer_sps (&self->sps_hdr, TRUE, packed_sps, &size)
1020       != GST_H265_BIT_WRITER_OK) {
1021     GST_ERROR_OBJECT (self, "Failed to write SPS header.");
1022     return FALSE;
1023   }
1024
1025   if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
1026           VAEncPackedHeaderSequence, packed_sps, size * 8, FALSE)) {
1027     GST_ERROR_OBJECT (self, "Failed to add packed SPS header.");
1028     return FALSE;
1029   }
1030
1031   return TRUE;
1032 }
1033
1034 static gboolean
1035 _h265_add_pps_header (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1036     GstH265PPS * pps)
1037 {
1038   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1039   guint size;
1040 #define PPS_SIZE 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8
1041   guint8 packed_pps[PPS_SIZE] = { 0, };
1042 #undef PPS_SIZE
1043
1044   size = sizeof (packed_pps);
1045   if (gst_h265_bit_writer_pps (pps, TRUE, packed_pps,
1046           &size) != GST_H265_BIT_WRITER_OK) {
1047     GST_ERROR_OBJECT (self, "Failed to generate the picture header");
1048     return FALSE;
1049   }
1050
1051   if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
1052           VAEncPackedHeaderPicture, packed_pps, size * 8, FALSE)) {
1053     GST_ERROR_OBJECT (self, "Failed to add the packed picture header");
1054     return FALSE;
1055   }
1056
1057   return TRUE;
1058 }
1059
1060 static gboolean
1061 _h265_add_slice_header (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1062     GstH265SliceHdr * slice_hdr)
1063 {
1064   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1065   GstH265NalUnitType nal_type = _h265_nal_unit_type (frame);
1066   guint size;
1067 #define SLICE_HDR_SIZE 4 + GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8
1068   guint8 packed_slice_hdr[SLICE_HDR_SIZE] = { 0, };
1069 #undef SLICE_HDR_SIZE
1070
1071   size = sizeof (packed_slice_hdr);
1072   if (gst_h265_bit_writer_slice_hdr (slice_hdr, TRUE, nal_type,
1073           packed_slice_hdr, &size) != GST_H265_BIT_WRITER_OK) {
1074     GST_ERROR_OBJECT (self, "Failed to generate the slice header");
1075     return FALSE;
1076   }
1077
1078   if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
1079           VAEncPackedHeaderSlice, packed_slice_hdr, size * 8, FALSE)) {
1080     GST_ERROR_OBJECT (self, "Failed to add the packed slice header");
1081     return FALSE;
1082   }
1083
1084   return TRUE;
1085 }
1086
1087 static gboolean
1088 _h265_add_aud (GstVaH265Enc * self, GstVaH265EncFrame * frame)
1089 {
1090   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1091   guint8 aud_data[8] = { };
1092   guint size;
1093   guint8 pic_type = 0;
1094
1095   switch (frame->type) {
1096     case GST_H265_I_SLICE:
1097       pic_type = 0;
1098       break;
1099     case GST_H265_P_SLICE:
1100       pic_type = 1;
1101       break;
1102     case GST_H265_B_SLICE:
1103       pic_type = 2;
1104       break;
1105     default:
1106       g_assert_not_reached ();
1107       break;
1108   }
1109
1110   size = sizeof (aud_data);
1111   if (gst_h265_bit_writer_aud (pic_type, TRUE, aud_data,
1112           &size) != GST_H265_BIT_WRITER_OK) {
1113     GST_ERROR_OBJECT (self, "Failed to generate the AUD");
1114     return FALSE;
1115   }
1116
1117   if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
1118           VAEncPackedHeaderRawData, aud_data, size * 8, FALSE)) {
1119     GST_ERROR_OBJECT (self, "Failed to add the AUD");
1120     return FALSE;
1121   }
1122
1123   return TRUE;
1124 }
1125
1126 /* Returns H.265 chroma_format_idc value from chroma type */
1127 static guint
1128 _h265_get_chroma_format_idc (guint chroma_type)
1129 {
1130   guint chroma_format_idc;
1131
1132   switch (chroma_type) {
1133     case VA_RT_FORMAT_YUV400:
1134       chroma_format_idc = 0;
1135       break;
1136     case VA_RT_FORMAT_YUV420:
1137     case VA_RT_FORMAT_YUV420_10:
1138     case VA_RT_FORMAT_YUV420_12:
1139       chroma_format_idc = 1;
1140       break;
1141     case VA_RT_FORMAT_YUV422:
1142     case VA_RT_FORMAT_YUV422_10:
1143     case VA_RT_FORMAT_YUV422_12:
1144       chroma_format_idc = 2;
1145       break;
1146     case VA_RT_FORMAT_YUV444:
1147     case VA_RT_FORMAT_YUV444_10:
1148     case VA_RT_FORMAT_YUV444_12:
1149       chroma_format_idc = 3;
1150       break;
1151     default:
1152       GST_DEBUG ("unsupported GstVaapiChromaType value");
1153       chroma_format_idc = 1;
1154       break;
1155   }
1156   return chroma_format_idc;
1157 }
1158
1159 static gboolean
1160 _h265_fill_sequence_parameter (GstVaH265Enc * self,
1161     VAEncSequenceParameterBufferHEVC * sequence)
1162 {
1163   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1164   guint profile_idc = 0;
1165
1166   switch (base->profile) {
1167     case VAProfileHEVCMain:
1168       profile_idc = 1;
1169       break;
1170     case VAProfileHEVCMain10:
1171       profile_idc = 2;
1172       break;
1173     case VAProfileHEVCMain12:
1174     case VAProfileHEVCMain422_10:
1175     case VAProfileHEVCMain422_12:
1176     case VAProfileHEVCMain444:
1177     case VAProfileHEVCMain444_10:
1178     case VAProfileHEVCMain444_12:
1179       profile_idc = 4;
1180       break;
1181     default:
1182       GST_ERROR_OBJECT (self, "unsupported profile %d", base->profile);
1183       return FALSE;
1184   }
1185
1186   /* *INDENT-OFF* */
1187   *sequence = (VAEncSequenceParameterBufferHEVC) {
1188     .general_profile_idc = profile_idc,
1189     .general_level_idc = self->level_idc,
1190     .general_tier_flag = self->tier_flag,
1191     .intra_period =
1192         self->gop.i_period > 0 ? self->gop.i_period : self->gop.idr_period,
1193     .intra_idr_period = self->gop.idr_period,
1194     .ip_period = self->gop.ip_period,
1195     .bits_per_second = self->rc.target_bitrate_bits,
1196     .pic_width_in_luma_samples = self->luma_width,
1197     .pic_height_in_luma_samples = self->luma_height,
1198     .seq_fields.bits = {
1199       .chroma_format_idc = _h265_get_chroma_format_idc (base->rt_format),
1200       .separate_colour_plane_flag = self->features.separate_colour_plane_flag,
1201       .bit_depth_luma_minus8 = self->bits_depth_luma_minus8,
1202       .bit_depth_chroma_minus8 = self->bits_depth_chroma_minus8,
1203       .scaling_list_enabled_flag = self->features.scaling_list_enabled_flag,
1204       .strong_intra_smoothing_enabled_flag =
1205           self->features.strong_intra_smoothing_enabled_flag,
1206       .amp_enabled_flag = self->features.amp_enabled_flag,
1207       .sample_adaptive_offset_enabled_flag =
1208           self->features.sample_adaptive_offset_enabled_flag,
1209       .pcm_enabled_flag = self->features.pcm_enabled_flag,
1210       .pcm_loop_filter_disabled_flag =
1211           self->features.pcm_loop_filter_disabled_flag,
1212       .sps_temporal_mvp_enabled_flag =
1213           self->features.temporal_mvp_enabled_flag,
1214       .low_delay_seq = (self->gop.num_bframes == 0),
1215       .hierachical_flag = self->gop.b_pyramid,
1216     },
1217     .log2_min_luma_coding_block_size_minus3 =
1218         self->features.log2_min_luma_coding_block_size_minus3,
1219     .log2_diff_max_min_luma_coding_block_size =
1220         self->features.log2_diff_max_min_luma_coding_block_size,
1221     .log2_min_transform_block_size_minus2 =
1222         self->features.log2_min_transform_block_size_minus2,
1223     .log2_diff_max_min_transform_block_size =
1224         self->features.log2_diff_max_min_transform_block_size,
1225     .max_transform_hierarchy_depth_inter =
1226         self->features.max_transform_hierarchy_depth_inter,
1227     .max_transform_hierarchy_depth_intra =
1228         self->features.max_transform_hierarchy_depth_intra,
1229     /* pcm_enabled_flag is unset, ignore */
1230     .pcm_sample_bit_depth_luma_minus1 =
1231         self->features.pcm_sample_bit_depth_luma_minus1,
1232     .pcm_sample_bit_depth_chroma_minus1 =
1233         self->features.pcm_sample_bit_depth_chroma_minus1,
1234     .log2_min_pcm_luma_coding_block_size_minus3 =
1235         self->features.log2_min_pcm_luma_coding_block_size_minus3,
1236     .log2_max_pcm_luma_coding_block_size_minus3 =
1237         self->features.log2_max_pcm_luma_coding_block_size_minus3,
1238     /* VUI parameters are always set, at least for timing_info (framerate) */
1239     .vui_parameters_present_flag = TRUE,
1240     .vui_fields.bits = {
1241       .aspect_ratio_info_present_flag = TRUE,
1242       .bitstream_restriction_flag = FALSE,
1243       .vui_timing_info_present_flag = TRUE,
1244     },
1245     /* if (vui_fields.bits.aspect_ratio_info_present_flag) */
1246     .aspect_ratio_idc = 0xff,
1247     .sar_width = GST_VIDEO_INFO_PAR_N (&base->input_state->info),
1248     .sar_height = GST_VIDEO_INFO_PAR_D (&base->input_state->info),
1249     /* if (vui_fields.bits.vui_timing_info_present_flag) */
1250     .vui_num_units_in_tick = GST_VIDEO_INFO_FPS_D (&base->input_state->info),
1251     .vui_time_scale = GST_VIDEO_INFO_FPS_N (&base->input_state->info),
1252   };
1253   /* *INDENT-ON* */
1254
1255   return TRUE;
1256 }
1257
1258 static guint
1259 _h265_to_va_coding_type (GstVaH265Enc * self, GstVaH265EncFrame * frame)
1260 {
1261   guint coding_type = 0;
1262
1263   switch (frame->type) {
1264     case GST_H265_I_SLICE:
1265       coding_type = 1;
1266       break;
1267     case GST_H265_P_SLICE:
1268       coding_type = 2;
1269       break;
1270     case GST_H265_B_SLICE:
1271       /* We use hierarchical_level_plus1, so same for all B frames */
1272       coding_type = 3;
1273       break;
1274     default:
1275       break;
1276   }
1277
1278   g_assert (coding_type > 0);
1279   return coding_type;
1280 }
1281
1282 static inline gboolean
1283 _h265_fill_picture_parameter (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1284     VAEncPictureParameterBufferHEVC * pic_param, gint collocated_poc)
1285 {
1286   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1287   gboolean tiles_enabled_flag;
1288   guint8 num_ref_idx_l0_default_active_minus1 = 0;
1289   guint8 num_ref_idx_l1_default_active_minus1 = 0;
1290   guint hierarchical_level_plus1 = 0;
1291   guint i;
1292
1293   if (self->gop.b_pyramid) {
1294     /* I/P is the base hierarchical level 0, L0 level B is 1, and so on. */
1295     hierarchical_level_plus1 = 1;
1296
1297     if (frame->type == GST_H265_B_SLICE) {
1298       hierarchical_level_plus1 += 1;
1299       hierarchical_level_plus1 += frame->pyramid_level;
1300     }
1301   }
1302
1303   if (frame->type == GST_H265_P_SLICE || frame->type == GST_H265_B_SLICE) {
1304     num_ref_idx_l0_default_active_minus1 =
1305         (self->gop.forward_ref_num > 0 ? self->gop.forward_ref_num - 1 : 0);
1306   }
1307   if (frame->type == GST_H265_B_SLICE) {
1308     num_ref_idx_l1_default_active_minus1 =
1309         (self->gop.backward_ref_num > 0 ? self->gop.backward_ref_num - 1 : 0);
1310   }
1311
1312   /* TODO: multi tile support. */
1313   tiles_enabled_flag = 0;
1314
1315   /* *INDENT-OFF* */
1316   *pic_param = (VAEncPictureParameterBufferHEVC) {
1317     .decoded_curr_pic.picture_id =
1318         gst_va_encode_picture_get_reconstruct_surface (frame->picture),
1319     .decoded_curr_pic.pic_order_cnt = frame->poc,
1320     .decoded_curr_pic.flags = 0,
1321
1322     .coded_buf = frame->picture->coded_buffer,
1323     .last_picture = frame->last_frame,
1324     .pic_init_qp = self->rc.qp_i,
1325     .diff_cu_qp_delta_depth = self->features.diff_cu_qp_delta_depth,
1326     /* Do not use qp offset in picture. */
1327     .pps_cb_qp_offset = 0,
1328     .pps_cr_qp_offset = 0,
1329     /* TODO: multi tile support */
1330     .num_tile_columns_minus1 = 0,
1331     .num_tile_rows_minus1 = 0,
1332     .log2_parallel_merge_level_minus2 = 0,
1333     .ctu_max_bitsize_allowed = 0,
1334     .num_ref_idx_l0_default_active_minus1 = num_ref_idx_l0_default_active_minus1,
1335     .num_ref_idx_l1_default_active_minus1 = num_ref_idx_l1_default_active_minus1,
1336     .slice_pic_parameter_set_id = 0,
1337     .nal_unit_type = _h265_nal_unit_type (frame),
1338     .pic_fields.bits = {
1339       .idr_pic_flag = (frame->poc == 0),
1340       .coding_type = _h265_to_va_coding_type (self, frame),
1341       .reference_pic_flag = frame->is_ref,
1342       /* allow slice to set dependent_slice_segment_flag */
1343       .dependent_slice_segments_enabled_flag =
1344           self->features.dependent_slice_segment_flag,
1345       .sign_data_hiding_enabled_flag =
1346           self->features.sign_data_hiding_enabled_flag,
1347       .constrained_intra_pred_flag = self->features.constrained_intra_pred_flag,
1348       .transform_skip_enabled_flag = self->features.transform_skip_enabled_flag,
1349       .cu_qp_delta_enabled_flag = self->features.cu_qp_delta_enabled_flag,
1350       .weighted_pred_flag = self->features.weighted_pred_flag,
1351       .weighted_bipred_flag = self->features.weighted_bipred_flag,
1352       .transquant_bypass_enabled_flag =
1353           self->features.transquant_bypass_enabled_flag,
1354       .tiles_enabled_flag = tiles_enabled_flag,
1355       .entropy_coding_sync_enabled_flag = 0,
1356       /* When we enable multi tiles, enable this. */
1357       .loop_filter_across_tiles_enabled_flag = tiles_enabled_flag,
1358       .pps_loop_filter_across_slices_enabled_flag = 1,
1359       /* Should not change the scaling list, not used now */
1360       .scaling_list_data_present_flag =
1361           self->features.scaling_list_data_present_flag,
1362       .screen_content_flag = 0,
1363       /* Depend on weighted_pred_flag and weighted_bipred_flag */
1364       .enable_gpu_weighted_prediction = 0,
1365       /* set if IDR. */
1366       .no_output_of_prior_pics_flag = 0,
1367     },
1368     /* We use coding_type here, set this to 0. */
1369     .hierarchical_level_plus1 = hierarchical_level_plus1,
1370   };
1371   /* *INDENT-ON* */
1372
1373   i = 0;
1374   if (frame->type != GST_H265_I_SLICE) {
1375     GstVaH265EncFrame *f;
1376
1377     if (g_queue_is_empty (&base->ref_list)) {
1378       GST_ERROR_OBJECT (self, "No reference found for frame type %s",
1379           _h265_slice_type_name (frame->type));
1380       return FALSE;
1381     }
1382
1383     g_assert (g_queue_get_length (&base->ref_list) <= self->gop.num_ref_frames);
1384
1385     /* ref frames in queue are already sorted by poc. */
1386     for (; i < g_queue_get_length (&base->ref_list); i++) {
1387       f = _enc_frame (g_queue_peek_nth (&base->ref_list, i));
1388
1389       pic_param->reference_frames[i].picture_id =
1390           gst_va_encode_picture_get_reconstruct_surface (f->picture);
1391       pic_param->reference_frames[i].pic_order_cnt = f->poc;
1392       pic_param->reference_frames[i].flags = 0;
1393     }
1394
1395     g_assert (i < 15);
1396   }
1397   for (; i < 15; i++) {
1398     pic_param->reference_frames[i].picture_id = VA_INVALID_SURFACE;
1399     pic_param->reference_frames[i].flags = VA_PICTURE_HEVC_INVALID;
1400   }
1401
1402   /* If mvp enabled, collocated_ref_idx specifies the reference index of
1403      the collocated picture used for temporal motion vector prediction.
1404      We should find the according index in reference_frames[] here. */
1405   if (frame->type != GST_H265_I_SLICE
1406       && self->features.temporal_mvp_enabled_flag) {
1407     gint index = -1;
1408
1409     for (i = 0; i < 15; i++) {
1410       if (pic_param->reference_frames[i].flags != VA_PICTURE_HEVC_INVALID &&
1411           pic_param->reference_frames[i].pic_order_cnt == collocated_poc) {
1412         index = i;
1413         break;
1414       }
1415     }
1416
1417     g_assert (index >= 0);
1418     pic_param->collocated_ref_pic_index = index;
1419   } else {
1420     pic_param->collocated_ref_pic_index = 0xFF;
1421   }
1422
1423   return TRUE;
1424 }
1425
1426 static gboolean
1427 _h265_fill_slice_parameter (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1428     guint start_address, gint ctu_num, gboolean last_slice_of_pic,
1429     GstVaH265EncFrame * list0[16], guint list0_num,
1430     GstVaH265EncFrame * list1[16], guint list1_num,
1431     VAEncSliceParameterBufferHEVC * slice)
1432 {
1433   int8_t slice_qp_delta = 0;
1434   gint i;
1435
1436   /* *INDENT-OFF* */
1437   if (self->rc.rc_ctrl_mode == VA_RC_CQP) {
1438     if (frame->type == GST_H265_P_SLICE) {
1439       slice_qp_delta = self->rc.qp_p - self->rc.qp_i;
1440     } else if (frame->type == GST_H265_B_SLICE) {
1441       slice_qp_delta = (int8_t) (self->rc.qp_b - self->rc.qp_i);
1442     }
1443     g_assert (slice_qp_delta <= 51 && slice_qp_delta >= -51);
1444   }
1445
1446   *slice = (VAEncSliceParameterBufferHEVC) {
1447     .slice_segment_address = start_address,
1448     .num_ctu_in_slice = ctu_num,
1449     .slice_type = frame->type,
1450     /* Only one parameter set supported now. */
1451     .slice_pic_parameter_set_id = 0,
1452     /* Set the reference list later
1453     .num_ref_idx_l0_active_minus1,
1454     .num_ref_idx_l1_active_minus1,
1455     .ref_pic_list0[15],
1456     .ref_pic_list1[15], */
1457     /* weighted_pred_flag or weighted_bipred_idc is not enabled. */
1458     .luma_log2_weight_denom = 0,
1459     .delta_chroma_log2_weight_denom = 0,
1460     .delta_luma_weight_l0 = { 0, },
1461     .luma_offset_l0 = { 0, },
1462     .delta_chroma_weight_l0 = { },
1463     .chroma_offset_l0 = { },
1464     .delta_luma_weight_l1 = { },
1465     .luma_offset_l1 = { },
1466     .delta_chroma_weight_l1 = { },
1467     .chroma_offset_l1 = { },
1468
1469     .max_num_merge_cand = 5,
1470     .slice_qp_delta = slice_qp_delta,
1471     .slice_cb_qp_offset = 0,
1472     .slice_cr_qp_offset = 0,
1473     /* deblocking_filter_control_present_flag not set now. */
1474     .slice_beta_offset_div2 = 0,
1475     .slice_tc_offset_div2 = 0,
1476     .slice_fields.bits = {
1477       .last_slice_of_pic_flag = last_slice_of_pic,
1478       .dependent_slice_segment_flag = (start_address == 0 ? 0 :
1479           self->features.dependent_slice_segment_flag),
1480       .colour_plane_id = self->features.colour_plane_id,
1481       .slice_temporal_mvp_enabled_flag =
1482           self->features.temporal_mvp_enabled_flag,
1483       .slice_sao_luma_flag = self->features.slice_sao_luma_flag,
1484       .slice_sao_chroma_flag = self->features.slice_sao_chroma_flag,
1485       /* Set the reference list later
1486       .num_ref_idx_active_override_flag, */
1487       .mvd_l1_zero_flag = 0,
1488       /* cabac_init_present_flag is not set now. */
1489       .cabac_init_flag = 0,
1490       /* deblocking_filter_control_present_flag not set now */
1491       .slice_deblocking_filter_disabled_flag = 0,
1492       .slice_loop_filter_across_slices_enabled_flag = 1,
1493       .collocated_from_l0_flag = (frame->type == GST_H265_I_SLICE ?
1494           0 : self->features.collocated_from_l0_flag),
1495     },
1496 #if VA_CHECK_VERSION(1, 10, 0)
1497     .pred_weight_table_bit_offset = 0,
1498     .pred_weight_table_bit_length = 0,
1499 #endif
1500   };
1501   /* *INDENT-ON* */
1502
1503   if (frame->type == GST_H265_B_SLICE || frame->type == GST_H265_P_SLICE) {
1504     slice->slice_fields.bits.num_ref_idx_active_override_flag =
1505         (list0_num > 0 || list1_num > 0);
1506     slice->num_ref_idx_l0_active_minus1 = list0_num > 0 ? list0_num - 1 : 0;
1507     if (frame->type == GST_H265_B_SLICE)
1508       slice->num_ref_idx_l1_active_minus1 = list1_num > 0 ? list1_num - 1 : 0;
1509   }
1510
1511   i = 0;
1512   if (frame->type != GST_H265_I_SLICE) {
1513     for (; i < list0_num; i++) {
1514       slice->ref_pic_list0[i].picture_id =
1515           gst_va_encode_picture_get_reconstruct_surface (list0[i]->picture);
1516       slice->ref_pic_list0[i].pic_order_cnt = list0[i]->poc;
1517     }
1518   }
1519   for (; i < G_N_ELEMENTS (slice->ref_pic_list0); ++i) {
1520     slice->ref_pic_list0[i].picture_id = VA_INVALID_SURFACE;
1521     slice->ref_pic_list0[i].flags = VA_PICTURE_HEVC_INVALID;
1522   }
1523
1524   i = 0;
1525   if (frame->type == GST_H265_B_SLICE) {
1526     for (; i < list1_num; i++) {
1527       slice->ref_pic_list1[i].picture_id =
1528           gst_va_encode_picture_get_reconstruct_surface (list1[i]->picture);
1529       slice->ref_pic_list1[i].pic_order_cnt = list1[i]->poc;
1530     }
1531   }
1532   for (; i < G_N_ELEMENTS (slice->ref_pic_list1); ++i) {
1533     slice->ref_pic_list1[i].picture_id = VA_INVALID_SURFACE;
1534     slice->ref_pic_list1[i].flags = VA_PICTURE_HEVC_INVALID;
1535   }
1536
1537   return TRUE;
1538 }
1539
1540 static gboolean
1541 _h265_add_sequence_parameter (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1542     VAEncSequenceParameterBufferHEVC * sequence)
1543 {
1544   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1545
1546   if (!gst_va_encoder_add_param (base->encoder, frame->picture,
1547           VAEncSequenceParameterBufferType, sequence, sizeof (*sequence))) {
1548     GST_ERROR_OBJECT (self, "Failed to create the sequence parameter");
1549     return FALSE;
1550   }
1551
1552   return TRUE;
1553 }
1554
1555 static gboolean
1556 _h265_add_picture_parameter (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1557     VAEncPictureParameterBufferHEVC * pic_param)
1558 {
1559   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1560
1561   if (!gst_va_encoder_add_param (base->encoder, frame->picture,
1562           VAEncPictureParameterBufferType, pic_param,
1563           sizeof (VAEncPictureParameterBufferHEVC))) {
1564     GST_ERROR_OBJECT (self, "Failed to create the picture parameter");
1565     return FALSE;
1566   }
1567
1568   return TRUE;
1569 }
1570
1571 static gboolean
1572 _h265_add_slice_parameter (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1573     VAEncSliceParameterBufferHEVC * slice)
1574 {
1575   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1576
1577   if (!gst_va_encoder_add_param (base->encoder, frame->picture,
1578           VAEncSliceParameterBufferType, slice,
1579           sizeof (VAEncSliceParameterBufferHEVC))) {
1580     GST_ERROR_OBJECT (self, "Failed to add the slice parameter");
1581     return FALSE;
1582   }
1583
1584   return TRUE;
1585 }
1586
1587 static gboolean
1588 _h265_add_slices (GstVaH265Enc * self,
1589     GstVaH265EncFrame * frame, GstH265PPS * pps,
1590     GstVaH265EncFrame * list_forward[16], guint list_forward_num,
1591     GstVaH265EncFrame * list_backward[16], guint list_backward_num,
1592     gint negative_pocs[16], guint num_negative_pics,
1593     gint positive_pocs[16], guint num_positive_pics)
1594 {
1595   guint ctu_size;
1596   guint ctus_per_slice, ctus_mod_slice, cur_slice_ctus;
1597   guint last_ctu_index;
1598   guint i_slice;
1599   VAEncSliceParameterBufferHEVC slice;
1600   GstH265SliceHdr slice_hdr;
1601
1602   ctu_size = self->ctu_width * self->ctu_height;
1603
1604   g_assert (self->num_slices && self->num_slices < ctu_size);
1605
1606   ctus_per_slice = ctu_size / self->num_slices;
1607   ctus_mod_slice = ctu_size % self->num_slices;
1608   last_ctu_index = 0;
1609
1610   for (i_slice = 0; i_slice < self->num_slices; i_slice++) {
1611     cur_slice_ctus = ctus_per_slice;
1612     /* Scatter the remainder to each slice */
1613     if (ctus_mod_slice) {
1614       ++cur_slice_ctus;
1615       --ctus_mod_slice;
1616     }
1617
1618     if (!_h265_fill_slice_parameter (self, frame, last_ctu_index,
1619             cur_slice_ctus, (i_slice == self->num_slices - 1),
1620             list_forward, list_forward_num,
1621             list_backward, list_backward_num, &slice))
1622       return FALSE;
1623
1624     if (!_h265_add_slice_parameter (self, frame, &slice))
1625       return FALSE;
1626
1627     if (self->packed_headers & VA_ENC_PACKED_HEADER_SLICE) {
1628       if (!_h265_fill_slice_header (self, frame, pps, &slice, i_slice == 0,
1629               list_forward_num, list_backward_num, negative_pocs,
1630               num_negative_pics, positive_pocs, num_positive_pics, &slice_hdr))
1631         return FALSE;
1632
1633       if (!_h265_add_slice_header (self, frame, &slice_hdr))
1634         return FALSE;
1635     }
1636
1637     /* set calculation for next slice */
1638     last_ctu_index += cur_slice_ctus;
1639     g_assert (last_ctu_index <= ctu_size);
1640   }
1641
1642   return TRUE;
1643 }
1644
1645 static gint
1646 _poc_asc_compare (const GstVaH265EncFrame ** a, const GstVaH265EncFrame ** b)
1647 {
1648   return (*a)->poc - (*b)->poc;
1649 }
1650
1651 static gint
1652 _poc_des_compare (const GstVaH265EncFrame ** a, const GstVaH265EncFrame ** b)
1653 {
1654   return (*b)->poc - (*a)->poc;
1655 }
1656
1657 static gboolean
1658 _h265_encode_one_frame (GstVaH265Enc * self, GstVideoCodecFrame * gst_frame)
1659 {
1660   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1661   VAEncPictureParameterBufferHEVC pic_param;
1662   GstH265PPS pps;
1663   GstVaH265EncFrame *frame;
1664   GstVaH265EncFrame *list_forward[16] = { NULL, };
1665   guint list_forward_num = 0;
1666   GstVaH265EncFrame *list_backward[16] = { NULL, };
1667   guint list_backward_num = 0;
1668   gint negative_pocs[16] = { };
1669   guint num_negative_pics = 0;
1670   gint positive_pocs[16] = { };
1671   guint num_positive_pics = 0;
1672   gint collocated_poc = -1;
1673   gint i;
1674
1675   g_return_val_if_fail (gst_frame, FALSE);
1676
1677   frame = _enc_frame (gst_frame);
1678
1679   if (self->aud && !_h265_add_aud (self, frame))
1680     return FALSE;
1681
1682   /* Repeat the VPS/SPS for IDR. */
1683   if (frame->poc == 0) {
1684     VAEncSequenceParameterBufferHEVC sequence;
1685
1686     if (!gst_va_base_enc_add_rate_control_parameter (base, frame->picture,
1687             self->rc.rc_ctrl_mode, self->rc.max_bitrate_bits,
1688             self->rc.target_percentage, self->rc.qp_i, self->rc.min_qp,
1689             self->rc.max_qp, self->rc.mbbrc))
1690       return FALSE;
1691
1692     if (!gst_va_base_enc_add_quality_level_parameter (base, frame->picture,
1693             self->rc.target_usage))
1694       return FALSE;
1695
1696     if (!gst_va_base_enc_add_frame_rate_parameter (base, frame->picture))
1697       return FALSE;
1698
1699     if (!gst_va_base_enc_add_hrd_parameter (base, frame->picture,
1700             self->rc.rc_ctrl_mode, self->rc.cpb_length_bits))
1701       return FALSE;
1702
1703     if (!gst_va_base_enc_add_trellis_parameter (base, frame->picture,
1704             self->features.use_trellis))
1705       return FALSE;
1706
1707     _h265_fill_sequence_parameter (self, &sequence);
1708     if (!_h265_add_sequence_parameter (self, frame, &sequence))
1709       return FALSE;
1710
1711     if (self->packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE) {
1712       if (!_h265_fill_vps (self, &sequence))
1713         return FALSE;
1714
1715       if (!_h265_fill_sps (self, &sequence))
1716         return FALSE;
1717
1718       if (!_h265_add_vps_header (self, frame))
1719         return FALSE;
1720
1721       if (!_h265_add_sps_header (self, frame))
1722         return FALSE;
1723     }
1724   }
1725
1726   /* Non I frame, construct reference list. */
1727   if (frame->type != GST_H265_I_SLICE) {
1728     GstVaH265EncFrame *vaf;
1729     GstVideoCodecFrame *f;
1730
1731     for (i = g_queue_get_length (&base->ref_list) - 1; i >= 0; i--) {
1732       f = g_queue_peek_nth (&base->ref_list, i);
1733       vaf = _enc_frame (f);
1734       if (vaf->poc > frame->poc)
1735         continue;
1736
1737       list_forward[list_forward_num] = vaf;
1738       list_forward_num++;
1739     }
1740
1741     /* reorder to select the most nearest forward frames. */
1742     g_qsort_with_data (list_forward, list_forward_num, sizeof (gpointer),
1743         (GCompareDataFunc) _poc_des_compare, NULL);
1744
1745     num_negative_pics = list_forward_num;
1746     for (i = 0; i < list_forward_num; i++)
1747       negative_pocs[i] = list_forward[i]->poc;
1748
1749     if (list_forward_num > self->gop.forward_ref_num)
1750       list_forward_num = self->gop.forward_ref_num;
1751
1752     if (self->features.temporal_mvp_enabled_flag
1753         && self->features.collocated_from_l0_flag) {
1754       if (self->features.collocated_ref_idx >= list_forward_num) {
1755         GST_ERROR_OBJECT (self, "MVP collocated_ref_idx %d is out of L0 range",
1756             self->features.collocated_ref_idx);
1757         return FALSE;
1758       }
1759
1760       collocated_poc = list_forward[self->features.collocated_ref_idx]->poc;
1761     }
1762   }
1763
1764   if (frame->type == GST_H265_B_SLICE) {
1765     GstVaH265EncFrame *vaf;
1766     GstVideoCodecFrame *f;
1767
1768     for (i = 0; i < g_queue_get_length (&base->ref_list); i++) {
1769       f = g_queue_peek_nth (&base->ref_list, i);
1770       vaf = _enc_frame (f);
1771       if (vaf->poc < frame->poc)
1772         continue;
1773
1774       list_backward[list_backward_num] = vaf;
1775       list_backward_num++;
1776     }
1777
1778     /* reorder to select the most nearest backward frames. */
1779     g_qsort_with_data (list_backward, list_backward_num, sizeof (gpointer),
1780         (GCompareDataFunc) _poc_asc_compare, NULL);
1781
1782     num_positive_pics = list_backward_num;
1783     for (i = 0; i < list_backward_num; i++)
1784       positive_pocs[i] = list_backward[i]->poc;
1785
1786     if (list_backward_num > self->gop.backward_ref_num)
1787       list_backward_num = self->gop.backward_ref_num;
1788
1789     if (self->features.temporal_mvp_enabled_flag
1790         && !self->features.collocated_from_l0_flag) {
1791       if (self->features.collocated_ref_idx >= list_backward_num) {
1792         GST_ERROR_OBJECT (self, "MVP collocated_ref_idx %d is out of L1 range",
1793             self->features.collocated_ref_idx);
1794         return FALSE;
1795       }
1796
1797       collocated_poc = list_backward[self->features.collocated_ref_idx]->poc;
1798     }
1799   }
1800
1801   g_assert (list_forward_num + list_backward_num <= self->gop.num_ref_frames);
1802
1803   if (!_h265_fill_picture_parameter (self, frame, &pic_param, collocated_poc))
1804     return FALSE;
1805   if (!_h265_add_picture_parameter (self, frame, &pic_param))
1806     return FALSE;
1807
1808   _h265_fill_pps (&pic_param, &self->sps_hdr, &pps);
1809
1810   if ((self->packed_headers & VA_ENC_PACKED_HEADER_PICTURE)
1811       && frame->type == GST_H265_I_SLICE
1812       && !_h265_add_pps_header (self, frame, &pps))
1813     return FALSE;
1814
1815   if (!_h265_add_slices (self, frame, &pps,
1816           list_forward, list_forward_num, list_backward, list_backward_num,
1817           negative_pocs, num_negative_pics, positive_pocs, num_positive_pics))
1818     return FALSE;
1819
1820   if (!gst_va_encoder_encode (base->encoder, frame->picture)) {
1821     GST_ERROR_OBJECT (self, "Encode frame error");
1822     return FALSE;
1823   }
1824
1825   return TRUE;
1826 }
1827
1828 static gboolean
1829 _h265_push_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame * gst_frame,
1830     gboolean last)
1831 {
1832   GstVaH265Enc *self = GST_VA_H265_ENC (base);
1833   GstVaH265EncFrame *frame;
1834
1835   g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
1836       FALSE);
1837
1838   if (gst_frame) {
1839     /* Begin a new GOP, should have a empty reorder_list. */
1840     if (self->gop.cur_frame_index == self->gop.idr_period) {
1841       g_assert (g_queue_is_empty (&base->reorder_list));
1842       self->gop.cur_frame_index = 0;
1843     }
1844
1845     frame = _enc_frame (gst_frame);
1846     frame->poc = self->gop.cur_frame_index;
1847     g_assert (self->gop.cur_frame_index <= self->gop.max_pic_order_cnt);
1848
1849     if (self->gop.cur_frame_index == 0) {
1850       g_assert (frame->poc == 0);
1851       GST_LOG_OBJECT (self, "system_frame_number: %d, an IDR frame, starts"
1852           " a new GOP", gst_frame->system_frame_number);
1853
1854       g_queue_clear_full (&base->ref_list,
1855           (GDestroyNotify) gst_video_codec_frame_unref);
1856     }
1857
1858     frame->type = self->gop.frame_types[self->gop.cur_frame_index].slice_type;
1859     frame->is_ref = self->gop.frame_types[self->gop.cur_frame_index].is_ref;
1860     frame->pyramid_level =
1861         self->gop.frame_types[self->gop.cur_frame_index].pyramid_level;
1862     frame->left_ref_poc_diff =
1863         self->gop.frame_types[self->gop.cur_frame_index].left_ref_poc_diff;
1864     frame->right_ref_poc_diff =
1865         self->gop.frame_types[self->gop.cur_frame_index].right_ref_poc_diff;
1866
1867     if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (gst_frame)) {
1868       GST_DEBUG_OBJECT (self, "system_frame_number: %d, a force key frame,"
1869           " promote its type from %s to %s", gst_frame->system_frame_number,
1870           _h265_slice_type_name (frame->type),
1871           _h265_slice_type_name (GST_H265_I_SLICE));
1872       frame->type = GST_H265_I_SLICE;
1873       frame->is_ref = TRUE;
1874     }
1875
1876     GST_LOG_OBJECT (self, "Push frame, system_frame_number: %d, poc %d, "
1877         "frame type %s", gst_frame->system_frame_number, frame->poc,
1878         _h265_slice_type_name (frame->type));
1879
1880     self->gop.cur_frame_index++;
1881     g_queue_push_tail (&base->reorder_list,
1882         gst_video_codec_frame_ref (gst_frame));
1883   }
1884
1885   /* ensure the last one a non-B and end the GOP. */
1886   if (last && self->gop.cur_frame_index < self->gop.idr_period) {
1887     GstVideoCodecFrame *last_frame;
1888
1889     /* Ensure next push will start a new GOP. */
1890     self->gop.cur_frame_index = self->gop.idr_period;
1891
1892     if (!g_queue_is_empty (&base->reorder_list)) {
1893       last_frame = g_queue_peek_tail (&base->reorder_list);
1894       frame = _enc_frame (last_frame);
1895       if (frame->type == GST_H265_B_SLICE) {
1896         frame->type = GST_H265_P_SLICE;
1897         frame->is_ref = TRUE;
1898       }
1899     }
1900   }
1901
1902   return TRUE;
1903 }
1904
1905 struct RefFramesCount
1906 {
1907   gint poc;
1908   guint num;
1909 };
1910
1911 static void
1912 _count_backward_ref_num (gpointer data, gpointer user_data)
1913 {
1914   GstVaH265EncFrame *frame = _enc_frame (data);
1915   struct RefFramesCount *count = (struct RefFramesCount *) user_data;
1916
1917   g_assert (frame->poc != count->poc);
1918   if (frame->poc > count->poc)
1919     count->num++;
1920 }
1921
1922 static GstVideoCodecFrame *
1923 _h265_pop_pyramid_b_frame (GstVaH265Enc * self)
1924 {
1925   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1926   guint i;
1927   gint index = -1;
1928   GstVaH265EncFrame *b_vaframe;
1929   GstVideoCodecFrame *b_frame;
1930   struct RefFramesCount count;
1931
1932   g_assert (self->gop.backward_ref_num <= 2);
1933
1934   b_frame = NULL;
1935   b_vaframe = NULL;
1936
1937   /* Find the highest level with smallest poc. */
1938   for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
1939     GstVaH265EncFrame *vaf;
1940     GstVideoCodecFrame *f;
1941
1942     f = g_queue_peek_nth (&base->reorder_list, i);
1943
1944     if (!b_frame) {
1945       b_frame = f;
1946       b_vaframe = _enc_frame (b_frame);
1947       index = i;
1948       continue;
1949     }
1950
1951     vaf = _enc_frame (f);
1952     if (b_vaframe->pyramid_level < vaf->pyramid_level) {
1953       b_frame = f;
1954       b_vaframe = vaf;
1955       index = i;
1956       continue;
1957     }
1958
1959     if (b_vaframe->poc > vaf->poc) {
1960       b_frame = f;
1961       b_vaframe = vaf;
1962       index = i;
1963     }
1964   }
1965
1966 again:
1967   /* Check whether its refs are already poped. */
1968   g_assert (b_vaframe->left_ref_poc_diff != 0);
1969   g_assert (b_vaframe->right_ref_poc_diff != 0);
1970   for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
1971     GstVaH265EncFrame *vaf;
1972     GstVideoCodecFrame *f;
1973
1974     f = g_queue_peek_nth (&base->reorder_list, i);
1975
1976     if (f == b_frame)
1977       continue;
1978
1979     vaf = _enc_frame (f);
1980     if (vaf->poc == b_vaframe->poc + b_vaframe->left_ref_poc_diff
1981         || vaf->poc == b_vaframe->poc + b_vaframe->right_ref_poc_diff) {
1982       b_frame = f;
1983       b_vaframe = vaf;
1984       index = i;
1985       goto again;
1986     }
1987   }
1988
1989   /* Ensure we already have backward refs */
1990   count.num = 0;
1991   count.poc = b_vaframe->poc;
1992   g_queue_foreach (&base->ref_list, (GFunc) _count_backward_ref_num, &count);
1993   if (count.num >= 1) {
1994     GstVideoCodecFrame *f;
1995
1996     /* it will unref at pop_frame */
1997     f = g_queue_pop_nth (&base->reorder_list, index);
1998     g_assert (f == b_frame);
1999   } else {
2000     b_frame = NULL;
2001   }
2002
2003   return b_frame;
2004 }
2005
2006 static gboolean
2007 _h265_pop_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame ** out_frame)
2008 {
2009   GstVaH265Enc *self = GST_VA_H265_ENC (base);
2010   GstVaH265EncFrame *vaframe;
2011   GstVideoCodecFrame *frame;
2012   struct RefFramesCount count;
2013
2014   g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
2015       FALSE);
2016
2017   *out_frame = NULL;
2018
2019   if (g_queue_is_empty (&base->reorder_list))
2020     return TRUE;
2021
2022   /* Return the last pushed non-B immediately. */
2023   frame = g_queue_peek_tail (&base->reorder_list);
2024   vaframe = _enc_frame (frame);
2025   if (vaframe->type != GST_H265_B_SLICE) {
2026     frame = g_queue_pop_tail (&base->reorder_list);
2027     goto get_one;
2028   }
2029
2030   if (self->gop.b_pyramid) {
2031     frame = _h265_pop_pyramid_b_frame (self);
2032     if (frame == NULL)
2033       return TRUE;
2034
2035     goto get_one;
2036   }
2037
2038   g_assert (self->gop.backward_ref_num > 0);
2039
2040   /* If GOP end, pop anyway. */
2041   if (self->gop.cur_frame_index == self->gop.idr_period) {
2042     frame = g_queue_pop_head (&base->reorder_list);
2043     goto get_one;
2044   }
2045
2046   /* Ensure we already have enough backward refs */
2047   frame = g_queue_peek_head (&base->reorder_list);
2048   vaframe = _enc_frame (frame);
2049   count.num = 0;
2050   count.poc = vaframe->poc;
2051   g_queue_foreach (&base->ref_list, _count_backward_ref_num, &count);
2052   if (count.num >= self->gop.backward_ref_num) {
2053     frame = g_queue_pop_head (&base->reorder_list);
2054     goto get_one;
2055   }
2056
2057   return TRUE;
2058
2059 get_one:
2060   vaframe = _enc_frame (frame);
2061
2062   if (vaframe->poc == 0)
2063     self->gop.total_idr_count++;
2064
2065   if (self->gop.b_pyramid && vaframe->type == GST_H265_B_SLICE) {
2066     GST_LOG_OBJECT (self, "pop a pyramid B frame with system_frame_number:"
2067         " %d, poc: %d, is_ref: %s, level %d",
2068         frame->system_frame_number, vaframe->poc,
2069         vaframe->is_ref ? "true" : "false", vaframe->pyramid_level);
2070   } else {
2071     GST_LOG_OBJECT (self, "pop a frame with system_frame_number: %d,"
2072         " frame type: %s, poc: %d, is_ref: %s",
2073         frame->system_frame_number, _h265_slice_type_name (vaframe->type),
2074         vaframe->poc, vaframe->is_ref ? "true" : "false");
2075   }
2076
2077   /* unref frame popped from queue or pyramid b_frame */
2078   gst_video_codec_frame_unref (frame);
2079   *out_frame = frame;
2080   return TRUE;
2081 }
2082
2083 static gboolean
2084 gst_va_h265_enc_reorder_frame (GstVaBaseEnc * base, GstVideoCodecFrame * frame,
2085     gboolean bump_all, GstVideoCodecFrame ** out_frame)
2086 {
2087   if (!_h265_push_one_frame (base, frame, bump_all)) {
2088     GST_ERROR_OBJECT (base, "Failed to push the input frame"
2089         " system_frame_number: %d into the reorder list",
2090         frame->system_frame_number);
2091
2092     *out_frame = NULL;
2093     return FALSE;
2094   }
2095
2096   if (!_h265_pop_one_frame (base, out_frame)) {
2097     GST_ERROR_OBJECT (base, "Failed to pop the frame from the reorder list");
2098     *out_frame = NULL;
2099     return FALSE;
2100   }
2101
2102   return TRUE;
2103 }
2104
2105 static GstVideoCodecFrame *
2106 _h265_find_unused_reference_frame (GstVaH265Enc * self,
2107     GstVaH265EncFrame * frame)
2108 {
2109   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2110   GstVaH265EncFrame *b_vaframe;
2111   GstVideoCodecFrame *b_frame;
2112   guint i;
2113
2114   /* We still have more space. */
2115   if (g_queue_get_length (&base->ref_list) < self->gop.num_ref_frames)
2116     return NULL;
2117
2118   /* Not b_pyramid, sliding window is enough. */
2119   if (!self->gop.b_pyramid)
2120     return g_queue_peek_head (&base->ref_list);
2121
2122   /* Non-b ref frame, just pop the first one. */
2123   if (frame->type != GST_H265_B_SLICE)
2124     return g_queue_peek_head (&base->ref_list);
2125
2126   /* Choose the B frame with lowest POC. */
2127   b_frame = NULL;
2128   b_vaframe = NULL;
2129   for (i = 0; i < g_queue_get_length (&base->ref_list); i++) {
2130     GstVideoCodecFrame *f;
2131     GstVaH265EncFrame *vaf;
2132
2133     f = g_queue_peek_nth (&base->ref_list, i);
2134     vaf = _enc_frame (f);
2135     if (vaf->type != GST_H265_B_SLICE)
2136       continue;
2137
2138     if (!b_frame) {
2139       g_assert (b_vaframe == NULL);
2140       b_frame = f;
2141       b_vaframe = vaf;
2142       continue;
2143     }
2144
2145     g_assert (b_vaframe);
2146     g_assert (vaf->poc != b_vaframe->poc);
2147     if (vaf->poc < b_vaframe->poc) {
2148       b_frame = f;
2149       b_vaframe = vaf;
2150     }
2151   }
2152
2153   /* No B frame as ref. */
2154   if (!b_frame)
2155     return g_queue_peek_head (&base->ref_list);
2156
2157   if (b_frame != g_queue_peek_head (&base->ref_list)) {
2158     b_vaframe = _enc_frame (b_frame);
2159     GST_LOG_OBJECT (self, "The frame with POC: %d will be"
2160         " replaced by the frame with POC: %d explicitly",
2161         b_vaframe->poc, frame->poc);
2162   }
2163
2164   return b_frame;
2165 }
2166
2167 static gint
2168 _sort_by_poc (gconstpointer a, gconstpointer b, gpointer user_data)
2169 {
2170   GstVaH265EncFrame *frame1 = _enc_frame ((GstVideoCodecFrame *) a);
2171   GstVaH265EncFrame *frame2 = _enc_frame ((GstVideoCodecFrame *) b);
2172
2173   g_assert (frame1->poc != frame2->poc);
2174
2175   return frame1->poc - frame2->poc;
2176 }
2177
2178 static GstFlowReturn
2179 gst_va_h265_enc_encode_frame (GstVaBaseEnc * base,
2180     GstVideoCodecFrame * gst_frame, gboolean is_last)
2181 {
2182   GstVaH265Enc *self = GST_VA_H265_ENC (base);
2183   GstVaH265EncFrame *frame;
2184   GstVideoCodecFrame *unused_ref;
2185
2186   frame = _enc_frame (gst_frame);
2187   frame->last_frame = is_last;
2188
2189   g_assert (frame->picture == NULL);
2190   frame->picture = gst_va_encode_picture_new (base->encoder,
2191       gst_frame->input_buffer);
2192
2193   if (!frame->picture) {
2194     GST_ERROR_OBJECT (base, "Failed to create the encode picture");
2195     return GST_FLOW_ERROR;
2196   }
2197
2198   if (!_h265_encode_one_frame (self, gst_frame)) {
2199     GST_ERROR_OBJECT (base, "Failed to encode the frame");
2200     return GST_FLOW_ERROR;
2201   }
2202
2203   g_queue_push_tail (&base->output_list, gst_video_codec_frame_ref (gst_frame));
2204
2205   if (frame->is_ref) {
2206     unused_ref = _h265_find_unused_reference_frame (self, frame);
2207
2208     if (unused_ref) {
2209       if (!g_queue_remove (&base->ref_list, unused_ref))
2210         g_assert_not_reached ();
2211
2212       gst_video_codec_frame_unref (unused_ref);
2213     }
2214
2215     /* Add it into the reference list. */
2216     g_queue_push_tail (&base->ref_list, gst_video_codec_frame_ref (gst_frame));
2217     g_queue_sort (&base->ref_list, _sort_by_poc, NULL);
2218
2219     g_assert (g_queue_get_length (&base->ref_list) <= self->gop.num_ref_frames);
2220   }
2221
2222   return GST_FLOW_OK;
2223 }
2224
2225 /* Clear all the info of last reconfig and set the fields based on
2226  * property. The reconfig may change these fields because of the
2227  * profile/level and HW limitation. */
2228 static void
2229 gst_va_h265_enc_reset_state (GstVaBaseEnc * base)
2230 {
2231   GstVaH265Enc *self = GST_VA_H265_ENC (base);
2232
2233   GST_VA_BASE_ENC_CLASS (parent_class)->reset_state (base);
2234
2235   GST_OBJECT_LOCK (self);
2236   self->features.use_trellis = self->prop.use_trellis;
2237   self->aud = self->prop.aud;
2238   self->num_slices = self->prop.num_slices;
2239   self->gop.idr_period = self->prop.key_int_max;
2240   self->gop.num_bframes = self->prop.num_bframes;
2241   self->gop.b_pyramid = self->prop.b_pyramid;
2242   self->gop.num_iframes = self->prop.num_iframes;
2243   self->gop.num_ref_frames = self->prop.num_ref_frames;
2244   self->rc.rc_ctrl_mode = self->prop.rc_ctrl;
2245   self->rc.min_qp = self->prop.min_qp;
2246   self->rc.max_qp = self->prop.max_qp;
2247   self->rc.qp_i = self->prop.qp_i;
2248   self->rc.qp_p = self->prop.qp_p;
2249   self->rc.qp_b = self->prop.qp_b;
2250   self->rc.mbbrc = self->prop.mbbrc;
2251   self->rc.target_percentage = self->prop.target_percentage;
2252   self->rc.target_usage = self->prop.target_usage;
2253   self->rc.cpb_size = self->prop.cpb_size;
2254   GST_OBJECT_UNLOCK (self);
2255
2256   self->level_idc = 0;
2257   self->level_str = NULL;
2258   self->min_cr = 0;
2259   self->tier_flag = FALSE;
2260   self->ctu_size = 0;
2261   self->min_coding_block_size = 0;
2262   self->ctu_width = 0;
2263   self->ctu_height = 0;
2264   self->luma_width = 0;
2265   self->luma_height = 0;
2266   self->conformance_window_flag = FALSE;
2267   self->conf_win_left_offset = 0;
2268   self->conf_win_right_offset = 0;
2269   self->conf_win_top_offset = 0;
2270   self->conf_win_bottom_offset = 0;
2271
2272   self->bits_depth_luma_minus8 = 0;
2273   self->bits_depth_chroma_minus8 = 0;
2274
2275   self->packed_headers = 0;
2276
2277   self->features.log2_min_luma_coding_block_size_minus3 = 0;
2278   self->features.log2_diff_max_min_luma_coding_block_size = 0;
2279   self->features.log2_diff_max_min_luma_coding_block_size = 0;
2280   self->features.log2_min_transform_block_size_minus2 = 0;
2281   self->features.log2_diff_max_min_transform_block_size = 0;
2282   self->features.max_transform_hierarchy_depth_inter = 0;
2283   self->features.max_transform_hierarchy_depth_intra = 0;
2284   self->features.separate_colour_plane_flag = FALSE;
2285   self->features.colour_plane_id = 0;
2286   self->features.scaling_list_enabled_flag = FALSE;
2287   self->features.scaling_list_data_present_flag = FALSE;
2288   self->features.amp_enabled_flag = FALSE;
2289   self->features.sample_adaptive_offset_enabled_flag = FALSE;
2290   self->features.slice_sao_luma_flag = FALSE;
2291   self->features.slice_sao_chroma_flag = FALSE;
2292   self->features.pcm_enabled_flag = FALSE;
2293   self->features.pcm_sample_bit_depth_luma_minus1 = 0;
2294   self->features.pcm_sample_bit_depth_chroma_minus1 = 0;
2295   self->features.log2_min_pcm_luma_coding_block_size_minus3 = 0;
2296   self->features.log2_max_pcm_luma_coding_block_size_minus3 = 0;
2297   self->features.temporal_mvp_enabled_flag = FALSE;
2298   self->features.collocated_from_l0_flag = FALSE;
2299   self->features.collocated_ref_idx = 0xFF;
2300   self->features.strong_intra_smoothing_enabled_flag = FALSE;
2301   self->features.dependent_slice_segment_flag = FALSE;
2302   self->features.sign_data_hiding_enabled_flag = FALSE;
2303   self->features.constrained_intra_pred_flag = FALSE;
2304   self->features.transform_skip_enabled_flag = FALSE;
2305   self->features.cu_qp_delta_enabled_flag = FALSE;
2306   self->features.diff_cu_qp_delta_depth = 0;
2307   self->features.weighted_pred_flag = FALSE;
2308   self->features.weighted_bipred_flag = FALSE;
2309   self->features.transquant_bypass_enabled_flag = FALSE;
2310
2311   self->gop.i_period = 0;
2312   self->gop.total_idr_count = 0;
2313   self->gop.ip_period = 0;
2314   self->gop.highest_pyramid_level = 0;
2315   memset (self->gop.frame_types, 0, sizeof (self->gop.frame_types));
2316   self->gop.cur_frame_index = 0;
2317   self->gop.max_pic_order_cnt = 0;
2318   self->gop.log2_max_pic_order_cnt = 0;
2319   /* VAEncPictureParameterBufferHEVC.reference_frames limit 15 refs */
2320   self->gop.max_l0_num = 0;
2321   self->gop.max_l1_num = 0;
2322   self->gop.forward_ref_num = 0;
2323   self->gop.backward_ref_num = 0;
2324   self->gop.num_reorder_frames = 0;
2325   self->gop.max_dpb_size = 0;
2326
2327   self->rc.max_bitrate = 0;
2328   self->rc.target_bitrate = 0;
2329   self->rc.max_bitrate_bits = 0;
2330   self->rc.target_bitrate_bits = 0;
2331   self->rc.cpb_length_bits = 0;
2332
2333   memset (&self->vps_hdr, 0, sizeof (GstH265VPS));
2334   memset (&self->sps_hdr, 0, sizeof (GstH265SPS));
2335 }
2336
2337 static guint
2338 _h265_get_rtformat (GstVaH265Enc * self, GstVideoFormat format)
2339 {
2340   guint chroma;
2341
2342   chroma = gst_va_chroma_from_video_format (format);
2343
2344   /* Check whether the rtformat is supported. */
2345   if (chroma != VA_RT_FORMAT_YUV420) {
2346     GST_ERROR_OBJECT (self, "Unsupported chroma for video format: %s",
2347         gst_video_format_to_string (format));
2348     return 0;
2349   }
2350
2351   return chroma;
2352 }
2353
2354 static gboolean
2355 _h265_decide_profile (GstVaH265Enc * self, VAProfile * _profile,
2356     guint * _rt_format)
2357 {
2358   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2359   gboolean ret = FALSE;
2360   GstVideoFormat in_format;
2361   VAProfile profile;
2362   guint rt_format;
2363   GstCaps *allowed_caps = NULL;
2364   guint num_structures, i;
2365   GstStructure *structure;
2366   const GValue *v_profile;
2367   GPtrArray *candidates = NULL;
2368   gchar *profile_name;
2369
2370   candidates = g_ptr_array_new_with_free_func (g_free);
2371
2372   /* First, check whether the downstream requires a specified profile. */
2373   allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (base));
2374   if (!allowed_caps)
2375     allowed_caps = gst_pad_query_caps (GST_VIDEO_ENCODER_SRC_PAD (base), NULL);
2376
2377   if (allowed_caps && !gst_caps_is_empty (allowed_caps)) {
2378     num_structures = gst_caps_get_size (allowed_caps);
2379     for (i = 0; i < num_structures; i++) {
2380       structure = gst_caps_get_structure (allowed_caps, i);
2381       v_profile = gst_structure_get_value (structure, "profile");
2382       if (!v_profile)
2383         continue;
2384
2385       if (G_VALUE_HOLDS_STRING (v_profile)) {
2386         profile_name = g_strdup (g_value_get_string (v_profile));
2387         g_ptr_array_add (candidates, profile_name);
2388       } else if (GST_VALUE_HOLDS_LIST (v_profile)) {
2389         guint j;
2390
2391         for (j = 0; j < gst_value_list_get_size (v_profile); j++) {
2392           const GValue *p = gst_value_list_get_value (v_profile, j);
2393           if (!p)
2394             continue;
2395
2396           profile_name = g_strdup (g_value_get_string (p));
2397           g_ptr_array_add (candidates, profile_name);
2398         }
2399       }
2400     }
2401   }
2402
2403   if (candidates->len == 0) {
2404     GST_ERROR_OBJECT (self, "No available profile in caps");
2405     ret = FALSE;
2406     goto out;
2407   }
2408
2409   in_format = GST_VIDEO_INFO_FORMAT (&base->input_state->info);
2410   rt_format = _h265_get_rtformat (self, in_format);
2411   if (!rt_format) {
2412     GST_ERROR_OBJECT (self, "unsupported video format %s",
2413         gst_video_format_to_string (in_format));
2414     ret = FALSE;
2415     goto out;
2416   }
2417
2418   /* Find the suitable profile by features and check the HW
2419    * support. */
2420
2421   /* Just use the first HW available profile and disable features if
2422    * needed. */
2423   profile_name = NULL;
2424   for (i = 0; i < candidates->len; i++) {
2425     profile_name = g_ptr_array_index (candidates, i);
2426     profile = gst_va_profile_from_name (HEVC, profile_name);
2427     if (profile == VAProfileNone)
2428       continue;
2429
2430     if (!gst_va_encoder_has_profile (base->encoder, profile))
2431       continue;
2432
2433     if ((rt_format & gst_va_encoder_get_rtformat (base->encoder,
2434                 profile, VAEntrypointEncSlice)) == 0)
2435       continue;
2436
2437     *_profile = profile;
2438     *_rt_format = rt_format;
2439     ret = TRUE;
2440     goto out;
2441   }
2442
2443   if (ret == FALSE)
2444     goto out;
2445
2446 out:
2447   g_clear_pointer (&candidates, g_ptr_array_unref);
2448   g_clear_pointer (&allowed_caps, gst_caps_unref);
2449
2450   if (ret) {
2451     GST_INFO_OBJECT (self, "Select the profile %s",
2452         gst_va_profile_name (profile));
2453   } else {
2454     GST_ERROR_OBJECT (self, "Failed to find an available profile");
2455   }
2456
2457   return ret;
2458 }
2459
2460 #define update_property(type, obj, old_val, new_val, prop_id)           \
2461   gst_va_base_enc_update_property_##type (obj, old_val, new_val, properties[prop_id])
2462 #define update_property_uint(obj, old_val, new_val, prop_id)    \
2463   update_property (uint, obj, old_val, new_val, prop_id)
2464 #define update_property_bool(obj, old_val, new_val, prop_id)    \
2465   update_property (bool, obj, old_val, new_val, prop_id)
2466
2467 static void
2468 _h265_validate_parameters (GstVaH265Enc * self)
2469 {
2470   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2471   gint32 max_slices;
2472
2473   /* Ensure the num_slices provided by the user not exceed the limit
2474    * of the number of slices permitted by the stream and by the
2475    * hardware. */
2476   g_assert (self->num_slices >= 1);
2477   max_slices = gst_va_encoder_get_max_slice_num (base->encoder,
2478       base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
2479   if (self->num_slices > max_slices)
2480     self->num_slices = max_slices;
2481
2482   /* The stream size limit. */
2483   if (self->num_slices > ((self->ctu_width * self->ctu_height + 1) / 2))
2484     self->num_slices = ((self->ctu_width * self->ctu_height + 1) / 2);
2485
2486   update_property_uint (base, &self->prop.num_slices, self->num_slices,
2487       PROP_NUM_SLICES);
2488
2489   /* Ensure trellis. */
2490   if (self->features.use_trellis &&
2491       !gst_va_encoder_has_trellis (base->encoder, base->profile,
2492           GST_VA_BASE_ENC_ENTRYPOINT (base))) {
2493     GST_INFO_OBJECT (self, "The trellis is not supported");
2494     self->features.use_trellis = FALSE;
2495   }
2496
2497   update_property_bool (base, &self->prop.use_trellis,
2498       self->features.use_trellis, PROP_TRELLIS);
2499 }
2500
2501 /* Normalizes bitrate (and CPB size) for HRD conformance */
2502 static void
2503 _h265_calculate_bitrate_hrd (GstVaH265Enc * self)
2504 {
2505   guint bitrate_bits, cpb_bits_size;
2506
2507   /* Round down bitrate. This is a hard limit mandated by the user */
2508   g_assert (SX_BITRATE >= 6);
2509   bitrate_bits = (self->rc.max_bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
2510   GST_DEBUG_OBJECT (self, "Max bitrate: %u bits/sec", bitrate_bits);
2511   self->rc.max_bitrate_bits = bitrate_bits;
2512
2513   bitrate_bits = (self->rc.target_bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
2514   GST_DEBUG_OBJECT (self, "Target bitrate: %u bits/sec", bitrate_bits);
2515   self->rc.target_bitrate_bits = bitrate_bits;
2516
2517   if (self->rc.cpb_size > 0 && self->rc.cpb_size < (self->rc.max_bitrate / 2)) {
2518     GST_INFO_OBJECT (self, "Too small cpb_size: %d", self->rc.cpb_size);
2519     self->rc.cpb_size = 0;
2520   }
2521
2522   if (self->rc.cpb_size == 0) {
2523     /* We cache 2 second coded data by default. */
2524     self->rc.cpb_size = self->rc.max_bitrate * 2;
2525     GST_INFO_OBJECT (self, "Adjust cpb_size to: %d", self->rc.cpb_size);
2526   }
2527
2528   /* Round up CPB size. This is an HRD compliance detail */
2529   g_assert (SX_CPB_SIZE >= 4);
2530   cpb_bits_size = (self->rc.cpb_size * 1000) & ~((1U << SX_CPB_SIZE) - 1);
2531
2532   GST_DEBUG_OBJECT (self, "HRD CPB size: %u bits", cpb_bits_size);
2533   self->rc.cpb_length_bits = cpb_bits_size;
2534 }
2535
2536 /* Estimates a good enough bitrate if none was supplied */
2537 static gboolean
2538 _h265_ensure_rate_control (GstVaH265Enc * self)
2539 {
2540   /* User can specify the properties of: "bitrate", "target-percentage",
2541    * "max-qp", "min-qp", "qpi", "qpp", "qpb", "mbbrc", "cpb-size",
2542    * "rate-control" and "target-usage" to control the RC behavior.
2543    *
2544    * "target-usage" is different from the others, it controls the encoding
2545    * speed and quality, while the others control encoding bit rate and
2546    * quality. The lower value has better quality(maybe bigger MV search
2547    * range) but slower speed, the higher value has faster speed but lower
2548    * quality.
2549    *
2550    * The possible composition to control the bit rate and quality:
2551    *
2552    * 1. CQP mode: "rate-control=cqp", then "qpi", "qpp" and "qpb"
2553    *    specify the QP of I/P/B frames respectively(within the
2554    *    "max-qp" and "min-qp" range). The QP will not change during
2555    *    the whole stream. Other properties are ignored.
2556    *
2557    * 2. CBR mode: "rate-control=CBR", then the "bitrate" specify the
2558    *    target bit rate and the "cpb-size" specifies the max coded
2559    *    picture buffer size to avoid overflow. If the "bitrate" is not
2560    *    set, it is calculated by the picture resolution and frame
2561    *    rate. If "cpb-size" is not set, it is set to the size of
2562    *    caching 2 second coded data. Encoder will try its best to make
2563    *    the QP with in the ["max-qp", "min-qp"] range. "mbbrc" can
2564    *    enable bit rate control in macro block level. Other paramters
2565    *    are ignored.
2566    *
2567    * 3. VBR mode: "rate-control=VBR", then the "bitrate" specify the
2568    *    target bit rate, "target-percentage" is used to calculate the
2569    *    max bit rate of VBR mode by ("bitrate" * 100) /
2570    *    "target-percentage". It is also used by driver to calculate
2571    *    the min bit rate. The "cpb-size" specifies the max coded
2572    *    picture buffer size to avoid overflow. If the "bitrate" is not
2573    *    set, the target bit rate will be calculated by the picture
2574    *    resolution and frame rate. Encoder will try its best to make
2575    *    the QP with in the ["max-qp", "min-qp"] range. "mbbrc" can
2576    *    enable bit rate control in macro block level. Other paramters
2577    *    are ignored.
2578    *
2579    * 4. VCM mode: "rate-control=VCM", then the "bitrate" specify the
2580    *    target bit rate, and encoder will try its best to make the QP
2581    *    with in the ["max-qp", "min-qp"] range. Other paramters are
2582    *    ignored.
2583    */
2584
2585   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2586   guint bitrate;
2587   guint32 rc_mode, quality_level, rc_ctrl;
2588
2589   quality_level = gst_va_encoder_get_quality_level (base->encoder,
2590       base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
2591   if (self->rc.target_usage > quality_level) {
2592     GST_INFO_OBJECT (self, "User setting target-usage: %d is not supported, "
2593         "fallback to %d", self->rc.target_usage, quality_level);
2594     self->rc.target_usage = quality_level;
2595     update_property_uint (base, &self->prop.target_usage,
2596         self->rc.target_usage, PROP_TARGET_USAGE);
2597   }
2598
2599   GST_OBJECT_LOCK (self);
2600   rc_ctrl = self->prop.rc_ctrl;
2601   GST_OBJECT_UNLOCK (self);
2602
2603   if (rc_ctrl != VA_RC_NONE) {
2604     rc_mode = gst_va_encoder_get_rate_control_mode (base->encoder,
2605         base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
2606     if (!(rc_mode & rc_ctrl)) {
2607       guint32 defval =
2608           G_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL])->default_value;
2609       GST_INFO_OBJECT (self, "The rate control mode %s is not supported, "
2610           "fallback to %s mode", _rate_control_get_name (rc_ctrl),
2611           _rate_control_get_name (defval));
2612       self->rc.rc_ctrl_mode = defval;
2613       update_property_uint (base, &self->prop.rc_ctrl,
2614           self->rc.rc_ctrl_mode, PROP_RATE_CONTROL);
2615     }
2616   } else {
2617     self->rc.rc_ctrl_mode = VA_RC_NONE;
2618   }
2619
2620   if (self->rc.min_qp > self->rc.max_qp) {
2621     GST_INFO_OBJECT (self, "The min_qp %d is bigger than the max_qp %d, "
2622         "set it to the max_qp", self->rc.min_qp, self->rc.max_qp);
2623     self->rc.min_qp = self->rc.max_qp;
2624
2625     update_property_uint (base, &self->prop.min_qp, self->rc.min_qp,
2626         PROP_MIN_QP);
2627   }
2628
2629   /* Make all the qp in the valid range */
2630   if (self->rc.qp_i < self->rc.min_qp) {
2631     if (self->rc.qp_i != 26)
2632       GST_INFO_OBJECT (self, "The qp_i %d is smaller than the min_qp %d, "
2633           "set it to the min_qp", self->rc.qp_i, self->rc.min_qp);
2634     self->rc.qp_i = self->rc.min_qp;
2635   }
2636   if (self->rc.qp_i > self->rc.max_qp) {
2637     if (self->rc.qp_i != 26)
2638       GST_INFO_OBJECT (self, "The qp_i %d is bigger than the max_qp %d, "
2639           "set it to the max_qp", self->rc.qp_i, self->rc.max_qp);
2640     self->rc.qp_i = self->rc.max_qp;
2641   }
2642
2643   if (self->rc.qp_p < self->rc.min_qp) {
2644     if (self->rc.qp_p != 26)
2645       GST_INFO_OBJECT (self, "The qp_p %d is smaller than the min_qp %d, "
2646           "set it to the min_qp", self->rc.qp_p, self->rc.min_qp);
2647     self->rc.qp_p = self->rc.min_qp;
2648   }
2649   if (self->rc.qp_p > self->rc.max_qp) {
2650     if (self->rc.qp_p != 26)
2651       GST_INFO_OBJECT (self, "The qp_p %d is bigger than the max_qp %d, "
2652           "set it to the max_qp", self->rc.qp_p, self->rc.max_qp);
2653     self->rc.qp_p = self->rc.max_qp;
2654   }
2655
2656   if (self->rc.qp_b < self->rc.min_qp) {
2657     if (self->rc.qp_b != 26)
2658       GST_INFO_OBJECT (self, "The qp_b %d is smaller than the min_qp %d, "
2659           "set it to the min_qp", self->rc.qp_b, self->rc.min_qp);
2660     self->rc.qp_b = self->rc.min_qp;
2661   }
2662   if (self->rc.qp_b > self->rc.max_qp) {
2663     if (self->rc.qp_b != 26)
2664       GST_INFO_OBJECT (self, "The qp_b %d is bigger than the max_qp %d, "
2665           "set it to the max_qp", self->rc.qp_b, self->rc.max_qp);
2666     self->rc.qp_b = self->rc.max_qp;
2667   }
2668
2669   GST_OBJECT_LOCK (self);
2670   bitrate = self->prop.bitrate;
2671   GST_OBJECT_UNLOCK (self);
2672
2673   /* Calculate a bitrate is not set. */
2674   if ((self->rc.rc_ctrl_mode == VA_RC_CBR || self->rc.rc_ctrl_mode == VA_RC_VBR
2675           || self->rc.rc_ctrl_mode == VA_RC_VCM) && bitrate == 0) {
2676     /* FIXME: Provide better estimation. */
2677     /* Just Using a 1/6 compression ratio, 12 bits per pixel for YUV420.
2678        TODO: Other video format. */
2679     guint64 factor;
2680
2681     factor = (guint64) self->luma_width * self->luma_height * 12 / 6;
2682     bitrate = gst_util_uint64_scale (factor,
2683         GST_VIDEO_INFO_FPS_N (&base->input_state->info),
2684         GST_VIDEO_INFO_FPS_D (&base->input_state->info)) / 1000;
2685
2686     GST_INFO_OBJECT (self, "target bitrate computed to %u kbps", bitrate);
2687   }
2688
2689   /* Adjust the setting based on RC mode. */
2690   switch (self->rc.rc_ctrl_mode) {
2691     case VA_RC_NONE:
2692     case VA_RC_CQP:
2693       self->rc.max_bitrate = 0;
2694       self->rc.target_bitrate = 0;
2695       self->rc.target_percentage = 0;
2696       self->rc.cpb_size = 0;
2697       break;
2698     case VA_RC_CBR:
2699       self->rc.max_bitrate = bitrate;
2700       self->rc.target_bitrate = bitrate;
2701       self->rc.target_percentage = 100;
2702       self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
2703       break;
2704     case VA_RC_VBR:
2705       g_assert (self->rc.target_percentage >= 10);
2706       self->rc.max_bitrate = (guint) gst_util_uint64_scale_int (bitrate,
2707           100, self->rc.target_percentage);
2708       self->rc.target_bitrate = bitrate;
2709       self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
2710       break;
2711     case VA_RC_VCM:
2712       self->rc.max_bitrate = bitrate;
2713       self->rc.target_bitrate = bitrate;
2714       self->rc.target_percentage = 0;
2715       self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
2716       self->rc.cpb_size = 0;
2717
2718       if (self->gop.num_bframes > 0) {
2719         GST_INFO_OBJECT (self, "VCM mode just support I/P mode, no B frame");
2720         self->gop.num_bframes = 0;
2721         self->gop.b_pyramid = FALSE;
2722       }
2723       break;
2724     default:
2725       GST_WARNING_OBJECT (self, "Unsupported rate control");
2726       return FALSE;
2727       break;
2728   }
2729
2730   GST_DEBUG_OBJECT (self, "Max bitrate: %u bits/sec, "
2731       "Target bitrate: %u bits/sec", self->rc.max_bitrate,
2732       self->rc.target_bitrate);
2733
2734   if (self->rc.rc_ctrl_mode != VA_RC_NONE && self->rc.rc_ctrl_mode != VA_RC_CQP)
2735     _h265_calculate_bitrate_hrd (self);
2736
2737   /* notifications */
2738   update_property_uint (base, &self->prop.min_qp, self->rc.min_qp, PROP_MIN_QP);
2739   update_property_uint (base, &self->prop.cpb_size,
2740       self->rc.cpb_size, PROP_CPB_SIZE);
2741   update_property_uint (base, &self->prop.target_percentage,
2742       self->rc.target_percentage, PROP_TARGET_PERCENTAGE);
2743   update_property_uint (base, &self->prop.qp_i, self->rc.qp_i, PROP_QP_I);
2744   update_property_uint (base, &self->prop.qp_p, self->rc.qp_p, PROP_QP_P);
2745   update_property_uint (base, &self->prop.qp_b, self->rc.qp_b, PROP_QP_B);
2746
2747   return TRUE;
2748 }
2749
2750 /* Derives the level and tier from the currently set limits */
2751 static gboolean
2752 _h265_calculate_tier_level (GstVaH265Enc * self)
2753 {
2754   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2755   guint i, PicSizeInSamplesY, LumaSr;
2756   guint32 tier_max_bitrate;
2757
2758   PicSizeInSamplesY = self->luma_width * self->luma_height;
2759   LumaSr = gst_util_uint64_scale_int_ceil (PicSizeInSamplesY,
2760       GST_VIDEO_INFO_FPS_N (&base->input_state->info),
2761       GST_VIDEO_INFO_FPS_D (&base->input_state->info));
2762
2763   for (i = 0; i < G_N_ELEMENTS (_va_h265_level_limits); i++) {
2764     const GstVaH265LevelLimits *const limits = &_va_h265_level_limits[i];
2765
2766     /* Choose level by luma picture size and luma sample rate */
2767     if (PicSizeInSamplesY <= limits->MaxLumaPs && LumaSr <= limits->MaxLumaSr)
2768       break;
2769   }
2770
2771   if (i == G_N_ELEMENTS (_va_h265_level_limits))
2772     goto error_unsupported_level;
2773
2774   self->level_idc = _va_h265_level_limits[i].level_idc;
2775   self->level_str = _va_h265_level_limits[i].level_name;
2776   self->min_cr = _va_h265_level_limits[i].MinCr;
2777
2778   if (self->rc.rc_ctrl_mode == VA_RC_CQP) {
2779     g_assert (self->rc.max_bitrate == 0);
2780
2781     /* We may need to calculate some max bit rate for CQP mode.
2782        Just set the main tier now. */
2783     self->tier_flag = FALSE;
2784   } else {
2785     if (_va_h265_level_limits[i].MaxBRTierHigh == 0 ||
2786         self->rc.max_bitrate <= _va_h265_level_limits[i].MaxBRTierMain) {
2787       self->tier_flag = FALSE;
2788     } else {
2789       self->tier_flag = TRUE;
2790     }
2791   }
2792
2793   tier_max_bitrate = self->tier_flag ? _va_h265_level_limits[i].MaxBRTierHigh :
2794       _va_h265_level_limits[i].MaxBRTierMain;
2795
2796   if (self->rc.max_bitrate > tier_max_bitrate) {
2797     GST_INFO_OBJECT (self, "The max bitrate of the stream is %u kbps, still"
2798         " larger than %s profile %s level %s tier's max bit rate %d kbps",
2799         self->rc.max_bitrate, gst_va_profile_name (base->profile),
2800         _va_h265_level_limits[i].level_name,
2801         (self->tier_flag ? "high" : "main"), tier_max_bitrate);
2802   }
2803
2804   GST_DEBUG_OBJECT (self, "profile: %s, level: %s, tier :%s, MinCr: %d",
2805       gst_va_profile_name (base->profile), _va_h265_level_limits[i].level_name,
2806       (self->tier_flag ? "high" : "main"), self->min_cr);
2807
2808   return TRUE;
2809
2810 error_unsupported_level:
2811   {
2812     GST_ERROR_OBJECT (self,
2813         "failed to find a suitable level matching codec config");
2814     return FALSE;
2815   }
2816 }
2817
2818 struct PyramidInfo
2819 {
2820   guint level;
2821   gint left_ref_poc_diff;
2822   gint right_ref_poc_diff;
2823 };
2824
2825 static void
2826 _set_pyramid_info (struct PyramidInfo *info, guint len,
2827     guint current_level, guint highest_level)
2828 {
2829   guint index;
2830
2831   g_assert (len >= 1);
2832
2833   if (current_level == highest_level || len == 1) {
2834     for (index = 0; index < len; index++) {
2835       info[index].level = current_level;
2836       info[index].left_ref_poc_diff = -(index + 1);
2837       info[index].right_ref_poc_diff = len - index;
2838     }
2839
2840     return;
2841   }
2842
2843   index = len / 2;
2844   info[index].level = current_level;
2845   info[index].left_ref_poc_diff = -(index + 1);
2846   info[index].right_ref_poc_diff = len - index;
2847
2848   current_level++;
2849
2850   if (index > 0)
2851     _set_pyramid_info (info, index, current_level, highest_level);
2852
2853   if (index + 1 < len)
2854     _set_pyramid_info (&info[index + 1], len - (index + 1),
2855         current_level, highest_level);
2856 }
2857
2858 static void
2859 _h265_create_gop_frame_types (GstVaH265Enc * self)
2860 {
2861   guint i;
2862   guint i_frames = self->gop.num_iframes;
2863   struct PyramidInfo pyramid_info[31] = { 0, };
2864
2865   if (self->gop.highest_pyramid_level > 0) {
2866     g_assert (self->gop.num_bframes > 0);
2867     _set_pyramid_info (pyramid_info, self->gop.num_bframes,
2868         0, self->gop.highest_pyramid_level);
2869   }
2870
2871   g_assert (self->gop.idr_period <= MAX_GOP_SIZE);
2872   for (i = 0; i < self->gop.idr_period; i++) {
2873     if (i == 0) {
2874       self->gop.frame_types[i].slice_type = GST_H265_I_SLICE;
2875       self->gop.frame_types[i].is_ref = TRUE;
2876       continue;
2877     }
2878
2879     /* Intra only stream. */
2880     if (self->gop.ip_period == 0) {
2881       self->gop.frame_types[i].slice_type = GST_H265_I_SLICE;
2882       self->gop.frame_types[i].is_ref = FALSE;
2883       continue;
2884     }
2885
2886     if (i % self->gop.ip_period) {
2887       guint pyramid_index =
2888           i % self->gop.ip_period - 1 /* The first P or IDR */ ;
2889
2890       self->gop.frame_types[i].slice_type = GST_H265_B_SLICE;
2891       self->gop.frame_types[i].pyramid_level =
2892           pyramid_info[pyramid_index].level;
2893       self->gop.frame_types[i].is_ref =
2894           (self->gop.frame_types[i].pyramid_level <
2895           self->gop.highest_pyramid_level);
2896       self->gop.frame_types[i].left_ref_poc_diff =
2897           pyramid_info[pyramid_index].left_ref_poc_diff;
2898       self->gop.frame_types[i].right_ref_poc_diff =
2899           pyramid_info[pyramid_index].right_ref_poc_diff;
2900       continue;
2901     }
2902
2903     if (self->gop.i_period && i % self->gop.i_period == 0 && i_frames > 0) {
2904       /* Replace P with I. */
2905       self->gop.frame_types[i].slice_type = GST_H265_I_SLICE;
2906       self->gop.frame_types[i].is_ref = TRUE;
2907       i_frames--;
2908       continue;
2909     }
2910
2911     self->gop.frame_types[i].slice_type = GST_H265_P_SLICE;
2912     self->gop.frame_types[i].is_ref = TRUE;
2913   }
2914
2915   /* Force the last one to be a P */
2916   if (self->gop.idr_period > 1 && self->gop.ip_period > 0) {
2917     self->gop.frame_types[self->gop.idr_period - 1].slice_type =
2918         GST_H265_P_SLICE;
2919     self->gop.frame_types[self->gop.idr_period - 1].is_ref = TRUE;
2920   }
2921 }
2922
2923 static void
2924 _h265_print_gop_structure (GstVaH265Enc * self)
2925 {
2926 #ifndef GST_DISABLE_GST_DEBUG
2927   GString *str;
2928   gint i;
2929
2930   if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) < GST_LEVEL_INFO)
2931     return;
2932
2933   str = g_string_new (NULL);
2934
2935   g_string_append_printf (str, "[ ");
2936
2937   for (i = 0; i < self->gop.idr_period; i++) {
2938     if (i == 0) {
2939       g_string_append_printf (str, "IDR");
2940       continue;
2941     } else {
2942       g_string_append_printf (str, ", ");
2943     }
2944
2945     g_string_append_printf (str, "%s",
2946         _h265_slice_type_name (self->gop.frame_types[i].slice_type));
2947
2948     if (self->gop.b_pyramid
2949         && self->gop.frame_types[i].slice_type == GST_H265_B_SLICE) {
2950       g_string_append_printf (str, "<L%d (%d, %d)>",
2951           self->gop.frame_types[i].pyramid_level,
2952           self->gop.frame_types[i].left_ref_poc_diff,
2953           self->gop.frame_types[i].right_ref_poc_diff);
2954     }
2955
2956     if (self->gop.frame_types[i].is_ref) {
2957       g_string_append_printf (str, "(ref)");
2958     }
2959
2960   }
2961
2962   g_string_append_printf (str, " ]");
2963
2964   GST_INFO_OBJECT (self, "GOP size: %d, forward reference %d, backward"
2965       " reference %d, GOP structure: %s", self->gop.idr_period,
2966       self->gop.forward_ref_num, self->gop.backward_ref_num, str->str);
2967
2968   g_string_free (str, TRUE);
2969 #endif
2970 }
2971
2972 static void
2973 _h265_calculate_coded_size (GstVaH265Enc * self)
2974 {
2975   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2976   /* FIXME: Using only a rough approximation for bitstream headers.
2977    * Not taken into account: ScalingList, RefPicListModification,
2978    * PredWeightTable, which is not used now. */
2979   /* Calculate the maximum sizes for common headers (in bits) */
2980   guint codedbuf_size = 0;
2981
2982   /* Account for VPS header */
2983   codedbuf_size += 4 /* start code */  + GST_ROUND_UP_8 (MAX_VPS_HDR_SIZE +
2984       MAX_PROFILE_TIER_LEVEL_SIZE + MAX_HRD_PARAMS_SIZE) / 8;
2985
2986   /* Account for SPS header */
2987   codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE +
2988       MAX_PROFILE_TIER_LEVEL_SIZE + 64 * MAX_SHORT_TERM_REFPICSET_SIZE +
2989       MAX_VUI_PARAMS_SIZE + MAX_HRD_PARAMS_SIZE) / 8;
2990
2991   /* Account for PPS header */
2992   codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8;
2993
2994   /* Account for slice header */
2995   codedbuf_size += self->num_slices * (4 +
2996       GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE + MAX_SHORT_TERM_REFPICSET_SIZE) / 8);
2997
2998   /* TODO: Only YUV 4:2:0 formats are supported for now.
2999      more video format to check. */
3000   codedbuf_size +=
3001       (self->luma_width * self->luma_height * 3 / 2) / self->min_cr;
3002
3003   base->codedbuf_size = codedbuf_size;
3004   GST_INFO_OBJECT (self, "Calculate codedbuf size: %u", base->codedbuf_size);
3005 }
3006
3007 /* Get log2_max_frame_num_minus4, log2_max_pic_order_cnt_lsb_minus4
3008  * value, shall be in the range of 0 to 12, inclusive. */
3009 static guint
3010 _get_log2_max_num (guint num)
3011 {
3012   guint ret = 0;
3013
3014   while (num) {
3015     ++ret;
3016     num >>= 1;
3017   }
3018
3019   /* shall be in the range of 0+4 to 12+4, inclusive. */
3020   if (ret < 4) {
3021     ret = 4;
3022   } else if (ret > 16) {
3023     ret = 16;
3024   }
3025   return ret;
3026 }
3027
3028 /* Consider the idr_period, num_bframes, L0/L1 reference number.
3029  * TODO: Load some preset fixed GOP structure.
3030  * TODO: Skip this if in lookahead mode. */
3031 static void
3032 _h265_generate_gop_structure (GstVaH265Enc * self)
3033 {
3034   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3035   guint32 log2_max_frame_num;
3036   guint32 list0, list1, forward_num, backward_num, gop_ref_num;
3037   gint32 p_frames;
3038
3039   /* If not set, generate a idr every second */
3040   if (self->gop.idr_period == 0) {
3041     self->gop.idr_period = (GST_VIDEO_INFO_FPS_N (&base->input_state->info)
3042         + GST_VIDEO_INFO_FPS_D (&base->input_state->info) - 1) /
3043         GST_VIDEO_INFO_FPS_D (&base->input_state->info);
3044   }
3045
3046   /* Do not use a too huge GOP size. */
3047   if (self->gop.idr_period > 1024) {
3048     self->gop.idr_period = 1024;
3049     GST_INFO_OBJECT (self, "Lowering the GOP size to %d", self->gop.idr_period);
3050   }
3051
3052   update_property_uint (base, &self->prop.key_int_max, self->gop.idr_period,
3053       PROP_KEY_INT_MAX);
3054
3055   /* Prefer have more than 1 refs for the GOP which is not very small. */
3056   if (self->gop.idr_period > 8) {
3057     if (self->gop.num_bframes > (self->gop.idr_period - 1) / 2) {
3058       self->gop.num_bframes = (self->gop.idr_period - 1) / 2;
3059       GST_INFO_OBJECT (self, "Lowering the number of num_bframes to %d",
3060           self->gop.num_bframes);
3061     }
3062   } else {
3063     /* beign and end should be ref */
3064     if (self->gop.num_bframes > self->gop.idr_period - 1 - 1) {
3065       if (self->gop.idr_period > 1) {
3066         self->gop.num_bframes = self->gop.idr_period - 1 - 1;
3067       } else {
3068         self->gop.num_bframes = 0;
3069       }
3070       GST_INFO_OBJECT (self, "Lowering the number of num_bframes to %d",
3071           self->gop.num_bframes);
3072     }
3073   }
3074
3075   if (!gst_va_encoder_get_max_num_reference (base->encoder, base->profile,
3076           GST_VA_BASE_ENC_ENTRYPOINT (base), &list0, &list1)) {
3077     GST_INFO_OBJECT (self, "Failed to get the max num reference");
3078     list0 = 1;
3079     list1 = 0;
3080   }
3081   self->gop.max_l0_num = list0;
3082   self->gop.max_l1_num = list1;
3083   GST_DEBUG_OBJECT (self, "list0 num: %d, list1 num: %d",
3084       self->gop.max_l0_num, self->gop.max_l1_num);
3085
3086   forward_num = list0;
3087   backward_num = list1;
3088   if (forward_num > self->gop.num_ref_frames)
3089     forward_num = self->gop.num_ref_frames;
3090   if (backward_num > self->gop.num_ref_frames)
3091     backward_num = self->gop.num_ref_frames;
3092
3093
3094   if (forward_num == 0) {
3095     GST_INFO_OBJECT (self,
3096         "No reference support, fallback to intra only stream");
3097
3098     /* It does not make sense that if only the list1 exists. */
3099     self->gop.num_ref_frames = 0;
3100
3101     self->gop.ip_period = 0;
3102     self->gop.num_bframes = 0;
3103     self->gop.b_pyramid = FALSE;
3104     self->gop.highest_pyramid_level = 0;
3105     self->gop.num_iframes = self->gop.idr_period - 1 /* The idr */ ;
3106     self->gop.forward_ref_num = 0;
3107     self->gop.backward_ref_num = 0;
3108     goto create_poc;
3109   }
3110
3111   if (self->gop.num_ref_frames <= 1) {
3112     GST_INFO_OBJECT (self, "The number of reference frames is only %d,"
3113         " no B frame allowed, fallback to I/P mode", self->gop.num_ref_frames);
3114     self->gop.num_bframes = 0;
3115     backward_num = 0;
3116   }
3117
3118   /* b_pyramid needs at least 1 ref for B, besides the I/P */
3119   if (self->gop.b_pyramid && self->gop.num_ref_frames <= 2) {
3120     GST_INFO_OBJECT (self, "The number of reference frames is only %d,"
3121         " not enough for b_pyramid", self->gop.num_ref_frames);
3122     self->gop.b_pyramid = FALSE;
3123   }
3124
3125   if (backward_num == 0 && self->gop.num_bframes > 0) {
3126     GST_INFO_OBJECT (self,
3127         "No hw reference support for list 1, fallback to I/P mode");
3128     self->gop.num_bframes = 0;
3129     self->gop.b_pyramid = FALSE;
3130   }
3131
3132   /* I/P mode, no list1 needed. */
3133   if (self->gop.num_bframes == 0)
3134     backward_num = 0;
3135
3136   /* Not enough B frame, no need for b_pyramid. */
3137   if (self->gop.num_bframes <= 1)
3138     self->gop.b_pyramid = FALSE;
3139
3140   if (self->gop.num_ref_frames > forward_num + backward_num) {
3141     self->gop.num_ref_frames = forward_num + backward_num;
3142     GST_INFO_OBJECT (self, "HW limits, lowering the number of reference"
3143         " frames to %d", self->gop.num_ref_frames);
3144   }
3145   self->gop.num_ref_frames = MIN (self->gop.num_ref_frames, 15);
3146
3147   /* How many possible refs within a GOP. */
3148   gop_ref_num = (self->gop.idr_period + self->gop.num_bframes) /
3149       (self->gop.num_bframes + 1);
3150   /* The end ref */
3151   if (self->gop.num_bframes > 0
3152       /* frame_num % (self->gop.num_bframes + 1) happens to be the end P */
3153       && (self->gop.idr_period % (self->gop.num_bframes + 1) != 1))
3154     gop_ref_num++;
3155
3156   /* Adjust reference num based on B frames and B pyramid. */
3157   if (self->gop.num_bframes == 0) {
3158     self->gop.b_pyramid = FALSE;
3159     self->gop.forward_ref_num = self->gop.num_ref_frames;
3160     self->gop.backward_ref_num = 0;
3161   } else if (self->gop.b_pyramid) {
3162     guint b_frames = self->gop.num_bframes;
3163     guint b_refs;
3164
3165     /* set b pyramid one backward ref. */
3166     self->gop.backward_ref_num = 1;
3167     self->gop.forward_ref_num =
3168         self->gop.num_ref_frames - self->gop.backward_ref_num;
3169     if (self->gop.forward_ref_num > forward_num)
3170       self->gop.forward_ref_num = forward_num;
3171
3172     /* Balance the forward and backward refs */
3173     if ((self->gop.forward_ref_num > self->gop.backward_ref_num * 3)
3174         && backward_num > 1) {
3175       self->gop.backward_ref_num++;
3176
3177       self->gop.forward_ref_num =
3178           self->gop.num_ref_frames - self->gop.backward_ref_num;
3179       if (self->gop.forward_ref_num > forward_num)
3180         self->gop.forward_ref_num = forward_num;
3181     }
3182
3183     b_frames = b_frames / 2;
3184     b_refs = 0;
3185     while (b_frames) {
3186       /* At least 1 B ref for each level, plus begin and end 2 P/I */
3187       b_refs += 1;
3188       if (b_refs + 2 > self->gop.num_ref_frames)
3189         break;
3190
3191       self->gop.highest_pyramid_level++;
3192       b_frames = b_frames / 2;
3193     }
3194
3195     GST_INFO_OBJECT (self, "pyramid level is %d",
3196         self->gop.highest_pyramid_level);
3197   } else {
3198     /* We prefer list0. Backward refs have more latency. */
3199     self->gop.backward_ref_num = 1;
3200     self->gop.forward_ref_num =
3201         self->gop.num_ref_frames - self->gop.backward_ref_num;
3202     /* Balance the forward and backward refs, but not cause a big latency. */
3203     while ((self->gop.num_bframes * self->gop.backward_ref_num <= 16)
3204         && (self->gop.backward_ref_num <= gop_ref_num)
3205         && (self->gop.backward_ref_num < backward_num)
3206         && (self->gop.forward_ref_num / self->gop.backward_ref_num > 4)) {
3207       self->gop.forward_ref_num--;
3208       self->gop.backward_ref_num++;
3209     }
3210
3211     if (self->gop.forward_ref_num > forward_num)
3212       self->gop.forward_ref_num = forward_num;
3213   }
3214
3215   /* It's OK, keep slots for GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME frame. */
3216   if (self->gop.forward_ref_num > gop_ref_num)
3217     GST_DEBUG_OBJECT (self, "num_ref_frames %d is bigger than gop_ref_num %d",
3218         self->gop.forward_ref_num, gop_ref_num);
3219
3220   /* Include the ref picture itself. */
3221   self->gop.ip_period = 1 + self->gop.num_bframes;
3222
3223   p_frames = gop_ref_num - 1 /* IDR */ ;
3224   if (p_frames < 0)
3225     p_frames = 0;
3226   if (self->gop.num_iframes > p_frames) {
3227     self->gop.num_iframes = p_frames;
3228     GST_INFO_OBJECT (self, "Too many I frames insertion, lowering it to %d",
3229         self->gop.num_iframes);
3230   }
3231
3232   if (self->gop.num_iframes > 0) {
3233     guint total_i_frames = self->gop.num_iframes + 1 /* IDR */ ;
3234     self->gop.i_period =
3235         (gop_ref_num / total_i_frames) * (self->gop.num_bframes + 1);
3236   }
3237
3238 create_poc:
3239   /* init max_frame_num, max_poc */
3240   log2_max_frame_num = _get_log2_max_num (self->gop.idr_period);
3241   self->gop.log2_max_pic_order_cnt = log2_max_frame_num;
3242   self->gop.max_pic_order_cnt = 1 << self->gop.log2_max_pic_order_cnt;
3243   self->gop.num_reorder_frames = self->gop.b_pyramid ?
3244       self->gop.highest_pyramid_level * 2 + 1 /* the last P frame. */ :
3245       self->gop.backward_ref_num;
3246   /* Should not exceed the max ref num. */
3247   self->gop.num_reorder_frames =
3248       MIN (self->gop.num_reorder_frames, self->gop.num_ref_frames);
3249   self->gop.num_reorder_frames = MIN (self->gop.num_reorder_frames, 16);
3250   self->gop.max_dpb_size = self->gop.num_ref_frames + 1;
3251
3252   _h265_create_gop_frame_types (self);
3253   _h265_print_gop_structure (self);
3254
3255   /* notifications */
3256   update_property_uint (base, &self->prop.num_ref_frames,
3257       self->gop.num_ref_frames, PROP_NUM_REF_FRAMES);
3258   update_property_uint (base, &self->prop.num_iframes,
3259       self->gop.num_iframes, PROP_IFRAMES);
3260   update_property_uint (base, &self->prop.num_bframes,
3261       self->gop.num_bframes, PROP_BFRAMES);
3262   update_property_bool (base, &self->prop.b_pyramid,
3263       self->gop.b_pyramid, PROP_B_PYRAMID);
3264 }
3265
3266 static gboolean
3267 _h265_init_packed_headers (GstVaH265Enc * self)
3268 {
3269   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3270   guint32 packed_headers;
3271   guint32 desired_packed_headers = VA_ENC_PACKED_HEADER_SEQUENCE        /* SPS */
3272       | VA_ENC_PACKED_HEADER_PICTURE    /* PPS */
3273       | VA_ENC_PACKED_HEADER_SLICE      /* Slice headers */
3274       | VA_ENC_PACKED_HEADER_RAW_DATA;  /* SEI, AUD, etc. */
3275
3276   self->packed_headers = 0;
3277
3278   if (!gst_va_encoder_get_packed_headers (base->encoder, base->profile,
3279           GST_VA_BASE_ENC_ENTRYPOINT (base), &packed_headers))
3280     return FALSE;
3281
3282   if (desired_packed_headers & ~packed_headers) {
3283     GST_INFO_OBJECT (self, "Driver does not support some wanted packed headers "
3284         "(wanted %#x, found %#x)", desired_packed_headers, packed_headers);
3285   }
3286
3287   self->packed_headers = desired_packed_headers & packed_headers;
3288
3289   return TRUE;
3290 }
3291
3292 static guint
3293 _get_chroma_format_idc (guint va_chroma)
3294 {
3295   guint chroma_format_idc;
3296
3297   switch (va_chroma) {
3298     case VA_RT_FORMAT_YUV400:
3299       chroma_format_idc = 0;
3300       break;
3301     case VA_RT_FORMAT_YUV420:
3302     case VA_RT_FORMAT_YUV420_10:
3303     case VA_RT_FORMAT_YUV420_12:
3304       chroma_format_idc = 1;
3305       break;
3306     case VA_RT_FORMAT_YUV422:
3307     case VA_RT_FORMAT_YUV422_10:
3308     case VA_RT_FORMAT_YUV422_12:
3309       chroma_format_idc = 2;
3310       break;
3311     case VA_RT_FORMAT_YUV444:
3312     case VA_RT_FORMAT_YUV444_10:
3313     case VA_RT_FORMAT_YUV444_12:
3314       chroma_format_idc = 3;
3315       break;
3316     default:
3317       GST_WARNING ("unsupported VA chroma value");
3318       chroma_format_idc = 1;
3319       break;
3320   }
3321
3322   return chroma_format_idc;
3323 }
3324
3325 static void
3326 _h265_init_mvp (GstVaH265Enc * self, gboolean enable)
3327 {
3328   if (enable) {
3329     /* For the simplicity, we only let MVP refer to List0[0],
3330        which is the last ref frame before the current frame. */
3331     self->features.temporal_mvp_enabled_flag = TRUE;
3332     self->features.collocated_from_l0_flag = TRUE;
3333     self->features.collocated_ref_idx = 0;
3334   } else {
3335     self->features.temporal_mvp_enabled_flag = FALSE;
3336     self->features.collocated_from_l0_flag = FALSE;
3337     self->features.collocated_ref_idx = 0xff;
3338   }
3339 }
3340
3341 /* We need to decide the profile and entrypoint before call this.
3342    It applies the optimized features provided by the va driver. */
3343 static void
3344 _h265_setup_encoding_features (GstVaH265Enc * self)
3345 {
3346   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3347
3348 #if VA_CHECK_VERSION(1, 13, 0)
3349   VAConfigAttribValEncHEVCFeatures features;
3350   VAStatus status;
3351   VAConfigAttrib attrib = {.type = VAConfigAttribEncHEVCFeatures };
3352
3353   status = vaGetConfigAttributes (gst_va_display_get_va_dpy (base->display),
3354       base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base), &attrib, 1);
3355   if (status != VA_STATUS_SUCCESS) {
3356     GST_INFO_OBJECT (self, "Failed to query encoding features: %s",
3357         vaErrorStr (status));
3358     goto default_options;
3359   }
3360
3361   if (attrib.value == VA_ATTRIB_NOT_SUPPORTED) {
3362     GST_INFO_OBJECT (self, "Driver does not support query encoding features");
3363     goto default_options;
3364   }
3365
3366   features.value = attrib.value;
3367
3368   /* We do not enable this no matter what the driver say. */
3369   self->features.separate_colour_plane_flag = FALSE;
3370   self->features.colour_plane_id = 0;
3371
3372   /* We do not enable scaling_list now. */
3373   self->features.scaling_list_enabled_flag = FALSE;
3374   self->features.scaling_list_data_present_flag = FALSE;
3375
3376   self->features.amp_enabled_flag = (features.bits.amp != 0);
3377
3378   self->features.sample_adaptive_offset_enabled_flag = (features.bits.sao != 0);
3379   self->features.slice_sao_luma_flag = (features.bits.sao != 0);
3380   self->features.slice_sao_chroma_flag = (features.bits.sao != 0);
3381
3382   self->features.pcm_enabled_flag = (features.bits.pcm != 0);
3383   if (!self->features.pcm_enabled_flag) {
3384     self->features.pcm_sample_bit_depth_luma_minus1 = 0;
3385     self->features.pcm_sample_bit_depth_chroma_minus1 = 0;
3386     self->features.log2_min_pcm_luma_coding_block_size_minus3 = 0;
3387     self->features.log2_max_pcm_luma_coding_block_size_minus3 = 0;
3388   } else {
3389     self->features.pcm_sample_bit_depth_luma_minus1 =
3390         self->bits_depth_luma_minus8 + 8 - 1;
3391     self->features.pcm_sample_bit_depth_chroma_minus1 =
3392         self->bits_depth_chroma_minus8 + 8 - 1;
3393     /* log2_min_pcm_luma_coding_block_size_minus3 and
3394        log2_diff_max_min_pcm_luma_coding_block_size set
3395        in coding_block_size */
3396   }
3397   self->features.pcm_loop_filter_disabled_flag = FALSE;
3398
3399   _h265_init_mvp (self, features.bits.temporal_mvp != 0);
3400
3401   self->features.strong_intra_smoothing_enabled_flag =
3402       (features.bits.strong_intra_smoothing != 0);
3403
3404   /* TODO: dependent slice */
3405   self->features.dependent_slice_segment_flag = FALSE;
3406
3407   self->features.sign_data_hiding_enabled_flag =
3408       (features.bits.sign_data_hiding != 0);
3409
3410   self->features.constrained_intra_pred_flag =
3411       (features.bits.constrained_intra_pred != 0);
3412
3413   self->features.transform_skip_enabled_flag =
3414       (features.bits.transform_skip != 0);
3415
3416   self->features.cu_qp_delta_enabled_flag =
3417       (self->rc.rc_ctrl_mode != VA_RC_CQP);
3418   self->features.diff_cu_qp_delta_depth = features.bits.cu_qp_delta;
3419
3420   /* TODO: use weighted pred */
3421   self->features.weighted_pred_flag = FALSE;
3422   self->features.weighted_bipred_flag = FALSE;
3423
3424   self->features.transquant_bypass_enabled_flag =
3425       (features.bits.transquant_bypass != 0);
3426   goto print_options;
3427
3428 default_options:
3429 #endif
3430
3431   GST_DEBUG_OBJECT (self, "Apply default setting for features");
3432
3433   self->features.separate_colour_plane_flag = FALSE;
3434   self->features.colour_plane_id = 0;
3435   self->features.scaling_list_enabled_flag = FALSE;
3436   self->features.scaling_list_data_present_flag = FALSE;
3437   self->features.amp_enabled_flag = TRUE;
3438   self->features.sample_adaptive_offset_enabled_flag = FALSE;
3439   self->features.slice_sao_luma_flag = FALSE;
3440   self->features.slice_sao_chroma_flag = FALSE;
3441   self->features.pcm_enabled_flag = 0;
3442   self->features.pcm_sample_bit_depth_luma_minus1 = 0;
3443   self->features.pcm_sample_bit_depth_chroma_minus1 = 0;
3444   self->features.log2_min_pcm_luma_coding_block_size_minus3 = 0;
3445   self->features.log2_max_pcm_luma_coding_block_size_minus3 = 0;
3446   self->features.pcm_loop_filter_disabled_flag = FALSE;
3447   _h265_init_mvp (self, TRUE);
3448   self->features.strong_intra_smoothing_enabled_flag = TRUE;
3449   self->features.dependent_slice_segment_flag = FALSE;
3450   self->features.sign_data_hiding_enabled_flag = FALSE;
3451   self->features.constrained_intra_pred_flag = FALSE;
3452   self->features.transform_skip_enabled_flag = TRUE;
3453   self->features.cu_qp_delta_enabled_flag =
3454       (self->rc.rc_ctrl_mode != VA_RC_CQP);
3455   self->features.diff_cu_qp_delta_depth = 0;
3456   self->features.weighted_pred_flag = FALSE;
3457   self->features.weighted_bipred_flag = FALSE;
3458   self->features.transquant_bypass_enabled_flag = FALSE;
3459
3460 #if VA_CHECK_VERSION(1, 13, 0)
3461 print_options:
3462 #endif
3463   GST_DEBUG_OBJECT (self, "Set features to: "
3464       "separate_colour_plane_flag = %d, "
3465       "colour_plane_id = %d, "
3466       "scaling_list_enabled_flag = %d, "
3467       "scaling_list_data_present_flag = %d, "
3468       "amp_enabled_flag = %d, "
3469       "sample_adaptive_offset_enabled_flag = %d, "
3470       "slice_sao_luma_flag = %d, "
3471       "slice_sao_chroma_flag = %d, "
3472       "pcm_enabled_flag = %d, "
3473       "pcm_sample_bit_depth_luma_minus1 = %d, "
3474       "pcm_sample_bit_depth_chroma_minus1 = %d, "
3475       "log2_min_pcm_luma_coding_block_size_minus3 = %d, "
3476       "log2_max_pcm_luma_coding_block_size_minus3 = %d, "
3477       "pcm_loop_filter_disabled_flag = %d, "
3478       "temporal_mvp_enabled_flag = %d, "
3479       "collocated_from_l0_flag = %d, "
3480       "collocated_ref_idx = %d, "
3481       "strong_intra_smoothing_enabled_flag = %d, "
3482       "dependent_slice_segment_flag = %d, "
3483       "sign_data_hiding_enabled_flag = %d, "
3484       "constrained_intra_pred_flag = %d, "
3485       "transform_skip_enabled_flag = %d, "
3486       "cu_qp_delta_enabled_flag = %d, "
3487       "diff_cu_qp_delta_depth = %d, "
3488       "weighted_pred_flag = %d, "
3489       "weighted_bipred_flag = %d, "
3490       "transquant_bypass_enabled_flag = %d",
3491       self->features.separate_colour_plane_flag,
3492       self->features.colour_plane_id,
3493       self->features.scaling_list_enabled_flag,
3494       self->features.scaling_list_data_present_flag,
3495       self->features.amp_enabled_flag,
3496       self->features.sample_adaptive_offset_enabled_flag,
3497       self->features.slice_sao_luma_flag,
3498       self->features.slice_sao_chroma_flag,
3499       self->features.pcm_enabled_flag,
3500       self->features.pcm_sample_bit_depth_luma_minus1,
3501       self->features.pcm_sample_bit_depth_chroma_minus1,
3502       self->features.log2_min_pcm_luma_coding_block_size_minus3,
3503       self->features.log2_max_pcm_luma_coding_block_size_minus3,
3504       self->features.pcm_loop_filter_disabled_flag,
3505       self->features.temporal_mvp_enabled_flag,
3506       self->features.collocated_from_l0_flag,
3507       self->features.collocated_ref_idx,
3508       self->features.strong_intra_smoothing_enabled_flag,
3509       self->features.dependent_slice_segment_flag,
3510       self->features.sign_data_hiding_enabled_flag,
3511       self->features.constrained_intra_pred_flag,
3512       self->features.transform_skip_enabled_flag,
3513       self->features.cu_qp_delta_enabled_flag,
3514       self->features.diff_cu_qp_delta_depth,
3515       self->features.weighted_pred_flag,
3516       self->features.weighted_bipred_flag,
3517       self->features.transquant_bypass_enabled_flag);
3518 }
3519
3520 /* We need to decide the profile and entrypoint before call this.
3521    It applies the optimized block size(coding and tranform) provided
3522    by the va driver. */
3523 static void
3524 _h265_set_coding_block_size (GstVaH265Enc * self)
3525 {
3526 #if VA_CHECK_VERSION(1, 13, 0)
3527   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3528
3529   VAConfigAttribValEncHEVCBlockSizes block_size;
3530   VAStatus status;
3531   VAConfigAttrib attrib = {.type = VAConfigAttribEncHEVCBlockSizes };
3532
3533   status = vaGetConfigAttributes (gst_va_display_get_va_dpy (base->display),
3534       base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base), &attrib, 1);
3535   if (status != VA_STATUS_SUCCESS) {
3536     GST_INFO_OBJECT (self, "Failed to query coding block size: %s",
3537         vaErrorStr (status));
3538     goto default_setting;
3539   }
3540
3541   if (attrib.value == VA_ATTRIB_NOT_SUPPORTED) {
3542     GST_INFO_OBJECT (self, "Driver does not support query"
3543         " coding block size");
3544     goto default_setting;
3545   }
3546
3547   block_size.value = attrib.value;
3548
3549   /* We always choose the biggest coding block size and the biggest
3550      hierarchy depth to achieve the best compression result.
3551      TODO: May choose smaller value when fast encoding is needed. */
3552
3553   if (block_size.bits.log2_min_luma_coding_block_size_minus3 >
3554       block_size.bits.log2_max_coding_tree_block_size_minus3) {
3555     GST_WARNING_OBJECT (self, "Invalid log2_min_luma_coding_block_size_minus3:"
3556         " %d, bigger than log2_max_coding_tree_block_size_minus3: %d",
3557         block_size.bits.log2_min_luma_coding_block_size_minus3,
3558         block_size.bits.log2_max_coding_tree_block_size_minus3);
3559     goto default_setting;
3560   }
3561   if (block_size.bits.log2_min_luma_coding_block_size_minus3 >
3562       block_size.bits.log2_min_coding_tree_block_size_minus3) {
3563     GST_WARNING_OBJECT (self, "Invalid log2_min_luma_coding_block_size_minus3:"
3564         " %d, bigger than log2_min_coding_tree_block_size_minus3: %d",
3565         block_size.bits.log2_min_luma_coding_block_size_minus3,
3566         block_size.bits.log2_min_coding_tree_block_size_minus3);
3567     block_size.bits.log2_min_coding_tree_block_size_minus3 =
3568         block_size.bits.log2_min_luma_coding_block_size_minus3;
3569   }
3570
3571   self->ctu_size =
3572       1 << (block_size.bits.log2_max_coding_tree_block_size_minus3 + 3);
3573   self->min_coding_block_size =
3574       1 << (block_size.bits.log2_min_luma_coding_block_size_minus3 + 3);
3575   self->features.log2_min_luma_coding_block_size_minus3 =
3576       block_size.bits.log2_min_luma_coding_block_size_minus3;
3577   self->features.log2_diff_max_min_luma_coding_block_size =
3578       block_size.bits.log2_max_coding_tree_block_size_minus3 -
3579       block_size.bits.log2_min_luma_coding_block_size_minus3;
3580
3581   if (block_size.bits.log2_min_luma_transform_block_size_minus2 >
3582       block_size.bits.log2_max_luma_transform_block_size_minus2) {
3583     GST_WARNING_OBJECT (self, "Invalid"
3584         " log2_min_luma_transform_block_size_minus2: %d, bigger"
3585         " than log2_max_luma_transform_block_size_minus2: %d",
3586         block_size.bits.log2_min_luma_transform_block_size_minus2,
3587         block_size.bits.log2_max_luma_transform_block_size_minus2);
3588     goto default_setting;
3589   }
3590   self->features.log2_min_transform_block_size_minus2 =
3591       block_size.bits.log2_min_luma_transform_block_size_minus2;
3592   self->features.log2_diff_max_min_transform_block_size =
3593       block_size.bits.log2_max_luma_transform_block_size_minus2 -
3594       block_size.bits.log2_min_luma_transform_block_size_minus2;
3595
3596   self->features.max_transform_hierarchy_depth_inter =
3597       block_size.bits.max_max_transform_hierarchy_depth_inter;
3598   self->features.max_transform_hierarchy_depth_intra =
3599       block_size.bits.max_max_transform_hierarchy_depth_intra;
3600
3601   /* For PCM setting later. */
3602   self->features.log2_min_pcm_luma_coding_block_size_minus3 =
3603       block_size.bits.log2_min_pcm_coding_block_size_minus3;
3604   self->features.log2_max_pcm_luma_coding_block_size_minus3 =
3605       block_size.bits.log2_max_pcm_coding_block_size_minus3;
3606
3607   if (self->features.log2_max_pcm_luma_coding_block_size_minus3 -
3608       self->features.log2_min_pcm_luma_coding_block_size_minus3 >
3609       self->features.log2_diff_max_min_luma_coding_block_size) {
3610     GST_WARNING_OBJECT (self, "Invalid"
3611         " log2_diff_max_min_pcm_luma_coding_block_size: %d",
3612         self->features.log2_max_pcm_luma_coding_block_size_minus3
3613         - self->features.log2_min_pcm_luma_coding_block_size_minus3);
3614     self->features.log2_max_pcm_luma_coding_block_size_minus3 = 0;
3615     self->features.log2_min_pcm_luma_coding_block_size_minus3 = 0;
3616   }
3617
3618   goto done;
3619
3620 default_setting:
3621 #endif
3622
3623   GST_DEBUG_OBJECT (self, "Apply default setting for coding block");
3624
3625   /* choose some conservative value */
3626   self->ctu_size = 32;
3627   self->min_coding_block_size = 8;
3628   self->features.log2_min_luma_coding_block_size_minus3 = 0;
3629   self->features.log2_diff_max_min_luma_coding_block_size = 2;
3630
3631   self->features.log2_min_transform_block_size_minus2 = 0;
3632   self->features.log2_diff_max_min_transform_block_size = 3;
3633   self->features.max_transform_hierarchy_depth_inter = 2;
3634   self->features.max_transform_hierarchy_depth_intra = 2;
3635   self->features.pcm_sample_bit_depth_luma_minus1 = 0;
3636   self->features.pcm_sample_bit_depth_chroma_minus1 = 0;
3637   /* Default PCM is disabled. */
3638   self->features.log2_min_pcm_luma_coding_block_size_minus3 = 0;
3639   self->features.log2_max_pcm_luma_coding_block_size_minus3 = 0;
3640
3641 #if VA_CHECK_VERSION(1, 13, 0)
3642 done:
3643 #endif
3644   GST_DEBUG_OBJECT (self, "Set coding block size to: "
3645       "log2_min_luma_coding_block_size_minus3: %d, "
3646       "log2_diff_max_min_luma_coding_block_size: %d, "
3647       "log2_min_transform_block_size_minus2: %d, "
3648       "log2_diff_max_min_transform_block_size: %d, "
3649       "max_transform_hierarchy_depth_inter: %d, "
3650       "max_transform_hierarchy_depth_intra: %d",
3651       self->features.log2_min_luma_coding_block_size_minus3,
3652       self->features.log2_diff_max_min_luma_coding_block_size,
3653       self->features.log2_min_transform_block_size_minus2,
3654       self->features.log2_diff_max_min_transform_block_size,
3655       self->features.max_transform_hierarchy_depth_inter,
3656       self->features.max_transform_hierarchy_depth_intra);
3657 }
3658
3659 static gboolean
3660 gst_va_h265_enc_reconfig (GstVaBaseEnc * base)
3661 {
3662   GstVideoEncoder *venc = GST_VIDEO_ENCODER (base);
3663   GstVaH265Enc *self = GST_VA_H265_ENC (base);
3664   GstCaps *out_caps, *reconf_caps = NULL;;
3665   GstVideoCodecState *output_state = NULL;
3666   GstVideoFormat format, reconf_format = GST_VIDEO_FORMAT_UNKNOWN;
3667   VAProfile profile = VAProfileNone;
3668   gboolean do_renegotiation = TRUE, do_reopen, need_negotiation;
3669   guint max_ref_frames, max_surfaces = 0, rt_format = 0, codedbuf_size;
3670   gint width, height;
3671
3672   width = GST_VIDEO_INFO_WIDTH (&base->input_state->info);
3673   height = GST_VIDEO_INFO_HEIGHT (&base->input_state->info);
3674   format = GST_VIDEO_INFO_FORMAT (&base->input_state->info);
3675   codedbuf_size = base->codedbuf_size;
3676
3677   need_negotiation =
3678       !gst_va_encoder_get_reconstruct_pool_config (base->encoder, &reconf_caps,
3679       &max_surfaces);
3680   if (!need_negotiation && reconf_caps) {
3681     GstVideoInfo vi;
3682     if (!gst_video_info_from_caps (&vi, reconf_caps))
3683       return FALSE;
3684     reconf_format = GST_VIDEO_INFO_FORMAT (&vi);
3685   }
3686
3687   if (!_h265_decide_profile (self, &profile, &rt_format))
3688     return FALSE;
3689
3690   /* first check */
3691   do_reopen = !(base->profile == profile && base->rt_format == rt_format
3692       && format == reconf_format && width == base->width
3693       && height == base->height && self->prop.rc_ctrl == self->rc.rc_ctrl_mode);
3694
3695   if (do_reopen && gst_va_encoder_is_open (base->encoder))
3696     gst_va_encoder_close (base->encoder);
3697
3698   gst_va_base_enc_reset_state (base);
3699
3700   base->profile = profile;
3701   base->rt_format = rt_format;
3702   base->width = width;
3703   base->height = height;
3704
3705   self->luma_width = GST_ROUND_UP_16 (base->width);
3706   self->luma_height = GST_ROUND_UP_16 (base->height);
3707
3708   /* Frame Cropping */
3709   if ((base->width & 15) || (base->height & 15)) {
3710     /* 6.1, Table 6-1 */
3711     static const guint SubWidthC[] = { 1, 2, 2, 1 };
3712     static const guint SubHeightC[] = { 1, 2, 1, 1 };
3713     guint index = _get_chroma_format_idc (gst_va_chroma_from_video_format
3714         (GST_VIDEO_INFO_FORMAT (&base->input_state->info)));
3715
3716     self->conformance_window_flag = 1;
3717     self->conf_win_left_offset = 0;
3718     self->conf_win_right_offset =
3719         (self->luma_width - base->width) / SubWidthC[index];
3720     self->conf_win_top_offset = 0;
3721     self->conf_win_bottom_offset =
3722         (self->luma_height - base->height) / SubHeightC[index];
3723   }
3724
3725   _h265_set_coding_block_size (self);
3726
3727   self->ctu_width = (self->luma_width + self->ctu_size - 1) / self->ctu_size;
3728   self->ctu_height = (self->luma_height + self->ctu_size - 1) / self->ctu_size;
3729   if (self->ctu_width == 0 || self->ctu_height == 0)
3730     return FALSE;
3731
3732   self->bits_depth_luma_minus8 =
3733       GST_VIDEO_FORMAT_INFO_DEPTH (base->input_state->info.finfo, 0);
3734   self->bits_depth_luma_minus8 -= 8;
3735
3736   if (GST_VIDEO_FORMAT_INFO_N_COMPONENTS (base->input_state->info.finfo)) {
3737     self->bits_depth_chroma_minus8 =
3738         GST_VIDEO_FORMAT_INFO_DEPTH (base->input_state->info.finfo, 1);
3739     if (self->bits_depth_chroma_minus8 <
3740         GST_VIDEO_FORMAT_INFO_DEPTH (base->input_state->info.finfo, 2))
3741       self->bits_depth_chroma_minus8 =
3742           GST_VIDEO_FORMAT_INFO_DEPTH (base->input_state->info.finfo, 2);
3743
3744     self->bits_depth_chroma_minus8 -= 8;
3745   } else {
3746     self->bits_depth_chroma_minus8 = 0;
3747   }
3748
3749   /* Frame rate is needed for rate control and PTS setting. */
3750   if (GST_VIDEO_INFO_FPS_N (&base->input_state->info) == 0
3751       || GST_VIDEO_INFO_FPS_D (&base->input_state->info) == 0) {
3752     GST_INFO_OBJECT (self, "Unknown framerate, just set to 30 fps");
3753     GST_VIDEO_INFO_FPS_N (&base->input_state->info) = 30;
3754     GST_VIDEO_INFO_FPS_D (&base->input_state->info) = 1;
3755   }
3756   base->frame_duration = gst_util_uint64_scale (GST_SECOND,
3757       GST_VIDEO_INFO_FPS_D (&base->input_state->info),
3758       GST_VIDEO_INFO_FPS_N (&base->input_state->info));
3759
3760   GST_DEBUG_OBJECT (self, "resolution:%dx%d, CTU size: %dx%d,"
3761       " frame duration is %" GST_TIME_FORMAT,
3762       base->width, base->height, self->ctu_width, self->ctu_height,
3763       GST_TIME_ARGS (base->frame_duration));
3764
3765   _h265_validate_parameters (self);
3766
3767   if (!_h265_ensure_rate_control (self))
3768     return FALSE;
3769
3770   if (!_h265_calculate_tier_level (self))
3771     return FALSE;
3772
3773   _h265_generate_gop_structure (self);
3774
3775   _h265_setup_encoding_features (self);
3776
3777   _h265_calculate_coded_size (self);
3778
3779   if (!_h265_init_packed_headers (self))
3780     return FALSE;
3781
3782   self->aud = self->aud && self->packed_headers & VA_ENC_PACKED_HEADER_RAW_DATA;
3783   update_property_bool (base, &self->prop.aud, self->aud, PROP_AUD);
3784
3785   max_ref_frames = self->gop.num_ref_frames + 3 /* scratch frames */ ;
3786
3787   /* second check after calculations */
3788   do_reopen |=
3789       !(max_ref_frames == max_surfaces && codedbuf_size == base->codedbuf_size);
3790   if (do_reopen && gst_va_encoder_is_open (base->encoder))
3791     gst_va_encoder_close (base->encoder);
3792
3793   if (!gst_va_encoder_is_open (base->encoder)
3794       && !gst_va_encoder_open (base->encoder, base->profile,
3795           format, base->rt_format, self->luma_width, self->luma_height,
3796           base->codedbuf_size, max_ref_frames, self->rc.rc_ctrl_mode,
3797           self->packed_headers)) {
3798     GST_ERROR_OBJECT (self, "Failed to open the VA encoder.");
3799     return FALSE;
3800   }
3801
3802   /* Add some tags */
3803   gst_va_base_enc_add_codec_tag (base, "H265");
3804
3805   out_caps = gst_va_profile_caps (base->profile);
3806   g_assert (out_caps);
3807   out_caps = gst_caps_fixate (out_caps);
3808
3809   if (self->level_str)
3810     gst_caps_set_simple (out_caps, "level", G_TYPE_STRING, self->level_str,
3811         NULL);
3812
3813   gst_caps_set_simple (out_caps, "width", G_TYPE_INT, base->width,
3814       "height", G_TYPE_INT, base->height, "alignment", G_TYPE_STRING, "au",
3815       "stream-format", G_TYPE_STRING, "byte-stream", NULL);
3816
3817   if (!need_negotiation) {
3818     output_state = gst_video_encoder_get_output_state (venc);
3819     do_renegotiation = TRUE;
3820
3821     if (output_state) {
3822       do_renegotiation = !gst_caps_is_subset (output_state->caps, out_caps);
3823       gst_video_codec_state_unref (output_state);
3824     }
3825
3826     if (!do_renegotiation) {
3827       gst_caps_unref (out_caps);
3828       return TRUE;
3829     }
3830   }
3831
3832   GST_DEBUG_OBJECT (self, "output caps is %" GST_PTR_FORMAT, out_caps);
3833
3834   output_state =
3835       gst_video_encoder_set_output_state (venc, out_caps, base->input_state);
3836   gst_video_codec_state_unref (output_state);
3837
3838   if (!gst_video_encoder_negotiate (venc)) {
3839     GST_ERROR_OBJECT (self, "Failed to negotiate with the downstream");
3840     return FALSE;
3841   }
3842
3843   return TRUE;
3844 }
3845
3846 static gboolean
3847 gst_va_h265_enc_flush (GstVideoEncoder * venc)
3848 {
3849   GstVaH265Enc *self = GST_VA_H265_ENC (venc);
3850
3851   /* begin from an IDR after flush. */
3852   self->gop.cur_frame_index = 0;
3853
3854   return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (venc);
3855 }
3856
3857 static gboolean
3858 gst_va_h265_enc_new_frame (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
3859 {
3860   GstVaH265EncFrame *frame_in;
3861
3862   frame_in = gst_va_h265_enc_frame_new ();
3863   frame_in->total_frame_count = base->input_frame_count++;
3864   gst_video_codec_frame_set_user_data (frame, frame_in,
3865       gst_va_h265_enc_frame_free);
3866
3867   return TRUE;
3868 }
3869
3870 static void
3871 gst_va_h265_enc_prepare_output (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
3872 {
3873   GstVaH265Enc *self = GST_VA_H265_ENC (base);
3874   GstVaH265EncFrame *frame_enc;
3875
3876   frame_enc = _enc_frame (frame);
3877
3878   frame->pts =
3879       base->start_pts + base->frame_duration * frame_enc->total_frame_count;
3880   /* The PTS should always be later than the DTS. */
3881   frame->dts = base->start_pts + base->frame_duration *
3882       ((gint64) base->output_frame_count -
3883       (gint64) self->gop.num_reorder_frames);
3884   base->output_frame_count++;
3885   frame->duration = base->frame_duration;
3886 }
3887
3888 /* *INDENT-OFF* */
3889 static const gchar *sink_caps_str =
3890     GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_VA,
3891         "{ NV12 }") " ;"
3892     GST_VIDEO_CAPS_MAKE ("{ NV12 }");
3893 /* *INDENT-ON* */
3894
3895 static const gchar *src_caps_str = "video/x-h265";
3896
3897 static gpointer
3898 _register_debug_category (gpointer data)
3899 {
3900   GST_DEBUG_CATEGORY_INIT (gst_va_h265enc_debug, "vah265enc", 0,
3901       "VA h265 encoder");
3902
3903   return NULL;
3904 }
3905
3906 static void
3907 gst_va_h265_enc_init (GTypeInstance * instance, gpointer g_class)
3908 {
3909   GstVaH265Enc *self = GST_VA_H265_ENC (instance);
3910
3911   /* default values */
3912   self->prop.key_int_max = 0;
3913   self->prop.num_bframes = 0;
3914   self->prop.num_iframes = 0;
3915   self->prop.num_ref_frames = 3;
3916   self->prop.b_pyramid = FALSE;
3917   self->prop.num_slices = 1;
3918   self->prop.min_qp = 1;
3919   self->prop.max_qp = 51;
3920   self->prop.qp_i = 26;
3921   self->prop.qp_p = 26;
3922   self->prop.qp_b = 26;
3923   self->prop.use_trellis = FALSE;
3924   self->prop.aud = FALSE;
3925   self->prop.mbbrc = 0;
3926   self->prop.bitrate = 0;
3927   self->prop.target_percentage = 66;
3928   self->prop.target_usage = 4;
3929   self->prop.cpb_size = 0;
3930   if (properties[PROP_RATE_CONTROL]) {
3931     self->prop.rc_ctrl =
3932         G_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL])->default_value;
3933   } else {
3934     self->prop.rc_ctrl = VA_RC_NONE;
3935   }
3936 }
3937
3938 static void
3939 gst_va_h265_enc_set_property (GObject * object, guint prop_id,
3940     const GValue * value, GParamSpec * pspec)
3941 {
3942   GstVaH265Enc *const self = GST_VA_H265_ENC (object);
3943   GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3944   gboolean already_effect = FALSE;
3945
3946   GST_OBJECT_LOCK (self);
3947
3948   switch (prop_id) {
3949     case PROP_KEY_INT_MAX:
3950       self->prop.key_int_max = g_value_get_uint (value);
3951       break;
3952     case PROP_BFRAMES:
3953       self->prop.num_bframes = g_value_get_uint (value);
3954       break;
3955     case PROP_IFRAMES:
3956       self->prop.num_iframes = g_value_get_uint (value);
3957       break;
3958     case PROP_NUM_REF_FRAMES:
3959       self->prop.num_ref_frames = g_value_get_uint (value);
3960       break;
3961     case PROP_B_PYRAMID:
3962       self->prop.b_pyramid = g_value_get_boolean (value);
3963       break;
3964     case PROP_NUM_SLICES:
3965       self->prop.num_slices = g_value_get_uint (value);
3966       break;
3967     case PROP_MIN_QP:
3968       self->prop.min_qp = g_value_get_uint (value);
3969       break;
3970     case PROP_MAX_QP:
3971       self->prop.max_qp = g_value_get_uint (value);
3972       break;
3973     case PROP_QP_I:
3974       self->prop.qp_i = g_value_get_uint (value);
3975       g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3976       already_effect = TRUE;
3977       break;
3978     case PROP_QP_P:
3979       self->prop.qp_p = g_value_get_uint (value);
3980       g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3981       already_effect = TRUE;
3982       break;
3983     case PROP_QP_B:
3984       self->prop.qp_b = g_value_get_uint (value);
3985       g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
3986       already_effect = TRUE;
3987       break;
3988     case PROP_TRELLIS:
3989       self->prop.use_trellis = g_value_get_boolean (value);
3990       break;
3991     case PROP_AUD:
3992       self->prop.aud = g_value_get_boolean (value);
3993       break;
3994     case PROP_MBBRC:{
3995       /* Macroblock-level rate control.
3996        * 0: use default,
3997        * 1: always enable,
3998        * 2: always disable,
3999        * other: reserved. */
4000       switch (g_value_get_enum (value)) {
4001         case GST_VA_FEATURE_DISABLED:
4002           self->prop.mbbrc = 2;
4003           break;
4004         case GST_VA_FEATURE_ENABLED:
4005           self->prop.mbbrc = 1;
4006           break;
4007         case GST_VA_FEATURE_AUTO:
4008           self->prop.mbbrc = 0;
4009           break;
4010       }
4011       break;
4012     }
4013     case PROP_BITRATE:
4014       self->prop.bitrate = g_value_get_uint (value);
4015       g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4016       already_effect = TRUE;
4017       break;
4018     case PROP_TARGET_PERCENTAGE:
4019       self->prop.target_percentage = g_value_get_uint (value);
4020       g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4021       already_effect = TRUE;
4022       break;
4023     case PROP_TARGET_USAGE:
4024       self->prop.target_usage = g_value_get_uint (value);
4025       g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4026       already_effect = TRUE;
4027       break;
4028     case PROP_RATE_CONTROL:
4029       self->prop.rc_ctrl = g_value_get_enum (value);
4030       g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4031       already_effect = TRUE;
4032       break;
4033     case PROP_CPB_SIZE:
4034       self->prop.cpb_size = g_value_get_uint (value);
4035       break;
4036     default:
4037       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4038   }
4039
4040   GST_OBJECT_UNLOCK (self);
4041
4042 #ifndef GST_DISABLE_GST_DEBUG
4043   if (!already_effect &&
4044       base->encoder && gst_va_encoder_is_open (base->encoder)) {
4045     GST_WARNING_OBJECT (self, "Property `%s` change ignored while processing.",
4046         pspec->name);
4047   }
4048 #endif
4049 }
4050
4051 static void
4052 gst_va_h265_enc_get_property (GObject * object, guint prop_id,
4053     GValue * value, GParamSpec * pspec)
4054 {
4055   GstVaH265Enc *const self = GST_VA_H265_ENC (object);
4056
4057   GST_OBJECT_LOCK (self);
4058
4059   switch (prop_id) {
4060     case PROP_KEY_INT_MAX:
4061       g_value_set_uint (value, self->prop.key_int_max);
4062       break;
4063     case PROP_BFRAMES:
4064       g_value_set_uint (value, self->prop.num_bframes);
4065       break;
4066     case PROP_IFRAMES:
4067       g_value_set_uint (value, self->prop.num_iframes);
4068       break;
4069     case PROP_NUM_REF_FRAMES:
4070       g_value_set_uint (value, self->prop.num_ref_frames);
4071       break;
4072     case PROP_B_PYRAMID:
4073       g_value_set_boolean (value, self->prop.b_pyramid);
4074       break;
4075     case PROP_NUM_SLICES:
4076       g_value_set_uint (value, self->prop.num_slices);
4077       break;
4078     case PROP_MIN_QP:
4079       g_value_set_uint (value, self->prop.min_qp);
4080       break;
4081     case PROP_MAX_QP:
4082       g_value_set_uint (value, self->prop.max_qp);
4083       break;
4084     case PROP_QP_I:
4085       g_value_set_uint (value, self->prop.qp_i);
4086       break;
4087     case PROP_QP_P:
4088       g_value_set_uint (value, self->prop.qp_p);
4089       break;
4090     case PROP_QP_B:
4091       g_value_set_uint (value, self->prop.qp_b);
4092       break;
4093     case PROP_TRELLIS:
4094       g_value_set_boolean (value, self->prop.use_trellis);
4095       break;
4096     case PROP_AUD:
4097       g_value_set_boolean (value, self->prop.aud);
4098       break;
4099     case PROP_MBBRC:
4100       g_value_set_enum (value, self->prop.mbbrc);
4101       break;
4102     case PROP_BITRATE:
4103       g_value_set_uint (value, self->prop.bitrate);
4104       break;
4105     case PROP_TARGET_PERCENTAGE:
4106       g_value_set_uint (value, self->prop.target_percentage);
4107       break;
4108     case PROP_TARGET_USAGE:
4109       g_value_set_uint (value, self->prop.target_usage);
4110       break;
4111     case PROP_RATE_CONTROL:
4112       g_value_set_enum (value, self->prop.rc_ctrl);
4113       break;
4114     case PROP_CPB_SIZE:
4115       g_value_set_uint (value, self->prop.cpb_size);
4116       break;
4117     default:
4118       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4119   }
4120
4121   GST_OBJECT_UNLOCK (self);
4122 }
4123
4124 static void
4125 gst_va_h265_enc_class_init (gpointer g_klass, gpointer class_data)
4126 {
4127   GstCaps *src_doc_caps, *sink_doc_caps;
4128   GstPadTemplate *sink_pad_templ, *src_pad_templ;
4129   GObjectClass *object_class = G_OBJECT_CLASS (g_klass);
4130   GstElementClass *element_class = GST_ELEMENT_CLASS (g_klass);
4131   GstVideoEncoderClass *venc_class = GST_VIDEO_ENCODER_CLASS (g_klass);
4132   GstVaBaseEncClass *va_enc_class = GST_VA_BASE_ENC_CLASS (g_klass);
4133   GstVaH265EncClass *vah265enc_class = GST_VA_H265_ENC_CLASS (g_klass);
4134   GstVaDisplay *display;
4135   GstVaEncoder *encoder;
4136   struct CData *cdata = class_data;
4137   gchar *long_name;
4138   gint n_props = N_PROPERTIES;
4139   GParamFlags param_flags =
4140       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT;
4141
4142   if (cdata->description) {
4143     long_name = g_strdup_printf ("VA-API H.265 Encoder in %s",
4144         cdata->description);
4145   } else {
4146     long_name = g_strdup ("VA-API H.265 Encoder");
4147   }
4148
4149   gst_element_class_set_metadata (element_class, long_name,
4150       "Codec/Encoder/Video/Hardware", "VA-API based H.265 video encoder",
4151       "He Junyan <junyan.he@intel.com>");
4152
4153   sink_doc_caps = gst_caps_from_string (sink_caps_str);
4154   src_doc_caps = gst_caps_from_string (src_caps_str);
4155
4156   parent_class = g_type_class_peek_parent (g_klass);
4157
4158   va_enc_class->codec = HEVC;
4159   va_enc_class->entrypoint = cdata->entrypoint;
4160   va_enc_class->render_device_path = g_strdup (cdata->render_device_path);
4161
4162   sink_pad_templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
4163       cdata->sink_caps);
4164   gst_element_class_add_pad_template (element_class, sink_pad_templ);
4165
4166   gst_pad_template_set_documentation_caps (sink_pad_templ, sink_doc_caps);
4167   gst_caps_unref (sink_doc_caps);
4168
4169   src_pad_templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
4170       cdata->src_caps);
4171   gst_element_class_add_pad_template (element_class, src_pad_templ);
4172
4173   gst_pad_template_set_documentation_caps (src_pad_templ, src_doc_caps);
4174   gst_caps_unref (src_doc_caps);
4175
4176   object_class->set_property = gst_va_h265_enc_set_property;
4177   object_class->get_property = gst_va_h265_enc_get_property;
4178
4179   venc_class->flush = GST_DEBUG_FUNCPTR (gst_va_h265_enc_flush);
4180
4181   va_enc_class->reset_state = GST_DEBUG_FUNCPTR (gst_va_h265_enc_reset_state);
4182   va_enc_class->reconfig = GST_DEBUG_FUNCPTR (gst_va_h265_enc_reconfig);
4183   va_enc_class->new_frame = GST_DEBUG_FUNCPTR (gst_va_h265_enc_new_frame);
4184   va_enc_class->reorder_frame =
4185       GST_DEBUG_FUNCPTR (gst_va_h265_enc_reorder_frame);
4186   va_enc_class->encode_frame = GST_DEBUG_FUNCPTR (gst_va_h265_enc_encode_frame);
4187   va_enc_class->prepare_output =
4188       GST_DEBUG_FUNCPTR (gst_va_h265_enc_prepare_output);
4189
4190   {
4191     display =
4192         gst_va_display_drm_new_from_path (va_enc_class->render_device_path);
4193     encoder = gst_va_encoder_new (display, va_enc_class->codec,
4194         va_enc_class->entrypoint);
4195     if (gst_va_encoder_get_rate_control_enum (encoder,
4196             vah265enc_class->rate_control)) {
4197       g_snprintf (vah265enc_class->rate_control_type_name,
4198           G_N_ELEMENTS (vah265enc_class->rate_control_type_name) - 1,
4199           "GstVaEncoderRateControl_%" GST_FOURCC_FORMAT "%s_%s",
4200           GST_FOURCC_ARGS (va_enc_class->codec),
4201           (va_enc_class->entrypoint == VAEntrypointEncSliceLP) ? "_LP" : "",
4202           g_path_get_basename (va_enc_class->render_device_path));
4203       vah265enc_class->rate_control_type =
4204           g_enum_register_static (vah265enc_class->rate_control_type_name,
4205           vah265enc_class->rate_control);
4206       gst_type_mark_as_plugin_api (vah265enc_class->rate_control_type, 0);
4207     }
4208     gst_object_unref (encoder);
4209     gst_object_unref (display);
4210   }
4211
4212   g_free (long_name);
4213   g_free (cdata->description);
4214   g_free (cdata->render_device_path);
4215   gst_caps_unref (cdata->src_caps);
4216   gst_caps_unref (cdata->sink_caps);
4217   g_free (cdata);
4218
4219   /**
4220    * GstVaH265Enc:key-int-max:
4221    *
4222    * The maximal distance between two keyframes.
4223    */
4224   properties[PROP_KEY_INT_MAX] = g_param_spec_uint ("key-int-max",
4225       "Key frame maximal interval",
4226       "The maximal distance between two keyframes. It decides the size of GOP"
4227       " (0: auto-calculate)", 0, MAX_GOP_SIZE, 0, param_flags);
4228
4229   /**
4230    * GstVaH265Enc:b-frames:
4231    *
4232    * Number of B-frames between two reference frames.
4233    */
4234   properties[PROP_BFRAMES] = g_param_spec_uint ("b-frames", "B Frames",
4235       "Number of B frames between I and P reference frames", 0, 31, 0,
4236       param_flags);
4237
4238   /**
4239    * GstVaH265Enc:i-frames:
4240    *
4241    * Force the number of i-frames insertion within one GOP.
4242    */
4243   properties[PROP_IFRAMES] = g_param_spec_uint ("i-frames", "I Frames",
4244       "Force the number of I frames insertion within one GOP, not including the "
4245       "first IDR frame", 0, 1023, 0, param_flags);
4246
4247   /* The VA only define 15 refs */
4248   /**
4249    * GstVaH265Enc:ref-frames:
4250    *
4251    * The number of reference frames.
4252    */
4253   properties[PROP_NUM_REF_FRAMES] = g_param_spec_uint ("ref-frames",
4254       "Number of Reference Frames",
4255       "Number of reference frames, including both the forward and the backward",
4256       0, 15, 3, param_flags);
4257
4258   /**
4259    * GstVaH265Enc:b-pyramid:
4260    *
4261    * Enable the b-pyramid reference structure in GOP.
4262    */
4263   properties[PROP_B_PYRAMID] = g_param_spec_boolean ("b-pyramid", "b pyramid",
4264       "Enable the b-pyramid reference structure in the GOP", FALSE,
4265       param_flags);
4266
4267   /**
4268    * GstVaH265Enc:num-slices:
4269    *
4270    * The number of slices per frame.
4271    */
4272   properties[PROP_NUM_SLICES] = g_param_spec_uint ("num-slices",
4273       "Number of Slices", "Number of slices per frame", 1, 200, 1, param_flags);
4274
4275   /**
4276    * GstVaH265Enc:max-qp:
4277    *
4278    * The maximum quantizer value.
4279    */
4280   properties[PROP_MAX_QP] = g_param_spec_uint ("max-qp", "Maximum QP",
4281       "Maximum quantizer value for each frame", 0, 51, 51, param_flags);
4282
4283   /**
4284    * GstVaH265Enc:min-qp:
4285    *
4286    * The minimum quantizer value.
4287    */
4288   properties[PROP_MIN_QP] = g_param_spec_uint ("min-qp", "Minimum QP",
4289       "Minimum quantizer value for each frame", 0, 51, 1, param_flags);
4290
4291   /**
4292    * GstVaH265Enc:qpi:
4293    *
4294    * The quantizer value for I frame. In CQP mode, it specifies the QP of
4295    * I frame, in other mode, it specifies the init QP of all frames.
4296    */
4297   properties[PROP_QP_I] = g_param_spec_uint ("qpi", "I Frame QP",
4298       "The quantizer value for I frame. In CQP mode, it specifies the QP of I "
4299       "frame, in other mode, it specifies the init QP of all frames", 0, 51, 26,
4300       param_flags | GST_PARAM_MUTABLE_PLAYING);
4301
4302   /**
4303    * GstVaH265Enc:qpp:
4304    *
4305    * The quantizer value for P frame. This is available only in CQP mode.
4306    */
4307   properties[PROP_QP_P] = g_param_spec_uint ("qpp",
4308       "The quantizer value for P frame",
4309       "The quantizer value for P frame. This is available only in CQP mode",
4310       0, 51, 26, param_flags | GST_PARAM_MUTABLE_PLAYING);
4311
4312   /**
4313    * GstVaH265Enc:qpb:
4314    *
4315    * The quantizer value for B frame. This is available only in CQP mode.
4316    */
4317   properties[PROP_QP_B] = g_param_spec_uint ("qpb",
4318       "The quantizer value for B frame",
4319       "The quantizer value for B frame. This is available only in CQP mode",
4320       0, 51, 26, param_flags | GST_PARAM_MUTABLE_PLAYING);
4321
4322   /**
4323    * GstVaH265Enc:trellis:
4324    *
4325    * It enable the trellis quantization method.
4326    * Trellis is an improved quantization algorithm.
4327    */
4328   properties[PROP_TRELLIS] = g_param_spec_boolean ("trellis", "Enable trellis",
4329       "Enable the trellis quantization method", FALSE, param_flags);
4330
4331   /**
4332    * GstVaH265Enc:aud:
4333    *
4334    * Insert the AU (Access Unit) delimeter for each frame.
4335    */
4336   properties[PROP_AUD] = g_param_spec_boolean ("aud", "Insert AUD",
4337       "Insert AU (Access Unit) delimeter for each frame", FALSE, param_flags);
4338
4339   /**
4340    * GstVaH265Enc:mbbrc:
4341    *
4342    * Macroblock level bitrate control.
4343    * This is not compatible with Constant QP rate control.
4344    */
4345   properties[PROP_MBBRC] = g_param_spec_enum ("mbbrc",
4346       "Macroblock level Bitrate Control",
4347       "Macroblock level Bitrate Control. It is not compatible with CQP",
4348       GST_TYPE_VA_FEATURE, GST_VA_FEATURE_AUTO, param_flags);
4349
4350   /**
4351    * GstVaH265Enc:bitrate:
4352    *
4353    * The desired target bitrate, expressed in kbps.
4354    * This is not available in CQP mode.
4355    *
4356    * CBR: This applies equally to the minimum, maximum and target bitrate.
4357    * VBR: This applies to the target bitrate. The driver will use the
4358    * "target-percentage" together to calculate the minimum and maximum bitrate.
4359    * VCM: This applies to the target bitrate. The minimum and maximum bitrate
4360    * are not needed.
4361    */
4362   properties[PROP_BITRATE] = g_param_spec_uint ("bitrate", "Bitrate (kbps)",
4363       "The desired bitrate expressed in kbps (0: auto-calculate)",
4364       0, 2000 * 1024, 0, param_flags | GST_PARAM_MUTABLE_PLAYING);
4365
4366   /**
4367    * GstVaH265Enc:target-percentage:
4368    *
4369    * The target percentage of the max bitrate, and expressed in uint,
4370    * equal to "target percentage"*100.
4371    * "target percentage" = "target bitrate" * 100 / "max bitrate"
4372    * This is available only when rate-control is VBR.
4373    * The driver uses it to calculate the minimum and maximum bitrate.
4374    */
4375   properties[PROP_TARGET_PERCENTAGE] = g_param_spec_uint ("target-percentage",
4376       "target bitrate percentage",
4377       "The percentage for 'target bitrate'/'maximum bitrate' (Only in VBR)",
4378       50, 100, 66, param_flags | GST_PARAM_MUTABLE_PLAYING);
4379
4380   /**
4381    * GstVaH265Enc:target-usage:
4382    *
4383    * The target usage of the encoder. It controls and balances the encoding
4384    * speed and the encoding quality. The lower value has better quality but
4385    * slower speed, the higher value has faster speed but lower quality.
4386    */
4387   properties[PROP_TARGET_USAGE] = g_param_spec_uint ("target-usage",
4388       "target usage",
4389       "The target usage to control and balance the encoding speed/quality",
4390       1, 7, 4, param_flags | GST_PARAM_MUTABLE_PLAYING);
4391
4392   /**
4393    * GstVaH265Enc:cpb-size:
4394    *
4395    * The desired max CPB size in Kb (0: auto-calculate).
4396    */
4397   properties[PROP_CPB_SIZE] = g_param_spec_uint ("cpb-size",
4398       "max CPB size in Kb",
4399       "The desired max CPB size in Kb (0: auto-calculate)", 0, 2000 * 1024, 0,
4400       param_flags);
4401
4402   if (vah265enc_class->rate_control_type > 0) {
4403     properties[PROP_RATE_CONTROL] = g_param_spec_enum ("rate-control",
4404         "rate control mode", "The desired rate control mode for the encoder",
4405         vah265enc_class->rate_control_type,
4406         vah265enc_class->rate_control[0].value,
4407         GST_PARAM_CONDITIONALLY_AVAILABLE | GST_PARAM_MUTABLE_PLAYING
4408         | param_flags);
4409   } else {
4410     n_props--;
4411     properties[PROP_RATE_CONTROL] = NULL;
4412   }
4413
4414   g_object_class_install_properties (object_class, n_props, properties);
4415
4416   /**
4417    * GstVaFeature:
4418    * @GST_VA_FEATURE_DISABLED: The feature is disabled.
4419    * @GST_VA_FEATURE_ENABLED: The feature is enabled.
4420    * @GST_VA_FEATURE_AUTO: The feature is enabled automatically.
4421    *
4422    * Since: 1.22
4423    */
4424   gst_type_mark_as_plugin_api (GST_TYPE_VA_FEATURE, 0);
4425 }
4426
4427 static GstCaps *
4428 _complete_src_caps (GstCaps * srccaps)
4429 {
4430   GstCaps *caps = gst_caps_copy (srccaps);
4431   GValue val = G_VALUE_INIT;
4432
4433   g_value_init (&val, G_TYPE_STRING);
4434   g_value_set_string (&val, "au");
4435   gst_caps_set_value (caps, "alignment", &val);
4436   g_value_unset (&val);
4437
4438   g_value_init (&val, G_TYPE_STRING);
4439   g_value_set_string (&val, "byte-stream");
4440   gst_caps_set_value (caps, "stream-format", &val);
4441   g_value_unset (&val);
4442
4443   return caps;
4444 }
4445
4446 gboolean
4447 gst_va_h265_enc_register (GstPlugin * plugin, GstVaDevice * device,
4448     GstCaps * sink_caps, GstCaps * src_caps, guint rank,
4449     VAEntrypoint entrypoint)
4450 {
4451   static GOnce debug_once = G_ONCE_INIT;
4452   GType type;
4453   GTypeInfo type_info = {
4454     .class_size = sizeof (GstVaH265EncClass),
4455     .class_init = gst_va_h265_enc_class_init,
4456     .instance_size = sizeof (GstVaH265Enc),
4457     .instance_init = gst_va_h265_enc_init,
4458   };
4459   struct CData *cdata;
4460   gboolean ret;
4461   gchar *type_name, *feature_name;
4462
4463   g_return_val_if_fail (GST_IS_PLUGIN (plugin), FALSE);
4464   g_return_val_if_fail (GST_IS_VA_DEVICE (device), FALSE);
4465   g_return_val_if_fail (GST_IS_CAPS (sink_caps), FALSE);
4466   g_return_val_if_fail (GST_IS_CAPS (src_caps), FALSE);
4467   g_return_val_if_fail (entrypoint == VAEntrypointEncSlice ||
4468       entrypoint == VAEntrypointEncSliceLP, FALSE);
4469
4470   if (entrypoint == VAEntrypointEncSliceLP) {
4471     GST_WARNING ("low power H265 encoder is not supported now.");
4472     return FALSE;
4473   }
4474
4475   cdata = g_new (struct CData, 1);
4476   cdata->entrypoint = entrypoint;
4477   cdata->description = NULL;
4478   cdata->render_device_path = g_strdup (device->render_device_path);
4479   cdata->sink_caps = gst_caps_ref (sink_caps);
4480   cdata->src_caps = _complete_src_caps (src_caps);
4481
4482   /* class data will be leaked if the element never gets instantiated */
4483   GST_MINI_OBJECT_FLAG_SET (cdata->sink_caps,
4484       GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
4485   GST_MINI_OBJECT_FLAG_SET (cdata->src_caps,
4486       GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
4487
4488   type_info.class_data = cdata;
4489   type_name = g_strdup ("GstVaH265Enc");
4490   feature_name = g_strdup ("vah265enc");
4491
4492   /* The first encoder to be registered should use a constant name,
4493    * like vah265enc, for any additional encoders, we create unique
4494    * names, using inserting the render device name. */
4495   if (g_type_from_name (type_name)) {
4496     gchar *basename = g_path_get_basename (device->render_device_path);
4497     g_free (type_name);
4498     g_free (feature_name);
4499     type_name = g_strdup_printf ("GstVa%sH265Enc", basename);
4500     feature_name = g_strdup_printf ("va%sh265enc", basename);
4501     cdata->description = basename;
4502     /* lower rank for non-first device */
4503     if (rank > 0)
4504       rank--;
4505   }
4506
4507   g_once (&debug_once, _register_debug_category, NULL);
4508   type = g_type_register_static (GST_TYPE_VA_BASE_ENC,
4509       type_name, &type_info, 0);
4510   ret = gst_element_register (plugin, feature_name, rank, type);
4511
4512   g_free (type_name);
4513   g_free (feature_name);
4514
4515   return ret;
4516 }