diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c index 7fdf7bcdd15..552b144c992 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c @@ -216,20 +216,44 @@ static void radeon_vcn_enc_get_latency_param(struct radeon_encoder *enc) sscreen->debug_flags & DBG(LOW_LATENCY_ENCODE) ? 1000 : 0; } -static void radeon_vcn_enc_h264_get_cropping_param(struct radeon_encoder *enc, - struct pipe_h264_enc_picture_desc *pic) +static void radeon_vcn_enc_h264_get_session_param(struct radeon_encoder *enc, + struct pipe_h264_enc_picture_desc *pic) { + if (enc->enc_pic.session_init.aligned_picture_width) + return; + + uint32_t align_width = PIPE_H264_MB_SIZE; + uint32_t align_height = PIPE_H264_MB_SIZE; + + enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_H264; + enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, align_width); + enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, align_height); + + uint32_t padding_width = 0; + uint32_t padding_height = 0; + uint32_t max_padding_width = align_width - 2; + uint32_t max_padding_height = align_height - 2; + + if (enc->enc_pic.session_init.aligned_picture_width > enc->source->width) + padding_width = enc->enc_pic.session_init.aligned_picture_width - enc->source->width; + if (enc->enc_pic.session_init.aligned_picture_height > enc->source->height) + padding_height = enc->enc_pic.session_init.aligned_picture_height - enc->source->height; + + /* Input surface can be smaller if the difference is within padding bounds. */ + if (padding_width > max_padding_width || padding_height > max_padding_height) + RADEON_ENC_ERR("Input surface size doesn't match aligned size\n"); + if (pic->seq.enc_frame_cropping_flag) { - enc->enc_pic.crop_left = pic->seq.enc_frame_crop_left_offset; - enc->enc_pic.crop_right = pic->seq.enc_frame_crop_right_offset; - enc->enc_pic.crop_top = pic->seq.enc_frame_crop_top_offset; - enc->enc_pic.crop_bottom = pic->seq.enc_frame_crop_bottom_offset; - } else { - enc->enc_pic.crop_left = 0; - enc->enc_pic.crop_right = 0; - enc->enc_pic.crop_top = 0; - enc->enc_pic.crop_bottom = 0; + uint32_t pad_w = + (pic->seq.enc_frame_crop_left_offset + pic->seq.enc_frame_crop_right_offset) * 2; + uint32_t pad_h = + (pic->seq.enc_frame_crop_top_offset + pic->seq.enc_frame_crop_bottom_offset) * 2; + padding_width = CLAMP(pad_w, padding_width, max_padding_width); + padding_height = CLAMP(pad_h, padding_height, max_padding_height); } + + enc->enc_pic.session_init.padding_width = padding_width; + enc->enc_pic.session_init.padding_height = padding_height; } static void radeon_vcn_enc_h264_get_dbk_param(struct radeon_encoder *enc, @@ -490,7 +514,7 @@ static void radeon_vcn_enc_h264_get_param(struct radeon_encoder *enc, } } - radeon_vcn_enc_h264_get_cropping_param(enc, pic); + radeon_vcn_enc_h264_get_session_param(enc, pic); radeon_vcn_enc_h264_get_dbk_param(enc, pic); radeon_vcn_enc_h264_get_rc_param(enc, pic); radeon_vcn_enc_h264_get_spec_misc_param(enc, pic); @@ -505,20 +529,44 @@ static void radeon_vcn_enc_h264_get_param(struct radeon_encoder *enc, radeon_vcn_enc_quality_modes(enc, &pic->quality_modes); } -static void radeon_vcn_enc_hevc_get_cropping_param(struct radeon_encoder *enc, - struct pipe_h265_enc_picture_desc *pic) +static void radeon_vcn_enc_hevc_get_session_param(struct radeon_encoder *enc, + struct pipe_h265_enc_picture_desc *pic) { + if (enc->enc_pic.session_init.aligned_picture_width) + return; + + uint32_t align_width = PIPE_H265_ENC_CTB_SIZE; + uint32_t align_height = 16; + + enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_HEVC; + enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, align_width); + enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, align_height); + + uint32_t padding_width = 0; + uint32_t padding_height = 0; + uint32_t max_padding_width = align_width - 2; + uint32_t max_padding_height = align_height - 2; + + if (enc->enc_pic.session_init.aligned_picture_width > enc->source->width) + padding_width = enc->enc_pic.session_init.aligned_picture_width - enc->source->width; + if (enc->enc_pic.session_init.aligned_picture_height > enc->source->height) + padding_height = enc->enc_pic.session_init.aligned_picture_height - enc->source->height; + + /* Input surface can be smaller if the difference is within padding bounds. */ + if (padding_width > max_padding_width || padding_height > max_padding_height) + RADEON_ENC_ERR("Input surface size doesn't match aligned size\n"); + if (pic->seq.conformance_window_flag) { - enc->enc_pic.crop_left = pic->seq.conf_win_left_offset; - enc->enc_pic.crop_right = pic->seq.conf_win_right_offset; - enc->enc_pic.crop_top = pic->seq.conf_win_top_offset; - enc->enc_pic.crop_bottom = pic->seq.conf_win_bottom_offset; - } else { - enc->enc_pic.crop_left = 0; - enc->enc_pic.crop_right = 0; - enc->enc_pic.crop_top = 0; - enc->enc_pic.crop_bottom = 0; + uint32_t pad_w = + (pic->seq.conf_win_left_offset + pic->seq.conf_win_right_offset) * 2; + uint32_t pad_h = + (pic->seq.conf_win_top_offset + pic->seq.conf_win_bottom_offset) * 2; + padding_width = CLAMP(pad_w, padding_width, max_padding_width); + padding_height = CLAMP(pad_h, padding_height, max_padding_height); } + + enc->enc_pic.session_init.padding_width = padding_width; + enc->enc_pic.session_init.padding_height = padding_height; } static void radeon_vcn_enc_hevc_get_dbk_param(struct radeon_encoder *enc, @@ -696,7 +744,7 @@ static void radeon_vcn_enc_hevc_get_param(struct radeon_encoder *enc, } } - radeon_vcn_enc_hevc_get_cropping_param(enc, pic); + radeon_vcn_enc_hevc_get_session_param(enc, pic); radeon_vcn_enc_hevc_get_dbk_param(enc, pic); radeon_vcn_enc_hevc_get_rc_param(enc, pic); radeon_vcn_enc_hevc_get_slice_ctrl_param(enc, pic); @@ -711,6 +759,63 @@ static void radeon_vcn_enc_hevc_get_param(struct radeon_encoder *enc, radeon_vcn_enc_quality_modes(enc, &pic->quality_modes); } +static void radeon_vcn_enc_av1_get_session_param(struct radeon_encoder *enc, + struct pipe_av1_enc_picture_desc *pic) +{ + struct si_screen *sscreen = (struct si_screen *)enc->screen; + + if (enc->enc_pic.session_init.aligned_picture_width) + return; + + enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_AV1; + + uint32_t width = enc->enc_pic.pic_width_in_luma_samples; + uint32_t height = enc->enc_pic.pic_height_in_luma_samples; + uint32_t align_width, align_height; + + if (sscreen->info.vcn_ip_version < VCN_5_0_0) { + align_width = PIPE_AV1_ENC_SB_SIZE; + align_height = 16; + enc->enc_pic.session_init.aligned_picture_width = align(width, align_width); + enc->enc_pic.session_init.aligned_picture_height = align(height, align_height); + if (!(height % 8) && (height % 16)) + enc->enc_pic.session_init.aligned_picture_height = height + 2; + enc->enc_pic.av1.coded_width = enc->enc_pic.session_init.aligned_picture_width; + enc->enc_pic.av1.coded_height = enc->enc_pic.session_init.aligned_picture_height; + if (sscreen->info.vcn_ip_version == VCN_4_0_2 || + sscreen->info.vcn_ip_version == VCN_4_0_5 || + sscreen->info.vcn_ip_version == VCN_4_0_6) + enc->enc_pic.session_init.WA_flags = 1; + } else { + align_width = 8; + align_height = 2; + enc->enc_pic.session_init.aligned_picture_width = align(width, align_width); + enc->enc_pic.session_init.aligned_picture_height = align(height, align_height); + enc->enc_pic.av1.coded_width = width; + enc->enc_pic.av1.coded_height = height; + } + + uint32_t padding_width = 0; + uint32_t padding_height = 0; + uint32_t max_padding_width = align_width - 2; + uint32_t max_padding_height = align_height - 2; + + if (enc->enc_pic.session_init.aligned_picture_width > enc->source->width) + padding_width = enc->enc_pic.session_init.aligned_picture_width - enc->source->width; + if (enc->enc_pic.session_init.aligned_picture_height > enc->source->height) + padding_height = enc->enc_pic.session_init.aligned_picture_height - enc->source->height; + + /* Input surface can be smaller if the difference is within padding bounds. */ + if (padding_width > max_padding_width || padding_height > max_padding_height) + RADEON_ENC_ERR("Input surface size doesn't match aligned size\n"); + + padding_width = MAX2(padding_width, enc->enc_pic.session_init.aligned_picture_width - width); + padding_height = MAX2(padding_height, enc->enc_pic.session_init.aligned_picture_height - height); + + enc->enc_pic.session_init.padding_width = padding_width; + enc->enc_pic.session_init.padding_height = padding_height; +} + static void radeon_vcn_enc_av1_get_spec_misc_param(struct radeon_encoder *enc, struct pipe_av1_enc_picture_desc *pic) { @@ -919,6 +1024,7 @@ static void radeon_vcn_enc_av1_get_param(struct radeon_encoder *enc, } } + radeon_vcn_enc_av1_get_session_param(enc, pic); radeon_vcn_enc_av1_get_spec_misc_param(enc, pic); radeon_vcn_enc_av1_get_rc_param(enc, pic); radeon_vcn_enc_av1_get_tile_config(enc, pic); @@ -1326,6 +1432,7 @@ static void radeon_enc_begin_frame(struct pipe_video_codec *encoder, struct vl_video_buffer *vid_buf = (struct vl_video_buffer *)source; unsigned dpb_slots = 0; + enc->source = source; enc->need_rate_control = false; enc->need_rc_per_pic = false; diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.h b/src/gallium/drivers/radeonsi/radeon_vcn_enc.h index c637f768c65..8db56f3ba32 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.h +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.h @@ -93,10 +93,6 @@ struct radeon_enc_pic { } av1; }; - unsigned crop_left; - unsigned crop_right; - unsigned crop_top; - unsigned crop_bottom; unsigned pic_width_in_luma_samples; unsigned pic_height_in_luma_samples; unsigned bit_depth_luma_minus8; @@ -237,6 +233,7 @@ struct radeon_encoder { struct pb_buffer_lean *handle; struct radeon_surf *luma; struct radeon_surf *chroma; + struct pipe_video_buffer *source; struct pb_buffer_lean *bs_handle; unsigned bs_size; diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c index f466040bc1c..b1ec27ed7ea 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c @@ -44,20 +44,6 @@ static void radeon_enc_task_info(struct radeon_encoder *enc, bool need_feedback) static void radeon_enc_session_init(struct radeon_encoder *enc) { - if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_H264; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 16); - } else if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_HEVC) { - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_HEVC; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 64); - } - enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, 16); - - enc->enc_pic.session_init.padding_width = - (enc->enc_pic.crop_left + enc->enc_pic.crop_right) * 2; - enc->enc_pic.session_init.padding_height = - (enc->enc_pic.crop_top + enc->enc_pic.crop_bottom) * 2; - enc->enc_pic.session_init.display_remote = 0; enc->enc_pic.session_init.pre_encode_mode = enc->enc_pic.quality_modes.pre_encode_mode; enc->enc_pic.session_init.pre_encode_chroma_enabled = !!(enc->enc_pic.quality_modes.pre_encode_mode); diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc_3_0.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc_3_0.c index 77782572232..b9af7bc7538 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_3_0.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_3_0.c @@ -162,20 +162,6 @@ static void radeon_enc_ctx(struct radeon_encoder *enc) static void radeon_enc_session_init(struct radeon_encoder *enc) { - if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_H264; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 16); - } else if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_HEVC) { - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_HEVC; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 64); - } - enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, 16); - - enc->enc_pic.session_init.padding_width = - (enc->enc_pic.crop_left + enc->enc_pic.crop_right) * 2; - enc->enc_pic.session_init.padding_height = - (enc->enc_pic.crop_top + enc->enc_pic.crop_bottom) * 2; - enc->enc_pic.session_init.slice_output_enabled = 0; enc->enc_pic.session_init.display_remote = 0; enc->enc_pic.session_init.pre_encode_mode = enc->enc_pic.quality_modes.pre_encode_mode; diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc_4_0.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc_4_0.c index 462c9ae5903..33b0eed8fd3 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_4_0.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_4_0.c @@ -60,65 +60,6 @@ static void radeon_enc_op_preset(struct radeon_encoder *enc) static void radeon_enc_session_init(struct radeon_encoder *enc) { - struct si_screen *sscreen = (struct si_screen *)enc->screen; - uint32_t av1_height = enc->enc_pic.pic_height_in_luma_samples; - - switch (u_reduce_video_profile(enc->base.profile)) { - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_H264; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 16); - enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, 16); - - enc->enc_pic.session_init.padding_width = - (enc->enc_pic.crop_left + enc->enc_pic.crop_right) * 2; - enc->enc_pic.session_init.padding_height = - (enc->enc_pic.crop_top + enc->enc_pic.crop_bottom) * 2; - break; - case PIPE_VIDEO_FORMAT_HEVC: - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_HEVC; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 64); - enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, 16); - enc->enc_pic.session_init.padding_width = - (enc->enc_pic.crop_left + enc->enc_pic.crop_right) * 2; - enc->enc_pic.session_init.padding_height = - (enc->enc_pic.crop_top + enc->enc_pic.crop_bottom) * 2; - break; - case PIPE_VIDEO_FORMAT_AV1: - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_AV1; - enc->enc_pic.session_init.aligned_picture_width = - align(enc->enc_pic.pic_width_in_luma_samples, 64); - enc->enc_pic.session_init.aligned_picture_height = - align(enc->enc_pic.pic_height_in_luma_samples, 16); - if (!(av1_height % 8) && (av1_height % 16) && !(enc->enc_pic.enable_render_size)) - enc->enc_pic.session_init.aligned_picture_height = av1_height + 2; - - enc->enc_pic.av1.coded_width = enc->enc_pic.session_init.aligned_picture_width; - enc->enc_pic.av1.coded_height = enc->enc_pic.session_init.aligned_picture_height; - - enc->enc_pic.session_init.padding_width = - enc->enc_pic.session_init.aligned_picture_width - - enc->enc_pic.pic_width_in_luma_samples; - enc->enc_pic.session_init.padding_height = - enc->enc_pic.session_init.aligned_picture_height - av1_height; - - if (enc->enc_pic.enable_render_size) - enc->enc_pic.enable_render_size = - (enc->enc_pic.session_init.aligned_picture_width != - enc->enc_pic.render_width) || - (enc->enc_pic.session_init.aligned_picture_height != - enc->enc_pic.render_height); - - if (sscreen->info.vcn_ip_version == VCN_4_0_2 || - sscreen->info.vcn_ip_version == VCN_4_0_5 || - sscreen->info.vcn_ip_version == VCN_4_0_6) - enc->enc_pic.session_init.WA_flags = 1; - - break; - default: - assert(0); - break; - } - enc->enc_pic.session_init.slice_output_enabled = 0; enc->enc_pic.session_init.display_remote = 0; enc->enc_pic.session_init.pre_encode_mode = enc->enc_pic.quality_modes.pre_encode_mode; diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc_5_0.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc_5_0.c index c5beec49731..b2d1a9b8b18 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_5_0.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_5_0.c @@ -959,55 +959,6 @@ static void radeon_enc_obu_instruction(struct radeon_encoder *enc) static void radeon_enc_session_init(struct radeon_encoder *enc) { - switch (u_reduce_video_profile(enc->base.profile)) { - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_H264; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 16); - enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, 16); - - enc->enc_pic.session_init.padding_width = - (enc->enc_pic.crop_left + enc->enc_pic.crop_right) * 2; - enc->enc_pic.session_init.padding_height = - (enc->enc_pic.crop_top + enc->enc_pic.crop_bottom) * 2; - break; - case PIPE_VIDEO_FORMAT_HEVC: - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_HEVC; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 64); - enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, 16); - enc->enc_pic.session_init.padding_width = - (enc->enc_pic.crop_left + enc->enc_pic.crop_right) * 2; - enc->enc_pic.session_init.padding_height = - (enc->enc_pic.crop_top + enc->enc_pic.crop_bottom) * 2; - break; - case PIPE_VIDEO_FORMAT_AV1: - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_AV1; - enc->enc_pic.session_init.aligned_picture_width = - align(enc->enc_pic.pic_width_in_luma_samples, 8); - enc->enc_pic.session_init.aligned_picture_height = - align(enc->enc_pic.pic_height_in_luma_samples, 2); - - enc->enc_pic.av1.coded_width = enc->enc_pic.pic_width_in_luma_samples; - enc->enc_pic.av1.coded_height = enc->enc_pic.pic_height_in_luma_samples; - - enc->enc_pic.session_init.padding_width = - enc->enc_pic.session_init.aligned_picture_width - - enc->enc_pic.pic_width_in_luma_samples; - enc->enc_pic.session_init.padding_height = - enc->enc_pic.session_init.aligned_picture_height - - enc->enc_pic.pic_height_in_luma_samples; - - if (enc->enc_pic.enable_render_size) - enc->enc_pic.enable_render_size = - (enc->enc_pic.session_init.aligned_picture_width != - enc->enc_pic.render_width) || - (enc->enc_pic.session_init.aligned_picture_height != - enc->enc_pic.render_height); - break; - default: - assert(0); - break; - } - enc->enc_pic.session_init.slice_output_enabled = 0; enc->enc_pic.session_init.display_remote = 0; enc->enc_pic.session_init.pre_encode_mode = enc->enc_pic.quality_modes.pre_encode_mode;