Kodi Community Forum

Full Version: Does Kodi convert from SD to HD correctly?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2 3
Okay, that probably sounds like rather a provocative question! I'll elaborate. (And I should make clear that my understanding of colour space conversions may not be perfect; if anything I'm about to say is actually wrong, feel free to correct me!).

On something like a DVD, the video is encoded using the rec.601 colour space. But 1080p or 2160p videos signals use the rec.709 colour space. The biggest difference between the two is that the formulae for deriving an RGB value from a YCrCb value aren't the same; so if you want to take a rec.601 YCbCr video and output it as part of a 1080p image that is also YCbCr, you can't just use original YCbCr values, you have to map from one colour space to another. I'm fairly sure Kodi does that correctly.

But there are other differences between the video standards as well, for example with the colour gamut that is used. An NTSC DVD (I believe) uses the SMPTE-C colour gamut; a PAL DVD uses the EBU gamut. EBU is quite close to the rec.709 gamut, but SMPTE-C has significant differences in the definition of its primary colours. So, if you take video an NTSC DVD and upscale it (or do something else which results in it being part of a 1080p image), it's not enough to take account of the YCbCr/RGB formulae, you also need to compensate for the difference in the primaries.

While this isn't the easiest thing to judge by eye, I suspect that Kodi (on my Nvidia Shield TV, anyway) isn't handling this correctly - that it's not taking account of the difference in the primaries, resulting in oversaturated colours when playing back an NTSC DVD rip.

I'm raising this here rather than on the Android forum because I want to know if Kodi, in general, is supposed to be able to handle this correctly. (If not, then it's obviously not an issue that is specific to Android).

