www.pudn.com > wm2.5.zip > main.c


/* 
*********************************************************************** 
* COPYRIGHT AND WARRANTY INFORMATION 
* 
* Copyright 2004, Advanced Audio Video Coding Standard, Part II 
* 
* DISCLAIMER OF WARRANTY 
* 
* These software programs are available to the users without any 
* license fee or royalty on an "as is" basis. The AVS disclaims 
* any and all warranties, whether express, implied, or statutory, 
* including any implied warranties of merchantability or of fitness 
* for a particular purpose. In no event shall the contributors or  
* the AVS be liable for any incidental, punitive, or consequential 
* damages of any kind whatsoever arising from the use of this program. 
* 
* This disclaimer of warranty extends to the user of this program 
* and user's customers, employees, agents, transferees, successors, 
* and assigns. 
* 
* The AVS does not represent or warrant that the program furnished 
* hereunder are free of infringement of any third-party patents. 
* Commercial implementations of AVS, including shareware, may be 
* subject to royalty fees to patent holders. Information regarding 
* the AVS patent policy is available from the AVS Web site at 
* http://www.avs.org.cn 
* 
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY. 
************************************************************************ 
*/ 
 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
 
#include "global.h" 
#include "define.h" 
#include "types.h" 
#include "main.h" 
#include "picture.h" 
#include "bitstream.h" 
#include "block.h" 
#include "interpred.h" 
 
#include "ratectl.h"             // LX 0409 
//cbzhu 041221 
#include "parset.h" 
 
//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
#include "IREG.h" 
#endif // _ISOLATED_REGION_ 
 
 
 
 
static float fSNRY, fSNRU, fSNRV; 
double g_snr_ya, g_snr_ua, g_snr_va; 
int search_range; 
 
double DCTscale[BLOCK_SIZE][BLOCK_SIZE];   // LX 0409 
int    currMB_delta_qp , currMB_qp;        // LX 0409 
 
#ifdef _PSNR_YUV_ 
double g_snr_yuva; 
#endif // _PSNR_YUV_ 
 
extern void IniIREG(); 
extern void UpdateIREGMap(); 
extern int AffectedByLeftover(int x_pos, int y_pos, int ref); 
 
