x264源代碼簡單分析:宏塊分析(Analysis)部分-幀內宏塊(Intra)

本文轉自:http://blog.csdn.net/leixiaohua1020/article/details/45870269  歡迎訪問原處!

      本文記錄x264的 x264_slice_write()函數中調用的x264_macroblock_analyse()的源代碼。x264_macroblock_analyse()對應着x264中的分析模塊。分析模塊主要完成了下面2個方面的功能:

(1)對於幀內宏塊,分析幀內預測模式
(2)對於幀間宏塊,進行運動估計,分析幀間預測模式
由於分析模塊比較複雜,因此分成兩篇文章記錄其中的源代碼:本文記錄幀內宏塊預測模式的分析,下一篇文章記錄幀間宏塊預測模式的分析。


函數調用關係圖

宏塊分析(Analysis)部分的源代碼在整個x264中的位置如下圖所示。



宏塊分析(Analysis)部分的函數調用關係如下圖所示。



從圖中可以看出,分析模塊的x264_macroblock_analyse()調用瞭如下函數(只列舉了幾個有代表性的函數):
x264_mb_analyse_init():Analysis模塊初始化。
x264_mb_analyse_intra():Intra宏塊幀內預測模式分析。
x264_macroblock_probe_pskip():分析是否是skip模式。
x264_mb_analyse_inter_p16x16():P16x16宏塊幀間預測模式分析。
x264_mb_analyse_inter_p8x8():P8x8宏塊幀間預測模式分析。
x264_mb_analyse_inter_p16x8():P16x8宏塊幀間預測模式分析。
x264_mb_analyse_inter_b16x16():B16x16宏塊幀間預測模式分析。
x264_mb_analyse_inter_b8x8():B8x8宏塊幀間預測模式分析。
x264_mb_analyse_inter_b16x8():B16x8宏塊幀間預測模式分析。
本文重點分析其中幀內宏塊(Intra宏塊)的分析函數x264_mb_analyse_intra()。下一篇文章再對x264_mb_analyse_inter_p16x16()等一系列幀間宏塊的分析函數。


x264_slice_write()

x264_slice_write()是x264項目的核心,它完成了編碼了一個Slice的工作。有關該函數的分析可以參考文章《 x264源代碼簡單分析:x264_slice_write() 》。本文分析其調用的x264_mb_analyse()函數。


x264_macroblock_analyse()

x264_macroblock_analyse()用於分析宏塊的預測模式。該函數的定義位於encoder\analyse.c,如下所示。
[cpp]  view plain  copy
  1. /**************************************************************************** 
  2.  * 分析-幀內預測模式選擇、幀間運動估計等 
  3.  * 
  4.  * 註釋和處理:雷霄驊 
  5.  * http://blog.csdn.net/leixiaohua1020 
  6.  * [email protected] 
  7.  ****************************************************************************/  
  8. void x264_macroblock_analyse( x264_t *h )  
  9. {  
  10.     x264_mb_analysis_t analysis;  
  11.     int i_cost = COST_MAX;  
  12.     //通過碼率控制方法,獲取本宏塊QP  
  13.     h->mb.i_qp = x264_ratecontrol_mb_qp( h );  
  14.     /* If the QP of this MB is within 1 of the previous MB, code the same QP as the previous MB, 
  15.      * to lower the bit cost of the qp_delta.  Don't do this if QPRD is enabled. */  
  16.     if( h->param.rc.i_aq_mode && h->param.analyse.i_subpel_refine < 10 )  
  17.         h->mb.i_qp = abs(h->mb.i_qp - h->mb.i_last_qp) == 1 ? h->mb.i_last_qp : h->mb.i_qp;  
  18.   
  19.     if( h->param.analyse.b_mb_info )  
  20.         h->fdec->effective_qp[h->mb.i_mb_xy] = h->mb.i_qp; /* Store the real analysis QP. */  
  21.     //初始化  
  22.     x264_mb_analyse_init( h, &analysis, h->mb.i_qp );  
  23.   
  24.     /*--------------------------- Do the analysis ---------------------------*/  
  25.     //I幀:只使用幀內預測,分別計算亮度16x16(4種)和4x4(9種)所有模式的代價值,選出代價最小的模式  
  26.   
  27.     //P幀:計算幀內模式和幀間模式( P Slice允許有Intra宏塊和P宏塊;同理B幀也支持Intra宏塊)。  
  28.     //對P幀的每一種分割進行幀間預測,得到最佳的運動矢量及最佳匹配塊。  
  29.     //幀間預測過程:選出最佳矢量——>找到最佳的整像素點——>找到最佳的二分之一像素點——>找到最佳的1/4像素點  
  30.     //然後取代價最小的爲最佳MV和分割方式  
  31.     //最後從幀內模式和幀間模式中選擇代價比較小的方式(有可能沒有找到很好的匹配塊,這時候就直接使用幀內預測而不是幀間預測)。  
  32.   
  33.     if( h->sh.i_type == SLICE_TYPE_I )  
  34.     {  
  35.         //I slice  
  36.         //通過一系列幀內預測模式(16x16的4種,4x4的9種)代價的計算得出代價最小的最優模式  
  37. intra_analysis:  
  38.         if( analysis.i_mbrd )  
  39.             x264_mb_init_fenc_cache( h, analysis.i_mbrd >= 2 );  
  40.         //幀內預測分析  
  41.         //從16×16的SAD,4個8×8的SAD和,16個4×4SAD中選出最優方式  
  42.         x264_mb_analyse_intra( h, &analysis, COST_MAX );  
  43.         if( analysis.i_mbrd )  
  44.             x264_intra_rd( h, &analysis, COST_MAX );  
  45.         //分析結果都存儲在analysis結構體中  
  46.         //開銷  
  47.         i_cost = analysis.i_satd_i16x16;  
  48.         h->mb.i_type = I_16x16;  
  49.         //如果I4x4或者I8x8開銷更小的話就拷貝  
  50.         //copy if little  
  51.         COPY2_IF_LT( i_cost, analysis.i_satd_i4x4, h->mb.i_type, I_4x4 );  
  52.         COPY2_IF_LT( i_cost, analysis.i_satd_i8x8, h->mb.i_type, I_8x8 );  
  53.         //畫面極其特殊的時候,纔有可能用到PCM  
  54.         if( analysis.i_satd_pcm < i_cost )  
  55.             h->mb.i_type = I_PCM;  
  56.   
  57.         else if( analysis.i_mbrd >= 2 )  
  58.             x264_intra_rd_refine( h, &analysis );  
  59.     }  
  60.     else if( h->sh.i_type == SLICE_TYPE_P )  
  61.     {  
  62.         //P slice  
  63.   
  64.         int b_skip = 0;  
  65.   
  66.         h->mc.prefetch_ref( h->mb.pic.p_fref[0][0][h->mb.i_mb_x&3], h->mb.pic.i_stride[0], 0 );  
  67.   
  68.         analysis.b_try_skip = 0;  
  69.         if( analysis.b_force_intra )  
  70.         {  
  71.             if( !h->param.analyse.b_psy )  
  72.             {  
  73.                 x264_mb_analyse_init_qp( h, &analysis, X264_MAX( h->mb.i_qp - h->mb.ip_offset, h->param.rc.i_qp_min ) );  
  74.                 goto intra_analysis;  
  75.             }  
  76.         }  
  77.         else  
  78.         {  
  79.             /* Special fast-skip logic using information from mb_info. */  
  80.             if( h->fdec->mb_info && (h->fdec->mb_info[h->mb.i_mb_xy]&X264_MBINFO_CONSTANT) )  
  81.             {  
  82.                 if( !SLICE_MBAFF && (h->fdec->i_frame - h->fref[0][0]->i_frame) == 1 && !h->sh.b_weighted_pred &&  
  83.                     h->fref[0][0]->effective_qp[h->mb.i_mb_xy] <= h->mb.i_qp )  
  84.                 {  
  85.                     h->mb.i_partition = D_16x16;  
  86.                     /* Use the P-SKIP MV if we can... */  
  87.                     if( !M32(h->mb.cache.pskip_mv) )  
  88.                     {  
  89.                         b_skip = 1;  
  90.                         h->mb.i_type = P_SKIP;  
  91.                     }  
  92.                     /* Otherwise, just force a 16x16 block. */  
  93.                     else  
  94.                     {  
  95.                         h->mb.i_type = P_L0;  
  96.                         analysis.l0.me16x16.i_ref = 0;  
  97.                         M32( analysis.l0.me16x16.mv ) = 0;  
  98.                     }  
  99.                     goto skip_analysis;  
  100.                 }  
  101.                 /* Reset the information accordingly */  
  102.                 else if( h->param.analyse.b_mb_info_update )  
  103.                     h->fdec->mb_info[h->mb.i_mb_xy] &= ~X264_MBINFO_CONSTANT;  
  104.             }  
  105.   
  106.             int skip_invalid = h->i_thread_frames > 1 && h->mb.cache.pskip_mv[1] > h->mb.mv_max_spel[1];  
  107.             /* If the current macroblock is off the frame, just skip it. */  
  108.             if( HAVE_INTERLACED && !MB_INTERLACED && h->mb.i_mb_y * 16 >= h->param.i_height && !skip_invalid )  
  109.                 b_skip = 1;  
  110.             /* Fast P_SKIP detection */  
  111.             else if( h->param.analyse.b_fast_pskip )  
  112.             {  
  113.                 if( skip_invalid )  
  114.                     // FIXME don't need to check this if the reference frame is done  
  115.                     {}  
  116.                 else if( h->param.analyse.i_subpel_refine >= 3 )  
  117.                     analysis.b_try_skip = 1;  
  118.                 else if( h->mb.i_mb_type_left[0] == P_SKIP ||  
  119.                          h->mb.i_mb_type_top == P_SKIP ||  
  120.                          h->mb.i_mb_type_topleft == P_SKIP ||  
  121.                          h->mb.i_mb_type_topright == P_SKIP )  
  122.                     b_skip = x264_macroblock_probe_pskip( h );//檢查是否是Skip類型  
  123.             }  
  124.         }  
  125.   
  126.         h->mc.prefetch_ref( h->mb.pic.p_fref[0][0][h->mb.i_mb_x&3], h->mb.pic.i_stride[0], 1 );  
  127.   
  128.         if( b_skip )  
  129.         {  
  130.             h->mb.i_type = P_SKIP;  
  131.             h->mb.i_partition = D_16x16;  
  132.             assert( h->mb.cache.pskip_mv[1] <= h->mb.mv_max_spel[1] || h->i_thread_frames == 1 );  
  133. skip_analysis:  
  134.             /* Set up MVs for future predictors */  
  135.             forint i = 0; i < h->mb.pic.i_fref[0]; i++ )  
  136.                 M32( h->mb.mvr[0][i][h->mb.i_mb_xy] ) = 0;  
  137.         }  
  138.         else  
  139.         {  
  140.             const unsigned int flags = h->param.analyse.inter;  
  141.             int i_type;  
  142.             int i_partition;  
  143.             int i_satd_inter, i_satd_intra;  
  144.   
  145.             x264_mb_analyse_load_costs( h, &analysis );  
  146.             /* 
  147.              * 16x16 幀間預測宏塊分析-P 
  148.              * 
  149.              * +--------+--------+ 
  150.              * |                 | 
  151.              * |                 | 
  152.              * |                 | 
  153.              * +        +        + 
  154.              * |                 | 
  155.              * |                 | 
  156.              * |                 | 
  157.              * +--------+--------+ 
  158.              * 
  159.              */  
  160.             x264_mb_analyse_inter_p16x16( h, &analysis );  
  161.   
  162.             if( h->mb.i_type == P_SKIP )  
  163.             {  
  164.                 forint i = 1; i < h->mb.pic.i_fref[0]; i++ )  
  165.                     M32( h->mb.mvr[0][i][h->mb.i_mb_xy] ) = 0;  
  166.                 return;  
  167.             }  
  168.   
  169.             if( flags & X264_ANALYSE_PSUB16x16 )  
  170.             {  
  171.                 if( h->param.analyse.b_mixed_references )  
  172.                     x264_mb_analyse_inter_p8x8_mixed_ref( h, &analysis );  
  173.                 else{  
  174.                     /* 
  175.                      * 8x8幀間預測宏塊分析-P 
  176.                      * +--------+ 
  177.                      * |        | 
  178.                      * |        | 
  179.                      * |        | 
  180.                      * +--------+ 
  181.                      */  
  182.                     x264_mb_analyse_inter_p8x8( h, &analysis );  
  183.                 }  
  184.             }  
  185.   
  186.             /* Select best inter mode */  
  187.             i_type = P_L0;  
  188.             i_partition = D_16x16;  
  189.             i_cost = analysis.l0.me16x16.cost;  
  190.   
  191.             //如果8x8的代價值小於16x16  
  192.             //則進行8x8子塊分割的處理  
  193.   
  194.             //處理的數據源自於l0  
  195.             if( ( flags & X264_ANALYSE_PSUB16x16 ) && (!analysis.b_early_terminate ||  
  196.                 analysis.l0.i_cost8x8 < analysis.l0.me16x16.cost) )  
  197.             {  
  198.                 i_type = P_8x8;  
  199.                 i_partition = D_8x8;  
  200.                 i_cost = analysis.l0.i_cost8x8;  
  201.   
  202.                 /* Do sub 8x8 */  
  203.                 if( flags & X264_ANALYSE_PSUB8x8 )  
  204.                 {  
  205.                     forint i = 0; i < 4; i++ )  
  206.                     {  
  207.                         //8x8塊的子塊的分析  
  208.                         /* 
  209.                          * 4x4 
  210.                          * +----+----+ 
  211.                          * |    |    | 
  212.                          * +----+----+ 
  213.                          * |    |    | 
  214.                          * +----+----+ 
  215.                          * 
  216.                          */  
  217.                         x264_mb_analyse_inter_p4x4( h, &analysis, i );  
  218.                         int i_thresh8x4 = analysis.l0.me4x4[i][1].cost_mv + analysis.l0.me4x4[i][2].cost_mv;  
  219.                         //如果4x4小於8x8  
  220.                         //則再分析8x4,4x8的代價  
  221.                         if( !analysis.b_early_terminate || analysis.l0.i_cost4x4[i] < analysis.l0.me8x8[i].cost + i_thresh8x4 )  
  222.                         {  
  223.                             int i_cost8x8 = analysis.l0.i_cost4x4[i];  
  224.                             h->mb.i_sub_partition[i] = D_L0_4x4;  
  225.                             /* 
  226.                              * 8x4 
  227.                              * +----+----+ 
  228.                              * |         | 
  229.                              * +----+----+ 
  230.                              * |         | 
  231.                              * +----+----+ 
  232.                              * 
  233.                              */  
  234.                             //如果8x4小於8x8  
  235.                             x264_mb_analyse_inter_p8x4( h, &analysis, i );  
  236.                             COPY2_IF_LT( i_cost8x8, analysis.l0.i_cost8x4[i],  
  237.                                          h->mb.i_sub_partition[i], D_L0_8x4 );  
  238.                             /* 
  239.                              * 4x8 
  240.                              * +----+----+ 
  241.                              * |    |    | 
  242.                              * +    +    + 
  243.                              * |    |    | 
  244.                              * +----+----+ 
  245.                              * 
  246.                              */  
  247.                             //如果4x8小於8x8  
  248.                             x264_mb_analyse_inter_p4x8( h, &analysis, i );  
  249.                             COPY2_IF_LT( i_cost8x8, analysis.l0.i_cost4x8[i],  
  250.                                          h->mb.i_sub_partition[i], D_L0_4x8 );  
  251.   
  252.                             i_cost += i_cost8x8 - analysis.l0.me8x8[i].cost;  
  253.                         }  
  254.                         x264_mb_cache_mv_p8x8( h, &analysis, i );  
  255.                     }  
  256.                     analysis.l0.i_cost8x8 = i_cost;  
  257.                 }  
  258.             }  
  259.   
  260.             /* Now do 16x8/8x16 */  
  261.             int i_thresh16x8 = analysis.l0.me8x8[1].cost_mv + analysis.l0.me8x8[2].cost_mv;  
  262.   
  263.             //前提要求8x8的代價值小於16x16  
  264.             if( ( flags & X264_ANALYSE_PSUB16x16 ) && (!analysis.b_early_terminate ||  
  265.                 analysis.l0.i_cost8x8 < analysis.l0.me16x16.cost + i_thresh16x8) )  
  266.             {  
  267.                 int i_avg_mv_ref_cost = (analysis.l0.me8x8[2].cost_mv + analysis.l0.me8x8[2].i_ref_cost  
  268.                                       + analysis.l0.me8x8[3].cost_mv + analysis.l0.me8x8[3].i_ref_cost + 1) >> 1;  
  269.                 analysis.i_cost_est16x8[1] = analysis.i_satd8x8[0][2] + analysis.i_satd8x8[0][3] + i_avg_mv_ref_cost;  
  270.                 /* 
  271.                  * 16x8 宏塊劃分 
  272.                  * 
  273.                  * +--------+--------+ 
  274.                  * |        |        | 
  275.                  * |        |        | 
  276.                  * |        |        | 
  277.                  * +--------+--------+ 
  278.                  * 
  279.                  */  
  280.                 x264_mb_analyse_inter_p16x8( h, &analysis, i_cost );  
  281.                 COPY3_IF_LT( i_cost, analysis.l0.i_cost16x8, i_type, P_L0, i_partition, D_16x8 );  
  282.   
  283.                 i_avg_mv_ref_cost = (analysis.l0.me8x8[1].cost_mv + analysis.l0.me8x8[1].i_ref_cost  
  284.                                   + analysis.l0.me8x8[3].cost_mv + analysis.l0.me8x8[3].i_ref_cost + 1) >> 1;  
  285.                 analysis.i_cost_est8x16[1] = analysis.i_satd8x8[0][1] + analysis.i_satd8x8[0][3] + i_avg_mv_ref_cost;  
  286.                 /* 
  287.                  * 8x16 宏塊劃分 
  288.                  * 
  289.                  * +--------+ 
  290.                  * |        | 
  291.                  * |        | 
  292.                  * |        | 
  293.                  * +--------+ 
  294.                  * |        | 
  295.                  * |        | 
  296.                  * |        | 
  297.                  * +--------+ 
  298.                  * 
  299.                  */  
  300.                 x264_mb_analyse_inter_p8x16( h, &analysis, i_cost );  
  301.                 COPY3_IF_LT( i_cost, analysis.l0.i_cost8x16, i_type, P_L0, i_partition, D_8x16 );  
  302.             }  
  303.   
  304.             h->mb.i_partition = i_partition;  
  305.   
  306.             /* refine qpel */  
  307.             //亞像素精度搜索  
  308.             //FIXME mb_type costs?  
  309.             if( analysis.i_mbrd || !h->mb.i_subpel_refine )  
  310.             {  
  311.                 /* refine later */  
  312.             }  
  313.             else if( i_partition == D_16x16 )  
  314.             {  
  315.                 x264_me_refine_qpel( h, &analysis.l0.me16x16 );  
  316.                 i_cost = analysis.l0.me16x16.cost;  
  317.             }  
  318.             else if( i_partition == D_16x8 )  
  319.             {  
  320.                 x264_me_refine_qpel( h, &analysis.l0.me16x8[0] );  
  321.                 x264_me_refine_qpel( h, &analysis.l0.me16x8[1] );  
  322.                 i_cost = analysis.l0.me16x8[0].cost + analysis.l0.me16x8[1].cost;  
  323.             }  
  324.             else if( i_partition == D_8x16 )  
  325.             {  
  326.                 x264_me_refine_qpel( h, &analysis.l0.me8x16[0] );  
  327.                 x264_me_refine_qpel( h, &analysis.l0.me8x16[1] );  
  328.                 i_cost = analysis.l0.me8x16[0].cost + analysis.l0.me8x16[1].cost;  
  329.             }  
  330.             else if( i_partition == D_8x8 )  
  331.             {  
  332.                 i_cost = 0;  
  333.                 forint i8x8 = 0; i8x8 < 4; i8x8++ )  
  334.                 {  
  335.                     switch( h->mb.i_sub_partition[i8x8] )  
  336.                     {  
  337.                         case D_L0_8x8:  
  338.                             x264_me_refine_qpel( h, &analysis.l0.me8x8[i8x8] );  
  339.                             i_cost += analysis.l0.me8x8[i8x8].cost;  
  340.                             break;  
  341.                         case D_L0_8x4:  
  342.                             x264_me_refine_qpel( h, &analysis.l0.me8x4[i8x8][0] );  
  343.                             x264_me_refine_qpel( h, &analysis.l0.me8x4[i8x8][1] );  
  344.                             i_cost += analysis.l0.me8x4[i8x8][0].cost +  
  345.                                       analysis.l0.me8x4[i8x8][1].cost;  
  346.                             break;  
  347.                         case D_L0_4x8:  
  348.                             x264_me_refine_qpel( h, &analysis.l0.me4x8[i8x8][0] );  
  349.                             x264_me_refine_qpel( h, &analysis.l0.me4x8[i8x8][1] );  
  350.                             i_cost += analysis.l0.me4x8[i8x8][0].cost +  
  351.                                       analysis.l0.me4x8[i8x8][1].cost;  
  352.                             break;  
  353.   
  354.                         case D_L0_4x4:  
  355.                             x264_me_refine_qpel( h, &analysis.l0.me4x4[i8x8][0] );  
  356.                             x264_me_refine_qpel( h, &analysis.l0.me4x4[i8x8][1] );  
  357.                             x264_me_refine_qpel( h, &analysis.l0.me4x4[i8x8][2] );  
  358.                             x264_me_refine_qpel( h, &analysis.l0.me4x4[i8x8][3] );  
  359.                             i_cost += analysis.l0.me4x4[i8x8][0].cost +  
  360.                                       analysis.l0.me4x4[i8x8][1].cost +  
  361.                                       analysis.l0.me4x4[i8x8][2].cost +  
  362.                                       analysis.l0.me4x4[i8x8][3].cost;  
  363.                             break;  
  364.                         default:  
  365.                             x264_log( h, X264_LOG_ERROR, "internal error (!8x8 && !4x4)\n" );  
  366.                             break;  
  367.                     }  
  368.                 }  
  369.             }  
  370.   
  371.             if( h->mb.b_chroma_me )  
  372.             {  
  373.                 if( CHROMA444 )  
  374.                 {  
  375.                     x264_mb_analyse_intra( h, &analysis, i_cost );  
  376.                     x264_mb_analyse_intra_chroma( h, &analysis );  
  377.                 }  
  378.                 else  
  379.                 {  
  380.                     x264_mb_analyse_intra_chroma( h, &analysis );  
  381.                     x264_mb_analyse_intra( h, &analysis, i_cost - analysis.i_satd_chroma );  
  382.                 }  
  383.                 analysis.i_satd_i16x16 += analysis.i_satd_chroma;  
  384.                 analysis.i_satd_i8x8   += analysis.i_satd_chroma;  
  385.                 analysis.i_satd_i4x4   += analysis.i_satd_chroma;  
  386.             }  
  387.             else  
  388.                 x264_mb_analyse_intra( h, &analysis, i_cost );//P Slice中也允許有Intra宏塊,所以也要進行分析  
  389.   
  390.             i_satd_inter = i_cost;  
  391.             i_satd_intra = X264_MIN3( analysis.i_satd_i16x16,  
  392.                                       analysis.i_satd_i8x8,  
  393.                                       analysis.i_satd_i4x4 );  
  394.   
  395.             if( analysis.i_mbrd )  
  396.             {  
  397.                 x264_mb_analyse_p_rd( h, &analysis, X264_MIN(i_satd_inter, i_satd_intra) );  
  398.                 i_type = P_L0;  
  399.                 i_partition = D_16x16;  
  400.                 i_cost = analysis.l0.i_rd16x16;  
  401.                 COPY2_IF_LT( i_cost, analysis.l0.i_cost16x8, i_partition, D_16x8 );  
  402.                 COPY2_IF_LT( i_cost, analysis.l0.i_cost8x16, i_partition, D_8x16 );  
  403.                 COPY3_IF_LT( i_cost, analysis.l0.i_cost8x8, i_partition, D_8x8, i_type, P_8x8 );  
  404.                 h->mb.i_type = i_type;  
  405.                 h->mb.i_partition = i_partition;  
  406.                 if( i_cost < COST_MAX )  
  407.                     x264_mb_analyse_transform_rd( h, &analysis, &i_satd_inter, &i_cost );  
  408.                 x264_intra_rd( h, &analysis, i_satd_inter * 5/4 + 1 );  
  409.             }  
  410.             //獲取最小的代價  
  411.             COPY2_IF_LT( i_cost, analysis.i_satd_i16x16, i_type, I_16x16 );  
  412.             COPY2_IF_LT( i_cost, analysis.i_satd_i8x8, i_type, I_8x8 );  
  413.             COPY2_IF_LT( i_cost, analysis.i_satd_i4x4, i_type, I_4x4 );  
  414.             COPY2_IF_LT( i_cost, analysis.i_satd_pcm, i_type, I_PCM );  
  415.   
  416.             h->mb.i_type = i_type;  
  417.   
  418.             if( analysis.b_force_intra && !IS_INTRA(i_type) )  
  419.             {  
  420.                 /* Intra masking: copy fdec to fenc and re-encode the block as intra in order to make it appear as if 
  421.                  * it was an inter block. */  
  422.                 x264_analyse_update_cache( h, &analysis );  
  423.                 x264_macroblock_encode( h );  
  424.                 forint p = 0; p < (CHROMA444 ? 3 : 1); p++ )  
  425.                     h->mc.copy[PIXEL_16x16]( h->mb.pic.p_fenc[p], FENC_STRIDE, h->mb.pic.p_fdec[p], FDEC_STRIDE, 16 );  
  426.                 if( !CHROMA444 )  
  427.                 {  
  428.                     int height = 16 >> CHROMA_V_SHIFT;  
  429.                     h->mc.copy[PIXEL_8x8]  ( h->mb.pic.p_fenc[1], FENC_STRIDE, h->mb.pic.p_fdec[1], FDEC_STRIDE, height );  
  430.                     h->mc.copy[PIXEL_8x8]  ( h->mb.pic.p_fenc[2], FENC_STRIDE, h->mb.pic.p_fdec[2], FDEC_STRIDE, height );  
  431.                 }  
  432.                 x264_mb_analyse_init_qp( h, &analysis, X264_MAX( h->mb.i_qp - h->mb.ip_offset, h->param.rc.i_qp_min ) );  
  433.                 goto intra_analysis;  
  434.             }  
  435.   
  436.             if( analysis.i_mbrd >= 2 && h->mb.i_type != I_PCM )  
  437.             {  
  438.                 if( IS_INTRA( h->mb.i_type ) )  
  439.                 {  
  440.                     x264_intra_rd_refine( h, &analysis );  
  441.                 }  
  442.                 else if( i_partition == D_16x16 )  
  443.                 {  
  444.                     x264_macroblock_cache_ref( h, 0, 0, 4, 4, 0, analysis.l0.me16x16.i_ref );  
  445.                     analysis.l0.me16x16.cost = i_cost;  
  446.                     x264_me_refine_qpel_rd( h, &analysis.l0.me16x16, analysis.i_lambda2, 0, 0 );  
  447.                 }  
  448.                 else if( i_partition == D_16x8 )  
  449.                 {  
  450.                     h->mb.i_sub_partition[0] = h->mb.i_sub_partition[1] =  
  451.                     h->mb.i_sub_partition[2] = h->mb.i_sub_partition[3] = D_L0_8x8;  
  452.                     x264_macroblock_cache_ref( h, 0, 0, 4, 2, 0, analysis.l0.me16x8[0].i_ref );  
  453.                     x264_macroblock_cache_ref( h, 0, 2, 4, 2, 0, analysis.l0.me16x8[1].i_ref );  
  454.                     x264_me_refine_qpel_rd( h, &analysis.l0.me16x8[0], analysis.i_lambda2, 0, 0 );  
  455.                     x264_me_refine_qpel_rd( h, &analysis.l0.me16x8[1], analysis.i_lambda2, 8, 0 );  
  456.                 }  
  457.                 else if( i_partition == D_8x16 )  
  458.                 {  
  459.                     h->mb.i_sub_partition[0] = h->mb.i_sub_partition[1] =  
  460.                     h->mb.i_sub_partition[2] = h->mb.i_sub_partition[3] = D_L0_8x8;  
  461.                     x264_macroblock_cache_ref( h, 0, 0, 2, 4, 0, analysis.l0.me8x16[0].i_ref );  
  462.                     x264_macroblock_cache_ref( h, 2, 0, 2, 4, 0, analysis.l0.me8x16[1].i_ref );  
  463.                     x264_me_refine_qpel_rd( h, &analysis.l0.me8x16[0], analysis.i_lambda2, 0, 0 );  
  464.                     x264_me_refine_qpel_rd( h, &analysis.l0.me8x16[1], analysis.i_lambda2, 4, 0 );  
  465.                 }  
  466.                 else if( i_partition == D_8x8 )  
  467.                 {  
  468.                     x264_analyse_update_cache( h, &analysis );  
  469.                     forint i8x8 = 0; i8x8 < 4; i8x8++ )  
  470.                     {  
  471.                         if( h->mb.i_sub_partition[i8x8] == D_L0_8x8 )  
  472.                         {  
  473.                             x264_me_refine_qpel_rd( h, &analysis.l0.me8x8[i8x8], analysis.i_lambda2, i8x8*4, 0 );  
  474.                         }  
  475.                         else if( h->mb.i_sub_partition[i8x8] == D_L0_8x4 )  
  476.                         {  
  477.                             x264_me_refine_qpel_rd( h, &analysis.l0.me8x4[i8x8][0], analysis.i_lambda2, i8x8*4+0, 0 );  
  478.                             x264_me_refine_qpel_rd( h, &analysis.l0.me8x4[i8x8][1], analysis.i_lambda2, i8x8*4+2, 0 );  
  479.                         }  
  480.                         else if( h->mb.i_sub_partition[i8x8] == D_L0_4x8 )  
  481.                         {  
  482.                             x264_me_refine_qpel_rd( h, &analysis.l0.me4x8[i8x8][0], analysis.i_lambda2, i8x8*4+0, 0 );  
  483.                             x264_me_refine_qpel_rd( h, &analysis.l0.me4x8[i8x8][1], analysis.i_lambda2, i8x8*4+1, 0 );  
  484.                         }  
  485.                         else if( h->mb.i_sub_partition[i8x8] == D_L0_4x4 )  
  486.                         {  
  487.                             x264_me_refine_qpel_rd( h, &analysis.l0.me4x4[i8x8][0], analysis.i_lambda2, i8x8*4+0, 0 );  
  488.                             x264_me_refine_qpel_rd( h, &analysis.l0.me4x4[i8x8][1], analysis.i_lambda2, i8x8*4+1, 0 );  
  489.                             x264_me_refine_qpel_rd( h, &analysis.l0.me4x4[i8x8][2], analysis.i_lambda2, i8x8*4+2, 0 );  
  490.                             x264_me_refine_qpel_rd( h, &analysis.l0.me4x4[i8x8][3], analysis.i_lambda2, i8x8*4+3, 0 );  
  491.                         }  
  492.                     }  
  493.                 }  
  494.             }  
  495.         }  
  496.     }  
  497.     else if( h->sh.i_type == SLICE_TYPE_B )//B Slice的時候  
  498.     {  
  499.         int i_bskip_cost = COST_MAX;  
  500.         int b_skip = 0;  
  501.   
  502.         if( analysis.i_mbrd )  
  503.             x264_mb_init_fenc_cache( h, analysis.i_mbrd >= 2 );  
  504.   
  505.         h->mb.i_type = B_SKIP;  
  506.         if( h->mb.b_direct_auto_write )  
  507.         {  
  508.             /* direct=auto heuristic: prefer whichever mode allows more Skip macroblocks */  
  509.             forint i = 0; i < 2; i++ )  
  510.             {  
  511.                 int b_changed = 1;  
  512.                 h->sh.b_direct_spatial_mv_pred ^= 1;  
  513.                 analysis.b_direct_available = x264_mb_predict_mv_direct16x16( h, i && analysis.b_direct_available ? &b_changed : NULL );  
  514.                 if( analysis.b_direct_available )  
  515.                 {  
  516.                     if( b_changed )  
  517.                     {  
  518.                         x264_mb_mc( h );  
  519.                         b_skip = x264_macroblock_probe_bskip( h );  
  520.                     }  
  521.                     h->stat.frame.i_direct_score[ h->sh.b_direct_spatial_mv_pred ] += b_skip;  
  522.                 }  
  523.                 else  
  524.                     b_skip = 0;  
  525.             }  
  526.         }  
  527.         else  
  528.             analysis.b_direct_available = x264_mb_predict_mv_direct16x16( h, NULL );  
  529.   
  530.         analysis.b_try_skip = 0;  
  531.         if( analysis.b_direct_available )  
  532.         {  
  533.             if( !h->mb.b_direct_auto_write )  
  534.                 x264_mb_mc( h );  
  535.             /* If the current macroblock is off the frame, just skip it. */  
  536.             if( HAVE_INTERLACED && !MB_INTERLACED && h->mb.i_mb_y * 16 >= h->param.i_height )  
  537.                 b_skip = 1;  
  538.             else if( analysis.i_mbrd )  
  539.             {  
  540.                 i_bskip_cost = ssd_mb( h );  
  541.                 /* 6 = minimum cavlc cost of a non-skipped MB */  
  542.                 b_skip = h->mb.b_skip_mc = i_bskip_cost <= ((6 * analysis.i_lambda2 + 128) >> 8);  
  543.             }  
  544.             else if( !h->mb.b_direct_auto_write )  
  545.             {  
  546.                 /* Conditioning the probe on neighboring block types 
  547.                  * doesn't seem to help speed or quality. */  
  548.                 analysis.b_try_skip = x264_macroblock_probe_bskip( h );  
  549.                 if( h->param.analyse.i_subpel_refine < 3 )  
  550.                     b_skip = analysis.b_try_skip;  
  551.             }  
  552.             /* Set up MVs for future predictors */  
  553.             if( b_skip )  
  554.             {  
  555.                 forint i = 0; i < h->mb.pic.i_fref[0]; i++ )  
  556.                     M32( h->mb.mvr[0][i][h->mb.i_mb_xy] ) = 0;  
  557.                 forint i = 0; i < h->mb.pic.i_fref[1]; i++ )  
  558.                     M32( h->mb.mvr[1][i][h->mb.i_mb_xy] ) = 0;  
  559.             }  
  560.         }  
  561.   
  562.         if( !b_skip )  
  563.         {  
  564.             const unsigned int flags = h->param.analyse.inter;  
  565.             int i_type;  
  566.             int i_partition;  
  567.             int i_satd_inter;  
  568.             h->mb.b_skip_mc = 0;  
  569.             h->mb.i_type = B_DIRECT;  
  570.   
  571.             x264_mb_analyse_load_costs( h, &analysis );  
  572.   
  573.             /* select best inter mode */  
  574.             /* direct must be first */  
  575.             if( analysis.b_direct_available )  
  576.                 x264_mb_analyse_inter_direct( h, &analysis );  
  577.             /* 
  578.              * 16x16 幀間預測宏塊分析-B 
  579.              * 
  580.              * +--------+--------+ 
  581.              * |                 | 
  582.              * |                 | 
  583.              * |                 | 
  584.              * +        +        + 
  585.              * |                 | 
  586.              * |                 | 
  587.              * |                 | 
  588.              * +--------+--------+ 
  589.              * 
  590.              */  
  591.             x264_mb_analyse_inter_b16x16( h, &analysis );  
  592.   
  593.             if( h->mb.i_type == B_SKIP )  
  594.             {  
  595.                 forint i = 1; i < h->mb.pic.i_fref[0]; i++ )  
  596.                     M32( h->mb.mvr[0][i][h->mb.i_mb_xy] ) = 0;  
  597.                 forint i = 1; i < h->mb.pic.i_fref[1]; i++ )  
  598.                     M32( h->mb.mvr[1][i][h->mb.i_mb_xy] ) = 0;  
  599.                 return;  
  600.             }  
  601.   
  602.             i_type = B_L0_L0;  
  603.             i_partition = D_16x16;  
  604.             i_cost = analysis.l0.me16x16.cost;  
  605.             COPY2_IF_LT( i_cost, analysis.l1.me16x16.cost, i_type, B_L1_L1 );  
  606.             COPY2_IF_LT( i_cost, analysis.i_cost16x16bi, i_type, B_BI_BI );  
  607.             COPY2_IF_LT( i_cost, analysis.i_cost16x16direct, i_type, B_DIRECT );  
  608.   
  609.             if( analysis.i_mbrd && analysis.b_early_terminate && analysis.i_cost16x16direct <= i_cost * 33/32 )  
  610.             {  
  611.                 x264_mb_analyse_b_rd( h, &analysis, i_cost );  
  612.                 if( i_bskip_cost < analysis.i_rd16x16direct &&  
  613.                     i_bskip_cost < analysis.i_rd16x16bi &&  
  614.                     i_bskip_cost < analysis.l0.i_rd16x16 &&  
  615.                     i_bskip_cost < analysis.l1.i_rd16x16 )  
  616.                 {  
  617.                     h->mb.i_type = B_SKIP;  
  618.                     x264_analyse_update_cache( h, &analysis );  
  619.                     return;  
  620.                 }  
  621.             }  
  622.   
  623.             if( flags & X264_ANALYSE_BSUB16x16 )  
  624.             {  
  625.   
  626.                 /* 
  627.                  * 8x8 幀間預測宏塊分析-B 
  628.                  * +--------+ 
  629.                  * |        | 
  630.                  * |        | 
  631.                  * |        | 
  632.                  * +--------+ 
  633.                  * 
  634.                  */  
  635.   
  636.                 if( h->param.analyse.b_mixed_references )  
  637.                     x264_mb_analyse_inter_b8x8_mixed_ref( h, &analysis );  
  638.                 else  
  639.                     x264_mb_analyse_inter_b8x8( h, &analysis );  
  640.   
  641.                 COPY3_IF_LT( i_cost, analysis.i_cost8x8bi, i_type, B_8x8, i_partition, D_8x8 );  
  642.   
  643.                 /* Try to estimate the cost of b16x8/b8x16 based on the satd scores of the b8x8 modes */  
  644.                 int i_cost_est16x8bi_total = 0, i_cost_est8x16bi_total = 0;  
  645.                 int i_mb_type, i_partition16x8[2], i_partition8x16[2];  
  646.                 forint i = 0; i < 2; i++ )  
  647.                 {  
  648.                     int avg_l0_mv_ref_cost, avg_l1_mv_ref_cost;  
  649.                     int i_l0_satd, i_l1_satd, i_bi_satd, i_best_cost;  
  650.                     // 16x8  
  651.                     i_best_cost = COST_MAX;  
  652.                     i_l0_satd = analysis.i_satd8x8[0][i*2] + analysis.i_satd8x8[0][i*2+1];  
  653.                     i_l1_satd = analysis.i_satd8x8[1][i*2] + analysis.i_satd8x8[1][i*2+1];  
  654.                     i_bi_satd = analysis.i_satd8x8[2][i*2] + analysis.i_satd8x8[2][i*2+1];  
  655.                     avg_l0_mv_ref_cost = ( analysis.l0.me8x8[i*2].cost_mv + analysis.l0.me8x8[i*2].i_ref_cost  
  656.                                          + analysis.l0.me8x8[i*2+1].cost_mv + analysis.l0.me8x8[i*2+1].i_ref_cost + 1 ) >> 1;  
  657.                     avg_l1_mv_ref_cost = ( analysis.l1.me8x8[i*2].cost_mv + analysis.l1.me8x8[i*2].i_ref_cost  
  658.                                          + analysis.l1.me8x8[i*2+1].cost_mv + analysis.l1.me8x8[i*2+1].i_ref_cost + 1 ) >> 1;  
  659.                     COPY2_IF_LT( i_best_cost, i_l0_satd + avg_l0_mv_ref_cost, i_partition16x8[i], D_L0_8x8 );  
  660.                     COPY2_IF_LT( i_best_cost, i_l1_satd + avg_l1_mv_ref_cost, i_partition16x8[i], D_L1_8x8 );  
  661.                     COPY2_IF_LT( i_best_cost, i_bi_satd + avg_l0_mv_ref_cost + avg_l1_mv_ref_cost, i_partition16x8[i], D_BI_8x8 );  
  662.                     analysis.i_cost_est16x8[i] = i_best_cost;  
  663.   
  664.                     // 8x16  
  665.                     i_best_cost = COST_MAX;  
  666.                     i_l0_satd = analysis.i_satd8x8[0][i] + analysis.i_satd8x8[0][i+2];  
  667.                     i_l1_satd = analysis.i_satd8x8[1][i] + analysis.i_satd8x8[1][i+2];  
  668.                     i_bi_satd = analysis.i_satd8x8[2][i] + analysis.i_satd8x8[2][i+2];  
  669.                     avg_l0_mv_ref_cost = ( analysis.l0.me8x8[i].cost_mv + analysis.l0.me8x8[i].i_ref_cost  
  670.                                          + analysis.l0.me8x8[i+2].cost_mv + analysis.l0.me8x8[i+2].i_ref_cost + 1 ) >> 1;  
  671.                     avg_l1_mv_ref_cost = ( analysis.l1.me8x8[i].cost_mv + analysis.l1.me8x8[i].i_ref_cost  
  672.                                          + analysis.l1.me8x8[i+2].cost_mv + analysis.l1.me8x8[i+2].i_ref_cost + 1 ) >> 1;  
  673.                     COPY2_IF_LT( i_best_cost, i_l0_satd + avg_l0_mv_ref_cost, i_partition8x16[i], D_L0_8x8 );  
  674.                     COPY2_IF_LT( i_best_cost, i_l1_satd + avg_l1_mv_ref_cost, i_partition8x16[i], D_L1_8x8 );  
  675.                     COPY2_IF_LT( i_best_cost, i_bi_satd + avg_l0_mv_ref_cost + avg_l1_mv_ref_cost, i_partition8x16[i], D_BI_8x8 );  
  676.                     analysis.i_cost_est8x16[i] = i_best_cost;  
  677.                 }  
  678.                 i_mb_type = B_L0_L0 + (i_partition16x8[0]>>2) * 3 + (i_partition16x8[1]>>2);  
  679.                 analysis.i_cost_est16x8[1] += analysis.i_lambda * i_mb_b16x8_cost_table[i_mb_type];  
  680.                 i_cost_est16x8bi_total = analysis.i_cost_est16x8[0] + analysis.i_cost_est16x8[1];  
  681.                 i_mb_type = B_L0_L0 + (i_partition8x16[0]>>2) * 3 + (i_partition8x16[1]>>2);  
  682.                 analysis.i_cost_est8x16[1] += analysis.i_lambda * i_mb_b16x8_cost_table[i_mb_type];  
  683.                 i_cost_est8x16bi_total = analysis.i_cost_est8x16[0] + analysis.i_cost_est8x16[1];  
  684.   
  685.                 /* We can gain a little speed by checking the mode with the lowest estimated cost first */  
  686.                 int try_16x8_first = i_cost_est16x8bi_total < i_cost_est8x16bi_total;  
  687.                 if( try_16x8_first && (!analysis.b_early_terminate || i_cost_est16x8bi_total < i_cost) )  
  688.                 {  
  689.                     x264_mb_analyse_inter_b16x8( h, &analysis, i_cost );  
  690.                     COPY3_IF_LT( i_cost, analysis.i_cost16x8bi, i_type, analysis.i_mb_type16x8, i_partition, D_16x8 );  
  691.                 }  
  692.                 if( !analysis.b_early_terminate || i_cost_est8x16bi_total < i_cost )  
  693.                 {  
  694.                     x264_mb_analyse_inter_b8x16( h, &analysis, i_cost );  
  695.                     COPY3_IF_LT( i_cost, analysis.i_cost8x16bi, i_type, analysis.i_mb_type8x16, i_partition, D_8x16 );  
  696.                 }  
  697.                 if( !try_16x8_first && (!analysis.b_early_terminate || i_cost_est16x8bi_total < i_cost) )  
  698.                 {  
  699.                     x264_mb_analyse_inter_b16x8( h, &analysis, i_cost );  
  700.                     COPY3_IF_LT( i_cost, analysis.i_cost16x8bi, i_type, analysis.i_mb_type16x8, i_partition, D_16x8 );  
  701.                 }  
  702.             }  
  703.   
  704.             if( analysis.i_mbrd || !h->mb.i_subpel_refine )  
  705.             {  
  706.                 /* refine later */  
  707.             }  
  708.             /* refine qpel */  
  709.             else if( i_partition == D_16x16 )  
  710.             {  
  711.                 analysis.l0.me16x16.cost -= analysis.i_lambda * i_mb_b_cost_table[B_L0_L0];  
  712.                 analysis.l1.me16x16.cost -= analysis.i_lambda * i_mb_b_cost_table[B_L1_L1];  
  713.                 if( i_type == B_L0_L0 )  
  714.                 {  
  715.                     x264_me_refine_qpel( h, &analysis.l0.me16x16 );  
  716.                     i_cost = analysis.l0.me16x16.cost  
  717.                            + analysis.i_lambda * i_mb_b_cost_table[B_L0_L0];  
  718.                 }  
  719.                 else if( i_type == B_L1_L1 )  
  720.                 {  
  721.                     x264_me_refine_qpel( h, &analysis.l1.me16x16 );  
  722.                     i_cost = analysis.l1.me16x16.cost  
  723.                            + analysis.i_lambda * i_mb_b_cost_table[B_L1_L1];  
  724.                 }  
  725.                 else if( i_type == B_BI_BI )  
  726.                 {  
  727.                     x264_me_refine_qpel( h, &analysis.l0.bi16x16 );  
  728.                     x264_me_refine_qpel( h, &analysis.l1.bi16x16 );  
  729.                 }  
  730.             }  
  731.             else if( i_partition == D_16x8 )  
  732.             {  
  733.                 forint i = 0; i < 2; i++ )  
  734.                 {  
  735.                     if( analysis.i_mb_partition16x8[i] != D_L1_8x8 )  
  736.                         x264_me_refine_qpel( h, &analysis.l0.me16x8[i] );  
  737.                     if( analysis.i_mb_partition16x8[i] != D_L0_8x8 )  
  738.                         x264_me_refine_qpel( h, &analysis.l1.me16x8[i] );  
  739.                 }  
  740.             }  
  741.             else if( i_partition == D_8x16 )  
  742.             {  
  743.                 forint i = 0; i < 2; i++ )  
  744.                 {  
  745.                     if( analysis.i_mb_partition8x16[i] != D_L1_8x8 )  
  746.                         x264_me_refine_qpel( h, &analysis.l0.me8x16[i] );  
  747.                     if( analysis.i_mb_partition8x16[i] != D_L0_8x8 )  
  748.                         x264_me_refine_qpel( h, &analysis.l1.me8x16[i] );  
  749.                 }  
  750.             }  
  751.             else if( i_partition == D_8x8 )  
  752.             {  
  753.                 forint i = 0; i < 4; i++ )  
  754.                 {  
  755.                     x264_me_t *m;  
  756.                     int i_part_cost_old;  
  757.                     int i_type_cost;  
  758.                     int i_part_type = h->mb.i_sub_partition[i];  
  759.                     int b_bidir = (i_part_type == D_BI_8x8);  
  760.   
  761.                     if( i_part_type == D_DIRECT_8x8 )  
  762.                         continue;  
  763.                     if( x264_mb_partition_listX_table[0][i_part_type] )  
  764.                     {  
  765.                         m = &analysis.l0.me8x8[i];  
  766.                         i_part_cost_old = m->cost;  
  767.                         i_type_cost = analysis.i_lambda * i_sub_mb_b_cost_table[D_L0_8x8];  
  768.                         m->cost -= i_type_cost;  
  769.                         x264_me_refine_qpel( h, m );  
  770.                         if( !b_bidir )  
  771.                             analysis.i_cost8x8bi += m->cost + i_type_cost - i_part_cost_old;  
  772.                     }  
  773.                     if( x264_mb_partition_listX_table[1][i_part_type] )  
  774.                     {  
  775.                         m = &analysis.l1.me8x8[i];  
  776.                         i_part_cost_old = m->cost;  
  777.                         i_type_cost = analysis.i_lambda * i_sub_mb_b_cost_table[D_L1_8x8];  
  778.                         m->cost -= i_type_cost;  
  779.                         x264_me_refine_qpel( h, m );  
  780.                         if( !b_bidir )  
  781.                             analysis.i_cost8x8bi += m->cost + i_type_cost - i_part_cost_old;  
  782.                     }  
  783.                     /* TODO: update mvp? */  
  784.                 }  
  785.             }  
  786.   
  787.             i_satd_inter = i_cost;  
  788.   
  789.             if( analysis.i_mbrd )  
  790.             {  
  791.                 x264_mb_analyse_b_rd( h, &analysis, i_satd_inter );  
  792.                 i_type = B_SKIP;  
  793.                 i_cost = i_bskip_cost;  
  794.                 i_partition = D_16x16;  
  795.                 COPY2_IF_LT( i_cost, analysis.l0.i_rd16x16, i_type, B_L0_L0 );  
  796.                 COPY2_IF_LT( i_cost, analysis.l1.i_rd16x16, i_type, B_L1_L1 );  
  797.                 COPY2_IF_LT( i_cost, analysis.i_rd16x16bi, i_type, B_BI_BI );  
  798.                 COPY2_IF_LT( i_cost, analysis.i_rd16x16direct, i_type, B_DIRECT );  
  799.                 COPY3_IF_LT( i_cost, analysis.i_rd16x8bi, i_type, analysis.i_mb_type16x8, i_partition, D_16x8 );  
  800.                 COPY3_IF_LT( i_cost, analysis.i_rd8x16bi, i_type, analysis.i_mb_type8x16, i_partition, D_8x16 );  
  801.                 COPY3_IF_LT( i_cost, analysis.i_rd8x8bi, i_type, B_8x8, i_partition, D_8x8 );  
  802.   
  803.                 h->mb.i_type = i_type;  
  804.                 h->mb.i_partition = i_partition;  
  805.             }  
  806.   
  807.             if( h->mb.b_chroma_me )  
  808.             {  
  809.                 if( CHROMA444 )  
  810.                 {  
  811.                     x264_mb_analyse_intra( h, &analysis, i_satd_inter );  
  812.                     x264_mb_analyse_intra_chroma( h, &analysis );  
  813.                 }  
  814.                 else  
  815.                 {  
  816.                     x264_mb_analyse_intra_chroma( h, &analysis );  
  817.                     x264_mb_analyse_intra( h, &analysis, i_satd_inter - analysis.i_satd_chroma );  
  818.                 }  
  819.                 analysis.i_satd_i16x16 += analysis.i_satd_chroma;  
  820.                 analysis.i_satd_i8x8   += analysis.i_satd_chroma;  
  821.                 analysis.i_satd_i4x4   += analysis.i_satd_chroma;  
  822.             }  
  823.             else  
  824.                 x264_mb_analyse_intra( h, &analysis, i_satd_inter );  
  825.   
  826.             if( analysis.i_mbrd )  
  827.             {  
  828.                 x264_mb_analyse_transform_rd( h, &analysis, &i_satd_inter, &i_cost );  
  829.                 x264_intra_rd( h, &analysis, i_satd_inter * 17/16 + 1 );  
  830.             }  
  831.   
  832.             COPY2_IF_LT( i_cost, analysis.i_satd_i16x16, i_type, I_16x16 );  
  833.             COPY2_IF_LT( i_cost, analysis.i_satd_i8x8, i_type, I_8x8 );  
  834.             COPY2_IF_LT( i_cost, analysis.i_satd_i4x4, i_type, I_4x4 );  
  835.             COPY2_IF_LT( i_cost, analysis.i_satd_pcm, i_type, I_PCM );  
  836.   
  837.             h->mb.i_type = i_type;  
  838.             h->mb.i_partition = i_partition;  
  839.   
  840.             if( analysis.i_mbrd >= 2 && IS_INTRA( i_type ) && i_type != I_PCM )  
  841.                 x264_intra_rd_refine( h, &analysis );  
  842.             if( h->mb.i_subpel_refine >= 5 )  
  843.                 x264_refine_bidir( h, &analysis );  
  844.   
  845.             if( analysis.i_mbrd >= 2 && i_type > B_DIRECT && i_type < B_SKIP )  
  846.             {  
  847.                 int i_biweight;  
  848.                 x264_analyse_update_cache( h, &analysis );  
  849.   
  850.                 if( i_partition == D_16x16 )  
  851.                 {  
  852.                     if( i_type == B_L0_L0 )  
  853.                     {  
  854.                         analysis.l0.me16x16.cost = i_cost;  
  855.                         x264_me_refine_qpel_rd( h, &analysis.l0.me16x16, analysis.i_lambda2, 0, 0 );  
  856.                     }  
  857.                     else if( i_type == B_L1_L1 )  
  858.                     {  
  859.                         analysis.l1.me16x16.cost = i_cost;  
  860.                         x264_me_refine_qpel_rd( h, &analysis.l1.me16x16, analysis.i_lambda2, 0, 1 );  
  861.                     }  
  862.                     else if( i_type == B_BI_BI )  
  863.                     {  
  864.                         i_biweight = h->mb.bipred_weight[analysis.l0.bi16x16.i_ref][analysis.l1.bi16x16.i_ref];  
  865.                         x264_me_refine_bidir_rd( h, &analysis.l0.bi16x16, &analysis.l1.bi16x16, i_biweight, 0, analysis.i_lambda2 );  
  866.                     }  
  867.                 }  
  868.                 else if( i_partition == D_16x8 )  
  869.                 {  
  870.                     forint i = 0; i < 2; i++ )  
  871.                     {  
  872.                         h->mb.i_sub_partition[i*2] = h->mb.i_sub_partition[i*2+1] = analysis.i_mb_partition16x8[i];  
  873.                         if( analysis.i_mb_partition16x8[i] == D_L0_8x8 )  
  874.                             x264_me_refine_qpel_rd( h, &analysis.l0.me16x8[i], analysis.i_lambda2, i*8, 0 );  
  875.                         else if( analysis.i_mb_partition16x8[i] == D_L1_8x8 )  
  876.                             x264_me_refine_qpel_rd( h, &analysis.l1.me16x8[i], analysis.i_lambda2, i*8, 1 );  
  877.                         else if( analysis.i_mb_partition16x8[i] == D_BI_8x8 )  
  878.                         {  
  879.                             i_biweight = h->mb.bipred_weight[analysis.l0.me16x8[i].i_ref][analysis.l1.me16x8[i].i_ref];  
  880.                             x264_me_refine_bidir_rd( h, &analysis.l0.me16x8[i], &analysis.l1.me16x8[i], i_biweight, i*2, analysis.i_lambda2 );  
  881.                         }  
  882.                     }  
  883.                 }  
  884.                 else if( i_partition == D_8x16 )  
  885.                 {  
  886.                     forint i = 0; i < 2; i++ )  
  887.                     {  
  888.                         h->mb.i_sub_partition[i] = h->mb.i_sub_partition[i+2] = analysis.i_mb_partition8x16[i];  
  889.                         if( analysis.i_mb_partition8x16[i] == D_L0_8x8 )  
  890.                             x264_me_refine_qpel_rd( h, &analysis.l0.me8x16[i], analysis.i_lambda2, i*4, 0 );  
  891.                         else if( analysis.i_mb_partition8x16[i] == D_L1_8x8 )  
  892.                             x264_me_refine_qpel_rd( h, &analysis.l1.me8x16[i], analysis.i_lambda2, i*4, 1 );  
  893.                         else if( analysis.i_mb_partition8x16[i] == D_BI_8x8 )  
  894.                         {  
  895.                             i_biweight = h->mb.bipred_weight[analysis.l0.me8x16[i].i_ref][analysis.l1.me8x16[i].i_ref];  
  896.                             x264_me_refine_bidir_rd( h, &analysis.l0.me8x16[i], &analysis.l1.me8x16[i], i_biweight, i, analysis.i_lambda2 );  
  897.                         }  
  898.                     }  
  899.                 }  
  900.                 else if( i_partition == D_8x8 )  
  901.                 {  
  902.                     forint i = 0; i < 4; i++ )  
  903.                     {  
  904.                         if( h->mb.i_sub_partition[i] == D_L0_8x8 )  
  905.                             x264_me_refine_qpel_rd( h, &analysis.l0.me8x8[i], analysis.i_lambda2, i*4, 0 );  
  906.                         else if( h->mb.i_sub_partition[i] == D_L1_8x8 )  
  907.                             x264_me_refine_qpel_rd( h, &analysis.l1.me8x8[i], analysis.i_lambda2, i*4, 1 );  
  908.                         else if( h->mb.i_sub_partition[i] == D_BI_8x8 )  
  909.                         {  
  910.                             i_biweight = h->mb.bipred_weight[analysis.l0.me8x8[i].i_ref][analysis.l1.me8x8[i].i_ref];  
  911.                             x264_me_refine_bidir_rd( h, &analysis.l0.me8x8[i], &analysis.l1.me8x8[i], i_biweight, i, analysis.i_lambda2 );  
  912.                         }  
  913.                     }  
  914.                 }  
  915.             }  
  916.         }  
  917.     }  
  918.   
  919.     x264_analyse_update_cache( h, &analysis );  
  920.   
  921.     /* In rare cases we can end up qpel-RDing our way back to a larger partition size 
  922.      * without realizing it.  Check for this and account for it if necessary. */  
  923.     if( analysis.i_mbrd >= 2 )  
  924.     {  
  925.         /* Don't bother with bipred or 8x8-and-below, the odds are incredibly low. */  
  926.         static const uint8_t check_mv_lists[X264_MBTYPE_MAX] = {[P_L0]=1, [B_L0_L0]=1, [B_L1_L1]=2};  
  927.         int list = check_mv_lists[h->mb.i_type] - 1;  
  928.         if( list >= 0 && h->mb.i_partition != D_16x16 &&  
  929.             M32( &h->mb.cache.mv[list][x264_scan8[0]] ) == M32( &h->mb.cache.mv[list][x264_scan8[12]] ) &&  
  930.             h->mb.cache.ref[list][x264_scan8[0]] == h->mb.cache.ref[list][x264_scan8[12]] )  
  931.                 h->mb.i_partition = D_16x16;  
  932.     }  
  933.   
  934.     if( !analysis.i_mbrd )  
  935.         x264_mb_analyse_transform( h );  
  936.   
  937.     if( analysis.i_mbrd == 3 && !IS_SKIP(h->mb.i_type) )  
  938.         x264_mb_analyse_qp_rd( h, &analysis );  
  939.   
  940.     h->mb.b_trellis = h->param.analyse.i_trellis;  
  941.     h->mb.b_noise_reduction = h->mb.b_noise_reduction || (!!h->param.analyse.i_noise_reduction && !IS_INTRA( h->mb.i_type ));  
  942.   
  943.     if( !IS_SKIP(h->mb.i_type) && h->mb.i_psy_trellis && h->param.analyse.i_trellis == 1 )  
  944.         x264_psy_trellis_init( h, 0 );  
  945.     if( h->mb.b_trellis == 1 || h->mb.b_noise_reduction )  
  946.         h->mb.i_skip_intra = 0;  
  947. }  

儘管x264_macroblock_analyse()的源代碼比較長,但是它的邏輯比較清晰,如下所示:
(1)如果當前是I Slice,調用x264_mb_analyse_intra()進行Intra宏塊的幀內預測模式分析。
(2)如果當前是P Slice,則進行下面流程的分析:
a)調用x264_macroblock_probe_pskip()分析是否爲Skip宏塊,如果是的話則不再進行下面分析。
b)調用x264_mb_analyse_inter_p16x16()分析P16x16幀間預測的代價。
c)調用x264_mb_analyse_inter_p8x8()分析P8x8幀間預測的代價。
d)如果P8x8代價值小於P16x16,則依次對4個8x8的子宏塊分割進行判斷:
i.調用x264_mb_analyse_inter_p4x4()分析P4x4幀間預測的代價。
ii.如果P4x4代價值小於P8x8,則調用 x264_mb_analyse_inter_p8x4()和x264_mb_analyse_inter_p4x8()分析P8x4和P4x8幀間預測的代價。
e)如果P8x8代價值小於P16x16,調用x264_mb_analyse_inter_p16x8()和x264_mb_analyse_inter_p8x16()分析P16x8和P8x16幀間預測的代價。
f)此外還要調用x264_mb_analyse_intra(),檢查當前宏塊作爲Intra宏塊編碼的代價是否小於作爲P宏塊編碼的代價(P Slice中也允許有Intra宏塊)。
(3)如果當前是B Slice,則進行和P Slice類似的處理。

