[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 1382 - (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 : edgomez 1382 * $Id: xvid_decraw.c,v 1.10 2004-03-22 22:36:23 edgomez 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 : edgomez 547 static int dec_init(int use_assembler);
80 :     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 :    
118 :     char filename[256];
119 :    
120 :     FILE *in_file;
121 :     int filenr;
122 :     int i;
123 :    
124 :     printf("xvid_decraw - raw mpeg4 bitstream decoder ");
125 : edgomez 851 printf("written by Christoph Lampert 2002-2003\n\n");
126 : edgomez 547
127 :     /*****************************************************************************
128 :     * Command line parsing
129 :     ****************************************************************************/
130 :    
131 :     for (i=1; i< argc; i++) {
132 :    
133 :     if (strcmp("-asm", argv[i]) == 0 ) {
134 :     use_assembler = 1;
135 : edgomez 1382 } else if (strcmp("-d", argv[i]) == 0) {
136 :     ARG_SAVEDECOUTPUT = 1;
137 :     } else if (strcmp("-i", argv[i]) == 0 && i < argc - 1 ) {
138 : edgomez 547 i++;
139 :     ARG_INPUTFILE = argv[i];
140 : edgomez 1382 } else if (strcmp("-m", argv[i]) == 0) {
141 :     ARG_SAVEMPEGSTREAM = 1;
142 :     } else if (strcmp("-help", argv[i]) == 0) {
143 : edgomez 547 usage();
144 :     return(0);
145 : edgomez 1382 } else {
146 : edgomez 547 usage();
147 :     exit(-1);
148 :     }
149 : chl 376 }
150 : edgomez 547
151 :     /*****************************************************************************
152 :     * Values checking
153 :     ****************************************************************************/
154 :    
155 :     if ( ARG_INPUTFILE == NULL || strcmp(ARG_INPUTFILE, "stdin") == 0) {
156 :     in_file = stdin;
157 :     }
158 :     else {
159 :    
160 :     in_file = fopen(ARG_INPUTFILE, "rb");
161 :     if (in_file == NULL) {
162 :     fprintf(stderr, "Error opening input file %s\n", ARG_INPUTFILE);
163 : edgomez 1382 return(-1);
164 : edgomez 547 }
165 :     }
166 :    
167 :     /*****************************************************************************
168 :     * Memory allocation
169 :     ****************************************************************************/
170 :    
171 :     /* Memory for encoded mp4 stream */
172 :     mp4_buffer = (unsigned char *) malloc(BUFFER_SIZE);
173 :     mp4_ptr = mp4_buffer;
174 :     if (!mp4_buffer)
175 :     goto free_all_memory;
176 :    
177 :     /*****************************************************************************
178 :     * XviD PART Start
179 :     ****************************************************************************/
180 :    
181 :     status = dec_init(use_assembler);
182 :     if (status) {
183 :     fprintf(stderr,
184 : edgomez 1382 "Decore INIT problem, return value %d\n", status);
185 : edgomez 547 goto release_all;
186 :     }
187 :    
188 :    
189 :     /*****************************************************************************
190 :     * Main loop
191 :     ****************************************************************************/
192 :    
193 : edgomez 851 /* Fill the buffer */
194 : edgomez 1382 useful_bytes = fread(mp4_buffer, 1, BUFFER_SIZE, in_file);
195 : edgomez 559
196 : edgomez 547 totaldectime = 0;
197 :     totalsize = 0;
198 :     filenr = 0;
199 :     mp4_ptr = mp4_buffer;
200 :    
201 :     do {
202 :     int used_bytes = 0;
203 :     double dectime;
204 :    
205 : edgomez 851 /*
206 :     * If the buffer is half empty or there are no more bytes in it
207 :     * then fill it.
208 :     */
209 : edgomez 1382 if (mp4_ptr > mp4_buffer + BUFFER_SIZE/2) {
210 :     int already_in_buffer = (mp4_buffer + BUFFER_SIZE - mp4_ptr);
211 : edgomez 547
212 : edgomez 851 /* Move data if needed */
213 : edgomez 1382 if (already_in_buffer > 0)
214 :     memcpy(mp4_buffer, mp4_ptr, already_in_buffer);
215 : edgomez 547
216 : edgomez 851 /* Update mp4_ptr */
217 :     mp4_ptr = mp4_buffer;
218 : edgomez 547
219 : edgomez 851 /* read new data */
220 : edgomez 1382 if(feof(in_file))
221 : edgomez 547 break;
222 :    
223 : edgomez 1382 useful_bytes += fread(mp4_buffer + already_in_buffer,
224 :     1, BUFFER_SIZE - already_in_buffer,
225 :     in_file);
226 : edgomez 547
227 :     }
228 :    
229 :    
230 : edgomez 1382 /* This loop is needed to handle VOL/NVOP reading */
231 : edgomez 851 do {
232 : edgomez 547
233 : edgomez 851 /* Decode frame */
234 :     dectime = msecond();
235 : edgomez 1382 used_bytes = dec_main(mp4_ptr, out_buffer, useful_bytes, &xvid_dec_stats);
236 : edgomez 851 dectime = msecond() - dectime;
237 : edgomez 547
238 : edgomez 1382 /* Resize image buffer if needed */
239 :     if(xvid_dec_stats.type == XVID_TYPE_VOL) {
240 :    
241 :     /* Check if old buffer is smaller */
242 :     if(XDIM*YDIM < xvid_dec_stats.data.vol.width*xvid_dec_stats.data.vol.height) {
243 :    
244 :     /* Copy new witdh and new height from the vol structure */
245 :     XDIM = xvid_dec_stats.data.vol.width;
246 :     YDIM = xvid_dec_stats.data.vol.height;
247 :    
248 :     /* Free old output buffer*/
249 :     if(out_buffer) free(out_buffer);
250 :    
251 :     /* Allocate the new buffer */
252 :     out_buffer = (unsigned char*)malloc(XDIM*YDIM*4);
253 :     if(out_buffer == NULL)
254 :     goto free_all_memory;
255 :    
256 :     fprintf(stderr, "Resized frame buffer to %dx%d\n", XDIM, YDIM);
257 :     }
258 : edgomez 851 }
259 : edgomez 547
260 : edgomez 851 /* Update buffer pointers */
261 : edgomez 1382 if(used_bytes > 0) {
262 :     mp4_ptr += used_bytes;
263 :     useful_bytes -= used_bytes;
264 : edgomez 559
265 : edgomez 1382 /* Total size */
266 :     totalsize += used_bytes;
267 :     }
268 : edgomez 547
269 : edgomez 1382 }while(xvid_dec_stats.type <= 0 && useful_bytes > 0);
270 : edgomez 547
271 : edgomez 1382 /* Check if there is a negative number of useful bytes left in buffer
272 :     * This means we went too far */
273 :     if(useful_bytes < 0)
274 :     break;
275 : edgomez 851
276 : edgomez 1382 /* Updated data - Count only usefull decode time */
277 : edgomez 851 totaldectime += dectime;
278 : edgomez 547
279 : edgomez 851
280 : edgomez 1382 printf("Frame %5d: type = %s, dectime(ms) =%6.1f, length(bytes) =%7d\n",
281 :     filenr, type2str(xvid_dec_stats.type), dectime, used_bytes);
282 :    
283 : edgomez 851 /* Save individual mpeg4 stream if required */
284 : edgomez 1382 if(ARG_SAVEMPEGSTREAM) {
285 : edgomez 547 FILE *filehandle = NULL;
286 :    
287 :     sprintf(filename, "%sframe%05d.m4v", filepath, filenr);
288 :     filehandle = fopen(filename, "wb");
289 :     if(!filehandle) {
290 :     fprintf(stderr,
291 : edgomez 851 "Error writing single mpeg4 stream to file %s\n",
292 :     filename);
293 : edgomez 547 }
294 :     else {
295 : edgomez 1382 fwrite(mp4_ptr-used_bytes, 1, used_bytes, filehandle);
296 : edgomez 547 fclose(filehandle);
297 :     }
298 :     }
299 : edgomez 851
300 : edgomez 547 /* Save output frame if required */
301 :     if (ARG_SAVEDECOUTPUT) {
302 :     sprintf(filename, "%sdec%05d.pgm", filepath, filenr);
303 :     if(write_pgm(filename,out_buffer)) {
304 :     fprintf(stderr,
305 : edgomez 851 "Error writing decoded PGM frame %s\n",
306 :     filename);
307 : edgomez 547 }
308 :     }
309 :    
310 :     filenr++;
311 :    
312 : edgomez 851 } while ( (status>=0) && (filenr<ABS_MAXFRAMENR));
313 : edgomez 547
314 :     /*****************************************************************************
315 : edgomez 851 * Flush decoder buffers
316 :     ****************************************************************************/
317 :    
318 : edgomez 1382 do {
319 :    
320 : edgomez 851 /* Fake vars */
321 : edgomez 1382 int used_bytes;
322 : edgomez 851 double dectime;
323 :    
324 : edgomez 1382 do {
325 :     dectime = msecond();
326 :     used_bytes = dec_main(NULL, out_buffer, -1, &xvid_dec_stats);
327 :     dectime = msecond() - dectime;
328 :     }while(used_bytes>=0 && xvid_dec_stats.type <= 0);
329 : edgomez 851
330 : edgomez 1382 if (used_bytes < 0) { /* XVID_ERR_END */
331 :     break;
332 :     }
333 : edgomez 851
334 :     /* Updated data - Count only usefull decode time */
335 :     totaldectime += dectime;
336 :    
337 :     /* Prints some decoding stats */
338 : edgomez 1382 printf("Frame %5d: type = %s, dectime(ms) =%6.1f, length(bytes) =%7d\n",
339 :     filenr, type2str(xvid_dec_stats.type), dectime, used_bytes);
340 : edgomez 851
341 :     /* Save output frame if required */
342 :     if (ARG_SAVEDECOUTPUT) {
343 :     sprintf(filename, "%sdec%05d.pgm", filepath, filenr);
344 : edgomez 1382 if(write_pgm(filename, out_buffer)) {
345 : edgomez 851 fprintf(stderr,
346 :     "Error writing decoded PGM frame %s\n",
347 :     filename);
348 :     }
349 :     }
350 :    
351 :     filenr++;
352 :    
353 : edgomez 1382 }while(1);
354 : edgomez 851
355 :     /*****************************************************************************
356 : edgomez 547 * Calculate totals and averages for output, print results
357 :     ****************************************************************************/
358 :    
359 :     totalsize /= filenr;
360 :     totaldectime /= filenr;
361 :    
362 : edgomez 851 printf("Avg: dectime(ms) =%7.2f, fps =%7.2f, length(bytes) =%7d\n",
363 : edgomez 1382 totaldectime, 1000/totaldectime, (int)totalsize);
364 : edgomez 547
365 :     /*****************************************************************************
366 :     * XviD PART Stop
367 : edgomez 559 ****************************************************************************/
368 : edgomez 547
369 :     release_all:
370 :     if (dec_handle) {
371 :     status = dec_stop();
372 :     if (status)
373 :     fprintf(stderr, "decore RELEASE problem return value %d\n", status);
374 :     }
375 :    
376 :     free_all_memory:
377 :     free(out_buffer);
378 :     free(mp4_buffer);
379 :    
380 : edgomez 1382 return(0);
381 : chl 376 }
382 :    
383 : edgomez 547 /*****************************************************************************
384 :     * Usage function
385 :     ****************************************************************************/
386 : chl 376
387 : edgomez 547 static void usage()
388 : chl 376 {
389 : edgomez 547
390 : edgomez 1382 fprintf(stderr, "Usage : xvid_decraw [OPTIONS]\n");
391 : edgomez 547 fprintf(stderr, "Options :\n");
392 :     fprintf(stderr, " -asm : use assembly optimizations (default=disabled)\n");
393 :     fprintf(stderr, " -i string : input filename (default=stdin)\n");
394 : edgomez 1382 fprintf(stderr, " -d : save decoder output\n");
395 :     fprintf(stderr, " -m : save mpeg4 raw stream to individual files\n");
396 : edgomez 547 fprintf(stderr, " -help : This help message\n");
397 :     fprintf(stderr, " (* means default)\n");
398 :    
399 :     }
400 :    
401 :     /*****************************************************************************
402 :     * "helper" functions
403 :     ****************************************************************************/
404 :    
405 :     /* return the current time in milli seconds */
406 :     static double
407 :     msecond()
408 :     {
409 : edgomez 824 #ifndef WIN32
410 : edgomez 547 struct timeval tv;
411 :     gettimeofday(&tv, 0);
412 : edgomez 1382 return((double)tv.tv_sec*1.0e3 + (double)tv.tv_usec*1.0e-3);
413 : edgomez 547 #else
414 :     clock_t clk;
415 :     clk = clock();
416 : edgomez 1382 return(clk * 1000 / CLOCKS_PER_SEC);
417 : edgomez 547 #endif
418 :     }
419 :    
420 :     /*****************************************************************************
421 :     * output functions
422 :     ****************************************************************************/
423 :    
424 :     static int
425 :     write_pgm(char *filename,
426 : edgomez 1382 unsigned char *image)
427 : edgomez 547 {
428 :     int loop;
429 :    
430 :     unsigned char *y = image;
431 :     unsigned char *u = image + XDIM*YDIM;
432 :     unsigned char *v = image + XDIM*YDIM + XDIM/2*YDIM/2;
433 :    
434 : chl 376 FILE *filehandle;
435 : edgomez 547 filehandle=fopen(filename,"w+b");
436 :     if (filehandle) {
437 : chl 376
438 : edgomez 547 /* Write header */
439 :     fprintf(filehandle,"P5\n\n%d %d 255\n", XDIM,YDIM*3/2);
440 :    
441 :     /* Write Y data */
442 :     fwrite(y, 1, XDIM*YDIM, filehandle);
443 :    
444 :     for(loop=0; loop<YDIM/2; loop++)
445 :     {
446 :     /* Write U scanline */
447 :     fwrite(u, 1, XDIM/2, filehandle);
448 :    
449 :     /* Write V scanline */
450 :     fwrite(v, 1, XDIM/2, filehandle);
451 :    
452 :     /* Update pointers */
453 :     u += XDIM/2;
454 :     v += XDIM/2;
455 :    
456 :     }
457 :    
458 :     /* Close file */
459 : chl 376 fclose(filehandle);
460 : edgomez 547
461 : edgomez 1382 return(0);
462 : chl 376 }
463 :     else
464 : edgomez 1382 return(1);
465 : chl 376 }
466 :    
467 : edgomez 547 /*****************************************************************************
468 :     * Routines for decoding: init decoder, use, and stop decoder
469 :     ****************************************************************************/
470 : chl 376
471 : edgomez 547 /* init decoder before first run */
472 :     static int
473 :     dec_init(int use_assembler)
474 : chl 376 {
475 : edgomez 1382 int ret;
476 : chl 376
477 : edgomez 1382 xvid_gbl_init_t xvid_gbl_init;
478 :     xvid_dec_create_t xvid_dec_create;
479 : chl 376
480 : edgomez 1382 /*------------------------------------------------------------------------
481 :     * XviD core initialization
482 :     *----------------------------------------------------------------------*/
483 :    
484 :     /* Version */
485 :     xvid_gbl_init.version = XVID_VERSION;
486 :    
487 :     /* Assembly setting */
488 :     if(use_assembler)
489 : suxen_drol 860 #ifdef ARCH_IS_IA64
490 : edgomez 1382 xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_IA64;
491 : chl 376 #else
492 : edgomez 1382 xvid_gbl_init.cpu_flags = 0;
493 : chl 376 #endif
494 : edgomez 1382 else
495 :     xvid_gbl_init.cpu_flags = XVID_CPU_FORCE;
496 : chl 376
497 : edgomez 1382 xvid_global(NULL, 0, &xvid_gbl_init, NULL);
498 : chl 376
499 : edgomez 1382 /*------------------------------------------------------------------------
500 :     * XviD encoder initialization
501 :     *----------------------------------------------------------------------*/
502 : edgomez 851
503 : edgomez 1382 /* Version */
504 :     xvid_dec_create.version = XVID_VERSION;
505 : chl 376
506 : edgomez 1382 /*
507 :     * Image dimensions -- set to 0, xvidcore will resize when ever it is
508 :     * needed
509 :     */
510 :     xvid_dec_create.width = 0;
511 :     xvid_dec_create.height = 0;
512 :    
513 :     ret = xvid_decore(NULL, XVID_DEC_CREATE, &xvid_dec_create, NULL);
514 :    
515 :     dec_handle = xvid_dec_create.handle;
516 :    
517 :     return(ret);
518 : chl 376 }
519 :    
520 : edgomez 547 /* decode one frame */
521 :     static int
522 :     dec_main(unsigned char *istream,
523 : edgomez 851 unsigned char *ostream,
524 :     int istream_size,
525 : edgomez 1382 xvid_dec_stats_t *xvid_dec_stats)
526 : edgomez 547 {
527 : chl 376
528 : edgomez 1382 int ret;
529 : chl 376
530 : edgomez 1382 xvid_dec_frame_t xvid_dec_frame;
531 : chl 376
532 : edgomez 1382 /* Set version */
533 :     xvid_dec_frame.version = XVID_VERSION;
534 :     xvid_dec_stats->version = XVID_VERSION;
535 : chl 376
536 : edgomez 1382 /* No general flags to set */
537 :     xvid_dec_frame.general = 0;
538 : chl 376
539 : edgomez 1382 /* Input stream */
540 :     xvid_dec_frame.bitstream = istream;
541 :     xvid_dec_frame.length = istream_size;
542 : edgomez 851
543 : edgomez 1382 /* Output frame structure */
544 :     xvid_dec_frame.output.plane[0] = ostream;
545 :     xvid_dec_frame.output.stride[0] = XDIM;
546 :     xvid_dec_frame.output.csp = XVID_CSP_I420;
547 :    
548 :     ret = xvid_decore(dec_handle, XVID_DEC_DECODE, &xvid_dec_frame, xvid_dec_stats);
549 :    
550 :     return(ret);
551 : chl 376 }
552 :    
553 : edgomez 547 /* close decoder to release resources */
554 :     static int
555 :     dec_stop()
556 : chl 376 {
557 : edgomez 1382 int ret;
558 : edgomez 547
559 : edgomez 1382 ret = xvid_decore(dec_handle, XVID_DEC_DESTROY, NULL, NULL);
560 : chl 376
561 : edgomez 1382 return(ret);
562 : chl 376 }

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