--- trunk/xvidcore/examples/xvid_decraw.c 2004/03/22 22:36:25 1382 +++ trunk/xvidcore/examples/xvid_decraw.c 2005/11/25 12:07:01 1658 @@ -20,7 +20,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: xvid_decraw.c,v 1.10 2004-03-22 22:36:23 edgomez Exp $ + * $Id: xvid_decraw.c,v 1.23 2005-11-25 12:07:01 chl Exp $ * ****************************************************************************/ @@ -54,36 +54,42 @@ * Global vars in module and constants ****************************************************************************/ -/* max number of frames */ -#define ABS_MAXFRAMENR 9999 +#define USE_PNM 0 +#define USE_TGA 1 static int XDIM = 0; static int YDIM = 0; static int ARG_SAVEDECOUTPUT = 0; static int ARG_SAVEMPEGSTREAM = 0; static char *ARG_INPUTFILE = NULL; - +static int CSP = XVID_CSP_I420; +static int BPP = 1; +static int FORMAT = USE_PNM; static char filepath[256] = "./"; static void *dec_handle = NULL; #define BUFFER_SIZE (2*1024*1024) +static const int display_buffer_bytes = 0; + +#define MIN_USEFUL_BYTES 1 + /***************************************************************************** * Local prototypes ****************************************************************************/ static double msecond(); -static int write_pgm(char *filename, - unsigned char *image); -static int dec_init(int use_assembler); +static int dec_init(int use_assembler, int debug_level); static int dec_main(unsigned char *istream, unsigned char *ostream, int istream_size, xvid_dec_stats_t *xvid_dec_stats); static int dec_stop(); static void usage(); - +static int write_image(char *prefix, unsigned char *image); +static int write_pnm(char *filename, unsigned char *image); +static int write_tga(char *filename, unsigned char *image); const char * type2str(int type) { @@ -106,6 +112,7 @@ unsigned char *mp4_ptr = NULL; unsigned char *out_buffer = NULL; int useful_bytes; + int chunk; xvid_dec_stats_t xvid_dec_stats; double totaldectime; @@ -114,6 +121,7 @@ int status; int use_assembler = 0; + int debug_level = 0; char filename[256]; @@ -132,6 +140,11 @@ if (strcmp("-asm", argv[i]) == 0 ) { use_assembler = 1; + } else if (strcmp("-debug", argv[i]) == 0 && i < argc - 1 ) { + i++; + if (sscanf(argv[i], "0x%x", &debug_level) != 1) { + debug_level = atoi(argv[i]); + } } else if (strcmp("-d", argv[i]) == 0) { ARG_SAVEDECOUTPUT = 1; } else if (strcmp("-i", argv[i]) == 0 && i < argc - 1 ) { @@ -139,6 +152,31 @@ ARG_INPUTFILE = argv[i]; } else if (strcmp("-m", argv[i]) == 0) { ARG_SAVEMPEGSTREAM = 1; + } else if (strcmp("-c", argv[i]) == 0 && i < argc - 1 ) { + i++; + if (strcmp(argv[i], "rgb16") == 0) { + CSP = XVID_CSP_RGB555; + BPP = 2; + } else if (strcmp(argv[i], "rgb24") == 0) { + CSP = XVID_CSP_BGR; + BPP = 3; + } else if (strcmp(argv[i], "rgb32") == 0) { + CSP = XVID_CSP_BGRA; + BPP = 4; + } else if (strcmp(argv[i], "yv12") == 0) { + CSP = XVID_CSP_YV12; + BPP = 1; + } else { + CSP = XVID_CSP_I420; + BPP = 1; + } + } else if (strcmp("-f", argv[i]) == 0 && i < argc -1) { + i++; + if (strcmp(argv[i], "tga") == 0) { + FORMAT = USE_TGA; + } else { + FORMAT = USE_PNM; + } } else if (strcmp("-help", argv[i]) == 0) { usage(); return(0); @@ -148,6 +186,12 @@ } } +#if defined(_MSC_VER) + if (ARG_INPUTFILE==NULL) { + fprintf(stderr, "Warning: MSVC build does not read EOF correctly from stdin. Use the -i switch.\n\n"); + } +#endif + /***************************************************************************** * Values checking ****************************************************************************/ @@ -164,6 +208,11 @@ } } + /* PNM/PGM format can't handle 16/32 bit data */ + if (BPP != 1 && BPP != 3 && FORMAT == USE_PNM) { + FORMAT = USE_TGA; + } + /***************************************************************************** * Memory allocation ****************************************************************************/ @@ -178,7 +227,7 @@ * XviD PART Start ****************************************************************************/ - status = dec_init(use_assembler); + status = dec_init(use_assembler, debug_level); if (status) { fprintf(stderr, "Decore INIT problem, return value %d\n", status); @@ -197,7 +246,8 @@ totalsize = 0; filenr = 0; mp4_ptr = mp4_buffer; - + chunk = 0; + do { int used_bytes = 0; double dectime; @@ -255,6 +305,22 @@ fprintf(stderr, "Resized frame buffer to %dx%d\n", XDIM, YDIM); } + + /* Save individual mpeg4 stream if required */ + if(ARG_SAVEMPEGSTREAM) { + FILE *filehandle = NULL; + + sprintf(filename, "%svolhdr.m4v", filepath); + filehandle = fopen(filename, "wb"); + if(!filehandle) { + fprintf(stderr, + "Error writing vol header mpeg4 stream to file %s\n", + filename); + } else { + fwrite(mp4_ptr, 1, used_bytes, filehandle); + fclose(filehandle); + } + } } /* Update buffer pointers */ @@ -266,7 +332,10 @@ totalsize += used_bytes; } - }while(xvid_dec_stats.type <= 0 && useful_bytes > 0); + if (display_buffer_bytes) { + printf("Data chunk %d: %d bytes consumed, %d bytes in buffer\n", chunk++, used_bytes, useful_bytes); + } + } while (xvid_dec_stats.type <= 0 && useful_bytes > MIN_USEFUL_BYTES); /* Check if there is a negative number of useful bytes left in buffer * This means we went too far */ @@ -277,9 +346,11 @@ totaldectime += dectime; - printf("Frame %5d: type = %s, dectime(ms) =%6.1f, length(bytes) =%7d\n", - filenr, type2str(xvid_dec_stats.type), dectime, used_bytes); - + if (!display_buffer_bytes) { + printf("Frame %5d: type = %s, dectime(ms) =%6.1f, length(bytes) =%7d\n", + filenr, type2str(xvid_dec_stats.type), dectime, used_bytes); + } + /* Save individual mpeg4 stream if required */ if(ARG_SAVEMPEGSTREAM) { FILE *filehandle = NULL; @@ -299,17 +370,19 @@ /* Save output frame if required */ if (ARG_SAVEDECOUTPUT) { - sprintf(filename, "%sdec%05d.pgm", filepath, filenr); - if(write_pgm(filename,out_buffer)) { + sprintf(filename, "%sdec%05d", filepath, filenr); + if(write_image(filename, out_buffer)) { fprintf(stderr, - "Error writing decoded PGM frame %s\n", + "Error writing decoded frame %s\n", filename); } } filenr++; - } while ( (status>=0) && (filenrMIN_USEFUL_BYTES || !feof(in_file)); + + useful_bytes = 0; /* Empty buffer */ /***************************************************************************** * Flush decoder buffers @@ -325,7 +398,10 @@ dectime = msecond(); used_bytes = dec_main(NULL, out_buffer, -1, &xvid_dec_stats); dectime = msecond() - dectime; - }while(used_bytes>=0 && xvid_dec_stats.type <= 0); + if (display_buffer_bytes) { + printf("Data chunk %d: %d bytes consumed, %d bytes in buffer\n", chunk++, used_bytes, useful_bytes); + } + } while(used_bytes>=0 && xvid_dec_stats.type <= 0); if (used_bytes < 0) { /* XVID_ERR_END */ break; @@ -335,15 +411,17 @@ totaldectime += dectime; /* Prints some decoding stats */ - printf("Frame %5d: type = %s, dectime(ms) =%6.1f, length(bytes) =%7d\n", - filenr, type2str(xvid_dec_stats.type), dectime, used_bytes); - + if (!display_buffer_bytes) { + printf("Frame %5d: type = %s, dectime(ms) =%6.1f, length(bytes) =%7d\n", + filenr, type2str(xvid_dec_stats.type), dectime, used_bytes); + } + /* Save output frame if required */ if (ARG_SAVEDECOUTPUT) { - sprintf(filename, "%sdec%05d.pgm", filepath, filenr); - if(write_pgm(filename, out_buffer)) { + sprintf(filename, "%sdec%05d", filepath, filenr); + if(write_image(filename, out_buffer)) { fprintf(stderr, - "Error writing decoded PGM frame %s\n", + "Error writing decoded frame %s\n", filename); } } @@ -356,11 +434,14 @@ * Calculate totals and averages for output, print results ****************************************************************************/ - totalsize /= filenr; - totaldectime /= filenr; - - printf("Avg: dectime(ms) =%7.2f, fps =%7.2f, length(bytes) =%7d\n", - totaldectime, 1000/totaldectime, (int)totalsize); + if (filenr>0) { + totalsize /= filenr; + totaldectime /= filenr; + printf("Avg: dectime(ms) =%7.2f, fps =%7.2f, length(bytes) =%7d\n", + totaldectime, 1000/totaldectime, (int)totalsize); + }else{ + printf("Nothing was decoded!\n"); + } /***************************************************************************** * XviD PART Stop @@ -390,8 +471,11 @@ fprintf(stderr, "Usage : xvid_decraw [OPTIONS]\n"); fprintf(stderr, "Options :\n"); fprintf(stderr, " -asm : use assembly optimizations (default=disabled)\n"); + fprintf(stderr, " -debug : debug level (debug=0)\n"); fprintf(stderr, " -i string : input filename (default=stdin)\n"); fprintf(stderr, " -d : save decoder output\n"); + fprintf(stderr, " -c csp : choose colorspace output (rgb16, rgb24, rgb32, yv12, i420)\n"); + fprintf(stderr, " -f format : choose output file format (tga, pnm, pgm)\n"); fprintf(stderr, " -m : save mpeg4 raw stream to individual files\n"); fprintf(stderr, " -help : This help message\n"); fprintf(stderr, " (* means default)\n"); @@ -413,7 +497,7 @@ #else clock_t clk; clk = clock(); - return(clk * 1000 / CLOCKS_PER_SEC); + return(clk * 1000.0 / CLOCKS_PER_SEC); #endif } @@ -421,47 +505,153 @@ * output functions ****************************************************************************/ -static int -write_pgm(char *filename, - unsigned char *image) +static int write_image(char *prefix, unsigned char *image) { - int loop; + char filename[1024]; + char *ext; + int ret; - unsigned char *y = image; - unsigned char *u = image + XDIM*YDIM; - unsigned char *v = image + XDIM*YDIM + XDIM/2*YDIM/2; + if (FORMAT == USE_PNM && BPP == 1) { + ext = "pgm"; + } else if (FORMAT == USE_PNM && BPP == 3) { + ext = "pnm"; + } else if (FORMAT == USE_TGA) { + ext = "tga"; + } else { + fprintf(stderr, "Bug: should not reach this path code -- please report to xvid-devel@xvid.org with command line options used"); + exit(-1); + } - FILE *filehandle; - filehandle=fopen(filename,"w+b"); - if (filehandle) { + sprintf(filename, "%s.%s", prefix, ext); - /* Write header */ - fprintf(filehandle,"P5\n\n%d %d 255\n", XDIM,YDIM*3/2); + if (FORMAT == USE_PNM) { + ret = write_pnm(filename, image); + } else { + ret = write_tga(filename, image); + } + + return(ret); +} - /* Write Y data */ - fwrite(y, 1, XDIM*YDIM, filehandle); +static int write_tga(char *filename, unsigned char *image) +{ + FILE * f; + char hdr[18]; - for(loop=0; loop1)?2:3; /* Uncompressed true color (2) or greymap (3) */ + hdr[3] = 0; /* Color map specification (not used) */ + hdr[4] = 0; /* Color map specification (not used) */ + hdr[5] = 0; /* Color map specification (not used) */ + hdr[6] = 0; /* Color map specification (not used) */ + hdr[7] = 0; /* Color map specification (not used) */ + hdr[8] = 0; /* LSB X origin */ + hdr[9] = 0; /* MSB X origin */ + hdr[10] = 0; /* LSB Y origin */ + hdr[11] = 0; /* MSB Y origin */ + hdr[12] = (XDIM>>0)&0xff; /* LSB Width */ + hdr[13] = (XDIM>>8)&0xff; /* MSB Width */ + if (BPP > 1) { + hdr[14] = (YDIM>>0)&0xff; /* LSB Height */ + hdr[15] = (YDIM>>8)&0xff; /* MSB Height */ + } else { + hdr[14] = ((YDIM*3)>>1)&0xff; /* LSB Height */ + hdr[15] = ((YDIM*3)>>9)&0xff; /* MSB Height */ + } + hdr[16] = BPP*8; + hdr[17] = 0x00 | (1<<5) /* Up to down */ | (0<<4); /* Image descriptor */ + + /* Write header */ + fwrite(hdr, 1, sizeof(hdr), f); - /* Update pointers */ - u += XDIM/2; - v += XDIM/2; +#ifdef ARCH_IS_LITTLE_ENDIAN + /* write first plane */ + fwrite(image, 1, XDIM*YDIM*BPP, f); +#else + { + int i; + for (i=0; iversion = XVID_VERSION; @@ -542,8 +742,8 @@ /* Output frame structure */ xvid_dec_frame.output.plane[0] = ostream; - xvid_dec_frame.output.stride[0] = XDIM; - xvid_dec_frame.output.csp = XVID_CSP_I420; + xvid_dec_frame.output.stride[0] = XDIM*BPP; + xvid_dec_frame.output.csp = CSP; ret = xvid_decore(dec_handle, XVID_DEC_DECODE, &xvid_dec_frame, xvid_dec_stats);