H264&H265格式

H264

1. NALU

H264码流可以分为两层,NAL层(网络抽象层)VCL层(视频编码层)

VCL层负责有效表示视频数据的内容,而NAL层则负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。

构成H264码流的基本单位是NAL单元,NAL单元简称为NALU,它包含一个字节的头信息(NALU Header) 和 **原始字节序列载荷(RBSP)**的字节流。

NALU结构如图:

在这里插入图片描述

1.1 NALU Header

以H264的NALU Header为例

NALU头由一个字节组成,它的语法如下:

字段大小含义
F1bitforbidden_zero_bit,H264定义此位必须为0
NRI2bitnal_ref_idc,0~3,标识这个NALU的重要性(3最高)
Type5bitnal_unit_type,NALU的类型

NALU Header分为3个部分:

  • forbidden_zero_bit:禁止位,必须为0。
  • nal_ref_idc:用来表示当前NALU的优先级,数值越大优先级越高。如00的NALU解码器可以丢弃它而不影响图像的显示,取值越大,表示当前NAL越重要,需要优先受到保护。如果当前NAL是属于参考帧的片(Slice),序列参数集(SPS),或是图像参数集(PPS)这些重要的单位时,nal_ref_idc必需大于0。
  • nal_unit_type :表示NALU类型。
1.1.1 nal_unit_type
nal_unit_type数值含义
0未使用
1不分区,非IDR图像的Slice
2片分区A
3片分区B
4片分区C
5IRD图像的Slice(IDR)
6补充增强信息单元(SEI)
7序列参数集(SPS)
8图像参数集(PPS)
9分隔符
10序列结束
11码流结束
12填充
13~23保留
24~25STAP-A/STAP-B 单一时间的组合包
26~27MTAP16/MTAP24 多个时间的组合包
28~29FU-A/FU-B 分片的单元
30~31没有定义

nal_unit_type为1, 2, 3, 4, 5的NAL单元称为VCL的NAL单元,其他类型的NAL单元为非VCL的NAL单元。此外1~12由H.264使用,24~31由H.264以外的应用使用。

 

2. 码流格式

一个NALU包中的数据并不包含它的大小(长度)信息,因此不能简单的连接NALU包来建立一个流,因为你不知道一个包从哪里结束,另一个包从哪里开始。

H264有两种码流格式解决上述问题:

  • Annex B格式
  • AVCC格式
2.1 Annex B格式

以起始码(0x00000001)作为H264/H265作为NALU边界。用起始码定位NALU边界存在一个问题,即NALU中可能存在与起始码相同的数据,这里引入防竞争字节。

防竞争字节:为了使NALU主体中不包括与开始码相冲突的,在编码时,就插入一个字节的0x03;解码时将0x03去掉。

如果编码器检测到NAL数据存在0x000001或0x000000时,编码器会在最后个字节前插入一个新的字节0x03,这样:
0x000000->0x00000300
0x000001->0x00000301
0x000002->0x00000302
0x000003->0x00000303

解码器检测到0x000003时,把03抛弃,恢复原始数据。

2.2 AVCC格式

使用NALU长度,固定字节,通常为4字节,分隔NALU;一般在每个NALU头部为4字节大端格式的长度字节,在一组GOP的头部包含extradata结构,用于存储sequence-header、SPS、PPS数据。

虽然AVCC格式不使用起始码,防竞争字节仍然存在。

2.2.1 extradata结构
namelengthcommnet
version8bit0x01
avc profile8bit0x64
avc compatibility8bit0x00
avc level8bit0x0A
NALULengthSizeMinusOne8bit0xFF,高6位保留,默认为1,低2位为11,表示NALU长度用3+1=4字节表示
number of SPS NALUs8bit0xE1,高3位保留,低5位表示有几个SPS,通常只有1个SPS
SPS size16bit大端格式的SPS长度,0x0019,表示25字节SPS
SPS NALU dataSPS size × 8bit0x67到0x80,表示SPS数据
number of PPS NALUs8bit0x01PPS个数,通常只有1个PPS
PPS size8bit0x07,表示PPS的数据长度
PPS NALU dataPPS size × 8bit0x68到0x30,表示PPS数据

NALULengthSizeMinusOne:用几个字节来存储NALU的长度,默认为3,表示使用4字节表示NALU长度。

2.3 H264 Annexb与AVCC格式转换

H264 Annexb转为AVCC

  • 1、对于一个GOP的开始,根据start-code,分离出SPS、PPS帧,并分别计算出长度
  • 2、根据SPS, PPS创建出extradata,附加到GOP的头部
  • 3、从IDR帧开始,搜索start-code,分离出每一个NALU,计算长度,然后将start-code转为4字节的NALU长度

