Browse Source

Complete AV1 decoder negative-path checkpoint

pull/2633/head
James Jackson-South 2 days ago
parent
commit
7f0e08126b
  1. 27
      HEIF_IMPLEMENTATION_PLAN.md
  2. 99
      tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReconstructionConformanceTests.cs
  3. 1
      tests/ImageSharp.Tests/Image/ImageTests.Decode_Cancellation.cs
  4. 2
      tests/ImageSharp.Tests/TestImages.cs
  5. 18
      tests/Images/Input/Heif/Av1/Conformance/README.md
  6. 3
      tests/Images/Input/Heif/Av1/Conformance/libaom-frame-id-196x196-8b-libaom.y4m
  7. 3
      tests/Images/Input/Heif/Av1/Conformance/libaom-frame-id-196x196-8b.ivf

27
HEIF_IMPLEMENTATION_PLAN.md

@ -82,7 +82,7 @@ Recovered task-history evidence from 2026-08-31:
### 2. Correct the single-reference inter-frame checkpoint ### 2. Correct the single-reference inter-frame checkpoint
The committed checkpoint remains valid through `57a3f6668e39d0934e7b6b8d37a3dc2a5adc88f0`. The current checkpoint replaces frame-sized palette maps with fixed decoder-session scratch, reconstructs each superblock before reusing that scratch, and passes the ownership, documentation, full AV1 test, and Release source-build gates on both target frameworks. The checkpoint is complete through `c4b4e4e0386328dea574a884b6fa36c360ad5a9b`. It replaces frame-sized palette maps with fixed decoder-session scratch, reconstructs each superblock before reusing that scratch, and passes the ownership, documentation, full AV1 test, and Release source-build gates on both target frameworks.
- [x] Reconcile interpolation-filter syntax in `Av1TileReader` with current libaom `main`. - [x] Reconcile interpolation-filter syntax in `Av1TileReader` with current libaom `main`.
- Current libaom `av1_is_interp_needed` calls `is_nontrans_global_motion`, whose loop rejects only `TRANSLATION`. Identity GLOBALMV therefore omits switchable-filter symbols. - Current libaom `av1_is_interp_needed` calls `is_nontrans_global_motion`, whose loop rejects only `TRANSLATION`. Identity GLOBALMV therefore omits switchable-filter symbols.
@ -122,6 +122,7 @@ Checkpoint gate:
- [x] The complete AV1 namespace passes 8,732 of 8,732 tests on net10.0 and net11.0 with zero failures or skips. - [x] The complete AV1 namespace passes 8,732 of 8,732 tests on net10.0 and net11.0 with zero failures or skips.
- [x] Roslynk reports zero compiler errors; scoped analyzer inspection reports no diagnostics introduced by the current changes; `git diff --check` passes. - [x] Roslynk reports zero compiler errors; scoped analyzer inspection reports no diagnostics introduced by the current changes; `git diff --check` passes.
- [x] The completed checkpoint was committed as `54bb6cbe59bd113058854a3ee31448cf61f462ca` with author and committer `James Jackson-South <james_south@hotmail.com>`. - [x] The completed checkpoint was committed as `54bb6cbe59bd113058854a3ee31448cf61f462ca` with author and committer `James Jackson-South <james_south@hotmail.com>`.
- [x] The palette-memory follow-up was committed as `c4b4e4e0386328dea574a884b6fa36c360ad5a9b` with author and committer `James Jackson-South <james_south@hotmail.com>`.
Verified single-reference checkpoint evidence on 2026-08-31: Verified single-reference checkpoint evidence on 2026-08-31:
@ -564,15 +565,31 @@ Previously verified algorithm checkpoints remain valuable evidence, but the fina
- [x] Intra-block copy has exact native reconstruction and feature-isolated SIMD evidence. - [x] Intra-block copy has exact native reconstruction and feature-isolated SIMD evidence.
- [x] Lossless inverse transform, loop filtering, CDEF, super-resolution, restoration, and film grain have focused checkpoint evidence. - [x] Lossless inverse transform, loop filtering, CDEF, super-resolution, restoration, and film grain have focused checkpoint evidence.
- [x] Retained references, CDF snapshots, segmentation maps, global motion, temporal motion fields, and dependent-frame lifecycle have been re-audited and verified against current libaom `main`. - [x] Retained references, CDF snapshots, segmentation maps, global motion, temporal motion fields, and dependent-frame lifecycle have been re-audited and verified against current libaom `main`.
- [~] All-intra and dependent-frame profile fixtures exist for 8, 10, and 12-bit monochrome, 4:2:0, 4:2:2, and 4:4:4 paths. Current item. - [x] The 12-case all-intra profile matrix covers every valid 8, 10, and 12-bit monochrome, 4:2:0, 4:2:2, and 4:4:4 combination. Dependent-frame coverage is recorded separately above.
- [ ] Re-run the exact current-tree native-plane matrix through the production decoder. - [x] The exact current-tree native-plane matrix passes through the production decoder on net10.0 and net11.0. The normal-dispatch and FeatureTestRunner fallback methods pass 2 of 2 focused tests on each target.
- [ ] Re-run the exact current-tree presentation matrix through ImageSharp's established comparison API. - [x] The exact current-tree presentation matrix passes 12 of 12 cases through ImageSharp's established reference-image API on net10.0 and net11.0.
- [ ] Verify malformed/truncated data, frame IDs, reference slots, tile bounds, allocation limits, cancellation, and failure unwinding. - [x] Verify malformed/truncated data, frame IDs, reference slots, tile bounds, allocation limits, cancellation, and failure unwinding.
- [ ] Verify still items and bounded sequences from file, memory, non-seekable, and short-read streams. - [ ] Verify still items and bounded sequences from file, memory, non-seekable, and short-read streams.
- [ ] Verify ICC, CICP, alpha, grids, pixel aspect ratio, clean aperture, rotation, mirroring, metadata, and every presented sequence frame. - [ ] Verify ICC, CICP, alpha, grids, pixel aspect ratio, clean aperture, rotation, mirroring, metadata, and every presented sequence frame.
- [ ] Complete the public AVIF format/API review so registered capabilities match implemented behavior. - [ ] Complete the public AVIF format/API review so registered capabilities match implemented behavior.
- [ ] Remove or reject every valid in-scope AV1 syntax branch that remains silently ignored or unsupported. - [ ] Remove or reject every valid in-scope AV1 syntax branch that remains silently ignored or unsupported.
Verified negative-path and frame-identifier gate evidence on 2026-08-31:
- [x] A two-frame lossless frame-identifier sequence was generated and decoded with the clean official
libaom `main` checkout at observed revision `441c439b9916474cac15d2822af47a9ad70674a8`.
Both decoded frames match the source Y, Cb, and Cr samples exactly.
- [x] `DecodeFrameIdentifiersMatchReference` executes the production decoder through FeatureTestRunner,
compares both native frames exactly, and proves the second frame is dependent with a changed current
frame identifier. The current-frame, reference-delta, stale-slot, and refreshed-slot identifier logic
was audited against the same current `main` source.
- [x] The focused negative-path set passes 46 of 46 cases on net10.0 and 46 of 46 on net11.0, with zero
failures or skips. It covers truncated palette entropy, malformed-following-OBU recovery, parser
lifecycle failure, overflowing and invalid tile bounds, reference-slot ownership and transfer,
constrained multi-group allocation, motion-field allocation failure unwinding, and frame identifiers.
- [x] The established paused-stream cancellation suite now includes AVIF. It verifies cancellation at
0%, 30%, and 70% of both file and memory streams, plus pre-cancelled identification, on both targets.
Verified bounded-OBU checkpoint evidence on 2026-08-31: Verified bounded-OBU checkpoint evidence on 2026-08-31:
- [x] Audited `av1/decoder/obu.c`, `av1/decoder/decodeframe.c`, `av1/common/obu_util.c`, - [x] Audited `av1/decoder/obu.c`, `av1/decoder/decodeframe.c`, `av1/common/obu_util.c`,

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

@ -312,6 +312,11 @@ public class Av1ReconstructionConformanceTests
/// </summary> /// </summary>
private const int FilmGrainCoverage = 1 << 3; private const int FilmGrainCoverage = 1 << 3;
/// <summary>
/// The coverage bit representing a validated inter-frame identifier transition.
/// </summary>
private const int FrameIdentifierCoverage = 1 << 4;
/// <summary> /// <summary>
/// The bit mask containing every intra prediction mode. /// The bit mask containing every intra prediction mode.
/// </summary> /// </summary>
@ -1392,7 +1397,7 @@ public class Av1ReconstructionConformanceTests
Configuration configuration = Configuration.Default.Clone(); Configuration configuration = Configuration.Default.Clone();
configuration.MemoryAllocator = allocator; configuration.MemoryAllocator = allocator;
int coverage = ValidateOfficialCompactSequence( int coverage = ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialMotionFieldSequence, TestImages.Heif.Av1OfficialMotionFieldSequence,
TestImages.Heif.Av1OfficialMotionFieldSequenceNativeReference, TestImages.Heif.Av1OfficialMotionFieldSequenceNativeReference,
@ -1414,7 +1419,7 @@ public class Av1ReconstructionConformanceTests
/// </summary> /// </summary>
private static void ValidateOfficialCdfUpdateFixture() private static void ValidateOfficialCdfUpdateFixture()
{ {
int coverage = ValidateOfficialCompactSequence( int coverage = ValidateCompactSequence(
Configuration.Default, Configuration.Default,
TestImages.Heif.Av1OfficialCdfUpdateSequence, TestImages.Heif.Av1OfficialCdfUpdateSequence,
TestImages.Heif.Av1OfficialCdfUpdateSequenceNativeReference, TestImages.Heif.Av1OfficialCdfUpdateSequenceNativeReference,
@ -1428,7 +1433,7 @@ public class Av1ReconstructionConformanceTests
/// </summary> /// </summary>
private static void ValidateOfficialMotionFieldFixture() private static void ValidateOfficialMotionFieldFixture()
{ {
int coverage = ValidateOfficialCompactSequence( int coverage = ValidateCompactSequence(
Configuration.Default, Configuration.Default,
TestImages.Heif.Av1OfficialMotionFieldSequence, TestImages.Heif.Av1OfficialMotionFieldSequence,
TestImages.Heif.Av1OfficialMotionFieldSequenceNativeReference, TestImages.Heif.Av1OfficialMotionFieldSequenceNativeReference,
@ -1459,7 +1464,7 @@ public class Av1ReconstructionConformanceTests
Configuration configuration = Configuration.Default.Clone(); Configuration configuration = Configuration.Default.Clone();
configuration.MemoryAllocator = allocator; configuration.MemoryAllocator = allocator;
ValidateOfficialCompactSequence( ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialTwoSpatialLayerSequence, TestImages.Heif.Av1OfficialTwoSpatialLayerSequence,
TestImages.Heif.Av1OfficialTwoSpatialLayerSequenceNativeReference, TestImages.Heif.Av1OfficialTwoSpatialLayerSequenceNativeReference,
@ -1479,7 +1484,7 @@ public class Av1ReconstructionConformanceTests
/// Decodes the default operating point of the official two-spatial-layer sequence. /// Decodes the default operating point of the official two-spatial-layer sequence.
/// </summary> /// </summary>
private static void ValidateOfficialTwoSpatialLayerFixture() private static void ValidateOfficialTwoSpatialLayerFixture()
=> ValidateOfficialCompactSequence( => ValidateCompactSequence(
Configuration.Default, Configuration.Default,
TestImages.Heif.Av1OfficialTwoSpatialLayerSequence, TestImages.Heif.Av1OfficialTwoSpatialLayerSequence,
TestImages.Heif.Av1OfficialTwoSpatialLayerSequenceNativeReference, TestImages.Heif.Av1OfficialTwoSpatialLayerSequenceNativeReference,
@ -1509,7 +1514,7 @@ public class Av1ReconstructionConformanceTests
Configuration configuration = Configuration.Default.Clone(); Configuration configuration = Configuration.Default.Clone();
configuration.MemoryAllocator = allocator; configuration.MemoryAllocator = allocator;
ValidateOfficialCompactSequence( ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialTwoTemporalLayerSequence, TestImages.Heif.Av1OfficialTwoTemporalLayerSequence,
TestImages.Heif.Av1OfficialTwoTemporalLayerSequenceNativeReference, TestImages.Heif.Av1OfficialTwoTemporalLayerSequenceNativeReference,
@ -1529,7 +1534,7 @@ public class Av1ReconstructionConformanceTests
/// Decodes the default operating point of the official two-temporal-layer sequence. /// Decodes the default operating point of the official two-temporal-layer sequence.
/// </summary> /// </summary>
private static void ValidateOfficialTwoTemporalLayerFixture() private static void ValidateOfficialTwoTemporalLayerFixture()
=> ValidateOfficialCompactSequence( => ValidateCompactSequence(
Configuration.Default, Configuration.Default,
TestImages.Heif.Av1OfficialTwoTemporalLayerSequence, TestImages.Heif.Av1OfficialTwoTemporalLayerSequence,
TestImages.Heif.Av1OfficialTwoTemporalLayerSequenceNativeReference, TestImages.Heif.Av1OfficialTwoTemporalLayerSequenceNativeReference,
@ -1559,7 +1564,7 @@ public class Av1ReconstructionConformanceTests
Configuration configuration = Configuration.Default.Clone(); Configuration configuration = Configuration.Default.Clone();
configuration.MemoryAllocator = allocator; configuration.MemoryAllocator = allocator;
ValidateOfficialCompactSequence( ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialSpatialTemporalLayerSequence, TestImages.Heif.Av1OfficialSpatialTemporalLayerSequence,
TestImages.Heif.Av1OfficialSpatialTemporalLayerSequenceNativeReference, TestImages.Heif.Av1OfficialSpatialTemporalLayerSequenceNativeReference,
@ -1579,7 +1584,7 @@ public class Av1ReconstructionConformanceTests
/// Decodes the default operating point of the official spatial-and-temporal-layer sequence. /// Decodes the default operating point of the official spatial-and-temporal-layer sequence.
/// </summary> /// </summary>
private static void ValidateOfficialSpatialTemporalLayerFixture() private static void ValidateOfficialSpatialTemporalLayerFixture()
=> ValidateOfficialCompactSequence( => ValidateCompactSequence(
Configuration.Default, Configuration.Default,
TestImages.Heif.Av1OfficialSpatialTemporalLayerSequence, TestImages.Heif.Av1OfficialSpatialTemporalLayerSequence,
TestImages.Heif.Av1OfficialSpatialTemporalLayerSequenceNativeReference, TestImages.Heif.Av1OfficialSpatialTemporalLayerSequenceNativeReference,
@ -1609,7 +1614,7 @@ public class Av1ReconstructionConformanceTests
Configuration configuration = Configuration.Default.Clone(); Configuration configuration = Configuration.Default.Clone();
configuration.MemoryAllocator = allocator; configuration.MemoryAllocator = allocator;
int coverage = ValidateOfficialCompactSequence( int coverage = ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialFilmGrainSequence, TestImages.Heif.Av1OfficialFilmGrainSequence,
TestImages.Heif.Av1OfficialFilmGrainSequenceNativeReference, TestImages.Heif.Av1OfficialFilmGrainSequenceNativeReference,
@ -1629,7 +1634,7 @@ public class Av1ReconstructionConformanceTests
/// </summary> /// </summary>
private static void ValidateOfficialFilmGrainFixture() private static void ValidateOfficialFilmGrainFixture()
{ {
int coverage = ValidateOfficialCompactSequence( int coverage = ValidateCompactSequence(
Configuration.Default, Configuration.Default,
TestImages.Heif.Av1OfficialFilmGrainSequence, TestImages.Heif.Av1OfficialFilmGrainSequence,
TestImages.Heif.Av1OfficialFilmGrainSequenceNativeReference, TestImages.Heif.Av1OfficialFilmGrainSequenceNativeReference,
@ -1652,7 +1657,7 @@ public class Av1ReconstructionConformanceTests
/// </summary> /// </summary>
private static void ValidateOfficialTenBitFilmGrainFixture() private static void ValidateOfficialTenBitFilmGrainFixture()
{ {
int coverage = ValidateOfficialCompactSequence( int coverage = ValidateCompactSequence(
Configuration.Default, Configuration.Default,
TestImages.Heif.Av1OfficialTenBitFilmGrainSequence, TestImages.Heif.Av1OfficialTenBitFilmGrainSequence,
TestImages.Heif.Av1OfficialTenBitFilmGrainSequenceNativeReference, TestImages.Heif.Av1OfficialTenBitFilmGrainSequenceNativeReference,
@ -1687,7 +1692,7 @@ public class Av1ReconstructionConformanceTests
Configuration configuration = Configuration.Default.Clone(); Configuration configuration = Configuration.Default.Clone();
configuration.MemoryAllocator = allocator; configuration.MemoryAllocator = allocator;
ValidateOfficialCompactSequence( ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialMonochromeSequence, TestImages.Heif.Av1OfficialMonochromeSequence,
TestImages.Heif.Av1OfficialMonochromeSequenceNativeReference, TestImages.Heif.Av1OfficialMonochromeSequenceNativeReference,
@ -1708,7 +1713,7 @@ public class Av1ReconstructionConformanceTests
/// Decodes the official eight-bit monochrome sequence. /// Decodes the official eight-bit monochrome sequence.
/// </summary> /// </summary>
private static void ValidateOfficialMonochromeFixture() private static void ValidateOfficialMonochromeFixture()
=> ValidateOfficialCompactSequence( => ValidateCompactSequence(
Configuration.Default, Configuration.Default,
TestImages.Heif.Av1OfficialMonochromeSequence, TestImages.Heif.Av1OfficialMonochromeSequence,
TestImages.Heif.Av1OfficialMonochromeSequenceNativeReference, TestImages.Heif.Av1OfficialMonochromeSequenceNativeReference,
@ -1730,7 +1735,7 @@ public class Av1ReconstructionConformanceTests
/// Decodes the official ten-bit monochrome sequence. /// Decodes the official ten-bit monochrome sequence.
/// </summary> /// </summary>
private static void ValidateOfficialTenBitMonochromeFixture() private static void ValidateOfficialTenBitMonochromeFixture()
=> ValidateOfficialCompactSequence( => ValidateCompactSequence(
Configuration.Default, Configuration.Default,
TestImages.Heif.Av1OfficialTenBitMonochromeSequence, TestImages.Heif.Av1OfficialTenBitMonochromeSequence,
TestImages.Heif.Av1OfficialTenBitMonochromeSequenceNativeReference, TestImages.Heif.Av1OfficialTenBitMonochromeSequenceNativeReference,
@ -1752,7 +1757,7 @@ public class Av1ReconstructionConformanceTests
Configuration configuration = Configuration.Default.Clone(); Configuration configuration = Configuration.Default.Clone();
configuration.MemoryAllocator = allocator; configuration.MemoryAllocator = allocator;
int filmGrainCoverage = ValidateOfficialCompactSequence( int filmGrainCoverage = ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialTenBitFilmGrainSequence, TestImages.Heif.Av1OfficialTenBitFilmGrainSequence,
TestImages.Heif.Av1OfficialTenBitFilmGrainSequenceNativeReference, TestImages.Heif.Av1OfficialTenBitFilmGrainSequenceNativeReference,
@ -1762,7 +1767,7 @@ public class Av1ReconstructionConformanceTests
Av1ColorFormat.Yuv420, Av1ColorFormat.Yuv420,
Av1BitDepth.TenBit); Av1BitDepth.TenBit);
ValidateOfficialCompactSequence( ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialTenBitMonochromeSequence, TestImages.Heif.Av1OfficialTenBitMonochromeSequence,
TestImages.Heif.Av1OfficialTenBitMonochromeSequenceNativeReference, TestImages.Heif.Av1OfficialTenBitMonochromeSequenceNativeReference,
@ -1849,7 +1854,7 @@ public class Av1ReconstructionConformanceTests
/// </summary> /// </summary>
private static void ValidateOfficialEightBitQuantizerBoundaryFixturesWithConfiguration(Configuration configuration) private static void ValidateOfficialEightBitQuantizerBoundaryFixturesWithConfiguration(Configuration configuration)
{ {
ValidateOfficialCompactSequence( ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialEightBitMinimumQuantizerSequence, TestImages.Heif.Av1OfficialEightBitMinimumQuantizerSequence,
TestImages.Heif.Av1OfficialEightBitMinimumQuantizerSequenceNativeReference, TestImages.Heif.Av1OfficialEightBitMinimumQuantizerSequenceNativeReference,
@ -1857,7 +1862,7 @@ public class Av1ReconstructionConformanceTests
OfficialEightBitQuantizerFixtureWidth, OfficialEightBitQuantizerFixtureWidth,
OfficialEightBitQuantizerFixtureHeight); OfficialEightBitQuantizerFixtureHeight);
ValidateOfficialCompactSequence( ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialEightBitMaximumQuantizerSequence, TestImages.Heif.Av1OfficialEightBitMaximumQuantizerSequence,
TestImages.Heif.Av1OfficialEightBitMaximumQuantizerSequenceNativeReference, TestImages.Heif.Av1OfficialEightBitMaximumQuantizerSequenceNativeReference,
@ -1871,7 +1876,7 @@ public class Av1ReconstructionConformanceTests
/// </summary> /// </summary>
private static void ValidateOfficialTenBitQuantizerBoundaryFixturesWithConfiguration(Configuration configuration) private static void ValidateOfficialTenBitQuantizerBoundaryFixturesWithConfiguration(Configuration configuration)
{ {
ValidateOfficialCompactSequence( ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialTenBitMinimumQuantizerSequence, TestImages.Heif.Av1OfficialTenBitMinimumQuantizerSequence,
TestImages.Heif.Av1OfficialTenBitMinimumQuantizerSequenceNativeReference, TestImages.Heif.Av1OfficialTenBitMinimumQuantizerSequenceNativeReference,
@ -1882,7 +1887,7 @@ public class Av1ReconstructionConformanceTests
Av1BitDepth.TenBit, Av1BitDepth.TenBit,
"60:1"); "60:1");
ValidateOfficialCompactSequence( ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialTenBitMaximumQuantizerSequence, TestImages.Heif.Av1OfficialTenBitMaximumQuantizerSequence,
TestImages.Heif.Av1OfficialTenBitMaximumQuantizerSequenceNativeReference, TestImages.Heif.Av1OfficialTenBitMaximumQuantizerSequenceNativeReference,
@ -1936,7 +1941,7 @@ public class Av1ReconstructionConformanceTests
/// </summary> /// </summary>
private static void ValidateOfficialFrameSizeCornerFixturesWithConfiguration(Configuration configuration) private static void ValidateOfficialFrameSizeCornerFixturesWithConfiguration(Configuration configuration)
{ {
ValidateOfficialCompactSequence( ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialMinimumFrameSizeSequence, TestImages.Heif.Av1OfficialMinimumFrameSizeSequence,
TestImages.Heif.Av1OfficialMinimumFrameSizeSequenceNativeReference, TestImages.Heif.Av1OfficialMinimumFrameSizeSequenceNativeReference,
@ -1944,7 +1949,7 @@ public class Av1ReconstructionConformanceTests
OfficialFrameSizeFixtureMinimumDimension, OfficialFrameSizeFixtureMinimumDimension,
OfficialFrameSizeFixtureMinimumDimension); OfficialFrameSizeFixtureMinimumDimension);
ValidateOfficialCompactSequence( ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialMinimumWidthMaximumHeightSequence, TestImages.Heif.Av1OfficialMinimumWidthMaximumHeightSequence,
TestImages.Heif.Av1OfficialMinimumWidthMaximumHeightSequenceNativeReference, TestImages.Heif.Av1OfficialMinimumWidthMaximumHeightSequenceNativeReference,
@ -1952,7 +1957,7 @@ public class Av1ReconstructionConformanceTests
OfficialFrameSizeFixtureMinimumDimension, OfficialFrameSizeFixtureMinimumDimension,
OfficialFrameSizeFixtureMaximumDimension); OfficialFrameSizeFixtureMaximumDimension);
ValidateOfficialCompactSequence( ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialMaximumWidthMinimumHeightSequence, TestImages.Heif.Av1OfficialMaximumWidthMinimumHeightSequence,
TestImages.Heif.Av1OfficialMaximumWidthMinimumHeightSequenceNativeReference, TestImages.Heif.Av1OfficialMaximumWidthMinimumHeightSequenceNativeReference,
@ -1960,7 +1965,7 @@ public class Av1ReconstructionConformanceTests
OfficialFrameSizeFixtureMaximumDimension, OfficialFrameSizeFixtureMaximumDimension,
OfficialFrameSizeFixtureMinimumDimension); OfficialFrameSizeFixtureMinimumDimension);
ValidateOfficialCompactSequence( ValidateCompactSequence(
configuration, configuration,
TestImages.Heif.Av1OfficialMaximumFrameSizeSequence, TestImages.Heif.Av1OfficialMaximumFrameSizeSequence,
TestImages.Heif.Av1OfficialMaximumFrameSizeSequenceNativeReference, TestImages.Heif.Av1OfficialMaximumFrameSizeSequenceNativeReference,
@ -1970,10 +1975,35 @@ public class Av1ReconstructionConformanceTests
} }
/// <summary> /// <summary>
/// Decodes one compact official IVF sequence, compares every native sample, and returns its active frame-state /// Verifies modulo frame identifiers across a key/inter sequence with exact native output under every dispatch.
/// </summary>
[Fact]
public void DecodeFrameIdentifiersMatchReference()
=> FeatureTestRunner.RunWithHwIntrinsicsFeature(
ValidateFrameIdentifierFixture,
ReconstructionConfigurations);
/// <summary>
/// Decodes the frame-identifier fixture and requires a validated identifier transition on its inter frame.
/// </summary>
private static void ValidateFrameIdentifierFixture()
{
int coverage = ValidateCompactSequence(
Configuration.Default,
TestImages.Heif.Av1FrameIdentifierSequence,
TestImages.Heif.Av1FrameIdentifierSequenceNativeReference,
OfficialFrameSizeFixtureFrameCount,
OfficialFrameSizeFixtureMinimumDimension,
OfficialFrameSizeFixtureMinimumDimension);
Assert.Equal(FrameIdentifierCoverage, coverage & FrameIdentifierCoverage);
}
/// <summary>
/// Decodes one compact IVF sequence, compares every native sample, and returns its active frame-state
/// coverage mask. /// coverage mask.
/// </summary> /// </summary>
private static int ValidateOfficialCompactSequence( private static int ValidateCompactSequence(
Configuration configuration, Configuration configuration,
string fixturePath, string fixturePath,
string nativeReferencePath, string nativeReferencePath,
@ -2035,6 +2065,8 @@ public class Av1ReconstructionConformanceTests
int nativeFrameLength = nativeSampleCount * (expectedBitDepth == Av1BitDepth.EightBit ? 1 : sizeof(ushort)); int nativeFrameLength = nativeSampleCount * (expectedBitDepth == Av1BitDepth.EightBit ? 1 : sizeof(ushort));
int coverage = 0; int coverage = 0;
uint previousFrameIdentifier = 0;
bool hasPreviousFrameIdentifier = false;
using Av1Decoder decoder = new(configuration); using Av1Decoder decoder = new(configuration);
for (int frameIndex = 0; frameIndex < expectedFrameCount; frameIndex++) for (int frameIndex = 0; frameIndex < expectedFrameCount; frameIndex++)
{ {
@ -2070,6 +2102,19 @@ public class Av1ReconstructionConformanceTests
coverage |= frameHeader.DisableFrameEndUpdateCdf ? 0 : FrameEndCdfUpdateCoverage; coverage |= frameHeader.DisableFrameEndUpdateCdf ? 0 : FrameEndCdfUpdateCoverage;
coverage |= frameHeader.UseReferenceFrameMotionVectors ? ReferenceFrameMotionVectorCoverage : 0; coverage |= frameHeader.UseReferenceFrameMotionVectors ? ReferenceFrameMotionVectorCoverage : 0;
coverage |= frameHeader.FilmGrainParameters.ApplyGrain ? FilmGrainCoverage : 0; coverage |= frameHeader.FilmGrainParameters.ApplyGrain ? FilmGrainCoverage : 0;
ObuSequenceHeader sequenceHeader = Assert.IsType<ObuSequenceHeader>(decoder.SequenceHeader);
if (sequenceHeader.IsFrameIdNumbersPresent)
{
if (hasPreviousFrameIdentifier && !frameHeader.IsIntra &&
previousFrameIdentifier != frameHeader.CurrentFrameId)
{
coverage |= FrameIdentifierCoverage;
}
previousFrameIdentifier = frameHeader.CurrentFrameId;
hasPreviousFrameIdentifier = true;
}
} }
Assert.Equal(ivf.Length, ivfOffset); Assert.Equal(ivf.Length, ivfOffset);

1
tests/ImageSharp.Tests/Image/ImageTests.Decode_Cancellation.cs

@ -16,6 +16,7 @@ public partial class ImageTests
public static readonly string[] TestFileForEachCodec = public static readonly string[] TestFileForEachCodec =
[ [
TestImages.Jpeg.Baseline.Snake, TestImages.Jpeg.Baseline.Snake,
TestImages.Heif.IrvineAvif,
// TODO: Figure out Unix cancellation failures, and validate cancellation for each decoder. // TODO: Figure out Unix cancellation failures, and validate cancellation for each decoder.
//TestImages.Bmp.Car, //TestImages.Bmp.Car,

2
tests/ImageSharp.Tests/TestImages.cs

@ -1361,6 +1361,8 @@ public static class TestImages
public const string Av1OfficialMaximumWidthMinimumHeightSequenceNativeReference = "Heif/Av1/Conformance/libaom-av1-1-b8-01-size-226x196-libaom.y4m"; public const string Av1OfficialMaximumWidthMinimumHeightSequenceNativeReference = "Heif/Av1/Conformance/libaom-av1-1-b8-01-size-226x196-libaom.y4m";
public const string Av1OfficialMaximumFrameSizeSequence = "Heif/Av1/Conformance/libaom-av1-1-b8-01-size-226x226.ivf"; public const string Av1OfficialMaximumFrameSizeSequence = "Heif/Av1/Conformance/libaom-av1-1-b8-01-size-226x226.ivf";
public const string Av1OfficialMaximumFrameSizeSequenceNativeReference = "Heif/Av1/Conformance/libaom-av1-1-b8-01-size-226x226-libaom.y4m"; public const string Av1OfficialMaximumFrameSizeSequenceNativeReference = "Heif/Av1/Conformance/libaom-av1-1-b8-01-size-226x226-libaom.y4m";
public const string Av1FrameIdentifierSequence = "Heif/Av1/Conformance/libaom-frame-id-196x196-8b.ivf";
public const string Av1FrameIdentifierSequenceNativeReference = "Heif/Av1/Conformance/libaom-frame-id-196x196-8b-libaom.y4m";
public const string Av1OfficialCdfUpdateSequence = "Heif/Av1/Conformance/libaom-av1-1-b8-04-cdfupdate.ivf"; 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 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"; public const string Av1OfficialMotionVectorSequence = "Heif/Av1/Conformance/libaom-av1-1-b8-05-mv.ivf";

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

@ -37,6 +37,7 @@ only and are not used as an AV1 implementation reference.
| `*-film-grain-*` | Full and restricted range, monochrome, identity matrix, 8/10/12-bit synthesis, overlap, and odd frame dimensions | | `*-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-b8-00-quantizer-*`, `libaom-av1-1-b10-00-quantizer-*` | Official minimum- and maximum-quantizer dependent-frame reconstruction |
| `libaom-av1-1-b8-01-size-*` | Official frame-size matrix corner reconstruction | | `libaom-av1-1-b8-01-size-*` | Official frame-size matrix corner reconstruction |
| `libaom-frame-id-196x196-8b` | Key/inter frame-identifier signaling and retained-reference validation |
| `libaom-av1-1-b10-23`, `libaom-av1-1-b10-24` | Official ten-bit dependent-frame film grain and monochrome sequence 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-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 | | `libavif-webp-logo-average-compound` | A 19-frame YUV444 image sequence whose retained references reach equal-weight compound inter reconstruction |
@ -51,6 +52,21 @@ only and are not used as an AV1 implementation reference.
The corresponding tests also assert the syntax required by each family before comparing output. This prevents an inactive tool or an incorrectly substituted stream from passing solely because its final pixels happen to match. The corresponding tests also assert the syntax required by each family before comparing output. This prevents an inactive tool or an incorrectly substituted stream from passing solely because its final pixels happen to match.
## Frame identifier fixture
On 2026-08-31 current official libaom `main` at observed revision
`441c439b9916474cac15d2822af47a9ad70674a8` encoded the two 196x196 YUV420 frames from the retained
minimum-frame-size native reference with error resilience and frame identifiers enabled:
```text
aomenc --ivf --passes=1 --limit=2 --threads=1 --row-mt=0 --lag-in-frames=0 --auto-alt-ref=0 --error-resilient=1 --kf-min-dist=9999 --kf-max-dist=9999 --lossless=1 --cpu-used=6 -o libaom-frame-id-196x196-8b.ivf libaom-av1-1-b8-01-size-196x196-libaom.y4m
aomdec --threads=1 --row-mt=0 --output-bit-depth=8 --all-layers --output=libaom-frame-id-196x196-8b-libaom.y4m libaom-frame-id-196x196-8b.ivf
```
The generated native reference contains both decoded frames. Every Y, Cb, and Cr sample matches the source
frames exactly. The production test additionally requires an enabled frame-identifier sequence header and a
validated identifier change on the dependent inter frame.
## Baseline deblocking fixtures ## Baseline deblocking fixtures
On 2026-08-31 current official libaom `main` at observed revision On 2026-08-31 current official libaom `main` at observed revision
@ -85,7 +101,7 @@ edges, and skipped prediction-unit boundaries.
The `libaom-av1-1-b10-23-film-grain-50.ivf` and `libaom-av1-1-b10-24-monochrome.ivf` streams are the official files from libaom's test-data bucket. Their SHA-1 values are `2F883C7E11C21A31F79BD9C809541BE90B0C7C4A` and `03A8D002594CCC51932332002BB6F9837EF46D0F`, exactly matching the current official libaom `main` manifest. Their SHA-256 values are `C36CF5AB6A2E9E27C212C06863759B60791E3FA681A0800B5D57FD4192EF29CB` and `6A1B0729305A167F10737A5375F0570139F055BCD7916DF260B653AB2210ADC1`. The `libaom-av1-1-b10-23-film-grain-50.ivf` and `libaom-av1-1-b10-24-monochrome.ivf` streams are the official files from libaom's test-data bucket. Their SHA-1 values are `2F883C7E11C21A31F79BD9C809541BE90B0C7C4A` and `03A8D002594CCC51932332002BB6F9837EF46D0F`, exactly matching the current official libaom `main` manifest. Their SHA-256 values are `C36CF5AB6A2E9E27C212C06863759B60791E3FA681A0800B5D57FD4192EF29CB` and `6A1B0729305A167F10737A5375F0570139F055BCD7916DF260B653AB2210ADC1`.
The retained native references were generated from the pinned generic libaom build with: The retained native references were generated from the generic libaom build with:
```text ```text
aomdec --threads=1 --output=libaom-av1-1-b10-23-film-grain-50-libaom.y4m libaom-av1-1-b10-23-film-grain-50.ivf aomdec --threads=1 --output=libaom-av1-1-b10-23-film-grain-50-libaom.y4m libaom-av1-1-b10-23-film-grain-50.ivf

3
tests/Images/Input/Heif/Av1/Conformance/libaom-frame-id-196x196-8b-libaom.y4m

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

3
tests/Images/Input/Heif/Av1/Conformance/libaom-frame-id-196x196-8b.ivf

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