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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user