一、规范介绍
ISO/IEC 14496是MPEG专家组指定的MPEG-4标准。该标准分为21个部分:
- Part 1: Systems
- Part 2: Visual
- Part 3: Audio
- Part 4: Conformance testing
- Part 5: Reference software
- Part 6: Delivery Multimedia Integration Framework (DMIF)
- Part 7: Optimized reference software for coding of audio-visual objects
- Part 8: Carriage of ISO/IEC 14496 contents over IP networks
- Part 9: Reference hardware description
- Part 10: Advanced Video Coding
- Part 11: Scene description and application engine
- Part 12: ISO base media file format
- Part 13: Intellectual Property Management and Protection (IPMP) extensions
- Part 14: MP4 file format
- Part 15: Carriage of NAL unit structured video in the ISO Base Media File Format
- Part 16: Animation Framework eXtension (AFX)
- Part 17: Streaming text format
- Part 18: Font compression and streaming
- Part 19: Synthesized texture stream
- Part 20: Lightweight Application Scene Representation (LASeR) and Simple Aggregation Format (SAF)
- Part 21: MPEG-J Graphics Framework eXtensions (GFX)
- Part 22: Open Font Format
- Part 23: Symbolic Music Representation
- Part 24: Audio and systems interaction
- Part 25: 3D Graphics Compression Model
- Part 26: Audio conformance
- Part 27: 3D Graphics conformance
- Part 28: Composite font representation
- Part 29: Web video coding
- Part 30: Timed text and other visual overlays in ISO base media file format
- Part 31: Video Coding for Browsers
MP4封装格式对应的标准为ISO/IEC 14496-12,即信息技术对象编码的第12部分:ISO基本媒体文件格式(Information technology Coding of audio-visual objects Part 12:ISO Base media file format)。
二、文件结构
MP4文件由于各个不同类型的Box组成,Box可以包含Box,其组成大致如下:
所有类型的Box如下表所示,其中标*号的是MP4文件中必须要带有的Box。
Box types, structure, and cross-reference (Informative) |
||||||||
ftyp |
* |
4.3 |
file type and compatibility |
|||||
pdin |
8.1.3 |
progressive download information |
||||||
moov |
* |
8.2.1 |
container for all the metadata |
|||||
mvhd |
* |
8.2.2 |
movie header, overall declarations |
|||||
meta |
8.11.1 |
metadata |
||||||
trak |
* |
8.3.1 |
container for an individual track or stream |
|||||
tkhd |
* |
8.3.2 |
track header, overall information about the track |
|||||
tref |
8.3.3 |
track reference container |
||||||
trgr |
8.3.4 |
track grouping indication |
||||||
edts |
8.6.4 |
edit list container |
||||||
elst |
8.6.6 |
an edit list |
||||||
meta |
8.11.1 |
metadata |
||||||
mdia |
* |
8.4 |
container for the media information in a track |
|||||
mdhd |
* |
8.4.2 |
media header, overall information about the media |
|||||
hdlr |
* |
8.4.3 |
handler, declares the media (handler) type |
|||||
elng |
8.4.6 |
extended language tag |
||||||
minf |
* |
8.4.4 |
media information container |
|||||
vmhd |
12.1.2 |
video media header, overall information (video track only) |
||||||
smhd |
12.2.2 |
sound media header, overall information (sound track only) |
||||||
hmhd |
12.4.2 |
hint media header, overall information (hint track only) |
||||||
sthd |
12.6.2 |
subtitle media header, overall information (subtitle track only) |
||||||
nmhd |
8.4.5.2 |
Null media header, overall information (some tracks only) |
||||||
dinf |
* |
8.7.1 |
data information box, container |
|||||
dref |
* |
8.7.2 |
data reference box, declares source(s) of media data in track |
|||||
stbl |
* |
8.5.1 |
sample table box, container for the time/space map |
|||||
stsd |
* |
8.5.2 |
sample descriptions (codec types, initialization etc.) |
|||||
stts |
* |
8.6.1.2 |
(decoding) time-to-sample |
|||||
ctts |
8.6.1.3 |
(composition) time to sample |
||||||
cslg |
8.6.1.4 |
composition to decode timeline mapping |
||||||
stsc |
* |
8.7.4 |
sample-to-chunk, partial data-offset information |
|||||
stsz |
8.7.3.2 |
sample sizes (framing) |
||||||
stz2 |
8.7.3.3 |
compact sample sizes (framing) |
||||||
stco |
* |
8.7.5 |
chunk offset, partial data-offset information |
|||||
co64 |
8.7.5 |
64-bit chunk offset |
||||||
stss |
8.6.2 |
sync sample table |
||||||
stsh |
8.6.3 |
shadow sync sample table |
||||||
padb |
8.7.6 |
sample padding bits |
||||||
stdp |
8.7.6 |
sample degradation priority |
||||||
sdtp |
8.6.4 |
independent and disposable samples |
||||||
sbgp |
8.9.2 |
sample-to-group |
||||||
sgpd |
8.9.3 |
sample group description |
||||||
subs |
8.7.7 |
sub-sample information |
||||||
saiz |
8.7.8 |
sample auxiliary information sizes |
||||||
saio |
8.7.9 |
sample auxiliary information offsets |
||||||
udta |
8.10.1 |
user-data |
||||||
mvex |
8.8.1 |
movie extends box |
||||||
mehd |
8.8.2 |
movie extends header box |
||||||
trex |
* |
8.8.3 |
track extends defaults |
|||||
leva |
8.8.13 |
level assignment |
||||||
moof |
8.8.4 |
movie fragment |
||||||
mfhd |
* |
8.8.5 |
movie fragment header |
|||||
meta |
8.11.1 |
metadata |
||||||
traf |
8.8.6 |
track fragment |
||||||
tfhd |
* |
8.8.7 |
track fragment header |
|||||
trun |
8.8.8 |
track fragment run |
||||||
sbgp |
8.9.2 |
sample-to-group |
||||||
sgpd |
8.9.3 |
sample group description |
||||||
subs |
8.7.7 |
sub-sample information |
||||||
saiz |
8.7.8 |
sample auxiliary information sizes |
||||||
saio |
8.7.9 |
sample auxiliary information offsets |
||||||
tfdt |
8.8.12 |
track fragment decode time |
||||||
meta |
8.11.1 |
metadata |
||||||
mfra |
8.8.9 |
movie fragment random access |
||||||
tfra |
8.8.10 |
track fragment random access |
||||||
mfro |
* |
8.8.11 |
movie fragment random access offset |
|||||
mdat |
8.2.2 |
media data container |
||||||
free |
8.1.2 |
free space |
||||||
skip |
8.1.2 |
free space |
||||||
udta |
8.10.1 |
user-data |
||||||
cprt |
8.10.2 |
copyright etc. |
||||||
tsel |
8.10.3 |
track selection box |
||||||
strk |
8.14.3 |
sub track box |
||||||
stri |
8.14.4 |
sub track information box |
||||||
strd |
8.14.5 |
sub track definition box |
||||||
meta |
8.11.1 |
metadata |
||||||
hdlr |
* |
8.4.3 |
handler, declares the metadata (handler) type |
|||||
dinf |
8.7.1 |
data information box, container |
||||||
dref |
8.7.2 |
data reference box, declares source(s) of metadata items |
||||||
iloc |
8.11.3 |
item location |
||||||
ipro |
8.11.5 |
item protection |
||||||
sinf |
8.12.1 |
protection scheme information box |
||||||
frma |
8.12.2 |
original format box |
||||||
schm |
8.12.5 |
scheme type box |
||||||
schi |
8.12.6 |
scheme information box |
||||||
iinf |
8.11.6 |
item information |
||||||
xml |
8.11.2 |
XML container |
||||||
bxml |
8.11.2 |
binary XML container |
||||||
pitm |
8.11.4 |
primary item reference |
||||||
fiin |
8.13.2 |
file delivery item information |
||||||
paen |
8.13.2 |
partition entry |
||||||
fire |
8.13.7 |
file reservoir |
||||||
fpar |
8.13.3 |
file partition |
||||||
fecr |
8.13.4 |
FEC reservoir |
||||||
segr |
8.13.5 |
file delivery session group |
||||||
gitn |
8.13.6 |
group id to name |
||||||
idat |
8.11.11 |
item data |
||||||
iref |
8.11.12 |
item reference |
||||||
meco |
8.11.7 |
additional metadata container |
||||||
mere |
8.11.8 |
metabox relation |
||||||
meta |
8.11.1 |
metadata |
||||||
styp |
8.16.2 |
segment type |
||||||
sidx |
8.16.3 |
segment index |
||||||
ssix |
8.16.4 |
subsegment index |
||||||
prft |
8.16.5 |
producer reference time |
其中,下面三个是必须必带的顶层Box:
ftyp: File Type Box,描述文件遵从的MP4规范;
moov:Movie Box,媒体的元数据信息,有且只有一个;
mdat:Media Data Box,存放实际的媒体数据(音频、视频);
对MP4文件必须携带的Box通过思维导图梳理下:
三、关键BOX解析
Box分为两种:Box和Full Box,区别为Box Header不一样,Full Box由Box派生得到,在尾部多了4字节的version(1字节)+flags(3字节);
Box=Box header+Box body,结构入下图所示:
Box Header
字段定义如下:
l type:box类型,包括 “预定义类型”、“自定义扩展类型”,占4个字节(对应类型的ASCII码);
l 预定义类型:比如ftyp、moov、mdat等预定义好的类型;
l 自定义扩展类型:如果type==uuid,则表示是自定义扩展类型。size(或largesize)随后的16字节,为自定义类型的值(extended_type)
l size:包含box header在内的整个box的大小,单位是字节。当size为0或1时,需要特殊处理:
l size等于0:box的大小由后续的largesize确定(一般只有装载媒体数据的mdat box会用到largesize);
l size等于1:当前box为文件的最后一个box,通常包含在mdat box中;
l largesize:当size为0时才存在,表示box的大小,占8个字节;(一般不使用)
l extended_type:自定义扩展类型,占16个字节;(type==uuid才存在)
Box Body
box数据体,不同box包含的内容不同,需要参考具体box的定义。有的 box body 很简单,比如 ftyp。有的 box 比较复杂,可能嵌套了其他box,比如moov。
3.2 关键Box介绍
3.2.1 ftyp (File Type Box)
isom(ISO Base Media file)是在 MPEG-4 Part 12 中定义的一种基础文件格式,MP4、3gp、QT 等常见的封装格式,都是基于这种基础文件格式衍生的。
MP4 文件可能遵循的规范有mp41、mp42,而mp41、mp42又是基于isom衍生出来的。
3gp(3GPP):一种容器格式,主要用于3G手机上;
QT:QuickTime的缩写,.qt 文件代表苹果QuickTime媒体文件;
ftyp定义如下:
l major_brand:比如常见的 isom、mp41、mp42、avc1、qt等。它表示“最好”基于哪种格式来解析当前的文件。举例,major_brand 是 A,compatible_brands 是 A1,当解码器同时支持 A、A1 规范时,最好使用A规范来解码当前媒体文件,如果不支持A规范,但支持A1规范,那么,可以使用A1规范来解码;
l minor_version:提供 major_brand 的说明信息,比如版本号,不得用来判断媒体文件是否符合某个标准/规范;
l compatible_brands:文件兼容的brand列表。比如 mp41 的兼容 brand 为 isom。通过兼容列表里的 brand 规范,可以将文件 部分(或全部)解码出来;
3.2.2 moov(Movie Box)
Movie Box,存储 mp4 的 metadata,是描述媒体信息的最主要Box,通过包含多个子Box记录信息。
moov中,最重要的两个box是 mvhd 和 trak:
l mvhd:Movie Header Box,mp4文件的整体信息,比如创建时间、文件时长等;
l trak:Track Box,一个mp4可以包含一个或多个轨道(比如视频轨道、音频轨道),轨道相关的信息就在trak里。trak是container box,至少包含两个box,tkhd、mdia;
mvhd针对整个影片,tkhd针对单个track,mdhd针对媒体,vmhd针对视频,smhd针对音频,可以认为是从 宽泛 > 具体,前者一般是从后者推导出来的。
mvhd(Movie Header Box)
MP4文件的整体信息,跟具体的视频流、音频流无关,比如创建时间、文件时长等。
字段含义如下:
l creation_time:文件创建时间;
l modification_time:文件修改时间;
l timescale:一秒包含的时间单位(整数)。举个例子,如果timescale等于1000,那么,一秒包含1000个时间单位(后面track等的时间,都要用这个来换算,比如track的duration为10,000,那么,track的实际时长为10,000/1000=10s);
l duration:影片时长(整数),根据文件中的track的信息推导出来,等于时间最长的track的duration;
l rate:推荐的播放速率,32位整数,高16位、低16位分别代表整数部分、小数部分([16.16]),举例 0x0001 0000 代表1.0,正常播放速度;
l volume:播放音量,16位整数,高8位、低8位分别代表整数部分、小数部分([8.8]),举例 0x01 00 表示 1.0,即最大音量;
l matrix:视频的转换矩阵,一般可以忽略不计;
l next_track_ID:32位整数,非0,一般可以忽略不计。当要添加一个新的track到这个影片时,可以使用的track id,必须比当前已经使用的track id要大。也就是说,添加新的track时,需要遍历所有track,确认可用的track id;
tkhd(Track Box)
单个 track 的 metadata,包含如下字段:
l version:tkhd box的版本;
l flags:按位或操作获得,默认值是7(0x000001 | 0x000002 | 0x000004),表示这个track是启用的、用于播放的 且 用于预览的。
Track_enabled:值为0x000001,表示这个track是启用的,当值为0x000000,表示这个track没有启用;
Track_in_movie:值为0x000002,表示当前track在播放时会用到;
Track_in_preview:值为0x000004,表示当前track用于预览模式;
l creation_time:当前track的创建时间;
l modification_time:当前track的最近修改时间;
l track_ID:当前track的唯一标识,不能为0,不能重复;
l duration:当前track的完整时长(需要除以timescale得到具体秒数);
l layer:视频轨道的叠加顺序,数字越小越靠近观看者,比如1比2靠上,0比1靠上;
l alternate_group:当前track的分组ID,alternate_group值相同的track在同一个分组里面。同个分组里的track,同一时间只能有一个track处于播放状态。当alternate_group为0时,表示当前track没有跟其他track处于同个分组。一个分组里面,也可以只有一个track;
l volume:audio track的音量,介于0.0~1.0之间;
l matrix:视频的变换矩阵;
l width、height:视频的宽高;
hdlr(Handler Reference Box)
声明当前track的类型,以及对应的处理器(handler)。
handler_type的取值包括:
l vide(0x76 69 64 65),video track;
l soun(0x73 6f 75 6e),audio track;
l hint(0x68 69 6e 74),hint track;
l name,为utf8字符串,对handler进行描述;
stbl(Sample Table Box)
stbl是所有Box最复杂的一个Box,包含多个Box,也是携带信息最主要的Box。MP4文件的媒体数据部分在mdat box里,而stbl则包含了这些媒体数据的索引以及时间信息,了解stbl对解码、渲染MP4文件很关键。
stbl中比较关键的box包含stsd、stco、stsc、stsz、stts、stss、ctts,概要介绍如下:
l stsd:给出视频、音频的编码、宽高、音量等信息,以及每个sample中包含多少个frame;
l stco:thunk在文件中的偏移;
l stsc:每个thunk中包含几个sample;
l stsz:每个sample的size(单位是字节);
l stts:每个sample的时长;
l stss:哪些sample是关键帧;
l ctts:帧解码到渲染的时间差值,通常用在B帧的场景;
stsd(Sample Description Box)
stsd给出sample的描述信息,这里面包含了在解码阶段需要用到的任意初始化信息,比如编码等。对于视频、音频来说,所需要的初始化信息不同,这里以视频为例。
在SampleDescriptionBox 中,handler_type 参数 为 track 的类型(soun、vide、hint),entry_count 变量代表当前box中 smaple description 的条目数。
针对不同的handler_type,SampleDescriptionBox 后续应用不同的 SampleEntry 类型,比如当类型为video track时,SampleEntry为VisualSampleEntry,字段如下图:
VisualSampleEntry包含如下字段:
l width、height:视频的宽高,单位是像素;
l horizresolution、vertresolution:水平、垂直方向的分辨率(像素/英寸),16.16定点数,默认是0x00480000(72dpi);
l frame_count:一个sample中包含多少个frame,对video track来说,默认是1;
l compressorname:仅供参考的名字,通常用于展示,占32个字节,比如 AVC Coding。第一个字节,表示这个名字实际要占用N个字节的长度。第2到第N+1个字节,存储这个名字。第N+2到32个字节为填充字节。compressorname 可以设置为0;
l depth:位图的深度信息,比如 0x0018(24),表示不带alpha通道的图片;
其中codingname代表视频编码格式,例如,当视频编码格式为H.264时,codingname=’avc1‘或’avc2‘,该Box对应的规范在ISO/IEC 14496-Part 15: Carriage of NAL unit structured video in the ISO Base Media File Format
中规定。入下图所示,为'acv1'Box字段定义,’avc1‘ Box主要信息存在内部的’avcC‘ Box中,’avcC‘ Box主要如下图二所示。
其中重要的字段如下:
l lengthSizeMinusOne:代表在mdat Box中在每帧前用(lengthSizeMinusOne+1)个字节代表帧数据长度,一般取值是3,即用4个字节前缀记录帧长度;
l numOfSequenceParameterSet~sequenceParametrSetNALUnit:保存SPS数据;
l numOfPictureParameterSets~ pictureParameterSetNALUnit:保存PPS数据
stco(Chunk Offset Box)
chunk在文件中的偏移量。针对小文件、大文件,有两种不同的box类型,分别是stco、co64,它们的结构是一样的,只是字段长度不同。
chunk_offset 指的是在文件本身中的 offset,而不是某个box内部的偏移。
在构建mp4文件的时候,需要特别注意 moov 所处的位置,它对于chunk_offset 的值是有影响的。有一些MP4文件的 moov 在文件末尾,为了优化首帧速度,需要将 moov 移到文件前面,此时,需要对 chunk_offset 进行改写。
stsc(Sample To Chunk Box)
ample 以 chunk 为单位分成多个组。chunk的size可以是不同的,chunk里面的sample的size也可以是不同的。
l entry_count:有多少个表项(每个表项,包含first_chunk、samples_per_chunk、sample_description_index信息);
l first_chunk:当前表项中,对应的第一个chunk的序号;
l samples_per_chunk:每个chunk包含的sample数;
l sample_description_index:指向 stsd 中 sample description 的索引值(参考stsd小节);
l 前面描述比较抽象,这里看个例子,这里表示的是:
l 序号1~15的chunk,每个chunk包含15个sample;
l 序号16的chunk,包含30个sample;
l 序号17以及之后的chunk,每个chunk包含28个sample;
l 以上所有chunk中的sample,对应的sample description的索引都是1;
stsz(Sample Size Boxes)
每个sample的大小(字节),根据 sample_size 字段,可以知道当前track包含了多少个sample(或帧)。
l sample_size:默认的sample大小(单位是byte),通常为0。如果sample_size不为0,那么,所有的sample都是同样的大小。如果sample_size为0,那么,sample的大小可能不一样。
l sample_count:当前track里面的sample数目。如果 sample_size==0,那么,sample_count 等于下面entry的条目;
| entry_size:单个sample的大小(如果sample_size==0的话);
stts(Decoding Time to Sample Box)
stts包含了DTS到sample number的映射表,主要用来推导每个帧的时长。
l entry_count:stts 中包含的entry条目数;
l sample_count:单个entry中,具有相同时长(duration 或 sample_delta)的连续sample的个数。
l sample_delta:sample的时长(以timescale为计量)
stss(Sync Sample Box)
mp4文件中,关键帧所在的sample序号。如果没有stss的话,所有的sample中都是关键帧(I帧)。
l entry_count:entry的条目数,可以认为是关键帧的数目;
l sample_number:关键帧对应的sample的序号;(从1开始计算)
3.2.3 mdat(Movie Box)
l data[]:保存实际的媒体数据,如果是视频数据,则data[0]~data[3]标识当前帧长度,data[4]~data[n]为当前帧数据=NALU不包含startcode数据。
四、参考
参考:ISO/IEC 14496-Part12和ISO/IEC 14496-Part15(规定AVC/HEVC BOX的语法)