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_ }