I帧、P帧和B帧(I-frames、P-frames and B-frames)的概念是视频压缩领域的基础。这三种帧类型在特定情况下用于提高编解码器的压缩效率、压缩流的视频质量,以及使得流去应对传输和存储时候的错误和故障。

翻译 | Alex

技术审校 | 赵军

本文来自OTTVerse,作者为Krishna Rao Vijayanagar。

I帧、P帧和B帧 Easy-Tech #002#

在本篇文章中,我们将学习I帧、P帧和B帧的工作原理以及它们的用途。

好,我们先从现代视频压缩中最基本的概念开始——帧内预测和帧间预测。

帧内预测和帧间预测

在本篇文章中,我并不会深入讲解帧内预测和帧间预测(Intra and Inter-prediction)的技术细节,但是我会告诉你它们为何存在以及有什么用处。

以下方图片为例。图片显示了两个视频帧(彼此相邻),有一个黑色像素的矩形块在其中移动。在第一帧中,该块位于图像的左侧,而在第二帧中,它已经移到了右侧。

如果我想用现代视频编码器(如H.264或HEVC)压缩帧2,我会这样做:

1.将视频分解为多个像素块(宏块),并逐一压缩。

2.为了压缩每个宏块,首先在当前帧和前后帧中搜索,找到与我们想要压缩的宏块相似的宏块。

3.记录最佳匹配的宏块的位置(位于哪一帧以及在该帧中的位置)。然后,两个宏块之间的差异被压缩,并和位置信息一起被发送给解码器。

请看下方图片。如果要压缩帧2中的宏块(已用红色方框标记),你认为最佳方法是什么?该怎么做?

1.首先,我可以查看帧1,并找到相匹配的宏块。它似乎移动了一个帧宽(我知道要少一些)的距离,并与帧2中像素块的高度大约相同。好的,运动矢量出现了。

2.我在同一帧内搜索,并很快发现,位于红色方框标记的宏块与上方的宏块相同。所以,我可以让解码器复制这一宏块,而不必再去其他帧搜索。这样一来,运动矢量便是最小的(如果存在的话)。

现在我们来看下一个示例。如果想要压缩帧2中包含蓝色球体的宏块,我们该怎么做呢?

在同一帧内搜索,还是在前面的编码帧中搜索?

1.首先,我查看了帧1并找到了相匹配的球体,它似乎移动了一个帧宽(我知道要少一些)的距离,并向上移动了一些。这让我们得到了运动矢量。另外,包含两个球体的宏块之间的差异似乎非常小(猜测的)。

2.然后我在同一帧内搜索,马上意识到相同帧里面并没有包含球体的其他宏块。看来这次运气不太好,没有在同一帧内找到匹配的宏块。

从上面那些示例中,我们都学到了什么?

1.编码器搜索匹配宏块以减少需要传输的数据的大小,整个过程通过运动估计和补偿来完成,这使得编码器可以在另一帧内发现宏块的水平和垂直位移。

2.编码器可以在同一帧内(帧内预测)和相邻帧内(帧间预测)搜到匹配的宏块。

3.它比较每个宏块的帧间和帧内预测结果,并选出最佳结果。这个过程被称为“模式选择”,我认为这是视频编码器最核心的部分。

现在,看完对帧内预测和帧间预测的快速介绍,让我们来学习I帧、P帧和B帧吧!

什么是I帧?

I帧或关键帧或帧内帧(I-frame or Key-Frame or Intra-frame)仅由帧内预测的宏块组成。

I帧中的每个宏块只能在同一帧内匹配其他宏块,这意味着,它只能利用帧内“空间冗余”来进行压缩。空间冗余是一个术语,用来指单个帧的像素之间的相似性。

I帧在不同的视频编解码器中以不同的形式出现,如IDR、CRA或者BLA。这些不同类型的I帧本质相同:都不存在时域预测。

I帧有很多用处,在我们学习P帧和B帧之后,我们再来研究。

什么是P帧?

P帧代表预测帧,除了空域预测以外,它还可以通过时域预测来进行压缩。P帧参考前面的帧进行运动估计。P帧中的每个宏块都可以被:

  • 时域预测
  • 空域预测
  • 跳过(skipped)(是指让解码器复制前一帧内的位于相同位置的宏块——0运动向量)

我制作了一张插图来说明其中的重点。上图中显示了I帧和P帧。如前面讨论,P帧参考前面的I帧或者P帧。图中,帧的编码、解码顺序与它们呈现在用户面前的顺序一致。这是因为P帧只参考前面的图像来进行编码。

什么是B帧?

B帧可以参考在其前后出现的帧。B帧中的B就代表双向(Bi-Directional)。如果你的视频编解码器使用基于宏块的压缩(如H.264/AVC所做的一样),那么B帧中的每个宏块都可以:

  • 后向预测(使用未来的帧)
  • 前向预测(使用过去的帧)
  • 无帧间预测,仅帧内预测
  • 完全跳过(帧内或帧间预测)

由于B帧可以参考和插入在它之前和之后发生的两个(或更多)帧(在时间维度上),所以它可以显著降低帧的大小,同时保持视频质量。B帧能够利用空间冗余和时间冗余(未来的帧和过去的帧),这使得它在视频压缩中非常有用。

但是,B帧是资源密集型——无论是从编码侧还是解码侧看,让我们来看看原因

想要理解B帧的作用,我们需要先理解呈现/显示顺序和解码顺序的概念。

以I帧和P帧为例。如果你只使用这两种类型的帧,那么每一帧要么参考自身(I 帧),要么参考前一帧(P 帧)。因此,帧可以以相同的顺序进出编码器。这里,呈现顺序(或显示顺序)与编码、解码顺序相同。

但如果某一帧要参考未来显示的一帧,你要怎么做呢?这是我们在使用B帧压缩时经常遇到的情况。下图中显示了一个GOP(group of pictures)结构,GOP是一组连续的画面,在每一个mini-GOP中,都使用了两个B帧和一个P帧,也就是IBBPBBP。

解码器端也是如此操作。

按照解码顺序,解码器先解码帧1(I帧),然后是帧2(P帧)。但它却无法显示帧2,因为在解码顺序中的实际上是帧4!所以,解码器需要将帧2(按解码顺序)放入缓冲区,然后等待显示它的时机。

所以,编码器和解码器需要在内存中维护两个“顺序”或“序列”:一个将帧放置在正确的显示顺序中,另一个用于将帧按照编码和解码所需顺序放置。

由于重新排序的要求,B帧会影响解码器缓冲区的大小,并增加延迟。

这就是为什么许多系统在压缩一个B帧时,对可用作参考的帧数做出严格的限制的原因。按照同样的思路,H.264/AVC的Baseline profile因为瞄准低端设备的,所以不允许使用B帧或Slice。

参考B帧和非参考B帧

我们在上文中学过,B帧可以参考两帧或者多帧,通常,(根据其位置)一帧在前,一帧在后。我们也已知道,I帧不参考任何帧,P帧只参考前面的帧。那么问题来了——任何帧都能使用B帧作为它的参考帧吗?

答案是肯定的。

  • 如果B帧可以作为参考帧,它就被称为参考B帧。
  • 如果B帧不用作参考帧,它便被称为非参考B帧。

在比特流中标明参考B帧和非参考B帧非常重要,因为解码器需要在DBP(Decoded Picture Buffer,解码图像缓存)中存储参考帧。

如果某一帧被标记为非参考B帧,但却将其用作参考帧,那么解码器很可能崩溃。因为解码器大概率在解码和显示之后就已经删除此帧。

与非参考B帧相比,大部分解码器在量化参考B帧时会获得更好的质量,从而减少传播损失。

在视频压缩/流化中使用I、P和B帧

在理解了I帧、P帧和B帧的工作原理之后,我们来解决一个重要问题:为什么要使用它们?

在下面内容中,我们会学习I帧、P帧和B帧在视频压缩中最重要的用例。

在哪里使用I帧?

我们在前面的部分了解到,I帧可以被独立地编码、解码,这使得它在视频压缩中得到广泛应用。

刷新视频质量

I帧的插入通常表示GOP(或视频片段)的结束。I帧压缩不依靠前一帧编码,从而可以刷新视频质量。正因为I帧在保持视频质量方面有如此重要的作用,所以通常情况下,编码器会在大小和质量方面偏向I帧。在编码高质量的I帧后,编码器便可以使用该I帧作为参考图像来压缩P帧和B帧。

那I帧只能用于刷新视频质量吗?不仅如此。

恢复比特流错误

我们之前说过,I帧可以被独立地编码和解码。这意味着I帧可用于恢复视频文件或视频流中的灾难性故障。

我们来看看是它是如何做到的。

如果P帧和参考B帧遭到破坏,其他所有依赖于它们的帧就不能完整解码,这会直接导致视频故障。视频通常无法从此类问题中恢复。然而,当被破坏的视频流到达I帧,因为I帧被独立地编码解码,所以视频问题可以从I帧恢复。

这种I帧通常被称为IDR帧(Instantaneous Decoder Refresh,即时解码刷新),并且这种不参考I帧之前图像的行为被称为闭合GOP(Closed GOP)。

IDR帧通常在ABR流中表示视频的某个新片段。由IDR帧开始,平台可以确保新片段能够独立于其他片段被解码。即使由于传输问题导致一些片段损坏或丢失,这一特性也能保证视频可以继续播放。

Trick Modes(快进快退)

最后,关键帧对于Trick Modes来说至关重要!

如果想在一个视频中快进快退,则在视频开始时需要一个I帧,对吧?

假设你搜索到的是P帧或者B帧,但解码器已经从内存中删除了参考帧,你该怎么重建它们呢?视频播放器很自然地会找到一个起始点(I帧)并成功解码,然后从这一点开始播放。

这又引出另一个有趣的事情。

如果你的关键帧在视频中相隔时间很长,假设它们之间间隔20秒,那么你的用户只能以20秒为增量进行快进快退,这样的体验非常糟糕!

如果关键帧放置太多,那么虽然快进快退体验会很棒,但这时候视频就太大了,可能导致网路缓冲等问题。

所以设计出最佳的GOP和mini-GOP结构真的是一项平衡的艺术。

在哪里使用P帧和B帧?

人们经常会问:在哪里、什么时候以及如何使用P帧和B帧?

如果你已经理解上文中所描述的P帧和B帧的工作原理,那么你就知道P帧和B帧可以在减少视频大小的同时,保证视频质量。这就是它们的主要用途!在合适的位置插入P帧和B帧可以减小视频文件尺寸或者比特率,并且仍能保持一定的视频质量水平。

基于你所使用的GOP和mini-GOP结构,使用相关QP值压缩P帧和B帧(被参考或者不被参考),你就可以达到目标比特率或视频质量。

 小 结

我希望这篇关于I帧、P帧和B帧的文章能够帮助你增加关于视频压缩的知识。想要更深入地理解它们,你可以下载静态编译好的 FFmpeg 版本,并在 FFmpeg 中使用 GOP、no-b-frame 相关设置来查看视频的大小及其质量如何变化。

本文已获得作者Krishna Rao Vijayanagar授权发布,特此感谢。

原文链接:https://ottverse.com/i-p-b-frames-idr-keyframes-differences-usecases/


扫描图中二维码了解大会更多信息

Easy Tech:什么是I帧、P帧和B帧?相关推荐

  1. 【计算机网络】数据链路层 : 选择重传协议 SR ( 帧分类 | “发送方“ 确认帧、超时事件 | “接受方“ 接收帧机制 | 滑动窗口长度 | 计算示例 )★

    文章目录 一. 选择重传协议 ( SR ) 引入 二. 选择重传协议 ( SR ) 帧分类 三. 发送方 事件 ( 确认帧.超时事件 ) 四. 接收方 事件 ( 接收帧 ) 五. 滑动窗口长度 五. ...

  2. pyrealsense2 frame_metadata_value类(帧的元数据)(帧的元数据指可能针对每个单独的帧公开的一组只读属性)

    文章目录 from frame_metadata_value.py 问题 from frame_metadata_value.py # encoding: utf-8 # module pyreals ...

  3. 平滑动画 每秒60帧 -- 16ms内绘完一帧

    大多数Android显示系统是以每秒钟60帧的频率工作的(专业点说,叫60Hz).为获得更平滑的动画,就必须具有每秒钟处理60帧的能力--意味着每帧只能花费16毫秒的时间.如果这个过程超过16毫秒,动 ...

  4. Easy Tech:什么是MPEG-DASH协议

    点击上方"LiveVideoStack"关注我们 翻译 | Alex 技术审校 | 赵军 本文来自OTTVerse,作者为Krishna Rao Vijayanagar. MPEG ...

  5. ffmpeg如何在结尾添加帧_一种“视频帧对齐”的测试方案实践

    点击蓝字?关注[测试先锋],不再迷路!一起成为互联网测试精英,前瞻测试技术-导语全参考清晰度测算的时候,输入两个视频帧序列,但是视频帧序列没有对齐,怎么知道丢了哪帧?又怎么知道补回哪一帧?今天介绍一种 ...

  6. html帧内容,html将内容从一个帧移动到另一个帧

    所以我把一个本地运行的网页放在一起,目前有2个框架 - 一个是导航栏,另一个是内容,用导航栏中的链接定义.这是在Internet Explorer 8中运行的,不幸的是必须保持这种状态. 从长远来看, ...

  7. 为什么游戏帧数要到 60 帧每秒才流畅,而电影帧数只有24FPS?

    首先要说的是电影就是24FPS也不如60FPS的流畅,对比就可以看出来,但是24FPS不会让人觉得卡,甚至12FPS都不会让人觉得卡,而24FPS的游戏能让人很明显的感受到卡,12FPS就是幻灯片了, ...

  8. Android性能优化 _ 大图做帧动画卡?优化帧动画之 SurfaceView滑动窗口式帧复用

    (ps:粗斜体表示引导方案逐步进化的关键点) SurfaceView逐帧解析 & 帧复用 简单回顾下上一篇的内容:原生帧动画在播放前解析所有帧,对内存压力大.SurfaceView可以精细地控 ...

  9. 【H.264/AVC视频编解码技术详解】二十三、帧间预测编码(1):帧间预测编码的基本原理

    <H.264/AVC视频编解码技术详解>视频教程已经在"CSDN学院"上线,视频中详述了H.264的背景.标准协议和实现,并通过一个实战工程的形式对H.264的标准进行 ...

最新文章

  1. 手撕面试题:多个线程交替打印问题
  2. 一份值得收藏的,互联网电商购物车架构演变案例
  3. matlab平滑曲线_说说地震波的那些事儿(二)——地震影响曲线
  4. 周鸿祎:过去只能在虚拟世界里发起的网络攻击,现在都可以通过物联网直达生产一线...
  5. java多线程测试框架(含入参和返回值)
  6. 被迫学计算机,电脑强迫人学习
  7. Windows 7平台安装Oracle Client 10g版本时需要做的一点变更
  8. OpenStack的部署T版(六)——Neutron组件
  9. python一节课多久_第一节课 python简介
  10. Apsara Stack 技术百科 | 可运营的行业云,让云上资源跑起来
  11. 推荐!京东开源姿态跟踪新框架LightTrack!
  12. 性能测试第一步——查看设备的硬件配置
  13. 零基础转行Web前端开发自学靠谱吗?菜鸟学习前端的方法分享
  14. 使用JavaScript(jQuery或Vanilla)选中/取消选中复选框?
  15. img 转esxi vmdk_KVM qcow2、raw、vmdk等镜像格式和转换
  16. matlab波浪力的数值模拟,【干货】二维波浪水槽以及波浪传播变形的数值模拟(附详细步骤)...
  17. DBC2000数据库,DBC2000怎么设置?DBC2000架设传奇教程
  18. redo日志和undo日志
  19. 如何在计算机设置鼠标宏,鼠标宏怎么设置,教您鼠标如何设置宏
  20. C语言--逻辑判断题

热门文章

  1. 200815-C指针高级和链表
  2. 同步异步阻塞非阻塞杂记
  3. 环信集成 2---基于环信Demo3.0,实现单聊功能
  4. [HDU 4344]Mark the Rope(Pollard_rho+Miller_Rabin)
  5. 语句的输入和输出 数据类型 运算符
  6. mongodb - 查看正在执行的操作
  7. 扩展GridView控件——为内容项添加拖放及分组功能
  8. MyBatis第四天
  9. 关于子网划分的几个捷径
  10. 详解JRE和JDK的区别