1 /*****************************************************************************
2  *
3  *  XVID MPEG-4 VIDEO CODEC
4  *  - Console based test application  -
5  *
6  *  Copyright(C) 2002-2003 Christoph Lampert <gruel@web.de>
7  *               2002-2003 Edouard Gomez <ed.gomez@free.fr>
8  *               2003      Peter Ross <pross@xvid.org>
9  *               2003-2014 Michael Militzer <isibaar@xvid.org>
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
24  *
25  * $Id: xvid_encraw.c 2129 2015-07-08 17:32:58Z Isibaar $
26  *
27  ****************************************************************************/
28 
29 /*****************************************************************************
30  *  Application notes :
31  *
32  *  A sequence of raw YUV I420 pics or YUV I420 PGM file format is encoded
33  *  The speed is measured and frames' PSNR are taken from core.
34  *
35  *  The program is plain C and needs no libraries except for libxvidcore,
36  *  and maths-lib.
37  *
38  *  Use ./xvid_encraw -help for a list of options
39  *
40  ************************************************************************/
41 
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <math.h>
46 #include <ctype.h>
47 #ifndef WIN32
48 #include <sys/time.h>
49 #else
50 #include <windows.h>
51 #include <vfw.h>
52 #include <time.h>
53 #define XVID_AVI_INPUT
54 #define XVID_AVI_OUTPUT
55 #endif
56 
57 #include "xvid.h"
58 #include "portab.h" /* for pthread */
59 
60 #ifdef XVID_MKV_OUTPUT
61 #include "matroska.cpp"
62 #endif
63 
64 #undef READ_PNM
65 
66 //#define USE_APP_LEVEL_THREADING /* Should xvid_encraw app use multi-threading? */
67 
68 /*****************************************************************************
69  *                            Quality presets
70  ****************************************************************************/
71 
72 // Equivalent to vfw's pmvfast_presets
73 static const int motion_presets[] = {
74 	/* quality 0 */
75 	0,
76 
77 	/* quality 1 */
78 	0,
79 
80 	/* quality 2 */
81 	0,
82 
83 	/* quality 3 */
84 	0,
85 
86 	/* quality 4 */
87 	0 | XVID_ME_HALFPELREFINE16 | 0,
88 
89 	/* quality 5 */
90 	0 | XVID_ME_HALFPELREFINE16 | 0 | XVID_ME_ADVANCEDDIAMOND16,
91 
92 	/* quality 6 */
93 	XVID_ME_HALFPELREFINE16 | XVID_ME_EXTSEARCH16 |	XVID_ME_HALFPELREFINE8 | 0 | XVID_ME_USESQUARES16
94 
95 };
96 #define ME_ELEMENTS (sizeof(motion_presets)/sizeof(motion_presets[0]))
97 
98 static const int vop_presets[] = {
99 	/* quality 0 */
100 	0,
101 
102 	/* quality 1 */
103 	0,
104 
105 	/* quality 2 */
106 	0,
107 
108 	/* quality 3 */
109 	0,
110 
111 	/* quality 4 */
112 	0,
113 
114 	/* quality 5 */
115 	XVID_VOP_INTER4V,
116 
117 	/* quality 6 */
118 	XVID_VOP_INTER4V,
119 
120 };
121 #define VOP_ELEMENTS (sizeof(vop_presets)/sizeof(vop_presets[0]))
122 
123 /*****************************************************************************
124  *                     Command line global variables
125  ****************************************************************************/
126 
127 #define MAX_ZONES   64
128 #define MAX_ENC_INSTANCES 4
129 #define MAX_XDIM 4096
130 #define MAX_YDIM 4096
131 #define DEFAULT_QUANT 400
132 #define DEFAULT_BITRATE 700000 /* bitrate expressed in bps, not kbps */
133 #define DEFAULT_INTERLACING 1  /* 1:BFF, 2:TFF */
134 #define DEFAULT_SSIM 2
135 #define DEFAULT_PROGRESS 10    /* show progress every 10 frames by default */
136 
137 typedef struct
138 {
139 	int frame;
140 
141 	int type;
142 	int mode;
143 	int modifier;
144 
145 	unsigned int greyscale;
146 	unsigned int chroma_opt;
147 	unsigned int bvop_threshold;
148 	unsigned int cartoon_mode;
149 } zone_t;
150 
151 typedef struct
152 {
153 	int count;
154 	int size;
155 	int quants[32];
156 } frame_stats_t;
157 
158 typedef struct
159 {
160 	pthread_t handle;       /* thread's handle */
161 
162 	int start_num;          /* begin/end of sequence */
163 	int stop_num;
164 
165 	char *outfilename;      /* output filename */
166 	char *outavifilename;   /* output avi filename */
167 	char *outmkvfilename;   /* output mkv filename */
168 	char *statsfilename1;   /* pass1 statsfile */
169 
170 	int input_num;
171 
172 	int totalsize;          /* encoder stats */
173 	double totalenctime;
174 	float totalPSNR[3];
175  	frame_stats_t framestats[7];
176 } enc_sequence_data_t;
177 
178 /* Maximum number of frames to encode */
179 #define ABS_MAXFRAMENR -1 /* no limit */
180 
181 #ifndef READ_PNM
182 #define IMAGE_SIZE(x,y) ((x)*(y)*3/2)
183 #else
184 #define IMAGE_SIZE(x,y) ((x)*(y)*3)
185 #endif
186 
187 #define MAX(A,B) ( ((A)>(B)) ? (A) : (B) )
188 #define SMALL_EPS (1e-10)
189 
190 #define SWAP(a) ( (((a)&0x000000ff)<<24) | (((a)&0x0000ff00)<<8) | \
191                   (((a)&0x00ff0000)>>8)  | (((a)&0xff000000)>>24) )
192 
193 static zone_t ZONES[MAX_ZONES];
194 static 	int NUM_ZONES = 0;
195 
196 static 	int ARG_NUM_APP_THREADS = 1;
197 static 	int ARG_CPU_FLAGS = 0;
198 static 	int ARG_SSIM = -1;
199 static 	char* ARG_SSIM_PATH = NULL;
200 static 	int ARG_DUMP = 0;
201 static 	int ARG_LUMIMASKING = 0;
202 static 	int ARG_BITRATE = 0;
203 static 	int ARG_TARGETSIZE = 0;
204 static 	int ARG_SINGLE = 1;
205 static 	char *ARG_PASS1 = 0;
206 static 	char *ARG_PASS2 = 0;
207 //static int ARG_QUALITY = ME_ELEMENTS - 1;
208 static 	int ARG_QUALITY = 6;
209 static 	float ARG_FRAMERATE = 0.f;
210 static 	int ARG_DWRATE = 25;
211 static 	int ARG_DWSCALE = 1;
212 static 	int ARG_MAXFRAMENR = ABS_MAXFRAMENR;
213 static 	int ARG_MAXKEYINTERVAL = 300;
214 static 	int ARG_STARTFRAMENR = 0;
215 static 	char *ARG_INPUTFILE = NULL;
216 static 	int ARG_INPUTTYPE = 0;
217 static 	int ARG_SAVEMPEGSTREAM = 0;
218 static 	int ARG_SAVEINDIVIDUAL = 0;
219 static 	char *ARG_OUTPUTFILE = NULL;
220 static 	char *ARG_AVIOUTPUTFILE = NULL;
221 static 	char *ARG_MKVOUTPUTFILE = NULL;
222 static 	char *ARG_TIMECODEFILE = NULL;
223 static 	int XDIM = 0;
224 static 	int YDIM = 0;
225 static 	int ARG_BQRATIO = 150;
226 static 	int ARG_BQOFFSET = 100;
227 static	int ARG_MAXBFRAMES = 2;
228 static 	int ARG_DEBUG = 0;
229 static 	int ARG_QTYPE = 0;
230 static 	int ARG_QMATRIX = 0;
231 static 	int ARG_INTERLACING = 0;
232 static 	int ARG_VHQMODE = 1;
233 static 	int ARG_QMETRIC = 0;
234 static 	int ARG_PAR = 1;
235 static 	int ARG_PARHEIGHT;
236 static 	int ARG_PARWIDTH;
237 static 	int ARG_QUANTS[6] = {2, 31, 2, 31, 2, 31};
238 static 	int ARG_FRAMEDROP = 0;
239 static 	double ARG_CQ = 0;
240 static 	int ARG_FULL1PASS = 0;
241 static 	int ARG_REACTION = 16;
242 static 	int ARG_AVERAGING = 100;
243 static 	int ARG_SMOOTHER = 100;
244 static 	int ARG_KBOOST = 10;
245 static 	int ARG_KREDUCTION = 20;
246 static 	int ARG_KTHRESH = 1;
247 static  int ARG_CHIGH = 0;
248 static 	int ARG_CLOW = 0;
249 static 	int ARG_OVERSTRENGTH = 5;
250 static 	int ARG_OVERIMPROVE = 5;
251 static 	int ARG_OVERDEGRADE = 5;
252 static 	int ARG_OVERHEAD = 0;
253 static 	int ARG_VBVSIZE = 0;
254 static 	int ARG_VBVMAXRATE = 0;
255 static 	int ARG_VBVPEAKRATE = 0;
256 static 	int ARG_THREADS = 0;
257 static 	int ARG_SLICES = 1;
258 static 	int ARG_PROGRESS = 0;
259 static 	int ARG_COLORSPACE = XVID_CSP_YV12;
260 	/* the path where to save output */
261 static char filepath[256] = "./";
262 
263 /* on/off options */
264 static  int ARG_USE_ASSEMBLER = 1;
265 static  int ARG_TURBO         = 0;
266 static  int ARG_BVHQ          = 0;
267 static  int ARG_QPEL          = 0;
268 static  int ARG_GMC           = 0;
269 static  int ARG_PACKED        = 1;
270 static  int ARG_CLOSED_GOP    = 1;
271 static  int ARG_STATS         = 0;
272 static  int ARG_PSNRHVSM      = 0;
273 static  int ARG_VOPDEBUG      = 0;
274 static  int ARG_CHROMAME      = 1;
275 static  int ARG_TRELLIS       = 1;
276 
277 static 	unsigned char qmatrix_intra[64];
278 static 	unsigned char qmatrix_inter[64];
279 
280 /****************************************************************************
281  *                     Nasty global vars ;-)
282  ***************************************************************************/
283 
284 static const int height_ratios[] = {1, 1, 11, 11, 11, 33};
285 static const int width_ratios[] = {1, 1, 12, 10, 16, 40};
286 
287 const char userdata_start_code[] = "\0\0\x01\xb2";
288 
289 
290 /*****************************************************************************
291  *               Local prototypes
292  ****************************************************************************/
293 
294 /* Prints program usage message */
295 static void usage();
296 
297 /* Statistical functions */
298 static double msecond();
299 int gcd(int a, int b);
300 int minquant(int quants[32]);
301 int maxquant(int quants[32]);
302 double avgquant(frame_stats_t frame);
303 
304 /* PGM related functions */
305 #ifndef READ_PNM
306 static int read_pgmheader(FILE * handle);
307 static int read_pgmdata(FILE * handle,
308 						unsigned char *image);
309 #else
310 static int read_pnmheader(FILE * handle);
311 static int read_pnmdata(FILE * handle,
312 						unsigned char *image);
313 #endif
314 static int read_yuvdata(FILE * handle,
315 						unsigned char *image);
316 
317 /* Encoder related functions */
318 static void enc_gbl(int use_assembler);
319 static int  enc_init(void **enc_handle, char *stats_pass1, int start_num);
320 static int  enc_info();
321 static int  enc_stop(void *enc_handle);
322 static int  enc_main(void *enc_handle,
323 					 unsigned char *image,
324 			 		 unsigned char *bitstream,
325 					 int *key,
326 					 int *stats_type,
327 					 int *stats_quant,
328 					 int *stats_length,
329 					 int stats[3],
330 					 int framenum);
331 static void encode_sequence(enc_sequence_data_t *h);
332 
333 /* Zone Related Functions */
334 static void apply_zone_modifiers(xvid_enc_frame_t * frame, int framenum);
335 static void prepare_full1pass_zones();
336 static void prepare_cquant_zones();
337 void sort_zones(zone_t * zones, int zone_num, int * sel);
338 
339 
340 void removedivxp(char *buf, int size);
341 
342 /*****************************************************************************
343  *               Main function
344  ****************************************************************************/
345 
346 int
main(int argc,char * argv[])347 main(int argc,
348 	 char *argv[])
349 {
350 	double totalenctime = 0.;
351 	float totalPSNR[3] = {0., 0., 0.};
352 
353 	FILE *statsfile;
354 	frame_stats_t framestats[7];
355 
356 	int input_num = 0;
357 	int totalsize = 0;
358 	int use_assembler = ARG_USE_ASSEMBLER;
359 	int i;
360 
361 	printf("xvid_encraw - raw mpeg4 bitstream encoder ");
362 	printf("written by Christoph Lampert\n\n");
363 
364 	/* Is there a dumb Xvid coder ? */
365 	if(ME_ELEMENTS != VOP_ELEMENTS) {
366 		fprintf(stderr, "Presets' arrays should have the same number of elements -- Please file a bug to xvid-devel@xvid.org\n");
367 		return(-1);
368 	}
369 
370 	/* Clear framestats */
371 	memset(framestats, 0, sizeof(framestats));
372 
373 /*****************************************************************************
374  *                            Command line parsing
375  ****************************************************************************/
376 
377 	for (i = 1; i < argc; i++) {
378 
379 		if (strcmp("-asm", argv[i]) == 0) {
380 			use_assembler = 1;
381 		} else if (strcmp("-noasm", argv[i]) == 0) {
382 			use_assembler = 0;
383 		} else if (strcmp("-w", argv[i]) == 0 && i < argc - 1) {
384 			i++;
385 			XDIM = atoi(argv[i]);
386 		} else if (strcmp("-h", argv[i]) == 0 && i < argc - 1) {
387 			i++;
388 			YDIM = atoi(argv[i]);
389 		} else if (strcmp("-csp",argv[i]) == 0 && i < argc - 1) {
390 			i++;
391 			if (strcmp(argv[i],"i420") == 0){
392 				ARG_COLORSPACE = XVID_CSP_I420;
393 			} else if(strcmp(argv[i],"yv12") == 0){
394 				ARG_COLORSPACE = XVID_CSP_YV12;
395 			} else {
396 				printf("Invalid colorspace\n");
397 				return 0;
398 			}
399 		} else if (strcmp("-bitrate", argv[i]) == 0) {
400 			if (i < argc - 1)
401 				ARG_BITRATE = atoi(argv[i+1]);
402 			if (ARG_BITRATE) {
403 				i++;
404 				if (ARG_BITRATE <= 20000)
405 					/* if given parameter is <= 20000, assume it means kbps */
406 					ARG_BITRATE *= 1000;
407 			}
408 			else
409 				ARG_BITRATE = DEFAULT_BITRATE;
410 		} else if (strcmp("-size", argv[i]) == 0 && i < argc - 1) {
411 			i++;
412 			ARG_TARGETSIZE = atoi(argv[i]);
413         } else if (strcmp("-cq", argv[i]) == 0 && i < argc - 1) {
414 			i++;
415 			ARG_CQ = atof(argv[i])*100;
416 		} else if (strcmp("-single", argv[i]) == 0) {
417 			ARG_SINGLE = 1;
418 			ARG_PASS1 = NULL;
419 			ARG_PASS2 = NULL;
420 		} else if (strcmp("-pass1", argv[i]) == 0) {
421 			ARG_SINGLE = 0;
422 			if ((i < argc - 1) && (*argv[i+1] != '-')) {
423 				i++;
424 				ARG_PASS1 = argv[i];
425 			} else {
426 				ARG_PASS1 = "xvid.stats";
427 			}
428 		} else if (strcmp("-full1pass", argv[i]) == 0) {
429 			ARG_FULL1PASS = 1;
430 		} else if (strcmp("-pass2", argv[i]) == 0) {
431 			ARG_SINGLE = 0;
432 			if ((i < argc - 1) && (*argv[i+1] != '-')) {
433 				i++;
434 				ARG_PASS2 = argv[i];
435 			} else {
436 				ARG_PASS2 = "xvid.stats";
437 			}
438 		} else if (strcmp("-max_bframes", argv[i]) == 0 && i < argc - 1) {
439 			i++;
440 			ARG_MAXBFRAMES = atoi(argv[i]);
441 		} else if (strcmp("-par", argv[i]) == 0 && i < argc - 1) {
442 			i++;
443 			if (sscanf(argv[i], "%d:%d", &(ARG_PARWIDTH), &(ARG_PARHEIGHT))!=2)
444 				ARG_PAR = atoi(argv[i]);
445 			else {
446 				int div;
447 				ARG_PAR = 0;
448 				div = gcd(ARG_PARWIDTH, ARG_PARHEIGHT);
449 				ARG_PARWIDTH /= div;
450 				ARG_PARHEIGHT /= div;
451 			}
452 		} else if (strcmp("-nopacked", argv[i]) == 0) {
453 			ARG_PACKED = 0;
454 		} else if (strcmp("-packed", argv[i]) == 0) {
455 			ARG_PACKED = 2;
456 		} else if (strcmp("-nochromame", argv[i]) == 0) {
457 			ARG_CHROMAME = 0;
458 		} else if (strcmp("-chromame", argv[i]) == 0) {
459 			ARG_CHROMAME = 1;
460 		} else if (strcmp("-threads", argv[i]) == 0 && i < argc -1) {
461 			i++;
462 			ARG_THREADS = atoi(argv[i]);
463 		} else if (strcmp("-slices", argv[i]) == 0 && i < argc -1) {
464 			i++;
465 			ARG_SLICES = atoi(argv[i]);
466 		} else if (strcmp("-bquant_ratio", argv[i]) == 0 && i < argc - 1) {
467 			i++;
468 			ARG_BQRATIO = atoi(argv[i]);
469 		} else if (strcmp("-bquant_offset", argv[i]) == 0 && i < argc - 1) {
470 			i++;
471 			ARG_BQOFFSET = atoi(argv[i]);
472 
473 		} else if (strcmp("-zones", argv[i]) == 0 && i < argc -1) {
474 			char c;
475 			char *frameoptions, *rem;
476 			int startframe;
477 			char options[40];
478 
479 			i++;
480 
481 			do {
482 				rem = strrchr(argv[i], '/');
483 				if (rem==NULL)
484 					rem=argv[i];
485 				else {
486 					*rem = '\0';
487 					rem++;
488 				}
489 				if (sscanf(rem, "%d,%c,%s", &startframe, &c, options)<3) {
490 					fprintf(stderr, "Zone error, bad parameters %s\n", rem);
491 					continue;
492 				}
493 				if (NUM_ZONES >= MAX_ZONES) {
494 					fprintf(stderr, "warning: too many zones; zone ignored\n");
495 					continue;
496 				}
497 				memset(&ZONES[NUM_ZONES], 0, sizeof(zone_t));
498 
499 				ZONES[NUM_ZONES].frame = startframe;
500 				ZONES[NUM_ZONES].modifier = (int)(atof(options)*100);
501 				if (toupper(c)=='Q')
502 					ZONES[NUM_ZONES].mode = XVID_ZONE_QUANT;
503 				else if (toupper(c)=='W')
504 					ZONES[NUM_ZONES].mode = XVID_ZONE_WEIGHT;
505 				else {
506 					fprintf(stderr, "Bad zone type %c\n", c);
507 					continue;
508 				}
509 
510 				if ((frameoptions=strchr(options, ','))!=NULL) {
511 					int readchar=0, count;
512 					frameoptions++;
513 					while (readchar<(int)strlen(frameoptions)) {
514 						if (sscanf(frameoptions+readchar, "%d%n", &(ZONES[NUM_ZONES].bvop_threshold), &count)==1) {
515 							readchar += count;
516 						}
517 						else {
518 							if (toupper(frameoptions[readchar])=='K')
519 								ZONES[NUM_ZONES].type = XVID_TYPE_IVOP;
520 							else if (toupper(frameoptions[readchar])=='G')
521 								ZONES[NUM_ZONES].greyscale = 1;
522 							else if (toupper(frameoptions[readchar])=='O')
523 								ZONES[NUM_ZONES].chroma_opt = 1;
524 							else if (toupper(frameoptions[readchar])=='C')
525 								ZONES[NUM_ZONES].cartoon_mode = 1;
526 							else {
527 								fprintf(stderr, "Error in zone %s option %c\n", rem, frameoptions[readchar]);
528 								break;
529 							}
530 							readchar++;
531 						}
532 					}
533 				}
534 				NUM_ZONES++;
535 			} while (rem != argv[i]);
536 
537 
538 		} else if ((strcmp("-zq", argv[i]) == 0 || strcmp("-zw", argv[i]) == 0) && i < argc - 2) {
539 
540             if (NUM_ZONES >= MAX_ZONES) {
541                 fprintf(stderr,"warning: too many zones; zone ignored\n");
542                 continue;
543             }
544 			memset(&ZONES[NUM_ZONES], 0, sizeof(zone_t));
545 			if (strcmp("-zq", argv[i])== 0) {
546 				ZONES[NUM_ZONES].mode = XVID_ZONE_QUANT;
547 			}
548 			else {
549 				ZONES[NUM_ZONES].mode = XVID_ZONE_WEIGHT;
550 			}
551 			ZONES[NUM_ZONES].modifier = (int)(atof(argv[i+2])*100);
552 			i++;
553             ZONES[NUM_ZONES].frame = atoi(argv[i]);
554 			i++;
555 			ZONES[NUM_ZONES].type = XVID_TYPE_AUTO;
556 			ZONES[NUM_ZONES].greyscale = 0;
557 			ZONES[NUM_ZONES].chroma_opt = 0;
558 			ZONES[NUM_ZONES].bvop_threshold = 0;
559 			ZONES[NUM_ZONES].cartoon_mode = 0;
560 
561             NUM_ZONES++;
562 		} else if (strcmp("-quality", argv[i]) == 0 && i < argc - 1) {
563 			i++;
564 			ARG_QUALITY = atoi(argv[i]);
565 		} else if (strcmp("-start", argv[i]) == 0 && i < argc - 1) {
566 			i++;
567 			ARG_STARTFRAMENR = atoi(argv[i]);
568 		} else if (strcmp("-vhqmode", argv[i]) == 0 && i < argc - 1) {
569 			i++;
570 			ARG_VHQMODE = atoi(argv[i]);
571 		} else if (strcmp("-metric", argv[i]) == 0 && i < argc - 1) {
572 			i++;
573 			ARG_QMETRIC = atoi(argv[i]);
574 		} else if (strcmp("-framerate", argv[i]) == 0 && i < argc - 1) {
575 			int exponent;
576 			i++;
577 			ARG_FRAMERATE = (float) atof(argv[i]);
578 			exponent = (int) strcspn(argv[i], ".");
579 			if (exponent<(int)strlen(argv[i]))
580 				exponent=(int)pow(10.0, (int)(strlen(argv[i])-1-exponent));
581 			else
582 				exponent=1;
583 			ARG_DWRATE = (int)(atof(argv[i])*exponent);
584 			ARG_DWSCALE = exponent;
585 			exponent = gcd(ARG_DWRATE, ARG_DWSCALE);
586 			ARG_DWRATE /= exponent;
587 			ARG_DWSCALE /= exponent;
588 		} else if (strcmp("-max_key_interval", argv[i]) == 0 && i < argc - 1) {
589 			i++;
590 			ARG_MAXKEYINTERVAL = atoi(argv[i]);
591 		} else if (strcmp("-i", argv[i]) == 0 && i < argc - 1) {
592 			i++;
593 			ARG_INPUTFILE = argv[i];
594 		} else if (strcmp("-stats", argv[i]) == 0) {
595 			ARG_STATS = 1;
596 		} else if (strcmp("-nostats", argv[i]) == 0) {
597 			ARG_STATS = 0;
598 		} else if (strcmp("-ssim", argv[i]) == 0) {
599 			ARG_SSIM = DEFAULT_SSIM;
600 			if ((i < argc - 1) && (*argv[i+1] != '-')) {
601 				i++;
602 				ARG_SSIM = atoi(argv[i]);
603 			}
604 		} else if (strcmp("-psnrhvsm", argv[i]) == 0) {
605 			ARG_PSNRHVSM = 1;
606 		} else if (strcmp("-nopsnrhvsm", argv[i]) == 0) {
607 			ARG_PSNRHVSM = 0;
608 		} else if (strcmp("-ssim_file", argv[i]) == 0 && i < argc -1) {
609 			i++;
610 			ARG_SSIM_PATH = argv[i];
611 		} else if (strcmp("-timecode", argv[i]) == 0 && i < argc -1) {
612 			i++;
613 			ARG_TIMECODEFILE = argv[i];
614 		} else if (strcmp("-dump", argv[i]) == 0) {
615 			ARG_DUMP = 1;
616 		} else if (strcmp("-masking", argv[i]) == 0 && i < argc -1) {
617 			i++;
618 			ARG_LUMIMASKING = atoi(argv[i]);
619 		} else if (strcmp("-type", argv[i]) == 0 && i < argc - 1) {
620 			i++;
621 			ARG_INPUTTYPE = atoi(argv[i]);
622 		} else if (strcmp("-frames", argv[i]) == 0 && i < argc - 1) {
623 			i++;
624 			ARG_MAXFRAMENR = atoi(argv[i]);
625 		} else if (strcmp("-drop", argv[i]) == 0 && i < argc - 1) {
626 			i++;
627 			ARG_FRAMEDROP = atoi(argv[i]);
628 		} else if (strcmp("-imin", argv[i]) == 0 && i < argc - 1) {
629 			i++;
630 			ARG_QUANTS[0] = atoi(argv[i]);
631 		} else if (strcmp("-imax", argv[i]) == 0 && i < argc - 1) {
632 			i++;
633 			ARG_QUANTS[1] = atoi(argv[i]);
634 		} else if (strcmp("-pmin", argv[i]) == 0 && i < argc - 1) {
635 			i++;
636 			ARG_QUANTS[2] = atoi(argv[i]);
637 		} else if (strcmp("-pmax", argv[i]) == 0 && i < argc - 1) {
638 			i++;
639 			ARG_QUANTS[3] = atoi(argv[i]);
640 		} else if (strcmp("-bmin", argv[i]) == 0 && i < argc - 1) {
641 			i++;
642 			ARG_QUANTS[4] = atoi(argv[i]);
643 		} else if (strcmp("-bmax", argv[i]) == 0 && i < argc - 1) {
644 			i++;
645 			ARG_QUANTS[5] = atoi(argv[i]);
646 		} else if (strcmp("-qtype", argv[i]) == 0 && i < argc - 1) {
647 			i++;
648 			ARG_QTYPE = atoi(argv[i]);
649 		} else if (strcmp("-qmatrix", argv[i]) == 0 && i < argc - 1) {
650 			FILE *fp = fopen(argv[++i], "rb");
651 			if (fp == NULL) {
652 				fprintf(stderr, "Error opening input file %s\n", argv[i]);
653 				return (-1);
654 			}
655 			fseek(fp, 0, SEEK_END);
656 			if (ftell(fp) != 128) {
657 				fprintf(stderr, "Unexpected size of input file %s\n", argv[i]);
658 				return (-1);
659 			}
660 
661 			fseek(fp, 0, SEEK_SET);
662 			fread(qmatrix_intra, 1, 64, fp);
663 			fread(qmatrix_inter, 1, 64, fp);
664 
665 			ARG_QMATRIX = 1;
666 			ARG_QTYPE = 1;
667 		} else if (strcmp("-save", argv[i]) == 0) {
668 			ARG_SAVEMPEGSTREAM = 1;
669 			ARG_SAVEINDIVIDUAL = 1;
670 		} else if (strcmp("-debug", argv[i]) == 0 && i < argc -1) {
671 			i++;
672             if (!(sscanf(argv[i],"0x%x", &(ARG_DEBUG))))
673 				sscanf(argv[i],"%d", &(ARG_DEBUG));
674 		} else if (strcmp("-o", argv[i]) == 0 && i < argc - 1) {
675 			ARG_SAVEMPEGSTREAM = 1;
676 			i++;
677 			ARG_OUTPUTFILE = argv[i];
678 		} else if (strcmp("-avi", argv[i]) == 0 && i < argc - 1) {
679 #ifdef XVID_AVI_OUTPUT
680 			ARG_SAVEMPEGSTREAM = 1;
681 			i++;
682 			ARG_AVIOUTPUTFILE = argv[i];
683 #else
684 			fprintf( stderr, "Not compiled with AVI output support.\n");
685 			return(-1);
686 #endif
687 		} else if (strcmp("-mkv", argv[i]) == 0 && i < argc - 1) {
688 #ifdef XVID_MKV_OUTPUT
689 			ARG_SAVEMPEGSTREAM = 1;
690 			i++;
691 			ARG_MKVOUTPUTFILE = argv[i];
692 #else
693 			fprintf(stderr, "Not compiled with MKV output support.\n");
694 			return(-1);
695 #endif
696 		} else if (strcmp("-vop_debug", argv[i]) == 0) {
697 			ARG_VOPDEBUG = 1;
698 		} else if (strcmp("-novop_debug", argv[i]) == 0) {
699 			ARG_VOPDEBUG = 0;
700 		} else if (strcmp("-trellis", argv[i]) == 0) {
701 			ARG_TRELLIS = 1;
702 		} else if (strcmp("-notrellis", argv[i]) == 0) {
703 			ARG_TRELLIS = 0;
704 		} else if (strcmp("-bvhq", argv[i]) == 0) {
705 			ARG_BVHQ = 1;
706 		} else if (strcmp("-nobvhq", argv[i]) == 0) {
707 			ARG_BVHQ = 0;
708 		} else if (strcmp("-qpel", argv[i]) == 0) {
709 			ARG_QPEL = 1;
710 		} else if (strcmp("-noqpel", argv[i]) == 0) {
711 			ARG_QPEL = 0;
712 		} else if (strcmp("-turbo", argv[i]) == 0) {
713 			ARG_TURBO = 1;
714 		} else if (strcmp("-noturbo", argv[i]) == 0) {
715 			ARG_TURBO = 0;
716 		} else if (strcmp("-gmc", argv[i]) == 0) {
717 			ARG_GMC = 1;
718 		} else if (strcmp("-nogmc", argv[i]) == 0) {
719 			ARG_GMC = 0;
720 		} else if (strcmp("-interlaced", argv[i]) == 0) {
721 			if ((i < argc - 1) && (*argv[i+1] != '-')) {
722 				i++;
723 				ARG_INTERLACING = atoi(argv[i]);
724 			} else {
725 				ARG_INTERLACING = DEFAULT_INTERLACING;
726 			}
727 		} else if (strcmp("-noclosed_gop", argv[i]) == 0) {
728 			ARG_CLOSED_GOP = 0;
729 		} else if (strcmp("-closed_gop", argv[i]) == 0) {
730 			ARG_CLOSED_GOP = 2;
731 		} else if (strcmp("-vbvsize", argv[i]) == 0 && i < argc -1) {
732 			i++;
733 			ARG_VBVSIZE = atoi(argv[i]);
734 		} else if (strcmp("-vbvmax", argv[i]) == 0 && i < argc -1) {
735 			i++;
736 			ARG_VBVMAXRATE = atoi(argv[i]);
737 		} else if (strcmp("-vbvpeak", argv[i]) == 0 && i < argc -1) {
738 			i++;
739 			ARG_VBVPEAKRATE = atoi(argv[i]);
740 		} else if (strcmp("-reaction", argv[i]) == 0 && i < argc -1) {
741 			i++;
742 			ARG_REACTION = atoi(argv[i]);
743 		} else if (strcmp("-averaging", argv[i]) == 0 && i < argc -1) {
744 			i++;
745 			ARG_AVERAGING = atoi(argv[i]);
746 		} else if (strcmp("-smoother", argv[i]) == 0 && i < argc -1) {
747 			i++;
748 			ARG_SMOOTHER = atoi(argv[i]);
749 		} else if (strcmp("-kboost", argv[i]) == 0 && i < argc -1) {
750 			i++;
751 			ARG_KBOOST = atoi(argv[i]);
752 		} else if (strcmp("-kthresh", argv[i]) == 0 && i < argc -1) {
753 			i++;
754 			ARG_KTHRESH = atoi(argv[i]);
755 		} else if (strcmp("-chigh", argv[i]) == 0 && i < argc -1) {
756 			i++;
757 			ARG_CHIGH = atoi(argv[i]);
758 		} else if (strcmp("-clow", argv[i]) == 0 && i < argc -1) {
759 			i++;
760 			ARG_CLOW = atoi(argv[i]);
761 		} else if (strcmp("-ostrength", argv[i]) == 0 && i < argc -1) {
762 			i++;
763 			ARG_OVERSTRENGTH = atoi(argv[i]);
764 		} else if (strcmp("-oimprove", argv[i]) == 0 && i < argc -1) {
765 			i++;
766 			ARG_OVERIMPROVE = atoi(argv[i]);
767 		} else if (strcmp("-odegrade", argv[i]) == 0 && i < argc -1) {
768 			i++;
769 			ARG_OVERDEGRADE = atoi(argv[i]);
770 		} else if (strcmp("-overhead", argv[i]) == 0 && i < argc -1) {
771 			i++;
772 			ARG_OVERHEAD = atoi(argv[i]);
773 		} else if (strcmp("-kreduction", argv[i]) == 0 && i < argc -1) {
774 			i++;
775 			ARG_KREDUCTION = atoi(argv[i]);
776         } else if (strcmp("-progress", argv[i]) == 0) {
777 			if (i < argc - 1)
778 				/* in kbps */
779 				ARG_PROGRESS = atoi(argv[i+1]);
780 			if (ARG_PROGRESS > 0)
781 				i++;
782 			else
783 				ARG_PROGRESS = DEFAULT_PROGRESS;
784 		} else if (strcmp("-help", argv[i]) == 0) {
785 		    if (i < argc - 1 && strcmp("zones", argv[i+1]) == 0) {
786 				fprintf(stderr, "Zones options\n\
787 NB: You can define up to %d zones using the -zones option as described below.\n\
788 \n\
789  -zones start,mode,value[,options][/start,mode,value[,options]]...\n\
790 \n\
791  Parameters of a zone use the comma (,) as a delimiter. Multiple zones are\n\
792  separated by a slash (/). The end of each zone is defined by either the start\n\
793  of the following zone or the last frame of the input file.\n\
794 \n\
795  start     : start frame of the zone\n\
796  mode      : weight zone = w, quantizer zone = q\n\
797  value     : depending on mode either the zone's weight or quantizer\n\
798  options   : enable certain encoder features for the zone. Each feature is\n\
799              represented by a single letter. An integer number stands for\n\
800              b-frame sensitivity. To enable multiple features at the same time\n\
801              combine the appropriate symbols without any delimiting characters.\n\
802              K = begin with keyframe\n\
803              O = enable chroma optimizer\n\
804              G = greyscale encoding\n\
805              C = cartoon mode\n\
806        integer = b-frame sensitivity\n\
807 \n\
808  Example:\n\
809   to create a first zone starting at frame 0 with weight 1.0, all options\n\
810   enabled and b-frame sensitivity -5, and a second zone starting at frame 1000\n\
811   with constant quant 4 and no options enabled you would use the -zones option\n\
812   like this:\n\
813 \n\
814   -zones 0,w,1.0,-5KOGC/1000,q,4\n\n", MAX_ZONES);
815 			} else
816 				usage();
817 			return (0);
818 		} else {
819 			usage();
820 			exit(-1);
821 		}
822 
823 	}
824 
825 /*****************************************************************************
826  *                            Arguments checking
827  ****************************************************************************/
828 
829 	if (XDIM <= 0 || XDIM >= MAX_XDIM || YDIM <= 0 || YDIM >= MAX_YDIM) {
830 		fprintf(stderr,
831 				"Trying to retrieve width and height from input header\n");
832 		if (!ARG_INPUTTYPE)
833 			ARG_INPUTTYPE = 1;		/* pgm */
834 	}
835 
836 	if (ARG_QUALITY < 0 ) {
837 		ARG_QUALITY = 0;
838 	} else if (ARG_QUALITY >= (int) ME_ELEMENTS) {
839 		ARG_QUALITY = ME_ELEMENTS - 1;
840 	}
841 
842 	if (ARG_STARTFRAMENR < 0) {
843 		fprintf(stderr, "Bad starting frame number %d, cannot be negative\n", ARG_STARTFRAMENR);
844 		return(-1);
845 	}
846 
847 	if (ARG_PASS2) {
848 		if (ARG_PASS2 == ARG_PASS1) {
849 			fprintf(stderr, "Can't use the same statsfile for pass1 and pass2: %s\n", ARG_PASS2);
850 			return(-1);
851 		}
852 		  statsfile = fopen(ARG_PASS2, "rb");
853 		  if (statsfile == NULL) {
854 			  fprintf(stderr, "Couldn't open statsfile '%s'!\n", ARG_PASS2);
855 			  return (-1);
856 		  }
857 		  fclose(statsfile);
858 	}
859 
860 #ifdef XVID_AVI_OUTPUT
861 	if (ARG_AVIOUTPUTFILE == NULL && ARG_PACKED <= 1)
862 		ARG_PACKED = 0;
863 #endif
864 
865 	if (ARG_BITRATE < 0) {
866 		fprintf(stderr, "Bad bitrate %d, cannot be negative\n", ARG_BITRATE);
867 		return(-1);
868 	}
869 
870 	if (NUM_ZONES) {
871 		int i;
872 		sort_zones(ZONES, NUM_ZONES, &i);
873 	}
874 
875 	if (ARG_PAR > 5) {
876 		fprintf(stderr, "Bad PAR: %d. Must be [1..5] or width:height\n", ARG_PAR);
877 		return(-1);
878 	}
879 
880 	if (ARG_MAXFRAMENR == 0) {
881 		fprintf(stderr, "Wrong number of frames\n");
882 		return (-1);
883 	}
884 
885 	if (ARG_INPUTFILE != NULL) {
886 #if defined(XVID_AVI_INPUT)
887       if (strcmp(ARG_INPUTFILE+(strlen(ARG_INPUTFILE)-3), "avs")==0 ||
888           strcmp(ARG_INPUTFILE+(strlen(ARG_INPUTFILE)-3), "avi")==0 ||
889 		  ARG_INPUTTYPE==2)
890       {
891 		  PAVIFILE avi_in = NULL;
892 		  PAVISTREAM avi_in_stream = NULL;
893 		  PGETFRAME get_frame = NULL;
894 		  BITMAPINFOHEADER myBitmapInfoHeader;
895 		  AVISTREAMINFO avi_info;
896 		  FILE *avi_fp = fopen(ARG_INPUTFILE, "rb");
897 
898 		  AVIFileInit();
899 
900 		  if (avi_fp == NULL) {
901 			  fprintf(stderr, "Couldn't open file '%s'!\n", ARG_INPUTFILE);
902 			  return (-1);
903 		  }
904 		  fclose(avi_fp);
905 
906 		  if (AVIFileOpen(&avi_in, ARG_INPUTFILE, OF_READ, NULL) != AVIERR_OK) {
907 			  fprintf(stderr, "Can't open avi/avs file %s\n", ARG_INPUTFILE);
908 			  AVIFileExit();
909 			  return(-1);
910 		  }
911 
912 		  if (AVIFileGetStream(avi_in, &avi_in_stream, streamtypeVIDEO, 0) != AVIERR_OK) {
913 			  fprintf(stderr, "Can't open stream from file '%s'!\n", ARG_INPUTFILE);
914 			  AVIFileRelease(avi_in);
915 			  AVIFileExit();
916 			  return (-1);
917 		  }
918 
919 		  AVIFileRelease(avi_in);
920 
921 		  if(AVIStreamInfo(avi_in_stream, &avi_info, sizeof(AVISTREAMINFO)) != AVIERR_OK) {
922 			  fprintf(stderr, "Can't get stream info from file '%s'!\n", ARG_INPUTFILE);
923 			  AVIStreamRelease(avi_in_stream);
924 			  AVIFileExit();
925 			  return (-1);
926 		  }
927 
928 	      if (avi_info.fccHandler != MAKEFOURCC('Y', 'V', '1', '2')) {
929 			  LONG size;
930 			  fprintf(stderr, "Non YV12 input colorspace %c%c%c%c! Attempting conversion...\n",
931 				  (char)avi_info.fccHandler%256, (char)(avi_info.fccHandler>>8)%256, (char)(avi_info.fccHandler>>16)%256,
932 				  (char)(avi_info.fccHandler>>24)%256);
933 			  size = sizeof(myBitmapInfoHeader);
934 			  AVIStreamReadFormat(avi_in_stream, 0, &myBitmapInfoHeader, &size);
935 			  if (size==0)
936 				  fprintf(stderr, "AVIStreamReadFormat read 0 bytes.\n");
937 			  else {
938 				  fprintf(stderr, "AVIStreamReadFormat read %d bytes.\n", (int)size);
939 				  fprintf(stderr, "width = %d, height = %d, planes = %d\n", (int)myBitmapInfoHeader.biWidth,
940 					  (int)myBitmapInfoHeader.biHeight, myBitmapInfoHeader.biPlanes);
941 				  fprintf(stderr, "Compression = %c%c%c%c, %d\n",
942 					  (char)myBitmapInfoHeader.biCompression%256, (char)(myBitmapInfoHeader.biCompression>>8)%256,
943 					  (char)(myBitmapInfoHeader.biCompression>>16)%256, (char)(myBitmapInfoHeader.biCompression>>24)%256,
944 					  (int)myBitmapInfoHeader.biCompression);
945 				  fprintf(stderr, "Bits Per Pixel = %d\n", myBitmapInfoHeader.biBitCount);
946 				  myBitmapInfoHeader.biCompression = MAKEFOURCC('Y', 'V', '1', '2');
947 				  myBitmapInfoHeader.biBitCount = 12;
948 				  myBitmapInfoHeader.biSizeImage = (myBitmapInfoHeader.biWidth*myBitmapInfoHeader.biHeight)*3/2;
949 				  get_frame = AVIStreamGetFrameOpen(avi_in_stream, &myBitmapInfoHeader);
950 			  }
951 			  if (get_frame == NULL) {
952 				AVIStreamRelease(avi_in_stream);
953 				AVIFileExit();
954 				return (-1);
955 			  }
956 			  else {
957 				unsigned char *temp;
958 				fprintf(stderr, "AVIStreamGetFrameOpen successful.\n");
959 				temp = (unsigned char*)AVIStreamGetFrame(get_frame, 0);
960 				if (temp != NULL) {
961 					int i;
962 					for (i = 0; i < (int)((DWORD*)temp)[0]; i++) {
963 						fprintf(stderr, "%2d ", temp[i]);
964 					}
965 					fprintf(stderr, "\n");
966 				}
967 			  }
968 			  if (avi_info.fccHandler == MAKEFOURCC('D', 'I', 'B', ' ')) {
969 				  AVIStreamGetFrameClose(get_frame);
970 				  get_frame = NULL;
971 				  ARG_COLORSPACE = XVID_CSP_BGR | XVID_CSP_VFLIP;
972 			  }
973 		  }
974 
975           if (ARG_MAXFRAMENR<0)
976 			ARG_MAXFRAMENR = avi_info.dwLength-ARG_STARTFRAMENR;
977 		  else
978 			ARG_MAXFRAMENR = min(ARG_MAXFRAMENR, (int) (avi_info.dwLength-ARG_STARTFRAMENR));
979 
980 		  XDIM = avi_info.rcFrame.right - avi_info.rcFrame.left;
981 		  YDIM = avi_info.rcFrame.bottom - avi_info.rcFrame.top;
982 		  if (ARG_FRAMERATE==0) {
983 	 		ARG_FRAMERATE = (float) avi_info.dwRate / (float) avi_info.dwScale;
984 			ARG_DWRATE = avi_info.dwRate;
985 			ARG_DWSCALE = avi_info.dwScale;
986 		  }
987 
988 		  ARG_INPUTTYPE = 2;
989 
990 	  	  if (get_frame) AVIStreamGetFrameClose(get_frame);
991 		  if (avi_in_stream) AVIStreamRelease(avi_in_stream);
992 		  AVIFileExit();
993       }
994       else
995 #endif
996 		{
997 			FILE *in_file = fopen(ARG_INPUTFILE, "rb");
998 			if (in_file == NULL) {
999 				fprintf(stderr, "Error opening input file %s\n", ARG_INPUTFILE);
1000 				return (-1);
1001 			}
1002 #ifdef USE_APP_LEVEL_THREADING
1003 			{
1004 				int pos;
1005 				fseek(in_file, 0, SEEK_END); /* Determine input size */
1006 				pos = ftell(in_file);
1007 				ARG_MAXFRAMENR = pos / IMAGE_SIZE(XDIM, YDIM); /* PGM, header size ?? */
1008 			}
1009 #endif
1010 			fclose(in_file);
1011 		}
1012 	}
1013 
1014 	if (ARG_FRAMERATE <= 0) {
1015 		ARG_FRAMERATE = 25.00f; /* default value */
1016 	}
1017 
1018 	if (ARG_TARGETSIZE) {
1019 		if (ARG_MAXFRAMENR <= 0) {
1020 			fprintf(stderr, "Bad target size; number of input frames unknown\n");
1021 			goto release_all;
1022 		} else if (ARG_BITRATE) {
1023 				fprintf(stderr, "Parameter conflict: Do not specify both -bitrate and -size\n");
1024 				goto release_all;
1025 		} else
1026 			ARG_BITRATE = (int) (((ARG_TARGETSIZE * 8) / (ARG_MAXFRAMENR / ARG_FRAMERATE)) * 1024);
1027 	}
1028 
1029 		/* Set constant quant to default if no bitrate given for single pass */
1030 	if (ARG_SINGLE && (!ARG_BITRATE) && (!ARG_CQ))
1031 			ARG_CQ = DEFAULT_QUANT;
1032 
1033 		/* Init xvidcore */
1034     enc_gbl(use_assembler);
1035 
1036 #ifdef USE_APP_LEVEL_THREADING
1037 	if (ARG_INPUTFILE == NULL || strcmp(ARG_INPUTFILE, "stdin") == 0 ||
1038 	    ARG_NUM_APP_THREADS <= 1 || ARG_THREADS != 0 ||
1039 	    ARG_TIMECODEFILE != NULL || ARG_INPUTTYPE == 1)		/* TODO: PGM input */
1040 #endif /* Spawn just one encoder instance */
1041 	{
1042 		enc_sequence_data_t enc_data;
1043 		memset(&enc_data, 0, sizeof(enc_sequence_data_t));
1044 
1045 		if (!ARG_THREADS) ARG_THREADS = ARG_NUM_APP_THREADS;
1046 		ARG_NUM_APP_THREADS = 1;
1047 
1048 		enc_data.outfilename = ARG_OUTPUTFILE;
1049 		enc_data.outavifilename = ARG_AVIOUTPUTFILE;
1050 		enc_data.outmkvfilename = ARG_MKVOUTPUTFILE;
1051 		enc_data.statsfilename1 = ARG_PASS1;
1052 		enc_data.start_num = ARG_STARTFRAMENR;
1053 		enc_data.stop_num = ARG_MAXFRAMENR;
1054 
1055 			/* Encode input */
1056 		encode_sequence(&enc_data);
1057 
1058 			/* Copy back stats */
1059 		input_num = enc_data.input_num;
1060 		totalsize = enc_data.totalsize;
1061 		totalenctime = enc_data.totalenctime;
1062 		for (i=0; i < 3; i++) totalPSNR[i] = enc_data.totalPSNR[i];
1063 		memcpy(framestats, enc_data.framestats, sizeof(framestats));
1064 	}
1065 #ifdef USE_APP_LEVEL_THREADING
1066 	else { /* Split input into sequences and create multiple encoder instances */
1067 		int k;
1068 		void *status;
1069 		FILE *f_out = NULL, *f_stats = NULL;
1070 
1071 		enc_sequence_data_t enc_data[MAX_ENC_INSTANCES];
1072 		char outfile[MAX_ENC_INSTANCES][256];
1073 		char outavifile[MAX_ENC_INSTANCES][256];
1074 		char outmkvfile[MAX_ENC_INSTANCES][256];
1075 		char statsfilename[MAX_ENC_INSTANCES][256];
1076 
1077 		for (k = 0; k < MAX_ENC_INSTANCES; k++)
1078 			memset(&enc_data[k], 0, sizeof(enc_sequence_data_t));
1079 
1080 			/* Overwrite internal encoder threading */
1081 		if (ARG_NUM_APP_THREADS > MAX_ENC_INSTANCES) {
1082 			ARG_THREADS = (int) (ARG_NUM_APP_THREADS / MAX_ENC_INSTANCES);
1083 			ARG_NUM_APP_THREADS = MAX_ENC_INSTANCES;
1084 		}
1085 		else
1086 			ARG_THREADS = -1;
1087 
1088 		enc_data[0].outfilename = ARG_OUTPUTFILE;
1089 		enc_data[0].outavifilename = ARG_AVIOUTPUTFILE;
1090 		enc_data[0].outmkvfilename = ARG_MKVOUTPUTFILE;
1091 		enc_data[0].statsfilename1 = ARG_PASS1;
1092 		enc_data[0].start_num = ARG_STARTFRAMENR;
1093 		enc_data[0].stop_num = (ARG_MAXFRAMENR-ARG_STARTFRAMENR)/ARG_NUM_APP_THREADS;
1094 
1095 		for (k = 1; k < ARG_NUM_APP_THREADS; k++) {
1096 			if (ARG_OUTPUTFILE) {
1097 				sprintf(outfile[k], "%s.%03d", ARG_OUTPUTFILE, k);
1098 				enc_data[k].outfilename = outfile[k];
1099 			}
1100 			else
1101 				enc_data[k].outfilename = NULL;
1102 
1103 			if (ARG_AVIOUTPUTFILE) {
1104 				sprintf(outavifile[k], "%.*s_%03d.avi", strlen(ARG_AVIOUTPUTFILE) - 4, ARG_AVIOUTPUTFILE, k);
1105 				enc_data[k].outavifilename = outavifile[k];
1106 			}
1107 			else
1108 				enc_data[k].outavifilename = NULL;
1109 
1110 			if (ARG_MKVOUTPUTFILE) {
1111 				sprintf(outmkvfile[k], "%.*s_%03d.mkv", strlen(ARG_MKVOUTPUTFILE) - 4, ARG_MKVOUTPUTFILE, k);
1112 				enc_data[k].outmkvfilename = outmkvfile[k];
1113 			}
1114 			else
1115 				enc_data[k].outmkvfilename = NULL;
1116 
1117 			if (ARG_PASS1) {
1118 				sprintf(statsfilename[k], "%s.%03d", ARG_PASS1, k);
1119 				enc_data[k].statsfilename1 = statsfilename[k];
1120 			}
1121 			enc_data[k].start_num = (k*(ARG_MAXFRAMENR-ARG_STARTFRAMENR))/ARG_NUM_APP_THREADS;
1122 			enc_data[k].stop_num = ((k+1)*(ARG_MAXFRAMENR-ARG_STARTFRAMENR))/ARG_NUM_APP_THREADS;
1123 		}
1124 
1125 			/* Start multiple encoder threads in parallel */
1126 		for (k = 1; k < ARG_NUM_APP_THREADS; k++) {
1127 			pthread_create(&enc_data[k].handle, NULL, (void*)encode_sequence, (void*)&enc_data[k]);
1128 		}
1129 
1130 			/* Encode first sequence in this thread */
1131 		encode_sequence(&enc_data[0]);
1132 
1133 			/* Wait until encoder threads have finished */
1134 		for (k = 1; k < ARG_NUM_APP_THREADS; k++) {
1135 			pthread_join(enc_data[k].handle, &status);
1136 		}
1137 
1138 			/* Join encoder stats and encoder output files */
1139 		if (ARG_OUTPUTFILE)
1140 			f_out = fopen(enc_data[0].outfilename, "ab+");
1141 		if (ARG_PASS1)
1142 			f_stats = fopen(enc_data[0].statsfilename1, "ab+");
1143 
1144 		for (k = 0; k < ARG_NUM_APP_THREADS; k++) {
1145 				/* Join stats */
1146 			input_num += enc_data[k].input_num;
1147 			totalsize += enc_data[k].totalsize;
1148 			totalenctime = MAX(totalenctime, enc_data[k].totalenctime);
1149 
1150 			for (i=0; i < 3; i++) totalPSNR[i] += enc_data[k].totalPSNR[i];
1151 			for (i=0; i < 7; i++) {
1152 				int l;
1153 				framestats[i].count += enc_data[k].framestats[i].count;
1154 				framestats[i].size += enc_data[k].framestats[i].size;
1155 				for (l=0; l < 32; l++)
1156 					framestats[i].quants[l] += enc_data[k].framestats[i].quants[l];
1157 			}
1158 				/* Join output files */
1159 			if ((k > 0) && (f_out != NULL)) {
1160 				int ch;
1161 				FILE *f = fopen(enc_data[k].outfilename, "rb");
1162 				while((ch = fgetc(f)) != EOF) { fputc(ch, f_out); }
1163 				fclose(f);
1164 				remove(enc_data[k].outfilename);
1165 			}
1166 				/* Join first pass stats files */
1167 			if ((k > 0) && (f_stats != NULL)) {
1168 				char str[256];
1169 				FILE *f = fopen(enc_data[k].statsfilename1, "r");
1170 				while(fgets(str, sizeof(str), f) != NULL) {
1171 					if (str[0] != '#' && strlen(str) > 3)
1172 						fputs(str, f_stats);
1173 				}
1174 				fclose(f);
1175 				remove(enc_data[k].statsfilename1);
1176 			}
1177 		}
1178 		if (f_out) fclose(f_out);
1179 		if (f_stats) fclose(f_stats);
1180 	}
1181 #endif
1182 
1183 /*****************************************************************************
1184  *         Calculate totals and averages for output, print results
1185  ****************************************************************************/
1186 
1187  printf("\n");
1188 	printf("Tot: enctime(ms) =%7.2f,               length(bytes) = %7d\n",
1189 		   totalenctime, (int) totalsize);
1190 
1191 	if (input_num > 0) {
1192 		totalsize /= input_num;
1193 		totalenctime /= input_num;
1194 		totalPSNR[0] /= input_num;
1195 		totalPSNR[1] /= input_num;
1196 		totalPSNR[2] /= input_num;
1197 	} else {
1198 		totalsize = -1;
1199 		totalenctime = -1;
1200 	}
1201 
1202 	printf("Avg: enctime(ms) =%7.2f, fps =%7.2f, length(bytes) = %7d",
1203 		   totalenctime, 1000 / totalenctime, (int) totalsize);
1204    if (ARG_STATS) {
1205        printf(", psnr y = %2.2f, psnr u = %2.2f, psnr v = %2.2f",
1206     		  totalPSNR[0],totalPSNR[1],totalPSNR[2]);
1207 	}
1208 	printf("\n");
1209 	if (framestats[XVID_TYPE_IVOP].count) {
1210 		printf("I frames: %6d frames, size = %7d/%7d, quants = %2d / %.2f / %2d\n", \
1211 			framestats[XVID_TYPE_IVOP].count, framestats[XVID_TYPE_IVOP].size/framestats[XVID_TYPE_IVOP].count, \
1212 			framestats[XVID_TYPE_IVOP].size, minquant(framestats[XVID_TYPE_IVOP].quants), \
1213 			avgquant(framestats[XVID_TYPE_IVOP]), maxquant(framestats[XVID_TYPE_IVOP].quants));
1214 	}
1215 	if (framestats[XVID_TYPE_PVOP].count) {
1216 		printf("P frames: %6d frames, size = %7d/%7d, quants = %2d / %.2f / %2d\n", \
1217 			framestats[XVID_TYPE_PVOP].count, framestats[XVID_TYPE_PVOP].size/framestats[XVID_TYPE_PVOP].count, \
1218 			framestats[XVID_TYPE_PVOP].size, minquant(framestats[XVID_TYPE_PVOP].quants), \
1219 			avgquant(framestats[XVID_TYPE_PVOP]), maxquant(framestats[XVID_TYPE_PVOP].quants));
1220 	}
1221 	if (framestats[XVID_TYPE_BVOP].count) {
1222 		printf("B frames: %6d frames, size = %7d/%7d, quants = %2d / %.2f / %2d\n", \
1223 			framestats[XVID_TYPE_BVOP].count, framestats[XVID_TYPE_BVOP].size/framestats[XVID_TYPE_BVOP].count, \
1224 			framestats[XVID_TYPE_BVOP].size, minquant(framestats[XVID_TYPE_BVOP].quants), \
1225 			avgquant(framestats[XVID_TYPE_BVOP]), maxquant(framestats[XVID_TYPE_BVOP].quants));
1226 	}
1227 	if (framestats[XVID_TYPE_SVOP].count) {
1228 		printf("S frames: %6d frames, size = %7d/%7d, quants = %2d / %.2f / %2d\n", \
1229 			framestats[XVID_TYPE_SVOP].count, framestats[XVID_TYPE_SVOP].size/framestats[XVID_TYPE_SVOP].count, \
1230 			framestats[XVID_TYPE_SVOP].size, minquant(framestats[XVID_TYPE_SVOP].quants), \
1231 			avgquant(framestats[XVID_TYPE_SVOP]), maxquant(framestats[XVID_TYPE_SVOP].quants));
1232 	}
1233 	if (framestats[5].count) {
1234 		printf("N frames: %6d frames, size = %7d/%7d\n", \
1235 			framestats[5].count, framestats[5].size/framestats[5].count, \
1236 			framestats[5].size);
1237 	}
1238 
1239 
1240 /*****************************************************************************
1241  *                            Xvid PART  Stop
1242  ****************************************************************************/
1243 
1244   release_all:
1245 
1246 	return (0);
1247 }
1248 
1249 /*****************************************************************************
1250  *               Encode a sequence
1251  ****************************************************************************/
1252 
encode_sequence(enc_sequence_data_t * h)1253 void encode_sequence(enc_sequence_data_t *h) {
1254 
1255 	/* Internal structures (handles) for encoding */
1256 	void *enc_handle = NULL;
1257 
1258 	int start_num = h->start_num;
1259 	int stop_num = h->stop_num;
1260 	char *outfilename = h->outfilename;
1261 	char *outavifilename = h->outavifilename;
1262 	char *outmkvfilename = h->outmkvfilename;
1263 	float *totalPSNR = h->totalPSNR;
1264 
1265 	int input_num;
1266 	int totalsize;
1267 	double totalenctime = 0.;
1268 
1269 	unsigned char *mp4_buffer = NULL;
1270 	unsigned char *in_buffer = NULL;
1271 	unsigned char *out_buffer = NULL;
1272 
1273 	double enctime;
1274 
1275 	int result;
1276 	int output_num;
1277 	int m4v_size;
1278 	int key;
1279 	int stats_type;
1280 	int stats_quant;
1281 	int stats_length;
1282 	int fakenvop = 0;
1283 
1284 	FILE *in_file = stdin;
1285 	FILE *out_file = NULL;
1286 	FILE *time_file = NULL;
1287 
1288 	char filename[256];
1289 
1290 #ifdef XVID_MKV_OUTPUT
1291 	PMKVFILE myMKVFile = NULL;
1292 	PMKVSTREAM myMKVStream = NULL;
1293 	MKVSTREAMINFO myMKVStreamInfo;
1294 #endif
1295 #if defined(XVID_AVI_INPUT)
1296 	PAVIFILE avi_in = NULL;
1297 	PAVISTREAM avi_in_stream = NULL;
1298  	PGETFRAME get_frame = NULL;
1299 #else
1300 #define get_frame NULL
1301 #endif
1302 #if defined(XVID_AVI_OUTPUT)
1303 	int avierr;
1304 	PAVIFILE myAVIFile = NULL;
1305 	PAVISTREAM myAVIStream = NULL;
1306 	AVISTREAMINFO myAVIStreamInfo;
1307 #endif
1308 #if defined(XVID_AVI_INPUT) || defined(XVID_AVI_OUTPUT)
1309 	BITMAPINFOHEADER myBitmapInfoHeader;
1310 	if (ARG_NUM_APP_THREADS > 1)
1311 		CoInitializeEx(0, COINIT_MULTITHREADED);
1312 	AVIFileInit();
1313 #endif
1314 
1315 	if (ARG_INPUTFILE == NULL || strcmp(ARG_INPUTFILE, "stdin") == 0) {
1316 		in_file = stdin;
1317 	} else {
1318 #ifdef XVID_AVI_INPUT
1319       if (strcmp(ARG_INPUTFILE+(strlen(ARG_INPUTFILE)-3), "avs")==0 ||
1320           strcmp(ARG_INPUTFILE+(strlen(ARG_INPUTFILE)-3), "avi")==0 ||
1321 		  ARG_INPUTTYPE==2)
1322       {
1323 		  AVISTREAMINFO avi_info;
1324 		  FILE *avi_fp = fopen(ARG_INPUTFILE, "rb");
1325 
1326 		  if (avi_fp == NULL) {
1327 			  fprintf(stderr, "Couldn't open file '%s'!\n", ARG_INPUTFILE);
1328 			  return;
1329 		  }
1330 		  fclose(avi_fp);
1331 
1332 		  if (AVIFileOpen(&avi_in, ARG_INPUTFILE, OF_READ, NULL) != AVIERR_OK) {
1333 			  fprintf(stderr, "Can't open avi/avs file %s\n", ARG_INPUTFILE);
1334 			  AVIFileExit();
1335 			  return;
1336 		  }
1337 
1338 		  if (AVIFileGetStream(avi_in, &avi_in_stream, streamtypeVIDEO, 0) != AVIERR_OK) {
1339 			  fprintf(stderr, "Can't open stream from file '%s'!\n", ARG_INPUTFILE);
1340 			  AVIFileRelease(avi_in);
1341 			  AVIFileExit();
1342 			  return;
1343 		  }
1344 
1345 		  AVIFileRelease(avi_in);
1346 
1347 		  if(AVIStreamInfo(avi_in_stream, &avi_info, sizeof(AVISTREAMINFO)) != AVIERR_OK) {
1348 			  fprintf(stderr, "Can't get stream info from file '%s'!\n", ARG_INPUTFILE);
1349 			  AVIStreamRelease(avi_in_stream);
1350 			  AVIFileExit();
1351 			  return;
1352 		  }
1353 
1354 	      if (avi_info.fccHandler != MAKEFOURCC('Y', 'V', '1', '2')) {
1355 			  LONG size;
1356 			  fprintf(stderr, "Non YV12 input colorspace %c%c%c%c! Attempting conversion...\n",
1357 				  (char)avi_info.fccHandler%256, (char)(avi_info.fccHandler>>8)%256, (char)(avi_info.fccHandler>>16)%256,
1358 				  (char)(avi_info.fccHandler>>24)%256);
1359 			  size = sizeof(myBitmapInfoHeader);
1360 			  AVIStreamReadFormat(avi_in_stream, 0, &myBitmapInfoHeader, &size);
1361 			  if (size==0)
1362 				  fprintf(stderr, "AVIStreamReadFormat read 0 bytes.\n");
1363 			  else {
1364 				  fprintf(stderr, "AVIStreamReadFormat read %d bytes.\n", (int)size);
1365 				  fprintf(stderr, "width = %d, height = %d, planes = %d\n", (int)myBitmapInfoHeader.biWidth,
1366 					  (int)myBitmapInfoHeader.biHeight, myBitmapInfoHeader.biPlanes);
1367 				  fprintf(stderr, "Compression = %c%c%c%c, %d\n",
1368 					  (char)myBitmapInfoHeader.biCompression%256, (char)(myBitmapInfoHeader.biCompression>>8)%256,
1369 					  (char)(myBitmapInfoHeader.biCompression>>16)%256, (char)(myBitmapInfoHeader.biCompression>>24)%256,
1370 					  (int)myBitmapInfoHeader.biCompression);
1371 				  fprintf(stderr, "Bits Per Pixel = %d\n", myBitmapInfoHeader.biBitCount);
1372 				  myBitmapInfoHeader.biCompression = MAKEFOURCC('Y', 'V', '1', '2');
1373 				  myBitmapInfoHeader.biBitCount = 12;
1374 				  myBitmapInfoHeader.biSizeImage = (myBitmapInfoHeader.biWidth*myBitmapInfoHeader.biHeight)*3/2;
1375 				  get_frame = AVIStreamGetFrameOpen(avi_in_stream, &myBitmapInfoHeader);
1376 			  }
1377 			  if (get_frame == NULL) {
1378 				AVIStreamRelease(avi_in_stream);
1379 				AVIFileExit();
1380 				return;
1381 			  }
1382 			  else {
1383 				unsigned char *temp;
1384 				fprintf(stderr, "AVIStreamGetFrameOpen successful.\n");
1385 				temp = (unsigned char*)AVIStreamGetFrame(get_frame, 0);
1386 				if (temp != NULL) {
1387 					int i;
1388 					for (i = 0; i < (int)((DWORD*)temp)[0]; i++) {
1389 						fprintf(stderr, "%2d ", temp[i]);
1390 					}
1391 					fprintf(stderr, "\n");
1392 				}
1393 			  }
1394 			  if (avi_info.fccHandler == MAKEFOURCC('D', 'I', 'B', ' ')) {
1395 				  AVIStreamGetFrameClose(get_frame);
1396 				  get_frame = NULL;
1397 				  ARG_COLORSPACE = XVID_CSP_BGR | XVID_CSP_VFLIP;
1398 			  }
1399 		  }
1400     }
1401     else
1402 #endif
1403 		{
1404 			in_file = fopen(ARG_INPUTFILE, "rb");
1405 			if (in_file == NULL) {
1406 				fprintf(stderr, "Error opening input file %s\n", ARG_INPUTFILE);
1407 				return;
1408 			}
1409 		}
1410 	}
1411 
1412 	// This should be after the avi input opening stuff
1413 	if (ARG_TIMECODEFILE != NULL) {
1414 		time_file = fopen(ARG_TIMECODEFILE, "r");
1415 		if (time_file==NULL) {
1416 			fprintf(stderr, "Couldn't open timecode file '%s'!\n", ARG_TIMECODEFILE);
1417 			return;
1418 		}
1419 		else {
1420 			fscanf(time_file, "# timecode format v2\n");
1421 		}
1422 	}
1423 
1424 	if (ARG_INPUTTYPE==1) {
1425 #ifndef READ_PNM
1426 		if (read_pgmheader(in_file)) {
1427 #else
1428 		if (read_pnmheader(in_file)) {
1429 #endif
1430 			fprintf(stderr,
1431 					"Wrong input format, I want YUV encapsulated in PGM\n");
1432 			return;
1433 		}
1434 	}
1435 
1436 	/* Jump to the starting frame */
1437 	if (ARG_INPUTTYPE == 0) /* TODO: Other input formats ??? */
1438 		fseek(in_file, start_num*IMAGE_SIZE(XDIM, YDIM), SEEK_SET);
1439 
1440 
1441 		/* now we know the sizes, so allocate memory */
1442 	if (get_frame == NULL)
1443 	{
1444 		in_buffer = (unsigned char *) malloc(4*XDIM*YDIM);
1445 		if (!in_buffer)
1446 			goto free_all_memory;
1447 	}
1448 
1449 	/* this should really be enough memory ! */
1450 	mp4_buffer = (unsigned char *) malloc(IMAGE_SIZE(XDIM, YDIM) * 2);
1451 	if (!mp4_buffer)
1452 		goto free_all_memory;
1453 
1454 /*****************************************************************************
1455  *                            Xvid PART  Start
1456  ****************************************************************************/
1457 
1458 
1459 	result = enc_init(&enc_handle, h->statsfilename1, h->start_num);
1460 	if (result) {
1461 		fprintf(stderr, "Encore INIT problem, return value %d\n", result);
1462 		goto release_all;
1463 	}
1464 
1465 /*****************************************************************************
1466  *                            Main loop
1467  ****************************************************************************/
1468 
1469 	if (ARG_SAVEMPEGSTREAM) {
1470 
1471 		if (outfilename) {
1472 			if ((out_file = fopen(outfilename, "w+b")) == NULL) {
1473 				fprintf(stderr, "Error opening output file %s\n", outfilename);
1474 				goto release_all;
1475 			}
1476 		}
1477 
1478 #ifdef XVID_AVI_OUTPUT
1479 		if (outavifilename != NULL ) {
1480 			{
1481 				/* Open the .avi output then close it */
1482 				/* Resets the file size to 0, which AVIFile doesn't seem to do */
1483 				FILE *scrub;
1484 				if ((scrub = fopen(outavifilename, "w+b")) == NULL) {
1485 					fprintf(stderr, "Error opening output file %s\n", outavifilename);
1486 					goto release_all;
1487 				}
1488 				else
1489 					fclose(scrub);
1490 			}
1491 			memset(&myAVIStreamInfo, 0, sizeof(AVISTREAMINFO));
1492 			myAVIStreamInfo.fccType = streamtypeVIDEO;
1493 			myAVIStreamInfo.fccHandler = MAKEFOURCC('x', 'v', 'i', 'd');
1494 			myAVIStreamInfo.dwScale = ARG_DWSCALE;
1495 			myAVIStreamInfo.dwRate = ARG_DWRATE;
1496 			myAVIStreamInfo.dwLength = (h->stop_num - h->start_num);
1497 			myAVIStreamInfo.dwQuality = 10000;
1498 			SetRect(&myAVIStreamInfo.rcFrame, 0, 0, XDIM, YDIM);
1499 
1500 			if ((avierr=AVIFileOpen(&myAVIFile, outavifilename, OF_CREATE|OF_WRITE, NULL))) {
1501 				fprintf(stderr, "AVIFileOpen failed opening output file %s, error code %d\n", outavifilename, avierr);
1502 				goto release_all;
1503 			}
1504 
1505 			if ((avierr=AVIFileCreateStream(myAVIFile, &myAVIStream, &myAVIStreamInfo))) {
1506 				fprintf(stderr, "AVIFileCreateStream failed, error code %d\n", avierr);
1507 				goto release_all;
1508 			}
1509 
1510 			memset(&myBitmapInfoHeader, 0, sizeof(BITMAPINFOHEADER));
1511 			myBitmapInfoHeader.biHeight = YDIM;
1512 			myBitmapInfoHeader.biWidth = XDIM;
1513 			myBitmapInfoHeader.biPlanes = 1;
1514 			myBitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
1515 			myBitmapInfoHeader.biCompression = MAKEFOURCC('X', 'V', 'I', 'D');
1516 			myBitmapInfoHeader.biBitCount = 12;
1517 			myBitmapInfoHeader.biSizeImage = 6*XDIM*YDIM;
1518 			if ((avierr=AVIStreamSetFormat(myAVIStream, 0, &myBitmapInfoHeader, sizeof(BITMAPINFOHEADER)))) {
1519 				fprintf(stderr, "AVIStreamSetFormat failed, error code %d\n", avierr);
1520 				goto release_all;
1521 			}
1522 		}
1523 #endif
1524 #ifdef XVID_MKV_OUTPUT
1525 		if (outmkvfilename != NULL) {
1526 			{
1527 				/* Open the .mkv output then close it */
1528 				/* Just to make sure we can write to it */
1529 				FILE *scrub;
1530 				if ((scrub = fopen(outmkvfilename, "w+b")) == NULL) {
1531 					fprintf(stderr, "Error opening output file %s\n", outmkvfilename);
1532 					goto release_all;
1533 				}
1534 				else
1535 					fclose(scrub);
1536 			}
1537 
1538 			MKVFileOpen(&myMKVFile, outmkvfilename, OF_CREATE|OF_WRITE, NULL);
1539 			if (ARG_PAR) {
1540 				myMKVStreamInfo.display_height = YDIM*height_ratios[ARG_PAR];
1541 				myMKVStreamInfo.display_width = XDIM*width_ratios[ARG_PAR];
1542 			}
1543 			else {
1544 				myMKVStreamInfo.display_height = YDIM*ARG_PARHEIGHT;
1545 				myMKVStreamInfo.display_width = XDIM*ARG_PARWIDTH;
1546 			}
1547 			myMKVStreamInfo.height = YDIM;
1548 			myMKVStreamInfo.width = XDIM;
1549 			myMKVStreamInfo.framerate = ARG_DWRATE;
1550 			myMKVStreamInfo.framescale = ARG_DWSCALE;
1551 			myMKVStreamInfo.length = (h->stop_num - h->start_num);
1552 			MKVFileCreateStream(myMKVFile, &myMKVStream, &myMKVStreamInfo);
1553 		}
1554 #endif
1555 	} else {
1556 		out_file = NULL;
1557 	}
1558 
1559 
1560 /*****************************************************************************
1561  *                       Encoding loop
1562  ****************************************************************************/
1563 
1564 	totalsize = 0;
1565 
1566 	result = 0;
1567 
1568 	input_num = 0;                      /* input frame counter */
1569 	output_num = start_num;             /* output frame counter */
1570 
1571 	do {
1572 
1573 		char *type;
1574 		int sse[3];
1575 
1576 		if ((input_num+start_num) >= stop_num && stop_num > 0) {
1577 			result = 1;
1578 		}
1579 
1580 		if (!result) {
1581 #ifdef XVID_AVI_INPUT
1582 			if (ARG_INPUTTYPE==2) {
1583 				/* read avs/avi data (YUV-format) */
1584 				if (get_frame != NULL) {
1585 					in_buffer = (unsigned char*)AVIStreamGetFrame(get_frame, input_num+start_num);
1586 					if (in_buffer == NULL)
1587 						result = 1;
1588 					else
1589 						in_buffer += ((DWORD*)in_buffer)[0];
1590 				} else {
1591 					if (AVIStreamRead(avi_in_stream, input_num + start_num, 1, in_buffer, 4 * XDIM*YDIM, NULL, NULL) != AVIERR_OK)
1592 						result = 1;
1593 				}
1594 			} else
1595 #endif
1596 			if (ARG_INPUTTYPE==1) {
1597 				/* read PGM data (YUV-format) */
1598 #ifndef READ_PNM
1599 				result = read_pgmdata(in_file, in_buffer);
1600 #else
1601 				result = read_pnmdata(in_file, in_buffer);
1602 #endif
1603 			} else {
1604 				/* read raw data (YUV-format) */
1605 				result = read_yuvdata(in_file, in_buffer);
1606 			}
1607 		}
1608 
1609 /*****************************************************************************
1610  *                       Encode and decode this frame
1611  ****************************************************************************/
1612 
1613 		if ((unsigned int)(input_num+start_num) >= (unsigned int)(stop_num-1) && ARG_MAXBFRAMES) {
1614 			stats_type = XVID_TYPE_PVOP;
1615 		}
1616 		else
1617 			stats_type = XVID_TYPE_AUTO;
1618 
1619 		enctime = msecond();
1620 		m4v_size =
1621 			enc_main(enc_handle, !result ? in_buffer : 0, mp4_buffer, &key, &stats_type,
1622 					 &stats_quant, &stats_length, sse, input_num);
1623 		enctime = msecond() - enctime;
1624 
1625 		/* Write the Frame statistics */
1626 
1627 		if (stats_type > 0) {	/* !XVID_TYPE_NOTHING */
1628 			switch (stats_type) {
1629 				case XVID_TYPE_IVOP:
1630 					type = "I";
1631 					break;
1632 				case XVID_TYPE_PVOP:
1633 					type = "P";
1634 					break;
1635 				case XVID_TYPE_BVOP:
1636 					type = "B";
1637 					if (ARG_PACKED)
1638 						fakenvop = 1;
1639 					break;
1640 				case XVID_TYPE_SVOP:
1641 					type = "S";
1642 					break;
1643 				default:
1644 					type = "U";
1645 					break;
1646 			}
1647 
1648 			if (stats_length > 8) {
1649 				h->framestats[stats_type].count++;
1650 				h->framestats[stats_type].quants[stats_quant]++;
1651 				h->framestats[stats_type].size += stats_length;
1652 			}
1653 			else {
1654 				h->framestats[5].count++;
1655 				h->framestats[5].quants[stats_quant]++;
1656 				h->framestats[5].size += stats_length;
1657 			}
1658 
1659 #define SSE2PSNR(sse, width, height) ((!(sse))?0.0f : 48.131f - 10*(float)log10((float)(sse)/((float)((width)*(height)))))
1660 
1661 			if (ARG_PROGRESS == 0) {
1662 				printf("%5d: key=%i, time= %6.0f, len= %7d", !result ? (input_num+start_num) : -1,
1663 					key, (float) enctime, (int) m4v_size);
1664 				printf(" | type=%s, quant= %2d, len= %7d", type, stats_quant,
1665 				   stats_length);
1666 
1667 
1668 				if (ARG_STATS) {
1669 					printf(", psnr y = %2.2f, psnr u = %2.2f, psnr v = %2.2f",
1670 						SSE2PSNR(sse[0], XDIM, YDIM), SSE2PSNR(sse[1], XDIM / 2, YDIM / 2),
1671 						SSE2PSNR(sse[2], XDIM / 2, YDIM / 2));
1672 				}
1673 				printf("\n");
1674 			} else {
1675 				if ((input_num) % ARG_PROGRESS == 1) {
1676 					if (stop_num > 0) {
1677 						fprintf(stderr, "\r%7d frames(%3d%%) encoded, %6.2f fps, Average Bitrate = %5.0fkbps", \
1678 							(ARG_NUM_APP_THREADS*input_num), (input_num)*100/(stop_num-start_num), (ARG_NUM_APP_THREADS*input_num)*1000/(totalenctime), \
1679 							((((totalsize)/1000)*ARG_FRAMERATE)*8)/(input_num));
1680 					} else {
1681 						fprintf(stderr, "\r%7d frames encoded, %6.2f fps, Average Bitrate = %5.0fkbps", \
1682 							(ARG_NUM_APP_THREADS*input_num), (ARG_NUM_APP_THREADS*input_num)*1000/(totalenctime), \
1683 							((((totalsize)/1000)*ARG_FRAMERATE)*8)/(input_num));
1684 					}
1685 				}
1686 			}
1687 
1688 			if (ARG_STATS) {
1689 				totalPSNR[0] += SSE2PSNR(sse[0], XDIM, YDIM);
1690 				totalPSNR[1] += SSE2PSNR(sse[1], XDIM/2, YDIM/2);
1691 				totalPSNR[2] += SSE2PSNR(sse[2], XDIM/2, YDIM/2);
1692 			}
1693 #undef SSE2PSNR
1694 		}
1695 
1696 		if (m4v_size < 0)
1697 			break;
1698 
1699 		/* Update encoding time stats */
1700 		totalenctime += enctime;
1701 		totalsize += m4v_size;
1702 
1703 /*****************************************************************************
1704  *                       Save stream to file
1705  ****************************************************************************/
1706 
1707 		if (m4v_size > 0 && ARG_SAVEMPEGSTREAM) {
1708 			char timecode[50];
1709 
1710 			if (time_file != NULL) {
1711 				if (fscanf(time_file, "%s\n", timecode) != 1) {
1712 					fprintf(stderr, "Error reading timecode file, frame %d\n", output_num);
1713 					goto release_all;
1714 				}
1715 			}
1716 			else
1717 				sprintf(timecode, "%f", ((double)ARG_DWSCALE/ARG_DWRATE)*1000*(output_num-start_num));
1718 
1719 			/* Save single files */
1720 			if (ARG_SAVEINDIVIDUAL) {
1721 				FILE *out;
1722 				sprintf(filename, "%sframe%05d.m4v", filepath, output_num);
1723 				out = fopen(filename, "w+b");
1724 				fwrite(mp4_buffer, m4v_size, 1, out);
1725 				fclose(out);
1726 			}
1727 #ifdef XVID_AVI_OUTPUT
1728 			if (outavifilename && myAVIStream) {
1729 				int output_frame;
1730 
1731 				if (time_file == NULL)
1732 					output_frame = (output_num-start_num);
1733 				else {
1734 					output_frame = (int)(atof(timecode)/1000/((double)ARG_DWSCALE/ARG_DWRATE)+.5);
1735 				}
1736 				if (AVIStreamWrite(myAVIStream, output_frame, 1, mp4_buffer, m4v_size, key ? AVIIF_KEYFRAME : 0, NULL, NULL)) {
1737 					fprintf(stderr, "AVIStreamWrite failed writing frame %d\n", output_num);
1738 					goto release_all;
1739 				}
1740 			}
1741 #endif
1742 
1743 				if (key && ARG_PACKED)
1744 					removedivxp((char*)mp4_buffer, m4v_size);
1745 
1746 				/* Save ES stream */
1747 				if (outfilename && out_file && !(fakenvop && m4v_size <= 8)) {
1748 						fwrite(mp4_buffer, 1, m4v_size, out_file);
1749 				}
1750 #ifdef XVID_MKV_OUTPUT
1751 				if (outmkvfilename && myMKVStream) {
1752 					MKVStreamWrite(myMKVStream, atof(timecode), 1, (ARG_PACKED && fakenvop && (m4v_size <= 8)) ? NULL : mp4_buffer, m4v_size, key ? AVIIF_KEYFRAME : 0, NULL, NULL);
1753 				}
1754 #endif
1755 
1756 			output_num++;
1757 			if (stats_type != XVID_TYPE_BVOP)
1758 				fakenvop=0;
1759 		}
1760 
1761 		if (!result)
1762 			(input_num)++;
1763 
1764 		/* Read the header if it's pgm stream */
1765 		if (!result && (ARG_INPUTTYPE==1))
1766 #ifndef READ_PNM
1767  			result = read_pgmheader(in_file);
1768 #else
1769  			result = read_pnmheader(in_file);
1770 #endif
1771 	} while (1);
1772 
1773 
1774   release_all:
1775 
1776   h->input_num = input_num;
1777   h->totalenctime = totalenctime;
1778   h->totalsize = totalsize;
1779 
1780 #ifdef XVID_AVI_INPUT
1781 	if (get_frame) AVIStreamGetFrameClose(get_frame);
1782 	if (avi_in_stream) AVIStreamRelease(avi_in_stream);
1783 #endif
1784 
1785 	if (enc_handle) {
1786 		result = enc_stop(enc_handle);
1787 		if (result)
1788 			fprintf(stderr, "Encore RELEASE problem return value %d\n",
1789 					result);
1790 	}
1791 
1792 	if (in_file)
1793 		fclose(in_file);
1794 	if (out_file)
1795 		fclose(out_file);
1796 	if (time_file)
1797 		fclose(time_file);
1798 
1799 #ifdef XVID_AVI_OUTPUT
1800 	if (myAVIStream) AVIStreamRelease(myAVIStream);
1801 	if (myAVIFile) AVIFileRelease(myAVIFile);
1802 #endif
1803 #ifdef XVID_MKV_OUTPUT
1804 	if (myMKVStream) MKVStreamRelease(myMKVStream);
1805 	if (myMKVFile) MKVFileRelease(myMKVFile);
1806 #endif
1807 #if defined(XVID_AVI_INPUT) || defined(XVID_AVI_OUTPUT)
1808 	AVIFileExit();
1809 #endif
1810 
1811   free_all_memory:
1812 	if (out_buffer)
1813 	    free(out_buffer);
1814 	if (mp4_buffer)
1815 	    free(mp4_buffer);
1816 	if ((in_buffer) && (get_frame == NULL))
1817 	    free(in_buffer);
1818 }
1819 
1820 /*****************************************************************************
1821  *                        "statistical" functions
1822  *
1823  *  these are not needed for encoding or decoding, but for measuring
1824  *  time and quality, there in nothing specific to Xvid in these
1825  *
1826  *****************************************************************************/
1827 
1828 /* Return time elapsed time in miliseconds since the program started */
1829 static double
1830 msecond()
1831 {
1832 #ifndef WIN32
1833 	struct timeval tv;
1834 
1835 	gettimeofday(&tv, 0);
1836 	return (tv.tv_sec * 1.0e3 + tv.tv_usec * 1.0e-3);
1837 #else
1838 	clock_t clk;
1839 
1840 	clk = clock();
1841 	return (clk * 1000.0 / CLOCKS_PER_SEC);
1842 #endif
1843 }
1844 
1845 int
1846 gcd(int a, int b)
1847 {
1848 	int r ;
1849 
1850 	if (b > a) {
1851 		r = a;
1852 		a = b;
1853 		b = r;
1854 	}
1855 
1856 	while ((r = a % b)) {
1857 		a = b;
1858 		b = r;
1859 	}
1860 	return b;
1861 }
1862 
1863 int minquant(int quants[32])
1864 {
1865 	int i = 1;
1866 	while (quants[i] == 0) {
1867 		i++;
1868 	}
1869 	return i;
1870 }
1871 
1872 int maxquant(int quants[32])
1873 {
1874 	int i = 31;
1875 	while (quants[i] == 0) {
1876 		i--;
1877 	}
1878 	return i;
1879 }
1880 
1881 double avgquant(frame_stats_t frame)
1882 {
1883 	double avg=0;
1884 	int i;
1885 	for (i=1; i < 32; i++) {
1886 		avg += frame.quants[i]*i;
1887 	}
1888 	avg /= frame.count;
1889 	return avg;
1890 }
1891 
1892 /*****************************************************************************
1893  *                             Usage message
1894  *****************************************************************************/
1895 
1896 static void
1897 usage()
1898 {
1899 	fprintf(stderr, "xvid_encraw built at %s on %s\n", __TIME__, __DATE__);
1900 	fprintf(stderr, "Usage : xvid_encraw [OPTIONS]\n\n");
1901 	fprintf(stderr, "Input options:\n");
1902 	fprintf(stderr, " -i      string  : input filename (stdin)\n");
1903 #ifdef XVID_AVI_INPUT
1904 	fprintf(stderr, " -type   integer : input data type (yuv=0, pgm=1, avi/avs=2) (");
1905 #else
1906 	fprintf(stderr, " -type   integer : input data type (yuv=0, pgm=1) (");
1907 #endif
1908 	fprintf(stderr, "%d)\n", ARG_INPUTTYPE);
1909 	fprintf(stderr, " -w      integer : frame width ([1.%d])\n", MAX_XDIM);
1910 	fprintf(stderr, " -h      integer : frame height ([1.%d])\n", MAX_YDIM);
1911 	fprintf(stderr, " -csp    string  : colorspace of raw input file i420%s, yv12%s\n", (ARG_COLORSPACE == XVID_CSP_I420)?" (default)":"", (ARG_COLORSPACE == XVID_CSP_YV12)?" (default)":"");
1912 	fprintf(stderr, " -frames integer : number of frames to encode (");
1913 	if (ARG_MAXFRAMENR==-1)
1914 		fprintf(stderr, "all)");
1915 	else
1916 		fprintf(stderr, "%d)", ARG_MAXFRAMENR);
1917 	fprintf(stderr, "\n\n");
1918 	fprintf(stderr, "Output options:\n");
1919 	fprintf(stderr, " -dump           : save decoder output\n");
1920 	fprintf(stderr, " -save           : save an Elementary Stream file per frame\n");
1921 	fprintf(stderr, " -o      string  : save an Elementary Stream for the complete sequence\n");
1922 #ifdef XVID_AVI_OUTPUT
1923 	fprintf(stderr, " -avi    string  : save an AVI file for the complete sequence\n");
1924 #endif
1925 #ifdef XVID_MKV_OUTPUT
1926 	fprintf(stderr, " -mkv    string  : save a MKV file for the complete sequence\n");
1927 #endif
1928 	fprintf(stderr, "\n");
1929 	fprintf(stderr, "Rate control options:\n");
1930 	fprintf(stderr, " -framerate        float      : target framerate (auto)\n");
1931 	fprintf(stderr,	" -bitrate          [integer]  : target bitrate in kbps (%d)\n", DEFAULT_BITRATE/1000);
1932 	fprintf(stderr, " -size             integer    : target size in kilobytes\n");
1933 	fprintf(stderr,	" -single                      : single pass mode%s\n", (ARG_SINGLE)?" (default)":"");
1934 	fprintf(stderr, " -cq               float      : single pass constant quantizer\n");
1935 	fprintf(stderr, " -pass1            [filename] : twopass mode (first pass)\n");
1936 	fprintf(stderr, " -full1pass                   : perform full quality first pass (disabled)\n");
1937 	fprintf(stderr,	" -pass2            [filename] : twopass mode (2nd pass)\n");
1938 	fprintf(stderr, " -max_key_interval integer    : maximum keyframe interval (%d)\n", ARG_MAXKEYINTERVAL);
1939 	fprintf(stderr, " -zones            [zones]    : use `-help zones' for usage guidelines\n");
1940 	fprintf(stderr,	" -zq     starting_frame float : bitrate zone; quant\n");
1941 	fprintf(stderr,	" -zw     starting_frame float : bitrate zone; weight\n");
1942 	fprintf(stderr, "\n");
1943 	fprintf(stderr, "Single Pass options:\n");
1944 	fprintf(stderr, " -reaction         integer    : reaction delay factor (%d)\n", ARG_REACTION);
1945 	fprintf(stderr, " -averaging        integer    : averaging period (%d)\n", ARG_AVERAGING);
1946 	fprintf(stderr, " -smoother         integer    : smoothing buffer (%d)\n", ARG_SMOOTHER);
1947 	fprintf(stderr, "\n");
1948 	fprintf(stderr, "Second Pass options:\n");
1949 	fprintf(stderr, " -kboost           integer    : I frame boost (%d)\n", ARG_KBOOST);
1950 	fprintf(stderr, " -kthresh          integer    : I frame reduction threshold (%d)\n", ARG_KTHRESH);
1951 	fprintf(stderr, " -kreduction       integer    : I frame reduction amount (%d)\n", ARG_KREDUCTION);
1952 	fprintf(stderr, " -ostrength        integer    : overflow control strength (%d)\n", ARG_OVERSTRENGTH);
1953 	fprintf(stderr, " -oimprove         integer    : max overflow improvement (%d)\n", ARG_OVERIMPROVE);
1954 	fprintf(stderr, " -odegrade         integer    : max overflow degradation (%d)\n", ARG_OVERDEGRADE);
1955 	fprintf(stderr, " -chigh            integer    : high bitrate scenes degradation (%d)\n", ARG_CHIGH);
1956 	fprintf(stderr, " -clow             integer    : low bitrate scenes improvement (%d)\n", ARG_CLOW);
1957 	fprintf(stderr, " -overhead         integer    : container frame overhead (%d)\n", ARG_OVERHEAD);
1958 	fprintf(stderr, " -vbvsize          integer    : use vbv buffer size\n");
1959 	fprintf(stderr, " -vbvmax           integer    : vbv max bitrate\n");
1960 	fprintf(stderr, " -vbvpeak          integer    : vbv peak bitrate over 1 second\n");
1961 	fprintf(stderr, "\n");
1962 	fprintf(stderr, "BFrames options:\n");
1963 	fprintf(stderr, " -max_bframes      integer    : max bframes (%d)\n", ARG_MAXBFRAMES);
1964 	fprintf(stderr,	" -bquant_ratio     integer    : bframe quantizer ratio (%d)\n", ARG_BQRATIO);
1965 	fprintf(stderr,	" -bquant_offset    integer    : bframe quantizer offset (%d)\n", ARG_BQOFFSET);
1966 	fprintf(stderr, "\n");
1967 	fprintf(stderr, "Other options\n");
1968 	if (ARG_USE_ASSEMBLER)
1969 		fprintf(stderr, " -noasm                       : do not use assembly optimized code (use)\n");
1970 	else
1971 		fprintf(stderr, " -asm                         : use assembly optimized code (don't use)\n");
1972 	if (ARG_TURBO)
1973 		fprintf(stderr, " -noturbo                     : do not use turbo presets for higher encoding speed (use)\n");
1974 	else
1975 		fprintf(stderr, " -turbo                       : use turbo presets for higher encoding speed (don't use)\n");
1976 	fprintf(stderr, " -quality          integer    : quality ([0..%d]) (%d)\n", ME_ELEMENTS - 1, ARG_QUALITY);
1977 	fprintf(stderr, " -vhqmode          integer    : level of R-D optimizations ([0..4]) (%d)\n", ARG_VHQMODE);
1978 	if (ARG_BVHQ)
1979 		fprintf(stderr, " -nobvhq                      : do not use R-D optimizations for B-frames (use)\n");
1980 	else
1981 		fprintf(stderr, " -bvhq                        : use R-D optimizations for B-frames (don't use)\n");
1982 	fprintf(stderr, " -metric           integer    : distortion metric for R-D opt (PSNR:0, PSNRHVSM:1) (%d)\n", ARG_QMETRIC);
1983 	if (ARG_QPEL)
1984 		fprintf(stderr, " -noqpel                      : do not use quarter pixel ME (use)\n");
1985 	else
1986 		fprintf(stderr, " -qpel                        : use quarter pixel ME (don't use)\n");
1987 	if (ARG_GMC)
1988 		fprintf(stderr, " -nogmc                       : do not use global motion compensation (use)\n");
1989 	else
1990 		fprintf(stderr, " -gmc                         : use global motion compensation (don't use)\n");
1991 	fprintf(stderr, " -qtype            integer    : quantization type (H263:0, MPEG4:1) (%d)\n", ARG_QTYPE);
1992 	fprintf(stderr, " -qmatrix          filename   : use custom MPEG4 quantization matrix\n");
1993 	fprintf(stderr, " -interlaced       [integer]  : interlaced encoding (BFF:1, TFF:2) (%d)\n", DEFAULT_INTERLACING);
1994 	if (ARG_PACKED)
1995 		fprintf(stderr, " -nopacked                    : disable packed B-frames mode (enabled)\n");
1996 	else
1997 		fprintf(stderr, " -packed                      : enable packed B-frames mode (disabled)\n");
1998 	if (ARG_CLOSED_GOP)
1999 		fprintf(stderr, " -noclosed_gop                : disable closed GOP mode (enabled)\n");
2000 	else
2001 		fprintf(stderr, " -closed_gop                  : enable closed GOP mode (disabled)\n");
2002 	fprintf(stderr, " -masking          [integer]  : HVS masking mode (None:0, Lumi:1, Variance:2) (%d)\n", ARG_LUMIMASKING);
2003 	if (ARG_STATS)
2004 		fprintf(stderr, " -nostats                     : do not print stats about encoded frames (print)\n");
2005 	else
2006 		fprintf(stderr, " -stats                       : print stats about encoded frames (don't print)\n");
2007 	fprintf(stderr, " -ssim             [integer]  : print ssim for every frame (accurate: 0 fast: 4) (%d)\n", DEFAULT_SSIM);
2008 	fprintf(stderr, " -ssim_file        filename   : output the ssim stats into a file\n");
2009 	if (ARG_PSNRHVSM)
2010 		fprintf(stderr, " -nopsnrhvsm                  : do not print PSNRHVSM metric for every frame (print)\n");
2011 	else
2012 		fprintf(stderr, " -psnrhvsm                    : print PSNRHVSM metric for every frame (don't print)\n");
2013 	fprintf(stderr, " -debug            integer    : activate xvidcore internal debugging output (don't activate)\n");
2014 	if (ARG_VOPDEBUG)
2015 		fprintf(stderr, " -novop_debug                 : do not print debug info directly into encoded frames (print)\n");
2016 	else
2017 		fprintf(stderr, " -vop_debug                   : print some info directly into encoded frames (don't print)\n");
2018 	if (ARG_CHROMAME)
2019 		fprintf(stderr, " -nochromame                  : disable chroma motion estimation (enabled)\n");
2020 	else
2021 		fprintf(stderr, " -chromame                    : enable chroma motion estimation (disabled)\n");
2022 	if (ARG_TRELLIS)
2023 		fprintf(stderr, " -notrellis                   : disable trellis quantization (enabled)\n");
2024 	else
2025 		fprintf(stderr, " -trellis                     : enable trellis quantization (disabled)\n");
2026 	fprintf(stderr, " -imin             integer    : minimum I Quantizer (1..31) (%d)\n", ARG_QUANTS[0]);
2027 	fprintf(stderr, " -imax             integer    : maximum I quantizer (1..31) (%d)\n", ARG_QUANTS[1]);
2028 	fprintf(stderr, " -bmin             integer    : minimum B Quantizer (1..31) (%d)\n", ARG_QUANTS[4]);
2029 	fprintf(stderr, " -bmax             integer    : maximum B quantizer (1..31) (%d)\n", ARG_QUANTS[5]);
2030 	fprintf(stderr, " -pmin             integer    : minimum P Quantizer (1..31) (%d)\n", ARG_QUANTS[2]);
2031 	fprintf(stderr, " -pmax             integer    : maximum P quantizer (1..31) (%d)\n", ARG_QUANTS[3]);
2032 	fprintf(stderr, " -drop             integer    : frame Drop Ratio (0..100) (%d)\n", ARG_FRAMEDROP);
2033 	fprintf(stderr, " -start            integer    : starting frame number (%d)\n", ARG_STARTFRAMENR);
2034 	fprintf(stderr, " -threads          integer    : number of threads (auto)\n");
2035 	fprintf(stderr, " -slices           integer    : number of slices (%d)\n", ARG_SLICES);
2036 	fprintf(stderr, " -progress         [integer]  : show progress updates every n frames (%d)\n", DEFAULT_PROGRESS);
2037 	fprintf(stderr, " -par       integer[:integer] : set Pixel Aspect Ratio (%d)\n", ARG_PAR);
2038 	fprintf(stderr, "                                1 = 1:1\n");
2039 	fprintf(stderr, "                                2 = 12:11 (4:3 PAL)\n");
2040 	fprintf(stderr, "                                3 = 10:11 (4:3 NTSC)\n");
2041 	fprintf(stderr, "                                4 = 16:11 (16:9 PAL)\n");
2042 	fprintf(stderr, "                                5 = 40:33 (16:9 NTSC)\n");
2043 	fprintf(stderr, "                            other = custom (width:height)\n");
2044 	fprintf(stderr, " -help                        : print this help message\n");
2045 	fprintf(stderr, "\n");
2046 	fprintf(stderr, "NB: You can define up to %d zones via both the -zones and the -z[qw] options as needed.\n", MAX_ZONES);
2047 }
2048 
2049 /*****************************************************************************
2050  *                       Input and output functions
2051  *
2052  *      the are small and simple routines to read and write PGM and YUV
2053  *      image. It's just for convenience, again nothing specific to Xvid
2054  *
2055  *****************************************************************************/
2056 
2057 #ifndef READ_PNM
2058 static int
2059 read_pgmheader(FILE * handle)
2060 {
2061 	int bytes, xsize, ysize, depth;
2062 	char dummy[2];
2063 
2064 	bytes = (int) fread(dummy, 1, 2, handle);
2065 
2066 	if ((bytes < 2) || (dummy[0] != 'P') || (dummy[1] != '5'))
2067 		return (1);
2068 
2069 	fscanf(handle, "%d %d %d", &xsize, &ysize, &depth);
2070 	fread(&dummy, 1, 1, handle);
2071 	if ((xsize > 4096) || (ysize > 4096*3/2) || (depth != 255)) {
2072 		fprintf(stderr, "%d %d %d\n", xsize, ysize, depth);
2073 		return (2);
2074 	}
2075 	if ((XDIM == 0) || (YDIM == 0)) {
2076 		XDIM = xsize;
2077 		YDIM = ysize * 2 / 3;
2078 	}
2079 
2080 	return (0);
2081 }
2082 
2083 static int
2084 read_pgmdata(FILE * handle,
2085 			 unsigned char *image)
2086 {
2087 	int i;
2088 
2089 	unsigned char *y = image;
2090 	unsigned char *u = image + XDIM * YDIM;
2091 	unsigned char *v = image + XDIM * YDIM + XDIM / 2 * YDIM / 2;
2092 
2093 	/* read Y component of picture */
2094 	fread(y, 1, XDIM * YDIM, handle);
2095 
2096 	for (i = 0; i < YDIM / 2; i++) {
2097 		/* read U */
2098 		fread(u, 1, XDIM / 2, handle);
2099 
2100 		/* read V */
2101 		fread(v, 1, XDIM / 2, handle);
2102 
2103 		/* Update pointers */
2104 		u += XDIM / 2;
2105 		v += XDIM / 2;
2106 	}
2107 
2108 	return (0);
2109 }
2110 #else
2111 static int
2112 read_pnmheader(FILE * handle)
2113 {
2114 	int bytes, xsize, ysize, depth;
2115 	char dummy[2];
2116 
2117 	bytes = fread(dummy, 1, 2, handle);
2118 
2119 	if ((bytes < 2) || (dummy[0] != 'P') || (dummy[1] != '6'))
2120 		return (1);
2121 
2122 	fscanf(handle, "%d %d %d", &xsize, &ysize, &depth);
2123 	if ((xsize > 1440) || (ysize > 2880) || (depth != 255)) {
2124 		fprintf(stderr, "%d %d %d\n", xsize, ysize, depth);
2125 		return (2);
2126 	}
2127 
2128 	XDIM = xsize;
2129 	YDIM = ysize;
2130 
2131 	return (0);
2132 }
2133 
2134 static int
2135 read_pnmdata(FILE * handle,
2136 			 unsigned char *image)
2137 {
2138 	int i;
2139 	char dummy;
2140 
2141 	/* read Y component of picture */
2142 	fread(image, 1, XDIM * YDIM * 3, handle);
2143 
2144 	/*  I don't know why, but this seems needed */
2145 	fread(&dummy, 1, 1, handle);
2146 
2147 	return (0);
2148 }
2149 #endif
2150 
2151 static int
2152 read_yuvdata(FILE * handle,
2153 			 unsigned char *image)
2154 {
2155 
2156 	if (fread(image, 1, IMAGE_SIZE(XDIM, YDIM), handle) !=
2157 		(unsigned int) IMAGE_SIZE(XDIM, YDIM))
2158 		return (1);
2159 	else
2160 		return (0);
2161 }
2162 
2163 /*****************************************************************************
2164  *     Routines for encoding: init encoder, frame step, release encoder
2165  ****************************************************************************/
2166 
2167 /* sample plugin */
2168 
2169 #if 0
2170 int
2171 rawenc_debug(void *handle,
2172 			 int opt,
2173 			 void *param1,
2174 			 void *param2)
2175 {
2176 	switch (opt) {
2177 	case XVID_PLG_INFO:
2178 		{
2179 			xvid_plg_info_t *info = (xvid_plg_info_t *) param1;
2180 
2181 			info->flags = XVID_REQDQUANTS;
2182 			return 0;
2183 		}
2184 
2185 	case XVID_PLG_CREATE:
2186 	case XVID_PLG_DESTROY:
2187 	case XVID_PLG_BEFORE:
2188 		return 0;
2189 
2190 	case XVID_PLG_AFTER:
2191 		{
2192 			xvid_plg_data_t *data = (xvid_plg_data_t *) param1;
2193 			int i, j;
2194 
2195 			printf("---[ frame: %5i   quant: %2i   length: %6i ]---\n",
2196 				   data->frame_num, data->quant, data->length);
2197 			for (j = 0; j < data->mb_height; j++) {
2198 				for (i = 0; i < data->mb_width; i++)
2199 					printf("%2i ", data->dquant[j * data->dquant_stride + i]);
2200 				printf("\n");
2201 			}
2202 
2203 			return 0;
2204 		}
2205 	}
2206 
2207 	return XVID_ERR_FAIL;
2208 }
2209 #endif
2210 
2211 #define FRAMERATE_INCR 1001
2212 
2213 /* Gobal encoder init, once per process */
2214 void
2215 enc_gbl(int use_assembler)
2216 {
2217 	xvid_gbl_init_t xvid_gbl_init;
2218 
2219 	/*------------------------------------------------------------------------
2220 	 * Xvid core initialization
2221 	 *----------------------------------------------------------------------*/
2222 
2223 	/* Set version -- version checking will done by xvidcore */
2224 	memset(&xvid_gbl_init, 0, sizeof(xvid_gbl_init));
2225 	xvid_gbl_init.version = XVID_VERSION;
2226     xvid_gbl_init.debug = ARG_DEBUG;
2227 
2228 
2229 	/* Do we have to enable ASM optimizations ? */
2230 	if (use_assembler) {
2231 
2232 #ifdef ARCH_IS_IA64
2233 		xvid_gbl_init.cpu_flags = XVID_CPU_FORCE | XVID_CPU_ASM;
2234 #else
2235 		xvid_gbl_init.cpu_flags = 0;
2236 #endif
2237 	} else {
2238 		xvid_gbl_init.cpu_flags = XVID_CPU_FORCE;
2239 	}
2240 
2241 	/* Initialize Xvid core -- Should be done once per __process__ */
2242 	xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL);
2243     ARG_CPU_FLAGS = xvid_gbl_init.cpu_flags;
2244 	enc_info();
2245 }
2246 
2247 /* Initialize encoder for first use, pass all needed parameters to the codec */
2248 static int
2249 enc_init(void **enc_handle, char *stats_pass1, int start_num)
2250 {
2251 	int xerr;
2252 	//xvid_plugin_cbr_t cbr;
2253     xvid_plugin_single_t single;
2254 	xvid_plugin_2pass1_t rc2pass1;
2255 	xvid_plugin_2pass2_t rc2pass2;
2256 	xvid_plugin_ssim_t ssim;
2257     xvid_plugin_lumimasking_t masking;
2258 	//xvid_plugin_fixed_t rcfixed;
2259 	xvid_enc_plugin_t plugins[8];
2260 	xvid_enc_create_t xvid_enc_create;
2261 	int i;
2262 
2263 	/*------------------------------------------------------------------------
2264 	 * Xvid encoder initialization
2265 	 *----------------------------------------------------------------------*/
2266 
2267 	/* Version again */
2268 	memset(&xvid_enc_create, 0, sizeof(xvid_enc_create));
2269 	xvid_enc_create.version = XVID_VERSION;
2270 
2271 	/* Width and Height of input frames */
2272 	xvid_enc_create.width = XDIM;
2273 	xvid_enc_create.height = YDIM;
2274 	xvid_enc_create.profile = 0xf5; /* Unrestricted */
2275 
2276 	/* init plugins  */
2277 //    xvid_enc_create.zones = ZONES;
2278 //    xvid_enc_create.num_zones = NUM_ZONES;
2279 
2280 	xvid_enc_create.plugins = plugins;
2281 	xvid_enc_create.num_plugins = 0;
2282 
2283 	if (ARG_SINGLE) {
2284 		memset(&single, 0, sizeof(xvid_plugin_single_t));
2285 		single.version = XVID_VERSION;
2286 		single.bitrate = ARG_BITRATE;
2287 		single.reaction_delay_factor = ARG_REACTION;
2288 		single.averaging_period = ARG_AVERAGING;
2289 		single.buffer = ARG_SMOOTHER;
2290 
2291 
2292 		plugins[xvid_enc_create.num_plugins].func = xvid_plugin_single;
2293 		plugins[xvid_enc_create.num_plugins].param = &single;
2294 		xvid_enc_create.num_plugins++;
2295 		if (!ARG_BITRATE)
2296 			prepare_cquant_zones();
2297 	}
2298 
2299 	if (ARG_PASS2) {
2300 		memset(&rc2pass2, 0, sizeof(xvid_plugin_2pass2_t));
2301 		rc2pass2.version = XVID_VERSION;
2302 		rc2pass2.filename = ARG_PASS2;
2303 		rc2pass2.bitrate = ARG_BITRATE;
2304 
2305 		rc2pass2.keyframe_boost = ARG_KBOOST;
2306 		rc2pass2.curve_compression_high = ARG_CHIGH;
2307 		rc2pass2.curve_compression_low = ARG_CLOW;
2308 		rc2pass2.overflow_control_strength = ARG_OVERSTRENGTH;
2309 		rc2pass2.max_overflow_improvement = ARG_OVERIMPROVE;
2310 		rc2pass2.max_overflow_degradation = ARG_OVERDEGRADE;
2311 		rc2pass2.kfreduction = ARG_KREDUCTION;
2312 		rc2pass2.kfthreshold = ARG_KTHRESH;
2313 		rc2pass2.container_frame_overhead = ARG_OVERHEAD;
2314 
2315 //		An example of activating VBV could look like this
2316 		rc2pass2.vbv_size     =  ARG_VBVSIZE;
2317 		rc2pass2.vbv_initial  =  (ARG_VBVSIZE*3)/4;
2318 		rc2pass2.vbv_maxrate  =  ARG_VBVMAXRATE;
2319 		rc2pass2.vbv_peakrate =  ARG_VBVPEAKRATE;
2320 
2321 
2322 		plugins[xvid_enc_create.num_plugins].func = xvid_plugin_2pass2;
2323 		plugins[xvid_enc_create.num_plugins].param = &rc2pass2;
2324 		xvid_enc_create.num_plugins++;
2325 	}
2326 
2327 	if (stats_pass1) {
2328 		memset(&rc2pass1, 0, sizeof(xvid_plugin_2pass1_t));
2329 		rc2pass1.version = XVID_VERSION;
2330 		rc2pass1.filename = stats_pass1;
2331 		if (ARG_FULL1PASS)
2332 			prepare_full1pass_zones();
2333 		plugins[xvid_enc_create.num_plugins].func = xvid_plugin_2pass1;
2334 		plugins[xvid_enc_create.num_plugins].param = &rc2pass1;
2335 		xvid_enc_create.num_plugins++;
2336 	}
2337 
2338 	/* Zones stuff */
2339 	xvid_enc_create.zones = (xvid_enc_zone_t*)malloc(sizeof(xvid_enc_zone_t) * NUM_ZONES);
2340 	xvid_enc_create.num_zones = NUM_ZONES;
2341 	for (i=0; i < xvid_enc_create.num_zones; i++) {
2342 		xvid_enc_create.zones[i].frame = ZONES[i].frame;
2343 		xvid_enc_create.zones[i].base = 100;
2344 		xvid_enc_create.zones[i].mode = ZONES[i].mode;
2345 		xvid_enc_create.zones[i].increment = ZONES[i].modifier;
2346 	}
2347 
2348 
2349 	if (ARG_LUMIMASKING) {
2350 		memset(&masking, 0, sizeof(xvid_plugin_lumimasking_t));
2351 		masking.method = (ARG_LUMIMASKING==2);
2352 		plugins[xvid_enc_create.num_plugins].func = xvid_plugin_lumimasking;
2353 		plugins[xvid_enc_create.num_plugins].param = &masking;
2354 		xvid_enc_create.num_plugins++;
2355 	}
2356 
2357 	if (ARG_DUMP) {
2358 		plugins[xvid_enc_create.num_plugins].func = xvid_plugin_dump;
2359 		plugins[xvid_enc_create.num_plugins].param = NULL;
2360 		xvid_enc_create.num_plugins++;
2361 	}
2362 
2363 	if (ARG_SSIM>=0 || ARG_SSIM_PATH != NULL) {
2364         memset(&ssim, 0, sizeof(xvid_plugin_ssim_t));
2365 
2366         plugins[xvid_enc_create.num_plugins].func = xvid_plugin_ssim;
2367 
2368 		if( ARG_SSIM >=0){
2369 			ssim.b_printstat = 1;
2370 			ssim.acc = ARG_SSIM;
2371 		} else {
2372 			ssim.b_printstat = 0;
2373 			ssim.acc = 2;
2374 		}
2375 
2376 		if(ARG_SSIM_PATH != NULL){
2377 			ssim.stat_path = ARG_SSIM_PATH;
2378 		}
2379 
2380         ssim.cpu_flags = ARG_CPU_FLAGS;
2381 		ssim.b_visualize = 0;
2382 		plugins[xvid_enc_create.num_plugins].param = &ssim;
2383 		xvid_enc_create.num_plugins++;
2384 	}
2385 
2386 	if (ARG_PSNRHVSM>0) {
2387         plugins[xvid_enc_create.num_plugins].func = xvid_plugin_psnrhvsm;
2388 		plugins[xvid_enc_create.num_plugins].param = NULL;
2389 		xvid_enc_create.num_plugins++;
2390 	}
2391 
2392 #if 0
2393 	if (ARG_DEBUG) {
2394 		plugins[xvid_enc_create.num_plugins].func = rawenc_debug;
2395 		plugins[xvid_enc_create.num_plugins].param = NULL;
2396 		xvid_enc_create.num_plugins++;
2397 	}
2398 #endif
2399 
2400 	xvid_enc_create.num_threads = ARG_THREADS;
2401 	xvid_enc_create.num_slices  = ARG_SLICES;
2402 
2403 	/* Frame rate  */
2404 	xvid_enc_create.fincr = ARG_DWSCALE;
2405 	xvid_enc_create.fbase = ARG_DWRATE;
2406 
2407 	/* Maximum key frame interval */
2408     if (ARG_MAXKEYINTERVAL > 0) {
2409         xvid_enc_create.max_key_interval = ARG_MAXKEYINTERVAL;
2410     }else {
2411 	    xvid_enc_create.max_key_interval = (int) ARG_FRAMERATE *10;
2412     }
2413 
2414 	xvid_enc_create.min_quant[0]=ARG_QUANTS[0];
2415 	xvid_enc_create.min_quant[1]=ARG_QUANTS[2];
2416 	xvid_enc_create.min_quant[2]=ARG_QUANTS[4];
2417 	xvid_enc_create.max_quant[0]=ARG_QUANTS[1];
2418 	xvid_enc_create.max_quant[1]=ARG_QUANTS[3];
2419 	xvid_enc_create.max_quant[2]=ARG_QUANTS[5];
2420 
2421 	/* Bframes settings */
2422 	xvid_enc_create.max_bframes = ARG_MAXBFRAMES;
2423 	xvid_enc_create.bquant_ratio = ARG_BQRATIO;
2424 	xvid_enc_create.bquant_offset = ARG_BQOFFSET;
2425 
2426 	/* Frame drop ratio */
2427 	xvid_enc_create.frame_drop_ratio = ARG_FRAMEDROP;
2428 
2429 	/* Start frame number */
2430 	xvid_enc_create.start_frame_num = start_num;
2431 
2432 	/* Global encoder options */
2433 	xvid_enc_create.global = 0;
2434 
2435 	if (ARG_PACKED)
2436 		xvid_enc_create.global |= XVID_GLOBAL_PACKED;
2437 
2438 	if (ARG_CLOSED_GOP)
2439 		xvid_enc_create.global |= XVID_GLOBAL_CLOSED_GOP;
2440 
2441 	if (ARG_STATS)
2442 		xvid_enc_create.global |= XVID_GLOBAL_EXTRASTATS_ENABLE;
2443 
2444 	/* I use a small value here, since will not encode whole movies, but short clips */
2445 	xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL);
2446 
2447 	/* Retrieve the encoder instance from the structure */
2448 	*enc_handle = xvid_enc_create.handle;
2449 
2450 	free(xvid_enc_create.zones);
2451 
2452 	return (xerr);
2453 }
2454 
2455 static int
2456 enc_info()
2457 {
2458 	xvid_gbl_info_t xvid_gbl_info;
2459 	int ret;
2460 
2461 	memset(&xvid_gbl_info, 0, sizeof(xvid_gbl_info));
2462 	xvid_gbl_info.version = XVID_VERSION;
2463 	ret = xvid_global(NULL, XVID_GBL_INFO, &xvid_gbl_info, NULL);
2464 	if (xvid_gbl_info.build != NULL) {
2465 		fprintf(stderr, "xvidcore build version: %s\n", xvid_gbl_info.build);
2466 	}
2467 	fprintf(stderr, "Bitstream version: %d.%d.%d\n", XVID_VERSION_MAJOR(xvid_gbl_info.actual_version), XVID_VERSION_MINOR(xvid_gbl_info.actual_version), XVID_VERSION_PATCH(xvid_gbl_info.actual_version));
2468 	fprintf(stderr, "Detected CPU flags: ");
2469 	if (xvid_gbl_info.cpu_flags & XVID_CPU_ASM)
2470 		fprintf(stderr, "ASM ");
2471 	if (xvid_gbl_info.cpu_flags & XVID_CPU_MMX)
2472 		fprintf(stderr, "MMX ");
2473 	if (xvid_gbl_info.cpu_flags & XVID_CPU_MMXEXT)
2474 		fprintf(stderr, "MMXEXT ");
2475 	if (xvid_gbl_info.cpu_flags & XVID_CPU_SSE)
2476 		fprintf(stderr, "SSE ");
2477 	if (xvid_gbl_info.cpu_flags & XVID_CPU_SSE2)
2478 		fprintf(stderr, "SSE2 ");
2479 	if (xvid_gbl_info.cpu_flags & XVID_CPU_SSE3)
2480 		fprintf(stderr, "SSE3 ");
2481 	if (xvid_gbl_info.cpu_flags & XVID_CPU_SSE41)
2482 		fprintf(stderr, "SSE41 ");
2483     if (xvid_gbl_info.cpu_flags & XVID_CPU_3DNOW)
2484 		fprintf(stderr, "3DNOW ");
2485 	if (xvid_gbl_info.cpu_flags & XVID_CPU_3DNOWEXT)
2486 		fprintf(stderr, "3DNOWEXT ");
2487 	if (xvid_gbl_info.cpu_flags & XVID_CPU_TSC)
2488 		fprintf(stderr, "TSC ");
2489 	fprintf(stderr, "\n");
2490 	fprintf(stderr, "Detected %d cpus,", xvid_gbl_info.num_threads);
2491 	ARG_NUM_APP_THREADS = xvid_gbl_info.num_threads;
2492 	fprintf(stderr, " using %d threads.\n", (!ARG_THREADS) ? ARG_NUM_APP_THREADS : ARG_THREADS);
2493 	return ret;
2494 }
2495 
2496 static int
2497 enc_stop(void *enc_handle)
2498 {
2499 	int xerr;
2500 
2501 	/* Destroy the encoder instance */
2502 	xerr = xvid_encore(enc_handle, XVID_ENC_DESTROY, NULL, NULL);
2503 
2504 	return (xerr);
2505 }
2506 
2507 static int
2508 enc_main(void *enc_handle,
2509 		 unsigned char *image,
2510 		 unsigned char *bitstream,
2511 		 int *key,
2512 		 int *stats_type,
2513 		 int *stats_quant,
2514 		 int *stats_length,
2515 		 int sse[3],
2516 		 int framenum)
2517 {
2518 	int ret;
2519 
2520 	xvid_enc_frame_t xvid_enc_frame;
2521 	xvid_enc_stats_t xvid_enc_stats;
2522 
2523 	/* Version for the frame and the stats */
2524 	memset(&xvid_enc_frame, 0, sizeof(xvid_enc_frame));
2525 	xvid_enc_frame.version = XVID_VERSION;
2526 
2527 	memset(&xvid_enc_stats, 0, sizeof(xvid_enc_stats));
2528 	xvid_enc_stats.version = XVID_VERSION;
2529 
2530 	/* Bind output buffer */
2531 	xvid_enc_frame.bitstream = bitstream;
2532 	xvid_enc_frame.length = -1;
2533 
2534 	/* Initialize input image fields */
2535 	if (image) {
2536 		xvid_enc_frame.input.plane[0] = image;
2537 #ifndef READ_PNM
2538 		xvid_enc_frame.input.csp = ARG_COLORSPACE;
2539 		xvid_enc_frame.input.stride[0] = XDIM;
2540 #else
2541 		xvid_enc_frame.input.csp = XVID_CSP_BGR;
2542 		xvid_enc_frame.input.stride[0] = XDIM*3;
2543 #endif
2544 	} else {
2545 		xvid_enc_frame.input.csp = XVID_CSP_NULL;
2546 	}
2547 
2548 	/* Set up core's general features */
2549 	xvid_enc_frame.vol_flags = 0;
2550 	if (ARG_STATS)
2551 		xvid_enc_frame.vol_flags |= XVID_VOL_EXTRASTATS;
2552 	if (ARG_QTYPE) {
2553 		xvid_enc_frame.vol_flags |= XVID_VOL_MPEGQUANT;
2554 		if (ARG_QMATRIX) {
2555 			xvid_enc_frame.quant_intra_matrix = qmatrix_intra;
2556 			xvid_enc_frame.quant_inter_matrix = qmatrix_inter;
2557 		}
2558 		else {
2559 			/* We don't use special matrices */
2560 			xvid_enc_frame.quant_intra_matrix = NULL;
2561 			xvid_enc_frame.quant_inter_matrix = NULL;
2562 		}
2563 	}
2564 
2565 	if (ARG_PAR)
2566 		xvid_enc_frame.par = ARG_PAR;
2567 	else {
2568 		xvid_enc_frame.par = XVID_PAR_EXT;
2569 		xvid_enc_frame.par_width = ARG_PARWIDTH;
2570 		xvid_enc_frame.par_height = ARG_PARHEIGHT;
2571 	}
2572 
2573 
2574 	if (ARG_QPEL) {
2575 		xvid_enc_frame.vol_flags |= XVID_VOL_QUARTERPEL;
2576 		xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE16 | XVID_ME_QUARTERPELREFINE8;
2577 	}
2578 	if (ARG_GMC) {
2579 		xvid_enc_frame.vol_flags |= XVID_VOL_GMC;
2580 		xvid_enc_frame.motion |= XVID_ME_GME_REFINE;
2581 	}
2582 
2583 	/* Set up core's general features */
2584 	xvid_enc_frame.vop_flags = vop_presets[ARG_QUALITY];
2585 
2586 	if (ARG_INTERLACING) {
2587 		xvid_enc_frame.vol_flags |= XVID_VOL_INTERLACING;
2588 		if (ARG_INTERLACING == 2)
2589 			xvid_enc_frame.vop_flags |= XVID_VOP_TOPFIELDFIRST;
2590 	}
2591 
2592 	xvid_enc_frame.vop_flags |= XVID_VOP_HALFPEL;
2593 	xvid_enc_frame.vop_flags |= XVID_VOP_HQACPRED;
2594 
2595     if (ARG_VOPDEBUG) {
2596         xvid_enc_frame.vop_flags |= XVID_VOP_DEBUG;
2597     }
2598 
2599     if (ARG_TRELLIS) {
2600         xvid_enc_frame.vop_flags |= XVID_VOP_TRELLISQUANT;
2601     }
2602 
2603 	/* Frame type -- taken from function call parameter */
2604 	/* Sometimes we might want to force the last frame to be a P Frame */
2605 	xvid_enc_frame.type = *stats_type;
2606 
2607 	/* Force the right quantizer -- It is internally managed by RC plugins */
2608 	xvid_enc_frame.quant = 0;
2609 
2610 	if (ARG_CHROMAME)
2611 		xvid_enc_frame.motion |= XVID_ME_CHROMA_PVOP + XVID_ME_CHROMA_BVOP;
2612 
2613 	/* Set up motion estimation flags */
2614 	xvid_enc_frame.motion |= motion_presets[ARG_QUALITY];
2615 
2616 	if (ARG_TURBO)
2617 		xvid_enc_frame.motion |= XVID_ME_FASTREFINE16 | XVID_ME_FASTREFINE8 |
2618 								 XVID_ME_SKIP_DELTASEARCH | XVID_ME_FAST_MODEINTERPOLATE |
2619 								 XVID_ME_BFRAME_EARLYSTOP;
2620 
2621 	if (ARG_BVHQ)
2622 		xvid_enc_frame.vop_flags |= XVID_VOP_RD_BVOP;
2623 
2624 	if (ARG_QMETRIC == 1)
2625 		xvid_enc_frame.vop_flags |= XVID_VOP_RD_PSNRHVSM;
2626 
2627 	switch (ARG_VHQMODE) /* this is the same code as for vfw */
2628 	{
2629 	case 1: /* VHQ_MODE_DECISION */
2630 		xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
2631 		break;
2632 
2633 	case 2: /* VHQ_LIMITED_SEARCH */
2634 		xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
2635 		xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE16_RD;
2636 		xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE16_RD;
2637 		break;
2638 
2639 	case 3: /* VHQ_MEDIUM_SEARCH */
2640 		xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
2641 		xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE16_RD;
2642 		xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE8_RD;
2643 		xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE16_RD;
2644 		xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE8_RD;
2645 		xvid_enc_frame.motion |= XVID_ME_CHECKPREDICTION_RD;
2646 		break;
2647 
2648 	case 4: /* VHQ_WIDE_SEARCH */
2649 		xvid_enc_frame.vop_flags |= XVID_VOP_MODEDECISION_RD;
2650 		xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE16_RD;
2651 		xvid_enc_frame.motion |= XVID_ME_HALFPELREFINE8_RD;
2652 		xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE16_RD;
2653 		xvid_enc_frame.motion |= XVID_ME_QUARTERPELREFINE8_RD;
2654 		xvid_enc_frame.motion |= XVID_ME_CHECKPREDICTION_RD;
2655 		xvid_enc_frame.motion |= XVID_ME_EXTSEARCH_RD;
2656 		break;
2657 
2658 	default :
2659 		break;
2660 	}
2661 
2662 	/* Not sure what this does */
2663 	// force keyframe spacing in 2-pass 1st pass
2664 	if (ARG_QUALITY == 0)
2665 		xvid_enc_frame.type = XVID_TYPE_IVOP;
2666 
2667 	/* frame-based stuff */
2668 	apply_zone_modifiers(&xvid_enc_frame, framenum);
2669 
2670 
2671 	/* Encode the frame */
2672 	ret = xvid_encore(enc_handle, XVID_ENC_ENCODE, &xvid_enc_frame,
2673 					  &xvid_enc_stats);
2674 
2675 	*key = (xvid_enc_frame.out_flags & XVID_KEYFRAME);
2676 	*stats_type = xvid_enc_stats.type;
2677 	*stats_quant = xvid_enc_stats.quant;
2678 	*stats_length = xvid_enc_stats.length;
2679 	sse[0] = xvid_enc_stats.sse_y;
2680 	sse[1] = xvid_enc_stats.sse_u;
2681 	sse[2] = xvid_enc_stats.sse_v;
2682 
2683 	return (ret);
2684 }
2685 
2686 void
2687 sort_zones(zone_t * zones, int zone_num, int * sel)
2688 {
2689 	int i, j;
2690 	zone_t tmp;
2691 	for (i = 0; i < zone_num; i++) {
2692 		int cur = i;
2693 		int min_f = zones[i].frame;
2694 		for (j = i + 1; j < zone_num; j++) {
2695 			if (zones[j].frame < min_f) {
2696 				min_f = zones[j].frame;
2697 				cur = j;
2698 			}
2699 		}
2700 		if (cur != i) {
2701 			tmp = zones[i];
2702 			zones[i] = zones[cur];
2703 			zones[cur] = tmp;
2704 			if (i == *sel) *sel = cur;
2705 			else if (cur == *sel) *sel = i;
2706 		}
2707 	}
2708 }
2709 
2710 /* constant-quant zones for fixed quant encoding */
2711 static void
2712 prepare_cquant_zones() {
2713 
2714 	int i = 0;
2715 	if (NUM_ZONES == 0 || ZONES[0].frame != 0) {
2716 		/* first zone does not start at frame 0 or doesn't exist */
2717 
2718 		if (NUM_ZONES >= MAX_ZONES) NUM_ZONES--; /* we sacrifice last zone */
2719 
2720 		ZONES[NUM_ZONES].frame = 0;
2721 		ZONES[NUM_ZONES].mode = XVID_ZONE_QUANT;
2722 		ZONES[NUM_ZONES].modifier = (int) ARG_CQ;
2723 		ZONES[NUM_ZONES].type = XVID_TYPE_AUTO;
2724 		ZONES[NUM_ZONES].greyscale = 0;
2725 		ZONES[NUM_ZONES].chroma_opt = 0;
2726 		ZONES[NUM_ZONES].bvop_threshold = 0;
2727 		ZONES[NUM_ZONES].cartoon_mode = 0;
2728 		NUM_ZONES++;
2729 
2730 		sort_zones(ZONES, NUM_ZONES, &i);
2731 	}
2732 
2733 	/* step 2: let's change all weight zones into quant zones */
2734 
2735 	for(i = 0; i < NUM_ZONES; i++)
2736 		if (ZONES[i].mode == XVID_ZONE_WEIGHT) {
2737 			ZONES[i].mode = XVID_ZONE_QUANT;
2738 			ZONES[i].modifier = (int) ((100*ARG_CQ) / ZONES[i].modifier);
2739 		}
2740 }
2741 
2742 /* full first pass zones */
2743 static void
2744 prepare_full1pass_zones() {
2745 
2746 	int i = 0;
2747 	if (NUM_ZONES == 0 || ZONES[0].frame != 0) {
2748 		/* first zone does not start at frame 0 or doesn't exist */
2749 
2750 		if (NUM_ZONES >= MAX_ZONES) NUM_ZONES--; /* we sacrifice last zone */
2751 
2752 		ZONES[NUM_ZONES].frame = 0;
2753 		ZONES[NUM_ZONES].mode = XVID_ZONE_QUANT;
2754 		ZONES[NUM_ZONES].modifier = 200;
2755 		ZONES[NUM_ZONES].type = XVID_TYPE_AUTO;
2756 		ZONES[NUM_ZONES].greyscale = 0;
2757 		ZONES[NUM_ZONES].chroma_opt = 0;
2758 		ZONES[NUM_ZONES].bvop_threshold = 0;
2759 		ZONES[NUM_ZONES].cartoon_mode = 0;
2760 		NUM_ZONES++;
2761 
2762 		sort_zones(ZONES, NUM_ZONES, &i);
2763 	}
2764 
2765 	/* step 2: let's change all weight zones into quant zones */
2766 
2767 	for(i = 0; i < NUM_ZONES; i++)
2768 		if (ZONES[i].mode == XVID_ZONE_WEIGHT) {
2769 			ZONES[i].mode = XVID_ZONE_QUANT;
2770 			ZONES[i].modifier = 200;
2771 		}
2772 }
2773 
2774 static void apply_zone_modifiers(xvid_enc_frame_t * frame, int framenum)
2775 {
2776 	int i;
2777 
2778 	for (i=0; i<NUM_ZONES && ZONES[i].frame <= framenum; i++) ;
2779 
2780 	if (--i < 0) return; /* there are no zones, or we're before the first zone */
2781 
2782 	if (framenum == ZONES[i].frame)
2783 		frame->type = ZONES[i].type;
2784 
2785 	if (ZONES[i].greyscale) {
2786 		frame->vop_flags |= XVID_VOP_GREYSCALE;
2787 	}
2788 
2789 	if (ZONES[i].chroma_opt) {
2790 		frame->vop_flags |= XVID_VOP_CHROMAOPT;
2791 	}
2792 
2793 	if (ZONES[i].cartoon_mode) {
2794 		frame->vop_flags |= XVID_VOP_CARTOON;
2795 		frame->motion |= XVID_ME_DETECT_STATIC_MOTION;
2796 	}
2797 
2798 	if (ARG_MAXBFRAMES) {
2799 		frame->bframe_threshold = ZONES[i].bvop_threshold;
2800 	}
2801 }
2802 
2803 void removedivxp(char *buf, int bufsize) {
2804 	int i;
2805 	char* userdata;
2806 
2807 	for (i=0; i <= (int)(bufsize-sizeof(userdata_start_code)); i++) {
2808 		if (memcmp((void*)userdata_start_code, (void*)(buf+i), strlen(userdata_start_code))==0) {
2809 			if ((userdata = strstr(buf+i+4, "DivX"))!=NULL) {
2810 				userdata[strlen(userdata)-1] = '\0';
2811 				return;
2812 			}
2813 		}
2814 	}
2815 }
2816