www.pudn.com > rm52f.rar > image.c


/* 
*********************************************************************** 
* COPYRIGHT AND WARRANTY INFORMATION 
* 
* Copyright 2003, Advanced Audio Video Coding Standard, Part II 
* 
* DISCLAIMER OF WARRANTY 
* 
* These software programs are available to the users without any 
* license fee or royalty on an "as is" basis. The AVS disclaims 
* any and all warranties, whether express, implied, or statutory, 
* including any implied warranties of merchantability or of fitness 
* for a particular purpose. In no event shall the contributors or  
* the AVS be liable for any incidental, punitive, or consequential 
* damages of any kind whatsoever arising from the use of this program. 
* 
* This disclaimer of warranty extends to the user of this program 
* and user's customers, employees, agents, transferees, successors, 
* and assigns. 
* 
* The AVS does not represent or warrant that the program furnished 
* hereunder are free of infringement of any third-party patents. 
* Commercial implementations of AVS, including shareware, may be 
* subject to royalty fees to patent holders. Information regarding 
* the AVS patent policy is available from the AVS Web site at 
* http://www.avs.org.cn 
* 
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY. 
************************************************************************ 
*/ 
 
/* 
************************************************************************************* 
* File name: image.c 
* Function: Decode a Slice 
* 
************************************************************************************* 
*/ 
 
 
#include "contributors.h" 
 
#include  
#include  
#include  
#include  
#include  
#include  
 
#include "global.h" 
#include "mbuffer.h" 
#include "header.h" 
#include "annexb.h" 
#include "vlc.h" 
#include "memalloc.h" 
 
 
static void rotate_buffer (); 
void store_field_MV(struct img_par *img); 
void report_frame(struct snr_par    *snr,int tmp_time); 
void copy2buffer(struct img_par *img, struct inp_par *inp,int bot); 
void replace2buffer(struct img_par *img, struct inp_par *inp,int bot); 
 
 
extern struct img_par *erc_img; 
 
