视频编码与封装格式完全指南
引言
在数字视频的世界中,为了在有限的带宽和存储空间下传输高质量的视听内容,人们开发了各种高效的编码和压缩技术。本文将深入解析视频编码中的IBP帧原理、封装格式、像素格式等核心概念,帮助读者全面理解现代视频技术的工作原理。
视频传输原理
视频是利用人眼视觉暂留的原理,通过播放一系列的图片,使人眼产生运动的感觉。单纯传输视频画面,视频量非常大,对现有的网络和存储来说是不可接受的。
为了能够使视频便于传输和存储,人们发现视频有大量重复的信息,如果将重复信息在发送端去掉,在接收端恢复出来,这样就大大减少了视频数据的体积,因此有了H.264等视频压缩标准。
视频里边的原始图像数据会采用H.264编码格式进行压缩,音频采样数据会采用AAC编码格式进行压缩。视频内容经过编码压缩后,确实有利于存储传输。不过当要观看播放时,相应地也需要解码过程。因此编码和解码之间,显然需要约定一种编码器和解码器都可以理解的约定。
**编码器将多张图像进行编码后生产成一段一段的GOP(Group of Pictures),解码器在播放时则是读取一段一段的GOP进行解码后读取画面再渲染显示。**GOP是一组连续的画面,由一张I帧和数张B/P帧组成,是视频图像编码器和解码器存取的基本单位,它的排列顺序将会一直重复到影像结束。
IBP帧详解
I帧 - 关键帧
I帧即Intra-coded picture(帧内编码图像帧),是关键帧,可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)。
【I帧特点】
- 它是一个全帧压缩编码帧,将全帧图像信息进行JPEG压缩编码及传输
- 解码时仅用I帧的数据就可重构完整图像
- I帧描述了图像背景和运动主体的详情
- I帧不需要参考其他画面而生成
- I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量)
- I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧
- I帧不需要考虑运动矢量
- I帧所占数据的信息量比较大
P帧 - 预测帧
P帧即Predictive-coded Picture(前向预测编码图像帧)。P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。
【P帧特点】
- P帧是I帧后面相隔1~2帧的编码帧
- P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差)
- 解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像
- P帧属于前向预测的帧间编码,只参考前面最靠近它的I帧或P帧
- P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧
- 由于P帧是参考帧,它可能造成解码错误的扩散
- 由于是差值传送,P帧的压缩比较高
B帧 - 双向预测帧
B帧即Bidirectionally predicted picture(双向预测编码图像帧)。B帧是双向差别帧,记录的是本帧与前后帧的差别。要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。
【B帧特点】
- B帧是由前面的I或P帧和后面的P帧来进行预测的
- B帧传送的是它与前面的I帧或P帧和后面的P帧之间的预测误差及运动矢量
- B帧是双向预测编码帧
- B帧压缩比最高,因为它只反映两参考帧间运动主体的变化情况,预测比较准确
- B帧不是参考帧,不会造成解码错误的扩散
生动理解:连环画比喻
想象一下,你在看一本连环画,这本连环画讲的是一个故事。为了节省纸张(就像视频为了节省文件大小),画家不会在每一页上都把整个场景画出来。
I帧 - “关键帧”或”全家福照片”
这是一张完整的、独立的画面。就像连环画里,每隔几页就会有一张画得非常精细、人物背景俱全的大图。
通俗讲:I帧就是 “来,咱们重新拍一张全家福!” —— 画面最清晰,信息最全。
P帧 - “预测帧”或”找不同”
它不会画一整张新图,而是基于前面的一张图(I帧或P帧),只画出变化了的部分。
通俗讲:P帧就是 “看上一张图,我只告诉你哪里动了” —— 比如”张三把手举起来了”。
B帧 - “双向预测帧”或”最聪明的找不同”
这是最节省空间的”偷懒大师”。它不只看前面的图,还会偷看后面的图,然后综合起来,只记录变化。
通俗讲:B帧就是 “我前后看看,然后只告诉你中间发生了啥” —— 比如”球飞到了屏幕中央”。
模拟时间轴与IBP帧分布
假设我们有一段30秒的动漫(番剧)混剪,我们以时间轴和字符图的方式来模拟。
图例:
I= 关键帧(体积大,独立)P= 预测帧(参考前一帧)B= 双向帧(参考前后帧)
时间轴模拟:
时间(秒) 0------5------10------15------20------25------30场景描述 [对话A] [战斗开始] [激烈战斗] [爆炸] [对话B] [结尾]
帧类型分布:
时间点: 0 2 5 7 10 12 15 17 20 22 25 27 30 I B I B I B P I B I B B I B B P B P B P B P B P P (结束) P P B P B P B P B P B B B B P B ... ... ... ... ... ... ... ... ... ... ... ...详细场景分析
-
0-5秒:对话场景(场景A)
- 帧0(I帧):场景开始,一个完整的镜头,人物A特写
- 帧1-4(B帧,P帧):人物口型微动、眼神变化。这里B帧居多,因为运动简单且有规律,双向预测效率极高
- 特点:GOP较长,
I...B.B.P...B.B.P...结构稳定
-
~5秒:战斗开始(场景切换)
- 帧5(I帧):强制插入I帧!因为画面从对话切到战斗,内容完全不同,无法从之前的帧预测
-
5-10秒:激烈战斗
- 帧5(I帧)后,跟随着P帧和B帧
- 但随着动作越来越复杂(快速挥刀、多个角色移动),B帧的比例会下降
- 特点:GOP可能被迫缩短,
I..P..P..B..P..I,I帧出现更频繁
-
~10秒:大爆炸(重大场景变化)
- 帧10(I帧):又一次强制插入。爆炸的火焰和飞溅的碎片与之前的战斗画面差异巨大
-
10-15秒:爆炸持续
- 这是最复杂的部分。火焰和烟雾是随机、无纹理的运动
- B帧几乎无效,因为”未来”的帧无法有效预测”现在”的随机变化
- 编码器会大量使用P帧,甚至可能短暂地使用仅I帧和P帧的序列
-
~15秒:切回对话(场景切换)
- 帧15(I帧):又一次强制插入。回到人物B的特写
-
15-25秒:对话场景B
- 模式回归到第一个对话场景,B帧再次成为主力,压缩效率极高
-
25-30秒:结尾
- 平稳的结束画面,可能有一个缓慢的拉远镜头。规律运动,B帧为主
- 以最后一个I帧结束,方便视频被完整解码
场景对比总结
| 场景类型 | 典型IBP分布 | 原因 |
|---|---|---|
| 笔记本电脑录屏 | I B B P B B P ...(稳定,B帧多) | 变化局部、有规律,双向预测效率高 |
| 番剧/动态视频 | I B B I P P I B I ...(不稳定,I帧和P帧增多) | 场景切换频繁,运动复杂无序,需要频繁重置参考点(I帧)并依赖更可靠的预测(P帧) |
简单来说:
- 每次镜头切换,都是一个I帧
- 文戏对话中,充满了高效的B帧
- 火爆打斗和复杂特效中,P帧会挑大梁,B帧几乎”罢工”
技术实现:运动估计与残差编码
这些”指令”是如何具体实现的呢?它们主要依靠两大核心技术:运动估计和残差编码。
第一步:分块
首先,编码器不会把整个画面当成一个整体来处理。它会将一帧图像(除了I帧)分割成许多个小的宏块,比如16x16像素的方块。
这就好比,我们要描述两张图的差异,不是重新画一整张新图,而是把图分成很多小格子,然后一格一格地去描述变化。
P帧工作流程:“单向追踪指令”
P帧的目标是描述当前帧相对于前面一帧的变化。
-
运动估计:对于当前P帧里的每一个宏块,编码器都会到前面的参考帧(I帧或P帧)里一个特定的搜索区域内,寻找一个最相似的块
- 输出结果:
运动矢量。这是一个指令,它告诉解码器:“亲,这个块,请你从参考帧的那个位置,移动(X, Y)个像素,就能得到我这个块的大致样子了。”
- 输出结果:
-
运动补偿与残差编码:
- 光靠移动得到的块通常不完美,会有细微的差异
- 编码器会用移动过来的块和当前帧实际的块进行对比,计算出差异部分,这个差异就是残差
- 输出结果:
残差数据。这是另一个指令:“好了,块移动过来了,但还不完全准确,请你再按照我给你的这个’修正图纸’(残差)稍微修改一下,就一模一样了。”
所以,一个P帧的”指令集”就是由成千上万个(运动矢量 + 残差数据)组成的清单。
B帧工作流程:“双向预测指令”
B帧更聪明,它允许一个宏块从前面、后面,或者前后两帧的平均值中来获取信息。
-
双向运动估计:对于当前B帧的每一个宏块,编码器会同时去前面的参考帧和后面的参考帧里寻找最相似的块
-
双向运动补偿与残差编码:
- 编码器根据找到的最佳预测方式(前向、后向或平均),从参考帧中获取像素数据
- 同样,它会计算预测块与实际块之间的差异,得到残差
因此,一个B帧的”指令集”就更复杂一些,可能包含:
(前向运动矢量 + 残差)(后向运动矢量 + 残差)(前向运动矢量 + 后向运动矢量 + 残差)
为什么B帧更高效? 因为它有更多的选择。比如一个物体从遮挡物后面移出来,前面的帧里它还被挡着,但后面的帧里它已经完全显露。这时B帧就可以聪明地从”未来”的帧中直接获取这个物体的完整信息,而不必费力地从”过去”的不完整信息中去推算,从而生成数据量更小的指令。
封装格式
音视频的封装格式和编码格式
封装方式(按顺序)
-
封装格式头
- 封装格式比如MP4、FLV、MOV
- 内容为编码,格式,以及关键帧索引(BOX存储)
-
视频编码帧
- H264:包括NAL(网络提取层)、VCL(视频编码层)、SPS(参数设置集合)、PPS(图像参数)
- 视频帧里包含I、B、P帧
- YUV(视频部分):实际上在解码格式头之后,这一部分被统一地解码成YUV(针对不同的压缩格式)
- YUV:比如用在老式电视的RGB,Y:明亮度,U、V:色域和色彩
- YUV → RGB转换显示,这部分开销比较大
- 软解码的效率要比硬解码效率高上很多
-
音频编码帧
- 包含了AAC、APE、FLAC、PCM原始音频格式
- 解码成PCM、FLT(float 4字节 32位)
- 然后进行重采样,转为声卡支持的S16播放
常用封装格式
- AVI:压缩标准可以任意选择
- FLV、TS:流媒体的格式
- ASF:高级流媒体格式
- MP4:ffmpeg4定义好的一种封装格式
视频编码:H264、WMV、XviD、MJPEG
音频编码:AAC、MP3(有损压缩)、APE(像是Wav,PCM原始的音频格式)、FLAC(无损压缩)
像素格式
RGB处理格式
R G B即为三原色
“A”代表Alpha通道,表示颜色的透明度,取值范围从0(完全透明)到1(完全不透明)
- BGRA、RGBA:RGBA和BGRA的主要区别在于颜色通道的排列顺序:RGBA的顺序是红色、绿色、蓝色和透明度,而BGRA的顺序是蓝色、绿色、红色和透明度
- ARGB32
- RGB32
YUV420
前文提到过的另一种的色彩格式(明亮度、色域、色彩)
RGB模式和YUV模式可以一定程度上进行转换(用某些算法)
RGB排列格式
R G B按照B G R模式倒序排列
总结
现代视频编码技术通过智能地使用I帧、P帧和B帧的组合,在保证视频质量的同时极大地压缩了文件体积。I帧作为关键帧提供完整的画面信息,P帧通过前向预测记录变化,B帧则利用双向预测实现最高效的压缩。
不同的场景类型会影响IBP帧的分布:静态或规律运动场景适合使用更多B帧,而复杂动态场景则需要更多P帧和更频繁的I帧。封装格式则负责将这些编码后的视频数据与音频数据打包在一起,形成我们常见的视频文件。
这种动态调整的能力,正是现代视频编码器智能和强大的体现。它总是在为每一帧寻找最经济的”描述方式”,从而在有限的带宽下,为我们呈现最精彩的画面。
部分信息可能已经过时