/*
* JaamSim Discrete Event Simulation
* Copyright (C) 2012 Ausenco Engineering Canada Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jaamsim.video.vp8;
public class Pred {
public static void predictDC(int x, int y, boolean yBlock, int stride, byte[] plane) {
int val = 0;
int blockSize = yBlock ? 16 : 8;
int shift = yBlock ? 5 : 4;
if (x == 0 && y == 0) {
val = 128;
} else if (x == 0) {
for (int i = 0; i < blockSize; ++i) {
val += Util.getUByte(plane,(y-1)*stride + x + i);
}
val += blockSize >> 1; // average
val = val >> (shift - 1);
} else if (y == 0) {
for (int i = 0; i < blockSize; ++i) {
val += Util.getUByte(plane,(y+i)*stride + x -1);
}
val += blockSize >> 1;
val = val >> (shift - 1);
} else {
for (int i = 0; i < blockSize; ++i) {
val += Util.getUByte(plane,(y-1)*stride + x + i);
val += Util.getUByte(plane,(y+i)*stride + x -1);
}
val += blockSize;
val = val >> shift;
}
for (int j = 0; j < blockSize; ++j) {
for (int i = 0; i < blockSize; ++i) {
plane[(y+j)*stride+x+i] = (byte)val;
}
}
}
public static void predictV(int x, int y, boolean yBlock, int stride, byte[] plane) {
int blockSize = yBlock ? 16 : 8;
if (y == 0) {
for (int j = 0; j < blockSize; ++j) {
for (int i = 0; i < blockSize; ++i) {
plane[(y+j)*stride+x+i] = (byte)127;
}
}
return;
}
for (int i = 0; i < blockSize; ++i) {
byte val = (byte)Util.getUByte(plane,(y-1)*stride+x+i);
for (int j = 0; j < blockSize; ++j) {
plane[(y+j)*stride+x+i] = val;
}
}
}
public static void predictH(int x, int y, boolean yBlock, int stride, byte[] plane) {
int blockSize = yBlock ? 16 : 8;
if (x == 0) {
for (int j = 0; j < blockSize; ++j) {
for (int i = 0; i < blockSize; ++i) {
plane[(y+j)*stride+x+i] = (byte)129;
}
}
return;
}
for (int j = 0; j < blockSize; ++j) {
byte val = (byte)Util.getUByte(plane,(y+j)*stride+x-1);
for (int i = 0; i < blockSize; ++i) {
plane[(y+j)*stride+x+i] = val;
}
}
}
public static void predictTM(int x, int y, boolean yBlock, int stride, byte[] plane) {
int blockSize = yBlock ? 16 : 8;
int p = 0;
if (x == 0 && y == 0) {
p = 128;
} else if (x == 0) {
p = 129;
} else if (y == 0) {
p = 127;
} else {
p = Util.getUByte(plane,(y-1)*stride+x-1);
}
int[] l = new int[blockSize];
int[] a = new int[blockSize];
for (int i = 0; i < blockSize; ++i) {
l[i] = (x==0)?129:Util.getUByte(plane,(y+i)*stride+x-1);
a[i] = (y==0)?127:Util.getUByte(plane,(y-1)*stride+x+i);
}
for (int j = 0; j < blockSize; ++j) {
for (int i = 0; i < blockSize; ++i) {
int val = Util.clamp255(a[i] + l[j] - p);
plane[(y+j)*stride+x+i] = (byte)val;
}
}
}
public static void predictBSubBlock(int blockX, int blockY, int subX, int subY, int subMode, int stride, byte[] plane) {
int[] e = new int[13];
// left
if (subX == 0) {
e[0] = e[1] = e[2] = e[3] = 129;
} else {
e[0] = Util.getUByte(plane,(subY+3)*stride + subX - 1);
e[1] = Util.getUByte(plane,(subY+2)*stride + subX - 1);
e[2] = Util.getUByte(plane,(subY+1)*stride + subX - 1);
e[3] = Util.getUByte(plane,(subY+0)*stride + subX - 1);
}
// Top
if (subY == 0) {
e[5] = e[6] = e[7] = e[8] = e[9] = e[10] = e[11] = e[12] = 127;
} else {
// Right top
e[5] = Util.getUByte(plane,(subY-1)*stride + subX + 0);
e[6] = Util.getUByte(plane,(subY-1)*stride + subX + 1);
e[7] = Util.getUByte(plane,(subY-1)*stride + subX + 2);
e[8] = Util.getUByte(plane,(subY-1)*stride + subX + 3);
if (subX + 4 == stride) {
if (blockY == 0) {
e[ 9] = e[10] = e[11] = e[12] = 127;
} else {
e[ 9] = e[10] = e[11] = e[12] = Util.getUByte(plane,(blockY-1)*stride + subX+3); // equal to the pixel above the right edge
}
} else if (subX - blockX == 12) { // We are in the 4th column,
if (blockY == 0) {
e[ 9] = e[10] = e[11] = e[12] = 127;
} else {
e[ 9] = Util.getUByte(plane,(blockY-1)*stride + subX + 4);
e[10] = Util.getUByte(plane,(blockY-1)*stride + subX + 5);
e[11] = Util.getUByte(plane,(blockY-1)*stride + subX + 6);
e[12] = Util.getUByte(plane,(blockY-1)*stride + subX + 7);
}
} else {
e[ 9] = Util.getUByte(plane,(subY-1)*stride + subX + 4);
e[10] = Util.getUByte(plane,(subY-1)*stride + subX + 5);
e[11] = Util.getUByte(plane,(subY-1)*stride + subX + 6);
e[12] = Util.getUByte(plane,(subY-1)*stride + subX + 7);
}
}
if (subX == 0 && subY == 0) {
e[4] = 128;
} else if (subX == 0) {
e[4] = 129;
} else if (subY == 0) {
e[4] = 127;
} else {
e[4] = Util.getUByte(plane,(subY-1)*stride + subX - 1);
}
switch(subMode) {
case Defs.B_DC_PRED:
predictBDC(subX, subY, e, stride, plane);
break;
case Defs.B_V_PRED:
predictBVE(subX, subY, e, stride, plane);
break;
case Defs.B_H_PRED:
predictBHE(subX, subY, e, stride, plane);
break;
case Defs.B_TM_PRED:
predictBTM(subX, subY, e, stride, plane);
break;
case Defs.B_LD_PRED:
predictBLD(subX, subY, e, stride, plane);
break;
case Defs.B_RD_PRED:
predictBRD(subX, subY, e, stride, plane);
break;
case Defs.B_VR_PRED:
predictBVR(subX, subY, e, stride, plane);
break;
case Defs.B_VL_PRED:
predictBVL(subX, subY, e, stride, plane);
break;
case Defs.B_HD_PRED:
predictBHD(subX, subY, e, stride, plane);
break;
case Defs.B_HU_PRED:
predictBHU(subX, subY, e, stride, plane);
break;
default:
assert(false);
}
}
private static void predictBDC(int x, int y, int[] e, int stride, byte[] plane) {
int val = 4;
for (int i = 0; i < 4; ++i) {
val += e[i] + e[5+i]; // edge left and above
}
val = val >> 3;
for (int j = 0; j < 4; ++j) {
for (int i = 0; i < 4; ++i) {
plane[(y+j)*stride+x+i] = (byte)val;
}
}
}
private static void predictBVE(int x, int y, int[] e, int stride, byte[] plane) {
for (int i = 0; i < 4; ++i) {
int val = Util.avg3(e[4+i], e[5+i], e[6+i]);
for (int j = 0; j < 4; ++j) {
plane[(y+j)*stride+x+i] = (byte)val;
}
}
}
private static void predictBHE(int x, int y, int[] e, int stride, byte[] plane) {
for (int j = 0; j < 4; ++j) {
int val = Util.avg3(e[4-j], e[3-j], (j == 3) ? e[0] : e[2-j]);
for (int i = 0; i < 4; ++i) {
plane[(y+j)*stride+x+i] = (byte)val;
}
}
}
private static void predictBTM(int x, int y, int[] e, int stride, byte[] plane) {
for (int j = 0; j < 4; ++j) {
for (int i = 0; i < 4; ++i) {
int val = Util.clamp255(e[5+i] + e[3-j] - e[4]);
plane[(y+j)*stride+x+i] = (byte)val;
}
}
}
private static void predictBLD(int x, int y, int[] e, int stride, byte[] plane) {
int val = Util.avg3(e[5], e[6], e[7]);
plane[(y+0)*stride+x+0] = (byte)val;
val = Util.avg3(e[6], e[7], e[8]);
plane[(y+1)*stride+x+0] = (byte)val;
plane[(y+0)*stride+x+1] = (byte)val;
val = Util.avg3(e[7], e[8], e[9]);
plane[(y+2)*stride+x+0] = (byte)val;
plane[(y+1)*stride+x+1] = (byte)val;
plane[(y+0)*stride+x+2] = (byte)val;
val = Util.avg3(e[8], e[9], e[10]);
plane[(y+3)*stride+x+0] = (byte)val;
plane[(y+2)*stride+x+1] = (byte)val;
plane[(y+1)*stride+x+2] = (byte)val;
plane[(y+0)*stride+x+3] = (byte)val;
val = Util.avg3(e[9], e[10], e[11]);
plane[(y+3)*stride+x+1] = (byte)val;
plane[(y+2)*stride+x+2] = (byte)val;
plane[(y+1)*stride+x+3] = (byte)val;
val = Util.avg3(e[10], e[11], e[12]);
plane[(y+3)*stride+x+2] = (byte)val;
plane[(y+2)*stride+x+3] = (byte)val;
val = Util.avg3(e[11], e[12], e[12]);
plane[(y+3)*stride+x+3] = (byte)val;
}
private static void predictBRD(int x, int y, int[] e, int stride, byte[] plane) {
int val = Util.avg3(e[0], e[1], e[2]);
plane[(y+3)*stride+x+0] = (byte)val;
val = Util.avg3(e[1], e[2], e[3]);
plane[(y+3)*stride+x+1] = (byte)val;
plane[(y+2)*stride+x+0] = (byte)val;
val = Util.avg3(e[2], e[3], e[4]);
plane[(y+3)*stride+x+2] = (byte)val;
plane[(y+2)*stride+x+1] = (byte)val;
plane[(y+1)*stride+x+0] = (byte)val;
val = Util.avg3(e[3], e[4], e[5]);
plane[(y+3)*stride+x+3] = (byte)val;
plane[(y+2)*stride+x+2] = (byte)val;
plane[(y+1)*stride+x+1] = (byte)val;
plane[(y+0)*stride+x+0] = (byte)val;
val = Util.avg3(e[4], e[5], e[6]);
plane[(y+2)*stride+x+3] = (byte)val;
plane[(y+1)*stride+x+2] = (byte)val;
plane[(y+0)*stride+x+1] = (byte)val;
val = Util.avg3(e[5], e[6], e[7]);
plane[(y+1)*stride+x+3] = (byte)val;
plane[(y+0)*stride+x+2] = (byte)val;
val = Util.avg3(e[6], e[7], e[8]);
plane[(y+0)*stride+x+3] = (byte)val;
}
private static void predictBVR(int x, int y, int[] e, int stride, byte[] plane) {
int val = Util.avg3(e[1], e[2], e[3]);
plane[(y+3)*stride+x+0] = (byte)val;
val = Util.avg3(e[2], e[3], e[4]);
plane[(y+2)*stride+x+0] = (byte)val;
val = Util.avg3(e[3], e[4], e[5]);
plane[(y+3)*stride+x+1] = (byte)val;
plane[(y+1)*stride+x+0] = (byte)val;
val = Util.avg2(e[4], e[5]);
plane[(y+2)*stride+x+1] = (byte)val;
plane[(y+0)*stride+x+0] = (byte)val;
val = Util.avg3(e[4], e[5], e[6]);
plane[(y+3)*stride+x+2] = (byte)val;
plane[(y+1)*stride+x+1] = (byte)val;
val = Util.avg2(e[5], e[6]);
plane[(y+2)*stride+x+2] = (byte)val;
plane[(y+0)*stride+x+1] = (byte)val;
val = Util.avg3(e[5], e[6], e[7]);
plane[(y+3)*stride+x+3] = (byte)val;
plane[(y+1)*stride+x+2] = (byte)val;
val = Util.avg2(e[6], e[7]);
plane[(y+2)*stride+x+3] = (byte)val;
plane[(y+0)*stride+x+2] = (byte)val;
val = Util.avg3(e[6], e[7], e[8]);
plane[(y+1)*stride+x+3] = (byte)val;
val = Util.avg2(e[7], e[8]);
plane[(y+0)*stride+x+3] = (byte)val;
}
private static void predictBVL(int x, int y, int[] e, int stride, byte[] plane) {
int val = Util.avg2(e[5], e[6]);
plane[(y+0)*stride+x+0] = (byte)val;
val = Util.avg3(e[5], e[6], e[7]);
plane[(y+1)*stride+x+0] = (byte)val;
val = Util.avg2(e[6], e[7]);
plane[(y+2)*stride+x+0] = (byte)val;
plane[(y+0)*stride+x+1] = (byte)val;
val = Util.avg3(e[6], e[7], e[8]);
plane[(y+1)*stride+x+1] = (byte)val;
plane[(y+3)*stride+x+0] = (byte)val;
val = Util.avg2(e[7], e[8]);
plane[(y+2)*stride+x+1] = (byte)val;
plane[(y+0)*stride+x+2] = (byte)val;
val = Util.avg3(e[7], e[8], e[9]);
plane[(y+3)*stride+x+1] = (byte)val;
plane[(y+1)*stride+x+2] = (byte)val;
val = Util.avg2(e[8], e[9]);
plane[(y+2)*stride+x+2] = (byte)val;
plane[(y+0)*stride+x+3] = (byte)val;
val = Util.avg3(e[8], e[9], e[10]);
plane[(y+3)*stride+x+2] = (byte)val;
plane[(y+1)*stride+x+3] = (byte)val;
val = Util.avg3(e[9], e[10], e[11]);
plane[(y+2)*stride+x+3] = (byte)val;
val = Util.avg3(e[10], e[11], e[12]);
plane[(y+3)*stride+x+3] = (byte)val;
}
private static void predictBHD(int x, int y, int[] e, int stride, byte[] plane) {
int val = Util.avg2(e[0], e[1]);
plane[(y+3)*stride+x+0] = (byte)val;
val = Util.avg3(e[0], e[1], e[2]);
plane[(y+3)*stride+x+1] = (byte)val;
val = Util.avg2(e[1], e[2]);
plane[(y+2)*stride+x+0] = (byte)val;
plane[(y+3)*stride+x+2] = (byte)val;
val = Util.avg3(e[1], e[2], e[3]);
plane[(y+2)*stride+x+1] = (byte)val;
plane[(y+3)*stride+x+3] = (byte)val;
val = Util.avg2(e[2], e[3]);
plane[(y+2)*stride+x+2] = (byte)val;
plane[(y+1)*stride+x+0] = (byte)val;
val = Util.avg3(e[2], e[3], e[4]);
plane[(y+2)*stride+x+3] = (byte)val;
plane[(y+1)*stride+x+1] = (byte)val;
val = Util.avg2(e[3], e[4]);
plane[(y+1)*stride+x+2] = (byte)val;
plane[(y+0)*stride+x+0] = (byte)val;
val = Util.avg3(e[3], e[4], e[5]);
plane[(y+1)*stride+x+3] = (byte)val;
plane[(y+0)*stride+x+1] = (byte)val;
val = Util.avg3(e[4], e[5], e[6]);
plane[(y+0)*stride+x+2] = (byte)val;
val = Util.avg3(e[5], e[6], e[7]);
plane[(y+0)*stride+x+3] = (byte)val;
}
private static void predictBHU(int x, int y, int[] e, int stride, byte[] plane) {
int val = Util.avg2(e[2], e[3]);
plane[(y+0)*stride+x+0] = (byte)val;
val = Util.avg3(e[1], e[2], e[3]);
plane[(y+0)*stride+x+1] = (byte)val;
val = Util.avg2(e[1], e[2]);
plane[(y+0)*stride+x+2] = (byte)val;
plane[(y+1)*stride+x+0] = (byte)val;
val = Util.avg3(e[0], e[1], e[2]);
plane[(y+0)*stride+x+3] = (byte)val;
plane[(y+1)*stride+x+1] = (byte)val;
val = Util.avg2(e[0], e[1]);
plane[(y+1)*stride+x+2] = (byte)val;
plane[(y+2)*stride+x+0] = (byte)val;
val = Util.avg3(e[0], e[0], e[1]);
plane[(y+1)*stride+x+3] = (byte)val;
plane[(y+2)*stride+x+1] = (byte)val;
val = e[0];
plane[(y+2)*stride+x+2] = (byte)val;
plane[(y+2)*stride+x+3] = (byte)val;
plane[(y+3)*stride+x+0] = (byte)val;
plane[(y+3)*stride+x+1] = (byte)val;
plane[(y+3)*stride+x+2] = (byte)val;
plane[(y+3)*stride+x+3] = (byte)val;
}
}