HM编码器代码阅读(23)——参数集的熵编码

在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是否包含扩展信息。

下面是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");
	}
}





  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值