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


/*! 
 ************************************************************************************* 
 * \file   
 *    decode.c 
 * \brief 
 *    AVS-M decoder main function including memory initialization, 
 *    variable definition and declaration etc. 
 * 
 * 
 * 
 * 
 ************************************************************************************* 
 */ 
 
#include  
#include  
//#include  
#include  
#if defined WIN32 
  #include  
#endif 
 
#include "global.h" 
#include "memalloc.h" 
#include "header.h" 
#include "parset.h"   
#include "global_define.h" 
 
#ifdef _ISOLATED_REGION_ 
 #include "IREG.h" 
#endif 
 
#ifdef _HRD_ 
 #include "HRD.h" 
#endif  
 
#define RM          "AVS-M WM" 
#define VERSION     "3.3" 
 
#define LOGFILE     "log.dec" 
#define DATADECFILE "dataDec.txt" 
#define TRACEFILE   "trace_dec.txt"      /* bitstream decoding processing statistics */ 
#define ERRFILE     "error_report.txt"   /* bitstream conformance statistics */ 
 
 
extern void InitiREG(); 
 
/*! 
************************************************************************ 
* \brief 
*    main function for AVS-M decoder. 
************************************************************************ 
*/ 
int main(int argc, char **argv) 
{ 
	int current_header; 
	init_decoder("c:\\avs-m\\decoderavs-m.cfg"); 
	//sequence header, first I picture header 
	//picture header decoding 
	//SPS PPS initialization 
 
	current_header = read_new_byte_stream(); 
     
 	 /* global memory allocation -- temporary location -- Aug 21st */ 
 	 init_global_buffers(); 
 
#ifdef _HRD_ 
  init_dpb(); 
#endif 
 
	//cbzhu 0412 
#ifdef _ISOLATED_REGION_ 
  if(iREGenable) 
	  InitiREG(); 
#endif //_ISOLATED_REGION_ 
 
  while (current_header==SOP||current_header==LPOS)//WJP FOR NAL 
	{ 
		//cbzhu 0412 
#ifdef _ISOLATED_REGION_ 
	  if(iREGenable) 
		{ 
		  if(pgImage->number== 0) 
        iREGstate=0; 
		} 
#endif //_ISOLATED_REGION_ 
 
		decode_one_picture(snr);// != EOS 
		 
		if(current_header==LPOS)//WJP FOR NAL 
			break; 
		current_header = read_new_byte_stream(); 
	} 
 
  /* bistream conformance checking */ 
  stat_parameter->tot_frame_number = pgImage->number; 
 
#if ERR_REPORT 
  CheckBitstreamStatus(p_err);  /* Bitstream Conformance Statistics Printout */ 
#endif 
   
	release_decoder(); 
 
	return 0; 
} 
 
 
/*!  
 ************************************************************************************* 
 * \brief : :Read input from configuration file 
 ************************************************************************************* 
 */ 
