From 50ff1e4f867287fa2bfce5a714c365957fbf098a Mon Sep 17 00:00:00 2001 From: yinjiyao Date: Fri, 26 Jul 2024 18:27:47 -0400 Subject: [PATCH] radeonsi/vcn: add HDR sei in hevc enc Enable HDR sei in hevc encoder. Signed-off-by: Yinjie Yao Reviewed-by: Boyuan Zhang Reviewed-by: Ruijing Dong Part-of: --- src/amd/common/ac_vcn_enc.h | 3 + src/gallium/drivers/radeonsi/radeon_vcn_enc.c | 38 +++++++++++ .../drivers/radeonsi/radeon_vcn_enc_1_2.c | 68 +++++++++++++++++++ 3 files changed, 109 insertions(+) diff --git a/src/amd/common/ac_vcn_enc.h b/src/amd/common/ac_vcn_enc.h index 7ced87fe143..eaa96e284be 100644 --- a/src/amd/common/ac_vcn_enc.h +++ b/src/amd/common/ac_vcn_enc.h @@ -98,6 +98,9 @@ #define RENCODE_H264_HEADER_INSTRUCTION_FIRST_MB 0x00020000 #define RENCODE_H264_HEADER_INSTRUCTION_SLICE_QP_DELTA 0x00020001 +#define RENCODE_HEVC_SEI_TYPE_MDCV 137 +#define RENCODE_HEVC_SEI_TYPE_CLL 144 + #define RENCODE_AV1_BITSTREAM_INSTRUCTION_OBU_START 0x00000002 #define RENCODE_AV1_BITSTREAM_INSTRUCTION_OBU_SIZE 0x00000003 #define RENCODE_AV1_BITSTREAM_INSTRUCTION_OBU_END 0x00000004 diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c index 07c2c25fb86..719ad8b3a8f 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c @@ -684,6 +684,43 @@ static void radeon_vcn_enc_hevc_get_slice_ctrl_param(struct radeon_encoder *enc, num_ctbs_in_slice; } +static void radeon_vcn_enc_hevc_get_metadata(struct radeon_encoder *enc, + struct pipe_h265_enc_picture_desc *pic) +{ + memset (&enc->enc_pic.enc_sei, 0, sizeof(rvcn_enc_seidata_t)); + + if (!pic->metadata_flags.value) { + enc->enc_pic.enc_sei.flags.value = 0; + return; + } + + if (pic->metadata_flags.hdr_cll) { + enc->enc_pic.enc_sei.flags.hdr_cll = 1; + enc->enc_pic.enc_sei.hdr_cll = (rvcn_enc_sei_hdr_cll_t) { + .max_cll = pic->metadata_hdr_cll.max_cll, + .max_fall = pic->metadata_hdr_cll.max_fall + }; + } + + if (pic->metadata_flags.hdr_mdcv) { + enc->enc_pic.enc_sei.flags.hdr_mdcv = 1; + for (int32_t i = 0; i < 3; i++) { + enc->enc_pic.enc_sei.hdr_mdcv.primary_chromaticity_x[i] + = pic->metadata_hdr_mdcv.primary_chromaticity_x[i]; + enc->enc_pic.enc_sei.hdr_mdcv.primary_chromaticity_y[i] + = pic->metadata_hdr_mdcv.primary_chromaticity_y[i]; + } + enc->enc_pic.enc_sei.hdr_mdcv.white_point_chromaticity_x = + pic->metadata_hdr_mdcv.white_point_chromaticity_x; + enc->enc_pic.enc_sei.hdr_mdcv.white_point_chromaticity_y = + pic->metadata_hdr_mdcv.white_point_chromaticity_y; + enc->enc_pic.enc_sei.hdr_mdcv.luminance_max = + pic->metadata_hdr_mdcv.luminance_max; + enc->enc_pic.enc_sei.hdr_mdcv.luminance_min = + pic->metadata_hdr_mdcv.luminance_min; + } +} + static void radeon_vcn_enc_hevc_get_param(struct radeon_encoder *enc, struct pipe_h265_enc_picture_desc *pic) { @@ -745,6 +782,7 @@ static void radeon_vcn_enc_hevc_get_param(struct radeon_encoder *enc, &pic->intra_refresh); radeon_vcn_enc_get_roi_param(enc, &pic->roi); radeon_vcn_enc_get_latency_param(enc); + radeon_vcn_enc_hevc_get_metadata(enc, pic); } static void radeon_vcn_enc_av1_get_spec_misc_param(struct radeon_encoder *enc, 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 a1f864b1c75..09381856b1a 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c @@ -658,6 +658,72 @@ static void radeon_enc_nalu_sei(struct radeon_encoder *enc) RADEON_ENC_END(); } +static void radeon_enc_nalu_sei_hevc(struct radeon_encoder *enc) +{ + if (!enc->enc_pic.enc_sei.flags.value) + return; + + struct radeon_enc_pic *pic = &enc->enc_pic; + RADEON_ENC_BEGIN(enc->cmd.nalu); + RADEON_ENC_CS(RENCODE_DIRECT_OUTPUT_NALU_TYPE_SEI); + uint32_t *size_in_bytes = &enc->cs.current.buf[enc->cs.current.cdw++]; + radeon_enc_reset(enc); + + if (enc->enc_pic.enc_sei.flags.hdr_mdcv){ + radeon_enc_set_emulation_prevention(enc, false); + + radeon_enc_code_fixed_bits(enc, 0x00000001, 32); + radeon_enc_code_fixed_bits(enc, 0, 1); /* forbidden_zero_bit f(1) */ + radeon_enc_code_fixed_bits(enc, 39, 6); /* nal_unit_type u(6) */ + radeon_enc_code_fixed_bits(enc, 0, 6); /* nuh_layer_id u(6) */ + radeon_enc_code_fixed_bits(enc, 1, 3); /* nuh_temporal_id_plus1 u(3) */ + radeon_enc_byte_align(enc); + + radeon_enc_set_emulation_prevention(enc, true); + + radeon_enc_code_fixed_bits(enc, RENCODE_HEVC_SEI_TYPE_MDCV, 8); /* last_payload_type_byte */ + radeon_enc_code_fixed_bits(enc, 24, 8); /* last_payload_size_byte */ + + for (int32_t i = 0; i < 3; i++) { + radeon_enc_code_fixed_bits(enc, pic->enc_sei.hdr_mdcv.primary_chromaticity_x[i], 16); + radeon_enc_code_fixed_bits(enc, pic->enc_sei.hdr_mdcv.primary_chromaticity_y[i], 16); + } + + radeon_enc_code_fixed_bits(enc, pic->enc_sei.hdr_mdcv.white_point_chromaticity_x, 16); + radeon_enc_code_fixed_bits(enc, pic->enc_sei.hdr_mdcv.white_point_chromaticity_y, 16); + + radeon_enc_code_fixed_bits(enc, pic->enc_sei.hdr_mdcv.luminance_max, 32); + radeon_enc_code_fixed_bits(enc, pic->enc_sei.hdr_mdcv.luminance_min, 32); + radeon_enc_code_fixed_bits(enc, 0x1, 1); + radeon_enc_byte_align(enc); + } + + if (enc->enc_pic.enc_sei.flags.hdr_cll) { + radeon_enc_set_emulation_prevention(enc, false); + + radeon_enc_code_fixed_bits(enc, 0x00000001, 32); + radeon_enc_code_fixed_bits(enc, 0, 1); /* forbidden_zero_bit f(1) */ + radeon_enc_code_fixed_bits(enc, 39, 6); /* nal_unit_type u(6) */ + radeon_enc_code_fixed_bits(enc, 0, 6); /* nuh_layer_id u(6) */ + radeon_enc_code_fixed_bits(enc, 1, 3); /* nuh_temporal_id_plus1 u(3) */ + radeon_enc_byte_align(enc); + + radeon_enc_set_emulation_prevention(enc, true); + + radeon_enc_code_fixed_bits(enc, RENCODE_HEVC_SEI_TYPE_CLL, 8); /* last_payload_type_byte */ + radeon_enc_code_fixed_bits(enc, 4, 8); /* last_payload_size_byte */ + + radeon_enc_code_fixed_bits(enc, pic->enc_sei.hdr_cll.max_cll, 16); + radeon_enc_code_fixed_bits(enc, pic->enc_sei.hdr_cll.max_fall, 16); + radeon_enc_code_fixed_bits(enc, 0x1, 1); + radeon_enc_byte_align(enc); + } + + radeon_enc_flush_headers(enc); + *size_in_bytes = (enc->bits_output + 7) / 8; + RADEON_ENC_END(); +} + static void radeon_enc_nalu_pps(struct radeon_encoder *enc) { RADEON_ENC_BEGIN(enc->cmd.nalu); @@ -1424,6 +1490,7 @@ static void radeon_enc_headers_hevc(struct radeon_encoder *enc) enc->nalu_vps(enc); enc->nalu_pps(enc); enc->nalu_sps(enc); + enc->nalu_sei(enc); } enc->slice_header(enc); enc->encode_params(enc); @@ -1646,6 +1713,7 @@ void radeon_enc_1_2_init(struct radeon_encoder *enc) enc->slice_header = radeon_enc_slice_header_hevc; enc->encode_headers = radeon_enc_headers_hevc; enc->encode_params_codec_spec = radeon_enc_dummy; + enc->nalu_sei = radeon_enc_nalu_sei_hevc; } enc->cmd.session_info = RENCODE_IB_PARAM_SESSION_INFO;