AVCC 转为 H264 Annexb

  • 1、对于一个GOP的开始,首先检索出extradata部分的数据
  • 2、根据extradata数据创建出SPS帧,并用4字节的start-code:0x00000001附加在SPS数据的头部
  • 3、根据extradata数据创建出PPS帧,并用4字节的start-code:0x00000001附加在PPS数据的头部,并将PPS数据连接到SPS后面
  • 4、根据NALU的长度字段,分离出每一个NALU,然后用用4字节的start-code:0x00000001替换长度字段
  • 5、在以上过程中需要计算每一个NALU的长度,尤其是GOP的IDR帧,一般在IDR帧前还有SPS与PPS帧,其长度需要一起计算

 

3. 视频编码帧
3.1 压缩方式

帧内压缩与帧间压缩

  • 帧内压缩(I帧,JPEG的压缩算法)
  • 帧间压缩( P帧与B帧的压缩算法)

有损压缩与无损压缩

  • 有损压缩: 解压缩后的数据与压缩前的数据不一致.在压缩的过程中要丢失一些人眼和人耳所不敏感的图像或音频信息,而且丢失的信息不可恢复
  • 无损压缩: 压缩前和解压缩后的数据完全一致.优化数据的排列等
3.2 编码帧

常见的H264的编码帧有四种:

  • I帧(关键帧)
  • IDR帧(即时刷新帧)
  • P帧(前向预测参考帧)
  • B帧(双向预测参考帧)

I帧

I帧是帧内编码帧,I帧又称关键帧。

特点:

  • I帧不需要参考P帧/B帧生成一个完整图像。
  • I帧是P帧和B帧的参考帧。
  • I帧通常是每个GOP的第一个帧,采用的帧内压缩,经过适度压缩,作为随机访问的参考点。

IDR帧

IDR为即时解码刷新帧,I帧和IDR帧都是使用帧内预测编码,IDR帧是I帧,但I帧不一定是IDR帧。

I帧(非IDR帧)和IDR帧,只有IDR帧才有SPS和PPS。当解码器收到IDR帧时,将参考帧队列清空;而收到I帧(非IDR帧)不会清空参考帧队列。也就是说,对某个IDR帧之后的帧,解码器不会参考这个IDR帧之前的任何帧做解码。对某个I帧(非IDR帧)之后的帧,解码器可能会参考这个I帧之前的帧做解码。

P帧

P帧是前向预测编码帧,以I帧为参考帧。

它存储与前面的I帧/P帧的预测误差及运动矢量。

特点:

  • P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧。
  • P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧。
  • 由于P帧是参考帧,它可能造成解码错误的扩散。
  • P帧的压缩率比I帧要高。

B帧

B帧是双向预测内插编码帧,以前面的I/P帧和后面的P帧为参考帧。B帧存储的是它与前面的I/P帧,和后面的P帧之间的预测误差及运动矢量。

特点:

  • B帧压缩比最高。因为它只反映前后两个参考帧间运动主体的变化情况,预测比较准确。
  • B帧不是参考帧,不会造成解码错误的扩散 。

I帧,B帧,P帧之间的关系:

img

3.3 丢帧

播放器变速中如何丢帧?

  • GOP间的丢帧,只播放关键帧,也就是seek操作。
  • GOP内的丢帧,需要先解码后丢帧播放。
  • 非参考帧的丢帧处理。

针对非参考帧的丢帧处理:

方式:可以判断它的 nal_ref_idc 值来决定是否要丢弃。如果为 0 ,说明其他帧不需要参考该帧,可以直接丢弃不发送给解码器,而不是解码后再丢帧

nalu typenalu header val重要性可否丢帧
SPS0x67(0 11 00111)非常重要不可丢帧
PPS0x68(0 11 01000)非常重要不可丢帧
IDR帧0x65(0 11 00101)非常重要不可丢帧
I帧0x61(0 11 00001)非常重要不可丢帧
P帧0x61(0 10 00001)重要可丢帧,但后面同GOP组内的P帧,B帧都要丢
B帧0x01(0 00 00001)不重要可丢帧
SEI0x06(0 00 00110)不重要可丢帧

参考链接:

​ https://www.cnblogs.com/hankfu/p/13968625.html
​ https://www.sohu.com/a/432293002_465219
​ https://cloud.tencent.com/developer/article/1619203
​ https://blog.csdn.net/u010925568/article/details/75040492

 

