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; i pic_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; h img_height/BLOCK_SIZE+4; h++) for(w=0; w img_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; h img_height/BLOCK_SIZE+4; h++) for(w=0; w img_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;i total_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