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 ...
随机推荐
- HackerRank-Python攻城歷程-3.List( Find the Second Largest Number )
if __name__ == '__main__': n = int(input()) arr = map(int, input().split()) print(sorted(list(set(ar ...
- 【HNOI 2017】大佬
Problem Description 人们总是难免会碰到大佬.他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢言语.你作为一个 OIer, ...
- 阿里云Hadoop集群DataNode连接不上NameNode
在logs日志中可以看见DataNode多次去连NameNode,但是都失败了. 经过长时间的研究百度,终于知道了原因. 原因就是安全组限制了端口的开放,所以我们只要把相应的端口打开即可.
- git命令-切换分支
git一般有很多分支,我们clone到本地的时候一般都是master分支,那么如何切换到其他分支呢? 1. 查看远程分支 $ git branch -a 我在mxnet根目录下运行以上命令: ~/mx ...
- Vue-admin工作整理(四):路由组件传参
路由组件传参:如果在一个页面中,需要根据路由去获得参数,去对页面进行一些逻辑处理,首先可以通过this.$router来获取路由实例的参数,这样页面组件和路由就进行了耦合,为了进行分离,更大程度复用, ...
- T2027 蜈蚣
传送门 思路: 设 f[ i ][ j ] 为第 i 节,切到第 j 段的最大恶心值. 枚举 左端点 j ,右端点 i ,段数 k → 转移: f [ i ][ k ] = max ( f [ i ...
- ZT: C#不建类直接Json解析与取值
C#不建类直接Json解析与取值 2017年10月19日 15:58:22 圆圆娃哈哈 阅读数:701 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn. ...
- postgres 11 单实例最大支持多少个database?
有人在pg8时代(10年前)问过,当时说10000个没问题,而且每个db会在/base下建立1个文件夹, 文件ext3只支持32000个子文件夹,所以这是上限了. 而现在早就ext4了,根本没有限制了 ...
- java反射使用和源码解析
1 反射 1.1 什么是反射 正射:指的是我们知道类的定义和类中的方法名称,直接先创建对象,然后通过对象去调用方法.例如: Apple apple = new A ...
- java mvn:安装jar包
mvn install:install-file -Dfile=fastdfs-client-java-1.27-SNAPSHOT.jar(路径) -DgroupId=org.csource -Dar ...