--- branches/dev-api-4/xvidcore/examples/xvid_encraw.c 2003/03/09 00:28:09 909 +++ branches/dev-api-4/xvidcore/examples/xvid_encraw.c 2003/03/15 16:41:32 923 @@ -19,15 +19,15 @@ * 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_encraw.c,v 1.11.2.1 2003-03-09 00:28:09 edgomez Exp $ + * $Id: xvid_encraw.c,v 1.11.2.7 2003-03-15 16:41:32 suxen_drol Exp $ * ****************************************************************************/ /***************************************************************************** * Application notes : * - * A sequence of YUV pics in PGM file format is encoded and decoded - * The speed is measured and PSNR of decoded picture is calculated. + * A sequence of raw YUV I420 pics or YUV I420 PGM file format is encoded + * The speed is measured and frames' PSNR are taken from core. * * The program is plain C and needs no libraries except for libxvidcore, * and maths-lib. @@ -46,6 +46,7 @@ #include "xvid.h" + /***************************************************************************** * Quality presets ****************************************************************************/ @@ -56,7 +57,7 @@ PMV_HALFPELREFINE16, PMV_HALFPELREFINE16 | PMV_HALFPELREFINE8, PMV_HALFPELREFINE16 | PMV_HALFPELREFINE8 | PMV_EXTSEARCH16 | PMV_USESQUARES16, - PMV_HALFPELREFINE16 | PMV_HALFPELREFINE8 | PMV_EXTSEARCH16 | PMV_USESQUARES16, + PMV_HALFPELREFINE16 | PMV_HALFPELREFINE8 | PMV_EXTSEARCH16 | PMV_USESQUARES16 | PMV_CHROMA16 | PMV_CHROMA8, }; static xvid_vol_t const vol_presets[] = { @@ -84,6 +85,8 @@ /* Maximum number of frames to encode */ #define ABS_MAXFRAMENR 9999 +static int ARG_STATS = 0; +static int ARG_DUMP = 0; static int ARG_BITRATE = 900; static int ARG_QUANTI = 0; static int ARG_QUALITY = 5; @@ -100,6 +103,7 @@ static int ARG_BQRATIO = 150; static int ARG_BQOFFSET = 100; static int ARG_MAXBFRAMES = 0; +static int ARG_PACKED = 0; #define IMAGE_SIZE(x,y) ((x)*(y)*3/2) #define MAX(A,B) ( ((A)>(B)) ? (A) : (B) ) @@ -112,7 +116,7 @@ * Nasty global vars ;-) ***************************************************************************/ -static int i,filenr = 0; +static int i; /* the path where to save output */ static char filepath[256] = "./"; @@ -140,7 +144,11 @@ static int enc_stop(); static int enc_main(unsigned char* image, unsigned char* bitstream, - long *frametype); + int *key, + int *stats_type, + int *stats_quant, + int *stats_length, + int stats[3]); /***************************************************************************** * Main function @@ -156,12 +164,17 @@ double enctime; double totalenctime=0.; - long totalsize; - int status; - long frame_type; - - long m4v_size; + int totalsize; + int result; + int m4v_size; + int key; + int stats_type; + int stats_quant; + int stats_length; int use_assembler=0; + + int input_num; + int output_num; char filename[256]; @@ -196,6 +209,9 @@ i++; ARG_MAXBFRAMES = atoi(argv[i]); } + else if (strcmp("-p", argv[i]) == 0) { + ARG_PACKED = 1; + } else if (strcmp("-bqr", argv[i]) == 0 && i < argc - 1 ) { i++; ARG_BQRATIO = atoi(argv[i]); @@ -216,6 +232,12 @@ i++; ARG_INPUTFILE = argv[i]; } + else if (strcmp("-s", argv[i]) == 0) { + ARG_STATS = 1; + } + else if (strcmp("-dump", argv[i]) == 0) { + ARG_DUMP = 1; + } else if (strcmp("-t", argv[i]) == 0 && i < argc - 1 ) { i++; ARG_INPUTTYPE = atoi(argv[i]); @@ -228,9 +250,8 @@ i++; ARG_QUANTI = atoi(argv[i]); } - else if (strcmp("-m", argv[i]) == 0 && i < argc - 1 ) { - i++; - ARG_SAVEMPEGSTREAM = atoi(argv[i]); + else if (strcmp("-m", argv[i]) == 0) { + ARG_SAVEMPEGSTREAM = 1; } else if (strcmp("-o", argv[i]) == 0 && i < argc - 1 ) { i++; @@ -310,10 +331,10 @@ ****************************************************************************/ - status = enc_init(use_assembler); - if (status) + result = enc_init(use_assembler); + if (result) { - fprintf(stderr, "Encore INIT problem, return value %d\n", status); + fprintf(stderr, "Encore INIT problem, return value %d\n", result); goto release_all; } @@ -339,56 +360,85 @@ totalsize = 0; + result = 0; + + input_num = 0; /* input frame counter */ + output_num = 0; /* output frame counter */ + do { - if (ARG_INPUTTYPE) - status = read_pgmdata(in_file, in_buffer); /* read PGM data (YUV-format) */ - else - status = read_yuvdata(in_file, in_buffer); /* read raw data (YUV-format) */ - - if (status) - { - /* Couldn't read image, most likely end-of-file */ - continue; - } + char *type; + int stats[3]; + + if (input_num >= ARG_MAXFRAMENR) + { + result = 1; + } + + if (!result) + { + if(ARG_INPUTTYPE) { + /* read PGM data (YUV-format) */ + result = read_pgmdata(in_file, in_buffer); + } else { + /* read raw data (YUV-format) */ + result = read_yuvdata(in_file, in_buffer); + } + } /***************************************************************************** * Encode and decode this frame ****************************************************************************/ enctime = msecond(); - m4v_size = enc_main(in_buffer, mp4_buffer, &frame_type); + m4v_size = enc_main(!result?in_buffer:0, mp4_buffer, &key, &stats_type, &stats_quant, &stats_length, stats); enctime = msecond() - enctime; - /* Not coded frames return 0 */ - if(m4v_size == 0) goto next_frame; - - { - char *type; - - switch(frame_type) { - case XVID_TYPE_IVOP: - type = "I"; - break; - case XVID_TYPE_PVOP: - type = "P"; - break; - case XVID_TYPE_BVOP: - type = "B"; - break; - case XVID_TYPE_SVOP: - type = "S"; - break; - default: - type = "Unknown"; - break; - } - - printf("Frame %5d: type = %s, enctime(ms) =%6.1f, length(bytes) =%7d\n", - (int)filenr, type, (float)enctime, (int)m4v_size); + /* Write the Frame statistics */ + + printf("%5d: key=%i, time(ms)=%6.1f, length=%7d", + !result?input_num:-1, + key, + (float)enctime, + (int)m4v_size); + + if (stats_type > 0) { /* !XVID_TYPE_NOTHING */ + + switch(stats_type) { + case XVID_TYPE_IVOP: + type = "I"; + break; + case XVID_TYPE_PVOP: + type = "P"; + break; + case XVID_TYPE_BVOP: + type = "B"; + break; + case XVID_TYPE_SVOP: + type = "S"; + break; + default: + type = "U"; + break; + } + + printf(" | type=%s quant=%2d, length=%7d", type, stats_quant, stats_length); + + if(ARG_STATS) { + printf(", psnr y = %2.2f, psnr u = %2.2f, psnr v = %2.2f", + (stats[0] == 0)? 0.0f: 48.131f - 10*(float)log10((float)stats[0]/((float)(XDIM)*(YDIM))), + (stats[1] == 0)? 0.0f: 48.131f - 10*(float)log10((float)stats[1]/((float)(XDIM)*(YDIM)/4)), + (stats[2] == 0)? 0.0f: 48.131f - 10*(float)log10((float)stats[2]/((float)(XDIM)*(YDIM)/4))); + } } + printf("\n"); + + if (m4v_size < 0) { + break; + } + /* Update encoding time stats */ totalenctime += enctime; totalsize += m4v_size; @@ -397,15 +447,16 @@ * Save stream to file ****************************************************************************/ - if (ARG_SAVEMPEGSTREAM) + if (m4v_size>0 && ARG_SAVEMPEGSTREAM) { /* Save single files */ if (out_file == NULL) { - sprintf(filename, "%sframe%05d.m4v", filepath, filenr); + sprintf(filename, "%sframe%05d.m4v", filepath, output_num); out_file = fopen(filename, "wb"); fwrite(mp4_buffer, m4v_size, 1, out_file); fclose(out_file); out_file = NULL; + output_num++; } else { @@ -415,14 +466,13 @@ } } - next_frame: - /* Read the header if it's pgm stream */ - if (ARG_INPUTTYPE) - status = read_pgmheader(in_file); + input_num++; - if(frame_type != 5) filenr++; + /* Read the header if it's pgm stream */ + if (!result && ARG_INPUTTYPE) + result = read_pgmheader(in_file); - } while ( (!status) && (filenr 0) { + totalsize /= input_num; + totalenctime /= input_num; + }else{ + totalsize = -1; + totalenctime = -1; + } printf("Avg: enctime(ms) =%7.2f, fps =%7.2f, length(bytes) = %7d\n", totalenctime, 1000/totalenctime, (int)totalsize); + /***************************************************************************** * XviD PART Stop ****************************************************************************/ @@ -444,9 +500,9 @@ if (enc_handle) { - status = enc_stop(); - if (status) - fprintf(stderr, "Encore RELEASE problem return value %d\n", status); + result = enc_stop(); + if (result) + fprintf(stderr, "Encore RELEASE problem return value %d\n", result); } if(in_file) @@ -499,15 +555,17 @@ fprintf(stderr, " -h integer : frame height ([1.2048])\n"); fprintf(stderr, " -b integer : target bitrate (>0 | default=900kbit)\n"); fprintf(stderr, " -bn integer : max bframes (default=0)\n"); + fprintf(stderr, " -p : packed mode\n"); fprintf(stderr, " -bqr integer : bframe quantizer ratio (default=150)\n"); fprintf(stderr, " -bqo integer : bframe quantizer offset (default=100)\n"); fprintf(stderr, " -f float : target framerate (>0)\n"); fprintf(stderr, " -i string : input filename (default=stdin)\n"); + fprintf(stderr, " -s : print stats about encoded frames\n"); fprintf(stderr, " -t integer : input data type (yuv=0, pgm=1)\n"); fprintf(stderr, " -n integer : number of frames to encode\n"); fprintf(stderr, " -q integer : quality ([0..5])\n"); - fprintf(stderr, " -d boolean : save decoder output (0 False*, !=0 True)\n"); - fprintf(stderr, " -m boolean : save mpeg4 raw stream (0 False*, !=0 True)\n"); + fprintf(stderr, " -dump : save decoder output\n"); + fprintf(stderr, " -m : save mpeg4 raw stream\n"); fprintf(stderr, " -o string : output container filename (only usefull when -m 1 is used) :\n"); fprintf(stderr, " When this option is not used : one file per encoded frame\n"); fprintf(stderr, " When this option is used : save to 'string' file\n"); @@ -594,12 +652,38 @@ * Routines for encoding: init encoder, frame step, release encoder ****************************************************************************/ +/* sample plugin */ + +int rawenc_debug(void * handle, int opt, void * param1, void * param2) +{ + switch(opt) + { + case XVID_PLG_INFO : + case XVID_PLG_CREATE : + case XVID_PLG_DESTROY : + case XVID_PLG_BEFORE : + return 0; + + case XVID_PLG_AFTER : + { + xvid_plg_data_t * data = (xvid_plg_data_t*)param1; + printf("type=%i, quant=%i, length=%i\n", data->type, data->quant, data->length); + return 0; + } + } + + return XVID_ERR_FAIL; +} + + #define FRAMERATE_INCR 1001 /* Initialize encoder for first use, pass all needed parameters to the codec */ static int enc_init(int use_assembler) { int xerr; + + xvid_enc_plugin_t plugins[1]; xvid_gbl_init_t xvid_gbl_init; xvid_enc_create_t xvid_enc_create; @@ -609,7 +693,9 @@ *----------------------------------------------------------------------*/ /* Set version -- version checking will done by xvidcore*/ + memset(&xvid_gbl_init, 0, sizeof(xvid_gbl_init)); xvid_gbl_init.version = XVID_VERSION; + /* Do we have to enable ASM optimizations ? */ if(use_assembler) { @@ -632,12 +718,23 @@ *----------------------------------------------------------------------*/ /* Version again */ + memset(&xvid_enc_create, 0, sizeof(xvid_enc_create)); xvid_enc_create.version = XVID_VERSION; /* Width and Height of input frames */ xvid_enc_create.width = XDIM; xvid_enc_create.height = YDIM; + /* init plugins */ + + xvid_enc_create.plugins = plugins; + xvid_enc_create.num_plugins = 0; + if (ARG_DUMP) { + plugins[xvid_enc_create.num_plugins].func = xvid_plugin_dump; + plugins[xvid_enc_create.num_plugins].param = NULL; + xvid_enc_create.num_plugins++; + } + /* No fancy thread tests */ xvid_enc_create.num_threads = 0; @@ -663,6 +760,8 @@ /* Global encoder options */ xvid_enc_create.global = 0; + if (ARG_PACKED) xvid_enc_create.global |= XVID_PACKED; + if (ARG_STATS) xvid_enc_create.global |= XVID_EXTRASTATS_ENABLE; /* I use a small value here, since will not encode whole movies, but short clips */ xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL); @@ -685,29 +784,40 @@ static int enc_main(unsigned char* image, unsigned char* bitstream, - long *frametype) + int * key, + int *stats_type, + int *stats_quant, + int *stats_length, + int stats[3]) { int ret; xvid_enc_frame_t xvid_enc_frame; - xvid_enc_stats_t xvid_enc_stats[2]; + xvid_enc_stats_t xvid_enc_stats; /* Version for the frame and the stats */ + memset(&xvid_enc_frame, 0, sizeof(xvid_enc_frame)); xvid_enc_frame.version = XVID_VERSION; - xvid_enc_stats[0].version = XVID_VERSION; - xvid_enc_stats[1].version = XVID_VERSION; - + + memset(&xvid_enc_stats, 0, sizeof(xvid_enc_stats)); + xvid_enc_stats.version = XVID_VERSION; + /* Bind output buffer */ xvid_enc_frame.bitstream = bitstream; xvid_enc_frame.length = -1; /* Initialize input image fields */ - xvid_enc_frame.input.plane[0] = image; - xvid_enc_frame.input.csp = XVID_CSP_I420; - xvid_enc_frame.input.stride[0] = XDIM; + if (image) { + xvid_enc_frame.input.plane[0] = image; + xvid_enc_frame.input.csp = XVID_CSP_I420; + xvid_enc_frame.input.stride[0] = XDIM; + }else{ + xvid_enc_frame.input.csp = XVID_CSP_NULL; + } /* Set up core's general features */ xvid_enc_frame.vol_flags = vol_presets[ARG_QUALITY]; + if (ARG_STATS) xvid_enc_frame.vol_flags |= XVID_EXTRASTATS; /* Set up core's general features */ xvid_enc_frame.vop_flags = vop_presets[ARG_QUALITY]; @@ -726,9 +836,16 @@ xvid_enc_frame.quant_intra_matrix = NULL; xvid_enc_frame.quant_inter_matrix = NULL; + /* Encode the frame */ ret = xvid_encore(enc_handle, XVID_ENC_ENCODE, &xvid_enc_frame, &xvid_enc_stats); - *frametype = xvid_enc_stats[0].type; + *key = (xvid_enc_frame.out_flags & XVID_KEYFRAME); + *stats_type = xvid_enc_stats.type; + *stats_quant = xvid_enc_stats.quant; + *stats_length = xvid_enc_stats.length; + stats[0] = xvid_enc_stats.sse_y; + stats[1] = xvid_enc_stats.sse_u; + stats[2] = xvid_enc_stats.sse_v; return(ret); }