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

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