radeonsi/vcn: add HDR metadata obu in av1enc

Enable HDR metadata obu in av1 encoder for
both vcn4/5.

Reviewed-by: David Rosca <david.rosca@amd.com>
Signed-off-by: Ruijing Dong <ruijing.dong@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30237>
This commit is contained in:
Ruijing Dong
2024-07-16 22:02:27 -04:00
committed by Marge Bot
parent fc4abbe27d
commit 8a5ef9413b
6 changed files with 122 additions and 3 deletions

View File

@@ -115,6 +115,11 @@
#define RENCODE_OBU_TYPE_TILE_LIST 8
#define RENCODE_OBU_TYPE_PADDING 15
#define RENCODE_METADATA_TYPE_HDR_CLL 1
#define RENCODE_METADATA_TYPE_HDR_MDCV 2
#define RENCODE_METADATA_TYPE_ITUT_T35 4
#define RENCODE_METADATA_TYPE_TIMECODE 5
#define RENCODE_AV1_MV_PRECISION_ALLOW_HIGH_PRECISION 0x00
#define RENCODE_AV1_MV_PRECISION_DISALLOW_HIGH_PRECISION 0x10
#define RENCODE_AV1_MV_PRECISION_FORCE_INTEGER_MV 0x30

View File

@@ -892,9 +892,6 @@ static void radeon_vcn_enc_av1_get_meta_param(struct radeon_encoder *enc,
enc->enc_pic.enc_sei.hdr_mdcv.luminance_min =
pic->metadata_hdr_mdcv.luminance_min;
}
/* meta data per picture will need to clear it after fetching it up */
pic->metadata_flags.value = 0;
}
static void radeon_vcn_enc_av1_get_param(struct radeon_encoder *enc,

View File

@@ -364,6 +364,8 @@ void radeon_enc_av1_sequence_header(struct radeon_encoder *enc, bool separate_de
void radeon_enc_av1_tile_group(struct radeon_encoder *enc);
void radeon_enc_av1_metadata_obu(struct radeon_encoder *enc);
unsigned char *radeon_enc_av1_header_size_offset(struct radeon_encoder *enc);
unsigned int radeon_enc_value_bits(unsigned int value);

View File

@@ -943,6 +943,105 @@ void radeon_enc_av1_tile_group(struct radeon_encoder *enc)
radeon_enc_av1_bs_instruction_type(enc, RENCODE_AV1_BITSTREAM_INSTRUCTION_OBU_END, 0);
}
static void radeon_enc_av1_metadata_obu_hdr_cll(struct radeon_encoder *enc)
{
uint8_t *size_offset;
uint8_t obu_size_bin;
uint8_t metadata_type;
uint8_t *p;
uint32_t obu_size;
uint32_t nb_obu_size_byte = sizeof(obu_size_bin);
rvcn_enc_sei_hdr_cll_t *p_cll = &enc->enc_pic.enc_sei.hdr_cll;
radeon_enc_av1_obu_header(enc, RENCODE_OBU_TYPE_METADATA);
/* obu_size, use nb_obu_size_byte bytes for header,
* the size will be written in afterwards */
size_offset = radeon_enc_av1_header_size_offset(enc);
radeon_enc_code_fixed_bits(enc, 0, nb_obu_size_byte * 8);
radeon_enc_code_leb128(&metadata_type, RENCODE_METADATA_TYPE_HDR_CLL, 1);
radeon_enc_code_fixed_bits(enc, metadata_type, 8);
radeon_enc_code_fixed_bits(enc, p_cll->max_cll, 16);
radeon_enc_code_fixed_bits(enc, p_cll->max_fall, 16);
/* trailing_one_bit */
radeon_enc_code_fixed_bits(enc, 1, 1);
radeon_enc_byte_align(enc);
/* obu_size doesn't include the bytes within obu_header
* or obu_size syntax element (6.2.1), here we use
* nb_obu_size_byte bytes for obu_size syntax
* which needs to be removed from the size.
*/
obu_size = (uint32_t)(radeon_enc_av1_header_size_offset(enc)
- size_offset - nb_obu_size_byte);
radeon_enc_code_leb128(&obu_size_bin, obu_size, nb_obu_size_byte);
p = (uint8_t *)((((uintptr_t)size_offset & 3) ^ 3) | ((uintptr_t)size_offset & ~3));
*p = obu_size_bin;
}
static void radeon_enc_av1_metadata_obu_hdr_mdcv(struct radeon_encoder *enc)
{
uint8_t *size_offset;
uint8_t obu_size_bin;
uint8_t metadata_type;
uint8_t *p;
uint32_t obu_size;
uint32_t nb_obu_size_byte = sizeof(obu_size_bin);
rvcn_enc_sei_hdr_mdcv_t *p_mdcv = &enc->enc_pic.enc_sei.hdr_mdcv;
radeon_enc_av1_obu_header(enc, RENCODE_OBU_TYPE_METADATA);
/* obu_size, use nb_obu_size_byte bytes for header,
* the size will be written in afterwards */
size_offset = radeon_enc_av1_header_size_offset(enc);
radeon_enc_code_fixed_bits(enc, 0, nb_obu_size_byte * 8);
radeon_enc_code_leb128(&metadata_type, RENCODE_METADATA_TYPE_HDR_MDCV, 1);
radeon_enc_code_fixed_bits(enc, metadata_type, 8);
for (int32_t i = 0; i < 3; i++) {
radeon_enc_code_fixed_bits(enc, p_mdcv->primary_chromaticity_x[i], 16);
radeon_enc_code_fixed_bits(enc, p_mdcv->primary_chromaticity_y[i], 16);
}
radeon_enc_code_fixed_bits(enc, p_mdcv->white_point_chromaticity_x, 16);
radeon_enc_code_fixed_bits(enc, p_mdcv->white_point_chromaticity_y, 16);
radeon_enc_code_fixed_bits(enc, p_mdcv->luminance_max, 32);
radeon_enc_code_fixed_bits(enc, p_mdcv->luminance_min, 32);
/* trailing_one_bit */
radeon_enc_code_fixed_bits(enc, 1, 1);
radeon_enc_byte_align(enc);
/* obu_size doesn't include the bytes within obu_header
* or obu_size syntax element (6.2.1), here we use
* nb_obu_size_byte bytes for obu_size syntax
* which needs to be removed from the size.
*/
obu_size = (uint32_t)(radeon_enc_av1_header_size_offset(enc)
- size_offset - nb_obu_size_byte);
radeon_enc_code_leb128(&obu_size_bin, obu_size, nb_obu_size_byte);
p = (uint8_t *)((((uintptr_t)size_offset & 3) ^ 3) | ((uintptr_t)size_offset & ~3));
*p = obu_size_bin;
}
void radeon_enc_av1_metadata_obu(struct radeon_encoder *enc)
{
if (!enc->enc_pic.enc_sei.flags.value)
return;
if (enc->enc_pic.enc_sei.flags.hdr_mdcv)
radeon_enc_av1_metadata_obu_hdr_mdcv(enc);
if (enc->enc_pic.enc_sei.flags.hdr_cll)
radeon_enc_av1_metadata_obu_hdr_cll(enc);
}
static void radeon_enc_obu_instruction(struct radeon_encoder *enc)
{
bool frame_header = !enc->enc_pic.stream_obu_frame ||
@@ -959,6 +1058,7 @@ static void radeon_enc_obu_instruction(struct radeon_encoder *enc)
*
* if (others)
* radeon_enc_av1_others(enc); */
radeon_enc_av1_metadata_obu(enc);
radeon_enc_av1_bs_instruction_type(enc,
RENCODE_AV1_BITSTREAM_INSTRUCTION_OBU_START,

View File

@@ -977,6 +977,7 @@ static void radeon_enc_obu_instruction(struct radeon_encoder *enc)
*
* if (others)
* radeon_enc_av1_others(enc); */
radeon_enc_av1_metadata_obu(enc);
radeon_enc_av1_bs_instruction_type(enc,
RENCODE_AV1_BITSTREAM_INSTRUCTION_OBU_START,

View File

@@ -140,6 +140,20 @@ vlVaBeginPicture(VADriverContextP ctx, VAContextID context_id, VASurfaceID rende
if (context->decoder->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE)
context->needs_begin_frame = true;
/* meta data and seis are per picture basis, it needs to be
* cleared before rendering the picture. */
if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
switch (u_reduce_video_profile(context->templat.profile)) {
case PIPE_VIDEO_FORMAT_AV1:
context->desc.av1enc.metadata_flags.value = 0;
break;
case PIPE_VIDEO_FORMAT_HEVC:
case PIPE_VIDEO_FORMAT_MPEG4_AVC:
default:
break;
}
}
context->slice_data_offset = 0;
context->have_slice_params = false;