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文件结构:
下图是节点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文件格式分析及分割实现(附源码)的更多相关文章
- Cesium专栏-填挖方分析(附源码下载)
Cesium 是一款面向三维地球和地图的,世界级的JavaScript开源产品.它提供了基于JavaScript语言的开发包,方便用户快速搭建一款零插件的虚拟地球Web应用,并在性能,精度,渲染质量以 ...
- Vue路由实现之通过URL中的hash(#号)来实现不同页面之间的切换(图表展示、案例分析、附源码详解)
前言 本篇随笔主要写了Vue框架中路由的基本概念.路由对象属性.vue-router插件的基本使用效果展示.案例分析.原理图解.附源码地址获取. 作为自己对Vue路由进行页面跳转效果知识的总结与笔记. ...
- 一步步实现windows版ijkplayer系列文章之七——终结篇(附源码)
一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...
- Web 开发中很实用的10个效果【附源码下载】
在工作中,我们可能会用到各种交互效果.而这些效果在平常翻看文章的时候碰到很多,但是一时半会又想不起来在哪,所以养成知识整理的习惯是很有必要的.这篇文章给大家推荐10个在 Web 开发中很有用的效果,记 ...
- C#编程总结(七)数据加密——附源码
C#编程总结(七)数据加密——附源码 概述 数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码,通常称为“密文”,使其只能在输入相应的密钥之后才能显示出本来内容 ...
- Entity Framework在Asp.net MVC中的实现One Context Per Request(附源码)
上篇中"Entity Framework中的Identity map和Unit of Work模式", 由于EF中的Identity map和Unit of Work模式,EF体现 ...
- Remote验证及其改进(附源码)
Remote验证及其改进(附源码) 表单中的输入项,有些是固定的,不变的验证规则,比如字符长度,必填等.但有些是动态的,比如注册用户名是否存在这样的检查,这个需要访问服务器后台才能解决.这篇文章将会介 ...
- 为SRS流媒体服务器添加HLS加密功能(附源码)
为SRS流媒体服务器添加HLS加密功能(附源码) 之前测试使用过nginx的HLS加密功能,会使用到一个叫做nginx-rtmp-module的插件,但此插件很久不更新了,网上搜索到一个中国制造的叫做 ...
- PHP简单的长文章分页教程 附源码
PHP简单的长文章分页教程 附源码.本文将content.txt里的内容分割成3页,这样浏览起来用户体验很好. 根据分页参数ipage,获取对应文章内容 include('page.class.php ...
随机推荐
- 咸鱼的ACM之路:DFS水题集
DFS的核心就是从一种状态出发,转向任意的一个可行状态,直到达到结束条件为止.(个人理解) 下面全是洛谷题,毕竟能找到测试点数据的OJ我就找到这一个....在其他OJ上直接各种玄学问题... P159 ...
- LeetCode 938. 二叉搜索树的范围和
题目链接:https://leetcode-cn.com/problems/range-sum-of-bst/ 给定二叉搜索树的根结点 root,返回 L 和 R(含)之间的所有结点的值的和. 二叉搜 ...
- 直观获取redis cluster 主从关系
需求:还是redis-trib.rb脚本获取的信息不足或者太繁杂,这里给出更加直观的一种方法, 说明:已在4.x版本测试通过,3.x不可用. 原生的输出 (1adfa7f3...) keys slot ...
- Chrome浏览器控制台报Refused to get unsafe header "XXX"的错误
最近在调试后端下载的接口时在浏览器的控制台中发现了红色的错误信息,例如Refused to get unsafe header "XXX":前端是采用XMLHttpRequest对 ...
- MySQL的修改和删除数据表字段
MySQL的修改和删除数据表字段 写在前面: 数据库存在的意义:数据存储和数据管理. 数据库:行(数据),列(字段) 注意:本页是解决了列的字段问题.下一页是解决行的数据问题. 注意,所有的字段名,最 ...
- 数据预处理 | 通过 Z-Score 方法判断异常值
判断异常值方法:Z-Score 计算公式 Z = (X-μ)/σ 其中μ为总体平均值,X-μ为离均差,σ表示标准差.z的绝对值表示在标准差范围内的原始分数与总体均值之间的距离.当原始分数低于平均值时, ...
- 《深入理解java虚拟机》读书笔记三——第四章
第四章 虚拟机性能监控与故障处理工具 1.JDK命令行工具 jps命令: 作用:列出正在运行的虚拟机进程. 格式:jps [option] [hostid] 选项:-q 只输出LVMID(Local ...
- 51Nod 1091 线段的重叠 (贪心)
X轴上有N条线段,每条线段包括1个起点和终点.线段的重叠是这样来算的,[10 20]和[12 25]的重叠部分为[12 20]. 给出N条线段的起点和终点,从中选出2条线段,这两条线段的重叠部分是最长 ...
- java的开发步骤----
首先老师给了一个 视频给我:叫我理解java的简单开发步骤: 上两张图: 然后我就理解成了这样::: 简述java开发步骤:第一步: 编写源代码,把源代码写好 :第二部:源代码通过编译器编译成字节码c ...
- 2020牛客寒假算法基础集训营5 B.牛牛战队的比赛地 (二分/三分)
https://ac.nowcoder.com/acm/contest/3006/B 三分做法 #include<bits/stdc++.h> #define inf 0x3f3f3f3f ...