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