Browse Source

Verify HEVC residual reconstruction against HM

pull/2633/head
James Jackson-South 4 days ago
parent
commit
97538abd29
  1. 7
      src/ImageSharp/Formats/Heif/Hevc/HevcIntraPredictionState.cs
  2. 93
      tests/ImageSharp.Tests/Formats/Heif/Hevc/HevcPictureDecoderTests.cs
  3. 5
      tests/ImageSharp.Tests/TestImages.cs
  4. 3
      tests/Images/Input/Heif/Hevc/Conformance/DELTAQP_A_BRCM_4_frame0.bit
  5. 3
      tests/Images/Input/Heif/Hevc/Conformance/EXTPREC_MAIN_444_16_INTRA_12BIT_RExt_Sony_1.bit
  6. 3
      tests/Images/Input/Heif/Hevc/Conformance/GENERAL_12b_444_RExt_Sony_2_idr7.bit
  7. 3
      tests/Images/Input/Heif/Hevc/Conformance/LS_A_Orange_2.bit
  8. 3
      tests/Images/Input/Heif/Hevc/Conformance/QMATRIX_A_RExt_Sony_1.bit
  9. 8
      tests/Images/Input/Heif/Hevc/Conformance/README.md

7
src/ImageSharp/Formats/Heif/Hevc/HevcIntraPredictionState.cs

@ -102,6 +102,13 @@ internal sealed class HevcIntraPredictionState : IDisposable
this.WidthInMinPredictionBlocks,
this.HeightInMinPredictionBlocks);
// PCM coding units skip intra-mode syntax but remain available as most-probable-mode neighbors. HM
// initializes every luma direction to DC so those units provide the required default until syntax replaces it.
for (int row = 0; row < this.HeightInMinPredictionBlocks; row++)
{
lumaModes.DangerousGetRowSpan(row).Fill(DcMode);
}
this.lumaModes = lumaModes;
this.chromaModes = chromaModes;
this.effectiveChromaModes = effectiveChromaModes;

93
tests/ImageSharp.Tests/Formats/Heif/Hevc/HevcPictureDecoderTests.cs

@ -15,6 +15,48 @@ namespace SixLabors.ImageSharp.Tests.Formats.Heif.Hevc;
[Trait("Format", "Heif")]
public class HevcPictureDecoderTests
{
/// <summary>
/// Identifies residual-tool signaling that an official independently decoded picture must exercise.
/// </summary>
[Flags]
public enum ResidualTools
{
/// <summary>
/// No optional residual tool is signaled.
/// </summary>
None = 0,
/// <summary>
/// Coding-unit luma quantization deltas are signaled.
/// </summary>
DeltaQuantization = 1,
/// <summary>
/// Non-flat quantization scaling matrices are enabled.
/// </summary>
ScalingLists = 2,
/// <summary>
/// Transform skip is enabled.
/// </summary>
TransformSkip = 4,
/// <summary>
/// Range-extension transform precision is enabled.
/// </summary>
ExtendedPrecision = 8,
/// <summary>
/// Transform and quantization bypass is enabled.
/// </summary>
TransquantizationBypass = 16,
/// <summary>
/// A coding-unit chroma quantization-offset list is enabled.
/// </summary>
ChromaQuantizationAdjustment = 32,
}
/// <summary>
/// Verifies the first independently coded picture from official ITU RExt conformance streams against its
/// published decoded-picture hashes.
@ -144,6 +186,57 @@ public class HevcPictureDecoderTests
Assert.Equal("baafaef47a55ae2e876862b30b3bc720", GetPlaneDigest(decoder.Picture, HevcPlane.Cr));
}
/// <summary>
/// Verifies official independently coded residual-tool pictures against pinned-HM native-plane hashes.
/// </summary>
/// <param name="path">The official or provenance-preserving extracted Annex B picture.</param>
/// <param name="bitDepth">The signaled component precision.</param>
/// <param name="chromaFormat">The signaled HEVC chroma-format identifier.</param>
/// <param name="expectedTools">The residual tools that the retained picture signals.</param>
/// <param name="lumaDigest">The pinned-HM luma-plane digest.</param>
/// <param name="chromaBlueDigest">The pinned-HM blue-difference-plane digest.</param>
/// <param name="chromaRedDigest">The pinned-HM red-difference-plane digest.</param>
[Theory]
[InlineData(TestImages.Heif.DeltaQuantizationParameterA, 8, 1, ResidualTools.DeltaQuantization, "2b715c3517e40c00f296260fd0d591c6", "e261d9de5312cba7ac2e355a976ce062", "ca058a402db52ae33aacfcd8c73ae3c6")]
[InlineData(TestImages.Heif.QuantizationMatrixA, 8, 3, ResidualTools.DeltaQuantization | ResidualTools.ScalingLists | ResidualTools.TransformSkip, "6995cec045398044d9cb9668d01fe295", "970394f8a6df16378a39ef2e8fbad354", "1c76949b0ee61b9c1a7d99681a324419")]
[InlineData(TestImages.Heif.ExtendedPrecision12Bit444, 12, 3, ResidualTools.TransformSkip | ResidualTools.ExtendedPrecision, "c8664d56d8391b236a8347397eb97a08", "08cd345d8798ac2714b2939462ac45e2", "5424bce4562f298e983302da697db849")]
[InlineData(TestImages.Heif.ChromaQuantizationAdjustment12Bit444, 12, 3, ResidualTools.TransformSkip | ResidualTools.ChromaQuantizationAdjustment, "0279d9ab84612be260dbd3d4832369b1", "b7eec690a0e5685913ac59d8121ea3e9", "64d7b590e5666f9286204e7e43c6a330")]
[InlineData(TestImages.Heif.LosslessA, 8, 1, ResidualTools.DeltaQuantization | ResidualTools.TransformSkip | ResidualTools.TransquantizationBypass, "6d063ac9bc53ab53e142e300e668c32e", "b69a3e55ff000c0418b79471247ca73f", "1b7449f2f395578ead369f6abde7c4eb")]
public void DecodeOfficialResidualToolsPictureMatchesPinnedHmDigest(
string path,
int bitDepth,
byte chromaFormat,
ResidualTools expectedTools,
string lumaDigest,
string chromaBlueDigest,
string chromaRedDigest)
{
byte[] annexB = TestFile.Create(path).Bytes;
ConvertAnnexBStillPicture(annexB, bitDepth, chromaFormat, out byte[] configurationData, out byte[] itemData);
HevcCodecConfiguration configuration = new(configurationData);
HevcImageItemBitstream bitstream = new(itemData, configuration);
HevcPictureParameterSet pictureParameterSet = bitstream.SliceSegments[0].PictureParameterSet;
HevcSequenceParameterSet sequenceParameterSet = pictureParameterSet.SequenceParameterSet;
using HevcPictureDecoder decoder = new(Configuration.Default, pictureParameterSet);
decoder.Decode(bitstream);
Assert.Equal(bitDepth, decoder.Picture.BitDepthLuma);
Assert.Equal(chromaFormat, decoder.Picture.ChromaFormat);
Assert.Equal((expectedTools & ResidualTools.DeltaQuantization) != 0, pictureParameterSet.CodingUnitQuantizationParameterDeltaEnabled);
Assert.Equal((expectedTools & ResidualTools.ScalingLists) != 0, sequenceParameterSet.ScalingListEnabled);
Assert.Equal((expectedTools & ResidualTools.TransformSkip) != 0, pictureParameterSet.TransformSkipEnabled);
Assert.Equal((expectedTools & ResidualTools.ExtendedPrecision) != 0, sequenceParameterSet.ExtendedPrecisionProcessingEnabled);
Assert.Equal((expectedTools & ResidualTools.TransquantizationBypass) != 0, pictureParameterSet.TransquantizationBypassEnabled);
Assert.Equal(
(expectedTools & ResidualTools.ChromaQuantizationAdjustment) != 0,
pictureParameterSet.ChromaQuantizationParameterOffsetsCb.Count != 0);
Assert.Equal(lumaDigest, GetPlaneDigest(decoder.Picture, HevcPlane.Y));
Assert.Equal(chromaBlueDigest, GetPlaneDigest(decoder.Picture, HevcPlane.Cb));
Assert.Equal(chromaRedDigest, GetPlaneDigest(decoder.Picture, HevcPlane.Cr));
}
/// <summary>
/// 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.

5
tests/ImageSharp.Tests/TestImages.cs

@ -1307,6 +1307,11 @@ public static class TestImages
public const string IntraPredictionB = "Heif/Hevc/Conformance/IPRED_B_Nokia_3.bit";
public const string IntraPredictionBReference = "Heif/Hevc/Conformance/IPRED_B_Nokia_3.yuv";
public const string ConstrainedIntraPredictionA = "Heif/Hevc/Conformance/CIP_A_Panasonic_3.bit";
public const string DeltaQuantizationParameterA = "Heif/Hevc/Conformance/DELTAQP_A_BRCM_4_frame0.bit";
public const string ExtendedPrecision12Bit444 = "Heif/Hevc/Conformance/EXTPREC_MAIN_444_16_INTRA_12BIT_RExt_Sony_1.bit";
public const string ChromaQuantizationAdjustment12Bit444 = "Heif/Hevc/Conformance/GENERAL_12b_444_RExt_Sony_2_idr7.bit";
public const string LosslessA = "Heif/Hevc/Conformance/LS_A_Orange_2.bit";
public const string QuantizationMatrixA = "Heif/Hevc/Conformance/QMATRIX_A_RExt_Sony_1.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";

3
tests/Images/Input/Heif/Hevc/Conformance/DELTAQP_A_BRCM_4_frame0.bit

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4dc49a2aae1cce20d5cd190a1342faf4c3b2bd06d1a59824542b9b22f53c581b
size 230658

3
tests/Images/Input/Heif/Hevc/Conformance/EXTPREC_MAIN_444_16_INTRA_12BIT_RExt_Sony_1.bit

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4107d5bb5df4f95185e7a8a5eef8f35970a4769c76901ff590f38f7bc36b268b
size 205277

3
tests/Images/Input/Heif/Hevc/Conformance/GENERAL_12b_444_RExt_Sony_2_idr7.bit

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:981d97f0adc228f2e3a739d7a68161f84cd60309745397d5cf24d2f81c009dbc
size 86390

3
tests/Images/Input/Heif/Hevc/Conformance/LS_A_Orange_2.bit

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:14251238f005a4576437429a327b34d216b346aaac2a7a05c132a3430174b11b
size 593001

3
tests/Images/Input/Heif/Hevc/Conformance/QMATRIX_A_RExt_Sony_1.bit

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:74847e07f3298923da0e9b68b1f861930d227bd5ad83a834a8280cf042a7e78f
size 236915

8
tests/Images/Input/Heif/Hevc/Conformance/README.md

@ -22,3 +22,11 @@ The intra-prediction fixtures come from the same official HEVC v1 attachment:
- `CIP_A_Panasonic_3` signals constrained intra prediction and contains one I picture followed by one B picture. The bounded still decoder test extracts only the independently coded I picture. The archive SHA-256 is `5C55B3594E5C951C9F5312913961750283EB2DADD15844FE35F9BEB94A9A548C`, and the published bitstream MD5 is `e1e00592fc8a158da9109b4dc05d03be`.
HM at commit `9c1f298659ab0cee9dc13d23d0304221575410b9` reproduces the published `IPRED_B_Nokia_3` YUV MD5 exactly and reports decoded-picture hashes `200ef9f7d2efde44ab872a78a40ece42`, `bfe9de3bef5ce5596a71bbfdbfb823fc`, and `5b14acdd5c5bf8c6887160817ee1ad11`. The same pinned decoder reproduces `CIP_A_Panasonic_3`'s published complete two-picture YUV MD5 `4cbf601ba98d63f642defab5eaa12c8d`; its independently coded first picture reports plane hashes `69a20189e6bbb9c088e3adc967244ca1`, `26502d354bb123f54c20413f14360ddb`, and `baafaef47a55ae2e876862b30b3bc720`.
The residual-reconstruction fixtures come from the official HEVC v1 and Range Extensions attachments. Pinned HM commit `9c1f298659ab0cee9dc13d23d0304221575410b9` decodes every retained independently coded picture and produces the plane hashes asserted by the tests.
- `DELTAQP_A_BRCM_4_frame0.bit` is the exact first independently coded picture extracted from `DELTAQP_A_BRCM_4.bit`. The official archive has SHA-256 `63ABBBAF43D334D7952EAB7BBC5B3E34B4AD0259EDDCD63CDB164DBCF9A36CA6`, the original bitstream has SHA-256 `1274E3E308DFE684B38A88F8B3A2845B84F57492B0B02AAECBE5DC29CA8ED532`, and the retained picture has SHA-256 `4DC49A2AAE1CCE20D5CD190A1342FAF4C3B2BD06D1A59824542B9B22F53C581B`. The official description randomizes `diff_cu_qp_delta_depth` from zero through three and delta QP from -26 through 25; the retained picture contains 384 delta-QP CABAC decisions.
- `QMATRIX_A_RExt_Sony_1.bit` has SHA-256 `74847E07F3298923DA0E9B68B1F861930D227BD5AD83A834A8280CF042A7E78F`. Its official description covers scaling-list data with and without transform skip at every transform size over different QPs; the retained first picture signals scaling lists, coding-unit QP deltas, transform skip, transform-skip contexts and rotation, and implicit residual DPCM.
- `EXTPREC_MAIN_444_16_INTRA_12BIT_RExt_Sony_1.bit` is the second of the official stream's two concatenated one-picture sequences, retained with its own VPS, SPS, and PPS. The official archive has SHA-256 `66C8E24866210B94A63A29C93F8C1490046CC17B26484C5BD81F805D7BFD18D1`, the original bitstream has SHA-256 `5F0164DCCC333296FB2753068CAFE4985B758DDB7E282358DBB8FAF74986817D`, and the retained sequence has SHA-256 `4107D5BB5DF4F95185E7A8A5EEF8F35970A4769C76901FF590F38F7BC36B268B`. This 12-bit GBR sequence is the one that signals extended-precision processing and transform skip. Its reference plane hashes were produced by the pinned HM commit built with its `HIGH_BITDEPTH` option, which is required by HM for this sequence.
- `GENERAL_12b_444_RExt_Sony_2_idr7.bit` is the seventh independently coded picture extracted with its active VPS, SPS, and PPS from the already retained official GENERAL stream. It has SHA-256 `981D97F0ADC228F2E3A739D7A68161F84CD60309745397D5CF24D2F81C009DBC` and contains 39 coding-unit chroma-QP adjustment decisions across 8-, 16-, and 32-sample chroma transforms.
- `LS_A_Orange_2.bit` has SHA-256 `14251238F005A4576437429A327B34D216B346AAAC2A7A05C132A3430174B11B` and published MD5 `9118d01cf6b3671038d6f99342c0895e`. The official lossless description states that every coding unit uses transform, quantization, and filtering bypass; the retained first picture exercises the bypass-flag path and its decoded-picture hash reports OK.

Loading…
Cancel
Save