admin 发表于 2018-12-27 20:36:28

MP4文件格式分析及分割实现(附源码)

MP4文件格式分析及分割实现(附源码)               MP4文件格式分析                    MP4(MPEG-4 Part 14)是一种常见的多媒体容器格式,它是在“ISO/IEC 14496-14”标准文件中定义的,属于MPEG-4的一部分,是“ISO/IEC 14496-12(MPEG-4 Part 12 ISO base media file format)”标准中所定义的媒体格式的一种实现,后者定义了一种通用的媒体文件结构标准。MP4是一种描述较为全面的容器格式,被认为可以在其中嵌入任何形式的数据,各种编码的视频、音频等都不在话下,不过我们常见的大部分的MP4文件存放的AVC(H.264)或MPEG-4(Part 2)编码的视频和AAC编码的音频。MP4格式的官方文件后缀名是“.mp4”,还有其他的以mp4为基础进行的扩展或者是缩水版本的格式,包括:M4V,3GP,F4V等。   一个mp4文件有可能包含非常多的box(全部大约70多个),在很大程度上增加了解析的复杂性。如果要全部解析必要性不是很大。大部分mp4文件没有那么多的box类型,下图就是一个简化了的,常见的mp4文件结构:http://images2015.cnblogs.com/blog/693621/201707/693621-20170719135846005-1746376481.png下图是节点box详细说明:http://images2015.cnblogs.com/blog/693621/201707/693621-20170714145046728-232725374.png下面我们将对以上主要box的解析进行详细说明:1. 一级box  一级box主要包含ftyp、moov、free、mdat等等。1.1 ftyp box结构:http://common.cnblogs.com/images/copycode.gif
/**********************************************************************************************                            File Type Box (ftyp)**--------------------------------------------------------------------------------------------**      字段名称              |    长度(bytes)   |      有关描述--------------------------------------------------------------------------------------------**      boxsize               |    4            |      box的长度**      boxtype               |    4            |      box的类型**      major_brand         |    4            |**      minor_version         |    4            |      版本号**      compatible_brands   |    4 * N      |      本文件遵从的多种协议(ismo, iso2, mp41)********************************************************************************************/http://common.cnblogs.com/images/copycode.gif

运行结果:http://images2015.cnblogs.com/blog/693621/201707/693621-20170714150537728-569984141.png1.2 moov box结构:http://common.cnblogs.com/images/copycode.gif
/**********************************************************************************************      字段名称            |    长度(bytes)   |      有关描述--------------------------------------------------------------------------------------------**      boxsize            |    4            |      box的长度**      boxtype            |    4            |      box的类型********************************************************************************************/http://common.cnblogs.com/images/copycode.gif

1.3 free box结构:http://common.cnblogs.com/images/copycode.gif
/**********************************************************************************************      字段名称            |    长度(bytes)   |      有关描述--------------------------------------------------------------------------------------------**      boxsize            |    4            |      box的长度**      boxtype            |    4            |      box的类型********************************************************************************************/http://common.cnblogs.com/images/copycode.gif

1.4 mdat box结构:http://common.cnblogs.com/images/copycode.gif
/**********************************************************************************************      字段名称             |    长度(bytes)    |      有关描述--------------------------------------------------------------------------------------------**      boxsize             |    4             |      box的长度**      boxtype             |    4             |      box的类型**                                             |      后面全是真实数据********************************************************************************************/http://common.cnblogs.com/images/copycode.gif

运行结果:http://images2015.cnblogs.com/blog/693621/201707/693621-20170714151314165-1184118153.png2. 二级box  本节所说的二级box皆为moov的子box,主要包含mvhd、trak、udat等等。2.1 mvhd box结构:http://common.cnblogs.com/images/copycode.gif
/**************************************************************************************************************                                          mvhd**--------------------------------------------------------------------------------------------**      字段名称              |    长度(bytes)   |      有关描述--------------------------------------------------------------------------------------------**      boxsize               |    4            |      box的长度**      boxtype               |    4            |      box的类型**      version               |    1            |      box版本,0或1,一般为0(以下字节数均按version = 0)**      flags               |    3            |      **      creation time         |    4            |      创建时间(相对于UTC时间1904 - 01 - 01零点的秒数)**      modification time   |    4            |      修改时间**      time scale            |    4            |      文件媒体在1秒时间内的刻度值,可以理解为1秒长度的时间单元数**      duration            |    4            |      该track的时间长度,用duration和time scale值可以计算track时长**      rate                  |    4            |      推荐播放速率,高16位和低16位分别为小数点整数部分和小数部分,即 格式.该值为1.0 (0x00010000)**      volume                |    2            |      与rate类似, 格式,1.0(0x0100)表示最大音量**      reserved            |    10         |      保留位**      matrix                |    36         |      视频变换矩阵**      pre-defined         |    24         |      **      next track id         |    4            |      下一个track使用的id号************************************************************************************************************/http://common.cnblogs.com/images/copycode.gif

