x264源代碼簡單分析:x264_slice_write()

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


      本文簡單分析x264的x264_slice_write()的源代碼。x264_slice_write()是x264項目的核心,它完成了編碼了一個Slice的工作。根據功能的不同,該函數可以分爲濾波(Filter),分析(Analysis),宏塊編碼(Encode)和熵編碼(Entropy Encoding)幾個子模塊。本文首先對x264_slice_write()進行總體的概括,在後續文章中將會對上述幾個子模塊展開進行分析。



函數調用關係圖

x264_slice_write()的源代碼在整個x264中的位置如下圖所示。



x264_slice_write()的函數調用關係如下圖所示。
 

從圖中可以看出,x264_slice_write()調用瞭如下函數:
x264_nal_start():開始寫一個NALU。
x264_macroblock_thread_init():初始化宏塊重建數據緩存fdec_buf[]和編碼數據緩存fenc_buf[]。
x264_slice_header_write():輸出 Slice Header。
x264_fdec_filter_row():濾波模塊。該模塊包含了環路濾波,半像素插值,SSIM/PSNR的計算。
x264_macroblock_cache_load():將要編碼的宏塊的周圍的宏塊的信息讀進來。
x264_macroblock_analyse():分析模塊。該模塊包含了幀內預測模式分析以及幀間運動估計等。
x264_macroblock_encode():宏塊編碼模塊。該模塊通過對殘差的DCT變換、量化等方式對宏塊進行編碼。
x264_macroblock_write_cabac():CABAC熵編碼模塊。
x264_macroblock_write_cavlc():CAVLC熵編碼模塊。
x264_macroblock_cache_save():保存當前宏塊的信息。
x264_ratecontrol_mb():碼率控制。
x264_nal_end():結束寫一個NALU。
本文將會對上述函數進行分析。其中x264_fdec_filter_row(),x264_macroblock_analyse(),x264_macroblock_encode(),x264_macroblock_write_cabac()/x264_macroblock_write_cavlc()只做概述,後續文章中再做分析。



x264_slice_write()

x264_slice_write()用於編碼一個Slice。該函數的定義位於encoder\encoder.c,如下所示。
[cpp]  view plain  copy
  1. /**************************************************************************** 
  2.  * 真正的編碼——編碼1個Slice 
  3.  * 註釋和處理:雷霄驊 
  4.  * http://blog.csdn.net/leixiaohua1020 
  5.  * [email protected] 
  6.  ****************************************************************************/  
  7. static intptr_t x264_slice_write( x264_t *h )  
  8. {  
  9.     int i_skip;  
  10.     //宏塊的序號,以及序號對應的x,y座標  
  11.     int mb_xy, i_mb_x, i_mb_y;  
  12.     /* NALUs other than the first use a 3-byte startcode. 
  13.      * Add one extra byte for the rbsp, and one more for the final CABAC putbyte. 
  14.      * Then add an extra 5 bytes just in case, to account for random NAL escapes and 
  15.      * other inaccuracies. */  
  16.     int overhead_guess = (NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal)) + 1 + h->param.b_cabac + 5;  
  17.     int slice_max_size = h->param.i_slice_max_size > 0 ? (h->param.i_slice_max_size-overhead_guess)*8 : 0;  
  18.     int back_up_bitstream_cavlc = !h->param.b_cabac && h->sps->i_profile_idc < PROFILE_HIGH;  
  19.     int back_up_bitstream = slice_max_size || back_up_bitstream_cavlc;  
  20.     int starting_bits = bs_pos(&h->out.bs);  
  21.     int b_deblock = h->sh.i_disable_deblocking_filter_idc != 1;  
  22.     int b_hpel = h->fdec->b_kept_as_ref;  
  23.     int orig_last_mb = h->sh.i_last_mb;  
  24.     int thread_last_mb = h->i_threadslice_end * h->mb.i_mb_width - 1;  
  25.     uint8_t *last_emu_check;  
  26. #define BS_BAK_SLICE_MAX_SIZE 0  
  27. #define BS_BAK_CAVLC_OVERFLOW 1  
  28. #define BS_BAK_SLICE_MIN_MBS  2  
  29. #define BS_BAK_ROW_VBV        3  
  30.     x264_bs_bak_t bs_bak[4];  
  31.     b_deblock &= b_hpel || h->param.b_full_recon || h->param.psz_dump_yuv;  
  32.     bs_realign( &h->out.bs );  
  33.   
  34.     /* Slice */  
  35.     //開始輸出一個NAL  
  36.     //後面對應着x264_nal_end()  
  37.     x264_nal_start( h, h->i_nal_type, h->i_nal_ref_idc );  
  38.     h->out.nal[h->out.i_nal].i_first_mb = h->sh.i_first_mb;  
  39.   
  40.     /* Slice header */  
  41.   
  42.     //存儲宏塊像素的緩存fdec_buf和fenc_buf的初始化  
  43.     //宏塊編碼緩存p_fenc[0],p_fenc[1],p_fenc[2]  
  44.     //宏塊重建緩存p_fdec[0],p_fdec[1],p_fdec[2]  
  45.     //[0]存Y,[1]存U,[2]存V  
  46.     x264_macroblock_thread_init( h );  
  47.   
  48.     /* Set the QP equal to the first QP in the slice for more accurate CABAC initialization. */  
  49.     h->mb.i_mb_xy = h->sh.i_first_mb;  
  50.     h->sh.i_qp = x264_ratecontrol_mb_qp( h );  
  51.     h->sh.i_qp = SPEC_QP( h->sh.i_qp );  
  52.     h->sh.i_qp_delta = h->sh.i_qp - h->pps->i_pic_init_qp;  
  53.     //輸出 slice header  
  54.     x264_slice_header_write( &h->out.bs, &h->sh, h->i_nal_ref_idc );  
  55.     //如果使用CABAC,需要初始化  
  56.     if( h->param.b_cabac )  
  57.     {  
  58.         /* alignment needed */  
  59.         bs_align_1( &h->out.bs );  
  60.   
  61.         /* init cabac */  
  62.         x264_cabac_context_init( h, &h->cabac, h->sh.i_type, x264_clip3( h->sh.i_qp-QP_BD_OFFSET, 0, 51 ), h->sh.i_cabac_init_idc );  
  63.         x264_cabac_encode_init ( &h->cabac, h->out.bs.p, h->out.bs.p_end );  
  64.         last_emu_check = h->cabac.p;  
  65.     }  
  66.     else  
  67.         last_emu_check = h->out.bs.p;  
  68.     h->mb.i_last_qp = h->sh.i_qp;  
  69.     h->mb.i_last_dqp = 0;  
  70.     h->mb.field_decoding_flag = 0;  
  71.     //宏塊位置-縱座標(初始值)  
  72.     i_mb_y = h->sh.i_first_mb / h->mb.i_mb_width;  
  73.     //宏塊位置-橫座標(初始值)  
  74.     i_mb_x = h->sh.i_first_mb % h->mb.i_mb_width;  
  75.     i_skip = 0;  
  76.   
  77.     //一個大循環  
  78.     //對一個slice中每個宏塊進行編碼  
  79.     while( 1 )  
  80.     {  
  81.         //宏塊序號。由i_mb_x和i_mb_y計算而來。  
  82.         mb_xy = i_mb_x + i_mb_y * h->mb.i_mb_width;  
  83.         int mb_spos = bs_pos(&h->out.bs) + x264_cabac_pos(&h->cabac);  
  84.         //一行的開始  
  85.         if( i_mb_x == 0 )  
  86.         {  
  87.             if( x264_bitstream_check_buffer( h ) )  
  88.                 return -1;  
  89.             if( !(i_mb_y & SLICE_MBAFF) && h->param.rc.i_vbv_buffer_size )  
  90.                 x264_bitstream_backup( h, &bs_bak[BS_BAK_ROW_VBV], i_skip, 1 );  
  91.             //去塊效應濾波、半像素插值、SSIM/PSNR計算等  
  92.             //一次處理一行宏塊  
  93.             if( !h->mb.b_reencode_mb )  
  94.                 x264_fdec_filter_row( h, i_mb_y, 0 );  
  95.         }  
  96.   
  97.         if( back_up_bitstream )  
  98.         {  
  99.             if( back_up_bitstream_cavlc )  
  100.                 x264_bitstream_backup( h, &bs_bak[BS_BAK_CAVLC_OVERFLOW], i_skip, 0 );  
  101.             if( slice_max_size && !(i_mb_y & SLICE_MBAFF) )  
  102.             {  
  103.                 x264_bitstream_backup( h, &bs_bak[BS_BAK_SLICE_MAX_SIZE], i_skip, 0 );  
  104.                 if( (thread_last_mb+1-mb_xy) == h->param.i_slice_min_mbs )  
  105.                     x264_bitstream_backup( h, &bs_bak[BS_BAK_SLICE_MIN_MBS], i_skip, 0 );  
  106.             }  
  107.         }  
  108.   
  109.         if( PARAM_INTERLACED )  
  110.         {  
  111.             if( h->mb.b_adaptive_mbaff )  
  112.             {  
  113.                 if( !(i_mb_y&1) )  
  114.                 {  
  115.                     /* FIXME: VSAD is fast but fairly poor at choosing the best interlace type. */  
  116.                     h->mb.b_interlaced = x264_field_vsad( h, i_mb_x, i_mb_y );  
  117.                     memcpy( &h->zigzagf, MB_INTERLACED ? &h->zigzagf_interlaced : &h->zigzagf_progressive, sizeof(h->zigzagf) );  
  118.                     if( !MB_INTERLACED && (i_mb_y+2) == h->mb.i_mb_height )  
  119.                         x264_expand_border_mbpair( h, i_mb_x, i_mb_y );  
  120.                 }  
  121.             }  
  122.             h->mb.field[mb_xy] = MB_INTERLACED;  
  123.         }  
  124.   
  125.         /* load cache */  
  126.         //將要編碼的宏塊的周圍的宏塊的值讀進來  
  127.         //主要是上面、左邊塊的值  
  128.         if( SLICE_MBAFF )  
  129.             x264_macroblock_cache_load_interlaced( h, i_mb_x, i_mb_y );  
  130.         else  
  131.             x264_macroblock_cache_load_progressive( h, i_mb_x, i_mb_y );  
  132.         //分析-幀內預測模式選擇、幀間運動估計等  
  133.         x264_macroblock_analyse( h );  
  134.   
  135.         /* encode this macroblock -> be careful it can change the mb type to P_SKIP if needed */  
  136. reencode:  
  137.         //編碼-殘差DCT變換、量化  
  138.         x264_macroblock_encode( h );  
  139.         //輸出CABAC  
  140.         if( h->param.b_cabac )  
  141.         {  
  142.             if( mb_xy > h->sh.i_first_mb && !(SLICE_MBAFF && (i_mb_y&1)) )  
  143.                 x264_cabac_encode_terminal( &h->cabac );  
  144.   
  145.             if( IS_SKIP( h->mb.i_type ) )  
  146.                 x264_cabac_mb_skip( h, 1 );  
  147.             else  
  148.             {  
  149.                 if( h->sh.i_type != SLICE_TYPE_I )  
  150.                     x264_cabac_mb_skip( h, 0 );  
  151.                 //輸出  
  152.                 x264_macroblock_write_cabac( h, &h->cabac );  
  153.             }  
  154.         }  
  155.         else  
  156.         {  
  157.             //輸出CAVLC  
  158.             if( IS_SKIP( h->mb.i_type ) )  
  159.                 i_skip++;  
  160.             else  
  161.             {  
  162.                 if( h->sh.i_type != SLICE_TYPE_I )  
  163.                 {  
  164.                     bs_write_ue( &h->out.bs, i_skip );  /* skip run */  
  165.                     i_skip = 0;  
  166.                 }  
  167.                 //輸出  
  168.                 x264_macroblock_write_cavlc( h );  
  169.                 /* If there was a CAVLC level code overflow, try again at a higher QP. */  
  170.                 if( h->mb.b_overflow )  
  171.                 {  
  172.                     h->mb.i_chroma_qp = h->chroma_qp_table[++h->mb.i_qp];  
  173.                     h->mb.i_skip_intra = 0;  
  174.                     h->mb.b_skip_mc = 0;  
  175.                     h->mb.b_overflow = 0;  
  176.                     x264_bitstream_restore( h, &bs_bak[BS_BAK_CAVLC_OVERFLOW], &i_skip, 0 );  
  177.                     goto reencode;  
  178.                 }  
  179.             }  
  180.         }  
  181.   
  182.         int total_bits = bs_pos(&h->out.bs) + x264_cabac_pos(&h->cabac);  
  183.         int mb_size = total_bits - mb_spos;  
  184.   
  185.         if( slice_max_size && (!SLICE_MBAFF || (i_mb_y&1)) )  
  186.         {  
  187.             /* Count the skip run, just in case. */  
  188.             if( !h->param.b_cabac )  
  189.                 total_bits += bs_size_ue_big( i_skip );  
  190.             /* Check for escape bytes. */  
  191.             uint8_t *end = h->param.b_cabac ? h->cabac.p : h->out.bs.p;  
  192.             for( ; last_emu_check < end - 2; last_emu_check++ )  
  193.                 if( last_emu_check[0] == 0 && last_emu_check[1] == 0 && last_emu_check[2] <= 3 )  
  194.                 {  
  195.                     slice_max_size -= 8;  
  196.                     last_emu_check++;  
  197.                 }  
  198.             /* We'll just re-encode this last macroblock if we go over the max slice size. */  
  199.             if( total_bits - starting_bits > slice_max_size && !h->mb.b_reencode_mb )  
  200.             {  
  201.                 if( !x264_frame_new_slice( h, h->fdec ) )  
  202.                 {  
  203.                     /* Handle the most obnoxious slice-min-mbs edge case: we need to end the slice 
  204.                      * because it's gone over the maximum size, but doing so would violate slice-min-mbs. 
  205.                      * If possible, roll back to the last checkpoint and try again. 
  206.                      * We could try raising QP, but that would break in the case where a slice spans multiple 
  207.                      * rows, which the re-encoding infrastructure can't currently handle. */  
  208.                     if( mb_xy <= thread_last_mb && (thread_last_mb+1-mb_xy) < h->param.i_slice_min_mbs )  
  209.                     {  
  210.                         if( thread_last_mb-h->param.i_slice_min_mbs < h->sh.i_first_mb+h->param.i_slice_min_mbs )  
  211.                         {  
  212.                             x264_log( h, X264_LOG_WARNING, "slice-max-size violated (frame %d, cause: slice-min-mbs)\n", h->i_frame );  
  213.                             slice_max_size = 0;  
  214.                             goto cont;  
  215.                         }  
  216.                         x264_bitstream_restore( h, &bs_bak[BS_BAK_SLICE_MIN_MBS], &i_skip, 0 );  
  217.                         h->mb.b_reencode_mb = 1;  
  218.                         h->sh.i_last_mb = thread_last_mb-h->param.i_slice_min_mbs;  
  219.                         break;  
  220.                     }  
  221.                     if( mb_xy-SLICE_MBAFF*h->mb.i_mb_stride != h->sh.i_first_mb )  
  222.                     {  
  223.                         x264_bitstream_restore( h, &bs_bak[BS_BAK_SLICE_MAX_SIZE], &i_skip, 0 );  
  224.                         h->mb.b_reencode_mb = 1;  
  225.                         if( SLICE_MBAFF )  
  226.                         {  
  227.                             // set to bottom of previous mbpair  
  228.                             if( i_mb_x )  
  229.                                 h->sh.i_last_mb = mb_xy-1+h->mb.i_mb_stride*(!(i_mb_y&1));  
  230.                             else  
  231.                                 h->sh.i_last_mb = (i_mb_y-2+!(i_mb_y&1))*h->mb.i_mb_stride + h->mb.i_mb_width - 1;  
  232.                         }  
  233.                         else  
  234.                             h->sh.i_last_mb = mb_xy-1;  
  235.                         break;  
  236.                     }  
  237.                     else  
  238.                         h->sh.i_last_mb = mb_xy;  
  239.                 }  
  240.                 else  
  241.                     slice_max_size = 0;  
  242.             }  
  243.         }  
  244. cont:  
  245.         h->mb.b_reencode_mb = 0;  
  246.   
  247.         /* save cache */  
  248.         //保存當前宏塊的的值,用於以後的宏塊的編碼  
  249.         //包括Intra4x4宏塊幀內預測模式,DCT非零係數,運動矢量,參考幀序號等等  
  250.         x264_macroblock_cache_save( h );  
  251.         //碼率控制  
  252.         if( x264_ratecontrol_mb( h, mb_size ) < 0 )  
  253.         {  
  254.             x264_bitstream_restore( h, &bs_bak[BS_BAK_ROW_VBV], &i_skip, 1 );  
  255.             h->mb.b_reencode_mb = 1;  
  256.             i_mb_x = 0;  
  257.             i_mb_y = i_mb_y - SLICE_MBAFF;  
  258.             h->mb.i_mb_prev_xy = i_mb_y * h->mb.i_mb_stride - 1;  
  259.             h->sh.i_last_mb = orig_last_mb;  
  260.             continue;  
  261.         }  
  262.   
  263.         /* accumulate mb stats */  
  264.         //後面很大一段代碼都是對stat結構體中的統計信息進行賦值================================  
  265.         h->stat.frame.i_mb_count[h->mb.i_type]++;  
  266.   
  267.         int b_intra = IS_INTRA( h->mb.i_type );  
  268.         int b_skip = IS_SKIP( h->mb.i_type );  
  269.         if( h->param.i_log_level >= X264_LOG_INFO || h->param.rc.b_stat_write )  
  270.         {  
  271.             if( !b_intra && !b_skip && !IS_DIRECT( h->mb.i_type ) )  
  272.             {  
  273.                 if( h->mb.i_partition != D_8x8 )  
  274.                         h->stat.frame.i_mb_partition[h->mb.i_partition] += 4;  
  275.                     else  
  276.                         forint i = 0; i < 4; i++ )  
  277.                             h->stat.frame.i_mb_partition[h->mb.i_sub_partition[i]] ++;  
  278.                 if( h->param.i_frame_reference > 1 )  
  279.                     forint i_list = 0; i_list <= (h->sh.i_type == SLICE_TYPE_B); i_list++ )  
  280.                         forint i = 0; i < 4; i++ )  
  281.                         {  
  282.                             int i_ref = h->mb.cache.ref[i_list][ x264_scan8[4*i] ];  
  283.                             if( i_ref >= 0 )  
  284.                                 h->stat.frame.i_mb_count_ref[i_list][i_ref] ++;  
  285.                         }  
  286.             }  
  287.         }  
  288.   
  289.         if( h->param.i_log_level >= X264_LOG_INFO )  
  290.         {  
  291.             if( h->mb.i_cbp_luma | h->mb.i_cbp_chroma )  
  292.             {  
  293.                 if( CHROMA444 )  
  294.                 {  
  295.                     forint i = 0; i < 4; i++ )  
  296.                         if( h->mb.i_cbp_luma & (1 << i) )  
  297.                             forint p = 0; p < 3; p++ )  
  298.                             {  
  299.                                 int s8 = i*4+p*16;  
  300.                                 int nnz8x8 = M16( &h->mb.cache.non_zero_count[x264_scan8[s8]+0] )  
  301.                                            | M16( &h->mb.cache.non_zero_count[x264_scan8[s8]+8] );  
  302.                                 h->stat.frame.i_mb_cbp[!b_intra + p*2] += !!nnz8x8;  
  303.                             }  
  304.                 }  
  305.                 else  
  306.                 {  
  307.                     int cbpsum = (h->mb.i_cbp_luma&1) + ((h->mb.i_cbp_luma>>1)&1)  
  308.                                + ((h->mb.i_cbp_luma>>2)&1) + (h->mb.i_cbp_luma>>3);  
  309.                     h->stat.frame.i_mb_cbp[!b_intra + 0] += cbpsum;  
  310.                     h->stat.frame.i_mb_cbp[!b_intra + 2] += !!h->mb.i_cbp_chroma;  
  311.                     h->stat.frame.i_mb_cbp[!b_intra + 4] += h->mb.i_cbp_chroma >> 1;  
  312.                 }  
  313.             }  
  314.             if( h->mb.i_cbp_luma && !b_intra )  
  315.             {  
  316.                 h->stat.frame.i_mb_count_8x8dct[0] ++;  
  317.                 h->stat.frame.i_mb_count_8x8dct[1] += h->mb.b_transform_8x8;  
  318.             }  
  319.             if( b_intra && h->mb.i_type != I_PCM )  
  320.             {  
  321.                 if( h->mb.i_type == I_16x16 )  
  322.                     h->stat.frame.i_mb_pred_mode[0][h->mb.i_intra16x16_pred_mode]++;  
  323.                 else if( h->mb.i_type == I_8x8 )  
  324.                     forint i = 0; i < 16; i += 4 )  
  325.                         h->stat.frame.i_mb_pred_mode[1][h->mb.cache.intra4x4_pred_mode[x264_scan8[i]]]++;  
  326.                 else //if( h->mb.i_type == I_4x4 )  
  327.                     forint i = 0; i < 16; i++ )  
  328.                         h->stat.frame.i_mb_pred_mode[2][h->mb.cache.intra4x4_pred_mode[x264_scan8[i]]]++;  
  329.                 h->stat.frame.i_mb_pred_mode[3][x264_mb_chroma_pred_mode_fix[h->mb.i_chroma_pred_mode]]++;  
  330.             }  
  331.             h->stat.frame.i_mb_field[b_intra?0:b_skip?2:1] += MB_INTERLACED;  
  332.         }  
  333.         //===========================================================  
  334.   
  335.         /* calculate deblock strength values (actual deblocking is done per-row along with hpel) */  
  336.         //計算去塊效應濾波器強度Bs  
  337.         //這裏沒有濾波  
  338.         if( b_deblock )  
  339.             x264_macroblock_deblock_strength( h );  
  340.   
  341.         //如果處理完最後一個宏塊,就跳出大循環  
  342.         if( mb_xy == h->sh.i_last_mb )  
  343.             break;  
  344.   
  345.         if( SLICE_MBAFF )  
  346.         {  
  347.             i_mb_x += i_mb_y & 1;  
  348.             i_mb_y ^= i_mb_x < h->mb.i_mb_width;  
  349.         }  
  350.         else  
  351.             i_mb_x++;//宏塊序號x加1  
  352.         //處理完一行宏塊  
  353.         if( i_mb_x == h->mb.i_mb_width )  
  354.         {  
  355.             //該處理下一行了  
  356.             i_mb_y++;//宏塊序號y加1  
  357.             i_mb_x = 0;//宏塊序號x設置爲0  
  358.         }  
  359.     }  
  360.     if( h->sh.i_last_mb < h->sh.i_first_mb )  
  361.         return 0;  
  362.   
  363.     h->out.nal[h->out.i_nal].i_last_mb = h->sh.i_last_mb;  
  364.   
  365.     //熵編碼的收尾工作  
  366.     if( h->param.b_cabac )  
  367.     {  
  368.         x264_cabac_encode_flush( h, &h->cabac );  
  369.         h->out.bs.p = h->cabac.p;  
  370.     }  
  371.     else  
  372.     {  
  373.         if( i_skip > 0 )  
  374.             bs_write_ue( &h->out.bs, i_skip );  /* last skip run */  
  375.         /* rbsp_slice_trailing_bits */  
  376.         bs_rbsp_trailing( &h->out.bs );  
  377.         bs_flush( &h->out.bs );  
  378.     }  
  379.     //結束輸出一個NAL  
  380.     //前面對應着x264_nal_start()  
  381.     if( x264_nal_end( h ) )  
  382.         return -1;  
  383.     //多線程並行處理?  
  384.     if( h->sh.i_last_mb == (h->i_threadslice_end * h->mb.i_mb_width - 1) )  
  385.     {  
  386.         h->stat.frame.i_misc_bits = bs_pos( &h->out.bs )  
  387.                                   + (h->out.i_nal*NALU_OVERHEAD * 8)  
  388.                                   - h->stat.frame.i_tex_bits  
  389.                                   - h->stat.frame.i_mv_bits;  
  390.         x264_fdec_filter_row( h, h->i_threadslice_end, 0 );  
  391.   
  392.         if( h->param.b_sliced_threads )  
  393.         {  
  394.             /* Tell the main thread we're done. */  
  395.             x264_threadslice_cond_broadcast( h, 1 );  
  396.             /* Do hpel now */  
  397.             forint mb_y = h->i_threadslice_start; mb_y <= h->i_threadslice_end; mb_y++ )  
  398.                 x264_fdec_filter_row( h, mb_y, 1 );  
  399.             x264_threadslice_cond_broadcast( h, 2 );  
  400.             /* Do the first row of hpel, now that the previous slice is done */  
  401.             if( h->i_thread_idx > 0 )  
  402.             {  
  403.                 x264_threadslice_cond_wait( h->thread[h->i_thread_idx-1], 2 );  
  404.                 x264_fdec_filter_row( h, h->i_threadslice_start + (1 << SLICE_MBAFF), 2 );  
  405.             }  
  406.         }  
  407.   
  408.         /* Free mb info after the last thread's done using it */  
  409.         if( h->fdec->mb_info_free && (!h->param.b_sliced_threads || h->i_thread_idx == (h->param.i_threads-1)) )  
  410.         {  
  411.             h->fdec->mb_info_free( h->fdec->mb_info );  
  412.             h->fdec->mb_info = NULL;  
  413.             h->fdec->mb_info_free = NULL;  
  414.         }  
  415.     }  
  416.   
  417.     return 0;  
  418. }  

