H.264/H265码流解析

一.H.264码流解析

一个原始的H.264 NALU 单元常由 [StartCode] [NALU Header] [NALU Payload] 三部分组成

一个原始的H.264 NALU 单元常由 [StartCode] [NALU Header] [NALU Payload] 三部分组成

NALU组成.jpeg

  • StartCode : Start Code 用于标示这是一个NALU 单元的开始,必须是”00 00 00 01” 或”00 00 01”
  • NALU Header

    下表为 NAL Header Type

NAL Header Type.png

例如,下面幅图分别代表IDR与非IDR帧具体的码流信息:

2.IDR

在一个NALU中,第一个字节(即NALU header)用以表示其包含数据的类型及其他信息。我们假定一个头信息字节为0x67作为例子:

十六进制

二进制

0x67

0 11 00111

如表所示,头字节可以被解析成3个部分,其中:

1>.
forbidden_zero_bit = 0:占1个bit,禁止位,用以检查传输过程中是否发生错误,0表示正常,1表示违反语法;

2>. nal_ref_idc
= 3:占2个bit,用来表示当前NAL单元的优先级。非0值表示参考字段/帧/图片数据,其他不那么重要的数据则为0。对于非0值,值越大表示NALU重要性越高

3>.
nal_unit_type = 7:最后5位用以指定NALU类型,NALU类型定义如上表

从表中我们可以获知,NALU类型1-5为视频帧,其余则为非视频帧。在解码过程中,我们只需要取出NALU头字节的后5位,即将NALU头字节和0x1F进行与计算即可得知NALU类型,即:

NALU类型 = NALU头字节 & 0x1F

注意: 可以将start code理解为不同nalu的分隔符,header是某种类型的key,payload是该key的value.

码流格式

H.264标准中指定了视频如何编码成独立的包,但如何存储和传输这些包却未作规范,虽然标准中包含了一个Annex附件,里面描述了一种可能的格式Annex B,但这并不是一个必须要求的格式。

为了针对不同的存储传输需求,出现了两种打包方法。一种即Annex B格式,另一种称为AVCC格式。

  • Annex B

从上文可知,一个NALU中的数据并未包含他的大小(长度)信息,因此我们并不能简单的将一个个NALU连接起来生成一个流,因为数据流的接收端并不知道一个NALU从哪里结束,另一个NALU从哪里开始。

Annex B格式用起始码(Start Code)来解决这个问题,它在每个NALU的开始处添加三字节或四字节的起始码0x000001或0x00000001。通过定位起始码,解码器就可以很容易的识别NALU的边界。

当然,用起始码定位NALU边界存在一个问题,即NALU中可能存在与起始码相同的数据。为了防止这个问题,在构建NALU时,需要将数据中的0x000000,0x000001,0x000002,0x000003中插入防竞争字节(Emulation Prevention Bytes)0x03,使其变为:

0x000000 = 0x0000
03 00

0x000001 = 0x0000 03 01

0x000002 = 0x0000 03 02

0x000003 = 0x0000 03 03

解码器在检测到0x000003时,将0x03抛弃,恢复原始数据。

由于Annex B格式每个NALU都包含起始码,所以解码器可以从视频流随机点开始进行解码,常用于实时的流格式。在这种格式中通常会周期性的重复SPS和PPS,并且经常时在每一个关键帧之前。

  • AVCC

AVCC格式不使用起始码作为NALU的分界,这种格式在每个NALU前都加上一个指定NALU长度的大端格式表示的前缀。这个前缀可以是1、2或4个字节,所以在解析AVCC格式的时候需要将指定的前缀字节数的值保存在一个头部对象中,这个都通常称为extradata或者sequence header。同时,SPS和PPS数据也需要保存在extradata中。

H.264 extradata语法如下:

bits

line by byte

remark

8

version

always

0x01

8

avc profile

sps[0][1]

 

8

