问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

H.264/h265编码与GOP组、I帧、B帧、P帧详解

创作时间:
作者:
@小白创作中心

H.264/h265编码与GOP组、I帧、B帧、P帧详解

引用
简书
1.
https://www.jianshu.com/p/c50464be920e

H.264编码技术是当前最流行的视频压缩标准之一,广泛应用于视频会议、流媒体、高清电视和视频监控等多个领域。本文将为您详细介绍H.264编码中的几个核心概念:GOP组、I帧、B帧和P帧,以及PTS、DTS等关键参数。


image-20241016062524877.png

视频编码技术是数字媒体领域的一项重要技术,它可以帮助我们以更小的文件大小存储和传输高质量的视频内容。H.264编码,作为当前最流行的视频压缩标准之一,广泛应用于视频会议、流媒体、高清电视和视频监控等多个领域。本文将为您详细介绍H.264编码中的几个核心概念:GOP组、I帧、B帧和P帧。

一、H.264编码简介

H.264,也称为MPEG-4 AVC(Advanced Video Coding),是一种高效的视频编码标准。它通过减少冗余数据,实现对视频内容的高压缩比,同时保持较高的图像质量。H.264编码技术是ITU-T和ISO/IEC共同开发的结果,被广泛认为是目前最高效的视频编码标准。

1、GOP组(Group of Pictures)

在H.264编码中,视频被组织成一系列的GOP组。每个GOP组由一个I帧开始,后面跟随多个P帧和B帧。GOP组的结构和大小对视频的压缩效率和解码性能有重要影响。

在视频编码序列中,GOP即Group of picture(图像组),指两个I帧之间的距离,Reference(参考周期)指两个P帧之间的距离。两个I帧之间形成一组图片,就是GOP(Group Of Picture)。

2、I帧(Intra-coded Picture)

I帧,也称为内码帧或关键帧,是完全独立于其他帧的帧。它包含了完整的图像信息,不依赖于其他帧进行解码。I帧在视频流中起到参考点的作用,其他帧(P帧和B帧)可以依赖于I帧进行解码。

3、P帧(Predictive-coded Picture)

P帧,也称为预测编码帧,是一种依赖于前一个I帧或P帧的帧。P帧通过预测和运动补偿技术来减少数据量,只存储与前一个参考帧之间的差异信息。这使得P帧的文件大小远小于I帧,但解码时需要依赖于参考帧。

4、B帧(Bidirectional Predictive-coded Picture)

B帧,也称为双向预测编码帧,是一种利用前后两个参考帧来预测当前帧内容的帧。B帧可以提供比P帧更高的压缩效率,因为它可以利用两个方向的信息来减少数据量。然而,B帧的解码复杂性也更高,因为它需要同时访问前后两个参考帧。

5、IDR帧 (Instantaneous Decoding Refresh)

IDR的全称是Instantaneous Decoding Refresh,中文叫做立即解码刷新。IDR一定是I帧,但I帧不一定是IDR。一旦出现IDR,就表示清除前面的序列,并且立刻渲染当前的IDR帧。

在每个H.264流的开头,都会出现这样的序列:SPS帧→PPS帧→IDR帧→其余SLICE,并且SPS、PPS、IDR三种帧必定是搭配出现的,缺一不可,如果少了其中任何一帧,都会导致后续视频流解码异常。

我们已经知道 GOP是对视频进行了若干的分组,分组之后,每一组之间他们是有明显的差别的。如果我们所有的视频是一串连续播下来,但是如果中间 某个地方出现了错误,那后面的视频就很难进行恢复了,因为是相互依赖的。而有了 IDR帧之后,当遇到IDR帧时,在解码器端,解码器会将缓冲区中的所有数据全部清空,全部重新来过,所以此时缓冲区中的第一针是IDR帧,一组GOP中的的第一帧是IDR帧,是关键帧,是帧内压缩,不依赖于其他帧。所以在缓冲区找到第一个IDR帧之后,后面再来的数据 就是都依赖于这个IDR帧,直到下一个IDR帧到来 即下一组GOP视频帧到来,如此就避免了错误的传播。

6、帧与分组的关系

一组GOP中 第一帧是 IDR帧,后面接着连续的三个B帧,在后面连着P帧,再接三个B帧,循环反复。

解码特点:

  1. 先解码I帧
  2. 解码第一个P帧
  3. 解码前三个B帧,这3个B帧依赖于 IDR帧和第一个P帧,只有IDR帧和第一个P帧解码完后,才能解码前三个B帧,而B帧与B帧之间是没有参考关系的,所以这就回扣到,前面所说的 B帧是前后参考帧,这里的前后,指的就是前面的IDR帧和后面的P帧,只有当前后参考帧解码后,才解码自己。
  4. 解码第二个出现的P帧
  5. 解码 再次连续的3个B帧,这里的3个B帧 依赖于 ,前后两个P帧,即第一个和第二个P帧。是他的前后参考帧。

注意 播放的顺序与解码顺序不同,虽然P帧相对于B帧是先解码,但是播放的帧的顺序 就是排列的顺序。当所有的帧解码完成之后,他们都成了一个一个的完整的图像,所以用播放器播放的时候,就是按照顺序播放即 I B B B P B B B P …

7、PTS和DTS

a、为什么会有PTS和DTS的概念

通过上面的描述可以看出:P帧需要参考前面的I帧或P帧才可以生成一张完整的图片,而B帧则需要参考前面I帧或P帧及其后面的一个P帧才可以生成一张完整的图片。这样就带来了一个问题:在视频流中,先到来的 B 帧无法立即解码,需要等待它依赖的后面的 I、P 帧先解码完成,这样一来播放时间与解码时间不一致了,顺序打乱了,那这些帧该如何播放呢?这时就引入了另外两个概念:DTS 和 PTS。

b、PTS和DTS

先来了解一下PTS和DTS的基本概念:

  • DTS(Decoding Time Stamp):即解码时间戳,这个时间戳的意义在于告诉播放器该在什么时候解码这一帧的数据。
    DTS主要用于视频的解码,在解码阶段使用

  • PTS(Presentation Time Stamp):即显示时间戳,这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。
    PTS主要用于视频的同步和输出.在display的时候使用.在没有B frame的情况下.DTS和PTS的输出顺序是一样的

虽然 DTS、PTS 是用于指导播放端的行为,但它们是在编码的时候由编码器生成的。

在视频采集的时候是录制一帧就编码一帧发送一帧的,在编码的时候会生成 PTS,这里需要特别注意的是 frame(帧)的编码方式,在通常的场景中,编解码器编码一个 I 帧,然后向后跳过几个帧,用编码 I 帧作为基准帧对一个未来 P 帧进行编码,然后跳回到 I 帧之后的下一个帧。编码的 I 帧和 P 帧之间的帧被编码为 B 帧。之后,编码器会再次跳过几个帧,使用第一个 P 帧作为基准帧编码另外一个 P 帧,然后再次跳回,用 B 帧填充显示序列中的空隙。这个过程不断继续,每 12 到 15 个 P 帧和 B 帧内插入一个新的 I 帧。P 帧由前一个 I 帧或 P 帧图像来预测,而 B 帧由前后的两个 P 帧或一个 I 帧和一个 P 帧来预测,因而编解码和帧的显示顺序有所不同,如下所示:

[图片上传失败...(image-c55178-1730278189662)]

假设编码器采集到的帧是这个样子的:

I B B P B B P

那么它的显示顺序,也就是PTS应该是这样:

1 2 3 4 5 6 7

编码器的编码顺序是:

1 4 2 3 7 5 6

推流顺序也是按照编码顺序去推的,即

I P B B P B B

那么接收断收到的视频流也就是

I P B B P B B

这时候去解码,也是按照收到的视频流一帧一帧去解的了,接收一帧解码一帧,因为在编码的时候已经按照 I、B、P 的依赖关系编好了,接收到数据直接解码就好了。那么解码顺序是:

I P B B P B B
DTS:1 2 3 4 5 6 7
PTS:1 4 2 3 7 5 6

可以看到解码出来对应的 PTS 不是顺序的,为了正确显示视频流,这时候我们就必须按照 PTS 重新调整解码后的 frame(帧),即

I B B P B B P
DTS:1 3 4 2 6 7 5
PTS:1 2 3 4 5 6 7

