目录
一、AV1编码技术
AV1是由开放媒体联盟(AOM,Alliance for Open Media)在2018年发布的,AV1的前身是VP9。AOM的成员已经涵盖了Amazon、Cisco、Google、Intel、Microsoft、Mozilla、Netflix、AMD、ARM和 NVIDIA,它成立的目的是为互联网和其他市场创建一个开源的视频编解码器(AV1,AOMedia Video codec),旨在取代VP9并成为与HEVC(H.265)竞争的主要视频编码标准,AV1压缩率比流行的H.264格式高50%、比VP9格式高20%。
AV1诞生原因:
1、专利费
先说专利费,可能刚开始所有人都没有想到H.265的专利费使用会如此之高,授权政策如此复杂。举例HEVC Advance,收费范围广泛同时费用高到令人乍舌。电视、智能手机、流媒体播放器、机顶盒、游戏主机、数字媒体存储设备、监控设备等几乎所有的硬件终端以及Netflix、YouTube等内容提供商都需要付高昂的费用,虽然之前微微下调了一下,但是杯水车薪。终端设备要缴纳0.2-1.2美元不等,封顶年费4000万美元。在内容方面,除了对终端用户提供免费内容的供应商外,其他内容提供商也要根据订阅数、节目数和媒体数收费,封顶年费500万美元。以此估算,每年需向三个专利池和Technicolor公司缴纳的H.265/HEVC专利许可封顶费用会超过1亿美元,鲜血淋漓。
2、反垄断
H.265贵,谷歌趁机出了一个免费的VP9,坚持免费开源,同时解码难度相对更低。但风险点就在于如果VP9广泛面世,那么如此重要的国际标准就会被单个独立巨头垄断,未知风险非常大,可以说是被扼住咽喉。当下企业级市场,侧重点基本都以HEVC/H.265为主,很少看到基于VP9的产品面世,这其中最重要的理由就是,行业中绝大多数企业根本不愿意让这么重要的国际标准被一个独立的公司(谷歌)所控制。
AV1特点:
- 高效压缩:AV1旨在比现有的视频编码标准(如H.264/AVC和HEVC/H.265)提供更高的数据压缩率,这意味着在相同的视频质量下,AV1编码的视频文件将占用更少的存储空间和带宽。
- 开放和免费:与某些其他视频编码标准(如HEVC)不同,AV1是完全开放且免版税的,这使得它对于开发人员和内容创作者来说是一个吸引人的选择,因为它消除了版权费用的负担。
AV1官网地址:https://aomedia.org/
由于是新一代编码技术,虽然具有较高的技术优势,但由于其推出时间相对较晚,市场占有率还不高。目前主要应用于一些对画质要求较高、对成本敏感的领域,如在线视频、OTT 服务等,硬件加速也不像H264/H265那样普及。
二、AV1码流结构(OBU)
YUV视频经过AV1编码之后有以下两种输出格式:
low-overhead bitstream format:由一系列OBU(Open Bitstream Units)组成。
length-delimited format:标准的Annex B规定了temporal_unit组成bitstram的方式,下图描述了如何将一个temporal_unit打包起来,而多个temporal_unit进行组合则形成了bitstream。该格式优点是很方便跳过某些帧或者temporal_unit。

编码器默认输出格式一般都是low-overhead bitstream format。
OBU类似于H26x中的NALU,H26x码流由NALU(包括起始码)组成,而AV1码流由OBU组成,如下图所示(Elecard Stream Analyzer高版本可解析AV1码流,软件收费,免费使用30天,网上的破解版都比较老,不支持AV1):

