[svn] / trunk / xvidcore / examples / xvid_decraw.c Repository:
ViewVC logotype

Annotation of /trunk/xvidcore/examples/xvid_decraw.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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