mpeg4文件分析(纯c解析代码)
参考链接: 1. MPEG4码流的帧率计算 https://blog.csdn.net/littlebee90/article/details/68924690
2. MPEG4码流分析(1) https://blog.csdn.net/season_hangzhou/article/details/18799933
由于未阅读MPEG4的标准文档,也为找到合适的mpeg4的裸文件(就是按标准一层层编码的文件, 即每种StartCode都有的)。因此本代码实际上只找出每个VOP并解析出帧的类型。
mpeg4的码流结构,如下图:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #define TAB44 " " 6 #define PRINTF_DEBUG 7 8 /****************************************************************** 9 ** vop_time_increment, 这个值暂时不会解析, 文档上写的1-16没看懂 10 VOL头中的Vop_time_increment_resolution和VOP头中的Vop_time_increment, 一起确定了码流所采用的帧率. 11 VOL头中的Vop_time_increment_resolution, 指示了vop_time_increment的时间分辨率. 它的值实际上就表示了1秒被分成多少间隔。 12 VOP头中的Vop_time_increment, 单位为vol中定义的1/vop_time_increment_resolution秒, 它给出当前vop的以modulo_time_base为基准的精确时间. 13 它的取值范围为[0, vop_time_increment_resolution]. 14 简单计算, 码流的实时帧率应该等于Vop_time_increment_resolution/每个Vop_time_increment的差值. 15 *******************************************************************/ 16 typedef struct t_mpeg4_vop 17 { 18 unsigned char vop_coding_type:2; 19 unsigned short vop_time_increment; 20 } T_MPEG4_VOP; 21 22 typedef enum e_mpeg4_sc_type 23 { 24 E_SC_MPEG4_MIN_VIDEO_OBJECT = 0x00000100, /* VO, 00-1F */ 25 E_SC_MPEG4_MAX_VIDEO_OBJECT = 0x0000011F, 26 E_SC_MPEG4_MIN_VIDEO_OBJECT_LAYER = 0x00000120, /* VOL, 20-2F*/ 27 E_SC_MPEG4_MAX_VIDEO_OBJECT_LAYER = 0x0000012F, 28 E_SC_MPEG4_MIN_RESERVED = 0x00000130, /* VOL, 30-AF*/ 29 E_SC_MPEG4_MAX_RESERVED = 0x000001AF, 30 E_SC_MPEG4_VISUAL_OBJECT_SEQUENCE_START = 0x000001B0, /* VOS */ 31 E_SC_MPEG4_VISUAL_OBJECT_SEQUENCE_END = 0x000001B1, 32 E_SC_MPEG4_USER_DATA = 0x000001B2, 33 E_SC_MPEG4_GROUP_OF_VOP = 0x000001B3, /* GOP */ 34 E_SC_MPEG4_VIDEO_SESSION_ERROR = 0x000001B4, 35 E_SC_MPEG4_VISIAL_OBJECT = 0x000001B5, /* VO */ 36 E_SC_MPEG4_VOP = 0x000001B6, 37 } E_MPEG4_SC_TYPE; 38 39 typedef enum e_mpeg4_coding_type 40 { 41 E_MPEG4_CODING_I = 0, 42 E_MPEG4_CODING_P = 1, 43 E_MPEG4_CODING_B = 2 44 } E_MPEG4_CODING_TYPE; 45 46 /* now n max is 4 */ 47 static int NBytes2Int(int n, unsigned char* const byte) 48 { 49 int i = 0; 50 int retInt = 0; 51 52 for (i=0; i<n; i++) 53 { 54 retInt += (byte[i]<<((n-i-1)*8)); 55 } 56 57 return retInt; 58 } 59 60 static int FindStartCode(const E_MPEG4_SC_TYPE mpeg4ScType, unsigned char *scData) 61 { 62 int isFind = 0; 63 int retInt = 0; 64 65 if (E_SC_MPEG4_MIN_VIDEO_OBJECT == mpeg4ScType) 66 { 67 retInt = NBytes2Int(4, scData); 68 if ((retInt>= E_SC_MPEG4_MIN_VIDEO_OBJECT) && (retInt<= E_SC_MPEG4_MAX_VIDEO_OBJECT)) 69 { 70 isFind = 1; 71 } 72 } 73 else if (E_SC_MPEG4_MIN_VIDEO_OBJECT_LAYER == mpeg4ScType) 74 { 75 retInt = NBytes2Int(4, scData); 76 if ((retInt>= E_SC_MPEG4_MIN_VIDEO_OBJECT_LAYER) && (retInt<= E_SC_MPEG4_MAX_VIDEO_OBJECT_LAYER)) 77 { 78 isFind = 1; 79 } 80 } 81 else if (E_SC_MPEG4_MIN_RESERVED == mpeg4ScType) 82 { 83 retInt = NBytes2Int(4, scData); 84 if ((retInt>= E_SC_MPEG4_MIN_RESERVED) && (retInt<= E_SC_MPEG4_MAX_RESERVED)) 85 { 86 isFind = 1; 87 } 88 } 89 else 90 { 91 if (mpeg4ScType == NBytes2Int(4, scData)) 92 { 93 isFind = 1; 94 } 95 } 96 97 return isFind; 98 } 99 100 static int GetMpeg4DataLen(const E_MPEG4_SC_TYPE mpeg4ScType, const int startPos, const int mpeg4BitsSize, unsigned char* const mpeg4Bits) 101 { 102 int parsePos = 0; 103 104 parsePos = startPos; 105 106 while (parsePos < mpeg4BitsSize) 107 { 108 if ((E_SC_MPEG4_VISUAL_OBJECT_SEQUENCE_START == mpeg4ScType) 109 || (E_SC_MPEG4_VOP == mpeg4ScType)) 110 { 111 if (FindStartCode(mpeg4ScType, &mpeg4Bits[parsePos])) 112 { 113 return parsePos - startPos; 114 } 115 else 116 { 117 parsePos++; 118 } 119 } 120 } 121 122 return parsePos - startPos; // if file is end 123 } 124 125 static void ParseVosData(const unsigned int vosLen, unsigned char* const vosData) 126 { 127 return; 128 } 129 130 static void ParseVopData(const unsigned int vopLen, unsigned char* const vopData) 131 { 132 static int vopNum = 0; 133 134 unsigned char *data = NULL; 135 136 T_MPEG4_VOP mpeg4Vop = {0}; 137 138 data = vopData; 139 140 memset(&mpeg4Vop, 0x0, sizeof(T_MPEG4_VOP)); 141 142 mpeg4Vop.vop_coding_type = ((data[0]&0xC0)>>6); 143 144 #ifdef PRINTF_DEBUG 145 switch (mpeg4Vop.vop_coding_type) 146 { 147 case E_MPEG4_CODING_I: 148 printf("Video Object Plane - I Frame #%d\n", vopNum); 149 150 break; 151 152 case E_MPEG4_CODING_P: 153 printf("Video Object Plane - P Frame #%d\n", vopNum); 154 155 break; 156 157 case E_MPEG4_CODING_B: 158 printf("Video Object Plane - B Frame #%d\n", vopNum); 159 160 break; 161 162 default: 163 printf("Video Object Plane - %d Frame #%d\n", mpeg4Vop.vop_coding_type, vopNum); 164 165 break; 166 } 167 168 vopNum++; 169 #endif 170 171 return; 172 } 173 174 int main(int argc, char *argv[]) 175 { 176 int fileLen = 0; 177 int vosLen = 0; 178 int vopLen = 0; 179 int mpeg4BitsPos = 0; 180 int mpeg4VosFind = 0; 181 182 unsigned char *mpeg4Bits = NULL; 183 unsigned char *vosData = NULL; 184 unsigned char *vopData = NULL; 185 186 FILE *fp = NULL; 187 188 if (2 != argc) 189 { 190 printf("Usage: mpeg4parse **.mpg\n"); 191 192 return -1; 193 } 194 195 fp = fopen(argv[1], "rb"); 196 if (!fp) 197 { 198 printf("open file[%s] error!\n", argv[1]); 199 200 return -1; 201 } 202 203 fseek(fp, 0, SEEK_END); 204 205 fileLen = ftell(fp); 206 207 fseek(fp, 0, SEEK_SET); 208 209 mpeg4Bits = (unsigned char*)malloc(fileLen); 210 if (!mpeg4Bits) 211 { 212 printf("maybe file is too long, or memery is not enough!\n"); 213 214 fclose(fp); 215 216 return -1; 217 } 218 219 memset(mpeg4Bits, 0x0, fileLen); 220 221 if (fread(mpeg4Bits, 1, fileLen, fp) < 0) 222 { 223 printf("read file data to mpeg4Bits error!\n"); 224 225 fclose(fp); 226 free(mpeg4Bits); 227 228 mpeg4Bits = NULL; 229 230 return -1; 231 } 232 233 fclose(fp); 234 235 /* find vos */ 236 while (mpeg4BitsPos < (fileLen-4)) 237 { 238 if (FindStartCode(E_SC_MPEG4_VISUAL_OBJECT_SEQUENCE_START, &mpeg4Bits[mpeg4BitsPos])) 239 { 240 mpeg4VosFind = 1; 241 242 vosLen = GetMpeg4DataLen(E_SC_MPEG4_VISUAL_OBJECT_SEQUENCE_START, mpeg4BitsPos+4, fileLen, mpeg4Bits); 243 244 vosData = (unsigned char*)malloc(vosLen); 245 if (vosData) 246 { 247 memset(vosData, 0x0, vosLen); 248 249 memcpy(vosData, mpeg4Bits+mpeg4BitsPos+4, vosLen); 250 251 ParseVosData(vosLen, vosData); 252 253 free(vosData); 254 vosData = NULL; 255 } 256 257 mpeg4BitsPos += (vosLen+4); 258 } 259 else 260 { 261 mpeg4BitsPos++; 262 } 263 } 264 265 if (!mpeg4VosFind) 266 { 267 #ifdef PRINTF_DEBUG 268 printf("Can not find vos, find vop...\n"); 269 #endif 270 /* can not find vos, find vop */ 271 mpeg4BitsPos = 0; 272 273 while (mpeg4BitsPos < (fileLen-4)) 274 { 275 if (FindStartCode(E_SC_MPEG4_VOP, &mpeg4Bits[mpeg4BitsPos])) 276 { 277 //printf("find vop??\n"); 278 vopLen = GetMpeg4DataLen(E_SC_MPEG4_VOP, mpeg4BitsPos+4, fileLen, mpeg4Bits); 279 280 vopData = (unsigned char*)malloc(vopLen); 281 if (vopData) 282 { 283 memset(vopData, 0x0, vopLen); 284 285 memcpy(vopData, mpeg4Bits+mpeg4BitsPos+4, vopLen); 286 287 ParseVopData(vopLen, vopData); 288 289 free(vopData); 290 vopData = NULL; 291 } 292 293 mpeg4BitsPos += (vopLen+4); 294 } 295 else 296 { 297 mpeg4BitsPos++; 298 } 299 } 300 } 301 }
最后如果您觉得本篇对您有帮助,可以打赏下,谢谢!!!