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 ...
随机推荐
- 理解bootstrap的列偏移offset 和 推拉push/pull的区别?
参考: http://www.cnblogs.com/jnslove/p/5430481.html & https://blog.csdn.net/hly_coder/article/deta ...
- ValueObject
ValueObject When programming, I often find it's useful to represent things as a compound混合物. A 2D co ...
- selenium中CSS选择器定位
selenium元素定位,CSS选择器定位效率会高很多. CSS选择器用于选择你想要的元素的样式的模式.表格摘自“菜鸟教程”,具体用法可去查阅 选择器 示例 示例说明 CSS .class .intr ...
- spring data jpa开启批量插入、批量更新
spring data jpa开启批量插入.批量更新 原文链接:https://www.cnblogs.com/blog5277/p/10661096.html 原文作者:博客园--曲高终和寡 *** ...
- Pandas 基础(14) - DatetimeIndex and Resample
这一小节要介绍两个内容, 一个是 DatetimeIndex 日期索引, 另一个是 Resample, 这是一个函数, 可以通过参数的设置, 来调整数据的查询条件, 从而得到不同的结果. 首先看下关于 ...
- highcharts数据标签显示在柱状图里面解决办法
1.现象:当各项占比相同时,数据显示在柱状图里面 2.解决方法: 3.效果
- IBase<T>
public interface IBase<T>//基类 { IEnumerable<T> SelectAll();//查询所有 T FindById(int ID);//根 ...
- Android 项目配置 gitlab-ci 持续集成
一.项目根目录下创建一个 .gitlab-ci.yml 文件 然后在 .gitlab-ci.yml 中配置持续集成的脚本: 脚本配置详细可以看: Configuration of your jobs ...
- inode满处理
https://blog.csdn.net/liuxiao723846/article/details/79423581 [root@monitor251 bin]# for i in /boot; ...
- Itext生成pdf文件
来源:https://my.oschina.net/lujianing/blog/894365 1.背景 在某些业务场景中,需要提供相关的电子凭证,比如网银/支付宝中转账的电子回单,签约的电子合同等. ...