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.16 2003-05-29 12:38:44 edgomez Exp $ |
* $Id: plugin_2pass2.c,v 1.1.2.20 2003-06-09 13:55:07 edgomez Exp $ |
29 |
* |
* |
30 |
*****************************************************************************/ |
*****************************************************************************/ |
31 |
|
|
357 |
if (data->frame_num >= rc->num_frames) |
if (data->frame_num >= rc->num_frames) |
358 |
return 0; |
return 0; |
359 |
|
|
|
/* |
|
|
* The last case is the one every normal minded developer should fear to |
|
|
* maintain in a project :-) |
|
|
*/ |
|
|
|
|
360 |
/* XXX: why by 8 */ |
/* XXX: why by 8 */ |
361 |
overflow = rc->overflow / 8; |
overflow = rc->overflow / 8; |
362 |
|
|
375 |
dbytes /= rc->movie_curve; |
dbytes /= rc->movie_curve; |
376 |
|
|
377 |
/* |
/* |
|
* We are now entering in the hard part of the algo, it was first designed |
|
|
* to work with i/pframes only streams, so the way it computes things is |
|
|
* adapted to pframes only. However we can use it if we just take care to |
|
|
* scale the bframes sizes to pframes sizes using the ratio avg_p/avg_p and |
|
|
* then before really using values depending on frame sizes, scaling the |
|
|
* value again with the inverse ratio |
|
|
*/ |
|
|
if (s->type == XVID_TYPE_BVOP) |
|
|
dbytes *= rc->avg_length[XVID_TYPE_PVOP-1] / rc->avg_length[XVID_TYPE_BVOP-1]; |
|
|
|
|
|
/* |
|
378 |
* Apply user's choosen Payback method. Payback helps bitrate to follow the |
* Apply user's choosen Payback method. Payback helps bitrate to follow the |
379 |
* scaled curve "paying back" past errors in curve previsions. |
* scaled curve "paying back" past errors in curve previsions. |
380 |
*/ |
*/ |
382 |
desired = (int)(rc->curve_comp_error / rc->param.bitrate_payback_delay); |
desired = (int)(rc->curve_comp_error / rc->param.bitrate_payback_delay); |
383 |
} else { |
} else { |
384 |
desired = (int)(rc->curve_comp_error * dbytes / |
desired = (int)(rc->curve_comp_error * dbytes / |
385 |
rc->avg_length[XVID_TYPE_PVOP-1] / rc->param.bitrate_payback_delay); |
rc->avg_length[s->type-1] / rc->param.bitrate_payback_delay); |
386 |
|
|
387 |
if (labs(desired) > fabs(rc->curve_comp_error)) { |
if (labs(desired) > fabs(rc->curve_comp_error)) |
388 |
desired = (int)rc->curve_comp_error; |
desired = (int)rc->curve_comp_error; |
389 |
} |
} |
|
} |
|
390 |
|
|
391 |
rc->curve_comp_error -= desired; |
rc->curve_comp_error -= desired; |
392 |
|
|
396 |
if ((rc->param.curve_compression_high + rc->param.curve_compression_low) && s->type != XVID_TYPE_IVOP) { |
if ((rc->param.curve_compression_high + rc->param.curve_compression_low) && s->type != XVID_TYPE_IVOP) { |
397 |
|
|
398 |
curve_temp = rc->curve_comp_scale; |
curve_temp = rc->curve_comp_scale; |
399 |
if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { |
if (dbytes > rc->avg_length[s->type-1]) { |
400 |
curve_temp *= ((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_high / 100.0); |
curve_temp *= ((double)dbytes + (rc->avg_length[s->type-1] - dbytes) * rc->param.curve_compression_high / 100.0); |
401 |
} else { |
} else { |
402 |
curve_temp *= ((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_low / 100.0); |
curve_temp *= ((double)dbytes + (rc->avg_length[s->type-1] - dbytes) * rc->param.curve_compression_low / 100.0); |
403 |
} |
} |
404 |
|
|
|
/* |
|
|
* 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]; |
|
|
|
|
405 |
desired += (int)curve_temp; |
desired += (int)curve_temp; |
406 |
rc->curve_comp_error += curve_temp - (int)curve_temp; |
rc->curve_comp_error += curve_temp - (int)curve_temp; |
407 |
} else { |
} 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]; |
|
|
|
|
408 |
desired += (int)dbytes; |
desired += (int)dbytes; |
409 |
rc->curve_comp_error += dbytes - (int)dbytes; |
rc->curve_comp_error += dbytes - (int)dbytes; |
410 |
} |
} |
429 |
|
|
430 |
s->desired_length = desired; |
s->desired_length = desired; |
431 |
|
|
|
|
|
432 |
/* |
/* |
433 |
* if this keyframe is too close to the next, reduce it's byte allotment |
* if this keyframe is too close to the next, reduce it's byte allotment |
434 |
* XXX: why do we do this after setting the desired length ? |
* XXX: why do we do this after setting the desired length ? |
457 |
} |
} |
458 |
} |
} |
459 |
|
|
460 |
|
/* |
461 |
|
* The "sens commun" would force us to use rc->avg_length[s->type-1] but |
462 |
|
* even VFW code uses the pframe average length. Note that this length is |
463 |
|
* used with desired which represents bframes _and_ pframes length. |
464 |
|
* |
465 |
|
* XXX: why are we using the avg pframe length for all frame types ? |
466 |
|
*/ |
467 |
overflow = (int)((double)overflow * desired / rc->avg_length[XVID_TYPE_PVOP-1]); |
overflow = (int)((double)overflow * desired / rc->avg_length[XVID_TYPE_PVOP-1]); |
468 |
|
|
469 |
/* Reign in overflow with huge frames */ |
/* Reign in overflow with huge frames */ |
573 |
if (capped_to_max_framesize == 0) |
if (capped_to_max_framesize == 0) |
574 |
rc->last_quant[s->type-1] = data->quant; |
rc->last_quant[s->type-1] = data->quant; |
575 |
|
|
576 |
|
/* Force frame type */ |
577 |
|
data->type = s->type; |
578 |
|
|
579 |
return 0; |
return 0; |
580 |
} |
} |
581 |
|
|
600 |
rc->overflow += rc->KFoverflow; |
rc->overflow += rc->KFoverflow; |
601 |
rc->KFoverflow = s->desired_length - data->length; |
rc->KFoverflow = s->desired_length - data->length; |
602 |
|
|
603 |
if (kfdiff > 1) { // non-consecutive keyframes |
if (kfdiff > 1) { /* non-consecutive keyframes */ |
604 |
rc->KFoverflow_partial = rc->KFoverflow / (kfdiff - 1); |
rc->KFoverflow_partial = rc->KFoverflow / (kfdiff - 1); |
605 |
}else{ // consecutive keyframes |
}else{ /* consecutive keyframes */ |
606 |
rc->overflow += rc->KFoverflow; |
rc->overflow += rc->KFoverflow; |
607 |
rc->KFoverflow = 0; |
rc->KFoverflow = 0; |
608 |
rc->KFoverflow_partial = 0; |
rc->KFoverflow_partial = 0; |
609 |
} |
} |
610 |
rc->KF_idx++; |
rc->KF_idx++; |
611 |
} else { |
} else { |
612 |
// distribute part of the keyframe overflow |
/* distribute part of the keyframe overflow */ |
613 |
rc->overflow += s->desired_length - data->length + rc->KFoverflow_partial; |
rc->overflow += s->desired_length - data->length + rc->KFoverflow_partial; |
614 |
rc->KFoverflow -= rc->KFoverflow_partial; |
rc->KFoverflow -= rc->KFoverflow_partial; |
615 |
} |
} |
696 |
}else if (type == 'b') { |
}else if (type == 'b') { |
697 |
s->type = XVID_TYPE_BVOP; |
s->type = XVID_TYPE_BVOP; |
698 |
}else{ /* unknown type */ |
}else{ /* unknown type */ |
699 |
DPRINTF(XVID_DEBUG_RC, "unknown stats frame type; assuming pvop\n"); |
DPRINTF(XVID_DEBUG_RC, "WARNING: unknown stats frame type, assuming pvop\n"); |
700 |
s->type = XVID_TYPE_PVOP; |
s->type = XVID_TYPE_PVOP; |
701 |
} |
} |
702 |
|
|
826 |
next -= create->zones[i].frame; |
next -= create->zones[i].frame; |
827 |
rc->avg_weight += (double)(next * create->zones[i].increment) / (double)create->zones[i].base; |
rc->avg_weight += (double)(next * create->zones[i].increment) / (double)create->zones[i].base; |
828 |
n += next; |
n += next; |
829 |
}else{ // XVID_ZONE_QUANT |
}else{ /* XVID_ZONE_QUANT */ |
830 |
for (j = create->zones[i].frame; j < next && j < rc->num_frames; j++ ) { |
for (j = create->zones[i].frame; j < next && j < rc->num_frames; j++ ) { |
831 |
rc->stats[j].zone_mode = XVID_ZONE_QUANT; |
rc->stats[j].zone_mode = XVID_ZONE_QUANT; |
832 |
rc->stats[j].weight = (double)create->zones[i].increment / (double)create->zones[i].base; |
rc->stats[j].weight = (double)create->zones[i].increment / (double)create->zones[i].base; |
982 |
dbytes = s->scaled_length / rc->movie_curve; |
dbytes = s->scaled_length / rc->movie_curve; |
983 |
dbytes2 = 0; /* XXX: warning */ |
dbytes2 = 0; /* XXX: warning */ |
984 |
total1 += dbytes; |
total1 += dbytes; |
|
if (s->type == XVID_TYPE_BVOP) |
|
|
dbytes *= rc->avg_length[XVID_TYPE_PVOP-1] / rc->avg_length[XVID_TYPE_BVOP-1]; |
|
985 |
|
|
986 |
if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { |
if (dbytes > rc->avg_length[s->type-1]) { |
987 |
dbytes2=((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_high / 100.0); |
dbytes2=((double)dbytes + (rc->avg_length[s->type-1] - dbytes) * rc->param.curve_compression_high / 100.0); |
988 |
} else { |
} else { |
989 |
dbytes2 = ((double)dbytes + (rc->avg_length[XVID_TYPE_PVOP-1] - dbytes) * rc->param.curve_compression_low / 100.0); |
dbytes2 = ((double)dbytes + (rc->avg_length[s->type-1] - dbytes) * rc->param.curve_compression_low / 100.0); |
990 |
} |
} |
991 |
|
|
992 |
if (s->type == XVID_TYPE_BVOP) { |
if (dbytes2 < rc->min_length[s->type-1]) |
993 |
dbytes2 *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; |
dbytes2 = rc->min_length[s->type-1]; |
994 |
if (dbytes2 < rc->min_length[XVID_TYPE_BVOP-1]) |
|
|
dbytes2 = rc->min_length[XVID_TYPE_BVOP-1]; |
|
|
}else{ |
|
|
if (dbytes2 < rc->min_length[XVID_TYPE_PVOP-1]) |
|
|
dbytes2 = rc->min_length[XVID_TYPE_PVOP-1]; |
|
|
} |
|
995 |
total2 += dbytes2; |
total2 += dbytes2; |
996 |
} |
} |
997 |
} |
} |
998 |
|
|
999 |
rc->curve_comp_scale = total1 / total2; |
rc->curve_comp_scale = total1 / total2; |
1000 |
|
|
1001 |
DPRINTF(XVID_DEBUG_RC, "middle frame size for asymmetric curve compression: %i\n", |
DPRINTF(XVID_DEBUG_RC, "middle frame size for asymmetric curve compression: pframe%d bframe:%d\n", |
1002 |
(int)(rc->avg_length[XVID_TYPE_PVOP-1] * rc->curve_comp_scale)); |
(int)(rc->avg_length[XVID_TYPE_PVOP-1] * rc->curve_comp_scale), |
1003 |
|
(int)(rc->avg_length[XVID_TYPE_BVOP-1] * rc->curve_comp_scale)); |
1004 |
|
|
1005 |
rc->overflow = 0; |
rc->overflow = 0; |
1006 |
rc->KFoverflow = 0; |
rc->KFoverflow = 0; |