www.pudn.com > AvsVideoCodec.rar > macroblock.c


     /* 
***************************************************************************** 
* COPYRIGHT AND WARRANTY INFORMATION 
* 
* Copyright 2003, Advanced Audio Video Coding Standard, Part II 
* 
* DISCLAIMER OF WARRANTY 
* 
* The contents of this file are subject to the Mozilla Public License 
* Version 1.1 (the "License"); you may not use this file except in 
* compliance with the License. You may obtain a copy of the License at 
* http://www.mozilla.org/MPL/ 
* 
* Software distributed under the License is distributed on an "AS IS" 
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the 
* License for the specific language governing rights and limitations under 
* the License. 
*                      
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY. 
* The AVS Working Group doesn't represent or warrant that the programs 
* furnished here under 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 for standardization procedure is available at  
* AVS Web site http://www.avs.org.cn. Patent Licensing is outside 
* of AVS Working Group. 
* 
* The Original Code is Reference Software for China National Standard  
* GB/T 20090.2-2006 (short for AVS-P2 or AVS Video) at version RM52J. 
* 
* The Initial Developer of the Original Code is Video subgroup of AVS 
* Workinggroup (Audio and Video coding Standard Working Group of China). 
* Contributors:   Guoping Li,    Siwei Ma,    Jian Lou,    Qiang Wang ,  
*   Jianwen Chen,Haiwu Zhao,  Xiaozhen Zheng, Junhao Zheng, Zhiming Wang 
*  
****************************************************************************** 
*/ 
 
 
 
/* 
************************************************************************************* 
* File name: macroblock.c 
* Function: Decode a Macroblock 
* 
************************************************************************************* 
*/ 
 
 
 
#include "contributors.h" 
 
#include  
#include  
#include  
#include  
 
#include "global.h" 
#include "mbuffer.h" 
#include "elements.h" 
#include "macroblock.h" 
#include "vlc.h" 
 
#include "defines.h" 
#include "block.h" 
 
void readReferenceIndex(struct img_par *img, struct inp_par *inp); 
void readMotionVector(struct img_par *img, struct inp_par *inp); 
 
#define MODE_IS_P8x8  (mbmode==4) 
#define MODE_IS_I4x4  (mbmode==5)                  //xfwang modify          2004.7.29 
#define I16OFFSET     (mbmode-7) 
#define fwd_ref_idx_to_refframe(idx) ((idx)+fwd_refframe_offset) 
#define bwd_ref_idx_to_refframe(idx) ((idx)+bwd_refframe_offset) 
 
 
 
/* 
****************************************************************************** 
*  Function: calculated field or frame distance between current field(frame) 
*            and the reference field(frame). 
*     Input: blkref  
			 fw_bw   
*    Output: distance for motion vector scale 
*    Return:  
* Attention: 
*    Author: Yulejun // 2004.07.14 
****************************************************************************** 
*/ 
// The funtion int calculate_distance(int blkref, int fw_bw ) is modified by Xiaozhen Zheng, HiSilicon, 20070327.  
// At the modified version, 'img->tr' is replaced by 'picture_distance', which is used to calculate DistanceIndex and BlockDistance. 
int calculate_distance(int blkref, int fw_bw )  //fw_bw>=0: forward ; fw_bw<0: backward 
{ 
  int distance; 
  if( img->picture_structure == 1 ) //frame coding 
  { 
    if ( img->type==P_IMG ) // P img 
    { 
        if(blkref==0) 
              distance = picture_distance*2 - img->imgtr_last_P*2; 
        else if(blkref==1) 
              distance = picture_distance*2 - img->imgtr_last_prev_P*2; 
		else 
		{ 
			  assert(0); //only two reference pictures for P frame 
		} 
    } 
    else //B_IMG 
    { 
		if (fw_bw >=0 ) //forward 
			  distance = picture_distance*2 - img->imgtr_last_P*2; 
		else 
			  distance = img->imgtr_next_P*2  - picture_distance*2; 
    } 
  }   
  else if( ! img->picture_structure )  //field coding 
  { 
    if(img->type==P_IMG) 
    { 
      if(img->top_bot==0) //top field 
			{ 
				switch ( blkref ) 
				{ 
				case 0: 
					distance = picture_distance*2 - img->imgtr_last_P*2 - 1 ; 
					break; 
				case 1: 
					distance = picture_distance*2 - img->imgtr_last_P*2 ; 
					break; 
				case 2: 
					distance = picture_distance*2 - img->imgtr_last_prev_P*2 - 1; 
					break; 
				case 3: 
					distance = picture_distance*2 - img->imgtr_last_prev_P*2 ; 
					break; 
				} 
			} 
        else if(img->top_bot==1) // bottom field. 
			{ 
				switch ( blkref ) 
				 { 
				case 0: 
					distance = 1 ; 
					break; 
				case 1: 
					distance = picture_distance*2 - img->imgtr_last_P*2 ; 
					break; 
				case 2: 
					distance = picture_distance*2 - img->imgtr_last_P*2 + 1; 
					break; 
				case 3: 
					distance = picture_distance*2 - img->imgtr_last_prev_P*2 ; 
						break; 
				  } 
			} 
		 else  
			{ 
				printf("Error. frame picture should not run into this branch."); 
				exit(-1); 
			} 
    } 
    else if(img->type==B_IMG) 
    { 
			assert(blkref==0 || blkref == 1); 
			if (fw_bw >= 0 ) //forward 
			{ 
				if(img->top_bot==0) //top field 
				{ 
					switch ( blkref ) 
					{ 
					case 0: 
						distance = picture_distance*2 - img->imgtr_last_P*2 - 1 ; 
						break; 
					case 1: 
						distance = picture_distance*2 - img->imgtr_last_P*2; 
						break; 
					} 
				} 
				else if(img->top_bot==1) // bottom field. 
				{ 
				        switch ( blkref ) 
					{ 
					case 0: 
						distance = picture_distance*2 - img->imgtr_last_P*2 ; 
						break; 
					case 1: 
						distance = picture_distance*2 - img->imgtr_last_P*2 + 1; 
						break; 
					} 
				} 
				else  
				{ 
					printf("Error. frame picture should not run into this branch."); 
					exit(-1); 
				} 
			} 
			else // backward 
			{ 
				if(img->top_bot==0) //top field 
				{ 
					switch ( blkref ) 
					{ 
						case 0: 
							distance = img->imgtr_next_P*2 - picture_distance*2; 
							break; 
						case 1: 
							distance = img->imgtr_next_P*2 - picture_distance*2 + 1; 
							break; 
					} 
				} 
				else if(img->top_bot==1) // bottom field. 
				{ 
					switch ( blkref ) 
					{ 
					case 0: 
						distance = img->imgtr_next_P*2 - picture_distance*2 -  1; 
						break; 
					case 1: 
						distance = img->imgtr_next_P*2 - picture_distance*2 ; 
						break; 
					} 
				} 
				else  
				{ 
					printf("Error. frame picture should not run into this branch."); 
					exit(-1); 
				} 
			} 
 
    } 
  } 
  distance = (distance+512)%512;	// Added by Xiaozhen ZHENG, 20070413, HiSilicon 
  return distance; 
} 
 
/*Lou 1016 Start*/ 
//The unit of time distance is calculated by field time 
/* 
************************************************************************* 
* Function: 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
int scale_motion_vector(int motion_vector, int currblkref, int neighbourblkref, int currsmbtype, int neighboursmbtype, int block_y_pos, int curr_block_y, int ref, int direct_mv) 
{ 
    int sign = (motion_vector>0?1:-1); 
    int mult_distance; 
    int devide_distance; 
 
    motion_vector = abs(motion_vector); 
 
    if(motion_vector == 0) 
        return 0; 
 
 
    mult_distance = calculate_distance( currblkref, ref ); 
    devide_distance = calculate_distance(neighbourblkref, ref); 
 
    motion_vector = sign*((motion_vector*mult_distance*(512/devide_distance)+256)>>9); 
 
    return motion_vector; 
} 
/*Lou 1016 End*/ 
 
/* 
************************************************************************* 
* Function:Set motion vector predictor 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
static void SetMotionVectorPredictor (struct img_par  *img, 
                                      int             *pmv_x, 
                                      int             *pmv_y, 
                                      int             ref_frame, 
                                      int             **refFrArr, 
                                      int             ***tmp_mv, 
                                      int             block_x, 
                                      int             block_y, 
                                      int             blockshape_x, 
                                      int             blockshape_y, 
				      int             ref, 
                                      int             direct_mv)//Lou 1016 
{ 
  int mb_x                 = 8*block_x; 
  int mb_y                 = 8*block_y; 
  int pic_block_x          = img->block_x + block_x; 
  int pic_block_y          = img->block_y + block_y; 
  int mb_width             = img->width/16; 
  int mb_nr = img->current_mb_nr; 
  int mb_available_up   = (img->mb_y == 0 ) ? 0 : (mb_data[mb_nr].slice_nr == mb_data[mb_nr-mb_width  ].slice_nr);  // jlzheng 6.23  
  int mb_available_left = (img->mb_x == 0 ) ? 0 : (mb_data[mb_nr].slice_nr == mb_data[mb_nr-1         ].slice_nr);  // jlzheng 6.23 
  int mb_available_upleft  = (img->mb_x == 0) ? 0 : ((img->mb_y == 0) ? 0 :  
  (mb_data[mb_nr].slice_nr == mb_data[mb_nr-mb_width-1].slice_nr)); 
  int mb_available_upright = (img->mb_y == 0) ? 0 : ((img->mb_x >= (mb_width-1)) ? 0 : 
  (mb_data[mb_nr].slice_nr == mb_data[mb_nr-mb_width+1].slice_nr)); 
   
  int block_available_up, block_available_left, block_available_upright, block_available_upleft; 
  int mv_a, mv_b, mv_c, mv_d, pred_vec=0; 
  int mvPredType, rFrameL, rFrameU, rFrameUR; 
  int hv; 
  int mva[3] , mvb[3],mvc[3]; 
	int y_up = 1,y_upright=1,y_upleft=1,off_y=0;	 
    /*Lou 1016 Start*/ 
  int rFrameUL; 
  Macroblock*     currMB = &mb_data[img->current_mb_nr]; 
  int smbtypecurr, smbtypeL, smbtypeU, smbtypeUL, smbtypeUR; 
  
 
    smbtypecurr = -2; 
    smbtypeL = -2; 
    smbtypeU = -2; 
    smbtypeUL = -2; 
    smbtypeUR = -2; 
  /*Lou 1016 End*/ 
 
  /* 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 : mb_available_up); 
  } 
  else if (mb_y > 0) 
  { 
    block_available_upleft = mb_available_left; 
  } 
  else 
  { 
    block_available_upleft = mb_available_upleft; 
  } 
 
    smbtypecurr = -2; 
    smbtypeL = -2; 
    smbtypeU = -2; 
    smbtypeUL = -2; 
    smbtypeUR = -2; 
 
    mvPredType = MVPRED_MEDIAN; 
 
    rFrameL    = block_available_left    ? refFrArr[pic_block_y]  [pic_block_x-1] : -1; 
    rFrameU    = block_available_up      ? refFrArr[pic_block_y-1][pic_block_x]   : -1; 
    rFrameUR   = block_available_upright ? refFrArr[pic_block_y-1][pic_block_x+blockshape_x/8] : 
    block_available_upleft  ? refFrArr[pic_block_y-1][pic_block_x-1] : -1; 
    rFrameUL   = block_available_upleft  ? refFrArr[pic_block_y-1][pic_block_x-1] : -1; 
 
  if((rFrameL != -1)&&(rFrameU == -1)&&(rFrameUR == -1)) 
    mvPredType = MVPRED_L; 
  else if((rFrameL == -1)&&(rFrameU != -1)&&(rFrameUR == -1)) 
    mvPredType = MVPRED_U; 
  else if((rFrameL == -1)&&(rFrameU == -1)&&(rFrameUR != -1)) 
    mvPredType = MVPRED_UR; 
  /*Lou 1016 End*/    
  // 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 MEDIAN(a,b,c)  (a + b + c - min(a, min(b, c)) - max(a, max(b, c))); 
 
  for (hv=0; hv < 2; hv++) 
  { 
    mva[hv] = mv_a = block_available_left    ? tmp_mv[4+pic_block_x-1             ][pic_block_y][hv] : 0; 
    mvb[hv] = mv_b = block_available_up      ? tmp_mv[4+pic_block_x               ][pic_block_y-1][hv] : 0; 
    mv_d = block_available_upleft  ? tmp_mv[4+pic_block_x-1][pic_block_y-1][hv] : 0; 
    mvc[hv] = mv_c = block_available_upright ? tmp_mv[4+pic_block_x+blockshape_x/8][pic_block_y-1][hv] : mv_d; 
    //--- Yulj 2004.07.14 
    // mv_a, mv_b... are not scaled. 
    mva[hv] = scale_motion_vector(mva[hv], ref_frame, rFrameL, smbtypecurr, smbtypeL, pic_block_y-off_y, pic_block_y, ref, direct_mv); 
    mvb[hv] = scale_motion_vector(mvb[hv], ref_frame, rFrameU, smbtypecurr, smbtypeU, pic_block_y-y_up, pic_block_y, ref, direct_mv); 
    mv_d = scale_motion_vector(mv_d, ref_frame, rFrameUL, smbtypecurr, smbtypeUL, pic_block_y-y_upleft, pic_block_y, ref, direct_mv); 
    mvc[hv] = block_available_upright ? scale_motion_vector(mvc[hv], ref_frame, rFrameUR, smbtypecurr, smbtypeUR, pic_block_y-y_upright, pic_block_y, ref, direct_mv): mv_d; 
    
     
    switch (mvPredType) 
    { 
    case MVPRED_MEDIAN: 
 
      if(hv == 1){ 
          //  jlzheng 7.2 
          // !! for A  
 
          mva[2] = abs(mva[0] - mvb[0])	+ abs(mva[1] - mvb[1]); 
          // !! for B 
 
	  mvb[2] = abs(mvb[0] - mvc[0]) + abs(mvb[1] - mvc[1]); 
          // !! for C 
 
          mvc[2] = abs(mvc[0] - mva[0])	+ abs(mvc[1] - mva[1]); 
           
          pred_vec = MEDIAN(mva[2],mvb[2],mvc[2]); 
           
          if(pred_vec == mva[2]){ 
            *pmv_x = mvc[0]; 
            *pmv_y = mvc[1]; 
          } 
          else if(pred_vec == mvb[2]){ 
            *pmv_x = mva[0]; 
            *pmv_y = mva[1]; 
          } 
          else{ 
            *pmv_x = mvb[0]; 
            *pmv_y = mvb[1]; 
          }   //  END 
           
 
      } 
      break; 
    case MVPRED_L: 
      pred_vec = mv_a; 
      break; 
    case MVPRED_U: 
      pred_vec = mv_b; 
      break; 
    case MVPRED_UR: 
      pred_vec = mv_c; 
      break; 
    default: 
      break; 
    } 
     
     
    if(mvPredType != MVPRED_MEDIAN){ 
      if (hv==0) 
        *pmv_x = pred_vec; 
      else 
        *pmv_y = pred_vec; 
    } 
  } 
 
#undef MEDIAN 
} 
 
/* 
************************************************************************* 
* Function: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. 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void CheckAvailabilityOfNeighbors(struct img_par *img) 
{ 
  int i,j; 
  const int mb_width = img->width/MB_BLOCK_SIZE; 
  const int mb_nr = img->current_mb_nr; 
  Macroblock *currMB = &mb_data[mb_nr]; 
  int check_value; 
   
  // mark all neighbors as unavailable 
  for (i=0; i<3; i++) 
    for (j=0; j<3; j++) 
      mb_data[mb_nr].mb_available[i][j]=NULL; 
 
  mb_data[mb_nr].mb_available[1][1]=currMB; // current MB 
     
  // Check MB to the left 
  if(img->pix_x >= MB_BLOCK_SIZE) 
  { 
    int remove_prediction = currMB->slice_nr != mb_data[mb_nr-1].slice_nr; 
    // upper blocks 
    if (remove_prediction) 
    { 
      img->ipredmode[img->block_x][img->block_y+1] = -1; 
      img->ipredmode[img->block_x][img->block_y+2] = -1; 
    } 
    if (!remove_prediction) 
    { 
      currMB->mb_available[1][0]=&(mb_data[mb_nr-1]); 
    } 
  } 
   
  // Check MB above 
  check_value =  (img->pix_y >= MB_BLOCK_SIZE); 
  if(check_value)  
  { 
    int remove_prediction = currMB->slice_nr != mb_data[mb_nr-mb_width].slice_nr; 
    // upper blocks 
    if (remove_prediction) 
    { 
      img->ipredmode[img->block_x+1][img->block_y] = -1; 
      img->ipredmode[img->block_x+2][img->block_y] = -1; 
    } 
     
    if (!remove_prediction) 
    { 
      currMB->mb_available[0][1]=&(mb_data[mb_nr-mb_width]); 
    } 
  } 
   
  // Check MB left above 
  if(img->pix_y >= MB_BLOCK_SIZE && img->pix_x >= MB_BLOCK_SIZE) 
  { 
    int remove_prediction = currMB->slice_nr != mb_data[mb_nr-mb_width-1].slice_nr; 
     
    if (remove_prediction) 
    { 
      img->ipredmode[img->block_x][img->block_y] = -1; 
    } 
    if (!remove_prediction) 
    { 
      currMB->mb_available[0][0]=&(mb_data[mb_nr-mb_width-1]); 
    } 
  } 
   
  // Check MB right above 
  if(img->pix_y >= MB_BLOCK_SIZE && img->pix_x < (img->width-MB_BLOCK_SIZE )) 
  { 
    if(currMB->slice_nr == mb_data[mb_nr-mb_width+1].slice_nr) 
      currMB->mb_available[0][2]=&(mb_data[mb_nr-mb_width+1]); 
  } 
 
} 
 
void set_MB_parameters (struct img_par *img,struct inp_par *inp, int mb) 
{ 
  const int number_mb_per_row = img->width / MB_BLOCK_SIZE ; 
  const int mb_nr = img->current_mb_nr; 
  Macroblock *currMB = &mb_data[mb_nr]; 
 
  img->mb_x = mb % number_mb_per_row; 
  img->mb_y = mb / number_mb_per_row; 
 
  // Define vertical positions 
  img->block8_y= img->mb_y * BLOCK_SIZE/2; 
  img->block_y = img->mb_y * BLOCK_SIZE/2;      // vertical luma block position 
  img->pix_y   = img->mb_y * MB_BLOCK_SIZE;   // vertical luma macroblock position 
  img->pix_c_y = img->mb_y * MB_BLOCK_SIZE/2; // vertical chroma macroblock position 
 
  // Define horizontal positions 
  img->block8_x= img->mb_x * BLOCK_SIZE/2; 
  img->block_x = img->mb_x * BLOCK_SIZE/2;        // luma block 
  img->pix_x   = img->mb_x * MB_BLOCK_SIZE;     // luma pixel 
  img->pix_c_x   = img->mb_x * MB_BLOCK_SIZE/2; // chroma pixel 
 
} 
 
/* 
************************************************************************* 
* Function:initializes the current macroblock 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
 
void start_macroblock(struct img_par *img,struct inp_par *inp) 
{ 
  int i,j,k,l; 
  Macroblock *currMB;   // intialization code deleted, see below, StW 
   
  assert (img->current_mb_nr >=0 && img->current_mb_nr < img->max_mb_nr); 
   
  currMB = &mb_data[img->current_mb_nr];//GB 
   
  /* Update coordinates of the current macroblock */ 
  img->mb_x = (img->current_mb_nr)%(img->width/MB_BLOCK_SIZE); 
  img->mb_y = (img->current_mb_nr)/(img->width/MB_BLOCK_SIZE); 
   
  /* Define vertical positions */ 
  img->block_y = img->mb_y * BLOCK_SIZE/2;      /* luma block position */ 
  img->block8_y = img->mb_y * BLOCK_SIZE/2;    
  img->pix_y   = img->mb_y * MB_BLOCK_SIZE;   /* luma macroblock position */ 
  img->pix_c_y = img->mb_y * MB_BLOCK_SIZE/2; /* chroma macroblock position */ 
   
  /* Define horizontal positions */ 
  img->block_x = img->mb_x * BLOCK_SIZE/2;      /* luma block position */ 
  img->block8_x = img->mb_x * BLOCK_SIZE/2;   
  img->pix_x   = img->mb_x * MB_BLOCK_SIZE;   /* luma pixel position */ 
  img->pix_c_x = img->mb_x * MB_BLOCK_SIZE/2; /* chroma pixel position */ 
   
  // If MB is next to a slice boundary, mark neighboring blocks unavailable for prediction 
  CheckAvailabilityOfNeighbors(img);      // support only slice mode 0 in MBINTLC1 at this time 
   
  // Reset syntax element entries in MB struct 
  currMB->qp          = img->qp ; 
  currMB->mb_type     = 0; 
  currMB->delta_quant = 0; 
  currMB->cbp         = 0; 
  currMB->cbp_blk     = 0; 
  currMB->c_ipred_mode= DC_PRED_8; //GB 
   
  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++) 
          currMB->mvd[l][j][i][k] = 0; 
         
  currMB->cbp_bits   = 0; 
         
  // initialize img->m7 for ABT//Lou 
  for (j=0; jm7[i][j] = 0; 
        
  for (j=0; jm8[0][i][j] = 0; 
      img->m8[1][i][j] = 0; 
    } 
   
	 currMB->lf_disable = loop_filter_disable; 
 
	 img->weighting_prediction=0;   //cjw 20051230 default value Weighting Predicition is 0 
} 
 
/* 
************************************************************************* 
* Function:Interpret the mb mode for P-Frames 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void interpret_mb_mode_P(struct img_par *img) 
{ 
  int i; 
  const int ICBPTAB[6] = {0,16,32,15,31,47}; 
  Macroblock *currMB = &mb_data[img->current_mb_nr];//GB current_mb_nr]; 
  int         mbmode = currMB->mb_type; 
 
  if(mbmode <4) 
  { 
    currMB->mb_type = mbmode; 
    for (i=0;i<4;i++) 
    { 
      currMB->b8mode[i]   = mbmode; 
      currMB->b8pdir[i]   = 0; 
    } 
  } 
  else if(MODE_IS_P8x8) 
  { 
    currMB->mb_type = P8x8; 
  } 
  else if(/* MODE_IS_I4x4 qhg */mbmode>=5)//modefy by xfwang 2004.7.29 
  { 
	  currMB->cbp=NCBP[currMB->mb_type-5][0]; // qhg  //modefy by xfwang 2004.7.29 
    currMB->mb_type = I4MB; 
    for (i=0;i<4;i++) 
    { 
      currMB->b8mode[i] = IBLOCK; 
      currMB->b8pdir[i] = -1; 
    } 
  } 
  else 
  { 
    currMB->mb_type = I16MB; 
    for (i=0;i<4;i++) {currMB->b8mode[i]=0; currMB->b8pdir[i]=-1; } 
    currMB->cbp= ICBPTAB[(I16OFFSET)>>2]; 
  } 
} 
 
/* 
************************************************************************* 
* Function:Interpret the mb mode for I-Frames 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void interpret_mb_mode_I(struct img_par *img) 
{ 
  int i; 
  const int ICBPTAB[6] = {0,16,32,15,31,47}; 
  Macroblock *currMB   = &mb_data[img->current_mb_nr]; 
  int         num      =4; 
 
  currMB->mb_type = I4MB; 
 
  for (i=0;i<4;i++) 
  { 
    currMB->b8mode[i]=IBLOCK;  
    currMB->b8pdir[i]=-1;  
  } 
 
  for (i=num;i<4;i++)  
  { 
    currMB->b8mode[i]=currMB->mb_type_2==P8x8? 4 : currMB->mb_type_2; currMB->b8pdir[i]=0;  
  } 
} 
 
/* 
************************************************************************* 
* Function:Interpret the mb mode for B-Frames 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void interpret_mb_mode_B(struct img_par *img) 
{ 
  static const int offset2pdir16x16[12]   = {0, 0, 1, 2, 0,0,0,0,0,0,0,0}; 
  static const int offset2pdir16x8[22][2] = {{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{1,1},{0,0},{0,1},{0,0},{1,0}, 
  {0,0},{0,2},{0,0},{1,2},{0,0},{2,0},{0,0},{2,1},{0,0},{2,2},{0,0}}; 
  static const int offset2pdir8x16[22][2] = {{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{1,1},{0,0},{0,1},{0,0}, 
  {1,0},{0,0},{0,2},{0,0},{1,2},{0,0},{2,0},{0,0},{2,1},{0,0},{2,2}}; 
   
  const int ICBPTAB[6] = {0,16,32,15,31,47}; 
  Macroblock *currMB = &mb_data[img->current_mb_nr];//GB current_mb_nr]; 
   
  int i, mbmode; 
  int mbtype  = currMB->mb_type; 
  int *b8mode = currMB->b8mode; 
  int *b8pdir = currMB->b8pdir; 
   
  //--- set mbtype, b8type, and b8pdir --- 
	if (mbtype==0)       // direct 
	{ 
		mbmode=0;       for(i=0;i<4;i++) {b8mode[i]=0;          b8pdir[i]=2; } 
	} 
	else if (/*mbtype==23 qhg */ mbtype>=23) // intra4x4 
	{ 
		currMB->cbp=NCBP[mbtype-23][0]; // qhg 
		mbmode=I4MB;    for(i=0;i<4;i++) {b8mode[i]=IBLOCK;     b8pdir[i]=-1; } 
	} 
	else if (mbtype==22) // 8x8(+split) 
	{ 
		mbmode=P8x8;       // b8mode and pdir is transmitted in additional codewords 
	} 
	else if (mbtype<4)   // 16x16 
	{ 
		mbmode=1;       
		for(i=0;i<4;i++) {b8mode[i]=1;          b8pdir[i]=offset2pdir16x16[mbtype]; } 
	} 
	else if (mbtype%2==0) // 16x8 
	{ 
	        mbmode=2;        
		for(i=0;i<4;i++) {b8mode[i]=2;          b8pdir[i]=offset2pdir16x8 [mbtype][i/2]; } 
	} 
	else 
	{ 
		mbmode=3;        
	 	for(i=0;i<4;i++) {b8mode[i]=3;          b8pdir[i]=offset2pdir8x16 [mbtype][i%2]; } 
	} 
		 
	 
	currMB->mb_type = mbmode; 
} 
 