另外,并不是一定要使用B帧。在实时互动直播系统中,很少使用B帧。主要的原因是压缩和解码B帧时,由于要双向参考,所以它需要缓冲更多的数据,且使用的CPU也会更高。由于实时性的要求,所以一般不使用它。不过对于播放器来说,遇到带有B帧的H264数据是常有的事儿。在没有B帧的情况下,存放帧的顺序和显示帧的顺序就是一样的,PTS和DTS的值也是一样的。

SPS和PPS

  • SPS:(Sequence Parameter Set) 序列参数集
  • PPS:(Picture Parameter Set) 图像参数集

每个视频帧都包含至少一个NAL单元,对于I帧、P帧来说,因为内部数据比较多,所以可能会分为多个NAL单元。各帧的第一个NAL单元以起始码0x00000001或0x000001开头,表示从这里开始是一个新帧;从第二个NAL单元开始,后继NAL单元以0x000001开头,表示其后数据是前面NAL单元的接续。

起始码往后的一个字节,代表当前帧的类型,常见的帧类型有下列六种:

0x67,类型值为7,为SPS帧,表示序列参数集。
0x68,类型值为8,为PPS帧,表示图像参数集。
0x65,类型值为5,为IDR帧,即IDR图像,也称为关键帧。
0x41,类型值为1,为SLICE分片,表示P帧。
0x01,类型值为1,为SLICE分片,表示B帧。
0x06,类型值为6,为SEI帧,表示辅助增强信息。

二、视频花屏/绿屏

视频花屏/绿屏的原因

直播中的画面花屏、绿屏是实时视频传输中经常碰到的问题。这种问题的原因有很多,但通常与编码和传输的细节有关。以下为详细原因:

1、丢失关键帧

在视频流中,关键帧(I帧)为完整的帧,它不依赖于其他任何帧。而其后的预测帧(P帧)和双向预测帧(B帧)则依赖于关键帧来进行解码。这意味着:如果关键帧丢失,那么所有直到下一个关键帧的P帧和B帧都无法被正确解码,从而导致花屏、绿屏等问题。

2、Metadata的变化

视频流的metadata包含了视频的关键参数(如分辨率、帧率、编码格式等),如果直播中metadata发生变化,播放器可能无法适应这些变化,从而导致解码问题,如花屏或绿屏。

3、硬件编解码的兼容性问题

尤其在Android设备上,硬件编解码的实现差异可能导致一些兼容性问题。一些Android设备上的硬件编解码器可能实现得并不好,导致其兼容性不佳。

4、颜色格式不一致问题

视频流中的颜色格式需要在推流和播放两端保持一致,如果推流端和播放端使用的颜色格式不同,解码时可能会出现花屏或绿屏等问题。

视频花屏/绿屏的解决方案

1、丢失关键帧的解决策略:

使用不同的播放器(如ffplay、VLC、Potplayer)可以帮助确定问题是否源自源码流。在必须丢帧的情况下,应该丢弃整个GOP,从而避免只丢失部分帧导致的花屏问题。

2、Metadata的变化的解决策略:

保持直播过程中的编码参数稳定,避免metadata信息发生变化。在必须丢帧的情况下,应该丢弃整个GOP,从而避免只丢失部分帧导致的花屏问题。

3、硬件编解码的兼容性问题的解决策略:

解决这类问题的一个方法是切换到软件编解码进行对比。为了提高兼容性,避免硬编解码的问题,开发者可以考虑使用软编码和解码,或者根据具体设备制定白名单或黑名单。

4、颜色格式不一致问题:

解决这类问题的办法是统一推流和拉流两端的颜色格式。确保图像的格式与编码器匹配。例如,如果采集到的视频是NV21格式,但编码器只支持I420,那么需要转换格式。在场景切换,如前后摄像头切换时,确保视频尺寸适应编码器的要求。

总之,当直播中出现花屏或绿屏问题时,开发者和操作人员需要进行全面的检查和排查,从源头到播放端逐一检查,以确保音视频流的稳定和清晰。

音视频 PTS DPS

对于视频来说,

如果视频里的各帧编码是按照输入顺序来依次进行的,那么解码时间(DTS)和显示时间(PTS)应该是一致的。但大多数编码中,编码顺序与输入顺序并不一致,因为B帧的存在,所以DTS与PTS并不一致。

对于音频来说

音频的播放,也有 DTS、PTS 的概念,但是音频没有类似视频中 B 帧,不需要双向预测,所以音频帧的 DTS、PTS 顺序是一致的

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号