本文記錄這一流程中Intra宏塊的幀內預測模式分析函數x264_mb_analyse_intra()。



x264_mb_analyse_intra()

x264_mb_analyse_intra()用於對Intra宏塊進行幀內預測模式的分析。該函數的定義位於encoder\analyse.c,如下所示。
[cpp]  view plain  copy
  1. //幀內預測分析-從16x16的SAD,4個8x8的SAD和,16個4x4SAD中選出最優方式  
  2. static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_inter )  
  3. {  
  4.     const unsigned int flags = h->sh.i_type == SLICE_TYPE_I ? h->param.analyse.intra : h->param.analyse.inter;  
  5.     //計算  
  6.     //p_fenc是編碼幀  
  7.     pixel *p_src = h->mb.pic.p_fenc[0];  
  8.     //p_fdec是重建幀  
  9.     pixel *p_dst = h->mb.pic.p_fdec[0];  
  10.   
  11.     static const int8_t intra_analysis_shortcut[2][2][2][5] =  
  12.     {  
  13.         {{{I_PRED_4x4_HU, -1, -1, -1, -1},  
  14.           {I_PRED_4x4_DDL, I_PRED_4x4_VL, -1, -1, -1}},  
  15.          {{I_PRED_4x4_DDR, I_PRED_4x4_HD, I_PRED_4x4_HU, -1, -1},  
  16.           {I_PRED_4x4_DDL, I_PRED_4x4_DDR, I_PRED_4x4_VR, I_PRED_4x4_VL, -1}}},  
  17.         {{{I_PRED_4x4_HU, -1, -1, -1, -1},  
  18.           {-1, -1, -1, -1, -1}},  
  19.          {{I_PRED_4x4_DDR, I_PRED_4x4_HD, I_PRED_4x4_HU, -1, -1},  
  20.           {I_PRED_4x4_DDR, I_PRED_4x4_VR, -1, -1, -1}}},  
  21.     };  
  22.   
  23.     int idx;  
  24.     int lambda = a->i_lambda;  
  25.   
  26.     /*---------------- Try all mode and calculate their score ---------------*/  
  27.     /* Disabled i16x16 for AVC-Intra compat */  
  28.     //幀內16x16  
  29.     if( !h->param.i_avcintra_class )  
  30.     {  
  31.         //獲得可用的幀內預測模式-針對幀內16x16  
  32.         /* 
  33.          * 16x16塊 
  34.          * 
  35.          * +--------+--------+ 
  36.          * |                 | 
  37.          * |                 | 
  38.          * |                 | 
  39.          * +        +        + 
  40.          * |                 | 
  41.          * |                 | 
  42.          * |                 | 
  43.          * +--------+--------+ 
  44.          * 
  45.          */  
  46.         //左側是否有可用數據?上方是否有可用數據?  
  47.         const int8_t *predict_mode = predict_16x16_mode_available( h->mb.i_neighbour_intra );  
  48.   
  49.         /* Not heavily tuned */  
  50.         static const uint8_t i16x16_thresh_lut[11] = { 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4 };  
  51.         int i16x16_thresh = a->b_fast_intra ? (i16x16_thresh_lut[h->mb.i_subpel_refine]*i_satd_inter)>>1 : COST_MAX;  
  52.   
  53.         if( !h->mb.b_lossless && predict_mode[3] >= 0 )  
  54.         {  
  55.             h->pixf.intra_mbcmp_x3_16x16( p_src, p_dst, a->i_satd_i16x16_dir );  
  56.             a->i_satd_i16x16_dir[0] += lambda * bs_size_ue(0);  
  57.             a->i_satd_i16x16_dir[1] += lambda * bs_size_ue(1);  
  58.             a->i_satd_i16x16_dir[2] += lambda * bs_size_ue(2);  
  59.             COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[0], a->i_predict16x16, 0 );  
  60.             COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[1], a->i_predict16x16, 1 );  
  61.             COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[2], a->i_predict16x16, 2 );  
  62.   
  63.             /* Plane is expensive, so don't check it unless one of the previous modes was useful. */  
  64.             if( a->i_satd_i16x16 <= i16x16_thresh )  
  65.             {  
  66.                 h->predict_16x16[I_PRED_16x16_P]( p_dst );  
  67.                 a->i_satd_i16x16_dir[I_PRED_16x16_P] = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE );  
  68.                 a->i_satd_i16x16_dir[I_PRED_16x16_P] += lambda * bs_size_ue(3);  
  69.                 COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[I_PRED_16x16_P], a->i_predict16x16, 3 );  
  70.             }  
  71.         }  
  72.         else  
  73.         {  
  74.             //遍歷所有的可用的Intra16x16幀內預測模式  
  75.             //最多4種  
  76.             for( ; *predict_mode >= 0; predict_mode++ )  
  77.             {  
  78.                 int i_satd;  
  79.                 int i_mode = *predict_mode;  
  80.   
  81.                 //幀內預測彙編函數:根據左邊和上邊的像素計算出預測值  
  82.                 /* 
  83.                  * 幀內預測舉例 
  84.                  * Vertical預測方式 
  85.                  *    |X1 X2 ... X16 
  86.                  *  --+--------------- 
  87.                  *    |X1 X2 ... X16 
  88.                  *    |X1 X2 ... X16 
  89.                  *    |.. .. ... X16 
  90.                  *    |X1 X2 ... X16 
  91.                  * 
  92.                  * Horizontal預測方式 
  93.                  *    | 
  94.                  *  --+--------------- 
  95.                  *  X1| X1  X1 ...  X1 
  96.                  *  X2| X2  X2 ...  X2 
  97.                  *  ..| ..  .. ...  .. 
  98.                  * X16|X16 X16 ... X16 
  99.                  * 
  100.                  * DC預測方式 
  101.                  *    |X1 X2 ... X16 
  102.                  *  --+--------------- 
  103.                  * X17| 
  104.                  * X18|     Y 
  105.                  *  ..| 
  106.                  * X32| 
  107.                  * 
  108.                  * Y=(X1+X2+X3+X4+...+X31+X32)/32 
  109.                  * 
  110.                  */  
  111.                 if( h->mb.b_lossless )  
  112.                     x264_predict_lossless_16x16( h, 0, i_mode );  
  113.                 else  
  114.                     h->predict_16x16[i_mode]( p_dst );//計算結果存儲在p_dst重建幀中  
  115.   
  116.                 //計算SAD或者是SATD(SATD(transformed)是經過Hadamard變換之後的SAD)  
  117.                 //即編碼代價  
  118.                 //數據位於p_dst和p_src  
  119.                 i_satd = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE ) +  
  120.                          lambda * bs_size_ue( x264_mb_pred_mode16x16_fix[i_mode] );  
  121.   
  122.                 //COPY2_IF_LT()函數的意思是「copy if little」。即如果值更小(代價更小),就拷貝。  
  123.                 //宏定義展開後如下所示  
  124.                 //if((i_satd)<(a->i_satd_i16x16))  
  125.                 //{  
  126.                 //    (a->i_satd_i16x16)=(i_satd);  
  127.                 //    (a->i_predict16x16)=(i_mode);  
  128.                 //}  
  129.                 COPY2_IF_LT( a->i_satd_i16x16, i_satd, a->i_predict16x16, i_mode );  
  130.                 //每種模式的代價都會存儲  
  131.                 a->i_satd_i16x16_dir[i_mode] = i_satd;  
  132.             }  
  133.         }  
  134.   
  135.         if( h->sh.i_type == SLICE_TYPE_B )  
  136.             /* cavlc mb type prefix */  
  137.             a->i_satd_i16x16 += lambda * i_mb_b_cost_table[I_16x16];  
  138.   
  139.         if( a->i_satd_i16x16 > i16x16_thresh )  
  140.             return;  
  141.     }  
  142.   
  143.     uint16_t *cost_i4x4_mode = (uint16_t*)ALIGN((intptr_t)x264_cost_i4x4_mode,64) + a->i_qp*32 + 8;  
  144.     /* 8x8 prediction selection */  
  145.     //幀內8x8(沒研究過)  
  146.     if( flags & X264_ANALYSE_I8x8 )  
  147.     {  
  148.         ALIGNED_ARRAY_32( pixel, edge,[36] );  
  149.         x264_pixel_cmp_t sa8d = (h->pixf.mbcmp[0] == h->pixf.satd[0]) ? h->pixf.sa8d[PIXEL_8x8] : h->pixf.mbcmp[PIXEL_8x8];  
  150.         int i_satd_thresh = a->i_mbrd ? COST_MAX : X264_MIN( i_satd_inter, a->i_satd_i16x16 );  
  151.   
  152.         // FIXME some bias like in i4x4?  
  153.         int i_cost = lambda * 4; /* base predmode costs */  
  154.         h->mb.i_cbp_luma = 0;  
  155.   
  156.         if( h->sh.i_type == SLICE_TYPE_B )  
  157.             i_cost += lambda * i_mb_b_cost_table[I_8x8];  
  158.   
  159.         for( idx = 0;; idx++ )  
  160.         {  
  161.             int x = idx&1;  
  162.             int y = idx>>1;  
  163.             pixel *p_src_by = p_src + 8*x + 8*y*FENC_STRIDE;  
  164.             pixel *p_dst_by = p_dst + 8*x + 8*y*FDEC_STRIDE;  
  165.             int i_best = COST_MAX;  
  166.             int i_pred_mode = x264_mb_predict_intra4x4_mode( h, 4*idx );  
  167.   
  168.             const int8_t *predict_mode = predict_8x8_mode_available( a->b_avoid_topright, h->mb.i_neighbour8[idx], idx );  
  169.             h->predict_8x8_filter( p_dst_by, edge, h->mb.i_neighbour8[idx], ALL_NEIGHBORS );  
  170.   
  171.             if( h->pixf.intra_mbcmp_x9_8x8 && predict_mode[8] >= 0 )  
  172.             {  
  173.                 /* No shortcuts here. The SSSE3 implementation of intra_mbcmp_x9 is fast enough. */  
  174.                 i_best = h->pixf.intra_mbcmp_x9_8x8( p_src_by, p_dst_by, edge, cost_i4x4_mode-i_pred_mode, a->i_satd_i8x8_dir[idx] );  
  175.                 i_cost += i_best & 0xffff;  
  176.                 i_best >>= 16;  
  177.                 a->i_predict8x8[idx] = i_best;  
  178.                 if( idx == 3 || i_cost > i_satd_thresh )  
  179.                     break;  
  180.                 x264_macroblock_cache_intra8x8_pred( h, 2*x, 2*y, i_best );  
  181.             }  
  182.             else  
  183.             {  
  184.                 if( !h->mb.b_lossless && predict_mode[5] >= 0 )  
  185.                 {  
  186.                     ALIGNED_ARRAY_16( int32_t, satd,[9] );  
  187.                     h->pixf.intra_mbcmp_x3_8x8( p_src_by, edge, satd );  
  188.                     int favor_vertical = satd[I_PRED_4x4_H] > satd[I_PRED_4x4_V];  
  189.                     satd[i_pred_mode] -= 3 * lambda;  
  190.                     forint i = 2; i >= 0; i-- )  
  191.                     {  
  192.                         int cost = satd[i];  
  193.                         a->i_satd_i8x8_dir[idx][i] = cost + 4 * lambda;  
  194.                         COPY2_IF_LT( i_best, cost, a->i_predict8x8[idx], i );  
  195.                     }  
  196.   
  197.                     /* Take analysis shortcuts: don't analyse modes that are too 
  198.                      * far away direction-wise from the favored mode. */  
  199.                     if( a->i_mbrd < 1 + a->b_fast_intra )  
  200.                         predict_mode = intra_analysis_shortcut[a->b_avoid_topright][predict_mode[8] >= 0][favor_vertical];  
  201.                     else  
  202.                         predict_mode += 3;  
  203.                 }  
  204.   
  205.                 for( ; *predict_mode >= 0 && (i_best >= 0 || a->i_mbrd >= 2); predict_mode++ )  
  206.                 {  
  207.                     int i_satd;  
  208.                     int i_mode = *predict_mode;  
  209.   
  210.                     if( h->mb.b_lossless )  
  211.                         x264_predict_lossless_8x8( h, p_dst_by, 0, idx, i_mode, edge );  
  212.                     else  
  213.                         h->predict_8x8[i_mode]( p_dst_by, edge );  
  214.   
  215.                     i_satd = sa8d( p_dst_by, FDEC_STRIDE, p_src_by, FENC_STRIDE );  
  216.                     if( i_pred_mode == x264_mb_pred_mode4x4_fix(i_mode) )  
  217.                         i_satd -= 3 * lambda;  
  218.   
  219.                     COPY2_IF_LT( i_best, i_satd, a->i_predict8x8[idx], i_mode );  
  220.                     a->i_satd_i8x8_dir[idx][i_mode] = i_satd + 4 * lambda;  
  221.                 }  
  222.                 i_cost += i_best + 3*lambda;  
  223.   
  224.                 if( idx == 3 || i_cost > i_satd_thresh )  
  225.                     break;  
  226.                 if( h->mb.b_lossless )  
  227.                     x264_predict_lossless_8x8( h, p_dst_by, 0, idx, a->i_predict8x8[idx], edge );  
  228.                 else  
  229.                     h->predict_8x8[a->i_predict8x8[idx]]( p_dst_by, edge );  
  230.                 x264_macroblock_cache_intra8x8_pred( h, 2*x, 2*y, a->i_predict8x8[idx] );  
  231.             }  
  232.             /* we need to encode this block now (for next ones) */  
  233.             x264_mb_encode_i8x8( h, 0, idx, a->i_qp, a->i_predict8x8[idx], edge, 0 );  
  234.         }  
  235.   
  236.         if( idx == 3 )  
  237.         {  
  238.             a->i_satd_i8x8 = i_cost;  
  239.             if( h->mb.i_skip_intra )  
  240.             {  
  241.                 h->mc.copy[PIXEL_16x16]( h->mb.pic.i8x8_fdec_buf, 16, p_dst, FDEC_STRIDE, 16 );  
  242.                 h->mb.pic.i8x8_nnz_buf[0] = M32( &h->mb.cache.non_zero_count[x264_scan8[ 0]] );  
  243.                 h->mb.pic.i8x8_nnz_buf[1] = M32( &h->mb.cache.non_zero_count[x264_scan8[ 2]] );  
  244.                 h->mb.pic.i8x8_nnz_buf[2] = M32( &h->mb.cache.non_zero_count[x264_scan8[ 8]] );  
  245.                 h->mb.pic.i8x8_nnz_buf[3] = M32( &h->mb.cache.non_zero_count[x264_scan8[10]] );  
  246.                 h->mb.pic.i8x8_cbp = h->mb.i_cbp_luma;  
  247.                 if( h->mb.i_skip_intra == 2 )  
  248.                     h->mc.memcpy_aligned( h->mb.pic.i8x8_dct_buf, h->dct.luma8x8, sizeof(h->mb.pic.i8x8_dct_buf) );  
  249.             }  
  250.         }  
  251.         else  
  252.         {  
  253.             static const uint16_t cost_div_fix8[3] = {1024,512,341};  
  254.             a->i_satd_i8x8 = COST_MAX;  
  255.             i_cost = (i_cost * cost_div_fix8[idx]) >> 8;  
  256.         }  
  257.         /* Not heavily tuned */  
  258.         static const uint8_t i8x8_thresh[11] = { 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 6 };  
  259.         if( a->b_early_terminate && X264_MIN(i_cost, a->i_satd_i16x16) > (i_satd_inter*i8x8_thresh[h->mb.i_subpel_refine])>>2 )  
  260.             return;  
  261.     }  
  262.   
  263.     /* 4x4 prediction selection */  
  264.     //幀內4x4  
  265.     if( flags & X264_ANALYSE_I4x4 )  
  266.     {  
  267.         /* 
  268.          * 16x16 宏塊被劃分爲16個4x4子塊 
  269.          * 
  270.          * +----+----+----+----+ 
  271.          * |    |    |    |    | 
  272.          * +----+----+----+----+ 
  273.          * |    |    |    |    | 
  274.          * +----+----+----+----+ 
  275.          * |    |    |    |    | 
  276.          * +----+----+----+----+ 
  277.          * |    |    |    |    | 
  278.          * +----+----+----+----+ 
  279.          * 
  280.          */  
  281.         int i_cost = lambda * (24+16); /* 24from JVT (SATD0), 16 from base predmode costs */  
  282.         int i_satd_thresh = a->b_early_terminate ? X264_MIN3( i_satd_inter, a->i_satd_i16x16, a->i_satd_i8x8 ) : COST_MAX;  
  283.         h->mb.i_cbp_luma = 0;  
  284.   
  285.         if( a->b_early_terminate && a->i_mbrd )  
  286.             i_satd_thresh = i_satd_thresh * (10-a->b_fast_intra)/8;  
  287.   
  288.         if( h->sh.i_type == SLICE_TYPE_B )  
  289.             i_cost += lambda * i_mb_b_cost_table[I_4x4];  
  290.         //循環所有的4x4塊  
  291.         for( idx = 0;; idx++ )  
  292.         {  
  293.             //編碼幀中的像素  
  294.             //block_idx_xy_fenc[]記錄了4x4小塊在p_fenc中的偏移地址  
  295.             pixel *p_src_by = p_src + block_idx_xy_fenc[idx];  
  296.             //重建幀中的像素  
  297.             //block_idx_xy_fdec[]記錄了4x4小塊在p_fdec中的偏移地址  
  298.             pixel *p_dst_by = p_dst + block_idx_xy_fdec[idx];  
  299.   
  300.             int i_best = COST_MAX;  
  301.             int i_pred_mode = x264_mb_predict_intra4x4_mode( h, idx );  
  302.             //獲得可用的幀內預測模式-針對幀內4x4  
  303.             //左側是否有可用數據?上方是否有可用數據?  
  304.             const int8_t *predict_mode = predict_4x4_mode_available( a->b_avoid_topright, h->mb.i_neighbour4[idx], idx );  
  305.   
  306.             if( (h->mb.i_neighbour4[idx] & (MB_TOPRIGHT|MB_TOP)) == MB_TOP )  
  307.                 /* emulate missing topright samples */  
  308.                 MPIXEL_X4( &p_dst_by[4 - FDEC_STRIDE] ) = PIXEL_SPLAT_X4( p_dst_by[3 - FDEC_STRIDE] );  
  309.   
  310.             if( h->pixf.intra_mbcmp_x9_4x4 && predict_mode[8] >= 0 )  
  311.             {  
  312.                 /* No shortcuts here. The SSSE3 implementation of intra_mbcmp_x9 is fast enough. */  
  313.                 i_best = h->pixf.intra_mbcmp_x9_4x4( p_src_by, p_dst_by, cost_i4x4_mode-i_pred_mode );  
  314.                 i_cost += i_best & 0xffff;  
  315.                 i_best >>= 16;  
  316.                 a->i_predict4x4[idx] = i_best;  
  317.                 if( i_cost > i_satd_thresh || idx == 15 )  
  318.                     break;  
  319.                 h->mb.cache.intra4x4_pred_mode[x264_scan8[idx]] = i_best;  
  320.             }  
  321.             else  
  322.             {  
  323.                 if( !h->mb.b_lossless && predict_mode[5] >= 0 )  
  324.                 {  
  325.                     ALIGNED_ARRAY_16( int32_t, satd,[9] );  
  326.   
  327.                     h->pixf.intra_mbcmp_x3_4x4( p_src_by, p_dst_by, satd );  
  328.                     int favor_vertical = satd[I_PRED_4x4_H] > satd[I_PRED_4x4_V];  
  329.                     satd[i_pred_mode] -= 3 * lambda;  
  330.                     i_best = satd[I_PRED_4x4_DC]; a->i_predict4x4[idx] = I_PRED_4x4_DC;  
  331.                     COPY2_IF_LT( i_best, satd[I_PRED_4x4_H], a->i_predict4x4[idx], I_PRED_4x4_H );  
  332.                     COPY2_IF_LT( i_best, satd[I_PRED_4x4_V], a->i_predict4x4[idx], I_PRED_4x4_V );  
  333.   
  334.                     /* Take analysis shortcuts: don't analyse modes that are too 
  335.                      * far away direction-wise from the favored mode. */  
  336.                     if( a->i_mbrd < 1 + a->b_fast_intra )  
  337.                         predict_mode = intra_analysis_shortcut[a->b_avoid_topright][predict_mode[8] >= 0][favor_vertical];  
  338.                     else  
  339.                         predict_mode += 3;  
  340.                 }  
  341.   
  342.                 if( i_best > 0 )  
  343.                 {  
  344.                     //遍歷所有Intra4x4幀內模式,最多9種  
  345.                     for( ; *predict_mode >= 0; predict_mode++ )  
  346.                     {  
  347.                         int i_satd;  
  348.                         int i_mode = *predict_mode;  
  349.                         /* 
  350.                          * 4x4幀內預測舉例 
  351.                          * 
  352.                          * Vertical預測方式 
  353.                          *   |X1 X2 X3 X4 
  354.                          * --+----------- 
  355.                          *   |X1 X2 X3 X4 
  356.                          *   |X1 X2 X3 X4 
  357.                          *   |X1 X2 X3 X4 
  358.                          *   |X1 X2 X3 X4 
  359.                          * 
  360.                          * Horizontal預測方式 
  361.                          *   | 
  362.                          * --+----------- 
  363.                          * X5|X5 X5 X5 X5 
  364.                          * X6|X6 X6 X6 X6 
  365.                          * X7|X7 X7 X7 X7 
  366.                          * X8|X8 X8 X8 X8 
  367.                          * 
  368.                          * DC預測方式 
  369.                          *   |X1 X2 X3 X4 
  370.                          * --+----------- 
  371.                          * X5| 
  372.                          * X6|     Y 
  373.                          * X7| 
  374.                          * X8| 
  375.                          * 
  376.                          * Y=(X1+X2+X3+X4+X5+X6+X7+X8)/8 
  377.                          * 
  378.                          */  
  379.                         if( h->mb.b_lossless )  
  380.                             x264_predict_lossless_4x4( h, p_dst_by, 0, idx, i_mode );  
  381.                         else  
  382.                             h->predict_4x4[i_mode]( p_dst_by );//幀內預測彙編函數-存儲在重建幀中  
  383.   
  384.                         //計算SAD或者是SATD(SATD(Transformed)是經過Hadamard變換之後的SAD)  
  385.                         //即編碼代價  
  386.                         //p_src_by編碼幀,p_dst_by重建幀  
  387.                         i_satd = h->pixf.mbcmp[PIXEL_4x4]( p_dst_by, FDEC_STRIDE, p_src_by, FENC_STRIDE );  
  388.                         if( i_pred_mode == x264_mb_pred_mode4x4_fix(i_mode) )  
  389.                         {  
  390.                             i_satd -= lambda * 3;  
  391.                             if( i_satd <= 0 )  
  392.                             {  
  393.                                 i_best = i_satd;  
  394.                                 a->i_predict4x4[idx] = i_mode;  
  395.                                 break;  
  396.                             }  
  397.                         }  
  398.                         //COPY2_IF_LT()函數的意思是「copy if little」。即如果值更小(代價更小),就拷貝。  
  399.                         //宏定義展開後如下所示  
  400.                         //if((i_satd)<(i_best))  
  401.                         //{  
  402.                         //    (i_best)=(i_satd);  
  403.                         //    (a->i_predict4x4[idx])=(i_mode);  
  404.                         //}  
  405.   
  406.                         //看看代價是否更小  
  407.                         //i_best中存儲了最小的代價值  
  408.                         //i_predict4x4[idx]中存儲了代價最小的預測模式(idx爲4x4小塊的序號)  
  409.                         COPY2_IF_LT( i_best, i_satd, a->i_predict4x4[idx], i_mode );  
  410.                     }  
  411.                 }  
  412.                 //累加各個4x4塊的代價(累加每個塊的最小代價)  
  413.                 i_cost += i_best + 3 * lambda;  
  414.                 if( i_cost > i_satd_thresh || idx == 15 )  
  415.                     break;  
  416.                 if( h->mb.b_lossless )  
  417.                     x264_predict_lossless_4x4( h, p_dst_by, 0, idx, a->i_predict4x4[idx] );  
  418.                 else  
  419.                     h->predict_4x4[a->i_predict4x4[idx]]( p_dst_by );  
  420.   
  421.                 /* 
  422.                  * 將mode填充至intra4x4_pred_mode_cache 
  423.                  * 
  424.                  * 用簡單圖形表示intra4x4_pred_mode_cache如下。數字代表填充順序(一共填充16次) 
  425.                  *   | 
  426.                  * --+------------------- 
  427.                  *   | 0 0 0 0  0  0  0  0 
  428.                  *   | 0 0 0 0  1  2  5  6 
  429.                  *   | 0 0 0 0  3  4  7  8 
  430.                  *   | 0 0 0 0  9 10 13 14 
  431.                  *   | 0 0 0 0 11 12 15 16 
  432.                  * 
  433.                  */  
  434.                 h->mb.cache.intra4x4_pred_mode[x264_scan8[idx]] = a->i_predict4x4[idx];  
  435.             }  
  436.             /* we need to encode this block now (for next ones) */  
  437.             x264_mb_encode_i4x4( h, 0, idx, a->i_qp, a->i_predict4x4[idx], 0 );  
  438.         }  
  439.         if( idx == 15 )//處理最後一個4x4小塊(一共16個塊)  
  440.         {  
  441.             //開銷(累加完的)  
  442.             a->i_satd_i4x4 = i_cost;  
  443.             if( h->mb.i_skip_intra )  
  444.             {  
  445.                 h->mc.copy[PIXEL_16x16]( h->mb.pic.i4x4_fdec_buf, 16, p_dst, FDEC_STRIDE, 16 );  
  446.                 h->mb.pic.i4x4_nnz_buf[0] = M32( &h->mb.cache.non_zero_count[x264_scan8[ 0]] );  
  447.                 h->mb.pic.i4x4_nnz_buf[1] = M32( &h->mb.cache.non_zero_count[x264_scan8[ 2]] );  
  448.                 h->mb.pic.i4x4_nnz_buf[2] = M32( &h->mb.cache.non_zero_count[x264_scan8[ 8]] );  
  449.                 h->mb.pic.i4x4_nnz_buf[3] = M32( &h->mb.cache.non_zero_count[x264_scan8[10]] );  
  450.                 h->mb.pic.i4x4_cbp = h->mb.i_cbp_luma;  
  451.                 if( h->mb.i_skip_intra == 2 )  
  452.                     h->mc.memcpy_aligned( h->mb.pic.i4x4_dct_buf, h->dct.luma4x4, sizeof(h->mb.pic.i4x4_dct_buf) );  
  453.             }  
  454.         }  
  455.         else  
  456.             a->i_satd_i4x4 = COST_MAX;  
  457.     }  
  458. }  

總體說來x264_mb_analyse_intra()通過計算Intra16x16,Intra8x8(暫時沒有研究),Intra4x4這3中幀內預測模式的代價,比較後得到最佳的幀內預測模式。該函數的等流程大致如下:
(1)進行Intra16X16模式的預測
a)調用predict_16x16_mode_available()根據周圍宏塊的情況判斷其可用的預測模式(主要檢查左邊和上邊的塊是否可用)。
b)循環計算4種Intra16x16幀內預測模式:
i.調用predict_16x16[]()彙編函數進行Intra16x16幀內預測
ii.調用x264_pixel_function_t中的mbcmp[]()計算編碼代價(mbcmp[]()指向SAD或者SATD彙編函數)。
c)獲取最小代價的Intra16x16模式。
(2)進行Intra8x8模式的預測(未研究,流程應該類似)
(3)進行Intra4X4塊模式的預測
a)循環處理16個4x4的塊:
i.調用x264_mb_predict_intra4x4_mode()根據周圍宏塊情況判斷該塊可用的預測模式。
ii.循環計算9種Intra4x4的幀內預測模式:
1)調用predict_4x4 []()彙編函數進行Intra4x4幀內預測
2)調用x264_pixel_function_t中的mbcmp[]()計算編碼代價(mbcmp[]()指向SAD或者SATD彙編函數)。
iii.獲取最小代價的Intra4x4模式。
b)將16個4X4塊的最小代價相加,得到總代價。

