EasyRTMP视频直播推送H264 sps解析错误导致播放画面拉伸问题解决

来源:互联网 发布:python 逆矩阵 编辑:程序博客网 时间:2024/06/05 20:15

EasyRTMP是将H264流以及AAC流以RTMP协议推送到RTMP服务器上进行直播。EasyRTMP推送库中会从H264流中提取中SPS、PPS进行解析,开发的时候遇到过有些SPS解析有误,获取到的宽高不正确,导致播放的时候画面被拉长的问题。下面给出一份比较完善的SPS解析

SPS解析

定义sps结构

typedef struct{    int i_id;    int i_profile_idc;    int i_level_idc;    int b_constraint_set0;    int b_constraint_set1;    int b_constraint_set2;    int i_chroma_format_idc;    int i_log2_max_frame_num;    int i_poc_type;    /* poc 0 */    int i_log2_max_poc_lsb;    /* poc 1 */    int b_delta_pic_order_always_zero;    int i_offset_for_non_ref_pic;    int i_offset_for_top_to_bottom_field;    int i_num_ref_frames_in_poc_cycle;    int i_offset_for_ref_frame[256];    int i_num_ref_frames;    int b_gaps_in_frame_num_value_allowed;    int i_mb_width;    int i_mb_height;    int b_frame_mbs_only;    int b_mb_adaptive_frame_field;    int b_direct8x8_inference;    int b_crop;    struct    {        int i_left;        int i_right;        int i_top;        int i_bottom;    } crop;    int b_vui;    struct    {        int b_aspect_ratio_info_present;        int i_sar_width;        int i_sar_height;        int b_overscan_info_present;        int b_overscan_info;        int b_signal_type_present;        int i_vidformat;        int b_fullrange;        int b_color_description_present;        int i_colorprim;        int i_transfer;        int i_colmatrix;        int b_chroma_loc_info_present;        int i_chroma_loc_top;        int i_chroma_loc_bottom;        int b_timing_info_present;        int i_num_units_in_tick;        int i_time_scale;        int b_fixed_frame_rate;        int nal_hrd_parameters_present_flag;        int vcl_hrd_parameters_present_flag;        int pic_struct_present_flag;        int b_bitstream_restriction;        int b_motion_vectors_over_pic_boundaries;        int i_max_bytes_per_pic_denom;        int i_max_bits_per_mb_denom;        int i_log2_max_mv_length_horizontal;        int i_log2_max_mv_length_vertical;        int i_num_reorder_frames;        int i_max_dec_frame_buffering;        /* FIXME to complete */    } vui;    int b_qpprime_y_zero_transform_bypass;    int scaling_matrix_present;    uint8_t scaling_matrix4[6][16];    uint8_t scaling_matrix8[6][64];} h264_sps_t;

解析SPS数据,得到h264_sps_t结构的数据

/* return -1 if invalid, else the id */int h264_sps_read( unsigned char *nal, int nal_len, h264_sps_t *sps){    int i_profile_idc;    int i_level_idc;    int b_constraint_set0;    int b_constraint_set1;    int b_constraint_set2;    int id;    bs_t bs;    bs_t *s = &bs;    sps->scaling_matrix_present = 0;    bs_init( &bs, nal+1, nal_len-1 );    //P264_TRACE_ADDRESS();    i_profile_idc     = bs_read( s, 8 );    //_TRACE2("SPS: profile_idc = %d\n", i_profile_idc);    b_constraint_set0 = bs_read( s, 1 );    b_constraint_set1 = bs_read( s, 1 );    b_constraint_set2 = bs_read( s, 1 );    bs_skip( s, 5 );    /* reserved */    //P264_TRACE_ADDRESS();    i_level_idc       = bs_read( s, 8 );    //_TRACE2("SPS: level_idc = %d\n", i_level_idc);    id = bs_read_ue( s );    if( bs_eof( s ) || id >= 32 )    {        /* the sps is invalid, no need to corrupt sps_array[0] */        return -1;    }    sps->i_id = id;    /* put pack parsed value */    sps->i_profile_idc     = i_profile_idc;    sps->i_level_idc       = i_level_idc;    sps->b_constraint_set0 = b_constraint_set0;    sps->b_constraint_set1 = b_constraint_set1;    sps->b_constraint_set2 = b_constraint_set2;    if(sps->i_profile_idc >= 100){ //high profile        sps->i_chroma_format_idc= bs_read_ue( s );        if(sps->i_chroma_format_idc >= 32 )            return -1;        if(sps->i_chroma_format_idc == 3)            bs_read( s, 1 );//residual_color_transform_flag        //sps->bit_depth_luma   = get_ue_golomb(&s->gb) + 8;        //sps->bit_depth_chroma = get_ue_golomb(&s->gb) + 8;        //sps->transform_bypass = get_bits1(&s->gb);        /* bit_depth_luma_minus8 */        bs_read_ue( s );        /* bit_depth_chroma_minus8 */        bs_read_ue( s );        /* qpprime_y_zero_transform_bypass_flag */        bs_skip( s, 1 );        /* seq_scaling_matrix_present_flag */        int seq_scaling_matrix_present_flag = bs_read( s, 1 );        //decode_scaling_matrices(s, sps, NULL, 1, sps->scaling_matrix4, sps->scaling_matrix8);            if (seq_scaling_matrix_present_flag)            {                for( int i = 0; i < ((3 != sps->i_chroma_format_idc) ? 8 : 12); i++ )                {                    /* seq_scaling_list_present_flag[i] */                    seq_scaling_matrix_present_flag = bs_read( s, 1 );                    if( !seq_scaling_matrix_present_flag )                        continue;                    const int i_size_of_scaling_list = (i < 6 ) ? 16 : 64;                    /* scaling_list (...) */                    int i_lastscale = 8;                    int i_nextscale = 8;                    for( int j = 0; j < i_size_of_scaling_list; j++ )                    {                        if( i_nextscale != 0 )                        {                            /* delta_scale */                            seq_scaling_matrix_present_flag = bs_read_se( s );                            i_nextscale = ( i_lastscale + seq_scaling_matrix_present_flag + 256 ) % 256;                            /* useDefaultScalingMatrixFlag = ... */                        }                        /* scalinglist[j] */                        i_lastscale = ( i_nextscale == 0 ) ? i_lastscale : i_nextscale;                    }                }            }    }    //sps->i_log2_max_frame_num = bs_read_ue( s ) + 4;    //sps->i_log2_max_frame_num = 2^(bs_read_ue( s ) + 4);    sps->i_log2_max_frame_num = bs_read_ue( s );    sps->i_poc_type = bs_read_ue( s );    if( sps->i_poc_type == 0 )    {        sps->i_log2_max_poc_lsb = bs_read_ue( s ) + 4;    }    else if( sps->i_poc_type == 1 )    {        int i;        sps->b_delta_pic_order_always_zero = bs_read( s, 1 );        sps->i_offset_for_non_ref_pic = bs_read_se( s );        sps->i_offset_for_top_to_bottom_field = bs_read_se( s );        sps->i_num_ref_frames_in_poc_cycle = bs_read_ue( s );        if( sps->i_num_ref_frames_in_poc_cycle > 256 )        {            /* FIXME what to do */            sps->i_num_ref_frames_in_poc_cycle = 256;        }        for( i = 0; i < sps->i_num_ref_frames_in_poc_cycle; i++ )        {            sps->i_offset_for_ref_frame[i] = bs_read_se( s );        }    }    else if( sps->i_poc_type > 2 )    {        goto error;    }    sps->i_num_ref_frames = bs_read_ue( s );    //_TRACE2("SPS: num_ref_frames = %d\n", sps->i_num_ref_frames);    sps->b_gaps_in_frame_num_value_allowed = bs_read( s, 1 );    sps->i_mb_width = bs_read_ue( s ) + 1;    //_TRACE2("SPS: mb_width = %d\n", sps->i_mb_width);    sps->i_mb_height= bs_read_ue( s ) + 1;    //_TRACE2("SPS: mb_height = %d\n", sps->i_mb_height);    sps->b_frame_mbs_only = bs_read( s, 1 );    if( !sps->b_frame_mbs_only )    {        sps->b_mb_adaptive_frame_field = bs_read( s, 1 );    }    else    {        sps->b_mb_adaptive_frame_field = 0;    }    sps->b_direct8x8_inference = bs_read( s, 1 );    sps->b_crop = bs_read( s, 1 );    if( sps->b_crop )    {        sps->crop.i_left  = bs_read_ue( s );        sps->crop.i_right = bs_read_ue( s );        sps->crop.i_top   = bs_read_ue( s );        sps->crop.i_bottom= bs_read_ue( s );    }    else    {        sps->crop.i_left  = 0;        sps->crop.i_right = 0;        sps->crop.i_top   = 0;        sps->crop.i_bottom= 0;    }    sps->b_vui = bs_read( s, 1 );    if( sps->b_vui )    {        /* FIXME */        //_TRACE2( "decode vui %d\n", bs_pos(s) );        decode_vui_parameters(s, sps);    }    if( bs_eof( s ) )    {        /* no rbsp trailing */        //_TRACE2( "incomplete SPS\n" );        sps->i_id = -1;        return -1000;    }    return id;error:    /* invalidate this sps */    sps->i_id = -1;    return -1;}

获取更多信息

邮件:support@easydarwin.org

WEB:www.EasyDarwin.org

Copyright © EasyDarwin.org 2012-2016

EasyDarwin

0 0
原创粉丝点击