Android音视频【五】H265/HEVC&码流结构

人间观察
我好像还什么都没有准备好,就到了而立之年的年纪,不是吃一个糖就能开心的年纪了。

前面我们了解了H264/AVC的一些知识。今天我们看H265 , 只有了解了这些基础的,什么协议(flv等)啦,什么封装格式(mp4等)啦,网络传输啦等都是很有帮助的。

背景知识

H265 又被叫做HEVC(全称叫做 Hight Efficiency Video Coding,高效率视频编码),它同H264一样也是ITU-T和ISO两个组织共同制定的视频压缩标准,是H264/AVC标准的继承者。

H265/HEVC是面向更高清晰度、更高帧率、更高压缩率视频的协议标准,是一套标准组织制定的视频压缩标准、规范。

为什么会有h265

说白了就是人们对视频的要求清晰度越来越高,而在有限的带宽下保证视频的质量是很难的。对于2k,4k的高清视频来说在存储空间和网络带宽有限的情况下,现有的视频压缩技术已经不能满足现实的应用需求。为了解决高清及超高清视频急剧增长的数据率给网络传输和数据存储带来的冲击,所以有了具有更高压缩效率的新一代视频压缩标准H265/HEVC。

标清:480x800
普通高清:720x1280 720P
高清:1920x1080 1080P
2K:2048*1024
超高清 4K:3840x2160

嗯,说白了,就是需求导致,然后产生的标准。ok,我们看一下技术上:

(1) 视频画面要求更高(如上),视频流畅度要求更高,帧率从30fps到60fps甚至更高,会导致H264的如下情况:

  • 宏块(MB)个数爆发式增加
  • 宏块内容的复杂度升高
  • 运动矢量数值的大幅度增加

(2) 由于H264本身的缺点
由于宏块级压缩视频的处理过程,很久没有改变了,还是2003年发布的实现方式,它的压缩算法没有调整。

H265延续了H264的很多定义,两个都是基于宏块的视频编码技术,h265是在H264的基础上进行了一些强优化。比如:

  • 以宏块来划分图像,并最终以块来细分。
  • 使用帧内压缩技术减少空间冗余
  • 使用帧间压缩技术减少时间冗余(运动估计和运动补偿)
  • 使用转换和量化来进行残留数据压缩
  • 使用熵编码来减少残留,运动矢量传输和信号发送中的最后冗余。

上面的描述太过于官方了,但是我这里还是参考一些书籍写下了(怕有遗漏造成理解偏差/知识的丢失就不好了),上面的这些技术都是编码器的内部实现,都是算法。我也知道这些概念而已,至于如何实现的我还清楚,我觉得我还没有到达到这一步,前几天看到了阿里淘系的音视频团队有自己的编码器实现,叫奇点编码器,还是觉得很厉害的。

H265的码流结构

H265 的码流结构和H264的结构类似

网络分层结构

H264/AVC结构类似,H265/HEVC也采用了视频编码层(video code layer ,简称VCL)和网络适配层(network abstract layer,简称NAL).VCL层包含了视频压缩的数据, NAL主要负责对数据的压缩数据进行划分和封装,保证数据在磁盘上保存和网络上进行传输。

和h264的码流结构一样,也是通过启始码(0x000001或者0x00000001)进行分割压缩数据,每一个称为NAL单元(NAL Unit,简称NALU)。NALU有不同的类型,主要是对数据内容进行区分。

对于一个码流文件来说,和h264一样,有一系列的NALU的类型定义,可以分为VPS,SPS,PPS,SEI,I帧,P帧 6种类型。码流结构如下所示:

启始码+VPS+启始码+SPS+启始码+PPS+启始码+SEI+启始码+I帧+启始码+P帧+启始码+P帧+.....

如上就是一个图像系列的组成,为什么这么说呢? 一般我们在网络上发送数据,比如采集端一般在发送压缩数据的I帧前先发送VPS,SPS,PPS。解码端不可能先启动后等着发送端数据到来吧,只有解码器拿到VPS,SPS,PPS后才可以解码H265的数据。VPS,SPS,PPS,SEI,一个I帧,一个P帧都可以常委一个NALU。

从上面可以看到h265比h264多了一个VPS,VPS是视频参数集。

我们这里看一下经过h265编码器编码后的码流文件,截取文件开头的数据,
因为h265码流最开始永远是VPS,SPS,PPS,可能含有SEI,后面接着是I帧P帧数据。
16进制打开文件如下:

0000 0001 4001 0c01 ffff 0160 0000 0300 // 4001
b000 0003 0000 0300 5aac 0900 0000 0142 // 4201
0101 0160 0000 0300 b000 0003 0000 0300
5aa0 0442 00f0 77e5 aee4 c92e a520 a0c0
c05d a142 5000 0000 0144 01c0 e30f 0330 // 4401
840a 0000 0001 2601 af0b e075 8d53 b010 // 2601
af65 bfb4 0b53 823d e91c ad66 f973 ce21
5d92 9227 9159 3dc6 2cae 5adf 4cda f9b5
6105 3165 97cd 64cd f04d 09d5 5e10 d231
// ...省略其它数据
2f04 c9cc 1e01 700a 0000 0001 0201 d08f // 0201
// ...省略其它数据

单元NALU的结构

可以看到上面的数据和h264一样,H265的NALU的结构也是:启始码+ NALU头+NALU数据。
如果NALU对应的Slice为一帧的开始(即视频流的首个NALU)就用0x00000001,否则就用0x000001

  • 启始码:是一个固定值4个字节00 00 00 01(十六进制)或者3个字节00 00 01(十六进制)
  • NALU的头大小为2个字节,第1位是0,第2-7位是NALU的类型,表示该NALU的数据内容是什么类型的,是VPS,SPS,PPS,SEI,I帧还是P帧。第8-15位是1
  • NALU的数据就是编码器编出来的图像信息或者图像压缩数据了

NALU的nal_unit_type官方文档所示:

h265-nal_unit_type.png

可以上面的文件数据片段中可以计算出6种NALU的头类型nal_unit_type,取2个字节的2-7位即可。计算方法:

// 0x7E的二进制的后8位是 0111  1110
 int naluType = (byteOffset & 0x7E) >> 1

byteOffset就是00 00 00 01或者00 00 01后面的2个字节。

  • VPS(视频参数集)NALU的头值为0x4001(十六进制),取出2-7位(40 & 0x7E)>>1 =32(十进制)
  • SPS(序列参数集)NALU的头值为0x4201(十六进制),取出2-7位(42 & 0x7E)>>1 =33(十进制)
  • PPS(图像参数集)NALU的头值为0x4401(十六进制),取出2-7位(44 & 0x7E)>>1 =34(十进制)
  • SEI(补充增强信息)NALU的头值为0x4e01(十六进制),取出2-7位(4e & 0x7E)>>1 =39(十进制)
  • I帧 NALU的头值为0x2601(十六进制),取出2-7位(26 & 0x7E)>>1 =19(十进制)
  • P帧 NALU的头值为0x0201(十六进制),取出2-7位(02& 0x7E)>>1 =1(十进制)

NALU的类型官方文档所示:

H265-nalu-type.png

RBSP的结构

H265的 RBSP(raw byte sequence payload)和H264的一样。

NAL 根据送压缩数据的规则,可以封装称不同的NALU, NALU包含VPS,SPS,PPSl类型信息,还包含视频片(Slice)的压缩数据,包含压缩的NALU被称为VCLU(VCL NALU),包含其它信息的压缩数据的NALU,则被称为non-VCLU(non-VCL NALU)。

H265下的NALU包含两部分数据结构:NALU头(header)和负载(payload),NALU头长度为固定的2字节,反应NALU的内容特征,而NALU的负载长度为整数字节,包含视频压缩后的原始字节序列负载RBSP(raw byte sequence payload)。RBSP是对视频 编码后的原始比特流片段SODB(string of data bits)进行添加尾部(添加比特1,以凑足整字节)的包装。

同样在H265中,为了避免字节流片段和NALU的启起码及结束码发生冲突,需要对RBSP的字节流进行冲突处理0x3,经过处理后的rbsp才可以直接作为NALU的负载信息,才可以进程磁盘保存和网络传输。
关于冲突和RBSP的结构的结构可以参考之前的h264码流分析文章:
Android音视频【二】 H264码流结构

H265远比此篇介绍的复杂的多,如果哪里不正确,欢迎指正。

H265官方文档,可以下载里面的pdf文件:
https://www.itu.int/rec/T-REC-H.265-201911-I/en

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容