【H.264】H.264详解(一)—— 一文看懂H.264协议

【H.264】H.264详解(一)—— 一文看懂H.264协议H 264 是一种视频压缩编码标准 同时也是 MPEG 4 第 10 部分规范 ISO IEC14496 10 MPEG 4Part10 叫 AdvancedVide 高级视频编码 因

大家好,欢迎来到IT知识分享网。

<> 博客简介:Linux、rtos系统,arm、stm32等芯片,嵌入式高级工程师、面试官、架构师,日常技术干货、个人总结、职场经验分享

<> 公众号:嵌入式技术部落

<> 系列专栏:C/C++、Linux、rtos、嵌入式开发、流媒体、数据结构、网络协议、开源库、CMake、Makefile、架构设计模式等



一、H.264 协议概述

H.264 协议介绍

H.264,是一种视频压缩编码标准 ,同时也是MPEG-4第10部分规范(ISO/IEC 14496-10),MPEG-4 Part 10,⼜叫Advanced Video Codec(高级视频编码),因此H.264常常称为MPEG-4 AVC或直接叫AVC。所以在H.264的参数中可以看到 AVC == H264,而 HECV == H265。H.264已经成为高精度视频录制、压缩和发布的最常用格式之一。常见的写法H264,标准写法应该是H.264。

H.264 协议目的

H.264/AVC 协议的目的是为了创建一个更佳的视频压缩标准,在更低的比特率的情况下依然能够提供良好视频质量的标准(如,一半或者更少于MPEG-2,H.263,或者MPEG-4 Part2 )。同时,还要不会太大的增加设计的复杂性。H.264的另外一个目标是提供足够的灵活性,以允许该标准能够应用于各种各样的网络和系统的各应用上,包括低和高比特率,低和高分辨率视频,广播,DVD存储,RTP / IP分组网络和ITU-T多媒体电话系统。

二、H.264 协议解析

H.264码流

H.264码流是指按照H.264标准编码的视频数据流。H.264码流只存放了原始的视频数据,而不包含其他信息。例如,我们通常说的视频要包含音频,而H.264码流里就没有。除了音频之外,我们通常说的视频里还存放着其他辅助信息,比如视频的播放时长,每一帧的播放时间、帧率、画面是否旋转等等很多信息,而H.264码流里也没有。所以严格来说,H.264码流和我们通常意义上的“视频”还是有一定差距的。

视频编码层(Video Coding Layer, VCL)

视频编码层负责将原始视频数据进行编码,它定义了如何将原始视频数据压缩成更小的格式,VCL使用多种编码工具和技术来实现高效的压缩。

网络抽象层(Network Abstraction Layer, NAL)

网络抽象层负责将视频编码层产生的比特流组织成适合传输和存储的格式。它的主要任务是将编码数据打包成网络抽象层单元(Network Abstraction Layer Unit,NALU),这些单元可以在不同的网络和存储介质上进行传输和存储。

码流组织方式

多个NALU在网络中传输或者写到一个文件里的时候,多个NALU首位相连成一串,因为NALU本身长度不一,也没有具体的标识符用来表明自己是一个独立的NALU,那么我们在从网络上接收到数据或者读取这个文件的时候,其实没有办法将在一起的NALU有效的进行区分。为了解决这个问题,我们必须在H264码流中将NALU进行分割,以便将在一起的NALU有效的进行区分,这种分割的方式就是H.264码流的组织方式。目前H264主流的码流组织方式有两种:AnnexB和AVCC两种格式。

AnnexB
起始码(start code)

起始码有两种模式,四字节模式(0x00 00 00 01)和三字节模式(0x00 00 01)。一路H.264码流中NALU的起始码可能都是0x00 00 00 01,也可能都是0x00 00 01,同样也有可能既有0x00 00 00 01也有0x00 00 01。

防竞争字节 (Emulation Prevention Bytes)

防竞争字节,就是在给 NALU 添加起始码之前,先对码流进行一次遍历,查找码流里面的存在的 0x00 00 00,0x00 00 01,0x00 00 02,0x00 00 03 的字节,然后对其进行如下修改

00 00 00 => 00 00 03 00 00 00 01 => 00 00 03 01 00 00 02 => 00 00 03 02 00 00 03 => 00 00 03 03 

当然,在解码过程中,通过起始码成功分割 NALU 数据之后,还要将防竞争字节去掉。

00 00 03 00 => 00 00 00 00 00 03 01 => 00 00 01 00 00 03 02 => 00 00 02 00 00 03 03 => 00 00 03 
AVCC

