2 * Copyright (C) 2022 Intel Corporation
3 * Author: He Junyan <junyan.he@intel.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 * SECTION:element-vah265enc
24 * @short_description: A VA-API based H265 video encoder
26 * vah265enc encodes raw video VA surfaces into H.265 bitstreams using
27 * the installed and chosen [VA-API](https://01.org/linuxmedia/vaapi)
30 * The raw video frames in main memory can be imported into VA surfaces.
32 * ## Example launch line
34 * gst-launch-1.0 videotestsrc num-buffers=60 ! timeoverlay ! vah265enc ! h265parse ! mp4mux ! filesink location=test.mp4
45 #include "gstvah265enc.h"
47 #include <gst/codecparsers/gsth265bitwriter.h>
48 #include <gst/va/gstva.h>
49 #include <gst/va/gstvavideoformat.h>
50 #include <gst/video/video.h>
51 #include <va/va_drmcommon.h>
54 #include "gstvabaseenc.h"
55 #include "gstvaencoder.h"
56 #include "gstvacaps.h"
57 #include "gstvaprofile.h"
58 #include "gstvadisplay_priv.h"
60 GST_DEBUG_CATEGORY_STATIC (gst_va_h265enc_debug);
61 #define GST_CAT_DEFAULT gst_va_h265enc_debug
63 #define GST_VA_H265_ENC(obj) ((GstVaH265Enc *) obj)
64 #define GST_VA_H265_ENC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_FROM_INSTANCE (obj), GstVaH265EncClass))
65 #define GST_VA_H265_ENC_CLASS(klass) ((GstVaH265EncClass *) klass)
67 typedef struct _GstVaH265Enc GstVaH265Enc;
68 typedef struct _GstVaH265EncClass GstVaH265EncClass;
69 typedef struct _GstVaH265EncFrame GstVaH265EncFrame;
70 typedef struct _GstVaH265LevelLimits GstVaH265LevelLimits;
88 PROP_TARGET_PERCENTAGE,
98 static GParamSpec *properties[N_PROPERTIES];
100 static GstObjectClass *parent_class = NULL;
102 /* Scale factor for bitrate (HRD bit_rate_scale: min = 6) */
104 /* Scale factor for CPB size (HRD cpb_size_scale: min = 4) */
105 #define SX_CPB_SIZE 4
106 /* Maximum sizes for common headers (in bits) */
107 #define MAX_PROFILE_TIER_LEVEL_SIZE 684
108 #define MAX_VPS_HDR_SIZE 13781
109 #define MAX_SPS_HDR_SIZE 615
110 #define MAX_SHORT_TERM_REFPICSET_SIZE 55
111 #define MAX_VUI_PARAMS_SIZE 267
112 #define MAX_HRD_PARAMS_SIZE 8196
113 #define MAX_PPS_HDR_SIZE 274
114 #define MAX_SLICE_HDR_SIZE 33660
116 #define MAX_GOP_SIZE 1024
118 /* The max tiles in column according to spec A1 */
119 #define MAX_COL_TILES 20
120 /* The max tiles in row according to spec A1 */
121 #define MAX_ROW_TILES 22
124 struct _GstVaH265EncClass
126 GstVaBaseEncClass parent_class;
128 GType rate_control_type;
129 char rate_control_type_name[64];
130 GEnumValue rate_control[16];
147 guint32 num_ref_frames;
156 gboolean use_trellis;
160 guint32 num_tile_cols;
161 guint32 num_tile_rows;
163 guint32 target_percentage;
164 guint32 target_usage;
169 guint32 min_coding_block_size;
170 guint32 ctu_width; /* CTU == Coding Tree Unit */
176 gboolean conformance_window_flag;
177 guint32 conf_win_left_offset;
178 guint32 conf_win_right_offset;
179 guint32 conf_win_top_offset;
180 guint32 conf_win_bottom_offset;
182 guint bits_depth_luma_minus8;
183 guint bits_depth_chroma_minus8;
186 /* Set true if high tier */
188 const gchar *level_str;
192 guint32 packed_headers;
197 /* start address in CTUs */
198 guint32 *slice_segment_address;
199 /* CTUs in this slice */
200 guint32 *num_ctu_in_slice;
202 gboolean slice_span_tiles;
203 guint32 num_tile_cols;
204 guint32 num_tile_rows;
205 /* CTUs in each tile column */
206 guint32 *tile_ctu_cols;
207 /* CTUs in each tile row */
208 guint32 *tile_ctu_rows;
213 guint8 log2_min_luma_coding_block_size_minus3;
214 guint8 log2_diff_max_min_luma_coding_block_size;
215 guint8 log2_min_transform_block_size_minus2;
216 guint8 log2_diff_max_min_transform_block_size;
217 guint8 max_transform_hierarchy_depth_inter;
218 guint8 max_transform_hierarchy_depth_intra;
220 gboolean separate_colour_plane_flag;
221 guint8 colour_plane_id;
223 gboolean scaling_list_enabled_flag;
224 gboolean scaling_list_data_present_flag;
226 gboolean amp_enabled_flag;
228 gboolean sample_adaptive_offset_enabled_flag;
229 gboolean slice_sao_luma_flag;
230 gboolean slice_sao_chroma_flag;
232 gboolean pcm_enabled_flag;
233 guint8 pcm_sample_bit_depth_luma_minus1;
234 guint8 pcm_sample_bit_depth_chroma_minus1;
235 guint8 log2_min_pcm_luma_coding_block_size_minus3;
236 guint8 log2_max_pcm_luma_coding_block_size_minus3;
237 guint8 pcm_loop_filter_disabled_flag;
239 gboolean temporal_mvp_enabled_flag;
240 gboolean collocated_from_l0_flag;
241 guint8 collocated_ref_idx;
243 gboolean strong_intra_smoothing_enabled_flag;
245 gboolean dependent_slice_segment_flag;
247 gboolean sign_data_hiding_enabled_flag;
249 gboolean constrained_intra_pred_flag;
251 gboolean transform_skip_enabled_flag;
253 gboolean cu_qp_delta_enabled_flag;
254 uint32_t diff_cu_qp_delta_depth;
256 gboolean weighted_pred_flag;
257 gboolean weighted_bipred_flag;
259 gboolean transquant_bypass_enabled_flag;
261 gboolean use_trellis;
266 /* frames between two IDR [idr, ...., idr) */
268 /* How may IDRs we have encoded */
269 guint32 total_idr_count;
270 /* frames between I/P and P frames [I, B, B, .., B, P) */
272 /* frames between I frames [I, B, B, .., B, P, ..., I), open GOP */
274 /* B frames between I/P and P. */
276 /* Use B pyramid structure in the GOP. */
278 /* Level 0 is the simple B not acting as ref. */
279 guint32 highest_pyramid_level;
280 /* If open GOP, I frames within a GOP. */
282 /* A map of all frames types within a GOP. */
287 guint8 pyramid_level;
288 /* Only for b pyramid */
289 gint left_ref_poc_diff;
290 gint right_ref_poc_diff;
291 } frame_types[MAX_GOP_SIZE];
293 /* Max poc within a GOP. */
294 guint32 max_pic_order_cnt;
295 guint32 log2_max_pic_order_cnt;
296 /* current index in the frames types map. */
297 guint cur_frame_index;
299 /* Total ref frames of forward and backward. */
300 guint32 num_ref_frames;
303 guint32 forward_ref_num;
304 guint32 backward_ref_num;
305 gboolean low_delay_b_mode;
307 guint num_reorder_frames;
314 guint32 rc_ctrl_mode;
321 /* macroblock bitrate control */
323 guint target_bitrate;
324 guint target_percentage;
327 guint max_bitrate_bits;
328 guint target_bitrate_bits;
329 /* length of CPB buffer */
331 /* length of CPB buffer (bits) */
332 guint cpb_length_bits;
339 struct _GstVaH265EncFrame
341 GstVaEncodePicture *picture;
342 GstH265SliceType type;
345 /* Only for b pyramid */
346 gint left_ref_poc_diff;
347 gint right_ref_poc_diff;
351 /* The total frame count we handled. */
352 guint total_frame_count;
356 * GstVaH265LevelLimits:
357 * @level_name: the level name
358 * @level_idc: the H.265 level_idc value
359 * @MaxLumaPs: the maximum luma picture size
360 * @MaxCPBTierMain: the maximum CPB size for Main tier(kbits)
361 * @MaxCPBTierHigh: the maximum CPB size for High tier(kbits)
362 * @MaxSliceSegPic: the maximum slice segments per picture
363 * @MaxTileRows: the maximum number of Tile Rows
364 * @MaxTileColumns: the maximum number of Tile Columns
365 * @MaxLumaSr: the maximum luma sample rate (samples/sec)
366 * @MaxBRTierMain: the maximum video bit rate for Main Tier(kbps)
367 * @MaxBRTierHigh: the maximum video bit rate for High Tier(kbps)
368 * @MinCr: the mimimum compression ratio
370 * The data structure that describes the limits of an H.265 level.
372 struct _GstVaH265LevelLimits
374 const gchar *level_name;
377 guint32 MaxCPBTierMain;
378 guint32 MaxCPBTierHigh;
379 guint32 MaxSliceSegPic;
381 guint32 MaxTileColumns;
383 guint32 MaxBRTierMain;
384 guint32 MaxBRTierHigh;
388 /* Table A-1 - Level limits */
390 static const GstVaH265LevelLimits _va_h265_level_limits[] = {
391 /* level idc MaxLumaPs MCPBMt MCPBHt MSlSeg MTR MTC MaxLumaSr MBRMt MBRHt MinCr */
392 { "1", 30, 36864, 350, 0, 16, 1, 1, 552960, 128, 0, 2 },
393 { "2", 60, 122880, 1500, 0, 16, 1, 1, 3686400, 1500, 0, 2 },
394 { "2.1", 63, 245760, 3000, 0, 20, 1, 1, 7372800, 3000, 0, 2 },
395 { "3", 90, 552960, 6000, 0, 30, 2, 2, 16588800, 6000, 0, 2 },
396 { "3.1", 93, 983040, 10000, 0, 40, 3, 3, 33177600, 10000, 0, 2 },
397 { "4", 120, 2228224, 12000, 30000, 75, 5, 5, 66846720, 12000, 30000, 4 },
398 { "4.1", 123, 2228224, 20000, 50000, 75, 5, 5, 133693440, 20000, 50000, 4 },
399 { "5", 150, 8912896, 25000, 100000, 200, 11, 10, 267386880, 25000, 100000, 6 },
400 { "5.1", 153, 8912896, 40000, 160000, 200, 11, 10, 534773760, 40000, 160000, 8 },
401 { "5.2", 156, 8912896, 60000, 240000, 200, 11, 10, 1069547520, 60000, 240000, 8 },
402 { "6", 180, 35651584, 60000, 240000, 600, 22, 20, 1069547520, 60000, 240000, 8 },
403 { "6.1", 183, 35651584, 120000, 480000, 600, 22, 20, 2139095040, 120000, 480000, 8 },
404 { "6.2", 186, 35651584, 240000, 800000, 600, 22, 20, 4278190080, 240000, 800000, 6 },
408 #ifndef GST_DISABLE_GST_DEBUG
410 _h265_slice_type_name (GstH265SliceType type)
413 case GST_H265_P_SLICE:
415 case GST_H265_B_SLICE:
417 case GST_H265_I_SLICE:
420 g_assert_not_reached ();
427 _rate_control_get_name (guint32 rc_mode)
429 GParamSpecEnum *spec;
432 if (!(properties[PROP_RATE_CONTROL]
433 && G_IS_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL])))
436 spec = G_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL]);
437 for (i = 0; i < spec->enum_class->n_values; i++) {
438 if (spec->enum_class->values[i].value == rc_mode)
439 return spec->enum_class->values[i].value_nick;
444 #endif /* end of GST_DISABLE_GST_DEBUG */
446 static GstVaH265EncFrame *
447 gst_va_h265_enc_frame_new (void)
449 GstVaH265EncFrame *frame;
451 frame = g_slice_new (GstVaH265EncFrame);
452 frame->last_frame = FALSE;
453 frame->picture = NULL;
454 frame->total_frame_count = 0;
460 gst_va_h265_enc_frame_free (gpointer pframe)
462 GstVaH265EncFrame *frame = pframe;
463 g_clear_pointer (&frame->picture, gst_va_encode_picture_free);
464 g_slice_free (GstVaH265EncFrame, frame);
467 static inline GstVaH265EncFrame *
468 _enc_frame (GstVideoCodecFrame * frame)
470 GstVaH265EncFrame *enc_frame = gst_video_codec_frame_get_user_data (frame);
471 g_assert (enc_frame);
475 static inline gboolean
476 _is_tile_enabled (GstVaH265Enc * self)
478 return self->partition.num_tile_cols * self->partition.num_tile_rows > 1;
481 static inline gboolean
482 _is_scc_enabled (GstVaH265Enc * self)
484 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
486 if (base->profile == VAProfileHEVCSccMain
487 || base->profile == VAProfileHEVCSccMain10
488 || base->profile == VAProfileHEVCSccMain444
489 #if VA_CHECK_VERSION(1, 8, 0)
490 || base->profile == VAProfileHEVCSccMain444_10
498 static GstH265NalUnitType
499 _h265_nal_unit_type (GstVaH265EncFrame * frame)
501 GstH265NalUnitType nal_unit_type = -1;
503 switch (frame->type) {
504 case GST_H265_I_SLICE:
505 if (frame->poc == 0) {
506 nal_unit_type = GST_H265_NAL_SLICE_IDR_W_RADL;
508 nal_unit_type = GST_H265_NAL_SLICE_TRAIL_R;
511 case GST_H265_P_SLICE:
512 nal_unit_type = GST_H265_NAL_SLICE_TRAIL_R;
514 case GST_H265_B_SLICE:
516 nal_unit_type = GST_H265_NAL_SLICE_TRAIL_R;
518 nal_unit_type = GST_H265_NAL_SLICE_TRAIL_N;
525 g_assert (nal_unit_type >= 0);
526 return nal_unit_type;
530 _h265_fill_ptl (GstVaH265Enc * self,
531 const VAEncSequenceParameterBufferHEVC * sequence,
532 GstH265ProfileTierLevel * ptl)
534 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
537 *ptl = (GstH265ProfileTierLevel) {
539 .tier_flag = sequence->general_tier_flag,
540 .profile_idc = sequence->general_profile_idc,
541 .profile_compatibility_flag = { },
542 .progressive_source_flag = 1,
543 .interlaced_source_flag = 0,
544 .non_packed_constraint_flag = 0,
545 .frame_only_constraint_flag = 1,
547 .level_idc = sequence->general_level_idc,
551 if (sequence->general_profile_idc == 1 /* Main profile */
552 /* In A.3.4, NOTE: When general_profile_compatibility_flag[ 3 ] is equal
553 to 1, general_profile_compatibility_flag[ 1 ] and
554 general_profile_compatibility_flag[ 2 ] should also be equal to 1. */
555 || sequence->general_profile_idc == 3 /* Main Still Picture profile */
557 ptl->profile_compatibility_flag[1] = 1;
561 /* In A.3.2, NOTE: When general_profile_compatibility_flag[ 1 ] is equal
562 to 1, general_profile_compatibility_flag[ 2 ] should also be equal to
564 sequence->general_profile_idc == 1 /* Main profile */
565 || sequence->general_profile_idc == 2 /* Main 10 profile */
566 /* In A.3.4, NOTE: When general_profile_compatibility_flag[ 3 ] is equal
567 to 1, general_profile_compatibility_flag[ 1 ] and
568 general_profile_compatibility_flag[ 2 ] should also be equal to 1. */
569 || sequence->general_profile_idc == 3 /* Main Still Picture profile */
571 ptl->profile_compatibility_flag[2] = 1;
574 if (sequence->general_profile_idc == 3)
575 ptl->profile_compatibility_flag[3] = 1;
577 if (sequence->general_profile_idc == 4) /* format range extensions profiles */
578 ptl->profile_compatibility_flag[4] = 1;
580 if (sequence->general_profile_idc == 9) /* screen content coding profiles */
581 ptl->profile_compatibility_flag[9] = 1;
583 /* additional indications specified for general_profile_idc from 4~10 */
584 if (sequence->general_profile_idc == 4) {
585 /* In A.3.5, Format range extensions profiles.
586 Just support main444, main444-10 main422-10 main422-12 and main-12
587 profile now, may add more profiles when needed. */
588 switch (base->profile) {
589 case VAProfileHEVCMain444:
590 ptl->max_12bit_constraint_flag = 1;
591 ptl->max_10bit_constraint_flag = 1;
592 ptl->max_8bit_constraint_flag = 1;
593 ptl->max_422chroma_constraint_flag = 0;
594 ptl->max_420chroma_constraint_flag = 0;
595 ptl->max_monochrome_constraint_flag = 0;
596 ptl->intra_constraint_flag = 0;
597 ptl->one_picture_only_constraint_flag = 0;
598 ptl->lower_bit_rate_constraint_flag = 1;
600 case VAProfileHEVCMain444_10:
601 ptl->max_12bit_constraint_flag = 1;
602 ptl->max_10bit_constraint_flag = 1;
603 ptl->max_8bit_constraint_flag = 0;
604 ptl->max_422chroma_constraint_flag = 0;
605 ptl->max_420chroma_constraint_flag = 0;
606 ptl->max_monochrome_constraint_flag = 0;
607 ptl->intra_constraint_flag = 0;
608 ptl->one_picture_only_constraint_flag = 0;
609 ptl->lower_bit_rate_constraint_flag = 1;
611 case VAProfileHEVCMain422_10:
612 ptl->max_12bit_constraint_flag = 1;
613 ptl->max_10bit_constraint_flag = 1;
614 ptl->max_8bit_constraint_flag = 0;
615 ptl->max_422chroma_constraint_flag = 1;
616 ptl->max_420chroma_constraint_flag = 0;
617 ptl->max_monochrome_constraint_flag = 0;
618 ptl->intra_constraint_flag = 0;
619 ptl->one_picture_only_constraint_flag = 0;
620 ptl->lower_bit_rate_constraint_flag = 1;
622 case VAProfileHEVCMain422_12:
623 ptl->max_12bit_constraint_flag = 1;
624 ptl->max_10bit_constraint_flag = 0;
625 ptl->max_8bit_constraint_flag = 0;
626 ptl->max_422chroma_constraint_flag = 1;
627 ptl->max_420chroma_constraint_flag = 0;
628 ptl->max_monochrome_constraint_flag = 0;
629 ptl->intra_constraint_flag = 0;
630 ptl->one_picture_only_constraint_flag = 0;
631 ptl->lower_bit_rate_constraint_flag = 1;
633 case VAProfileHEVCMain12:
634 ptl->max_12bit_constraint_flag = 1;
635 ptl->max_10bit_constraint_flag = 0;
636 ptl->max_8bit_constraint_flag = 0;
637 ptl->max_422chroma_constraint_flag = 1;
638 ptl->max_420chroma_constraint_flag = 1;
639 ptl->max_monochrome_constraint_flag = 0;
640 ptl->intra_constraint_flag = 0;
641 ptl->one_picture_only_constraint_flag = 0;
642 ptl->lower_bit_rate_constraint_flag = 1;
645 GST_WARNING_OBJECT (self, "do not support the profile: %s of"
646 " range extensions.", gst_va_profile_name (base->profile));
649 } else if (sequence->general_profile_idc == 9) {
650 /* In A.3.7, Screen content coding extensions profiles. */
651 switch (base->profile) {
652 case VAProfileHEVCSccMain:
653 ptl->max_14bit_constraint_flag = 1;
654 ptl->max_12bit_constraint_flag = 1;
655 ptl->max_10bit_constraint_flag = 1;
656 ptl->max_8bit_constraint_flag = 1;
657 ptl->max_422chroma_constraint_flag = 1;
658 ptl->max_420chroma_constraint_flag = 1;
659 ptl->max_monochrome_constraint_flag = 0;
660 ptl->intra_constraint_flag = 0;
661 ptl->one_picture_only_constraint_flag = 0;
662 ptl->lower_bit_rate_constraint_flag = 1;
664 case VAProfileHEVCSccMain10:
665 ptl->max_14bit_constraint_flag = 1;
666 ptl->max_12bit_constraint_flag = 1;
667 ptl->max_10bit_constraint_flag = 1;
668 ptl->max_8bit_constraint_flag = 0;
669 ptl->max_422chroma_constraint_flag = 1;
670 ptl->max_420chroma_constraint_flag = 1;
671 ptl->max_monochrome_constraint_flag = 0;
672 ptl->intra_constraint_flag = 0;
673 ptl->one_picture_only_constraint_flag = 0;
674 ptl->lower_bit_rate_constraint_flag = 1;
676 case VAProfileHEVCSccMain444:
677 ptl->max_14bit_constraint_flag = 1;
678 ptl->max_12bit_constraint_flag = 1;
679 ptl->max_10bit_constraint_flag = 1;
680 ptl->max_8bit_constraint_flag = 1;
681 ptl->max_422chroma_constraint_flag = 0;
682 ptl->max_420chroma_constraint_flag = 0;
683 ptl->max_monochrome_constraint_flag = 0;
684 ptl->intra_constraint_flag = 0;
685 ptl->one_picture_only_constraint_flag = 0;
686 ptl->lower_bit_rate_constraint_flag = 1;
688 #if VA_CHECK_VERSION(1, 8, 0)
689 case VAProfileHEVCSccMain444_10:
690 ptl->max_14bit_constraint_flag = 1;
691 ptl->max_12bit_constraint_flag = 1;
692 ptl->max_10bit_constraint_flag = 1;
693 ptl->max_8bit_constraint_flag = 0;
694 ptl->max_422chroma_constraint_flag = 0;
695 ptl->max_420chroma_constraint_flag = 0;
696 ptl->max_monochrome_constraint_flag = 0;
697 ptl->intra_constraint_flag = 0;
698 ptl->one_picture_only_constraint_flag = 0;
699 ptl->lower_bit_rate_constraint_flag = 1;
703 GST_WARNING_OBJECT (self, "do not support the profile: %s of screen"
704 " content coding extensions.", gst_va_profile_name (base->profile));
712 GST_WARNING_OBJECT (self, "Failed to write Profile Tier Level");
716 /* By now, the VPS is not really used, we just fill all its fields
717 with the same info from the SPS. */
719 _h265_fill_vps (GstVaH265Enc * self,
720 const VAEncSequenceParameterBufferHEVC * seq_param)
722 guint max_dec_pic_buffering =
723 self->gop.num_ref_frames + 1 < self->gop.max_dpb_size ?
724 self->gop.num_ref_frames + 1 : self->gop.max_dpb_size;
727 self->vps_hdr = (GstH265VPS) {
729 .base_layer_internal_flag = 1,
730 .base_layer_available_flag = 1,
731 .max_layers_minus1 = 0,
732 .max_sub_layers_minus1 = 0,
733 .temporal_id_nesting_flag = 1,
735 .sub_layer_ordering_info_present_flag = 0,
736 .max_dec_pic_buffering_minus1 = { max_dec_pic_buffering - 1, },
737 .max_num_reorder_pics = { self->gop.num_reorder_frames, },
738 .max_latency_increase_plus1 = { 0, },
740 .num_layer_sets_minus1 = 0,
741 .timing_info_present_flag = 0,
746 if (!_h265_fill_ptl (self, seq_param, &self->vps_hdr.profile_tier_level))
753 _h265_fill_sps (GstVaH265Enc * self,
754 const VAEncSequenceParameterBufferHEVC * seq_param)
756 guint max_dec_pic_buffering =
757 self->gop.num_ref_frames + 1 < self->gop.max_dpb_size ?
758 self->gop.num_ref_frames + 1 : self->gop.max_dpb_size;
760 g_assert (self->gop.log2_max_pic_order_cnt >= 4);
762 self->sps_hdr = (GstH265SPS) {
764 .vps = &self->vps_hdr,
765 .max_sub_layers_minus1 = 0,
766 .temporal_id_nesting_flag = 1,
768 .chroma_format_idc = seq_param->seq_fields.bits.chroma_format_idc,
769 .separate_colour_plane_flag =
770 seq_param->seq_fields.bits.separate_colour_plane_flag,
771 .pic_width_in_luma_samples = seq_param->pic_width_in_luma_samples,
772 .pic_height_in_luma_samples = seq_param->pic_height_in_luma_samples,
773 .conformance_window_flag = self->conformance_window_flag,
774 .conf_win_left_offset = self->conf_win_left_offset,
775 .conf_win_right_offset = self->conf_win_right_offset,
776 .conf_win_top_offset = self->conf_win_top_offset,
777 .conf_win_bottom_offset = self->conf_win_bottom_offset,
778 .bit_depth_luma_minus8 = seq_param->seq_fields.bits.bit_depth_luma_minus8,
779 .bit_depth_chroma_minus8 =
780 seq_param->seq_fields.bits.bit_depth_chroma_minus8,
781 .log2_max_pic_order_cnt_lsb_minus4 = self->gop.log2_max_pic_order_cnt - 4,
782 .sub_layer_ordering_info_present_flag = 0,
783 .max_dec_pic_buffering_minus1 = { max_dec_pic_buffering - 1, },
784 .max_num_reorder_pics = { self->gop.num_reorder_frames, },
785 .max_latency_increase_plus1 = { 0, },
786 .log2_min_luma_coding_block_size_minus3 =
787 seq_param->log2_min_luma_coding_block_size_minus3,
788 .log2_diff_max_min_luma_coding_block_size =
789 seq_param->log2_diff_max_min_luma_coding_block_size,
790 .log2_min_transform_block_size_minus2 =
791 seq_param->log2_min_transform_block_size_minus2,
792 .log2_diff_max_min_transform_block_size =
793 seq_param->log2_diff_max_min_transform_block_size,
794 .max_transform_hierarchy_depth_inter =
795 seq_param->max_transform_hierarchy_depth_inter,
796 .max_transform_hierarchy_depth_intra =
797 seq_param->max_transform_hierarchy_depth_intra,
798 .scaling_list_enabled_flag =
799 seq_param->seq_fields.bits.scaling_list_enabled_flag,
800 .scaling_list_data_present_flag =
801 self->features.scaling_list_data_present_flag,
802 /* Do not change the scaling list now. */
804 .amp_enabled_flag = seq_param->seq_fields.bits.amp_enabled_flag,
805 .sample_adaptive_offset_enabled_flag =
806 seq_param->seq_fields.bits.sample_adaptive_offset_enabled_flag,
807 .pcm_enabled_flag = seq_param->seq_fields.bits.pcm_enabled_flag,
808 .pcm_sample_bit_depth_luma_minus1 =
809 seq_param->pcm_sample_bit_depth_luma_minus1,
810 .pcm_sample_bit_depth_chroma_minus1 =
811 seq_param->pcm_sample_bit_depth_chroma_minus1,
812 .log2_min_pcm_luma_coding_block_size_minus3 =
813 seq_param->log2_min_pcm_luma_coding_block_size_minus3,
814 .log2_diff_max_min_pcm_luma_coding_block_size =
815 seq_param->log2_max_pcm_luma_coding_block_size_minus3 -
816 seq_param->log2_min_pcm_luma_coding_block_size_minus3,
817 .pcm_loop_filter_disabled_flag =
818 seq_param->seq_fields.bits.pcm_loop_filter_disabled_flag,
819 .num_short_term_ref_pic_sets = 0,
820 .long_term_ref_pics_present_flag = 0,
821 .temporal_mvp_enabled_flag =
822 seq_param->seq_fields.bits.sps_temporal_mvp_enabled_flag,
823 .strong_intra_smoothing_enabled_flag =
824 seq_param->seq_fields.bits.strong_intra_smoothing_enabled_flag,
825 .vui_parameters_present_flag =
826 seq_param->vui_parameters_present_flag,
828 .aspect_ratio_info_present_flag =
829 seq_param->vui_fields.bits.aspect_ratio_info_present_flag,
830 .aspect_ratio_idc = seq_param->aspect_ratio_idc,
831 .sar_width = seq_param->sar_width,
832 .sar_height = seq_param->sar_height,
833 .overscan_info_present_flag = 0,
834 .video_signal_type_present_flag = 0,
835 .chroma_loc_info_present_flag = 0,
836 .neutral_chroma_indication_flag =
837 seq_param->vui_fields.bits.neutral_chroma_indication_flag,
838 .field_seq_flag = seq_param->vui_fields.bits.field_seq_flag,
839 .frame_field_info_present_flag = 0,
840 .default_display_window_flag = 0,
841 .timing_info_present_flag =
842 seq_param->vui_fields.bits.vui_timing_info_present_flag,
843 .num_units_in_tick = seq_param->vui_num_units_in_tick,
844 .time_scale = seq_param->vui_time_scale,
845 .poc_proportional_to_timing_flag = 0,
846 /* TODO: provide HRD. */
847 .hrd_parameters_present_flag = 0,
849 .hrd_parameters_present_flag = (seq_param->bits_per_second > 0),
851 .nal_hrd_parameters_present_flag = 1,
852 .vcl_hrd_parameters_present_flag = 0,
853 .sub_pic_hrd_params_present_flag = 0,
854 .bit_rate_scale = (SX_BITRATE - 6),
855 .cpb_size_scale = (SX_CPB_SIZE - 4),
856 .initial_cpb_removal_delay_length_minus1 = 23,
857 .au_cpb_removal_delay_length_minus1 = 23,
858 .dpb_output_delay_length_minus1 = 23,
859 .fixed_pic_rate_general_flag = { 0, },
860 .fixed_pic_rate_within_cvs_flag = { 0, },
861 .low_delay_hrd_flag = { 1, },
862 .cpb_cnt_minus1 = { 0, },
863 .sublayer_hrd_params = {
864 { .bit_rate_value_minus1 = { (seq_param->bits_per_second >> SX_BITRATE) - 1, },
865 .cpb_size_value_minus1 = { (hrd_params->buffer_size >> SX_CPB_SIZE) - 1, },
866 .cpb_size_du_value_minus1 = { 0, },
867 .bit_rate_du_value_minus1 = { 0, },
868 .cbr_flag = { self->rc_ctrl == VA_RC_CBR, },
872 .bitstream_restriction_flag =
873 seq_param->vui_fields.bits.bitstream_restriction_flag,
874 .tiles_fixed_structure_flag =
875 seq_param->vui_fields.bits.tiles_fixed_structure_flag,
876 .motion_vectors_over_pic_boundaries_flag =
877 seq_param->vui_fields.bits.motion_vectors_over_pic_boundaries_flag,
878 .restricted_ref_pic_lists_flag =
879 seq_param->vui_fields.bits.restricted_ref_pic_lists_flag,
880 .min_spatial_segmentation_idc = seq_param->min_spatial_segmentation_idc,
881 .max_bytes_per_pic_denom = seq_param->max_bytes_per_pic_denom,
882 .max_bits_per_min_cu_denom = seq_param->max_bits_per_min_cu_denom,
883 .log2_max_mv_length_horizontal =
884 seq_param->vui_fields.bits.log2_max_mv_length_horizontal,
885 .log2_max_mv_length_vertical =
886 seq_param->vui_fields.bits.log2_max_mv_length_vertical,
888 .sps_extension_flag = _is_scc_enabled (self),
889 /* if sps_extension_present_flag */
890 .sps_range_extension_flag = 0,
891 .sps_multilayer_extension_flag = 0,
892 .sps_3d_extension_flag = 0,
893 .sps_scc_extension_flag = _is_scc_enabled (self),
894 /* if sps_scc_extension_flag */
895 #if VA_CHECK_VERSION(1, 8, 0)
896 .sps_scc_extension_params = {
897 .sps_curr_pic_ref_enabled_flag = 1,
898 .palette_mode_enabled_flag =
899 seq_param->scc_fields.bits.palette_mode_enabled_flag,
900 .palette_max_size = 64,
901 .delta_palette_max_predictor_size = 32,
902 .sps_palette_predictor_initializers_present_flag = 0,
903 .sps_num_palette_predictor_initializer_minus1 = 0,
904 .sps_palette_predictor_initializer = { },
905 .motion_vector_resolution_control_idc = 0,
906 .intra_boundary_filtering_disabled_flag = 0,
912 if (!_h265_fill_ptl (self, seq_param, &self->sps_hdr.profile_tier_level))
919 _h265_fill_pps (GstVaH265Enc * self,
920 VAEncPictureParameterBufferHEVC * pic_param,
921 GstH265SPS * sps, GstH265PPS * pps)
924 *pps = (GstH265PPS) {
927 .dependent_slice_segments_enabled_flag =
928 pic_param->pic_fields.bits.dependent_slice_segments_enabled_flag,
929 .output_flag_present_flag = 0,
930 .num_extra_slice_header_bits = 0,
931 .sign_data_hiding_enabled_flag =
932 pic_param->pic_fields.bits.sign_data_hiding_enabled_flag,
933 .cabac_init_present_flag = 0,
934 .num_ref_idx_l0_default_active_minus1 =
935 pic_param->num_ref_idx_l0_default_active_minus1,
936 .num_ref_idx_l1_default_active_minus1 =
937 pic_param->num_ref_idx_l1_default_active_minus1,
938 .init_qp_minus26 = pic_param->pic_init_qp - 26,
939 .constrained_intra_pred_flag =
940 pic_param->pic_fields.bits.constrained_intra_pred_flag,
941 .transform_skip_enabled_flag =
942 pic_param->pic_fields.bits.transform_skip_enabled_flag,
943 .cu_qp_delta_enabled_flag =
944 pic_param->pic_fields.bits.cu_qp_delta_enabled_flag,
945 .diff_cu_qp_delta_depth = pic_param->diff_cu_qp_delta_depth,
946 .cb_qp_offset = pic_param->pps_cb_qp_offset,
947 .cr_qp_offset = pic_param->pps_cr_qp_offset,
948 .slice_chroma_qp_offsets_present_flag = 0,
949 .weighted_pred_flag = pic_param->pic_fields.bits.weighted_pred_flag,
950 .weighted_bipred_flag = pic_param->pic_fields.bits.weighted_bipred_flag,
951 .transquant_bypass_enabled_flag =
952 pic_param->pic_fields.bits.transquant_bypass_enabled_flag,
953 .tiles_enabled_flag = pic_param->pic_fields.bits.tiles_enabled_flag,
954 .entropy_coding_sync_enabled_flag =
955 pic_param->pic_fields.bits.entropy_coding_sync_enabled_flag,
956 .num_tile_columns_minus1 = pic_param->num_tile_columns_minus1,
957 .num_tile_rows_minus1 = pic_param->num_tile_rows_minus1,
958 /* Only support uniform tile mode now. */
959 .uniform_spacing_flag = 1,
960 .loop_filter_across_tiles_enabled_flag =
961 pic_param->pic_fields.bits.loop_filter_across_tiles_enabled_flag,
962 .loop_filter_across_slices_enabled_flag =
963 pic_param->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag,
964 /* Do not change the default deblocking filter */
965 .deblocking_filter_control_present_flag = 0,
966 .deblocking_filter_override_enabled_flag = 0,
967 .deblocking_filter_disabled_flag = 0,
968 /* .beta_offset_div2,
970 .scaling_list_data_present_flag =
971 pic_param->pic_fields.bits.scaling_list_data_present_flag,
972 /* Do not change the scaling list now. */
974 /* Do not change the ref list */
975 .lists_modification_present_flag = 0,
976 .log2_parallel_merge_level_minus2 =
977 pic_param->log2_parallel_merge_level_minus2,
978 .slice_segment_header_extension_present_flag = 0,
979 .pps_extension_flag = _is_scc_enabled (self),
980 /* if pps_extension_flag*/
981 .pps_range_extension_flag = 0,
982 .pps_multilayer_extension_flag = 0,
983 .pps_3d_extension_flag = 0,
984 .pps_scc_extension_flag = _is_scc_enabled (self),
985 /* if pps_scc_extension_flag*/
986 #if VA_CHECK_VERSION(1, 8, 0)
987 .pps_scc_extension_params = {
988 .pps_curr_pic_ref_enabled_flag =
989 pic_param->scc_fields.bits.pps_curr_pic_ref_enabled_flag,
990 .residual_adaptive_colour_transform_enabled_flag = 0,
991 .pps_palette_predictor_initializers_present_flag = 0,
999 _h265_fill_slice_header (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1000 GstH265PPS * pps, VAEncSliceParameterBufferHEVC * slice_param,
1001 gboolean first_slice_segment_in_pic,
1002 guint list_forward_num, guint list_backward_num,
1003 gint negative_pocs[16], guint num_negative_pics,
1004 gint positive_pocs[16], guint num_positive_pics,
1005 GstH265SliceHdr * slice_hdr)
1011 *slice_hdr = (GstH265SliceHdr) {
1013 .first_slice_segment_in_pic_flag = first_slice_segment_in_pic,
1015 .no_output_of_prior_pics_flag = 0,
1016 .dependent_slice_segment_flag =
1017 slice_param->slice_fields.bits.dependent_slice_segment_flag,
1018 .segment_address = slice_param->slice_segment_address,
1019 .type = slice_param->slice_type,
1020 /* pps->output_flag_present_flag is not set now. */
1021 .pic_output_flag = 0,
1022 .colour_plane_id = slice_param->slice_fields.bits.colour_plane_id,
1023 /* Set the reference list fields later
1025 .short_term_ref_pic_set_sps_flag,
1026 .short_term_ref_pic_sets,
1027 .short_term_ref_pic_set_idx,
1029 .num_long_term_pics,
1032 .used_by_curr_pic_lt_flag[16],
1033 .delta_poc_msb_present_flag[16],
1034 .delta_poc_msb_cycle_lt[16], */
1035 .temporal_mvp_enabled_flag =
1036 slice_param->slice_fields.bits.slice_temporal_mvp_enabled_flag,
1038 slice_param->slice_fields.bits.slice_sao_luma_flag,
1040 slice_param->slice_fields.bits.slice_sao_chroma_flag,
1041 /* Set the ref num later
1042 .num_ref_idx_active_override_flag,
1043 .num_ref_idx_l0_active_minus1,
1044 .num_ref_idx_l1_active_minus1,
1045 .ref_pic_list_modification, */
1046 .mvd_l1_zero_flag = slice_param->slice_fields.bits.mvd_l1_zero_flag,
1047 .cabac_init_flag = slice_param->slice_fields.bits.cabac_init_flag,
1048 .collocated_from_l0_flag =
1049 slice_param->slice_fields.bits.collocated_from_l0_flag,
1050 .collocated_ref_idx = (slice_param->slice_type == GST_H265_I_SLICE ?
1051 0xFF : self->features.collocated_ref_idx),
1053 .pred_weight_table = { },
1054 .five_minus_max_num_merge_cand = 5 - slice_param->max_num_merge_cand,
1055 .use_integer_mv_flag = 0,
1056 .qp_delta = slice_param->slice_qp_delta,
1057 .cb_qp_offset = slice_param->slice_cb_qp_offset,
1058 .cr_qp_offset = slice_param->slice_cr_qp_offset,
1059 /* SCC is not enabled. */
1060 .slice_act_y_qp_offset = 0,
1061 .slice_act_cb_qp_offset = 0,
1062 .slice_act_cr_qp_offset = 0,
1064 .cu_chroma_qp_offset_enabled_flag = 0,
1065 /* Do not change deblocking filter setting. */
1066 .deblocking_filter_override_flag = 0,
1067 .deblocking_filter_disabled_flag = 0,
1068 /* .beta_offset_div2,
1070 .loop_filter_across_slices_enabled_flag =
1071 slice_param->slice_fields.bits.slice_loop_filter_across_slices_enabled_flag,
1072 .num_entry_point_offsets = 0,
1073 /* .offset_len_minus1,
1074 .entry_point_offset_minus1, */
1078 if (slice_hdr->dependent_slice_segment_flag)
1081 if (slice_param->slice_type == GST_H265_I_SLICE)
1084 slice_hdr->pic_order_cnt_lsb = frame->poc;
1086 /* Write the ref set explicitly. */
1087 slice_hdr->short_term_ref_pic_set_sps_flag = 0;
1088 slice_hdr->short_term_ref_pic_sets.inter_ref_pic_set_prediction_flag = 0;
1089 slice_hdr->short_term_ref_pic_sets.NumDeltaPocs =
1090 num_negative_pics + num_positive_pics;
1092 slice_hdr->short_term_ref_pic_sets.NumNegativePics = num_negative_pics;
1093 for (i = 0; i < num_negative_pics; i++) {
1094 delta_poc = negative_pocs[i] - frame->poc;
1095 g_assert (delta_poc < 0);
1096 slice_hdr->short_term_ref_pic_sets.DeltaPocS0[i] = delta_poc;
1098 if (i < list_forward_num) {
1099 slice_hdr->short_term_ref_pic_sets.UsedByCurrPicS0[i] = 1;
1101 slice_hdr->short_term_ref_pic_sets.UsedByCurrPicS0[i] = 0;
1105 slice_hdr->short_term_ref_pic_sets.NumPositivePics = num_positive_pics;
1106 for (i = 0; i < num_positive_pics; i++) {
1107 delta_poc = positive_pocs[i] - frame->poc;
1108 g_assert (delta_poc > 0);
1109 slice_hdr->short_term_ref_pic_sets.DeltaPocS1[i] = delta_poc;
1111 if (i < list_backward_num) {
1112 slice_hdr->short_term_ref_pic_sets.UsedByCurrPicS1[i] = 1;
1114 slice_hdr->short_term_ref_pic_sets.UsedByCurrPicS1[i] = 0;
1118 /* For scc, add the current frame into ref */
1119 if (_is_scc_enabled (self)) {
1120 slice_hdr->num_ref_idx_active_override_flag = 1;
1122 slice_hdr->num_ref_idx_active_override_flag =
1123 slice_param->slice_fields.bits.num_ref_idx_active_override_flag;
1126 if (slice_hdr->num_ref_idx_active_override_flag) {
1127 if (_is_scc_enabled (self)) {
1128 /* For scc, need to add 1 for current picture itself when calculating
1129 NumRpsCurrTempList0. But slice_param->num_ref_idx_l0_active_minus1
1130 does not include the current frame, but the stream's
1131 slice_hdr->num_ref_idx_l0_active_minus1 needs to include. */
1132 if (frame->type == GST_H265_I_SLICE) {
1133 g_assert (slice_param->num_ref_idx_l0_active_minus1 == 0);
1134 slice_hdr->num_ref_idx_l0_active_minus1 = 0;
1136 slice_hdr->num_ref_idx_l0_active_minus1 =
1137 slice_param->num_ref_idx_l0_active_minus1 + 1;
1140 slice_hdr->num_ref_idx_l0_active_minus1 =
1141 slice_param->num_ref_idx_l0_active_minus1;
1144 if (slice_param->slice_type == GST_H265_B_SLICE)
1145 slice_hdr->num_ref_idx_l1_active_minus1 =
1146 slice_param->num_ref_idx_l1_active_minus1;
1153 _h265_add_vps_header (GstVaH265Enc * self, GstVaH265EncFrame * frame)
1155 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1157 #define VPS_SIZE 4 + GST_ROUND_UP_8 (MAX_VPS_HDR_SIZE + \
1158 MAX_PROFILE_TIER_LEVEL_SIZE + MAX_HRD_PARAMS_SIZE) / 8
1159 guint8 packed_vps[VPS_SIZE] = { 0, };
1162 size = sizeof (packed_vps);
1163 if (gst_h265_bit_writer_vps (&self->vps_hdr, TRUE, packed_vps, &size)
1164 != GST_H265_BIT_WRITER_OK) {
1165 GST_ERROR_OBJECT (self, "Failed to write VPS header.");
1169 /* VPS does not have its own packed header define, just reuse
1170 VAEncPackedHeaderSequence */
1171 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
1172 VAEncPackedHeaderSequence, packed_vps, size * 8, FALSE)) {
1173 GST_ERROR_OBJECT (self, "Failed to add packed VPS header.");
1181 _h265_add_sps_header (GstVaH265Enc * self, GstVaH265EncFrame * frame)
1183 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1185 #define SPS_SIZE 4 + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE + \
1186 MAX_PROFILE_TIER_LEVEL_SIZE + 64 * MAX_SHORT_TERM_REFPICSET_SIZE + \
1187 MAX_VUI_PARAMS_SIZE + MAX_HRD_PARAMS_SIZE) / 8
1188 guint8 packed_sps[SPS_SIZE] = { 0, };
1191 size = sizeof (packed_sps);
1192 if (gst_h265_bit_writer_sps (&self->sps_hdr, TRUE, packed_sps, &size)
1193 != GST_H265_BIT_WRITER_OK) {
1194 GST_ERROR_OBJECT (self, "Failed to write SPS header.");
1198 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
1199 VAEncPackedHeaderSequence, packed_sps, size * 8, FALSE)) {
1200 GST_ERROR_OBJECT (self, "Failed to add packed SPS header.");
1208 _h265_add_pps_header (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1211 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1213 #define PPS_SIZE 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8
1214 guint8 packed_pps[PPS_SIZE] = { 0, };
1217 size = sizeof (packed_pps);
1218 if (gst_h265_bit_writer_pps (pps, TRUE, packed_pps,
1219 &size) != GST_H265_BIT_WRITER_OK) {
1220 GST_ERROR_OBJECT (self, "Failed to generate the picture header");
1224 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
1225 VAEncPackedHeaderPicture, packed_pps, size * 8, FALSE)) {
1226 GST_ERROR_OBJECT (self, "Failed to add the packed picture header");
1234 _h265_add_slice_header (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1235 GstH265SliceHdr * slice_hdr)
1237 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1238 GstH265NalUnitType nal_type = _h265_nal_unit_type (frame);
1240 #define SLICE_HDR_SIZE 4 + GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8
1241 guint8 packed_slice_hdr[SLICE_HDR_SIZE] = { 0, };
1242 #undef SLICE_HDR_SIZE
1244 size = sizeof (packed_slice_hdr);
1245 if (gst_h265_bit_writer_slice_hdr (slice_hdr, TRUE, nal_type,
1246 packed_slice_hdr, &size) != GST_H265_BIT_WRITER_OK) {
1247 GST_ERROR_OBJECT (self, "Failed to generate the slice header");
1251 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
1252 VAEncPackedHeaderSlice, packed_slice_hdr, size * 8, FALSE)) {
1253 GST_ERROR_OBJECT (self, "Failed to add the packed slice header");
1261 _h265_add_aud (GstVaH265Enc * self, GstVaH265EncFrame * frame)
1263 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1264 guint8 aud_data[8] = { };
1266 guint8 pic_type = 0;
1268 switch (frame->type) {
1269 case GST_H265_I_SLICE:
1272 case GST_H265_P_SLICE:
1275 case GST_H265_B_SLICE:
1279 g_assert_not_reached ();
1283 size = sizeof (aud_data);
1284 if (gst_h265_bit_writer_aud (pic_type, TRUE, aud_data,
1285 &size) != GST_H265_BIT_WRITER_OK) {
1286 GST_ERROR_OBJECT (self, "Failed to generate the AUD");
1290 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
1291 VAEncPackedHeaderRawData, aud_data, size * 8, FALSE)) {
1292 GST_ERROR_OBJECT (self, "Failed to add the AUD");
1299 /* Returns H.265 chroma_format_idc value from chroma type */
1301 _h265_get_chroma_format_idc (guint chroma_type)
1303 guint chroma_format_idc;
1305 switch (chroma_type) {
1306 case VA_RT_FORMAT_YUV400:
1307 chroma_format_idc = 0;
1309 case VA_RT_FORMAT_YUV420:
1310 case VA_RT_FORMAT_YUV420_10:
1311 case VA_RT_FORMAT_YUV420_12:
1312 chroma_format_idc = 1;
1314 case VA_RT_FORMAT_YUV422:
1315 case VA_RT_FORMAT_YUV422_10:
1316 case VA_RT_FORMAT_YUV422_12:
1317 chroma_format_idc = 2;
1319 case VA_RT_FORMAT_YUV444:
1320 case VA_RT_FORMAT_YUV444_10:
1321 case VA_RT_FORMAT_YUV444_12:
1322 chroma_format_idc = 3;
1325 GST_DEBUG ("unsupported GstVaapiChromaType value");
1326 chroma_format_idc = 1;
1329 return chroma_format_idc;
1333 _h265_fill_sequence_parameter (GstVaH265Enc * self,
1334 VAEncSequenceParameterBufferHEVC * sequence)
1336 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1337 guint profile_idc = 0;
1339 switch (base->profile) {
1340 case VAProfileHEVCMain:
1341 profile_idc = GST_H265_PROFILE_IDC_MAIN;
1343 case VAProfileHEVCMain10:
1344 profile_idc = GST_H265_PROFILE_IDC_MAIN;
1346 case VAProfileHEVCMain12:
1347 case VAProfileHEVCMain422_10:
1348 case VAProfileHEVCMain422_12:
1349 case VAProfileHEVCMain444:
1350 case VAProfileHEVCMain444_10:
1351 case VAProfileHEVCMain444_12:
1352 profile_idc = GST_H265_PROFILE_IDC_FORMAT_RANGE_EXTENSION;
1354 case VAProfileHEVCSccMain:
1355 case VAProfileHEVCSccMain10:
1356 case VAProfileHEVCSccMain444:
1357 #if VA_CHECK_VERSION(1, 8, 0)
1358 case VAProfileHEVCSccMain444_10:
1360 profile_idc = GST_H265_PROFILE_IDC_SCREEN_CONTENT_CODING;
1363 GST_ERROR_OBJECT (self, "unsupported profile %d", base->profile);
1368 *sequence = (VAEncSequenceParameterBufferHEVC) {
1369 .general_profile_idc = profile_idc,
1370 .general_level_idc = self->level_idc,
1371 .general_tier_flag = self->tier_flag,
1373 self->gop.i_period > 0 ? self->gop.i_period : self->gop.idr_period,
1374 .intra_idr_period = self->gop.idr_period,
1375 .ip_period = self->gop.ip_period,
1376 .bits_per_second = self->rc.target_bitrate_bits,
1377 .pic_width_in_luma_samples = self->luma_width,
1378 .pic_height_in_luma_samples = self->luma_height,
1379 .seq_fields.bits = {
1380 .chroma_format_idc = _h265_get_chroma_format_idc (base->rt_format),
1381 .separate_colour_plane_flag = self->features.separate_colour_plane_flag,
1382 .bit_depth_luma_minus8 = self->bits_depth_luma_minus8,
1383 .bit_depth_chroma_minus8 = self->bits_depth_chroma_minus8,
1384 .scaling_list_enabled_flag = self->features.scaling_list_enabled_flag,
1385 .strong_intra_smoothing_enabled_flag =
1386 self->features.strong_intra_smoothing_enabled_flag,
1387 .amp_enabled_flag = self->features.amp_enabled_flag,
1388 .sample_adaptive_offset_enabled_flag =
1389 self->features.sample_adaptive_offset_enabled_flag,
1390 .pcm_enabled_flag = self->features.pcm_enabled_flag,
1391 .pcm_loop_filter_disabled_flag =
1392 self->features.pcm_loop_filter_disabled_flag,
1393 .sps_temporal_mvp_enabled_flag =
1394 self->features.temporal_mvp_enabled_flag,
1395 .low_delay_seq = (self->gop.num_bframes == 0),
1396 .hierachical_flag = self->gop.b_pyramid,
1398 .log2_min_luma_coding_block_size_minus3 =
1399 self->features.log2_min_luma_coding_block_size_minus3,
1400 .log2_diff_max_min_luma_coding_block_size =
1401 self->features.log2_diff_max_min_luma_coding_block_size,
1402 .log2_min_transform_block_size_minus2 =
1403 self->features.log2_min_transform_block_size_minus2,
1404 .log2_diff_max_min_transform_block_size =
1405 self->features.log2_diff_max_min_transform_block_size,
1406 .max_transform_hierarchy_depth_inter =
1407 self->features.max_transform_hierarchy_depth_inter,
1408 .max_transform_hierarchy_depth_intra =
1409 self->features.max_transform_hierarchy_depth_intra,
1410 /* pcm_enabled_flag is unset, ignore */
1411 .pcm_sample_bit_depth_luma_minus1 =
1412 self->features.pcm_sample_bit_depth_luma_minus1,
1413 .pcm_sample_bit_depth_chroma_minus1 =
1414 self->features.pcm_sample_bit_depth_chroma_minus1,
1415 .log2_min_pcm_luma_coding_block_size_minus3 =
1416 self->features.log2_min_pcm_luma_coding_block_size_minus3,
1417 .log2_max_pcm_luma_coding_block_size_minus3 =
1418 self->features.log2_max_pcm_luma_coding_block_size_minus3,
1419 /* VUI parameters are always set, at least for timing_info (framerate) */
1420 .vui_parameters_present_flag = TRUE,
1421 .vui_fields.bits = {
1422 .aspect_ratio_info_present_flag = TRUE,
1423 .bitstream_restriction_flag = FALSE,
1424 .vui_timing_info_present_flag = TRUE,
1426 /* if (vui_fields.bits.aspect_ratio_info_present_flag) */
1427 .aspect_ratio_idc = 0xff,
1428 .sar_width = GST_VIDEO_INFO_PAR_N (&base->input_state->info),
1429 .sar_height = GST_VIDEO_INFO_PAR_D (&base->input_state->info),
1430 /* if (vui_fields.bits.vui_timing_info_present_flag) */
1431 .vui_num_units_in_tick = GST_VIDEO_INFO_FPS_D (&base->input_state->info),
1432 .vui_time_scale = GST_VIDEO_INFO_FPS_N (&base->input_state->info),
1433 #if VA_CHECK_VERSION(1, 8, 0)
1434 .scc_fields.bits.palette_mode_enabled_flag = _is_scc_enabled (self),
1443 _h265_to_va_coding_type (GstVaH265Enc * self, GstVaH265EncFrame * frame)
1445 guint coding_type = 0;
1447 switch (frame->type) {
1448 case GST_H265_I_SLICE:
1451 case GST_H265_P_SLICE:
1452 if (self->gop.low_delay_b_mode) {
1453 /* Convert P into forward ref B */
1459 case GST_H265_B_SLICE:
1460 /* We use hierarchical_level_plus1, so same for all B frames */
1467 g_assert (coding_type > 0);
1471 static inline gboolean
1472 _h265_fill_picture_parameter (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1473 VAEncPictureParameterBufferHEVC * pic_param, gint collocated_poc)
1475 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1476 guint8 num_ref_idx_l0_default_active_minus1 = 0;
1477 guint8 num_ref_idx_l1_default_active_minus1 = 0;
1478 guint hierarchical_level_plus1 = 0;
1482 if (self->gop.b_pyramid) {
1483 /* I/P is the base hierarchical level 0, L0 level B is 1, and so on. */
1484 hierarchical_level_plus1 = 1;
1486 if (frame->type == GST_H265_B_SLICE) {
1487 hierarchical_level_plus1 += 1;
1488 hierarchical_level_plus1 += frame->pyramid_level;
1492 if (frame->type == GST_H265_P_SLICE || frame->type == GST_H265_B_SLICE) {
1493 num_ref_idx_l0_default_active_minus1 =
1494 (self->gop.forward_ref_num > 0 ? self->gop.forward_ref_num - 1 : 0);
1496 if (frame->type == GST_H265_B_SLICE) {
1497 num_ref_idx_l1_default_active_minus1 =
1498 (self->gop.backward_ref_num > 0 ? self->gop.backward_ref_num - 1 : 0);
1501 *pic_param = (VAEncPictureParameterBufferHEVC) {
1502 .decoded_curr_pic.picture_id =
1503 gst_va_encode_picture_get_reconstruct_surface (frame->picture),
1504 .decoded_curr_pic.pic_order_cnt = frame->poc,
1505 .decoded_curr_pic.flags = 0,
1507 .coded_buf = frame->picture->coded_buffer,
1508 .last_picture = frame->last_frame,
1509 .pic_init_qp = self->rc.qp_i,
1510 .diff_cu_qp_delta_depth = self->features.diff_cu_qp_delta_depth,
1511 /* Do not use qp offset in picture. */
1512 .pps_cb_qp_offset = 0,
1513 .pps_cr_qp_offset = 0,
1514 /* TODO: multi tile support */
1515 .num_tile_columns_minus1 = 0,
1516 .num_tile_rows_minus1 = 0,
1517 .log2_parallel_merge_level_minus2 = 0,
1518 .ctu_max_bitsize_allowed = 0,
1519 .num_ref_idx_l0_default_active_minus1 = num_ref_idx_l0_default_active_minus1,
1520 .num_ref_idx_l1_default_active_minus1 = num_ref_idx_l1_default_active_minus1,
1521 .slice_pic_parameter_set_id = 0,
1522 .nal_unit_type = _h265_nal_unit_type (frame),
1523 .pic_fields.bits = {
1524 .idr_pic_flag = (frame->poc == 0),
1525 .coding_type = _h265_to_va_coding_type (self, frame),
1526 .reference_pic_flag = frame->is_ref,
1527 /* allow slice to set dependent_slice_segment_flag */
1528 .dependent_slice_segments_enabled_flag =
1529 self->features.dependent_slice_segment_flag,
1530 .sign_data_hiding_enabled_flag =
1531 self->features.sign_data_hiding_enabled_flag,
1532 .constrained_intra_pred_flag = self->features.constrained_intra_pred_flag,
1533 .transform_skip_enabled_flag = self->features.transform_skip_enabled_flag,
1534 .cu_qp_delta_enabled_flag = self->features.cu_qp_delta_enabled_flag,
1535 .weighted_pred_flag = self->features.weighted_pred_flag,
1536 .weighted_bipred_flag = self->features.weighted_bipred_flag,
1537 .transquant_bypass_enabled_flag =
1538 self->features.transquant_bypass_enabled_flag,
1539 .tiles_enabled_flag = _is_tile_enabled (self),
1540 .entropy_coding_sync_enabled_flag = 0,
1541 /* When we enable multi tiles, enable this. */
1542 .loop_filter_across_tiles_enabled_flag = _is_tile_enabled (self),
1543 .pps_loop_filter_across_slices_enabled_flag = 1,
1544 /* Should not change the scaling list, not used now */
1545 .scaling_list_data_present_flag =
1546 self->features.scaling_list_data_present_flag,
1547 .screen_content_flag = 0,
1548 /* Depend on weighted_pred_flag and weighted_bipred_flag */
1549 .enable_gpu_weighted_prediction = 0,
1551 .no_output_of_prior_pics_flag = 0,
1553 /* We use coding_type here, set this to 0. */
1554 .hierarchical_level_plus1 = hierarchical_level_plus1,
1555 #if VA_CHECK_VERSION(1, 8, 0)
1556 .scc_fields.bits.pps_curr_pic_ref_enabled_flag =
1557 _is_scc_enabled (self),
1563 if (frame->type != GST_H265_I_SLICE) {
1564 GstVaH265EncFrame *f;
1566 if (g_queue_is_empty (&base->ref_list)) {
1567 GST_ERROR_OBJECT (self, "No reference found for frame type %s",
1568 _h265_slice_type_name (frame->type));
1572 g_assert (g_queue_get_length (&base->ref_list) <= self->gop.num_ref_frames);
1574 /* ref frames in queue are already sorted by poc. */
1575 for (; i < g_queue_get_length (&base->ref_list); i++) {
1576 f = _enc_frame (g_queue_peek_nth (&base->ref_list, i));
1578 pic_param->reference_frames[i].picture_id =
1579 gst_va_encode_picture_get_reconstruct_surface (f->picture);
1580 pic_param->reference_frames[i].pic_order_cnt = f->poc;
1581 pic_param->reference_frames[i].flags = 0;
1586 for (; i < 15; i++) {
1587 pic_param->reference_frames[i].picture_id = VA_INVALID_SURFACE;
1588 pic_param->reference_frames[i].flags = VA_PICTURE_HEVC_INVALID;
1591 /* If mvp enabled, collocated_ref_idx specifies the reference index of
1592 the collocated picture used for temporal motion vector prediction.
1593 We should find the according index in reference_frames[] here. */
1594 if (frame->type != GST_H265_I_SLICE
1595 && self->features.temporal_mvp_enabled_flag) {
1598 for (i = 0; i < 15; i++) {
1599 if (pic_param->reference_frames[i].flags != VA_PICTURE_HEVC_INVALID &&
1600 pic_param->reference_frames[i].pic_order_cnt == collocated_poc) {
1606 g_assert (index >= 0);
1607 pic_param->collocated_ref_pic_index = index;
1609 pic_param->collocated_ref_pic_index = 0xFF;
1612 /* Setup tile info */
1613 if (pic_param->pic_fields.bits.tiles_enabled_flag) {
1614 /* Always set loop filter across tiles enabled now */
1615 pic_param->pic_fields.bits.loop_filter_across_tiles_enabled_flag = 1;
1617 pic_param->num_tile_columns_minus1 = self->partition.num_tile_cols - 1;
1618 pic_param->num_tile_rows_minus1 = self->partition.num_tile_rows - 1;
1620 /* The VA row_height_minus1 and column_width_minus1 size is 1 smaller
1621 than the MAX_COL_TILES and MAX_ROW_TILES, which means the driver
1622 can deduce the last tile's size based on the picture info. We need
1623 to take care of the array size here. */
1624 for (i = 0; i < MIN (self->partition.num_tile_cols, 19); i++)
1625 pic_param->column_width_minus1[i] = self->partition.tile_ctu_cols[i] - 1;
1626 for (i = 0; i < MIN (self->partition.num_tile_rows, 21); i++)
1627 pic_param->row_height_minus1[i] = self->partition.tile_ctu_rows[i] - 1;
1634 _h265_fill_slice_parameter (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1635 guint start_address, gint ctu_num, gboolean last_slice_of_pic,
1636 GstVaH265EncFrame * list0[16], guint list0_num,
1637 GstVaH265EncFrame * list1[16], guint list1_num,
1638 VAEncSliceParameterBufferHEVC * slice)
1640 int8_t slice_qp_delta = 0;
1641 GstH265SliceType frame_type;
1645 if (self->rc.rc_ctrl_mode == VA_RC_CQP) {
1646 if (frame->type == GST_H265_P_SLICE) {
1647 slice_qp_delta = self->rc.qp_p - self->rc.qp_i;
1648 } else if (frame->type == GST_H265_B_SLICE) {
1649 slice_qp_delta = (int8_t) (self->rc.qp_b - self->rc.qp_i);
1651 g_assert (slice_qp_delta <= 51 && slice_qp_delta >= -51);
1654 frame_type = frame->type;
1655 /* If low_delay_b_mode, we convert P to low delay b, which has 2
1656 ref lists and clone L1 from L0. */
1657 if (self->gop.low_delay_b_mode && frame->type == GST_H265_P_SLICE) {
1658 g_assert (self->gop.max_l1_num > 0);
1659 g_assert (list1_num == 0);
1661 frame_type = GST_H265_B_SLICE;
1662 list1_num = (list0_num <= self->gop.max_l1_num ?
1663 list0_num : self->gop.max_l1_num);
1665 for (i = 0; i < list1_num; i++)
1666 list1[i] = list0[i];
1669 /* In scc mode, the I frame can ref to itself and so the L0 reference
1670 list is enabled. Then we need to change I frame to P frame because
1671 it uses L0 list. We just leave all reference unchanged and so all
1672 ref_pic_list0's picture is invalid, the only ref is itself enabled
1673 by pic_param->scc_fields.bits.pps_curr_pic_ref_enabled_flag. */
1674 if (_is_scc_enabled (self) && frame->type == GST_H265_I_SLICE) {
1675 frame_type = GST_H265_P_SLICE;
1676 g_assert (list0_num == 0);
1679 *slice = (VAEncSliceParameterBufferHEVC) {
1680 .slice_segment_address = start_address,
1681 .num_ctu_in_slice = ctu_num,
1682 .slice_type = frame_type,
1683 /* Only one parameter set supported now. */
1684 .slice_pic_parameter_set_id = 0,
1685 /* Set the reference list later
1686 .num_ref_idx_l0_active_minus1,
1687 .num_ref_idx_l1_active_minus1,
1689 .ref_pic_list1[15], */
1690 /* weighted_pred_flag or weighted_bipred_idc is not enabled. */
1691 .luma_log2_weight_denom = 0,
1692 .delta_chroma_log2_weight_denom = 0,
1693 .delta_luma_weight_l0 = { 0, },
1694 .luma_offset_l0 = { 0, },
1695 .delta_chroma_weight_l0 = { },
1696 .chroma_offset_l0 = { },
1697 .delta_luma_weight_l1 = { },
1698 .luma_offset_l1 = { },
1699 .delta_chroma_weight_l1 = { },
1700 .chroma_offset_l1 = { },
1702 .max_num_merge_cand = 5,
1703 .slice_qp_delta = slice_qp_delta,
1704 .slice_cb_qp_offset = 0,
1705 .slice_cr_qp_offset = 0,
1706 /* deblocking_filter_control_present_flag not set now. */
1707 .slice_beta_offset_div2 = 0,
1708 .slice_tc_offset_div2 = 0,
1709 .slice_fields.bits = {
1710 .last_slice_of_pic_flag = last_slice_of_pic,
1711 .dependent_slice_segment_flag = (start_address == 0 ? 0 :
1712 self->features.dependent_slice_segment_flag),
1713 .colour_plane_id = self->features.colour_plane_id,
1714 .slice_temporal_mvp_enabled_flag =
1715 self->features.temporal_mvp_enabled_flag,
1716 .slice_sao_luma_flag = self->features.slice_sao_luma_flag,
1717 .slice_sao_chroma_flag = self->features.slice_sao_chroma_flag,
1718 /* Set the reference list later
1719 .num_ref_idx_active_override_flag, */
1720 .mvd_l1_zero_flag = 0,
1721 /* cabac_init_present_flag is not set now. */
1722 .cabac_init_flag = 0,
1723 /* deblocking_filter_control_present_flag not set now */
1724 .slice_deblocking_filter_disabled_flag = 0,
1725 .slice_loop_filter_across_slices_enabled_flag = 1,
1726 .collocated_from_l0_flag = (frame_type == GST_H265_I_SLICE ?
1727 0 : self->features.collocated_from_l0_flag),
1729 #if VA_CHECK_VERSION(1, 10, 0)
1730 .pred_weight_table_bit_offset = 0,
1731 .pred_weight_table_bit_length = 0,
1736 if (frame_type == GST_H265_B_SLICE || frame_type == GST_H265_P_SLICE) {
1737 slice->slice_fields.bits.num_ref_idx_active_override_flag =
1738 (list0_num > 0 || list1_num > 0);
1739 slice->num_ref_idx_l0_active_minus1 = list0_num > 0 ? list0_num - 1 : 0;
1741 if (frame_type == GST_H265_B_SLICE)
1742 slice->num_ref_idx_l1_active_minus1 = list1_num > 0 ? list1_num - 1 : 0;
1746 if (frame_type != GST_H265_I_SLICE) {
1747 for (; i < list0_num; i++) {
1748 slice->ref_pic_list0[i].picture_id =
1749 gst_va_encode_picture_get_reconstruct_surface (list0[i]->picture);
1750 slice->ref_pic_list0[i].pic_order_cnt = list0[i]->poc;
1753 for (; i < G_N_ELEMENTS (slice->ref_pic_list0); ++i) {
1754 slice->ref_pic_list0[i].picture_id = VA_INVALID_SURFACE;
1755 slice->ref_pic_list0[i].flags = VA_PICTURE_HEVC_INVALID;
1759 if (frame_type == GST_H265_B_SLICE) {
1760 for (; i < list1_num; i++) {
1761 slice->ref_pic_list1[i].picture_id =
1762 gst_va_encode_picture_get_reconstruct_surface (list1[i]->picture);
1763 slice->ref_pic_list1[i].pic_order_cnt = list1[i]->poc;
1766 for (; i < G_N_ELEMENTS (slice->ref_pic_list1); ++i) {
1767 slice->ref_pic_list1[i].picture_id = VA_INVALID_SURFACE;
1768 slice->ref_pic_list1[i].flags = VA_PICTURE_HEVC_INVALID;
1775 _h265_add_sequence_parameter (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1776 VAEncSequenceParameterBufferHEVC * sequence)
1778 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1780 if (!gst_va_encoder_add_param (base->encoder, frame->picture,
1781 VAEncSequenceParameterBufferType, sequence, sizeof (*sequence))) {
1782 GST_ERROR_OBJECT (self, "Failed to create the sequence parameter");
1790 _h265_add_picture_parameter (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1791 VAEncPictureParameterBufferHEVC * pic_param)
1793 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1795 if (!gst_va_encoder_add_param (base->encoder, frame->picture,
1796 VAEncPictureParameterBufferType, pic_param,
1797 sizeof (VAEncPictureParameterBufferHEVC))) {
1798 GST_ERROR_OBJECT (self, "Failed to create the picture parameter");
1806 _h265_add_slice_parameter (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1807 VAEncSliceParameterBufferHEVC * slice)
1809 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1811 if (!gst_va_encoder_add_param (base->encoder, frame->picture,
1812 VAEncSliceParameterBufferType, slice,
1813 sizeof (VAEncSliceParameterBufferHEVC))) {
1814 GST_ERROR_OBJECT (self, "Failed to add the slice parameter");
1822 _h265_add_slices (GstVaH265Enc * self,
1823 GstVaH265EncFrame * frame, GstH265PPS * pps,
1824 GstVaH265EncFrame * list_forward[16], guint list_forward_num,
1825 GstVaH265EncFrame * list_backward[16], guint list_backward_num,
1826 gint negative_pocs[16], guint num_negative_pics,
1827 gint positive_pocs[16], guint num_positive_pics)
1830 VAEncSliceParameterBufferHEVC slice;
1831 GstH265SliceHdr slice_hdr;
1833 for (i_slice = 0; i_slice < self->partition.num_slices; i_slice++) {
1834 if (!_h265_fill_slice_parameter (self, frame,
1835 self->partition.slice_segment_address[i_slice],
1836 self->partition.num_ctu_in_slice[i_slice],
1837 (i_slice == self->partition.num_slices - 1), list_forward,
1838 list_forward_num, list_backward, list_backward_num, &slice))
1841 if (!_h265_add_slice_parameter (self, frame, &slice))
1844 if (self->packed_headers & VA_ENC_PACKED_HEADER_SLICE) {
1845 if (!_h265_fill_slice_header (self, frame, pps, &slice, i_slice == 0,
1846 list_forward_num, list_backward_num, negative_pocs,
1847 num_negative_pics, positive_pocs, num_positive_pics, &slice_hdr))
1850 if (!_h265_add_slice_header (self, frame, &slice_hdr))
1859 _poc_asc_compare (const GstVaH265EncFrame ** a, const GstVaH265EncFrame ** b)
1861 return (*a)->poc - (*b)->poc;
1865 _poc_des_compare (const GstVaH265EncFrame ** a, const GstVaH265EncFrame ** b)
1867 return (*b)->poc - (*a)->poc;
1871 _h265_encode_one_frame (GstVaH265Enc * self, GstVideoCodecFrame * gst_frame)
1873 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1874 VAEncPictureParameterBufferHEVC pic_param;
1876 GstVaH265EncFrame *frame;
1877 GstVaH265EncFrame *list_forward[16] = { NULL, };
1878 guint list_forward_num = 0;
1879 GstVaH265EncFrame *list_backward[16] = { NULL, };
1880 guint list_backward_num = 0;
1881 gint negative_pocs[16] = { };
1882 guint num_negative_pics = 0;
1883 gint positive_pocs[16] = { };
1884 guint num_positive_pics = 0;
1885 gint collocated_poc = -1;
1888 g_return_val_if_fail (gst_frame, FALSE);
1890 frame = _enc_frame (gst_frame);
1892 if (self->aud && !_h265_add_aud (self, frame))
1895 /* Repeat the VPS/SPS for IDR. */
1896 if (frame->poc == 0) {
1897 VAEncSequenceParameterBufferHEVC sequence;
1899 if (!gst_va_base_enc_add_rate_control_parameter (base, frame->picture,
1900 self->rc.rc_ctrl_mode, self->rc.max_bitrate_bits,
1901 self->rc.target_percentage, self->rc.qp_i, self->rc.min_qp,
1902 self->rc.max_qp, self->rc.mbbrc))
1905 if (!gst_va_base_enc_add_quality_level_parameter (base, frame->picture,
1906 self->rc.target_usage))
1909 if (!gst_va_base_enc_add_frame_rate_parameter (base, frame->picture))
1912 if (!gst_va_base_enc_add_hrd_parameter (base, frame->picture,
1913 self->rc.rc_ctrl_mode, self->rc.cpb_length_bits))
1916 if (!gst_va_base_enc_add_trellis_parameter (base, frame->picture,
1917 self->features.use_trellis))
1920 _h265_fill_sequence_parameter (self, &sequence);
1921 if (!_h265_add_sequence_parameter (self, frame, &sequence))
1924 if (self->packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE) {
1925 if (!_h265_fill_vps (self, &sequence))
1928 if (!_h265_fill_sps (self, &sequence))
1931 if (!_h265_add_vps_header (self, frame))
1934 if (!_h265_add_sps_header (self, frame))
1939 /* Non I frame, construct reference list. */
1940 if (frame->type != GST_H265_I_SLICE) {
1941 GstVaH265EncFrame *vaf;
1942 GstVideoCodecFrame *f;
1944 for (i = g_queue_get_length (&base->ref_list) - 1; i >= 0; i--) {
1945 f = g_queue_peek_nth (&base->ref_list, i);
1946 vaf = _enc_frame (f);
1947 if (vaf->poc > frame->poc)
1950 list_forward[list_forward_num] = vaf;
1954 /* reorder to select the most nearest forward frames. */
1955 g_qsort_with_data (list_forward, list_forward_num, sizeof (gpointer),
1956 (GCompareDataFunc) _poc_des_compare, NULL);
1958 num_negative_pics = list_forward_num;
1959 for (i = 0; i < list_forward_num; i++)
1960 negative_pocs[i] = list_forward[i]->poc;
1962 if (list_forward_num > self->gop.forward_ref_num)
1963 list_forward_num = self->gop.forward_ref_num;
1965 if (self->features.temporal_mvp_enabled_flag
1966 && self->features.collocated_from_l0_flag) {
1967 if (self->features.collocated_ref_idx >= list_forward_num) {
1968 GST_ERROR_OBJECT (self, "MVP collocated_ref_idx %d is out of L0 range",
1969 self->features.collocated_ref_idx);
1973 collocated_poc = list_forward[self->features.collocated_ref_idx]->poc;
1977 if (frame->type == GST_H265_B_SLICE) {
1978 GstVaH265EncFrame *vaf;
1979 GstVideoCodecFrame *f;
1981 for (i = 0; i < g_queue_get_length (&base->ref_list); i++) {
1982 f = g_queue_peek_nth (&base->ref_list, i);
1983 vaf = _enc_frame (f);
1984 if (vaf->poc < frame->poc)
1987 list_backward[list_backward_num] = vaf;
1988 list_backward_num++;
1991 /* reorder to select the most nearest backward frames. */
1992 g_qsort_with_data (list_backward, list_backward_num, sizeof (gpointer),
1993 (GCompareDataFunc) _poc_asc_compare, NULL);
1995 num_positive_pics = list_backward_num;
1996 for (i = 0; i < list_backward_num; i++)
1997 positive_pocs[i] = list_backward[i]->poc;
1999 if (list_backward_num > self->gop.backward_ref_num)
2000 list_backward_num = self->gop.backward_ref_num;
2002 if (self->features.temporal_mvp_enabled_flag
2003 && !self->features.collocated_from_l0_flag) {
2004 if (self->features.collocated_ref_idx >= list_backward_num) {
2005 GST_ERROR_OBJECT (self, "MVP collocated_ref_idx %d is out of L1 range",
2006 self->features.collocated_ref_idx);
2010 collocated_poc = list_backward[self->features.collocated_ref_idx]->poc;
2014 g_assert (list_forward_num + list_backward_num <= self->gop.num_ref_frames);
2016 if (!_h265_fill_picture_parameter (self, frame, &pic_param, collocated_poc))
2018 if (!_h265_add_picture_parameter (self, frame, &pic_param))
2021 _h265_fill_pps (self, &pic_param, &self->sps_hdr, &pps);
2023 if ((self->packed_headers & VA_ENC_PACKED_HEADER_PICTURE)
2024 && frame->type == GST_H265_I_SLICE
2025 && !_h265_add_pps_header (self, frame, &pps))
2028 if (!_h265_add_slices (self, frame, &pps,
2029 list_forward, list_forward_num, list_backward, list_backward_num,
2030 negative_pocs, num_negative_pics, positive_pocs, num_positive_pics))
2033 if (!gst_va_encoder_encode (base->encoder, frame->picture)) {
2034 GST_ERROR_OBJECT (self, "Encode frame error");
2042 _h265_push_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame * gst_frame,
2045 GstVaH265Enc *self = GST_VA_H265_ENC (base);
2046 GstVaH265EncFrame *frame;
2048 g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
2052 /* Begin a new GOP, should have a empty reorder_list. */
2053 if (self->gop.cur_frame_index == self->gop.idr_period) {
2054 g_assert (g_queue_is_empty (&base->reorder_list));
2055 self->gop.cur_frame_index = 0;
2058 frame = _enc_frame (gst_frame);
2059 frame->poc = self->gop.cur_frame_index;
2060 g_assert (self->gop.cur_frame_index <= self->gop.max_pic_order_cnt);
2062 if (self->gop.cur_frame_index == 0) {
2063 g_assert (frame->poc == 0);
2064 GST_LOG_OBJECT (self, "system_frame_number: %d, an IDR frame, starts"
2065 " a new GOP", gst_frame->system_frame_number);
2067 g_queue_clear_full (&base->ref_list,
2068 (GDestroyNotify) gst_video_codec_frame_unref);
2071 frame->type = self->gop.frame_types[self->gop.cur_frame_index].slice_type;
2072 frame->is_ref = self->gop.frame_types[self->gop.cur_frame_index].is_ref;
2073 frame->pyramid_level =
2074 self->gop.frame_types[self->gop.cur_frame_index].pyramid_level;
2075 frame->left_ref_poc_diff =
2076 self->gop.frame_types[self->gop.cur_frame_index].left_ref_poc_diff;
2077 frame->right_ref_poc_diff =
2078 self->gop.frame_types[self->gop.cur_frame_index].right_ref_poc_diff;
2080 if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (gst_frame)) {
2081 GST_DEBUG_OBJECT (self, "system_frame_number: %d, a force key frame,"
2082 " promote its type from %s to %s", gst_frame->system_frame_number,
2083 _h265_slice_type_name (frame->type),
2084 _h265_slice_type_name (GST_H265_I_SLICE));
2085 frame->type = GST_H265_I_SLICE;
2086 frame->is_ref = TRUE;
2089 GST_LOG_OBJECT (self, "Push frame, system_frame_number: %d, poc %d, "
2090 "frame type %s", gst_frame->system_frame_number, frame->poc,
2091 _h265_slice_type_name (frame->type));
2093 self->gop.cur_frame_index++;
2094 g_queue_push_tail (&base->reorder_list,
2095 gst_video_codec_frame_ref (gst_frame));
2098 /* ensure the last one a non-B and end the GOP. */
2099 if (last && self->gop.cur_frame_index < self->gop.idr_period) {
2100 GstVideoCodecFrame *last_frame;
2102 /* Ensure next push will start a new GOP. */
2103 self->gop.cur_frame_index = self->gop.idr_period;
2105 if (!g_queue_is_empty (&base->reorder_list)) {
2106 last_frame = g_queue_peek_tail (&base->reorder_list);
2107 frame = _enc_frame (last_frame);
2108 if (frame->type == GST_H265_B_SLICE) {
2109 frame->type = GST_H265_P_SLICE;
2110 frame->is_ref = TRUE;
2118 struct RefFramesCount
2125 _count_backward_ref_num (gpointer data, gpointer user_data)
2127 GstVaH265EncFrame *frame = _enc_frame (data);
2128 struct RefFramesCount *count = (struct RefFramesCount *) user_data;
2130 g_assert (frame->poc != count->poc);
2131 if (frame->poc > count->poc)
2135 static GstVideoCodecFrame *
2136 _h265_pop_pyramid_b_frame (GstVaH265Enc * self)
2138 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2141 GstVaH265EncFrame *b_vaframe;
2142 GstVideoCodecFrame *b_frame;
2143 struct RefFramesCount count;
2145 g_assert (self->gop.backward_ref_num <= 2);
2150 /* Find the highest level with smallest poc. */
2151 for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
2152 GstVaH265EncFrame *vaf;
2153 GstVideoCodecFrame *f;
2155 f = g_queue_peek_nth (&base->reorder_list, i);
2159 b_vaframe = _enc_frame (b_frame);
2164 vaf = _enc_frame (f);
2165 if (b_vaframe->pyramid_level < vaf->pyramid_level) {
2172 if (b_vaframe->poc > vaf->poc) {
2180 /* Check whether its refs are already poped. */
2181 g_assert (b_vaframe->left_ref_poc_diff != 0);
2182 g_assert (b_vaframe->right_ref_poc_diff != 0);
2183 for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
2184 GstVaH265EncFrame *vaf;
2185 GstVideoCodecFrame *f;
2187 f = g_queue_peek_nth (&base->reorder_list, i);
2192 vaf = _enc_frame (f);
2193 if (vaf->poc == b_vaframe->poc + b_vaframe->left_ref_poc_diff
2194 || vaf->poc == b_vaframe->poc + b_vaframe->right_ref_poc_diff) {
2202 /* Ensure we already have backward refs */
2204 count.poc = b_vaframe->poc;
2205 g_queue_foreach (&base->ref_list, (GFunc) _count_backward_ref_num, &count);
2206 if (count.num >= 1) {
2207 GstVideoCodecFrame *f;
2209 /* it will unref at pop_frame */
2210 f = g_queue_pop_nth (&base->reorder_list, index);
2211 g_assert (f == b_frame);
2220 _h265_pop_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame ** out_frame)
2222 GstVaH265Enc *self = GST_VA_H265_ENC (base);
2223 GstVaH265EncFrame *vaframe;
2224 GstVideoCodecFrame *frame;
2225 struct RefFramesCount count;
2227 g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
2232 if (g_queue_is_empty (&base->reorder_list))
2235 /* Return the last pushed non-B immediately. */
2236 frame = g_queue_peek_tail (&base->reorder_list);
2237 vaframe = _enc_frame (frame);
2238 if (vaframe->type != GST_H265_B_SLICE) {
2239 frame = g_queue_pop_tail (&base->reorder_list);
2243 if (self->gop.b_pyramid) {
2244 frame = _h265_pop_pyramid_b_frame (self);
2251 g_assert (self->gop.backward_ref_num > 0);
2253 /* If GOP end, pop anyway. */
2254 if (self->gop.cur_frame_index == self->gop.idr_period) {
2255 frame = g_queue_pop_head (&base->reorder_list);
2259 /* Ensure we already have enough backward refs */
2260 frame = g_queue_peek_head (&base->reorder_list);
2261 vaframe = _enc_frame (frame);
2263 count.poc = vaframe->poc;
2264 g_queue_foreach (&base->ref_list, _count_backward_ref_num, &count);
2265 if (count.num >= self->gop.backward_ref_num) {
2266 frame = g_queue_pop_head (&base->reorder_list);
2273 vaframe = _enc_frame (frame);
2275 if (vaframe->poc == 0)
2276 self->gop.total_idr_count++;
2278 if (self->gop.b_pyramid && vaframe->type == GST_H265_B_SLICE) {
2279 GST_LOG_OBJECT (self, "pop a pyramid B frame with system_frame_number:"
2280 " %d, poc: %d, is_ref: %s, level %d",
2281 frame->system_frame_number, vaframe->poc,
2282 vaframe->is_ref ? "true" : "false", vaframe->pyramid_level);
2284 GST_LOG_OBJECT (self, "pop a frame with system_frame_number: %d,"
2285 " frame type: %s, poc: %d, is_ref: %s",
2286 frame->system_frame_number, _h265_slice_type_name (vaframe->type),
2287 vaframe->poc, vaframe->is_ref ? "true" : "false");
2290 /* unref frame popped from queue or pyramid b_frame */
2291 gst_video_codec_frame_unref (frame);
2297 gst_va_h265_enc_reorder_frame (GstVaBaseEnc * base, GstVideoCodecFrame * frame,
2298 gboolean bump_all, GstVideoCodecFrame ** out_frame)
2300 if (!_h265_push_one_frame (base, frame, bump_all)) {
2301 GST_ERROR_OBJECT (base, "Failed to push the input frame"
2302 " system_frame_number: %d into the reorder list",
2303 frame->system_frame_number);
2309 if (!_h265_pop_one_frame (base, out_frame)) {
2310 GST_ERROR_OBJECT (base, "Failed to pop the frame from the reorder list");
2318 static GstVideoCodecFrame *
2319 _h265_find_unused_reference_frame (GstVaH265Enc * self,
2320 GstVaH265EncFrame * frame)
2322 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2323 GstVaH265EncFrame *b_vaframe;
2324 GstVideoCodecFrame *b_frame;
2327 /* We still have more space. */
2328 if (g_queue_get_length (&base->ref_list) < self->gop.num_ref_frames)
2331 /* Not b_pyramid, sliding window is enough. */
2332 if (!self->gop.b_pyramid)
2333 return g_queue_peek_head (&base->ref_list);
2335 /* Non-b ref frame, just pop the first one. */
2336 if (frame->type != GST_H265_B_SLICE)
2337 return g_queue_peek_head (&base->ref_list);
2339 /* Choose the B frame with lowest POC. */
2342 for (i = 0; i < g_queue_get_length (&base->ref_list); i++) {
2343 GstVideoCodecFrame *f;
2344 GstVaH265EncFrame *vaf;
2346 f = g_queue_peek_nth (&base->ref_list, i);
2347 vaf = _enc_frame (f);
2348 if (vaf->type != GST_H265_B_SLICE)
2352 g_assert (b_vaframe == NULL);
2358 g_assert (b_vaframe);
2359 g_assert (vaf->poc != b_vaframe->poc);
2360 if (vaf->poc < b_vaframe->poc) {
2366 /* No B frame as ref. */
2368 return g_queue_peek_head (&base->ref_list);
2370 if (b_frame != g_queue_peek_head (&base->ref_list)) {
2371 b_vaframe = _enc_frame (b_frame);
2372 GST_LOG_OBJECT (self, "The frame with POC: %d will be"
2373 " replaced by the frame with POC: %d explicitly",
2374 b_vaframe->poc, frame->poc);
2381 _sort_by_poc (gconstpointer a, gconstpointer b, gpointer user_data)
2383 GstVaH265EncFrame *frame1 = _enc_frame ((GstVideoCodecFrame *) a);
2384 GstVaH265EncFrame *frame2 = _enc_frame ((GstVideoCodecFrame *) b);
2386 g_assert (frame1->poc != frame2->poc);
2388 return frame1->poc - frame2->poc;
2391 static GstFlowReturn
2392 gst_va_h265_enc_encode_frame (GstVaBaseEnc * base,
2393 GstVideoCodecFrame * gst_frame, gboolean is_last)
2395 GstVaH265Enc *self = GST_VA_H265_ENC (base);
2396 GstVaH265EncFrame *frame;
2397 GstVideoCodecFrame *unused_ref;
2399 frame = _enc_frame (gst_frame);
2400 frame->last_frame = is_last;
2402 g_assert (frame->picture == NULL);
2403 frame->picture = gst_va_encode_picture_new (base->encoder,
2404 gst_frame->input_buffer);
2406 if (!frame->picture) {
2407 GST_ERROR_OBJECT (base, "Failed to create the encode picture");
2408 return GST_FLOW_ERROR;
2411 if (!_h265_encode_one_frame (self, gst_frame)) {
2412 GST_ERROR_OBJECT (base, "Failed to encode the frame");
2413 return GST_FLOW_ERROR;
2416 g_queue_push_tail (&base->output_list, gst_video_codec_frame_ref (gst_frame));
2418 if (frame->is_ref) {
2419 unused_ref = _h265_find_unused_reference_frame (self, frame);
2422 if (!g_queue_remove (&base->ref_list, unused_ref))
2423 g_assert_not_reached ();
2425 gst_video_codec_frame_unref (unused_ref);
2428 /* Add it into the reference list. */
2429 g_queue_push_tail (&base->ref_list, gst_video_codec_frame_ref (gst_frame));
2430 g_queue_sort (&base->ref_list, _sort_by_poc, NULL);
2432 g_assert (g_queue_get_length (&base->ref_list) <= self->gop.num_ref_frames);
2438 /* Clear all the info of last reconfig and set the fields based on
2439 * property. The reconfig may change these fields because of the
2440 * profile/level and HW limitation. */
2442 gst_va_h265_enc_reset_state (GstVaBaseEnc * base)
2444 GstVaH265Enc *self = GST_VA_H265_ENC (base);
2446 GST_VA_BASE_ENC_CLASS (parent_class)->reset_state (base);
2448 GST_OBJECT_LOCK (self);
2449 self->features.use_trellis = self->prop.use_trellis;
2450 self->aud = self->prop.aud;
2451 self->partition.num_slices = self->prop.num_slices;
2452 self->partition.num_tile_cols = self->prop.num_tile_cols;
2453 self->partition.num_tile_rows = self->prop.num_tile_rows;
2454 self->gop.idr_period = self->prop.key_int_max;
2455 self->gop.num_bframes = self->prop.num_bframes;
2456 self->gop.b_pyramid = self->prop.b_pyramid;
2457 self->gop.num_iframes = self->prop.num_iframes;
2458 self->gop.num_ref_frames = self->prop.num_ref_frames;
2459 self->rc.rc_ctrl_mode = self->prop.rc_ctrl;
2460 self->rc.min_qp = self->prop.min_qp;
2461 self->rc.max_qp = self->prop.max_qp;
2462 self->rc.qp_i = self->prop.qp_i;
2463 self->rc.qp_p = self->prop.qp_p;
2464 self->rc.qp_b = self->prop.qp_b;
2465 self->rc.mbbrc = self->prop.mbbrc;
2466 self->rc.target_percentage = self->prop.target_percentage;
2467 self->rc.target_usage = self->prop.target_usage;
2468 self->rc.cpb_size = self->prop.cpb_size;
2469 GST_OBJECT_UNLOCK (self);
2471 self->level_idc = 0;
2472 self->level_str = NULL;
2474 self->tier_flag = FALSE;
2476 self->min_coding_block_size = 0;
2477 self->ctu_width = 0;
2478 self->ctu_height = 0;
2479 self->luma_width = 0;
2480 self->luma_height = 0;
2481 self->conformance_window_flag = FALSE;
2482 self->conf_win_left_offset = 0;
2483 self->conf_win_right_offset = 0;
2484 self->conf_win_top_offset = 0;
2485 self->conf_win_bottom_offset = 0;
2487 self->bits_depth_luma_minus8 = 0;
2488 self->bits_depth_chroma_minus8 = 0;
2490 self->packed_headers = 0;
2492 self->partition.slice_span_tiles = FALSE;
2493 g_clear_pointer (&self->partition.slice_segment_address, g_free);
2494 g_clear_pointer (&self->partition.num_ctu_in_slice, g_free);
2495 g_clear_pointer (&self->partition.tile_ctu_cols, g_free);
2496 g_clear_pointer (&self->partition.tile_ctu_rows, g_free);
2498 self->features.log2_min_luma_coding_block_size_minus3 = 0;
2499 self->features.log2_diff_max_min_luma_coding_block_size = 0;
2500 self->features.log2_diff_max_min_luma_coding_block_size = 0;
2501 self->features.log2_min_transform_block_size_minus2 = 0;
2502 self->features.log2_diff_max_min_transform_block_size = 0;
2503 self->features.max_transform_hierarchy_depth_inter = 0;
2504 self->features.max_transform_hierarchy_depth_intra = 0;
2505 self->features.separate_colour_plane_flag = FALSE;
2506 self->features.colour_plane_id = 0;
2507 self->features.scaling_list_enabled_flag = FALSE;
2508 self->features.scaling_list_data_present_flag = FALSE;
2509 self->features.amp_enabled_flag = FALSE;
2510 self->features.sample_adaptive_offset_enabled_flag = FALSE;
2511 self->features.slice_sao_luma_flag = FALSE;
2512 self->features.slice_sao_chroma_flag = FALSE;
2513 self->features.pcm_enabled_flag = FALSE;
2514 self->features.pcm_sample_bit_depth_luma_minus1 = 0;
2515 self->features.pcm_sample_bit_depth_chroma_minus1 = 0;
2516 self->features.log2_min_pcm_luma_coding_block_size_minus3 = 0;
2517 self->features.log2_max_pcm_luma_coding_block_size_minus3 = 0;
2518 self->features.temporal_mvp_enabled_flag = FALSE;
2519 self->features.collocated_from_l0_flag = FALSE;
2520 self->features.collocated_ref_idx = 0xFF;
2521 self->features.strong_intra_smoothing_enabled_flag = FALSE;
2522 self->features.dependent_slice_segment_flag = FALSE;
2523 self->features.sign_data_hiding_enabled_flag = FALSE;
2524 self->features.constrained_intra_pred_flag = FALSE;
2525 self->features.transform_skip_enabled_flag = FALSE;
2526 self->features.cu_qp_delta_enabled_flag = FALSE;
2527 self->features.diff_cu_qp_delta_depth = 0;
2528 self->features.weighted_pred_flag = FALSE;
2529 self->features.weighted_bipred_flag = FALSE;
2530 self->features.transquant_bypass_enabled_flag = FALSE;
2532 self->gop.i_period = 0;
2533 self->gop.total_idr_count = 0;
2534 self->gop.ip_period = 0;
2535 self->gop.low_delay_b_mode = FALSE;
2536 self->gop.highest_pyramid_level = 0;
2537 memset (self->gop.frame_types, 0, sizeof (self->gop.frame_types));
2538 self->gop.cur_frame_index = 0;
2539 self->gop.max_pic_order_cnt = 0;
2540 self->gop.log2_max_pic_order_cnt = 0;
2541 /* VAEncPictureParameterBufferHEVC.reference_frames limit 15 refs */
2542 self->gop.max_l0_num = 0;
2543 self->gop.max_l1_num = 0;
2544 self->gop.forward_ref_num = 0;
2545 self->gop.backward_ref_num = 0;
2546 self->gop.num_reorder_frames = 0;
2547 self->gop.max_dpb_size = 0;
2549 self->rc.max_bitrate = 0;
2550 self->rc.target_bitrate = 0;
2551 self->rc.max_bitrate_bits = 0;
2552 self->rc.target_bitrate_bits = 0;
2553 self->rc.cpb_length_bits = 0;
2555 memset (&self->vps_hdr, 0, sizeof (GstH265VPS));
2556 memset (&self->sps_hdr, 0, sizeof (GstH265SPS));
2560 _h265_get_rtformat (GstVaH265Enc * self, GstVideoFormat format,
2561 guint * depth, guint * chrome)
2565 chroma = gst_va_chroma_from_video_format (format);
2568 case VA_RT_FORMAT_YUV400:
2572 case VA_RT_FORMAT_YUV420:
2576 case VA_RT_FORMAT_YUV422:
2580 case VA_RT_FORMAT_YUV444:
2584 case VA_RT_FORMAT_YUV420_10:
2588 case VA_RT_FORMAT_YUV422_10:
2592 case VA_RT_FORMAT_YUV444_10:
2596 case VA_RT_FORMAT_YUV420_12:
2600 case VA_RT_FORMAT_YUV422_12:
2604 case VA_RT_FORMAT_YUV444_12:
2610 GST_ERROR_OBJECT (self, "Unsupported chroma for video format: %s",
2611 gst_video_format_to_string (format));
2619 _h265_decide_profile (GstVaH265Enc * self, VAProfile * _profile,
2622 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2623 gboolean ret = FALSE;
2624 GstVideoFormat in_format;
2627 GstCaps *allowed_caps = NULL;
2628 guint num_structures, i, j;
2629 GstStructure *structure;
2630 const GValue *v_profile;
2631 GArray *caps_candidates = NULL;
2632 GArray *chroma_candidates = NULL;
2633 guint depth = 0, chrome = 0;
2634 gboolean support_scc = TRUE;
2636 /* We do not have scc_fields defined in sequence and picture
2637 before 1.8.0, just disable scc all. */
2638 #if VA_CHECK_VERSION(1, 8, 0)
2641 support_scc = FALSE;
2644 caps_candidates = g_array_new (TRUE, TRUE, sizeof (VAProfile));
2645 chroma_candidates = g_array_new (TRUE, TRUE, sizeof (VAProfile));
2647 /* First, check whether the downstream requires a specified profile. */
2648 allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (base));
2650 allowed_caps = gst_pad_query_caps (GST_VIDEO_ENCODER_SRC_PAD (base), NULL);
2652 if (allowed_caps && !gst_caps_is_empty (allowed_caps)) {
2653 num_structures = gst_caps_get_size (allowed_caps);
2654 for (i = 0; i < num_structures; i++) {
2655 structure = gst_caps_get_structure (allowed_caps, i);
2656 v_profile = gst_structure_get_value (structure, "profile");
2660 if (G_VALUE_HOLDS_STRING (v_profile)) {
2662 gst_va_profile_from_name (HEVC, g_value_get_string (v_profile));
2663 if (profile == VAProfileNone)
2666 g_array_append_val (caps_candidates, profile);
2667 } else if (GST_VALUE_HOLDS_LIST (v_profile)) {
2670 for (j = 0; j < gst_value_list_get_size (v_profile); j++) {
2671 const GValue *p = gst_value_list_get_value (v_profile, j);
2675 profile = gst_va_profile_from_name (HEVC, g_value_get_string (p));
2676 if (profile == VAProfileNone)
2678 g_array_append_val (caps_candidates, profile);
2684 if (caps_candidates->len == 0) {
2685 GST_ERROR_OBJECT (self, "No available profile in caps");
2690 in_format = GST_VIDEO_INFO_FORMAT (&base->input_state->info);
2691 rt_format = _h265_get_rtformat (self, in_format, &depth, &chrome);
2693 GST_ERROR_OBJECT (self, "unsupported video format %s",
2694 gst_video_format_to_string (in_format));
2699 /* To make the thing a little simple here, We only consider the bit
2700 depth compatibility for each level. For example, we will consider
2701 that Main-4:4:4-10 is able to contain 8 bits 4:4:4 streams, but
2702 the we wiil not consider that it will contain 10 bits 4:2:0 stream. */
2706 profile = VAProfileHEVCMain444;
2707 g_array_append_val (chroma_candidates, profile);
2709 profile = VAProfileHEVCSccMain444;
2710 g_array_append_val (chroma_candidates, profile);
2715 profile = VAProfileHEVCMain444_10;
2716 g_array_append_val (chroma_candidates, profile);
2717 #if VA_CHECK_VERSION(1, 8, 0)
2718 profile = VAProfileHEVCSccMain444_10;
2719 g_array_append_val (chroma_candidates, profile);
2724 profile = VAProfileHEVCMain444_12;
2725 g_array_append_val (chroma_candidates, profile);
2727 } else if (chrome == 2) {
2730 profile = VAProfileHEVCMain422_10;
2731 g_array_append_val (chroma_candidates, profile);
2735 profile = VAProfileHEVCMain422_12;
2736 g_array_append_val (chroma_candidates, profile);
2738 } else if (chrome == 1 || chrome == 0) {
2739 /* 4:2:0 or 4:0:0 */
2741 profile = VAProfileHEVCMain;
2742 g_array_append_val (chroma_candidates, profile);
2744 profile = VAProfileHEVCSccMain;
2745 g_array_append_val (chroma_candidates, profile);
2750 profile = VAProfileHEVCMain10;
2751 g_array_append_val (chroma_candidates, profile);
2753 profile = VAProfileHEVCSccMain10;
2754 g_array_append_val (chroma_candidates, profile);
2759 profile = VAProfileHEVCMain12;
2760 g_array_append_val (chroma_candidates, profile);
2764 /* Just use the first HW available profile in candidate. */
2765 for (i = 0; i < chroma_candidates->len; i++) {
2766 profile = g_array_index (chroma_candidates, VAProfile, i);
2767 if (!gst_va_encoder_has_profile (base->encoder, profile))
2770 if ((rt_format & gst_va_encoder_get_rtformat (base->encoder,
2771 profile, GST_VA_BASE_ENC_ENTRYPOINT (base))) == 0)
2774 for (j = 0; j < caps_candidates->len; j++) {
2775 VAProfile p = g_array_index (caps_candidates, VAProfile, j);
2779 if (j == caps_candidates->len)
2782 *_profile = profile;
2783 *_rt_format = rt_format;
2789 g_clear_pointer (&caps_candidates, g_array_unref);
2790 g_clear_pointer (&chroma_candidates, g_array_unref);
2791 g_clear_pointer (&allowed_caps, gst_caps_unref);
2794 GST_INFO_OBJECT (self, "Select the profile %s",
2795 gst_va_profile_name (profile));
2797 GST_ERROR_OBJECT (self, "Failed to find an available profile");
2803 #define update_property(type, obj, old_val, new_val, prop_id) \
2804 gst_va_base_enc_update_property_##type (obj, old_val, new_val, properties[prop_id])
2805 #define update_property_uint(obj, old_val, new_val, prop_id) \
2806 update_property (uint, obj, old_val, new_val, prop_id)
2807 #define update_property_bool(obj, old_val, new_val, prop_id) \
2808 update_property (bool, obj, old_val, new_val, prop_id)
2811 _h265_calculate_tile_partition (GstVaH265Enc * self)
2813 guint32 ctu_per_slice;
2814 guint32 left_slices;
2816 guint32 ctu_tile_width_accu[MAX_COL_TILES + 1];
2817 guint32 ctu_tile_height_accu[MAX_ROW_TILES + 1];
2818 /* CTB address in tile scan.
2819 Add one as sentinel, hold val to calculate ctu_num */
2820 guint32 *tile_slice_address =
2821 g_malloc ((self->partition.num_slices + 1) * sizeof (guint32));
2822 /* map the CTB address in tile scan to CTB raster scan of a picture. */
2823 guint32 *tile_slice_address_map =
2824 g_malloc (self->ctu_width * self->ctu_height * sizeof (guint32));
2826 self->partition.slice_segment_address =
2827 g_malloc (self->partition.num_slices * sizeof (guint32));
2828 self->partition.num_ctu_in_slice =
2829 g_malloc (self->partition.num_slices * sizeof (guint32));
2830 self->partition.tile_ctu_cols = g_malloc (MAX_COL_TILES * sizeof (guint32));
2831 self->partition.tile_ctu_rows = g_malloc (MAX_ROW_TILES * sizeof (guint32));
2833 /* firstly uniformly separate CTUs into tiles, as the spec 6.5.1 define */
2834 for (i = 0; i < self->partition.num_tile_cols; i++)
2835 self->partition.tile_ctu_cols[i] =
2836 ((i + 1) * self->ctu_width) / self->partition.num_tile_cols -
2837 (i * self->ctu_width) / self->partition.num_tile_cols;
2838 for (i = 0; i < self->partition.num_tile_rows; i++)
2839 self->partition.tile_ctu_rows[i] =
2840 ((i + 1) * self->ctu_height) / self->partition.num_tile_rows -
2841 (i * self->ctu_height) / self->partition.num_tile_rows;
2843 /* The requirement that the slice should not span tiles. Firstly we
2844 should scatter slices uniformly into each tile, bigger tile gets
2845 more slices. Then we should assign CTUs within one tile uniformly
2846 to each slice in that tile. */
2847 if (!self->partition.slice_span_tiles) {
2848 guint32 *slices_per_tile = g_malloc (self->partition.num_tile_cols *
2849 self->partition.num_tile_rows * sizeof (guint32));
2851 ctu_per_slice = (self->ctu_width * self->ctu_height +
2852 self->partition.num_slices - 1) / self->partition.num_slices;
2853 g_assert (ctu_per_slice > 0);
2854 left_slices = self->partition.num_slices;
2857 i < self->partition.num_tile_cols * self->partition.num_tile_rows;
2859 slices_per_tile[i] = 1;
2862 while (left_slices) {
2863 /* Find the biggest CTUs/slices, and assign more. */
2864 gfloat largest = 0.0f;
2867 i < self->partition.num_tile_cols * self->partition.num_tile_rows;
2871 (self->partition.tile_ctu_cols[i % self->partition.num_tile_cols] *
2872 self->partition.tile_ctu_rows
2873 [i / self->partition.num_tile_cols])) /
2874 (gfloat) slices_per_tile[i];
2875 g_assert (f >= 1.0f);
2883 slices_per_tile[k]++;
2887 /* Assign CTUs in one tile uniformly to each slice. Note: the slice start
2888 address is CTB address in tile scan(see spec 6.5), that is, we accumulate
2889 all CTUs in tile0, then tile1, and tile2..., not from the picture's
2891 tile_slice_address[0] = 0;
2893 for (i = 0; i < self->partition.num_tile_rows; i++) {
2894 for (j = 0; j < self->partition.num_tile_cols; j++) {
2895 guint32 s_num = slices_per_tile[i * self->partition.num_tile_cols + j];
2896 guint32 one_tile_ctus =
2897 self->partition.tile_ctu_cols[j] * self->partition.tile_ctu_rows[i];
2900 GST_LOG_OBJECT (self, "Tile(row %d col %d), has CTU in col %d,"
2901 " CTU in row is %d, total CTU %d, assigned %d slices", i, j,
2902 self->partition.tile_ctu_cols[j], self->partition.tile_ctu_rows[i],
2903 one_tile_ctus, s_num);
2905 g_assert (s_num > 0);
2906 for (s = 0; s < s_num; s++) {
2907 tile_slice_address[k] = tile_slice_address[k - 1] +
2908 ((s + 1) * one_tile_ctus) / s_num - (s * one_tile_ctus) / s_num;
2909 self->partition.num_ctu_in_slice[k - 1] =
2910 tile_slice_address[k] - tile_slice_address[k - 1];
2916 g_assert (k == self->partition.num_slices + 1);
2917 /* Calculate the last one */
2918 self->partition.num_ctu_in_slice[self->partition.num_slices - 1] =
2919 self->ctu_width * self->ctu_height -
2920 tile_slice_address[self->partition.num_slices - 1];
2922 g_free (slices_per_tile);
2924 /* The easy way, just assign CTUs to each slice uniformly */
2926 guint ctu_size, ctu_mod_slice, cur_slice_ctu, last_ctu_index;
2928 ctu_size = self->ctu_width * self->ctu_height;
2930 ctu_per_slice = ctu_size / self->partition.num_slices;
2931 ctu_mod_slice = ctu_size % self->partition.num_slices;
2934 for (i = 0; i < self->partition.num_slices; i++) {
2935 cur_slice_ctu = ctu_per_slice;
2936 /* Scatter the remainder to each slice */
2937 if (ctu_mod_slice) {
2942 tile_slice_address[i] = last_ctu_index;
2943 self->partition.num_ctu_in_slice[i] = cur_slice_ctu;
2945 /* set calculation for next slice */
2946 last_ctu_index += cur_slice_ctu;
2947 g_assert (last_ctu_index <= ctu_size);
2951 /* Build the map to specifying the conversion between a CTB address in CTB
2952 raster scan of a picture and a CTB address in tile scan(see spec 6.5.1
2954 ctu_tile_width_accu[0] = 0;
2955 for (i = 1; i <= self->partition.num_tile_cols; i++)
2956 ctu_tile_width_accu[i] =
2957 ctu_tile_width_accu[i - 1] + self->partition.tile_ctu_cols[i - 1];
2959 ctu_tile_height_accu[0] = 0;
2960 for (i = 1; i <= self->partition.num_tile_rows; i++)
2961 ctu_tile_height_accu[i] =
2962 ctu_tile_height_accu[i - 1] + self->partition.tile_ctu_rows[i - 1];
2964 for (k = 0; k < self->ctu_width * self->ctu_height; k++) {
2965 /* The ctu coordinate in the picture. */
2966 guint32 x = k % self->ctu_width;
2967 guint32 y = k / self->ctu_width;
2968 /* The ctu coordinate in the tile mode. */
2971 /* The index of the CTU in the tile mode. */
2974 for (i = 0; i < self->partition.num_tile_cols; i++)
2975 if (x >= ctu_tile_width_accu[i])
2977 g_assert (tile_x <= self->partition.num_tile_cols - 1);
2979 for (j = 0; j < self->partition.num_tile_rows; j++)
2980 if (y >= ctu_tile_height_accu[j])
2982 g_assert (tile_y <= self->partition.num_tile_rows - 1);
2984 /* add all ctus in the tiles the same line before us */
2985 for (i = 0; i < tile_x; i++)
2986 tso += self->partition.tile_ctu_rows[tile_y] *
2987 self->partition.tile_ctu_cols[i];
2989 /* add all ctus in the tiles above us */
2990 for (j = 0; j < tile_y; j++)
2991 tso += self->ctu_width * self->partition.tile_ctu_rows[j];
2993 /* add the ctus inside the same tile before us */
2994 tso += (y - ctu_tile_height_accu[tile_y]) *
2995 self->partition.tile_ctu_cols[tile_x]
2996 + x - ctu_tile_width_accu[tile_x];
2998 g_assert (tso < self->ctu_width * self->ctu_height);
3000 tile_slice_address_map[tso] = k;
3003 for (i = 0; i < self->partition.num_slices; i++)
3004 self->partition.slice_segment_address[i] =
3005 tile_slice_address_map[tile_slice_address[i]];
3007 g_free (tile_slice_address);
3008 g_free (tile_slice_address_map);
3012 _h265_calculate_slice_partition (GstVaH265Enc * self, gint32 slice_structure)
3015 guint ctus_per_slice, ctus_mod_slice, cur_slice_ctus;
3016 guint last_ctu_index;
3019 /* TODO: consider other slice structure modes */
3020 if (!(slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS) &&
3021 !(slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS)) {
3022 GST_INFO_OBJECT (self, "Driver slice structure is %x, does not support"
3023 " ARBITRARY_MACROBLOCKS mode, fallback to no slice partition",
3025 self->partition.num_slices = 1;
3028 self->partition.slice_segment_address =
3029 g_malloc (self->partition.num_slices * sizeof (guint32));
3030 self->partition.num_ctu_in_slice =
3031 g_malloc (self->partition.num_slices * sizeof (guint32));
3033 ctu_size = self->ctu_width * self->ctu_height;
3035 g_assert (self->partition.num_slices &&
3036 self->partition.num_slices < ctu_size);
3038 ctus_per_slice = ctu_size / self->partition.num_slices;
3039 ctus_mod_slice = ctu_size % self->partition.num_slices;
3042 for (i_slice = 0; i_slice < self->partition.num_slices; i_slice++) {
3043 cur_slice_ctus = ctus_per_slice;
3044 /* Scatter the remainder to each slice */
3045 if (ctus_mod_slice) {
3050 /* Align start address to the row begin */
3051 if (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS) {
3052 guint ctu_width_round_factor;
3054 ctu_width_round_factor =
3055 self->ctu_width - (cur_slice_ctus % self->ctu_width);
3056 cur_slice_ctus += ctu_width_round_factor;
3057 if ((last_ctu_index + cur_slice_ctus) > ctu_size)
3058 cur_slice_ctus = ctu_size - last_ctu_index;
3061 self->partition.slice_segment_address[i_slice] = last_ctu_index;
3062 self->partition.num_ctu_in_slice[i_slice] = cur_slice_ctus;
3064 /* set calculation for next slice */
3065 last_ctu_index += cur_slice_ctus;
3066 g_assert (last_ctu_index <= ctu_size);
3071 _h265_setup_slice_and_tile_partition (GstVaH265Enc * self)
3073 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3075 gint32 slice_structure;
3077 /* Ensure the num_slices provided by the user not exceed the limit
3078 * of the number of slices permitted by the stream and by the
3080 g_assert (self->partition.num_slices >= 1);
3081 max_slices = gst_va_encoder_get_max_slice_num (base->encoder,
3082 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
3083 if (self->partition.num_slices > max_slices)
3084 self->partition.num_slices = max_slices;
3086 /* The stream size limit. */
3087 if (self->partition.num_slices >
3088 ((self->ctu_width * self->ctu_height + 1) / 2))
3089 self->partition.num_slices = ((self->ctu_width * self->ctu_height + 1) / 2);
3091 slice_structure = gst_va_encoder_get_slice_structure (base->encoder,
3092 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
3094 if (_is_tile_enabled (self)) {
3095 const GstVaH265LevelLimits *level_limits;
3098 if (!gst_va_encoder_has_tile (base->encoder,
3099 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base))) {
3100 self->partition.num_tile_cols = 1;
3101 self->partition.num_tile_rows = 1;
3104 level_limits = NULL;
3105 for (i = 0; i < G_N_ELEMENTS (_va_h265_level_limits); i++) {
3106 if (_va_h265_level_limits[i].level_idc == self->level_idc) {
3107 level_limits = &_va_h265_level_limits[i];
3111 g_assert (level_limits);
3113 if (self->partition.num_tile_cols > level_limits->MaxTileColumns) {
3114 GST_INFO_OBJECT (self, "num_tile_cols:%d exceeds MaxTileColumns:%d"
3115 " of level %s", self->partition.num_tile_cols,
3116 level_limits->MaxTileColumns, self->level_str);
3117 self->partition.num_tile_cols = level_limits->MaxTileColumns;
3119 if (self->partition.num_tile_rows > level_limits->MaxTileRows) {
3120 GST_INFO_OBJECT (self, "num_tile_rows:%d exceeds MaxTileRows:%d"
3121 " of level %s", self->partition.num_tile_rows,
3122 level_limits->MaxTileRows, self->level_str);
3123 self->partition.num_tile_rows = level_limits->MaxTileRows;
3126 if (self->partition.num_tile_cols > self->ctu_width) {
3127 GST_INFO_OBJECT (self,
3128 "Only %d CTUs in width, not enough to split into %d tile columns",
3129 self->ctu_width, self->partition.num_tile_cols);
3130 self->partition.num_tile_cols = self->ctu_width;
3132 if (self->partition.num_tile_rows > self->ctu_height) {
3133 GST_INFO_OBJECT (self,
3134 "Only %d CTUs in height, not enough to split into %d tile rows",
3135 self->ctu_height, self->partition.num_tile_rows);
3136 self->partition.num_tile_rows = self->ctu_height;
3139 /* Some driver require that the slice should not span tiles,
3140 we need to increase slice number if needed. */
3141 if (gst_va_display_is_implementation (base->display,
3142 GST_VA_IMPLEMENTATION_INTEL_IHD)) {
3143 if (self->partition.num_slices <
3144 self->partition.num_tile_cols * self->partition.num_tile_rows) {
3145 if (self->partition.num_tile_cols * self->partition.num_tile_rows >
3147 GST_ERROR_OBJECT (self, "The slice can not span tiles, but total"
3148 " tile num %d is bigger than max_slices %d",
3149 self->partition.num_tile_cols * self->partition.num_tile_rows,
3153 GST_INFO_OBJECT (self, "The num_slices %d is smaller than tile"
3154 " num %d. The slice can not span tiles, so set the num-slices"
3155 " to tile num.", self->partition.num_slices,
3156 self->partition.num_tile_cols * self->partition.num_tile_rows);
3157 self->partition.num_slices =
3158 self->partition.num_tile_cols * self->partition.num_tile_rows;
3162 self->partition.slice_span_tiles = FALSE;
3164 self->partition.slice_span_tiles = TRUE;
3167 _h265_calculate_tile_partition (self);
3169 _h265_calculate_slice_partition (self, slice_structure);
3172 update_property_uint (base, &self->prop.num_slices,
3173 self->partition.num_slices, PROP_NUM_SLICES);
3174 update_property_uint (base, &self->prop.num_tile_cols,
3175 self->partition.num_tile_cols, PROP_NUM_TILE_COLS);
3176 update_property_uint (base, &self->prop.num_tile_rows,
3177 self->partition.num_tile_rows, PROP_NUM_TILE_ROWS);
3182 /* Normalizes bitrate (and CPB size) for HRD conformance */
3184 _h265_calculate_bitrate_hrd (GstVaH265Enc * self)
3186 guint bitrate_bits, cpb_bits_size;
3188 /* Round down bitrate. This is a hard limit mandated by the user */
3189 g_assert (SX_BITRATE >= 6);
3190 bitrate_bits = (self->rc.max_bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
3191 GST_DEBUG_OBJECT (self, "Max bitrate: %u bits/sec", bitrate_bits);
3192 self->rc.max_bitrate_bits = bitrate_bits;
3194 bitrate_bits = (self->rc.target_bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
3195 GST_DEBUG_OBJECT (self, "Target bitrate: %u bits/sec", bitrate_bits);
3196 self->rc.target_bitrate_bits = bitrate_bits;
3198 if (self->rc.cpb_size > 0 && self->rc.cpb_size < (self->rc.max_bitrate / 2)) {
3199 GST_INFO_OBJECT (self, "Too small cpb_size: %d", self->rc.cpb_size);
3200 self->rc.cpb_size = 0;
3203 if (self->rc.cpb_size == 0) {
3204 /* We cache 2 second coded data by default. */
3205 self->rc.cpb_size = self->rc.max_bitrate * 2;
3206 GST_INFO_OBJECT (self, "Adjust cpb_size to: %d", self->rc.cpb_size);
3209 /* Round up CPB size. This is an HRD compliance detail */
3210 g_assert (SX_CPB_SIZE >= 4);
3211 cpb_bits_size = (self->rc.cpb_size * 1000) & ~((1U << SX_CPB_SIZE) - 1);
3213 GST_DEBUG_OBJECT (self, "HRD CPB size: %u bits", cpb_bits_size);
3214 self->rc.cpb_length_bits = cpb_bits_size;
3217 /* Estimates a good enough bitrate if none was supplied */
3219 _h265_ensure_rate_control (GstVaH265Enc * self)
3221 /* User can specify the properties of: "bitrate", "target-percentage",
3222 * "max-qp", "min-qp", "qpi", "qpp", "qpb", "mbbrc", "cpb-size",
3223 * "rate-control" and "target-usage" to control the RC behavior.
3225 * "target-usage" is different from the others, it controls the encoding
3226 * speed and quality, while the others control encoding bit rate and
3227 * quality. The lower value has better quality(maybe bigger MV search
3228 * range) but slower speed, the higher value has faster speed but lower
3231 * The possible composition to control the bit rate and quality:
3233 * 1. CQP mode: "rate-control=cqp", then "qpi", "qpp" and "qpb"
3234 * specify the QP of I/P/B frames respectively(within the
3235 * "max-qp" and "min-qp" range). The QP will not change during
3236 * the whole stream. Other properties are ignored.
3238 * 2. CBR mode: "rate-control=CBR", then the "bitrate" specify the
3239 * target bit rate and the "cpb-size" specifies the max coded
3240 * picture buffer size to avoid overflow. If the "bitrate" is not
3241 * set, it is calculated by the picture resolution and frame
3242 * rate. If "cpb-size" is not set, it is set to the size of
3243 * caching 2 second coded data. Encoder will try its best to make
3244 * the QP with in the ["max-qp", "min-qp"] range. "mbbrc" can
3245 * enable bit rate control in macro block level. Other paramters
3248 * 3. VBR mode: "rate-control=VBR", then the "bitrate" specify the
3249 * target bit rate, "target-percentage" is used to calculate the
3250 * max bit rate of VBR mode by ("bitrate" * 100) /
3251 * "target-percentage". It is also used by driver to calculate
3252 * the min bit rate. The "cpb-size" specifies the max coded
3253 * picture buffer size to avoid overflow. If the "bitrate" is not
3254 * set, the target bit rate will be calculated by the picture
3255 * resolution and frame rate. Encoder will try its best to make
3256 * the QP with in the ["max-qp", "min-qp"] range. "mbbrc" can
3257 * enable bit rate control in macro block level. Other paramters
3260 * 4. VCM mode: "rate-control=VCM", then the "bitrate" specify the
3261 * target bit rate, and encoder will try its best to make the QP
3262 * with in the ["max-qp", "min-qp"] range. Other paramters are
3266 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3268 guint32 rc_mode, quality_level, rc_ctrl;
3270 quality_level = gst_va_encoder_get_quality_level (base->encoder,
3271 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
3272 if (self->rc.target_usage > quality_level) {
3273 GST_INFO_OBJECT (self, "User setting target-usage: %d is not supported, "
3274 "fallback to %d", self->rc.target_usage, quality_level);
3275 self->rc.target_usage = quality_level;
3276 update_property_uint (base, &self->prop.target_usage,
3277 self->rc.target_usage, PROP_TARGET_USAGE);
3280 GST_OBJECT_LOCK (self);
3281 rc_ctrl = self->prop.rc_ctrl;
3282 GST_OBJECT_UNLOCK (self);
3284 if (rc_ctrl != VA_RC_NONE) {
3285 rc_mode = gst_va_encoder_get_rate_control_mode (base->encoder,
3286 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
3287 if (!(rc_mode & rc_ctrl)) {
3289 G_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL])->default_value;
3290 GST_INFO_OBJECT (self, "The rate control mode %s is not supported, "
3291 "fallback to %s mode", _rate_control_get_name (rc_ctrl),
3292 _rate_control_get_name (defval));
3293 self->rc.rc_ctrl_mode = defval;
3294 update_property_uint (base, &self->prop.rc_ctrl,
3295 self->rc.rc_ctrl_mode, PROP_RATE_CONTROL);
3298 self->rc.rc_ctrl_mode = VA_RC_NONE;
3301 if (self->rc.min_qp > self->rc.max_qp) {
3302 GST_INFO_OBJECT (self, "The min_qp %d is bigger than the max_qp %d, "
3303 "set it to the max_qp", self->rc.min_qp, self->rc.max_qp);
3304 self->rc.min_qp = self->rc.max_qp;
3306 update_property_uint (base, &self->prop.min_qp, self->rc.min_qp,
3310 /* Make all the qp in the valid range */
3311 if (self->rc.qp_i < self->rc.min_qp) {
3312 if (self->rc.qp_i != 26)
3313 GST_INFO_OBJECT (self, "The qp_i %d is smaller than the min_qp %d, "
3314 "set it to the min_qp", self->rc.qp_i, self->rc.min_qp);
3315 self->rc.qp_i = self->rc.min_qp;
3317 if (self->rc.qp_i > self->rc.max_qp) {
3318 if (self->rc.qp_i != 26)
3319 GST_INFO_OBJECT (self, "The qp_i %d is bigger than the max_qp %d, "
3320 "set it to the max_qp", self->rc.qp_i, self->rc.max_qp);
3321 self->rc.qp_i = self->rc.max_qp;
3324 if (self->rc.qp_p < self->rc.min_qp) {
3325 if (self->rc.qp_p != 26)
3326 GST_INFO_OBJECT (self, "The qp_p %d is smaller than the min_qp %d, "
3327 "set it to the min_qp", self->rc.qp_p, self->rc.min_qp);
3328 self->rc.qp_p = self->rc.min_qp;
3330 if (self->rc.qp_p > self->rc.max_qp) {
3331 if (self->rc.qp_p != 26)
3332 GST_INFO_OBJECT (self, "The qp_p %d is bigger than the max_qp %d, "
3333 "set it to the max_qp", self->rc.qp_p, self->rc.max_qp);
3334 self->rc.qp_p = self->rc.max_qp;
3337 if (self->rc.qp_b < self->rc.min_qp) {
3338 if (self->rc.qp_b != 26)
3339 GST_INFO_OBJECT (self, "The qp_b %d is smaller than the min_qp %d, "
3340 "set it to the min_qp", self->rc.qp_b, self->rc.min_qp);
3341 self->rc.qp_b = self->rc.min_qp;
3343 if (self->rc.qp_b > self->rc.max_qp) {
3344 if (self->rc.qp_b != 26)
3345 GST_INFO_OBJECT (self, "The qp_b %d is bigger than the max_qp %d, "
3346 "set it to the max_qp", self->rc.qp_b, self->rc.max_qp);
3347 self->rc.qp_b = self->rc.max_qp;
3350 GST_OBJECT_LOCK (self);
3351 bitrate = self->prop.bitrate;
3352 GST_OBJECT_UNLOCK (self);
3354 /* Calculate a bitrate is not set. */
3355 if ((self->rc.rc_ctrl_mode == VA_RC_CBR || self->rc.rc_ctrl_mode == VA_RC_VBR
3356 || self->rc.rc_ctrl_mode == VA_RC_VCM) && bitrate == 0) {
3357 /* FIXME: Provide better estimation. */
3358 /* Choose the max value of all levels' MinCr which is 8, and x2 for
3359 conservative calculation. So just using a 1/16 compression ratio,
3360 and the bits per pixel for YUV420, YUV422, YUV444, accordingly. */
3362 guint depth = 8, chrome = 1;
3365 if (!_h265_get_rtformat (self,
3366 GST_VIDEO_INFO_FORMAT (&base->input_state->info), &depth, &chrome))
3367 g_assert_not_reached ();
3371 } else if (chrome == 2) {
3376 bits_per_pix = bits_per_pix + bits_per_pix * (depth - 8) / 8;
3378 factor = (guint64) self->luma_width * self->luma_height * bits_per_pix / 16;
3379 bitrate = gst_util_uint64_scale (factor,
3380 GST_VIDEO_INFO_FPS_N (&base->input_state->info),
3381 GST_VIDEO_INFO_FPS_D (&base->input_state->info)) / 1000;
3383 GST_INFO_OBJECT (self, "target bitrate computed to %u kbps", bitrate);
3385 self->prop.bitrate = bitrate;
3386 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_BITRATE]);
3389 /* Adjust the setting based on RC mode. */
3390 switch (self->rc.rc_ctrl_mode) {
3393 self->rc.max_bitrate = 0;
3394 self->rc.target_bitrate = 0;
3395 self->rc.target_percentage = 0;
3396 self->rc.cpb_size = 0;
3399 self->rc.max_bitrate = bitrate;
3400 self->rc.target_bitrate = bitrate;
3401 self->rc.target_percentage = 100;
3402 self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
3405 g_assert (self->rc.target_percentage >= 10);
3406 self->rc.max_bitrate = (guint) gst_util_uint64_scale_int (bitrate,
3407 100, self->rc.target_percentage);
3408 self->rc.target_bitrate = bitrate;
3409 self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
3412 self->rc.max_bitrate = bitrate;
3413 self->rc.target_bitrate = bitrate;
3414 self->rc.target_percentage = 0;
3415 self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
3416 self->rc.cpb_size = 0;
3418 if (self->gop.num_bframes > 0) {
3419 GST_INFO_OBJECT (self, "VCM mode just support I/P mode, no B frame");
3420 self->gop.num_bframes = 0;
3421 self->gop.b_pyramid = FALSE;
3425 GST_WARNING_OBJECT (self, "Unsupported rate control");
3430 GST_DEBUG_OBJECT (self, "Max bitrate: %u bits/sec, "
3431 "Target bitrate: %u bits/sec", self->rc.max_bitrate,
3432 self->rc.target_bitrate);
3434 if (self->rc.rc_ctrl_mode != VA_RC_NONE && self->rc.rc_ctrl_mode != VA_RC_CQP)
3435 _h265_calculate_bitrate_hrd (self);
3438 update_property_uint (base, &self->prop.min_qp, self->rc.min_qp, PROP_MIN_QP);
3439 update_property_uint (base, &self->prop.cpb_size,
3440 self->rc.cpb_size, PROP_CPB_SIZE);
3441 update_property_uint (base, &self->prop.target_percentage,
3442 self->rc.target_percentage, PROP_TARGET_PERCENTAGE);
3443 update_property_uint (base, &self->prop.qp_i, self->rc.qp_i, PROP_QP_I);
3444 update_property_uint (base, &self->prop.qp_p, self->rc.qp_p, PROP_QP_P);
3445 update_property_uint (base, &self->prop.qp_b, self->rc.qp_b, PROP_QP_B);
3450 /* Derives the level and tier from the currently set limits */
3452 _h265_calculate_tier_level (GstVaH265Enc * self)
3454 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3455 guint i, PicSizeInSamplesY, LumaSr;
3456 guint32 tier_max_bitrate;
3458 PicSizeInSamplesY = self->luma_width * self->luma_height;
3459 LumaSr = gst_util_uint64_scale_int_ceil (PicSizeInSamplesY,
3460 GST_VIDEO_INFO_FPS_N (&base->input_state->info),
3461 GST_VIDEO_INFO_FPS_D (&base->input_state->info));
3463 for (i = 0; i < G_N_ELEMENTS (_va_h265_level_limits); i++) {
3464 const GstVaH265LevelLimits *const limits = &_va_h265_level_limits[i];
3466 /* Choose level by luma picture size and luma sample rate */
3467 if (PicSizeInSamplesY <= limits->MaxLumaPs && LumaSr <= limits->MaxLumaSr)
3471 if (i == G_N_ELEMENTS (_va_h265_level_limits))
3472 goto error_unsupported_level;
3474 self->level_idc = _va_h265_level_limits[i].level_idc;
3475 self->level_str = _va_h265_level_limits[i].level_name;
3476 self->min_cr = _va_h265_level_limits[i].MinCr;
3478 if (self->rc.rc_ctrl_mode == VA_RC_CQP) {
3479 g_assert (self->rc.max_bitrate == 0);
3481 /* We may need to calculate some max bit rate for CQP mode.
3482 Just set the main tier now. */
3483 self->tier_flag = FALSE;
3485 if (_va_h265_level_limits[i].MaxBRTierHigh == 0 ||
3486 self->rc.max_bitrate <= _va_h265_level_limits[i].MaxBRTierMain) {
3487 self->tier_flag = FALSE;
3489 self->tier_flag = TRUE;
3493 tier_max_bitrate = self->tier_flag ? _va_h265_level_limits[i].MaxBRTierHigh :
3494 _va_h265_level_limits[i].MaxBRTierMain;
3496 if (self->rc.max_bitrate > tier_max_bitrate) {
3497 GST_INFO_OBJECT (self, "The max bitrate of the stream is %u kbps, still"
3498 " larger than %s profile %s level %s tier's max bit rate %d kbps",
3499 self->rc.max_bitrate, gst_va_profile_name (base->profile),
3500 _va_h265_level_limits[i].level_name,
3501 (self->tier_flag ? "high" : "main"), tier_max_bitrate);
3504 GST_DEBUG_OBJECT (self, "profile: %s, level: %s, tier :%s, MinCr: %d",
3505 gst_va_profile_name (base->profile), _va_h265_level_limits[i].level_name,
3506 (self->tier_flag ? "high" : "main"), self->min_cr);
3510 error_unsupported_level:
3512 GST_ERROR_OBJECT (self,
3513 "failed to find a suitable level matching codec config");
3521 gint left_ref_poc_diff;
3522 gint right_ref_poc_diff;
3526 _set_pyramid_info (struct PyramidInfo *info, guint len,
3527 guint current_level, guint highest_level)
3531 g_assert (len >= 1);
3533 if (current_level == highest_level || len == 1) {
3534 for (index = 0; index < len; index++) {
3535 info[index].level = current_level;
3536 info[index].left_ref_poc_diff = -(index + 1);
3537 info[index].right_ref_poc_diff = len - index;
3544 info[index].level = current_level;
3545 info[index].left_ref_poc_diff = -(index + 1);
3546 info[index].right_ref_poc_diff = len - index;
3551 _set_pyramid_info (info, index, current_level, highest_level);
3553 if (index + 1 < len)
3554 _set_pyramid_info (&info[index + 1], len - (index + 1),
3555 current_level, highest_level);
3559 _h265_create_gop_frame_types (GstVaH265Enc * self)
3562 guint i_frames = self->gop.num_iframes;
3563 struct PyramidInfo pyramid_info[31] = { 0, };
3565 if (self->gop.highest_pyramid_level > 0) {
3566 g_assert (self->gop.num_bframes > 0);
3567 _set_pyramid_info (pyramid_info, self->gop.num_bframes,
3568 0, self->gop.highest_pyramid_level);
3571 g_assert (self->gop.idr_period <= MAX_GOP_SIZE);
3572 for (i = 0; i < self->gop.idr_period; i++) {
3574 self->gop.frame_types[i].slice_type = GST_H265_I_SLICE;
3575 self->gop.frame_types[i].is_ref = TRUE;
3579 /* Intra only stream. */
3580 if (self->gop.ip_period == 0) {
3581 self->gop.frame_types[i].slice_type = GST_H265_I_SLICE;
3582 self->gop.frame_types[i].is_ref = FALSE;
3586 if (i % self->gop.ip_period) {
3587 guint pyramid_index =
3588 i % self->gop.ip_period - 1 /* The first P or IDR */ ;
3590 self->gop.frame_types[i].slice_type = GST_H265_B_SLICE;
3591 self->gop.frame_types[i].pyramid_level =
3592 pyramid_info[pyramid_index].level;
3593 self->gop.frame_types[i].is_ref =
3594 (self->gop.frame_types[i].pyramid_level <
3595 self->gop.highest_pyramid_level);
3596 self->gop.frame_types[i].left_ref_poc_diff =
3597 pyramid_info[pyramid_index].left_ref_poc_diff;
3598 self->gop.frame_types[i].right_ref_poc_diff =
3599 pyramid_info[pyramid_index].right_ref_poc_diff;
3603 if (self->gop.i_period && i % self->gop.i_period == 0 && i_frames > 0) {
3604 /* Replace P with I. */
3605 self->gop.frame_types[i].slice_type = GST_H265_I_SLICE;
3606 self->gop.frame_types[i].is_ref = TRUE;
3611 self->gop.frame_types[i].slice_type = GST_H265_P_SLICE;
3612 self->gop.frame_types[i].is_ref = TRUE;
3615 /* Force the last one to be a P */
3616 if (self->gop.idr_period > 1 && self->gop.ip_period > 0) {
3617 self->gop.frame_types[self->gop.idr_period - 1].slice_type =
3619 self->gop.frame_types[self->gop.idr_period - 1].is_ref = TRUE;
3624 _h265_print_gop_structure (GstVaH265Enc * self)
3626 #ifndef GST_DISABLE_GST_DEBUG
3630 if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) < GST_LEVEL_INFO)
3633 str = g_string_new (NULL);
3635 g_string_append_printf (str, "[ ");
3637 for (i = 0; i < self->gop.idr_period; i++) {
3639 g_string_append_printf (str, "IDR");
3642 g_string_append_printf (str, ", ");
3645 if (self->gop.low_delay_b_mode &&
3646 self->gop.frame_types[i].slice_type == GST_H265_P_SLICE) {
3647 g_string_append_printf (str, "%s", "LDB");
3649 g_string_append_printf (str, "%s",
3650 _h265_slice_type_name (self->gop.frame_types[i].slice_type));
3653 if (self->gop.b_pyramid
3654 && self->gop.frame_types[i].slice_type == GST_H265_B_SLICE) {
3655 g_string_append_printf (str, "<L%d (%d, %d)>",
3656 self->gop.frame_types[i].pyramid_level,
3657 self->gop.frame_types[i].left_ref_poc_diff,
3658 self->gop.frame_types[i].right_ref_poc_diff);
3661 if (self->gop.frame_types[i].is_ref) {
3662 g_string_append_printf (str, "(ref)");
3667 g_string_append_printf (str, " ]");
3669 GST_INFO_OBJECT (self, "GOP size: %d, forward reference %d, backward"
3670 " reference %d, GOP structure: %s", self->gop.idr_period,
3671 self->gop.forward_ref_num, self->gop.backward_ref_num, str->str);
3673 g_string_free (str, TRUE);
3678 _h265_calculate_coded_size (GstVaH265Enc * self)
3680 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3681 guint codedbuf_size = 0;
3682 guint chrome, depth;
3684 if (!_h265_get_rtformat (self,
3685 GST_VIDEO_INFO_FORMAT (&base->input_state->info), &depth, &chrome))
3686 g_assert_not_reached ();
3693 codedbuf_size = (self->luma_width * self->luma_height * 3 / 2);
3697 codedbuf_size = (self->luma_width * self->luma_height * 2);
3701 codedbuf_size = (self->luma_width * self->luma_height * 3);
3704 g_assert_not_reached ();
3708 codedbuf_size = codedbuf_size + (codedbuf_size * (depth - 8) / 8);
3709 codedbuf_size = codedbuf_size / (self->min_cr / 2 /* For safety */ );
3711 /* FIXME: Using only a rough approximation for bitstream headers.
3712 * Not taken into account: ScalingList, RefPicListModification,
3713 * PredWeightTable, which is not used now. */
3714 /* Calculate the maximum sizes for common headers (in bits) */
3716 /* Account for VPS header */
3717 codedbuf_size += 4 /* start code */ + GST_ROUND_UP_8 (MAX_VPS_HDR_SIZE +
3718 MAX_PROFILE_TIER_LEVEL_SIZE + MAX_HRD_PARAMS_SIZE) / 8;
3720 /* Account for SPS header */
3721 codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE +
3722 MAX_PROFILE_TIER_LEVEL_SIZE + 64 * MAX_SHORT_TERM_REFPICSET_SIZE +
3723 MAX_VUI_PARAMS_SIZE + MAX_HRD_PARAMS_SIZE) / 8;
3725 /* Account for PPS header */
3726 codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8;
3728 /* Account for slice header */
3729 codedbuf_size += self->partition.num_slices * (4 +
3730 GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE + MAX_SHORT_TERM_REFPICSET_SIZE) / 8);
3732 base->codedbuf_size = codedbuf_size;
3733 GST_INFO_OBJECT (self, "Calculate codedbuf size: %u", base->codedbuf_size);
3736 /* Get log2_max_frame_num_minus4, log2_max_pic_order_cnt_lsb_minus4
3737 * value, shall be in the range of 0 to 12, inclusive. */
3739 _get_log2_max_num (guint num)
3748 /* shall be in the range of 0+4 to 12+4, inclusive. */
3751 } else if (ret > 16) {
3757 /* Consider the idr_period, num_bframes, L0/L1 reference number.
3758 * TODO: Load some preset fixed GOP structure.
3759 * TODO: Skip this if in lookahead mode. */
3761 _h265_generate_gop_structure (GstVaH265Enc * self)
3763 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3764 guint32 log2_max_frame_num;
3765 guint32 list0, list1, forward_num, backward_num, gop_ref_num;
3767 guint32 prediction_direction;
3769 /* If not set, generate a idr every second */
3770 if (self->gop.idr_period == 0) {
3771 self->gop.idr_period = (GST_VIDEO_INFO_FPS_N (&base->input_state->info)
3772 + GST_VIDEO_INFO_FPS_D (&base->input_state->info) - 1) /
3773 GST_VIDEO_INFO_FPS_D (&base->input_state->info);
3776 /* Do not use a too huge GOP size. */
3777 if (self->gop.idr_period > 1024) {
3778 self->gop.idr_period = 1024;
3779 GST_INFO_OBJECT (self, "Lowering the GOP size to %d", self->gop.idr_period);
3782 update_property_uint (base, &self->prop.key_int_max, self->gop.idr_period,
3785 /* Prefer have more than 1 refs for the GOP which is not very small. */
3786 if (self->gop.idr_period > 8) {
3787 if (self->gop.num_bframes > (self->gop.idr_period - 1) / 2) {
3788 self->gop.num_bframes = (self->gop.idr_period - 1) / 2;
3789 GST_INFO_OBJECT (self, "Lowering the number of num_bframes to %d",
3790 self->gop.num_bframes);
3793 /* beign and end should be ref */
3794 if (self->gop.num_bframes > self->gop.idr_period - 1 - 1) {
3795 if (self->gop.idr_period > 1) {
3796 self->gop.num_bframes = self->gop.idr_period - 1 - 1;
3798 self->gop.num_bframes = 0;
3800 GST_INFO_OBJECT (self, "Lowering the number of num_bframes to %d",
3801 self->gop.num_bframes);
3805 if (!gst_va_encoder_get_max_num_reference (base->encoder, base->profile,
3806 GST_VA_BASE_ENC_ENTRYPOINT (base), &list0, &list1)) {
3807 GST_INFO_OBJECT (self, "Failed to get the max num reference");
3811 self->gop.max_l0_num = list0;
3812 self->gop.max_l1_num = list1;
3813 GST_DEBUG_OBJECT (self, "list0 num: %d, list1 num: %d",
3814 self->gop.max_l0_num, self->gop.max_l1_num);
3816 forward_num = list0;
3817 backward_num = list1;
3819 prediction_direction = gst_va_encoder_get_prediction_direction (base->encoder,
3820 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
3821 if (prediction_direction) {
3822 #if VA_CHECK_VERSION(1,9,0)
3823 if (!(prediction_direction & VA_PREDICTION_DIRECTION_PREVIOUS)) {
3824 GST_INFO_OBJECT (self, "No forward prediction support");
3826 /* Only backward ref is insane. */
3830 if (!(prediction_direction & VA_PREDICTION_DIRECTION_FUTURE)) {
3831 GST_INFO_OBJECT (self, "No backward prediction support");
3835 if (prediction_direction & VA_PREDICTION_DIRECTION_BI_NOT_EMPTY) {
3836 if (self->gop.max_l1_num == 0) {
3837 GST_INFO_OBJECT (self, "Not possible to support "
3838 "VA_PREDICTION_DIRECTION_BI_NOT_EMPTY while list1 is 0");
3841 GST_INFO_OBJECT (self, "Enable low-delay-b mode");
3842 self->gop.low_delay_b_mode = TRUE;
3847 if (forward_num > self->gop.num_ref_frames)
3848 forward_num = self->gop.num_ref_frames;
3849 if (backward_num > self->gop.num_ref_frames)
3850 backward_num = self->gop.num_ref_frames;
3852 if (forward_num == 0) {
3853 GST_INFO_OBJECT (self,
3854 "No reference support, fallback to intra only stream");
3856 /* It does not make sense that if only the list1 exists. */
3857 self->gop.num_ref_frames = 0;
3859 self->gop.ip_period = 0;
3860 self->gop.num_bframes = 0;
3861 self->gop.b_pyramid = FALSE;
3862 self->gop.highest_pyramid_level = 0;
3863 self->gop.num_iframes = self->gop.idr_period - 1 /* The idr */ ;
3864 self->gop.forward_ref_num = 0;
3865 self->gop.backward_ref_num = 0;
3869 if (self->gop.num_ref_frames <= 1) {
3870 GST_INFO_OBJECT (self, "The number of reference frames is only %d,"
3871 " no B frame allowed, fallback to I/P mode", self->gop.num_ref_frames);
3872 self->gop.num_bframes = 0;
3876 /* b_pyramid needs at least 1 ref for B, besides the I/P */
3877 if (self->gop.b_pyramid && self->gop.num_ref_frames <= 2) {
3878 GST_INFO_OBJECT (self, "The number of reference frames is only %d,"
3879 " not enough for b_pyramid", self->gop.num_ref_frames);
3880 self->gop.b_pyramid = FALSE;
3883 if (backward_num == 0 && self->gop.num_bframes > 0) {
3884 GST_INFO_OBJECT (self,
3885 "No hw reference support for list 1, fallback to I/P mode");
3886 self->gop.num_bframes = 0;
3887 self->gop.b_pyramid = FALSE;
3890 /* I/P mode, no list1 needed. */
3891 if (self->gop.num_bframes == 0)
3894 /* Not enough B frame, no need for b_pyramid. */
3895 if (self->gop.num_bframes <= 1)
3896 self->gop.b_pyramid = FALSE;
3898 if (self->gop.num_ref_frames > forward_num + backward_num) {
3899 self->gop.num_ref_frames = forward_num + backward_num;
3900 GST_INFO_OBJECT (self, "HW limits, lowering the number of reference"
3901 " frames to %d", self->gop.num_ref_frames);
3903 self->gop.num_ref_frames = MIN (self->gop.num_ref_frames, 15);
3905 /* How many possible refs within a GOP. */
3906 gop_ref_num = (self->gop.idr_period + self->gop.num_bframes) /
3907 (self->gop.num_bframes + 1);
3909 if (self->gop.num_bframes > 0
3910 /* frame_num % (self->gop.num_bframes + 1) happens to be the end P */
3911 && (self->gop.idr_period % (self->gop.num_bframes + 1) != 1))
3914 /* Adjust reference num based on B frames and B pyramid. */
3915 if (self->gop.num_bframes == 0) {
3916 self->gop.b_pyramid = FALSE;
3917 self->gop.forward_ref_num = self->gop.num_ref_frames;
3918 self->gop.backward_ref_num = 0;
3919 } else if (self->gop.b_pyramid) {
3920 guint b_frames = self->gop.num_bframes;
3923 /* set b pyramid one backward ref. */
3924 self->gop.backward_ref_num = 1;
3925 self->gop.forward_ref_num =
3926 self->gop.num_ref_frames - self->gop.backward_ref_num;
3927 if (self->gop.forward_ref_num > forward_num)
3928 self->gop.forward_ref_num = forward_num;
3930 /* Balance the forward and backward refs */
3931 if ((self->gop.forward_ref_num > self->gop.backward_ref_num * 3)
3932 && backward_num > 1) {
3933 self->gop.backward_ref_num++;
3935 self->gop.forward_ref_num =
3936 self->gop.num_ref_frames - self->gop.backward_ref_num;
3937 if (self->gop.forward_ref_num > forward_num)
3938 self->gop.forward_ref_num = forward_num;
3941 b_frames = b_frames / 2;
3944 /* At least 1 B ref for each level, plus begin and end 2 P/I */
3946 if (b_refs + 2 > self->gop.num_ref_frames)
3949 self->gop.highest_pyramid_level++;
3950 b_frames = b_frames / 2;
3953 GST_INFO_OBJECT (self, "pyramid level is %d",
3954 self->gop.highest_pyramid_level);
3956 /* We prefer list0. Backward refs have more latency. */
3957 self->gop.backward_ref_num = 1;
3958 self->gop.forward_ref_num =
3959 self->gop.num_ref_frames - self->gop.backward_ref_num;
3960 /* Balance the forward and backward refs, but not cause a big latency. */
3961 while ((self->gop.num_bframes * self->gop.backward_ref_num <= 16)
3962 && (self->gop.backward_ref_num <= gop_ref_num)
3963 && (self->gop.backward_ref_num < backward_num)
3964 && (self->gop.forward_ref_num / self->gop.backward_ref_num > 4)) {
3965 self->gop.forward_ref_num--;
3966 self->gop.backward_ref_num++;
3969 if (self->gop.forward_ref_num > forward_num)
3970 self->gop.forward_ref_num = forward_num;
3973 /* It's OK, keep slots for GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME frame. */
3974 if (self->gop.forward_ref_num > gop_ref_num)
3975 GST_DEBUG_OBJECT (self, "num_ref_frames %d is bigger than gop_ref_num %d",
3976 self->gop.forward_ref_num, gop_ref_num);
3978 /* Include the ref picture itself. */
3979 self->gop.ip_period = 1 + self->gop.num_bframes;
3981 p_frames = gop_ref_num - 1 /* IDR */ ;
3984 if (self->gop.num_iframes > p_frames) {
3985 self->gop.num_iframes = p_frames;
3986 GST_INFO_OBJECT (self, "Too many I frames insertion, lowering it to %d",
3987 self->gop.num_iframes);
3990 if (self->gop.num_iframes > 0) {
3991 guint total_i_frames = self->gop.num_iframes + 1 /* IDR */ ;
3992 self->gop.i_period =
3993 (gop_ref_num / total_i_frames) * (self->gop.num_bframes + 1);
3997 /* init max_frame_num, max_poc */
3998 log2_max_frame_num = _get_log2_max_num (self->gop.idr_period);
3999 self->gop.log2_max_pic_order_cnt = log2_max_frame_num;
4000 self->gop.max_pic_order_cnt = 1 << self->gop.log2_max_pic_order_cnt;
4001 self->gop.num_reorder_frames = self->gop.b_pyramid ?
4002 self->gop.highest_pyramid_level * 2 + 1 /* the last P frame. */ :
4003 self->gop.backward_ref_num;
4004 /* Should not exceed the max ref num. */
4005 self->gop.num_reorder_frames =
4006 MIN (self->gop.num_reorder_frames, self->gop.num_ref_frames);
4007 self->gop.num_reorder_frames = MIN (self->gop.num_reorder_frames, 16);
4008 self->gop.max_dpb_size = self->gop.num_ref_frames + 1;
4010 _h265_create_gop_frame_types (self);
4011 _h265_print_gop_structure (self);
4014 update_property_uint (base, &self->prop.num_ref_frames,
4015 self->gop.num_ref_frames, PROP_NUM_REF_FRAMES);
4016 update_property_uint (base, &self->prop.num_iframes,
4017 self->gop.num_iframes, PROP_IFRAMES);
4018 update_property_uint (base, &self->prop.num_bframes,
4019 self->gop.num_bframes, PROP_BFRAMES);
4020 update_property_bool (base, &self->prop.b_pyramid,
4021 self->gop.b_pyramid, PROP_B_PYRAMID);
4027 _h265_init_packed_headers (GstVaH265Enc * self)
4029 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
4030 guint32 packed_headers;
4031 guint32 desired_packed_headers = VA_ENC_PACKED_HEADER_SEQUENCE /* SPS */
4032 | VA_ENC_PACKED_HEADER_PICTURE /* PPS */
4033 | VA_ENC_PACKED_HEADER_SLICE /* Slice headers */
4034 | VA_ENC_PACKED_HEADER_RAW_DATA; /* SEI, AUD, etc. */
4036 self->packed_headers = 0;
4038 if (!gst_va_encoder_get_packed_headers (base->encoder, base->profile,
4039 GST_VA_BASE_ENC_ENTRYPOINT (base), &packed_headers))
4042 if (desired_packed_headers & ~packed_headers) {
4043 GST_INFO_OBJECT (self, "Driver does not support some wanted packed headers "
4044 "(wanted %#x, found %#x)", desired_packed_headers, packed_headers);
4047 self->packed_headers = desired_packed_headers & packed_headers;
4053 _get_chroma_format_idc (guint va_chroma)
4055 guint chroma_format_idc;
4057 switch (va_chroma) {
4058 case VA_RT_FORMAT_YUV400:
4059 chroma_format_idc = 0;
4061 case VA_RT_FORMAT_YUV420:
4062 case VA_RT_FORMAT_YUV420_10:
4063 case VA_RT_FORMAT_YUV420_12:
4064 chroma_format_idc = 1;
4066 case VA_RT_FORMAT_YUV422:
4067 case VA_RT_FORMAT_YUV422_10:
4068 case VA_RT_FORMAT_YUV422_12:
4069 chroma_format_idc = 2;
4071 case VA_RT_FORMAT_YUV444:
4072 case VA_RT_FORMAT_YUV444_10:
4073 case VA_RT_FORMAT_YUV444_12:
4074 chroma_format_idc = 3;
4077 GST_WARNING ("unsupported VA chroma value");
4078 chroma_format_idc = 1;
4082 return chroma_format_idc;
4086 _h265_init_mvp (GstVaH265Enc * self, gboolean enable)
4089 /* For the simplicity, we only let MVP refer to List0[0],
4090 which is the last ref frame before the current frame. */
4091 self->features.temporal_mvp_enabled_flag = TRUE;
4092 self->features.collocated_from_l0_flag = TRUE;
4093 self->features.collocated_ref_idx = 0;
4095 self->features.temporal_mvp_enabled_flag = FALSE;
4096 self->features.collocated_from_l0_flag = FALSE;
4097 self->features.collocated_ref_idx = 0xff;
4101 /* We need to decide the profile and entrypoint before call this.
4102 It applies the optimized features provided by the va driver. */
4104 _h265_setup_encoding_features (GstVaH265Enc * self)
4106 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
4108 #if VA_CHECK_VERSION(1, 13, 0)
4109 VAConfigAttribValEncHEVCFeatures features;
4111 VAConfigAttrib attrib = {.type = VAConfigAttribEncHEVCFeatures };
4113 status = vaGetConfigAttributes (gst_va_display_get_va_dpy (base->display),
4114 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base), &attrib, 1);
4115 if (status != VA_STATUS_SUCCESS) {
4116 GST_INFO_OBJECT (self, "Failed to query encoding features: %s",
4117 vaErrorStr (status));
4118 goto default_options;
4121 if (attrib.value == VA_ATTRIB_NOT_SUPPORTED) {
4122 GST_INFO_OBJECT (self, "Driver does not support query encoding features");
4123 goto default_options;
4126 features.value = attrib.value;
4128 /* We do not enable this no matter what the driver say. */
4129 self->features.separate_colour_plane_flag = FALSE;
4130 self->features.colour_plane_id = 0;
4132 /* We do not enable scaling_list now. */
4133 self->features.scaling_list_enabled_flag = FALSE;
4134 self->features.scaling_list_data_present_flag = FALSE;
4136 self->features.amp_enabled_flag = (features.bits.amp != 0);
4138 self->features.sample_adaptive_offset_enabled_flag = (features.bits.sao != 0);
4139 self->features.slice_sao_luma_flag = (features.bits.sao != 0);
4140 self->features.slice_sao_chroma_flag = (features.bits.sao != 0);
4142 self->features.pcm_enabled_flag = (features.bits.pcm != 0);
4143 if (!self->features.pcm_enabled_flag) {
4144 self->features.pcm_sample_bit_depth_luma_minus1 = 0;
4145 self->features.pcm_sample_bit_depth_chroma_minus1 = 0;
4146 self->features.log2_min_pcm_luma_coding_block_size_minus3 = 0;
4147 self->features.log2_max_pcm_luma_coding_block_size_minus3 = 0;
4149 self->features.pcm_sample_bit_depth_luma_minus1 =
4150 self->bits_depth_luma_minus8 + 8 - 1;
4151 self->features.pcm_sample_bit_depth_chroma_minus1 =
4152 self->bits_depth_chroma_minus8 + 8 - 1;
4153 /* log2_min_pcm_luma_coding_block_size_minus3 and
4154 log2_diff_max_min_pcm_luma_coding_block_size set
4155 in coding_block_size */
4157 self->features.pcm_loop_filter_disabled_flag = FALSE;
4159 _h265_init_mvp (self, features.bits.temporal_mvp != 0);
4161 self->features.strong_intra_smoothing_enabled_flag =
4162 (features.bits.strong_intra_smoothing != 0);
4164 /* TODO: dependent slice */
4165 self->features.dependent_slice_segment_flag = FALSE;
4167 self->features.sign_data_hiding_enabled_flag =
4168 (features.bits.sign_data_hiding != 0);
4170 self->features.constrained_intra_pred_flag =
4171 (features.bits.constrained_intra_pred != 0);
4173 self->features.transform_skip_enabled_flag =
4174 (features.bits.transform_skip != 0);
4176 self->features.cu_qp_delta_enabled_flag =
4177 (self->rc.rc_ctrl_mode != VA_RC_CQP);
4178 self->features.diff_cu_qp_delta_depth = features.bits.cu_qp_delta;
4180 /* TODO: use weighted pred */
4181 self->features.weighted_pred_flag = FALSE;
4182 self->features.weighted_bipred_flag = FALSE;
4184 self->features.transquant_bypass_enabled_flag =
4185 (features.bits.transquant_bypass != 0);
4191 GST_DEBUG_OBJECT (self, "Apply default setting for features");
4193 self->features.separate_colour_plane_flag = FALSE;
4194 self->features.colour_plane_id = 0;
4195 self->features.scaling_list_enabled_flag = FALSE;
4196 self->features.scaling_list_data_present_flag = FALSE;
4197 self->features.amp_enabled_flag = TRUE;
4198 self->features.sample_adaptive_offset_enabled_flag = FALSE;
4199 self->features.slice_sao_luma_flag = FALSE;
4200 self->features.slice_sao_chroma_flag = FALSE;
4201 self->features.pcm_enabled_flag = 0;
4202 self->features.pcm_sample_bit_depth_luma_minus1 = 0;
4203 self->features.pcm_sample_bit_depth_chroma_minus1 = 0;
4204 self->features.log2_min_pcm_luma_coding_block_size_minus3 = 0;
4205 self->features.log2_max_pcm_luma_coding_block_size_minus3 = 0;
4206 self->features.pcm_loop_filter_disabled_flag = FALSE;
4207 _h265_init_mvp (self, TRUE);
4208 self->features.strong_intra_smoothing_enabled_flag = TRUE;
4209 self->features.dependent_slice_segment_flag = FALSE;
4210 self->features.sign_data_hiding_enabled_flag = FALSE;
4211 self->features.constrained_intra_pred_flag = FALSE;
4212 self->features.transform_skip_enabled_flag = TRUE;
4213 self->features.cu_qp_delta_enabled_flag =
4214 (self->rc.rc_ctrl_mode != VA_RC_CQP);
4215 self->features.diff_cu_qp_delta_depth = 0;
4216 self->features.weighted_pred_flag = FALSE;
4217 self->features.weighted_bipred_flag = FALSE;
4218 self->features.transquant_bypass_enabled_flag = FALSE;
4220 #if VA_CHECK_VERSION(1, 13, 0)
4223 GST_DEBUG_OBJECT (self, "Set features to: "
4224 "separate_colour_plane_flag = %d, "
4225 "colour_plane_id = %d, "
4226 "scaling_list_enabled_flag = %d, "
4227 "scaling_list_data_present_flag = %d, "
4228 "amp_enabled_flag = %d, "
4229 "sample_adaptive_offset_enabled_flag = %d, "
4230 "slice_sao_luma_flag = %d, "
4231 "slice_sao_chroma_flag = %d, "
4232 "pcm_enabled_flag = %d, "
4233 "pcm_sample_bit_depth_luma_minus1 = %d, "
4234 "pcm_sample_bit_depth_chroma_minus1 = %d, "
4235 "log2_min_pcm_luma_coding_block_size_minus3 = %d, "
4236 "log2_max_pcm_luma_coding_block_size_minus3 = %d, "
4237 "pcm_loop_filter_disabled_flag = %d, "
4238 "temporal_mvp_enabled_flag = %d, "
4239 "collocated_from_l0_flag = %d, "
4240 "collocated_ref_idx = %d, "
4241 "strong_intra_smoothing_enabled_flag = %d, "
4242 "dependent_slice_segment_flag = %d, "
4243 "sign_data_hiding_enabled_flag = %d, "
4244 "constrained_intra_pred_flag = %d, "
4245 "transform_skip_enabled_flag = %d, "
4246 "cu_qp_delta_enabled_flag = %d, "
4247 "diff_cu_qp_delta_depth = %d, "
4248 "weighted_pred_flag = %d, "
4249 "weighted_bipred_flag = %d, "
4250 "transquant_bypass_enabled_flag = %d",
4251 self->features.separate_colour_plane_flag,
4252 self->features.colour_plane_id,
4253 self->features.scaling_list_enabled_flag,
4254 self->features.scaling_list_data_present_flag,
4255 self->features.amp_enabled_flag,
4256 self->features.sample_adaptive_offset_enabled_flag,
4257 self->features.slice_sao_luma_flag,
4258 self->features.slice_sao_chroma_flag,
4259 self->features.pcm_enabled_flag,
4260 self->features.pcm_sample_bit_depth_luma_minus1,
4261 self->features.pcm_sample_bit_depth_chroma_minus1,
4262 self->features.log2_min_pcm_luma_coding_block_size_minus3,
4263 self->features.log2_max_pcm_luma_coding_block_size_minus3,
4264 self->features.pcm_loop_filter_disabled_flag,
4265 self->features.temporal_mvp_enabled_flag,
4266 self->features.collocated_from_l0_flag,
4267 self->features.collocated_ref_idx,
4268 self->features.strong_intra_smoothing_enabled_flag,
4269 self->features.dependent_slice_segment_flag,
4270 self->features.sign_data_hiding_enabled_flag,
4271 self->features.constrained_intra_pred_flag,
4272 self->features.transform_skip_enabled_flag,
4273 self->features.cu_qp_delta_enabled_flag,
4274 self->features.diff_cu_qp_delta_depth,
4275 self->features.weighted_pred_flag,
4276 self->features.weighted_bipred_flag,
4277 self->features.transquant_bypass_enabled_flag);
4279 /* Ensure trellis. */
4280 if (self->features.use_trellis &&
4281 !gst_va_encoder_has_trellis (base->encoder, base->profile,
4282 GST_VA_BASE_ENC_ENTRYPOINT (base))) {
4283 GST_INFO_OBJECT (self, "The trellis is not supported");
4284 self->features.use_trellis = FALSE;
4287 if (self->prop.use_trellis != self->features.use_trellis) {
4288 self->prop.use_trellis = self->features.use_trellis;
4289 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TRELLIS]);
4293 /* We need to decide the profile and entrypoint before call this.
4294 It applies the optimized block size(coding and tranform) provided
4295 by the va driver. */
4297 _h265_set_coding_block_size (GstVaH265Enc * self)
4299 #if VA_CHECK_VERSION(1, 13, 0)
4300 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
4302 VAConfigAttribValEncHEVCBlockSizes block_size;
4304 VAConfigAttrib attrib = {.type = VAConfigAttribEncHEVCBlockSizes };
4306 status = vaGetConfigAttributes (gst_va_display_get_va_dpy (base->display),
4307 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base), &attrib, 1);
4308 if (status != VA_STATUS_SUCCESS) {
4309 GST_INFO_OBJECT (self, "Failed to query coding block size: %s",
4310 vaErrorStr (status));
4311 goto default_setting;
4314 if (attrib.value == VA_ATTRIB_NOT_SUPPORTED) {
4315 GST_INFO_OBJECT (self, "Driver does not support query"
4316 " coding block size");
4317 goto default_setting;
4320 block_size.value = attrib.value;
4322 /* We always choose the biggest coding block size and the biggest
4323 hierarchy depth to achieve the best compression result.
4324 TODO: May choose smaller value when fast encoding is needed. */
4326 if (block_size.bits.log2_min_luma_coding_block_size_minus3 >
4327 block_size.bits.log2_max_coding_tree_block_size_minus3) {
4328 GST_WARNING_OBJECT (self, "Invalid log2_min_luma_coding_block_size_minus3:"
4329 " %d, bigger than log2_max_coding_tree_block_size_minus3: %d",
4330 block_size.bits.log2_min_luma_coding_block_size_minus3,
4331 block_size.bits.log2_max_coding_tree_block_size_minus3);
4332 goto default_setting;
4334 if (block_size.bits.log2_min_luma_coding_block_size_minus3 >
4335 block_size.bits.log2_min_coding_tree_block_size_minus3) {
4336 GST_WARNING_OBJECT (self, "Invalid log2_min_luma_coding_block_size_minus3:"
4337 " %d, bigger than log2_min_coding_tree_block_size_minus3: %d",
4338 block_size.bits.log2_min_luma_coding_block_size_minus3,
4339 block_size.bits.log2_min_coding_tree_block_size_minus3);
4340 block_size.bits.log2_min_coding_tree_block_size_minus3 =
4341 block_size.bits.log2_min_luma_coding_block_size_minus3;
4345 1 << (block_size.bits.log2_max_coding_tree_block_size_minus3 + 3);
4346 self->min_coding_block_size =
4347 1 << (block_size.bits.log2_min_luma_coding_block_size_minus3 + 3);
4348 self->features.log2_min_luma_coding_block_size_minus3 =
4349 block_size.bits.log2_min_luma_coding_block_size_minus3;
4350 self->features.log2_diff_max_min_luma_coding_block_size =
4351 block_size.bits.log2_max_coding_tree_block_size_minus3 -
4352 block_size.bits.log2_min_luma_coding_block_size_minus3;
4354 if (block_size.bits.log2_min_luma_transform_block_size_minus2 >
4355 block_size.bits.log2_max_luma_transform_block_size_minus2) {
4356 GST_WARNING_OBJECT (self, "Invalid"
4357 " log2_min_luma_transform_block_size_minus2: %d, bigger"
4358 " than log2_max_luma_transform_block_size_minus2: %d",
4359 block_size.bits.log2_min_luma_transform_block_size_minus2,
4360 block_size.bits.log2_max_luma_transform_block_size_minus2);
4361 goto default_setting;
4363 self->features.log2_min_transform_block_size_minus2 =
4364 block_size.bits.log2_min_luma_transform_block_size_minus2;
4365 self->features.log2_diff_max_min_transform_block_size =
4366 block_size.bits.log2_max_luma_transform_block_size_minus2 -
4367 block_size.bits.log2_min_luma_transform_block_size_minus2;
4369 self->features.max_transform_hierarchy_depth_inter =
4370 block_size.bits.max_max_transform_hierarchy_depth_inter;
4371 self->features.max_transform_hierarchy_depth_intra =
4372 block_size.bits.max_max_transform_hierarchy_depth_intra;
4374 /* For PCM setting later. */
4375 self->features.log2_min_pcm_luma_coding_block_size_minus3 =
4376 block_size.bits.log2_min_pcm_coding_block_size_minus3;
4377 self->features.log2_max_pcm_luma_coding_block_size_minus3 =
4378 block_size.bits.log2_max_pcm_coding_block_size_minus3;
4380 if (self->features.log2_max_pcm_luma_coding_block_size_minus3 -
4381 self->features.log2_min_pcm_luma_coding_block_size_minus3 >
4382 self->features.log2_diff_max_min_luma_coding_block_size) {
4383 GST_WARNING_OBJECT (self, "Invalid"
4384 " log2_diff_max_min_pcm_luma_coding_block_size: %d",
4385 self->features.log2_max_pcm_luma_coding_block_size_minus3
4386 - self->features.log2_min_pcm_luma_coding_block_size_minus3);
4387 self->features.log2_max_pcm_luma_coding_block_size_minus3 = 0;
4388 self->features.log2_min_pcm_luma_coding_block_size_minus3 = 0;
4396 GST_DEBUG_OBJECT (self, "Apply default setting for coding block");
4398 /* choose some conservative value */
4399 self->ctu_size = 32;
4400 self->min_coding_block_size = 8;
4401 self->features.log2_min_luma_coding_block_size_minus3 = 0;
4402 self->features.log2_diff_max_min_luma_coding_block_size = 2;
4404 self->features.log2_min_transform_block_size_minus2 = 0;
4405 self->features.log2_diff_max_min_transform_block_size = 3;
4406 self->features.max_transform_hierarchy_depth_inter = 2;
4407 self->features.max_transform_hierarchy_depth_intra = 2;
4408 self->features.pcm_sample_bit_depth_luma_minus1 = 0;
4409 self->features.pcm_sample_bit_depth_chroma_minus1 = 0;
4410 /* Default PCM is disabled. */
4411 self->features.log2_min_pcm_luma_coding_block_size_minus3 = 0;
4412 self->features.log2_max_pcm_luma_coding_block_size_minus3 = 0;
4414 #if VA_CHECK_VERSION(1, 13, 0)
4417 GST_DEBUG_OBJECT (self, "Set coding block size to: "
4418 "log2_min_luma_coding_block_size_minus3: %d, "
4419 "log2_diff_max_min_luma_coding_block_size: %d, "
4420 "log2_min_transform_block_size_minus2: %d, "
4421 "log2_diff_max_min_transform_block_size: %d, "
4422 "max_transform_hierarchy_depth_inter: %d, "
4423 "max_transform_hierarchy_depth_intra: %d",
4424 self->features.log2_min_luma_coding_block_size_minus3,
4425 self->features.log2_diff_max_min_luma_coding_block_size,
4426 self->features.log2_min_transform_block_size_minus2,
4427 self->features.log2_diff_max_min_transform_block_size,
4428 self->features.max_transform_hierarchy_depth_inter,
4429 self->features.max_transform_hierarchy_depth_intra);
4433 gst_va_h265_enc_reconfig (GstVaBaseEnc * base)
4435 GstVideoEncoder *venc = GST_VIDEO_ENCODER (base);
4436 GstVaH265Enc *self = GST_VA_H265_ENC (base);
4437 GstCaps *out_caps, *reconf_caps = NULL;;
4438 GstVideoCodecState *output_state = NULL;
4439 GstVideoFormat format, reconf_format = GST_VIDEO_FORMAT_UNKNOWN;
4440 VAProfile profile = VAProfileNone;
4441 gboolean do_renegotiation = TRUE, do_reopen, need_negotiation;
4442 guint max_ref_frames, max_surfaces = 0, rt_format = 0, codedbuf_size;
4445 width = GST_VIDEO_INFO_WIDTH (&base->input_state->info);
4446 height = GST_VIDEO_INFO_HEIGHT (&base->input_state->info);
4447 format = GST_VIDEO_INFO_FORMAT (&base->input_state->info);
4448 codedbuf_size = base->codedbuf_size;
4451 !gst_va_encoder_get_reconstruct_pool_config (base->encoder, &reconf_caps,
4453 if (!need_negotiation && reconf_caps) {
4455 if (!gst_video_info_from_caps (&vi, reconf_caps))
4457 reconf_format = GST_VIDEO_INFO_FORMAT (&vi);
4460 if (!_h265_decide_profile (self, &profile, &rt_format))
4464 do_reopen = !(base->profile == profile && base->rt_format == rt_format
4465 && format == reconf_format && width == base->width
4466 && height == base->height && self->prop.rc_ctrl == self->rc.rc_ctrl_mode);
4468 if (do_reopen && gst_va_encoder_is_open (base->encoder))
4469 gst_va_encoder_close (base->encoder);
4471 gst_va_base_enc_reset_state (base);
4473 base->profile = profile;
4474 base->rt_format = rt_format;
4475 base->width = width;
4476 base->height = height;
4478 self->luma_width = GST_ROUND_UP_16 (base->width);
4479 self->luma_height = GST_ROUND_UP_16 (base->height);
4481 /* Frame Cropping */
4482 if ((base->width & 15) || (base->height & 15)) {
4483 /* 6.1, Table 6-1 */
4484 static const guint SubWidthC[] = { 1, 2, 2, 1 };
4485 static const guint SubHeightC[] = { 1, 2, 1, 1 };
4486 guint index = _get_chroma_format_idc (gst_va_chroma_from_video_format
4487 (GST_VIDEO_INFO_FORMAT (&base->input_state->info)));
4489 self->conformance_window_flag = 1;
4490 self->conf_win_left_offset = 0;
4491 self->conf_win_right_offset =
4492 (self->luma_width - base->width) / SubWidthC[index];
4493 self->conf_win_top_offset = 0;
4494 self->conf_win_bottom_offset =
4495 (self->luma_height - base->height) / SubHeightC[index];
4498 _h265_set_coding_block_size (self);
4500 self->ctu_width = (self->luma_width + self->ctu_size - 1) / self->ctu_size;
4501 self->ctu_height = (self->luma_height + self->ctu_size - 1) / self->ctu_size;
4502 if (self->ctu_width == 0 || self->ctu_height == 0)
4505 self->bits_depth_luma_minus8 =
4506 GST_VIDEO_FORMAT_INFO_DEPTH (base->input_state->info.finfo, 0);
4507 self->bits_depth_luma_minus8 -= 8;
4509 if (GST_VIDEO_FORMAT_INFO_N_COMPONENTS (base->input_state->info.finfo)) {
4510 self->bits_depth_chroma_minus8 =
4511 GST_VIDEO_FORMAT_INFO_DEPTH (base->input_state->info.finfo, 1);
4512 if (self->bits_depth_chroma_minus8 <
4513 GST_VIDEO_FORMAT_INFO_DEPTH (base->input_state->info.finfo, 2))
4514 self->bits_depth_chroma_minus8 =
4515 GST_VIDEO_FORMAT_INFO_DEPTH (base->input_state->info.finfo, 2);
4517 self->bits_depth_chroma_minus8 -= 8;
4519 self->bits_depth_chroma_minus8 = 0;
4522 /* Frame rate is needed for rate control and PTS setting. */
4523 if (GST_VIDEO_INFO_FPS_N (&base->input_state->info) == 0
4524 || GST_VIDEO_INFO_FPS_D (&base->input_state->info) == 0) {
4525 GST_INFO_OBJECT (self, "Unknown framerate, just set to 30 fps");
4526 GST_VIDEO_INFO_FPS_N (&base->input_state->info) = 30;
4527 GST_VIDEO_INFO_FPS_D (&base->input_state->info) = 1;
4529 base->frame_duration = gst_util_uint64_scale (GST_SECOND,
4530 GST_VIDEO_INFO_FPS_D (&base->input_state->info),
4531 GST_VIDEO_INFO_FPS_N (&base->input_state->info));
4533 GST_DEBUG_OBJECT (self, "resolution:%dx%d, CTU size: %dx%d,"
4534 " frame duration is %" GST_TIME_FORMAT,
4535 base->width, base->height, self->ctu_width, self->ctu_height,
4536 GST_TIME_ARGS (base->frame_duration));
4538 if (!_h265_ensure_rate_control (self))
4541 if (!_h265_calculate_tier_level (self))
4544 if (!_h265_generate_gop_structure (self))
4547 _h265_setup_encoding_features (self);
4549 _h265_calculate_coded_size (self);
4551 if (!_h265_setup_slice_and_tile_partition (self))
4554 if (!_h265_init_packed_headers (self))
4557 self->aud = self->aud && self->packed_headers & VA_ENC_PACKED_HEADER_RAW_DATA;
4558 update_property_bool (base, &self->prop.aud, self->aud, PROP_AUD);
4560 max_ref_frames = self->gop.num_ref_frames + 3 /* scratch frames */ ;
4562 /* second check after calculations */
4564 !(max_ref_frames == max_surfaces && codedbuf_size == base->codedbuf_size);
4565 if (do_reopen && gst_va_encoder_is_open (base->encoder))
4566 gst_va_encoder_close (base->encoder);
4568 if (!gst_va_encoder_is_open (base->encoder)
4569 && !gst_va_encoder_open (base->encoder, base->profile,
4570 format, base->rt_format, self->luma_width, self->luma_height,
4571 base->codedbuf_size, max_ref_frames, self->rc.rc_ctrl_mode,
4572 self->packed_headers)) {
4573 GST_ERROR_OBJECT (self, "Failed to open the VA encoder.");
4578 gst_va_base_enc_add_codec_tag (base, "H265");
4580 out_caps = gst_va_profile_caps (base->profile);
4581 g_assert (out_caps);
4582 out_caps = gst_caps_fixate (out_caps);
4584 if (self->level_str)
4585 gst_caps_set_simple (out_caps, "level", G_TYPE_STRING, self->level_str,
4588 gst_caps_set_simple (out_caps, "width", G_TYPE_INT, base->width,
4589 "height", G_TYPE_INT, base->height, "alignment", G_TYPE_STRING, "au",
4590 "stream-format", G_TYPE_STRING, "byte-stream", NULL);
4592 if (!need_negotiation) {
4593 output_state = gst_video_encoder_get_output_state (venc);
4594 do_renegotiation = TRUE;
4597 do_renegotiation = !gst_caps_is_subset (output_state->caps, out_caps);
4598 gst_video_codec_state_unref (output_state);
4601 if (!do_renegotiation) {
4602 gst_caps_unref (out_caps);
4607 GST_DEBUG_OBJECT (self, "output caps is %" GST_PTR_FORMAT, out_caps);
4610 gst_video_encoder_set_output_state (venc, out_caps, base->input_state);
4611 gst_video_codec_state_unref (output_state);
4613 if (!gst_video_encoder_negotiate (venc)) {
4614 GST_ERROR_OBJECT (self, "Failed to negotiate with the downstream");
4622 gst_va_h265_enc_flush (GstVideoEncoder * venc)
4624 GstVaH265Enc *self = GST_VA_H265_ENC (venc);
4626 /* begin from an IDR after flush. */
4627 self->gop.cur_frame_index = 0;
4629 return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (venc);
4633 gst_va_h265_enc_new_frame (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
4635 GstVaH265EncFrame *frame_in;
4637 frame_in = gst_va_h265_enc_frame_new ();
4638 frame_in->total_frame_count = base->input_frame_count++;
4639 gst_video_codec_frame_set_user_data (frame, frame_in,
4640 gst_va_h265_enc_frame_free);
4646 gst_va_h265_enc_prepare_output (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
4648 GstVaH265Enc *self = GST_VA_H265_ENC (base);
4649 GstVaH265EncFrame *frame_enc;
4651 frame_enc = _enc_frame (frame);
4654 base->start_pts + base->frame_duration * frame_enc->total_frame_count;
4655 /* The PTS should always be later than the DTS. */
4656 frame->dts = base->start_pts + base->frame_duration *
4657 ((gint64) base->output_frame_count -
4658 (gint64) self->gop.num_reorder_frames);
4659 base->output_frame_count++;
4660 frame->duration = base->frame_duration;
4664 static const gchar *sink_caps_str =
4665 GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_VA,
4667 GST_VIDEO_CAPS_MAKE ("{ NV12 }");
4670 static const gchar *src_caps_str = "video/x-h265";
4673 _register_debug_category (gpointer data)
4675 GST_DEBUG_CATEGORY_INIT (gst_va_h265enc_debug, "vah265enc", 0,
4682 gst_va_h265_enc_init (GTypeInstance * instance, gpointer g_class)
4684 GstVaH265Enc *self = GST_VA_H265_ENC (instance);
4686 /* default values */
4687 self->prop.key_int_max = 0;
4688 self->prop.num_bframes = 0;
4689 self->prop.num_iframes = 0;
4690 self->prop.num_ref_frames = 3;
4691 self->prop.b_pyramid = FALSE;
4692 self->prop.num_slices = 1;
4693 self->prop.min_qp = 1;
4694 self->prop.max_qp = 51;
4695 self->prop.qp_i = 26;
4696 self->prop.qp_p = 26;
4697 self->prop.qp_b = 26;
4698 self->prop.use_trellis = FALSE;
4699 self->prop.aud = FALSE;
4700 self->prop.mbbrc = 0;
4701 self->prop.bitrate = 0;
4702 self->prop.target_percentage = 66;
4703 self->prop.target_usage = 4;
4704 self->prop.cpb_size = 0;
4705 if (properties[PROP_RATE_CONTROL]) {
4706 self->prop.rc_ctrl =
4707 G_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL])->default_value;
4709 self->prop.rc_ctrl = VA_RC_NONE;
4714 gst_va_h265_enc_set_property (GObject * object, guint prop_id,
4715 const GValue * value, GParamSpec * pspec)
4717 GstVaH265Enc *const self = GST_VA_H265_ENC (object);
4718 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
4719 gboolean already_effect = FALSE;
4721 GST_OBJECT_LOCK (self);
4724 case PROP_KEY_INT_MAX:
4725 self->prop.key_int_max = g_value_get_uint (value);
4728 self->prop.num_bframes = g_value_get_uint (value);
4731 self->prop.num_iframes = g_value_get_uint (value);
4733 case PROP_NUM_REF_FRAMES:
4734 self->prop.num_ref_frames = g_value_get_uint (value);
4736 case PROP_B_PYRAMID:
4737 self->prop.b_pyramid = g_value_get_boolean (value);
4739 case PROP_NUM_SLICES:
4740 self->prop.num_slices = g_value_get_uint (value);
4743 self->prop.min_qp = g_value_get_uint (value);
4746 self->prop.max_qp = g_value_get_uint (value);
4749 self->prop.qp_i = g_value_get_uint (value);
4750 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4751 already_effect = TRUE;
4754 self->prop.qp_p = g_value_get_uint (value);
4755 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4756 already_effect = TRUE;
4759 self->prop.qp_b = g_value_get_uint (value);
4760 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4761 already_effect = TRUE;
4764 self->prop.use_trellis = g_value_get_boolean (value);
4767 self->prop.aud = g_value_get_boolean (value);
4770 /* Macroblock-level rate control.
4773 * 2: always disable,
4774 * other: reserved. */
4775 switch (g_value_get_enum (value)) {
4776 case GST_VA_FEATURE_DISABLED:
4777 self->prop.mbbrc = 2;
4779 case GST_VA_FEATURE_ENABLED:
4780 self->prop.mbbrc = 1;
4782 case GST_VA_FEATURE_AUTO:
4783 self->prop.mbbrc = 0;
4789 self->prop.bitrate = g_value_get_uint (value);
4790 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4791 already_effect = TRUE;
4793 case PROP_TARGET_PERCENTAGE:
4794 self->prop.target_percentage = g_value_get_uint (value);
4795 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4796 already_effect = TRUE;
4798 case PROP_TARGET_USAGE:
4799 self->prop.target_usage = g_value_get_uint (value);
4800 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4801 already_effect = TRUE;
4803 case PROP_NUM_TILE_COLS:
4804 self->prop.num_tile_cols = g_value_get_uint (value);
4806 case PROP_NUM_TILE_ROWS:
4807 self->prop.num_tile_rows = g_value_get_uint (value);
4809 case PROP_RATE_CONTROL:
4810 self->prop.rc_ctrl = g_value_get_enum (value);
4811 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4812 already_effect = TRUE;
4815 self->prop.cpb_size = g_value_get_uint (value);
4818 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4821 GST_OBJECT_UNLOCK (self);
4823 #ifndef GST_DISABLE_GST_DEBUG
4824 if (!already_effect &&
4825 base->encoder && gst_va_encoder_is_open (base->encoder)) {
4826 GST_WARNING_OBJECT (self, "Property `%s` change ignored while processing.",
4833 gst_va_h265_enc_get_property (GObject * object, guint prop_id,
4834 GValue * value, GParamSpec * pspec)
4836 GstVaH265Enc *const self = GST_VA_H265_ENC (object);
4838 GST_OBJECT_LOCK (self);
4841 case PROP_KEY_INT_MAX:
4842 g_value_set_uint (value, self->prop.key_int_max);
4845 g_value_set_uint (value, self->prop.num_bframes);
4848 g_value_set_uint (value, self->prop.num_iframes);
4850 case PROP_NUM_REF_FRAMES:
4851 g_value_set_uint (value, self->prop.num_ref_frames);
4853 case PROP_B_PYRAMID:
4854 g_value_set_boolean (value, self->prop.b_pyramid);
4856 case PROP_NUM_SLICES:
4857 g_value_set_uint (value, self->prop.num_slices);
4860 g_value_set_uint (value, self->prop.min_qp);
4863 g_value_set_uint (value, self->prop.max_qp);
4866 g_value_set_uint (value, self->prop.qp_i);
4869 g_value_set_uint (value, self->prop.qp_p);
4872 g_value_set_uint (value, self->prop.qp_b);
4875 g_value_set_boolean (value, self->prop.use_trellis);
4878 g_value_set_boolean (value, self->prop.aud);
4881 g_value_set_enum (value, self->prop.mbbrc);
4884 g_value_set_uint (value, self->prop.bitrate);
4886 case PROP_TARGET_PERCENTAGE:
4887 g_value_set_uint (value, self->prop.target_percentage);
4889 case PROP_TARGET_USAGE:
4890 g_value_set_uint (value, self->prop.target_usage);
4892 case PROP_NUM_TILE_COLS:
4893 g_value_set_uint (value, self->prop.num_tile_cols);
4895 case PROP_NUM_TILE_ROWS:
4896 g_value_set_uint (value, self->prop.num_tile_rows);
4898 case PROP_RATE_CONTROL:
4899 g_value_set_enum (value, self->prop.rc_ctrl);
4902 g_value_set_uint (value, self->prop.cpb_size);
4905 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4908 GST_OBJECT_UNLOCK (self);
4912 gst_va_h265_enc_class_init (gpointer g_klass, gpointer class_data)
4914 GstCaps *src_doc_caps, *sink_doc_caps;
4915 GstPadTemplate *sink_pad_templ, *src_pad_templ;
4916 GObjectClass *object_class = G_OBJECT_CLASS (g_klass);
4917 GstElementClass *element_class = GST_ELEMENT_CLASS (g_klass);
4918 GstVideoEncoderClass *venc_class = GST_VIDEO_ENCODER_CLASS (g_klass);
4919 GstVaBaseEncClass *va_enc_class = GST_VA_BASE_ENC_CLASS (g_klass);
4920 GstVaH265EncClass *vah265enc_class = GST_VA_H265_ENC_CLASS (g_klass);
4921 GstVaDisplay *display;
4922 GstVaEncoder *encoder;
4923 struct CData *cdata = class_data;
4925 const gchar *name, *desc;
4926 gint n_props = N_PROPERTIES;
4927 GParamFlags param_flags =
4928 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT;
4930 if (cdata->entrypoint == VAEntrypointEncSlice) {
4931 desc = "VA-API based H.265 video encoder";
4932 name = "VA-API H.265 Encoder";
4934 desc = "VA-API based H.265 low power video encoder";
4935 name = "VA-API H.265 Low Power Encoder";
4938 if (cdata->description)
4939 long_name = g_strdup_printf ("%s in %s", name, cdata->description);
4941 long_name = g_strdup (name);
4943 gst_element_class_set_metadata (element_class, long_name,
4944 "Codec/Encoder/Video/Hardware", desc, "He Junyan <junyan.he@intel.com>");
4946 sink_doc_caps = gst_caps_from_string (sink_caps_str);
4947 src_doc_caps = gst_caps_from_string (src_caps_str);
4949 parent_class = g_type_class_peek_parent (g_klass);
4951 va_enc_class->codec = HEVC;
4952 va_enc_class->entrypoint = cdata->entrypoint;
4953 va_enc_class->render_device_path = g_strdup (cdata->render_device_path);
4955 sink_pad_templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
4957 gst_element_class_add_pad_template (element_class, sink_pad_templ);
4959 gst_pad_template_set_documentation_caps (sink_pad_templ, sink_doc_caps);
4960 gst_caps_unref (sink_doc_caps);
4962 src_pad_templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
4964 gst_element_class_add_pad_template (element_class, src_pad_templ);
4966 gst_pad_template_set_documentation_caps (src_pad_templ, src_doc_caps);
4967 gst_caps_unref (src_doc_caps);
4969 object_class->set_property = gst_va_h265_enc_set_property;
4970 object_class->get_property = gst_va_h265_enc_get_property;
4972 venc_class->flush = GST_DEBUG_FUNCPTR (gst_va_h265_enc_flush);
4974 va_enc_class->reset_state = GST_DEBUG_FUNCPTR (gst_va_h265_enc_reset_state);
4975 va_enc_class->reconfig = GST_DEBUG_FUNCPTR (gst_va_h265_enc_reconfig);
4976 va_enc_class->new_frame = GST_DEBUG_FUNCPTR (gst_va_h265_enc_new_frame);
4977 va_enc_class->reorder_frame =
4978 GST_DEBUG_FUNCPTR (gst_va_h265_enc_reorder_frame);
4979 va_enc_class->encode_frame = GST_DEBUG_FUNCPTR (gst_va_h265_enc_encode_frame);
4980 va_enc_class->prepare_output =
4981 GST_DEBUG_FUNCPTR (gst_va_h265_enc_prepare_output);
4985 gst_va_display_drm_new_from_path (va_enc_class->render_device_path);
4986 encoder = gst_va_encoder_new (display, va_enc_class->codec,
4987 va_enc_class->entrypoint);
4988 if (gst_va_encoder_get_rate_control_enum (encoder,
4989 vah265enc_class->rate_control)) {
4990 g_snprintf (vah265enc_class->rate_control_type_name,
4991 G_N_ELEMENTS (vah265enc_class->rate_control_type_name) - 1,
4992 "GstVaEncoderRateControl_%" GST_FOURCC_FORMAT "%s_%s",
4993 GST_FOURCC_ARGS (va_enc_class->codec),
4994 (va_enc_class->entrypoint == VAEntrypointEncSliceLP) ? "_LP" : "",
4995 g_path_get_basename (va_enc_class->render_device_path));
4996 vah265enc_class->rate_control_type =
4997 g_enum_register_static (vah265enc_class->rate_control_type_name,
4998 vah265enc_class->rate_control);
4999 gst_type_mark_as_plugin_api (vah265enc_class->rate_control_type, 0);
5001 gst_object_unref (encoder);
5002 gst_object_unref (display);
5006 g_free (cdata->description);
5007 g_free (cdata->render_device_path);
5008 gst_caps_unref (cdata->src_caps);
5009 gst_caps_unref (cdata->sink_caps);
5013 * GstVaH265Enc:key-int-max:
5015 * The maximal distance between two keyframes.
5017 properties[PROP_KEY_INT_MAX] = g_param_spec_uint ("key-int-max",
5018 "Key frame maximal interval",
5019 "The maximal distance between two keyframes. It decides the size of GOP"
5020 " (0: auto-calculate)", 0, MAX_GOP_SIZE, 0, param_flags);
5023 * GstVaH265Enc:b-frames:
5025 * Number of B-frames between two reference frames.
5027 properties[PROP_BFRAMES] = g_param_spec_uint ("b-frames", "B Frames",
5028 "Number of B frames between I and P reference frames", 0, 31, 0,
5032 * GstVaH265Enc:i-frames:
5034 * Force the number of i-frames insertion within one GOP.
5036 properties[PROP_IFRAMES] = g_param_spec_uint ("i-frames", "I Frames",
5037 "Force the number of I frames insertion within one GOP, not including the "
5038 "first IDR frame", 0, 1023, 0, param_flags);
5040 /* The VA only define 15 refs */
5042 * GstVaH265Enc:ref-frames:
5044 * The number of reference frames.
5046 properties[PROP_NUM_REF_FRAMES] = g_param_spec_uint ("ref-frames",
5047 "Number of Reference Frames",
5048 "Number of reference frames, including both the forward and the backward",
5049 0, 15, 3, param_flags);
5052 * GstVaH265Enc:b-pyramid:
5054 * Enable the b-pyramid reference structure in GOP.
5056 properties[PROP_B_PYRAMID] = g_param_spec_boolean ("b-pyramid", "b pyramid",
5057 "Enable the b-pyramid reference structure in the GOP", FALSE,
5061 * GstVaH265Enc:num-slices:
5063 * The number of slices per frame.
5065 properties[PROP_NUM_SLICES] = g_param_spec_uint ("num-slices",
5066 "Number of Slices", "Number of slices per frame", 1, 200, 1, param_flags);
5069 * GstVaH265Enc:max-qp:
5071 * The maximum quantizer value.
5073 properties[PROP_MAX_QP] = g_param_spec_uint ("max-qp", "Maximum QP",
5074 "Maximum quantizer value for each frame", 0, 51, 51, param_flags);
5077 * GstVaH265Enc:min-qp:
5079 * The minimum quantizer value.
5081 properties[PROP_MIN_QP] = g_param_spec_uint ("min-qp", "Minimum QP",
5082 "Minimum quantizer value for each frame", 0, 51, 1, param_flags);
5087 * The quantizer value for I frame. In CQP mode, it specifies the QP of
5088 * I frame, in other mode, it specifies the init QP of all frames.
5090 properties[PROP_QP_I] = g_param_spec_uint ("qpi", "I Frame QP",
5091 "The quantizer value for I frame. In CQP mode, it specifies the QP of I "
5092 "frame, in other mode, it specifies the init QP of all frames", 0, 51, 26,
5093 param_flags | GST_PARAM_MUTABLE_PLAYING);
5098 * The quantizer value for P frame. This is available only in CQP mode.
5100 properties[PROP_QP_P] = g_param_spec_uint ("qpp",
5101 "The quantizer value for P frame",
5102 "The quantizer value for P frame. This is available only in CQP mode",
5103 0, 51, 26, param_flags | GST_PARAM_MUTABLE_PLAYING);
5108 * The quantizer value for B frame. This is available only in CQP mode.
5110 properties[PROP_QP_B] = g_param_spec_uint ("qpb",
5111 "The quantizer value for B frame",
5112 "The quantizer value for B frame. This is available only in CQP mode",
5113 0, 51, 26, param_flags | GST_PARAM_MUTABLE_PLAYING);
5116 * GstVaH265Enc:trellis:
5118 * It enable the trellis quantization method.
5119 * Trellis is an improved quantization algorithm.
5121 properties[PROP_TRELLIS] = g_param_spec_boolean ("trellis", "Enable trellis",
5122 "Enable the trellis quantization method", FALSE, param_flags);
5127 * Insert the AU (Access Unit) delimeter for each frame.
5129 properties[PROP_AUD] = g_param_spec_boolean ("aud", "Insert AUD",
5130 "Insert AU (Access Unit) delimeter for each frame", FALSE, param_flags);
5133 * GstVaH265Enc:mbbrc:
5135 * Macroblock level bitrate control.
5136 * This is not compatible with Constant QP rate control.
5138 properties[PROP_MBBRC] = g_param_spec_enum ("mbbrc",
5139 "Macroblock level Bitrate Control",
5140 "Macroblock level Bitrate Control. It is not compatible with CQP",
5141 GST_TYPE_VA_FEATURE, GST_VA_FEATURE_AUTO, param_flags);
5144 * GstVaH265Enc:bitrate:
5146 * The desired target bitrate, expressed in kbps.
5147 * This is not available in CQP mode.
5149 * CBR: This applies equally to the minimum, maximum and target bitrate.
5150 * VBR: This applies to the target bitrate. The driver will use the
5151 * "target-percentage" together to calculate the minimum and maximum bitrate.
5152 * VCM: This applies to the target bitrate. The minimum and maximum bitrate
5155 properties[PROP_BITRATE] = g_param_spec_uint ("bitrate", "Bitrate (kbps)",
5156 "The desired bitrate expressed in kbps (0: auto-calculate)",
5157 0, 2000 * 1024, 0, param_flags | GST_PARAM_MUTABLE_PLAYING);
5160 * GstVaH265Enc:target-percentage:
5162 * The target percentage of the max bitrate, and expressed in uint,
5163 * equal to "target percentage"*100.
5164 * "target percentage" = "target bitrate" * 100 / "max bitrate"
5165 * This is available only when rate-control is VBR.
5166 * The driver uses it to calculate the minimum and maximum bitrate.
5168 properties[PROP_TARGET_PERCENTAGE] = g_param_spec_uint ("target-percentage",
5169 "target bitrate percentage",
5170 "The percentage for 'target bitrate'/'maximum bitrate' (Only in VBR)",
5171 50, 100, 66, param_flags | GST_PARAM_MUTABLE_PLAYING);
5174 * GstVaH265Enc:target-usage:
5176 * The target usage of the encoder. It controls and balances the encoding
5177 * speed and the encoding quality. The lower value has better quality but
5178 * slower speed, the higher value has faster speed but lower quality.
5180 properties[PROP_TARGET_USAGE] = g_param_spec_uint ("target-usage",
5182 "The target usage to control and balance the encoding speed/quality",
5183 1, 7, 4, param_flags | GST_PARAM_MUTABLE_PLAYING);
5186 * GstVaH265Enc:cpb-size:
5188 * The desired max CPB size in Kb (0: auto-calculate).
5190 properties[PROP_CPB_SIZE] = g_param_spec_uint ("cpb-size",
5191 "max CPB size in Kb",
5192 "The desired max CPB size in Kb (0: auto-calculate)", 0, 2000 * 1024, 0,
5196 * GstVaH265Enc:num-tile-cols:
5198 * The number of tile columns when tile encoding is enabled.
5200 properties[PROP_NUM_TILE_COLS] = g_param_spec_uint ("num-tile-cols",
5201 "number of tile columns", "The number of columns for tile encoding",
5202 1, MAX_COL_TILES, 1, param_flags);
5205 * GstVaH265Enc:num-tile-rows:
5207 * The number of tile rows when tile encoding is enabled.
5209 properties[PROP_NUM_TILE_ROWS] = g_param_spec_uint ("num-tile-rows",
5210 "number of tile rows", "The number of rows for tile encoding",
5211 1, MAX_ROW_TILES, 1, param_flags);
5213 if (vah265enc_class->rate_control_type > 0) {
5214 properties[PROP_RATE_CONTROL] = g_param_spec_enum ("rate-control",
5215 "rate control mode", "The desired rate control mode for the encoder",
5216 vah265enc_class->rate_control_type,
5217 vah265enc_class->rate_control[0].value,
5218 GST_PARAM_CONDITIONALLY_AVAILABLE | GST_PARAM_MUTABLE_PLAYING
5222 properties[PROP_RATE_CONTROL] = NULL;
5225 g_object_class_install_properties (object_class, n_props, properties);
5229 * @GST_VA_FEATURE_DISABLED: The feature is disabled.
5230 * @GST_VA_FEATURE_ENABLED: The feature is enabled.
5231 * @GST_VA_FEATURE_AUTO: The feature is enabled automatically.
5235 gst_type_mark_as_plugin_api (GST_TYPE_VA_FEATURE, 0);
5239 _complete_src_caps (GstCaps * srccaps)
5241 GstCaps *caps = gst_caps_copy (srccaps);
5242 GValue val = G_VALUE_INIT;
5244 g_value_init (&val, G_TYPE_STRING);
5245 g_value_set_string (&val, "au");
5246 gst_caps_set_value (caps, "alignment", &val);
5247 g_value_unset (&val);
5249 g_value_init (&val, G_TYPE_STRING);
5250 g_value_set_string (&val, "byte-stream");
5251 gst_caps_set_value (caps, "stream-format", &val);
5252 g_value_unset (&val);
5258 gst_va_h265_enc_register (GstPlugin * plugin, GstVaDevice * device,
5259 GstCaps * sink_caps, GstCaps * src_caps, guint rank,
5260 VAEntrypoint entrypoint)
5262 static GOnce debug_once = G_ONCE_INIT;
5264 GTypeInfo type_info = {
5265 .class_size = sizeof (GstVaH265EncClass),
5266 .class_init = gst_va_h265_enc_class_init,
5267 .instance_size = sizeof (GstVaH265Enc),
5268 .instance_init = gst_va_h265_enc_init,
5270 struct CData *cdata;
5272 gchar *type_name, *feature_name;
5274 g_return_val_if_fail (GST_IS_PLUGIN (plugin), FALSE);
5275 g_return_val_if_fail (GST_IS_VA_DEVICE (device), FALSE);
5276 g_return_val_if_fail (GST_IS_CAPS (sink_caps), FALSE);
5277 g_return_val_if_fail (GST_IS_CAPS (src_caps), FALSE);
5278 g_return_val_if_fail (entrypoint == VAEntrypointEncSlice ||
5279 entrypoint == VAEntrypointEncSliceLP, FALSE);
5281 cdata = g_new (struct CData, 1);
5282 cdata->entrypoint = entrypoint;
5283 cdata->description = NULL;
5284 cdata->render_device_path = g_strdup (device->render_device_path);
5285 cdata->sink_caps = gst_caps_ref (sink_caps);
5286 cdata->src_caps = _complete_src_caps (src_caps);
5288 /* class data will be leaked if the element never gets instantiated */
5289 GST_MINI_OBJECT_FLAG_SET (cdata->sink_caps,
5290 GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
5291 GST_MINI_OBJECT_FLAG_SET (cdata->src_caps,
5292 GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
5294 type_info.class_data = cdata;
5296 /* The first encoder to be registered should use a constant name,
5297 * like vah265enc, for any additional encoders, we create unique
5298 * names, using inserting the render device name. */
5299 if (device->index == 0) {
5300 if (entrypoint == VAEntrypointEncSlice) {
5301 type_name = g_strdup ("GstVaH265Enc");
5302 feature_name = g_strdup ("vah265enc");
5304 type_name = g_strdup ("GstVaH265LPEnc");
5305 feature_name = g_strdup ("vah265lpenc");
5308 gchar *basename = g_path_get_basename (device->render_device_path);
5309 if (entrypoint == VAEntrypointEncSlice) {
5310 type_name = g_strdup_printf ("GstVa%sH265Enc", basename);
5311 feature_name = g_strdup_printf ("va%sh265enc", basename);
5313 type_name = g_strdup_printf ("GstVa%sH265LPEnc", basename);
5314 feature_name = g_strdup_printf ("va%sh265lpenc", basename);
5316 cdata->description = basename;
5318 /* lower rank for non-first device */
5323 g_once (&debug_once, _register_debug_category, NULL);
5324 type = g_type_register_static (GST_TYPE_VA_BASE_ENC,
5325 type_name, &type_info, 0);
5326 ret = gst_element_register (plugin, feature_name, rank, type);
5329 g_free (feature_name);