/*
Project : H.264 encoder test
Module : Quantization
Author : Marko 'Fador' Viitanen
Date : 28/6/2009
Modified : 28/6/2009
*/
#include "common.h"
#include "tables.h"
/*
//Inverse
double E_i[4*4]= {
0.25000, 0.31623, 0.25000, 0.31623,
0.31623, 0.40000, 0.31623, 0.40000,
0.25000, 0.31623, 0.25000, 0.31623,
0.31623, 0.40000, 0.31623, 0.40000
};
//E=[a^2,(a*b)/2,a^2,(a*b)/2;(1*b)/2,(b^2)/4,(a*b)/2,(b^2)/4;a^2,(a*b)/2,a^2,(a*b)/2;(a*b)/2,(b^2)/4,(a*b)/2,(b^2)/4]
//Forward
double E_f[4*4]={
0.25000, 0.15811, 0.25000, 0.15811,
0.15811, 0.10000, 0.15811, 0.10000,
0.25000, 0.15811, 0.25000, 0.15811,
0.15811, 0.10000, 0.15811, 0.10000
};
*/
void init_QPstep()
{
static const double Qsteps[6] = { 0.625, 0.6875, 0.8125, 0.875, 1.0, 1.125 };
uint8 i;
//QPstep doubles every 6th QP
for(i=0;i<52;i++)
{
Qstep[i]=Qsteps[i%6]*(1<<(i/6));
}
}
void init_MF()
{
uint8 QP;
uint16 PF1[6]={13107,11916,10082,9362,8192,7282};
uint16 PF2[6]={5243,4660,4194,3647,3355,2893};
uint16 PF3[6]={8066,7490,6554,5825,5243,4559};
for(QP=0;QP<52;QP++)
{
MF[QP][0]=PF1[QP%6];
MF[QP][1]=PF2[QP%6];
MF[QP][2]=PF3[QP%6];
}
}
void init_V()
{
uint32 QP;
uint32 V1[6]={10,11,13,14,16,18};
uint32 V2[6]={16,18,20,23,25,29};
uint32 V3[6]={13,14,16,18,20,23};
for(QP=0;QP<52;QP++)
{
V[QP][0]=V1[QP%6]<<(QP/6);
V[QP][1]=V2[QP%6]<<(QP/6);
V[QP][2]=V3[QP%6]<<(QP/6);
}
}
void init_quant()
{
init_QPstep();
init_MF();
init_V();
}
//Quantisation for 4x4 blocks, mode 0 for intra, 1 for inter
uint8 quant_4x4(sint32* block, sint32* target, uint32 QP, uint32 mode)
{
uint32 i;
uint32 qbits=(15+(QP/6));
uint32 divider=mode?6:3;
uint32 helper;
uint32 qval=((1<<qbits)/divider);
uint32 MFtable[16]={MF[QP][0],MF[QP][2],MF[QP][0],MF[QP][2],
MF[QP][2],MF[QP][1],MF[QP][2],MF[QP][1],
MF[QP][0],MF[QP][2],MF[QP][0],MF[QP][2],
MF[QP][2],MF[QP][1],MF[QP][2],MF[QP][1]};
//Zij=round(Wij*(MF/2^qbits));
for(i=0;i<16;i++)
{
//Defined in book page 192
helper=((uint32)(abs(block[i])*MFtable[i]+qval))>>qbits;
if(block[i]<0) target[i]=-1*helper;
else target[i]=helper;
}
return 1;
}
//Inverse quantisation for 4x4 blocks
uint8 rescale_4x4(sint32* block, sint32* target, uint32 QP)
{
uint32 i;
uint32 helper;
uint32 Vtable[16]={V[QP][0],V[QP][2],V[QP][0],V[QP][2],
V[QP][2],V[QP][1],V[QP][2],V[QP][1],
V[QP][0],V[QP][2],V[QP][0],V[QP][2],
V[QP][2],V[QP][1],V[QP][2],V[QP][1]};
for(i=0;i<16;i++)
{
target[i]=block[i]*Vtable[i]/**(1<<(QP/6))*/;
}
return 1;
}
//Quantisation for DC 4x4 blocks, mode 0 for intra, 1 for inter
uint8 quantDC_4x4(sint32* block, sint32* target, uint32 QP, uint32 mode)
{
uint32 i;
uint32 qbits=(15+(QP/6));
uint32 divider=mode?6:3;
uint32 helper;
uint32 qval=2*((1<<qbits)/divider);
//|Zij| = (|Yij*MF[0]+qval) >> (qbits-1)
for(i=0;i<16;i++)
{
//Defined in book page 194
helper=((uint32)(abs(block[i])*MF[QP][0]+qval))>>(qbits-1);
if(block[i]<0) target[i]=-1*helper;
else target[i]=helper;
}
return 1;
}
//Inverse quantisation for 4x4 DC blocks
uint8 rescaleDC_4x4(sint32* block, sint32* target, uint32 QP)
{
uint32 i;
uint32 helper;
if(QP>=12)
{
for(i=0;i<16;i++)
{
target[i]=block[i]*V[QP][0]*(1<<((QP/6)-2));
}
}
else
{
for(i=0;i<16;i++)
{
helper=(abs(block[i])*V[QP][0]*(1<<(1-(QP/6))))>>(2-(QP/6));
if(block[i]<0) target[i]=-1*helper;
else target[i]=helper;
}
}
return 1;
}
//Quantisation for DC 2x2 blocks, mode 0 for intra, 1 for inter
uint8 quantDC_2x2(sint32* block, sint32* target, uint32 QP, uint32 mode)
{
uint32 i;
uint32 qbits=(15+(QP/6));
uint32 divider=mode?6:3;
uint32 helper;
uint32 qval=2*((1<<qbits)/divider);
//|Zij| = (|Yij*MF[0]+qval) >> (qbits-1)
for(i=0;i<4;i++)
{
//Defined in book page 194
helper=((uint32)(abs(block[i])*MF[QP][0]+qval))>>(qbits+1);
if(block[i]<0) target[i]=-1*helper;
else target[i]=helper;
}
return 1;
}
//Inverse quantisation for 2x2 DC blocks
uint8 rescaleDC_2x2(sint32* block, sint32* target, uint32 QP)
{
uint32 i;
uint32 helper;
if(QP>=6)
{
for(i=0;i<4;i++)
{
target[i]=block[i]*V[QP][0]*(1<<((QP/6)-1));
}
}
else
{
for(i=0;i<4;i++)
{
helper=(abs(block[i])*V[QP][0])>>1;
if(block[i]<0) target[i]=-1*helper;
else target[i]=helper;
}
}
return 1;
}