帧间预测模式选择和分割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 );                        }                    }                }            }        }    }


 

原创粉丝点击