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

Annotation of /xvidcore/examples/xvid_decraw.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.10 - (view) (download)

1 : edgomez 1.2 /*****************************************************************************
2 : chl 1.1 *
3 : edgomez 1.2 * XVID MPEG-4 VIDEO CODEC
4 :     * - Console based decoding test application -
5 : chl 1.1 *
6 : edgomez 1.6 * Copyright(C) 2002-2003 Christoph Lampert
7 : edgomez 1.10 * 2002-2003 Edouard Gomez <ed.gomez@free.fr>
8 : chl 1.1 *
9 : edgomez 1.2 * 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 1.1 *
14 : edgomez 1.2 * 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 1.1 *
19 : edgomez 1.2 * 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 1.10 * $Id$
24 : edgomez 1.2 *
25 :     ****************************************************************************/
26 : chl 1.1
27 : edgomez 1.2 /*****************************************************************************
28 : chl 1.1 *
29 : edgomez 1.2 * Application notes :
30 : chl 1.1 *
31 : edgomez 1.2 * An MPEG-4 bitstream is read from an input file (or stdin) and decoded,
32 :     * the speed for this is measured.
33 : edgomez 1.10 *
34 :     * The program is plain C and needs no libraries except for libxvidcore,
35 :     * and maths-lib.
36 : chl 1.1 *
37 : edgomez 1.10 * Use ./xvid_decraw -help for a list of options
38 : chl 1.1 *
39 : edgomez 1.2 ****************************************************************************/
40 : chl 1.1
41 :     #include <stdio.h>
42 :     #include <stdlib.h>
43 : edgomez 1.2 #include <string.h>
44 :     #include <math.h>
45 : edgomez 1.5 #ifndef WIN32
46 : edgomez 1.2 #include <sys/time.h>
47 :     #else
48 :     #include <time.h>
49 :     #endif
50 :    
51 :     #include "xvid.h"
52 :    
53 :     /*****************************************************************************
54 :     * Global vars in module and constants
55 :     ****************************************************************************/
56 :    
57 :     /* max number of frames */
58 :     #define ABS_MAXFRAMENR 9999
59 :    
60 :     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 :    
66 :    
67 :     static char filepath[256] = "./";
68 :     static void *dec_handle = NULL;
69 :    
70 : edgomez 1.10 #define BUFFER_SIZE (2*1024*1024)
71 : edgomez 1.2
72 :     /*****************************************************************************
73 :     * Local prototypes
74 :     ****************************************************************************/
75 :    
76 :     static double msecond();
77 :     static int write_pgm(char *filename,
78 : edgomez 1.10 unsigned char *image);
79 : edgomez 1.2 static int dec_init(int use_assembler);
80 :     static int dec_main(unsigned char *istream,
81 : edgomez 1.6 unsigned char *ostream,
82 :     int istream_size,
83 : edgomez 1.10 xvid_dec_stats_t *xvid_dec_stats);
84 : edgomez 1.2 static int dec_stop();
85 :     static void usage();
86 :    
87 : edgomez 1.10
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 1.2 /*****************************************************************************
100 :     * Main program
101 :     ****************************************************************************/
102 :    
103 :     int main(int argc, char *argv[])
104 :     {
105 :     unsigned char *mp4_buffer = NULL;
106 :     unsigned char *mp4_ptr = NULL;
107 :     unsigned char *out_buffer = NULL;
108 : edgomez 1.10 int useful_bytes;
109 :     xvid_dec_stats_t xvid_dec_stats;
110 : edgomez 1.6
111 : edgomez 1.2 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 1.6 printf("written by Christoph Lampert 2002-2003\n\n");
126 : edgomez 1.2
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 1.10 } else if (strcmp("-d", argv[i]) == 0) {
136 :     ARG_SAVEDECOUTPUT = 1;
137 :     } else if (strcmp("-i", argv[i]) == 0 && i < argc - 1 ) {
138 : edgomez 1.2 i++;
139 :     ARG_INPUTFILE = argv[i];
140 : edgomez 1.10 } else if (strcmp("-m", argv[i]) == 0) {
141 :     ARG_SAVEMPEGSTREAM = 1;
142 :     } else if (strcmp("-help", argv[i]) == 0) {
143 : edgomez 1.2 usage();
144 :     return(0);
145 : edgomez 1.10 } else {
146 : edgomez 1.2 usage();
147 :     exit(-1);
148 :     }
149 :     }
150 :    
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 1.10 return(-1);
164 : edgomez 1.2 }
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 : chl 1.1
181 : edgomez 1.2 status = dec_init(use_assembler);
182 :     if (status) {
183 :     fprintf(stderr,
184 : edgomez 1.10 "Decore INIT problem, return value %d\n", status);
185 : edgomez 1.2 goto release_all;
186 :     }
187 :    
188 :    
189 :     /*****************************************************************************
190 :     * Main loop
191 :     ****************************************************************************/
192 :    
193 : edgomez 1.6 /* Fill the buffer */
194 : edgomez 1.10 useful_bytes = fread(mp4_buffer, 1, BUFFER_SIZE, in_file);
195 : edgomez 1.2
196 :     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 1.6 /*
206 :     * If the buffer is half empty or there are no more bytes in it
207 :     * then fill it.
208 :     */
209 : edgomez 1.10 if (mp4_ptr > mp4_buffer + BUFFER_SIZE/2) {
210 :     int already_in_buffer = (mp4_buffer + BUFFER_SIZE - mp4_ptr);
211 : edgomez 1.6
212 :     /* Move data if needed */
213 : edgomez 1.10 if (already_in_buffer > 0)
214 :     memcpy(mp4_buffer, mp4_ptr, already_in_buffer);
215 : edgomez 1.2
216 : edgomez 1.6 /* Update mp4_ptr */
217 :     mp4_ptr = mp4_buffer;
218 : edgomez 1.2
219 : edgomez 1.6 /* read new data */
220 : edgomez 1.10 if(feof(in_file))
221 : edgomez 1.2 break;
222 :    
223 : edgomez 1.10 useful_bytes += fread(mp4_buffer + already_in_buffer,
224 :     1, BUFFER_SIZE - already_in_buffer,
225 :     in_file);
226 : edgomez 1.2
227 : edgomez 1.6 }
228 : edgomez 1.2
229 :    
230 : edgomez 1.10 /* This loop is needed to handle VOL/NVOP reading */
231 : edgomez 1.6 do {
232 : edgomez 1.2
233 : edgomez 1.6 /* Decode frame */
234 :     dectime = msecond();
235 : edgomez 1.10 used_bytes = dec_main(mp4_ptr, out_buffer, useful_bytes, &xvid_dec_stats);
236 : edgomez 1.6 dectime = msecond() - dectime;
237 : edgomez 1.2
238 : edgomez 1.10 /* 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 1.6 }
259 : edgomez 1.4
260 : edgomez 1.6 /* Update buffer pointers */
261 : edgomez 1.10 if(used_bytes > 0) {
262 :     mp4_ptr += used_bytes;
263 :     useful_bytes -= used_bytes;
264 : edgomez 1.2
265 : edgomez 1.10 /* Total size */
266 :     totalsize += used_bytes;
267 :     }
268 : edgomez 1.2
269 : edgomez 1.10 }while(xvid_dec_stats.type <= 0 && useful_bytes > 0);
270 : edgomez 1.2
271 : edgomez 1.10 /* 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 1.6
276 : edgomez 1.10 /* Updated data - Count only usefull decode time */
277 : edgomez 1.6 totaldectime += dectime;
278 : edgomez 1.2
279 : edgomez 1.10
280 :     printf("Frame %5d: type = %s, dectime(ms) =%6.1f, length(bytes) =%7d\n",
281 :     filenr, type2str(xvid_dec_stats.type), dectime, used_bytes);
282 : edgomez 1.6
283 :     /* Save individual mpeg4 stream if required */
284 : edgomez 1.10 if(ARG_SAVEMPEGSTREAM) {
285 : edgomez 1.2 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 1.6 "Error writing single mpeg4 stream to file %s\n",
292 :     filename);
293 : edgomez 1.2 }
294 :     else {
295 : edgomez 1.10 fwrite(mp4_ptr-used_bytes, 1, used_bytes, filehandle);
296 : edgomez 1.2 fclose(filehandle);
297 :     }
298 :     }
299 : edgomez 1.6
300 : edgomez 1.2 /* 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 1.6 "Error writing decoded PGM frame %s\n",
306 :     filename);
307 : edgomez 1.2 }
308 :     }
309 :    
310 :     filenr++;
311 :    
312 : edgomez 1.6 } while ( (status>=0) && (filenr<ABS_MAXFRAMENR));
313 :    
314 :     /*****************************************************************************
315 :     * Flush decoder buffers
316 :     ****************************************************************************/
317 : edgomez 1.10
318 :     do {
319 : edgomez 1.6
320 :     /* Fake vars */
321 : edgomez 1.10 int used_bytes;
322 : edgomez 1.6 double dectime;
323 :    
324 : edgomez 1.10 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 :    
330 :     if (used_bytes < 0) { /* XVID_ERR_END */
331 :     break;
332 :     }
333 : edgomez 1.6
334 :     /* Updated data - Count only usefull decode time */
335 :     totaldectime += dectime;
336 : edgomez 1.2
337 : edgomez 1.6 /* Prints some decoding stats */
338 : edgomez 1.10 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 1.6
341 :     /* Save output frame if required */
342 :     if (ARG_SAVEDECOUTPUT) {
343 :     sprintf(filename, "%sdec%05d.pgm", filepath, filenr);
344 : edgomez 1.10 if(write_pgm(filename, out_buffer)) {
345 : edgomez 1.6 fprintf(stderr,
346 :     "Error writing decoded PGM frame %s\n",
347 :     filename);
348 :     }
349 :     }
350 :    
351 :     filenr++;
352 :    
353 : edgomez 1.10 }while(1);
354 : edgomez 1.6
355 : edgomez 1.2 /*****************************************************************************
356 :     * Calculate totals and averages for output, print results
357 :     ****************************************************************************/
358 : chl 1.1
359 : edgomez 1.2 totalsize /= filenr;
360 :     totaldectime /= filenr;
361 :    
362 : edgomez 1.6 printf("Avg: dectime(ms) =%7.2f, fps =%7.2f, length(bytes) =%7d\n",
363 : edgomez 1.10 totaldectime, 1000/totaldectime, (int)totalsize);
364 : edgomez 1.2
365 :     /*****************************************************************************
366 :     * XviD PART Stop
367 : edgomez 1.4 ****************************************************************************/
368 : chl 1.1
369 : edgomez 1.2 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 : chl 1.1
376 : edgomez 1.2 free_all_memory:
377 :     free(out_buffer);
378 :     free(mp4_buffer);
379 : chl 1.1
380 : edgomez 1.10 return(0);
381 : edgomez 1.2 }
382 : chl 1.1
383 : edgomez 1.2 /*****************************************************************************
384 :     * Usage function
385 :     ****************************************************************************/
386 : chl 1.1
387 : edgomez 1.2 static void usage()
388 :     {
389 :    
390 : edgomez 1.10 fprintf(stderr, "Usage : xvid_decraw [OPTIONS]\n");
391 : edgomez 1.2 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 1.10 fprintf(stderr, " -d : save decoder output\n");
395 :     fprintf(stderr, " -m : save mpeg4 raw stream to individual files\n");
396 : edgomez 1.2 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 : chl 1.1 {
409 : edgomez 1.5 #ifndef WIN32
410 : chl 1.1 struct timeval tv;
411 :     gettimeofday(&tv, 0);
412 : edgomez 1.10 return((double)tv.tv_sec*1.0e3 + (double)tv.tv_usec*1.0e-3);
413 : edgomez 1.2 #else
414 :     clock_t clk;
415 :     clk = clock();
416 : edgomez 1.10 return(clk * 1000 / CLOCKS_PER_SEC);
417 : edgomez 1.2 #endif
418 : chl 1.1 }
419 :    
420 : edgomez 1.2 /*****************************************************************************
421 :     * output functions
422 :     ****************************************************************************/
423 :    
424 :     static int
425 :     write_pgm(char *filename,
426 : edgomez 1.10 unsigned char *image)
427 : edgomez 1.2 {
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 : chl 1.1
434 :     FILE *filehandle;
435 : edgomez 1.2 filehandle=fopen(filename,"w+b");
436 :     if (filehandle) {
437 :    
438 :     /* Write header */
439 :     fprintf(filehandle,"P5\n\n%d %d 255\n", XDIM,YDIM*3/2);
440 : chl 1.1
441 : edgomez 1.2 /* Write Y data */
442 :     fwrite(y, 1, XDIM*YDIM, filehandle);
443 : chl 1.1
444 : edgomez 1.2 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 : chl 1.1
456 : edgomez 1.2 }
457 : chl 1.1
458 : edgomez 1.2 /* Close file */
459 : chl 1.1 fclose(filehandle);
460 : edgomez 1.2
461 : edgomez 1.10 return(0);
462 : chl 1.1 }
463 :     else
464 : edgomez 1.10 return(1);
465 : chl 1.1 }
466 :    
467 : edgomez 1.2 /*****************************************************************************
468 :     * Routines for decoding: init decoder, use, and stop decoder
469 :     ****************************************************************************/
470 :    
471 :     /* init decoder before first run */
472 :     static int
473 :     dec_init(int use_assembler)
474 : chl 1.1 {
475 : edgomez 1.10 int ret;
476 :    
477 :     xvid_gbl_init_t xvid_gbl_init;
478 :     xvid_dec_create_t xvid_dec_create;
479 :    
480 :     /*------------------------------------------------------------------------
481 :     * XviD core initialization
482 :     *----------------------------------------------------------------------*/
483 : chl 1.1
484 : edgomez 1.10 /* Version */
485 :     xvid_gbl_init.version = XVID_VERSION;
486 : chl 1.1
487 : edgomez 1.10 /* Assembly setting */
488 :     if(use_assembler)
489 : suxen_drol 1.7 #ifdef ARCH_IS_IA64
490 : edgomez 1.10 xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_IA64;
491 : chl 1.1 #else
492 : edgomez 1.10 xvid_gbl_init.cpu_flags = 0;
493 : chl 1.1 #endif
494 : edgomez 1.10 else
495 :     xvid_gbl_init.cpu_flags = XVID_CPU_FORCE;
496 :    
497 :     xvid_global(NULL, 0, &xvid_gbl_init, NULL);
498 :    
499 :     /*------------------------------------------------------------------------
500 :     * XviD encoder initialization
501 :     *----------------------------------------------------------------------*/
502 : chl 1.1
503 : edgomez 1.10 /* Version */
504 :     xvid_dec_create.version = XVID_VERSION;
505 : chl 1.1
506 : edgomez 1.10 /*
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 : edgomez 1.6
513 : edgomez 1.10 ret = xvid_decore(NULL, XVID_DEC_CREATE, &xvid_dec_create, NULL);
514 : chl 1.1
515 : edgomez 1.10 dec_handle = xvid_dec_create.handle;
516 :    
517 :     return(ret);
518 : chl 1.1 }
519 :    
520 : edgomez 1.2 /* decode one frame */
521 :     static int
522 :     dec_main(unsigned char *istream,
523 : edgomez 1.6 unsigned char *ostream,
524 :     int istream_size,
525 : edgomez 1.10 xvid_dec_stats_t *xvid_dec_stats)
526 : edgomez 1.2 {
527 : chl 1.1
528 : edgomez 1.10 int ret;
529 :    
530 :     xvid_dec_frame_t xvid_dec_frame;
531 :    
532 :     /* Set version */
533 :     xvid_dec_frame.version = XVID_VERSION;
534 :     xvid_dec_stats->version = XVID_VERSION;
535 : edgomez 1.6
536 : edgomez 1.10 /* No general flags to set */
537 :     xvid_dec_frame.general = 0;
538 : chl 1.1
539 : edgomez 1.10 /* Input stream */
540 :     xvid_dec_frame.bitstream = istream;
541 :     xvid_dec_frame.length = istream_size;
542 : chl 1.1
543 : edgomez 1.10 /* 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 : chl 1.1
548 : edgomez 1.10 ret = xvid_decore(dec_handle, XVID_DEC_DECODE, &xvid_dec_frame, xvid_dec_stats);
549 : chl 1.1
550 : edgomez 1.10 return(ret);
551 : chl 1.1 }
552 :    
553 : edgomez 1.2 /* close decoder to release resources */
554 :     static int
555 :     dec_stop()
556 : chl 1.1 {
557 : edgomez 1.10 int ret;
558 : edgomez 1.2
559 : edgomez 1.10 ret = xvid_decore(dec_handle, XVID_DEC_DESTROY, NULL, NULL);
560 : chl 1.1
561 : edgomez 1.10 return(ret);
562 : chl 1.1 }

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