On Thu, 2011-08-25 at 08:36 +0200, madshi wrote:
> > The current code in swscale is based on how 8-bit to
> > 16-bit YUV conversions have been done earlier - basically
> > duplicating each input byte in the output (e.g. 0xf0 -> 0xf0f0,
> > 0x65 -> 0x6565). I believe this is the right thing for full
> > range content.
> 
> Not necessarily. If you upscale like that, smooth gradiants
> will not be perfectly smooth, anymore.

Gradients are perfectly smooth for a 8->16 conversion like that. You
seem to be assuming the special case of a 8->10 conversion done by
shifting out the lowest bits of the 16-bit value again.

>  IMHO, there are three
> ways to upscale full range content:
> 
> (1) 10bit = 8bit << 2
> (2) 10bit = round(8bit * 1023 / 255)  (similar to byte duplicating)
> (3) 10bit = dither(8bit * 1023 / 255)
> 
> Solution (1) keeps gradiants smooth, but loses a bit of
> dynamic range. Solution (2) maintains full dynamic range,
> but gradiants are not perfectly smooth, anymore. Solution
> (3) keep gradiants smooth *and* maintains full dynamic
> range. However, if you try to compress (3), compression
> efficiency will go down due to the dither noise. Also (3) will
> perform slowest, of course.
> 
> My personal favorites are either (1) or (3), while swscale
> currently does (2).

swscale does no "/ 255" stuff AFAIK. If "byte duplication" is used
that's multiplication by 257; corresponding 8->10 conversion would be
multiplication by 257/64, not 1023/255 (these won't produce exactly the
same results even if the former is rounded down and the latter to
nearest).

> Furthermore, the chroma channel needs to be scaled
> with signed math, to make sure that 8bit 128 gets properly
> scaled to 10bit 512. If you use (1), though, signed math
> is not necessary.

By "signed math" I assume you mean something like C*(x-128)+512 instead
of what you wrote in (2)/(3) (at least that would be the most correct
way - implementing it does not actually require using signed arithmetic
though). But note that different chroma ranges actually have different
_shapes_ in the sense that the "neutral point" is a different portion of
the range away from the absolute middle of the range (it's always +0.5
absolute units off from the middle, but that's a smaller portion of the
range for larger ranges). No value of C in the above will produce
exactly the full dynamic range from 0 to 1023: if you make C large
enough to produce 1023 at the top end then the bottom will be below 0
already.


_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to