mp4格式随笔

说明:MP4v2版本号为mp4v2-2.0.0;不同版本创建的mp4info结构略有差异;

创建mp4文件

接口有两个:
(1) MP4FileHandle MP4Create(
		const char* fileName,  //输入的想要创建的mp4文件名;
		uint32_t flags DEFAULT(0) );//位掩码,允许用户为数据或时间原子设置64位值.有效位可以是以下任意组合: 
		//MP4_CREATE_64BIT_DATA(0x01) 与 MP4_CREATE_64BIT_TIME(0x02) 默认为0,两者皆没有选择;
/*源码
{
	return MP4CreateEx(fileName, flags); 实际上调用了MP4CreateEx;
}*/

(2) MP4FileHandle MP4CreateEx(
	    const char* fileName,   //输入的想要创建的mp4文件名;
	    uint32_t    flags DEFAULT(0),//位掩码,允许用户为数据或时间原子设置64位值; 默认0;
	    int         add_ftyp DEFAULT(1),//如果为true,则自动创建<b>ftyp</b>原子。 默认1; 
	    int         add_iods DEFAULT(1),//如果为true,则自动创建<b>iods</b>原子。 默认1; 
	    char*       majorBrand DEFAULT(0),//<b>ftyp</b>主要标识,默认0;
	    uint32_t    minorVersion DEFAULT(0),//为主要标识的次要版本提供信息整数。 默认0;
	    char**      compatibleBrands DEFAULT(0),//<b>ftyp</b>兼容标识列表。默认0;
	    uint32_t    compatibleBrandsCount DEFAULT(0) );//兼容标识数量,默认0;


总结:
	实际调用时,通过:
	MP4FileHandle hMp4file = MP4Create(pFileName,  MP4_CREATE_64BIT_DATA);
	if (hMp4file == MP4_INVALID_FILE_HANDLE){...}
	或
	MP4FileHandle hMp4file = MP4CreateEx(pFileName,  MP4_CREATE_64BIT_DATA, 1, 1, 0, 0, 0, 0);
	if (hMp4file == MP4_INVALID_FILE_HANDLE){...}
	来创建mp4文件;

mp4info 与 WinHex工具分析

在这里插入图片描述

1. ftyp box

简介: 有且只有一个,在mp4文件最开始的地方;

1.1 MP4CreateEx(pFileName, MP4_CREATE_64BIT_DATA, 1, 1, “wu”, 100, 0, 0);调用后;
通过二进制分析:
在这里插入图片描述

其中: 
00 00 00 10 为该box的长度;总共占位4字节;
66 74 79 70为固定标识ftyp;总共占位4字节;
77 75 00 00为MP4CreateEx中majorBrand主标识;明显这里填入的是"wu"; 总共占位4字节;
00 00 00 64为MP4CreateEx中minorVersion整数值; 这里写入的是100; 总共占位4字节;

参数 compatibleBrands和compatibleBrandsCount 传入若compatibleBrandsCount 大于1,将会产生段错误;原因未知;使用默认就好;

1.2 MP4CreateEx(pFileName, MP4_CREATE_64BIT_DATA, 1, 1, 0, 0, 0, 0); 默认参数创建后;
在这里插入图片描述
其中:

00 00 00 18 为该box的长度;
...
6D 70 34 32 69 73 6F 6D:为mp42isom;兼容标识;占位8bit;
兼容标识为mp42isom的源码,可能各个版本标识不太一样;
void MP4FtypAtom::Generate()
{
    MP4Atom::Generate();

    majorBrand.SetValue( "mp42" );
    minorVersion.SetValue( 0 );

    compatibleBrands.SetCount( 2 );
    compatibleBrands.SetValue( "mp42", 0 );
    compatibleBrands.SetValue( "isom", 1 );
}

2. free box

简介: "free"中的内容是无关紧要的, 可以被忽略;该box被删除后,不会对播放产生任何影响;

从mp4info部分看出,free box有两个,另外一个在最后;数据一模一样;
其中:

00 00 00 88 为该free box的长度;0x88 -> 十进制为136字节;
66 72 65 65 为该free box的固定标识 "free";

3. (截图仅仅开始部分值) mdat box

简介: 该box包含于文件层,可以有多个,当媒体数据全部为外部文件引用时也可以没有;用来存储媒体数据;数据直接跟在 box type字段后面;
具体的意义参考metadata(主要在sample table中);

4. Movie Box(moov)

简介: 该box包含了文件媒体的metadata信息,"moov"是一个container box,具体内容信息由子box诠释;同 ftyp box 一样;该box有且只有一个;
且被包含在文件层;一般情况下,"moov"会仅随着"ftyp"出现;
一般情况下:“moov"中会包含一个"mvhd"和若干个"trak”;其中"mvhd"为header box,作为"moov"的第一个子box出现;"trak"包含了一个
tack的相关信息,是一个container box;
在这里插入图片描述
其中:

00 00 1E B8 为moov的长度;
6D 6F 6F 76为"moov"标识; 
4.1 mvhd

简介:Movie Header Box; 对整个文件所包含的媒体数据作全面的描述;包含了媒体的创建与修改时间刻度,默认音量,色域时长等信息;

mvhd用结构体表示如下;
typedef struct 
{
	int box_size; //box大小;4字节;
	int box_type; //box类型;4字节;
	char version; //box版本,0或1;一般为0; 1字节;
	char flags[3];//标志,3字节;
	int creation_time;//创建时间;相对于UTC时间1904-01-01零点的秒数;4字节;
	int modification_time;//修改时间; 4字节; 
	int time_scale;//文件媒体在1秒时间内的刻度值,可以理解为1秒长度的时间单元数;4字节;
	int duration;//该track的时间长度,用duration和time scale值可以计算track时长, 4字节;
				//比如audio track的time scale = 8000,duration = 560128,时长为70.016,video track的time scale=600,duration=42000,时长为70;
	int rate;//	推荐播放速率,高16位和低16位分别为小数点整数部分和小数部分,即[16.16] 格式,该值为1.0(0x00010000)表示正常前向播放;4字节;
	short volume;//与rate类似,[8.8] 格式,1.0(0x0100)表示最大音量;
	char reserved[10];//保留
	char matrix[36];//视频变换矩阵;
	char pre_defined[24];
	int next_track_id;//下一个track使用的id号;4字节;
	
}mvhd;

mp4info如下如:
在这里插入图片描述

其中:

00 00 00 6C 为mvhd的长度;对应box_size;
6D 76 68 64为"mvhd"标识; 对应box_type;
00 00 00 00为版本和标记;对应version(1byte)+flags(3byte);
7C 27 D9 0D为创建时间,对应creation_time;
7C 27 D9 3C为修改时间,对应modification_time;
00 01 5F 90为time_scale;
00 3F 75 00为duration;公式:duration / timescale = 可播放时长(s);换算下来等于46s;和实际播放一样;
00 01 00 00为rate; 值为1.0,正常速率播放;
01 00 为volume;值为1.0,最大音量;
...
00 00 00 03 为next_track_id;

对应部分源码在 src\atom_mvhd.cpp中;

4.2 iods

可以在MP4CreateEx的参数4控制是否创建; 可省,具体作用暂不知;
00 00 00 18 表示该box长度;
69 6F 64 73 表示"iods"标识;

4.3 trak

简介:trak box它属于moov的子box;是一个container box;其子box包含了该track的媒体数据引用和描述(hint track除外);
一个mp4文件中的媒体可以包含多个track,且至少由一个track,这些track间彼此独立,有自己的时间和空间信息;“trak"必须
包含一个"tkhd"和一个"media”,

4.3.1 tkhd

简介: 它是trak box的第一个子box; 全名(Track Header Box);
源码位置:src\atom_tkhd.cpp中;