void main(int argc, char *argv[]) 
{ 
	//Rate Control 
  int M,N,n,np,nb;                   // LX 0409 
	double dct_a , dct_b , dct_d ;     // LX 0409 
	int bits = 0;                      // LX 0409 
 
	int i,h,w; 
	 
	time_t ltime1; 
	time_t ltime2; 
	int tmp_time; 
	int tot_time = 0; 
	struct _timeb tstruct1; 
	struct _timeb tstruct2; 
 
	g_snr_ya = g_snr_ua = g_snr_va = 0; 
 
  //Rate Control 
	dct_a = 0.5;                           
	dct_b = sqrt(0.4); 
	dct_d = 0.5; 
	 
	DCTscale[0][0] = dct_a*dct_a; 
	DCTscale[0][1] = dct_a*dct_b/2; 
	DCTscale[0][2] = dct_a*dct_a; 
	DCTscale[0][3] = dct_a*dct_b/2; 
	 
	DCTscale[1][0] = dct_a*dct_b/2; 
	DCTscale[1][1] = dct_b*dct_b/4; 
	DCTscale[1][2] = dct_a*dct_b/2; 
	DCTscale[1][3] = dct_b*dct_b/4; 
	 
	DCTscale[2][0] = dct_a*dct_a; 
	DCTscale[2][1] = dct_a*dct_b/2; 
	DCTscale[2][2] = dct_a*dct_a; 
	DCTscale[2][3] = dct_a*dct_b/2; 
	 
	DCTscale[3][0] = dct_a*dct_b/2; 
	DCTscale[3][1] = dct_b*dct_b/4; 
	DCTscale[3][2] = dct_a*dct_b/2; 
	DCTscale[3][3] = dct_b*dct_b/4;	          
  // 
 
#ifdef _PSNR_YUV_ 
    g_snr_yuva = 0; 
#endif // _PSNR_YUV_ 
	 
	//Read configure file 
	Configure(argc, argv); 
	 
	//Init reconstruction/reference buffer 
	Init_Frame_Buffer(); 
 
	Init_Global_Variable(); 
 
	AllocateBitstream(); 
 
	//cbzhu 041221   -----start 
	//generate parameter set 
	GenerateParameterSets(); 
 
	//write parameter set 
  //write sps pps 
	write_parset(active_sps , active_pps); 
	 
	//write sequence header 
	//Sequence_Header(); 
	//if((picture_header_rbsp=(pic_header *)calloc (1,sizeof (pic_header) )) == NULL)  
	//	no_mem_exit ("Allocpicheader: picheader"); 
	//-----end 
	 
	fprintf(stdout, "Input YUV file        : %s\n", input.infile); 
	fprintf(stdout, "Output bitstream file : %s\n", input.outfile); 
	fprintf(stdout, "Reconstructed YUV file: %s\n", input.ReconFile); 
	fprintf(stdout,"\n"); 
#ifndef _PSNR_YUV_ 
	fprintf(stdout, " Frame      QP  Bits    PSNRY     PSNRU     PSNRV     Time(ms)\n"); 
#else 
	fprintf(stdout, " Frame      QP  Bits    PSNRY     PSNRU     PSNRV     PSNRYVV    Time(ms)\n"); 
#endif // _PSNR_YUV_ 
 
     // LX 0409 
	pgImage->framerate=input.PictureRate;   // The basic frame rate (of the original sequence) 
	if(input.RCEnable)       // LX 0409 
		rc_init_seq();       // LX 0409 
 
#ifdef _ISOLATED_REGION_ //cbzhu 0412 
  if (input.IREGEnable) 
  { 
    IniIREG();		 
  } 
#endif // _ISOLATED_REGION_ 
 
 
	for(i=0; ipic_num = i; 
 
		//cbzhu 041221 
		if(input.intra_period) 
			pgImage->frame_num = (i%input.intra_period)%32; 
		else 
			pgImage->frame_num = i%32; 
		if(input.intra_period) 
			pgImage->picture_distance = ((i%input.intra_period)*(input.jumpd+1))%256; 
		else 
			pgImage->picture_distance = (i*(input.jumpd+1))%256; 
		pgImage->picture_distance_gap_minus1 = pgImage->picture_distance - 1; 
		pgImage->alpha_ci_offset = 0 ; 
		pgImage->cp_offset = -1; 
		pgImage->loopfilter_qp_offset = 0; 
		 
 
		//init bitstream,jiahz added 2004-02-18 
		Init_Bitstream();  
 
		Read_One_Frame(i); 
 
    //initial padding ipredmode 
		//set edge to -1, indicate nothing to predict from 
		for(w=0;w<(pgImage->img_width/BLOCK_SIZE+2);w++)           
		{ 
			ipredmode[w][0]=-1; 
			ipredmode[w][pgImage->img_height/BLOCK_SIZE+2]=-1; 
		} 
		for(h=0;h<(pgImage->img_height/BLOCK_SIZE+2);h++) 
		{ 
			ipredmode[0][h+1]=-1; 
			ipredmode[pgImage->img_width/BLOCK_SIZE+1][h+1]=-1; 
		} 
    //MZ 
/*   	for(w=0;w<(pgImage->img_width/MB_BLOCK_SIZE+2);w++)           
		{ 
			c_ipredmode[w][0]=-1; 
			c_ipredmode[w][pgImage->img_height/MB_BLOCK_SIZE+2]=-1; 
		} 
		for(h=0;h<(pgImage->img_height/MB_BLOCK_SIZE+2);h++) 
		{ 
			c_ipredmode[0][h+1]=-1; 
			c_ipredmode[pgImage->img_width/MB_BLOCK_SIZE+1][h+1]=-1; 
		} 
*/ 
        // LX 0409 
		pgImage->NumberofPPicture = i-1; 
		pgImage->NumberofCodedPFrame = i-1; 
		 
		if((i % g_iFrameNum) == 0) 
			pgImage->type = INTRA_IMG; 
		else 
			pgImage->type = INTER_IMG; 
		 
		if (pgImage->type == INTRA_IMG) 
		{ 
			//Rate Control 
			if(input.RCEnable) 
			{ 
				if (input.intra_period == 0) 
				{ 
			    n = input.no_frames ; 
				  //number of P frames 
					np = input.no_frames - 1;  
					//number of B frames 
					nb = 0; 
				} 
        else 
				{ 
					N = input.intra_period; 
					M = 1; 
					n = (pgImage->number==0) ? N - ( M - 1) : N; 
					// last GOP may contain less frames  
					if(pgImage->number/input.intra_period >= input.no_frames / input.intra_period) 
					{ 
						if (pgImage->number != 0) 
						  n = (input.no_frames - pgImage->number); 
						else 
							n = input.no_frames; 
					} 
				  // number of P frames  
					if (pgImage->number == 0) 
						np = (n + 2 * (M - 1)) / M - 1; // first GOP  
					else 
						np = (n + (M - 1)) / M - 1; 
	 
					nb = n - np - 1; 
				} 
				rc_init_GOP(np,nb); 
			} 
      // 
		} 
 
		if(!input.RCEnable)                  // without using rate control 
		{ 
			pgMbData->qp_mb = pgImage->qp0; 
		} 
		else 
		{ 
			rc_init_pict(1,0,1);  
			pgMbData->qp_mb = updateQuantizationParameter(0);   
		} 
 
		currMB_delta_qp = 0; 
		currMB_qp       = pgMbData->qp_mb ; 
        // LX 0409 
 
#ifdef _ISOLATED_REGION_  
  if (input.IREGEnable) 
  { 
    UpdateIREGMap(); 
  } 
#endif // _ISOLATED_REGION_ 
		 
		if(g_iKeyFrame!=0) 
		{ 
			if (i%g_iKeyFrame) 
			{ 
				for(h=0; himg_height/BLOCK_SIZE+4; h++) 
					for(w=0; wimg_width/BLOCK_SIZE+4 ; w++) 
					{ 
						refFrArr[h][w]=-1; 
						tmp_mv[0][h][w] = 0; 
						tmp_mv[1][h][w] = 0; 
					} 
				Encode_P_Frame(); 
				if(pgImage->p_pic_type == 0) 
				{ 
					pgImage->nb_references += 1; 
					pgImage->nb_references = min(pgImage->nb_references, pgImage->refnum);   
				} 
				else 
				{ 
				} 
			} 
			else 
			{ 
				Encode_I_Frame(); 
				pgImage->nb_references = 1; 
  		} 
		} 
		else 
		{ 
			if(i==0) 
			{ 
				pgImage->picture_code_type = INTRA_IMG; 
				 
				Encode_I_Frame(); 
				pgImage->nb_references = 1; 
				//pgImage->nb_references = min(pgImage->nb_references, 1);  
			} 
			else 
			{ 
				for(h=0; himg_height/BLOCK_SIZE+4; h++) 
					for(w=0; wimg_width/BLOCK_SIZE+4 ; w++) 
					{ 
						refFrArr[h][w]=-1; 
						tmp_mv[0][h][w] = 0; 
						tmp_mv[1][h][w] = 0; 
					} 
                pgImage->picture_code_type = INTER_IMG; 
				 
				Encode_P_Frame(); 
				pgImage->nb_references += 1; 
 
				pgImage->nb_references = min(pgImage->nb_references, pgImage->refnum);  
			} 
		} 
		 
		Write_Reconstructed_Image();		 
 
		WriteBitstreamtoFile(); 
 
		// rate control 
		if(input.RCEnable) 
		{ 
			bits = 0;   //UVLC && Bitstream output mode  
			rc_update_pict_frame(bits); 
		} 
		// rate control 
 
		Find_SNR(i); 
 
		// rate control 
		if (i == 0) 
		{ 
			if(input.RCEnable) 
				bits = pgcurrBitStream->byte_pos*8; // used for rate control update  
		} 
		//      后续帧 
		else 
		{ 
			//Rate control 
			if(input.RCEnable) 
			{ 
				bits = pgcurrBitStream->byte_pos*8; 
			} 
		} 
		 
		if(input.RCEnable)  
		{ 
			rc_update_pict(bits); 
			/*update the parameters of quadratic R-D model*/ 
			//每个宏块都是帧编码时 
			// 
			if(pgImage->picture_code_type == INTER_IMG) 
				updateRCModel(); 
		} 
		// LX 0409 
 
		 
		//half/quater Interpolation and exchange reconstruction/reference buffer 
		Update_Buffer(); 
 
		time (<ime2);               // end time sec 
		_ftime (&tstruct2);           // end time ms 
		tmp_time = (ltime2 * 1000 + tstruct2.millitm) - (ltime1 * 1000 + tstruct1.millitm); 
 
		tot_time += tmp_time; 
#ifndef _PSNR_YUV_ 
        printf("%5d\n",tmp_time); 
#else 
        printf("  %5d\n",tmp_time); 
#endif // _PSNR_YUV_ 
	} 
 
	//byte align 
//	terminate_sequence(); 
  //free encoder 
  FreeParameterSets(); 
	FreeBitstream(); 
  Free_Frame_Buffer(); 
	// statistics output 
	fprintf(stdout, "\n******* Total time : %.3f sec \t ( %d frms | %.2f frm/sec) \n\n", 
		tot_time*0.001,g_iFrameNum,g_iFrameNum/(tot_time*0.001)); 
  fprintf(stdout, "\n******* Total Bits : %d\n\n",gTotalBits); 
	fprintf(stdout,"-------------------- Average data all frames  --------------------------------\n"); 
#ifndef _PSNR_YUV_ 
  fprintf(stdout, "SNR Y(dB)\tSNR U(dB)\tSNR V(dB)\tBitrate(kbps)\n"); 
  fprintf(stdout, "%f\t%f\t%f\t%f\n", 
    g_snr_ya/g_iFrameNum, g_snr_ua/g_iFrameNum,g_snr_va/g_iFrameNum,  
    gTotalBits*30.0/(1000.0*g_iFrameNum*(1+input.jumpd))); 
#else 
  fprintf(stdout, "SNR Y(dB)\tSNR U(dB)\tSNR V(dB)\tSNR YUV(dB)\tBitrate(kbps)\n"); 
  fprintf(stdout, "%f\t%f\t%f\t%f\t%f\n", 
    g_snr_ya/g_iFrameNum, g_snr_ua/g_iFrameNum,g_snr_va/g_iFrameNum, g_snr_yuva/g_iFrameNum, 
    gTotalBits*30.0/(1000.0*g_iFrameNum*(1+input.jumpd))); 
#endif // _PSNR_YUV_ 
	fprintf(stdout, "Frame rate: %d(Hz)\n ", 30/(1+input.jumpd)); 
	fprintf(stdout,"\n"); 
	return; 
} 
 
/*! 
 *********************************************************************** 
 * \brief 
 *    Parse the command line parameters and read the config files. 
 * \param ac 
 *    number of command line parameters 
 * \param av 
 *    command line parameters 
 *********************************************************************** 
 */ 
void Configure (int ac, char *av[]) 
{ 
  char *content; 
  int CLcount, ContentLen, NumberParams; 
  char *filename=DEFAULTCONFIGFILENAME; 
 
  memset (&input, 0, sizeof (InputParameters)); 
  // Process default config file 
 
  CLcount = 1; 
  if (ac>=3) 
  { 
    if (0 == strncmp (av[1], "-d", 2)) 
    { 
      filename=av[2]; 
      CLcount = 3; 
    } 
  } 
  printf ("Parsing Configfile %s", filename); 
  content = GetConfigFileContent (filename); 
  ParseContent (content, strlen(content)); 
  printf ("\n"); 
  free (content); 
 
  // Parse the command line 
 
  while (CLcount < ac) 
  { 
    if (0 == strncmp (av[CLcount], "-f", 2))  // A file parameter? 
    { 
      content = GetConfigFileContent (av[CLcount+1]); 
      printf ("Parsing Configfile %s", av[CLcount+1]); 
      ParseContent (content, strlen (content)); 
      printf ("\n"); 
      free (content); 
      CLcount += 2; 
    }  
	  else 
    { 
      if (0 == strncmp (av[CLcount], "-p", 2))  // A config change? 
      { 
        // Collect all data until next parameter (starting with - (x is any character)), 
        // put it into content, and parse content. 
 
        CLcount++; 
        ContentLen = 0; 
        NumberParams = CLcount; 
 
        // determine the necessary size for content 
        while (NumberParams < ac && av[NumberParams][0] != '-') 
          ContentLen += strlen (av[NumberParams++]);        // Space for all the strings 
        ContentLen += 1000;                     // Additional 1000 bytes for spaces and \0s 
 
 
        if ((content = malloc (ContentLen))==NULL) no_mem_exit("Configure: content");; 
        content[0] = '\0'; 
 
        // concatenate all parameters identified before 
 
        while (CLcount < NumberParams) 
        { 
          char *source = &av[CLcount][0]; 
          char *destin = &content[strlen (content)]; 
 
          while (*source != '\0') 
          { 
            if (*source == '=')  // The Parser expects whitespace before and after '=' 
            { 
              *destin++=' '; *destin++='='; *destin++=' ';  // Hence make sure we add it 
            } else 
              *destin++=*source; 
            source++; 
          } 
          *destin = '\0'; 
          CLcount++; 
        } 
        printf ("Parsing command line string '%s'", content); 
        ParseContent (content, strlen(content)); 
        free (content); 
        printf ("\n"); 
      } 
      else 
      { 
        _snprintf (errortext, ET_SIZE, "Error in command line, ac %d, around string '%s', missing -f or -p parameters?", CLcount, av[CLcount]); 
        error (errortext, 300); 
      } 
    } 
  } 
  printf ("\n"); 
  // 
  pInFile = fopen(input.infile, "rb"); 
  if (pInFile == NULL) 
  { 
    printf("Error: Can't open input YUV file\n"); 
    exit(-1);  
  } 
   
  if ((pOutFile = fopen(input.ReconFile, "wb")) == NULL) 
  { 
    printf("Error: Can't create reconstruction YUV file\n"); 
    exit(-1);  
  } 
 
  pgcurrBitStream->f = fopen(input.outfile ,"wb"); 
  if(pgcurrBitStream->f == NULL) 
  { 
    printf("Error: can not create bitstream file\n"); 
    exit(0); 
  } 
   
  pgImage->img_width = input.img_width; 
  pgImage->img_height = input.img_height; 
  g_iFrameNum        = input.no_frames;   
  g_iKeyFrame        = input.intra_period; 
  pgImage->qp0       = input.qp0; 
  pgImage->qpN       = input.qpN; 
  pgImage->skipnum   = input.jumpd; 
  pgImage->refnum    = input.num_reference_frames; 
  search_range       = input.search_range; 
   
  pgImage->img_Y_size  = pgImage->img_width * pgImage->img_height; 
  pgImage->img_UV_size = (pgImage->img_Y_size >> 2); 
  pgImage->img_size    = pgImage->img_Y_size + 2 * pgImage->img_UV_size;  
   
  pgImage->half_pixel_mv_enable_flag = input.HalfPixelMVEnable; 
} 
 
