diff --git a/osu-framework.sln.DotSettings b/osu-framework.sln.DotSettings index 05061adb75..45f036361e 100644 --- a/osu-framework.sln.DotSettings +++ b/osu-framework.sln.DotSettings @@ -381,6 +381,8 @@ BNG UI WM + SDTV + HDTV False HINT <?xml version="1.0" encoding="utf-16"?> diff --git a/osu.Framework.Tests/Resources/Textures/h264-hd-screenshot.png b/osu.Framework.Tests/Resources/Textures/h264-hd-screenshot.png new file mode 100644 index 0000000000..e79ffb3131 Binary files /dev/null and b/osu.Framework.Tests/Resources/Textures/h264-hd-screenshot.png differ diff --git a/osu.Framework.Tests/Resources/Textures/h264-screenshot.png b/osu.Framework.Tests/Resources/Textures/h264-screenshot.png new file mode 100644 index 0000000000..66743aab13 Binary files /dev/null and b/osu.Framework.Tests/Resources/Textures/h264-screenshot.png differ diff --git a/osu.Framework.Tests/Resources/Videos/h264-hd.mp4 b/osu.Framework.Tests/Resources/Videos/h264-hd.mp4 new file mode 100644 index 0000000000..87c36a580d Binary files /dev/null and b/osu.Framework.Tests/Resources/Videos/h264-hd.mp4 differ diff --git a/osu.Framework.Tests/Visual/Sprites/TestSceneVideo.cs b/osu.Framework.Tests/Visual/Sprites/TestSceneVideo.cs index 3c320a7fab..e925989ce4 100644 --- a/osu.Framework.Tests/Visual/Sprites/TestSceneVideo.cs +++ b/osu.Framework.Tests/Visual/Sprites/TestSceneVideo.cs @@ -10,9 +10,12 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Video; using osu.Framework.IO.Stores; using osu.Framework.Timing; +using osuTK; namespace osu.Framework.Tests.Visual.Sprites { @@ -32,6 +35,9 @@ public partial class TestSceneVideo : FrameworkTestScene [Resolved] private FrameworkConfigManager config { get; set; } + [Resolved] + private TextureStore textures { get; set; } + private static readonly string[] file_formats = { "h264.mp4", @@ -239,6 +245,57 @@ public void TestShader() AddToggleStep("Toggle rounding", v => video.Rounded = v); } + [Test] + public void TestUnspecifiedColorspace() + { + AddStep("Reset clock", () => + { + clock.CurrentTime = 0; + didDecode = false; + }); + AddStep("load videos", () => + { + videoContainer.Child = new FillFlowContainer + { + Scale = new Vector2(0.75f), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Children = new[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new[] + { + new SpriteText { Text = "SDTV / Rec. 601" }, + new TestVideo(videoStore.GetStream("h264.mp4")), + Empty().With(d => d.Height = 10), + new Sprite { Texture = textures.Get("h264-screenshot.png", WrapMode.ClampToEdge, WrapMode.ClampToEdge), Scale = new Vector2(2f) }, + new SpriteText { Text = "Expected" }, + } + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new[] + { + new SpriteText { Text = "HDTV / Rec. 709" }, + new TestVideo(videoStore.GetStream("h264-hd.mp4")) { Scale = new Vector2(270f / 576f) }, + Empty().With(d => d.Height = 10), + new Sprite { Texture = textures.Get("h264-hd-screenshot.png", WrapMode.ClampToEdge, WrapMode.ClampToEdge), Scale = new Vector2(270f / 576f * 2f) }, + new SpriteText { Text = "Expected" }, + } + }, + }, + }; + }); + AddStep("Reset clock", () => clock.CurrentTime = 0); + } + private int currentSecond; private int fps; private int lastFramesProcessed; diff --git a/osu.Framework/Graphics/Video/VideoDecoder.cs b/osu.Framework/Graphics/Video/VideoDecoder.cs index 62c87389ff..6b8638a805 100644 --- a/osu.Framework/Graphics/Video/VideoDecoder.cs +++ b/osu.Framework/Graphics/Video/VideoDecoder.cs @@ -268,21 +268,25 @@ public Matrix3 GetConversionMatrix() if (codecContext == null) return Matrix3.Zero; - switch (codecContext->colorspace) + // this matches QuickTime Player's choice of colour spaces: + // - any video with width < 704 and height < 576 uses the SDTV colorspace. + // - any video with width >= 704 and height >= 576 uses the HDTV colorspace. + // (704x576 in particular has a special colour space, but we don't worry about it). + bool unspecifiedUsesHDTV = codecContext->width >= 704 || codecContext->height >= 576; + + if (codecContext->colorspace == AVColorSpace.AVCOL_SPC_BT709 + || (codecContext->colorspace == AVColorSpace.AVCOL_SPC_UNSPECIFIED && unspecifiedUsesHDTV)) { - case AVColorSpace.AVCOL_SPC_BT709: - return new Matrix3(1.164f, 1.164f, 1.164f, - 0.000f, -0.213f, 2.112f, - 1.793f, -0.533f, 0.000f); - - case AVColorSpace.AVCOL_SPC_UNSPECIFIED: - case AVColorSpace.AVCOL_SPC_SMPTE170M: - case AVColorSpace.AVCOL_SPC_SMPTE240M: - default: - return new Matrix3(1.164f, 1.164f, 1.164f, - 0.000f, -0.392f, 2.017f, - 1.596f, -0.813f, 0.000f); + // matrix coefficients for HDTV / Rec. 709 colorspace. + return new Matrix3(1.164f, 1.164f, 1.164f, + 0.000f, -0.213f, 2.112f, + 1.793f, -0.533f, 0.000f); } + + // matrix coefficients for SDTV / Rec. 601 colorspace. + return new Matrix3(1.164f, 1.164f, 1.164f, + 0.000f, -0.392f, 2.017f, + 1.596f, -0.813f, 0.000f); } [MonoPInvokeCallback(typeof(avio_alloc_context_read_packet))]