📄 xvid_stat.c
字号:
/***************************************************************************** * * XVID MPEG-4 VIDEO CODEC * - Console based test application - * * Copyright(C) 2002 Christoph Lampert * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: xvid_stat.c,v 1.19 2003/02/09 19:32:52 edgomez Exp $ * ****************************************************************************//***************************************************************************** * Application notes : * * A sequence of YUV pics in PGM file format is encoded and decoded * The speed is measured and PSNR of decoded picture is calculated. * * The program is plain C and needs no libraries except for libxvidcore, * and maths-lib. * * Usage : xvid_stat [OPTIONS] * Options : * -w integer : frame width ([1.2048]) * -h integer : frame height ([1.2048]) * -b integer : target bitrate (>0 | default=900kbit) * -f float : target framerate (>0) * -i string : input filename (default=stdin) * -t integer : input data type (yuv=0, pgm=1) * -n integer : number of frames to encode * -q integer : quality ([0..5]) * -d boolean : save decoder output (0 False*, !=0 True) * -m boolean : save mpeg4 raw stream (0 False*, !=0 True) * -mv integer : Hinted Motion Estimation (0 none, 1 get hints, 2 set hints) * -help : prints this help message * -quant integer : fixed quantizer (disables -b setting) * (* means default) * * An input file named "stdin" is treated as standard input stream. * * * PGM input must be in a very specific format, basically it pgm file must * contain Y plane first just like usual P5 pgm files, and then U and V * planes are stored just after Y plane so y dimension is y*3/2 in reality * * See read_pgmheader for more details. * * Such a PGM file can be generated from MPEG2 by # mpeg2dec -o pgmpipe * ****************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#ifndef WIN32#include <sys/time.h>#else#include <time.h>#endif#include "xvid.h"/**************************************************************************** * Prototypes ***************************************************************************//* Prints program usage message */static void usage();/* Statistical functions */static double msecond();static double absdistq(int x, int y, unsigned char* buf1, int stride1, unsigned char* buf2, int stride2);static double PSNR(int x, int y, unsigned char* buf1, int stride1, unsigned char* buf2, int stride2);/* PGM related functions */static int read_pgmheader(FILE* handle);static int read_pgmdata(FILE* handle, unsigned char *image);static int read_yuvdata(FILE* handle, unsigned char *image);static int write_pgm(char *filename, unsigned char *image);/* Encoder related functions */static int enc_init(int use_assembler);static int enc_stop();static int enc_main(unsigned char* image, unsigned char* bitstream, unsigned char* hints_buffer, long *streamlength, long* frametype, long* hints_size);/* Decoder related functions */static int dec_stop();static int dec_main(unsigned char *m4v_buffer, unsigned char *out_buffer, int m4v_size);static int dec_init(int use_assembler);/***************************************************************************** * Quality presets ****************************************************************************/static int const motion_presets[7] = { 0, /* Q 0 */ PMV_EARLYSTOP16, /* Q 1 */ PMV_EARLYSTOP16, /* Q 2 */ PMV_EARLYSTOP16 | PMV_HALFPELREFINE16, /* Q 3 */ PMV_EARLYSTOP16 | PMV_HALFPELREFINE16, /* Q 4 */ PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EARLYSTOP8 | /* Q 5 */ PMV_HALFPELREFINE8, PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EXTSEARCH16 | /* Q 6 */ PMV_USESQUARES16 | PMV_EARLYSTOP8 | PMV_HALFPELREFINE8};static int const general_presets[7] = { XVID_H263QUANT, /* Q 0 */ XVID_MPEGQUANT, /* Q 1 */ XVID_H263QUANT, /* Q 2 */ XVID_H263QUANT | XVID_HALFPEL, /* Q 3 */ XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V, /* Q 4 */ XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V, /* Q 5 */ XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V /* Q 6 */}; /***************************************************************************** * Command line global variables ****************************************************************************//* Maximum number of frames to encode */#define ABS_MAXFRAMENR 9999/* HINTMODEs */#define HINT_MODE_NONE 0#define HINT_MODE_GET 1#define HINT_MODE_SET 2#define HINT_FILE "hints.mv"static int ARG_BITRATE = 900;static int ARG_QUANTI = 0;static int ARG_QUALITY = 6;static int ARG_MINQUANT = 1;static int ARG_MAXQUANT = 31;static float ARG_FRAMERATE = 25.00f;static int ARG_MAXFRAMENR = ABS_MAXFRAMENR;static char *ARG_INPUTFILE = NULL;static int ARG_INPUTTYPE = 0;static int ARG_SAVEDECOUTPUT = 0;static int ARG_SAVEMPEGSTREAM = 0;static int ARG_HINTMODE = HINT_MODE_NONE;static int XDIM = 0;static int YDIM = 0;#define IMAGE_SIZE(x,y) ((x)*(y)*3/2)#define MAX(A,B) ( ((A)>(B)) ? (A) : (B) )#define SMALL_EPS 1e-10#define LONG_PACK(a,b,c,d) ((long) (((long)(a))<<24) | (((long)(b))<<16) | \ (((long)(c))<<8) |((long)(d)))#define SWAP(a) ( (((a)&0x000000ff)<<24) | (((a)&0x0000ff00)<<8) | \ (((a)&0x00ff0000)>>8) | (((a)&0xff000000)>>24) )/**************************************************************************** * Nasty global vars ;-) ***************************************************************************/static int i,filenr = 0;static int save_ref_flag = 0;/* the path where to save output */static char filepath[256] = "./";/* Internal structures (handles) for encoding and decoding */static void *enc_handle = NULL;static void *dec_handle = NULL;/***************************************************************************** * Main program ****************************************************************************/int main(int argc, char *argv[]){ unsigned char *divx_buffer = NULL; unsigned char *in_buffer = NULL; unsigned char *out_buffer = NULL; unsigned char *hints_buffer = NULL; double enctime,dectime; double totalenctime=0.; double totaldectime=0.; long totalsize = 0; long hints_size = 0; int status; int bigendian = 0; long m4v_size = 0; long frame_type[ABS_MAXFRAMENR]; int Iframes=0, Pframes=0, use_assembler=0; double framepsnr[ABS_MAXFRAMENR]; double Ipsnr=0.,Imaxpsnr=0.,Iminpsnr=999.,Ivarpsnr=0.; double Ppsnr=0.,Pmaxpsnr=0.,Pminpsnr=999.,Pvarpsnr=0.; char filename[256]; FILE *filehandle; FILE *in_file = stdin; FILE *hints_file = NULL; printf("xvid_stat - XviD core library test program "); printf("written by Christoph Lampert 2002\n\n");/***************************************************************************** * Command line parsing ****************************************************************************/ for (i=1; i< argc; i++) { if (strcmp("-asm", argv[i]) == 0 ) { use_assembler = 1; } else if (strcmp("-w", argv[i]) == 0 && i < argc - 1 ) { i++; XDIM = atoi(argv[i]); } else if (strcmp("-h", argv[i]) == 0 && i < argc - 1 ) { i++; YDIM = atoi(argv[i]); } else if (strcmp("-b", argv[i]) == 0 && i < argc - 1 ) { i++; ARG_BITRATE = atoi(argv[i]); } else if (strcmp("-q", argv[i]) == 0 && i < argc - 1 ) { i++; ARG_QUALITY = atoi(argv[i]); } else if (strcmp("-f", argv[i]) == 0 && i < argc - 1 ) { i++; ARG_FRAMERATE = (float)atof(argv[i]); } else if (strcmp("-i", argv[i]) == 0 && i < argc - 1 ) { i++; ARG_INPUTFILE = argv[i]; } else if (strcmp("-t", argv[i]) == 0 && i < argc - 1 ) { i++; ARG_INPUTTYPE = atoi(argv[i]); } else if(strcmp("-n", argv[i]) == 0 && i < argc - 1 ) { i++; ARG_MAXFRAMENR = atoi(argv[i]); } else if (strcmp("-quant", argv[i]) == 0 && i < argc - 1 ) { i++; ARG_QUANTI = atoi(argv[i]); } else if (strcmp("-d", argv[i]) == 0 && i < argc - 1 ) { i++; ARG_SAVEDECOUTPUT = atoi(argv[i]); } else if (strcmp("-m", argv[i]) == 0 && i < argc - 1 ) { i++; ARG_SAVEMPEGSTREAM = atoi(argv[i]); } else if (strcmp("-mv", argv[i]) == 0 && i < argc - 1 ) { i++; ARG_HINTMODE = atoi(argv[i]); } else if (strcmp("-help", argv[i])) { usage(); return(0); } else { usage(); exit(-1); } } /***************************************************************************** * Arguments checking ****************************************************************************/ if (XDIM <= 0 || XDIM >= 2048 || YDIM <=0 || YDIM >= 2048 ) { fprintf(stderr, "Trying to retreive width and height from PGM header\n"); ARG_INPUTTYPE = 1; /* pgm */ } if ( ARG_QUALITY < 0 || ARG_QUALITY > 6) { fprintf(stderr,"Wrong Quality\n"); return -1; } if ( ARG_BITRATE <= 0 && ARG_QUANTI == 0) { fprintf(stderr,"Wrong Bitrate\n"); return -1; } if ( ARG_FRAMERATE <= 0) { fprintf(stderr,"Wrong Framerate %s \n",argv[5]); return -1; } if ( ARG_MAXFRAMENR <= 0) { fprintf(stderr,"Wrong number of frames\n"); return -1; } if ( ARG_HINTMODE != HINT_MODE_NONE && ARG_HINTMODE != HINT_MODE_GET && ARG_HINTMODE != HINT_MODE_SET) ARG_HINTMODE = HINT_MODE_NONE; if( ARG_HINTMODE != HINT_MODE_NONE) { char *rights = "rb"; /* * If we are getting hints from core, we will have to write them to * hint file */ if(ARG_HINTMODE == HINT_MODE_GET) rights = "w+b"; /* Open the hint file */ hints_file = fopen(HINT_FILE, rights); if(hints_file == NULL) { fprintf(stderr, "Error opening input file %s\n", HINT_FILE); return -1; } /* Allocate hint memory space, we will be using rawhints */ /* NB : Hope 1Mb is enough */ if((hints_buffer = malloc(1024*1024)) == NULL) { fprintf(stderr, "Memory allocation error\n"); return -1; } } if ( ARG_INPUTFILE == NULL || strcmp(ARG_INPUTFILE, "stdin") == 0) { in_file = stdin; } else { in_file = fopen(ARG_INPUTFILE, "rb"); if (in_file == NULL) { fprintf(stderr, "Error opening input file %s\n", ARG_INPUTFILE); return -1; } } if (ARG_INPUTTYPE) { if (read_pgmheader(in_file)) { fprintf(stderr, "Wrong input format, I want YUV encapsulated in PGM\n"); return -1; } } /* now we know the sizes, so allocate memory */ in_buffer = (unsigned char *) malloc(IMAGE_SIZE(XDIM,YDIM)); if (!in_buffer) goto free_all_memory; /* this should really be enough memory ! */ divx_buffer = (unsigned char *) malloc(IMAGE_SIZE(XDIM,YDIM)*2); if (!divx_buffer) goto free_all_memory; out_buffer = (unsigned char *) malloc(IMAGE_SIZE(XDIM,YDIM)*4); if (!out_buffer) goto free_all_memory; /***************************************************************************** * XviD PART Start ****************************************************************************/ status = enc_init(use_assembler); if (status) { fprintf(stderr, "Encore INIT problem, return value %d\n", status); goto release_all; } status = dec_init(use_assembler); if (status) { fprintf(stderr, "Decore INIT problem, return value %d\n", status); goto release_all; } totalsize = LONG_PACK('M','P','4','U'); if(*((char *)(&totalsize)) == 'M') bigendian = 1; else bigendian = 0; totalsize = 0;/***************************************************************************** * Main loop ****************************************************************************/ do { if (ARG_INPUTTYPE) status = read_pgmdata(in_file, in_buffer); /* read PGM data (YUV-format) */ else status = read_yuvdata(in_file, in_buffer); /* read raw data (YUV-format) */ if (status) { /* Couldn't read image, most likely end-of-file */ continue; } if (save_ref_flag) { sprintf(filename, "%s%05d.pgm", filepath, filenr); write_pgm(filename,in_buffer); }/***************************************************************************** * Analyse this frame before encoding ****************************************************************************//* * nothing is done here at the moment, but you could e.g. create * histograms or measure entropy or apply preprocessing filters... *//***************************************************************************** * Read hints from file ****************************************************************************/ if(ARG_HINTMODE == HINT_MODE_SET) { fread(&hints_size, 1, sizeof(long), hints_file); hints_size = (!bigendian)?SWAP(hints_size):hints_size; fread(hints_buffer, 1, hints_size, hints_file); }/***************************************************************************** * Encode and decode this frame ****************************************************************************/ enctime = msecond(); status = enc_main(in_buffer, divx_buffer, hints_buffer, &m4v_size, &frame_type[filenr], &hints_size); enctime = msecond() - enctime; totalenctime += enctime; totalsize += m4v_size; printf("Frame %5d: intra %1d, enctime=%6.1f ms, size=%6d bytes ", (int)filenr, (int)frame_type[filenr], (float)enctime, (int)m4v_size);/***************************************************************************** * Save hints to file ****************************************************************************/ if(ARG_HINTMODE == HINT_MODE_GET) { hints_size = (!bigendian)?SWAP(hints_size):hints_size; fwrite(&hints_size, 1, sizeof(long), hints_file); hints_size = (!bigendian)?SWAP(hints_size):hints_size; fwrite(hints_buffer, 1, hints_size, hints_file); }/***************************************************************************** * Save stream to file ****************************************************************************/ if (ARG_SAVEMPEGSTREAM) { sprintf(filename, "%sframe%05d.m4v", filepath, filenr); filehandle = fopen(filename, "wb"); fwrite(divx_buffer, m4v_size, 1, filehandle); fclose(filehandle); } dectime = msecond(); status = dec_main(divx_buffer, out_buffer, m4v_size); dectime = msecond() - dectime; totaldectime += dectime; /***************************************************************************** * Analyse the decoded frame and compare to original ****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -