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

Annotation of /trunk/vfw/src/2pass.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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