[置顶] x264_scan8 的理解

先上代码及注释
#define X264_SCAN8_SIZE (6*8) //!< 扫描表的尺寸
#define X264_SCAN8_0 (4+1*8) //!< 扫描表第一个扫描序(即亮度的首扫描序)

static const int x264_scan8[16+2*4+3] =
{
    /* Luma */
    4+1*8, 5+1*8, 4+2*8, 5+2*8,
    6+1*8, 7+1*8, 6+2*8, 7+2*8,
    4+3*8, 5+3*8, 4+4*8, 5+4*8,
    6+3*8, 7+3*8, 6+4*8, 7+4*8,

    /* Cb */
    1+1*8, 2+1*8,
    1+2*8, 2+2*8,

    /* Cr */
    1+4*8, 2+4*8,
    1+5*8, 2+5*8,

    /* Luma DC */
    4+5*8,

    /* Chroma DC */
    5+5*8, 6+5*8
};
/*
   0 1 2 3 4 5 6 7
 0
 1   B B   L L L L
 2   B B   L L L L
 3         L L L L
 4   R R   L L L L
 5   R R   DyDuDv
*/ // 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块的相关参数,起到便于访问和节省内存的作用。

看下面这个例子:

void x264_mb_predict_mv_16x16( x264_t *h, int i_list, int i_ref, int16_t mvp[2] )
{
    int     i_refa = h->mb.cache.ref[i_list][X264_SCAN8_0 - 1];		//!< a块参考帧序号
    int16_t *mv_a  = h->mb.cache.mv[i_list][X264_SCAN8_0 - 1];		//!< a块的运动矢量
    int     i_refb = h->mb.cache.ref[i_list][X264_SCAN8_0 - 8];		//!< b块参考帧序号
    int16_t *mv_b  = h->mb.cache.mv[i_list][X264_SCAN8_0 - 8];		//!< b块的运动矢量
    int     i_refc = h->mb.cache.ref[i_list][X264_SCAN8_0 - 8 + 4];	//!< c块参考帧序号
    int16_t *mv_c  = h->mb.cache.mv[i_list][X264_SCAN8_0 - 8 + 4];	//!< c块的运动矢量

    int i_count;

    if( i_refc == -2 )
    {
        i_refc = h->mb.cache.ref[i_list][X264_SCAN8_0 - 8 - 1];
        mv_c   = h->mb.cache.mv[i_list][X264_SCAN8_0 - 8 - 1];
    }

    i_count = 0;
    if( i_refa == i_ref ) i_count++;
    if( i_refb == i_ref ) i_count++;
    if( i_refc == i_ref ) i_count++;

    if( i_count > 1 )
        x264_median_mv( mvp, mv_a, mv_b, mv_c );
    else if( i_count == 1 )
    {
        if( i_refa == i_ref )
            *(uint32_t*)mvp = *(uint32_t*)mv_a;
        else if( i_refb == i_ref )
            *(uint32_t*)mvp = *(uint32_t*)mv_b;
        else
            *(uint32_t*)mvp = *(uint32_t*)mv_c;
    }
    else if( i_refb == -2 && i_refc == -2 && i_refa != -2 )
        *(uint32_t*)mvp = *(uint32_t*)mv_a;
    else
        x264_median_mv( mvp, mv_a, mv_b, mv_c );
}


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

 

(转载请注明出处。)


你可能感兴趣的:(x264,h.264,h.264,x264_scan8)