运行结果:http://images2015.cnblogs.com/blog/693621/201707/693621-20170718204331411-215399662.png2.2 trak box结构:http://common.cnblogs.com/images/copycode.gif
/**********************************************************************************************      字段名称            |    长度(bytes)   |      有关描述--------------------------------------------------------------------------------------------**      boxsize            |    4            |      box的长度**      boxtype            |    4            |      box的类型********************************************************************************************/http://common.cnblogs.com/images/copycode.gif

2.3 udat box结构:http://common.cnblogs.com/images/copycode.gif
/**************************************************************************************************************         udat**--------------------------------------------------------------------------------------------**字段名称      | 长度(bytes)    |有关描述--------------------------------------------------------------------------------------------**boxsize     | 4        |box的长度**boxtype      | 4        |box的类型**                          |用户自定义数据解析************************************************************************************************************/http://common.cnblogs.com/images/copycode.gif

运行结果:http://images2015.cnblogs.com/blog/693621/201707/693621-20170718213538490-607273759.png3. 三级box  本节所说的三级box皆为trak的子box,主要包含tkhd、mdia等。3.1 tkhd box结构:http://common.cnblogs.com/images/copycode.gif
/**************************************************************************************************************                                        tkhd**-------------------------------------------------------------------------------------------------------------**      字段名称               |    长度(bytes)   |      有关描述-------------------------------------------------------------------------------------------------------------**      boxsize                |    4            |      box的长度**      boxtype                |    4            |      box的类型**      version                |    1            |      box版本,0或1,一般为0。(以下字节数均按version = 0)**      flags                  |    3            |      按位或操作结果值,预定义如下;                                                         0x000001 track_enabled,否则该track不被播放;                                                         0x000002 track_in_movie,表示该track在播放中被引用;                                                         0x000004 track_in_preview,表示该track在预览时被引用。                                                         一般该值为7,如果一个媒体所有track均未设置track_in_movie和track_in_preview,将被理解为所有track均设置了这两项;                                                         对于hint track,该值为0;**      creation_time          |    4            |      创建时间(相对于UTC时间1904 - 01 - 01零点的秒数)**      modification_time      |    4            |      修改时间**      track_id               |    4            |      id号 不能重复且不能为0**      reserved               |    4            |      保留位**      duration               |    4            |      track的时间长度**      reserved               |    8            |      保留位**      layer                  |    2            |      视频层,默认为0,值小的在上层**      alternate_group      |    2            |      track分组信息,默认为0表示该track未与其他track有群组关系**      volume               |    2            |       格式,如果为音频track,1.0(0x0100)表示最大音量;否则为0**      reserved               |    2            |      保留位**      matrix               |    36         |      视频变换矩阵**      width                  |    4            |      宽**      height               |    4            |      高,均为 格式值 与sample描述中的实际画面大小比值,用于播放时的展示宽高************************************************************************************************************/http://common.cnblogs.com/images/copycode.gif

运行结果:http://images2015.cnblogs.com/blog/693621/201707/693621-20170719142936615-1906247260.png3.2 mdia box结构:http://common.cnblogs.com/images/copycode.gif
/**********************************************************************************************      字段名称            |    长度(bytes)   |      有关描述--------------------------------------------------------------------------------------------**      boxsize            |    4            |      box的长度**      boxtype            |    4            |      box的类型********************************************************************************************/http://common.cnblogs.com/images/copycode.gif

4. 四级box  本节所说的四级box皆为mdia的子box,主要包含mdhd、hdlr、minf等。4.1 mdhd box结构:http://common.cnblogs.com/images/copycode.gif
/**************************************************************************************************************                                        tkhd**-------------------------------------------------------------------------------------------------------------**      字段名称              |      长度(bytes)   |      有关描述-------------------------------------------------------------------------------------------------------------**      boxsize               |    4              |      box的长度**      boxtype               |    4              |      box的类型**      version               |    1         |      box版本0或1 一般为0 (以下字节数均按version=0)**      flags               |    3              |      **      creation_time         |    4              |      创建时间(相对于UTC时间1904 - 01 - 01零点的秒数)**      modification_time   |    4              |      修改时间**      time_scale            |    4              |      **      duration            |    4               |      track的时间长度**      language            |    2               |      媒体语言码,最高位为0 后面15位为3个字符[见ISO 639-2/T标准中定义]**      pre-defined         |    2              |      保留位************************************************************************************************************/http://common.cnblogs.com/images/copycode.gif

结果:http://images2015.cnblogs.com/blog/693621/201707/693621-20170719144742411-1841800357.png4.2 hdlr box结构:http://common.cnblogs.com/images/copycode.gif
/**************************************************************************************************************                                        hdlr**-------------------------------------------------------------------------------------------------------------**      字段名称               |    长度(bytes)    |      有关描述-------------------------------------------------------------------------------------------------------------**      boxsize                |    4             |      box的长度**      boxtype                |    4             |      box的类型**      version                |    1             |      box版本0或1 一般为0 (以下字节数均按version=0)**      flags                  |    3             |**      pre-defined            |    4             |**      handler type         |    4             |      在media box中,该值为4个字符                                                          "vide"— video track                                                          "soun"— audio track                                                          "hint"— hint track**      reserved               |    12            |**      name                   |    不定         |      track type name,以‘\0’结尾的字符串************************************************************************************************************/http://common.cnblogs.com/images/copycode.gif

结果:http://images2015.cnblogs.com/blog/693621/201707/693621-20170719150233271-721045400.png4.3 minf box结构:http://common.cnblogs.com/images/copycode.gif
/**********************************************************************************************      字段名称            |    长度(bytes)   |      有关描述--------------------------------------------------------------------------------------------**      boxsize            |    4            |      box的长度**      boxtype            |    4            |      box的类型********************************************************************************************/http://common.cnblogs.com/images/copycode.gif

5. 五级box  本节所说的五级box皆为minf的子box,主要包含header box(vmhd/smhd/hmld/nmld)、stbl等。5.1 header box本处的headerbox会根据前面的handler type数值选择哪个box。 "vide"—vmhd 视频"soun"— smhd 音频"hint"—hmhd 忽略vmhd结构:http://common.cnblogs.com/images/copycode.gif
/**************************************************************************************************************                                        vmhd**-------------------------------------------------------------------------------------------------------------**      字段名称            |    长度(bytes)    |      有关描述-------------------------------------------------------------------------------------------------------------**      boxsize                |    4            |      box的长度**      boxtype                |    4            |      box的类型**      version                |    1            |      box版本0或1 一般为0 (以下字节数均按version=0)**      flags                |    3            |**      graphics_mode      |    4            |      视频合成模式,为0时拷贝原始图像,否则与opcolor进行合成**      opcolor                |    2 ×3      |      {red,green,blue}************************************************************************************************************/http://common.cnblogs.com/images/copycode.gif

结果:http://images2015.cnblogs.com/blog/693621/201707/693621-20170719151858755-561329904.png5.2 stbl box结构:http://common.cnblogs.com/images/copycode.gif
/**********************************************************************************************      字段名称            |    长度(bytes)   |      有关描述--------------------------------------------------------------------------------------------**      boxsize            |    4            |      box的长度**      boxtype            |    4            |      box的类型********************************************************************************************/http://common.cnblogs.com/images/copycode.gif

6. 六级box  本节所说的六级box皆为stbl的子box,主要包含stsd、stts、stsz、stsc、stss、stco等,这些也是mp4文件设计的精髓所在,主要控制chunk、sample、mdat之间的映射关系。6.1 stsd boxstsd: Sample Description Box,解析stsd可获得coding类型、视频宽高、音频samplesize、channelcount这些和解码器有关信息。http://images2015.cnblogs.com/blog/693621/201707/693621-20170720191759911-1780775432.png6.2 stts boxstts: Decoding Time to Sample Box,时间戳和Sample映射表http://images2015.cnblogs.com/blog/693621/201707/693621-20170720192010396-1449570870.png上图是一个video trak,说明该视频包含87帧数据,每帧包含512个采样。总共512*87=44544个采样,和我们前面mdhd box的Duration完全一致。Duration / TimeScale = 44544 / 12288 = 3.625秒 正是我们的视频播放长度。12288 / 512 = 24 p/s (帧率)。6.3 stsz boxstsz, stz2: Sample Size Boxes,每个Sample大小的表http://images2015.cnblogs.com/blog/693621/201707/693621-20170720195659474-1927436027.png一共87帧 每帧的字节大小。6.4 stsc boxstsc: Sample to chunk 的映射表。http://images2015.cnblogs.com/blog/693621/201707/693621-20170720201645990-191548870.png前面说了一共87帧数据,放在83个chunk中。1~82个chunk每个里面放1帧,第83个chunk放了5帧。6.5 stss boxstss: 关键帧索引表。http://images2015.cnblogs.com/blog/693621/201707/693621-20170720202131755-1503601782.png第1、13、25、37、49、61、73、85.... 这些帧都是关键帧。每12帧就有一个关键帧, 前面我们计算得知fps是24。由此可知该视频关键帧间隔为0.5秒。6.6 stco box'stco','co64': Chunk位置偏移表http://images2015.cnblogs.com/blog/693621/201707/693621-20170720202507849-399968312.png一共83个chunk,记录在mdat真实数据中的字节偏移量。
下图为第三方MP4文件解析结果:http://images2015.cnblogs.com/blog/693621/201707/693621-20170714165054915-515273568.png MP4文件格式解析源码:https://github.com/kingsunc/AVFileParse
搞清楚stbl的映射关系后 我们就可以进行MP4文件的分割实现(也就是所谓的点播拖动)。MP4分割实现源码:https://github.com/kingsunc/AVFileParse/tree/master/Mp4_Segment

MXL 发表于 2019-1-7 13:20:03

看不懂
......

学生 发表于 2019-1-13 10:59:11

好文章,值得学习

度帮主 发表于 2022-6-2 09:46:07

默默的对天书点了个赞
页: [1]
查看完整版本: MP4文件格式分析及分割实现(附源码)