【FFmpeg实战】视频基础和MP4容器解封装

news2024/10/5 22:23:09

转载自原文地址:https://juejin.cn/post/6901218687081480206

一、视频的编解码方式

谈到视频,我们经常会听到视频编解码、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。

img

编辑切换为居中

添加图片注释,不超过 140 字(可选)

通过上图可以看到,一个视频帧包含了一个或多个NALU,开头一般是SPS和PPS,这两个主要是用于初始化解码器所需要的参数信息,也是解码的关键,接下去就是I/P/B帧等NALU数据,而NALU细分下去还有切片、宏等单位,这里由于篇幅原因就不在展开述论。

三、视频帧相关概念

在视频的编解码中,经常会讨论到几个很关键的名词,如I帧、P帧、B帧等。接下来从编码和解码角度来理解它们。

从编码角度上来说:

  1. I帧:帧内编码帧, I帧通常是每个GOP(MPEG所使用的一种视频压缩技术)的第一个帧,经过适度地压缩,作为随机访问的参考点,可以当成静态图像,I帧压缩掉视频的空间冗余信息;
  2. P帧:前向预测编码帧,通过将图像序列中前面已编码帧的时间冗余信息充分去除来压缩传输数据量的编码图像;
  3. B帧:双向预测内插编码帧,既考虑源图像序列前面的已编码帧,又顾及源图像序列后面的已编码帧之间的时间冗余信息,来压缩传输数据量的编码图像。

从解码角度上来说:

  1. I帧自身可以通过视频解压算法解压成一张单独的完整视频画面,所以I帧去掉的是视频帧在空间维度上的冗余信息;
  2. P帧需要参考其前面的一个I帧或者P帧来解码成一张完整的视频画面;
  3. B帧则需要参考其前一个I帧或者P帧及其后面的一个P帧来生成一张完整的视频画面,所以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为基本单位。

img

编辑切换为居中

添加图片注释,不超过 140 字(可选)

二、Box理解

img

编辑切换为居中

添加图片注释,不超过 140 字(可选)

MP4文件由若干个box组成,box的示意图如上图所示:

  1. box由header和body组成,header指明了box的size和type;
  2. size包含了box的header和body整个大小;如果size为1,表示box的长度需要用更多的bits位来描述,可以通过一个64bits位的largesize来描述box的长度,如果size为0,表示该box为文件的最后一个box;
  3. type,通常使用4个ASCII码的字符如"ftyp"、“moov"等表示,这些box type是已经预定义好的,表示固定的含义,如果是"uuid”,表示该box为用户自定义拓展的类型,如果box type是未定义的,应将其忽略;
  4. box中可以包含box,这种box叫做container box;
  5. box分为两种,Box和Fullbox,FullBox是Box的拓展,header中增加了8位的version和24位的flags字段。

三、常见的MP4文件工具

  1. mp4box.js:一个在线解析mp4的工具。
  2. bento4:包含mp4dump、mp4edit、mp4encrypt等工具。
  3. MP4Box:类似于bento4,包含很全面的工具。
  4. mp4info.exe: windows平台图形界面展示mp4基本信息的工具。

我们使用mp4box.js,可以看到MP4文件由许多box组成,每个box包含不同的信息,以树形的方式组织,主要的box如下:

img

编辑切换为居中

添加图片注释,不超过 140 字(可选)

通过上表,我们可以看到有4个树节点:

  1. ftyp:文件类型;
  2. moov box:媒体的metadata的描述和信息;
  3. mdat:具体的媒体数据;
  4. 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。

img

编辑

添加图片注释,不超过 140 字(可选)

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。

img

编辑切换为居中

添加图片注释,不超过 140 字(可选)

  • 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了。

总结

感谢您阅读到这里,本次分享的内容只是视频方面的基础,过程有些枯燥,如若有什么描述不对或不得当,欢迎指出。

  >>> 音视频开发 视频教程: https://ke.qq.com/course/3202131?flowToken=1031864 
  >>> 音视频开发学习资料、教学视频,免费分享有需要的可以自行添加学习交流群: 739729163  领取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/692587.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ros版本KF-GINS(带有rviz可视化结果显示及文件生成)

原始的KF-GINS是基于读写文件实现的,在此基础上改进了ros版本,将原始数据文件转换为rosbag格式,并实现了rviz下的可视化结果显示,代码已共享至github https://github.com/slender1031/kf-gins-ros 感谢武汉大学卫星导航定位技术研…

IT培训的背后,是“韭菜”的躺赚梦!

本文只谈"骗局",不谈其他,绝不引战,如有错误,希望指出我会及时改正。 实际也有大量做得好的、值得肯定的培训机构,这里需要大家仔细鉴别。 导语 为什么要写这篇文章呢,近些年培训这个话题也比较…

Mhz_c1f靶场-简记

靶机 名称:mhz_cxf:clf download url:https://www.vulnhub.com/entry/mhz_cxf-c1f,471/ IP地址探测 sudo netdiscover -i eth1 -r 192.168.56.0/24 sudo netdiscover -i eth1 -r 192.168.56.0/24 Currently scanning: 192.168.56.0/24 | Screen …

ARM Trace32(劳特巴赫) 使用介绍 1 - Veloce 环境中使用 Trace32 介绍

