[svn] / trunk / xvidcore / examples / xvid_stat.c Repository:
ViewVC logotype

Annotation of /trunk/xvidcore/examples/xvid_stat.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 824 - (view) (download)

1 : chl 479 /*****************************************************************************
2 : chl 119 *
3 : chl 479 * XVID MPEG-4 VIDEO CODEC
4 :     * - Console based test application -
5 : chl 119 *
6 : chl 479 * Copyright(C) 2002 Christoph Lampert
7 : chl 119 *
8 : chl 479 * This program is free software; you can redistribute it and/or modify
9 :     * it under the terms of the GNU General Public License as published by
10 :     * the Free Software Foundation; either version 2 of the License, or
11 :     * (at your option) any later version.
12 : chl 119 *
13 : chl 479 * This program is distributed in the hope that it will be useful,
14 :     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 :     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 :     * GNU General Public License for more details.
17 :     *
18 :     * You should have received a copy of the GNU General Public License
19 :     * along with this program; if not, write to the Free Software
20 :     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 :     *
22 : edgomez 824 * $Id: xvid_stat.c,v 1.19 2003-02-09 19:32:52 edgomez Exp $
23 : chl 479 *
24 :     ****************************************************************************/
25 : chl 119
26 : edgomez 483 /*****************************************************************************
27 :     * Application notes :
28 : chl 119 *
29 :     * A sequence of YUV pics in PGM file format is encoded and decoded
30 :     * The speed is measured and PSNR of decoded picture is calculated.
31 :     *
32 :     * The program is plain C and needs no libraries except for libxvidcore,
33 : edgomez 483 * and maths-lib.
34 : chl 119 *
35 : edgomez 483 * Usage : xvid_stat [OPTIONS]
36 :     * Options :
37 :     * -w integer : frame width ([1.2048])
38 :     * -h integer : frame height ([1.2048])
39 :     * -b integer : target bitrate (>0 | default=900kbit)
40 :     * -f float : target framerate (>0)
41 :     * -i string : input filename (default=stdin)
42 :     * -t integer : input data type (yuv=0, pgm=1)
43 :     * -n integer : number of frames to encode
44 :     * -q integer : quality ([0..5])
45 :     * -d boolean : save decoder output (0 False*, !=0 True)
46 :     * -m boolean : save mpeg4 raw stream (0 False*, !=0 True)
47 : edgomez 728 * -mv integer : Hinted Motion Estimation (0 none, 1 get hints, 2 set hints)
48 : edgomez 548 * -help : prints this help message
49 : edgomez 483 * -quant integer : fixed quantizer (disables -b setting)
50 :     * (* means default)
51 : chl 119 *
52 : edgomez 483 * An input file named "stdin" is treated as standard input stream.
53 : chl 119 *
54 :     *
55 : edgomez 483 * PGM input must be in a very specific format, basically it pgm file must
56 :     * contain Y plane first just like usual P5 pgm files, and then U and V
57 :     * planes are stored just after Y plane so y dimension is y*3/2 in reality
58 :     *
59 :     * See read_pgmheader for more details.
60 :     *
61 :     * Such a PGM file can be generated from MPEG2 by # mpeg2dec -o pgmpipe
62 : chl 119 *
63 : edgomez 483 ****************************************************************************/
64 : chl 119
65 :     #include <stdio.h>
66 :     #include <stdlib.h>
67 : edgomez 483 #include <string.h>
68 :     #include <math.h>
69 : edgomez 824 #ifndef WIN32
70 : edgomez 548 #include <sys/time.h>
71 :     #else
72 : edgomez 483 #include <time.h>
73 : edgomez 548 #endif
74 : chl 119
75 : edgomez 548 #include "xvid.h"
76 : chl 119
77 : edgomez 483 /****************************************************************************
78 :     * Prototypes
79 :     ***************************************************************************/
80 : chl 119
81 : edgomez 483 /* Prints program usage message */
82 :     static void usage();
83 : chl 119
84 : edgomez 483 /* Statistical functions */
85 :     static double msecond();
86 :     static double absdistq(int x, int y,
87 :     unsigned char* buf1, int stride1,
88 :     unsigned char* buf2, int stride2);
89 :     static double PSNR(int x, int y,
90 :     unsigned char* buf1, int stride1,
91 :     unsigned char* buf2, int stride2);
92 : chl 119
93 : edgomez 483 /* PGM related functions */
94 :     static int read_pgmheader(FILE* handle);
95 :     static int read_pgmdata(FILE* handle, unsigned char *image);
96 :     static int read_yuvdata(FILE* handle, unsigned char *image);
97 :     static int write_pgm(char *filename, unsigned char *image);
98 : chl 151
99 : edgomez 483 /* Encoder related functions */
100 :     static int enc_init(int use_assembler);
101 :     static int enc_stop();
102 :     static int enc_main(unsigned char* image, unsigned char* bitstream,
103 : edgomez 728 unsigned char* hints_buffer,
104 :     long *streamlength, long* frametype, long* hints_size);
105 : chl 119
106 : edgomez 483 /* Decoder related functions */
107 :     static int dec_stop();
108 :     static int dec_main(unsigned char *m4v_buffer, unsigned char *out_buffer,
109 :     int m4v_size);
110 :     static int dec_init(int use_assembler);
111 : chl 119
112 : edgomez 483 /*****************************************************************************
113 :     * Quality presets
114 :     ****************************************************************************/
115 : chl 119
116 : edgomez 483 static int const motion_presets[7] = {
117 : edgomez 684 0, /* Q 0 */
118 :     PMV_EARLYSTOP16, /* Q 1 */
119 :     PMV_EARLYSTOP16, /* Q 2 */
120 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16, /* Q 3 */
121 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16, /* Q 4 */
122 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EARLYSTOP8 | /* Q 5 */
123 : edgomez 483 PMV_HALFPELREFINE8,
124 : edgomez 684 PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EXTSEARCH16 | /* Q 6 */
125 : edgomez 483 PMV_USESQUARES16 | PMV_EARLYSTOP8 | PMV_HALFPELREFINE8
126 :     };
127 : chl 151
128 : edgomez 483 static int const general_presets[7] = {
129 : edgomez 684 XVID_H263QUANT, /* Q 0 */
130 :     XVID_MPEGQUANT, /* Q 1 */
131 :     XVID_H263QUANT, /* Q 2 */
132 :     XVID_H263QUANT | XVID_HALFPEL, /* Q 3 */
133 :     XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V, /* Q 4 */
134 :     XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V, /* Q 5 */
135 :     XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V /* Q 6 */
136 : edgomez 483 };
137 :    
138 :    
139 :     /*****************************************************************************
140 :     * Command line global variables
141 :     ****************************************************************************/
142 :    
143 :     /* Maximum number of frames to encode */
144 :     #define ABS_MAXFRAMENR 9999
145 :    
146 : edgomez 728 /* HINTMODEs */
147 :     #define HINT_MODE_NONE 0
148 :     #define HINT_MODE_GET 1
149 :     #define HINT_MODE_SET 2
150 :     #define HINT_FILE "hints.mv"
151 :    
152 : edgomez 483 static int ARG_BITRATE = 900;
153 :     static int ARG_QUANTI = 0;
154 :     static int ARG_QUALITY = 6;
155 :     static int ARG_MINQUANT = 1;
156 :     static int ARG_MAXQUANT = 31;
157 :     static float ARG_FRAMERATE = 25.00f;
158 :     static int ARG_MAXFRAMENR = ABS_MAXFRAMENR;
159 :     static char *ARG_INPUTFILE = NULL;
160 :     static int ARG_INPUTTYPE = 0;
161 :     static int ARG_SAVEDECOUTPUT = 0;
162 :     static int ARG_SAVEMPEGSTREAM = 0;
163 : edgomez 728 static int ARG_HINTMODE = HINT_MODE_NONE;
164 : edgomez 483 static int XDIM = 0;
165 :     static int YDIM = 0;
166 : edgomez 484 #define IMAGE_SIZE(x,y) ((x)*(y)*3/2)
167 : edgomez 483
168 : chl 119 #define MAX(A,B) ( ((A)>(B)) ? (A) : (B) )
169 :     #define SMALL_EPS 1e-10
170 :    
171 : edgomez 728 #define LONG_PACK(a,b,c,d) ((long) (((long)(a))<<24) | (((long)(b))<<16) | \
172 :     (((long)(c))<<8) |((long)(d)))
173 :    
174 :     #define SWAP(a) ( (((a)&0x000000ff)<<24) | (((a)&0x0000ff00)<<8) | \
175 :     (((a)&0x00ff0000)>>8) | (((a)&0xff000000)>>24) )
176 :    
177 : edgomez 483 /****************************************************************************
178 :     * Nasty global vars ;-)
179 :     ***************************************************************************/
180 :    
181 :     static int i,filenr = 0;
182 :     static int save_ref_flag = 0;
183 :    
184 :     /* the path where to save output */
185 :     static char filepath[256] = "./";
186 :    
187 :     /* Internal structures (handles) for encoding and decoding */
188 :     static void *enc_handle = NULL;
189 :     static void *dec_handle = NULL;
190 :    
191 :     /*****************************************************************************
192 :     * Main program
193 :     ****************************************************************************/
194 :    
195 :     int main(int argc, char *argv[])
196 :     {
197 :    
198 :     unsigned char *divx_buffer = NULL;
199 :     unsigned char *in_buffer = NULL;
200 :     unsigned char *out_buffer = NULL;
201 : edgomez 728 unsigned char *hints_buffer = NULL;
202 : edgomez 483
203 :     double enctime,dectime;
204 :     double totalenctime=0.;
205 :     double totaldectime=0.;
206 :    
207 : edgomez 729 long totalsize = 0;
208 :     long hints_size = 0;
209 : edgomez 483 int status;
210 : edgomez 729 int bigendian = 0;
211 : edgomez 728
212 : edgomez 729 long m4v_size = 0;
213 : edgomez 728 long frame_type[ABS_MAXFRAMENR];
214 : edgomez 483 int Iframes=0, Pframes=0, use_assembler=0;
215 :     double framepsnr[ABS_MAXFRAMENR];
216 :    
217 :     double Ipsnr=0.,Imaxpsnr=0.,Iminpsnr=999.,Ivarpsnr=0.;
218 :     double Ppsnr=0.,Pmaxpsnr=0.,Pminpsnr=999.,Pvarpsnr=0.;
219 :    
220 :     char filename[256];
221 :    
222 :     FILE *filehandle;
223 :     FILE *in_file = stdin;
224 : edgomez 728 FILE *hints_file = NULL;
225 : edgomez 483
226 :     printf("xvid_stat - XviD core library test program ");
227 :     printf("written by Christoph Lampert 2002\n\n");
228 :    
229 :     /*****************************************************************************
230 :     * Command line parsing
231 :     ****************************************************************************/
232 :    
233 :     for (i=1; i< argc; i++) {
234 :    
235 :     if (strcmp("-asm", argv[i]) == 0 ) {
236 :     use_assembler = 1;
237 :     }
238 :     else if (strcmp("-w", argv[i]) == 0 && i < argc - 1 ) {
239 :     i++;
240 :     XDIM = atoi(argv[i]);
241 :     }
242 :     else if (strcmp("-h", argv[i]) == 0 && i < argc - 1 ) {
243 :     i++;
244 :     YDIM = atoi(argv[i]);
245 :     }
246 :     else if (strcmp("-b", argv[i]) == 0 && i < argc - 1 ) {
247 :     i++;
248 :     ARG_BITRATE = atoi(argv[i]);
249 :     }
250 :     else if (strcmp("-q", argv[i]) == 0 && i < argc - 1 ) {
251 :     i++;
252 :     ARG_QUALITY = atoi(argv[i]);
253 :     }
254 :     else if (strcmp("-f", argv[i]) == 0 && i < argc - 1 ) {
255 :     i++;
256 :     ARG_FRAMERATE = (float)atof(argv[i]);
257 :     }
258 :     else if (strcmp("-i", argv[i]) == 0 && i < argc - 1 ) {
259 :     i++;
260 :     ARG_INPUTFILE = argv[i];
261 :     }
262 :     else if (strcmp("-t", argv[i]) == 0 && i < argc - 1 ) {
263 :     i++;
264 :     ARG_INPUTTYPE = atoi(argv[i]);
265 :     }
266 :     else if(strcmp("-n", argv[i]) == 0 && i < argc - 1 ) {
267 :     i++;
268 :     ARG_MAXFRAMENR = atoi(argv[i]);
269 :     }
270 :     else if (strcmp("-quant", argv[i]) == 0 && i < argc - 1 ) {
271 :     i++;
272 :     ARG_QUANTI = atoi(argv[i]);
273 :     }
274 :     else if (strcmp("-d", argv[i]) == 0 && i < argc - 1 ) {
275 :     i++;
276 :     ARG_SAVEDECOUTPUT = atoi(argv[i]);
277 :     }
278 :     else if (strcmp("-m", argv[i]) == 0 && i < argc - 1 ) {
279 :     i++;
280 :     ARG_SAVEMPEGSTREAM = atoi(argv[i]);
281 :     }
282 : edgomez 728 else if (strcmp("-mv", argv[i]) == 0 && i < argc - 1 ) {
283 :     i++;
284 :     ARG_HINTMODE = atoi(argv[i]);
285 :     }
286 : edgomez 548 else if (strcmp("-help", argv[i])) {
287 : edgomez 483 usage();
288 :     return(0);
289 :     }
290 :     else {
291 :     usage();
292 :     exit(-1);
293 :     }
294 :    
295 :     }
296 :    
297 :     /*****************************************************************************
298 :     * Arguments checking
299 :     ****************************************************************************/
300 :    
301 : edgomez 484 if (XDIM <= 0 || XDIM >= 2048 || YDIM <=0 || YDIM >= 2048 ) {
302 : edgomez 559 fprintf(stderr, "Trying to retreive width and height from PGM header\n");
303 : edgomez 483 ARG_INPUTTYPE = 1; /* pgm */
304 :     }
305 :    
306 :     if ( ARG_QUALITY < 0 || ARG_QUALITY > 6) {
307 :     fprintf(stderr,"Wrong Quality\n");
308 :     return -1;
309 :     }
310 :    
311 :     if ( ARG_BITRATE <= 0 && ARG_QUANTI == 0) {
312 :     fprintf(stderr,"Wrong Bitrate\n");
313 :     return -1;
314 :     }
315 :    
316 :     if ( ARG_FRAMERATE <= 0) {
317 : edgomez 559 fprintf(stderr,"Wrong Framerate %s \n",argv[5]);
318 : edgomez 483 return -1;
319 :     }
320 :    
321 :     if ( ARG_MAXFRAMENR <= 0) {
322 :     fprintf(stderr,"Wrong number of frames\n");
323 :     return -1;
324 :     }
325 :    
326 : edgomez 728 if ( ARG_HINTMODE != HINT_MODE_NONE &&
327 :     ARG_HINTMODE != HINT_MODE_GET &&
328 :     ARG_HINTMODE != HINT_MODE_SET)
329 :     ARG_HINTMODE = HINT_MODE_NONE;
330 :    
331 :     if( ARG_HINTMODE != HINT_MODE_NONE) {
332 :     char *rights = "rb";
333 :    
334 :     /*
335 :     * If we are getting hints from core, we will have to write them to
336 :     * hint file
337 :     */
338 :     if(ARG_HINTMODE == HINT_MODE_GET)
339 :     rights = "w+b";
340 :    
341 :     /* Open the hint file */
342 :     hints_file = fopen(HINT_FILE, rights);
343 :     if(hints_file == NULL) {
344 :     fprintf(stderr, "Error opening input file %s\n", HINT_FILE);
345 :     return -1;
346 :     }
347 :    
348 :     /* Allocate hint memory space, we will be using rawhints */
349 :     /* NB : Hope 1Mb is enough */
350 :     if((hints_buffer = malloc(1024*1024)) == NULL) {
351 :     fprintf(stderr, "Memory allocation error\n");
352 :     return -1;
353 :     }
354 :    
355 :     }
356 :    
357 : edgomez 483 if ( ARG_INPUTFILE == NULL || strcmp(ARG_INPUTFILE, "stdin") == 0) {
358 :     in_file = stdin;
359 :     }
360 :     else {
361 :    
362 :     in_file = fopen(ARG_INPUTFILE, "rb");
363 :     if (in_file == NULL) {
364 :     fprintf(stderr, "Error opening input file %s\n", ARG_INPUTFILE);
365 :     return -1;
366 :     }
367 :     }
368 :    
369 :     if (ARG_INPUTTYPE) {
370 :     if (read_pgmheader(in_file)) {
371 :     fprintf(stderr, "Wrong input format, I want YUV encapsulated in PGM\n");
372 : edgomez 484 return -1;
373 : edgomez 483 }
374 :     }
375 :    
376 :     /* now we know the sizes, so allocate memory */
377 :    
378 : edgomez 484 in_buffer = (unsigned char *) malloc(IMAGE_SIZE(XDIM,YDIM));
379 : edgomez 483 if (!in_buffer)
380 :     goto free_all_memory;
381 :    
382 :     /* this should really be enough memory ! */
383 : edgomez 484 divx_buffer = (unsigned char *) malloc(IMAGE_SIZE(XDIM,YDIM)*2);
384 : edgomez 483 if (!divx_buffer)
385 :     goto free_all_memory;
386 :    
387 : edgomez 484 out_buffer = (unsigned char *) malloc(IMAGE_SIZE(XDIM,YDIM)*4);
388 : edgomez 483 if (!out_buffer)
389 :     goto free_all_memory;
390 :    
391 :    
392 :     /*****************************************************************************
393 :     * XviD PART Start
394 :     ****************************************************************************/
395 :    
396 :    
397 :     status = enc_init(use_assembler);
398 :     if (status)
399 :     {
400 :     fprintf(stderr, "Encore INIT problem, return value %d\n", status);
401 :     goto release_all;
402 :     }
403 :    
404 :     status = dec_init(use_assembler);
405 :     if (status)
406 :     {
407 :     fprintf(stderr, "Decore INIT problem, return value %d\n", status);
408 :     goto release_all;
409 :     }
410 :    
411 : edgomez 728 totalsize = LONG_PACK('M','P','4','U');
412 :     if(*((char *)(&totalsize)) == 'M')
413 :     bigendian = 1;
414 :     else
415 :     bigendian = 0;
416 : edgomez 729 totalsize = 0;
417 : edgomez 483
418 :     /*****************************************************************************
419 :     * Main loop
420 :     ****************************************************************************/
421 :    
422 :     do {
423 :    
424 :     if (ARG_INPUTTYPE)
425 : edgomez 684 status = read_pgmdata(in_file, in_buffer); /* read PGM data (YUV-format) */
426 : edgomez 483 else
427 : edgomez 684 status = read_yuvdata(in_file, in_buffer); /* read raw data (YUV-format) */
428 : edgomez 483
429 :     if (status)
430 :     {
431 :     /* Couldn't read image, most likely end-of-file */
432 :     continue;
433 :     }
434 :    
435 :    
436 :     if (save_ref_flag)
437 :     {
438 :     sprintf(filename, "%s%05d.pgm", filepath, filenr);
439 :     write_pgm(filename,in_buffer);
440 :     }
441 :    
442 :    
443 :     /*****************************************************************************
444 :     * Analyse this frame before encoding
445 :     ****************************************************************************/
446 :    
447 :     /*
448 :     * nothing is done here at the moment, but you could e.g. create
449 :     * histograms or measure entropy or apply preprocessing filters...
450 :     */
451 :    
452 :     /*****************************************************************************
453 : edgomez 728 * Read hints from file
454 :     ****************************************************************************/
455 :    
456 :     if(ARG_HINTMODE == HINT_MODE_SET) {
457 :     fread(&hints_size, 1, sizeof(long), hints_file);
458 :     hints_size = (!bigendian)?SWAP(hints_size):hints_size;
459 :     fread(hints_buffer, 1, hints_size, hints_file);
460 :     }
461 :    
462 :     /*****************************************************************************
463 : edgomez 483 * Encode and decode this frame
464 :     ****************************************************************************/
465 :    
466 :     enctime = msecond();
467 : edgomez 728 status = enc_main(in_buffer, divx_buffer, hints_buffer,
468 :     &m4v_size, &frame_type[filenr], &hints_size);
469 : edgomez 483 enctime = msecond() - enctime;
470 :    
471 :     totalenctime += enctime;
472 :     totalsize += m4v_size;
473 :    
474 :     printf("Frame %5d: intra %1d, enctime=%6.1f ms, size=%6d bytes ",
475 :     (int)filenr, (int)frame_type[filenr], (float)enctime, (int)m4v_size);
476 :    
477 : edgomez 728 /*****************************************************************************
478 :     * Save hints to file
479 :     ****************************************************************************/
480 :    
481 :     if(ARG_HINTMODE == HINT_MODE_GET) {
482 :     hints_size = (!bigendian)?SWAP(hints_size):hints_size;
483 :     fwrite(&hints_size, 1, sizeof(long), hints_file);
484 :     hints_size = (!bigendian)?SWAP(hints_size):hints_size;
485 :     fwrite(hints_buffer, 1, hints_size, hints_file);
486 :     }
487 :    
488 :     /*****************************************************************************
489 :     * Save stream to file
490 :     ****************************************************************************/
491 :    
492 : edgomez 483 if (ARG_SAVEMPEGSTREAM)
493 :     {
494 :     sprintf(filename, "%sframe%05d.m4v", filepath, filenr);
495 :     filehandle = fopen(filename, "wb");
496 :     fwrite(divx_buffer, m4v_size, 1, filehandle);
497 :     fclose(filehandle);
498 :     }
499 :    
500 :     dectime = msecond();
501 :     status = dec_main(divx_buffer, out_buffer, m4v_size);
502 :     dectime = msecond() - dectime;
503 :    
504 :     totaldectime += dectime;
505 :    
506 :    
507 :     /*****************************************************************************
508 :     * Analyse the decoded frame and compare to original
509 :     ****************************************************************************/
510 :    
511 : edgomez 485 framepsnr[filenr] = PSNR(XDIM,YDIM*3/2, in_buffer, XDIM, out_buffer, XDIM);
512 : chl 119
513 : edgomez 483 printf("dectime =%6.1f ms PSNR %5.2f\n",dectime, framepsnr[filenr]);
514 : chl 119
515 : edgomez 483 if (ARG_SAVEDECOUTPUT)
516 :     {
517 :     sprintf(filename, "%sdec%05d.pgm", filepath, filenr);
518 :     write_pgm(filename, out_buffer);
519 :     }
520 : chl 119
521 : edgomez 483 /* Read the header if it's pgm stream */
522 :     if (ARG_INPUTTYPE)
523 :     status = read_pgmheader(in_file);
524 : chl 119
525 : edgomez 483 filenr++;
526 : chl 119
527 : edgomez 483 } while ( (!status) && (filenr<ARG_MAXFRAMENR) );
528 : chl 119
529 : edgomez 483
530 :    
531 :     /*****************************************************************************
532 :     * Calculate totals and averages for output, print results
533 :     ****************************************************************************/
534 : chl 119
535 : edgomez 483 totalsize /= filenr;
536 :     totalenctime /= filenr;
537 :     totaldectime /= filenr;
538 :    
539 :     for (i=0;i<filenr;i++)
540 :     {
541 :     switch (frame_type[i])
542 :     {
543 :     case 0:
544 :     Pframes++;
545 :     Ppsnr += framepsnr[i];
546 :     break;
547 :     case 1:
548 :     Iframes++;
549 :     Ipsnr += framepsnr[i];
550 :     break;
551 :     default:
552 :     break;
553 :     }
554 :     }
555 :    
556 :     if (Pframes)
557 :     Ppsnr /= Pframes;
558 :     if (Iframes)
559 :     Ipsnr /= Iframes;
560 :    
561 :     /* calculate statistics for every frametype: P,I */
562 :     for (i=0;i<filenr;i++)
563 :     {
564 :     switch (frame_type[i])
565 :     {
566 :     case 0:
567 :     if (framepsnr[i] > Pmaxpsnr)
568 :     Pmaxpsnr = framepsnr[i];
569 :     if (framepsnr[i] < Pminpsnr)
570 :     Pminpsnr = framepsnr[i];
571 :     Pvarpsnr += (framepsnr[i] - Ppsnr)*(framepsnr[i] - Ppsnr) /Pframes;
572 :     break;
573 :     case 1:
574 :     if (framepsnr[i] > Imaxpsnr)
575 :     Imaxpsnr = framepsnr[i];
576 :     if (framepsnr[i] < Pminpsnr)
577 :     Iminpsnr = framepsnr[i];
578 :     Ivarpsnr += (framepsnr[i] - Ipsnr)*(framepsnr[i] - Ipsnr) /Iframes;
579 :     default:
580 :     break;
581 :     }
582 :     }
583 :    
584 :     /* Print all statistics */
585 :     printf("Avg. Q%1d %2s ",ARG_QUALITY, (ARG_QUANTI ? " q" : "br"));
586 : edgomez 501 printf("%04d ",(ARG_QUANTI)?ARG_QUANTI:ARG_BITRATE);
587 : edgomez 483 printf("( %.2f bpp) ", (double)ARG_BITRATE*1000/XDIM/YDIM/ARG_FRAMERATE);
588 : edgomez 561 printf("size %6d ", (int)totalsize);
589 : edgomez 483 printf("( %4d kbps ",(int)(totalsize*8*ARG_FRAMERATE/1000));
590 :     printf("/ %.2f bpp) ",(double)totalsize*8/XDIM/YDIM);
591 : edgomez 548 printf("enc: %6.1f fps, dec: %6.1f fps \n",1000/totalenctime, 1000/totaldectime);
592 : edgomez 483 printf("PSNR P(%d): %5.2f ( %5.2f , %5.2f ; %5.4f ) ",Pframes,Ppsnr,Pminpsnr,Pmaxpsnr,sqrt(Pvarpsnr/filenr));
593 :     printf("I(%d): %5.2f ( %5.2f , %5.2f ; %5.4f ) ",Iframes,Ipsnr,Iminpsnr,Imaxpsnr,sqrt(Ivarpsnr/filenr));
594 :     printf("\n");
595 :    
596 :     /*****************************************************************************
597 :     * XviD PART Stop
598 :     ****************************************************************************/
599 :    
600 :     release_all:
601 :    
602 :     if (enc_handle)
603 :     {
604 :     status = enc_stop();
605 :     if (status)
606 :     fprintf(stderr, "Encore RELEASE problem return value %d\n", status);
607 :     }
608 :    
609 :     if (dec_handle)
610 :     {
611 :     status = dec_stop();
612 :     if (status)
613 :     fprintf(stderr, "Decore RELEASE problem return value %d\n", status);
614 :     }
615 :    
616 :     fclose(in_file);
617 :    
618 :     free_all_memory:
619 :     free(out_buffer);
620 :     free(divx_buffer);
621 :     free(in_buffer);
622 :    
623 :     return 0;
624 :    
625 :     }
626 :    
627 :     /*****************************************************************************
628 :     * "statistical" functions
629 :     *
630 :     * these are not needed for encoding or decoding, but for measuring
631 :     * time and quality, there in nothing specific to XviD in these
632 :     *
633 :     *****************************************************************************/
634 :    
635 :    
636 :    
637 :     /* Return time elapsed time in miliseconds since the program started */
638 :     static double msecond()
639 : chl 119 {
640 : edgomez 824 #ifndef WIN32
641 : edgomez 548 struct timeval tv;
642 :     gettimeofday(&tv, 0);
643 : edgomez 550 return tv.tv_sec*1.0e3 + tv.tv_usec * 1.0e-3;
644 : edgomez 548 #else
645 : edgomez 483 clock_t clk;
646 :     clk = clock();
647 :     return clk * 1000 / CLOCKS_PER_SEC;
648 : edgomez 548 #endif
649 : chl 119 }
650 :    
651 :    
652 : edgomez 483 /*
653 :     * Returns the sum of squared distances (SSD) between two images of dimensions
654 :     * x times y
655 :     */
656 :     static double absdistq(int x, int y,
657 :     unsigned char* buf1, int stride1,
658 :     unsigned char* buf2, int stride2)
659 : chl 119 {
660 :     double dist=0.;
661 :     int i,j,val;
662 :    
663 :     for (i=0;i<y;i++)
664 :     {
665 :     val=0;
666 :     for (j=0;j<x;j++)
667 :     val+= ((int)buf1[j]-(int)buf2[j])*((int)buf1[j]-(int)buf2[j]);
668 :    
669 :     dist += (double)val;
670 :     buf1 += stride1;
671 :     buf2 += stride2;
672 :     }
673 : edgomez 483 return dist/(x*y);
674 : chl 119 }
675 :    
676 :    
677 : edgomez 483 /*
678 :     * Returns the PSNR between to images.
679 :     *
680 :     * This is a common logarithmic measure for "quality" from the world of signal
681 :     * processing if you don't know what it is, simply accept that higher values
682 :     * are better.
683 :     *
684 :     * PSNR represents the ratio of useful signal over noise signal. In our case,
685 :     * useful signal is refernce image, noise signal is the difference between
686 :     * reference and decoded frame from encoded bitstream.
687 :     *
688 :     * The problem is this type of value is dependant of image source and so, is
689 :     * not reliable as a common "quality" indicator.
690 :     * So PSNR computes the ratio of maximum/noise. Maximum being set to 2^bpp/channel
691 :     * This way, PSNR is not dependant anymore of image data type.
692 :     *
693 :     */
694 :     static double PSNR(int x, int y,
695 :     unsigned char* buf1, int stride1,
696 :     unsigned char* buf2, int stride2)
697 : chl 119 {
698 : edgomez 483 return 10*(log10(255*255)-log10( absdistq(x, y, buf1, stride1, buf2, stride2) ));
699 : chl 119 }
700 :    
701 : edgomez 483 /*****************************************************************************
702 :     * Usage message
703 :     *****************************************************************************/
704 : chl 119
705 : edgomez 483 static void usage()
706 :     {
707 : chl 119
708 : edgomez 483 fprintf(stderr, "Usage : xvid_stat [OPTIONS]\n");
709 :     fprintf(stderr, "Options :\n");
710 :     fprintf(stderr, " -w integer : frame width ([1.2048])\n");
711 :     fprintf(stderr, " -h integer : frame height ([1.2048])\n");
712 :     fprintf(stderr, " -b integer : target bitrate (>0 | default=900kbit)\n");
713 :     fprintf(stderr, " -f float : target framerate (>0)\n");
714 :     fprintf(stderr, " -i string : input filename (default=stdin)\n");
715 :     fprintf(stderr, " -t integer : input data type (yuv=0, pgm=1)\n");
716 :     fprintf(stderr, " -n integer : number of frames to encode\n");
717 :     fprintf(stderr, " -q integer : quality ([0..5])\n");
718 :     fprintf(stderr, " -d boolean : save decoder output (0 False*, !=0 True)\n");
719 :     fprintf(stderr, " -m boolean : save mpeg4 raw stream (0 False*, !=0 True)\n");
720 : edgomez 548 fprintf(stderr, " -help : prints this help message\n");
721 : edgomez 483 fprintf(stderr, " -quant integer : fixed quantizer (disables -b setting)\n");
722 :     fprintf(stderr, " (* means default)\n");
723 :    
724 :     }
725 :    
726 :     /*****************************************************************************
727 :     * Input and output functions
728 :     *
729 :     * the are small and simple routines to read and write PGM and YUV
730 :     * image. It's just for convenience, again nothing specific to XviD
731 :     *
732 :     *****************************************************************************/
733 :    
734 :     static int read_pgmheader(FILE* handle)
735 : chl 119 {
736 :     int bytes,xsize,ysize,depth;
737 :     char dummy[2];
738 :    
739 :     bytes = fread(dummy,1,2,handle);
740 :    
741 :     if ( (bytes < 2) || (dummy[0] != 'P') || (dummy[1] != '5' ))
742 :     return 1;
743 : edgomez 484
744 : chl 119 fscanf(handle,"%d %d %d",&xsize,&ysize,&depth);
745 :     if ( (xsize > 1440) || (ysize > 2880 ) || (depth != 255) )
746 :     {
747 :     fprintf(stderr,"%d %d %d\n",xsize,ysize,depth);
748 :     return 2;
749 :     }
750 :     if ( (XDIM==0) || (YDIM==0) )
751 : edgomez 483 {
752 :     XDIM=xsize;
753 : edgomez 484 YDIM=ysize*2/3;
754 : chl 119 }
755 :    
756 :     return 0;
757 :     }
758 :    
759 : edgomez 483 static int read_pgmdata(FILE* handle, unsigned char *image)
760 : chl 119 {
761 : edgomez 483 int i;
762 : chl 119 char dummy;
763 : edgomez 483
764 : edgomez 484 unsigned char *y = image;
765 :     unsigned char *u = image + XDIM*YDIM;
766 :     unsigned char *v = image + XDIM*YDIM + XDIM/2*YDIM/2;
767 : chl 119
768 : edgomez 484 /* read Y component of picture */
769 :     fread(y, 1, XDIM*YDIM, handle);
770 : chl 119
771 : edgomez 483 for (i=0;i<YDIM/2;i++)
772 : chl 119 {
773 : edgomez 484 /* read U */
774 :     fread(u, 1, XDIM/2, handle);
775 :    
776 :     /* read V */
777 :     fread(v, 1, XDIM/2, handle);
778 :    
779 :     /* Update pointers */
780 :     u += XDIM/2;
781 :     v += XDIM/2;
782 : chl 119 }
783 : edgomez 484
784 :     /* I don't know why, but this seems needed */
785 :     fread(&dummy, 1, 1, handle);
786 :    
787 : chl 119 return 0;
788 :     }
789 :    
790 : edgomez 483 static int read_yuvdata(FILE* handle, unsigned char *image)
791 :     {
792 : chl 119
793 : edgomez 548 if (fread(image, 1, IMAGE_SIZE(XDIM, YDIM), handle) != (unsigned int)IMAGE_SIZE(XDIM, YDIM))
794 : chl 119 return 1;
795 :     else
796 :     return 0;
797 :     }
798 :    
799 : edgomez 483 static int write_pgm(char *filename, unsigned char *image)
800 : chl 119 {
801 : edgomez 484 int loop;
802 :    
803 :     unsigned char *y = image;
804 :     unsigned char *u = image + XDIM*YDIM;
805 :     unsigned char *v = image + XDIM*YDIM + XDIM/2*YDIM/2;
806 :    
807 : chl 119 FILE *filehandle;
808 : edgomez 484 filehandle=fopen(filename,"w+b");
809 : chl 119 if (filehandle)
810 : edgomez 483 {
811 : edgomez 484 /* Write header */
812 :     fprintf(filehandle,"P5\n\n%d %d 255\n", XDIM,YDIM*3/2);
813 :    
814 :     /* Write Y data */
815 :     fwrite(y, 1, XDIM*YDIM, filehandle);
816 :    
817 :     for(loop=0; loop<YDIM/2; loop++)
818 :     {
819 :     /* Write U scanline */
820 :     fwrite(u, 1, XDIM/2, filehandle);
821 :    
822 :     /* Write V scanline */
823 :     fwrite(v, 1, XDIM/2, filehandle);
824 :    
825 :     /* Update pointers */
826 :     u += XDIM/2;
827 :     v += XDIM/2;
828 :    
829 :     }
830 :    
831 :     /* Close file */
832 : chl 119 fclose(filehandle);
833 : edgomez 484
834 : chl 119 return 0;
835 :     }
836 :     else
837 :     return 1;
838 :     }
839 :    
840 : edgomez 483 /*****************************************************************************
841 :     * Routines for encoding: init encoder, frame step, release encoder
842 :     ****************************************************************************/
843 : chl 119
844 :     #define FRAMERATE_INCR 1001
845 :    
846 : edgomez 483 /* Initialize encoder for first use, pass all needed parameters to the codec */
847 :     static int enc_init(int use_assembler)
848 :     {
849 : chl 119 int xerr;
850 :    
851 :     XVID_INIT_PARAM xinit;
852 :     XVID_ENC_PARAM xparam;
853 :    
854 : edgomez 483 if(use_assembler) {
855 : Isibaar 209
856 :     #ifdef ARCH_IA64
857 :     xinit.cpu_flags = XVID_CPU_FORCE | XVID_CPU_IA64;
858 :     #else
859 :     xinit.cpu_flags = 0;
860 :     #endif
861 : edgomez 483 }
862 :     else {
863 : Isibaar 209 xinit.cpu_flags = XVID_CPU_FORCE;
864 : edgomez 483 }
865 : Isibaar 209
866 : chl 119 xvid_init(NULL, 0, &xinit, NULL);
867 :    
868 :     xparam.width = XDIM;
869 :     xparam.height = YDIM;
870 :     if ((ARG_FRAMERATE - (int)ARG_FRAMERATE) < SMALL_EPS)
871 :     {
872 : edgomez 483 xparam.fincr = 1;
873 :     xparam.fbase = (int)ARG_FRAMERATE;
874 : chl 119 }
875 :     else
876 :     {
877 : edgomez 483 xparam.fincr = FRAMERATE_INCR;
878 :     xparam.fbase = (int)(FRAMERATE_INCR * ARG_FRAMERATE);
879 : chl 119 }
880 : chl 151 xparam.rc_reaction_delay_factor = 16;
881 : chl 479 xparam.rc_averaging_period = 100;
882 :     xparam.rc_buffer = 10;
883 : chl 151 xparam.rc_bitrate = ARG_BITRATE*1000;
884 : edgomez 484 xparam.min_quantizer = ARG_MINQUANT;
885 :     xparam.max_quantizer = ARG_MAXQUANT;
886 : chl 119 xparam.max_key_interval = (int)ARG_FRAMERATE*10;
887 : chl 151
888 : edgomez 483 /* I use a small value here, since will not encode whole movies, but short clips */
889 : chl 119
890 :     xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xparam, NULL);
891 :     enc_handle=xparam.handle;
892 :    
893 :     return xerr;
894 :     }
895 :    
896 : edgomez 483 static int enc_stop()
897 :     {
898 :     int xerr;
899 : chl 119
900 :     xerr = xvid_encore(enc_handle, XVID_ENC_DESTROY, NULL, NULL);
901 : edgomez 483 return xerr;
902 :    
903 : chl 119 }
904 :    
905 : edgomez 483 static int enc_main(unsigned char* image, unsigned char* bitstream,
906 : edgomez 728 unsigned char* hints_buffer,
907 :     long *streamlength, long* frametype, long* hints_size)
908 : edgomez 483 {
909 :     int xerr;
910 : chl 119
911 :     XVID_ENC_FRAME xframe;
912 :     XVID_ENC_STATS xstats;
913 :    
914 :     xframe.bitstream = bitstream;
915 : edgomez 684 xframe.length = -1; /* this is written by the routine */
916 : chl 119
917 :     xframe.image = image;
918 : edgomez 684 xframe.colorspace = XVID_CSP_YV12; /* defined in <xvid.h> */
919 : chl 119
920 : edgomez 684 xframe.intra = -1; /* let the codec decide between I-frame (1) and P-frame (0) */
921 : chl 119
922 : edgomez 684 xframe.quant = ARG_QUANTI; /* is quant != 0, use a fixed quant (and ignore bitrate) */
923 : chl 119
924 :     xframe.motion = motion_presets[ARG_QUALITY];
925 :     xframe.general = general_presets[ARG_QUALITY];
926 :     xframe.quant_intra_matrix = xframe.quant_inter_matrix = NULL;
927 :    
928 : edgomez 728 xframe.hint.hintstream = hints_buffer;
929 :    
930 :     if(ARG_HINTMODE == HINT_MODE_SET) {
931 :     xframe.hint.hintlength = *hints_size;
932 :     xframe.hint.rawhints = 0;
933 :     xframe.general |= XVID_HINTEDME_SET;
934 :     }
935 :    
936 :     if(ARG_HINTMODE == HINT_MODE_GET) {
937 :     xframe.hint.rawhints = 0;
938 :     xframe.general |= XVID_HINTEDME_GET;
939 :     }
940 :    
941 : chl 119 xerr = xvid_encore(enc_handle, XVID_ENC_ENCODE, &xframe, &xstats);
942 :    
943 : edgomez 728 if(ARG_HINTMODE == HINT_MODE_GET)
944 :     *hints_size = xframe.hint.hintlength;
945 :    
946 : edgomez 483 /*
947 :     * This is statictical data, e.g. for 2-pass. If you are not
948 :     * interested in any of this, you can use NULL instead of &xstats
949 :     */
950 : chl 119 *frametype = xframe.intra;
951 :     *streamlength = xframe.length;
952 :    
953 :     return xerr;
954 :     }
955 :    
956 : edgomez 483 /*****************************************************************************
957 :     * Routines for decoding: init encoder, frame step, release encoder
958 :     ****************************************************************************/
959 : chl 119
960 : edgomez 483 /* init decoder before first run */
961 :     static int dec_init(int use_assembler)
962 : chl 119 {
963 : edgomez 483 int xerr;
964 : chl 119
965 : edgomez 483 XVID_INIT_PARAM xinit;
966 :     XVID_DEC_PARAM xparam;
967 : chl 119
968 : edgomez 483 if(use_assembler)
969 : Isibaar 209
970 :     #ifdef ARCH_IA64
971 : edgomez 483 xinit.cpu_flags = XVID_CPU_FORCE | XVID_CPU_IA64;
972 : Isibaar 209 #else
973 : edgomez 483 xinit.cpu_flags = 0;
974 : Isibaar 209 #endif
975 :    
976 : edgomez 483 else
977 :     xinit.cpu_flags = XVID_CPU_FORCE;
978 : Isibaar 209
979 : edgomez 483 xvid_init(NULL, 0, &xinit, NULL);
980 :     xparam.width = XDIM;
981 :     xparam.height = YDIM;
982 : chl 119
983 : edgomez 483 xerr = xvid_decore(NULL, XVID_DEC_CREATE, &xparam, NULL);
984 :     dec_handle = xparam.handle;
985 : chl 119
986 : edgomez 483 return xerr;
987 : chl 119 }
988 :    
989 : edgomez 483 /* decode one frame */
990 :     static int dec_main(unsigned char *m4v_buffer, unsigned char *out_buffer,
991 :     int m4v_size)
992 :     {
993 :     int xerr;
994 :     XVID_DEC_FRAME xframe;
995 : chl 119
996 : edgomez 483 xframe.bitstream = m4v_buffer;
997 :     xframe.length = m4v_size;
998 :     xframe.image = out_buffer;
999 :     xframe.stride = XDIM;
1000 : edgomez 684 xframe.colorspace = XVID_CSP_YV12; /* XVID_CSP_USER is fastest (no memcopy involved) */
1001 : chl 119
1002 : edgomez 483 xerr = xvid_decore(dec_handle, XVID_DEC_DECODE, &xframe, NULL);
1003 : chl 119
1004 : edgomez 483 return xerr;
1005 : chl 119 }
1006 :    
1007 : edgomez 483 /* close decoder to release resources */
1008 :     static int dec_stop()
1009 : chl 119 {
1010 : edgomez 483 int xerr;
1011 :     xerr = xvid_decore(dec_handle, XVID_DEC_DESTROY, NULL, NULL);
1012 : chl 119
1013 : edgomez 483 return xerr;
1014 : chl 119 }
1015 :    
1016 : edgomez 483 /* EOF */

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4