/*! 
*********************************************************************** 
* \brief 
*    allocates memory buf, opens file Filename in f, reads contents into 
*    buf and returns buf 
* \param Filename 
*    name of config file 
*********************************************************************** 
*/ 
char *GetConfigFileContent (char *Filename) 
{ 
  long FileSize; 
  FILE *f; 
  char *buf; 
   
  if (NULL == (f = fopen (Filename, "r"))) 
  { 
    _snprintf (errortext, ET_SIZE, "Cannot open configuration file %s.\n", Filename); 
    error (errortext, 300); 
  } 
   
   
  if (0 != fseek (f, 0, SEEK_END)) 
  { 
    _snprintf (errortext, ET_SIZE, "Cannot fseek in configuration file %s.\n", Filename); 
    error (errortext, 300); 
  } 
   
  FileSize = ftell (f); 
 
   
  if (0 != fseek (f, 0, SEEK_SET)) 
  { 
    _snprintf (errortext, ET_SIZE, "Cannot fseek in configuration file %s.\n", Filename); 
    error (errortext, 300); 
  } 
   
    
  if ((buf = malloc (FileSize + 1))==NULL) no_mem_exit("GetConfigFileContent: buf"); 
   
  // Note that ftell() gives us the file size as the file system sees it.  The actual file size, 
  // as reported by fread() below will be often smaller due to CR/LF to CR conversion and/or 
  // control characters after the dos EOF marker in the file. 
   
  FileSize = fread (buf, 1, FileSize, f); 
  buf[FileSize] = '\0'; 
     
  fclose (f); 
  return buf; 
} 
 
/*! 
 *********************************************************************** 
 * \brief 
 *    Parses the character array buf and writes global variable input, which is defined in 
 *    configfile.h.  This hack will continue to be necessary to facilitate the addition of 
 *    new parameters through the Map[] mechanism (Need compiler-generated addresses in map[]). 
 * \param buf 
 *    buffer to be parsed 
 * \param bufsize 
 *    buffer size of buffer 
 *********************************************************************** 
 */ 
