MP4 文件格式
2015-10-11 19:53
399 查看
一、概况
最基本的3个结构:ftyp(文件类型头)、moov(媒体描述信息)、mdat(媒体sample数据)。
二、Mp4中 sample 时间索引 与 文件偏移索引(stbl)
1、标准描述:
“stbl”几乎是普通的MP4文件中最复杂的一个box了,首先需要回忆一下sample的概念。sample是媒体数据存储的单位,存储在media的chunk中,chunk和sample的长度均可互不相同。
“stbl”包含了关于track中sample所有时间和位置的信息,以及sample的编解码等信息。利用这个表,可以解释sample的时序、类型、大小以及在各自存储容器中的位置。“stbl”是一个container
box,其子box包括:sample
description box(stsd)、time
to sample box(stts)、sample
size box(stsz或stz2)、sample
to chunk box(stsc)、chunk
offset box(stco或co64)、composition
time to sample box(ctts)、sync
sample box(stss)等。
sample table box描述sample的所有信息以及一些不同类型的box,media
handler可以用这些信息正确的按顺序解析所有的samples,而不需要强迫这些数据按movie的时间顺序存放到实际数据流中。
如果sample table
box所在的track引用了数据,那么必须包含以下的子box:sample
description, sample size, sample to chunk和chunk offset。所有的子表有相同的sample数目。
“stsd”必不可少,且至少包含一个条目,该box包含了data
reference box进行sample数据检索的信息。没有“stsd”就无法计算media
sample的存储位置。“stsd”包含了编码的信息,其存储的信息随媒体类型不同而不同。
Sample Description Box(stsd)
box header和version字段后会有一个entry
count字段,根据entry的个数,每个entry会有type信息,如“vide”、“sund”等,根据type不同sample
description会提供不同的信息,例如对于video track,会有“VisualSampleEntry”类型信息,对于audio
track会有“AudioSampleEntry”类型信息。
视频的编码类型、宽高、长度,音频的声道、采样等信息都会出现在这个box中。
根据不同的编码方案和存储数据的文件数目,每个media可以有一个到多个sample
description。sample-to-chunk通过这个索引表,找到合适media中每个sample的description。
数据结构表:
Time To Sample Box(stts)
“stts”存储了sample的duration,描述了sample时序的映射方法,我们通过它可以找到任何时间的sample。“stts”可以包含一个压缩的表来映射时间和sample序号,用其他的表来提供每个sample的长度和指针。表中每个条目提供了在同一个时间偏移量里面连续的sample序号,以及samples的偏移量。递增这些偏移量,就可以建立一个完整的time
to sample表。
计算公式如下
DT(n+1) = DT(n) + STTS(n)
其中STTS(n)是没有压缩的STTS第n项信息,DT是第n个sample的显示时间。Sample的排列是按照时间戳的顺序,这样偏移量永远是非负的。DT一般以0开始,如果不为0,edit
list box 设定初始的DT值。DT计算公式如下
DT(i) = SUM (for j=0 to i-1 of delta(j))
所有偏移量的和就是track中media的长度,这个长度不包括media的time
scale,也不包括任何edit list。
如果多个sample有相同的duration,可以只用一项描述所有这些samples,数量字段说明sample的个数。例如,如果一个视频媒体的帧率保持不变,整个表可以只有一项,数量就是全部的帧数。
Sample Size Box(stsz)
“stsz” 定义了每个sample的大小,包含了媒体中全部sample的数目和一张给出每个sample大小的表。这个box相对来说体积是比较大的。
解析stsz - Sample
Size table。这个表包含了每个sample的长度,找到sample的序号,就可以找到对应sample的长度了。
Sample To Chunk Box(stsc)
用chunk组织sample可以方便优化数据获取,一个thunk包含一个或多个sample。“stsc”中用一个表描述了sample与chunk的映射关系,查看这张表就可以找到包含指定sample的thunk,从而找到这个sample。
如何得到chunk的数目和每个chunk包含多少个sample,每个chunk的description是如何
解析stsc - Sample-to-Chunk
table。这个表类似于行程编码,第一个first chunk减去第二个first
chunk就是一共有多少个trunk包含相同的sample数目,这样通过不断的叠加,就可以得到一共有多少个trunk,每个trunk包含多少个sample,以及每个trunk对应的description。
Sync Sample Box(stss)
“stss”确定media中的关键帧。对于压缩媒体数据,关键帧是一系列压缩序列的开始帧,其解压缩时不依赖以前的帧,而后续帧的解压缩将依赖于这个关键帧。“stss”可以非常紧凑的标记媒体内的随机存取点,它包含一个sample序号表,表内的每一项严格按照sample的序号排列,说明了媒体中的哪一个sample是关键帧。如果此表不存在,说明每一个sample都是一个关键帧,是一个随机存取点。
Chunk Offset Box(stco)
“stco”定义了每个thunk在媒体流中的位置。位置有两种可能,32位的和64位的,后者对非常大的电影很有用。在一个表中只会有一种可能,这个位置是在整个文件中的,而不是在任何box中的,这样做就可以直接在文件中找到媒体数据,而不用解释box。需要注意的是一旦前面的box有了任何改变,这张表都要重新建立,因为位置信息已经改变了。
2、查找sample的位置:
当播放一部电影或者一个track的时候,对应的media
handler必须能够正确的解析数据流,对一定的时间获取对应的媒体数据。如果是视频媒体, media handler可能会解析多个atom,才能找到给定时间的sample的大小和位置。具体步骤如下:
1.确定时间,相对于媒体时间坐标系统
2.检查time-to-sample atom来确定给定时间的sample序号。
3.检查sample-to-chunk atom来发现对应该sample的chunk。
4.从chunk offset atom中提取该trunk的偏移量。
5.利用sample size atom找到sample在trunk内的偏移量和sample的大小。
例如,如果要找第1秒的视频数据,过程如下:
1. 第1秒的视频数据相对于此电影的时间为600
2. 检查time-to-sample
atom,得出每个sample的duration是40,从而得出需要寻找第600/40
= 15 + 1 = 16个sample
3. 检查sample-to-chunk
atom,得到该sample属于第5个chunk的第一个sample,该chunk共有4个sample
4. 检查chunk
offset atom找到第5个trunk的偏移量是20472
5. 由于第16个sample是第5个trunk的第一个sample,所以不用检查sample
size atom,trunk的偏移量即是该sample的偏移量20472。如果是这个trunk的第二个sample,则从sample
size atom中找到该trunk的前一个sample的大小,然后加上偏移量即可得到实际位置。
6. 得到位置后,即可取出相应数据进行解码,播放
3、查找关键帧:
查找过程与查找sample的过程非常类似,只是需要利用sync
sample atom来确定key frame的sample序号
确定给定时间的sample序号
检查sync
sample atom来发现这个sample序号之后的key frame
检查sample-to-chunk
atom来发现对应该sample的chunk
从chunk
offset atom中提取该trunk的偏移量
利用sample
size atom找到sample在trunk内的偏移量和sample的大小
最基本的3个结构:ftyp(文件类型头)、moov(媒体描述信息)、mdat(媒体sample数据)。
二、Mp4中 sample 时间索引 与 文件偏移索引(stbl)
1、标准描述:
“stbl”几乎是普通的MP4文件中最复杂的一个box了,首先需要回忆一下sample的概念。sample是媒体数据存储的单位,存储在media的chunk中,chunk和sample的长度均可互不相同。
“stbl”包含了关于track中sample所有时间和位置的信息,以及sample的编解码等信息。利用这个表,可以解释sample的时序、类型、大小以及在各自存储容器中的位置。“stbl”是一个container
box,其子box包括:sample
description box(stsd)、time
to sample box(stts)、sample
size box(stsz或stz2)、sample
to chunk box(stsc)、chunk
offset box(stco或co64)、composition
time to sample box(ctts)、sync
sample box(stss)等。
sample table box描述sample的所有信息以及一些不同类型的box,media
handler可以用这些信息正确的按顺序解析所有的samples,而不需要强迫这些数据按movie的时间顺序存放到实际数据流中。
如果sample table
box所在的track引用了数据,那么必须包含以下的子box:sample
description, sample size, sample to chunk和chunk offset。所有的子表有相同的sample数目。
“stsd”必不可少,且至少包含一个条目,该box包含了data
reference box进行sample数据检索的信息。没有“stsd”就无法计算media
sample的存储位置。“stsd”包含了编码的信息,其存储的信息随媒体类型不同而不同。
Sample Description Box(stsd)
box header和version字段后会有一个entry
count字段,根据entry的个数,每个entry会有type信息,如“vide”、“sund”等,根据type不同sample
description会提供不同的信息,例如对于video track,会有“VisualSampleEntry”类型信息,对于audio
track会有“AudioSampleEntry”类型信息。
视频的编码类型、宽高、长度,音频的声道、采样等信息都会出现在这个box中。
根据不同的编码方案和存储数据的文件数目,每个media可以有一个到多个sample
description。sample-to-chunk通过这个索引表,找到合适media中每个sample的description。
数据结构表:
字段 | 长度(字节) | 描述 |
尺寸 | 4 | box大小 |
类型 | 4 | stsd |
版本 | 1 | box版本 |
标志 | 3 | 这里为0 |
条目数目 | 4 | sample descriptions的数目 |
Sample description | 不同的媒体类型有不同的sample description,但是每个sample description的前四个字段是相同的,包含以下的数据成员 | |
尺寸 | 4 | 这个sample description的字节数 |
数据格式 | 4 | 存储数据的格式。 |
保留 | 6 | |
数据引用索引 | 2 | 利用这个索引可以检索与当前sample description关联的数据。数据引用存储在data reference box。 |
Time To Sample Box(stts)
“stts”存储了sample的duration,描述了sample时序的映射方法,我们通过它可以找到任何时间的sample。“stts”可以包含一个压缩的表来映射时间和sample序号,用其他的表来提供每个sample的长度和指针。表中每个条目提供了在同一个时间偏移量里面连续的sample序号,以及samples的偏移量。递增这些偏移量,就可以建立一个完整的time
to sample表。
计算公式如下
DT(n+1) = DT(n) + STTS(n)
其中STTS(n)是没有压缩的STTS第n项信息,DT是第n个sample的显示时间。Sample的排列是按照时间戳的顺序,这样偏移量永远是非负的。DT一般以0开始,如果不为0,edit
list box 设定初始的DT值。DT计算公式如下
DT(i) = SUM (for j=0 to i-1 of delta(j))
所有偏移量的和就是track中media的长度,这个长度不包括media的time
scale,也不包括任何edit list。
字段 | 长度(字节) | 描述 |
尺寸 | 4 | 这个box的字节数 |
类型 | 4 | Stts |
版本 | 1 | 这个box的版本 |
标志 | 3 | 这里为0 |
条目数目 | 4 | time-to-sample的数目 |
time-to-sample | Media中每个sample的duration。包含如下结构 | |
Sample count | 4 | 有相同duration的连续sample的数目 |
Sample duration | 4 | 每个sample的duration(长度) |
Sample Size Box(stsz)
“stsz” 定义了每个sample的大小,包含了媒体中全部sample的数目和一张给出每个sample大小的表。这个box相对来说体积是比较大的。
解析stsz - Sample
Size table。这个表包含了每个sample的长度,找到sample的序号,就可以找到对应sample的长度了。
字段 | 长度(字节) | 描述 |
尺寸 | 4 | 这个box的字节数 |
类型 | 4 | Stsz |
版本 | 1 | 这个box的版本 |
标志 | 3 | 这里为0 |
Sample size | 4 | 全部sample的数目。如果所有的sample有相同的长度,这个字段就是这个值。否则,这个字段的值就是0。那些长度存在sample size表中 |
条目数目 | 4 | sample size的数目 |
sample size | sample size表的结构。这个表根据sample number索引,第一项就是第一个sample,第二项就是第二个sample | |
大小 | 4 | 每个sample的大小 |
Sample To Chunk Box(stsc)
用chunk组织sample可以方便优化数据获取,一个thunk包含一个或多个sample。“stsc”中用一个表描述了sample与chunk的映射关系,查看这张表就可以找到包含指定sample的thunk,从而找到这个sample。
字段 | 长度(字节) | 描述 |
尺寸 | 4 | 这个box的字节数 |
类型 | 4 | Stsc |
版本 | 1 | 这个box的版本 |
标志 | 3 | 这里为0 |
条目数目 | 4 | sample-to-chunk的数目 |
sample-to-chunk | sample-to-chunk表的结构 | |
First chunk | 4 | 这个table使用的第一个chunk序号 |
Samples per chunk | 4 | 当前trunk内的sample数目 |
Sample description ID | 4 | 与这些sample关联的sample description的序号 |
解析stsc - Sample-to-Chunk
table。这个表类似于行程编码,第一个first chunk减去第二个first
chunk就是一共有多少个trunk包含相同的sample数目,这样通过不断的叠加,就可以得到一共有多少个trunk,每个trunk包含多少个sample,以及每个trunk对应的description。
Sync Sample Box(stss)
“stss”确定media中的关键帧。对于压缩媒体数据,关键帧是一系列压缩序列的开始帧,其解压缩时不依赖以前的帧,而后续帧的解压缩将依赖于这个关键帧。“stss”可以非常紧凑的标记媒体内的随机存取点,它包含一个sample序号表,表内的每一项严格按照sample的序号排列,说明了媒体中的哪一个sample是关键帧。如果此表不存在,说明每一个sample都是一个关键帧,是一个随机存取点。
字段 | 长度(字节) | 描述 |
尺寸 | 4 | 这个box的字节数 |
类型 | 4 | Stss |
版本 | 1 | 这个box的版本 |
标志 | 3 | 这里为0 |
条目数目 | 4 | sync sample的数目 |
sync sample | sync sample表的结构 | |
Sample序号 | 4 | 是关键帧的sample序号 |
Chunk Offset Box(stco)
“stco”定义了每个thunk在媒体流中的位置。位置有两种可能,32位的和64位的,后者对非常大的电影很有用。在一个表中只会有一种可能,这个位置是在整个文件中的,而不是在任何box中的,这样做就可以直接在文件中找到媒体数据,而不用解释box。需要注意的是一旦前面的box有了任何改变,这张表都要重新建立,因为位置信息已经改变了。
字段 | 长度(字节) | 描述 |
尺寸 | 4 | 这个box的字节数 |
类型 | 4 | Stco |
版本 | 1 | 这个box的版本 |
标志 | 3 | 这里为0 |
条目数目 | 4 | chunk offset的数目 |
chunk offset | 字节偏移量从文件开始到当前chunk。这个表根据chunk number索引,第一项就是第一个trunk,第二项就是第二个trunk | |
大小 | 4 | 每个sample的大小 |
当播放一部电影或者一个track的时候,对应的media
handler必须能够正确的解析数据流,对一定的时间获取对应的媒体数据。如果是视频媒体, media handler可能会解析多个atom,才能找到给定时间的sample的大小和位置。具体步骤如下:
1.确定时间,相对于媒体时间坐标系统
2.检查time-to-sample atom来确定给定时间的sample序号。
3.检查sample-to-chunk atom来发现对应该sample的chunk。
4.从chunk offset atom中提取该trunk的偏移量。
5.利用sample size atom找到sample在trunk内的偏移量和sample的大小。
例如,如果要找第1秒的视频数据,过程如下:
1. 第1秒的视频数据相对于此电影的时间为600
2. 检查time-to-sample
atom,得出每个sample的duration是40,从而得出需要寻找第600/40
= 15 + 1 = 16个sample
3. 检查sample-to-chunk
atom,得到该sample属于第5个chunk的第一个sample,该chunk共有4个sample
4. 检查chunk
offset atom找到第5个trunk的偏移量是20472
5. 由于第16个sample是第5个trunk的第一个sample,所以不用检查sample
size atom,trunk的偏移量即是该sample的偏移量20472。如果是这个trunk的第二个sample,则从sample
size atom中找到该trunk的前一个sample的大小,然后加上偏移量即可得到实际位置。
6. 得到位置后,即可取出相应数据进行解码,播放
3、查找关键帧:
查找过程与查找sample的过程非常类似,只是需要利用sync
sample atom来确定key frame的sample序号
确定给定时间的sample序号
检查sync
sample atom来发现这个sample序号之后的key frame
检查sample-to-chunk
atom来发现对应该sample的chunk
从chunk
offset atom中提取该trunk的偏移量
利用sample
size atom找到sample在trunk内的偏移量和sample的大小
相关文章推荐
- DVI 视频接口图文解析
- C#实现语音视频录制-附demo源码
- C#调用mmpeg进行各种视频转换的类实例
- C#获取视频某一帧的缩略图的方法
- 显示youtube视频缩略图和Vimeo视频缩略图代码分享
- PHP使用ffmpeg给视频增加字幕显示的方法
- PHP实现将视频转成MP4并获取视频预览图的方法
- 解决node-webkit 不支持html5播放mp4视频的方法
- C++实现优酷土豆去视频广告的方法
- PHP简单获取视频预览图的方法
- asp.net 页面中添加普通视频的几种方式介绍
- Android获取SD卡上图片和视频缩略图的小例子
- php使用memcoder将视频转成mp4格式的方法
- 基于js与flash实现的网站flv视频播放插件代码
- java调用ffmpeg实现视频转换的方法
- js+HTML5基于过滤器从摄像头中捕获视频的方法
- python+ffmpeg视频并发直播压力测试
- 为Nginx添加mp4流媒体支持
- 用Python的Django框架完成视频处理任务的教程
- Nginx搭建流媒体FLV视频服务器配置示例