Browse Source

Verify complete AV1 partition traversal

pull/2633/head
James Jackson-South 2 months ago
parent
commit
d735a92a4b
  1. 1
      HEIF_IMPLEMENTATION_PLAN.md
  2. 2
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs
  3. 60
      tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReconstructionConformanceTests.cs
  4. 2
      tests/Images/Input/Heif/Av1/Conformance/README.md

1
HEIF_IMPLEMENTATION_PLAN.md

@ -498,6 +498,7 @@ Implement and verify in dependency order:
- [ ] OBU framing, sequence headers, frame headers, tile groups, byte alignment, and trailing bits.
- [ ] One coherent decoder lifecycle that retains parsed frame and tile state and disposes all buffers deterministically.
- [ ] Tile partitioning, mode information, segmentation, delta quantization, transform-size selection, coefficient token decode, inverse quantization, and inverse transforms.
- [x] Match libaom's depth-first traversal and frame-edge behavior for all ten AV1 partition types. Independent 8/10/12-bit streams collectively select every terminal partition shape and contain nested block geometry that requires recursive `Split` traversal; their complete native planes remain byte-exact under normal hardware dispatch and the scalar fallback.
- [ ] Intra prediction, including every directional, smooth, Paeth, CFL, filter-intra, and palette case permitted by AV1.
- [x] Implement SIMD-first chroma-from-luma storage, 4:4:4/4:2:2/4:2:0 subsampling, rounded mean subtraction, and 8/10/12-bit prediction with exact scalar fallback and `FeatureTestRunner` parity.
- [x] Implement allocation-free SIMD-first palette reconstruction for palette sizes 2-8, transform widths 4-64, and 8/10/12-bit samples with exact scalar fallback and `FeatureTestRunner` parity.

2
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs

@ -622,7 +622,7 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable
break;
default:
throw new NotImplementedException($"Partition type: {partitionType} is not supported.");
throw new InvalidImageContentException($"The decoded AV1 partition type {partitionType} is invalid.");
}
this.UpdatePartitionContext(new Point(columnIndex, rowIndex), tileInfo, superblockInfo, subSize, blockSize, partitionType);

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

