首页 > 代码库 > 通过H264获取分辨率,FFmpeg

通过H264获取分辨率,FFmpeg

每次从liveView callback的数据,需要放入解码库,但是解码库就需要分辨率信息,当然有写解码库,会自动确认,但是当解码库,没有做这个处理的时候怎么办?

 

这时候就需要我们自己去从buffer中解析分辨率

 

 

 以下是别人的总结============================================

http://www.oschina.net/question/225813_35707

 

解析sps,pps的代码在ffmpeg里面就有, 抄出来就行了, 我以前也自己写过...
ffmpeg的libavcodec/h264_parser.c,
h264_ps.c
函数
ff_h264_decode_seq_parameter_set
ff_h264_decode_picture_parameter_set
自己可以看代码.

 

==================================

还有这个

http://www.cnblogs.com/likwo/p/3531241.html

 

总体来说就是

使用RTP传输的时候,需要用到sdp协议描述,其中有两项:Sequence Parameter Sets (SPS) 和Picture Parameter Set (PPS) 需要用到,那么这两项从哪里获取呢?答案是从H264码流中获取.在H264码流中,都是以"0x00 0x00 0x01"或者"0x00 0x00 0x00 0x01"为开始码的,找到开始码之后,使用开始码之后的第一个字节的低5位判断是否为7(sps)或者8(pps), 及data[4] & 0x1f == 7 || data[4] & 0x1f == 8.然后对获取的nal去掉开始码之后进行base64编码,得到的信息就可以用于sdp.sps和pps需要用逗号分隔开来.

 

 

===============================

对比了下FFMpeg修改的

重点是你要知道有哪些分辨率

 

  if (sps->profile_idc == 100 ||  // High profile
        sps->profile_idc == 110 ||  // High10 profile
        sps->profile_idc == 122 ||  // High422 profile
        sps->profile_idc == 244 ||  // High444 Predictive profile
        sps->profile_idc ==  44 ||  // Cavlc444 profile
        sps->profile_idc ==  83 ||  // Scalable Constrained High profile (SVC)
        sps->profile_idc ==  86 ||  // Scalable High Intra profile (SVC)
        sps->profile_idc == 118 ||  // Stereo High profile (MVC)
        sps->profile_idc == 128 ||  // Multiview High profile (MVC)
        sps->profile_idc == 138 ||  // Multiview Depth High profile (MVCD)
        sps->profile_idc == 144) {  // old High444 profile

 

1080p,960p,VGA 640*480, 还有几个DVR的300多*200多的,分辨率的都解析成功了。:-)

 

 

 

