首页 > 代码库 > 通过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; }}