H264编码基础概念+格式分析
一、编码基础概念
1、为什么要进行视频编码?
视频由连续的画面构成,在视觉效果上类似于常见的GIF动画。当打开一张GIF图片时,其内部包含大量画面片。为了减少观看卡顿感,在实际应用中通常要求每秒至少展示16帧画面(常见配置为30帧/秒)。假如该视频是一个1280x720分辨率的视频,则未经编码的一秒钟文件大小为:
结果:1280×720×60≈843.75MB
所以不经过编码的视频根本没法保存,更不用说传输了。
2、视频压缩编码标准
在视频中包含了大量的重复信息。例如,在图像中相邻像素之间具有较强的关联性,在连续的帧之间呈现出高度的一致性特征。由于人眼对于某些细节并不敏感,在实际应用中往往可以通过去除这些重复的信息来提高传输效率和存储效果。将这些重复的信息去除后所实现的功能即为 video 编码的核心过程。
H.26X系列(由ITU[国际电传视讯联盟]主导)
H.261:主要在老的视频会议和视频电话产品中使用
H.263:主要用在视频会议、视频电话和网络视频上
H.264:H.264/MPEG-4第十部分,或称AVC(Advanced Video Coding,高级视频编码),是一种视频压缩标准,一种被广泛使用的高精度视频的录制、压缩和发布格式。
H.265:高效率视频编码(High Efficiency Video Coding,简称HEVC)是一种视频压缩标准,H.264/MPEG-4 AVC的继任者。可支持4K分辨率甚至到超高画质电视,最高分辨率可达到8192×4320(8K分辨率),这是目前发展的趋势,尚未有大众化编码软件出现
MPEG系列(由ISO[国际标准组织机构]下属的MPEG[运动图象专家组]开发)
MPEG-1第二部分:MPEG-1第二部分主要使用在VCD上,有些在线视频也使用这种格式
MPEG-2第二部分(MPEG-2第二部分等同于H.262,使用在DVD、SVCD和大多数数字视频广播系统中
MPEG-4第二部分(MPEG-4第二部分标准可以使用在网络传输、广播和媒体存储上
在编码所处理的信号时,在编码器中首先会生成该信号的预测值,并将其标记为预测信号(predicted signal)。
预测的方式:
时间上的预测(interprediction),亦即使用先前帧的信号做预测
空间上的预测 (intra prediction),亦即使用同一张帧之中相邻像素的信号做预测
接收到预测信号后,编码器通过计算当前信号与预测信号的差值来生成残差信号(residual signal),随后仅对计算出的残差进行编码。从而,在时间和空间维度上去除了部分冗余信息。
编译器并不会直接对残留信号执行编码操作,而是首先对该残留信号施加某种转换(其中一种常见的转换方式是采用离散余弦转换),随后对其进行量化处理,并进一步去除其在空间域和感知域中的剩余冗余信息.经过量化处理得到的量化系数,则会被应用熵编码技术,从而消除其中的统计特性所导致的剩余冗余信息.
二、H.264编码详解(AVC)
H.264是一种新型的编码标准,以其高效压缩率和优质图像质量著称,并且能够支持多种网络下的流媒体传输
相关理解:
在相邻几幅图像画面中,一般有差别的像素只有10%以内的点,亮度差值变化不超过2%,而色度差值的变化只有1%以内
所以对于一段变化不大图像画面,我们可以先编码出一个完整的图像帧A,随后的B帧就不编码全部图像,只写入与A帧的差别,这样B帧的大小就只有完整帧的1/10或更小!
B帧之后的C帧如果变化不大,我们可以继续以参考B的方式编码C帧,这样循环下去。
这段图像我们称为一个序列:序列就是有相同特点的一段数据
当某个图像与之前的图像变化很大,无法参考前面的帧来生成,那我们就结束上一个序列,开始下一段序列
也就是对这个图像生成一个完整帧A1,随后的图像就参考A1生成,只写入与A1的差别内容
2、H.264三种帧
在H.264标准中定义了三类特殊的视频数据单元。其中:
- I型(Intra)单元是基于自身像素直接完成完全码化的;
- P型(Predictive)单元基于前一单位进行压缩编码;
- B型(Bidirectional)单元则基于前后两个相邻单位进行压缩编码。
H264的主要编码方案包括 intra-frame compression 和 inter-frame compression:
I frames are generated by the intra-coding process;
The inter-coding process is responsible for generating B and P frames.
压缩方法:
分组处理:将多帧图像按一定规则分组处理(GOP),以减少运动矢量大小;避免过多的分组数量以降低计算复杂度。
定义框架:每组内的各幅图像被划分为三类别——I型、B型和P型;
预测层:采用I型框架作为基准层;生成P型编码映射表,并基于此生成P型编码映射表;基于现有结果生成B型编码映射表;
数据传输:最后将I型数据与其预测差值进行存储与传输处理。
GOP序列:
H264中图像按照序列进行组织,每个序列代表一段经过编码的图像数据流。
每个序列的第一个图像被称为 IDR 图像(Immediate Refresh Image),且每个 IDR 图像均为 I 帧。
a、H.264 引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR 图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。
b、这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。
c、IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。
一个序列就是一段内容差异不太大的图像编码后生成的一串数据流:
a、当运动变化比较少时,一个序列可以很长,因为运动变化少就代表图像画面的内容变动很小,所以就可以编一个I帧,然后一直P帧、B帧了。
b、当运动变化多时,可能一个序列就比较短了,比如就包含一个I帧和3、4个P帧。
在视频编码序列中,GOP即Group of picture(图像组),指两个I帧之间的距离。
I帧、P帧、B帧实际顺序&&编码顺序:


三、H.264分层设计
从概念上来看,H264算法划分为两个层次,VCL:视频编码层次,负责高效地表达内容,NAL:网络提取层次,负责按照符合网络需求的适当打包方式传送数据,这些所学的知识主要集中在VCL层次上
NAL的设计目的是针对不同类型的网络环境来包装数据为特定格式,并使由VCL生成的位(bit)字符串在多种网络环境下保持兼容性。
采用的方式为:
该系统采用将单帧数据封装进NA...
该结构由头信息与主体信息组成。
其头部标识符一般设置为全零加一的形式。
其头部标识符一般设置为全零加一的形式。
NAL封装流程如下:
I型、P型和B型帧分别被封装成一个或多个NALU以实现传输或存储。
每个I型帧之前都会有一个非VCL类型的NAL单元用于保存相关参数。
其中:
PPS(Picture Parameter Sets):图像参数集
SPS(Sequence Parameter Set):序列参数集
在H.264的实际数据包中:
通常带有这样的分隔符:
编码器编出的第一帧通常包含PPS与SPS信息块后紧跟I型帧,
随后是B型和P型等数据块

引言:
在国内直播行业的繁荣时期(注:ps: 其实大多都亏钱),许多观众也投身于技术领域中(注:ps: 其实就是搬运知识)。每天日复一日地学习音视频技术的相关知识(注:ps: 这里指的是音视频编码的核心原理),渐渐地越来越多的人摘下了音/视频技术的面纱(注:ps: 这里的"面纱"指的是其背后的复杂原理)。作为刚入门的新手,在实践中不断摸索前进。好了吧,别再浪费时间了。今天我们就来详细聊聊我们在视频编码中常用的 H.264 编码器这个概念(注:H.264 是一种先进的 video coding 标准),相信对于 H.264 编码器这个概念(注:H.264 encoder),我相信大家都有一定的了解。(注:但实际上每个人对它的理解可能各有不同))。不过由于其算法众多与复杂(注:算法众多与复杂),本博主也不会深入讲解过于专业的知识。(注:如果大家对此有浓厚兴趣的话,请继续关注我们的后续内容)。相反我会尽量避免涉及过于专业的知识。(注:当然啦!如果有相关背景的朋友可以在评论区指正我的理解哦))。通过本次讲解 ,我希望帮助大家更好地认识 H.264 编码器的核心组件与工作原理(注:当然啦!如果有相关背景的朋友可以在评论区指正我的理解哦)。
首先来一段大家都熟悉的官方话来介绍一下 H.264
H.264: H.264/AVC项目的设立旨在构建一套新的视频压缩标准,在低数据传输速率下仍能保障良好的视觉效果(例如较之MPEG-2、H.263或MPEG-4 Part 2等标准可降低至其一半或更低)。同时该方案要求在保证视频质量的同时不以显著增加开发难度为代价。
其主要优势体现在:
1)兼容性:支持多种主流通信网络架构
2)压缩效率:相较于H.263和MPEG-4等标准而言具有显著提升;现已成为基础技术之一
那么很明显,什么时候需要到压缩呢?当然是文件体积太大的时候啦,我们想想,所谓的视频,就是像小时候的连环画一样,在一秒内翻过 24 张以上的图片,就感觉图像是连续的了,这就是视频的原理。但是大家有没有想过,一张图片有多大呢?我们的屏幕分辨率按 1280 * 720 算的话,一秒钟的视频大概就 2.64 MB 了,大家想想,我们大部分的小伙伴为了下载个小嗨片省吃俭用才开了个 1M 的网线,然后连个直播都看不了是什么感觉。那肯定不能这样了,所以我们要进行压缩,而 H.264 不仅压缩比比较高,对网络的兼容性也非常好,所以大多数人做直播也就选择了 H.264 作为编码格式了。
编码流程:
那么 H.264 的编解码流程大致包括哪些环节呢?其实可以分成五个关键步骤:帧间与帧内预测(Estimation)、变换(Transform)与反变换(Inverse Transform)、量化(Quantization)与反量化(Inverse Quantization)、环路滤波(Loop Filter)以及熵编码(Entropy Coding)。
说白了就是非常复杂的技术细节,在这里就不展开具体细节了。具体细节就不太适合在这里展开讲解了。如果对这些技术感兴趣的朋友可以通过网络资源进一步了解。H.264详细文档
原理简介
H.264 原始数据流(又被统称为裸流),是由连续排列的 NALU(Non-Abstraction Layer Units)组成的。该数据流的功能可划分为两个主要部分:视频编码部分(VCL, Video Coding Layer)和网络抽象部分(NAL, Network Abstraction Layer)。
其中,在 VCL 处理后的输出即为编码后的视频数据序列。在 VCL 的数据进行传输或存储之前,在其基础上会进行进一步处理:首先会被映射到或封装成 NAL 单元(以下简称NALU)。每个NALU包含一个原始字节序列负荷(RBSP, Raw Byte Sequence Payload)、一组与之相关的NALU头部信息。
RBSP的基本结构包括:在原始编码数据后附加了一个结束位‘1’以及若干个‘0’位以实现字节对齐。

