[svn] / branches / dev-api-3 / vfw / src / 2pass.c Repository:
ViewVC logotype

Annotation of /branches/dev-api-3/vfw/src/2pass.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 552 - (view) (download)

1 : h 102 /**************************************************************************
2 :     *
3 :     * XVID 2PASS CODE
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 127 * 17.04.2002 changed 1st pass quant to always be 2 (2pass_update())
27 : h 109 * 07.04.2002 added max bitrate constraint, overflow controls (foxer)
28 : h 102 * 31.03.2002 inital version;
29 :     *
30 :     *************************************************************************/
31 :    
32 :     #include <windows.h>
33 :     #include <math.h>
34 :    
35 :     #include "2pass.h"
36 :    
37 :    
38 :     int codec_2pass_init(CODEC* codec)
39 :     {
40 :     TWOPASS *twopass = &codec->twopass;
41 :     DWORD version = -20;
42 :     DWORD read, wrote;
43 :    
44 : h 552 int frames = 0, credits_frames = 0, i_frames = 0, recminpsize = 0, recminisize = 0;
45 : h 102 __int64 total_ext = 0, total = 0, i_total = 0, i_boost_total = 0, start = 0, end = 0, start_curved = 0, end_curved = 0;
46 :     __int64 desired = (__int64)codec->config.desired_size * 1024;
47 :    
48 :     double total1 = 0.0;
49 :     double total2 = 0.0;
50 : h 528 double dbytes, dbytes2;
51 : h 102
52 :     if (codec->config.hinted_me)
53 :     {
54 :     codec->twopass.hintstream = malloc(100000);
55 :    
56 :     if (codec->twopass.hintstream == NULL)
57 :     {
58 :     DEBUGERR("couldn't allocate memory for mv hints");
59 :     return ICERR_ERROR;
60 :     }
61 :     }
62 :    
63 :     switch (codec->config.mode)
64 :     {
65 :     case DLG_MODE_2PASS_1 :
66 :     twopass->stats1 = CreateFile(codec->config.stats1, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
67 :     if (twopass->stats1 == INVALID_HANDLE_VALUE)
68 :     {
69 :     DEBUGERR("2pass init error - couldn't create stats1");
70 :     return ICERR_ERROR;
71 :     }
72 :     if (WriteFile(twopass->stats1, &version, sizeof(DWORD), &wrote, 0) == 0 || wrote != sizeof(DWORD))
73 :     {
74 :     CloseHandle(twopass->stats1);
75 :     twopass->stats1 = INVALID_HANDLE_VALUE;
76 :     DEBUGERR("2pass init error - couldn't write to stats1");
77 :     return ICERR_ERROR;
78 :     }
79 :     break;
80 :    
81 :     case DLG_MODE_2PASS_2_INT :
82 :     case DLG_MODE_2PASS_2_EXT :
83 :     twopass->stats1 = CreateFile(codec->config.stats1, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
84 :     if (twopass->stats1 == INVALID_HANDLE_VALUE)
85 :     {
86 :     DEBUGERR("2pass init error - couldn't open stats1");
87 :     return ICERR_ERROR;
88 :     }
89 :     if (ReadFile(twopass->stats1, &version, sizeof(DWORD), &read, 0) == 0 || read != sizeof(DWORD))
90 :     {
91 :     CloseHandle(twopass->stats1);
92 :     twopass->stats1 = INVALID_HANDLE_VALUE;
93 :     DEBUGERR("2pass init error - couldn't read from stats1");
94 :     return ICERR_ERROR;
95 :     }
96 :     if (version != -20)
97 :     {
98 :     CloseHandle(twopass->stats1);
99 :     twopass->stats1 = INVALID_HANDLE_VALUE;
100 :     DEBUGERR("2pass init error - wrong .stats version");
101 :     return ICERR_ERROR;
102 :     }
103 :    
104 :     if (codec->config.mode == DLG_MODE_2PASS_2_EXT)
105 :     {
106 :     if (twopass->stats2 != INVALID_HANDLE_VALUE)
107 :     {
108 :     CloseHandle(twopass->stats2);
109 :     }
110 :    
111 :     twopass->stats2 = CreateFile(codec->config.stats2, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
112 :    
113 :     if (twopass->stats2 == INVALID_HANDLE_VALUE)
114 :     {
115 :     CloseHandle(twopass->stats1);
116 :     twopass->stats1 = INVALID_HANDLE_VALUE;
117 :     DEBUGERR("2pass init error - couldn't open stats2");
118 :     return ICERR_ERROR;
119 :     }
120 :     if (ReadFile(twopass->stats2, &version, sizeof(DWORD), &read, 0) == 0 || read != sizeof(DWORD))
121 :     {
122 :     CloseHandle(twopass->stats1);
123 :     twopass->stats1 = INVALID_HANDLE_VALUE;
124 :     CloseHandle(twopass->stats2);
125 :     twopass->stats2 = INVALID_HANDLE_VALUE;
126 :     DEBUGERR("2pass init error - couldn't read from stats2");
127 :     return ICERR_ERROR;
128 :     }
129 :     if (version != -20)
130 :     {
131 :     CloseHandle(twopass->stats1);
132 :     twopass->stats1 = INVALID_HANDLE_VALUE;
133 :     CloseHandle(twopass->stats2);
134 :     twopass->stats2 = INVALID_HANDLE_VALUE;
135 :     DEBUGERR("2pass init error - wrong .stats version");
136 :     return ICERR_ERROR;
137 :     }
138 :    
139 :     while (1)
140 :     {
141 :     if (!ReadFile(twopass->stats1, &twopass->nns1, sizeof(NNSTATS), &read, NULL) || read != sizeof(NNSTATS) ||
142 :     !ReadFile(twopass->stats2, &twopass->nns2, sizeof(NNSTATS), &read, NULL) || read != sizeof(NNSTATS))
143 :     {
144 :     DWORD err = GetLastError();
145 :    
146 :     if (err == ERROR_HANDLE_EOF || err == ERROR_SUCCESS)
147 :     {
148 :     break;
149 :     }
150 :     else
151 :     {
152 :     CloseHandle(twopass->stats1);
153 :     CloseHandle(twopass->stats2);
154 :     twopass->stats1 = INVALID_HANDLE_VALUE;
155 :     twopass->stats2 = INVALID_HANDLE_VALUE;
156 :     DEBUGERR("2pass init error - incomplete stats1/stats2 record?");
157 :     return ICERR_ERROR;
158 :     }
159 :     }
160 :    
161 :     if (!codec_is_in_credits(&codec->config, frames))
162 :     {
163 :     if (twopass->nns1.quant & NNSTATS_KEYFRAME)
164 :     {
165 : h 528 i_boost_total += twopass->nns2.bytes * codec->config.keyframe_boost / 100;
166 : h 102 i_total += twopass->nns2.bytes;
167 : Foxer 342 twopass->keyframe_locations[i_frames] = frames;
168 : h 102 ++i_frames;
169 :     }
170 :    
171 :     total += twopass->nns1.bytes;
172 :     total_ext += twopass->nns2.bytes;
173 :     }
174 :     else
175 :     ++credits_frames;
176 :    
177 : h 552 if (twopass->nns1.quant & NNSTATS_KEYFRAME)
178 :     {
179 :     if (!(twopass->nns1.kblk + twopass->nns1.mblk))
180 :     recminisize = twopass->nns1.bytes;
181 :     }
182 :     else
183 :     {
184 :     if (!(twopass->nns1.kblk + twopass->nns1.mblk))
185 :     recminpsize = twopass->nns1.bytes;
186 :     }
187 :    
188 : h 102 ++frames;
189 :     }
190 : Foxer 342 twopass->keyframe_locations[i_frames] = frames;
191 : h 102
192 :     twopass->movie_curve = ((double)(total_ext + i_boost_total) / total_ext);
193 :     twopass->average_frame = ((double)(total_ext - i_total) / (frames - credits_frames - i_frames) / twopass->movie_curve);
194 :    
195 :     SetFilePointer(twopass->stats1, sizeof(DWORD), 0, FILE_BEGIN);
196 :     SetFilePointer(twopass->stats2, sizeof(DWORD), 0, FILE_BEGIN);
197 :    
198 :     // perform prepass to compensate for over/undersizing
199 :     frames = 0;
200 :    
201 :     if (codec->config.use_alt_curve)
202 :     {
203 :     twopass->alt_curve_low = twopass->average_frame - twopass->average_frame * (double)codec->config.alt_curve_low_dist / 100.0;
204 :     twopass->alt_curve_low_diff = twopass->average_frame - twopass->alt_curve_low;
205 :     twopass->alt_curve_high = twopass->average_frame + twopass->average_frame * (double)codec->config.alt_curve_high_dist / 100.0;
206 :     twopass->alt_curve_high_diff = twopass->alt_curve_high - twopass->average_frame;
207 :     if (codec->config.alt_curve_use_auto)
208 :     {
209 :     if (total > total_ext)
210 :     {
211 :     codec->config.alt_curve_min_rel_qual = (int)(100.0 - (100.0 - 100.0 / ((double)total / (double)total_ext)) * (double)codec->config.alt_curve_auto_str / 100.0);
212 :     if (codec->config.alt_curve_min_rel_qual < 20)
213 :     codec->config.alt_curve_min_rel_qual = 20;
214 :     }
215 :     else
216 :     codec->config.alt_curve_min_rel_qual = 100;
217 :     }
218 :     twopass->alt_curve_mid_qual = (1.0 + (double)codec->config.alt_curve_min_rel_qual / 100.0) / 2.0;
219 :     twopass->alt_curve_qual_dev = 1.0 - twopass->alt_curve_mid_qual;
220 :     if (codec->config.alt_curve_low_dist > 100)
221 :     {
222 :     switch(codec->config.alt_curve_type)
223 :     {
224 :     case 2: // Sine Curve (high aggressiveness)
225 :     twopass->alt_curve_qual_dev *= 2.0 / (1.0 +
226 :     sin(DEG2RAD * (twopass->average_frame * 90.0 / twopass->alt_curve_low_diff)));
227 :     twopass->alt_curve_mid_qual = 1.0 - twopass->alt_curve_qual_dev *
228 :     sin(DEG2RAD * (twopass->average_frame * 90.0 / twopass->alt_curve_low_diff));
229 :     break;
230 :     case 1: // Linear (medium aggressiveness)
231 :     twopass->alt_curve_qual_dev *= 2.0 / (1.0 +
232 :     twopass->average_frame / twopass->alt_curve_low_diff);
233 :     twopass->alt_curve_mid_qual = 1.0 - twopass->alt_curve_qual_dev *
234 :     twopass->average_frame / twopass->alt_curve_low_diff;
235 :     break;
236 :     case 0: // Cosine Curve (low aggressiveness)
237 :     twopass->alt_curve_qual_dev *= 2.0 / (1.0 +
238 :     (1.0 - cos(DEG2RAD * (twopass->average_frame * 90.0 / twopass->alt_curve_low_diff))));
239 :     twopass->alt_curve_mid_qual = 1.0 - twopass->alt_curve_qual_dev *
240 :     (1.0 - cos(DEG2RAD * (twopass->average_frame * 90.0 / twopass->alt_curve_low_diff)));
241 :     }
242 :     }
243 :     }
244 :    
245 :     while (1)
246 :     {
247 :     if (!ReadFile(twopass->stats1, &twopass->nns1, sizeof(NNSTATS), &read, NULL) || read != sizeof(NNSTATS) ||
248 :     !ReadFile(twopass->stats2, &twopass->nns2, sizeof(NNSTATS), &read, NULL) || read != sizeof(NNSTATS))
249 :     {
250 :     DWORD err = GetLastError();
251 :    
252 :     if (err == ERROR_HANDLE_EOF || err == ERROR_SUCCESS)
253 :     {
254 :     break;
255 :     }
256 :     else
257 :     {
258 :     CloseHandle(twopass->stats1);
259 :     CloseHandle(twopass->stats2);
260 :     twopass->stats1 = INVALID_HANDLE_VALUE;
261 :     twopass->stats2 = INVALID_HANDLE_VALUE;
262 :     DEBUGERR("2pass init error - incomplete stats1/stats2 record?");
263 :     return ICERR_ERROR;
264 :     }
265 :     }
266 :    
267 : h 528 if (frames == 0)
268 :     {
269 :     twopass->minpsize = (twopass->nns1.kblk + 88) / 8;
270 :     twopass->minisize = ((twopass->nns1.kblk * 22) + 240) / 8;
271 : h 552 if (recminpsize > twopass->minpsize)
272 :     twopass->minpsize = recminpsize;
273 :     if (recminisize > twopass->minisize)
274 :     twopass->minisize = recminisize;
275 : h 528 }
276 :    
277 : h 102 if (!codec_is_in_credits(&codec->config, frames) &&
278 :     !(twopass->nns1.quant & NNSTATS_KEYFRAME))
279 :     {
280 : h 528 dbytes = twopass->nns2.bytes / twopass->movie_curve;
281 : h 102 total1 += dbytes;
282 :    
283 :     if (codec->config.use_alt_curve)
284 :     {
285 :     if (dbytes > twopass->average_frame)
286 :     {
287 :     if (dbytes >= twopass->alt_curve_high)
288 : h 528 dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev);
289 : h 102 else
290 :     {
291 :     switch(codec->config.alt_curve_type)
292 :     {
293 :     case 2:
294 : h 528 dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
295 : h 102 sin(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_high_diff)));
296 :     break;
297 :     case 1:
298 : h 528 dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
299 : h 102 (dbytes - twopass->average_frame) / twopass->alt_curve_high_diff);
300 :     break;
301 :     case 0:
302 : h 528 dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
303 : h 102 (1.0 - cos(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_high_diff))));
304 :     }
305 :     }
306 :     }
307 :     else
308 :     {
309 :     if (dbytes <= twopass->alt_curve_low)
310 : h 528 dbytes2 = dbytes;
311 : h 102 else
312 :     {
313 :     switch(codec->config.alt_curve_type)
314 :     {
315 :     case 2:
316 : h 528 dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
317 : h 102 sin(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_low_diff)));
318 :     break;
319 :     case 1:
320 : h 528 dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
321 : h 102 (dbytes - twopass->average_frame) / twopass->alt_curve_low_diff);
322 :     break;
323 :     case 0:
324 : h 528 dbytes2 = dbytes * (twopass->alt_curve_mid_qual + twopass->alt_curve_qual_dev *
325 : h 102 (1.0 - cos(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_low_diff))));
326 :     }
327 :     }
328 :     }
329 :     }
330 :     else
331 :     {
332 :     if (dbytes > twopass->average_frame)
333 :     {
334 : h 528 dbytes2 = ((double)dbytes + (twopass->average_frame - dbytes) *
335 : h 102 codec->config.curve_compression_high / 100.0);
336 :     }
337 :     else
338 :     {
339 : h 528 dbytes2 = ((double)dbytes + (twopass->average_frame - dbytes) *
340 : h 102 codec->config.curve_compression_low / 100.0);
341 :     }
342 :     }
343 : h 528
344 :     if (dbytes2 < twopass->minpsize)
345 :     dbytes2 = twopass->minpsize;
346 :    
347 :     total2 += dbytes2;
348 : h 102 }
349 :    
350 :     ++frames;
351 :     }
352 :    
353 :     twopass->curve_comp_scale = total1 / total2;
354 :    
355 :     if (!codec->config.use_alt_curve)
356 :     {
357 :     int asymmetric_average_frame;
358 :     char s[100];
359 :    
360 :     asymmetric_average_frame = (int)(twopass->average_frame * twopass->curve_comp_scale);
361 :     wsprintf(s, "middle frame size for asymmetric curve compression: %i", asymmetric_average_frame);
362 :     DEBUG2P(s);
363 :     }
364 :    
365 :     SetFilePointer(twopass->stats1, sizeof(DWORD), 0, FILE_BEGIN);
366 :     SetFilePointer(twopass->stats2, sizeof(DWORD), 0, FILE_BEGIN);
367 :     }
368 :     else // DLG_MODE_2PASS_2_INT
369 :     {
370 :     while (1)
371 :     {
372 :     if (!ReadFile(twopass->stats1, &twopass->nns1, sizeof(NNSTATS), &read, NULL) || read != sizeof(NNSTATS))
373 :     {
374 :     DWORD err = GetLastError();
375 :    
376 :     if (err == ERROR_HANDLE_EOF || err == ERROR_SUCCESS)
377 :     {
378 :     break;
379 :     }
380 :     else
381 :     {
382 :     CloseHandle(twopass->stats1);
383 :     twopass->stats1 = INVALID_HANDLE_VALUE;
384 :     DEBUGERR("2pass init error - incomplete stats2 record?");
385 :     return ICERR_ERROR;
386 :     }
387 :     }
388 :    
389 :     if (codec_is_in_credits(&codec->config, frames) == CREDITS_START)
390 :     {
391 :     start += twopass->nns1.bytes;
392 :     ++credits_frames;
393 :     }
394 :     else if (codec_is_in_credits(&codec->config, frames) == CREDITS_END)
395 :     {
396 :     end += twopass->nns1.bytes;
397 :     ++credits_frames;
398 :     }
399 :     else if (twopass->nns1.quant & NNSTATS_KEYFRAME)
400 :     {
401 :     i_total += twopass->nns1.bytes + twopass->nns1.bytes * codec->config.keyframe_boost / 100;
402 :     total += twopass->nns1.bytes * codec->config.keyframe_boost / 100;
403 : Foxer 342 twopass->keyframe_locations[i_frames] = frames;
404 : h 102 ++i_frames;
405 :     }
406 :    
407 :     total += twopass->nns1.bytes;
408 :    
409 : h 552 if (twopass->nns1.quant & NNSTATS_KEYFRAME)
410 :     {
411 :     if (!(twopass->nns1.kblk + twopass->nns1.mblk))
412 :     recminisize = twopass->nns1.bytes;
413 :     }
414 :     else
415 :     {
416 :     if (!(twopass->nns1.kblk + twopass->nns1.mblk))
417 :     recminpsize = twopass->nns1.bytes;
418 :     }
419 :    
420 : h 102 ++frames;
421 :     }
422 : Foxer 342 twopass->keyframe_locations[i_frames] = frames;
423 : h 102
424 :     // compensate for avi frame overhead
425 :     desired -= frames * 24;
426 :    
427 :     switch (codec->config.credits_mode)
428 :     {
429 :     case CREDITS_MODE_RATE :
430 :    
431 :     // credits curve = (total / desired_size) * (100 / credits_rate)
432 :     twopass->credits_start_curve = twopass->credits_end_curve =
433 :     ((double)total / desired) * ((double)100 / codec->config.credits_rate);
434 :    
435 :     start_curved = (__int64)(start / twopass->credits_start_curve);
436 :     end_curved = (__int64)(end / twopass->credits_end_curve);
437 :    
438 :     // movie curve = (total - credits) / (desired_size - curved credits)
439 :     twopass->movie_curve = (double)
440 :     (total - start - end) /
441 :     (desired - start_curved - end_curved);
442 :    
443 :     break;
444 :    
445 :     case CREDITS_MODE_QUANT :
446 :    
447 :     // movie curve = (total - credits) / (desired_size - credits)
448 :     twopass->movie_curve = (double)
449 :     (total - start - end) / (desired - start - end);
450 :    
451 :     // aid the average asymmetric frame calculation below
452 :     start_curved = start;
453 :     end_curved = end;
454 :    
455 :     break;
456 :    
457 :     case CREDITS_MODE_SIZE :
458 :    
459 :     // start curve = (start / start desired size)
460 :     twopass->credits_start_curve = (double)
461 :     (start / 1024) / codec->config.credits_start_size;
462 :    
463 :     // end curve = (end / end desired size)
464 :     twopass->credits_end_curve = (double)
465 :     (end / 1024) / codec->config.credits_end_size;
466 :    
467 :     start_curved = (__int64)(start / twopass->credits_start_curve);
468 :     end_curved = (__int64)(end / twopass->credits_end_curve);
469 :    
470 :     // movie curve = (total - credits) / (desired_size - curved credits)
471 :     twopass->movie_curve = (double)
472 :     (total - start - end) /
473 :     (desired - start_curved - end_curved);
474 :    
475 :     break;
476 :     }
477 :    
478 :     // average frame size = (desired - curved credits - curved keyframes) /
479 :     // (frames - credits frames - keyframes)
480 :     twopass->average_frame = (double)
481 :     (desired - start_curved - end_curved - (i_total / twopass->movie_curve)) /
482 :     (frames - credits_frames - i_frames);
483 :    
484 :     SetFilePointer(twopass->stats1, sizeof(DWORD), 0, FILE_BEGIN);
485 :    
486 :     // perform prepass to compensate for over/undersizing
487 :     frames = 0;
488 :    
489 :     if (codec->config.use_alt_curve)
490 :     {
491 :     twopass->alt_curve_low = twopass->average_frame - twopass->average_frame * (double)codec->config.alt_curve_low_dist / 100.0;
492 :     twopass->alt_curve_low_diff = twopass->average_frame - twopass->alt_curve_low;
493 :     twopass->alt_curve_high = twopass->average_frame + twopass->average_frame * (double)codec->config.alt_curve_high_dist / 100.0;
494 :     twopass->alt_curve_high_diff = twopass->alt_curve_high - twopass->average_frame;
495 :     if (codec->config.alt_curve_use_auto)
496 :     {
497 :     if (twopass->movie_curve > 1.0)
498 :     {
499 :     codec->config.alt_curve_min_rel_qual = (int)(100.0 - (100.0 - 100.0 / twopass->movie_curve) * (double)codec->config.alt_curve_auto_str / 100.0);
500 :     if (codec->config.alt_curve_min_rel_qual < 20)
501 :     codec->config.alt_curve_min_rel_qual = 20;
502 :     }
503 :     else
504 :     codec->config.alt_curve_min_rel_qual = 100;
505 :     }
506 :     twopass->alt_curve_mid_qual = (1.0 + (double)codec->config.alt_curve_min_rel_qual / 100.0) / 2.0;
507 :     twopass->alt_curve_qual_dev = 1.0 - twopass->alt_curve_mid_qual;
508 :     if (codec->config.alt_curve_low_dist > 100)
509 :     {
510 :     switch(codec->config.alt_curve_type)
511 :     {
512 :     case 2: // Sine Curve (high aggressiveness)
513 :     twopass->alt_curve_qual_dev *= 2.0 / (1.0 +
514 :     sin(DEG2RAD * (twopass->average_frame * 90.0 / twopass->alt_curve_low_diff)));
515 :     twopass->alt_curve_mid_qual = 1.0 - twopass->alt_curve_qual_dev *
516 :     sin(DEG2RAD * (twopass->average_frame * 90.0 / twopass->alt_curve_low_diff));
517 :     break;
518 :     case 1: // Linear (medium aggressiveness)
519 :     twopass->alt_curve_qual_dev *= 2.0 / (1.0 +
520 :     twopass->average_frame / twopass->alt_curve_low_diff);
521 :     twopass->alt_curve_mid_qual = 1.0 - twopass->alt_curve_qual_dev *
522 :     twopass->average_frame / twopass->alt_curve_low_diff;
523 :     break;
524 :     case 0: // Cosine Curve (low aggressiveness)
525 :     twopass->alt_curve_qual_dev *= 2.0 / (1.0 +
526 :     (1.0 - cos(DEG2RAD * (twopass->average_frame * 90.0 / twopass->alt_curve_low_diff))));
527 :     twopass->alt_curve_mid_qual = 1.0 - twopass->alt_curve_qual_dev *
528 :     (1.0 - cos(DEG2RAD * (twopass->average_frame * 90.0 / twopass->alt_curve_low_diff)));
529 :     }
530 :     }
531 :     }
532 :    
533 :     while (1)
534 :     {
535 :     if (!ReadFile(twopass->stats1, &twopass->nns1, sizeof(NNSTATS), &read, NULL) || read != sizeof(NNSTATS))
536 :     {
537 :     DWORD err = GetLastError();
538 :    
539 :     if (err == ERROR_HANDLE_EOF || err == ERROR_SUCCESS)
540 :     {
541 :     break;
542 :     }
543 :     else
544 :     {
545 :     CloseHandle(twopass->stats1);
546 :     twopass->stats1 = INVALID_HANDLE_VALUE;
547 :     DEBUGERR("2pass init error - incomplete stats2 record?");
548 :     return ICERR_ERROR;
549 :     }
550 :     }
551 :    
552 : h 528 if (frames == 0)
553 :     {
554 :     twopass->minpsize = (twopass->nns1.kblk + 88) / 8;
555 :     twopass->minisize = ((twopass->nns1.kblk * 22) + 240) / 8;
556 : h 552 if (recminpsize > twopass->minpsize)
557 :     twopass->minpsize = recminpsize;
558 :     if (recminisize > twopass->minisize)
559 :     twopass->minisize = recminisize;
560 : h 528 }
561 :    
562 : h 102 if (!codec_is_in_credits(&codec->config, frames) &&
563 :     !(twopass->nns1.quant & NNSTATS_KEYFRAME))
564 :     {
565 : h 528 dbytes = twopass->nns1.bytes / twopass->movie_curve;
566 : h 102 total1 += dbytes;
567 :    
568 :     if (codec->config.use_alt_curve)
569 :     {
570 :     if (dbytes > twopass->average_frame)
571 :     {
572 :     if (dbytes >= twopass->alt_curve_high)
573 : h 528 dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev);
574 : h 102 else
575 :     {
576 :     switch(codec->config.alt_curve_type)
577 :     {
578 :     case 2:
579 : h 528 dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
580 : h 102 sin(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_high_diff)));
581 :     break;
582 :     case 1:
583 : h 528 dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
584 : h 102 (dbytes - twopass->average_frame) / twopass->alt_curve_high_diff);
585 :     break;
586 :     case 0:
587 : h 528 dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
588 : h 102 (1.0 - cos(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_high_diff))));
589 :     }
590 :     }
591 :     }
592 :     else
593 :     {
594 :     if (dbytes <= twopass->alt_curve_low)
595 : h 528 dbytes2 = dbytes;
596 : h 102 else
597 :     {
598 :     switch(codec->config.alt_curve_type)
599 :     {
600 :     case 2:
601 : h 528 dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
602 : h 102 sin(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_low_diff)));
603 :     break;
604 :     case 1:
605 : h 528 dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
606 : h 102 (dbytes - twopass->average_frame) / twopass->alt_curve_low_diff);
607 :     break;
608 :     case 0:
609 : h 528 dbytes2 = dbytes * (twopass->alt_curve_mid_qual + twopass->alt_curve_qual_dev *
610 : h 102 (1.0 - cos(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_low_diff))));
611 :     }
612 :     }
613 :     }
614 :     }
615 :     else
616 :     {
617 :     if (dbytes > twopass->average_frame)
618 :     {
619 : h 528 dbytes2 = ((double)dbytes + (twopass->average_frame - dbytes) *
620 : h 102 codec->config.curve_compression_high / 100.0);
621 :     }
622 :     else
623 :     {
624 : h 528 dbytes2 = ((double)dbytes + (twopass->average_frame - dbytes) *
625 : h 102 codec->config.curve_compression_low / 100.0);
626 :     }
627 :     }
628 : h 528
629 :     if (dbytes2 < twopass->minpsize)
630 :     dbytes2 = twopass->minpsize;
631 :    
632 :     total2 += dbytes2;
633 : h 102 }
634 :    
635 :     ++frames;
636 :     }
637 :    
638 :     twopass->curve_comp_scale = total1 / total2;
639 :    
640 :     if (!codec->config.use_alt_curve)
641 :     {
642 :     int asymmetric_average_frame;
643 :     char s[100];
644 :    
645 :     asymmetric_average_frame = (int)(twopass->average_frame * twopass->curve_comp_scale);
646 :     wsprintf(s, "middle frame size for asymmetric curve compression: %i", asymmetric_average_frame);
647 :     DEBUG2P(s);
648 :     }
649 :    
650 :     SetFilePointer(twopass->stats1, sizeof(DWORD), 0, FILE_BEGIN);
651 :     }
652 :    
653 :     if (codec->config.use_alt_curve)
654 :     {
655 :     if (codec->config.alt_curve_use_auto_bonus_bias)
656 :     codec->config.alt_curve_bonus_bias = codec->config.alt_curve_min_rel_qual;
657 :    
658 :     twopass->curve_bias_bonus = (total1 - total2) * (double)codec->config.alt_curve_bonus_bias / 100.0 / (double)(frames - credits_frames - i_frames);
659 :     twopass->curve_comp_scale = ((total1 - total2) * (1.0 - (double)codec->config.alt_curve_bonus_bias / 100.0) + total2) / total2;
660 :    
661 :    
662 :     // special info for alt curve: bias bonus and quantizer thresholds,
663 :     {
664 :     double curve_temp, dbytes;
665 :     char s[100];
666 :     int i, newquant, percent;
667 :     int oldquant = 1;
668 :    
669 :     wsprintf(s, "avg scaled framesize:%i", (int)(twopass->average_frame));
670 :     DEBUG2P(s);
671 :    
672 :     wsprintf(s, "bias bonus:%i bytes", (int)(twopass->curve_bias_bonus));
673 :     DEBUG2P(s);
674 :    
675 :     for (i=1; i <= (int)(twopass->alt_curve_high*2)+1; i++)
676 :     {
677 :     dbytes = i;
678 :     if (dbytes > twopass->average_frame)
679 :     {
680 :     if (dbytes >= twopass->alt_curve_high)
681 :     curve_temp = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev);
682 :     else
683 :     {
684 :     switch(codec->config.alt_curve_type)
685 :     {
686 :     case 2:
687 :     curve_temp = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
688 :     sin(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_high_diff)));
689 :     break;
690 :     case 1:
691 :     curve_temp = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
692 :     (dbytes - twopass->average_frame) / twopass->alt_curve_high_diff);
693 :     break;
694 :     case 0:
695 :     curve_temp = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
696 :     (1.0 - cos(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_high_diff))));
697 :     }
698 :     }
699 :     }
700 :     else
701 :     {
702 :     if (dbytes <= twopass->alt_curve_low)
703 :     curve_temp = dbytes;
704 :     else
705 :     {
706 :     switch(codec->config.alt_curve_type)
707 :     {
708 :     case 2:
709 :     curve_temp = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
710 :     sin(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_low_diff)));
711 :     break;
712 :     case 1:
713 :     curve_temp = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
714 :     (dbytes - twopass->average_frame) / twopass->alt_curve_low_diff);
715 :     break;
716 :     case 0:
717 :     curve_temp = dbytes * (twopass->alt_curve_mid_qual + twopass->alt_curve_qual_dev *
718 :     (1.0 - cos(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_low_diff))));
719 :     }
720 :     }
721 :     }
722 :    
723 :     if (twopass->movie_curve > 1.0)
724 :     dbytes *= twopass->movie_curve;
725 :    
726 :     newquant = (int)(dbytes * 2.0 / (curve_temp * twopass->curve_comp_scale + twopass->curve_bias_bonus));
727 :     if (newquant > 1)
728 :     {
729 :     if (newquant != oldquant)
730 :     {
731 :     oldquant = newquant;
732 :     percent = (int)((i - twopass->average_frame) * 100.0 / twopass->average_frame);
733 :     wsprintf(s, "quant:%i threshold at %i : %i percent", newquant, i, percent);
734 :     DEBUG2P(s);
735 :     }
736 :     }
737 :     }
738 :     }
739 :     }
740 :    
741 :     twopass->overflow = 0;
742 : Foxer 342 twopass->KFoverflow = 0;
743 :     twopass->KFoverflow_partial = 0;
744 :     twopass->KF_idx = 1;
745 : h 102
746 :     break;
747 :     }
748 :    
749 :     return ICERR_OK;
750 :     }
751 :    
752 :    
753 :     int codec_2pass_get_quant(CODEC* codec, XVID_ENC_FRAME* frame)
754 :     {
755 :     static double quant_error[32];
756 :     static double curve_comp_error;
757 :     static int last_quant;
758 :    
759 :     TWOPASS * twopass = &codec->twopass;
760 :    
761 :     DWORD read;
762 :     int bytes1, bytes2;
763 :     int overflow;
764 :     int credits_pos;
765 : h 109 int capped_to_max_framesize = 0;
766 : Foxer 343 int KFdistance, KF_min_size;
767 : h 102
768 :     if (codec->framenum == 0)
769 :     {
770 :     int i;
771 :    
772 :     for (i=0 ; i<32 ; ++i)
773 :     {
774 :     quant_error[i] = 0.0;
775 : h 105 twopass->quant_count[i] = 0;
776 : h 102 }
777 :    
778 :     curve_comp_error = 0.0;
779 :     last_quant = 0;
780 :     }
781 :    
782 :     if (ReadFile(twopass->stats1, &twopass->nns1, sizeof(NNSTATS), &read, 0) == 0 || read != sizeof(NNSTATS))
783 :     {
784 :     DEBUGERR("2ndpass quant: couldn't read from stats1");
785 :     return ICERR_ERROR;
786 :     }
787 :     if (codec->config.mode == DLG_MODE_2PASS_2_EXT)
788 :     {
789 :     if (ReadFile(twopass->stats2, &twopass->nns2, sizeof(NNSTATS), &read, 0) == 0 || read != sizeof(NNSTATS))
790 :     {
791 :     DEBUGERR("2ndpass quant: couldn't read from stats2");
792 :     return ICERR_ERROR;
793 :     }
794 :     }
795 :    
796 :     bytes1 = twopass->nns1.bytes;
797 :     overflow = twopass->overflow / 8;
798 :    
799 :     // override codec i-frame choice (reenable in credits)
800 :     frame->intra = (twopass->nns1.quant & NNSTATS_KEYFRAME);
801 :    
802 :     if (frame->intra)
803 :     {
804 :     overflow = 0;
805 :     }
806 :    
807 :     credits_pos = codec_is_in_credits(&codec->config, codec->framenum);
808 :    
809 :     if (credits_pos)
810 :     {
811 :     if (codec->config.mode == DLG_MODE_2PASS_2_INT)
812 :     {
813 :     switch (codec->config.credits_mode)
814 :     {
815 :     case CREDITS_MODE_RATE :
816 :     case CREDITS_MODE_SIZE :
817 :     if (credits_pos == CREDITS_START)
818 :     {
819 :     bytes2 = (int)(bytes1 / twopass->credits_start_curve);
820 :     }
821 :     else // CREDITS_END
822 :     {
823 :     bytes2 = (int)(bytes1 / twopass->credits_end_curve);
824 :     }
825 :    
826 :     frame->intra = -1;
827 :     break;
828 :    
829 :     case CREDITS_MODE_QUANT :
830 :     if (codec->config.credits_quant_i != codec->config.credits_quant_p)
831 :     {
832 :     frame->quant = frame->intra ?
833 :     codec->config.credits_quant_i :
834 :     codec->config.credits_quant_p;
835 :     }
836 :     else
837 :     {
838 :     frame->quant = codec->config.credits_quant_p;
839 :     frame->intra = -1;
840 :     }
841 :    
842 :     twopass->bytes1 = bytes1;
843 :     twopass->bytes2 = bytes1;
844 :     twopass->desired_bytes2 = bytes1;
845 :     return ICERR_OK;
846 :     }
847 :     }
848 :     else // DLG_MODE_2PASS_2_EXT
849 :     {
850 : h 528 if (codec->config.credits_mode == CREDITS_MODE_QUANT)
851 :     {
852 :     if (codec->config.credits_quant_i != codec->config.credits_quant_p)
853 :     {
854 :     frame->quant = frame->intra ?
855 :     codec->config.credits_quant_i :
856 :     codec->config.credits_quant_p;
857 :     }
858 :     else
859 :     {
860 :     frame->quant = codec->config.credits_quant_p;
861 :     frame->intra = -1;
862 :     }
863 :    
864 :     twopass->bytes1 = bytes1;
865 :     twopass->bytes2 = bytes1;
866 :     twopass->desired_bytes2 = bytes1;
867 :     return ICERR_OK;
868 :     }
869 :     else
870 :     bytes2 = twopass->nns2.bytes;
871 : h 102 }
872 :     }
873 :     else // Foxer: apply curve compression outside credits
874 :     {
875 :     double dbytes, curve_temp;
876 :    
877 :     bytes2 = (codec->config.mode == DLG_MODE_2PASS_2_INT) ? bytes1 : twopass->nns2.bytes;
878 :    
879 :     if (frame->intra)
880 :     {
881 :     dbytes = ((int)(bytes2 + bytes2 * codec->config.keyframe_boost / 100)) /
882 :     twopass->movie_curve;
883 :     }
884 :     else
885 :     {
886 :     dbytes = bytes2 / twopass->movie_curve;
887 :     }
888 :    
889 :     // spread the compression error across payback_delay frames
890 :     if (codec->config.bitrate_payback_method == 0)
891 :     {
892 :     bytes2 = (int)(curve_comp_error / codec->config.bitrate_payback_delay);
893 :     }
894 :     else
895 :     {
896 :     bytes2 = (int)(curve_comp_error * dbytes /
897 :     twopass->average_frame / codec->config.bitrate_payback_delay);
898 :    
899 :     if (labs(bytes2) > fabs(curve_comp_error))
900 :     {
901 :     bytes2 = (int)curve_comp_error;
902 :     }
903 :     }
904 :    
905 :     curve_comp_error -= bytes2;
906 :    
907 :     if (codec->config.use_alt_curve)
908 :     {
909 :     if (!frame->intra)
910 :     {
911 :     if (dbytes > twopass->average_frame)
912 :     {
913 :     if (dbytes >= twopass->alt_curve_high)
914 :     curve_temp = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev);
915 :     else
916 :     {
917 :     switch(codec->config.alt_curve_type)
918 :     {
919 :     case 2:
920 :     curve_temp = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
921 :     sin(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_high_diff)));
922 :     break;
923 :     case 1:
924 :     curve_temp = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
925 :     (dbytes - twopass->average_frame) / twopass->alt_curve_high_diff);
926 :     break;
927 :     case 0:
928 :     curve_temp = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
929 :     (1.0 - cos(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_high_diff))));
930 :     }
931 :     }
932 :     }
933 :     else
934 :     {
935 :     if (dbytes <= twopass->alt_curve_low)
936 :     curve_temp = dbytes;
937 :     else
938 :     {
939 :     switch(codec->config.alt_curve_type)
940 :     {
941 :     case 2:
942 :     curve_temp = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
943 :     sin(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_low_diff)));
944 :     break;
945 :     case 1:
946 :     curve_temp = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev *
947 :     (dbytes - twopass->average_frame) / twopass->alt_curve_low_diff);
948 :     break;
949 :     case 0:
950 :     curve_temp = dbytes * (twopass->alt_curve_mid_qual + twopass->alt_curve_qual_dev *
951 :     (1.0 - cos(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_low_diff))));
952 :     }
953 :     }
954 :     }
955 :     curve_temp = curve_temp * twopass->curve_comp_scale + twopass->curve_bias_bonus;
956 :    
957 :     bytes2 += ((int)curve_temp);
958 :     curve_comp_error += curve_temp - ((int)curve_temp);
959 :     }
960 :     else
961 :     {
962 :     curve_comp_error += dbytes - ((int)dbytes);
963 :     bytes2 += ((int)dbytes);
964 :     }
965 :     }
966 :     else if ((codec->config.curve_compression_high + codec->config.curve_compression_low) &&
967 :     !frame->intra)
968 :     {
969 :     if (dbytes > twopass->average_frame)
970 :     {
971 :     curve_temp = twopass->curve_comp_scale *
972 :     ((double)dbytes + (twopass->average_frame - dbytes) *
973 :     codec->config.curve_compression_high / 100.0);
974 :     }
975 :     else
976 :     {
977 :     curve_temp = twopass->curve_comp_scale *
978 :     ((double)dbytes + (twopass->average_frame - dbytes) *
979 :     codec->config.curve_compression_low / 100.0);
980 :     }
981 :    
982 :     bytes2 += ((int)curve_temp);
983 :     curve_comp_error += curve_temp - ((int)curve_temp);
984 :     }
985 :     else
986 :     {
987 :     curve_comp_error += dbytes - ((int)dbytes);
988 :     bytes2 += ((int)dbytes);
989 :     }
990 :    
991 : h 552 // cap bytes2 to first pass size, lowers number of quant=1 frames
992 :     if (bytes2 > bytes1)
993 : h 102 {
994 : h 552 curve_comp_error += bytes2 - bytes1;
995 :     bytes2 = bytes1;
996 : h 102 }
997 : h 528 else
998 : h 102 {
999 : h 552 if (frame->intra)
1000 : h 528 {
1001 : h 552 if (bytes2 < twopass->minisize)
1002 :     {
1003 :     curve_comp_error -= twopass->minisize - bytes2;
1004 :     bytes2 = twopass->minisize;
1005 :     }
1006 : h 528 }
1007 :     else if (bytes2 < twopass->minpsize)
1008 :     bytes2 = twopass->minpsize;
1009 : h 102 }
1010 :     }
1011 :    
1012 :     twopass->desired_bytes2 = bytes2;
1013 :    
1014 : Foxer 365 // if this keyframe is too close to the next,
1015 :     // reduce it's byte allotment
1016 :     if (frame->intra && !credits_pos)
1017 : Foxer 343 {
1018 :     KFdistance = codec->twopass.keyframe_locations[codec->twopass.KF_idx] -
1019 :     codec->twopass.keyframe_locations[codec->twopass.KF_idx - 1];
1020 :    
1021 :     if (KFdistance < codec->config.kftreshold)
1022 :     {
1023 :     KFdistance = KFdistance - codec->config.min_key_interval;
1024 :    
1025 :     if (KFdistance >= 0)
1026 :     {
1027 :     KF_min_size = bytes2 * (100 - codec->config.kfreduction) / 100;
1028 :     if (KF_min_size < 1)
1029 :     KF_min_size = 1;
1030 :    
1031 :     bytes2 = KF_min_size + (bytes2 - KF_min_size) * KFdistance /
1032 :     (codec->config.kftreshold - codec->config.min_key_interval);
1033 :    
1034 :     if (bytes2 < 1)
1035 :     bytes2 = 1;
1036 :     }
1037 :     }
1038 :     }
1039 :    
1040 : h 102 // Foxer: scale overflow in relation to average size, so smaller frames don't get
1041 :     // too much/little bitrate
1042 : h 552 overflow = (int)((double)overflow * bytes2 / twopass->average_frame);
1043 : h 102
1044 :     // Foxer: reign in overflow with huge frames
1045 :     if (labs(overflow) > labs(twopass->overflow))
1046 :     {
1047 :     overflow = twopass->overflow;
1048 :     }
1049 :    
1050 :     // Foxer: make sure overflow doesn't run away
1051 : h 109 if (overflow > bytes2 * codec->config.twopass_max_overflow_improvement / 100)
1052 : h 102 {
1053 : h 109 bytes2 += (overflow <= bytes2) ? bytes2 * codec->config.twopass_max_overflow_improvement / 100 :
1054 :     overflow * codec->config.twopass_max_overflow_improvement / 100;
1055 : h 102 }
1056 : h 109 else if (overflow < bytes2 * codec->config.twopass_max_overflow_degradation / -100)
1057 : h 102 {
1058 : h 109 bytes2 += bytes2 * codec->config.twopass_max_overflow_degradation / -100;
1059 : h 102 }
1060 :     else
1061 :     {
1062 :     bytes2 += overflow;
1063 :     }
1064 :    
1065 : h 109 if (bytes2 > twopass->max_framesize)
1066 :     {
1067 :     capped_to_max_framesize = 1;
1068 :     bytes2 = twopass->max_framesize;
1069 :     }
1070 :    
1071 : h 552 // make sure to not scale below the minimum framesize
1072 :     if (twopass->nns1.quant & NNSTATS_KEYFRAME)
1073 : h 102 {
1074 : h 552 if (bytes2 < twopass->minisize)
1075 :     bytes2 = twopass->minisize;
1076 : h 102 }
1077 : h 552 else if (bytes2 < twopass->minpsize)
1078 :     bytes2 = twopass->minpsize;
1079 : h 102
1080 :     twopass->bytes1 = bytes1;
1081 :     twopass->bytes2 = bytes2;
1082 :    
1083 :     // very 'simple' quant<->filesize relationship
1084 :     frame->quant = ((twopass->nns1.quant & ~NNSTATS_KEYFRAME) * bytes1) / bytes2;
1085 :    
1086 :     if (frame->quant < 1)
1087 :     {
1088 :     frame->quant = 1;
1089 :     }
1090 :     else if (frame->quant > 31)
1091 :     {
1092 :     frame->quant = 31;
1093 :     }
1094 :     else if (!frame->intra)
1095 :     {
1096 :     // Foxer: aid desired quantizer precision by accumulating decision error
1097 :     quant_error[frame->quant] += ((double)((twopass->nns1.quant & ~NNSTATS_KEYFRAME) *
1098 :     bytes1) / bytes2) - frame->quant;
1099 :    
1100 :     if (quant_error[frame->quant] >= 1.0)
1101 :     {
1102 :     quant_error[frame->quant] -= 1.0;
1103 :     ++frame->quant;
1104 :     }
1105 :     }
1106 :    
1107 :     // we're done with credits
1108 :     if (codec_is_in_credits(&codec->config, codec->framenum))
1109 :     {
1110 :     return ICERR_OK;
1111 :     }
1112 :    
1113 :     if (frame->intra)
1114 :     {
1115 :     if (frame->quant < codec->config.min_iquant)
1116 :     {
1117 :     frame->quant = codec->config.min_iquant;
1118 :     DEBUG2P("I-frame quantizer raised");
1119 :     }
1120 :     if (frame->quant > codec->config.max_iquant)
1121 :     {
1122 :     frame->quant = codec->config.max_iquant;
1123 :     DEBUG2P("I-frame quantizer lowered");
1124 :     }
1125 :     }
1126 :     else
1127 :     {
1128 :     if (frame->quant > codec->config.max_pquant)
1129 :     {
1130 :     frame->quant = codec->config.max_pquant;
1131 :     }
1132 :     if (frame->quant < codec->config.min_pquant)
1133 :     {
1134 :     frame->quant = codec->config.min_pquant;
1135 :     }
1136 :    
1137 :     // subsequent frame quants can only be +- 2
1138 : h 109 if (last_quant && capped_to_max_framesize == 0)
1139 : h 102 {
1140 :     if (frame->quant > last_quant + 2)
1141 :     {
1142 :     frame->quant = last_quant + 2;
1143 :     DEBUG2P("P-frame quantizer prevented from rising too steeply");
1144 :     }
1145 :     if (frame->quant < last_quant - 2)
1146 :     {
1147 :     frame->quant = last_quant - 2;
1148 :     DEBUG2P("P-frame quantizer prevented from falling too steeply");
1149 :     }
1150 :     }
1151 :     }
1152 :    
1153 : h 109 if (capped_to_max_framesize == 0)
1154 :     last_quant = frame->quant;
1155 : h 102
1156 :     if (codec->config.quant_type == QUANT_MODE_MOD)
1157 :     {
1158 :     frame->general |= (frame->quant < 4) ? XVID_MPEGQUANT : XVID_H263QUANT;
1159 :     frame->general &= (frame->quant < 4) ? ~XVID_H263QUANT : ~XVID_MPEGQUANT;
1160 :     }
1161 :    
1162 :     return ICERR_OK;
1163 :     }
1164 :    
1165 :    
1166 :     int codec_2pass_update(CODEC* codec, XVID_ENC_FRAME* frame, XVID_ENC_STATS* stats)
1167 :     {
1168 :     static __int64 total_size;
1169 :    
1170 :     NNSTATS nns1;
1171 :     DWORD wrote;
1172 : Foxer 342 int credits_pos, tempdiv;
1173 : h 102 char* quant_type;
1174 :    
1175 :     if (codec->framenum == 0)
1176 :     {
1177 :     total_size = 0;
1178 :     }
1179 :    
1180 :     quant_type = (frame->general & XVID_H263QUANT) ? "H.263" :
1181 :     ((frame->general & XVID_MPEGQUANT) && (frame->general & XVID_CUSTOM_QMATRIX)) ?
1182 :     "Cust" : "MPEG";
1183 :    
1184 :     switch (codec->config.mode)
1185 :     {
1186 :     case DLG_MODE_2PASS_1 :
1187 :     nns1.bytes = frame->length; // total bytes
1188 :     nns1.dd_v = stats->hlength; // header bytes
1189 :    
1190 :     nns1.dd_u = nns1.dd_y = 0;
1191 :     nns1.dk_v = nns1.dk_u = nns1.dk_y = 0;
1192 :     nns1.md_u = nns1.md_y = 0;
1193 :     nns1.mk_u = nns1.mk_y = 0;
1194 :    
1195 : h 127 // nns1.quant = stats->quant;
1196 :     nns1.quant = 2; // ugly fix for lumi masking in 1st pass returning new quant
1197 : h 102 if (frame->intra)
1198 :     {
1199 :     nns1.quant |= NNSTATS_KEYFRAME;
1200 :     }
1201 :     nns1.kblk = stats->kblks;
1202 :     nns1.mblk = stats->mblks;
1203 :     nns1.ublk = stats->ublks;
1204 :     nns1.lum_noise[0] = nns1.lum_noise[1] = 1;
1205 :    
1206 :     total_size += frame->length;
1207 :    
1208 :     DEBUG1ST(frame->length, (int)total_size/1024, frame->intra, frame->quant, quant_type, stats->kblks, stats->mblks)
1209 :    
1210 :     if (WriteFile(codec->twopass.stats1, &nns1, sizeof(NNSTATS), &wrote, 0) == 0 || wrote != sizeof(NNSTATS))
1211 :     {
1212 :     DEBUGERR("stats1: WriteFile error");
1213 :     return ICERR_ERROR;
1214 :     }
1215 :     break;
1216 :    
1217 :     case DLG_MODE_2PASS_2_INT :
1218 :     case DLG_MODE_2PASS_2_EXT :
1219 : h 105 credits_pos = codec_is_in_credits(&codec->config, codec->framenum);
1220 :     if (!credits_pos)
1221 : Foxer 342 {
1222 : h 105 codec->twopass.quant_count[frame->quant]++;
1223 : Foxer 342 if ((codec->twopass.nns1.quant & NNSTATS_KEYFRAME))
1224 :     {
1225 : Foxer 365 // calculate how much to distribute per frame in
1226 :     // order to make up for this keyframe's overflow
1227 :    
1228 : Foxer 342 codec->twopass.overflow += codec->twopass.KFoverflow;
1229 :     codec->twopass.KFoverflow = codec->twopass.desired_bytes2 - frame->length;
1230 : h 105
1231 : Foxer 342 tempdiv = (codec->twopass.keyframe_locations[codec->twopass.KF_idx] -
1232 :     codec->twopass.keyframe_locations[codec->twopass.KF_idx - 1]);
1233 :    
1234 :     if (tempdiv > 1)
1235 :     {
1236 :     // non-consecutive keyframes
1237 :     codec->twopass.KFoverflow_partial = codec->twopass.KFoverflow / (tempdiv - 1);
1238 :     }
1239 :     else
1240 :     {
1241 :     // consecutive keyframes
1242 :     codec->twopass.overflow += codec->twopass.KFoverflow;
1243 :     codec->twopass.KFoverflow = 0;
1244 :     codec->twopass.KFoverflow_partial = 0;
1245 :     }
1246 :     codec->twopass.KF_idx++;
1247 :     }
1248 :     else
1249 :     {
1250 : Foxer 365 // distribute part of the keyframe overflow
1251 :    
1252 : Foxer 342 codec->twopass.overflow += codec->twopass.desired_bytes2 - frame->length +
1253 :     codec->twopass.KFoverflow_partial;
1254 :     codec->twopass.KFoverflow -= codec->twopass.KFoverflow_partial;
1255 :     }
1256 :     }
1257 :     else
1258 :     {
1259 :     codec->twopass.overflow += codec->twopass.desired_bytes2 - frame->length;
1260 :    
1261 :     // ugly fix for credits..
1262 :     codec->twopass.overflow += codec->twopass.KFoverflow;
1263 :     codec->twopass.KFoverflow = 0;
1264 :     codec->twopass.KFoverflow_partial = 0;
1265 :     // end of ugly fix.
1266 :     }
1267 :    
1268 : h 105 DEBUG2ND(frame->quant, quant_type, frame->intra, codec->twopass.bytes1, codec->twopass.desired_bytes2, frame->length, codec->twopass.overflow, credits_pos)
1269 : h 102 break;
1270 :    
1271 :     default:
1272 :     break;
1273 :     }
1274 :    
1275 :     return ICERR_OK;
1276 :     }
1277 :    
1278 : h 105 void codec_2pass_finish(CODEC* codec)
1279 :     {
1280 :     int i;
1281 :     char s[100];
1282 :     if (codec->config.mode == DLG_MODE_2PASS_2_EXT || codec->config.mode == DLG_MODE_2PASS_2_INT)
1283 :     {
1284 :     // output the quantizer distribution for this encode.
1285 : h 102
1286 : h 105 OutputDebugString("Quantizer distribution for 2nd pass:");
1287 :     for (i=1; i<=31; i++)
1288 :     {
1289 :     if (codec->twopass.quant_count[i])
1290 :     {
1291 :     wsprintf(s, "Q:%i:%i", i, codec->twopass.quant_count[i]);
1292 :     OutputDebugString(s);
1293 :     }
1294 :     }
1295 :     return;
1296 :     }
1297 : h 552 }
1298 :    

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