/* This file is part of javavp8decoder.
javavp8decoder 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 3 of the License, or
(at your option) any later version.
javavp8decoder 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 javavp8decoder. If not, see .
*/
package net.sourceforge.plantuml.webp;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Vector;
import javax.imageio.event.IIOReadProgressListener;
import javax.imageio.stream.ImageInputStream;
public class VP8Frame {
private static int BLOCK_TYPES = 4;
private static int COEF_BANDS = 8;
private static int MAX_ENTROPY_TOKENS = 12;
private static int MAX_MODE_LF_DELTAS = 4;
private static int MAX_REF_LF_DELTAS = 4;
private static int PREV_COEF_CONTEXTS = 3;
private ArrayList _listeners = new ArrayList();
private int bufferCount;
private int buffersToCreate=1;
private int[][][][] coefProbs;
private boolean debug=false;
private int filterLevel;
private int filterType;
private ImageInputStream frame;
private int frameType;
private int height;
private int macroBlockCols;
private int macroBlockNoCoeffSkip;
private int macroBlockRows;
private MacroBlock[][] macroBlocks;
private int macroBlockSegementAbsoluteDelta;
private int[] macroBlockSegmentTreeProbs;
private int[] modeLoopFilterDeltas = new int[MAX_MODE_LF_DELTAS];
private int modeRefLoopFilterDeltaEnabled;
private int modeRefLoopFilterDeltaUpdate;
private int multiTokenPartition = 0;
private long offset;
private int[] refLoopFilterDeltas = new int[MAX_REF_LF_DELTAS];
private int refreshEntropyProbs;
private int refreshLastFrame;
private int segmentationIsEnabled;
private SegmentQuants segmentQuants;
private int sharpnessLevel;
private int simpleFilter;
private BoolDecoder tokenBoolDecoder;
private Vector tokenBoolDecoders;
private int updateMacroBlockSegmentationMap;
private int updateMacroBlockSegmentatonData;
private int width;
public VP8Frame(ImageInputStream stream) throws IOException {
this.frame = stream;
offset = frame.getStreamPosition();
this.coefProbs=Globals.getDefaultCoefProbs();
tokenBoolDecoders = new Vector();
}
public VP8Frame(ImageInputStream stream, int[][][][] coefProbs) throws IOException {
this.frame = stream;
offset = frame.getStreamPosition();
this.coefProbs=coefProbs;
tokenBoolDecoders = new Vector();
}
public void addIIOReadProgressListener(IIOReadProgressListener listener) {
_listeners.add(listener);
}
private void createMacroBlocks() {
macroBlocks = new MacroBlock[macroBlockCols+2][macroBlockRows+2];
for(int x=0; x> 4;
macroBlockCols=tWidth >> 4;
createMacroBlocks();
BoolDecoder bc = new BoolDecoder(frame, offset);
if (frameType == 0) {
int clr_type = bc.readBit();
int clamp_type = bc.readBit();
}
segmentationIsEnabled = bc.readBit();
if (segmentationIsEnabled > 0) {
updateMacroBlockSegmentationMap = bc.readBit();
updateMacroBlockSegmentatonData = bc.readBit();
if(updateMacroBlockSegmentatonData > 0 ) {
macroBlockSegementAbsoluteDelta = bc.readBit();
/* For each segmentation feature (Quant and loop filter level) */
for (int i = 0; i < Globals.MAX_MB_SEGMENTS; i++) {
int value =0;
if (bc.readBit() > 0) {
value = bc.readLiteral(Globals.vp8MacroBlockFeatureDataBits[0]);
if(bc.readBit()>0)
value=-value;
}
this.segmentQuants.getSegQuants()[i].setQindex(value);
}
for (int i = 0; i < Globals.MAX_MB_SEGMENTS; i++) {
int value = 0;
if (bc.readBit() > 0) {
value = bc.readLiteral(Globals.vp8MacroBlockFeatureDataBits[1]);
if(bc.readBit()>0)
value=-value;
}
this.segmentQuants.getSegQuants()[i].setFilterStrength(value);
}
if(updateMacroBlockSegmentationMap > 0) {
macroBlockSegmentTreeProbs = new int[Globals.MB_FEATURE_TREE_PROBS];
for (int i = 0; i < Globals.MB_FEATURE_TREE_PROBS; i++) {
int value=255;
if (bc.readBit()>0) {
value = bc.readLiteral(8);
}
else
value = 255;
macroBlockSegmentTreeProbs[i] = value;
}
}
}
}
simpleFilter = bc.readBit();
filterLevel = bc.readLiteral(6);
sharpnessLevel = bc.readLiteral(3);
modeRefLoopFilterDeltaEnabled = bc.readBit();
if (modeRefLoopFilterDeltaEnabled > 0) {
// Do the deltas need to be updated
modeRefLoopFilterDeltaUpdate = bc.readBit();
if (modeRefLoopFilterDeltaUpdate > 0) {
for (int i = 0; i < MAX_REF_LF_DELTAS; i++) {
if (bc.readBit() > 0) {
refLoopFilterDeltas[i] = bc.readLiteral(6);
if (bc.readBit() > 0) // Apply sign
refLoopFilterDeltas[i] = refLoopFilterDeltas[i] * -1;
}
}
for (int i = 0; i < MAX_MODE_LF_DELTAS; i++) {
if (bc.readBit() > 0) {
modeLoopFilterDeltas[i] = bc.readLiteral(6);
if (bc.readBit() > 0) // Apply sign
modeLoopFilterDeltas[i] = modeLoopFilterDeltas[i] * -1;
}
}
}
}
filterType = (filterLevel == 0) ? 0 : (simpleFilter>0) ? 1 : 2;
setupTokenDecoder(bc, firstPartitionLengthInBytes,
offset);
bc.seek();
segmentQuants.parse(bc, segmentationIsEnabled==1, macroBlockSegementAbsoluteDelta==1);
// Determine if the golden frame or ARF buffer should be updated and
// how.
// For all non key frames the GF and ARF refresh flags and sign bias
// flags must be set explicitly.
if (frameType != 0) {
throw new IllegalArgumentException("bad input: not intra");
}
refreshEntropyProbs = bc.readBit();
if (refreshEntropyProbs > 0) {
}
refreshLastFrame = 0;
if (frameType == 0)
refreshLastFrame = 1;
else
refreshLastFrame = bc.readBit();
for (int i = 0; i < BLOCK_TYPES; i++)
for (int j = 0; j < COEF_BANDS; j++)
for (int k = 0; k < PREV_COEF_CONTEXTS; k++)
for (int l = 0; l < MAX_ENTROPY_TOKENS - 1; l++) {
if (bc.readBool(Globals.vp8CoefUpdateProbs[i][j][k][l]) > 0) {
int newp = bc.readLiteral(8);
this.coefProbs[i][j][k][l] = newp;
}
}
// Read the mb_no_coeff_skip flag
macroBlockNoCoeffSkip = (int) bc.readBit();
if (frameType == 0) {
readModes(bc);
} else {
throw new IllegalArgumentException("bad input: not intra");
}
int ibc = 0;
int num_part = 1 << multiTokenPartition;
for (int mb_row = 0; mb_row < macroBlockRows; mb_row++) {
if (num_part > 1) {
tokenBoolDecoder = tokenBoolDecoders.elementAt(ibc);
tokenBoolDecoder.seek();
decodeMacroBlockRow(mb_row);
ibc++;
if(ibc==num_part)
ibc=0;
}
else
decodeMacroBlockRow(mb_row);
fireProgressUpdate(mb_row);
}
if(this.getFilterType()>0 && this.getFilterLevel()!=0)
this.loopFilter();
return true;
}
private void decodeMacroBlockRow(int mbRow) throws IOException {
for (int mbCol = 0; mbCol < macroBlockCols; mbCol++) {
MacroBlock mb = getMacroBlock(mbCol, mbRow);
mb.decodeMacroBlock(this);
mb.dequantMacroBlock(this);
}
}
public void fireLFProgressUpdate(float p) {
java.util.Iterator listeners = _listeners.iterator();
while( listeners.hasNext() ) {
( (IIOReadProgressListener)listeners.next() ).imageProgress( null, (100/buffersToCreate)+(p/buffersToCreate));
}
}
private void fireProgressUpdate(int mb_row) {
java.util.Iterator listeners = _listeners.iterator();
while( listeners.hasNext() ) {
( (IIOReadProgressListener)listeners.next() ).imageProgress( null, (100.0f*((float)(mb_row+1)/(float)getMacroBlockRows()))/buffersToCreate);
}
}
public void fireRGBProgressUpdate(float p) {
java.util.Iterator listeners = _listeners.iterator();
while( listeners.hasNext() ) {
( (IIOReadProgressListener)listeners.next() ).imageProgress( null, ((bufferCount+4)*(100/buffersToCreate))+(p/buffersToCreate));
}
}
public SubBlock getAboveRightSubBlock(SubBlock sb, SubBlock.PLANE plane) {
// this might break at right edge
SubBlock r;
MacroBlock mb = sb.getMacroBlock();
int x = mb.getSubblockX(sb);
int y = mb.getSubblockY(sb);
if(plane==SubBlock.PLANE.Y1) {
// top row
if(y==0 && x<3) {
MacroBlock mb2=this.getMacroBlock(mb.getX(), mb.getY()-1);
r = mb2.getSubBlock(plane, x+1, 3);
return r;
}
//top right
else if(y==0 && x==3) {
MacroBlock mb2=this.getMacroBlock(mb.getX()+1, mb.getY()-1);
r = mb2.getSubBlock(plane, 0, 3);
if(mb2.getX()==this.getMacroBlockCols()) {
int dest[][] = new int [4][4];
for(int b=0; b<4; b++)
for(int a=0; a<4; a++) {
if(mb2.getY()<0)
dest[a][b]=127;
else
dest[a][b]=this.getMacroBlock(mb.getX(), mb.getY()-1).getSubBlock(SubBlock.PLANE.Y1, 3, 3).getDest()[3][3];
}
r=new SubBlock(mb2,null, null, SubBlock.PLANE.Y1);
r.setDest(dest);
}
return r;
}
//not right edge or top row
else if(y>0 && x<3) {
r = mb.getSubBlock(plane, x+1, y-1);
return r;
}
//else use top right
else {
SubBlock sb2 = mb.getSubBlock(sb.getPlane(), 3, 0);
return this.getAboveRightSubBlock(sb2, plane);
}
}
else {
throw new IllegalArgumentException("bad input: getAboveRightSubBlock()");
}
}
public SubBlock getAboveSubBlock(SubBlock sb, SubBlock.PLANE plane) {
SubBlock r = sb.getAbove();
if(r==null) {
MacroBlock mb = sb.getMacroBlock();
int x = mb.getSubblockX(sb);
MacroBlock mb2 = getMacroBlock(mb.getX(), mb.getY()-1);
//TODO: SPLIT
while(plane==SubBlock.PLANE.Y2 && mb2.getYMode()== Globals.B_PRED) {
mb2 = getMacroBlock(mb2.getX(), mb2.getY()-1);
}
r = mb2.getBottomSubBlock(x, sb.getPlane());
}
return r;
}
private boolean getBit(int data, int bit) {
int r = data & (1 << bit);
if (r > 0)
return true;
return false;
}
private int getBitAsInt(int data, int bit) {
int r = data & (1 << bit);
if (r > 0)
return 1;
return 0;
}
public BufferedImage getBufferedImage() {
BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
useBufferedImage(bi);
bufferCount++;
return bi;
}
public int[][][][] getCoefProbs() {
return coefProbs;
}
public BufferedImage getDebugImageDiff() {
BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster imRas = bi.getWritableTile(0, 0);
for(int x = 0; x< getWidth(); x++) {
for(int y = 0; y< getHeight(); y++) {
int c[] = new int[3];
int yy, u, v;
yy = 127+this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.Y1, (x%16)/4, (y%16)/4).getDiff()[x%4][y%4];
u = 127+this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.U, ((x/2)%8)/4, ((y/2)%8)/4).getDiff()[(x/2)%4][(y/2)%4];
v = 127+this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.V, ((x/2)%8)/4, ((y/2)%8)/4).getDiff()[(x/2)%4][(y/2)%4];
c[0] = (int)( 1.164*(yy-16)+1.596*(v-128) );
c[1] = (int)( 1.164*(yy-16)-0.813*(v-128)-0.391*(u-128) );
c[2] = (int)( 1.164*(yy-16)+2.018*(u-128) );
for(int z=0; z<3; z++) {
if(c[z]<0)
c[z]=0;
if(c[z]>255)
c[z]=255;
}
imRas.setPixel(x, y, c);
}
fireRGBProgressUpdate(100.0F*x/getWidth());
}
bufferCount++;
return bi;
}
public BufferedImage getDebugImagePredict() {
BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster imRas = bi.getWritableTile(0, 0);
for(int x = 0; x< getWidth(); x++) {
for(int y = 0; y< getHeight(); y++) {
int c[] = new int[3];
int yy, u, v;
yy = this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.Y1, (x%16)/4, (y%16)/4).getPredict()[x%4][y%4];
u = this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.U, ((x/2)%8)/4, ((y/2)%8)/4).getPredict()[(x/2)%4][(y/2)%4];
v = this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.V, ((x/2)%8)/4, ((y/2)%8)/4).getPredict()[(x/2)%4][(y/2)%4];
c[0] = (int)( 1.164*(yy-16)+1.596*(v-128) );
c[1] = (int)( 1.164*(yy-16)-0.813*(v-128)-0.391*(u-128) );
c[2] = (int)( 1.164*(yy-16)+2.018*(u-128) );
for(int z=0; z<3; z++) {
if(c[z]<0)
c[z]=0;
if(c[z]>255)
c[z]=255;
}
imRas.setPixel(x, y, c);
}
fireRGBProgressUpdate(100.0F*x/getWidth());
}
bufferCount++;
return bi;
}
public BufferedImage getDebugImageUBuffer() {
BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster imRas = bi.getWritableTile(0, 0);
for(int x = 0; x< getWidth(); x++) {
for(int y = 0; y< getHeight(); y++) {
int c[] = new int[3];
int u;
u = this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.U, ((x/2)%8)/4, ((y/2)%8)/4).getDest()[(x/2)%4][(y/2)%4];
c[0] = u;
c[1] = u;
c[2] = u;
for(int z=0; z<3; z++) {
if(c[z]<0)
c[z]=0;
if(c[z]>255)
c[z]=255;
}
imRas.setPixel(x, y, c);
}
fireRGBProgressUpdate(100.0F*x/getWidth());
}
bufferCount++;
return bi;
}
public BufferedImage getDebugImageUDiffBuffer() {
BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster imRas = bi.getWritableTile(0, 0);
for(int x = 0; x< getWidth(); x++) {
for(int y = 0; y< getHeight(); y++) {
int c[] = new int[3];
int u;
u = 127+this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.U, ((x/2)%8)/4, ((y/2)%8)/4).getDiff()[(x/2)%4][(y/2)%4];
c[0] = u;
c[1] = u;
c[2] = u;
for(int z=0; z<3; z++) {
if(c[z]<0)
c[z]=0;
if(c[z]>255)
c[z]=255;
}
imRas.setPixel(x, y, c);
}
fireRGBProgressUpdate(100.0F*x/getWidth());
}
bufferCount++;
return bi;
}
public BufferedImage getDebugImageUPredBuffer() {
BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster imRas = bi.getWritableTile(0, 0);
for(int x = 0; x< getWidth(); x++) {
for(int y = 0; y< getHeight(); y++) {
int c[] = new int[3];
int u;
u = this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.U, ((x/2)%8)/4, ((y/2)%8)/4).getPredict()[(x/2)%4][(y/2)%4];
c[0] = u;
c[1] = u;
c[2] = u;
for(int z=0; z<3; z++) {
if(c[z]<0)
c[z]=0;
if(c[z]>255)
c[z]=255;
}
imRas.setPixel(x, y, c);
}
fireRGBProgressUpdate(100.0F*x/getWidth());
}
bufferCount++;
return bi;
}
public BufferedImage getDebugImageVBuffer() {
BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster imRas = bi.getWritableTile(0, 0);
for(int x = 0; x< getWidth(); x++) {
for(int y = 0; y< getHeight(); y++) {
int c[] = new int[3];
int v;
v = this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.V, ((x/2)%8)/4, ((y/2)%8)/4).getDest()[(x/2)%4][(y/2)%4];
c[0] = v;
c[1] = v;
c[2] = v;
for(int z=0; z<3; z++) {
if(c[z]<0)
c[z]=0;
if(c[z]>255)
c[z]=255;
}
imRas.setPixel(x, y, c);
}
fireRGBProgressUpdate(100.0F*x/getWidth());
}
bufferCount++;
return bi;
}
public BufferedImage getDebugImageVDiffBuffer() {
BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster imRas = bi.getWritableTile(0, 0);
for(int x = 0; x< getWidth(); x++) {
for(int y = 0; y< getHeight(); y++) {
int c[] = new int[3];
int v;
v = 127+this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.V, ((x/2)%8)/4, ((y/2)%8)/4).getDiff()[(x/2)%4][(y/2)%4];
c[0] = v;
c[1] = v;
c[2] = v;
for(int z=0; z<3; z++) {
if(c[z]<0)
c[z]=0;
if(c[z]>255)
c[z]=255;
}
imRas.setPixel(x, y, c);
}
fireRGBProgressUpdate(100.0F*x/getWidth());
}
bufferCount++;
return bi;
}
public BufferedImage getDebugImageVPredBuffer() {
BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster imRas = bi.getWritableTile(0, 0);
for(int x = 0; x< getWidth(); x++) {
for(int y = 0; y< getHeight(); y++) {
int c[] = new int[3];
int v;
v = this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.V, ((x/2)%8)/4, ((y/2)%8)/4).getPredict()[(x/2)%4][(y/2)%4];
c[0] = v;
c[1] = v;
c[2] = v;
for(int z=0; z<3; z++) {
if(c[z]<0)
c[z]=0;
if(c[z]>255)
c[z]=255;
}
imRas.setPixel(x, y, c);
}
fireRGBProgressUpdate(100.0F*x/getWidth());
}
bufferCount++;
return bi;
}
public BufferedImage getDebugImageYBuffer() {
BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster imRas = bi.getWritableTile(0, 0);
for(int x = 0; x< getWidth(); x++) {
for(int y = 0; y< getHeight(); y++) {
int c[] = new int[3];
int yy;
yy = this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.Y1, (x%16)/4, (y%16)/4).getDest()[x%4][y%4];
c[0] = yy;
c[1] = yy;
c[2] = yy;
for(int z=0; z<3; z++) {
if(c[z]<0)
c[z]=0;
if(c[z]>255)
c[z]=255;
}
imRas.setPixel(x, y, c);
}
fireRGBProgressUpdate(100.0F*x/getWidth());
}
bufferCount++;
return bi;
}
public BufferedImage getDebugImageYDiffBuffer() {
BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster imRas = bi.getWritableTile(0, 0);
for(int x = 0; x< getWidth(); x++) {
for(int y = 0; y< getHeight(); y++) {
int c[] = new int[3];
int yy;
yy = 127+this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.Y1, (x%16)/4, (y%16)/4).getDiff()[x%4][y%4];
c[0] = yy;
c[1] = yy;
c[2] = yy;
for(int z=0; z<3; z++) {
if(c[z]<0)
c[z]=0;
if(c[z]>255)
c[z]=255;
}
imRas.setPixel(x, y, c);
}
fireRGBProgressUpdate(100.0F*x/getWidth());
}
bufferCount++;
return bi;
}
public BufferedImage getDebugImageYPredBuffer() {
BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster imRas = bi.getWritableTile(0, 0);
for(int x = 0; x< getWidth(); x++) {
for(int y = 0; y< getHeight(); y++) {
int c[] = new int[3];
int yy;
yy = this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.Y1, (x%16)/4, (y%16)/4).getPredict()[x%4][y%4];
c[0] = yy;
c[1] = yy;
c[2] = yy;
for(int z=0; z<3; z++) {
if(c[z]<0)
c[z]=0;
if(c[z]>255)
c[z]=255;
}
imRas.setPixel(x, y, c);
}
fireRGBProgressUpdate(100.0F*x/getWidth());
}
bufferCount++;
return bi;
}
public int getFilterLevel() {
return filterLevel;
}
public int getFilterType() {
return filterType;
}
public int getFrameType() {
return frameType;
}
public int getHeight() {
return height;
}
public SubBlock getLeftSubBlock(SubBlock sb, SubBlock.PLANE plane) {
SubBlock r = sb.getLeft();
if(r==null) {
MacroBlock mb = sb.getMacroBlock();
int y = mb.getSubblockY(sb);
MacroBlock mb2 = getMacroBlock(mb.getX()-1, mb.getY());
//TODO: SPLIT
while(plane==SubBlock.PLANE.Y2 && mb2.getYMode()== Globals.B_PRED)
mb2 = getMacroBlock(mb2.getX()-1, mb2.getY());
r = mb2.getRightSubBlock(y, sb.getPlane());
}
return r;
}
public MacroBlock getMacroBlock(int mbCol, int mbRow) {
return macroBlocks[mbCol+1][mbRow+1];
}
public int getMacroBlockCols() {
return macroBlockCols;
}
public String getMacroBlockDebugString(int mbx, int mby, int sbx, int sby) {
String r = new String();
if(mbx 0) {
prob_skip_false = bc.readLiteral(8);
}
while (++mb_row < macroBlockRows) {
int mb_col = -1;
while (++mb_col < macroBlockCols) {
//if (this.segmentation_enabled > 0) {
// logger.log(Level.SEVERE, "TODO:");
// throw new IllegalArgumentException("bad input: segmentation_enabled()");
//}
// Read the macroblock coeff skip flag if this feature is in
// use, else default to 0
MacroBlock mb = getMacroBlock(mb_col, mb_row);
if ((segmentationIsEnabled >0) &&( updateMacroBlockSegmentationMap > 0)) {
int value = bc.readTree(Globals.macroBlockSegmentTree, this.macroBlockSegmentTreeProbs);
mb.setSegmentId(value);
}
if(modeRefLoopFilterDeltaEnabled > 0) {
int level = filterLevel;
level = level + refLoopFilterDeltas[0];
level = (level < 0) ? 0 : (level > 63) ? 63 : level;
mb.setFilterLevel(level);
}
else {
mb.setFilterLevel(segmentQuants.getSegQuants()[mb.getSegmentId()].getFilterStrength());
// logger.error("TODO:");
}
int mb_skip_coeff = 0;
if (macroBlockNoCoeffSkip > 0)
mb_skip_coeff = bc.readBool(prob_skip_false);
else
mb_skip_coeff = 0;
mb.setSkipCoeff(mb_skip_coeff);
int y_mode = readYMode(bc);
mb.setYMode(y_mode);
if (y_mode == Globals.B_PRED) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
SubBlock sb = mb.getYSubBlock(j, i);
SubBlock A = getAboveSubBlock(sb, SubBlock.PLANE.Y1);
SubBlock L = getLeftSubBlock(sb, SubBlock.PLANE.Y1);
int mode = readSubBlockMode(bc, A.getMode(), L.getMode());
sb.setMode(mode);
}
}
if(modeRefLoopFilterDeltaEnabled > 0) {
int level = mb.getFilterLevel();
level = level + this.modeLoopFilterDeltas[0];
level = (level < 0) ? 0 : (level > 63) ? 63 : level;
mb.setFilterLevel(level);
}
} else {
int BMode;
switch (y_mode) {
case Globals.DC_PRED:
BMode = Globals.B_DC_PRED;
break;
case Globals.V_PRED:
BMode = Globals.B_VE_PRED;
break;
case Globals.H_PRED:
BMode = Globals.B_HE_PRED;
break;
case Globals.TM_PRED:
BMode = Globals.B_TM_PRED;
break;
default:
BMode = Globals.B_DC_PRED;
break;
}
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 4; y++) {
SubBlock sb = mb.getYSubBlock(x, y);
sb.setMode(BMode);
}
}
}
int mode = readUvMode(bc);
mb.setUvMode(mode);
}
}
}
private int readPartitionSize(long l) throws IOException {
frame.seek(l);
int size =frame.readUnsignedByte() + (frame.readUnsignedByte() << 8) + (frame.readUnsignedByte() << 16);
return size;
}
private int readSubBlockMode(BoolDecoder bc, int A, int L) throws IOException {
int i = bc.readTree(Globals.vp8SubBlockModeTree, Globals.vp8KeyFrameSubBlockModeProb[A][L]);
return i;
}
private int readUvMode(BoolDecoder bc) throws IOException {
int i = bc.readTree(Globals.vp8UVModeTree, Globals.vp8KeyFrameUVModeProb);
return i;
}
private int readYMode(BoolDecoder bc) throws IOException {
int i = bc.readTree(Globals.vp8KeyFrameYModeTree, Globals.vp8KeyFrameYModeProb);
return i;
}
public void removeIIOReadProgressListener(IIOReadProgressListener listener) {
_listeners.remove(listener);
}
public void setBuffersToCreate (int count) {
this.buffersToCreate = 3+count;
this.bufferCount=0;
}
private void setupTokenDecoder(BoolDecoder bc, int first_partition_length_in_bytes, long offset) throws IOException {
long partitionSize = 0;
long partitionsStart = offset+first_partition_length_in_bytes;
long partition = partitionsStart;
multiTokenPartition = bc.readLiteral(2);
int num_part = 1 << multiTokenPartition;
if (num_part > 1) {
partition += 3 * (num_part - 1);
}
for (int i = 0; i < num_part; i++) {
/*
* Calculate the length of this partition. The last partition size
* is implicit.
*/
if (i < num_part - 1) {
partitionSize = readPartitionSize(partitionsStart+(i*3));
bc.seek();
} else {
partitionSize = frame.length() - partition;
}
tokenBoolDecoders.add(new BoolDecoder(frame, partition));
partition+=partitionSize;
}
tokenBoolDecoder = tokenBoolDecoders.elementAt(0);
}
public void useBufferedImage(BufferedImage dst) {
WritableRaster imRas = dst.getWritableTile(0, 0);
for(int x = 0; x< getWidth(); x++) {
for(int y = 0; y< getHeight(); y++) {
int c[] = new int[3];
int yy, u, v;
yy = this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.Y1, (x%16)/4, (y%16)/4).getDest()[x%4][y%4];
u = this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.U, ((x/2)%8)/4, ((y/2)%8)/4).getDest()[(x/2)%4][(y/2)%4];
v = this.getMacroBlock(x/16, y/16).getSubBlock(SubBlock.PLANE.V, ((x/2)%8)/4, ((y/2)%8)/4).getDest()[(x/2)%4][(y/2)%4];
c[0] = (int)( 1.164*(yy-16)+1.596*(v-128) );
c[1] = (int)( 1.164*(yy-16)-0.813*(v-128)-0.391*(u-128) );
c[2] = (int)( 1.164*(yy-16)+2.018*(u-128) );
for(int z=0; z<3; z++) {
if(c[z]<0)
c[z]=0;
if(c[z]>255)
c[z]=255;
}
imRas.setPixel(x, y, c);
}
fireRGBProgressUpdate(100.0F*x/getWidth());
}
}
public void setFrame(ImageInputStream frame) {
try {
this.frame.flush();
this.frame.close();
this.frame = frame;
offset = frame.getStreamPosition();
this.coefProbs=Globals.getDefaultCoefProbs();
tokenBoolDecoders = new Vector();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Ads help maintain this website.