NAL 单元排列
如图所示,在编码架构中,NALU头与Rbsp组合相当于一个NalUnit。每个单元均通过独立的NALUE进行数据传输。实际上其核心架构基于NALU设计
一帧图片跟 NALU 的关联 :
究竟 NALU 是怎么由一帧图片变化而来的呀,H.264究竟为什么这么神奇?
一帧图片通过 H.264 编码器被转换成一个或多个片(slice),而装载这些片(slice)的载体称为 NALU,我们可以通过进一步了解 NALU 来深入探究其与片的关系。我们可以对 NALU 与片的关系进行研究分析。

图片编码后

NALU 结构
我们需要理解其中'片'的概念不同于'帧'。其中'帧'用于描述单张图像,'一帧即代表一张独立的图像'。而'片'则是H.264标准中提出的一种新概念,它是经过对图像进行编码处理后进行高效的分割和整合形成的。值得注意的是,每张图像至少包含一个或多个这样的'片',以确保视频数据的高效传输与解码过程中的完整性与准确性。
从图表中可以看出, slices (片)都由NALU加载并执行网络传输操作。然而这并不意味着NALU内部必须是切片,这是一个充分而不必要的条件.因为NALU还可能承载其他用于描述视频信息的模块.
什么是切片(slice)?
作为宏块(Macroblock)的支持结构(ps:下面将详细讲解这一概念),正是由于这一需求推动了这一技术的发展。为了实现其主要目标即是约束误码在其传播路径上的扩散,并确保其能够有效传递出去。
在实际应用中需要考虑的问题包括如何保证各分块间的独立传输?为此提出了一种新的编码方案。
其中分块内部及分块之间预测均需避免基于其他分块的信息作为参考依据。
那么片(slice)的具体结构,我们用一张图来直观说明吧:

