视频基础 以及 MP4 容器解封装
作者:SeanMa
来源:https://juejin.cn/post/6901218687081480206
最近在研究基于移动端平台上使用视频做动画载体的方案,目前移动端平台使用动画的方案有:gif图、apng、webp、lottie、svga等,各有各的优势,也有相应的劣势。
而使用视频做动画的目的,寻求的是完美还原设计师的设计特效外,同时性能达到极致。
在这个过程中,也积累了一些视频相关的知识,借此同大家分享下。
第一部分 视频相关基础
一、视频的编解码方式
谈到视频,我们经常会听到视频编解码、H.264等诸如此类的内容。那么视频编解码是什么意思呢?
视频编解码,其实就是对视频数据进行压缩和解压缩的过程,而在讨论到编解码时,又经常同H.264联系到一起,那么H.264又是什么?
H.264是一种视频压缩标准,简称AVG,一种被广泛使用的高精度视频的录制、压缩和发布格式。该标准引入了一系列新的能够大大提高压缩性能的技术,并能够同时在高码率端和低码率端大大超越以前的诸标准,可以说是一种压缩算法,但又不仅仅止步于此。
H.264是H.26X系列中的一种,目前最新是H.265,简称HEVC,在同样的画面质量下,后者的压缩率是前者两倍(比特率减少50%),是未来发展趋势,iOS上的Video ToolBox目前可支持H.265的编解码。视频编码还有其他的标准,比如AMV、AVS等等,但主流基本是H.26X系列。
二、关于H.264
H.264是视频的原始码流,分为两层,分别是视频编码层(VCL)和网络提取层(NAL),前者是H.264编码/压缩的核心,主要负责将视频数据编码/压缩,再切分,后者负责格式化VCL数据并提供头信息,以保证数据适合各种信道和存储介质的传输,基本单位是NALU。
通过上图可以看到,一个视频帧包含了一个或多个NALU,开头一般是SPS和PPS,这两个主要是用于初始化解码器所需要的参数信息,也是解码的关键,接下去就是I/P/B帧等NALU数据,而NALU细分下去还有切片、宏等单位,这里由于篇幅原因就不在展开述论。
三、视频帧相关概念
在视频的编解码中,经常会讨论到几个很关键的名词,如I帧、P帧、B帧等。接下来从编码和解码角度来理解它们。
从编码角度上来说:
I帧:帧内编码帧, I帧通常是每个GOP(MPEG所使用的一种视频压缩技术)的第一个帧,经过适度地压缩,作为随机访问的参考点,可以当成静态图像,I帧压缩掉视频的空间冗余信息;
P帧:前向预测编码帧,通过将图像序列中前面已编码帧的时间冗余信息充分去除来压缩传输数据量的编码图像;
B帧:双向预测内插编码帧,既考虑源图像序列前面的已编码帧,又顾及源图像序列后面的已编码帧之间的时间冗余信息,来压缩传输数据量的编码图像。
除次之外,还有PTS、DTS、GOP。
PTS是用来描述视频解码阶段的帧输出顺序,DTS用来描述视频解码阶段的帧解码顺序,在无B帧的情况下,PTS等于DTS,在有B帧的情况下,输出顺序需要参考PTS。
而GOP,描述的是两个I帧之间形成的一组图片。
第二部分 MP4解封装
一、MP4定义
MP4是我们常见的视频资源,但MP4的本质又是什么呢?和H.264有什么不可告人的秘密呢?
MP4也叫MPEG-4,是一种多媒体容器格式,后缀是.mp4,其容器格式借鉴了Apple的QuickTime的组织方式,即以一系列BOX为基本单位。
二、Box理解
MP4文件由若干个box组成,box的示意图如上图所示:
box由header和body组成,header指明了box的size和type;
size包含了box的header和body整个大小;如果size为1,表示box的长度需要用更多的bits位来描述,可以通过一个64bits位的largesize来描述box的长度,如果size为0,表示该box为文件的最后一个box;
type,通常使用4个ASCII码的字符如"ftyp"、"moov"等表示,这些box type是已经预定义好的,表示固定的含义,如果是"uuid",表示该box为用户自定义拓展的类型,如果box type是未定义的,应将其忽略;
box中可以包含box,这种box叫做container box;
box分为两种,Box和Fullbox,FullBox是Box的拓展,header中增加了8位的version和24位的flags字段。
三、常见的MP4文件工具
mp4box.js:一个在线解析mp4的工具。
bento4:包含mp4dump、mp4edit、mp4encrypt等工具。
MP4Box:类似于bento4,包含很全面的工具。
mp4info.exe: windows平台图形界面展示mp4基本信息的工具。
我们使用mp4box.js,可以看到MP4文件由许多box组成,每个box包含不同的信息,以树形的方式组织,主要的box如下:
通过上表,我们可以看到有4个树节点:
ftyp:文件类型;
moov box:媒体的metadata的描述和信息;
mdat:具体的媒体数据;
free:无关紧要的内容。
四、基本Box介绍
File Type Box
ftyp简单的说就是为了标识它的developer是谁,兼容哪些标准等,如“mp42”表示它的major brand是MP4 v2,而“mp42”和“mp41”则表示它的compatible brands是MP4 v2和MP4 v1。
major_brand:推荐兼容性的版本;
minor_version:最低兼容性的版本;
compatible_brands[]:所有的兼容性的版本。
Movie Box(moov)
包含了文件媒体的metadata信息,是一个container box,一般在ftyp后面。moov包含1个mvhd和若干个trak,其中mvhd是header box,作为第一个子box出现,trak包含一个trakc的相关信息,是一个container box。
Movie Header Box(mvhd)
mvhd(Movie Header Box),主要存放着视频文件的meta data,其中的time scale和 duration对文件的播放有着重要作用
version:box的版本,0或者1,一般为0;
creation time:创建时间(相对于UTC时间1904-01-01零点的秒数);
modification time:修改时间;
timescale:文件媒体在1秒时间内的刻度,可理解为1s长度的时间单元数;
duration:该track的时间长度;
rate:推荐播放速率,高16位和低16位分别为小数点整数部分和小数部分,[16.16]格式,该值为1.0(0x00010000)表示正常向前播放;
volume:推荐播放音量,[8.8]格式,1.0(0x0100)表示最大音量。
martix:视频变换矩阵
newxt track id:下一个track使用的id
Track Header Box(tkhd)
version:box版本,0或者1,一般为0;
flags:24-bit整数,按位或操作结果值;
track id:track id号,不能重复且不能为0;
duration:track的时间长度;
volume:[8.8]格式,如果为音频track,1.0(0x0100)表示最大音量,否则为0;
width:宽度,[16.16]格式;
height:高度,[16.16]格式,不必与sample的像素尺寸一致,用于播放时显示的宽高。
Media Box(mdia)
Media Boxyeshi 也是一个container box,其定义了track媒体类型以及smaple数据,描述sample的信息。mdia包含:
一个Media Header Atom,即mdhd;
一个Handler Reference,即hdlr;
一个media information,即minf,解码的关键。
Media Header Box(mdhd)
mdhd和tkhd内容上大致一致,不过tkhd通常是指定的track设定的相关属性和内容,而mdhd是针对独立的media来设置的,字段包含
version:box的版本,0或者1,一般为0;
timescale:比mvhd中的timescale精度更高;
duration:track的时间长度;
language:媒体语言码,最高位为0。
handler Reference Box(hdlr)
hdlr解释了媒体的播放过程信息,可获取track类型信息,主要是有字段handler_type(uint32_t)区分,具体含义如下:
handler type:该值为4个字符,会有以下取值:
vide:视频;
soun:音频;
hint:这个特殊的track并不包含媒体数据,而是包含了一些将其他数据track打包成流媒体的指示信息。
Media Information Box(minf)
重要的容器box,存储了解释track媒体数据的handler-specific信息,media handler用这些信息将媒体时间映射到媒体数据并行处理,minf是一个container box,其实际内容由子box说明。
一般情况下,minf包含了一个header box,一个dinf和一个stbl,其中header box的数据类型有vmhd(视频轨)、smhd(音轨)、hmhd(hint track)、nmhd(null track),dinf为data information box,stbl为sample table box。
五、重要Box
Sample Table Box(stbl)
stbl包含了关于track中sample所有时间和位置的信息,以及sample的编解码等信息。利用这个表,可以解释sample的时序、类型、大小以及在各自存储容器中的位置。stbl是MP4文件中最复杂的一个box了,也是解开MP4文件格式的主干,是一个container box;
stbl包含:
stsd:sample description box,样本的描述信息;
stts:time to sample box,sample解码时间的压缩表;
ctts:composition time to sample box,sample的CTS与DTS的时间差压缩表;
stss:sync sample box,针对视频,关键帧的序号;
stsz/stz2:sample size box,每个smaple的字节大小;
stsc:sample to chunk box,sample-chunk映射表;
stco/co64:chunk offset box,chunk在文件中的偏移。
在mp4文件中,sample是一个媒体流的基本单元,例如视频流的一个sample代表实际的nal数据。chunk是数据存储的基本单位,它是一系列sample数据的集合,一个chunk中可以包含一个或多的sample。
Sample Description Box(stsd)
存储了编码类型和初始化解码器需要的信息。stsd有多种类型的子box,具体取决于该track是视频或是音频或是其他,对于视频,若是通过使用了H.264编码的,子box为avc1,avc1的主要字段:
type:avc1;
width、height:视频像素宽高;
horizresolution、vertresolution:每英寸的像素值,[16,16]格式的数据;
frame_count:每个sample的视频帧数,默认是1;
avcC:存放sps和pps内容。
Decoding Time to Sample Box(stts)
包含一个Sample编码时序表,通过这个表可以从解码时间映射到sample序号,表中的每一项是连续相同的编码时间增量(Decode Delta)的个数和编码时间增量,通过把时间增量累加就可以建立一个完整的time to sample表。
Composition time to sample box(ctts)
这个box提供了decoding time到composition time的offset的表,用于计算pts。
这个表在Decoding time和composition time不一样的情况下是必须的。
如果box的version等于0,decoding time必须小于等于composition time,因而差值用一个无符号的数字表示。
sample_count:连续相同的offset的个数;
sample_offset:CT和DT之间的offset。
DT(decoding time):编码时间;
CT(composition offset):创作时间;
Decode Delta:编码时间增量,通过前面提到的stts表可获取;
Composition offset:显示时间同解码时间的差值,等于CT-DT,通过ctts获取。
由此可知,通过stts和ctts可以方向推出解码顺序和视频播放顺序,当无B帧视频时,ctts不存在,解码顺序和播放顺序一致。
Sync Sample box(stss)
它包含media中的关键帧的sample表,如果此表不存在,则每一帧都是关键帧。
主要字段sample_number:媒体流中同步的sample序号。
Sample Size Box(stsz/stz2)
包含sample的数量和每个sample的字节大小,box体积有点大,主要字段有:
sample_size:指定默认的sample的字节大小,如果smaple大小不一样,则这个字段为0;
sample_count:track中的sample的数量;
sample_sizes:每个sample的字节大小。
Sample To Chunk Box(stsc)
meida中的sample被分组成chunk,chunk可以有不同的大小,chunk内的sample可以有不同的大小,通过stsc中的sample-chunk映射表可以找到指定的smaple的chunk,从而找到这个sample。结构相同的chunk可以聚集在一起形成一个entry,这个entry就是一个stsc映射表的表项。
主要字段说明:
first_chunk:一组chunk的第一个chunk的序号;
chunk的编号从1开始。
samples_per_chunk:每个chunk有多少个sample;
sample_desc_idx:stsd中的sample desc信息的索引。
Chunk Offset Box(stco/co64)
Chunk Offset表存储了每个thunk在文件中的位置,这样就可以找到媒体数据,而不用解析box了。
总结
感谢您阅读到这里,本次分享的内容只是视频方面的基础,过程有些枯燥,如若有什么描述不对或不得当,欢迎指出。
技术交流,欢迎加我微信:ezglumes ,拉你入技术交流群。
推荐阅读:
音视频面试基础题
OpenGL ES 学习资源分享
开通专辑 | 细数那些年写过的技术文章专辑
NDK 学习进阶免费视频来了
推荐几个堪称教科书级别的 Android 音视频入门项目
觉得不错,点个在看呗~
视频基础 以及 MP4 容器解封装相关推荐
- ffmpeg之mp4文件解封装截取一段视频并重封装
#include <iostream> #include <fstream> #include <thread>extern "C"{#incl ...
- MP4/MP3解封装ffmpeg(十三)
前言 解封装包括很多层步骤,包括协议的解析,封装格式的解析.ffmpeg中,本地文件当做file://协议来解析,远程文件采用的传输协议有http(s),rtsp等等.封装格式比如MP4,MOV,TS ...
- 最全音视频基础知识学习详解(含多个干货链接)
这里将了解到的和一些博客网站讲到的音视频基础相关的内容总结整理到了一起,方便系统的学习和回顾记录. 首先一个最简易的音视频图解,包括一下几个部分: 对于一个实时音视频应用共包括几个环节:采集.编码.前 ...
- 音视频解封装:MP4核心Box详解及H264AAC打包方案
问题背景: 上一篇文章<音视频封装:MP4结构概述和分析工具>让大家看了下MP4的主要结构和推荐了一些分析工具,如果你对MP4没有任何了解,还是先看上文,了解MP4的基本结构,其中还有许 ...
- FFmpeg分离(解封装)视频和音频
使用FFmpeg库对mp4文件进行解封装,提取mp4中的视频流和音频流输出到单独的输出文件中. 所谓的分离视频和音频是我们通俗的说法,官方的说法叫解封装.与解封装对应的叫封装或复用器,也就是将多个视频 ...
- 各种音视频编解码学习详解之 编解码学习笔记(十三):容器
最近在研究音视频编解码这一块儿,看到@bitbit大神写的[各种音视频编解码学习详解]这篇文章,非常感谢,佩服的五体投地.奈何大神这边文章太长,在这里我把它分解成很多小的篇幅,方便阅读.大神博客传送门 ...
- 软编码Flv 到Mp4 容器(五) fmp4 ftyp box 和moovmvhd box详解
https://github.com/332065255/flv2fmp4 代码库 软编码Flv 到Mp4 容器(一) 软编码Flv 到Mp4 容器(二) flv tag拆解 软编码Flv 到Mp4 ...
- FFmpeg解封装、解码音频和视频(分别使用OpenGL和OpenAL播放)
1 ffmpeg解码大致流程 下图是ffmpeg解码播放音视频的基本流程: 首先是网络媒体解协议,解协议之后得到对应的媒体文件比如mp4,ts等,这些格式是媒体文件的封装格式,也就是将音频,视频, ...
- MP4 格式:最少加载多少数据就能渲染出视频首帧?优化短视频播放体验必须先了解它丨音视频基础
(本文基本逻辑:MP4 封装格式概览 → 重要 Box 具体信息介绍 → 实战中对 MP4 Box 信息的使用) MP4 也称为 MPEG-4 第 14 部分,是继承 MPEG-4 第 12 部分的 ...
- 【音视频处理】MP4文件播放不了?视频播放、转码工作原理。封装、编码
大家好,欢迎来到停止重构的频道. 本期开始,我们将展开一个全新的系列:音视频处理. 里面会涉及到直播.音视频转码.音视频合成.音视频AI处理等应用场景. 本期我们先从基础讲起,介绍一下音视频文件.直播 ...
最新文章
- ai css 线条粗细_如何训练AI将您的设计模型转换为HTML和CSS
- matlab 级联cic,Matlab中CIC滤波器的应用
- github pages markdown_排版利器——MarkDown入门简介
- iPhone开发教程之Core Data 常见问题的总结
- 用GD32替代STM32,是什么体验?
- java什么内部类_Java的内部类学习
- python123程序设计实验答案_Python程序设计第二次实验报告
- 剑指offer——面试题59:对称的二叉树
- [SQL SERVER] 跨库查询--分布式查询
- 拓端tecdat|r语言中如何进行两组独立样本秩和检验
- android adb日志过滤包名,adb过滤只查看某一个app的日志
- 删除进程 linux,linux批量删除进程
- 省一级计算机操作题,江苏省计算机一级操作题大全
- javaScript实现简单网页倒计时代码
- mysql redo查看_mysql redo
- nacos + springcloud gateway 出现503错误
- Docker学习之day01 Docker的前世今生
- 分享 | masked自编码器(MAE):一种可扩展的用于计算机视觉任务的自监督学习器
- 0x7fffffff是多少(也就是INT_MAX,首位是 0,其余都是1,f代表1111)
- 入门深度学习?这里有5件你应该知道的事