Fix h264 on intel vaapi

This commit is contained in:
mittorn 2024-09-30 18:49:48 +03:00
parent ffd6bb3d7d
commit 01293b5565

View file

@ -58,8 +58,9 @@
#define SLICE_TYPE_P 0
#define SLICE_TYPE_B 1
#define SLICE_TYPE_I 2
#define SLICE_TYPE_P_ONLY 5
#define IS_P_SLICE(type) (SLICE_TYPE_P == (type))
#define IS_P_SLICE(type) (SLICE_TYPE_P == (type) || SLICE_TYPE_P_ONLY == (type))
#define IS_B_SLICE(type) (SLICE_TYPE_B == (type))
#define IS_I_SLICE(type) (SLICE_TYPE_I == (type))
@ -370,11 +371,14 @@ encoder_init_seq_parameters(struct vaapi_recorder *r)
r->encoder.param.seq.level_idc = 60;
r->encoder.param.seq.intra_period = 32767; //r->encoder.intra_period;
r->encoder.param.seq.intra_idr_period = 32767;
r->encoder.param.seq.max_num_ref_frames = 1;
r->encoder.param.seq.picture_width_in_mbs = width_in_mbs;
r->encoder.param.seq.picture_height_in_mbs = height_in_mbs;
r->encoder.param.seq.seq_fields.bits.chroma_format_idc = 1;
r->encoder.param.seq.seq_fields.bits.frame_mbs_only_flag = 1;
r->encoder.param.seq.ip_period = 1;
/* Tc = num_units_in_tick / time_scale */
r->encoder.param.seq.time_scale = 180;
@ -388,7 +392,7 @@ encoder_init_seq_parameters(struct vaapi_recorder *r)
r->encoder.param.seq.frame_cropping_flag = frame_cropping_flag;
r->encoder.param.seq.frame_crop_bottom_offset = frame_crop_bottom_offset;
r->encoder.param.seq.seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = 0;
r->encoder.param.seq.seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = 0;//12;
r->encoder.param.seq.seq_fields.bits.log2_max_frame_num_minus4 = 4;
r->encoder.param.seq.seq_fields.bits.pic_order_cnt_type = 2;
}
@ -442,11 +446,12 @@ encoder_update_pic_parameters(struct vaapi_recorder *r,
pic->CurrPic.picture_id = curr_pic;
pic->CurrPic.frame_idx = r->frame_count;
pic->CurrPic.TopFieldOrderCnt = 0;//r->frame_count * 2;
pic->CurrPic.TopFieldOrderCnt = r->encoder.param.seq.seq_fields.bits.pic_order_cnt_type == 0? r->frame_count:0;
for(int i = 0; i < 16; i++)
{
pic->ReferenceFrames[i].picture_id = VA_INVALID_ID;
pic->ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID;
pic->ReferenceFrames[i].frame_idx = 0;
}
if(r->frame_count)
{
@ -496,11 +501,13 @@ encoder_update_slice_parameter(struct vaapi_recorder *r, int slice_type)
{
r->encoder.param.slice.RefPicList0[i].picture_id = VA_INVALID_ID;
r->encoder.param.slice.RefPicList0[i].flags = VA_PICTURE_H264_INVALID;
r->encoder.param.slice.RefPicList0[i].frame_idx = 0;
}
for(int i = 0; i < 32; i++)
{
r->encoder.param.slice.RefPicList1[i].picture_id = VA_INVALID_ID;
r->encoder.param.slice.RefPicList1[i].flags = VA_PICTURE_H264_INVALID;
r->encoder.param.slice.RefPicList0[i].frame_idx = 0;
}
if(r->frame_count)
{
@ -508,10 +515,11 @@ encoder_update_slice_parameter(struct vaapi_recorder *r, int slice_type)
r->encoder.param.slice.RefPicList0[0].picture_id = r->encoder.reference_picture[(r->frame_count - 1)% 2];
r->encoder.param.slice.RefPicList0[0].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
}
r->encoder.param.slice.pic_order_cnt_lsb = r->encoder.param.seq.seq_fields.bits.pic_order_cnt_type == 0? r->frame_count: 0;
//r->encoder.param.slice.RefPicList0
r->encoder.param.slice.slice_alpha_c0_offset_div2 = 2;
r->encoder.param.slice.slice_beta_offset_div2 = 2;
//r->encoder.param.slice.slice_alpha_c0_offset_div2 = 2;
//r->encoder.param.slice.slice_beta_offset_div2 = 2;
status = vaCreateBuffer(r->va_dpy, r->encoder.ctx,
VAEncSliceParameterBufferType,
@ -675,8 +683,8 @@ static void sps_rbsp(struct bitstream *bs,
}
/* vui_parameters_present_flag */
bitstream_put_ui(bs, 1, 1);
bitstream_put_ui(bs, 0, 1);
#if 0
/* aspect_ratio_info_present_flag */
bitstream_put_ui(bs, 0, 1);
/* overscan_info_present_flag */
@ -707,7 +715,7 @@ static void sps_rbsp(struct bitstream *bs,
bitstream_put_ui(bs, 0, 1);
/* bitstream_restriction_flag */
bitstream_put_ui(bs, 0, 1);
#endif
rbsp_trailing_bits(bs);
}
@ -1039,9 +1047,10 @@ encoder_encode(struct vaapi_recorder *r, VASurfaceID input)
else
slice_type = SLICE_TYPE_P;
if (r->frame_count == 0)
buffers[count++] = encoder_update_seq_parameters(r);
buffers[count++] = encoder_update_misc_hdr_parameter(r);
buffers[count++] = encoder_update_slice_parameter(r, slice_type);
//buffers[count++] = encoder_update_misc_hdr_parameter(r);
VABufferID slice_buf = encoder_update_slice_parameter(r, slice_type);
for (i = 0; i < count; i++)
if (buffers[i] == VA_INVALID_ID)
@ -1057,8 +1066,6 @@ encoder_encode(struct vaapi_recorder *r, VASurfaceID input)
goto bail;
//status = vaRenderPicture(r->va_dpy, r->encoder.ctx, &buffers[2], 1);
do {
output_buf = encoder_create_output_buffer(r);
@ -1072,7 +1079,7 @@ encoder_encode(struct vaapi_recorder *r, VASurfaceID input)
if (r->frame_count == 0)
count += encoder_prepare_headers(r, buffers + count);
// todo: this might be required in every frame
if(r->frame_count == 0)
//if(r->frame_count == 0)
{
void *data;
uint32_t bit_length = build_packed_slice_buffer((unsigned char **)&data, &r->encoder.param.seq, &r->encoder.param.pic, &r->encoder.param.slice );
@ -1080,6 +1087,10 @@ encoder_encode(struct vaapi_recorder *r, VASurfaceID input)
data, bit_length);
free(data);
}
// its important to push slice after packed slice
// otherwise intel encoder will crash on packed slice encoding
// or produce invalid slice header
buffers[count++] = slice_buf;
status = vaRenderPicture(r->va_dpy, r->encoder.ctx, buffers, count);
/*VAStatus er = encoder_render_picture(r, input, buffers, count);
if(er != VA_STATUS_SUCCESS)