我们可以通过理解得知一张/帧图象可以包含一个或多个分 slice (Slixe),每个 slice (Slixe)则由若干 Macroblocks (Macroblcok)组成。其中每个 slice (Slixe)最少含有一个 Macroblocks (Macro block),当其数量最多时,则整个 image (Image)被分割成单一的 slice (Slice)。
在上图所示的架构中,通过观察我们可以发现每个分块都由头部信息和数据内容两个主要部分组成:其中包含着分块类型,当前所处宏块类型,该分块所占有的帧数,所属图像类别以及相应的帧设置参数等详细信息.而在分片数据区域,则具体存储着各个像素值的位置.
什么是宏块?
在视频编码过程中,宏块被视为核心数据单元,在此过程中它们承担了主要的责任以承载整个视频的信息内容。
每个像素的亮度(luminance)和色度(chrominance)信息被整合到这里。
视频解码器的主要职责是通过高效算法从编码流中重建宏块内的像素矩阵。
这些高阶编码单元通常以平面形式排列,在图像中占据较大的空间区域。
这些核心数据单元由特定结构构成:每个宏块包含一个16×16的luminance(Y)分量以及附加的一个8×8的Cb和一个8×8的Cr彩色分量。
我们先来看看宏块的结构图:

从图表中可以看出,在宏块内部包含了宏块类型、预测模式以及相关的Coded Block Pattern(CBP)、量化参数(QP),此外还包括了图像的空间分辨率参数等其他相关参数。
切片(slice)类型跟宏块类型的关系
对于切片(slice)来讲,分为以下几种类型:
0 P-slice: Comprised exclusively of P-macros, each predicted by a single reference frame, alongside optional I-macros.
1 B-slice: Constructed from B-macros, each forecasted utilizing one or two reference frames, in combination with optional I-macros.
2 I-slice: Encompasses exclusively I-macros, all predicted from previously encoded blocks within the same slice.
3 SP-slice: Formed by integrating both P- and optional I-macros, this slice enables switching among encoded streams.
4 SI-slice: This slice features a unique type of SI(macros), specifically engineered to facilitate switching between encoded streams.
对于 I 片而言,仅包含其内部的 I 宏块。每个 I 宏块会基于当前 slice 中已被解码出的像素信息来进行帧内预测。而这些宏块不会考虑来自其他 slice 的像素数据用于同一 Slice 的帧内编码。
P片:其中包含P型和I型两种类型的宏块。其中P型宏块基于之前已编码图像作为基准图像来进行帧内预测。对于一个经帧内编码处理后的宏观区域,则可以通过以下方式进行细分:
具体来说,
包括以下几种基本划分方式:
首先是16x16、16x8、
或者
其转置形式,
以及伴随色信息;
如果选择的是一个尺寸为
则可以在其基础上
按照以下方式进行细分:
包括
或者
伴随色信息。
B系列:可包含 B型和 I型宏块;其中 B型宏块基于双方向的参考图像(当前帧和之前的已编码图像帧)进行帧内预测。
SP片(切换P):用于不同编码流之间的切换,包含 P 和/或 I 宏块
SI 片:在扩展档次中必须具备的一种切换操作包含了一种特殊类型的编码宏块,即 SI 宏块。同样属于扩展档次中的必要功能。
整体结构
我们对许多个小零件进行了深入分析,并且到了这个时候,
我们就可以向大家展示整个架构图了。
随后的NALU整体结构自然浮现出来,
以下就是引用H.264文档中的一幅图。

实际上H.264的码流结构没有像大家想象中那样显得相当复杂。编码后的视频每一组图像(GOP、图像组)都携带了传输中的序列(PPS)以及该帧自身的编码参数(SPS),因此我们的整体结构应当遵循这样的架构。

GOP用于描述每隔多少个帧。
增大图组会导致编码后视频体积降低。
但这会牺牲一些视频质量。
主题外:(未完待续)
那么,NALU 头部中的类型确定着什么信息呢?
我们首先来看看 NALU 中究竟有哪几种类型,我们来看看 H.264 中源码对 nal_unit_type_e 中的定义:
注
H.264 标准引入了一种新概念——参数集,并通过优化视频码流结构来提高错误恢复能力。
其中,
NAL\_SPLS = 7;
// 序列参数集(包含了单个图像序列的所有信息……)
NAL\_PPS = 8;
// 图像参数集(包含了单个图像的所有分片及相关信息……)
- NAL AUD 标识符设定为 9 ,// 表示分界线
- NAL 填充参数赋值为 12 ,// 其中填充(占位符数据),用于填充字节数量的空缺
/* 当 ref_idc 等于零时,则针对编号为 6、9及 10 的情况表示后续图片为 IDR 格式的,
当 ref_idc 等于零时,则针对编号为 11 的情况表示当前流内已无图片,
而 ref_idc 设定为 2 则表示当前流内无图像数据 */
};
注:上述括号内的内容属于数据类型说明
在NALU架构中,在此基础上我们对其中的分块/切分(slice)概念已经非常熟悉。此外,在基于NALU架构的应用中涉及的技术还包括SEI、SPS以及PPS等技术。
今天我们不会逐一阐述这些类型对整个流程的作用,并且筛选出两个与我们今天主题相关的类型来进行介绍,并使用PPS 和 SPS进行说明。


那么今天我们阐述了 H.264 的码流结构大致轮廓的信息,请问大家对这一部分是否有基本理解?总结来说:
H.264 中,句法元素共被组织成 序列、图像、片、宏块、子宏块五个层次。
大家期待着好好琢磨这份手动画图作品吧!因为手动画图费时费力不容易完成。想关注的朋友可以点个关注哦!想打赏的朋友可以点个"三连击"呀!记得点个"在看"哈!
最后福利:
在文章末尾部分,在iOS设备上开发了一段具体的实例代码来帮助大家更好地理解相关技术。这段代码的主要功能包括利用摄像头实时录制yuv格式文件并进行H.264编码以及实时分析每个帧中的NALU数据。旨在帮助新手快速掌握相关技术。(其中所有的源码均已放置于个人博客的底部部分)
文章作者为Abson在简书平台注册账号并活跃于该网站内容创作领域。具体链接位于此处。来源:简书 簡書著作權归作者所有,僅限于用于个人学习交流之用,任何形式的转载都请联系作者获得授權並注明出处。