/* 
************************************************************************* 
* Function:init macroblock I and P frames 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void init_macroblock(struct img_par *img) 
{ 
  int i,j; 
  Macroblock *currMB = &mb_data[img->current_mb_nr];//GB current_mb_nr]; 
	 
  img->mv[img->block_x+4][img->block_y][2]=img->number; 
	 
  for (i=0;i<2;i++) 
  {                           // reset vectors and pred. modes 
    for(j=0;j<2;j++) 
    { 
        img->mv[img->block_x+i+4][img->block_y+j][0] = 0; 
        img->mv[img->block_x+i+4][img->block_y+j][1] = 0; 
    } 
  } 
 
  for (i=0;i<2;i++) 
  {                           // reset vectors and pred. modes 
    for(j=0;j<2;j++) 
    { 
	img->ipredmode[img->block_x+i+1][img->block_y+j+1] = -1;            //by oliver 0512 
    } 
  } 
 
  // Set the reference frame information for motion vector prediction 
  if (IS_INTRA (currMB)) 
  { 
	for (j=0; j<2; j++) 
		for (i=0; i<2; i++) 
		{ 
			refFrArr[img->block_y+j][img->block_x+i] = -1; 
		} 
  } 
  else if (!IS_P8x8 (currMB)) 
  { 
	for (j=0; j<2; j++) 
		for (i=0; i<2; i++) 
		{ 
			refFrArr[img->block_y+j][img->block_x+i] = 0; 
		} 
  } 
  else 
  { 
	for (j=0; j<2; j++) 
		for (i=0; i<2; i++) 
		{ 
			refFrArr[img->block_y+j][img->block_x+i] = (currMB->b8mode[2*j+i]==IBLOCK ? -1 : 0); 
		} 
  }  
} 
 
/* 
************************************************************************* 
* Function:Sets mode for 8x8 block 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void SetB8Mode (struct img_par* img, Macroblock* currMB, int value, int i) 
{ 
  static const int p_v2b8 [ 5] = {4, 5, 6, 7, IBLOCK}; 
  static const int p_v2pd [ 5] = {0, 0, 0, 0, -1}; 
  static const int b_v2b8 [14] = {0, 4, 4, 4, 5, 6, 5, 6, 5, 6, 7, 7, 7, IBLOCK}; 
  static const int b_v2pd [14] = {2, 0, 1, 2, 0, 0, 1, 1, 2, 2, 0, 1, 2, -1}; 
   
  if (img->type==B_IMG) 
  { 
    currMB->b8mode[i]   = b_v2b8[value]; 
    currMB->b8pdir[i]   = b_v2pd[value]; 
  } 
  else 
  { 
    currMB->b8mode[i]   = p_v2b8[value]; 
    currMB->b8pdir[i]   = p_v2pd[value]; 
  } 
   
} 
 
/* 
************************************************************************* 
* Function:Get the syntax elements from the NAL 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
int read_one_macroblock(struct img_par *img,struct inp_par *inp) 
{ 
  int i,j; 
  	  
  SyntaxElement currSE; 
  Macroblock *currMB = &mb_data[img->current_mb_nr];//GB current_mb_nr]; 
  int  img_block_y; 
  int  real_mb_type; 
   int fixqp;          //add by wuzhongmou 200612 
   fixqp = (fixed_picture_qp|| fixed_slice_qp);  //add by wuzhongmou 200612 
 
  for(i=0;i<8;i++) 
    for(j=0;j<8;j++) 
    { 
      img->m8[0][i][j]=0; 
      img->m8[1][i][j]=0; 
    } 
     
  currMB->qp = img->qp ; 
  currSE.type = SE_MBTYPE; 
  currSE.mapping = linfo_ue; 
   
	currMB->mb_type_2= 0;	 
 
  if(img->type == I_IMG)  
  { 
		currMB->mb_type = 0; 
  }  
  else if(skip_mode_flag) 
  { 
    if(img->cod_counter == -1) 
    { 
 
#if TRACE 
      strncpy(currSE.tracestring, "MB runlength", TRACESTRING_SIZE); 
#endif 
 
      readSyntaxElement_UVLC(&currSE,inp); 
      img->cod_counter = currSE.value1; 
    } 
 
    if (img->cod_counter==0) 
    { 
#if TRACE 
      strncpy(currSE.tracestring, "MB Type", TRACESTRING_SIZE); 
#endif 
 
      readSyntaxElement_UVLC(&currSE,inp); 
 
      if(img->type == P_IMG) 
        currSE.value1++; 
       
      currMB->mb_type = currSE.value1; 
      img->cod_counter--; 
    }  
    else 
    { 
      img->cod_counter--; 
      currMB->mb_type = 0;  // !! skip mode shenyanfei  
    } 
  }  
  else  
  { 
 
#if TRACE 
	strncpy(currSE.tracestring, "MB Type", TRACESTRING_SIZE); 
#endif 
		 
	readSyntaxElement_UVLC(&currSE,inp); 
	 
	if(img->type == P_IMG) 
		currSE.value1++; 
	 
	currSE.value1--; 
	real_mb_type = currSE.value1; 
	if(currSE.value1<0) 
		currSE.value1 = 0; 
	currMB->mb_type = currSE.value1; 
	img->cod_counter--;		 
  } 
   
  if ((img->type==P_IMG ))      // inter frame 
    interpret_mb_mode_P(img); 
  else if (img->type==I_IMG)                                  // intra frame 
    interpret_mb_mode_I(img); 
  else if ((img->type==B_IMG))  // B frame 
    interpret_mb_mode_B(img); 
 
	//====== READ 8x8 SUB-PARTITION MODES (modes of 8x8 blocks) and Intra VBST block modes ====== 
  if (IS_P8x8 (currMB)) 
  { 
    currSE.type    = SE_MBTYPE;     
		 
    if(img->type!=P_IMG) 
    { 
      for (i=0; i<4; i++) 
      { 
        currSE.mapping = linfo_ue; 
         
#if TRACE 
        strncpy(currSE.tracestring, "8x8 mode", TRACESTRING_SIZE); 
#endif 
         
        //mb_part_type is fix length coding(fix length equal 2)!!   jlzheng    7.22 
        assert (currStream->streamBuffer != NULL); 
        currSE.len = 2; 
        readSyntaxElement_FLC (&currSE); 
		//  END 
        SetB8Mode (img, currMB, currSE.value1, i); 
      } 
    } 
    else 
    { 
      currSE.value1 = 0; 
      for (i=0; i<4; i++) 
      { 
        SetB8Mode (img, currMB, currSE.value1, i); 
      } 
    } 
  } 
 
 
    
  //! TO for Error Concelament 
  //! If we have an INTRA Macroblock and we lost the partition 
  //! which contains the intra coefficients Copy MB would be better  
  //! than just a grey block. 
  //! Seems to be a bit at the wrong place to do this right here, but for this case  
  //! up to now there is no other way.//Lou 
 
  //--- init macroblock data --- 
  if (img->type==B_IMG)  
    init_macroblock_Bframe(img); 
  else 
    init_macroblock       (img); 
   
	if (IS_INTRA(currMB)) 
	{ 
		for (i=0;i<5;i++) 
			read_ipred_block_modes(img,inp,i); 
	} 
 
	if (skip_mode_flag) 
	{ 
		if (IS_DIRECT (currMB) && img->cod_counter >= 0) 
		{ 
			int i, j, iii, jjj; 
			currMB->cbp = 0; 
			 
			for (i=0;icof[i][j][iii][jjj]=0; 
			} 
			 
			for (j=4;j<6;j++) 
			{ // reset chroma coeffs 
				for (i=0;i<4;i++) 
					for (iii=0;iii<4;iii++) 
						for (jjj=0;jjj<4;jjj++) 
							img->cof[i][j][iii][jjj]=0; 
			} 
		 
			return DECODE_MB; 
		} 
	} 
	else 
	{ 
		if (img->type==B_IMG&& real_mb_type<0) 
		{ 
			int i, j, iii, jjj; 
			currMB->cbp = 0; 
			 
			for (i=0;icof[i][j][iii][jjj]=0; 
			} 
			 
			for (j=4;j<6;j++) 
			{ // reset chroma coeffs 
				for (i=0;i<4;i++) 
					for (iii=0;iii<4;iii++) 
						for (jjj=0;jjj<4;jjj++) 
							img->cof[i][j][iii][jjj]=0; 
			} 
 
			return DECODE_MB; 
		} 
	} 
   
	if (IS_COPY (currMB)) //keep last macroblock 
	{ 
		int i, j, iii, jjj, pmv[2]; 
		int ***tmp_mv         = img->mv; 
		int mb_available_up   = (img->mb_y == 0)  ? 0 : (currMB->slice_nr == mb_data[img->current_mb_nr-img->width/16].slice_nr); 
		int mb_available_left = (img->mb_x == 0)  ? 0 : (currMB->slice_nr == mb_data[img->current_mb_nr-1].slice_nr); 
		int zeroMotionAbove   = !mb_available_up  ? 1 : refFrArr[img->block_y-1][img->block_x]  == 0 && tmp_mv[4+img->block_x  ][img->block_y-1][0] == 0 && tmp_mv[4+img->block_x  ][img->block_y-1][1] == 0 ? 1 : 0; 
		int zeroMotionLeft    = !mb_available_left? 1 : refFrArr[img->block_y][img->block_x-1]  == 0 && tmp_mv[4+img->block_x-1][img->block_y  ][0] == 0 && tmp_mv[4+img->block_x-1][img->block_y  ][1] == 0 ? 1 : 0; 
		 
		currMB->cbp = 0; 
		 
		for (i=0;icof[i][j][iii][jjj]=0; 
		} 
		for (j=4;j<6;j++) 
		{ // reset chroma coeffs 
			for (i=0;i<4;i++) 
				for (iii=0;iii<4;iii++) 
					for (jjj=0;jjj<4;jjj++) 
						img->cof[i][j][iii][jjj]=0; 
		} 
		 
		 
		img_block_y   = img->block_y;  
		 
		if (zeroMotionAbove || zeroMotionLeft) 
		{ 
			for(i=0;i<2;i++) 
				for(j=0;j<2;j++) 
				{ 
					img->mv[img->block_x+i+BLOCK_SIZE][img->block_y+j][0] = 0; 
					img->mv[img->block_x+i+BLOCK_SIZE][img->block_y+j][1] = 0; 
				} 
		} 
		else 
		{ 
			SetMotionVectorPredictor (img, pmv, pmv+1, 0, refFrArr, img->mv, 0, 0, 16, 16, 0, 0);//Lou 1016 
			for(i=0;i<2;i++) 
				for(j=0;j<2;j++) 
				{ 
					img->mv[img->block_x+i+BLOCK_SIZE][img_block_y+j][0] = pmv[0]; 
					img->mv[img->block_x+i+BLOCK_SIZE][img_block_y+j][1] = pmv[1]; 
				} 
		} 
		 
		for (j=0; j<2;j++) 
			for (i=0; i<2;i++) 
			{ 
				refFrArr_frm[img->block_y+j][img->block_x+i] = 0; 
			} 
			 
		return DECODE_MB; 
	} 
 
	readReferenceIndex(img, inp);  
	readMotionVector (img, inp); 
	 
	// !! start shenyanfei cjw 
	//if((!IS_INTRA(currMB)) && (img->slice_weighting_flag == 1) && (img->mb_weighting_flag == 0)){ //cjw 20051219 
	//if((!IS_INTRA(currMB)) && (img->slice_weighting_flag == 1) && (img->mb_weighting_flag == 1)&&(!IS_COPY(currMB))&&(!IS_DIRECT(currMB))){ //cjw20051230 for skip MB  
	if((!IS_INTRA(currMB)) && (img->slice_weighting_flag == 1) && (img->mb_weighting_flag == 1)&&(!IS_COPY(currMB))){ //cjw20060321 skip no WP, direct WP 
		img->weighting_prediction = u_v(1,"MB weighting_prediction");  //cjw 20051219 
	} 
	// !! end shenyanfei cjw 
 
	// read CBP if not new intra mode 
  if (!(IS_COPY (currMB) || (IS_DIRECT (currMB) && img->cod_counter >= 0))) 
  { 
 
    if (IS_OLDINTRA (currMB) || currMB->mb_type == SI4MB )   currSE.type = SE_CBP_INTRA; 
    else                        currSE.type = SE_CBP_INTER; 
     
    if (IS_OLDINTRA (currMB) || currMB->mb_type == SI4MB)   
      currSE.mapping = linfo_cbp_intra; 
    else                        
      currSE.mapping = linfo_cbp_inter; 
     
     
#if TRACE 
    snprintf(currSE.tracestring, TRACESTRING_SIZE, "CBP"); 
#endif 
     
    if(img->type==I_IMG||IS_INTER(currMB)) // qhg 
	{ 
		currSE.golomb_maxlevels = 0; 
		readSyntaxElement_UVLC(&currSE,inp); 
		currMB->cbp = currSE.value1; 
    } 
    // Delta quant only if nonzero coeffs 
    if (!fixqp&&currMB->cbp !=0) 
    { 
      if (IS_INTER (currMB))  currSE.type = SE_DELTA_QUANT_INTER; 
      else                    currSE.type = SE_DELTA_QUANT_INTRA; 
       
      currSE.mapping = linfo_se; 
       
#if TRACE 
      snprintf(currSE.tracestring, TRACESTRING_SIZE, "Delta quant "); 
#endif 
      readSyntaxElement_UVLC(&currSE,inp); 
      currMB->delta_quant = currSE.value1; 
      img->qp= (img->qp-MIN_QP+currMB->delta_quant+(MAX_QP-MIN_QP+1))%(MAX_QP-MIN_QP+1)+MIN_QP; //discussed by cjw AVS Zhuhai 20070123 
    } 
 
	if (fixqp) 
	{ 
		currMB->delta_quant = 0; 
		img->qp= (img->qp-MIN_QP+currMB->delta_quant+(MAX_QP-MIN_QP+1))%(MAX_QP-MIN_QP+1)+MIN_QP; 
		 
	} 
 
  } 
  // read CBP and Coeffs  *************************************************************** 
  readCBPandCoeffsFromNAL (img,inp); 
   
  return DECODE_MB; 
} 
 
void read_ipred_block_modes(struct img_par *img,struct inp_par *inp,int b8) 
{ 
  int bi,bj,dec; 
  SyntaxElement currSE; 
  Macroblock *currMB; 
  int j2; 
  int mostProbableIntraPredMode; 
  int upIntraPredMode; 
  int leftIntraPredMode; 
  int IntraChromaPredModeFlag; 
	int MBRowSize = img->width / MB_BLOCK_SIZE; 
   
  currMB=mb_data+img->current_mb_nr;//current_mb_nr; 
  IntraChromaPredModeFlag = IS_INTRA(currMB); 
   
  currSE.type = SE_INTRAPREDMODE; 
#if TRACE 
  strncpy(currSE.tracestring, "Ipred Mode", TRACESTRING_SIZE); 
#endif 
   
	if(b8<4) 
	{		 
		if( currMB->b8mode[b8]==IBLOCK ) 
		{ 
			IntraChromaPredModeFlag = 1; 
			//get from stream 
			readSyntaxElement_Intra8x8PredictionMode(&currSE); 
			 
			//get from array and decode 
			bi = img->block_x + (b8&1); 
			bj = img->block_y + (b8/2); 
			 
			upIntraPredMode            = img->ipredmode[bi+1][bj]; 
			leftIntraPredMode          = img->ipredmode[bi][bj+1]; 
			mostProbableIntraPredMode  = (upIntraPredMode < 0 || leftIntraPredMode < 0) ? DC_PRED : upIntraPredMode < leftIntraPredMode ? upIntraPredMode : leftIntraPredMode; 
			 
			dec = (currSE.value1 == -1) ? mostProbableIntraPredMode : currSE.value1 + (currSE.value1 >= mostProbableIntraPredMode); 
			 
			//set 
			img->ipredmode[1+bi][1+bj]=dec; 
			j2 = bj; 
		} 
	}	 
	else if( b8==4&&currMB->b8mode[b8-3]==IBLOCK) 
	{ 
		 
	    currSE.type = SE_INTRAPREDMODE; 
#if TRACE 
    strncpy(currSE.tracestring, "Chroma intra pred mode", TRACESTRING_SIZE); 
#endif 
     
	    currSE.mapping = linfo_ue; 
     
	    readSyntaxElement_UVLC(&currSE,inp); 
	    currMB->c_ipred_mode = currSE.value1; 
 
	    if (currSE.value1 < DC_PRED_8 || currSE.value1 > PLANE_8) 
	    { 
	      printf("%d\n", img->current_mb_nr); 
	      error("illegal chroma intra pred mode!\n", 600); 
	    } 
	 } 
} 
 
/* 
************************************************************************* 
* Function:Set context for reference frames 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
int BType2CtxRef (int btype) 
{ 
  if (btype<4) 
    return 0; 
  else 
    return 1; 
} 
 
/* 
************************************************************************* 
* Function: 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
void readReferenceIndex(struct img_par *img, struct inp_par *inp) 
{ 
    int i,j,k; 
    // int mb_nr           = img->current_mb_nr; //GB Falsch 
    Macroblock *currMB  = &mb_data[img->current_mb_nr]; 
    SyntaxElement currSE; 
    int bframe          = (img->type==B_IMG); 
    int partmode        = (IS_P8x8(currMB)?4:currMB->mb_type); 
    int step_h0         = BLOCK_STEP [partmode][0]; 
    int step_v0         = BLOCK_STEP [partmode][1]; 
 
    int i0, j0, refframe; 
    int **fwRefFrArr = img->fw_refFrArr; 
    int **bwRefFrArr = img->bw_refFrArr; 
    int  ***fw_mv = img->fw_mv; 
    int  ***bw_mv = img->bw_mv; 
    //int  **moving_block_dir = moving_block;  
    int flag_mode; 
 
    //  If multiple ref. frames, read reference frame for the MB ********************************* 
    flag_mode = 0; 
 
    currSE.type = SE_REFFRAME; 
    currSE.mapping = linfo_ue; 
 
	if(currMB->mb_type!=I4MB) 
	{				 
		step_h0         = (BLOCK_STEP[IS_P8x8(currMB) ? 4 : currMB->mb_type][0]); 
		step_v0         = (BLOCK_STEP[IS_P8x8(currMB) ? 4 : currMB->mb_type][1]); 
	} 
 
    // !! shenyanfei  
    for (j0=0; j0<2; ) 
    { 
        if((currMB->mb_type==I4MB&&j0==0))  
        { j0 += 1; continue;} 
 
        for (i0=0; i0<2; ) 
        {				 
            k=2*j0+i0; 
            if ((currMB->b8pdir[k]==0 || currMB->b8pdir[k]==2) && currMB->b8mode[k]!=0) 
            { 
                img->subblock_x = i0; 
                img->subblock_y = j0; 
 
                if ((!picture_reference_flag&&img->type==P_IMG && img->types!=I_IMG) || (!picture_reference_flag&&!img->picture_structure && img->types!=I_IMG))  
                { 
#if TRACE 
                    strncpy(currSE.tracestring,  "Fwd ref frame no ", TRACESTRING_SIZE); 
#endif 
                    currSE.context = BType2CtxRef (currMB->b8mode[k]); 
 
                    if(img->picture_structure || bframe) 
                        currSE.len = 1; 
                    else 
                        currSE.len = 2; 
 
                    readSyntaxElement_FLC(&currSE); 
                    refframe = currSE.value1; 
                } 
                else 
                { 
                    refframe = 0; 
                } 
 
                if (!bframe) 
                { 
                    for (j=j0; jblock_y+j][img->block_x+i] = refframe; 
                } 
                else // !! for B frame shenyanfei  
                { 
                    for (j=j0; jfw_refFrArr[img->block_y+j][img->block_x+i] = refframe; 
 
                    if (currMB->b8pdir[k]==2 && !img->picture_structure) 
                    { 
                        for (j=j0; jbw_refFrArr[img->block_y+j][img->block_x+i] = 1-refframe; 
                    } 
                } 
            } 
            i0+=max(1,step_h0); 
        } 
        j0+=max(1,step_v0); 
    } 
 
	for (j0=0; j0<2; ) 
	{ 
		if((currMB->mb_type==I4MB&&j0==0))  
		{ j0 += 1; continue;} 
		 
		for (i0=0; i0<2; ) 
		{				 
			k=2*j0+i0; 
				if ((currMB->b8pdir[k]==1) && currMB->b8mode[k]!=0) 
				{ 
					img->subblock_x = i0; 
					img->subblock_y = j0; 
					 
					if (img->type==B_IMG && !img->picture_structure&&!picture_reference_flag)  
					{ 
	#if TRACE 
						strncpy(currSE.tracestring,  "Bwd ref frame no ", TRACESTRING_SIZE); 
	#endif 
						currSE.context = BType2CtxRef (currMB->b8mode[k]); 
						 
						if(img->picture_structure || bframe) 
							currSE.len = 1; 
						else 
							currSE.len = 2; 
						 
						readSyntaxElement_FLC(&currSE);						 
						refframe = currSE.value1; 
					} 
					else 
					{ 
						refframe = 0; 
					} 
					 
					for (j=j0; jbw_refFrArr[img->block_y+j][img->block_x+i] = refframe; 
				}  
				 
				i0+=max(1,step_h0); 
			} 
			j0+=max(1,step_v0); 
	} 
} 
 
/* 
************************************************************************* 
* Function: 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
void readMotionVector(struct img_par *img, struct inp_par *inp) 
{ 
    int i,j,k,l,m,n; 
    int step_h,step_v; 
    int curr_mvd; 
    // int mb_nr           = img->current_mb_nr; //GB Falsch 
    Macroblock *currMB  = &mb_data[img->current_mb_nr]; 
    SyntaxElement currSE; 
    int bframe          = (img->type==B_IMG); 
    int partmode        = (IS_P8x8(currMB)?4:currMB->mb_type); 
    int step_h0         = BLOCK_STEP [partmode][0]; 
    int step_v0         = BLOCK_STEP [partmode][1]; 
 
    int mv_mode, i0, j0, refframe; 
    int pmv[2]; 
    int j4, i4, ii,jj; 
    int vec; 
 
    int iTRb,iTRp,iTRd; 
    int frame_no_next_P, frame_no_B, delta_P; 
    int ref; 
    int img_block_y; 
    int use_scaled_mv; 
    int fw_refframe,current_tr; 
 
    int **fwRefFrArr = img->fw_refFrArr; 
    int **bwRefFrArr = img->bw_refFrArr; 
    int  ***fw_mv = img->fw_mv; 
    int  ***bw_mv = img->bw_mv; 
    int	scale_refframe,iTRp1,bw_ref; 
 
    if (bframe && IS_P8x8 (currMB)) 
    { 
        for (i=0;i<4;i++) 
        { 
            if (currMB->b8mode[i] == 0) 
            { 
                for(j=i/2;jfw_refFrArr[img->block_y + j][img->block_x + k] = 0; 
                        img->bw_refFrArr[img->block_y + j][img->block_x + k] = 0;  
                    } 
                } 
            } 
        } 
    }  
 
 
    //=====  READ FORWARD MOTION VECTORS ===== 
    currSE.type = SE_MVD; 
 
    currSE.mapping = linfo_se; 
 
    for (j0=0; j0<2; ) 
    { 
        if(currMB->mb_type!=I4MB) 
        {				 
            step_h0         = (BLOCK_STEP[(currMB->mb_type==P8x8)? 4 : currMB->mb_type][0]); 
            step_v0         = (BLOCK_STEP[(currMB->mb_type==P8x8)? 4 : currMB->mb_type][1]); 
        } 
 
        if((currMB->mb_type==I4MB&&j0==0)) // for  by jhzheng [2004/08/02] 
        { j0 += 1; continue;} 
		//{break;} 
 
 
        for (i0=0; i0<2; ) 
        { 
            k=2*j0+i0; 
            if ((currMB->b8pdir[k]==0 || currMB->b8pdir[k]==2) && (currMB->b8mode[k] !=0))//has forward vector 
            { 
                mv_mode  = currMB->b8mode[k]; 
                step_h   = BLOCK_STEP [mv_mode][0]; 
                step_v   = BLOCK_STEP [mv_mode][1]; 
 
                if (!bframe)  refframe = refFrArr        [img->block_y+j0][img->block_x+i0]; 
                else                                     refframe = img->fw_refFrArr[img->block_y+j0][img->block_x+i0]; 
 
 
                for (j=j0; jblock_y+j; 
                        i4 = img->block_x+i; 
 
                        // first make mv-prediction 
                        if (!bframe)   
                            SetMotionVectorPredictor (img, pmv, pmv+1, refframe, refFrArr,         img->mv,    i, j, 8*step_h, 8*step_v, 0, 0);//Lou 1016 
                        else                
                            SetMotionVectorPredictor (img, pmv, pmv+1, refframe, img->fw_refFrArr, img->fw_mv, i, j, 8*step_h, 8*step_v, 0, 0);//Lou 1016 
						 
 
                        for (n=0; n < 2; n++)  
                        { 
#if TRACE 
                            snprintf(currSE.tracestring, TRACESTRING_SIZE, "FMVD (pred %d)",pmv[n]); 
#endif 
                            img->subblock_x = i; // position used for context determination 
                            img->subblock_y = j; // position used for context determination 
                            currSE.value2 = (!bframe ? n : 2*n); // identifies the component; only used for context determination 
                            readSyntaxElement_UVLC(&currSE,inp); 
                            curr_mvd = currSE.value1;  
 
                            vec=curr_mvd+pmv[n];           /* find motion vector */ 
 
                            // need B support 
                            if (!bframe) 
                            { 
                                for(ii=0;iimv[i4+ii+BLOCK_SIZE][j4+jj][n]=vec;				 
                            } 
                            else      // B frame 
                            {         
                                for(ii=0;iifw_mv[i4+ii+BLOCK_SIZE][j4+jj][n]=vec; 
                            } 
 
                            /* store (oversampled) mvd */ 
                            for (l=0; l < step_v; l++)  
                                for (m=0; m < step_h; m++)   
                                    currMB->mvd[0][j+l][i+m][n] =  curr_mvd; 
                        } 
                    } 
            } 
            else if (currMB->b8mode[k=2*j0+i0]==0)       
            {// direct mode   
                // by Junhao Zheng 2004-08-04 22:00:51   
                //step_v0 = step_h0 = 1; 
                for (j=j0; jblock_y+j][img->block_x+i]; 
                        img_block_y = (img->current_mb_nr%2) ? (img->block_y-4)/2:img->block_y/2; 
 
                        if(ref == -1) 
                        { 
 
                            //sw              
                            img->fw_refFrArr[img->block_y+j][img->block_x+i]=0;  
                            img->bw_refFrArr[img->block_y+j][img->block_x+i]=0;  
                            j4 = img->block_y+j; 
                            i4 = img->block_x+i;   
 
                            for (ii=0; ii < 2; ii++)  
                            { 
                                img->fw_mv[i4+BLOCK_SIZE][j4][ii]=0; 
                                img->bw_mv[i4+BLOCK_SIZE][j4][ii]=0; 
                            } 
 
                            SetMotionVectorPredictor(img,&(img->fw_mv[i4+BLOCK_SIZE][j4][0]), 
                                                     &(img->fw_mv[i4+BLOCK_SIZE][j4][1]),0,img->fw_refFrArr,  
                                                     img->fw_mv,0,0,16,16, 0, 1); 
                            SetMotionVectorPredictor(img,&(img->bw_mv[i4+BLOCK_SIZE][j4][0]), 
                                                     &(img->bw_mv[i4+BLOCK_SIZE][j4][1]),0,img->bw_refFrArr,  
                                                     img->bw_mv,0,0,16,16, -1, 1);					 
                        } 
                        else 
                        { 
                            frame_no_next_P =2*img->imgtr_next_P; 
//                            frame_no_B = 2*img->tr; 
							frame_no_B = 2*img->pic_distance;  // Added by Xiaozhen ZHENG, 2007.05.01 
 
                            delta_P = 2* (img->imgtr_next_P - img->imgtr_last_P); 
							delta_P = (delta_P + 512)%512;            // Added by Xiaozhen ZHENG, 2007.05.01 
 
                            if(!img->picture_structure) 
                            {				   
 
                                if (img->current_mb_nr_fld < img->PicSizeInMbs) //top field 
                                    scale_refframe = 	ref == 0 ? 0 : 1; 
                                else 
                                    scale_refframe = 	ref == 1 ? 1 : 2;  
                            } 
                            else 
                                scale_refframe = 0; 
 
 
                            if(img->picture_structure) 
                            { 
                                iTRp = (ref+1)*delta_P; 
                                iTRp1 = (scale_refframe+1)*delta_P; 
                            }else 
                            { 
                                if (img->current_mb_nr_fld < img->PicSizeInMbs) //top field 
                                { 
                                    iTRp = delta_P*(ref/2+1)-(ref+1)%2;  //the lates backward reference 
                                    iTRp1 = delta_P*(scale_refframe/2+1)-(scale_refframe+1)%2;  //the lates backward reference 
                                    bw_ref = 0; 
                                } 
                                else 
                                { 
                                    iTRp = 1 + delta_P*((ref+1)/2)-ref%2; 
                                    iTRp1 = 1 + delta_P*((scale_refframe+1)/2)-scale_refframe%2; 
                                    bw_ref = 1; 
                                } 
                            } 
 
                            iTRd = frame_no_next_P - frame_no_B; 
                            iTRb = iTRp1 - iTRd; 
 
						 
							// Added by Xiaozhen ZHENG, 2007.05.01 
							iTRp  = (iTRp  + 512)%512; 
							iTRp1 = (iTRp1 + 512)%512; 
							iTRd  = (iTRd  + 512)%512; 
							iTRb  = (iTRb  + 512)%512; 
							// Added by Xiaozhen ZHENG, 2007.05.01 
							 
                            if(!img->picture_structure) 
                            { 
                                if (img->current_mb_nr_fld >= img->PicSizeInMbs)  
                                    scale_refframe --; 
                                img->fw_refFrArr[img->block_y+j][img->block_x+i]=scale_refframe; // PLUS2, Krit, 7/06 (used to be + 1) 
                                img->bw_refFrArr[img->block_y+j][img->block_x+i]=bw_ref; 
                            } 
                            else 
                            { 
                                img->fw_refFrArr[img->block_y+j][img->block_x+i]=0; // PLUS2, Krit, 7/06 (used to be + 1) 
                                // by Junhao Zheng 2004-08-04 21:50:38   
                                //img->bw_refFrArr[img->block_y+j][img->block_x+i]=1; 
                                img->bw_refFrArr[img->block_y+j][img->block_x+i]=0; 
                            } 
 
                            j4 = img->block_y+j; 
                            i4 = img->block_x+i; 
 
                            for (ii=0; ii < 2; ii++) 
                            { 
                                if(img->mv[img->block_x+i+4][img->block_y+j][ii] < 0) 
                                { 
                                    img->fw_mv[i4+BLOCK_SIZE][j4][ii] =  -(((16384/iTRp)*(1-iTRb*img->mv[img->block_x+i+4][img->block_y+j][ii])-1)>>14); 
                                    img->bw_mv[i4+BLOCK_SIZE][j4][ii] = ((16384/iTRp)*(1-iTRd*img->mv[img->block_x+i+4][img->block_y+j][ii])-1)>>14; 
                                } 
                                else 
                                { 
                                    img->fw_mv[i4+BLOCK_SIZE][j4][ii] = ((16384/iTRp)*(1+iTRb*img->mv[img->block_x+i+4][img->block_y+j][ii])-1)>>14; 
                                    img->bw_mv[i4+BLOCK_SIZE][j4][ii] = -(((16384/iTRp)*(1+iTRd*img->mv[img->block_x+i+4][img->block_y+j][ii])-1)>>14); 
                                } 
 
                            } 
                        }  
                    } 
            } 
 
            img_block_y = img->block_y; 
 
            i0+=max(1,step_h0); 
        } 
        j0+=max(1,step_v0); 
    } 
 
 
	  //=====  READ BACKWARD MOTION VECTORS ===== 
  currSE.type = SE_MVD; 
   
  currSE.mapping = linfo_se; 
   
  img_block_y = img->block_y; 
   
  for (j0=0; j0<2; ) 
  { 
	  if(currMB->mb_type!=I4MB) 
	  {				 
		  step_h0         = (BLOCK_STEP[(currMB->mb_type==P8x8)? 4 : currMB->mb_type][0]); 
		  step_v0         = (BLOCK_STEP[(currMB->mb_type==P8x8)? 4 : currMB->mb_type][1]); 
	  } 
	   
	  if((currMB->mb_type==I4MB&&j0==0))  
	  { j0 += 1; continue;} 
	   
	   
	  for (i0=0; i0<2; ) 
	  { 
		  k=2*j0+i0; 
		   
		  if ((currMB->b8pdir[k]==1 || currMB->b8pdir[k]==2) && (currMB->b8mode[k]!=0))//has backward vector 
		  { 
			  mv_mode  = currMB->b8mode[k]; 
			  step_h   = BLOCK_STEP [mv_mode][0]; 
			  step_v   = BLOCK_STEP [mv_mode][1]; 
			   
			  refframe = img->bw_refFrArr[img->block_y+j0][img->block_x+i0]; // always 0 
			   
			  use_scaled_mv = 0; 
 
			  if(currMB->b8pdir[k]==2) 
			  { 
				  fw_refframe = img->fw_refFrArr[img->block_y+j0][img->block_x+i0]; 
//				  current_tr  = 2*img->tr_frm;   // Commented by Xiaozhen ZHENG, 2007.05.01 
				  current_tr  = 2*(img->pic_distance/2); 
				   
			  } 
			   
			  for (j=j0; jblock_y+j; 
					  i4 = img->block_x+i; 
					   
					  SetMotionVectorPredictor (img, pmv, pmv+1, refframe, img->bw_refFrArr, img->bw_mv, i, j, 8*step_h, 8*step_v, -1, 0);//Lou 1016 
					   
					  for (k=0; k < 2; k++)  
					  { 
#if TRACE 
						  snprintf(currSE.tracestring, TRACESTRING_SIZE, "BMVD (pred %d)",pmv[k]); 
#endif 
						  img->subblock_x = i; // position used for context determination 
						  img->subblock_y = j; // position used for context determination 
						  currSE.value2   = 2*k+1; // identifies the component; only used for context determination 
						   
						   
						  if(currMB->b8pdir[2*j0+i0] == 2) 
						  {				   
							  int delta_P,iTRp,DistanceIndexFw,DistanceIndexBw,refframe,delta_PB;				   
							  refframe = fw_refframe; 
							  delta_P = 2*(img->imgtr_next_P - img->imgtr_last_P); 
							  delta_P = (delta_P + 512)%512;    // Added by Xiaozhen ZHENG, 2007.05.01 
							  if(img->picture_structure) 
								  iTRp = (refframe+1)*delta_P;  //the lates backward reference 
							  else 
							  { 
								  iTRp = delta_P;//refframe == 0 ? delta_P-1 : delta_P+1; 
							  } 
//							  delta_PB = 2*(img->tr - img->imgtr_last_P);            // Commented by Xiaozhen ZHENG, 2007.05.01 
							  delta_PB = 2*(img->pic_distance - img->imgtr_last_P);  // Added by Xiaozhen ZHENG, 2007.05.01 
							  delta_PB = (delta_PB + 512)%512;                       // Added by Xiaozhen ZHENG, 2007.05.01 
							  iTRp     = (iTRp + 512)%512;                           // Added by Xiaozhen ZHENG, 2007.05.01 
							  if(!img->picture_structure) 
							  { 
								  if(img->current_mb_nr_fld < img->PicSizeInMbs) //top field 
									  DistanceIndexFw =  refframe == 0 ? delta_PB-1:delta_PB; 
								  else 
									  DistanceIndexFw =  refframe == 0 ? delta_PB:delta_PB+1; 
							  } 
							  else 
								  DistanceIndexFw = delta_PB;							     
							   
							  //DistanceIndexBw  = iTRp - DistanceIndexFw;       
							  DistanceIndexBw    = (iTRp - DistanceIndexFw+512)%512; // Added by Zhijie Yang, 20070419, Broadcom 
							   
							  curr_mvd = - ((img->fw_mv[i4+BLOCK_SIZE][j4][k]*DistanceIndexBw*(512/DistanceIndexFw)+256)>>9);  
							  vec=curr_mvd;           /* find motion vector */ 
						  } 
						  else 
						  { 
							  readSyntaxElement_UVLC(&currSE,inp); 
							  curr_mvd = currSE.value1;  
							  vec=curr_mvd+pmv[k];           /* find motion vector */ 
						  } 
						   
						  for(ii=0;iibw_mv[i4+ii+BLOCK_SIZE][j4+jj][k]=vec; 
							   
							  /* store (oversampled) mvd */ 
							  for (l=0; l < step_v; l++)  
								  for (m=0; m < step_h; m++)   
									  currMB->mvd[1][j+l][i+m][k] =  curr_mvd; 
					  } 
				  } 
		  } 
		  i0+=max(1,step_h0); 
	  } 
	  j0+=max(1,step_v0); 
	   
    } 
} 
 
