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


/*! 
 ************************************************************************************* 
 * \file  decode.c 
 * 
 * \brief 
 *     
 * 
 * \date: updating  
 *      
 * \author     
 *     
 ************************************************************************************* 
 */ 
#include  
#include  
#include  
#include  
#include  
#include  
 
#if defined WIN32 
  #include  
#endif 
 
#include "global.h" 
#include "memalloc.h" 
#include "bitstream.h" 
#include "ldecod.h" 
#include "header.h" 
#include "nalu.h" 
#include "parset.h"  //cbzhu 0412 
//cbzhu 12-15 
#ifdef _ISOLATED_REGION_ 
#include "iREG.h" 
#endif //_ISOLATED_REGION_ 
 
#define RM          "wm" 
#define VERSION     "2.4" 
 
#define LOGFILE     "log.dec" 
#define DATADECFILE "dataDec.txt" 
#define TRACEFILE   "trace_dec.txt" 
 
extern FILE* bits; 
extern void InitiREG(); 
 
/* 
************************************************************************* 
* Function: Main Function  
* Input:    Command Parameter 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
int main(int argc, char **argv) 
{ 
	int current_header; 
	 
	if (argc != 2) 
	{ 
	  snprintf(errortext, ET_SIZE, "Usage: %s  \n\t defines decoder parameters",argv[0]); 
	  error(errortext, 300); 
	} 
	 
 
	//init decoder : readin configure file; allocate bitstreambuffer 
	init_decoder(argv[1]); 
    
	//sequence header, first I picture header 
	//picture header decoding 
	//SPS PPS initialization 
	current_header = Header(); 
   
	// allocate memory for frame buffers 
	init_global_buffers();  
 
	//cbzhu 0412 
#ifdef _ISOLATED_REGION_ 
		if(iREGenable) 
		{ 
			InitiREG(); 
		} 
#endif //_ISOLATED_REGION_ 
 
	if (current_header == EOS) 
		return EOS; 
 
	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_ 
			//cbzhu 041231 
		if(pgImage->number == 0) 
		nb_references = 0; 
			 
		decode_one_frame(snr);// != EOS 
 
		if(pgImage->type == I_IMG) 
			nb_references = 1; 
		else if(p_pic_type == 0) 
		{ 
			nb_references++ ; 
			nb_references = min(nb_references , sps->num_ref_frames); 
		} 
		if(current_header==LPOS)//WJP FOR NAL 
			break; 
		current_header = Header(); 
	} 
 
	 
	//FreePicHeader(picture_header_rbsp); 
	release_decoder(); 
 
	return 0; 
} 
 
/* 
************************************************************************* 
* Function:Read input from configuration file 
* Input:Name of configuration filename 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void read_config_file(char *config_filename) 
{ 
  FILE *fd; 
 
  // read the decoder configuration file 
  if((fd=fopen(config_filename,"r")) == NULL) 
  { 
    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 
 
#if TRACE 
  if ((p_trace=fopen(TRACEFILE,"w"))==0)             // append new statistic at the end 
  { 
    snprintf(errortext, ET_SIZE, "Error open file %s!",TRACEFILE); 
    error(errortext,500); 
  } 
#endif 
 
  if (NULL == (bits=fopen(input->infile, "rb"))) 
  { 
	  snprintf (errortext, ET_SIZE, "Cannot open Annex B ByteStream file '%s'", input->infile); 
	  error(errortext,500); 
  } 
   
  if ((p_out=fopen(input->outfile,"wb"))==0) 
  { 
	  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"); 
#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_ 
} 
 
/* 
************************************************************************* 
* Function:Reports the gathered information to appropriate outputs 
* Input:   struct snr_par *stat 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
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,"--------------------------------------------------------------------------\n"); 
  fprintf(stdout," Exit %s decoder, ver %s ",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); 
} 
 
/* 
************************************************************************* 
* Function:Allocates a Bitstream 
* Input: 
* Output:allocated Bitstream point 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
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; 
} 
 
 
/* 
************************************************************************* 
* Function:Frees a partition structure (array).   
* Input:Partition to be freed, size of partition Array (Number of Partitions) 
* Output: 
* Return:  
* Attention:n must be the same as for the corresponding call of AllocPartition 
************************************************************************* 
*/ 
 
void FreeBitstream () 
{ 
  assert (currStream!= NULL); 
  assert (currStream->streamBuffer != NULL); 
 
	free (currStream->streamBuffer); 
  free (currStream); 
} 
 
/* 
************************************************************************* 
* Function: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() 
* Input: 
* Output:Number of allocated bytes 
* Return:  
* Attention: 
************************************************************************* 
*/ 
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 
//	memory_size += get_mem2Dint(&(pgImage->c_ipredmode),pgImage->width/MB_BLOCK_SIZE +2,vertical_size/MB_BLOCK_SIZE +2 );//MZ 
	// 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); 
} 
 
/* 
************************************************************************* 
* Function:Free allocated memory of frame size related global buffers 
      buffers are defined in global.h, allocated memory is allocated in 
      int init_global_buffers() 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
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); 
//	free_mem2Dint (pgImage->c_ipredmode); 
	for (i=0; i<3; i++) 
	for(j=0;j<3; j++) 
	{ 
		free_mem2D(reference_frame[i][j]); 
	} 
} 
 
/* 
************************************************************************* 
* Function:update the decoder picture buffer 
* Input:frame number in the bitstream and the video sequence 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
 
void Update_Picture_Buffers() 
{  
	unsigned char **tmp; 
	int i; 
	 
  if (p_pic_type==0) 
  { 
    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; 
    } 
  } 
} 
 
/* 
************************************************************************* 
* Function:Initialize decoder 
* Input:config file name 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
void init_decoder(char *config_file) 
{ 
	int i; 
 
	// 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"); 
	 
	//read config file 
	//mapping the configurable parameter to decoding structure. 
	read_config_file(config_file); 
	 
	//allocate stream buffer 
	currStream = AllocBitstream(); 
	 
  // initilize quad matrix used in snr routine 
	for (i=0; i <  256; i++) 
	{ 
		pgImage->quad[i]=i*i;  
	} 
 
	//initialize image number 
	pgImage->number=0; 
 
	// time for total decoding session 
	// Global variable 
	tot_time = 0; 
} 
 
/* 
************************************************************************* 
* Function: release decoder 
* Input: 
* Output: 
* Return:  
* Attention: 
************************************************************************* 
*/ 
void release_decoder() 
{ 
  FreePPS(pps); 
  FreeSPS(sps); 
  report_seq(snr); 
  FreeBitstream(); 
  free_global_buffers(); 
	 
  fclose (bits); 
  fclose(p_out); 
   
	if (p_ref) 
    fclose(p_ref); 
	 
#if TRACE 
  fclose(p_trace); 
#endif 
	 
  free (input); 
  free (snr); 
  free (pgImage); 
}