zoukankan      html  css  js  c++  java
  • 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

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

  • 相关阅读:
    bstToDoublyList
    Springboot系列1_什么是Springboot
    servlet总结
    JavaFx开发桌面软件
    在Emacs中使用plantuml画UML图
    IIS7.0上传文件限制的解决方法
    开源免费的天气预报接口API以及全国所有地区代码(国家气象局提供)
    如何得到天气情况?在那个接口获取?
    Windows Update 时出现8024402C的错误
    OC中copy的使用
  • 原文地址:https://www.cnblogs.com/leaffei/p/10552105.html
Copyright © 2011-2022 走看看