From 6d5880fe19a086d6b355dfd81ea4e5af88e5e9d727b0da8e7f1cfcf39bf33ede Mon Sep 17 00:00:00 2001 From: copecone Date: Sun, 11 Oct 2026 22:46:31 +0900 Subject: [PATCH] Fix YUV to RGB Color Matrix Selection --- Bundle/Linux/shaders | Bin 13142 -> 13925 bytes Bundle/OSX/shaders | Bin 4537 -> 4716 bytes Bundle/Win64/shaders | Bin 3380 -> 3483 bytes Util/FFmpeg/FFmpegNativeDecoder.cs | 162 ++++++++++++++++++++++++++++- Util/VideoBGPlayer.cs | 3 + 5 files changed, 161 insertions(+), 4 deletions(-) diff --git a/Bundle/Linux/shaders b/Bundle/Linux/shaders index 6c668e8fc3764ca41aa4c01460bfc504bf5b5b4730fc7699b1f11cc3584e5f44..f7f0c5e552e18ce3d954423b4635e8e870695e9e1435c6b7d2fa547281c26b64 100644 GIT binary patch delta 13896 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 W?PllD=~URmAj$;gI{*Kc)ouyY6dpPN delta 13107 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 NifauK4gcU_-8rLQVzdAN diff --git a/Bundle/OSX/shaders b/Bundle/OSX/shaders index 6aeaeaa90a275cdfe9baa3e09694a4e6bfec9632b93ee64ccece4884ce9e04ee..e2a8e85ea45ba2f72889ec1b7c90e79ec1af04dcefad5d305df7a372aa9b0798 100644 GIT binary patch delta 4616 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 delta 4436 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 a6U1rnk9P=HdBBbmZ+Z`q_GAC`_oD2hr=&ap diff --git a/Bundle/Win64/shaders b/Bundle/Win64/shaders index 6503a4f865929372bec98665bdd92a6d71168aafe57965380e35a5c188b42fe4..4b9072084a3296fb4c41a1d0ab45a5f51f50fd1973e872b1af0eebd743cbf6f8 100644 GIT binary patch delta 3386 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 Q5+M^*%)}{+O!dXWJxIGh%>V!Z diff --git a/Util/FFmpeg/FFmpegNativeDecoder.cs b/Util/FFmpeg/FFmpegNativeDecoder.cs index 46737b8..d85038c 100644 --- a/Util/FFmpeg/FFmpegNativeDecoder.cs +++ b/Util/FFmpeg/FFmpegNativeDecoder.cs @@ -206,6 +206,12 @@ internal sealed unsafe class FFmpegNativeDecoder : IDisposable private int _srcWidth; private int _srcHeight; + /// YUV→RGB matrix id (SWS_CS_*) applied to the context. 0 when no matrix is set (non-RGBA output). + private int _srcSwsColorspace; + + /// Whether the source range applied to the context is the full range. + private bool _srcFullRange; + // ────────────────────────────────────────────────────────────── // Public Properties // ────────────────────────────────────────────────────────────── @@ -296,6 +302,59 @@ internal sealed unsafe class FFmpegNativeDecoder : IDisposable } } + /// + /// Color matrix id used to convert the YUV frames of this stream to RGB, selected from the colorspace tag of the stream. + /// The ids are shared with the ColorMatrix uniform of ColorConversion.compute: + /// 0 = BT.709 (also used when the stream has no usable tag), 1 = BT.601, 2 = BT.2020 (non-constant luminance). + /// + public int ColorMatrix + { + get + { + lock (_lock) + { + if (_pCodecContext != null && _pCodecContext->colorspace != AVColorSpace.AVCOL_SPC_UNSPECIFIED) + { + return GetColorMatrixId(_pCodecContext->colorspace); + } + if (_pFormatContext != null && _videoStreamIndex >= 0) + { + return GetColorMatrixId(_pFormatContext->streams[_videoStreamIndex]->codecpar->color_space); + } + return ColorMatrixBT709; + } + } + } + + /// Color matrix id of BT.709. + // ReSharper disable InconsistentNaming + public const int ColorMatrixBT709 = 0; + + /// Color matrix id of BT.601 (SMPTE 170M / BT.470 BG). + public const int ColorMatrixBT601 = 1; + + /// Color matrix id of BT.2020 (non-constant luminance). + public const int ColorMatrixBT2020 = 2; + // ReSharper restore InconsistentNaming + + /// + /// Converts a colorspace tag to a color matrix id (see ). + /// Tags that have no matrix of their own (unspecified, RGB, other standards) use BT.709. + /// + private static int GetColorMatrixId(AVColorSpace colorspace) + { + switch (colorspace) + { + case AVColorSpace.AVCOL_SPC_SMPTE170M: + case AVColorSpace.AVCOL_SPC_BT470BG: + return ColorMatrixBT601; + case AVColorSpace.AVCOL_SPC_BT2020_NCL: + return ColorMatrixBT2020; + default: + return ColorMatrixBT709; + } + } + /// /// Gets a value indicating whether hardware-accelerated decoding is currently active. /// @@ -778,12 +837,67 @@ internal sealed unsafe class FFmpegNativeDecoder : IDisposable } /// - /// Lazily initializes or updates the when source/destination formats or dimensions change. + /// Selects the YUV→RGB conversion matrix (libswscale SWS_CS_*) from the colorspace tag of a frame. + /// The matrix set is the same as that of the compute shader path (ColorConversion.compute, ColorMatrix uniform): + /// BT.709 (also for frames without a usable tag), BT.601 and BT.2020, so both paths give the same colors. + /// Reference: https://ffmpeg.org/doxygen/trunk/group__libsws.html (sws_getCoefficients) + /// + private static int GetSwsColorspace(AVColorSpace colorspace) + { + switch (GetColorMatrixId(colorspace)) + { + case ColorMatrixBT601: + return ffmpeg.SWS_CS_ITU601; + case ColorMatrixBT2020: + return ffmpeg.SWS_CS_BT2020; + default: + return ffmpeg.SWS_CS_ITU709; + } + } + + /// + /// Returns true when the Y/U/V samples of the frame use the full range (0-255) instead of the limited range (16-235 / 16-240). + /// The range is given by the frame's color_range tag or by a deprecated full range pixel format (YUVJ*). + /// + private static bool IsFullRange(AVFrame* frame) + { + if (frame->color_range == AVColorRange.AVCOL_RANGE_JPEG) return true; + + switch ((AVPixelFormat)frame->format) + { + case AVPixelFormat.AV_PIX_FMT_YUVJ420P: + case AVPixelFormat.AV_PIX_FMT_YUVJ422P: + case AVPixelFormat.AV_PIX_FMT_YUVJ444P: + case AVPixelFormat.AV_PIX_FMT_YUVJ440P: + return true; + default: + return false; + } + } + + /// + /// Lazily initializes or updates the when source/destination formats, dimensions, + /// or (for RGBA output) the colorspace / range of the source frame change. + /// For RGBA output the YUV→RGB matrix and the source range are taken from . /// Reference: https://ffmpeg.org/doxygen/trunk/group__libsws.html /// - private void InitOrUpdateSwsContext(AVPixelFormat srcFormat, int srcWidth, int srcHeight, AVPixelFormat dstFormat) + /// Pixel format of the source frame. + /// Width of the source frame in pixels. + /// Height of the source frame in pixels. + /// Pixel format of the output. + /// Source frame whose colorspace / range tags are applied. Required for RGBA output. + private void InitOrUpdateSwsContext(AVPixelFormat srcFormat, int srcWidth, int srcHeight, AVPixelFormat dstFormat, AVFrame* colorFrame = null) { - if (_pSwsContext != null && _srcPixFmt == srcFormat && _srcWidth == srcWidth && _srcHeight == srcHeight && _dstPixFmt == dstFormat) + var swsColorspace = 0; + var fullRange = false; + if (colorFrame != null && dstFormat == AVPixelFormat.AV_PIX_FMT_RGBA) + { + swsColorspace = GetSwsColorspace(colorFrame->colorspace); + fullRange = IsFullRange(colorFrame); + } + + if (_pSwsContext != null && _srcPixFmt == srcFormat && _srcWidth == srcWidth && _srcHeight == srcHeight && _dstPixFmt == dstFormat + && _srcSwsColorspace == swsColorspace && _srcFullRange == fullRange) { return; } @@ -798,6 +912,8 @@ internal sealed unsafe class FFmpegNativeDecoder : IDisposable _srcWidth = srcWidth; _srcHeight = srcHeight; _dstPixFmt = dstFormat; + _srcSwsColorspace = swsColorspace; + _srcFullRange = fullRange; _pSwsContext = ffmpeg.sws_getContext( srcWidth, srcHeight, srcFormat, @@ -809,6 +925,44 @@ internal sealed unsafe class FFmpegNativeDecoder : IDisposable { throw new Exception($"Failed to initialize SwsContext (src: {srcFormat} {srcWidth}x{srcHeight} -> dst: {dstFormat} {Width}x{Height})."); } + + if (swsColorspace != 0) + { + ApplySwsColorspace(swsColorspace, fullRange); + } + } + + /// + /// Sets the YUV→RGB matrix and the source range of . + /// The destination range, brightness, contrast and saturation keep the values of the context. + /// Reference: https://ffmpeg.org/doxygen/trunk/group__libsws.html (sws_setColorspaceDetails) + /// + /// Matrix id (SWS_CS_*) of the source. + /// True when the source uses the full range. + private void ApplySwsColorspace(int swsColorspace, bool fullRange) + { + int* currentInvTable; + int* currentTable; + int srcRange, dstRange, brightness, contrast, saturation; + + // Returns a negative value when the context cannot change its colorspace details (e.g. YUV to YUV conversion). + if (ffmpeg.sws_getColorspaceDetails(_pSwsContext, ¤tInvTable, &srcRange, ¤tTable, &dstRange, + &brightness, &contrast, &saturation) < 0) + { + return; + } + + var coefficients = ffmpeg.sws_getCoefficients(swsColorspace); + var invTable = new int_array4(); + var table = new int_array4(); + for (uint i = 0; i < 4; i++) + { + invTable[i] = coefficients[i]; + table[i] = currentTable[i]; + } + + ffmpeg.sws_setColorspaceDetails(_pSwsContext, invTable, fullRange ? 1 : 0, table, dstRange, + brightness, contrast, saturation); } /// @@ -900,7 +1054,7 @@ internal sealed unsafe class FFmpegNativeDecoder : IDisposable if (frame == null) return false; timestamp = GetTimestampAndUpdateIndex(frame); - InitOrUpdateSwsContext((AVPixelFormat)frame->format, frame->width, frame->height, AVPixelFormat.AV_PIX_FMT_RGBA); + InitOrUpdateSwsContext((AVPixelFormat)frame->format, frame->width, frame->height, AVPixelFormat.AV_PIX_FMT_RGBA, frame); ClearConvertedFramePointers(); if (vflip) diff --git a/Util/VideoBGPlayer.cs b/Util/VideoBGPlayer.cs index 7df95e3..c27b8b4 100644 --- a/Util/VideoBGPlayer.cs +++ b/Util/VideoBGPlayer.cs @@ -20,6 +20,7 @@ internal class VideoBGPlayer : MonoBehaviour private static readonly int UTex = Shader.PropertyToID("_UTex"); private static readonly int VTex = Shader.PropertyToID("_VTex"); private static readonly int ColorRange = Shader.PropertyToID("ColorRange"); + private static readonly int ColorMatrix = Shader.PropertyToID("ColorMatrix"); [SuppressMessage("ReSharper", "InconsistentNaming")] private enum GPUMode @@ -307,6 +308,7 @@ internal class VideoBGPlayer : MonoBehaviour _computeShader.SetInt(Width, w); _computeShader.SetInt(Height, h); _computeShader.SetInt(ColorRange, _decoder.ColorRange == AVColorRange.AVCOL_RANGE_JPEG ? 1 : 0); + _computeShader.SetInt(ColorMatrix, _decoder.ColorMatrix); int threadGroupsX = (w + 7) / 8; int threadGroupsY = (h + 7) / 8; @@ -341,6 +343,7 @@ internal class VideoBGPlayer : MonoBehaviour _computeShader.SetInt(Width, w); _computeShader.SetInt(Height, h); _computeShader.SetInt(ColorRange, _decoder.ColorRange == AVColorRange.AVCOL_RANGE_JPEG ? 1 : 0); + _computeShader.SetInt(ColorMatrix, _decoder.ColorMatrix); int threadGroupsX = (w + 7) / 8; int threadGroupsY = (h + 7) / 8;