在读取的时候,先把这个extradata读出来,解析得到NALU Length的字节数,NALU Length这几个字节转成一个整数即为NALU Length的值,然后按照长度值读取整个 NALU。

extradata

在一路采用 avcC 打包的 H.264 流中,我们首先看到的将是 extradata 的数据,我们来看一下 extradata 数据格式

长度(bits) 名称 备注
8 version always 0x01
8 avc profile sps[0][1] 所存放第一个 SPS 的第一个字节
8 avc compatibility sps[0][2] 所存放第一个 SPS 的第二个字节
8 avc level sps[0][3] 所存放第一个 SPS 的第三个字节
6 reserved 保留字段
2 NALULengthSizeMinusOne NALU Length 数据的长度减去 1,单位字节数
3 reserved 保留字段
5 number of SPS NALUs 有几个 SPS,一般情况下这里是 1
for(int i=0; i<number of SPS NALUs; i++){
~
16   SPS size SPS 的长度
变长   SPS NALU data SPS NALU 的数据
} ~
8 number of PPS NALUs 有几个 PPS,一般情况下这里是 1
for(int i=0; i<number of PPS NALUs; i++){
~
16   PPS size PPS 的长度
变长   PPS NALU data PPS NALU 的数据
} ~

注: avcC 允许存多个 PPS 和 SPS。在 AnnexB 中,SPS 和 PPS 被当做了普通的 NALU 进行处理;而在 avcC 中,SPS 和 PPS 被当做特殊的信息进行了处理。

NALU Length

extradata中有一个变量NALULengthSizeMinusOne,这个变量告诉我们用几个字节来存储NALU的长度。我们注意一下上表中的这个值 NALULengthSizeMinusOne 这个字段长度是 2 个 bit,取值范围为0~3。NALULengthSizeMinusOne翻译一下为”NALU长度减1″,单位是字节数,即 NALU Length 的字节数 – 1 = NALULengthSizeMinusOne ,通过将 NALULengthSizeMinusOne 加 1 ,我们就得出了后续每个 NALU 的 前缀 NALU Length 的字节数。

AVCC和AnnexB对比

AnnexB格式:

AVCC格式:

NALU的作用

NALU(Network Abstraction Layer Unit,网络抽象层单元)在H.264编码标准中起着至关重要的作用,是构建H.264码流的基本单元。NALU的主要作用和功能包括以下几个方面:

NALU的组成

NALU 主体

NALU的主体涉及到三个重要的名词,分别为EBSP、RBSP和SODB。其中EBSP完全等价于NALU主体,而且它们三个的结构关系为:EBSP包含RBSP,RBSP包含SODB。

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

RBSP 是 H.264 标准中的概念,要说 RBSP,我们就要提到一个我们之前提到的概念,防竞争字节 (Emulation Prevention Bytes)。EBSP 相较于 RBSP,多了防竞争字节:0x03。

SODB(String of Data Bits,数据比特串)

SODB是一种以比特为单位的数据表示形式。RBSP 相较于 SOBP,多了tariling bits。

NALU Header
forbidden_zero_bit

在网络传输中发生错误时,会被置为1,告诉接收方丢掉该单元,否则为0。

nal_ref_idc

用于表示当前NALU的重要性,值越大,越重要。解码器在解码处理不过来的时候,可以丢掉重要性为0的NALU。可能的值有 4 个,详情如下表。

nal_ref_idc 重要性
3 HIGHEST
2 HIGH
1 LOW
0 DISPOSABLE
nal_unit_type
片(Slice)

片的主要作用是用作宏块(Macroblock)的载体。一个 slice 最少包含一个宏块,最多包含整帧图像的宏块。我们可以理解为一帧图像可以编码为一个或多个片(Slice),而每一个片(Slice)最少包含一个宏块,最多包含整帧图像的宏块。

片的主要目的是为限制误码的扩散和传输。如何限制误码的扩散和传输呢?每个片(slice)都应该是互相独立被传输的,某片的预测(片内预测和片间预测)不能以其它片中的宏块(Macroblock)为参考图像。

宏块(Macroblock)

宏块是视频信息的主要承载者,因为它包含着每一个像素的亮度和色度信息。视频解码最主要的工作则是提供高效的方式从码流中获得宏块中的像素阵列。

从上图中,可以看到,宏块中包含了宏块类型、预测类型、Coded Block Pattern 编码的块模式、Quantization Parameter 量化参数、像素的亮度和色度数据集等等信息。

写在后面
受限于时间,同时为了方便讲解,部分内容可能不是很严谨,如有错漏,敬请指出。如有问题,也欢迎随时交流

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/129168.html

(0)
上一篇 2025-08-26 14:15
下一篇 2025-08-26 14:20

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信