根據源代碼簡單梳理了x264_slice_write()的流程,如下所示:

(1)調用x264_nal_start()開始輸出一個NALU。

(2)x264_macroblock_thread_init():初始化宏塊重建像素緩存fdec_buf[]和編碼像素緩存fenc_buf[]。

(3)調用x264_slice_header_write()輸出 Slice Header。

(4)進入一個循環,該循環每執行一遍編碼一個宏塊:

a) 每處理一行宏塊,調用一次x264_fdec_filter_row()執行濾波模塊。
b) 調用x264_macroblock_cache_load_progressive()將要編碼的宏塊的周圍的宏塊的信息讀進來。
c) 調用x264_macroblock_analyse()執行分析模塊。
d) 調用x264_macroblock_encode()執行宏塊編碼模塊。
e) 調用x264_macroblock_write_cabac()/x264_macroblock_write_cavlc()執行熵編碼模塊。
f) 調用x264_macroblock_cache_save()保存當前宏塊的信息。
g) 調用x264_ratecontrol_mb()執行碼率控制。
h) 準備處理下一個宏塊。
(5)調用x264_nal_end()結束輸出一個NALU。

下文分別從數據結構和函數兩個方面分析x264_slice_write()的源代碼。



重要的數據結構

X264在宏塊編碼方面涉及到下面幾個比較重要的結構體:
宏塊像素存儲緩存fenc_buf[]和fdec_buf[]——位於x264_t.mb.pic中,用於存儲宏塊的亮度和色度像素。
宏塊各種信息的緩存Cache——位於x264_t.mb.pic中,用於存儲宏塊的信息例如4x4幀內預測模式、DCT的非0係數個數、運動矢量、參考幀序號等。
圖像半像素點存儲空間filtered[]——位於x264_frame_t中,用於存儲半像素插值後的點。

宏塊像素存儲緩存fenc_buf[]和fdec_buf[]

fenc_buf[]和fdec_buf[]爲x264_t.mb.cache中的結構體,用於存儲一個宏塊的像素數據。其中fenc_buf[]用於存儲宏塊編碼像素數據,而fdec_buf[]用於存儲宏塊重建像素數據。他們的定義如下所示。
[cpp]  view plain  copy
  1. /* space for p_fenc and p_fdec */  
  2. #define FENC_STRIDE 16  
  3. #define FDEC_STRIDE 32  
  4. //存儲編碼宏塊fenc和重建宏塊fdec的內存  
  5. uint8_t fenc_buf[48*FENC_STRIDE]  
  6. uint8_t fdec_buf[52*FDEC_STRIDE]  
從定義可以看出,fenc_buf[]每行16個數據;而fdec_buf[]每行32個數據。在x264_t.mb.cache中和fenc_buf[]和fdec_buf[]相關的指針數組還有p_fenc[3]和p_fdec[3],它們中的3個元素[0]、[1]、[2]分別指向分別指向對應緩存buf的Y、U、V分量。下圖畫出了像素格式爲YUV420P的時候fenc_buf[]的存儲示意圖。圖中灰色區域存儲Y,藍色區域存儲U,粉紅區域存儲V。p_fenc[0]指向Y的存儲區域,p_fenc[1]指向U的存儲區域,p_fenc[2]指向V的存儲區域,在圖中以方框的形式標註了出來。

下圖畫出了像素格式爲YUV420P的時候fdec_buf[]的存儲示意圖。圖中灰色區域存儲Y,藍色區域存儲U,粉紅區域存儲V。p_fenc[0]指向Y的存儲區域,p_fenc[1]指向U的存儲區域,p_fenc[2]指向V的存儲區域,在圖中以方框的形式標註了出來。

