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

Annotation of /xvidcore/examples/xvid_stat.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.10 - (view) (download)

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

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