From e3c5f1d58df5fd1a6495458e4eb3acd81a628692 Mon Sep 17 00:00:00 2001 From: Max Heimbrock <43608204+MaxHeimbrock@users.noreply.github.com> Date: Thu, 26 Mar 2026 11:09:13 +0100 Subject: [PATCH 1/6] Mirror in cpu yuv path as well --- Runtime/Scripts/Video/YuvToRgbConverter.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Runtime/Scripts/Video/YuvToRgbConverter.cs b/Runtime/Scripts/Video/YuvToRgbConverter.cs index 32f9072b..462cb34d 100644 --- a/Runtime/Scripts/Video/YuvToRgbConverter.cs +++ b/Runtime/Scripts/Video/YuvToRgbConverter.cs @@ -127,13 +127,17 @@ private void UploadYuvPlanes(VideoFrameBuffer buffer) // CPU-side conversion to RGBA and blit to the output render target. private void CpuConvertToRenderTarget(VideoFrameBuffer buffer, int width, int height) { + Debug.Log($"CPU conversion"); + var rgba = buffer.ToRGBA(); var tempTex = new Texture2D(width, height, TextureFormat.RGBA32, false); try { tempTex.LoadRawTextureData((IntPtr)rgba.Info.DataPtr, (int)rgba.GetMemorySize()); tempTex.Apply(); - Graphics.Blit(tempTex, Output); + + // Also mirror horizontally by flipping the UV scale on the X axis and offsetting. + Graphics.Blit(tempTex, Output, new Vector2(-1f, 1f), new Vector2(1f, 0f)); } finally { @@ -145,9 +149,12 @@ private void CpuConvertToRenderTarget(VideoFrameBuffer buffer, int width, int he // GPU-side YUV->RGB conversion using shader material. private void GpuConvertToRenderTarget() { + Debug.Log($"GPU conversion"); + _yuvToRgbMaterial.SetTexture("_TexY", _planeY); _yuvToRgbMaterial.SetTexture("_TexU", _planeU); _yuvToRgbMaterial.SetTexture("_TexV", _planeV); + Graphics.Blit(Texture2D.blackTexture, Output, _yuvToRgbMaterial); } } From 419a365f0d83664bb8ac62a6cc230cc7f30d3bc7 Mon Sep 17 00:00:00 2001 From: Max Heimbrock <43608204+MaxHeimbrock@users.noreply.github.com> Date: Thu, 26 Mar 2026 11:15:38 +0100 Subject: [PATCH 2/6] Getting rid of temp version files in git --- .gitignore | 3 +++ Samples~/Meet/Assets/Resources/LiveKitSdkVersionInfo.txt | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) delete mode 100644 Samples~/Meet/Assets/Resources/LiveKitSdkVersionInfo.txt diff --git a/.gitignore b/.gitignore index 27ebdc9a..9288d387 100644 --- a/.gitignore +++ b/.gitignore @@ -88,3 +88,6 @@ downloads~ # Ignore temporaries from GameCI **/[Aa]rtifacts/ **/[Cc]odeCoverage/ + +# Temp generated SDK version file +**/LiveKitSdkVersionInfo.txt \ No newline at end of file diff --git a/Samples~/Meet/Assets/Resources/LiveKitSdkVersionInfo.txt b/Samples~/Meet/Assets/Resources/LiveKitSdkVersionInfo.txt deleted file mode 100644 index 785cda80..00000000 --- a/Samples~/Meet/Assets/Resources/LiveKitSdkVersionInfo.txt +++ /dev/null @@ -1 +0,0 @@ -1.3.3 \ No newline at end of file From 6c1b86c678ffb4fa440c4ef87b0cde751409d786 Mon Sep 17 00:00:00 2001 From: Max Heimbrock <43608204+MaxHeimbrock@users.noreply.github.com> Date: Thu, 26 Mar 2026 11:24:44 +0100 Subject: [PATCH 3/6] Moving shaders into resources folder, then they will be included in builds automatically. --- Resources.meta | 8 ++++++++ {Runtime => Resources}/Shaders.meta | 0 {Runtime => Resources}/Shaders/YuvToRgb.shader | 0 {Runtime => Resources}/Shaders/YuvToRgb.shader.meta | 0 Runtime/Scripts/Video/YuvToRgbConverter.cs | 2 -- Samples~/Meet/Assets/Resources/Shaders.meta | 8 ++++++++ .../ResizeVideo => Resources/Shaders}/ResizeShader.shader | 0 .../Shaders}/ResizeShader.shader.meta | 0 Samples~/Meet/ProjectSettings/GraphicsSettings.asset | 1 - 9 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 Resources.meta rename {Runtime => Resources}/Shaders.meta (100%) rename {Runtime => Resources}/Shaders/YuvToRgb.shader (100%) rename {Runtime => Resources}/Shaders/YuvToRgb.shader.meta (100%) create mode 100644 Samples~/Meet/Assets/Resources/Shaders.meta rename Samples~/Meet/Assets/{Runtime/Utils/ResizeVideo => Resources/Shaders}/ResizeShader.shader (100%) rename Samples~/Meet/Assets/{Runtime/Utils/ResizeVideo => Resources/Shaders}/ResizeShader.shader.meta (100%) diff --git a/Resources.meta b/Resources.meta new file mode 100644 index 00000000..cac0fc94 --- /dev/null +++ b/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ee238a2ee670f4cd7bad98293b9e94fd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Shaders.meta b/Resources/Shaders.meta similarity index 100% rename from Runtime/Shaders.meta rename to Resources/Shaders.meta diff --git a/Runtime/Shaders/YuvToRgb.shader b/Resources/Shaders/YuvToRgb.shader similarity index 100% rename from Runtime/Shaders/YuvToRgb.shader rename to Resources/Shaders/YuvToRgb.shader diff --git a/Runtime/Shaders/YuvToRgb.shader.meta b/Resources/Shaders/YuvToRgb.shader.meta similarity index 100% rename from Runtime/Shaders/YuvToRgb.shader.meta rename to Resources/Shaders/YuvToRgb.shader.meta diff --git a/Runtime/Scripts/Video/YuvToRgbConverter.cs b/Runtime/Scripts/Video/YuvToRgbConverter.cs index 462cb34d..034c507a 100644 --- a/Runtime/Scripts/Video/YuvToRgbConverter.cs +++ b/Runtime/Scripts/Video/YuvToRgbConverter.cs @@ -149,8 +149,6 @@ private void CpuConvertToRenderTarget(VideoFrameBuffer buffer, int width, int he // GPU-side YUV->RGB conversion using shader material. private void GpuConvertToRenderTarget() { - Debug.Log($"GPU conversion"); - _yuvToRgbMaterial.SetTexture("_TexY", _planeY); _yuvToRgbMaterial.SetTexture("_TexU", _planeU); _yuvToRgbMaterial.SetTexture("_TexV", _planeV); diff --git a/Samples~/Meet/Assets/Resources/Shaders.meta b/Samples~/Meet/Assets/Resources/Shaders.meta new file mode 100644 index 00000000..1826d635 --- /dev/null +++ b/Samples~/Meet/Assets/Resources/Shaders.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dfbb08de08ecc4679a09b6187e28f3df +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Samples~/Meet/Assets/Runtime/Utils/ResizeVideo/ResizeShader.shader b/Samples~/Meet/Assets/Resources/Shaders/ResizeShader.shader similarity index 100% rename from Samples~/Meet/Assets/Runtime/Utils/ResizeVideo/ResizeShader.shader rename to Samples~/Meet/Assets/Resources/Shaders/ResizeShader.shader diff --git a/Samples~/Meet/Assets/Runtime/Utils/ResizeVideo/ResizeShader.shader.meta b/Samples~/Meet/Assets/Resources/Shaders/ResizeShader.shader.meta similarity index 100% rename from Samples~/Meet/Assets/Runtime/Utils/ResizeVideo/ResizeShader.shader.meta rename to Samples~/Meet/Assets/Resources/Shaders/ResizeShader.shader.meta diff --git a/Samples~/Meet/ProjectSettings/GraphicsSettings.asset b/Samples~/Meet/ProjectSettings/GraphicsSettings.asset index d822b0f2..a9da4b15 100644 --- a/Samples~/Meet/ProjectSettings/GraphicsSettings.asset +++ b/Samples~/Meet/ProjectSettings/GraphicsSettings.asset @@ -34,7 +34,6 @@ GraphicsSettings: - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0} - - {fileID: 4800000, guid: 2475752d0dcc74d1eb5e66b8317e87b6, type: 3} m_PreloadedShaders: [] m_PreloadShadersBatchTimeLimit: -1 m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} From 5ab74e0fa3da23443eca503af43f653643be0d2c Mon Sep 17 00:00:00 2001 From: Max Heimbrock <43608204+MaxHeimbrock@users.noreply.github.com> Date: Fri, 27 Mar 2026 09:59:21 +0100 Subject: [PATCH 4/6] Removed debug statement --- Runtime/Scripts/Video/YuvToRgbConverter.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Runtime/Scripts/Video/YuvToRgbConverter.cs b/Runtime/Scripts/Video/YuvToRgbConverter.cs index 034c507a..ed0b97a4 100644 --- a/Runtime/Scripts/Video/YuvToRgbConverter.cs +++ b/Runtime/Scripts/Video/YuvToRgbConverter.cs @@ -127,8 +127,6 @@ private void UploadYuvPlanes(VideoFrameBuffer buffer) // CPU-side conversion to RGBA and blit to the output render target. private void CpuConvertToRenderTarget(VideoFrameBuffer buffer, int width, int height) { - Debug.Log($"CPU conversion"); - var rgba = buffer.ToRGBA(); var tempTex = new Texture2D(width, height, TextureFormat.RGBA32, false); try From ce132139bdd88a87f88529c90103e24f193f66f0 Mon Sep 17 00:00:00 2001 From: Max Heimbrock <43608204+MaxHeimbrock@users.noreply.github.com> Date: Fri, 27 Mar 2026 15:33:28 +0100 Subject: [PATCH 5/6] Convert sRGB to linear in the shader --- Resources/Shaders/YuvToRgb.shader | 19 ++++++++++--------- Runtime/Scripts/Video/YuvToRgbConverter.cs | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Resources/Shaders/YuvToRgb.shader b/Resources/Shaders/YuvToRgb.shader index 1ef01af5..d2ef4606 100644 --- a/Resources/Shaders/YuvToRgb.shader +++ b/Resources/Shaders/YuvToRgb.shader @@ -36,19 +36,16 @@ Shader "Hidden/LiveKit/YUV2RGB" return o; } - inline half3 yuvToRgb709Limited(half y, half u, half v) + inline half3 yuvToRgb709Full(half y, half u, half v) { - // BT.709 limited range - half c = y - half(16.0 / 255.0); + // BT.709 full range (0-255) half d = u - half(128.0 / 255.0); half e = v - half(128.0 / 255.0); - half Y = half(1.16438356) * c; - half3 rgb; - rgb.r = Y + half(1.79274107) * e; - rgb.g = Y - half(0.21324861) * d - half(0.53290933) * e; - rgb.b = Y + half(2.11240179) * d; + rgb.r = y + half(1.5748) * e; + rgb.g = y - half(0.18733) * d - half(0.46813) * e; + rgb.b = y + half(1.8556) * d; return saturate(rgb); } @@ -60,7 +57,11 @@ Shader "Hidden/LiveKit/YUV2RGB" half y = tex2D(_TexY, uv).r; half u = tex2D(_TexU, uv).r; half v = tex2D(_TexV, uv).r; - return half4(yuvToRgb709Limited(y, u, v), 1.0h); + half3 rgb = yuvToRgb709Full(y, u, v); + // YUV→RGB produces sRGB/gamma values; convert to linear so the + // hardware's linear→sRGB write to the sRGB RT gives correct output. + rgb = GammaToLinearSpace(rgb); + return half4(rgb, 1.0h); } ENDHLSL } diff --git a/Runtime/Scripts/Video/YuvToRgbConverter.cs b/Runtime/Scripts/Video/YuvToRgbConverter.cs index ed0b97a4..9cded2b9 100644 --- a/Runtime/Scripts/Video/YuvToRgbConverter.cs +++ b/Runtime/Scripts/Video/YuvToRgbConverter.cs @@ -25,7 +25,7 @@ public bool EnsureOutput(int width, int height) Output.Release(); UnityEngine.Object.Destroy(Output); } - Output = new RenderTexture(width, height, 0, RenderTextureFormat.ARGB32); + Output = new RenderTexture(width, height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.sRGB); Output.Create(); changed = true; } From 06a629ead80404b404e190b54018550c4b91c55d Mon Sep 17 00:00:00 2001 From: Max Heimbrock <43608204+MaxHeimbrock@users.noreply.github.com> Date: Fri, 27 Mar 2026 15:37:57 +0100 Subject: [PATCH 6/6] Shader looks even better with some more tweaking, using limited range coefficients --- Resources/Shaders/YuvToRgb.shader | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Resources/Shaders/YuvToRgb.shader b/Resources/Shaders/YuvToRgb.shader index d2ef4606..ae282fb0 100644 --- a/Resources/Shaders/YuvToRgb.shader +++ b/Resources/Shaders/YuvToRgb.shader @@ -36,16 +36,19 @@ Shader "Hidden/LiveKit/YUV2RGB" return o; } - inline half3 yuvToRgb709Full(half y, half u, half v) + inline half3 yuvToRgb709Limited(half y, half u, half v) { - // BT.709 full range (0-255) + // BT.709 limited range (Y: 16-235, UV: 16-240) + half c = y - half(16.0 / 255.0); half d = u - half(128.0 / 255.0); half e = v - half(128.0 / 255.0); + half Y = half(1.16438356) * c; + half3 rgb; - rgb.r = y + half(1.5748) * e; - rgb.g = y - half(0.18733) * d - half(0.46813) * e; - rgb.b = y + half(1.8556) * d; + rgb.r = Y + half(1.79274107) * e; + rgb.g = Y - half(0.21324861) * d - half(0.53290933) * e; + rgb.b = Y + half(2.11240179) * d; return saturate(rgb); } @@ -57,7 +60,7 @@ Shader "Hidden/LiveKit/YUV2RGB" half y = tex2D(_TexY, uv).r; half u = tex2D(_TexU, uv).r; half v = tex2D(_TexV, uv).r; - half3 rgb = yuvToRgb709Full(y, u, v); + half3 rgb = yuvToRgb709Limited(y, u, v); // YUV→RGB produces sRGB/gamma values; convert to linear so the // hardware's linear→sRGB write to the sRGB RT gives correct output. rgb = GammaToLinearSpace(rgb);