H.264编码及AAC编码基础 2

简介: H.264编码及AAC编码基础

2、H.264 编码原理与实现

①、前言

H264 在视频采集到输出中属于编解码层次的数据,如下图所示,是在采集数据后做编码压缩时通过编码标准编码后所呈现的数据。

②、H264 相关概念

<1>、序列

H264 编码标准中所遵循的理论依据个人理解成:参照一段时间内相邻的图像中, 像素、 亮度与色温的差别很小。

所以当面对一段时间内图像我们没必要去对每一幅图像进行完整一帧的编码,而是可以选取这段时间的第一帧图像作为完整编码,而下一幅图像可以记录与第一帧完整编码图像像素、亮度与色温等的差别即可,以此类推循环下去。

什么叫序列呢?上述的这段时间内图像变化不大的图像集我们就可以称之为一个序列。 序列可以理解为有相同特点的一段数据。

<2>、帧类型

H264 结构中,一个视频图像编码后的数据叫做一帧,一帧由一个片(slice)或多个片组成,一个片由一个或多个宏块(MB)组成,一个宏块由 16x16 的 yuv 数据组成。宏块作为 H264 编码的基本单位。


在 H264 协议内定义了三种帧,分别是 I 帧、B 帧与 P 帧。

<3>、GOP(画面组,图像组)

GOP 我个人也理解为跟序列差不多意思,就是一段时间内变化不大的图像集。

GOP 结构一般有两个数字,如 M=3,N=12。M 指定 I 帧和 P 帧之间的距离,N 指定两个 I 帧之间的距离。

上面的 M=3,N=12,GOP 结构为: IBBPBBPBBPBBI。


在一个 GOP 内 I frame 解码不依赖任何的其它帧,p frame 解码则依赖前面的 I frame 或 P frame,B frame 解码依赖前最近的一个 I frame 或 P frame 及其后最近的一个 P frame。

<4>、IDR 帧(关键帧)

在编码解码中为了方便,将 GOP 中首个 I 帧要和其他 I 帧区别开,把第一个 I 帧叫 IDR,这样方便控制编码和解码流程,所以 IDR 帧一定是 I 帧,但 I 帧不一定是 IDR 帧;IDR 帧的作用是立刻刷新,使错误不致传播,从 IDR 帧开始算新的序列开始编码。I 帧有被跨帧参考的可能,IDR 不会。


I 帧不用参考任何帧,但是之后的 P 帧和 B 帧是有可能参考这个 I 帧之前的帧的。IDR 就不允许这样, 例如:

IDR1 P4 B2 B3 P7 B5 B6 I10 B8 B9 P13 B11 B12 P16 B14 B15

这里的 B8 可以跨过 I10 去参考 P7

IDR1 P4 B2 B3 P7 B5 B6 IDR8 P11 B9 B10 P14 B11 B12

这里的 B9 就只能参照 IDR8 和 P11,不可以参考 IDR8 前面的帧

作用:

H.264 引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR 图像时,立即将参考帧队列清空,

将已解码的数据全部输出或抛弃,重新查找参数集, 开始一个新的序列。 这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR 图像之后的图像永远不会使用 IDR 之前的图像的数据来解码。

③、H264 压缩方式

H264 采用的核心算法是帧内压缩和帧间压缩, 帧内压缩是生成 I 帧的算法, 帧间压缩是生成 B 帧和 P 帧的算法。

帧内(Intraframe)压缩也称为空间压缩(Spatialcompression)。当压缩一帧图像时,仅考虑本帧的数据而不考虑相邻帧之间的冗余信息,这实际上与静态图像压缩类似。帧内一般采用有损压缩算法,由于帧内压缩是编码一个完整的图像,所以可以独立的解码、显示。帧内压缩一般达不到很高的压缩,跟编码 jpeg 差不多

帧间(Interframe)压缩的原理是:相邻几帧的数据有很大的相关性,或者说前后两帧信息变化很小的特点。也即连续的视频其相邻帧之间具有冗余信息,根据这一特性,压缩相邻帧之间的冗余量就可以进一步提高压缩量,减小压缩比。帧间压缩也称为时间压缩(Temporalcompression),它通过比较时间轴上不同帧之间的数据进行压缩。帧间压缩一般是无损的。帧差值(Framedifferencing)算法是一种典型的时间压缩法,它通过比较本帧与相邻帧之间的差异,仅记录本帧与其相邻帧的差值,这样可以大大减少数据量。

压缩方式说明

  • Step1:分组,也就是将一系列变换不大的图像归为一个组,也就是一个序列,也可以叫 GOP(画面组) ;
  • Step2:定义帧,将每组的图像帧归分为 I 帧、P 帧和 B 帧三种类型;
  • Step3:预测帧,以 I 帧做为基础帧,以 I 帧预测 P 帧,再由 I 帧和 P 帧预测 B 帧;
  • Step4:数据传输,最后将 I 帧数据与预测的差值信息进行存储和传输。

④、H264 分层结构

H.264 原始码流(裸流)是由一个接一个 NALU 组成,它的功能分为两层,VCL(视频编码层)和 NAL(网络提取层)

H264 的主要目标是为了有高的视频压缩比和良好的网络亲和性,为了达成这两个目标,H264 的解决方案是将系统框架分为两个层面,分别是视频编码层面(VCL) 和网络抽象层面(NAL),如下图;

VCL 层(视频编码层)是对核心算法引擎、块、宏块及片的语法级别的定义,负责有效表示视频数据的内容,最终输出编码完的数据 SODB

对视频的原始数据进行压缩。

NAL 层(视频数据网络抽象层)定义了片级以上的语法级别(如序列参数集参数集和图像参数集,针对网络传输,后面会描述到),负责以网络所要求的恰当方式去格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。NAL 层将 SODB 打包成RBSP 然后加上 NAL 头组成一个 NALU 单元。

因为 H264 最终还是要在网络上进行传输,在传输的时候,网络包的最大传输单元是 1500 字节,一个 H264 的帧往往是大于 1500 字节的,所以需要将一个帧拆成多个包进行传输。这些拆包、组包等工作都在 NAL 层去处理

<1>、SODB 与 RBSP 的关联

具体结构如下图所示:

  • SODB:数据比特串,是编码后的原始数据;
  • RBSP:原始字节序列载荷,是在原始编码数据后面添加了结尾比特,一个 bit“1”和若干个比特“0”,用于字节对齐。
<2>、SODB RBSP EBSP 的区别

最原始, 未经过处理的编码数据

因为它是流的形式,所以长度不一定是 8 倍数,它是由 VLC 层产生的。由于我们计算机是以 8 倍数去处理数据所以计算机在处理 H264 时,就需要 RBSP。

RBSP(Raw Byte Sequence Payload,原始字节序列载荷)

在 SODB 的后面填加了结尾 bit(RBSP trailing bits 一个 bit ‘1’) 若干 bit ‘0’,以便字节对齐。

由于它是一个压缩流,SODB 不知道是在何处结束,所以算法在 SODB 最后一位补一个 1,没有按字节对齐的则补 0。

EBSP(Encapsulated Byte Sequence Payload,扩展字节序列载荷)

NALU 的起始码为 0x000001 或 0x00000001(起始码包括两种:3 字节(0x000001)和 4 字节(0x00000001),在 SPS、PPS 和 Access Unit 的第一个 NALU 使用 4 字节起始码,其余情况均使用 3 字节起始码。)

在生成压缩流之后,在每一帧的开头加一个起始位,这个起始位一般是 00 00 00 01 或者是 00 00 01。所以在 h264 码流中规定每有两个连续的 00 00,就增加一个 0x03。

仿校验字节(0x03)

同时 H264 规定,当检测到 0x000000 时,也可以表示当前 NALU 的结束。那这样就会产生一个问题,就是如果在 NALU 的内部,出现了 0x000001 或 0x000000 时该怎么办?

在 RBSP 基础上填加了仿校验字节(0x03)它的原因是:在 NALU 加到 Annexb 上时,需要填加每组 NALU 之前的开始码 StartCodePrefix,如果该 NALU 对应的 slice为一帧的开始则用 4 位字节表示,0x00000001,否则用 3 位字节表示 0x000001,为了使 NALU 主体中不包括与开始码相冲突的,在编码时,每遇到两个字节连续为 0,就插入一个字节的 0x03。解码时将 0x03 去掉。也称为脱壳操作。关系图:

为什么要弄一个 EBSP 呢?

EBSP 相较于 RBSP, 多了防止竞争的一个字节: 0x03。

我们知道,NALU 的起始码为 0x000001 或 0x00000001,同时 H264 规定,当检测到 0x000000 时,也可以表示当前 NALU 的结束。那这样就会产生一个问题,就是如果在 NALU 的内部,出现了 0x000001 或 0x000000 时该怎么办?

所以 H264 就提出了“防止竞争”这样一种机制,当编码器编码完一个 NAL 时,应该检测 NALU 内部,是否出现如下左侧的四个序列。当检测到它们存在时,编码器就在最后一个字节, 插入一个新的字节:0x03。

⑤、H264 码流结构

在具体讲述 NAL 单元前,十分有必要先了解一下 H264 的码流结构;在经过编码后的 H264 的码流如下图所示,从图中我们需要得到一个概念,H264 码流是由一个个的 NAL 单元组成,其中 SPS、PPS、IDR 和 SLICE 是 NAL 单元某一类型的数据。

⑥、H264 的 NAL 单元

<1>、H264 的 NAL 结构

在实际的网络数据传输过程中 H264 的数据结构是以 NALU(NAL 单元)进行传输的,传输数据结构组成为 [NALU Header]+[RBSP],如下图所示:

VCL 层编码后的视频帧数据,帧有可能是 I/B/P 帧,这些帧也可能是属于不同的序列之中,同一序列也还有相应的序列参数集与图片参数集;想要完成准确无误视频的解码,除了需要 VCL 层编码出来的视频帧数据,同时还需要传输 序列参数集和 图像参数集等等。


上面知道 NAL 单元是作为实际视频数据传输的基本单元,NALU 头是用来标识后面 RBSP 是什么类型的数据,同时记录 RBSP 数据是否会被其他帧参考以及网络传输是否有错误。


<2>、NAL 头

NAL 单元的头部是由 forbidden_bit(1bit),nal_reference_bit(2bits)(优先级),nal_unit_type(5bits)(类型)三个部分组成的, 组成如下图所示:


F(forbiden):禁止位,占用 NAL 头的第一个位,当禁止位值为 1 时表示语法错误

NRl:参考级别,占用 NAL 头的第二到第三个位;值越大, 该 NAL 越重要

Type:Nal 单元数据类型,也就是标识该 NAL 单元的数据类型是哪种,占用 NAL 头的第四到第 8 个位

<3>、NAL 单元数据类型

NAL 类型主要就是下面图中这些类型每个类型都有特殊的作用;

在具体介绍 NAL 数据类型前, 有必要知道 NAL 分为 VCL 和非 VCL 的 NAL 单元。


而另外一个需要了解的概念就是参数集(Parameter sets) ,参数集是携带解码参数的 NAL 单元,参数集对于正确解码是非常重要的,在一个有损耗的传输场景中,传输过程中比特列或包可能丢失或损坏,在这种网络环境下,参数集可以通过高质量的服务来发送,比如向前纠错机制或优先级机制。

非 VCL 的 NAL 数据类型:


SPS(序列参数集):SPS 对如标识符、帧数以及参考帧数目、解码图像尺寸和帧场模式等解码参数进行标识记录。

PPS(图像参数集):PPS 对如熵编码类型、有效参考图像的数目和初始化等解码参数进行标志记录。

SEI(补充增强信息):这部分参数可作为 H264 的比特流数据而被传输,每一个 SEI 信息被封装成一个 NAL 单元。SEI 对于解码器来说可能是有用的,但是对于基本的解码过程来说,并不是必须的。

VCL 的 NAL 数据类型:


头信息块,包括宏块类型,量化参数,运动矢量。这些信息是最重要的,因为离开他们,被的数据块种的码元都无法使用。 该数据分块称为 A 类数据分块。

帧内编码信息数据块,称为 B 类数据分块。它包含帧内编码宏块类型,帧内编码系数。对应的 slice 来说,B 类数据分块的可用性依赖于 A 类数据分块。和帧间编码信息数据块不通的是,帧内编码信息能防止进一步的偏差,因此比帧间编码信息更重要。

帧间编码信息数据块,称为 C 类数据分块。它包含帧间编码宏块类型,帧间编码系数。它通常是 slice 种最大的一部分。帧间编码信息数据块是不重要的一部分。它所包含的信息并不提供编解码器之间的同步。C 类数据分块的可用性也依赖于 A 类数据分块,但于 B类数据分块无关。

以上三种数据块每种分割被单独的存放在一个 NAL 单元中,因此可以被单独传输

目录
相关文章
|
1月前
|
存储 编解码 缓存
H.264编码
H.264编码
20 0
|
7月前
|
存储 编解码 算法
H.264编码及AAC编码基础 1
H.264编码及AAC编码基础
80 0
|
7月前
|
存储 编解码 算法
H.264编码及AAC编码基础 3
H.264编码及AAC编码基础
102 0
|
编解码 API 语音技术
Opus从入门到精通(七)Opus编码基础之认识声音
前面我们分析完Opus的编解码api使用,封装原理等,接下来我们准备分析Opus编码原理.Opus编码是一个复杂的工作,我们需要做一些基本铺垫,包括认识声音,压缩编码基础.认识音频有助于我们了解音频特征,不仅对语音有助于我们理解编码技术,同时在语音识别,TTS等场景提供帮助
382 0
Opus从入门到精通(七)Opus编码基础之认识声音
|
机器学习/深度学习 存储 编解码
Opus从入门到精通(八)Opus编码基础之压缩编码
莫尔斯码就是大家熟悉的电报码,它的发明为人类做出了巨大的贡献.该码采用"."和"-"来表示26个英文字母,这实质上还是二进制码(点为"0",而杠为"1"),但是它没有采用固定字长的编码方式,而是采用了常用字母用短码表示(如E用"."表示,T用"-"表示),不常用字母用长码表示(如Z用"--.."表示,j用"-..-"表示)的变长编码方式.通过对英文单词进行大量统计,找出各字母的概率,最后确定有12个字母出现概率最低,用4bit数字表示,有8个字母出现概率较低,用3bit数字表示;有4个字母出现概率较高,用2bit数字表示;有两个字母出现概率最高,用1bit表示,共26个字母.
415 0
|
编解码 算法
白话H.265/HEVC和H.264/AVC编码结构
写在前面 在信息化时代,视频技术和应用的发展,特别是高清(HD)、超高清(UHD)、多视点(MultiView)视频、VR/AR技术的兴起,海量的视频信息已如潮涌般深入到我们工作和生活的方方面面。随着5G通信技术逐渐铺开落地,移动端设备的传输数据量会进一步增加。
2442 0
|
内存技术
ffmpeg4音频pcm转aac编码
本文是基于ffmpeg4开发的音频编码器开源,并对其中出现的一些bug与各界同行探讨。
327 0
ffmpeg4音频pcm转aac编码