void ParseContent (char *buf, int bufsize) 
{ 
 
  char *items[MAX_ITEMS_TO_PARSE]; 
  int MapIdx; 
  int item = 0; 
  int InString = 0, InItem = 0; 
  char *p = buf; 
  char *bufend = &buf[bufsize]; 
  int IntContent; 
  int i; 
 
// Stage one: Generate an argc/argv-type list in items[], without comments and whitespace. 
// This is context insensitive and could be done most easily with lex(1). 
 
  while (p < bufend) 
  { 
    switch (*p) 
    { 
      case 13: 
        p++; 
        break; 
      case '#':                 // Found comment 
        *p = '\0';              // Replace '#' with '\0' in case of comment immediately following integer or string 
        while (*p != '\n' && p < bufend)  // Skip till EOL or EOF, whichever comes first 
          p++; 
        InString = 0; 
        InItem = 0; 
        break; 
      case '\n': 
        InItem = 0; 
        InString = 0; 
        *p++='\0'; 
        break; 
      case ' ': 
      case '\t':              // Skip whitespace, leave state unchanged 
        if (InString) 
          p++; 
        else 
        {                     // Terminate non-strings once whitespace is found 
          *p++ = '\0'; 
          InItem = 0; 
        } 
        break; 
 
      case '"':               // Begin/End of String 
        *p++ = '\0'; 
        if (!InString) 
        { 
          items[item++] = p; 
          InItem = ~InItem; 
        } 
        else 
          InItem = 0; 
        InString = ~InString; // Toggle 
        break; 
 
      default: 
        if (!InItem) 
        { 
          items[item++] = p; 
          InItem = ~InItem; 
        } 
        p++; 
    } 
  } 
 
  item--; 
 
  for (i=0; i (MapIdx = ParameterNameToMapIndex (items[i]))) 
    { 
      _snprintf (errortext, ET_SIZE, " Parsing error in config file: Parameter Name '%s' not recognized.", items[i]); 
      error (errortext, 300); 
    } 
    if (strcmp ("=", items[i+1])) 
    { 
      _snprintf (errortext, ET_SIZE, " Parsing error in config file: '=' expected as the second token in each line."); 
      error (errortext, 300); 
    } 
 
    // Now interprete the Value, context sensitive... 
 
    switch (Map[MapIdx].Type) 
    { 
      case 0:           // Numerical 
        if (1 != sscanf (items[i+2], "%d", &IntContent)) 
        { 
          _snprintf (errortext, ET_SIZE, " Parsing error: Expected numerical value for Parameter of %s, found '%s'.", items[i], items[i+2]); 
          error (errortext, 300); 
        } 
        * (int *) (Map[MapIdx].Place) = IntContent; 
        printf ("."); 
        break; 
      case 1: 
        strcpy ((char *) Map[MapIdx].Place, items [i+2]); 
        printf ("."); 
        break; 
      default: 
        assert ("Unknown value type in the map definition of configfile.h"); 
    } 
  } 
} 
 
int ParameterNameToMapIndex (char *s) 
{ 
  int i = 0; 
   
  while (Map[i].TokenName != NULL) 
    if (0==strcmp (Map[i].TokenName, s)) 
      return i; 
    else 
      i++; 
    return -1; 
}; 
 
