--- trunk/xvidcore/examples/xvid_decraw.c 2002/09/28 14:27:16 559 +++ trunk/xvidcore/examples/xvid_decraw.c 2004/04/10 04:25:31 1416 @@ -3,7 +3,8 @@ * XVID MPEG-4 VIDEO CODEC * - Console based decoding test application - * - * Copyright(C) 2002 Christoph Lampert + * Copyright(C) 2002-2003 Christoph Lampert + * 2002-2003 Edouard Gomez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,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.4 2002-09-28 14:27:16 edgomez Exp $ + * $Id: xvid_decraw.c,v 1.11 2004-04-10 04:25:31 suxen_drol Exp $ * ****************************************************************************/ @@ -29,26 +30,11 @@ * * An MPEG-4 bitstream is read from an input file (or stdin) and decoded, * the speed for this is measured. - * - * The program is plain C and needs no libraries except for libxvidcore, - * and maths-lib, so with UN*X you simply compile by - * - * gcc xvid_decraw.c -lxvidcore -lm -o xvid_decraw * - * You have to specify the image dimensions (until the add the feature - * to read this from the bitstream) - * - * Usage : xvid_decraw <-w width> <-h height> [OPTIONS] - * Options : - * -asm : use assembly optimizations (default=disabled) - * -w integer : frame width ([1.2048]) - * -h integer : frame height ([1.2048]) - * -i string : input filename (default=stdin) - * -t integer : input data type (raw=0, mp4u=1) - * -d boolean : save decoder output (0 False*, !=0 True) - * -m boolean : save mpeg4 raw stream to single files (0 False*, !=0 True) - * -help : This help message - * (* means default) + * The program is plain C and needs no libraries except for libxvidcore, + * and maths-lib. + * + * Use ./xvid_decraw -help for a list of options * ****************************************************************************/ @@ -56,7 +42,7 @@ #include #include #include -#ifndef _MSC_VER +#ifndef WIN32 #include #else #include @@ -75,20 +61,13 @@ static int YDIM = 0; static int ARG_SAVEDECOUTPUT = 0; static int ARG_SAVEMPEGSTREAM = 0; -static int ARG_STREAMTYPE = 0; static char *ARG_INPUTFILE = NULL; static char filepath[256] = "./"; static void *dec_handle = NULL; -# define BUFFER_SIZE 10*XDIM*YDIM - -#define LONG_PACK(a,b,c,d) ((long) (((long)(a))<<24) | (((long)(b))<<16) | \ - (((long)(c))<<8) |((long)(d))) - -#define SWAP(a) ( (((a)&0x000000ff)<<24) | (((a)&0x0000ff00)<<8) | \ - (((a)&0x00ff0000)>>8) | (((a)&0xff000000)>>24) ) +#define BUFFER_SIZE (2*1024*1024) /***************************************************************************** * Local prototypes @@ -96,15 +75,27 @@ static double msecond(); static int write_pgm(char *filename, - unsigned char *image); -static int dec_init(int use_assembler); + unsigned char *image); +static int dec_init(int use_assembler, int debug_level); static int dec_main(unsigned char *istream, - unsigned char *ostream, - int istream_size, - int *ostream_size); + unsigned char *ostream, + int istream_size, + xvid_dec_stats_t *xvid_dec_stats); static int dec_stop(); static void usage(); + +const char * type2str(int type) +{ + if (type==XVID_TYPE_IVOP) + return "I"; + if (type==XVID_TYPE_PVOP) + return "P"; + if (type==XVID_TYPE_BVOP) + return "B"; + return "S"; +} + /***************************************************************************** * Main program ****************************************************************************/ @@ -114,14 +105,16 @@ unsigned char *mp4_buffer = NULL; unsigned char *mp4_ptr = NULL; unsigned char *out_buffer = NULL; - int bigendian = 0; - + int useful_bytes; + xvid_dec_stats_t xvid_dec_stats; + double totaldectime; long totalsize; int status; int use_assembler = 0; + int debug_level = 0; char filename[256]; @@ -130,7 +123,7 @@ int i; printf("xvid_decraw - raw mpeg4 bitstream decoder "); - printf("written by Christoph Lampert 2002\n\n"); + printf("written by Christoph Lampert 2002-2003\n\n"); /***************************************************************************** * Command line parsing @@ -140,51 +133,31 @@ if (strcmp("-asm", argv[i]) == 0 ) { use_assembler = 1; - } - else if (strcmp("-w", argv[i]) == 0 && i < argc - 1 ) { + } else if (strcmp("-debug", argv[i]) == 0 && i < argc - 1 ) { i++; - XDIM = atoi(argv[i]); - } - else if (strcmp("-h", argv[i]) == 0 && i < argc - 1 ) { - i++; - YDIM = atoi(argv[i]); - } - else if (strcmp("-d", argv[i]) == 0 && i < argc - 1 ) { - i++; - ARG_SAVEDECOUTPUT = atoi(argv[i]); - } - else if (strcmp("-i", argv[i]) == 0 && i < argc - 1 ) { + 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 ) { i++; ARG_INPUTFILE = argv[i]; - } - else if (strcmp("-m", argv[i]) == 0 && i < argc - 1 ) { - i++; - ARG_SAVEMPEGSTREAM = atoi(argv[i]); - } - else if (strcmp("-t", argv[i]) == 0 && i < argc - 1 ) { - i++; - ARG_STREAMTYPE = atoi(argv[i]); - } - else if (strcmp("-help", argv[i])) { + } else if (strcmp("-m", argv[i]) == 0) { + ARG_SAVEMPEGSTREAM = 1; + } else if (strcmp("-help", argv[i]) == 0) { usage(); return(0); - } - else { + } else { usage(); exit(-1); } - } /***************************************************************************** * Values checking ****************************************************************************/ - if(XDIM <= 0 || XDIM > 2048 || YDIM <= 0 || YDIM > 2048) { - usage(); - return -1; - } - if ( ARG_INPUTFILE == NULL || strcmp(ARG_INPUTFILE, "stdin") == 0) { in_file = stdin; } @@ -193,7 +166,7 @@ in_file = fopen(ARG_INPUTFILE, "rb"); if (in_file == NULL) { fprintf(stderr, "Error opening input file %s\n", ARG_INPUTFILE); - return -1; + return(-1); } } @@ -207,20 +180,14 @@ if (!mp4_buffer) goto free_all_memory; - /* Memory for frame output */ - out_buffer = (unsigned char *) malloc(XDIM*YDIM*4); - if (!out_buffer) - goto free_all_memory; - - /***************************************************************************** * 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); + "Decore INIT problem, return value %d\n", status); goto release_all; } @@ -229,32 +196,8 @@ * Main loop ****************************************************************************/ - totalsize = LONG_PACK('M','P','4','U'); - mp4_ptr = (unsigned char *)&totalsize; - if(*mp4_ptr == 'M') - bigendian = 1; - else - bigendian = 0; - - if(ARG_STREAMTYPE) { - - unsigned char header[4]; - - /* MP4U format : read header */ - if(feof(in_file)) - goto release_all; - fread(header, 4, 1, in_file); - - if(header[0] != 'M' || header[1] != 'P' || - header[2] != '4' || header[3] != 'U') { - fprintf(stderr, "Error, this not a mp4u container file\n"); - goto release_all; - } - - } - else { - fread(mp4_buffer, BUFFER_SIZE, 1, in_file); - } + /* Fill the buffer */ + useful_bytes = fread(mp4_buffer, 1, BUFFER_SIZE, in_file); totaldectime = 0; totalsize = 0; @@ -262,118 +205,159 @@ mp4_ptr = mp4_buffer; do { - - int mp4_size = (mp4_buffer + BUFFER_SIZE - mp4_ptr); int used_bytes = 0; double dectime; - /* Read data from input file */ - if(ARG_STREAMTYPE) { - - /* MP4U container */ + /* + * If the buffer is half empty or there are no more bytes in it + * then fill it. + */ + if (mp4_ptr > mp4_buffer + BUFFER_SIZE/2) { + int already_in_buffer = (mp4_buffer + BUFFER_SIZE - mp4_ptr); - /* Read stream size first */ - if(feof(in_file)) - break; - fread(&mp4_size, sizeof(long), 1, in_file); + /* Move data if needed */ + if (already_in_buffer > 0) + memcpy(mp4_buffer, mp4_ptr, already_in_buffer); - /* Mp4U container is big endian */ - if(!bigendian) - mp4_size = SWAP(mp4_size); + /* Update mp4_ptr */ + mp4_ptr = mp4_buffer; - /* Read mp4_size_bytes */ - if(feof(in_file)) + /* read new data */ + if(feof(in_file)) break; - fread(mp4_buffer, mp4_size, 1, in_file); - /* - * When reading mp4u, we don't have to care about buffer - * filling as we know exactly how much bytes there are in - * next frame - */ - mp4_ptr = mp4_buffer; + useful_bytes += fread(mp4_buffer + already_in_buffer, + 1, BUFFER_SIZE - already_in_buffer, + in_file); } - else { - /* Real raw stream */ - /* buffer more than half empty -> Fill it */ - if (mp4_ptr > mp4_buffer + BUFFER_SIZE/2) { - int rest = (mp4_buffer + BUFFER_SIZE - mp4_ptr); + /* This loop is needed to handle VOL/NVOP reading */ + do { - /* Move data if needed */ - if (rest) - memcpy(mp4_buffer, mp4_ptr, rest); + /* Decode frame */ + dectime = msecond(); + used_bytes = dec_main(mp4_ptr, out_buffer, useful_bytes, &xvid_dec_stats); + dectime = msecond() - dectime; - /* Update mp4_ptr */ - mp4_ptr = mp4_buffer; + /* Resize image buffer if needed */ + if(xvid_dec_stats.type == XVID_TYPE_VOL) { - /* read new data */ - if(feof(in_file)) - break; - fread(mp4_buffer + rest, BUFFER_SIZE - rest, 1, in_file); + /* Check if old buffer is smaller */ + if(XDIM*YDIM < xvid_dec_stats.data.vol.width*xvid_dec_stats.data.vol.height) { - } + /* Copy new witdh and new height from the vol structure */ + XDIM = xvid_dec_stats.data.vol.width; + YDIM = xvid_dec_stats.data.vol.height; - } + /* Free old output buffer*/ + if(out_buffer) free(out_buffer); - /* Decode frame */ - dectime = msecond(); - status = dec_main(mp4_ptr, out_buffer, mp4_size, &used_bytes); - dectime = msecond() - dectime; + /* Allocate the new buffer */ + out_buffer = (unsigned char*)malloc(XDIM*YDIM*4); + if(out_buffer == NULL) + goto free_all_memory; - if (status) { - break; - } + fprintf(stderr, "Resized frame buffer to %dx%d\n", XDIM, YDIM); + } + } - /* - * Only needed for real raw stream, mp4u uses - * mp4_ptr = mp4_buffer for each frame - */ - mp4_ptr += used_bytes; + /* Update buffer pointers */ + if(used_bytes > 0) { + mp4_ptr += used_bytes; + useful_bytes -= used_bytes; + + /* Total size */ + totalsize += used_bytes; + } - /* Updated data */ - totalsize += used_bytes; + }while(xvid_dec_stats.type <= 0 && useful_bytes > 0); + + /* Check if there is a negative number of useful bytes left in buffer + * This means we went too far */ + if(useful_bytes < 0) + break; + + /* Updated data - Count only usefull decode time */ totaldectime += dectime; - - /* Prints some decoding stats */ - printf("Frame %5d: dectime =%6.1f ms length=%7d bytes \n", - filenr, dectime, used_bytes); - /* Save individual mpeg4 strean if required */ - if (ARG_SAVEMPEGSTREAM) { + + 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; sprintf(filename, "%sframe%05d.m4v", filepath, filenr); filehandle = fopen(filename, "wb"); if(!filehandle) { fprintf(stderr, - "Error writing single mpeg4 stream to file %s\n", - filename); + "Error writing single mpeg4 stream to file %s\n", + filename); } else { - fwrite(mp4_buffer, used_bytes, 1, filehandle); + fwrite(mp4_ptr-used_bytes, 1, used_bytes, filehandle); fclose(filehandle); } } - - + /* Save output frame if required */ if (ARG_SAVEDECOUTPUT) { sprintf(filename, "%sdec%05d.pgm", filepath, filenr); if(write_pgm(filename,out_buffer)) { fprintf(stderr, - "Error writing decoded PGM frame %s\n", - filename); + "Error writing decoded PGM frame %s\n", + filename); } } filenr++; - } while ( (status>=0) && (filenr=0) && (filenr=0 && xvid_dec_stats.type <= 0); + + if (used_bytes < 0) { /* XVID_ERR_END */ + break; + } - + /* Updated data - Count only usefull decode time */ + 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); + + /* Save output frame if required */ + if (ARG_SAVEDECOUTPUT) { + sprintf(filename, "%sdec%05d.pgm", filepath, filenr); + if(write_pgm(filename, out_buffer)) { + fprintf(stderr, + "Error writing decoded PGM frame %s\n", + filename); + } + } + + filenr++; + + }while(1); + /***************************************************************************** * Calculate totals and averages for output, print results ****************************************************************************/ @@ -381,8 +365,8 @@ totalsize /= filenr; totaldectime /= filenr; - printf("Avg: dectime %5.2f ms, %5.2f fps, mp4 stream size =%d\n", - totaldectime, 1000/totaldectime, (int)totalsize); + printf("Avg: dectime(ms) =%7.2f, fps =%7.2f, length(bytes) =%7d\n", + totaldectime, 1000/totaldectime, (int)totalsize); /***************************************************************************** * XviD PART Stop @@ -399,7 +383,7 @@ free(out_buffer); free(mp4_buffer); - return 0; + return(0); } /***************************************************************************** @@ -409,15 +393,13 @@ static void usage() { - fprintf(stderr, "Usage : xvid_decraw <-w width> <-h height> [OPTIONS]\n"); + fprintf(stderr, "Usage : xvid_decraw [OPTIONS]\n"); fprintf(stderr, "Options :\n"); fprintf(stderr, " -asm : use assembly optimizations (default=disabled)\n"); - fprintf(stderr, " -w integer : frame width ([1.2048])\n"); - fprintf(stderr, " -h integer : frame height ([1.2048])\n"); + fprintf(stderr, " -debug : debug level (debug=0)\n"); fprintf(stderr, " -i string : input filename (default=stdin)\n"); - fprintf(stderr, " -t integer : input data type (raw=0, mp4u=1)\n"); - fprintf(stderr, " -d boolean : save decoder output (0 False*, !=0 True)\n"); - fprintf(stderr, " -m boolean : save mpeg4 raw stream to individual files (0 False*, !=0 True)\n"); + fprintf(stderr, " -d : save decoder output\n"); + fprintf(stderr, " -m : save mpeg4 raw stream to individual files\n"); fprintf(stderr, " -help : This help message\n"); fprintf(stderr, " (* means default)\n"); @@ -431,14 +413,14 @@ static double msecond() { -#ifndef _MSC_VER +#ifndef WIN32 struct timeval tv; gettimeofday(&tv, 0); - return (double)tv.tv_sec*1.0e3 + (double)tv.tv_usec*1.0e-3; + return((double)tv.tv_sec*1.0e3 + (double)tv.tv_usec*1.0e-3); #else clock_t clk; clk = clock(); - return clk * 1000 / CLOCKS_PER_SEC; + return(clk * 1000 / CLOCKS_PER_SEC); #endif } @@ -448,7 +430,7 @@ static int write_pgm(char *filename, - unsigned char *image) + unsigned char *image) { int loop; @@ -483,10 +465,10 @@ /* Close file */ fclose(filehandle); - return 0; + return(0); } else - return 1; + return(1); } /***************************************************************************** @@ -495,63 +477,95 @@ /* init decoder before first run */ static int -dec_init(int use_assembler) +dec_init(int use_assembler, int debug_level) { - int xerr; + int ret; - XVID_INIT_PARAM xinit; - XVID_DEC_PARAM xparam; + xvid_gbl_init_t xvid_gbl_init; + xvid_dec_create_t xvid_dec_create; - if(use_assembler) -#ifdef ARCH_IA64 - xinit.cpu_flags = XVID_CPU_FORCE | XVID_CPU_IA64; + /*------------------------------------------------------------------------ + * XviD core initialization + *----------------------------------------------------------------------*/ + + /* Version */ + xvid_gbl_init.version = XVID_VERSION; + + /* Assembly setting */ + if(use_assembler) +#ifdef ARCH_IS_IA64 + xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_IA64; #else - xinit.cpu_flags = 0; + xvid_gbl_init.cpu_flags = 0; #endif - else - xinit.cpu_flags = XVID_CPU_FORCE; + else + xvid_gbl_init.cpu_flags = XVID_CPU_FORCE; + + xvid_gbl_init.debug = debug_level; + + xvid_global(NULL, 0, &xvid_gbl_init, NULL); + + /*------------------------------------------------------------------------ + * XviD encoder initialization + *----------------------------------------------------------------------*/ - xvid_init(NULL, 0, &xinit, NULL); - xparam.width = XDIM; - xparam.height = YDIM; + /* Version */ + xvid_dec_create.version = XVID_VERSION; - xerr = xvid_decore(NULL, XVID_DEC_CREATE, &xparam, NULL); - dec_handle = xparam.handle; + /* + * Image dimensions -- set to 0, xvidcore will resize when ever it is + * needed + */ + xvid_dec_create.width = 0; + xvid_dec_create.height = 0; - return xerr; + ret = xvid_decore(NULL, XVID_DEC_CREATE, &xvid_dec_create, NULL); + + dec_handle = xvid_dec_create.handle; + + return(ret); } /* decode one frame */ static int dec_main(unsigned char *istream, - unsigned char *ostream, - int istream_size, - int *ostream_size) + unsigned char *ostream, + int istream_size, + xvid_dec_stats_t *xvid_dec_stats) { - int xerr; - XVID_DEC_FRAME xframe; + int ret; + + xvid_dec_frame_t xvid_dec_frame; + + /* Set version */ + xvid_dec_frame.version = XVID_VERSION; + xvid_dec_stats->version = XVID_VERSION; + + /* No general flags to set */ + xvid_dec_frame.general = 0; - xframe.bitstream = istream; - xframe.length = istream_size; - xframe.image = ostream; - xframe.stride = XDIM; - xframe.colorspace = XVID_CSP_YV12; + /* Input stream */ + xvid_dec_frame.bitstream = istream; + xvid_dec_frame.length = istream_size; - xerr = xvid_decore(dec_handle, XVID_DEC_DECODE, &xframe, NULL); + /* 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; - *ostream_size = xframe.length; + ret = xvid_decore(dec_handle, XVID_DEC_DECODE, &xvid_dec_frame, xvid_dec_stats); - return xerr; + return(ret); } /* close decoder to release resources */ static int dec_stop() { - int xerr; + int ret; - xerr = xvid_decore(dec_handle, XVID_DEC_DESTROY, NULL, NULL); + ret = xvid_decore(dec_handle, XVID_DEC_DESTROY, NULL, NULL); - return xerr; + return(ret); }