文章目录 背景1.1 Trace 启动1.1.1 Trace32 系统相关设置 1.2 Trace 常用命令1.2.2 加在bin文件1.2.3 寄存器常用命令1.2.4 内存(寄存器)数据修改 1.3 变量相关命令 背景 Veloce是一款基于FPGA的高速仿真器,可用于验证芯片设计和软件开发, 它和 Trace32 都可以用于…

16.RocketMQ之消费重试以及原理

highlight: arduino-light 1.4 消费重试 对于顺序消息,当消费者消费消息失败后,消费者会在本地自动不断进行消息重试,每次间隔时间为 1 秒,重试最大值是 Integer.MAX_VALUE。 对于无序消息(普通、定时、延时、事务消息)当消费者消费消息失败时可以通过设置返回状态达到重试的目…

湿地环境监测物联网解决方案

湿地作为生态系统的关键组成部分,发挥着涵养水源、调节气候、改善环境、维护生物多样性等生态功能。湿地提供了独特的生境,为许多鸟类、鱼类和其他野生动物提供了栖息地和食物来源。此外,湿地还具有保持水量平衡和水质净化的重要功能&#xf…

最优控制:代数黎卡提方程ARE(Algebraic Riccati Equation)

本文介绍代数黎卡提方程的Matlab解法,包括直接求解和迭代求解 问题描述: 一、数值解法 可以看出,ARE方程是关于P的一个非线性方程,当系统矩阵维度较高时,难以求解,但是MATLAB给出了求解ARE的函数care % 系…

颜色聚合向量 Color Co-ccurrence Vector 介绍以及MATLAB代码实现

这件事情的起因是我想复习一下我在亚太杯数学建模当中使用过的CCV这种方法,但是CSDN平台上找了半天都没有,所以后来决定Google一下,终于找到了,甚至还有实现的代码,因此放上来。原文见Dr. Mahmoud Attia的博客。 一、…

JAVA中的伪共享与缓存行

一.伪共享与缓存行 1.CPU缓存架构 CPU 是计算机的心脏,所有运算和程序最终都要由它来执行。 主内存(RAM)是数据存放的地方,CPU 和主内存之间有好几级缓存,因为即使直接访问主内存也是非常慢的。 CPU的速度要远远大…

一图看懂CodeArts Board 5大特性,带你玩转看板服务

华为云看板服务CodeArts Board,通过构建研发效能度量体系,实现软件研发过程的可视化、软件交付的可管理可跟踪可量化,及时识别研发过程的堵塞点和改进点,通过数据驱动运营和治理,不断提升企业的软件能力和研发效能。

详解JAVA序列化

目录 1.什么是序列化 2.JAVA中的序列化 2.1.成员变量必须可序列化 2.2.transient关键字,可避免被序列化 2.3.无法更新状态 2.4.serialVersionUID 3.JDK序列化算法 4.序列化在实际中的一些应用 1.什么是序列化 序列化就是将对象转换为二进制格式的过程。对象…

Maven安装和配置详细教程

Maven安装和配置详细教程 1、Maven简介 Maven 是 Apache 软件基金会的一个开源项目,是一个优秀的项目构建工具,它用来帮助开发者管理项目中的 jar,以及 jar 之间的依赖关系、完成项目的编译、测试、打包和发布等工作。 2、Maven下载 点击Maven下载官方地址下载Maven。或者去…

postman持续集成-Jenkins自动构建

自动构建,就是设置一个定时器,定时时间到, Jenkins 自动执行测试用例 比如说,我设置下午五点,那么jenkins就是自动执行命令,自动生成报告,后续还可加上邮箱,会把报告发至邮箱 1. Jenkins 首页,点击任务名:如&#xff…

数据库—关系代数

传统的集合运算 在数据库中的关系代数运算有以下三种基本运算 并交差 必须满足两个表之间的属性个数必须一样。(必须具有相容性) 投影与选择运算 投影:π L _L L​( R ) 解释->π是投影符号,L是R表中的属性列,从…

临时文件中转服务的搭建-chfs软件的使用

因为经常用到远程桌面连接,所以本地pc和远程pc间的文件传输一直是个经常遇到的问题,尝试过用vftp搭建ftp服务,但是该服务在许多vps上被禁用,且windows上使用也要进行设置,比较麻烦。所幸发现了ods-im/CuteHttpFileServ…

接口测试如何做?你真的会做吗?全网超全整理实战案例...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 API测试的流程 准…

分布式事务Seate

一、Seata简介 1、Seata的核心组件 TC (Transaction Coordinator)事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。TM (Transaction Manager)事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。RM (Resourc…

2023下半年北京/上海/深圳软考(中/高级)认证招生

软考是全国计算机技术与软件专业技术资格(水平)考试(简称软考)项目,是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试,既属于国家职业资格考试,又是职称资格考试。 系统集成…

Docker安装与启动

Docker安装与启动 文章目录 Docker安装与启动前言容器与虚拟机比较 1、安装Docker2、设置ustc的镜像3、Docker的启动与停止总结 前言 容器与虚拟机比较 虚拟机(VM)是计算机系统的仿真。简而言之,它可以在实际上是一台计算机的硬件上运行看起…

Docker教程

Docker 能解决的问题 ⾸先,我们先来看⼏个问题: 1. 合作开发的时候,在本机可以运⾏,在别⼈的电脑上跑不起来。 这⾥我们以 Java Web 应⽤程序为例,⼀个 Java Web 应⽤程序涉及很多东⻄,⽐如 JDK 、 Tomc…