解析slice header来判断当前slice的帧类型的代码实现
时间: 2023-07-14 12:13:22 浏览: 228
下面是一个基于H.264标准的slice header解析代码示例,可以用来判断当前slice的帧类型:
```c++
typedef struct
{
int first_mb_in_slice;
int slice_type;
int pic_parameter_set_id;
int frame_num;
int field_pic_flag;
int bottom_field_flag;
int idr_pic_id;
int pic_order_cnt_lsb;
int delta_pic_order_cnt_bottom;
int delta_pic_order_cnt0;
int delta_pic_order_cnt1;
int redundant_pic_cnt;
int direct_spatial_mv_pred_flag;
int num_ref_idx_active_override_flag;
int num_ref_idx_l0_active_minus1;
int num_ref_idx_l1_active_minus1;
int cabac_init_idc;
int slice_qp_delta;
int sp_for_switch_flag;
int slice_qs_delta;
int disable_deblocking_filter_idc;
int slice_alpha_c0_offset_div2;
int slice_beta_offset_div2;
int slice_group_change_cycle;
} slice_header_t;
int get_slice_type(slice_header_t *slice_header)
{
int slice_type = slice_header->slice_type;
if (slice_type == 0 || slice_type == 5)
{
return I_SLICE;
}
else if (slice_type == 1 || slice_type == 6)
{
return P_SLICE;
}
else if (slice_type == 2 || slice_type == 7)
{
return B_SLICE;
}
else if (slice_type == 3 || slice_type == 8)
{
return SP_SLICE;
}
else if (slice_type == 4 || slice_type == 9)
{
return SI_SLICE;
}
else
{
return -1;
}
}
int parse_slice_header(uint8_t *data, slice_header_t *slice_header)
{
bitstream_t bs;
init_bitstream(&bs, data);
slice_header->first_mb_in_slice = read_ue(&bs);
slice_header->slice_type = read_ue(&bs);
slice_header->pic_parameter_set_id = read_ue(&bs);
slice_header->frame_num = read_bits(&bs, 16);
slice_header->field_pic_flag = read_bits(&bs, 1);
if (slice_header->field_pic_flag)
{
slice_header->bottom_field_flag = read_bits(&bs, 1);
}
if (slice_header->nal_unit_type == NAL_IDR_SLICE)
{
slice_header->idr_pic_id = read_ue(&bs);
}
if (slice_header->pic_order_cnt_type == 0)
{
slice_header->pic_order_cnt_lsb = read_bits(&bs, slice_header->log2_max_pic_order_cnt_lsb_minus4 + 4);
if (slice_header->delta_pic_order_always_zero_flag)
{
slice_header->delta_pic_order_cnt_bottom = 0;
slice_header->delta_pic_order_cnt0 = 0;
slice_header->delta_pic_order_cnt1 = 0;
}
else
{
if (slice_header->delta_pic_order_cnt_bottom_exist)
{
slice_header->delta_pic_order_cnt_bottom = read_se(&bs);
}
if (slice_header->delta_pic_order_cnt0_exist)
{
slice_header->delta_pic_order_cnt0 = read_se(&bs);
}
if (slice_header->delta_pic_order_cnt1_exist)
{
slice_header->delta_pic_order_cnt1 = read_se(&bs);
}
}
}
else if (slice_header->pic_order_cnt_type == 1)
{
// TODO: implement
}
slice_header->redundant_pic_cnt = read_ue(&bs);
if (is_slice_type_B(slice_header->slice_type))
{
slice_header->direct_spatial_mv_pred_flag = read_bits(&bs, 1);
}
if (is_slice_type_P(slice_header->slice_type) || is_slice_type_SP(slice_header->slice_type) || is_slice_type_B(slice_header->slice_type))
{
slice_header->num_ref_idx_active_override_flag = read_bits(&bs, 1);
if (slice_header->num_ref_idx_active_override_flag)
{
slice_header->num_ref_idx_l0_active_minus1 = read_ue(&bs);
if (is_slice_type_B(slice_header->slice_type))
{
slice_header->num_ref_idx_l1_active_minus1 = read_ue(&bs);
}
}
}
if (slice_header->slice_type == 2 || slice_header->slice_type == 4 || slice_header->slice_type == 7 || slice_header->slice_type == 9)
{
slice_header->sp_for_switch_flag = read_bits(&bs, 1);
}
if (slice_header->slice_type == 1 || slice_header->slice_type == 6 || slice_header->slice_type == 3 || slice_header->slice_type == 8)
{
slice_header->slice_qs_delta = read_se(&bs);
}
if (slice_header->use_default_scaling_matrix_flag)
{
// TODO: implement
}
else
{
// TODO: implement
}
if (slice_header->disable_deblocking_filter_idc != 1)
{
slice_header->slice_alpha_c0_offset_div2 = read_se(&bs);
slice_header->slice_beta_offset_div2 = read_se(&bs);
}
if (slice_header->slice_group_map_type >= 3 && slice_header->slice_group_map_type <= 5)
{
// TODO: implement
}
if (slice_header->slice_group_change_direction_flag)
{
slice_header->slice_group_change_rate_minus1 = read_ue(&bs);
}
if (slice_header->slice_group_change_direction_flag || (slice_header->slice_group_change_cycle != 0 && slice_header->pic_parameter_set_id == 0))
{
// TODO: implement
}
return 0;
}
```
在这个代码示例中,我们定义了一个slice_header_t结构体来保存slice header中的各个参数。然后我们实现了一个parse_slice_header函数,用来解析slice header中各个参数的值。最后,我们定义了一个get_slice_type函数来根据slice_header中的slice_type参数来判断当前slice的帧类型。
阅读全文