Parent Directory | Revision Log
Revision 1043 - (view) (download)
1 : | suxen_drol | 942 | /****************************************************************************** |
2 : | * | ||
3 : | * XviD Bit Rate Controller Library | ||
4 : | edgomez | 1042 | * - VBR 2 pass bitrate controller implementation - |
5 : | suxen_drol | 942 | * |
6 : | edgomez | 1037 | * Copyright (C) 2002 Foxer <email?> |
7 : | * 2002 Dirk Knop <dknop@gwdg.de> | ||
8 : | * 2002-2003 Edouard Gomez <ed.gomez@free.fr> | ||
9 : | * 2003 Pete Ross <pross@xvid.org> | ||
10 : | suxen_drol | 942 | * |
11 : | edgomez | 1037 | * This curve treatment algorithm is the one originally implemented by Foxer |
12 : | * and tuned by Dirk Knop for the XviD vfw frontend. | ||
13 : | suxen_drol | 942 | * |
14 : | * This program is free software; you can redistribute it and/or modify | ||
15 : | * it under the terms of the GNU General Public License as published by | ||
16 : | * the Free Software Foundation; either version 2 of the License, or | ||
17 : | * (at your option) any later version. | ||
18 : | * | ||
19 : | * This program is distributed in the hope that it will be useful, | ||
20 : | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 : | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 : | * GNU General Public License for more details. | ||
23 : | * | ||
24 : | * You should have received a copy of the GNU General Public License | ||
25 : | * along with this program; if not, write to the Free Software | ||
26 : | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
27 : | * | ||
28 : | edgomez | 1043 | * $Id: plugin_2pass2.c,v 1.1.2.12 2003-05-24 22:03:50 edgomez Exp $ |
29 : | suxen_drol | 942 | * |
30 : | *****************************************************************************/ | ||
31 : | |||
32 : | #include <stdio.h> | ||
33 : | #include <math.h> | ||
34 : | edgomez | 1040 | #include <limits.h> |
35 : | suxen_drol | 942 | |
36 : | edgomez | 1042 | #include "../xvid.h" |
37 : | #include "../image/image.h" | ||
38 : | |||
39 : | /***************************************************************************** | ||
40 : | * Some constants | ||
41 : | ****************************************************************************/ | ||
42 : | |||
43 : | suxen_drol | 942 | #define RAD2DEG 57.295779513082320876798154814105 |
44 : | #define DEG2RAD 0.017453292519943295769236907684886 | ||
45 : | |||
46 : | edgomez | 1042 | #define DEFAULT_KEYFRAME_BOOST 0 |
47 : | #define DEFAULT_PAYBACK_METHOD XVID_PAYBACK_PROP | ||
48 : | #define DEFAULT_BITRATE_PAYBACK_DELAY 250 | ||
49 : | #define DEFAULT_CURVE_COMPRESSION_HIGH 0 | ||
50 : | #define DEFAULT_CURVE_COMPRESSION_LOW 0 | ||
51 : | #define DEFAULT_MAX_OVERFLOW_IMPROVEMENT 60 | ||
52 : | #define DEFAULT_MAX_OVERFLOW_DEGRADATION 60 | ||
53 : | suxen_drol | 942 | |
54 : | edgomez | 1042 | /* Alt curve settings */ |
55 : | #define DEFAULT_USE_ALT_CURVE 0 | ||
56 : | #define DEFAULT_ALT_CURVE_HIGH_DIST 500 | ||
57 : | #define DEFAULT_ALT_CURVE_LOW_DIST 90 | ||
58 : | #define DEFAULT_ALT_CURVE_USE_AUTO 1 | ||
59 : | #define DEFAULT_ALT_CURVE_AUTO_STR 30 | ||
60 : | #define DEFAULT_ALT_CURVE_TYPE XVID_CURVE_LINEAR | ||
61 : | #define DEFAULT_ALT_CURVE_MIN_REL_QUAL 50 | ||
62 : | #define DEFAULT_ALT_CURVE_USE_AUTO_BONUS_BIAS 1 | ||
63 : | #define DEFAULT_ALT_CURVE_BONUS_BIAS 50 | ||
64 : | |||
65 : | /* Keyframe settings */ | ||
66 : | #define DEFAULT_KFTRESHOLD 10 | ||
67 : | #define DEFAULT_KFREDUCTION 20 | ||
68 : | #define DEFAULT_MIN_KEY_INTERVAL 1 | ||
69 : | |||
70 : | /***************************************************************************** | ||
71 : | * Structures | ||
72 : | ****************************************************************************/ | ||
73 : | |||
74 : | /* Statistics */ | ||
75 : | suxen_drol | 942 | typedef struct { |
76 : | int type; /* first pass type */ | ||
77 : | int quant; /* first pass quant */ | ||
78 : | suxen_drol | 977 | int blks[3]; /* k,m,y blks */ |
79 : | suxen_drol | 942 | int length; /* first pass length */ |
80 : | suxen_drol | 1030 | int scaled_length; /* scaled length */ |
81 : | int desired_length; /* desired length; calcuated during encoding */ | ||
82 : | |||
83 : | int zone_mode; /* XVID_ZONE_xxx */ | ||
84 : | double weight; | ||
85 : | suxen_drol | 942 | } stat_t; |
86 : | |||
87 : | edgomez | 1042 | /* Context struct */ |
88 : | suxen_drol | 942 | typedef struct |
89 : | { | ||
90 : | xvid_plugin_2pass2_t param; | ||
91 : | |||
92 : | /* constant statistical data */ | ||
93 : | suxen_drol | 977 | int num_frames; |
94 : | suxen_drol | 942 | int num_keyframes; |
95 : | suxen_drol | 1030 | uint64_t target; /* target filesize */ |
96 : | suxen_drol | 977 | |
97 : | suxen_drol | 942 | int count[3]; /* count of each frame types */ |
98 : | uint64_t tot_length[3]; /* total length of each frame types */ | ||
99 : | double avg_length[3]; /* avg */ | ||
100 : | int min_length[3]; /* min frame length of each frame types */ | ||
101 : | uint64_t tot_scaled_length[3]; /* total scaled length of each frame type */ | ||
102 : | int max_length; /* max frame size */ | ||
103 : | suxen_drol | 1030 | |
104 : | /* zone statistical data */ | ||
105 : | double avg_weight; /* average weight */ | ||
106 : | int64_t tot_quant; /* total length used by XVID_ZONE_QUANT zones */ | ||
107 : | |||
108 : | |||
109 : | suxen_drol | 942 | double curve_comp_scale; |
110 : | double movie_curve; | ||
111 : | |||
112 : | double alt_curve_low; | ||
113 : | double alt_curve_high; | ||
114 : | double alt_curve_low_diff; | ||
115 : | double alt_curve_high_diff; | ||
116 : | double alt_curve_curve_bias_bonus; | ||
117 : | double alt_curve_mid_qual; | ||
118 : | double alt_curve_qual_dev; | ||
119 : | |||
120 : | /* dynamic */ | ||
121 : | |||
122 : | int * keyframe_locations; | ||
123 : | stat_t * stats; | ||
124 : | |||
125 : | double pquant_error[32]; | ||
126 : | double bquant_error[32]; | ||
127 : | int quant_count[32]; | ||
128 : | int last_quant[3]; | ||
129 : | |||
130 : | double curve_comp_error; | ||
131 : | int overflow; | ||
132 : | int KFoverflow; | ||
133 : | int KFoverflow_partial; | ||
134 : | int KF_idx; | ||
135 : | suxen_drol | 1030 | |
136 : | double fq_error; | ||
137 : | suxen_drol | 942 | } rc_2pass2_t; |
138 : | |||
139 : | |||
140 : | edgomez | 1042 | /***************************************************************************** |
141 : | * Sub plugin functions prototypes | ||
142 : | ****************************************************************************/ | ||
143 : | suxen_drol | 942 | |
144 : | edgomez | 1042 | static int rc_2pass2_create(xvid_plg_create_t * create, rc_2pass2_t ** handle); |
145 : | static int rc_2pass2_before(rc_2pass2_t * rc, xvid_plg_data_t * data); | ||
146 : | static int rc_2pass2_after(rc_2pass2_t * rc, xvid_plg_data_t * data); | ||
147 : | static int rc_2pass2_destroy(rc_2pass2_t * rc, xvid_plg_destroy_t * destroy); | ||
148 : | suxen_drol | 942 | |
149 : | edgomez | 1042 | /***************************************************************************** |
150 : | * Plugin definition | ||
151 : | ****************************************************************************/ | ||
152 : | suxen_drol | 942 | |
153 : | edgomez | 1042 | int |
154 : | xvid_plugin_2pass2(void * handle, int opt, void * param1, void * param2) | ||
155 : | suxen_drol | 942 | { |
156 : | edgomez | 1042 | switch(opt) { |
157 : | case XVID_PLG_INFO : | ||
158 : | suxen_drol | 942 | return 0; |
159 : | |||
160 : | edgomez | 1042 | case XVID_PLG_CREATE : |
161 : | return rc_2pass2_create((xvid_plg_create_t*)param1, param2); | ||
162 : | suxen_drol | 942 | |
163 : | edgomez | 1042 | case XVID_PLG_DESTROY : |
164 : | return rc_2pass2_destroy((rc_2pass2_t*)handle, (xvid_plg_destroy_t*)param1); | ||
165 : | suxen_drol | 942 | |
166 : | edgomez | 1042 | case XVID_PLG_BEFORE : |
167 : | return rc_2pass2_before((rc_2pass2_t*)handle, (xvid_plg_data_t*)param1); | ||
168 : | suxen_drol | 942 | |
169 : | edgomez | 1042 | case XVID_PLG_AFTER : |
170 : | return rc_2pass2_after((rc_2pass2_t*)handle, (xvid_plg_data_t*)param1); | ||
171 : | suxen_drol | 977 | } |
172 : | edgomez | 1037 | |
173 : | edgomez | 1042 | return XVID_ERR_FAIL; |
174 : | suxen_drol | 977 | } |
175 : | |||
176 : | edgomez | 1042 | /***************************************************************************** |
177 : | * Sub plugin functions definitions | ||
178 : | ****************************************************************************/ | ||
179 : | suxen_drol | 977 | |
180 : | edgomez | 1042 | /* First a few local helping function prototypes */ |
181 : | static int det_stats_length(rc_2pass2_t * rc, char * filename); | ||
182 : | static int load_stats(rc_2pass2_t *rc, char * filename); | ||
183 : | static void zone_process(rc_2pass2_t *rc, const xvid_plg_create_t * create); | ||
184 : | static void internal_scale(rc_2pass2_t *rc); | ||
185 : | static void pre_process0(rc_2pass2_t * rc); | ||
186 : | static void pre_process1(rc_2pass2_t * rc); | ||
187 : | suxen_drol | 977 | |
188 : | edgomez | 1042 | /*---------------------------------------------------------------------------- |
189 : | *--------------------------------------------------------------------------*/ | ||
190 : | suxen_drol | 942 | |
191 : | edgomez | 1042 | static int |
192 : | rc_2pass2_create(xvid_plg_create_t * create, rc_2pass2_t **handle) | ||
193 : | suxen_drol | 942 | { |
194 : | xvid_plugin_2pass2_t * param = (xvid_plugin_2pass2_t *)create->param; | ||
195 : | rc_2pass2_t * rc; | ||
196 : | suxen_drol | 1030 | int i; |
197 : | suxen_drol | 942 | |
198 : | rc = malloc(sizeof(rc_2pass2_t)); | ||
199 : | if (rc == NULL) | ||
200 : | return XVID_ERR_MEMORY; | ||
201 : | |||
202 : | rc->param = *param; | ||
203 : | |||
204 : | edgomez | 1042 | #define _INIT(a, b) if((a) <= 0) (a) = (b) |
205 : | /* Let's set our defaults if needed */ | ||
206 : | _INIT(rc->param.keyframe_boost, DEFAULT_KEYFRAME_BOOST); | ||
207 : | _INIT(rc->param.payback_method, DEFAULT_PAYBACK_METHOD); | ||
208 : | _INIT(rc->param.bitrate_payback_delay, DEFAULT_BITRATE_PAYBACK_DELAY); | ||
209 : | _INIT(rc->param.curve_compression_high, DEFAULT_CURVE_COMPRESSION_HIGH); | ||
210 : | _INIT(rc->param.curve_compression_low, DEFAULT_CURVE_COMPRESSION_LOW); | ||
211 : | _INIT(rc->param.max_overflow_improvement, DEFAULT_MAX_OVERFLOW_IMPROVEMENT); | ||
212 : | _INIT(rc->param.max_overflow_degradation, DEFAULT_MAX_OVERFLOW_DEGRADATION); | ||
213 : | suxen_drol | 942 | |
214 : | edgomez | 1042 | /* Alt curve settings */ |
215 : | _INIT(rc->param.use_alt_curve, DEFAULT_USE_ALT_CURVE); | ||
216 : | _INIT(rc->param.alt_curve_high_dist, DEFAULT_ALT_CURVE_HIGH_DIST); | ||
217 : | _INIT(rc->param.alt_curve_low_dist, DEFAULT_ALT_CURVE_LOW_DIST); | ||
218 : | _INIT(rc->param.alt_curve_use_auto, DEFAULT_ALT_CURVE_USE_AUTO); | ||
219 : | _INIT(rc->param.alt_curve_auto_str, DEFAULT_ALT_CURVE_AUTO_STR); | ||
220 : | _INIT(rc->param.alt_curve_type, DEFAULT_ALT_CURVE_TYPE); | ||
221 : | _INIT(rc->param.alt_curve_min_rel_qual, DEFAULT_ALT_CURVE_MIN_REL_QUAL); | ||
222 : | _INIT(rc->param.alt_curve_use_auto_bonus_bias, DEFAULT_ALT_CURVE_USE_AUTO_BONUS_BIAS); | ||
223 : | _INIT(rc->param.alt_curve_bonus_bias, DEFAULT_ALT_CURVE_BONUS_BIAS); | ||
224 : | suxen_drol | 942 | |
225 : | edgomez | 1042 | /* Keyframe settings */ |
226 : | _INIT(rc->param.kftreshold, DEFAULT_KFTRESHOLD); | ||
227 : | _INIT(rc->param.kfreduction, DEFAULT_KFREDUCTION); | ||
228 : | _INIT(rc->param.min_key_interval, DEFAULT_MIN_KEY_INTERVAL); | ||
229 : | #undef _INIT | ||
230 : | suxen_drol | 942 | |
231 : | edgomez | 1042 | /* Count frames in the stats file */ |
232 : | suxen_drol | 977 | if (!det_stats_length(rc, param->filename)){ |
233 : | suxen_drol | 1032 | DPRINTF(XVID_DEBUG_RC,"fopen %s failed\n", param->filename); |
234 : | suxen_drol | 942 | free(rc); |
235 : | return XVID_ERR_FAIL; | ||
236 : | } | ||
237 : | |||
238 : | edgomez | 1042 | /* Allocate the stats' memory */ |
239 : | if ((rc->stats = malloc(rc->num_frames * sizeof(stat_t))) == NULL) { | ||
240 : | suxen_drol | 942 | free(rc); |
241 : | return XVID_ERR_MEMORY; | ||
242 : | } | ||
243 : | |||
244 : | edgomez | 1037 | /* |
245 : | edgomez | 1042 | * Allocate keyframes location's memory |
246 : | * PS: see comment in pre_process0 for the +1 location requirement | ||
247 : | edgomez | 1037 | */ |
248 : | suxen_drol | 942 | if ((rc->keyframe_locations = malloc((rc->num_keyframes + 1) * sizeof(int))) == NULL) { |
249 : | free(rc->stats); | ||
250 : | free(rc); | ||
251 : | return XVID_ERR_MEMORY; | ||
252 : | } | ||
253 : | |||
254 : | suxen_drol | 977 | if (!load_stats(rc, param->filename)) { |
255 : | suxen_drol | 1032 | DPRINTF(XVID_DEBUG_RC,"fopen %s failed\n", param->filename); |
256 : | suxen_drol | 942 | free(rc->keyframe_locations); |
257 : | free(rc->stats); | ||
258 : | free(rc); | ||
259 : | return XVID_ERR_FAIL; | ||
260 : | } | ||
261 : | |||
262 : | /* pre-process our stats */ | ||
263 : | suxen_drol | 977 | |
264 : | suxen_drol | 1030 | if (rc->num_frames < create->fbase/create->fincr) { |
265 : | rc->target = rc->param.bitrate / 8; /* one second */ | ||
266 : | edgomez | 1042 | } else { |
267 : | edgomez | 1040 | rc->target = |
268 : | ((uint64_t)rc->param.bitrate * (uint64_t)rc->num_frames * (uint64_t)create->fincr) / \ | ||
269 : | ((uint64_t)create->fbase * 8); | ||
270 : | suxen_drol | 977 | } |
271 : | suxen_drol | 1030 | |
272 : | edgomez | 1040 | DPRINTF(XVID_DEBUG_RC, "Number of frames: %d\n", rc->num_frames); |
273 : | DPRINTF(XVID_DEBUG_RC, "Frame rate: %d/%d\n", create->fbase, create->fincr); | ||
274 : | DPRINTF(XVID_DEBUG_RC, "Target bitrate: %ld\n", rc->param.bitrate); | ||
275 : | DPRINTF(XVID_DEBUG_RC, "Target filesize: %lld\n", rc->target); | ||
276 : | suxen_drol | 1032 | |
277 : | edgomez | 1041 | /* Compensate the mean frame overhead caused by the container */ |
278 : | rc->target -= rc->num_frames*rc->param.container_frame_overhead; | ||
279 : | DPRINTF(XVID_DEBUG_RC, "Container Frame overhead: %d\n", rc->param.container_frame_overhead); | ||
280 : | DPRINTF(XVID_DEBUG_RC, "Target filesize (after container compensation): %lld\n", rc->target); | ||
281 : | suxen_drol | 977 | |
282 : | pre_process0(rc); | ||
283 : | edgomez | 1036 | |
284 : | suxen_drol | 977 | if (rc->param.bitrate) { |
285 : | suxen_drol | 1030 | zone_process(rc, create); |
286 : | suxen_drol | 977 | internal_scale(rc); |
287 : | suxen_drol | 1030 | }else{ |
288 : | /* external scaler: ignore zone */ | ||
289 : | for (i=0;i<rc->num_frames;i++) { | ||
290 : | rc->stats[i].zone_mode = XVID_ZONE_WEIGHT; | ||
291 : | rc->stats[i].weight = 1.0; | ||
292 : | } | ||
293 : | rc->avg_weight = 1.0; | ||
294 : | rc->tot_quant = 0; | ||
295 : | } | ||
296 : | pre_process1(rc); | ||
297 : | |||
298 : | for (i=0; i<32;i++) { | ||
299 : | rc->pquant_error[i] = 0; | ||
300 : | rc->bquant_error[i] = 0; | ||
301 : | rc->quant_count[i] = 0; | ||
302 : | } | ||
303 : | |||
304 : | rc->fq_error = 0; | ||
305 : | suxen_drol | 977 | |
306 : | suxen_drol | 942 | *handle = rc; |
307 : | return(0); | ||
308 : | } | ||
309 : | |||
310 : | edgomez | 1042 | /*---------------------------------------------------------------------------- |
311 : | *--------------------------------------------------------------------------*/ | ||
312 : | suxen_drol | 942 | |
313 : | edgomez | 1042 | static int |
314 : | rc_2pass2_destroy(rc_2pass2_t * rc, xvid_plg_destroy_t * destroy) | ||
315 : | suxen_drol | 942 | { |
316 : | free(rc->keyframe_locations); | ||
317 : | free(rc->stats); | ||
318 : | free(rc); | ||
319 : | return(0); | ||
320 : | } | ||
321 : | |||
322 : | edgomez | 1042 | /*---------------------------------------------------------------------------- |
323 : | *--------------------------------------------------------------------------*/ | ||
324 : | suxen_drol | 942 | |
325 : | edgomez | 1042 | static int |
326 : | rc_2pass2_before(rc_2pass2_t * rc, xvid_plg_data_t * data) | ||
327 : | suxen_drol | 942 | { |
328 : | stat_t * s = &rc->stats[data->frame_num]; | ||
329 : | int overflow; | ||
330 : | int desired; | ||
331 : | double dbytes; | ||
332 : | double curve_temp; | ||
333 : | int capped_to_max_framesize = 0; | ||
334 : | |||
335 : | edgomez | 1037 | /* |
336 : | * This function is quite long but easy to understand. In order to simplify | ||
337 : | * the code path (a bit), we treat 3 cases that can return immediatly. | ||
338 : | */ | ||
339 : | suxen_drol | 942 | |
340 : | edgomez | 1037 | /* First case: Another plugin has already set a quantizer */ |
341 : | if (data->quant > 0) | ||
342 : | return(0); | ||
343 : | suxen_drol | 942 | |
344 : | edgomez | 1037 | /* Second case: We are in a Quant zone */ |
345 : | if (s->zone_mode == XVID_ZONE_QUANT) { | ||
346 : | suxen_drol | 942 | |
347 : | edgomez | 1037 | rc->fq_error += s->weight; |
348 : | data->quant = (int)rc->fq_error; | ||
349 : | rc->fq_error -= data->quant; | ||
350 : | |||
351 : | s->desired_length = s->length; | ||
352 : | suxen_drol | 1032 | |
353 : | edgomez | 1037 | return(0); |
354 : | suxen_drol | 942 | |
355 : | edgomez | 1037 | } |
356 : | suxen_drol | 977 | |
357 : | edgomez | 1037 | /* Third case: insufficent stats data */ |
358 : | if (data->frame_num >= rc->num_frames) | ||
359 : | return 0; | ||
360 : | suxen_drol | 942 | |
361 : | edgomez | 1037 | /* |
362 : | * The last case is the one every normal minded developer should fear to | ||
363 : | * maintain in a project :-) | ||
364 : | */ | ||
365 : | suxen_drol | 942 | |
366 : | edgomez | 1037 | /* XXX: why by 8 */ |
367 : | overflow = rc->overflow / 8; | ||
368 : | suxen_drol | 942 | |
369 : | edgomez | 1037 | /* |
370 : | * The rc->overflow field represents the overflow in current scene (between two | ||
371 : | edgomez | 1042 | * IFrames) so we must not forget to reset it if we are entering a new scene |
372 : | edgomez | 1037 | */ |
373 : | if (s->type == XVID_TYPE_IVOP) { | ||
374 : | overflow = 0; | ||
375 : | } | ||
376 : | suxen_drol | 942 | |
377 : | edgomez | 1037 | desired = s->scaled_length; |
378 : | suxen_drol | 942 | |
379 : | edgomez | 1037 | dbytes = desired; |
380 : | if (s->type == XVID_TYPE_IVOP) { | ||
381 : | dbytes += desired * rc->param.keyframe_boost / 100; | ||
382 : | } | ||
383 : | dbytes /= rc->movie_curve; | ||
384 : | suxen_drol | 942 | |
385 : | edgomez | 1037 | /* |
386 : | * We are now entering in the hard part of the algo, it was first designed | ||
387 : | * to work with i/pframes only streams, so the way it computes things is | ||
388 : | * adapted to pframes only. However we can use it if we just take care to | ||
389 : | * scale the bframes sizes to pframes sizes using the ratio avg_p/avg_p and | ||
390 : | * then before really using values depending on frame sizes, scaling the | ||
391 : | * value again with the inverse ratio | ||
392 : | */ | ||
393 : | edgomez | 1042 | if (s->type == XVID_TYPE_BVOP) |
394 : | edgomez | 1037 | dbytes *= rc->avg_length[XVID_TYPE_PVOP-1] / rc->avg_length[XVID_TYPE_BVOP-1]; |
395 : | suxen_drol | 942 | |
396 : | edgomez | 1037 | /* |
397 : | * Apply user's choosen Payback method. Payback helps bitrate to follow the | ||
398 : | * scaled curve "paying back" past errors in curve previsions. | ||
399 : | */ | ||
400 : | if (rc->param.payback_method == XVID_PAYBACK_BIAS) { | ||
401 : | desired =(int)(rc->curve_comp_error / rc->param.bitrate_payback_delay); | ||
402 : | edgomez | 1042 | } else { |
403 : | edgomez | 1037 | desired = (int)(rc->curve_comp_error * dbytes / |
404 : | rc->avg_length[XVID_TYPE_PVOP-1] / rc->param.bitrate_payback_delay); | ||
405 : | suxen_drol | 942 | |
406 : | edgomez | 1037 | if (labs(desired) > fabs(rc->curve_comp_error)) { |
407 : | desired = (int)rc->curve_comp_error; | ||
408 : | } | ||
409 : | } | ||
410 : | suxen_drol | 942 | |
411 : | edgomez | 1037 | rc->curve_comp_error -= desired; |
412 : | suxen_drol | 942 | |
413 : | edgomez | 1037 | /* |
414 : | * Alt curve treatment is not that hard to understand though the formulas | ||
415 : | * seem to be huge. Alt treatment is basically a way to soft/harden the | ||
416 : | * curve flux applying sine/linear/cosine ratios | ||
417 : | */ | ||
418 : | suxen_drol | 942 | |
419 : | edgomez | 1037 | /* XXX: warning */ |
420 : | curve_temp = 0; | ||
421 : | suxen_drol | 942 | |
422 : | edgomez | 1037 | if (rc->param.use_alt_curve) { |
423 : | if (s->type != XVID_TYPE_IVOP) { | ||
424 : | if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { | ||
425 : | if (dbytes >= rc->alt_curve_high) { | ||
426 : | curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev); | ||
427 : | } else { | ||
428 : | switch(rc->param.alt_curve_type) { | ||
429 : | case XVID_CURVE_SINE : | ||
430 : | 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))); | ||
431 : | break; | ||
432 : | case XVID_CURVE_LINEAR : | ||
433 : | 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); | ||
434 : | break; | ||
435 : | case XVID_CURVE_COSINE : | ||
436 : | 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)))); | ||
437 : | } | ||
438 : | } | ||
439 : | } else { | ||
440 : | if (dbytes <= rc->alt_curve_low){ | ||
441 : | curve_temp = dbytes; | ||
442 : | } else { | ||
443 : | switch(rc->param.alt_curve_type) { | ||
444 : | case XVID_CURVE_SINE : | ||
445 : | 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))); | ||
446 : | break; | ||
447 : | case XVID_CURVE_LINEAR : | ||
448 : | 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); | ||
449 : | break; | ||
450 : | case XVID_CURVE_COSINE : | ||
451 : | 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)))); | ||
452 : | } | ||
453 : | } | ||
454 : | } | ||
455 : | suxen_drol | 942 | |
456 : | edgomez | 1037 | /* |
457 : | * End of code path for curve_temp, as told earlier, we are now | ||
458 : | * obliged to scale the value to a bframe one using the inverse | ||
459 : | * ratio applied earlier | ||
460 : | */ | ||
461 : | if (s->type == XVID_TYPE_BVOP) | ||
462 : | curve_temp *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; | ||
463 : | suxen_drol | 942 | |
464 : | edgomez | 1037 | curve_temp = curve_temp * rc->curve_comp_scale + rc->alt_curve_curve_bias_bonus; |
465 : | suxen_drol | 942 | |
466 : | edgomez | 1037 | desired += ((int)curve_temp); |
467 : | rc->curve_comp_error += curve_temp - (int)curve_temp; | ||
468 : | } else { | ||
469 : | /* | ||
470 : | * End of code path for dbytes, as told earlier, we are now | ||
471 : | * obliged to scale the value to a bframe one using the inverse | ||
472 : | * ratio applied earlier | ||
473 : | */ | ||
474 : | if (s->type == XVID_TYPE_BVOP) | ||
475 : | dbytes *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; | ||
476 : | suxen_drol | 1030 | |
477 : | edgomez | 1037 | desired += ((int)dbytes); |
478 : | rc->curve_comp_error += dbytes - (int)dbytes; | ||
479 : | } | ||
480 : | suxen_drol | 1030 | |
481 : | edgomez | 1037 | } else if ((rc->param.curve_compression_high + rc->param.curve_compression_low) && s->type != XVID_TYPE_IVOP) { |
482 : | suxen_drol | 1030 | |
483 : | edgomez | 1037 | curve_temp = rc->curve_comp_scale; |
484 : | if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { | ||
485 : | curve_temp *= ((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_high / 100.0); | ||
486 : | } else { | ||
487 : | curve_temp *= ((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_low / 100.0); | ||
488 : | } | ||
489 : | suxen_drol | 942 | |
490 : | edgomez | 1037 | /* |
491 : | * End of code path for curve_temp, as told earlier, we are now | ||
492 : | * obliged to scale the value to a bframe one using the inverse | ||
493 : | * ratio applied earlier | ||
494 : | */ | ||
495 : | if (s->type == XVID_TYPE_BVOP) | ||
496 : | curve_temp *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; | ||
497 : | suxen_drol | 1032 | |
498 : | edgomez | 1037 | desired += (int)curve_temp; |
499 : | rc->curve_comp_error += curve_temp - (int)curve_temp; | ||
500 : | } else { | ||
501 : | /* | ||
502 : | * End of code path for dbytes, as told earlier, we are now | ||
503 : | * obliged to scale the value to a bframe one using the inverse | ||
504 : | * ratio applied earlier | ||
505 : | */ | ||
506 : | edgomez | 1042 | if (s->type == XVID_TYPE_BVOP) |
507 : | edgomez | 1037 | dbytes *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; |
508 : | edgomez | 1042 | |
509 : | edgomez | 1037 | desired += (int)dbytes; |
510 : | rc->curve_comp_error += dbytes - (int)dbytes; | ||
511 : | } | ||
512 : | suxen_drol | 942 | |
513 : | |||
514 : | edgomez | 1037 | /* |
515 : | * We can't do bigger frames than first pass, this would be stupid as first | ||
516 : | * pass is quant=2 and that reaching quant=1 is not worth it. We would lose | ||
517 : | * many bytes and we would not not gain much quality. | ||
518 : | */ | ||
519 : | if (desired > s->length) { | ||
520 : | rc->curve_comp_error += desired - s->length; | ||
521 : | desired = s->length; | ||
522 : | edgomez | 1042 | } else { |
523 : | edgomez | 1037 | if (desired < rc->min_length[s->type-1]) { |
524 : | if (s->type == XVID_TYPE_IVOP){ | ||
525 : | rc->curve_comp_error -= rc->min_length[XVID_TYPE_IVOP-1] - desired; | ||
526 : | } | ||
527 : | desired = rc->min_length[s->type-1]; | ||
528 : | } | ||
529 : | } | ||
530 : | suxen_drol | 942 | |
531 : | edgomez | 1037 | s->desired_length = desired; |
532 : | suxen_drol | 942 | |
533 : | edgomez | 1037 | |
534 : | /* if this keyframe is too close to the next, reduce it's byte allotment | ||
535 : | XXX: why do we do this after setting the desired length */ | ||
536 : | suxen_drol | 942 | |
537 : | edgomez | 1037 | if (s->type == XVID_TYPE_IVOP) { |
538 : | int KFdistance = rc->keyframe_locations[rc->KF_idx] - rc->keyframe_locations[rc->KF_idx - 1]; | ||
539 : | suxen_drol | 942 | |
540 : | edgomez | 1037 | if (KFdistance < rc->param.kftreshold) { |
541 : | |||
542 : | edgomez | 1042 | KFdistance -= rc->param.min_key_interval; |
543 : | suxen_drol | 942 | |
544 : | edgomez | 1037 | if (KFdistance >= 0) { |
545 : | int KF_min_size; | ||
546 : | suxen_drol | 942 | |
547 : | edgomez | 1037 | KF_min_size = desired * (100 - rc->param.kfreduction) / 100; |
548 : | if (KF_min_size < 1) | ||
549 : | KF_min_size = 1; | ||
550 : | suxen_drol | 942 | |
551 : | edgomez | 1037 | desired = KF_min_size + (desired - KF_min_size) * KFdistance / |
552 : | (rc->param.kftreshold - rc->param.min_key_interval); | ||
553 : | suxen_drol | 942 | |
554 : | edgomez | 1037 | if (desired < 1) |
555 : | desired = 1; | ||
556 : | } | ||
557 : | } | ||
558 : | } | ||
559 : | suxen_drol | 942 | |
560 : | edgomez | 1037 | overflow = (int)((double)overflow * desired / rc->avg_length[XVID_TYPE_PVOP-1]); |
561 : | suxen_drol | 942 | |
562 : | edgomez | 1037 | /* Reign in overflow with huge frames */ |
563 : | if (labs(overflow) > labs(rc->overflow)) { | ||
564 : | overflow = rc->overflow; | ||
565 : | } | ||
566 : | suxen_drol | 942 | |
567 : | edgomez | 1037 | /* Make sure overflow doesn't run away */ |
568 : | if (overflow > desired * rc->param.max_overflow_improvement / 100) { | ||
569 : | desired += (overflow <= desired) ? desired * rc->param.max_overflow_improvement / 100 : | ||
570 : | overflow * rc->param.max_overflow_improvement / 100; | ||
571 : | } else if (overflow < desired * rc->param.max_overflow_degradation / -100){ | ||
572 : | desired += desired * rc->param.max_overflow_degradation / -100; | ||
573 : | } else { | ||
574 : | desired += overflow; | ||
575 : | } | ||
576 : | suxen_drol | 942 | |
577 : | edgomez | 1037 | /* Make sure we are not higher than desired frame size */ |
578 : | if (desired > rc->max_length) { | ||
579 : | capped_to_max_framesize = 1; | ||
580 : | desired = rc->max_length; | ||
581 : | edgomez | 1040 | DPRINTF(XVID_DEBUG_RC,"[%i] Capped to maximum frame size\n", |
582 : | data->frame_num); | ||
583 : | edgomez | 1037 | } |
584 : | suxen_drol | 942 | |
585 : | edgomez | 1037 | /* Make sure to not scale below the minimum framesize */ |
586 : | edgomez | 1040 | if (desired < rc->min_length[s->type-1]) { |
587 : | edgomez | 1037 | desired = rc->min_length[s->type-1]; |
588 : | edgomez | 1040 | DPRINTF(XVID_DEBUG_RC,"[%i] Capped to minimum frame size\n", |
589 : | data->frame_num); | ||
590 : | } | ||
591 : | suxen_drol | 942 | |
592 : | edgomez | 1037 | /* |
593 : | * Don't laugh at this very 'simple' quant<->filesize relationship, it | ||
594 : | * proves to be acurate enough for our algorithm | ||
595 : | */ | ||
596 : | edgomez | 1042 | data->quant = s->quant*s->length/desired; |
597 : | suxen_drol | 942 | |
598 : | edgomez | 1037 | /* Let's clip the computed quantizer, if needed */ |
599 : | if (data->quant < 1) { | ||
600 : | data->quant = 1; | ||
601 : | } else if (data->quant > 31) { | ||
602 : | data->quant = 31; | ||
603 : | } else if (s->type != XVID_TYPE_IVOP) { | ||
604 : | suxen_drol | 942 | |
605 : | edgomez | 1037 | /* |
606 : | * The frame quantizer has not been clipped, this appear to be a good | ||
607 : | * computed quantizer, however past frames give us some info about how | ||
608 : | * this quantizer performs against the algo prevision. Let's use this | ||
609 : | * prevision to increase the quantizer when we observe a too big | ||
610 : | * accumulated error | ||
611 : | */ | ||
612 : | edgomez | 1042 | if (s->type == XVID_TYPE_BVOP) { |
613 : | edgomez | 1037 | rc->bquant_error[data->quant] += ((double)(s->quant * s->length) / desired) - data->quant; |
614 : | suxen_drol | 942 | |
615 : | edgomez | 1037 | if (rc->bquant_error[data->quant] >= 1.0) { |
616 : | rc->bquant_error[data->quant] -= 1.0; | ||
617 : | data->quant++; | ||
618 : | } | ||
619 : | } else { | ||
620 : | rc->pquant_error[data->quant] += ((double)(s->quant * s->length) / desired) - data->quant; | ||
621 : | suxen_drol | 942 | |
622 : | edgomez | 1037 | if (rc->pquant_error[data->quant] >= 1.0) { |
623 : | rc->pquant_error[data->quant] -= 1.0; | ||
624 : | edgomez | 1042 | data->quant++; |
625 : | edgomez | 1037 | } |
626 : | } | ||
627 : | } | ||
628 : | suxen_drol | 942 | |
629 : | edgomez | 1037 | /* |
630 : | * Now we have a computed quant that is in the right quante range, with a | ||
631 : | * possible +1 correction due to cumulated error. We can now safely clip | ||
632 : | * the quantizer again with user's quant ranges. "Safely" means the Rate | ||
633 : | * Control could learn more about this quantizer, this knowledge is useful | ||
634 : | * for future frames even if it this quantizer won't be really used atm, | ||
635 : | * that's why we don't perform this clipping earlier. | ||
636 : | */ | ||
637 : | if (data->quant < data->min_quant[s->type-1]) { | ||
638 : | data->quant = data->min_quant[s->type-1]; | ||
639 : | } else if (data->quant > data->max_quant[s->type-1]) { | ||
640 : | data->quant = data->max_quant[s->type-1]; | ||
641 : | } | ||
642 : | suxen_drol | 942 | |
643 : | edgomez | 1037 | /* |
644 : | * To avoid big quality jumps from frame to frame, we apply a "security" | ||
645 : | * rule that makes |last_quant - new_quant| <= 2. This rule only applies | ||
646 : | * to predicted frames (P and B) | ||
647 : | */ | ||
648 : | if (s->type != XVID_TYPE_IVOP && rc->last_quant[s->type-1] && capped_to_max_framesize == 0) { | ||
649 : | suxen_drol | 942 | |
650 : | edgomez | 1037 | if (data->quant > rc->last_quant[s->type-1] + 2) { |
651 : | data->quant = rc->last_quant[s->type-1] + 2; | ||
652 : | edgomez | 1040 | DPRINTF(XVID_DEBUG_RC, |
653 : | "[%i] p/b-frame quantizer prevented from rising too steeply\n", | ||
654 : | data->frame_num); | ||
655 : | edgomez | 1037 | } |
656 : | if (data->quant < rc->last_quant[s->type-1] - 2) { | ||
657 : | data->quant = rc->last_quant[s->type-1] - 2; | ||
658 : | edgomez | 1040 | DPRINTF(XVID_DEBUG_RC, |
659 : | "[%i] p/b-frame quantizer prevented from falling too steeply\n", | ||
660 : | data->frame_num); | ||
661 : | edgomez | 1037 | } |
662 : | } | ||
663 : | suxen_drol | 1030 | |
664 : | edgomez | 1037 | /* |
665 : | * We don't want to pollute the RC history results when our computed quant | ||
666 : | * has been computed from a capped frame size | ||
667 : | */ | ||
668 : | if (capped_to_max_framesize == 0) { | ||
669 : | rc->last_quant[s->type-1] = data->quant; | ||
670 : | } | ||
671 : | suxen_drol | 1030 | |
672 : | edgomez | 1037 | return 0; |
673 : | suxen_drol | 942 | } |
674 : | |||
675 : | edgomez | 1042 | /*---------------------------------------------------------------------------- |
676 : | *--------------------------------------------------------------------------*/ | ||
677 : | suxen_drol | 942 | |
678 : | edgomez | 1042 | static int |
679 : | rc_2pass2_after(rc_2pass2_t * rc, xvid_plg_data_t * data) | ||
680 : | suxen_drol | 942 | { |
681 : | edgomez | 1043 | const char frame_type[4] = { 'i', 'p', 'b', 's'}; |
682 : | stat_t * s = &rc->stats[data->frame_num]; | ||
683 : | suxen_drol | 942 | |
684 : | edgomez | 1037 | /* Insufficent stats data */ |
685 : | if (data->frame_num >= rc->num_frames) | ||
686 : | suxen_drol | 942 | return 0; |
687 : | |||
688 : | rc->quant_count[data->quant]++; | ||
689 : | |||
690 : | if (data->type == XVID_TYPE_IVOP) { | ||
691 : | int kfdiff = (rc->keyframe_locations[rc->KF_idx] - rc->keyframe_locations[rc->KF_idx - 1]); | ||
692 : | |||
693 : | rc->overflow += rc->KFoverflow; | ||
694 : | rc->KFoverflow = s->desired_length - data->length; | ||
695 : | |||
696 : | if (kfdiff > 1) { // non-consecutive keyframes | ||
697 : | rc->KFoverflow_partial = rc->KFoverflow / (kfdiff - 1); | ||
698 : | }else{ // consecutive keyframes | ||
699 : | rc->overflow += rc->KFoverflow; | ||
700 : | rc->KFoverflow = 0; | ||
701 : | rc->KFoverflow_partial = 0; | ||
702 : | } | ||
703 : | rc->KF_idx++; | ||
704 : | edgomez | 1042 | } else { |
705 : | suxen_drol | 942 | // distribute part of the keyframe overflow |
706 : | rc->overflow += s->desired_length - data->length + rc->KFoverflow_partial; | ||
707 : | rc->KFoverflow -= rc->KFoverflow_partial; | ||
708 : | } | ||
709 : | |||
710 : | edgomez | 1043 | DPRINTF(XVID_DEBUG_RC, "[%i] type:%c quant:%i stats1:%i scaled:%i actual:%i overflow:%i\n", |
711 : | edgomez | 1042 | data->frame_num, |
712 : | edgomez | 1043 | frame_type[data->type-1], |
713 : | edgomez | 1042 | data->quant, |
714 : | s->length, | ||
715 : | s->scaled_length, | ||
716 : | data->length, | ||
717 : | rc->overflow); | ||
718 : | suxen_drol | 942 | |
719 : | return(0); | ||
720 : | } | ||
721 : | |||
722 : | edgomez | 1042 | /***************************************************************************** |
723 : | * Helper functions definition | ||
724 : | ****************************************************************************/ | ||
725 : | suxen_drol | 942 | |
726 : | edgomez | 1042 | #define BUF_SZ 1024 |
727 : | #define MAX_COLS 5 | ||
728 : | suxen_drol | 942 | |
729 : | edgomez | 1042 | /* open stats file, and count num frames */ |
730 : | static int | ||
731 : | det_stats_length(rc_2pass2_t * rc, char * filename) | ||
732 : | suxen_drol | 942 | { |
733 : | edgomez | 1042 | FILE * f; |
734 : | int n, ignore; | ||
735 : | char type; | ||
736 : | |||
737 : | rc->num_frames = 0; | ||
738 : | rc->num_keyframes = 0; | ||
739 : | |||
740 : | if ((f = fopen(filename, "rt")) == NULL) | ||
741 : | suxen_drol | 942 | return 0; |
742 : | |||
743 : | edgomez | 1042 | while((n = fscanf(f, "%c %d %d %d %d %d %d\n", |
744 : | &type, &ignore, &ignore, &ignore, &ignore, &ignore, &ignore)) != EOF) { | ||
745 : | if (type == 'i') { | ||
746 : | rc->num_frames++; | ||
747 : | rc->num_keyframes++; | ||
748 : | }else if (type == 'p' || type == 'b' || type == 's') { | ||
749 : | rc->num_frames++; | ||
750 : | } | ||
751 : | } | ||
752 : | suxen_drol | 942 | |
753 : | edgomez | 1042 | fclose(f); |
754 : | suxen_drol | 942 | |
755 : | edgomez | 1042 | return 1; |
756 : | } | ||
757 : | suxen_drol | 942 | |
758 : | edgomez | 1042 | /* open stats file(s) and read into rc->stats array */ |
759 : | |||
760 : | static int | ||
761 : | load_stats(rc_2pass2_t *rc, char * filename) | ||
762 : | { | ||
763 : | FILE * f; | ||
764 : | int i, not_scaled; | ||
765 : | |||
766 : | |||
767 : | if ((f = fopen(filename, "rt"))==NULL) | ||
768 : | return 0; | ||
769 : | |||
770 : | i = 0; | ||
771 : | not_scaled = 0; | ||
772 : | while(i < rc->num_frames) { | ||
773 : | stat_t * s = &rc->stats[i]; | ||
774 : | int n; | ||
775 : | char type; | ||
776 : | |||
777 : | s->scaled_length = 0; | ||
778 : | n = fscanf(f, "%c %d %d %d %d %d %d\n", &type, &s->quant, &s->blks[0], &s->blks[1], &s->blks[2], &s->length, &s->scaled_length); | ||
779 : | if (n == EOF) break; | ||
780 : | if (n < 7) { | ||
781 : | not_scaled = 1; | ||
782 : | } | ||
783 : | |||
784 : | if (type == 'i') { | ||
785 : | s->type = XVID_TYPE_IVOP; | ||
786 : | }else if (type == 'p' || type == 's') { | ||
787 : | s->type = XVID_TYPE_PVOP; | ||
788 : | }else if (type == 'b') { | ||
789 : | s->type = XVID_TYPE_BVOP; | ||
790 : | }else{ /* unknown type */ | ||
791 : | DPRINTF(XVID_DEBUG_RC, "unknown stats frame type; assuming pvop\n"); | ||
792 : | s->type = XVID_TYPE_PVOP; | ||
793 : | } | ||
794 : | |||
795 : | i++; | ||
796 : | suxen_drol | 942 | } |
797 : | |||
798 : | edgomez | 1042 | rc->num_frames = i; |
799 : | |||
800 : | fclose(f); | ||
801 : | |||
802 : | return 1; | ||
803 : | suxen_drol | 942 | } |
804 : | edgomez | 1042 | |
805 : | #if 0 | ||
806 : | static void print_stats(rc_2pass2_t * rc) | ||
807 : | { | ||
808 : | int i; | ||
809 : | DPRINTF(XVID_DEBUG_RC, "type quant length scaled_length\n"); | ||
810 : | for (i = 0; i < rc->num_frames; i++) { | ||
811 : | stat_t * s = &rc->stats[i]; | ||
812 : | DPRINTF(XVID_DEBUG_RC, "%d %d %d %d\n", s->type, s->quant, s->length, s->scaled_length); | ||
813 : | } | ||
814 : | } | ||
815 : | #endif | ||
816 : | |||
817 : | /* pre-process the statistics data | ||
818 : | - for each type, count, tot_length, min_length, max_length | ||
819 : | - set keyframes_locations | ||
820 : | */ | ||
821 : | |||
822 : | static void | ||
823 : | pre_process0(rc_2pass2_t * rc) | ||
824 : | { | ||
825 : | int i,j; | ||
826 : | |||
827 : | for (i=0; i<3; i++) { | ||
828 : | rc->count[i]=0; | ||
829 : | rc->tot_length[i] = 0; | ||
830 : | rc->last_quant[i] = 0; | ||
831 : | rc->min_length[i] = INT_MAX; | ||
832 : | } | ||
833 : | |||
834 : | rc->max_length = INT_MIN; | ||
835 : | |||
836 : | for (i=j=0; i<rc->num_frames; i++) { | ||
837 : | stat_t * s = &rc->stats[i]; | ||
838 : | |||
839 : | rc->count[s->type-1]++; | ||
840 : | rc->tot_length[s->type-1] += s->length; | ||
841 : | |||
842 : | if (s->length < rc->min_length[s->type-1]) { | ||
843 : | rc->min_length[s->type-1] = s->length; | ||
844 : | } | ||
845 : | |||
846 : | if (s->length > rc->max_length) { | ||
847 : | rc->max_length = s->length; | ||
848 : | } | ||
849 : | |||
850 : | if (s->type == XVID_TYPE_IVOP) { | ||
851 : | rc->keyframe_locations[j] = i; | ||
852 : | j++; | ||
853 : | } | ||
854 : | } | ||
855 : | |||
856 : | /* | ||
857 : | * Nota Bene: | ||
858 : | * The "per sequence" overflow system considers a natural sequence to be | ||
859 : | * formed by all frames between two iframes, so if we want to make sure | ||
860 : | * the system does not go nuts during last sequence, we force the last | ||
861 : | * frame to appear in the keyframe locations array. | ||
862 : | */ | ||
863 : | rc->keyframe_locations[j] = i; | ||
864 : | |||
865 : | DPRINTF(XVID_DEBUG_RC, "Min 1st pass IFrame length: %d\n", rc->min_length[0]); | ||
866 : | DPRINTF(XVID_DEBUG_RC, "Min 1st pass PFrame length: %d\n", rc->min_length[1]); | ||
867 : | DPRINTF(XVID_DEBUG_RC, "Min 1st pass BFrame length: %d\n", rc->min_length[2]); | ||
868 : | } | ||
869 : | |||
870 : | /* calculate zone weight "center" */ | ||
871 : | |||
872 : | static void | ||
873 : | zone_process(rc_2pass2_t *rc, const xvid_plg_create_t * create) | ||
874 : | { | ||
875 : | int i,j; | ||
876 : | int n = 0; | ||
877 : | |||
878 : | rc->avg_weight = 0.0; | ||
879 : | rc->tot_quant = 0; | ||
880 : | |||
881 : | |||
882 : | if (create->num_zones == 0) { | ||
883 : | for (j = 0; j < rc->num_frames; j++) { | ||
884 : | rc->stats[j].zone_mode = XVID_ZONE_WEIGHT; | ||
885 : | rc->stats[j].weight = 1.0; | ||
886 : | } | ||
887 : | rc->avg_weight += rc->num_frames * 1.0; | ||
888 : | n += rc->num_frames; | ||
889 : | } | ||
890 : | |||
891 : | |||
892 : | for(i=0; i < create->num_zones; i++) { | ||
893 : | |||
894 : | int next = (i+1<create->num_zones) ? create->zones[i+1].frame : rc->num_frames; | ||
895 : | |||
896 : | if (i==0 && create->zones[i].frame > 0) { | ||
897 : | for (j = 0; j < create->zones[i].frame && j < rc->num_frames; j++) { | ||
898 : | rc->stats[j].zone_mode = XVID_ZONE_WEIGHT; | ||
899 : | rc->stats[j].weight = 1.0; | ||
900 : | } | ||
901 : | rc->avg_weight += create->zones[i].frame * 1.0; | ||
902 : | n += create->zones[i].frame; | ||
903 : | } | ||
904 : | |||
905 : | if (create->zones[i].mode == XVID_ZONE_WEIGHT) { | ||
906 : | for (j = create->zones[i].frame; j < next && j < rc->num_frames; j++ ) { | ||
907 : | rc->stats[j].zone_mode = XVID_ZONE_WEIGHT; | ||
908 : | rc->stats[j].weight = (double)create->zones[i].increment / (double)create->zones[i].base; | ||
909 : | } | ||
910 : | next -= create->zones[i].frame; | ||
911 : | rc->avg_weight += (double)(next * create->zones[i].increment) / (double)create->zones[i].base; | ||
912 : | n += next; | ||
913 : | }else{ // XVID_ZONE_QUANT | ||
914 : | for (j = create->zones[i].frame; j < next && j < rc->num_frames; j++ ) { | ||
915 : | rc->stats[j].zone_mode = XVID_ZONE_QUANT; | ||
916 : | rc->stats[j].weight = (double)create->zones[i].increment / (double)create->zones[i].base; | ||
917 : | rc->tot_quant += rc->stats[j].length; | ||
918 : | } | ||
919 : | } | ||
920 : | } | ||
921 : | rc->avg_weight = n>0 ? rc->avg_weight/n : 1.0; | ||
922 : | |||
923 : | DPRINTF(XVID_DEBUG_RC, "center_weight: %f (for %i frames); fixed_bytes: %i\n", rc->avg_weight, n, rc->tot_quant); | ||
924 : | } | ||
925 : | |||
926 : | |||
927 : | /* scale the curve */ | ||
928 : | |||
929 : | static void | ||
930 : | internal_scale(rc_2pass2_t *rc) | ||
931 : | { | ||
932 : | int64_t target = rc->target - rc->tot_quant; | ||
933 : | int64_t pass1_length = rc->tot_length[0] + rc->tot_length[1] + rc->tot_length[2] - rc->tot_quant; | ||
934 : | double scaler; | ||
935 : | int i; | ||
936 : | |||
937 : | |||
938 : | /* Let's compute a linear scaler in order to perform curve scaling */ | ||
939 : | scaler = (double)target / (double)pass1_length; | ||
940 : | |||
941 : | if (target <= 0 || pass1_length <= 0 || target >= pass1_length) { | ||
942 : | DPRINTF(XVID_DEBUG_RC, "WARNING: Undersize detected\n"); | ||
943 : | scaler = 1.0; | ||
944 : | } | ||
945 : | |||
946 : | DPRINTF(XVID_DEBUG_RC, | ||
947 : | "Before correction: target=%i, tot_length=%i, scaler=%f\n", | ||
948 : | (int)target, (int)pass1_length, scaler); | ||
949 : | |||
950 : | /* | ||
951 : | * Perform an initial scale pass. | ||
952 : | * If a frame size is scaled underneath our hardcoded minimums, then we | ||
953 : | * force the frame size to the minimum, and deduct the original & scaled | ||
954 : | * frame length from the original and target total lengths | ||
955 : | */ | ||
956 : | |||
957 : | for (i=0; i<rc->num_frames; i++) { | ||
958 : | stat_t * s = &rc->stats[i]; | ||
959 : | int min_size[3]; | ||
960 : | int len; | ||
961 : | |||
962 : | /* Compute min frame lengths (oe for each frame type) */ | ||
963 : | min_size[0] = ((s->blks[0]*22) + 240) / 8; | ||
964 : | min_size[1] = (s->blks[0] + 88) / 8; | ||
965 : | min_size[2] = 8; | ||
966 : | |||
967 : | if (s->zone_mode == XVID_ZONE_QUANT) { | ||
968 : | s->scaled_length = s->length; | ||
969 : | continue; | ||
970 : | } | ||
971 : | |||
972 : | /* Compute teh scaled length */ | ||
973 : | len = (int)((double)s->length * scaler * s->weight / rc->avg_weight); | ||
974 : | |||
975 : | /* Compare with the computed minimum */ | ||
976 : | if (len < min_size[s->type-1]) { | ||
977 : | /* force frame size to our computed minimum */ | ||
978 : | s->scaled_length = min_size[s->type-1]; | ||
979 : | target -= s->scaled_length; | ||
980 : | pass1_length -= s->length; | ||
981 : | } else { | ||
982 : | /* Do nothing for now, we'll scale this later */ | ||
983 : | s->scaled_length = 0; | ||
984 : | } | ||
985 : | |||
986 : | } | ||
987 : | |||
988 : | /* Correct the scaler for all non forced frames */ | ||
989 : | scaler = (double)target / (double)pass1_length; | ||
990 : | |||
991 : | /* Detect undersizing */ | ||
992 : | if (target <= 0 || pass1_length <= 0 || target >= pass1_length) { | ||
993 : | DPRINTF(XVID_DEBUG_RC, "WARNING: Undersize detected\n"); | ||
994 : | scaler = 1.0; | ||
995 : | } | ||
996 : | |||
997 : | DPRINTF(XVID_DEBUG_RC, | ||
998 : | "After correction: target=%i, tot_length=%i, scaler=%f\n", | ||
999 : | (int)target, (int)pass1_length, scaler); | ||
1000 : | |||
1001 : | /* Do another pass with the new scaler */ | ||
1002 : | for (i=0; i<rc->num_frames; i++) { | ||
1003 : | stat_t * s = &rc->stats[i]; | ||
1004 : | |||
1005 : | /* Ignore frame with forced frame sizes */ | ||
1006 : | if (s->scaled_length == 0) | ||
1007 : | s->scaled_length = (int)((double)s->length * scaler * s->weight / rc->avg_weight); | ||
1008 : | } | ||
1009 : | |||
1010 : | } | ||
1011 : | |||
1012 : | static void | ||
1013 : | pre_process1(rc_2pass2_t * rc) | ||
1014 : | { | ||
1015 : | int i; | ||
1016 : | double total1, total2; | ||
1017 : | uint64_t ivop_boost_total; | ||
1018 : | |||
1019 : | ivop_boost_total = 0; | ||
1020 : | rc->curve_comp_error = 0; | ||
1021 : | |||
1022 : | for (i=0; i<3; i++) { | ||
1023 : | rc->tot_scaled_length[i] = 0; | ||
1024 : | } | ||
1025 : | |||
1026 : | for (i=0; i<rc->num_frames; i++) { | ||
1027 : | stat_t * s = &rc->stats[i]; | ||
1028 : | |||
1029 : | rc->tot_scaled_length[s->type-1] += s->scaled_length; | ||
1030 : | |||
1031 : | if (s->type == XVID_TYPE_IVOP) { | ||
1032 : | ivop_boost_total += s->scaled_length * rc->param.keyframe_boost / 100; | ||
1033 : | } | ||
1034 : | } | ||
1035 : | |||
1036 : | rc->movie_curve = ((double)(rc->tot_scaled_length[XVID_TYPE_PVOP-1] + rc->tot_scaled_length[XVID_TYPE_BVOP-1] + ivop_boost_total) / | ||
1037 : | (rc->tot_scaled_length[XVID_TYPE_PVOP-1] + rc->tot_scaled_length[XVID_TYPE_BVOP-1])); | ||
1038 : | |||
1039 : | for(i=0; i<3; i++) { | ||
1040 : | if (rc->count[i] == 0 || rc->movie_curve == 0) { | ||
1041 : | rc->avg_length[i] = 1; | ||
1042 : | }else{ | ||
1043 : | rc->avg_length[i] = rc->tot_scaled_length[i] / rc->count[i] / rc->movie_curve; | ||
1044 : | } | ||
1045 : | } | ||
1046 : | |||
1047 : | /* alt curve stuff here */ | ||
1048 : | |||
1049 : | if (rc->param.use_alt_curve) { | ||
1050 : | const double avg_pvop = rc->avg_length[XVID_TYPE_PVOP-1]; | ||
1051 : | const uint64_t tot_pvop = rc->tot_length[XVID_TYPE_PVOP-1]; | ||
1052 : | const uint64_t tot_bvop = rc->tot_length[XVID_TYPE_BVOP-1]; | ||
1053 : | const uint64_t tot_scaled_pvop = rc->tot_scaled_length[XVID_TYPE_PVOP-1]; | ||
1054 : | const uint64_t tot_scaled_bvop = rc->tot_scaled_length[XVID_TYPE_BVOP-1]; | ||
1055 : | |||
1056 : | rc->alt_curve_low = avg_pvop - avg_pvop * (double)rc->param.alt_curve_low_dist / 100.0; | ||
1057 : | rc->alt_curve_low_diff = avg_pvop - rc->alt_curve_low; | ||
1058 : | rc->alt_curve_high = avg_pvop + avg_pvop * (double)rc->param.alt_curve_high_dist / 100.0; | ||
1059 : | rc->alt_curve_high_diff = rc->alt_curve_high - avg_pvop; | ||
1060 : | |||
1061 : | if (rc->param.alt_curve_use_auto) { | ||
1062 : | if (tot_bvop + tot_pvop > tot_scaled_bvop + tot_scaled_pvop) { | ||
1063 : | rc->param.alt_curve_min_rel_qual = (int)(100.0 - (100.0 - 100.0 / | ||
1064 : | ((double)(tot_pvop + tot_bvop) / (double)(tot_scaled_pvop + tot_scaled_bvop))) * (double)rc->param.alt_curve_auto_str / 100.0); | ||
1065 : | |||
1066 : | if (rc->param.alt_curve_min_rel_qual < 20) | ||
1067 : | rc->param.alt_curve_min_rel_qual = 20; | ||
1068 : | }else{ | ||
1069 : | rc->param.alt_curve_min_rel_qual = 100; | ||
1070 : | } | ||
1071 : | } | ||
1072 : | rc->alt_curve_mid_qual = (1.0 + (double)rc->param.alt_curve_min_rel_qual / 100.0) / 2.0; | ||
1073 : | rc->alt_curve_qual_dev = 1.0 - rc->alt_curve_mid_qual; | ||
1074 : | |||
1075 : | if (rc->param.alt_curve_low_dist > 100) { | ||
1076 : | switch(rc->param.alt_curve_type) { | ||
1077 : | case XVID_CURVE_SINE: // Sine Curve (high aggressiveness) | ||
1078 : | rc->alt_curve_qual_dev *= 2.0 / (1.0 + sin(DEG2RAD * (avg_pvop * 90.0 / rc->alt_curve_low_diff))); | ||
1079 : | rc->alt_curve_mid_qual = 1.0 - rc->alt_curve_qual_dev * sin(DEG2RAD * (avg_pvop * 90.0 / rc->alt_curve_low_diff)); | ||
1080 : | break; | ||
1081 : | case XVID_CURVE_LINEAR: // Linear (medium aggressiveness) | ||
1082 : | rc->alt_curve_qual_dev *= 2.0 / (1.0 + avg_pvop / rc->alt_curve_low_diff); | ||
1083 : | rc->alt_curve_mid_qual = 1.0 - rc->alt_curve_qual_dev * avg_pvop / rc->alt_curve_low_diff; | ||
1084 : | break; | ||
1085 : | case XVID_CURVE_COSINE: // Cosine Curve (low aggressiveness) | ||
1086 : | rc->alt_curve_qual_dev *= 2.0 / (1.0 + (1.0 - cos(DEG2RAD * (avg_pvop * 90.0 / rc->alt_curve_low_diff)))); | ||
1087 : | 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))); | ||
1088 : | } | ||
1089 : | } | ||
1090 : | } | ||
1091 : | |||
1092 : | /* --- */ | ||
1093 : | |||
1094 : | total1=total2=0; | ||
1095 : | |||
1096 : | for (i=0; i<rc->num_frames; i++) { | ||
1097 : | stat_t * s = &rc->stats[i]; | ||
1098 : | |||
1099 : | if (s->type != XVID_TYPE_IVOP) { | ||
1100 : | double dbytes,dbytes2; | ||
1101 : | |||
1102 : | dbytes = s->scaled_length / rc->movie_curve; | ||
1103 : | dbytes2 = 0; /* XXX: warning */ | ||
1104 : | total1 += dbytes; | ||
1105 : | if (s->type == XVID_TYPE_BVOP) | ||
1106 : | dbytes *= rc->avg_length[XVID_TYPE_PVOP-1] / rc->avg_length[XVID_TYPE_BVOP-1]; | ||
1107 : | |||
1108 : | if (rc->param.use_alt_curve) { | ||
1109 : | if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { | ||
1110 : | |||
1111 : | if (dbytes >= rc->alt_curve_high) { | ||
1112 : | dbytes2 = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev); | ||
1113 : | }else{ | ||
1114 : | switch(rc->param.alt_curve_type) { | ||
1115 : | case XVID_CURVE_SINE : | ||
1116 : | 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))); | ||
1117 : | break; | ||
1118 : | case XVID_CURVE_LINEAR : | ||
1119 : | 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); | ||
1120 : | break; | ||
1121 : | case XVID_CURVE_COSINE : | ||
1122 : | 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)))); | ||
1123 : | } | ||
1124 : | } | ||
1125 : | }else{ | ||
1126 : | if (dbytes <= rc->alt_curve_low) { | ||
1127 : | dbytes2 = dbytes; | ||
1128 : | }else{ | ||
1129 : | switch(rc->param.alt_curve_type) { | ||
1130 : | case XVID_CURVE_SINE : | ||
1131 : | 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))); | ||
1132 : | break; | ||
1133 : | case XVID_CURVE_LINEAR : | ||
1134 : | 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); | ||
1135 : | break; | ||
1136 : | case XVID_CURVE_COSINE : | ||
1137 : | 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)))); | ||
1138 : | } | ||
1139 : | } | ||
1140 : | |||
1141 : | } | ||
1142 : | |||
1143 : | |||
1144 : | }else{ | ||
1145 : | if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { | ||
1146 : | dbytes2=((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_high / 100.0); | ||
1147 : | }else{ | ||
1148 : | dbytes2 = ((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_low / 100.0); | ||
1149 : | } | ||
1150 : | } | ||
1151 : | |||
1152 : | if (s->type == XVID_TYPE_BVOP) { | ||
1153 : | dbytes2 *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; | ||
1154 : | if (dbytes2 < rc->min_length[XVID_TYPE_BVOP-1]) | ||
1155 : | dbytes2 = rc->min_length[XVID_TYPE_BVOP-1]; | ||
1156 : | }else{ | ||
1157 : | if (dbytes2 < rc->min_length[XVID_TYPE_PVOP-1]) | ||
1158 : | dbytes2 = rc->min_length[XVID_TYPE_PVOP-1]; | ||
1159 : | } | ||
1160 : | total2 += dbytes2; | ||
1161 : | } | ||
1162 : | } | ||
1163 : | |||
1164 : | rc->curve_comp_scale = total1 / total2; | ||
1165 : | |||
1166 : | if (!rc->param.use_alt_curve) { | ||
1167 : | DPRINTF(XVID_DEBUG_RC, "middle frame size for asymmetric curve compression: %i\n", | ||
1168 : | (int)(rc->avg_length[XVID_TYPE_PVOP-1] * rc->curve_comp_scale)); | ||
1169 : | } | ||
1170 : | |||
1171 : | if (rc->param.use_alt_curve) { | ||
1172 : | int bonus_bias = rc->param.alt_curve_bonus_bias; | ||
1173 : | int oldquant = 1; | ||
1174 : | |||
1175 : | if (rc->param.alt_curve_use_auto_bonus_bias) | ||
1176 : | bonus_bias = rc->param.alt_curve_min_rel_qual; | ||
1177 : | |||
1178 : | rc->alt_curve_curve_bias_bonus = (total1 - total2) * (double)bonus_bias / 100.0 / (double)(rc->num_frames /* - credits_frames */ - rc->num_keyframes); | ||
1179 : | rc->curve_comp_scale = ((total1 - total2) * (1.0 - (double)bonus_bias / 100.0) + total2) / total2; | ||
1180 : | |||
1181 : | |||
1182 : | /* special info for alt curve: bias bonus and quantizer thresholds */ | ||
1183 : | |||
1184 : | DPRINTF(XVID_DEBUG_RC, "avg scaled framesize:%i\n", (int)rc->avg_length[XVID_TYPE_PVOP-1]); | ||
1185 : | DPRINTF(XVID_DEBUG_RC, "bias bonus:%i bytes\n", (int)rc->alt_curve_curve_bias_bonus); | ||
1186 : | |||
1187 : | for (i=1; i <= (int)(rc->alt_curve_high*2)+1; i++) { | ||
1188 : | double curve_temp, dbytes; | ||
1189 : | int newquant; | ||
1190 : | |||
1191 : | dbytes = i; | ||
1192 : | if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { | ||
1193 : | if (dbytes >= rc->alt_curve_high) { | ||
1194 : | curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev); | ||
1195 : | }else{ | ||
1196 : | switch(rc->param.alt_curve_type) | ||
1197 : | { | ||
1198 : | case XVID_CURVE_SINE : | ||
1199 : | 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))); | ||
1200 : | break; | ||
1201 : | case XVID_CURVE_LINEAR : | ||
1202 : | 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); | ||
1203 : | break; | ||
1204 : | case XVID_CURVE_COSINE : | ||
1205 : | 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)))); | ||
1206 : | } | ||
1207 : | } | ||
1208 : | }else{ | ||
1209 : | if (dbytes <= rc->alt_curve_low) { | ||
1210 : | curve_temp = dbytes; | ||
1211 : | }else{ | ||
1212 : | switch(rc->param.alt_curve_type) | ||
1213 : | { | ||
1214 : | case XVID_CURVE_SINE : | ||
1215 : | 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))); | ||
1216 : | break; | ||
1217 : | case XVID_CURVE_LINEAR : | ||
1218 : | 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); | ||
1219 : | break; | ||
1220 : | case XVID_CURVE_COSINE : | ||
1221 : | 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)))); | ||
1222 : | } | ||
1223 : | } | ||
1224 : | } | ||
1225 : | |||
1226 : | if (rc->movie_curve > 1.0) | ||
1227 : | dbytes *= rc->movie_curve; | ||
1228 : | |||
1229 : | newquant = (int)(dbytes * 2.0 / (curve_temp * rc->curve_comp_scale + rc->alt_curve_curve_bias_bonus)); | ||
1230 : | if (newquant > 1) { | ||
1231 : | if (newquant != oldquant) { | ||
1232 : | int percent = (int)((i - rc->avg_length[XVID_TYPE_PVOP-1]) * 100.0 / rc->avg_length[XVID_TYPE_PVOP-1]); | ||
1233 : | oldquant = newquant; | ||
1234 : | DPRINTF(XVID_DEBUG_RC, "quant:%i threshold at %i : %i percent\n", newquant, i, percent); | ||
1235 : | } | ||
1236 : | } | ||
1237 : | } | ||
1238 : | |||
1239 : | } | ||
1240 : | |||
1241 : | rc->overflow = 0; | ||
1242 : | rc->KFoverflow = 0; | ||
1243 : | rc->KFoverflow_partial = 0; | ||
1244 : | rc->KF_idx = 1; | ||
1245 : | } |
No admin address has been configured | ViewVC Help |
Powered by ViewVC 1.0.4 |