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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 783 - (view) (download)

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

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