📄 idct.c
字号:
}
}
}
}
for (index = 0; index < IDCT_NTAB2_SIZE; index++) {
magn = 2 * IDCT_NTAB1_SIZE * (index + 1);
//printf( "Init index = %d magn = %f \n", index+IDCT_NTAB1_SIZE, magn);
for (zzpos = 0; zzpos < 8*8; zzpos++) {
n = InvZZ[zzpos] / 8;
m = InvZZ[zzpos] % 8;
for (j=0; j < 4; j++) {
for (i=0; i < 2; i++) {
idct_tab [index + IDCT_NTAB1_SIZE][zzpos][2*j+i]
= dct_tab_entry (magn * bfunc[n][m][j][2*i],
magn * bfunc[n][m][j][2*i+1]);
}
}
}
}
// Modify tables for index=1 to truncate more values to zero
Fix_PTel_S4000_mismatch();
// LUT to clip to allowed range for PIXEL
for (i = CLIPMIN; i <= CLIPMAX; i++) {
clip[i-CLIPMIN] = max( PIXEL_MIN, min( PIXEL_MAX, i));
}
// Classify zigzag position as even or odd, horizontally and vertically
for (zzpos = 0; zzpos < 8*8; zzpos++) {
n = InvZZ[zzpos] / 8;
m = InvZZ[zzpos] % 8;
even_odd_index[zzpos] = 2 * (n % 2) + m % 2;
}
#ifdef DO_H263_PLUS
InitAdvancedIntraTables();
#endif
return;
}
// Fix_PTel_S4000_mismatch - Modify tables for index=1 to truncate more
// values to zero. This improves the quality when communicating with a
// system that has an IDCT mismatch problem (PTel S-4000, bug #250)
static void Fix_PTel_S4000_mismatch( void )
{
int index, i, j, zzpos;
index = 1;
for (i = 0; i < 2; i++) {
truncate_more( &hor_ac_tab [index][i] );
}
for (j = 0; j < 4; j++) {
truncate_more( &vert_ac_tab [index][j] );
}
for (zzpos = 0; zzpos < 8*8; zzpos++) {
for (j=0; j < 4; j++) {
for (i=0; i < 2; i++) {
truncate_more( &idct_tab [index][zzpos][2*j+i] );
}
}
}
return;
}
// truncate_more
static void truncate_more( S32 * idct_tab_entry )
{
#define ONE_HALF (1 << (FRACBITS - 1))
#define PTEL_FIX_INTERVAL (3) // Set to 0 if no fix needed
S32 halfword[2];
int i;
halfword[0] = *idct_tab_entry >> 16; // Upper part of word
halfword[1] = (*idct_tab_entry << 16) >> 16; // Lower part of word
for (i = 0; i < 2; ++i) {
if (halfword[i] >= ONE_HALF && halfword[i] < ONE_HALF + PTEL_FIX_INTERVAL) {
halfword[i] = ONE_HALF - 1;
} else if (halfword[i] <= -ONE_HALF && halfword[i] > -(ONE_HALF + PTEL_FIX_INTERVAL)) {
halfword[i] = -(ONE_HALF - 1);
}
}
*idct_tab_entry = (halfword[0] << 16) | (halfword[1] & 0xffff);
return;
}
#ifdef WHY_IS_THIS_HERE
static int idct2_energy_test( SYMBOL sym[], int nsym,
S16 recon[] )
{
int isym, zzpos;
int temp;
isym = 0;
temp = 0;
zzpos = sym[0].type;
while (isym < nsym && zzpos < 10) {
temp += abs((int) recon[(U8)sym[isym].value]);
isym++;
zzpos += 1 + sym[isym].type;
}
return(temp);
}
#endif
static void idct2_goertzel( SYMBOL sym[], int nsym, S32 x[8][4],
S16 recon[], int intra, int clean, int idct_class)
{
int i, zzpos, isym;
S32 even_odd[4][8]; /* Accumulate even/even, even/odd, odd/even, odd/odd */
S32 temp[4]; /* Used in final butterfly computations */
#ifdef LITTLE_ENDIAN
char msg[120]; /* Flawfinder: ignore */
int LUT_index;
#endif
UNREFERENCED_PARAMETER(clean);
// The four special class implementations are specific to LITTLE_ENDIAN.
#ifdef LITTLE_ENDIAN
switch (idct_class)
{
case GENERAL:
{
memset(even_odd, 0, 128);
isym = 0;
zzpos = sym[0].type;
// Reconstruct DC coeff
if (intra == YES) {
recon_intra_dc( (U8) sym[0].value, even_odd[0]);
isym++;
zzpos += 1 + sym[isym].type;
}
else if (zzpos == 0) {
recon_dc( (S32) recon[(U8)sym[0].value], even_odd[0]);
isym++;
zzpos += 1 + sym[isym].type;
}
// Init even/odd: reconstruct first hor. AC coeff
if (isym < nsym && zzpos == 1) {
recon_hor_ac( (S32) recon[(U8)sym[isym].value], even_odd[1]);
isym++;
zzpos += 1 + sym[isym].type;
}
// Init odd/even: reconstruct first vert. AC coeff
if (isym < nsym && zzpos == 2) {
recon_vert_ac( (S32) recon[(U8)sym[isym].value], even_odd[2]);
isym++;
zzpos += 1 + sym[isym].type;
}
// Reconstruct remaining coeffs
// if (clean == YES) { // activate this for sleazy IDCT decoder
while (isym < nsym) {
//printf(" Calling update with zzpos = %d\n", zzpos);
update( &even_odd[ even_odd_index[zzpos]] [0],
(S32) recon[(U8)sym[isym].value],
(long (*)[512]) &idct_tab[0][zzpos][0]);
isym++;
zzpos += 1 + sym[isym].type;
}
// } // activate this for sleazy IDCT decoder
// else {
//
// Sleazy reconstruction
//
// while (isym < nsym && zzpos < 10) {
// //printf(" Calling update with zzpos = %d\n", zzpos);
// update( &even_odd[ even_odd_index[zzpos]] [0],
// (S32) recon[(U8)sym[isym].value],
// (U32 (*)[8*8*8])&idct_tab[0][zzpos][0]);
// isym++;
// zzpos += 1 + sym[isym].type;
// }
// }
}
break;
case DC_ONLY:
case DC_AC_H:
case DC_AC_V:
case DC_3:
{
isym = 0;
zzpos = sym[0].type;
// Reconstruct DC coeff
if (intra == YES)
{
LUT_index = (U8)sym[0].value;
even_odd[0][0] = intra_dc_tab[LUT_index];
isym++;
zzpos += 1 + sym[isym].type;
}
else if (zzpos == 0)
{
LUT_index = (S32)recon[(U8)sym[0].value];
if (LUT_index>0)
even_odd[0][0] = dc_tab[LUT_index-1];
else if (LUT_index<0)
even_odd[0][0] = -dc_tab[-LUT_index-1];
else
{
//sprintf(msg, "ERROR:recon_dc called with arg=0");
//H261ErrMsg(msg);
}
isym++;
zzpos += 1 + sym[isym].type;
}
// Init even/odd: reconstruct first hor. AC coeff
if (isym < nsym && zzpos == 1) {
recon_hor_ac( (S32) recon[(U8)sym[isym].value], even_odd[1]);
isym++;
zzpos += 1 + sym[isym].type;
}
// Init odd/even: reconstruct first vert. AC coeff
if (isym < nsym && zzpos == 2) {
recon_vert_ac( (S32) recon[(U8)sym[isym].value], even_odd[2]);
isym++;
zzpos += 1 + sym[isym].type;
}
}
break;
default:
break;
}
#else
memset(even_odd, 0, 128);
isym = 0;
zzpos = sym[0].type;
// Reconstruct DC coeff
if (intra == YES) {
recon_intra_dc( (U8) sym[0].value, even_odd[0]);
isym++;
zzpos += 1 + sym[isym].type;
}
else if (zzpos == 0) {
recon_dc( (S32) recon[(U8)sym[0].value], even_odd[0]);
isym++;
zzpos += 1 + sym[isym].type;
}
// Init even/odd: reconstruct first hor. AC coeff
if (isym < nsym && zzpos == 1) {
recon_hor_ac( (S32) recon[(U8)sym[isym].value], even_odd[1]);
isym++;
zzpos += 1 + sym[isym].type;
}
// Init odd/even: reconstruct first vert. AC coeff
if (isym < nsym && zzpos == 2) {
recon_vert_ac( (S32) recon[(U8)sym[isym].value], even_odd[2]);
isym++;
zzpos += 1 + sym[isym].type;
}
// Reconstruct remaining coeffs
// if (clean == YES) { // activate this for sleazy IDCT decoder
while (isym < nsym) {
//printf(" Calling update with zzpos = %d\n", zzpos);
update( &even_odd[ even_odd_index[zzpos]] [0],
(S32) recon[(U8)sym[isym].value],
(S32 (*)[8*8*8]) &idct_tab[0][zzpos][0]);
isym++;
zzpos += 1 + sym[isym].type;
}
// } // activate this for sleazy IDCT decoder
// else {
//
// Sleazy reconstruction
//
// while (isym < nsym && zzpos < 10) {
// //printf(" Calling update with zzpos = %d\n", zzpos);
// update( &even_odd[ even_odd_index[zzpos]] [0],
// (S32) recon[(U8)sym[isym].value],
// (U32 (*)[8*8*8]) &idct_tab[0][zzpos][0]);
// isym++;
// zzpos += 1 + sym[isym].type;
// }
// }
#endif
#ifdef LITTLE_ENDIAN
// Final butterflies
switch (idct_class)
{
// DC only case
case DC_ONLY:
{
temp[0] = even_odd[0][0];
temp[0] += (0x10001L << (FRACBITS-1));
x[0][0] = temp[0];
}
break;
// DC + 1 horizontal AC case
case DC_AC_H:
{
temp[0] = even_odd[0][0];
temp[0] += (0x10001L << (FRACBITS-1));
x[0][0] = temp[0] + even_odd[1][0];
x[0][2] = temp[0] - even_odd[1][0];
x[0][1] = temp[0] + even_odd[1][1];
x[0][3] = temp[0] - even_odd[1][1];
}
break;
// DC + 1 vertical AC case
case DC_AC_V:
{
for (i = 0; i < 4; i++)
{
temp[0] = even_odd[0][0] + even_odd[2][2*i];
temp[1] = even_odd[0][0] - even_odd[2][2*i];
temp[0] += (0x10001L << (FRACBITS-1));
temp[1] += (0x10001L << (FRACBITS-1));
x[i][0] = temp[0];
x[i][1] = temp[0];
x[i][2] = temp[0];
x[i][3] = temp[0];
x[7-i][0] = temp[1];
x[7-i][1] = temp[1];
x[7-i][2] = temp[1];
x[7-i][3] = temp[1];
}
}
break;
// DC + 1 vertical AC + 1 horizontal AC case
case DC_3:
{
for (i = 0; i < 4; i++)
{
temp[0] = even_odd[0][0] + even_odd[2][2*i];
temp[2] = even_odd[0][0] - even_odd[2][2*i];
temp[0] += (0x10001L << (FRACBITS-1));
temp[2] += (0x10001L << (FRACBITS-1));
x[i][0] = temp[0] + even_odd[1][2*i];
x[i][2] = temp[0] - even_odd[1][2*i];
x[7-i][0] = temp[2] + even_odd[1][2*i];
x[7-i][2] = temp[2] - even_odd[1][2*i];
x[i][1] = temp[0] + even_odd[1][2*i+1];
x[i][3] = temp[0] - even_odd[1][2*i+1];
x[7-i][1] = temp[2] + even_odd[1][2*i+1];
x[7-i][3] = temp[2] - even_odd[1][2*i+1];
}
}
break;
case GENERAL:
{
for (i = 0; i < 4; i++)
{
// j=0
temp[0] = even_odd[0][2*i] + even_odd[2][2*i];
temp[2] = even_odd[0][2*i] - even_odd[2][2*i];
temp[1] = even_odd[1][2*i] + even_odd[3][2*i];
temp[3] = even_odd[1][2*i] - even_odd[3][2*i];
temp[0] += (0x10001L << (FRACBITS-1)); /* Round */
x[i][0] = temp[0] + temp[1];
x[i][2] = temp[0] - temp[1];
temp[2] += (0x10001L << (FRACBITS-1)); /* Round */
x[7-i][0] = temp[2] + temp[3];
x[7-i][2] = temp[2] - temp[3];
// j=1
temp[0] = even_odd[0][2*i+1] + even_odd[2][2*i+1];
temp[2] = even_odd[0][2*i+1] - even_odd[2][2*i+1];
temp[1] = even_odd[1][2*i+1] + even_odd[3][2*i+1];
temp[3] = even_odd[1][2*i+1] - even_odd[3][2*i+1];
temp[0] += (0x10001L << (FRACBITS-1)); /* Round */
x[i][1] = temp[0] + temp[1];
x[i][3] = temp[0] - temp[1];
temp[2] += (0x10001L << (FRACBITS-1)); /* Round */
x[7-i][1] = temp[2] + temp[3];
x[7-i][3] = temp[2] - temp[3];
}
}
break;
default:
break;
}
#else
{
for (i = 0; i < 4; i++)
{
// j=0
temp[0] = even_odd[0][2*i] + even_odd[2][2*i];
temp[2] = even_odd[0][2*i] - even_odd[2][2*i];
temp[1] = even_odd[1][2*i] + even_odd[3][2*i];
temp[3] = even_odd[1][2*i] - even_odd[3][2*i];
temp[0] += (0x10001L << (FRACBITS-1)); /* Round */
x[i][0] = temp[0] + temp[1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -