-
#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亮度块及色度块扫描序的数组,其内存存储方式如下所示:
其中,每一个小方格代表着一个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的赋值及上图不难分析出上述结论。
(转载请注明出处。)
-
#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亮度块及色度块扫描序的数组,其内存存储方式如下所示:
其中,每一个小方格代表着一个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的赋值及上图不难分析出上述结论。
(转载请注明出处。)