帧间预测模式选择和分割part1
来源:互联网 发布:虾米音乐 mac 快捷键 编辑:程序博客网 时间:2024/05/16 09:14
// http://blog.chinaunix.net/uid-22763991-id-1769545.html
//帧间预测模式的选择及宏块分割 //在对P帧或B帧的宏块进行预测之前,先判断当前帧是否适宜用帧内模式, //如果宏块的临近已编码宏块均不采用帧内模式,并且若宏块所在的slice为p的话, //参考帧相应位置的宏块也不采用帧内模式的话,则该宏块采用帧内预测的可能性就很小。 //那么在该宏块用帧间模式得到的最小的SAD后,只要计算帧内16*16预测模式的SAD, //将二者相比,当比值超过门限值时,即用帧间预测模式,而不用计算帧内4*4的模式了。else if( h->sh.i_type == SLICE_TYPE_P )// P帧预测模式的选择 { //当是P帧时,首先判断是否是skip模式,只有在左,上,左上,右上有一个是skip模式的时候, //这时mb才 可能是skip模式:b_skip = x264_macroblock_probe_pskip( h ); //当不采用p_skip模式时,则调用x264_mb_analyse_inter_p16x16( x264_t *h, x264_mb_analysis_t *a ) //进行帧间16*16块的分析:计算p16x16模式的运动适量及cost(其中还要考虑到参考帧部分,运动估计)。 //然后在允许16*16块分割时,进一步分析8*8,4*4,16*8,8*16块的运动矢量,并比较cost的大小。 //获得最佳的运动估计模式。得到子宏块的分割方式存储在 i_partion。随后根据i_partion进行像素细化。 int b_skip = 0; int i_intra_cost, i_intra_type; h->mc.prefetch_ref( h->mb.pic.p_fref[0][0][h->mb.i_mb_x&3], h->mb.pic.i_stride[0], 0 );//空函数? /* Fast P_SKIP detection */ analysis.b_try_pskip = 0; if( h->param.analyse.b_fast_pskip ) { if( h->param.i_threads > 1 && h->mb.cache.pskip_mv[1] > h->mb.mv_max_spel[1] ) // FIXME don't need to check this if the reference frame is done {} else if( h->param.analyse.i_subpel_refine >= 3 ) analysis.b_try_pskip = 1; else if( h->mb.i_mb_type_left == P_SKIP || h->mb.i_mb_type_top == P_SKIP || h->mb.i_mb_type_topleft == P_SKIP || h->mb.i_mb_type_topright == P_SKIP ) b_skip = x264_macroblock_probe_pskip( h );//判断是否可以进行P_skip编码 } h->mc.prefetch_ref( h->mb.pic.p_fref[0][0][h->mb.i_mb_x&3], h->mb.pic.i_stride[0], 1 ); if( b_skip ) { h->mb.i_type = P_SKIP; h->mb.i_partition = D_16x16; assert( h->mb.cache.pskip_mv[1] <= h->mb.mv_max_spel[1] || h->param.i_threads == 1 ); } else { const unsigned int flags = h->param.analyse.inter; int i_type; int i_partition; int i_thresh16x8; int i_satd_inter, i_satd_intra; x264_mb_analyse_load_costs( h, &analysis );// initialize an array of lambda*nbits for all possible mvs x264_mb_analyse_inter_p16x16( h, &analysis );//P16x16 宏块预测模式的分析;下面是这个函数的解析 static void x264_mb_analyse_inter_p16x16( x264_t *h, x264_mb_analysis_t *a ) { x264_me_t m; int i_ref, i_mvc; DECLARE_ALIGNED_4( int16_t mvc[8][2] ); int i_halfpel_thresh = INT_MAX; int *p_halfpel_thresh = h->mb.pic.i_fref[0]>1 ? &i_halfpel_thresh : NULL; /* 16x16 Search on all ref frame */ m.i_pixel = PIXEL_16x16; m.p_cost_mv = a->p_cost_mv; //初始化MV的cost LOAD_FENC( &m, h->mb.pic.p_fenc, 0, 0 );//加载将要编码的宏块 a->l0.me16x16.cost = INT_MAX;//初始化ME的cost for( i_ref = 0; i_ref < h->mb.pic.i_fref[0]; i_ref++ )//遍历所有的参考帧寻找最佳的参考块 { const int i_ref_cost = REF_COST( 0, i_ref );//参考帧的cost i_halfpel_thresh -= i_ref_cost; m.i_ref_cost = i_ref_cost; m.i_ref = i_ref; /* search with ref */ LOAD_HPELS( &m, h->mb.pic.p_fref[0][i_ref], 0, i_ref, 0, 0 );//加载参考帧 x264_mb_predict_mv_16x16( h, 0, i_ref, m.mvp );//确定搜索的初始位置(中值法) x264_mb_predict_mv_ref16x16( h, 0, i_ref, mvc, &i_mvc );//寻找其它候选运动矢量。这些候选者包括:空间相邻的左、左上、上、右上块的MV;第0个参考帧中的当前块、右边块、下边快运动矢量乘以时间差权重。(时空域和空间域) x264_me_search_ref( h, &m, mvc, i_mvc, p_halfpel_thresh );//搜索该参考帧中最佳的匹配块(亚像素搜索在里面) /* early termination * SSD threshold would probably be better than SATD */ if( i_ref == 0 && a->b_try_pskip && m.cost-m.cost_mv < 300*a->i_lambda && abs(m.mv[0]-h->mb.cache.pskip_mv[0]) + abs(m.mv[1]-h->mb.cache.pskip_mv[1]) <= 1 && x264_macroblock_probe_pskip( h ) ) { h->mb.i_type = P_SKIP; x264_analyse_update_cache( h, a ); assert( h->mb.cache.pskip_mv[1] <= h->mb.mv_max_spel[1] || h->param.i_threads == 1 ); return; } m.cost += i_ref_cost; i_halfpel_thresh += i_ref_cost; if( m.cost < a->l0.me16x16.cost ) h->mc.memcpy_aligned( &a->l0.me16x16, &m, sizeof(x264_me_t) ); /* save mv for predicting neighbors */ *(uint32_t*)a->l0.mvc[i_ref][0] = *(uint32_t*)h->mb.mvr[0][i_ref][h->mb.i_mb_xy] = *(uint32_t*)m.mv; } x264_macroblock_cache_ref( h, 0, 0, 4, 4, 0, a->l0.me16x16.i_ref );//这里存储的P_L0的ME assert( a->l0.me16x16.mv[1] <= h->mb.mv_max_spel[1] || h->param.i_threads == 1 ); h->mb.i_type = P_L0; if( a->i_mbrd ) { x264_mb_cache_fenc_satd( h );// if( a->l0.me16x16.i_ref == 0 && *(uint32_t*)a->l0.me16x16.mv == *(uint32_t*)h->mb.cache.pskip_mv ) { h->mb.i_partition = D_16x16; x264_macroblock_cache_mv_ptr( h, 0, 0, 4, 4, 0, a->l0.me16x16.mv );//这里存储的P_L0的MV a->l0.i_rd16x16 = x264_rd_cost_mb( h, a->i_lambda2 );//保留cost } } } if( h->mb.i_type == P_SKIP ) return; if( flags & X264_ANALYSE_PSUB16x16 )//P8x8预测模式的选择 { if( h->param.analyse.b_mixed_references ) x264_mb_analyse_inter_p8x8_mixed_ref( h, &analysis ); else x264_mb_analyse_inter_p8x8( h, &analysis ); } /* Select best inter mode */ i_type = P_L0; i_partition = D_16x16; i_cost = analysis.l0.me16x16.cost; if( ( flags & X264_ANALYSE_PSUB16x16 ) && analysis.l0.i_cost8x8 < analysis.l0.me16x16.cost ) { i_type = P_8x8; i_partition = D_8x8; i_cost = analysis.l0.i_cost8x8; /* Do sub 8x8 */ if( flags & X264_ANALYSE_PSUB8x8 )//4x4,8x4,4x8,帧间预测模式的选择 { for( i = 0; i < 4; i++ ) { x264_mb_analyse_inter_p4x4( h, &analysis, i ); if( analysis.l0.i_cost4x4[i] < analysis.l0.me8x8[i].cost ) { int i_cost8x8 = analysis.l0.i_cost4x4[i]; h->mb.i_sub_partition[i] = D_L0_4x4; x264_mb_analyse_inter_p8x4( h, &analysis, i ); COPY2_IF_LT( i_cost8x8, analysis.l0.i_cost8x4[i], h->mb.i_sub_partition[i], D_L0_8x4 ); x264_mb_analyse_inter_p4x8( h, &analysis, i ); COPY2_IF_LT( i_cost8x8, analysis.l0.i_cost4x8[i], h->mb.i_sub_partition[i], D_L0_4x8 ); i_cost += i_cost8x8 - analysis.l0.me8x8[i].cost; } x264_mb_cache_mv_p8x8( h, &analysis, i ); } analysis.l0.i_cost8x8 = i_cost; } } /* Now do 16x8/8x16 */ i_thresh16x8 = analysis.l0.me8x8[1].cost_mv + analysis.l0.me8x8[2].cost_mv; if( ( flags & X264_ANALYSE_PSUB16x16 ) && analysis.l0.i_cost8x8 < analysis.l0.me16x16.cost + i_thresh16x8 ) { x264_mb_analyse_inter_p16x8( h, &analysis ); COPY3_IF_LT( i_cost, analysis.l0.i_cost16x8, i_type, P_L0, i_partition, D_16x8 ); x264_mb_analyse_inter_p8x16( h, &analysis ); COPY3_IF_LT( i_cost, analysis.l0.i_cost8x16, i_type, P_L0, i_partition, D_8x16 ); } h->mb.i_partition = i_partition; /* refine qpel */ //FIXME mb_type costs? if( analysis.i_mbrd )//1/4像素的me { /* refine later */ } else if( i_partition == D_16x16 ) { x264_me_refine_qpel( h, &analysis.l0.me16x16 ); i_cost = analysis.l0.me16x16.cost; } else if( i_partition == D_16x8 ) { x264_me_refine_qpel( h, &analysis.l0.me16x8[0] ); x264_me_refine_qpel( h, &analysis.l0.me16x8[1] ); i_cost = analysis.l0.me16x8[0].cost + analysis.l0.me16x8[1].cost; } else if( i_partition == D_8x16 ) { x264_me_refine_qpel( h, &analysis.l0.me8x16[0] ); x264_me_refine_qpel( h, &analysis.l0.me8x16[1] ); i_cost = analysis.l0.me8x16[0].cost + analysis.l0.me8x16[1].cost; } else if( i_partition == D_8x8 ) { int i8x8; i_cost = 0; for( i8x8 = 0; i8x8 < 4; i8x8++ ) { switch( h->mb.i_sub_partition[i8x8] ) { case D_L0_8x8: x264_me_refine_qpel( h, &analysis.l0.me8x8[i8x8] ); i_cost += analysis.l0.me8x8[i8x8].cost; break; case D_L0_8x4: x264_me_refine_qpel( h, &analysis.l0.me8x4[i8x8][0] ); x264_me_refine_qpel( h, &analysis.l0.me8x4[i8x8][1] ); i_cost += analysis.l0.me8x4[i8x8][0].cost + analysis.l0.me8x4[i8x8][1].cost; break; case D_L0_4x8: x264_me_refine_qpel( h, &analysis.l0.me4x8[i8x8][0] ); x264_me_refine_qpel( h, &analysis.l0.me4x8[i8x8][1] ); i_cost += analysis.l0.me4x8[i8x8][0].cost + analysis.l0.me4x8[i8x8][1].cost; break; case D_L0_4x4: x264_me_refine_qpel( h, &analysis.l0.me4x4[i8x8][0] ); x264_me_refine_qpel( h, &analysis.l0.me4x4[i8x8][1] ); x264_me_refine_qpel( h, &analysis.l0.me4x4[i8x8][2] ); x264_me_refine_qpel( h, &analysis.l0.me4x4[i8x8][3] ); i_cost += analysis.l0.me4x4[i8x8][0].cost + analysis.l0.me4x4[i8x8][1].cost + analysis.l0.me4x4[i8x8][2].cost + analysis.l0.me4x4[i8x8][3].cost; break; default: x264_log( h, X264_LOG_ERROR, "internal error (!8x8 && !4x4)\n" ); break; } } } if( h->mb.b_chroma_me )//是否进行色度的ME { x264_mb_analyse_intra_chroma( h, &analysis ); x264_mb_analyse_intra( h, &analysis, i_cost - analysis.i_satd_i8x8chroma ); analysis.i_satd_i16x16 += analysis.i_satd_i8x8chroma; analysis.i_satd_i8x8 += analysis.i_satd_i8x8chroma; analysis.i_satd_i4x4 += analysis.i_satd_i8x8chroma; } else x264_mb_analyse_intra( h, &analysis, i_cost ); //这段是帧内预测 i_satd_inter = i_cost; i_satd_intra = X264_MIN3( analysis.i_satd_i16x16, analysis.i_satd_i8x8, analysis.i_satd_i4x4 ); if( analysis.i_mbrd ) { x264_mb_analyse_p_rd( h, &analysis, X264_MIN(i_satd_inter, i_satd_intra) ); i_type = P_L0; i_partition = D_16x16; i_cost = analysis.l0.me16x16.cost; COPY2_IF_LT( i_cost, analysis.l0.i_cost16x8, i_partition, D_16x8 ); COPY2_IF_LT( i_cost, analysis.l0.i_cost8x16, i_partition, D_8x16 ); COPY3_IF_LT( i_cost, analysis.l0.i_cost8x8, i_partition, D_8x8, i_type, P_8x8 ); h->mb.i_type = i_type; h->mb.i_partition = i_partition; if( i_cost < COST_MAX ) x264_mb_analyse_transform_rd( h, &analysis, &i_satd_inter, &i_cost ); x264_intra_rd( h, &analysis, i_satd_inter * 5/4 ); } i_intra_type = I_16x16; i_intra_cost = analysis.i_satd_i16x16; COPY2_IF_LT( i_intra_cost, analysis.i_satd_i8x8, i_intra_type, I_8x8 ); COPY2_IF_LT( i_intra_cost, analysis.i_satd_i4x4, i_intra_type, I_4x4 ); COPY2_IF_LT( i_intra_cost, analysis.i_satd_pcm, i_intra_type, I_PCM ); COPY2_IF_LT( i_cost, i_intra_cost, i_type, i_intra_type );//比较帧内帧间的cost if( i_intra_cost == COST_MAX ) i_intra_cost = i_cost * i_satd_intra / i_satd_inter + 1; h->mb.i_type = i_type; h->stat.frame.i_intra_cost += i_intra_cost; h->stat.frame.i_inter_cost += i_cost; h->stat.frame.i_mbs_analysed++; if( analysis.i_mbrd >= 2 && h->mb.i_type != I_PCM )//亚像素搜索...() { if( IS_INTRA( h->mb.i_type ) ) { x264_intra_rd_refine( h, &analysis ); } else if( i_partition == D_16x16 ) { x264_macroblock_cache_ref( h, 0, 0, 4, 4, 0, analysis.l0.me16x16.i_ref ); x264_me_refine_qpel_rd( h, &analysis.l0.me16x16, analysis.i_lambda2, 0, 0 ); //率失真函数 } else if( i_partition == D_16x8 ) { h->mb.i_sub_partition[0] = h->mb.i_sub_partition[1] = h->mb.i_sub_partition[2] = h->mb.i_sub_partition[3] = D_L0_8x8; x264_macroblock_cache_ref( h, 0, 0, 4, 2, 0, analysis.l0.me16x8[0].i_ref ); x264_macroblock_cache_ref( h, 0, 2, 4, 2, 0, analysis.l0.me16x8[1].i_ref ); x264_me_refine_qpel_rd( h, &analysis.l0.me16x8[0], analysis.i_lambda2, 0, 0 ); x264_me_refine_qpel_rd( h, &analysis.l0.me16x8[1], analysis.i_lambda2, 8, 0 ); } else if( i_partition == D_8x16 ) { h->mb.i_sub_partition[0] = h->mb.i_sub_partition[1] = h->mb.i_sub_partition[2] = h->mb.i_sub_partition[3] = D_L0_8x8; x264_macroblock_cache_ref( h, 0, 0, 2, 4, 0, analysis.l0.me8x16[0].i_ref ); x264_macroblock_cache_ref( h, 2, 0, 2, 4, 0, analysis.l0.me8x16[1].i_ref ); x264_me_refine_qpel_rd( h, &analysis.l0.me8x16[0], analysis.i_lambda2, 0, 0 ); x264_me_refine_qpel_rd( h, &analysis.l0.me8x16[1], analysis.i_lambda2, 4, 0 ); } else if( i_partition == D_8x8 ) { int i8x8; x264_analyse_update_cache( h, &analysis ); for( i8x8 = 0; i8x8 < 4; i8x8++ ) { if( h->mb.i_sub_partition[i8x8] == D_L0_8x8 ) { x264_me_refine_qpel_rd( h, &analysis.l0.me8x8[i8x8], analysis.i_lambda2, i8x8*4, 0 ); } else if( h->mb.i_sub_partition[i8x8] == D_L0_8x4 ) { x264_me_refine_qpel_rd( h, &analysis.l0.me8x4[i8x8][0], analysis.i_lambda2, i8x8*4+0, 0 ); x264_me_refine_qpel_rd( h, &analysis.l0.me8x4[i8x8][1], analysis.i_lambda2, i8x8*4+2, 0 ); } else if( h->mb.i_sub_partition[i8x8] == D_L0_4x8 ) { x264_me_refine_qpel_rd( h, &analysis.l0.me4x8[i8x8][0], analysis.i_lambda2, i8x8*4+0, 0 ); x264_me_refine_qpel_rd( h, &analysis.l0.me4x8[i8x8][1], analysis.i_lambda2, i8x8*4+1, 0 ); } else if( h->mb.i_sub_partition[i8x8] == D_L0_4x4 ) { x264_me_refine_qpel_rd( h, &analysis.l0.me4x4[i8x8][0], analysis.i_lambda2, i8x8*4+0, 0 ); x264_me_refine_qpel_rd( h, &analysis.l0.me4x4[i8x8][1], analysis.i_lambda2, i8x8*4+1, 0 ); x264_me_refine_qpel_rd( h, &analysis.l0.me4x4[i8x8][2], analysis.i_lambda2, i8x8*4+2, 0 ); x264_me_refine_qpel_rd( h, &analysis.l0.me4x4[i8x8][3], analysis.i_lambda2, i8x8*4+3, 0 ); } } } } } }
- 帧间预测模式选择和分割part1
- 帧间预测模式的选择及宏块分割part2
- 帧内预测和帧间预测
- 帧间预测-AMVP 模式
- 帧内预测模式预测
- HEVC帧间预测模式获取
- 帧内预测和帧间预测的比较
- 帧内预测和帧间预测的比较
- 帧内预测和帧间预测的关系
- HEVC算法和体系结构:预测编码之帧间预测
- h.264视频编码中快速的帧内预测模式选择
- HEVC中的帧内预测模式选择(Intra prediction mode selection in HEVC)
- 图像语义分割之特征整合和结构预测
- 帧内预测模式提取
- 帧内预测模式RDO
- 帧内预测模式RDO
- 帧间预测:视频内容与最佳预测模式之间的关系(总结)
- Story 1---O2O优惠券使用预测---part1
- UML类图示例
- Android 中如何关闭线程
- Firebug使用之五--Console API
- 【POI】 Excel导入异常Cannot get a text value from a numeric cell解决
- usrpL0变采样滤波器的性能优化
- 帧间预测模式选择和分割part1
- Android应用开发学习笔记之Service
- 线程的创建和等待
- linux lsof
- hdu 1575 Tr A (矩阵快模幂)
- 介绍VC中3种方法得到文本框中的值
- HTTP协议详解个人总结(1)
- poj 1604
- Unix网络编程--进程间通信--管道通信