void read_configfile(char *config_filename) 
{ 
  FILE *fd; 
 
  // read the decoder configuration file 
  if( NULL == (fd=fopen(config_filename,"r")) ) 
  { 
    snprintf(errortext, ET_SIZE, "Error: Control file %s not found\n",config_filename); 
    error(errortext, 300); 
  } 
 
  fscanf(fd,"%s",input->infile);                // input bitstream file 
  fscanf(fd,"%*[^\n]"); 
 
  fscanf(fd,"%s",input->outfile);               // output picture file 
  fscanf(fd,"%*[^\n]"); 
 
  fscanf(fd,"%s",input->reffile);               // reference file 
  fscanf(fd,"%*[^\n]"); 
 
#ifdef _ISOLATED_REGION_ 
  fscanf(fd,"%d",&iREGenable); 
  fscanf(fd,"%*[^\n]"); 
 
  fscanf(fd,"%d",&iREGrate); 
  fscanf(fd,"%*[^\n]"); 
 
#endif 
 
#ifdef _HRD_ 
  fscanf(fd,"%ld,",&input->R_decoder);             // Decoder rate 
  fscanf(fd, "%*[^\n]"); 
  fscanf(fd,"%ld,",&input->B_decoder);             // Decoder buffer size 
  fscanf(fd, "%*[^\n]"); 
  fscanf(fd,"%ld,",&input->F_decoder);             // Decoder initial delay 
  fscanf(fd, "%*[^\n]");  
  fscanf(fd,"%s",input->LeakyBucketParamFile);    // file where Leaky Bucket params (computed by encoder) are stored 
  fscanf(fd,"%*[^\n]"); 
#endif // _HRD_ 
 
 
 
#if TRACE 
  if ( NULL == (p_trace=fopen(TRACEFILE,"w")) )        //!infile, "rb")) )    //!< open bitstream file in bit format 
//  { 
//	  snprintf (errortext, ET_SIZE, "Cannot open Annex B ByteStream file '%s'", input->infile); 
//	  error(errortext,500); 
//  } 
   
  if ( NULL ==(p_out=fopen(input->outfile,"wb")) )   //!< write out dec.yuv in bit format 
  { 
	  snprintf(errortext, ET_SIZE, "Error open file %s ",input->outfile); 
	  error(errortext,500); 
  } 
 
  fprintf(stdout,"--------------------------------------------------------------------------\n"); 
  fprintf(stdout," Decoder config file                    : %s \n",config_filename); 
  fprintf(stdout,"--------------------------------------------------------------------------\n"); 
  fprintf(stdout," Input  bitstream file                  : %s \n",input->infile); 
  fprintf(stdout," Output decoded YUV 4:2:0               : %s \n",input->outfile); 
  fprintf(stdout," Output status file                     : %s \n",LOGFILE); 
 
  if ((p_ref=fopen(input->reffile,"rb"))==0) 
  { 
    fprintf(stdout," Input reference file                   : %s does not exist \n",input->reffile); 
    fprintf(stdout,"                                          SNR values are not available\n"); 
  } 
  else 
    fprintf(stdout," Input reference file                   : %s \n",input->reffile); 
 
  fprintf(stdout,"--------------------------------------------------------------------------\n"); 
 
  //added by yiwang, 2005.3.19 
#ifdef _HRD_ 
  if(fopen(input->LeakyBucketParamFile,"rb")) 
  { 
	  fprintf(stdout," Rate_decoder        : %8ld \n",input->R_decoder); 
	  fprintf(stdout," B_decoder           : %8ld \n",input->B_decoder); 
	  fprintf(stdout," F_decoder           : %8ld \n",input->F_decoder); 
	  fprintf(stdout," LeakyBucketParamFile: %s \n",input->LeakyBucketParamFile); // Leaky Bucket Param file 
	  calc_buffer(input); 
	  fprintf(stdout,"--------------------------------------------------------------------------\n"); 
  } 
#endif // _HRD_ 
 
#ifndef _PSNR_YUV_ 
  fprintf(stdout," Frame      QP  SnrY    SnrU    SnrV   Time(ms)\n"); 
#else 
  fprintf(stdout," Frame      QP  SnrY    SnrU    SnrV    SnrYUV   Time(ms)\n"); 
#endif // _PSNR_YUV_ 
} 
 
 
/*!  
 ************************************************************************************* 
 * \brief : Reports the gathered information to appropriate outputs 
 ************************************************************************************* 
 */ 