4. PTS与DTS
4.1 概念

DTS是解码时间戳,表示解码器应该什么时候解码数据帧。

PTS是显示时间戳,表示渲染器应该什么时候渲染显示数据帧。

一般来说,数据帧经过解码之后,就立即用于渲染显示,为什么还需要两个时间戳?

PTS与DTS是对于视频而言,音频只是一个时间戳DTS,也就是音频帧经过解码就立即播放。对于视频,当视频只有I帧和P帧,PTS和DTS是相同的,只有视频有B帧,PTS与DTS才有可能不一样。

4.2 为什么需要PTS,DTS?

以一个例子说明:

在这里插入图片描述

  1. 视频采集到的一组数据帧,经过传输解码,最终播放顺序按照:

​ I(1) -> B(2) -> B(3) -> P(4) -> B(5) -> B(6) -> P(7)

​ PTS: I(1) < B(2) < B(3) < P(4) < B(5) < B(6) < P(7)

​ 同时也知道采集顺序和显示顺序是一致的

  1. 由于B帧的存在,B帧是前后双向预测帧,必须先缓存并解码其前后两个参考帧才能解码B帧,如B(2),B(3)要解码,必须先缓存解码I(1)和P(4)才行,由此可知:

​ DTS:I(1) < P(4) < B(2) < B(3)

依此类推得出:

​ DTS:I(1) < P(4) < B(2) < B(3) < P(7) < B(5) < B(6)

可看出由于B帧的存在,视频帧的DTS和PTS可能不同

​ 采集到原始视频帧经过编码后得到编码帧,就会被传输,播放端接收到编码帧就进行解码,所以编码顺序、传输顺序和解码顺序是一致的

 

H265

1.NALU

H265的NALU结构和H264是一致的,都是Nalu Header + RBSP的结构。

1.1 Nalu Header

Nalu Header由两个字节组成:

字段大小含义
forbidden_zero_bit1bit禁止位,用以检查传输过程中是否发生错误,0表示正常,1表示违反语法
nal_unit_type6bit用来指示NALU类型
nuh_reserved_zero_6bits6bit预留位,要求为0
nuh_temporal_id_plus13bit表示NALU所在的时间层ID
1.1.1 nal_unit_type

来保存视频流的编解码参数,其格式定义如下:

nal_unit_typeNALU类型备注
0NAL_UNIT_CODE_SLICE_TRAIL_N非关键帧
1NAL_UNIT_CODED_SLICE_TRAIL_R
2NAL_UNIT_CODED_SLICE_TSA_N
3NAL_UINT_CODED_SLICE_TSA_R
4NAL_UINT_CODED_SLICE_STSA_N
5NAL_UINT_CODED_SLICE_STSA_R
6NAL_UNIT_CODED_SLICE_RADL_N
7NAL_UNIT_CODED_SLICE_RADL_R
8NAL_UNIT_CODED_SLICE_RASL_N
9NAL_UNIT_CODE_SLICE_RASL_R
10 ~ 15NAL_UNIT_RESERVED_X保留
16NAL_UNIT_CODED_SLICE_BLA_W_LP关键帧
17NAL_UNIT_CODE_SLICE_BLA_W_RADL
18NAL_UNIT_CODE_SLICE_BLA_N_LP
19NAL_UNIT_CODE_SLICE_IDR_W_RADL
20NAL_UNIT_CODE_SLICE_IDR_N_LP
21NAL_UNIT_CODE_SLICE_CRA
22NAL_RSV_IRAP_VCL22
23NAL_RSV_IRAP_VCL23
24 ~ 31NAL_UNIT_RESERVED_X保留
32NAL_UNIT_VPSVPS(Video Paramater Set)
33NAL_UNIT_SPSSPS
34NAL_UNIT_PPSPPS
35NAL_UNIT_ACCESS_UNIT_DELIMITER
36NAL_UNIT_EOS
37NAL_UNIT_EOB
38NAL_UNIT_FILLER_DATA
39NAL_UNIT_SEI_PREFIXPrefix SEI
40NAL_UNIT_SEI_SUFFIXSuffix SEI
41 ~ 47NAL_UNIT_RESERVED_X保留
48 ~ 63NAL_UNIT_UNSPECIFIED_X未规定
64NAL_UNIT_INVALID
  • NAL_AUD(35),NAL_SEI_PREFIX(39),NAL_SEI_SUFFIX(40)为可丢弃的视频帧。
  • nalu_type:0 ~ 23(不包含保留的nalu_type)用于解码的视频帧。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值