H.264(MPEG-4 AVC) NALU分析

简介

H.264从1999年开始,到2003年形成草案,最后在2007年定稿有待核实。在ITU的标准⾥称为H.264,在MPEG的标准⾥是MPEG-4的⼀个组成部分MPEG-4 Part 10,⼜叫Advanced Video Codec,因此常常称为MPEG-4 AVC或直接AVC。
其实在这里有个地方值得了解,为什么同一个视频编码标准会有两个名字?

  1. 联合开发的背景
    H.264/MPEG-4 AVC是由ITU-T(国际电信联盟电信标准化部门)的VCEG(视频编码专家组)和ISO(国际标准化组织)/IEC(国际电工委员会)的MPEG(运动图像专家组)联合开发的。为了提高效率并避免重复工作,这两个组织在2001年成立了联合视频小组(JVT,Joint Vdieo Team),共同制定这一标准。
    联合开发的结果是一个同一的技术规范,但两个组织保留了各自的命名方式,以适应各自的标准体系和用户群体。

H.264的编码原理

在音视频的传输过程中,视频文件的传输是一个大问题;例如一段分辨率为 19201080,每个像素点为RGB占3字节,帧率是25的视频,对于传输带宽的要求是 19201080325/1024/1024=148.3154296875MB/s,换成bps则意味视频每秒带宽为1,186.5234375Mbps,这样的速率对于网络存储是不可接受的,因此视频压缩和编码技术应运而生。
对于视频文件来说,视频由单张图片帧所组成,比如每秒25帧,但是图片帧的像素块之间存在相似性,因此视频帧图像可以进行图像压缩;H264采用了16*16的分块大小对视频图像进行相似比较和压缩编码。如图所示:
在这里插入图片描述

H264的I帧、P帧和B帧

H264采用帧内压缩和帧间压缩的方式提高编码压缩率;H264采用了独特的I帧、P帧和B帧策略来实现,实现帧之间的压缩。
解码顺序
详情看:视频I P B帧理解
在这里插入图片描述
从上面可以得知 压缩率:B>P>I

H264编码结构解析

H264除了实现对视频的压缩处理外,为了方便网络传输,提供了对应的视频编码和分片策略;类似于网络数据封装成IPB帧,在H264中将其称为组(GOP, group of pictures)、片(slice)、宏块(Macroblock)这些组成了H264的码流分层结构,H264将其组织成为 序列(GOP),图片(picture)、片(slice)、宏块(Macroblock)、子块(subblock)五个层次。
GOP(图像组)注意用来形容一个IDR帧(Instantaneous Decoding Refresh Frame,即瞬时解码刷新帧)到下一个IDR帧中间隔了多少帧。
在这里插入图片描述
H264将视频分为连续的帧进⾏传输,在连续的帧之间使⽤I帧、P帧和B帧。同时对于帧内⽽⾔,将图像分块为⽚、宏块和字块进⾏分⽚传输;通过这个过程实现对视频⽂件的压缩包装。

这里值得注意的是:IDR帧一定是I帧,但I帧不一定是IDR帧

IDR帧和I帧的区别

  • 共同点
    1、I帧和IDR帧都是帧内编码帧(Intra-coded frame),只用当前帧的信息编码,不依赖其他帧。
    2、它们都由宏块组成,使用帧内预测(如Intra 16x16或Intra 4x4)
  • 区别
    I帧:
    只是一个独立编码的帧,后续的P帧或B帧可能仍然参考I帧之前的帧。
    不会重置解码器的状态,错误可能从之前的帧传播到I帧之后的帧。
    IDR帧:
    不仅独立编码,还会重置解码器,清空参考帧缓冲区。
    后续的P帧或B帧只能参考IDR帧及其之后的帧,禁止参考IDR帧之前的帧。
    作用:提供“干净”的起点,适合随机访问(如视频跳转)和错误恢复。
  • 实际场景
    视频播放:
    你拖动视频进度条到10分钟处,播放器会找到最近的IDR帧开始解码,因为IDR帧保证不需要之前的帧数据。
    如果是普通I帧,可能无法正确解码,因为后续帧可能依赖I帧之前的帧。
    网络传输
    如果网络丢包导致某帧丢失,IDR帧可以让解码器“从头开始”,避免错误影响后续帧。而I帧可能让错误继续传播。

什么是NALU?

NALU(Network Abstraction Layer Unit,网络抽象层单元)是H.264视频编码标准中用于数据封装和传输的基本单元。它是H.264码流的最小组织单元,包含了视频编码数据和相关信息的"包",便于网络传输和解码。

  • 定义
    NALU是H.264码流中的一个数据块,每个NALU包含一个头部(描述数据类型)和有效载荷(实际数据,如视频帧、参数集等)。

  • 作用:
    将H.264编码的视频数据(或元数据)封装成适合网络传输的格式。
    提供灵活性和鲁棒性,方便在不同网络环境下(如实时流媒体)传输视频。
    支持解码器识别和处理不同类型的数据(如视频帧、序列参数等)。
    发I帧之前,⾄少要发⼀次SPS和PPS

NALU结构

⼀个NALU = ⼀组对应于视频编码的NALU头部信息+ ⼀个原始字节序列负荷(RBSP,Raw Byte Sequence Payload)
NALU结构单元的主体结构如下所示;⼀个原始的H.264 NALU单元通常由[StartCode] [NALU Header] [NALU Payload]三部分组成,其中Start Code ⽤于标示这是⼀个NALU 单元的开始,必须是"00 00 00 01" 或"00 00 01",除此之外基本相当于⼀个NAL header + RBSP
在这里插入图片描述
(FFmpeg解复用后,MP4文件读取处理的packet是不带startcode的,TS文件读取出来的packet带了startcode)

解析NALU

每个NAL单元是⼀个⼀定语法元素的可变⻓字节字符串,包括包含⼀个字节的头信息(⽤来表示数据类型),以及若⼲整数字节的负荷数据。
在这里插入图片描述
其中:

  • T为负荷数据类型,占5bit
    nal_unit_type:这个NALU单元的类型,1~12由H.264使用,24-31由H.264外的应用使用,13-23是H.264预留
  • R为重要性指标,占2bit
    nal_ref_idc:范围0-3,值越大,表示此单元越重要,如00的NALU解码器可以丢弃它⽽不影响图像的回放,如果当前NAL是属于参考帧的⽚,或是序列参数集,或是图像参数集这些重要的单位时,本句法元素必需⼤于0
  • F为禁止位,占1bit
    forbidden_zero_bit:在H.264 规范中规定了这⼀位必须为0

H.264标准指出,当数据流是储存在介质上时,在每个NALU 前添加起始码:0x000001 或0x00000001,⽤来指示⼀个NALU 的起始和终⽌位置:
在这样的机制下,在码流中检测起始码,作为⼀个NALU得起始标识,当检测到下⼀个起始码时,当前NALU结束。3字节的0x000001只有⼀种场合下使⽤,就是⼀个完整的帧被编为多个slice(⽚)的时候,包含这些slice的NALU 使⽤3字节起始码。其余场合都是4字节0x00000001的

在这里插入图片描述
在这里插入图片描述

H.264的两种封装格式

  1. Annex B字节流格式(Byte Stream Format)
  2. AVCC格式(AVC Configuration Format)
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值