zoukankan      html  css  js  c++  java
  • 多媒体文件格式之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 name Type Size(bits)
    box size uint32 32
    box type uint32 32
    largesize uint64 0/64
    usertype uint8[16] 0/128

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

    Field name Type Size(bits)
    boxHeader - -
    version uint8 8
    flag uint24 24

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

    MP4顶部视图

    MP4文件的整体结构如下:

    表1 MP4 file structure
    ftyp
    pdin
    moov
    -
    -
    -
    -
    moof
    -
    -
    -
    mfra
    -
    -
    mdat
    free
    skip
    -
    meta
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    meco
    -
    styp
    sidx
    ssix
    prft

    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 name Type Size(bits)
    FullBoxHeader - -
    creation time uint32/uint64 32/64
    modify time uint32/uint64 32/64
    timescale uint32 32
    duration uint32/uint64 32/64
    rate uint32 32
    volume uint16 16
    reserved uint8 80
    matrix uint32[9] 9*32
    pre_defined uint32[6] 6*32
    next_track_ID uint32 32

    对于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
    tref
    trgr
    edts
    ---
    meta
    mdia
    ---
    ---
    ---
    ---
    ---

    .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
    smhd
    hmhd
    sthd
    nmhd
    dinf
    ---
    stbl
    ---
    ---
    ---
    ---
    ---
    ---
    ---
    ---
    ---
    ---
    ---
    ---
    ---
    ---
    ---
    ---
    ---
    ---
    ---

    '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 name type Size(bits)
    FullBox Header --- ---
    sample_size uint32 32
    sample_count uint32 32
    entry_size uint32[] 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 name type Size(bits)
    FullBox Header --- ---
    entry_cout uint32 32
    chunk_entry uint32[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
  • 相关阅读:
    PS后期合成,你和大神的差距就这5步!
    欧几里得算法:从证明等式gcd(m, n) = gcd(n, m mod n)对每一对正整数m, n都成立说开去
    谜题:过桥问题
    《世界是数字的》读书笔记第一部分_硬件篇
    完全偶图K(3,3)与完全图K5是否存在平面表示
    Dijkstar算法的数学原理
    LeetCode 141. Linked List Cycle
    LeetCode 155. Min Stack
    LeetCode 160. Intersection of Two Linked Lists
    LeetCode 165.Compare Version Numbers
  • 原文地址:https://www.cnblogs.com/tocy/p/media_container_3_mp4.html
Copyright © 2011-2022 走看看