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

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