x264_scan8 的理解

原文:http://blog.csdn.net/hevc_cjl/article/details/8273533

先上代码及注释

[cpp]  view plain copy
  1. #define X264_SCAN8_SIZE (6*8) //!< 扫描表的尺寸  
  2. #define X264_SCAN8_0 (4+1*8) //!< 扫描表第一个扫描序(即亮度的首扫描序)  
  3.   
  4. static const int x264_scan8[16+2*4+3] =  
  5. {  
  6.     /* Luma */  
  7.     4+1*8, 5+1*8, 4+2*8, 5+2*8,  
  8.     6+1*8, 7+1*8, 6+2*8, 7+2*8,  
  9.     4+3*8, 5+3*8, 4+4*8, 5+4*8,  
  10.     6+3*8, 7+3*8, 6+4*8, 7+4*8,  
  11.   
  12.     /* Cb */  
  13.     1+1*8, 2+1*8,  
  14.     1+2*8, 2+2*8,  
  15.   
  16.     /* Cr */  
  17.     1+4*8, 2+4*8,  
  18.     1+5*8, 2+5*8,  
  19.   
  20.     /* Luma DC */  
  21.     4+5*8,  
  22.   
  23.     /* Chroma DC */  
  24.     5+5*8, 6+5*8  
  25. };  
  26. /* 
  27.    0 1 2 3 4 5 6 7 
  28.  0 
  29.  1   B B   L L L L 
  30.  2   B B   L L L L 
  31.  3         L L L L 
  32.  4   R R   L L L L 
  33.  5   R R   DyDuDv 
  34. */ // B -- Cb; R -- Cr; L -- Luma; Dy -- Luma DC; Du -- Cb DC; Dv -- Cr DC  

 

x264_scan8是一个存放着4x4亮度块及色度块扫描序的数组,其内存存储方式如下所示:

x264_scan8 的理解_第1张图片

其中,每一个小方格代表着一个4x4块,方格中的数字则是对应块的序号。

根据代码中对x264_scan8这个数组的赋值不难得到上图,其中,红色方块代表的是亮度块,绿色块和蓝色块分别代表两个色度块,而三个橙色块则依次代表亮度、两个色度的DC块。

为什么要这么做呢?我们知道,在进行帧内预测,帧间运动矢量预测的时候,需要使用到当前块的left块和top块,在CAVLC编码过程中,也需要知道当前块的left块和top块的non_zero_count,故由上图可以看到,空出来的部分可以用于存储前述所需的left块和top块的相关参数,起到便于访问和节省内存的作用。

看下面这个例子:

[cpp]  view plain copy
  1. void x264_mb_predict_mv_16x16( x264_t *h, int i_list, int i_ref, int16_t mvp[2] )  
  2. {  
  3.     int     i_refa = h->mb.cache.ref[i_list][X264_SCAN8_0 - 1];      //!< a块参考帧序号  
  4.     int16_t *mv_a  = h->mb.cache.mv[i_list][X264_SCAN8_0 - 1];       //!< a块的运动矢量  
  5.     int     i_refb = h->mb.cache.ref[i_list][X264_SCAN8_0 - 8];      //!< b块参考帧序号  
  6.     int16_t *mv_b  = h->mb.cache.mv[i_list][X264_SCAN8_0 - 8];       //!< b块的运动矢量  
  7.     int     i_refc = h->mb.cache.ref[i_list][X264_SCAN8_0 - 8 + 4];  //!< c块参考帧序号  
  8.     int16_t *mv_c  = h->mb.cache.mv[i_list][X264_SCAN8_0 - 8 + 4];   //!< c块的运动矢量  
  9.   
  10.     int i_count;  
  11.   
  12.     if( i_refc == -2 )  
  13.     {  
  14.         i_refc = h->mb.cache.ref[i_list][X264_SCAN8_0 - 8 - 1];  
  15.         mv_c   = h->mb.cache.mv[i_list][X264_SCAN8_0 - 8 - 1];  
  16.     }  
  17.   
  18.     i_count = 0;  
  19.     if( i_refa == i_ref ) i_count++;  
  20.     if( i_refb == i_ref ) i_count++;  
  21.     if( i_refc == i_ref ) i_count++;  
  22.   
  23.     if( i_count > 1 )  
  24.         x264_median_mv( mvp, mv_a, mv_b, mv_c );  
  25.     else if( i_count == 1 )  
  26.     {  
  27.         if( i_refa == i_ref )  
  28.             *(uint32_t*)mvp = *(uint32_t*)mv_a;  
  29.         else if( i_refb == i_ref )  
  30.             *(uint32_t*)mvp = *(uint32_t*)mv_b;  
  31.         else  
  32.             *(uint32_t*)mvp = *(uint32_t*)mv_c;  
  33.     }  
  34.     else if( i_refb == -2 && i_refc == -2 && i_refa != -2 )  
  35.         *(uint32_t*)mvp = *(uint32_t*)mv_a;  
  36.     else  
  37.         x264_median_mv( mvp, mv_a, mv_b, mv_c );  
  38. }  


其中,a块,b块,c块分别是当前宏块左、上、右上邻块,结合x264_scan8的赋值及上图不难分析出上述结论。

你可能感兴趣的:(X264)