/* 
************************************************************************* 
* Function:Get coded block pattern and coefficients (run/level) 
    from the NAL 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void readCBPandCoeffsFromNAL(struct img_par *img,struct inp_par *inp) 
{ 
  int i,j; 
  int mb_nr = img->current_mb_nr; //GBimg->current_mb_nr; 
   
  int  m2,jg2; 
  Macroblock *currMB = &mb_data[mb_nr]; 
  int iii,jjj; 
  int b8; 
   
  int block_x,block_y; 
   
  int qp_per    = (img->qp-MIN_QP)/6; 
  int qp_rem    = (img->qp-MIN_QP)%6; 
  int qp_per_uv = QP_SCALE_CR[img->qp-MIN_QP]/6; 
  int qp_rem_uv = QP_SCALE_CR[img->qp-MIN_QP]%6; 
   
  for (i=0;icof[i][j][iii][jjj]=0;// reset luma coeffs 
         
  qp_per    = (img->qp-MIN_QP)/6; 
  qp_rem    = (img->qp-MIN_QP)%6; 
  qp_per_uv = QP_SCALE_CR[img->qp-MIN_QP]/6; 
  qp_rem_uv = QP_SCALE_CR[img->qp-MIN_QP]%6; 
  currMB->qp = img->qp; 
         
  // luma coefficients 
  for (block_y=0; block_y < 4; block_y += 2) /* all modes */ 
  { 
    for (block_x=0; block_x < 4; block_x += 2) 
    { 
      b8 = 2*(block_y/2) + block_x/2; 
  
			if (currMB->cbp&(1<cof[i][j][iii][jjj]=0; 
         
  m2 =img->mb_x*2; 
  jg2=img->mb_y*2; 
   
  if ((currMB->cbp>>4)&1) 
	{ 
		readChromaCoeff_B8(4, inp, img); 
	} 
 
 
  if ((currMB->cbp>>4)&2) 
  { 
		readChromaCoeff_B8(5, inp, img); 
	} 
} 
 
/* 
************************************************************************* 
* Function:decode one macroblock 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
int decode_one_macroblock(struct img_par *img,struct inp_par *inp) 
{ 
  unsigned char edgepixu[40]; 
#define EPU (edgepixu+20) 
  unsigned char edgepixv[40]; 
#define EPV (edgepixv+20) 
  int x,y,last_pix,new_pix; 
  int bs_x=8; 
  int bs_y=8; 
   
  int tmp_block[8][8]; 
  int tmp_blockbw[8][8]; 
  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, hv; 
  int vec1_x=0,vec1_y=0,vec2_x=0,vec2_y=0; 
  int ioff,joff; 
  short curr_blk[B8_SIZE][B8_SIZE];  //SW for AVS 
  int tmp; 
  int block8x8;   // needed for ABT 
  int bw_pred, fw_pred, ifx; 
  int ii0,jj0,ii1,jj1,if1,jf1,if0,jf0; 
  int mv_mul,f1,f2,f3,f4; 
	 
  const byte decode_block_scan[16] = {0,1,4,5,2,3,6,7,8,9,12,13,10,11,14,15}; 
	 
  Macroblock *currMB   = &mb_data[img->current_mb_nr];//GB current_mb_nr]; 
  int refframe, fw_refframe, bw_refframe, mv_mode, pred_dir, intra_prediction; // = currMB->ref_frame; 
  int fw_ref_idx, bw_ref_idx; 
  int*** mv_array, ***fw_mv_array, ***bw_mv_array; 
  int bframe = (img->type==B_IMG); 
  int  b8_s=0,b8_e=4,incr_y=1,off_y=0,even_y=4,add_y=0; 
  int frame_no_next_P, frame_no_B, delta_P; 
  int iTRb, iTRp,iTRd; 
	 
  int mb_nr             = img->current_mb_nr;//GBimg->current_mb_nr; 
  int mb_width          = img->width/16; 
  int mb_available_up; 
  int mb_available_left; 
   
  int fwd_refframe_offset,bwd_refframe_offset; 
  int direct_pdir; 
  int	scale_refframe,iTRp1,bw_ref; 
    
  // !! shenyanfei  
	int fw_lum_scale , fw_lum_shift ; 
	int bw_lum_scale , bw_lum_shift ; 
  //cjw 20051219 Weighted Predition 
	int fw_chrom_scale , fw_chrom_shift ; 
	int bw_chrom_scale , bw_chrom_shift ; 
 
int	mb_available_up_right=((img->mb_y==0)||(img->mb_x==img->width/MB_BLOCK_SIZE-1)) ? 0 : (mb_data[mb_nr].slice_nr == mb_data[mb_nr-mb_width+1].slice_nr); 
int  mb_available_left_down=((img->mb_x==0)||(img->mb_y==img->height/MB_BLOCK_SIZE-1)) ? 0 : (mb_data[mb_nr].slice_nr == mb_data[mb_nr+mb_width-1].slice_nr); 
//by oliver according to 1658 
  mb_available_up   = (img->mb_y == 0) ? 0 : (mb_data[mb_nr].slice_nr == mb_data[mb_nr-mb_width].slice_nr); 
  mb_available_left = (img->mb_x == 0) ? 0 : (mb_data[mb_nr].slice_nr == mb_data[mb_nr-1].slice_nr); 
   
  /* 
  //cjw weighted prediction parameter map 20060112 
  ///frame coding///////// 
	P		img->lum_scale[0]  fw[0]  
			img->lum_scale[1]  fw[1]			 
	B	    img->lum_scale[0]  fw[0] 
			img->lum_scale[1]  bw[0] 
	///field coding//////// 
	P		img->lum_scale[0]  fw[0] ; img->lum_scale[1]  fw[1]  
			img->lum_scale[2]  fw[2] ; img->lum_scale[3]  fw[3] 			 
	B		img->lum_scale[0]  fw[0] ; img->lum_scale[1]  bw[0]  
			img->lum_scale[2]  fw[1] ; img->lum_scale[3]  bw[1]  
   	//For B framecoding		  
			fw	[fw_ref] 
			bw	[bw_ref+1] 
	//For B fieldcoding       
			fw	[fw_ref*2] 
			bw	[bw_ref*2+1] 
	*/ 
   
   	if(bframe) 
  { 
//    int current_tr  = 2*img->tr_frm;   // Commented by Xiaozhen ZHENG, 2007.05.01 
	int current_tr = 2*(img->pic_distance/2); 
    if(img->imgtr_next_P <= current_tr) 
      fwd_refframe_offset = 0; 
    else  
      fwd_refframe_offset = 1; 
  } 
  else 
  { 
    fwd_refframe_offset = 0; 
  } 
	 
  if (bframe) 
  { 
    bwd_refframe_offset = 0; 
  } 
	 
  mv_mul=4; 
  f1=8; 
  f2=7; 
   
  f3=f1*f1; 
  f4=f3/2; 
   
  // luma decoding ************************************************** 
  for (block8x8=0; block8x8<4; block8x8++) 
  { 
    if (currMB->b8mode[block8x8] != IBLOCK) 
    { 
			i = block8x8%2; 
			j = block8x8/2; 
			 
			ioff=i*8; 
			i4=img->block_x+i; 
			 
			joff=j*8; 
			j4=img->block_y+j; 
			 
			mv_mode  = currMB->b8mode[block8x8]; 
			pred_dir = currMB->b8pdir[block8x8]; 
			 
			if (pred_dir != 2) 
			{ 
				//===== FORWARD/BACKWARD PREDICTION ===== 
				if (!bframe)  // !! P MB shenyanfei  
				{ 
					refframe = refFrArr[j4][i4]; 
					fw_ref_idx = refframe; 
					mv_array = img->mv; 
				} 
				else if (!pred_dir) // !! B forward shenyanfei  
				{ 
					refframe = img->fw_refFrArr[j4][i4];// fwd_ref_idx_to_refframe(img->fw_refFrArr[j4][i4]); 
					fw_ref_idx = img->fw_refFrArr[j4][i4]; 
					mv_array = img->fw_mv; 
				} 
				else // !! B backward shenyanfei  
				{ 
					refframe = img->bw_refFrArr[j4][i4];// bwd_ref_idx_to_refframe(img->bw_refFrArr[j4][i4]); 
					bw_ref_idx = img->bw_refFrArr[j4][i4]; 
					bw_ref_idx = bw_ref_idx; 
					mv_array = img->bw_mv; 
				} 
				 
				if((progressive_sequence||progressive_frame)&&bframe&&img->picture_structure)  
					refframe = 0; 
				vec1_x = i4*8*mv_mul + mv_array[i4+BLOCK_SIZE][j4][0]; 
				vec1_y = j4*8*mv_mul + mv_array[i4+BLOCK_SIZE][j4][1]; 
				 
				if(!bframe){ // !! for P MB shenyanfei cjw 
 
					get_block(refframe, vec1_x, vec1_y, img, tmp_block,mref[refframe]); 
					 
					//if(((currMB->mb_type != 0)&&(img->slice_weighting_flag == 1) &&   
					if(((img->slice_weighting_flag == 1)&&			//cjw20060321 
						(img->mb_weighting_flag == 1)&&(img->weighting_prediction == 1))   
						||((img->slice_weighting_flag == 1) && (img->mb_weighting_flag == 0))){ 
						fw_lum_scale = img->lum_scale[refframe] ; 
						fw_lum_shift = img->lum_shift[refframe] ; 
						for(ii=0;ii<8;ii++){ 
							for(jj=0;jj<8;jj++){ 
								tmp_block[ii][jj] = Clip1(((tmp_block[ii][jj]*fw_lum_scale+16)>>5) + fw_lum_shift); 
							} 
						} 
					} 
				} 
				else // !! for B MB one direction  shenyanfei cjw 
				{ 
					if(!pred_dir){  // !! forward shenyanfei  
						get_block (refframe, vec1_x, vec1_y, img, tmp_block,mref_fref[refframe]); 
						 
						if(((img->slice_weighting_flag == 1) && (img->mb_weighting_flag == 1)&&(img->weighting_prediction == 1)) 
							||((img->slice_weighting_flag == 1) && (img->mb_weighting_flag == 0))){ 
	 
							refframe=(img->picture_structure)?(refframe):(2*refframe);  //cjw 20060112 fw  
 
							fw_lum_scale = img->lum_scale[refframe] ; 
							fw_lum_shift = img->lum_shift[refframe] ; 
							 
							for(ii=0;ii<8;ii++){ 
								for(jj=0;jj<8;jj++){ 
									tmp_block[ii][jj] = Clip1(((tmp_block[ii][jj]*fw_lum_scale+16)>>5) + fw_lum_shift); 
								} 
							} 
						} 
					} 
					else{ // !! backward shenyanfei  
						get_block (refframe, vec1_x, vec1_y, img, tmp_block,mref_bref[refframe]); 
						 
						if(((img->slice_weighting_flag == 1) && (img->mb_weighting_flag == 1)&&(img->weighting_prediction == 1)) 
							||((img->slice_weighting_flag == 1) && (img->mb_weighting_flag == 0))){ 
							 
							refframe=(img->picture_structure)?(refframe+1):(2*refframe+1);  //cjw 20060112 bw 
 
							bw_lum_scale = img->lum_scale[refframe] ; 
							bw_lum_shift = img->lum_shift[refframe] ; 
							for(ii=0;ii<8;ii++){ 
								for(jj=0;jj<8;jj++){ 
									tmp_block[ii][jj] = Clip1(((tmp_block[ii][jj]*bw_lum_scale+16)>>5) + bw_lum_shift); 
								} 
							} 
						} 
					} 
				} 
				 
				for(ii=0;ii<8;ii++) 
					for(jj=0;jj<8;jj++)   
						img->mpr[ii+ioff][jj+joff] = tmp_block[ii][jj]; 
			} 
			else  // !! pred_dir == 2  
			{ 
				if (mv_mode != 0) 
				{ 
					//===== BI-DIRECTIONAL PREDICTION ===== 
					 
					fw_mv_array = img->fw_mv; 
					bw_mv_array = img->bw_mv; 
					 
					fw_refframe = img->fw_refFrArr[j4][i4];// fwd_ref_idx_to_refframe(img->fw_refFrArr[j4][i4]); 
					bw_refframe = img->bw_refFrArr[j4][i4];// bwd_ref_idx_to_refframe(img->bw_refFrArr[j4][i4]); 
					fw_ref_idx = img->fw_refFrArr[j4][i4]; 
					bw_ref_idx = img->bw_refFrArr[j4][i4]; 
					bw_ref_idx = bw_ref_idx; 
				} 
				else 
				{ 
					//===== DIRECT PREDICTION ===== 
					fw_mv_array = img->dfMV; 
					bw_mv_array = img->dbMV; 
					bw_refframe = 0; 
					 
					 
					if(refFrArr[j4][i4] == -1) // next P is intra mode 
					{ 
 
						for(hv=0; hv<2; hv++) 
						{ 
							img->dfMV[i4+BLOCK_SIZE][j4][hv]=img->dbMV[i4+BLOCK_SIZE][j4][hv]=0; 
							img->fw_mv[i4+BLOCK_SIZE][j4][hv]=img->bw_mv[i4+BLOCK_SIZE][j4][hv]=0;                     
						} 
						//sw 
						img->fw_refFrArr[j4][i4]=0; 
						img->bw_refFrArr[j4][i4]=0; 
									 
						SetMotionVectorPredictor(img,&(img->fw_mv[i4+BLOCK_SIZE][j4][0]), 
						  &(img->fw_mv[i4+BLOCK_SIZE][j4][1]),0,img->fw_refFrArr,  
						  img->fw_mv,0,0,16,16, 0, 1); 
						SetMotionVectorPredictor(img,&(img->bw_mv[i4+BLOCK_SIZE][j4][0]), 
						  &(img->bw_mv[i4+BLOCK_SIZE][j4][1]),0,img->bw_refFrArr,  
						  img->bw_mv,0,0,16,16, -1, 1); 
						for(hv=0; hv<2; hv++) 
						{ 
						  img->dfMV[i4+BLOCK_SIZE][j4][hv]=img->fw_mv[i4+BLOCK_SIZE][j4][hv]; 
						  img->dbMV[i4+BLOCK_SIZE][j4][hv]=img->bw_mv[i4+BLOCK_SIZE][j4][hv];			 
						} 
						 
						fw_refframe = 0; 
						fw_ref_idx = 0; 
					} 
					else // next P is skip or inter mode 
					{   
						refframe = refFrArr[j4][i4]; 
						 
						fw_ref_idx = refframe; 
						frame_no_next_P =2*img->imgtr_next_P; 
						 
//						frame_no_B = 2*img->tr;            // Commented by Xiaozhen ZHENG, 2007.05.01 
						frame_no_B = 2*img->pic_distance;  // Added by Xiaozhen ZHENG, 2007.05.01 
						delta_P = 2*(img->imgtr_next_P - img->imgtr_last_P); 
						delta_P = (delta_P + 512)%512;            // Added by Xiaozhen ZHENG,2007.05.01 
						 
						iTRp = (refframe+1)*delta_P; 
						iTRb = iTRp - (frame_no_next_P - frame_no_B); 
						 
						if(!img->picture_structure) 
						{ 
							if (img->current_mb_nr_fld < img->PicSizeInMbs) //top field 
								scale_refframe = 	refframe == 0 ? 0 : 1; 
							else 
								scale_refframe = 	refframe == 1 ? 1 : 2;  
						} 
						else 
							scale_refframe = 0; 
						 
						if(img->picture_structure)  
						{ 
							iTRp = (refframe+1)*delta_P; 
							iTRp1 = (scale_refframe+1)*delta_P; 
						}else 
						{ 
							if (img->current_mb_nr_fld < img->PicSizeInMbs) //top field 
							{ 
								iTRp = delta_P*(refframe/2+1)-(refframe+1)%2;  //the lates backward reference 
								iTRp1 = delta_P*(scale_refframe/2+1)-(scale_refframe+1)%2;  //the lates backward reference 
								bw_ref = 0; 
							} 
							else 
							{ 
								iTRp = 1 + delta_P*((refframe+1)/2)-refframe%2; 
								iTRp1 = 1 + delta_P*((scale_refframe+1)/2)-scale_refframe%2; 
								bw_ref = 1; 
							}	 
						} 
						iTRd = frame_no_next_P - frame_no_B; 
						if(img->picture_structure)  
						{ 
							iTRb = iTRp1 - (frame_no_next_P - frame_no_B); 
						}else 
						{ 
							iTRb = iTRp1 - (frame_no_next_P - frame_no_B); 
							if (img->current_mb_nr_fld >= img->PicSizeInMbs) //top field 
								scale_refframe --; 
						}				 
						// Added by Xiaozhen ZHENG, 2007.05.01 
						iTRp  = (iTRp  + 512)%512; 
						iTRp1 = (iTRp1 + 512)%512; 
						iTRd  = (iTRd  + 512)%512; 
						iTRb  = (iTRb  + 512)%512; 
						// Added by Xiaozhen ZHENG, 2007.05.01 
						 
						if(img->mv[i4+4][j4][0] < 0) 
						{ 
							img->dfMV[i4+BLOCK_SIZE][j4][0] = -(((16384/iTRp)*(1-iTRb*img->mv[i4+4][j4][0])-1)>>14); 
							img->dbMV[i4+BLOCK_SIZE][j4][0] = ((16384/iTRp)*(1-iTRd*img->mv[i4+4][j4][0])-1)>>14; 
						} 
						else 
						{ 
							img->dfMV[i4+BLOCK_SIZE][j4][0] = ((16384/iTRp)*(1+iTRb*img->mv[i4+4][j4][0])-1)>>14; 
							img->dbMV[i4+BLOCK_SIZE][j4][0] = -(((16384/iTRp)*(1+iTRd*img->mv[i4+4][j4][0])-1)>>14); 
						} 
						 
						if(img->mv[i4+4][j4][1] < 0) 
						{ 
							img->dfMV[i4+BLOCK_SIZE][j4][1] = -(((16384/iTRp)*(1-iTRb*img->mv[i4+4][j4][1])-1)>>14); 
							img->dbMV[i4+BLOCK_SIZE][j4][1] = ((16384/iTRp)*(1-iTRd*img->mv[i4+4][j4][1])-1)>>14; 
						} 
						else 
						{ 
							img->dfMV[i4+BLOCK_SIZE][j4][1] = ((16384/iTRp)*(1+iTRb*img->mv[i4+4][j4][1])-1)>>14; 
							img->dbMV[i4+BLOCK_SIZE][j4][1] = -(((16384/iTRp)*(1+iTRd*img->mv[i4+4][j4][1])-1)>>14); 
						} 
						 
						if(!img->picture_structure) 
						{ 
							fw_refframe = scale_refframe;  // DIRECT 
							fw_ref_idx = max(0,scale_refframe); 
							img->fw_refFrArr[j4][i4]=scale_refframe; 
						} 
						else 
						{ 
							fw_refframe = 0;  // DIRECT 
							fw_ref_idx = max(0,refFrArr[j4][i4]); 
							img->fw_refFrArr[j4][i4]=0; 
						} 
						 
						 
						img->fw_mv[i4+BLOCK_SIZE][j4][0]=img->dfMV[i4+BLOCK_SIZE][j4][0]; 
						img->fw_mv[i4+BLOCK_SIZE][j4][1]=img->dfMV[i4+BLOCK_SIZE][j4][1]; 
						img->bw_mv[i4+BLOCK_SIZE][j4][0]=img->dbMV[i4+BLOCK_SIZE][j4][0]; 
						img->bw_mv[i4+BLOCK_SIZE][j4][1]=img->dbMV[i4+BLOCK_SIZE][j4][1]; 
						 
						if(img->picture_structure) 
							img->bw_refFrArr[j4][i4]=0; 
						else 
							bw_refframe = img->bw_refFrArr[j4][i4]=bw_ref; 
					} 
          }     
					//if ((progressive_sequence||progressive_frame)&&img->picture_structure)           
					 
          vec1_x = i4*8*mv_mul + fw_mv_array[i4+BLOCK_SIZE][j4][0]; 
          vec1_y = j4*8*mv_mul + fw_mv_array[i4+BLOCK_SIZE][j4][1]; 
          vec2_x = i4*8*mv_mul + bw_mv_array[i4+BLOCK_SIZE][j4][0]; 
          vec2_y = j4*8*mv_mul + bw_mv_array[i4+BLOCK_SIZE][j4][1]; 
           
					// !! bidirection prediction shenyanfei  
		  get_block (fw_refframe, vec1_x, vec1_y, img, tmp_block,mref_fref[fw_refframe]); 
          get_block (bw_refframe, vec2_x, vec2_y, img, tmp_blockbw,mref_bref[bw_refframe]); 
		 //get_block (bw_refframe, vec2_x, vec2_y, img, tmp_blockbw,mref_bref[bw_refframe+1]); 
		 //by oliver 0502 
				 
		  //if(((img->slice_weighting_flag == 1) && (img->mb_weighting_flag == 1)&&(img->weighting_prediction == 1)&&(mv_mode != 0)) 
		  if(((img->slice_weighting_flag == 1) && (img->mb_weighting_flag == 1)&&(img->weighting_prediction == 1)) //cjw20060321 
				||((img->slice_weighting_flag == 1) && (img->mb_weighting_flag == 0))){ 
 
						fw_refframe=(img->picture_structure)?(fw_refframe):(2*fw_refframe);  //cjw 20060112 fw  
						bw_refframe=(img->picture_structure)?(bw_refframe+1):(2*bw_refframe+1);  //cjw 20060112 bw 
 
						fw_lum_scale = img->lum_scale[fw_refframe] ; 
						fw_lum_shift = img->lum_shift[fw_refframe] ; 
						bw_lum_scale = img->lum_scale[bw_refframe] ; 
						bw_lum_shift = img->lum_shift[bw_refframe] ; 
 
						for(ii=0;ii<8;ii++){ 
							for(jj=0;jj<8;jj++){ 
								tmp_block[ii][jj] =Clip1(((tmp_block[ii][jj]*fw_lum_scale+16)>>5) + fw_lum_shift); 
							} 
						} 
					 
						for(ii=0;ii<8;ii++){ 
							for(jj=0;jj<8;jj++){ 
								tmp_blockbw[ii][jj] =Clip1(((tmp_blockbw[ii][jj]*bw_lum_scale+16)>>5) + bw_lum_shift); 
							} 
						} 
					} 
					 
          for(ii=0;ii<8;ii++) 
            for(jj=0;jj<8;jj++)   
              img->mpr[ii+ioff][jj+joff] = (tmp_block[ii][jj]+tmp_blockbw[ii][jj]+1)/2; 
						 
        } 
    } 
     
    get_curr_blk (block8x8, img, curr_blk); 
     
    if (currMB->b8mode[block8x8]!=IBLOCK)//((IS_INTER (currMB) && mv_mode!=IBLOCK)) 
    { 
		idct_dequant_B8 (block8x8, currMB->qp-MIN_QP, curr_blk, img); 
    } 
    else 
    { 
      //intrapred creates the intraprediction in the array img->mpr[x][y] at the location corresponding to the position within the 16x16 MB. 
      tmp = intrapred( img, (img->mb_x<<4)+((block8x8&1)<<3), 
        (img->mb_y<<4)+((block8x8&2)<<2)); 
      if ( tmp == SEARCH_SYNC)  /* make 4x4 prediction block mpr from given prediction img->mb_mode */ 
        return SEARCH_SYNC;                   /* bit error */ 
 
    	idct_dequant_B8 (block8x8, currMB->qp-MIN_QP, curr_blk, img); 
			 
    } 
  } 
	 
  // chroma decoding ******************************************************* 
  for(uv=0;uv<2;uv++) 
  { 
    intra_prediction = IS_INTRA (currMB); 
     
		if (intra_prediction) 
		{ 
			if (uv==0) 
			{ 
				if(mb_available_up) 
				{ 
					for(x=0;xpix_c_y-1][img->pix_c_x+x]; 
					 
				/* 
					for(x=0;xpix_c_y-1][img->pix_c_x+bs_x+x]; 
					} 
				else{ 
					 for(x=0;xpix_c_y-1][img->pix_c_x]; 
				} 
				if(mb_available_left) 
				{ 
					for(y=0;ypix_c_y+y][img->pix_c_x-1]; 
					 
					for(y=0;ypix_c_y][img->pix_c_x-1]; 
				} 
				if(mb_available_up&&mb_available_left) 
					EPU[0]=imgUV[uv][img->pix_c_y-1][img->pix_c_x-1]; 
				 
				//lowpass (Those emlements that are not needed will not disturb) 
				last_pix=EPU[-8]; 
				for(i=-8;i<=8;i++) 
				{ 
					new_pix=( last_pix + (EPU[i]<<1) + EPU[i+1] + 2 )>>2; 
					last_pix=EPU[i]; 
					EPU[i]=(unsigned char)new_pix; 
				} 
			} 
			 
			 
			if (uv==1) 
			{ 
				if(mb_available_up) 
				{ 
					for(x=0;xpix_c_y-1][img->pix_c_x+x]; 
					 
/*					for(x=0;xpix_c_y-1][img->pix_c_x+bs_x+x]; 
					} 
					else{ 
					 for(x=0;xpix_c_y-1][img->pix_c_x]; 
				} 
				if(mb_available_left) 
				{ 
					for(y=0;ypix_c_y+y][img->pix_c_x-1]; 
					 
					for(y=0;ypix_c_y][img->pix_c_x-1]; 
				} 
				if(mb_available_up&&mb_available_left) 
					EPV[0]=imgUV[uv][img->pix_c_y-1][img->pix_c_x-1]; 
				 
				//lowpass (Those emlements that are not needed will not disturb) 
				last_pix=EPV[-8]; 
				for(i=-8;i<=8;i++) 
				{ 
					new_pix=( last_pix + (EPV[i]<<1) + EPV[i+1] + 2 )>>2; 
					last_pix=EPV[i]; 
					EPV[i]=(unsigned char)new_pix; 
				} 
			} 
		} 
		 
    for (j=4;j<6;j++) 
    { 
      joff=(j-4)*4; 
      j4=img->pix_c_y+joff; 
			 
      for(i=0;i<2;i++) 
      { 
        ioff=i*4; 
        i4=img->pix_c_x+ioff; 
         
        mv_mode  = currMB->b8mode[2*(j-4)+i]; 
        pred_dir = currMB->b8pdir[2*(j-4)+i]; 
         
        // PREDICTION 
        if (currMB->mb_type==I4MB) 
        { 
          //--- INTRA PREDICTION --- 
          int pred; 
          int ih, iv, ib, ic, iaa; 
           
          switch (currMB->c_ipred_mode) 
          { 
          case DC_PRED_8: 
				if (uv==0) 
				{ 
					if      (!mb_available_up && !mb_available_left)   
						for (ii=0; ii<4; ii++) 
							for (jj=0; jj<4; jj++) 
							{ 
								img->mpr[ii+ioff][jj+joff]=128; 
							}  
					if      (mb_available_up && !mb_available_left)   
						for (ii=0; ii<4; ii++) 
							for (jj=0; jj<4; jj++) 
							{ 
								img->mpr[ii+ioff][jj+joff]=EPU[1+ii+ioff]; 
							} 
					if      (!mb_available_up && mb_available_left) 
						for (ii=0; ii<4; ii++) 
							for (jj=0; jj<4; jj++) 
							{ 
								img->mpr[ii+ioff][jj+joff]=EPU[-1-jj-joff]; 
							} 
					if      (mb_available_up && mb_available_left)   
						for (ii=0; ii<4; ii++) 
							for (jj=0; jj<4; jj++) 
							{ 
								img->mpr[ii+ioff][jj+joff]=(EPU[1+ii+ioff]+EPU[-1-jj-joff])>>1; 
							}                
				} 
				if (uv==1) 
				{ 
					if      (!mb_available_up && !mb_available_left)   
						for (ii=0; ii<4; ii++) 
							for (jj=0; jj<4; jj++) 
							{ 
								img->mpr[ii+ioff][jj+joff]=128; 
							}  
					if      (mb_available_up && !mb_available_left) 
						for (ii=0; ii<4; ii++) 
							for (jj=0; jj<4; jj++) 
							{ 
								img->mpr[ii+ioff][jj+joff]=EPV[1+ii+ioff]; 
							} 
					if      (!mb_available_up && mb_available_left) 
						for (ii=0; ii<4; ii++) 
							for (jj=0; jj<4; jj++) 
							{ 
								img->mpr[ii+ioff][jj+joff]=EPV[-1-jj-joff]; 
							} 
					if      (mb_available_up && mb_available_left)   
						for (ii=0; ii<4; ii++) 
							for (jj=0; jj<4; jj++) 
							{ 
								img->mpr[ii+ioff][jj+joff]=(EPV[1+ii+ioff]+EPV[-1-jj-joff])>>1; 
							}                        
				} 
            break; 
          case HOR_PRED_8: 
            if (!mb_available_left) 
              error("unexpected HOR_PRED_8 chroma intra prediction mode",-1); 
            for (jj=0; jj<4; jj++) 
            { 
              pred = imgUV[uv][img->pix_c_y+jj+joff][img->pix_c_x-1]; 
              for (ii=0; ii<4; ii++) 
                img->mpr[ii+ioff][jj+joff]=pred; 
            } 
            break; 
          case VERT_PRED_8: 
            if (!mb_available_up) 
              error("unexpected VERT_PRED_8 chroma intra prediction mode",-1); 
            for (ii=0; ii<4; ii++) 
            { 
              pred = imgUV[uv][img->pix_c_y-1][img->pix_c_x+ii+ioff]; 
              for (jj=0; jj<4; jj++) 
                img->mpr[ii+ioff][jj+joff]=pred; 
            } 
            break; 
          case PLANE_8: 
            if (!mb_available_left || !mb_available_up) 
              error("unexpected PLANE_8 chroma intra prediction mode",-1); 
            ih=iv=0; 
            for (ii=1;ii<5;ii++) 
            { 
              ih += ii*(imgUV[uv][img->pix_c_y-1][img->pix_c_x+3+ii] - imgUV[uv][img->pix_c_y-1][img->pix_c_x+3-ii]); 
              iv += ii*(imgUV[uv][img->pix_c_y+3+ii][img->pix_c_x-1] - imgUV[uv][img->pix_c_y+3-ii][img->pix_c_x-1]); 
            } 
            ib=(17*ih+16)>>5; 
            ic=(17*iv+16)>>5; 
            iaa=16*(imgUV[uv][img->pix_c_y-1][img->pix_c_x+7]+imgUV[uv][img->pix_c_y+7][img->pix_c_x-1]); 
            for (ii=0; ii<4; ii++) 
              for (jj=0; jj<4; jj++) 
                img->mpr[ii+ioff][jj+joff]=max(0,min(255,(iaa+(ii+ioff-3)*ib +(jj+joff-3)*ic + 16)/32)); 
							break; 
          default: 
            error("illegal chroma intra prediction mode", 600); 
            break; 
          } 
        } 
        else if (pred_dir != 2)  
        { 
          //--- FORWARD/BACKWARD PREDICTION --- 
			if (!bframe) 
			{ 
				mv_array = img->mv; 
			} 
			else if (!pred_dir) 
			{ 
				mv_array = img->fw_mv; 
			} 
			else                 
			{ 
				mv_array = img->bw_mv; 
			} 
					 
          for(jj=0;jj<4;jj++) 
          { 
            jf=(j4+jj)/4; 
            for(ii=0;ii<4;ii++) 
            { 
              if1=(i4+ii)/4; 
               
              if (!bframe)         
              { 
                refframe = refFrArr[jf][if1]; 
                fw_ref_idx = refFrArr[jf][if1]; 
              } 
              else if (!pred_dir)  
              { 
                refframe = img->fw_refFrArr[jf][if1];// fwd_ref_idx_to_refframe(img->fw_refFrArr[jf][if1]); 
                fw_ref_idx = img->fw_refFrArr[jf][if1]; 
              } 
              else  
              { 
                refframe = img->bw_refFrArr[jf][if1];// bwd_ref_idx_to_refframe(img->bw_refFrArr[jf][if1]); 
                bw_ref_idx = img->bw_refFrArr[jf][if1]; 
                bw_ref_idx = bw_ref_idx; 
              } 
               
	          i1=(img->pix_c_x+ii+ioff)*f1+mv_array[if1+4][jf][0]; 
              j1=(img->pix_c_y+jj+joff)*f1+mv_array[if1+4][jf][1]; 
       					 
              ii0=max (0, min (i1/f1, img->width_cr-1)); 
              jj0=max (0, min (j1/f1, img->height_cr-1)); 
              ii1=max (0, min ((i1+f2)/f1, img->width_cr-1)); 
              jj1=max (0, min ((j1+f2)/f1, img->height_cr-1));				 
               
              if1=(i1 & f2); 
              jf1=(j1 & f2); 
              if0=f1-if1; 
              jf0=f1-jf1; 
               
              if(!bframe) 
              { 
                img->mpr[ii+ioff][jj+joff]=(if0*jf0*mcef[refframe][uv][jj0][ii0]+ 
                  if1*jf0*mcef[refframe][uv][jj0][ii1]+ 
                  if0*jf1*mcef[refframe][uv][jj1][ii0]+ 
                  if1*jf1*mcef[refframe][uv][jj1][ii1]+f4)/f3;	 
				 
			//cjw 20051219 Weighted Predition 
		      // if(((currMB->mb_type != 0 )&&(img->slice_weighting_flag == 1) &&  
		if(((img->slice_weighting_flag == 1) && //cjw20060321 
			(img->mb_weighting_flag == 1)&&(img->weighting_prediction == 1))     
				||((img->slice_weighting_flag == 1) && (img->mb_weighting_flag == 0))) 
			{					 
				fw_chrom_scale = img->chroma_scale[refframe]; 
				fw_chrom_shift = img->chroma_shift[refframe]; 
				 
				img->mpr[ii+ioff][jj+joff]=Clip1(((img->mpr[ii+ioff][jj+joff]*fw_chrom_scale+16)>>5)+fw_chrom_shift); 
			} 
              } 
              else 
              { 
			if(img->picture_structure) 
				refframe = 0; 
								 
                if(!pred_dir) //cjw 20051219 forward  
			{ 
				img->mpr[ii+ioff][jj+joff]=(if0*jf0*mcef_fref[refframe][uv][jj0][ii0]+ 
					  if1*jf0*mcef_fref[refframe][uv][jj0][ii1]+ 
					  if0*jf1*mcef_fref[refframe][uv][jj1][ii0]+ 
					  if1*jf1*mcef_fref[refframe][uv][jj1][ii1]+f4)/f3;		 
 
					//cjw 20051219 Weighted Predition 
			       if(((img->slice_weighting_flag == 1) &&(img->mb_weighting_flag == 1)&&(img->weighting_prediction == 1))  //cjw20060321 
					||((img->slice_weighting_flag == 1) && (img->mb_weighting_flag == 0))) 
					{			 
					    
					    refframe=(img->picture_structure)?(refframe):(2*refframe);  //cjw 20060112 fw  
 
					    fw_chrom_scale = img->chroma_scale[refframe]; 
					    fw_chrom_shift = img->chroma_shift[refframe]; 
				 
					    img->mpr[ii+ioff][jj+joff]=Clip1(((img->mpr[ii+ioff][jj+joff]*fw_chrom_scale+16)>>5)+fw_chrom_shift); 
					} 
				} 
                else   //cjw 20051219 backward   
				{ 
				  img->mpr[ii+ioff][jj+joff]=(if0*jf0*mcef_bref[refframe][uv][jj0][ii0]+ 
				  if1*jf0*mcef_bref[refframe][uv][jj0][ii1]+ 
				  if0*jf1*mcef_bref[refframe][uv][jj1][ii0]+ 
				  if1*jf1*mcef_bref[refframe][uv][jj1][ii1]+f4)/f3;		 
				   
				  //cjw 20051219 Weighted Predition 
			       if(((img->slice_weighting_flag == 1) &&(img->mb_weighting_flag == 1)&&(img->weighting_prediction == 1)) 
						||((img->slice_weighting_flag == 1) && (img->mb_weighting_flag == 0))) 
					{					 
						 
					    refframe=(img->picture_structure)?(refframe+1):(2*refframe+1);  //cjw 20060112 bw 
						 
					    fw_chrom_scale = img->chroma_scale[refframe]; 
					    fw_chrom_shift = img->chroma_shift[refframe]; 
				 
					    img->mpr[ii+ioff][jj+joff]=Clip1(((img->mpr[ii+ioff][jj+joff]*fw_chrom_scale+16)>>5)+fw_chrom_shift); 
					} 
				} 
              } 
            } 
          } 
        } 
        else // !! bidirection prediction 
        { 
          if (mv_mode != 0) 
          { 
            //===== BI-DIRECTIONAL PREDICTION ===== 
            fw_mv_array = img->fw_mv; 
            bw_mv_array = img->bw_mv; 
          } 
          else 
          { 
            //===== DIRECT PREDICTION ===== 
            fw_mv_array = img->dfMV; 
            bw_mv_array = img->dbMV; 
          } 
           
          for(jj=0;jj<4;jj++) 
          { 
            jf=(j4+jj)/4; 
            for(ii=0;ii<4;ii++) 
            { 
				ifx=(i4+ii)/4; 
				 
				direct_pdir = 2; 
				 
				if (mv_mode != 0) 
				{ 
					fw_refframe = img->fw_refFrArr[jf][ifx];// fwd_ref_idx_to_refframe(img->fw_refFrArr[jf][ifx]); 
					bw_refframe = img->bw_refFrArr[jf][ifx];//bwd_ref_idx_to_refframe(img->bw_refFrArr[jf][ifx]); 
					 
					fw_ref_idx = img->fw_refFrArr[jf][ifx]; 
					bw_ref_idx = img->bw_refFrArr[jf][ifx]; 
					bw_ref_idx = bw_ref_idx; 
				} 
				else 
				{	 
					fw_refframe = 0; 
					bw_refframe = 0; 
					 
					if(!img->picture_structure) 
					{ 
						fw_refframe = img->fw_refFrArr[jf][ifx]; 
						bw_refframe = img->bw_refFrArr[jf][ifx]; 
					} 
				} 
												 
              i1=(img->pix_c_x+ii+ioff)*f1+fw_mv_array[ifx+4][jf][0]; 
              j1=(img->pix_c_y+jj+joff)*f1+fw_mv_array[ifx+4][jf][1]; 
               
              ii0=max (0, min (i1/f1, img->width_cr-1)); 
              jj0=max (0, min (j1/f1, img->height_cr-1)); 
              ii1=max (0, min ((i1+f2)/f1, img->width_cr-1)); 
              jj1=max (0, min ((j1+f2)/f1, img->height_cr-1)); 
							 
							if1=(i1 & f2); 
              jf1=(j1 & f2); 
              if0=f1-if1; 
              jf0=f1-jf1; 
               
              fw_pred=(if0*jf0*mcef_fref[fw_refframe][uv][jj0][ii0]+ 
                if1*jf0*mcef_fref[fw_refframe][uv][jj0][ii1]+ 
                if0*jf1*mcef_fref[fw_refframe][uv][jj1][ii0]+ 
                if1*jf1*mcef_fref[fw_refframe][uv][jj1][ii1]+f4)/f3; 
							 
              i1=(img->pix_c_x+ii+ioff)*f1+bw_mv_array[ifx+4][jf][0]; 
              j1=(img->pix_c_y+jj+joff)*f1+bw_mv_array[ifx+4][jf][1]; 
							 
              ii0=max (0, min (i1/f1, img->width_cr-1)); 
              jj0=max (0, min (j1/f1, img->height_cr-1)); 
              ii1=max (0, min ((i1+f2)/f1, img->width_cr-1)); 
              jj1=max (0, min ((j1+f2)/f1, img->height_cr-1)); 
               
              if1=(i1 & f2); 
              jf1=(j1 & f2); 
              if0=f1-if1; 
              jf0=f1-jf1; 
               
              bw_pred=(if0*jf0*mcef_bref[bw_refframe][uv][jj0][ii0]+ 
                if1*jf0*mcef_bref[bw_refframe][uv][jj0][ii1]+ 
                if0*jf1*mcef_bref[bw_refframe][uv][jj1][ii0]+ 
                if1*jf1*mcef_bref[bw_refframe][uv][jj1][ii1]+f4)/f3; 
               
              img->mpr[ii+ioff][jj+joff]=(fw_pred + bw_pred + 1 )/2;   //slice_weighting_flag == 1) &&(img->mb_weighting_flag == 1)&&(img->weighting_prediction == 1)&&(mv_mode != 0)) 
			     if(((img->slice_weighting_flag == 1) &&(img->mb_weighting_flag == 1)&&(img->weighting_prediction == 1))   //cjw 20060321 
					||((img->slice_weighting_flag == 1) && (img->mb_weighting_flag == 0))) 
				{					 
					 
				    fw_refframe=(img->picture_structure)?(fw_refframe):(2*fw_refframe);  //cjw 20060112 fw  
				    bw_refframe=(img->picture_structure)?(bw_refframe+1):(2*bw_refframe+1);  //cjw 20060112 bw 
 
					fw_chrom_scale = img->chroma_scale[fw_refframe]; 
					fw_chrom_shift = img->chroma_shift[fw_refframe]; 
					 
					bw_chrom_scale = img->chroma_scale[bw_refframe]; 
					bw_chrom_shift = img->chroma_shift[bw_refframe]; 
					 
					img->mpr[ii+ioff][jj+joff]=((Clip1(((fw_pred*fw_chrom_scale+16)>>5)+fw_chrom_shift) 
 							  +Clip1(((bw_pred*bw_chrom_scale+16)>>5)+bw_chrom_shift))+1)/2; 
 
				} 
            } 
          } 
        } 
      } 
    } 
		 
     get_curr_blk (4+uv, img, curr_blk); 
		 
     idct_dequant_B8 (4+uv, QP_SCALE_CR[currMB->qp-MIN_QP], curr_blk, img); 
  } 
	 
  return 0; 
}