码迷,mamicode.com
首页 > 其他好文 > 详细

通过H264获取分辨率,FFmpeg

时间:2014-07-18 09:39:00      阅读:2012      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   使用   os   

每次从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多的,分辨率的都解析成功了。:-)

 

 

 

bubuko.com,布布扣
// 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=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

通过H264获取分辨率,FFmpeg,布布扣,bubuko.com

通过H264获取分辨率,FFmpeg

标签:style   blog   http   color   使用   os   

原文地址:http://www.cnblogs.com/scotth/p/3851941.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!