[svn] / branches / dev-api-4 / xvidcore / examples / xvid_encraw.c Repository:
ViewVC logotype

Annotation of /branches/dev-api-4/xvidcore/examples/xvid_encraw.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 376 - (view) (download)
Original Path: trunk/xvidcore/examples/xvid_encraw.c

1 : chl 376 /**************************************************************************
2 :     *
3 :     * XVID MPEG-4 VIDEO CODEC - Example for encoding and decoding
4 :     *
5 :     * This program is free software; you can redistribute it and/or modify
6 :     * it under the terms of the GNU General Public License as published by
7 :     * the Free Software Foundation; either version 2 of the License, or
8 :     * (at your option) any later version.
9 :     *
10 :     * This program is distributed in the hope that it will be useful,
11 :     * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 :     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 :     * GNU General Public License for more details.
14 :     *
15 :     * You should have received a copy of the GNU General Public License
16 :     * along with this program; if not, write to the Free Software
17 :     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 :     *
19 :     *************************************************************************/
20 :    
21 :     /************************************************************************
22 :     *
23 :     * Speed test routine for XviD using the XviD-API
24 :     * (C) Christoph Lampert, 2002/08/17
25 :     *
26 :     * A sequence of YUV pics in PGM or RAW file format is encoded and the
27 :     * raw MPEG-4 stream is written to stdout.
28 :     * The encoding speed of this is measured, too.
29 :     *
30 :     * The program is plain C and needs no libraries except for libxvidcore,
31 :     * and maths-lib, so with UN*X you simply compile by
32 :     *
33 :     * gcc xvid_encraw.c -lxvidcore -lm -o xvid_encraw
34 :     *
35 :     * Run without or with illegal parameters, then PGM input input is read
36 :     * from stdin.
37 :     *
38 :     * Parameters are: xvid_stat XDIM YDIM QUALITY BITRATE/QUANTIZER FRAMERATE
39 :     *
40 :     * if XDIM or YDIM are illegal (e.g. 0), they are ignored and input is
41 :     * considered to be PGM. Otherwise (X and Y both greater than 0) raw YUV
42 :     * is expected, as e.g. the standard MPEG test-files, like "foreman"
43 :     *
44 :     * 0 <= QUALITY <= 6 (default 5)
45 :     *
46 :     * BITRATE is in kbps (default 900),
47 :     * if BITRATE<32, then value is taken is fixed QUANTIZER
48 :     *
49 :     * FRAMERATE is a float (with or without decimal dot), default is 25.00
50 :     *
51 :     * input/output and m4v-output is saved, if corresponding flags are set
52 :     *
53 :     * PGM input must in a very specific format, see read_pgmheader
54 :     * it can be generated e.g. from MPEG2 by mpeg2dec -o pgmpipe
55 :     *
56 :     ************************************************************************/
57 :    
58 :     /************************************************************************
59 :     *
60 :     * For EXAMPLES how to use this, see the seperate file xvid_stat.examples
61 :     *
62 :     ************************************************************************/
63 :    
64 :     #include <stdio.h>
65 :     #include <stdlib.h>
66 :     #include <math.h> // needed for log10
67 :     #include <sys/time.h> // only needed for gettimeofday
68 :    
69 :     #include "../src/xvid.h"
70 :    
71 :     int motion_presets[7] = {
72 :     0, // Q 0
73 :     PMV_EARLYSTOP16, // Q 1
74 :     PMV_EARLYSTOP16, // Q 2
75 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16, // Q 3
76 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16, // Q 4
77 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EARLYSTOP8 // Q 5
78 :     | PMV_HALFPELREFINE8,
79 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EXTSEARCH16 // Q 6
80 :     | PMV_USESQUARES16 | PMV_EARLYSTOP8 | PMV_HALFPELREFINE8
81 :     };
82 :    
83 :     int general_presets[7] = {
84 :     XVID_H263QUANT, /* or use XVID_MPEGQUANT */ // Q 0
85 :     XVID_MPEGQUANT, // Q 1
86 :     XVID_H263QUANT, // Q 2
87 :     XVID_H263QUANT | XVID_HALFPEL, // Q 3
88 :     XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V, // Q 4
89 :     XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V, // Q 5
90 :     XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V }; // Q 6
91 :    
92 :    
93 :     /* my default values for encoding */
94 :    
95 :     #define ABS_MAXFRAMENR 9999 // max number of frames
96 :    
97 :     int ARG_BITRATE=900;
98 :     int ARG_QUANTI=0;
99 :    
100 :     int ARG_QUALITY =6;
101 :     int ARG_MINQUANT=1;
102 :     int ARG_MAXQUANT=31;
103 :     float ARG_FRAMERATE=25.00;
104 :    
105 :     int ARG_MAXFRAMENR=ABS_MAXFRAMENR;
106 :    
107 :     #ifdef BFRAMES
108 :    
109 :     int ARG_MAXBFRAMES=1;
110 :     int ARG_BQUANTRATIO=200;
111 :    
112 :     #endif
113 :    
114 :     #define MAX(A,B) ( ((A)>(B)) ? (A) : (B) )
115 :     #define SMALL_EPS 1e-10
116 :    
117 :     /* these are global variables. Not very elegant, but easy, and this is an easy program */
118 :    
119 :     int XDIM=0;
120 :     int YDIM=0; // will be set when reading first image
121 :     int i,filenr = 0;
122 :    
123 :     int save_m4v_flag = 1; // output MPEG4-bytestream?
124 :     int save_ref_flag = 0; // save input image
125 :    
126 :     int pgmflag = 0; // a flag, if input is in PGM format, overwritten in init-phase
127 :     char filepath[256] = "./"; // the path where to save output
128 :    
129 :     void *enc_handle = NULL; // internal structures (handles) for encoding
130 :    
131 :    
132 :     /*********************************************************************/
133 :     /* "statistical" functions */
134 :     /* */
135 :     /* these are not needed for encoding or decoding, but for measuring */
136 :     /* time and quality, there in nothing specific to XviD in these */
137 :     /* */
138 :     /*********************************************************************/
139 :    
140 :     double msecond()
141 :     /* return the current time in seconds(!) */
142 :     {
143 :     struct timeval tv;
144 :     gettimeofday(&tv, 0);
145 :     return tv.tv_sec + tv.tv_usec * 1.0e-6;
146 :     }
147 :    
148 :     /*********************************************************************/
149 :     /* input and output functions */
150 :     /* */
151 :     /* the are small and simple routines to read and write PGM and YUV */
152 :     /* image. It's just for convenience, again nothing specific to XviD */
153 :     /* */
154 :     /*********************************************************************/
155 :    
156 :     int read_pgmheader(FILE* handle)
157 :     {
158 :     int bytes,xsize,ysize,depth;
159 :     char dummy[2];
160 :    
161 :     bytes = fread(dummy,1,2,handle);
162 :    
163 :     if ( (bytes < 2) || (dummy[0] != 'P') || (dummy[1] != '5' ))
164 :     return 1;
165 :     fscanf(handle,"%d %d %d",&xsize,&ysize,&depth);
166 :     if ( (xsize > 1440) || (ysize > 2880 ) || (depth != 255) )
167 :     {
168 :     return 2;
169 :     }
170 :     if ( (XDIM==0) || (YDIM==0) )
171 :     { XDIM=xsize;
172 :     YDIM=ysize;
173 :     }
174 :    
175 :     return 0;
176 :     }
177 :    
178 :     int read_pgmdata(FILE* handle, unsigned char *image)
179 :     {
180 :     int i,status;
181 :     char dummy;
182 :    
183 :     unsigned char* buff1_ptr2 = image + XDIM*YDIM;
184 :     unsigned char* buff1_ptr3 = image + XDIM*YDIM + XDIM/2*YDIM/2;
185 :    
186 :     fread(image,XDIM*YDIM,1,stdin); // read Y component of picture
187 :    
188 :     for (i=0;i<YDIM/2;i++)
189 :     {
190 :     fread(buff1_ptr2,XDIM/2,1,stdin); // read U
191 :     buff1_ptr2 += XDIM/2;
192 :     fread(buff1_ptr3,XDIM/2,1,stdin); // read V
193 :     buff1_ptr3 += XDIM/2;
194 :     }
195 :     fread(&dummy,1,1,handle); // I don't know why, but this seems needed
196 :     return 0;
197 :     }
198 :    
199 :     int read_yuvdata(FILE* handle, unsigned char *image)
200 :     { int i;
201 :     char dummy;
202 :    
203 :     unsigned char* buff1_ptr2 = image + XDIM*YDIM;
204 :     unsigned char* buff1_ptr3 = image + XDIM*YDIM + XDIM/2*YDIM/2;
205 :    
206 :     if (fread(image,XDIM,YDIM*3/2,stdin) != YDIM*3/2)
207 :     return 1;
208 :     else
209 :     return 0;
210 :     }
211 :    
212 :     int write_pgm(char *filename, unsigned char *image)
213 :     {
214 :     FILE *filehandle;
215 :     filehandle=fopen(filename,"wb");
216 :     if (filehandle)
217 :     {
218 :     fprintf(filehandle,"P5\n\n"); //
219 :     fprintf(filehandle,"%d %d 255\n",XDIM,YDIM*3/2);
220 :     fwrite(image,XDIM,YDIM*3/2,filehandle);
221 :     fclose(filehandle);
222 :     return 0;
223 :     }
224 :     else
225 :     return 1;
226 :     }
227 :    
228 :     /*********************************************************************/
229 :     /* Routines for encoding: init encoder, frame step, release encoder */
230 :     /*********************************************************************/
231 :    
232 :     #define FRAMERATE_INCR 1001
233 :    
234 :    
235 :     int enc_init(int use_assembler)
236 :     { /* initialize encoder for first use, pass all needed parameters to the codec */
237 :     int xerr;
238 :    
239 :     XVID_INIT_PARAM xinit;
240 :     XVID_ENC_PARAM xparam;
241 :    
242 :     if(use_assembler)
243 :    
244 :     #ifdef ARCH_IA64
245 :     xinit.cpu_flags = XVID_CPU_FORCE | XVID_CPU_IA64;
246 :     #else
247 :     xinit.cpu_flags = 0;
248 :     #endif
249 :    
250 :     else
251 :     xinit.cpu_flags = XVID_CPU_FORCE;
252 :    
253 :     xvid_init(NULL, 0, &xinit, NULL);
254 :    
255 :     xparam.width = XDIM;
256 :     xparam.height = YDIM;
257 :     if ((ARG_FRAMERATE - (int)ARG_FRAMERATE) < SMALL_EPS)
258 :     {
259 :     xparam.fincr = 1;
260 :     xparam.fbase = (int)ARG_FRAMERATE;
261 :     }
262 :     else
263 :     {
264 :     xparam.fincr = FRAMERATE_INCR;
265 :     xparam.fbase = (int)(FRAMERATE_INCR * ARG_FRAMERATE);
266 :     }
267 :     xparam.rc_reaction_delay_factor = 16;
268 :     xparam.rc_averaging_period = 100;
269 :     xparam.rc_buffer = 10;
270 :     xparam.rc_bitrate = ARG_BITRATE*1000;
271 :     xparam.min_quantizer = 1;
272 :     xparam.max_quantizer = 31;
273 :     xparam.max_key_interval = (int)ARG_FRAMERATE*10;
274 :    
275 :     #ifdef BFRAMES
276 :     xparam.global = XVID_GLOBAL_DX50BVOP;
277 :     xparam.max_bframes = ARG_MAXBFRAMES;
278 :     xparam.bquant_ratio = ARG_BQUANTRATIO;
279 :     xparam.frame_drop_ratio=0;
280 :     #endif
281 :    
282 :     /* I use a small value here, since will not encode whole movies,
283 :     but short clips */
284 :    
285 :     xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xparam, NULL);
286 :     enc_handle=xparam.handle;
287 :    
288 :     return xerr;
289 :     }
290 :    
291 :     int enc_stop()
292 :     { int xerr;
293 :    
294 :     xerr = xvid_encore(enc_handle, XVID_ENC_DESTROY, NULL, NULL);
295 :     return xerr;
296 :     }
297 :    
298 :     int enc_main(unsigned char* image, unsigned char* bitstream, int *streamlength, int* frametype)
299 :     { int xerr;
300 :    
301 :     XVID_ENC_FRAME xframe;
302 :     XVID_ENC_STATS xstats;
303 :    
304 :     xframe.bitstream = bitstream;
305 :     xframe.length = -1; // this is written by the routine
306 :    
307 :     xframe.image = image;
308 :     xframe.colorspace = XVID_CSP_YV12; // defined in <xvid.h>
309 :    
310 :     xframe.intra = -1; // let the codec decide between I-frame (1) and P-frame (0)
311 :    
312 :     xframe.quant = ARG_QUANTI; // is quant != 0, use a fixed quant (and ignore bitrate)
313 :    
314 :     xframe.motion = motion_presets[ARG_QUALITY];
315 :     xframe.general = general_presets[ARG_QUALITY];
316 :     xframe.quant_intra_matrix = xframe.quant_inter_matrix = NULL;
317 :    
318 :     #ifdef BFRAMES
319 :     xframe.bquant = 0;
320 :     #endif
321 :    
322 :     xerr = xvid_encore(enc_handle, XVID_ENC_ENCODE, &xframe, &xstats);
323 :    
324 :     /* enc_result->is_key_frame = xframe.intra;
325 :     enc_result->quantizer = xframe.quant;
326 :     enc_result->total_bits = xframe.length * 8;
327 :     enc_result->motion_bits = xstats.hlength * 8;
328 :     enc_result->texture_bits = enc_result->total_bits - enc_result->motion_bits;
329 :     */
330 :    
331 :     /* This is statictical data, e.g. for 2-pass.
332 :     If you are not interested in any of this, you can use
333 :     NULL instead of &xstats
334 :     */
335 :     *frametype = xframe.intra;
336 :     *streamlength = xframe.length;
337 :    
338 :     return xerr;
339 :     }
340 :    
341 :     /*********************************************************************/
342 :     /* Main program */
343 :     /*********************************************************************/
344 :    
345 :     int main(int argc, char *argv[])
346 :     {
347 :     unsigned char *divx_buffer = NULL;
348 :     unsigned char *in_buffer = NULL;
349 :    
350 :     double enctime;
351 :     double totalenctime=0.;
352 :    
353 :     long totalsize=0;
354 :     int status;
355 :    
356 :     int m4v_size;
357 :     int frame_type[ABS_MAXFRAMENR];
358 :     int Iframes=0, Pframes=0, Bframes=0;
359 :     int use_assembler=1;
360 :    
361 :     char filename[256];
362 :    
363 :     FILE *filehandle;
364 :    
365 :     /* read YUV in pgm format from stdin */
366 :     if (!pgmflag)
367 :     {
368 :     pgmflag = 1;
369 :    
370 :     // if (argc==2 && !strcmp(argv[1],"-noasm"))
371 :     // use_assembler = 0;
372 :    
373 :     if (argc>=3)
374 :     { XDIM = atoi(argv[1]);
375 :     YDIM = atoi(argv[2]);
376 :     if ( (XDIM <= 0) || (XDIM >= 2048) || (YDIM <=0) || (YDIM >= 2048) )
377 :     { fprintf(stderr,"Wrong frames size %d %d, trying PGM \n",XDIM, YDIM);
378 :     }
379 :     else
380 :     {
381 :     YDIM = YDIM*3/2; /* for YUV */
382 :     pgmflag = 0;
383 :     }
384 :     }
385 :     }
386 :    
387 :     if (pgmflag)
388 :     { if (read_pgmheader(stdin))
389 :     {
390 :     fprintf(stderr,"Wrong input format, I want YUV encapsulated in PGM\n");
391 :     return 1;
392 :     }
393 :     }
394 :     if (argc>=4)
395 :     { ARG_QUALITY = atoi(argv[3]);
396 :     if ( (ARG_QUALITY < 0) || (ARG_QUALITY > 6) )
397 :     { fprintf(stderr,"Wrong Quality\n"); return -1; }
398 :     else
399 :     fprintf(stderr,"Quality %d\n",ARG_QUALITY);
400 :     }
401 :     if (argc>=5)
402 :     { ARG_BITRATE = atoi(argv[4]);
403 :     if ( (ARG_BITRATE <= 0) )
404 :     { fprintf(stderr,"Wrong Bitrate\n"); return -1; }
405 :     if ( (ARG_BITRATE < 32) )
406 :     { ARG_QUANTI = ARG_BITRATE;
407 :     ARG_BITRATE=0;
408 :     fprintf(stderr,"Quantizer %d\n",ARG_QUANTI);
409 :     }
410 :     else
411 :     fprintf(stderr,"Bitrate %d kbps\n",ARG_BITRATE);
412 :     }
413 :     if (argc>=6)
414 :     { ARG_FRAMERATE = (float)atof(argv[5]);
415 :     if ( (ARG_FRAMERATE <= 0) )
416 :     { fprintf(stderr,"Wrong Fraterate %s \n",argv[5]); return -1; }
417 :     fprintf(stderr,"Framerate %6.3f fps\n",ARG_FRAMERATE);
418 :     }
419 :    
420 :     if (argc>=7)
421 :     { ARG_MAXFRAMENR = atoi(argv[6]);
422 :     if ( (ARG_MAXFRAMENR <= 0) )
423 :     { fprintf(stderr,"Wrong number of frames\n"); return -1; }
424 :     fprintf(stderr,"max. Framenr. %d\n",ARG_MAXFRAMENR);
425 :     }
426 :    
427 :     #ifdef BFRAMES
428 :     if (argc>=8)
429 :     { ARG_MAXBFRAMES = atoi(argv[7]);
430 :     if ( (ARG_MAXBFRAMES < -1) || ( ARG_MAXBFRAMES > ARG_FRAMERATE) )
431 :     { fprintf(stderr,"Wrong maximumnumber of bframes\n"); return -1; }
432 :     fprintf(stderr,"max. B-frames %d\n",ARG_MAXBFRAMES);
433 :     }
434 :    
435 :     if (argc>=9)
436 :     { ARG_MAXFRAMENR = atoi(argv[8]);
437 :     if ( (ARG_BQUANTRATIO <= 0) )
438 :     { fprintf(stderr,"Wrong B-frames Quantizer ratio \n"); return -1; }
439 :     fprintf(stderr,"B-frames quant-ratio %d\n",ARG_BQUANTRATIO);
440 :     }
441 :     #endif
442 :    
443 :     /* now we know the sizes, so allocate memory */
444 :    
445 :     in_buffer = (unsigned char *) malloc(XDIM*YDIM);
446 :     if (!in_buffer)
447 :     goto free_all_memory;
448 :    
449 :     divx_buffer = (unsigned char *) malloc(XDIM*YDIM*2);
450 :     if (!divx_buffer)
451 :     goto free_all_memory;
452 :    
453 :     YDIM = YDIM*2/3; // PGM is YUV 4:2:0 format, so real image height is *2/3 of PGM picture
454 :    
455 :     /*********************************************************************/
456 :     /* XviD PART Start */
457 :     /*********************************************************************/
458 :    
459 :     status = enc_init(use_assembler);
460 :     if (status)
461 :     {
462 :     fprintf(stderr,"Encore INIT problem, return value %d\n", status);
463 :     goto release_all;
464 :     }
465 :    
466 :     /*********************************************************************/
467 :     /* Main loop */
468 :     /*********************************************************************/
469 :    
470 :     do
471 :     {
472 :     if (pgmflag)
473 :     status = read_pgmdata(stdin, in_buffer); // read PGM data (YUV-format)
474 :     else
475 :     status = read_yuvdata(stdin, in_buffer); // read raw data (YUV-format)
476 :    
477 :     if (status)
478 :     {
479 :     // Couldn't read image, most likely end-of-file
480 :     continue;
481 :     }
482 :    
483 :    
484 :     if (save_ref_flag)
485 :     {
486 :     sprintf(filename, "%s%05d.pgm", filepath, filenr);
487 :     write_pgm(filename,in_buffer);
488 :     }
489 :    
490 :    
491 :     /*********************************************************************/
492 :     /* analyse this frame before encoding */
493 :     /*********************************************************************/
494 :    
495 :     // nothing is done here at the moment, but you could e.g. create
496 :     // histograms or measure entropy or apply preprocessing filters...
497 :    
498 :     /*********************************************************************/
499 :     /* encode and decode this frame */
500 :     /*********************************************************************/
501 :    
502 :     enctime = -msecond();
503 :     status = enc_main(in_buffer, divx_buffer, &m4v_size, &frame_type[filenr]);
504 :     enctime += msecond();
505 :    
506 :     totalenctime += enctime;
507 :     totalsize += m4v_size;
508 :    
509 :     fprintf(stderr,"Frame %5d: intra %d, enctime =%6.1f ms length=%7d bytes\n",
510 :     filenr, frame_type[filenr], enctime*1000, m4v_size);
511 :    
512 :     if (save_m4v_flag)
513 :     {
514 :     fwrite(divx_buffer, m4v_size, 1, stdout);
515 :     }
516 :    
517 :     if (pgmflag)
518 :     status = read_pgmheader(stdin);
519 :     // because if this was the last PGM, stop now
520 :    
521 :     filenr++;
522 :    
523 :     } while ( (!status) && (filenr<ARG_MAXFRAMENR) );
524 :    
525 :    
526 :    
527 :     /*********************************************************************/
528 :     /* calculate totals and averages for output, print results */
529 :     /*********************************************************************/
530 :    
531 :     totalsize /= filenr;
532 :     totalenctime /= filenr;
533 :    
534 :     for (i=0;i<filenr;i++)
535 :     {
536 :     switch (frame_type[i])
537 :     {
538 :     case 0:
539 :     Pframes++;
540 :     break;
541 :     case 1:
542 :     Iframes++;
543 :     break;
544 :     case 2:
545 :     default:
546 :     Bframes++;
547 :     break;
548 :     }
549 :     }
550 :    
551 :     fprintf(stderr,"Avg: enctime %5.2f ms, %5.2f fps, filesize =%d\n",
552 :     1000*totalenctime, 1./totalenctime, totalsize);
553 :    
554 :     /*********************************************************************/
555 :     /* XviD PART Stop */
556 :     /*********************************************************************/
557 :    
558 :     release_all:
559 :    
560 :     if (enc_handle)
561 :     {
562 :     status = enc_stop();
563 :     if (status)
564 :     fprintf(stderr,"Encore RELEASE problem return value %d\n", status);
565 :     }
566 :    
567 :     free_all_memory:
568 :     free(divx_buffer);
569 :     free(in_buffer);
570 :    
571 :     return 0;
572 :     }

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