(I tried doing a search before posting this but "rec.601" didn't bring anything back, and "601" is not an acceptable search term. Sad Apologies if this is a duplicate thread!)
I don't know if it's handled correctly by the Android port. I know that platforms using OpenGL like Linux X11/Wayland and OSX do it right. Provided that we get the correct info from the encoded stream (which is usally the case)

EDIT: we have different yuv to rgb conversion matrices for the different color spaces
https://github.com/xbmc/xbmc/blob/1cfbb0...ix.cpp#L31
(2017-11-10, 14:00)FernetMenta Wrote: [ -> ]I don't know if it's handled correctly by the Android port. I know that platforms using OpenGL like Linux X11/Wayland and OSX do it right. Provided that we get the correct info from the encoded stream (which is usally the case)

EDIT: we have different yuv to rgb conversion matrices for the different color spaces
https://github.com/xbmc/xbmc/blob/1cfbb0...ix.cpp#L31
Right, but does that take account of the fact that (for example) pure red in the SMPTE-C colour gamut is not the same as pure red in the rec.709 gamut? The same RGB values represent different points on the CIE diagram because the primaries are different.
Which is handled by the matrix? Isn't it?
When CIE primary coordinates are different between color spaces, you are supposed to convert first to linear RGB before transforming the color space. Matrix conversion doesn't do this. The differences between BT. 709 and BT. 601 primaries are small enough that matrix conversion doesn't generate a perceivable color error (in most cases). Ideally, you shouldn't be using matrix conversion. Some NL video editors do internal processing in linear RGB, but the majority of the devices do matrix conversion because it is simple and fast.

I only see YCbCr to RGB conversion matrix in the linked code. I am not seeing a BT.601 to BT.709 conversion matrix.
I'm not seeing what the upscaling has to do with color space conversion?

scott s.
.
(2017-11-11, 00:31)wesk05 Wrote: [ -> ]When CIE primary coordinates are different between color spaces, you are supposed to convert first to linear RGB before transforming the color space. Matrix conversion doesn't do this. The differences between BT. 709 and BT. 601 primaries are small enough that matrix conversion doesn't generate a perceivable color error (in most cases). Ideally, you shouldn't be using matrix conversion. Some NL video editors do internal processing in linear RGB, but the majority of the devices do matrix conversion because it is simple and fast.

I only see YCbCr to RGB conversion matrix in the linked code. I am not seeing a BT.601 to BT.709 conversion matrix.

I see. I looked up the conversion, which is mainly a section wise defined function, yeah - two sections. One < 0.04045, which is handled by a scaling factor and one larger, which is computed by a pow function to produce the linear mapping. This is for sRGB to linear RGB. Now the problem is, we don't have sRGB as input, but a different representation, yuv with certain other values, depending on BT601, smtpe, whatever.

So basically you say: we need section wise defined methods to do this conversion first? And from there we can go to sRGB again? Because of the non linear character of the functions, therefore: G(X) != H(I(x)) where H and I are linear, cause they are both not.

So much about the math. What I don't get is, the goal of linear RGB is, that if we concentrate on one channel, let's say R, that means: double the value is double the brightness. My question here is: Why does linear RGB come into play at all? Where in the original color / video editing did we have a linear combination between those two color value and brightness?
(2017-11-11, 00:31)wesk05 Wrote: [ -> ]I only see YCbCr to RGB conversion matrix in the linked code. I am not seeing a BT.601 to BT.709 conversion matrix.

OpenGL rendering is in RGB and finally your display is RGB. Hence there is no need for convertion of colour spaces YUV -> YUV.
(2017-11-11, 03:23)scott967 Wrote: [ -> ]I'm not seeing what the upscaling has to do with color space conversion?
Well, briefly, because if you're sending an image to the TV that is 720p, 1080p or 2160p, then the TV can only interpret it as being in rec.709 space - you can't send it something in rec.601 space unless it's in 480 or 576 resolution. So you have to convert your rec.601 image to corresponding values to rec.709 before it's sent to the TV.
(2017-11-11, 11:08)Shasarak Wrote: [ -> ]
(2017-11-11, 03:23)scott967 Wrote: [ -> ]I'm not seeing what the upscaling has to do with color space conversion?
Well, briefly, because if you're sending an image to the TV that is 720p, 1080p or 2160p, then the TV can only interpret it as being in rec.709 space - you can't send it something in rec.601 space unless it's in 480 or 576 resolution. So you have to convert your rec.601 image to corresponding values to rec.709 before it's sent to the TV. 

We don't do that. The only position in kodi where we use 601/709 conversion is when converting from Yuv to RGB. After that, the colors are not touched by us at all. Kodi outputs RGB via OpenGL. Rest is done by drivers under the hood, without our control.
(2017-11-11, 09:19)FernetMenta Wrote: [ -> ]OpenGL rendering is in RGB and finally your display is RGB. Hence there is no need for convertion of colour spaces YUV -> YUV.
Terminology is a little tricky, here - people use the phrase "colour space" to mean slightly different things.

Often it's used to refer to the way that you specify colour coordinates - are we using RGB, YUV, YCbCr, etc.?

A second concept is what you might call the "colour decoding standard" - different systems use different formulae to convert between the different coordinate systems. So, for example, a particular set of YCbCr values in rec. 601 space converts to a particular RGB value; the same YCbCr value in rec.709 refers to a different RGB value, because the rules for mapping between YCrCb and RGB aren't the same. (They use different matrices, of the kind you were talking about earlier).

If you're converting from rec.601 to rec.709, the matrix approach handles the different decoding standards perfectly. But there's a third factor to worry about, the "colour gamut". This refers to the total range of colours that can be displayed, and it defines where the red, green and blue primary colours are within the range of colours that the eye can perceive.

So, you can convert from YCbCr to RGB using the matrix that is appropriate, and that tells you "how much red, how much green, how much blue?" - but you also need to ask "which green are we talking about?" Even if you've converted to RGB coordinates, pure green means something different in the SMPTE-C colour gamut than it means in the rec.709 or sRGB gamut; and the EBU gamut is different again.

An example that will be more familiar to people is the rec.2020 space. As compared with rec.709, rec.2020 uses a much wider gamut; so pure green in rec.2020 is much more saturated than pure green in rec.709.

In the case of rec.2020, the television knows about that, and it holds two different calibrated values for green - one for rec.709 green and one for rec.2020 green - and depending on which gamut the signal tells it to use, it displays RGB values differently.

But there is no way that you can tag the signal to tell the TV to use SMPTE-C or EBU gamuts - if you're sending it something in HD resolution, it will only ever use the rec.709/sRGB gamut. So, if you want to convert a point in rec.601/SMPTE-C space to the nearest equivalent point in rec.709 space, your matrix approach isn't sufficient.

I'm afraid I don't know enough about this to tell you what maths you need to use to do this correctly. I suspect it's quite complicated, because hardly anything seems to do it correctly! But if you don't you end up with significantly oversaturated colours on upscaled NTSC DVDs. (Many people describe the difference as "subtle" - to my eye, with NTSC DVDs, it really isn't! With PAL DVDs, "subtle" is probably an accurate description, but even then, if you were to view the two side by side, the difference would be easily visible.)
(2017-11-11, 11:19)fritsch Wrote: [ -> ]
(2017-11-11, 11:08)Shasarak Wrote: [ -> ]
(2017-11-11, 03:23)scott967 Wrote: [ -> ]I'm not seeing what the upscaling has to do with color space conversion?
Well, briefly, because if you're sending an image to the TV that is 720p, 1080p or 2160p, then the TV can only interpret it as being in rec.709 space - you can't send it something in rec.601 space unless it's in 480 or 576 resolution. So you have to convert your rec.601 image to corresponding values to rec.709 before it's sent to the TV. 

We don't do that. The only position in kodi where we use 601/709 conversion is when converting from Yuv to RGB. After that, the colors are not touched by us at all. Kodi outputs RGB via OpenGL. Rest is done by drivers under the hood, without our control.
How do you expect the driver to know which colour gamut the video was originally encoded in if you've already converted it to RGB and upscaled it?
I don't - and that's exactly the point.
(2017-11-11, 12:27)fritsch Wrote: [ -> ]I don't - and that's exactly the point.
All right, well, that at least gives me an answer to my question: Kodi doesn't convert from SD to HD correctly.

This actually brings up another question: if you're converting to RGB internally, and feeding that to the device's video driver, does that mean you're converting from the original video's limited range YCbCr (16-235) to full-range RGB (0-255)? If so, does that apply on all Kodi platforms (e.g. Nvidia Shield TV and Raspberry Pi 3, both of which I run Kodi on)? And does that mean I'll get marginally more accurate results if I set the device's output colour space to full-range RGB rather than limited range YCbCr 4:2:2?

(Not sure how well my TV will handle that, mind you).
You still did not get the point. There is no conversion fron SD to HS or vice versa. Computer graphics are in RGB.. That is a well defined color space and has nothing to do with ITU 601/709 etc. The only conversion we do is to convert from the original color space of the vido to a standard computer graphics colorspace. That's it.
The Android port is not as matured as Windows and Linux (OpenGL). If you want hight quality, don't use Kodi on Android. Windows and Linux even offer CMS.
Pages: 1 2 3