从H264码流中获取视频宽高 (SPS帧)
获取.h264视频宽高的方法
花了2个通宵终于搞定。(后面附上完整代码)
http://write.blog.csdn.net/postedit/7852406
图像的高和宽在H264的SPS帧中。
在H264码流中,都是以"0x00 0x00 0x01"或者"0x00 0x00 0x00 0x01"为开始码的,找到开始码之后,使用开始码之后的第一个字节的低5位判断是否为7(sps),等于7表示该帧就是SPS帧,从该帧就可以解析出高和宽,SPS是个结构体,里面有两个成员:pic_width_in_mbs_minus1,pic_height_in_map_units_minus_1,分别表示图像的宽和高,以宏块(16x16)为单位的值减1,因此,实际的宽为 (pic_width_in_mbs_minus1+1)*16,高为 (pic_height_in_map_units_minus_1+1)*16
http://write.blog.csdn.net/postedit/7852406
UINT Ue(BYTE *pBuff, UINT nLen, UINT &nStartBit)
{
//计算0bit的个数
UINT nZeroNum = ;
while (nStartBit < nLen * )
{
if (pBuff[nStartBit / ] & (0x80 >> (nStartBit % ))) //&:按位与,%取余
{
break;
}
nZeroNum++;
nStartBit++;
}
nStartBit ++; //计算结果
DWORD dwRet = ;
for (UINT i=; i<nZeroNum; i++)
{
dwRet <<= ;
if (pBuff[nStartBit / ] & (0x80 >> (nStartBit % )))
{
dwRet += ;
}
nStartBit++;
}
return ( << nZeroNum) - + dwRet;
} int Se(BYTE *pBuff, UINT nLen, UINT &nStartBit)
{ int UeVal=Ue(pBuff,nLen,nStartBit);
double k=UeVal;
int nValue=ceil(k/);//ceil函数:ceil函数的作用是求不小于给定实数的最小整数。ceil(2)=ceil(1.2)=cei(1.5)=2.00
if (UeVal % ==)
nValue=-nValue;
return nValue; } DWORD u(UINT BitCount,BYTE * buf,UINT &nStartBit)
{
DWORD dwRet = ;
for (UINT i=; i<BitCount; i++)
{
dwRet <<= ;
if (buf[nStartBit / ] & (0x80 >> (nStartBit % )))
{
dwRet += ;
}
nStartBit++;
}
return dwRet;
} bool h264_decode_seq_parameter_set(BYTE * buf,UINT nLen,int &Width,int &Height)
{
UINT StartBit=;
int forbidden_zero_bit=u(,buf,StartBit);
int nal_ref_idc=u(,buf,StartBit);
int nal_unit_type=u(,buf,StartBit);
if(nal_unit_type==)
{
int profile_idc=u(,buf,StartBit);
int constraint_set0_flag=u(,buf,StartBit);//(buf[1] & 0x80)>>7;
int constraint_set1_flag=u(,buf,StartBit);//(buf[1] & 0x40)>>6;
int constraint_set2_flag=u(,buf,StartBit);//(buf[1] & 0x20)>>5;
int constraint_set3_flag=u(,buf,StartBit);//(buf[1] & 0x10)>>4;
int reserved_zero_4bits=u(,buf,StartBit);
int level_idc=u(,buf,StartBit); int seq_parameter_set_id=Ue(buf,nLen,StartBit); if( profile_idc == || profile_idc == ||
profile_idc == || profile_idc == )
{
int chroma_format_idc=Ue(buf,nLen,StartBit);
if( chroma_format_idc == )
int residual_colour_transform_flag=u(,buf,StartBit);
int bit_depth_luma_minus8=Ue(buf,nLen,StartBit);
int bit_depth_chroma_minus8=Ue(buf,nLen,StartBit);
int qpprime_y_zero_transform_bypass_flag=u(,buf,StartBit);
int seq_scaling_matrix_present_flag=u(,buf,StartBit); int seq_scaling_list_present_flag[];
if( seq_scaling_matrix_present_flag )
{
for( int i = ; i < ; i++ ) {
seq_scaling_list_present_flag[i]=u(,buf,StartBit);
}
}
}
int log2_max_frame_num_minus4=Ue(buf,nLen,StartBit);
int pic_order_cnt_type=Ue(buf,nLen,StartBit);
if( pic_order_cnt_type == )
int log2_max_pic_order_cnt_lsb_minus4=Ue(buf,nLen,StartBit);
else if( pic_order_cnt_type == )
{
int delta_pic_order_always_zero_flag=u(,buf,StartBit);
int offset_for_non_ref_pic=Se(buf,nLen,StartBit);
int offset_for_top_to_bottom_field=Se(buf,nLen,StartBit);
int num_ref_frames_in_pic_order_cnt_cycle=Ue(buf,nLen,StartBit); int *offset_for_ref_frame=new int[num_ref_frames_in_pic_order_cnt_cycle];
for( int i = ; i < num_ref_frames_in_pic_order_cnt_cycle; i++ )
offset_for_ref_frame[i]=Se(buf,nLen,StartBit);
delete [] offset_for_ref_frame;
}
int num_ref_frames=Ue(buf,nLen,StartBit);
int gaps_in_frame_num_value_allowed_flag=u(,buf,StartBit);
int pic_width_in_mbs_minus1=Ue(buf,nLen,StartBit);
int pic_height_in_map_units_minus1=Ue(buf,nLen,StartBit); Width=(pic_width_in_mbs_minus1+)*;
Height=(pic_height_in_map_units_minus1+)*; return true;
}
else
return false;
} void CCommDlg::OnOK()
{
CString str;
//数据必须把H264的头0x000001去掉
BYTE bytes[]={0x67,0x64,0x08,0x1F,0xAC,0x34,0xC1,0x08,0x28,0x0F,0x64};
UINT startbit=;
int Width,Height;
if (h264_decode_seq_parameter_set(bytes,,Width,Height))
{
str.Format("%d-%d",Width,Height); AfxMessageBox(str);
}
}
从H264码流中获取视频宽高 (SPS帧)的更多相关文章
- 从H264码流中获取视频宽高 (SPS帧) 升级篇
之前写过 <从H264码流中获取视频宽高 (SPS帧)> . 但发现很多局限性,而且有时解出来是错误的. 所以重新去研究了. 用了 官方提供的代码库来解析. 花了点时间,从代码库里单独把解 ...
- H264码流中SPS PPS详解<转>
转载地址:https://zhuanlan.zhihu.com/p/27896239 1 SPS和PPS从何处而来? 2 SPS和PPS中的每个参数起什么作用? 3 如何解析SDP中包含的H.264的 ...
- Activity启动过程中获取组件宽高的五种方式
第一种:(重写Activity的onWindowFocusChanged方法) /** * 重写Acitivty的onWindowFocusChanged方法 */ @Override public ...
- H.264从SPS中提取视频宽高
H.264有两种封装模式: (1)annexb模式:传统模式,使用start code来分隔NAL, SPS和PPS是在ES流的头部: (2)mp4模式:没有start code,使用NALU长度(固 ...
- Vue中获取元素宽高
<div ref="init"></div> 写在 页面 方法 部分 这里的 offsetHeight 是返回元素的宽度(包括元素宽度.内边距和边框,不包括 ...
- android onCreate中获取view宽高为0的解决方法
view.post(runnable) 通过post可以将一个runnable投递到消息队列的尾部,然后等待UI线程Looper调用此runnable的时候,view也已经初始化好了. view.po ...
- ffmpeg 获取视频宽高
int main(int argc, char *argv[]) { const char* file_name = "video.mp4"; int ret; unsigned ...
- Activity正确获取View宽高
在View的measure完成后,一般可以通过getMeasureWidth/getMeasureWidth方法可以正确的获取View的宽高,而在特殊情况下,可能需要多次measure才能确定最终的测 ...
- H264码流打包分析
转自:http://www.360doc.com/content/13/0124/08/9008018_262076786.shtml SODB 数据比特串-->最原始的编码数据 RBSP ...
随机推荐
- TP-link TL-WN725 USB无线网卡在DX2 CPU下的Xlinux 驱动移植
网上查到,TP-link TL-WN725 USB无线网卡用的芯片是8188EU 下载驱动:http://download.csdn.net/detail/zzz_mraz/5262010 tar z ...
- apache httpd.conf 参数详解
由于网站需要,需要配置多个虚拟主机,但是apache主机的参数太多,记不住,下面做一下总结 归纳: ServerRoot:apache安装位置 Listen:服务器监听的端口号 LoadModule: ...
- verilog断言(SVA:systemverlog assertion)语法 ---- 转载
转载自:http://blog.sina.com.cn/s/blog_4c270c730101f6mw.html 作者:白栎旸 断言assertion被放在verilog设计中,方便在仿真时查 ...
- 剑指Offer:解决难题时的三大方法
1.画图 让抽象的东西变得直观生动起来.比如设计二叉树,链表,栈,队列这些数据结构时. 2.举例子 同样可以化抽象为直观.能够更清晰的展现思路.从例子归纳出一般做法. 3.分解 有时问题本身是比较复杂 ...
- 不安装Oracle客户端情况下使用PL/SQL 远程连接数据库
附送PL/SQL Developer11中文版下载地址 1.先到Oracle网站下载Instant Client : http://www.oracle.com/technetwork/databas ...
- Ubuntu Kylin 14.04-修改IP固定地址
前言:今天我们办公室的网络不稳定,隔一会时间就断掉,后来请负责网络的同事来处理了一下,说是路由器的有些配置起冲突了,所以他将IP地址做了一些修改,比如:原IP是192.168.0.110 ...
- (Hibernate进阶)Hibernate映射——多对多关联映射(八)
多对多映射是现实生活中最常见的映射,也是最容易理解的映射.废话少说,直接开始. 映射原理 不论是单向关联还是双向关联都是通过第三张表,将两个表中的主键放到第三张做一个关联.用第三张表来解决可能会造成数 ...
- MFC 自绘按钮 消息响应
单检测到按下消息时,发送一个消息 m_pParent->PostMessage(WM_COMMAND, IDC_BUTTON1); 然后再在消息映射里建立映射. ON_COMMAND(IDC_B ...
- jQuery Validate + Ckeditor 驗證 textarea 解決方式
jQuery Validate + Ckeditor 驗證 textarea 解決方式 html <textarea name="content" id="cont ...
- Linux:history命令记录操作时间、操作用户、操作IP
[步骤] 1./etc/profile文件中加入以下内容 2.执行:source /etc/profile [效果]