從圖中可以看出,fdec_buf[]和fenc_buf[]主要的區別在於fdec_buf[]像素塊的左邊和上邊包含了左上方相鄰塊用於預測的像素。


宏塊各種信息的緩存Cache 

在x264中x264_t.mb.cache結構體中包含了存儲宏塊信息的各種各樣的緩存Cache。例如:
intra4x4_pred_mode:Intra4x4幀內預測模式的緩存
non_zero_count:DCT的非0係數個數的緩存
mv:運動矢量緩存
ref:運動矢量參考幀的緩存
這幾個Cache的定義如下所示。

[cpp]  view plain  copy
  1. /* 宏塊信息緩存cache */  
  2.         struct  
  3.         {  
  4.             /* real intra4x4_pred_mode if I_4X4 or I_8X8, I_PRED_4x4_DC if mb available, -1 if not */  
  5.             /* 
  6.              * mb.cache.intra4x4_pred_mode[]格式如下 
  7.              *   | 
  8.              * --+-------------- 
  9.              *   | 0 0 0 y y y y y 
  10.              *   | 0 0 0 y Y Y Y Y 
  11.              *   | 0 0 0 y Y Y Y Y 
  12.              *   | 0 0 0 y Y Y Y Y 
  13.              *   | 0 0 0 y Y Y Y Y 
  14.              */  
  15.             ALIGNED_8( int8_t intra4x4_pred_mode[X264_SCAN8_LUMA_SIZE] );  
  16.   
  17.             /* i_non_zero_count if available else 0x80 */  
  18.             /* 
  19.              * mb.cache.non_zero_count[]格式如下 
  20.              *   | 
  21.              * --+-------------- 
  22.              *   | 0 0 0 y y y y y 
  23.              *   | 0 0 0 y Y Y Y Y 
  24.              *   | 0 0 0 y Y Y Y Y 
  25.              *   | 0 0 0 y Y Y Y Y 
  26.              *   | 0 0 0 y Y Y Y Y 
  27.              *   | 0 0 0 u u u u u 
  28.              *   | 0 0 0 u U U U U 
  29.              *   | 0 0 0 u U U U U 
  30.              *   | 0 0 0 u U U U U 
  31.              *   | 0 0 0 u U U U U 
  32.              *   | 0 0 0 v v v v v 
  33.              *   | 0 0 0 v V V V V 
  34.              *   | 0 0 0 v V V V V 
  35.              *   | 0 0 0 v V V V V 
  36.              *   | 0 0 0 v V V V V 
  37.              */  
  38.             ALIGNED_16( uint8_t non_zero_count[X264_SCAN8_SIZE] );  
  39.   
  40.             /* -1 if unused, -2 if unavailable */  
  41.             /* 
  42.              * mb.cache.ref[0][]格式如下 
  43.              *   | 
  44.              * --+-------------- 
  45.              *   | 0 0 0 y y y y y 
  46.              *   | 0 0 0 y Y Y Y Y 
  47.              *   | 0 0 0 y Y Y Y Y 
  48.              *   | 0 0 0 y Y Y Y Y 
  49.              *   | 0 0 0 y Y Y Y Y 
  50.              */  
  51.             ALIGNED_4( int8_t ref[2][X264_SCAN8_LUMA_SIZE] );  
  52.   
  53.             /* 0 if not available */  
  54.             /* 
  55.              * mb.cache.mv[0][]格式如下 
  56.              *   | 
  57.              * --+-------------- 
  58.              *   | 0 0 0 y y y y y 
  59.              *   | 0 0 0 y Y Y Y Y 
  60.              *   | 0 0 0 y Y Y Y Y 
  61.              *   | 0 0 0 y Y Y Y Y 
  62.              *   | 0 0 0 y Y Y Y Y 
  63.              */  
  64.             ALIGNED_16( int16_t mv[2][X264_SCAN8_LUMA_SIZE][2] );  
  65.             ALIGNED_8( uint8_t mvd[2][X264_SCAN8_LUMA_SIZE][2] );  
  66.   
  67.             /* 1 if SKIP or DIRECT. set only for B-frames + CABAC */  
  68.             ALIGNED_4( int8_t skip[X264_SCAN8_LUMA_SIZE] );  
  69.   
  70.             ALIGNED_4( int16_t direct_mv[2][4][2] );  
  71.             ALIGNED_4( int8_t  direct_ref[2][4] );  
  72.             int     direct_partition;  
  73.             ALIGNED_4( int16_t pskip_mv[2] );  
  74.   
  75.             /* number of neighbors (top and left) that used 8x8 dct */  
  76.             int     i_neighbour_transform_size;  
  77.             int     i_neighbour_skip;  
  78.   
  79.             /* neighbor CBPs */  
  80.             int     i_cbp_top;  
  81.             int     i_cbp_left;  
  82.   
  83.             /* extra data required for mbaff in mv prediction */  
  84.             int16_t topright_mv[2][3][2];  
  85.             int8_t  topright_ref[2][3];  
  86.   
  87.             /* current mb deblock strength */  
  88.             uint8_t (*deblock_strength)[8][4];  
  89.         } cache;  

通過觀察上面的定義,會發現Cache都是一個包含x*8個元素的一維數組(x取15或者5)。Cache使用一維數組比較形象的存儲了二維圖像的信息。從上面的代碼可以看出Cache中存儲有效數據的地方是一個位於右下角的「方形區域」,這一部分實際上對應一維數組中第12-15,20-23,28-31,36-39的元素。這個「方形區域」代表了一個宏塊的亮度相關的信息,其中一共包含16個元素。由於1個宏塊的亮度數據是1個16x16的塊,所以這個「方形區域」裏面1個元素實際上代表了一個4x4的塊的信息(「4x4」的亮度塊應該也是H.264壓縮編碼中最小的處理單元)。

如果我們使用12-15,20-23,28-31,36-39這些範圍內的下標引用Cache中的元素,實在是不太方便。由此也引出了x264中另一個關鍵的變量——scan8[]數組。

scan8[]

scan8[]存儲的是緩存的序號值,它一般情況下是與前面提到的Cache配合使用的。scan8[]的定義位於libavcodec\h264.h,如下所示。
[cpp]  view plain  copy
  1. /* Scan8 organization: 
  2.  *    0 1 2 3 4 5 6 7 
  3.  * 0  DY    y y y y y 
  4.  * 1        y Y Y Y Y 
  5.  * 2        y Y Y Y Y 
  6.  * 3        y Y Y Y Y 
  7.  * 4        y Y Y Y Y 
  8.  * 5  DU    u u u u u 
  9.  * 6        u U U U U 
  10.  * 7        u U U U U 
  11.  * 8        u U U U U 
  12.  * 9        u U U U U 
  13.  * 10 DV    v v v v v 
  14.  * 11       v V V V V 
  15.  * 12       v V V V V 
  16.  * 13       v V V V V 
  17.  * 14       v V V V V 
  18.  * DY/DU/DV are for luma/chroma DC. 
  19.  */  
  20. /* 
  21.  * 掃描方式: 
  22.  * o-o o-o 
  23.  *  / / / 
  24.  * o-o o-o 
  25.  *  ,---' 
  26.  * o-o o-o 
  27.  *  / / / 
  28.  * o-o o-o 
  29.  */  
  30. /* 
  31.  * 關於多次出現的scan8 
  32.  * 
  33.  * cache是一個表格。表格中存儲了一整個宏塊的信息,每一個元素代表了一個「4x4塊」(H.264中最小的處理單位)。 
  34.  * scan8[]則存儲了宏塊信息在cache中的索引值 
  35.  * 
  36.  * scan8[]中的「8」,意思應該是按照8x8爲單元來掃描? 
  37.  * 因此可以理解爲「按照8x8爲單元來掃描4x4的塊」? 
  38.  * 
  39.  * scan8中按照順序分別存儲了Y,U,V的索引值。具體的存儲還是在相應的cache中。 
  40.  * 
  41.  * cache中首先存儲Y,然後存儲U和V。cache中的存儲方式如下所示。 
  42.  * 其中數字代表了scan8[]中元素的索引值 
  43.  * 
  44.  * +---+---+---+---+---+---+---+---+---+ 
  45.  * |   | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 
  46.  * +---+---+---+---+---+---+---+---+---+ 
  47.  * | 0 | 48|   |   |   |  y|  y|  y|  y| 
  48.  * | 1 |   |   |   |  y|  0|  1|  4|  5| 
  49.  * | 2 |   |   |   |  y|  2|  3|  6|  7| 
  50.  * | 3 |   |   |   |  y|  8|  9| 12| 13| 
  51.  * | 4 |   |   |   |  y| 10| 11| 14| 15| 
  52.  * | 5 | 49|   |   |   |  u|  u|  u|  u| 
  53.  * | 6 |   |   |   |  u| 16| 17| 20| 21| 
  54.  * | 7 |   |   |   |  u| 18| 19| 22| 23| 
  55.  * | 8 |   |   |   |  u| 24| 25| 28| 29| 
  56.  * | 9 |   |   |   |  u| 26| 27| 30| 31| 
  57.  * |10 | 50|   |   |   |  v|  v|  v|  v| 
  58.  * |11 |   |   |   |  v| 32| 33| 36| 37| 
  59.  * |12 |   |   |   |  v| 34| 35| 38| 39| 
  60.  * |13 |   |   |   |  v| 40| 41| 44| 45| 
  61.  * |14 |   |   |   |  v| 42| 43| 46| 47| 
  62.  * |---+---+---+---+---+---+---+---+---+ 
  63.  * |   | 
  64.  * 
  65.  */  
  66.   
  67. #define LUMA_DC   48  
  68. #define CHROMA_DC 49  
  69.   
  70. static const uint8_t x264_scan8[16*3 + 3] =  
  71. {  
  72.     4+ 1*8, 5+ 1*8, 4+ 2*8, 5+ 2*8,  
  73.     6+ 1*8, 7+ 1*8, 6+ 2*8, 7+ 2*8,  
  74.     4+ 3*8, 5+ 3*8, 4+ 4*8, 5+ 4*8,  
  75.     6+ 3*8, 7+ 3*8, 6+ 4*8, 7+ 4*8,  
  76.     4+ 6*8, 5+ 6*8, 4+ 7*8, 5+ 7*8,  
  77.     6+ 6*8, 7+ 6*8, 6+ 7*8, 7+ 7*8,  
  78.     4+ 8*8, 5+ 8*8, 4+ 9*8, 5+ 9*8,  
  79.     6+ 8*8, 7+ 8*8, 6+ 9*8, 7+ 9*8,  
  80.     4+11*8, 5+11*8, 4+12*8, 5+12*8,  
  81.     6+11*8, 7+11*8, 6+12*8, 7+12*8,  
  82.     4+13*8, 5+13*8, 4+14*8, 5+14*8,  
  83.     6+13*8, 7+13*8, 6+14*8, 7+14*8,  
  84.     0+ 0*8, 0+ 5*8, 0+10*8  
  85. };  

可以看出scan8[]數組中元素的值都是以「a+b*8」的形式寫的,我們不妨計算一下前面16個元素的值:
scan8[0]=12
scan8[1]= 13
scan8[2]= 20
scan8[3]= 21
scan8[4]= 14
scan8[5]= 15
scan8[6]= 22
scan8[7]= 23
scan8[8]= 28
scan8[9]= 29
scan8[10]= 36
scan8[11]= 37
scan8[12]= 30
scan8[13]= 31
scan8[14]= 38
scan8[15]= 39

如果把scan8[]數組這些元素的值,作爲Cache(例如mv[],ref[]等)的序號,會發現他們的在Cache中代表的元素的位置如下圖所示。
 
上圖中灰色背景的元素即爲Cache中有效的元素(不使用左邊的空白區域的元素可能是由於歷史原因)。直接使用Cache元素序號可能感覺比較抽象,下圖使用scan8[]數組元素序號表示Cache中存儲的數據,則結果如下圖所示。
 
圖中每個元素代表了一個4x4的塊的信息,每個由16個元素組成的「大方塊」代表了1個宏塊的1個分量的信息。灰色背景的「大方塊」存儲的是宏塊中亮度Y相關的信息,藍色背景的「大方塊」存儲的是宏塊中色度U相關的信息,粉紅背景的「大方塊」存儲的是宏塊中色度U相關的信息。

PS:有關scan8[]數組在網上能查到一點資料。但是經過源代碼比對之後,我發現網上的資料已經過時了。舊版本scan8[]代表的Cache的存儲方式如下所示。
 
可以看出舊版本的scan8[]中U、V是存儲在Y的左邊的區域,而且每個分量只有4個元素,而新版本的scan8[]中U、V是存儲在Y的下邊的區域,而且每個分量有16個元素。

圖像半像素點存儲緩存filtered[]

X264中在圖像運動搜索的過程中,需要使用1/4像素精度的運動補償。其中半像素點的內插工作是提前完成的。每一幀的半像素點存儲在x264_frame_t的filtered[3][4]變量中。其中前面的「[3]」代表Y,U,V三個分量,後面的「[4]」分別存儲了整像素, H半像素, V半像素, C(對角線)半像素的數據。

下面的圖以4x4圖像塊爲例演示了filtered[][4]中幾種半像素點與整像素點之間的位置關係。圖中灰色的點爲整像素點,黃色的點爲半像素點。filtered[][0]存儲了整像素點數據,filtered[][1]存儲了H半像素點數據,filtered[][2]存儲了V半像素點數據,filtered[][3]存儲了C(對角線)半像素點數據。


重要的函數

下文簡單記錄x264_slice_write()中調用的幾個函數:
x264_macroblock_thread_init():初始化宏塊重建數據緩存fdec_buf[]和編碼數據緩存fenc_buf[]。
x264_slice_header_write():輸出 Slice Header。
x264_macroblock_cache_load():將要編碼的宏塊的周圍的宏塊的信息讀進來。

x264_macroblock_cache_save():保存當前宏塊的信息。

另外還有一些關鍵模塊對應的函數將會在後續文章中進行分析:
x264_fdec_filter_row():濾波模塊。該模塊包含了環路濾波,半像素插值,SSIM/PSNR的計算。
x264_macroblock_analyse():分析模塊。該模塊包含了幀內預測模式分析以及幀間運動估計等。
x264_macroblock_encode():宏塊編碼模塊。該模塊通過對殘差的DCT變換、量化等方式對宏塊進行編碼。
x264_macroblock_write_cabac():CABAC熵編碼模塊。
x264_macroblock_write_cavlc():CAVLC熵編碼模塊。

x264_macroblock_thread_init()

