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
", vopNum);
149             
150             break;
151             
152         case E_MPEG4_CODING_P:
153             printf("Video Object Plane - P Frame #%d
", vopNum);
154 
155             break;
156 
157         case E_MPEG4_CODING_B:
158             printf("Video Object Plane - B Frame #%d
", vopNum);
159 
160             break;
161             
162         default:
163             printf("Video Object Plane - %d Frame #%d
", 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
");
191 
192         return -1;
193     }
194 
195     fp = fopen(argv[1], "rb");
196     if (!fp)
197     {
198         printf("open file[%s] error!
", 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!
");
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!
");
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...
");
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??
");
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 }
View Code

  最后如果您觉得本篇对您有帮助,可以打赏下,谢谢!!!

原文地址:https://www.cnblogs.com/leaffei/p/10552105.html