25 |
* along with this program; if not, write to the Free Software |
* along with this program; if not, write to the Free Software |
26 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
27 |
* |
* |
28 |
* $Id: plugin_2pass2.c,v 1.1.2.11 2003-05-24 21:22:18 edgomez Exp $ |
* $Id: plugin_2pass2.c,v 1.1.2.15 2003-05-29 11:37:20 edgomez Exp $ |
29 |
* |
* |
30 |
*****************************************************************************/ |
*****************************************************************************/ |
31 |
|
|
40 |
* Some constants |
* Some constants |
41 |
****************************************************************************/ |
****************************************************************************/ |
42 |
|
|
|
#define RAD2DEG 57.295779513082320876798154814105 |
|
|
#define DEG2RAD 0.017453292519943295769236907684886 |
|
|
|
|
43 |
#define DEFAULT_KEYFRAME_BOOST 0 |
#define DEFAULT_KEYFRAME_BOOST 0 |
44 |
#define DEFAULT_PAYBACK_METHOD XVID_PAYBACK_PROP |
#define DEFAULT_PAYBACK_METHOD XVID_PAYBACK_PROP |
45 |
#define DEFAULT_BITRATE_PAYBACK_DELAY 250 |
#define DEFAULT_BITRATE_PAYBACK_DELAY 250 |
48 |
#define DEFAULT_MAX_OVERFLOW_IMPROVEMENT 60 |
#define DEFAULT_MAX_OVERFLOW_IMPROVEMENT 60 |
49 |
#define DEFAULT_MAX_OVERFLOW_DEGRADATION 60 |
#define DEFAULT_MAX_OVERFLOW_DEGRADATION 60 |
50 |
|
|
|
/* Alt curve settings */ |
|
|
#define DEFAULT_USE_ALT_CURVE 0 |
|
|
#define DEFAULT_ALT_CURVE_HIGH_DIST 500 |
|
|
#define DEFAULT_ALT_CURVE_LOW_DIST 90 |
|
|
#define DEFAULT_ALT_CURVE_USE_AUTO 1 |
|
|
#define DEFAULT_ALT_CURVE_AUTO_STR 30 |
|
|
#define DEFAULT_ALT_CURVE_TYPE XVID_CURVE_LINEAR |
|
|
#define DEFAULT_ALT_CURVE_MIN_REL_QUAL 50 |
|
|
#define DEFAULT_ALT_CURVE_USE_AUTO_BONUS_BIAS 1 |
|
|
#define DEFAULT_ALT_CURVE_BONUS_BIAS 50 |
|
|
|
|
51 |
/* Keyframe settings */ |
/* Keyframe settings */ |
52 |
#define DEFAULT_KFTRESHOLD 10 |
#define DEFAULT_KFTRESHOLD 10 |
53 |
#define DEFAULT_KFREDUCTION 20 |
#define DEFAULT_KFREDUCTION 20 |
95 |
double curve_comp_scale; |
double curve_comp_scale; |
96 |
double movie_curve; |
double movie_curve; |
97 |
|
|
|
double alt_curve_low; |
|
|
double alt_curve_high; |
|
|
double alt_curve_low_diff; |
|
|
double alt_curve_high_diff; |
|
|
double alt_curve_curve_bias_bonus; |
|
|
double alt_curve_mid_qual; |
|
|
double alt_curve_qual_dev; |
|
|
|
|
98 |
/* dynamic */ |
/* dynamic */ |
99 |
|
|
100 |
int * keyframe_locations; |
int * keyframe_locations; |
101 |
stat_t * stats; |
stat_t * stats; |
102 |
|
|
103 |
double pquant_error[32]; |
double quant_error[3][32]; |
|
double bquant_error[32]; |
|
104 |
int quant_count[32]; |
int quant_count[32]; |
105 |
int last_quant[3]; |
int last_quant[3]; |
106 |
|
|
178 |
|
|
179 |
rc->param = *param; |
rc->param = *param; |
180 |
|
|
181 |
|
/* |
182 |
|
* Initialize all defaults |
183 |
|
*/ |
184 |
#define _INIT(a, b) if((a) <= 0) (a) = (b) |
#define _INIT(a, b) if((a) <= 0) (a) = (b) |
185 |
/* Let's set our defaults if needed */ |
/* Let's set our defaults if needed */ |
186 |
_INIT(rc->param.keyframe_boost, DEFAULT_KEYFRAME_BOOST); |
_INIT(rc->param.keyframe_boost, DEFAULT_KEYFRAME_BOOST); |
191 |
_INIT(rc->param.max_overflow_improvement, DEFAULT_MAX_OVERFLOW_IMPROVEMENT); |
_INIT(rc->param.max_overflow_improvement, DEFAULT_MAX_OVERFLOW_IMPROVEMENT); |
192 |
_INIT(rc->param.max_overflow_degradation, DEFAULT_MAX_OVERFLOW_DEGRADATION); |
_INIT(rc->param.max_overflow_degradation, DEFAULT_MAX_OVERFLOW_DEGRADATION); |
193 |
|
|
|
/* Alt curve settings */ |
|
|
_INIT(rc->param.use_alt_curve, DEFAULT_USE_ALT_CURVE); |
|
|
_INIT(rc->param.alt_curve_high_dist, DEFAULT_ALT_CURVE_HIGH_DIST); |
|
|
_INIT(rc->param.alt_curve_low_dist, DEFAULT_ALT_CURVE_LOW_DIST); |
|
|
_INIT(rc->param.alt_curve_use_auto, DEFAULT_ALT_CURVE_USE_AUTO); |
|
|
_INIT(rc->param.alt_curve_auto_str, DEFAULT_ALT_CURVE_AUTO_STR); |
|
|
_INIT(rc->param.alt_curve_type, DEFAULT_ALT_CURVE_TYPE); |
|
|
_INIT(rc->param.alt_curve_min_rel_qual, DEFAULT_ALT_CURVE_MIN_REL_QUAL); |
|
|
_INIT(rc->param.alt_curve_use_auto_bonus_bias, DEFAULT_ALT_CURVE_USE_AUTO_BONUS_BIAS); |
|
|
_INIT(rc->param.alt_curve_bonus_bias, DEFAULT_ALT_CURVE_BONUS_BIAS); |
|
|
|
|
194 |
/* Keyframe settings */ |
/* Keyframe settings */ |
195 |
_INIT(rc->param.kftreshold, DEFAULT_KFTRESHOLD); |
_INIT(rc->param.kftreshold, DEFAULT_KFTRESHOLD); |
196 |
_INIT(rc->param.kfreduction, DEFAULT_KFREDUCTION); |
_INIT(rc->param.kfreduction, DEFAULT_KFREDUCTION); |
197 |
_INIT(rc->param.min_key_interval, DEFAULT_MIN_KEY_INTERVAL); |
_INIT(rc->param.min_key_interval, DEFAULT_MIN_KEY_INTERVAL); |
198 |
#undef _INIT |
#undef _INIT |
199 |
|
|
200 |
|
/* Initialize some stuff to zero */ |
201 |
|
for(i=0; i<32; i++) rc->quant_count[i] = 0; |
202 |
|
|
203 |
|
for(i=0; i<3; i++) { |
204 |
|
int j; |
205 |
|
for (j=0; j<32; j++) |
206 |
|
rc->quant_error[i][j] = 0; |
207 |
|
} |
208 |
|
|
209 |
|
for (i=0; i<3; i++) |
210 |
|
rc->last_quant[i] = 0; |
211 |
|
|
212 |
|
rc->fq_error = 0; |
213 |
|
|
214 |
/* Count frames in the stats file */ |
/* Count frames in the stats file */ |
215 |
if (!det_stats_length(rc, param->filename)){ |
if (!det_stats_length(rc, param->filename)){ |
216 |
DPRINTF(XVID_DEBUG_RC,"fopen %s failed\n", param->filename); |
DPRINTF(XVID_DEBUG_RC,"ERROR: fopen %s failed\n", param->filename); |
217 |
free(rc); |
free(rc); |
218 |
return XVID_ERR_FAIL; |
return XVID_ERR_FAIL; |
219 |
} |
} |
228 |
* Allocate keyframes location's memory |
* Allocate keyframes location's memory |
229 |
* PS: see comment in pre_process0 for the +1 location requirement |
* PS: see comment in pre_process0 for the +1 location requirement |
230 |
*/ |
*/ |
231 |
if ((rc->keyframe_locations = malloc((rc->num_keyframes + 1) * sizeof(int))) == NULL) { |
rc->keyframe_locations = malloc((rc->num_keyframes + 1) * sizeof(int)); |
232 |
|
if (rc->keyframe_locations == NULL) { |
233 |
free(rc->stats); |
free(rc->stats); |
234 |
free(rc); |
free(rc); |
235 |
return XVID_ERR_MEMORY; |
return XVID_ERR_MEMORY; |
236 |
} |
} |
237 |
|
|
238 |
if (!load_stats(rc, param->filename)) { |
if (!load_stats(rc, param->filename)) { |
239 |
DPRINTF(XVID_DEBUG_RC,"fopen %s failed\n", param->filename); |
DPRINTF(XVID_DEBUG_RC,"ERROR: fopen %s failed\n", param->filename); |
240 |
free(rc->keyframe_locations); |
free(rc->keyframe_locations); |
241 |
free(rc->stats); |
free(rc->stats); |
242 |
free(rc); |
free(rc); |
243 |
return XVID_ERR_FAIL; |
return XVID_ERR_FAIL; |
244 |
} |
} |
245 |
|
|
246 |
/* pre-process our stats */ |
/* Compute the target filesize */ |
|
|
|
247 |
if (rc->num_frames < create->fbase/create->fincr) { |
if (rc->num_frames < create->fbase/create->fincr) { |
248 |
rc->target = rc->param.bitrate / 8; /* one second */ |
/* Source sequence is less than 1s long, we do as if it was 1s long */ |
249 |
|
rc->target = rc->param.bitrate / 8; |
250 |
} else { |
} else { |
251 |
|
/* Target filesize = bitrate/8 * numframes / framerate */ |
252 |
rc->target = |
rc->target = |
253 |
((uint64_t)rc->param.bitrate * (uint64_t)rc->num_frames * (uint64_t)create->fincr) / \ |
((uint64_t)rc->param.bitrate * (uint64_t)rc->num_frames * \ |
254 |
|
(uint64_t)create->fincr) / \ |
255 |
((uint64_t)create->fbase * 8); |
((uint64_t)create->fbase * 8); |
256 |
} |
} |
257 |
|
|
258 |
|
DPRINTF(XVID_DEBUG_RC, "Frame rate: %d/%d (%ffps)\n", |
259 |
|
create->fbase, create->fincr, |
260 |
|
(double)create->fbase/(double)create->fincr); |
261 |
DPRINTF(XVID_DEBUG_RC, "Number of frames: %d\n", rc->num_frames); |
DPRINTF(XVID_DEBUG_RC, "Number of frames: %d\n", rc->num_frames); |
|
DPRINTF(XVID_DEBUG_RC, "Frame rate: %d/%d\n", create->fbase, create->fincr); |
|
262 |
DPRINTF(XVID_DEBUG_RC, "Target bitrate: %ld\n", rc->param.bitrate); |
DPRINTF(XVID_DEBUG_RC, "Target bitrate: %ld\n", rc->param.bitrate); |
263 |
DPRINTF(XVID_DEBUG_RC, "Target filesize: %lld\n", rc->target); |
DPRINTF(XVID_DEBUG_RC, "Target filesize: %lld\n", rc->target); |
264 |
|
|
265 |
/* Compensate the mean frame overhead caused by the container */ |
/* Compensate the average frame overhead caused by the container */ |
266 |
rc->target -= rc->num_frames*rc->param.container_frame_overhead; |
rc->target -= rc->num_frames*rc->param.container_frame_overhead; |
267 |
DPRINTF(XVID_DEBUG_RC, "Container Frame overhead: %d\n", rc->param.container_frame_overhead); |
DPRINTF(XVID_DEBUG_RC, "Container Frame overhead: %d\n", rc->param.container_frame_overhead); |
268 |
DPRINTF(XVID_DEBUG_RC, "Target filesize (after container compensation): %lld\n", rc->target); |
DPRINTF(XVID_DEBUG_RC, "Target filesize (after container compensation): %lld\n", rc->target); |
269 |
|
|
270 |
|
/* |
271 |
|
* First data pre processing: |
272 |
|
* - finds the minimum frame length for each frame type during 1st pass. |
273 |
|
* rc->min_size[] |
274 |
|
* - determines the maximum frame length observed (no frame type distinction). |
275 |
|
* rc->max_size |
276 |
|
* - count how many times each frame type has been used. |
277 |
|
* rc->count[] |
278 |
|
* - total bytes used per frame type |
279 |
|
* rc->total[] |
280 |
|
* - store keyframe location |
281 |
|
* rc->keyframe_locations[] |
282 |
|
*/ |
283 |
pre_process0(rc); |
pre_process0(rc); |
284 |
|
|
285 |
|
/* |
286 |
|
* When bitrate is not given it means it has been scaled by an external |
287 |
|
* application |
288 |
|
*/ |
289 |
if (rc->param.bitrate) { |
if (rc->param.bitrate) { |
290 |
|
/* Apply zone settings */ |
291 |
zone_process(rc, create); |
zone_process(rc, create); |
292 |
|
/* Perform curve scaling */ |
293 |
internal_scale(rc); |
internal_scale(rc); |
294 |
}else{ |
}else{ |
295 |
/* external scaler: ignore zone */ |
/* External scaling -- zones are ignored */ |
296 |
for (i=0;i<rc->num_frames;i++) { |
for (i=0;i<rc->num_frames;i++) { |
297 |
rc->stats[i].zone_mode = XVID_ZONE_WEIGHT; |
rc->stats[i].zone_mode = XVID_ZONE_WEIGHT; |
298 |
rc->stats[i].weight = 1.0; |
rc->stats[i].weight = 1.0; |
300 |
rc->avg_weight = 1.0; |
rc->avg_weight = 1.0; |
301 |
rc->tot_quant = 0; |
rc->tot_quant = 0; |
302 |
} |
} |
|
pre_process1(rc); |
|
|
|
|
|
for (i=0; i<32;i++) { |
|
|
rc->pquant_error[i] = 0; |
|
|
rc->bquant_error[i] = 0; |
|
|
rc->quant_count[i] = 0; |
|
|
} |
|
303 |
|
|
304 |
rc->fq_error = 0; |
pre_process1(rc); |
305 |
|
|
306 |
*handle = rc; |
*handle = rc; |
307 |
return(0); |
return(0); |
330 |
int desired; |
int desired; |
331 |
double dbytes; |
double dbytes; |
332 |
double curve_temp; |
double curve_temp; |
333 |
|
double scaled_quant; |
334 |
int capped_to_max_framesize = 0; |
int capped_to_max_framesize = 0; |
335 |
|
|
336 |
/* |
/* |
344 |
|
|
345 |
/* Second case: We are in a Quant zone */ |
/* Second case: We are in a Quant zone */ |
346 |
if (s->zone_mode == XVID_ZONE_QUANT) { |
if (s->zone_mode == XVID_ZONE_QUANT) { |
|
|
|
347 |
rc->fq_error += s->weight; |
rc->fq_error += s->weight; |
348 |
data->quant = (int)rc->fq_error; |
data->quant = (int)rc->fq_error; |
349 |
rc->fq_error -= data->quant; |
rc->fq_error -= data->quant; |
351 |
s->desired_length = s->length; |
s->desired_length = s->length; |
352 |
|
|
353 |
return(0); |
return(0); |
|
|
|
354 |
} |
} |
355 |
|
|
356 |
/* Third case: insufficent stats data */ |
/* Third case: insufficent stats data */ |
369 |
* The rc->overflow field represents the overflow in current scene (between two |
* The rc->overflow field represents the overflow in current scene (between two |
370 |
* IFrames) so we must not forget to reset it if we are entering a new scene |
* IFrames) so we must not forget to reset it if we are entering a new scene |
371 |
*/ |
*/ |
372 |
if (s->type == XVID_TYPE_IVOP) { |
if (s->type == XVID_TYPE_IVOP) |
373 |
overflow = 0; |
overflow = 0; |
|
} |
|
374 |
|
|
375 |
desired = s->scaled_length; |
desired = s->scaled_length; |
376 |
|
|
377 |
dbytes = desired; |
dbytes = desired; |
378 |
if (s->type == XVID_TYPE_IVOP) { |
if (s->type == XVID_TYPE_IVOP) |
379 |
dbytes += desired * rc->param.keyframe_boost / 100; |
dbytes += desired * rc->param.keyframe_boost / 100; |
|
} |
|
380 |
dbytes /= rc->movie_curve; |
dbytes /= rc->movie_curve; |
381 |
|
|
382 |
/* |
/* |
407 |
|
|
408 |
rc->curve_comp_error -= desired; |
rc->curve_comp_error -= desired; |
409 |
|
|
|
/* |
|
|
* Alt curve treatment is not that hard to understand though the formulas |
|
|
* seem to be huge. Alt treatment is basically a way to soft/harden the |
|
|
* curve flux applying sine/linear/cosine ratios |
|
|
*/ |
|
|
|
|
410 |
/* XXX: warning */ |
/* XXX: warning */ |
411 |
curve_temp = 0; |
curve_temp = 0; |
412 |
|
|
413 |
if (rc->param.use_alt_curve) { |
if ((rc->param.curve_compression_high + rc->param.curve_compression_low) && s->type != XVID_TYPE_IVOP) { |
|
if (s->type != XVID_TYPE_IVOP) { |
|
|
if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { |
|
|
if (dbytes >= rc->alt_curve_high) { |
|
|
curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev); |
|
|
} else { |
|
|
switch(rc->param.alt_curve_type) { |
|
|
case XVID_CURVE_SINE : |
|
|
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))); |
|
|
break; |
|
|
case XVID_CURVE_LINEAR : |
|
|
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); |
|
|
break; |
|
|
case XVID_CURVE_COSINE : |
|
|
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)))); |
|
|
} |
|
|
} |
|
|
} else { |
|
|
if (dbytes <= rc->alt_curve_low){ |
|
|
curve_temp = dbytes; |
|
|
} else { |
|
|
switch(rc->param.alt_curve_type) { |
|
|
case XVID_CURVE_SINE : |
|
|
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))); |
|
|
break; |
|
|
case XVID_CURVE_LINEAR : |
|
|
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); |
|
|
break; |
|
|
case XVID_CURVE_COSINE : |
|
|
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)))); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
/* |
|
|
* End of code path for curve_temp, as told earlier, we are now |
|
|
* obliged to scale the value to a bframe one using the inverse |
|
|
* ratio applied earlier |
|
|
*/ |
|
|
if (s->type == XVID_TYPE_BVOP) |
|
|
curve_temp *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; |
|
|
|
|
|
curve_temp = curve_temp * rc->curve_comp_scale + rc->alt_curve_curve_bias_bonus; |
|
|
|
|
|
desired += ((int)curve_temp); |
|
|
rc->curve_comp_error += curve_temp - (int)curve_temp; |
|
|
} else { |
|
|
/* |
|
|
* End of code path for dbytes, as told earlier, we are now |
|
|
* obliged to scale the value to a bframe one using the inverse |
|
|
* ratio applied earlier |
|
|
*/ |
|
|
if (s->type == XVID_TYPE_BVOP) |
|
|
dbytes *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; |
|
|
|
|
|
desired += ((int)dbytes); |
|
|
rc->curve_comp_error += dbytes - (int)dbytes; |
|
|
} |
|
|
|
|
|
} else if ((rc->param.curve_compression_high + rc->param.curve_compression_low) && s->type != XVID_TYPE_IVOP) { |
|
414 |
|
|
415 |
curve_temp = rc->curve_comp_scale; |
curve_temp = rc->curve_comp_scale; |
416 |
if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { |
if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { |
463 |
s->desired_length = desired; |
s->desired_length = desired; |
464 |
|
|
465 |
|
|
466 |
/* if this keyframe is too close to the next, reduce it's byte allotment |
/* |
467 |
XXX: why do we do this after setting the desired length */ |
* if this keyframe is too close to the next, reduce it's byte allotment |
468 |
|
* XXX: why do we do this after setting the desired length ? |
469 |
|
*/ |
470 |
|
|
471 |
if (s->type == XVID_TYPE_IVOP) { |
if (s->type == XVID_TYPE_IVOP) { |
472 |
int KFdistance = rc->keyframe_locations[rc->KF_idx] - rc->keyframe_locations[rc->KF_idx - 1]; |
int KFdistance = rc->keyframe_locations[rc->KF_idx] - rc->keyframe_locations[rc->KF_idx - 1]; |
494 |
overflow = (int)((double)overflow * desired / rc->avg_length[XVID_TYPE_PVOP-1]); |
overflow = (int)((double)overflow * desired / rc->avg_length[XVID_TYPE_PVOP-1]); |
495 |
|
|
496 |
/* Reign in overflow with huge frames */ |
/* Reign in overflow with huge frames */ |
497 |
if (labs(overflow) > labs(rc->overflow)) { |
if (labs(overflow) > labs(rc->overflow)) |
498 |
overflow = rc->overflow; |
overflow = rc->overflow; |
|
} |
|
499 |
|
|
500 |
/* Make sure overflow doesn't run away */ |
/* Make sure overflow doesn't run away */ |
501 |
if (overflow > desired * rc->param.max_overflow_improvement / 100) { |
if (overflow > desired * rc->param.max_overflow_improvement / 100) { |
526 |
* Don't laugh at this very 'simple' quant<->filesize relationship, it |
* Don't laugh at this very 'simple' quant<->filesize relationship, it |
527 |
* proves to be acurate enough for our algorithm |
* proves to be acurate enough for our algorithm |
528 |
*/ |
*/ |
529 |
data->quant = s->quant*s->length/desired; |
scaled_quant = (double)s->quant*(double)s->length/(double)desired; |
530 |
|
|
531 |
|
/* |
532 |
|
* Quantizer has been scaled using floating point operations/results, we |
533 |
|
* must cast it to integer |
534 |
|
*/ |
535 |
|
data->quant = (int)scaled_quant; |
536 |
|
|
537 |
/* Let's clip the computed quantizer, if needed */ |
/* Let's clip the computed quantizer, if needed */ |
538 |
if (data->quant < 1) { |
if (data->quant < 1) { |
542 |
} else if (s->type != XVID_TYPE_IVOP) { |
} else if (s->type != XVID_TYPE_IVOP) { |
543 |
|
|
544 |
/* |
/* |
545 |
* The frame quantizer has not been clipped, this appear to be a good |
* The frame quantizer has not been clipped, this appears to be a good |
546 |
* computed quantizer, however past frames give us some info about how |
* computed quantizer, do not loose quantizer decimal part that we |
547 |
* this quantizer performs against the algo prevision. Let's use this |
* accumulate for later reuse when its sum represents a complete unit. |
|
* prevision to increase the quantizer when we observe a too big |
|
|
* accumulated error |
|
548 |
*/ |
*/ |
549 |
if (s->type == XVID_TYPE_BVOP) { |
rc->quant_error[s->type-1][data->quant] += scaled_quant - (double)data->quant; |
|
rc->bquant_error[data->quant] += ((double)(s->quant * s->length) / desired) - data->quant; |
|
550 |
|
|
551 |
if (rc->bquant_error[data->quant] >= 1.0) { |
if (rc->quant_error[s->type-1][data->quant] >= 1.0) { |
552 |
rc->bquant_error[data->quant] -= 1.0; |
rc->quant_error[s->type-1][data->quant] -= 1.0; |
553 |
data->quant++; |
data->quant++; |
554 |
|
} else if (rc->quant_error[s->type-1][data->quant] <= -1.0) { |
555 |
|
rc->quant_error[s->type-1][data->quant] += 1.0; |
556 |
|
data->quant--; |
557 |
} |
} |
|
} else { |
|
|
rc->pquant_error[data->quant] += ((double)(s->quant * s->length) / desired) - data->quant; |
|
558 |
|
|
|
if (rc->pquant_error[data->quant] >= 1.0) { |
|
|
rc->pquant_error[data->quant] -= 1.0; |
|
|
data->quant++; |
|
|
} |
|
|
} |
|
559 |
} |
} |
560 |
|
|
561 |
/* |
/* |
597 |
* We don't want to pollute the RC history results when our computed quant |
* We don't want to pollute the RC history results when our computed quant |
598 |
* has been computed from a capped frame size |
* has been computed from a capped frame size |
599 |
*/ |
*/ |
600 |
if (capped_to_max_framesize == 0) { |
if (capped_to_max_framesize == 0) |
601 |
rc->last_quant[s->type-1] = data->quant; |
rc->last_quant[s->type-1] = data->quant; |
|
} |
|
602 |
|
|
603 |
return 0; |
return 0; |
604 |
} |
} |
609 |
static int |
static int |
610 |
rc_2pass2_after(rc_2pass2_t * rc, xvid_plg_data_t * data) |
rc_2pass2_after(rc_2pass2_t * rc, xvid_plg_data_t * data) |
611 |
{ |
{ |
612 |
|
const char frame_type[4] = { 'i', 'p', 'b', 's'}; |
613 |
stat_t * s = &rc->stats[data->frame_num]; |
stat_t * s = &rc->stats[data->frame_num]; |
614 |
|
|
615 |
/* Insufficent stats data */ |
/* Insufficent stats data */ |
638 |
rc->KFoverflow -= rc->KFoverflow_partial; |
rc->KFoverflow -= rc->KFoverflow_partial; |
639 |
} |
} |
640 |
|
|
641 |
DPRINTF(XVID_DEBUG_RC, "[%i] quant:%i stats1:%i scaled:%i actual:%i overflow:%i\n", |
DPRINTF(XVID_DEBUG_RC, "[%i] type:%c quant:%i stats1:%i scaled:%i actual:%i desired:%d overflow:%i\n", |
642 |
data->frame_num, |
data->frame_num, |
643 |
|
frame_type[data->type-1], |
644 |
data->quant, |
data->quant, |
645 |
s->length, |
s->length, |
646 |
s->scaled_length, |
s->scaled_length, |
647 |
data->length, |
data->length, |
648 |
|
s->desired_length, |
649 |
rc->overflow); |
rc->overflow); |
650 |
|
|
651 |
return(0); |
return(0); |
756 |
{ |
{ |
757 |
int i,j; |
int i,j; |
758 |
|
|
759 |
|
/* |
760 |
|
* *rc fields initialization |
761 |
|
* NB: INT_MAX and INT_MIN are used in order to be immediately replaced |
762 |
|
* with real values of the 1pass |
763 |
|
*/ |
764 |
for (i=0; i<3; i++) { |
for (i=0; i<3; i++) { |
765 |
rc->count[i]=0; |
rc->count[i]=0; |
766 |
rc->tot_length[i] = 0; |
rc->tot_length[i] = 0; |
|
rc->last_quant[i] = 0; |
|
767 |
rc->min_length[i] = INT_MAX; |
rc->min_length[i] = INT_MAX; |
768 |
} |
} |
769 |
|
|
770 |
rc->max_length = INT_MIN; |
rc->max_length = INT_MIN; |
771 |
|
|
772 |
|
/* |
773 |
|
* Loop through all frames and find/compute all the stuff this function |
774 |
|
* is supposed to do |
775 |
|
*/ |
776 |
for (i=j=0; i<rc->num_frames; i++) { |
for (i=j=0; i<rc->num_frames; i++) { |
777 |
stat_t * s = &rc->stats[i]; |
stat_t * s = &rc->stats[i]; |
778 |
|
|
872 |
int64_t target = rc->target - rc->tot_quant; |
int64_t target = rc->target - rc->tot_quant; |
873 |
int64_t pass1_length = rc->tot_length[0] + rc->tot_length[1] + rc->tot_length[2] - rc->tot_quant; |
int64_t pass1_length = rc->tot_length[0] + rc->tot_length[1] + rc->tot_length[2] - rc->tot_quant; |
874 |
double scaler; |
double scaler; |
875 |
int i; |
int i, num_MBs; |
876 |
|
int min_size[3]; |
877 |
|
|
878 |
/* Let's compute a linear scaler in order to perform curve scaling */ |
/* Let's compute a linear scaler in order to perform curve scaling */ |
879 |
scaler = (double)target / (double)pass1_length; |
scaler = (double)target / (double)pass1_length; |
888 |
(int)target, (int)pass1_length, scaler); |
(int)target, (int)pass1_length, scaler); |
889 |
|
|
890 |
/* |
/* |
891 |
|
* Compute min frame lengths (for each frame type) according to the number |
892 |
|
* of MBs. We sum all blocks count from frame 0 (should be an IFrame, so |
893 |
|
* blocks[0] should be enough) to know how many MBs there are. |
894 |
|
*/ |
895 |
|
num_MBs = rc->stats[0].blks[0] + rc->stats[0].blks[1] + rc->stats[0].blks[2]; |
896 |
|
min_size[0] = ((num_MBs*22) + 240) / 8; |
897 |
|
min_size[1] = ((num_MBs) + 88) / 8; |
898 |
|
min_size[2] = 8; |
899 |
|
|
900 |
|
/* |
901 |
* Perform an initial scale pass. |
* Perform an initial scale pass. |
902 |
* If a frame size is scaled underneath our hardcoded minimums, then we |
* If a frame size is scaled underneath our hardcoded minimums, then we |
903 |
* force the frame size to the minimum, and deduct the original & scaled |
* force the frame size to the minimum, and deduct the original & scaled |
904 |
* frame length from the original and target total lengths |
* frame length from the original and target total lengths |
905 |
*/ |
*/ |
|
|
|
906 |
for (i=0; i<rc->num_frames; i++) { |
for (i=0; i<rc->num_frames; i++) { |
907 |
stat_t * s = &rc->stats[i]; |
stat_t * s = &rc->stats[i]; |
|
int min_size[3]; |
|
908 |
int len; |
int len; |
909 |
|
|
|
/* Compute min frame lengths (oe for each frame type) */ |
|
|
min_size[0] = ((s->blks[0]*22) + 240) / 8; |
|
|
min_size[1] = (s->blks[0] + 88) / 8; |
|
|
min_size[2] = 8; |
|
|
|
|
910 |
if (s->zone_mode == XVID_ZONE_QUANT) { |
if (s->zone_mode == XVID_ZONE_QUANT) { |
911 |
s->scaled_length = s->length; |
s->scaled_length = s->length; |
912 |
continue; |
continue; |
913 |
} |
} |
914 |
|
|
915 |
/* Compute teh scaled length */ |
/* Compute the scaled length */ |
916 |
len = (int)((double)s->length * scaler * s->weight / rc->avg_weight); |
len = (int)((double)s->length * scaler * s->weight / rc->avg_weight); |
917 |
|
|
918 |
/* Compare with the computed minimum */ |
/* Compare with the computed minimum */ |
925 |
/* Do nothing for now, we'll scale this later */ |
/* Do nothing for now, we'll scale this later */ |
926 |
s->scaled_length = 0; |
s->scaled_length = 0; |
927 |
} |
} |
|
|
|
928 |
} |
} |
929 |
|
|
930 |
/* Correct the scaler for all non forced frames */ |
/* Correct the scaler for all non forced frames */ |
948 |
if (s->scaled_length == 0) |
if (s->scaled_length == 0) |
949 |
s->scaled_length = (int)((double)s->length * scaler * s->weight / rc->avg_weight); |
s->scaled_length = (int)((double)s->length * scaler * s->weight / rc->avg_weight); |
950 |
} |
} |
|
|
|
951 |
} |
} |
952 |
|
|
953 |
static void |
static void |
985 |
} |
} |
986 |
} |
} |
987 |
|
|
|
/* alt curve stuff here */ |
|
|
|
|
|
if (rc->param.use_alt_curve) { |
|
|
const double avg_pvop = rc->avg_length[XVID_TYPE_PVOP-1]; |
|
|
const uint64_t tot_pvop = rc->tot_length[XVID_TYPE_PVOP-1]; |
|
|
const uint64_t tot_bvop = rc->tot_length[XVID_TYPE_BVOP-1]; |
|
|
const uint64_t tot_scaled_pvop = rc->tot_scaled_length[XVID_TYPE_PVOP-1]; |
|
|
const uint64_t tot_scaled_bvop = rc->tot_scaled_length[XVID_TYPE_BVOP-1]; |
|
|
|
|
|
rc->alt_curve_low = avg_pvop - avg_pvop * (double)rc->param.alt_curve_low_dist / 100.0; |
|
|
rc->alt_curve_low_diff = avg_pvop - rc->alt_curve_low; |
|
|
rc->alt_curve_high = avg_pvop + avg_pvop * (double)rc->param.alt_curve_high_dist / 100.0; |
|
|
rc->alt_curve_high_diff = rc->alt_curve_high - avg_pvop; |
|
|
|
|
|
if (rc->param.alt_curve_use_auto) { |
|
|
if (tot_bvop + tot_pvop > tot_scaled_bvop + tot_scaled_pvop) { |
|
|
rc->param.alt_curve_min_rel_qual = (int)(100.0 - (100.0 - 100.0 / |
|
|
((double)(tot_pvop + tot_bvop) / (double)(tot_scaled_pvop + tot_scaled_bvop))) * (double)rc->param.alt_curve_auto_str / 100.0); |
|
|
|
|
|
if (rc->param.alt_curve_min_rel_qual < 20) |
|
|
rc->param.alt_curve_min_rel_qual = 20; |
|
|
}else{ |
|
|
rc->param.alt_curve_min_rel_qual = 100; |
|
|
} |
|
|
} |
|
|
rc->alt_curve_mid_qual = (1.0 + (double)rc->param.alt_curve_min_rel_qual / 100.0) / 2.0; |
|
|
rc->alt_curve_qual_dev = 1.0 - rc->alt_curve_mid_qual; |
|
|
|
|
|
if (rc->param.alt_curve_low_dist > 100) { |
|
|
switch(rc->param.alt_curve_type) { |
|
|
case XVID_CURVE_SINE: // Sine Curve (high aggressiveness) |
|
|
rc->alt_curve_qual_dev *= 2.0 / (1.0 + sin(DEG2RAD * (avg_pvop * 90.0 / rc->alt_curve_low_diff))); |
|
|
rc->alt_curve_mid_qual = 1.0 - rc->alt_curve_qual_dev * sin(DEG2RAD * (avg_pvop * 90.0 / rc->alt_curve_low_diff)); |
|
|
break; |
|
|
case XVID_CURVE_LINEAR: // Linear (medium aggressiveness) |
|
|
rc->alt_curve_qual_dev *= 2.0 / (1.0 + avg_pvop / rc->alt_curve_low_diff); |
|
|
rc->alt_curve_mid_qual = 1.0 - rc->alt_curve_qual_dev * avg_pvop / rc->alt_curve_low_diff; |
|
|
break; |
|
|
case XVID_CURVE_COSINE: // Cosine Curve (low aggressiveness) |
|
|
rc->alt_curve_qual_dev *= 2.0 / (1.0 + (1.0 - cos(DEG2RAD * (avg_pvop * 90.0 / rc->alt_curve_low_diff)))); |
|
|
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))); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
988 |
/* --- */ |
/* --- */ |
989 |
|
|
990 |
total1=total2=0; |
total1=total2=0; |
1001 |
if (s->type == XVID_TYPE_BVOP) |
if (s->type == XVID_TYPE_BVOP) |
1002 |
dbytes *= rc->avg_length[XVID_TYPE_PVOP-1] / rc->avg_length[XVID_TYPE_BVOP-1]; |
dbytes *= rc->avg_length[XVID_TYPE_PVOP-1] / rc->avg_length[XVID_TYPE_BVOP-1]; |
1003 |
|
|
|
if (rc->param.use_alt_curve) { |
|
|
if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { |
|
|
|
|
|
if (dbytes >= rc->alt_curve_high) { |
|
|
dbytes2 = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev); |
|
|
}else{ |
|
|
switch(rc->param.alt_curve_type) { |
|
|
case XVID_CURVE_SINE : |
|
|
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))); |
|
|
break; |
|
|
case XVID_CURVE_LINEAR : |
|
|
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); |
|
|
break; |
|
|
case XVID_CURVE_COSINE : |
|
|
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)))); |
|
|
} |
|
|
} |
|
|
}else{ |
|
|
if (dbytes <= rc->alt_curve_low) { |
|
|
dbytes2 = dbytes; |
|
|
}else{ |
|
|
switch(rc->param.alt_curve_type) { |
|
|
case XVID_CURVE_SINE : |
|
|
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))); |
|
|
break; |
|
|
case XVID_CURVE_LINEAR : |
|
|
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); |
|
|
break; |
|
|
case XVID_CURVE_COSINE : |
|
|
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)))); |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
}else{ |
|
1004 |
if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { |
if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { |
1005 |
dbytes2=((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_high / 100.0); |
dbytes2=((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_high / 100.0); |
1006 |
}else{ |
}else{ |
1007 |
dbytes2 = ((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_low / 100.0); |
dbytes2 = ((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_low / 100.0); |
1008 |
} |
} |
|
} |
|
1009 |
|
|
1010 |
if (s->type == XVID_TYPE_BVOP) { |
if (s->type == XVID_TYPE_BVOP) { |
1011 |
dbytes2 *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; |
dbytes2 *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; |
1021 |
|
|
1022 |
rc->curve_comp_scale = total1 / total2; |
rc->curve_comp_scale = total1 / total2; |
1023 |
|
|
|
if (!rc->param.use_alt_curve) { |
|
1024 |
DPRINTF(XVID_DEBUG_RC, "middle frame size for asymmetric curve compression: %i\n", |
DPRINTF(XVID_DEBUG_RC, "middle frame size for asymmetric curve compression: %i\n", |
1025 |
(int)(rc->avg_length[XVID_TYPE_PVOP-1] * rc->curve_comp_scale)); |
(int)(rc->avg_length[XVID_TYPE_PVOP-1] * rc->curve_comp_scale)); |
|
} |
|
|
|
|
|
if (rc->param.use_alt_curve) { |
|
|
int bonus_bias = rc->param.alt_curve_bonus_bias; |
|
|
int oldquant = 1; |
|
|
|
|
|
if (rc->param.alt_curve_use_auto_bonus_bias) |
|
|
bonus_bias = rc->param.alt_curve_min_rel_qual; |
|
|
|
|
|
rc->alt_curve_curve_bias_bonus = (total1 - total2) * (double)bonus_bias / 100.0 / (double)(rc->num_frames /* - credits_frames */ - rc->num_keyframes); |
|
|
rc->curve_comp_scale = ((total1 - total2) * (1.0 - (double)bonus_bias / 100.0) + total2) / total2; |
|
|
|
|
|
|
|
|
/* special info for alt curve: bias bonus and quantizer thresholds */ |
|
|
|
|
|
DPRINTF(XVID_DEBUG_RC, "avg scaled framesize:%i\n", (int)rc->avg_length[XVID_TYPE_PVOP-1]); |
|
|
DPRINTF(XVID_DEBUG_RC, "bias bonus:%i bytes\n", (int)rc->alt_curve_curve_bias_bonus); |
|
|
|
|
|
for (i=1; i <= (int)(rc->alt_curve_high*2)+1; i++) { |
|
|
double curve_temp, dbytes; |
|
|
int newquant; |
|
|
|
|
|
dbytes = i; |
|
|
if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { |
|
|
if (dbytes >= rc->alt_curve_high) { |
|
|
curve_temp = dbytes * (rc->alt_curve_mid_qual - rc->alt_curve_qual_dev); |
|
|
}else{ |
|
|
switch(rc->param.alt_curve_type) |
|
|
{ |
|
|
case XVID_CURVE_SINE : |
|
|
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))); |
|
|
break; |
|
|
case XVID_CURVE_LINEAR : |
|
|
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); |
|
|
break; |
|
|
case XVID_CURVE_COSINE : |
|
|
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)))); |
|
|
} |
|
|
} |
|
|
}else{ |
|
|
if (dbytes <= rc->alt_curve_low) { |
|
|
curve_temp = dbytes; |
|
|
}else{ |
|
|
switch(rc->param.alt_curve_type) |
|
|
{ |
|
|
case XVID_CURVE_SINE : |
|
|
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))); |
|
|
break; |
|
|
case XVID_CURVE_LINEAR : |
|
|
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); |
|
|
break; |
|
|
case XVID_CURVE_COSINE : |
|
|
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)))); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
if (rc->movie_curve > 1.0) |
|
|
dbytes *= rc->movie_curve; |
|
|
|
|
|
newquant = (int)(dbytes * 2.0 / (curve_temp * rc->curve_comp_scale + rc->alt_curve_curve_bias_bonus)); |
|
|
if (newquant > 1) { |
|
|
if (newquant != oldquant) { |
|
|
int percent = (int)((i - rc->avg_length[XVID_TYPE_PVOP-1]) * 100.0 / rc->avg_length[XVID_TYPE_PVOP-1]); |
|
|
oldquant = newquant; |
|
|
DPRINTF(XVID_DEBUG_RC, "quant:%i threshold at %i : %i percent\n", newquant, i, percent); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
1026 |
|
|
1027 |
rc->overflow = 0; |
rc->overflow = 0; |
1028 |
rc->KFoverflow = 0; |
rc->KFoverflow = 0; |