x264_macroblock_thread_init()用於初始化宏塊重建數據緩存fdec_buf[]和編碼數據緩存fenc_buf[]。該函數的定義位於common\macroblock.c,如下所示。
[cpp]  view plain  copy
  1. //存儲宏塊像素的緩存fdec_buf和fenc_buf的初始化  
  2. //設定宏塊編碼緩存p_fenc[0],p_fenc[1],p_fenc[2]  
  3. //設定宏塊重建緩存p_fdec[0],p_fdec[1],p_fdec[2]  
  4. //[0]存Y,[1]存U,[2]存V  
  5. void x264_macroblock_thread_init( x264_t *h )  
  6. {  
  7.     h->mb.i_me_method = h->param.analyse.i_me_method;  
  8.     h->mb.i_subpel_refine = h->param.analyse.i_subpel_refine;  
  9.     if( h->sh.i_type == SLICE_TYPE_B && (h->mb.i_subpel_refine == 6 || h->mb.i_subpel_refine == 8) )  
  10.         h->mb.i_subpel_refine--;  
  11.     h->mb.b_chroma_me = h->param.analyse.b_chroma_me &&  
  12.                         ((h->sh.i_type == SLICE_TYPE_P && h->mb.i_subpel_refine >= 5) ||  
  13.                          (h->sh.i_type == SLICE_TYPE_B && h->mb.i_subpel_refine >= 9));  
  14.     h->mb.b_dct_decimate = h->sh.i_type == SLICE_TYPE_B ||  
  15.                           (h->param.analyse.b_dct_decimate && h->sh.i_type != SLICE_TYPE_I);  
  16.     h->mb.i_mb_prev_xy = -1;  
  17.   
  18.   
  19.     /* 
  20.      * fdec_buf和fenc_buf簡易存儲圖 
  21.      * fdec_buf用於存儲重建幀 
  22.      * fenc_buf用於存儲編碼幀 
  23.      * 
  24.      * 存儲結果如圖所示 
  25.      * fdec_buf用於存儲數據;fdec[0],fdec[1],fdec[2]指向fdec_buf的不同位置 
  26.      *           4:2:0                      4:2:2                      4:4:4 
  27.      * fdec            fenc       fdec            fenc       fdec            fenc 
  28.      * y y y y y y y   Y Y Y Y    y y y y y y y   Y Y Y Y    y y y y y y y   Y Y Y Y 
  29.      * y Y Y Y Y       Y Y Y Y    y Y Y Y Y       Y Y Y Y    y Y Y Y Y       Y Y Y Y 
  30.      * y Y Y Y Y       Y Y Y Y    y Y Y Y Y       Y Y Y Y    y Y Y Y Y       Y Y Y Y 
  31.      * y Y Y Y Y       Y Y Y Y    y Y Y Y Y       Y Y Y Y    y Y Y Y Y       Y Y Y Y 
  32.      * y Y Y Y Y       U U V V    y Y Y Y Y       U U V V    y Y Y Y Y       U U U U 
  33.      * u u u   v v v   U U V V    u u u   v v v   U U V V    u u u u u u u   U U U U 
  34.      * u U U   v V V              u U U   v V V   U U V V    u U U U U       U U U U 
  35.      * u U U   v V V              u U U   v V V   U U V V    u U U U U       U U U U 
  36.      *                            u U U   v V V              u U U U U       V V V V 
  37.      *                            u U U   v V V              u U U U U       V V V V 
  38.      *                                                       v v v v v v v   V V V V 
  39.      *                                                       v V V V V       V V V V 
  40.      *                                                       v V V V V 
  41.      *                                                       v V V V V 
  42.      *                                                       v V V V V 
  43.      * 
  44.      * fdec_buf詳細存儲示例(YUV420P) 
  45.      * y、u、v爲預測要用到的數據 
  46.      * Y、U、V爲像素數據 
  47.      * 每行32像素 
  48.      * 
  49.      * p_fdec[0] = fdec_buf + 2*32; 
  50.      * p_fenc[1] = fenc_buf + 19*32; 
  51.      * p_fenc[2] = fenc_buf + 19*32+16; 
  52.      * 
  53.      * 
  54.      * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 y 
  55.      * y y y y y y y y y y y y y y y y 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 y 
  56.      * Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 y 
  57.      * Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 y 
  58.      * Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 y 
  59.      * Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 y 
  60.      *                              ... 
  61.      *                              Y一共16行 
  62.      *                              ... 
  63.      * Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 y 
  64.      * Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 y 
  65.      * Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 u 
  66.      * u u u u u u u u 0 0 0 0 0 0 0 v v v v v v v v v 0 0 0 0 0 0 0 u 
  67.      * U U U U U U U U 0 0 0 0 0 0 0 v V V V V V V V V 0 0 0 0 0 0 0 u 
  68.      * U U U U U U U U 0 0 0 0 0 0 0 v V V V V V V V V 0 0 0 0 0 0 0 u 
  69.      * U U U U U U U U 0 0 0 0 0 0 0 v V V V V V V V V 0 0 0 0 0 0 0 u 
  70.      * U U U U U U U U 0 0 0 0 0 0 0 v V V V V V V V V 0 0 0 0 0 0 0 u 
  71.      *                              ... 
  72.      *                              UV一共8行 
  73.      *                              ... 
  74.      * 
  75.      * ============================================================================= 
  76.      * 
  77.      * fenc_buf詳細存儲示例(YUV420P) 
  78.      * Y、U、V爲像素數據 
  79.      * 每行16像素 
  80.      * 
  81.      * p_fdec[0] = fdec_buf + 0; 
  82.      * p_fenc[1] = fenc_buf + 16*32; 
  83.      * p_fenc[2] = fenc_buf + 16*32+8; 
  84.      * 
  85.      * Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
  86.      * Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
  87.      * Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
  88.      * Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
  89.      *            ... 
  90.      *          Y一共16行 
  91.      *            ... 
  92.      * Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
  93.      * Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
  94.      * Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
  95.      * U U U U U U U U V V V V V V V V 
  96.      * U U U U U U U U V V V V V V V V 
  97.      * U U U U U U U U V V V V V V V V 
  98.      * U U U U U U U U V V V V V V V V 
  99.      *            ... 
  100.      *          UV一共8行 
  101.      *            ... 
  102.      */  
  103.   
  104.     //fenc(編碼幀)結構比較簡單,Y、U、V像素「挨着」存放  
  105.     h->mb.pic.p_fenc[0] = h->mb.pic.fenc_buf;  
  106.     //fdec(重建幀)結構比較複雜,需要當前宏塊左邊以及上邊宏塊的信息  
  107.     //第1行爲空,第2行用於存儲上邊宏塊下邊緣的像素  
  108.     h->mb.pic.p_fdec[0] = h->mb.pic.fdec_buf + 2*FDEC_STRIDE;  
  109.   
  110.     //U  
  111.     h->mb.pic.p_fenc[1] = h->mb.pic.fenc_buf + 16*FENC_STRIDE;  
  112.     h->mb.pic.p_fdec[1] = h->mb.pic.fdec_buf + 19*FDEC_STRIDE;  
  113.   
  114.     //V  
  115.     if( CHROMA444 )  
  116.     {  
  117.         h->mb.pic.p_fenc[2] = h->mb.pic.fenc_buf + 32*FENC_STRIDE;  
  118.         h->mb.pic.p_fdec[2] = h->mb.pic.fdec_buf + 36*FDEC_STRIDE;  
  119.     }  
  120.     else  
  121.     {  
  122.         //注意+8和+16  
  123.         h->mb.pic.p_fenc[2] = h->mb.pic.fenc_buf + 16*FENC_STRIDE + 8;  
  124.         h->mb.pic.p_fdec[2] = h->mb.pic.fdec_buf + 19*FDEC_STRIDE + 16;  
  125.     }  
  126. }  

從源代碼可以看出,x264_macroblock_thread_init()設定了宏塊編碼數據指針p_fenc[0],p_fenc[1],p_fenc[2]在fenc_buf[]中的位置,以及宏塊重建數據指針p_fdec[0],p_fdec[1],p_fdec[2] 在fdec_buf[]中的位置。由於前文中已經介紹過fenc_buf[]和fdec_buf[]的結構,在這裏不再重複。

x264_slice_header_write()

x264_slice_header_write()用於輸出Slice Header。該函數的定義位於encoder\encoder.c,如下所示。
[cpp]  view plain  copy
  1. //輸出 slice header  
  2. static void x264_slice_header_write( bs_t *s, x264_slice_header_t *sh, int i_nal_ref_idc )  
  3. {  
  4.     if( sh->b_mbaff )  
  5.     {  
  6.         int first_x = sh->i_first_mb % sh->sps->i_mb_width;  
  7.         int first_y = sh->i_first_mb / sh->sps->i_mb_width;  
  8.         assert( (first_y&1) == 0 );  
  9.         bs_write_ue( s, (2*first_x + sh->sps->i_mb_width*(first_y&~1) + (first_y&1)) >> 1 );  
  10.     }  
  11.     else  
  12.         bs_write_ue( s, sh->i_first_mb );//first_mb_in_slice: Slice中的第一個宏塊的地址  
  13.     //slice_type: Slice類型(I,B,P,SI,SP)  
  14.     bs_write_ue( s, sh->i_type + 5 );   /* same type things */  
  15.     //pic_parameter_set_id: PPS的索引號  
  16.     bs_write_ue( s, sh->i_pps_id );  
  17.     //frame_num: 指明瞭各圖像的解碼順序  
  18.     bs_write( s, sh->sps->i_log2_max_frame_num, sh->i_frame_num & ((1<<sh->sps->i_log2_max_frame_num)-1) );  
  19.   
  20.     if( !sh->sps->b_frame_mbs_only )  
  21.     {  
  22.         bs_write1( s, sh->b_field_pic );  
  23.         if( sh->b_field_pic )  
  24.             bs_write1( s, sh->b_bottom_field );  
  25.     }  
  26.   
  27.     if( sh->i_idr_pic_id >= 0 ) /* NAL IDR */  
  28.         bs_write_ue( s, sh->i_idr_pic_id );//idr_pic_id: IDR圖像的標識  
  29.   
  30.     if( sh->sps->i_poc_type == 0 )  
  31.     {  
  32.         bs_write( s, sh->sps->i_log2_max_poc_lsb, sh->i_poc & ((1<<sh->sps->i_log2_max_poc_lsb)-1) );  
  33.         if( sh->pps->b_pic_order && !sh->b_field_pic )  
  34.             bs_write_se( s, sh->i_delta_poc_bottom );  
  35.     }  
  36.   
  37.     if( sh->pps->b_redundant_pic_cnt )  
  38.         bs_write_ue( s, sh->i_redundant_pic_cnt );  
  39.   
  40.     if( sh->i_type == SLICE_TYPE_B )  
  41.         bs_write1( s, sh->b_direct_spatial_mv_pred );  
  42.   
  43.     if( sh->i_type == SLICE_TYPE_P || sh->i_type == SLICE_TYPE_B )  
  44.     {  
  45.         bs_write1( s, sh->b_num_ref_idx_override );  
  46.         if( sh->b_num_ref_idx_override )  
  47.         {  
  48.             bs_write_ue( s, sh->i_num_ref_idx_l0_active - 1 );  
  49.             if( sh->i_type == SLICE_TYPE_B )  
  50.                 bs_write_ue( s, sh->i_num_ref_idx_l1_active - 1 );  
  51.         }  
  52.     }  
  53.   
  54.     /* ref pic list reordering */  
  55.     if( sh->i_type != SLICE_TYPE_I )  
  56.     {  
  57.         bs_write1( s, sh->b_ref_pic_list_reordering[0] );  
  58.         if( sh->b_ref_pic_list_reordering[0] )  
  59.         {  
  60.             forint i = 0; i < sh->i_num_ref_idx_l0_active; i++ )  
  61.             {  
  62.                 bs_write_ue( s, sh->ref_pic_list_order[0][i].idc );  
  63.                 bs_write_ue( s, sh->ref_pic_list_order[0][i].arg );  
  64.             }  
  65.             bs_write_ue( s, 3 );  
  66.         }  
  67.     }  
  68.     if( sh->i_type == SLICE_TYPE_B )  
  69.     {  
  70.         bs_write1( s, sh->b_ref_pic_list_reordering[1] );  
  71.         if( sh->b_ref_pic_list_reordering[1] )  
  72.         {  
  73.             forint i = 0; i < sh->i_num_ref_idx_l1_active; i++ )  
  74.             {  
  75.                 bs_write_ue( s, sh->ref_pic_list_order[1][i].idc );  
  76.                 bs_write_ue( s, sh->ref_pic_list_order[1][i].arg );  
  77.             }  
  78.             bs_write_ue( s, 3 );  
  79.         }  
  80.     }  
  81.   
  82.     sh->b_weighted_pred = 0;  
  83.     if( sh->pps->b_weighted_pred && sh->i_type == SLICE_TYPE_P )  
  84.     {  
  85.         sh->b_weighted_pred = sh->weight[0][0].weightfn || sh->weight[0][1].weightfn || sh->weight[0][2].weightfn;  
  86.         /* pred_weight_table() */  
  87.         bs_write_ue( s, sh->weight[0][0].i_denom );  
  88.         bs_write_ue( s, sh->weight[0][1].i_denom );  
  89.         forint i = 0; i < sh->i_num_ref_idx_l0_active; i++ )  
  90.         {  
  91.             int luma_weight_l0_flag = !!sh->weight[i][0].weightfn;  
  92.             int chroma_weight_l0_flag = !!sh->weight[i][1].weightfn || !!sh->weight[i][2].weightfn;  
  93.             bs_write1( s, luma_weight_l0_flag );  
  94.             if( luma_weight_l0_flag )  
  95.             {  
  96.                 bs_write_se( s, sh->weight[i][0].i_scale );  
  97.                 bs_write_se( s, sh->weight[i][0].i_offset );  
  98.             }  
  99.             bs_write1( s, chroma_weight_l0_flag );  
  100.             if( chroma_weight_l0_flag )  
  101.             {  
  102.                 forint j = 1; j < 3; j++ )  
  103.                 {  
  104.                     bs_write_se( s, sh->weight[i][j].i_scale );  
  105.                     bs_write_se( s, sh->weight[i][j].i_offset );  
  106.                 }  
  107.             }  
  108.         }  
  109.     }  
  110.     else if( sh->pps->b_weighted_bipred == 1 && sh->i_type == SLICE_TYPE_B )  
  111.     {  
  112.       /* TODO */  
  113.     }  
  114.   
  115.     if( i_nal_ref_idc != 0 )  
  116.     {  
  117.         if( sh->i_idr_pic_id >= 0 )  
  118.         {  
  119.             bs_write1( s, 0 );  /* no output of prior pics flag */  
  120.             bs_write1( s, 0 );  /* long term reference flag */  
  121.         }  
  122.         else  
  123.         {  
  124.             bs_write1( s, sh->i_mmco_command_count > 0 ); /* adaptive_ref_pic_marking_mode_flag */  
  125.             if( sh->i_mmco_command_count > 0 )  
  126.             {  
  127.                 forint i = 0; i < sh->i_mmco_command_count; i++ )  
  128.                 {  
  129.                     bs_write_ue( s, 1 ); /* mark short term ref as unused */  
  130.                     bs_write_ue( s, sh->mmco[i].i_difference_of_pic_nums - 1 );  
  131.                 }  
  132.                 bs_write_ue( s, 0 ); /* end command list */  
  133.             }  
  134.         }  
  135.     }  
  136.   
  137.     if( sh->pps->b_cabac && sh->i_type != SLICE_TYPE_I )  
  138.         bs_write_ue( s, sh->i_cabac_init_idc );  
  139.   
  140.     //slice_qp_delta: 指出在用於當前片的所有宏塊的量化參數的初始值  
  141.     //SliceQP = 26 + pic_init_qp_minus26 + slice_qp_delta  
  142.     bs_write_se( s, sh->i_qp_delta );      /* slice qp delta */  
  143.   
  144.     if( sh->pps->b_deblocking_filter_control )  
  145.     {  
  146.         bs_write_ue( s, sh->i_disable_deblocking_filter_idc );  
  147.         if( sh->i_disable_deblocking_filter_idc != 1 )  
  148.         {  
  149.             bs_write_se( s, sh->i_alpha_c0_offset >> 1 );  
  150.             bs_write_se( s, sh->i_beta_offset >> 1 );  
  151.         }  
  152.     }  
  153. }  

有關x264_slice_header_write()的源代碼不再做詳細的分析。其中Slice Header的結構參考《H.264標準》即可。


x264_fdec_filter_row()

x264_fdec_filter_row()屬於濾波模塊,完成幾種濾波工作:
(1)半像素內插
(2)環路濾波
(3)PSNR/SSIM計算
下面簡單記錄一下半像素內插和環路濾波的概念(後續文章再對源代碼進行分析)。

(1)半像素插值知識簡述

簡單記錄一下半像素插值的知識。《H.264標準》中規定,運動估計爲1/4像素精度。因此在H.264編碼和解碼的過程中,需要將畫面中的像素進行插值——簡單地說就是把原先的1個像素點拓展成4x4一共16個點。下圖顯示了H.264編碼和解碼過程中像素插值情況。可以看出原先的G點的右下方通過插值的方式產生了a、b、c、d等一共16個點。
 
如圖所示,1/4像素內插一般分成兩步:
(1)半像素內插。這一步通過6抽頭濾波器獲得5個半像素點。
(2)線性內插。這一步通過簡單的線性內插獲得剩餘的1/4像素點。
圖中半像素內插點爲b、m、h、s、j五個點。半像素內插方法是對整像素點進行6 抽頭濾波得出,濾波器的權重爲(1/32, -5/32, 5/8, 5/8, -5/32, 1/32)。例如b的計算公式爲:
b=round( (E - 5F + 20G + 20H - 5I + J ) / 32)
剩下幾個半像素點的計算關係如下:
m:由B、D、H、N、S、U計算
h:由A、C、G、M、R、T計算
s:由K、L、M、N、P、Q計算
j:由cc、dd、h、m、ee、ff計算。需要注意j點的運算量比較大,因爲cc、dd、ee、ff都需要通過半像素內插方法進行計算。

在獲得半像素點之後,就可以通過簡單的線性內插獲得1/4像素內插點了。1/4像素內插的方式如下圖所示。例如圖中a點的計算公式如下:

A=round( (G+b)/2 )

在這裏有一點需要注意:位於4個角的e、g、p、r四個點並不是通過j點計算計算的,而是通過b、h、s、m四個半像素點計算的。


(2)環路濾波相關知識簡述

簡單記錄一下環路濾波(去塊效應濾波)的知識。X264的重建幀(通過解碼得到)一般情況下會出現方塊效應。產生這種效應的原因主要有兩個:
(1)DCT變換後的量化造成誤差(主要原因)。
(2)運動補償
正是由於這種塊效應的存在,才需要添加環路濾波器調整相鄰的「塊」邊緣上的像素值以減輕這種視覺上的不連續感。下面一張圖顯示了環路濾波的效果。圖中左邊的圖沒有使用環路濾波,而右邊的圖使用了環路濾波。

環路濾波分類