/******************************************************************** 
	Created:	12:2:2004   
	Author :	Siwei Ma 
	Input  : 
    Output : 
 
	Function:	allocate global buffer 
*********************************************************************/ 
static void Init_Frame_Buffer(void) 
{ 
	int i; 
	int j; 
 
	if ((org_yuv_buffer = (Byte *)malloc(pgImage->img_size)) == NULL) 
		printf("Error: Can't allocate orginal YUV buffer\n"); 
 
 
	if((pgImage->mb_headerdata = (MacroblockHeader *)calloc(pgImage->img_height/16*pgImage->img_width/16 , sizeof(MacroblockHeader))) == NULL) 
		printf("Error: Can't allocate mb_headerdata \n"); 
	if((pgImage->mb_data_forlf= (MacroblockData *)calloc(pgImage->img_height/16*pgImage->img_width/16 , sizeof(MacroblockData))) == NULL) 
		printf("Error: Can't allocate mb_headerdata \n"); 
 
	for (i=0; i<3; i++) 
	{ 
		if(i==0) 
		{ 
			Get_Mem2D(&original_frame[i] , pgImage->img_height, pgImage->img_width); 
			Get_Mem2D(¤t_frame[i]  , pgImage->img_height+2*PAD_SIZE, pgImage->img_width+2*PAD_SIZE); 
		}else 
		{ 
			Get_Mem2D(&original_frame[i] , pgImage->img_height/2, pgImage->img_width/2); 
			Get_Mem2D(¤t_frame[i]  , pgImage->img_height/2, pgImage->img_width/2); 
		} 
	} 
 
	Get_Mem2D(&imgY_rec , pgImage->img_height , pgImage->img_width);//cbzhu 
	Get_Mem2D(&imgU_rec , pgImage->img_height/2 , pgImage->img_width/2); 
	Get_Mem2D(&imgV_rec , pgImage->img_height/2 , pgImage->img_width/2); 
 
  for(j=0; j<3; j++) 
		for (i=0; i<3; i++) 
		{ 
			if (i==0) 
			{ 
				Get_Mem2D(&reference_frame[j][i],pgImage->img_height+2*PAD_SIZE, pgImage->img_width+2*PAD_SIZE); 
			}else 
			{ 
				Get_Mem2D(&reference_frame[j][i],pgImage->img_height+2*PAD_SIZE, pgImage->img_width+2*PAD_SIZE); 
			} 
		} 
 
		for(j=0; j<3; j++) 
		{ 
			Get_Mem2D(&reference_half_pel_frame[j], 2*(pgImage->img_height+2*PAD_SIZE), 2*(pgImage->img_width+2*PAD_SIZE)); 
			Get_Mem2D(&reference_quater_pel_frame[j], 4*(pgImage->img_height+2*PAD_SIZE), 4*(pgImage->img_width+2*PAD_SIZE)); 
			 
			Get_Mem2D_Int(&half_pel_frame_tmp[j], 2*(pgImage->img_height+2*PAD_SIZE), 2*(pgImage->img_width+2*PAD_SIZE)); 
		} 
  Get_Mem2D_Int(&imgY, pgImage->img_height, pgImage->img_width); 
  Get_Mem2D_Int(&imgUV[0], pgImage->img_height/2, pgImage->img_width/2); 
  Get_Mem2D_Int(&imgUV[1], pgImage->img_height/2, pgImage->img_width/2); 
 
  Get_Mem2D_Int(&refFrArr, pgImage->img_height/BLOCK_SIZE+4, pgImage->img_width/BLOCK_SIZE+4); 
  Get_Mem2D_Int(&refFrArr_tmp, pgImage->img_height/BLOCK_SIZE+4, pgImage->img_width/BLOCK_SIZE+4); 
 
  for (i=0; i<2; i++) 
  { 
	Get_Mem2D_Int(&tmp_mv[i] , pgImage->img_height/BLOCK_SIZE+4, pgImage->img_width/BLOCK_SIZE+4); 
  } 
 
  Get_Mem2D_Int(&ipredmode,  pgImage->img_width/BLOCK_SIZE+3, pgImage->img_height/BLOCK_SIZE+3); 
  //MZ 
//  Get_Mem2D_Int(&c_ipredmode, pgImage->img_width/MB_BLOCK_SIZE+2, pgImage->img_height/MB_BLOCK_SIZE+2); 
   
  pgImage->nb_references=0; 
 
//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
  if (input.IREGEnable) 
  { 
      for (i=0; i<3; i++) 
      { 
          Get_Mem2D(&IREGMap[i] , pgImage->img_height/MB_BLOCK_SIZE, pgImage->img_width/MB_BLOCK_SIZE); 
      }   
  } 
#endif // _ISOLATED_REGION_ 
 
} 
 
/*! 
*********************************************************************** 
* \brief 
*    free global  buf 
*********************************************************************** 
*/ 
static void Free_Frame_Buffer() 
{ 
	int i; 
	int j; 
		 
	free(org_yuv_buffer); 
 
	for (i=0; i<3; i++) 
	{ 
		free_mem2D(original_frame[i]); 
		free_mem2D(current_frame[i]); 
	} 
 
	for(j=0; j<3; j++) 
		for (i=0; i<3; i++) 
		{ 
			free_mem2D(reference_frame[j][i]); 
		} 
 
	for(j=0; j<3; j++) 
	{ 
		free_mem2D(reference_half_pel_frame[j]); 
		free_mem2D(reference_quater_pel_frame[j]); 
		 
		free_mem2Dint(half_pel_frame_tmp[j]); 
	} 
 
  free_mem2Dint(imgY); 
  free_mem2Dint(imgUV[0]); 
  free_mem2Dint(imgUV[1]); 
 
//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
  if(input.IREGEnable) 
  {  
	  for(i=0;i<3;i++)free_mem2D(IREGMap[i]); 
  } 
#endif //_ISOLATED_REGION_ 
 
  free_mem2Dint(refFrArr); 
  free_mem2Dint(refFrArr_tmp); 
 
  for (i=0; i<2; i++) 
  { 
	  free_mem2Dint(tmp_mv[i]); 
  } 
 
  free_mem2Dint(ipredmode); 
  //MZ 
//  free_mem2Dint(c_ipredmode); 
} 
 
