diff --git a/tests/ImageSharp.Tests/Formats/Heif/Hevc/HevcPictureDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Hevc/HevcPictureDecoderTests.cs
index f556aa169..3205c6712 100644
--- a/tests/ImageSharp.Tests/Formats/Heif/Hevc/HevcPictureDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Heif/Hevc/HevcPictureDecoderTests.cs
@@ -80,6 +80,57 @@ public class HevcPictureDecoderTests
}
}
+ ///
+ /// Verifies coding-tree and transform-tree conformance streams against native-plane digests produced by the
+ /// pinned HM decoder from output that matches each archive's published checksum.
+ ///
+ /// The official Annex B conformance stream.
+ /// The expected coding-tree-block size logarithm.
+ /// The expected minimum coding-block size logarithm.
+ /// The expected minimum transform-block size logarithm.
+ /// The expected internal intra transform-depth limit.
+ /// The reference luma-plane MD5 digest.
+ /// The reference blue-difference-plane MD5 digest.
+ /// The reference red-difference-plane MD5 digest.
+ [Theory]
+ [InlineData(TestImages.Heif.RqtA, 6, 3, 2, 1, "adf2bfab6de808840c82f48eee31a0a5", "4b29b1d2699b77e42a4e22fb0d70993e", "8ada6d784647329a4f0da232176914f4")]
+ [InlineData(TestImages.Heif.RqtB, 6, 3, 2, 2, "797f41be9a4d53b640332f9d03b1f304", "ef67e5ceff912f7aeb14f2e00ddd5cbf", "e2af5fa6f3c4bcc96dfa95cb8947a7db")]
+ [InlineData(TestImages.Heif.RqtC, 6, 3, 2, 3, "5d431346cd0b3f52846fc20fc0afdcc4", "ff9355b8cc72d77edbad6f5bd4938df1", "24f8aae8c00f418af487be29d2a5a126")]
+ [InlineData(TestImages.Heif.RqtD, 6, 3, 2, 4, "30138fa13664590d16355be8f7362eb2", "6198b3d1e990baadcaa533b4c44a5be2", "45f5427aec28b4f4655240812387607b")]
+ [InlineData(TestImages.Heif.RqtE, 6, 3, 2, 5, "e9e182380f3209ef877b75199b546c00", "f555fd054855dc5a1cb82cb8f3393b5a", "baed53765a5424fbc38aa541917d0625")]
+ [InlineData(TestImages.Heif.StructA, 4, 3, 2, 2, "bf47fb8ff96a225c2646c0539744ac93", "c105b60fd0e8740574fb76972bbc3b1a", "f9e2d8327da50734b54771df29b343bb")]
+ [InlineData(TestImages.Heif.StructB, 5, 4, 2, 2, "61e13729a4e3d6fd96f5002a501d1d60", "fee8312ceaccb1f254ef21449f104e4e", "dbe684d5fffbbc2f5ca90b205018060c")]
+ [InlineData(TestImages.Heif.TuSizeA, 6, 5, 4, 3, "17a84e6f516dbcb8810c7548bf6e216c", "edd3085f7a152d7ffaabae816f4942ac", "e8b47494064c1a730aca3c6ee23572c8")]
+ public void DecodeOfficialTraversalPictureMatchesPinnedHmDigest(
+ string path,
+ int expectedCodingTreeBlockLog2,
+ int expectedMinCodingBlockLog2,
+ int expectedMinTransformBlockLog2,
+ int expectedMaxTransformHierarchyDepthIntra,
+ string lumaDigest,
+ string chromaBlueDigest,
+ string chromaRedDigest)
+ {
+ byte[] annexB = TestFile.Create(path).Bytes;
+ ConvertAnnexBStillPicture(annexB, 8, 1, out byte[] configurationData, out byte[] itemData);
+ HevcCodecConfiguration configuration = new(configurationData);
+ HevcImageItemBitstream bitstream = new(itemData, configuration);
+ HevcSequenceParameterSet sequenceParameterSet = bitstream.SliceSegments[0].PictureParameterSet.SequenceParameterSet;
+ using HevcPictureDecoder decoder = new(Configuration.Default, bitstream.SliceSegments[0].PictureParameterSet);
+
+ decoder.Decode(bitstream);
+
+ Assert.Equal(8, decoder.Picture.BitDepthLuma);
+ Assert.Equal(1, decoder.Picture.ChromaFormat);
+ Assert.Equal(expectedCodingTreeBlockLog2, sequenceParameterSet.CodingTreeBlockLog2);
+ Assert.Equal(expectedMinCodingBlockLog2, sequenceParameterSet.MinCodingBlockLog2);
+ Assert.Equal(expectedMinTransformBlockLog2, sequenceParameterSet.MinTransformBlockLog2);
+ Assert.Equal(expectedMaxTransformHierarchyDepthIntra, sequenceParameterSet.MaxTransformHierarchyDepthIntra);
+ Assert.Equal(lumaDigest, GetPlaneDigest(decoder.Picture, HevcPlane.Y));
+ Assert.Equal(chromaBlueDigest, GetPlaneDigest(decoder.Picture, HevcPlane.Cb));
+ Assert.Equal(chromaRedDigest, GetPlaneDigest(decoder.Picture, HevcPlane.Cr));
+ }
+
///
/// Verifies all reconstructed samples from a real HEIC grid tile against the HM reference decoder.
///
@@ -290,11 +341,12 @@ public class HevcPictureDecoderTests
}
}
- Assert.True(
- mismatchCount == 0,
+ string message =
$"{plane} contained {mismatchCount} differing samples. The maximum difference was {maximumDifference}; " +
$"the mismatches span ({minimumMismatchX}, {minimumMismatchY}) through ({maximumMismatchX}, {maximumMismatchY}), " +
- $"and the first mismatch at ({firstMismatchX}, {firstMismatchY}) was {firstActual}, expected {firstExpected}.");
+ $"and the first mismatch at ({firstMismatchX}, {firstMismatchY}) was {firstActual}, expected {firstExpected}.";
+
+ Assert.True(mismatchCount == 0, message);
}
///
@@ -593,7 +645,6 @@ public class HevcPictureDecoderTests
Assert.Single(
allocator.ReturnLog,
returned => returned.AllocationId == allocation.AllocationId);
-
}
}
diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs
index 297fc0921..97a5a9329 100644
--- a/tests/ImageSharp.Tests/TestImages.cs
+++ b/tests/ImageSharp.Tests/TestImages.cs
@@ -1304,6 +1304,14 @@ public static class TestImages
public const string General12Bit420 = "Heif/Hevc/Conformance/GENERAL_12b_420_RExt_Sony_1.bit";
public const string General12Bit422 = "Heif/Hevc/Conformance/GENERAL_12b_422_RExt_Sony_1.bit";
public const string General12Bit444 = "Heif/Hevc/Conformance/GENERAL_12b_444_RExt_Sony_2.bit";
+ public const string RqtA = "Heif/Hevc/Conformance/RQT_A_HHI_4.bit";
+ public const string RqtB = "Heif/Hevc/Conformance/RQT_B_HHI_4.bit";
+ public const string RqtC = "Heif/Hevc/Conformance/RQT_C_HHI_4.bit";
+ public const string RqtD = "Heif/Hevc/Conformance/RQT_D_HHI_4.bit";
+ public const string RqtE = "Heif/Hevc/Conformance/RQT_E_HHI_4.bit";
+ public const string StructA = "Heif/Hevc/Conformance/STRUCT_A_Samsung_7.bit";
+ public const string StructB = "Heif/Hevc/Conformance/STRUCT_B_Samsung_7.bit";
+ public const string TuSizeA = "Heif/Hevc/Conformance/TUSIZE_A_Samsung_1.bit";
public const string Image1 = "Heif/image1.heic";
public const string Image2 = "Heif/image2.heic";
public const string Image3 = "Heif/image3.heic";
diff --git a/tests/Images/Input/Heif/Hevc/Conformance/README.md b/tests/Images/Input/Heif/Hevc/Conformance/README.md
index 098a490c3..0d2cde298 100644
--- a/tests/Images/Input/Heif/Hevc/Conformance/README.md
+++ b/tests/Images/Input/Heif/Hevc/Conformance/README.md
@@ -1,9 +1,17 @@
-# HEVC Range Extensions conformance fixtures
+# HEVC conformance fixtures
These fixtures come from the electronic attachment to [ITU-T H.265.1 (10/2018)](https://www.itu.int/rec/T-REC-H.265.1-201810-I/en), the conformance specification aligned with ISO/IEC 23008-8. Table 4 identifies the Sony `GENERAL_*_RExt` streams and their required profiles.
-The `.bit` files are the original Annex B conformance streams. Each `_frame0.yuv` file contains the first decoded picture extracted byte-for-byte from the corresponding published planar reference output; it was not generated by ImageSharp.
+The `.bit` files are the original Annex B conformance streams. The Samsung archives name their payloads `.bin`; the repository stores those unchanged bytes with the common `.bit` extension. Each `GENERAL_*_frame0.yuv` file contains the first decoded picture extracted byte-for-byte from the corresponding published planar reference output; it was not generated by ImageSharp.
`HevcPictureDecoderTests.DecodeOfficialRangeExtensionsPictureMatchesPublishedDigest` limits each stream to its first independently coded picture, adapts that picture to the bounded `hvc1` item contract, compares every reconstructed sample with `_frame0.yuv`, and verifies the published decoded-picture MD5 value for every present plane.
The retained matrix covers the ImageSharp 8, 10, and 12-bit still-image precision boundary across monochrome, 4:2:0, 4:2:2, and 4:4:4. Tool-specific H.265.1 streams remain necessary before every exposed Range Extensions tool can be marked complete.
+
+The Main-profile traversal matrix comes from the official `RQT_A_HHI_4` through `RQT_E_HHI_4`, `STRUCT_A_Samsung_7`, `STRUCT_B_Samsung_7`, and `TUSIZE_A_Samsung_1` archives. Their published descriptions target residual-quadtree intra hierarchy depths zero through four, coding-tree and minimum-coding-unit structure, and a 64x64 coding-tree block with 32x32 minimum coding units and 16x16 minimum luma transforms, respectively.
+
+`HevcPictureDecoderTests.DecodeOfficialTraversalPictureMatchesPinnedHmDigest` decodes each first independently coded picture through the production still-item path and compares all three native planes with fixed MD5 digests. The RQT values are the streams' decoded-picture-hash SEI values. For STRUCT and TUSIZE, the plane values were calculated from the first picture written by the [HM reference decoder at commit `9c1f298659ab0cee9dc13d23d0304221575410b9`](https://vcgit.hhi.fraunhofer.de/jvet/HM/-/commit/9c1f298659ab0cee9dc13d23d0304221575410b9); the complete HM output also matched each archive's published file MD5:
+
+- `STRUCT_A_Samsung_7`: `02f02cc9a67222004ae18ee6bebd475a`
+- `STRUCT_B_Samsung_7`: `1f472e014aff120681e8482c8a04ef93`
+- `TUSIZE_A_Samsung_1`: `5e6c198c852e92cdcca0e137fc2610c4`
diff --git a/tests/Images/Input/Heif/Hevc/Conformance/RQT_A_HHI_4.bit b/tests/Images/Input/Heif/Hevc/Conformance/RQT_A_HHI_4.bit
new file mode 100644
index 000000000..8466c1c00
--- /dev/null
+++ b/tests/Images/Input/Heif/Hevc/Conformance/RQT_A_HHI_4.bit
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c07a976943200d97ba9eb0a16a858d2c77fb3fe37410c6c6f956e5960b2f4621
+size 66244
diff --git a/tests/Images/Input/Heif/Hevc/Conformance/RQT_B_HHI_4.bit b/tests/Images/Input/Heif/Hevc/Conformance/RQT_B_HHI_4.bit
new file mode 100644
index 000000000..6a9a096ac
--- /dev/null
+++ b/tests/Images/Input/Heif/Hevc/Conformance/RQT_B_HHI_4.bit
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:49a8037bbbed4efa8de285c522d215c3c5a117dd58d17822db0ffb9808161e29
+size 66149
diff --git a/tests/Images/Input/Heif/Hevc/Conformance/RQT_C_HHI_4.bit b/tests/Images/Input/Heif/Hevc/Conformance/RQT_C_HHI_4.bit
new file mode 100644
index 000000000..bc5295c2c
--- /dev/null
+++ b/tests/Images/Input/Heif/Hevc/Conformance/RQT_C_HHI_4.bit
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a7b157215595b68ddbb70d952fb786923826c26ecc448bbfe36f4df47f9abc5c
+size 66094
diff --git a/tests/Images/Input/Heif/Hevc/Conformance/RQT_D_HHI_4.bit b/tests/Images/Input/Heif/Hevc/Conformance/RQT_D_HHI_4.bit
new file mode 100644
index 000000000..052db04bb
--- /dev/null
+++ b/tests/Images/Input/Heif/Hevc/Conformance/RQT_D_HHI_4.bit
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6b37468d7e4acf7d1fb97bf0062e0124785d3bda1284e1f698a1e8eb6441d76b
+size 66078
diff --git a/tests/Images/Input/Heif/Hevc/Conformance/RQT_E_HHI_4.bit b/tests/Images/Input/Heif/Hevc/Conformance/RQT_E_HHI_4.bit
new file mode 100644
index 000000000..111213496
--- /dev/null
+++ b/tests/Images/Input/Heif/Hevc/Conformance/RQT_E_HHI_4.bit
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d792e442c19d9ffc45f43a8842c7a6ad57d0a51d62364c43ef97810689c2eea8
+size 84820
diff --git a/tests/Images/Input/Heif/Hevc/Conformance/STRUCT_A_Samsung_7.bit b/tests/Images/Input/Heif/Hevc/Conformance/STRUCT_A_Samsung_7.bit
new file mode 100644
index 000000000..144dcaa04
--- /dev/null
+++ b/tests/Images/Input/Heif/Hevc/Conformance/STRUCT_A_Samsung_7.bit
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e511007d79d66f6988654a7f89a934cd68329be6492143cda9570e3741f5a551
+size 319053
diff --git a/tests/Images/Input/Heif/Hevc/Conformance/STRUCT_B_Samsung_7.bit b/tests/Images/Input/Heif/Hevc/Conformance/STRUCT_B_Samsung_7.bit
new file mode 100644
index 000000000..654dd6ea6
--- /dev/null
+++ b/tests/Images/Input/Heif/Hevc/Conformance/STRUCT_B_Samsung_7.bit
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e58b04f1434449721957857ca38adab3865b71cb93ae9705a4361b7cb4400d8e
+size 324322
diff --git a/tests/Images/Input/Heif/Hevc/Conformance/TUSIZE_A_Samsung_1.bit b/tests/Images/Input/Heif/Hevc/Conformance/TUSIZE_A_Samsung_1.bit
new file mode 100644
index 000000000..7475185e8
--- /dev/null
+++ b/tests/Images/Input/Heif/Hevc/Conformance/TUSIZE_A_Samsung_1.bit
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:23c9959a0dd09d9a0b9c64b980794ca18214d7a3cb0fd091ca87f98dda75acf4
+size 1238476