matt.beghin
New member
Our application uses NDI for input and output. We try to do as much on the GPU, so we have fragment shaders for YUV => RGB conversion. Those are made for standard color profiles.
For NDI out, we actually download an RGBA texture and transmit it as is to NDI. But I can't find what color profile NDI library uses internally for RGB<=>YUV conversions.
The best I can get (I do a NDI loop: a color pattern is sent to NDI, and the NDI input stream-loopback, is displayed offsetted vertically, so I can see what the color looks like after N iterations) is by doing this transform (I tweak values manually until it looks perfect with a wide range of colors):
yuv.r = (yuv.r - 0.0625);
yuv.gb -= 0.5;
vec4 color = vec4(mat3(1.1643, 1.1643, 1.1643,
0.0, -0.2, 2.1,
1.7748, -0.4991, 0) * yuv.rgb,
1.0);

But this matrix does not match any of the standard conversions described here: https:en.wikipedia.org/wiki/YCbCr#Y'CbCr_to_xvYCC
BT.709 with Limited Range (without yuv.r = 1.164383561643836 * (yuv.r - 0.0625)) seems the closer, but colors are becoming desaturated after some iterations:

Here are the
// Color profile ITU-R BT.601 -
yuv.r = 1.164383561643836 * (yuv.r - 0.0625);
yuv.g -= 0.5;
yuv.b -= 0.5;
vec4 color = vec4(yuv.r + 1.6007 * yuv.b,
yuv.r - 0.391762290094914 * yuv.g - 0.812967647237771 * yuv.b,
yuv.r + 2.017232142857143 * yuv.g,
1);
// Color profile ITU-R BT.709 - https:en.wikipedia.org/wiki/YCbCr#Y'CbCr_to_xvYCC
yuv.r = 1.164383561643836 * (yuv.r - 0.0625);
yuv.g -= 0.5;
yuv.b -= 0.5;
vec4 color = vec4(mat3(1, 1, 1,
0.0, -0.1873, 1.8556,
1.5748, -0.4681, 0) * yuv.rgb,
1.0);
// Color profile ITU-R BT.2020
yuv.r = 1.164383561643836 * (yuv.r - 0.0625);
yuv.g -= 0.5;
yuv.b -= 0.5;
vec4 color = vec4(mat3(1, 1, 1,
0.0, -0.1645531, 1.8814,
1.4746, -0.571353, 0) * yuv.rgb,
1.0);
Is there any documentation on how the library converts RGB to YUV ?
I tested on Apple M1 & Apple Intel.
For NDI out, we actually download an RGBA texture and transmit it as is to NDI. But I can't find what color profile NDI library uses internally for RGB<=>YUV conversions.
The best I can get (I do a NDI loop: a color pattern is sent to NDI, and the NDI input stream-loopback, is displayed offsetted vertically, so I can see what the color looks like after N iterations) is by doing this transform (I tweak values manually until it looks perfect with a wide range of colors):
yuv.r = (yuv.r - 0.0625);
yuv.gb -= 0.5;
vec4 color = vec4(mat3(1.1643, 1.1643, 1.1643,
0.0, -0.2, 2.1,
1.7748, -0.4991, 0) * yuv.rgb,
1.0);

But this matrix does not match any of the standard conversions described here: https:en.wikipedia.org/wiki/YCbCr#Y'CbCr_to_xvYCC
BT.709 with Limited Range (without yuv.r = 1.164383561643836 * (yuv.r - 0.0625)) seems the closer, but colors are becoming desaturated after some iterations:

Here are the
// Color profile ITU-R BT.601 -
yuv.r = 1.164383561643836 * (yuv.r - 0.0625);
yuv.g -= 0.5;
yuv.b -= 0.5;
vec4 color = vec4(yuv.r + 1.6007 * yuv.b,
yuv.r - 0.391762290094914 * yuv.g - 0.812967647237771 * yuv.b,
yuv.r + 2.017232142857143 * yuv.g,
1);
// Color profile ITU-R BT.709 - https:en.wikipedia.org/wiki/YCbCr#Y'CbCr_to_xvYCC
yuv.r = 1.164383561643836 * (yuv.r - 0.0625);
yuv.g -= 0.5;
yuv.b -= 0.5;
vec4 color = vec4(mat3(1, 1, 1,
0.0, -0.1873, 1.8556,
1.5748, -0.4681, 0) * yuv.rgb,
1.0);
// Color profile ITU-R BT.2020
yuv.r = 1.164383561643836 * (yuv.r - 0.0625);
yuv.g -= 0.5;
yuv.b -= 0.5;
vec4 color = vec4(mat3(1, 1, 1,
0.0, -0.1645531, 1.8814,
1.4746, -0.571353, 0) * yuv.rgb,
1.0);
Is there any documentation on how the library converts RGB to YUV ?
I tested on Apple M1 & Apple Intel.
Last edited: