📄 xvid_stat.c
字号:
framepsnr[filenr] = PSNR(XDIM,YDIM*3/2, in_buffer, XDIM, out_buffer, XDIM); printf("dectime =%6.1f ms PSNR %5.2f\n",dectime, framepsnr[filenr]); if (ARG_SAVEDECOUTPUT) { sprintf(filename, "%sdec%05d.pgm", filepath, filenr); write_pgm(filename, out_buffer); } /* Read the header if it's pgm stream */ if (ARG_INPUTTYPE) status = read_pgmheader(in_file); filenr++; } while ( (!status) && (filenr<ARG_MAXFRAMENR) ); /***************************************************************************** * Calculate totals and averages for output, print results ****************************************************************************/ totalsize /= filenr; totalenctime /= filenr; totaldectime /= filenr; for (i=0;i<filenr;i++) { switch (frame_type[i]) { case 0: Pframes++; Ppsnr += framepsnr[i]; break; case 1: Iframes++; Ipsnr += framepsnr[i]; break; default: break; } } if (Pframes) Ppsnr /= Pframes; if (Iframes) Ipsnr /= Iframes; /* calculate statistics for every frametype: P,I */ for (i=0;i<filenr;i++) { switch (frame_type[i]) { case 0: if (framepsnr[i] > Pmaxpsnr) Pmaxpsnr = framepsnr[i]; if (framepsnr[i] < Pminpsnr) Pminpsnr = framepsnr[i]; Pvarpsnr += (framepsnr[i] - Ppsnr)*(framepsnr[i] - Ppsnr) /Pframes; break; case 1: if (framepsnr[i] > Imaxpsnr) Imaxpsnr = framepsnr[i]; if (framepsnr[i] < Pminpsnr) Iminpsnr = framepsnr[i]; Ivarpsnr += (framepsnr[i] - Ipsnr)*(framepsnr[i] - Ipsnr) /Iframes; default: break; } } /* Print all statistics */ printf("Avg. Q%1d %2s ",ARG_QUALITY, (ARG_QUANTI ? " q" : "br")); printf("%04d ",(ARG_QUANTI)?ARG_QUANTI:ARG_BITRATE); printf("( %.2f bpp) ", (double)ARG_BITRATE*1000/XDIM/YDIM/ARG_FRAMERATE); printf("size %6d ", (int)totalsize); printf("( %4d kbps ",(int)(totalsize*8*ARG_FRAMERATE/1000)); printf("/ %.2f bpp) ",(double)totalsize*8/XDIM/YDIM); printf("enc: %6.1f fps, dec: %6.1f fps \n",1000/totalenctime, 1000/totaldectime); printf("PSNR P(%d): %5.2f ( %5.2f , %5.2f ; %5.4f ) ",Pframes,Ppsnr,Pminpsnr,Pmaxpsnr,sqrt(Pvarpsnr/filenr)); printf("I(%d): %5.2f ( %5.2f , %5.2f ; %5.4f ) ",Iframes,Ipsnr,Iminpsnr,Imaxpsnr,sqrt(Ivarpsnr/filenr)); printf("\n");/***************************************************************************** * XviD PART Stop ****************************************************************************/ release_all: if (enc_handle) { status = enc_stop(); if (status) fprintf(stderr, "Encore RELEASE problem return value %d\n", status); } if (dec_handle) { status = dec_stop(); if (status) fprintf(stderr, "Decore RELEASE problem return value %d\n", status); } fclose(in_file); free_all_memory: free(out_buffer); free(divx_buffer); free(in_buffer); return 0;}/***************************************************************************** * "statistical" functions * * these are not needed for encoding or decoding, but for measuring * time and quality, there in nothing specific to XviD in these * *****************************************************************************//* Return time elapsed time in miliseconds since the program started */static double msecond(){ #ifndef WIN32 struct timeval tv; gettimeofday(&tv, 0); return tv.tv_sec*1.0e3 + tv.tv_usec * 1.0e-3;#else clock_t clk; clk = clock(); return clk * 1000 / CLOCKS_PER_SEC;#endif}/* * Returns the sum of squared distances (SSD) between two images of dimensions * x times y */static double absdistq(int x, int y, unsigned char* buf1, int stride1, unsigned char* buf2, int stride2){ double dist=0.; int i,j,val; for (i=0;i<y;i++) { val=0; for (j=0;j<x;j++) val+= ((int)buf1[j]-(int)buf2[j])*((int)buf1[j]-(int)buf2[j]); dist += (double)val; buf1 += stride1; buf2 += stride2; } return dist/(x*y);}/* * Returns the PSNR between to images. * * This is a common logarithmic measure for "quality" from the world of signal * processing if you don't know what it is, simply accept that higher values * are better. * * PSNR represents the ratio of useful signal over noise signal. In our case, * useful signal is refernce image, noise signal is the difference between * reference and decoded frame from encoded bitstream. * * The problem is this type of value is dependant of image source and so, is * not reliable as a common "quality" indicator. * So PSNR computes the ratio of maximum/noise. Maximum being set to 2^bpp/channel * This way, PSNR is not dependant anymore of image data type. * */static double PSNR(int x, int y, unsigned char* buf1, int stride1, unsigned char* buf2, int stride2){ return 10*(log10(255*255)-log10( absdistq(x, y, buf1, stride1, buf2, stride2) ));}/***************************************************************************** * Usage message *****************************************************************************/static void usage(){ fprintf(stderr, "Usage : xvid_stat [OPTIONS]\n"); fprintf(stderr, "Options :\n"); fprintf(stderr, " -w integer : frame width ([1.2048])\n"); fprintf(stderr, " -h integer : frame height ([1.2048])\n"); fprintf(stderr, " -b integer : target bitrate (>0 | default=900kbit)\n"); fprintf(stderr, " -f float : target framerate (>0)\n"); fprintf(stderr, " -i string : input filename (default=stdin)\n"); fprintf(stderr, " -t integer : input data type (yuv=0, pgm=1)\n"); fprintf(stderr, " -n integer : number of frames to encode\n"); fprintf(stderr, " -q integer : quality ([0..5])\n"); fprintf(stderr, " -d boolean : save decoder output (0 False*, !=0 True)\n"); fprintf(stderr, " -m boolean : save mpeg4 raw stream (0 False*, !=0 True)\n"); fprintf(stderr, " -help : prints this help message\n"); fprintf(stderr, " -quant integer : fixed quantizer (disables -b setting)\n"); fprintf(stderr, " (* means default)\n");}/***************************************************************************** * Input and output functions * * the are small and simple routines to read and write PGM and YUV * image. It's just for convenience, again nothing specific to XviD * *****************************************************************************/static int read_pgmheader(FILE* handle){ int bytes,xsize,ysize,depth; char dummy[2]; bytes = fread(dummy,1,2,handle); if ( (bytes < 2) || (dummy[0] != 'P') || (dummy[1] != '5' )) return 1; fscanf(handle,"%d %d %d",&xsize,&ysize,&depth); if ( (xsize > 1440) || (ysize > 2880 ) || (depth != 255) ) { fprintf(stderr,"%d %d %d\n",xsize,ysize,depth); return 2; } if ( (XDIM==0) || (YDIM==0) ) { XDIM=xsize; YDIM=ysize*2/3; } return 0;}static int read_pgmdata(FILE* handle, unsigned char *image){ int i; char dummy; unsigned char *y = image; unsigned char *u = image + XDIM*YDIM; unsigned char *v = image + XDIM*YDIM + XDIM/2*YDIM/2; /* read Y component of picture */ fread(y, 1, XDIM*YDIM, handle); for (i=0;i<YDIM/2;i++) { /* read U */ fread(u, 1, XDIM/2, handle); /* read V */ fread(v, 1, XDIM/2, handle); /* Update pointers */ u += XDIM/2; v += XDIM/2; } /* I don't know why, but this seems needed */ fread(&dummy, 1, 1, handle); return 0;}static int read_yuvdata(FILE* handle, unsigned char *image){ if (fread(image, 1, IMAGE_SIZE(XDIM, YDIM), handle) != (unsigned int)IMAGE_SIZE(XDIM, YDIM)) return 1; else return 0;}static int write_pgm(char *filename, unsigned char *image){ int loop; unsigned char *y = image; unsigned char *u = image + XDIM*YDIM; unsigned char *v = image + XDIM*YDIM + XDIM/2*YDIM/2; FILE *filehandle; filehandle=fopen(filename,"w+b"); if (filehandle) { /* Write header */ fprintf(filehandle,"P5\n\n%d %d 255\n", XDIM,YDIM*3/2); /* Write Y data */ fwrite(y, 1, XDIM*YDIM, filehandle); for(loop=0; loop<YDIM/2; loop++) { /* Write U scanline */ fwrite(u, 1, XDIM/2, filehandle); /* Write V scanline */ fwrite(v, 1, XDIM/2, filehandle); /* Update pointers */ u += XDIM/2; v += XDIM/2; } /* Close file */ fclose(filehandle); return 0; } else return 1;}/***************************************************************************** * Routines for encoding: init encoder, frame step, release encoder ****************************************************************************/#define FRAMERATE_INCR 1001/* Initialize encoder for first use, pass all needed parameters to the codec */static int enc_init(int use_assembler){ int xerr; XVID_INIT_PARAM xinit; XVID_ENC_PARAM xparam; if(use_assembler) {#ifdef ARCH_IA64 xinit.cpu_flags = XVID_CPU_FORCE | XVID_CPU_IA64;#else xinit.cpu_flags = 0;#endif } else { xinit.cpu_flags = XVID_CPU_FORCE; } xvid_init(NULL, 0, &xinit, NULL); xparam.width = XDIM; xparam.height = YDIM; if ((ARG_FRAMERATE - (int)ARG_FRAMERATE) < SMALL_EPS) { xparam.fincr = 1; xparam.fbase = (int)ARG_FRAMERATE; } else { xparam.fincr = FRAMERATE_INCR; xparam.fbase = (int)(FRAMERATE_INCR * ARG_FRAMERATE); } xparam.rc_reaction_delay_factor = 16; xparam.rc_averaging_period = 100; xparam.rc_buffer = 10; xparam.rc_bitrate = ARG_BITRATE*1000; xparam.min_quantizer = ARG_MINQUANT; xparam.max_quantizer = ARG_MAXQUANT; xparam.max_key_interval = (int)ARG_FRAMERATE*10; /* I use a small value here, since will not encode whole movies, but short clips */ xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xparam, NULL); enc_handle=xparam.handle; return xerr;}static int enc_stop(){ int xerr; xerr = xvid_encore(enc_handle, XVID_ENC_DESTROY, NULL, NULL); return xerr;}static int enc_main(unsigned char* image, unsigned char* bitstream, unsigned char* hints_buffer, long *streamlength, long* frametype, long* hints_size){ int xerr; XVID_ENC_FRAME xframe; XVID_ENC_STATS xstats; xframe.bitstream = bitstream; xframe.length = -1; /* this is written by the routine */ xframe.image = image; xframe.colorspace = XVID_CSP_YV12; /* defined in <xvid.h> */ xframe.intra = -1; /* let the codec decide between I-frame (1) and P-frame (0) */ xframe.quant = ARG_QUANTI; /* is quant != 0, use a fixed quant (and ignore bitrate) */ xframe.motion = motion_presets[ARG_QUALITY]; xframe.general = general_presets[ARG_QUALITY]; xframe.quant_intra_matrix = xframe.quant_inter_matrix = NULL; xframe.hint.hintstream = hints_buffer; if(ARG_HINTMODE == HINT_MODE_SET) { xframe.hint.hintlength = *hints_size; xframe.hint.rawhints = 0; xframe.general |= XVID_HINTEDME_SET; } if(ARG_HINTMODE == HINT_MODE_GET) { xframe.hint.rawhints = 0; xframe.general |= XVID_HINTEDME_GET; } xerr = xvid_encore(enc_handle, XVID_ENC_ENCODE, &xframe, &xstats); if(ARG_HINTMODE == HINT_MODE_GET) *hints_size = xframe.hint.hintlength; /* * This is statictical data, e.g. for 2-pass. If you are not * interested in any of this, you can use NULL instead of &xstats */ *frametype = xframe.intra; *streamlength = xframe.length; return xerr;}/***************************************************************************** * Routines for decoding: init encoder, frame step, release encoder ****************************************************************************//* init decoder before first run */static int dec_init(int use_assembler){ int xerr; XVID_INIT_PARAM xinit; XVID_DEC_PARAM xparam; if(use_assembler)#ifdef ARCH_IA64 xinit.cpu_flags = XVID_CPU_FORCE | XVID_CPU_IA64;#else xinit.cpu_flags = 0;#endif else xinit.cpu_flags = XVID_CPU_FORCE; xvid_init(NULL, 0, &xinit, NULL); xparam.width = XDIM; xparam.height = YDIM; xerr = xvid_decore(NULL, XVID_DEC_CREATE, &xparam, NULL); dec_handle = xparam.handle; return xerr;}/* decode one frame */static int dec_main(unsigned char *m4v_buffer, unsigned char *out_buffer, int m4v_size){ int xerr; XVID_DEC_FRAME xframe; xframe.bitstream = m4v_buffer; xframe.length = m4v_size; xframe.image = out_buffer; xframe.stride = XDIM; xframe.colorspace = XVID_CSP_YV12; /* XVID_CSP_USER is fastest (no memcopy involved) */ xerr = xvid_decore(dec_handle, XVID_DEC_DECODE, &xframe, NULL); return xerr;}/* close decoder to release resources */static int dec_stop(){ int xerr; xerr = xvid_decore(dec_handle, XVID_DEC_DESTROY, NULL, NULL); return xerr;}/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -