MP4文件格式解析
wqyuwss的专栏 http://www.52rd.com/Blog/wqyuwss/559/一、概述 MP4文件格式中,所有的内容存在一个称为movie的容器中。一个movie可以由多个tracks组成。每个track就是一个随时间变化的媒体序列,例如,视频帧序列。track里的每个时间单位是一个sample,它可以是一帧视频,或者
wqyuwss的专栏 http://www.52rd.com/Blog/wqyuwss/559/
一、概述
MP4文件格式中,所有的内容存在一个称为movie的容器中。一个movie可以由多个tracks组成。每个track就是一个随时间变化的媒体序列,例如,视频帧序列。track里的每个时间单位是一个sample,它可以是一帧视频,或者音频。sample按照时间顺序排列。注意,一帧音频可以分解成多个音频sample,所以音频一般用sample作为单位,而不用帧。MP4文件格式的定义里面,用sample这个单词表示一个时间帧或者数据单元。每个track会有一个或者多个sample descriptions。track里面的每个sample通过引用关联到一个sample description。这个sampledescriptions定义了怎样解码这个sample,例如使用的压缩算法。
与其他的多媒体文件格式不同的是,MP4文件格式经常使用几个不同的概念,理解其不同是理解这个文件格式的关键。
这个文件的物理格式没有限定媒体本身的格式。例如,许多文件格式将媒体数据分成帧,头部或者其他数据紧紧跟随每一帧视频,!!!TODO(例如MPEG2)。而MP4文件格式不是如此。
文件的物理格式和媒体数据的排列都不受媒体的时间顺序的限制。视频帧不需要在文件按时间顺序排列。这就意味着如果文件中真的存在这样的一些帧,那么就有一些文件结构来描述媒体的排列和对应的时间信息。
MP4文件中所有的数据都封装在一些box中(以前叫atom)。所有的metadata(媒体描述元数据),包括定义媒体的排列和时间信息的数据都包含在这样的一些结构box中。MP4文件格式定义了这些这些box的格式。Metadata对媒体数据(例如,视频帧)引用说明。媒体数据可以包含在同一个的一个或多个box里,也可以在其他文件中,metadata允许使用URLs来引用其他的文件,而媒体数据在这些引用文件中的排列关系全部在第一个主文件中的metadata描述。其他的文件不一定是MP4文件格式,例如,可能就没有一个box。
有很多种类的track,其中有三个最重要,video track包含了视频sample;audio track包含了audiosample;hint track稍有不同,它描述了一个流媒体服务器如何把文件中的媒体数据组成符合流媒体协议的数据包。 如果文件只是本地播放,可以忽略hint track,他们只与流媒体有关系。
二、 结构
整体结构
1 ftype
size = 0x 00 00 00 18 ftype = 66 74 79 70 data 为蓝色部分
2 moov
Movie atom定义了一部电影的数据信息。它的类型是'moov',是一个容器atom,至少必须包含三种atom中的一种—movie header atom('mvhd'),compressed movie atom('cmov')和referencemovie atom ('rmra')。没有压缩的movie header atom必须至少包含movie header atom 和referencemovie atom中的一种。也可以包含其他的atom,例如一个clippingatom ('clip'),一个或几个trackatoms ('trak'),一个colortable atom ('ctab'),和一个userdata atom ('udta')。其中movieheader atom定义了整部电影的time scale,duration信息以及displaycharacteristics。track atom定义了电影中一个track的信息。Track就是电影中可以独立操作的媒体单位,例如一个声道就是一个track。
2.1 mvhd
电影的长度 = duration / time scale
2.2 track
一个Track atom定义了movie中的一个track。一部movie可以包含一个或多个tracks,它们之间相互独立,各自有各自的时间和空间信息。每个track atom 都有与之关联的media atom。
Track主要用于以下目的:
· 包含媒体数据引用和描述(media tracks)
· 包含modifier tracks (tweens等)
· 对于流媒体协议的打包信息(hint tracks)。Hint tracks可以引用或者复制对应的媒体sample data。
Hinttracks和modifiertracks必须保证完整性,同时和至少一个media track一起存在。换句话说,即使hint tracks复制了对应的媒体sample data,media tracks也不能从一部hinted movie中删除。
Track atoms 的atom类型是'trak'. Track atom要求必须有一个track header atom ('tkhd')和一个media atom ('mdia')。其他的track clipping atom ('clip'),track matte atom ('matt'),edit atom ('edts'),track reference atom ('tref'),track load settings atom ('load'),a track input map atom ('imap')以及user data atom ('udta')都是可选的。
2.2.1 tkhd
每个trak都包含了一个track header atom. Thetrack header atom 定义了一个track的特性,例如时间,空间和音量信息,它的类型是('tkhd').
( video) 左边为video 解析出来的字段值
可以获取图像的宽、 高等信息
(audio) 右边为audio解析出来的字段值
2.2. 2 mdia
Mediaatoms定义了track的媒体类型和sample数据,例如音频或视频,描述sample数据的media handler component,media timescale and track duration以及media-and-track-specific 信息,例如音量和图形模式。它也可以包含一个引用,指明媒体数据存储在另一个文件中。也可以包含一个sample table atoms,指明sample description, duration, andbyte offset from the data reference for each media sample.
Mediaatom 的类型是'mdia'。它是一个容器atom,必须包含一个mediaheader atom ('mdhd'),一个handlerreference ('hdlr'),一个媒体信息引用('minf')和用户数据atom('udta').
1 mdhd (Media head atom)
Mediaheader atom 定义了媒体的特性,例如time scale和duration。它的类型是'mdhd'.
video 的播放时长 = duration / time scale audio 的播放时长也可计算。 video audio 可以不一样
2 hdrl
Handlerreference atom 定义了描述此媒体数据的mediahandler component,类型是'hdlr'。在过去,handler reference atom也可以用来数据引用,但是现在,已经不允许这样使用了。一个media atom内的handler atom解释了媒体流的播放过程。例如,一个视频handler处理一个video track.
可知 音视频 采用的压缩方法
3、 MINF
Mediainformation atoms的类型是'minf',存储了解释该track的媒体数据的handler-specific的信息。media handler用这些信息将媒体时间映射到媒体数据,并进行处理。它是一个容器atom,包含其他的子atom。
这些信息是与媒体定义的数据类型特别对应的,而且media information atoms 的格式和内容也是与解释此媒体数据流的media handler 密切相关的。其他的media handler不知道如何解释这些信息。
a vmhd smhd
Video media information atoms是视频媒体的第一层atoms,包含其他的定义视频媒体数据的特性。
Sound media information atoms是音频媒体的第一层atoms,包含其他的定义音频媒体数据的特性。
video 和 audio 分别为:
字段 | 长度(字节) | 描述 |
尺寸 | 4 | 这个atom的字节数 |
类型 | 4 | vmhd |
版本 | 1 | 这个atom的版本 |
标志 | 3 | 这里总是0x000001 |
图形模式 | 2 | The transfer mode. The transfer mode specifies which Boolean operation QuickDrawshould performwhen drawing or transferring an image fromone location to another. |
Opcolor | 6 | Three 16-bit values that specify the red, green, and blue colors for the transfer mode operation indicated in the graphics mode field. |
字段 | 长度(字节) | 描述 |
尺寸 | 4 | 这个atom的字节数 |
类型 | 4 | smhd |
版本 | 1 | 这个atom的版本 |
标志 | 3 | 这里为0 |
均衡 | 2 | 音频的均衡是用来控制计算机的两个扬声器的声音混合效果,一般是0。一般值是0。 |
保留 | 2 | 保留字段,缺省为0 |
b dinf
handler reference定义data handler component如何获取媒体数据,data handler用这些数据信息来解释媒体数据。Data information atoms的类型是'dinf'。它是一个容器atom,包含其他的子atom。
C stbal sample table atom
存储媒体数据的单位是samples。一个sample是一系列按时间顺序排列的数据的一个element。Samples存储在media中的chunk内,可以有不同的durations。Chunk存储一个或者多个samples,是数据存取的基本单位,可以有不同的长度,一个chunk内的每个sample也可以有不同的长度。例如如下图,chunk 2和3不同的长度,chunk 2内的sample5和6的长度一样,但是sample 4和5,6的长度不同。
i stsd
sample description atom的类型是'stsd',包含了一个sample description表。根据不同的编码方案和存储数据的文件数目,每个media可以有一个到多个sample description。sample-to-chunk atom通过这个索引表,找到合适medai中每个sample的description。
字段 | 长度(字节) | 描述 |
尺寸 | 4 | 这个atom的字节数 |
类型 | 4 | stsd |
版本 | 1 | 这个atom的版本 |
标志 | 3 | 这里为0 |
条目数目 | 4 | sample descriptions的数目 |
Sample description |
| 不同的媒体类型有不同的sample description,但是每个sample description的前四个字段是相同的,包含以下的数据成员 |
尺寸 | 4 | 这个sample description的字节数 |
数据格式 | 4 | 存储数据的格式。 |
保留 | 6 |
|
数据引用索引 | 2 | 利用这个索引可以检索与当前sample description关联的数据。数据引用存储在data reference atoms。 |
可以看出这个sample只有一个description,对应得的数据格式是'mp4a',14496-12定义了这种结构,mp4解码器会识别此description。
ii stts Time-to-sample atoms
Time-to-sampleatoms存储了media sample的duration 信息,提供了时间对具体data sample的映射方法,通过这个atom,你可以找到任何时间的sample,类型是'stts'。
这个atom可以包含一个压缩的表来映射时间和sample序号,用其他的表来提供每个sample的长度和指针。表中每个条目提供了在同一个时间偏移量里面连续的sample序号, 以及samples的偏移量。递增这些偏移量,就可以建立一个完整的time-to-sample表.
通过这个表,可以得知,任意时间所对应的第几个sample。 由 mdhd 知 timescale = 1000。 如计算0.2s所对应的sample为第几个时。对应的duration = timescale * 0.2 s = 200 entry 4 所对应的sample 第 5 个sample
iii stsc sample to chunk atoms
当添加samples到media时,用chunks组织这些sample,这样可以方便优化数据获取。一个trunk包含一个或多个sample,chunk的长度可以不同,chunk内的sample的长度也可以不同。sample-to-chunkatom存储sample与chunk的映射关系。
Sample-to-chunkatoms的类型是'stsc'。它也有一个表来映射sample和trunk之间的关系,查看这张表,就可以找到包含指定sample的trunk,从而找到这个sample。
第 500个sample 500 = 28*13 + 12 + 13*9 + 7 所以相当于在chunk = 39 的 第7个sample中,这样 我们可以根据 stco 这个表找到 在chunk = 39位置所对应的偏移地址。 再根据 stsz 中找到第 494 至 496 中每个sample所占的大小。这样我们就可以求得 第500个sample的偏移地址,这样可以 seek 快进 快退。
如果要快进到任意时间,先根据 stts 表获取是第几个sample。在根据上面步骤就可快进。
iv stsz sample size atoms
sample size atoms定义了每个sample的大小,它的类型是'stsz',包含了媒体中全部sample的数目和一张给出每个sample大小的表。这样,媒体数据自身就可以没有边框的限制。
字段 | 长度(字节) | 描述 |
尺寸 | 4 | 这个atom的字节数 |
类型 | 4 | stsz |
版本 | 1 | 这个atom的版本 |
标志 | 3 | 这里为0 |
Sample size | 4 | 全部sample的数目。如果所有的sample有相同的长度,这个字段就是这个值。否则,这个字段的值就是0。那些长度存在sample size表中 |
条目数目 | 4 | sample size的数目 |
sample size |
| sample size表的结构。这个表根据sample number索引,第一项就是第一个sample,第二项就是第二个sample |
大小 | 4 | 每个sample的大小 |
可以看到这个vedio track的sample的长度都不一样。
v stco (Chunk offset atoms)
Chunk offset atoms 定义了每个trunk在媒体流中的位置,它的类型是'stco'。位置有两种可能,32位的和64位的,后者对非常大的电影很有用。在一个表中只会有一种可能,这个位置是在整个文件中的,而不是在任何atom中的,这样做就可以直接在文件中找到媒体数据,而不用解释atom。需要注意的是一旦前面的atom有了任何改变,这张表都要重新建立,因为位置信息已经改变了。
字段 | 长度(字节) | 描述 |
尺寸 | 4 | 这个atom的字节数 |
类型 | 4 | stco |
版本 | 1 | 这个atom的版本 |
标志 | 3 | 这里为0 |
条目数目 | 4 | chunk offset的数目 |
chunk offset |
| 字节偏移量从文件开始到当前chunk。这个表根据chunk number索引,第一项就是第一个trunk,第二项就是第二个trunk |
大小 | 4 | 每个sample的大小 |
计算:
1 计算电影时长
方法1
从mvhd - movie header atom中找到time scale和duration,duration除以time scale即是整部电影的长度。
time scale相当于定义了标准的1秒在这部电影里面的刻度是多少。
例如audio track的time scale = 8000, duration = 560128,所以总长度是70.016,video track的timescale = 600, duration = 42000,所以总长度是70
方法2
首先计算出共有多少个帧,也就是sample(从sample size atoms中得到),然后
整部电影的duration = 每个帧的duration之和(从Time-to-sample atoms中得出)
例如audio track共有547个sample,每个sample的长度是1024,则总duration是560128,电影长度是70.016;video track共有1050个sample,每个sample的长度是40,则总duration是42000,电影长度是70
2 计算图像的宽 高
从tkhd – track header atom中找到宽度和高度即是。
3 电影声音采样率
从tkhd – track header atom中找出audio track的timescale即是声音的采样频率。
4 计算视频帧率
首先计算出整部电影的duration,和帧的数目然后
帧率 = 整部电影的duration / 帧的数目
5 计算电影的比特率
整部电影的尺寸除以长度,即是比特率,此电影的比特率为846623/70 = 12094 bps
6 查找sample
当播放一部电影或者一个track的时候,对应的media handler必须能够正确的解析数据流,对一定的时间获取对应的媒体数据。如果是视频媒体,mediahandler可能会解析多个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-sampleatom,得出每个sample的duration是40,从而得出需要寻找第600/40 = 15 + 1 = 16个sample
3. 检查sample-to-chunkatom,得到该sample属于第5个chunk的第一个sample,该chunk共有4个sample
4. 检查chunkoffset atom找到第5个trunk的偏移量是20472
5. 由于第16个sample是第5个trunk的第一个sample,所以不用检查sample size atom,trunk的偏移量即是该sample的偏移量20472。如果是这个trunk的第二个sample,则从sample size atom中找到该trunk的前一个sample的大小,然后加上偏移量即可得到实际位置。
6. 得到位置后,即可取出相应数据进行解码,播放
7 查找关键帧
查找过程与查找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的大小
更多推荐
所有评论(0)