ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/trunk/xvidcore/examples/xvid_encraw.c
Revision: 2128
Committed: Wed Jul 8 17:32:48 2015 UTC (9 years, 3 months ago) by Isibaar
Content type: text/plain
File size: 88158 byte(s)
Log Message:
Making the applevel multithreading work also for AVI output

File Contents

# Content
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-2010 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$
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
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
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 }

Properties

Name Value
svn:keywords Id