@ -67,6 +67,11 @@ public class Av1ReconstructionConformanceTests
/// </summary>
private const int RequiredPaletteCoverage = LumaPaletteCoverage | ChromaPaletteCoverage;
/// <summary>
/// The bit mask containing every AV1 partition type defined for a coding block.
/// </summary>
private const int RequiredPartitionCoverage = (1 << ((int)Av1PartitionType.Vertical4 + 1)) - 1;
/// <summary>
/// The displayed width shared by the independent lossless fixtures.
/// </summary>
@ -252,6 +257,19 @@ public class Av1ReconstructionConformanceTests
public void DecodeWithFilmGrainMatchesPinnedLibaomReference()
=> FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateFilmGrainFixtures, LoopRestorationConfigurations);
/// <summary>
/// Verifies that independently encoded AV1 streams exercise every normative coding-block partition shape.
/// </summary>
[Fact]
public void IndependentFixturesCoverEveryPartitionType()
{
int coverage = GetPartitionCoverage(TestImages.Heif.Av1Cdef8BitPayload);
coverage |= GetPartitionCoverage(TestImages.Heif.Av1Cdef10BitPayload);
coverage |= GetPartitionCoverage(TestImages.Heif.Av1Cdef12BitPayload);
Assert.Equal(RequiredPartitionCoverage, coverage & RequiredPartitionCoverage);
}
/// <summary>
/// Validates every active-CDEF fixture under the hardware configuration selected by <see cref="FeatureTestRunner"/>.
/// </summary>
@ -1075,6 +1093,48 @@ public class Av1ReconstructionConformanceTests
return restorationCoverage;
}
/// <summary>
/// Gets the partition types selected by one independently encoded AV1 elementary stream.
/// </summary>
/// <param name="payloadPath">The AV1 elementary-stream sample.</param>
/// <returns>A bit mask containing every selected partition type.</returns>
private static int GetPartitionCoverage(string payloadPath)
{
byte[] payload = TestFile.Create(payloadPath).Bytes;
using Av1Decoder decoder = new(Configuration.Default);
using Av1FrameBuffer<byte> frameBuffer = decoder.DecodeFrameBuffer(payload, null, null, out _);
Assert.NotNull(decoder.SequenceHeader);
Assert.NotNull(decoder.FrameInfo);
int superblockSizeLog2 = decoder.SequenceHeader.SuperblockSizeLog2;
int superblockColumnCount = Av1Math.AlignPowerOf2(decoder.SequenceHeader.MaxFrameWidth, superblockSizeLog2) >> superblockSizeLog2;
int superblockRowCount = Av1Math.AlignPowerOf2(decoder.SequenceHeader.MaxFrameHeight, superblockSizeLog2) >> superblockSizeLog2;
int halfSuperblockSize = 1 << (superblockSizeLog2 - 1);
int coverage = 0;
// Mode records retain their bitstream traversal order and store each final coding block once, so iterating
// the parsed count observes every selected leaf partition without repeatedly visiting its covered 4x4 cells.
// Split itself creates no mode record. All other partition types are terminal, so a leaf below half the
// superblock size on both axes proves that the parser reached it through at least one recursive split.
for (int superblockRow = 0; superblockRow < superblockRowCount; superblockRow++)
{
for (int superblockColumn = 0; superblockColumn < superblockColumnCount; superblockColumn++)
{
Av1SuperblockInfo superblock = decoder.FrameInfo.GetSuperblock(new Point(superblockColumn, superblockRow));
foreach (Av1BlockModeInfo modeInfo in superblock.GetModeInfos())
{
coverage |= 1 << (int)modeInfo.PartitionType;
if (modeInfo.BlockSize.GetWidth() < halfSuperblockSize && modeInfo.BlockSize.GetHeight() < halfSuperblockSize)
{
coverage |= 1 << (int)Av1PartitionType.Split;
}
}
}
}
return coverage;
}
/// <summary>
/// Gets the complete media-data payload from a single-item AVIF conformance fixture.
/// </summary>

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

@ -27,6 +27,8 @@ The native reference layouts are:
The conformance tests compare every visible reconstructed sample with these files. The deblocking corpus verifies nonzero loop-filter levels. The CDEF corpus additionally verifies sequence-level CDEF enablement, a selected nonzero frame strength, and disabled loop restoration, so a disabled or bypassed CDEF stage cannot satisfy the exact native-plane comparison accidentally.
Across the three active-CDEF elementary streams, the decoded mode records select every terminal AV1 partition shape. Their nested blocks also require recursive square splits, which produce no terminal mode record of their own. The tests verify that complete ten-type coverage before relying on the exact native-plane comparisons.
The `libaom-superres-*` streams were encoded from the same Kodak and Cosmos sources with the pinned generic libaom build. Their material options were `--usage=2 --passes=1 --limit=1 --obu --end-usage=q --cq-level=30 --cpu-used=4 --threads=1 --lag-in-frames=0 --full-still-picture-hdr --enable-cdef=0 --enable-restoration=0 --superres-mode=1 --superres-denominator=12 --superres-kf-denominator=12`, together with the matching input depth, output depth, and profile. Disabling CDEF and restoration isolates the normative horizontal upscaling result, while the tests separately require a coded width smaller than the displayed width so an unscaled stream cannot satisfy the reference comparison.
The matching `libaom-superres-*-libaom.yuv` files were decoded by `aomdec --rawvideo` from that exact generic build. They retain the displayed 768x512 8-bit YUV 4:2:0 and 1024x428 10/12-bit YUV 4:4:4 layouts described above.

Loading…
Cancel
Save