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,
96 static GParamSpec *properties[N_PROPERTIES];
98 static GstObjectClass *parent_class = NULL;
100 /* Scale factor for bitrate (HRD bit_rate_scale: min = 6) */
102 /* Scale factor for CPB size (HRD cpb_size_scale: min = 4) */
103 #define SX_CPB_SIZE 4
104 /* Maximum sizes for common headers (in bits) */
105 #define MAX_PROFILE_TIER_LEVEL_SIZE 684
106 #define MAX_VPS_HDR_SIZE 13781
107 #define MAX_SPS_HDR_SIZE 615
108 #define MAX_SHORT_TERM_REFPICSET_SIZE 55
109 #define MAX_VUI_PARAMS_SIZE 267
110 #define MAX_HRD_PARAMS_SIZE 8196
111 #define MAX_PPS_HDR_SIZE 274
112 #define MAX_SLICE_HDR_SIZE 33660
114 #define MAX_GOP_SIZE 1024
117 struct _GstVaH265EncClass
119 GstVaBaseEncClass parent_class;
121 GType rate_control_type;
122 char rate_control_type_name[64];
123 GEnumValue rate_control[16];
140 guint32 num_ref_frames;
149 gboolean use_trellis;
154 guint32 target_percentage;
155 guint32 target_usage;
160 guint32 min_coding_block_size;
161 guint32 ctu_width; /* CTU == Coding Tree Unit */
167 gboolean conformance_window_flag;
168 guint32 conf_win_left_offset;
169 guint32 conf_win_right_offset;
170 guint32 conf_win_top_offset;
171 guint32 conf_win_bottom_offset;
173 guint bits_depth_luma_minus8;
174 guint bits_depth_chroma_minus8;
177 /* Set true if high tier */
179 const gchar *level_str;
184 guint32 packed_headers;
188 guint8 log2_min_luma_coding_block_size_minus3;
189 guint8 log2_diff_max_min_luma_coding_block_size;
190 guint8 log2_min_transform_block_size_minus2;
191 guint8 log2_diff_max_min_transform_block_size;
192 guint8 max_transform_hierarchy_depth_inter;
193 guint8 max_transform_hierarchy_depth_intra;
195 gboolean separate_colour_plane_flag;
196 guint8 colour_plane_id;
198 gboolean scaling_list_enabled_flag;
199 gboolean scaling_list_data_present_flag;
201 gboolean amp_enabled_flag;
203 gboolean sample_adaptive_offset_enabled_flag;
204 gboolean slice_sao_luma_flag;
205 gboolean slice_sao_chroma_flag;
207 gboolean pcm_enabled_flag;
208 guint8 pcm_sample_bit_depth_luma_minus1;
209 guint8 pcm_sample_bit_depth_chroma_minus1;
210 guint8 log2_min_pcm_luma_coding_block_size_minus3;
211 guint8 log2_max_pcm_luma_coding_block_size_minus3;
212 guint8 pcm_loop_filter_disabled_flag;
214 gboolean temporal_mvp_enabled_flag;
215 gboolean collocated_from_l0_flag;
216 guint8 collocated_ref_idx;
218 gboolean strong_intra_smoothing_enabled_flag;
220 gboolean dependent_slice_segment_flag;
222 gboolean sign_data_hiding_enabled_flag;
224 gboolean constrained_intra_pred_flag;
226 gboolean transform_skip_enabled_flag;
228 gboolean cu_qp_delta_enabled_flag;
229 uint32_t diff_cu_qp_delta_depth;
231 gboolean weighted_pred_flag;
232 gboolean weighted_bipred_flag;
234 gboolean transquant_bypass_enabled_flag;
236 gboolean use_trellis;
241 /* frames between two IDR [idr, ...., idr) */
243 /* How may IDRs we have encoded */
244 guint32 total_idr_count;
245 /* frames between I/P and P frames [I, B, B, .., B, P) */
247 /* frames between I frames [I, B, B, .., B, P, ..., I), open GOP */
249 /* B frames between I/P and P. */
251 /* Use B pyramid structure in the GOP. */
253 /* Level 0 is the simple B not acting as ref. */
254 guint32 highest_pyramid_level;
255 /* If open GOP, I frames within a GOP. */
257 /* A map of all frames types within a GOP. */
262 guint8 pyramid_level;
263 /* Only for b pyramid */
264 gint left_ref_poc_diff;
265 gint right_ref_poc_diff;
266 } frame_types[MAX_GOP_SIZE];
268 /* Max poc within a GOP. */
269 guint32 max_pic_order_cnt;
270 guint32 log2_max_pic_order_cnt;
271 /* current index in the frames types map. */
272 guint cur_frame_index;
274 /* Total ref frames of forward and backward. */
275 guint32 num_ref_frames;
278 guint32 forward_ref_num;
279 guint32 backward_ref_num;
280 gboolean low_delay_b_mode;
282 guint num_reorder_frames;
289 guint32 rc_ctrl_mode;
296 /* macroblock bitrate control */
298 guint target_bitrate;
299 guint target_percentage;
302 guint max_bitrate_bits;
303 guint target_bitrate_bits;
304 /* length of CPB buffer */
306 /* length of CPB buffer (bits) */
307 guint cpb_length_bits;
314 struct _GstVaH265EncFrame
316 GstVaEncodePicture *picture;
317 GstH265SliceType type;
320 /* Only for b pyramid */
321 gint left_ref_poc_diff;
322 gint right_ref_poc_diff;
326 /* The total frame count we handled. */
327 guint total_frame_count;
331 * GstVaH265LevelLimits:
332 * @level_name: the level name
333 * @level_idc: the H.265 level_idc value
334 * @MaxLumaPs: the maximum luma picture size
335 * @MaxCPBTierMain: the maximum CPB size for Main tier(kbits)
336 * @MaxCPBTierHigh: the maximum CPB size for High tier(kbits)
337 * @MaxSliceSegPic: the maximum slice segments per picture
338 * @MaxTileRows: the maximum number of Tile Rows
339 * @MaxTileColumns: the maximum number of Tile Columns
340 * @MaxLumaSr: the maximum luma sample rate (samples/sec)
341 * @MaxBRTierMain: the maximum video bit rate for Main Tier(kbps)
342 * @MaxBRTierHigh: the maximum video bit rate for High Tier(kbps)
343 * @MinCr: the mimimum compression ratio
345 * The data structure that describes the limits of an H.265 level.
347 struct _GstVaH265LevelLimits
349 const gchar *level_name;
352 guint32 MaxCPBTierMain;
353 guint32 MaxCPBTierHigh;
354 guint32 MaxSliceSegPic;
356 guint32 MaxTileColumns;
358 guint32 MaxBRTierMain;
359 guint32 MaxBRTierHigh;
363 /* Table A-1 - Level limits */
365 static const GstVaH265LevelLimits _va_h265_level_limits[] = {
366 /* level idc MaxLumaPs MCPBMt MCPBHt MSlSeg MTR MTC MaxLumaSr MBRMt MBRHt MinCr */
367 { "1", 30, 36864, 350, 0, 16, 1, 1, 552960, 128, 0, 2 },
368 { "2", 60, 122880, 1500, 0, 16, 1, 1, 3686400, 1500, 0, 2 },
369 { "2.1", 63, 245760, 3000, 0, 20, 1, 1, 7372800, 3000, 0, 2 },
370 { "3", 90, 552960, 6000, 0, 30, 2, 2, 16588800, 6000, 0, 2 },
371 { "3.1", 93, 983040, 10000, 0, 40, 3, 3, 33177600, 10000, 0, 2 },
372 { "4", 120, 2228224, 12000, 30000, 75, 5, 5, 66846720, 12000, 30000, 4 },
373 { "4.1", 123, 2228224, 20000, 50000, 75, 5, 5, 133693440, 20000, 50000, 4 },
374 { "5", 150, 8912896, 25000, 100000, 200, 11, 10, 267386880, 25000, 100000, 6 },
375 { "5.1", 153, 8912896, 40000, 160000, 200, 11, 10, 534773760, 40000, 160000, 8 },
376 { "5.2", 156, 8912896, 60000, 240000, 200, 11, 10, 1069547520, 60000, 240000, 8 },
377 { "6", 180, 35651584, 60000, 240000, 600, 22, 20, 1069547520, 60000, 240000, 8 },
378 { "6.1", 183, 35651584, 120000, 480000, 600, 22, 20, 2139095040, 120000, 480000, 8 },
379 { "6.2", 186, 35651584, 240000, 800000, 600, 22, 20, 4278190080, 240000, 800000, 6 },
383 #ifndef GST_DISABLE_GST_DEBUG
385 _h265_slice_type_name (GstH265SliceType type)
388 case GST_H265_P_SLICE:
390 case GST_H265_B_SLICE:
392 case GST_H265_I_SLICE:
395 g_assert_not_reached ();
402 _rate_control_get_name (guint32 rc_mode)
404 GParamSpecEnum *spec;
407 if (!(properties[PROP_RATE_CONTROL]
408 && G_IS_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL])))
411 spec = G_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL]);
412 for (i = 0; i < spec->enum_class->n_values; i++) {
413 if (spec->enum_class->values[i].value == rc_mode)
414 return spec->enum_class->values[i].value_nick;
419 #endif /* end of GST_DISABLE_GST_DEBUG */
421 static GstVaH265EncFrame *
422 gst_va_h265_enc_frame_new (void)
424 GstVaH265EncFrame *frame;
426 frame = g_slice_new (GstVaH265EncFrame);
427 frame->last_frame = FALSE;
428 frame->picture = NULL;
429 frame->total_frame_count = 0;
435 gst_va_h265_enc_frame_free (gpointer pframe)
437 GstVaH265EncFrame *frame = pframe;
438 g_clear_pointer (&frame->picture, gst_va_encode_picture_free);
439 g_slice_free (GstVaH265EncFrame, frame);
442 static inline GstVaH265EncFrame *
443 _enc_frame (GstVideoCodecFrame * frame)
445 GstVaH265EncFrame *enc_frame = gst_video_codec_frame_get_user_data (frame);
446 g_assert (enc_frame);
450 static GstH265NalUnitType
451 _h265_nal_unit_type (GstVaH265EncFrame * frame)
453 GstH265NalUnitType nal_unit_type = -1;
455 switch (frame->type) {
456 case GST_H265_I_SLICE:
457 if (frame->poc == 0) {
458 nal_unit_type = GST_H265_NAL_SLICE_IDR_W_RADL;
460 nal_unit_type = GST_H265_NAL_SLICE_TRAIL_R;
463 case GST_H265_P_SLICE:
464 nal_unit_type = GST_H265_NAL_SLICE_TRAIL_R;
466 case GST_H265_B_SLICE:
468 nal_unit_type = GST_H265_NAL_SLICE_TRAIL_R;
470 nal_unit_type = GST_H265_NAL_SLICE_TRAIL_N;
477 g_assert (nal_unit_type >= 0);
478 return nal_unit_type;
482 _h265_fill_ptl (GstVaH265Enc * self,
483 const VAEncSequenceParameterBufferHEVC * sequence,
484 GstH265ProfileTierLevel * ptl)
486 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
489 *ptl = (GstH265ProfileTierLevel) {
491 .tier_flag = sequence->general_tier_flag,
492 .profile_idc = sequence->general_profile_idc,
493 .profile_compatibility_flag = { },
494 .progressive_source_flag = 1,
495 .interlaced_source_flag = 0,
496 .non_packed_constraint_flag = 0,
497 .frame_only_constraint_flag = 1,
499 .level_idc = sequence->general_level_idc,
503 if (sequence->general_profile_idc == 1 /* Main profile */
504 /* In A.3.4, NOTE: When general_profile_compatibility_flag[ 3 ] is equal
505 to 1, general_profile_compatibility_flag[ 1 ] and
506 general_profile_compatibility_flag[ 2 ] should also be equal to 1. */
507 || sequence->general_profile_idc == 3 /* Main Still Picture profile */
509 ptl->profile_compatibility_flag[1] = 1;
513 /* In A.3.2, NOTE: When general_profile_compatibility_flag[ 1 ] is equal
514 to 1, general_profile_compatibility_flag[ 2 ] should also be equal to
516 sequence->general_profile_idc == 1 /* Main profile */
517 || sequence->general_profile_idc == 2 /* Main 10 profile */
518 /* In A.3.4, NOTE: When general_profile_compatibility_flag[ 3 ] is equal
519 to 1, general_profile_compatibility_flag[ 1 ] and
520 general_profile_compatibility_flag[ 2 ] should also be equal to 1. */
521 || sequence->general_profile_idc == 3 /* Main Still Picture profile */
523 ptl->profile_compatibility_flag[2] = 1;
526 if (sequence->general_profile_idc == 3)
527 ptl->profile_compatibility_flag[3] = 1;
529 if (sequence->general_profile_idc == 4) /* format range extensions profiles */
530 ptl->profile_compatibility_flag[4] = 1;
532 if (sequence->general_profile_idc == 9) /* screen content coding profiles */
533 ptl->profile_compatibility_flag[9] = 1;
535 /* additional indications specified for general_profile_idc from 4~10 */
536 if (sequence->general_profile_idc == 4) {
537 /* In A.3.5, Format range extensions profiles.
538 Just support main444, main444-10 and main422-10 profile now, may add
539 more profiles when needed. */
540 switch (base->profile) {
541 case VAProfileHEVCMain444:
542 ptl->max_12bit_constraint_flag = 1;
543 ptl->max_10bit_constraint_flag = 1;
544 ptl->max_8bit_constraint_flag = 1;
545 ptl->max_422chroma_constraint_flag = 0;
546 ptl->max_420chroma_constraint_flag = 0;
547 ptl->max_monochrome_constraint_flag = 0;
548 ptl->intra_constraint_flag = 0;
549 ptl->one_picture_only_constraint_flag = 0;
550 ptl->lower_bit_rate_constraint_flag = 1;
552 case VAProfileHEVCMain444_10:
553 ptl->max_12bit_constraint_flag = 1;
554 ptl->max_10bit_constraint_flag = 1;
555 ptl->max_8bit_constraint_flag = 0;
556 ptl->max_422chroma_constraint_flag = 0;
557 ptl->max_420chroma_constraint_flag = 0;
558 ptl->max_monochrome_constraint_flag = 0;
559 ptl->intra_constraint_flag = 0;
560 ptl->one_picture_only_constraint_flag = 0;
561 ptl->lower_bit_rate_constraint_flag = 1;
563 case VAProfileHEVCMain422_10:
564 ptl->max_12bit_constraint_flag = 1;
565 ptl->max_10bit_constraint_flag = 1;
566 ptl->max_8bit_constraint_flag = 0;
567 ptl->max_422chroma_constraint_flag = 1;
568 ptl->max_420chroma_constraint_flag = 0;
569 ptl->max_monochrome_constraint_flag = 0;
570 ptl->intra_constraint_flag = 0;
571 ptl->one_picture_only_constraint_flag = 0;
572 ptl->lower_bit_rate_constraint_flag = 1;
574 case VAProfileHEVCMain12:
575 ptl->max_12bit_constraint_flag = 1;
576 ptl->max_10bit_constraint_flag = 0;
577 ptl->max_8bit_constraint_flag = 0;
578 ptl->max_422chroma_constraint_flag = 1;
579 ptl->max_420chroma_constraint_flag = 1;
580 ptl->max_monochrome_constraint_flag = 0;
581 ptl->intra_constraint_flag = 0;
582 ptl->one_picture_only_constraint_flag = 0;
583 ptl->lower_bit_rate_constraint_flag = 1;
586 GST_WARNING_OBJECT (self, "do not support the profile: %s of"
587 " range extensions.", gst_va_profile_name (base->profile));
595 GST_WARNING_OBJECT (self, "Failed to write Profile Tier Level");
599 /* By now, the VPS is not really used, we just fill all its fields
600 with the same info from the SPS. */
602 _h265_fill_vps (GstVaH265Enc * self,
603 const VAEncSequenceParameterBufferHEVC * seq_param)
605 guint max_dec_pic_buffering =
606 self->gop.num_ref_frames + 1 < self->gop.max_dpb_size ?
607 self->gop.num_ref_frames + 1 : self->gop.max_dpb_size;
610 self->vps_hdr = (GstH265VPS) {
612 .base_layer_internal_flag = 1,
613 .base_layer_available_flag = 1,
614 .max_layers_minus1 = 0,
615 .max_sub_layers_minus1 = 0,
616 .temporal_id_nesting_flag = 1,
618 .sub_layer_ordering_info_present_flag = 0,
619 .max_dec_pic_buffering_minus1 = { max_dec_pic_buffering - 1, },
620 .max_num_reorder_pics = { self->gop.num_reorder_frames, },
621 .max_latency_increase_plus1 = { 0, },
623 .num_layer_sets_minus1 = 0,
624 .timing_info_present_flag = 0,
629 if (!_h265_fill_ptl (self, seq_param, &self->vps_hdr.profile_tier_level))
636 _h265_fill_sps (GstVaH265Enc * self,
637 const VAEncSequenceParameterBufferHEVC * seq_param)
639 guint max_dec_pic_buffering =
640 self->gop.num_ref_frames + 1 < self->gop.max_dpb_size ?
641 self->gop.num_ref_frames + 1 : self->gop.max_dpb_size;
643 g_assert (self->gop.log2_max_pic_order_cnt >= 4);
645 self->sps_hdr = (GstH265SPS) {
647 .vps = &self->vps_hdr,
648 .max_sub_layers_minus1 = 0,
649 .temporal_id_nesting_flag = 1,
651 .chroma_format_idc = seq_param->seq_fields.bits.chroma_format_idc,
652 .separate_colour_plane_flag =
653 seq_param->seq_fields.bits.separate_colour_plane_flag,
654 .pic_width_in_luma_samples = seq_param->pic_width_in_luma_samples,
655 .pic_height_in_luma_samples = seq_param->pic_height_in_luma_samples,
656 .conformance_window_flag = self->conformance_window_flag,
657 .conf_win_left_offset = self->conf_win_left_offset,
658 .conf_win_right_offset = self->conf_win_right_offset,
659 .conf_win_top_offset = self->conf_win_top_offset,
660 .conf_win_bottom_offset = self->conf_win_bottom_offset,
661 .bit_depth_luma_minus8 = seq_param->seq_fields.bits.bit_depth_luma_minus8,
662 .bit_depth_chroma_minus8 =
663 seq_param->seq_fields.bits.bit_depth_chroma_minus8,
664 .log2_max_pic_order_cnt_lsb_minus4 = self->gop.log2_max_pic_order_cnt - 4,
665 .sub_layer_ordering_info_present_flag = 0,
666 .max_dec_pic_buffering_minus1 = { max_dec_pic_buffering - 1, },
667 .max_num_reorder_pics = { self->gop.num_reorder_frames, },
668 .max_latency_increase_plus1 = { 0, },
669 .log2_min_luma_coding_block_size_minus3 =
670 seq_param->log2_min_luma_coding_block_size_minus3,
671 .log2_diff_max_min_luma_coding_block_size =
672 seq_param->log2_diff_max_min_luma_coding_block_size,
673 .log2_min_transform_block_size_minus2 =
674 seq_param->log2_min_transform_block_size_minus2,
675 .log2_diff_max_min_transform_block_size =
676 seq_param->log2_diff_max_min_transform_block_size,
677 .max_transform_hierarchy_depth_inter =
678 seq_param->max_transform_hierarchy_depth_inter,
679 .max_transform_hierarchy_depth_intra =
680 seq_param->max_transform_hierarchy_depth_intra,
681 .scaling_list_enabled_flag =
682 seq_param->seq_fields.bits.scaling_list_enabled_flag,
683 .scaling_list_data_present_flag =
684 self->features.scaling_list_data_present_flag,
685 /* Do not change the scaling list now. */
687 .amp_enabled_flag = seq_param->seq_fields.bits.amp_enabled_flag,
688 .sample_adaptive_offset_enabled_flag =
689 seq_param->seq_fields.bits.sample_adaptive_offset_enabled_flag,
690 .pcm_enabled_flag = seq_param->seq_fields.bits.pcm_enabled_flag,
691 .pcm_sample_bit_depth_luma_minus1 =
692 seq_param->pcm_sample_bit_depth_luma_minus1,
693 .pcm_sample_bit_depth_chroma_minus1 =
694 seq_param->pcm_sample_bit_depth_chroma_minus1,
695 .log2_min_pcm_luma_coding_block_size_minus3 =
696 seq_param->log2_min_pcm_luma_coding_block_size_minus3,
697 .log2_diff_max_min_pcm_luma_coding_block_size =
698 seq_param->log2_max_pcm_luma_coding_block_size_minus3 -
699 seq_param->log2_min_pcm_luma_coding_block_size_minus3,
700 .pcm_loop_filter_disabled_flag =
701 seq_param->seq_fields.bits.pcm_loop_filter_disabled_flag,
702 .num_short_term_ref_pic_sets = 0,
703 .long_term_ref_pics_present_flag = 0,
704 .temporal_mvp_enabled_flag =
705 seq_param->seq_fields.bits.sps_temporal_mvp_enabled_flag,
706 .strong_intra_smoothing_enabled_flag =
707 seq_param->seq_fields.bits.strong_intra_smoothing_enabled_flag,
708 .vui_parameters_present_flag =
709 seq_param->vui_parameters_present_flag,
711 .aspect_ratio_info_present_flag =
712 seq_param->vui_fields.bits.aspect_ratio_info_present_flag,
713 .aspect_ratio_idc = seq_param->aspect_ratio_idc,
714 .sar_width = seq_param->sar_width,
715 .sar_height = seq_param->sar_height,
716 .overscan_info_present_flag = 0,
717 .video_signal_type_present_flag = 0,
718 .chroma_loc_info_present_flag = 0,
719 .neutral_chroma_indication_flag =
720 seq_param->vui_fields.bits.neutral_chroma_indication_flag,
721 .field_seq_flag = seq_param->vui_fields.bits.field_seq_flag,
722 .frame_field_info_present_flag = 0,
723 .default_display_window_flag = 0,
724 .timing_info_present_flag =
725 seq_param->vui_fields.bits.vui_timing_info_present_flag,
726 .num_units_in_tick = seq_param->vui_num_units_in_tick,
727 .time_scale = seq_param->vui_time_scale,
728 .poc_proportional_to_timing_flag = 0,
729 /* TODO: provide HRD. */
730 .hrd_parameters_present_flag = 0,
732 .hrd_parameters_present_flag = (seq_param->bits_per_second > 0),
734 .nal_hrd_parameters_present_flag = 1,
735 .vcl_hrd_parameters_present_flag = 0,
736 .sub_pic_hrd_params_present_flag = 0,
737 .bit_rate_scale = (SX_BITRATE - 6),
738 .cpb_size_scale = (SX_CPB_SIZE - 4),
739 .initial_cpb_removal_delay_length_minus1 = 23,
740 .au_cpb_removal_delay_length_minus1 = 23,
741 .dpb_output_delay_length_minus1 = 23,
742 .fixed_pic_rate_general_flag = { 0, },
743 .fixed_pic_rate_within_cvs_flag = { 0, },
744 .low_delay_hrd_flag = { 1, },
745 .cpb_cnt_minus1 = { 0, },
746 .sublayer_hrd_params = {
747 { .bit_rate_value_minus1 = { (seq_param->bits_per_second >> SX_BITRATE) - 1, },
748 .cpb_size_value_minus1 = { (hrd_params->buffer_size >> SX_CPB_SIZE) - 1, },
749 .cpb_size_du_value_minus1 = { 0, },
750 .bit_rate_du_value_minus1 = { 0, },
751 .cbr_flag = { self->rc_ctrl == VA_RC_CBR, },
755 .bitstream_restriction_flag =
756 seq_param->vui_fields.bits.bitstream_restriction_flag,
757 .tiles_fixed_structure_flag =
758 seq_param->vui_fields.bits.tiles_fixed_structure_flag,
759 .motion_vectors_over_pic_boundaries_flag =
760 seq_param->vui_fields.bits.motion_vectors_over_pic_boundaries_flag,
761 .restricted_ref_pic_lists_flag =
762 seq_param->vui_fields.bits.restricted_ref_pic_lists_flag,
763 .min_spatial_segmentation_idc = seq_param->min_spatial_segmentation_idc,
764 .max_bytes_per_pic_denom = seq_param->max_bytes_per_pic_denom,
765 .max_bits_per_min_cu_denom = seq_param->max_bits_per_min_cu_denom,
766 .log2_max_mv_length_horizontal =
767 seq_param->vui_fields.bits.log2_max_mv_length_horizontal,
768 .log2_max_mv_length_vertical =
769 seq_param->vui_fields.bits.log2_max_mv_length_vertical,
774 if (!_h265_fill_ptl (self, seq_param, &self->sps_hdr.profile_tier_level))
781 _h265_fill_pps (VAEncPictureParameterBufferHEVC * pic_param,
782 GstH265SPS * sps, GstH265PPS * pps)
785 *pps = (GstH265PPS) {
788 .dependent_slice_segments_enabled_flag =
789 pic_param->pic_fields.bits.dependent_slice_segments_enabled_flag,
790 .output_flag_present_flag = 0,
791 .num_extra_slice_header_bits = 0,
792 .sign_data_hiding_enabled_flag =
793 pic_param->pic_fields.bits.sign_data_hiding_enabled_flag,
794 .cabac_init_present_flag = 0,
795 .num_ref_idx_l0_default_active_minus1 =
796 pic_param->num_ref_idx_l0_default_active_minus1,
797 .num_ref_idx_l1_default_active_minus1 =
798 pic_param->num_ref_idx_l1_default_active_minus1,
799 .init_qp_minus26 = pic_param->pic_init_qp - 26,
800 .constrained_intra_pred_flag =
801 pic_param->pic_fields.bits.constrained_intra_pred_flag,
802 .transform_skip_enabled_flag =
803 pic_param->pic_fields.bits.transform_skip_enabled_flag,
804 .cu_qp_delta_enabled_flag =
805 pic_param->pic_fields.bits.cu_qp_delta_enabled_flag,
806 .diff_cu_qp_delta_depth = pic_param->diff_cu_qp_delta_depth,
807 .cb_qp_offset = pic_param->pps_cb_qp_offset,
808 .cr_qp_offset = pic_param->pps_cr_qp_offset,
809 .slice_chroma_qp_offsets_present_flag = 0,
810 .weighted_pred_flag = pic_param->pic_fields.bits.weighted_pred_flag,
811 .weighted_bipred_flag = pic_param->pic_fields.bits.weighted_bipred_flag,
812 .transquant_bypass_enabled_flag =
813 pic_param->pic_fields.bits.transquant_bypass_enabled_flag,
814 .tiles_enabled_flag = pic_param->pic_fields.bits.tiles_enabled_flag,
815 .entropy_coding_sync_enabled_flag =
816 pic_param->pic_fields.bits.entropy_coding_sync_enabled_flag,
817 .num_tile_columns_minus1 = pic_param->num_tile_columns_minus1,
818 .num_tile_rows_minus1 = pic_param->num_tile_rows_minus1,
819 /* Only support uniform tile mode now. */
820 .uniform_spacing_flag = 1,
821 .loop_filter_across_tiles_enabled_flag =
822 pic_param->pic_fields.bits.loop_filter_across_tiles_enabled_flag,
823 .loop_filter_across_slices_enabled_flag =
824 pic_param->pic_fields.bits.pps_loop_filter_across_slices_enabled_flag,
825 /* Do not change the default deblocking filter */
826 .deblocking_filter_control_present_flag = 0,
827 .deblocking_filter_override_enabled_flag = 0,
828 .deblocking_filter_disabled_flag = 0,
829 /* .beta_offset_div2,
831 .scaling_list_data_present_flag =
832 pic_param->pic_fields.bits.scaling_list_data_present_flag,
833 /* Do not change the scaling list now. */
835 /* Do not change the ref list */
836 .lists_modification_present_flag = 0,
837 .log2_parallel_merge_level_minus2 =
838 pic_param->log2_parallel_merge_level_minus2,
839 .slice_segment_header_extension_present_flag = 0,
840 /* TODO: set for SCC */
841 .pps_extension_flag = 0,
847 _h265_fill_slice_header (GstVaH265Enc * self, GstVaH265EncFrame * frame,
848 GstH265PPS * pps, VAEncSliceParameterBufferHEVC * slice_param,
849 gboolean first_slice_segment_in_pic,
850 guint list_forward_num, guint list_backward_num,
851 gint negative_pocs[16], guint num_negative_pics,
852 gint positive_pocs[16], guint num_positive_pics,
853 GstH265SliceHdr * slice_hdr)
859 *slice_hdr = (GstH265SliceHdr) {
861 .first_slice_segment_in_pic_flag = first_slice_segment_in_pic,
863 .no_output_of_prior_pics_flag = 0,
864 .dependent_slice_segment_flag =
865 slice_param->slice_fields.bits.dependent_slice_segment_flag,
866 .segment_address = slice_param->slice_segment_address,
867 .type = slice_param->slice_type,
868 /* pps->output_flag_present_flag is not set now. */
869 .pic_output_flag = 0,
870 .colour_plane_id = slice_param->slice_fields.bits.colour_plane_id,
871 /* Set the reference list fields later
873 .short_term_ref_pic_set_sps_flag,
874 .short_term_ref_pic_sets,
875 .short_term_ref_pic_set_idx,
880 .used_by_curr_pic_lt_flag[16],
881 .delta_poc_msb_present_flag[16],
882 .delta_poc_msb_cycle_lt[16], */
883 .temporal_mvp_enabled_flag =
884 slice_param->slice_fields.bits.slice_temporal_mvp_enabled_flag,
886 slice_param->slice_fields.bits.slice_sao_luma_flag,
888 slice_param->slice_fields.bits.slice_sao_chroma_flag,
889 /* Set the ref num later
890 .num_ref_idx_active_override_flag,
891 .num_ref_idx_l0_active_minus1,
892 .num_ref_idx_l1_active_minus1,
893 .ref_pic_list_modification, */
894 .mvd_l1_zero_flag = slice_param->slice_fields.bits.mvd_l1_zero_flag,
895 .cabac_init_flag = slice_param->slice_fields.bits.cabac_init_flag,
896 .collocated_from_l0_flag =
897 slice_param->slice_fields.bits.collocated_from_l0_flag,
898 .collocated_ref_idx = (slice_param->slice_type == GST_H265_I_SLICE ?
899 0xFF : self->features.collocated_ref_idx),
901 .pred_weight_table = { },
902 .five_minus_max_num_merge_cand = 5 - slice_param->max_num_merge_cand,
903 .use_integer_mv_flag = 0,
904 .qp_delta = slice_param->slice_qp_delta,
905 .cb_qp_offset = slice_param->slice_cb_qp_offset,
906 .cr_qp_offset = slice_param->slice_cr_qp_offset,
907 /* SCC is not enabled. */
908 .slice_act_y_qp_offset = 0,
909 .slice_act_cb_qp_offset = 0,
910 .slice_act_cr_qp_offset = 0,
912 .cu_chroma_qp_offset_enabled_flag = 0,
913 /* Do not change deblocking filter setting. */
914 .deblocking_filter_override_flag = 0,
915 .deblocking_filter_disabled_flag = 0,
916 /* .beta_offset_div2,
918 .loop_filter_across_slices_enabled_flag =
919 slice_param->slice_fields.bits.slice_loop_filter_across_slices_enabled_flag,
920 .num_entry_point_offsets = 0,
921 /* .offset_len_minus1,
922 .entry_point_offset_minus1, */
926 if (slice_hdr->dependent_slice_segment_flag)
929 if (slice_param->slice_type == GST_H265_I_SLICE)
932 slice_hdr->pic_order_cnt_lsb = frame->poc;
934 /* Write the ref set explicitly. */
935 slice_hdr->short_term_ref_pic_set_sps_flag = 0;
936 slice_hdr->short_term_ref_pic_sets.inter_ref_pic_set_prediction_flag = 0;
937 slice_hdr->short_term_ref_pic_sets.NumDeltaPocs =
938 num_negative_pics + num_positive_pics;
940 slice_hdr->short_term_ref_pic_sets.NumNegativePics = num_negative_pics;
941 for (i = 0; i < num_negative_pics; i++) {
942 delta_poc = negative_pocs[i] - frame->poc;
943 g_assert (delta_poc < 0);
944 slice_hdr->short_term_ref_pic_sets.DeltaPocS0[i] = delta_poc;
946 if (i < list_forward_num) {
947 slice_hdr->short_term_ref_pic_sets.UsedByCurrPicS0[i] = 1;
949 slice_hdr->short_term_ref_pic_sets.UsedByCurrPicS0[i] = 0;
953 slice_hdr->short_term_ref_pic_sets.NumPositivePics = num_positive_pics;
954 for (i = 0; i < num_positive_pics; i++) {
955 delta_poc = positive_pocs[i] - frame->poc;
956 g_assert (delta_poc > 0);
957 slice_hdr->short_term_ref_pic_sets.DeltaPocS1[i] = delta_poc;
959 if (i < list_backward_num) {
960 slice_hdr->short_term_ref_pic_sets.UsedByCurrPicS1[i] = 1;
962 slice_hdr->short_term_ref_pic_sets.UsedByCurrPicS1[i] = 0;
966 slice_hdr->num_ref_idx_active_override_flag =
967 slice_param->slice_fields.bits.num_ref_idx_active_override_flag;
968 if (slice_hdr->num_ref_idx_active_override_flag) {
969 slice_hdr->num_ref_idx_l0_active_minus1 =
970 slice_param->num_ref_idx_l0_active_minus1;
972 if (slice_param->slice_type == GST_H265_B_SLICE)
973 slice_hdr->num_ref_idx_l1_active_minus1 =
974 slice_param->num_ref_idx_l1_active_minus1;
981 _h265_add_vps_header (GstVaH265Enc * self, GstVaH265EncFrame * frame)
983 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
985 #define VPS_SIZE 4 + GST_ROUND_UP_8 (MAX_VPS_HDR_SIZE + \
986 MAX_PROFILE_TIER_LEVEL_SIZE + MAX_HRD_PARAMS_SIZE) / 8
987 guint8 packed_vps[VPS_SIZE] = { 0, };
990 size = sizeof (packed_vps);
991 if (gst_h265_bit_writer_vps (&self->vps_hdr, TRUE, packed_vps, &size)
992 != GST_H265_BIT_WRITER_OK) {
993 GST_ERROR_OBJECT (self, "Failed to write VPS header.");
997 /* VPS does not have its own packed header define, just reuse
998 VAEncPackedHeaderSequence */
999 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
1000 VAEncPackedHeaderSequence, packed_vps, size * 8, FALSE)) {
1001 GST_ERROR_OBJECT (self, "Failed to add packed VPS header.");
1009 _h265_add_sps_header (GstVaH265Enc * self, GstVaH265EncFrame * frame)
1011 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1013 #define SPS_SIZE 4 + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE + \
1014 MAX_PROFILE_TIER_LEVEL_SIZE + 64 * MAX_SHORT_TERM_REFPICSET_SIZE + \
1015 MAX_VUI_PARAMS_SIZE + MAX_HRD_PARAMS_SIZE) / 8
1016 guint8 packed_sps[SPS_SIZE] = { 0, };
1019 size = sizeof (packed_sps);
1020 if (gst_h265_bit_writer_sps (&self->sps_hdr, TRUE, packed_sps, &size)
1021 != GST_H265_BIT_WRITER_OK) {
1022 GST_ERROR_OBJECT (self, "Failed to write SPS header.");
1026 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
1027 VAEncPackedHeaderSequence, packed_sps, size * 8, FALSE)) {
1028 GST_ERROR_OBJECT (self, "Failed to add packed SPS header.");
1036 _h265_add_pps_header (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1039 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1041 #define PPS_SIZE 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8
1042 guint8 packed_pps[PPS_SIZE] = { 0, };
1045 size = sizeof (packed_pps);
1046 if (gst_h265_bit_writer_pps (pps, TRUE, packed_pps,
1047 &size) != GST_H265_BIT_WRITER_OK) {
1048 GST_ERROR_OBJECT (self, "Failed to generate the picture header");
1052 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
1053 VAEncPackedHeaderPicture, packed_pps, size * 8, FALSE)) {
1054 GST_ERROR_OBJECT (self, "Failed to add the packed picture header");
1062 _h265_add_slice_header (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1063 GstH265SliceHdr * slice_hdr)
1065 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1066 GstH265NalUnitType nal_type = _h265_nal_unit_type (frame);
1068 #define SLICE_HDR_SIZE 4 + GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE) / 8
1069 guint8 packed_slice_hdr[SLICE_HDR_SIZE] = { 0, };
1070 #undef SLICE_HDR_SIZE
1072 size = sizeof (packed_slice_hdr);
1073 if (gst_h265_bit_writer_slice_hdr (slice_hdr, TRUE, nal_type,
1074 packed_slice_hdr, &size) != GST_H265_BIT_WRITER_OK) {
1075 GST_ERROR_OBJECT (self, "Failed to generate the slice header");
1079 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
1080 VAEncPackedHeaderSlice, packed_slice_hdr, size * 8, FALSE)) {
1081 GST_ERROR_OBJECT (self, "Failed to add the packed slice header");
1089 _h265_add_aud (GstVaH265Enc * self, GstVaH265EncFrame * frame)
1091 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1092 guint8 aud_data[8] = { };
1094 guint8 pic_type = 0;
1096 switch (frame->type) {
1097 case GST_H265_I_SLICE:
1100 case GST_H265_P_SLICE:
1103 case GST_H265_B_SLICE:
1107 g_assert_not_reached ();
1111 size = sizeof (aud_data);
1112 if (gst_h265_bit_writer_aud (pic_type, TRUE, aud_data,
1113 &size) != GST_H265_BIT_WRITER_OK) {
1114 GST_ERROR_OBJECT (self, "Failed to generate the AUD");
1118 if (!gst_va_encoder_add_packed_header (base->encoder, frame->picture,
1119 VAEncPackedHeaderRawData, aud_data, size * 8, FALSE)) {
1120 GST_ERROR_OBJECT (self, "Failed to add the AUD");
1127 /* Returns H.265 chroma_format_idc value from chroma type */
1129 _h265_get_chroma_format_idc (guint chroma_type)
1131 guint chroma_format_idc;
1133 switch (chroma_type) {
1134 case VA_RT_FORMAT_YUV400:
1135 chroma_format_idc = 0;
1137 case VA_RT_FORMAT_YUV420:
1138 case VA_RT_FORMAT_YUV420_10:
1139 case VA_RT_FORMAT_YUV420_12:
1140 chroma_format_idc = 1;
1142 case VA_RT_FORMAT_YUV422:
1143 case VA_RT_FORMAT_YUV422_10:
1144 case VA_RT_FORMAT_YUV422_12:
1145 chroma_format_idc = 2;
1147 case VA_RT_FORMAT_YUV444:
1148 case VA_RT_FORMAT_YUV444_10:
1149 case VA_RT_FORMAT_YUV444_12:
1150 chroma_format_idc = 3;
1153 GST_DEBUG ("unsupported GstVaapiChromaType value");
1154 chroma_format_idc = 1;
1157 return chroma_format_idc;
1161 _h265_fill_sequence_parameter (GstVaH265Enc * self,
1162 VAEncSequenceParameterBufferHEVC * sequence)
1164 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1165 guint profile_idc = 0;
1167 switch (base->profile) {
1168 case VAProfileHEVCMain:
1171 case VAProfileHEVCMain10:
1174 case VAProfileHEVCMain12:
1175 case VAProfileHEVCMain422_10:
1176 case VAProfileHEVCMain422_12:
1177 case VAProfileHEVCMain444:
1178 case VAProfileHEVCMain444_10:
1179 case VAProfileHEVCMain444_12:
1183 GST_ERROR_OBJECT (self, "unsupported profile %d", base->profile);
1188 *sequence = (VAEncSequenceParameterBufferHEVC) {
1189 .general_profile_idc = profile_idc,
1190 .general_level_idc = self->level_idc,
1191 .general_tier_flag = self->tier_flag,
1193 self->gop.i_period > 0 ? self->gop.i_period : self->gop.idr_period,
1194 .intra_idr_period = self->gop.idr_period,
1195 .ip_period = self->gop.ip_period,
1196 .bits_per_second = self->rc.target_bitrate_bits,
1197 .pic_width_in_luma_samples = self->luma_width,
1198 .pic_height_in_luma_samples = self->luma_height,
1199 .seq_fields.bits = {
1200 .chroma_format_idc = _h265_get_chroma_format_idc (base->rt_format),
1201 .separate_colour_plane_flag = self->features.separate_colour_plane_flag,
1202 .bit_depth_luma_minus8 = self->bits_depth_luma_minus8,
1203 .bit_depth_chroma_minus8 = self->bits_depth_chroma_minus8,
1204 .scaling_list_enabled_flag = self->features.scaling_list_enabled_flag,
1205 .strong_intra_smoothing_enabled_flag =
1206 self->features.strong_intra_smoothing_enabled_flag,
1207 .amp_enabled_flag = self->features.amp_enabled_flag,
1208 .sample_adaptive_offset_enabled_flag =
1209 self->features.sample_adaptive_offset_enabled_flag,
1210 .pcm_enabled_flag = self->features.pcm_enabled_flag,
1211 .pcm_loop_filter_disabled_flag =
1212 self->features.pcm_loop_filter_disabled_flag,
1213 .sps_temporal_mvp_enabled_flag =
1214 self->features.temporal_mvp_enabled_flag,
1215 .low_delay_seq = (self->gop.num_bframes == 0),
1216 .hierachical_flag = self->gop.b_pyramid,
1218 .log2_min_luma_coding_block_size_minus3 =
1219 self->features.log2_min_luma_coding_block_size_minus3,
1220 .log2_diff_max_min_luma_coding_block_size =
1221 self->features.log2_diff_max_min_luma_coding_block_size,
1222 .log2_min_transform_block_size_minus2 =
1223 self->features.log2_min_transform_block_size_minus2,
1224 .log2_diff_max_min_transform_block_size =
1225 self->features.log2_diff_max_min_transform_block_size,
1226 .max_transform_hierarchy_depth_inter =
1227 self->features.max_transform_hierarchy_depth_inter,
1228 .max_transform_hierarchy_depth_intra =
1229 self->features.max_transform_hierarchy_depth_intra,
1230 /* pcm_enabled_flag is unset, ignore */
1231 .pcm_sample_bit_depth_luma_minus1 =
1232 self->features.pcm_sample_bit_depth_luma_minus1,
1233 .pcm_sample_bit_depth_chroma_minus1 =
1234 self->features.pcm_sample_bit_depth_chroma_minus1,
1235 .log2_min_pcm_luma_coding_block_size_minus3 =
1236 self->features.log2_min_pcm_luma_coding_block_size_minus3,
1237 .log2_max_pcm_luma_coding_block_size_minus3 =
1238 self->features.log2_max_pcm_luma_coding_block_size_minus3,
1239 /* VUI parameters are always set, at least for timing_info (framerate) */
1240 .vui_parameters_present_flag = TRUE,
1241 .vui_fields.bits = {
1242 .aspect_ratio_info_present_flag = TRUE,
1243 .bitstream_restriction_flag = FALSE,
1244 .vui_timing_info_present_flag = TRUE,
1246 /* if (vui_fields.bits.aspect_ratio_info_present_flag) */
1247 .aspect_ratio_idc = 0xff,
1248 .sar_width = GST_VIDEO_INFO_PAR_N (&base->input_state->info),
1249 .sar_height = GST_VIDEO_INFO_PAR_D (&base->input_state->info),
1250 /* if (vui_fields.bits.vui_timing_info_present_flag) */
1251 .vui_num_units_in_tick = GST_VIDEO_INFO_FPS_D (&base->input_state->info),
1252 .vui_time_scale = GST_VIDEO_INFO_FPS_N (&base->input_state->info),
1260 _h265_to_va_coding_type (GstVaH265Enc * self, GstVaH265EncFrame * frame)
1262 guint coding_type = 0;
1264 switch (frame->type) {
1265 case GST_H265_I_SLICE:
1268 case GST_H265_P_SLICE:
1269 if (self->gop.low_delay_b_mode) {
1270 /* Convert P into forward ref B */
1276 case GST_H265_B_SLICE:
1277 /* We use hierarchical_level_plus1, so same for all B frames */
1284 g_assert (coding_type > 0);
1288 static inline gboolean
1289 _h265_fill_picture_parameter (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1290 VAEncPictureParameterBufferHEVC * pic_param, gint collocated_poc)
1292 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1293 gboolean tiles_enabled_flag;
1294 guint8 num_ref_idx_l0_default_active_minus1 = 0;
1295 guint8 num_ref_idx_l1_default_active_minus1 = 0;
1296 guint hierarchical_level_plus1 = 0;
1299 if (self->gop.b_pyramid) {
1300 /* I/P is the base hierarchical level 0, L0 level B is 1, and so on. */
1301 hierarchical_level_plus1 = 1;
1303 if (frame->type == GST_H265_B_SLICE) {
1304 hierarchical_level_plus1 += 1;
1305 hierarchical_level_plus1 += frame->pyramid_level;
1309 if (frame->type == GST_H265_P_SLICE || frame->type == GST_H265_B_SLICE) {
1310 num_ref_idx_l0_default_active_minus1 =
1311 (self->gop.forward_ref_num > 0 ? self->gop.forward_ref_num - 1 : 0);
1313 if (frame->type == GST_H265_B_SLICE) {
1314 num_ref_idx_l1_default_active_minus1 =
1315 (self->gop.backward_ref_num > 0 ? self->gop.backward_ref_num - 1 : 0);
1318 /* TODO: multi tile support. */
1319 tiles_enabled_flag = 0;
1322 *pic_param = (VAEncPictureParameterBufferHEVC) {
1323 .decoded_curr_pic.picture_id =
1324 gst_va_encode_picture_get_reconstruct_surface (frame->picture),
1325 .decoded_curr_pic.pic_order_cnt = frame->poc,
1326 .decoded_curr_pic.flags = 0,
1328 .coded_buf = frame->picture->coded_buffer,
1329 .last_picture = frame->last_frame,
1330 .pic_init_qp = self->rc.qp_i,
1331 .diff_cu_qp_delta_depth = self->features.diff_cu_qp_delta_depth,
1332 /* Do not use qp offset in picture. */
1333 .pps_cb_qp_offset = 0,
1334 .pps_cr_qp_offset = 0,
1335 /* TODO: multi tile support */
1336 .num_tile_columns_minus1 = 0,
1337 .num_tile_rows_minus1 = 0,
1338 .log2_parallel_merge_level_minus2 = 0,
1339 .ctu_max_bitsize_allowed = 0,
1340 .num_ref_idx_l0_default_active_minus1 = num_ref_idx_l0_default_active_minus1,
1341 .num_ref_idx_l1_default_active_minus1 = num_ref_idx_l1_default_active_minus1,
1342 .slice_pic_parameter_set_id = 0,
1343 .nal_unit_type = _h265_nal_unit_type (frame),
1344 .pic_fields.bits = {
1345 .idr_pic_flag = (frame->poc == 0),
1346 .coding_type = _h265_to_va_coding_type (self, frame),
1347 .reference_pic_flag = frame->is_ref,
1348 /* allow slice to set dependent_slice_segment_flag */
1349 .dependent_slice_segments_enabled_flag =
1350 self->features.dependent_slice_segment_flag,
1351 .sign_data_hiding_enabled_flag =
1352 self->features.sign_data_hiding_enabled_flag,
1353 .constrained_intra_pred_flag = self->features.constrained_intra_pred_flag,
1354 .transform_skip_enabled_flag = self->features.transform_skip_enabled_flag,
1355 .cu_qp_delta_enabled_flag = self->features.cu_qp_delta_enabled_flag,
1356 .weighted_pred_flag = self->features.weighted_pred_flag,
1357 .weighted_bipred_flag = self->features.weighted_bipred_flag,
1358 .transquant_bypass_enabled_flag =
1359 self->features.transquant_bypass_enabled_flag,
1360 .tiles_enabled_flag = tiles_enabled_flag,
1361 .entropy_coding_sync_enabled_flag = 0,
1362 /* When we enable multi tiles, enable this. */
1363 .loop_filter_across_tiles_enabled_flag = tiles_enabled_flag,
1364 .pps_loop_filter_across_slices_enabled_flag = 1,
1365 /* Should not change the scaling list, not used now */
1366 .scaling_list_data_present_flag =
1367 self->features.scaling_list_data_present_flag,
1368 .screen_content_flag = 0,
1369 /* Depend on weighted_pred_flag and weighted_bipred_flag */
1370 .enable_gpu_weighted_prediction = 0,
1372 .no_output_of_prior_pics_flag = 0,
1374 /* We use coding_type here, set this to 0. */
1375 .hierarchical_level_plus1 = hierarchical_level_plus1,
1380 if (frame->type != GST_H265_I_SLICE) {
1381 GstVaH265EncFrame *f;
1383 if (g_queue_is_empty (&base->ref_list)) {
1384 GST_ERROR_OBJECT (self, "No reference found for frame type %s",
1385 _h265_slice_type_name (frame->type));
1389 g_assert (g_queue_get_length (&base->ref_list) <= self->gop.num_ref_frames);
1391 /* ref frames in queue are already sorted by poc. */
1392 for (; i < g_queue_get_length (&base->ref_list); i++) {
1393 f = _enc_frame (g_queue_peek_nth (&base->ref_list, i));
1395 pic_param->reference_frames[i].picture_id =
1396 gst_va_encode_picture_get_reconstruct_surface (f->picture);
1397 pic_param->reference_frames[i].pic_order_cnt = f->poc;
1398 pic_param->reference_frames[i].flags = 0;
1403 for (; i < 15; i++) {
1404 pic_param->reference_frames[i].picture_id = VA_INVALID_SURFACE;
1405 pic_param->reference_frames[i].flags = VA_PICTURE_HEVC_INVALID;
1408 /* If mvp enabled, collocated_ref_idx specifies the reference index of
1409 the collocated picture used for temporal motion vector prediction.
1410 We should find the according index in reference_frames[] here. */
1411 if (frame->type != GST_H265_I_SLICE
1412 && self->features.temporal_mvp_enabled_flag) {
1415 for (i = 0; i < 15; i++) {
1416 if (pic_param->reference_frames[i].flags != VA_PICTURE_HEVC_INVALID &&
1417 pic_param->reference_frames[i].pic_order_cnt == collocated_poc) {
1423 g_assert (index >= 0);
1424 pic_param->collocated_ref_pic_index = index;
1426 pic_param->collocated_ref_pic_index = 0xFF;
1433 _h265_fill_slice_parameter (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1434 guint start_address, gint ctu_num, gboolean last_slice_of_pic,
1435 GstVaH265EncFrame * list0[16], guint list0_num,
1436 GstVaH265EncFrame * list1[16], guint list1_num,
1437 VAEncSliceParameterBufferHEVC * slice)
1439 int8_t slice_qp_delta = 0;
1440 GstH265SliceType frame_type;
1444 if (self->rc.rc_ctrl_mode == VA_RC_CQP) {
1445 if (frame->type == GST_H265_P_SLICE) {
1446 slice_qp_delta = self->rc.qp_p - self->rc.qp_i;
1447 } else if (frame->type == GST_H265_B_SLICE) {
1448 slice_qp_delta = (int8_t) (self->rc.qp_b - self->rc.qp_i);
1450 g_assert (slice_qp_delta <= 51 && slice_qp_delta >= -51);
1453 frame_type = frame->type;
1454 /* If low_delay_b_mode, we convert P to low delay b, which has 2
1455 ref lists and clone L1 from L0. */
1456 if (self->gop.low_delay_b_mode && frame->type == GST_H265_P_SLICE) {
1457 g_assert (self->gop.max_l1_num > 0);
1458 g_assert (list1_num == 0);
1460 frame_type = GST_H265_B_SLICE;
1461 list1_num = (list0_num <= self->gop.max_l1_num ?
1462 list0_num : self->gop.max_l1_num);
1464 for (i = 0; i < list1_num; i++)
1465 list1[i] = list0[i];
1468 *slice = (VAEncSliceParameterBufferHEVC) {
1469 .slice_segment_address = start_address,
1470 .num_ctu_in_slice = ctu_num,
1471 .slice_type = frame_type,
1472 /* Only one parameter set supported now. */
1473 .slice_pic_parameter_set_id = 0,
1474 /* Set the reference list later
1475 .num_ref_idx_l0_active_minus1,
1476 .num_ref_idx_l1_active_minus1,
1478 .ref_pic_list1[15], */
1479 /* weighted_pred_flag or weighted_bipred_idc is not enabled. */
1480 .luma_log2_weight_denom = 0,
1481 .delta_chroma_log2_weight_denom = 0,
1482 .delta_luma_weight_l0 = { 0, },
1483 .luma_offset_l0 = { 0, },
1484 .delta_chroma_weight_l0 = { },
1485 .chroma_offset_l0 = { },
1486 .delta_luma_weight_l1 = { },
1487 .luma_offset_l1 = { },
1488 .delta_chroma_weight_l1 = { },
1489 .chroma_offset_l1 = { },
1491 .max_num_merge_cand = 5,
1492 .slice_qp_delta = slice_qp_delta,
1493 .slice_cb_qp_offset = 0,
1494 .slice_cr_qp_offset = 0,
1495 /* deblocking_filter_control_present_flag not set now. */
1496 .slice_beta_offset_div2 = 0,
1497 .slice_tc_offset_div2 = 0,
1498 .slice_fields.bits = {
1499 .last_slice_of_pic_flag = last_slice_of_pic,
1500 .dependent_slice_segment_flag = (start_address == 0 ? 0 :
1501 self->features.dependent_slice_segment_flag),
1502 .colour_plane_id = self->features.colour_plane_id,
1503 .slice_temporal_mvp_enabled_flag =
1504 self->features.temporal_mvp_enabled_flag,
1505 .slice_sao_luma_flag = self->features.slice_sao_luma_flag,
1506 .slice_sao_chroma_flag = self->features.slice_sao_chroma_flag,
1507 /* Set the reference list later
1508 .num_ref_idx_active_override_flag, */
1509 .mvd_l1_zero_flag = 0,
1510 /* cabac_init_present_flag is not set now. */
1511 .cabac_init_flag = 0,
1512 /* deblocking_filter_control_present_flag not set now */
1513 .slice_deblocking_filter_disabled_flag = 0,
1514 .slice_loop_filter_across_slices_enabled_flag = 1,
1515 .collocated_from_l0_flag = (frame_type == GST_H265_I_SLICE ?
1516 0 : self->features.collocated_from_l0_flag),
1518 #if VA_CHECK_VERSION(1, 10, 0)
1519 .pred_weight_table_bit_offset = 0,
1520 .pred_weight_table_bit_length = 0,
1525 if (frame_type == GST_H265_B_SLICE || frame_type == GST_H265_P_SLICE) {
1526 slice->slice_fields.bits.num_ref_idx_active_override_flag =
1527 (list0_num > 0 || list1_num > 0);
1528 slice->num_ref_idx_l0_active_minus1 = list0_num > 0 ? list0_num - 1 : 0;
1530 if (frame_type == GST_H265_B_SLICE)
1531 slice->num_ref_idx_l1_active_minus1 = list1_num > 0 ? list1_num - 1 : 0;
1535 if (frame_type != GST_H265_I_SLICE) {
1536 for (; i < list0_num; i++) {
1537 slice->ref_pic_list0[i].picture_id =
1538 gst_va_encode_picture_get_reconstruct_surface (list0[i]->picture);
1539 slice->ref_pic_list0[i].pic_order_cnt = list0[i]->poc;
1542 for (; i < G_N_ELEMENTS (slice->ref_pic_list0); ++i) {
1543 slice->ref_pic_list0[i].picture_id = VA_INVALID_SURFACE;
1544 slice->ref_pic_list0[i].flags = VA_PICTURE_HEVC_INVALID;
1548 if (frame_type == GST_H265_B_SLICE) {
1549 for (; i < list1_num; i++) {
1550 slice->ref_pic_list1[i].picture_id =
1551 gst_va_encode_picture_get_reconstruct_surface (list1[i]->picture);
1552 slice->ref_pic_list1[i].pic_order_cnt = list1[i]->poc;
1555 for (; i < G_N_ELEMENTS (slice->ref_pic_list1); ++i) {
1556 slice->ref_pic_list1[i].picture_id = VA_INVALID_SURFACE;
1557 slice->ref_pic_list1[i].flags = VA_PICTURE_HEVC_INVALID;
1564 _h265_add_sequence_parameter (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1565 VAEncSequenceParameterBufferHEVC * sequence)
1567 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1569 if (!gst_va_encoder_add_param (base->encoder, frame->picture,
1570 VAEncSequenceParameterBufferType, sequence, sizeof (*sequence))) {
1571 GST_ERROR_OBJECT (self, "Failed to create the sequence parameter");
1579 _h265_add_picture_parameter (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1580 VAEncPictureParameterBufferHEVC * pic_param)
1582 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1584 if (!gst_va_encoder_add_param (base->encoder, frame->picture,
1585 VAEncPictureParameterBufferType, pic_param,
1586 sizeof (VAEncPictureParameterBufferHEVC))) {
1587 GST_ERROR_OBJECT (self, "Failed to create the picture parameter");
1595 _h265_add_slice_parameter (GstVaH265Enc * self, GstVaH265EncFrame * frame,
1596 VAEncSliceParameterBufferHEVC * slice)
1598 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1600 if (!gst_va_encoder_add_param (base->encoder, frame->picture,
1601 VAEncSliceParameterBufferType, slice,
1602 sizeof (VAEncSliceParameterBufferHEVC))) {
1603 GST_ERROR_OBJECT (self, "Failed to add the slice parameter");
1611 _h265_add_slices (GstVaH265Enc * self,
1612 GstVaH265EncFrame * frame, GstH265PPS * pps,
1613 GstVaH265EncFrame * list_forward[16], guint list_forward_num,
1614 GstVaH265EncFrame * list_backward[16], guint list_backward_num,
1615 gint negative_pocs[16], guint num_negative_pics,
1616 gint positive_pocs[16], guint num_positive_pics)
1619 guint ctus_per_slice, ctus_mod_slice, cur_slice_ctus;
1620 guint last_ctu_index;
1622 VAEncSliceParameterBufferHEVC slice;
1623 GstH265SliceHdr slice_hdr;
1625 ctu_size = self->ctu_width * self->ctu_height;
1627 g_assert (self->num_slices && self->num_slices < ctu_size);
1629 ctus_per_slice = ctu_size / self->num_slices;
1630 ctus_mod_slice = ctu_size % self->num_slices;
1633 for (i_slice = 0; i_slice < self->num_slices; i_slice++) {
1634 cur_slice_ctus = ctus_per_slice;
1635 /* Scatter the remainder to each slice */
1636 if (ctus_mod_slice) {
1641 if (!_h265_fill_slice_parameter (self, frame, last_ctu_index,
1642 cur_slice_ctus, (i_slice == self->num_slices - 1),
1643 list_forward, list_forward_num,
1644 list_backward, list_backward_num, &slice))
1647 if (!_h265_add_slice_parameter (self, frame, &slice))
1650 if (self->packed_headers & VA_ENC_PACKED_HEADER_SLICE) {
1651 if (!_h265_fill_slice_header (self, frame, pps, &slice, i_slice == 0,
1652 list_forward_num, list_backward_num, negative_pocs,
1653 num_negative_pics, positive_pocs, num_positive_pics, &slice_hdr))
1656 if (!_h265_add_slice_header (self, frame, &slice_hdr))
1660 /* set calculation for next slice */
1661 last_ctu_index += cur_slice_ctus;
1662 g_assert (last_ctu_index <= ctu_size);
1669 _poc_asc_compare (const GstVaH265EncFrame ** a, const GstVaH265EncFrame ** b)
1671 return (*a)->poc - (*b)->poc;
1675 _poc_des_compare (const GstVaH265EncFrame ** a, const GstVaH265EncFrame ** b)
1677 return (*b)->poc - (*a)->poc;
1681 _h265_encode_one_frame (GstVaH265Enc * self, GstVideoCodecFrame * gst_frame)
1683 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1684 VAEncPictureParameterBufferHEVC pic_param;
1686 GstVaH265EncFrame *frame;
1687 GstVaH265EncFrame *list_forward[16] = { NULL, };
1688 guint list_forward_num = 0;
1689 GstVaH265EncFrame *list_backward[16] = { NULL, };
1690 guint list_backward_num = 0;
1691 gint negative_pocs[16] = { };
1692 guint num_negative_pics = 0;
1693 gint positive_pocs[16] = { };
1694 guint num_positive_pics = 0;
1695 gint collocated_poc = -1;
1698 g_return_val_if_fail (gst_frame, FALSE);
1700 frame = _enc_frame (gst_frame);
1702 if (self->aud && !_h265_add_aud (self, frame))
1705 /* Repeat the VPS/SPS for IDR. */
1706 if (frame->poc == 0) {
1707 VAEncSequenceParameterBufferHEVC sequence;
1709 if (!gst_va_base_enc_add_rate_control_parameter (base, frame->picture,
1710 self->rc.rc_ctrl_mode, self->rc.max_bitrate_bits,
1711 self->rc.target_percentage, self->rc.qp_i, self->rc.min_qp,
1712 self->rc.max_qp, self->rc.mbbrc))
1715 if (!gst_va_base_enc_add_quality_level_parameter (base, frame->picture,
1716 self->rc.target_usage))
1719 if (!gst_va_base_enc_add_frame_rate_parameter (base, frame->picture))
1722 if (!gst_va_base_enc_add_hrd_parameter (base, frame->picture,
1723 self->rc.rc_ctrl_mode, self->rc.cpb_length_bits))
1726 if (!gst_va_base_enc_add_trellis_parameter (base, frame->picture,
1727 self->features.use_trellis))
1730 _h265_fill_sequence_parameter (self, &sequence);
1731 if (!_h265_add_sequence_parameter (self, frame, &sequence))
1734 if (self->packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE) {
1735 if (!_h265_fill_vps (self, &sequence))
1738 if (!_h265_fill_sps (self, &sequence))
1741 if (!_h265_add_vps_header (self, frame))
1744 if (!_h265_add_sps_header (self, frame))
1749 /* Non I frame, construct reference list. */
1750 if (frame->type != GST_H265_I_SLICE) {
1751 GstVaH265EncFrame *vaf;
1752 GstVideoCodecFrame *f;
1754 for (i = g_queue_get_length (&base->ref_list) - 1; i >= 0; i--) {
1755 f = g_queue_peek_nth (&base->ref_list, i);
1756 vaf = _enc_frame (f);
1757 if (vaf->poc > frame->poc)
1760 list_forward[list_forward_num] = vaf;
1764 /* reorder to select the most nearest forward frames. */
1765 g_qsort_with_data (list_forward, list_forward_num, sizeof (gpointer),
1766 (GCompareDataFunc) _poc_des_compare, NULL);
1768 num_negative_pics = list_forward_num;
1769 for (i = 0; i < list_forward_num; i++)
1770 negative_pocs[i] = list_forward[i]->poc;
1772 if (list_forward_num > self->gop.forward_ref_num)
1773 list_forward_num = self->gop.forward_ref_num;
1775 if (self->features.temporal_mvp_enabled_flag
1776 && self->features.collocated_from_l0_flag) {
1777 if (self->features.collocated_ref_idx >= list_forward_num) {
1778 GST_ERROR_OBJECT (self, "MVP collocated_ref_idx %d is out of L0 range",
1779 self->features.collocated_ref_idx);
1783 collocated_poc = list_forward[self->features.collocated_ref_idx]->poc;
1787 if (frame->type == GST_H265_B_SLICE) {
1788 GstVaH265EncFrame *vaf;
1789 GstVideoCodecFrame *f;
1791 for (i = 0; i < g_queue_get_length (&base->ref_list); i++) {
1792 f = g_queue_peek_nth (&base->ref_list, i);
1793 vaf = _enc_frame (f);
1794 if (vaf->poc < frame->poc)
1797 list_backward[list_backward_num] = vaf;
1798 list_backward_num++;
1801 /* reorder to select the most nearest backward frames. */
1802 g_qsort_with_data (list_backward, list_backward_num, sizeof (gpointer),
1803 (GCompareDataFunc) _poc_asc_compare, NULL);
1805 num_positive_pics = list_backward_num;
1806 for (i = 0; i < list_backward_num; i++)
1807 positive_pocs[i] = list_backward[i]->poc;
1809 if (list_backward_num > self->gop.backward_ref_num)
1810 list_backward_num = self->gop.backward_ref_num;
1812 if (self->features.temporal_mvp_enabled_flag
1813 && !self->features.collocated_from_l0_flag) {
1814 if (self->features.collocated_ref_idx >= list_backward_num) {
1815 GST_ERROR_OBJECT (self, "MVP collocated_ref_idx %d is out of L1 range",
1816 self->features.collocated_ref_idx);
1820 collocated_poc = list_backward[self->features.collocated_ref_idx]->poc;
1824 g_assert (list_forward_num + list_backward_num <= self->gop.num_ref_frames);
1826 if (!_h265_fill_picture_parameter (self, frame, &pic_param, collocated_poc))
1828 if (!_h265_add_picture_parameter (self, frame, &pic_param))
1831 _h265_fill_pps (&pic_param, &self->sps_hdr, &pps);
1833 if ((self->packed_headers & VA_ENC_PACKED_HEADER_PICTURE)
1834 && frame->type == GST_H265_I_SLICE
1835 && !_h265_add_pps_header (self, frame, &pps))
1838 if (!_h265_add_slices (self, frame, &pps,
1839 list_forward, list_forward_num, list_backward, list_backward_num,
1840 negative_pocs, num_negative_pics, positive_pocs, num_positive_pics))
1843 if (!gst_va_encoder_encode (base->encoder, frame->picture)) {
1844 GST_ERROR_OBJECT (self, "Encode frame error");
1852 _h265_push_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame * gst_frame,
1855 GstVaH265Enc *self = GST_VA_H265_ENC (base);
1856 GstVaH265EncFrame *frame;
1858 g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
1862 /* Begin a new GOP, should have a empty reorder_list. */
1863 if (self->gop.cur_frame_index == self->gop.idr_period) {
1864 g_assert (g_queue_is_empty (&base->reorder_list));
1865 self->gop.cur_frame_index = 0;
1868 frame = _enc_frame (gst_frame);
1869 frame->poc = self->gop.cur_frame_index;
1870 g_assert (self->gop.cur_frame_index <= self->gop.max_pic_order_cnt);
1872 if (self->gop.cur_frame_index == 0) {
1873 g_assert (frame->poc == 0);
1874 GST_LOG_OBJECT (self, "system_frame_number: %d, an IDR frame, starts"
1875 " a new GOP", gst_frame->system_frame_number);
1877 g_queue_clear_full (&base->ref_list,
1878 (GDestroyNotify) gst_video_codec_frame_unref);
1881 frame->type = self->gop.frame_types[self->gop.cur_frame_index].slice_type;
1882 frame->is_ref = self->gop.frame_types[self->gop.cur_frame_index].is_ref;
1883 frame->pyramid_level =
1884 self->gop.frame_types[self->gop.cur_frame_index].pyramid_level;
1885 frame->left_ref_poc_diff =
1886 self->gop.frame_types[self->gop.cur_frame_index].left_ref_poc_diff;
1887 frame->right_ref_poc_diff =
1888 self->gop.frame_types[self->gop.cur_frame_index].right_ref_poc_diff;
1890 if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (gst_frame)) {
1891 GST_DEBUG_OBJECT (self, "system_frame_number: %d, a force key frame,"
1892 " promote its type from %s to %s", gst_frame->system_frame_number,
1893 _h265_slice_type_name (frame->type),
1894 _h265_slice_type_name (GST_H265_I_SLICE));
1895 frame->type = GST_H265_I_SLICE;
1896 frame->is_ref = TRUE;
1899 GST_LOG_OBJECT (self, "Push frame, system_frame_number: %d, poc %d, "
1900 "frame type %s", gst_frame->system_frame_number, frame->poc,
1901 _h265_slice_type_name (frame->type));
1903 self->gop.cur_frame_index++;
1904 g_queue_push_tail (&base->reorder_list,
1905 gst_video_codec_frame_ref (gst_frame));
1908 /* ensure the last one a non-B and end the GOP. */
1909 if (last && self->gop.cur_frame_index < self->gop.idr_period) {
1910 GstVideoCodecFrame *last_frame;
1912 /* Ensure next push will start a new GOP. */
1913 self->gop.cur_frame_index = self->gop.idr_period;
1915 if (!g_queue_is_empty (&base->reorder_list)) {
1916 last_frame = g_queue_peek_tail (&base->reorder_list);
1917 frame = _enc_frame (last_frame);
1918 if (frame->type == GST_H265_B_SLICE) {
1919 frame->type = GST_H265_P_SLICE;
1920 frame->is_ref = TRUE;
1928 struct RefFramesCount
1935 _count_backward_ref_num (gpointer data, gpointer user_data)
1937 GstVaH265EncFrame *frame = _enc_frame (data);
1938 struct RefFramesCount *count = (struct RefFramesCount *) user_data;
1940 g_assert (frame->poc != count->poc);
1941 if (frame->poc > count->poc)
1945 static GstVideoCodecFrame *
1946 _h265_pop_pyramid_b_frame (GstVaH265Enc * self)
1948 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
1951 GstVaH265EncFrame *b_vaframe;
1952 GstVideoCodecFrame *b_frame;
1953 struct RefFramesCount count;
1955 g_assert (self->gop.backward_ref_num <= 2);
1960 /* Find the highest level with smallest poc. */
1961 for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
1962 GstVaH265EncFrame *vaf;
1963 GstVideoCodecFrame *f;
1965 f = g_queue_peek_nth (&base->reorder_list, i);
1969 b_vaframe = _enc_frame (b_frame);
1974 vaf = _enc_frame (f);
1975 if (b_vaframe->pyramid_level < vaf->pyramid_level) {
1982 if (b_vaframe->poc > vaf->poc) {
1990 /* Check whether its refs are already poped. */
1991 g_assert (b_vaframe->left_ref_poc_diff != 0);
1992 g_assert (b_vaframe->right_ref_poc_diff != 0);
1993 for (i = 0; i < g_queue_get_length (&base->reorder_list); i++) {
1994 GstVaH265EncFrame *vaf;
1995 GstVideoCodecFrame *f;
1997 f = g_queue_peek_nth (&base->reorder_list, i);
2002 vaf = _enc_frame (f);
2003 if (vaf->poc == b_vaframe->poc + b_vaframe->left_ref_poc_diff
2004 || vaf->poc == b_vaframe->poc + b_vaframe->right_ref_poc_diff) {
2012 /* Ensure we already have backward refs */
2014 count.poc = b_vaframe->poc;
2015 g_queue_foreach (&base->ref_list, (GFunc) _count_backward_ref_num, &count);
2016 if (count.num >= 1) {
2017 GstVideoCodecFrame *f;
2019 /* it will unref at pop_frame */
2020 f = g_queue_pop_nth (&base->reorder_list, index);
2021 g_assert (f == b_frame);
2030 _h265_pop_one_frame (GstVaBaseEnc * base, GstVideoCodecFrame ** out_frame)
2032 GstVaH265Enc *self = GST_VA_H265_ENC (base);
2033 GstVaH265EncFrame *vaframe;
2034 GstVideoCodecFrame *frame;
2035 struct RefFramesCount count;
2037 g_return_val_if_fail (self->gop.cur_frame_index <= self->gop.idr_period,
2042 if (g_queue_is_empty (&base->reorder_list))
2045 /* Return the last pushed non-B immediately. */
2046 frame = g_queue_peek_tail (&base->reorder_list);
2047 vaframe = _enc_frame (frame);
2048 if (vaframe->type != GST_H265_B_SLICE) {
2049 frame = g_queue_pop_tail (&base->reorder_list);
2053 if (self->gop.b_pyramid) {
2054 frame = _h265_pop_pyramid_b_frame (self);
2061 g_assert (self->gop.backward_ref_num > 0);
2063 /* If GOP end, pop anyway. */
2064 if (self->gop.cur_frame_index == self->gop.idr_period) {
2065 frame = g_queue_pop_head (&base->reorder_list);
2069 /* Ensure we already have enough backward refs */
2070 frame = g_queue_peek_head (&base->reorder_list);
2071 vaframe = _enc_frame (frame);
2073 count.poc = vaframe->poc;
2074 g_queue_foreach (&base->ref_list, _count_backward_ref_num, &count);
2075 if (count.num >= self->gop.backward_ref_num) {
2076 frame = g_queue_pop_head (&base->reorder_list);
2083 vaframe = _enc_frame (frame);
2085 if (vaframe->poc == 0)
2086 self->gop.total_idr_count++;
2088 if (self->gop.b_pyramid && vaframe->type == GST_H265_B_SLICE) {
2089 GST_LOG_OBJECT (self, "pop a pyramid B frame with system_frame_number:"
2090 " %d, poc: %d, is_ref: %s, level %d",
2091 frame->system_frame_number, vaframe->poc,
2092 vaframe->is_ref ? "true" : "false", vaframe->pyramid_level);
2094 GST_LOG_OBJECT (self, "pop a frame with system_frame_number: %d,"
2095 " frame type: %s, poc: %d, is_ref: %s",
2096 frame->system_frame_number, _h265_slice_type_name (vaframe->type),
2097 vaframe->poc, vaframe->is_ref ? "true" : "false");
2100 /* unref frame popped from queue or pyramid b_frame */
2101 gst_video_codec_frame_unref (frame);
2107 gst_va_h265_enc_reorder_frame (GstVaBaseEnc * base, GstVideoCodecFrame * frame,
2108 gboolean bump_all, GstVideoCodecFrame ** out_frame)
2110 if (!_h265_push_one_frame (base, frame, bump_all)) {
2111 GST_ERROR_OBJECT (base, "Failed to push the input frame"
2112 " system_frame_number: %d into the reorder list",
2113 frame->system_frame_number);
2119 if (!_h265_pop_one_frame (base, out_frame)) {
2120 GST_ERROR_OBJECT (base, "Failed to pop the frame from the reorder list");
2128 static GstVideoCodecFrame *
2129 _h265_find_unused_reference_frame (GstVaH265Enc * self,
2130 GstVaH265EncFrame * frame)
2132 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2133 GstVaH265EncFrame *b_vaframe;
2134 GstVideoCodecFrame *b_frame;
2137 /* We still have more space. */
2138 if (g_queue_get_length (&base->ref_list) < self->gop.num_ref_frames)
2141 /* Not b_pyramid, sliding window is enough. */
2142 if (!self->gop.b_pyramid)
2143 return g_queue_peek_head (&base->ref_list);
2145 /* Non-b ref frame, just pop the first one. */
2146 if (frame->type != GST_H265_B_SLICE)
2147 return g_queue_peek_head (&base->ref_list);
2149 /* Choose the B frame with lowest POC. */
2152 for (i = 0; i < g_queue_get_length (&base->ref_list); i++) {
2153 GstVideoCodecFrame *f;
2154 GstVaH265EncFrame *vaf;
2156 f = g_queue_peek_nth (&base->ref_list, i);
2157 vaf = _enc_frame (f);
2158 if (vaf->type != GST_H265_B_SLICE)
2162 g_assert (b_vaframe == NULL);
2168 g_assert (b_vaframe);
2169 g_assert (vaf->poc != b_vaframe->poc);
2170 if (vaf->poc < b_vaframe->poc) {
2176 /* No B frame as ref. */
2178 return g_queue_peek_head (&base->ref_list);
2180 if (b_frame != g_queue_peek_head (&base->ref_list)) {
2181 b_vaframe = _enc_frame (b_frame);
2182 GST_LOG_OBJECT (self, "The frame with POC: %d will be"
2183 " replaced by the frame with POC: %d explicitly",
2184 b_vaframe->poc, frame->poc);
2191 _sort_by_poc (gconstpointer a, gconstpointer b, gpointer user_data)
2193 GstVaH265EncFrame *frame1 = _enc_frame ((GstVideoCodecFrame *) a);
2194 GstVaH265EncFrame *frame2 = _enc_frame ((GstVideoCodecFrame *) b);
2196 g_assert (frame1->poc != frame2->poc);
2198 return frame1->poc - frame2->poc;
2201 static GstFlowReturn
2202 gst_va_h265_enc_encode_frame (GstVaBaseEnc * base,
2203 GstVideoCodecFrame * gst_frame, gboolean is_last)
2205 GstVaH265Enc *self = GST_VA_H265_ENC (base);
2206 GstVaH265EncFrame *frame;
2207 GstVideoCodecFrame *unused_ref;
2209 frame = _enc_frame (gst_frame);
2210 frame->last_frame = is_last;
2212 g_assert (frame->picture == NULL);
2213 frame->picture = gst_va_encode_picture_new (base->encoder,
2214 gst_frame->input_buffer);
2216 if (!frame->picture) {
2217 GST_ERROR_OBJECT (base, "Failed to create the encode picture");
2218 return GST_FLOW_ERROR;
2221 if (!_h265_encode_one_frame (self, gst_frame)) {
2222 GST_ERROR_OBJECT (base, "Failed to encode the frame");
2223 return GST_FLOW_ERROR;
2226 g_queue_push_tail (&base->output_list, gst_video_codec_frame_ref (gst_frame));
2228 if (frame->is_ref) {
2229 unused_ref = _h265_find_unused_reference_frame (self, frame);
2232 if (!g_queue_remove (&base->ref_list, unused_ref))
2233 g_assert_not_reached ();
2235 gst_video_codec_frame_unref (unused_ref);
2238 /* Add it into the reference list. */
2239 g_queue_push_tail (&base->ref_list, gst_video_codec_frame_ref (gst_frame));
2240 g_queue_sort (&base->ref_list, _sort_by_poc, NULL);
2242 g_assert (g_queue_get_length (&base->ref_list) <= self->gop.num_ref_frames);
2248 /* Clear all the info of last reconfig and set the fields based on
2249 * property. The reconfig may change these fields because of the
2250 * profile/level and HW limitation. */
2252 gst_va_h265_enc_reset_state (GstVaBaseEnc * base)
2254 GstVaH265Enc *self = GST_VA_H265_ENC (base);
2256 GST_VA_BASE_ENC_CLASS (parent_class)->reset_state (base);
2258 GST_OBJECT_LOCK (self);
2259 self->features.use_trellis = self->prop.use_trellis;
2260 self->aud = self->prop.aud;
2261 self->num_slices = self->prop.num_slices;
2262 self->gop.idr_period = self->prop.key_int_max;
2263 self->gop.num_bframes = self->prop.num_bframes;
2264 self->gop.b_pyramid = self->prop.b_pyramid;
2265 self->gop.num_iframes = self->prop.num_iframes;
2266 self->gop.num_ref_frames = self->prop.num_ref_frames;
2267 self->rc.rc_ctrl_mode = self->prop.rc_ctrl;
2268 self->rc.min_qp = self->prop.min_qp;
2269 self->rc.max_qp = self->prop.max_qp;
2270 self->rc.qp_i = self->prop.qp_i;
2271 self->rc.qp_p = self->prop.qp_p;
2272 self->rc.qp_b = self->prop.qp_b;
2273 self->rc.mbbrc = self->prop.mbbrc;
2274 self->rc.target_percentage = self->prop.target_percentage;
2275 self->rc.target_usage = self->prop.target_usage;
2276 self->rc.cpb_size = self->prop.cpb_size;
2277 GST_OBJECT_UNLOCK (self);
2279 self->level_idc = 0;
2280 self->level_str = NULL;
2282 self->tier_flag = FALSE;
2284 self->min_coding_block_size = 0;
2285 self->ctu_width = 0;
2286 self->ctu_height = 0;
2287 self->luma_width = 0;
2288 self->luma_height = 0;
2289 self->conformance_window_flag = FALSE;
2290 self->conf_win_left_offset = 0;
2291 self->conf_win_right_offset = 0;
2292 self->conf_win_top_offset = 0;
2293 self->conf_win_bottom_offset = 0;
2295 self->bits_depth_luma_minus8 = 0;
2296 self->bits_depth_chroma_minus8 = 0;
2298 self->packed_headers = 0;
2300 self->features.log2_min_luma_coding_block_size_minus3 = 0;
2301 self->features.log2_diff_max_min_luma_coding_block_size = 0;
2302 self->features.log2_diff_max_min_luma_coding_block_size = 0;
2303 self->features.log2_min_transform_block_size_minus2 = 0;
2304 self->features.log2_diff_max_min_transform_block_size = 0;
2305 self->features.max_transform_hierarchy_depth_inter = 0;
2306 self->features.max_transform_hierarchy_depth_intra = 0;
2307 self->features.separate_colour_plane_flag = FALSE;
2308 self->features.colour_plane_id = 0;
2309 self->features.scaling_list_enabled_flag = FALSE;
2310 self->features.scaling_list_data_present_flag = FALSE;
2311 self->features.amp_enabled_flag = FALSE;
2312 self->features.sample_adaptive_offset_enabled_flag = FALSE;
2313 self->features.slice_sao_luma_flag = FALSE;
2314 self->features.slice_sao_chroma_flag = FALSE;
2315 self->features.pcm_enabled_flag = FALSE;
2316 self->features.pcm_sample_bit_depth_luma_minus1 = 0;
2317 self->features.pcm_sample_bit_depth_chroma_minus1 = 0;
2318 self->features.log2_min_pcm_luma_coding_block_size_minus3 = 0;
2319 self->features.log2_max_pcm_luma_coding_block_size_minus3 = 0;
2320 self->features.temporal_mvp_enabled_flag = FALSE;
2321 self->features.collocated_from_l0_flag = FALSE;
2322 self->features.collocated_ref_idx = 0xFF;
2323 self->features.strong_intra_smoothing_enabled_flag = FALSE;
2324 self->features.dependent_slice_segment_flag = FALSE;
2325 self->features.sign_data_hiding_enabled_flag = FALSE;
2326 self->features.constrained_intra_pred_flag = FALSE;
2327 self->features.transform_skip_enabled_flag = FALSE;
2328 self->features.cu_qp_delta_enabled_flag = FALSE;
2329 self->features.diff_cu_qp_delta_depth = 0;
2330 self->features.weighted_pred_flag = FALSE;
2331 self->features.weighted_bipred_flag = FALSE;
2332 self->features.transquant_bypass_enabled_flag = FALSE;
2334 self->gop.i_period = 0;
2335 self->gop.total_idr_count = 0;
2336 self->gop.ip_period = 0;
2337 self->gop.low_delay_b_mode = FALSE;
2338 self->gop.highest_pyramid_level = 0;
2339 memset (self->gop.frame_types, 0, sizeof (self->gop.frame_types));
2340 self->gop.cur_frame_index = 0;
2341 self->gop.max_pic_order_cnt = 0;
2342 self->gop.log2_max_pic_order_cnt = 0;
2343 /* VAEncPictureParameterBufferHEVC.reference_frames limit 15 refs */
2344 self->gop.max_l0_num = 0;
2345 self->gop.max_l1_num = 0;
2346 self->gop.forward_ref_num = 0;
2347 self->gop.backward_ref_num = 0;
2348 self->gop.num_reorder_frames = 0;
2349 self->gop.max_dpb_size = 0;
2351 self->rc.max_bitrate = 0;
2352 self->rc.target_bitrate = 0;
2353 self->rc.max_bitrate_bits = 0;
2354 self->rc.target_bitrate_bits = 0;
2355 self->rc.cpb_length_bits = 0;
2357 memset (&self->vps_hdr, 0, sizeof (GstH265VPS));
2358 memset (&self->sps_hdr, 0, sizeof (GstH265SPS));
2362 _h265_get_rtformat (GstVaH265Enc * self, GstVideoFormat format)
2366 chroma = gst_va_chroma_from_video_format (format);
2368 /* Check whether the rtformat is supported. */
2369 if (chroma != VA_RT_FORMAT_YUV420) {
2370 GST_ERROR_OBJECT (self, "Unsupported chroma for video format: %s",
2371 gst_video_format_to_string (format));
2379 _h265_decide_profile (GstVaH265Enc * self, VAProfile * _profile,
2382 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2383 gboolean ret = FALSE;
2384 GstVideoFormat in_format;
2387 GstCaps *allowed_caps = NULL;
2388 guint num_structures, i;
2389 GstStructure *structure;
2390 const GValue *v_profile;
2391 GPtrArray *candidates = NULL;
2392 gchar *profile_name;
2394 candidates = g_ptr_array_new_with_free_func (g_free);
2396 /* First, check whether the downstream requires a specified profile. */
2397 allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (base));
2399 allowed_caps = gst_pad_query_caps (GST_VIDEO_ENCODER_SRC_PAD (base), NULL);
2401 if (allowed_caps && !gst_caps_is_empty (allowed_caps)) {
2402 num_structures = gst_caps_get_size (allowed_caps);
2403 for (i = 0; i < num_structures; i++) {
2404 structure = gst_caps_get_structure (allowed_caps, i);
2405 v_profile = gst_structure_get_value (structure, "profile");
2409 if (G_VALUE_HOLDS_STRING (v_profile)) {
2410 profile_name = g_strdup (g_value_get_string (v_profile));
2411 g_ptr_array_add (candidates, profile_name);
2412 } else if (GST_VALUE_HOLDS_LIST (v_profile)) {
2415 for (j = 0; j < gst_value_list_get_size (v_profile); j++) {
2416 const GValue *p = gst_value_list_get_value (v_profile, j);
2420 profile_name = g_strdup (g_value_get_string (p));
2421 g_ptr_array_add (candidates, profile_name);
2427 if (candidates->len == 0) {
2428 GST_ERROR_OBJECT (self, "No available profile in caps");
2433 in_format = GST_VIDEO_INFO_FORMAT (&base->input_state->info);
2434 rt_format = _h265_get_rtformat (self, in_format);
2436 GST_ERROR_OBJECT (self, "unsupported video format %s",
2437 gst_video_format_to_string (in_format));
2442 /* Find the suitable profile by features and check the HW
2445 /* Just use the first HW available profile and disable features if
2447 profile_name = NULL;
2448 for (i = 0; i < candidates->len; i++) {
2449 profile_name = g_ptr_array_index (candidates, i);
2450 profile = gst_va_profile_from_name (HEVC, profile_name);
2451 if (profile == VAProfileNone)
2454 if (!gst_va_encoder_has_profile (base->encoder, profile))
2457 if ((rt_format & gst_va_encoder_get_rtformat (base->encoder,
2458 profile, GST_VA_BASE_ENC_ENTRYPOINT (base))) == 0)
2461 *_profile = profile;
2462 *_rt_format = rt_format;
2471 g_clear_pointer (&candidates, g_ptr_array_unref);
2472 g_clear_pointer (&allowed_caps, gst_caps_unref);
2475 GST_INFO_OBJECT (self, "Select the profile %s",
2476 gst_va_profile_name (profile));
2478 GST_ERROR_OBJECT (self, "Failed to find an available profile");
2484 #define update_property(type, obj, old_val, new_val, prop_id) \
2485 gst_va_base_enc_update_property_##type (obj, old_val, new_val, properties[prop_id])
2486 #define update_property_uint(obj, old_val, new_val, prop_id) \
2487 update_property (uint, obj, old_val, new_val, prop_id)
2488 #define update_property_bool(obj, old_val, new_val, prop_id) \
2489 update_property (bool, obj, old_val, new_val, prop_id)
2492 _h265_validate_parameters (GstVaH265Enc * self)
2494 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2497 /* Ensure the num_slices provided by the user not exceed the limit
2498 * of the number of slices permitted by the stream and by the
2500 g_assert (self->num_slices >= 1);
2501 max_slices = gst_va_encoder_get_max_slice_num (base->encoder,
2502 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
2503 if (self->num_slices > max_slices)
2504 self->num_slices = max_slices;
2506 /* The stream size limit. */
2507 if (self->num_slices > ((self->ctu_width * self->ctu_height + 1) / 2))
2508 self->num_slices = ((self->ctu_width * self->ctu_height + 1) / 2);
2510 update_property_uint (base, &self->prop.num_slices, self->num_slices,
2513 /* Ensure trellis. */
2514 if (self->features.use_trellis &&
2515 !gst_va_encoder_has_trellis (base->encoder, base->profile,
2516 GST_VA_BASE_ENC_ENTRYPOINT (base))) {
2517 GST_INFO_OBJECT (self, "The trellis is not supported");
2518 self->features.use_trellis = FALSE;
2521 update_property_bool (base, &self->prop.use_trellis,
2522 self->features.use_trellis, PROP_TRELLIS);
2525 /* Normalizes bitrate (and CPB size) for HRD conformance */
2527 _h265_calculate_bitrate_hrd (GstVaH265Enc * self)
2529 guint bitrate_bits, cpb_bits_size;
2531 /* Round down bitrate. This is a hard limit mandated by the user */
2532 g_assert (SX_BITRATE >= 6);
2533 bitrate_bits = (self->rc.max_bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
2534 GST_DEBUG_OBJECT (self, "Max bitrate: %u bits/sec", bitrate_bits);
2535 self->rc.max_bitrate_bits = bitrate_bits;
2537 bitrate_bits = (self->rc.target_bitrate * 1000) & ~((1U << SX_BITRATE) - 1);
2538 GST_DEBUG_OBJECT (self, "Target bitrate: %u bits/sec", bitrate_bits);
2539 self->rc.target_bitrate_bits = bitrate_bits;
2541 if (self->rc.cpb_size > 0 && self->rc.cpb_size < (self->rc.max_bitrate / 2)) {
2542 GST_INFO_OBJECT (self, "Too small cpb_size: %d", self->rc.cpb_size);
2543 self->rc.cpb_size = 0;
2546 if (self->rc.cpb_size == 0) {
2547 /* We cache 2 second coded data by default. */
2548 self->rc.cpb_size = self->rc.max_bitrate * 2;
2549 GST_INFO_OBJECT (self, "Adjust cpb_size to: %d", self->rc.cpb_size);
2552 /* Round up CPB size. This is an HRD compliance detail */
2553 g_assert (SX_CPB_SIZE >= 4);
2554 cpb_bits_size = (self->rc.cpb_size * 1000) & ~((1U << SX_CPB_SIZE) - 1);
2556 GST_DEBUG_OBJECT (self, "HRD CPB size: %u bits", cpb_bits_size);
2557 self->rc.cpb_length_bits = cpb_bits_size;
2560 /* Estimates a good enough bitrate if none was supplied */
2562 _h265_ensure_rate_control (GstVaH265Enc * self)
2564 /* User can specify the properties of: "bitrate", "target-percentage",
2565 * "max-qp", "min-qp", "qpi", "qpp", "qpb", "mbbrc", "cpb-size",
2566 * "rate-control" and "target-usage" to control the RC behavior.
2568 * "target-usage" is different from the others, it controls the encoding
2569 * speed and quality, while the others control encoding bit rate and
2570 * quality. The lower value has better quality(maybe bigger MV search
2571 * range) but slower speed, the higher value has faster speed but lower
2574 * The possible composition to control the bit rate and quality:
2576 * 1. CQP mode: "rate-control=cqp", then "qpi", "qpp" and "qpb"
2577 * specify the QP of I/P/B frames respectively(within the
2578 * "max-qp" and "min-qp" range). The QP will not change during
2579 * the whole stream. Other properties are ignored.
2581 * 2. CBR mode: "rate-control=CBR", then the "bitrate" specify the
2582 * target bit rate and the "cpb-size" specifies the max coded
2583 * picture buffer size to avoid overflow. If the "bitrate" is not
2584 * set, it is calculated by the picture resolution and frame
2585 * rate. If "cpb-size" is not set, it is set to the size of
2586 * caching 2 second coded data. Encoder will try its best to make
2587 * the QP with in the ["max-qp", "min-qp"] range. "mbbrc" can
2588 * enable bit rate control in macro block level. Other paramters
2591 * 3. VBR mode: "rate-control=VBR", then the "bitrate" specify the
2592 * target bit rate, "target-percentage" is used to calculate the
2593 * max bit rate of VBR mode by ("bitrate" * 100) /
2594 * "target-percentage". It is also used by driver to calculate
2595 * the min bit rate. The "cpb-size" specifies the max coded
2596 * picture buffer size to avoid overflow. If the "bitrate" is not
2597 * set, the target bit rate will be calculated by the picture
2598 * resolution and frame rate. Encoder will try its best to make
2599 * the QP with in the ["max-qp", "min-qp"] range. "mbbrc" can
2600 * enable bit rate control in macro block level. Other paramters
2603 * 4. VCM mode: "rate-control=VCM", then the "bitrate" specify the
2604 * target bit rate, and encoder will try its best to make the QP
2605 * with in the ["max-qp", "min-qp"] range. Other paramters are
2609 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2611 guint32 rc_mode, quality_level, rc_ctrl;
2613 quality_level = gst_va_encoder_get_quality_level (base->encoder,
2614 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
2615 if (self->rc.target_usage > quality_level) {
2616 GST_INFO_OBJECT (self, "User setting target-usage: %d is not supported, "
2617 "fallback to %d", self->rc.target_usage, quality_level);
2618 self->rc.target_usage = quality_level;
2619 update_property_uint (base, &self->prop.target_usage,
2620 self->rc.target_usage, PROP_TARGET_USAGE);
2623 GST_OBJECT_LOCK (self);
2624 rc_ctrl = self->prop.rc_ctrl;
2625 GST_OBJECT_UNLOCK (self);
2627 if (rc_ctrl != VA_RC_NONE) {
2628 rc_mode = gst_va_encoder_get_rate_control_mode (base->encoder,
2629 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
2630 if (!(rc_mode & rc_ctrl)) {
2632 G_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL])->default_value;
2633 GST_INFO_OBJECT (self, "The rate control mode %s is not supported, "
2634 "fallback to %s mode", _rate_control_get_name (rc_ctrl),
2635 _rate_control_get_name (defval));
2636 self->rc.rc_ctrl_mode = defval;
2637 update_property_uint (base, &self->prop.rc_ctrl,
2638 self->rc.rc_ctrl_mode, PROP_RATE_CONTROL);
2641 self->rc.rc_ctrl_mode = VA_RC_NONE;
2644 if (self->rc.min_qp > self->rc.max_qp) {
2645 GST_INFO_OBJECT (self, "The min_qp %d is bigger than the max_qp %d, "
2646 "set it to the max_qp", self->rc.min_qp, self->rc.max_qp);
2647 self->rc.min_qp = self->rc.max_qp;
2649 update_property_uint (base, &self->prop.min_qp, self->rc.min_qp,
2653 /* Make all the qp in the valid range */
2654 if (self->rc.qp_i < self->rc.min_qp) {
2655 if (self->rc.qp_i != 26)
2656 GST_INFO_OBJECT (self, "The qp_i %d is smaller than the min_qp %d, "
2657 "set it to the min_qp", self->rc.qp_i, self->rc.min_qp);
2658 self->rc.qp_i = self->rc.min_qp;
2660 if (self->rc.qp_i > self->rc.max_qp) {
2661 if (self->rc.qp_i != 26)
2662 GST_INFO_OBJECT (self, "The qp_i %d is bigger than the max_qp %d, "
2663 "set it to the max_qp", self->rc.qp_i, self->rc.max_qp);
2664 self->rc.qp_i = self->rc.max_qp;
2667 if (self->rc.qp_p < self->rc.min_qp) {
2668 if (self->rc.qp_p != 26)
2669 GST_INFO_OBJECT (self, "The qp_p %d is smaller than the min_qp %d, "
2670 "set it to the min_qp", self->rc.qp_p, self->rc.min_qp);
2671 self->rc.qp_p = self->rc.min_qp;
2673 if (self->rc.qp_p > self->rc.max_qp) {
2674 if (self->rc.qp_p != 26)
2675 GST_INFO_OBJECT (self, "The qp_p %d is bigger than the max_qp %d, "
2676 "set it to the max_qp", self->rc.qp_p, self->rc.max_qp);
2677 self->rc.qp_p = self->rc.max_qp;
2680 if (self->rc.qp_b < self->rc.min_qp) {
2681 if (self->rc.qp_b != 26)
2682 GST_INFO_OBJECT (self, "The qp_b %d is smaller than the min_qp %d, "
2683 "set it to the min_qp", self->rc.qp_b, self->rc.min_qp);
2684 self->rc.qp_b = self->rc.min_qp;
2686 if (self->rc.qp_b > self->rc.max_qp) {
2687 if (self->rc.qp_b != 26)
2688 GST_INFO_OBJECT (self, "The qp_b %d is bigger than the max_qp %d, "
2689 "set it to the max_qp", self->rc.qp_b, self->rc.max_qp);
2690 self->rc.qp_b = self->rc.max_qp;
2693 GST_OBJECT_LOCK (self);
2694 bitrate = self->prop.bitrate;
2695 GST_OBJECT_UNLOCK (self);
2697 /* Calculate a bitrate is not set. */
2698 if ((self->rc.rc_ctrl_mode == VA_RC_CBR || self->rc.rc_ctrl_mode == VA_RC_VBR
2699 || self->rc.rc_ctrl_mode == VA_RC_VCM) && bitrate == 0) {
2700 /* FIXME: Provide better estimation. */
2701 /* Just Using a 1/6 compression ratio, 12 bits per pixel for YUV420.
2702 TODO: Other video format. */
2705 factor = (guint64) self->luma_width * self->luma_height * 12 / 6;
2706 bitrate = gst_util_uint64_scale (factor,
2707 GST_VIDEO_INFO_FPS_N (&base->input_state->info),
2708 GST_VIDEO_INFO_FPS_D (&base->input_state->info)) / 1000;
2710 GST_INFO_OBJECT (self, "target bitrate computed to %u kbps", bitrate);
2713 /* Adjust the setting based on RC mode. */
2714 switch (self->rc.rc_ctrl_mode) {
2717 self->rc.max_bitrate = 0;
2718 self->rc.target_bitrate = 0;
2719 self->rc.target_percentage = 0;
2720 self->rc.cpb_size = 0;
2723 self->rc.max_bitrate = bitrate;
2724 self->rc.target_bitrate = bitrate;
2725 self->rc.target_percentage = 100;
2726 self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
2729 g_assert (self->rc.target_percentage >= 10);
2730 self->rc.max_bitrate = (guint) gst_util_uint64_scale_int (bitrate,
2731 100, self->rc.target_percentage);
2732 self->rc.target_bitrate = bitrate;
2733 self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
2736 self->rc.max_bitrate = bitrate;
2737 self->rc.target_bitrate = bitrate;
2738 self->rc.target_percentage = 0;
2739 self->rc.qp_i = self->rc.qp_p = self->rc.qp_b = 26;
2740 self->rc.cpb_size = 0;
2742 if (self->gop.num_bframes > 0) {
2743 GST_INFO_OBJECT (self, "VCM mode just support I/P mode, no B frame");
2744 self->gop.num_bframes = 0;
2745 self->gop.b_pyramid = FALSE;
2749 GST_WARNING_OBJECT (self, "Unsupported rate control");
2754 GST_DEBUG_OBJECT (self, "Max bitrate: %u bits/sec, "
2755 "Target bitrate: %u bits/sec", self->rc.max_bitrate,
2756 self->rc.target_bitrate);
2758 if (self->rc.rc_ctrl_mode != VA_RC_NONE && self->rc.rc_ctrl_mode != VA_RC_CQP)
2759 _h265_calculate_bitrate_hrd (self);
2762 update_property_uint (base, &self->prop.min_qp, self->rc.min_qp, PROP_MIN_QP);
2763 update_property_uint (base, &self->prop.cpb_size,
2764 self->rc.cpb_size, PROP_CPB_SIZE);
2765 update_property_uint (base, &self->prop.target_percentage,
2766 self->rc.target_percentage, PROP_TARGET_PERCENTAGE);
2767 update_property_uint (base, &self->prop.qp_i, self->rc.qp_i, PROP_QP_I);
2768 update_property_uint (base, &self->prop.qp_p, self->rc.qp_p, PROP_QP_P);
2769 update_property_uint (base, &self->prop.qp_b, self->rc.qp_b, PROP_QP_B);
2774 /* Derives the level and tier from the currently set limits */
2776 _h265_calculate_tier_level (GstVaH265Enc * self)
2778 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
2779 guint i, PicSizeInSamplesY, LumaSr;
2780 guint32 tier_max_bitrate;
2782 PicSizeInSamplesY = self->luma_width * self->luma_height;
2783 LumaSr = gst_util_uint64_scale_int_ceil (PicSizeInSamplesY,
2784 GST_VIDEO_INFO_FPS_N (&base->input_state->info),
2785 GST_VIDEO_INFO_FPS_D (&base->input_state->info));
2787 for (i = 0; i < G_N_ELEMENTS (_va_h265_level_limits); i++) {
2788 const GstVaH265LevelLimits *const limits = &_va_h265_level_limits[i];
2790 /* Choose level by luma picture size and luma sample rate */
2791 if (PicSizeInSamplesY <= limits->MaxLumaPs && LumaSr <= limits->MaxLumaSr)
2795 if (i == G_N_ELEMENTS (_va_h265_level_limits))
2796 goto error_unsupported_level;
2798 self->level_idc = _va_h265_level_limits[i].level_idc;
2799 self->level_str = _va_h265_level_limits[i].level_name;
2800 self->min_cr = _va_h265_level_limits[i].MinCr;
2802 if (self->rc.rc_ctrl_mode == VA_RC_CQP) {
2803 g_assert (self->rc.max_bitrate == 0);
2805 /* We may need to calculate some max bit rate for CQP mode.
2806 Just set the main tier now. */
2807 self->tier_flag = FALSE;
2809 if (_va_h265_level_limits[i].MaxBRTierHigh == 0 ||
2810 self->rc.max_bitrate <= _va_h265_level_limits[i].MaxBRTierMain) {
2811 self->tier_flag = FALSE;
2813 self->tier_flag = TRUE;
2817 tier_max_bitrate = self->tier_flag ? _va_h265_level_limits[i].MaxBRTierHigh :
2818 _va_h265_level_limits[i].MaxBRTierMain;
2820 if (self->rc.max_bitrate > tier_max_bitrate) {
2821 GST_INFO_OBJECT (self, "The max bitrate of the stream is %u kbps, still"
2822 " larger than %s profile %s level %s tier's max bit rate %d kbps",
2823 self->rc.max_bitrate, gst_va_profile_name (base->profile),
2824 _va_h265_level_limits[i].level_name,
2825 (self->tier_flag ? "high" : "main"), tier_max_bitrate);
2828 GST_DEBUG_OBJECT (self, "profile: %s, level: %s, tier :%s, MinCr: %d",
2829 gst_va_profile_name (base->profile), _va_h265_level_limits[i].level_name,
2830 (self->tier_flag ? "high" : "main"), self->min_cr);
2834 error_unsupported_level:
2836 GST_ERROR_OBJECT (self,
2837 "failed to find a suitable level matching codec config");
2845 gint left_ref_poc_diff;
2846 gint right_ref_poc_diff;
2850 _set_pyramid_info (struct PyramidInfo *info, guint len,
2851 guint current_level, guint highest_level)
2855 g_assert (len >= 1);
2857 if (current_level == highest_level || len == 1) {
2858 for (index = 0; index < len; index++) {
2859 info[index].level = current_level;
2860 info[index].left_ref_poc_diff = -(index + 1);
2861 info[index].right_ref_poc_diff = len - index;
2868 info[index].level = current_level;
2869 info[index].left_ref_poc_diff = -(index + 1);
2870 info[index].right_ref_poc_diff = len - index;
2875 _set_pyramid_info (info, index, current_level, highest_level);
2877 if (index + 1 < len)
2878 _set_pyramid_info (&info[index + 1], len - (index + 1),
2879 current_level, highest_level);
2883 _h265_create_gop_frame_types (GstVaH265Enc * self)
2886 guint i_frames = self->gop.num_iframes;
2887 struct PyramidInfo pyramid_info[31] = { 0, };
2889 if (self->gop.highest_pyramid_level > 0) {
2890 g_assert (self->gop.num_bframes > 0);
2891 _set_pyramid_info (pyramid_info, self->gop.num_bframes,
2892 0, self->gop.highest_pyramid_level);
2895 g_assert (self->gop.idr_period <= MAX_GOP_SIZE);
2896 for (i = 0; i < self->gop.idr_period; i++) {
2898 self->gop.frame_types[i].slice_type = GST_H265_I_SLICE;
2899 self->gop.frame_types[i].is_ref = TRUE;
2903 /* Intra only stream. */
2904 if (self->gop.ip_period == 0) {
2905 self->gop.frame_types[i].slice_type = GST_H265_I_SLICE;
2906 self->gop.frame_types[i].is_ref = FALSE;
2910 if (i % self->gop.ip_period) {
2911 guint pyramid_index =
2912 i % self->gop.ip_period - 1 /* The first P or IDR */ ;
2914 self->gop.frame_types[i].slice_type = GST_H265_B_SLICE;
2915 self->gop.frame_types[i].pyramid_level =
2916 pyramid_info[pyramid_index].level;
2917 self->gop.frame_types[i].is_ref =
2918 (self->gop.frame_types[i].pyramid_level <
2919 self->gop.highest_pyramid_level);
2920 self->gop.frame_types[i].left_ref_poc_diff =
2921 pyramid_info[pyramid_index].left_ref_poc_diff;
2922 self->gop.frame_types[i].right_ref_poc_diff =
2923 pyramid_info[pyramid_index].right_ref_poc_diff;
2927 if (self->gop.i_period && i % self->gop.i_period == 0 && i_frames > 0) {
2928 /* Replace P with I. */
2929 self->gop.frame_types[i].slice_type = GST_H265_I_SLICE;
2930 self->gop.frame_types[i].is_ref = TRUE;
2935 self->gop.frame_types[i].slice_type = GST_H265_P_SLICE;
2936 self->gop.frame_types[i].is_ref = TRUE;
2939 /* Force the last one to be a P */
2940 if (self->gop.idr_period > 1 && self->gop.ip_period > 0) {
2941 self->gop.frame_types[self->gop.idr_period - 1].slice_type =
2943 self->gop.frame_types[self->gop.idr_period - 1].is_ref = TRUE;
2948 _h265_print_gop_structure (GstVaH265Enc * self)
2950 #ifndef GST_DISABLE_GST_DEBUG
2954 if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) < GST_LEVEL_INFO)
2957 str = g_string_new (NULL);
2959 g_string_append_printf (str, "[ ");
2961 for (i = 0; i < self->gop.idr_period; i++) {
2963 g_string_append_printf (str, "IDR");
2966 g_string_append_printf (str, ", ");
2969 if (self->gop.low_delay_b_mode &&
2970 self->gop.frame_types[i].slice_type == GST_H265_P_SLICE) {
2971 g_string_append_printf (str, "%s", "LDB");
2973 g_string_append_printf (str, "%s",
2974 _h265_slice_type_name (self->gop.frame_types[i].slice_type));
2977 if (self->gop.b_pyramid
2978 && self->gop.frame_types[i].slice_type == GST_H265_B_SLICE) {
2979 g_string_append_printf (str, "<L%d (%d, %d)>",
2980 self->gop.frame_types[i].pyramid_level,
2981 self->gop.frame_types[i].left_ref_poc_diff,
2982 self->gop.frame_types[i].right_ref_poc_diff);
2985 if (self->gop.frame_types[i].is_ref) {
2986 g_string_append_printf (str, "(ref)");
2991 g_string_append_printf (str, " ]");
2993 GST_INFO_OBJECT (self, "GOP size: %d, forward reference %d, backward"
2994 " reference %d, GOP structure: %s", self->gop.idr_period,
2995 self->gop.forward_ref_num, self->gop.backward_ref_num, str->str);
2997 g_string_free (str, TRUE);
3002 _h265_calculate_coded_size (GstVaH265Enc * self)
3004 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3005 /* FIXME: Using only a rough approximation for bitstream headers.
3006 * Not taken into account: ScalingList, RefPicListModification,
3007 * PredWeightTable, which is not used now. */
3008 /* Calculate the maximum sizes for common headers (in bits) */
3009 guint codedbuf_size = 0;
3011 /* Account for VPS header */
3012 codedbuf_size += 4 /* start code */ + GST_ROUND_UP_8 (MAX_VPS_HDR_SIZE +
3013 MAX_PROFILE_TIER_LEVEL_SIZE + MAX_HRD_PARAMS_SIZE) / 8;
3015 /* Account for SPS header */
3016 codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_SPS_HDR_SIZE +
3017 MAX_PROFILE_TIER_LEVEL_SIZE + 64 * MAX_SHORT_TERM_REFPICSET_SIZE +
3018 MAX_VUI_PARAMS_SIZE + MAX_HRD_PARAMS_SIZE) / 8;
3020 /* Account for PPS header */
3021 codedbuf_size += 4 + GST_ROUND_UP_8 (MAX_PPS_HDR_SIZE) / 8;
3023 /* Account for slice header */
3024 codedbuf_size += self->num_slices * (4 +
3025 GST_ROUND_UP_8 (MAX_SLICE_HDR_SIZE + MAX_SHORT_TERM_REFPICSET_SIZE) / 8);
3027 /* TODO: Only YUV 4:2:0 formats are supported for now.
3028 more video format to check. */
3030 (self->luma_width * self->luma_height * 3 / 2) / self->min_cr;
3032 base->codedbuf_size = codedbuf_size;
3033 GST_INFO_OBJECT (self, "Calculate codedbuf size: %u", base->codedbuf_size);
3036 /* Get log2_max_frame_num_minus4, log2_max_pic_order_cnt_lsb_minus4
3037 * value, shall be in the range of 0 to 12, inclusive. */
3039 _get_log2_max_num (guint num)
3048 /* shall be in the range of 0+4 to 12+4, inclusive. */
3051 } else if (ret > 16) {
3057 /* Consider the idr_period, num_bframes, L0/L1 reference number.
3058 * TODO: Load some preset fixed GOP structure.
3059 * TODO: Skip this if in lookahead mode. */
3061 _h265_generate_gop_structure (GstVaH265Enc * self)
3063 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3064 guint32 log2_max_frame_num;
3065 guint32 list0, list1, forward_num, backward_num, gop_ref_num;
3067 guint32 prediction_direction;
3069 /* If not set, generate a idr every second */
3070 if (self->gop.idr_period == 0) {
3071 self->gop.idr_period = (GST_VIDEO_INFO_FPS_N (&base->input_state->info)
3072 + GST_VIDEO_INFO_FPS_D (&base->input_state->info) - 1) /
3073 GST_VIDEO_INFO_FPS_D (&base->input_state->info);
3076 /* Do not use a too huge GOP size. */
3077 if (self->gop.idr_period > 1024) {
3078 self->gop.idr_period = 1024;
3079 GST_INFO_OBJECT (self, "Lowering the GOP size to %d", self->gop.idr_period);
3082 update_property_uint (base, &self->prop.key_int_max, self->gop.idr_period,
3085 /* Prefer have more than 1 refs for the GOP which is not very small. */
3086 if (self->gop.idr_period > 8) {
3087 if (self->gop.num_bframes > (self->gop.idr_period - 1) / 2) {
3088 self->gop.num_bframes = (self->gop.idr_period - 1) / 2;
3089 GST_INFO_OBJECT (self, "Lowering the number of num_bframes to %d",
3090 self->gop.num_bframes);
3093 /* beign and end should be ref */
3094 if (self->gop.num_bframes > self->gop.idr_period - 1 - 1) {
3095 if (self->gop.idr_period > 1) {
3096 self->gop.num_bframes = self->gop.idr_period - 1 - 1;
3098 self->gop.num_bframes = 0;
3100 GST_INFO_OBJECT (self, "Lowering the number of num_bframes to %d",
3101 self->gop.num_bframes);
3105 if (!gst_va_encoder_get_max_num_reference (base->encoder, base->profile,
3106 GST_VA_BASE_ENC_ENTRYPOINT (base), &list0, &list1)) {
3107 GST_INFO_OBJECT (self, "Failed to get the max num reference");
3111 self->gop.max_l0_num = list0;
3112 self->gop.max_l1_num = list1;
3113 GST_DEBUG_OBJECT (self, "list0 num: %d, list1 num: %d",
3114 self->gop.max_l0_num, self->gop.max_l1_num);
3116 forward_num = list0;
3117 backward_num = list1;
3119 prediction_direction = gst_va_encoder_get_prediction_direction (base->encoder,
3120 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base));
3121 if (prediction_direction) {
3122 #if VA_CHECK_VERSION(1,9,0)
3123 if (!(prediction_direction & VA_PREDICTION_DIRECTION_PREVIOUS)) {
3124 GST_INFO_OBJECT (self, "No forward prediction support");
3126 /* Only backward ref is insane. */
3130 if (!(prediction_direction & VA_PREDICTION_DIRECTION_FUTURE)) {
3131 GST_INFO_OBJECT (self, "No backward prediction support");
3135 if (prediction_direction & VA_PREDICTION_DIRECTION_BI_NOT_EMPTY) {
3136 if (self->gop.max_l1_num == 0) {
3137 GST_INFO_OBJECT (self, "Not possible to support "
3138 "VA_PREDICTION_DIRECTION_BI_NOT_EMPTY while list1 is 0");
3141 GST_INFO_OBJECT (self, "Enable low-delay-b mode");
3142 self->gop.low_delay_b_mode = TRUE;
3147 if (forward_num > self->gop.num_ref_frames)
3148 forward_num = self->gop.num_ref_frames;
3149 if (backward_num > self->gop.num_ref_frames)
3150 backward_num = self->gop.num_ref_frames;
3152 if (forward_num == 0) {
3153 GST_INFO_OBJECT (self,
3154 "No reference support, fallback to intra only stream");
3156 /* It does not make sense that if only the list1 exists. */
3157 self->gop.num_ref_frames = 0;
3159 self->gop.ip_period = 0;
3160 self->gop.num_bframes = 0;
3161 self->gop.b_pyramid = FALSE;
3162 self->gop.highest_pyramid_level = 0;
3163 self->gop.num_iframes = self->gop.idr_period - 1 /* The idr */ ;
3164 self->gop.forward_ref_num = 0;
3165 self->gop.backward_ref_num = 0;
3169 if (self->gop.num_ref_frames <= 1) {
3170 GST_INFO_OBJECT (self, "The number of reference frames is only %d,"
3171 " no B frame allowed, fallback to I/P mode", self->gop.num_ref_frames);
3172 self->gop.num_bframes = 0;
3176 /* b_pyramid needs at least 1 ref for B, besides the I/P */
3177 if (self->gop.b_pyramid && self->gop.num_ref_frames <= 2) {
3178 GST_INFO_OBJECT (self, "The number of reference frames is only %d,"
3179 " not enough for b_pyramid", self->gop.num_ref_frames);
3180 self->gop.b_pyramid = FALSE;
3183 if (backward_num == 0 && self->gop.num_bframes > 0) {
3184 GST_INFO_OBJECT (self,
3185 "No hw reference support for list 1, fallback to I/P mode");
3186 self->gop.num_bframes = 0;
3187 self->gop.b_pyramid = FALSE;
3190 /* I/P mode, no list1 needed. */
3191 if (self->gop.num_bframes == 0)
3194 /* Not enough B frame, no need for b_pyramid. */
3195 if (self->gop.num_bframes <= 1)
3196 self->gop.b_pyramid = FALSE;
3198 if (self->gop.num_ref_frames > forward_num + backward_num) {
3199 self->gop.num_ref_frames = forward_num + backward_num;
3200 GST_INFO_OBJECT (self, "HW limits, lowering the number of reference"
3201 " frames to %d", self->gop.num_ref_frames);
3203 self->gop.num_ref_frames = MIN (self->gop.num_ref_frames, 15);
3205 /* How many possible refs within a GOP. */
3206 gop_ref_num = (self->gop.idr_period + self->gop.num_bframes) /
3207 (self->gop.num_bframes + 1);
3209 if (self->gop.num_bframes > 0
3210 /* frame_num % (self->gop.num_bframes + 1) happens to be the end P */
3211 && (self->gop.idr_period % (self->gop.num_bframes + 1) != 1))
3214 /* Adjust reference num based on B frames and B pyramid. */
3215 if (self->gop.num_bframes == 0) {
3216 self->gop.b_pyramid = FALSE;
3217 self->gop.forward_ref_num = self->gop.num_ref_frames;
3218 self->gop.backward_ref_num = 0;
3219 } else if (self->gop.b_pyramid) {
3220 guint b_frames = self->gop.num_bframes;
3223 /* set b pyramid one backward ref. */
3224 self->gop.backward_ref_num = 1;
3225 self->gop.forward_ref_num =
3226 self->gop.num_ref_frames - self->gop.backward_ref_num;
3227 if (self->gop.forward_ref_num > forward_num)
3228 self->gop.forward_ref_num = forward_num;
3230 /* Balance the forward and backward refs */
3231 if ((self->gop.forward_ref_num > self->gop.backward_ref_num * 3)
3232 && backward_num > 1) {
3233 self->gop.backward_ref_num++;
3235 self->gop.forward_ref_num =
3236 self->gop.num_ref_frames - self->gop.backward_ref_num;
3237 if (self->gop.forward_ref_num > forward_num)
3238 self->gop.forward_ref_num = forward_num;
3241 b_frames = b_frames / 2;
3244 /* At least 1 B ref for each level, plus begin and end 2 P/I */
3246 if (b_refs + 2 > self->gop.num_ref_frames)
3249 self->gop.highest_pyramid_level++;
3250 b_frames = b_frames / 2;
3253 GST_INFO_OBJECT (self, "pyramid level is %d",
3254 self->gop.highest_pyramid_level);
3256 /* We prefer list0. Backward refs have more latency. */
3257 self->gop.backward_ref_num = 1;
3258 self->gop.forward_ref_num =
3259 self->gop.num_ref_frames - self->gop.backward_ref_num;
3260 /* Balance the forward and backward refs, but not cause a big latency. */
3261 while ((self->gop.num_bframes * self->gop.backward_ref_num <= 16)
3262 && (self->gop.backward_ref_num <= gop_ref_num)
3263 && (self->gop.backward_ref_num < backward_num)
3264 && (self->gop.forward_ref_num / self->gop.backward_ref_num > 4)) {
3265 self->gop.forward_ref_num--;
3266 self->gop.backward_ref_num++;
3269 if (self->gop.forward_ref_num > forward_num)
3270 self->gop.forward_ref_num = forward_num;
3273 /* It's OK, keep slots for GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME frame. */
3274 if (self->gop.forward_ref_num > gop_ref_num)
3275 GST_DEBUG_OBJECT (self, "num_ref_frames %d is bigger than gop_ref_num %d",
3276 self->gop.forward_ref_num, gop_ref_num);
3278 /* Include the ref picture itself. */
3279 self->gop.ip_period = 1 + self->gop.num_bframes;
3281 p_frames = gop_ref_num - 1 /* IDR */ ;
3284 if (self->gop.num_iframes > p_frames) {
3285 self->gop.num_iframes = p_frames;
3286 GST_INFO_OBJECT (self, "Too many I frames insertion, lowering it to %d",
3287 self->gop.num_iframes);
3290 if (self->gop.num_iframes > 0) {
3291 guint total_i_frames = self->gop.num_iframes + 1 /* IDR */ ;
3292 self->gop.i_period =
3293 (gop_ref_num / total_i_frames) * (self->gop.num_bframes + 1);
3297 /* init max_frame_num, max_poc */
3298 log2_max_frame_num = _get_log2_max_num (self->gop.idr_period);
3299 self->gop.log2_max_pic_order_cnt = log2_max_frame_num;
3300 self->gop.max_pic_order_cnt = 1 << self->gop.log2_max_pic_order_cnt;
3301 self->gop.num_reorder_frames = self->gop.b_pyramid ?
3302 self->gop.highest_pyramid_level * 2 + 1 /* the last P frame. */ :
3303 self->gop.backward_ref_num;
3304 /* Should not exceed the max ref num. */
3305 self->gop.num_reorder_frames =
3306 MIN (self->gop.num_reorder_frames, self->gop.num_ref_frames);
3307 self->gop.num_reorder_frames = MIN (self->gop.num_reorder_frames, 16);
3308 self->gop.max_dpb_size = self->gop.num_ref_frames + 1;
3310 _h265_create_gop_frame_types (self);
3311 _h265_print_gop_structure (self);
3314 update_property_uint (base, &self->prop.num_ref_frames,
3315 self->gop.num_ref_frames, PROP_NUM_REF_FRAMES);
3316 update_property_uint (base, &self->prop.num_iframes,
3317 self->gop.num_iframes, PROP_IFRAMES);
3318 update_property_uint (base, &self->prop.num_bframes,
3319 self->gop.num_bframes, PROP_BFRAMES);
3320 update_property_bool (base, &self->prop.b_pyramid,
3321 self->gop.b_pyramid, PROP_B_PYRAMID);
3327 _h265_init_packed_headers (GstVaH265Enc * self)
3329 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3330 guint32 packed_headers;
3331 guint32 desired_packed_headers = VA_ENC_PACKED_HEADER_SEQUENCE /* SPS */
3332 | VA_ENC_PACKED_HEADER_PICTURE /* PPS */
3333 | VA_ENC_PACKED_HEADER_SLICE /* Slice headers */
3334 | VA_ENC_PACKED_HEADER_RAW_DATA; /* SEI, AUD, etc. */
3336 self->packed_headers = 0;
3338 if (!gst_va_encoder_get_packed_headers (base->encoder, base->profile,
3339 GST_VA_BASE_ENC_ENTRYPOINT (base), &packed_headers))
3342 if (desired_packed_headers & ~packed_headers) {
3343 GST_INFO_OBJECT (self, "Driver does not support some wanted packed headers "
3344 "(wanted %#x, found %#x)", desired_packed_headers, packed_headers);
3347 self->packed_headers = desired_packed_headers & packed_headers;
3353 _get_chroma_format_idc (guint va_chroma)
3355 guint chroma_format_idc;
3357 switch (va_chroma) {
3358 case VA_RT_FORMAT_YUV400:
3359 chroma_format_idc = 0;
3361 case VA_RT_FORMAT_YUV420:
3362 case VA_RT_FORMAT_YUV420_10:
3363 case VA_RT_FORMAT_YUV420_12:
3364 chroma_format_idc = 1;
3366 case VA_RT_FORMAT_YUV422:
3367 case VA_RT_FORMAT_YUV422_10:
3368 case VA_RT_FORMAT_YUV422_12:
3369 chroma_format_idc = 2;
3371 case VA_RT_FORMAT_YUV444:
3372 case VA_RT_FORMAT_YUV444_10:
3373 case VA_RT_FORMAT_YUV444_12:
3374 chroma_format_idc = 3;
3377 GST_WARNING ("unsupported VA chroma value");
3378 chroma_format_idc = 1;
3382 return chroma_format_idc;
3386 _h265_init_mvp (GstVaH265Enc * self, gboolean enable)
3389 /* For the simplicity, we only let MVP refer to List0[0],
3390 which is the last ref frame before the current frame. */
3391 self->features.temporal_mvp_enabled_flag = TRUE;
3392 self->features.collocated_from_l0_flag = TRUE;
3393 self->features.collocated_ref_idx = 0;
3395 self->features.temporal_mvp_enabled_flag = FALSE;
3396 self->features.collocated_from_l0_flag = FALSE;
3397 self->features.collocated_ref_idx = 0xff;
3401 /* We need to decide the profile and entrypoint before call this.
3402 It applies the optimized features provided by the va driver. */
3404 _h265_setup_encoding_features (GstVaH265Enc * self)
3406 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3408 #if VA_CHECK_VERSION(1, 13, 0)
3409 VAConfigAttribValEncHEVCFeatures features;
3411 VAConfigAttrib attrib = {.type = VAConfigAttribEncHEVCFeatures };
3413 status = vaGetConfigAttributes (gst_va_display_get_va_dpy (base->display),
3414 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base), &attrib, 1);
3415 if (status != VA_STATUS_SUCCESS) {
3416 GST_INFO_OBJECT (self, "Failed to query encoding features: %s",
3417 vaErrorStr (status));
3418 goto default_options;
3421 if (attrib.value == VA_ATTRIB_NOT_SUPPORTED) {
3422 GST_INFO_OBJECT (self, "Driver does not support query encoding features");
3423 goto default_options;
3426 features.value = attrib.value;
3428 /* We do not enable this no matter what the driver say. */
3429 self->features.separate_colour_plane_flag = FALSE;
3430 self->features.colour_plane_id = 0;
3432 /* We do not enable scaling_list now. */
3433 self->features.scaling_list_enabled_flag = FALSE;
3434 self->features.scaling_list_data_present_flag = FALSE;
3436 self->features.amp_enabled_flag = (features.bits.amp != 0);
3438 self->features.sample_adaptive_offset_enabled_flag = (features.bits.sao != 0);
3439 self->features.slice_sao_luma_flag = (features.bits.sao != 0);
3440 self->features.slice_sao_chroma_flag = (features.bits.sao != 0);
3442 self->features.pcm_enabled_flag = (features.bits.pcm != 0);
3443 if (!self->features.pcm_enabled_flag) {
3444 self->features.pcm_sample_bit_depth_luma_minus1 = 0;
3445 self->features.pcm_sample_bit_depth_chroma_minus1 = 0;
3446 self->features.log2_min_pcm_luma_coding_block_size_minus3 = 0;
3447 self->features.log2_max_pcm_luma_coding_block_size_minus3 = 0;
3449 self->features.pcm_sample_bit_depth_luma_minus1 =
3450 self->bits_depth_luma_minus8 + 8 - 1;
3451 self->features.pcm_sample_bit_depth_chroma_minus1 =
3452 self->bits_depth_chroma_minus8 + 8 - 1;
3453 /* log2_min_pcm_luma_coding_block_size_minus3 and
3454 log2_diff_max_min_pcm_luma_coding_block_size set
3455 in coding_block_size */
3457 self->features.pcm_loop_filter_disabled_flag = FALSE;
3459 _h265_init_mvp (self, features.bits.temporal_mvp != 0);
3461 self->features.strong_intra_smoothing_enabled_flag =
3462 (features.bits.strong_intra_smoothing != 0);
3464 /* TODO: dependent slice */
3465 self->features.dependent_slice_segment_flag = FALSE;
3467 self->features.sign_data_hiding_enabled_flag =
3468 (features.bits.sign_data_hiding != 0);
3470 self->features.constrained_intra_pred_flag =
3471 (features.bits.constrained_intra_pred != 0);
3473 self->features.transform_skip_enabled_flag =
3474 (features.bits.transform_skip != 0);
3476 self->features.cu_qp_delta_enabled_flag =
3477 (self->rc.rc_ctrl_mode != VA_RC_CQP);
3478 self->features.diff_cu_qp_delta_depth = features.bits.cu_qp_delta;
3480 /* TODO: use weighted pred */
3481 self->features.weighted_pred_flag = FALSE;
3482 self->features.weighted_bipred_flag = FALSE;
3484 self->features.transquant_bypass_enabled_flag =
3485 (features.bits.transquant_bypass != 0);
3491 GST_DEBUG_OBJECT (self, "Apply default setting for features");
3493 self->features.separate_colour_plane_flag = FALSE;
3494 self->features.colour_plane_id = 0;
3495 self->features.scaling_list_enabled_flag = FALSE;
3496 self->features.scaling_list_data_present_flag = FALSE;
3497 self->features.amp_enabled_flag = TRUE;
3498 self->features.sample_adaptive_offset_enabled_flag = FALSE;
3499 self->features.slice_sao_luma_flag = FALSE;
3500 self->features.slice_sao_chroma_flag = FALSE;
3501 self->features.pcm_enabled_flag = 0;
3502 self->features.pcm_sample_bit_depth_luma_minus1 = 0;
3503 self->features.pcm_sample_bit_depth_chroma_minus1 = 0;
3504 self->features.log2_min_pcm_luma_coding_block_size_minus3 = 0;
3505 self->features.log2_max_pcm_luma_coding_block_size_minus3 = 0;
3506 self->features.pcm_loop_filter_disabled_flag = FALSE;
3507 _h265_init_mvp (self, TRUE);
3508 self->features.strong_intra_smoothing_enabled_flag = TRUE;
3509 self->features.dependent_slice_segment_flag = FALSE;
3510 self->features.sign_data_hiding_enabled_flag = FALSE;
3511 self->features.constrained_intra_pred_flag = FALSE;
3512 self->features.transform_skip_enabled_flag = TRUE;
3513 self->features.cu_qp_delta_enabled_flag =
3514 (self->rc.rc_ctrl_mode != VA_RC_CQP);
3515 self->features.diff_cu_qp_delta_depth = 0;
3516 self->features.weighted_pred_flag = FALSE;
3517 self->features.weighted_bipred_flag = FALSE;
3518 self->features.transquant_bypass_enabled_flag = FALSE;
3520 #if VA_CHECK_VERSION(1, 13, 0)
3523 GST_DEBUG_OBJECT (self, "Set features to: "
3524 "separate_colour_plane_flag = %d, "
3525 "colour_plane_id = %d, "
3526 "scaling_list_enabled_flag = %d, "
3527 "scaling_list_data_present_flag = %d, "
3528 "amp_enabled_flag = %d, "
3529 "sample_adaptive_offset_enabled_flag = %d, "
3530 "slice_sao_luma_flag = %d, "
3531 "slice_sao_chroma_flag = %d, "
3532 "pcm_enabled_flag = %d, "
3533 "pcm_sample_bit_depth_luma_minus1 = %d, "
3534 "pcm_sample_bit_depth_chroma_minus1 = %d, "
3535 "log2_min_pcm_luma_coding_block_size_minus3 = %d, "
3536 "log2_max_pcm_luma_coding_block_size_minus3 = %d, "
3537 "pcm_loop_filter_disabled_flag = %d, "
3538 "temporal_mvp_enabled_flag = %d, "
3539 "collocated_from_l0_flag = %d, "
3540 "collocated_ref_idx = %d, "
3541 "strong_intra_smoothing_enabled_flag = %d, "
3542 "dependent_slice_segment_flag = %d, "
3543 "sign_data_hiding_enabled_flag = %d, "
3544 "constrained_intra_pred_flag = %d, "
3545 "transform_skip_enabled_flag = %d, "
3546 "cu_qp_delta_enabled_flag = %d, "
3547 "diff_cu_qp_delta_depth = %d, "
3548 "weighted_pred_flag = %d, "
3549 "weighted_bipred_flag = %d, "
3550 "transquant_bypass_enabled_flag = %d",
3551 self->features.separate_colour_plane_flag,
3552 self->features.colour_plane_id,
3553 self->features.scaling_list_enabled_flag,
3554 self->features.scaling_list_data_present_flag,
3555 self->features.amp_enabled_flag,
3556 self->features.sample_adaptive_offset_enabled_flag,
3557 self->features.slice_sao_luma_flag,
3558 self->features.slice_sao_chroma_flag,
3559 self->features.pcm_enabled_flag,
3560 self->features.pcm_sample_bit_depth_luma_minus1,
3561 self->features.pcm_sample_bit_depth_chroma_minus1,
3562 self->features.log2_min_pcm_luma_coding_block_size_minus3,
3563 self->features.log2_max_pcm_luma_coding_block_size_minus3,
3564 self->features.pcm_loop_filter_disabled_flag,
3565 self->features.temporal_mvp_enabled_flag,
3566 self->features.collocated_from_l0_flag,
3567 self->features.collocated_ref_idx,
3568 self->features.strong_intra_smoothing_enabled_flag,
3569 self->features.dependent_slice_segment_flag,
3570 self->features.sign_data_hiding_enabled_flag,
3571 self->features.constrained_intra_pred_flag,
3572 self->features.transform_skip_enabled_flag,
3573 self->features.cu_qp_delta_enabled_flag,
3574 self->features.diff_cu_qp_delta_depth,
3575 self->features.weighted_pred_flag,
3576 self->features.weighted_bipred_flag,
3577 self->features.transquant_bypass_enabled_flag);
3580 /* We need to decide the profile and entrypoint before call this.
3581 It applies the optimized block size(coding and tranform) provided
3582 by the va driver. */
3584 _h265_set_coding_block_size (GstVaH265Enc * self)
3586 #if VA_CHECK_VERSION(1, 13, 0)
3587 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
3589 VAConfigAttribValEncHEVCBlockSizes block_size;
3591 VAConfigAttrib attrib = {.type = VAConfigAttribEncHEVCBlockSizes };
3593 status = vaGetConfigAttributes (gst_va_display_get_va_dpy (base->display),
3594 base->profile, GST_VA_BASE_ENC_ENTRYPOINT (base), &attrib, 1);
3595 if (status != VA_STATUS_SUCCESS) {
3596 GST_INFO_OBJECT (self, "Failed to query coding block size: %s",
3597 vaErrorStr (status));
3598 goto default_setting;
3601 if (attrib.value == VA_ATTRIB_NOT_SUPPORTED) {
3602 GST_INFO_OBJECT (self, "Driver does not support query"
3603 " coding block size");
3604 goto default_setting;
3607 block_size.value = attrib.value;
3609 /* We always choose the biggest coding block size and the biggest
3610 hierarchy depth to achieve the best compression result.
3611 TODO: May choose smaller value when fast encoding is needed. */
3613 if (block_size.bits.log2_min_luma_coding_block_size_minus3 >
3614 block_size.bits.log2_max_coding_tree_block_size_minus3) {
3615 GST_WARNING_OBJECT (self, "Invalid log2_min_luma_coding_block_size_minus3:"
3616 " %d, bigger than log2_max_coding_tree_block_size_minus3: %d",
3617 block_size.bits.log2_min_luma_coding_block_size_minus3,
3618 block_size.bits.log2_max_coding_tree_block_size_minus3);
3619 goto default_setting;
3621 if (block_size.bits.log2_min_luma_coding_block_size_minus3 >
3622 block_size.bits.log2_min_coding_tree_block_size_minus3) {
3623 GST_WARNING_OBJECT (self, "Invalid log2_min_luma_coding_block_size_minus3:"
3624 " %d, bigger than log2_min_coding_tree_block_size_minus3: %d",
3625 block_size.bits.log2_min_luma_coding_block_size_minus3,
3626 block_size.bits.log2_min_coding_tree_block_size_minus3);
3627 block_size.bits.log2_min_coding_tree_block_size_minus3 =
3628 block_size.bits.log2_min_luma_coding_block_size_minus3;
3632 1 << (block_size.bits.log2_max_coding_tree_block_size_minus3 + 3);
3633 self->min_coding_block_size =
3634 1 << (block_size.bits.log2_min_luma_coding_block_size_minus3 + 3);
3635 self->features.log2_min_luma_coding_block_size_minus3 =
3636 block_size.bits.log2_min_luma_coding_block_size_minus3;
3637 self->features.log2_diff_max_min_luma_coding_block_size =
3638 block_size.bits.log2_max_coding_tree_block_size_minus3 -
3639 block_size.bits.log2_min_luma_coding_block_size_minus3;
3641 if (block_size.bits.log2_min_luma_transform_block_size_minus2 >
3642 block_size.bits.log2_max_luma_transform_block_size_minus2) {
3643 GST_WARNING_OBJECT (self, "Invalid"
3644 " log2_min_luma_transform_block_size_minus2: %d, bigger"
3645 " than log2_max_luma_transform_block_size_minus2: %d",
3646 block_size.bits.log2_min_luma_transform_block_size_minus2,
3647 block_size.bits.log2_max_luma_transform_block_size_minus2);
3648 goto default_setting;
3650 self->features.log2_min_transform_block_size_minus2 =
3651 block_size.bits.log2_min_luma_transform_block_size_minus2;
3652 self->features.log2_diff_max_min_transform_block_size =
3653 block_size.bits.log2_max_luma_transform_block_size_minus2 -
3654 block_size.bits.log2_min_luma_transform_block_size_minus2;
3656 self->features.max_transform_hierarchy_depth_inter =
3657 block_size.bits.max_max_transform_hierarchy_depth_inter;
3658 self->features.max_transform_hierarchy_depth_intra =
3659 block_size.bits.max_max_transform_hierarchy_depth_intra;
3661 /* For PCM setting later. */
3662 self->features.log2_min_pcm_luma_coding_block_size_minus3 =
3663 block_size.bits.log2_min_pcm_coding_block_size_minus3;
3664 self->features.log2_max_pcm_luma_coding_block_size_minus3 =
3665 block_size.bits.log2_max_pcm_coding_block_size_minus3;
3667 if (self->features.log2_max_pcm_luma_coding_block_size_minus3 -
3668 self->features.log2_min_pcm_luma_coding_block_size_minus3 >
3669 self->features.log2_diff_max_min_luma_coding_block_size) {
3670 GST_WARNING_OBJECT (self, "Invalid"
3671 " log2_diff_max_min_pcm_luma_coding_block_size: %d",
3672 self->features.log2_max_pcm_luma_coding_block_size_minus3
3673 - self->features.log2_min_pcm_luma_coding_block_size_minus3);
3674 self->features.log2_max_pcm_luma_coding_block_size_minus3 = 0;
3675 self->features.log2_min_pcm_luma_coding_block_size_minus3 = 0;
3683 GST_DEBUG_OBJECT (self, "Apply default setting for coding block");
3685 /* choose some conservative value */
3686 self->ctu_size = 32;
3687 self->min_coding_block_size = 8;
3688 self->features.log2_min_luma_coding_block_size_minus3 = 0;
3689 self->features.log2_diff_max_min_luma_coding_block_size = 2;
3691 self->features.log2_min_transform_block_size_minus2 = 0;
3692 self->features.log2_diff_max_min_transform_block_size = 3;
3693 self->features.max_transform_hierarchy_depth_inter = 2;
3694 self->features.max_transform_hierarchy_depth_intra = 2;
3695 self->features.pcm_sample_bit_depth_luma_minus1 = 0;
3696 self->features.pcm_sample_bit_depth_chroma_minus1 = 0;
3697 /* Default PCM is disabled. */
3698 self->features.log2_min_pcm_luma_coding_block_size_minus3 = 0;
3699 self->features.log2_max_pcm_luma_coding_block_size_minus3 = 0;
3701 #if VA_CHECK_VERSION(1, 13, 0)
3704 GST_DEBUG_OBJECT (self, "Set coding block size to: "
3705 "log2_min_luma_coding_block_size_minus3: %d, "
3706 "log2_diff_max_min_luma_coding_block_size: %d, "
3707 "log2_min_transform_block_size_minus2: %d, "
3708 "log2_diff_max_min_transform_block_size: %d, "
3709 "max_transform_hierarchy_depth_inter: %d, "
3710 "max_transform_hierarchy_depth_intra: %d",
3711 self->features.log2_min_luma_coding_block_size_minus3,
3712 self->features.log2_diff_max_min_luma_coding_block_size,
3713 self->features.log2_min_transform_block_size_minus2,
3714 self->features.log2_diff_max_min_transform_block_size,
3715 self->features.max_transform_hierarchy_depth_inter,
3716 self->features.max_transform_hierarchy_depth_intra);
3720 gst_va_h265_enc_reconfig (GstVaBaseEnc * base)
3722 GstVideoEncoder *venc = GST_VIDEO_ENCODER (base);
3723 GstVaH265Enc *self = GST_VA_H265_ENC (base);
3724 GstCaps *out_caps, *reconf_caps = NULL;;
3725 GstVideoCodecState *output_state = NULL;
3726 GstVideoFormat format, reconf_format = GST_VIDEO_FORMAT_UNKNOWN;
3727 VAProfile profile = VAProfileNone;
3728 gboolean do_renegotiation = TRUE, do_reopen, need_negotiation;
3729 guint max_ref_frames, max_surfaces = 0, rt_format = 0, codedbuf_size;
3732 width = GST_VIDEO_INFO_WIDTH (&base->input_state->info);
3733 height = GST_VIDEO_INFO_HEIGHT (&base->input_state->info);
3734 format = GST_VIDEO_INFO_FORMAT (&base->input_state->info);
3735 codedbuf_size = base->codedbuf_size;
3738 !gst_va_encoder_get_reconstruct_pool_config (base->encoder, &reconf_caps,
3740 if (!need_negotiation && reconf_caps) {
3742 if (!gst_video_info_from_caps (&vi, reconf_caps))
3744 reconf_format = GST_VIDEO_INFO_FORMAT (&vi);
3747 if (!_h265_decide_profile (self, &profile, &rt_format))
3751 do_reopen = !(base->profile == profile && base->rt_format == rt_format
3752 && format == reconf_format && width == base->width
3753 && height == base->height && self->prop.rc_ctrl == self->rc.rc_ctrl_mode);
3755 if (do_reopen && gst_va_encoder_is_open (base->encoder))
3756 gst_va_encoder_close (base->encoder);
3758 gst_va_base_enc_reset_state (base);
3760 base->profile = profile;
3761 base->rt_format = rt_format;
3762 base->width = width;
3763 base->height = height;
3765 self->luma_width = GST_ROUND_UP_16 (base->width);
3766 self->luma_height = GST_ROUND_UP_16 (base->height);
3768 /* Frame Cropping */
3769 if ((base->width & 15) || (base->height & 15)) {
3770 /* 6.1, Table 6-1 */
3771 static const guint SubWidthC[] = { 1, 2, 2, 1 };
3772 static const guint SubHeightC[] = { 1, 2, 1, 1 };
3773 guint index = _get_chroma_format_idc (gst_va_chroma_from_video_format
3774 (GST_VIDEO_INFO_FORMAT (&base->input_state->info)));
3776 self->conformance_window_flag = 1;
3777 self->conf_win_left_offset = 0;
3778 self->conf_win_right_offset =
3779 (self->luma_width - base->width) / SubWidthC[index];
3780 self->conf_win_top_offset = 0;
3781 self->conf_win_bottom_offset =
3782 (self->luma_height - base->height) / SubHeightC[index];
3785 _h265_set_coding_block_size (self);
3787 self->ctu_width = (self->luma_width + self->ctu_size - 1) / self->ctu_size;
3788 self->ctu_height = (self->luma_height + self->ctu_size - 1) / self->ctu_size;
3789 if (self->ctu_width == 0 || self->ctu_height == 0)
3792 self->bits_depth_luma_minus8 =
3793 GST_VIDEO_FORMAT_INFO_DEPTH (base->input_state->info.finfo, 0);
3794 self->bits_depth_luma_minus8 -= 8;
3796 if (GST_VIDEO_FORMAT_INFO_N_COMPONENTS (base->input_state->info.finfo)) {
3797 self->bits_depth_chroma_minus8 =
3798 GST_VIDEO_FORMAT_INFO_DEPTH (base->input_state->info.finfo, 1);
3799 if (self->bits_depth_chroma_minus8 <
3800 GST_VIDEO_FORMAT_INFO_DEPTH (base->input_state->info.finfo, 2))
3801 self->bits_depth_chroma_minus8 =
3802 GST_VIDEO_FORMAT_INFO_DEPTH (base->input_state->info.finfo, 2);
3804 self->bits_depth_chroma_minus8 -= 8;
3806 self->bits_depth_chroma_minus8 = 0;
3809 /* Frame rate is needed for rate control and PTS setting. */
3810 if (GST_VIDEO_INFO_FPS_N (&base->input_state->info) == 0
3811 || GST_VIDEO_INFO_FPS_D (&base->input_state->info) == 0) {
3812 GST_INFO_OBJECT (self, "Unknown framerate, just set to 30 fps");
3813 GST_VIDEO_INFO_FPS_N (&base->input_state->info) = 30;
3814 GST_VIDEO_INFO_FPS_D (&base->input_state->info) = 1;
3816 base->frame_duration = gst_util_uint64_scale (GST_SECOND,
3817 GST_VIDEO_INFO_FPS_D (&base->input_state->info),
3818 GST_VIDEO_INFO_FPS_N (&base->input_state->info));
3820 GST_DEBUG_OBJECT (self, "resolution:%dx%d, CTU size: %dx%d,"
3821 " frame duration is %" GST_TIME_FORMAT,
3822 base->width, base->height, self->ctu_width, self->ctu_height,
3823 GST_TIME_ARGS (base->frame_duration));
3825 _h265_validate_parameters (self);
3827 if (!_h265_ensure_rate_control (self))
3830 if (!_h265_calculate_tier_level (self))
3833 if (!_h265_generate_gop_structure (self))
3836 _h265_setup_encoding_features (self);
3838 _h265_calculate_coded_size (self);
3840 if (!_h265_init_packed_headers (self))
3843 self->aud = self->aud && self->packed_headers & VA_ENC_PACKED_HEADER_RAW_DATA;
3844 update_property_bool (base, &self->prop.aud, self->aud, PROP_AUD);
3846 max_ref_frames = self->gop.num_ref_frames + 3 /* scratch frames */ ;
3848 /* second check after calculations */
3850 !(max_ref_frames == max_surfaces && codedbuf_size == base->codedbuf_size);
3851 if (do_reopen && gst_va_encoder_is_open (base->encoder))
3852 gst_va_encoder_close (base->encoder);
3854 if (!gst_va_encoder_is_open (base->encoder)
3855 && !gst_va_encoder_open (base->encoder, base->profile,
3856 format, base->rt_format, self->luma_width, self->luma_height,
3857 base->codedbuf_size, max_ref_frames, self->rc.rc_ctrl_mode,
3858 self->packed_headers)) {
3859 GST_ERROR_OBJECT (self, "Failed to open the VA encoder.");
3864 gst_va_base_enc_add_codec_tag (base, "H265");
3866 out_caps = gst_va_profile_caps (base->profile);
3867 g_assert (out_caps);
3868 out_caps = gst_caps_fixate (out_caps);
3870 if (self->level_str)
3871 gst_caps_set_simple (out_caps, "level", G_TYPE_STRING, self->level_str,
3874 gst_caps_set_simple (out_caps, "width", G_TYPE_INT, base->width,
3875 "height", G_TYPE_INT, base->height, "alignment", G_TYPE_STRING, "au",
3876 "stream-format", G_TYPE_STRING, "byte-stream", NULL);
3878 if (!need_negotiation) {
3879 output_state = gst_video_encoder_get_output_state (venc);
3880 do_renegotiation = TRUE;
3883 do_renegotiation = !gst_caps_is_subset (output_state->caps, out_caps);
3884 gst_video_codec_state_unref (output_state);
3887 if (!do_renegotiation) {
3888 gst_caps_unref (out_caps);
3893 GST_DEBUG_OBJECT (self, "output caps is %" GST_PTR_FORMAT, out_caps);
3896 gst_video_encoder_set_output_state (venc, out_caps, base->input_state);
3897 gst_video_codec_state_unref (output_state);
3899 if (!gst_video_encoder_negotiate (venc)) {
3900 GST_ERROR_OBJECT (self, "Failed to negotiate with the downstream");
3908 gst_va_h265_enc_flush (GstVideoEncoder * venc)
3910 GstVaH265Enc *self = GST_VA_H265_ENC (venc);
3912 /* begin from an IDR after flush. */
3913 self->gop.cur_frame_index = 0;
3915 return GST_VIDEO_ENCODER_CLASS (parent_class)->flush (venc);
3919 gst_va_h265_enc_new_frame (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
3921 GstVaH265EncFrame *frame_in;
3923 frame_in = gst_va_h265_enc_frame_new ();
3924 frame_in->total_frame_count = base->input_frame_count++;
3925 gst_video_codec_frame_set_user_data (frame, frame_in,
3926 gst_va_h265_enc_frame_free);
3932 gst_va_h265_enc_prepare_output (GstVaBaseEnc * base, GstVideoCodecFrame * frame)
3934 GstVaH265Enc *self = GST_VA_H265_ENC (base);
3935 GstVaH265EncFrame *frame_enc;
3937 frame_enc = _enc_frame (frame);
3940 base->start_pts + base->frame_duration * frame_enc->total_frame_count;
3941 /* The PTS should always be later than the DTS. */
3942 frame->dts = base->start_pts + base->frame_duration *
3943 ((gint64) base->output_frame_count -
3944 (gint64) self->gop.num_reorder_frames);
3945 base->output_frame_count++;
3946 frame->duration = base->frame_duration;
3950 static const gchar *sink_caps_str =
3951 GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_VA,
3953 GST_VIDEO_CAPS_MAKE ("{ NV12 }");
3956 static const gchar *src_caps_str = "video/x-h265";
3959 _register_debug_category (gpointer data)
3961 GST_DEBUG_CATEGORY_INIT (gst_va_h265enc_debug, "vah265enc", 0,
3968 gst_va_h265_enc_init (GTypeInstance * instance, gpointer g_class)
3970 GstVaH265Enc *self = GST_VA_H265_ENC (instance);
3972 /* default values */
3973 self->prop.key_int_max = 0;
3974 self->prop.num_bframes = 0;
3975 self->prop.num_iframes = 0;
3976 self->prop.num_ref_frames = 3;
3977 self->prop.b_pyramid = FALSE;
3978 self->prop.num_slices = 1;
3979 self->prop.min_qp = 1;
3980 self->prop.max_qp = 51;
3981 self->prop.qp_i = 26;
3982 self->prop.qp_p = 26;
3983 self->prop.qp_b = 26;
3984 self->prop.use_trellis = FALSE;
3985 self->prop.aud = FALSE;
3986 self->prop.mbbrc = 0;
3987 self->prop.bitrate = 0;
3988 self->prop.target_percentage = 66;
3989 self->prop.target_usage = 4;
3990 self->prop.cpb_size = 0;
3991 if (properties[PROP_RATE_CONTROL]) {
3992 self->prop.rc_ctrl =
3993 G_PARAM_SPEC_ENUM (properties[PROP_RATE_CONTROL])->default_value;
3995 self->prop.rc_ctrl = VA_RC_NONE;
4000 gst_va_h265_enc_set_property (GObject * object, guint prop_id,
4001 const GValue * value, GParamSpec * pspec)
4003 GstVaH265Enc *const self = GST_VA_H265_ENC (object);
4004 GstVaBaseEnc *base = GST_VA_BASE_ENC (self);
4005 gboolean already_effect = FALSE;
4007 GST_OBJECT_LOCK (self);
4010 case PROP_KEY_INT_MAX:
4011 self->prop.key_int_max = g_value_get_uint (value);
4014 self->prop.num_bframes = g_value_get_uint (value);
4017 self->prop.num_iframes = g_value_get_uint (value);
4019 case PROP_NUM_REF_FRAMES:
4020 self->prop.num_ref_frames = g_value_get_uint (value);
4022 case PROP_B_PYRAMID:
4023 self->prop.b_pyramid = g_value_get_boolean (value);
4025 case PROP_NUM_SLICES:
4026 self->prop.num_slices = g_value_get_uint (value);
4029 self->prop.min_qp = g_value_get_uint (value);
4032 self->prop.max_qp = g_value_get_uint (value);
4035 self->prop.qp_i = g_value_get_uint (value);
4036 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4037 already_effect = TRUE;
4040 self->prop.qp_p = g_value_get_uint (value);
4041 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4042 already_effect = TRUE;
4045 self->prop.qp_b = g_value_get_uint (value);
4046 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4047 already_effect = TRUE;
4050 self->prop.use_trellis = g_value_get_boolean (value);
4053 self->prop.aud = g_value_get_boolean (value);
4056 /* Macroblock-level rate control.
4059 * 2: always disable,
4060 * other: reserved. */
4061 switch (g_value_get_enum (value)) {
4062 case GST_VA_FEATURE_DISABLED:
4063 self->prop.mbbrc = 2;
4065 case GST_VA_FEATURE_ENABLED:
4066 self->prop.mbbrc = 1;
4068 case GST_VA_FEATURE_AUTO:
4069 self->prop.mbbrc = 0;
4075 self->prop.bitrate = g_value_get_uint (value);
4076 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4077 already_effect = TRUE;
4079 case PROP_TARGET_PERCENTAGE:
4080 self->prop.target_percentage = g_value_get_uint (value);
4081 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4082 already_effect = TRUE;
4084 case PROP_TARGET_USAGE:
4085 self->prop.target_usage = g_value_get_uint (value);
4086 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4087 already_effect = TRUE;
4089 case PROP_RATE_CONTROL:
4090 self->prop.rc_ctrl = g_value_get_enum (value);
4091 g_atomic_int_set (&GST_VA_BASE_ENC (self)->reconf, TRUE);
4092 already_effect = TRUE;
4095 self->prop.cpb_size = g_value_get_uint (value);
4098 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4101 GST_OBJECT_UNLOCK (self);
4103 #ifndef GST_DISABLE_GST_DEBUG
4104 if (!already_effect &&
4105 base->encoder && gst_va_encoder_is_open (base->encoder)) {
4106 GST_WARNING_OBJECT (self, "Property `%s` change ignored while processing.",
4113 gst_va_h265_enc_get_property (GObject * object, guint prop_id,
4114 GValue * value, GParamSpec * pspec)
4116 GstVaH265Enc *const self = GST_VA_H265_ENC (object);
4118 GST_OBJECT_LOCK (self);
4121 case PROP_KEY_INT_MAX:
4122 g_value_set_uint (value, self->prop.key_int_max);
4125 g_value_set_uint (value, self->prop.num_bframes);
4128 g_value_set_uint (value, self->prop.num_iframes);
4130 case PROP_NUM_REF_FRAMES:
4131 g_value_set_uint (value, self->prop.num_ref_frames);
4133 case PROP_B_PYRAMID:
4134 g_value_set_boolean (value, self->prop.b_pyramid);
4136 case PROP_NUM_SLICES:
4137 g_value_set_uint (value, self->prop.num_slices);
4140 g_value_set_uint (value, self->prop.min_qp);
4143 g_value_set_uint (value, self->prop.max_qp);
4146 g_value_set_uint (value, self->prop.qp_i);
4149 g_value_set_uint (value, self->prop.qp_p);
4152 g_value_set_uint (value, self->prop.qp_b);
4155 g_value_set_boolean (value, self->prop.use_trellis);
4158 g_value_set_boolean (value, self->prop.aud);
4161 g_value_set_enum (value, self->prop.mbbrc);
4164 g_value_set_uint (value, self->prop.bitrate);
4166 case PROP_TARGET_PERCENTAGE:
4167 g_value_set_uint (value, self->prop.target_percentage);
4169 case PROP_TARGET_USAGE:
4170 g_value_set_uint (value, self->prop.target_usage);
4172 case PROP_RATE_CONTROL:
4173 g_value_set_enum (value, self->prop.rc_ctrl);
4176 g_value_set_uint (value, self->prop.cpb_size);
4179 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4182 GST_OBJECT_UNLOCK (self);
4186 gst_va_h265_enc_class_init (gpointer g_klass, gpointer class_data)
4188 GstCaps *src_doc_caps, *sink_doc_caps;
4189 GstPadTemplate *sink_pad_templ, *src_pad_templ;
4190 GObjectClass *object_class = G_OBJECT_CLASS (g_klass);
4191 GstElementClass *element_class = GST_ELEMENT_CLASS (g_klass);
4192 GstVideoEncoderClass *venc_class = GST_VIDEO_ENCODER_CLASS (g_klass);
4193 GstVaBaseEncClass *va_enc_class = GST_VA_BASE_ENC_CLASS (g_klass);
4194 GstVaH265EncClass *vah265enc_class = GST_VA_H265_ENC_CLASS (g_klass);
4195 GstVaDisplay *display;
4196 GstVaEncoder *encoder;
4197 struct CData *cdata = class_data;
4199 const gchar *name, *desc;
4200 gint n_props = N_PROPERTIES;
4201 GParamFlags param_flags =
4202 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT;
4204 if (cdata->entrypoint == VAEntrypointEncSlice) {
4205 desc = "VA-API based H.265 video encoder";
4206 name = "VA-API H.265 Encoder";
4208 desc = "VA-API based H.265 low power video encoder";
4209 name = "VA-API H.265 Low Power Encoder";
4212 if (cdata->description)
4213 long_name = g_strdup_printf ("%s in %s", name, cdata->description);
4215 long_name = g_strdup (name);
4217 gst_element_class_set_metadata (element_class, long_name,
4218 "Codec/Encoder/Video/Hardware", desc, "He Junyan <junyan.he@intel.com>");
4220 sink_doc_caps = gst_caps_from_string (sink_caps_str);
4221 src_doc_caps = gst_caps_from_string (src_caps_str);
4223 parent_class = g_type_class_peek_parent (g_klass);
4225 va_enc_class->codec = HEVC;
4226 va_enc_class->entrypoint = cdata->entrypoint;
4227 va_enc_class->render_device_path = g_strdup (cdata->render_device_path);
4229 sink_pad_templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
4231 gst_element_class_add_pad_template (element_class, sink_pad_templ);
4233 gst_pad_template_set_documentation_caps (sink_pad_templ, sink_doc_caps);
4234 gst_caps_unref (sink_doc_caps);
4236 src_pad_templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
4238 gst_element_class_add_pad_template (element_class, src_pad_templ);
4240 gst_pad_template_set_documentation_caps (src_pad_templ, src_doc_caps);
4241 gst_caps_unref (src_doc_caps);
4243 object_class->set_property = gst_va_h265_enc_set_property;
4244 object_class->get_property = gst_va_h265_enc_get_property;
4246 venc_class->flush = GST_DEBUG_FUNCPTR (gst_va_h265_enc_flush);
4248 va_enc_class->reset_state = GST_DEBUG_FUNCPTR (gst_va_h265_enc_reset_state);
4249 va_enc_class->reconfig = GST_DEBUG_FUNCPTR (gst_va_h265_enc_reconfig);
4250 va_enc_class->new_frame = GST_DEBUG_FUNCPTR (gst_va_h265_enc_new_frame);
4251 va_enc_class->reorder_frame =
4252 GST_DEBUG_FUNCPTR (gst_va_h265_enc_reorder_frame);
4253 va_enc_class->encode_frame = GST_DEBUG_FUNCPTR (gst_va_h265_enc_encode_frame);
4254 va_enc_class->prepare_output =
4255 GST_DEBUG_FUNCPTR (gst_va_h265_enc_prepare_output);
4259 gst_va_display_drm_new_from_path (va_enc_class->render_device_path);
4260 encoder = gst_va_encoder_new (display, va_enc_class->codec,
4261 va_enc_class->entrypoint);
4262 if (gst_va_encoder_get_rate_control_enum (encoder,
4263 vah265enc_class->rate_control)) {
4264 g_snprintf (vah265enc_class->rate_control_type_name,
4265 G_N_ELEMENTS (vah265enc_class->rate_control_type_name) - 1,
4266 "GstVaEncoderRateControl_%" GST_FOURCC_FORMAT "%s_%s",
4267 GST_FOURCC_ARGS (va_enc_class->codec),
4268 (va_enc_class->entrypoint == VAEntrypointEncSliceLP) ? "_LP" : "",
4269 g_path_get_basename (va_enc_class->render_device_path));
4270 vah265enc_class->rate_control_type =
4271 g_enum_register_static (vah265enc_class->rate_control_type_name,
4272 vah265enc_class->rate_control);
4273 gst_type_mark_as_plugin_api (vah265enc_class->rate_control_type, 0);
4275 gst_object_unref (encoder);
4276 gst_object_unref (display);
4280 g_free (cdata->description);
4281 g_free (cdata->render_device_path);
4282 gst_caps_unref (cdata->src_caps);
4283 gst_caps_unref (cdata->sink_caps);
4287 * GstVaH265Enc:key-int-max:
4289 * The maximal distance between two keyframes.
4291 properties[PROP_KEY_INT_MAX] = g_param_spec_uint ("key-int-max",
4292 "Key frame maximal interval",
4293 "The maximal distance between two keyframes. It decides the size of GOP"
4294 " (0: auto-calculate)", 0, MAX_GOP_SIZE, 0, param_flags);
4297 * GstVaH265Enc:b-frames:
4299 * Number of B-frames between two reference frames.
4301 properties[PROP_BFRAMES] = g_param_spec_uint ("b-frames", "B Frames",
4302 "Number of B frames between I and P reference frames", 0, 31, 0,
4306 * GstVaH265Enc:i-frames:
4308 * Force the number of i-frames insertion within one GOP.
4310 properties[PROP_IFRAMES] = g_param_spec_uint ("i-frames", "I Frames",
4311 "Force the number of I frames insertion within one GOP, not including the "
4312 "first IDR frame", 0, 1023, 0, param_flags);
4314 /* The VA only define 15 refs */
4316 * GstVaH265Enc:ref-frames:
4318 * The number of reference frames.
4320 properties[PROP_NUM_REF_FRAMES] = g_param_spec_uint ("ref-frames",
4321 "Number of Reference Frames",
4322 "Number of reference frames, including both the forward and the backward",
4323 0, 15, 3, param_flags);
4326 * GstVaH265Enc:b-pyramid:
4328 * Enable the b-pyramid reference structure in GOP.
4330 properties[PROP_B_PYRAMID] = g_param_spec_boolean ("b-pyramid", "b pyramid",
4331 "Enable the b-pyramid reference structure in the GOP", FALSE,
4335 * GstVaH265Enc:num-slices:
4337 * The number of slices per frame.
4339 properties[PROP_NUM_SLICES] = g_param_spec_uint ("num-slices",
4340 "Number of Slices", "Number of slices per frame", 1, 200, 1, param_flags);
4343 * GstVaH265Enc:max-qp:
4345 * The maximum quantizer value.
4347 properties[PROP_MAX_QP] = g_param_spec_uint ("max-qp", "Maximum QP",
4348 "Maximum quantizer value for each frame", 0, 51, 51, param_flags);
4351 * GstVaH265Enc:min-qp:
4353 * The minimum quantizer value.
4355 properties[PROP_MIN_QP] = g_param_spec_uint ("min-qp", "Minimum QP",
4356 "Minimum quantizer value for each frame", 0, 51, 1, param_flags);
4361 * The quantizer value for I frame. In CQP mode, it specifies the QP of
4362 * I frame, in other mode, it specifies the init QP of all frames.
4364 properties[PROP_QP_I] = g_param_spec_uint ("qpi", "I Frame QP",
4365 "The quantizer value for I frame. In CQP mode, it specifies the QP of I "
4366 "frame, in other mode, it specifies the init QP of all frames", 0, 51, 26,
4367 param_flags | GST_PARAM_MUTABLE_PLAYING);
4372 * The quantizer value for P frame. This is available only in CQP mode.
4374 properties[PROP_QP_P] = g_param_spec_uint ("qpp",
4375 "The quantizer value for P frame",
4376 "The quantizer value for P frame. This is available only in CQP mode",
4377 0, 51, 26, param_flags | GST_PARAM_MUTABLE_PLAYING);
4382 * The quantizer value for B frame. This is available only in CQP mode.
4384 properties[PROP_QP_B] = g_param_spec_uint ("qpb",
4385 "The quantizer value for B frame",
4386 "The quantizer value for B frame. This is available only in CQP mode",
4387 0, 51, 26, param_flags | GST_PARAM_MUTABLE_PLAYING);
4390 * GstVaH265Enc:trellis:
4392 * It enable the trellis quantization method.
4393 * Trellis is an improved quantization algorithm.
4395 properties[PROP_TRELLIS] = g_param_spec_boolean ("trellis", "Enable trellis",
4396 "Enable the trellis quantization method", FALSE, param_flags);
4401 * Insert the AU (Access Unit) delimeter for each frame.
4403 properties[PROP_AUD] = g_param_spec_boolean ("aud", "Insert AUD",
4404 "Insert AU (Access Unit) delimeter for each frame", FALSE, param_flags);
4407 * GstVaH265Enc:mbbrc:
4409 * Macroblock level bitrate control.
4410 * This is not compatible with Constant QP rate control.
4412 properties[PROP_MBBRC] = g_param_spec_enum ("mbbrc",
4413 "Macroblock level Bitrate Control",
4414 "Macroblock level Bitrate Control. It is not compatible with CQP",
4415 GST_TYPE_VA_FEATURE, GST_VA_FEATURE_AUTO, param_flags);
4418 * GstVaH265Enc:bitrate:
4420 * The desired target bitrate, expressed in kbps.
4421 * This is not available in CQP mode.
4423 * CBR: This applies equally to the minimum, maximum and target bitrate.
4424 * VBR: This applies to the target bitrate. The driver will use the
4425 * "target-percentage" together to calculate the minimum and maximum bitrate.
4426 * VCM: This applies to the target bitrate. The minimum and maximum bitrate
4429 properties[PROP_BITRATE] = g_param_spec_uint ("bitrate", "Bitrate (kbps)",
4430 "The desired bitrate expressed in kbps (0: auto-calculate)",
4431 0, 2000 * 1024, 0, param_flags | GST_PARAM_MUTABLE_PLAYING);
4434 * GstVaH265Enc:target-percentage:
4436 * The target percentage of the max bitrate, and expressed in uint,
4437 * equal to "target percentage"*100.
4438 * "target percentage" = "target bitrate" * 100 / "max bitrate"
4439 * This is available only when rate-control is VBR.
4440 * The driver uses it to calculate the minimum and maximum bitrate.
4442 properties[PROP_TARGET_PERCENTAGE] = g_param_spec_uint ("target-percentage",
4443 "target bitrate percentage",
4444 "The percentage for 'target bitrate'/'maximum bitrate' (Only in VBR)",
4445 50, 100, 66, param_flags | GST_PARAM_MUTABLE_PLAYING);
4448 * GstVaH265Enc:target-usage:
4450 * The target usage of the encoder. It controls and balances the encoding
4451 * speed and the encoding quality. The lower value has better quality but
4452 * slower speed, the higher value has faster speed but lower quality.
4454 properties[PROP_TARGET_USAGE] = g_param_spec_uint ("target-usage",
4456 "The target usage to control and balance the encoding speed/quality",
4457 1, 7, 4, param_flags | GST_PARAM_MUTABLE_PLAYING);
4460 * GstVaH265Enc:cpb-size:
4462 * The desired max CPB size in Kb (0: auto-calculate).
4464 properties[PROP_CPB_SIZE] = g_param_spec_uint ("cpb-size",
4465 "max CPB size in Kb",
4466 "The desired max CPB size in Kb (0: auto-calculate)", 0, 2000 * 1024, 0,
4469 if (vah265enc_class->rate_control_type > 0) {
4470 properties[PROP_RATE_CONTROL] = g_param_spec_enum ("rate-control",
4471 "rate control mode", "The desired rate control mode for the encoder",
4472 vah265enc_class->rate_control_type,
4473 vah265enc_class->rate_control[0].value,
4474 GST_PARAM_CONDITIONALLY_AVAILABLE | GST_PARAM_MUTABLE_PLAYING
4478 properties[PROP_RATE_CONTROL] = NULL;
4481 g_object_class_install_properties (object_class, n_props, properties);
4485 * @GST_VA_FEATURE_DISABLED: The feature is disabled.
4486 * @GST_VA_FEATURE_ENABLED: The feature is enabled.
4487 * @GST_VA_FEATURE_AUTO: The feature is enabled automatically.
4491 gst_type_mark_as_plugin_api (GST_TYPE_VA_FEATURE, 0);
4495 _complete_src_caps (GstCaps * srccaps)
4497 GstCaps *caps = gst_caps_copy (srccaps);
4498 GValue val = G_VALUE_INIT;
4500 g_value_init (&val, G_TYPE_STRING);
4501 g_value_set_string (&val, "au");
4502 gst_caps_set_value (caps, "alignment", &val);
4503 g_value_unset (&val);
4505 g_value_init (&val, G_TYPE_STRING);
4506 g_value_set_string (&val, "byte-stream");
4507 gst_caps_set_value (caps, "stream-format", &val);
4508 g_value_unset (&val);
4514 gst_va_h265_enc_register (GstPlugin * plugin, GstVaDevice * device,
4515 GstCaps * sink_caps, GstCaps * src_caps, guint rank,
4516 VAEntrypoint entrypoint)
4518 static GOnce debug_once = G_ONCE_INIT;
4520 GTypeInfo type_info = {
4521 .class_size = sizeof (GstVaH265EncClass),
4522 .class_init = gst_va_h265_enc_class_init,
4523 .instance_size = sizeof (GstVaH265Enc),
4524 .instance_init = gst_va_h265_enc_init,
4526 struct CData *cdata;
4528 gchar *type_name, *feature_name;
4530 g_return_val_if_fail (GST_IS_PLUGIN (plugin), FALSE);
4531 g_return_val_if_fail (GST_IS_VA_DEVICE (device), FALSE);
4532 g_return_val_if_fail (GST_IS_CAPS (sink_caps), FALSE);
4533 g_return_val_if_fail (GST_IS_CAPS (src_caps), FALSE);
4534 g_return_val_if_fail (entrypoint == VAEntrypointEncSlice ||
4535 entrypoint == VAEntrypointEncSliceLP, FALSE);
4537 cdata = g_new (struct CData, 1);
4538 cdata->entrypoint = entrypoint;
4539 cdata->description = NULL;
4540 cdata->render_device_path = g_strdup (device->render_device_path);
4541 cdata->sink_caps = gst_caps_ref (sink_caps);
4542 cdata->src_caps = _complete_src_caps (src_caps);
4544 /* class data will be leaked if the element never gets instantiated */
4545 GST_MINI_OBJECT_FLAG_SET (cdata->sink_caps,
4546 GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
4547 GST_MINI_OBJECT_FLAG_SET (cdata->src_caps,
4548 GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
4550 type_info.class_data = cdata;
4551 if (entrypoint == VAEntrypointEncSlice) {
4552 type_name = g_strdup ("GstVaH265Enc");
4553 feature_name = g_strdup ("vah265enc");
4555 type_name = g_strdup ("GstVaH265LPEnc");
4556 feature_name = g_strdup ("vah265lpenc");
4559 /* The first encoder to be registered should use a constant name,
4560 * like vah265enc, for any additional encoders, we create unique
4561 * names, using inserting the render device name. */
4562 if (g_type_from_name (type_name)) {
4563 gchar *basename = g_path_get_basename (device->render_device_path);
4565 g_free (feature_name);
4566 if (entrypoint == VAEntrypointEncSlice) {
4567 type_name = g_strdup_printf ("GstVa%sH265Enc", basename);
4568 feature_name = g_strdup_printf ("va%sh265enc", basename);
4570 type_name = g_strdup_printf ("GstVa%sH265LPEnc", basename);
4571 feature_name = g_strdup_printf ("va%sh265lpenc", basename);
4573 cdata->description = basename;
4574 /* lower rank for non-first device */
4579 g_once (&debug_once, _register_debug_category, NULL);
4580 type = g_type_register_static (GST_TYPE_VA_BASE_ENC,
4581 type_name, &type_info, 0);
4582 ret = gst_element_register (plugin, feature_name, rank, type);
4585 g_free (feature_name);