radeonsi/mm: Add support for 2-ref H264 encode

Two l0 refs are only supported for P-frames, so we must override
number of active refs in slice header in case the app tries to use
two l0 refs with B-frame.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/work_items/15539
Tested-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
Reviewed-by: Benjamin Cheng <benjamin.cheng@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41795>
This commit is contained in:
David Rosca 2026-05-26 09:32:33 +02:00 committed by Marge Bot
parent 617d4810c1
commit 187c723798
3 changed files with 41 additions and 20 deletions

View file

@ -551,6 +551,21 @@ static void radeon_vcn_enc_h264_get_param(struct radeon_encoder *enc,
enc->enc_pic.enc_params.reference_picture_index = 0xffffffff;
}
if (pic->ref_list1[0] == PIPE_H2645_LIST_REF_INVALID_ENTRY &&
pic->ref_list0[1] != PIPE_H2645_LIST_REF_INVALID_ENTRY) {
uint8_t ref_l0_1 = pic->ref_list0[1];
enc->enc_pic.h264_enc_params.l0_reference_picture1_index = ref_l0_1;
enc->enc_pic.h264_enc_params.picture_info_l0_reference_picture1.pic_type =
radeon_enc_h2645_picture_type(pic->dpb[ref_l0_1].picture_type);
enc->enc_pic.h264_enc_params.picture_info_l0_reference_picture1.pic_order_cnt =
pic->dpb[ref_l0_1].pic_order_cnt;
enc->enc_pic.h264_enc_params.picture_info_l0_reference_picture1.is_long_term =
pic->dpb[ref_l0_1].is_ltr;
} else {
enc->enc_pic.h264_enc_params.l0_reference_picture1_index = 0xffffffff;
}
if (pic->ref_list1[0] != PIPE_H2645_LIST_REF_INVALID_ENTRY) {
uint8_t ref_l1 = pic->ref_list1[0];

View file

@ -223,6 +223,7 @@ unsigned int radeon_enc_write_sps_hevc(struct radeon_encoder *enc, uint8_t *out)
unsigned int radeon_enc_write_pps(struct radeon_encoder *enc, uint8_t nal_byte, uint8_t *out)
{
struct pipe_h264_enc_pic_control pps = enc->enc_pic.h264.desc->pic_ctrl;
pps.num_ref_idx_l0_default_active_minus1 = 0;
pps.weighted_bipred_idc = enc->enc_pic.spec_misc.weighted_bipred_idc;
pps.transform_8x8_mode_flag = enc->enc_pic.spec_misc.transform_8x8_mode;
@ -333,15 +334,17 @@ static void radeon_enc_slice_header(struct radeon_encoder *enc)
if (enc->enc_pic.picture_type == PIPE_H2645_ENC_PICTURE_TYPE_P ||
enc->enc_pic.picture_type == PIPE_H2645_ENC_PICTURE_TYPE_B) {
radeon_bs_code_fixed_bits(&bs, slice->num_ref_idx_active_override_flag, 1);
if (slice->num_ref_idx_active_override_flag) {
radeon_bs_code_ue(&bs, slice->num_ref_idx_l0_active_minus1);
uint32_t num_l0 =
enc->enc_pic.h264_enc_params.l0_reference_picture1_index != 0xffffffff ? 2 : 1;
radeon_bs_code_fixed_bits(&bs, num_l0 == 2 ? 1 : 0, 1); /* num_ref_idx_active_override_flag */
if (num_l0 == 2) {
radeon_bs_code_ue(&bs, 1); /* num_ref_idx_l0_active_minus1 */
if (enc->enc_pic.picture_type == PIPE_H2645_ENC_PICTURE_TYPE_B)
radeon_bs_code_ue(&bs, slice->num_ref_idx_l1_active_minus1);
}
radeon_bs_code_fixed_bits(&bs, slice->ref_pic_list_modification_flag_l0, 1);
if (slice->ref_pic_list_modification_flag_l0) {
for (unsigned i = 0; i < slice->num_ref_list0_mod_operations; i++) {
for (unsigned i = 0; i < MIN2(num_l0, slice->num_ref_list0_mod_operations); i++) {
struct pipe_h264_ref_list_mod_entry *op =
&slice->ref_list0_mod_operations[i];
radeon_bs_code_ue(&bs, op->modification_of_pic_nums_idc);

View file

@ -80,17 +80,22 @@ static void radeon_enc_encode_params(struct radeon_encoder *enc)
static void radeon_enc_encode_params_h264(struct radeon_encoder *enc)
{
enc->enc_pic.h264_enc_params.lsm_reference_pictures[0].list = 0;
enc->enc_pic.h264_enc_params.lsm_reference_pictures[0].list_index = 0xFFFFFFFF;
enc->enc_pic.h264_enc_params.lsm_reference_pictures[1].list = 0;
enc->enc_pic.h264_enc_params.lsm_reference_pictures[1].list_index = 0xFFFFFFFF;
enc->enc_pic.h264_enc_params.num_active_references_l0 = 0;
enc->enc_pic.h264_enc_params.num_active_references_l1 = 0;
enc->enc_pic.h264_enc_params.ref_list0[0] = 0;
enc->enc_pic.h264_enc_params.ref_list0[1] = 0;
enc->enc_pic.h264_enc_params.ref_list1[0] = 0;
if (enc->enc_pic.enc_params.reference_picture_index != 0xFFFFFFFF){
enc->enc_pic.h264_enc_params.lsm_reference_pictures[0].list = 0;
enc->enc_pic.h264_enc_params.lsm_reference_pictures[0].list_index = 0;
enc->enc_pic.h264_enc_params.ref_list0[0] =
enc->enc_pic.enc_params.reference_picture_index;
enc->enc_pic.h264_enc_params.num_active_references_l0 = 1;
} else {
enc->enc_pic.h264_enc_params.lsm_reference_pictures[0].list = 0;
enc->enc_pic.h264_enc_params.lsm_reference_pictures[0].list_index = 0xFFFFFFFF;
enc->enc_pic.h264_enc_params.ref_list0[0] = 0xFFFFFFFF;
enc->enc_pic.h264_enc_params.num_active_references_l0 = 0;
}
if (enc->enc_pic.h264_enc_params.l1_reference_picture0_index != 0xFFFFFFFF) {
@ -99,12 +104,12 @@ static void radeon_enc_encode_params_h264(struct radeon_encoder *enc)
enc->enc_pic.h264_enc_params.ref_list1[0] =
enc->enc_pic.h264_enc_params.l1_reference_picture0_index;
enc->enc_pic.h264_enc_params.num_active_references_l1 = 1;
} else {
} else if (enc->enc_pic.h264_enc_params.l0_reference_picture1_index != 0xFFFFFFFF) {
enc->enc_pic.h264_enc_params.lsm_reference_pictures[1].list = 0;
enc->enc_pic.h264_enc_params.lsm_reference_pictures[1].list_index = 0xFFFFFFFF;
enc->enc_pic.h264_enc_params.ref_list0[1] = 0;
enc->enc_pic.h264_enc_params.ref_list1[0] = 0;
enc->enc_pic.h264_enc_params.num_active_references_l1 = 0;
enc->enc_pic.h264_enc_params.lsm_reference_pictures[1].list_index = 1;
enc->enc_pic.h264_enc_params.ref_list0[1] =
enc->enc_pic.h264_enc_params.l0_reference_picture1_index;
enc->enc_pic.h264_enc_params.num_active_references_l0 = 2;
}
RADEON_ENC_BEGIN(enc->cmd.enc_params_h264);
@ -113,13 +118,11 @@ static void radeon_enc_encode_params_h264(struct radeon_encoder *enc)
RADEON_ENC_CS(enc->enc_pic.h264_enc_params.is_reference);
RADEON_ENC_CS(enc->enc_pic.h264_enc_params.is_long_term);
RADEON_ENC_CS(enc->enc_pic.h264_enc_params.interlaced_mode);
RADEON_ENC_CS(enc->enc_pic.h264_enc_params.ref_list0[0]);
for (int i = 1; i < RENCODE_H264_MAX_REFERENCE_LIST_SIZE; i++)
RADEON_ENC_CS(0x00000000);
for (int i = 0; i < RENCODE_H264_MAX_REFERENCE_LIST_SIZE; i++)
RADEON_ENC_CS(enc->enc_pic.h264_enc_params.ref_list0[i]);
RADEON_ENC_CS(enc->enc_pic.h264_enc_params.num_active_references_l0);
RADEON_ENC_CS(enc->enc_pic.h264_enc_params.ref_list1[0]);
for (int i = 1; i < RENCODE_H264_MAX_REFERENCE_LIST_SIZE; i++)
RADEON_ENC_CS(0x00000000);
for (int i = 0; i < RENCODE_H264_MAX_REFERENCE_LIST_SIZE; i++)
RADEON_ENC_CS(enc->enc_pic.h264_enc_params.ref_list1[i]);
RADEON_ENC_CS(enc->enc_pic.h264_enc_params.num_active_references_l1);
RADEON_ENC_CS(enc->enc_pic.h264_enc_params.lsm_reference_pictures[0].list);
RADEON_ENC_CS(enc->enc_pic.h264_enc_params.lsm_reference_pictures[0].list_index);