tkhd用结构体表示如下;
typedef struct
{
	int box_size;//box大小;4字节;
	int box_type;//box类型;4字节;
	char version;//box版本,0或1,一般为0; 1字节;
	char flags[3];//按位或操作结果值; 3字节;
				/*0x000001 :track_enabled,使能;未使能该track不能被播放
				  0x000002 :track_in_movie,表示该track在播放中被引用;
				  0x000004 :track_in_preview;表示该track在预览时被引用;
				  一般该值为7,若一个媒体所有track均未设置track_in_movie和track_in_preview;
				  将被理解为所有track均设置了这两项;对于hint_track,该值为0;
				*/
	int creation_time;//创建时间; 4字节;
	int modification_time;//修改时间;4字节;
	int track_id;//id号,不能重复且不能为0;4字节;
	char reserved[4];//保留位;4字节;
	int duration;//track的时间长度;4字节;
	char reserved1[8];//保留位;8字节;
	short layer;//视频层,默认0;值小的在上面;2字节;
	short alternate_group;//track分组信息;默认为0表示该track未与其他track有群组关系;2字节;
	short volume;//[8.8] 格式,如果为音频track,1.0(0x0100)表示最大音量;否则为0;2字节;
	char reserved2[2];//保留位;2字节;
	char matrix[36];//视频变换矩阵;
	int width;//宽;4字节;
	int height;//高;均为 [16.16]格式值,与sample描述中的实际画面大小比值,用于播放时的展示宽高;4字节;
}tkhd;

mp4info如下如:
在这里插入图片描述

其中:

00 00 00 5C表示该tkhd长度;
74 6B 68 64表示"tkhd"标识;
00 00 00 01表示version(0x00)+flags(0x000001)使能;可以播放该track;
7C 27 D9 0D:创建时间;对应creation_time;
7C 27 D9 3C:修改时间modification_time;
00 00 00 02:track id;
00 00 00 00:保留
00 3F 75 00:track的时间长度;对应duration;   
00 00 00 00 00 00 00 00 :保留;  
00 00 :layer 视频层;
00 00:track分组信息;
01 00:volume对应值未1.0;最大音量;
00 00 :保留
后面36字节:视频变换矩阵;    与源码中的值一模一样;
03 20 00 00:宽;800;
02 58 00 00:高;600;
源码:
static uint8_t matrix[36] = {
       0x00, 0x01, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00,
       0x00, 0x01, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00,
       0x40, 0x00, 0x00, 0x00,
   };
((MP4BytesProperty*)m_pProperties[12])->SetValue(matrix, sizeof(matrix));
4.3.2 mdia

简介:“Media Box”;是一个 container box;子box结构和种类比较复杂;
总体来说,"mdia"定义了track媒体类型以及sample数据;描述sample信息;一般"mdia"下列内容:
=>"mdhd"为media header box;
=>"hdlr"为handler reference box;解释了媒体播放的播放过程信息;该box也可以被包含在meta box中;
=>"minf"为media information box;存储了解释track媒体数据的handler-specific信息,media handler用这些信息将媒体时间映射到媒体
数据并进行处理;"minf"中的信息格式信息和内容与媒体类型以及解释媒体数据的media handler密切相关;其他media handler不知道
如何解释这些信息;是一个container box;其实际内容由子box说明;

4.3.2.1 mdhd
mdhd对应结构内容
typdef struct
{
	int box_size;//box大小;4字节;
	int box_type;//box类型;4字节;
	char version;//box版本,0或1,一般为0; 1字节;
	char flags[3];
	int creation_time;//创建时间; 4字节;
	int modification_time;//修改时间;4字节;
	int time_scale;//文件媒体在1秒时间内的刻度值,可以理解为1秒长度的时间单元数;4字节;
	int duration;//该track的时间长度;
	short language;//媒体语言码;最高位为0,后面15位为3个字符(见ISO 639-2/T标准中定义)
	short pre_defined;
}mdhd;

mp4info如下如:
在这里插入图片描述
其中:

