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))]