[MPlayer-dev-eng] Changing the weight functions in the opengl bicubic scaler?

Thomas Lindroth thomas.lindroth at gmail.com
Fri Jun 3 22:42:06 CEST 2011


I tried to use the bicubic filter with the opengl output (-vo
gl:yuv=3:lscale=1:cscale=1) and noticed the result is very smooth. The
software implementation (sws) got parameters that can be tweaked so I
checked the code to see which parameters are used by the gl code. The
relevant code is in libvo/gl_common.c store_weights and by calculating
backwards I found out that the parameters are B (blurring) = 1 and C
(ringing) = 0 that corresponds to a cubic B-spline filter.

The cubic B-spline filter give very blurry output and it modifies the
output even when the output size is the same as the input causing the
video to be blurry even when playing at native resolution in a window.
The software implementation's default parameters are B = 0, C = 0.6 and
that looks a lot better imho.

I tried to fix this by calculating new weights with B = 0, C = 0.5 and
got these new values:
  float w0 = (((-3 * x + 6 ) * x - 3) * x + 0) / 6;
  float w1 = ((( 9 * x - 15) * x + 0) * x + 6) / 6;
  float w2 = (((-9 * x + 12) * x + 3) * x + 0) / 6;
  float w3 = ((( 3 * x - 3 ) * x + 0) * x + 0) / 6;
but when I substitute in my new values I get a filter that looks a lot
like bilinear scaling. I can't figure out where things go wrong. It's
been a while since I last took a course in signal theory so I might have
misunderstood something. My calculations are at the bottom. The equation
for the filter function k(x) comes from the paper "Reconstruction
Filters in Computer Graphics, Don P. Mitchell, Arun N. Netravali (1988)"

Mplayer's gl implementation use some kind of clever trick where 4 texel
lookups can be replaced with 2 filtered texture lookups. It's described
here http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter20.html
(yes, the url is suppose to look like that). I don't understand how it
works but it might make assumptions that are only true for a B-spline
filter. Some help sorting this thing out would be appreciated.

While digging I also found a bug in the scaler. The right and bottom
border pixels are always black.
gl: http://oi55.tinypic.com/2znn5th.jpg
sws with B=1,C=0: http://oi54.tinypic.com/282hwlv.jpg


Calculations:
=====================================================================
Current filter  B=1, C=0
k(x)=((12 - 9 * B - 6 * C) * x * x * x +
     (-18 + 12 * B + 6 * C) * x * x +
     (6 - 2 * B)) / 6  when x < 1
k(x) = ((-B - 6 * C) * x * x * x +
       (6 * B + 30 * C) * x * x +
       (-12 * B - 48 * C) * x +
       (8 * B + 24 * C)) / 6  when 1 < x < 2
k(x) = 0 when x < 2


  x < 1
((12 - 9 * 1 - 6 * 0) * x * x * x +
(-18 + 12 * 1 + 6 * 0) * x * x +
(6 - 2 * 1)) / 6 = (4 + 3 (-2 + x) x^2) / 6
  1 < x < 2
((-1 - 6 * 0) * x * x * x +
(6 * 1 + 30 * 0) * x * x +
(-12 * 1 - 48 * 0) * x +
(8 * 1 + 24 * 0)) / 6 = (-x^3+6 x^2-12 x+8) / 6

  w0(x) = k((x+1))  	when 1 < x < 2
  w1(x) = k(x)		when x < 1
  w2(x) = k(1-x)	when x < 1
  w3(x) = k(2-x)	when 1 < x < 2

w0 = (-(x+1)^3+6 (x+1)^2-12 (x+1)+8) / 6 = (((-1*x+3)*x-3)*x+1) / 6
w1 = (4 + 3 (-2 + x) x^2) / 6 =            (((3*x-6)*x+0)*x+4) / 6
w2 = (4 + 3 (-2 + (1-x)) (1-x)^2) / 6 =    (((-3*x+3)*x+3)*x+1) / 6
w3 = (-(2-x)^3+6 (2-x)^2-12 (2-x)+8) / 6 = (((1*x+0)*x+0)*x+0) / 6
  Calculated weights match current implementation
=====================================================================
NEW  B=0, C=0.5
k(x)=((12 - 9 * B - 6 * C) * x * x * x +
     (-18 + 12 * B + 6 * C) * x * x +
     (6 - 2 * B)) / 6  when x < 1
k(x) = ((-B - 6 * C) * x * x * x +
       (6 * B + 30 * C) * x * x +
       (-12 * B - 48 * C) * x +
       (8 * B + 24 * C)) / 6  when 1 < x < 2
k(x) = 0 when x < 2

  x < 1
((12 - 9 * 0 - 6 * 0.5) * x * x * x +
(-18 + 12 * 0 + 6 * 0.5) * x * x +
(6 - 2 * 0)) / 6 = (9x^3 -15x^2 + 6) / 6
  1 < x < 2
((-0 - 6 * 0.5) * x * x * x +
(6 * 0 + 30 * 0.5) * x * x +
(-12 * 0 - 48 * 0.5) * x +
(8 * 0 + 24 * 0.5)) / 6 = (-3x^3 + 15x^2 - 24x + 12) / 6


  w0(x) = k((x+1))  	when 1 < x < 2
  w1(x) = k(x)		when x < 1
  w2(x) = k(1-x)	when x < 1
  w3(x) = k(2-x)	when 1 < x < 2

w0 = (-3(x+1)^3 + 15(x+1)^2 - 24(x+1) + 12) / 6 = (-3x^3+6x^2-3x) / 6
w1 = (9x^3 -15x^2 + 6) / 6
w2 = (9(1-x)^3 -15(1-x)^2 + 6) / 6 = (-9x^3+12x^2+3x) / 6
w3 = (-3(2-x)^3 + 15(2-x)^2 - 24(2-x) + 12) / 6 = (3x^3-3x^2) / 6

float w0 = (((-3 * x + 6 ) * x - 3) * x + 0) / 6;
float w1 = ((( 9 * x - 15) * x + 0) * x + 6) / 6;
float w2 = (((-9 * x + 12) * x + 3) * x + 0) / 6;
float w3 = ((( 3 * x - 3 ) * x + 0) * x + 0) / 6;


/Thomas Lindroth


More information about the MPlayer-dev-eng mailing list