00 00 00 20 :box大小
6D 64 68 64 :"mdhd"标识;   
00 00 00 00 :version+flags
7C 27 D9 0D :创建时间
7C 27 D9 3C :修改时间;
00 01 5F 90 :time_scale值
00 3F 39 F0:duration值
55 C4:媒体语言码
00 00:pre_defined
4.3.2.2 hdlr
hdlr对应结构内容
typdef struct
{
	int box_size;//box大小;4字节;
	int box_type;//box类型;4字节;
	char version;//box版本,0或1,一般为0; 1字节;
	char flags[3];
	int pre_defined;
	int handler_type;//在media box中,该值为4个字符;
	/*vide -> video track 
	  soun -> audio track
	  hint -> hint  track
	*/
	char reserved[12];
	char *name;//长度不定,track type name;以'\0'结尾的字符串;
}mdlr;

mp4info如下如:
在这里插入图片描述
其中:

00 00 00 21 :mdlr box长度
68 64 6C 72 :"mdlr"标识;
00 00 00 00 :version+flags
00 00 00 00  : pre_defined
76 69 64 65 :vide;可知为视频track;
...
4.3.2.3 minf

简介:"minf"包含如下:
源码: src/mp4file.cpp/AddH264VideoTrack

4.3.2.3.1 header box;

根据上面的track type对应;
/* 源码
#define MP4_OD_TRACK_TYPE       "odsm"  /**< Constant: OD track. */
#define MP4_SCENE_TRACK_TYPE    "sdsm"  /**< Constant: scene track. */
#define MP4_AUDIO_TRACK_TYPE    "soun"  /**< Constant: audio track. */
#define MP4_VIDEO_TRACK_TYPE    "vide"  /**< Constant: video track. */
#define MP4_HINT_TRACK_TYPE     "hint"  /**< Constant: hint track. */
#define MP4_CNTL_TRACK_TYPE     "cntl"  /**< Constant: control track. */
#define MP4_TEXT_TRACK_TYPE     "text"  /**< Constant: text track. */
#define MP4_SUBTITLE_TRACK_TYPE "sbtl"  /**< Constant: subtitle track. */
#define MP4_SUBPIC_TRACK_TYPE   "subp"  /**< Constant: subpic track. */
*/
struct xxx
{
	int box_size;//box大小;4字节;
	int box_type;//box类型;4字节;
	char version;//box版本,0或1,一般为0; 1字节;
	char flags[3];
	
	#if vmhd
	int graphics_mode;//视频合成模式;为0时拷贝原始图像;否则与opcolor进行合成;
	short[3];//{red,green,blue};
	#else if smhd
	float balance;//立体声平衡,[8.8] 格式值,一般为0,-1.0表示全部左声道,1.0表示全部右声道
	char reserved[2];
	#else
	...
	#endif
};

在这里插入图片描述
vmhd
其中:

00 00 00 14 :该box长度;
76 6D 68 64 :"vmhd",可知为视频;  
00 00 00 01:version+flags 
00 00 00 00 : graphics_mode 为0;
00 00 00 00: 

4.3.2.3.2 dinf:data information box;

简介:解释如何定位媒体信息;是一个container box;一般包含一个 dref;即data reference box;
dref下回包含若干 url或 urn;这些box组成一个表;用来定位track数据;
简单的说:track可以被分成若干段,每一段都可以根据url或urn指向的地址来获取数据;sample描述中会用这些片段的序号将这些组成
一个完整的track;一般情况下,当数据被完全包含在文件中时;url和urn中的定位字符串为空的;url或urn都是box;url的内容为字符
串(location string); urn的内容为一对字符串(name string and location string);当url或urn的box flag为时,字符串均为空;
typedef struct 
{
	int box_size;//box大小;4字节;
	int box_type;//box类型;4字节;
	char version;//box版本,0或1,一般为0; 1字节;
	char flags[3];
	int entry_count;//“url”或“urn”表的元素个数
	char *url_urn_table;//“url”或“urn”表
}dinf;