int *last_P_no; 
int *last_P_no_frm; 
 
 
/* 
************************************************************************* 
* Function:decodes one I- or P-frame 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
int decode_one_frame(struct img_par *img,struct inp_par *inp, struct snr_par *snr) 
{ 
  int current_header; 
 
  time_t ltime1;                  // for time measurement 
  time_t ltime2; 
 
#ifdef WIN32 
  struct _timeb tstruct1; 
  struct _timeb tstruct2; 
#else 
  struct timeb tstruct1; 
  struct timeb tstruct2; 
#endif 
 
  int tmp_time;                   // time used by decoding the last frame 
  int i; 
 
#ifdef WIN32 
  _ftime (&tstruct1);             // start time ms 
#else 
  ftime (&tstruct1);              // start time ms 
#endif 
  time( <ime1 );                // start time s 
 
  singlefactor =(float)((Bframe_ctr & 0x01) ? 0.5 : 2); 
 
  if(!img->picture_structure) 
	singlefactor = 1; 
   
  img->current_mb_nr = -4711; // initialized to an impossible value for debugging -- correct value is taken from slice header 
   
  second_IField=0;  //cjw 20051230  
   
  current_header = Header(); 
   
  if (current_header == EOS) 
    return EOS; 
   
  img->current_mb_nr = 0; 
   
	init_frame(img, inp); 
	if (img->picture_structure) 
  	{ 
		img->types = img->type;   // jlzheng 7.15 
		picture_data(img, inp); 
			 
		if (img->type != B_IMG&&!progressive_sequence) 
		{    
			img->height >>= 1; 
			img->height_cr >>= 1; 
			init_top_buffer(); 
			split_field_top(); 
			Update_Picture_top_field(); 
			init_bot_buffer(); 
			split_field_bot(); 
			Update_Picture_bot_field(); 
			img->height <<= 1; 
			img->height_cr <<= 1; 
		} 
		imgY = imgY_frm; 
		imgUV = imgUV_frm; 
	} 
	else 
	{ 
		img->height         = vertical_size/2; 
		img->height_cr      = (img->height>>1); 
		img->PicWidthInMbs  = img->width/MB_BLOCK_SIZE; 
		img->PicHeightInMbs = img->height/MB_BLOCK_SIZE; 
	    img->PicSizeInMbs   = img->PicWidthInMbs * img->PicHeightInMbs; 
	    img->types = img->type; 
		 
		init_top(img,inp); 
	 
	    top_field(img,inp); 
		if(img->type!=B_IMG) 
		{ 
		      Update_Picture_top_field(); 
		} 
		else 
		{ 
			for (i=0; iheight; i++) 
			{ 
				memcpy(imgY_frm[i*2], imgY_top[i], img->width);     // top field 
			} 
			 
			for (i=0; iheight_cr; i++) 
			{ 
				memcpy(imgUV_frm[0][i*2], imgUV_top[0][i], img->width_cr); 
				memcpy(imgUV_frm[1][i*2], imgUV_top[1][i], img->width_cr); 
			} 
		} 
 
		if(img->type == I_IMG) 
		{ 
	    	img->type = P_IMG;	 
			second_IField=1;		       //cjw 20051230 
		}                                    // delete by jlzheng 7.21 
 
		init_bot(img,inp); 
		bot_field(img,inp); 
 
		if(img->type!=B_IMG) 
    		{       
		  Update_Picture_bot_field(); 
		} 
		else 
		{ 
			for (i=0; iheight; i++) 
			{ 
				memcpy(imgY_frm[i*2 + 1], imgY_bot[i], img->width); // bottom field 
			} 
			 
			for (i=0; iheight_cr; i++) 
			{ 
				memcpy(imgUV_frm[0][i*2 + 1], imgUV_bot[0][i], img->width_cr); 
				memcpy(imgUV_frm[1][i*2 + 1], imgUV_bot[1][i], img->width_cr); 
			} 
		} 
	    init_frame_buffer(); 
		if(img->type!=B_IMG) 
		  combine_field(img); 
		 
		imgY = imgY_frm; 
		imgUV = imgUV_frm; 
	} 
 
	img->height = vertical_size; 
	img->height_cr = vertical_size/2; 
	img->PicWidthInMbs  = img->width/MB_BLOCK_SIZE; 
	img->PicHeightInMbs = img->height/MB_BLOCK_SIZE; 
	img->PicSizeInMbs   = img->PicWidthInMbs * img->PicHeightInMbs; 
	 
	if(!progressive_sequence) 
	{ 
		store_field_MV(img); 
	} 
 
	frame_postprocessing(img); 
 
	if (p_ref) 
	    find_snr(snr,img,p_ref);      // if ref sequence exist 
 
#ifdef WIN32 
	 _ftime (&tstruct2);   // end time ms 
#else 
	 ftime (&tstruct2);    // end time ms 
#endif 
   
	 time( <ime2 );                                // end time sec 
	 tmp_time=(ltime2*1000+tstruct2.millitm) - (ltime1*1000+tstruct1.millitm); 
	 tot_time=tot_time + tmp_time; 
 
	 if(img->type == I_IMG) // I picture 
	    fprintf(stdout,"%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\n", 
        	frame_no, img->tr, img->qp,snr->snr_y,snr->snr_u,snr->snr_v,tmp_time); 
  	 else if(img->type == P_IMG) // P pictures 
  	 { 
	    if(frame_no == 0) 
		fprintf(stdout,"%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\n", 
       	      frame_no, img->tr, img->qp,snr->snr_y,snr->snr_u,snr->snr_v,tmp_time);   //jlzheng 7.3 
	    else 
	        fprintf(stdout,"%3d(P)  %3d %5d %7.4f %7.4f %7.4f %5d\n", 
	    frame_no, img->tr, img->qp,snr->snr_y,snr->snr_u,snr->snr_v,tmp_time); 
	 } 
	 else // B pictures 
	    fprintf(stdout,"%3d(B)  %3d %5d %7.4f %7.4f %7.4f %5d\n", 
        	frame_no, img->tr, img->qp,snr->snr_y,snr->snr_u,snr->snr_v,tmp_time); 
 
	 fflush(stdout); 
 
	report_frame(snr,tmp_time); 
 
	if(img->type == I_IMG || img->type == P_IMG) // I or P pictures 
	  { 
		copy_Pframe(img);  // imgY-->imgY_prev, imgUV-->imgUV_prev 
		Update_Picture_Buffers(); 
	  } 
	else // B pictures 
	    write_frame(img,p_out);         // write image to output YUV file 
 
//! TO 19.11.2001 Known Problem: for init_frame we have to know the picture type of the actual frame 
//! in case the first slice of the P-Frame following the I-Frame was lost we decode this P-Frame but//! do not write it because it was assumed to be an I-Frame in init_frame.So we force the decoder to 
//! guess the right picture type. This is a hack a should be removed by the time there is a clean 
//! solution where we do not have to know the picture type for the function init_frame. 
//! End TO 19.11.2001//Lou 
 
	  if(img->type == I_IMG || img->type == P_IMG)   // I or P pictures 
	    img->number++; 
	  else 
	    Bframe_ctr++;    // B pictures 
 
	  return (SOP); 
} 
 
/* 
************************************************************************* 
* Function: 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
void report_frame(struct snr_par    *snr,int tmp_time) 
{ 
    FILE *file; 
      file = fopen("stat.dat","at"); 
 
  if(img->type == I_IMG) // I picture 
    fprintf(file,"%3d(I)  %3d %5d %7.4f %7.4f %7.4f %5d\n", 
        frame_no, img->tr, img->qp,snr->snr_y,snr->snr_u,snr->snr_v,tmp_time); 
  else if(img->type == P_IMG) // P pictures 
    fprintf(file,"%3d(P)  %3d %5d %7.4f %7.4f %7.4f %5d\n", 
    frame_no, img->tr, img->qp,snr->snr_y,snr->snr_u,snr->snr_v,tmp_time); 
  else // B pictures 
    fprintf(file,"%3d(B)  %3d %5d %7.4f %7.4f %7.4f %5d\n", 
        frame_no, img->tr, img->qp,snr->snr_y,snr->snr_u,snr->snr_v,tmp_time); 
  fclose(file); 
} 
 
/* 
************************************************************************* 
* Function:Find PSNR for all three components.Compare decoded frame with 
      the original sequence. Read inp->jumpd frames to reflect frame skipping. 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void find_snr( 
  struct snr_par *snr,   //!< pointer to snr parameters 
  struct img_par *img,   //!< pointer to image parameters 
  FILE *p_ref)           //!< filestream to reference YUV file 
{ 
  int i,j; 
  int diff_y,diff_u,diff_v; 
  int uv; 
  int  status; 
   
  byte       diff; 
 
  snr->snr_y=0.0; 
  snr->snr_u=0.0; 
  snr->snr_v=0.0; 
 
  if(img->type==I_IMG || img->type==P_IMG) // I, P pictures 
    frame_no=img->tr; 
  else // B pictures 
  { 
    diff=nextP_tr-img->tr; 
    frame_no=(img->number-1)*P_interval-diff; 
  } 
 
  rewind(p_ref); 
  status = fseek (p_ref, frame_no*img->height*img->width*3/2, 0); 
  if (status != 0) 
  { 
    snprintf(errortext, ET_SIZE, "Error in seeking img->tr: %d", img->tr); 
    error(errortext, 500); 
  } 
  for (j=0; j < img->height; j++) 
    for (i=0; i < img->width; i++) 
    { 
      imgY_ref[j][i]=fgetc(p_ref); 
    } 
     
  for (uv=0; uv < 2; uv++) 
    for (j=0; j < img->height_cr ; j++) 
      for (i=0; i < img->width_cr; i++) 
        imgUV_ref[uv][j][i]=fgetc(p_ref); 
 
  img->quad[0]=0; 
  diff_y=0; 
  for (j=0; j < img->height; ++j) 
  { 
    for (i=0; i < img->width; ++i) 
    { 
      diff_y += img->quad[abs(imgY[j][i]-imgY_ref[j][i])]; 
       
      if(imgY[j][i]!=imgY_ref[j][i]) 
      { 
        int mb_nr; 
	// printf("error\n"); 
        mb_nr = (j/16)*(img->width/16)+i/16; 
         
        // printf("mb_nr is %d\n",mb_nr); 
      } 
    } 
  } 
 
  // Chroma 
  diff_u=0; 
  diff_v=0; 
 
  for (j=0; j < img->height_cr; ++j) 
  { 
    for (i=0; i < img->width_cr; ++i) 
    { 
      diff_u += img->quad[abs(imgUV_ref[0][j][i]-imgUV[0][j][i])]; 
      diff_v += img->quad[abs(imgUV_ref[1][j][i]-imgUV[1][j][i])]; 
      if(imgUV_ref[0][j][i]!=imgUV[0][j][i]) 
      { 
        int mb_nr; 
	// printf("error\n"); 
		 
        mb_nr = (j/16)*(img->width/16)+i/8; 
        // printf("mb_nr is %d\n",mb_nr); 
      } 
 
    } 
  } 
 
  // Collecting SNR statistics 
  if (diff_y != 0) 
    snr->snr_y=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)diff_y));        // luma snr for current frame 
  if (diff_u != 0) 
    snr->snr_u=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_u)));    //  chroma snr for current frame 
  if (diff_v != 0) 
    snr->snr_v=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_v)));    //  chroma snr for current frame 
 
  if (img->number == 0) // first 
  { 
    snr->snr_y1=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)diff_y));       // keep luma snr for first frame 
    snr->snr_u1=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_u)));   // keep chroma snr for first frame 
    snr->snr_v1=(float)(10*log10(65025*(float)(img->width)*(img->height)/(float)(4*diff_v)));   // keep chroma snr for first frame 
    snr->snr_ya=snr->snr_y1; 
    snr->snr_ua=snr->snr_u1; 
    snr->snr_va=snr->snr_v1; 
 
    if (diff_y == 0)    
      snr->snr_ya=50; // need to assign a reasonable large number so avg snr of entire sequece isn't infinite 
    if (diff_u == 0) 
      snr->snr_ua=50; 
    if (diff_v == 0) 
      snr->snr_va=50; 
  } 
  else 
  { 
    snr->snr_ya=(float)(snr->snr_ya*(img->number+Bframe_ctr)+snr->snr_y)/(img->number+Bframe_ctr+1); // average snr chroma for all frames 
    snr->snr_ua=(float)(snr->snr_ua*(img->number+Bframe_ctr)+snr->snr_u)/(img->number+Bframe_ctr+1); // average snr luma for all frames 
    snr->snr_va=(float)(snr->snr_va*(img->number+Bframe_ctr)+snr->snr_v)/(img->number+Bframe_ctr+1); // average snr luma for all frames 
  } 
} 
 
/* 
************************************************************************* 
* Function:Interpolation of 1/4 subpixel 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
void get_block(int ref_frame,int x_pos, int y_pos, struct img_par *img, int block[8][8], unsigned char **ref_pic) 
{ 
 
  int dx, dy; 
  int x, y; 
  int i, j; 
  int maxold_x,maxold_y; 
  int result; 
  int tmp_res[26][26]; 
  int tmp_res_2[26][26]; 
  static const int COEF_HALF[4] = { 
    -1, 5, 5, -1 
  }; 
  static const int COEF_QUART[4] = { 
    1, 7, 7, 1 
  }; 
 
    //    A  a  1  b  B 
    //    c  d  e  f 
    //    2  h  3  i 
    //    j  k  l  m 
    //    C           D 
 
  dx = x_pos&3; 
  dy = y_pos&3; 
  x_pos = (x_pos-dx)/4; 
  y_pos = (y_pos-dy)/4; 
  maxold_x = img->width-1; 
  maxold_y = img->height-1; 
 
 
  if (dx == 0 && dy == 0) {  //fullpel position: A 
    for (j = 0; j < B8_SIZE; j++) 
      for (i = 0; i < B8_SIZE; i++) 
        block[i][j] = ref_pic[max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i))]; 
  } 
  else  
  { /* other positions */ 
      if((dx==2) && (dy==0)){//horizonal 1/2 position: 1 
          for (j = 0; j < B8_SIZE; j++){ 
            for (i = 0; i < B8_SIZE; i++) { 
              for (result = 0, x = -1; x < 3; x++) 
                result += ref_pic[max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i+x))]*COEF_HALF[x+1]; 
              block[i][j] = max(0, min(255, (result+4)/8)); 
            } 
          } 
      } 
 
      else if(((dx==1) || (dx==3)) && (dy==0)){//horizonal 1/4 position: a and b 
         for (j = 0; j < B8_SIZE; j++) { 
            for (i = -1; i < B8_SIZE+1; i++) { 
 
              for (result = 0, x = -1; x < 3; x++) 
                result += ref_pic[max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i+x))]*COEF_HALF[x+1]; 
 
              tmp_res[j][2*(i+1)] = result; 
              tmp_res[j][2*(i+1)+1] = ref_pic[max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i+1))]*8; 
            } 
      	   } 
         for (j = 0; j < B8_SIZE; j++) { 
            for (i = 0; i < B8_SIZE; i++) { 
 
              for (result = 0, x = -1; x < 3; x++) 
                if(dx==1)//a 
                    result += tmp_res[j][2*i+x+1]*COEF_QUART[x+1]; 
                else//b 
                    result += tmp_res[j][2*i+x+2]*COEF_QUART[x+1]; 
 
              block[i][j] = max(0, min(255, (result+64)/128)); 
            } 
         } 
      } 
 
      else if((dy==2) && (dx==0)){//vertical 1/2 position: 2 
          for (j = 0; j < B8_SIZE; j++) { 
            for (i = 0; i < B8_SIZE; i++) { 
              for (result = 0, y = -1; y < 3; y++) 
                result += ref_pic[max(0,min(maxold_y,y_pos+j+y))][max(0,min(maxold_x,x_pos+i))]*COEF_HALF[y+1]; 
              block[i][j] = max(0, min(255, (result+4)/8)); 
            } 
          } 
      } 
 
      else if(((dy==1) || (dy==3)) && (dx==0)){//vertical 1/4 position: c and j 
          for (j = -1; j < B8_SIZE+1; j++) { 
            for (i = 0; i < B8_SIZE; i++) { 
 
              for (result = 0, y = -1; y < 3; y++) 
                result += ref_pic[max(0,min(maxold_y,y_pos+j+y))][max(0,min(maxold_x,x_pos+i))]*COEF_HALF[y+1]; 
 
              tmp_res[2*(j+1)][i] = result; 
              tmp_res[2*(j+1)+1][i] = ref_pic[max(0,min(maxold_y,y_pos+j+1))][max(0,min(maxold_x,x_pos+i))]*8; 
            } 
          } 
          for (j = 0; j < B8_SIZE; j++) { 
            for (i = 0; i < B8_SIZE; i++) { 
 
              for (result = 0, y = -1; y < 3; y++) 
                  if(dy==1)//c 
                      result += tmp_res[2*j+y+1][i]*COEF_QUART[y+1]; 
                  else//j 
                      result += tmp_res[2*j+y+2][i]*COEF_QUART[y+1]; 
 
              block[i][j] = max(0, min(255, (result+64)/128)); 
            } 
          } 
      } 
 
      else if((dx==2) && (dy==2)){//horizonal and vertical 1/2 position: 3 
          for (j = -1; j < B8_SIZE+2; j++) { 
            for (i = 0; i < B8_SIZE; i++) { 
		    
              for (result = 0, x = -1; x < 3; x++) 
                result += ref_pic[max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i+x))]*COEF_HALF[x+1]; 
 
              tmp_res[j+1][i] = result; 
            } 
          } 
          for (j = 0; j < B8_SIZE; j++) { 
            for (i = 0; i < B8_SIZE; i++) { 
 
              for (result = 0, y = -1; y < 3; y++) 
                result += tmp_res[j+y+1][i]*COEF_HALF[y+1]; 
 
              block[i][j] = max(0, min(255, (result+32)/64)); 
            } 
          } 
      } 
 
      else if(((dx==1) || (dx==3)) && dy==2){//horizonal and vertical 1/4 position: h and i 
          for (j = 0; j < B8_SIZE; j++) { 
            for (i = -2; i < B8_SIZE+3; i++) { 
		     
              for (result = 0, y = -1; y < 3; y++) 
                result += ref_pic[max(0,min(maxold_y,y_pos+j+y))][max(0,min(maxold_x,x_pos+i))]*COEF_HALF[y+1]; 
 
              tmp_res[j][i+2] = result; 
            } 
          } 
          for (j = 0; j < B8_SIZE; j++) { 
            for (i = 0; i < B8_SIZE+2; i++) { 
 
              for (result = 0, x = -1; x < 3; x++) 
                result += tmp_res[j][i+1+x]*COEF_HALF[x+1]; 
 
              tmp_res_2[j][2*i] = result; 
              tmp_res_2[j][2*i+1] = tmp_res[j][i+2]*8; 
            } 
          } 
          for (j = 0; j < B8_SIZE; j++) { 
            for (i = 0; i < B8_SIZE; i++) { 
 
              for (result = 0, x = -1; x < 3; x++) 
                  if(dx==1)//h 
                      result += tmp_res_2[j][2*i+x+1]*COEF_QUART[x+1]; 
                  else 
                      result += tmp_res_2[j][2*i+x+2]*COEF_QUART[x+1]; 
 
              block[i][j] = max(0, min(255, (result+512)/1024)); 
            } 
          } 
      } 
 
      else if(((dy==1) || (dy==3)) && (dx==2)){//vertical and horizonal 1/4 position: e and l 
          for (j = -2; j < B8_SIZE+3; j++) { 
            for (i = 0; i < B8_SIZE; i++) { 
		     
              for (result = 0, x = -1; x < 3; x++) 
                result += ref_pic[max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i+x))]*COEF_HALF[x+1]; 
 
              tmp_res[j+2][i] =result; 
            } 
          } 
          for (j = 0; j < B8_SIZE+2; j++) { 
            for (i = 0; i < B8_SIZE; i++) { 
 
              for (result = 0, y = -1; y < 3; y++) 
                result += tmp_res[j+y+1][i]*COEF_HALF[y+1]; 
 
              tmp_res_2[2*j][i] = result; 
              tmp_res_2[2*j+1][i] =  tmp_res[j+2][i]*8; 
            } 
          } 
          for (j = 0; j < B8_SIZE; j++) { 
            for (i = 0; i < B8_SIZE; i++) { 
 
              for (result = 0, y = -1; y < 3; y++) 
                  if(dy==1)//e 
                      result += tmp_res_2[2*j+y+1][i]*COEF_QUART[y+1]; 
                  else//l 
                      result += tmp_res_2[2*j+y+2][i]*COEF_QUART[y+1]; 
 
              block[i][j] = max(0, min(255, (result+512)/1024)); 
            } 
          } 
      } 
 
      else{//Diagonal 1/4 position : d, f, k and m 
          for (j = -1; j < B8_SIZE+2; j++) { 
            for (i = 0; i < B8_SIZE; i++) { 
 
              for (result = 0, x = -1; x < 3; x++) 
                result += ref_pic[max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i+x))]*COEF_HALF[x+1]; 
 
              tmp_res[j+1][i] = result; 
            } 
          } 
          for (j = 0; j < B8_SIZE; j++) { 
            for (i = 0; i < B8_SIZE; i++) { 
 
              for (result = 0, y = -1; y < 3; y++) 
                result += tmp_res[j+y+1][i]*COEF_HALF[y+1]; 
 
              tmp_res_2[j][i] = result; 
            } 
          } 
          for (j = 0; j < B8_SIZE; j++) { 
            for (i = 0; i < B8_SIZE; i++) { 
                if((dx==1) && (dy==1))//d 
                    result = tmp_res_2[j][i]+ref_pic[max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i))]*64; 
                else if((dx==3) && (dy==1))//f 
                    result = tmp_res_2[j][i]+ref_pic[max(0,min(maxold_y,y_pos+j))][max(0,min(maxold_x,x_pos+i+1))]*64; 
                else if((dx==1) && (dy==3))//k 
                    result = tmp_res_2[j][i]+ref_pic[max(0,min(maxold_y,y_pos+j+1))][max(0,min(maxold_x,x_pos+i))]*64; 
                else if((dx==3) && (dy==3))//m 
                    result = tmp_res_2[j][i]+ref_pic[max(0,min(maxold_y,y_pos+j+1))][max(0,min(maxold_x,x_pos+i+1))]*64; 
              block[i][j] = max(0, min(255, (result+64)/128)); 
            } 
          } 
      } 
   } 
} 
 
/* 
************************************************************************* 
* Function:Reads new slice from bit_stream 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
int Header() 
{ 
	unsigned char *Buf; 
	int startcodepos,length;  
	 
	if ((Buf = (char*)calloc (MAX_CODED_FRAME_SIZE , sizeof(char))) == NULL) 
		no_mem_exit("GetAnnexbNALU: Buf"); 
 
	while (1) 
	{ 
		StartCodePosition = GetOneUnit(Buf,&startcodepos,&length);    //jlzheng  7.5 
		 
		switch(Buf[startcodepos]) 
		{ 
		case SEQUENCE_HEADER_CODE: 
			SequenceHeader(Buf,startcodepos,length); 
				 
			break; 
         
		case RESERVED_CODE1: //060426wb 
			 break; 
		case RESERVED_CODE2: //060426wb 
			break; 
			  
		case EXTENSION_START_CODE: 
			extension_data(Buf,startcodepos,length); 
			break; 
		case USER_DATA_START_CODE: 
			user_data(Buf,startcodepos,length); 
			break; 
	    	case I_PICTURE_START_CODE: 
			I_Picture_Header(Buf,startcodepos,length); 
			calc_picture_distance(img); 
			     free(Buf); 
                        return SOP; 
		case PB_PICTURE_START_CODE: 
			PB_Picture_Header(Buf,startcodepos,length); 
			calc_picture_distance(img); 
			    free(Buf); 
				return SOP; 
		case SEQUENCE_END_CODE: 
			free(Buf); 
			return EOS; 
			break; 
		default: 
			printf("Can't find start code"); 
			free(Buf); 
			return EOS; 
		} 
	} 
		 
		 
 
 
} 
 
/* 
************************************************************************* 
* Function:Initializes the parameters for a new frame 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
 
void init_frame(struct img_par *img, struct inp_par *inp) 
{ 
  static int first_P = TRUE; 
  int i,j; 
 
 
  img->top_bot = -1; // Yulj 2004.07.20 
  last_P_no = last_P_no_frm; 
  nextP_tr = nextP_tr_frm; 
 
  if (img->number == 0) // first picture 
  { 
    nextP_tr=prevP_tr=img->tr; 
  } 
  else if(img->type == I_IMG || img->type == P_IMG ) 
  { 
    nextP_tr=img->tr; 
     
    if(first_P) // first P picture 
    { 
      first_P = FALSE; 
      P_interval=nextP_tr-prevP_tr; //! TO 4.11.2001 we get problems here in case the first P-Frame was lost 
    } 
    write_prev_Pframe(img, p_out);  // imgY_prev, imgUV_prev -> file 
  } 
 
  // allocate memory for frame buffers 
  if (img->number == 0)  
  { 
   init_global_buffers(inp, img);  
  } 
 
  for(i=0;iwidth/(2*BLOCK_SIZE)+1;i++)          // set edge to -1, indicate nothing to predict from 
  { 
    img->ipredmode[i+1][0]=-1; 
    img->ipredmode[i+1][img->height/(2*BLOCK_SIZE)+1]=-1; 
  } 
 
  for(j=0;jheight/(2*BLOCK_SIZE)+1;j++) 
  { 
    img->ipredmode[0][j+1]=-1; 
    img->ipredmode[img->width/(2*BLOCK_SIZE)+1][j+1]=-1; 
  } 
 
  img->ipredmode    [0][0]=-1; 
 
  for(i=0; imax_mb_nr; i++) 
  { 
    mb_data[i].slice_nr = -1;  
  } 
 
	//luma 
	mref[0] = mref_frm[0]; //mref[ref_index][yuv]height(height/2)][width] ref_index=0,1 for P frame, ref_index = 0,1,2,3 for P field 
	mref[1] = mref_frm[1];  
	mref_fref[0] = mref_fref_frm[0]; //mref_fref[ref_index][yuv]height(height/2)][width] ref_index=0 for B frame, ref_index = 0,1 for B field 
	mref_bref[0] = mref_bref_frm[0]; 
		 
	//chroma 
	mcef[0][0] = mcef_frm[0][0];       //mcef[ref_index][uv][height][width] 
	mcef[0][1] = mcef_frm[0][1]; 
	mcef[1][0] = mcef_frm[1][0]; 
	mcef[1][1] = mcef_frm[1][1]; 
		 
	mcef_fref[0][0] = 	mcef_fref_frm[0][0]; //mcef_fref[ref_index][uv][height/2][width] 
	mcef_fref[0][1] = 	mcef_fref_frm[0][1]; 
	mcef_bref[0][0] = 	mcef_bref_frm[0][0]; 
 	mcef_bref[0][1] =   mcef_bref_frm[0][1];  
 
	imgY = imgY_frm =  current_frame[0]; 
	imgUV = imgUV_frm =  ¤t_frame[1]; 
 
  	img->mv = img->mv_frm; 
	refFrArr = refFrArr_frm; 
 
  	img->fw_refFrArr = img->fw_refFrArr_frm; 
  	img->bw_refFrArr = img->bw_refFrArr_frm; 
} 
 
 
void init_frame_buffer() 
{ 
	 
	//luma 
	mref[0] = mref_frm[0]; //mref[ref_index][yuv]height(height/2)][width] ref_index=0,1 for P frame, ref_index = 0,1,2,3 for P field 
	mref[1] = mref_frm[1];  
	mref_fref[0] = mref_fref_frm[0]; //mref_fref[ref_index][yuv]height(height/2)][width] ref_index=0 for B frame, ref_index = 0,1 for B field 
	mref_bref[0] = mref_bref_frm[0]; 
	 
	//chroma 
	mcef[0][0] = mcef_frm[0][0];       //mcef[ref_index][uv][height][width] 
	mcef[0][1] = mcef_frm[0][1]; 
	mcef[1][0] = mcef_frm[1][0]; 
	mcef[1][1] = mcef_frm[1][1]; 
	 
	mcef_fref[0][0] = 	mcef_fref_frm[0][0]; //mcef_fref[ref_index][uv][height/2][width] 
	mcef_fref[0][1] = 	mcef_fref_frm[0][1]; 
	mcef_bref[0][0] = 	mcef_bref_frm[0][0]; 
	mcef_bref[0][1] =   mcef_bref_frm[0][1];  
	 
	imgY_frm =  current_frame[0]; 
	imgUV_frm =  ¤t_frame[1]; 
} 
 
 
void init_top(struct img_par *img, struct inp_par *inp) 
{ 
  int i,j; 
 
  img->top_bot = 0; // Yulj 2004.07.20 
 
  for(i=0;iwidth/(2*BLOCK_SIZE)+1;i++)          // set edge to -1, indicate nothing to predict from 
  { 
    img->ipredmode[i+1][0]=-1; 
    img->ipredmode[i+1][img->height/(2*BLOCK_SIZE)+1]=-1; 
  } 
 
  for(j=0;jheight/(2*BLOCK_SIZE)+1;j++) 
  { 
    img->ipredmode[0][j+1]=-1; 
    img->ipredmode[img->width/(2*BLOCK_SIZE)+1][j+1]=-1; 
  } 
	 
  img->ipredmode    [0][0]=-1; 
	 
 					 
	for(i=0; imax_mb_nr; i++) 
	{ 
		mb_data[i].slice_nr = -1;  
	} 
		 
	//luma 
	for (i=0;i<4;i++) 
	{ 
		mref[i] = mref_fld[i]; //mref[ref_index][yuv]height(height/2)][width] ref_index=0,1 for P frame, ref_index = 0,1,2,3 for P field 
	} 
	//chroma 
	for(j=0;j<4;j++) 
		for(i=0;i<2;i++) 
		{ 
			mcef[j][i] = mcef_fld[j][i];       //mcef[ref_index][uv][height][width] 
		} 
 
	//forward/backward 
	for (i=0;i<2;i++) 
	{ 
		mref_fref[i] = mref_fref_fld[i]; //mref_fref[ref_index][yuv]height(height/2)][width] ref_index=0 for B frame, ref_index = 0,1 for B field 
		mref_bref[i] = mref_bref_fld[i]; 
	} 
	 
	for(j=0;j<2;j++) 
		for(i=0;i<2;i++) 
		{ 
			mcef_fref[j][i] = 	mcef_fref_fld[j][i]; //mcef_fref[ref_index][uv][height/2][width] 
			mcef_bref[j][i] = 	mcef_bref_fld[j][i]; 
		} 
	 
	imgY = imgY_top = current_field[0]; 
	imgUV = imgUV_top =  ¤t_field[1]; 
	 
	img->mv = img->mv_top; 
	refFrArr = refFrArr_top; 
	 
	img->fw_refFrArr = img->fw_refFrArr_top; 
	img->bw_refFrArr = img->bw_refFrArr_top; 
} 
 
 
void init_top_buffer() 
{ 
	int i,j; 
		//luma 
	for (i=0;i<4;i++) 
	{ 
		mref[i] = mref_fld[i]; //mref[ref_index][yuv]height(height/2)][width] ref_index=0,1 for P frame, ref_index = 0,1,2,3 for P field 
	} 
	//chroma 
	for(j=0;j<4;j++) 
	for(i=0;i<2;i++) 
	{ 
		mcef[j][i] = mcef_fld[j][i];       //mcef[ref_index][uv][height][width] 
	} 
 
	//forward/backward 
	for (i=0;i<2;i++) 
	{ 
		mref_fref[i] = mref_fref_fld[i]; //mref_fref[ref_index][yuv]height(height/2)][width] ref_index=0 for B frame, ref_index = 0,1 for B field 
		mref_bref[i] = mref_bref_fld[i]; 
	} 
	 
	for(j=0;j<2;j++) 
	for(i=0;i<2;i++) 
	{ 
		mcef_fref[j][i] = 	mcef_fref_fld[j][i]; //mcef_fref[ref_index][uv][height/2][width] 
		mcef_bref[j][i] = 	mcef_bref_fld[j][i]; 
	} 
	 
	imgY_top = current_field[0]; 
	imgUV_top =  ¤t_field[1]; 
	 
	img->mv = img->mv_top; 
	refFrArr = refFrArr_top; 
	 
	img->fw_refFrArr = img->fw_refFrArr_top; 
	img->bw_refFrArr = img->bw_refFrArr_top; 
} 
 
void init_bot_buffer() 
{ 
	//luma 
	int i,j; 
	for (i=0;i<4;i++) 
	{ 
	   mref[i] = mref_fld[i]; //mref[ref_index][yuv]height(height/2)][width] ref_index=0,1 for P frame, ref_index = 0,1,2,3 for P field 
	} 
	//chroma 
	for(j=0;j<4;j++) 
	for(i=0;i<2;i++) 
	{ 
	   mcef[j][i] = mcef_fld[j][i];       //mcef[ref_index][uv][height][width] 
	} 
	 
	//forward/backward 
	for (i=0;i<2;i++) 
	{ 
		mref_fref[i] = mref_fref_fld[i]; //mref_fref[ref_index][yuv]height(height/2)][width] ref_index=0 for B frame, ref_index = 0,1 for B field 
		mref_bref[i] = mref_bref_fld[i]; 
	} 
	 
	for(j=0;j<2;j++) 
	for(i=0;i<2;i++) 
	{ 
		mcef_fref[j][i] = 	mcef_fref_fld[j][i]; //mcef_fref[ref_index][uv][height/2][width] 
		mcef_bref[j][i] = 	mcef_bref_fld[j][i]; 
	} 
 
	imgY_bot =  current_field[0]; 
	imgUV_bot = ¤t_field[1]; 
 
	img->mv = img->mv_bot; 
	refFrArr = refFrArr_bot; 
 
	img->fw_refFrArr = img->fw_refFrArr_bot; 
	img->bw_refFrArr = img->bw_refFrArr_bot; 
} 
 
void init_bot(struct img_par *img, struct inp_par *inp) 
{ 
	int i,j; 
	 
	img->top_bot = 1; // Yulj 2004.07.20 
	img->current_mb_nr = 0; 
	 
	for(i=0;iwidth/(2*BLOCK_SIZE)+1;i++)          // set edge to -1, indicate nothing to predict from 
  	{ 
	    img->ipredmode[i+1][0]=-1; 
	    img->ipredmode[i+1][img->height/(2*BLOCK_SIZE)+1]=-1; 
	} 
	for(j=0;jheight/(2*BLOCK_SIZE)+1;j++) 
	{ 
	    img->ipredmode[0][j+1]=-1; 
	    img->ipredmode[img->width/(2*BLOCK_SIZE)+1][j+1]=-1; 
	} 
	 
	img->ipredmode    [0][0]=-1; 
		 
	for(i=0; imax_mb_nr; i++) 
	{ 
		mb_data[i].slice_nr = -1;  
	} 
	 
	//luma 
	for (i=0;i<4;i++) 
	{ 
		mref[i] = mref_fld[i]; //mref[ref_index][yuv]height(height/2)][width] ref_index=0,1 for P frame, ref_index = 0,1,2,3 for P field 
	} 
	//chroma 
	for(j=0;j<4;j++) 
		for(i=0;i<2;i++) 
	{ 
		mcef[j][i] = mcef_fld[j][i];       //mcef[ref_index][uv][height][width] 
	} 
		 
	//forward/backward 
	for (i=0;i<2;i++) 
	{ 
		mref_fref[i] = mref_fref_fld[i]; //mref_fref[ref_index][yuv]height(height/2)][width] ref_index=0 for B frame, ref_index = 0,1 for B field 
		mref_bref[i] = mref_bref_fld[i]; 
	} 
		 
	for(j=0;j<2;j++) 
		for(i=0;i<2;i++) 
		{ 
			mcef_fref[j][i] = 	mcef_fref_fld[j][i]; //mcef_fref[ref_index][uv][height/2][width] 
			mcef_bref[j][i] = 	mcef_bref_fld[j][i]; 
		} 
			 
	imgY = imgY_bot =  current_field[0]; 
	imgUV = imgUV_bot = ¤t_field[1]; 
			 
	img->mv = img->mv_bot; 
	refFrArr = refFrArr_bot; 
			 
	img->fw_refFrArr = img->fw_refFrArr_bot; 
	img->bw_refFrArr = img->bw_refFrArr_bot; 
			 
} 
 
/* 
************************************************************************* 
* Function: 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void split_field_top() 
{ 
  int i; 
 
  imgY = imgY_top; 
  imgUV = imgUV_top; 
   
  for (i=0; iheight; i++) 
  { 
    memcpy(imgY[i], imgY_frm[i*2], img->width);  
  } 
   
  for (i=0; iheight_cr; i++) 
  { 
    memcpy(imgUV[0][i], imgUV_frm[0][i*2], img->width_cr); 
    memcpy(imgUV[1][i], imgUV_frm[1][i*2], img->width_cr); 
  } 
} 
 
   
/* 
************************************************************************* 
* Function:extract bottom field from a frame  
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void split_field_bot() 
{ 
  int i; 
	 
  imgY = imgY_bot; 
  imgUV = imgUV_bot; 
     
  for (i=0; iheight; i++) 
  { 
    memcpy(imgY[i], imgY_frm[i*2 + 1], img->width); 
  } 
   
  for (i=0; iheight_cr; i++) 
  { 
    memcpy(imgUV[0][i], imgUV_frm[0][i*2 + 1], img->width_cr); 
    memcpy(imgUV[1][i], imgUV_frm[1][i*2 + 1], img->width_cr); 
  } 
} 
 
 
/* 
************************************************************************* 
* Function:decodes one picture 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void picture_data(struct img_par *img,struct inp_par *inp) 
{ 
	unsigned char *Buf; 
	int startcodepos,length;  
	const int mb_nr = img->current_mb_nr; 
	int mb_width = img->width/16; 
    	Macroblock *currMB = &mb_data[mb_nr]; 
    	img->current_slice_nr = -1;             // jlzheng 6.30 
	currentbitoffset = currStream->frame_bitoffset;   // jlzheng 6.30 
	currStream->frame_bitoffset = 0;                  // jlzheng 6.30 
	if ((Buf = (char*)calloc (MAX_CODED_FRAME_SIZE , sizeof(char))) == NULL)  
		no_mem_exit("GetAnnexbNALU: Buf");	 //jlzheng  6.30 
	img->coding_stage = 0; 
    	img->cod_counter=-1; 
 
  while (img->current_mb_nrPicSizeInMbs) // loop over macroblocks 
  { 
	  //decode slice header   jlzheng 6.30 
	  if( img->current_mb_nr%mb_width ==0 )  
	  { 
		  if(img->cod_counter<=0) 
		  { 
			  if(checkstartcode()) 
			  { 
				  GetOneUnit(Buf,&startcodepos,&length); 
				  SliceHeader(Buf,startcodepos,length); 
				  img->current_slice_nr++; 
				  img->cod_counter = -1; // Yulj 2004.07.15 
			  } 
		  } 
	  }  //decode slice header    
 
	  if(img->current_mb_nr==147&&img->tr==0) 
		  img->current_mb_nr=147; 
 
	mb_data[img->current_mb_nr].slice_nr = img->current_slice_nr;     // jlzheng 6.30 
 
#if TRACE 
    // Here was the slice nr from the mb_data used.  This slice number is only set after  
    // the reconstruction of an MB and hence here not yet valid 
    fprintf(p_trace,"\n*********** Pic: %i (I/P) MB: %i Slice: %i Type %d **********\n", img->tr, img->current_mb_nr, img->current_slice_nr, img->type); 
#endif 
     
    // Initializes the current macroblock 
    start_macroblock(img,inp); 
    // Get the syntax elements from the NAL 
    read_one_macroblock(img,inp); 
    // decode one macroblock 
    decode_one_macroblock(img,inp); 
    img->current_mb_nr++; 
  } 
 
  free(Buf); 
 
 //DeblockFrame (img, imgY, imgUV); 
 
} 
 
 
void top_field(struct img_par *img,struct inp_par *inp) 
{ 
 
  	unsigned char *Buf; 
	int startcodepos,length;  
	const int mb_nr = img->current_mb_nr; 
	int mb_width = img->width/16; 
    	Macroblock *currMB = &mb_data[mb_nr]; 
    	img->current_slice_nr = -1;     // jlzheng 6.30 
	currentbitoffset = currStream->frame_bitoffset;    // jlzheng 6.30 
	currStream->frame_bitoffset = 0;   // jlzheng 6.30 
	if ((Buf = (char*)calloc (MAX_CODED_FRAME_SIZE , sizeof(char))) == NULL) 
		no_mem_exit("GetAnnexbNALU: Buf");	 //jlzheng 
	img->coding_stage = 0; 
        img->cod_counter=-1; 
	 
	 
  while (img->current_mb_nrPicSizeInMbs) // loop over macroblocks 
  { 
      //decode slice header   jlzheng 6.30 
	  if( img->current_mb_nr%mb_width ==0 )  
	  { 
		  if(img->cod_counter<=0) 
		  { 
			  if(checkstartcode()) 
			  { 
				  GetOneUnit(Buf,&startcodepos,&length); 
				  SliceHeader(Buf,startcodepos,length); 
				  img->current_slice_nr++; 
				  img->cod_counter = -1; // Yulj 2004.07.15 
			  } 
		  } 
	  }  //decode slice header  
 
	if(img->current_mb_nr == 0) 
    img->current_slice_nr = 0; 
	mb_data[img->current_mb_nr].slice_nr = img->current_slice_nr;   // jlzheng 6.30 
		 
#if TRACE 
    // Here was the slice nr from the mb_data used.  This slice number is only set after  
    // the reconstruction of an MB and hence here not yet valid 
     
    fprintf(p_trace,"\n*********** Pic: %i (I/P) MB: %i Slice: %i Type %d **********\n", img->tr, img->current_mb_nr, img->current_slice_nr, img->type); 
#endif 
     
	if(img->current_mb_nr==1&&img->tr==3) 
		img->current_mb_nr=1; 
 
    // Initializes the current macroblock 
    start_macroblock(img,inp); 
	img->current_mb_nr_fld = img->current_mb_nr; 
    // Get the syntax elements from the NAL 
    read_one_macroblock(img,inp); 
    // decode one macroblock 
    decode_one_macroblock(img,inp); 
    img->current_mb_nr++; 
 
  } 
 
  free(Buf); 
 //DeblockFrame (img, imgY, imgUV); 
	 
} 
 
 
void bot_field(struct img_par *img,struct inp_par *inp) 
{ 
 
  	unsigned char *Buf; 
	int startcodepos,length;  
	const int mb_nr = img->current_mb_nr; 
	int mb_width = img->width/16; 
        Macroblock *currMB = &mb_data[mb_nr]; 
        img->current_slice_nr = -1;    // jlzheng 6.30 
	currentbitoffset = currStream->frame_bitoffset;    // jlzheng 6.30 
	currStream->frame_bitoffset = 0;   // jlzheng 6.30 
	if ((Buf = (char*)calloc (MAX_CODED_FRAME_SIZE , sizeof(char))) == NULL)  
		no_mem_exit("GetAnnexbNALU: Buf");	 //jlzheng 
	img->coding_stage = 0; 
        img->cod_counter=-1; 
	 
	 
  while (img->current_mb_nrPicSizeInMbs) // loop over macroblocks 
  { 
	  //decode slice header   jlzheng 6.30 
	  if( img->current_mb_nr%mb_width ==0 )  
	  { 
		  if(img->cod_counter<=0) 
		  { 
			  if(checkstartcode()) 
			  { 
				  GetOneUnit(Buf,&startcodepos,&length); 
				  SliceHeader(Buf,startcodepos,length); 
				  img->current_slice_nr++; 
				  img->cod_counter = -1; // Yulj 2004.07.15 
			  } 
		  } 
	  }  //decode slice header  
 
    if(img->current_mb_nr == 0) 
    img->current_slice_nr = 0; 
	mb_data[img->current_mb_nr].slice_nr = img->current_slice_nr;   // jlzheng 6.30 
 
#if TRACE 
    // Here was the slice nr from the mb_data used.  This slice number is only set after  
    // the reconstruction of an MB and hence here not yet valid 
	 
    fprintf(p_trace,"\n*********** Pic: %i (I/P) MB: %i Slice: %i Type %d **********\n", img->tr, img->current_mb_nr, img->current_slice_nr, img->type); 
#endif 
     
	if(img->current_mb_nr==660&&img->tr==2) 
		img->current_mb_nr=660; 
 
    // Initializes the current macroblock 
    start_macroblock(img,inp); 
	img->current_mb_nr_fld = img->current_mb_nr + img->PicSizeInMbs; 
    // Get the syntax elements from the NAL 
    read_one_macroblock(img,inp); 
    // decode one macroblock 
    decode_one_macroblock(img,inp); 
    img->current_mb_nr++; 
 } 
 
  free(Buf); 
 // DeblockFrame (img, imgY, imgUV); 
	 
} 
 
/*! 
************************************************************************ 
* \brief 
*    Generate a frame from top and bottom fields 
************************************************************************ 
*/ 
void combine_field(struct img_par *img) 
{ 
  int i; 
	 
  for (i=0; iheight; i++) 
  { 
    memcpy(imgY_frm[i*2], imgY_top[i], img->width);     // top field 
    memcpy(imgY_frm[i*2 + 1], imgY_bot[i], img->width); // bottom field 
  } 
	 
  for (i=0; iheight_cr; i++) 
  { 
    memcpy(imgUV_frm[0][i*2], imgUV_top[0][i], img->width_cr); 
    memcpy(imgUV_frm[0][i*2 + 1], imgUV_bot[0][i], img->width_cr); 
    memcpy(imgUV_frm[1][i*2], imgUV_top[1][i], img->width_cr); 
    memcpy(imgUV_frm[1][i*2 + 1], imgUV_bot[1][i], img->width_cr); 
  } 
} 
 
 
/* 
************************************************************************* 
* Function:Prepare field and frame buffer after frame decoding 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void frame_postprocessing(struct img_par *img) 
{ 
  if((img->number)&&(img->type==I_IMG || img->type == P_IMG)) 
  { 
    nextP_tr_frm = nextP_tr; 
  } 
 
  img->PrevPicDistanceLsb = img->pic_distance; 
  img->PicDistanceMsb = img->CurrPicDistanceMsb; 
} 
 
/* 
************************************************************************* 
* Function: 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
static void rotate_buffer () 
{ 
  Frame *f; 
   
  f = fb->picbuf_short[1]; 
  fb->picbuf_short[1] = fb->picbuf_short[0]; 
  fb->picbuf_short[0] = f; 
   
  mref[0] = fb->picbuf_short[0]->mref; 
  mcef[0] = fb->picbuf_short[0]->mcef; 
  mref[1] = fb->picbuf_short[1]->mref; 
  mcef[1] = fb->picbuf_short[1]->mcef; 
} 
 
 
/*! 
 ************************************************************************ 
 * \brief 
 *    Store information for use in B picture 
 ************************************************************************ 
 */ 
void store_field_MV(struct img_par *img) 
{ 
  int i, j; 
 
  if(img->type!=B_IMG) 
  { 
    if (img->picture_structure != FRAME) 
    { 
      for (i=0 ; iwidth/8 ; i++) 
      { 
        for (j=0 ; jheight/16 ; j++) 
        { 
          img->mv_frm[i+4][2*j][0] = img->mv_frm[i+4][2*j+1][0] = img->mv_top[i+4][j][0]; 
          img->mv_frm[i+4][2*j][0] = img->mv_frm[i+4][2*j+1][0] = img->mv_top[i+4][j][0]; 
          img->mv_frm[i+4][2*j][1] = img->mv_frm[i+4][2*j+1][1] = img->mv_top[i+4][j][1]*2; 
          img->mv_frm[i+4][2*j][1] = img->mv_frm[i+4][2*j+1][1] = img->mv_top[i+4][j][1]*2; 
          
 
          if (refFrArr_top[j][i] == -1) 
          { 
            refFrArr_frm[2*j][i] = refFrArr_frm[2*j+1][i] = -1; 
          } 
          else 
          { 
            refFrArr_frm[2*j][i] = refFrArr_frm[2*j+1][i] = (int)(refFrArr_top[j][i]/2); 
          } 
        } 
      } 
    } 
    else 
    { 
      for (i=0 ; iwidth/8; i++) 
      { 
        for (j=0 ; jheight/16 ; j++) 
        { 
          img->mv_top[i+4][j][0] = img->mv_bot[i+4][j][0] = (int)(img->mv_frm[i+4][2*j][0]); 
          img->mv_top[i+4][j][1] = img->mv_bot[i+4][j][1] = (int)((img->mv_frm[i+4][2*j][1])/2); 
 
            if (refFrArr_frm[2*j][i] == -1) 
            { 
              refFrArr_top[j][i] = refFrArr_bot[j][i] = -1; 
            } 
            else 
            { 
             // refFrArr_top[j][i] = refFrArr_bot[j][i] = refFrArr_frm[2*j][i]*2; 
				 refFrArr_top[j][i] = refFrArr_frm[2*j][i]*2; 
              refFrArr_bot[j][i] = refFrArr_frm[2*j][i]*2 + 1; 
                     //by oliver 0512 
            } 
        } 
      } 
    } 
  } 
}