h.265音视频开发,H265码音视频流解析

H.265技术的应用

编码技术主要运用于视频播放设备、软件应用以及拍摄、录制视频的设备。人们最熟悉的莫过于PPS网络视频播放器。在PC屏客户端产品上面,PPS已经于2013年初推出了基于H.265标准的高清视频,并命名“臻高清”为自己的高清品牌。同时 PPS不断加大了在H.265技术应用方面的研究,把H.265推向手机客户端,且在性能上不断优化提升。

名词

  • CTU: 编码树单元
  • CU: 编码单元
  • PU: 以CU为根,对CU进行划分,一个预测单元PU包含一个亮度预测块PB和两个色度预测块PB.
  • TU: 以CU为根,变换单元TU是在CU的基础上划分的,跟PU没有关系,采用四叉树划分方式,具体划分有率失真代价决定,下图给出了某个CU划分成TU的结构。

H265-NALU-Type介绍

NAL_TRAIL_N = 0, NAL_TRAIL_R = 1, NAL_TSA_N = 2, NAL_TSA_R = 3, NAL_STSA_N = 4, NAL_STSA_R = 5, NAL_RADL_N = 6, NAL_RADL_R = 7, NAL_RASL_N = 8, NAL_RASL_R = 9, NAL_BLA_W_LP = 16, NAL_BLA_W_RADL = 17, NAL_BLA_N_LP = 18, NAL_IDR_W_RADL = 19, NAL_IDR_N_LP = 20, NAL_CRA_NUT = 21, NAL_VPS = 32, NAL_SPS = 33, NAL_PPS = 34, NAL_AUD = 35, NAL_EOS_NUT = 36, NAL_EOB_NUT = 37, NAL_FD_NUT = 38, NAL_SEI_PREFIX = 39, NAL_SEI_SUFFIX = 40,

H265码流格式

VPS:视频参数集,用于传输视频分级信息,有利于兼容标准在可分级视频编码或多视点视频的扩展。

NALU header定义:

NALU header(){Descriptor
forbidden_zero_bitf(1)
nalu unit typeu(6)
nuh_layer_idu(6)
nuh_temporal_id_plus1u(3)

H264的NALU type是首字节&0x1f,H265的NALU type是(首字节&0x7E)>>1;

NALU type定义:

/**
 * Table 7-3: NAL unit type codes
 */
enum HEVCNALUnitType {
    HEVC_NAL_TRAIL_N    = 0,
    HEVC_NAL_TRAIL_R    = 1,
    HEVC_NAL_TSA_N      = 2,
    HEVC_NAL_TSA_R      = 3,
    HEVC_NAL_STSA_N     = 4,
    HEVC_NAL_STSA_R     = 5,
    HEVC_NAL_RADL_N     = 6,
    HEVC_NAL_RADL_R     = 7,
    HEVC_NAL_RASL_N     = 8,
    HEVC_NAL_RASL_R     = 9,
    HEVC_NAL_VCL_N10    = 10,
    HEVC_NAL_VCL_R11    = 11,
    HEVC_NAL_VCL_N12    = 12,
    HEVC_NAL_VCL_R13    = 13,
    HEVC_NAL_VCL_N14    = 14,
    HEVC_NAL_VCL_R15    = 15,
    HEVC_NAL_BLA_W_LP   = 16,
    HEVC_NAL_BLA_W_RADL = 17,
    HEVC_NAL_BLA_N_LP   = 18,
    HEVC_NAL_IDR_W_RADL = 19,
    HEVC_NAL_IDR_N_LP   = 20,
    HEVC_NAL_CRA_NUT    = 21,
    HEVC_NAL_IRAP_VCL22 = 22,
    HEVC_NAL_IRAP_VCL23 = 23,
    HEVC_NAL_RSV_VCL24  = 24,
    HEVC_NAL_RSV_VCL25  = 25,
    HEVC_NAL_RSV_VCL26  = 26,
    HEVC_NAL_RSV_VCL27  = 27,
    HEVC_NAL_RSV_VCL28  = 28,
    HEVC_NAL_RSV_VCL29  = 29,
    HEVC_NAL_RSV_VCL30  = 30,
    HEVC_NAL_RSV_VCL31  = 31,
    HEVC_NAL_VPS        = 32,
    HEVC_NAL_SPS        = 33,
    HEVC_NAL_PPS        = 34,
    HEVC_NAL_AUD        = 35,
    HEVC_NAL_EOS_NUT    = 36,
    HEVC_NAL_EOB_NUT    = 37,
    HEVC_NAL_FD_NUT     = 38,
    HEVC_NAL_SEI_PREFIX = 39,
    HEVC_NAL_SEI_SUFFIX = 40,
};

丢帧

在性能不足,或者音画不同步时,需要进行丢帧,H264丢帧根据nal_ref_idc来判断,H265根据来NALU type判断。以下type是可以丢帧,且不花屏的:

HEVC_NAL_TRAIL_N、HEVC_NAL_TSA_N、HEVC_NAL_STSA_N、HEVC_NAL_RADL_N、HEVC_NAL_RASL_N。

H265码流分析

H265相比较于H264,除了包含SPS、PPS外,还多包含一个VPS;在NALU header上,H.264的HALU header是一个字节,而H.265则是两个字节。

以OX4001为例,头信息可以被解析成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

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

NALU类型 = (NALU头第一字节 & 0x7E) >> 1 与H.264类似,H.265码流也有两种封装格式,一种是用起始码作为分界的Annex B格式,另一种则是在NALU头添加NALU长度前缀的格式,称为HVCC。

H265码流分析帧类型

  • nal单元分割

寻找0x000001或者0x00000001, 规则如下:

  1. 每个NALU前面都有起始码0x000001, 3bits
  2. 如果NALU类型为vps, sps, pps, 或者解码顺序为第一个AU的第一个NALU, 起始码前面再加一个0x00
  3. 视频流的首个NALU的起始码前加入0x00 实际分析中,不必要整的这么复杂,只要找到0x000001或者0x00000001即可
  • 上图中的码流nal拆分为: 第一帧: 0000 0001 4001 0c01 ffff 0160 0000 0300 0003 0000 0300 0003 00ba 9702 40 第二帧: 00 0000 0142 0101 0160 0000 0300 0003 0000 0300 0003 00ba a00f 0804 47f9 65e4 91b6 1c5e 4924 fe79 fcf2 ffff ffcf e7f3 f3f9 d9 第三帧: 00 0000 0144 01c1 9095 8112 第四帧: 0000 0126 01af 1380 790b dc5c 557c 74...
  • NAL类型分析 类型枚举定义

enum NALUnitType {
    NAL_TRAIL_N    = 0,
    NAL_TRAIL_R    = 1,
    NAL_TSA_N      = 2,
    NAL_TSA_R      = 3,
    NAL_STSA_N     = 4,
    NAL_STSA_R     = 5,
    NAL_RADL_N     = 6,
    NAL_RADL_R     = 7,
    NAL_RASL_N     = 8,
    NAL_RASL_R     = 9,
    NAL_BLA_W_LP   = 16,
    NAL_BLA_W_RADL = 17,
    NAL_BLA_N_LP   = 18,
    NAL_IDR_W_RADL = 19,
    NAL_IDR_N_LP   = 20,
    NAL_CRA_NUT    = 21,
    NAL_VPS        = 32,
    NAL_SPS        = 33,
    NAL_PPS        = 34,
    NAL_AUD        = 35,
    NAL_EOS_NUT    = 36,
    NAL_EOB_NUT    = 37,
    NAL_FD_NUT     = 38,
    NAL_SEI_PREFIX = 39,
    NAL_SEI_SUFFIX = 40,
};

类型判断方式为分隔符之后的第一个字节右移一位的值 第一帧:0x40 >> 1 , 得到0x20,十进制32,为NAL_VPS 第二帧:0x42 >> 1 , 得到0x21, 十进制33, 为NAL_SPS 第三帧:0x44 >> 1 , 得到0x22, 十进制34, 为NAL_PPS 第四帧:0x26 >> 1 , 得到0x13, 十进制19, 为NAL_IDR_W_RADL

  • 代码如下

static int hevc_probe(char* pbuf, int buf_size)
{
    unsigned int code = -1;
    int vps = 0, sps = 0, pps = 0, irap = 0;
    int i;
    
    for (i = 0; i < buf_size - 1; i++) {
        code = (code << 8) + pbuf[i];
        if ((code & 0xffffff00) == 0x100) {
            char nal2 = pbuf[i + 1];
            int type = (code & 0x7E) >> 1;
            
            if (code & 0x81) // forbidden and reserved zero bits
                return 0;
            
            if (nal2 & 0xf8) // reserved zero
                return 0;
            
            switch (type) {
                case NAL_VPS:        vps++;  break;
                case NAL_SPS:        sps++;  break;
                case NAL_PPS:        pps++;  break;
                case NAL_BLA_N_LP:
                case NAL_BLA_W_LP:
                case NAL_BLA_W_RADL:
                case NAL_CRA_NUT:
                case NAL_IDR_N_LP:
                case NAL_IDR_W_RADL: irap++; break;
            }
        }
    }
    
    return 0;
}

image

以上主要解析了音视频开发中的,H265码流的码流格式、NALU-Type、码流分析、帧类型分析等等。

文末

H265码流结构

H265的视频流中也是存在多个GOP,每一个GOP里面包含多个视频编码帧。H265支持的视频编码帧类型有IDR帧、I帧、P帧、B帧,这些帧类型的含义和H264码流的帧类型的含义是一样,作用也是一样,比如IDR帧和I帧都是帧内压缩编码,IDR帧是即时解码刷新帧,也是关键帧;P帧是前向参考帧,B帧是双向参考帧。


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值