(4)將上述3中模式的代價進行對比,取最小者爲當前宏塊的幀內預測模式。

後文將會對其中涉及到的幾種彙編函數進行分析。在看源代碼之前,簡單記錄一下相關的知識。


幀內預測知識

簡單記錄一下幀內預測的方法。幀內預測根據宏塊左邊和上邊的邊界像素值推算宏塊內部的像素值,幀內預測的效果如下圖所示。其中左邊的圖爲圖像原始畫面,右邊的圖爲經過幀內預測後沒有疊加殘差的畫面。


H.264中有兩種幀內預測模式:16x16亮度幀內預測模式和4x4亮度幀內預測模式。其中16x16幀內預測模式一共有4種,如下圖所示。


這4種模式列表如下。

模式

描述

Vertical

由上邊像素推出相應像素值

Horizontal

由左邊像素推出相應像素值

DC

由上邊和左邊像素平均值推出相應像素值

Plane

由上邊和左邊像素推出相應像素值


4x4幀內預測模式一共有9種,如下圖所示。
 
可以看出,Intra4x4幀內預測模式中前4種和Intra16x16是一樣的。後面多增加了幾種預測箭頭不是45度角的方式——前面的箭頭位於「口」中,而後面的箭頭位於「日」中。

像素比較知識

幀內預測代價計算的過程中涉及到SAD和SATD像素計算,簡單記錄幾個相關的概念。有關SAD、SATD、SSD的定義如下:
SAD(Sum of Absolute Difference)也可以稱爲SAE(Sum of Absolute Error),即絕對誤差和。它的計算方法就是求出兩個像素塊對應像素點的差值,將這些差值分別求絕對值之後再進行累加。
SATD(Sum of Absolute Transformed Difference)即Hadamard變換後再絕對值求和。它和SAD的區別在於多了一個「變換」。
SSD(Sum of Squared Difference)也可以稱爲SSE(Sum of Squared Error),即差值的平方和。它和SAD的區別在於多了一個「平方」。
H.264中使用SAD和SATD進行宏塊預測模式的判斷。早期的編碼器使用SAD進行計算,近期的編碼器多使用SATD進行計算。爲什麼使用SATD而不使用SAD呢?關鍵原因在於編碼之後碼流的大小是和圖像塊DCT變換後頻域信息緊密相關的,而和變換前的時域信息關聯性小一些。SAD只能反應時域信息;SATD卻可以反映頻域信息,而且計算複雜度也低於DCT變換,因此是比較合適的模式選擇的依據。
使用SAD進行模式選擇的示例如下所示。下面這張圖代表了一個普通的Intra16x16的宏塊的像素。它的下方包含了使用Vertical,Horizontal,DC和Plane四種幀內預測模式預測的像素。通過計算可以得到這幾種預測像素和原始像素之間的SAD(SAE)分別爲3985,5097,4991,2539。由於Plane模式的SAD取值最小,由此可以斷定Plane模式對於這個宏塊來說是最好的幀內預測模式。



下面按照Intra16x16預測,Intra4x4預測,像素計算的順序記錄依次記錄各個模塊的彙編函數源代碼。



Intra16x16幀內預測源代碼

Intra16x16幀內預測模塊的初始化函數是x264_predict_16x16_init()。該函數對x264_predict_t結構體中的函數指針進行了賦值。X264運行的過程中只要調用x264_predict_t的函數指針就可以完成相應的功能。


x264_predict_16x16_init()

x264_predict_16x16_init()用於初始化Intra16x16幀內預測彙編函數。該函數的定義位於x264\common\predict.c,如下所示。
[cpp]  view plain  copy
  1. //Intra16x16幀內預測彙編函數初始化  
  2. void x264_predict_16x16_init( int cpu, x264_predict_t pf[7] )  
  3. {  
  4.     //C語言版本  
  5.     //================================================  
  6.     //垂直 Vertical  
  7.     pf[I_PRED_16x16_V ]     = x264_predict_16x16_v_c;  
  8.     //水平 Horizontal  
  9.     pf[I_PRED_16x16_H ]     = x264_predict_16x16_h_c;  
  10.     //DC  
  11.     pf[I_PRED_16x16_DC]     = x264_predict_16x16_dc_c;  
  12.     //Plane  
  13.     pf[I_PRED_16x16_P ]     = x264_predict_16x16_p_c;  
  14.     //這幾種是啥?  
  15.     pf[I_PRED_16x16_DC_LEFT]= x264_predict_16x16_dc_left_c;  
  16.     pf[I_PRED_16x16_DC_TOP ]= x264_predict_16x16_dc_top_c;  
  17.     pf[I_PRED_16x16_DC_128 ]= x264_predict_16x16_dc_128_c;  
  18.     //================================================  
  19.     //MMX版本  
  20. #if HAVE_MMX  
  21.     x264_predict_16x16_init_mmx( cpu, pf );  
  22. #endif  
  23.     //ALTIVEC版本  
  24. #if HAVE_ALTIVEC  
  25.     if( cpu&X264_CPU_ALTIVEC )  
  26.         x264_predict_16x16_init_altivec( pf );  
  27. #endif  
  28.     //ARMV6版本  
  29. #if HAVE_ARMV6  
  30.     x264_predict_16x16_init_arm( cpu, pf );  
  31. #endif  
  32.     //AARCH64版本  
  33. #if ARCH_AARCH64  
  34.     x264_predict_16x16_init_aarch64( cpu, pf );  
  35. #endif  
  36. }  

從源代碼可看出,x264_predict_16x16_init()首先對幀內預測函數指針數組x264_predict_t[]中的元素賦值了C語言版本的函數x264_predict_16x16_v_c(),x264_predict_16x16_h_c(),x264_predict_16x16_dc_c(),x264_predict_16x16_p_c();然後會判斷系統平臺的特性,如果平臺支持的話,會調用x264_predict_16x16_init_mmx(),x264_predict_16x16_init_arm()等給x264_predict_t[]中的元素賦值經過彙編優化的函數。下文首先看一下Intra16x16中的4種幀內預測模式的C語言版本,作爲對比再看一下Intra16x16中Vertical模式的X86彙編版本和NEON彙編版本。

x264_predict_16x16_v_c()

x264_predict_16x16_v_c()是Intra16x16幀內預測Vertical模式的C語言版本函數。該函數的定義位於common\predict.c,如下所示。
[cpp]  view plain  copy
  1. //16x16幀內預測  
  2. //垂直預測(Vertical)  
  3. void x264_predict_16x16_v_c( pixel *src )  
  4. {  
  5.     /* 
  6.      * Vertical預測方式 
  7.      *   |X1 X2 X3 X4 
  8.      * --+----------- 
  9.      *   |X1 X2 X3 X4 
  10.      *   |X1 X2 X3 X4 
  11.      *   |X1 X2 X3 X4 
  12.      *   |X1 X2 X3 X4 
  13.      * 
  14.      */  
  15.     /* 
  16.      * 【展開宏定義】 
  17.      * uint32_t v0 = ((x264_union32_t*)(&src[ 0-FDEC_STRIDE]))->i; 
  18.      * uint32_t v1 = ((x264_union32_t*)(&src[ 4-FDEC_STRIDE]))->i; 
  19.      * uint32_t v2 = ((x264_union32_t*)(&src[ 8-FDEC_STRIDE]))->i; 
  20.      * uint32_t v3 = ((x264_union32_t*)(&src[12-FDEC_STRIDE]))->i; 
  21.      * 在這裏,上述代碼實際上相當於: 
  22.      * uint32_t v0 = *((uint32_t*)(&src[ 0-FDEC_STRIDE])); 
  23.      * uint32_t v1 = *((uint32_t*)(&src[ 4-FDEC_STRIDE])); 
  24.      * uint32_t v2 = *((uint32_t*)(&src[ 8-FDEC_STRIDE])); 
  25.      * uint32_t v3 = *((uint32_t*)(&src[12-FDEC_STRIDE])); 
  26.      * 即分成4次,每次取出4個像素(一共16個像素),分別賦值給v0,v1,v2,v3 
  27.      * 取出的值源自於16x16塊上面的一行像素 
  28.      *    0|          4          8          12         16 
  29.      *    ||    v0    |    v1    |    v2    |    v3    | 
  30.      * ---++==========+==========+==========+==========+ 
  31.      *    || 
  32.      *    || 
  33.      *    || 
  34.      *    || 
  35.      *    || 
  36.      *    || 
  37.      * 
  38.      */  
  39.     //pixel4實際上是uint32_t(佔用32bit),存儲4個像素的值(每個像素佔用8bit)  
  40.   
  41.     pixel4 v0 = MPIXEL_X4( &src[ 0-FDEC_STRIDE] );  
  42.     pixel4 v1 = MPIXEL_X4( &src[ 4-FDEC_STRIDE] );  
  43.     pixel4 v2 = MPIXEL_X4( &src[ 8-FDEC_STRIDE] );  
  44.     pixel4 v3 = MPIXEL_X4( &src[12-FDEC_STRIDE] );  
  45.   
  46.     //循環賦值16行  
  47.     forint i = 0; i < 16; i++ )  
  48.     {  
  49.         //【展開宏定義】  
  50.         //(((x264_union32_t*)(src+ 0))->i) = v0;  
  51.         //(((x264_union32_t*)(src+ 4))->i) = v1;  
  52.         //(((x264_union32_t*)(src+ 8))->i) = v2;  
  53.         //(((x264_union32_t*)(src+12))->i) = v3;  
  54.         //即分成4次,每次賦值4個像素  
  55.         //  
  56.         MPIXEL_X4( src+ 0 ) = v0;  
  57.         MPIXEL_X4( src+ 4 ) = v1;  
  58.         MPIXEL_X4( src+ 8 ) = v2;  
  59.         MPIXEL_X4( src+12 ) = v3;  
  60.         //下一行  
  61.         //FDEC_STRIDE=32,是重建宏塊緩存fdec_buf一行的數據量  
  62.         src += FDEC_STRIDE;  
  63.     }  
  64. }  

從源代碼可以看出,x264_predict_16x16_v_c()首先取出16x16塊上面一行像素值,依次存儲在v0、v1、v2、v3,然後循環16次賦值給塊中的16行像素。


x264_predict_16x16_h_c()

x264_predict_16x16_h_c()是Intra16x16幀內預測Horizontal模式的C語言版本函數。該函數的定義位於common\predict.c,如下所示。
[cpp]  view plain  copy
  1. //16x16幀內預測  
  2. //水平預測(Horizontal)  
  3. void x264_predict_16x16_h_c( pixel *src )  
  4. {  
  5.     /* 
  6.      * Horizontal預測方式 
  7.      *   | 
  8.      * --+----------- 
  9.      * X5|X5 X5 X5 X5 
  10.      * X6|X6 X6 X6 X6 
  11.      * X7|X7 X7 X7 X7 
  12.      * X8|X8 X8 X8 X8 
  13.      * 
  14.      */  
  15.     /* 
  16.      * const pixel4 v = PIXEL_SPLAT_X4( src[-1] ); 
  17.      * 宏定義展開後 
  18.      * const uint32_t v = (src[-1])*0x01010101U; 
  19.      * 
  20.      * PIXEL_SPLAT_X4()的作用應該是把最後一個像素(最後8位)拷貝給前面3個像素(前24位) 
  21.      * 即把0x0100009F變成0x9F9F9F9F 
  22.      * 推導: 
  23.      * 前提是x佔8bit(對應1個像素) 
  24.      * y=x*0x01010101 
  25.      *  =x*(0x00000001+0x00000100+0x00010000+0x01000000) 
  26.      *  =x<<0+x<<8+x<<16+x<<24 
  27.      * 
  28.      * const uint32_t v = (src[-1])*0x01010101U含義: 
  29.      * 每行把src[-1]中像素值例如0x02賦值給v.v取值爲0x02020202 
  30.      * src[-1]即16x16塊左側的值 
  31.      */  
  32.     //循環賦值16行  
  33.     forint i = 0; i < 16; i++ )  
  34.     {  
  35.         const pixel4 v = PIXEL_SPLAT_X4( src[-1] );  
  36.         //宏定義展開後:  
  37.         //((x264_union32_t*)(src+ 0))->i=v;  
  38.         //((x264_union32_t*)(src+ 4))->i=v;  
  39.         //((x264_union32_t*)(src+ 8))->i=v;  
  40.         //((x264_union32_t*)(src+12))->i=v;  
  41.         //即分4次,每次賦值4個像素(一行一共16個像素,取值是一樣的)  
  42.         //  
  43.         //   0|          4          8         12         16  
  44.         //   ||          |          |          |          |  
  45.         //---++==========+==========+==========+==========+  
  46.         //   ||  
  47.         // v ||    v     |    v     |    v     |    v     |  
  48.         //   ||  
  49.         //   ||  
  50.         //   ||  
  51.         //  
  52.         MPIXEL_X4( src+ 0 ) = v;  
  53.         MPIXEL_X4( src+ 4 ) = v;  
  54.         MPIXEL_X4( src+ 8 ) = v;  
  55.         MPIXEL_X4( src+12 ) = v;  
  56.         //下一行  
  57.         //FDEC_STRIDE=32,是重建宏塊緩存fdec_buf一行的數據量  
  58.         src += FDEC_STRIDE;  
  59.     }  
  60. }  

從源代碼可以看出,x264_predict_16x16_h_c()首先取出16x16塊每行左邊的1個像素,複製4份後存儲在v中,然後分成4次將v賦值給這一行像素。其中「PIXEL_SPLAT_X4()」的功能是取出變量低8位的數值複製4份到高24位,相關的推導功能已經記錄在源代碼中,不再重複敘述。

x264_predict_16x16_dc_c()

x264_predict_16x16_dc_c()是Intra16x16幀內預測DC模式的C語言版本函數。該函數的定義位於common\predict.c,如下所示。
[cpp]  view plain  copy
  1. #define PREDICT_16x16_DC(v)\  
  2.     forint i = 0; i < 16; i++ )\  
  3.     {\  
  4.         MPIXEL_X4( src+ 0 ) = v;\  
  5.         MPIXEL_X4( src+ 4 ) = v;\  
  6.         MPIXEL_X4( src+ 8 ) = v;\  
  7.         MPIXEL_X4( src+12 ) = v;\  
  8.         src += FDEC_STRIDE;\  
  9.     }  
  10.   
  11. void x264_predict_16x16_dc_c( pixel *src )  
  12. {  
  13.     /* 
  14.      * DC預測方式 
  15.      *   |X1 X2 X3 X4 
  16.      * --+----------- 
  17.      * X5| 
  18.      * X6|     Y 
  19.      * X7| 
  20.      * X8| 
  21.      * 
  22.      * Y=(X1+X2+X3+X4+X5+X6+X7+X8)/8 
  23.      */  
  24.   
  25.     int dc = 0;  
  26.     //把16x16塊中所有像素的值加起來,存儲在dc中  
  27.     forint i = 0; i < 16; i++ )  
  28.     {  
  29.         //左側的值  
  30.         dc += src[-1 + i * FDEC_STRIDE];  
  31.         //上方的值  
  32.         dc += src[i - FDEC_STRIDE];  
  33.     }  
  34.     //加起來的值除以32(一共16+16個點)  
  35.     //「+16」是爲了四捨五入?  
  36.     //PIXEL_SPLAT_X4()的作用應該是把最後一個像素(最後8位)拷貝給前面3個像素(前24位)  
  37.     //即把0x0100009F變成0x9F9F9F9F  
  38.     pixel4 dcsplat = PIXEL_SPLAT_X4( ( dc + 16 ) >> 5 );  
  39.     //賦值到16x16塊中的每個像素  
  40.     /* 
  41.      * 宏展開之後結果 
  42.      * for( int i = 0; i < 16; i++ ) 
  43.      * { 
  44.      *  (((x264_union32_t*)(src+ 0))->i) = dcsplat; 
  45.      *  (((x264_union32_t*)(src+ 4))->i) = dcsplat; 
  46.      *  (((x264_union32_t*)(src+ 8))->i) = dcsplat; 
  47.      *  (((x264_union32_t*)(src+12))->i) = dcsplat; 
  48.      *  src += 32; 
  49.      * } 
  50.      */
相關文章
相關標籤/搜索