/******************************************************************** 
	Created:	12:2:2004   
	Author :	Siwei Ma 
	Input  : 
    Output : 
 
	Function:	Allocate 2D memory array -> Byte array2D[rows][columns] 
*********************************************************************/ 
static void Get_Mem2D(Byte ***array2D, int rows, int columns) 
{ 
	int i; 
	 
	if((*array2D      = (Byte**)calloc(rows,        sizeof(Byte*))) == NULL) 
		printf("Can't allocate YUV memory\n"); 
	 
	if(((*array2D)[0] = (Byte* )calloc(columns*rows,sizeof(Byte ))) == NULL) 
		printf("Can't allocate YUV memory\n"); 
	 
	for(i=1;i Byte array2D[rows][columns] 
*********************************************************************/ 
static void Get_Mem2D_Int(int ***array2D, int rows, int columns) 
{ 
	int i; 
	 
	if((*array2D      = (int**)calloc(rows,        sizeof(int*))) == NULL) 
		printf("Can't allocate YUV memory\n"); 
	 
	if(((*array2D)[0] = (int* )calloc(columns*rows,sizeof(int ))) == NULL) 
		printf("Can't allocate YUV memory\n"); 
	 
	for(i=1;itotal_mb_number = ((pgImage->img_width * pgImage->img_height)>>8); 
	pgImage->fixed_picture_qp = 1; 
	 
	//Inter Initialization 
	Init_Inter_Sequence(); 
 
	gTotalBits = 0; 
} 
 
/* 
******************************************************************* 
	Created:	12:2:2004   
	Author :	Siwei Ma 
	Input  : 
  Output : 
 
	Function:	read one frame YUV data to buffer 
******************************************************************** 
*/ 
static void Read_One_Frame(int frame_no) 
{ 
	int i, j; 
  int pos; 
	 
  fseek(pInFile, 0, SEEK_SET); 
  pos = (frame_no + frame_no * input.jumpd) * pgImage->img_size; 
  fseek(pInFile, pos, SEEK_CUR); 
 
  if ((i = fread(org_yuv_buffer, 1, pgImage->img_size, pInFile))img_size) 
		printf("Error: File end!\n"); 
 
  //store 1/1 pixel value - luma 
	for (j =0; j < pgImage->img_height; j++) 
	  for (i = 0; i < pgImage->img_width; i++) 
	    original_frame[0][j][i] = org_yuv_buffer[j * pgImage->img_width + i];// 1/1 pix pos 
  //store 1/1 pixel value - chroma 
	for (j = 0; j < pgImage->img_height/2; j++) 
		for (i = 0; i < pgImage->img_width/2; i++) 
		{		 
  		original_frame[1][j][i] = org_yuv_buffer[pgImage->img_Y_size + j * pgImage->img_width/2 + i];// 1/1 pix pos 
			original_frame[2][j][i] = org_yuv_buffer[pgImage->img_Y_size + pgImage->img_UV_size + j * pgImage->img_width/2 + i];// 1/1 pix pos 
		} 
} 
 
/* 
******************************************************************* 
	Created:	12:2:2004   
	Author :	Siwei Ma 
	Input  : 
    Output : 
 
	Function:	exchange global buffer 
******************************************************************** 
*/ 
static void Update_Buffer(void) 
{ 
	int i; 
	Byte **tmp; 
 
	//padding current reconstructed frame 
	Padding_IP_Frame(); 
 
  if (pgImage->p_pic_type == 0)  //zhangnan 
	{ 
		tmp = reference_quater_pel_frame[1];  //zhangnan 
		reference_quater_pel_frame[1]= reference_quater_pel_frame[0]; 
		reference_quater_pel_frame[0] = tmp; 
		 
		tmp =  reference_half_pel_frame [1]; 
		reference_half_pel_frame [1] = reference_half_pel_frame [0]; 
		reference_half_pel_frame [0] = tmp; 
		 
		//interpolate current Y image to 1/2, 1/4 refernce buffer 
		Interpolate_IP_Frame(); 
		 
		for(i=0; i<3; i++)   //zhangnan 
		{ 
			tmp = reference_frame[1][i]; 
			reference_frame[1][i]= reference_frame[0][i];//current_frame[i]; 
			reference_frame[0][i] = current_frame[i]; 
			current_frame[i]=tmp; 
		} 
 
		//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
		//printf("%d \n" , iIREGState); 
        if (input.IREGEnable) 
        { 
            tmp = IREGMap[2]; 
            IREGMap[2] = IREGMap[1]; 
            IREGMap[1] = IREGMap[0]; 
            IREGMap[0] = tmp; 
            pCurrFrmIREGMap = IREGMap[2]; 
             
            if (iIREGState == pgImage->img_height * pgImage->img_width / MB_BLOCK_SIZE / MB_BLOCK_SIZE) 
            { 
                iIREGReliableFrmFlag = 1; 
            } 
            else 
            { 
                iIREGReliableFrmFlag = 0; 
            } 
        } 
#endif // _ISOLATED_REGION_ 
  }	 
	// dongjie(check) 
	if(pgImage->type==INTRA_IMG) 
	{ 
		pgImage->p_pic_type = 1; 
	} 
	// end 
} 
 
/* 
******************************************************************* 
	Created:	15:2:2004   
	Author :	 
	Input  : 
    Output : 
 
	Function:	 
******************************************************************** 
*/ 
static void Write_Reconstructed_Image(void) 
{ 
	int j; 
	 
	for (j = 0; j < pgImage->img_height; j++) 
	{ 
		//store 1/1 pixel value 
		fwrite(¤t_frame[0][j + PAD_SIZE][PAD_SIZE], 1, pgImage->img_width, pOutFile);// 1/1 pix pos 
	} 
		 
	for (j = 0; j < pgImage->img_height/2; j++) 
	{ 
		//store 1/1 pixel value 
		fwrite(¤t_frame[1][j][0], 1, pgImage->img_width/2, pOutFile);// 1/1 pix pos 
	} 
	 
	for (j = 0; j < pgImage->img_height/2; j++) 
	{ 
		//store 1/1 pixel value 
		fwrite(¤t_frame[2][j][0], 1, pgImage->img_width/2, pOutFile);// 1/1 pix pos 
	} 
} 
 
 
/* 
******************************************************************* 
	Created:	14:2:2004   
	Author :	Siwei Ma 
	Input  : 
    Output : 
 
	Function:	 
******************************************************************** 
*/ 
static void Find_SNR (int frame_num) 
{ 
	int i, j; 
	int diff_y, diff_u, diff_v; 
	float snr_y, snr_u, snr_v; 
	char imgtype; 
	int  qp; 
#ifdef _PSNR_YUV_ 
	float snr_yuv; 
	float tmpy, tmpu, tmpv; 
#endif // _PSNR_YUV_ 
   
	//  Calculate  PSNR for Y, U and V. 
	//     Luma. 
	 
	diff_y = 0; 
	for (i = 0; i < pgImage->img_width; ++i) 
	{ 
		for (j = 0; j < pgImage->img_height; ++j) 
		{ 
			diff_y += quadarr[original_frame[0][j][i] - current_frame[0][j + PAD_SIZE][i + PAD_SIZE]]; 
		} 
	} 
	 
	//     Chroma. 
	diff_u = 0; 
	diff_v = 0; 
	 
	for (i = 0; i < pgImage->img_width/2; i++) 
	{ 
		for (j = 0; j < pgImage->img_height/2; j++) 
		{ 
			diff_u += quadarr[original_frame[1][j][i] - current_frame[1][j][i]]; 
			diff_v += quadarr[original_frame[2][j][i] - current_frame[2][j][i]]; 
		} 
	} 
	 
	//  Collecting SNR statistics 
	if (diff_y != 0) 
	{ 
		snr_y = (float) (10 * log10 (65025 * (float) pgImage->img_Y_size / (float) diff_y));         // luma snr for current frame 
		snr_u = (float) (10 * log10 (65025 * (float) pgImage->img_UV_size / (float) (diff_u)));   // u croma snr for current frame, 1/4 of luma samples 
		snr_v = (float) (10 * log10 (65025 * (float) pgImage->img_UV_size / (float) (diff_v)));   // v croma snr for current frame, 1/4 of luma samples 
	}	 
 
	if(g_iKeyFrame!=0) 
    { 
      imgtype = (frame_num%g_iKeyFrame) ? 'P' : 'I'; 
 
	  if(!input.RCEnable) 
	  { 
		  if(imgtype=='I')             // LX 0409 
			  qp = pgImage->qp0; 
		  else   
			  //qp = pgImage->qpN;  
			  qp=pgMbData->qp_mb;  //cbzhu Nov.13 2004 
	  } 
	  else           
		  qp = pgMbData->qp_mb ;        // LX 0409 
	   
    } 
	else 
    { 
      imgtype = (frame_num==0) ? 'I' : 'P'; 
 
 	  if(!input.RCEnable) 
	  { 
		  if(imgtype=='I')             // LX 0409 
			  qp = pgImage->qp0; 
		  else   
			  //qp = pgImage->qpN;  
			  qp=pgMbData->qp_mb;  //cbzhu Nov.13 2004 
	  } 
 	  else           
 		  qp = pgMbData->qp_mb ;        // LX 0409 
  
    } 
#ifdef _PSNR_YUV_ 
    tmpy = (float)(4.0 / pow(10, snr_y / 10)); 
    tmpu = (float)(1.0 / pow(10, snr_u / 10)); 
    tmpv = (float)(1.0 / pow(10, snr_v / 10)); 
    snr_yuv = (float)(10 * log10(6 / ( tmpy + tmpu + tmpv ) )); 
#endif // _PSNR_YUV_ 
     
#ifndef _PSNR_YUV_ 
    printf("%3d(%c) \t %5d %5d   %5.4f   %5.4f   %5.4f   ",  
        frame_num*(1+input.jumpd), imgtype, qp, pgcurrBitStream->byte_pos*8, snr_y, snr_u, snr_v); 
#else 
    printf("%3d(%c) \t %5d %5d   %5.4f   %5.4f   %5.4f    %5.4f   ",  
        frame_num*(1+input.jumpd), imgtype, qp, pgcurrBitStream->byte_pos*8, snr_y, snr_u, snr_v, snr_yuv); 
#endif // _PSNR_YUV_ 
	 
	if (frame_num == 0) 
	{ 
		fSNRY = snr_y; 
		fSNRU = snr_u; 
		fSNRV = snr_v; 
	} 
	// B pictures 
	else 
	{ 
		fSNRY = (float) (fSNRY * frame_num + snr_y) / (frame_num  + 1); // average snr lume for all frames inc. first 
		fSNRU = (float) (fSNRU * frame_num + snr_u) / (frame_num  + 1); // average snr u croma for all frames inc. first 
		fSNRV = (float) (fSNRV * frame_num + snr_v) / (frame_num  + 1); // average snr v croma for all frames inc. first 
	}	 
 
	//gTotalBits += pgcurrBitStream->byte_pos*8;//WJP 050105 
 
	FrameActualBit = pgcurrBitStream->byte_pos*8;           // LX 0409 
 
	g_snr_ya += snr_y; 
	g_snr_ua += snr_u; 
	g_snr_va += snr_v; 
#ifdef _PSNR_YUV_ 
    g_snr_yuva += snr_yuv; 
#endif // _PSNR_YUV_	 
} 
 
 
/* 
************************************************************************* 
* Function: 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
static void error(char *text, int code) 
{ 
	fprintf(stderr, "%s\n", text); 
	exit(code); 
} 
 
/* 
************************************************************************* 
* Function: allocat 2D integer memory 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
void get_mem2Dint(int ***array2D, int rows, int columns) 
{ 
  int i; 
 
  if((*array2D      = (int**)calloc(rows,        sizeof(short*))) == NULL) 
    printf("get_mem2Dint: array2D"); 
  if(((*array2D)[0] = (int* )calloc(rows*columns,sizeof(short ))) == NULL) 
    printf("get_mem2Dint: array2D"); 
 
  for(i=1 ; i