From bc316b3dc855e93d4d11e2c0d73d70326c38b889 Mon Sep 17 00:00:00 2001
From: NoFear0411 <9083405+NoFear0411@users.noreply.github.com>
Date: Sun, 1 Mar 2026 00:00:05 +0400
Subject: Fix near-1:1 SAR values falsely flagged as anamorphic
Encoders sometimes produce sample aspect ratios like 3201:3200
(0.03% off square) for content that has effectively square pixels.
The exact string comparison against "1:1" marks these as anamorphic,
which triggers unnecessary transcoding on clients that require
non-anamorphic video.
Parse the SAR ratio numerically and treat values within 1% of 1:1
as square pixels. This threshold is well clear of the nearest real
anamorphic SAR (PAL 4:3 at 16:15 = 6.67% off).
---
.../Probing/ProbeResultNormalizer.cs | 28 +++++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
(limited to 'MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs')
diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
index dbe532289..471df369b 100644
--- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
+++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
@@ -863,7 +863,7 @@ namespace MediaBrowser.MediaEncoding.Probing
{
stream.IsAnamorphic = false;
}
- else if (string.Equals(streamInfo.SampleAspectRatio, "1:1", StringComparison.Ordinal))
+ else if (IsNearSquarePixelSar(streamInfo.SampleAspectRatio))
{
stream.IsAnamorphic = false;
}
@@ -1154,6 +1154,32 @@ namespace MediaBrowser.MediaEncoding.Probing
return Math.Abs(d1 - d2) <= variance;
}
+ ///
+ /// Determines whether a sample aspect ratio represents square (or near-square) pixels.
+ /// Some encoders produce SARs like 3201:3200 for content that is effectively 1:1,
+ /// which would be falsely classified as anamorphic by an exact string comparison.
+ /// A 1% tolerance safely covers encoder rounding artifacts while preserving detection
+ /// of genuine anamorphic content (closest standard is PAL 4:3 at 16:15 = 6.67% off).
+ ///
+ internal static bool IsNearSquarePixelSar(string sar)
+ {
+ if (string.IsNullOrEmpty(sar))
+ {
+ return false;
+ }
+
+ var parts = sar.Split(':');
+ if (parts.Length == 2
+ && double.TryParse(parts[0], CultureInfo.InvariantCulture, out var num)
+ && double.TryParse(parts[1], CultureInfo.InvariantCulture, out var den)
+ && den > 0)
+ {
+ return IsClose(num / den, 1.0, 0.01);
+ }
+
+ return string.Equals(sar, "1:1", StringComparison.Ordinal);
+ }
+
///
/// Gets a frame rate from a string value in ffprobe output
/// This could be a number or in the format of 2997/125.
--
cgit v1.2.3
From d87fe973f3516e20ae4c4ecd8036286deeb4b51d Mon Sep 17 00:00:00 2001
From: NoFear0411 <9083405+NoFear0411@users.noreply.github.com>
Date: Sun, 1 Mar 2026 18:51:27 +0400
Subject: Fix StyleCop and xUnit analyzer errors
- Add missing param and returns XML doc tags (SA1611, SA1615)
- Remove trailing alignment whitespace in test attributes (SA1025)
- Use nullable string parameter for null test case (xUnit1012)
---
.../Probing/ProbeResultNormalizer.cs | 2 ++
.../Probing/ProbeResultNormalizerTests.cs | 28 +++++++++++-----------
2 files changed, 16 insertions(+), 14 deletions(-)
(limited to 'MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs')
diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
index 471df369b..127bdd380 100644
--- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
+++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
@@ -1161,6 +1161,8 @@ namespace MediaBrowser.MediaEncoding.Probing
/// A 1% tolerance safely covers encoder rounding artifacts while preserving detection
/// of genuine anamorphic content (closest standard is PAL 4:3 at 16:15 = 6.67% off).
///
+ /// The sample aspect ratio string in "N:D" format.
+ /// true if the SAR is within 1% of 1:1; otherwise false.
internal static bool IsNearSquarePixelSar(string sar)
{
if (string.IsNullOrEmpty(sar))
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
index 40f853699..8ebbd029a 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
+++ b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs
@@ -40,20 +40,20 @@ namespace Jellyfin.MediaEncoding.Tests.Probing
=> Assert.Equal(expected, ProbeResultNormalizer.GetFrameRate(value));
[Theory]
- [InlineData("1:1", true)] // exact square pixels
- [InlineData("3201:3200", true)] // 0.03% off — encoder rounding artifact (4K HEVC)
- [InlineData("1215:1216", true)] // 0.08% off — encoder rounding artifact
- [InlineData("1001:1000", true)] // 0.1% off — encoder rounding artifact
- [InlineData("16:15", false)] // 6.67% off — PAL DVD 4:3, genuinely anamorphic
- [InlineData("8:9", false)] // 11.1% off — NTSC DVD 4:3
- [InlineData("32:27", false)] // 18.5% off — NTSC DVD 16:9
- [InlineData("10:11", false)] // 9.1% off — DV NTSC
- [InlineData("64:45", false)] // 42.2% off — PAL DVD 16:9
- [InlineData("4:3", false)] // 33.3% off — classic anamorphic
- [InlineData("0:1", false)] // invalid/unknown SAR
- [InlineData("", false)] // empty
- [InlineData(null, false)] // null
- public void IsNearSquarePixelSar_DetectsCorrectly(string sar, bool expected)
+ [InlineData("1:1", true)]
+ [InlineData("3201:3200", true)]
+ [InlineData("1215:1216", true)]
+ [InlineData("1001:1000", true)]
+ [InlineData("16:15", false)]
+ [InlineData("8:9", false)]
+ [InlineData("32:27", false)]
+ [InlineData("10:11", false)]
+ [InlineData("64:45", false)]
+ [InlineData("4:3", false)]
+ [InlineData("0:1", false)]
+ [InlineData("", false)]
+ [InlineData(null, false)]
+ public void IsNearSquarePixelSar_DetectsCorrectly(string? sar, bool expected)
=> Assert.Equal(expected, ProbeResultNormalizer.IsNearSquarePixelSar(sar));
[Fact]
--
cgit v1.2.3