Parent Directory | Revision Log
Revision 1161 - (view) (download)
1 : | suxen_drol | 942 | /****************************************************************************** |
2 : | * | ||
3 : | edgomez | 1054 | * XviD Bit Rate Controller Library |
4 : | * - VBR 2 pass bitrate controller implementation - | ||
5 : | suxen_drol | 942 | * |
6 : | edgomez | 1054 | * 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 | 1054 | * 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 : | edgomez | 1054 | * 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 : | suxen_drol | 942 | * |
19 : | edgomez | 1054 | * 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 : | suxen_drol | 942 | * |
24 : | edgomez | 1054 | * 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 : | suxen_drol | 942 | * |
28 : | edgomez | 1161 | * $Id: plugin_2pass2.c,v 1.1.2.23 2003-10-01 23:23:01 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 : | #define DEFAULT_KEYFRAME_BOOST 0 | ||
44 : | #define DEFAULT_PAYBACK_METHOD XVID_PAYBACK_PROP | ||
45 : | #define DEFAULT_BITRATE_PAYBACK_DELAY 250 | ||
46 : | #define DEFAULT_CURVE_COMPRESSION_HIGH 0 | ||
47 : | #define DEFAULT_CURVE_COMPRESSION_LOW 0 | ||
48 : | #define DEFAULT_MAX_OVERFLOW_IMPROVEMENT 60 | ||
49 : | #define DEFAULT_MAX_OVERFLOW_DEGRADATION 60 | ||
50 : | suxen_drol | 942 | |
51 : | edgomez | 1042 | /* Keyframe settings */ |
52 : | #define DEFAULT_KFTRESHOLD 10 | ||
53 : | #define DEFAULT_KFREDUCTION 20 | ||
54 : | #define DEFAULT_MIN_KEY_INTERVAL 1 | ||
55 : | |||
56 : | /***************************************************************************** | ||
57 : | * Structures | ||
58 : | ****************************************************************************/ | ||
59 : | |||
60 : | /* Statistics */ | ||
61 : | suxen_drol | 942 | typedef struct { |
62 : | edgomez | 1064 | int type; /* first pass type */ |
63 : | int quant; /* first pass quant */ | ||
64 : | suxen_drol | 977 | int blks[3]; /* k,m,y blks */ |
65 : | edgomez | 1064 | int length; /* first pass length */ |
66 : | int scaled_length; /* scaled length */ | ||
67 : | int desired_length; /* desired length; calcuated during encoding */ | ||
68 : | suxen_drol | 1030 | |
69 : | edgomez | 1064 | int zone_mode; /* XVID_ZONE_xxx */ |
70 : | double weight; | ||
71 : | suxen_drol | 942 | } stat_t; |
72 : | |||
73 : | edgomez | 1042 | /* Context struct */ |
74 : | suxen_drol | 942 | typedef struct |
75 : | { | ||
76 : | edgomez | 1064 | xvid_plugin_2pass2_t param; |
77 : | suxen_drol | 942 | |
78 : | edgomez | 1064 | /* constant statistical data */ |
79 : | suxen_drol | 977 | int num_frames; |
80 : | edgomez | 1048 | int num_keyframes; |
81 : | uint64_t target; /* target filesize */ | ||
82 : | suxen_drol | 1030 | |
83 : | edgomez | 1048 | int count[3]; /* count of each frame types */ |
84 : | uint64_t tot_length[3]; /* total length of each frame types */ | ||
85 : | double avg_length[3]; /* avg */ | ||
86 : | int min_length[3]; /* min frame length of each frame types */ | ||
87 : | uint64_t tot_scaled_length[3]; /* total scaled length of each frame type */ | ||
88 : | int max_length; /* max frame size */ | ||
89 : | suxen_drol | 1030 | |
90 : | edgomez | 1048 | /* zone statistical data */ |
91 : | double avg_weight; /* average weight */ | ||
92 : | int64_t tot_quant; /* total length used by XVID_ZONE_QUANT zones */ | ||
93 : | suxen_drol | 1030 | |
94 : | suxen_drol | 942 | |
95 : | edgomez | 1048 | double curve_comp_scale; |
96 : | double movie_curve; | ||
97 : | suxen_drol | 942 | |
98 : | edgomez | 1048 | /* dynamic */ |
99 : | int * keyframe_locations; | ||
100 : | stat_t * stats; | ||
101 : | suxen_drol | 1030 | |
102 : | edgomez | 1048 | double quant_error[3][32]; |
103 : | int quant_count[32]; | ||
104 : | int last_quant[3]; | ||
105 : | |||
106 : | double curve_comp_error; | ||
107 : | int overflow; | ||
108 : | int KFoverflow; | ||
109 : | int KFoverflow_partial; | ||
110 : | int KF_idx; | ||
111 : | |||
112 : | double fq_error; | ||
113 : | suxen_drol | 942 | } rc_2pass2_t; |
114 : | |||
115 : | |||
116 : | edgomez | 1042 | /***************************************************************************** |
117 : | * Sub plugin functions prototypes | ||
118 : | ****************************************************************************/ | ||
119 : | suxen_drol | 942 | |
120 : | edgomez | 1042 | static int rc_2pass2_create(xvid_plg_create_t * create, rc_2pass2_t ** handle); |
121 : | static int rc_2pass2_before(rc_2pass2_t * rc, xvid_plg_data_t * data); | ||
122 : | static int rc_2pass2_after(rc_2pass2_t * rc, xvid_plg_data_t * data); | ||
123 : | static int rc_2pass2_destroy(rc_2pass2_t * rc, xvid_plg_destroy_t * destroy); | ||
124 : | suxen_drol | 942 | |
125 : | edgomez | 1042 | /***************************************************************************** |
126 : | * Plugin definition | ||
127 : | ****************************************************************************/ | ||
128 : | suxen_drol | 942 | |
129 : | edgomez | 1042 | int |
130 : | xvid_plugin_2pass2(void * handle, int opt, void * param1, void * param2) | ||
131 : | suxen_drol | 942 | { |
132 : | edgomez | 1064 | switch(opt) { |
133 : | case XVID_PLG_INFO : | ||
134 : | return 0; | ||
135 : | suxen_drol | 942 | |
136 : | edgomez | 1064 | case XVID_PLG_CREATE : |
137 : | return rc_2pass2_create((xvid_plg_create_t*)param1, param2); | ||
138 : | suxen_drol | 942 | |
139 : | edgomez | 1064 | case XVID_PLG_DESTROY : |
140 : | return rc_2pass2_destroy((rc_2pass2_t*)handle, (xvid_plg_destroy_t*)param1); | ||
141 : | suxen_drol | 942 | |
142 : | edgomez | 1064 | case XVID_PLG_BEFORE : |
143 : | return rc_2pass2_before((rc_2pass2_t*)handle, (xvid_plg_data_t*)param1); | ||
144 : | suxen_drol | 942 | |
145 : | edgomez | 1064 | case XVID_PLG_AFTER : |
146 : | return rc_2pass2_after((rc_2pass2_t*)handle, (xvid_plg_data_t*)param1); | ||
147 : | } | ||
148 : | edgomez | 1037 | |
149 : | edgomez | 1064 | return XVID_ERR_FAIL; |
150 : | suxen_drol | 977 | } |
151 : | |||
152 : | edgomez | 1042 | /***************************************************************************** |
153 : | * Sub plugin functions definitions | ||
154 : | ****************************************************************************/ | ||
155 : | suxen_drol | 977 | |
156 : | edgomez | 1042 | /* First a few local helping function prototypes */ |
157 : | static int det_stats_length(rc_2pass2_t * rc, char * filename); | ||
158 : | static int load_stats(rc_2pass2_t *rc, char * filename); | ||
159 : | static void zone_process(rc_2pass2_t *rc, const xvid_plg_create_t * create); | ||
160 : | static void internal_scale(rc_2pass2_t *rc); | ||
161 : | static void pre_process0(rc_2pass2_t * rc); | ||
162 : | static void pre_process1(rc_2pass2_t * rc); | ||
163 : | suxen_drol | 977 | |
164 : | edgomez | 1042 | /*---------------------------------------------------------------------------- |
165 : | *--------------------------------------------------------------------------*/ | ||
166 : | suxen_drol | 942 | |
167 : | edgomez | 1042 | static int |
168 : | rc_2pass2_create(xvid_plg_create_t * create, rc_2pass2_t **handle) | ||
169 : | suxen_drol | 942 | { |
170 : | edgomez | 1064 | xvid_plugin_2pass2_t * param = (xvid_plugin_2pass2_t *)create->param; |
171 : | rc_2pass2_t * rc; | ||
172 : | int i; | ||
173 : | suxen_drol | 942 | |
174 : | edgomez | 1064 | rc = malloc(sizeof(rc_2pass2_t)); |
175 : | edgomez | 1161 | if (rc == NULL) |
176 : | edgomez | 1064 | return XVID_ERR_MEMORY; |
177 : | suxen_drol | 942 | |
178 : | edgomez | 1064 | rc->param = *param; |
179 : | suxen_drol | 942 | |
180 : | edgomez | 1048 | /* |
181 : | * Initialize all defaults | ||
182 : | */ | ||
183 : | edgomez | 1042 | #define _INIT(a, b) if((a) <= 0) (a) = (b) |
184 : | edgomez | 1064 | /* Let's set our defaults if needed */ |
185 : | edgomez | 1042 | _INIT(rc->param.keyframe_boost, DEFAULT_KEYFRAME_BOOST); |
186 : | _INIT(rc->param.payback_method, DEFAULT_PAYBACK_METHOD); | ||
187 : | _INIT(rc->param.bitrate_payback_delay, DEFAULT_BITRATE_PAYBACK_DELAY); | ||
188 : | edgomez | 1064 | _INIT(rc->param.curve_compression_high, DEFAULT_CURVE_COMPRESSION_HIGH); |
189 : | _INIT(rc->param.curve_compression_low, DEFAULT_CURVE_COMPRESSION_LOW); | ||
190 : | _INIT(rc->param.max_overflow_improvement, DEFAULT_MAX_OVERFLOW_IMPROVEMENT); | ||
191 : | _INIT(rc->param.max_overflow_degradation, DEFAULT_MAX_OVERFLOW_DEGRADATION); | ||
192 : | suxen_drol | 942 | |
193 : | edgomez | 1064 | /* Keyframe settings */ |
194 : | edgomez | 1042 | _INIT(rc->param.kftreshold, DEFAULT_KFTRESHOLD); |
195 : | edgomez | 1064 | _INIT(rc->param.kfreduction, DEFAULT_KFREDUCTION); |
196 : | _INIT(rc->param.min_key_interval, DEFAULT_MIN_KEY_INTERVAL); | ||
197 : | edgomez | 1042 | #undef _INIT |
198 : | suxen_drol | 942 | |
199 : | edgomez | 1048 | /* Initialize some stuff to zero */ |
200 : | for(i=0; i<32; i++) rc->quant_count[i] = 0; | ||
201 : | |||
202 : | for(i=0; i<3; i++) { | ||
203 : | int j; | ||
204 : | for (j=0; j<32; j++) | ||
205 : | rc->quant_error[i][j] = 0; | ||
206 : | } | ||
207 : | |||
208 : | for (i=0; i<3; i++) | ||
209 : | rc->last_quant[i] = 0; | ||
210 : | |||
211 : | rc->fq_error = 0; | ||
212 : | |||
213 : | edgomez | 1042 | /* Count frames in the stats file */ |
214 : | edgomez | 1048 | if (!det_stats_length(rc, param->filename)) { |
215 : | DPRINTF(XVID_DEBUG_RC,"ERROR: fopen %s failed\n", param->filename); | ||
216 : | free(rc); | ||
217 : | return XVID_ERR_FAIL; | ||
218 : | } | ||
219 : | suxen_drol | 942 | |
220 : | edgomez | 1064 | /* Allocate the stats' memory */ |
221 : | edgomez | 1042 | if ((rc->stats = malloc(rc->num_frames * sizeof(stat_t))) == NULL) { |
222 : | edgomez | 1064 | free(rc); |
223 : | return XVID_ERR_MEMORY; | ||
224 : | } | ||
225 : | suxen_drol | 942 | |
226 : | edgomez | 1064 | /* |
227 : | edgomez | 1042 | * Allocate keyframes location's memory |
228 : | * PS: see comment in pre_process0 for the +1 location requirement | ||
229 : | edgomez | 1037 | */ |
230 : | edgomez | 1048 | rc->keyframe_locations = malloc((rc->num_keyframes + 1) * sizeof(int)); |
231 : | if (rc->keyframe_locations == NULL) { | ||
232 : | free(rc->stats); | ||
233 : | free(rc); | ||
234 : | return XVID_ERR_MEMORY; | ||
235 : | } | ||
236 : | suxen_drol | 942 | |
237 : | edgomez | 1048 | if (!load_stats(rc, param->filename)) { |
238 : | DPRINTF(XVID_DEBUG_RC,"ERROR: fopen %s failed\n", param->filename); | ||
239 : | free(rc->keyframe_locations); | ||
240 : | free(rc->stats); | ||
241 : | free(rc); | ||
242 : | return XVID_ERR_FAIL; | ||
243 : | } | ||
244 : | suxen_drol | 942 | |
245 : | edgomez | 1048 | /* Compute the target filesize */ |
246 : | edgomez | 1064 | if (rc->param.bitrate<0) { |
247 : | /* if negative, bitrate equals the target (in kbytes) */ | ||
248 : | rc->target = (-rc->param.bitrate) * 1024; | ||
249 : | } else if (rc->num_frames < create->fbase/create->fincr) { | ||
250 : | edgomez | 1048 | /* Source sequence is less than 1s long, we do as if it was 1s long */ |
251 : | rc->target = rc->param.bitrate / 8; | ||
252 : | edgomez | 1042 | } else { |
253 : | edgomez | 1048 | /* Target filesize = bitrate/8 * numframes / framerate */ |
254 : | edgomez | 1161 | rc->target = |
255 : | edgomez | 1048 | ((uint64_t)rc->param.bitrate * (uint64_t)rc->num_frames * \ |
256 : | (uint64_t)create->fincr) / \ | ||
257 : | edgomez | 1040 | ((uint64_t)create->fbase * 8); |
258 : | suxen_drol | 977 | } |
259 : | suxen_drol | 1030 | |
260 : | edgomez | 1048 | DPRINTF(XVID_DEBUG_RC, "Frame rate: %d/%d (%ffps)\n", |
261 : | create->fbase, create->fincr, | ||
262 : | (double)create->fbase/(double)create->fincr); | ||
263 : | DPRINTF(XVID_DEBUG_RC, "Number of frames: %d\n", rc->num_frames); | ||
264 : | edgomez | 1040 | DPRINTF(XVID_DEBUG_RC, "Target bitrate: %ld\n", rc->param.bitrate); |
265 : | DPRINTF(XVID_DEBUG_RC, "Target filesize: %lld\n", rc->target); | ||
266 : | suxen_drol | 1032 | |
267 : | edgomez | 1048 | /* Compensate the average frame overhead caused by the container */ |
268 : | edgomez | 1041 | rc->target -= rc->num_frames*rc->param.container_frame_overhead; |
269 : | DPRINTF(XVID_DEBUG_RC, "Container Frame overhead: %d\n", rc->param.container_frame_overhead); | ||
270 : | DPRINTF(XVID_DEBUG_RC, "Target filesize (after container compensation): %lld\n", rc->target); | ||
271 : | suxen_drol | 977 | |
272 : | edgomez | 1161 | /* |
273 : | edgomez | 1048 | * First data pre processing: |
274 : | * - finds the minimum frame length for each frame type during 1st pass. | ||
275 : | * rc->min_size[] | ||
276 : | * - determines the maximum frame length observed (no frame type distinction). | ||
277 : | * rc->max_size | ||
278 : | * - count how many times each frame type has been used. | ||
279 : | * rc->count[] | ||
280 : | * - total bytes used per frame type | ||
281 : | * rc->total[] | ||
282 : | * - store keyframe location | ||
283 : | * rc->keyframe_locations[] | ||
284 : | */ | ||
285 : | suxen_drol | 977 | pre_process0(rc); |
286 : | edgomez | 1036 | |
287 : | edgomez | 1048 | /* |
288 : | * When bitrate is not given it means it has been scaled by an external | ||
289 : | * application | ||
290 : | */ | ||
291 : | suxen_drol | 977 | if (rc->param.bitrate) { |
292 : | edgomez | 1048 | /* Apply zone settings */ |
293 : | zone_process(rc, create); | ||
294 : | /* Perform curve scaling */ | ||
295 : | suxen_drol | 977 | internal_scale(rc); |
296 : | edgomez | 1048 | } else { |
297 : | /* External scaling -- zones are ignored */ | ||
298 : | for (i=0;i<rc->num_frames;i++) { | ||
299 : | rc->stats[i].zone_mode = XVID_ZONE_WEIGHT; | ||
300 : | rc->stats[i].weight = 1.0; | ||
301 : | } | ||
302 : | rc->avg_weight = 1.0; | ||
303 : | rc->tot_quant = 0; | ||
304 : | } | ||
305 : | |||
306 : | suxen_drol | 1030 | pre_process1(rc); |
307 : | |||
308 : | edgomez | 1048 | *handle = rc; |
309 : | suxen_drol | 942 | return(0); |
310 : | } | ||
311 : | |||
312 : | edgomez | 1042 | /*---------------------------------------------------------------------------- |
313 : | *--------------------------------------------------------------------------*/ | ||
314 : | suxen_drol | 942 | |
315 : | edgomez | 1042 | static int |
316 : | rc_2pass2_destroy(rc_2pass2_t * rc, xvid_plg_destroy_t * destroy) | ||
317 : | suxen_drol | 942 | { |
318 : | edgomez | 1064 | free(rc->keyframe_locations); |
319 : | free(rc->stats); | ||
320 : | suxen_drol | 942 | free(rc); |
321 : | return(0); | ||
322 : | } | ||
323 : | |||
324 : | edgomez | 1042 | /*---------------------------------------------------------------------------- |
325 : | *--------------------------------------------------------------------------*/ | ||
326 : | suxen_drol | 942 | |
327 : | edgomez | 1042 | static int |
328 : | rc_2pass2_before(rc_2pass2_t * rc, xvid_plg_data_t * data) | ||
329 : | suxen_drol | 942 | { |
330 : | edgomez | 1048 | stat_t * s = &rc->stats[data->frame_num]; |
331 : | int overflow; | ||
332 : | int desired; | ||
333 : | double dbytes; | ||
334 : | double curve_temp; | ||
335 : | double scaled_quant; | ||
336 : | int capped_to_max_framesize = 0; | ||
337 : | suxen_drol | 942 | |
338 : | edgomez | 1037 | /* |
339 : | * This function is quite long but easy to understand. In order to simplify | ||
340 : | * the code path (a bit), we treat 3 cases that can return immediatly. | ||
341 : | */ | ||
342 : | suxen_drol | 942 | |
343 : | edgomez | 1037 | /* First case: Another plugin has already set a quantizer */ |
344 : | edgomez | 1064 | if (data->quant > 0) |
345 : | edgomez | 1037 | return(0); |
346 : | suxen_drol | 942 | |
347 : | edgomez | 1037 | /* Second case: We are in a Quant zone */ |
348 : | if (s->zone_mode == XVID_ZONE_QUANT) { | ||
349 : | rc->fq_error += s->weight; | ||
350 : | data->quant = (int)rc->fq_error; | ||
351 : | rc->fq_error -= data->quant; | ||
352 : | edgomez | 1064 | |
353 : | edgomez | 1037 | s->desired_length = s->length; |
354 : | suxen_drol | 1032 | |
355 : | edgomez | 1037 | return(0); |
356 : | } | ||
357 : | suxen_drol | 977 | |
358 : | edgomez | 1037 | /* Third case: insufficent stats data */ |
359 : | if (data->frame_num >= rc->num_frames) | ||
360 : | return 0; | ||
361 : | suxen_drol | 942 | |
362 : | edgomez | 1037 | /* XXX: why by 8 */ |
363 : | overflow = rc->overflow / 8; | ||
364 : | suxen_drol | 942 | |
365 : | edgomez | 1037 | /* |
366 : | * The rc->overflow field represents the overflow in current scene (between two | ||
367 : | edgomez | 1042 | * IFrames) so we must not forget to reset it if we are entering a new scene |
368 : | edgomez | 1037 | */ |
369 : | edgomez | 1046 | if (s->type == XVID_TYPE_IVOP) |
370 : | edgomez | 1037 | overflow = 0; |
371 : | suxen_drol | 942 | |
372 : | edgomez | 1037 | desired = s->scaled_length; |
373 : | suxen_drol | 942 | |
374 : | edgomez | 1037 | dbytes = desired; |
375 : | edgomez | 1046 | if (s->type == XVID_TYPE_IVOP) |
376 : | edgomez | 1037 | dbytes += desired * rc->param.keyframe_boost / 100; |
377 : | dbytes /= rc->movie_curve; | ||
378 : | suxen_drol | 942 | |
379 : | edgomez | 1037 | /* |
380 : | * Apply user's choosen Payback method. Payback helps bitrate to follow the | ||
381 : | * scaled curve "paying back" past errors in curve previsions. | ||
382 : | */ | ||
383 : | if (rc->param.payback_method == XVID_PAYBACK_BIAS) { | ||
384 : | edgomez | 1048 | desired = (int)(rc->curve_comp_error / rc->param.bitrate_payback_delay); |
385 : | edgomez | 1042 | } else { |
386 : | edgomez | 1037 | desired = (int)(rc->curve_comp_error * dbytes / |
387 : | edgomez | 1051 | rc->avg_length[s->type-1] / rc->param.bitrate_payback_delay); |
388 : | suxen_drol | 942 | |
389 : | edgomez | 1051 | if (labs(desired) > fabs(rc->curve_comp_error)) |
390 : | edgomez | 1037 | desired = (int)rc->curve_comp_error; |
391 : | } | ||
392 : | suxen_drol | 942 | |
393 : | edgomez | 1037 | rc->curve_comp_error -= desired; |
394 : | suxen_drol | 942 | |
395 : | edgomez | 1037 | /* XXX: warning */ |
396 : | curve_temp = 0; | ||
397 : | suxen_drol | 942 | |
398 : | edgomez | 1046 | if ((rc->param.curve_compression_high + rc->param.curve_compression_low) && s->type != XVID_TYPE_IVOP) { |
399 : | suxen_drol | 942 | |
400 : | edgomez | 1037 | curve_temp = rc->curve_comp_scale; |
401 : | edgomez | 1051 | if (dbytes > rc->avg_length[s->type-1]) { |
402 : | curve_temp *= ((double)dbytes + (rc->avg_length[s->type-1] - dbytes) * rc->param.curve_compression_high / 100.0); | ||
403 : | edgomez | 1037 | } else { |
404 : | edgomez | 1051 | curve_temp *= ((double)dbytes + (rc->avg_length[s->type-1] - dbytes) * rc->param.curve_compression_low / 100.0); |
405 : | edgomez | 1037 | } |
406 : | suxen_drol | 942 | |
407 : | edgomez | 1037 | desired += (int)curve_temp; |
408 : | rc->curve_comp_error += curve_temp - (int)curve_temp; | ||
409 : | } else { | ||
410 : | desired += (int)dbytes; | ||
411 : | rc->curve_comp_error += dbytes - (int)dbytes; | ||
412 : | } | ||
413 : | suxen_drol | 942 | |
414 : | edgomez | 1037 | /* |
415 : | * We can't do bigger frames than first pass, this would be stupid as first | ||
416 : | * pass is quant=2 and that reaching quant=1 is not worth it. We would lose | ||
417 : | * many bytes and we would not not gain much quality. | ||
418 : | */ | ||
419 : | if (desired > s->length) { | ||
420 : | rc->curve_comp_error += desired - s->length; | ||
421 : | desired = s->length; | ||
422 : | edgomez | 1042 | } else { |
423 : | edgomez | 1037 | if (desired < rc->min_length[s->type-1]) { |
424 : | if (s->type == XVID_TYPE_IVOP){ | ||
425 : | rc->curve_comp_error -= rc->min_length[XVID_TYPE_IVOP-1] - desired; | ||
426 : | } | ||
427 : | desired = rc->min_length[s->type-1]; | ||
428 : | } | ||
429 : | } | ||
430 : | suxen_drol | 942 | |
431 : | edgomez | 1037 | s->desired_length = desired; |
432 : | suxen_drol | 942 | |
433 : | edgomez | 1048 | /* |
434 : | * if this keyframe is too close to the next, reduce it's byte allotment | ||
435 : | * XXX: why do we do this after setting the desired length ? | ||
436 : | */ | ||
437 : | |||
438 : | edgomez | 1037 | if (s->type == XVID_TYPE_IVOP) { |
439 : | int KFdistance = rc->keyframe_locations[rc->KF_idx] - rc->keyframe_locations[rc->KF_idx - 1]; | ||
440 : | suxen_drol | 942 | |
441 : | edgomez | 1037 | if (KFdistance < rc->param.kftreshold) { |
442 : | edgomez | 1064 | |
443 : | edgomez | 1042 | KFdistance -= rc->param.min_key_interval; |
444 : | suxen_drol | 942 | |
445 : | edgomez | 1037 | if (KFdistance >= 0) { |
446 : | int KF_min_size; | ||
447 : | suxen_drol | 942 | |
448 : | edgomez | 1037 | KF_min_size = desired * (100 - rc->param.kfreduction) / 100; |
449 : | if (KF_min_size < 1) | ||
450 : | KF_min_size = 1; | ||
451 : | suxen_drol | 942 | |
452 : | edgomez | 1037 | desired = KF_min_size + (desired - KF_min_size) * KFdistance / |
453 : | (rc->param.kftreshold - rc->param.min_key_interval); | ||
454 : | suxen_drol | 942 | |
455 : | edgomez | 1037 | if (desired < 1) |
456 : | desired = 1; | ||
457 : | } | ||
458 : | } | ||
459 : | } | ||
460 : | suxen_drol | 942 | |
461 : | edgomez | 1051 | /* |
462 : | * The "sens commun" would force us to use rc->avg_length[s->type-1] but | ||
463 : | * even VFW code uses the pframe average length. Note that this length is | ||
464 : | * used with desired which represents bframes _and_ pframes length. | ||
465 : | * | ||
466 : | edgomez | 1161 | * XXX: why are we using the avg pframe length for all frame types ? |
467 : | edgomez | 1051 | */ |
468 : | edgomez | 1037 | overflow = (int)((double)overflow * desired / rc->avg_length[XVID_TYPE_PVOP-1]); |
469 : | suxen_drol | 942 | |
470 : | edgomez | 1037 | /* Reign in overflow with huge frames */ |
471 : | edgomez | 1046 | if (labs(overflow) > labs(rc->overflow)) |
472 : | edgomez | 1037 | overflow = rc->overflow; |
473 : | suxen_drol | 942 | |
474 : | edgomez | 1037 | /* Make sure overflow doesn't run away */ |
475 : | if (overflow > desired * rc->param.max_overflow_improvement / 100) { | ||
476 : | desired += (overflow <= desired) ? desired * rc->param.max_overflow_improvement / 100 : | ||
477 : | overflow * rc->param.max_overflow_improvement / 100; | ||
478 : | } else if (overflow < desired * rc->param.max_overflow_degradation / -100){ | ||
479 : | desired += desired * rc->param.max_overflow_degradation / -100; | ||
480 : | } else { | ||
481 : | desired += overflow; | ||
482 : | } | ||
483 : | suxen_drol | 942 | |
484 : | edgomez | 1037 | /* Make sure we are not higher than desired frame size */ |
485 : | if (desired > rc->max_length) { | ||
486 : | capped_to_max_framesize = 1; | ||
487 : | desired = rc->max_length; | ||
488 : | edgomez | 1040 | DPRINTF(XVID_DEBUG_RC,"[%i] Capped to maximum frame size\n", |
489 : | data->frame_num); | ||
490 : | edgomez | 1037 | } |
491 : | suxen_drol | 942 | |
492 : | edgomez | 1037 | /* Make sure to not scale below the minimum framesize */ |
493 : | edgomez | 1040 | if (desired < rc->min_length[s->type-1]) { |
494 : | edgomez | 1037 | desired = rc->min_length[s->type-1]; |
495 : | edgomez | 1040 | DPRINTF(XVID_DEBUG_RC,"[%i] Capped to minimum frame size\n", |
496 : | data->frame_num); | ||
497 : | } | ||
498 : | suxen_drol | 942 | |
499 : | edgomez | 1037 | /* |
500 : | * Don't laugh at this very 'simple' quant<->filesize relationship, it | ||
501 : | * proves to be acurate enough for our algorithm | ||
502 : | */ | ||
503 : | edgomez | 1048 | scaled_quant = (double)s->quant*(double)s->length/(double)desired; |
504 : | suxen_drol | 942 | |
505 : | edgomez | 1048 | /* |
506 : | * Quantizer has been scaled using floating point operations/results, we | ||
507 : | * must cast it to integer | ||
508 : | */ | ||
509 : | data->quant = (int)scaled_quant; | ||
510 : | |||
511 : | edgomez | 1037 | /* Let's clip the computed quantizer, if needed */ |
512 : | if (data->quant < 1) { | ||
513 : | data->quant = 1; | ||
514 : | } else if (data->quant > 31) { | ||
515 : | data->quant = 31; | ||
516 : | } else if (s->type != XVID_TYPE_IVOP) { | ||
517 : | suxen_drol | 942 | |
518 : | edgomez | 1037 | /* |
519 : | edgomez | 1048 | * The frame quantizer has not been clipped, this appears to be a good |
520 : | * computed quantizer, do not loose quantizer decimal part that we | ||
521 : | * accumulate for later reuse when its sum represents a complete unit. | ||
522 : | edgomez | 1037 | */ |
523 : | edgomez | 1048 | rc->quant_error[s->type-1][data->quant] += scaled_quant - (double)data->quant; |
524 : | suxen_drol | 942 | |
525 : | edgomez | 1048 | if (rc->quant_error[s->type-1][data->quant] >= 1.0) { |
526 : | rc->quant_error[s->type-1][data->quant] -= 1.0; | ||
527 : | data->quant++; | ||
528 : | } else if (rc->quant_error[s->type-1][data->quant] <= -1.0) { | ||
529 : | rc->quant_error[s->type-1][data->quant] += 1.0; | ||
530 : | data->quant--; | ||
531 : | } | ||
532 : | suxen_drol | 942 | |
533 : | edgomez | 1037 | } |
534 : | suxen_drol | 942 | |
535 : | edgomez | 1037 | /* |
536 : | * Now we have a computed quant that is in the right quante range, with a | ||
537 : | * possible +1 correction due to cumulated error. We can now safely clip | ||
538 : | * the quantizer again with user's quant ranges. "Safely" means the Rate | ||
539 : | * Control could learn more about this quantizer, this knowledge is useful | ||
540 : | * for future frames even if it this quantizer won't be really used atm, | ||
541 : | * that's why we don't perform this clipping earlier. | ||
542 : | */ | ||
543 : | if (data->quant < data->min_quant[s->type-1]) { | ||
544 : | data->quant = data->min_quant[s->type-1]; | ||
545 : | } else if (data->quant > data->max_quant[s->type-1]) { | ||
546 : | data->quant = data->max_quant[s->type-1]; | ||
547 : | } | ||
548 : | suxen_drol | 942 | |
549 : | edgomez | 1037 | /* |
550 : | * To avoid big quality jumps from frame to frame, we apply a "security" | ||
551 : | * rule that makes |last_quant - new_quant| <= 2. This rule only applies | ||
552 : | * to predicted frames (P and B) | ||
553 : | */ | ||
554 : | if (s->type != XVID_TYPE_IVOP && rc->last_quant[s->type-1] && capped_to_max_framesize == 0) { | ||
555 : | suxen_drol | 942 | |
556 : | edgomez | 1037 | if (data->quant > rc->last_quant[s->type-1] + 2) { |
557 : | data->quant = rc->last_quant[s->type-1] + 2; | ||
558 : | edgomez | 1040 | DPRINTF(XVID_DEBUG_RC, |
559 : | "[%i] p/b-frame quantizer prevented from rising too steeply\n", | ||
560 : | data->frame_num); | ||
561 : | edgomez | 1037 | } |
562 : | if (data->quant < rc->last_quant[s->type-1] - 2) { | ||
563 : | data->quant = rc->last_quant[s->type-1] - 2; | ||
564 : | edgomez | 1040 | DPRINTF(XVID_DEBUG_RC, |
565 : | "[%i] p/b-frame quantizer prevented from falling too steeply\n", | ||
566 : | data->frame_num); | ||
567 : | edgomez | 1037 | } |
568 : | } | ||
569 : | suxen_drol | 1030 | |
570 : | edgomez | 1037 | /* |
571 : | * We don't want to pollute the RC history results when our computed quant | ||
572 : | * has been computed from a capped frame size | ||
573 : | */ | ||
574 : | edgomez | 1046 | if (capped_to_max_framesize == 0) |
575 : | edgomez | 1037 | rc->last_quant[s->type-1] = data->quant; |
576 : | suxen_drol | 1030 | |
577 : | edgomez | 1050 | /* Force frame type */ |
578 : | data->type = s->type; | ||
579 : | |||
580 : | edgomez | 1037 | return 0; |
581 : | suxen_drol | 942 | } |
582 : | |||
583 : | edgomez | 1042 | /*---------------------------------------------------------------------------- |
584 : | *--------------------------------------------------------------------------*/ | ||
585 : | suxen_drol | 942 | |
586 : | edgomez | 1042 | static int |
587 : | rc_2pass2_after(rc_2pass2_t * rc, xvid_plg_data_t * data) | ||
588 : | suxen_drol | 942 | { |
589 : | edgomez | 1043 | const char frame_type[4] = { 'i', 'p', 'b', 's'}; |
590 : | stat_t * s = &rc->stats[data->frame_num]; | ||
591 : | suxen_drol | 942 | |
592 : | edgomez | 1037 | /* Insufficent stats data */ |
593 : | edgomez | 1064 | if (data->frame_num >= rc->num_frames) |
594 : | return 0; | ||
595 : | suxen_drol | 942 | |
596 : | edgomez | 1064 | rc->quant_count[data->quant]++; |
597 : | suxen_drol | 942 | |
598 : | edgomez | 1064 | if (data->type == XVID_TYPE_IVOP) { |
599 : | int kfdiff = (rc->keyframe_locations[rc->KF_idx] - rc->keyframe_locations[rc->KF_idx - 1]); | ||
600 : | suxen_drol | 942 | |
601 : | edgomez | 1064 | rc->overflow += rc->KFoverflow; |
602 : | rc->KFoverflow = s->desired_length - data->length; | ||
603 : | |||
604 : | if (kfdiff > 1) { /* non-consecutive keyframes */ | ||
605 : | rc->KFoverflow_partial = rc->KFoverflow / (kfdiff - 1); | ||
606 : | }else{ /* consecutive keyframes */ | ||
607 : | suxen_drol | 942 | rc->overflow += rc->KFoverflow; |
608 : | rc->KFoverflow = 0; | ||
609 : | rc->KFoverflow_partial = 0; | ||
610 : | edgomez | 1064 | } |
611 : | rc->KF_idx++; | ||
612 : | } else { | ||
613 : | /* distribute part of the keyframe overflow */ | ||
614 : | rc->overflow += s->desired_length - data->length + rc->KFoverflow_partial; | ||
615 : | rc->KFoverflow -= rc->KFoverflow_partial; | ||
616 : | } | ||
617 : | suxen_drol | 942 | |
618 : | edgomez | 1048 | DPRINTF(XVID_DEBUG_RC, "[%i] type:%c quant:%i stats1:%i scaled:%i actual:%i desired:%d overflow:%i\n", |
619 : | edgomez | 1042 | data->frame_num, |
620 : | edgomez | 1043 | frame_type[data->type-1], |
621 : | edgomez | 1042 | data->quant, |
622 : | s->length, | ||
623 : | s->scaled_length, | ||
624 : | data->length, | ||
625 : | edgomez | 1048 | s->desired_length, |
626 : | edgomez | 1042 | rc->overflow); |
627 : | suxen_drol | 942 | |
628 : | edgomez | 1064 | return(0); |
629 : | suxen_drol | 942 | } |
630 : | |||
631 : | edgomez | 1042 | /***************************************************************************** |
632 : | * Helper functions definition | ||
633 : | ****************************************************************************/ | ||
634 : | suxen_drol | 942 | |
635 : | edgomez | 1042 | #define BUF_SZ 1024 |
636 : | #define MAX_COLS 5 | ||
637 : | suxen_drol | 942 | |
638 : | edgomez | 1042 | /* open stats file, and count num frames */ |
639 : | static int | ||
640 : | det_stats_length(rc_2pass2_t * rc, char * filename) | ||
641 : | suxen_drol | 942 | { |
642 : | edgomez | 1064 | FILE * f; |
643 : | int n, ignore; | ||
644 : | char type; | ||
645 : | edgomez | 1042 | |
646 : | edgomez | 1064 | rc->num_frames = 0; |
647 : | rc->num_keyframes = 0; | ||
648 : | edgomez | 1042 | |
649 : | edgomez | 1064 | if ((f = fopen(filename, "rt")) == NULL) |
650 : | return 0; | ||
651 : | suxen_drol | 942 | |
652 : | edgomez | 1064 | while((n = fscanf(f, "%c %d %d %d %d %d %d\n", |
653 : | &type, &ignore, &ignore, &ignore, &ignore, &ignore, &ignore)) != EOF) { | ||
654 : | if (type == 'i') { | ||
655 : | rc->num_frames++; | ||
656 : | rc->num_keyframes++; | ||
657 : | }else if (type == 'p' || type == 'b' || type == 's') { | ||
658 : | rc->num_frames++; | ||
659 : | } | ||
660 : | } | ||
661 : | suxen_drol | 942 | |
662 : | edgomez | 1064 | fclose(f); |
663 : | suxen_drol | 942 | |
664 : | edgomez | 1064 | return 1; |
665 : | edgomez | 1042 | } |
666 : | suxen_drol | 942 | |
667 : | edgomez | 1042 | /* open stats file(s) and read into rc->stats array */ |
668 : | |||
669 : | static int | ||
670 : | load_stats(rc_2pass2_t *rc, char * filename) | ||
671 : | { | ||
672 : | edgomez | 1064 | FILE * f; |
673 : | int i, not_scaled; | ||
674 : | edgomez | 1042 | |
675 : | edgomez | 1064 | |
676 : | if ((f = fopen(filename, "rt"))==NULL) | ||
677 : | return 0; | ||
678 : | |||
679 : | i = 0; | ||
680 : | edgomez | 1042 | not_scaled = 0; |
681 : | edgomez | 1064 | while(i < rc->num_frames) { |
682 : | stat_t * s = &rc->stats[i]; | ||
683 : | int n; | ||
684 : | char type; | ||
685 : | edgomez | 1042 | |
686 : | s->scaled_length = 0; | ||
687 : | edgomez | 1064 | 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); |
688 : | if (n == EOF) break; | ||
689 : | edgomez | 1042 | if (n < 7) { |
690 : | not_scaled = 1; | ||
691 : | } | ||
692 : | |||
693 : | edgomez | 1064 | if (type == 'i') { |
694 : | s->type = XVID_TYPE_IVOP; | ||
695 : | }else if (type == 'p' || type == 's') { | ||
696 : | s->type = XVID_TYPE_PVOP; | ||
697 : | }else if (type == 'b') { | ||
698 : | s->type = XVID_TYPE_BVOP; | ||
699 : | }else{ /* unknown type */ | ||
700 : | DPRINTF(XVID_DEBUG_RC, "WARNING: unknown stats frame type, assuming pvop\n"); | ||
701 : | s->type = XVID_TYPE_PVOP; | ||
702 : | } | ||
703 : | edgomez | 1042 | |
704 : | edgomez | 1064 | i++; |
705 : | } | ||
706 : | suxen_drol | 942 | |
707 : | edgomez | 1064 | rc->num_frames = i; |
708 : | edgomez | 1042 | |
709 : | fclose(f); | ||
710 : | |||
711 : | edgomez | 1064 | return 1; |
712 : | suxen_drol | 942 | } |
713 : | edgomez | 1042 | |
714 : | #if 0 | ||
715 : | static void print_stats(rc_2pass2_t * rc) | ||
716 : | { | ||
717 : | edgomez | 1064 | int i; |
718 : | DPRINTF(XVID_DEBUG_RC, "type quant length scaled_length\n"); | ||
719 : | edgomez | 1042 | for (i = 0; i < rc->num_frames; i++) { |
720 : | edgomez | 1064 | stat_t * s = &rc->stats[i]; |
721 : | DPRINTF(XVID_DEBUG_RC, "%d %d %d %d\n", s->type, s->quant, s->length, s->scaled_length); | ||
722 : | } | ||
723 : | edgomez | 1042 | } |
724 : | #endif | ||
725 : | |||
726 : | edgomez | 1161 | /* pre-process the statistics data |
727 : | edgomez | 1064 | - for each type, count, tot_length, min_length, max_length |
728 : | - set keyframes_locations | ||
729 : | edgomez | 1042 | */ |
730 : | |||
731 : | static void | ||
732 : | pre_process0(rc_2pass2_t * rc) | ||
733 : | { | ||
734 : | edgomez | 1064 | int i,j; |
735 : | edgomez | 1042 | |
736 : | edgomez | 1048 | /* |
737 : | * *rc fields initialization | ||
738 : | * NB: INT_MAX and INT_MIN are used in order to be immediately replaced | ||
739 : | * with real values of the 1pass | ||
740 : | */ | ||
741 : | edgomez | 1064 | for (i=0; i<3; i++) { |
742 : | edgomez | 1048 | rc->count[i]=0; |
743 : | rc->tot_length[i] = 0; | ||
744 : | edgomez | 1042 | rc->min_length[i] = INT_MAX; |
745 : | edgomez | 1064 | } |
746 : | edgomez | 1042 | |
747 : | rc->max_length = INT_MIN; | ||
748 : | |||
749 : | edgomez | 1048 | /* |
750 : | * Loop through all frames and find/compute all the stuff this function | ||
751 : | * is supposed to do | ||
752 : | */ | ||
753 : | for (i=j=0; i<rc->num_frames; i++) { | ||
754 : | stat_t * s = &rc->stats[i]; | ||
755 : | edgomez | 1042 | |
756 : | edgomez | 1048 | rc->count[s->type-1]++; |
757 : | rc->tot_length[s->type-1] += s->length; | ||
758 : | edgomez | 1042 | |
759 : | edgomez | 1048 | if (s->length < rc->min_length[s->type-1]) { |
760 : | rc->min_length[s->type-1] = s->length; | ||
761 : | } | ||
762 : | edgomez | 1042 | |
763 : | edgomez | 1048 | if (s->length > rc->max_length) { |
764 : | rc->max_length = s->length; | ||
765 : | } | ||
766 : | edgomez | 1042 | |
767 : | edgomez | 1048 | if (s->type == XVID_TYPE_IVOP) { |
768 : | rc->keyframe_locations[j] = i; | ||
769 : | j++; | ||
770 : | } | ||
771 : | } | ||
772 : | |||
773 : | edgomez | 1042 | /* |
774 : | * Nota Bene: | ||
775 : | * The "per sequence" overflow system considers a natural sequence to be | ||
776 : | * formed by all frames between two iframes, so if we want to make sure | ||
777 : | * the system does not go nuts during last sequence, we force the last | ||
778 : | * frame to appear in the keyframe locations array. | ||
779 : | */ | ||
780 : | edgomez | 1064 | rc->keyframe_locations[j] = i; |
781 : | edgomez | 1042 | |
782 : | DPRINTF(XVID_DEBUG_RC, "Min 1st pass IFrame length: %d\n", rc->min_length[0]); | ||
783 : | DPRINTF(XVID_DEBUG_RC, "Min 1st pass PFrame length: %d\n", rc->min_length[1]); | ||
784 : | DPRINTF(XVID_DEBUG_RC, "Min 1st pass BFrame length: %d\n", rc->min_length[2]); | ||
785 : | } | ||
786 : | edgomez | 1064 | |
787 : | edgomez | 1042 | /* calculate zone weight "center" */ |
788 : | |||
789 : | static void | ||
790 : | zone_process(rc_2pass2_t *rc, const xvid_plg_create_t * create) | ||
791 : | { | ||
792 : | edgomez | 1064 | int i,j; |
793 : | int n = 0; | ||
794 : | edgomez | 1042 | |
795 : | edgomez | 1064 | rc->avg_weight = 0.0; |
796 : | rc->tot_quant = 0; | ||
797 : | edgomez | 1042 | |
798 : | |||
799 : | edgomez | 1064 | if (create->num_zones == 0) { |
800 : | for (j = 0; j < rc->num_frames; j++) { | ||
801 : | rc->stats[j].zone_mode = XVID_ZONE_WEIGHT; | ||
802 : | rc->stats[j].weight = 1.0; | ||
803 : | } | ||
804 : | rc->avg_weight += rc->num_frames * 1.0; | ||
805 : | n += rc->num_frames; | ||
806 : | } | ||
807 : | edgomez | 1042 | |
808 : | |||
809 : | edgomez | 1064 | for(i=0; i < create->num_zones; i++) { |
810 : | edgomez | 1042 | |
811 : | edgomez | 1064 | int next = (i+1<create->num_zones) ? create->zones[i+1].frame : rc->num_frames; |
812 : | edgomez | 1042 | |
813 : | edgomez | 1064 | if (i==0 && create->zones[i].frame > 0) { |
814 : | for (j = 0; j < create->zones[i].frame && j < rc->num_frames; j++) { | ||
815 : | rc->stats[j].zone_mode = XVID_ZONE_WEIGHT; | ||
816 : | rc->stats[j].weight = 1.0; | ||
817 : | } | ||
818 : | rc->avg_weight += create->zones[i].frame * 1.0; | ||
819 : | n += create->zones[i].frame; | ||
820 : | } | ||
821 : | edgomez | 1042 | |
822 : | edgomez | 1064 | if (create->zones[i].mode == XVID_ZONE_WEIGHT) { |
823 : | for (j = create->zones[i].frame; j < next && j < rc->num_frames; j++ ) { | ||
824 : | rc->stats[j].zone_mode = XVID_ZONE_WEIGHT; | ||
825 : | rc->stats[j].weight = (double)create->zones[i].increment / (double)create->zones[i].base; | ||
826 : | } | ||
827 : | next -= create->zones[i].frame; | ||
828 : | rc->avg_weight += (double)(next * create->zones[i].increment) / (double)create->zones[i].base; | ||
829 : | n += next; | ||
830 : | }else{ /* XVID_ZONE_QUANT */ | ||
831 : | for (j = create->zones[i].frame; j < next && j < rc->num_frames; j++ ) { | ||
832 : | rc->stats[j].zone_mode = XVID_ZONE_QUANT; | ||
833 : | rc->stats[j].weight = (double)create->zones[i].increment / (double)create->zones[i].base; | ||
834 : | rc->tot_quant += rc->stats[j].length; | ||
835 : | } | ||
836 : | } | ||
837 : | } | ||
838 : | rc->avg_weight = n>0 ? rc->avg_weight/n : 1.0; | ||
839 : | |||
840 : | DPRINTF(XVID_DEBUG_RC, "center_weight: %f (for %i frames); fixed_bytes: %i\n", rc->avg_weight, n, rc->tot_quant); | ||
841 : | edgomez | 1042 | } |
842 : | |||
843 : | |||
844 : | /* scale the curve */ | ||
845 : | |||
846 : | static void | ||
847 : | internal_scale(rc_2pass2_t *rc) | ||
848 : | { | ||
849 : | int64_t target = rc->target - rc->tot_quant; | ||
850 : | int64_t pass1_length = rc->tot_length[0] + rc->tot_length[1] + rc->tot_length[2] - rc->tot_quant; | ||
851 : | double scaler; | ||
852 : | edgomez | 1047 | int i, num_MBs; |
853 : | edgomez | 1042 | |
854 : | /* Let's compute a linear scaler in order to perform curve scaling */ | ||
855 : | scaler = (double)target / (double)pass1_length; | ||
856 : | |||
857 : | if (target <= 0 || pass1_length <= 0 || target >= pass1_length) { | ||
858 : | DPRINTF(XVID_DEBUG_RC, "WARNING: Undersize detected\n"); | ||
859 : | edgomez | 1064 | scaler = 1.0; |
860 : | edgomez | 1042 | } |
861 : | |||
862 : | edgomez | 1064 | DPRINTF(XVID_DEBUG_RC, |
863 : | edgomez | 1042 | "Before correction: target=%i, tot_length=%i, scaler=%f\n", |
864 : | (int)target, (int)pass1_length, scaler); | ||
865 : | |||
866 : | /* | ||
867 : | edgomez | 1047 | * Compute min frame lengths (for each frame type) according to the number |
868 : | * of MBs. We sum all blocks count from frame 0 (should be an IFrame, so | ||
869 : | * blocks[0] should be enough) to know how many MBs there are. | ||
870 : | edgomez | 1049 | * |
871 : | * We compare these hardcoded values with observed values in first pass | ||
872 : | * (determined in pre_process0).Then we keep the real minimum. | ||
873 : | edgomez | 1047 | */ |
874 : | num_MBs = rc->stats[0].blks[0] + rc->stats[0].blks[1] + rc->stats[0].blks[2]; | ||
875 : | |||
876 : | edgomez | 1049 | if(rc->min_length[0] > ((num_MBs*22) + 240) / 8) |
877 : | rc->min_length[0] = ((num_MBs*22) + 240) / 8; | ||
878 : | |||
879 : | if(rc->min_length[1] > ((num_MBs) + 88) / 8) | ||
880 : | rc->min_length[1] = ((num_MBs) + 88) / 8; | ||
881 : | |||
882 : | if(rc->min_length[2] > 8) | ||
883 : | rc->min_length[2] = 8; | ||
884 : | |||
885 : | edgomez | 1047 | /* |
886 : | edgomez | 1042 | * Perform an initial scale pass. |
887 : | * If a frame size is scaled underneath our hardcoded minimums, then we | ||
888 : | * force the frame size to the minimum, and deduct the original & scaled | ||
889 : | * frame length from the original and target total lengths | ||
890 : | */ | ||
891 : | for (i=0; i<rc->num_frames; i++) { | ||
892 : | stat_t * s = &rc->stats[i]; | ||
893 : | int len; | ||
894 : | |||
895 : | edgomez | 1064 | if (s->zone_mode == XVID_ZONE_QUANT) { |
896 : | s->scaled_length = s->length; | ||
897 : | edgomez | 1042 | continue; |
898 : | } | ||
899 : | |||
900 : | edgomez | 1048 | /* Compute the scaled length */ |
901 : | edgomez | 1042 | len = (int)((double)s->length * scaler * s->weight / rc->avg_weight); |
902 : | |||
903 : | /* Compare with the computed minimum */ | ||
904 : | edgomez | 1049 | if (len < rc->min_length[s->type-1]) { |
905 : | edgomez | 1042 | /* force frame size to our computed minimum */ |
906 : | edgomez | 1049 | s->scaled_length = rc->min_length[s->type-1]; |
907 : | edgomez | 1042 | target -= s->scaled_length; |
908 : | pass1_length -= s->length; | ||
909 : | } else { | ||
910 : | /* Do nothing for now, we'll scale this later */ | ||
911 : | s->scaled_length = 0; | ||
912 : | } | ||
913 : | } | ||
914 : | |||
915 : | /* Correct the scaler for all non forced frames */ | ||
916 : | scaler = (double)target / (double)pass1_length; | ||
917 : | |||
918 : | /* Detect undersizing */ | ||
919 : | edgomez | 1064 | if (target <= 0 || pass1_length <= 0 || target >= pass1_length) { |
920 : | edgomez | 1042 | DPRINTF(XVID_DEBUG_RC, "WARNING: Undersize detected\n"); |
921 : | scaler = 1.0; | ||
922 : | } | ||
923 : | |||
924 : | DPRINTF(XVID_DEBUG_RC, | ||
925 : | "After correction: target=%i, tot_length=%i, scaler=%f\n", | ||
926 : | (int)target, (int)pass1_length, scaler); | ||
927 : | |||
928 : | /* Do another pass with the new scaler */ | ||
929 : | for (i=0; i<rc->num_frames; i++) { | ||
930 : | stat_t * s = &rc->stats[i]; | ||
931 : | |||
932 : | /* Ignore frame with forced frame sizes */ | ||
933 : | if (s->scaled_length == 0) | ||
934 : | s->scaled_length = (int)((double)s->length * scaler * s->weight / rc->avg_weight); | ||
935 : | } | ||
936 : | } | ||
937 : | |||
938 : | static void | ||
939 : | pre_process1(rc_2pass2_t * rc) | ||
940 : | { | ||
941 : | edgomez | 1064 | int i; |
942 : | double total1, total2; | ||
943 : | uint64_t ivop_boost_total; | ||
944 : | edgomez | 1042 | |
945 : | edgomez | 1064 | ivop_boost_total = 0; |
946 : | rc->curve_comp_error = 0; | ||
947 : | edgomez | 1042 | |
948 : | edgomez | 1064 | for (i=0; i<3; i++) { |
949 : | rc->tot_scaled_length[i] = 0; | ||
950 : | } | ||
951 : | edgomez | 1042 | |
952 : | edgomez | 1064 | for (i=0; i<rc->num_frames; i++) { |
953 : | stat_t * s = &rc->stats[i]; | ||
954 : | edgomez | 1042 | |
955 : | edgomez | 1064 | rc->tot_scaled_length[s->type-1] += s->scaled_length; |
956 : | edgomez | 1042 | |
957 : | edgomez | 1064 | if (s->type == XVID_TYPE_IVOP) { |
958 : | ivop_boost_total += s->scaled_length * rc->param.keyframe_boost / 100; | ||
959 : | } | ||
960 : | } | ||
961 : | edgomez | 1042 | |
962 : | edgomez | 1064 | rc->movie_curve = ((double)(rc->tot_scaled_length[XVID_TYPE_PVOP-1] + rc->tot_scaled_length[XVID_TYPE_BVOP-1] + ivop_boost_total) / |
963 : | (rc->tot_scaled_length[XVID_TYPE_PVOP-1] + rc->tot_scaled_length[XVID_TYPE_BVOP-1])); | ||
964 : | edgomez | 1042 | |
965 : | edgomez | 1064 | for(i=0; i<3; i++) { |
966 : | if (rc->count[i] == 0 || rc->movie_curve == 0) { | ||
967 : | rc->avg_length[i] = 1; | ||
968 : | }else{ | ||
969 : | rc->avg_length[i] = rc->tot_scaled_length[i] / rc->count[i] / rc->movie_curve; | ||
970 : | } | ||
971 : | } | ||
972 : | edgomez | 1042 | |
973 : | edgomez | 1064 | /* --- */ |
974 : | edgomez | 1042 | |
975 : | edgomez | 1064 | total1=total2=0; |
976 : | edgomez | 1042 | |
977 : | edgomez | 1064 | for (i=0; i<rc->num_frames; i++) { |
978 : | stat_t * s = &rc->stats[i]; | ||
979 : | edgomez | 1042 | |
980 : | edgomez | 1064 | if (s->type != XVID_TYPE_IVOP) { |
981 : | double dbytes,dbytes2; | ||
982 : | edgomez | 1042 | |
983 : | edgomez | 1064 | dbytes = s->scaled_length / rc->movie_curve; |
984 : | dbytes2 = 0; /* XXX: warning */ | ||
985 : | total1 += dbytes; | ||
986 : | |||
987 : | edgomez | 1051 | if (dbytes > rc->avg_length[s->type-1]) { |
988 : | dbytes2=((double)dbytes + (rc->avg_length[s->type-1] - dbytes) * rc->param.curve_compression_high / 100.0); | ||
989 : | edgomez | 1046 | } else { |
990 : | edgomez | 1051 | dbytes2 = ((double)dbytes + (rc->avg_length[s->type-1] - dbytes) * rc->param.curve_compression_low / 100.0); |
991 : | edgomez | 1046 | } |
992 : | edgomez | 1042 | |
993 : | edgomez | 1051 | if (dbytes2 < rc->min_length[s->type-1]) |
994 : | edgomez | 1064 | dbytes2 = rc->min_length[s->type-1]; |
995 : | edgomez | 1051 | |
996 : | edgomez | 1064 | total2 += dbytes2; |
997 : | } | ||
998 : | } | ||
999 : | edgomez | 1042 | |
1000 : | edgomez | 1064 | rc->curve_comp_scale = total1 / total2; |
1001 : | edgomez | 1042 | |
1002 : | edgomez | 1051 | DPRINTF(XVID_DEBUG_RC, "middle frame size for asymmetric curve compression: pframe%d bframe:%d\n", |
1003 : | edgomez | 1064 | (int)(rc->avg_length[XVID_TYPE_PVOP-1] * rc->curve_comp_scale), |
1004 : | edgomez | 1051 | (int)(rc->avg_length[XVID_TYPE_BVOP-1] * rc->curve_comp_scale)); |
1005 : | edgomez | 1042 | |
1006 : | edgomez | 1064 | rc->overflow = 0; |
1007 : | rc->KFoverflow = 0; | ||
1008 : | rc->KFoverflow_partial = 0; | ||
1009 : | rc->KF_idx = 1; | ||
1010 : | edgomez | 1042 | } |
No admin address has been configured | ViewVC Help |
Powered by ViewVC 1.0.4 |