/**
* MediaFrame is an Open Source streaming media platform in Java
* which provides a fast, easy to implement and extremely small applet
* that enables to view your audio/video content without having
* to rely on external player applications or bulky plug-ins.
*
* Copyright (C) 2004/5 MediaFrame (http://www.mediaframe.org).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
package mediaframe.mpeg4.video;
/************************************************************************
*
* idct.c, inverse fast DCT for tmndecode (H.263 decoder)
* Copyright (C) 1995, 1996 Telenor R&D, Norway
* Karl Olav Lillevold <Karl.Lillevold@nta.no>
*
* Contacts:
* Karl Olav Lillevold <Karl.Lillevold@nta.no>, or
* Robert Danielsen <Robert.Danielsen@nta.no>
*
* Telenor Research and Development http://www.nta.no/brukere/DVC/
* P.O.Box 83 tel.: +47 63 84 84 00
* N-2007 Kjeller, Norway fax.: +47 63 81 00 76
*
************************************************************************/
/*
* Disclaimer of Warranty
*
* These software programs are available to the user without any license
* fee or royalty on an "as is" basis. Telenor Research and Development
* disclaims any and all warranties, whether express, implied, or statuary,
* including any implied warranties or merchantability or of fitness for a
* particular purpose. In no event shall the copyright-holder be liable
* for any incidental, punitive, or consequential damages of any kind
* whatsoever arising from the use of these programs.
*
* This disclaimer of warranty extends to the user of these programs and
* user's customers, employees, agents, transferees, successors, and
* assigns.
*
* Telenor Research and Development does not represent or warrant that the
* programs furnished hereunder are free of infringement of any third-party
* patents.
*
* Commercial implementations of H.263, including shareware, are subject to
* royalty fees to patent holders. Many of these patents are general
* enough such that they are unavoidable regardless of implementation
* design.
*
*/
/*
* based on mpeg2decode, (C) 1994, MPEG Software Simulation Group
* and mpeg2play, (C) 1994 Stefan Eckart
* <stefan@lis.e-technik.tu-muenchen.de>
*
*/
/**********************************************************
/* inverse two dimensional DCT, Chen-Wang algorithm *
/* (cf. IEEE ASSP-32, pp. 803-816, Aug. 1984) *
/* 32-bit integer arithmetic (8 bit coefficients) *
/* 11 mults, 29 adds per DCT *
/* sE, 18.8.91 *
/**********************************************************
/* coefficients extended to 12 bit for IEEE1180-1990 *
/* compliance sE, 2.1.94 *
/**********************************************************/
/**
* IDCT
*
*/
public final class IDCT {
/* this code assumes >> to be a two's-complement arithmetic */
/* right shift: (-2)>>1 == -1 , (-3)>>1 == -2 */
private final static int W1 = 2841; /* 2048*sqrt(2)*cos(1*pi/16) */
private final static int W2 = 2676; /* 2048*sqrt(2)*cos(2*pi/16) */
private final static int W3 = 2408; /* 2048*sqrt(2)*cos(3*pi/16) */
private final static int W5 = 1609; /* 2048*sqrt(2)*cos(5*pi/16) */
private final static int W6 = 1108; /* 2048*sqrt(2)*cos(6*pi/16) */
private final static int W7 = 565; /* 2048*sqrt(2)*cos(7*pi/16) */
private int pixels_per_line;
private int line_1_index;
private int line_2_index;
private int line_3_index;
private int line_4_index;
private int line_5_index;
private int line_6_index;
private int line_7_index;
public IDCT(int pixels_per_line) {
super();
line_1_index = 1 * pixels_per_line;
line_2_index = 2 * pixels_per_line;
line_3_index = 3 * pixels_per_line;
line_4_index = 4 * pixels_per_line;
line_5_index = 5 * pixels_per_line;
line_6_index = 6 * pixels_per_line;
line_7_index = 7 * pixels_per_line;
this.pixels_per_line = pixels_per_line;
}
int x0, x1, x2, x3, x4, x5, x6, x7, x8;
/*
* row (horizontal) IDCT
*
* 7 pi 1 dst[k] = sum c[l] * src[l] * cos( -- * ( k + - ) * l ) l=0 8 2
*
* where: c[0] = 128 c[1..7] = 128*sqrt(2)
*/
private void idctrow(int[] blk, int[] pixel_data, int block_pointer) {
/* shortcut */
if (((x1 = blk[4] << 11) | (x2 = blk[6]) | (x3 = blk[2])
| (x4 = blk[1]) | (x5 = blk[7]) | (x6 = blk[5]) | (x7 = blk[3])) == 0) {
pixel_data[block_pointer] = pixel_data[block_pointer + 1] = pixel_data[block_pointer + 2] = pixel_data[block_pointer + 3] = pixel_data[block_pointer + 4] = pixel_data[block_pointer + 5] = pixel_data[block_pointer + 6] = pixel_data[block_pointer + 7] = blk[0] << 3;
return;
}
x0 = (blk[0] << 11) + 128; /* for proper rounding in the fourth stage */
/* first stage */
x8 = W7 * (x4 + x5);
x4 = x8 + (W1 - W7) * x4;
x5 = x8 - (W1 + W7) * x5;
x8 = W3 * (x6 + x7);
x6 = x8 - (W3 - W5) * x6;
x7 = x8 - (W3 + W5) * x7;
/* second stage */
x8 = x0 + x1;
x0 -= x1;
x1 = W6 * (x3 + x2);
x2 = x1 - (W2 + W6) * x2;
x3 = x1 + (W2 - W6) * x3;
x1 = x4 + x6;
x4 -= x6;
x6 = x5 + x7;
x5 -= x7;
/* third stage */
x7 = x8 + x3;
x8 -= x3;
x3 = x0 + x2;
x0 -= x2;
x2 = (181 * (x4 + x5) + 128) >> 8;
x4 = (181 * (x4 - x5) + 128) >> 8;
/* fourth stage */
pixel_data[block_pointer] = (x7 + x1) >> 8;
pixel_data[block_pointer + 1] = (x3 + x2) >> 8;
pixel_data[block_pointer + 2] = (x0 + x4) >> 8;
pixel_data[block_pointer + 3] = (x8 + x6) >> 8;
pixel_data[block_pointer + 4] = (x8 - x6) >> 8;
pixel_data[block_pointer + 5] = (x0 - x4) >> 8;
pixel_data[block_pointer + 6] = (x3 - x2) >> 8;
pixel_data[block_pointer + 7] = (x7 - x1) >> 8;
}
/*
* column (vertical) IDCT
*
* 7 pi 1 dst[8*k] = sum c[l] * src[8*l] * cos( -- * ( k + - ) * l ) l=0 8 2
*
* where: c[0] = 1/1024 c[1..7] = (1/1024)*sqrt(2)
*/
private void idctcol(int[] pixel_data, int block_pointer) {
/* shortcut */
if (((x1 = (pixel_data[block_pointer + line_4_index] << 8))
| (x2 = pixel_data[block_pointer + line_6_index])
| (x3 = pixel_data[block_pointer + line_2_index])
| (x4 = pixel_data[block_pointer + line_1_index])
| (x5 = pixel_data[block_pointer + line_7_index])
| (x6 = pixel_data[block_pointer + line_5_index]) | (x7 = pixel_data[block_pointer
+ line_3_index])) == 0) {
pixel_data[block_pointer] = pixel_data[block_pointer + line_1_index] = pixel_data[block_pointer
+ line_2_index] = pixel_data[block_pointer + line_3_index] = pixel_data[block_pointer
+ line_4_index] = pixel_data[block_pointer + line_5_index] = pixel_data[block_pointer
+ line_6_index] = pixel_data[block_pointer + line_7_index] = ((pixel_data[block_pointer] + 32) >> 6);
return;
}
x0 = (pixel_data[block_pointer] << 8) + 8192;
/* first stage */
x8 = W7 * (x4 + x5) + 4;
x4 = (x8 + (W1 - W7) * x4) >> 3;
x5 = (x8 - (W1 + W7) * x5) >> 3;
x8 = W3 * (x6 + x7) + 4;
x6 = (x8 - (W3 - W5) * x6) >> 3;
x7 = (x8 - (W3 + W5) * x7) >> 3;
/* second stage */
x8 = x0 + x1;
x0 -= x1;
x1 = W6 * (x3 + x2) + 4;
x2 = (x1 - (W2 + W6) * x2) >> 3;
x3 = (x1 + (W2 - W6) * x3) >> 3;
x1 = x4 + x6;
x4 -= x6;
x6 = x5 + x7;
x5 -= x7;
/* third stage */
x7 = x8 + x3;
x8 -= x3;
x3 = x0 + x2;
x0 -= x2;
x2 = (181 * (x4 + x5) + 128) >> 8;
x4 = (181 * (x4 - x5) + 128) >> 8;
/* fourth stage */
pixel_data[block_pointer] = ((x7 + x1) >> 14);
pixel_data[block_pointer + line_1_index] = ((x3 + x2) >> 14);
pixel_data[block_pointer + line_2_index] = ((x0 + x4) >> 14);
pixel_data[block_pointer + line_3_index] = ((x8 + x6) >> 14);
pixel_data[block_pointer + line_4_index] = ((x8 - x6) >> 14);
pixel_data[block_pointer + line_5_index] = ((x0 - x4) >> 14);
pixel_data[block_pointer + line_6_index] = ((x3 - x2) >> 14);
pixel_data[block_pointer + line_7_index] = ((x7 - x1) >> 14);
}
/* two dimensional inverse discrete cosine transform */
public void idct(int[][] block, int[] pixel_data, int block_pointer) {
int i;
for (i = 0; i < 8; i++)
idctrow(block[i], pixel_data, block_pointer + i * pixels_per_line);
for (i = 0; i < 8; i++)
idctcol(pixel_data, block_pointer + i);
}
}