Kodi Community Forum

Full Version: Intel VAAPI howto with Leia v18 nightly based on Ubuntu 18.04 server
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Kodi either renders the GUI in limited Range RGB (produced from a full range RGB, it's explicitely scaled). For Video it converts NV12 to either Limited RGB directly (1:1) or to full range. When doing the full range conversion it needs to extend the 16-235 to 0..255 so that's where dithering makes a lot of sense.

So, if you want to enjoy the gui in full range and you are fine with the quality of our "up" dithering. Option 2 is a good way to go.

Banding is quite clear, nothing to do with maths rouding. If you want a gray ramp over 255 values, but only have 219 values, you will introduce "steps" - that's why dithering needs to be applied.

Option 2 is especially great for pictures as they are full range RGB. For WTW and BTB those only work in Limited Range Mode. For my part I don't really care. The only reason I use Limited Range output here is, that my old AVR cuts off the 0 to 15 and 235 to 255 when I send through Full Range RGB.
Thanks for the detailed reply.

(2016-11-25, 08:07)fritsch Wrote: [ -> ]Banding is quite clear, nothing to do with maths rouding. If you want a gray ramp over 255 values, but only have 219 values, you will introduce "steps" - that's why dithering needs to be applied.

For lack of a better analogy, wouldn't scaling the color space be like upscaling video? Spreading 219 discrete values into 255 slots seems like nearest neighbor upscaling. Wouldn't it be better to interpolate the 219 values across the 255 bits, such as converting the 219 values to 16-bit (or whatever), interpolate the other 65k+ values and downscale to 8-bit?

If we are stuck with "nearest neighbor" grayscale scaling (e.g. for performance reasons), can we avoid dithering if we're fortunate enough to own a 10-bit television? I haven't fully thought it out, but 219 values into 1024 seems like it would have less banding than whatever is inherently in the 8-bit content.
I think you mix a lot of things here ...

the problem is in full range 0 == black and 16 is dark grey, 255 is white and 235 is light grey. Now if you have an image of width 235px, with pixel 0 is 16 and pixel 235 is 235. How would you get that to 0 .. 255 without seeing banding?

Let's do by example, assume we have limited fritsch10 range and full fritsch10 range, meaning: limited fritsch10 range is 2 .. 8 and fritsch10 full range is 0 .. 10.

Now you get the following picture (a nice grey ramp in fritsch10 limited format):
Code:
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8

What would you now do with it in order to have 2 at 0 and 8 at 10, but you only have 7 values?
(2016-11-25, 08:07)fritsch Wrote: [ -> ]Kodi either renders the GUI in limited Range RGB (produced from a full range RGB, it's explicitely scaled). For Video it converts NV12 to either Limited RGB directly (1:1) or to full range. When doing the full range conversion it needs to extend the 16-235 to 0..255 so that's where dithering makes a lot of sense.

So, if you want to enjoy the gui in full range and you are fine with the quality of our "up" dithering. Option 2 is a good way to go.

Banding is quite clear, nothing to do with maths rouding. If you want a gray ramp over 255 values, but only have 219 values, you will introduce "steps" - that's why dithering needs to be applied.

Option 2 is especially great for pictures as they are full range RGB. For WTW and BTB those only work in Limited Range Mode. For my part I don't really care. The only reason I use Limited Range output here is, that my old AVR cuts off the 0 to 15 and 235 to 255 when I send through Full Range RGB.

Thanks fritsch for clearing up this again (for so many times). Since I don't care too much about pictures, and the gui in full range, I want the best possible quality for video, it looks that Option 1 is the way to go for me. As you say: " For Video it converts NV12 to either Limited RGB directly (1:1) or to full range." -> video is converted from NV12 to Limited RGB directly, and therefore there is no dithering required, in my understanding this would produce the least conversion of the source material.

Just to reflect on your patched Kernel with passtrough: if the TV supports both Option 1 and Option 2, then there is no need to use your patched Kernel, or there might be some quality gain compared to Option 1?
The problem is again highly hw dependend.

My patch has the nice advantage that it signals correctly limited range to the TV. So it can stay in that range and all the data send through it are kept as is -> 1:1 video colors -> TV mapping. Cause some TVs simply can't do full range RGB. Disadvantage: Everything else: GUI, Pictures are scaled from full to limited to match.

I personally use (with my new AVR): Full Range (Intel) + Full Range Kodi + 8 bit dithering on a Samsung UHD TV where I have set the black value to "Normal" which reflects full range with samungs. With that setup I can have full range pictures and for video I am satisfied with the limited to full range scaling + dithering. Looking perfect and fits my needs. I don't care about BTB and WTW. So Black is 0 here and BTB also ends up in 0.

On my old setup I used the limited path though to workaround my AVR ... kodi is not only a video player but also used for gaming, pictures and so on which are all full range.
(2016-11-25, 10:49)fritsch Wrote: [ -> ]What would you now do with it in order to have 2 at 0 and 8 at 10, but you only have 7 values?

Maybe I need to sit on this for a bit, but

Image

I'd choose the following interpolated shades from the higher bit depth:

Code:
00 06 12 18 24 30 36 42 48 54 60
It is Intel hw, N3150 (Braswell), and a Samsung plasma TV, with the same values as you write (Low=Limited, Normal=Full). There is no AVR in the setup (actually there is, but using optical, no HDMI, therefore not relevant here).

In this case Kodi is used only for video playback, so the downside of gaming, pictures that are full range are not important here.

As you say, Full Range (Intel) + Full Range Kodi +8 bit dithering + Samsung TV set to Normal (full range) = excellent picture quality. And the same excellent quality is with Full Range (Intel) + Kodi set to limited + Samsung TV set to Low (limited range) = excellent picture quality, I couldn't tell the difference between these two when it comes to video playback.

Thanks for confirming this, as I was not sure that what I actually see is correct (that there is no visible pq difference between these two options in this case). And as the saying goes: if you like what you see, just use it.

Since I was (and I'm still) using an RPi2 with LE, I must say that even if the pq is really nice on Rpi2, Kodi on Intel hw with EGL is definitely better in every aspect: SD content is way better on Intel (I guess it is thanks to Lanczos3 Optimized upscaling, which is doing a great job), and live tv with VAAPI-MCDI deinterlacing is amazing (again, RPi2 does a great job with MMAL-Advanced deinterlacing, but VAAPI-MCDI is again definitely way nicer and better). Great work! Now that I have the Pulse8 CEC adapter, it is time to switch to Kodi v17 and Intel.
The only downside is the missing full 3D support RPi has, but there is still SBS and OU, and I don't really watch 3D at all anymore.

The new J3455/4205 by Intel will probably even bring full HEVC 10bit 60Hz & 4K support on Linux, combined that with EGL in Kodi v17 will be the best solution (I'm sure support for J3455 will arrive soon in Kodi). Not that there are so much need for HEVC support at the moment, not to speak about 4K content (I don't care about 4K at all, FullHD is perfectly fine for me, but HEVC support will be needed probably in near future for 1080p content too).
(2016-11-25, 12:16)ZwartePiet Wrote: [ -> ]
(2016-11-25, 10:49)fritsch Wrote: [ -> ]What would you now do with it in order to have 2 at 0 and 8 at 10, but you only have 7 values?

Maybe I need to sit on this for a bit, but

Image

I'd choose the following interpolated shades from the higher bit depth:

Code:
00 06 12 18 24 30 36 42 48 54 60

That's no valid answer :-) as neither 12 nor 60 fit into the 0 .. 10 range ...

Yeah, got your notation wrong. But what happens now? Is the ramp smooth? Or asked differently: What are you now doing ?

Can you give the result in this format (meaning the gray values where it ends up) for all lines:
Code:
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
(2016-11-25, 12:41)fritsch Wrote: [ -> ]Yeah, got your notation wrong. But what happens now? Is the ramp smooth? Or asked differently: What are you now doing ?

Can you give the result in this format (meaning the gray values where it ends up) for all lines:
Code:
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8

Smoothness is determined by the interpolation. Since it's linear, it should be perfect. In practice, higher bit-depths won't share least common multiples, so the deviation from perfection will depend on the bit-depth (higher=smoother). In my example, lets say value 1 from Fritsch10 Full lands between "06" and "07," you'll be forced to choose the closest value rather than the perfect one as I was able to do here.

Fritsch10 Full:
Code:
00 = 0
06 = 1
12 = 2
18 = 3
24 = 4
30 = 5
36 = 6
42 = 7
48 = 8
54 = 9
60 = 10

0,1,2,3,4,5,6,7,8,9,10
0,1,2,3,4,5,6,7,8,9,10
0,1,2,3,4,5,6,7,8,9,10
0,1,2,3,4,5,6,7,8,9,10
0,1,2,3,4,5,6,7,8,9,10
0,1,2,3,4,5,6,7,8,9,10
0,1,2,3,4,5,6,7,8,9,10
0,1,2,3,4,5,6,7,8,9,10
0,1,2,3,4,5,6,7,8,9,10
0,1,2,3,4,5,6,7,8,9,10

The key point is that we're not just lining up grey values. You can create new grey values, then use those to line up with your output format.

EDIT: Grey values aren't actually linear since they follow a power function, but the point still stands. Perfect interpolation is theoretically possible.

Hmm... now I'm beginning to doubt myself and see the error of my ways. Smile
We only have an image of 8x8 values (!) - I am not sure how you want to fit 100 values into it.

So with a direct mapping it would end up like:

new(val) = (old_val - min_old) / (old_format_max - old_format_min) * (new_format_max - new_format_min)
in our case:
new(val) = (old_val - 2) / 6 * 10

e.g.
new(2) = 0 / 6 * 10 = 0
new(3) = 1 / 6 * 10 = 1.667 -> 2 (or 1 if casted)
new (4) = 2/6 * 10 = 3.33 -> 3
new (5) = 5
new (6) = 6.667 -> 7 (or 6)
new (7) = 8.33 -> 8
new(8) = 10

Code:
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8
2,3,4,5,6,7,8

Result without doing anything (besides proper rounding):
Code:
0,2,3,5,7,8,10
0,2,3,5,7,8,10
0,2,3,5,7,8,10
0,2,3,5,7,8,10
0,2,3,5,7,8,10
0,2,3,5,7,8,10
0,2,3,5,7,8,10
0,2,3,5,7,8,10

That would produce banding, cause there is now "space" between direct neighbours, right?
What dithering now does is the following: Add a random number between 0 and < 1 ontop of the computed value and clamp / round whatever. With that it would end up like this:
Code:
0,1,3,5,7,9,10
0,2,4,6,7,9,10
... and so forth. The human eye won't see the "stairs" that much, cause they are "randomized" out within a limited range.

Here, the same with images: https://sunmaiblog.wordpress.com/2010/10...eo-output/ explained.
I really appreciate you walking me through this and will read your link.

Where I'm getting confused is why the gradient width is relevant. What if you had an image 255 pixels wide in limited color? How would you avoid banding then? What about an image 215 pixels wide? Surely the more values you have to work with (11 for your full range example vs. 7 for your limited range) the smoother your gradient can be, other than perfect scaling I suppose. It's the whole reason higher bit-depth reduces banding - more colors available mean more precision.

Full range RGB is in effect a higher bit-depth color space than limited range RGB. 255 gradations will cause less banding than 219, just like 1024 gradations is better than 255. I think banding is occurring because RGB limited isn't being correctly mapped to RGB full. The shade of grey in your limited range "3" is mapped to your full range "2," which is too dark. The interpolated grey "12" should be mapped instead.
Two problems here:
a) range
b) resolution

Btw. the banding is not introduced by b) but by a) as the range needs to be shifted, cause the values are interpreted differently.

You can display Limited Range in Full Range without any banding and without even processing it - but, you guessed it, black will be gone and white won't be there, too.

For your second example: When I have limited range image with > 255 length - I need to have the same "value" more than once, but as the distance between the values not equal is still just 1 unit - there won't be (Edit: introduced) banding, but a resolution issue.
And some images:

Limited range (smooth grey ramp), the grey would be black on a Limited TV screen, the bright grey would be white on such a screen
Image
If we now just "expand", e.g. just spread it to the full range, we would get a lot of banding
Image
If we add some dithering to the party - all fine again (* for showing what it does I oversthrenghed it a bit too much).
Image
Perhaps a stupid question,
I was wondering if the work done here has been implemented yet on the official Kodi V17 Beta 5.

I'm most likely going to wait for the OpenElec version, but I was just curious as I've been away from the forum for awhile.