参考链接: 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的码流结构,如下图:

 #include <stdio.h>
#include <stdlib.h>
#include <string.h> #define TAB44 " "
#define PRINTF_DEBUG /******************************************************************
** vop_time_increment, 这个值暂时不会解析, 文档上写的1-16没看懂
VOL头中的Vop_time_increment_resolution和VOP头中的Vop_time_increment, 一起确定了码流所采用的帧率.
VOL头中的Vop_time_increment_resolution, 指示了vop_time_increment的时间分辨率. 它的值实际上就表示了1秒被分成多少间隔。
VOP头中的Vop_time_increment, 单位为vol中定义的1/vop_time_increment_resolution秒, 它给出当前vop的以modulo_time_base为基准的精确时间.
它的取值范围为[0, vop_time_increment_resolution].
简单计算, 码流的实时帧率应该等于Vop_time_increment_resolution/每个Vop_time_increment的差值.
*******************************************************************/
typedef struct t_mpeg4_vop
{
unsigned char vop_coding_type:;
unsigned short vop_time_increment;
} T_MPEG4_VOP; typedef enum e_mpeg4_sc_type
{
E_SC_MPEG4_MIN_VIDEO_OBJECT = 0x00000100, /* VO, 00-1F */
E_SC_MPEG4_MAX_VIDEO_OBJECT = 0x0000011F,
E_SC_MPEG4_MIN_VIDEO_OBJECT_LAYER = 0x00000120, /* VOL, 20-2F*/
E_SC_MPEG4_MAX_VIDEO_OBJECT_LAYER = 0x0000012F,
E_SC_MPEG4_MIN_RESERVED = 0x00000130, /* VOL, 30-AF*/
E_SC_MPEG4_MAX_RESERVED = 0x000001AF,
E_SC_MPEG4_VISUAL_OBJECT_SEQUENCE_START = 0x000001B0, /* VOS */
E_SC_MPEG4_VISUAL_OBJECT_SEQUENCE_END = 0x000001B1,
E_SC_MPEG4_USER_DATA = 0x000001B2,
E_SC_MPEG4_GROUP_OF_VOP = 0x000001B3, /* GOP */
E_SC_MPEG4_VIDEO_SESSION_ERROR = 0x000001B4,
E_SC_MPEG4_VISIAL_OBJECT = 0x000001B5, /* VO */
E_SC_MPEG4_VOP = 0x000001B6,
} E_MPEG4_SC_TYPE; typedef enum e_mpeg4_coding_type
{
E_MPEG4_CODING_I = ,
E_MPEG4_CODING_P = ,
E_MPEG4_CODING_B =
} E_MPEG4_CODING_TYPE; /* now n max is 4 */
static int NBytes2Int(int n, unsigned char* const byte)
{
int i = ;
int retInt = ; for (i=; i<n; i++)
{
retInt += (byte[i]<<((n-i-)*));
} return retInt;
} static int FindStartCode(const E_MPEG4_SC_TYPE mpeg4ScType, unsigned char *scData)
{
int isFind = ;
int retInt = ; if (E_SC_MPEG4_MIN_VIDEO_OBJECT == mpeg4ScType)
{
retInt = NBytes2Int(, scData);
if ((retInt>= E_SC_MPEG4_MIN_VIDEO_OBJECT) && (retInt<= E_SC_MPEG4_MAX_VIDEO_OBJECT))
{
isFind = ;
}
}
else if (E_SC_MPEG4_MIN_VIDEO_OBJECT_LAYER == mpeg4ScType)
{
retInt = NBytes2Int(, scData);
if ((retInt>= E_SC_MPEG4_MIN_VIDEO_OBJECT_LAYER) && (retInt<= E_SC_MPEG4_MAX_VIDEO_OBJECT_LAYER))
{
isFind = ;
}
}
else if (E_SC_MPEG4_MIN_RESERVED == mpeg4ScType)
{
retInt = NBytes2Int(, scData);
if ((retInt>= E_SC_MPEG4_MIN_RESERVED) && (retInt<= E_SC_MPEG4_MAX_RESERVED))
{
isFind = ;
}
}
else
{
if (mpeg4ScType == NBytes2Int(, scData))
{
isFind = ;
}
} return isFind;
} static int GetMpeg4DataLen(const E_MPEG4_SC_TYPE mpeg4ScType, const int startPos, const int mpeg4BitsSize, unsigned char* const mpeg4Bits)
{
int parsePos = ; parsePos = startPos; while (parsePos < mpeg4BitsSize)
{
if ((E_SC_MPEG4_VISUAL_OBJECT_SEQUENCE_START == mpeg4ScType)
|| (E_SC_MPEG4_VOP == mpeg4ScType))
{
if (FindStartCode(mpeg4ScType, &mpeg4Bits[parsePos]))
{
return parsePos - startPos;
}
else
{
parsePos++;
}
}
} return parsePos - startPos; // if file is end
} static void ParseVosData(const unsigned int vosLen, unsigned char* const vosData)
{
return;
} static void ParseVopData(const unsigned int vopLen, unsigned char* const vopData)
{
static int vopNum = ; unsigned char *data = NULL; T_MPEG4_VOP mpeg4Vop = {}; data = vopData; memset(&mpeg4Vop, 0x0, sizeof(T_MPEG4_VOP)); mpeg4Vop.vop_coding_type = ((data[]&0xC0)>>); #ifdef PRINTF_DEBUG
switch (mpeg4Vop.vop_coding_type)
{
case E_MPEG4_CODING_I:
printf("Video Object Plane - I Frame #%d\n", vopNum); break; case E_MPEG4_CODING_P:
printf("Video Object Plane - P Frame #%d\n", vopNum); break; case E_MPEG4_CODING_B:
printf("Video Object Plane - B Frame #%d\n", vopNum); break; default:
printf("Video Object Plane - %d Frame #%d\n", mpeg4Vop.vop_coding_type, vopNum); break;
} vopNum++;
#endif return;
} int main(int argc, char *argv[])
{
int fileLen = ;
int vosLen = ;
int vopLen = ;
int mpeg4BitsPos = ;
int mpeg4VosFind = ; unsigned char *mpeg4Bits = NULL;
unsigned char *vosData = NULL;
unsigned char *vopData = NULL; FILE *fp = NULL; if ( != argc)
{
printf("Usage: mpeg4parse **.mpg\n"); return -;
} fp = fopen(argv[], "rb");
if (!fp)
{
printf("open file[%s] error!\n", argv[]); return -;
} fseek(fp, , SEEK_END); fileLen = ftell(fp); fseek(fp, , SEEK_SET); mpeg4Bits = (unsigned char*)malloc(fileLen);
if (!mpeg4Bits)
{
printf("maybe file is too long, or memery is not enough!\n"); fclose(fp); return -;
} memset(mpeg4Bits, 0x0, fileLen); if (fread(mpeg4Bits, , fileLen, fp) < )
{
printf("read file data to mpeg4Bits error!\n"); fclose(fp);
free(mpeg4Bits); mpeg4Bits = NULL; return -;
} fclose(fp); /* find vos */
while (mpeg4BitsPos < (fileLen-))
{
if (FindStartCode(E_SC_MPEG4_VISUAL_OBJECT_SEQUENCE_START, &mpeg4Bits[mpeg4BitsPos]))
{
mpeg4VosFind = ; vosLen = GetMpeg4DataLen(E_SC_MPEG4_VISUAL_OBJECT_SEQUENCE_START, mpeg4BitsPos+, fileLen, mpeg4Bits); vosData = (unsigned char*)malloc(vosLen);
if (vosData)
{
memset(vosData, 0x0, vosLen); memcpy(vosData, mpeg4Bits+mpeg4BitsPos+, vosLen); ParseVosData(vosLen, vosData); free(vosData);
vosData = NULL;
} mpeg4BitsPos += (vosLen+);
}
else
{
mpeg4BitsPos++;
}
} if (!mpeg4VosFind)
{
#ifdef PRINTF_DEBUG
printf("Can not find vos, find vop...\n");
#endif
/* can not find vos, find vop */
mpeg4BitsPos = ; while (mpeg4BitsPos < (fileLen-))
{
if (FindStartCode(E_SC_MPEG4_VOP, &mpeg4Bits[mpeg4BitsPos]))
{
//printf("find vop??\n");
vopLen = GetMpeg4DataLen(E_SC_MPEG4_VOP, mpeg4BitsPos+, fileLen, mpeg4Bits); vopData = (unsigned char*)malloc(vopLen);
if (vopData)
{
memset(vopData, 0x0, vopLen); memcpy(vopData, mpeg4Bits+mpeg4BitsPos+, vopLen); ParseVopData(vopLen, vopData); free(vopData);
vopData = NULL;
} mpeg4BitsPos += (vopLen+);
}
else
{
mpeg4BitsPos++;
}
}
}
}

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

