From: Steinar H. Gunderson Date: Thu, 21 Apr 2016 13:58:20 +0000 (+0200) Subject: Switch to exponential interpolation between presets. X-Git-Url: https://git.sesse.net/?p=x264;a=commitdiff_plain;h=64db190d1157916a75656101fdf51e6bd00ba6e3 Switch to exponential interpolation between presets. The preset timings mostly grow in an exponential fashion, not linear, and as such, interpolation should be exponential, too. More importantly, this changes extrapolation to be exponential. This fixes an issue where the chosen preset goes way out of range: If the picture has been at very low complexity, we would have a very high target (say, 10000 seconds), which due to linear interpolation would choose a way too high preset (say, preset 5000 out of 25). This would completely drown out the controller responsible for turning down the preset based on the queue length alone; even though it would subtract e.g. 20 levels from the chosen preset, still preset 4980 would we be chosen, and effectively, we'd oscillate between the highest and the lowest presets all the time. As an extra precaution, we cap the chosen preset to five levels of extrapolation. This makes us less sensitive to choosing a max_presets where the last two entries are not that far apart (throwing the extrapolation off). --- diff --git a/encoder/speed.c b/encoder/speed.c index c59f2c7f..4f67640d 100644 --- a/encoder/speed.c +++ b/encoder/speed.c @@ -105,6 +105,10 @@ typedef struct // on top of the given settings (equivalent settings to the "faster" preset). // Timings and SSIM measurements were done on a quadcore Haswell i5 3.2 GHz // on the first 1000 frames of "Tears of Steel" in 1080p. +// +// Note that the two first and the two last are also used for extrapolation +// should the desired time be outside the range. Thus, it is disadvantageous if +// they are chosen so that the timings are too close to each other. static const sc_preset_t presets[SC_PRESETS] = { #define I4 X264_ANALYSE_I4x4 #define I8 X264_ANALYSE_I8x8 @@ -307,8 +311,9 @@ void x264_speedcontrol_frame( x264_t *h ) break; t0 = t1; } - // linear interpolation between states - set = i-1 + (target - t0) / (t1 - t0); + // exponential interpolation between states + set = i-1 + (log(target) - log(t0)) / (log(t1) - log(t0)); + set = x264_clip3f( set, -5, (SC_PRESETS-1) + 5 ); // Even if our time estimations in the SC_PRESETS array are off // this will push us towards our target fullness set += (40 * (filled-0.75));