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