[svn] / trunk / vfw / src / codec.c Repository:
ViewVC logotype

Annotation of /trunk/vfw/src/codec.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (view) (download)

1 : Isibaar 3 /**************************************************************************
2 :     *
3 :     * XVID VFW FRONTEND
4 :     * codec
5 :     *
6 :     * This program is free software; you can redistribute it and/or modify
7 :     * it under the terms of the GNU General Public License as published by
8 :     * the Free Software Foundation; either version 2 of the License, or
9 :     * (at your option) any later version.
10 :     *
11 :     * This program is distributed in the hope that it will be useful,
12 :     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 :     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 :     * GNU General Public License for more details.
15 :     *
16 :     * You should have received a copy of the GNU General Public License
17 :     * along with this program; if not, write to the Free Software
18 :     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 :     *
20 :     *************************************************************************/
21 :    
22 :     /**************************************************************************
23 :     *
24 :     * History:
25 :     *
26 :     * ... ???
27 :     * 01.12.2001 inital version; (c)2001 peter ross <suxen_drol@hotmail.com>
28 :     *
29 :     *************************************************************************/
30 :    
31 :     #include <windows.h>
32 :     #include <vfw.h>
33 :    
34 :     #include "codec.h"
35 :     #include <math.h> // fabs()
36 :    
37 :     int pmvfast_presets[7] = {
38 :     0, PMV_QUICKSTOP16, PMV_EARLYSTOP16, PMV_EARLYSTOP16 | PMV_EARLYSTOP8,
39 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8,
40 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EARLYSTOP8 | PMV_HALFPELDIAMOND8,
41 :     PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EXTSEARCH16 |
42 :     PMV_EARLYSTOP8 | PMV_HALFPELREFINE8 | PMV_HALFPELDIAMOND8
43 :     };
44 :    
45 :     /* return xvid compatbile colorspace,
46 :     or XVID_CSP_NULL if failure
47 :     */
48 :    
49 :     int get_colorspace(BITMAPV4HEADER * hdr)
50 :     {
51 :     if (hdr->bV4Height < 0)
52 :     {
53 :     DEBUG("colorspace: inverted input format not supported");
54 :     return XVID_CSP_NULL;
55 :     }
56 :    
57 :     switch(hdr->bV4V4Compression)
58 :     {
59 :     case BI_RGB :
60 :     if (hdr->bV4BitCount == 16)
61 :     {
62 :     DEBUG("RGB16 (RGB555)");
63 :     return XVID_CSP_VFLIP | XVID_CSP_RGB555;
64 :     }
65 :     if (hdr->bV4BitCount == 24)
66 :     {
67 :     DEBUG("RGB24");
68 :     return XVID_CSP_VFLIP | XVID_CSP_RGB24;
69 :     }
70 :     if (hdr->bV4BitCount == 32)
71 :     {
72 :     DEBUG("RGB32");
73 :     return XVID_CSP_VFLIP | XVID_CSP_RGB32;
74 :     }
75 :    
76 :     DEBUG1("BI_RGB unsupported", hdr->bV4BitCount);
77 :     return XVID_CSP_NULL;
78 :    
79 :     case BI_BITFIELDS :
80 :     if(hdr->bV4BitCount == 16 &&
81 :     hdr->bV4RedMask == 0x7c00 &&
82 :     hdr->bV4GreenMask == 0x3e0 &&
83 :     hdr->bV4BlueMask == 0x1f)
84 :     {
85 :     DEBUG("RGB555");
86 :     return XVID_CSP_VFLIP | XVID_CSP_RGB555;
87 :     }
88 :     if(hdr->bV4BitCount == 16 &&
89 :     hdr->bV4RedMask == 0xf800 &&
90 :     hdr->bV4GreenMask == 0x7e0 &&
91 :     hdr->bV4BlueMask == 0x1f)
92 :     {
93 :     DEBUG("RGB565");
94 :     return XVID_CSP_VFLIP | XVID_CSP_RGB565;
95 :     }
96 :    
97 :     DEBUG1("BI_FIELDS unsupported", hdr->bV4BitCount);
98 :     return XVID_CSP_NULL;
99 :    
100 :     case FOURCC_I420:
101 :     case FOURCC_IYUV:
102 :     DEBUG("IYUY");
103 :     return XVID_CSP_I420;
104 :    
105 :     case FOURCC_YV12 :
106 :     DEBUG("YV12");
107 :     return XVID_CSP_YV12;
108 :    
109 :     case FOURCC_YUYV :
110 :     case FOURCC_YUY2 :
111 :     case FOURCC_V422 :
112 :     DEBUG("YUY2");
113 :     return XVID_CSP_YUY2;
114 :    
115 :     case FOURCC_YVYU:
116 :     DEBUG("YVYU");
117 :     return XVID_CSP_YVYU;
118 :    
119 :     case FOURCC_UYVY:
120 :     DEBUG("UYVY");
121 :     return XVID_CSP_UYVY;
122 :    
123 :     }
124 :     DEBUGFOURCC("colorspace: unknown", hdr->bV4V4Compression);
125 :     return XVID_CSP_NULL;
126 :     }
127 :    
128 :    
129 :     /* compressor */
130 :    
131 :    
132 :     /* test the output format */
133 :    
134 :     LRESULT compress_query(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput)
135 :     {
136 :     BITMAPV4HEADER * inhdr = (BITMAPV4HEADER *)&lpbiInput->bmiHeader;
137 :     BITMAPV4HEADER * outhdr = (BITMAPV4HEADER *)&lpbiOutput->bmiHeader;
138 :    
139 :     if (get_colorspace(inhdr) == XVID_CSP_NULL)
140 :     {
141 :     return ICERR_BADFORMAT;
142 :     }
143 :    
144 :     if (lpbiOutput == NULL)
145 :     {
146 :     return ICERR_OK;
147 :     }
148 :    
149 :     if (inhdr->bV4Width != outhdr->bV4Width || inhdr->bV4Height != outhdr->bV4Height ||
150 :     (outhdr->bV4V4Compression != FOURCC_XVID && outhdr->bV4V4Compression != FOURCC_DIVX))
151 :     {
152 :     return ICERR_BADFORMAT;
153 :     }
154 :    
155 :     return ICERR_OK;
156 :     }
157 :    
158 :    
159 :     LRESULT compress_get_format(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput)
160 :     {
161 :     BITMAPV4HEADER * inhdr = (BITMAPV4HEADER *)&lpbiInput->bmiHeader;
162 :     BITMAPV4HEADER * outhdr = (BITMAPV4HEADER *)&lpbiOutput->bmiHeader;
163 :    
164 :     if (get_colorspace(inhdr) == XVID_CSP_NULL)
165 :     {
166 :     return ICERR_BADFORMAT;
167 :     }
168 :    
169 :     if (lpbiOutput == NULL)
170 :     {
171 :     return sizeof(BITMAPV4HEADER);
172 :     }
173 :    
174 :     memcpy(outhdr, inhdr, sizeof(BITMAPV4HEADER));
175 :     outhdr->bV4Size = sizeof(BITMAPV4HEADER);
176 :     outhdr->bV4BitCount = 24; // or 16
177 :     outhdr->bV4SizeImage = compress_get_size(codec, lpbiInput, lpbiOutput);
178 :     outhdr->bV4XPelsPerMeter = 0;
179 :     outhdr->bV4YPelsPerMeter = 0;
180 :     outhdr->bV4ClrUsed = 0;
181 :     outhdr->bV4ClrImportant = 0;
182 :    
183 :     if (codec->config.fourcc_used == 0)
184 :     {
185 :     outhdr->bV4V4Compression = FOURCC_XVID;
186 :     }
187 :     else
188 :     {
189 :     outhdr->bV4V4Compression = FOURCC_DIVX;
190 :     }
191 :    
192 :     return ICERR_OK;
193 :     }
194 :    
195 :    
196 :     LRESULT compress_get_size(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput)
197 :     {
198 :     BITMAPV4HEADER * outhdr = (BITMAPV4HEADER *)&lpbiOutput->bmiHeader;
199 :     return outhdr->bV4Width * outhdr->bV4Height * 3;
200 :     }
201 :    
202 :    
203 :     LRESULT compress_frames_info(CODEC * codec, ICCOMPRESSFRAMES * icf)
204 :     {
205 :     // DEBUG2("frate fscale", codec->frate, codec->fscale);
206 :     codec->fincr = icf->dwScale;
207 :     codec->fbase = icf->dwRate;
208 :     return ICERR_OK;
209 :     }
210 :    
211 :    
212 :     LRESULT compress_begin(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput)
213 :     {
214 :     BITMAPV4HEADER * inhdr = (BITMAPV4HEADER *)&lpbiInput->bmiHeader;
215 :     XVID_ENC_PARAM param;
216 :     XVID_INIT_PARAM init_param;
217 :    
218 :     switch (codec->config.mode)
219 :     {
220 :     case DLG_MODE_CBR :
221 :     param.bitrate = codec->config.bitrate;
222 :     param.rc_buffersize = codec->config.rc_buffersize;
223 :     break;
224 :    
225 :     case DLG_MODE_VBR_QUAL :
226 :     codec->config.fquant = 0;
227 :     param.bitrate = 0;
228 :     break;
229 :    
230 :     case DLG_MODE_VBR_QUANT :
231 :     codec->config.fquant = (float) codec->config.quant;
232 :     param.bitrate = 0;
233 :     break;
234 :    
235 :     case DLG_MODE_2PASS_1:
236 :     case DLG_MODE_2PASS_2_INT:
237 :     case DLG_MODE_2PASS_2_EXT:
238 :     param.bitrate = 0;
239 :     break;
240 :    
241 :     default :
242 :     break;
243 :     }
244 :    
245 :     if(codec->ehandle)
246 :     {
247 :     xvid_encore(codec->ehandle, XVID_ENC_DESTROY, NULL, NULL);
248 :     codec->ehandle = NULL;
249 :     }
250 :    
251 :     init_param.cpu_flags = codec->config.cpu;
252 :     xvid_init(0, 0, &init_param, NULL);
253 :     if((codec->config.cpu & XVID_CPU_FORCE) <= 0)
254 :     codec->config.cpu = init_param.cpu_flags;
255 :    
256 :     param.width = inhdr->bV4Width;
257 :     param.height = inhdr->bV4Height;
258 :     param.fincr = codec->fincr;
259 :     param.fbase = codec->fbase;
260 :    
261 :     param.rc_buffersize = codec->config.rc_buffersize;
262 :    
263 :     param.min_quantizer = codec->config.min_quant;
264 :     param.max_quantizer = codec->config.max_quant;
265 :     param.max_key_interval = codec->config.max_key_interval;
266 :    
267 :     switch(xvid_encore(0, XVID_ENC_CREATE, &param, NULL))
268 :     {
269 :     case XVID_ERR_FAIL :
270 :     return ICERR_ERROR;
271 :    
272 :     case XVID_ERR_MEMORY :
273 :     return ICERR_MEMORY;
274 :    
275 :     case XVID_ERR_FORMAT :
276 :     return ICERR_BADFORMAT;
277 :     }
278 :    
279 :     codec->ehandle = param.handle;
280 :     codec->framenum = 0;
281 :     codec->keyspacing = 0;
282 :    
283 :     codec->twopass.stats1 = codec->twopass.stats2 = INVALID_HANDLE_VALUE;
284 :    
285 :     return ICERR_OK;
286 :     }
287 :    
288 :    
289 :     LRESULT compress_end(CODEC * codec)
290 :     {
291 :     if (codec->ehandle != NULL)
292 :     {
293 :     xvid_encore(codec->ehandle, XVID_ENC_DESTROY, NULL, NULL);
294 :     if (codec->twopass.stats1 != INVALID_HANDLE_VALUE)
295 :     {
296 :     CloseHandle(codec->twopass.stats1);
297 :     }
298 :     if (codec->twopass.stats2 != INVALID_HANDLE_VALUE)
299 :     {
300 :     CloseHandle(codec->twopass.stats2);
301 :     }
302 :     codec->ehandle = NULL;
303 :     }
304 :    
305 :     return ICERR_OK;
306 :     }
307 :    
308 :    
309 :     LRESULT compress(CODEC * codec, ICCOMPRESS * icc)
310 :     {
311 :     BITMAPV4HEADER * inhdr = (BITMAPV4HEADER *)icc->lpbiInput;
312 :     BITMAPV4HEADER * outhdr = (BITMAPV4HEADER *)icc->lpbiOutput;
313 :     XVID_ENC_FRAME frame;
314 :     XVID_ENC_STATS stats;
315 :    
316 :     // mpeg2avi yuv bug workaround (2 instances of CODEC)
317 :     if (codec->twopass.stats1 == INVALID_HANDLE_VALUE)
318 :     {
319 :     if (codec_2pass_init(codec) == ICERR_ERROR)
320 :     {
321 :     return ICERR_ERROR;
322 :     }
323 :     }
324 :    
325 :     frame.general = 0;
326 :     frame.motion = 0;
327 :    
328 :     if(codec->config.motion_search == 0)
329 :     frame.intra = 1;
330 :    
331 :     frame.general |= XVID_HALFPEL;
332 :    
333 :     if(codec->config.motion_search > 3)
334 :     frame.general |= XVID_INTER4V;
335 :    
336 :     // we actually need "default/custom" selectbox for both inter/intra
337 :     // this will do for now
338 :    
339 :     if ((codec->config.quant_type == QUANT_MODE_CUSTOM) && (codec->config.quant_type == 1))
340 :     {
341 :     frame.general |= XVID_CUSTOM_QMATRIX;
342 :     frame.quant_intra_matrix = codec->config.qmatrix_intra;
343 :     frame.quant_inter_matrix = codec->config.qmatrix_inter;
344 :     }
345 :     else
346 :     {
347 :     frame.quant_intra_matrix = NULL;
348 :     frame.quant_inter_matrix = NULL;
349 :     }
350 :    
351 :     if(codec->config.quant_type == 0)
352 :     frame.general |= XVID_H263QUANT;
353 :     else
354 :     frame.general |= XVID_MPEGQUANT;
355 :    
356 :     if(((codec->config.mode == DLG_MODE_2PASS_1) ? 0 : codec->config.lum_masking) == 1)
357 :     frame.general |= XVID_LUMIMASKING;
358 :    
359 :     frame.motion = pmvfast_presets[codec->config.motion_search];
360 :    
361 :     frame.image = icc->lpInput;
362 :    
363 :     if ((frame.colorspace = get_colorspace(inhdr)) == XVID_CSP_NULL) {
364 :     return ICERR_BADFORMAT;
365 :     }
366 :    
367 :     frame.bitstream = icc->lpOutput;
368 :     frame.length = icc->lpbiOutput->biSizeImage;
369 :     frame.intra = -1;
370 :    
371 :     switch (codec->config.mode)
372 :     {
373 :     case DLG_MODE_CBR :
374 :     frame.quant = 0;
375 :     break;
376 :    
377 :     case DLG_MODE_VBR_QUAL :
378 :     case DLG_MODE_VBR_QUANT :
379 :     case DLG_MODE_2PASS_1 :
380 :     if (codec_get_quant(codec, &frame) == ICERR_ERROR)
381 :     {
382 :     return ICERR_ERROR;
383 :     }
384 :     break;
385 :    
386 :     case DLG_MODE_2PASS_2_EXT :
387 :     case DLG_MODE_2PASS_2_INT :
388 :     if (codec_2pass_get_quant(codec, &frame) == ICERR_ERROR)
389 :     {
390 :     return ICERR_ERROR;
391 :     }
392 :     if (codec->config.dummy2pass)
393 :     {
394 :     outhdr->bV4SizeImage = codec->twopass.bytes2;
395 :     *icc->lpdwFlags = (codec->twopass.nns1.quant & NNSTATS_KEYFRAME) ? AVIIF_KEYFRAME : 0;
396 :     return ICERR_OK;
397 :     }
398 :     break;
399 :    
400 :     case DLG_MODE_NULL :
401 :     outhdr->bV4SizeImage = 0;
402 :     *icc->lpdwFlags = AVIIF_KEYFRAME;
403 :     return ICERR_OK;
404 :    
405 :     default :
406 :     DEBUG("Invalid encoding mode");
407 :     return ICERR_ERROR;
408 :     }
409 :    
410 :     // force keyframe spacing in 2-pass modes
411 :     if ((codec->keyspacing < codec->config.min_key_interval && codec->framenum) &&
412 :     (codec->config.mode == DLG_MODE_2PASS_1 || codec->config.mode == DLG_MODE_2PASS_2_INT ||
413 :     codec->config.mode == DLG_MODE_2PASS_2_EXT))
414 :     {
415 :     DEBUG("current frame forced to p-frame");
416 :     frame.intra = 0;
417 :     }
418 :    
419 :     switch (xvid_encore(codec->ehandle, XVID_ENC_ENCODE, &frame, &stats))
420 :     {
421 :     case XVID_ERR_FAIL :
422 :     return ICERR_ERROR;
423 :    
424 :     case XVID_ERR_MEMORY :
425 :     return ICERR_MEMORY;
426 :    
427 :     case XVID_ERR_FORMAT :
428 :     return ICERR_BADFORMAT;
429 :     }
430 :    
431 :     if (frame.intra)
432 :     {
433 :     codec->keyspacing = 0;
434 :     *icc->lpdwFlags = AVIIF_KEYFRAME;
435 :     }
436 :     else
437 :     {
438 :     *icc->lpdwFlags = 0;
439 :     }
440 :    
441 :     outhdr->bV4SizeImage = frame.length;
442 :    
443 :     if (codec->config.mode == DLG_MODE_2PASS_1)
444 :     {
445 :     if (codec->config.discard1pass)
446 :     {
447 :     outhdr->bV4SizeImage = 0;
448 :     }
449 :     }
450 :    
451 :     codec_2pass_update(codec, &frame, &stats);
452 :    
453 :     ++codec->framenum;
454 :     ++codec->keyspacing;
455 :    
456 :     return ICERR_OK;
457 :     }
458 :    
459 :    
460 :     /* decompressor */
461 :    
462 :    
463 :     LRESULT decompress_query(CODEC * codec, BITMAPINFO *lpbiInput, BITMAPINFO *lpbiOutput)
464 :     {
465 :     BITMAPV4HEADER * inhdr = (BITMAPV4HEADER *)&lpbiInput->bmiHeader;
466 :     BITMAPV4HEADER * outhdr = (BITMAPV4HEADER *)&lpbiOutput->bmiHeader;
467 :    
468 :     if (lpbiInput == NULL)
469 :     {
470 :     return ICERR_ERROR;
471 :     }
472 :    
473 :     if (inhdr->bV4V4Compression != FOURCC_XVID && inhdr->bV4V4Compression != FOURCC_DIVX)
474 :     {
475 :     return ICERR_BADFORMAT;
476 :     }
477 :    
478 :     if (lpbiOutput == NULL)
479 :     {
480 :     return ICERR_OK;
481 :     }
482 :    
483 :     if (inhdr->bV4Width != outhdr->bV4Width ||
484 :     inhdr->bV4Height != outhdr->bV4Height ||
485 :     get_colorspace(outhdr) == XVID_CSP_NULL)
486 :     {
487 :     return ICERR_BADFORMAT;
488 :     }
489 :    
490 :     return ICERR_OK;
491 :     }
492 :    
493 :    
494 :     LRESULT decompress_get_format(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput)
495 :     {
496 :     BITMAPV4HEADER * inhdr = (BITMAPV4HEADER *)&lpbiInput->bmiHeader;
497 :     BITMAPV4HEADER * outhdr = (BITMAPV4HEADER *)&lpbiOutput->bmiHeader;
498 :     LRESULT result;
499 :    
500 :     if (lpbiOutput == NULL)
501 :     {
502 :     return sizeof(BITMAPV4HEADER);
503 :     }
504 :    
505 :     result = decompress_query(codec, lpbiInput, lpbiOutput);
506 :     if (result != ICERR_OK)
507 :     {
508 :     return result;
509 :     }
510 :    
511 :     memcpy(outhdr, inhdr, sizeof(BITMAPV4HEADER));
512 :     outhdr->bV4Size = sizeof(BITMAPV4HEADER);
513 :     outhdr->bV4V4Compression = FOURCC_YUY2;
514 :     outhdr->bV4SizeImage = outhdr->bV4Width * outhdr->bV4Height * outhdr->bV4BitCount;
515 :     outhdr->bV4XPelsPerMeter = 0;
516 :     outhdr->bV4YPelsPerMeter = 0;
517 :     outhdr->bV4ClrUsed = 0;
518 :     outhdr->bV4ClrImportant = 0;
519 :    
520 :     return ICERR_OK;
521 :     }
522 :    
523 :    
524 :     LRESULT decompress_begin(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput)
525 :     {
526 :     BITMAPV4HEADER * inhdr = (BITMAPV4HEADER *)&lpbiInput->bmiHeader;
527 :     BITMAPV4HEADER * outhdr = (BITMAPV4HEADER *)&lpbiOutput->bmiHeader;
528 :     XVID_DEC_PARAM param;
529 :     XVID_INIT_PARAM init_param;
530 :    
531 :     init_param.cpu_flags = codec->config.cpu;
532 :     xvid_init(0, 0, &init_param, NULL);
533 :     if((codec->config.cpu & XVID_CPU_FORCE) <= 0)
534 :     {
535 :     codec->config.cpu = init_param.cpu_flags;
536 :     }
537 :    
538 :     param.width = inhdr->bV4Width;
539 :     param.height = inhdr->bV4Height;
540 :    
541 :     switch(xvid_decore(0, XVID_DEC_CREATE, &param, NULL))
542 :     {
543 :     case XVID_ERR_FAIL :
544 :     return ICERR_ERROR;
545 :    
546 :     case XVID_ERR_MEMORY :
547 :     return ICERR_MEMORY;
548 :    
549 :     case XVID_ERR_FORMAT :
550 :     return ICERR_BADFORMAT;
551 :     }
552 :    
553 :     codec->dhandle = param.handle;
554 :    
555 :     return ICERR_OK;
556 :     }
557 :    
558 :    
559 :     LRESULT decompress_end(CODEC * codec)
560 :     {
561 :     if (codec->dhandle != NULL)
562 :     {
563 :     xvid_decore(codec->dhandle, XVID_DEC_DESTROY, NULL, NULL);
564 :     codec->dhandle = NULL;
565 :     }
566 :     return ICERR_OK;
567 :     }
568 :    
569 :    
570 :     LRESULT decompress(CODEC * codec, ICDECOMPRESS * icd)
571 :     {
572 :     BITMAPV4HEADER * inhdr = (BITMAPV4HEADER *)icd->lpbiInput;
573 :     BITMAPV4HEADER * outhdr = (BITMAPV4HEADER *)icd->lpbiOutput;
574 :     XVID_DEC_FRAME frame;
575 :    
576 :     frame.bitstream = icd->lpInput;
577 :     frame.length = icd->lpbiInput->biSizeImage;
578 :    
579 :     frame.image = icd->lpOutput;
580 :     frame.stride = icd->lpbiOutput->biWidth;
581 :    
582 :     if (~((icd->dwFlags & ICDECOMPRESS_HURRYUP) | (icd->dwFlags & ICDECOMPRESS_UPDATE)))
583 :     {
584 :     if ((frame.colorspace = get_colorspace(outhdr)) == XVID_CSP_NULL)
585 :     {
586 :     return ICERR_BADFORMAT;
587 :     }
588 :     }
589 :     else
590 :     {
591 :     frame.colorspace = XVID_CSP_NULL;
592 :     }
593 :    
594 :     switch (xvid_decore(codec->dhandle, XVID_DEC_DECODE, &frame, NULL))
595 :     {
596 :     case XVID_ERR_FAIL :
597 :     return ICERR_ERROR;
598 :    
599 :     case XVID_ERR_MEMORY :
600 :     return ICERR_MEMORY;
601 :    
602 :     case XVID_ERR_FORMAT :
603 :     return ICERR_BADFORMAT;
604 :     }
605 :    
606 :     return ICERR_OK;
607 :     }
608 :    
609 :     int codec_2pass_init(CODEC* codec)
610 :     {
611 :     TWOPASS *twopass = &codec->twopass;
612 :     DWORD version = -20;
613 :     DWORD read, wrote;
614 :    
615 :     int frames = 0, credits_frames = 0, i_frames = 0;
616 :     __int64 total = 0, i_total = 0, i_boost_total = 0, start = 0, end = 0, start_curved = 0, end_curved = 0;
617 :     __int64 desired = codec->config.desired_size * 1024;
618 :    
619 :     double total1 = 0.0;
620 :     double total2 = 0.0;
621 :    
622 :     switch (codec->config.mode)
623 :     {
624 :     case DLG_MODE_2PASS_1 :
625 :     twopass->stats1 = CreateFile(codec->config.stats1, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
626 :     if (twopass->stats1 == INVALID_HANDLE_VALUE)
627 :     {
628 :     DEBUG("2pass init error - couldn't create stats1");
629 :     return ICERR_ERROR;
630 :     }
631 :     if (WriteFile(twopass->stats1, &version, sizeof(DWORD), &wrote, 0) == 0 || wrote != sizeof(DWORD))
632 :     {
633 :     CloseHandle(twopass->stats1);
634 :     twopass->stats1 = INVALID_HANDLE_VALUE;
635 :     DEBUG("2pass init error - couldn't write to stats1");
636 :     return ICERR_ERROR;
637 :     }
638 :     break;
639 :    
640 :     case DLG_MODE_2PASS_2_INT :
641 :     case DLG_MODE_2PASS_2_EXT :
642 :     twopass->stats1 = CreateFile(codec->config.stats1, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
643 :     if (twopass->stats1 == INVALID_HANDLE_VALUE)
644 :     {
645 :     DEBUG("2pass init error - couldn't open stats1");
646 :     return ICERR_ERROR;
647 :     }
648 :     if (ReadFile(twopass->stats1, &version, sizeof(DWORD), &read, 0) == 0 || read != sizeof(DWORD))
649 :     {
650 :     CloseHandle(twopass->stats1);
651 :     twopass->stats1 = INVALID_HANDLE_VALUE;
652 :     DEBUG("2pass init error - couldn't read from stats1");
653 :     return ICERR_ERROR;
654 :     }
655 :     if (version != -20)
656 :     {
657 :     CloseHandle(twopass->stats1);
658 :     twopass->stats1 = INVALID_HANDLE_VALUE;
659 :     DEBUG("2pass init error - wrong .stats version");
660 :     return ICERR_ERROR;
661 :     }
662 :    
663 :     if (codec->config.mode == DLG_MODE_2PASS_2_EXT)
664 :     {
665 :     if (twopass->stats2 != INVALID_HANDLE_VALUE)
666 :     {
667 :     CloseHandle(twopass->stats2);
668 :     }
669 :    
670 :     twopass->stats2 = CreateFile(codec->config.stats2, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
671 :    
672 :     if (twopass->stats2 == INVALID_HANDLE_VALUE)
673 :     {
674 :     CloseHandle(twopass->stats1);
675 :     twopass->stats1 = INVALID_HANDLE_VALUE;
676 :     DEBUG("2pass init error - couldn't open stats2");
677 :     return ICERR_ERROR;
678 :     }
679 :     if (ReadFile(twopass->stats2, &version, sizeof(DWORD), &read, 0) == 0 || read != sizeof(DWORD))
680 :     {
681 :     CloseHandle(twopass->stats1);
682 :     twopass->stats1 = INVALID_HANDLE_VALUE;
683 :     CloseHandle(twopass->stats2);
684 :     twopass->stats2 = INVALID_HANDLE_VALUE;
685 :     DEBUG("2pass init error - couldn't read from stats2");
686 :     return ICERR_ERROR;
687 :     }
688 :     if (version != -20)
689 :     {
690 :     CloseHandle(twopass->stats1);
691 :     twopass->stats1 = INVALID_HANDLE_VALUE;
692 :     CloseHandle(twopass->stats2);
693 :     twopass->stats2 = INVALID_HANDLE_VALUE;
694 :     DEBUG("2pass init error - wrong .stats version");
695 :     return ICERR_ERROR;
696 :     }
697 :    
698 :     while (1)
699 :     {
700 :     if (!ReadFile(twopass->stats1, &twopass->nns1, sizeof(NNSTATS), &read, NULL) || read != sizeof(NNSTATS) ||
701 :     !ReadFile(twopass->stats2, &twopass->nns2, sizeof(NNSTATS), &read, NULL) || read != sizeof(NNSTATS))
702 :     {
703 :     DWORD err = GetLastError();
704 :    
705 :     if (err == ERROR_HANDLE_EOF || err == ERROR_SUCCESS)
706 :     {
707 :     break;
708 :     }
709 :     else
710 :     {
711 :     CloseHandle(twopass->stats1);
712 :     CloseHandle(twopass->stats2);
713 :     twopass->stats1 = INVALID_HANDLE_VALUE;
714 :     twopass->stats2 = INVALID_HANDLE_VALUE;
715 :     DEBUG("2pass init error - incomplete stats1/stats2 record?");
716 :     return ICERR_ERROR;
717 :     }
718 :     }
719 :    
720 :     if (!codec_is_in_credits(&codec->config, frames))
721 :     {
722 :     if (twopass->nns1.quant & NNSTATS_KEYFRAME)
723 :     {
724 :     i_boost_total = twopass->nns2.bytes * codec->config.keyframe_boost / 100;
725 :     i_total += twopass->nns2.bytes;
726 :     ++i_frames;
727 :     }
728 :    
729 :     total += twopass->nns2.bytes;
730 :     }
731 :     else
732 :     ++credits_frames;
733 :    
734 :     ++frames;
735 :     }
736 :    
737 :     twopass->movie_curve = ((float)(total + i_boost_total) / total);
738 :     twopass->average_frame = ((double)(total - i_total) / (frames - credits_frames - i_frames) / twopass->movie_curve);
739 :    
740 :     SetFilePointer(twopass->stats1, sizeof(DWORD), 0, FILE_BEGIN);
741 :     SetFilePointer(twopass->stats2, sizeof(DWORD), 0, FILE_BEGIN);
742 :    
743 :     // perform prepass to compensate for over/undersizing
744 :     frames = 0;
745 :    
746 :     while (1)
747 :     {
748 :     if (!ReadFile(twopass->stats1, &twopass->nns1, sizeof(NNSTATS), &read, NULL) || read != sizeof(NNSTATS) ||
749 :     !ReadFile(twopass->stats2, &twopass->nns2, sizeof(NNSTATS), &read, NULL) || read != sizeof(NNSTATS))
750 :     {
751 :     DWORD err = GetLastError();
752 :    
753 :     if (err == ERROR_HANDLE_EOF || err == ERROR_SUCCESS)
754 :     {
755 :     break;
756 :     }
757 :     else
758 :     {
759 :     CloseHandle(twopass->stats1);
760 :     CloseHandle(twopass->stats2);
761 :     twopass->stats1 = INVALID_HANDLE_VALUE;
762 :     twopass->stats2 = INVALID_HANDLE_VALUE;
763 :     DEBUG("2pass init error - incomplete stats1/stats2 record?");
764 :     return ICERR_ERROR;
765 :     }
766 :     }
767 :    
768 :     if (!codec_is_in_credits(&codec->config, frames) &&
769 :     !(twopass->nns1.quant & NNSTATS_KEYFRAME))
770 :     {
771 :     double dbytes = twopass->nns2.bytes / twopass->movie_curve;
772 :     total1 += dbytes;
773 :    
774 :     if (dbytes > twopass->average_frame)
775 :     {
776 :     total2 += ((double)dbytes + (twopass->average_frame - dbytes) *
777 :     codec->config.curve_compression_high / 100.0);
778 :     }
779 :     else
780 :     {
781 :     total2 += ((double)dbytes + (twopass->average_frame - dbytes) *
782 :     codec->config.curve_compression_low / 100.0);
783 :     }
784 :     }
785 :    
786 :     ++frames;
787 :     }
788 :    
789 :     twopass->curve_comp_scale = total1 / total2;
790 :    
791 :     {
792 :     int asymmetric_average_frame;
793 :     char s[100];
794 :    
795 :     asymmetric_average_frame = (int)(twopass->average_frame * twopass->curve_comp_scale);
796 :     wsprintf(s, "middle frame size for asymmetric curve compression: %i", asymmetric_average_frame);
797 :     DEBUG2P(s);
798 :     }
799 :    
800 :     SetFilePointer(twopass->stats1, sizeof(DWORD), 0, FILE_BEGIN);
801 :     SetFilePointer(twopass->stats2, sizeof(DWORD), 0, FILE_BEGIN);
802 :     }
803 :     else // DLG_MODE_2PASS_2_INT
804 :     {
805 :     while (1)
806 :     {
807 :     if (!ReadFile(twopass->stats1, &twopass->nns1, sizeof(NNSTATS), &read, NULL) || read != sizeof(NNSTATS))
808 :     {
809 :     DWORD err = GetLastError();
810 :    
811 :     if (err == ERROR_HANDLE_EOF || err == ERROR_SUCCESS)
812 :     {
813 :     break;
814 :     }
815 :     else
816 :     {
817 :     CloseHandle(twopass->stats1);
818 :     twopass->stats1 = INVALID_HANDLE_VALUE;
819 :     DEBUG("2pass init error - incomplete stats2 record?");
820 :     return ICERR_ERROR;
821 :     }
822 :     }
823 :    
824 :     if (codec_is_in_credits(&codec->config, frames) == CREDITS_START)
825 :     {
826 :     start += twopass->nns1.bytes;
827 :     ++credits_frames;
828 :     }
829 :     else if (codec_is_in_credits(&codec->config, frames) == CREDITS_END)
830 :     {
831 :     end += twopass->nns1.bytes;
832 :     ++credits_frames;
833 :     }
834 :     else if (twopass->nns1.quant & NNSTATS_KEYFRAME)
835 :     {
836 :     i_total += twopass->nns1.bytes + twopass->nns1.bytes * codec->config.keyframe_boost / 100;
837 :     total += twopass->nns1.bytes * codec->config.keyframe_boost / 100;
838 :     ++i_frames;
839 :     }
840 :    
841 :     total += twopass->nns1.bytes;
842 :    
843 :     ++frames;
844 :     }
845 :    
846 :     // compensate for avi frame overhead
847 :     desired -= frames * 24;
848 :    
849 :     switch (codec->config.credits_mode)
850 :     {
851 :     case CREDITS_MODE_RATE :
852 :    
853 :     // credits curve = (total / desired_size) * (100 / credits_rate)
854 :     twopass->credits_start_curve = twopass->credits_end_curve =
855 :     ((float)total / desired) * ((float)100 / codec->config.credits_rate);
856 :    
857 :     start_curved = (__int64)(start / twopass->credits_start_curve);
858 :     end_curved = (__int64)(end / twopass->credits_end_curve);
859 :    
860 :     // movie curve = (total - credits) / (desired_size - curved credits)
861 :     twopass->movie_curve = (float)
862 :     (total - start - end) /
863 :     (desired - start_curved - end_curved);
864 :    
865 :     break;
866 :    
867 :     case CREDITS_MODE_QUANT :
868 :    
869 :     // movie curve = (total - credits) / (desired_size - credits)
870 :     twopass->movie_curve = (float)
871 :     (total - start - end) / (desired - start - end);
872 :    
873 :     // aid the average asymmetric frame calculation below
874 :     start_curved = start;
875 :     end_curved = end;
876 :    
877 :     break;
878 :    
879 :     case CREDITS_MODE_SIZE :
880 :    
881 :     // start curve = (start / start desired size)
882 :     twopass->credits_start_curve = (float)
883 :     (start / 1024) / codec->config.credits_start_size;
884 :    
885 :     // end curve = (end / end desired size)
886 :     twopass->credits_end_curve = (float)
887 :     (end / 1024) / codec->config.credits_end_size;
888 :    
889 :     start_curved = (__int64)(start / twopass->credits_start_curve);
890 :     end_curved = (__int64)(end / twopass->credits_end_curve);
891 :    
892 :     // movie curve = (total - credits) / (desired_size - curved credits)
893 :     twopass->movie_curve = (float)
894 :     (total - start - end) /
895 :     (desired - start_curved - end_curved);
896 :    
897 :     break;
898 :     }
899 :    
900 :     // average frame size = (desired - curved credits - curved keyframes) /
901 :     // (frames - credits frames - keyframes)
902 :     twopass->average_frame = (double)
903 :     (desired - start_curved - end_curved - (i_total / twopass->movie_curve)) /
904 :     (frames - credits_frames - i_frames);
905 :    
906 :     SetFilePointer(twopass->stats1, sizeof(DWORD), 0, FILE_BEGIN);
907 :    
908 :     // perform prepass to compensate for over/undersizing
909 :     frames = 0;
910 :    
911 :     while (1)
912 :     {
913 :     if (!ReadFile(twopass->stats1, &twopass->nns1, sizeof(NNSTATS), &read, NULL) || read != sizeof(NNSTATS))
914 :     {
915 :     DWORD err = GetLastError();
916 :    
917 :     if (err == ERROR_HANDLE_EOF || err == ERROR_SUCCESS)
918 :     {
919 :     break;
920 :     }
921 :     else
922 :     {
923 :     CloseHandle(twopass->stats1);
924 :     twopass->stats1 = INVALID_HANDLE_VALUE;
925 :     DEBUG("2pass init error - incomplete stats2 record?");
926 :     return ICERR_ERROR;
927 :     }
928 :     }
929 :    
930 :     if (!codec_is_in_credits(&codec->config, frames) &&
931 :     !(twopass->nns1.quant & NNSTATS_KEYFRAME))
932 :     {
933 :     double dbytes = twopass->nns1.bytes / twopass->movie_curve;
934 :     total1 += dbytes;
935 :    
936 :     if (dbytes > twopass->average_frame)
937 :     {
938 :     total2 += ((double)dbytes + (twopass->average_frame - dbytes) *
939 :     codec->config.curve_compression_high / 100.0);
940 :     }
941 :     else
942 :     {
943 :     total2 += ((double)dbytes + (twopass->average_frame - dbytes) *
944 :     codec->config.curve_compression_low / 100.0);
945 :     }
946 :     }
947 :    
948 :     ++frames;
949 :     }
950 :    
951 :     twopass->curve_comp_scale = total1 / total2;
952 :    
953 :     {
954 :     int asymmetric_average_frame;
955 :     char s[100];
956 :    
957 :     asymmetric_average_frame = (int)(twopass->average_frame * twopass->curve_comp_scale);
958 :     wsprintf(s, "middle frame size for asymmetric curve compression: %i", asymmetric_average_frame);
959 :     DEBUG2P(s);
960 :     }
961 :    
962 :     SetFilePointer(twopass->stats1, sizeof(DWORD), 0, FILE_BEGIN);
963 :     }
964 :    
965 :     twopass->overflow = 0;
966 :    
967 :     break;
968 :     }
969 :    
970 :     return ICERR_OK;
971 :     }
972 :    
973 :    
974 :     int codec_get_quant(CODEC* codec, XVID_ENC_FRAME* frame)
975 :     {
976 :     switch (codec->config.mode)
977 :     {
978 :     case DLG_MODE_VBR_QUAL :
979 :     if (codec_is_in_credits(&codec->config, codec->framenum))
980 :     {
981 :     switch (codec->config.credits_mode)
982 :     {
983 :     case CREDITS_MODE_RATE :
984 :     frame->quant = codec_get_vbr_quant(&codec->config, codec->config.quality * codec->config.credits_rate / 100);
985 :     break;
986 :    
987 :     case CREDITS_MODE_QUANT :
988 :     frame->quant = codec->config.credits_quant_p;
989 :     break;
990 :    
991 :     default :
992 :     DEBUG("Can't use credits size mode in quality mode");
993 :     return ICERR_ERROR;
994 :     }
995 :     }
996 :     else
997 :     {
998 :     frame->quant = codec_get_vbr_quant(&codec->config, codec->config.quality);
999 :     }
1000 :     return ICERR_OK;
1001 :    
1002 :     case DLG_MODE_VBR_QUANT :
1003 :     if (codec_is_in_credits(&codec->config, codec->framenum))
1004 :     {
1005 :     switch (codec->config.credits_mode)
1006 :     {
1007 :     case CREDITS_MODE_RATE :
1008 :     frame->quant =
1009 :     codec->config.max_quant -
1010 :     ((codec->config.max_quant - codec->config.quant) * codec->config.credits_rate / 100);
1011 :     break;
1012 :    
1013 :     case CREDITS_MODE_QUANT :
1014 :     frame->quant = codec->config.credits_quant_p;
1015 :     break;
1016 :    
1017 :     default :
1018 :     DEBUG("Can't use credits size mode in quantizer mode");
1019 :     return ICERR_ERROR;
1020 :     }
1021 :     }
1022 :     else
1023 :     {
1024 :     frame->quant = codec->config.quant;
1025 :     }
1026 :     return ICERR_OK;
1027 :    
1028 :     case DLG_MODE_2PASS_1 :
1029 :     if (codec->config.credits_mode == CREDITS_MODE_QUANT)
1030 :     {
1031 :     if (codec_is_in_credits(&codec->config, codec->framenum))
1032 :     {
1033 :     frame->quant = codec->config.credits_quant_p;
1034 :     }
1035 :     else
1036 :     {
1037 :     frame->quant = 2;
1038 :     }
1039 :     }
1040 :     else
1041 :     {
1042 :     frame->quant = 2;
1043 :     }
1044 :     return ICERR_OK;
1045 :    
1046 :     default:
1047 :     DEBUG("get quant: invalid mode");
1048 :     return ICERR_ERROR;
1049 :     }
1050 :     }
1051 :    
1052 :    
1053 :     int codec_2pass_get_quant(CODEC* codec, XVID_ENC_FRAME* frame)
1054 :     {
1055 :     static double quant_error[32];
1056 :     static double curve_comp_error;
1057 :     static int last_quant;
1058 :    
1059 :     TWOPASS * twopass = &codec->twopass;
1060 :    
1061 :     DWORD read;
1062 :     int bytes1, bytes2;
1063 :     int overflow;
1064 :     int credits_pos;
1065 :    
1066 :     if (codec->framenum == 0)
1067 :     {
1068 :     int i;
1069 :    
1070 :     for (i=0 ; i<32 ; ++i)
1071 :     {
1072 :     quant_error[i] = 0.0;
1073 :     }
1074 :    
1075 :     curve_comp_error = 0.0;
1076 :     last_quant = 0;
1077 :     }
1078 :    
1079 :     if (ReadFile(twopass->stats1, &twopass->nns1, sizeof(NNSTATS), &read, 0) == 0 || read != sizeof(NNSTATS))
1080 :     {
1081 :     DEBUG("2ndpass quant: couldn't read from stats1");
1082 :     return ICERR_ERROR;
1083 :     }
1084 :     if (codec->config.mode == DLG_MODE_2PASS_2_EXT)
1085 :     {
1086 :     if (ReadFile(twopass->stats2, &twopass->nns2, sizeof(NNSTATS), &read, 0) == 0 || read != sizeof(NNSTATS))
1087 :     {
1088 :     DEBUG("2ndpass quant: couldn't read from stats2");
1089 :     return ICERR_ERROR;
1090 :     }
1091 :     }
1092 :    
1093 :     bytes1 = twopass->nns1.bytes;
1094 :     overflow = twopass->overflow / 8;
1095 :    
1096 :     // override codec i-frame choice (reenable in credits)
1097 :     frame->intra = (twopass->nns1.quant & NNSTATS_KEYFRAME);
1098 :    
1099 :     if (frame->intra)
1100 :     {
1101 :     overflow = 0;
1102 :     }
1103 :    
1104 :     credits_pos = codec_is_in_credits(&codec->config, codec->framenum);
1105 :    
1106 :     if (credits_pos)
1107 :     {
1108 :     if (codec->config.mode == DLG_MODE_2PASS_2_INT)
1109 :     {
1110 :     switch (codec->config.credits_mode)
1111 :     {
1112 :     case CREDITS_MODE_RATE :
1113 :     case CREDITS_MODE_SIZE :
1114 :     if (credits_pos == CREDITS_START)
1115 :     {
1116 :     bytes2 = (int)(bytes1 / twopass->credits_start_curve);
1117 :     }
1118 :     else // CREDITS_END
1119 :     {
1120 :     bytes2 = (int)(bytes1 / twopass->credits_end_curve);
1121 :     }
1122 :    
1123 :     frame->intra = -1;
1124 :     break;
1125 :    
1126 :     case CREDITS_MODE_QUANT :
1127 :     if (codec->config.credits_quant_i != codec->config.credits_quant_p)
1128 :     {
1129 :     frame->quant = frame->intra ?
1130 :     codec->config.credits_quant_i :
1131 :     codec->config.credits_quant_p;
1132 :     }
1133 :     else
1134 :     {
1135 :     frame->quant = codec->config.credits_quant_p;
1136 :     frame->intra = -1;
1137 :     }
1138 :    
1139 :     twopass->bytes1 = bytes1;
1140 :     twopass->bytes2 = bytes1;
1141 :     twopass->desired_bytes2 = bytes1;
1142 :     return ICERR_OK;
1143 :     }
1144 :     }
1145 :     else // DLG_MODE_2PASS_2_EXT
1146 :     {
1147 :     bytes2 = twopass->nns2.bytes;
1148 :     }
1149 :     }
1150 :     else // Foxer: apply curve compression outside credits
1151 :     {
1152 :     double dbytes, curve_temp;
1153 :    
1154 :     bytes2 = (codec->config.mode == DLG_MODE_2PASS_2_INT) ? bytes1 : twopass->nns2.bytes;
1155 :    
1156 :     if (frame->intra)
1157 :     {
1158 :     dbytes = ((int)(bytes2 + bytes2 * codec->config.keyframe_boost / 100)) /
1159 :     twopass->movie_curve;
1160 :     }
1161 :     else
1162 :     {
1163 :     dbytes = bytes2 / twopass->movie_curve;
1164 :     }
1165 :    
1166 :     // spread the compression error across payback_delay frames
1167 :     if (codec->config.bitrate_payback_method == 0)
1168 :     {
1169 :     bytes2 = (int)(curve_comp_error / codec->config.bitrate_payback_delay);
1170 :     }
1171 :     else
1172 :     {
1173 :     bytes2 = (int)(curve_comp_error * dbytes /
1174 :     twopass->average_frame / codec->config.bitrate_payback_delay);
1175 :    
1176 :     if (labs(bytes2) > fabs(curve_comp_error))
1177 :     {
1178 :     bytes2 = (int)curve_comp_error;
1179 :     }
1180 :     }
1181 :    
1182 :     curve_comp_error -= bytes2;
1183 :    
1184 :     if ((codec->config.curve_compression_high + codec->config.curve_compression_low) &&
1185 :     !frame->intra)
1186 :     {
1187 :     if (dbytes > twopass->average_frame)
1188 :     {
1189 :     curve_temp = twopass->curve_comp_scale *
1190 :     ((double)dbytes + (twopass->average_frame - dbytes) *
1191 :     codec->config.curve_compression_high / 100.0);
1192 :     }
1193 :     else
1194 :     {
1195 :     curve_temp = twopass->curve_comp_scale *
1196 :     ((double)dbytes + (twopass->average_frame - dbytes) *
1197 :     codec->config.curve_compression_low / 100.0);
1198 :     }
1199 :    
1200 :     bytes2 += ((int)curve_temp);
1201 :     curve_comp_error += curve_temp - ((int)curve_temp);
1202 :     }
1203 :     else
1204 :     {
1205 :     curve_comp_error += dbytes - ((int)dbytes);
1206 :     bytes2 += ((int)dbytes);
1207 :     }
1208 :    
1209 :     // cap bytes2 to first pass size, lowers number of quant=1 frames
1210 :     if (bytes2 > bytes1)
1211 :     {
1212 :     curve_comp_error += bytes2 - bytes1;
1213 :     bytes2 = bytes1;
1214 :     }
1215 :     else if (bytes2 < 1)
1216 :     {
1217 :     curve_comp_error += --bytes2;
1218 :     bytes2 = 1;
1219 :     }
1220 :     }
1221 :    
1222 :     twopass->desired_bytes2 = bytes2;
1223 :    
1224 :     // Foxer: scale overflow in relation to average size, so smaller frames don't get
1225 :     // too much/little bitrate
1226 :     overflow = (int)((double)overflow * bytes2 / twopass->average_frame);
1227 :    
1228 :     // Foxer: reign in overflow with huge frames
1229 :     if (labs(overflow) > labs(twopass->overflow))
1230 :     {
1231 :     overflow = twopass->overflow;
1232 :     }
1233 :    
1234 :     // Foxer: make sure overflow doesn't run away
1235 :     if (overflow > bytes2 * 6 / 10)
1236 :     {
1237 :     bytes2 += (overflow <= bytes2) ? bytes2 * 6 / 10 : overflow * 6 / 10;
1238 :     }
1239 :     else if (overflow < bytes2 * -6 / 10)
1240 :     {
1241 :     bytes2 += bytes2 * -6 / 10;
1242 :     }
1243 :     else
1244 :     {
1245 :     bytes2 += overflow;
1246 :     }
1247 :    
1248 :     if (bytes2 < 1)
1249 :     {
1250 :     bytes2 = 1;
1251 :     }
1252 :    
1253 :     twopass->bytes1 = bytes1;
1254 :     twopass->bytes2 = bytes2;
1255 :    
1256 :     // very 'simple' quant<->filesize relationship
1257 :     frame->quant = ((twopass->nns1.quant & ~NNSTATS_KEYFRAME) * bytes1) / bytes2;
1258 :    
1259 :     if (frame->quant < 1)
1260 :     {
1261 :     frame->quant = 1;
1262 :     }
1263 :     else if (frame->quant > 31)
1264 :     {
1265 :     frame->quant = 31;
1266 :     }
1267 :     else if (!frame->intra)
1268 :     {
1269 :     // Foxer: aid desired quantizer precision by accumulating decision error
1270 :     quant_error[frame->quant] += ((double)((twopass->nns1.quant & ~NNSTATS_KEYFRAME) *
1271 :     bytes1) / bytes2) - frame->quant;
1272 :    
1273 :     if (quant_error[frame->quant] >= 1.0)
1274 :     {
1275 :     quant_error[frame->quant] -= 1.0;
1276 :     ++frame->quant;
1277 :     }
1278 :     }
1279 :    
1280 :     // we're done with credits
1281 :     if (codec_is_in_credits(&codec->config, codec->framenum))
1282 :     {
1283 :     return ICERR_OK;
1284 :     }
1285 :    
1286 :     if (frame->intra)
1287 :     {
1288 :     if (frame->quant < codec->config.min_iquant)
1289 :     {
1290 :     frame->quant = codec->config.min_iquant;
1291 :     DEBUG2P("I-frame quantizer raised");
1292 :     }
1293 :     if (frame->quant > codec->config.max_iquant)
1294 :     {
1295 :     frame->quant = codec->config.max_iquant;
1296 :     DEBUG2P("I-frame quantizer lowered");
1297 :     }
1298 :     }
1299 :     else
1300 :     {
1301 :     if (frame->quant > codec->config.max_quant)
1302 :     {
1303 :     frame->quant = codec->config.max_quant;
1304 :     }
1305 :     if (frame->quant < codec->config.min_quant)
1306 :     {
1307 :     frame->quant = codec->config.min_quant;
1308 :     }
1309 :    
1310 :     // subsequent frame quants can only be +- 2
1311 :     if (last_quant)
1312 :     {
1313 :     if (frame->quant > last_quant + 2)
1314 :     {
1315 :     frame->quant = last_quant + 2;
1316 :     DEBUG2P("P-frame quantizer prevented from rising too steeply");
1317 :     }
1318 :     if (frame->quant < last_quant - 2)
1319 :     {
1320 :     frame->quant = last_quant - 2;
1321 :     DEBUG2P("P-frame quantizer prevented from falling too steeply");
1322 :     }
1323 :     }
1324 :     }
1325 :    
1326 :     last_quant = frame->quant;
1327 :    
1328 :     return ICERR_OK;
1329 :     }
1330 :    
1331 :    
1332 :     int codec_2pass_update(CODEC* codec, XVID_ENC_FRAME* frame, XVID_ENC_STATS* stats)
1333 :     {
1334 :     static __int64 total_size;
1335 :    
1336 :     NNSTATS nns1;
1337 :     DWORD wrote;
1338 :    
1339 :     if (codec->framenum == 0)
1340 :     {
1341 :     total_size = 0;
1342 :     }
1343 :    
1344 :     switch (codec->config.mode)
1345 :     {
1346 :     case DLG_MODE_2PASS_1 :
1347 :     nns1.bytes = frame->length; // total bytes
1348 :     nns1.dd_v = stats->hlength; // header bytes
1349 :    
1350 :     nns1.dd_u = nns1.dd_y = 0;
1351 :     nns1.dk_v = nns1.dk_u = nns1.dk_y = 0;
1352 :     nns1.md_u = nns1.md_y = 0;
1353 :     nns1.mk_u = nns1.mk_y = 0;
1354 :    
1355 :     nns1.quant = stats->quant;
1356 :     if (frame->intra)
1357 :     {
1358 :     nns1.quant |= NNSTATS_KEYFRAME;
1359 :     }
1360 :     nns1.kblk = stats->kblks;
1361 :     nns1.mblk = stats->mblks;
1362 :     nns1.ublk = stats->ublks;
1363 :     nns1.lum_noise[0] = nns1.lum_noise[1] = 1;
1364 :    
1365 :     total_size += frame->length;
1366 :     DEBUG1ST(frame->length, (int)total_size/1024, frame->intra, frame->quant, stats->kblks, stats->mblks)
1367 :    
1368 :     if (WriteFile(codec->twopass.stats1, &nns1, sizeof(NNSTATS), &wrote, 0) == 0 || wrote != sizeof(NNSTATS))
1369 :     {
1370 :     DEBUG("stats1: WriteFile error");
1371 :     return ICERR_ERROR;
1372 :     }
1373 :     break;
1374 :    
1375 :     case DLG_MODE_2PASS_2_INT :
1376 :     case DLG_MODE_2PASS_2_EXT :
1377 :     codec->twopass.overflow += codec->twopass.desired_bytes2 - frame->length;
1378 :     DEBUG2ND(frame->quant, frame->intra, codec->twopass.bytes1, codec->twopass.desired_bytes2, frame->length, codec->twopass.overflow, codec_is_in_credits(&codec->config, codec->framenum))
1379 :     break;
1380 :    
1381 :     default:
1382 :     break;
1383 :     }
1384 :    
1385 :     return ICERR_OK;
1386 :     }
1387 :    
1388 :    
1389 :     int codec_is_in_credits(CONFIG* config, int framenum)
1390 :     {
1391 :     if (config->mode == DLG_MODE_2PASS_2_EXT)
1392 :     {
1393 :     return 0;
1394 :     }
1395 :    
1396 :     if (config->credits_start)
1397 :     {
1398 :     if (framenum >= config->credits_start_begin &&
1399 :     framenum <= config->credits_start_end)
1400 :     {
1401 :     return CREDITS_START;
1402 :     }
1403 :     }
1404 :    
1405 :     if (config->credits_end)
1406 :     {
1407 :     if (framenum >= config->credits_end_begin &&
1408 :     framenum <= config->credits_end_end)
1409 :     {
1410 :     return CREDITS_END;
1411 :     }
1412 :     }
1413 :    
1414 :     return 0;
1415 :     }
1416 :    
1417 :    
1418 :     int codec_get_vbr_quant(CONFIG* config, int quality)
1419 :     {
1420 :     static float fquant_running = 0;
1421 :     static int my_quality = -1;
1422 :     int quant;
1423 :    
1424 :     // if quality changes, recalculate fquant (credits)
1425 :     if (quality != my_quality)
1426 :     {
1427 :     config->fquant = 0;
1428 :     }
1429 :    
1430 :     my_quality = quality;
1431 :    
1432 :     // desired quantiser = (maxQ-minQ)/100 * (100-qual) + minQ
1433 :     if (!config->fquant)
1434 :     {
1435 :     config->fquant =
1436 :     ((float) (config->max_quant - config->min_quant) / 100) *
1437 :     (100 - quality) +
1438 :     (float) config->min_quant;
1439 :    
1440 :     fquant_running = config->fquant;
1441 :     }
1442 :    
1443 :     if (fquant_running < config->min_quant)
1444 :     {
1445 :     fquant_running = (float) config->min_quant;
1446 :     }
1447 :     else if(fquant_running > config->max_quant)
1448 :     {
1449 :     fquant_running = (float) config->max_quant;
1450 :     }
1451 :    
1452 :     quant = (int) fquant_running;
1453 :    
1454 :     // add error between fquant and quant to fquant_running
1455 :     fquant_running += config->fquant - quant;
1456 :    
1457 :     return quant;
1458 :     }
1459 :    

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4