一、H265的优势和特点
H265编码(也称之为HEVC编码),它是继H264之后所制定的一个全新的视频编码标准。H265保留了许多H264的技术,并在H264的基础上使用了全新的技术来改善编码质量和画面质量。H265的优势在于超高的压缩比(压缩比高达1:200)编码超高清的分辨率,如:4K分辨率(3840 * 2160)、8K分辨率(7680 * 4320),一般只有在编码超高清分辨率的时候才会用到H265编码,普通的分辨率如:1920 * 1080以下的分辨率只需要H264即可(这是由于H265虽然压缩比非常高,但是它的算法复杂程度也远超H264,对于一般播放器来说CPU运算也过于复杂)。
二、H265的帧内预测
H265的帧内预测比H264更加灵活,H264帧内预测只支持16 * 16的宏块。但是H265能够支持支持多种尺寸的宏块预测,包括4 * 4、8 * 8、16 * 16、32 * 32多种宏块的预测。 下面我们来看看,两种编码格式的区别。
从上面两张图我们可以看出来,H264视频文件处理的宏块基本上都是固定16 * 16。而H265视频文件处理的宏块范围就比较广了,从4 * 4到32 * 32的宏块都可以进行编码。那么宏块广泛的好处就是H265编码的细节就会更加清晰,对绝大部分物体都可以进行清晰编码,这一点比H264编码要强。如下图:
除了多种尺寸的宏块预测外,HEVC总共还提供了35种预测模式,对比H264的9种帧内预测模式。H265的帧内预测模式是H264的4倍以上。下面我们来看看,HEVC的35种帧内预测模式。
从上面这张图我们可以看出来,35种帧内预测模式本质上可以分成三种帧内预测模式。
0:Planner模式,它主要适用于像素变化缓慢区域,它和其他模式相比能够动态调节视频质量。
适合只有草这种静止的绿色植物
1:DC模式,主要适用于大面积平坦区域;适合例如沙漠、草原这种。
2-34就是33种角度预测,如图3,从这张图我们来看看,这33种角度模式,相当于33个角度向量的预测。
(图3)
三、H265的帧间预测
H265帧间预测可以智能识别出前一帧图像的复杂画面和简单画面,并把数据传输到下一个p帧
在HEVC中,帧间预测单元PU总共有8种划分方式,包括4种对称方式:2Nx2N、2NxN、Nx2N、NxN和4种非对称模式:2NxnN、2NxnD、nLx2N、nRx2N(如图1)。PU指的是帧间预测的基本单元,每个单元通过帧间预测获得一组运动数据。HEVC定义了两种帧间预测模式:分别是帧间模式(inter mode)、合并模式(merge mode)。
1.Merge模式:
Merge模式会为当前预测单元建立一个MV候选表,在列表中存在着5个候选MV。通过遍历5个候选MV,同时进行失真率计算,最终选择失真率最低的MV作为最优的MV。假设编/解码依旧相同的候选表,编码器只需要传输最优MV索引,这样就可以大幅度节省运动信息传输数。(MV指的是运动向量)
在空域领域最多提供4个候选MV,最多使用5个候选中的4个候选块的运动信息,如列表所示按照A1-B1-B0-A0的顺序建立起来。这其中B2属于替补位置,当A1、B1、B0、A0中只有一个或者多个不存在的时候,此时就需要用到B2。下面我们来看看,时域候选列表的建立过程
它的过程如下:
利用当前PU在邻近已编码图像中找到对应的PU位置的运动信息,相比于空域,时域候选表不能直接使用候选块的信息,它是需要根据参考图像位置来做对应的比例伸缩调整。
curr_PU表示的是当前PU(预测单元)
col_PU表示的是同位PU
td和tb分别表示图像cur_pic、同位col_pic与二者参与图像cur_ref、col_ref之间的距离
当前的PU时域候选MV计算公式为:curPU = (td/tb)*colPU;
2.Inter模式:
Inter模式也称之为AMVP模式(高级运动向量预测),它是利用空域、时域上运动变量的相关性,并且为当前PU建立了候选的预测MV列表。HEVC编码器会从中选出最优的预测MV。HEVC编码器从中选择最优质的预测MV,并对MV进行编码。下面我们来看看inter模式如何计算当前PU
从上面这张图我们可以看出,inter处理过程是从空域MV列表5个里面选择2个,时域MV列表2个选择1个,紧接着去除重复的MV,然后填补零矢量(填补0,0),保留候选列表中前2个MV,最后选择出最优MV。
注意:这里要科普两个东西分别是空域和时域
空域:指的是像素域,换言之空域处理就是在像素级别进行处理,比方说像素叠加等等。
时域:自变量是时间,换言之横轴是时间,纵轴是信号的变化。
四、H265重点帧类型的讲解
在H265中,绝大部分的结构都和H264是一样,但是H265码流增加了一个NALU结构,那就是VPS。VPS的主要作用是对传输的视频进行分级,视频分级的最主要作用是有利于兼容标准在多视点视频的扩展,下面是一个经典H265的NALU结构
VPS:视频参数集(NALU:00 00 00 01 40 01),VPS主要用于传输视频的分级信息,它用于兼容可分级视频编码和多视点的扩展。
H265中加入该结构主要目的是兼容标准在系统多字方面的扩展。可分级编码主要解决的是根据网络情况的好坏来判断传输什么类型的数据。
比方说在弱网环境下可分级编码可以使得视频数据只保留基本的信息进行传输,并实时根据网络的情况动态来决定是否传输增强的视频信息从而使得图像质量得以提升,我们来看看每个VPS里面的内容。
vps_video_parameter_set_id:当前的VPS标识号
vps_reserved_three_2bits:保留位,其值为3
vps_max_layers_minus1:当前保留位,其数值为0,主要用于3D视频的编码或者可分级视频编码使用。
vps_max_sub_layers_minus1:表示比特流中可支持子层的最大数目减一,最大可以支持7个子层。
vps_temporal_id_nesting_flag:
当vps_max_sub_layers_minus1等于0时,这个参数为1;
当vps_max_sub_layers_minus1大于0时,这个参数指定是否对帧间预测进行限定。
该参数主要用于子层升档,相当于从低子层升级到高子层。
vps_reserved_0xffff_16bits:两字节的保留位
vps_sub_layer_ordering_info_present_flag:等于1的时候
vps_max_dec_pic_buffering_minus[1]、
vps_max_num_reorder_pics[1]、
vps_max_latency_incresing_plus[1]
并用于vps_max_sub_layers_minus1 + 1子层;
当这个值等于0的时候,三个语法都可以用于所有子层。
vps_max_dec_pic_buffering_minus1[i]:当HighestTid等于i的时候,CVS图像存储单元中解码图像所需要的最大缓存。
vps_max_num_reorder_pics[i]:规定了HighestTid等于i的时候,在CVS解码顺序在某一副图像之中,而显示顺序在该图像之前的最大数量
vps_max_latency_incresing_plus1[i]:当HighestTid等于i时,该语法元素用于计算VpsMaxLatencyPictures[i]的数值
vps_max_layer_id:指定CVS所有的NAL单元nuh_layer_id的最大值
vps_num_layer_sets_minus1:指定VPS中图层集的数量,该语法被要求是0。解码器的范围是0-1023之间的值
vps_timing_info_present_flag:该语法取值等于1,表示在VPS中存在vps_num_units_in_tick、vps_time_scale、vps_poc_proportional_to_timing_flag、vps_num_hrd_parameters存在;当为0的时候,则表示VPS不存在上面这四个元素
SPS:序列参数集(NALU:00 00 00 01 42 01),一段H265视频码流可能包含一个或者多个编码的视频序列号。SPS的内容包含了一个CVS里面所有编码图像的编码参数,SPS通过被PPS引用并且作用在编码图像,值得注意的是一个CVS中所有被使用的PPS必须引用到同一个SPS里面。实际上,SPS为编码图像提供了公共参数,如图像格式,档次,编码等级,若一个SPS被引用的时候,整个SPS都处于激活状态。
sps_video_parameter_set_id:指定当前激活的VPS的ID号
sps_max_sub_layers_minus1:用于指定时域子层的最大数目
sps_temporal_id_nesting_flag:当sps_max_sub_layers_minus1大于0的时候,其规定是否额外限制帧间预测的范围。当sps_max_sub_layers_minus1为0时,该语法取值是1。
sps_seq_parameter_set_id:表示当前SPS的ID号,取值范围是[0,15]
chroma_format_idc:表示色度采样格式,取值范围是[0,3]。
pic_width_in_luma_samples:解码图像中的亮度样点的宽度
pic_height_in_luma_samples:解码图像中的亮度样点的高度
conformance_window_flag:解码器是否要对解码后的数据进行裁剪。当这个值等于1时,conf_win_left_offset、conf_win_right_offset、conf_win_top_offset、conf_win_bottom_offset这四个参数就会用到。
bit_depth_luma_minus8:表示亮度像素的比特深度
bit_depth_chroma_minus8:表示色度像素的比特深度
log2_max_pic_order_cnt_lsb_minus4:该语法元素的取值范围是[0,12],它用于计算变量MaxPicOrderCntLsb。MaxPicOrderCntLsb用于控制进位,在HEVC比特流中只传入一个低位的POC,而不需要传入高位的POC。
sps_sub_layer_ordering_info_present_flag:时域子层顺序标识开关。这值等于1,表示sps_max_dec_pic_buffering_minus[i]、sps_max_num_reorder_pics[i]、sps_max_latency_increase_plus[1]适用于sps_max_sub_layers_minus1+1子层;若该数值等于0,则表示这些参数适用于子层。
log2_min_luma_coding_block_size_minus3:指定亮度编码块的最小尺寸
log2_diff_max_min_luma_coding_block_size:指定亮度编码块最大尺寸和最小尺寸的差值
log2_min_transform_block_size:指定亮度变换块最大尺寸和最小尺寸差值
log2_diff_max_min_transform_block_size:指定亮度变换块的最大尺寸和最小尺寸差值
max_transform_hierarchy_depth_inter:表示帧间预测变换块的最大划分深度,取值范围是[0, CtbLog2SizeY - Log2MinTrafoSize]
max_transform_hierarchy_depth_intra:表示帧内预测变换块的最大划分深度,取值范围是[0, CtbLog2SizeY - Log2MinTrafoSize]
scaling_list_enable_flag:表示对变换系数在量化过程中是否使用量化矩阵。
amp_enable_flag:是否使用非对称划分模式,非对称模式有四种分别是PART_2NxnU、PART_2NxnD、PART_nLx2N、PART_nRx2N
sample_adaptive_offset_enable_flag:表示去方块滤波过程后的图像重构是否自适应补偿
pcm_enable_flag:是否使用pcm模式
num_short_term_ref_pic_set:表示sps中short_term_ref_pic_ste的数目,取值范围是[0,64]
long_term_ref_pics_present_flag:表示帧间预测是否使用长期参考图像
sps_temporal_mvp_enable_flag:指定非IDR图像片头中是否存在slice_temporal_mvp_enable_flag
strong_intra_smoothing_enable_flag:表示滤过的时候,是否使用双向性插值
vui_parameters_present_flag:表示是否含有语法vui_parameters()
pps:图像参数集(NALU:00 00 00 01 44 01),在HEVC中会包含多个图像,每一张图像会提供所引用的PPS标识符,以此会得到PPS的共用信息。需要注意的是,pps中存在许多和sps相同的参数,在pps中这些参数有可能会直接覆盖sps的取值。换言之,在HEVC开始解码的时候,所有的PPS参数都是非活动状态,当解码过程中某一张图片在解码过程中引用了某个pps参数的时候,这个PPS就会处于激活状态直到图像解码结束。
pps_pic_parameter_set_id:当前激活的PPS ID号,取值范围是[0,63]
pps_seq_parameter_set_id:当前激活的SPS ID号,取值范围是[0,15]
dependent_slice_segments_enable_flag:表示slice头中是否存在句法dependent_slice_segment_flag,并用于判断当前片段是否有依赖片
output_flag_present_flag:表示Slice头中是否存在句法pic_output_flag、pic_output_flag影响解码图像的输出
num_extra_slice_headers_bits:其数值为0,表示Slice头部中没有额外的Slice头比特
sign_data_hiding_enable_flag:表示是否不允许使用符号位隐藏技术
cabac_init_present_flag:表示片头中是否存在cabac_init_flag、此标志位用于判断在CABAC中使用何种方法初始化变量
num_ref_idx_10_default_active_minus1:该语法元素取值范围是[0,14],表示在num_ref_idx_active_override_flag等于0,P Slice和B Slice中num_ref_idx_l0_active_minus1默认值。
num_ref_idx_11_default_active_minus1:该语法元素取值范围是[0,14],表示在num_ref_idx_active_override_flag等于0,num_ref_idx_11_default_active_minus1的默认值,也就是引用list1中参考图像数目的最大默认值。
init_qp_minus26:规定了每个Slice亮度分量的量化参数初始值
constrained_intra_pred_flag:表示帧内预测是否受限制,就是是否允许采用帧间预测模式的临近块信息进行帧内预测
transform_skip_enabled_flag:指定在残差编码语法中是否存在transform_skip_flag,transform_skip_flag用于表示残差编码是否为transform_skip模式
cu_qp_delta_enable_flag:取值1,表示当前PPS存在difff_cu_qp_delta_depth,并且在变换单元句法可能存在
pps_cb_qp_offset:表示色度分量Cb采用量化参数(Qp’cb模式)
pps_cr_qp_offset:表示色度分量Cr采用量化参数(Qp’cr模式)
pps_slice_chroma_qp_offsets_present_flag:Slice头中是否存在slice_cb_qp_offset和slice_cr_qp_offset,这两个参数用来计算量化参数QpCb和QpCr。
weighted_pred_flag:表示P Slice是否使用加权预测
weighted_bipred_flag:表示B Slice是否使用双向加权预测
transquant_bypass_enable_flag:表示是否存在cu_transquant_bypass_flag,cu_transquant_bypass_flag用于判断是否存在cu_transquant_bypass模式,换言之是否调过滤波变化
tiles_enable_flag:表示是够使用tile模式
entropy_coding_sync_enable_flag:是否使用熵编码同步机制
pps_loop_filter_across_slices_enabled_flag:是否允许环路滤波跨越Slice左边界和上边界
deblocking_filter_control_present_flag:表示PPS中是否存在去方块滤波控制信息
pps_scaling_list_data_present_flag:表示当前PPS中是否存在变换矩阵的信息,若存在,在一信息中会对SPS中的信息进行覆盖
lists_modification_present_flag:表示Slice头中是否存在结构ref_pic_lists_modification()
log2_parallel_merge_level_minus2:给出变量Log2ParMrgLevel的值,变量Log2ParMrgLevel被用在merge模式下亮度分量MV产生过程
slice_segment_header_extension_present_flag:表示SS头部扩展元素是否存在,在这个版本中取值为0。若取值为1,用做保留,提供给ITU-T和ISO/IEC使用
pps_extension_flag:表示是否存在语法元素pps_extension_data_flag,默认取值为0。若取值为1,用做码流ITU-T以及ISO/IEC来使用
SEI帧:
HEVC的SEI帧(它的NALU是:00 00 00 01 4e 01)和H264的SEI帧功能是一样的,也是在HEVC中添加额外的信息如:字幕、表情、时间戳等等的信息。下面我们来看看SEI的组成部分:
00 00 01 4E 01 + 05 + payloadSize + sei_payload
00 00 01 4E 01:表示的是NALU是SEI类型
05:SEI的 payload type,这里的sei payload遵循user_data_unregistered()语法
PayloadSize:05后面的这个值是SEI的长度,SEI的长度是包含了UUID+PAYLOAD_CONTENT的总长度
SEI_PAYLOAD:SEI的内容包含了UUID和PAYLOAD_CONTENT。
I帧
HEVC的I帧,NALU是(00 00 00 01 26 01)。HEVC的I帧和H264的I帧也是同样的概念,同样也是表示一副完整的图片。