void report_seq(struct snr_par *snr) 
{ 
  #define OUTSTRING_SIZE 255 
  char string[OUTSTRING_SIZE]; 
  FILE *p_log; 
 
#ifndef WIN32 
  time_t  now; 
  struct tm *l_time; 
#else 
  char timebuf[128]; 
#endif 
 
  fprintf(stdout,"-------------------- Average SNR all frames ------------------------------\n"); 
  fprintf(stdout," SNR Y(dB)           : %5.2f\n",snr->snr_ya); 
  fprintf(stdout," SNR U(dB)           : %5.2f\n",snr->snr_ua); 
  fprintf(stdout," SNR V(dB)           : %5.2f\n",snr->snr_va); 
#ifdef _PSNR_YUV_ 
  fprintf(stdout," SNR YUV(dB)         : %5.2f\n",snr->snr_yuva); 
#endif // _PSNR_YUV_ 
   
  fprintf(stdout," Total decoding time : %.3f sec \n",tot_time*0.001); 
  fprintf(stdout," Decoding Frames/sec : %.3f fps \n",stat_parameter->tot_frame_number/(tot_time*0.001)); 
  fprintf(stdout,"--------------------------------------------------------------------------\n"); 
  fprintf(stdout," Exit %s decoder, ver %s \n",RM,VERSION); 
  fprintf(stdout,"\n"); 
  // write to log file 
 
  snprintf(string, OUTSTRING_SIZE, "%s", LOGFILE); 
  if ((p_log=fopen(string,"r"))==0)                    // check if file exist 
  { 
    if ((p_log=fopen(string,"a"))==0) 
    { 
      snprintf(errortext, ET_SIZE, "Error open file %s for appending",string); 
      error(errortext, 500); 
    } 
    else                                              // Create header to new file 
    { 
      fprintf(p_log," ------------------------------------------------------------------------------------------\n"); 
      fprintf(p_log,"|  Decoder statistics. This file is made first time, later runs are appended               |\n"); 
      fprintf(p_log," ------------------------------------------------------------------------------------------ \n"); 
      fprintf(p_log,"| Date  | Time  |    Sequence        |#Img|Format|SNRY 1|SNRU 1|SNRV 1|SNRY N|SNRU N|SNRV N|\n"); 
      fprintf(p_log," ------------------------------------------------------------------------------------------\n"); 
    } 
  } 
  else 
  {  
    fclose(p_log); 
    p_log=fopen(string,"a");                    // File exist,just open for appending 
  } 
 
#ifdef WIN32 
  _strdate( timebuf ); 
  fprintf(p_log,"| %1.5s |",timebuf ); 
 
  _strtime( timebuf); 
  fprintf(p_log," % 1.5s |",timebuf); 
#else 
  now = time ((time_t *) NULL); // Get the system time and put it into 'now' as 'calender time' 
  time (&now); 
  l_time = localtime (&now); 
  strftime (string, sizeof string, "%d-%b-%Y", l_time); 
  fprintf(p_log,"| %1.5s |",string ); 
 
  strftime (string, sizeof string, "%H:%M:%S", l_time); 
  fprintf(p_log,"| %1.5s |",string ); 
#endif 
 
  fprintf(p_log,"%20.20s|",input->infile); 
 
  fprintf(p_log,"%3d |",pgImage->number); 
 
  fprintf(p_log,"%6.3f|",snr->snr_y1); 
  fprintf(p_log,"%6.3f|",snr->snr_u1); 
  fprintf(p_log,"%6.3f|",snr->snr_v1); 
  fprintf(p_log,"%6.3f|",snr->snr_ya); 
  fprintf(p_log,"%6.3f|",snr->snr_ua); 
  fprintf(p_log,"%6.3f|\n",snr->snr_va); 
 
  fclose(p_log); 
 
  snprintf(string, OUTSTRING_SIZE,"%s", DATADECFILE); 
  p_log=fopen(string,"a"); 
 
   
  fprintf(p_log, "%3d %2d %2d %2.2f %2.2f %2.2f %5d " 
      "%2.2f %2.2f %2.2f %5d " 
      "%2.2f %2.2f %2.2f %5d %.3f\n", 
      pgImage->number, 0, pgImage->qp, 
      snr->snr_y1, 
      snr->snr_u1, 
      snr->snr_v1, 
      0, 
      0.0, 
      0.0, 
      0.0, 
      0, 
      snr->snr_ya, 
      snr->snr_ua, 
      snr->snr_va, 
      0, 
      (double)0.001*tot_time/pgImage->number); 
   
  fclose(p_log); 
} 
 
/*!  
 ************************************************************************************* 
 * \brief : Allocates a Bitstream 
 ************************************************************************************* 
 */ 
Bitstream *AllocBitstream() 
{ 
	 Bitstream *bitstream; 
	  
	 bitstream = (Bitstream *) calloc(1, sizeof(Bitstream)); 
	  
	 if (bitstream == NULL) 
	 { 
		 snprintf(errortext, ET_SIZE, "AllocBitstream: Memory allocation for Bitstream failed"); 
		 error(errortext, 100); 
	 } 
	  
	 bitstream->streamBuffer = (byte *) calloc(MAX_CODED_FRAME_SIZE, sizeof(byte)); 
	  
	 if (bitstream->streamBuffer == NULL) 
	 { 
		 snprintf(errortext, ET_SIZE, "AllocBitstream: Memory allocation for streamBuffer failed"); 
		 error(errortext, 100); 
	 } 
 
	 return bitstream; 
} 
 
