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); }