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

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