[H264]x264_encoder_headers函数
##x264_encoder_headers
#####H264中我们所说的帧是不包含全部的视频的数据的,它是由网络数据NAL和视频数据VCL组成。这个函数主要用来生成一个帧的NAL数据层,这个函数主要是输出SPS、PPS、SEI等数据封装。
具体来看代码
int x264_encoder_headers( x264_t *h, x264_nal_t **pp_nal, int *pi_nal )
{
int frame_size = 0;
/* init bitstream context */
h->out.i_nal = 0;
bs_init( &h->out.bs, h->out.p_bitstream, h->out.i_bitstream );
/* Write SEI, SPS and PPS. */
/* generate sequence parameters */
x264_nal_start( h, NAL_SPS, NAL_PRIORITY_HIGHEST );
x264_sps_write( &h->out.bs, h->sps );
if( x264_nal_end( h ) )
return -1;
/* generate picture parameters */
x264_nal_start( h, NAL_PPS, NAL_PRIORITY_HIGHEST );
x264_pps_write( &h->out.bs, h->sps, h->pps );
if( x264_nal_end( h ) )
return -1;
/* identify ourselves */
x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
if( x264_sei_version_write( h, &h->out.bs ) )
return -1;
if( x264_nal_end( h ) )
return -1;
frame_size = x264_encoder_encapsulate_nals( h, 0 );
if( frame_size < 0 )
return -1;
/* now set output*/
*pi_nal = h->out.i_nal;
*pp_nal = &h->out.nal[0];
h->out.i_nal = 0;
return frame_size;
}
进入这个函数后,bs_init()先申请内存用来存放比特流数据的内存块,x264_nal_start接着生成SPS信息并存放在h->out.nal[h->out.inal]中,接着,将SPS信息写入h->sps[0]之中,如下
void x264_sps_write( bs_t *s, x264_sps_t *sps )
{
bs_realign( s );
//这个函数将8bit写入s->cur_bits中
//profile的含义见https://blog.csdn.net/heanyu/article/details/6204414
bs_write( s, 8, sps->i_profile_idc );
//左移写入四bit数据,为0不用遵从附录A2.1的条件
bs_write1( s, sps->b_constraint_set0 );
bs_write1( s, sps->b_constraint_set1 );
bs_write1( s, sps->b_constraint_set2 );
bs_write1( s, sps->b_constraint_set3 );
//保留的4位
bs_write( s, 4, 0 ); /* reserved */
//写入的水平,代表分辨率,同样见https://blog.csdn.net/heanyu/article/details/6204414
bs_write( s, 8, sps->i_level_idc );
//写入SPS的ID号码
bs_write_ue( s, sps->i_id );
if( sps->i_profile_idc >= PROFILE_HIGH )
{
bs_write_ue( s, sps->i_chroma_format_idc );
if( sps->i_chroma_format_idc == CHROMA_444 )
bs_write1( s, 0 ); // separate_colour_plane_flag
bs_write_ue( s, BIT_DEPTH-8 ); // bit_depth_luma_minus8
bs_write_ue( s, BIT_DEPTH-8 ); // bit_depth_chroma_minus8
bs_write1( s, sps->b_qpprime_y_zero_transform_bypass );
bs_write1( s, 0 ); // seq_scaling_matrix_present_flag
}
bs_write_ue( s, sps->i_log2_max_frame_num - 4 );
bs_write_ue( s, sps->i_poc_type );
if( sps->i_poc_type == 0 )
bs_write_ue( s, sps->i_log2_max_poc_lsb - 4 );
bs_write_ue( s, sps->i_num_ref_frames );
bs_write1( s, sps->b_gaps_in_frame_num_value_allowed );
bs_write_ue( s, sps->i_mb_width - 1 );
bs_write_ue( s, (sps->i_mb_height >> !sps->b_frame_mbs_only) - 1);
bs_write1( s, sps->b_frame_mbs_only );
if( !sps->b_frame_mbs_only )
bs_write1( s, sps->b_mb_adaptive_frame_field );
bs_write1( s, sps->b_direct8x8_inference );
bs_write1( s, sps->b_crop );
if( sps->b_crop )
{
int h_shift = sps->i_chroma_format_idc == CHROMA_420 || sps->i_chroma_format_idc == CHROMA_422;
int v_shift = sps->i_chroma_format_idc == CHROMA_420;
bs_write_ue( s, sps->crop.i_left >> h_shift );
bs_write_ue( s, sps->crop.i_right >> h_shift );
bs_write_ue( s, sps->crop.i_top >> v_shift );
bs_write_ue( s, sps->crop.i_bottom >> v_shift );
}
bs_write1( s, sps->b_vui );
if( sps->b_vui )
{
bs_write1( s, sps->vui.b_aspect_ratio_info_present );
if( sps->vui.b_aspect_ratio_info_present )
{
int i;
static const struct { uint8_t w, h, sar; } sar[] =
{
// aspect_ratio_idc = 0 -> unspecified
{ 1, 1, 1 }, { 12, 11, 2 }, { 10, 11, 3 }, { 16, 11, 4 },
{ 40, 33, 5 }, { 24, 11, 6 }, { 20, 11, 7 }, { 32, 11, 8 },
{ 80, 33, 9 }, { 18, 11, 10}, { 15, 11, 11}, { 64, 33, 12},
{160, 99, 13}, { 4, 3, 14}, { 3, 2, 15}, { 2, 1, 16},
// aspect_ratio_idc = [17..254] -> reserved
{ 0, 0, 255 }
};
for( i = 0; sar[i].sar != 255; i++ )
{
if( sar[i].w == sps->vui.i_sar_width &&
sar[i].h == sps->vui.i_sar_height )
break;
}
bs_write( s, 8, sar[i].sar );
if( sar[i].sar == 255 ) /* aspect_ratio_idc (extended) */
{
bs_write( s, 16, sps->vui.i_sar_width );
bs_write( s, 16, sps->vui.i_sar_height );
}
}
bs_write1( s, sps->vui.b_overscan_info_present );
if( sps->vui.b_overscan_info_present )
bs_write1( s, sps->vui.b_overscan_info );
bs_write1( s, sps->vui.b_signal_type_present );
if( sps->vui.b_signal_type_present )
{
bs_write( s, 3, sps->vui.i_vidformat );
bs_write1( s, sps->vui.b_fullrange );
bs_write1( s, sps->vui.b_color_description_present );
if( sps->vui.b_color_description_present )
{
bs_write( s, 8, sps->vui.i_colorprim );
bs_write( s, 8, sps->vui.i_transfer );
bs_write( s, 8, sps->vui.i_colmatrix );
}
}
bs_write1( s, sps->vui.b_chroma_loc_info_present );
if( sps->vui.b_chroma_loc_info_present )
{
bs_write_ue( s, sps->vui.i_chroma_loc_top );
bs_write_ue( s, sps->vui.i_chroma_loc_bottom );
}
bs_write1( s, sps->vui.b_timing_info_present );
if( sps->vui.b_timing_info_present )
{
bs_write32( s, sps->vui.i_num_units_in_tick );
bs_write32( s, sps->vui.i_time_scale );
bs_write1( s, sps->vui.b_fixed_frame_rate );
}
bs_write1( s, sps->vui.b_nal_hrd_parameters_present );
if( sps->vui.b_nal_hrd_parameters_present )
{
bs_write_ue( s, sps->vui.hrd.i_cpb_cnt - 1 );
bs_write( s, 4, sps->vui.hrd.i_bit_rate_scale );
bs_write( s, 4, sps->vui.hrd.i_cpb_size_scale );
bs_write_ue( s, sps->vui.hrd.i_bit_rate_value - 1 );
bs_write_ue( s, sps->vui.hrd.i_cpb_size_value - 1 );
bs_write1( s, sps->vui.hrd.b_cbr_hrd );
bs_write( s, 5, sps->vui.hrd.i_initial_cpb_removal_delay_length - 1 );
bs_write( s, 5, sps->vui.hrd.i_cpb_removal_delay_length - 1 );
bs_write( s, 5, sps->vui.hrd.i_dpb_output_delay_length - 1 );
bs_write( s, 5, sps->vui.hrd.i_time_offset_length );
}
bs_write1( s, sps->vui.b_vcl_hrd_parameters_present );
if( sps->vui.b_nal_hrd_parameters_present || sps->vui.b_vcl_hrd_parameters_present )
bs_write1( s, 0 ); /* low_delay_hrd_flag */
bs_write1( s, sps->vui.b_pic_struct_present );
bs_write1( s, sps->vui.b_bitstream_restriction );
if( sps->vui.b_bitstream_restriction )
{
bs_write1( s, sps->vui.b_motion_vectors_over_pic_boundaries );
bs_write_ue( s, sps->vui.i_max_bytes_per_pic_denom );
bs_write_ue( s, sps->vui.i_max_bits_per_mb_denom );
bs_write_ue( s, sps->vui.i_log2_max_mv_length_horizontal );
bs_write_ue( s, sps->vui.i_log2_max_mv_length_vertical );
bs_write_ue( s, sps->vui.i_num_reorder_frames );
bs_write_ue( s, sps->vui.i_max_dec_frame_buffering );
}
}
bs_rbsp_trailing( s );
bs_flush( s );
}