/**
* 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;
/**
* based on H.263 decoder, (C) 1995, 1996 Telenor R&D, Norway
* Karl Olav Lillevold <Karl.Lillevold@nta.no>
*
* modified by Wayne Ellis BT Labs to run Annex E Arithmetic Decoding
* <ellis_w_wayne@bt-web.bt.co.uk>
*
* based on mpeg2decode, (C) 1994, MPEG Software Simulation Group
* and mpeg2play, (C) 1994 Stefan Eckart
* <stefan@lis.e-technik.tu-muenchen.de>
*/
/**
* VideoFrame
*
*/
public final class VideoFrame {
private int type;
private int buffer_width;
private int buffer_height;
private int frame_width;
private int frame_height;
private int[][] zero_block = new int[9][9];
private int[][] zero_block2 = new int[9][9];
private int[][][] lumminance_blocks;
private int[][][] cr_chrominace_blocks;
private int[][][] cb_chrominace_blocks;
private int lumminance_blocks_per_line;
private int chrominace_blocks_per_line;
private int previousQuantiserScale;
private int[][] previousBlock;
private int[][] macroblocks_info;
private IDCT idct;
private int[][] pixel_data;
private byte rounding_control;
private long playing_time;
/**
* Constructs a VideoFrame object.
*
* @param type
* @param width
* @param height
* @param bits_per_pixel
*/
public VideoFrame(int type, int width, int height, int bits_per_pixel) {
super();
this.type = type;
this.frame_width = buffer_width = width;
this.frame_height = buffer_height = height;
this.rounding_control = 0;
if ((buffer_width & 15) > 0) {
buffer_width = buffer_width - (buffer_width & 15) + 16;
}
if ((buffer_height & 15) > 0) {
buffer_height = buffer_height - (buffer_height & 15) + 16;
}
this.idct = new IDCT(buffer_width);
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
zero_block[i][j] = 0;
zero_block2[i][j] = 0;
}
}
// init DC value
zero_block[0][0] = 1 << (bits_per_pixel + 2);
this.lumminance_blocks_per_line = buffer_width >> 3;
this.chrominace_blocks_per_line = buffer_width >> 4;
this.lumminance_blocks = new int[(buffer_width >> 3)
* (buffer_height >> 3)][9][9];
this.cr_chrominace_blocks = new int[(buffer_width >> 4)
* (buffer_height >> 4)][9][9];
this.cb_chrominace_blocks = new int[(buffer_width >> 4)
* (buffer_height >> 4)][9][9];
this.macroblocks_info = new int[(buffer_width >> 4)
* (buffer_height >> 4)][10];
this.pixel_data = new int[3][buffer_width * buffer_height];
}
public void copyMacroblock(VideoFrame last_I_P_Frame, int macroblock_number) {
// set macroblock type and quantization information
macroblocks_info[macroblock_number][0] = 0;
macroblocks_info[macroblock_number][1] = 0;
// set motion vector data
macroblocks_info[macroblock_number][2] = macroblocks_info[macroblock_number][3] = macroblocks_info[macroblock_number][4] = macroblocks_info[macroblock_number][5] = 0;
macroblocks_info[macroblock_number][6] = macroblocks_info[macroblock_number][7] = macroblocks_info[macroblock_number][8] = macroblocks_info[macroblock_number][9] = 0;
// copy pixel data
int[][] src_pixel_data = last_I_P_Frame.getPixelData();
int x_index_c = macroblock_number % chrominace_blocks_per_line;
int y_index_c = macroblock_number / chrominace_blocks_per_line;
// copy lumminance data
int start_index = ((y_index_c * buffer_width) << 4) + (x_index_c << 4);
for (int i = 0; i < 16; i++) {
System.arraycopy(src_pixel_data[0], start_index, pixel_data[0],
start_index, 16);
start_index += buffer_width;
}
// copy chrominance data
start_index = ((y_index_c * buffer_width) << 3) + (x_index_c << 3);
for (int i = 0; i < 8; i++) {
System.arraycopy(src_pixel_data[1], start_index, pixel_data[1],
start_index, 8);
System.arraycopy(src_pixel_data[2], start_index, pixel_data[2],
start_index, 8);
start_index += buffer_width;
}
}
private int MVDx;
private int MVDy;
private int MVx;
private int MVy;
private int Px;
private int Py;
private boolean quarter_sample;
int[][][] predictor_indexes = {
// macroblock with one motion vector
{ // x y n x y n x y n
{ -1, 0, 1 }, { 0, -1, 2 }, { 1, -1, 2 } },
// macroblock with four motion vectors
// block (n = 0)
{ // x y n x y n x y n
{ -1, 0, 1 }, { 0, -1, 2 }, { 1, -1, 2 } },
// block (n = 1)
{ // x y n x y n x y n
{ 0, 0, 0 }, { 0, -1, 3 }, { 1, -1, 2 } },
// block (n = 2)
{ // x y n x y n x y n
{ -1, 0, 3 }, { 0, 0, 0 }, { 0, 0, 1 } },
// block (n = 3)
{ // x y n x y n x y n
{ 0, 0, 2 }, { 0, 0, 0 }, { 0, 0, 1 } } };
public void setForwardMotionVector(int macroblock_number, int block_number,
boolean quarter_sample, int vop_fcode_forward,
int horizontal_mv_data, byte horizontal_mv_residual,
int vertical_mv_data, byte vertical_mv_residual) {
this.quarter_sample = quarter_sample;
int x_index = macroblock_number % chrominace_blocks_per_line;
int y_index = macroblock_number / chrominace_blocks_per_line;
int max_x = chrominace_blocks_per_line - 1;
int[][] predictor_index = predictor_indexes[block_number + 1];
if (block_number != -1) {
x_index = (x_index << 1) + (block_number & 1);
y_index = (y_index << 1) + (block_number < 2 ? 0 : 1);
max_x = (chrominace_blocks_per_line << 1) - 1;
}
Px = 0;
Py = 0;
if (y_index == 0) {
if (x_index > 0) {
Px = macroblocks_info[macroblock_number + predictor_index[0][0]][2 + predictor_index[0][2]];
Py = macroblocks_info[macroblock_number + predictor_index[0][0]][6 + predictor_index[0][2]];
if (Px == Integer.MAX_VALUE) {
Px = 0;
Py = 0;
}
}
} else {
int MV1x = Integer.MAX_VALUE;
int MV2x = Integer.MAX_VALUE;
int MV3x = Integer.MAX_VALUE;
int MV1y = Integer.MAX_VALUE;
int MV2y = Integer.MAX_VALUE;
int MV3y = Integer.MAX_VALUE;
MV2x = macroblocks_info[macroblock_number
+ chrominace_blocks_per_line * predictor_index[1][1]][2 + predictor_index[1][2]];
MV2y = macroblocks_info[macroblock_number
+ chrominace_blocks_per_line * predictor_index[1][1]][6 + predictor_index[1][2]];
if (x_index == 0) {
MV3x = macroblocks_info[macroblock_number
+ chrominace_blocks_per_line * predictor_index[2][1]
+ predictor_index[2][0]][2 + predictor_index[2][2]];
MV3y = macroblocks_info[macroblock_number
+ chrominace_blocks_per_line * predictor_index[2][1]
+ predictor_index[2][0]][6 + predictor_index[2][2]];
} else if (x_index == max_x) {
MV1x = macroblocks_info[macroblock_number
+ predictor_index[0][0]][2 + predictor_index[0][2]];
MV1y = macroblocks_info[macroblock_number
+ predictor_index[0][0]][6 + predictor_index[0][2]];
} else {
MV1x = macroblocks_info[macroblock_number
+ predictor_index[0][0]][2 + predictor_index[0][2]];
MV1y = macroblocks_info[macroblock_number
+ predictor_index[0][0]][6 + predictor_index[0][2]];
MV3x = macroblocks_info[macroblock_number
+ chrominace_blocks_per_line * predictor_index[2][1]
+ predictor_index[2][0]][2 + predictor_index[2][2]];
MV3y = macroblocks_info[macroblock_number
+ chrominace_blocks_per_line * predictor_index[2][1]
+ predictor_index[2][0]][6 + predictor_index[2][2]];
}
int n = 3;
int mask = 0;
if (MV1x == Integer.MAX_VALUE) {
MV1x = MV1y = 0;
n--;
mask |= 1;
}
if (MV2x == Integer.MAX_VALUE) {
MV2x = MV2y = 0;
n--;
mask |= 2;
}
if (MV3x == Integer.MAX_VALUE) {
MV3x = MV3y = 0;
n--;
mask |= 4;
}
if (n == 1) {
if (mask == 6) {
Px = MV1x;
Py = MV1y;
} else if (mask == 5) {
Px = MV2x;
Py = MV2y;
} else if (mask == 3) {
Px = MV3x;
Py = MV3y;
}
} else if (n > 0) {
Px = MV1x + MV2x + MV3x - Math.max(MV3x, Math.max(MV1x, MV2x))
- Math.min(MV3x, Math.min(MV1x, MV2x));
Py = MV1y + MV2y + MV3y - Math.max(MV3y, Math.max(MV1y, MV2y))
- Math.min(MV3y, Math.min(MV1y, MV2y));
}
}
int r_size = vop_fcode_forward - 1;
int f = 1 << r_size;
int high = (32 * f) - 1;
int low = ((-32) * f);
int range = (64 * f);
if ((f == 1) || (horizontal_mv_data == 0))
MVDx = horizontal_mv_data;
else {
MVDx = ((Math.abs(horizontal_mv_data) - 1) * f)
+ horizontal_mv_residual + 1;
if (horizontal_mv_data < 0)
MVDx = -MVDx;
}
if ((f == 1) || (vertical_mv_data == 0))
MVDy = vertical_mv_data;
else {
MVDy = ((Math.abs(vertical_mv_data) - 1) * f)
+ vertical_mv_residual + 1;
if (vertical_mv_data < 0)
MVDy = -MVDy;
}
if (quarter_sample) {
// divides motion vector by 2 - try to emulate quarter sample mode
// with the half sample mode
MVDx >>= 1;
MVDy >>= 1;
low >>= 1;
high >>= 1;
}
MVx = MVDx + Px;
if (MVx < low)
MVx = MVx + range;
if (MVx > high)
MVx = MVx - range;
MVy = MVDy + Py;
if (MVy < low)
MVy = MVy + range;
if (MVy > high)
MVy = MVy - range;
if (block_number == -1) {
// one motion vector per macroblock
macroblocks_info[macroblock_number][2] = macroblocks_info[macroblock_number][3] = macroblocks_info[macroblock_number][4] = macroblocks_info[macroblock_number][5] = MVx;
macroblocks_info[macroblock_number][6] = macroblocks_info[macroblock_number][7] = macroblocks_info[macroblock_number][8] = macroblocks_info[macroblock_number][9] = MVy;
} else {
// four motion vectors per macroblock
macroblocks_info[macroblock_number][2 + block_number] = MVx;
macroblocks_info[macroblock_number][6 + block_number] = MVy;
}
}
private static final int[] roundtab = { 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 2, 2 };
public void applyForwardMotionVector(VideoFrame last_I_P_Frame,
int macroblock_number) {
int[][] src_pixel_data = last_I_P_Frame.getPixelData();
int x_index_c = macroblock_number % chrominace_blocks_per_line;
int y_index_c = macroblock_number / chrominace_blocks_per_line;
boolean half_x;
boolean half_y;
int[] dst_data = null;
int[] src_data = null;
int src_start_index = 0;
int dst_start_index = 0;
int block_width;
int motion_block_width = 16;
int motion_vectors = 1;
int MVCHx = 0;
int MVCHy = 0;
if (macroblocks_info[macroblock_number][0] == 2) {
// four motion vectors per macroblock
motion_vectors = 4;
motion_block_width = 8;
// calculates the chrominance motion vector
MVCHx = (macroblocks_info[macroblock_number][2]
+ macroblocks_info[macroblock_number][3]
+ macroblocks_info[macroblock_number][4] + macroblocks_info[macroblock_number][5]);
MVCHy = (macroblocks_info[macroblock_number][6]
+ macroblocks_info[macroblock_number][7]
+ macroblocks_info[macroblock_number][8] + macroblocks_info[macroblock_number][9]);
int y_sign = ((MVCHy >= 0) ? 1 : -1);
int x_sign = ((MVCHx >= 0) ? 1 : -1);
int y_abs = MVCHy * y_sign;
int x_abs = MVCHx * x_sign;
MVCHy = y_sign * (((y_abs >> 4) << 1) + roundtab[y_abs & 15]);
MVCHx = x_sign * (((x_abs >> 4) << 1) + roundtab[x_abs & 15]);
} else {
MVCHx = macroblocks_info[macroblock_number][2];
MVCHy = macroblocks_info[macroblock_number][6];
if ((MVCHx & 3) == 0) {
MVCHx = MVCHx >> 1;
} else {
MVCHx = (MVCHx >> 1) | 1;
}
if ((MVCHy & 3) == 0) {
MVCHy = MVCHy >> 1;
} else {
MVCHy = (MVCHy >> 1) | 1;
}
}
for (int block_number = 0; block_number < motion_vectors; block_number++) {
MVx = macroblocks_info[macroblock_number][2 + block_number];
MVy = macroblocks_info[macroblock_number][6 + block_number];
int x_index_block = (x_index_c << 1) + (block_number & 1);
int y_index_block = (y_index_c << 1) + (block_number < 2 ? 0 : 1);
if ((block_number == 0) && (MVCHx == 0) && (MVCHy == 0)) {
// process chrominance data
int[] dst_data_cb = pixel_data[1];
int[] dst_data_cr = pixel_data[2];
int[] src_data_cb = src_pixel_data[1];
int[] src_data_cr = src_pixel_data[2];
int start_index = (y_index_block << 2) * buffer_width
+ (x_index_block << 2);
for (int i = 0; i < 8; i++) {
for (int data_index = start_index; data_index < (start_index + 8); data_index += 4) {
dst_data_cr[data_index] += src_data_cr[data_index];
dst_data_cb[data_index] += src_data_cb[data_index];
dst_data_cr[data_index + 1] += src_data_cr[data_index + 1];
dst_data_cb[data_index + 1] += src_data_cb[data_index + 1];
dst_data_cr[data_index + 2] += src_data_cr[data_index + 2];
dst_data_cb[data_index + 2] += src_data_cb[data_index + 2];
dst_data_cr[data_index + 3] += src_data_cr[data_index + 3];
dst_data_cb[data_index + 3] += src_data_cb[data_index + 3];
}
start_index += buffer_width;
}
}
if ((MVy == 0) && (MVx == 0)) {
// apply zero motion vector
// process lumminance data
dst_data = pixel_data[0];
src_data = src_pixel_data[0];
int start_index = (y_index_block << 3) * buffer_width
+ (x_index_block << 3);
for (int i = 0; i < motion_block_width; i++) {
for (int data_index = start_index; data_index < (start_index + motion_block_width); data_index += 8) {
dst_data[data_index] += src_data[data_index];
dst_data[data_index + 1] += src_data[data_index + 1];
dst_data[data_index + 2] += src_data[data_index + 2];
dst_data[data_index + 3] += src_data[data_index + 3];
dst_data[data_index + 4] += src_data[data_index + 4];
dst_data[data_index + 5] += src_data[data_index + 5];
dst_data[data_index + 6] += src_data[data_index + 6];
dst_data[data_index + 7] += src_data[data_index + 7];
}
start_index += buffer_width;
}
}
for (int n = 0; n < (block_number == 0 ? 3 : 1); n++) {
int x_src_index = 0;
int y_src_index = 0;
int max_y = buffer_height;
int max_x = buffer_width;
if (n == 0) {
if ((MVy == 0) && (MVx == 0)) {
continue;
}
src_data = src_pixel_data[0];
dst_data = pixel_data[0];
half_x = (MVx & 1) == 1;
half_y = (MVy & 1) == 1;
block_width = motion_block_width;
x_src_index = (x_index_block << 3) + (MVx >> 1);
y_src_index = (y_index_block << 3) + (MVy >> 1);
dst_start_index = ((y_index_block * buffer_width) << 3)
+ (x_index_block << 3);
} else {
if ((MVCHx == 0) && (MVCHy == 0)) {
continue;
}
if (n == 1) {
src_data = src_pixel_data[1];
dst_data = pixel_data[1];
} else {
src_data = src_pixel_data[2];
dst_data = pixel_data[2];
}
max_y >>= 1;
max_x >>= 1;
block_width = 8;
half_x = (MVCHx & 1) == 1;
half_y = (MVCHy & 1) == 1;
x_src_index = (x_index_block << 2) + (MVCHx >> 1);
y_src_index = (y_index_block << 2) + (MVCHy >> 1);
dst_start_index = (y_index_block << 2) * buffer_width
+ (x_index_block << 2);
}
max_y--;
max_x--;
if ((half_x == false) && (half_y == false)) {
for (int i = 0; i < block_width; i++) {
if (y_src_index >= max_y) {
src_start_index = max_y * buffer_width;
} else if (y_src_index >= 0) {
src_start_index = y_src_index * buffer_width;
} else {
src_start_index = 0;
}
for (int j = 0, src_x = x_src_index; j < block_width; j++, src_x++) {
if (src_x >= max_x) {
dst_data[dst_start_index + j] += src_data[src_start_index
+ max_x];
} else if (src_x >= 0) {
dst_data[dst_start_index + j] += src_data[src_start_index
+ src_x];
} else {
dst_data[dst_start_index + j] += src_data[src_start_index];
}
}
y_src_index++;
dst_start_index += buffer_width;
}
} else if ((half_x == true) && (half_y == false)) {
for (int i = 0; i < block_width; i++) {
if (y_src_index >= max_y) {
src_start_index = max_y * buffer_width;
} else if (y_src_index >= 0) {
src_start_index = y_src_index * buffer_width;
} else {
src_start_index = 0;
}
for (int j = 0, src_x = x_src_index; j < block_width; j++, src_x++) {
if (src_x >= max_x) {
dst_data[dst_start_index + j] += src_data[src_start_index
+ max_x];
} else if (src_x >= 0) {
dst_data[dst_start_index + j] += (src_data[src_start_index
+ src_x]
+ src_data[src_start_index + src_x + 1]
+ 1 - rounding_control) >> 1;
} else {
dst_data[dst_start_index + j] += src_data[src_start_index];
}
}
y_src_index++;
dst_start_index += buffer_width;
}
} else if ((half_x == false) && (half_y == true)) {
for (int i = 0; i < block_width; i++, y_src_index++, dst_start_index += buffer_width) {
if ((y_src_index >= max_y) || (y_src_index < 0)) {
if (y_src_index >= max_y) {
src_start_index = max_y * buffer_width;
} else {
src_start_index = 0;
}
for (int j = 0, src_x = x_src_index; j < block_width; j++, src_x++) {
if (src_x >= max_x) {
dst_data[dst_start_index + j] += src_data[src_start_index
+ max_x];
} else if (src_x >= 0) {
dst_data[dst_start_index + j] += src_data[src_start_index
+ src_x];
} else {
dst_data[dst_start_index + j] += src_data[src_start_index];
}
}
continue;
}
src_start_index = y_src_index * buffer_width;
for (int j = 0, src_x = x_src_index; j < block_width; j++, src_x++) {
if (src_x >= max_x) {
dst_data[dst_start_index + j] += (src_data[src_start_index
+ max_x]
+ src_data[src_start_index + max_x
+ buffer_width] + 1 - rounding_control) >> 1;
} else if (src_x >= 0) {
dst_data[dst_start_index + j] += (src_data[src_start_index
+ src_x]
+ src_data[src_start_index + src_x
+ buffer_width] + 1 - rounding_control) >> 1;
} else {
dst_data[dst_start_index + j] += (src_data[src_start_index]
+ src_data[src_start_index
+ buffer_width] + 1 - rounding_control) >> 1;
}
}
}
} else if ((half_x == true) && (half_y == true)) {
for (int i = 0; i < block_width; i++, y_src_index++, dst_start_index += buffer_width) {
if ((y_src_index >= max_y) || (y_src_index < 0)) {
if (y_src_index >= max_y) {
src_start_index = max_y * buffer_width;
} else {
src_start_index = 0;
}
for (int j = 0, src_x = x_src_index; j < block_width; j++, src_x++) {
if (src_x >= max_x) {
dst_data[dst_start_index + j] += src_data[src_start_index
+ max_x];
} else if (src_x >= 0) {
dst_data[dst_start_index + j] += (src_data[src_start_index
+ src_x]
+ src_data[src_start_index + src_x
+ 1] + 1 - rounding_control) >> 1;
} else {
dst_data[dst_start_index + j] += src_data[src_start_index];
}
}
continue;
}
src_start_index = y_src_index * buffer_width;
for (int j = 0, src_x = x_src_index; j < block_width; j++, src_x++) {
if (src_x >= max_x) {
dst_data[dst_start_index + j] += (src_data[src_start_index
+ max_x]
+ src_data[src_start_index + max_x
+ buffer_width] + 1 - rounding_control) >> 1;
} else if (src_x >= 0) {
dst_data[dst_start_index + j] += (src_data[src_start_index
+ src_x]
+ src_data[src_start_index + src_x + 1]
+ src_data[src_start_index + src_x
+ buffer_width]
+ src_data[src_start_index + src_x
+ buffer_width + 1] + 2 - rounding_control) >> 2;
} else {
dst_data[dst_start_index + j] += (src_data[src_start_index]
+ src_data[src_start_index
+ buffer_width] + 1 - rounding_control) >> 1;
}
}
}
}
}
}
}
public int[][] getBlock(int macroblock_number, int n) {
int[][][] input_blocks = null;
int index = macroblock_number;
if (n < 4) {
int x_index = (macroblock_number % chrominace_blocks_per_line) * 2
+ (n & 1);
int y_index = (macroblock_number / chrominace_blocks_per_line) * 2
+ (n < 2 ? 0 : 1);
index = y_index * lumminance_blocks_per_line + x_index;
input_blocks = lumminance_blocks;
} else if (n == 4) {
index = macroblock_number;
input_blocks = cb_chrominace_blocks;
} else {
index = macroblock_number;
input_blocks = cr_chrominace_blocks;
}
if ((index < 0) || (index >= input_blocks.length)) {
return null;
}
return input_blocks[index];
}
public int[][] getPreviousBlock() {
return previousBlock;
}
public int getPreviousQuantiserScale() {
return previousQuantiserScale;
}
public void setMacroblockInfo(int macroblock_number, int type,
int quantiser_scale) {
macroblocks_info[macroblock_number][0] = type;
macroblocks_info[macroblock_number][1] = quantiser_scale;
if (type >= 3) {
// reset motion vector data
macroblocks_info[macroblock_number][2] = macroblocks_info[macroblock_number][3] = macroblocks_info[macroblock_number][4] = macroblocks_info[macroblock_number][5] = 0;
macroblocks_info[macroblock_number][6] = macroblocks_info[macroblock_number][7] = macroblocks_info[macroblock_number][8] = macroblocks_info[macroblock_number][9] = 0;
}
}
public boolean getPredictionDirection(int macroblock_number, int n) {
int[][] blockA = zero_block;
int[][] blockB = zero_block;
int[][] blockC = zero_block;
int[][][] input_blocks = null;
int x_index = macroblock_number % chrominace_blocks_per_line;
int y_index = macroblock_number / chrominace_blocks_per_line;
int blocks_per_line = 0;
int quantiser_scale_c = 0;
int quantiser_scale_a = 0;
int prev_macroblock_number;
int scale_factor = 0;
if (n < 4) {
x_index = x_index * 2 + (n & 1);
y_index = y_index * 2 + (n < 2 ? 0 : 1);
input_blocks = lumminance_blocks;
blocks_per_line = lumminance_blocks_per_line;
scale_factor = 1;
} else if (n == 4) {
input_blocks = cb_chrominace_blocks;
blocks_per_line = chrominace_blocks_per_line;
} else {
input_blocks = cr_chrominace_blocks;
blocks_per_line = chrominace_blocks_per_line;
}
int x_index_AB = x_index - 1;
int y_index_BC = y_index - 1;
if (x_index_AB >= 0) {
prev_macroblock_number = (y_index >> scale_factor)
* chrominace_blocks_per_line + (x_index_AB >> scale_factor);
if (macroblocks_info[prev_macroblock_number][0] > 2) {
blockA = input_blocks[y_index * blocks_per_line + x_index_AB];
quantiser_scale_a = macroblocks_info[prev_macroblock_number][1];
}
}
if (y_index_BC >= 0) {
prev_macroblock_number = (y_index_BC >> scale_factor)
* chrominace_blocks_per_line + (x_index >> scale_factor);
if (macroblocks_info[prev_macroblock_number][0] > 2) {
blockC = input_blocks[y_index_BC * blocks_per_line + x_index];
quantiser_scale_c = macroblocks_info[prev_macroblock_number][1];
}
}
if ((y_index_BC >= 0) && (x_index_AB >= 0)) {
prev_macroblock_number = (y_index_BC >> scale_factor)
* chrominace_blocks_per_line + (x_index_AB >> scale_factor);
if (macroblocks_info[prev_macroblock_number][0] > 2) {
blockB = input_blocks[y_index_BC * blocks_per_line + x_index_AB];
}
}
if (((Math.abs(blockA[0][0] - blockB[0][0]))) < (Math.abs(blockB[0][0]
- blockC[0][0]))) {
// predict from block C
previousBlock = blockC;
previousQuantiserScale = quantiser_scale_c;
return true;
} else {
// predict from block A
previousBlock = blockA;
previousQuantiserScale = quantiser_scale_a;
return false;
}
}
public void clearMacroblockInfo(int current_macroblock_num) {
if (current_macroblock_num > macroblocks_info.length) {
current_macroblock_num = macroblocks_info.length;
}
for (int i = 0; i < current_macroblock_num; i++) {
macroblocks_info[i][0] = macroblocks_info[i][1] = 0;
for (int j = 2; j < 10; j++) {
macroblocks_info[i][j] = Integer.MAX_VALUE;
}
}
}
public void clearFrame() {
int pixel_data_length = pixel_data[0].length;
for (int i = 0; i < macroblocks_info.length; i++) {
for (int j = 0; j < 10; j++) {
macroblocks_info[i][j] = 0;
}
}
for (int i = 0; i < pixel_data_length; i++) {
pixel_data[0][i] = 0;
pixel_data[1][i] = 128;
pixel_data[2][i] = 128;
}
}
public void transformBlock(int macroblock_number, int n) {
int[][][] input_blocks = null;
int index = macroblock_number;
int[] output_data = null;
int x_index = macroblock_number % chrominace_blocks_per_line;
int y_index = macroblock_number / chrominace_blocks_per_line;
if (n < 4) {
x_index = (x_index << 1) + (n & 1);
y_index = (y_index << 1) + (n < 2 ? 0 : 1);
index = y_index * lumminance_blocks_per_line + x_index;
input_blocks = lumminance_blocks;
output_data = pixel_data[0];
} else if (n == 4) {
input_blocks = cb_chrominace_blocks;
output_data = pixel_data[1];
} else {
input_blocks = cr_chrominace_blocks;
output_data = pixel_data[2];
}
if ((index < 0) || (index >= input_blocks.length)) {
return;
}
idct.idct(input_blocks[index], output_data,
((y_index * buffer_width) << 3) + (x_index << 3));
}
public int getFrameWidth() {
return frame_width;
}
public int getFrameHeight() {
return frame_height;
}
public int getBufferWidth() {
return buffer_width;
}
public int getBufferHeight() {
return buffer_height;
}
public int[][] getPixelData() {
return pixel_data;
}
public int[][] getMacroblocks_info() {
return macroblocks_info;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public void setRounding_control(byte rounding_control) {
this.rounding_control = rounding_control;
}
public void setPlaying_time(long playing_time) {
this.playing_time = playing_time;
}
public long getPlaying_time() {
return playing_time;
}
public static int[] getRoundtab() {
return roundtab;
}
public int getBuffer_height() {
return buffer_height;
}
public void setBuffer_height(int buffer_height) {
this.buffer_height = buffer_height;
}
public int getBuffer_width() {
return buffer_width;
}
public void setBuffer_width(int buffer_width) {
this.buffer_width = buffer_width;
}
public int[][][] getCb_chrominace_blocks() {
return cb_chrominace_blocks;
}
public void setCb_chrominace_blocks(int[][][] cb_chrominace_blocks) {
this.cb_chrominace_blocks = cb_chrominace_blocks;
}
public int getChrominace_blocks_per_line() {
return chrominace_blocks_per_line;
}
public void setChrominace_blocks_per_line(int chrominace_blocks_per_line) {
this.chrominace_blocks_per_line = chrominace_blocks_per_line;
}
public int[][][] getCr_chrominace_blocks() {
return cr_chrominace_blocks;
}
public void setCr_chrominace_blocks(int[][][] cr_chrominace_blocks) {
this.cr_chrominace_blocks = cr_chrominace_blocks;
}
public int getFrame_height() {
return frame_height;
}
public void setFrame_height(int frame_height) {
this.frame_height = frame_height;
}
public int getFrame_width() {
return frame_width;
}
public void setFrame_width(int frame_width) {
this.frame_width = frame_width;
}
public IDCT getIdct() {
return idct;
}
public void setIdct(IDCT idct) {
this.idct = idct;
}
public int[][][] getLumminance_blocks() {
return lumminance_blocks;
}
public void setLumminance_blocks(int[][][] lumminance_blocks) {
this.lumminance_blocks = lumminance_blocks;
}
public int getLumminance_blocks_per_line() {
return lumminance_blocks_per_line;
}
public void setLumminance_blocks_per_line(int lumminance_blocks_per_line) {
this.lumminance_blocks_per_line = lumminance_blocks_per_line;
}
public int getMVDx() {
return MVDx;
}
public void setMVDx(int dx) {
MVDx = dx;
}
public int getMVDy() {
return MVDy;
}
public void setMVDy(int dy) {
MVDy = dy;
}
public int getMVx() {
return MVx;
}
public void setMVx(int vx) {
MVx = vx;
}
public int getMVy() {
return MVy;
}
public void setMVy(int vy) {
MVy = vy;
}
public int[][] getPixel_data() {
return pixel_data;
}
public void setPixel_data(int[][] pixel_data) {
this.pixel_data = pixel_data;
}
public int[][][] getPredictor_indexes() {
return predictor_indexes;
}
public void setPredictor_indexes(int[][][] predictor_indexes) {
this.predictor_indexes = predictor_indexes;
}
public int getPx() {
return Px;
}
public void setPx(int px) {
Px = px;
}
public int getPy() {
return Py;
}
public void setPy(int py) {
Py = py;
}
public boolean isQuarter_sample() {
return quarter_sample;
}
public void setQuarter_sample(boolean quarter_sample) {
this.quarter_sample = quarter_sample;
}
public int[][] getZero_block() {
return zero_block;
}
public void setZero_block(int[][] zero_block) {
this.zero_block = zero_block;
}
public int[][] getZero_block2() {
return zero_block2;
}
public void setZero_block2(int[][] zero_block2) {
this.zero_block2 = zero_block2;
}
public byte getRounding_control() {
return rounding_control;
}
public void setMacroblocks_info(int[][] macroblocks_info) {
this.macroblocks_info = macroblocks_info;
}
public void setPreviousBlock(int[][] previousBlock) {
this.previousBlock = previousBlock;
}
public void setPreviousQuantiserScale(int previousQuantiserScale) {
this.previousQuantiserScale = previousQuantiserScale;
}
}