環路濾波器根據濾波的強度可以分爲兩種:
(1)普通濾波器。針對邊界的Bs(邊界強度)爲1、2、3的濾波器。此時環路濾波涉及到方塊邊界周圍的6個點(邊界兩邊各3個點):p2,p1,p0,q0,q1,q2。需要處理4個點(邊界兩邊各2個點,只以p點爲例):
p0’ = p0 + (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3
p1’ = ( p2 + ( ( p0 + q0 + 1 ) >> 1) – 2p1 ) >> 1

(2)強濾波器。針對邊界的Bs(邊界強度)爲4的濾波器。此時環路濾波涉及到方塊邊界周圍的8個點(邊界兩邊各4個點):p3,p2,p1,p0,q0,q1,q2,q3。需要處理6個點(邊界兩邊各3個點,只以p點爲例):
p0’ = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3
p1’ = ( p2 + p1 + p0 + q0 + 2 ) >> 2
p2’ = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3

其中上文中提到的邊界強度Bs的判定方式如下。

條件(針對兩邊的圖像塊)

Bs

有一個塊爲幀內預測 + 邊界爲宏塊邊界

4

有一個塊爲幀內預測

3

有一個塊對殘差編碼

2

運動矢量差不小於1像素

1

運動補償參考幀不同

1

其它

0


總體說來,與幀內預測相關的圖像塊(幀內預測塊)的邊界強度比較大,取值爲3或者4;與運動補償相關的圖像塊(幀間預測塊)的邊界強度比較小,取值爲1。

環路濾波的門限

並不是所有的塊的邊界處都需要環路濾波。例如畫面中物體的邊界正好和塊的邊界重合的話,就不能進行濾波,否則會使畫面中物體的邊界變模糊。因此需要區別開物體邊界和塊效應邊界。一般情況下,物體邊界兩邊的像素值差別很大,而塊效應邊界兩邊像素值差別比較小。《H.264標準》以這個特點定義了2個變量alpha和beta來判決邊界是否需要進行環路濾波。只有滿足下面三個條件的時候才能進行環路濾波:
| p0 - q0 | < alpha
| p1 – p0 | < beta
| q1 - q0 | < beta
簡而言之,就是邊界兩邊的兩個點的像素值不能太大,即不能超過alpha;邊界一邊的前兩個點之間的像素值也不能太大,即不能超過beta。其中alpha和beta是根據量化參數QP推算出來(具體方法不再記錄)。總體說來QP越大,alpha和beta的值也越大,也就越容易觸發環路濾波。由於QP越大表明壓縮的程度越大,所以也可以得知高壓縮比的情況下更需要進行環路濾波。


x264_macroblock_cache_load()

x264_slice_write()根據是否包含隔行掃描,會分別調用x264_macroblock_cache_load_progressive()或者x264_macroblock_cache_load_interlaced()加載當前宏塊的周邊宏塊的信息。這兩個函數都會調用同一個函數x264_macroblock_cache_load()。上述兩個函數的定義位於common\macroblock.c,如下所示。
[cpp]  view plain  copy
  1. //加載Cache-逐行掃描  
  2. //即將要編碼的宏塊的周圍的宏塊的值讀進來  
  3. void x264_macroblock_cache_load_progressive( x264_t *h, int mb_x, int mb_y )  
  4. {  
  5.     x264_macroblock_cache_load( h, mb_x, mb_y, 0 );  
  6. }  
  7. //加載Cache-隔行掃描  
  8. void x264_macroblock_cache_load_interlaced( x264_t *h, int mb_x, int mb_y )  
  9. {  
  10.     x264_macroblock_cache_load( h, mb_x, mb_y, 1 );  
  11. }  

x264_macroblock_cache_load()的定義位於common\macroblock.c,如下所示。
[cpp]  view plain  copy
  1. //加載Cache  
  2. //即將要編碼的宏塊的周圍的宏塊的值讀進來  
  3. static void ALWAYS_INLINE x264_macroblock_cache_load( x264_t *h, int mb_x, int mb_y, int b_mbaff )  
  4. {  
  5.     x264_macroblock_cache_load_neighbours( h, mb_x, mb_y, b_mbaff );  
  6.   
  7.     //左邊宏塊  
  8.     int *left = h->mb.i_mb_left_xy;  
  9.     //上邊宏塊  
  10.     int top  = h->mb.i_mb_top_xy;  
  11.     int top_y = h->mb.i_mb_top_y;  
  12.     int s8x8 = h->mb.i_b8_stride;  
  13.     int s4x4 = h->mb.i_b4_stride;  
  14.     int top_8x8 = (2*top_y+1) * s8x8 + 2*mb_x;  
  15.     int top_4x4 = (4*top_y+3) * s4x4 + 4*mb_x;  
  16.     int lists = (1 << h->sh.i_type) & 3;  
  17.   
  18.     /* GCC pessimizes direct loads from heap-allocated arrays due to aliasing. */  
  19.     /* By only dereferencing them once, we avoid this issue. */  
  20.     int8_t (*i4x4)[8] = h->mb.intra4x4_pred_mode;  
  21.     //DCT非0係數個數  
  22.     uint8_t (*nnz)[48] = h->mb.non_zero_count;  
  23.     //CBP值  
  24.     int16_t *cbp = h->mb.cbp;  
  25.   
  26.     const x264_left_table_t *left_index_table = h->mb.left_index_table;  
  27.   
  28.     h->mb.cache.deblock_strength = h->deblock_strength[mb_y&1][h->param.b_sliced_threads?h->mb.i_mb_xy:mb_x];  
  29.   
  30.     /* 
  31.      * 
  32.      * 關於多次出現的scan8 
  33.      * 
  34.      * scan8是和cache配合使用的 
  35.      * cache是一個表格。表格中存儲了一整個宏塊的信息,每一個元素代表了一個「4x4亮度塊」(H.264中最小的亮度處理單位)。 
  36.      * scan8[]則存儲了宏塊信息在cache中的索引值 
  37.      * 
  38.      * scan8[]中的「8」,意思應該是按照8x8爲單元來掃描? 
  39.      * 因此可以理解爲「按照8x8爲單元來掃描4x4的塊」? 
  40.      * 
  41.      * scan8中按照順序分別存儲了Y,U,V信息在cache中的索引值。具體的存儲還是在相應的cache中。 
  42.      * 
  43.      * cache中首先存儲Y,然後存儲U和V。cache中的存儲方式如下所示。 
  44.      * 其中數字代表了scan8[]中元素的索引值 
  45.      * 
  46.      * +---+---+---+---+---+---+---+---+---+ 
  47.      * |   | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 
  48.      * +---+---+---+---+---+---+---+---+---+ 
  49.      * | 0 | 48|   |   |   |  y|  y|  y|  y| 
  50.      * | 1 |   |   |   |  y|  0|  1|  4|  5| 
  51.      * | 2 |   |   |   |  y|  2|  3|  6|  7| 
  52.      * | 3 |   |   |   |  y|  8|  9| 12| 13| 
  53.      * | 4 |   |   |   |  y| 10| 11| 14| 15| 
  54.      * | 5 | 49|   |   |   |  u|  u|  u|  u| 
  55.      * | 6 |   |   |   |  u| 16| 17| 20| 21| 
  56.      * | 7 |   |   |   |  u| 18| 19| 22| 23| 
  57.      * | 8 |   |   |   |  u| 24| 25| 28| 29| 
  58.      * | 9 |   |   |   |  u| 26| 27| 30| 31| 
  59.      * |10 | 50|   |   |   |  v|  v|  v|  v| 
  60.      * |11 |   |   |   |  v| 32| 33| 36| 37| 
  61.      * |12 |   |   |   |  v| 34| 35| 38| 39| 
  62.      * |13 |   |   |   |  v| 40| 41| 44| 45| 
  63.      * |14 |   |   |   |  v| 42| 43| 46| 47| 
  64.      * |---+---+---+---+---+---+---+---+---+ 
  65.      * |   | 
  66.      * 
  67.      * 掃描方式: 
  68.      * o-o o-o 
  69.      *  / / / 
  70.      * o-o o-o 
  71.      *  ,---' 
  72.      * o-o o-o 
  73.      *  / / / 
  74.      * o-o o-o 
  75.      * 
  76.      */  
  77.   
  78.     /* load cache */  
  79.     if( h->mb.i_neighbour & MB_TOP )  
  80.     {  
  81.         h->mb.cache.i_cbp_top = cbp[top];  
  82.         /* load intra4x4 */  
  83.         /* 
  84.          * 填充intra4x4_pred_mode[] 
  85.          * 在這裏相當於在intra4x4_pred_mode[]填充了「y」,如下所示(沒有U、V) 
  86.          *   | 
  87.          * --+-------------- 
  88.          *   | 0 0 0 0 y y y y 
  89.          *   | 0 0 0 0 Y Y Y Y 
  90.          *   | 0 0 0 0 Y Y Y Y 
  91.          *   | 0 0 0 0 Y Y Y Y 
  92.          *   | 0 0 0 0 Y Y Y Y 
  93.          */  
  94.         CP32( &h->mb.cache.intra4x4_pred_mode[x264_scan8[0] - 8], &i4x4[top][0] );  
  95.   
  96.         /* load non_zero_count */  
  97.         /* 
  98.          * 填充non_zero_count[] 
  99.          * 在這裏相當於在non_zero_count[]填充了「y」,如下所示(只列出了Y。U、V是類似的) 
  100.          *   | 
  101.          * --+-------------- 
  102.          *   | 0 0 0 0 y y y y 
  103.          *   | 0 0 0 0 Y Y Y Y 
  104.          *   | 0 0 0 0 Y Y Y Y 
  105.          *   | 0 0 0 0 Y Y Y Y 
  106.          *   | 0 0 0 0 Y Y Y Y 
  107.          */  
  108.         CP32( &h->mb.cache.non_zero_count[x264_scan8[ 0] - 8], &nnz[top][12] ); //Y  
  109.         CP32( &h->mb.cache.non_zero_count[x264_scan8[16] - 8], &nnz[top][16-4 + (16>>CHROMA_V_SHIFT)] ); //U  
  110.         CP32( &h->mb.cache.non_zero_count[x264_scan8[32] - 8], &nnz[top][32-4 + (16>>CHROMA_V_SHIFT)] ); //V  
  111.   
  112.         /* Finish the prefetching */  
  113.         forint l = 0; l < lists; l++ )  
  114.         {  
  115.             x264_prefetch( &h->mb.mv[l][top_4x4-1] );  
  116.             /* Top right being not in the same cacheline as top left will happen 
  117.              * once every 4 MBs, so one extra prefetch is worthwhile */  
  118.             x264_prefetch( &h->mb.mv[l][top_4x4+4] );  
  119.             x264_prefetch( &h->mb.ref[l][top_8x8-1] );  
  120.             x264_prefetch( &h->mb.mvd[l][top] );  
  121.         }  
  122.     }  
  123.     else  
  124.     {  
  125.         //沒有相關信息的時候,填充下列數據  
  126.   
  127.         h->mb.cache.i_cbp_top = -1;  
  128.   
  129.         /* load intra4x4 */  
  130.         M32( &h->mb.cache.intra4x4_pred_mode[x264_scan8[0] - 8] ) = 0xFFFFFFFFU;  
  131.   
  132.         /* load non_zero_count */  
  133.         M32( &h->mb.cache.non_zero_count[x264_scan8[ 0] - 8] ) = 0x80808080U;  
  134.         M32( &h->mb.cache.non_zero_count[x264_scan8[16] - 8] ) = 0x80808080U;  
  135.         M32( &h->mb.cache.non_zero_count[x264_scan8[32] - 8] ) = 0x80808080U;  
  136.     }  
  137.   
  138.     if( h->mb.i_neighbour & MB_LEFT )  
  139.     {  
  140.         int ltop = left[LTOP];  
  141.         int lbot = b_mbaff ? left[LBOT] : ltop;  
  142.         if( b_mbaff )  
  143.         {  
  144.             const int16_t top_luma = (cbp[ltop] >> (left_index_table->mv[0]&(~1))) & 2;  
  145.             const int16_t bot_luma = (cbp[lbot] >> (left_index_table->mv[2]&(~1))) & 2;  
  146.             h->mb.cache.i_cbp_left = (cbp[ltop] & 0xfff0) | (bot_luma<<2) | top_luma;  
  147.         }  
  148.         else  
  149.             h->mb.cache.i_cbp_left = cbp[ltop];  
  150.   
  151.         /* load intra4x4 */  
  152.         /* 
  153.          * 填充intra4x4_pred_mode[] 
  154.          * 在這裏相當於在intra4x4_pred_mode[]填充了「y」,如下所示(沒有U、V) 
  155.          *   | 
  156.          * --+-------------- 
  157.          *   | 0 0 0 0 0 0 0 0 
  158.          *   | 0 0 0 y Y Y Y Y 
  159.          *   | 0 0 0 y Y Y Y Y 
  160.          *   | 0 0 0 y Y Y Y Y 
  161.          *   | 0 0 0 y Y Y Y Y 
  162.          */  
  163.         h->mb.cache.intra4x4_pred_mode[x264_scan8[ 0] - 1] = i4x4[ltop][left_index_table->intra[0]];  
  164.         h->mb.cache.intra4x4_pred_mode[x264_scan8[ 2] - 1] = i4x4[ltop][left_index_table->intra[1]];  
  165.         h->mb.cache.intra4x4_pred_mode[x264_scan8[ 8] - 1] = i4x4[lbot][left_index_table->intra[2]];  
  166.         h->mb.cache.intra4x4_pred_mode[x264_scan8[10] - 1] = i4x4[lbot][left_index_table->intra[3]];  
  167.   
  168.         /* load non_zero_count */  
  169.         /* 
  170.          * 填充non_zero_count[] 
  171.          * 在這裏相當於在non_zero_count[]填充了「y」,如下所示(只列出了Y,U、V是類似的) 
  172.          *   | 
  173.          * --+-------------- 
  174.          *   | 0 0 0 0 0 0 0 0 
  175.          *   | 0 0 0 y Y Y Y Y 
  176.          *   | 0 0 0 y Y Y Y Y 
  177.          *   | 0 0 0 y Y Y Y Y 
  178.          *   | 0 0 0 y Y Y Y Y 
  179.          */  
  180.         h->mb.cache.non_zero_count[x264_scan8[ 0] - 1] = nnz[ltop][left_index_table->nnz[0]];  
  181.         h->mb.cache.non_zero_count[x264_scan8[ 2] - 1] = nnz[ltop][left_index_table->nnz[1]];  
  182.         h->mb.cache.non_zero_count[x264_scan8[ 8] - 1] = nnz[lbot][left_index_table->nnz[2]];  
  183.         h->mb.cache.non_zero_count[x264_scan8[10] - 1] = nnz[lbot][left_index_table->nnz[3]];  
  184.   
  185.         if( CHROMA_FORMAT >= CHROMA_422 )  
  186.         {  
  187.             int offset = (4>>CHROMA_H_SHIFT) - 4;  
  188.             h->mb.cache.non_zero_count[x264_scan8[16+ 0] - 1] = nnz[ltop][left_index_table->nnz[0]+16+offset];  
  189.             h->mb.cache.non_zero_count[x264_scan8[16+ 2] - 1] = nnz[ltop][left_index_table->nnz[1]+16+offset];  
  190.             h->mb.cache.non_zero_count[x264_scan8[16+ 8] - 1] = nnz[lbot][left_index_table->nnz[2]+16+offset];  
  191.             h->mb.cache.non_zero_count[x264_scan8[16+10] - 1] = nnz[lbot][left_index_table->nnz[3]+16+offset];  
  192.             h->mb.cache.non_zero_count[x264_scan8[32+ 0] - 1] = nnz[ltop][left_index_table->nnz[0]+32+offset];  
  193.             h->mb.cache.non_zero_count[x264_scan8[32+ 2] - 1] = nnz[ltop][left_index_table->nnz[1]+32+offset];  
  194.             h->mb.cache.non_zero_count[x264_scan8[32+ 8] - 1] = nnz[lbot][left_index_table->nnz[2]+32+offset];  
  195.             h->mb.cache.non_zero_count[x264_scan8[32+10] - 1] = nnz[lbot][left_index_table->nnz[3]+32+offset];  
  196.         }  
  197.         else  
  198.         {  
  199.             h->mb.cache.non_zero_count[x264_scan8[16+ 0] - 1] = nnz[ltop][left_index_table->nnz_chroma[0]];  
  200.             h->mb.cache.non_zero_count[x264_scan8[16+ 2] - 1] = nnz[lbot][left_index_table->nnz_chroma[1]];  
  201.             h->mb.cache.non_zero_count[x264_scan8[32+ 0] - 1] = nnz[ltop][left_index_table->nnz_chroma[2]];  
  202.             h->mb.cache.non_zero_count[x264_scan8[32+ 2] - 1] = nnz[lbot][left_index_table->nnz_chroma[3]];  
  203.         }  
  204.     }  
  205.     else  
  206.     {  
  207.         //沒有相關信息的時候,填充下列數據  
  208.   
  209.         h->mb.cache.i_cbp_left = -1;  
  210.   
  211.         h->mb.cache.intra4x4_pred_mode[x264_scan8[ 0] - 1] =  
  212.         h->mb.cache.intra4x4_pred_mode[x264_scan8[ 2] - 1] =  
  213.         h->mb.cache.intra4x4_pred_mode[x264_scan8[ 8] - 1] =  
  214.         h->mb.cache.intra4x4_pred_mode[x264_scan8[10] - 1] = -1;  
  215.   
  216.         /* load non_zero_count */  
  217.         h->mb.cache.non_zero_count[x264_scan8[ 0] - 1] =  
  218.         h->mb.cache.non_zero_count[x264_scan8[ 2] - 1] =  
  219.         h->mb.cache.non_zero_count[x264_scan8[ 8] - 1] =  
  220.         h->mb.cache.non_zero_count[x264_scan8[10] - 1] =  
  221.         h->mb.cache.non_zero_count[x264_scan8[16+ 0] - 1] =  
  222.         h->mb.cache.non_zero_count[x264_scan8[16+ 2] - 1] =  
  223.         h->mb.cache.non_zero_count[x264_scan8[32+ 0] - 1] =  
  224.         h->mb.cache.non_zero_count[x264_scan8[32+ 2] - 1] = 0x80;  
  225.         if( CHROMA_FORMAT >= CHROMA_422 )  
  226.         {  
  227.             h->mb.cache.non_zero_count[x264_scan8[16+ 8] - 1] =  
  228.             h->mb.cache.non_zero_count[x264_scan8[16+10] - 1] =  
  229.             h->mb.cache.non_zero_count[x264_scan8[32+ 8] - 1] =  
  230.             h->mb.cache.non_zero_count[x264_scan8[32+10] - 1] = 0x80;  
  231.         }  
  232.     }  
  233.   
  234.     if( h->pps->b_transform_8x8_mode )  
  235.     {  
  236.         h->mb.cache.i_neighbour_transform_size =  
  237.             ( (h->mb.i_neighbour & MB_LEFT) && h->mb.mb_transform_size[left[0]] )  
  238.           + ( (h->mb.i_neighbour & MB_TOP) && h->mb.mb_transform_size[top]  );  
  239.     }  
  240.   
  241.     if( b_mbaff )  
  242.     {  
  243.         h->mb.pic.i_fref[0] = h->i_ref[0] << MB_INTERLACED;  
  244.         h->mb.pic.i_fref[1] = h->i_ref[1] << MB_INTERLACED;  
  245.     }  
  246.   
  247.     if( !b_mbaff )  
  248.     {  
  249.         //沒有「宏塊級幀場自適應」情況的時候  
  250.   
  251.         //亮度  
  252.         //拷貝上一個宏塊最右邊一列(共16個)像素(p_fdec[0]+15)  
  253.         //作爲這一個宏塊最左邊再靠左的一列像素(p_fdec[0]-1)  
  254.         //一次拷貝8個(起始點上面4個下面4個),拷貝2次  
  255.   
  256.         x264_copy_column8( h->mb.pic.p_fdec[0]-1+ 4*FDEC_STRIDE, h->mb.pic.p_fdec[0]+15+ 4*FDEC_STRIDE );  
  257.         x264_copy_column8( h->mb.pic.p_fdec[0]-1+12*FDEC_STRIDE, h->mb.pic.p_fdec[0]+15+12*FDEC_STRIDE );  
  258.         //加載圖像相關的指針  
  259.         //第4個參數:指明瞭第幾個分量(Y、U、V)  
  260.         //第5個參數:指明瞭是否爲色度  
  261.         x264_macroblock_load_pic_pointers( h, mb_x, mb_y, 0, 0, 0 );  
  262.         if( CHROMA444 )  
  263.         {  
  264.             x264_copy_column8( h->mb.pic.p_fdec[1]-1+ 4*FDEC_STRIDE, h->mb.pic.p_fdec[1]+15+ 4*FDEC_STRIDE );  
  265.             x264_copy_column8( h->mb.pic.p_fdec[1]-1+12*FDEC_STRIDE, h->mb.pic.p_fdec[1]+15+12*FDEC_STRIDE );  
  266.             x264_copy_column8( h->mb.pic.p_fdec[2]-1+ 4*FDEC_STRIDE, h->mb.pic.p_fdec[2]+15+ 4*FDEC_STRIDE );  
  267.             x264_copy_column8( h->mb.pic.p_fdec[2]-1+12*FDEC_STRIDE, h->mb.pic.p_fdec[2]+15+12*FDEC_STRIDE );  
  268.             x264_macroblock_load_pic_pointers( h, mb_x, mb_y, 1, 0, 0 );  
  269.             x264_macroblock_load_pic_pointers( h, mb_x, mb_y, 2, 0, 0 );  
  270.         }  
  271.         else  
  272.         {  
  273.             //U和V  
  274.             //YUV420P的情況下  
  275.             //拷貝上一個宏塊最右邊一列(共8個)像素  
  276.             //作爲這一個宏塊最左邊再靠左的一列像素  
  277.             //一次拷貝8個  
  278.             x264_copy_column8( h->mb.pic.p_fdec[1]-1+ 4*FDEC_STRIDE, h->mb.pic.p_fdec[1]+ 7+ 4*FDEC_STRIDE );  
  279.             x264_copy_column8( h->mb.pic.p_fdec[2]-1+ 4*FDEC_STRIDE, h->mb.pic.p_fdec[2]+ 7+ 4*FDEC_STRIDE );  
  280.             if( CHROMA_FORMAT == CHROMA_422 )  
  281.             {  
  282.                 x264_copy_column8( h->mb.pic.p_fdec[1]-1+12*FDEC_STRIDE, h->mb.pic.p_fdec[1]+ 7+12*FDEC_STRIDE );  
  283.                 x264_copy_column8( h->mb.pic.p_fdec[2]-1+12*FDEC_STRIDE, h->mb.pic.p_fdec[2]+ 7+12*FDEC_STRIDE );  
  284.             }  
  285.             x264_macroblock_load_pic_pointers( h, mb_x, mb_y, 1, 1, 0 );  
  286.         }  
  287.     }  
  288.     else  
  289.     {  
  290.         x264_macroblock_load_pic_pointers( h, mb_x, mb_y, 0, 0, 1 );  
  291.         if( CHROMA444 )  
  292.         {  
  293.             x264_macroblock_load_pic_pointers( h, mb_x, mb_y, 1, 0, 1 );  
  294.             x264_macroblock_load_pic_pointers( h, mb_x, mb_y, 2, 0, 1 );  
  295.         }  
  296.         else  
  297.             x264_macroblock_load_pic_pointers( h, mb_x, mb_y, 1, 1, 1 );  
  298.     }  
  299.   
  300.     if( h->fdec->integral )  
  301.     {  
  302.         int offset = 16 * (mb_x + mb_y * h->fdec->i_stride[0]);  
  303.         forint list = 0; list < 2; list++ )  
  304.             forint i = 0; i < h->mb.pic.i_fref[list]; i++ )  
  305.                 h->mb.pic.p_integral[list][i] = &h->fref[list][i]->integral[offset];  
  306.     }  
  307.   
  308.     x264_prefetch_fenc( h, h->fenc, mb_x, mb_y );  
  309.   
  310.     /* load ref/mv/mvd */  
  311.     forint l = 0; l < lists; l++ )  
  312.     {  
  313.         int16_t (*mv)[2] = h->mb.mv[l];  
  314.         int8_t *ref = h->mb.ref[l];  
  315.   
  316.         int i8 = x264_scan8[0] - 1 - 1*8;  
  317.         if( h->mb.i_neighbour & MB_TOPLEFT )  
  318.         {  
  319.             //填充宏塊左上方信息  
  320.   
  321.             int ir = b_mbaff ? 2*(s8x8*h->mb.i_mb_topleft_y + mb_x-1)+1+s8x8 : top_8x8 - 1;  
  322.             int iv = b_mbaff ? 4*(s4x4*h->mb.i_mb_topleft_y + mb_x-1)+3+3*s4x4 : top_4x4 - 1;  
  323.             if( b_mbaff && h->mb.topleft_partition )  
  324.             {  
  325.                 /* Take motion vector from the middle of macroblock instead of 
  326.                  * the bottom right as usual. */  
  327.                 iv -= 2*s4x4;  
  328.                 ir -= s8x8;  
  329.             }  
  330.             /* 
  331.              * 填充參考幀序號ref[] 
  332.              * 在這裏相當於在ref[]填充了「y」, 
  333.              *   | 
  334.              * --+-------------- 
  335.              *   | 0 0 0 y 0 0 0 0 
  336.              *   | 0 0 0 0 Y Y Y Y 
  337.              *   | 0 0 0 0 Y Y Y Y 
  338.              *   | 0 0 0 0 Y Y Y Y 
  339.              *   | 0 0 0 0 Y Y Y Y 
  340.              */  
  341.             //參考幀序號  
  342.             h->mb.cache.ref[l][i8] = ref[ir];  
  343.             /* 
  344.              * 填充運動矢量mv[] 
  345.              * 在這裏相當於在mv[]填充了「y」, 
  346.              *   | 
  347.              * --+-------------- 
  348.              *   | 0 0 0 y 0 0 0 0 
  349.              *   | 0 0 0 0 Y Y Y Y 
  350.              *   | 0 0 0 0 Y Y Y Y 
  351.              *   | 0 0 0 0 Y Y Y Y 
  352.              *   | 0 0 0 0 Y Y Y Y 
  353.              */  
  354.             //運動矢量  
  355.             CP32( h->mb.cache.mv[l][i8], mv[iv] );  
  356.         }  
  357.         else  
  358.         {  
  359.             h->mb.cache.ref[l][i8] = -2;  
  360.             M32( h->mb.cache.mv[l][i8] ) = 0;  
  361.         }  
  362.   
  363.         i8 = x264_scan8[0] - 8;  
  364.         if( h->mb.i_neighbour & MB_TOP )  
  365.         {  
  366.             //填充宏塊上方信息  
  367.   
  368.             /* 
  369.              * 填充參考幀序號ref[] 
  370.              * 在這裏相當於在ref[]分別填充了「1」和「2」, 
  371.              *   | 
  372.              * --+-------------- 
  373.              *   | 0 0 0 0 1 1 2 2 
  374.              *   | 0 0 0 0 Y Y Y Y 
  375.              *   | 0 0 0 0 Y Y Y Y 
  376.              *   | 0 0 0 0 Y Y Y Y 
  377.              *   | 0 0 0 0 Y Y Y Y 
  378.              */  
  379.             h->mb.cache.ref[l][i8+0] =  
  380.             h->mb.cache.ref[l][i8+1] = ref[top_8x8 + 0];  
  381.             h->mb.cache.ref[l][i8+2] =  
  382.             h->mb.cache.ref[l][i8+3] = ref[top_8x8 + 1];  
  383.             /* 
  384.              * 填充運動矢量mv[] 
  385.              * 在這裏相當於在mv[]填充了y, 
  386.              *   | 
  387.              * --+-------------- 
  388.              *   | 0 0 0 0 y y y y 
  389.              *   | 0 0 0 0 Y Y Y Y 
  390.              *   | 0 0 0 0 Y Y Y Y 
  391.              *   | 0 0 0 0 Y Y Y Y 
  392.              *   | 0 0 0 0 Y Y Y Y 
  393.              */  
  394.             CP128( h->mb.cache.mv[l][i8], mv[top_4x4] );  
  395.         }  
  396.         else  
  397.         {  
  398.             M128( h->mb.cache.mv[l][i8] ) = M128_ZERO;  
  399.             M32( &h->mb.cache.ref[l][i8] ) = (uint8_t)(-2) * 0x01010101U;  
  400.         }  
  401.   
  402.         i8 = x264_scan8[0] + 4 - 1*8;  
  403.         if( h->mb.i_neighbour & MB_TOPRIGHT )  
  404.         {  
  405.             //填充宏塊右上方信息  
  406.             int ir = b_mbaff ? 2*(s8x8*h->mb.i_mb_topright_y + (mb_x+1))+s8x8 : top_8x8 + 2;  
  407.             int iv = b_mbaff ? 4*(s4x4*h->mb.i_mb_topright_y + (mb_x+1))+3*s4x4 : top_4x4 + 4;  
  408.             h->mb.cache.ref[l][i8] = ref[ir];  
  409.             CP32( h->mb.cache.mv[l][i8], mv[iv] );  
  410.         }  
  411.         else  
  412.              h->mb.cache.ref[l][i8] = -2;  
  413.   
  414.         i8 = x264_scan8[0] - 1;  
  415.         if( h->mb.i_neighbour & MB_LEFT )  
  416.         {  
  417.             //填充宏塊左邊信息  
  418.   
  419.             if( b_mbaff )  
  420.             {  
  421.                 h->mb.cache.ref[l][i8+0*8] = ref[h->mb.left_b8[LTOP] + 1 + s8x8*left_index_table->ref[0]];  
  422.                 h->mb.cache.ref[l][i8+1*8] = ref[h->mb.left_b8[LTOP] + 1 + s8x8*left_index_table->ref[1]];  
  423.                 h->mb.cache.ref[l][i8+2*8] = ref[h->mb.left_b8[LBOT] + 1 + s8x8*left_index_table->ref[2]];  
  424.                 h->mb.cache.ref[l][i8+3*8] = ref[h->mb.left_b8[LBOT] + 1 + s8x8*left_index_table->ref[3]];  
  425.   
  426.                 CP32( h->mb.cache.mv[l][i8+0*8], mv[h->mb.left_b4[LTOP] + 3 + s4x4*left_index_table->mv[0]] );  
  427.                 CP32( h->mb.cache.mv[l][i8+1*8], mv[h->mb.left_b4[LTOP] + 3 + s4x4*left_index_table->mv[1]] );  
  428.                 CP32( h->mb.cache.mv[l][i8+2*8], mv[h->mb.left_b4[LBOT] + 3 + s4x4*left_index_table->mv[2]] );  
  429.                 CP32( h->mb.cache.mv[l][i8+3*8], mv[h->mb.left_b4[LBOT] + 3 + s4x4*left_index_table->mv[3]] );  
  430.             }  
  431.             else  
  432.             {  
  433.                 //不考慮「宏塊級幀場自適應」的時候  
  434.   
  435.                 const int ir = h->mb.i_b8_xy - 1;  
  436.                 const int iv = h->mb.i_b4_xy - 1;  
  437.   
  438.                 /* 
  439.                  * 填充參考幀序號ref[] 
  440.                  * 在這裏相當於在ref[]分別填充了「1」和「2」, 
  441.                  *   | 
  442.                  * --+-------------- 
  443.                  *   | 0 0 0 0 0 0 0 0 
  444.                  *   | 0 0 0 1 Y Y Y Y 
  445.                  *   | 0 0 0 1 Y Y Y Y 
  446.                  *   | 0 0 0 2 Y Y Y Y 
  447.                  *   | 0 0 0 2 Y Y Y Y 
  448.                  */  
  449.                 h->mb.cache.ref[l][i8+0*8] =  
  450.                 h->mb.cache.ref[l][i8+1*8] = ref[ir + 0*s8x8];  
  451.                 h->mb.cache.ref[l][i8+2*8] =  
  452.                 h->mb.cache.ref[l][i8+3*8] = ref[ir + 1*s8x8];  
  453.   
  454.                 /* 
  455.                  * 填充運動矢量mv[] 
  456.                  * 在這裏相當於在mv[]填充了y, 
  457.                  *   | 
  458.                  * --+-------------- 
  459.                  *   | 0 0 0 0 0 0 0 0 
  460.                  *   | 0 0 0 y Y Y Y Y 
  461.                  *   | 0 0 0 y Y Y Y Y 
  462.                  *   | 0 0 0 y Y Y Y Y 
  463.                  *   | 0 0 0 y Y Y Y Y 
  464.                  */  
  465.                 CP32( h->mb.cache.mv[l][i8+0*8], mv[iv + 0*s4x4] );  
  466.                 CP32( h->mb.cache.mv[l][i8+1*8], mv[iv + 1*s4x4] );  
  467.                 CP32( h->mb.cache.mv[l][i8+2*8], mv[iv + 2*s4x4] );  
  468.                 CP32( h->mb.cache.mv[l][i8+3*8], mv[iv + 3*s4x4] );  
  469.             }  
  470.         }  
  471.         else  
  472.         {  
  473.             forint i = 0; i < 4; i++ )  
  474.             {  
  475.                 h->mb.cache.ref[l][i8+i*8] = -2;  
  476.                 M32( h->mb.cache.mv[l][i8+i*8] ) = 0;  
  477.             }  
  478.         }  
  479.   
  480.         /* Extra logic for top right mv in mbaff. 
  481.          * . . . d  . . a . 
  482.          * . . . e  . . . . 
  483.          * . . . f  b . c . 
  484.          * . . . .  . . . . 
  485.          * 
  486.          * If the top right of the 4x4 partitions labeled a, b and c in the 
  487.          * above diagram do not exist, but the entries d, e and f exist (in 
  488.          * the macroblock to the left) then use those instead. 
  489.          */  
  490.         if( b_mbaff && (h->mb.i_neighbour & MB_LEFT) )  
  491.         {  
  492.             if( MB_INTERLACED && !h->mb.field[h->mb.i_mb_xy-1] )  
  493.             {  
  494.                 h->mb.cache.topright_ref[l][0] = ref[h->mb.left_b8[0] + 1 + s8x8*0];  
  495.                 h->mb.cache.topright_ref[l][1] = ref[h->mb.left_b8[0] + 1 + s8x8*1];  
  496.                 h->mb.cache.topright_ref[l][2] = ref[h->mb.left_b8[1] + 1 + s8x8*0];  
  497.                 CP32( h->mb.cache.topright_mv[l][0], mv[h->mb.left_b4[0] + 3 + s4x4*(left_index_table->mv[0]+1)] );  
  498.                 CP32( h->mb.cache.topright_mv[l][1], mv[h->mb.left_b4[0] + 3 + s4x4*(left_index_table->mv[1]+1)] );  
  499.                 CP32( h->mb.cache.topright_mv[l][2], mv[h->mb.left_b4[1] + 3 + s4x4*(left_index_table->mv[2]+1)] );  
  500.             }  
  501.             else if( !MB_INTERLACED && h->mb.field[h->mb.i_mb_xy-1] )  
  502.             {  
  503.                 // Looking at the bottom field so always take the bottom macroblock of the pair.  
  504.                 h->mb.cache.topright_ref[l][0] = ref[h->mb.left_b8[0] + 1 + s8x8*2 + s8x8*left_index_table->ref[0]];  
  505.                 h->mb.cache.topright_ref[l][1] = ref[h->mb.left_b8[0] + 1 + s8x8*2 + s8x8*left_index_table->ref[0]];  
  506.                 h->mb.cache.topright_ref[l][2] = ref[h->mb.left_b8[0] + 1 + s8x8*2 + s8x8*left_index_table->ref[2]];  
  507.                 CP32( h->mb.cache.topright_mv[l][0], mv[h->mb.left_b4[0] + 3 + s4x4*4 + s4x4*left_index_table->mv[0]] );  
  508.                 CP32( h->mb.cache.topright_mv[l][1], mv[h->mb.left_b4[0] + 3 + s4x4*4 + s4x4*left_index_table->mv[1]] );  
  509.                 CP32( h->mb.cache.topright_mv[l][2], mv[h->mb.left_b4[0] + 3 + s4x4*4 + s4x4*left_index_table->mv[2]] );  
  510.             }  
  511.         }  
  512.   
  513.         //使用了CABAC的時候纔會運行  
  514.         if( h->param.b_cabac )  
  515.         {  
  516.             uint8_t (*mvd)[8][2] = h->mb.mvd[l];  
  517.             if( h->mb.i_neighbour & MB_TOP )  
  518.                 CP64( h->mb.cache.mvd[l][x264_scan8[0] - 8], mvd[top][0] );  
  519.             else  
  520.                 M64( h->mb.cache.mvd[l][x264_scan8[0] - 8] ) = 0;  
  521.   
  522.             if( h->mb.i_neighbour & MB_LEFT && (!b_mbaff || h->mb.cache.ref[l][x264_scan8[0]-1] >= 0) )  
  523.             {  
  524.                 CP16( h->mb.cache.mvd[l][x264_scan8[0 ] - 1], mvd[left[LTOP]][left_index_table->intra[0]] );  
  525.                 CP16( h->mb.cache.mvd[l][x264_scan8[2 ] - 1], mvd[left[LTOP]][left_index_table->intra[1]] );  
  526.             }  
  527.             else  
  528.             {  
  529.                 M16( h->mb.cache.mvd[l][x264_scan8[0]-1+0*8] ) = 0;  
  530.                 M16( h->mb.cache.mvd[l][x264_scan8[0]-1+1*8] ) = 0;  
  531.             }  
  532.             if( h->mb.i_neighbour & MB_LEFT && (!b_mbaff || h->mb.cache.ref[l][x264_scan8[0]-1+2*8] >=0) )  
  533.             {  
  534.                 CP16( h->mb.cache.mvd[l][x264_scan8[8 ] - 1], mvd[left[LBOT]][left_index_table->intra[2]] );  
  535.                 CP16( h->mb.cache.mvd[l][x264_scan8[10] - 1], mvd[left[LBOT]][left_index_table->intra[3]] );  
  536.             }  
  537.             else  
  538.             {  
  539.                 M16( h->mb.cache.mvd[l][x264_scan8[0]-1+2*8] ) = 0;  
  540.                 M16( h->mb.cache.mvd[l][x264_scan8[0]-1+3*8] ) = 0;  
  541.             }  
  542.         }  
  543.   
  544.         /* If motion vectors are cached from frame macroblocks but this 
  545.          * macroblock is a field macroblock then the motion vector must be 
  546.          * halved. Similarly, motion vectors from field macroblocks are doubled. */  
  547.         if( b_mbaff )  
  548.         {  
  549. #define MAP_MVS\  
  550.                 if( FIELD_DIFFERENT(h->mb.i_mb_topleft_xy) )\  
  551.                     MAP_F2F(mv, ref, x264_scan8[0] - 1 - 1*8)\  
  552.                 if( FIELD_DIFFERENT(top) )\  
  553.                 {\  
  554.                     MAP_F2F(mv, ref, x264_scan8[0] + 0 - 1*8)\  
  555.                     MAP_F2F(mv, ref, x264_scan8[0] + 1 - 1*8)\  
  556.                     MAP_F2F(mv, ref, x264_scan8[0] + 2 - 1*8)\  
  557.                     MAP_F2F(mv, ref, x264_scan8[0] + 3 - 1*8)\  
  558.                 }\  
  559.                 if( FIELD_DIFFERENT(h->mb.i_mb_topright_xy) )\  
  560.                     MAP_F2F(mv, ref, x264_scan8[0] + 4 - 1*8)\  
  561.                 if( FIELD_DIFFERENT(left[0]) )\  
  562.                 {\  
  563.                     MAP_F2F(mv, ref, x264_scan8[0] - 1 + 0*8)\  
  564.                     MAP_F2F(mv, ref, x264_scan8[0] - 1 + 1*8)\  
  565.                     MAP_F2F(mv, ref, x264_scan8[0] - 1 + 2*8)\  
  566.                     MAP_F2F(mv, ref, x264_scan8[0] - 1 + 3*8)\  
  567.                     MAP_F2F(topright_mv, topright_ref, 0)\  
  568.                     MAP_F2F(topright_mv, topright_ref, 1)\  
  569.                     MAP_F2F(topright_mv, topright_ref, 2)\  
  570.                 }  
  571.   
  572.             if( MB_INTERLACED )  
  573.             {  
  574. #define FIELD_DIFFERENT(macroblock) (macroblock >= 0 && !h->mb.field[macroblock])  
  575. #define MAP_F2F(varmv, varref, index)\  
  576.                 if( h->mb.cache.varref[l][index] >= 0 )\  
  577.                 {\  
  578.                     h->mb.cache.varref[l][index] <<= 1;\  
  579.                     h->mb.cache.varmv[l][index][1] /= 2;\  
  580.                     h->mb.cache.mvd[l][index][1] >>= 1;\  
  581.                 }  
  582.                 MAP_MVS  
  583. #undef MAP_F2F  
  584. #undef FIELD_DIFFERENT  
  585.             }  
  586.             else  
  587.             {  
  588. #define FIELD_DIFFERENT(macroblock) (macroblock >= 0 && h->mb.field[macroblock])  
  589. #define MAP_F2F(varmv, varref, index)\  
  590.                 if( h->mb.cache.varref[l][index] >= 0 )\  
  591.                 {\  
  592.                     h->mb.cache.varref[l][index] >>= 1;\  
  593.                     h->mb.cache.varmv[l][index][1] <<= 1;\  
  594.                     h->mb.cache.mvd[l][index][1] <<= 1;\  
  595.                 }  
  596.                 MAP_MVS  
  597. #undef MAP_F2F  
  598. #undef FIELD_DIFFERENT  
  599.             }  
  600.         }  
  601.     }  
  602.   
  603.     if( b_mbaff && mb_x == 0 && !(mb_y&1) )  
  604.     {  
  605.         if( h->mb.i_mb_top_xy >= h->sh.i_first_mb )  
  606.             h->mb.field_decoding_flag = h->mb.field[h->mb.i_mb_top_xy];  
  607.         else  
  608.             h->mb.field_decoding_flag = 0;  
  609.     }  
  610.   
  611.     /* Check whether skip here would cause decoder to predict interlace mode incorrectly. 
  612.      * FIXME: It might be better to change the interlace type rather than forcing a skip to be non-skip. */  
  613.     h->mb.b_allow_skip = 1;  
  614.     if( b_mbaff )  
  615.     {  
  616.         if( MB_INTERLACED != h->mb.field_decoding_flag &&  
  617.             (mb_y&1) && IS_SKIP(h->mb.type[h->mb.i_mb_xy - h->mb.i_mb_stride]) )  
  618.             h->mb.b_allow_skip = 0;  
  619.     }  
  620.   
  621.     //使用了CABAC的時候纔會運行  
  622.     if( h->param.b_cabac )  
  623.     {  
  624.         if( b_mbaff )  
  625.         {  
  626.             int left_xy, top_xy;  
  627.             /* Neighbours here are calculated based on field_decoding_flag */  
  628.             int mb_xy = mb_x + (mb_y&~1)*h->mb.i_mb_stride;  
  629.             left_xy = mb_xy - 1;  
  630.             if( (mb_y&1) && mb_x > 0 && h->mb.field_decoding_flag == h->mb.field[left_xy] )  
  631.                 left_xy += h->mb.i_mb_stride;  
  632.             if( h->mb.field_decoding_flag )  
  633.             {  
  634.                 top_xy = mb_xy - h->mb.i_mb_stride;  
  635.                 if( !(mb_y&1) && top_xy >= 0 && h->mb.slice_table[top_xy] == h->sh.i_first_mb && h->mb.field[top_xy] )  
  636.                     top_xy -= h->mb.i_mb_stride;  
  637.             }  
  638.             else  
  639.                 top_xy = mb_x + (mb_y-1)*h->mb.i_mb_stride;  
  640.   
  641.             h->mb.cache.i_neighbour_skip =   (mb_x >  0 && h->mb.slice_table[left_xy] == h->sh.i_first_mb && !IS_SKIP( h->mb.type[left_xy] ))  
  642.                                          + (top_xy >= 0 && h->mb.slice_table[top_xy]  == h->sh.i_first_mb && !IS_SKIP( h->mb.type[top_xy] ));  
  643.         }  
  644.         else  
  645.         {  
  646.             h->mb.cache.i_neighbour_skip = ((h->mb.i_neighbour & MB_LEFT) && !IS_SKIP( h->mb.i_mb_type_left[0] ))  
  647.                                          + ((h->mb.i_neighbour & MB_TOP)  && !IS_SKIP( h->mb.i_mb_type_top ));  
  648.         }  
  649.     }  
  650.   
  651.     /* load skip */  
  652.     //處理「skip」類型宏塊  
  653.     if( h->sh.i_type == SLICE_TYPE_B )  
  654.     {  
  655.         h->mb.bipred_weight = h->mb.bipred_weight_buf[MB_INTERLACED][MB_INTERLACED&(mb_y&1)];  
  656.         h->mb.dist_scale_factor = h->mb.dist_scale_factor_buf[MB_INTERLACED][MB_INTERLACED&(mb_y&1)];  
  657.         if( h->param.b_cabac )  
  658.         {  
  659.             uint8_t skipbp;  
  660.             x264_macroblock_cache_skip( h, 0, 0, 4, 4, 0 );  
  661.             if( b_mbaff )  
  662.             {  
  663.                 skipbp = (h->mb.i_neighbour & MB_LEFT) ? h->mb.skipbp[left[LTOP]] : 0;  
  664.                 h->mb.cache.skip[x264_scan8[0] - 1] = (skipbp >> (1+(left_index_table->mv[0]&~1))) & 1;  
  665.                 skipbp = (h->mb.i_neighbour & MB_LEFT) ? h->mb.skipbp[left[LBOT]] : 0;  
  666.                 h->mb.cache.skip[x264_scan8[8] - 1] = (skipbp >> (1+(left_index_table->mv[2]&~1))) & 1;  
  667.             }  
  668.             else  
  669.             {  
  670.                 skipbp = (h->mb.i_neighbour & MB_LEFT) ? h->mb.skipbp[left[0]] : 0;  
  671.                 h->mb.cache.skip[x264_scan8[0] - 1] = skipbp & 0x2;  
  672.                 h->mb.cache.skip[x264_scan8[8] - 1] = skipbp & 0x8;  
  673.             }  
  674.             skipbp = (h->mb.i_neighbour & MB_TOP) ? h->mb.skipbp[top] : 0;  
  675.             h->mb.cache.skip[x264_scan8[0] - 8] = skipbp & 0x4;  
  676.             h->mb.cache.skip[x264_scan8[4] - 8] = skipbp & 0x8;  
  677.         }  
  678.     }  
  679.   
  680.     if( h->sh.i_type == SLICE_TYPE_P )  
  681.         x264_mb_predict_mv_pskip( h, h->mb.cache.pskip_mv );  
  682.   
  683.     /* 
  684.      * i_neightbour8把一個宏塊分成4個8x8的子塊,編號如下,用於記錄它們鄰塊的可用性 
  685.      * +--------+--------+ 
  686.      * |        |        | 
  687.      * |   0    |   1    | 
  688.      * |        |        | 
  689.      * +--------+--------+ 
  690.      * |        |        | 
  691.      * |   2    |   3    | 
  692.      * |        |        | 
  693.      * +--------+--------+ 
  694.      * 
  695.      * i_neightbour4把一個宏塊分成16個4x4的子塊,編號如下,用於記錄它們鄰塊的可用性 
  696.      * (實際上也是類似scan8[]讀取cache的順序) 
  697.      * +----+----+----+----+ 
  698.      * | 0  | 1  | 4  | 5  | 
  699.      * +----+----+----+----+ 
  700.      * | 2  | 3  | 6  | 7  | 
  701.      * +----+----+----+----+ 
  702.      * | 8  | 9  | 12 | 13 | 
  703.      * +----+----+----+----+ 
  704.      * | 10 | 11 | 14 | 15 | 
  705.      * +----+----+----+----+ 
  706.      * 
  707.      */  
  708.     h->mb.i_neighbour4[0] =  
  709.     h->mb.i_neighbour8[0] = (h->mb.i_neighbour_intra & (MB_TOP|MB_LEFT|MB_TOPLEFT))  
  710.                             | ((h->mb.i_neighbour_intra & MB_TOP) ? MB_TOPRIGHT : 0);  
  711.     h->mb.i_neighbour4[4] =  
  712.     h->mb.i_neighbour4[1] = MB_LEFT | ((h->mb.i_neighbour_intra & MB_TOP) ? (MB_TOP|MB_TOPLEFT|MB_TOPRIGHT) : 0);  
  713.     h->mb.i_neighbour4[2] =  
  714.     h->mb.i_neighbour4[8] =  
  715.     h->mb.i_neighbour4[10] =  
  716.     h->mb.i_neighbour8[2] = MB_TOP|MB_TOPRIGHT | ((h->mb.i_neighbour_intra & MB_LEFT) ? (MB_LEFT|MB_TOPLEFT) : 0);  
  717.     h->mb.i_neighbour4[5] =  
  718.     h->mb.i_neighbour8[1] = MB_LEFT | (h->mb.i_neighbour_intra & MB_TOPRIGHT)  
  719.                             | ((h->mb.i_neighbour_intra & MB_TOP) ? MB_TOP|MB_TOPLEFT : 0);  
  720. }  

