www.pudn.com > avs-m3.rar > macroblock.c


/*! 
 ************************************************************************************* 
 * \file macorblock.c 
 * 
 * \brief 
 *    decoder one macroblock 
 ************************************************************************************* 
 */ 
#include  
#include  
#include  
#include  
 
#include "global.h" 
#include "header.h" 
#include "macroblock.h" 
#include "vlc.h" 
#include "defines.h" 
#include "block.h" 
 
/*!  
 ************************************************************************************* 
 * \brief 
 *    Checks the availability of neighboring macroblocks of 
 *    the current macroblock for prediction and context determination; 
 *    marks the unavailable MBs for intra prediction in the 
 *    ipredmode-array by -1. Only neighboring MBs in the causal 
 *    past of the current MB are checked. 
 ************************************************************************************* 
 */ 
void CheckAvailabilityOfNeighbors() 
{ 
  const int mb_width = pgImage->width/MB_BLOCK_SIZE; 
  const int mb_nr = pgImage->current_mb_nr; 
   
  // Check MB to the left 
  if(pgImage->pix_x >= MB_BLOCK_SIZE) 
  { 
    int remove_prediction = pgcurrMB->slice_nr != mb_data[mb_nr-1].slice_nr; 
    // upper blocks 
    if (remove_prediction) 
    { 
      pgImage->ipredmode[pgImage->block4_x][pgImage->block4_y+1] = -1; 
      pgImage->ipredmode[pgImage->block4_x][pgImage->block4_y+2] = -1; 
      pgImage->ipredmode[pgImage->block4_x][pgImage->block4_y+3] = -1; 
      pgImage->ipredmode[pgImage->block4_x][pgImage->block4_y+4] = -1; 
    } 
  } 
   
  // Check MB above 
  if(pgImage->pix_y >= MB_BLOCK_SIZE)  
  { 
    int remove_prediction = pgcurrMB->slice_nr != mb_data[mb_nr-mb_width].slice_nr; 
    // upper blocks 
    if (remove_prediction) 
    { 
      pgImage->ipredmode[pgImage->block4_x+1][pgImage->block4_y] = -1; 
      pgImage->ipredmode[pgImage->block4_x+2][pgImage->block4_y] = -1; 
      pgImage->ipredmode[pgImage->block4_x+3][pgImage->block4_y] = -1; 
      pgImage->ipredmode[pgImage->block4_x+4][pgImage->block4_y] = -1; 
    } 
  } 
   
  // Check MB left above 
  if(pgImage->pix_y >= MB_BLOCK_SIZE && pgImage->pix_x >= MB_BLOCK_SIZE) 
  { 
    int remove_prediction = pgcurrMB->slice_nr != mb_data[mb_nr-mb_width-1].slice_nr; 
     
    if (remove_prediction) 
    { 
      pgImage->ipredmode[pgImage->block4_x][pgImage->block4_y] = -1; 
    } 
  } 
  /* 
  // Check MB right above 
  if(pgImage->pix_y >= MB_BLOCK_SIZE && pgImage->pix_x < (pgImage->width-MB_BLOCK_SIZE )) 
  { 
  //if(pgcurrMB->slice_nr == mb_data[mb_nr-mb_width+1].slice_nr) 
  //pgcurrMB->mb_available[0][2]=&(mb_data[mb_nr-mb_width+1]); 
  } 
  */ 
} 
 
/*!  
 ************************************************************************************* 
 * \brief  
 *     initializes the current macroblock 
 ************************************************************************************* 
 */ 
void start_macroblock()     //qwang 2004-3-8 
{ 
  int i,j,k; 
  //int iii, jjj; 
   
  assert (pgImage->current_mb_nr >=0 && pgImage->current_mb_nr < pgImage->max_mb_nr); 
   
  pgcurrMB = &mb_data[pgImage->current_mb_nr];//GB 
  pgcurrMB->slice_nr = pgImage->current_slice_nr;//WJP FOR SLICE// 
  pgcurrMB->I_MODE = 1/*0 dongjie(check) */;//WJP FOR I_DIRECT 
  //pgcurrMB->lf_disable = pgImage->loop_filter_disable_flag; 
   
  // Update coordinates of the current macroblock  
  pgImage->mb_x = (pgImage->current_mb_nr)%(pgImage->width/MB_BLOCK_SIZE); 
  pgImage->mb_y = (pgImage->current_mb_nr)/(pgImage->width/MB_BLOCK_SIZE); 
   
  // Define vertical positions  
  pgImage->block4_y = pgImage->mb_y * BLOCK_SIZE;       // 4x4 luma block position 
  pgImage->pix_y   = pgImage->mb_y * MB_BLOCK_SIZE;   // luma macroblock position  
  pgImage->pix_c_y = pgImage->mb_y * MB_BLOCK_SIZE/2; // chroma macroblock position  
   
  // Define horizontal positions  
  pgImage->block_x = pgImage->mb_x * BLOCK_SIZE/2;      // luma block position  //zhangnan   //qwang 2004-3-10 
  pgImage->block4_x = pgImage->mb_x * BLOCK_SIZE;       // 4x4 luma block position 
  pgImage->pix_x   = pgImage->mb_x * MB_BLOCK_SIZE;   // luma pixel position  
  pgImage->pix_c_x = pgImage->mb_x * MB_BLOCK_SIZE/2; // chroma pixel position  
   
  //need modification for intra-prediction   qwang 2004-3-9  ???? 
  // If MB is next to a slice boundary, mark neighboring blocks unavailable for prediction 
  CheckAvailabilityOfNeighbors();       
   
  // Reset syntax element entries in MB struct 
  pgcurrMB->qp          = previous_qp; 
  pgcurrMB->mb_type     = -1;  /* Do not use the mb type defined in FCD 0-5*/ 
  pgcurrMB->delta_quant = 0; 
  pgcurrMB->cbp         = 0; 
  pgcurrMB->cbp_blk     = 0; 
  pgcurrMB->c_ipred_mode= -1; //MZ 
   
  //for (l=0; l < 2; l++) 
  for (j=0; j < BLOCK_MULTIPLE; j++) 
    for (i=0; i < BLOCK_MULTIPLE; i++) 
      for (k=0; k < 2; k++) 
        pgcurrMB->mvd[j][i][k] = 0; 
       
   // initialize pgImage->m7 for ABT//Lou 
  for (j=0; jm7[i][j] = 0;		 
         
  for (j=0; jm8[0][i][j] = 0; 
      pgImage->m8[1][i][j] = 0; 
    } 
           
  for (i=0;i<4;i++) 
    pgcurrMB->sub_mb_type[i]   = 0; 
           
  for (i=0;i<4;i++) // reset vectors and pred. modes 
    for(j=0;j<4;j++) 
    { 
      pgImage->mv[pgImage->block4_x+i+4][pgImage->block4_y+j][0] = 0; 
      pgImage->mv[pgImage->block4_x+i+4][pgImage->block4_y+j][1] = 0; 
      pgImage->ipredmode[pgImage->block4_x+i+1][pgImage->block4_y+j+1] = (pgImage->constrained_intra_pred_flag?-1:10) ; 
    } 
           
  //for (j=0;j<6;j++) // reset all chroma coeffs before read 
  //  for (i=0;i<4;i++) 
  //    for (iii=0;iii<4;iii++) 
  //       for (jjj=0;jjj<4;jjj++) 
  //         pgImage->cof[i][j][iii][jjj]=0;	 
                   
  for (j=0; j<4; j++) 
    for (i=0; i<4; i++) 
      refFrArr[pgImage->block4_y+j][pgImage->block4_x+i] = -1; 
} 
 
/*!  
 ************************************************************************************* 
 * \brief  
 *     Get the syntax elements from the NAL 
 ************************************************************************************* 
 */ 
int read_one_macroblock()    //qwang 2004-3-9 
{ 
  int b8; 
  int len, inf;//WJP FOR SUB_MB_TYPE 
  int i; 
 
  //read macroblock type 
  read_mb_type(); 
  
  //read intra prediction mode currStream->frame_bitoffset 
  if (IS_INTRA(pgcurrMB)) 
  { 
    for (b8=0;b8<4;b8++)  //b8 
    { 
      read_luma_ipred_modes(b8); 
    } 
    read_chroma_ipred_modes(); 
  }  
   
  if (IS_COPY (pgcurrMB)) //keep last macroblock 
  { 
    FindSkipMVandRef(pgcurrMB); 
  } 
   
 
   
  if (IS_INTERMV (pgcurrMB))  
  { 
    readReferenceIndex();  
    //WJP FOR SUB_MB_TYPE 
    //====== READ 8x8 SUB-PARTITION MODES (modes of 8x8 blocks) and Intra VBST block modes ====== 
    if (IS_P8x8 (pgcurrMB)) 
    { 
 
      for (i=0; i<4; i++) 
      { 
        len =  GetVLCSymbol (&inf); 
        mapping_ue(len,inf,&pgcurrMB->sub_mb_type[i]);	  
#if TRACE 
        tracebits("Sub mb type", len, inf, pgcurrMB->sub_mb_type[i]); 
#endif 
      } 
    } 
    //WJP END 
    //read motion information 
    readMotionVector (); 
  }	 
   
  // read CBP if not new intra mode 
  if (!IS_COPY (pgcurrMB)) 
  {	 
    read_CBP_dquant(pgcurrMB); 
  } 
   
  // read CBP and Coeffs  *************************************************************** 
  read_luma_chroma_coeffs(); 
 
 
  CheckMbOverHeadValid(pgcurrMB);  /* MB parameter check*/ 
   
#if TRACE 
   trace_mboverhead(pgcurrMB); 
#endif 
     
    return DECODE_MB; 
} 
/*!  
 ************************************************************************************* 
 * \brief  
 *     decode intra prediction mode  
 ************************************************************************************* 
 */ 
const int mpm[9][9] = 
{ 
  {0,	0,	2,	0,	0,	0,	2,	0,	2}, 
  {2,	1,	2,	2,	2,	2,	2,	2,	2}, 
  {2,	2,	2,	2,	2,	2,	2,	2,	2}, 
  {2,	1,	2,	3,	4,	5,	2,	7,	2}, 
  {4,	4,	2,	4,	4,	4,	6,	4,	4}, 
  {5,	5,	2,	5,	5,	5,	6,	5,	5}, 
  {6,	6,	6,	6,	6,	6,	6,	6,	6}, 
  {7,	7,	2,	7,	7,	7,	6,	7,	7}, 
  {0,	1,	2,	3,	4,	5,	6,	7,	8} 
}; 
 
void read_luma_ipred_modes(int b8)    //qwang 2004-3-9 
{ 
  int bi,bj,dec; 
  int b4; 
  SyntaxElement currSE; 
  int mostProbableIntraPredMode; 
  int upIntraPredMode; 
  int leftIntraPredMode; 
  int IntraChromaPredModeFlag; 
  //int MBRowSize = pgImage->width / MB_BLOCK_SIZE; 
   
  pgcurrMB=mb_data+pgImage->current_mb_nr;//current_mb_nr; 
   
  IntraChromaPredModeFlag = IS_INTRA(pgcurrMB); 
   
  currSE.type = SE_INTRAPREDMODE; 
   
#if TRACE 
  strncpy(currSE.tracestring, "Intra4x4_pred_Mode", TRACESTRING_SIZE); 
#endif 
   
  IntraChromaPredModeFlag = 1;  //?  
   
   
  for(b4=0; b4<4; b4++) 
  { 
    //get from stream 
    if(pgcurrMB->I_MODE)//I4x4 
				  read_Intra4x4PredictionMode(&currSE); 
     
     
    //get from array and decode 
    bi = (pgImage->block4_x + ((b8 &1)<<1) + (b4 &1)); 
    bj = (pgImage->block4_y + ((b8>>1)<<1) + (b4>>1)); 
     
    upIntraPredMode            = ((pgImage->ipredmode[bi+1][bj]==10)?-1:pgImage->ipredmode[bi+1][bj]); 
    leftIntraPredMode          = ((pgImage->ipredmode[bi][bj+1]==10)?-1:pgImage->ipredmode[bi][bj+1]); 
     
    mostProbableIntraPredMode  = (upIntraPredMode < 0 || leftIntraPredMode < 0) ? DC_PRED : mpm[leftIntraPredMode][upIntraPredMode]; 
 
     
    dec = (currSE.value1 == -1) ? mostProbableIntraPredMode : currSE.value1 + (currSE.value1 >= mostProbableIntraPredMode); 
 
    pgImage->ipredmode[1+bi][1+bj]=dec; 
 
    /* bistream conformance check -- zhan ma*/ 
    stat_parameter->intra_luma_pred_mode[dec] = 1; 
 
#if TRACE 
    MB_ipredmode_Y[((b8>>1)<<1) + (b4>>1)][((b8 &1)<<1) + (b4 &1)]=dec; 
#endif 
    if(!pgcurrMB->I_MODE) // added by dongjie(check) 
      pgImage->ipredmode[1+bi][1+bj]=mostProbableIntraPredMode; 
#if TRACE 
    MB_ipredmode_Y[((b8>>1)<<1) + (b4>>1)][((b8 &1)<<1) + (b4 &1)]=dec; 
     
#endif 
  } 
 
 
     
   
} 
/*!  
 ************************************************************************************* 
 * \brief  
 *     decode intra chroma prediction mode 
 ************************************************************************************* 
 */ 
void read_chroma_ipred_modes()    //qwang 2004-3-9 
{ 
  SyntaxElement currSE; 
  int IntraChromaPredModeFlag; 
   
  pgcurrMB=mb_data+pgImage->current_mb_nr;//current_mb_nr; 
  IntraChromaPredModeFlag = IS_INTRA(pgcurrMB); 
 
   
		currSE.type = SE_INTRAPREDMODE; 
#if TRACE 
    strncpy(currSE.tracestring, "intra_Chroma_pred_mode", TRACESTRING_SIZE); 
#endif 
     
    currSE.mapping = mapping_ue; 
     
    read_UVLC(&currSE); 
 
    pgcurrMB->c_ipred_mode = currSE.value1; 
 
    /* bistream conformance check -- zhan ma */ 
    stat_parameter->intra_chroma_pred_mode[pgcurrMB->c_ipred_mode] = 1; 
     
    if (currSE.value1 < DC_PRED_8 || currSE.value1 > VERT_PRED_8) 
    { 
      printf("%d\n", pgImage->current_mb_nr); 
      error("illegal chroma intra pred mode!\n", 600); 
    } 
} 
 
 
/*!  
 ************************************************************************************* 
 * \brief  
 *     readReferenceIndex 
 ************************************************************************************* 
 */ 
void readReferenceIndex() 
{ 
  int i,j,k; 
  SyntaxElement currSE; 
  int partmode        = (IS_P8x8(pgcurrMB)?4:pgcurrMB->mb_type); 
  int step_h0         = BLOCK_STEP [partmode][0]; 
  int step_v0         = BLOCK_STEP [partmode][1]; 
   
  int i0, j0, refframe; 
  int flag_mode; 
   
  //  If multiple ref. frames, read reference frame for the MB ********************************* 
  flag_mode = 0; 
   
  currSE.type = SE_REFFRAME; 
  currSE.mapping = mapping_ue; 
   
  // !! shenyanfei  
  for (j0=0; j0<4; j0+=step_v0) 
    for (i0=0; i0<4; i0+=step_h0) 
    { 
      k=2*(j0/2)+(i0/2); 
       
      if (pgcurrMB->mb_type!=SKIP_MB)//WJP FOR ZERO_REF 
      {			 
        if ((pgImage->num_ref_frames == 2)&&(!pgImage->picture_reference_flag)&&(!pgImage->is_ref0_an_IDR))  /* added by zhan ma*/ 
        { 
#if TRACE 
          strncpy(currSE.tracestring,  "Fwd ref frame no ", TRACESTRING_SIZE); 
#endif 
 
          currSE.len = 1; 
           
          read_FLC(&currSE); 
          refframe = currSE.value1; 
 
        } 
        else 
        { 
          refframe = 0; 
        } 
         
        for (j=j0; jblock4_y+j][pgImage->block4_x+i] = refframe; 
      } 
      else 
      { 
        for (j=j0; jblock4_y+j][pgImage->block4_x+i] = 0; 
      } 
    } 
} 
 
/*!  
 ************************************************************************************* 
 * \brief  
 *     readMotionVector 
 ************************************************************************************* 
 */ 
void readMotionVector() 
{ 
  int i,j,k,l,m; 
  int step_h,step_v; 
  int curr_mvd; 
  SyntaxElement currSE; 
  int partmode        = (IS_P8x8(pgcurrMB)?4:pgcurrMB->mb_type); 
  int step_h0         = BLOCK_STEP [partmode][0]; 
  int step_v0         = BLOCK_STEP [partmode][1]; 
   
  int i0, j0, refframe; 
  int pmv[2]; 
  int j4, i4, ii,jj; 
  int vec; 
   
  //=====  READ FORWARD MOTION VECTORS ===== 
  currSE.type = SE_MVD; 
   
  currSE.mapping = mapping_se; 
   
  for (j0=0; j0<4; j0+=step_v0) 
    for (i0=0; i0<4; i0+=step_h0) 
    { 
      k=2*(j0/2)+(i0/2); 
      step_h   = BLOCK_STEP [pgcurrMB->mb_type +pgcurrMB->sub_mb_type[k]][0]; 
      step_v   = BLOCK_STEP [pgcurrMB->mb_type +pgcurrMB->sub_mb_type[k]][1]; 
       
      refframe = refFrArr        [pgImage->block4_y+j0][pgImage->block4_x+i0]; 
       
      for (j=j0; jblock4_y+j; 
          i4 = pgImage->block4_x+i; 
           
          // first make mv-prediction 
          SetMotionVectorPredictor (pmv, pmv+1, refframe, i, j, 4*step_h, 4*step_v, 0);//Lou 1016 
           
          for (k=0; k < 2; k++)  
          { 
#if TRACE 
            snprintf(currSE.tracestring, TRACESTRING_SIZE, "FMVD (pred %d)",pmv[k]); 
#endif 
            currSE.value2 =  k ; // identifies the component; only used for context determination 
            read_UVLC(&currSE); 
              
             
            if ( pgImage->half_pixel_mv_flag == 0 )  // 1/4 accuracy 
            { 
              curr_mvd = currSE.value1;  
            } 
            else 
            { 
              curr_mvd = (currSE.value1 << 1);  
            } 
             
             
            vec=(curr_mvd)+pmv[k];           /* find motion vector */ 
             
            for(ii=0;iimv[i4+ii+BLOCK_SIZE][j4+jj][k]=vec; 
                 
                /* bistream conformance check */ 
                if (stat_parameter->min_mv[k] >= pgImage->mv[i4+ii+BLOCK_SIZE][j4+jj][k]) 
                  stat_parameter->min_mv[k] = pgImage->mv[i4+ii+BLOCK_SIZE][j4+jj][k]; 
 
                if (stat_parameter->max_mv[k] <= pgImage->mv[i4+ii+BLOCK_SIZE][j4+jj][k]) 
                  stat_parameter->max_mv[k] = pgImage->mv[i4+ii+BLOCK_SIZE][j4+jj][k]; 
              } 
               
              /* store (oversampled) mvd */ 
              for (l=0; l < step_v; l++)  
                for (m=0; m < step_h; m++)   
                  pgcurrMB->mvd[j+l][i+m][k] =  curr_mvd; 
             
      
             
 
          } 
        } 
    }		 
} 
 
/*!  
 ************************************************************************************* 
 * \brief  
 *     Get coded block pattern and coefficients (run/level) from the NAL 
 ************************************************************************************* 
 */ 
void read_luma_chroma_coeffs() 
{ 
  int mb_nr = pgImage->current_mb_nr; //GBimg->current_mb_nr; 
  int b8, b4; 
    
  // luma coefficients 
  for(b8=0; b8<4; b8++) 
  { 
    if (pgcurrMB->cbp&(1<cbp_4x4[b8]&(1<cbp>>4)&1) 
  { 
    for(b4=0; b4<4; b4++) 
    { 
      if (pgcurrMB->cbp_4x4[4]&(1<cbp>>4)&2) 
  { 
    // dongjie read cbp_4x4 from bitstream 
    //pgcurrMB->cbp_4x4 = u_v(4, "cbp_4x4");//WJP FOR CBP4X4 
    // end 
    for(b4=0; b4<4; b4++) 
    { 
      if (pgcurrMB->cbp_4x4[5]&(1<type == I_IMG)  
   { 
     pgcurrMB->mb_type = I4MB; 
     pgcurrMB->I_MODE = u_v(1,"Intra Mb mode");//WJP FOR I_DIRECT 
   }  
   else  
   { 
     //skip run coding 
     if(pgImage->skip_mode_flag) 
     { 
        
       if(pgImage->cod_counter == -1)  // 
       {			  
         len =  GetVLCSymbol (&inf); 
         mapping_ue(len,inf,&pgImage->cod_counter);	  
#if TRACE 
         tracebits("mb_skip_run", len, inf, pgImage->cod_counter); 
#endif 
       } 
        
       if (pgImage->cod_counter == 0) 
       { 
         len =  GetVLCSymbol (&inf); 
         mapping_ue(len,inf,&pgcurrMB->mb_type); 
          
#if TRACE 
       tracebits("MB Type", len, inf, pgcurrMB->mb_type); 
#endif 
         pgcurrMB->mb_type++; 
         pgImage->cod_counter--; 
          
       }  
       else 
       { 
         pgImage->cod_counter--; 
         pgcurrMB->mb_type = 0;  // !! skip mode shenyanfei  
       } 
     } 
     else 
     { 
       len =  GetVLCSymbol (&inf); 
       mapping_ue(len,inf,&pgcurrMB->mb_type); 
        
#if TRACE 
       tracebits("mb_type", len, inf, pgcurrMB->mb_type); 
#endif 
     } 
      
     //====== READ 8x8 SUB-PARTITION MODES (modes of 8x8 blocks) and Intra VBST block modes ====== 
     if (IS_P8x8 (pgcurrMB)) 
     { 
       pgcurrMB->mb_type=P8x8; 
     } 
 
     else if(pgcurrMB->mb_type>=I4MB) /* I4MB = 5 */ 
     { 
       pgcurrMB->cbp=NCBP[pgcurrMB->mb_type-5][0]; 
       pgcurrMB->mb_type = I4MB; 
     }  //JX 05-4-1 
   } 
 
  /* bistream conformance check -- zhan ma */ 
  stat_parameter->mb_type[pgcurrMB->mb_type] = 1; 
} 
 
/*!  
 ************************************************************************************* 
 * \brief  
 *     read_CBP_dquant 
 ************************************************************************************* 
 */ 
void read_CBP_dquant() 
{ 
  int len; 
  int inf; 
  int i; 
		 
  if(pgImage->type==I_IMG) // qhg 
  { 
    len =  GetVLCSymbol (&inf); 
    read_cbp_intra(len,inf,&pgcurrMB->cbp);	  
#if TRACE 
    tracebits("Coded_Block_Pattern", len, inf, pgcurrMB->cbp); 
#endif 
  } 
  else if(IS_INTER(pgcurrMB)) // qhg 
  { 
    len =  GetVLCSymbol (&inf); 
    read_cbp_inter(len,inf,&pgcurrMB->cbp);	  
#if TRACE 
    tracebits("Coded_Block_Pattern", len, inf, pgcurrMB->cbp); 
#endif 
  } 
   
  //WJP FOR CBP4X4 
  for(i=0;i<6;i++) 
  { 
    if(pgcurrMB->cbp & (1<cbp_4x4[i] = u_v(4, "cbp_4x4"); 
  } 
  //WJP END 
   
  // Delta quant only if nonzero coeffs 
  if ((!fixed_slice_qp_flag) && pgcurrMB->cbp !=0) 
  { 
    len =  GetVLCSymbol (&inf); 
    mapping_se(len,inf,&pgcurrMB->delta_quant);	  
 
#if TRACE 
    tracebits("Delta quant", len, inf, pgcurrMB->delta_quant); 
#endif 
    pgcurrMB->qp= (previous_qp-MIN_QP+pgcurrMB->delta_quant+(MAX_QP-MIN_QP+1))% (MAX_QP-MIN_QP+1)+MIN_QP; // zhan ma 0714 
  } 
  else 
    pgcurrMB->delta_quant = 0; 
 
} 
 
/*!  
 ************************************************************************************* 
 * \brief :   
 *    macorblock decoding process including  
 ************************************************************************************* 
 */					  
int decode_one_macroblock()     
{  
  int bx,by; 
  int tmp_block[4][4]; 
  int i=0,j=0,ii=0,jj=0,i1=0,j1=0,j4=0,i4=0; 
  int js0=0,js1=0,js2=0,js3=0,jf=0; 
  int uv; 
  int vec1_x=0,vec1_y=0,vec2_x=0,vec2_y=0; 
  int k; 
  int ioff,joff; 
  int tmp; 
  int b8, b4;   // needed for ABT 
  int ii0,jj0,ii1,jj1,if1,jf1,if0,jf0; 
  int mv_mul,f1,f2,f3,f4; 
  int chroma_offset =0; 
 
 
  const byte decode_block_scan[16] = {0,1,4,5,2,3,6,7,8,9,12,13,10,11,14,15};  /* block relative coordinate mapping */ 
   
  int refframe; // = pgcurrMB->ref_frame; 
  //int fw_ref_idx; 
  int*** mv_array; 
  //int  b8_s=0,b8_e=4,incr_y=1,off_y=0,even_y=4,add_y=0; 
   
  int mb_nr             = pgImage->current_mb_nr; 
  int mb_width          = pgImage->width/MB_BLOCK_SIZE; 
  int mb_available_up   = (pgImage->mb_y == 0) ? 0 : (mb_data[mb_nr].slice_nr == mb_data[mb_nr-mb_width].slice_nr); 
  int mb_available_left = (pgImage->mb_x == 0) ? 0 : (mb_data[mb_nr].slice_nr == mb_data[mb_nr-1].slice_nr); 
   
#ifdef _ISOLATED_REGION_ 
  if (iREGenable) 
  { 
    if (pgImage->type == P_IMG) 
    { 
      if (mb_available_up != 0) 
      { 
        if (iREGmap[pgImage->mb_y - 1][pgImage->mb_x] != 2) 
          mb_available_up = 0;        
      } 
       
      if (mb_available_left != 0) 
      { 
        if (iREGmap[pgImage->mb_y][pgImage->mb_x - 1] != 2) 
          mb_available_left = 0; 
      } 
    } 
  } 
#endif // _ISOLATED_REGION_ 
   
  mv_mul=4; 
  f1=8; 
  f2=7; 
   
  f3=f1*f1; 
  f4=f3/2; 
   
  //f4=f4; 
  // luma decoding ************************************************** 
  for (b8=0; b8> 2) & 3); 
		   
		  ioff=i*4; 
		  i4=pgImage->block4_x+i; 
		   
		  joff=j*4; 
		  j4=pgImage->block4_y+j;   /* locate the 4x4 block position of a macroblock */ 
		   
      /*Get Predictive Sample*/ 
		  if (pgcurrMB->mb_type != I4MB) 
		  {//===== FORWARD PREDICTION ===== 
			  refframe = refFrArr[j4][i4]; 
			  //fw_ref_idx = refframe; 
			  mv_array = pgImage->mv; 
			   
			  vec1_x = i4*4*mv_mul + mv_array[i4+BLOCK_SIZE][j4][0];     /* obtain absolute MV coordinate */ 
			  vec1_y = j4*4*mv_mul + mv_array[i4+BLOCK_SIZE][j4][1]; 
 
	     //fprintf(p_trace,"@INTER_MV (x,y) (%d,%d)\n" , vec1_x,vec1_y); MAZHAN 
			//--- INTER PREDICTION --- 
			//Get the block from reference frame with MVP 
				get_block(vec1_x, vec1_y, tmp_block,reference_frame[refframe][0]); 
			   
			  for(ii=0;iipred_sample[b8][b4][ii][jj] = tmp_block[ii][jj]; //vld 
				  } 
		  } 
		  else 
		  {			 
			  //--- INTRA PREDICTION --- 
			  tmp = intrapred(b8, b4, ioff, joff, i4, j4); 
			   
			  if ( tmp == SEARCH_SYNC)  /* make 4x4 prediction block mpr from given prediction pgImage->mb_mode */ 
				  return SEARCH_SYNC;       
		  } 
		   
		  Get_residual(b8,b4); 
      /* inverse transform */ 
			Dequant_B4(pgcurrMB->qp, b8, b4);  //zhangnan 
			Inv_Transform_B4 (b8,b4); 
			Recon_B4(b8, b4); 
	  } //!< end of b4-loop 
  } 
 
   
  // chroma decoding ******************************************************* 
    if(IS_INTRA(pgcurrMB)) 
    { 
      for (b4=0;b4<4;b4++) 
      { 
        intrapred_chroma_4x4(pgImage->mb_x,pgImage->mb_y,b4,pgcurrMB->c_ipred_mode); 
        bx = (b4 &1)<<2; 
        by = (b4>>1)<<2; 
        for (uv=0; uv<2;uv++) 
        { 
          Get_residual(4+uv,b4); 
          /* inverse transform */ 
          Dequant_B4(pgcurrMB->qp, 4+uv, b4); 
          Inv_Transform_B4 (4+uv,b4); 
          Recon_B4(4+uv, b4); 
        } 
      } 
 
    } 
    else 
    { //--- FORWARD PREDICTION --- 
        for(uv =0;uv<2;uv++) 
        { 
            for (j=4;j<6;j++) 
            { 
                joff = (j-4)*4; 
                j4 = pgImage->pix_c_y + joff; 
                for (i=0;i<2;i++) 
                { 
                    ioff = i*4; 
                    i4 = pgImage->pix_c_x + ioff; 
                    mv_array = pgImage->mv; 
                    for(jj=0;jj<4;jj++) 
                    { 
                        jf=(j4+jj)/2; 
                        for(ii=0;ii<4;ii++) 
                        { 
                            if1=(i4+ii)/2; 
                            refframe = refFrArr[jf][if1]; 
                           // fw_ref_idx = refFrArr[jf][if1]; 
                            chroma_offset = 0; 
                            i1=(pgImage->pix_c_x+ii+ioff)*f1+mv_array[if1+4][jf][0]; 
                            j1=(pgImage->pix_c_y+jj+joff)*f1+mv_array[if1+4][jf][1]; 
                            j1 += chroma_offset; 
                            ii0=max (0, min (i1/f1, pgImage->width_cr-1)); 
                            jj0=max (0, min (j1/f1, pgImage->height_cr-1)); 
                            ii1=max (0, min ((i1+f2)/f1, pgImage->width_cr-1)); 
                            jj1=max (0, min ((j1+f2)/f1, pgImage->height_cr-1));				 
                            if1=(i1 & f2); 
                            jf1=(j1 & f2); 
                            if0=f1-if1; 
                            jf0=f1-jf1; 
                            pgcurrMB->pred_sample[4+uv][(j-4)*2+i][ii][jj]= 
                                (if0*jf0*reference_frame[refframe][uv+1][jj0][ii0] 
                                +if1*jf0*reference_frame[refframe][uv+1][jj0][ii1] 
                                +if0*jf1*reference_frame[refframe][uv+1][jj1][ii0] 
                                +if1*jf1*reference_frame[refframe][uv+1][jj1][ii1]+f4)/f3; 
                        } //end for ii 
                    }// end for jj 
                } // end for i 
            }// end for j 
            for(b4=0; b4<4; b4++) 
            { 
                Get_residual(4+uv,b4); 
                /* inverse transform */ 
                Dequant_B4(pgcurrMB->qp, 4+uv, b4); 
                Inv_Transform_B4 (4+uv,b4); 
                Recon_B4(4+uv, b4); 
            } 
 
        }// end for uv 
    } // end for   if(IS_INTRA(pgcurrMB)) 
   
    
#if TRACE 
  trace_mb_data(pgcurrMB); 
#endif 
 
  return 0; 
}