/*!  
 ************************************************************************************* 
 * \brief : Frees a partition structure (array).   
 ************************************************************************************* 
 */ 
void FreeBitstream () 
{ 
  assert (currStream!= NULL); 
  assert (currStream->streamBuffer != NULL); 
 
	free (currStream->streamBuffer); 
  free (currStream); 
} 
 
/*!  
 ************************************************************************************* 
 * \brief :  
 *    Dynamic memory allocation of frame size related global buffers 
 *    buffers are defined in global.h, allocated memory must be freed in 
 *    void free_global_buffers()  
 ************************************************************************************* 
 */ 
int init_global_buffers() 
{ 
	int i; 
	int refnum; 
	 
	int memory_size=0; 
	 
		// allocate memory for reference frames of each block: refFrArr 
	memory_size += get_mem2Dint(&refFrArr, vertical_size/BLOCK_SIZE, pgImage->width/BLOCK_SIZE);    //zhangnan 
	 
	// allocate memory for reference frame in find_snr 
	memory_size += get_mem2D(&imgY_ref, vertical_size, pgImage->width); 
	memory_size += get_mem3D(&imgUV_ref, 2, vertical_size/2, pgImage->width_cr); 
	 
	// allocate memory in structure pgImage 
	if(((mb_data) = (Macroblock *) calloc((pgImage->width/MB_BLOCK_SIZE) * (vertical_size/MB_BLOCK_SIZE),sizeof(Macroblock))) == NULL) 
		no_mem_exit("init_global_buffers: mb_data"); 
	 
	memory_size += get_mem3Dint(&(pgImage->mv),pgImage->width/BLOCK_SIZE +4, vertical_size/BLOCK_SIZE,3);     //zhangnan 
	memory_size += get_mem2Dint(&(pgImage->ipredmode),pgImage->width/BLOCK_SIZE +2 , vertical_size/BLOCK_SIZE +2);    //qwang 2004-3-9 
 
	// allocate frame buffer 
	for(refnum=0; refnum<3; refnum++) 
		for (i=0; i<3; i++) 
		{ 
			if (i==0) 
				get_mem2D(&reference_frame[refnum][i],vertical_size,pgImage->width); 
      else 
				get_mem2D(&reference_frame[refnum][i],vertical_size/2,pgImage->width_cr); 
		} 
 
		//forward reference frame buffer 
		current_frame = reference_frame[2];	 
 
		//cbzhu 0412 
#ifdef _ISOLATED_REGION_ 
		if(iREGenable) 
			memory_size+=get_mem2Dint(&iREGmap,pgImage->height/MB_BLOCK_SIZE,pgImage->width/MB_BLOCK_SIZE); 
#endif //_ISOLATED_REGION_ 
		 
    return (memory_size); 
} 
 
/*!  
 ************************************************************************************* 
 * \brief :  
 *    Free allocated memory of frame size related global buffers 
 *    buffers are defined in global.h, allocated memory is allocated in 
 *    int init_global_buffers() 
 ************************************************************************************* 
 */ 
void free_global_buffers() 
{ 
	int  i,j; 
	 
	free_mem2D (imgY_ref); 
	free_mem3D (imgUV_ref,2); 
	 
	// free mem, allocated for structure pgImage 
	if (mb_data       != NULL) free(mb_data); 
 
	free_mem3Dint (pgImage->mv,pgImage->width/B8_SIZE + 4); 
	free_mem2Dint (pgImage->ipredmode); 
 
 
	for (i=0; i<3; i++) 
	  for(j=0;j<3; j++) 
  		free_mem2D(reference_frame[i][j]); 
 
 
} 
 
/*!  
 ************************************************************************************* 
 * \brief :  
 *    update the decoder picture buffer 
 ************************************************************************************* 
 */ 
void Update_Picture_Buffers() 
{  
	unsigned char **tmp; 
	int i; 
	 
  if (pgImage->idr_flag == 1) /* accurate? */ 
    pgImage->is_ref0_an_IDR  = 1; 
  else 
    pgImage->is_ref0_an_IDR  = 0;    /* check current picture is IDR frame or not */ 
 
  //fprintf(stdout,"%d\n",pgImage->is_ref0_an_IDR); 
 
  /* update picture bufffer for next frame decoding */ 
  if (!pgImage->pic_ref_flag) /* pic_ref_flag = 0 --> to be used as reference frame */ 
  { 
    if (pgImage->active_num_ref_frames == sps->num_ref_frames) 
    { 
      if(pgImage->ssw == 2) 
      { 
        for(i=0; i<3; i++) 
        { 
          tmp = reference_frame[1][i]; 
          reference_frame[1][i] = reference_frame[0][i]; 
          reference_frame[0][i] = current_frame[i];	 
          current_frame[i] = tmp; 
        } 
      } 
      else if (pgImage->ssw == 1) 
      { 
        for(i=0; i<3; i++) 
        { 
          tmp = reference_frame[0][i]; 
          reference_frame[0][i] = current_frame[i]; 
          current_frame[i] = tmp; 
        }       
      } 
    } 
    else 
    { 
      for(i=0; i<3; i++) 
      { 
        tmp = reference_frame[1][i]; 
        reference_frame[1][i] = reference_frame[0][i]; 
        reference_frame[0][i] = current_frame[i];	 
        current_frame[i] = tmp; 
      } 
        
    } 
 
  } 
 
   if(pgImage->idr_flag == 1) 
   { 
		  pgImage->active_num_ref_frames = 1; 
   } 
	 else if(!pgImage->pic_ref_flag) 
   { 
		 pgImage->active_num_ref_frames++ ; 
	 	 pgImage->active_num_ref_frames = min(pgImage->active_num_ref_frames , sps->num_ref_frames); 
   } 
 
} 
 
 
 
/*!  
 ************************************************************************************* 
 * \brief :  
 *    Initialize decoder 
 ************************************************************************************* 
 */ 
void init_decoder(char *config_file) 
{ 
	int i; 
  seq_parameter_set *sps_t[16]; 
  pic_parameter_set *pps_t[128]; 
 
	// allocate memory for the structures 
	if ((input =  (struct inp_par *)calloc(1, sizeof(struct inp_par)))==NULL) no_mem_exit("main: input"); 
	if ((snr =  (struct snr_par *)calloc(1, sizeof(struct snr_par)))==NULL) no_mem_exit("main: snr"); 
	if ((pgImage =  (struct img_par *)calloc(1, sizeof(struct img_par)))==NULL) no_mem_exit("main: pgImage"); 
  if ((stat_parameter =  (StatParameter *)calloc(1, sizeof(StatParameter)))==NULL) no_mem_exit("main: bistream conformance stat"); 
	 
	//read config file 
	//mapping the configurable parameter to decoding structure. 
	read_configfile(config_file); 
	 
  OpenAnnexbFile("c:\\avs-m\\test.avs"); 
 
	//allocate stream buffer 
	currStream = AllocBitstream(); 
   
 
  for(i=0;i<16;i++) 
  {  
    sps_t[i] = AllocSPS(); 
    sps_buf[i] = sps_t[i]; 
  } 
 
	   
  for(i=0;i<128;i++) 
  { 
    pps_t[i]   = AllocPPS(); 
    pps_buf[i] = pps_t[i]; 
  } 
	 
  // initilize quad matrix used in snr routine 
	for (i=0; i <  256; i++) 
	{ 
		pgImage->quad[i]=i*i;  
	} 
 
	//initialize image number 
	pgImage->number=0; 
 
	// Global time for total decoding session 
	tot_time = 0; 
} 
 
/*!  
 ************************************************************************************* 
 * \brief :  
 *     release decoder 
 ************************************************************************************* 
 */ 
void release_decoder() 
{ 
  FreePPS(pps); 
  FreeSPS(sps); 
  report_seq(snr); 
  FreeBitstream(); 
  free_global_buffers(); 
	 
  CloseAnnexbFile(); 
  //fclose (bits); 
  fclose(p_out); 
   
	if (p_ref) 
    fclose(p_ref); 
	 
#if TRACE 
  fclose(p_trace); 
#endif 
	 
  free (input); 
  free (snr); 
  free (pgImage); 
 
#ifdef _HRD_ 
	end_hrd(); 
  free_dpb(); 
#endif // _HRD_ 
 
}