x264_macroblock_cache_load()源代碼比較長,比較關鍵的地方都做了註釋,在這裏就不詳細記錄了。總體說來該函數的流程如下所示:

(1)加載Intra4x4幀內預測模式intra4x4_pred_mode[]和DCT非零係數non_zero_count[]緩存Cache的宏塊周邊信息。加載順序爲:上->左->左上。

(2)加載宏塊重建像素p_fdec[]的周邊像素,以及宏塊編碼像素p_fenc[]。對於p_fdec[]來說,在本函數中直接加載當前宏塊左邊的像素;調用函數x264_macroblock_load_pic_pointers()加載當前宏塊上面的像素。對於p_fenc[]來說,調用x264_macroblock_load_pic_pointers()從圖像上拷貝數據。

(3)加載參考幀序號ref[]和運動矢量mv[]緩存Cache的宏塊周邊信息。加載順序爲:左上->上->左。
(4)加載其它信息。

下面簡單瀏覽一下x264_macroblock_load_pic_pointers()的源代碼。

x264_macroblock_load_pic_pointers()

x264_macroblock_load_pic_pointers()用於給宏塊重建像素p_fdec[]和宏塊編碼像素p_fenc[]加載數據,並且加載圖像的半像素數據。它的定義位於common\macroblock.c,如下所示。
[cpp]  view plain  copy
  1. //加載圖像相關的指針  
  2. static void ALWAYS_INLINE x264_macroblock_load_pic_pointers( x264_t *h, int mb_x, int mb_y, int i, int b_chroma, int b_mbaff )  
  3. {  
  4.     int mb_interlaced = b_mbaff && MB_INTERLACED;  
  5.     int height = b_chroma ? 16 >> CHROMA_V_SHIFT : 16;  
  6.     int i_stride = h->fdec->i_stride[i];  
  7.     int i_stride2 = i_stride << mb_interlaced;  
  8.     int i_pix_offset = mb_interlaced  
  9.                      ? 16 * mb_x + height * (mb_y&~1) * i_stride + (mb_y&1) * i_stride  
  10.                      : 16 * mb_x + height * mb_y * i_stride;  
  11.     //從一整個重建幀中讀取一部分像素,賦值到重建幀宏塊中  
  12.     //i_pix_offset爲宏塊相對於整個幀起始位置的偏移量  
  13.     pixel *plane_fdec = &h->fdec->plane[i][i_pix_offset];  
  14.     int fdec_idx = b_mbaff ? (mb_interlaced ? (3 + (mb_y&1)) : (mb_y&1) ? 2 : 4) : !(mb_y&1);  
  15.     //前一行宏塊的底部邊界像素  
  16.     pixel *intra_fdec = &h->intra_border_backup[fdec_idx][i][mb_x*16];  
  17.     int ref_pix_offset[2] = { i_pix_offset, i_pix_offset };  
  18.     /* ref_pix_offset[0] references the current field and [1] the opposite field. */  
  19.     if( mb_interlaced )  
  20.         ref_pix_offset[1] += (1-2*(mb_y&1)) * i_stride;  
  21.     h->mb.pic.i_stride[i] = i_stride2;  
  22.     h->mb.pic.p_fenc_plane[i] = &h->fenc->plane[i][i_pix_offset];  
  23.     if( b_chroma )  
  24.     {  
  25.         //色度  
  26.         //編碼幀p_fenc  
  27.         h->mc.load_deinterleave_chroma_fenc( h->mb.pic.p_fenc[1], h->mb.pic.p_fenc_plane[1], i_stride2, height );  
  28.         //重建幀p_fdec  
  29.         memcpy( h->mb.pic.p_fdec[1]-FDEC_STRIDE, intra_fdec, 8*sizeof(pixel) );  
  30.         memcpy( h->mb.pic.p_fdec[2]-FDEC_STRIDE, intra_fdec+8, 8*sizeof(pixel) );  
  31.         h->mb.pic.p_fdec[1][-FDEC_STRIDE-1] = intra_fdec[-1-8];  
  32.         h->mb.pic.p_fdec[2][-FDEC_STRIDE-1] = intra_fdec[-1];  
  33.     }  
相關文章
相關標籤/搜索