www.pudn.com > wm2.5.zip > interpred.c
/* *********************************************************************** * COPYRIGHT AND WARRANTY INFORMATION * * Copyright 2004, Advanced Audio Video Coding Standard, Part II * * DISCLAIMER OF WARRANTY * * These software programs are available to the users without any * license fee or royalty on an "as is" basis. The AVS disclaims * any and all warranties, whether express, implied, or statutory, * including any implied warranties of merchantability or of fitness * for a particular purpose. In no event shall the contributors or * the AVS be liable for any incidental, punitive, or consequential * damages of any kind whatsoever arising from the use of this program. * * This disclaimer of warranty extends to the user of this program * and user's customers, employees, agents, transferees, successors, * and assigns. * * The AVS does not represent or warrant that the program furnished * hereunder are free of infringement of any third-party patents. * Commercial implementations of AVS, including shareware, may be * subject to royalty fees to patent holders. Information regarding * the AVS patent policy is available from the AVS Web site at * http://www.avs.org.cn * * THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY. ************************************************************************ */ #include "define.h" #include "global.h" #include "motion_esti.h" #include "interpred.h" #include "macroblock.h" #include "rdopt.h" #include "block.h" #include "vlc.h" #include "IREG.h" #include#include #include #include extern MacroblockData MbData, *pgMbData; extern int AffectedByLeftover(int x_pos, int y_pos, int ref); const int csiInter_Block_Size[4][2] = {{16,16},{16,8},{8,16},{8,8}}; const int csiInter_Subblk_Size[4][2] = {{8,8},{8,4},{4,8},{4,4}}; //qwang 2004-3-20 const int BITSMBTYPE[6] = {1, 3, 3, 5, 5, 5}; //qwang 2004-3-20 const int BITSSUBBLKTYPE[4] = {1, 3, 3, 5}; //qwang 2004-3-20 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function name : Select one mode for sub block + parameters : void + return : 8x8, 8x4, 4x8, 4x4 + descriptions : + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int Subblk_Inter_Modes_Decision(int ref,int b8, int pic_pel_y, int pic_pel_x, int lambda_factor) //qwang 2004-3-20 { static int bx0[4] = {0,2,0,2}; static int by0[4] = {0,0,2,2}; int mcost, mincost = 1<<20; int subblktype; int pic_block_y,pic_block_x; int b4; int v,h; int step_h; int step_v; int step_h0; int step_v0; int pic_pixel_x, pic_pixel_y; int j, i; int refframe=ref; int coeff_cost; for(subblktype=1; subblktype<=4; subblktype++) { coeff_cost = 0; mcost = 0; step_h0 = 2; step_v0 = 2; step_h = (csiInter_Subblk_Size[subblktype-1][0]>>2); step_v = (csiInter_Subblk_Size[subblktype-1][1]>>2); pic_pixel_x = pic_pel_x; pic_pixel_y = pic_pel_y; for (v=by0[b8]; v mb_y*4 + v; pic_pixel_y += (v-by0[b8]) * 4; for (h=bx0[b8]; h mb_x*4 + h; pic_pixel_x += (h-bx0[b8])* 4; //--- motion search for block --- b4 = (v-by0[b8]) * 2 + (h-bx0[b8]); mcost += Subblock_Motion_Search (ref, b8,subblktype,b4,4*pic_block_y,4*pic_block_x,pic_pixel_y,pic_pixel_x,lambda_factor); //cbzhu 12-15 #ifdef _ISOLATED_REGION_ if (input.IREGEnable) { mcost = min(mcost, 1<<30); } #endif // _ISOLATED_REGION_ //--- set motion vectors and reference frame (for motion vector prediction) --- for (j=0; j best_mode_subblk_ref[ref][b8] = subblktype; Save_Subblk_Motion_Vector(subblktype, b8); } for(b4=0; b4<4; b4++) { tmp_mv[0][pgMbData->mb_y*4 +((b8>>1)<<1) + (b4>>1)][pgMbData->mb_x*4 +((b8 &1)<<1) + (b4 &1)+4] = pgMbData->mvb_tmp[b8][b4][0]; tmp_mv[1][pgMbData->mb_y*4 +((b8>>1)<<1) + (b4>>1)][pgMbData->mb_x*4 +((b8 &1)<<1) + (b4 &1)+4] = pgMbData->mvb_tmp[b8][b4][1]; refFrArr [pgMbData->mb_y*4 +((b8>>1)<<1) + (b4>>1)][pgMbData->mb_x*4 +((b8 &1)<<1) + (b4 &1)] = refframe; } if(input.rdopt) Save_Subblk_Motion_Vector_RDO(subblktype, b8, ref); } return mincost; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function name : Inter_Modes_Decision + parameters : void + return : the best cost of inter modes including 16x16,16x8,8x16,8x8 + descriptions : created by xyji: 2004/02/12 + modified by jhzheng: 2004/02/15 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int Inter_Modes_Decision(void) //qwang 2004-3-20 //zhangnan { int mcost, mincost = 1<<20 ,mincost_ref = 1<<20,motion_cost_ref; int blocktype; int v,h; int b8, b4; int i,j; int pic_block_y,pic_block_x; int pic_pel_x, pic_pel_y; int step_h; int step_v; int min_ref = 0; int ref; int refframe; int max_ref = pgImage->nb_references; int ref_ref; int lambda_factor; int subblktype; int best_ref; int coeff_cost; int rdcost, minrdcost; int rate, distortion; //cbzhu 12-15 #ifdef _ISOLATED_REGION_ int m,n; if(input.IREGEnable) { for(i=0;i<2;i++) for(j=0;j<4;j++) for(m=0;m<4;m++) for(n=0;n<4;n++) typemap[i][j][m][n]=1; //initial : enable } #endif //_ISOLATED_REGION_ if(!input.rdopt) lambda_factor = LAMBDA_FACTOR (pgMbData->lambda); else lambda_factor = LAMBDA_FACTOR(pgMbData->lamda_motion); //cbzhu 12-15 #ifdef _ISOLATED_REGION_ if (input.IREGEnable) { if (iIREGState==input.IREGRate || iIREGState==2*input.IREGRate) { max_ref = 1; } } #endif // _ISOLATED_REGION_ for(blocktype =1; blocktype <=4; blocktype ++) { mcost = 0; step_h = (csiInter_Block_Size[blocktype-1][0]>>3); step_v = (csiInter_Block_Size[blocktype-1][1]>>3); for(v = 0 ; v < 2 ; v += step_v) { pic_pel_y = pgMbData->mb_y * 16 + v * 8; pic_block_y = pgImage->block_y + v * 2; for( h = 0 ; h < 2 ; h += step_h) { pic_pel_x = pgMbData->mb_x * 16 + h * 8; pic_block_x = pgImage->block_x + h * 2; b8 = v * 2 + h; mincost_ref = 1<<20; for (ref=min_ref; ref mb_y][pgImage->mb_x] != 0) { iIntegerPixFlag = 0; //initial: integer is disable iSubPixFlag1 = 1; //subpix is disable } else { iIntegerPixFlag = 1; iSubPixFlag1 = 0; // leftover initial : integer and subpix all enable } } #endif // _ISOLATED_REGION_ refframe = ref; motion_cost_ref = 0; if(blocktype < 4) //16x16, 16x8, 8x16 Motion Estimation { motion_cost_ref = Block_Motion_Search (ref,blocktype,b8,pic_pel_y,pic_pel_x,lambda_factor); //cbzhu 0412 #ifdef _ISOLATED_REGION_ if (input.IREGEnable) { if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) { if (iIntegerPixFlag == 0 || iSubPixFlag1 == 1) { if(ref==0) { if(blocktype==1) for(m=0;m<4;m++) for(n=0;n<4;n++) typemap[0][blocktype-1][m][n]=0; else if (blocktype==2) for(m=0;m<2;m++) for(n=0;n<4;n++) typemap[0][blocktype-1][b8+m][n]=0; else if (blocktype==3) for(m=0;m<3;m+=2) for(n=0;n<4;n++) typemap[0][blocktype-1][b8+m][n]=0; if(max_ref==1) { if(blocktype==1) for(m=0;m<4;m++) for(n=0;n<4;n++) typemap[1][blocktype-1][m][n]=0; else if (blocktype==2) for(m=0;m<2;m++) for(n=0;n<4;n++) typemap[1][blocktype-1][b8+m][n]=0; else if (blocktype==3) for(m=0;m<3;m+=2) for(n=0;n<4;n++) typemap[1][blocktype-1][b8+m][n]=0; } motion_cost_ref = (1<<20)-1; } if(ref==1) { if(blocktype==1) for(m=0;m<4;m++) for(n=0;n<4;n++) typemap[1][blocktype-1][m][n]=0; else if (blocktype==2) for(m=0;m<2;m++) for(n=0;n<4;n++) typemap[1][blocktype-1][b8+m][n]=0; else if (blocktype==3) for(m=0;m<3;m+=2) for(n=0;n<4;n++) typemap[1][blocktype-1][b8+m][n]=0; motion_cost_ref = (1<<20); } } } } #endif // _ISOLATED_REGION_ } else //P8x8 mode decision { motion_cost_ref= Subblk_Inter_Modes_Decision (ref,b8,pic_pel_y,pic_pel_x,lambda_factor); //cbzhu 0412 #ifdef _ISOLATED_REGION_ if (input.IREGEnable) { if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) { if (iIntegerPixFlag == 0 || iSubPixFlag1 == 1) { if(ref==0) { for(n=0;n<4;n++)typemap[0][blocktype-1][b8][n]=0; if(max_ref==1) for(n=0;n<4;n++)typemap[1][blocktype-1][b8][n]=0; motion_cost_ref = (1<<20)-1; } if(ref==1) { for(n=0;n<4;n++)typemap[1][blocktype-1][b8][n]=0; motion_cost_ref = (1<<20); } } } } #endif // _ISOLATED_REGION_ } if(blocktype < 4) for (j=0; j mvb_ref[b8][b4][0] = pgMbData->mvb_tmp[b8][b4][0]; pgMbData->mvb_ref[b8][b4][1] = pgMbData->mvb_tmp[b8][b4][1]; pgMbData->pred_mv_ref[b8][b4][0] = pgMbData->pred_mv_tmp[b8][b4][0]; pgMbData->pred_mv_ref[b8][b4][1] = pgMbData->pred_mv_tmp[b8][b4][1]; ref_ref=refframe; } }//zhangnan }//if (motion_cost_ref < mincost_ref) else { if (blocktype==1) {//16x16 for (j=0; j block_y +((b8>>1)<<1) + (b4>>1)][pgImage->block_x +((b8 &1)<<1) + (b4 &1)+4] = pgMbData->mvb_ref[b8][b4][0]; tmp_mv[1][pgImage->block_y +((b8>>1)<<1) + (b4>>1)][pgImage->block_x +((b8 &1)<<1) + (b4 &1)+4] = pgMbData->mvb_ref[b8][b4][1]; refFrArr [pgImage->block_y +((b8>>1)<<1) + (b4>>1)][pgImage->block_x +((b8 &1)<<1) + (b4 &1)] = ref_ref; } }//zhangnan }// if (motion_cost_ref < mincost_ref) //zhangnan } if(input.rdopt) { if(blocktype==4) { minrdcost = 1<<20; best_ref = refFrArr [pgImage->block_y +((b8>>1)<<1) ][pgImage->block_x +((b8 &1)<<1) ]; for(subblktype=1; subblktype<=4; subblktype++) { coeff_cost = 0; coeff_cost_4x4[0]=coeff_cost_4x4[1]=coeff_cost_4x4[2]=coeff_cost_4x4[3] = 0; // dongjie for(b4 = 0; b4 < 4; b4++) { pgMbData->mvb[b8][b4][0] = subblk_MV[subblktype][best_ref][b8][b4][0]; pgMbData->mvb[b8][b4][1] = subblk_MV[subblktype][best_ref][b8][b4][1]; pgMbData->pred_mv[b8][b4][0] = subblk_Pred_MV[subblktype][best_ref][b8][b4][0]; pgMbData->pred_mv[b8][b4][1] = subblk_Pred_MV[subblktype][best_ref][b8][b4][1]; } pgMbHeader->mb_type = 4; pgMbHeader->subblk_type[b8] = subblktype; Save_RD_State(); //bits for sub_blk mode ue_linfo(subblktype-1); //Not: all zero ref: ref index rate = 1; //--- Get MVD info --- for(b4=0; b4<4; b4++) { pgMbHeader->mvd[b8][b4][0] = pgMbData->mvb[b8][b4][0] - pgMbData->pred_mv[b8][b4][0]; pgMbHeader->mvd[b8][b4][1] = pgMbData->mvb[b8][b4][1] - pgMbData->pred_mv[b8][b4][1]; } Load_8x8_Residual(b8); //WJP 040903 if(subblktype==1 && (!input.ABT_RDO) && input.ABT) { abt_transform_B8(b8); abt_quant_B8(pgMbData->qp_mb, b8, &coeff_cost); } else { for(b4=0; b4<4; b4++) { Transform_B4(b8,b4); Quant_B4(pgMbData->qp_mb, b8, b4, &coeff_cost); } // dongjie if(pgMbHeader->cbp_4x4[b8]==0) pgMbHeader->cbp &= (~(1< cbp |= (1< cbp &= (63 - (1< pred_residual[b8][b4][j][i] = 0; } // dongjie else { for(b4=0;b4<4;b4++) { if(coeff_cost_4x4[b4] <= LUMACOEFFCOST4x4) { pgMbHeader->cbp_4x4[b8] &= (15 - (1< pred_residual[b8][b4][j][i] = 0; } } } // end //WJP 040903 if(pgMbHeader->cbp & (1< cbp_4x4[b8] & (1< qp_mb,b8); abt_Itransform_B8(b8); } else { for(b4=0;b4<4;b4++) { Dequant_B4(pgMbData->qp_mb, b8, b4); Inv_Transform_B4(b8, b4); } } for(b4=0; b4<4; b4++) { Recon_B4(b8, b4, 0); for(j=0; j<4; j++) for(i=0; i<4; i++) { imgY[(pgMbData->mb_y<<4) + (b8/2)*8+(b4/2)*4+j][(pgMbData->mb_x<<4) + (b8%2)*8+(b4%2)*4+i] = imgY1[j][i]; } } //WJP END rate += (pgcurrBitStream->byte_pos-pgRDStream->byte_pos)*8 +(pgRDStream->bits_to_go-pgcurrBitStream->bits_to_go); Restore_RD_State(); distortion = 0; for(j=(b8>>1)*8; j<(b8>>1)*8 + 8; j++) for(i=(b8%2)*8; i<(b8%2)*8+8; i++) { distortion += quadarr[pgMbData->org_luma[j][i]-imgY[(pgMbData->mb_y<<4) + j][(pgMbData->mb_x<<4) + i]]; } rdcost = (int)(distortion + pgMbData->lamda_mode * rate); if(rdcost best_mode_subblk[b8] = subblktype; for(b4 = 0; b4 < 4; b4++) { tmp_mv[0][pgImage->block_y +((b8>>1)<<1) + (b4>>1)][pgImage->block_x +((b8 &1)<<1) + (b4 &1)+4] = subblk_MV[subblktype][best_ref][b8][b4][0]; tmp_mv[1][pgImage->block_y +((b8>>1)<<1) + (b4>>1)][pgImage->block_x +((b8 &1)<<1) + (b4 &1)+4] = subblk_MV[subblktype][best_ref][b8][b4][1]; } } } } } //sw if(!input.rdopt) { if (refFrArr [pgImage->block_y +((b8>>1)<<1) ][pgImage->block_x +((b8 &1)<<1) ] ==0) pgMbData->best_mode_subblk[b8] = pgMbData->best_mode_subblk_ref[0][b8]; else pgMbData->best_mode_subblk[b8] = pgMbData->best_mode_subblk_ref[1][b8]; } } } mcost += MODE_COST(lambda_factor, BITSMBTYPE[blocktype]); //qwang 2004-3-24 if(!input.rdopt) { if(mcost < mincost) { mincost = mcost; pgMbData->best_mode = blocktype; // P8x8 used when blocktype == 4 for(b8=0; b8<4; b8++) for(b4=0; b4<4; b4++) { refFrArr_tmp[pgImage->block_y +((b8>>1)<<1) + (b4>>1)][pgImage->block_x +((b8 &1)<<1) + (b4 &1)] = refFrArr[pgImage->block_y+((b8>>1)<<1) + (b4>>1)][pgImage->block_x +((b8 &1)<<1) + (b4 &1)] ; } Save_Motion_Vector(blocktype); } } else { for(b8=0; b8<4; b8++) for(b4=0; b4<4; b4++) { sInter_Ref[blocktype][b8][b4] = refFrArr[pgImage->block_y+((b8>>1)<<1) + (b4>>1)][pgImage->block_x +((b8 &1)<<1) + (b4 &1)] ; } Save_Motion_Vector_RDO(blocktype, best_ref); } } if(!input.rdopt) { for(b8=0; b8<4; b8++) for(b4=0; b4<4; b4++) { refFrArr[pgImage->block_y +((b8>>1)<<1) + (b4>>1)][pgImage->block_x +((b8 &1)<<1) + (b4 &1)] = refFrArr_tmp[pgImage->block_y +((b8>>1)<<1) + (b4>>1)][pgImage->block_x +((b8 &1)<<1) + (b4 &1)] ; } } return mincost; } int Subblock_Motion_Search(int ref, int b8, int subblktype, int b4, int picy, int picx, int pic_pel_y, int pic_pel_x, int lambda_factor) //qwang 2004-3-20 { int mincost = 1<<30 ; int offx ,off_y , k; int i,j; int** ref_array = refFrArr ; int*** mv_array = tmp_mv ; int mb_x = picx-pgImage->pix_x; //zhangnan 2004-04-16 int mb_y = picy-pgImage->pix_y; int block_x = (mb_x>>2); int block_y = (mb_y>>2); int bsx = csiInter_Subblk_Size[subblktype-1][0]; int bsy = csiInter_Subblk_Size[subblktype-1][1]; //zhangnan 2004-04-16 int pred_mv[2]; int xpos, ypos; SetMotionVectorPredictor(pred_mv, ref, mb_x, mb_y, bsx, bsy); sInter_Pred_MV[b8][b4][0] = pred_mv[0]; sInter_Pred_MV[b8][b4][1] = pred_mv[1]; //zhangnan //--- Integer MV from Prediction sInteger_MV[0] = sInter_Pred_MV[b8][b4][0] / 4 ; // >>2 OR /4 ??? sInteger_MV[1] = sInter_Pred_MV[b8][b4][1] / 4 ; //--- adjust search center so that the (0,0)-vector is inside --- sInteger_MV[0] = max (-SEARCHRANGE, min (SEARCHRANGE, sInteger_MV[0])); sInteger_MV[1] = max (-SEARCHRANGE, min (SEARCHRANGE, sInteger_MV[1])); //--- get residual MV info sResidual_MV[0] = sInter_Pred_MV[b8][b4][0] - sInteger_MV[0]*4; sResidual_MV[1] = sInter_Pred_MV[b8][b4][1] - sInteger_MV[1]*4; offx = off_y = 0; ypos = sInteger_MV[1] + pic_pel_y; xpos = sInteger_MV[0] + pic_pel_x; #ifndef _FULL_SEARCH_ mincost = FME_Integer_Pel_Block_Motion_Search(ref, offx,off_y,b8, P8x8, b4, subblktype, mincost,lambda_factor, ypos, xpos); #else mincost = Full_Integer_Pel_Block_Motion_Search(ref,offx,off_y,b8, P8x8, b4,subblktype,mincost,lambda_factor, ypos, xpos); #endif if(input.hadamard) mincost = 1<<20; ypos = sInteger_MV[1]*4 + sInter_MV[b8][b4][1] - QUARTER_CENTER_OFFSET + (pic_pel_y << 2); xpos = sInteger_MV[0]*4 + sInter_MV[b8][b4][0] - QUARTER_CENTER_OFFSET + (pic_pel_x << 2); #ifndef _FULL_SEARCH_ mincost = FME_Sub_Pel_Block_Motion_Search(ref, 0,0, b8, b4, subblktype,mincost,lambda_factor, ypos, xpos); #else mincost = Sub_Pel_Block_Motion_Search(ref,0,0,b8, P8x8,b4,subblktype,mincost,lambda_factor,ypos, xpos); #endif sInter_MV[b8][b4][0] += sInteger_MV[0]*4 - (offx << 2); //sInter_Pred_MV[blockindex][0]/4*4; sInter_MV[b8][b4][1] += sInteger_MV[1]*4 - (off_y << 2); //sInter_Pred_MV[blockindex][1]/4*4; if(subblktype == 1) { for(k=0; k<4; k++) { sInter_MV[b8][k][0] = sInter_MV[b8][0][0]; sInter_MV[b8][k][1] = sInter_MV[b8][0][1]; } } else if(subblktype == 2) { sInter_MV[b8][b4+1][0] = sInter_MV[b8][b4][0]; sInter_MV[b8][b4+1][1] = sInter_MV[b8][b4][1]; } else if(subblktype == 3) { sInter_MV[b8][b4+2][0] = sInter_MV[b8][b4][0]; sInter_MV[b8][b4+2][1] = sInter_MV[b8][b4][1]; } for (i=0; i < (bsx>>2); i++) { for (j=0; j < (bsy>>2); j++) { all_mv[block_x+i][block_y+j][subblktype+3][0] = sInter_MV[b8][b4][0]; all_mv[block_x+i][block_y+j][subblktype+3][1] = sInter_MV[b8][b4][1]; } } return mincost; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function name : Block_Motion_Search + parameters 1 : blocktype (mode type) + parameters 2 : blockindex(block index based on blocktype) + return : cost of the current block + descriptions : created by xyji: 2004/02/12 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int Block_Motion_Search(int ref, int blktype, int blkindex, int pic_pel_y, int pic_pel_x, int lambda_factor) //qwang 2004-3-20 { int mincost = 1<<30 , cost ; int offx ,off_y ; int i,j; int mb_x = pic_pel_x-pgImage->pix_x; //zhangnan 2004-04-16 int mb_y = pic_pel_y-pgImage->pix_y; int block_x = (mb_x>>2); int block_y = (mb_y>>2); int bsx = csiInter_Block_Size[blktype-1][0]; int bsy = csiInter_Block_Size[blktype-1][1]; //zhangnan 2004-04-16 int pred_mv[2]; int ypos, xpos; //cbzhu 12-15 #ifdef _ISOLATED_REGION_ int ireg_flag ; int x,y,refx,refy; #endif //_ISOLATED_REGION_ SetMotionVectorPredictor(pred_mv,ref, mb_x, mb_y, bsx, bsy); sInter_Pred_MV[blkindex][0][0] = pred_mv[0]; sInter_Pred_MV[blkindex][0][1] = pred_mv[1]; //--- Integer MV from Prediction sInteger_MV[0] = sInter_Pred_MV[blkindex][0][0] / 4 ; // >>2 OR /4 sInteger_MV[1] = sInter_Pred_MV[blkindex][0][1] / 4 ; //--- adjust search center so that the (0,0)-vector is inside --- sInteger_MV[0] = max (-SEARCHRANGE, min (SEARCHRANGE, sInteger_MV[0])); sInteger_MV[1] = max (-SEARCHRANGE, min (SEARCHRANGE, sInteger_MV[1])); //--- get residual MV info sResidual_MV[0] = sInter_Pred_MV[blkindex][0][0] - sInteger_MV[0]*4; sResidual_MV[1] = sInter_Pred_MV[blkindex][0][1] - sInteger_MV[1]*4; offx = off_y = 0; ypos = sInteger_MV[1] + pic_pel_y; xpos = sInteger_MV[0] + pic_pel_x; #ifndef _FULL_SEARCH_ mincost = FME_Integer_Pel_Block_Motion_Search(ref,offx,off_y,blkindex,blktype,0, 3 , mincost,lambda_factor, ypos, xpos); #else mincost = Full_Integer_Pel_Block_Motion_Search(ref,offx,off_y,blkindex,blktype,0,-1,mincost,lambda_factor, ypos, xpos); #endif //cbzhu 0412 #ifdef _ISOLATED_REGION_ if (input.IREGEnable) { if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) { if (iIntegerPixFlag == 0) { return (1 << 30); } } } #endif // _ISOLATED_REGION_ ypos = sInteger_MV[1]*4 + sInter_MV[blkindex][0][1] - QUARTER_CENTER_OFFSET + (pic_pel_y << 2); xpos = sInteger_MV[0]*4 + sInter_MV[blkindex][0][0] - QUARTER_CENTER_OFFSET + (pic_pel_x << 2); #ifndef _FULL_SEARCH_ if(input.hadamard) mincost = 1<<20; mincost = Sub_Pel_Block_Motion_Search(ref,0,0,blkindex,blktype,0,-1,mincost,lambda_factor, ypos, xpos); #else if(input.hadamard) mincost = 1<<20; mincost = Sub_Pel_Block_Motion_Search(ref,0,0,blkindex,blktype,0,-1,mincost,lambda_factor, ypos, xpos); #endif //cbzhu 12-15 #ifdef _ISOLATED_REGION_ if (input.IREGEnable) { if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) { if (iSubPixFlag1 == 1) { return (1 << 30); } } } #endif // _ISOLATED_REGION_ // Get the Skip Mode cost by jhzheng [16:25 2004/02/27] if ((blktype == 1) && (ref==0)) { Find_SkipMode_MotionVector(); ypos = sSkip_MV[1] - QUARTER_CENTER_OFFSET + (pic_pel_y << 2); xpos = sSkip_MV[0] - QUARTER_CENTER_OFFSET + (pic_pel_x << 2); cost = Get_SkipCostMB(ref,0,0,mincost, ypos, xpos); //cbzhu 12-15 #ifdef _ISOLATED_REGION_ if (input.IREGEnable) { if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) { ireg_flag = 0; for (y = 0; y < MB_BLOCK_SIZE; y++) { for (x = 0; x < MB_BLOCK_SIZE; x++) { refx = (pic_pel_x << 2) + ( x << 2 ) + sSkip_MV[0]; refy = (pic_pel_y << 2) + ( y << 2 ) + sSkip_MV[1]; ireg_flag = AffectedByLeftover(refx, refy, ref); if ( ireg_flag ) { break; } } if ( ireg_flag ) { break; } } if ( ireg_flag ) { cost = 1<<30; } } }//if (input->IREGEnable) #endif // _ISOLATED_REGION_ if (cost < mincost) { mincost = cost; sInter_MV[blkindex][0][0] = sSkip_MV[0]; sInter_MV[blkindex][0][1] = sSkip_MV[1]; // must set sInter_MV = sInter_Pred_MV !!! sInteger_MV[0] = sInteger_MV[1] = 0; offx = off_y = 0; } } sInter_MV[blkindex][0][0] += sInteger_MV[0]*4 - (offx << 2); //sInter_Pred_MV[blockindex][0]/4*4; sInter_MV[blkindex][0][1] += sInteger_MV[1]*4 - (off_y << 2); //sInter_Pred_MV[blockindex][1]/4*4; for (i=0; i < (bsx>>2); i++) { for (j=0; j < (bsy>>2); j++) { all_mv[block_x+i][block_y+j][blktype][0] = sInter_MV[blkindex][0][0]; all_mv[block_x+i][block_y+j][blktype][1] = sInter_MV[blkindex][0][1]; } } return mincost; } /*! *********************************************************************** * \brief * setting the motion vector predictor *********************************************************************** */ void SetMotionVectorPredictor (int pmv[2], //zhangnan int ref_frame, int mb_x, int mb_y, int blockshape_x, int blockshape_y) { int pic_block_x = pgImage->block_x + (mb_x>>2); int pic_block_y = pgImage->block_y + (mb_y>>2); int mb_width = pgImage->img_width/16; //WJP FOR SLICE int mb_available_up = (pgImage->mb_y == 0 ) ? 0 : (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-mb_width].slice_nr); int mb_available_left = (pgImage->mb_x == 0 ) ? 0 : (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-1].slice_nr); int mb_available_upleft = (pgImage->mb_x == 0 || pgImage->mb_y == 0) ? 0 : (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-mb_width-1].slice_nr); int mb_available_upright = (pgImage->mb_x >= mb_width-1 || pgImage->mb_y == 0) ? 0 : (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-mb_width+1].slice_nr); //WJP END int block_available_up, block_available_left, block_available_upright, block_available_upleft; int mv_a, mv_b, mv_c, mv_d, pred_vec[2]; int mvPredType, rFrameL, rFrameU, rFrameUR; int hv; int a_c, b_c, a_b;//qhg int ABC;//qhg int a[2],b[2],c[2];//qhg // D B C // A X // 1 A, B, D are set to 0 if unavailable // 2 If C is not available it is replaced by D block_available_up = mb_available_up || (mb_y > 0); block_available_left = mb_available_left || (mb_x > 0); if (mb_y > 0) { if (mb_x < 8) // first column of 8x8 blocks { if (mb_y==8) { if (blockshape_x == 16) block_available_upright = 0; else block_available_upright = 1; } else { if (mb_x+blockshape_x != 8) block_available_upright = 1; else block_available_upright = 0; } } else { if (mb_x+blockshape_x != 16) block_available_upright = 1; else block_available_upright = 0; } } else if (mb_x+blockshape_x != MB_BLOCK_SIZE) { block_available_upright = block_available_up; } else { block_available_upright = mb_available_upright; } if (mb_x > 0) { block_available_upleft = (mb_y > 0 ? 1 : block_available_up); } else if (mb_y > 0) { block_available_upleft = block_available_left; } else { block_available_upleft = mb_available_upleft; } mvPredType = MVPRED_MEDIAN; // rFrameL = block_available_left ? refFrArr[pic_block_y] [pic_block_x-1] : -1; rFrameL = block_available_left ? refFrArr[pic_block_y+blockshape_y/4 -1] [pic_block_x-1] : -1; //JX 05-4-1 rFrameU = block_available_up ? refFrArr[pic_block_y-1][pic_block_x] : -1; //added by MZ if(block_available_upright) block_available_upright = block_available_upright && (refFrArr[pic_block_y-1][pic_block_x+blockshape_x/4]!=-1); if(block_available_upleft) block_available_upleft = block_available_upleft && (refFrArr[pic_block_y-1][pic_block_x-1 ]!=-1); rFrameUR = block_available_upright ? refFrArr[pic_block_y-1][pic_block_x+blockshape_x/4] : block_available_upleft ? refFrArr[pic_block_y-1][pic_block_x-1] : -1; //Prediction if only one of the neighbors uses the reference frame if(rFrameL == ref_frame && rFrameU != ref_frame && rFrameUR != ref_frame) mvPredType = MVPRED_L; else if(rFrameL != ref_frame && rFrameU == ref_frame && rFrameUR != ref_frame) mvPredType = MVPRED_U; else if(rFrameL != ref_frame && rFrameU != ref_frame && rFrameUR == ref_frame) mvPredType = MVPRED_UR; // Directional predictions else if(blockshape_x == 8 && blockshape_y == 16) { if(mb_x == 0) { if(rFrameL == ref_frame) mvPredType = MVPRED_L; } else { if(rFrameUR == ref_frame) mvPredType = MVPRED_UR; } } else if(blockshape_x == 16 && blockshape_y == 8) { if(mb_y == 0) { if(rFrameU == ref_frame) mvPredType = MVPRED_U; } else { if(rFrameL == ref_frame) mvPredType = MVPRED_L; } } #define MIN(a,b,c) (ab?a>c?a:c:b>c?b:c)//WJP FOR MV prediction 050320 a_b=a_c=b_c=0; //printf("%d \n" , pgImage->current_mb_nr); for (hv=0; hv < 2; hv++) { //mv_a = block_available_left ? tmp_mv[hv][pic_block_y ][4+pic_block_x-1] : 0; mv_a = block_available_left ? tmp_mv[hv][pic_block_y + (blockshape_y/4) -1 ][4+pic_block_x-1]: 0; mv_b = block_available_up ? tmp_mv[hv][pic_block_y-1][4+pic_block_x] : 0; mv_d = block_available_upleft ? tmp_mv[hv][pic_block_y-1][4+pic_block_x-1] : 0; mv_c = block_available_upright ? tmp_mv[hv][pic_block_y-1][4+pic_block_x+blockshape_x/4] : mv_d; //qhg a[hv] = mv_a; b[hv] = mv_b; c[hv] = mv_c; a_b+= abs(mv_a-mv_b); a_c+= abs(mv_a-mv_c); b_c+= abs(mv_b-mv_c); switch (mvPredType) { case MVPRED_MEDIAN: /*WJP FOR MV prediction 050320 if(!(block_available_upleft || block_available_up || block_available_upright)) pred_vec[hv] = mv_a; else { //qhg if(hv==1) { ABC = MIN(a_b,a_c,b_c); if(ABC==a_b) { if(ABC==a_c) { pred_vec[0] = a[0]; pred_vec[1] = a[1]; } else if(ABC==b_c) { pred_vec[0] = b[0]; pred_vec[1] = b[1]; } else { pred_vec[0] = (a[0]+b[0]+1)>>1; pred_vec[1] = (a[1]+b[1]+1)>>1; } } else if(ABC==a_c) { if(ABC==b_c) { pred_vec[0] = c[0]; pred_vec[1] = c[1]; } else { pred_vec[0] = (a[0]+c[0]+1)>>1; pred_vec[1] = (a[1]+c[1]+1)>>1; } } else { pred_vec[0] = (b[0]+c[0]+1)>>1; pred_vec[1] = (b[1]+c[1]+1)>>1; } } } */ if(hv == 1) { ABC = MAX(a_b,a_c,b_c); if(ABC == a_b) { pred_vec[0] = c[0]; pred_vec[1] = c[1]; } else if(ABC == b_c) { pred_vec[0] = a[0]; pred_vec[1] = a[1]; } else { pred_vec[0] = b[0]; pred_vec[1] = b[1]; } } //WJP END break; case MVPRED_L: pred_vec[hv] = mv_a; break; case MVPRED_U: pred_vec[hv] = mv_b; break; case MVPRED_UR: pred_vec[hv] = mv_c; break; default: break; } } if ( pgImage->half_pixel_mv_flag == 0) // 1/4 MV { pmv[0] = pred_vec[0]; //qhg pmv[1] = pred_vec[1]; } else // 1/2 MV { pmv[0] = pred_vec[0] << 1; //qhg pmv[1] = pred_vec[1] << 1; } #undef MIN } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function name : Get_SkipModeMB + parameters : void + return : int + descriptions : Get cost for skip mode of a macroblock + created by jhzheng : 2004/02/27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int Get_SkipCostMB(int ref, int cand_x, int cand_y, int mincost, int ypos, int xpos) { int cost = -(pgMbData->lambda<<3); int diff[16]; int y,x,i,j, k; int refy,refx,oriy,orix; int y_pos, x_pos; int width4 = (pgImage->img_width + (PAD_SIZE<<1) - 1)<<2; int height4 = (pgImage->img_height + (PAD_SIZE<<1) - 1)<<2; pgMbData->skip_cost = 0; for (y=0; y<16; y+=4) { oriy = y; refy = QUARTER_CENTER_OFFSET + cand_y + (y<<2); for (x=0; x<16; x+=4) { orix = x; refx = QUARTER_CENTER_OFFSET + cand_x + (x<<2); k = 0; if(!input.hadamard) { for(j=0; j<4; j++) for(i = 0 ; i < 4 ; i ++) { y_pos = ypos+ QUARTER_CENTER_OFFSET+ (j<<2) + cand_y + (y<<2) + (PAD_SIZE<<2); x_pos = xpos+ QUARTER_CENTER_OFFSET+ (i<<2) + cand_x + (x<<2) + (PAD_SIZE<<2); x_pos = (x_pos < 0) ? (x_pos & 3) : (x_pos > width4 ) ? (width4 + (x_pos & 3)) : x_pos; y_pos = (y_pos < 0) ? (y_pos & 3) : (y_pos > height4) ? (height4 + (y_pos & 3)) : y_pos; cost += absm(pgMbData->org_luma[oriy+j][orix+i] - reference_quater_pel_frame[ref][y_pos][x_pos]); //???? qwang 2004-3-21 pgMbData->skip_cost += quadarr[pgMbData->org_luma[oriy+j][orix+i] - reference_quater_pel_frame[ref][y_pos][x_pos]]; } }else { for(j=0; j<4; j++) for(i = 0 ; i < 4 ; i++) { y_pos = ypos+ QUARTER_CENTER_OFFSET+ (j<<2) + cand_y + (y<<2) + (PAD_SIZE<<2); x_pos = xpos+ QUARTER_CENTER_OFFSET+ (i<<2) + cand_x + (x<<2) + (PAD_SIZE<<2); x_pos = (x_pos < 0) ? (x_pos & 3) : (x_pos > width4 ) ? (width4 + (x_pos & 3)) : x_pos; y_pos = (y_pos < 0) ? (y_pos & 3) : (y_pos > height4) ? (height4 + (y_pos & 3)) : y_pos; diff[k++] = (pgMbData->org_luma[oriy+j][orix+i] - reference_quater_pel_frame[ref][y_pos][x_pos]); //???? qwang 2004-3-21 pgMbData->skip_cost += quadarr[pgMbData->org_luma[oriy+j][orix+i] - reference_quater_pel_frame[ref][y_pos][x_pos]]; } cost += SATD(diff); } } if (cost > mincost) { break; } } return cost; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function name : Get skip mode rd cost + parameters : void + return : int + descriptions : Get cost for skip mode of a macroblock + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ void Get_Skip_RD_Cost_MB() { int i, j; int b8, b4; int rate1, rate2; for(j=0; j<4; j++) for(i=0; i<4; i++) { pgMbData->mvb[j][i][0] = sSkip_MV[0]; pgMbData->mvb[j][i][1] = sSkip_MV[1]; tmp_mv[0][pgMbData->mb_y*4+j][pgMbData->mb_x*4+i+4] = sSkip_MV[0]; tmp_mv[1][pgMbData->mb_y*4+j][pgMbData->mb_x*4+i+4] = sSkip_MV[1]; } for(b8=0; b8<4; b8++) for(b4=0; b4<4; b4++) { refFrArr[pgImage->block_y +((b8>>1)<<1) + (b4>>1)][pgImage->block_x +((b8 &1)<<1) + (b4 &1)]=0; } Load_Ref_Luma(); Load_Ref_Chroma(); for(b8 = 4 ; b8 < 6 ; b8++) { for (j=0; j<8; j++) { for (i=0; i<8; i++) { pgMbData->pred_sample[b8][i/4+(j/4)*2][j%4][i%4] = pgMbData->pred_sample_c[b8][j][i]; pgMbData->skip_cost += quadarr[pgMbData->org_chroma[b8-4][j][i]-pgMbData->pred_sample_c[b8][j][i]]; } } } Save_RD_State(); rate2 = ue_linfo(pgImage->cod_counter); rate1 = ue_linfo(pgImage->cod_counter+1); Restore_RD_State(); //pgMbData->skip_cost += pgMbData->lamda_mode*(rate2-rate1);//WJP pgMbData->skip_cost += pgMbData->lamda_mode*(rate1-rate2); //cbzhu #ifdef _ISOLATED_REGION_ if (input.IREGEnable) { int ireg_flag; int y, x; int refx, refy; int pic_pel_x, pic_pel_y; pic_pel_x = pgImage->mb_x * MB_BLOCK_SIZE; pic_pel_y = pgImage->mb_y * MB_BLOCK_SIZE; if (pCurrFrmIREGMap[pgImage->mb_y][pgImage->mb_x] != 0) { ireg_flag = 0; for (y = 0; y < MB_BLOCK_SIZE; y++) { for (x = 0; x < MB_BLOCK_SIZE; x++) { refx = (pic_pel_x << 2) + ( x << 2 ) + sSkip_MV[0]; refy = (pic_pel_y << 2) + ( y << 2 ) + sSkip_MV[1]; ireg_flag = AffectedByLeftover(refx, refy, 0); if ( ireg_flag ) { break; } } if ( ireg_flag ) { break; } } if ( ireg_flag ) { pgMbData->skip_cost = 1<<30; } } }//if (input->IREGEnable) #endif // _ISOLATED_REGION_ } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function name : FindSkipModeMotionVector + parameters : void + return : void + descriptions : Find motion vector for the Skip mode + created by jhzheng : 2004/02/27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ void Find_SkipMode_MotionVector(void) //zhangnan { int pmv[2]; int mb_available_up = (pgMbData->mb_y == 0) ? 0 : (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-pgImage->img_width/16].slice_nr);//WJP FOR SLICE int mb_available_left = (pgMbData->mb_x == 0) ? 0 : (pgMbData->slice_nr == pgImage->mb_data_forlf[pgImage->current_mb_nr-1].slice_nr);//WJP FOR SLICE int zeroMotionAbove = !mb_available_up ? 1 : refFrArr[pgImage->block_y-1][pgImage->block_x] == 0 && tmp_mv[0][pgImage->block_y-1][4+pgImage->block_x ] == 0 && tmp_mv[1][pgImage->block_y-1][4+pgImage->block_x ] == 0 ? 1 : 0; //int zeroMotionLeft = !mb_available_left? 1 : refFrArr[pgImage->block_y][pgImage->block_x-1] == 0 && tmp_mv[0][pgImage->block_y+][4+pgImage->block_x-1] == 0 && tmp_mv[1][pgImage->block_y][4+pgImage->block_x-1] == 0 ? 1 : 0; // MZ 050403 int zeroMotionLeft = !mb_available_left? 1 : refFrArr[pgImage->block_y+BLOCK_SIZE-1][pgImage->block_x-1] == 0 && tmp_mv[0][pgImage->block_y+BLOCK_SIZE-1][4+pgImage->block_x-1] == 0 && tmp_mv[1][pgImage->block_y+BLOCK_SIZE-1][4+pgImage->block_x-1] == 0 ? 1 : 0; if (zeroMotionAbove || zeroMotionLeft) { sSkip_MV[0] = sSkip_MV[1] = 0; } else { SetMotionVectorPredictor(pmv,0, 0,0, 16, 16); sSkip_MV[0] = pmv[0]; sSkip_MV[1] = pmv[1]; } } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function name : Init_Inter_Image + parameters : void + return : void + descriptions : created by xyji & jhzheng : 2004/02/12 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ void Init_Inter_Sequence(void) { int k, l, i, bits, imin, imax; int number_of_subpel_positions = 4 * (2 * SEARCHRANGE + 3); int max_mv_bits = 3 + 2 * (int)ceil (log(number_of_subpel_positions+1) / log(2) + 1e-10); int max_mvd = (1<<( max_mv_bits >>1) )-1; if ((gMV_Bits = (short*)calloc(2*max_mvd+1, sizeof(short))) == NULL) printf("Init_Inter_Sequence: mvbits"); //--- set array offsets --- gMV_Bits += max_mvd; //--- init array: motion vector bits --- gMV_Bits[0] = 1; for (bits=3; bits<=max_mv_bits; bits+=2) { imax = 1 << (bits >> 1); imin = imax >> 1; for (i = imin; i < imax; i++) gMV_Bits[-i] = gMV_Bits[i] = bits; } pgMbData->Spiral_index[0][0] = pgMbData->Spiral_index[0][1] = 0; #ifdef _FULL_SEARCH_ // when use Full Search Algorithm, l value <= SearchRange for (k=1, l=1; l<=SEARCHRANGE; l++) #else // 5x5 : 2*2 + 1 // when use Fast Search Algorithm, l value <= 2 OK for (k=1, l=1; l<=2; l++) #endif { for (i=-l+1; i< l; i++) { pgMbData->Spiral_index[k][0] = i; pgMbData->Spiral_index[k++][1] = -l; pgMbData->Spiral_index[k][0] = i; pgMbData->Spiral_index[k++][1] = l; } for (i=-l; i<=l; i++) { pgMbData->Spiral_index[k][0] = -l; pgMbData->Spiral_index[k++][1] = i; pgMbData->Spiral_index[k][0] = l; pgMbData->Spiral_index[k++][1] = i; } } pgMbData->Diamond_index[0][0] = -1; pgMbData->Diamond_index[0][1] = 0; pgMbData->Diamond_index[1][0] = 0; pgMbData->Diamond_index[1][1] = 1; pgMbData->Diamond_index[2][0] = 1; pgMbData->Diamond_index[2][1] = 0; pgMbData->Diamond_index[3][0] = 0; pgMbData->Diamond_index[3][1] = -1; pgMbData->Hexagon_index[0][0] = 2; pgMbData->Hexagon_index[0][1] = 0; pgMbData->Hexagon_index[1][0] = 1; pgMbData->Hexagon_index[1][1] = -2; pgMbData->Hexagon_index[2][0] = -1; pgMbData->Hexagon_index[2][1] = -2; pgMbData->Hexagon_index[3][0] = -2; pgMbData->Hexagon_index[3][1] = 0; pgMbData->Hexagon_index[4][0] = -1; pgMbData->Hexagon_index[4][1] = 2; pgMbData->Hexagon_index[5][0] = 1; pgMbData->Hexagon_index[5][1] = 2; pgMbData->BigHexagon_index[ 0][0] = 0; pgMbData->BigHexagon_index[ 0][1] = 4; pgMbData->BigHexagon_index[ 1][0] = -2; pgMbData->BigHexagon_index[ 1][1] = 3; pgMbData->BigHexagon_index[ 2][0] = -4; pgMbData->BigHexagon_index[ 2][1] = 2; pgMbData->BigHexagon_index[ 3][0] = -4; pgMbData->BigHexagon_index[ 3][1] = 1; pgMbData->BigHexagon_index[ 4][0] = -4; pgMbData->BigHexagon_index[ 4][1] = 0; pgMbData->BigHexagon_index[ 5][0] = -4; pgMbData->BigHexagon_index[ 5][1] = -1; pgMbData->BigHexagon_index[ 6][0] = -4; pgMbData->BigHexagon_index[ 6][1] = -2; pgMbData->BigHexagon_index[ 7][0] = -2; pgMbData->BigHexagon_index[ 7][1] = -3; pgMbData->BigHexagon_index[ 8][0] = 0; pgMbData->BigHexagon_index[ 8][1] = -4; pgMbData->BigHexagon_index[ 9][0] = 2; pgMbData->BigHexagon_index[ 9][1] = -3; pgMbData->BigHexagon_index[10][0] = 4; pgMbData->BigHexagon_index[10][1] = -2; pgMbData->BigHexagon_index[11][0] = 4; pgMbData->BigHexagon_index[11][1] = -1; pgMbData->BigHexagon_index[12][0] = 4; pgMbData->BigHexagon_index[12][1] = 0; pgMbData->BigHexagon_index[13][0] = 4; pgMbData->BigHexagon_index[13][1] = 1; pgMbData->BigHexagon_index[14][0] = 4; pgMbData->BigHexagon_index[14][1] = 2; pgMbData->BigHexagon_index[15][0] = 2; pgMbData->BigHexagon_index[15][1] = 3; } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function name : save motion vector for each block + parameters : + return : + descriptions : ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ void Save_Motion_Vector(int blocktype) { int b8, b4; // fill all 4 MV in one MB by jhzheng [21:01 2004/02/15] if (blocktype==1) {//16x16 for(b8=0; b8<4; b8++) for(b4=0; b4<4; b4++) { sInter_MV[b8][b4][0] = sInter_MV_ref[0][0][0]; sInter_MV[b8][b4][1] = sInter_MV_ref[0][0][1]; sInter_Pred_MV[b8][b4][0] = sInter_Pred_MV_ref[0][0][0]; //zhangnan sInter_Pred_MV[b8][b4][1] = sInter_Pred_MV_ref[0][0][1]; } } else if (blocktype==2) {//16x8 for(b8=0; b8<4; b8++) for(b4=0; b4<4; b4++) { if(b8<2) { sInter_MV[b8][b4][0] = sInter_MV_ref[0][0][0]; sInter_MV[b8][b4][1] = sInter_MV_ref[0][0][1]; sInter_Pred_MV[b8][b4][0] = sInter_Pred_MV_ref[0][0][0]; //zhangnan sInter_Pred_MV[b8][b4][1] = sInter_Pred_MV_ref[0][0][1]; } else { sInter_MV[b8][b4][0] = sInter_MV_ref[2][0][0]; sInter_MV[b8][b4][1] = sInter_MV_ref[2][0][1]; sInter_Pred_MV[b8][b4][0] = sInter_Pred_MV_ref[2][0][0]; //zhangnan sInter_Pred_MV[b8][b4][1] = sInter_Pred_MV_ref[2][0][1]; } } } else if (blocktype==3) {//8x16 for(b8=0; b8<4; b8++) for(b4=0; b4<4; b4++) { if(b8&1) { sInter_MV[b8][b4][0] = sInter_MV_ref[1][0][0]; sInter_MV[b8][b4][1] = sInter_MV_ref[1][0][1]; sInter_Pred_MV[b8][b4][0] = sInter_Pred_MV_ref[1][0][0]; //zhangnan sInter_Pred_MV[b8][b4][1] = sInter_Pred_MV_ref[1][0][1]; } else { sInter_MV[b8][b4][0] = sInter_MV_ref[0][0][0]; sInter_MV[b8][b4][1] = sInter_MV_ref[0][0][1]; sInter_Pred_MV[b8][b4][0] = sInter_Pred_MV_ref[0][0][0]; //zhangnan sInter_Pred_MV[b8][b4][1] = sInter_Pred_MV_ref[0][0][1]; } } } if(blocktype==4) { for(b8 = 0; b8 < 4; b8++) for(b4 = 0; b4 < 4; b4++) { pgMbData->mvb[b8][b4][0] = pgMbData->mvb_ref[b8][b4][0]; pgMbData->mvb[b8][b4][1] = pgMbData->mvb_ref[b8][b4][1]; pgMbData->pred_mv[b8][b4][0] = pgMbData->pred_mv_ref[b8][b4][0]; pgMbData->pred_mv[b8][b4][1] = pgMbData->pred_mv_ref[b8][b4][1]; } } else { for(b8 = 0; b8 < 4; b8++) for(b4 = 0; b4 < 4; b4++) { pgMbData->mvb[b8][b4][0] = sInter_MV[b8][b4][0]; pgMbData->mvb[b8][b4][1] = sInter_MV[b8][b4][1]; pgMbData->pred_mv[b8][b4][0] = sInter_Pred_MV[b8][b4][0]; pgMbData->pred_mv[b8][b4][1] = sInter_Pred_MV[b8][b4][1]; } } } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function name : save motion vector for RDO + parameters : + return : + descriptions : ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ void Save_Motion_Vector_RDO(int blocktype, int best_ref) { int b8, b4; // fill all 4 MV in one MB by jhzheng [21:01 2004/02/15] if (blocktype==1) {//16x16 for(b8=0; b8<4; b8++) for(b4=0; b4<4; b4++) { blk_MV[blocktype][b8][b4][0] = sInter_MV_ref[0][0][0]; blk_MV[blocktype][b8][b4][1] = sInter_MV_ref[0][0][1]; blk_Pred_MV[blocktype][b8][b4][0] = sInter_Pred_MV_ref[0][0][0]; //zhangnan blk_Pred_MV[blocktype][b8][b4][1] = sInter_Pred_MV_ref[0][0][1]; } } else if (blocktype==2) {//16x8 for(b8=0; b8<4; b8++) for(b4=0; b4<4; b4++) { if(b8<2) { blk_MV[blocktype][b8][b4][0] = sInter_MV_ref[0][0][0]; blk_MV[blocktype][b8][b4][1] = sInter_MV_ref[0][0][1]; blk_Pred_MV[blocktype][b8][b4][0] = sInter_Pred_MV_ref[0][0][0]; //zhangnan blk_Pred_MV[blocktype][b8][b4][1] = sInter_Pred_MV_ref[0][0][1]; } else { blk_MV[blocktype][b8][b4][0] = sInter_MV_ref[2][0][0]; blk_MV[blocktype][b8][b4][1] = sInter_MV_ref[2][0][1]; blk_Pred_MV[blocktype][b8][b4][0] = sInter_Pred_MV_ref[2][0][0]; //zhangnan blk_Pred_MV[blocktype][b8][b4][1] = sInter_Pred_MV_ref[2][0][1]; } } } else if (blocktype==3) {//8x16 for(b8=0; b8<4; b8++) for(b4=0; b4<4; b4++) { if(b8&1) { blk_MV[blocktype][b8][b4][0] = sInter_MV_ref[1][0][0]; blk_MV[blocktype][b8][b4][1] = sInter_MV_ref[1][0][1]; blk_Pred_MV[blocktype][b8][b4][0] = sInter_Pred_MV_ref[1][0][0]; //zhangnan blk_Pred_MV[blocktype][b8][b4][1] = sInter_Pred_MV_ref[1][0][1]; } else { blk_MV[blocktype][b8][b4][0] = sInter_MV_ref[0][0][0]; blk_MV[blocktype][b8][b4][1] = sInter_MV_ref[0][0][1]; blk_Pred_MV[blocktype][b8][b4][0] = sInter_Pred_MV_ref[0][0][0]; //zhangnan blk_Pred_MV[blocktype][b8][b4][1] = sInter_Pred_MV_ref[0][0][1]; } } } if(blocktype==4) { for(b8 = 0; b8 < 4; b8++) { int best_subblk_type = pgMbData->best_mode_subblk[b8]; for(b4 = 0; b4 < 4; b4++) { int best_ref2 = sInter_Ref[4][b8][b4]; blk_MV[blocktype][b8][b4][0] = subblk_MV[best_subblk_type][best_ref2][b8][b4][0]; blk_MV[blocktype][b8][b4][1] = subblk_MV[best_subblk_type][best_ref2][b8][b4][1]; blk_Pred_MV[blocktype][b8][b4][0] = subblk_Pred_MV[best_subblk_type][best_ref2][b8][b4][0]; blk_Pred_MV[blocktype][b8][b4][1] = subblk_Pred_MV[best_subblk_type][best_ref2][b8][b4][1]; } } } } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function name : save motion vector for each block + parameters : + return : + descriptions : ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ void Save_Subblk_Motion_Vector_RDO(int subblktype, int b8, int ref) { int b4; if (subblktype==1) {//8x8 for(b4=0; b4<4; b4++) { subblk_MV[subblktype][ref][b8][b4][0] = sInter_MV[b8][0][0]; subblk_MV[subblktype][ref][b8][b4][1] = sInter_MV[b8][0][1]; subblk_Pred_MV[subblktype][ref][b8][b4][0] = sInter_Pred_MV[b8][0][0]; subblk_Pred_MV[subblktype][ref][b8][b4][1] = sInter_Pred_MV[b8][0][1]; } } else if (subblktype==2) {//8x4 subblk_MV[subblktype][ref][b8][0][0] = sInter_MV[b8][0][0]; subblk_MV[subblktype][ref][b8][0][1] = sInter_MV[b8][0][1]; subblk_MV[subblktype][ref][b8][1][0] = sInter_MV[b8][0][0]; subblk_MV[subblktype][ref][b8][1][1] = sInter_MV[b8][0][1]; subblk_MV[subblktype][ref][b8][2][0] = sInter_MV[b8][2][0]; subblk_MV[subblktype][ref][b8][2][1] = sInter_MV[b8][2][1]; subblk_MV[subblktype][ref][b8][3][0] = sInter_MV[b8][2][0]; subblk_MV[subblktype][ref][b8][3][1] = sInter_MV[b8][2][1]; subblk_Pred_MV[subblktype][ref][b8][0][0] = sInter_Pred_MV[b8][0][0]; subblk_Pred_MV[subblktype][ref][b8][0][1] = sInter_Pred_MV[b8][0][1]; subblk_Pred_MV[subblktype][ref][b8][1][0] = sInter_Pred_MV[b8][0][0]; subblk_Pred_MV[subblktype][ref][b8][1][1] = sInter_Pred_MV[b8][0][1]; subblk_Pred_MV[subblktype][ref][b8][2][0] = sInter_Pred_MV[b8][2][0]; subblk_Pred_MV[subblktype][ref][b8][2][1] = sInter_Pred_MV[b8][2][1]; subblk_Pred_MV[subblktype][ref][b8][3][0] = sInter_Pred_MV[b8][2][0]; subblk_Pred_MV[subblktype][ref][b8][3][1] = sInter_Pred_MV[b8][2][1]; } else if (subblktype==3) {//4x8 subblk_MV[subblktype][ref][b8][0][0] = sInter_MV[b8][0][0]; subblk_MV[subblktype][ref][b8][0][1] = sInter_MV[b8][0][1]; subblk_MV[subblktype][ref][b8][2][0] = sInter_MV[b8][0][0]; subblk_MV[subblktype][ref][b8][2][1] = sInter_MV[b8][0][1]; subblk_MV[subblktype][ref][b8][1][0] = sInter_MV[b8][1][0]; subblk_MV[subblktype][ref][b8][1][1] = sInter_MV[b8][1][1]; subblk_MV[subblktype][ref][b8][3][0] = sInter_MV[b8][1][0]; subblk_MV[subblktype][ref][b8][3][1] = sInter_MV[b8][1][1]; subblk_Pred_MV[subblktype][ref][b8][0][0] = sInter_Pred_MV[b8][0][0]; subblk_Pred_MV[subblktype][ref][b8][0][1] = sInter_Pred_MV[b8][0][1]; subblk_Pred_MV[subblktype][ref][b8][2][0] = sInter_Pred_MV[b8][0][0]; subblk_Pred_MV[subblktype][ref][b8][2][1] = sInter_Pred_MV[b8][0][1]; subblk_Pred_MV[subblktype][ref][b8][1][0] = sInter_Pred_MV[b8][1][0]; subblk_Pred_MV[subblktype][ref][b8][1][1] = sInter_Pred_MV[b8][1][1]; subblk_Pred_MV[subblktype][ref][b8][3][0] = sInter_Pred_MV[b8][1][0]; subblk_Pred_MV[subblktype][ref][b8][3][1] = sInter_Pred_MV[b8][1][1]; }else { for(b4 = 0; b4 < 4; b4++) { subblk_MV[subblktype][ref][b8][b4][0] = sInter_MV[b8][b4][0]; subblk_MV[subblktype][ref][b8][b4][1] = sInter_MV[b8][b4][1]; subblk_Pred_MV[subblktype][ref][b8][b4][0] = sInter_Pred_MV[b8][b4][0]; subblk_Pred_MV[subblktype][ref][b8][b4][1] = sInter_Pred_MV[b8][b4][1]; } } } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function name : save motion vector for each block + parameters : + return : + descriptions : ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ void Save_Subblk_Motion_Vector(int subblktype, int b8) { int b4; if (subblktype==1) {//8x8 for(b4=0; b4<4; b4++) { sInter_MV[b8][b4][0] = sInter_MV[b8][0][0]; sInter_MV[b8][b4][1] = sInter_MV[b8][0][1]; sInter_Pred_MV[b8][b4][0] = sInter_Pred_MV[b8][0][0]; sInter_Pred_MV[b8][b4][1] = sInter_Pred_MV[b8][0][1]; } } else if (subblktype==2) {//8x4 sInter_MV[b8][1][0] = sInter_MV[b8][0][0]; sInter_MV[b8][1][1] = sInter_MV[b8][0][1]; sInter_MV[b8][3][0] = sInter_MV[b8][2][0]; sInter_MV[b8][3][1] = sInter_MV[b8][2][1]; sInter_Pred_MV[b8][1][0] = sInter_Pred_MV[b8][0][0]; sInter_Pred_MV[b8][1][1] = sInter_Pred_MV[b8][0][1]; sInter_Pred_MV[b8][3][0] = sInter_Pred_MV[b8][2][0]; sInter_Pred_MV[b8][3][1] = sInter_Pred_MV[b8][2][1]; } else if (subblktype==3) {//4x8 sInter_MV[b8][2][0] = sInter_MV[b8][0][0]; sInter_MV[b8][2][1] = sInter_MV[b8][0][1]; sInter_MV[b8][3][0] = sInter_MV[b8][1][0]; sInter_MV[b8][3][1] = sInter_MV[b8][1][1]; sInter_Pred_MV[b8][2][0] = sInter_Pred_MV[b8][0][0]; sInter_Pred_MV[b8][2][1] = sInter_Pred_MV[b8][0][1]; sInter_Pred_MV[b8][3][0] = sInter_Pred_MV[b8][1][0]; sInter_Pred_MV[b8][3][1] = sInter_Pred_MV[b8][1][1]; } for(b4 = 0; b4 < 4; b4++) { pgMbData->mvb_tmp[b8][b4][0] = sInter_MV[b8][b4][0]; pgMbData->mvb_tmp[b8][b4][1] = sInter_MV[b8][b4][1]; pgMbData->pred_mv_tmp[b8][b4][0] = sInter_Pred_MV[b8][b4][0]; pgMbData->pred_mv_tmp[b8][b4][1] = sInter_Pred_MV[b8][b4][1]; } } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + function name : restore motion vector for RDO + parameters : + return : + descriptions : ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ void Restore_Motion_Vector(int blocktype) { int b8, b4; for(b8 = 0; b8 < 4; b8++) for(b4 = 0; b4 < 4; b4++) { pgMbData->mvb[b8][b4][0] = blk_MV[blocktype][b8][b4][0]; pgMbData->mvb[b8][b4][1] = blk_MV[blocktype][b8][b4][1]; pgMbData->pred_mv[b8][b4][0] = blk_Pred_MV[blocktype][b8][b4][0]; pgMbData->pred_mv[b8][b4][1] = blk_Pred_MV[blocktype][b8][b4][1]; } }