H265标准自2013年推出以来,一直受限于CPU或者GPU硬解性能的限制,难以普及。

IOS11的VideoToolbox支持硬解H265,开发者可以调用提供的接口实现HEVC的硬解。而安卓阵营近几代SOC芯片早就支持了H265的硬解,并且其计算能力也强大到出现了出现了讨论是否性能过剩的现象。至于PC端,由于PC设备更新速度远没有移动设备快速,目前在用的PC设备性能参差不齐,并且这类现象会持续一长段时间。

推流侧的H265比拉流要容易推广,主播向来持有的设备性能都较强,也是比较新的旗舰产品,一般都可以支持HEVC的硬编。

在CDN侧,各大CDN服务提供商大多数均已支持了H265格式的视频数据分发。

基于以上,预测2018年,各大视频内容提供商处于CDN带宽成本考虑,应该会把H265作为一个比较重要的工作项目。

所以,我们学习下H265的码流格式。

FLV与H265

FLV是一个Adobe公司为flash播放器(SWF)配套推出的视频封装格式。由于其格式结构简单,配套方案成熟,在流媒体行业内应用十分广泛。

虽然FLV的标准几乎每年都在更新,但是Adobe并没有让FLV支持H265。FLV支持的编码格式有以下几种(引自wikipedia):

Id Video encoding
0 RGB
1 run-length
2 Sorenson's H.263
3 Screen 1
4 On2 TrueMotion VP6
5 VP6 with alpha
6 Screen 2
7 MP4 H.264
8 ITU H.263
9 MPEG-4 ASP.

目前国内直播大多数采用HTTP-FLV的拉流方式,其原因是HTTP可以保证在TCP握手成功之后马上发起GET请求,不像RTMP那样还需要进行RTMP应用层面的握手以及各类message消息的传输来确定许多参数,从而保证较快的首屏时间。至于HLS,HDS,MSS,MPEG-DASH等基于切片的,在国外直播中较为常见,国内的直播普遍无法接受切片带来的延迟,因此HTTP-FLV在国内直播行业内应用广泛。

理所当然的,大家也都希望将H265的码流也封装进FLV中,如此可以省去很多适配工作。

因此,便有了非官方的墨守成规的”标准“了。

FLV中,Video Tag中的Tag Data中的第一字节的低四位表示编码格式CodecID,其取值便如上述表格所示,常见的是7,即AVC编码方式。而非官方的大家普遍的做法是将0XC=12D标志为HEVC。

CodecID

H265码流格式

2018年2月6日补充,在非官方的FLV封装265码流中,基本与264一致,分为265标准自带的附录B(Annex-B)和avcC类似的hvcC。

hvcC一般解析

hvcC
  1. 2C
  2. 2,代表非关键帧
  3. CH=12D,代表CodecID=12D,为hevc
  4. 01
  5. 沿用AVC中的格式
  6. 00 00 00
  7. 沿用AVC中的格式
  8. 00 00 15 B0
  9. 代表下一个NALU的长度为15B0H=5552D字节
  10. 02 01H=0000 0010 0000 0001B,NAL units header
  11. 第一位,1比特,0,禁止位,forbidden_zero_bit。非零代表异常;
  12. 第二至七位,6比特,000001,NALU类型,nal_unit_type。
    常见的类型有:
    1. 40 01H-->nal_unit_type=32D,VPS
    2. 42 01H-->nal_unit_type=33D,SPS
    3. 44 01H-->nal_unit_type=34D,PPS
    4. 4E 01H-->nal_unit_type=39D,SEI
    5. 26 01H-->nal_unit_type=19D,IDR
    6. 02 01H-->nal_unit_type=1D,被参考的后置图像
  13. 第八至十三位,6比特,000000,nuh_layer_id,一般取值为0,非0为3D等特殊视频。
  14. 第十四至十六位,3比特,001,nuh_temporal_id_plus1,NALU所在时域层的标识号temporalId+1。

hvcC头解析

CodecID
  1. 1C
    1. 1,代表关键帧
    2. CH=12D,代表CodecID=12D,为hevc
  2. 01
    1. 沿用AVC中的格式
  3. 00 00 00
    1. 沿用AVC中的格式
  4. 00 00 00 19
    1. 下一个NALU的长度为19H字节
  5. 40 01 0C 01 ...
    1. 40 01 : VPS
  6. 00 00 00 28
    1. 下一个NALU的长度为28H字节
  7. 42 01 01 01 …
    1. 42 01 : SPS
  8. 00 00 00 08
    1. 下一个NALU的长度为8H字节
  9. 44 01 C1 71 …
    1. 44 01 : PPS
  10. 00 03 A0 C1
  11. 下一个NALU的长度是03A0C1H字节
  12. 26 01 ..
    1. 26 01 : IDR

Annex-B一般解析

CodecID
  1. 1C
    1. 1,代表关键帧
    2. CH=12D,代表CodecID=12D,为hevc
  2. 01
    1. 沿用AVC中的格式
  3. 00 01 F4
    1. 沿用AVC中的格式
  4. 00 00 00 01
    1. Start code : 分隔符
  5. 26 01 …
    1. 26 01 : IDR
  6. 00 00 03 00 …
    1. 此处0x03即防竞争字节,emulation_prevention_three_byte

Annex-B头解析

CodecID
  1. 1C
    1. 1,代表关键帧
    2. CH=12D,代表CodecID=12D,为hevc
  2. 01
    1. 沿用AVC中的格式
  3. 00 00 00
    1. 沿用AVC中的格式
  4. 00 00 00 01
    1. Start code : 分隔符
  5. 40 01 …
    1. 40 01 : VPS
  6. 00 00 00 01
    1. Start code : 分隔符
  7. 42 01 …
    1. 42 01 : SPS
  8. 00 00 00 01
    1. Start code : 分隔符
  9. 44 01 …
    1. 44 01 : PPS