zoukankan      html  css  js  c++  java
  • H.264/H265码流解析

    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标准在系统的多子层方面的扩展。




  • 相关阅读:
    在Windows环境下搭建redis
    三种主流的Web服务实现方案(REST+SOAP+XML-RPC)简述及比较
    ASP.NET Web API身份验证和授权
    quartz 设置时间格式
    服务端发post请求产生的编码问题
    大型网站的灵魂——性能
    大型网站系统架构的演化
    c# url自动解码解决方案
    C# RSA非对称加密实现
    .net上传图片之使用第三方平台七牛上传图片接口
  • 原文地址:https://www.cnblogs.com/wujianming-110117/p/12722286.html
Copyright © 2011-2022 走看看