radeonsi/vcn: Add ability to encode with ltr

reads flags field from CurrPic struct in pps for VA_PICTURE_H264_LONG_TERM_REFERENCE. If found, Curr_pic.frame_idx wil be used for the long term reference index
In get_picture_storage, check if current frame is ltr, and whether its ref frame is ltr.
In radeon_enc_slice_header, adds the ref_pic_list_modification_flag_l0 and long_term_reference_flag for ltr

v2: fix code formatting issues

Reviewed-by: Ruijing Dong ruijing.dong@amd.com
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18219>
This commit is contained in:
Kuixi Ren
2022-08-23 20:22:40 +00:00
committed by Kuixi Ren
parent bf8c08a0df
commit 9c5edda3ca
5 changed files with 94 additions and 15 deletions
@@ -78,9 +78,13 @@ static void radeon_vcn_enc_get_param(struct radeon_encoder *enc, struct pipe_pic
enc->enc_pic.pic_order_cnt = pic->pic_order_cnt;
enc->enc_pic.pic_order_cnt_type = pic->pic_order_cnt_type;
enc->enc_pic.ref_idx_l0 = pic->ref_idx_l0_list[0];
enc->enc_pic.ref_idx_l0_is_ltr = pic->l0_is_long_term[0];
enc->enc_pic.ref_idx_l1 = pic->ref_idx_l1_list[0];
enc->enc_pic.ref_idx_l1_is_ltr = pic->l1_is_long_term[0];
enc->enc_pic.not_referenced = pic->not_referenced;
enc->enc_pic.is_idr = (pic->picture_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR);
enc->enc_pic.is_ltr = pic->is_ltr;
enc->enc_pic.ltr_idx = pic->is_ltr ? pic->ltr_index : 0;
if (pic->pic_ctrl.enc_frame_cropping_flag) {
enc->enc_pic.crop_left = pic->pic_ctrl.enc_frame_crop_left_offset;
enc->enc_pic.crop_right = pic->pic_ctrl.enc_frame_crop_right_offset;
@@ -362,6 +366,7 @@ static int setup_dpb(struct radeon_encoder *enc)
enc_pic->ctx_buf.num_reconstructed_pictures = num_reconstructed_pictures;
enc_pic->ctx_buf.colloc_buffer_offset = 0;
enc->dpb_size = offset;
enc->max_ltr_idx = 0;
return offset;
}
@@ -357,7 +357,8 @@ typedef struct rvcn_enc_reconstructed_picture_s {
typedef struct rvcn_enc_picture_info_s
{
bool in_use;
uint32_t frame_num;
bool is_ltr;
uint32_t pic_num;
} rvcn_enc_picture_info_t;
typedef struct rvcn_enc_pre_encode_input_picture_s {
@@ -458,7 +459,9 @@ struct radeon_enc_pic {
unsigned pic_order_cnt;
unsigned pic_order_cnt_type;
unsigned ref_idx_l0;
bool ref_idx_l0_is_ltr;
unsigned ref_idx_l1;
bool ref_idx_l1_is_ltr;
unsigned crop_left;
unsigned crop_right;
unsigned crop_top;
@@ -487,6 +490,8 @@ struct radeon_enc_pic {
rvcn_enc_quality_modes_t quality_modes;
bool not_referenced;
bool is_ltr;
unsigned ltr_idx;
bool is_idr;
bool is_even_frame;
bool sample_adaptive_offset_enabled_flag;
@@ -598,6 +603,7 @@ struct radeon_encoder {
bool need_feedback;
unsigned dpb_size;
rvcn_enc_picture_info_t dpb_info[RENCODE_MAX_NUM_RECONSTRUCTED_PICTURES];
unsigned max_ltr_idx;
};
void radeon_enc_add_buffer(struct radeon_encoder *enc, struct pb_buffer *buf,
@@ -865,8 +865,17 @@ static void radeon_enc_slice_header(struct radeon_encoder *enc)
if (enc->enc_pic.picture_type != PIPE_H2645_ENC_PICTURE_TYPE_IDR) {
radeon_enc_code_fixed_bits(enc, 0x0, 1);
/* long-term reference */
if (enc->enc_pic.ref_idx_l0_is_ltr) {
radeon_enc_code_fixed_bits(enc, 0x1, 1); /* ref_pic_list_modification_flag_l0 */
radeon_enc_code_ue(enc, 0x2); /* modification_of_pic_nums_idc */
radeon_enc_code_ue(enc, enc->enc_pic.ref_idx_l0); /* long_term_pic_num */
radeon_enc_code_ue(enc, 0x3);
}
/* short-term reference */
/* list_mod_diff_pic_minus1 != 0 */
if (enc->enc_pic.frame_num - enc->enc_pic.ref_idx_l0 > 1) {
else if (enc->enc_pic.frame_num - enc->enc_pic.ref_idx_l0 > 1) {
radeon_enc_code_fixed_bits(enc, 0x1, 1); /* ref_pic_list_modification_flag_l0 */
radeon_enc_code_ue(enc, 0x0); /* modification_of_pic_nums_idc */
/* abs_diff_pic_num_minus1 */
@@ -878,10 +887,22 @@ static void radeon_enc_slice_header(struct radeon_encoder *enc)
if (enc->enc_pic.is_idr) {
radeon_enc_code_fixed_bits(enc, 0x0, 1);
radeon_enc_code_fixed_bits(enc, 0x0, 1);
} else if (!enc->enc_pic.not_referenced)
radeon_enc_code_fixed_bits(enc, 0x0, 1);
if (enc->enc_pic.is_ltr)
radeon_enc_code_fixed_bits(enc, 0x1, 1); /* long_term_reference_flag */
else
radeon_enc_code_fixed_bits(enc, 0x0, 1);
} else if (!enc->enc_pic.not_referenced) {
if (enc->enc_pic.is_ltr) {
radeon_enc_code_fixed_bits(enc, 0x1, 1);
radeon_enc_code_ue(enc, 0x4); /* memory_management_control_operation */
radeon_enc_code_ue(enc, enc->max_ltr_idx + 1); /* max_long_term_frame_idx_plus1 */
radeon_enc_code_ue(enc, 0x6); /*memory_management_control_operation */
radeon_enc_code_ue(enc, enc->enc_pic.ltr_idx); /* long_term_frame_idx */
radeon_enc_code_ue(enc, 0x0); /*memory_management_control_operation end*/
} else
radeon_enc_code_fixed_bits(enc, 0x0, 1);
}
if ((enc->enc_pic.picture_type != PIPE_H2645_ENC_PICTURE_TYPE_IDR) &&
(enc->enc_pic.spec_misc.cabac_enable))
radeon_enc_code_ue(enc, enc->enc_pic.spec_misc.cabac_init_idc);
@@ -1312,17 +1333,42 @@ static void destroy(struct radeon_encoder *enc)
*enc->p_task_size = (enc->total_task_size);
}
static int find_short_ref_idx(struct radeon_encoder *enc, int frame_num)
static int find_ref_idx(struct radeon_encoder *enc, int pic_num, bool is_ltr)
{
for (int i = 0; i < enc->base.max_references + 1; i++)
if (enc->dpb_info[i].frame_num == frame_num && enc->dpb_info[i].in_use)
for (int i = 0; i < enc->base.max_references + 1; i++) {
if (enc->dpb_info[i].pic_num == pic_num &&
enc->dpb_info[i].in_use &&
enc->dpb_info[i].is_ltr == is_ltr)
return i;
}
return -1;
}
static int get_picture_storage(struct radeon_encoder *enc)
{
if (enc->enc_pic.is_ltr) {
if (enc->enc_pic.is_idr) {
enc->enc_pic.ltr_idx = 0;
enc->max_ltr_idx = 0;
}
/*
find ltr with the same ltr_idx to replace
if this is a new ltr_idx, increase max_ltr_idx and use the normal logic to find slot
*/
if (enc->enc_pic.ltr_idx <= enc->max_ltr_idx) {
for (int i = 0; i < enc->base.max_references + 1; i++) {
if (enc->dpb_info[i].in_use &&
enc->dpb_info[i].is_ltr &&
enc->enc_pic.ltr_idx == enc->dpb_info[i].pic_num) {
enc->dpb_info[i].in_use = FALSE;
return i;
}
}
} else
enc->max_ltr_idx = enc->enc_pic.ltr_idx;
}
for (int i = 0; i < enc->base.max_references + 1; i++) {
if (!enc->dpb_info[i].in_use) {
memset(&(enc->dpb_info[i]), 0, sizeof(rvcn_enc_picture_info_t));
@@ -1334,8 +1380,8 @@ static int get_picture_storage(struct radeon_encoder *enc)
unsigned int oldest_frame_num = 0xFFFFFFFF;
int oldest_idx = -1;
for (int i = 0; i < enc->base.max_references + 1; i++)
if (enc->dpb_info[i].frame_num < oldest_frame_num) {
oldest_frame_num = enc->dpb_info[i].frame_num;
if (!enc->dpb_info[i].is_ltr && enc->dpb_info[i].pic_num < oldest_frame_num) {
oldest_frame_num = enc->dpb_info[i].pic_num;
oldest_idx = i;
}
@@ -1358,12 +1404,18 @@ static void manage_dpb_before_encode(struct radeon_encoder *enc)
current_pic_idx = get_picture_storage(enc);
assert(current_pic_idx >= 0);
int ref0_idx = find_short_ref_idx(enc, enc->enc_pic.ref_idx_l0);
int ref0_idx = find_ref_idx(enc, enc->enc_pic.ref_idx_l0, enc->enc_pic.ref_idx_l0_is_ltr);
if (!enc->enc_pic.not_referenced)
enc->dpb_info[current_pic_idx].in_use = TRUE;
enc->dpb_info[current_pic_idx].frame_num = enc->enc_pic.frame_num;
if (enc->enc_pic.is_ltr) {
enc->dpb_info[current_pic_idx].pic_num = enc->enc_pic.ltr_idx;
enc->dpb_info[current_pic_idx].is_ltr = TRUE;
} else {
enc->dpb_info[current_pic_idx].pic_num = enc->enc_pic.frame_num;
enc->dpb_info[current_pic_idx].is_ltr = FALSE;
}
if (enc->enc_pic.picture_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR)
enc->enc_pic.enc_params.reference_picture_index = 0xFFFFFFFF;
+14 -2
View File
@@ -40,6 +40,9 @@ vlVaHandleVAEncPictureParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *cont
context->desc.h264enc.frame_num = 0;
context->desc.h264enc.not_referenced = !h264->pic_fields.bits.reference_pic_flag;
context->desc.h264enc.pic_order_cnt = h264->CurrPic.TopFieldOrderCnt;
context->desc.h264enc.is_ltr = h264->CurrPic.flags & VA_PICTURE_H264_LONG_TERM_REFERENCE;
if (context->desc.h264enc.is_ltr)
context->desc.h264enc.ltr_index = h264->CurrPic.frame_idx;
if (context->desc.h264enc.gop_cnt == 0)
context->desc.h264enc.i_remain = context->gop_coeff;
else if (context->desc.h264enc.frame_num == 1)
@@ -53,7 +56,12 @@ vlVaHandleVAEncPictureParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *cont
PIPE_USAGE_STREAM, coded_buf->size);
context->coded_buf = coded_buf;
_mesa_hash_table_insert(context->desc.h264enc.frame_idx,
if (context->desc.h264enc.is_ltr)
_mesa_hash_table_insert(context->desc.h264enc.frame_idx,
UINT_TO_PTR(h264->CurrPic.picture_id + 1),
UINT_TO_PTR(context->desc.h264enc.ltr_index));
else
_mesa_hash_table_insert(context->desc.h264enc.frame_idx,
UINT_TO_PTR(h264->CurrPic.picture_id + 1),
UINT_TO_PTR(context->desc.h264enc.frame_num));
@@ -98,10 +106,14 @@ vlVaHandleVAEncSliceParameterBufferTypeH264(vlVaDriver *drv, vlVaContext *contex
if (h264->RefPicList0[i].picture_id != VA_INVALID_ID) {
context->desc.h264enc.ref_idx_l0_list[i] = PTR_TO_UINT(util_hash_table_get(context->desc.h264enc.frame_idx,
UINT_TO_PTR(h264->RefPicList0[i].picture_id + 1)));
context->desc.h264enc.l0_is_long_term[i] = h264->RefPicList0[i].flags &
VA_PICTURE_H264_LONG_TERM_REFERENCE;
}
if (h264->RefPicList1[i].picture_id != VA_INVALID_ID && h264->slice_type == 1) {
context->desc.h264enc.ref_idx_l1_list[i] = PTR_TO_UINT(util_hash_table_get(context->desc.h264enc.frame_idx,
UINT_TO_PTR(h264->RefPicList1[i].picture_id + 1)));
UINT_TO_PTR(h264->RefPicList1[i].picture_id + 1)));
context->desc.h264enc.l1_is_long_term[i] = h264->RefPicList1[i].flags &
VA_PICTURE_H264_LONG_TERM_REFERENCE;
}
}
+4
View File
@@ -481,12 +481,16 @@ struct pipe_h264_enc_picture_desc
unsigned num_ref_idx_l0_active_minus1;
unsigned num_ref_idx_l1_active_minus1;
unsigned ref_idx_l0_list[32];
bool l0_is_long_term[32];
unsigned ref_idx_l1_list[32];
bool l1_is_long_term[32];
unsigned gop_size;
unsigned num_temporal_layers;
struct pipe_enc_quality_modes quality_modes;
bool not_referenced;
bool is_ltr;
unsigned ltr_index;
bool enable_vui;
struct hash_table *frame_idx;