x264 4x4帧内预测代码解析
/****************************************************************************
* 4x4 prediction for intra luma block
****************************************************************************/
#define SRC(x,y) src[(x)+(y)*FDEC_STRIDE] //!< 坐标为(x, y)的像素值
#define SRC32(x,y) *(uint32_t*)&SRC(x,y) //!< 将src的类型转换为uint_32_t*,这样可以一次性给4个字节(即一行)赋值
#define PREDICT_4x4_DC(v)\
SRC32(0,0) = SRC32(0,1) = SRC32(0,2) = SRC32(0,3) = v; //!< 分别给每行赋值
static void predict_4x4_dc_128( uint8_t *src ) //!< 模式9(V和H都不存在的情况)
{
PREDICT_4x4_DC(0x80808080); //!< 0x80 = 1000 0000 = 128
}
static void predict_4x4_dc_left( uint8_t *src ) //!< 模式9(只有V存在的情况)
{
uint32_t dc = ((SRC(-1,0) + SRC(-1,1) + SRC(-1,2) + SRC(-1,3) + 2) >> 2) * 0x01010101; //!< 同时给4个像素点赋值
PREDICT_4x4_DC(dc);
}
static void predict_4x4_dc_top( uint8_t *src ) //!< 模式9(只有H存在的情况)
{
uint32_t dc = ((SRC(0,-1) + SRC(1,-1) + SRC(2,-1) + SRC(3,-1) + 2) >> 2) * 0x01010101; //!< 同时给4个像素点赋值
PREDICT_4x4_DC(dc);
}
static void predict_4x4_dc( uint8_t *src ) //!< 模式9(V和H都存在的情况)
{
uint32_t dc = ((SRC(-1,0) + SRC(-1,1) + SRC(-1,2) + SRC(-1,3) +
SRC(0,-1) + SRC(1,-1) + SRC(2,-1) + SRC(3,-1) + 4) >> 3) * 0x01010101;
PREDICT_4x4_DC(dc);
}
static void predict_4x4_h( uint8_t *src ) //!< 模式1
{
SRC32(0,0) = SRC(-1,0) * 0x01010101; //!< 第1行
SRC32(0,1) = SRC(-1,1) * 0x01010101; //!< 第2行
SRC32(0,2) = SRC(-1,2) * 0x01010101; //!< 第3行
SRC32(0,3) = SRC(-1,3) * 0x01010101; //!< 第4行
}
static void predict_4x4_v( uint8_t *src ) //!< 模式0
{
PREDICT_4x4_DC(SRC32(0,-1)); //!< SRC32(0, -1)存放着当前4x4块上方的4个像素点值,PREDICT_4x4_DC将每一行的4个像素点都分别赋值为上邻块的4个像素点
}
#define PREDICT_4x4_LOAD_LEFT\
const int l0 = SRC(-1,0);\
const int l1 = SRC(-1,1);\
const int l2 = SRC(-1,2);\
UNUSED const int l3 = SRC(-1,3); //!< 当前4x4块的左邻列
#define PREDICT_4x4_LOAD_TOP\
const int t0 = SRC(0,-1);\
const int t1 = SRC(1,-1);\
const int t2 = SRC(2,-1);\
UNUSED const int t3 = SRC(3,-1); //!< 当前4x4块的上邻行
#define PREDICT_4x4_LOAD_TOP_RIGHT\
const int t4 = SRC(4,-1);\
const int t5 = SRC(5,-1);\
const int t6 = SRC(6,-1);\
UNUSED const int t7 = SRC(7,-1); //!< 当前4x4块的右上邻行
#define F1(a,b) (((a)+(b)+1)>>1) //!< 求a和b的平均值
#define F2(a,b,c) (((a)+2*(b)+(c)+2)>>2) //!< 求a,b和c的加权平均值
static void predict_4x4_ddl( uint8_t *src ) //!< 模式3(Diagonal_Down_Left)
{
PREDICT_4x4_LOAD_TOP
PREDICT_4x4_LOAD_TOP_RIGHT
SRC(0,0)= F2(t0,t1,t2);
SRC(1,0)=SRC(0,1)= F2(t1,t2,t3);
SRC(2,0)=SRC(1,1)=SRC(0,2)= F2(t2,t3,t4);
SRC(3,0)=SRC(2,1)=SRC(1,2)=SRC(0,3)= F2(t3,t4,t5);
SRC(3,1)=SRC(2,2)=SRC(1,3)= F2(t4,t5,t6);
SRC(3,2)=SRC(2,3)= F2(t5,t6,t7);
SRC(3,3)= F2(t6,t7,t7);
}
static void predict_4x4_ddr( uint8_t *src ) //!< 模式4(Diagonal_Down_Right)
{
const int lt = SRC(-1,-1);
PREDICT_4x4_LOAD_LEFT
PREDICT_4x4_LOAD_TOP
SRC(3,0)= F2(t3,t2,t1);
SRC(2,0)=SRC(3,1)= F2(t2,t1,t0);
SRC(1,0)=SRC(2,1)=SRC(3,2)= F2(t1,t0,lt);
SRC(0,0)=SRC(1,1)=SRC(2,2)=SRC(3,3)= F2(t0,lt,l0);
SRC(0,1)=SRC(1,2)=SRC(2,3)= F2(lt,l0,l1);
SRC(0,2)=SRC(1,3)= F2(l0,l1,l2);
SRC(0,3)= F2(l1,l2,l3);
}
static void predict_4x4_vr( uint8_t *src ) //!< 模式5(Vertical_Right)
{
const int lt = SRC(-1,-1);
PREDICT_4x4_LOAD_LEFT
PREDICT_4x4_LOAD_TOP
SRC(0,3)= F2(l2,l1,l0);
SRC(0,2)= F2(l1,l0,lt);
SRC(0,1)=SRC(1,3)= F2(l0,lt,t0);
SRC(0,0)=SRC(1,2)= F1(lt,t0);
SRC(1,1)=SRC(2,3)= F2(lt,t0,t1);
SRC(1,0)=SRC(2,2)= F1(t0,t1);
SRC(2,1)=SRC(3,3)= F2(t0,t1,t2);
SRC(2,0)=SRC(3,2)= F1(t1,t2);
SRC(3,1)= F2(t1,t2,t3);
SRC(3,0)= F1(t2,t3);
}
static void predict_4x4_hd( uint8_t *src ) //!< 模式6(Horizontal_Down)
{
const int lt= SRC(-1,-1);
PREDICT_4x4_LOAD_LEFT
PREDICT_4x4_LOAD_TOP
SRC(0,3)= F1(l2,l3);
SRC(1,3)= F2(l1,l2,l3);
SRC(0,2)=SRC(2,3)= F1(l1,l2);
SRC(1,2)=SRC(3,3)= F2(l0,l1,l2);
SRC(0,1)=SRC(2,2)= F1(l0,l1);
SRC(1,1)=SRC(3,2)= F2(lt,l0,l1);
SRC(0,0)=SRC(2,1)= F1(lt,l0);
SRC(1,0)=SRC(3,1)= F2(t0,lt,l0);
SRC(2,0)= F2(t1,t0,lt);
SRC(3,0)= F2(t2,t1,t0);
}
static void predict_4x4_vl( uint8_t *src ) //!< 模式7(Vertical_Left)
{
PREDICT_4x4_LOAD_TOP
PREDICT_4x4_LOAD_TOP_RIGHT
SRC(0,0)= F1(t0,t1);
SRC(0,1)= F2(t0,t1,t2);
SRC(1,0)=SRC(0,2)= F1(t1,t2);
SRC(1,1)=SRC(0,3)= F2(t1,t2,t3);
SRC(2,0)=SRC(1,2)= F1(t2,t3);
SRC(2,1)=SRC(1,3)= F2(t2,t3,t4);
SRC(3,0)=SRC(2,2)= F1(t3,t4);
SRC(3,1)=SRC(2,3)= F2(t3,t4,t5);
SRC(3,2)= F1(t4,t5);
SRC(3,3)= F2(t4,t5,t6);
}
static void predict_4x4_hu( uint8_t *src ) //!< 模式8(Horizontal_Up)
{
PREDICT_4x4_LOAD_LEFT
SRC(0,0)= F1(l0,l1);
SRC(1,0)= F2(l0,l1,l2);
SRC(2,0)=SRC(0,1)= F1(l1,l2);
SRC(3,0)=SRC(1,1)= F2(l1,l2,l3);
SRC(2,1)=SRC(0,2)= F1(l2,l3);
SRC(3,1)=SRC(1,2)= F2(l2,l3,l3);
SRC(3,2)=SRC(1,3)=SRC(0,3)=
SRC(2,2)=SRC(2,3)=SRC(3,3)= l3;
}
补充:综合编程 , 其他综合 ,