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;
}

(转载请注明出处。)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值