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

#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解析代码)的更多相关文章
- h264文件分析(纯c解析代码)
参考链接:1. 解析H264的SPS信息 https://blog.csdn.net/lizhijian21/article/details/80982403 2. h.2 ...
- ts文件分析(纯c解析代码)
参考链接: 1. MPEG-2 TS码流分析 https://blog.csdn.net/zhubin215130/article/details/8958567 TS Header PAT PMT ...
- h265文件分析(纯c解析代码)
参考链接: 1. HEVC码流解析 https://blog.csdn.net/CrystalShaw/article/details/80624804 2. HEVC编码结构:序列参数集SPS. ...
- mpeg2文件分析(纯c解析代码)
参考链接: 1. MPEG-2码流结构分析 https://www.cnblogs.com/CoderTian/p/9246225.html(本文语法采用这里的截图,代码原创) 1. mpeg2的码流 ...
- flv文件解析(纯c解析代码)
参考链接: 1. FLV科普12 FLV脚本数据解析-Metadata Tag解析 https://blog.csdn.net/cabbage2008/article/details/50500021 ...
- ps文件解析(纯c解析代码)
参考链接:1. PS流的格式和解析总结 http://www.cnblogs.com/lihaiping/p/4181607.html 2. TS科普5 PES包解析 https://blog.cs ...
- mp4文件解析(纯c解析代码)
参考链接:1. mp4文件格式解析 https://www.cnblogs.com/ranson7zop/p/7889272.html 2. MP4文件格式分析及分割实现(附源码) https: ...
- linux内核中链表代码分析---list.h头文件分析(一)【转】
转自:http://blog.chinaunix.net/uid-30254565-id-5637596.html linux内核中链表代码分析---list.h头文件分析(一) 16年2月27日17 ...
- linux内核中链表代码分析---list.h头文件分析(二)【转】
转自:http://blog.chinaunix.net/uid-30254565-id-5637598.html linux内核中链表代码分析---list.h头文件分析(二) 16年2月28日16 ...
随机推荐
- Elasticsearch .net client NEST 空字符/null值查询
null值查询 当某个字段值为null时,其实在es里该条数据是没有这个字段的.查询时检测包含不包含该字段就行. /// <summary> /// null 值查询 /// 当数据为Nu ...
- Python内置进制转换函数(实现16进制和ASCII转换)
在进行wireshark抓包时你会发现底端窗口报文内容左边是十六进制数字,右边是每两个十六进制转换的ASCII字符,这里使用Python代码实现一个十六进制和ASCII的转换方法. hex() 转换一 ...
- jenkins 配置
配置: echo " aliyun.oss.access.key=LTAIz4Koeff8sCr8 " > ./src/main/resources/oss.dev.prop ...
- IIC为什么要配置为开漏输出呢?
开漏输出只能输出低电平,类似于三极管的集电极,要输出高电平需要上拉电阻才能输出 当集电极接上拉电阻后,(1)基极为高电平,三极管导通,集电极的电位就会被拉低: (2)基极为低电平,三极管不导通,集电极 ...
- 深度学习环境搭建(ubuntu16.04+Titan Xp安装显卡驱动+Cuda9.0+cudnn+其他软件)
一.硬件环境 ubuntu 16.04LTS + windows10 双系统 NVIDIA TiTan XP 显卡(12G) 二.软件环境 搜狗输入法 下载地址 显卡驱动:LINUX X64 (AMD ...
- gdb 命令汇总
https://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_109.html whatis expr 举例 whatis uint64 -& ...
- Spring Boot 返回 JSON 数据,一分钟搞定!
如何返回 JSON 数据? 在 Spring Boot 中返回 JSON 数据很简单,如下几步. 加入依赖 12345678910 <parent> <groupId>org. ...
- [Windows] 重新安装/卸载桌面版OneDrive / Reinstall/ Uninstall Desktop Version OneDrive
Deep within the OS is a backup copy of the OneDriver installer. To find it, go to File Explorer> ...
- UML图概述
UML图概述 UML是一种分析设计语言,即一种建模语言.UML是由图形符号表达的建模语言,其结构主要包括视图.图.模型元素和通用机制四部分. UML包括5种视图,分别是用户视图.结构视图.行为视图.实 ...
- Java Design Pattern(Factory,Singleton,Prototype,Proxy)
一.Factory 设计模式: the most common pattern,create a new object ,eg. A a=new A();工厂模式的好处:工厂模式可以做到把创建对象单独 ...