多媒体文件格式之MP4

[时间:2016-06] [状态:Open]

学习多媒体容器格式的目的

主要是为了回答以下问题:

  1. 该容器中数据是如何组织的?
  2. 该容器包含哪些编码格式的数据?这些数据是如何存储的?
  3. 该容器包含哪些元数据信息?包含哪些节目信息?
  4. 对于支持多节目的容器格式,如何找到对应的音频流、视频流、字幕流?
  5. 如何确定该容器的节目播放时长?
  6. 如何从该容器中提取音频、视频、字幕数据,并交给解码器解码,有时间戳否?
  7. 该容器是否支持seek?有哪些辅助信息?
  8. 是否支持直接流化?
  9. 哪里可以找到该容器格式最标准的文档资料?
  10. 有哪些可用的工具,方便分析容器格式异常或者错误?

1. MP4文件内部结构

MP4文件是有多个box嵌套构成的,所有数据都必须保存在box中,而且必须包含一个File Type box。

box的定义

其基本存储结构box(或者atom),其定义如下:

==========
BoxHeader
----------
BoxData
==========

其中BoxHeader定义如下:

Field nameTypeSize(bits)
box sizeuint3232
box typeuint3232
largesizeuint640/64
usertypeuint8[16]0/128

其中box size为1时,表示largesize域存在,size为0时,表示该box持续到文件结尾;box长度是64位无符号整数。当box type是"uuid"时,usertype域存在,表示自定义的box。
在解析时,可以忽略所有无法识别的box。
还有一种FullBox,作为Box的扩展,仅在header中添加了以下两个字段:

Field nameTypeSize(bits)
boxHeader--
versionuint88
flaguint2424

在解析时可以忽略所有无法识别的version。

MP4顶部视图

MP4文件的整体结构如下:

表1 MP4 file structure
ftyp-file type and compatbility
pdin-progressive download info
moov-container for all the metadata
-mvhdmovie header, overall declarations
-metametadata
-trakcontainer for an individual track or stream
-mvexmovie extends box
moof-movie fragement
-mfhdmovie fragement header
-metametadata
-traftrack fragement
mfra-movie fragement random access
-tfratrack fragment random access
-mfromovie fragment random access offset
mdat-movie data container
free-free space
skip-free space
-udtauser-data
meta-metadata
-hdlrhandler, declares the metadata(handler) type
-dinfdata infomation box, container
-ilocitem location
-iproitem protection
-iinfitem inforamtion
-xmlXML container
-bxmlbinary XML container
-pitmprimary item reference
-fiinfile delivery item information
-idatitem data
-irefitem reference
meco-additional metadata container
-meremetabox relation
styp-segment type
sidx-segment index
ssix-subsegment index
prft-producer reference time

Box是可以相互嵌套的。上面表格中加黑的box类型是比较常见的,需要重点关注下。这个表中也仅给出了box的第二层嵌套关系。更详细的建议参考标准文档的6.2节。
从表1中可以看出movie数据是存储在mdat box中,但是如何解析这个box需要参考moov box。
接下来的部分也主要是与moov box解析有关。

2. Movie Structure('moov' box)

Movie Box在mp4文件中有且仅有一个。

Movie Header Box

Movie Header Box包含在Movie Structure Box中,通常包含媒体无关的信息,比如说播放时长、创建时间等。它是FullBox("mvhd")
其结构定义如下:

Field nameTypeSize(bits)
FullBoxHeader--
creation timeuint32/uint6432/64
modify timeuint32/uint6432/64
timescaleuint3232
durationuint32/uint6432/64
rateuint3232
volumeuint1616
reserveduint880
matrixuint32[9]9*32
pre_defineduint32[6]6*32
next_track_IDuint3232