avc compatibility

sps[0][2]

 

8

avc level

sps[0][3]

 

6

reserved

all bits on

 

2

NALULengthSizeMinusOne

   

3

reserved

all bits on

 

5

number of SPS NALUs usually

1

 

16

SPS size

   

N

variable SPS NALU data

   

8

number of PPS NALUs usually

1

 

16

PPS size

   

N

variable PPS NALU data

   

其中第5字节的后2位表示的就是NAL size的字节数。需要注意的是,这个NALULengthSizeMinusOne是NALU前缀长度减一,即,假设前缀长度为4,那么这个值应该为3。

这里还需要注意的一点是,虽然AVCC格式不使用起始码,但防竞争字节还是有的。

AVCC格式的一个优点在于解码器配置参数在一开始就配置好了,系统可以很容易的识别NALU的边界,不需要额外的起始码,减少了资源的浪费,同时可以在播放时调到视频的中间位置。这种格式通常被用于可以被随机访问的多媒体数据,如存储在硬盘的文件。

二.
H.265码流解析

HEVC全称High Efficiency Video Coding(高效率视频编码,又称H.265),是比H.264更优秀的一种视频压缩标准。HEVC在低码率视频压缩上,提升视频质量、减少容量即节省带宽方面都有突出表现。

H.265标准围绕H.264编码标准,保留原有的某些技术,同时对一些技术进行改进,编码结构大致上和H.264的架构类似。这里着重讲一下两者编码格式的区别。

同H.264一样,H.265也是以NALU的形式组织起来。而在NALU header上,H.264的HALU header是一个字节,而H.265则是两个字节。我们同样假定一个头信息为0x4001作为例子:

十六进制

二进制

0x4001

0 100000 000000 001

如表所示,头信息可以被解析成4个部分,其中:

  • forbidden_zero_bit
    = 0:占1个bit,与H.264相同,禁止位,用以检查传输过程中是否发生错误,0表示正常,1表示违反语法;
  • nal_unit_type = 32:占6个bit,用来用以指定NALU类型
  • nuh_reserved_zero_6bits
    = 0:占6位,预留位,要求为0,用于未来扩展或3D视频编码
  • nuh_temporal_id_plus1
    = 1:占3个bit,表示NAL所在的时间层ID

对比H.264的头信息,H.265移除了nal_ref_idc,此信息被合并到了nal_unit_type中,H.265NALU类型规定如下:

nal_unit_type

NALU类型

备注

0

NAL_UNIT_CODE_SLICE_TRAIL_N

非关键帧

1

NAL_UNIT_CODED_SLICE_TRAIL_R

 

2

NAL_UNIT_CODED_SLICE_TSA_N

 

3

NAL_UINT_CODED_SLICE_TSA_R

 

4

NAL_UINT_CODED_SLICE_STSA_N

 

5

NAL_UINT_CODED_SLICE_STSA_R

 

6

NAL_UNIT_CODED_SLICE_RADL_N

 

7

NAL_UNIT_CODED_SLICE_RADL_R

 

8

NAL_UNIT_CODED_SLICE_RASL_N

 

9

NAL_UNIT_CODE_SLICE_RASL_R

 

10 ~ 15

NAL_UNIT_RESERVED_X

保留

16

NAL_UNIT_CODED_SLICE_BLA_W_LP

关键帧

17

NAL_UNIT_CODE_SLICE_BLA_W_RADL

 

18

NAL_UNIT_CODE_SLICE_BLA_N_LP

 

19

NAL_UNIT_CODE_SLICE_IDR_W_RADL

 

20

NAL_UNIT_CODE_SLICE_IDR_N_LP

 

21

NAL_UNIT_CODE_SLICE_CRA

 

22 ~ 31

NAL_UNIT_RESERVED_X

保留

32

NAL_UNIT_VPS

VPS(Video Paramater Set)

33

NAL_UNIT_SPS