mpeg4文件分析(纯c解析代码)的更多相关文章

  1. h264文件分析(纯c解析代码)

    参考链接:1. 解析H264的SPS信息 https://blog.csdn.net/lizhijian21/article/details/80982403               2. h.2 ...

  2. ts文件分析(纯c解析代码)

    参考链接: 1. MPEG-2 TS码流分析 https://blog.csdn.net/zhubin215130/article/details/8958567 TS Header PAT PMT ...

  3. h265文件分析(纯c解析代码)

    参考链接: 1. HEVC码流解析 https://blog.csdn.net/CrystalShaw/article/details/80624804   2. HEVC编码结构:序列参数集SPS. ...

  4. mpeg2文件分析(纯c解析代码)

    参考链接: 1. MPEG-2码流结构分析 https://www.cnblogs.com/CoderTian/p/9246225.html(本文语法采用这里的截图,代码原创) 1. mpeg2的码流 ...

  5. flv文件解析(纯c解析代码)

    参考链接: 1. FLV科普12 FLV脚本数据解析-Metadata Tag解析 https://blog.csdn.net/cabbage2008/article/details/50500021 ...

  6. ps文件解析(纯c解析代码)

    参考链接:1. PS流的格式和解析总结 http://www.cnblogs.com/lihaiping/p/4181607.html  2. TS科普5 PES包解析 https://blog.cs ...

  7. mp4文件解析(纯c解析代码)

     参考链接:1. mp4文件格式解析 https://www.cnblogs.com/ranson7zop/p/7889272.html   2. MP4文件格式分析及分割实现(附源码) https: ...

  8. linux内核中链表代码分析---list.h头文件分析(一)【转】

    转自:http://blog.chinaunix.net/uid-30254565-id-5637596.html linux内核中链表代码分析---list.h头文件分析(一) 16年2月27日17 ...

  9. linux内核中链表代码分析---list.h头文件分析(二)【转】

    转自:http://blog.chinaunix.net/uid-30254565-id-5637598.html linux内核中链表代码分析---list.h头文件分析(二) 16年2月28日16 ...

