2 * gstvaapiencoder_h265.c - H.265 encoder
4 * Copyright (C) 2015 Intel Corporation
5 * Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
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.
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.
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
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"
37 #include "gstvaapidebug.h"
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 GST_VAAPI_RATECONTROL_MASK (ICQ) | \
45 GST_VAAPI_RATECONTROL_MASK (QVBR))
47 /* Supported set of tuning options, within this implementation */
48 #define SUPPORTED_TUNE_OPTIONS \
49 (GST_VAAPI_ENCODER_TUNE_MASK (NONE) | \
50 GST_VAAPI_ENCODER_TUNE_MASK (LOW_POWER))
52 /* Supported set of VA packed headers, within this implementation */
53 #define SUPPORTED_PACKED_HEADERS \
54 (VA_ENC_PACKED_HEADER_SEQUENCE | \
55 VA_ENC_PACKED_HEADER_PICTURE | \
56 VA_ENC_PACKED_HEADER_SLICE)
60 GstVaapiSurfaceProxy *pic;
62 } GstVaapiEncoderH265Ref;
66 GST_VAAPI_ENC_H265_REORD_NONE = 0,
67 GST_VAAPI_ENC_H265_REORD_DUMP_FRAMES = 1,
68 GST_VAAPI_ENC_H265_REORD_WAIT_FRAMES = 2
69 } GstVaapiEncH265ReorderState;
71 typedef struct _GstVaapiH265RefPool
75 guint max_reflist0_count;
76 guint max_reflist1_count;
77 } GstVaapiH265RefPool;
79 typedef struct _GstVaapiH265ReorderPool
81 GQueue reorder_frame_list;
84 guint cur_present_index;
85 } GstVaapiH265ReorderPool;
87 /* ------------------------------------------------------------------------- */
88 /* --- H.265 Encoder --- */
89 /* ------------------------------------------------------------------------- */
91 struct _GstVaapiEncoderH265
93 GstVaapiEncoder parent_instance;
95 GstVaapiProfile profile;
96 GstVaapiTierH265 tier;
97 GstVaapiLevelH265 level;
98 GstVaapiEntrypoint entrypoint;
100 GArray *allowed_profiles;
111 guint32 ctu_width; /* CTU == Coding Tree Unit */
115 guint32 quality_factor;
116 GstClockTime cts_offset;
117 gboolean config_changed;
118 /* Always need two reference lists for inter frame */
120 guint32 num_tile_cols;
121 guint32 num_tile_rows;
122 /* CTUs start address used in stream pack */
123 guint32 *tile_slice_address;
124 /* CTUs in this slice */
125 guint32 *tile_slice_ctu_num;
126 /* map the tile_slice_address to CTU start address in picture,
127 which is used by VA API. */
128 guint32 *tile_slice_address_map;
130 /* maximum required size of the decoded picture buffer */
131 guint32 max_dec_pic_buffering;
132 /* maximum allowed number of pictures that can precede any picture in
133 * the CVS in decoding order and follow that picture in output order */
134 guint32 max_num_reorder_pics;
137 guint32 max_pic_order_cnt;
138 guint32 log2_max_pic_order_cnt;
140 guint num_ref_frames;
146 guint bitrate_bits; // bitrate (bits)
147 guint cpb_length; // length of CPB buffer (ms)
148 guint cpb_length_bits; // length of CPB buffer (bits)
149 GstVaapiEncoderMbbrc mbbrc; // macroblock bitrate control
152 guint conformance_window_flag:1;
153 guint32 conf_win_left_offset;
154 guint32 conf_win_right_offset;
155 guint32 conf_win_top_offset;
156 guint32 conf_win_bottom_offset;
158 GstVaapiH265RefPool ref_pool;
159 GstVaapiH265ReorderPool reorder_pool;
160 guint first_slice_segment_in_pic_flag:1;
161 guint sps_temporal_mvp_enabled_flag:1;
162 guint sample_adaptive_offset_enabled_flag:1;
165 static inline gboolean
166 _poc_greater_than (guint poc1, guint poc2, guint max_poc)
168 return (((poc1 - poc2) & (max_poc - 1)) < max_poc / 2);
171 /* Get slice_type value for H.265 specification */
173 h265_get_slice_type (GstVaapiPictureType type)
176 case GST_VAAPI_PICTURE_TYPE_I:
177 return GST_H265_I_SLICE;
178 case GST_VAAPI_PICTURE_TYPE_P:
179 return GST_H265_P_SLICE;
180 case GST_VAAPI_PICTURE_TYPE_B:
181 return GST_H265_B_SLICE;
189 h265_is_scc (GstVaapiEncoderH265 * encoder)
191 if (encoder->profile == GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN ||
192 encoder->profile == GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN_10 ||
193 encoder->profile == GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN_444 ||
194 encoder->profile == GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN_444_10)
201 h265_is_tile_enabled (GstVaapiEncoderH265 * encoder)
203 return encoder->num_tile_cols * encoder->num_tile_rows > 1;
206 /* Get log2_max_pic_order_cnt value for H.265 specification */
208 h265_get_log2_max_pic_order_cnt (guint num)
220 /* must be greater than 4 */
224 /* Write the NAL unit header */
226 bs_write_nal_header (GstBitWriter * bs, guint32 nal_unit_type)
228 guint8 nuh_layer_id = 0;
229 guint8 nuh_temporal_id_plus1 = 1;
231 WRITE_UINT32 (bs, 0, 1);
232 WRITE_UINT32 (bs, nal_unit_type, 6);
233 WRITE_UINT32 (bs, nuh_layer_id, 6);
234 WRITE_UINT32 (bs, nuh_temporal_id_plus1, 3);
241 GST_WARNING ("failed to write NAL unit header");
246 /* Write the NAL unit trailing bits */
248 bs_write_trailing_bits (GstBitWriter * bs)
250 if (!gst_bit_writer_put_bits_uint32 (bs, 1, 1))
252 gst_bit_writer_align_bytes_unchecked (bs, 0);
258 GST_WARNING ("failed to write NAL unit trailing bits");
263 /* Write profile_tier_level() */
265 bs_write_profile_tier_level (GstBitWriter * bs,
266 const VAEncSequenceParameterBufferHEVC * seq_param, GstVaapiProfile profile)
270 /* general_profile_space */
271 WRITE_UINT32 (bs, 0, 2);
272 /* general_tier_flag */
273 WRITE_UINT32 (bs, seq_param->general_tier_flag, 1);
274 /* general_profile_idc */
275 WRITE_UINT32 (bs, seq_param->general_profile_idc, 5);
277 /* general_profile_compatibility_flag[0] */
278 WRITE_UINT32 (bs, 0, 1);
279 /* general_profile_compatibility_flag[1] */
280 if (seq_param->general_profile_idc == 1 /* Main profile */
281 /* In A.3.4, NOTE: When general_profile_compatibility_flag[ 3 ] is equal
282 to 1, general_profile_compatibility_flag[ 1 ] and
283 general_profile_compatibility_flag[ 2 ] should also be equal to 1. */
284 || seq_param->general_profile_idc == 3 /* Main Still Picture profile */
286 WRITE_UINT32 (bs, 1, 1);
288 WRITE_UINT32 (bs, 0, 1);
290 /* general_profile_compatibility_flag[2] */
292 /* In A.3.2, NOTE: When general_profile_compatibility_flag[ 1 ] is equal
293 to 1, general_profile_compatibility_flag[ 2 ] should also be equal to
295 seq_param->general_profile_idc == 1 /* Main profile */
296 || seq_param->general_profile_idc == 2 /* Main 10 profile */
297 /* In A.3.4, NOTE: When general_profile_compatibility_flag[ 3 ] is equal
298 to 1, general_profile_compatibility_flag[ 1 ] and
299 general_profile_compatibility_flag[ 2 ] should also be equal to 1. */
300 || seq_param->general_profile_idc == 3 /* Main Still Picture profile */
302 WRITE_UINT32 (bs, 1, 1);
304 WRITE_UINT32 (bs, 0, 1);
306 /* general_profile_compatibility_flag[3] */
307 if (seq_param->general_profile_idc == 3) {
308 WRITE_UINT32 (bs, 1, 1);
310 WRITE_UINT32 (bs, 0, 1);
313 /* general_profile_compatibility_flag[4] */
314 if (seq_param->general_profile_idc == 4) { /* format range extensions profiles */
315 WRITE_UINT32 (bs, 1, 1);
317 WRITE_UINT32 (bs, 0, 1);
320 /* general_profile_compatibility_flag[5~8] */
321 WRITE_UINT32 (bs, 0, 4);
323 /* general_profile_compatibility_flag[9] */
324 if (seq_param->general_profile_idc == 9) { /* screen content coding profiles */
325 WRITE_UINT32 (bs, 1, 1);
327 WRITE_UINT32 (bs, 0, 1);
330 /* general_profile_compatibility_flag[10~32] */
331 WRITE_UINT32 (bs, 0, 22);
333 /* general_progressive_source_flag */
334 WRITE_UINT32 (bs, 1, 1);
335 /* general_interlaced_source_flag */
336 WRITE_UINT32 (bs, 0, 1);
337 /* general_non_packed_constraint_flag */
338 WRITE_UINT32 (bs, 0, 1);
339 /* general_frame_only_constraint_flag */
340 WRITE_UINT32 (bs, 1, 1);
342 /* additional indications specified for general_profile_idc from 4~10 */
343 if (seq_param->general_profile_idc == 4) {
344 /* In A.3.5, Format range extensions profiles.
345 Just support main444, main444-10 and main422-10 profile now, may add
346 more profiles when needed. */
348 case GST_VAAPI_PROFILE_H265_MAIN_444:
349 /* max_12bit_constraint_flag */
350 WRITE_UINT32 (bs, 1, 1);
351 /* max_10bit_constraint_flag */
352 WRITE_UINT32 (bs, 1, 1);
353 /* max_8bit_constraint_flag */
354 WRITE_UINT32 (bs, 1, 1);
355 /* max_422chroma_constraint_flag */
356 WRITE_UINT32 (bs, 0, 1);
357 /* max_420chroma_constraint_flag */
358 WRITE_UINT32 (bs, 0, 1);
359 /* max_monochrome_constraint_flag */
360 WRITE_UINT32 (bs, 0, 1);
361 /* intra_constraint_flag */
362 WRITE_UINT32 (bs, 0, 1);
363 /* one_picture_only_constraint_flag */
364 WRITE_UINT32 (bs, 0, 1);
365 /* lower_bit_rate_constraint_flag */
366 WRITE_UINT32 (bs, 1, 1);
368 case GST_VAAPI_PROFILE_H265_MAIN_444_10:
369 /* max_12bit_constraint_flag */
370 WRITE_UINT32 (bs, 1, 1);
371 /* max_10bit_constraint_flag */
372 WRITE_UINT32 (bs, 1, 1);
373 /* max_8bit_constraint_flag */
374 WRITE_UINT32 (bs, 0, 1);
375 /* max_422chroma_constraint_flag */
376 WRITE_UINT32 (bs, 0, 1);
377 /* max_420chroma_constraint_flag */
378 WRITE_UINT32 (bs, 0, 1);
379 /* max_monochrome_constraint_flag */
380 WRITE_UINT32 (bs, 0, 1);
381 /* intra_constraint_flag */
382 WRITE_UINT32 (bs, 0, 1);
383 /* one_picture_only_constraint_flag */
384 WRITE_UINT32 (bs, 0, 1);
385 /* lower_bit_rate_constraint_flag */
386 WRITE_UINT32 (bs, 1, 1);
388 case GST_VAAPI_PROFILE_H265_MAIN_422_10:
389 /* max_12bit_constraint_flag */
390 WRITE_UINT32 (bs, 1, 1);
391 /* max_10bit_constraint_flag */
392 WRITE_UINT32 (bs, 1, 1);
393 /* max_8bit_constraint_flag */
394 WRITE_UINT32 (bs, 0, 1);
395 /* max_422chroma_constraint_flag */
396 WRITE_UINT32 (bs, 1, 1);
397 /* max_420chroma_constraint_flag */
398 WRITE_UINT32 (bs, 0, 1);
399 /* max_monochrome_constraint_flag */
400 WRITE_UINT32 (bs, 0, 1);
401 /* intra_constraint_flag */
402 WRITE_UINT32 (bs, 0, 1);
403 /* one_picture_only_constraint_flag */
404 WRITE_UINT32 (bs, 0, 1);
405 /* lower_bit_rate_constraint_flag */
406 WRITE_UINT32 (bs, 1, 1);
408 case GST_VAAPI_PROFILE_H265_MAIN12:
409 /* max_12bit_constraint_flag */
410 WRITE_UINT32 (bs, 1, 1);
411 /* max_10bit_constraint_flag */
412 WRITE_UINT32 (bs, 0, 1);
413 /* max_8bit_constraint_flag */
414 WRITE_UINT32 (bs, 0, 1);
415 /* max_422chroma_constraint_flag */
416 WRITE_UINT32 (bs, 1, 1);
417 /* max_420chroma_constraint_flag */
418 WRITE_UINT32 (bs, 1, 1);
419 /* max_monochrome_constraint_flag */
420 WRITE_UINT32 (bs, 0, 1);
421 /* intra_constraint_flag */
422 WRITE_UINT32 (bs, 0, 1);
423 /* one_picture_only_constraint_flag */
424 WRITE_UINT32 (bs, 0, 1);
425 /* lower_bit_rate_constraint_flag */
426 WRITE_UINT32 (bs, 1, 1);
429 GST_WARNING ("do not support the profile: %s of range extensions",
430 gst_vaapi_profile_get_va_name (profile));
434 /* general_reserved_zero_34bits */
435 for (i = 0; i < 34; i++)
436 WRITE_UINT32 (bs, 0, 1);
437 } else if (seq_param->general_profile_idc == 9) {
438 /* In A.3.7, Screen content coding extensions profiles. */
440 case GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN:
441 /* max_12bit_constraint_flag */
442 WRITE_UINT32 (bs, 1, 1);
443 /* max_10bit_constraint_flag */
444 WRITE_UINT32 (bs, 1, 1);
445 /* max_8bit_constraint_flag */
446 WRITE_UINT32 (bs, 1, 1);
447 /* max_422chroma_constraint_flag */
448 WRITE_UINT32 (bs, 1, 1);
449 /* max_420chroma_constraint_flag */
450 WRITE_UINT32 (bs, 1, 1);
451 /* max_monochrome_constraint_flag */
452 WRITE_UINT32 (bs, 0, 1);
453 /* intra_constraint_flag */
454 WRITE_UINT32 (bs, 0, 1);
455 /* one_picture_only_constraint_flag */
456 WRITE_UINT32 (bs, 0, 1);
457 /* lower_bit_rate_constraint_flag */
458 WRITE_UINT32 (bs, 1, 1);
459 /* general_max_14bit_constraint_flag */
460 WRITE_UINT32 (bs, 1, 1);
462 case GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN_10:
463 /* max_12bit_constraint_flag */
464 WRITE_UINT32 (bs, 1, 1);
465 /* max_10bit_constraint_flag */
466 WRITE_UINT32 (bs, 1, 1);
467 /* max_8bit_constraint_flag */
468 WRITE_UINT32 (bs, 0, 1);
469 /* max_422chroma_constraint_flag */
470 WRITE_UINT32 (bs, 1, 1);
471 /* max_420chroma_constraint_flag */
472 WRITE_UINT32 (bs, 1, 1);
473 /* max_monochrome_constraint_flag */
474 WRITE_UINT32 (bs, 0, 1);
475 /* intra_constraint_flag */
476 WRITE_UINT32 (bs, 0, 1);
477 /* one_picture_only_constraint_flag */
478 WRITE_UINT32 (bs, 0, 1);
479 /* lower_bit_rate_constraint_flag */
480 WRITE_UINT32 (bs, 1, 1);
481 /* general_max_14bit_constraint_flag */
482 WRITE_UINT32 (bs, 1, 1);
484 case GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN_444:
485 /* max_12bit_constraint_flag */
486 WRITE_UINT32 (bs, 1, 1);
487 /* max_10bit_constraint_flag */
488 WRITE_UINT32 (bs, 1, 1);
489 /* max_8bit_constraint_flag */
490 WRITE_UINT32 (bs, 1, 1);
491 /* max_422chroma_constraint_flag */
492 WRITE_UINT32 (bs, 0, 1);
493 /* max_420chroma_constraint_flag */
494 WRITE_UINT32 (bs, 0, 1);
495 /* max_monochrome_constraint_flag */
496 WRITE_UINT32 (bs, 0, 1);
497 /* intra_constraint_flag */
498 WRITE_UINT32 (bs, 0, 1);
499 /* one_picture_only_constraint_flag */
500 WRITE_UINT32 (bs, 0, 1);
501 /* lower_bit_rate_constraint_flag */
502 WRITE_UINT32 (bs, 1, 1);
503 /* general_max_14bit_constraint_flag */
504 WRITE_UINT32 (bs, 1, 1);
506 case GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN_444_10:
507 /* max_12bit_constraint_flag */
508 WRITE_UINT32 (bs, 1, 1);
509 /* max_10bit_constraint_flag */
510 WRITE_UINT32 (bs, 1, 1);
511 /* max_8bit_constraint_flag */
512 WRITE_UINT32 (bs, 0, 1);
513 /* max_422chroma_constraint_flag */
514 WRITE_UINT32 (bs, 0, 1);
515 /* max_420chroma_constraint_flag */
516 WRITE_UINT32 (bs, 0, 1);
517 /* max_monochrome_constraint_flag */
518 WRITE_UINT32 (bs, 0, 1);
519 /* intra_constraint_flag */
520 WRITE_UINT32 (bs, 0, 1);
521 /* one_picture_only_constraint_flag */
522 WRITE_UINT32 (bs, 0, 1);
523 /* lower_bit_rate_constraint_flag */
524 WRITE_UINT32 (bs, 1, 1);
525 /* general_max_14bit_constraint_flag */
526 WRITE_UINT32 (bs, 1, 1);
529 GST_WARNING ("do not support the profile: %s of screen"
530 " content coding extensions",
531 gst_vaapi_profile_get_va_name (profile));
535 /* general_reserved_zero_33bits */
536 for (i = 0; i < 33; i++)
537 WRITE_UINT32 (bs, 0, 1);
539 /* general_reserved_zero_43bits */
540 for (i = 0; i < 43; i++)
541 WRITE_UINT32 (bs, 0, 1);
544 /* general_inbld_flag */
545 WRITE_UINT32 (bs, 0, 1);
546 /* general_level_idc */
547 WRITE_UINT32 (bs, seq_param->general_level_idc, 8);
554 GST_WARNING ("failed to write Profile Tier Level");
559 /* Write an VPS NAL unit */
561 bs_write_vps_data (GstBitWriter * bs, GstVaapiEncoderH265 * encoder,
562 GstVaapiEncPicture * picture,
563 const VAEncSequenceParameterBufferHEVC * seq_param, GstVaapiProfile profile)
565 guint32 video_parameter_set_id = 0;
566 guint32 vps_max_layers_minus1 = 0;
567 guint32 vps_max_sub_layers_minus1 = 0;
568 guint32 vps_temporal_id_nesting_flag = 1;
569 guint32 vps_sub_layer_ordering_info_present_flag = 0;
570 guint32 vps_max_latency_increase_plus1 = 0;
571 guint32 vps_max_layer_id = 0;
572 guint32 vps_num_layer_sets_minus1 = 0;
573 guint32 vps_timing_info_present_flag = 0;
574 guint32 vps_extension_flag = 0;
575 guint32 vps_base_layer_internal_flag = 1;
576 guint32 vps_base_layer_available_flag = 1;
578 /* video_parameter_set_id */
579 WRITE_UINT32 (bs, video_parameter_set_id, 4);
580 /* vps_base_layer_internal_flag */
581 WRITE_UINT32 (bs, vps_base_layer_internal_flag, 1);
582 /* vps_base_layer_available_flag */
583 WRITE_UINT32 (bs, vps_base_layer_available_flag, 1);
584 /* vps_max_layers_minus1 */
585 WRITE_UINT32 (bs, vps_max_layers_minus1, 6);
586 /* vps_max_sub_layers_minus1 */
587 WRITE_UINT32 (bs, vps_max_sub_layers_minus1, 3);
588 /* vps_temporal_id_nesting_flag */
589 WRITE_UINT32 (bs, vps_temporal_id_nesting_flag, 1);
590 /* vps_reserved_0xffff_16bits */
591 WRITE_UINT32 (bs, 0xffff, 16);
593 /* profile_tier_level */
594 bs_write_profile_tier_level (bs, seq_param, profile);
596 /* vps_sub_layer_ordering_info_present_flag */
597 WRITE_UINT32 (bs, vps_sub_layer_ordering_info_present_flag, 1);
598 /* vps_max_dec_pic_buffering_minus1 */
599 WRITE_UE (bs, encoder->max_dec_pic_buffering - 1);
600 /* vps_max_num_reorder_pics */
601 WRITE_UE (bs, encoder->max_num_reorder_pics);
602 /* vps_max_latency_increase_plus1 */
603 WRITE_UE (bs, vps_max_latency_increase_plus1);
604 /* vps_max_layer_id */
605 WRITE_UINT32 (bs, vps_max_layer_id, 6);
606 /* vps_num_layer_sets_minus1 */
607 WRITE_UE (bs, vps_num_layer_sets_minus1);
608 /* vps_timing_info_present_flag */
609 WRITE_UINT32 (bs, vps_timing_info_present_flag, 1);
610 /* vps_extension_flag */
611 WRITE_UINT32 (bs, vps_extension_flag, 1);
618 GST_WARNING ("failed to write VPS NAL unit");
624 bs_write_vps (GstBitWriter * bs, GstVaapiEncoderH265 * encoder,
625 GstVaapiEncPicture * picture,
626 const VAEncSequenceParameterBufferHEVC * seq_param, GstVaapiProfile profile)
628 if (!bs_write_vps_data (bs, encoder, picture, seq_param, profile))
631 /* rbsp_trailing_bits */
632 bs_write_trailing_bits (bs);
637 /* Write an SPS NAL unit */
639 bs_write_sps_data (GstBitWriter * bs, GstVaapiEncoderH265 * encoder,
640 GstVaapiEncPicture * picture,
641 const VAEncSequenceParameterBufferHEVC * seq_param, GstVaapiProfile profile,
642 GstVaapiRateControl rate_control, const VAEncMiscParameterHRD * hrd_params)
644 guint32 video_parameter_set_id = 0;
645 guint32 max_sub_layers_minus1 = 0;
646 guint32 temporal_id_nesting_flag = 1;
647 guint32 separate_colour_plane_flag = 0;
648 guint32 seq_parameter_set_id = 0;
649 guint32 sps_sub_layer_ordering_info_present_flag = 0;
650 guint32 sps_max_latency_increase_plus1 = 0;
651 guint32 num_short_term_ref_pic_sets = 0;
652 guint32 long_term_ref_pics_present_flag = 0;
653 guint32 sps_extension_flag = 0;
654 guint32 nal_hrd_parameters_present_flag = 0;
655 guint maxNumSubLayers = 1, i;
656 guint32 cbr_flag = rate_control == GST_VAAPI_RATECONTROL_CBR ? 1 : 0;
658 /* video_parameter_set_id */
659 WRITE_UINT32 (bs, video_parameter_set_id, 4);
660 /* max_sub_layers_minus1 */
661 WRITE_UINT32 (bs, max_sub_layers_minus1, 3);
662 /* temporal_id_nesting_flag */
663 WRITE_UINT32 (bs, temporal_id_nesting_flag, 1);
665 /* profile_tier_level */
666 bs_write_profile_tier_level (bs, seq_param, profile);
668 /* seq_parameter_set_id */
669 WRITE_UE (bs, seq_parameter_set_id);
670 /* chroma_format_idc = 1, 4:2:0 */
671 WRITE_UE (bs, seq_param->seq_fields.bits.chroma_format_idc);
672 if (seq_param->seq_fields.bits.chroma_format_idc == 3)
673 /* if( chroma_format_idc == 3 ) separate_colour_plane_flag */
674 WRITE_UINT32 (bs, separate_colour_plane_flag, 1);
675 /* pic_width_in_luma_samples */
676 WRITE_UE (bs, seq_param->pic_width_in_luma_samples);
677 /* pic_height_in_luma_samples */
678 WRITE_UE (bs, seq_param->pic_height_in_luma_samples);
680 /* conformance_window_flag */
681 WRITE_UINT32 (bs, encoder->conformance_window_flag, 1);
682 if (encoder->conformance_window_flag) {
683 WRITE_UE (bs, encoder->conf_win_left_offset);
684 WRITE_UE (bs, encoder->conf_win_right_offset);
685 WRITE_UE (bs, encoder->conf_win_top_offset);
686 WRITE_UE (bs, encoder->conf_win_bottom_offset);
689 /* bit_depth_luma_minus8 */
690 WRITE_UE (bs, seq_param->seq_fields.bits.bit_depth_luma_minus8);
691 /* bit_depth_chroma_minus8 */
692 WRITE_UE (bs, seq_param->seq_fields.bits.bit_depth_chroma_minus8);
693 /* log2_max_pic_order_cnt_lsb_minus4 */
694 WRITE_UE (bs, encoder->log2_max_pic_order_cnt - 4);
696 /* sps_sub_layer_ordering_info_present_flag */
697 WRITE_UINT32 (bs, sps_sub_layer_ordering_info_present_flag, 1);
698 /* sps_max_dec_pic_buffering_minus1 */
699 WRITE_UE (bs, encoder->max_dec_pic_buffering - 1);
700 /* sps_max_num_reorder_pics */
701 WRITE_UE (bs, encoder->max_num_reorder_pics);
702 /* sps_max_latency_increase_plus1 */
703 WRITE_UE (bs, sps_max_latency_increase_plus1);
705 /* log2_min_luma_coding_block_size_minus3 */
706 WRITE_UE (bs, seq_param->log2_min_luma_coding_block_size_minus3);
707 /* log2_diff_max_min_luma_coding_block_size */
708 WRITE_UE (bs, seq_param->log2_diff_max_min_luma_coding_block_size);
709 /* log2_min_transform_block_size_minus2 */
710 WRITE_UE (bs, seq_param->log2_min_transform_block_size_minus2);
711 /* log2_diff_max_min_transform_block_size */
712 WRITE_UE (bs, seq_param->log2_diff_max_min_transform_block_size);
713 /* max_transform_hierarchy_depth_inter */
714 WRITE_UE (bs, seq_param->max_transform_hierarchy_depth_inter);
715 /*max_transform_hierarchy_depth_intra */
716 WRITE_UE (bs, seq_param->max_transform_hierarchy_depth_intra);
718 /* scaling_list_enabled_flag */
719 WRITE_UINT32 (bs, seq_param->seq_fields.bits.scaling_list_enabled_flag, 1);
720 /* amp_enabled_flag */
721 WRITE_UINT32 (bs, seq_param->seq_fields.bits.amp_enabled_flag, 1);
722 /* sample_adaptive_offset_enabled_flag */
724 seq_param->seq_fields.bits.sample_adaptive_offset_enabled_flag, 1);
725 /* pcm_enabled_flag */
726 WRITE_UINT32 (bs, seq_param->seq_fields.bits.pcm_enabled_flag, 1);
728 /* num_short_term_ref_pic_sets */
729 WRITE_UE (bs, num_short_term_ref_pic_sets);
731 /* long_term_ref_pics_present_flag */
732 WRITE_UINT32 (bs, long_term_ref_pics_present_flag, 1);
734 /* sps_temporal_mvp_enabled_flag */
735 WRITE_UINT32 (bs, seq_param->seq_fields.bits.sps_temporal_mvp_enabled_flag,
737 /* strong_intra_smoothing_enabled_flag */
739 seq_param->seq_fields.bits.strong_intra_smoothing_enabled_flag, 1);
741 /* vui_parameters_present_flag */
742 WRITE_UINT32 (bs, seq_param->vui_parameters_present_flag, 1);
744 /*--------------- Write VUI Parameters--------------- */
745 if (seq_param->vui_parameters_present_flag) {
746 gboolean vui_hrd_parameters_present_flag;
747 /* aspect_ratio_info_present_flag */
749 seq_param->vui_fields.bits.aspect_ratio_info_present_flag, 1);
750 if (seq_param->vui_fields.bits.aspect_ratio_info_present_flag) {
751 WRITE_UINT32 (bs, seq_param->aspect_ratio_idc, 8);
752 if (seq_param->aspect_ratio_idc == 0xFF) {
753 WRITE_UINT32 (bs, seq_param->sar_width, 16);
754 WRITE_UINT32 (bs, seq_param->sar_height, 16);
757 /* overscan_info_present_flag */
758 WRITE_UINT32 (bs, 0, 1);
759 /* video_signal_type_present_flag */
760 WRITE_UINT32 (bs, 0, 1);
761 /* chroma_loc_info_present_flag */
762 WRITE_UINT32 (bs, 0, 1);
763 /* neutral_chroma_indication_flag */
764 WRITE_UINT32 (bs, seq_param->vui_fields.bits.neutral_chroma_indication_flag,
767 WRITE_UINT32 (bs, seq_param->vui_fields.bits.field_seq_flag, 1);
768 /* frame_field_info_present_flag */
769 WRITE_UINT32 (bs, 0, 1);
770 /* default_display_window_flag */
771 WRITE_UINT32 (bs, 0, 1);
773 /* timing_info_present_flag */
774 WRITE_UINT32 (bs, seq_param->vui_fields.bits.vui_timing_info_present_flag,
776 if (seq_param->vui_fields.bits.vui_timing_info_present_flag) {
777 /* vui_num_units_in_tick */
778 WRITE_UINT32 (bs, seq_param->vui_num_units_in_tick, 32);
780 WRITE_UINT32 (bs, seq_param->vui_time_scale, 32);
781 /* vui_poc_proportional_to_timing_flag */
782 WRITE_UINT32 (bs, 0, 1);
784 /* vui_hrd_parameters_present_flag */
785 vui_hrd_parameters_present_flag = seq_param->bits_per_second > 0;
786 WRITE_UINT32 (bs, vui_hrd_parameters_present_flag, 1);
788 if (vui_hrd_parameters_present_flag) {
789 nal_hrd_parameters_present_flag = 1;
790 /* nal_hrd_parameters_present_flag */
791 WRITE_UINT32 (bs, nal_hrd_parameters_present_flag, 1);
792 /* vcl_hrd_parameters_present_flag */
793 WRITE_UINT32 (bs, 0, 1);
795 if (nal_hrd_parameters_present_flag) {
796 /* sub_pic_hrd_params_present_flag */
797 WRITE_UINT32 (bs, 0, 1);
799 WRITE_UINT32 (bs, SX_BITRATE - 6, 4);
801 WRITE_UINT32 (bs, SX_CPB_SIZE - 4, 4);
802 /* initial_cpb_removal_delay_length_minus1 */
803 WRITE_UINT32 (bs, 23, 5);
804 /* au_cpb_removal_delay_length_minus1 */
805 WRITE_UINT32 (bs, 23, 5);
806 /* dpb_output_delay_length_minus1 */
807 WRITE_UINT32 (bs, 23, 5);
809 for (i = 0; i < maxNumSubLayers; i++) {
810 /* fixed_pic_rate_general_flag */
811 WRITE_UINT32 (bs, 0, 1);
812 /* fixed_pic_rate_within_cvs_flag */
813 WRITE_UINT32 (bs, 0, 1);
814 /* low_delay_hrd_flag */
815 WRITE_UINT32 (bs, 1, 1);
816 /* bit_rate_value_minus1 */
817 WRITE_UE (bs, (seq_param->bits_per_second >> SX_BITRATE) - 1);
818 /* cpb_size_value_minus1 */
819 WRITE_UE (bs, (hrd_params->buffer_size >> SX_CPB_SIZE) - 1);
821 WRITE_UINT32 (bs, cbr_flag, 1);
826 /* bitstream_restriction_flag */
827 WRITE_UINT32 (bs, seq_param->vui_fields.bits.bitstream_restriction_flag, 1);
830 if (h265_is_scc (encoder)) {
831 /* sps_extension_flag */
832 WRITE_UINT32 (bs, 1, 1);
833 /* sps_range_extension_flag */
834 WRITE_UINT32 (bs, 0, 1);
835 /* sps_multilayer_extension_flag */
836 WRITE_UINT32 (bs, 0, 1);
837 /* sps_3d_extension_flag */
838 WRITE_UINT32 (bs, 0, 1);
839 /* sps_scc_extension_flag */
840 WRITE_UINT32 (bs, 1, 1);
841 /* sps_extension_4bits */
842 WRITE_UINT32 (bs, 0, 4);
844 /* sps_scc_extension() */
845 /* sps_curr_pic_ref_enabled_flag */
846 WRITE_UINT32 (bs, 1, 1);
847 /* palette_mode_enabled_flag */
848 WRITE_UINT32 (bs, 1, 1);
849 /* palette_max_size */
851 /* delta_palette_max_predictor_size */
853 /* sps_palette_predictor_initializers_present_flag */
854 WRITE_UINT32 (bs, 0, 1);
855 /* motion_vector_resolution_control_idc */
856 WRITE_UINT32 (bs, 0, 2);
857 /* intra_boundary_filtering_disabled_flag */
858 WRITE_UINT32 (bs, 0, 1);
860 /* sps_extension_flag */
861 WRITE_UINT32 (bs, sps_extension_flag, 1);
869 GST_WARNING ("failed to write SPS NAL unit");
875 bs_write_sps (GstBitWriter * bs, GstVaapiEncoderH265 * encoder,
876 GstVaapiEncPicture * picture,
877 const VAEncSequenceParameterBufferHEVC * seq_param, GstVaapiProfile profile,
878 GstVaapiRateControl rate_control, const VAEncMiscParameterHRD * hrd_params)
880 if (!bs_write_sps_data (bs, encoder, picture, seq_param, profile,
881 rate_control, hrd_params))
884 /* rbsp_trailing_bits */
885 bs_write_trailing_bits (bs);
890 /* Write a PPS NAL unit */
892 bs_write_pps (GstBitWriter * bs, gboolean is_scc,
893 const VAEncPictureParameterBufferHEVC * pic_param)
895 guint32 pic_parameter_set_id = 0;
896 guint32 seq_parameter_set_id = 0;
897 guint32 output_flag_present_flag = 0;
898 guint32 num_extra_slice_header_bits = 0;
899 guint32 cabac_init_present_flag = 0;
900 guint32 pps_slice_chroma_qp_offsets_present_flag = 0;
901 guint32 deblocking_filter_control_present_flag = 0;
902 guint32 lists_modification_present_flag = 0;
903 guint32 slice_segment_header_extension_present_flag = 0;
904 guint32 pps_extension_flag = 0;
906 /* pic_parameter_set_id */
907 WRITE_UE (bs, pic_parameter_set_id);
908 /* seq_parameter_set_id */
909 WRITE_UE (bs, seq_parameter_set_id);
910 /* dependent_slice_segments_enabled_flag */
912 pic_param->pic_fields.bits.dependent_slice_segments_enabled_flag, 1);
913 /* output_flag_present_flag */
914 WRITE_UINT32 (bs, output_flag_present_flag, 1);
915 /* num_extra_slice_header_bits */
916 WRITE_UINT32 (bs, num_extra_slice_header_bits, 3);
917 /* sign_data_hiding_enabled_flag */
918 WRITE_UINT32 (bs, pic_param->pic_fields.bits.sign_data_hiding_enabled_flag,
920 /* cabac_init_present_flag */
921 WRITE_UINT32 (bs, cabac_init_present_flag, 1);
922 /* num_ref_idx_l0_default_active_minus1 */
923 WRITE_UE (bs, pic_param->num_ref_idx_l0_default_active_minus1);
924 /* num_ref_idx_l1_default_active_minus1 */
925 WRITE_UE (bs, pic_param->num_ref_idx_l1_default_active_minus1);
926 /* pic_init_qp_minus26 */
927 WRITE_SE (bs, pic_param->pic_init_qp - 26);
928 /* constrained_intra_pred_flag */
929 WRITE_UINT32 (bs, pic_param->pic_fields.bits.constrained_intra_pred_flag, 1);
930 /* transform_skip_enabled_flag */
931 WRITE_UINT32 (bs, pic_param->pic_fields.bits.transform_skip_enabled_flag, 1);
932 /* cu_qp_delta_enabled_flag */
933 WRITE_UINT32 (bs, pic_param->pic_fields.bits.cu_qp_delta_enabled_flag, 1);
934 /* diff_cu_qp_delta_depth */
935 if (pic_param->pic_fields.bits.cu_qp_delta_enabled_flag)
936 WRITE_UE (bs, pic_param->diff_cu_qp_delta_depth);
938 /* pps_cb_qp_offset */
939 WRITE_SE (bs, pic_param->pps_cb_qp_offset);
940 /* pps_cr_qp_offset */
941 WRITE_SE (bs, pic_param->pps_cr_qp_offset);
942 /* pps_slice_chroma_qp_offsets_present_flag */
943 WRITE_UINT32 (bs, pps_slice_chroma_qp_offsets_present_flag, 1);
944 /* weighted_pred_flag */
945 WRITE_UINT32 (bs, pic_param->pic_fields.bits.weighted_pred_flag, 1);
946 /* weighted_bipred_flag */
947 WRITE_UINT32 (bs, pic_param->pic_fields.bits.weighted_bipred_flag, 1);
948 /* transquant_bypass_enabled_flag */
949 WRITE_UINT32 (bs, pic_param->pic_fields.bits.transquant_bypass_enabled_flag,
951 /* tiles_enabled_flag */
952 WRITE_UINT32 (bs, pic_param->pic_fields.bits.tiles_enabled_flag, 1);
953 /* entropy_coding_sync_enabled_flag */
954 WRITE_UINT32 (bs, pic_param->pic_fields.bits.entropy_coding_sync_enabled_flag,
958 if (pic_param->pic_fields.bits.tiles_enabled_flag) {
959 WRITE_UE (bs, pic_param->num_tile_columns_minus1);
960 WRITE_UE (bs, pic_param->num_tile_rows_minus1);
961 /* uniform_spacing_flag is 1 now */
962 WRITE_UINT32 (bs, 1, 1);
963 /* if (!uniform_spacing_flag) {
964 for (i = 0; i < num_tile_columns_minus1; i++)
965 column_width_minus1[i]
967 for (i = 0; i < num_tile_rows_minus1; i++)
972 pic_param->pic_fields.bits.loop_filter_across_tiles_enabled_flag, 1);
975 /* pps_loop_filter_across_slices_enabled_flag */
977 pic_param->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag, 1);
978 /* deblocking_filter_control_present_flag */
979 WRITE_UINT32 (bs, deblocking_filter_control_present_flag, 1);
980 /* pps_scaling_list_data_present_flag */
981 WRITE_UINT32 (bs, pic_param->pic_fields.bits.scaling_list_data_present_flag,
983 /* lists_modification_present_flag */
984 WRITE_UINT32 (bs, lists_modification_present_flag, 1);
985 /* log2_parallel_merge_level_minus2 */
986 WRITE_UE (bs, pic_param->log2_parallel_merge_level_minus2);
987 /* slice_segment_header_extension_present_flag */
988 WRITE_UINT32 (bs, slice_segment_header_extension_present_flag, 1);
991 #if VA_CHECK_VERSION(1,8,0)
992 /* pps_extension_flag */
993 WRITE_UINT32 (bs, 1, 1);
994 /* pps_range_extension_flag */
995 WRITE_UINT32 (bs, 0, 1);
996 /* pps_multilayer_extension_flag */
997 WRITE_UINT32 (bs, 0, 1);
998 /* pps_3d_extension_flag */
999 WRITE_UINT32 (bs, 0, 1);
1000 /* pps_scc_extension_flag */
1001 WRITE_UINT32 (bs, 1, 1);
1002 /* pps_extension_4bits */
1003 WRITE_UINT32 (bs, 0, 4);
1005 /* pps_scc_extension() */
1006 /* pps_curr_pic_ref_enabled_flag */
1008 pic_param->scc_fields.bits.pps_curr_pic_ref_enabled_flag, 1);
1009 /* residual_adaptive_colour_transform_enabled_flag */
1010 WRITE_UINT32 (bs, 0, 1);
1011 /* pps_palette_predictor_initializers_present_flag */
1012 WRITE_UINT32 (bs, 0, 1);
1014 /* SCC profile should not be selected. */
1015 g_assert_not_reached ();
1019 /* pps_extension_flag */
1020 WRITE_UINT32 (bs, pps_extension_flag, 1);
1023 /* rbsp_trailing_bits */
1024 bs_write_trailing_bits (bs);
1031 GST_WARNING ("failed to write PPS NAL unit");
1036 /* Write a Slice NAL unit */
1038 bs_write_slice (GstBitWriter * bs,
1039 const VAEncSliceParameterBufferHEVC * slice_param,
1040 GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture,
1041 guint8 nal_unit_type)
1043 const VAEncPictureParameterBufferHEVC *const pic_param = picture->param;
1045 guint8 no_output_of_prior_pics_flag = 0;
1046 guint8 dependent_slice_segment_flag = 0;
1047 guint8 short_term_ref_pic_set_sps_flag = 0;
1048 guint8 slice_deblocking_filter_disabled_flag = 0;
1049 guint8 num_ref_idx_active_override_flag =
1050 slice_param->slice_fields.bits.num_ref_idx_active_override_flag;
1052 if (h265_is_scc (encoder)) {
1053 /* If scc, need to add the current picture itself. */
1054 num_ref_idx_active_override_flag = 1;
1057 /* first_slice_segment_in_pic_flag */
1058 WRITE_UINT32 (bs, encoder->first_slice_segment_in_pic_flag, 1);
1060 /* FIXME: For all IRAP pics */
1061 /* no_output_of_prior_pics_flag */
1062 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
1063 WRITE_UINT32 (bs, no_output_of_prior_pics_flag, 1);
1065 /* slice_pic_parameter_set_id */
1066 WRITE_UE (bs, slice_param->slice_pic_parameter_set_id);
1068 /* slice_segment_address , bits_size = Ceil(Log2(PicSizeInCtbsY)) */
1069 if (!encoder->first_slice_segment_in_pic_flag) {
1070 guint pic_size_ctb = encoder->ctu_width * encoder->ctu_height;
1071 guint bits_size = (guint) ceil ((log2 (pic_size_ctb)));
1072 WRITE_UINT32 (bs, slice_param->slice_segment_address, bits_size);
1075 if (!dependent_slice_segment_flag) {
1077 WRITE_UE (bs, slice_param->slice_type);
1079 if (!pic_param->pic_fields.bits.idr_pic_flag) {
1080 /* slice_pic_order_cnt_lsb */
1081 WRITE_UINT32 (bs, picture->poc, encoder->log2_max_pic_order_cnt);
1082 /* short_term_ref_pic_set_sps_flag */
1083 WRITE_UINT32 (bs, short_term_ref_pic_set_sps_flag, 1);
1085 /*---------- Write short_term_ref_pic_set(0) ----------- */
1087 guint num_positive_pics = 0, num_negative_pics = 0;
1088 guint delta_poc_s0_minus1 = 0, delta_poc_s1_minus1 = 0;
1089 guint used_by_curr_pic_s0_flag = 0, used_by_curr_pic_s1_flag = 0;
1090 guint reflist_0_count = 0, reflist_1_count = 0;
1093 /* Get count of ref_pic_list */
1094 if (picture->type == GST_VAAPI_PICTURE_TYPE_P
1095 || picture->type == GST_VAAPI_PICTURE_TYPE_B) {
1096 for (i = 0; i < G_N_ELEMENTS (slice_param->ref_pic_list0); ++i) {
1097 if (slice_param->ref_pic_list0[i].picture_id == VA_INVALID_SURFACE)
1100 reflist_0_count = i;
1102 if (picture->type == GST_VAAPI_PICTURE_TYPE_B) {
1103 for (i = 0; i < G_N_ELEMENTS (slice_param->ref_pic_list1); ++i) {
1104 if (slice_param->ref_pic_list1[i].picture_id ==
1108 reflist_1_count = i;
1112 if (picture->type == GST_VAAPI_PICTURE_TYPE_P) {
1113 delta_poc_s0_minus1 =
1114 picture->poc - slice_param->ref_pic_list0[0].pic_order_cnt - 1;
1115 used_by_curr_pic_s0_flag = 1;
1116 delta_poc_s1_minus1 = 0;
1117 used_by_curr_pic_s1_flag = 0;
1119 if (picture->type == GST_VAAPI_PICTURE_TYPE_B) {
1120 delta_poc_s0_minus1 =
1121 picture->poc - slice_param->ref_pic_list0[0].pic_order_cnt - 1;
1122 used_by_curr_pic_s0_flag = 1;
1123 delta_poc_s1_minus1 =
1124 slice_param->ref_pic_list1[0].pic_order_cnt - picture->poc - 1;
1125 used_by_curr_pic_s1_flag = 1;
1128 num_negative_pics = reflist_0_count;
1129 num_positive_pics = reflist_1_count;
1131 /* num_negative_pics */
1132 WRITE_UE (bs, num_negative_pics);
1133 /* num_positive_pics */
1134 WRITE_UE (bs, num_positive_pics);
1136 for (i = 0; i < num_negative_pics; i++) {
1137 /* delta_poc_s0_minus1 */
1139 WRITE_UE (bs, delta_poc_s0_minus1);
1142 slice_param->ref_pic_list0[i - 1].pic_order_cnt -
1143 slice_param->ref_pic_list0[i].pic_order_cnt - 1);
1145 /* used_by_curr_pic_s0_flag */
1146 WRITE_UINT32 (bs, used_by_curr_pic_s0_flag, 1);
1148 for (i = 0; i < num_positive_pics; i++) {
1149 /* delta_poc_s1_minus1 */
1151 WRITE_UE (bs, delta_poc_s1_minus1);
1154 slice_param->ref_pic_list1[i - 1].pic_order_cnt -
1155 slice_param->ref_pic_list1[i].pic_order_cnt - 1);
1157 /* used_by_curr_pic_s1_flag */
1158 WRITE_UINT32 (bs, used_by_curr_pic_s1_flag, 1);
1162 /* slice_temporal_mvp_enabled_flag */
1163 if (encoder->sps_temporal_mvp_enabled_flag)
1165 slice_param->slice_fields.bits.slice_temporal_mvp_enabled_flag, 1);
1168 if (encoder->sample_adaptive_offset_enabled_flag) {
1169 WRITE_UINT32 (bs, slice_param->slice_fields.bits.slice_sao_luma_flag, 1);
1170 WRITE_UINT32 (bs, slice_param->slice_fields.bits.slice_sao_chroma_flag,
1174 if (slice_param->slice_type == GST_H265_P_SLICE ||
1175 slice_param->slice_type == GST_H265_B_SLICE) {
1176 /* num_ref_idx_active_override_flag */
1177 WRITE_UINT32 (bs, num_ref_idx_active_override_flag, 1);
1178 if (num_ref_idx_active_override_flag) {
1179 if (h265_is_scc (encoder)) {
1180 if (picture->type == GST_VAAPI_PICTURE_TYPE_I) {
1181 g_assert (slice_param->num_ref_idx_l0_active_minus1 == 0);
1182 /* Let num_ref_idx_l0_active_minus1 = 0 and
1183 NumRpsCurrTempList0 = 1 to include current picture itself */
1186 /* For scc, need to add 1 for current picture itself when
1187 calculating NumRpsCurrTempList0. */
1188 WRITE_UE (bs, slice_param->num_ref_idx_l0_active_minus1 + 1);
1191 WRITE_UE (bs, slice_param->num_ref_idx_l0_active_minus1);
1193 if (slice_param->slice_type == GST_H265_B_SLICE)
1194 WRITE_UE (bs, slice_param->num_ref_idx_l1_active_minus1);
1197 /* mvd_l1_zero_flag */
1198 if (slice_param->slice_type == GST_H265_B_SLICE)
1199 WRITE_UINT32 (bs, slice_param->slice_fields.bits.mvd_l1_zero_flag, 1);
1201 /* cabac_init_present_flag == FALSE */
1202 /* cabac_init_flag = FALSE */
1204 /* collocated_from_l0_flag */
1205 if (slice_param->slice_fields.bits.slice_temporal_mvp_enabled_flag) {
1206 if (slice_param->slice_type == GST_H265_B_SLICE)
1208 slice_param->slice_fields.bits.collocated_from_l0_flag, 1);
1210 /* five_minus_max_num_merge_cand */
1211 WRITE_UE (bs, 5 - slice_param->max_num_merge_cand);
1214 /* slice_qp_delta */
1215 WRITE_SE (bs, slice_param->slice_qp_delta);
1216 if (pic_param->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag &&
1217 (slice_param->slice_fields.bits.slice_sao_luma_flag
1218 || slice_param->slice_fields.bits.slice_sao_chroma_flag
1219 || !slice_deblocking_filter_disabled_flag))
1221 slice_param->slice_fields.bits.
1222 slice_loop_filter_across_slices_enabled_flag, 1);
1225 if (pic_param->pic_fields.bits.tiles_enabled_flag
1226 || pic_param->pic_fields.bits.entropy_coding_sync_enabled_flag) {
1227 /* output a num_entry_point_offsets, which should be 0 here */
1231 /* byte_alignment() */
1233 /* alignment_bit_equal_to_one */
1234 WRITE_UINT32 (bs, 1, 1);
1235 while (GST_BIT_WRITER_BIT_SIZE (bs) % 8 != 0) {
1236 /* alignment_bit_equal_to_zero */
1237 WRITE_UINT32 (bs, 0, 1);
1246 GST_WARNING ("failed to write Slice NAL unit");
1252 _check_vps_sps_pps_status (GstVaapiEncoderH265 * encoder,
1253 const guint8 * nal, guint32 size)
1256 G_GNUC_UNUSED gsize ret; /* FIXME */
1259 if (encoder->vps_data && encoder->sps_data && encoder->pps_data)
1262 nal_type = (nal[0] & 0x7E) >> 1;
1264 case GST_H265_NAL_VPS:
1265 encoder->vps_data = gst_buffer_new_allocate (NULL, size, NULL);
1266 ret = gst_buffer_fill (encoder->vps_data, 0, nal, size);
1267 g_assert (ret == size);
1269 case GST_H265_NAL_SPS:
1270 encoder->sps_data = gst_buffer_new_allocate (NULL, size, NULL);
1271 ret = gst_buffer_fill (encoder->sps_data, 0, nal, size);
1272 g_assert (ret == size);
1274 case GST_H265_NAL_PPS:
1275 encoder->pps_data = gst_buffer_new_allocate (NULL, size, NULL);
1276 ret = gst_buffer_fill (encoder->pps_data, 0, nal, size);
1277 g_assert (ret == size);
1285 is_profile_allowed (GstVaapiEncoderH265 * encoder, GstVaapiProfile profile)
1289 if (encoder->allowed_profiles == NULL)
1292 for (i = 0; i < encoder->allowed_profiles->len; i++)
1294 g_array_index (encoder->allowed_profiles, GstVaapiProfile, i))
1300 /* Derives the profile from the active coding tools. */
1302 ensure_profile (GstVaapiEncoderH265 * encoder)
1304 GstVaapiProfile profile;
1305 const GstVideoFormat format =
1306 GST_VIDEO_INFO_FORMAT (GST_VAAPI_ENCODER_VIDEO_INFO (encoder));
1307 guint depth, chrome;
1308 GstVaapiProfile profile_candidates[6];
1311 g_assert (GST_VIDEO_FORMAT_INFO_IS_YUV (gst_video_format_get_info (format)));
1312 depth = GST_VIDEO_FORMAT_INFO_DEPTH (gst_video_format_get_info (format), 0);
1313 chrome = gst_vaapi_utils_h265_get_chroma_format_idc
1314 (gst_vaapi_video_format_get_chroma_type (format));
1321 profile_candidates[num++] = GST_VAAPI_PROFILE_H265_MAIN_444;
1323 profile_candidates[num++] = GST_VAAPI_PROFILE_H265_MAIN_444_10;
1324 #if VA_CHECK_VERSION(1,8,0)
1325 /* Consider SCREEN_EXTENDED_MAIN_444 and SCREEN_EXTENDED_MAIN_444_10 */
1327 profile_candidates[num++] =
1328 GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN_444;
1330 profile_candidates[num++] =
1331 GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN_444_10;
1333 } else if (chrome == 2) {
1335 profile_candidates[num++] = GST_VAAPI_PROFILE_H265_MAIN_422_10;
1336 } else if (chrome == 1 || chrome == 0) {
1337 /* 4:2:0 or 4:0:0 */
1339 profile_candidates[num++] = GST_VAAPI_PROFILE_H265_MAIN;
1341 profile_candidates[num++] = GST_VAAPI_PROFILE_H265_MAIN10;
1343 profile_candidates[num++] = GST_VAAPI_PROFILE_H265_MAIN12;
1344 /* Always add STILL_PICTURE as a candidate for Main and Main10. */
1346 profile_candidates[num++] = GST_VAAPI_PROFILE_H265_MAIN_STILL_PICTURE;
1347 #if VA_CHECK_VERSION(1,8,0)
1348 /* Consider SCREEN_EXTENDED_MAIN and SCREEN_EXTENDED_MAIN_10 */
1350 profile_candidates[num++] = GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN;
1352 profile_candidates[num++] =
1353 GST_VAAPI_PROFILE_H265_SCREEN_EXTENDED_MAIN_10;
1358 GST_ERROR ("Fail to find a profile for format %s.",
1359 gst_video_format_to_string (format));
1363 profile = GST_VAAPI_PROFILE_UNKNOWN;
1364 for (i = 0; i < num; i++) {
1365 if (!is_profile_allowed (encoder, profile_candidates[i]))
1367 /* If we can get valid entrypoint, hw must support this profile. */
1368 if (gst_vaapi_encoder_get_entrypoint (GST_VAAPI_ENCODER_CAST (encoder),
1369 profile_candidates[i]) == GST_VAAPI_ENTRYPOINT_INVALID)
1372 profile = profile_candidates[i];
1376 if (profile == GST_VAAPI_PROFILE_UNKNOWN) {
1377 GST_ERROR ("Fail to find a supported profile %sfor format %s.",
1378 GST_VAAPI_ENCODER_TUNE (encoder) == GST_VAAPI_ENCODER_TUNE_LOW_POWER ?
1379 "in low power mode " : "", gst_video_format_to_string (format));
1383 encoder->profile = profile;
1384 encoder->profile_idc = gst_vaapi_utils_h265_get_profile_idc (profile);
1388 /* Derives the level and tier from the currently set limits */
1390 ensure_tier_level (GstVaapiEncoderH265 * encoder)
1392 guint bitrate = GST_VAAPI_ENCODER_CAST (encoder)->bitrate;
1393 guint i, num_limits, PicSizeInSamplesY;
1395 const GstVaapiH265LevelLimits *limits_table;
1396 const GstVaapiH265LevelLimits *limits;
1398 PicSizeInSamplesY = encoder->luma_width * encoder->luma_height;
1400 gst_util_uint64_scale (PicSizeInSamplesY,
1401 GST_VAAPI_ENCODER_FPS_N (encoder), GST_VAAPI_ENCODER_FPS_D (encoder));
1403 limits_table = gst_vaapi_utils_h265_get_level_limits_table (&num_limits);
1404 for (i = 0; i < num_limits; i++) {
1405 limits = &limits_table[i];
1406 /* Choose level by luma picture size and luma sample rate */
1407 if (PicSizeInSamplesY <= limits->MaxLumaPs && LumaSr <= limits->MaxLumaSr)
1411 if (i == num_limits)
1412 goto error_unsupported_level;
1414 /* may need to promote the level by tile setting */
1415 if (h265_is_tile_enabled (encoder)) {
1416 for (; i < num_limits; i++) {
1417 limits = &limits_table[i];
1418 if (encoder->num_tile_cols <= limits->MaxTileColumns &&
1419 encoder->num_tile_rows <= limits->MaxTileRows)
1423 if (i == num_limits)
1424 goto error_promote_level;
1427 if (bitrate <= limits_table[i].MaxBRTierMain) {
1428 encoder->tier = GST_VAAPI_TIER_H265_MAIN;
1430 encoder->tier = GST_VAAPI_TIER_H265_HIGH;
1431 if (bitrate > limits_table[i].MaxBRTierHigh) {
1432 GST_INFO ("The bitrate of the stream is %d kbps, larger than"
1433 " %s profile %s level %s tier's max bit rate %d kbps",
1435 gst_vaapi_utils_h265_get_profile_string (encoder->profile),
1436 gst_vaapi_utils_h265_get_level_string (limits_table[i].level),
1437 gst_vaapi_utils_h265_get_tier_string (GST_VAAPI_TIER_H265_HIGH),
1438 limits_table[i].MaxBRTierHigh);
1442 encoder->level = limits_table[i].level;
1443 encoder->level_idc = limits_table[i].level_idc;
1447 error_promote_level:
1449 GST_ERROR ("failed to promote level for num-tile-cols is %d,"
1450 " num-tile-rows %d", encoder->num_tile_cols, encoder->num_tile_rows);
1453 error_unsupported_level:
1455 GST_ERROR ("failed to find a suitable level matching codec config");
1460 /* Handle new GOP starts */
1462 reset_gop_start (GstVaapiEncoderH265 * encoder)
1464 GstVaapiH265ReorderPool *const reorder_pool = &encoder->reorder_pool;
1466 reorder_pool->frame_index = 1;
1467 reorder_pool->cur_present_index = 0;
1471 /* Marks the supplied picture as a B-frame */
1473 set_b_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH265 * encoder)
1475 g_assert (pic && encoder);
1476 g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1477 pic->type = GST_VAAPI_PICTURE_TYPE_B;
1480 /* Marks the supplied picture as a P-frame */
1482 set_p_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH265 * encoder)
1484 g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1485 pic->type = GST_VAAPI_PICTURE_TYPE_P;
1488 /* Marks the supplied picture as an I-frame */
1490 set_i_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH265 * encoder)
1492 g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1493 pic->type = GST_VAAPI_PICTURE_TYPE_I;
1495 g_assert (pic->frame);
1496 GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (pic->frame);
1499 /* Marks the supplied picture as an IDR frame */
1501 set_idr_frame (GstVaapiEncPicture * pic, GstVaapiEncoderH265 * encoder)
1503 g_return_if_fail (pic->type == GST_VAAPI_PICTURE_TYPE_NONE);
1504 pic->type = GST_VAAPI_PICTURE_TYPE_I;
1506 GST_VAAPI_ENC_PICTURE_FLAG_SET (pic, GST_VAAPI_ENC_PICTURE_FLAG_IDR);
1508 g_assert (pic->frame);
1509 GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (pic->frame);
1512 /* Marks the supplied picture a a key-frame */
1514 set_key_frame (GstVaapiEncPicture * picture,
1515 GstVaapiEncoderH265 * encoder, gboolean is_idr)
1518 reset_gop_start (encoder);
1519 set_idr_frame (picture, encoder);
1521 set_i_frame (picture, encoder);
1524 /* Fills in VA HRD parameters */
1526 fill_hrd_params (GstVaapiEncoderH265 * encoder, VAEncMiscParameterHRD * hrd)
1528 if (encoder->bitrate_bits > 0) {
1529 hrd->buffer_size = encoder->cpb_length_bits;
1530 hrd->initial_buffer_fullness = hrd->buffer_size / 2;
1532 hrd->buffer_size = 0;
1533 hrd->initial_buffer_fullness = 0;
1537 /* Adds the supplied video parameter set header (VPS) to the list of packed
1538 headers to pass down as-is to the encoder */
1540 add_packed_vps_header (GstVaapiEncoderH265 * encoder,
1541 GstVaapiEncPicture * picture, GstVaapiEncSequence * sequence)
1543 GstVaapiEncPackedHeader *packed_vps;
1545 VAEncPackedHeaderParameterBuffer packed_vps_param = { 0 };
1546 const VAEncSequenceParameterBufferHEVC *const seq_param = sequence->param;
1547 GstVaapiProfile profile = encoder->profile;
1549 guint32 data_bit_size;
1552 gst_bit_writer_init_with_size (&bs, 128, FALSE);
1553 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1554 bs_write_nal_header (&bs, GST_H265_NAL_VPS);
1556 bs_write_vps (&bs, encoder, picture, seq_param, profile);
1558 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1559 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1560 data = GST_BIT_WRITER_DATA (&bs);
1562 packed_vps_param.type = VAEncPackedHeaderSequence;
1563 packed_vps_param.bit_length = data_bit_size;
1564 packed_vps_param.has_emulation_bytes = 0;
1566 packed_vps = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1567 &packed_vps_param, sizeof (packed_vps_param),
1568 data, (data_bit_size + 7) / 8);
1569 g_assert (packed_vps);
1571 gst_vaapi_enc_picture_add_packed_header (picture, packed_vps);
1572 gst_vaapi_codec_object_replace (&packed_vps, NULL);
1574 /* store vps data */
1575 _check_vps_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1576 gst_bit_writer_reset (&bs);
1582 GST_WARNING ("failed to write VPS NAL unit");
1583 gst_bit_writer_reset (&bs);
1588 /* Adds the supplied sequence header (SPS) to the list of packed
1589 headers to pass down as-is to the encoder */
1591 add_packed_sequence_header (GstVaapiEncoderH265 * encoder,
1592 GstVaapiEncPicture * picture, GstVaapiEncSequence * sequence)
1594 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
1595 GstVaapiEncPackedHeader *packed_seq;
1597 VAEncPackedHeaderParameterBuffer packed_seq_param = { 0 };
1598 const VAEncSequenceParameterBufferHEVC *const seq_param = sequence->param;
1599 GstVaapiProfile profile = encoder->profile;
1601 VAEncMiscParameterHRD hrd_params;
1602 guint32 data_bit_size;
1605 fill_hrd_params (encoder, &hrd_params);
1607 gst_bit_writer_init_with_size (&bs, 128, FALSE);
1608 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1609 bs_write_nal_header (&bs, GST_H265_NAL_SPS);
1611 bs_write_sps (&bs, encoder, picture, seq_param, profile,
1612 base_encoder->rate_control, &hrd_params);
1614 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1615 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1616 data = GST_BIT_WRITER_DATA (&bs);
1618 packed_seq_param.type = VAEncPackedHeaderSequence;
1619 packed_seq_param.bit_length = data_bit_size;
1620 packed_seq_param.has_emulation_bytes = 0;
1622 packed_seq = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1623 &packed_seq_param, sizeof (packed_seq_param),
1624 data, (data_bit_size + 7) / 8);
1625 g_assert (packed_seq);
1627 gst_vaapi_enc_picture_add_packed_header (picture, packed_seq);
1628 gst_vaapi_codec_object_replace (&packed_seq, NULL);
1630 /* store sps data */
1631 _check_vps_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1632 gst_bit_writer_reset (&bs);
1638 GST_WARNING ("failed to write SPS NAL unit");
1639 gst_bit_writer_reset (&bs);
1644 /* Adds the supplied picture header (PPS) to the list of packed
1645 headers to pass down as-is to the encoder */
1647 add_packed_picture_header (GstVaapiEncoderH265 * encoder,
1648 GstVaapiEncPicture * picture)
1650 GstVaapiEncPackedHeader *packed_pic;
1652 VAEncPackedHeaderParameterBuffer packed_pic_param = { 0 };
1653 const VAEncPictureParameterBufferHEVC *const pic_param = picture->param;
1654 guint32 data_bit_size;
1657 gst_bit_writer_init_with_size (&bs, 128, FALSE);
1658 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1659 bs_write_nal_header (&bs, GST_H265_NAL_PPS);
1660 bs_write_pps (&bs, h265_is_scc (encoder), pic_param);
1661 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
1662 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1663 data = GST_BIT_WRITER_DATA (&bs);
1665 packed_pic_param.type = VAEncPackedHeaderPicture;
1666 packed_pic_param.bit_length = data_bit_size;
1667 packed_pic_param.has_emulation_bytes = 0;
1669 packed_pic = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1670 &packed_pic_param, sizeof (packed_pic_param),
1671 data, (data_bit_size + 7) / 8);
1672 g_assert (packed_pic);
1674 gst_vaapi_enc_picture_add_packed_header (picture, packed_pic);
1675 gst_vaapi_codec_object_replace (&packed_pic, NULL);
1677 /* store pps data */
1678 _check_vps_sps_pps_status (encoder, data + 4, data_bit_size / 8 - 4);
1679 gst_bit_writer_reset (&bs);
1685 GST_WARNING ("failed to write PPS NAL unit");
1686 gst_bit_writer_reset (&bs);
1692 get_nal_unit_type (GstVaapiEncPicture * picture, guint8 * nal_unit_type)
1694 switch (picture->type) {
1695 case GST_VAAPI_PICTURE_TYPE_I:
1696 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
1697 *nal_unit_type = GST_H265_NAL_SLICE_IDR_W_RADL;
1699 *nal_unit_type = GST_H265_NAL_SLICE_TRAIL_R;
1701 case GST_VAAPI_PICTURE_TYPE_P:
1702 *nal_unit_type = GST_H265_NAL_SLICE_TRAIL_R;
1704 case GST_VAAPI_PICTURE_TYPE_B:
1705 *nal_unit_type = GST_H265_NAL_SLICE_TRAIL_N;
1713 /* Adds the supplied slice header to the list of packed
1714 headers to pass down as-is to the encoder */
1716 add_packed_slice_header (GstVaapiEncoderH265 * encoder,
1717 GstVaapiEncPicture * picture, GstVaapiEncSlice * slice)
1719 GstVaapiEncPackedHeader *packed_slice;
1721 VAEncPackedHeaderParameterBuffer packed_slice_param = { 0 };
1722 const VAEncSliceParameterBufferHEVC *const slice_param = slice->param;
1723 guint32 data_bit_size;
1725 guint8 nal_unit_type;
1727 gst_bit_writer_init_with_size (&bs, 128, FALSE);
1728 WRITE_UINT32 (&bs, 0x00000001, 32); /* start code */
1730 if (!get_nal_unit_type (picture, &nal_unit_type))
1732 bs_write_nal_header (&bs, nal_unit_type);
1734 bs_write_slice (&bs, slice_param, encoder, picture, nal_unit_type);
1735 data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
1736 data = GST_BIT_WRITER_DATA (&bs);
1738 packed_slice_param.type = VAEncPackedHeaderSlice;
1739 packed_slice_param.bit_length = data_bit_size;
1740 packed_slice_param.has_emulation_bytes = 0;
1742 packed_slice = gst_vaapi_enc_packed_header_new (GST_VAAPI_ENCODER (encoder),
1743 &packed_slice_param, sizeof (packed_slice_param),
1744 data, (data_bit_size + 7) / 8);
1745 g_assert (packed_slice);
1747 gst_vaapi_enc_slice_add_packed_header (slice, packed_slice);
1748 gst_vaapi_codec_object_replace (&packed_slice, NULL);
1750 gst_bit_writer_reset (&bs);
1756 GST_WARNING ("failed to write Slice NAL unit header");
1757 gst_bit_writer_reset (&bs);
1762 /* Reference picture management */
1764 reference_pic_free (GstVaapiEncoderH265 * encoder, GstVaapiEncoderH265Ref * ref)
1769 gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder), ref->pic);
1770 g_slice_free (GstVaapiEncoderH265Ref, ref);
1773 static inline GstVaapiEncoderH265Ref *
1774 reference_pic_create (GstVaapiEncoderH265 * encoder,
1775 GstVaapiEncPicture * picture, GstVaapiSurfaceProxy * surface)
1777 GstVaapiEncoderH265Ref *const ref = g_slice_new0 (GstVaapiEncoderH265Ref);
1780 ref->poc = picture->poc;
1785 reference_list_update (GstVaapiEncoderH265 * encoder,
1786 GstVaapiEncPicture * picture, GstVaapiSurfaceProxy * surface)
1788 GstVaapiEncoderH265Ref *ref;
1789 GstVaapiH265RefPool *const ref_pool = &encoder->ref_pool;
1791 if (GST_VAAPI_PICTURE_TYPE_B == picture->type) {
1792 gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder), surface);
1796 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture)) {
1797 while (!g_queue_is_empty (&ref_pool->ref_list))
1798 reference_pic_free (encoder, g_queue_pop_head (&ref_pool->ref_list));
1799 } else if (g_queue_get_length (&ref_pool->ref_list) >=
1800 ref_pool->max_ref_frames) {
1801 reference_pic_free (encoder, g_queue_pop_head (&ref_pool->ref_list));
1803 ref = reference_pic_create (encoder, picture, surface);
1804 g_queue_push_tail (&ref_pool->ref_list, ref);
1805 g_assert (g_queue_get_length (&ref_pool->ref_list) <=
1806 ref_pool->max_ref_frames);
1811 reference_list_init (GstVaapiEncoderH265 * encoder,
1812 GstVaapiEncPicture * picture,
1813 GstVaapiEncoderH265Ref ** reflist_0,
1814 guint * reflist_0_count,
1815 GstVaapiEncoderH265Ref ** reflist_1, guint * reflist_1_count)
1817 GstVaapiEncoderH265Ref *tmp;
1818 GstVaapiH265RefPool *const ref_pool = &encoder->ref_pool;
1819 GList *iter, *list_0_start = NULL, *list_1_start = NULL;
1822 *reflist_0_count = 0;
1823 *reflist_1_count = 0;
1824 if (picture->type == GST_VAAPI_PICTURE_TYPE_I)
1827 iter = g_queue_peek_tail_link (&ref_pool->ref_list);
1828 for (; iter; iter = g_list_previous (iter)) {
1829 tmp = (GstVaapiEncoderH265Ref *) iter->data;
1830 g_assert (tmp && tmp->poc != picture->poc);
1831 if (_poc_greater_than (picture->poc, tmp->poc, encoder->max_pic_order_cnt)) {
1832 list_0_start = iter;
1833 list_1_start = g_list_next (iter);
1838 /* order reflist_0 */
1839 g_assert (list_0_start);
1840 iter = list_0_start;
1842 for (; iter; iter = g_list_previous (iter)) {
1843 reflist_0[count] = (GstVaapiEncoderH265Ref *) iter->data;
1846 *reflist_0_count = count;
1848 if (picture->type != GST_VAAPI_PICTURE_TYPE_B)
1851 /* order reflist_1 */
1853 iter = list_1_start;
1854 for (; iter; iter = g_list_next (iter)) {
1855 reflist_1[count] = (GstVaapiEncoderH265Ref *) iter->data;
1858 *reflist_1_count = count;
1862 /* Fills in VA sequence parameter buffer */
1864 fill_sequence (GstVaapiEncoderH265 * encoder, GstVaapiEncSequence * sequence)
1866 VAEncSequenceParameterBufferHEVC *const seq_param = sequence->param;
1867 const GstVideoFormat format =
1868 GST_VIDEO_INFO_FORMAT (GST_VAAPI_ENCODER_VIDEO_INFO (encoder));
1869 guint bits_depth_luma_minus8 =
1870 GST_VIDEO_FORMAT_INFO_DEPTH (gst_video_format_get_info (format), 0);
1871 if (bits_depth_luma_minus8 < 8)
1873 bits_depth_luma_minus8 -= 8;
1875 memset (seq_param, 0, sizeof (VAEncSequenceParameterBufferHEVC));
1877 seq_param->general_profile_idc = encoder->profile_idc;
1878 seq_param->general_level_idc = encoder->level_idc;
1879 seq_param->general_tier_flag = encoder->tier;
1881 seq_param->intra_period = GST_VAAPI_ENCODER_KEYFRAME_PERIOD (encoder);
1882 seq_param->intra_idr_period = encoder->idr_period;
1883 seq_param->ip_period = seq_param->intra_period > 1 ?
1884 (1 + encoder->num_bframes) : 0;
1885 seq_param->bits_per_second = encoder->bitrate_bits;
1887 seq_param->pic_width_in_luma_samples = encoder->luma_width;
1888 seq_param->pic_height_in_luma_samples = encoder->luma_height;
1890 /*sequence field values */
1891 seq_param->seq_fields.value = 0;
1892 seq_param->seq_fields.bits.chroma_format_idc =
1893 gst_vaapi_utils_h265_get_chroma_format_idc
1894 (gst_vaapi_video_format_get_chroma_type (GST_VIDEO_INFO_FORMAT
1895 (GST_VAAPI_ENCODER_VIDEO_INFO (encoder))));
1896 /* the 4:4:4 chrome format */
1897 if (seq_param->seq_fields.bits.chroma_format_idc == 3)
1898 seq_param->seq_fields.bits.separate_colour_plane_flag = 0;
1899 seq_param->seq_fields.bits.separate_colour_plane_flag = 0;
1900 seq_param->seq_fields.bits.bit_depth_luma_minus8 = bits_depth_luma_minus8;
1901 seq_param->seq_fields.bits.bit_depth_chroma_minus8 = bits_depth_luma_minus8;
1902 seq_param->seq_fields.bits.scaling_list_enabled_flag = FALSE;
1903 seq_param->seq_fields.bits.strong_intra_smoothing_enabled_flag = TRUE;
1904 seq_param->seq_fields.bits.amp_enabled_flag = TRUE;
1905 seq_param->seq_fields.bits.sample_adaptive_offset_enabled_flag =
1906 encoder->sample_adaptive_offset_enabled_flag = FALSE;
1907 seq_param->seq_fields.bits.pcm_enabled_flag = FALSE;
1908 seq_param->seq_fields.bits.pcm_loop_filter_disabled_flag = FALSE;
1909 seq_param->seq_fields.bits.sps_temporal_mvp_enabled_flag =
1910 encoder->sps_temporal_mvp_enabled_flag = TRUE;
1912 /* Based on 32x32 CTU (64x64 when using lowpower mode for hardware limitation) */
1913 seq_param->log2_min_luma_coding_block_size_minus3 = 0;
1914 if (encoder->entrypoint == GST_VAAPI_ENTRYPOINT_SLICE_ENCODE_LP)
1915 seq_param->log2_diff_max_min_luma_coding_block_size = 3;
1917 seq_param->log2_diff_max_min_luma_coding_block_size = 2;
1918 seq_param->log2_min_transform_block_size_minus2 = 0;
1919 seq_param->log2_diff_max_min_transform_block_size = 3;
1921 * Intel HW supports up to 2, we can provide a quirk for other HWs in future
1922 * if other HW may support other values
1924 * Refer to https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-kbl-vol10-hevc.pdf
1926 seq_param->max_transform_hierarchy_depth_inter = 2;
1927 seq_param->max_transform_hierarchy_depth_intra = 2;
1929 seq_param->pcm_sample_bit_depth_luma_minus1 = 0;
1930 seq_param->pcm_sample_bit_depth_chroma_minus1 = 0;
1931 seq_param->log2_min_pcm_luma_coding_block_size_minus3 = 0;
1932 seq_param->log2_max_pcm_luma_coding_block_size_minus3 = 0;
1934 /* VUI parameters are always set, at least for timing_info (framerate) */
1935 seq_param->vui_parameters_present_flag = TRUE;
1936 if (seq_param->vui_parameters_present_flag) {
1937 seq_param->vui_fields.bits.aspect_ratio_info_present_flag = TRUE;
1938 if (seq_param->vui_fields.bits.aspect_ratio_info_present_flag) {
1939 const GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
1940 seq_param->aspect_ratio_idc = 0xff;
1941 seq_param->sar_width = GST_VIDEO_INFO_PAR_N (vip);
1942 seq_param->sar_height = GST_VIDEO_INFO_PAR_D (vip);
1944 seq_param->vui_fields.bits.bitstream_restriction_flag = FALSE;
1945 seq_param->vui_fields.bits.vui_timing_info_present_flag = TRUE;
1946 if (seq_param->vui_fields.bits.vui_timing_info_present_flag) {
1947 seq_param->vui_num_units_in_tick = GST_VAAPI_ENCODER_FPS_D (encoder);
1948 seq_param->vui_time_scale = GST_VAAPI_ENCODER_FPS_N (encoder);
1952 if (h265_is_scc (encoder)) {
1953 #if VA_CHECK_VERSION(1,8,0)
1954 seq_param->scc_fields.bits.palette_mode_enabled_flag = 1;
1956 /* SCC profile should not be selected. */
1957 g_assert_not_reached ();
1965 /* CTUs in each tile column */
1966 static guint32 tile_ctu_cols[GST_VAAPI_H265_MAX_COL_TILES];
1967 /* CTUs in each tile row */
1968 static guint32 tile_ctu_rows[GST_VAAPI_H265_MAX_ROW_TILES];
1970 /* Fills in VA picture parameter buffer */
1972 fill_picture (GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture,
1973 GstVaapiCodedBuffer * codedbuf, GstVaapiSurfaceProxy * surface)
1975 VAEncPictureParameterBufferHEVC *const pic_param = picture->param;
1976 GstVaapiH265RefPool *const ref_pool = &encoder->ref_pool;
1977 GstVaapiEncoderH265Ref *ref_pic;
1980 guint8 nal_unit_type, no_output_of_prior_pics_flag = 0;
1982 memset (pic_param, 0, sizeof (VAEncPictureParameterBufferHEVC));
1984 pic_param->decoded_curr_pic.picture_id =
1985 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (surface);
1986 pic_param->decoded_curr_pic.pic_order_cnt = picture->poc;
1987 pic_param->decoded_curr_pic.flags = 0;
1990 if (picture->type != GST_VAAPI_PICTURE_TYPE_I) {
1991 for (reflist = g_queue_peek_head_link (&ref_pool->ref_list);
1992 reflist; reflist = g_list_next (reflist)) {
1993 ref_pic = reflist->data;
1994 g_assert (ref_pic && ref_pic->pic &&
1995 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (ref_pic->pic) != VA_INVALID_ID);
1997 pic_param->reference_frames[i].picture_id =
1998 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (ref_pic->pic);
1999 pic_param->reference_frames[i].pic_order_cnt = ref_pic->poc;
2002 g_assert (i <= 15 && i <= ref_pool->max_ref_frames);
2004 for (; i < 15; ++i) {
2005 pic_param->reference_frames[i].picture_id = VA_INVALID_SURFACE;
2006 pic_param->reference_frames[i].flags = VA_PICTURE_HEVC_INVALID;
2008 pic_param->coded_buf = GST_VAAPI_CODED_BUFFER_ID (codedbuf);
2010 /* slice_temporal_mvp_enable_flag == FALSE */
2011 pic_param->collocated_ref_pic_index = 0xFF;
2013 pic_param->last_picture = 0;
2014 pic_param->pic_init_qp = encoder->qp_i;
2015 pic_param->num_ref_idx_l0_default_active_minus1 =
2016 (ref_pool->max_reflist0_count ? (ref_pool->max_reflist0_count - 1) : 0);
2017 pic_param->num_ref_idx_l1_default_active_minus1 =
2018 (ref_pool->max_reflist1_count ? (ref_pool->max_reflist1_count - 1) : 0);
2020 if (!get_nal_unit_type (picture, &nal_unit_type))
2022 pic_param->nal_unit_type = nal_unit_type;
2024 /* set picture fields */
2025 pic_param->pic_fields.value = 0;
2026 pic_param->pic_fields.bits.idr_pic_flag =
2027 GST_VAAPI_ENC_PICTURE_IS_IDR (picture);
2028 pic_param->pic_fields.bits.coding_type = picture->type;
2029 if (picture->type != GST_VAAPI_PICTURE_TYPE_B)
2030 pic_param->pic_fields.bits.reference_pic_flag = TRUE;
2031 pic_param->pic_fields.bits.sign_data_hiding_enabled_flag = FALSE;
2032 pic_param->pic_fields.bits.transform_skip_enabled_flag = TRUE;
2033 /* it seems driver requires enablement of cu_qp_delta_enabled_flag
2034 * to modifiy QP values in CBR mode or low power encoding */
2035 if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) != GST_VAAPI_RATECONTROL_CQP
2037 || encoder->entrypoint == GST_VAAPI_ENTRYPOINT_SLICE_ENCODE_LP)
2038 pic_param->pic_fields.bits.cu_qp_delta_enabled_flag = 1;
2040 /* XXX: Intel's media-driver, when using low-power mode, requires
2041 * that diff_cu_qp_delta_depth has to be equal to
2042 * log2_diff_max_min_luma_coding_block_size, meaning 3.
2044 * For now we assume that on only Intel's media-drivers supports
2046 if ((encoder->entrypoint == GST_VAAPI_ENTRYPOINT_SLICE_ENCODE_LP) &&
2047 (pic_param->pic_fields.bits.cu_qp_delta_enabled_flag))
2048 pic_param->diff_cu_qp_delta_depth = 3;
2050 pic_param->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag = TRUE;
2052 if (GST_VAAPI_ENC_PICTURE_IS_IDR (picture))
2053 no_output_of_prior_pics_flag = 1;
2054 pic_param->pic_fields.bits.no_output_of_prior_pics_flag =
2055 no_output_of_prior_pics_flag;
2057 /* Setup tile info */
2058 pic_param->pic_fields.bits.tiles_enabled_flag =
2059 h265_is_tile_enabled (encoder);
2060 if (pic_param->pic_fields.bits.tiles_enabled_flag) {
2061 /* Always set loop filter across tiles enabled now */
2062 pic_param->pic_fields.bits.loop_filter_across_tiles_enabled_flag = 1;
2064 pic_param->num_tile_columns_minus1 = encoder->num_tile_cols - 1;
2065 pic_param->num_tile_rows_minus1 = encoder->num_tile_rows - 1;
2067 /* The VA row_height_minus1 and column_width_minus1 size is 1 smaller
2068 than the MAX_COL_TILES and MAX_ROW_TILES, which means the driver
2069 can deduce the last tile's size based on the picture info. We need
2070 to take care of the array size here. */
2071 for (i = 0; i < MIN (encoder->num_tile_cols, 19); ++i)
2072 pic_param->column_width_minus1[i] = tile_ctu_cols[i] - 1;
2073 for (i = 0; i < MIN (encoder->num_tile_rows, 21); ++i)
2074 pic_param->row_height_minus1[i] = tile_ctu_rows[i] - 1;
2077 if (h265_is_scc (encoder)) {
2078 #if VA_CHECK_VERSION(1,8,0)
2079 pic_param->scc_fields.bits.pps_curr_pic_ref_enabled_flag = 1;
2081 /* SCC profile should not be selected. */
2082 g_assert_not_reached ();
2090 static GstVaapiEncSlice *
2091 create_and_fill_one_slice (GstVaapiEncoderH265 * encoder,
2092 GstVaapiEncPicture * picture,
2093 GstVaapiEncoderH265Ref ** reflist_0, guint reflist_0_count,
2094 GstVaapiEncoderH265Ref ** reflist_1, guint reflist_1_count)
2096 VAEncSliceParameterBufferHEVC *slice_param;
2097 GstVaapiEncSlice *slice;
2100 slice = GST_VAAPI_ENC_SLICE_NEW (HEVC, encoder);
2101 g_assert (slice && slice->param_id != VA_INVALID_ID);
2102 slice_param = slice->param;
2103 memset (slice_param, 0, sizeof (VAEncSliceParameterBufferHEVC));
2105 slice_param->slice_type = h265_get_slice_type (picture->type);
2106 if (encoder->no_p_frame && slice_param->slice_type == GST_H265_P_SLICE) {
2107 slice_param->slice_type = GST_H265_B_SLICE;
2108 } else if (h265_is_scc (encoder) &&
2109 slice_param->slice_type == GST_H265_I_SLICE) {
2110 /* In scc mode, the I frame can ref to itself and so need the L0
2111 reference list enabled. Just set the I frame to P_SLICE type
2112 and leaving all reference unchanged. So all ref_pic_list0's
2113 picture is invalid, the only ref is itself enabled by
2114 pic_param->scc_fields.bits.pps_curr_pic_ref_enabled_flag. */
2115 slice_param->slice_type = GST_H265_P_SLICE;
2118 slice_param->slice_pic_parameter_set_id = 0;
2120 slice_param->slice_fields.bits.num_ref_idx_active_override_flag =
2121 reflist_0_count || reflist_1_count;
2122 if (picture->type != GST_VAAPI_PICTURE_TYPE_I && reflist_0_count > 0)
2123 slice_param->num_ref_idx_l0_active_minus1 = reflist_0_count - 1;
2125 slice_param->num_ref_idx_l0_active_minus1 = 0;
2126 if (picture->type == GST_VAAPI_PICTURE_TYPE_B && reflist_1_count > 0)
2127 slice_param->num_ref_idx_l1_active_minus1 = reflist_1_count - 1;
2129 slice_param->num_ref_idx_l1_active_minus1 = 0;
2130 if (picture->type == GST_VAAPI_PICTURE_TYPE_P && encoder->no_p_frame)
2131 slice_param->num_ref_idx_l1_active_minus1 =
2132 slice_param->num_ref_idx_l0_active_minus1;
2135 if (picture->type != GST_VAAPI_PICTURE_TYPE_I) {
2136 for (; i_ref < reflist_0_count; ++i_ref) {
2137 slice_param->ref_pic_list0[i_ref].picture_id =
2138 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (reflist_0[i_ref]->pic);
2139 slice_param->ref_pic_list0[i_ref].pic_order_cnt = reflist_0[i_ref]->poc;
2142 for (; i_ref < G_N_ELEMENTS (slice_param->ref_pic_list0); ++i_ref) {
2143 slice_param->ref_pic_list0[i_ref].picture_id = VA_INVALID_SURFACE;
2144 slice_param->ref_pic_list0[i_ref].flags = VA_PICTURE_HEVC_INVALID;
2148 if (picture->type == GST_VAAPI_PICTURE_TYPE_B) {
2149 for (; i_ref < reflist_1_count; ++i_ref) {
2150 slice_param->ref_pic_list1[i_ref].picture_id =
2151 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (reflist_1[i_ref]->pic);
2152 slice_param->ref_pic_list1[i_ref].pic_order_cnt = reflist_1[i_ref]->poc;
2154 } else if (picture->type == GST_VAAPI_PICTURE_TYPE_P && encoder->no_p_frame) {
2155 for (; i_ref < reflist_0_count; ++i_ref) {
2156 slice_param->ref_pic_list1[i_ref].picture_id =
2157 GST_VAAPI_SURFACE_PROXY_SURFACE_ID (reflist_0[i_ref]->pic);
2158 slice_param->ref_pic_list1[i_ref].pic_order_cnt = reflist_0[i_ref]->poc;
2161 for (; i_ref < G_N_ELEMENTS (slice_param->ref_pic_list1); ++i_ref) {
2162 slice_param->ref_pic_list1[i_ref].picture_id = VA_INVALID_SURFACE;
2163 slice_param->ref_pic_list1[i_ref].flags = VA_PICTURE_HEVC_INVALID;
2166 slice_param->max_num_merge_cand = 5; /* MaxNumMergeCand */
2167 slice_param->slice_qp_delta = encoder->qp_i - encoder->init_qp;
2168 if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CQP) {
2169 if (picture->type == GST_VAAPI_PICTURE_TYPE_P) {
2170 slice_param->slice_qp_delta += encoder->qp_ip;
2171 } else if (picture->type == GST_VAAPI_PICTURE_TYPE_B) {
2172 slice_param->slice_qp_delta += encoder->qp_ib;
2174 if ((gint) encoder->init_qp + slice_param->slice_qp_delta <
2175 (gint) encoder->min_qp) {
2176 slice_param->slice_qp_delta = encoder->min_qp - encoder->init_qp;
2178 if ((gint) encoder->init_qp + slice_param->slice_qp_delta >
2179 (gint) encoder->max_qp) {
2180 slice_param->slice_qp_delta = encoder->max_qp - encoder->init_qp;
2184 slice_param->slice_fields.bits.slice_loop_filter_across_slices_enabled_flag =
2190 /* Adds slice headers to picture */
2192 add_slice_headers (GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture,
2193 GstVaapiEncoderH265Ref ** reflist_0, guint reflist_0_count,
2194 GstVaapiEncoderH265Ref ** reflist_1, guint reflist_1_count)
2196 VAEncSliceParameterBufferHEVC *slice_param;
2197 GstVaapiEncSlice *slice;
2198 guint slice_of_ctus, slice_mod_ctus, cur_slice_ctus;
2200 guint ctu_width_round_factor;
2201 guint last_ctu_index;
2206 if (h265_is_tile_enabled (encoder)) {
2207 for (i_slice = 0; i_slice < encoder->num_slices; ++i_slice) {
2208 encoder->first_slice_segment_in_pic_flag = (i_slice == 0);
2210 slice = create_and_fill_one_slice (encoder, picture, reflist_0,
2211 reflist_0_count, reflist_1, reflist_1_count);
2212 slice_param = slice->param;
2214 slice_param->slice_segment_address =
2215 encoder->tile_slice_address_map[encoder->tile_slice_address[i_slice]];
2216 slice_param->num_ctu_in_slice = encoder->tile_slice_ctu_num[i_slice];
2217 GST_LOG ("slice %d start tile address is %d, start address is %d,"
2218 " CTU num %d", i_slice, encoder->tile_slice_address[i_slice],
2219 slice_param->slice_segment_address, slice_param->num_ctu_in_slice);
2221 if (i_slice == encoder->num_slices - 1)
2222 slice_param->slice_fields.bits.last_slice_of_pic_flag = 1;
2224 if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2225 VA_ENC_PACKED_HEADER_SLICE)
2226 && !add_packed_slice_header (encoder, picture, slice))
2227 goto error_create_packed_slice_hdr;
2229 gst_vaapi_enc_picture_add_slice (picture, slice);
2230 gst_vaapi_codec_object_replace (&slice, NULL);
2233 ctu_size = encoder->ctu_width * encoder->ctu_height;
2235 g_assert (encoder->num_slices && encoder->num_slices < ctu_size);
2236 slice_of_ctus = ctu_size / encoder->num_slices;
2237 slice_mod_ctus = ctu_size % encoder->num_slices;
2241 i_slice < encoder->num_slices && (last_ctu_index < ctu_size);
2243 cur_slice_ctus = slice_of_ctus;
2244 if (slice_mod_ctus) {
2249 slice = create_and_fill_one_slice (encoder, picture, reflist_0,
2250 reflist_0_count, reflist_1, reflist_1_count);
2251 slice_param = slice->param;
2253 /* Work-around for satisfying the VA-Intel driver.
2254 * The driver only support multi slice begin from row start address */
2255 ctu_width_round_factor =
2256 encoder->ctu_width - (cur_slice_ctus % encoder->ctu_width);
2257 cur_slice_ctus += ctu_width_round_factor;
2258 if ((last_ctu_index + cur_slice_ctus) > ctu_size)
2259 cur_slice_ctus = ctu_size - last_ctu_index;
2262 encoder->first_slice_segment_in_pic_flag = TRUE;
2263 slice_param->slice_segment_address = 0;
2265 encoder->first_slice_segment_in_pic_flag = FALSE;
2266 slice_param->slice_segment_address = last_ctu_index;
2268 slice_param->num_ctu_in_slice = cur_slice_ctus;
2270 /* set calculation for next slice */
2271 last_ctu_index += cur_slice_ctus;
2273 if ((i_slice == encoder->num_slices - 1) || (last_ctu_index == ctu_size))
2274 slice_param->slice_fields.bits.last_slice_of_pic_flag = 1;
2276 if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2277 VA_ENC_PACKED_HEADER_SLICE)
2278 && !add_packed_slice_header (encoder, picture, slice))
2279 goto error_create_packed_slice_hdr;
2281 gst_vaapi_enc_picture_add_slice (picture, slice);
2282 gst_vaapi_codec_object_replace (&slice, NULL);
2285 if (i_slice < encoder->num_slices)
2287 ("Using less number of slices than requested, Number of slices per"
2288 " pictures is %d", i_slice);
2289 g_assert (last_ctu_index == ctu_size);
2294 error_create_packed_slice_hdr:
2296 GST_ERROR ("failed to create packed slice header buffer");
2297 gst_vaapi_codec_object_replace (&slice, NULL);
2302 /* Generates and submits SPS header accordingly into the bitstream */
2304 ensure_sequence (GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture)
2306 GstVaapiEncSequence *sequence = NULL;
2308 /* submit an SPS header before every new I-frame, if codec config changed */
2309 if (!encoder->config_changed || picture->type != GST_VAAPI_PICTURE_TYPE_I)
2312 sequence = GST_VAAPI_ENC_SEQUENCE_NEW (HEVC, encoder);
2313 if (!sequence || !fill_sequence (encoder, sequence))
2314 goto error_create_seq_param;
2316 /* add packed vps and sps headers */
2317 if ((GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2318 VA_ENC_PACKED_HEADER_SEQUENCE)
2319 && !(add_packed_vps_header (encoder, picture, sequence)
2320 && add_packed_sequence_header (encoder, picture, sequence))) {
2321 goto error_create_packed_seq_hdr;
2325 gst_vaapi_enc_picture_set_sequence (picture, sequence);
2326 gst_vaapi_codec_object_replace (&sequence, NULL);
2329 encoder->config_changed = FALSE;
2333 error_create_seq_param:
2335 GST_ERROR ("failed to create sequence parameter buffer (SPS)");
2336 gst_vaapi_codec_object_replace (&sequence, NULL);
2339 error_create_packed_seq_hdr:
2341 GST_ERROR ("failed to create packed sequence header buffer");
2342 gst_vaapi_codec_object_replace (&sequence, NULL);
2348 ensure_control_rate_params (GstVaapiEncoderH265 * encoder)
2350 if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CQP)
2353 #if VA_CHECK_VERSION(1,1,0)
2354 if (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_ICQ) {
2355 GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).ICQ_quality_factor =
2356 encoder->quality_factor;
2361 /* RateControl params */
2362 GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).bits_per_second =
2363 encoder->bitrate_bits;
2364 /* CPB (Coded picture buffer) length in milliseconds, which could be
2365 * provided as a property */
2366 GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).window_size = encoder->cpb_length;
2367 GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).initial_qp = encoder->init_qp;
2368 GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).min_qp = encoder->min_qp;
2370 #if VA_CHECK_VERSION(1,1,0)
2371 GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).max_qp = encoder->max_qp;
2374 #if VA_CHECK_VERSION(1,0,0)
2375 GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).rc_flags.bits.mb_rate_control =
2376 (guint) encoder->mbbrc;
2379 #if VA_CHECK_VERSION(1,3,0)
2380 GST_VAAPI_ENCODER_VA_RATE_CONTROL (encoder).quality_factor =
2381 encoder->quality_factor;
2385 fill_hrd_params (encoder, &GST_VAAPI_ENCODER_VA_HRD (encoder));
2391 ensure_misc_params (GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture)
2393 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2395 if (!gst_vaapi_encoder_ensure_param_control_rate (base_encoder, picture))
2397 if (!gst_vaapi_encoder_ensure_param_roi_regions (base_encoder, picture))
2399 if (!gst_vaapi_encoder_ensure_param_quality_level (base_encoder, picture))
2404 /* Generates and submits PPS header accordingly into the bitstream */
2406 ensure_picture (GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture,
2407 GstVaapiCodedBufferProxy * codedbuf_proxy, GstVaapiSurfaceProxy * surface)
2409 GstVaapiCodedBuffer *const codedbuf =
2410 GST_VAAPI_CODED_BUFFER_PROXY_BUFFER (codedbuf_proxy);
2411 gboolean res = FALSE;
2413 res = fill_picture (encoder, picture, codedbuf, surface);
2418 if (picture->type == GST_VAAPI_PICTURE_TYPE_I &&
2419 (GST_VAAPI_ENCODER_PACKED_HEADERS (encoder) &
2420 VA_ENC_PACKED_HEADER_PICTURE)
2421 && !add_packed_picture_header (encoder, picture)) {
2422 GST_ERROR ("set picture packed header failed");
2429 /* Generates slice headers */
2431 ensure_slices (GstVaapiEncoderH265 * encoder, GstVaapiEncPicture * picture)
2433 GstVaapiEncoderH265Ref *reflist_0[15];
2434 GstVaapiEncoderH265Ref *reflist_1[15];
2435 GstVaapiH265RefPool *const ref_pool = &encoder->ref_pool;
2436 guint reflist_0_count = 0, reflist_1_count = 0;
2440 if (picture->type != GST_VAAPI_PICTURE_TYPE_I &&
2441 !reference_list_init (encoder, picture,
2442 reflist_0, &reflist_0_count, reflist_1, &reflist_1_count)) {
2443 GST_ERROR ("reference list reorder failed");
2447 g_assert (reflist_0_count + reflist_1_count <= ref_pool->max_ref_frames);
2448 if (reflist_0_count > ref_pool->max_reflist0_count)
2449 reflist_0_count = ref_pool->max_reflist0_count;
2450 if (reflist_1_count > ref_pool->max_reflist1_count)
2451 reflist_1_count = ref_pool->max_reflist1_count;
2453 if (!add_slice_headers (encoder, picture,
2454 reflist_0, reflist_0_count, reflist_1, reflist_1_count))
2460 /* Normalizes bitrate (and CPB size) for HRD conformance */
2462 ensure_bitrate_hrd (GstVaapiEncoderH265 * encoder)
2464 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2465 guint bitrate, cpb_size;
2467 if (!base_encoder->bitrate) {
2468 encoder->bitrate_bits = 0;
2472 /* Round down bitrate. This is a hard limit mandated by the user */
2473 g_assert (SX_BITRATE >= 6);
2474 bitrate = (base_encoder->bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
2475 if (bitrate != encoder->bitrate_bits) {
2476 GST_DEBUG ("HRD bitrate: %u bits/sec", bitrate);
2477 encoder->bitrate_bits = bitrate;
2478 encoder->config_changed = TRUE;
2481 /* Round up CPB size. This is an HRD compliance detail */
2482 g_assert (SX_CPB_SIZE >= 4);
2483 cpb_size = gst_util_uint64_scale (bitrate, encoder->cpb_length, 1000) &
2484 ~((1U << SX_CPB_SIZE) - 1);
2485 if (cpb_size != encoder->cpb_length_bits) {
2486 GST_DEBUG ("HRD CPB size: %u bits", cpb_size);
2487 encoder->cpb_length_bits = cpb_size;
2488 encoder->config_changed = TRUE;
2492 /* Estimates a good enough bitrate if none was supplied */
2494 ensure_bitrate (GstVaapiEncoderH265 * encoder)
2496 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2498 switch (GST_VAAPI_ENCODER_RATE_CONTROL (encoder)) {
2499 case GST_VAAPI_RATECONTROL_CBR:
2500 case GST_VAAPI_RATECONTROL_VBR:
2501 case GST_VAAPI_RATECONTROL_QVBR:
2502 if (!base_encoder->bitrate) {
2503 /* FIXME: Provide better estimation */
2504 /* Using a 1/6 compression ratio */
2505 /* 12 bits per pixel for YUV420 */
2508 factor = (guint64) encoder->luma_width * encoder->luma_height * 12 / 6;
2509 base_encoder->bitrate =
2510 gst_util_uint64_scale (factor, GST_VAAPI_ENCODER_FPS_N (encoder),
2511 GST_VAAPI_ENCODER_FPS_D (encoder)) / 1000;
2512 GST_INFO ("target bitrate computed to %u kbps", base_encoder->bitrate);
2516 base_encoder->bitrate = 0;
2519 ensure_bitrate_hrd (encoder);
2522 /* Constructs profile, tier and level information based on user-defined limits */
2523 static GstVaapiEncoderStatus
2524 ensure_profile_tier_level (GstVaapiEncoderH265 * encoder)
2526 const GstVaapiProfile profile = encoder->profile;
2527 const GstVaapiTierH265 tier = encoder->tier;
2528 const GstVaapiLevelH265 level = encoder->level;
2530 if (!ensure_profile (encoder))
2531 return GST_VAAPI_ENCODER_STATUS_ERROR_UNSUPPORTED_PROFILE;
2533 encoder->entrypoint =
2534 gst_vaapi_encoder_get_entrypoint (GST_VAAPI_ENCODER_CAST (encoder),
2536 g_assert (encoder->entrypoint != GST_VAAPI_ENTRYPOINT_INVALID);
2538 /* Ensure bitrate if not set already and derive the right level to use */
2539 ensure_bitrate (encoder);
2541 if (!ensure_tier_level (encoder))
2542 return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
2544 if (encoder->profile != profile || encoder->level != level
2545 || encoder->tier != tier) {
2546 GST_DEBUG ("selected %s profile at tier %s and level %s",
2547 gst_vaapi_utils_h265_get_profile_string (encoder->profile),
2548 gst_vaapi_utils_h265_get_tier_string (encoder->tier),
2549 gst_vaapi_utils_h265_get_level_string (encoder->level));
2550 encoder->config_changed = TRUE;
2552 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2556 check_ref_list (GstVaapiEncoderH265 * encoder)
2558 #if VA_CHECK_VERSION(1,9,0)
2559 /* Some driver require both r0 and r1 list are non NULL, i.e. no p frame
2560 in the stream. The traditional P frame can be converted to B frame with
2561 forward dependency only. The new B frame has only forward reference in
2562 both r0 and r1 list, which conforms to H265 spec. This can get some gain
2563 because there are 2 MVs for each frame and can generate better motion
2565 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER (encoder);
2567 VAProfile va_profile = gst_vaapi_profile_get_va_profile (encoder->profile);
2568 VAEntrypoint va_entrypoint =
2569 gst_vaapi_entrypoint_get_va_entrypoint (encoder->entrypoint);
2571 encoder->no_p_frame = FALSE;
2572 if (gst_vaapi_get_config_attribute (base_encoder->display, va_profile,
2573 va_entrypoint, VAConfigAttribPredictionDirection, &value)) {
2574 gboolean double_ref_list =
2575 ((value & VA_PREDICTION_DIRECTION_BI_NOT_EMPTY) != 0);
2576 if (double_ref_list) {
2577 GST_INFO ("driver does not support P frame, we need to convert P"
2578 " frame to forward dependency B frame.");
2579 encoder->no_p_frame = double_ref_list;
2583 if (encoder->no_p_frame == TRUE && base_encoder->max_num_ref_frames_1 < 1) {
2584 GST_WARNING ("P frame should be converted to forward dependent B,"
2585 " but reference list 1 is disabled here. Should be an invalid"
2586 " setting or a driver error.");
2594 static GstVaapiEncoderStatus
2595 reset_properties (GstVaapiEncoderH265 * encoder)
2597 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER_CAST (encoder);
2598 GstVaapiH265ReorderPool *reorder_pool;
2599 GstVaapiH265RefPool *ref_pool;
2603 if (encoder->idr_period < base_encoder->keyframe_period)
2604 encoder->idr_period = base_encoder->keyframe_period;
2606 if (encoder->min_qp > encoder->init_qp)
2607 encoder->min_qp = encoder->init_qp;
2608 if (encoder->max_qp < encoder->init_qp)
2609 encoder->max_qp = encoder->init_qp;
2611 encoder->qp_i = encoder->init_qp;
2613 ctu_size = encoder->ctu_width * encoder->ctu_height;
2614 ret = gst_vaapi_encoder_ensure_num_slices (base_encoder, encoder->profile,
2615 encoder->entrypoint, (ctu_size + 1) / 2, &encoder->num_slices);
2618 gst_vaapi_encoder_ensure_max_num_ref_frames (base_encoder, encoder->profile,
2619 encoder->entrypoint);
2621 if (!check_ref_list (encoder))
2622 return GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
2624 if (base_encoder->max_num_ref_frames_1 < 1 && encoder->num_bframes > 0) {
2625 GST_WARNING ("Disabling b-frame since the driver doesn't support it");
2626 encoder->num_bframes = 0;
2629 if (encoder->num_ref_frames > base_encoder->max_num_ref_frames_0) {
2630 GST_INFO ("Lowering the number of reference frames to %d",
2631 base_encoder->max_num_ref_frames_0);
2632 encoder->num_ref_frames = base_encoder->max_num_ref_frames_0;
2635 if (encoder->num_bframes > (base_encoder->keyframe_period + 1) / 2)
2636 encoder->num_bframes = (base_encoder->keyframe_period + 1) / 2;
2638 if (encoder->num_bframes > 0 && GST_VAAPI_ENCODER_FPS_N (encoder) > 0)
2639 encoder->cts_offset = gst_util_uint64_scale (GST_SECOND,
2640 GST_VAAPI_ENCODER_FPS_D (encoder), GST_VAAPI_ENCODER_FPS_N (encoder));
2642 encoder->cts_offset = 0;
2645 encoder->log2_max_pic_order_cnt =
2646 h265_get_log2_max_pic_order_cnt (encoder->idr_period);
2647 g_assert (encoder->log2_max_pic_order_cnt >= 4);
2648 encoder->max_pic_order_cnt = (1 << encoder->log2_max_pic_order_cnt);
2649 encoder->idr_num = 0;
2651 /* Only Supporting a maximum of two reference frames */
2652 if (encoder->num_bframes) {
2653 encoder->max_dec_pic_buffering = encoder->num_ref_frames + 2;
2654 encoder->max_num_reorder_pics = 1;
2656 encoder->max_dec_pic_buffering = encoder->num_ref_frames + 1;
2657 encoder->max_num_reorder_pics = 0;
2660 ref_pool = &encoder->ref_pool;
2661 ref_pool->max_reflist0_count = encoder->num_ref_frames;
2662 ref_pool->max_reflist1_count = encoder->num_bframes > 0;
2663 ref_pool->max_ref_frames = ref_pool->max_reflist0_count
2664 + ref_pool->max_reflist1_count;
2666 reorder_pool = &encoder->reorder_pool;
2667 reorder_pool->frame_index = 0;
2669 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2673 reset_tile (GstVaapiEncoderH265 * encoder)
2675 memset (tile_ctu_cols, 0, sizeof (tile_ctu_cols));
2676 memset (tile_ctu_rows, 0, sizeof (tile_ctu_rows));
2678 if (encoder->tile_slice_address)
2679 g_free (encoder->tile_slice_address);
2680 encoder->tile_slice_address = NULL;
2682 if (encoder->tile_slice_ctu_num)
2683 g_free (encoder->tile_slice_ctu_num);
2684 encoder->tile_slice_ctu_num = NULL;
2686 if (encoder->tile_slice_address_map)
2687 g_free (encoder->tile_slice_address_map);
2688 encoder->tile_slice_address_map = NULL;
2692 recalculate_slices_num_by_tile (GstVaapiEncoderH265 * encoder)
2694 GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
2696 /* If driver has the requirement that the slice should not span tiles,
2697 we need to increase slice number if needed. */
2698 if (gst_vaapi_display_has_driver_quirks (display,
2699 GST_VAAPI_DRIVER_QUIRK_HEVC_ENC_SLICE_NOT_SPAN_TILE)) {
2700 if (encoder->num_slices < encoder->num_tile_cols * encoder->num_tile_rows) {
2701 /* encoder->num_slices > 1 means user set it */
2702 if (encoder->num_slices > 1)
2703 GST_WARNING ("user set num-slices to %d, which is smaller than tile"
2704 " num %d. We should make slice not span tiles, just set the"
2705 " num-slices to tile num here.",
2706 encoder->num_slices,
2707 encoder->num_tile_cols * encoder->num_tile_rows);
2709 GST_INFO ("set default slice num to %d, the same as the tile num.",
2710 encoder->num_tile_cols * encoder->num_tile_rows);
2711 encoder->num_slices = encoder->num_tile_cols * encoder->num_tile_rows;
2716 static GstVaapiEncoderStatus
2717 calculate_slices_start_address (GstVaapiEncoderH265 * encoder)
2719 GstVaapiDisplay *const display = GST_VAAPI_ENCODER_DISPLAY (encoder);
2720 guint32 ctu_per_slice;
2721 guint32 left_slices;
2724 /* If driver has the requirement that the slice should not span tiles,
2725 firstly we should scatter slices uniformly into each tile, bigger
2726 tile gets more slices. Then we should assign CTUs within one tile
2727 uniformly to each slice in that tile. */
2728 if (gst_vaapi_display_has_driver_quirks (display,
2729 GST_VAAPI_DRIVER_QUIRK_HEVC_ENC_SLICE_NOT_SPAN_TILE)) {
2730 guint32 *slices_per_tile = g_malloc (encoder->num_tile_cols *
2731 encoder->num_tile_rows * sizeof (guint32));
2732 if (!slices_per_tile)
2733 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2735 ctu_per_slice = (encoder->ctu_width * encoder->ctu_height +
2736 encoder->num_slices - 1) / encoder->num_slices;
2737 g_assert (ctu_per_slice > 0);
2738 left_slices = encoder->num_slices;
2740 for (i = 0; i < encoder->num_tile_cols * encoder->num_tile_rows; i++) {
2741 slices_per_tile[i] = 1;
2744 while (left_slices) {
2745 /* Find the biggest CTUs/slices, and assign more. */
2746 gfloat largest = 0.0f;
2748 for (i = 0; i < encoder->num_tile_cols * encoder->num_tile_rows; i++) {
2750 f = ((gfloat) (tile_ctu_cols[i % encoder->num_tile_cols] *
2751 tile_ctu_rows[i / encoder->num_tile_cols])) /
2752 (gfloat) slices_per_tile[i];
2753 g_assert (f >= 1.0f);
2761 slices_per_tile[k]++;
2765 /* Assign CTUs in one tile uniformly to each slice. Note: the slice start
2766 address is CTB address in tile scan(see spec 6.5), that is, we accumulate
2767 all CTUs in tile0, then tile1, and tile2..., not from the picture's
2769 encoder->tile_slice_address[0] = 0;
2771 for (i = 0; i < encoder->num_tile_rows; i++) {
2772 for (j = 0; j < encoder->num_tile_cols; j++) {
2773 guint32 s_num = slices_per_tile[i * encoder->num_tile_cols + j];
2774 guint32 one_tile_ctus = tile_ctu_cols[j] * tile_ctu_rows[i];
2777 GST_LOG ("Tile(row %d col %d), has CTU in col %d,"
2778 " CTU in row is %d, total CTU %d, assigned %d slices", i, j,
2779 tile_ctu_cols[j], tile_ctu_rows[i], one_tile_ctus, s_num);
2781 g_assert (s_num > 0);
2782 for (s = 0; s < s_num; s++) {
2783 encoder->tile_slice_address[k] =
2784 encoder->tile_slice_address[k - 1] + ((s +
2785 1) * one_tile_ctus) / s_num - (s * one_tile_ctus) / s_num;
2786 encoder->tile_slice_ctu_num[k - 1] =
2787 encoder->tile_slice_address[k] - encoder->tile_slice_address[k -
2794 g_assert (k == encoder->num_slices + 1);
2795 /* Calculate the last one */
2796 encoder->tile_slice_ctu_num[encoder->num_slices - 1] =
2797 encoder->ctu_width * encoder->ctu_height -
2798 encoder->tile_slice_address[encoder->num_slices - 1];
2800 g_free (slices_per_tile);
2802 /* The easy way, just assign CTUs to each slice uniformly */
2804 ctu_per_slice = (encoder->ctu_width * encoder->ctu_height +
2805 encoder->num_slices - 1) / encoder->num_slices;
2806 g_assert (ctu_per_slice > 0);
2808 for (i = 0; i < encoder->num_slices - 1; i++)
2809 encoder->tile_slice_ctu_num[i] = ctu_per_slice;
2810 encoder->tile_slice_ctu_num[encoder->num_slices - 1] =
2811 encoder->ctu_width * encoder->ctu_height -
2812 (encoder->num_slices - 1) * ctu_per_slice;
2814 encoder->tile_slice_address[0] = 0;
2815 for (i = 1; i <= encoder->num_slices; i++)
2816 encoder->tile_slice_address[i] = encoder->tile_slice_address[i - 1] +
2817 encoder->tile_slice_ctu_num[i - 1];
2820 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2823 static GstVaapiEncoderStatus
2824 ensure_tile (GstVaapiEncoderH265 * encoder)
2827 guint32 ctu_tile_width_accu[GST_VAAPI_H265_MAX_COL_TILES + 1];
2828 guint32 ctu_tile_height_accu[GST_VAAPI_H265_MAX_ROW_TILES + 1];
2830 GstVaapiEncoderStatus ret;
2832 reset_tile (encoder);
2834 if (!h265_is_tile_enabled (encoder))
2835 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2837 if (!gst_vaapi_encoder_ensure_tile_support (GST_VAAPI_ENCODER (encoder),
2838 encoder->profile, encoder->entrypoint)) {
2839 GST_ERROR ("The profile:%s, entrypoint:%d does not support tile.",
2840 gst_vaapi_utils_h265_get_profile_string (encoder->profile),
2841 encoder->entrypoint);
2842 return GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
2845 if (encoder->num_tile_cols >
2846 gst_vaapi_utils_h265_get_level_limits (encoder->level)->MaxTileColumns) {
2847 GST_ERROR ("num_tile_cols:%d exceeds MaxTileColumns:%d",
2848 encoder->num_tile_cols,
2849 gst_vaapi_utils_h265_get_level_limits (encoder->level)->MaxTileColumns);
2850 return GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
2852 if (encoder->num_tile_rows >
2853 gst_vaapi_utils_h265_get_level_limits (encoder->level)->MaxTileRows) {
2854 GST_ERROR ("num_tile_rows:%d exceeds MaxTileRows:%d",
2855 encoder->num_tile_rows,
2856 gst_vaapi_utils_h265_get_level_limits (encoder->level)->MaxTileRows);
2857 return GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
2860 if (encoder->ctu_width < encoder->num_tile_cols) {
2862 ("Only %d CTUs in width, not enough to split into %d tile columns",
2863 encoder->ctu_width, encoder->num_tile_cols);
2864 return GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
2866 if (encoder->ctu_height < encoder->num_tile_rows) {
2868 ("Only %d CTUs in height, not enough to split into %d tile rows",
2869 encoder->ctu_height, encoder->num_tile_rows);
2870 return GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
2873 recalculate_slices_num_by_tile (encoder);
2875 /* ensure not exceed max supported slices */
2876 num_slices = encoder->num_slices;
2877 gst_vaapi_encoder_ensure_num_slices (GST_VAAPI_ENCODER_CAST (encoder),
2878 encoder->profile, encoder->entrypoint,
2879 (encoder->ctu_width * encoder->ctu_height + 1) / 2, &num_slices);
2880 if (num_slices != encoder->num_slices) {
2881 GST_ERROR ("The tile setting need at least %d slices, but the max"
2882 " slice number is just %d", encoder->num_slices, num_slices);
2883 return GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
2886 encoder->tile_slice_address =
2887 /* Add one as sentinel, hold val to calculate ctu_num */
2888 g_malloc ((encoder->num_slices + 1) * sizeof (guint32));
2889 if (!encoder->tile_slice_address)
2890 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2891 encoder->tile_slice_ctu_num =
2892 g_malloc (encoder->num_slices * sizeof (guint32));
2893 if (!encoder->tile_slice_ctu_num)
2894 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2895 encoder->tile_slice_address_map =
2896 g_malloc (encoder->ctu_width * encoder->ctu_height * sizeof (guint32));
2897 if (!encoder->tile_slice_address_map)
2898 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
2900 /* firstly uniformly separate CTUs into tiles, as the spec 6.5.1 define */
2901 for (i = 0; i < encoder->num_tile_cols; i++)
2903 ((i + 1) * encoder->ctu_width) / encoder->num_tile_cols -
2904 (i * encoder->ctu_width) / encoder->num_tile_cols;
2905 for (i = 0; i < encoder->num_tile_rows; i++)
2907 ((i + 1) * encoder->ctu_height) / encoder->num_tile_rows -
2908 (i * encoder->ctu_height) / encoder->num_tile_rows;
2910 ret = calculate_slices_start_address (encoder);
2911 if (ret != GST_VAAPI_ENCODER_STATUS_SUCCESS)
2914 /* Build the map to specifying the conversion between a CTB address in CTB
2915 raster scan of a picture and a CTB address in tile scan(see spec 6.5.1
2917 ctu_tile_width_accu[0] = 0;
2918 for (i = 1; i <= encoder->num_tile_cols; i++)
2919 ctu_tile_width_accu[i] = ctu_tile_width_accu[i - 1] + tile_ctu_cols[i - 1];
2920 ctu_tile_height_accu[0] = 0;
2921 for (i = 1; i <= encoder->num_tile_rows; i++)
2922 ctu_tile_height_accu[i] =
2923 ctu_tile_height_accu[i - 1] + tile_ctu_rows[i - 1];
2925 for (k = 0; k < encoder->ctu_width * encoder->ctu_height; k++) {
2926 /* The ctu coordinate in the picture. */
2927 guint32 x = k % encoder->ctu_width;
2928 guint32 y = k / encoder->ctu_width;
2929 /* The ctu coordinate in the tile mode. */
2932 /* The index of the CTU in the tile mode. */
2935 for (i = 0; i < encoder->num_tile_cols; i++)
2936 if (x >= ctu_tile_width_accu[i])
2938 g_assert (tile_x <= encoder->num_tile_cols - 1);
2940 for (j = 0; j < encoder->num_tile_rows; j++)
2941 if (y >= ctu_tile_height_accu[j])
2943 g_assert (tile_y <= encoder->num_tile_rows - 1);
2945 /* add all ctus in the tiles the same line before us */
2946 for (i = 0; i < tile_x; i++)
2947 tso += tile_ctu_rows[tile_y] * tile_ctu_cols[i];
2949 /* add all ctus in the tiles above us */
2950 for (j = 0; j < tile_y; j++)
2951 tso += encoder->ctu_width * tile_ctu_rows[j];
2953 /* add the ctus inside the same tile before us */
2954 tso += (y - ctu_tile_height_accu[tile_y]) * tile_ctu_cols[tile_x]
2955 + x - ctu_tile_width_accu[tile_x];
2957 g_assert (tso < encoder->ctu_width * encoder->ctu_height);
2959 encoder->tile_slice_address_map[tso] = k;
2962 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2965 static GstVaapiEncoderStatus
2966 gst_vaapi_encoder_h265_encode (GstVaapiEncoder * base_encoder,
2967 GstVaapiEncPicture * picture, GstVaapiCodedBufferProxy * codedbuf)
2969 GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
2970 GstVaapiEncoderStatus ret = GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN;
2971 GstVaapiSurfaceProxy *reconstruct = NULL;
2973 reconstruct = gst_vaapi_encoder_create_surface (base_encoder);
2975 g_assert (GST_VAAPI_SURFACE_PROXY_SURFACE (reconstruct));
2977 if (!ensure_sequence (encoder, picture))
2979 if (!ensure_misc_params (encoder, picture))
2981 if (!ensure_picture (encoder, picture, codedbuf, reconstruct))
2983 if (!ensure_slices (encoder, picture))
2985 if (!gst_vaapi_enc_picture_encode (picture))
2988 if (!reference_list_update (encoder, picture, reconstruct))
2991 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
2997 gst_vaapi_encoder_release_surface (GST_VAAPI_ENCODER (encoder),
3003 struct _PendingIterState
3005 GstVaapiPictureType pic_type;
3009 gst_vaapi_encoder_h265_get_pending_reordered (GstVaapiEncoder * base_encoder,
3010 GstVaapiEncPicture ** picture, gpointer * state)
3012 GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
3013 GstVaapiH265ReorderPool *reorder_pool;
3014 GstVaapiEncPicture *pic;
3015 struct _PendingIterState *iter;
3017 g_return_val_if_fail (state, FALSE);
3020 iter = g_new0 (struct _PendingIterState, 1);
3021 iter->pic_type = GST_VAAPI_PICTURE_TYPE_P;
3029 reorder_pool = &encoder->reorder_pool;
3030 if (g_queue_is_empty (&reorder_pool->reorder_frame_list))
3033 pic = g_queue_pop_tail (&reorder_pool->reorder_frame_list);
3035 if (iter->pic_type == GST_VAAPI_PICTURE_TYPE_P) {
3036 set_p_frame (pic, encoder);
3037 iter->pic_type = GST_VAAPI_PICTURE_TYPE_B;
3038 } else if (iter->pic_type == GST_VAAPI_PICTURE_TYPE_B) {
3039 set_b_frame (pic, encoder);
3041 GST_WARNING ("Unhandled pending picture type");
3044 if (GST_CLOCK_TIME_IS_VALID (pic->frame->pts))
3045 pic->frame->pts += encoder->cts_offset;
3051 static GstVaapiEncoderStatus
3052 gst_vaapi_encoder_h265_flush (GstVaapiEncoder * base_encoder)
3054 GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
3055 GstVaapiH265ReorderPool *reorder_pool;
3056 GstVaapiEncPicture *pic;
3058 reorder_pool = &encoder->reorder_pool;
3059 reorder_pool->frame_index = 0;
3060 reorder_pool->cur_present_index = 0;
3062 while (!g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
3063 pic = (GstVaapiEncPicture *)
3064 g_queue_pop_head (&reorder_pool->reorder_frame_list);
3065 gst_vaapi_enc_picture_unref (pic);
3067 g_queue_clear (&reorder_pool->reorder_frame_list);
3069 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
3072 /* Generate "codec-data" buffer */
3073 static GstVaapiEncoderStatus
3074 gst_vaapi_encoder_h265_get_codec_data (GstVaapiEncoder * base_encoder,
3075 GstBuffer ** out_buffer_ptr)
3077 GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
3078 const guint32 configuration_version = 0x01;
3079 const guint32 nal_length_size = 4;
3080 GstMapInfo vps_info, sps_info, pps_info;
3083 guint min_spatial_segmentation_idc = 0;
3084 guint num_arrays = 3;
3086 if (!encoder->vps_data || !encoder->sps_data || !encoder->pps_data)
3087 return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER;
3088 if (gst_buffer_get_size (encoder->sps_data) < 4)
3089 return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER;
3091 if (!gst_buffer_map (encoder->vps_data, &vps_info, GST_MAP_READ))
3092 goto error_map_vps_buffer;
3094 if (!gst_buffer_map (encoder->sps_data, &sps_info, GST_MAP_READ))
3095 goto error_map_sps_buffer;
3097 if (!gst_buffer_map (encoder->pps_data, &pps_info, GST_MAP_READ))
3098 goto error_map_pps_buffer;
3101 gst_bit_writer_init_with_size (&bs,
3102 (vps_info.size + sps_info.size + pps_info.size + 64), FALSE);
3103 WRITE_UINT32 (&bs, configuration_version, 8);
3104 WRITE_UINT32 (&bs, sps_info.data[4], 8); /* profile_space | tier_flag | profile_idc */
3105 WRITE_UINT32 (&bs, sps_info.data[5], 32); /* profile_compatibility_flag [0-31] */
3106 /* progressive_source_flag | interlaced_source_flag | non_packed_constraint_flag |
3107 * frame_only_constraint_flag | reserved_zero_bits[0-27] */
3108 WRITE_UINT32 (&bs, sps_info.data[9], 32);
3109 WRITE_UINT32 (&bs, sps_info.data[13], 16); /* reserved_zero_bits [28-43] */
3110 WRITE_UINT32 (&bs, sps_info.data[15], 8); /* level_idc */
3111 WRITE_UINT32 (&bs, 0x0f, 4); /* 1111 */
3112 WRITE_UINT32 (&bs, min_spatial_segmentation_idc, 12); /* min_spatial_segmentation_idc */
3113 WRITE_UINT32 (&bs, 0x3f, 6); /* 111111 */
3114 WRITE_UINT32 (&bs, 0x00, 2); /* parallelismType */
3115 WRITE_UINT32 (&bs, 0x3f, 6); /* 111111 */
3116 WRITE_UINT32 (&bs, 0x01, 2); /* chroma_format_idc */
3117 WRITE_UINT32 (&bs, 0x1f, 5); /* 11111 */
3118 WRITE_UINT32 (&bs, 0x01, 3); /* bit_depth_luma_minus8 */
3119 WRITE_UINT32 (&bs, 0x1f, 5); /* 11111 */
3120 WRITE_UINT32 (&bs, 0x01, 3); /* bit_depth_chroma_minus8 */
3121 WRITE_UINT32 (&bs, 0x00, 16); /* avgFramerate */
3122 WRITE_UINT32 (&bs, 0x00, 2); /* constatnFramerate */
3123 WRITE_UINT32 (&bs, 0x00, 3); /* numTemporalLayers */
3124 WRITE_UINT32 (&bs, 0x00, 1); /* temporalIdNested */
3125 WRITE_UINT32 (&bs, nal_length_size - 1, 2); /* lengthSizeMinusOne */
3126 WRITE_UINT32 (&bs, 0x00, 8); /* numOfArrays */
3128 WRITE_UINT32 (&bs, num_arrays, 8); /* numOfArrays */
3131 WRITE_UINT32 (&bs, 0x00, 1); /* array_completeness */
3132 WRITE_UINT32 (&bs, 0x00, 1); /* reserved zero */
3133 WRITE_UINT32 (&bs, GST_H265_NAL_VPS, 6); /* Nal_unit_type */
3134 WRITE_UINT32 (&bs, 0x01, 16); /* numNalus, VPS count = 1 */
3135 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
3136 /* Write Nal unit length and data of VPS */
3137 if (!gst_vaapi_utils_h26x_write_nal_unit (&bs, vps_info.data, vps_info.size))
3138 goto nal_to_byte_stream_error;
3141 WRITE_UINT32 (&bs, 0x00, 1); /* array_completeness */
3142 WRITE_UINT32 (&bs, 0x00, 1); /* reserved zero */
3143 WRITE_UINT32 (&bs, GST_H265_NAL_SPS, 6); /* Nal_unit_type */
3144 WRITE_UINT32 (&bs, 0x01, 16); /* numNalus, SPS count = 1 */
3145 g_assert (GST_BIT_WRITER_BIT_SIZE (&bs) % 8 == 0);
3146 /* Write Nal unit length and data of SPS */
3147 if (!gst_vaapi_utils_h26x_write_nal_unit (&bs, sps_info.data, sps_info.size))
3148 goto nal_to_byte_stream_error;
3151 WRITE_UINT32 (&bs, 0x00, 1); /* array_completeness */
3152 WRITE_UINT32 (&bs, 0x00, 1); /* reserved zero */
3153 WRITE_UINT32 (&bs, GST_H265_NAL_PPS, 6); /* Nal_unit_type */
3154 WRITE_UINT32 (&bs, 0x01, 16); /* numNalus, PPS count = 1 */
3155 /* Write Nal unit length and data of PPS */
3156 if (!gst_vaapi_utils_h26x_write_nal_unit (&bs, pps_info.data, pps_info.size))
3157 goto nal_to_byte_stream_error;
3159 gst_buffer_unmap (encoder->pps_data, &pps_info);
3160 gst_buffer_unmap (encoder->sps_data, &sps_info);
3161 gst_buffer_unmap (encoder->vps_data, &vps_info);
3163 buffer = gst_bit_writer_reset_and_get_buffer (&bs);
3165 goto error_alloc_buffer;
3166 if (gst_buffer_n_memory (buffer) == 0) {
3167 gst_buffer_unref (buffer);
3168 goto error_alloc_buffer;
3170 *out_buffer_ptr = buffer;
3172 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
3177 GST_ERROR ("failed to write codec-data");
3178 gst_buffer_unmap (encoder->vps_data, &vps_info);
3179 gst_buffer_unmap (encoder->sps_data, &sps_info);
3180 gst_buffer_unmap (encoder->pps_data, &pps_info);
3181 gst_bit_writer_reset (&bs);
3182 return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
3184 nal_to_byte_stream_error:
3186 GST_ERROR ("failed to write nal unit");
3187 gst_buffer_unmap (encoder->vps_data, &vps_info);
3188 gst_buffer_unmap (encoder->sps_data, &sps_info);
3189 gst_buffer_unmap (encoder->pps_data, &pps_info);
3190 gst_bit_writer_reset (&bs);
3191 return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
3193 error_map_vps_buffer:
3195 GST_ERROR ("failed to map VPS packed header");
3196 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
3198 error_map_sps_buffer:
3200 GST_ERROR ("failed to map SPS packed header");
3201 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
3203 error_map_pps_buffer:
3205 GST_ERROR ("failed to map PPS packed header");
3206 gst_buffer_unmap (encoder->sps_data, &sps_info);
3207 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
3211 GST_ERROR ("failed to allocate codec-data buffer");
3212 gst_bit_writer_reset (&bs);
3213 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
3218 /* The re-ordering algorithm is similar to what we implemented for
3219 * h264 encoder. But We could have a better algorithm for hevc encoder
3220 * by having B-frames as reference pictures */
3221 static GstVaapiEncoderStatus
3222 gst_vaapi_encoder_h265_reordering (GstVaapiEncoder * base_encoder,
3223 GstVideoCodecFrame * frame, GstVaapiEncPicture ** output)
3225 GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
3226 GstVaapiH265ReorderPool *reorder_pool = NULL;
3227 GstVaapiEncPicture *picture;
3228 gboolean is_idr = FALSE;
3232 reorder_pool = &encoder->reorder_pool;
3235 if (reorder_pool->reorder_state != GST_VAAPI_ENC_H265_REORD_DUMP_FRAMES)
3236 return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
3238 /* reorder_state = GST_VAAPI_ENC_H265_REORD_DUMP_FRAMES
3239 dump B frames from queue, sometime, there may also have P frame or I frame */
3240 g_assert (encoder->num_bframes > 0);
3241 g_return_val_if_fail (!g_queue_is_empty (&reorder_pool->reorder_frame_list),
3242 GST_VAAPI_ENCODER_STATUS_ERROR_UNKNOWN);
3243 picture = g_queue_pop_head (&reorder_pool->reorder_frame_list);
3245 if (g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
3246 reorder_pool->reorder_state = GST_VAAPI_ENC_H265_REORD_WAIT_FRAMES;
3251 /* new frame coming */
3252 picture = GST_VAAPI_ENC_PICTURE_NEW (HEVC, encoder, frame);
3254 GST_WARNING ("create H265 picture failed, frame timestamp:%"
3255 GST_TIME_FORMAT, GST_TIME_ARGS (frame->pts));
3256 return GST_VAAPI_ENCODER_STATUS_ERROR_ALLOCATION_FAILED;
3258 ++reorder_pool->cur_present_index;
3259 picture->poc = ((reorder_pool->cur_present_index * 1) %
3260 encoder->max_pic_order_cnt);
3262 is_idr = (reorder_pool->frame_index == 0 ||
3263 reorder_pool->frame_index >= encoder->idr_period);
3265 /* check key frames */
3266 if (is_idr || GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame) ||
3267 (reorder_pool->frame_index %
3268 GST_VAAPI_ENCODER_KEYFRAME_PERIOD (encoder)) == 0) {
3269 ++reorder_pool->frame_index;
3271 /* b frame enabled, check queue of reorder_frame_list */
3272 if (encoder->num_bframes
3273 && !g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
3274 GstVaapiEncPicture *p_pic;
3276 p_pic = g_queue_pop_tail (&reorder_pool->reorder_frame_list);
3277 set_p_frame (p_pic, encoder);
3278 g_queue_foreach (&reorder_pool->reorder_frame_list,
3279 (GFunc) set_b_frame, encoder);
3280 set_key_frame (picture, encoder, is_idr);
3281 g_queue_push_tail (&reorder_pool->reorder_frame_list, picture);
3283 reorder_pool->reorder_state = GST_VAAPI_ENC_H265_REORD_DUMP_FRAMES;
3284 } else { /* no b frames in queue */
3285 set_key_frame (picture, encoder, is_idr);
3286 g_assert (g_queue_is_empty (&reorder_pool->reorder_frame_list));
3287 if (encoder->num_bframes)
3288 reorder_pool->reorder_state = GST_VAAPI_ENC_H265_REORD_WAIT_FRAMES;
3293 /* new p/b frames coming */
3294 ++reorder_pool->frame_index;
3295 if (reorder_pool->reorder_state == GST_VAAPI_ENC_H265_REORD_WAIT_FRAMES &&
3296 g_queue_get_length (&reorder_pool->reorder_frame_list) <
3297 encoder->num_bframes) {
3298 g_queue_push_tail (&reorder_pool->reorder_frame_list, picture);
3299 return GST_VAAPI_ENCODER_STATUS_NO_SURFACE;
3302 set_p_frame (picture, encoder);
3304 if (reorder_pool->reorder_state == GST_VAAPI_ENC_H265_REORD_WAIT_FRAMES) {
3305 g_queue_foreach (&reorder_pool->reorder_frame_list, (GFunc) set_b_frame,
3307 reorder_pool->reorder_state = GST_VAAPI_ENC_H265_REORD_DUMP_FRAMES;
3308 g_assert (!g_queue_is_empty (&reorder_pool->reorder_frame_list));
3313 frame = picture->frame;
3314 if (GST_CLOCK_TIME_IS_VALID (frame->pts))
3315 frame->pts += encoder->cts_offset;
3318 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
3321 static GstVaapiEncoderStatus
3322 set_context_info (GstVaapiEncoder * base_encoder)
3324 GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
3325 GstVideoInfo *const vip = GST_VAAPI_ENCODER_VIDEO_INFO (encoder);
3326 const guint DEFAULT_SURFACES_COUNT = 3;
3328 /* FIXME: Using only a rough approximation for bitstream headers.
3329 * Not taken into account: ScalingList, RefPicListModification,
3330 * PredWeightTable */
3331 /* Maximum sizes for common headers (in bits) */
3334 MAX_PROFILE_TIER_LEVEL_SIZE = 684,
3335 MAX_VPS_HDR_SIZE = 13781,
3336 MAX_SPS_HDR_SIZE = 615,
3337 MAX_SHORT_TERM_REFPICSET_SIZE = 55,
3338 MAX_VUI_PARAMS_SIZE = 267,
3339 MAX_HRD_PARAMS_SIZE = 8196,
3340 MAX_PPS_HDR_SIZE = 274,
3341 MAX_SLICE_HDR_SIZE = 33660
3344 /* Account for VPS header */
3345 base_encoder->codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_VPS_HDR_SIZE +
3346 MAX_PROFILE_TIER_LEVEL_SIZE + MAX_HRD_PARAMS_SIZE) / 8;
3348 /* Account for SPS header */
3349 base_encoder->codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE +
3350 MAX_PROFILE_TIER_LEVEL_SIZE + 64 * MAX_SHORT_TERM_REFPICSET_SIZE +
3351 MAX_VUI_PARAMS_SIZE + MAX_HRD_PARAMS_SIZE) / 8;
3353 /* Account for PPS header */
3354 base_encoder->codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8;
3356 /* Account for slice header */
3357 base_encoder->codedbuf_size += encoder->num_slices * (4 +
3358 GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE + MAX_SHORT_TERM_REFPICSET_SIZE) / 8);
3360 GST_VAAPI_ENCODER_CAST (encoder)->profile = encoder->profile;
3362 base_encoder->num_ref_frames = (encoder->num_ref_frames
3363 + (encoder->num_bframes > 0 ? 1 : 0) + DEFAULT_SURFACES_COUNT);
3365 /* Only YUV 4:2:0 formats are supported for now. */
3366 base_encoder->codedbuf_size += GST_ROUND_UP_16 (vip->width) *
3367 GST_ROUND_UP_16 (vip->height) * 3 / 2;
3369 base_encoder->context_info.profile = base_encoder->profile;
3370 base_encoder->context_info.entrypoint = encoder->entrypoint;
3372 return GST_VAAPI_ENCODER_STATUS_SUCCESS;
3375 static GstVaapiEncoderStatus
3376 gst_vaapi_encoder_h265_reconfigure (GstVaapiEncoder * base_encoder)
3378 GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (base_encoder);
3379 GstVaapiEncoderStatus status;
3380 guint luma_width, luma_height;
3382 luma_width = GST_VAAPI_ENCODER_WIDTH (encoder);
3383 luma_height = GST_VAAPI_ENCODER_HEIGHT (encoder);
3385 if (luma_width != encoder->luma_width || luma_height != encoder->luma_height) {
3386 GST_DEBUG ("resolution: %d %d", GST_VAAPI_ENCODER_WIDTH (encoder),
3387 GST_VAAPI_ENCODER_HEIGHT (encoder));
3388 encoder->luma_width = GST_ROUND_UP_16 (luma_width);
3389 encoder->luma_height = GST_ROUND_UP_16 (luma_height);
3390 encoder->config_changed = TRUE;
3391 /* Frame Cropping */
3392 if ((GST_VAAPI_ENCODER_WIDTH (encoder) & 15) ||
3393 (GST_VAAPI_ENCODER_HEIGHT (encoder) & 15)) {
3394 /* 6.1, Table 6-1 */
3395 static const guint SubWidthC[] = { 1, 2, 2, 1 };
3396 static const guint SubHeightC[] = { 1, 2, 1, 1 };
3397 guint index = gst_vaapi_utils_h265_get_chroma_format_idc
3398 (gst_vaapi_video_format_get_chroma_type (GST_VIDEO_INFO_FORMAT
3399 (GST_VAAPI_ENCODER_VIDEO_INFO (encoder))));
3401 encoder->conformance_window_flag = 1;
3402 encoder->conf_win_left_offset = 0;
3403 encoder->conf_win_right_offset =
3404 (encoder->luma_width -
3405 GST_VAAPI_ENCODER_WIDTH (encoder)) / SubWidthC[index];
3406 encoder->conf_win_top_offset = 0;
3407 encoder->conf_win_bottom_offset =
3408 (encoder->luma_height -
3409 GST_VAAPI_ENCODER_HEIGHT (encoder)) / SubHeightC[index];
3413 status = ensure_profile_tier_level (encoder);
3414 if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
3417 /* Set ctu size based on entrypoint. */
3418 if (encoder->entrypoint == GST_VAAPI_ENTRYPOINT_SLICE_ENCODE_LP) {
3419 encoder->ctu_width = (encoder->luma_width + 63) / 64;
3420 encoder->ctu_height = (encoder->luma_height + 63) / 64;
3422 encoder->ctu_width = (encoder->luma_width + 31) / 32;
3423 encoder->ctu_height = (encoder->luma_height + 31) / 32;
3426 status = reset_properties (encoder);
3427 if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
3430 status = ensure_tile (encoder);
3431 if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
3433 ensure_control_rate_params (encoder);
3434 return set_context_info (base_encoder);
3438 gst_vaapi_encoder_h265_init (GstVaapiEncoderH265 * encoder)
3440 GstVaapiH265ReorderPool *reorder_pool;
3441 GstVaapiH265RefPool *ref_pool;
3443 /* Default encoding entrypoint */
3444 encoder->entrypoint = GST_VAAPI_ENTRYPOINT_SLICE_ENCODE;
3445 encoder->tier = GST_VAAPI_TIER_H265_UNKNOWN;
3447 encoder->conformance_window_flag = 0;
3448 encoder->num_slices = 1;
3449 encoder->no_p_frame = FALSE;
3451 /* re-ordering list initialize */
3452 reorder_pool = &encoder->reorder_pool;
3453 g_queue_init (&reorder_pool->reorder_frame_list);
3454 reorder_pool->reorder_state = GST_VAAPI_ENC_H265_REORD_NONE;
3455 reorder_pool->frame_index = 0;
3456 reorder_pool->cur_present_index = 0;
3458 /* reference list info initialize */
3459 ref_pool = &encoder->ref_pool;
3460 g_queue_init (&ref_pool->ref_list);
3461 ref_pool->max_ref_frames = 0;
3462 ref_pool->max_reflist0_count = 1;
3463 ref_pool->max_reflist1_count = 1;
3465 encoder->allowed_profiles = NULL;
3468 struct _GstVaapiEncoderH265Class
3470 GstVaapiEncoderClass parent_class;
3473 G_DEFINE_TYPE (GstVaapiEncoderH265, gst_vaapi_encoder_h265,
3474 GST_TYPE_VAAPI_ENCODER);
3477 gst_vaapi_encoder_h265_finalize (GObject * object)
3479 /*free private buffers */
3480 GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (object);
3481 GstVaapiEncPicture *pic;
3482 GstVaapiEncoderH265Ref *ref;
3483 GstVaapiH265RefPool *ref_pool;
3484 GstVaapiH265ReorderPool *reorder_pool;
3486 gst_buffer_replace (&encoder->vps_data, NULL);
3487 gst_buffer_replace (&encoder->sps_data, NULL);
3488 gst_buffer_replace (&encoder->pps_data, NULL);
3490 /* reference list info de-init */
3491 ref_pool = &encoder->ref_pool;
3492 while (!g_queue_is_empty (&ref_pool->ref_list)) {
3493 ref = (GstVaapiEncoderH265Ref *) g_queue_pop_head (&ref_pool->ref_list);
3494 reference_pic_free (encoder, ref);
3496 g_queue_clear (&ref_pool->ref_list);
3498 /* re-ordering list initialize */
3499 reorder_pool = &encoder->reorder_pool;
3500 while (!g_queue_is_empty (&reorder_pool->reorder_frame_list)) {
3501 pic = (GstVaapiEncPicture *)
3502 g_queue_pop_head (&reorder_pool->reorder_frame_list);
3503 gst_vaapi_enc_picture_unref (pic);
3505 g_queue_clear (&reorder_pool->reorder_frame_list);
3507 reset_tile (encoder);
3509 if (encoder->allowed_profiles)
3510 g_array_unref (encoder->allowed_profiles);
3512 G_OBJECT_CLASS (gst_vaapi_encoder_h265_parent_class)->finalize (object);
3516 * @ENCODER_H265_PROP_RATECONTROL: Rate control (#GstVaapiRateControl).
3517 * @ENCODER_H265_PROP_TUNE: The tuning options (#GstVaapiEncoderTune).
3518 * @ENCODER_H265_PROP_MAX_BFRAMES: Number of B-frames between I
3520 * @ENCODER_H265_PROP_INIT_QP: Initial quantizer value (uint).
3521 * @ENCODER_H265_PROP_MIN_QP: Minimal quantizer value (uint).
3522 * @ENCODER_H265_PROP_NUM_SLICES: Number of slices per frame (uint).
3523 * @ENCODER_H265_PROP_NUM_REF_FRAMES: Maximum number of reference frames.
3524 * @ENCODER_H265_PROP_CPB_LENGTH: Length of the CPB buffer
3525 * in milliseconds (uint).
3526 * @ENCODER_H265_PROP_MBBRC: Macroblock level Bitrate Control.
3527 * @ENCODER_H265_PROP_QP_IP: Difference of QP between I and P frame.
3528 * @ENCODER_H265_PROP_QP_IB: Difference of QP between I and B frame.
3529 * @ENCODER_H265_PROP_LOW_DELAY_B: use low delay b feature.
3530 * @ENCODER_H265_PROP_MAX_QP: Maximal quantizer value (uint).
3532 * The set of H.265 encoder specific configurable properties.
3536 ENCODER_H265_PROP_RATECONTROL = 1,
3537 ENCODER_H265_PROP_TUNE,
3538 ENCODER_H265_PROP_MAX_BFRAMES,
3539 ENCODER_H265_PROP_INIT_QP,
3540 ENCODER_H265_PROP_MIN_QP,
3541 ENCODER_H265_PROP_NUM_SLICES,
3542 ENCODER_H265_PROP_NUM_REF_FRAMES,
3543 ENCODER_H265_PROP_CPB_LENGTH,
3544 ENCODER_H265_PROP_MBBRC,
3545 ENCODER_H265_PROP_QP_IP,
3546 ENCODER_H265_PROP_QP_IB,
3547 #ifndef GST_REMOVE_DEPRECATED
3548 ENCODER_H265_PROP_LOW_DELAY_B,
3550 ENCODER_H265_PROP_MAX_QP,
3551 ENCODER_H265_PROP_QUALITY_FACTOR,
3552 ENCODER_H265_PROP_NUM_TILE_COLS,
3553 ENCODER_H265_PROP_NUM_TILE_ROWS,
3554 ENCODER_H265_N_PROPERTIES
3557 static GParamSpec *properties[ENCODER_H265_N_PROPERTIES];
3560 gst_vaapi_encoder_h265_set_property (GObject * object, guint prop_id,
3561 const GValue * value, GParamSpec * pspec)
3563 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER (object);
3564 GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (object);
3566 if (base_encoder->num_codedbuf_queued > 0) {
3567 GST_ERROR_OBJECT (object,
3568 "failed to set any property after encoding started");
3573 case ENCODER_H265_PROP_RATECONTROL:
3574 gst_vaapi_encoder_set_rate_control (base_encoder,
3575 g_value_get_enum (value));
3577 case ENCODER_H265_PROP_TUNE:
3578 gst_vaapi_encoder_set_tuning (base_encoder, g_value_get_enum (value));
3580 case ENCODER_H265_PROP_MAX_BFRAMES:
3581 encoder->num_bframes = g_value_get_uint (value);
3583 case ENCODER_H265_PROP_INIT_QP:
3584 encoder->init_qp = g_value_get_uint (value);
3586 case ENCODER_H265_PROP_MIN_QP:
3587 encoder->min_qp = g_value_get_uint (value);
3589 case ENCODER_H265_PROP_QP_IP:
3590 encoder->qp_ip = g_value_get_int (value);
3592 case ENCODER_H265_PROP_QP_IB:
3593 encoder->qp_ib = g_value_get_int (value);
3595 case ENCODER_H265_PROP_NUM_SLICES:
3596 encoder->num_slices = g_value_get_uint (value);
3598 case ENCODER_H265_PROP_CPB_LENGTH:
3599 encoder->cpb_length = g_value_get_uint (value);
3601 case ENCODER_H265_PROP_NUM_REF_FRAMES:
3602 encoder->num_ref_frames = g_value_get_uint (value);
3604 case ENCODER_H265_PROP_MBBRC:
3605 encoder->mbbrc = g_value_get_enum (value);
3607 #ifndef GST_REMOVE_DEPRECATED
3608 case ENCODER_H265_PROP_LOW_DELAY_B:
3609 #if !VA_CHECK_VERSION(1,9,0)
3610 encoder->no_p_frame = g_value_get_boolean (value);
3612 if (g_value_get_boolean (value) == TRUE) {
3613 GST_WARNING ("Deprecate low-delay-b property. Driver now already"
3614 " has the ability to detect whether supporting P frames. this"
3615 " value should not be set manually and will take no effect.");
3620 case ENCODER_H265_PROP_MAX_QP:
3621 encoder->max_qp = g_value_get_uint (value);
3623 case ENCODER_H265_PROP_QUALITY_FACTOR:
3624 encoder->quality_factor = g_value_get_uint (value);
3626 case ENCODER_H265_PROP_NUM_TILE_COLS:
3627 encoder->num_tile_cols = g_value_get_uint (value);
3629 case ENCODER_H265_PROP_NUM_TILE_ROWS:
3630 encoder->num_tile_rows = g_value_get_uint (value);
3633 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3638 gst_vaapi_encoder_h265_get_property (GObject * object, guint prop_id,
3639 GValue * value, GParamSpec * pspec)
3641 GstVaapiEncoderH265 *const encoder = GST_VAAPI_ENCODER_H265 (object);
3642 GstVaapiEncoder *const base_encoder = GST_VAAPI_ENCODER (object);
3645 case ENCODER_H265_PROP_RATECONTROL:
3646 g_value_set_enum (value, base_encoder->rate_control);
3648 case ENCODER_H265_PROP_TUNE:
3649 g_value_set_enum (value, base_encoder->tune);
3651 case ENCODER_H265_PROP_MAX_BFRAMES:
3652 g_value_set_uint (value, encoder->num_bframes);
3654 case ENCODER_H265_PROP_INIT_QP:
3655 g_value_set_uint (value, encoder->init_qp);
3657 case ENCODER_H265_PROP_MIN_QP:
3658 g_value_set_uint (value, encoder->min_qp);
3660 case ENCODER_H265_PROP_QP_IP:
3661 g_value_set_int (value, encoder->qp_ip);
3663 case ENCODER_H265_PROP_QP_IB:
3664 g_value_set_int (value, encoder->qp_ib);
3666 case ENCODER_H265_PROP_NUM_SLICES:
3667 g_value_set_uint (value, encoder->num_slices);
3669 case ENCODER_H265_PROP_CPB_LENGTH:
3670 g_value_set_uint (value, encoder->cpb_length);
3672 case ENCODER_H265_PROP_NUM_REF_FRAMES:
3673 g_value_set_uint (value, encoder->num_ref_frames);
3675 case ENCODER_H265_PROP_MBBRC:
3676 g_value_set_enum (value, encoder->mbbrc);
3678 #ifndef GST_REMOVE_DEPRECATED
3679 case ENCODER_H265_PROP_LOW_DELAY_B:
3680 g_value_set_boolean (value, encoder->no_p_frame);
3683 case ENCODER_H265_PROP_MAX_QP:
3684 g_value_set_uint (value, encoder->max_qp);
3686 case ENCODER_H265_PROP_QUALITY_FACTOR:
3687 g_value_set_uint (value, encoder->quality_factor);
3689 case ENCODER_H265_PROP_NUM_TILE_COLS:
3690 g_value_set_uint (value, encoder->num_tile_cols);
3692 case ENCODER_H265_PROP_NUM_TILE_ROWS:
3693 g_value_set_uint (value, encoder->num_tile_rows);
3696 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3700 GST_VAAPI_ENCODER_DEFINE_CLASS_DATA (H265);
3703 gst_vaapi_encoder_h265_class_init (GstVaapiEncoderH265Class * klass)
3705 GObjectClass *const object_class = G_OBJECT_CLASS (klass);
3706 GstVaapiEncoderClass *const encoder_class = GST_VAAPI_ENCODER_CLASS (klass);
3708 encoder_class->class_data = &g_class_data;
3709 encoder_class->reconfigure = gst_vaapi_encoder_h265_reconfigure;
3710 encoder_class->reordering = gst_vaapi_encoder_h265_reordering;
3711 encoder_class->encode = gst_vaapi_encoder_h265_encode;
3712 encoder_class->flush = gst_vaapi_encoder_h265_flush;
3713 encoder_class->get_codec_data = gst_vaapi_encoder_h265_get_codec_data;
3714 encoder_class->get_pending_reordered =
3715 gst_vaapi_encoder_h265_get_pending_reordered;
3717 object_class->set_property = gst_vaapi_encoder_h265_set_property;
3718 object_class->get_property = gst_vaapi_encoder_h265_get_property;
3719 object_class->finalize = gst_vaapi_encoder_h265_finalize;
3722 * GstVaapiEncoderH265:rate-control:
3724 * The desired rate control mode, expressed as a #GstVaapiRateControl.
3726 properties[ENCODER_H265_PROP_RATECONTROL] =
3727 g_param_spec_enum ("rate-control",
3728 "Rate Control", "Rate control mode",
3729 g_class_data.rate_control_get_type (),
3730 g_class_data.default_rate_control,
3731 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3732 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3735 * GstVaapiEncoderH265:tune:
3737 * The desired encoder tuning option.
3739 properties[ENCODER_H265_PROP_TUNE] =
3740 g_param_spec_enum ("tune",
3742 "Encoder tuning option",
3743 g_class_data.encoder_tune_get_type (),
3744 g_class_data.default_encoder_tune,
3745 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3746 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3749 * GstVaapiEncoderH265:max-bframes:
3751 * The number of B-frames between I and P.
3753 properties[ENCODER_H265_PROP_MAX_BFRAMES] =
3754 g_param_spec_uint ("max-bframes",
3755 "Max B-Frames", "Number of B-frames between I and P", 0, 10, 0,
3756 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3757 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3760 * GstVaapiEncoderH265:refs:
3762 * The number of reference frames.
3763 * If B frame is encoded, it will add 1 reference frame more.
3765 properties[ENCODER_H265_PROP_NUM_REF_FRAMES] =
3766 g_param_spec_uint ("refs",
3767 "Number of Reference Frames", "Number of reference frames", 1, 3, 1,
3768 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3769 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3772 * GstVaapiEncoderH265:init-qp:
3774 * The initial quantizer value.
3776 properties[ENCODER_H265_PROP_INIT_QP] =
3777 g_param_spec_uint ("init-qp",
3778 "Initial QP", "Initial quantizer value", 0, 51, 26,
3779 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3780 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3783 * GstVaapiEncoderH265:min-qp:
3785 * The minimum quantizer value.
3787 properties[ENCODER_H265_PROP_MIN_QP] =
3788 g_param_spec_uint ("min-qp",
3789 "Minimum QP", "Minimum quantizer value", 0, 51, 1,
3790 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3791 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3794 * GstVaapiEncoderH265:max-qp:
3796 * The maximum quantizer value.
3800 properties[ENCODER_H265_PROP_MAX_QP] =
3801 g_param_spec_uint ("max-qp",
3802 "Maximum QP", "Maximum quantizer value", 0, 51, 51,
3803 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3804 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3807 * GstVaapiEncoderH265:qp-ip:
3809 * The difference of QP between I and P Frame.
3810 * This is available only on CQP mode.
3812 properties[ENCODER_H265_PROP_QP_IP] =
3813 g_param_spec_int ("qp-ip",
3814 "Difference of QP between I and P frame",
3815 "Difference of QP between I and P frame (available only on CQP)",
3817 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3818 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3821 * GstVaapiEncoderH265:qp-ib:
3823 * The difference of QP between I and B Frame.
3824 * This is available only on CQP mode.
3826 properties[ENCODER_H265_PROP_QP_IB] =
3827 g_param_spec_int ("qp-ib",
3828 "Difference of QP between I and B frame",
3829 "Difference of QP between I and B frame (available only on CQP)",
3831 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3832 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3834 /* FIXME: there seems to be issues with multi-slice encoding */
3836 * GstVaapiEncoderH265:num-slices:
3838 * The number of slices per frame.
3840 properties[ENCODER_H265_PROP_NUM_SLICES] =
3841 g_param_spec_uint ("num-slices",
3843 "Number of slices per frame",
3845 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3846 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3849 * GstVaapiEncoderH265:cpb-length:
3851 * The size of the CPB buffer in milliseconds.
3853 properties[ENCODER_H265_PROP_CPB_LENGTH] =
3854 g_param_spec_uint ("cpb-length",
3855 "CPB Length", "Length of the CPB buffer in milliseconds",
3856 1, 10000, DEFAULT_CPB_LENGTH,
3857 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3858 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3861 * GstVaapiEncoderH265:mbbrc:
3863 * Macroblock level bitrate control.
3864 * This is not compatible with Constant QP rate control.
3866 properties[ENCODER_H265_PROP_MBBRC] =
3867 g_param_spec_enum ("mbbrc",
3868 "Macroblock level Bitrate Control",
3869 "Macroblock level Bitrate Control",
3870 GST_VAAPI_TYPE_ENCODER_MBBRC, GST_VAAPI_ENCODER_MBBRC_AUTO,
3871 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3872 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3874 #ifndef GST_REMOVE_DEPRECATED
3876 * GstVaapiEncoderH265:low_delay_b:
3878 * Enable low delay b frame, which will change P frame with B frame.
3880 properties[ENCODER_H265_PROP_LOW_DELAY_B] =
3881 g_param_spec_boolean ("low-delay-b",
3882 "Enable low delay b",
3883 "Transforms P frames into predictive B frames."
3884 " Enable it when P frames are not supported.",
3885 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3886 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3890 * GstVaapiEncoderH265:quality_factor:
3892 * Quality factor used with ICQ/QVBR bitrate control mode.
3894 properties[ENCODER_H265_PROP_QUALITY_FACTOR] =
3895 g_param_spec_uint ("quality-factor",
3896 "Quality factor for ICQ/QVBR",
3897 "quality factor for ICQ/QBVR bitrate control mode"
3898 " (lower value means higher quality, higher value means lower quality)",
3900 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3901 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3904 * GstVaapiEncoderH265:num-tile-cols:
3906 * The number of tile columns when tile encoding is enabled.
3908 properties[ENCODER_H265_PROP_NUM_TILE_COLS] =
3909 g_param_spec_uint ("num-tile-cols",
3910 "number of tile columns",
3911 "the number of columns for tile encoding", 1,
3912 GST_VAAPI_H265_MAX_COL_TILES, 1,
3913 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3914 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3917 * GstVaapiEncoderH265:num-tile-rows:
3919 * The number of tile rows when tile encoding is enabled.
3921 properties[ENCODER_H265_PROP_NUM_TILE_ROWS] =
3922 g_param_spec_uint ("num-tile-rows",
3923 "number of tile rows",
3924 "the number of rows for tile encoding", 1,
3925 GST_VAAPI_H265_MAX_ROW_TILES, 1,
3926 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT |
3927 GST_VAAPI_PARAM_ENCODER_EXPOSURE);
3929 g_object_class_install_properties (object_class, ENCODER_H265_N_PROPERTIES,
3932 gst_type_mark_as_plugin_api (g_class_data.rate_control_get_type (), 0);
3933 gst_type_mark_as_plugin_api (g_class_data.encoder_tune_get_type (), 0);
3937 * gst_vaapi_encoder_h265_new:
3938 * @display: a #GstVaapiDisplay
3940 * Creates a new #GstVaapiEncoder for H.265 encoding. Note that the
3941 * only supported output stream format is "byte-stream" format.
3943 * Return value: the newly allocated #GstVaapiEncoder object
3946 gst_vaapi_encoder_h265_new (GstVaapiDisplay * display)
3948 return g_object_new (GST_TYPE_VAAPI_ENCODER_H265, "display", display, NULL);
3952 * gst_vaapi_encoder_h265_set_allowed_profiles:
3953 * @encoder: a #GstVaapiEncoderH265
3954 * @profiles: a #GArray of all allowed #GstVaapiProfile.
3956 * Set the all allowed profiles for the encoder.
3958 * Return value: %TRUE on success
3961 gst_vaapi_encoder_h265_set_allowed_profiles (GstVaapiEncoderH265 * encoder,
3964 g_return_val_if_fail (encoder != NULL, FALSE);
3965 g_return_val_if_fail (profiles, FALSE);
3967 encoder->allowed_profiles = g_array_ref (profiles);
3972 * gst_vaapi_encoder_h265_get_profile_tier_level:
3973 * @encoder: a #GstVaapiEncoderH265
3974 * @out_profile_ptr: return location for the #GstVaapiProfile
3975 * @out_level_ptr: return location for the #GstVaapiLevelH265
3976 * @out_tier_ptr: return location for the #GstVaapiTierH265
3978 * Queries the H.265 @encoder for the active profile and level. That
3979 * information is only constructed and valid after the encoder is
3980 * configured, i.e. after the gst_vaapi_encoder_set_codec_state()
3981 * function is called.
3983 * Return value: %TRUE on success
3986 gst_vaapi_encoder_h265_get_profile_tier_level (GstVaapiEncoderH265 * encoder,
3987 GstVaapiProfile * out_profile_ptr, GstVaapiTierH265 * out_tier_ptr,
3988 GstVaapiLevelH265 * out_level_ptr)
3990 g_return_val_if_fail (encoder != NULL, FALSE);
3992 if (!encoder->profile || encoder->tier == GST_VAAPI_TIER_H265_UNKNOWN
3996 if (out_profile_ptr)
3997 *out_profile_ptr = encoder->profile;
3999 *out_level_ptr = encoder->level;
4001 *out_tier_ptr = encoder->tier;