public Vector Scale(int h_shift, int v_shift) { Vector o = new Vector(); o.namespace_global = namespace_global; o.pred_mode = pred_mode; o.dx[0] = dx[0] >> h_shift; o.dx[1] = dx[1] >> h_shift; o.dy[0] = dy[0] >> v_shift; o.dy[1] = dy[1] >> v_shift; return o; }
private void VectorPrediction(Vector mv, int x, int y, int mode) { int n = 0; int[] vx = new int[3]; int[] vy = new int[3]; if(x > 0) { Vector ov = GetVector(x-1, y); if(!ov.namespace_global && (ov.pred_mode & mode) != 0) { vx[n] = ov.dx[mode-1]; vy[n] = ov.dx[mode-1]; n++; } } if(y > 0) { Vector ov = GetVector(x, y-1); if(!ov.namespace_global && (ov.pred_mode & mode) != 0) { vx[n] = ov.dx[mode-1]; vy[n] = ov.dx[mode-1]; n++; } } if(x > 0 && y > 0) { Vector ov = GetVector(x - 1, y - 1); if(!ov.namespace_global && (ov.pred_mode & mode) != 0) { vx[n] = ov.dx[mode-1]; vy[n] = ov.dy[mode-1]; n++; } } switch(n) { case 0: mv.dx[mode-1] = 0; mv.dy[mode-1] = 0; break; case 1: mv.dx[mode-1] = vx[0]; mv.dy[mode-1] = vy[0]; break; case 2: mv.dx[mode-1] = (vx[0] + vx[1] + 1) >> 1; mv.dy[mode-1] = (vy[0] + vy[1] + 1) >> 1; break; case 3: mv.dx[mode-1] = Util.Median(vx); mv.dy[mode-1] = Util.Median(vy); break; } }
private void SetVector(Vector mv, int x, int y) { vecs[x + y*par.x_num_blocks] = mv; }
private short PredictPixel(Vector mv, int x, int y, int k) { if(mv.namespace_global) { for(int i = 0; i < par.num_refs; i++) { par.global[i].GetVector(mv, x, y, i); } if(k != 0) mv = mv.Scale(chroma_h_shift, chroma_v_shift); } short weight = (short)(par.picture_weight_1 + par.picture_weight_2); short val = 0; int px, py; switch(mv.pred_mode) { case 1: px = (x << par.mv_precision) + mv.dx[0]; py = (y << par.mv_precision) + mv.dy[0]; val = (short)(weight*PredictSubPixel(0, px, py)); break; case 2: px = (x << par.mv_precision) + mv.dx[1]; py = (y << par.mv_precision) + mv.dy[1]; val = (short)(weight*PredictSubPixel(1, px, py)); break; case 3: px = (x << par.mv_precision) + mv.dx[0]; py = (y << par.mv_precision) + mv.dy[0]; val = (short)(par.picture_weight_1*PredictSubPixel(0, px, py)); px = (x << par.mv_precision) + mv.dx[1]; py = (x << par.mv_precision) + mv.dy[1]; val += (short)(par.picture_weight_2*PredictSubPixel(1, px, py)); break; default: break; } return (short)Util.RoundShift(val, par.picture_weight_bits); }
private Vector GetVector(int x, int y) { int pos = x + y*par.x_num_blocks; if(vecs[pos] == null) { vecs[pos] = new Vector(); } return vecs[pos]; }
private void DecodePredictionUnit(Vector mv, int x, int y) { mv.pred_mode = ModePrediction(x,y); mv.pred_mode ^= ar[ARITH_PRED_MODE].DecodeBit(Context.BLOCK_MODE_REF1); if(par.num_refs > 1) { mv.pred_mode ^= (ar[ARITH_PRED_MODE].DecodeBit(Context.BLOCK_MODE_REF2) << 1); } if(mv.pred_mode == 0) { int[] pred = new int[3]; DcPrediction(x,y,pred); mv.dc[0] = pred[0] + ar[ARITH_DC_0].DecodeSint(Context.LUMA_DC_CONT_BIN1, Context.LUMA_DC_VALUE, Context.LUMA_DC_SIGN); mv.dc[1] = pred[1] + ar[ARITH_DC_1].DecodeSint(Context.CHROMA1_DC_CONT_BIN1, Context.CHROMA1_DC_VALUE, Context.CHROMA1_DC_SIGN); mv.dc[2] = pred[2] + ar[ARITH_DC_2].DecodeSint(Context.CHROMA2_DC_CONT_BIN1, Context.CHROMA2_DC_VALUE, Context.CHROMA2_DC_SIGN); } else { int pred_x, pred_y; if(par.have_global_motion) { int pred = GlobalPrediction(x,y); pred ^= ar[ARITH_SUPERBLOCK].DecodeBit(Context.GLOBAL_BLOCK); mv.namespace_global = (pred == 0 ? false : true); } else { mv.namespace_global = false; } if(!mv.namespace_global) { if((mv.pred_mode & 1) != 0) { VectorPrediction(mv,x,y,1); mv.dx[0] += ar[ARITH_REF1_X].DecodeSint(Context.MV_REF1_H_CONT_BIN1, Context.MV_REF1_H_VALUE, Context.MV_REF1_H_SIGN); mv.dy[0] += ar[ARITH_REF1_Y].DecodeSint(Context.MV_REF1_V_CONT_BIN1, Context.MV_REF1_V_VALUE, Context.MV_REF1_V_SIGN); } if((mv.pred_mode & 2) != 0) { VectorPrediction(mv, x, y, 2); mv.dx[1] += ar[ARITH_REF2_X].DecodeSint(Context.MV_REF2_H_CONT_BIN1, Context.MV_REF2_H_VALUE, Context.MV_REF2_H_SIGN); mv.dy[1] += ar[ARITH_REF2_Y].DecodeSint(Context.MV_REF2_V_CONT_BIN1, Context.MV_REF2_V_VALUE, Context.MV_REF2_V_SIGN); } } } mv.namespace_global = false; mv.dx[0] = 0; mv.dy[0] = 0; mv.dx[1] = 0; mv.dy[1] = 0; }