Parent Directory | Revision Log
Revision 1.1.2.1 - (view) (download)
1 : | suxen_drol | 1.1.2.1 | /****************************************************************************** |
2 : | * | ||
3 : | * XviD Bit Rate Controller Library | ||
4 : | * - VBR 2 pass bitrate controler implementation - | ||
5 : | * | ||
6 : | * Copyright (C) 2002 Edouard Gomez <ed.gomez@wanadoo.fr> | ||
7 : | * | ||
8 : | * The curve treatment algorithm is the one implemented by Foxer <email?> and | ||
9 : | * Dirk Knop <dknop@gwdg.de> for the XviD vfw dynamic library. | ||
10 : | * | ||
11 : | * This program is free software; you can redistribute it and/or modify | ||
12 : | * it under the terms of the GNU General Public License as published by | ||
13 : | * the Free Software Foundation; either version 2 of the License, or | ||
14 : | * (at your option) any later version. | ||
15 : | * | ||
16 : | * This program is distributed in the hope that it will be useful, | ||
17 : | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 : | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 : | * GNU General Public License for more details. | ||
20 : | * | ||
21 : | * You should have received a copy of the GNU General Public License | ||
22 : | * along with this program; if not, write to the Free Software | ||
23 : | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 : | * | ||
25 : | * $Id$ | ||
26 : | * | ||
27 : | *****************************************************************************/ | ||
28 : | |||
29 : | #include <stdio.h> | ||
30 : | #include <math.h> | ||
31 : | |||
32 : | #define RAD2DEG 57.295779513082320876798154814105 | ||
33 : | #define DEG2RAD 0.017453292519943295769236907684886 | ||
34 : | |||
35 : | #include "../xvid.h" | ||
36 : | #include "../image/image.h" | ||
37 : | |||
38 : | typedef struct { | ||
39 : | int type; /* first pass type */ | ||
40 : | int quant; /* first pass quant */ | ||
41 : | int length; /* first pass length */ | ||
42 : | int scaled_length; /* scaled length */ | ||
43 : | int desired_length; | ||
44 : | } stat_t; | ||
45 : | |||
46 : | |||
47 : | |||
48 : | |||
49 : | /* context struct */ | ||
50 : | typedef struct | ||
51 : | { | ||
52 : | xvid_plugin_2pass2_t param; | ||
53 : | |||
54 : | /* constant statistical data */ | ||
55 : | int num_frames; | ||
56 : | int num_keyframes; | ||
57 : | |||
58 : | int count[3]; /* count of each frame types */ | ||
59 : | uint64_t tot_length[3]; /* total length of each frame types */ | ||
60 : | double avg_length[3]; /* avg */ | ||
61 : | int min_length[3]; /* min frame length of each frame types */ | ||
62 : | uint64_t tot_scaled_length[3]; /* total scaled length of each frame type */ | ||
63 : | int max_length; /* max frame size */ | ||
64 : | |||
65 : | double curve_comp_scale; | ||
66 : | double movie_curve; | ||
67 : | |||
68 : | double alt_curve_low; | ||
69 : | double alt_curve_high; | ||
70 : | double alt_curve_low_diff; | ||
71 : | double alt_curve_high_diff; | ||
72 : | double alt_curve_curve_bias_bonus; | ||
73 : | double alt_curve_mid_qual; | ||
74 : | double alt_curve_qual_dev; | ||
75 : | |||
76 : | /* dynamic */ | ||
77 : | |||
78 : | int * keyframe_locations; | ||
79 : | stat_t * stats; | ||
80 : | |||
81 : | double pquant_error[32]; | ||
82 : | double bquant_error[32]; | ||
83 : | int quant_count[32]; | ||
84 : | int last_quant[3]; | ||
85 : | |||
86 : | double curve_comp_error; | ||
87 : | int overflow; | ||
88 : | int KFoverflow; | ||
89 : | int KFoverflow_partial; | ||
90 : | int KF_idx; | ||
91 : | } rc_2pass2_t; | ||
92 : | |||
93 : | |||
94 : | |||
95 : | #define BUF_SZ 1024 | ||
96 : | #define MAX_COLS 5 | ||
97 : | |||
98 : | |||
99 : | /* open stats file, and count num frames */ | ||
100 : | |||
101 : | static int det_stats_length(rc_2pass2_t * rc, char * filename) | ||
102 : | { | ||
103 : | FILE * f; | ||
104 : | int n, ignore; | ||
105 : | char type; | ||
106 : | |||
107 : | rc->num_frames = 0; | ||
108 : | rc->num_keyframes = 0; | ||
109 : | |||
110 : | if ((f = fopen(filename, "rt")) == NULL) | ||
111 : | return 0; | ||
112 : | |||
113 : | while((n = fscanf(f, "%c %d %d %d %d %d\n", | ||
114 : | &type, &ignore, &ignore, &ignore, &ignore, &ignore)) != EOF) { | ||
115 : | if (type == 'i') { | ||
116 : | rc->num_frames++; | ||
117 : | rc->num_keyframes++; | ||
118 : | }else if (type == 'p' || type == 'b' || type == 's') { | ||
119 : | rc->num_frames++; | ||
120 : | } | ||
121 : | } | ||
122 : | |||
123 : | fclose(f); | ||
124 : | |||
125 : | return 1; | ||
126 : | } | ||
127 : | |||
128 : | |||
129 : | /* open stats file(s) and read into rc->stats array */ | ||
130 : | |||
131 : | static int load_stats(rc_2pass2_t *rc, char * filename1, char * filename2) | ||
132 : | { | ||
133 : | FILE * f1, *f2; | ||
134 : | int i; | ||
135 : | |||
136 : | |||
137 : | if ((f1 = fopen(filename1, "rt"))==NULL) | ||
138 : | return 0; | ||
139 : | |||
140 : | if ((f2 = fopen(filename2, "rt"))==NULL) { | ||
141 : | fclose(f1); | ||
142 : | return 0; | ||
143 : | } | ||
144 : | |||
145 : | i = 0; | ||
146 : | while(i < rc->num_frames) { | ||
147 : | stat_t * s = &rc->stats[i]; | ||
148 : | int n, ignore; | ||
149 : | char type; | ||
150 : | |||
151 : | n = fscanf(f1, "%c %d %d %d %d %d\n", &type, &s->quant, &s->length, &ignore, &ignore, &ignore); | ||
152 : | if (n == EOF) break; | ||
153 : | |||
154 : | if (type == 'i') { | ||
155 : | s->type = XVID_TYPE_IVOP; | ||
156 : | }else if (type == 'p' || type == 's') { | ||
157 : | s->type = XVID_TYPE_PVOP; | ||
158 : | }else if (type == 'b') { | ||
159 : | s->type = XVID_TYPE_BVOP; | ||
160 : | }else{ /* unknown type */ | ||
161 : | printf("unk\n"); | ||
162 : | continue; | ||
163 : | } | ||
164 : | |||
165 : | n = fscanf(f2, "%c %d %d %d %d %d\n", &type, &ignore, &s->scaled_length, &ignore, &ignore, &ignore); | ||
166 : | if (n == EOF) break; | ||
167 : | if (type != 'i'&& type != 'p' && type != 'b' && type != 's') { | ||
168 : | printf("unk\n"); | ||
169 : | continue; /* unknown type */ | ||
170 : | } | ||
171 : | |||
172 : | i++; | ||
173 : | } | ||
174 : | rc->num_frames = i; | ||
175 : | |||
176 : | |||
177 : | fclose(f1); | ||
178 : | if (filename2) | ||
179 : | fclose(f2); | ||
180 : | |||
181 : | return 1; | ||
182 : | } | ||
183 : | |||
184 : | |||
185 : | /*static void internal_scale(rc_2pass2_t *rc) | ||
186 : | { | ||
187 : | const double avg_pvop = rc->avg_length[XVID_TYPE_PVOP-1]; | ||
188 : | const double avg_bvop = rc->avg_length[XVID_TYPE_BVOP-1]; | ||
189 : | const uint64_t tot_pvop = rc->tot_length[XVID_TYPE_PVOP-1]; | ||
190 : | const uint64_t tot_bvop = rc->tot_length[XVID_TYPE_BVOP-1]; | ||
191 : | uint64_t i_total = 0; | ||
192 : | double total1,total2; | ||
193 : | int i; | ||
194 : | |||
195 : | for (i=0; i<rc->num_frames; i++) { | ||
196 : | stat_t * s = &rc->stats[i]; | ||
197 : | |||
198 : | if (s->type == XVID_TYPE_IVOP) { | ||
199 : | i_total += s->length + s->length * rc->param.keyframe_boost / 100; | ||
200 : | } | ||
201 : | } | ||
202 : | |||
203 : | // compensate for avi frame overhead | ||
204 : | rc->target_size -= rc->num_frames * 24; | ||
205 : | |||
206 : | // perform prepass to compensate for over/undersizing | ||
207 : | |||
208 : | if (rc->param.use_alt_curve) { | ||
209 : | |||
210 : | rc->alt_curve_low = avg_pvop - avg_pvop * (double)rc->param.alt_curve_low_dist / 100.0; | ||
211 : | rc->alt_curve_low_diff = avg_pvop - rc->alt_curve_low; | ||
212 : | rc->alt_curve_high = avg_pvop + avg_pvop * (double)rc->param.alt_curve_high_dist / 100.0; | ||
213 : | rc->alt_curve_high_diff = rc->alt_curve_high - avg_pvop; | ||
214 : | if (rc->alt_curve_use_auto) { | ||
215 : | if (rc->movie_curve > 1.0) { | ||
216 : | rc->param.alt_curve_min_rel_qual = (int)(100.0 - (100.0 - 100.0 / rc->movie_curve) * (double)rc->param.alt_curve_auto_str / 100.0); | ||
217 : | if (rc->param.alt_curve_min_rel_qual < 20) | ||
218 : | rc->param.alt_curve_min_rel_qual = 20; | ||
219 : | }else{ | ||
220 : | rc->param.alt_curve_min_rel_qual = 100; | ||
221 : | } | ||
222 : | } | ||
223 : | rc->alt_curve_mid_qual = (1.0 + (double)rc->param.alt_curve_min_rel_qual / 100.0) / 2.0; | ||
224 : | rc->alt_curve_qual_dev = 1.0 - rc->alt_curve_mid_qual; | ||
225 : | |||
226 : | if (rc->param.alt_curve_low_dist > 100) { | ||
227 : | switch(rc->param.alt_curve_type) { | ||
228 : | case XVID_CURVE_SINE : // Sine Curve (high aggressiveness) | ||
229 : | rc->alt_curve_qual_dev *= 2.0 / (1.0 + sin(DEG2RAD * (avg_pvop * 90.0 / rc->alt_curve_low_diff))); | ||
230 : | rc->alt_curve_mid_qual = 1.0 - rc->alt_curve_qual_dev * sin(DEG2RAD * (avg_pvop * 90.0 / rc->alt_curve_low_diff)); | ||
231 : | break; | ||
232 : | case XVID_CURVE_LINEAR : // Linear (medium aggressiveness) | ||
233 : | rc->alt_curve_qual_dev *= 2.0 / (1.0 + avg_pvop / rc->alt_curve_low_diff); | ||
234 : | rc->alt_curve_mid_qual = 1.0 - rc->alt_curve_qual_dev * avg_pvop / rc->alt_curve_low_diff; | ||
235 : | break; | ||
236 : | case XVID_CURVE_COSINE : // Cosine Curve (low aggressiveness) | ||
237 : | rc->alt_curve_qual_dev *= 2.0 / (1.0 + (1.0 - cos(DEG2RAD * (avg_pvop * 90.0 / rc->alt_curve_low_diff)))); | ||
238 : | rc->alt_curve_mid_qual = 1.0 - rc->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * (avg_pvop * 90.0 / rc->alt_curve_low_diff))); | ||
239 : | } | ||
240 : | } | ||
241 : | } | ||
242 : | |||
243 : | total1 = 0; | ||
244 : | total2 = 0; | ||
245 : | |||
246 : | for (i=0; i<rc->num_frames; i++) { | ||
247 : | stat_t * s = &rc->stats[i]; | ||
248 : | |||
249 : | if (s->type != XVID_TYPE_IVOP) { | ||
250 : | |||
251 : | double dbytes = s->length / rc->movie_curve; | ||
252 : | double dbytes2; | ||
253 : | total1 += dbytes; | ||
254 : | |||
255 : | if (s->type == XVID_TYPE_BVOP) | ||
256 : | dbytes *= avg_pvop / avg_bvop; | ||
257 : | |||
258 : | if (rc->param.use_alt_curve) { | ||
259 : | if (dbytes > avg_pvop) { | ||
260 : | if (dbytes >= rc->alt_curve_high) { | ||
261 : | dbytes2 = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev); | ||
262 : | }else{ | ||
263 : | switch(rc->param.alt_curve_type){ | ||
264 : | case XVID_CURVE_SINE : | ||
265 : | dbytes2 = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * sin(DEG2RAD * ((dbytes - avg_pvop) * 90.0 / rc->alt_curve_high_diff))); | ||
266 : | break; | ||
267 : | case XVID_CURVE_LINEAR : | ||
268 : | dbytes2 = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * (dbytes - avg_pvop) / rc->alt_curve_high_diff); | ||
269 : | break; | ||
270 : | case XVID_CURVE_COSINE : | ||
271 : | dbytes2 = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * ((dbytes - avg_pvop) * 90.0 / rc->alt_curve_high_diff)))); | ||
272 : | } | ||
273 : | } | ||
274 : | }else{ | ||
275 : | if (dbytes <= rc->alt_curve_low){ | ||
276 : | dbytes2 = dbytes; | ||
277 : | }else{ | ||
278 : | switch(rc->param.alt_curve_type){ | ||
279 : | case XVID_CURVE_SINE : | ||
280 : | dbytes2 = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * sin(DEG2RAD * ((dbytes - avg_pvop) * 90.0 / rc->alt_curve_low_diff))); | ||
281 : | break; | ||
282 : | case XVID_CURVE_LINEAR : | ||
283 : | dbytes2 = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * (dbytes - avg_pvop) / rc->alt_curve_low_diff); | ||
284 : | break; | ||
285 : | case XVID_CURVE_COSINE : | ||
286 : | dbytes2 = dbytes * (rc->alt_curve_mid_qual + rc->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * ((dbytes - avg_pvop) * 90.0 / rc->alt_curve_low_diff)))); | ||
287 : | } | ||
288 : | } | ||
289 : | } | ||
290 : | }else{ | ||
291 : | if (dbytes > avg_pvop) { | ||
292 : | dbytes2 = ((double)dbytes + (avg_pvop - dbytes) * | ||
293 : | rc->param.curve_compression_high / 100.0); | ||
294 : | }else{ | ||
295 : | dbytes2 = ((double)dbytes + (avg_pvop - dbytes) * | ||
296 : | rc->param.curve_compression_low / 100.0); | ||
297 : | } | ||
298 : | } | ||
299 : | |||
300 : | if (s->type == XVID_TYPE_BVOP) { | ||
301 : | dbytes2 *= avg_bvop / avg_pvop; | ||
302 : | } | ||
303 : | |||
304 : | if (dbytes2 < rc->min_length[s->type-1]) { | ||
305 : | dbytes = rc->min_length[s->type-1]; | ||
306 : | } | ||
307 : | |||
308 : | total2 += dbytes2; | ||
309 : | } | ||
310 : | } | ||
311 : | |||
312 : | rc->curve_comp_scale = total1 / total2; | ||
313 : | |||
314 : | if (!rc->param.use_alt_curve) { | ||
315 : | printf("middle frame size for asymmetric curve compression: %i", | ||
316 : | (int)(avg_pvop * rc->curve_comp_scale)); | ||
317 : | } | ||
318 : | }*/ | ||
319 : | |||
320 : | |||
321 : | |||
322 : | |||
323 : | static void print_stats(rc_2pass2_t * rc) | ||
324 : | { | ||
325 : | int i; | ||
326 : | for (i = 0; i < rc->num_frames; i++) { | ||
327 : | stat_t * s = &rc->stats[i]; | ||
328 : | printf("%i %i %i %i\n", s->type, s->quant, s->length, s->scaled_length); | ||
329 : | |||
330 : | } | ||
331 : | } | ||
332 : | |||
333 : | |||
334 : | /* pre-process the statistics data | ||
335 : | this is a clone of vfw/src/2pass.c:codec_2pass_init minus file reading, alt_curve, internal scale | ||
336 : | */ | ||
337 : | |||
338 : | void pre_process(rc_2pass2_t * rc) | ||
339 : | { | ||
340 : | int i,j; | ||
341 : | double total1, total2; | ||
342 : | uint64_t ivop_boost_total; | ||
343 : | |||
344 : | ivop_boost_total = 0; | ||
345 : | rc->curve_comp_error = 0; | ||
346 : | |||
347 : | for (i=0; i<3; i++) { | ||
348 : | rc->count[i]=0; | ||
349 : | rc->tot_length[i] = 0; | ||
350 : | rc->tot_scaled_length[i] = 0; | ||
351 : | rc->last_quant[i] = 0; | ||
352 : | } | ||
353 : | |||
354 : | for (i=0; i<32;i++) { | ||
355 : | rc->pquant_error[i] = 0; | ||
356 : | rc->bquant_error[i] = 0; | ||
357 : | rc->quant_count[i] = 0; | ||
358 : | } | ||
359 : | |||
360 : | for (i=j=0; i<rc->num_frames; i++) { | ||
361 : | stat_t * s = &rc->stats[i]; | ||
362 : | |||
363 : | rc->count[s->type-1]++; | ||
364 : | rc->tot_length[s->type-1] += s->length; | ||
365 : | rc->tot_scaled_length[s->type-1] += s->scaled_length; | ||
366 : | |||
367 : | if (i == 0 || s->length < rc->min_length[s->type-1]) { | ||
368 : | rc->min_length[s->type-1] = s->length; | ||
369 : | } | ||
370 : | |||
371 : | if (i == 0 || s->length > rc->max_length) { | ||
372 : | rc->max_length = s->length; | ||
373 : | } | ||
374 : | |||
375 : | if (s->type == XVID_TYPE_IVOP) { | ||
376 : | ivop_boost_total += s->scaled_length * rc->param.keyframe_boost / 100; | ||
377 : | rc->keyframe_locations[j] = i; | ||
378 : | j++; | ||
379 : | } | ||
380 : | } | ||
381 : | rc->keyframe_locations[j] = i; | ||
382 : | |||
383 : | rc->movie_curve = ((double)(rc->tot_scaled_length[XVID_TYPE_PVOP-1] + rc->tot_scaled_length[XVID_TYPE_BVOP-1] + ivop_boost_total) / | ||
384 : | (rc->tot_scaled_length[XVID_TYPE_PVOP-1] + rc->tot_scaled_length[XVID_TYPE_BVOP-1])); | ||
385 : | |||
386 : | for(i=0; i<3; i++) { | ||
387 : | if (rc->count[i] == 0 || rc->movie_curve == 0) { | ||
388 : | rc->avg_length[i] = 1; | ||
389 : | }else{ | ||
390 : | rc->avg_length[i] = rc->tot_scaled_length[i] / rc->count[i] / rc->movie_curve; | ||
391 : | } | ||
392 : | } | ||
393 : | |||
394 : | printf("--\n"); | ||
395 : | /* alt curve stuff here */ | ||
396 : | |||
397 : | if (rc->param.use_alt_curve) { | ||
398 : | const double avg_pvop = rc->avg_length[XVID_TYPE_PVOP-1]; | ||
399 : | const uint64_t tot_pvop = rc->tot_length[XVID_TYPE_PVOP-1]; | ||
400 : | const uint64_t tot_bvop = rc->tot_length[XVID_TYPE_BVOP-1]; | ||
401 : | const uint64_t tot_scaled_pvop = rc->tot_scaled_length[XVID_TYPE_PVOP-1]; | ||
402 : | const uint64_t tot_scaled_bvop = rc->tot_scaled_length[XVID_TYPE_BVOP-1]; | ||
403 : | |||
404 : | rc->alt_curve_low = avg_pvop - avg_pvop * (double)rc->param.alt_curve_low_dist / 100.0; | ||
405 : | rc->alt_curve_low_diff = avg_pvop - rc->alt_curve_low; | ||
406 : | rc->alt_curve_high = avg_pvop + avg_pvop * (double)rc->param.alt_curve_high_dist / 100.0; | ||
407 : | rc->alt_curve_high_diff = rc->alt_curve_high - avg_pvop; | ||
408 : | |||
409 : | if (rc->param.alt_curve_use_auto) { | ||
410 : | if (tot_bvop + tot_pvop > tot_scaled_bvop + tot_scaled_pvop) { | ||
411 : | rc->param.alt_curve_min_rel_qual = (int)(100.0 - (100.0 - 100.0 / | ||
412 : | ((double)(tot_pvop + tot_bvop) / (double)(tot_scaled_pvop + tot_scaled_bvop))) * (double)rc->param.alt_curve_auto_str / 100.0); | ||
413 : | |||
414 : | if (rc->param.alt_curve_min_rel_qual < 20) | ||
415 : | rc->param.alt_curve_min_rel_qual = 20; | ||
416 : | }else{ | ||
417 : | rc->param.alt_curve_min_rel_qual = 100; | ||
418 : | } | ||
419 : | } | ||
420 : | rc->alt_curve_mid_qual = (1.0 + (double)rc->param.alt_curve_min_rel_qual / 100.0) / 2.0; | ||
421 : | rc->alt_curve_qual_dev = 1.0 - rc->alt_curve_mid_qual; | ||
422 : | |||
423 : | if (rc->param.alt_curve_low_dist > 100) { | ||
424 : | switch(rc->param.alt_curve_type) { | ||
425 : | case XVID_CURVE_SINE: // Sine Curve (high aggressiveness) | ||
426 : | rc->alt_curve_qual_dev *= 2.0 / (1.0 + sin(DEG2RAD * (avg_pvop * 90.0 / rc->alt_curve_low_diff))); | ||
427 : | rc->alt_curve_mid_qual = 1.0 - rc->alt_curve_qual_dev * sin(DEG2RAD * (avg_pvop * 90.0 / rc->alt_curve_low_diff)); | ||
428 : | break; | ||
429 : | case XVID_CURVE_LINEAR: // Linear (medium aggressiveness) | ||
430 : | rc->alt_curve_qual_dev *= 2.0 / (1.0 + avg_pvop / rc->alt_curve_low_diff); | ||
431 : | rc->alt_curve_mid_qual = 1.0 - rc->alt_curve_qual_dev * avg_pvop / rc->alt_curve_low_diff; | ||
432 : | break; | ||
433 : | case XVID_CURVE_COSINE: // Cosine Curve (low aggressiveness) | ||
434 : | rc->alt_curve_qual_dev *= 2.0 / (1.0 + (1.0 - cos(DEG2RAD * (avg_pvop * 90.0 / rc->alt_curve_low_diff)))); | ||
435 : | rc->alt_curve_mid_qual = 1.0 - rc->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * (avg_pvop * 90.0 / rc->alt_curve_low_diff))); | ||
436 : | } | ||
437 : | } | ||
438 : | } | ||
439 : | /* --- */ | ||
440 : | |||
441 : | |||
442 : | total1=total2=0; | ||
443 : | for (i=j=0; i<rc->num_frames; i++) { | ||
444 : | stat_t * s = &rc->stats[i]; | ||
445 : | |||
446 : | if (s->type != XVID_TYPE_IVOP) { | ||
447 : | double dbytes,dbytes2; | ||
448 : | |||
449 : | dbytes = s->scaled_length / rc->movie_curve; | ||
450 : | dbytes2 = 0; /* XXX: warning */ | ||
451 : | total1 += dbytes; | ||
452 : | if (s->type == XVID_TYPE_BVOP) | ||
453 : | dbytes *= rc->avg_length[XVID_TYPE_PVOP-1] / rc->avg_length[XVID_TYPE_BVOP-1]; | ||
454 : | |||
455 : | if (rc->param.use_alt_curve) { | ||
456 : | if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { | ||
457 : | |||
458 : | if (dbytes >= rc->alt_curve_high) { | ||
459 : | dbytes2 = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev); | ||
460 : | }else{ | ||
461 : | switch(rc->param.alt_curve_type) { | ||
462 : | case XVID_CURVE_SINE : | ||
463 : | dbytes2 = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * sin(DEG2RAD * ((dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) * 90.0 / rc->alt_curve_high_diff))); | ||
464 : | break; | ||
465 : | case XVID_CURVE_LINEAR : | ||
466 : | dbytes2 = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * (dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) / rc->alt_curve_high_diff); | ||
467 : | break; | ||
468 : | case XVID_CURVE_COSINE : | ||
469 : | dbytes2 = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * ((dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) * 90.0 / rc->alt_curve_high_diff)))); | ||
470 : | } | ||
471 : | } | ||
472 : | }else{ | ||
473 : | if (dbytes <= rc->alt_curve_low) { | ||
474 : | dbytes2 = dbytes; | ||
475 : | }else{ | ||
476 : | switch(rc->param.alt_curve_type) { | ||
477 : | case XVID_CURVE_SINE : | ||
478 : | dbytes2 = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * sin(DEG2RAD * ((dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) * 90.0 / rc->alt_curve_low_diff))); | ||
479 : | break; | ||
480 : | case XVID_CURVE_LINEAR : | ||
481 : | dbytes2 = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * (dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) / rc->alt_curve_low_diff); | ||
482 : | break; | ||
483 : | case XVID_CURVE_COSINE : | ||
484 : | dbytes2 = dbytes * (rc->alt_curve_mid_qual + rc->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * ((dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) * 90.0 / rc->alt_curve_low_diff)))); | ||
485 : | } | ||
486 : | } | ||
487 : | |||
488 : | } | ||
489 : | |||
490 : | |||
491 : | }else{ | ||
492 : | if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { | ||
493 : | dbytes2=((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_high / 100.0); | ||
494 : | }else{ | ||
495 : | dbytes2 = ((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_low / 100.0); | ||
496 : | } | ||
497 : | } | ||
498 : | |||
499 : | if (s->type == XVID_TYPE_BVOP) { | ||
500 : | dbytes2 *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; | ||
501 : | if (dbytes2 < rc->min_length[XVID_TYPE_BVOP-1]) | ||
502 : | dbytes2 = rc->min_length[XVID_TYPE_BVOP-1]; | ||
503 : | }else{ | ||
504 : | if (dbytes2 < rc->min_length[XVID_TYPE_PVOP-1]) | ||
505 : | dbytes2 = rc->min_length[XVID_TYPE_PVOP-1]; | ||
506 : | } | ||
507 : | total2 += dbytes2; | ||
508 : | } | ||
509 : | } | ||
510 : | |||
511 : | rc->curve_comp_scale = total1 / total2; | ||
512 : | |||
513 : | if (!rc->param.use_alt_curve) { | ||
514 : | printf("middle frame size for asymmetric curve compression: %i\n", | ||
515 : | (int)(rc->avg_length[XVID_TYPE_PVOP-1] * rc->curve_comp_scale)); | ||
516 : | } | ||
517 : | |||
518 : | if (rc->param.use_alt_curve) { | ||
519 : | int bonus_bias = rc->param.alt_curve_bonus_bias; | ||
520 : | int oldquant = 1; | ||
521 : | |||
522 : | if (rc->param.alt_curve_use_auto_bonus_bias) | ||
523 : | bonus_bias = rc->param.alt_curve_min_rel_qual; | ||
524 : | |||
525 : | rc->alt_curve_curve_bias_bonus = (total1 - total2) * (double)bonus_bias / 100.0 / (double)(rc->num_frames /* - credits_frames */ - rc->num_keyframes); | ||
526 : | rc->curve_comp_scale = ((total1 - total2) * (1.0 - (double)bonus_bias / 100.0) + total2) / total2; | ||
527 : | |||
528 : | |||
529 : | /* special info for alt curve: bias bonus and quantizer thresholds */ | ||
530 : | |||
531 : | printf("avg scaled framesize:%i", (int)rc->avg_length[XVID_TYPE_PVOP-1]); | ||
532 : | printf("bias bonus:%i bytes", (int)rc->alt_curve_curve_bias_bonus); | ||
533 : | |||
534 : | for (i=1; i <= (int)(rc->alt_curve_high*2)+1; i++) { | ||
535 : | double curve_temp, dbytes; | ||
536 : | int newquant; | ||
537 : | |||
538 : | dbytes = i; | ||
539 : | if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { | ||
540 : | if (dbytes >= rc->alt_curve_high) { | ||
541 : | curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev); | ||
542 : | }else{ | ||
543 : | switch(rc->param.alt_curve_type) | ||
544 : | { | ||
545 : | case XVID_CURVE_SINE : | ||
546 : | curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * sin(DEG2RAD * ((dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) * 90.0 / rc->alt_curve_high_diff))); | ||
547 : | break; | ||
548 : | case XVID_CURVE_LINEAR : | ||
549 : | curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * (dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) / rc->alt_curve_high_diff); | ||
550 : | break; | ||
551 : | case XVID_CURVE_COSINE : | ||
552 : | curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * ((dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) * 90.0 / rc->alt_curve_high_diff)))); | ||
553 : | } | ||
554 : | } | ||
555 : | }else{ | ||
556 : | if (dbytes <= rc->alt_curve_low) { | ||
557 : | curve_temp = dbytes; | ||
558 : | }else{ | ||
559 : | switch(rc->param.alt_curve_type) | ||
560 : | { | ||
561 : | case XVID_CURVE_SINE : | ||
562 : | curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * sin(DEG2RAD * ((dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) * 90.0 / rc->alt_curve_low_diff))); | ||
563 : | break; | ||
564 : | case XVID_CURVE_LINEAR : | ||
565 : | curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * (dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) / rc->alt_curve_low_diff); | ||
566 : | break; | ||
567 : | case XVID_CURVE_COSINE : | ||
568 : | curve_temp = dbytes * (rc->alt_curve_mid_qual + rc->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * ((dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) * 90.0 / rc->alt_curve_low_diff)))); | ||
569 : | } | ||
570 : | } | ||
571 : | } | ||
572 : | |||
573 : | if (rc->movie_curve > 1.0) | ||
574 : | dbytes *= rc->movie_curve; | ||
575 : | |||
576 : | newquant = (int)(dbytes * 2.0 / (curve_temp * rc->curve_comp_scale + rc->alt_curve_curve_bias_bonus)); | ||
577 : | if (newquant > 1) { | ||
578 : | if (newquant != oldquant) { | ||
579 : | int percent = (int)((i - rc->avg_length[XVID_TYPE_PVOP-1]) * 100.0 / rc->avg_length[XVID_TYPE_PVOP-1]); | ||
580 : | oldquant = newquant; | ||
581 : | printf("quant:%i threshold at %i : %i percent", newquant, i, percent); | ||
582 : | } | ||
583 : | } | ||
584 : | } | ||
585 : | |||
586 : | } | ||
587 : | |||
588 : | rc->overflow = 0; | ||
589 : | rc->KFoverflow = 0; | ||
590 : | rc->KFoverflow_partial = 0; | ||
591 : | rc->KF_idx = 1; | ||
592 : | } | ||
593 : | |||
594 : | |||
595 : | |||
596 : | |||
597 : | static int rc_2pass2_create(xvid_plg_create_t * create, rc_2pass2_t ** handle) | ||
598 : | { | ||
599 : | xvid_plugin_2pass2_t * param = (xvid_plugin_2pass2_t *)create->param; | ||
600 : | rc_2pass2_t * rc; | ||
601 : | |||
602 : | rc = malloc(sizeof(rc_2pass2_t)); | ||
603 : | if (rc == NULL) | ||
604 : | return XVID_ERR_MEMORY; | ||
605 : | |||
606 : | rc->param = *param; | ||
607 : | |||
608 : | if (rc->param.keyframe_boost <= 0) rc->param.keyframe_boost = 0; | ||
609 : | if (rc->param.payback_method <= 0) rc->param.payback_method = XVID_PAYBACK_PROP; | ||
610 : | if (rc->param.bitrate_payback_delay <= 0) rc->param.bitrate_payback_delay = 250; | ||
611 : | if (rc->param.curve_compression_high <= 0) rc->param.curve_compression_high = 0; | ||
612 : | if (rc->param.curve_compression_low <= 0) rc->param.curve_compression_low = 0; | ||
613 : | if (rc->param.max_overflow_improvement <= 0) rc->param.max_overflow_improvement = 60; | ||
614 : | if (rc->param.max_overflow_degradation <= 0) rc->param.max_overflow_degradation = 60; | ||
615 : | if (rc->param.min_quant[0] <= 0) rc->param.min_quant[0] = 2; | ||
616 : | if (rc->param.max_quant[0] <= 0) rc->param.max_quant[0] = 31; | ||
617 : | if (rc->param.min_quant[1] <= 0) rc->param.min_quant[1] = 2; | ||
618 : | if (rc->param.max_quant[1] <= 0) rc->param.max_quant[1] = 31; | ||
619 : | if (rc->param.min_quant[2] <= 0) rc->param.min_quant[2] = 2; | ||
620 : | if (rc->param.max_quant[2] <= 0) rc->param.max_quant[2] = 31; | ||
621 : | |||
622 : | if (rc->param.use_alt_curve <= 0) rc->param.use_alt_curve = 0; | ||
623 : | if (rc->param.alt_curve_high_dist <= 0) rc->param.alt_curve_high_dist = 500; | ||
624 : | if (rc->param.alt_curve_low_dist <= 0) rc->param.alt_curve_low_dist = 90; | ||
625 : | if (rc->param.alt_curve_use_auto <= 0) rc->param.alt_curve_use_auto = 1; | ||
626 : | if (rc->param.alt_curve_auto_str <= 0) rc->param.alt_curve_auto_str = 30; | ||
627 : | if (rc->param.alt_curve_type <= 0) rc->param.alt_curve_type = XVID_CURVE_LINEAR; | ||
628 : | if (rc->param.alt_curve_min_rel_qual <= 0) rc->param.alt_curve_min_rel_qual = 50; | ||
629 : | if (rc->param.alt_curve_use_auto_bonus_bias <= 0) rc->param.alt_curve_use_auto_bonus_bias = 1; | ||
630 : | if (rc->param.alt_curve_bonus_bias <= 0) rc->param.alt_curve_bonus_bias = 50; | ||
631 : | |||
632 : | if (rc->param.kftreshold <= 0) rc->param.kftreshold = 10; | ||
633 : | if (rc->param.kfreduction <= 0) rc->param.kfreduction = 20; | ||
634 : | if (rc->param.min_key_interval <= 0) rc->param.min_key_interval = 300; | ||
635 : | |||
636 : | if (!det_stats_length(rc, param->filename1)){ | ||
637 : | DPRINTF(DPRINTF_RC,"fopen %s failed\n", param->filename1); | ||
638 : | free(rc); | ||
639 : | return XVID_ERR_FAIL; | ||
640 : | } | ||
641 : | |||
642 : | if ((rc->stats = malloc(rc->num_frames * sizeof(stat_t))) == NULL) { | ||
643 : | free(rc); | ||
644 : | return XVID_ERR_MEMORY; | ||
645 : | } | ||
646 : | |||
647 : | /* XXX: do we need an addition location */ | ||
648 : | if ((rc->keyframe_locations = malloc((rc->num_keyframes + 1) * sizeof(int))) == NULL) { | ||
649 : | free(rc->stats); | ||
650 : | free(rc); | ||
651 : | return XVID_ERR_MEMORY; | ||
652 : | } | ||
653 : | |||
654 : | if (!load_stats(rc, param->filename1, param->filename2)) { | ||
655 : | DPRINTF(DPRINTF_RC,"fopen %s,%s failed\n", param->filename1, param->filename2); | ||
656 : | free(rc->keyframe_locations); | ||
657 : | free(rc->stats); | ||
658 : | free(rc); | ||
659 : | return XVID_ERR_FAIL; | ||
660 : | } | ||
661 : | |||
662 : | /* pre-process our stats */ | ||
663 : | pre_process(rc); | ||
664 : | |||
665 : | *handle = rc; | ||
666 : | return(0); | ||
667 : | } | ||
668 : | |||
669 : | |||
670 : | static int rc_2pass2_destroy(rc_2pass2_t * rc, xvid_plg_destroy_t * destroy) | ||
671 : | { | ||
672 : | free(rc->keyframe_locations); | ||
673 : | free(rc->stats); | ||
674 : | free(rc); | ||
675 : | return(0); | ||
676 : | } | ||
677 : | |||
678 : | |||
679 : | |||
680 : | static int rc_2pass2_before(rc_2pass2_t * rc, xvid_plg_data_t * data) | ||
681 : | { | ||
682 : | stat_t * s = &rc->stats[data->frame_num]; | ||
683 : | int overflow; | ||
684 : | int desired; | ||
685 : | double dbytes; | ||
686 : | double curve_temp; | ||
687 : | int capped_to_max_framesize = 0; | ||
688 : | |||
689 : | if (data->frame_num >= rc->num_frames) { | ||
690 : | /* insufficent stats data */ | ||
691 : | return 0; | ||
692 : | } | ||
693 : | |||
694 : | overflow = rc->overflow / 8; /* XXX: why by 8 */ | ||
695 : | |||
696 : | if (s->type == XVID_TYPE_IVOP) { /* XXX: why */ | ||
697 : | overflow = 0; | ||
698 : | } | ||
699 : | |||
700 : | desired = s->scaled_length; | ||
701 : | |||
702 : | dbytes = desired; | ||
703 : | if (s->type == XVID_TYPE_IVOP) { | ||
704 : | dbytes += desired * rc->param.keyframe_boost / 100; | ||
705 : | } | ||
706 : | dbytes /= rc->movie_curve; | ||
707 : | |||
708 : | if (s->type == XVID_TYPE_BVOP) { | ||
709 : | dbytes *= rc->avg_length[XVID_TYPE_PVOP-1] / rc->avg_length[XVID_TYPE_BVOP-1]; | ||
710 : | } | ||
711 : | |||
712 : | if (rc->param.payback_method == XVID_PAYBACK_BIAS) { | ||
713 : | desired =(int)(rc->curve_comp_error / rc->param.bitrate_payback_delay); | ||
714 : | }else{ | ||
715 : | desired = (int)(rc->curve_comp_error * dbytes / | ||
716 : | rc->avg_length[XVID_TYPE_PVOP-1] / rc->param.bitrate_payback_delay); | ||
717 : | |||
718 : | if (labs(desired) > fabs(rc->curve_comp_error)) { | ||
719 : | desired = (int)rc->curve_comp_error; | ||
720 : | } | ||
721 : | } | ||
722 : | |||
723 : | rc->curve_comp_error -= desired; | ||
724 : | |||
725 : | /* alt curve */ | ||
726 : | |||
727 : | curve_temp = 0; /* XXX: warning */ | ||
728 : | |||
729 : | if (rc->param.use_alt_curve) { | ||
730 : | if (s->type != XVID_TYPE_IVOP) { | ||
731 : | if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { | ||
732 : | if (dbytes >= rc->alt_curve_high) { | ||
733 : | curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev); | ||
734 : | }else{ | ||
735 : | switch(rc->param.alt_curve_type) { | ||
736 : | case XVID_CURVE_SINE : | ||
737 : | curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * sin(DEG2RAD * ((dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) * 90.0 / rc->alt_curve_high_diff))); | ||
738 : | break; | ||
739 : | case XVID_CURVE_LINEAR : | ||
740 : | curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * (dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) / rc->alt_curve_high_diff); | ||
741 : | break; | ||
742 : | case XVID_CURVE_COSINE : | ||
743 : | curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * ((dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) * 90.0 / rc->alt_curve_high_diff)))); | ||
744 : | } | ||
745 : | } | ||
746 : | }else{ | ||
747 : | if (dbytes <= rc->alt_curve_low){ | ||
748 : | curve_temp = dbytes; | ||
749 : | }else{ | ||
750 : | switch(rc->param.alt_curve_type) { | ||
751 : | case XVID_CURVE_SINE : | ||
752 : | curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * sin(DEG2RAD * ((dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) * 90.0 / rc->alt_curve_low_diff))); | ||
753 : | break; | ||
754 : | case XVID_CURVE_LINEAR : | ||
755 : | curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev * (dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) / rc->alt_curve_low_diff); | ||
756 : | break; | ||
757 : | case XVID_CURVE_COSINE : | ||
758 : | curve_temp = dbytes * (rc->alt_curve_mid_qual + rc->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * ((dbytes - rc->avg_length[XVID_TYPE_PVOP-1]) * 90.0 / rc->alt_curve_low_diff)))); | ||
759 : | } | ||
760 : | } | ||
761 : | } | ||
762 : | if (s->type == XVID_TYPE_BVOP) | ||
763 : | curve_temp *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; | ||
764 : | |||
765 : | curve_temp = curve_temp * rc->curve_comp_scale + rc->alt_curve_curve_bias_bonus; | ||
766 : | |||
767 : | desired += ((int)curve_temp); | ||
768 : | rc->curve_comp_error += curve_temp - (int)curve_temp; | ||
769 : | }else{ | ||
770 : | if (s->type == XVID_TYPE_BVOP) | ||
771 : | dbytes *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; | ||
772 : | |||
773 : | desired += ((int)dbytes); | ||
774 : | rc->curve_comp_error += dbytes - (int)dbytes; | ||
775 : | } | ||
776 : | |||
777 : | }else if ((rc->param.curve_compression_high + rc->param.curve_compression_low) && s->type != XVID_TYPE_IVOP) { | ||
778 : | |||
779 : | curve_temp = rc->curve_comp_scale; | ||
780 : | if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { | ||
781 : | curve_temp *= ((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_high / 100.0); | ||
782 : | } else { | ||
783 : | curve_temp *= ((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_low / 100.0); | ||
784 : | } | ||
785 : | |||
786 : | if (s->type == XVID_TYPE_BVOP){ | ||
787 : | curve_temp *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; | ||
788 : | } | ||
789 : | |||
790 : | desired += (int)curve_temp; | ||
791 : | rc->curve_comp_error += curve_temp - (int)curve_temp; | ||
792 : | }else{ | ||
793 : | if (s->type == XVID_TYPE_BVOP){ | ||
794 : | dbytes *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; | ||
795 : | } | ||
796 : | |||
797 : | desired += (int)dbytes; | ||
798 : | rc->curve_comp_error += dbytes - (int)dbytes; | ||
799 : | } | ||
800 : | |||
801 : | if (desired > s->length){ | ||
802 : | rc->curve_comp_error += desired - s->length; | ||
803 : | desired = s->length; | ||
804 : | }else{ | ||
805 : | if (desired < rc->min_length[s->type-1]) { | ||
806 : | if (s->type == XVID_TYPE_IVOP){ | ||
807 : | rc->curve_comp_error -= rc->min_length[XVID_TYPE_IVOP-1] - desired; | ||
808 : | } | ||
809 : | desired = rc->min_length[s->type-1]; | ||
810 : | } | ||
811 : | } | ||
812 : | |||
813 : | s->desired_length = desired; | ||
814 : | |||
815 : | |||
816 : | /* if this keyframe is too close to the next, reduce it's byte allotment | ||
817 : | XXX: why do we do this after setting the desired length */ | ||
818 : | |||
819 : | if (s->type == XVID_TYPE_IVOP) { | ||
820 : | int KFdistance = rc->keyframe_locations[rc->KF_idx] - rc->keyframe_locations[rc->KF_idx - 1]; | ||
821 : | |||
822 : | if (KFdistance < rc->param.kftreshold) { | ||
823 : | |||
824 : | KFdistance = KFdistance - rc->param.min_key_interval; | ||
825 : | |||
826 : | if (KFdistance >= 0) { | ||
827 : | int KF_min_size; | ||
828 : | |||
829 : | KF_min_size = desired * (100 - rc->param.kfreduction) / 100; | ||
830 : | if (KF_min_size < 1) | ||
831 : | KF_min_size = 1; | ||
832 : | |||
833 : | desired = KF_min_size + (desired - KF_min_size) * KFdistance / | ||
834 : | (rc->param.kftreshold - rc->param.min_key_interval); | ||
835 : | |||
836 : | if (desired < 1) | ||
837 : | desired = 1; | ||
838 : | } | ||
839 : | } | ||
840 : | } | ||
841 : | |||
842 : | overflow = (int)((double)overflow * desired / rc->avg_length[XVID_TYPE_PVOP-1]); | ||
843 : | |||
844 : | // Foxer: reign in overflow with huge frames | ||
845 : | if (labs(overflow) > labs(rc->overflow)) { | ||
846 : | overflow = rc->overflow; | ||
847 : | } | ||
848 : | |||
849 : | // Foxer: make sure overflow doesn't run away | ||
850 : | |||
851 : | if (overflow > desired * rc->param.max_overflow_improvement / 100) { | ||
852 : | desired += (overflow <= desired) ? desired * rc->param.max_overflow_improvement / 100 : | ||
853 : | overflow * rc->param.max_overflow_improvement / 100; | ||
854 : | }else if (overflow < desired * rc->param.max_overflow_degradation / -100){ | ||
855 : | desired += desired * rc->param.max_overflow_degradation / -100; | ||
856 : | }else{ | ||
857 : | desired += overflow; | ||
858 : | } | ||
859 : | |||
860 : | if (desired > rc->max_length) { | ||
861 : | capped_to_max_framesize = 1; | ||
862 : | desired = rc->max_length; | ||
863 : | } | ||
864 : | |||
865 : | // make sure to not scale below the minimum framesize | ||
866 : | if (desired < rc->min_length[s->type-1]) { | ||
867 : | desired = rc->min_length[s->type-1]; | ||
868 : | } | ||
869 : | |||
870 : | |||
871 : | // very 'simple' quant<->filesize relationship | ||
872 : | data->quant= (s->quant * s->length) / desired; | ||
873 : | |||
874 : | if (data->quant < 1) { | ||
875 : | data->quant = 1; | ||
876 : | } else if (data->quant > 31) { | ||
877 : | data->quant = 31; | ||
878 : | } | ||
879 : | else if (s->type != XVID_TYPE_IVOP) | ||
880 : | { | ||
881 : | // Foxer: aid desired quantizer precision by accumulating decision error | ||
882 : | if (s->type== XVID_TYPE_BVOP) { | ||
883 : | rc->bquant_error[data->quant] += ((double)(s->quant * s->length) / desired) - data->quant; | ||
884 : | |||
885 : | if (rc->bquant_error[data->quant] >= 1.0) { | ||
886 : | rc->bquant_error[data->quant] -= 1.0; | ||
887 : | data->quant++; | ||
888 : | } | ||
889 : | }else{ | ||
890 : | rc->pquant_error[data->quant] += ((double)(s->quant * s->length) / desired) - data->quant; | ||
891 : | |||
892 : | if (rc->pquant_error[data->quant] >= 1.0) { | ||
893 : | rc->pquant_error[data->quant] -= 1.0; | ||
894 : | ++data->quant; | ||
895 : | } | ||
896 : | } | ||
897 : | } | ||
898 : | |||
899 : | /* cap to min/max quant */ | ||
900 : | |||
901 : | if (data->quant < rc->param.min_quant[s->type-1]) { | ||
902 : | data->quant = rc->param.min_quant[s->type-1]; | ||
903 : | }else if (data->quant > rc->param.max_quant[s->type-1]) { | ||
904 : | data->quant = rc->param.max_quant[s->type-1]; | ||
905 : | } | ||
906 : | |||
907 : | /* subsequent p/b frame quants can only be +- 2 */ | ||
908 : | if (s->type != XVID_TYPE_IVOP && rc->last_quant[s->type-1] && capped_to_max_framesize == 0) { | ||
909 : | |||
910 : | if (data->quant > rc->last_quant[s->type-1] + 2) { | ||
911 : | data->quant = rc->last_quant[s->type-1] + 2; | ||
912 : | DPRINTF(DPRINTF_RC, "p/b-frame quantizer prevented from rising too steeply"); | ||
913 : | } | ||
914 : | if (data->quant < rc->last_quant[s->type-1] - 2) { | ||
915 : | data->quant = rc->last_quant[s->type-1] - 2; | ||
916 : | DPRINTF(DPRINTF_RC, "p/b-frame quantizer prevented from falling too steeply"); | ||
917 : | } | ||
918 : | } | ||
919 : | |||
920 : | if (capped_to_max_framesize == 0) { | ||
921 : | rc->last_quant[s->type-1] = data->quant; | ||
922 : | } | ||
923 : | |||
924 : | return 0; | ||
925 : | } | ||
926 : | |||
927 : | |||
928 : | |||
929 : | static int rc_2pass2_after(rc_2pass2_t * rc, xvid_plg_data_t * data) | ||
930 : | { | ||
931 : | stat_t * s = &rc->stats[data->frame_num]; | ||
932 : | |||
933 : | if (data->frame_num >= rc->num_frames) { | ||
934 : | /* insufficent stats data */ | ||
935 : | return 0; | ||
936 : | } | ||
937 : | |||
938 : | rc->quant_count[data->quant]++; | ||
939 : | |||
940 : | if (data->type == XVID_TYPE_IVOP) { | ||
941 : | int kfdiff = (rc->keyframe_locations[rc->KF_idx] - rc->keyframe_locations[rc->KF_idx - 1]); | ||
942 : | |||
943 : | rc->overflow += rc->KFoverflow; | ||
944 : | rc->KFoverflow = s->desired_length - data->length; | ||
945 : | |||
946 : | if (kfdiff > 1) { // non-consecutive keyframes | ||
947 : | rc->KFoverflow_partial = rc->KFoverflow / (kfdiff - 1); | ||
948 : | }else{ // consecutive keyframes | ||
949 : | rc->overflow += rc->KFoverflow; | ||
950 : | rc->KFoverflow = 0; | ||
951 : | rc->KFoverflow_partial = 0; | ||
952 : | } | ||
953 : | rc->KF_idx++; | ||
954 : | }else{ | ||
955 : | // distribute part of the keyframe overflow | ||
956 : | rc->overflow += s->desired_length - data->length + rc->KFoverflow_partial; | ||
957 : | rc->KFoverflow -= rc->KFoverflow_partial; | ||
958 : | } | ||
959 : | |||
960 : | printf("[%i] quant:%i stats1:%i scaled:%i actual:%i overflow:%i\n", | ||
961 : | data->frame_num, | ||
962 : | data->quant, | ||
963 : | s->length, | ||
964 : | s->scaled_length, | ||
965 : | data->length, | ||
966 : | rc->overflow); | ||
967 : | |||
968 : | return(0); | ||
969 : | } | ||
970 : | |||
971 : | |||
972 : | |||
973 : | int xvid_plugin_2pass2(void * handle, int opt, void * param1, void * param2) | ||
974 : | { | ||
975 : | switch(opt) | ||
976 : | { | ||
977 : | case XVID_PLG_INFO : | ||
978 : | return 0; | ||
979 : | |||
980 : | case XVID_PLG_CREATE : | ||
981 : | return rc_2pass2_create((xvid_plg_create_t*)param1, param2); | ||
982 : | |||
983 : | case XVID_PLG_DESTROY : | ||
984 : | return rc_2pass2_destroy((rc_2pass2_t*)handle, (xvid_plg_destroy_t*)param1); | ||
985 : | |||
986 : | case XVID_PLG_BEFORE : | ||
987 : | return rc_2pass2_before((rc_2pass2_t*)handle, (xvid_plg_data_t*)param1); | ||
988 : | |||
989 : | case XVID_PLG_AFTER : | ||
990 : | return rc_2pass2_after((rc_2pass2_t*)handle, (xvid_plg_data_t*)param1); | ||
991 : | } | ||
992 : | |||
993 : | return XVID_ERR_FAIL; | ||
994 : | } |
No admin address has been configured | ViewVC Help |
Powered by ViewVC 1.0.4 |