zoukankan      html  css  js  c++  java
  • EasyRTMP视频直播推送H264 sps解析错误导致播放画面拉伸问题解决

    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
    ", 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
    ", 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
    ", 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
    ", sps->i_mb_width);
        sps->i_mb_height= bs_read_ue( s ) + 1;
        //_TRACE2("SPS: mb_height = %d
    ", 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
    ", bs_pos(s) );
            decode_vui_parameters(s, sps);
        }
    
        if( bs_eof( s ) )
        {
            /* no rbsp trailing */
            //_TRACE2( "incomplete SPS
    " );
            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

  • 相关阅读:
    Effective Java 19 Use interfaces only to define types
    Effective Java 18 Prefer interfaces to abstract classes
    Effective Java 17 Design and document for inheritance or else prohibit it
    Effective Java 16 Favor composition over inheritance
    Effective Java 15 Minimize mutability
    Effective Java 14 In public classes, use accessor methods, not public fields
    Effective Java 13 Minimize the accessibility of classes and members
    Effective Java 12 Consider implementing Comparable
    sencha touch SortableList 的使用
    sencha touch dataview 中添加 button 等复杂布局并添加监听事件
  • 原文地址:https://www.cnblogs.com/babosa/p/7348802.html
Copyright © 2011-2022 走看看