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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 918 - (view) (download)

1 : edgomez 547 /*****************************************************************************
2 : chl 376 *
3 : edgomez 547 * XVID MPEG-4 VIDEO CODEC
4 :     * - Console based decoding test application -
5 : chl 376 *
6 : edgomez 851 * Copyright(C) 2002-2003 Christoph Lampert
7 : chl 376 *
8 : edgomez 547 * 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 376 *
13 : edgomez 547 * 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 : chl 376 *
18 : edgomez 547 * 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 918 * $Id: xvid_decraw.c,v 1.7.2.1 2003-03-11 23:39:47 edgomez Exp $
23 : edgomez 547 *
24 :     ****************************************************************************/
25 : chl 376
26 : edgomez 547 /*****************************************************************************
27 : chl 376 *
28 : edgomez 547 * Application notes :
29 : chl 376 *
30 : edgomez 547 * An MPEG-4 bitstream is read from an input file (or stdin) and decoded,
31 :     * the speed for this is measured.
32 : chl 376 *
33 :     * The program is plain C and needs no libraries except for libxvidcore,
34 :     * and maths-lib, so with UN*X you simply compile by
35 : edgomez 547 *
36 : chl 376 * gcc xvid_decraw.c -lxvidcore -lm -o xvid_decraw
37 :     *
38 :     * You have to specify the image dimensions (until the add the feature
39 :     * to read this from the bitstream)
40 : edgomez 547 *
41 :     * Usage : xvid_decraw <-w width> <-h height> [OPTIONS]
42 :     * Options :
43 :     * -asm : use assembly optimizations (default=disabled)
44 :     * -i string : input filename (default=stdin)
45 :     * -t integer : input data type (raw=0, mp4u=1)
46 : edgomez 918 * -d : save decoder output (0 False*, !=0 True)
47 :     * -m : save mpeg4 raw stream to single files (0 False*, !=0 True)
48 : edgomez 547 * -help : This help message
49 :     * (* means default)
50 : chl 376 *
51 : edgomez 547 ****************************************************************************/
52 : chl 376
53 :     #include <stdio.h>
54 :     #include <stdlib.h>
55 : edgomez 547 #include <string.h>
56 :     #include <math.h>
57 : edgomez 824 #ifndef WIN32
58 : edgomez 547 #include <sys/time.h>
59 :     #else
60 :     #include <time.h>
61 :     #endif
62 : chl 376
63 : edgomez 547 #include "xvid.h"
64 : chl 376
65 : edgomez 547 /*****************************************************************************
66 :     * Global vars in module and constants
67 :     ****************************************************************************/
68 : chl 376
69 : edgomez 547 /* max number of frames */
70 :     #define ABS_MAXFRAMENR 9999
71 : chl 376
72 : edgomez 547 static int XDIM = 0;
73 :     static int YDIM = 0;
74 :     static int ARG_SAVEDECOUTPUT = 0;
75 :     static int ARG_SAVEMPEGSTREAM = 0;
76 :     static char *ARG_INPUTFILE = NULL;
77 : chl 376
78 :    
79 : edgomez 547 static char filepath[256] = "./";
80 :     static void *dec_handle = NULL;
81 : chl 376
82 : edgomez 918 # define BUFFER_SIZE (2*1024*1024)
83 : chl 376
84 : edgomez 547 /*****************************************************************************
85 :     * Local prototypes
86 :     ****************************************************************************/
87 : chl 376
88 : edgomez 547 static double msecond();
89 :     static int write_pgm(char *filename,
90 : edgomez 918 unsigned char *image);
91 : edgomez 547 static int dec_init(int use_assembler);
92 :     static int dec_main(unsigned char *istream,
93 : edgomez 851 unsigned char *ostream,
94 :     int istream_size,
95 : edgomez 918 xvid_dec_stats_t *xvid_dec_stats);
96 : edgomez 547 static int dec_stop();
97 :     static void usage();
98 :    
99 :     /*****************************************************************************
100 :     * Main program
101 :     ****************************************************************************/
102 :    
103 :     int main(int argc, char *argv[])
104 : chl 376 {
105 : edgomez 547 unsigned char *mp4_buffer = NULL;
106 :     unsigned char *mp4_ptr = NULL;
107 :     unsigned char *out_buffer = NULL;
108 : edgomez 918 unsigned char *type = NULL;
109 : edgomez 851 int still_left_in_buffer;
110 :     int delayed_frames;
111 : edgomez 918 xvid_dec_stats_t xvid_dec_stats;
112 : edgomez 851
113 : edgomez 547 double totaldectime;
114 :    
115 :     long totalsize;
116 :     int status;
117 :    
118 :     int use_assembler = 0;
119 :    
120 :     char filename[256];
121 :    
122 :     FILE *in_file;
123 :     int filenr;
124 :     int i;
125 :    
126 :     printf("xvid_decraw - raw mpeg4 bitstream decoder ");
127 : edgomez 851 printf("written by Christoph Lampert 2002-2003\n\n");
128 : edgomez 547
129 :     /*****************************************************************************
130 :     * Command line parsing
131 :     ****************************************************************************/
132 :    
133 :     for (i=1; i< argc; i++) {
134 :    
135 :     if (strcmp("-asm", argv[i]) == 0 ) {
136 :     use_assembler = 1;
137 :     }
138 : edgomez 918 else if (strcmp("-d", argv[i]) == 0) {
139 :     ARG_SAVEDECOUTPUT = 1;
140 : edgomez 547 }
141 :     else if (strcmp("-i", argv[i]) == 0 && i < argc - 1 ) {
142 :     i++;
143 :     ARG_INPUTFILE = argv[i];
144 :     }
145 : edgomez 918 else if (strcmp("-m", argv[i]) == 0) {
146 :     ARG_SAVEMPEGSTREAM = 1;
147 : edgomez 547 }
148 :     else if (strcmp("-help", argv[i])) {
149 :     usage();
150 :     return(0);
151 :     }
152 :     else {
153 :     usage();
154 :     exit(-1);
155 :     }
156 :    
157 : chl 376 }
158 : edgomez 547
159 :     /*****************************************************************************
160 :     * Values checking
161 :     ****************************************************************************/
162 :    
163 :     if ( ARG_INPUTFILE == NULL || strcmp(ARG_INPUTFILE, "stdin") == 0) {
164 :     in_file = stdin;
165 :     }
166 :     else {
167 :    
168 :     in_file = fopen(ARG_INPUTFILE, "rb");
169 :     if (in_file == NULL) {
170 :     fprintf(stderr, "Error opening input file %s\n", ARG_INPUTFILE);
171 : edgomez 918 return(-1);
172 : edgomez 547 }
173 :     }
174 :    
175 :     /*****************************************************************************
176 :     * Memory allocation
177 :     ****************************************************************************/
178 :    
179 :     /* Memory for encoded mp4 stream */
180 :     mp4_buffer = (unsigned char *) malloc(BUFFER_SIZE);
181 :     mp4_ptr = mp4_buffer;
182 :     if (!mp4_buffer)
183 :     goto free_all_memory;
184 :    
185 :     /*****************************************************************************
186 :     * XviD PART Start
187 :     ****************************************************************************/
188 :    
189 :     status = dec_init(use_assembler);
190 :     if (status) {
191 :     fprintf(stderr,
192 : edgomez 918 "Decore INIT problem, return value %d\n", status);
193 : edgomez 547 goto release_all;
194 :     }
195 :    
196 :    
197 :     /*****************************************************************************
198 :     * Main loop
199 :     ****************************************************************************/
200 :    
201 : edgomez 851 /* Fill the buffer */
202 :     still_left_in_buffer = fread(mp4_buffer, 1, BUFFER_SIZE, in_file);
203 : edgomez 559
204 : edgomez 547 totaldectime = 0;
205 :     totalsize = 0;
206 :     filenr = 0;
207 : edgomez 851 delayed_frames = 0;
208 : edgomez 547 mp4_ptr = mp4_buffer;
209 :    
210 :     do {
211 :    
212 :     int mp4_size = (mp4_buffer + BUFFER_SIZE - mp4_ptr);
213 :     int used_bytes = 0;
214 :     double dectime;
215 :    
216 : edgomez 851 /*
217 :     * If the buffer is half empty or there are no more bytes in it
218 :     * then fill it.
219 :     */
220 :     if (mp4_ptr > mp4_buffer + BUFFER_SIZE/2 ||
221 :     still_left_in_buffer <= 0) {
222 :     int rest = (mp4_buffer + BUFFER_SIZE - mp4_ptr);
223 : edgomez 547
224 : edgomez 851 /* Move data if needed */
225 :     if (rest)
226 :     memcpy(mp4_buffer, mp4_ptr, rest);
227 : edgomez 547
228 : edgomez 851 /* Update mp4_ptr */
229 :     mp4_ptr = mp4_buffer;
230 : edgomez 547
231 : edgomez 851 /* read new data */
232 : edgomez 547 if(feof(in_file))
233 :     break;
234 :    
235 : edgomez 851 still_left_in_buffer = fread(mp4_buffer + rest,
236 :     1,
237 :     BUFFER_SIZE - rest,
238 :     in_file);
239 : edgomez 547
240 :     }
241 :    
242 :    
243 : edgomez 918 /* This loop is needed to handle VOL/NVOP reading */
244 : edgomez 851 do {
245 : edgomez 547
246 : edgomez 851 /* Decode frame */
247 :     dectime = msecond();
248 : edgomez 918 used_bytes = dec_main(mp4_ptr, out_buffer, mp4_size, &xvid_dec_stats);
249 : edgomez 851 dectime = msecond() - dectime;
250 : edgomez 547
251 : edgomez 918 /* Resize image buffer if needed */
252 :     if(xvid_dec_stats.type == XVID_TYPE_VOL) {
253 :    
254 :     /* Free old output buffer*/
255 :     if(out_buffer) free(out_buffer);
256 :    
257 :     /* Copy witdh and height from the vol structure */
258 :     XDIM = xvid_dec_stats.data.vol.width;
259 :     YDIM = xvid_dec_stats.data.vol.height;
260 :    
261 :     /* Allocate the new buffer */
262 :     if((out_buffer = (unsigned char*)malloc(XDIM*YDIM*4)) == NULL)
263 :     goto free_all_memory;
264 : edgomez 851 }
265 : edgomez 547
266 : edgomez 851 /* Update buffer pointers */
267 : edgomez 918 if(used_bytes > 0) {
268 :     mp4_ptr += used_bytes;
269 :     still_left_in_buffer -= used_bytes;
270 : edgomez 559
271 : edgomez 918 /* Total size */
272 :     totalsize += used_bytes;
273 :     }
274 : edgomez 547
275 : edgomez 918 }while(xvid_dec_stats.type != XVID_TYPE_IVOP &&
276 :     xvid_dec_stats.type != XVID_TYPE_PVOP &&
277 :     xvid_dec_stats.type != XVID_TYPE_BVOP &&
278 :     xvid_dec_stats.type != XVID_TYPE_SVOP &&
279 :     still_left_in_buffer > 0);
280 : edgomez 547
281 : edgomez 851 /* Negative buffer would mean we went too far */
282 :     if(still_left_in_buffer < 0) break;
283 :    
284 : edgomez 918 /* Skip when decoder is buffering images because of bframes */
285 :     if(xvid_dec_stats.type == XVID_TYPE_NOTHING) {
286 :     delayed_frames++;
287 : edgomez 851 continue;
288 : edgomez 547 }
289 :    
290 : edgomez 851 /* Updated data - Count only usefull decode time */
291 :     totaldectime += dectime;
292 : edgomez 547
293 :     /* Prints some decoding stats */
294 : edgomez 918 switch(xvid_dec_stats.type) {
295 :     case XVID_TYPE_IVOP:
296 :     type = "I";
297 :     break;
298 :     case XVID_TYPE_PVOP:
299 :     type = "P";
300 :     break;
301 :     case XVID_TYPE_BVOP:
302 :     type = "B";
303 :     break;
304 :     case XVID_TYPE_SVOP:
305 :     type = "S";
306 :     break;
307 :     }
308 :    
309 :     printf("Frame %5d: type = %s, dectime(ms) =%6.1f, length(bytes) =%7d\n",
310 :     filenr, type, dectime, used_bytes);
311 : edgomez 851
312 :     /* Save individual mpeg4 stream if required */
313 : edgomez 918 if(ARG_SAVEMPEGSTREAM) {
314 : edgomez 547 FILE *filehandle = NULL;
315 :    
316 :     sprintf(filename, "%sframe%05d.m4v", filepath, filenr);
317 :     filehandle = fopen(filename, "wb");
318 :     if(!filehandle) {
319 :     fprintf(stderr,
320 : edgomez 851 "Error writing single mpeg4 stream to file %s\n",
321 :     filename);
322 : edgomez 547 }
323 :     else {
324 : edgomez 851 fwrite(mp4_buffer, 1, used_bytes, filehandle);
325 : edgomez 547 fclose(filehandle);
326 :     }
327 :     }
328 : edgomez 851
329 : edgomez 547 /* Save output frame if required */
330 :     if (ARG_SAVEDECOUTPUT) {
331 :     sprintf(filename, "%sdec%05d.pgm", filepath, filenr);
332 :     if(write_pgm(filename,out_buffer)) {
333 :     fprintf(stderr,
334 : edgomez 851 "Error writing decoded PGM frame %s\n",
335 :     filename);
336 : edgomez 547 }
337 :     }
338 :    
339 :     filenr++;
340 :    
341 : edgomez 851 } while ( (status>=0) && (filenr<ABS_MAXFRAMENR));
342 : edgomez 547
343 :     /*****************************************************************************
344 : edgomez 851 * Flush decoder buffers
345 :     ****************************************************************************/
346 : edgomez 918
347 : edgomez 851 while(delayed_frames--) {
348 :    
349 :     /* Fake vars */
350 : edgomez 918 int used_bytes;
351 : edgomez 851 double dectime;
352 :    
353 :     /* Decode frame */
354 :     dectime = msecond();
355 : edgomez 918 used_bytes = dec_main(NULL, out_buffer, -1, &xvid_dec_stats);
356 : edgomez 851 dectime = msecond() - dectime;
357 :    
358 :     /* Updated data - Count only usefull decode time */
359 :     totaldectime += dectime;
360 :    
361 :     /* Prints some decoding stats */
362 :     printf("Frame %5d: dectime(ms) =%6.1f, length(bytes) =%7d\n",
363 :     filenr, dectime, used_bytes);
364 :    
365 :     /* Save output frame if required */
366 :     if (ARG_SAVEDECOUTPUT) {
367 :     sprintf(filename, "%sdec%05d.pgm", filepath, filenr);
368 : edgomez 918 if(write_pgm(filename, out_buffer)) {
369 : edgomez 851 fprintf(stderr,
370 :     "Error writing decoded PGM frame %s\n",
371 :     filename);
372 :     }
373 :     }
374 :    
375 :     filenr++;
376 :    
377 :     }
378 :    
379 :     /*****************************************************************************
380 : edgomez 547 * Calculate totals and averages for output, print results
381 :     ****************************************************************************/
382 :    
383 :     totalsize /= filenr;
384 :     totaldectime /= filenr;
385 :    
386 : edgomez 851 printf("Avg: dectime(ms) =%7.2f, fps =%7.2f, length(bytes) =%7d\n",
387 : edgomez 918 totaldectime, 1000/totaldectime, (int)totalsize);
388 : edgomez 547
389 :     /*****************************************************************************
390 :     * XviD PART Stop
391 : edgomez 559 ****************************************************************************/
392 : edgomez 547
393 :     release_all:
394 :     if (dec_handle) {
395 :     status = dec_stop();
396 :     if (status)
397 :     fprintf(stderr, "decore RELEASE problem return value %d\n", status);
398 :     }
399 :    
400 :     free_all_memory:
401 :     free(out_buffer);
402 :     free(mp4_buffer);
403 :    
404 : edgomez 918 return(0);
405 : chl 376 }
406 :    
407 : edgomez 547 /*****************************************************************************
408 :     * Usage function
409 :     ****************************************************************************/
410 : chl 376
411 : edgomez 547 static void usage()
412 : chl 376 {
413 : edgomez 547
414 :     fprintf(stderr, "Usage : xvid_decraw <-w width> <-h height> [OPTIONS]\n");
415 :     fprintf(stderr, "Options :\n");
416 :     fprintf(stderr, " -asm : use assembly optimizations (default=disabled)\n");
417 :     fprintf(stderr, " -i string : input filename (default=stdin)\n");
418 :     fprintf(stderr, " -t integer : input data type (raw=0, mp4u=1)\n");
419 : edgomez 918 fprintf(stderr, " -d : save decoder output\n");
420 :     fprintf(stderr, " -m : save mpeg4 raw stream to individual files\n");
421 : edgomez 547 fprintf(stderr, " -help : This help message\n");
422 :     fprintf(stderr, " (* means default)\n");
423 :    
424 :     }
425 :    
426 :     /*****************************************************************************
427 :     * "helper" functions
428 :     ****************************************************************************/
429 :    
430 :     /* return the current time in milli seconds */
431 :     static double
432 :     msecond()
433 :     {
434 : edgomez 824 #ifndef WIN32
435 : edgomez 547 struct timeval tv;
436 :     gettimeofday(&tv, 0);
437 : edgomez 918 return((double)tv.tv_sec*1.0e3 + (double)tv.tv_usec*1.0e-3);
438 : edgomez 547 #else
439 :     clock_t clk;
440 :     clk = clock();
441 : edgomez 918 return(clk * 1000 / CLOCKS_PER_SEC);
442 : edgomez 547 #endif
443 :     }
444 :    
445 :     /*****************************************************************************
446 :     * output functions
447 :     ****************************************************************************/
448 :    
449 :     static int
450 :     write_pgm(char *filename,
451 : edgomez 918 unsigned char *image)
452 : edgomez 547 {
453 :     int loop;
454 :    
455 :     unsigned char *y = image;
456 :     unsigned char *u = image + XDIM*YDIM;
457 :     unsigned char *v = image + XDIM*YDIM + XDIM/2*YDIM/2;
458 :    
459 : chl 376 FILE *filehandle;
460 : edgomez 547 filehandle=fopen(filename,"w+b");
461 :     if (filehandle) {
462 : chl 376
463 : edgomez 547 /* Write header */
464 :     fprintf(filehandle,"P5\n\n%d %d 255\n", XDIM,YDIM*3/2);
465 :    
466 :     /* Write Y data */
467 :     fwrite(y, 1, XDIM*YDIM, filehandle);
468 :    
469 :     for(loop=0; loop<YDIM/2; loop++)
470 :     {
471 :     /* Write U scanline */
472 :     fwrite(u, 1, XDIM/2, filehandle);
473 :    
474 :     /* Write V scanline */
475 :     fwrite(v, 1, XDIM/2, filehandle);
476 :    
477 :     /* Update pointers */
478 :     u += XDIM/2;
479 :     v += XDIM/2;
480 :    
481 :     }
482 :    
483 :     /* Close file */
484 : chl 376 fclose(filehandle);
485 : edgomez 547
486 : edgomez 918 return(0);
487 : chl 376 }
488 :     else
489 : edgomez 918 return(1);
490 : chl 376 }
491 :    
492 : edgomez 547 /*****************************************************************************
493 :     * Routines for decoding: init decoder, use, and stop decoder
494 :     ****************************************************************************/
495 : chl 376
496 : edgomez 547 /* init decoder before first run */
497 :     static int
498 :     dec_init(int use_assembler)
499 : chl 376 {
500 : edgomez 918 int ret;
501 : chl 376
502 : edgomez 918 xvid_gbl_init_t xvid_gbl_init;
503 :     xvid_dec_create_t xvid_dec_create;
504 : chl 376
505 : edgomez 918 /*------------------------------------------------------------------------
506 :     * XviD core initialization
507 :     *----------------------------------------------------------------------*/
508 :    
509 :     /* Version */
510 :     xvid_gbl_init.version = XVID_VERSION;
511 :    
512 :     /* Assembly setting */
513 :     if(use_assembler)
514 : suxen_drol 860 #ifdef ARCH_IS_IA64
515 : edgomez 918 xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_IA64;
516 : chl 376 #else
517 : edgomez 918 xvid_gbl_init.cpu_flags = 0;
518 : chl 376 #endif
519 : edgomez 918 else
520 :     xvid_gbl_init.cpu_flags = XVID_CPU_FORCE;
521 : chl 376
522 : edgomez 918 xvid_global(NULL, 0, &xvid_gbl_init, NULL);
523 : chl 376
524 : edgomez 918 /*------------------------------------------------------------------------
525 :     * XviD encoder initialization
526 :     *----------------------------------------------------------------------*/
527 : edgomez 851
528 : edgomez 918 /* Version */
529 :     xvid_dec_create.version = XVID_VERSION;
530 : chl 376
531 : edgomez 918 /*
532 :     * Image dimensions -- set to 0, xvidcore will resize when ever it is
533 :     * needed
534 :     */
535 :     xvid_dec_create.width = 0;
536 :     xvid_dec_create.height = 0;
537 :    
538 :     ret = xvid_decore(NULL, XVID_DEC_CREATE, &xvid_dec_create, NULL);
539 :    
540 :     dec_handle = xvid_dec_create.handle;
541 :    
542 :     return(ret);
543 : chl 376 }
544 :    
545 : edgomez 547 /* decode one frame */
546 :     static int
547 :     dec_main(unsigned char *istream,
548 : edgomez 851 unsigned char *ostream,
549 :     int istream_size,
550 : edgomez 918 xvid_dec_stats_t *xvid_dec_stats)
551 : edgomez 547 {
552 : chl 376
553 : edgomez 918 int ret;
554 : chl 376
555 : edgomez 918 xvid_dec_frame_t xvid_dec_frame;
556 : chl 376
557 : edgomez 918 /* Set version */
558 :     xvid_dec_frame.version = XVID_VERSION;
559 :     xvid_dec_stats->version = XVID_VERSION;
560 : chl 376
561 : edgomez 918 /* No general flags to set */
562 :     xvid_dec_frame.general = 0;
563 : chl 376
564 : edgomez 918 /* Input stream */
565 :     xvid_dec_frame.bitstream = istream;
566 :     xvid_dec_frame.length = istream_size;
567 : edgomez 851
568 : edgomez 918 /* Output frame structure */
569 :     xvid_dec_frame.output.plane[0] = ostream;
570 :     xvid_dec_frame.output.stride[0] = XDIM;
571 :     xvid_dec_frame.output.csp = XVID_CSP_I420;
572 :    
573 :     ret = xvid_decore(dec_handle, XVID_DEC_DECODE, &xvid_dec_frame, xvid_dec_stats);
574 :    
575 :     return(ret);
576 : chl 376 }
577 :    
578 : edgomez 547 /* close decoder to release resources */
579 :     static int
580 :     dec_stop()
581 : chl 376 {
582 : edgomez 918 int ret;
583 : edgomez 547
584 : edgomez 918 ret = xvid_decore(dec_handle, XVID_DEC_DESTROY, NULL, NULL);
585 : chl 376
586 : edgomez 918 return(ret);
587 : chl 376 }

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