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文件结构:

下图是节点box详细说明:

下面我们将对以上主要box的解析进行详细说明:

1. 一级box

  一级box主要包含ftyp、moov、free、mdat等等。

1.1 ftyp box

结构:

/********************************************************************************************
** File Type Box (ftyp)
**
--------------------------------------------------------------------------------------------
** 字段名称   | 长度(bytes) | 有关描述
--------------------------------------------------------------------------------------------
** boxsize | 4 | box的长度
** boxtype | 4 | box的类型
** major_brand | 4 |
** minor_version | 4 | 版本号
** compatible_brands | 4 * N | 本文件遵从的多种协议(ismo, iso2, mp41)
********************************************************************************************/

运行结果:

1.2 moov box

结构:

/********************************************************************************************
** 字段名称 | 长度(bytes) | 有关描述
--------------------------------------------------------------------------------------------
** boxsize | 4 | box的长度
** boxtype | 4 | box的类型
********************************************************************************************/

1.3 free box

结构:

/********************************************************************************************
** 字段名称 | 长度(bytes) | 有关描述
--------------------------------------------------------------------------------------------
** boxsize | 4 | box的长度
** boxtype | 4 | box的类型
********************************************************************************************/

1.4 mdat box

结构:

/********************************************************************************************
** 字段名称 | 长度(bytes) | 有关描述
--------------------------------------------------------------------------------------------
** boxsize | 4 | box的长度
** boxtype | 4 | box的类型
** | 后面全是真实数据
********************************************************************************************/

运行结果:

2. 二级box

  本节所说的二级box皆为moov的子box,主要包含mvhd、trak、udat等等。

2.1 mvhd box

结构:

/************************************************************************************************************
** 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位分别为小数点整数部分和小数部分,即[16.16] 格式.该值为1.0 (0x00010000)
** volume | 2 | 与rate类似,[8.8] 格式,1.0(0x0100)表示最大音量
** reserved | 10 | 保留位
** matrix | 36 | 视频变换矩阵
** pre-defined | 24 |
** next track id | 4 | 下一个track使用的id号
************************************************************************************************************/

运行结果:

2.2 trak box

结构:

/********************************************************************************************
** 字段名称 | 长度(bytes) | 有关描述
--------------------------------------------------------------------------------------------
** boxsize | 4 | box的长度
** boxtype | 4 | box的类型
********************************************************************************************/

2.3 udat box

结构:

/************************************************************************************************************
**           udat
**
--------------------------------------------------------------------------------------------
**  字段名称 | 长度(bytes)  |  有关描述
--------------------------------------------------------------------------------------------
**  boxsize     | 4        |  box的长度
**  boxtype     | 4        |  box的类型
**                    |  用户自定义数据解析
************************************************************************************************************/

运行结果:

3. 三级box

  本节所说的三级box皆为trak的子box,主要包含tkhd、mdia等。

3.1 tkhd box

结构:

/************************************************************************************************************
** 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 | [8.8] 格式,如果为音频track,1.0(0x0100)表示最大音量;否则为0
** reserved | 2 | 保留位
** matrix | 36 | 视频变换矩阵
** width | 4 | 宽
** height | 4 | 高,均为[16.16] 格式值 与sample描述中的实际画面大小比值,用于播放时的展示宽高
************************************************************************************************************/

运行结果:

3.2 mdia box

结构:

/********************************************************************************************
** 字段名称 | 长度(bytes) | 有关描述
--------------------------------------------------------------------------------------------
** boxsize | 4 | box的长度
** boxtype | 4 | box的类型
********************************************************************************************/

4. 四级box

  本节所说的四级box皆为mdia的子box,主要包含mdhd、hdlr、minf等。

4.1 mdhd box

结构:

/************************************************************************************************************
** 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    | 保留位
************************************************************************************************************/

结果:

4.2 hdlr box

结构:

/************************************************************************************************************
** 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’结尾的字符串
************************************************************************************************************/

结果:

4.3 minf box

结构:

/********************************************************************************************
** 字段名称 | 长度(bytes) | 有关描述
--------------------------------------------------------------------------------------------
** boxsize | 4 | box的长度
** boxtype | 4 | box的类型
********************************************************************************************/

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结构:

/************************************************************************************************************
** 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}
************************************************************************************************************/

结果:

5.2 stbl box

结构:

/********************************************************************************************
** 字段名称 | 长度(bytes) | 有关描述
--------------------------------------------------------------------------------------------
** boxsize | 4 | box的长度
** boxtype | 4 | box的类型
********************************************************************************************/

6. 六级box

  本节所说的六级box皆为stbl的子box,主要包含stsd、stts、stsz、stsc、stss、stco等,这些也是mp4文件设计的精髓所在,主要控制chunk、sample、mdat之间的映射关系。

6.1 stsd box

stsd: Sample Description Box,解析stsd可获得coding类型、视频宽高、音频samplesize、channelcount这些和解码器有关信息。

6.2 stts box

stts: Decoding Time to Sample Box,时间戳和Sample映射表

上图是一个video trak,说明该视频包含87帧数据,每帧包含512个采样。

总共512*87=44544个采样,和我们前面mdhd box的Duration完全一致。

Duration / TimeScale = 44544 / 12288 = 3.625秒 正是我们的视频播放长度。

12288 / 512 = 24 p/s (帧率)。

6.3 stsz box

stsz, stz2: Sample Size Boxes,每个Sample大小的表

一共87帧 每帧的字节大小。

6.4 stsc box

stsc: Sample to chunk 的映射表。

前面说了一共87帧数据,放在83个chunk中。1~82个chunk每个里面放1帧,第83个chunk放了5帧。

6.5 stss box

stss: 关键帧索引表。

第1、13、25、37、49、61、73、85.... 这些帧都是关键帧。

每12帧就有一个关键帧, 前面我们计算得知fps是24。由此可知该视频关键帧间隔为0.5秒。

6.6 stco box

'stco','co64': Chunk位置偏移表

一共83个chunk,记录在mdat真实数据中的字节偏移量。

下图为第三方MP4文件解析结果:

MP4文件格式解析源码:https://github.com/kingsunc/AVFileParse

搞清楚stbl的映射关系后 我们就可以进行MP4文件的分割实现(也就是所谓的点播拖动)。

MP4分割实现源码:https://github.com/kingsunc/AVFileParse/tree/master/Mp4_Segment

MP4文件格式分析及分割实现(附源码)的更多相关文章

  1. Cesium专栏-填挖方分析(附源码下载)

    Cesium 是一款面向三维地球和地图的,世界级的JavaScript开源产品.它提供了基于JavaScript语言的开发包,方便用户快速搭建一款零插件的虚拟地球Web应用,并在性能,精度,渲染质量以 ...

  2. Vue路由实现之通过URL中的hash(#号)来实现不同页面之间的切换(图表展示、案例分析、附源码详解)

    前言 本篇随笔主要写了Vue框架中路由的基本概念.路由对象属性.vue-router插件的基本使用效果展示.案例分析.原理图解.附源码地址获取. 作为自己对Vue路由进行页面跳转效果知识的总结与笔记. ...

  3. 一步步实现windows版ijkplayer系列文章之七——终结篇(附源码)

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  4. Web 开发中很实用的10个效果【附源码下载】

    在工作中,我们可能会用到各种交互效果.而这些效果在平常翻看文章的时候碰到很多,但是一时半会又想不起来在哪,所以养成知识整理的习惯是很有必要的.这篇文章给大家推荐10个在 Web 开发中很有用的效果,记 ...

  5. C#编程总结(七)数据加密——附源码

    C#编程总结(七)数据加密——附源码 概述 数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码,通常称为“密文”,使其只能在输入相应的密钥之后才能显示出本来内容 ...

  6. Entity Framework在Asp.net MVC中的实现One Context Per Request(附源码)

    上篇中"Entity Framework中的Identity map和Unit of Work模式", 由于EF中的Identity map和Unit of Work模式,EF体现 ...

  7. Remote验证及其改进(附源码)

    Remote验证及其改进(附源码) 表单中的输入项,有些是固定的,不变的验证规则,比如字符长度,必填等.但有些是动态的,比如注册用户名是否存在这样的检查,这个需要访问服务器后台才能解决.这篇文章将会介 ...

  8. 为SRS流媒体服务器添加HLS加密功能(附源码)

    为SRS流媒体服务器添加HLS加密功能(附源码) 之前测试使用过nginx的HLS加密功能,会使用到一个叫做nginx-rtmp-module的插件,但此插件很久不更新了,网上搜索到一个中国制造的叫做 ...

  9. PHP简单的长文章分页教程 附源码

    PHP简单的长文章分页教程 附源码.本文将content.txt里的内容分割成3页,这样浏览起来用户体验很好. 根据分页参数ipage,获取对应文章内容 include('page.class.php ...

随机推荐

  1. [ERR] Node goodsleep.vip:6379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.

    解决方案 以前的cluster节点信息 保留 要删除 dump.rdb node.conf集群启动时自动生成文件

  2. 牛客网 —— 爱奇艺2020校招C++方向笔试题 总结

    错了5,6个,主要集中在数据库和操作系统上.    C++还需要提高熟练度. 总结 第6题: 折半查找树:根据二分查找构造得到的树,它一定是一个二叉排序树,是一个特殊的二叉排序树.  (接近于平衡二叉 ...

  3. BLE直接Data channel抓包方法汇总

    之前一致在做一些有关与BLE安全研究的“基础设施建设”工作,我们知道,在BLE进入跳频之后,所有的固定标志都会消失,但是是不是意味着没办法了?不是的.我会提出一些恢复出来的方法. 首先,前导码分析,B ...

  4. 刷题22. Generate Parentheses

    一.题目说明 这个题目是22. Generate Parentheses,简单来说,输入一个数字n,输出n对匹配的小括号. 简单考虑了一下,n=0,输出"";n=1,输出" ...

  5. 假期学习【十一】Python切词,以及从百度爬取词典

    今天主要对从CSDN爬取的标题利用jieba(结巴)进行分词,但在分词过程中发现,如大数据被分成了大/数据,云计算被分隔成了云/计算. 后来又从百度百科--->信息领域爬取了相关词语作为词典,预 ...

  6. vue animate.css训练动画案例 列表循环

    制作目标动画:向上入场添加数据,点击数据右滑动离场 简单页面效果: 实现代码如下: <!DOCTYPE html> <html> <head> <meta c ...

  7. [ZJOI2009] 狼与羊的故事 - 最小割

    给定一个\(N \times M\)方格矩阵,每个格子可在\(0,1,2\)中取值.要求在方格的边上进行划分,使得任意联通块内不同时包含\(1\)和\(2\)的格子. ________________ ...

  8. javascript download geoserver layer as kml file

     var sqlfilter = " CITY='" + city + "' and SDATE>" + sdate + " and SDATE ...

  9. 用Navicat连接mysql报错:2003-Can't connect to MySql server on '10.100.0.109'(10039)

    问题描述 在 window 系统上,用 Navicat 连接 Mysql 数据库,弹出以下提示 问题原因  Mysql 数据库未启动 解决方案:启动 Mysql 数据库 1.点击桌面左下角运行 cmd ...

  10. Linux C/C++ 字符串逆序

    /*字符串逆序*/ #include <stdio.h> #include <string.h> void nixu(char *str) { ; char tmp; for( ...