Browse Source

Verify official AV1 quantizer boundaries

pull/2633/head
James Jackson-South 4 days ago
parent
commit
68cbe2fb94
  1. 3
      HEIF_IMPLEMENTATION_PLAN.md
  2. 133
      tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReconstructionConformanceTests.cs
  3. 8
      tests/ImageSharp.Tests/TestImages.cs
  4. 7
      tests/Images/Input/Heif/Av1/Conformance/README.md
  5. 3
      tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b10-00-quantizer-00-libaom.y4m
  6. 3
      tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b10-00-quantizer-00.ivf
  7. 3
      tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b10-00-quantizer-63-libaom.y4m
  8. 3
      tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b10-00-quantizer-63.ivf
  9. 3
      tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b8-00-quantizer-00-libaom.y4m
  10. 3
      tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b8-00-quantizer-00.ivf
  11. 3
      tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b8-00-quantizer-63-libaom.y4m
  12. 3
      tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b8-00-quantizer-63.ivf

3
HEIF_IMPLEMENTATION_PLAN.md

@ -131,7 +131,8 @@ Immediate checkpoint: **remaining — close the Phase 3 AV1 still-image decode e
- [x] Correct the audited 12-bit inverse ADST4, Identity4, and Identity16 SIMD arithmetic by widening only the libaom-widened multiply/accumulate operations, with exact conformant-range vectors and `FeatureTestRunner` coverage. Both 128-bit and 256-bit operators match pinned outputs through every required hardware fallback; 510 focused inverse-transform cases, 44 production reconstruction cases, both zero-warning source builds, the zero-error analyzer build, zero Roslynk compiler errors, and clean `git diff --check` complete the verification.
- [x] Verify the official libaom all-intra, CDF-update, and temporal motion-field sequences through exact native output, selected syntax coverage, normal/scalar dispatch, constrained tracked allocation, and the family-owned JPEG-style predictor operator architecture.
- [ ] **Current:** continue inventorying and removing every remaining valid AV1 still-image unsupported branch, adding exact independent compression-tool fixtures to the profile-matrix regression gate.
- [x] Add the missing official ten-bit sequence evidence from libaom's pinned test-data manifest. All ten active-film-grain YUV420 frames and all ten monochrome frames match the pinned generic libaom native Y4M samples exactly under normal and scalar `FeatureTestRunner` dispatch, and both complete sequences pass through a 2 KiB constrained tracked allocator with balanced exactly-once returns. The existing production decoder required no correction.
- [x] Add the missing official ten-bit sequence evidence from libaom's pinned test-data manifest. All ten active-film-grain YUV420 frames and all ten monochrome frames match the pinned generic libaom native Y4M samples exactly under normal and scalar `FeatureTestRunner` dispatch, and both complete sequences pass through a 2 KiB constrained tracked allocator with balanced exactly-once returns. The three new focused cases and all 20 official-sequence regression cases pass without failures or skips, the scoped Release test-project analyzer build completes with zero errors and 1,011 repository warnings, Roslynk reports zero compiler errors, and `git diff --check` is clean. The existing production decoder required no correction. Commit `deefeba2340932909aa3e27516d965a294cf6faa` records the checkpoint.
- [x] Add official minimum- and maximum-quantizer dependent-frame evidence for the eight- and ten-bit libaom matrices. The four retained streams and pinned generic-libaom Y4M references pass exact native comparison under normal and scalar `FeatureTestRunner` dispatch, and the combined sequences pass through a 2,560-byte row-aligned constrained tracked allocator with balanced exactly-once returns. All three new focused cases and all 23 official-sequence regression cases pass without failures or skips, the scoped Release test-project analyzer build completes with zero errors and 1,011 repository warnings, Roslynk reports zero compiler errors, and `git diff --check` is clean. The existing production decoder required no correction.
- [ ] Complete the remaining HEVC still-image profile and Range Extensions matrix with exact independent native-plane and presentation evidence.
- [ ] Close shared decoded presentation, ICC, alpha, grid, transform, metadata, and animated AV1/HEVC decode gates.
- [ ] Implement and independently verify real AV1/AVIF still encoding.

133
tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReconstructionConformanceTests.cs

@ -251,6 +251,31 @@ public class Av1ReconstructionConformanceTests
/// </summary>
private const int OfficialMonochromeFixtureFrameCount = 10;
/// <summary>
/// The width of the official libaom eight-bit quantizer-boundary sequences.
/// </summary>
private const int OfficialEightBitQuantizerFixtureWidth = 352;
/// <summary>
/// The height of the official libaom eight-bit quantizer-boundary sequences.
/// </summary>
private const int OfficialEightBitQuantizerFixtureHeight = 288;
/// <summary>
/// The width of the official libaom ten-bit quantizer-boundary sequences.
/// </summary>
private const int OfficialTenBitQuantizerFixtureWidth = 640;
/// <summary>
/// The height of the official libaom ten-bit quantizer-boundary sequences.
/// </summary>
private const int OfficialTenBitQuantizerFixtureHeight = 360;
/// <summary>
/// The number of frames in each official libaom quantizer-boundary sequence.
/// </summary>
private const int OfficialQuantizerFixtureFrameCount = 2;
/// <summary>
/// The coverage bit representing tile-local adaptive CDF updates.
/// </summary>
@ -1633,6 +1658,109 @@ public class Av1ReconstructionConformanceTests
returned => returned.AllocationId == allocation.AllocationId));
}
/// <summary>
/// Verifies the official eight-bit quantizer boundaries against exact pinned-libaom native output.
/// </summary>
[Fact]
public void DecodeOfficialEightBitQuantizerBoundarySequencesMatchPinnedLibaomReferences()
=> FeatureTestRunner.RunWithHwIntrinsicsFeature(
ValidateOfficialEightBitQuantizerBoundaryFixtures,
ReconstructionConfigurations);
/// <summary>
/// Decodes the official eight-bit quantizer boundaries.
/// </summary>
private static void ValidateOfficialEightBitQuantizerBoundaryFixtures()
=> ValidateOfficialEightBitQuantizerBoundaryFixturesWithConfiguration(Configuration.Default);
/// <summary>
/// Verifies the official ten-bit quantizer boundaries against exact pinned-libaom native output.
/// </summary>
[Fact]
public void DecodeOfficialTenBitQuantizerBoundarySequencesMatchPinnedLibaomReferences()
=> FeatureTestRunner.RunWithHwIntrinsicsFeature(
ValidateOfficialTenBitQuantizerBoundaryFixtures,
ReconstructionConfigurations);
/// <summary>
/// Decodes the official ten-bit quantizer boundaries.
/// </summary>
private static void ValidateOfficialTenBitQuantizerBoundaryFixtures()
=> ValidateOfficialTenBitQuantizerBoundaryFixturesWithConfiguration(Configuration.Default);
/// <summary>
/// Verifies the official quantizer boundaries through constrained tracked allocation.
/// </summary>
[Fact]
[ValidateDisposedMemoryAllocations]
public void DecodeOfficialQuantizerBoundarySequencesWithConstrainedAllocator()
{
TestMemoryAllocator allocator = new() { BufferCapacityInBytes = 2_560 };
allocator.EnableNonThreadSafeLogging();
Configuration configuration = Configuration.Default.Clone();
configuration.MemoryAllocator = allocator;
ValidateOfficialEightBitQuantizerBoundaryFixturesWithConfiguration(configuration);
ValidateOfficialTenBitQuantizerBoundaryFixturesWithConfiguration(configuration);
Assert.Equal(allocator.AllocationLog.Count, allocator.ReturnLog.Count);
Assert.All(
allocator.AllocationLog,
allocation => Assert.Single(
allocator.ReturnLog,
returned => returned.AllocationId == allocation.AllocationId));
}
/// <summary>
/// Decodes both retained official eight-bit quantizer-boundary fixtures.
/// </summary>
private static void ValidateOfficialEightBitQuantizerBoundaryFixturesWithConfiguration(Configuration configuration)
{
ValidateOfficialCompactSequence(
configuration,
TestImages.Heif.Av1OfficialEightBitMinimumQuantizerSequence,
TestImages.Heif.Av1OfficialEightBitMinimumQuantizerSequenceNativeReference,
OfficialQuantizerFixtureFrameCount,
OfficialEightBitQuantizerFixtureWidth,
OfficialEightBitQuantizerFixtureHeight);
ValidateOfficialCompactSequence(
configuration,
TestImages.Heif.Av1OfficialEightBitMaximumQuantizerSequence,
TestImages.Heif.Av1OfficialEightBitMaximumQuantizerSequenceNativeReference,
OfficialQuantizerFixtureFrameCount,
OfficialEightBitQuantizerFixtureWidth,
OfficialEightBitQuantizerFixtureHeight);
}
/// <summary>
/// Decodes both retained official ten-bit quantizer-boundary fixtures.
/// </summary>
private static void ValidateOfficialTenBitQuantizerBoundaryFixturesWithConfiguration(Configuration configuration)
{
ValidateOfficialCompactSequence(
configuration,
TestImages.Heif.Av1OfficialTenBitMinimumQuantizerSequence,
TestImages.Heif.Av1OfficialTenBitMinimumQuantizerSequenceNativeReference,
OfficialQuantizerFixtureFrameCount,
OfficialTenBitQuantizerFixtureWidth,
OfficialTenBitQuantizerFixtureHeight,
Av1ColorFormat.Yuv420,
Av1BitDepth.TenBit,
"60:1");
ValidateOfficialCompactSequence(
configuration,
TestImages.Heif.Av1OfficialTenBitMaximumQuantizerSequence,
TestImages.Heif.Av1OfficialTenBitMaximumQuantizerSequenceNativeReference,
OfficialQuantizerFixtureFrameCount,
OfficialTenBitQuantizerFixtureWidth,
OfficialTenBitQuantizerFixtureHeight,
Av1ColorFormat.Yuv420,
Av1BitDepth.TenBit,
"60:1");
}
/// <summary>
/// Decodes one compact official IVF sequence, compares every native sample, and returns its active frame-state
/// coverage mask.
@ -1645,7 +1773,8 @@ public class Av1ReconstructionConformanceTests
int expectedWidth = OfficialMotionVectorFixtureWidth,
int expectedHeight = OfficialMotionVectorFixtureHeight,
Av1ColorFormat expectedColorFormat = Av1ColorFormat.Yuv420,
Av1BitDepth expectedBitDepth = Av1BitDepth.EightBit)
Av1BitDepth expectedBitDepth = Av1BitDepth.EightBit,
string expectedFrameRate = "30:1")
{
byte[] ivf = TestFile.Create(fixturePath).Bytes;
byte[] nativeReference = TestFile.Create(nativeReferencePath).Bytes;
@ -1671,7 +1800,7 @@ public class Av1ReconstructionConformanceTests
ReadOnlySpan<byte> y4mFileHeader = hasY4mHeaders
? Encoding.ASCII.GetBytes(
$"YUV4MPEG2 W{expectedWidth} H{expectedHeight} F30:1 Ip {y4mColorSpace}\n")
$"YUV4MPEG2 W{expectedWidth} H{expectedHeight} F{expectedFrameRate} Ip {y4mColorSpace}\n")
: [];
ReadOnlySpan<byte> y4mFrameHeader = "FRAME\n"u8;

8
tests/ImageSharp.Tests/TestImages.cs

@ -1390,6 +1390,14 @@ public static class TestImages
public const string Av1GlobalWarpSequencePresentationReference = "Heif/Av1/Conformance/libavif-rotating-grid-global-warp-libavif.png";
public const string Av1OfficialAllIntraSequence = "Heif/Av1/Conformance/libaom-av1-1-b8-02-allintra.ivf";
public const string Av1OfficialAllIntraSequenceNativeReference = "Heif/Av1/Conformance/libaom-av1-1-b8-02-allintra-libaom.y4m";
public const string Av1OfficialEightBitMinimumQuantizerSequence = "Heif/Av1/Conformance/libaom-av1-1-b8-00-quantizer-00.ivf";
public const string Av1OfficialEightBitMinimumQuantizerSequenceNativeReference = "Heif/Av1/Conformance/libaom-av1-1-b8-00-quantizer-00-libaom.y4m";
public const string Av1OfficialEightBitMaximumQuantizerSequence = "Heif/Av1/Conformance/libaom-av1-1-b8-00-quantizer-63.ivf";
public const string Av1OfficialEightBitMaximumQuantizerSequenceNativeReference = "Heif/Av1/Conformance/libaom-av1-1-b8-00-quantizer-63-libaom.y4m";
public const string Av1OfficialTenBitMinimumQuantizerSequence = "Heif/Av1/Conformance/libaom-av1-1-b10-00-quantizer-00.ivf";
public const string Av1OfficialTenBitMinimumQuantizerSequenceNativeReference = "Heif/Av1/Conformance/libaom-av1-1-b10-00-quantizer-00-libaom.y4m";
public const string Av1OfficialTenBitMaximumQuantizerSequence = "Heif/Av1/Conformance/libaom-av1-1-b10-00-quantizer-63.ivf";
public const string Av1OfficialTenBitMaximumQuantizerSequenceNativeReference = "Heif/Av1/Conformance/libaom-av1-1-b10-00-quantizer-63-libaom.y4m";
public const string Av1OfficialCdfUpdateSequence = "Heif/Av1/Conformance/libaom-av1-1-b8-04-cdfupdate.ivf";
public const string Av1OfficialCdfUpdateSequenceNativeReference = "Heif/Av1/Conformance/libaom-av1-1-b8-04-cdfupdate-libaom.y4m";
public const string Av1OfficialMotionVectorSequence = "Heif/Av1/Conformance/libaom-av1-1-b8-05-mv.ivf";