在这里插入图片描述
其中:

00 00 00 24:dinf长度
64 69 6E 66 :”dinf“字符串标识   
00 00 00 1C :dref长度
64 72 65 66 :"dref"字符串标识;
00 00 00 00 :version+flags
00 00 00 01 :url/urn元素个数;   
00 00 00 0C :url/urn元素表;   

4.3.2.3.3 stbl (sample table box)
简介:它是minf box的子box;"stbl"几乎是普通mp4文件中最复杂的一个box了;首先需要会议一下sample的概率;
sample是媒体数据存储的单位;存储在media的chunk中;chunk和sample的长度均互不相同;
在这里插入图片描述

stbl包含了关于track中sample所有时间和位置的信息;以及sample的编解码等信息;
利用这个表,可以解释sample的时序,类型,大小以及在各自存储容器中的位置;stbl是一个container box,其子box包括:
在这里插入图片描述

(a) stsd: sample description box;
=> 属于stbl box的子box;stsd必不可少;且至少包含一个条目;该box包含了data reference box进行sample数据检索的信息;
=> 没有stsd就无法计算media sample的存储位置;sdsd包含了编码的信息,其存储的信息随媒体类型不同而不同;box header
和version字段后有一个entry count字段;根据entry的个数,每个entry会有信息,如vide,sund等;根据type不同,sample destription
会提供不同的信息,如video track,会有visualSampleEntry类型信息,对于audio track会有AudioSampleEntry类型信息;
=> 视频的编码类型,宽高,长度,音频的声道,采样等信息都会出现在这个box中;

(b) stts:time to sample box;
=> 属于stbl box的子box;stts存储了sample的duration,描述了sample时序的映射方法;我们通过它可以找到任何时间的sample;stts可以包含
一个压缩的表来映射时间和sample序号;用其他的表来提供每个sample的长度和指针;表中每个条目提供了在同一个时间偏移里面连续的
sample序号,以及samples的偏移量;递增这些偏移量,就可以建立一个完整的time to sample表;

(c ) stsz或stz2: sample size box;
=> 属于stbl box的子box; stsz定义了每个sample 的大小;包含了媒体中全部的sample的数目和一张给出每个sample大小的表;这个box相对
来说是体积比较大的;

(d) stsc:sample to chunk box
=> 属于stbl box的子box;用chunk组织的sample可以方便优化数据获取,一个trunk包含一个或多个sample;stsc中用一个表来描述sample
和chunk的映射关系,查看这张表就可以找到指定sample的thunk,从而找到这个sample;

(e) stco或co64:chunk offset box;
=> 属于stbl box的子box;stco”定义了每个thunk在媒体流中的位置。位置有两种可能,32位的和64位的,后者对非常 大的电影很有用。
在一个表中只会有一种可能,这个位置是在整个文件中的,而不是在任何box中的,这样做就可以直接在文件中找到媒体数据,
而不用解释 box。需要注意的是一旦前面的box有了任何改变,这张表都要重新建立,因为位置信息已经改变了。

(f) ctts:composion time to sample box;
=> 属于stbl box的子box;

(g) stss:sync sample box;
=> 属于stbl box的子box;它是stbl box的子box。stss”确定media中的关键帧。对于压缩媒体数据,关键帧是一系列压缩序列的开始帧,
其解压缩 时不依赖以前的帧,而后续帧的解压缩将依赖于这个关键帧。“stss”可以非常紧凑的标记媒体内的随机存取点,它包含一个
sample序号表,表内的每一 项严格按照sample的序号排列,说明了媒体中的哪一个sample是关键帧。如果此表不存在,说明每一个
sample都是一个关键帧,是一个随机存取点。

参考博客:

本文绝大部分参考自下面博客,仅做学习笔录;
https://www.cnblogs.com/ranson7zop/p/7889272.html
https://blog.csdn.net/lh2016rocky/article/details/52691768

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值