随机推荐

  1. 从手机中导出apk

    输入指令adb devices, 出现类似下面信息,说明设备连接成功. List of devices attached HT4C3JT00386 device 3.查看该手机所有安装包的包名, 输入 ...

  2. 工作中常用的 Shell 命令及技巧

    调试 bash 脚本的技巧 加 -x 参数运行 bash 脚本时,会显示执行的语句 # 也可以在 demo.sh 中加上 set -x bash -x demo.sh 设置环境变量,然后通过如上方式运 ...

  3. KMP总结

    首先给一个我能看懂的KMP讲解: http://blog.csdn.net/v_july_v/article/details/7041827 来自大神july 文章很长,但是慢慢看,会发现讲的很好. ...

  4. Ubuntu下的Selenium爬虫的配置

    在服务器Ubuntu系统上跑爬虫,爬虫是基于Selenium写的,遇到好几个问题,现在这里记录一下. 1. 安装环境 阿里云,Ubuntu16.04,因为没有界面,所以远程命令行操作.爬虫是基于Sel ...

  5. python转义符

  6. linux下查找堆栈信息例子

  7. php安全开发(1)文件包含漏洞

    开发过程总结的漏洞: 一,,如何造成包含漏洞:在通过函数包含文件时,由于没有对包含的文件名进行有效的过滤处理,被攻击者利用从而导致了包含了Web根目录以外的文件进来,就会导致文件信息的泄露甚至注入了恶 ...

  8. 2019.4.24(js)

    1. 取得正数和负数的绝对值 Math.abs(7.25) Math.abs(-7.25) 2.利用JS刷新页面方法 https://www.cnblogs.com/Chen-XiaoJun/p/62 ...

  9. jquary高级和ajax

    jquary高级: 1.动画 1.三种方式显示与隐藏元素 1.默认显示和隐藏的方式 1.show([speed],[easing],[fn]):显示 [speed],[easing],[fn] spe ...

  10. 毕设记录(ajax)

    有关ajax的cache属性值 cache作用:是否在缓存中读取数据的读取. cache属性是true(默认值)时:在第一次请求完成之后,如果地址和参数不变化,第二次去请求,会默认获取缓存中的数据,不 ...