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.21 2003-06-10 10:12:24 suxen_drol Exp $ |
29 |
* |
* |
30 |
*****************************************************************************/ |
*****************************************************************************/ |
31 |
|
|
244 |
} |
} |
245 |
|
|
246 |
/* Compute the target filesize */ |
/* Compute the target filesize */ |
247 |
if (rc->num_frames < create->fbase/create->fincr) { |
if (rc->param.bitrate<0) { |
248 |
|
/* if negative, bitrate equals the target (int kbytes) */ |
249 |
|
rc->target = (-rc->param.bitrate) * 1024; |
250 |
|
|
251 |
|
}else if (rc->num_frames < create->fbase/create->fincr) { |
252 |
/* Source sequence is less than 1s long, we do as if it was 1s long */ |
/* Source sequence is less than 1s long, we do as if it was 1s long */ |
253 |
rc->target = rc->param.bitrate / 8; |
rc->target = rc->param.bitrate / 8; |
254 |
} else { |
} else { |
361 |
if (data->frame_num >= rc->num_frames) |
if (data->frame_num >= rc->num_frames) |
362 |
return 0; |
return 0; |
363 |
|
|
|
/* |
|
|
* The last case is the one every normal minded developer should fear to |
|
|
* maintain in a project :-) |
|
|
*/ |
|
|
|
|
364 |
/* XXX: why by 8 */ |
/* XXX: why by 8 */ |
365 |
overflow = rc->overflow / 8; |
overflow = rc->overflow / 8; |
366 |
|
|
379 |
dbytes /= rc->movie_curve; |
dbytes /= rc->movie_curve; |
380 |
|
|
381 |
/* |
/* |
|
* 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]; |
|
|
|
|
|
/* |
|
382 |
* Apply user's choosen Payback method. Payback helps bitrate to follow the |
* Apply user's choosen Payback method. Payback helps bitrate to follow the |
383 |
* scaled curve "paying back" past errors in curve previsions. |
* scaled curve "paying back" past errors in curve previsions. |
384 |
*/ |
*/ |
386 |
desired = (int)(rc->curve_comp_error / rc->param.bitrate_payback_delay); |
desired = (int)(rc->curve_comp_error / rc->param.bitrate_payback_delay); |
387 |
} else { |
} else { |
388 |
desired = (int)(rc->curve_comp_error * dbytes / |
desired = (int)(rc->curve_comp_error * dbytes / |
389 |
rc->avg_length[XVID_TYPE_PVOP-1] / rc->param.bitrate_payback_delay); |
rc->avg_length[s->type-1] / rc->param.bitrate_payback_delay); |
390 |
|
|
391 |
if (labs(desired) > fabs(rc->curve_comp_error)) { |
if (labs(desired) > fabs(rc->curve_comp_error)) |
392 |
desired = (int)rc->curve_comp_error; |
desired = (int)rc->curve_comp_error; |
393 |
} |
} |
|
} |
|
394 |
|
|
395 |
rc->curve_comp_error -= desired; |
rc->curve_comp_error -= desired; |
396 |
|
|
400 |
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) { |
401 |
|
|
402 |
curve_temp = rc->curve_comp_scale; |
curve_temp = rc->curve_comp_scale; |
403 |
if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { |
if (dbytes > rc->avg_length[s->type-1]) { |
404 |
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); |
405 |
} else { |
} else { |
406 |
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); |
407 |
} |
} |
408 |
|
|
|
/* |
|
|
* 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]; |
|
|
|
|
409 |
desired += (int)curve_temp; |
desired += (int)curve_temp; |
410 |
rc->curve_comp_error += curve_temp - (int)curve_temp; |
rc->curve_comp_error += curve_temp - (int)curve_temp; |
411 |
} 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]; |
|
|
|
|
412 |
desired += (int)dbytes; |
desired += (int)dbytes; |
413 |
rc->curve_comp_error += dbytes - (int)dbytes; |
rc->curve_comp_error += dbytes - (int)dbytes; |
414 |
} |
} |
433 |
|
|
434 |
s->desired_length = desired; |
s->desired_length = desired; |
435 |
|
|
|
|
|
436 |
/* |
/* |
437 |
* 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 |
438 |
* XXX: why do we do this after setting the desired length ? |
* XXX: why do we do this after setting the desired length ? |
461 |
} |
} |
462 |
} |
} |
463 |
|
|
464 |
|
/* |
465 |
|
* The "sens commun" would force us to use rc->avg_length[s->type-1] but |
466 |
|
* even VFW code uses the pframe average length. Note that this length is |
467 |
|
* used with desired which represents bframes _and_ pframes length. |
468 |
|
* |
469 |
|
* XXX: why are we using the avg pframe length for all frame types ? |
470 |
|
*/ |
471 |
overflow = (int)((double)overflow * desired / rc->avg_length[XVID_TYPE_PVOP-1]); |
overflow = (int)((double)overflow * desired / rc->avg_length[XVID_TYPE_PVOP-1]); |
472 |
|
|
473 |
/* Reign in overflow with huge frames */ |
/* Reign in overflow with huge frames */ |
577 |
if (capped_to_max_framesize == 0) |
if (capped_to_max_framesize == 0) |
578 |
rc->last_quant[s->type-1] = data->quant; |
rc->last_quant[s->type-1] = data->quant; |
579 |
|
|
580 |
|
/* Force frame type */ |
581 |
|
data->type = s->type; |
582 |
|
|
583 |
return 0; |
return 0; |
584 |
} |
} |
585 |
|
|
604 |
rc->overflow += rc->KFoverflow; |
rc->overflow += rc->KFoverflow; |
605 |
rc->KFoverflow = s->desired_length - data->length; |
rc->KFoverflow = s->desired_length - data->length; |
606 |
|
|
607 |
if (kfdiff > 1) { // non-consecutive keyframes |
if (kfdiff > 1) { /* non-consecutive keyframes */ |
608 |
rc->KFoverflow_partial = rc->KFoverflow / (kfdiff - 1); |
rc->KFoverflow_partial = rc->KFoverflow / (kfdiff - 1); |
609 |
}else{ // consecutive keyframes |
}else{ /* consecutive keyframes */ |
610 |
rc->overflow += rc->KFoverflow; |
rc->overflow += rc->KFoverflow; |
611 |
rc->KFoverflow = 0; |
rc->KFoverflow = 0; |
612 |
rc->KFoverflow_partial = 0; |
rc->KFoverflow_partial = 0; |
613 |
} |
} |
614 |
rc->KF_idx++; |
rc->KF_idx++; |
615 |
} else { |
} else { |
616 |
// distribute part of the keyframe overflow |
/* distribute part of the keyframe overflow */ |
617 |
rc->overflow += s->desired_length - data->length + rc->KFoverflow_partial; |
rc->overflow += s->desired_length - data->length + rc->KFoverflow_partial; |
618 |
rc->KFoverflow -= rc->KFoverflow_partial; |
rc->KFoverflow -= rc->KFoverflow_partial; |
619 |
} |
} |
700 |
}else if (type == 'b') { |
}else if (type == 'b') { |
701 |
s->type = XVID_TYPE_BVOP; |
s->type = XVID_TYPE_BVOP; |
702 |
}else{ /* unknown type */ |
}else{ /* unknown type */ |
703 |
DPRINTF(XVID_DEBUG_RC, "unknown stats frame type; assuming pvop\n"); |
DPRINTF(XVID_DEBUG_RC, "WARNING: unknown stats frame type, assuming pvop\n"); |
704 |
s->type = XVID_TYPE_PVOP; |
s->type = XVID_TYPE_PVOP; |
705 |
} |
} |
706 |
|
|
830 |
next -= create->zones[i].frame; |
next -= create->zones[i].frame; |
831 |
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; |
832 |
n += next; |
n += next; |
833 |
}else{ // XVID_ZONE_QUANT |
}else{ /* XVID_ZONE_QUANT */ |
834 |
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++ ) { |
835 |
rc->stats[j].zone_mode = XVID_ZONE_QUANT; |
rc->stats[j].zone_mode = XVID_ZONE_QUANT; |
836 |
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; |
986 |
dbytes = s->scaled_length / rc->movie_curve; |
dbytes = s->scaled_length / rc->movie_curve; |
987 |
dbytes2 = 0; /* XXX: warning */ |
dbytes2 = 0; /* XXX: warning */ |
988 |
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]; |
|
989 |
|
|
990 |
if (dbytes > rc->avg_length[XVID_TYPE_PVOP-1]) { |
if (dbytes > rc->avg_length[s->type-1]) { |
991 |
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); |
992 |
} else { |
} else { |
993 |
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); |
994 |
} |
} |
995 |
|
|
996 |
if (s->type == XVID_TYPE_BVOP) { |
if (dbytes2 < rc->min_length[s->type-1]) |
997 |
dbytes2 *= rc->avg_length[XVID_TYPE_BVOP-1] / rc->avg_length[XVID_TYPE_PVOP-1]; |
dbytes2 = rc->min_length[s->type-1]; |
998 |
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]; |
|
|
} |
|
999 |
total2 += dbytes2; |
total2 += dbytes2; |
1000 |
} |
} |
1001 |
} |
} |
1002 |
|
|
1003 |
rc->curve_comp_scale = total1 / total2; |
rc->curve_comp_scale = total1 / total2; |
1004 |
|
|
1005 |
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", |
1006 |
(int)(rc->avg_length[XVID_TYPE_PVOP-1] * rc->curve_comp_scale)); |
(int)(rc->avg_length[XVID_TYPE_PVOP-1] * rc->curve_comp_scale), |
1007 |
|
(int)(rc->avg_length[XVID_TYPE_BVOP-1] * rc->curve_comp_scale)); |
1008 |
|
|
1009 |
rc->overflow = 0; |
rc->overflow = 0; |
1010 |
rc->KFoverflow = 0; |
rc->KFoverflow = 0; |