标签:
Mode Decision(模式选择)决定一个宏块以何种类型进行分割。宏块的分割类型有以下几种:
enum { //P_Skip and B_Skip(B_Direct) means that nothing need to be encoded ,just use the mv predicted and the residue mb base on such mv PSKIP = 0, //just use residue of mb coeff but mvc BSKIP_DIRECT = 0, //skip mode on b slice P16x16 = 1, //16x16 on p or b slice P16x8 = 2, //16x8 on p or b slice P8x16 = 3, //8x16 on p or b slice SMB8x8 = 4, //sub macroblock 8x8 on p or b slice SMB8x4 = 5, //sub macroblock 8x4 on p or b slice SMB4x8 = 6, //sub macroblock 4x8 on p or b slice SMB4x4 = 7, //sub macroblock 4x4 on p or b slice P8x8 = 8, //set of sub macroblock modes I4MB = 9, //4x4 on i slice I16MB = 10, //16x16 on i slice IBLOCK = 11, //the same with I4MB SI4MB = 12, // I8MB = 13, //8x8 on i slice IPCM = 14, //PCM mode MAXMODE = 15 } MBModeTypes;
模式选择就是通过某种算法得到最优的宏块分割类型。不同算法在流程、最优分割方式选择上会有区别,但是都遵循h.264的标准。
宏块与子宏块
macroblock_layer( ) { mb_type if( mb_type = = I_PCM ) { while( !byte_aligned( ) ) pcm_alignment_zero_bit for( i = 0; i < 256; i++ ) pcm_sample_luma[ i ] for( i = 0; i < 2 * MbWidthC * MbHeightC; i++ ) pcm_sample_chroma[ i ] } else { noSubMbPartSizeLessThan8x8Flag = 1 if( mb_type != I_NxN && MbPartPredMode( mb_type, 0 ) != Intra_16x16 && NumMbPart( mb_type ) = = 4 ) { sub_mb_pred( mb_type ) //子宏块预测 for( mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++ ) if( sub_mb_type[ mbPartIdx ] != B_Direct_8x8 ) { if( NumSubMbPart( sub_mb_type[ mbPartIdx ] ) > 1 ) noSubMbPartSizeLessThan8x8Flag = 0 } else if( !direct_8x8_inference_flag ) noSubMbPartSizeLessThan8x8Flag = 0 } else { if( transform_8x8_mode_flag && mb_type = = I_NxN ) transform_size_8x8_flag mb_pred( mb_type ) //宏块预测 } if( MbPartPredMode( mb_type, 0 ) != Intra_16x16 ) { coded_block_pattern if( CodedBlockPatternLuma > 0 && transform_8x8_mode_flag && mb_type != I_NxN && noSubMbPartSizeLessThan8x8Flag && ( mb_type != B_Direct_16x16 | | direct_8x8_inference_flag ) ) transform_size_8x8_flag } if( CodedBlockPatternLuma > 0 | | CodedBlockPatternChroma > 0 | | MbPartPredMode( mb_type, 0 ) = = Intra_16x16 ) { mb_qp_delta residual( ) } } }
上面是宏块层的语法,可以看到宏块预测可以分为两大类:宏块预测、子宏块预测,这两类预测是相互独立的。宏块预测包含的宏块类型有:PSKIP, BSKIP_DIRECT, P16x16, P16x8, P8x16, I4MB, I16MB, I8MB。子宏块包含的宏块类型有:SMB8x8, SMB8x4, SMB4x8, SMB4x4。
宏块类型可以再分为三小类:
子宏块类型则可以统一为一种类型P8x8,每个宏块有4个P8x8的子宏块,4个子宏块独立进行子宏块预测,每个子宏块都可以为不同的子宏块类型。
Chroma模式选择
Chroma宏块只分为intra与inter两种类型,并不再细分。标准规定了Chroma宏块的预测方式是受到luma的预测方式的制约的。当luma是以intra进行预测时,chroma宏块才会进行intra预测;当luma是以inter进行预测时,chroma宏块进行的是inter预测(Chroma inter预测不会自行预测,而是通过luma预测结果进行缩放处理后得到的Chroma mv)。
宏块预测中,只有I4MB, I16MB, I8MB时Chroma宏块才会采用intra预测:
//只有当luma的预测模式为intra时,才会进行Chroma的intra预测 mb_pred( mb_type ) { if( MbPartPredMode( mb_type, 0 ) = = Intra_4x4 | | MbPartPredMode( mb_type, 0 ) = = Intra_8x8 | | MbPartPredMode( mb_type, 0 ) = = Intra_16x16 ) { if( MbPartPredMode( mb_type, 0 ) = = Intra_4x4 ) for( luma4x4BlkIdx=0; luma4x4BlkIdx<16; luma4x4BlkIdx++ ) { prev_intra4x4_pred_mode_flag[ luma4x4BlkIdx ] if( !prev_intra4x4_pred_mode_flag[ luma4x4BlkIdx ] ) rem_intra4x4_pred_mode[ luma4x4BlkIdx ] } if( MbPartPredMode( mb_type, 0 ) = = Intra_8x8 ) for( luma8x8BlkIdx=0; luma8x8BlkIdx<4; luma8x8BlkIdx++ ) { prev_intra8x8_pred_mode_flag[ luma8x8BlkIdx ] if( !prev_intra8x8_pred_mode_flag[ luma8x8BlkIdx ] ) rem_intra8x8_pred_mode[ luma8x8BlkIdx ] } if( chroma_format_idc != 0 ) intra_chroma_pred_mode } else if( MbPartPredMode( mb_type, 0 ) != Direct ) { for( mbPartIdx = 0; mbPartIdx < NumMbPart( mb_type ); mbPartIdx++) if( ( num_ref_idx_l0_active_minus1 > 0 | | mb_field_decoding_flag ) && MbPartPredMode( mb_type, mbPartIdx ) != Pred_L1 ) ref_idx_l0[ mbPartIdx ] for( mbPartIdx = 0; mbPartIdx < NumMbPart( mb_type ); mbPartIdx++) if( ( num_ref_idx_l1_active_minus1 > 0 | | mb_field_decoding_flag ) && MbPartPredMode( mb_type, mbPartIdx ) != Pred_L0 ) ref_idx_l1[ mbPartIdx ] for( mbPartIdx = 0; mbPartIdx < NumMbPart( mb_type ); mbPartIdx++) if( MbPartPredMode ( mb_type, mbPartIdx ) != Pred_L1 ) for( compIdx = 0; compIdx < 2; compIdx++ ) mvd_l0[ mbPartIdx ][ 0 ][ compIdx ] for( mbPartIdx = 0; mbPartIdx < NumMbPart( mb_type ); mbPartIdx++) if( MbPartPredMode( mb_type, mbPartIdx ) != Pred_L0 ) for( compIdx = 0; compIdx < 2; compIdx++ ) mvd_l1[ mbPartIdx ][ 0 ][ compIdx ] } }
子宏块预测中没有Chroma intra预测:
//可以看到子宏块预测时,没有Chroma的intra预测 sub_mb_pred( mb_type ) { for( mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++ ) sub_mb_type[ mbPartIdx ] for( mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++ ) if( ( num_ref_idx_l0_active_minus1 > 0 | | mb_field_decoding_flag ) && mb_type != P_8x8ref0 && sub_mb_type[ mbPartIdx ] != B_Direct_8x8 && SubMbPredMode( sub_mb_type[ mbPartIdx ] ) != Pred_L1 ) ref_idx_l0[ mbPartIdx ] for( mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++ ) if( (num_ref_idx_l1_active_minus1 > 0 | | mb_field_decoding_flag ) && sub_mb_type[ mbPartIdx ] != B_Direct_8x8 && SubMbPredMode( sub_mb_type[ mbPartIdx ] ) != Pred_L0 ) ref_idx_l1[ mbPartIdx ] for( mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++ ) if( sub_mb_type[ mbPartIdx ] != B_Direct_8x8 && SubMbPredMode( sub_mb_type[ mbPartIdx ] ) != Pred_L1 ) for( subMbPartIdx = 0; subMbPartIdx < NumSubMbPart( sub_mb_type[ mbPartIdx ] ); subMbPartIdx++) for( compIdx = 0; compIdx < 2; compIdx++ ) mvd_l0[ mbPartIdx ][ subMbPartIdx ][ compIdx ] for( mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++ ) if( sub_mb_type[ mbPartIdx ] != B_Direct_8x8 && SubMbPredMode( sub_mb_type[ mbPartIdx ] ) != Pred_L0 ) for( subMbPartIdx = 0; subMbPartIdx < NumSubMbPart( sub_mb_type[ mbPartIdx ] ); subMbPartIdx++) for( compIdx = 0; compIdx < 2; compIdx++ ) mvd_l1[ mbPartIdx ][ subMbPartIdx ][ compIdx ] }
JM18.6中有几种模式选择的算法,下面来分析一下low与high这两种算法的流程。
Mode Decision Low
该过程非常主要的一个特点是Chroma不参与模式选择
简述一下Low的流程:
Mode Decision High
该过程中chroma宏块也参与模式选择。
简述一下high的流程:
LOW与HIGH的共同点
可以看到他们在inter模式选择时流程大致一样的。先得到宏块的最佳分割模式,然后得到4个子宏块的最佳分割模式。下面大致浏览一下PartitionMotionSearch与SubPartitionMotionSearch的流程。
LOW与HIGH的不同点
不同点大致分为流程上,最优分割模式选择(计算rdcost)的差异。
Low在对每种分割模式预测完后,立刻进行rdcost计算,用得到的rdcost对比前面已经得到的最佳cost,从而得到最佳模式。在得到最佳模式后,再进行残差编码与重建。
High统一把对比cost并得到最佳模式这个过程写到compute_mode_RD_cost里面。在前面进行完成运动预测后,进入该函数对9种分割模式进行残差编码,宏块重建,cost计算与对比。其中4种intra分割模式是在这个函数内部才分别进行预测的。
Low的rdcost计算并不像high的那么严谨,只是简单地算出distortion与残差系数以外的bit数。Low的rdcost不包括chroma所占用的bit。
High的rdcost会计算经由熵编码后得到的bit,并且包含了chroma所占用的bit,因此更加精准。但是也会相应地增加编码时间。
标签:
原文地址:http://www.cnblogs.com/TaigaCon/p/4458189.html