libs: encoder: h265: add multi reference support
[platform/upstream/gstreamer.git] / gst-libs / gst / vaapi / gstvaapiencoder_h265.c
1 /*
2  *  gstvaapiencoder_h265.c - H.265 encoder
3  *
4  *  Copyright (C) 2015 Intel Corporation
5  *    Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public License
9  *  as published by the Free Software Foundation; either version 2.1
10  *  of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free
19  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  *  Boston, MA 02110-1301 USA
21  */
22
23 #include "sysdeps.h"
24 #include <math.h>
25 #include <gst/base/gstbitwriter.h>
26 #include <gst/codecparsers/gsth265parser.h>
27 #include "gstvaapicompat.h"
28 #include "gstvaapiencoder_priv.h"
29 #include "gstvaapiencoder_h265.h"
30 #include "gstvaapiutils_h265.h"
31 #include "gstvaapiutils_h265_priv.h"
32 #include "gstvaapiutils_h26x_priv.h"
33 #include "gstvaapicodedbufferproxy_priv.h"
34 #include "gstvaapisurface.h"
35
36 #define DEBUG 1
37 #include "gstvaapidebug.h"
38
39 /* Supported set of VA rate controls, within this implementation */
40 #define SUPPORTED_RATECONTROLS                          \
41   (GST_VAAPI_RATECONTROL_MASK (CQP) |                   \
42    GST_VAAPI_RATECONTROL_MASK (CBR) |                   \
43    GST_VAAPI_RATECONTROL_MASK (VBR))
44
45 /* Supported set of tuning options, within this implementation */
46 #define SUPPORTED_TUNE_OPTIONS                          \
47   (GST_VAAPI_ENCODER_TUNE_MASK (NONE))
48
49 /* Supported set of VA packed headers, within this implementation */
50 #define SUPPORTED_PACKED_HEADERS                \
51   (VA_ENC_PACKED_HEADER_SEQUENCE |              \
52    VA_ENC_PACKED_HEADER_PICTURE  |              \
53    VA_ENC_PACKED_HEADER_SLICE)
54
55 typedef struct
56 {
57   GstVaapiSurfaceProxy *pic;
58   guint poc;
59 } GstVaapiEncoderH265Ref;
60
61 typedef enum
62 {
63   GST_VAAPI_ENC_H265_REORD_NONE = 0,
64   GST_VAAPI_ENC_H265_REORD_DUMP_FRAMES = 1,
65   GST_VAAPI_ENC_H265_REORD_WAIT_FRAMES = 2
66 } GstVaapiEncH265ReorderState;
67
68 typedef struct _GstVaapiH265RefPool
69 {
70   GQueue ref_list;
71   guint max_ref_frames;
72   guint max_reflist0_count;
73   guint max_reflist1_count;
74 } GstVaapiH265RefPool;
75
76 typedef struct _GstVaapiH265ReorderPool
77 {
78   GQueue reorder_frame_list;
79   guint reorder_state;
80   guint frame_index;
81   guint cur_present_index;
82 } GstVaapiH265ReorderPool;
83
84 /* ------------------------------------------------------------------------- */
85 /* --- H.265 Encoder                                                     --- */
86 /* ------------------------------------------------------------------------- */
87
88 struct _GstVaapiEncoderH265
89 {
90   GstVaapiEncoder parent_instance;
91
92   GstVaapiProfile profile;
93   GstVaapiTierH265 tier;
94   GstVaapiLevelH265 level;
95   guint8 profile_idc;
96   guint8 max_profile_idc;
97   guint8 hw_max_profile_idc;
98   guint8 level_idc;
99   guint32 idr_period;
100   guint32 init_qp;
101   guint32 min_qp;
102   guint32 num_slices;
103   guint32 num_bframes;
104   guint32 ctu_width;            /* CTU == Coding Tree Unit */
105   guint32 ctu_height;
106   guint32 luma_width;
107   guint32 luma_height;
108   GstClockTime cts_offset;
109   gboolean config_changed;
110
111   /* maximum required size of the decoded picture buffer */
112   guint32 max_dec_pic_buffering;
113   /* maximum allowed number of pictures that can precede any picture in
114    * the CVS in decoding order and follow that picture in output order */
115   guint32 max_num_reorder_pics;
116
117   /* frame, poc */
118   guint32 max_pic_order_cnt;
119   guint32 log2_max_pic_order_cnt;
120   guint32 idr_num;
121   guint num_ref_frames;
122
123   GstBuffer *vps_data;
124   GstBuffer *sps_data;
125   GstBuffer *pps_data;
126
127   guint bitrate_bits;           // bitrate (bits)
128   guint cpb_length;             // length of CPB buffer (ms)
129   guint cpb_length_bits;        // length of CPB buffer (bits)
130
131   /* Crop rectangle */
132   guint conformance_window_flag:1;
133   guint32 conf_win_left_offset;
134   guint32 conf_win_right_offset;
135   guint32 conf_win_top_offset;
136   guint32 conf_win_bottom_offset;
137
138   GstVaapiH265RefPool ref_pool;
139   GstVaapiH265ReorderPool reorder_pool;
140   guint first_slice_segment_in_pic_flag:1;
141   guint sps_temporal_mvp_enabled_flag:1;
142   guint sample_adaptive_offset_enabled_flag:1;
143 };
144
145 static inline gboolean
146 _poc_greater_than (guint poc1, guint poc2, guint max_poc)
147 {
148   return (((poc1 - poc2) & (max_poc - 1)) < max_poc / 2);
149 }
150
151 /* Get slice_type value for H.265 specification */
152 static guint8
153 h265_get_slice_type (GstVaapiPictureType type)
154 {
155   switch (type) {
156     case GST_VAAPI_PICTURE_TYPE_I:
157       return GST_H265_I_SLICE;
158     case GST_VAAPI_PICTURE_TYPE_P:
159       return GST_H265_P_SLICE;
160     case GST_VAAPI_PICTURE_TYPE_B:
161       return GST_H265_B_SLICE;
162     default:
163       break;
164   }
165   return -1;
166 }
167
168 /* Get log2_max_pic_order_cnt value for H.265 specification */
169 static guint
170 h265_get_log2_max_pic_order_cnt (guint num)
171 {
172   guint ret = 0;
173
174   while (num) {
175     ++ret;
176     num >>= 1;
177   }
178   if (ret <= 4)
179     ret = 4;
180   else if (ret > 10)
181     ret = 10;
182   /* must be greater than 4 */
183   return ret;
184 }
185
186 /* Write the NAL unit header */
187 static gboolean
188 bs_write_nal_header (GstBitWriter * bs, guint32 nal_unit_type)
189 {
190   guint8 nuh_layer_id = 0;
191   guint8 nuh_temporal_id_plus1 = 1;
192
193   WRITE_UINT32 (bs, 0, 1);
194   WRITE_UINT32 (bs, nal_unit_type, 6);
195   WRITE_UINT32 (bs, nuh_layer_id, 6);
196   WRITE_UINT32 (bs, nuh_temporal_id_plus1, 3);
197
198   return TRUE;
199
200   /* ERRORS */
201 bs_error:
202   {
203     GST_WARNING ("failed to write NAL unit header");
204     return FALSE;
205   }
206 }
207
208 /* Write the NAL unit trailing bits */
209 static gboolean
210 bs_write_trailing_bits (GstBitWriter * bs)
211 {
212   if (!gst_bit_writer_put_bits_uint32 (bs, 1, 1))
213     goto bs_error;
214   gst_bit_writer_align_bytes_unchecked (bs, 0);
215   return TRUE;
216
217   /* ERRORS */
218 bs_error:
219   {
220     GST_WARNING ("failed to write NAL unit trailing bits");
221     return FALSE;
222   }
223 }
224
225 /* Write profile_tier_level()  */
226 static gboolean
227 bs_write_profile_tier_level (GstBitWriter * bs,
228     const VAEncSequenceParameterBufferHEVC * seq_param)
229 {
230   guint i;
231   /* general_profile_space */
232   WRITE_UINT32 (bs, 0, 2);
233   /* general_tier_flag */
234   WRITE_UINT32 (bs, seq_param->general_tier_flag, 1);
235   /* general_profile_idc */
236   WRITE_UINT32 (bs, seq_param->general_profile_idc, 5);
237   /* general_profile_compatibility_flag[32] */
238   for (i = 0; i < 32; i++) {
239     if (i == 1 || i == 2)
240       WRITE_UINT32 (bs, 1, 1);
241     else
242       WRITE_UINT32 (bs, 0, 1);
243   }
244   /* general_progressive_source_flag */
245   WRITE_UINT32 (bs, 1, 1);
246   /* general_interlaced_source_flag */
247   WRITE_UINT32 (bs, 0, 1);
248   /* general_non_packed_constraint_flag */
249   WRITE_UINT32 (bs, 0, 1);
250   /* general_frame_only_constraint_flag */
251   WRITE_UINT32 (bs, 1, 1);
252   /* general_reserved_zero_44bits */
253   for (i = 0; i < 44; i++)
254     WRITE_UINT32 (bs, 0, 1);
255   /* general_level_idc */
256   WRITE_UINT32 (bs, seq_param->general_level_idc, 8);
257
258   return TRUE;
259
260   /* ERRORS */
261 bs_error:
262   {
263     GST_WARNING ("failed to write Profile Tier Level");
264     return FALSE;
265   }
266 }
267
268 /* Write an VPS NAL unit */
269 static gboolean
270 bs_write_vps_data (GstBitWriter * bs, GstVaapiEncoderH265 * encoder,
271     GstVaapiEncPicture * picture,
272     const VAEncSequenceParameterBufferHEVC * seq_param, GstVaapiProfile profile)
273 {
274   guint32 video_parameter_set_id = 0;
275   guint32 vps_max_layers_minus1 = 0;
276   guint32 vps_max_sub_layers_minus1 = 0;
277   guint32 vps_temporal_id_nesting_flag = 1;
278   guint32 vps_sub_layer_ordering_info_present_flag = 0;
279   guint32 vps_max_latency_increase_plus1 = 0;
280   guint32 vps_max_layer_id = 0;
281   guint32 vps_num_layer_sets_minus1 = 0;
282   guint32 vps_timing_info_present_flag = 0;
283   guint32 vps_extension_flag = 0;
284
285   /* video_parameter_set_id */
286   WRITE_UINT32 (bs, video_parameter_set_id, 4);
287   /* vps_reserved_three_2bits */
288   WRITE_UINT32 (bs, 3, 2);
289   /* vps_max_layers_minus1 */
290   WRITE_UINT32 (bs, vps_max_layers_minus1, 6);
291   /* vps_max_sub_layers_minus1 */
292   WRITE_UINT32 (bs, vps_max_sub_layers_minus1, 3);
293   /* vps_temporal_id_nesting_flag */
294   WRITE_UINT32 (bs, vps_temporal_id_nesting_flag, 1);
295   /* vps_reserved_0xffff_16bits */
296   WRITE_UINT32 (bs, 0xffff, 16);
297
298   /* profile_tier_level */
299   bs_write_profile_tier_level (bs, seq_param);
300
301   /* vps_sub_layer_ordering_info_present_flag */
302   WRITE_UINT32 (bs, vps_sub_layer_ordering_info_present_flag, 1);
303   /* vps_max_dec_pic_buffering_minus1 */
304   WRITE_UE (bs, encoder->max_dec_pic_buffering - 1);
305   /* vps_max_num_reorder_pics */
306   WRITE_UE (bs, encoder->max_num_reorder_pics);
307   /* vps_max_latency_increase_plus1 */
308   WRITE_UE (bs, vps_max_latency_increase_plus1);
309   /* vps_max_layer_id */
310   WRITE_UINT32 (bs, vps_max_layer_id, 6);
311   /* vps_num_layer_sets_minus1 */
312   WRITE_UE (bs, vps_num_layer_sets_minus1);
313   /* vps_timing_info_present_flag */
314   WRITE_UINT32 (bs, vps_timing_info_present_flag, 1);
315   /* vps_extension_flag */
316   WRITE_UINT32 (bs, vps_extension_flag, 1);
317
318   return TRUE;
319
320   /* ERRORS */
321 bs_error:
322   {
323     GST_WARNING ("failed to write VPS NAL unit");
324     return FALSE;
325   }
326 }
327
328 static gboolean
329 bs_write_vps (GstBitWriter * bs, GstVaapiEncoderH265 * encoder,
330     GstVaapiEncPicture * picture,
331     const VAEncSequenceParameterBufferHEVC * seq_param, GstVaapiProfile profile)
332 {
333   if (!bs_write_vps_data (bs, encoder, picture, seq_param, profile))
334     return FALSE;
335
336   /* rbsp_trailing_bits */
337   bs_write_trailing_bits (bs);
338
339   return FALSE;
340 }
341
342 /* Write an SPS NAL unit */
343 static gboolean
344 bs_write_sps_data (GstBitWriter * bs, GstVaapiEncoderH265 * encoder,
345     GstVaapiEncPicture * picture,
346     const VAEncSequenceParameterBufferHEVC * seq_param, GstVaapiProfile profile,
347     const VAEncMiscParameterHRD * hrd_params)
348 {
349   guint32 video_parameter_set_id = 0;
350   guint32 max_sub_layers_minus1 = 0;
351   guint32 temporal_id_nesting_flag = 1;
352   guint32 seq_parameter_set_id = 0;
353   guint32 sps_sub_layer_ordering_info_present_flag = 0;
354   guint32 sps_max_latency_increase_plus1 = 0;
355   guint32 num_short_term_ref_pic_sets = 0;
356   guint32 long_term_ref_pics_present_flag = 0;
357   guint32 sps_extension_flag = 0;
358   guint32 nal_hrd_parameters_present_flag = 0;
359   guint maxNumSubLayers = 1, i;
360
361   /* video_parameter_set_id */
362   WRITE_UINT32 (bs, video_parameter_set_id, 4);
363   /* max_sub_layers_minus1 */
364   WRITE_UINT32 (bs, max_sub_layers_minus1, 3);
365   /* temporal_id_nesting_flag */
366   WRITE_UINT32 (bs, temporal_id_nesting_flag, 1);
367
368   /* profile_tier_level */
369   bs_write_profile_tier_level (bs, seq_param);
370
371   /* seq_parameter_set_id */
372   WRITE_UE (bs, seq_parameter_set_id);
373   /* chroma_format_idc  = 1, 4:2:0 */
374   WRITE_UE (bs, seq_param->seq_fields.bits.chroma_format_idc);
375   /* pic_width_in_luma_samples */
376   WRITE_UE (bs, seq_param->pic_width_in_luma_samples);
377   /* pic_height_in_luma_samples */
378   WRITE_UE (bs, seq_param->pic_height_in_luma_samples);
379
380   /* conformance_window_flag */
381   WRITE_UINT32 (bs, encoder->conformance_window_flag, 1);
382   if (encoder->conformance_window_flag) {
383     WRITE_UE (bs, encoder->conf_win_left_offset);
384     WRITE_UE (bs, encoder->conf_win_right_offset);
385     WRITE_UE (bs, encoder->conf_win_top_offset);
386     WRITE_UE (bs, encoder->conf_win_bottom_offset);
387   }
388
389   /* bit_depth_luma_minus8 */
390   WRITE_UE (bs, seq_param->seq_fields.bits.bit_depth_luma_minus8);
391   /* bit_depth_chroma_minus8 */
392   WRITE_UE (bs, seq_param->seq_fields.bits.bit_depth_chroma_minus8);
393   /* log2_max_pic_order_cnt_lsb_minus4  */
394   WRITE_UE (bs, encoder->log2_max_pic_order_cnt - 4);
395
396   /* sps_sub_layer_ordering_info_present_flag */
397   WRITE_UINT32 (bs, sps_sub_layer_ordering_info_present_flag, 1);
398   /* sps_max_dec_pic_buffering_minus1 */
399   WRITE_UE (bs, encoder->max_dec_pic_buffering - 1);
400   /* sps_max_num_reorder_pics */
401   WRITE_UE (bs, encoder->max_num_reorder_pics);
402   /* sps_max_latency_increase_plus1 */
403   WRITE_UE (bs, sps_max_latency_increase_plus1);
404
405   /* log2_min_luma_coding_block_size_minus3 */
406   WRITE_UE (bs, seq_param->log2_min_luma_coding_block_size_minus3);
407   /* log2_diff_max_min_luma_coding_block_size */
408   WRITE_UE (bs, seq_param->log2_diff_max_min_luma_coding_block_size);
409   /* log2_min_transform_block_size_minus2 */
410   WRITE_UE (bs, seq_param->log2_min_transform_block_size_minus2);
411   /* log2_diff_max_min_transform_block_size */
412   WRITE_UE (bs, seq_param->log2_diff_max_min_transform_block_size);
413   /* max_transform_hierarchy_depth_inter */
414   WRITE_UE (bs, seq_param->max_transform_hierarchy_depth_inter);
415   /*max_transform_hierarchy_depth_intra */
416   WRITE_UE (bs, seq_param->max_transform_hierarchy_depth_intra);
417
418   /* scaling_list_enabled_flag */
419   WRITE_UINT32 (bs, seq_param->seq_fields.bits.scaling_list_enabled_flag, 1);
420   /* amp_enabled_flag */
421   WRITE_UINT32 (bs, seq_param->seq_fields.bits.amp_enabled_flag, 1);
422   /* sample_adaptive_offset_enabled_flag */
423   WRITE_UINT32 (bs,
424       seq_param->seq_fields.bits.sample_adaptive_offset_enabled_flag, 1);
425   /* pcm_enabled_flag */
426   WRITE_UINT32 (bs, seq_param->seq_fields.bits.pcm_enabled_flag, 1);
427
428   /* num_short_term_ref_pic_sets  */
429   WRITE_UE (bs, num_short_term_ref_pic_sets);
430
431   /* long_term_ref_pics_present_flag */
432   WRITE_UINT32 (bs, long_term_ref_pics_present_flag, 1);
433
434   /* sps_temporal_mvp_enabled_flag */
435   WRITE_UINT32 (bs, seq_param->seq_fields.bits.sps_temporal_mvp_enabled_flag,
436       1);
437   /* strong_intra_smoothing_enabled_flag */
438   WRITE_UINT32 (bs,
439       seq_param->seq_fields.bits.strong_intra_smoothing_enabled_flag, 1);
440
441   /* vui_parameters_present_flag */
442   WRITE_UINT32 (bs, seq_param->vui_parameters_present_flag, 1);
443
444   /*--------------- Write VUI Parameters--------------- */
445   if (seq_param->vui_parameters_present_flag) {
446     gboolean vui_hrd_parameters_present_flag;
447     /* aspect_ratio_info_present_flag */
448     WRITE_UINT32 (bs,
449         seq_param->vui_fields.bits.aspect_ratio_info_present_flag, 1);
450     if (seq_param->vui_fields.bits.aspect_ratio_info_present_flag) {
451       WRITE_UINT32 (bs, seq_param->aspect_ratio_idc, 8);
452       if (seq_param->aspect_ratio_idc == 0xFF) {
453         WRITE_UINT32 (bs, seq_param->sar_width, 16);
454         WRITE_UINT32 (bs, seq_param->sar_height, 16);
455       }
456     }
457     /* overscan_info_present_flag */
458     WRITE_UINT32 (bs, 0, 1);
459     /* video_signal_type_present_flag */
460     WRITE_UINT32 (bs, 0, 1);
461     /* chroma_loc_info_present_flag */
462     WRITE_UINT32 (bs, 0, 1);
463     /* neutral_chroma_indication_flag */
464     WRITE_UINT32 (bs, seq_param->vui_fields.bits.neutral_chroma_indication_flag,
465         1);
466     /* field_seq_flag */
467     WRITE_UINT32 (bs, seq_param->vui_fields.bits.field_seq_flag, 1);
468     /* frame_field_info_present_flag */
469     WRITE_UINT32 (bs, 0, 1);
470     /* default_display_window_flag */
471     WRITE_UINT32 (bs, 0, 1);
472
473     /* timing_info_present_flag */
474     WRITE_UINT32 (bs, seq_param->vui_fields.bits.vui_timing_info_present_flag,
475         1);
476     if (seq_param->vui_fields.bits.vui_timing_info_present_flag) {
477       /* vui_num_units_in_tick */
478       WRITE_UINT32 (bs, seq_param->vui_num_units_in_tick, 32);
479       /* vui_time_scale */
480       WRITE_UINT32 (bs, seq_param->vui_time_scale, 32);
481       /* vui_poc_proportional_to_timing_flag */
482       WRITE_UINT32 (bs, 0, 1);
483
484       /* vui_hrd_parameters_present_flag */
485       vui_hrd_parameters_present_flag = seq_param->bits_per_second > 0;
486       WRITE_UINT32 (bs, vui_hrd_parameters_present_flag, 1);
487
488       if (vui_hrd_parameters_present_flag) {
489         nal_hrd_parameters_present_flag = 1;
490         /* nal_hrd_parameters_present_flag */
491         WRITE_UINT32 (bs, nal_hrd_parameters_present_flag, 1);
492         /* vcl_hrd_parameters_present_flag */
493         WRITE_UINT32 (bs, 0, 1);
494
495         if (nal_hrd_parameters_present_flag) {
496           /* sub_pic_hrd_params_present_flag */
497           WRITE_UINT32 (bs, 0, 1);
498           /* bit_rate_scale */
499           WRITE_UINT32 (bs, SX_BITRATE - 6, 4);
500           /* cpb_size_scale */
501           WRITE_UINT32 (bs, SX_CPB_SIZE - 4, 4);
502           /* initial_cpb_removal_delay_length_minus1 */
503           WRITE_UINT32 (bs, 23, 5);
504           /* au_cpb_removal_delay_length_minus1 */
505           WRITE_UINT32 (bs, 23, 5);
506           /* dpb_output_delay_length_minus1 */
507           WRITE_UINT32 (bs, 23, 5);
508
509           for (i = 0; i < maxNumSubLayers; i++) {
510             /* fixed_pic_rate_general_flag */
511             WRITE_UINT32 (bs, 0, 1);
512             /* fixed_pic_rate_within_cvs_flag */
513             WRITE_UINT32 (bs, 0, 1);
514             /* low_delay_hrd_flag */
515             WRITE_UINT32 (bs, 1, 1);
516             /* bit_rate_value_minus1 */
517             WRITE_UE (bs, (seq_param->bits_per_second >> SX_BITRATE) - 1);
518             /* cpb_size_value_minus1 */
519             WRITE_UE (bs, (hrd_params->buffer_size >> SX_CPB_SIZE) - 1);
520             /* cbr_flag */
521             WRITE_UINT32 (bs, 1, 1);
522           }
523         }
524       }
525     }
526     /* bitstream_restriction_flag */
527     WRITE_UINT32 (bs, seq_param->vui_fields.bits.bitstream_restriction_flag, 1);
528   }
529   /* sps_extension_flag */
530   WRITE_UINT32 (bs, sps_extension_flag, 1);
531
532   return TRUE;
533
534   /* ERRORS */
535 bs_error:
536   {
537     GST_WARNING ("failed to write SPS NAL unit");
538     return FALSE;
539   }
540 }
541
542 static gboolean
543 bs_write_sps (GstBitWriter * bs, GstVaapiEncoderH265 * encoder,
544     GstVaapiEncPicture * picture,
545     const VAEncSequenceParameterBufferHEVC * seq_param, GstVaapiProfile profile,
546     const VAEncMiscParameterHRD * hrd_params)
547 {
548   if (!bs_write_sps_data (bs, encoder, picture, seq_param, profile, hrd_params))
549     return FALSE;
550
551   /* rbsp_trailing_bits */
552   bs_write_trailing_bits (bs);
553
554   return FALSE;
555 }
556
557 /* Write a PPS NAL unit */
558 static gboolean
559 bs_write_pps (GstBitWriter * bs,
560     const VAEncPictureParameterBufferHEVC * pic_param)
561 {
562   guint32 pic_parameter_set_id = 0;
563   guint32 seq_parameter_set_id = 0;
564   guint32 output_flag_present_flag = 0;
565   guint32 num_extra_slice_header_bits = 0;
566   guint32 cabac_init_present_flag = 0;
567   guint32 pps_slice_chroma_qp_offsets_present_flag = 0;
568   guint32 deblocking_filter_control_present_flag = 0;
569   guint32 lists_modification_present_flag = 0;
570   guint32 slice_segment_header_extension_present_flag = 0;
571   guint32 pps_extension_flag = 0;
572
573   /* pic_parameter_set_id */
574   WRITE_UE (bs, pic_parameter_set_id);
575   /* seq_parameter_set_id */
576   WRITE_UE (bs, seq_parameter_set_id);
577   /* dependent_slice_segments_enabled_flag */
578   WRITE_UINT32 (bs,
579       pic_param->pic_fields.bits.dependent_slice_segments_enabled_flag, 1);
580   /* output_flag_present_flag */
581   WRITE_UINT32 (bs, output_flag_present_flag, 1);
582   /* num_extra_slice_header_bits */
583   WRITE_UINT32 (bs, num_extra_slice_header_bits, 3);
584   /* sign_data_hiding_enabled_flag */
585   WRITE_UINT32 (bs, pic_param->pic_fields.bits.sign_data_hiding_enabled_flag,
586       1);
587   /* cabac_init_present_flag */
588   WRITE_UINT32 (bs, cabac_init_present_flag, 1);
589   /* num_ref_idx_l0_default_active_minus1 */
590   WRITE_UE (bs, pic_param->num_ref_idx_l0_default_active_minus1);
591   /* num_ref_idx_l1_default_active_minus1 */
592   WRITE_UE (bs, pic_param->num_ref_idx_l1_default_active_minus1);
593   /* pic_init_qp_minus26 */
594   WRITE_SE (bs, pic_param->pic_init_qp - 26);
595   /* constrained_intra_pred_flag */
596   WRITE_UINT32 (bs, pic_param->pic_fields.bits.constrained_intra_pred_flag, 1);
597   /* transform_skip_enabled_flag */
598   WRITE_UINT32 (bs, pic_param->pic_fields.bits.transform_skip_enabled_flag, 1);
599   /* cu_qp_delta_enabled_flag */
600   WRITE_UINT32 (bs, pic_param->pic_fields.bits.cu_qp_delta_enabled_flag, 1);
601   /* diff_cu_qp_delta_depth */
602   if (pic_param->pic_fields.bits.cu_qp_delta_enabled_flag)
603     WRITE_UE (bs, pic_param->diff_cu_qp_delta_depth);
604
605   /* pps_cb_qp_offset */
606   WRITE_SE (bs, pic_param->pps_cb_qp_offset);
607   /* pps_cr_qp_offset */
608   WRITE_SE (bs, pic_param->pps_cr_qp_offset);
609   /* pps_slice_chroma_qp_offsets_present_flag */
610   WRITE_UINT32 (bs, pps_slice_chroma_qp_offsets_present_flag, 1);
611   /* weighted_pred_flag */
612   WRITE_UINT32 (bs, pic_param->pic_fields.bits.weighted_pred_flag, 1);
613   /* weighted_bipred_flag */
614   WRITE_UINT32 (bs, pic_param->pic_fields.bits.weighted_bipred_flag, 1);
615   /* transquant_bypass_enabled_flag */
616   WRITE_UINT32 (bs, pic_param->pic_fields.bits.transquant_bypass_enabled_flag,
617       1);
618   /* tiles_enabled_flag */
619   WRITE_UINT32 (bs, pic_param->pic_fields.bits.tiles_enabled_flag, 1);
620   /* entropy_coding_sync_enabled_flag */
621   WRITE_UINT32 (bs, pic_param->pic_fields.bits.entropy_coding_sync_enabled_flag,
622       1);
623   /* pps_loop_filter_across_slices_enabled_flag */
624   WRITE_UINT32 (bs,
625       pic_param->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag, 1);
626   /* deblocking_filter_control_present_flag */
627   WRITE_UINT32 (bs, deblocking_filter_control_present_flag, 1);
628   /* pps_scaling_list_data_present_flag */
629   WRITE_UINT32 (bs, pic_param->pic_fields.bits.scaling_list_data_present_flag,
630       1);
631   /* lists_modification_present_flag */
632   WRITE_UINT32 (bs, lists_modification_present_flag, 1);
633   /* log2_parallel_merge_level_minus2 */
634   WRITE_UE (bs, pic_param->log2_parallel_merge_level_minus2);
635   /* slice_segment_header_extension_present_flag */
636   WRITE_UINT32 (bs, slice_segment_header_extension_present_flag, 1);
637   /* pps_extension_flag */
638   WRITE_UINT32 (bs, pps_extension_flag, 1);
639
640   /* rbsp_trailing_bits */
641   bs_write_trailing_bits (bs);
642
643   return TRUE;
644
645   /* ERRORS */
646 bs_error:
647   {
648     GST_WARNING ("failed to write PPS NAL unit");
649     return FALSE;
650   }
651 }
652
653 /* Write a Slice NAL unit */
654 static gboolean
655 bs_write_slice (GstBitWriter * bs,
656     const VAEncSliceParameterBufferHEVC * slice_param,
657     GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture,
658     guint8 nal_unit_type)
659 {
660   const VAEncPictureParameterBufferHEVC *const pic_param = picture->param;
661
662   guint8 no_output_of_prior_pics_flag = 0;
663   guint8 dependent_slice_segment_flag = 0;
664   guint8 short_term_ref_pic_set_sps_flag = 0;
665   guint8 slice_deblocking_filter_disabled_flag = 0;
666   guint8 num_ref_idx_active_override_flag =
667       slice_param->slice_fields.bits.num_ref_idx_active_override_flag;
668
669   /* first_slice_segment_in_pic_flag */
670   WRITE_UINT32 (bs, encoder->first_slice_segment_in_pic_flag, 1);
671
672   /* FIXME: For all IRAP pics */
673   /* no_output_of_prior_pics_flag */
674   if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
675     WRITE_UINT32 (bs, no_output_of_prior_pics_flag, 1);
676
677   /* slice_pic_parameter_set_id */
678   WRITE_UE (bs, slice_param->slice_pic_parameter_set_id);
679
680   /* slice_segment_address , bits_size = Ceil(Log2(PicSizeInCtbsY)) */
681   if (!encoder->first_slice_segment_in_pic_flag) {
682     guint pic_size_ctb = encoder->ctu_width * encoder->ctu_height;
683     guint bits_size = (guint) ceil ((log2 (pic_size_ctb)));
684     WRITE_UINT32 (bs, slice_param->slice_segment_address, bits_size);
685   }
686
687   if (!dependent_slice_segment_flag) {
688     /* slice_type */
689     WRITE_UE (bs, slice_param->slice_type);
690
691     if (!pic_param->pic_fields.bits.idr_pic_flag) {
692       /* slice_pic_order_cnt_lsb */
693       WRITE_UINT32 (bs, picture->poc, encoder->log2_max_pic_order_cnt);
694       /* short_term_ref_pic_set_sps_flag */
695       WRITE_UINT32 (bs, short_term_ref_pic_set_sps_flag, 1);
696
697     /*---------- Write short_term_ref_pic_set(0) ----------- */
698       {
699         guint num_positive_pics = 0, num_negative_pics = 0;
700         guint delta_poc_s0_minus1 = 0, delta_poc_s1_minus1 = 0;
701         guint used_by_curr_pic_s0_flag = 0, used_by_curr_pic_s1_flag = 0;
702         guint reflist_0_count = 0, reflist_1_count = 0;
703         gint i;
704
705         /* Get count of ref_pic_list */
706         if (picture->type == GST_VAAPI_PICTURE_TYPE_P
707             || picture->type == GST_VAAPI_PICTURE_TYPE_B) {
708           for (i = 0; i < G_N_ELEMENTS (slice_param->ref_pic_list0); ++i) {
709             if (slice_param->ref_pic_list0[i].picture_id == VA_INVALID_SURFACE)
710               break;
711           }
712           reflist_0_count = i;
713
714           if (picture->type == GST_VAAPI_PICTURE_TYPE_B) {
715             for (i = 0; i < G_N_ELEMENTS (slice_param->ref_pic_list1); ++i) {
716               if (slice_param->ref_pic_list1[i].picture_id ==
717                   VA_INVALID_SURFACE)
718                 break;
719             }
720             reflist_1_count = i;
721           }
722         }
723
724         if (picture->type == GST_VAAPI_PICTURE_TYPE_P) {
725           delta_poc_s0_minus1 =
726               picture->poc - slice_param->ref_pic_list0[0].pic_order_cnt - 1;
727           used_by_curr_pic_s0_flag = 1;
728           delta_poc_s1_minus1 = 0;
729           used_by_curr_pic_s1_flag = 0;
730         }
731         if (picture->type == GST_VAAPI_PICTURE_TYPE_B) {
732           delta_poc_s0_minus1 =
733               picture->poc - slice_param->ref_pic_list0[0].pic_order_cnt - 1;
734           used_by_curr_pic_s0_flag = 1;
735           delta_poc_s1_minus1 =
736               slice_param->ref_pic_list1[0].pic_order_cnt - picture->poc - 1;
737           used_by_curr_pic_s1_flag = 1;
738         }
739
740         num_negative_pics = reflist_0_count;
741         num_positive_pics = reflist_1_count;
742
743         /* num_negative_pics */
744         WRITE_UE (bs, num_negative_pics);
745         /* num_positive_pics */
746         WRITE_UE (bs, num_positive_pics);
747
748         for (i = 0; i < num_negative_pics; i++) {
749           /* delta_poc_s0_minus1 */
750           if (i == 0) {
751             WRITE_UE (bs, delta_poc_s0_minus1);
752           } else {
753             WRITE_UE (bs,
754                 slice_param->ref_pic_list0[i - 1].pic_order_cnt -
755                 slice_param->ref_pic_list0[i].pic_order_cnt - 1);
756           }
757           /* used_by_curr_pic_s0_flag */
758           WRITE_UINT32 (bs, used_by_curr_pic_s0_flag, 1);
759         }
760         for (i = 0; i < num_positive_pics; i++) {
761           /* delta_poc_s1_minus1 */
762           if (i == 0) {
763             WRITE_UE (bs, delta_poc_s1_minus1);
764           } else {
765             WRITE_UE (bs,
766                 slice_param->ref_pic_list1[i - 1].pic_order_cnt -
767                 slice_param->ref_pic_list1[i].pic_order_cnt - 1);
768           }
769           /* used_by_curr_pic_s1_flag */
770           WRITE_UINT32 (bs, used_by_curr_pic_s1_flag, 1);
771         }
772       }
773
774       /* slice_temporal_mvp_enabled_flag */
775       if (encoder->sps_temporal_mvp_enabled_flag)
776         WRITE_UINT32 (bs,
777             slice_param->slice_fields.bits.slice_temporal_mvp_enabled_flag, 1);
778     }
779
780     if (encoder->sample_adaptive_offset_enabled_flag) {
781       WRITE_UINT32 (bs, slice_param->slice_fields.bits.slice_sao_luma_flag, 1);
782       WRITE_UINT32 (bs, slice_param->slice_fields.bits.slice_sao_chroma_flag,
783           1);
784     }
785
786     if (slice_param->slice_type == GST_H265_P_SLICE ||
787         slice_param->slice_type == GST_H265_B_SLICE) {
788       /* num_ref_idx_active_override_flag */
789       WRITE_UINT32 (bs, num_ref_idx_active_override_flag, 1);
790       if (num_ref_idx_active_override_flag) {
791         WRITE_UE (bs, slice_param->num_ref_idx_l0_active_minus1);
792         if (slice_param->slice_type == GST_H265_B_SLICE)
793           WRITE_UE (bs, slice_param->num_ref_idx_l1_active_minus1);
794       }
795
796       /* mvd_l1_zero_flag */
797       if (slice_param->slice_type == GST_H265_B_SLICE)
798         WRITE_UINT32 (bs, slice_param->slice_fields.bits.mvd_l1_zero_flag, 1);
799
800       /* cabac_init_present_flag == FALSE */
801       /* cabac_init_flag  = FALSE */
802
803       /* collocated_from_l0_flag */
804       if (slice_param->slice_fields.bits.slice_temporal_mvp_enabled_flag) {
805         if (slice_param->slice_type == GST_H265_B_SLICE)
806           WRITE_UINT32 (bs,
807               slice_param->slice_fields.bits.collocated_from_l0_flag, 1);
808       }
809       /* five_minus_max_num_merge_cand */
810       WRITE_UE (bs, 5 - slice_param->max_num_merge_cand);
811     }
812
813     /* slice_qp_delta */
814     WRITE_SE (bs, slice_param->slice_qp_delta);
815     if (pic_param->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag &&
816         (slice_param->slice_fields.bits.slice_sao_luma_flag
817             || slice_param->slice_fields.bits.slice_sao_chroma_flag
818             || !slice_deblocking_filter_disabled_flag))
819       WRITE_UINT32 (bs,
820           slice_param->slice_fields.bits.
821           slice_loop_filter_across_slices_enabled_flag, 1);
822
823   }
824
825   /* byte_alignment() */
826   {
827     /* alignment_bit_equal_to_one */
828     WRITE_UINT32 (bs, 1, 1);
829     while (GST_BIT_WRITER_BIT_SIZE (bs) % 8 != 0) {
830       /* alignment_bit_equal_to_zero */
831       WRITE_UINT32 (bs, 0, 1);
832     }
833   }
834
835   return TRUE;
836
837   /* ERRORS */
838 bs_error:
839   {
840     GST_WARNING ("failed to write Slice NAL unit");
841     return FALSE;
842   }
843 }
844
845 static inline void
846 _check_vps_sps_pps_status (GstVaapiEncoderH265 * encoder,
847     const guint8 * nal, guint32 size)
848 {
849   guint8 nal_type;
850   G_GNUC_UNUSED gsize ret;      /* FIXME */
851   g_assert (size);
852
853   if (encoder->vps_data && encoder->sps_data && encoder->pps_data)
854     return;
855
856   nal_type = (nal[0] & 0x7E) >> 1;
857   switch (nal_type) {
858     case GST_H265_NAL_VPS:
859       encoder->vps_data = gst_buffer_new_allocate (NULL, size, NULL);
860       ret = gst_buffer_fill (encoder->vps_data, 0, nal, size);
861       g_assert (ret == size);
862       break;
863     case GST_H265_NAL_SPS:
864       encoder->sps_data = gst_buffer_new_allocate (NULL, size, NULL);
865       ret = gst_buffer_fill (encoder->sps_data, 0, nal, size);
866       g_assert (ret == size);
867       break;
868     case GST_H265_NAL_PPS:
869       encoder->pps_data = gst_buffer_new_allocate (NULL, size, NULL);
870       ret = gst_buffer_fill (encoder->pps_data, 0, nal, size);
871       g_assert (ret == size);
872       break;
873     default:
874       break;
875   }
876 }
877
878 /* Determines the largest supported profile by the underlying hardware */
879 static gboolean
880 ensure_hw_profile_limits (GstVaapiEncoderH265 * encoder)
881 {
882   GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
883   GArray *profiles;
884   guint i, profile_idc, max_profile_idc;
885
886   if (encoder->hw_max_profile_idc)
887     return TRUE;
888
889   profiles = gst_vaapi_display_get_encode_profiles (display);
890   if (!profiles)
891     return FALSE;
892
893   max_profile_idc = 0;
894   for (i = 0; i < profiles->len; i++) {
895     const GstVaapiProfile profile =
896         g_array_index (profiles, GstVaapiProfile, i);
897     profile_idc = gst_vaapi_utils_h265_get_profile_idc (profile);
898     if (!profile_idc)
899       continue;
900     if (max_profile_idc < profile_idc)
901       max_profile_idc = profile_idc;
902   }
903   g_array_unref (profiles);
904
905   encoder->hw_max_profile_idc = max_profile_idc;
906   return TRUE;
907 }
908
909 /* Derives the profile supported by the underlying hardware */
910 static gboolean
911 ensure_hw_profile (GstVaapiEncoderH265 * encoder)
912 {
913   GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
914   GstVaapiEntrypoint entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE;
915   GstVaapiProfile profile, profiles[4];
916   guint i, num_profiles = 0;
917
918   profiles[num_profiles++] = encoder->profile;
919   switch (encoder->profile) {
920     case GST_VAAPI_PROFILE_H265_MAIN_STILL_PICTURE:
921       profiles[num_profiles++] = GST_VAAPI_PROFILE_H265_MAIN;
922       // fall-through
923     case GST_VAAPI_PROFILE_H265_MAIN:
924       profiles[num_profiles++] = GST_VAAPI_PROFILE_H265_MAIN10;
925       break;
926     default:
927       break;
928   }
929
930   profile = GST_VAAPI_PROFILE_UNKNOWN;
931   for (i = 0; i < num_profiles; i++) {
932     if (gst_vaapi_display_has_encoder (display, profiles[i], entrypoint)) {
933       profile = profiles[i];
934       break;
935     }
936   }
937   if (profile == GST_VAAPI_PROFILE_UNKNOWN)
938     goto error_unsupported_profile;
939
940   GST_VAAPI_ENCODER_CAST (encoder)->profile = profile;
941   return TRUE;
942
943   /* ERRORS */
944 error_unsupported_profile:
945   {
946     GST_ERROR ("unsupported HW profile %s",
947         gst_vaapi_profile_get_name (encoder->profile));
948     return FALSE;
949   }
950 }
951
952 /* Check target decoder constraints */
953 static gboolean
954 ensure_profile_limits (GstVaapiEncoderH265 * encoder)
955 {
956
957   if (!encoder->max_profile_idc
958       || encoder->profile_idc <= encoder->max_profile_idc)
959     return TRUE;
960
961   GST_WARNING
962       ("Needs to lower coding tools to meet target decoder constraints");
963   GST_WARNING ("Only supporting Main profile, reset profile to Main");
964
965   encoder->profile = GST_VAAPI_PROFILE_H265_MAIN;
966   encoder->profile_idc =
967       gst_vaapi_utils_h265_get_profile_idc (encoder->profile);
968
969   return TRUE;
970 }
971
972 /* Derives the minimum profile from the active coding tools */
973 static gboolean
974 ensure_profile (GstVaapiEncoderH265 * encoder)
975 {
976   GstVaapiProfile profile;
977   const GstVideoFormat format =
978       GST_VIDEO_INFO_FORMAT (GST_VAAPI_ENCODER_VIDEO_INFO (encoder));
979
980   /* Always start from "Main" profile for maximum
981      compatibility */
982   profile = GST_VAAPI_PROFILE_H265_MAIN;
983
984   if (format == GST_VIDEO_FORMAT_P010_10LE)
985     profile = GST_VAAPI_PROFILE_H265_MAIN10;
986
987   encoder->profile = profile;
988   encoder->profile_idc = gst_vaapi_utils_h265_get_profile_idc (profile);
989   return TRUE;
990 }
991
992 /* Derives the minimum tier from the active coding tools */
993 static gboolean
994 ensure_tier (GstVaapiEncoderH265 * encoder)
995 {
996
997   encoder->tier = GST_VAAPI_TIER_H265_MAIN;
998   /* FIXME: Derive proper tier based on upstream caps or limits, coding
999    * tools etc */
1000
1001   return TRUE;
1002 }
1003
1004 /* Derives the level from the currently set limits */
1005 static gboolean
1006 ensure_level (GstVaapiEncoderH265 * encoder)
1007 {
1008   const GstVaapiH265LevelLimits *limits_table;
1009   guint i, num_limits, PicSizeInSamplesY;
1010
1011   PicSizeInSamplesY = encoder->luma_width * encoder->luma_height;
1012
1013   limits_table = gst_vaapi_utils_h265_get_level_limits_table (&num_limits);
1014   for (i = 0; i < num_limits; i++) {
1015     const GstVaapiH265LevelLimits *const limits = &limits_table[i];
1016     if (PicSizeInSamplesY <= limits->MaxLumaPs)
1017       break;
1018     /* FIXME: Add more constraint checking:tier (extracted from caps),
1019      * cpb size, bitrate, num_tile_columns and num_tile_rows */
1020   }
1021   if (i == num_limits)
1022     goto error_unsupported_level;
1023
1024   encoder->level = limits_table[i].level;
1025   encoder->level_idc = limits_table[i].level_idc;
1026   return TRUE;
1027
1028   /* ERRORS */
1029 error_unsupported_level:
1030   {
1031     GST_ERROR ("failed to find a suitable level matching codec config");
1032     return FALSE;
1033   }
1034 }
1035
1036 /* Enable "high-compression" tuning options */
1037 static gboolean
1038 ensure_tuning_high_compression (GstVaapiEncoderH265 * encoder)
1039 {
1040   guint8 profile_idc;
1041
1042   if (!ensure_hw_profile_limits (encoder))
1043     return FALSE;
1044
1045   profile_idc = encoder->hw_max_profile_idc;
1046   if (encoder->max_profile_idc && encoder->max_profile_idc < profile_idc)
1047     profile_idc = encoder->max_profile_idc;
1048
1049   /* Tuning options */
1050   if (!encoder->num_bframes)
1051     encoder->num_bframes = 3;
1052
1053   return TRUE;
1054 }
1055
1056 /* Ensure tuning options */
1057 static gboolean
1058 ensure_tuning (GstVaapiEncoderH265 * encoder)
1059 {
1060   gboolean success;
1061
1062   switch (GST_VAAPI_ENCODER_TUNE (encoder)) {
1063     case GST_VAAPI_ENCODER_TUNE_HIGH_COMPRESSION:
1064       success = ensure_tuning_high_compression (encoder);
1065       break;
1066     default:
1067       success = TRUE;
1068       break;
1069   }
1070   return success;
1071 }
1072
1073 /* Handle new GOP starts */
1074 static void
1075 reset_gop_start (GstVaapiEncoderH265 * encoder)
1076 {
1077   GstVaapiH265ReorderPool *const reorder_pool = &encoder->reorder_pool;
1078
1079   reorder_pool->frame_index = 1;
1080   reorder_pool->cur_present_index = 0;
1081   ++encoder->idr_num;
1082 }
1083
1084 /* Marks the supplied picture as a B-frame */
1085 static void
1086 set_b_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH265 * encoder)
1087 {
1088   g_assert (pic && encoder);
1089   g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1090   pic->type = GST_VAAPI_PICTURE_TYPE_B;
1091 }
1092
1093 /* Marks the supplied picture as a P-frame */
1094 static void
1095 set_p_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH265 * encoder)
1096 {
1097   g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1098   pic->type = GST_VAAPI_PICTURE_TYPE_P;
1099 }
1100
1101 /* Marks the supplied picture as an I-frame */
1102 static void
1103 set_i_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH265 * encoder)
1104 {
1105   g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1106   pic->type = GST_VAAPI_PICTURE_TYPE_I;
1107
1108   g_assert (pic->frame);
1109   GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (pic->frame);
1110 }
1111
1112 /* Marks the supplied picture as an IDR frame */
1113 static void
1114 set_idr_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH265 * encoder)
1115 {
1116   g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1117   pic->type = GST_VAAPI_PICTURE_TYPE_I;
1118   pic->poc = 0;
1119   GST_VAAPI_ENC_PICTURE_FLAG_SET (pic, GST_VAAPI_ENC_PICTURE_FLAG_IDR);
1120
1121   g_assert (pic->frame);
1122   GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (pic->frame);
1123 }
1124
1125 /* Marks the supplied picture a a key-frame */
1126 static void
1127 set_key_frame (GstVaapiEncPicture * picture,
1128     GstVaapiEncoderH265 * encoder, gboolean is_idr)
1129 {
1130   if (is_idr) {
1131     reset_gop_start (encoder);
1132     set_idr_frame (picture, encoder);
1133   } else
1134     set_i_frame (picture, encoder);
1135 }
1136
1137 /* Fills in VA HRD parameters */
1138 static void
1139 fill_hrd_params (GstVaapiEncoderH265 * encoder, VAEncMiscParameterHRD * hrd)
1140 {
1141   if (encoder->bitrate_bits > 0) {
1142     hrd->buffer_size = encoder->cpb_length_bits;
1143     hrd->initial_buffer_fullness = hrd->buffer_size / 2;
1144   } else {
1145     hrd->buffer_size = 0;
1146     hrd->initial_buffer_fullness = 0;
1147   }
1148 }
1149
1150 /* Adds the supplied video parameter set header (VPS) to the list of packed
1151    headers to pass down as-is to the encoder */
1152 static gboolean
1153 add_packed_vps_header (GstVaapiEncoderH265 * encoder,
1154     GstVaapiEncPicture * picture, GstVaapiEncSequence * sequence)
1155 {
1156   GstVaapiEncPackedHeader *packed_vps;
1157   GstBitWriter bs;
1158   VAEncPackedHeaderParameterBuffer packed_vps_param = { 0 };
1159   const VAEncSequenceParameterBufferHEVC *const seq_param = sequence->param;
1160   GstVaapiProfile profile = encoder->profile;
1161
1162   guint32 data_bit_size;
1163   guint8 *data;
1164
1165   gst_bit_writer_init (&bs, 128 * 8);
1166   WRITE_UINT32 (&bs, 0x00000001, 32);   /* start code */
1167   bs_write_nal_header (&bs, GST_H265_NAL_VPS);
1168
1169   bs_write_vps (&bs, encoder, picture, seq_param, profile);
1170
1171   g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1172   data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1173   data = GST_BIT_WRITER_DATA (&bs);
1174
1175   packed_vps_param.type = VAEncPackedHeaderSequence;
1176   packed_vps_param.bit_length = data_bit_size;
1177   packed_vps_param.has_emulation_bytes = 0;
1178
1179   packed_vps = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1180       &packed_vps_param, sizeof (packed_vps_param),
1181       data, (data_bit_size + 7) / 8);
1182   g_assert (packed_vps);
1183
1184   gst_vaapi_enc_picture_add_packed_header (picture, packed_vps);
1185   gst_vaapi_codec_object_replace (&packed_vps, NULL);
1186
1187   /* store vps data */
1188   _check_vps_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1189   gst_bit_writer_clear (&bs, TRUE);
1190   return TRUE;
1191
1192   /* ERRORS */
1193 bs_error:
1194   {
1195     GST_WARNING ("failed to write VPS NAL unit");
1196     gst_bit_writer_clear (&bs, TRUE);
1197     return FALSE;
1198   }
1199 }
1200
1201 /* Adds the supplied sequence header (SPS) to the list of packed
1202    headers to pass down as-is to the encoder */
1203 static gboolean
1204 add_packed_sequence_header (GstVaapiEncoderH265 * encoder,
1205     GstVaapiEncPicture * picture, GstVaapiEncSequence * sequence)
1206 {
1207   GstVaapiEncPackedHeader *packed_seq;
1208   GstBitWriter bs;
1209   VAEncPackedHeaderParameterBuffer packed_seq_param = { 0 };
1210   const VAEncSequenceParameterBufferHEVC *const seq_param = sequence->param;
1211   GstVaapiProfile profile = encoder->profile;
1212
1213   VAEncMiscParameterHRD hrd_params;
1214   guint32 data_bit_size;
1215   guint8 *data;
1216
1217   fill_hrd_params (encoder, &hrd_params);
1218
1219   gst_bit_writer_init (&bs, 128 * 8);
1220   WRITE_UINT32 (&bs, 0x00000001, 32);   /* start code */
1221   bs_write_nal_header (&bs, GST_H265_NAL_SPS);
1222
1223   bs_write_sps (&bs, encoder, picture, seq_param, profile, &hrd_params);
1224
1225   g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1226   data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1227   data = GST_BIT_WRITER_DATA (&bs);
1228
1229   packed_seq_param.type = VAEncPackedHeaderSequence;
1230   packed_seq_param.bit_length = data_bit_size;
1231   packed_seq_param.has_emulation_bytes = 0;
1232
1233   packed_seq = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1234       &packed_seq_param, sizeof (packed_seq_param),
1235       data, (data_bit_size + 7) / 8);
1236   g_assert (packed_seq);
1237
1238   gst_vaapi_enc_picture_add_packed_header (picture, packed_seq);
1239   gst_vaapi_codec_object_replace (&packed_seq, NULL);
1240
1241   /* store sps data */
1242   _check_vps_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1243   gst_bit_writer_clear (&bs, TRUE);
1244   return TRUE;
1245
1246   /* ERRORS */
1247 bs_error:
1248   {
1249     GST_WARNING ("failed to write SPS NAL unit");
1250     gst_bit_writer_clear (&bs, TRUE);
1251     return FALSE;
1252   }
1253 }
1254
1255 /* Adds the supplied picture header (PPS) to the list of packed
1256    headers to pass down as-is to the encoder */
1257 static gboolean
1258 add_packed_picture_header (GstVaapiEncoderH265 * encoder,
1259     GstVaapiEncPicture * picture)
1260 {
1261   GstVaapiEncPackedHeader *packed_pic;
1262   GstBitWriter bs;
1263   VAEncPackedHeaderParameterBuffer packed_pic_param = { 0 };
1264   const VAEncPictureParameterBufferHEVC *const pic_param = picture->param;
1265   guint32 data_bit_size;
1266   guint8 *data;
1267
1268   gst_bit_writer_init (&bs, 128 * 8);
1269   WRITE_UINT32 (&bs, 0x00000001, 32);   /* start code */
1270   bs_write_nal_header (&bs, GST_H265_NAL_PPS);
1271   bs_write_pps (&bs, pic_param);
1272   g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1273   data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1274   data = GST_BIT_WRITER_DATA (&bs);
1275
1276   packed_pic_param.type = VAEncPackedHeaderPicture;
1277   packed_pic_param.bit_length = data_bit_size;
1278   packed_pic_param.has_emulation_bytes = 0;
1279
1280   packed_pic = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1281       &packed_pic_param, sizeof (packed_pic_param),
1282       data, (data_bit_size + 7) / 8);
1283   g_assert (packed_pic);
1284
1285   gst_vaapi_enc_picture_add_packed_header (picture, packed_pic);
1286   gst_vaapi_codec_object_replace (&packed_pic, NULL);
1287
1288   /* store pps data */
1289   _check_vps_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1290   gst_bit_writer_clear (&bs, TRUE);
1291   return TRUE;
1292
1293   /* ERRORS */
1294 bs_error:
1295   {
1296     GST_WARNING ("failed to write PPS NAL unit");
1297     gst_bit_writer_clear (&bs, TRUE);
1298     return FALSE;
1299   }
1300 }
1301
1302 static gboolean
1303 get_nal_unit_type (GstVaapiEncPicture * picture, guint8 * nal_unit_type)
1304 {
1305   switch (picture->type) {
1306     case GST_VAAPI_PICTURE_TYPE_I:
1307       if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
1308         *nal_unit_type = GST_H265_NAL_SLICE_IDR_W_RADL;
1309       else
1310         *nal_unit_type = GST_H265_NAL_SLICE_TRAIL_R;
1311       break;
1312     case GST_VAAPI_PICTURE_TYPE_P:
1313       *nal_unit_type = GST_H265_NAL_SLICE_TRAIL_R;
1314       break;
1315     case GST_VAAPI_PICTURE_TYPE_B:
1316       *nal_unit_type = GST_H265_NAL_SLICE_TRAIL_N;
1317       break;
1318     default:
1319       return FALSE;
1320   }
1321   return TRUE;
1322 }
1323
1324 /* Adds the supplied slice header to the list of packed
1325    headers to pass down as-is to the encoder */
1326 static gboolean
1327 add_packed_slice_header (GstVaapiEncoderH265 * encoder,
1328     GstVaapiEncPicture * picture, GstVaapiEncSlice * slice)
1329 {
1330   GstVaapiEncPackedHeader *packed_slice;
1331   GstBitWriter bs;
1332   VAEncPackedHeaderParameterBuffer packed_slice_param = { 0 };
1333   const VAEncSliceParameterBufferHEVC *const slice_param = slice->param;
1334   guint32 data_bit_size;
1335   guint8 *data;
1336   guint8 nal_unit_type;
1337
1338   gst_bit_writer_init (&bs, 128 * 8);
1339   WRITE_UINT32 (&bs, 0x00000001, 32);   /* start code */
1340
1341   if (!get_nal_unit_type (picture, &nal_unit_type))
1342     goto bs_error;
1343   bs_write_nal_header (&bs, nal_unit_type);
1344
1345   bs_write_slice (&bs, slice_param, encoder, picture, nal_unit_type);
1346   data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1347   data = GST_BIT_WRITER_DATA (&bs);
1348
1349   packed_slice_param.type = VAEncPackedHeaderSlice;
1350   packed_slice_param.bit_length = data_bit_size;
1351   packed_slice_param.has_emulation_bytes = 0;
1352
1353   packed_slice = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1354       &packed_slice_param, sizeof (packed_slice_param),
1355       data, (data_bit_size + 7) / 8);
1356   g_assert (packed_slice);
1357
1358   gst_vaapi_enc_slice_add_packed_header (slice, packed_slice);
1359   gst_vaapi_codec_object_replace (&packed_slice, NULL);
1360
1361   gst_bit_writer_clear (&bs, TRUE);
1362   return TRUE;
1363
1364   /* ERRORS */
1365 bs_error:
1366   {
1367     GST_WARNING ("failed to write Slice NAL unit header");
1368     gst_bit_writer_clear (&bs, TRUE);
1369     return FALSE;
1370   }
1371 }
1372
1373 /* Reference picture management */
1374 static void
1375 reference_pic_free (GstVaapiEncoderH265 * encoder, GstVaapiEncoderH265Ref * ref)
1376 {
1377   if (!ref)
1378     return;
1379   if (ref->pic)
1380     gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder), ref->pic);
1381   g_slice_free (GstVaapiEncoderH265Ref, ref);
1382 }
1383
1384 static inline GstVaapiEncoderH265Ref *
1385 reference_pic_create (GstVaapiEncoderH265 * encoder,
1386     GstVaapiEncPicture * picture, GstVaapiSurfaceProxy * surface)
1387 {
1388   GstVaapiEncoderH265Ref *const ref = g_slice_new0 (GstVaapiEncoderH265Ref);
1389
1390   ref->pic = surface;
1391   ref->poc = picture->poc;
1392   return ref;
1393 }
1394
1395 static gboolean
1396 reference_list_update (GstVaapiEncoderH265 * encoder,
1397     GstVaapiEncPicture * picture, GstVaapiSurfaceProxy * surface)
1398 {
1399   GstVaapiEncoderH265Ref *ref;
1400   GstVaapiH265RefPool *const ref_pool = &encoder->ref_pool;
1401
1402   if (GST_VAAPI_PICTURE_TYPE_B == picture->type) {
1403     gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder), surface);
1404     return TRUE;
1405   }
1406
1407   if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture)) {
1408     while (!g_queue_is_empty (&ref_pool->ref_list))
1409       reference_pic_free (encoder, g_queue_pop_head (&ref_pool->ref_list));
1410   } else if (g_queue_get_length (&ref_pool->ref_list) >=
1411       ref_pool->max_ref_frames) {
1412     reference_pic_free (encoder, g_queue_pop_head (&ref_pool->ref_list));
1413   }
1414   ref = reference_pic_create (encoder, picture, surface);
1415   g_queue_push_tail (&ref_pool->ref_list, ref);
1416   g_assert (g_queue_get_length (&ref_pool->ref_list) <=
1417       ref_pool->max_ref_frames);
1418   return TRUE;
1419 }
1420
1421 static gboolean
1422 reference_list_init (GstVaapiEncoderH265 * encoder,
1423     GstVaapiEncPicture * picture,
1424     GstVaapiEncoderH265Ref ** reflist_0,
1425     guint * reflist_0_count,
1426     GstVaapiEncoderH265Ref ** reflist_1, guint * reflist_1_count)
1427 {
1428   GstVaapiEncoderH265Ref *tmp;
1429   GstVaapiH265RefPool *const ref_pool = &encoder->ref_pool;
1430   GList *iter, *list_0_start = NULL, *list_1_start = NULL;
1431   guint count;
1432
1433   *reflist_0_count = 0;
1434   *reflist_1_count = 0;
1435   if (picture->type == GST_VAAPI_PICTURE_TYPE_I)
1436     return TRUE;
1437
1438   iter = g_queue_peek_tail_link (&ref_pool->ref_list);
1439   for (; iter; iter = g_list_previous (iter)) {
1440     tmp = (GstVaapiEncoderH265Ref *) iter->data;
1441     g_assert (tmp && tmp->poc != picture->poc);
1442     if (_poc_greater_than (picture->poc, tmp->poc, encoder->max_pic_order_cnt)) {
1443       list_0_start = iter;
1444       list_1_start = g_list_next (iter);
1445       break;
1446     }
1447   }
1448
1449   /* order reflist_0 */
1450   g_assert (list_0_start);
1451   iter = list_0_start;
1452   count = 0;
1453   for (; iter; iter = g_list_previous (iter)) {
1454     reflist_0[count] = (GstVaapiEncoderH265Ref *) iter->data;
1455     ++count;
1456   }
1457   *reflist_0_count = count;
1458
1459   if (picture->type != GST_VAAPI_PICTURE_TYPE_B)
1460     return TRUE;
1461
1462   /* order reflist_1 */
1463   count = 0;
1464   iter = list_1_start;
1465   for (; iter; iter = g_list_next (iter)) {
1466     reflist_1[count] = (GstVaapiEncoderH265Ref *) iter->data;
1467     ++count;
1468   }
1469   *reflist_1_count = count;
1470   return TRUE;
1471 }
1472
1473 /* Fills in VA sequence parameter buffer */
1474 static gboolean
1475 fill_sequence (GstVaapiEncoderH265 * encoder, GstVaapiEncSequence * sequence)
1476 {
1477   VAEncSequenceParameterBufferHEVC *const seq_param = sequence->param;
1478   const GstVideoFormat format =
1479       GST_VIDEO_INFO_FORMAT (GST_VAAPI_ENCODER_VIDEO_INFO (encoder));
1480   guint bits_depth_luma_minus8 =
1481       GST_VIDEO_FORMAT_INFO_DEPTH (gst_video_format_get_info (format), 0);
1482   if (bits_depth_luma_minus8 < 8)
1483     return FALSE;
1484   bits_depth_luma_minus8 -= 8;
1485
1486   memset (seq_param, 0, sizeof (VAEncSequenceParameterBufferHEVC));
1487
1488   seq_param->general_profile_idc = encoder->profile_idc;
1489   seq_param->general_level_idc = encoder->level_idc;
1490   seq_param->general_tier_flag = 0;     /* FIXME: use the tier flag
1491                                          * extracted from upstream
1492                                          * caps or calcuted one */
1493
1494   seq_param->intra_period = GST_VAAPI_ENCODER_KEYFRAME_PERIOD (encoder);
1495   seq_param->intra_idr_period = encoder->idr_period;
1496   seq_param->ip_period = seq_param->intra_period > 1 ?
1497       (1 + encoder->num_bframes) : 0;
1498   seq_param->bits_per_second = encoder->bitrate_bits;
1499
1500   seq_param->pic_width_in_luma_samples = encoder->luma_width;
1501   seq_param->pic_height_in_luma_samples = encoder->luma_height;
1502
1503   /*sequence field values */
1504   seq_param->seq_fields.value = 0;
1505   seq_param->seq_fields.bits.chroma_format_idc = 1;
1506   seq_param->seq_fields.bits.separate_colour_plane_flag = 0;
1507   seq_param->seq_fields.bits.bit_depth_luma_minus8 = bits_depth_luma_minus8;
1508   seq_param->seq_fields.bits.bit_depth_chroma_minus8 = bits_depth_luma_minus8;
1509   seq_param->seq_fields.bits.scaling_list_enabled_flag = FALSE;
1510   seq_param->seq_fields.bits.strong_intra_smoothing_enabled_flag = TRUE;
1511   seq_param->seq_fields.bits.amp_enabled_flag = TRUE;
1512   seq_param->seq_fields.bits.sample_adaptive_offset_enabled_flag =
1513       encoder->sample_adaptive_offset_enabled_flag = FALSE;
1514   seq_param->seq_fields.bits.pcm_enabled_flag = FALSE;
1515   seq_param->seq_fields.bits.pcm_loop_filter_disabled_flag = FALSE;
1516   seq_param->seq_fields.bits.sps_temporal_mvp_enabled_flag =
1517       encoder->sps_temporal_mvp_enabled_flag = TRUE;
1518
1519   /* Based on 32x32 CTU */
1520   seq_param->log2_min_luma_coding_block_size_minus3 = 0;
1521   seq_param->log2_diff_max_min_luma_coding_block_size = 2;
1522   seq_param->log2_min_transform_block_size_minus2 = 0;
1523   seq_param->log2_diff_max_min_transform_block_size = 3;
1524   seq_param->max_transform_hierarchy_depth_inter = 3;
1525   seq_param->max_transform_hierarchy_depth_intra = 3;
1526
1527   seq_param->pcm_sample_bit_depth_luma_minus1 = 0;
1528   seq_param->pcm_sample_bit_depth_chroma_minus1 = 0;
1529   seq_param->log2_min_pcm_luma_coding_block_size_minus3 = 0;
1530   seq_param->log2_max_pcm_luma_coding_block_size_minus3 = 0;
1531
1532   /* VUI parameters are always set, at least for timing_info (framerate) */
1533   seq_param->vui_parameters_present_flag = TRUE;
1534   if (seq_param->vui_parameters_present_flag) {
1535     seq_param->vui_fields.bits.aspect_ratio_info_present_flag = TRUE;
1536     if (seq_param->vui_fields.bits.aspect_ratio_info_present_flag) {
1537       const GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
1538       seq_param->aspect_ratio_idc = 0xff;
1539       seq_param->sar_width = GST_VIDEO_INFO_PAR_N (vip);
1540       seq_param->sar_height = GST_VIDEO_INFO_PAR_D (vip);
1541     }
1542     seq_param->vui_fields.bits.bitstream_restriction_flag = FALSE;
1543     seq_param->vui_fields.bits.vui_timing_info_present_flag = TRUE;
1544     if (seq_param->vui_fields.bits.vui_timing_info_present_flag) {
1545       seq_param->vui_num_units_in_tick = GST_VAAPI_ENCODER_FPS_D (encoder);
1546       seq_param->vui_time_scale = GST_VAAPI_ENCODER_FPS_N (encoder);
1547     }
1548   }
1549   return TRUE;
1550 }
1551
1552 /* Fills in VA picture parameter buffer */
1553 static gboolean
1554 fill_picture (GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture,
1555     GstVaapiCodedBuffer * codedbuf, GstVaapiSurfaceProxy * surface)
1556 {
1557   VAEncPictureParameterBufferHEVC *const pic_param = picture->param;
1558   GstVaapiH265RefPool *const ref_pool = &encoder->ref_pool;
1559   GstVaapiEncoderH265Ref *ref_pic;
1560   GList *reflist;
1561   guint i;
1562   guint8 nal_unit_type, no_output_of_prior_pics_flag = 0;
1563
1564   memset (pic_param, 0, sizeof (VAEncPictureParameterBufferHEVC));
1565
1566   pic_param->decoded_curr_pic.picture_id =
1567       GST_VAAPI_SURFACE_PROXY_SURFACE_ID (surface);
1568   pic_param->decoded_curr_pic.pic_order_cnt = picture->poc;
1569   pic_param->decoded_curr_pic.flags = 0;
1570
1571   i = 0;
1572   if (picture->type != GST_VAAPI_PICTURE_TYPE_I) {
1573     for (reflist = g_queue_peek_head_link (&ref_pool->ref_list);
1574         reflist; reflist = g_list_next (reflist)) {
1575       ref_pic = reflist->data;
1576       g_assert (ref_pic && ref_pic->pic &&
1577           GST_VAAPI_SURFACE_PROXY_SURFACE_ID (ref_pic->pic) != VA_INVALID_ID);
1578
1579       pic_param->reference_frames[i].picture_id =
1580           GST_VAAPI_SURFACE_PROXY_SURFACE_ID (ref_pic->pic);
1581       pic_param->reference_frames[i].pic_order_cnt = ref_pic->poc;
1582       ++i;
1583     }
1584     g_assert (i <= 15 && i <= ref_pool->max_ref_frames);
1585   }
1586   for (; i < 15; ++i) {
1587     pic_param->reference_frames[i].picture_id = VA_INVALID_SURFACE;
1588     pic_param->reference_frames[i].flags = 0;
1589   }
1590   pic_param->coded_buf = GST_VAAPI_OBJECT_ID (codedbuf);
1591
1592   /* slice_temporal_mvp_enable_flag == FALSE */
1593   pic_param->collocated_ref_pic_index = 0xFF;
1594
1595   pic_param->last_picture = 0;
1596   pic_param->pic_init_qp = encoder->init_qp;
1597   pic_param->num_ref_idx_l0_default_active_minus1 =
1598       (ref_pool->max_reflist0_count ? (ref_pool->max_reflist0_count - 1) : 0);
1599   pic_param->num_ref_idx_l1_default_active_minus1 =
1600       (ref_pool->max_reflist1_count ? (ref_pool->max_reflist1_count - 1) : 0);
1601
1602   if (!get_nal_unit_type (picture, &nal_unit_type))
1603     return FALSE;
1604   pic_param->nal_unit_type = nal_unit_type;
1605
1606   /* set picture fields */
1607   pic_param->pic_fields.value = 0;
1608   pic_param->pic_fields.bits.idr_pic_flag =
1609       GST_VAAPI_ENC_PICTURE_IS_IDR (picture);
1610   pic_param->pic_fields.bits.coding_type = picture->type;
1611   if (picture->type != GST_VAAPI_PICTURE_TYPE_B)
1612     pic_param->pic_fields.bits.reference_pic_flag = TRUE;
1613   pic_param->pic_fields.bits.sign_data_hiding_enabled_flag = FALSE;
1614   pic_param->pic_fields.bits.transform_skip_enabled_flag = TRUE;
1615   /* it seems driver requires enablement of cu_qp_delta_enabled_flag
1616    * to modifiy QP values in CBR mode encoding */
1617   pic_param->pic_fields.bits.cu_qp_delta_enabled_flag =
1618       GST_VAAPI_ENCODER_RATE_CONTROL (encoder) != GST_VAAPI_RATECONTROL_CQP;
1619
1620   pic_param->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag = TRUE;
1621
1622   if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
1623     no_output_of_prior_pics_flag = 1;
1624   pic_param->pic_fields.bits.no_output_of_prior_pics_flag =
1625       no_output_of_prior_pics_flag;
1626
1627   return TRUE;
1628 }
1629
1630 /* Adds slice headers to picture */
1631 static gboolean
1632 add_slice_headers (GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture,
1633     GstVaapiEncoderH265Ref ** reflist_0, guint reflist_0_count,
1634     GstVaapiEncoderH265Ref ** reflist_1, guint reflist_1_count)
1635 {
1636   VAEncSliceParameterBufferHEVC *slice_param;
1637   GstVaapiEncSlice *slice;
1638   guint slice_of_ctus, slice_mod_ctus, cur_slice_ctus;
1639   guint ctu_size;
1640   guint ctu_width_round_factor;
1641   guint last_ctu_index;
1642   guint i_slice, i_ref;
1643
1644   g_assert (picture);
1645
1646   ctu_size = encoder->ctu_width * encoder->ctu_height;
1647
1648   g_assert (encoder->num_slices && encoder->num_slices < ctu_size);
1649   slice_of_ctus = ctu_size / encoder->num_slices;
1650   slice_mod_ctus = ctu_size % encoder->num_slices;
1651   last_ctu_index = 0;
1652
1653   for (i_slice = 0;
1654       i_slice < encoder->num_slices && (last_ctu_index < ctu_size); ++i_slice) {
1655     cur_slice_ctus = slice_of_ctus;
1656     if (slice_mod_ctus) {
1657       ++cur_slice_ctus;
1658       --slice_mod_ctus;
1659     }
1660
1661     /* Work-around for satisfying the VA-Intel driver.
1662      * The driver only support multi slice begin from row start address */
1663     ctu_width_round_factor =
1664         encoder->ctu_width - (cur_slice_ctus % encoder->ctu_width);
1665     cur_slice_ctus += ctu_width_round_factor;
1666     if ((last_ctu_index + cur_slice_ctus) > ctu_size)
1667       cur_slice_ctus = ctu_size - last_ctu_index;
1668
1669     slice = GST_VAAPI_ENC_SLICE_NEW (HEVC, encoder);
1670     g_assert (slice && slice->param_id != VA_INVALID_ID);
1671     slice_param = slice->param;
1672
1673     memset (slice_param, 0, sizeof (VAEncSliceParameterBufferHEVC));
1674     if (i_slice == 0) {
1675       encoder->first_slice_segment_in_pic_flag = TRUE;
1676       slice_param->slice_segment_address = 0;
1677     } else {
1678       encoder->first_slice_segment_in_pic_flag = FALSE;
1679       slice_param->slice_segment_address = last_ctu_index;
1680     }
1681     slice_param->num_ctu_in_slice = cur_slice_ctus;
1682     slice_param->slice_type = h265_get_slice_type (picture->type);
1683     slice_param->slice_pic_parameter_set_id = 0;
1684
1685     slice_param->slice_fields.bits.num_ref_idx_active_override_flag =
1686         reflist_0_count || reflist_1_count;
1687     if (picture->type != GST_VAAPI_PICTURE_TYPE_I && reflist_0_count > 0)
1688       slice_param->num_ref_idx_l0_active_minus1 = reflist_0_count - 1;
1689     else
1690       slice_param->num_ref_idx_l0_active_minus1 = 0;
1691     if (picture->type == GST_VAAPI_PICTURE_TYPE_B && reflist_1_count > 0)
1692       slice_param->num_ref_idx_l1_active_minus1 = reflist_1_count - 1;
1693     else
1694       slice_param->num_ref_idx_l1_active_minus1 = 0;
1695
1696     i_ref = 0;
1697     if (picture->type != GST_VAAPI_PICTURE_TYPE_I) {
1698       for (; i_ref < reflist_0_count; ++i_ref) {
1699         slice_param->ref_pic_list0[i_ref].picture_id =
1700             GST_VAAPI_SURFACE_PROXY_SURFACE_ID (reflist_0[i_ref]->pic);
1701         slice_param->ref_pic_list0[i_ref].pic_order_cnt = reflist_0[i_ref]->poc;
1702       }
1703     }
1704     for (; i_ref < G_N_ELEMENTS (slice_param->ref_pic_list0); ++i_ref) {
1705       slice_param->ref_pic_list0[i_ref].picture_id = VA_INVALID_SURFACE;
1706       slice_param->ref_pic_list0[i_ref].flags = 0;
1707     }
1708
1709     i_ref = 0;
1710     if (picture->type == GST_VAAPI_PICTURE_TYPE_B) {
1711       for (; i_ref < reflist_1_count; ++i_ref) {
1712         slice_param->ref_pic_list1[i_ref].picture_id =
1713             GST_VAAPI_SURFACE_PROXY_SURFACE_ID (reflist_1[i_ref]->pic);
1714         slice_param->ref_pic_list1[i_ref].pic_order_cnt = reflist_1[i_ref]->poc;
1715       }
1716     }
1717     for (; i_ref < G_N_ELEMENTS (slice_param->ref_pic_list1); ++i_ref) {
1718       slice_param->ref_pic_list1[i_ref].picture_id = VA_INVALID_SURFACE;
1719       slice_param->ref_pic_list1[i_ref].flags = 0;
1720     }
1721
1722     slice_param->max_num_merge_cand = 5;        /* MaxNumMergeCand  */
1723     slice_param->slice_qp_delta = encoder->init_qp - encoder->min_qp;
1724
1725     slice_param->slice_fields.bits.
1726         slice_loop_filter_across_slices_enabled_flag = TRUE;
1727
1728     /* set calculation for next slice */
1729     last_ctu_index += cur_slice_ctus;
1730
1731     if ((i_slice == encoder->num_slices - 1) || (last_ctu_index == ctu_size))
1732       slice_param->slice_fields.bits.last_slice_of_pic_flag = 1;
1733
1734     if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
1735             VA_ENC_PACKED_HEADER_SLICE)
1736         && !add_packed_slice_header (encoder, picture, slice))
1737       goto error_create_packed_slice_hdr;
1738
1739     gst_vaapi_enc_picture_add_slice (picture, slice);
1740     gst_vaapi_codec_object_replace (&slice, NULL);
1741   }
1742   if (i_slice < encoder->num_slices)
1743     GST_WARNING
1744         ("Using less number of slices than requested, Number of slices per pictures is %d",
1745         i_slice);
1746   g_assert (last_ctu_index == ctu_size);
1747
1748   return TRUE;
1749
1750 error_create_packed_slice_hdr:
1751   {
1752     GST_ERROR ("failed to create packed slice header buffer");
1753     gst_vaapi_codec_object_replace (&slice, NULL);
1754     return FALSE;
1755   }
1756 }
1757
1758 /* Generates and submits SPS header accordingly into the bitstream */
1759 static gboolean
1760 ensure_sequence (GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture)
1761 {
1762   GstVaapiEncSequence *sequence = NULL;
1763
1764   /* submit an SPS header before every new I-frame, if codec config changed */
1765   if (!encoder->config_changed || picture->type != GST_VAAPI_PICTURE_TYPE_I)
1766     return TRUE;
1767
1768   sequence = GST_VAAPI_ENC_SEQUENCE_NEW (HEVC, encoder);
1769   if (!sequence || !fill_sequence (encoder, sequence))
1770     goto error_create_seq_param;
1771
1772   /* add packed vps and sps headers */
1773   if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
1774           VA_ENC_PACKED_HEADER_SEQUENCE)
1775       && !(add_packed_vps_header (encoder, picture, sequence)
1776           && add_packed_sequence_header (encoder, picture, sequence))) {
1777     goto error_create_packed_seq_hdr;
1778   }
1779
1780   if (sequence) {
1781     gst_vaapi_enc_picture_set_sequence (picture, sequence);
1782     gst_vaapi_codec_object_replace (&sequence, NULL);
1783   }
1784
1785   encoder->config_changed = FALSE;
1786   return TRUE;
1787
1788   /* ERRORS */
1789 error_create_seq_param:
1790   {
1791     GST_ERROR ("failed to create sequence parameter buffer (SPS)");
1792     gst_vaapi_codec_object_replace (&sequence, NULL);
1793     return FALSE;
1794   }
1795 error_create_packed_seq_hdr:
1796   {
1797     GST_ERROR ("failed to create packed sequence header buffer");
1798     gst_vaapi_codec_object_replace (&sequence, NULL);
1799     return FALSE;
1800   }
1801 }
1802
1803 static gboolean
1804 ensure_control_rate_params (GstVaapiEncoderH265 * encoder)
1805 {
1806   if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CQP)
1807     return TRUE;
1808
1809   /* RateControl params */
1810   GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).bits_per_second =
1811       encoder->bitrate_bits;
1812   /* CPB (Coded picture buffer) length in milliseconds, which could be
1813    * provided as a property */
1814   GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).window_size = encoder->cpb_length;
1815   GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).initial_qp = encoder->init_qp;
1816   GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).min_qp = encoder->min_qp;
1817
1818   /* HRD params */
1819   fill_hrd_params (encoder, &GST_VAAPI_ENCODER_VA_HRD (encoder));
1820
1821   return TRUE;
1822 }
1823
1824 static gboolean
1825 ensure_misc_params (GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture)
1826 {
1827   GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
1828
1829   if (!gst_vaapi_encoder_ensure_param_control_rate (base_encoder, picture))
1830     return FALSE;
1831   if (!gst_vaapi_encoder_ensure_param_quality_level (base_encoder, picture))
1832     return FALSE;
1833   return TRUE;
1834 }
1835
1836 /* Generates and submits PPS header accordingly into the bitstream */
1837 static gboolean
1838 ensure_picture (GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture,
1839     GstVaapiCodedBufferProxy * codedbuf_proxy, GstVaapiSurfaceProxy * surface)
1840 {
1841   GstVaapiCodedBuffer *const codedbuf =
1842       GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf_proxy);
1843   gboolean res = FALSE;
1844
1845   res = fill_picture (encoder, picture, codedbuf, surface);
1846
1847   if (!res)
1848     return FALSE;
1849
1850   if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
1851       (GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
1852           VA_ENC_PACKED_HEADER_PICTURE)
1853       && !add_packed_picture_header (encoder, picture)) {
1854     GST_ERROR ("set picture packed header failed");
1855     return FALSE;
1856   }
1857   return TRUE;
1858 }
1859
1860
1861 /* Generates slice headers */
1862 static gboolean
1863 ensure_slices (GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture)
1864 {
1865   GstVaapiEncoderH265Ref *reflist_0[15];
1866   GstVaapiEncoderH265Ref *reflist_1[15];
1867   GstVaapiH265RefPool *const ref_pool = &encoder->ref_pool;
1868   guint reflist_0_count = 0, reflist_1_count = 0;
1869
1870   g_assert (picture);
1871
1872   if (picture->type != GST_VAAPI_PICTURE_TYPE_I &&
1873       !reference_list_init (encoder, picture,
1874           reflist_0, &reflist_0_count, reflist_1, &reflist_1_count)) {
1875     GST_ERROR ("reference list reorder failed");
1876     return FALSE;
1877   }
1878
1879   g_assert (reflist_0_count + reflist_1_count <= ref_pool->max_ref_frames);
1880   if (reflist_0_count > ref_pool->max_reflist0_count)
1881     reflist_0_count = ref_pool->max_reflist0_count;
1882   if (reflist_1_count > ref_pool->max_reflist1_count)
1883     reflist_1_count = ref_pool->max_reflist1_count;
1884
1885   if (!add_slice_headers (encoder, picture,
1886           reflist_0, reflist_0_count, reflist_1, reflist_1_count))
1887     return FALSE;
1888
1889   return TRUE;
1890 }
1891
1892 /* Normalizes bitrate (and CPB size) for HRD conformance */
1893 static void
1894 ensure_bitrate_hrd (GstVaapiEncoderH265 * encoder)
1895 {
1896   GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
1897   guint bitrate, cpb_size;
1898
1899   if (!base_encoder->bitrate) {
1900     encoder->bitrate_bits = 0;
1901     return;
1902   }
1903
1904   /* Round down bitrate. This is a hard limit mandated by the user */
1905   g_assert (SX_BITRATE >= 6);
1906   bitrate = (base_encoder->bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
1907   if (bitrate != encoder->bitrate_bits) {
1908     GST_DEBUG ("HRD bitrate: %u bits/sec", bitrate);
1909     encoder->bitrate_bits = bitrate;
1910     encoder->config_changed = TRUE;
1911   }
1912
1913   /* Round up CPB size. This is an HRD compliance detail */
1914   g_assert (SX_CPB_SIZE >= 4);
1915   cpb_size = gst_util_uint64_scale (bitrate, encoder->cpb_length, 1000) &
1916       ~((1U << SX_CPB_SIZE) - 1);
1917   if (cpb_size != encoder->cpb_length_bits) {
1918     GST_DEBUG ("HRD CPB size: %u bits", cpb_size);
1919     encoder->cpb_length_bits = cpb_size;
1920     encoder->config_changed = TRUE;
1921   }
1922 }
1923
1924 /* Estimates a good enough bitrate if none was supplied */
1925 static void
1926 ensure_bitrate (GstVaapiEncoderH265 * encoder)
1927 {
1928   GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
1929
1930   switch (GST_VAAPI_ENCODER_RATE_CONTROL (encoder)) {
1931     case GST_VAAPI_RATECONTROL_CBR:
1932     case GST_VAAPI_RATECONTROL_VBR:
1933       if (!base_encoder->bitrate) {
1934         /* FIXME: Provide better estimation */
1935         /* Using a 1/6 compression ratio */
1936         /* 12 bits per pixel for YUV420 */
1937         guint64 factor;
1938
1939         factor = (guint64) encoder->luma_width * encoder->luma_height * 12 / 6;
1940         base_encoder->bitrate =
1941             gst_util_uint64_scale (factor, GST_VAAPI_ENCODER_FPS_N (encoder),
1942             GST_VAAPI_ENCODER_FPS_D (encoder)) / 1000;
1943         GST_INFO ("target bitrate computed to %u kbps", base_encoder->bitrate);
1944       }
1945       break;
1946     default:
1947       base_encoder->bitrate = 0;
1948       break;
1949   }
1950   ensure_bitrate_hrd (encoder);
1951 }
1952
1953 /* Constructs profile, tier and level information based on user-defined limits */
1954 static GstVaapiEncoderStatus
1955 ensure_profile_tier_level (GstVaapiEncoderH265 * encoder)
1956 {
1957   const GstVaapiProfile profile = encoder->profile;
1958   const GstVaapiTierH265 tier = encoder->tier;
1959   const GstVaapiLevelH265 level = encoder->level;
1960
1961   ensure_tuning (encoder);
1962
1963   if (!ensure_profile (encoder) || !ensure_profile_limits (encoder))
1964     return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
1965
1966   /* Check HW constraints */
1967   if (!ensure_hw_profile_limits (encoder))
1968     return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
1969   if (encoder->profile_idc > encoder->hw_max_profile_idc)
1970     return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
1971
1972   /* ensure tier */
1973   if (!ensure_tier (encoder))
1974     return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
1975
1976   /* Ensure bitrate if not set already and derive the right level to use */
1977   ensure_bitrate (encoder);
1978
1979   if (!ensure_level (encoder))
1980     return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
1981
1982   if (encoder->profile != profile || encoder->level != level
1983       || encoder->tier != tier) {
1984     GST_DEBUG ("selected %s profile at tier %s and level %s",
1985         gst_vaapi_utils_h265_get_profile_string (encoder->profile),
1986         gst_vaapi_utils_h265_get_tier_string (encoder->tier),
1987         gst_vaapi_utils_h265_get_level_string (encoder->level));
1988     encoder->config_changed = TRUE;
1989   }
1990   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
1991 }
1992
1993 static void
1994 reset_properties (GstVaapiEncoderH265 * encoder)
1995 {
1996   GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
1997   GstVaapiH265ReorderPool *reorder_pool;
1998   GstVaapiH265RefPool *ref_pool;
1999   guint ctu_size;
2000
2001   if (encoder->idr_period < base_encoder->keyframe_period)
2002     encoder->idr_period = base_encoder->keyframe_period;
2003   if (encoder->idr_period > MAX_IDR_PERIOD)
2004     encoder->idr_period = MAX_IDR_PERIOD;
2005
2006   if (encoder->min_qp > encoder->init_qp ||
2007       (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CQP &&
2008           encoder->min_qp < encoder->init_qp))
2009     encoder->min_qp = encoder->init_qp;
2010
2011   ctu_size = encoder->ctu_width * encoder->ctu_height;
2012   g_assert (gst_vaapi_encoder_ensure_num_slices (base_encoder, encoder->profile,
2013           GST_VAAPI_ENTRYPOINT_SLICE_ENCODE, (ctu_size + 1) / 2,
2014           &encoder->num_slices));
2015
2016   gst_vaapi_encoder_ensure_max_num_ref_frames (base_encoder, encoder->profile,
2017       GST_VAAPI_ENTRYPOINT_SLICE_ENCODE);
2018
2019   if (base_encoder->max_num_ref_frames_1 < 1 && encoder->num_bframes > 0) {
2020     GST_WARNING ("Disabling b-frame since the driver doesn't support it");
2021     encoder->num_bframes = 0;
2022   }
2023
2024   if (encoder->num_ref_frames > base_encoder->max_num_ref_frames_0) {
2025     GST_INFO ("Lowering the number of reference frames to %d",
2026         base_encoder->max_num_ref_frames_0);
2027     encoder->num_ref_frames = base_encoder->max_num_ref_frames_0;
2028   }
2029
2030   if (encoder->num_bframes > (base_encoder->keyframe_period + 1) / 2)
2031     encoder->num_bframes = (base_encoder->keyframe_period + 1) / 2;
2032
2033   if (encoder->num_bframes > 0 && GST_VAAPI_ENCODER_FPS_N (encoder) > 0)
2034     encoder->cts_offset = gst_util_uint64_scale (GST_SECOND,
2035         GST_VAAPI_ENCODER_FPS_D (encoder), GST_VAAPI_ENCODER_FPS_N (encoder));
2036   else
2037     encoder->cts_offset = 0;
2038
2039   /* init max_poc */
2040   encoder->log2_max_pic_order_cnt =
2041       h265_get_log2_max_pic_order_cnt (encoder->idr_period);
2042   g_assert (encoder->log2_max_pic_order_cnt >= 4);
2043   encoder->max_pic_order_cnt = (1 << encoder->log2_max_pic_order_cnt);
2044   encoder->idr_num = 0;
2045
2046   /* Only Supporting a maximum of two reference frames */
2047   if (encoder->num_bframes) {
2048     encoder->max_dec_pic_buffering = encoder->num_ref_frames + 2;
2049     encoder->max_num_reorder_pics = 1;
2050   } else {
2051     encoder->max_dec_pic_buffering = encoder->num_ref_frames + 1;
2052     encoder->max_num_reorder_pics = 0;
2053   }
2054
2055   ref_pool = &encoder->ref_pool;
2056   ref_pool->max_reflist0_count = encoder->num_ref_frames;
2057   ref_pool->max_reflist1_count = encoder->num_bframes > 0;
2058   ref_pool->max_ref_frames = ref_pool->max_reflist0_count
2059       + ref_pool->max_reflist1_count;
2060
2061   reorder_pool = &encoder->reorder_pool;
2062   reorder_pool->frame_index = 0;
2063 }
2064
2065 static GstVaapiEncoderStatus
2066 gst_vaapi_encoder_h265_encode (GstVaapiEncoder * base_encoder,
2067     GstVaapiEncPicture * picture, GstVaapiCodedBufferProxy * codedbuf)
2068 {
2069   GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
2070   GstVaapiEncoderStatus ret = GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
2071   GstVaapiSurfaceProxy *reconstruct = NULL;
2072
2073   reconstruct = gst_vaapi_encoder_create_surface (base_encoder);
2074
2075   g_assert (GST_VAAPI_SURFACE_PROXY_SURFACE (reconstruct));
2076
2077   if (!ensure_sequence (encoder, picture))
2078     goto error;
2079   if (!ensure_misc_params (encoder, picture))
2080     goto error;
2081   if (!ensure_picture (encoder, picture, codedbuf, reconstruct))
2082     goto error;
2083   if (!ensure_slices (encoder, picture))
2084     goto error;
2085   if (!gst_vaapi_enc_picture_encode (picture))
2086     goto error;
2087
2088   if (!reference_list_update (encoder, picture, reconstruct))
2089     goto error;
2090
2091   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2092
2093   /* ERRORS */
2094 error:
2095   {
2096     if (reconstruct)
2097       gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder),
2098           reconstruct);
2099     return ret;
2100   }
2101 }
2102
2103 static GstVaapiEncoderStatus
2104 gst_vaapi_encoder_h265_flush (GstVaapiEncoder * base_encoder)
2105 {
2106   GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
2107   GstVaapiH265ReorderPool *reorder_pool;
2108   GstVaapiEncPicture *pic;
2109
2110   reorder_pool = &encoder->reorder_pool;
2111   reorder_pool->frame_index = 0;
2112   reorder_pool->cur_present_index = 0;
2113
2114   while (!g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
2115     pic = (GstVaapiEncPicture *)
2116         g_queue_pop_head (&reorder_pool->reorder_frame_list);
2117     gst_vaapi_enc_picture_unref (pic);
2118   }
2119   g_queue_clear (&reorder_pool->reorder_frame_list);
2120
2121   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2122 }
2123
2124 /* Generate "codec-data" buffer */
2125 static GstVaapiEncoderStatus
2126 gst_vaapi_encoder_h265_get_codec_data (GstVaapiEncoder * base_encoder,
2127     GstBuffer ** out_buffer_ptr)
2128 {
2129   GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
2130   const guint32 configuration_version = 0x01;
2131   const guint32 nal_length_size = 4;
2132   GstMapInfo vps_info, sps_info, pps_info;
2133   GstBitWriter bs;
2134   GstBuffer *buffer;
2135   guint min_spatial_segmentation_idc = 0;
2136   guint num_arrays = 3;
2137
2138   if (!encoder->vps_data || !encoder->sps_data || !encoder->pps_data)
2139     return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER;
2140   if (gst_buffer_get_size (encoder->sps_data) < 4)
2141     return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER;
2142
2143   if (!gst_buffer_map (encoder->vps_data, &vps_info, GST_MAP_READ))
2144     goto error_map_vps_buffer;
2145
2146   if (!gst_buffer_map (encoder->sps_data, &sps_info, GST_MAP_READ))
2147     goto error_map_sps_buffer;
2148
2149   if (!gst_buffer_map (encoder->pps_data, &pps_info, GST_MAP_READ))
2150     goto error_map_pps_buffer;
2151
2152   /* Header */
2153   gst_bit_writer_init (&bs,
2154       (vps_info.size + sps_info.size + pps_info.size + 64) * 8);
2155   WRITE_UINT32 (&bs, configuration_version, 8);
2156   WRITE_UINT32 (&bs, sps_info.data[4], 8);      /* profile_space | tier_flag | profile_idc */
2157   WRITE_UINT32 (&bs, sps_info.data[5], 32);     /* profile_compatibility_flag [0-31] */
2158   /* progressive_source_flag | interlaced_source_flag | non_packed_constraint_flag |
2159    * frame_only_constraint_flag | reserved_zero_bits[0-27] */
2160   WRITE_UINT32 (&bs, sps_info.data[9], 32);
2161   WRITE_UINT32 (&bs, sps_info.data[13], 16);    /* reserved_zero_bits [28-43] */
2162   WRITE_UINT32 (&bs, sps_info.data[15], 8);     /* level_idc */
2163   WRITE_UINT32 (&bs, 0x0f, 4);  /* 1111 */
2164   WRITE_UINT32 (&bs, min_spatial_segmentation_idc, 12); /* min_spatial_segmentation_idc */
2165   WRITE_UINT32 (&bs, 0x3f, 6);  /* 111111 */
2166   WRITE_UINT32 (&bs, 0x00, 2);  /* parallelismType */
2167   WRITE_UINT32 (&bs, 0x3f, 6);  /* 111111 */
2168   WRITE_UINT32 (&bs, 0x01, 2);  /* chroma_format_idc */
2169   WRITE_UINT32 (&bs, 0x1f, 5);  /* 11111 */
2170   WRITE_UINT32 (&bs, 0x01, 3);  /* bit_depth_luma_minus8 */
2171   WRITE_UINT32 (&bs, 0x1f, 5);  /* 11111 */
2172   WRITE_UINT32 (&bs, 0x01, 3);  /* bit_depth_chroma_minus8 */
2173   WRITE_UINT32 (&bs, 0x00, 16); /* avgFramerate */
2174   WRITE_UINT32 (&bs, 0x00, 2);  /* constatnFramerate */
2175   WRITE_UINT32 (&bs, 0x00, 3);  /* numTemporalLayers */
2176   WRITE_UINT32 (&bs, 0x00, 1);  /* temporalIdNested */
2177   WRITE_UINT32 (&bs, nal_length_size - 1, 2);   /* lengthSizeMinusOne */
2178   WRITE_UINT32 (&bs, 0x00, 8);  /* numOfArrays */
2179
2180   WRITE_UINT32 (&bs, num_arrays, 8);    /* numOfArrays */
2181
2182   /* Write VPS */
2183   WRITE_UINT32 (&bs, 0x00, 1);  /* array_completeness */
2184   WRITE_UINT32 (&bs, 0x00, 1);  /* reserved zero */
2185   WRITE_UINT32 (&bs, GST_H265_NAL_VPS, 6);      /* Nal_unit_type */
2186   WRITE_UINT32 (&bs, 0x01, 16); /* numNalus, VPS count = 1 */
2187   g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
2188   /* Write Nal unit length and data of VPS */
2189   if (!gst_vaapi_utils_h26x_write_nal_unit (&bs, vps_info.data, vps_info.size))
2190     goto nal_to_byte_stream_error;
2191
2192   /* Write SPS */
2193   WRITE_UINT32 (&bs, 0x00, 1);  /* array_completeness */
2194   WRITE_UINT32 (&bs, 0x00, 1);  /* reserved zero */
2195   WRITE_UINT32 (&bs, GST_H265_NAL_SPS, 6);      /* Nal_unit_type */
2196   WRITE_UINT32 (&bs, 0x01, 16); /* numNalus, SPS count = 1 */
2197   g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
2198   /* Write Nal unit length and data of SPS */
2199   if (!gst_vaapi_utils_h26x_write_nal_unit (&bs, sps_info.data, sps_info.size))
2200     goto nal_to_byte_stream_error;
2201
2202   /* Write PPS */
2203   WRITE_UINT32 (&bs, 0x00, 1);  /* array_completeness */
2204   WRITE_UINT32 (&bs, 0x00, 1);  /* reserved zero */
2205   WRITE_UINT32 (&bs, GST_H265_NAL_PPS, 6);      /* Nal_unit_type */
2206   WRITE_UINT32 (&bs, 0x01, 16); /* numNalus, PPS count = 1 */
2207   /* Write Nal unit length and data of PPS */
2208   if (!gst_vaapi_utils_h26x_write_nal_unit (&bs, pps_info.data, pps_info.size))
2209     goto nal_to_byte_stream_error;
2210
2211   gst_buffer_unmap (encoder->pps_data, &pps_info);
2212   gst_buffer_unmap (encoder->sps_data, &sps_info);
2213   gst_buffer_unmap (encoder->vps_data, &vps_info);
2214
2215   buffer = gst_buffer_new_wrapped (GST_BIT_WRITER_DATA (&bs),
2216       GST_BIT_WRITER_BIT_SIZE (&bs) / 8);
2217   if (!buffer)
2218     goto error_alloc_buffer;
2219   *out_buffer_ptr = buffer;
2220
2221   gst_bit_writer_clear (&bs, FALSE);
2222   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2223
2224   /* ERRORS */
2225 bs_error:
2226   {
2227     GST_ERROR ("failed to write codec-data");
2228     gst_buffer_unmap (encoder->vps_data, &vps_info);
2229     gst_buffer_unmap (encoder->sps_data, &sps_info);
2230     gst_buffer_unmap (encoder->pps_data, &pps_info);
2231     gst_bit_writer_clear (&bs, TRUE);
2232     return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
2233   }
2234 nal_to_byte_stream_error:
2235   {
2236     GST_ERROR ("failed to write nal unit");
2237     gst_buffer_unmap (encoder->vps_data, &vps_info);
2238     gst_buffer_unmap (encoder->sps_data, &sps_info);
2239     gst_buffer_unmap (encoder->pps_data, &pps_info);
2240     gst_bit_writer_clear (&bs, TRUE);
2241     return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
2242   }
2243 error_map_vps_buffer:
2244   {
2245     GST_ERROR ("failed to map VPS packed header");
2246     return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2247   }
2248 error_map_sps_buffer:
2249   {
2250     GST_ERROR ("failed to map SPS packed header");
2251     return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2252   }
2253 error_map_pps_buffer:
2254   {
2255     GST_ERROR ("failed to map PPS packed header");
2256     gst_buffer_unmap (encoder->sps_data, &sps_info);
2257     return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2258   }
2259 error_alloc_buffer:
2260   {
2261     GST_ERROR ("failed to allocate codec-data buffer");
2262     gst_bit_writer_clear (&bs, TRUE);
2263     return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2264   }
2265 }
2266
2267 /* TODO */
2268 /* The re-ordering algorithm is similar to what we implemented for
2269  * h264 encoder. But We could have a better algorithm for hevc encoder
2270  * by having B-frames as reference pictures */
2271 static GstVaapiEncoderStatus
2272 gst_vaapi_encoder_h265_reordering (GstVaapiEncoder * base_encoder,
2273     GstVideoCodecFrame * frame, GstVaapiEncPicture ** output)
2274 {
2275   GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
2276   GstVaapiH265ReorderPool *reorder_pool = NULL;
2277   GstVaapiEncPicture *picture;
2278   gboolean is_idr = FALSE;
2279
2280   *output = NULL;
2281
2282   reorder_pool = &encoder->reorder_pool;
2283
2284   if (!frame) {
2285     if (reorder_pool->reorder_state != GST_VAAPI_ENC_H265_REORD_DUMP_FRAMES)
2286       return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
2287
2288     /* reorder_state = GST_VAAPI_ENC_H265_REORD_DUMP_FRAMES
2289        dump B frames from queue, sometime, there may also have P frame or I frame */
2290     g_assert (encoder->num_bframes > 0);
2291     g_return_val_if_fail (!g_queue_is_empty (&reorder_pool->reorder_frame_list),
2292         GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN);
2293     picture = g_queue_pop_head (&reorder_pool->reorder_frame_list);
2294     g_assert (picture);
2295     if (g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
2296       reorder_pool->reorder_state = GST_VAAPI_ENC_H265_REORD_WAIT_FRAMES;
2297     }
2298     goto end;
2299   }
2300
2301   /* new frame coming */
2302   picture = GST_VAAPI_ENC_PICTURE_NEW (HEVC, encoder, frame);
2303   if (!picture) {
2304     GST_WARNING ("create H265 picture failed, frame timestamp:%"
2305         GST_TIME_FORMAT, GST_TIME_ARGS (frame->pts));
2306     return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2307   }
2308   ++reorder_pool->cur_present_index;
2309   picture->poc = ((reorder_pool->cur_present_index * 1) %
2310       encoder->max_pic_order_cnt);
2311
2312   is_idr = (reorder_pool->frame_index == 0 ||
2313       reorder_pool->frame_index >= encoder->idr_period);
2314
2315   /* check key frames */
2316   if (is_idr || GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame) ||
2317       (reorder_pool->frame_index %
2318           GST_VAAPI_ENCODER_KEYFRAME_PERIOD (encoder)) == 0) {
2319     ++reorder_pool->frame_index;
2320
2321     /* b frame enabled,  check queue of reorder_frame_list */
2322     if (encoder->num_bframes
2323         && !g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
2324       GstVaapiEncPicture *p_pic;
2325
2326       p_pic = g_queue_pop_tail (&reorder_pool->reorder_frame_list);
2327       set_p_frame (p_pic, encoder);
2328       g_queue_foreach (&reorder_pool->reorder_frame_list,
2329           (GFunc) set_b_frame, encoder);
2330       set_key_frame (picture, encoder, is_idr);
2331       g_queue_push_tail (&reorder_pool->reorder_frame_list, picture);
2332       picture = p_pic;
2333       reorder_pool->reorder_state = GST_VAAPI_ENC_H265_REORD_DUMP_FRAMES;
2334     } else {                    /* no b frames in queue */
2335       set_key_frame (picture, encoder, is_idr);
2336       g_assert (g_queue_is_empty (&reorder_pool->reorder_frame_list));
2337       if (encoder->num_bframes)
2338         reorder_pool->reorder_state = GST_VAAPI_ENC_H265_REORD_WAIT_FRAMES;
2339     }
2340     goto end;
2341   }
2342
2343   /* new p/b frames coming */
2344   ++reorder_pool->frame_index;
2345   if (reorder_pool->reorder_state == GST_VAAPI_ENC_H265_REORD_WAIT_FRAMES &&
2346       g_queue_get_length (&reorder_pool->reorder_frame_list) <
2347       encoder->num_bframes) {
2348     g_queue_push_tail (&reorder_pool->reorder_frame_list, picture);
2349     return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
2350   }
2351
2352   set_p_frame (picture, encoder);
2353
2354   if (reorder_pool->reorder_state == GST_VAAPI_ENC_H265_REORD_WAIT_FRAMES) {
2355     g_queue_foreach (&reorder_pool->reorder_frame_list, (GFunc) set_b_frame,
2356         encoder);
2357     reorder_pool->reorder_state = GST_VAAPI_ENC_H265_REORD_DUMP_FRAMES;
2358     g_assert (!g_queue_is_empty (&reorder_pool->reorder_frame_list));
2359   }
2360
2361 end:
2362   g_assert (picture);
2363   frame = picture->frame;
2364   if (GST_CLOCK_TIME_IS_VALID (frame->pts))
2365     frame->pts += encoder->cts_offset;
2366   *output = picture;
2367
2368   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2369 }
2370
2371 static GstVaapiEncoderStatus
2372 set_context_info (GstVaapiEncoder * base_encoder)
2373 {
2374   GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
2375   GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
2376   const guint DEFAULT_SURFACES_COUNT = 3;
2377
2378   /* FIXME: Using only a rough approximation for bitstream headers.
2379    * Not taken into account: ScalingList, RefPicListModification,
2380    * PredWeightTable */
2381   /* Maximum sizes for common headers (in bits) */
2382   enum
2383   {
2384     MAX_PROFILE_TIER_LEVEL_SIZE = 684,
2385     MAX_VPS_HDR_SIZE = 13781,
2386     MAX_SPS_HDR_SIZE = 615,
2387     MAX_SHORT_TERM_REFPICSET_SIZE = 55,
2388     MAX_VUI_PARAMS_SIZE = 267,
2389     MAX_HRD_PARAMS_SIZE = 8196,
2390     MAX_PPS_HDR_SIZE = 274,
2391     MAX_SLICE_HDR_SIZE = 33660
2392   };
2393
2394   /* Account for VPS header */
2395   base_encoder->codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_VPS_HDR_SIZE +
2396       MAX_PROFILE_TIER_LEVEL_SIZE + MAX_HRD_PARAMS_SIZE) / 8;
2397
2398   /* Account for SPS header */
2399   base_encoder->codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE +
2400       MAX_PROFILE_TIER_LEVEL_SIZE + 64 * MAX_SHORT_TERM_REFPICSET_SIZE +
2401       MAX_VUI_PARAMS_SIZE + MAX_HRD_PARAMS_SIZE) / 8;
2402
2403   /* Account for PPS header */
2404   base_encoder->codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8;
2405
2406   /* Account for slice header */
2407   base_encoder->codedbuf_size += encoder->num_slices * (4 +
2408       GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE + MAX_SHORT_TERM_REFPICSET_SIZE) / 8);
2409
2410   if (!ensure_hw_profile (encoder))
2411     return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
2412
2413   base_encoder->num_ref_frames = (encoder->num_ref_frames
2414       + (encoder->num_bframes > 0 ? 1 : 0) + DEFAULT_SURFACES_COUNT);
2415
2416   /* Only YUV 4:2:0 formats are supported for now. */
2417   base_encoder->codedbuf_size += GST_ROUND_UP_32 (vip->width) *
2418       GST_ROUND_UP_32 (vip->height) * 3 / 2;
2419
2420   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2421 }
2422
2423 static GstVaapiEncoderStatus
2424 gst_vaapi_encoder_h265_reconfigure (GstVaapiEncoder * base_encoder)
2425 {
2426   GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
2427   GstVaapiEncoderStatus status;
2428   guint luma_width, luma_height;
2429
2430   luma_width = GST_VAAPI_ENCODER_WIDTH (encoder);
2431   luma_height = GST_VAAPI_ENCODER_HEIGHT (encoder);
2432
2433   if (luma_width != encoder->luma_width || luma_height != encoder->luma_height) {
2434     GST_DEBUG ("resolution: %d %d", GST_VAAPI_ENCODER_WIDTH (encoder),
2435         GST_VAAPI_ENCODER_HEIGHT (encoder));
2436     encoder->luma_width = GST_ROUND_UP_32 (luma_width);
2437     encoder->luma_height = GST_ROUND_UP_32 (luma_height);
2438     encoder->ctu_width = (encoder->luma_width + 31) / 32;
2439     encoder->ctu_height = (encoder->luma_height + 31) / 32;
2440     encoder->config_changed = TRUE;
2441
2442     /* Frame Cropping */
2443     if ((GST_VAAPI_ENCODER_WIDTH (encoder) & 31) ||
2444         (GST_VAAPI_ENCODER_HEIGHT (encoder) & 31)) {
2445       static const guint SubWidthC[] = { 1, 2, 2, 1 };
2446       static const guint SubHeightC[] = { 1, 2, 1, 1 };
2447       encoder->conformance_window_flag = 1;
2448       encoder->conf_win_left_offset = 0;
2449       encoder->conf_win_right_offset =
2450           (encoder->luma_width -
2451           GST_VAAPI_ENCODER_WIDTH (encoder)) / SubWidthC[1];
2452       encoder->conf_win_top_offset = 0;
2453       encoder->conf_win_bottom_offset =
2454           (encoder->luma_height -
2455           GST_VAAPI_ENCODER_HEIGHT (encoder)) / SubHeightC[1];
2456     }
2457   }
2458
2459   status = ensure_profile_tier_level (encoder);
2460   if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
2461     return status;
2462
2463   reset_properties (encoder);
2464   ensure_control_rate_params (encoder);
2465   return set_context_info (base_encoder);
2466 }
2467
2468 static gboolean
2469 gst_vaapi_encoder_h265_init (GstVaapiEncoder * base_encoder)
2470 {
2471   GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
2472   GstVaapiH265ReorderPool *reorder_pool;
2473   GstVaapiH265RefPool *ref_pool;
2474
2475   encoder->conformance_window_flag = 0;
2476   encoder->num_slices = 1;
2477
2478   /* re-ordering  list initialize */
2479   reorder_pool = &encoder->reorder_pool;
2480   g_queue_init (&reorder_pool->reorder_frame_list);
2481   reorder_pool->reorder_state = GST_VAAPI_ENC_H265_REORD_NONE;
2482   reorder_pool->frame_index = 0;
2483   reorder_pool->cur_present_index = 0;
2484
2485   /* reference list info initialize */
2486   ref_pool = &encoder->ref_pool;
2487   g_queue_init (&ref_pool->ref_list);
2488   ref_pool->max_ref_frames = 0;
2489   ref_pool->max_reflist0_count = 1;
2490   ref_pool->max_reflist1_count = 1;
2491
2492   return TRUE;
2493 }
2494
2495 static void
2496 gst_vaapi_encoder_h265_finalize (GstVaapiEncoder * base_encoder)
2497 {
2498   /*free private buffers */
2499   GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
2500   GstVaapiEncPicture *pic;
2501   GstVaapiEncoderH265Ref *ref;
2502   GstVaapiH265RefPool *ref_pool;
2503   GstVaapiH265ReorderPool *reorder_pool;
2504
2505   gst_buffer_replace (&encoder->vps_data, NULL);
2506   gst_buffer_replace (&encoder->sps_data, NULL);
2507   gst_buffer_replace (&encoder->pps_data, NULL);
2508
2509   /* reference list info de-init */
2510   ref_pool = &encoder->ref_pool;
2511   while (!g_queue_is_empty (&ref_pool->ref_list)) {
2512     ref = (GstVaapiEncoderH265Ref *) g_queue_pop_head (&ref_pool->ref_list);
2513     reference_pic_free (encoder, ref);
2514   }
2515   g_queue_clear (&ref_pool->ref_list);
2516
2517   /* re-ordering  list initialize */
2518   reorder_pool = &encoder->reorder_pool;
2519   while (!g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
2520     pic = (GstVaapiEncPicture *)
2521         g_queue_pop_head (&reorder_pool->reorder_frame_list);
2522     gst_vaapi_enc_picture_unref (pic);
2523   }
2524   g_queue_clear (&reorder_pool->reorder_frame_list);
2525 }
2526
2527 static GstVaapiEncoderStatus
2528 gst_vaapi_encoder_h265_set_property (GstVaapiEncoder * base_encoder,
2529     gint prop_id, const GValue * value)
2530 {
2531   GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
2532
2533   switch (prop_id) {
2534     case GST_VAAPI_ENCODER_H265_PROP_MAX_BFRAMES:
2535       encoder->num_bframes = g_value_get_uint (value);
2536       break;
2537     case GST_VAAPI_ENCODER_H265_PROP_INIT_QP:
2538       encoder->init_qp = g_value_get_uint (value);
2539       break;
2540     case GST_VAAPI_ENCODER_H265_PROP_MIN_QP:
2541       encoder->min_qp = g_value_get_uint (value);
2542       break;
2543     case GST_VAAPI_ENCODER_H265_PROP_NUM_SLICES:
2544       encoder->num_slices = g_value_get_uint (value);
2545       break;
2546     case GST_VAAPI_ENCODER_H265_PROP_CPB_LENGTH:
2547       encoder->cpb_length = g_value_get_uint (value);
2548       break;
2549     case GST_VAAPI_ENCODER_H265_PROP_NUM_REF_FRAMES:
2550       encoder->num_ref_frames = g_value_get_uint (value);
2551       break;
2552     default:
2553       return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER;
2554   }
2555   return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2556 }
2557
2558 GST_VAAPI_ENCODER_DEFINE_CLASS_DATA (H265);
2559
2560 static inline const GstVaapiEncoderClass *
2561 gst_vaapi_encoder_h265_class (void)
2562 {
2563   static const GstVaapiEncoderClass GstVaapiEncoderH265Class = {
2564     GST_VAAPI_ENCODER_CLASS_INIT (H265, h265),
2565     .set_property = gst_vaapi_encoder_h265_set_property,
2566     .get_codec_data = gst_vaapi_encoder_h265_get_codec_data
2567   };
2568   return &GstVaapiEncoderH265Class;
2569 }
2570
2571 /**
2572  * gst_vaapi_encoder_h265_new:
2573  * @display: a #GstVaapiDisplay
2574  *
2575  * Creates a new #GstVaapiEncoder for H.265 encoding. Note that the
2576  * only supported output stream format is "byte-stream" format.
2577  *
2578  * Return value: the newly allocated #GstVaapiEncoder object
2579  */
2580 GstVaapiEncoder *
2581 gst_vaapi_encoder_h265_new (GstVaapiDisplay * display)
2582 {
2583   return gst_vaapi_encoder_new (gst_vaapi_encoder_h265_class (), display);
2584 }
2585
2586 /**
2587  * gst_vaapi_encoder_h265_get_default_properties:
2588  *
2589  * Determines the set of common and H.265 specific encoder properties.
2590  * The caller owns an extra reference to the resulting array of
2591  * #GstVaapiEncoderPropInfo elements, so it shall be released with
2592  * g_ptr_array_unref() after usage.
2593  *
2594  * Return value: the set of encoder properties for #GstVaapiEncoderH265,
2595  *   or %NULL if an error occurred.
2596  */
2597 GPtrArray *
2598 gst_vaapi_encoder_h265_get_default_properties (void)
2599 {
2600   const GstVaapiEncoderClass *const klass = gst_vaapi_encoder_h265_class ();
2601   GPtrArray *props;
2602
2603   props = gst_vaapi_encoder_properties_get_default (klass);
2604   if (!props)
2605     return NULL;
2606
2607   /**
2608    * GstVaapiEncoderH265:max-bframes:
2609    *
2610    * The number of B-frames between I and P.
2611    */
2612   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
2613       GST_VAAPI_ENCODER_H265_PROP_MAX_BFRAMES,
2614       g_param_spec_uint ("max-bframes",
2615           "Max B-Frames", "Number of B-frames between I and P", 0, 10, 0,
2616           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2617
2618   /**
2619    * GstVaapiEncoderH265:refs:
2620    *
2621    * The number of reference frames.
2622    * If B frame is encoded, it will add 1 reference frame more.
2623    */
2624   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
2625       GST_VAAPI_ENCODER_H265_PROP_NUM_REF_FRAMES,
2626       g_param_spec_uint ("refs",
2627           "Number of Reference Frames", "Number of reference frames", 1, 3, 1,
2628           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2629
2630   /**
2631    * GstVaapiEncoderH265:init-qp:
2632    *
2633    * The initial quantizer value.
2634    */
2635   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
2636       GST_VAAPI_ENCODER_H265_PROP_INIT_QP,
2637       g_param_spec_uint ("init-qp",
2638           "Initial QP", "Initial quantizer value", 1, 51, 26,
2639           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2640
2641   /**
2642    * GstVaapiEncoderH265:min-qp:
2643    *
2644    * The minimum quantizer value.
2645    */
2646   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
2647       GST_VAAPI_ENCODER_H265_PROP_MIN_QP,
2648       g_param_spec_uint ("min-qp",
2649           "Minimum QP", "Minimum quantizer value", 1, 51, 1,
2650           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2651
2652   /* FIXME: there seems to be issues with multi-slice encoding */
2653   /**
2654    * GstVaapiEncoderH265:num-slices:
2655    *
2656    * The number of slices per frame.
2657    */
2658   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
2659       GST_VAAPI_ENCODER_H265_PROP_NUM_SLICES,
2660       g_param_spec_uint ("num-slices",
2661           "Number of Slices",
2662           "Number of slices per frame",
2663           1, 200, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2664
2665   /**
2666    * GstVaapiEncoderH265:cpb-length:
2667    *
2668    * The size of the CPB buffer in milliseconds.
2669    */
2670   GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
2671       GST_VAAPI_ENCODER_H265_PROP_CPB_LENGTH,
2672       g_param_spec_uint ("cpb-length",
2673           "CPB Length", "Length of the CPB buffer in milliseconds",
2674           1, 10000, DEFAULT_CPB_LENGTH,
2675           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
2676
2677   return props;
2678 }
2679
2680 /**
2681  * gst_vaapi_encoder_h265_set_max_profile:
2682  * @encoder: a #GstVaapiEncoderH265
2683  * @profile: an H.265 #GstVaapiProfile
2684  *
2685  * Notifies the @encoder to use coding tools from the supplied
2686  * @profile at most.
2687  *
2688  * This means that if the minimal profile derived to
2689  * support the specified coding tools is greater than this @profile,
2690  * then an error is returned when the @encoder is configured.
2691  *
2692  * Return value: %TRUE on success
2693  */
2694 gboolean
2695 gst_vaapi_encoder_h265_set_max_profile (GstVaapiEncoderH265 * encoder,
2696     GstVaapiProfile profile)
2697 {
2698   guint8 profile_idc;
2699
2700   g_return_val_if_fail (encoder != NULL, FALSE);
2701   g_return_val_if_fail (profile != GST_VAAPI_PROFILE_UNKNOWN, FALSE);
2702
2703   if (gst_vaapi_profile_get_codec (profile) != GST_VAAPI_CODEC_H265)
2704     return FALSE;
2705
2706   profile_idc = gst_vaapi_utils_h265_get_profile_idc (profile);
2707   if (!profile_idc)
2708     return FALSE;
2709
2710   encoder->max_profile_idc = profile_idc;
2711   return TRUE;
2712 }
2713
2714 /**
2715  * gst_vaapi_encoder_h265_get_profile_tier_level:
2716  * @encoder: a #GstVaapiEncoderH265
2717  * @out_profile_ptr: return location for the #GstVaapiProfile
2718  * @out_level_ptr: return location for the #GstVaapiLevelH265
2719  * @out_tier_ptr: return location for the #GstVaapiTierH265
2720  *
2721  * Queries the H.265 @encoder for the active profile and level. That
2722  * information is only constructed and valid after the encoder is
2723  * configured, i.e. after the gst_vaapi_encoder_set_codec_state()
2724  * function is called.
2725  *
2726  * Return value: %TRUE on success
2727  */
2728 gboolean
2729 gst_vaapi_encoder_h265_get_profile_tier_level (GstVaapiEncoderH265 * encoder,
2730     GstVaapiProfile * out_profile_ptr, GstVaapiTierH265 * out_tier_ptr,
2731     GstVaapiLevelH265 * out_level_ptr)
2732 {
2733   g_return_val_if_fail (encoder != NULL, FALSE);
2734
2735   if (!encoder->profile || !encoder->tier || !encoder->level)
2736     return FALSE;
2737
2738   if (out_profile_ptr)
2739     *out_profile_ptr = encoder->profile;
2740   if (out_level_ptr)
2741     *out_level_ptr = encoder->level;
2742   if (out_tier_ptr)
2743     *out_tier_ptr = encoder->tier;
2744
2745   return TRUE;
2746 }