对于version为1时,上面表格中选择数据类型为uint64,对于version为0时,选择类型为uint32。
这里解释下,timescale表示单位时间内的精度,即1秒内经过的时间单位计数;举个例子,正常的时间系统里以毫秒为单位,timescale就是1000。
duration中记录的是最长的track的播放长度。rate是16.16的格式,表示优先选择的播放速度,比如ox00010000表示1.0的播放速度。volume是浮点数的8.8的格式,表示优先选择的播放音量,0x0100表示1.0的音量大小。next_track_ID主要用于添加新的track,通常会大约当前文件最大track-ID。

Track Structure('trak' box)

一个mp4文件至少包含一个media trak box,不同的Track box是相互独立的。每个track box都携带独立的时域空域信息,同时包含相关的media box。track box有两种:media track和hint track,前者用于保存media相关信息,后者包含用于流媒体的打包信息。
track box包含的sub-box如下:

'trak' box
tkhd---track header, overall info about the track
tref---track reference container
trgr---track grouping indication
edts---edit list container
---elstan edit list
meta---metadata
mdia---container for the media info in a track
---mdhdmedia header,overall info about the media
---hdlrhandler,说明媒体类型
---elngextended language tag
---minfmedia info container
---udatuser-data
.1 track header box('tkhd')

这里边有一个字段,track_ID,用于唯一的表示当前track。
另一个字段,duration,用于记录当前track的播放长度。

.2 track media box('mdia')

track media box包含用于声明当前track信息的所有对象。以下sub-box需要关注:

  • handler box('hdlr')
    可获取track类型信息,主要是有字段handler_type(uint32_t)区分,具体含义如下:
    • 'vide' Video track
    • 'soun' Audio track
    • 'hint' Hint track
.3 media infomation box ('minf')

先看看media infomation box的构成,如下表:

minf
vmhd---video media header(video track only)
smhd---audio media header(audio track only)
hmhd---hint media header(hint track only)
sthd---subtitle media header(subtitle track only)
nmhd---null media header(some tracks only)
dinf---data info box, container
---drefdata reference box, declare source of media data
stbl---sample table box, container for time/space map
---stsdsample descriptions(codec types, initialization etc.)
---sttsdecoding time-to-sample
---cttscomposition time-to-sample
---cslgcomposition to decode timeline mapping
---stscsample-to-chunk, partial data-offset info
---stszsample sizes(framing)
---stz2compact sample sizes(framing)
---stcochunk offset, partial data-offset info
---co6464-bit chunk offset
---stsssync sample table
---stshshadow sync sample table
---padbsample padding bits
---stdpsample degradation priority
---sdtpindependent and disposable samples
---sbgpsample-to-group
---sgpdsample group description
---subssub-sample information
---saizsample auxiliary information sizes
---saiosample auxiliary information offsets

'minf' box中的header box是根据'hdlr' box中媒体类型一致的,只能出现一个。

.4 Sample Tables('stbl')

可以说stbl box是mp4中最复杂,包含媒体信息最多的box。主要包含时间和media samples的数据映射表,使用这部分数据可以按照时间检索sample的位置、类型、大小、实际偏移位置。

  • sample description box ('stsd')
    主要描述当前track有关的编码信息,以及用于初始化解码的附加信息。
  • Time to Sample box('stts' 'ctts')
    比较常见的'stts' box,decoding time to sample,通过这个box可以实现时间到sample number的映射。
  • sync sample box('stss')
    这个box提供了可以用于同步的sample索引号,并严格按照sample number递增顺序排列。如果不存在这个box,表示所有sample都是可以用于同步。对视频而言,sync sample通常指的关键帧。
  • sample size box('stsz' 'stz2')
    这个box记录每个sample的大小。'stsz' box存储格式如下:
Filed nametypeSize(bits)
FullBox Header------
sample_sizeuint3232
sample_countuint3232
entry_sizeuint32[]varies

sample_size中表示sample长度,如果是0表示每个sample长度不定,会记录在entry_size中;否则每个sample长度一样,并且entry_size域不存在。
'stz2' box中的entry_size是compact的,长度由特定字段指定。

  • sample to chunk box('stsc')
    'stsc' box中记录了每个chunk中包含多少sample,其结构定义如下:
Filed nametypeSize(bits)
FullBox Header------
entry_coutuint3232
chunk_entryuint32[3]varies

chunk_entry包含三个字段:
first_chunk: uint32
samples_per_chunk: uint32
sample_description_index: uint32

每个entry表示从first_chunk开始的每个chunk都包含samples_per_chunk个samples,这些sample都可以用使用sample_description_index信息解码。

通过这个box,可以构建出当前track的chunk结构,及其包含的sample。

  • chunk offset box('stco' 'co64')
    这个box记录了chunk对应的offset,只是包含字段一个是32为('stco'),一个是64位('co64')。
    chunk offset box中记录都是相对文件的偏移量,可以直接通过这些信息读取。

Track Structure小结

由于'mdat' box中的多媒体数据是没有结构的,只能参考moov的trak box解析。反过头来。我们看一下针对单个track中的media信息存储应该是下面的结构:
|chunk #0| chunk#1| ... | chunk #n|
每个chunk的构成是下面的结构:
|sample #0|sample #1| ... | sample #n|
从trak box中的minf中可以看出,每个chunk的长度不定,其所包含的sample数目不同,每个sample的长度也不完全相同。

3. mp4中的节目信息有哪些? 如何获取?

每个'trak' box表示一个media,其类型记录在stsd中,对于视频,其中包括我们最关心的宽高信息、编码器,保存在VisualSampleEntry;对于音频,其中也包括采样率、声道数、编码方式等,这些信息保存在AudioSampleEntry或AudioSampleEntryV1中。

对于单节目的mp4文件,不需要选择流。从标准上来看'tkhd'中有一个字段alternate_group,估计这个是表示选择节目的一个标志。

4. 如何实现seek?

第2部分介绍moov的结构时,里面有很多信息是跟seek相关的,比如time-sample映射。那么为了实现seek到指定时间,在mp4中需要做如下工作:

  1. 使用timescale将目标时间标准化。
  2. 通过time-to-sample box找到指定track的给定时间之前的第一个sample number。
  3. 通过sync sample table查询sample number之前的第一个sync sample。
  4. 通过sample-to-chunk table查找到对应的chunk number。
  5. 通过chunk offset box查找到对应chunk在文件中的起始偏移量。
  6. 最后使用sample-to-chunk box和sample size box的信息计算出该chunk中需要读取的sample数据,即完成seek。

当然标准中还有关于edit list box的使用,这里多数情况下不涉及,所以不做额外介绍。

5. 其他问题

这里解释下上面没有涉及的问题。

该容器包含哪些元数据信息?包含哪些节目信息?

MP4中包含'meta' box,从中可以解析出需要的metadata,具体建议参考标准。

是否支持直接流化?

mp4支持流化,直接通过特定协议及hint track完成。后续会有介绍。

哪里可以找到该容器格式最标准的文档资料?

标准文档的全称是"ISO/IEC 14496-12:ISO base media file format"(c068960_ISO_IEC_14496-12_2015)。
我是从ISO.org的以下地址下载:http://www.iso.org/iso/home/store/catalogue_ics/catalogue_detail_ics.htm?csnumber=61988

有哪些可用的工具,方便分析容器格式异常或者错误?

比较经典的工具是mp4info或者elecard streameye,但是如果对mp4熟悉了的话,直接二进制查看还是不错的。

总结

本文主要是关于mp4文件解析的介绍,是我第一次深入的了解mp4文件格式,虽然可用的测试文件不是很多,但是足够理解文件结构了。
本文内容主要作为我个人后续分析mp4文件的参考。

参考资料

  1. "ISO/IEC 14496-12:ISO base media file format"(c068960_ISO_IEC_14496-12_2015)。
  2. MP4文件格式解析
  3. http://blog.chinaunix.net/uid-20758197-id-5056943.html

转载于:https://www.cnblogs.com/tocy/p/media_container_3_mp4.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值