SPS

34

NAL_UNIT_PPS

PPS

35

NAL_UNIT_ACCESS_UNIT_DELIMITER

 

36

NAL_UNIT_EOS

 

37

NAL_UNIT_EOB

 

38

NAL_UNIT_FILLER_DATA

 

39

NAL_UNIT_SEI

Prefix SEI

40

NAL_UNIT_SEI_SUFFIX

Suffix SEI

41 ~ 47

NAL_UNIT_RESERVED_X

保留

48 ~ 63

NAL_UNIT_UNSPECIFIED_X

未规定

64

NAL_UNIT_INVALID

 

具体type含义可以参考这篇文档type类型

H.265的NALU类型是在信息头的第一个字节的第2到7位,所以判断H.265NALU类型的方法是将NALU第一个字节与0x7E进行与操作并右移一位,即:

NALU类型 = (NALU头第一字节 & 0x7E) >> 1

与H.264类似,H.265码流也有两种封装格式,一种是用起始码作为分界的Annex B格式,另一种则是在NALU头添加NALU长度前缀的格式,称为HVCC。在HVCC中,同样需要一个extradata来保存视频流的编解码参数,其格式定义如下:

bits

line by byte

remark

8

configurationVersion

always 0x01

2

general_profile_space

 

1

general_tier_flag

 

5

general_profile_idc

 

32

general_profile_compatibility_flags

 

48

general_constraint_indicator_flags

 

8

general_level_idc

 

4

reserved

‘1111’b

12

min_spatial_segmentation_idc

 

6

reserved

‘111111’b

2

parallelismType

 

6

reserved

‘111111’b

2

chromaFormat

 

5

reserved

‘11111’b

3

bitDepthLumaMinus8

 

5

reserved

‘11111’b

3

bitDepthChromaMinus8

 

16

avgFrameRate

 

2

constantFrameRate

 

3

numTemporalLayers

 

1

tmporalIdNested

 

2

lengthSizeMinusOne

 

8

numOfArrays

 

Repeated of
Array(VPS/SPS/PPS)

1| array_completeness

1| reserved| ‘0’b

6| NAL_unit_type

16| numNalus

16| nalUnitLength

N| NALU data

从上表可以看到,在H.265的extradata后半段是一段格式重复的数组数据,里面需要包含的除了与H.264相同的SPS、PPS外,还需多添加一个VPS。

VPS(Video Parament Set,视频参数集),在H.265中类型为32。VPS用于解释编码过的视频的整体结构,包括时域子层依赖关系等,主要目的在于兼容H.265标准在系统的多子层方面的扩展。

H.264/H265码流解析的更多相关文章

  1. 视音频数据处理入门:H.264视频码流解析

    ===================================================== 视音频数据处理入门系列文章: 视音频数据处理入门:RGB.YUV像素数据处理 视音频数据处理 ...

  2. 【视频编解码·学习笔记】4. H.264的码流封装格式

    一.码流封装格式简单介绍: H.264的语法元素进行编码后,生成的输出数据都封装为NAL Unit进行传递,多个NAL Unit的数据组合在一起形成总的输出码流.对于不同的应用场景,NAL规定了一种通 ...

  3. 【视频编解码·学习笔记】4. H.264的码流封装格式 & 提取NAL有效数据

    一.码流封装格式简单介绍: H.264的语法元素进行编码后,生成的输出数据都封装为NAL Unit进行传递,多个NAL Unit的数据组合在一起形成总的输出码流.对于不同的应用场景,NAL规定了一种通 ...

  4. 视音频数据处理入门:AAC音频码流解析

    ===================================================== 视音频数据处理入门系列文章: 视音频数据处理入门:RGB.YUV像素数据处理 视音频数据处理 ...

  5. Wireshark Lua: 一个从RTP抓包里导出H.264 Payload,变成264裸码流文件(xxx.264)的Wireshark插件

    Wireshark Lua: 一个从RTP抓包里导出H.264 Payload,变成264裸码流文件(xxx.264)的Wireshark插件 在win7-64, wireshark Version ...

  6. 【雷神源码解析】无基础看懂AAC码流解析,看不懂你打我

    一 前言 最近在尝试学习一些视频相关的知识,随便一搜才知道原来国内有雷神这么一个真正神级的人物存在,尤其是在这里(传送门)看到他的感言更是对他膜拜不已,雷神这种无私奉献的精神应当被我辈发扬光大.那写这 ...

  7. H265码流格式

    一.H265码流格式 VPS:视频参数集,用于传输视频分级信息,有利于兼容标准在可分级视频编码或多视点视频的扩展. NALU header定义: NALU header(){ Descriptor f ...

  8. h.264码流解析_一个SPS的nalu及获取视频的分辨率

    00 00 00 01 67 42 00 28 E9 00  A0 0B 77 FE 00 02 00 03 C4 80  00 00 03 00 80 00 00 1A 4D 88  10 94 0 ...

  9. H265码流分析

    H265相比较于H264,除了包含SPS.PPS外,还多包含一个VPS:在NALU header上,H.264的HALU header是一个字节,而H.265则是两个字节. 以OX4001为例,头信息 ...

随机推荐

  1. php变量的命名规则

    php变量的命名规则 1.变量以美元符号$开头.如$name,$age: 2.美元符号$后面的第一个字符不可以是数字: 3.除了下划线_外,变量不允许出现任何空格或者标点符号: 4.PHP变量名是区分 ...

  2. 使用EasySYS搭建驱动开发基本框架

    提供EasySYS的下载地址:http://bbs.pediy.com/showthread.php?p=956643,看雪上有提供下载,自行百度. EasySYS你能够帮我们快速的搭建驱动的开发框架 ...

  3. ARM汇编中的:比较指令--CMN / CMP / TEQ / TST

    1. 简介 CMP / CMN : 算术指令 TEQ / TST : 逻辑指令      它们总是会影响CPSR条件标志位. APSR(CPSR)与condition的关系图: 2. CMN -- 比 ...

  4. 如何以最简单的方式安装 KALI 渗透测试框架系统

    0x01 第一步下载 KALI 百度搜索 KALI 官网,找到下载区,我选的是 64 位标准版,但是推荐下载 32 位(功能貌似更全) 这个为下载后的 iso 镜像文件 0x02 第二步打开虚拟机,配 ...

  5. WIN64内核编程-的基础知识

    WIN64内核编程基础班(作者:胡文亮)   https://www.dbgpro.com/x64driver 我们先从一份"简历"说起: 姓名:X86或80x86 性别:? 出生 ...

  6. android The content of the adapter has changed but ListView did not receive a notification 错误的解决方案

    使用了AsyncTask在后台刷新适配器,并且通知ui线程更新ListView,运行时发现时不时的出现 如题 的错误, 导致程序崩溃,解决方法如下: 1.建立一个缓冲数据集,这个数据集就是填充适配器的 ...

  7. MetInfo Password Reset Poisoning By Host Header Attack

    if we know some user's email, the we will can reset the user's email by host header attack. The atta ...

  8. 【python】Leetcode每日一题-设计停车系统

    [python]Leetcode每日一题-设计停车系统 [题目描述] 请你给一个停车场设计一个停车系统.停车场总共有三种不同大小的车位:大,中和小,每种尺寸分别有固定数目的车位. 请你实现 Parki ...

  9. 【python】Leetcode每日一题-不同的子序列

    [python]Leetcode每日一题-不同的子序列 [题目描述] 给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数. 字符串的一个 子序列 是指,通过删除一些(也可以 ...

  10. PHP中ftp的连接与操作

    1.操作类 <?phpclass FtpService{ protected $connect = 0; public function __construct() { $this->co ...