// Ue find the num of zeros and get (num+1) bits from the first 1, and // change it to decimal// e.g. 00110 -> return 6(110)unsigned int Ue(unsigned char *pBuff, unsigned int nLen, unsigned int &nStartBit){    //计算0bit的个数    unsigned int nZeroNum = 0;    while (nStartBit < nLen * 8)    {        //&:按位与,%取余        if (pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8)))         {            break;        }        nZeroNum++;        nStartBit++;    }        nStartBit++;    //计算结果    unsigned int dwRet = 0;    for (unsigned int i = 0; i < nZeroNum; i++)    {        dwRet <<= 1;        if (pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8)))        {            dwRet += 1;        }        nStartBit++;    }    return (1 << nZeroNum) - 1 + dwRet;}int Se(unsigned char *pBuff, unsigned int nLen, unsigned int &nStartBit){    int nUeVal = Ue(pBuff, nLen, nStartBit);    double k = nUeVal;    //ceil函数:ceil函数的作用是求不小于给定实数的最小整数。ceil(2)=ceil(1.2)=cei(1.5)=2.00    int nValue=http://www.mamicode.com/ceil(k/2);    if (nUeVal % 2 == 0)        nValue = -nValue;    return nValue;}// u Just returns the BitCount bits of buf and change it to decimal.// e.g. BitCount = 4, buf = 01011100, then return 5(0101)unsigned int u(unsigned int nBitCount, unsigned char* buf, unsigned int &nStartBit){    unsigned int dwRet = 0;    for (unsigned int i = 0; i < nBitCount; i++)    {        dwRet <<= 1;        if (buf[nStartBit / 8] & (0x80 >> (nStartBit % 8)))        {            dwRet += 1;        }        nStartBit++;    }    return dwRet;}bool GetResulotion(unsigned char *pData, int nDataLen, int &nWidth, int &nHeight, int &nDeinterlace){    bool     bSpsComplete = false;        // Find SPS    unsigned char ucLastNalType = 0;                if (pData[0] == 0x00 && pData[1] == 0x00 && pData[2] == 0x00 && pData[3] == 0x01)    {        ucLastNalType = pData[4]; //Modify by HJ  20140717        unsigned char ucSPS = pData[4] & 0x7;        if (ucSPS ==  0x7)//SPS后5bit 和为7        {            bSpsComplete = true;        }    }    //先找到SPS类型的帧序列    if (bSpsComplete == false) return false;    //LOG4C_DEBUG(g_Logger, "GetResulotion:: Find SPS frame, nDataLen(%d)", nDataLen);    //Analyze SPS to find width and height    unsigned int   nStartBit = 0;     unsigned char *pBuf = pData + 4;    int nDataLeft = nDataLen - 4;    char temp[200];    int forbidden_zero_bit = u(1, pBuf, nStartBit);    int nal_ref_idc = u(2, pBuf, nStartBit);    int nal_unit_type = u(5, pBuf, nStartBit);    sprintf_s(temp,"GetResulotion  forbidden_zero_bit=%d, nal_ref_idc=%d, nal_unit_type=%d ",forbidden_zero_bit, nal_ref_idc, nal_unit_type);    OutputDebugStringA(temp);    if (nal_unit_type == 7)    {        int profile_idc = u(8, pBuf, nStartBit);        int constraint_set0_flag = u(1, pBuf, nStartBit);//(buf[1] & 0x80)>>7;        int constraint_set1_flag = u(1, pBuf, nStartBit);//(buf[1] & 0x40)>>6;        int constraint_set2_flag = u(1, pBuf, nStartBit);//(buf[1] & 0x20)>>5;        int constraint_set3_flag = u(1, pBuf, nStartBit);//(buf[1] & 0x10)>>4;        int reserved_zero_4bits  = u(4, pBuf, nStartBit);        int level_idc            = u(8, pBuf, nStartBit);        int seq_parameter_set_id = Ue(pBuf, nDataLeft, nStartBit);        //if (profile_idc == 100 || profile_idc == 110 ||        //    profile_idc == 122 || profile_idc == 144)        if (profile_idc == 100 ||  // High profile            profile_idc == 110 ||  // High10 profile            profile_idc == 122 ||  // High422 profile            profile_idc == 244 ||  // High444 Predictive profile            profile_idc ==  44 ||  // Cavlc444 profile            profile_idc ==  83 ||  // Scalable Constrained High profile (SVC)            profile_idc ==  86 ||  // Scalable High Intra profile (SVC)            profile_idc == 118 ||  // Stereo High profile (MVC)            profile_idc == 128 ||  // Multiview High profile (MVC)            profile_idc == 138 ||  // Multiview Depth High profile (MVCD)            profile_idc == 144)    // old High444 profile        {            int chroma_format_idc = Ue(pBuf, nDataLeft, nStartBit);            if(chroma_format_idc == 3)               int residual_colour_transform_flag = u(1, pBuf, nStartBit);            int bit_depth_luma_minus8 = Ue(pBuf, nDataLeft, nStartBit);            int bit_depth_chroma_minus8 = Ue(pBuf, nDataLeft, nStartBit);            int qpprime_y_zero_transform_bypass_flag = u(1, pBuf, nStartBit);            int seq_scaling_matrix_present_flag = u(1, pBuf, nStartBit);            int seq_scaling_list_present_flag[8];            if (seq_scaling_matrix_present_flag)            {                for (int i = 0; i < 8; i++)                 {                    seq_scaling_list_present_flag[i] = u(1, pBuf, nStartBit);                }            }        }        int log2_max_frame_num_minus4 = Ue(pBuf, nDataLeft, nStartBit);        int pic_order_cnt_type = Ue(pBuf, nDataLeft, nStartBit);                //LOG4C_DEBUG(g_Logger, "GetResulotion:: Find SPS frame, nDataLen(%d), nStarBit(%d), pic_order_cnt_type(%d)",         //    nDataLen, nStartBit, pic_order_cnt_type);        if (pic_order_cnt_type == 0)        {            int log2_max_pic_order_cnt_lsb_minus4 = Ue(pBuf, nDataLeft, nStartBit);        }        else if (pic_order_cnt_type == 1)        {            int delta_pic_order_always_zero_flag = u(1, pBuf, nStartBit);            int offset_for_non_ref_pic = Se(pBuf, nDataLeft, nStartBit);            int offset_for_top_to_bottom_field = Se(pBuf, nDataLeft, nStartBit);            int num_ref_frames_in_pic_order_cnt_cycle = Ue(pBuf, nDataLeft, nStartBit);            int *offset_for_ref_frame = new int[num_ref_frames_in_pic_order_cnt_cycle];            for( int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++ )                offset_for_ref_frame[i] = Se(pBuf, nDataLeft, nStartBit);                        delete []offset_for_ref_frame;        }        int num_ref_frames = Ue(pBuf, nDataLeft, nStartBit);        int gaps_in_frame_num_value_allowed_flag = u(1, pBuf, nStartBit);        int pic_width_in_mbs_minus1 = Ue(pBuf, nDataLeft, nStartBit);        int pic_height_in_map_units_minus1 = Ue(pBuf, nDataLeft, nStartBit);        int frame_mbs_only_flag = u(1, pBuf, nStartBit);        //LOG4C_DEBUG(g_Logger, "GetResulotion:: Find SPS frame, nDataLen(%d), nStarBit(%d), pic_order_cnt_type(%d), pic_width_in_mbs_minus1(%d), pic_height_in_map_units_minus1(%d)",         //    nDataLen, nStartBit, pic_order_cnt_type, pic_width_in_mbs_minus1, pic_height_in_map_units_minus1);        nWidth = (pic_width_in_mbs_minus1 + 1) * 16;        nHeight = (pic_height_in_map_units_minus1 + 1) * 16;        nDeinterlace = 0;        if (0 == frame_mbs_only_flag)        {            nHeight *= 2;             nDeinterlace = 1;        }        //if(nHeight == 1088)    nHeight = 1080;        //LOG4C_DEBUG(g_Logger, "GetResulotion:: Find SPS frame, nDataLen(%d), width(%d), height(%d) frame_mbs_only_flag(%d)", nDataLen, nWidth, nHeight,frame_mbs_only_flag);        return true;    }    else    {        LOG4C_DEBUG(g_Logger, "GetResulotion:: Find SPS frame, Invalid nal unit type, nDataLen(%d), nal_unit_type(%d)", nDataLen, nal_unit_type);        return false;    }}
View Code