获取.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
1 UINT Ue(BYTE *pBuff, UINT nLen, UINT &nStartBit) 2 { 3 //计算0bit的个数 4 UINT nZeroNum = 0; 5 while (nStartBit < nLen * 8) 6 { 7 if (pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8))) //&:按位与,%取余 8 { 9 break; 10 } 11 nZeroNum++; 12 nStartBit++; 13 } 14 nStartBit ++; 15 16 17 //计算结果 18 DWORD dwRet = 0; 19 for (UINT i=0; i<nZeroNum; i++) 20 { 21 dwRet <<= 1; 22 if (pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8))) 23 { 24 dwRet += 1; 25 } 26 nStartBit++; 27 } 28 return (1 << nZeroNum) - 1 + dwRet; 29 } 30 31 32 int Se(BYTE *pBuff, UINT nLen, UINT &nStartBit) 33 { 34 35 36 int UeVal=Ue(pBuff,nLen,nStartBit); 37 double k=UeVal; 38 int nValue=ceil(k/2);//ceil函数:ceil函数的作用是求不小于给定实数的最小整数。ceil(2)=ceil(1.2)=cei(1.5)=2.00 39 if (UeVal % 2==0) 40 nValue=-nValue; 41 return nValue; 42 43 44 } 45 46 47 DWORD u(UINT BitCount,BYTE * buf,UINT &nStartBit) 48 { 49 DWORD dwRet = 0; 50 for (UINT i=0; i<BitCount; i++) 51 { 52 dwRet <<= 1; 53 if (buf[nStartBit / 8] & (0x80 >> (nStartBit % 8))) 54 { 55 dwRet += 1; 56 } 57 nStartBit++; 58 } 59 return dwRet; 60 } 61 62 63 bool h264_decode_seq_parameter_set(BYTE * buf,UINT nLen,int &Width,int &Height) 64 { 65 UINT StartBit=0; 66 int forbidden_zero_bit=u(1,buf,StartBit); 67 int nal_ref_idc=u(2,buf,StartBit); 68 int nal_unit_type=u(5,buf,StartBit); 69 if(nal_unit_type==7) 70 { 71 int profile_idc=u(8,buf,StartBit); 72 int constraint_set0_flag=u(1,buf,StartBit);//(buf[1] & 0x80)>>7; 73 int constraint_set1_flag=u(1,buf,StartBit);//(buf[1] & 0x40)>>6; 74 int constraint_set2_flag=u(1,buf,StartBit);//(buf[1] & 0x20)>>5; 75 int constraint_set3_flag=u(1,buf,StartBit);//(buf[1] & 0x10)>>4; 76 int reserved_zero_4bits=u(4,buf,StartBit); 77 int level_idc=u(8,buf,StartBit); 78 79 int seq_parameter_set_id=Ue(buf,nLen,StartBit); 80 81 if( profile_idc == 100 || profile_idc == 110 || 82 profile_idc == 122 || profile_idc == 144 ) 83 { 84 int chroma_format_idc=Ue(buf,nLen,StartBit); 85 if( chroma_format_idc == 3 ) 86 int residual_colour_transform_flag=u(1,buf,StartBit); 87 int bit_depth_luma_minus8=Ue(buf,nLen,StartBit); 88 int bit_depth_chroma_minus8=Ue(buf,nLen,StartBit); 89 int qpprime_y_zero_transform_bypass_flag=u(1,buf,StartBit); 90 int seq_scaling_matrix_present_flag=u(1,buf,StartBit); 91 92 int seq_scaling_list_present_flag[8]; 93 if( seq_scaling_matrix_present_flag ) 94 { 95 for( int i = 0; i < 8; i++ ) { 96 seq_scaling_list_present_flag[i]=u(1,buf,StartBit); 97 } 98 } 99 } 100 int log2_max_frame_num_minus4=Ue(buf,nLen,StartBit); 101 int pic_order_cnt_type=Ue(buf,nLen,StartBit); 102 if( pic_order_cnt_type == 0 ) 103 int log2_max_pic_order_cnt_lsb_minus4=Ue(buf,nLen,StartBit); 104 else if( pic_order_cnt_type == 1 ) 105 { 106 int delta_pic_order_always_zero_flag=u(1,buf,StartBit); 107 int offset_for_non_ref_pic=Se(buf,nLen,StartBit); 108 int offset_for_top_to_bottom_field=Se(buf,nLen,StartBit); 109 int num_ref_frames_in_pic_order_cnt_cycle=Ue(buf,nLen,StartBit); 110 111 int *offset_for_ref_frame=new int[num_ref_frames_in_pic_order_cnt_cycle]; 112 for( int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++ ) 113 offset_for_ref_frame[i]=Se(buf,nLen,StartBit); 114 delete [] offset_for_ref_frame; 115 } 116 int num_ref_frames=Ue(buf,nLen,StartBit); 117 int gaps_in_frame_num_value_allowed_flag=u(1,buf,StartBit); 118 int pic_width_in_mbs_minus1=Ue(buf,nLen,StartBit); 119 int pic_height_in_map_units_minus1=Ue(buf,nLen,StartBit); 120 121 Width=(pic_width_in_mbs_minus1+1)*16; 122 Height=(pic_height_in_map_units_minus1+1)*16; 123 124 return true; 125 } 126 else 127 return false; 128 } 129 130 131 132 133 void CCommDlg::OnOK() 134 { 135 CString str; 136 //数据必须把H264的头0x000001去掉 137 BYTE bytes[11]={0x67,0x64,0x08,0x1F,0xAC,0x34,0xC1,0x08,0x28,0x0F,0x64}; 138 UINT startbit=0; 139 int Width,Height; 140 if (h264_decode_seq_parameter_set(bytes,11,Width,Height)) 141 { 142 str.Format("%d-%d",Width,Height); 143 144 145 AfxMessageBox(str); 146 } 147 }