在HEVC中,各种参数集以及控制信息等使用CAVLC编码,片头部也是使用cavlc进行编码,而帧或者片中的数据(连同CU的语法元素等)使用的是CABAC进行熵编码。
下面介绍一下各种参数集的熵编码。
在TEncGOP::compressGOP函数(图像组编码函数)中可以看到,在调用compressSlice对片编码之后,调用了m_pcEntropyCoder->setEntropyCoder ( m_pcCavlcCoder, pcSlice )设置CAVLC编码器为当前的熵编码器,然后调用encodeVPS,encodeSPS,encodePPS分别对视频参数集、序列参数集、图像参数集进行熵编码。当然只有在视频序列的开头才会调用
encodeVPS,encodeSPS,encodePPS。然后调用codeSliceHeader对片的头部进行编码。
vps的格式(部分参数)
vps_video_parameter_set_id:其他语法元素所参考的VPS编号;
vps_reserved_three_2bits:保留位,指定为3;
vps_max_layers_minus1:保留,值为0,用于未来的3D和可分级扩展标准使用;
vps_max_sub_layers_minus1:这个值表示比特流中可以支持最大数目的时域子层数目减1,取值范围为0到6,也就是最大可以支持7个子层;
vps_temporal_id_nesting_flag:当前一个参数vps_max_sub_layers_minus1为0(即不支持时域子层)时,这个参数应该为1;vps_max_sub_layers_minus1非0时,指定是否对编码视频序列的帧间预测添加限制。用于子层切换过程中。
vps_reserved_0xffff_16bits:两个字节的保留位,全部为1;
vps_sub_layer_ordering_info_present_flag:为1,vps_max_dec_pic_buffering_minus1[i],vps_max_num_reorder_pics[i]和vps_max_latency_increase_plus1[i]适用于vps_max_sub_layers_minus1+ 1个子层;为0,这些参数适用于所有子层;
vps_max_dec_pic_buffering_minus1:指定所需的最大解码图像缓存的数量;
vps_max_num_reorder_pics和vps_max_latency_increase_plus1:指定按照解码顺序在某一帧之后,而显示顺序在某一帧之前的帧的最大数量;
vps_max_layer_id:CVS中所有NAL单元的最大允许的nuh_layer_id值;
vps_num_layer_sets_minus1:由VPS指定的图层组的数量-1;当前标准中指定为0;
layer_id_included_flag[][]:表示nuh_layer_id与layerSetLayerIdList[]的包含关系;
vps_timing_info_present_flag:标识该VPS是否包含几个时间相关参数;
vps_extension_flag:标识该VPS是否包含扩展信息。
vps_reserved_three_2bits:保留位,指定为3;
vps_max_layers_minus1:保留,值为0,用于未来的3D和可分级扩展标准使用;
vps_max_sub_layers_minus1:这个值表示比特流中可以支持最大数目的时域子层数目减1,取值范围为0到6,也就是最大可以支持7个子层;
vps_temporal_id_nesting_flag:当前一个参数vps_max_sub_layers_minus1为0(即不支持时域子层)时,这个参数应该为1;vps_max_sub_layers_minus1非0时,指定是否对编码视频序列的帧间预测添加限制。用于子层切换过程中。
vps_reserved_0xffff_16bits:两个字节的保留位,全部为1;
vps_sub_layer_ordering_info_present_flag:为1,vps_max_dec_pic_buffering_minus1[i],vps_max_num_reorder_pics[i]和vps_max_latency_increase_plus1[i]适用于vps_max_sub_layers_minus1+ 1个子层;为0,这些参数适用于所有子层;
vps_max_dec_pic_buffering_minus1:指定所需的最大解码图像缓存的数量;
vps_max_num_reorder_pics和vps_max_latency_increase_plus1:指定按照解码顺序在某一帧之后,而显示顺序在某一帧之前的帧的最大数量;
vps_max_layer_id:CVS中所有NAL单元的最大允许的nuh_layer_id值;
vps_num_layer_sets_minus1:由VPS指定的图层组的数量-1;当前标准中指定为0;
layer_id_included_flag[][]:表示nuh_layer_id与layerSetLayerIdList[]的包含关系;
vps_timing_info_present_flag:标识该VPS是否包含几个时间相关参数;
vps_extension_flag:标识该VPS是否包含扩展信息。
下面是encodeVPS,encodeSPS,encodePPS三个函数的定义:
// vps的格式需要参考官方文档
Void TEncCavlc::codeVPS( TComVPS* pcVPS )
{
// 编码vps的id
WRITE_CODE( pcVPS->getVPSId(), 4, "vps_video_parameter_set_id" );
// 保留位,指定为3
WRITE_CODE( 3, 2, "vps_reserved_three_2bits" );
// 保留的6个0比特
WRITE_CODE( 0, 6, "vps_reserved_zero_6bits" );
// 时域层的数量
WRITE_CODE( pcVPS->getMaxTLayers() - 1, 3, "vps_max_sub_layers_minus1" );
// 时域层嵌套标志
WRITE_FLAG( pcVPS->getTemporalNestingFlag(), "vps_temporal_id_nesting_flag" );
assert (pcVPS->getMaxTLayers()>1||pcVPS->getTemporalNestingFlag());
// 保留的16个比特(值都是0xffff)
WRITE_CODE( 0xffff, 16, "vps_reserved_ffff_16bits" );
// 对Profile Tier Level的信息进行编码
codePTL( pcVPS->getPTL(), true, pcVPS->getMaxTLayers() - 1 );
const Bool subLayerOrderingInfoPresentFlag = 1;
// 时域层排序信息存在的标志?
WRITE_FLAG(subLayerOrderingInfoPresentFlag, "vps_sub_layer_ordering_info_present_flag");
// 写入每个时域层的信息
for(UInt i=0; i <= pcVPS->getMaxTLayers()-1; i++)
{
// 解码缓冲区的数量
WRITE_UVLC( pcVPS->getMaxDecPicBuffering(i) - 1, "vps_max_dec_pic_buffering_minus1[i]" );
// 重排图像的数量(指定按照解码顺序在某一帧之后,而显示顺序在某一帧之前的帧的最大数量)
WRITE_UVLC( pcVPS->getNumReorderPics(i), "vps_num_reorder_pics[i]" );
WRITE_UVLC( pcVPS->getMaxLatencyIncrease(i), "vps_max_latency_increase_plus1[i]" );
if (!subLayerOrderingInfoPresentFlag)
{
break;
}
}
assert( pcVPS->getNumHrdParameters() <= MAX_VPS_NUM_HRD_PARAMETERS );
assert( pcVPS->getMaxNuhReservedZeroLayerId() < MAX_VPS_NUH_RESERVED_ZERO_LAYER_ID_PLUS1 );
WRITE_CODE( pcVPS->getMaxNuhReservedZeroLayerId(), 6, "vps_max_nuh_reserved_zero_layer_id" );
pcVPS->setMaxOpSets(1);
// 操作集的数量?
WRITE_UVLC( pcVPS->getMaxOpSets() - 1, "vps_max_op_sets_minus1" );
for( UInt opsIdx = 1; opsIdx <= ( pcVPS->getMaxOpSets() - 1 ); opsIdx ++ )
{
// Operation point set
for( UInt i = 0; i <= pcVPS->getMaxNuhReservedZeroLayerId(); i ++ )
{
// Only applicable for version 1
pcVPS->setLayerIdIncludedFlag( true, opsIdx, i );
WRITE_FLAG( pcVPS->getLayerIdIncludedFlag( opsIdx, i ) ? 1 : 0, "layer_id_included_flag[opsIdx][i]" );
}
}
// 计时或者时域方面的信息
TimingInfo *timingInfo = pcVPS->getTimingInfo();
// 时域信息存在的标志
WRITE_FLAG(timingInfo->getTimingInfoPresentFlag(), "vps_timing_info_present_flag");
// 写入计时或者时域信息
if(timingInfo->getTimingInfoPresentFlag())
{
WRITE_CODE(timingInfo->getNumUnitsInTick(), 32, "vps_num_units_in_tick");
WRITE_CODE(timingInfo->getTimeScale(), 32, "vps_time_scale");
WRITE_FLAG(timingInfo->getPocProportionalToTimingFlag(), "vps_poc_proportional_to_timing_flag");
if(timingInfo->getPocProportionalToTimingFlag())
{
WRITE_UVLC(timingInfo->getNumTicksPocDiffOneMinus1(), "vps_num_ticks_poc_diff_one_minus1");
}
pcVPS->setNumHrdParameters( 0 );
WRITE_UVLC( pcVPS->getNumHrdParameters(), "vps_num_hrd_parameters" );
if( pcVPS->getNumHrdParameters() > 0 )
{
pcVPS->createHrdParamBuffer();
}
for( UInt i = 0; i < pcVPS->getNumHrdParameters(); i ++ )
{
// Only applicable for version 1
pcVPS->setHrdOpSetIdx( 0, i );
WRITE_UVLC( pcVPS->getHrdOpSetIdx( i ), "hrd_op_set_idx" );
if( i > 0 )
{
WRITE_FLAG( pcVPS->getCprmsPresentFlag( i ) ? 1 : 0, "cprms_present_flag[i]" );
}
// 编码HRD(参考解码器)的参数
codeHrdParameters(pcVPS->getHrdParameters(i), pcVPS->getCprmsPresentFlag( i ), pcVPS->getMaxTLayers() - 1);
}
}
// 扩展标志
WRITE_FLAG( 0, "vps_extension_flag" );
//future extensions here..
return;
}
// sps的格式需要参考官方文档
Void TEncCavlc::codeSPS( TComSPS* pcSPS )
{
#if ENC_DEC_TRACE
xTraceSPSHeader (pcSPS);
#endif
// sps的id
WRITE_CODE( pcSPS->getVPSId (), 4, "sps_video_parameter_set_id" );
// 时域层
WRITE_CODE( pcSPS->getMaxTLayers() - 1, 3, "sps_max_sub_layers_minus1" );
// 时域层嵌套标志
WRITE_FLAG( pcSPS->getTemporalIdNestingFlag() ? 1 : 0, "sps_temporal_id_nesting_flag" );
// Profile,Tier,Level的参数
codePTL(pcSPS->getPTL(), 1, pcSPS->getMaxTLayers() - 1);
WRITE_UVLC( pcSPS->getSPSId (), "sps_seq_parameter_set_id" );
// 视频采样格式
WRITE_UVLC( pcSPS->getChromaFormatIdc (), "chroma_format_idc" );
assert(pcSPS->getChromaFormatIdc () == 1);
// in the first version chroma_format_idc can only be equal to 1 (4:2:0)
if( pcSPS->getChromaFormatIdc () == 3 )
{
WRITE_FLAG( 0, "separate_colour_plane_flag");
}
// 帧的亮度分量的宽高
WRITE_UVLC( pcSPS->getPicWidthInLumaSamples (), "pic_width_in_luma_samples" );
WRITE_UVLC( pcSPS->getPicHeightInLumaSamples(), "pic_height_in_luma_samples" );
Window conf = pcSPS->getConformanceWindow();
// 是否启用一致性窗口
WRITE_FLAG( conf.getWindowEnabledFlag(), "conformance_window_flag" );
if (conf.getWindowEnabledFlag())
{
WRITE_UVLC( conf.getWindowLeftOffset() / TComSPS::getWinUnitX(pcSPS->getChromaFormatIdc() ), "conf_win_left_offset" );
WRITE_UVLC( conf.getWindowRightOffset() / TComSPS::getWinUnitX(pcSPS->getChromaFormatIdc() ), "conf_win_right_offset" );
WRITE_UVLC( conf.getWindowTopOffset() / TComSPS::getWinUnitY(pcSPS->getChromaFormatIdc() ), "conf_win_top_offset" );
WRITE_UVLC( conf.getWindowBottomOffset() / TComSPS::getWinUnitY(pcSPS->getChromaFormatIdc() ), "conf_win_bottom_offset" );
}
// 深度信息
WRITE_UVLC( pcSPS->getBitDepthY() - 8, "bit_depth_luma_minus8" );
WRITE_UVLC( pcSPS->getBitDepthC() - 8, "bit_depth_chroma_minus8" );
// 存储poc需要的比特数
WRITE_UVLC( pcSPS->getBitsForPOC()-4, "log2_max_pic_order_cnt_lsb_minus4" );
const Bool subLayerOrderingInfoPresentFlag = 1;
WRITE_FLAG(subLayerOrderingInfoPresentFlag, "sps_sub_layer_ordering_info_present_flag");
for(UInt i=0; i <= pcSPS->getMaxTLayers()-1; i++)
{
WRITE_UVLC( pcSPS->getMaxDecPicBuffering(i) - 1, "sps_max_dec_pic_buffering_minus1[i]" );
WRITE_UVLC( pcSPS->getNumReorderPics(i), "sps_num_reorder_pics[i]" );
WRITE_UVLC( pcSPS->getMaxLatencyIncrease(i), "sps_max_latency_increase_plus1[i]" );
if (!subLayerOrderingInfoPresentFlag)
{
break;
}
}
assert( pcSPS->getMaxCUWidth() == pcSPS->getMaxCUHeight() );
WRITE_UVLC( pcSPS->getLog2MinCodingBlockSize() - 3, "log2_min_coding_block_size_minus3" );
WRITE_UVLC( pcSPS->getLog2DiffMaxMinCodingBlockSize(), "log2_diff_max_min_coding_block_size" );
WRITE_UVLC( pcSPS->getQuadtreeTULog2MinSize() - 2, "log2_min_transform_block_size_minus2" );
WRITE_UVLC( pcSPS->getQuadtreeTULog2MaxSize() - pcSPS->getQuadtreeTULog2MinSize(), "log2_diff_max_min_transform_block_size" );
WRITE_UVLC( pcSPS->getQuadtreeTUMaxDepthInter() - 1, "max_transform_hierarchy_depth_inter" );
WRITE_UVLC( pcSPS->getQuadtreeTUMaxDepthIntra() - 1, "max_transform_hierarchy_depth_intra" );
WRITE_FLAG( pcSPS->getScalingListFlag() ? 1 : 0, "scaling_list_enabled_flag" );
if(pcSPS->getScalingListFlag())
{
WRITE_FLAG( pcSPS->getScalingListPresentFlag() ? 1 : 0, "sps_scaling_list_data_present_flag" );
if(pcSPS->getScalingListPresentFlag())
{
codeScalingList( m_pcSlice->getScalingList() );
}
}
WRITE_FLAG( pcSPS->getUseAMP() ? 1 : 0, "amp_enabled_flag" );
WRITE_FLAG( pcSPS->getUseSAO() ? 1 : 0, "sample_adaptive_offset_enabled_flag");
WRITE_FLAG( pcSPS->getUsePCM() ? 1 : 0, "pcm_enabled_flag");
if( pcSPS->getUsePCM() )
{
WRITE_CODE( pcSPS->getPCMBitDepthLuma() - 1, 4, "pcm_sample_bit_depth_luma_minus1" );
WRITE_CODE( pcSPS->getPCMBitDepthChroma() - 1, 4, "pcm_sample_bit_depth_chroma_minus1" );
WRITE_UVLC( pcSPS->getPCMLog2MinSize() - 3, "log2_min_pcm_luma_coding_block_size_minus3" );
WRITE_UVLC( pcSPS->getPCMLog2MaxSize() - pcSPS->getPCMLog2MinSize(), "log2_diff_max_min_pcm_luma_coding_block_size" );
WRITE_FLAG( pcSPS->getPCMFilterDisableFlag()?1 : 0, "pcm_loop_filter_disable_flag");
}
assert( pcSPS->getMaxTLayers() > 0 );
TComRPSList* rpsList = pcSPS->getRPSList();
TComReferencePictureSet* rps;
WRITE_UVLC(rpsList->getNumberOfReferencePictureSets(), "num_short_term_ref_pic_sets" );
for(Int i=0; i < rpsList->getNumberOfReferencePictureSets(); i++)
{
rps = rpsList->getReferencePictureSet(i);
codeShortTermRefPicSet(pcSPS,rps,false, i);
}
WRITE_FLAG( pcSPS->getLongTermRefsPresent() ? 1 : 0, "long_term_ref_pics_present_flag" );
if (pcSPS->getLongTermRefsPresent())
{
WRITE_UVLC(pcSPS->getNumLongTermRefPicSPS(), "num_long_term_ref_pic_sps" );
for (UInt k = 0; k < pcSPS->getNumLongTermRefPicSPS(); k++)
{
WRITE_CODE( pcSPS->getLtRefPicPocLsbSps(k), pcSPS->getBitsForPOC(), "lt_ref_pic_poc_lsb_sps");
WRITE_FLAG( pcSPS->getUsedByCurrPicLtSPSFlag(k), "used_by_curr_pic_lt_sps_flag");
}
}
WRITE_FLAG( pcSPS->getTMVPFlagsPresent() ? 1 : 0, "sps_temporal_mvp_enable_flag" );
WRITE_FLAG( pcSPS->getUseStrongIntraSmoothing(), "sps_strong_intra_smoothing_enable_flag" );
WRITE_FLAG( pcSPS->getVuiParametersPresentFlag(), "vui_parameters_present_flag" );
if (pcSPS->getVuiParametersPresentFlag())
{
codeVUI(pcSPS->getVuiParameters(), pcSPS);
}
WRITE_FLAG( 0, "sps_extension_flag" );
}
// pps的格式要参考官方文档
Void TEncCavlc::codePPS( TComPPS* pcPPS )
{
#if ENC_DEC_TRACE
xTracePPSHeader (pcPPS);
#endif
// PPS的id
WRITE_UVLC( pcPPS->getPPSId(), "pps_pic_parameter_set_id" );
// SPS的id
WRITE_UVLC( pcPPS->getSPSId(), "pps_seq_parameter_set_id" );
// 是否使用了依赖性片片段
WRITE_FLAG( pcPPS->getDependentSliceSegmentsEnabledFlag() ? 1 : 0, "dependent_slice_segments_enabled_flag" );
// OutputFlag存在的标志
WRITE_FLAG( pcPPS->getOutputFlagPresentFlag() ? 1 : 0, "output_flag_present_flag" );
// slice头部额外的比特数
WRITE_CODE( pcPPS->getNumExtraSliceHeaderBits(), 3, "num_extra_slice_header_bits");
// 整数符号是否隐藏(往下不一一细讲,总之就是对一堆参数进行编码)
WRITE_FLAG( pcPPS->getSignHideFlag(), "sign_data_hiding_flag" );
WRITE_FLAG( pcPPS->getCabacInitPresentFlag() ? 1 : 0, "cabac_init_present_flag" );
WRITE_UVLC( pcPPS->getNumRefIdxL0DefaultActive()-1, "num_ref_idx_l0_default_active_minus1");
WRITE_UVLC( pcPPS->getNumRefIdxL1DefaultActive()-1, "num_ref_idx_l1_default_active_minus1");
WRITE_SVLC( pcPPS->getPicInitQPMinus26(), "init_qp_minus26");
WRITE_FLAG( pcPPS->getConstrainedIntraPred() ? 1 : 0, "constrained_intra_pred_flag" );
WRITE_FLAG( pcPPS->getUseTransformSkip() ? 1 : 0, "transform_skip_enabled_flag" );
WRITE_FLAG( pcPPS->getUseDQP() ? 1 : 0, "cu_qp_delta_enabled_flag" );
if ( pcPPS->getUseDQP() )
{
WRITE_UVLC( pcPPS->getMaxCuDQPDepth(), "diff_cu_qp_delta_depth" );
}
WRITE_SVLC( pcPPS->getChromaCbQpOffset(), "pps_cb_qp_offset" );
WRITE_SVLC( pcPPS->getChromaCrQpOffset(), "pps_cr_qp_offset" );
WRITE_FLAG( pcPPS->getSliceChromaQpFlag() ? 1 : 0, "pps_slice_chroma_qp_offsets_present_flag" );
WRITE_FLAG( pcPPS->getUseWP() ? 1 : 0, "weighted_pred_flag" ); // Use of Weighting Prediction (P_SLICE)
WRITE_FLAG( pcPPS->getWPBiPred() ? 1 : 0, "weighted_bipred_flag" ); // Use of Weighting Bi-Prediction (B_SLICE)
WRITE_FLAG( pcPPS->getTransquantBypassEnableFlag() ? 1 : 0, "transquant_bypass_enable_flag" );
WRITE_FLAG( pcPPS->getTilesEnabledFlag() ? 1 : 0, "tiles_enabled_flag" );
WRITE_FLAG( pcPPS->getEntropyCodingSyncEnabledFlag() ? 1 : 0, "entropy_coding_sync_enabled_flag" );
if( pcPPS->getTilesEnabledFlag() )
{
WRITE_UVLC( pcPPS->getNumTileColumnsMinus1(), "num_tile_columns_minus1" );
WRITE_UVLC( pcPPS->getTileNumRowsMinus1(), "num_tile_rows_minus1" );
WRITE_FLAG( pcPPS->getTileUniformSpacingFlag(), "uniform_spacing_flag" );
if( !pcPPS->getTileUniformSpacingFlag() )
{
for(UInt i=0; i<pcPPS->getNumTileColumnsMinus1(); i++)
{
WRITE_UVLC( pcPPS->getTileColumnWidth(i)-1, "column_width_minus1" );
}
for(UInt i=0; i<pcPPS->getTileNumRowsMinus1(); i++)
{
WRITE_UVLC( pcPPS->getTileRowHeight(i)-1, "row_height_minus1" );
}
}
if(pcPPS->getNumTileColumnsMinus1() !=0 || pcPPS->getTileNumRowsMinus1() !=0)
{
WRITE_FLAG( pcPPS->getLoopFilterAcrossTilesEnabledFlag()?1 : 0, "loop_filter_across_tiles_enabled_flag");
}
}
WRITE_FLAG( pcPPS->getLoopFilterAcrossSlicesEnabledFlag()?1 : 0, "loop_filter_across_slices_enabled_flag");
WRITE_FLAG( pcPPS->getDeblockingFilterControlPresentFlag()?1 : 0, "deblocking_filter_control_present_flag");
if(pcPPS->getDeblockingFilterControlPresentFlag())
{
WRITE_FLAG( pcPPS->getDeblockingFilterOverrideEnabledFlag() ? 1 : 0, "deblocking_filter_override_enabled_flag" );
WRITE_FLAG( pcPPS->getPicDisableDeblockingFilterFlag() ? 1 : 0, "pps_disable_deblocking_filter_flag" );
if(!pcPPS->getPicDisableDeblockingFilterFlag())
{
WRITE_SVLC( pcPPS->getDeblockingFilterBetaOffsetDiv2(), "pps_beta_offset_div2" );
WRITE_SVLC( pcPPS->getDeblockingFilterTcOffsetDiv2(), "pps_tc_offset_div2" );
}
}
WRITE_FLAG( pcPPS->getScalingListPresentFlag() ? 1 : 0, "pps_scaling_list_data_present_flag" );
if( pcPPS->getScalingListPresentFlag() )
{
codeScalingList( m_pcSlice->getScalingList() );
}
WRITE_FLAG( pcPPS->getListsModificationPresentFlag(), "lists_modification_present_flag");
WRITE_UVLC( pcPPS->getLog2ParallelMergeLevelMinus2(), "log2_parallel_merge_level_minus2");
WRITE_FLAG( pcPPS->getSliceHeaderExtensionPresentFlag() ? 1 : 0, "slice_segment_header_extension_present_flag");
WRITE_FLAG( 0, "pps_extension_flag" );
}
// 对片头进行编码
Void TEncCavlc::codeSliceHeader ( TComSlice* pcSlice )
{
#if ENC_DEC_TRACE
xTraceSliceHeader (pcSlice);
#endif
//calculate number of bits required for slice address
Int maxSliceSegmentAddress = pcSlice->getPic()->getNumCUsInFrame();
Int bitsSliceSegmentAddress = 0;
while(maxSliceSegmentAddress>(1<<bitsSliceSegmentAddress))
{
bitsSliceSegmentAddress++;
}
Int ctuAddress;
if (pcSlice->isNextSlice())
{
// Calculate slice address
ctuAddress = (pcSlice->getSliceCurStartCUAddr()/pcSlice->getPic()->getNumPartInCU());
}
else
{
// Calculate slice address
ctuAddress = (pcSlice->getSliceSegmentCurStartCUAddr()/pcSlice->getPic()->getNumPartInCU());
}
//write slice address
Int sliceSegmentAddress = pcSlice->getPic()->getPicSym()->getCUOrderMap(ctuAddress);
// 该片是否为帧中的第一个片
WRITE_FLAG( sliceSegmentAddress==0, "first_slice_segment_in_pic_flag" );
if ( pcSlice->getRapPicFlag() )
{
#if SETTING_NO_OUT_PIC_PRIOR
WRITE_FLAG( pcSlice->getNoOutputPriorPicsFlag() ? 1 : 0, "no_output_of_prior_pics_flag" );
#else
WRITE_FLAG( 0, "no_output_of_prior_pics_flag" );
#endif
}
// pps的id
WRITE_UVLC( pcSlice->getPPS()->getPPSId(), "slice_pic_parameter_set_id" );
pcSlice->setDependentSliceSegmentFlag(!pcSlice->isNextSlice());
if ( pcSlice->getPPS()->getDependentSliceSegmentsEnabledFlag() && (sliceSegmentAddress!=0) )
{
// 依赖性的片是否存在的标志
WRITE_FLAG( pcSlice->getDependentSliceSegmentFlag() ? 1 : 0, "dependent_slice_segment_flag" );
}
if(sliceSegmentAddress>0)
{
// 片的地址
WRITE_CODE( sliceSegmentAddress, bitsSliceSegmentAddress, "slice_segment_address" );
}
if ( !pcSlice->getDependentSliceSegmentFlag() )
{
for (Int i = 0; i < pcSlice->getPPS()->getNumExtraSliceHeaderBits(); i++)
{
assert(!!"slice_reserved_undetermined_flag[]");
WRITE_FLAG(0, "slice_reserved_undetermined_flag[]");
}
// 片的类型
WRITE_UVLC( pcSlice->getSliceType(), "slice_type" );
if( pcSlice->getPPS()->getOutputFlagPresentFlag() )
{
// 帧输出的标志
WRITE_FLAG( pcSlice->getPicOutputFlag() ? 1 : 0, "pic_output_flag" );
}
// in the first version chroma_format_idc is equal to one, thus colour_plane_id will not be present
assert (pcSlice->getSPS()->getChromaFormatIdc() == 1 );
// if( separate_colour_plane_flag == 1 )
// colour_plane_id u(2)
if( !pcSlice->getIdrPicFlag() )
{
Int picOrderCntLSB = (pcSlice->getPOC()-pcSlice->getLastIDR()+(1<<pcSlice->getSPS()->getBitsForPOC())) & ((1<<pcSlice->getSPS()->getBitsForPOC())-1);
// 用于存储poc的比特数
WRITE_CODE( picOrderCntLSB, pcSlice->getSPS()->getBitsForPOC(), "pic_order_cnt_lsb");
TComReferencePictureSet* rps = pcSlice->getRPS();
// check for bitstream restriction stating that:
// If the current picture is a BLA or CRA picture, the value of NumPocTotalCurr shall be equal to 0.
// Ideally this process should not be repeated for each slice in a picture
if (pcSlice->isIRAP())
{
for (Int picIdx = 0; picIdx < rps->getNumberOfPictures(); picIdx++)
{
assert (!rps->getUsed(picIdx));
}
}
if(pcSlice->getRPSidx() < 0)
{
// 短期参考图像集的标志
WRITE_FLAG( 0, "short_term_ref_pic_set_sps_flag");
// 编码短期参考图像集
codeShortTermRefPicSet(pcSlice->getSPS(), rps, true, pcSlice->getSPS()->getRPSList()->getNumberOfReferencePictureSets());
}
else
{
WRITE_FLAG( 1, "short_term_ref_pic_set_sps_flag");
Int numBits = 0;
while ((1 << numBits) < pcSlice->getSPS()->getRPSList()->getNumberOfReferencePictureSets())
{
numBits++;
}
if (numBits > 0)
{
// 参考图像集的索引
WRITE_CODE( pcSlice->getRPSidx(), numBits, "short_term_ref_pic_set_idx" );
}
}
if(pcSlice->getSPS()->getLongTermRefsPresent())
{
Int numLtrpInSH = rps->getNumberOfLongtermPictures();
Int ltrpInSPS[MAX_NUM_REF_PICS];
Int numLtrpInSPS = 0;
UInt ltrpIndex;
Int counter = 0;
for(Int k = rps->getNumberOfPictures()-1; k > rps->getNumberOfPictures()-rps->getNumberOfLongtermPictures()-1; k--)
{
if (findMatchingLTRP(pcSlice, <rpIndex, rps->getPOC(k), rps->getUsed(k)))
{
ltrpInSPS[numLtrpInSPS] = ltrpIndex;
numLtrpInSPS++;
}
else
{
counter++;
}
}
numLtrpInSH -= numLtrpInSPS;
Int bitsForLtrpInSPS = 0;
while (pcSlice->getSPS()->getNumLongTermRefPicSPS() > (1 << bitsForLtrpInSPS))
{
bitsForLtrpInSPS++;
}
if (pcSlice->getSPS()->getNumLongTermRefPicSPS() > 0)
{
WRITE_UVLC( numLtrpInSPS, "num_long_term_sps");
}
// 长期参考帧的数量
WRITE_UVLC( numLtrpInSH, "num_long_term_pics");
// Note that the LSBs of the LT ref. pic. POCs must be sorted before.
// Not sorted here because LT ref indices will be used in setRefPicList()
Int prevDeltaMSB = 0, prevLSB = 0;
Int offset = rps->getNumberOfNegativePictures() + rps->getNumberOfPositivePictures();
for(Int i=rps->getNumberOfPictures()-1 ; i > offset-1; i--)
{
if (counter < numLtrpInSPS)
{
if (bitsForLtrpInSPS > 0)
{
WRITE_CODE( ltrpInSPS[counter], bitsForLtrpInSPS, "lt_idx_sps[i]");
}
}
else
{
WRITE_CODE( rps->getPocLSBLT(i), pcSlice->getSPS()->getBitsForPOC(), "poc_lsb_lt");
WRITE_FLAG( rps->getUsed(i), "used_by_curr_pic_lt_flag");
}
WRITE_FLAG( rps->getDeltaPocMSBPresentFlag(i), "delta_poc_msb_present_flag");
if(rps->getDeltaPocMSBPresentFlag(i))
{
Bool deltaFlag = false;
// First LTRP from SPS || First LTRP from SH || curr LSB != prev LSB
if( (i == rps->getNumberOfPictures()-1) || (i == rps->getNumberOfPictures()-1-numLtrpInSPS) || (rps->getPocLSBLT(i) != prevLSB) )
{
deltaFlag = true;
}
if(deltaFlag)
{
WRITE_UVLC( rps->getDeltaPocMSBCycleLT(i), "delta_poc_msb_cycle_lt[i]" );
}
else
{
Int differenceInDeltaMSB = rps->getDeltaPocMSBCycleLT(i) - prevDeltaMSB;
assert(differenceInDeltaMSB >= 0);
WRITE_UVLC( differenceInDeltaMSB, "delta_poc_msb_cycle_lt[i]" );
}
prevLSB = rps->getPocLSBLT(i);
prevDeltaMSB = rps->getDeltaPocMSBCycleLT(i);
}
}
}
if (pcSlice->getSPS()->getTMVPFlagsPresent())
{
// 是否启用时域MVP
WRITE_FLAG( pcSlice->getEnableTMVPFlag() ? 1 : 0, "slice_temporal_mvp_enable_flag" );
}
}
if(pcSlice->getSPS()->getUseSAO())
{
if (pcSlice->getSPS()->getUseSAO())
{
// 是否启用SAO
WRITE_FLAG( pcSlice->getSaoEnabledFlag(), "slice_sao_luma_flag" );
WRITE_FLAG( pcSlice->getSaoEnabledFlagChroma(), "slice_sao_chroma_flag" );
}
}
//check if numrefidxes match the defaults. If not, override
if (!pcSlice->isIntra())
{
Bool overrideFlag = (pcSlice->getNumRefIdx( REF_PIC_LIST_0 )!=pcSlice->getPPS()->getNumRefIdxL0DefaultActive()||(pcSlice->isInterB()&&pcSlice->getNumRefIdx( REF_PIC_LIST_1 )!=pcSlice->getPPS()->getNumRefIdxL1DefaultActive()));
// 参考帧的数量
WRITE_FLAG( overrideFlag ? 1 : 0, "num_ref_idx_active_override_flag");
if (overrideFlag)
{
// 参考帧的数量
WRITE_UVLC( pcSlice->getNumRefIdx( REF_PIC_LIST_0 ) - 1, "num_ref_idx_l0_active_minus1" );
if (pcSlice->isInterB())
{
// 参考帧的数量
WRITE_UVLC( pcSlice->getNumRefIdx( REF_PIC_LIST_1 ) - 1, "num_ref_idx_l1_active_minus1" );
}
else
{
pcSlice->setNumRefIdx(REF_PIC_LIST_1, 0);
}
}
}
else
{
pcSlice->setNumRefIdx(REF_PIC_LIST_0, 0);
pcSlice->setNumRefIdx(REF_PIC_LIST_1, 0);
}
if( pcSlice->getPPS()->getListsModificationPresentFlag() && pcSlice->getNumRpsCurrTempList() > 1)
{
TComRefPicListModification* refPicListModification = pcSlice->getRefPicListModification();
if(!pcSlice->isIntra())
{
WRITE_FLAG(pcSlice->getRefPicListModification()->getRefPicListModificationFlagL0() ? 1 : 0, "ref_pic_list_modification_flag_l0" );
if (pcSlice->getRefPicListModification()->getRefPicListModificationFlagL0())
{
Int numRpsCurrTempList0 = pcSlice->getNumRpsCurrTempList();
if (numRpsCurrTempList0 > 1)
{
Int length = 1;
numRpsCurrTempList0 --;
while ( numRpsCurrTempList0 >>= 1)
{
length ++;
}
for(Int i = 0; i < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); i++)
{
// 参考帧索引
WRITE_CODE( refPicListModification->getRefPicSetIdxL0(i), length, "list_entry_l0");
}
}
}
}
if(pcSlice->isInterB())
{
WRITE_FLAG(pcSlice->getRefPicListModification()->getRefPicListModificationFlagL1() ? 1 : 0, "ref_pic_list_modification_flag_l1" );
if (pcSlice->getRefPicListModification()->getRefPicListModificationFlagL1())
{
Int numRpsCurrTempList1 = pcSlice->getNumRpsCurrTempList();
if ( numRpsCurrTempList1 > 1 )
{
Int length = 1;
numRpsCurrTempList1 --;
while ( numRpsCurrTempList1 >>= 1)
{
length ++;
}
for(Int i = 0; i < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); i++)
{
// 参考帧的索引
WRITE_CODE( refPicListModification->getRefPicSetIdxL1(i), length, "list_entry_l1");
}
}
}
}
}
if (pcSlice->isInterB())
{
// list1中MVD是否为0的标志?
WRITE_FLAG( pcSlice->getMvdL1ZeroFlag() ? 1 : 0, "mvd_l1_zero_flag");
}
if(!pcSlice->isIntra())
{
if (!pcSlice->isIntra() && pcSlice->getPPS()->getCabacInitPresentFlag())
{
SliceType sliceType = pcSlice->getSliceType();
Int encCABACTableIdx = pcSlice->getPPS()->getEncCABACTableIdx();
Bool encCabacInitFlag = (sliceType!=encCABACTableIdx && encCABACTableIdx!=I_SLICE) ? true : false;
pcSlice->setCabacInitFlag( encCabacInitFlag );
// CABAC初始化的标志
WRITE_FLAG( encCabacInitFlag?1:0, "cabac_init_flag" );
}
}
if ( pcSlice->getEnableTMVPFlag() )
{
if ( pcSlice->getSliceType() == B_SLICE )
{
// 是否使用了混合列表
WRITE_FLAG( pcSlice->getColFromL0Flag(), "collocated_from_l0_flag" );
}
if ( pcSlice->getSliceType() != I_SLICE &&
((pcSlice->getColFromL0Flag()==1 && pcSlice->getNumRefIdx(REF_PIC_LIST_0)>1)||
(pcSlice->getColFromL0Flag()==0 && pcSlice->getNumRefIdx(REF_PIC_LIST_1)>1)))
{
// 混合参考列表的索引?
WRITE_UVLC( pcSlice->getColRefIdx(), "collocated_ref_idx" );
}
}
if ( (pcSlice->getPPS()->getUseWP() && pcSlice->getSliceType()==P_SLICE) || (pcSlice->getPPS()->getWPBiPred() && pcSlice->getSliceType()==B_SLICE) )
{
// 带权预测的一些信息
xCodePredWeightTable( pcSlice );
}
assert(pcSlice->getMaxNumMergeCand()<=MRG_MAX_NUM_CANDS);
if (!pcSlice->isIntra())
{
// merge模式的候选者的数量
WRITE_UVLC(MRG_MAX_NUM_CANDS - pcSlice->getMaxNumMergeCand(), "five_minus_max_num_merge_cand");
}
Int iCode = pcSlice->getSliceQp() - ( pcSlice->getPPS()->getPicInitQPMinus26() + 26 );
// 量化步长
WRITE_SVLC( iCode, "slice_qp_delta" );
if (pcSlice->getPPS()->getSliceChromaQpFlag())
{
iCode = pcSlice->getSliceQpDeltaCb();
WRITE_SVLC( iCode, "slice_qp_delta_cb" );
iCode = pcSlice->getSliceQpDeltaCr();
WRITE_SVLC( iCode, "slice_qp_delta_cr" );
}
if (pcSlice->getPPS()->getDeblockingFilterControlPresentFlag())
{
if (pcSlice->getPPS()->getDeblockingFilterOverrideEnabledFlag() )
{
// 去方块滤波覆盖的标记?
WRITE_FLAG(pcSlice->getDeblockingFilterOverrideFlag(), "deblocking_filter_override_flag");
}
if (pcSlice->getDeblockingFilterOverrideFlag())
{
// 是否启用去方块滤波
WRITE_FLAG(pcSlice->getDeblockingFilterDisable(), "slice_disable_deblocking_filter_flag");
if(!pcSlice->getDeblockingFilterDisable())
{
WRITE_SVLC (pcSlice->getDeblockingFilterBetaOffsetDiv2(), "slice_beta_offset_div2");
WRITE_SVLC (pcSlice->getDeblockingFilterTcOffsetDiv2(), "slice_tc_offset_div2");
}
}
}
Bool isSAOEnabled = (!pcSlice->getSPS()->getUseSAO())?(false):(pcSlice->getSaoEnabledFlag()||pcSlice->getSaoEnabledFlagChroma());
Bool isDBFEnabled = (!pcSlice->getDeblockingFilterDisable());
if(pcSlice->getPPS()->getLoopFilterAcrossSlicesEnabledFlag() && ( isSAOEnabled || isDBFEnabled ))
{
// 环路滤波是否跨越片的边界
WRITE_FLAG(pcSlice->getLFCrossSliceBoundaryFlag()?1:0, "slice_loop_filter_across_slices_enabled_flag");
}
}
if(pcSlice->getPPS()->getSliceHeaderExtensionPresentFlag())
{
// 片头扩展长度
WRITE_UVLC(0,"slice_header_extension_length");
}
}