7
tests/Images/Input/Heif/Av1/Conformance/README.md

@ -36,6 +36,7 @@ The reference builds use `AOM_TARGET_CPU=generic` and disable libyuv. Native rec
| `*-intrabc-*` | Intra-block copy at every supported bit depth |
| `*-lossless-*` | Lossless quantization, reversible transforms, and exact presentation |
| `*-film-grain-*` | Full and restricted range, monochrome, identity matrix, 8/10/12-bit synthesis, overlap, and odd frame dimensions |
| `libaom-av1-1-b8-00-quantizer-*`, `libaom-av1-1-b10-00-quantizer-*` | Official minimum- and maximum-quantizer dependent-frame reconstruction |
| `libaom-av1-1-b10-23`, `libaom-av1-1-b10-24` | Official ten-bit dependent-frame film grain and monochrome sequence reconstruction |
| `libavif-progressive-draw-points-8b` | A real two-layer color item whose final frame uses single-reference inter reconstruction, plus its progressive auxiliary alpha item |
| `libavif-webp-logo-average-compound` | A 19-frame YUV444 image sequence whose retained references reach equal-weight compound inter reconstruction |
@ -62,6 +63,12 @@ aomdec --threads=1 --output=libaom-av1-1-b10-24-monochrome-libaom.y4m libaom-av1
The film-grain Y4M SHA-256 is `A1B553BE140F48ABDDB2A6D39917AB714BA03AC7FFD6359EAA1CB0D89C985A3B`, and the monochrome Y4M SHA-256 is `7394BC8146485D200BFDEC62E170482F8B1A85A64D21FAC62D10116FB1BB140D`. The tests decode and compare all ten frames from each sequence exactly under normal and scalar dispatch. The film-grain stream retains dependent ungrained references while applying ten-bit grain to each displayed 352x288 YUV420 frame; the monochrome stream verifies every 320x180 ten-bit luma sample without manufacturing chroma in ImageSharp. Both sequences also run through a constrained tracked allocator.
## Official quantizer-boundary fixtures
The retained `quantizer-00` and `quantizer-63` streams are the minimum- and maximum-quantizer boundaries from libaom's official eight- and ten-bit test matrices. Their SHA-1 values are `C2E1EC9936B95254187A359E94AA32A9F3DAD1B7`, `2A8AA33513D8E01AE9410C4BF5FE1E471B775482`, `9BBE8499796AA588FF02E313FB0D4349940D2FEA`, and `8B6EB3FFF2E0DB7EAC775B08C745250CA591E2D9`, exactly matching `test/test-data.sha1` at pinned libaom commit `03087864cf4bea6abb0d28f95cf7843511413d8f`. Their SHA-256 values, in the same order, are `6382DBD2BEFBBC93D4EA283586F4FB43FEA5F1C52400E3D2C5281A46B1104C00`, `0E4EC80680F7AF8DE9621B016E0F2D7C0858B2951DEBC173DDA50C6A051547D3`, `FE6053CE4EE20A1C0EC6F7FE35DB097E92AD25D8A3505598BD89162C74D7944F`, and `39759AB77483E1D11049DC38B5F5262158FD9C3CBC9D1F82A02462FC5DF30E0C`.
The native references were generated with the pinned generic `aomdec --threads=1` build. Their SHA-256 values are `D499028E0606DB70CD56A72F151E04F36C09F300A448CCCD8430DD920D3589C5`, `4CC9892B3EE3399B293E31014B9F566C21E0C7A4765FC5F444528769C33E6D67`, `78373C28F401EB95D3E563D146622ED6C714ED96661E5E57C539CE71D7BED599`, and `A9DF86F671B8CF01EFC130660556412D4EBAF31A81D6F26FBDAEB0A7E839D8EA`. Each reference's two raw-frame MD5 values also match the corresponding official `.ivf.md5` file exactly. The tests compare every native sample under normal and scalar `FeatureTestRunner` dispatch and run all four sequences through a 2,560-byte row-aligned constrained tracked allocator.
## Progressive dependent-frame fixture
The `libavif-progressive-draw-points-8b.avif` fixture is the unmodified `tests/data/draw_points_idat_progressive.avif` file from the pinned libavif tree. Its SHA-256 is `077AB2AD1E46DD912A973E4F024CB1EB242A08298BE2DBF1A52A058E88C48A4A`. It was generated with:

3
tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b10-00-quantizer-00-libaom.y4m

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:78373c28f401eb95d3e563d146622ed6c714ed96661e5e57c539ce71d7bed599
size 1382463

3
tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b10-00-quantizer-00.ivf

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

3
tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b10-00-quantizer-63-libaom.y4m

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

3
tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b10-00-quantizer-63.ivf

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:39759ab77483e1d11049dc38b5f5262158fd9c3cbc9d1f82a02462fc5df30e0c
size 1243

3
tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b8-00-quantizer-00-libaom.y4m

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

3
tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b8-00-quantizer-00.ivf

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6382dbd2befbbc93d4ea283586f4fb43fea5f1c52400e3d2c5281a46b1104c00
size 128943

3
tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b8-00-quantizer-63-libaom.y4m

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

3
tests/Images/Input/Heif/Av1/Conformance/libaom-av1-1-b8-00-quantizer-63.ivf

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0e4ec80680f7af8de9621b016e0f2d7c0858b2951debc173dda50c6a051547d3
size 606
Loading…
Cancel
Save