上图是AV1的裸流文件,就是由不同类型的OBU组成。和NALU一样,OBU也是由header和payload组成,OBU头部定义如下:
open_bitstream_unit( sz ) {
obu_header()
if ( obu_has_size_field ) {
obu_size //leb128()
} else {
obu_size = sz - 1 - obu_extension_flag
}
....
}
obu_header() {
obu_forbidden_bit // f(1)
obu_type // f(4)
obu_extension_flag // f(1)
obu_has_size_field // f(1)
obu_reserved_1bit // f(1)
if ( obu_extension_flag == 1 )
obu_extension_header()
}
obu_extension_header() {
temporal_id //f(3)
spatial_id //f(2)
extension_header_reserved_3bits //f(3)
}
f(n)表示字段占多少了bit;
obu_forbidden_bit:一定是0,没有实际意义
obu_type:表示obu的类型
| obu_type | Name of obu_type | Description |
| 0 | Reserved | |
| 1 | OBU_SEQUENCE_HEADER | 功能类似SPS |
| 2 | OBU_TEMPORAL_DELIMITER | 时间分隔符,每帧前面都要加 |
| 3 | OBU_FRAME_HEADER | 功能类似PPS |
| 4 | OBU_TILE_GROUP | 一帧由N个TILE_GROUP组成,编码主要信息在此type内 |
| 5 | OBU_METADATA | 声明 profie,level,svc,HDR信息等 |
| 6 | OBU_FRAME | 一个obu_frame就是一帧,一帧有n个tile group |
| 7 | OBU_REDUNDANT_FRAME_HEADER | 当前obu采用上一个obu hdr |
| 8 | OBU_TILE_LIST | 用于large scale,见Annex D |
| 9-14 | Reserved | 保留 |
| 15 | OBU_PADDING | 填充OBU,解码器可以忽略整个padding OBU单元 |
obu_extension_flag:是否包含extension_header
temporal_id,spatial_id:obu_extension_flag为0时,这两个flag默认为0,大于0时表示为增强层图像;temporal_id表示帧率的分层,spatial_id表示图像分辨率的分层
obu_has_size_field:该码流里是否包含了obu_size; obu_size表示该obu若是frame或者一组tile信息时,这些frame和tile的所占字节长度;默认值为obu_size = obu_length - 1 - obu_extension_flag;Low overhead bitstream format格式要求obu_has_size_field必须为1。
obu_size:leb128()读取可变长的小字端的无符号整形数,读取一个字节时,如果最高比特为1表示需要读取更多的字节,为0表示这是最后一个字节了。解析过程如下:
leb128() {
value = 0
Leb128Bytes = 0
for (i = 0; i < 8; i++) {
leb128_byte //f(8)
value |= ( (leb128_byte & 0x7f) << (i*7) )
Leb128Bytes += 1
if ( !(leb128_byte & 0x80) ) {
break
}
}
return value
}
1、Sequence Header OBU
视频宽高和帧率可以通过Sequence Header OBU获取,Sequence Header OBU定义如下:
sequence_header_obu( ) { Type
seq_profile f(3)
still_picture f(1)
reduced_still_picture_header f(1)
if ( reduced_still_picture_header ) {
timing_info_present_flag = 0
decoder_model_info_present_flag = 0
initial_display_delay_present_flag = 0
operating_points_cnt_minus_1 = 0
operating_point_idc[ 0 ] = 0
seq_level_idx[ 0 ] f(5)
seq_tier[ 0 ] = 0
decoder_model_present_for_this_op[ 0 ] = 0
initial_display_delay_present_for_this_op[ 0 ] = 0
} else {
timing_info_present_flag f(1)
if ( timing_info_present_flag ) {
timing_info( )
decoder_model_info_present_flag f(1)
if ( decoder_model_info_present_flag ) {
decoder_model_info( )
}
} else {
decoder_model_info_present_flag = 0
}
initial_display_delay_present_flag f(1)
operating_points_cnt_minus_1 f(5)
for ( i = 0; i <= operating_points_cnt_minus_1; i++ ) {
operating_point_idc[ i ] f(12)
seq_level_idx[ i ] f(5)
if ( seq_level_idx[ i ] > 7 ) {
seq_tier[ i ] f(1)
} else {
seq_tier[ i ] = 0
}
if ( decoder_model_i

最低0.47元/天 解锁文章
2962

被折叠的 条评论
为什么被折叠?



