diff --git a/HEIF_IMPLEMENTATION_PLAN.md b/HEIF_IMPLEMENTATION_PLAN.md index 5001fab66..f443b3df6 100644 --- a/HEIF_IMPLEMENTATION_PLAN.md +++ b/HEIF_IMPLEMENTATION_PLAN.md @@ -82,12 +82,12 @@ Recovered task-history evidence from 2026-08-31: ### 2. Correct the single-reference inter-frame checkpoint -The checkpoint implementation is complete. The first two inherited audit findings were rechecked against current libaom `main` and did not require production changes; the remaining production boundary, reconstruction, and ownership work is now implemented and verified. +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. - [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 `Av1TileReader` uses the same non-Translation classification. The existing Identity test leaves sentinel filter symbols unread, while the Translation test consumes them. - - No production change is required. The stale test comment was changed from “pinned” to “current” libaom. + - No production change is required. The focused test describes only the syntax behavior it proves. - [x] Reconcile both spatial single-reference extension loops in `Av1ReferenceMotionVectors` with current libaom `main`. - Current libaom `setup_ref_mv_list` stops both loops at `MAX_MV_REF_CANDIDATES`, which is two. `MAX_REF_MV_STACK_SIZE`, which is eight, is the stack capacity used by the earlier direct and temporal candidate collection; it is not the stop condition for these two extension loops. - Current `Av1ReferenceMotionVectors` uses the same two-entry stop condition and retains an eight-entry stack for earlier candidates and DRL selection. @@ -102,10 +102,10 @@ The checkpoint implementation is complete. The first two inherited audit finding - Compare the final frame's native Y, Cb, and Cr planes exactly with current-main libaom output. - Compare the final presented image through the established ImageSharp reference-image comparison API. - Do not substitute an internal helper test, fake tile reader, non-zero assertion, custom pixel loop, or tolerant comparison. -- [x] Prove motion-field ownership and lifetime. +- [x] Prove motion-field ownership and lifetime after the current reconstruction-timing change. - Track initialization, retained-slot aliases, failure unwinding, presentation ownership, decoder-result ownership, and final disposal. - Every allocator-owned object must be returned exactly once. -- [x] Correct stale documentation. +- [x] Correct stale documentation for the current worktree. - Av1InterFrameModeInfoTests must describe the behavior it actually proves. - Do not claim production reconstruction, constrained allocation, ownership, or reference-stack coverage unless the test executes that contract. @@ -117,20 +117,20 @@ Checkpoint gate: - [x] The established exact presentation comparison passes. - [x] Normal, AVX-512-disabled, AVX-disabled, and scalar FeatureTestRunner configurations pass where supported. - [x] Constrained allocation preserves the enforced single-group plane invariant without copying or per-block allocation. -- [x] Motion-field allocation tracking is balanced across success and failure. -- [x] Release builds for net10.0 and net11.0 pass with zero errors. -- [x] Focused Release tests pass with zero failures or skips. -- [x] Scoped semantic, StyleCop, whitespace, and git diff checks pass. +- [x] Motion-field allocation tracking is balanced across success and failure on net10.0 and net11.0. +- [x] Release source builds pass for net10.0 and net11.0 with zero warnings and zero errors. +- [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] The completed checkpoint was committed as `54bb6cbe59bd113058854a3ee31448cf61f462ca` with author and committer `James Jackson-South `. Verified single-reference checkpoint evidence on 2026-08-31: - The current-main `aomdec` was rebuilt directly from `D:\GitHub\AOMediaCodec\aom` and identified itself as `3.15.0-13-g441c439b99`. - Decoding the 72-byte progressive payload with `--all-layers`, one thread, and row multithreading disabled produced 2,178 YUV444 color samples. All samples in both layers match the first three planes of the stored YUV444-alpha reference exactly. -- `DecodeProgressiveSingleReferenceMatchesCurrentLibaomReferences` executes the production decoder through FeatureTestRunner and compares the complete presented `Rgba32` image with `CompareToReferenceOutput(ImageComparer.Exact, provider)`. The redundant manual alpha loop was removed. -- `DecodeProgressiveSingleReferenceWithConstrainedAllocator` executes the same production reconstruction with a 1,024-byte allocator group capacity and verifies that every allocation is returned exactly once. -- `MotionFieldsFollowReferenceAliasesAndPresentationOwnership`, `MotionFieldAllocationFailureUnwindsTileReaderOwnership`, `DecodeProgressiveSingleReferenceTracksMotionFieldResultOwnership`, and the reference-store replacement, reset, and transfer tests cover initialization, aliases, presentation ownership, decoder-result ownership, failure unwinding, repeated disposal, and exactly-once final returns. -- The focused Release set passed 17 of 17 tests on net10.0 and 17 of 17 tests on net11.0, with zero failures and zero skips. This includes both GLOBALMV syntax cases, spatial extension, plane invariants, production reconstruction, FeatureTestRunner dispatch, and ownership. +- `DecodeProgressiveSingleMatchesReference` executes the production decoder through FeatureTestRunner and compares the complete presented `Rgba32` image with `CompareToReferenceOutput(ImageComparer.Exact, provider)`. The redundant manual alpha loop was removed. +- `DecodeProgressiveSingleWithConstrainedAllocator` executes the same production reconstruction with a 1,024-byte allocator group capacity and verifies that every allocation is returned exactly once. +- `MotionFieldsFollowAliasesAndPresentationOwnership`, `MotionFieldAllocationFailureUnwindsTileReaderOwnership`, `DecodeProgressiveSingleTracksMotionFieldOwnership`, and the reference-store replacement, reset, and transfer tests cover initialization, aliases, presentation ownership, decoder-result ownership, failure unwinding, repeated disposal, and exactly-once final returns in the current worktree. +- The current worktree passes the four-case palette set, seven-case ownership set, and 29-case syntax, plane, and production reconstruction set on both target frameworks. The complete AV1 namespace passes 8,732 of 8,732 tests on net10.0 and net11.0 with zero failures or skips. - Release source builds passed for net10.0 and net11.0 with zero warnings and zero errors. - Roslynk reported zero compiler errors. The scoped changed-file analyzer inspection reported no StyleCop diagnostics attributable to this checkpoint; its only remaining match is the pre-existing xUnit cancellation warning in an unrelated `HeifDecoderTests` method. - `git diff --check` passed, and neither `.gitattributes` file changed. @@ -148,7 +148,7 @@ $env:COMPlus_DbgEnableMiniDump = '0' $env:DOTNET_EnableCrashReport = '0' $env:COMPlus_EnableCrashReport = '0' -$heifCheckpointFilter = 'FullyQualifiedName~Av1InterFrameModeInfoTests.ReadInterFrameModeInfoReadsInterpolationFilters|FullyQualifiedName~Av1InterFrameModeInfoTests.ReadInterFrameModeInfoOmitsInterpolationFiltersForIdentityGlobalMotion|FullyQualifiedName~Av1ReferenceMotionVectorsTests.BuildReversesOppositeDirectionExtensionCandidate|FullyQualifiedName~Av1FrameBufferTests|FullyQualifiedName~Av1ReferenceFrameStoreTests.MotionFieldsFollowReferenceAliasesAndPresentationOwnership|FullyQualifiedName~Av1ReferenceFrameStoreTests.MotionFieldAllocationFailureUnwindsTileReaderOwnership|FullyQualifiedName~Av1ReferenceFrameStoreTests.PartialReplacementPreservesSharedOwner|FullyQualifiedName~Av1ReferenceFrameStoreTests.FinalReplacementReleasesDisplacedOwner|FullyQualifiedName~Av1ReferenceFrameStoreTests.ResetReleasesUniqueOwnersAndClearsSlots|FullyQualifiedName~Av1ReferenceFrameStoreTests.TakeOutputTransfersPlanesAndReleasesOtherReferences|FullyQualifiedName~Av1ReconstructionConformanceTests.DecodeProgressiveSingleReferenceMatchesCurrentLibaomReferences|FullyQualifiedName~Av1ReconstructionConformanceTests.DecodeProgressiveSingleReferenceWithConstrainedAllocator|FullyQualifiedName~Av1ReconstructionConformanceTests.DecodeProgressiveSingleReferenceTracksMotionFieldResultOwnership' +$heifCheckpointFilter = 'FullyQualifiedName~Av1InterFrameModeInfoTests.ReadInterFrameModeInfoReadsInterpolationFilters|FullyQualifiedName~Av1InterFrameModeInfoTests.IdentityGlobalMotionOmitsInterpolationFilters|FullyQualifiedName~Av1ReferenceMotionVectorsTests.BuildReversesOppositeDirectionExtensionCandidate|FullyQualifiedName~Av1FrameBufferTests|FullyQualifiedName~Av1ReferenceFrameStoreTests.MotionFieldsFollowAliasesAndPresentationOwnership|FullyQualifiedName~Av1ReferenceFrameStoreTests.MotionFieldAllocationFailureUnwindsTileReaderOwnership|FullyQualifiedName~Av1ReferenceFrameStoreTests.PartialReplacementPreservesSharedOwner|FullyQualifiedName~Av1ReferenceFrameStoreTests.FinalReplacementReleasesDisplacedOwner|FullyQualifiedName~Av1ReferenceFrameStoreTests.ResetReleasesUniqueOwnersAndClearsSlots|FullyQualifiedName~Av1ReferenceFrameStoreTests.TakeOutputTransfersPlanesAndReleasesOtherReferences|FullyQualifiedName~Av1ReconstructionConformanceTests.DecodeProgressiveSingleMatchesReference|FullyQualifiedName~Av1ReconstructionConformanceTests.DecodeProgressiveSingleWithConstrainedAllocator|FullyQualifiedName~Av1ReconstructionConformanceTests.DecodeProgressiveSingleTracksMotionFieldOwnership' dotnet build src\ImageSharp\ImageSharp.csproj -c Release -f net10.0 --no-restore --disable-build-servers -m:1 --no-incremental --nologo --verbosity:minimal dotnet build src\ImageSharp\ImageSharp.csproj -c Release -f net11.0 --no-restore --disable-build-servers -m:1 --no-incremental --nologo --verbosity:minimal @@ -563,8 +563,8 @@ Previously verified algorithm checkpoints remain valuable evidence, but the fina - [x] Intra prediction covers directional, DC, smooth, Paeth, chroma-from-luma, filter-intra, and palette families with the established operator architecture. - [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. -- [~] Retained references, CDF snapshots, segmentation maps, global motion, temporal motion fields, and dependent-frame lifecycle exist locally and require current-tree re-verification. -- [~] 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. +- [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. - [ ] Re-run the exact current-tree native-plane matrix through the production decoder. - [ ] Re-run the exact current-tree presentation matrix through ImageSharp's established comparison API. - [ ] Verify malformed/truncated data, frame IDs, reference slots, tile bounds, allocation limits, cancellation, and failure unwinding. @@ -626,12 +626,12 @@ Verified partition, mode, segmentation, quantization, and transform checkpoint e Each transform resets and clears only its active padded geometry, so no transform creates an allocation. Allocation tracking over all eight minimum- and maximum-quantizer frames proves exactly one coefficient scratch allocation per frame and exactly-once return after decoder disposal. -- [x] Palette index maps are allocator-backed frame surfaces addressed row by row through `Buffer2DRegion`. - The wavefront context, stable neighbor ordering, right/bottom padding, transform offsets, and prediction - were audited against current libaom `av1/decoder/detokenize.c`, `av1/common/entropymode.c`, - `av1/decoder/decodeframe.c`, and `av1/common/reconintra.c`. A 1 KiB constrained allocator forces both - luma and chroma maps across multiple memory groups without copies or per-block allocations and proves - exactly-once disposal. +- [x] Palette index maps use two allocator-backed 128x128 decoder-session scratch buffers, one for luma and + one for chroma. Each parsed superblock is reconstructed before either buffer is reused, and each block + clears only its transient `Buffer2DRegion` view after prediction. The fixed 32 KiB session cost replaces + the former two full-frame maps without copies or per-block allocations. A 1 KiB constrained allocator + splits both buffers across memory groups. The four-case palette set passes on net10.0 and net11.0 with + exact native and presentation output, truncated-entropy rejection, and balanced exactly-once disposal. - [x] `Av1BlockModeInfo` is value storage, removing the managed object allocation formerly created for every decoded coding block. Explicit `ModeInfoIndex` values preserve libaom's mode-info identity semantics at prediction-unit loop-filter edges, and the frame map now uses integer offsets so more than 65,535 decoded @@ -649,6 +649,39 @@ Verified partition, mode, segmentation, quantization, and transform checkpoint e - [x] The exact final AV1 namespace passes 8,732 of 8,732 cases on net10.0 and 8,732 of 8,732 cases on net11.0, with zero failures or skips. Release source builds pass for net10.0 and net11.0 with zero warnings and zero errors. Roslynk reports zero compiler errors, and scoped analyzer verification reports no changes. +- [x] The completed checkpoint was committed as `57a3f6668e39d0934e7b6b8d37a3dc2a5adc88f0` with author + and committer `James Jackson-South `. + +Verified retained-frame lifecycle checkpoint evidence on 2026-08-31: + +- [x] Audited primary-reference entropy selection, independent per-tile CDF starts, context-update-tile + publication, segmentation-map inheritance, reference-map refresh, and show-existing key-frame reset + against current libaom `av1/decoder/decodeframe.c`, `av1/decoder/decodemv.c`, + `av1/decoder/decoder.c`, and `av1/common/entropymode.c`. +- [x] Audited retained motion-vector cells, reference-side classification, projection source ordering, + projection limits, and reference-frame publication against `av1_copy_frame_mvs`, + `av1_calculate_ref_frame_side`, `motion_field_projection`, and `av1_setup_motion_field` in current + libaom. Same-role primary-reference global-motion inheritance remains covered by the exact current-main + global-warp fixture. The observed clean `HEAD` and `origin/main` revision was + `441c439b9916474cac15d2822af47a9ad70674a8`; this is verification evidence, not a pin. +- [x] Current official libaom decoded the retained `cdfupdate`, `mfmv`, `svc-L2T1`, `svc-L1T2`, and + `svc-L2T2` streams with one thread, row threading disabled, and eight-bit output depth. Their generated + Y4M files match the retained references byte for byte at SHA-256 + `4FBFF73FF0DE2D9084DAE557D1D4BD677B0486516525BF4D327D2D795D5A7779`, + `F7DB607694818C19E62FD9A27F53E1A3E2D00B72C39C0430C1B26399CC76777D`, + `7A427631ECBF144F435AA4612F1201415FB1A9BCF9A67BA010AEF830B0C3AB81`, + `4012DE2D4AFD095E7BB68EAE18B50B0674781BB4971CECABC0E5471E63373ED3`, and + `1ABB981CFF76BA9557DA437B258D8A95FCA755DED8E3949D857E8388AB1D6AE3`. +- [x] Existing allocation-tracking tests exercise initialization, retained-slot aliases, allocation-failure + unwinding, presentation ownership, decoder-result ownership, repeated disposal, and final exactly-once + return of reference frames, frame-owned motion fields, entropy snapshots, and segmentation maps. +- [x] The focused Release checkpoint set passes 54 of 54 cases on net10.0 and 54 of 54 cases on net11.0, + with zero failures or skips. It includes exact native CDF-update, motion-field, spatial-layer, + temporal-layer, spatial-temporal-layer, progressive dependent-frame, and global-warp production paths, + plus constrained allocator coverage. +- [x] Release source builds pass for net10.0 and net11.0 with zero warnings and zero errors. Roslynk + reports zero compiler errors, scoped analyzer verification reports no changes, `git diff --check` + passes, and `.gitattributes` is unchanged. Decoder exit gate: diff --git a/src/ImageSharp/Formats/Heif/Av1/Av1BlockSizeExtensions.cs b/src/ImageSharp/Formats/Heif/Av1/Av1BlockSizeExtensions.cs index 3f46a3b41..53993efd8 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Av1BlockSizeExtensions.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Av1BlockSizeExtensions.cs @@ -148,7 +148,7 @@ internal static class Av1BlockSizeExtensions public static int GetSizeGroup(this Av1BlockSize blockSize) { // AV1 section 9.3 groups a block by its smaller dimension in 4x4 units and caps that logarithm at three. - // Deriving the value from the existing geometry tables exactly matches libaom's size_group_lookup table. + // Deriving the value from the existing geometry tables exactly matches the reference decoder's size_group_lookup table. return Math.Min(3, Math.Min(blockSize.Get4x4WidthLog2(), blockSize.Get4x4HeightLog2())); } diff --git a/src/ImageSharp/Formats/Heif/Av1/Av1CodecConfiguration.cs b/src/ImageSharp/Formats/Heif/Av1/Av1CodecConfiguration.cs index 087ce232a..8b5d63cb6 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Av1CodecConfiguration.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Av1CodecConfiguration.cs @@ -427,7 +427,7 @@ internal sealed class Av1CodecConfiguration throw new InvalidImageContentException($"The {sourceName} contains an OBU with a set forbidden header bit."); } - // Current libaom deliberately ignores obu_reserved_1bit. The bit does not alter the OBU boundary or + // The reference decoder deliberately ignores obu_reserved_1bit. The bit does not alter the OBU boundary or // decoded syntax, so the bounded container scan must not reject data that the production parser accepts. ObuType type = (ObuType)((header >> 3) & 0x0F); bool hasExtension = (header & 0x04) != 0; @@ -440,7 +440,7 @@ internal sealed class Av1CodecConfiguration throw new InvalidImageContentException($"The {sourceName} contains a truncated OBU extension header."); } - // extension_header_reserved_3bits is also consumed but ignored by current libaom. + // extension_header_reserved_3bits is also consumed but ignored by the reference decoder. extension = data[offset++]; } @@ -629,7 +629,7 @@ internal sealed class Av1CodecConfiguration } } - // Both fixed HDR structures end on a byte boundary. libaom accepts zero padding after the required 0x80 byte, + // Both fixed HDR structures end on a byte boundary. Zero padding after the required 0x80 byte is accepted, // so locate the last nonzero byte rather than assuming the OBU payload ends immediately after trailing_bits(). if (lastNonzeroByte != 0x80) { diff --git a/src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs b/src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs index de881bce1..01fc9ba2b 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs @@ -8,6 +8,7 @@ using SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline; using SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline.FilmGrain; using SixLabors.ImageSharp.Formats.Heif.Av1.ReferenceFrames; using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; +using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Cicp; using SixLabors.ImageSharp.PixelFormats; @@ -30,6 +31,16 @@ internal sealed class Av1Decoder : IAv1TileReader, IDisposable /// private readonly Configuration configuration; + /// + /// Reusable luma palette indices for the coding blocks in one superblock. + /// + private readonly Buffer2D lumaPaletteColorIndexMap; + + /// + /// Reusable chroma palette indices for the coding blocks in one superblock. + /// + private readonly Buffer2D chromaPaletteColorIndexMap; + /// /// The reconstructed references and selected presentation output owned by the current bounded decode session. /// @@ -66,6 +77,16 @@ internal sealed class Av1Decoder : IAv1TileReader, IDisposable /// private Av1TileReader? tileReader; + /// + /// The destination sample buffer for the frame currently being parsed and reconstructed. + /// + private Av1FrameBuffer? frameBuffer; + + /// + /// The reconstruction pipeline for the frame currently being parsed. + /// + private Av1FrameDecoder? frameDecoder; + /// /// Initializes a new instance of the class. /// @@ -84,6 +105,27 @@ internal sealed class Av1Decoder : IAv1TileReader, IDisposable { this.configuration = configuration; this.obuReader = new(operatingPointIndex, this.referenceFrames); + + Buffer2D? lumaPaletteColorIndexMap = null; + Buffer2D? chromaPaletteColorIndexMap = null; + + try + { + // Sequential tile decoding needs only the palette indices belonging to the current superblock. Keeping + // two maximum-superblock surfaces at decoder scope makes the memory bound independent of frame size and + // reuses the same allocator rents across every frame in the bounded sequence. + int paletteMapLength = 1 << Av1Constants.MaxSuperBlockSizeLog2; + lumaPaletteColorIndexMap = configuration.MemoryAllocator.Allocate2D(paletteMapLength, paletteMapLength); + chromaPaletteColorIndexMap = configuration.MemoryAllocator.Allocate2D(paletteMapLength, paletteMapLength); + this.lumaPaletteColorIndexMap = lumaPaletteColorIndexMap; + this.chromaPaletteColorIndexMap = chromaPaletteColorIndexMap; + } + catch + { + chromaPaletteColorIndexMap?.Dispose(); + lumaPaletteColorIndexMap?.Dispose(); + throw; + } } /// @@ -506,6 +548,10 @@ internal sealed class Av1Decoder : IAv1TileReader, IDisposable { // A failed frame may own pooled neighbor contexts while earlier layers own reconstructed references and // published CDF snapshots. None can be reused after a non-transactional frame transition has failed. + this.frameDecoder?.Dispose(); + this.frameDecoder = null; + this.frameBuffer?.Dispose(); + this.frameBuffer = null; this.tileReader?.Dispose(); this.tileReader = null; this.obuReader.Reset(); @@ -527,6 +573,66 @@ internal sealed class Av1Decoder : IAv1TileReader, IDisposable } } + /// + /// Validates the active sequence against its container declarations before reconstruction begins. + /// + /// The active sequence header. + private void ValidateSequence(ObuSequenceHeader sequenceHeader) + { + if (ReferenceEquals(this.validatedSequenceHeader, sequenceHeader)) + { + return; + } + + this.codecConfiguration?.Validate(sequenceHeader); + CicpProfile? colorProfile = this.containerColorProfile; + + if (colorProfile is not null) + { + ObuColorConfig colorConfig = sequenceHeader.ColorConfig; + ObuColorPrimaries containerColorPrimaries = (ObuColorPrimaries)colorProfile.ColorPrimaries; + ObuTransferCharacteristics containerTransferCharacteristics = (ObuTransferCharacteristics)colorProfile.TransferCharacteristics; + ObuMatrixCoefficients containerMatrixCoefficients = (ObuMatrixCoefficients)colorProfile.MatrixCoefficients; + + // AV1-ISOBMFF permits nclx to supply only bitstream fields explicitly coded as unspecified. A different + // specified value is a conformance error rather than a container-level color override. + if (colorConfig.ColorPrimaries == ObuColorPrimaries.Unspecified) + { + colorConfig.ColorPrimaries = containerColorPrimaries; + } + else if (colorConfig.ColorPrimaries != containerColorPrimaries) + { + throw new InvalidImageContentException("The HEIF CICP color primaries do not match the AV1 sequence header."); + } + + if (colorConfig.TransferCharacteristics == ObuTransferCharacteristics.Unspecified) + { + colorConfig.TransferCharacteristics = containerTransferCharacteristics; + } + else if (colorConfig.TransferCharacteristics != containerTransferCharacteristics) + { + throw new InvalidImageContentException("The HEIF CICP transfer characteristics do not match the AV1 sequence header."); + } + + if (colorConfig.MatrixCoefficients == ObuMatrixCoefficients.Unspecified) + { + colorConfig.MatrixCoefficients = containerMatrixCoefficients; + } + else if (colorConfig.MatrixCoefficients != containerMatrixCoefficients) + { + throw new InvalidImageContentException("The HEIF CICP matrix coefficients do not match the AV1 sequence header."); + } + + if (colorConfig.ColorRange != colorProfile.FullRange) + { + throw new InvalidImageContentException("The HEIF CICP color range does not match the AV1 sequence header."); + } + } + + // The same sequence header governs subsequent layered frames until another header OBU replaces it. + this.validatedSequenceHeader = sequenceHeader; + } + /// /// Parses one entropy-coded tile payload into the current frame state. /// @@ -540,6 +646,7 @@ internal sealed class Av1Decoder : IAv1TileReader, IDisposable ObuFrameHeader? frameHeader = this.obuReader.FrameHeader; Guard.NotNull(sequenceHeader, nameof(sequenceHeader)); Guard.NotNull(frameHeader, nameof(frameHeader)); + this.ValidateSequence(sequenceHeader); if (!ReferenceEquals(this.entropySequenceHeader, sequenceHeader)) { @@ -579,7 +686,18 @@ internal sealed class Av1Decoder : IAv1TileReader, IDisposable frameHeader, entropyContexts, primaryReferenceContext, - this.referenceFrames); + this.referenceFrames, + this.lumaPaletteColorIndexMap, + this.chromaPaletteColorIndexMap); + + this.frameBuffer = new Av1FrameBuffer(this.configuration, sequenceHeader, sequenceHeader.ColorConfig.GetColorFormat(), false) + { + Width = frameHeader.FrameSize.FrameWidth, + Height = frameHeader.FrameSize.FrameHeight + }; + + this.frameDecoder = new Av1FrameDecoder(sequenceHeader, frameHeader, this.tileReader.FrameInfo, this.frameBuffer, this.referenceFrames); + this.tileReader.FrameDecoder = this.frameDecoder; } this.tileReader.ReadTile(tileData, tileNum); @@ -592,65 +710,15 @@ internal sealed class Av1Decoder : IAv1TileReader, IDisposable { ObuSequenceHeader sequenceHeader = this.obuReader.SequenceHeader!; ObuFrameHeader frameHeader = this.obuReader.FrameHeader!; - Av1FrameBuffer? frameBuffer = null; + Av1FrameBuffer? frameBuffer = this.frameBuffer; + this.frameBuffer = null; + Av1FrameDecoder? frameDecoder = this.frameDecoder; + this.frameDecoder = null; Av1FrameBuffer? presentationBuffer = null; try { - if (!ReferenceEquals(this.validatedSequenceHeader, sequenceHeader)) - { - this.codecConfiguration?.Validate(sequenceHeader); - CicpProfile? colorProfile = this.containerColorProfile; - - if (colorProfile is not null) - { - ObuColorConfig colorConfig = sequenceHeader.ColorConfig; - ObuColorPrimaries containerColorPrimaries = (ObuColorPrimaries)colorProfile.ColorPrimaries; - ObuTransferCharacteristics containerTransferCharacteristics = - (ObuTransferCharacteristics)colorProfile.TransferCharacteristics; - - ObuMatrixCoefficients containerMatrixCoefficients = - (ObuMatrixCoefficients)colorProfile.MatrixCoefficients; - - // AV1-ISOBMFF permits nclx to supply only bitstream fields explicitly coded as unspecified. A - // different specified value is a conformance error rather than a container-level color override. - if (colorConfig.ColorPrimaries == ObuColorPrimaries.Unspecified) - { - colorConfig.ColorPrimaries = containerColorPrimaries; - } - else if (colorConfig.ColorPrimaries != containerColorPrimaries) - { - throw new InvalidImageContentException("The HEIF CICP color primaries do not match the AV1 sequence header."); - } - - if (colorConfig.TransferCharacteristics == ObuTransferCharacteristics.Unspecified) - { - colorConfig.TransferCharacteristics = containerTransferCharacteristics; - } - else if (colorConfig.TransferCharacteristics != containerTransferCharacteristics) - { - throw new InvalidImageContentException("The HEIF CICP transfer characteristics do not match the AV1 sequence header."); - } - - if (colorConfig.MatrixCoefficients == ObuMatrixCoefficients.Unspecified) - { - colorConfig.MatrixCoefficients = containerMatrixCoefficients; - } - else if (colorConfig.MatrixCoefficients != containerMatrixCoefficients) - { - throw new InvalidImageContentException("The HEIF CICP matrix coefficients do not match the AV1 sequence header."); - } - - if (colorConfig.ColorRange != colorProfile.FullRange) - { - throw new InvalidImageContentException("The HEIF CICP color range does not match the AV1 sequence header."); - } - } - - // The same sequence header governs subsequent layered frames until another header OBU replaces it. - // Retaining the validated reference prevents repeated item/color checks in the common layered case. - this.validatedSequenceHeader = sequenceHeader; - } + this.ValidateSequence(sequenceHeader); if (frameHeader.ShowExistingFrame) { @@ -660,7 +728,7 @@ internal sealed class Av1Decoder : IAv1TileReader, IDisposable if (existingFrameHeader.FrameType == ObuFrameType.KeyFrame) { - // libaom resets both the decoder working context and the context retained by the newly aliased key + // Both the decoder working context and the context retained by the newly aliased key frame reset // frame. Later primary-reference selection must therefore observe normative defaults. existingFrame.ResetEntropyContext(); this.entropyContexts?.Reset(); @@ -695,28 +763,16 @@ internal sealed class Av1Decoder : IAv1TileReader, IDisposable } Av1TileReader tileReader = this.tileReader!; - Av1FrameInfo frameInfo = tileReader.FrameInfo; - frameBuffer = new Av1FrameBuffer( - this.configuration, - sequenceHeader, - sequenceHeader.ColorConfig.GetColorFormat(), - false); - - // Plane allocations use the sequence maxima, while every reconstruction stage must see the active coded - // dimensions. Super-resolution replaces Width after decoding; Height remains the coded frame height. - frameBuffer.Width = frameHeader.FrameSize.FrameWidth; - frameBuffer.Height = frameHeader.FrameSize.FrameHeight; - - using Av1FrameDecoder frameDecoder = new(sequenceHeader, frameHeader, frameInfo, frameBuffer, this.referenceFrames); - frameDecoder.DecodeFrame(); + Av1FrameBuffer reconstructedFrameBuffer = frameBuffer!; + frameDecoder!.CompleteFrame(); bool retainsReference = (frameHeader.RefreshFrameFlags & byte.MaxValue) != 0; if (retainsReference) { // Motion compensation may address any clamped position inside the decoder border. Extending once after // all in-loop filters lets every later block use the full padded span without per-prediction edge copies. - Av1ReferenceFrameBorder.Extend(frameBuffer); + Av1ReferenceFrameBorder.Extend(reconstructedFrameBuffer); } bool needsSeparatePresentation = frameHeader.ShowFrame && frameHeader.FilmGrainParameters.ApplyGrain && retainsReference; @@ -730,10 +786,10 @@ internal sealed class Av1Decoder : IAv1TileReader, IDisposable // Film grain must never contaminate a decoded reference. A shown frame that is also refreshed therefore // receives one allocator-owned presentation copy; frames with no reference role are grained in place. - frameBuffer.CopyTo(presentationBuffer); + reconstructedFrameBuffer.CopyTo(presentationBuffer); } - Av1FrameBuffer grainTarget = presentationBuffer ?? frameBuffer; + Av1FrameBuffer grainTarget = presentationBuffer ?? reconstructedFrameBuffer; if (frameHeader.ShowFrame && frameHeader.FilmGrainParameters.ApplyGrain) { Av1FilmGrainDecoder filmGrainDecoder = new(sequenceHeader, frameHeader, grainTarget); @@ -745,12 +801,12 @@ internal sealed class Av1Decoder : IAv1TileReader, IDisposable { Av1FrameEntropyContexts entropyContexts = this.entropyContexts!; Av1FrameEntropyContext entropySnapshot = entropyContexts.RentPublishedSnapshot(); - referenceFrame = new(frameBuffer, frameHeader, frameInfo, entropySnapshot, entropyContexts); + referenceFrame = new(reconstructedFrameBuffer, frameHeader, frameInfo, entropySnapshot, entropyContexts); } else { // Presentation-only frames can never become primary references, so they own no unused CDF graph. - referenceFrame = new(frameBuffer, frameHeader, frameInfo); + referenceFrame = new(reconstructedFrameBuffer, frameHeader, frameInfo); } frameBuffer = null; @@ -785,6 +841,7 @@ internal sealed class Av1Decoder : IAv1TileReader, IDisposable // A non-shown frame or failed reconstruction never escapes this callback. The tile reader releases only // its initial frame-state lease; retained frames and the decoder result keep allocator-owned motion fields // alive independently after the entropy-neighbor contexts are returned. + frameDecoder?.Dispose(); presentationBuffer?.Dispose(); frameBuffer?.Dispose(); this.tileReader?.Dispose(); @@ -797,10 +854,16 @@ internal sealed class Av1Decoder : IAv1TileReader, IDisposable /// public void Dispose() { + this.frameDecoder?.Dispose(); + this.frameDecoder = null; + this.frameBuffer?.Dispose(); + this.frameBuffer = null; this.tileReader?.Dispose(); this.tileReader = null; this.referenceFrames.Dispose(); this.FrameInfo?.ReleaseOwner(); this.FrameInfo = null; + this.lumaPaletteColorIndexMap.Dispose(); + this.chromaPaletteColorIndexMap.Dispose(); } } diff --git a/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolContextHelper.cs b/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolContextHelper.cs index 187059506..0d4933251 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolContextHelper.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolContextHelper.cs @@ -283,7 +283,7 @@ internal static class Av1SymbolContextHelper int topClass = Math.Min(top, 4); int leftClass = Math.Min(left, 4); - // AV1 groups each edge into zero, low, or high coefficient-level classes. Retaining libaom's complete table + // AV1 groups each edge into zero, low, or high coefficient-level classes. Retaining the reference decoder's complete table // lets the reader and writer share one compile-time mapping without an encoder-side jagged-array allocation. return TransformBlockSkipContexts[(topClass * 5) + leftClass]; } @@ -550,7 +550,7 @@ internal static class Av1SymbolContextHelper /// The transform type associated with the selected prediction mode. public static Av1TransformType ConvertIntraModeToTransformType(Av1BlockModeInfo modeInfo, Av1PlaneType planeType) { - // libaom's get_uv_mode() is the explicit boundary between the distinct UV and luma prediction domains. CfL maps + // the reference decoder's get_uv_mode() is the explicit boundary between the distinct UV and luma prediction domains. CfL maps // to DC because the chroma AC contribution is applied to a DC predictor before coefficient reconstruction. Av1PredictionMode mode = planeType == Av1PlaneType.Y ? modeInfo.YMode : modeInfo.UvMode.ToLumaMode(); @@ -723,7 +723,7 @@ internal static class Av1SymbolContextHelper } // A single intra neighbor uses context two. A single inter neighbor and a block with no neighbors both use - // context zero, matching the unavailable-neighbor behavior in libaom's av1_get_intra_inter_context. + // context zero, matching the unavailable-neighbor behavior in the reference decoder's av1_get_intra_inter_context. if (above is not null) { return above.Value.ReferenceFrames[0] <= Av1ReferenceFrameType.Intra ? 2 : 0; @@ -745,7 +745,7 @@ internal static class Av1SymbolContextHelper /// The context in the inclusive range zero through four. public static int GetReferenceModeContext(Av1BlockModeInfo? above, Av1BlockModeInfo? left) { - // Libaom first classifies whether each neighbor uses a second inter reference. Single neighbors then contribute + // The reference decoder first classifies whether each neighbor uses a second inter reference. Single neighbors then contribute // their forward/backward direction, while intra neighbors take the same branch as a non-forward reference. if (above is not null && left is not null) { @@ -906,7 +906,7 @@ internal static class Av1SymbolContextHelper return context + leftFilter; } - // The fourth neighbor state is not a selectable Bilinear filter. It is the value libaom uses when a neighbor + // The fourth neighbor state is not a selectable Bilinear filter. It is the value the reference decoder uses when a neighbor // does not share the current primary reference, and when two contributing neighbors selected different filters. if (leftFilter == SwitchableInterpolationFilterCount) { @@ -995,7 +995,7 @@ internal static class Av1SymbolContextHelper /// The eight-entry reference-count destination indexed by . public static void CollectNeighborReferenceCounts(Av1BlockModeInfo? above, Av1BlockModeInfo? left, Span referenceCounts) { - // The caller reuses fixed inline storage across blocks. Clearing all eight entries matches libaom's + // The caller reuses fixed inline storage across blocks. Clearing all eight entries matches the reference decoder's // av1_collect_neighbors_ref_counts and prevents an unavailable neighbor from retaining an earlier block's vote. referenceCounts.Clear(); @@ -1265,7 +1265,7 @@ internal static class Av1SymbolContextHelper referenceCounts[(int)referenceFrames[0]]++; - // A current block may use one reference, but the conditioning neighbors may be compound blocks. Libaom counts + // A current block may use one reference, but the conditioning neighbors may be compound blocks. The reference decoder counts // both labels so later single-reference decisions remain bit-exact when compound support is enabled. if (referenceFrames[1] > Av1ReferenceFrameType.Intra) { diff --git a/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolDecoder.cs index e2a872603..4e1738fe1 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolDecoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolDecoder.cs @@ -1086,7 +1086,7 @@ internal ref struct Av1SymbolDecoder int endOfBlockShift = Av1SymbolContextHelper.EndOfBlockOffsetBits[endOfBlockPoint]; if (endOfBlockShift > 0) { - // The local table retains placeholders for the first three tokens, unlike libaom's compact table, + // The local table retains placeholders for the first three tokens, unlike the reference decoder's compact table, // so the decoded token is also the distribution index. int endOfBlockContext = endOfBlockPoint; bool bit = this.ReadEndOfBlockExtra(transformSizeContext, planeType, endOfBlockContext); diff --git a/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolEncoder.cs b/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolEncoder.cs index b00cf8da9..7fa1e1e19 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolEncoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolEncoder.cs @@ -387,7 +387,7 @@ internal class Av1SymbolEncoder : IDisposable int eobShift = eobOffsetBitCount - 1; int bit = Av1Math.GetBit(eobExtra, eobShift); - // The local table retains placeholders for the first three tokens, unlike libaom's compact table, + // The local table retains placeholders for the first three tokens, unlike the reference decoder's compact table, // so the encoded token is also the distribution index. int endOfBlockContext = endOfBlockPosition; w.WriteSymbol(bit, this.endOfBlockExtra[(int)transformSizeContext][(int)componentType][endOfBlockContext]); diff --git a/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolReader.cs b/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolReader.cs index c218f527c..336cf703a 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolReader.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolReader.cs @@ -87,7 +87,7 @@ internal ref struct Av1SymbolReader } // The final consumed byte must contain one trailing-one bit at the range decoder's exact stopping position, - // followed only by zero bits. This is the same bounded-stream check performed after libaom decodes a tile. + // followed only by zero bits. This is the same bounded-stream check performed after the reference decoder decodes a tile. int trailingOneBit = 128 >> ((consumedBitCount - 1) & 7); int trailingBitMask = (trailingOneBit << 1) - 1; if ((this.buffer[consumedByteCount - 1] & trailingBitMask) != trailingOneBit) diff --git a/src/ImageSharp/Formats/Heif/Av1/ModeDecision/Av1BlockGeometryFactory.cs b/src/ImageSharp/Formats/Heif/Av1/ModeDecision/Av1BlockGeometryFactory.cs index c7e77c92b..107fb02f6 100644 --- a/src/ImageSharp/Formats/Heif/Av1/ModeDecision/Av1BlockGeometryFactory.cs +++ b/src/ImageSharp/Formats/Heif/Av1/ModeDecision/Av1BlockGeometryFactory.cs @@ -125,7 +125,6 @@ internal class Av1BlockGeometryFactory /// Initializes a new instance of the class. /// /// The predefined geometry used to size and populate the mode-decision scan. - /// SVT-AV1: md_scan_all_blks. public Av1BlockGeometryFactory(Av1GeometryIndex geom) { this.blockGeometryModeDecisionScan = new Av1BlockGeometry[MaxBlocksAllocated]; @@ -211,8 +210,6 @@ internal class Av1BlockGeometryFactory // (0)compute total number of blocks using the information provided // maxActiveBlockCount = CountTotalNumberOfActiveBlocks(min_nsq_bsize); - // if (maxActiveBlockCount != max_block_count) - // SVT_LOG(" \n\n Error %i blocks\n\n ", maxActiveBlockCount); // (2) Construct md scan blk_geom_mds: use info from dps int idx_mds = 0; this.ScanAllBlocks(ref idx_mds, maxSuperblock, 0, 0, false, 0, min_nsq_bsize); @@ -224,7 +221,6 @@ internal class Av1BlockGeometryFactory /// /// The smallest square size, in pixels, at which non-square partitions remain enabled. /// The number of active mode-decision scan entries. - /// SVT-AV1: count_total_num_of_active_blks. private static int CountTotalNumberOfActiveBlocks(int min_nsq_bsize) { int depth_scan_idx = 0; @@ -273,7 +269,6 @@ internal class Av1BlockGeometryFactory /// The zero-based partition-shape index in scan order. /// The width and height, in pixels, of the square being partitioned. /// The number of component blocks in the partition. - /// SVT-AV1: get_num_ns_per_part. private static int GetNonSquareCountPerPart(int partitionIterator, int sequenceSize) { int tot_num_ns_per_part = partitionIterator < 1 ? 1 : partitionIterator < 3 ? 2 : partitionIterator < 5 && sequenceSize < 128 ? 4 : 3; @@ -284,7 +279,6 @@ internal class Av1BlockGeometryFactory /// Records scan entries that represent the same block size at the same pixel origin. /// /// The number of populated scan entries to compare. - /// SVT-AV1: log_redundancy_similarity. private static void LogRedundancySimilarity(int max_block_count) { for (int blockIterator = 0; blockIterator < max_block_count; blockIterator++) @@ -315,7 +309,6 @@ internal class Av1BlockGeometryFactory /// The zero-based mode-decision scan index. /// The geometry stored at . /// Always thrown because the geometry lookup has not been implemented. - /// SVT-AV1: get_blk_geom_mds. public static Av1BlockGeometry GetBlockGeometryByModeDecisionScanIndex(int modeDecisionScanIndex) => throw new NotImplementedException(); /// @@ -377,12 +370,6 @@ internal class Av1BlockGeometryFactory // this.blockGeometryModeDecisionScan[index].QuadIndex = quadIterator; // this.blockGeometryModeDecisionScan[index].d1i = depth1Iterator++; // this.blockGeometryModeDecisionScan[index].sqi_mds = sqi_mds; - // this.blockGeometryModeDecisionScan[index].svt_aom_geom_idx = svt_aom_geom_idx; - /* - this.blockGeometryModeDecisionScan[index].parent_depth_idx_mds = sqi_mds == 0 - ? 0 - : (sqi_mds + (3 - quad_it) * ns_depth_offset[svt_aom_geom_idx][this.blockGeometryModeDecisionScan[index].Depth]) - - parent_depth_offset[svt_aom_geom_idx][this.blockGeometryModeDecisionScan[index].Depth];*/ this.blockGeometryModeDecisionScan[index].Depth1Offset = Depth1DepthOffset[(int)geometryIndex][this.blockGeometryModeDecisionScan[index].Depth]; this.blockGeometryModeDecisionScan[index].NextDepthOffset = @@ -473,17 +460,6 @@ internal class Av1BlockGeometryFactory this.blockGeometryModeDecisionScan[index].TransformOrigin[tx_depth][transformBlockIterator] = this.blockGeometryModeDecisionScan[index].Origin; } - - /*if (this.blockGeometryModeDecisionScan[index].bsize == BLOCK_16X8) - SVT_LOG(""); - this.blockGeometryModeDecisionScan[index].tx_width[tx_depth] = - tx_size_wide[this.blockGeometryModeDecisionScan[index].TransformSize[tx_depth]]; - this.blockGeometryModeDecisionScan[index].tx_height[tx_depth] = - tx_size_high[this.blockGeometryModeDecisionScan[index].TransformSize[tx_depth]]; - this.blockGeometryModeDecisionScan[index].tx_width_uv[tx_depth] = - tx_size_wide[this.blockGeometryModeDecisionScan[index].TransformSizeUv[tx_depth]]; - this.blockGeometryModeDecisionScan[index].tx_height_uv[tx_depth] = - tx_size_high[this.blockGeometryModeDecisionScan[index].TransformSizeUv[tx_depth]];*/ } // Transform depth one subdivides eligible luma blocks once while chroma retains its depth-zero size. @@ -1058,7 +1034,6 @@ internal class Av1BlockGeometryFactory /// The coded block size whose transform limit is requested. /// The plane index, where zero selects luma and a positive value selects chroma. /// The maximum transform size for the selected plane. - /// SVT-AV1: av1_get_tx_size. private static Av1TransformSize GetTransformSize(Av1BlockSize blockSize, int plane) { // Luma uses the coded block's normative transform ceiling directly. diff --git a/src/ImageSharp/Formats/Heif/Av1/Motion/Av1GlobalMotionParameters.cs b/src/ImageSharp/Formats/Heif/Av1/Motion/Av1GlobalMotionParameters.cs index b505b3df9..ee1930f7a 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Motion/Av1GlobalMotionParameters.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Motion/Av1GlobalMotionParameters.cs @@ -270,7 +270,7 @@ internal struct Av1GlobalMotionParameters } // These biased products are the normative reduced-precision P'P, P'q, and P'r matrices. Computing them - // directly preserves libaom's integer least-squares rounding instead of introducing floating-point drift. + // directly preserves the reference decoder's integer least-squares rounding instead of introducing floating-point drift. a00 += LeastSquaresSquare(sourceX); a01 += LeastSquaresProduct1(sourceX, sourceY); a11 += LeastSquaresSquare(sourceY); diff --git a/src/ImageSharp/Formats/Heif/Av1/Motion/Av1IntraBlockCopy.cs b/src/ImageSharp/Formats/Heif/Av1/Motion/Av1IntraBlockCopy.cs index 5ab25b8fa..d92b3959a 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Motion/Av1IntraBlockCopy.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Motion/Av1IntraBlockCopy.cs @@ -89,7 +89,7 @@ internal static class Av1IntraBlockCopy } // The top-left sample begins the outer search region. Sorting the adjacent and outer regions independently - // preserves libaom's nearest/near ordering while still accumulating repeated vectors across both regions. + // preserves the reference decoder's nearest/near ordering while still accumulating repeated vectors across both regions. AddBlock(ref partitionInfo, -1, -1, tileInfo, candidates, weights, ref candidateCount); for (int index = 2; index <= ReferenceSearchDistance; index++) { @@ -109,7 +109,7 @@ internal static class Av1IntraBlockCopy SortByWeight(candidates, weights, 0, nearestCandidateCount); SortByWeight(candidates, weights, nearestCandidateCount, candidateCount); - // Libaom clamps the ranked stack before selecting nearest and near. The displacement entropy syntax is + // The reference decoder clamps the ranked stack before selecting nearest and near. The displacement entropy syntax is // differential, so using an unclamped spatial candidate changes every following component even though the // final decoded displacement is validated separately against the stricter intra-block-copy source limits. for (int index = 0; index < candidateCount; index++) @@ -241,7 +241,7 @@ internal static class Av1IntraBlockCopy } } - // Libaom uses the four-mode-info-unit step only once the active block reaches 64 samples. + // Blocks below 64 samples use the finer two-mode-info-unit scan step. bool useFourUnitStep = width >= 16; for (int index = 0; index < end;) { @@ -296,7 +296,7 @@ internal static class Av1IntraBlockCopy } } - // Libaom uses the four-mode-info-unit step only once the active block reaches 64 samples. + // Blocks below 64 samples use the finer two-mode-info-unit scan step. bool useFourUnitStep = height >= 16; for (int index = 0; index < end;) { diff --git a/src/ImageSharp/Formats/Heif/Av1/Motion/Av1ReferenceMotionVectors.cs b/src/ImageSharp/Formats/Heif/Av1/Motion/Av1ReferenceMotionVectors.cs index 5a26a75d7..04dfb5060 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Motion/Av1ReferenceMotionVectors.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Motion/Av1ReferenceMotionVectors.cs @@ -337,8 +337,8 @@ internal sealed class Av1ReferenceMotionVectors } else { - // When the direct single-reference stack has fewer than two entries, AV1 extends it from every inter - // reference in the immediate above and left spatial blocks. Differing reference sign biases are reversed. + // This fallback supplies only the nearest and near pair when direct and projected scans leave gaps. + // Differing reference sign biases are reversed before either candidate enters that pair. for (int index = 0; Math.Abs(maximumRowOffset) >= 1 && index < extensionLength && this.Count < 2;) { Av1BlockModeInfo candidate = partitionInfo.SuperblockInfo.GetModeInfoAt(new Point(column + index, row - 1)); @@ -377,7 +377,7 @@ internal sealed class Av1ReferenceMotionVectors } // The two-element reference list is separate from the full DRL stack. Missing entries use global motion, - // and both entries undergo the same precision reduction as libaom's av1_find_best_ref_mvs output. + // and both entries undergo the same precision reduction as the reference decoder's av1_find_best_ref_mvs output. this.references[0] = (this.Count > 0 ? this.candidates[0] : globalMotionVector).LowerPrecision( frameHeader.AllowHighPrecisionMotionVector, frameHeader.ForceIntegerMotionVector); @@ -1154,7 +1154,7 @@ internal sealed class Av1ReferenceMotionVectors } // The fallback list is positional rather than a weighted candidate scan. Preserve both entries even when - // they are equal so DRL indices have the same meaning as the current libaom main implementation. + // they are equal so the derived DRL indices retain the same meaning. for (int index = 0; index < 2; index++) { this.candidates[index] = primaryList[index]; diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuFrameReferenceState.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuFrameReferenceState.cs index f8f3533f7..82f4ed2cc 100644 --- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuFrameReferenceState.cs +++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuFrameReferenceState.cs @@ -87,7 +87,7 @@ internal struct ObuFrameReferenceState if (frameIdNumbersPresent) { - // libaom keeps one current_frame_id in decoder-session state. The following header snapshots this value as + // the reference decoder keeps one current_frame_id in decoder-session state. The following header snapshots this value as // its previous identifier before consuming its own current_frame_id syntax. this.CurrentFrameId = frameHeader.CurrentFrameId; this.HasCurrentFrameId = true; diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs index 8363fe99e..4920687b7 100644 --- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs +++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs @@ -204,7 +204,7 @@ internal class ObuReader // advances once here, so ignored metadata, padding, and reserved OBUs are skipped without copying. Span obuPayload = reader.ReadBytes(payloadSize); - // AV1 operating_point_idc uses bits 0-7 for temporal IDs and bits 8-11 for spatial IDs. libaom + // AV1 operating_point_idc uses bits 0-7 for temporal IDs and bits 8-11 for spatial IDs. the reference decoder // requires both selected bits for an extended OBU, while an all-zero mask and unextended OBUs apply // universally. Sequence headers establish the mask and temporal delimiters define framing, so neither // can be filtered even when their extension identifies a layer outside the selected operating point. @@ -294,7 +294,7 @@ internal class ObuReader } // The primary header already owns the decoded frame state. Matching its encoded bytes avoids - // parsing the same adaptive frame-header syntax twice, as in libaom's decoder. + // parsing the same adaptive frame-header syntax twice. decodedPayloadSize = primaryFrameHeaderPayload.Length; break; case ObuType.Frame: @@ -322,7 +322,7 @@ internal class ObuReader if (combinedFrameHeader.ShowExistingFrame) { - // Current libaom permits show_existing_frame only in a standalone frame-header OBU. A + // The reference decoder permits show_existing_frame only in a standalone frame-header OBU. A // combined frame OBU is required to continue with a tile group and therefore cannot use // the header-only retained-frame presentation form. throw new InvalidImageContentException("A combined AV1 frame OBU cannot display an existing frame."); @@ -350,7 +350,7 @@ internal class ObuReader } // AV1 section 5.6 defines no delimiter syntax. The common post-switch validation still permits - // zero bytes between the empty syntax and the declared payload boundary, matching libaom. + // zero bytes between the empty syntax and the declared payload boundary, matching the reference decoder. decodedPayloadSize = 0; break; case ObuType.Padding: @@ -376,7 +376,7 @@ internal class ObuReader break; default: // Metadata, tile-list, and reserved OBUs do not contribute to this still-image reconstruction - // pass. Their declared payload has already been skipped by the parent reader. libaom rejects a + // pass. Their declared payload has already been skipped by the parent reader. the reference decoder rejects a // nonempty unrecognized payload that contains only zeros because it has no trailing one bit. if (payloadSize > 0) { @@ -476,7 +476,7 @@ internal class ObuReader header.HasExtension = reader.ReadBoolean(); header.HasSize = reader.ReadBoolean(); - // Current libaom consumes obu_reserved_1bit without rejecting its value. Reserved fields do not change the + // The reference decoder consumes obu_reserved_1bit without rejecting its value. Reserved fields do not change the // decoded syntax, so accepting either value preserves forward-compatible framing while the forbidden bit // remains a hard error above. _ = reader.ReadBoolean(); @@ -487,7 +487,7 @@ internal class ObuReader header.TemporalId = (int)reader.ReadLiteral(3); header.SpatialId = (int)reader.ReadLiteral(2); - // Current libaom likewise consumes extension_header_reserved_3bits without interpreting their value. + // The reference decoder likewise consumes extension_header_reserved_3bits without interpreting their value. _ = reader.ReadLiteral(3); } else @@ -1111,7 +1111,7 @@ internal class ObuReader ObuFrameSize referenceSize = referenceFrame.FrameHeader.FrameSize; // AV1 5.9.7 inherits the reference buffer's visible post-super-resolution dimensions, corresponding to - // libaom's y_crop_width and y_crop_height, plus its render rectangle. The current frame then signals its own + // the reference decoder's y_crop_width and y_crop_height, plus its render rectangle. The current frame then signals its own // super-resolution denominator, so the reference's coded width and denominator are not copied. frameSize.FrameWidth = referenceFrame.FrameBuffer.Width; frameSize.FrameHeight = referenceFrame.FrameBuffer.Height; @@ -1331,7 +1331,7 @@ internal class ObuReader int tileWidth = (tileInfo.TileColumnStartModeInfo[column + 1] - tileInfo.TileColumnStartModeInfo[column]) << Av1Constants.ModeInfoSizeLog2; - // Current libaom excludes the rightmost column from this conformance check because it receives the + // The reference decoder excludes the rightmost column from this conformance check because it receives the // remainder of the coded width. Every inner column must be at least 64 pixels, doubled when the frame // is super-resolution scaled. if (tileWidth < minimumInnerTileWidth) @@ -1811,7 +1811,7 @@ internal class ObuReader // Slot occupancy and frame-ID validity are independent normative states. Short signaling derives roles // from every occupied slot before this per-role validity check, matching av1_set_frame_refs followed by - // libaom's valid_for_referencing check. + // the reference decoder's valid_for_referencing check. if (referenceFrames.Resolve((int)slot) is null) { throw new InvalidImageContentException("An AV1 inter frame selects an unoccupied reference-map slot."); diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuSkipModeParameters.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuSkipModeParameters.cs index ca83961df..a45b504ea 100644 --- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuSkipModeParameters.cs +++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuSkipModeParameters.cs @@ -54,7 +54,7 @@ internal class ObuSkipModeParameters int nearestBackwardReferenceIndex = -1; // The seven entries are canonical roles, while each value selects one physical reference-map slot. Compare - // the selected slot's order hint so duplicate roles retain the same deterministic ordering as libaom. + // the selected slot's order hint so duplicate roles retain the same deterministic ordering as the reference decoder. for (int referenceIndex = 0; referenceIndex < Av1Constants.ReferencesPerFrame; referenceIndex++) { uint referenceOrderHint = referenceOrderHints[(int)referenceFrameIndices[referenceIndex]]; diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs index 4744a5988..a3d1d7fd7 100644 --- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs +++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs @@ -523,7 +523,7 @@ internal class ObuWriter int tileCount = tileInfo.TileColumnCount * tileInfo.TileRowCount; if (tileCount > 1) { - // A combined OBU_FRAME has implicit complete-frame tile bounds. Current libaom still + // A combined OBU_FRAME has implicit complete-frame tile bounds. The reference decoder still // writes the presence bit for a multi-tile frame, but requires that bit to remain zero. writer.WriteBoolean(false); } diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameDecoder.cs index 47aa19c57..279e5c5e7 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameDecoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameDecoder.cs @@ -103,16 +103,10 @@ internal sealed class Av1FrameDecoder : IAv1FrameDecoder, IDisposable public void Dispose() => this.blockDecoder.Dispose(); /// - /// Reconstructs every coded tile and applies the implemented in-loop frame stages in normative order. + /// Applies the in-loop frame stages after every superblock has been reconstructed. /// - public void DecodeFrame() + public void CompleteFrame() { - // Tile columns are the outer traversal because each call walks that column's tile rows and their superblocks. - for (int column = 0; column < this.frameHeader.TilesInfo.TileColumnCount; column++) - { - this.DecodeFrameTiles(column); - } - bool doLoopRestoration = this.frameHeader.LoopRestorationParameters.UsesLoopRestoration; Av1LoopFilterDecoder loopFilterDecoder = new( @@ -156,61 +150,12 @@ internal sealed class Av1FrameDecoder : IAv1FrameDecoder, IDisposable // The owning decoder applies grain only to the presentation buffer after reference ownership is established. } - /// - /// Reconstructs every tile row in one tile column. - /// - /// The zero-based tile-column index. - /// Follows libaom's single-threaded decode_tiles ordering. - private void DecodeFrameTiles(int tileColumn) - { - ObuTileGroupHeader tileInfo = this.frameHeader.TilesInfo; - for (int tileRow = 0; tileRow < tileInfo.TileRowCount; tileRow++) - { - // Tile boundaries are expressed in 4x4 mode-info units. Walk every superblock row between consecutive - // boundaries; using only the tile-row index would reconstruct one row and leave taller tiles incomplete. - int modeInfoRowStart = tileInfo.TileRowStartModeInfo[tileRow]; - int modeInfoRowEnd = tileInfo.TileRowStartModeInfo[tileRow + 1]; - for (int modeInfoRow = modeInfoRowStart; - modeInfoRow < modeInfoRowEnd; - modeInfoRow += this.sequenceHeader.SuperblockModeInfoSize) - { - int superblockRow = modeInfoRow / this.sequenceHeader.SuperblockModeInfoSize; - this.DecodeTileSuperblockRow(tileRow, tileColumn, modeInfoRow, superblockRow); - } - } - } - - /// - /// Reconstructs one superblock row within a tile from left to right. - /// - /// The zero-based tile-row index. - /// The zero-based tile-column index. - /// The frame-relative row in 4x4 mode-info units. - /// The frame-relative superblock row. - /// Corresponds to the superblock-row traversal in libaom's decode_tile. - private void DecodeTileSuperblockRow(int tileRow, int tileColumn, int modeInfoRow, int superblockRow) - { - ObuTileGroupHeader tileInfo = this.frameHeader.TilesInfo; - for (int modeInfoColumn = tileInfo.TileColumnStartModeInfo[tileColumn]; modeInfoColumn < tileInfo.TileColumnStartModeInfo[tileColumn + 1]; - modeInfoColumn += this.sequenceHeader.SuperblockModeInfoSize) - { - // Convert the signaled 4x4 mode-info column to the frame-level superblock index used by Av1FrameInfo. - int superblockColumn = modeInfoColumn << Av1Constants.ModeInfoSizeLog2 >> this.sequenceHeader.SuperblockSizeLog2; - - Av1SuperblockInfo superblockInfo = this.frameInfo.GetSuperblock(new Point(superblockColumn, superblockRow)); - - Point modeInfoPosition = new(modeInfoColumn, modeInfoRow); - this.DecodeSuperblock(modeInfoPosition, superblockInfo, new Av1TileInfo(tileRow, tileColumn, this.frameHeader)); - } - } - /// /// Reconstructs one superblock after applying its block state and delta-Q context. /// /// The superblock's top-left position in 4x4 mode-info units. /// The decoded syntax and block modes for the superblock. /// The tile that contains the superblock. - /// Corresponds to libaom's superblock decode boundary. public void DecodeSuperblock(Point modeInfoPosition, Av1SuperblockInfo superblockInfo, Av1TileInfo tileInfo) { this.blockDecoder.UpdateSuperblock(superblockInfo); @@ -224,10 +169,10 @@ internal sealed class Av1FrameDecoder : IAv1FrameDecoder, IDisposable /// The superblock's frame-relative origin in 4x4 mode-info units. /// The superblock whose block modes are traversed. /// The tile boundary information used by intra prediction. - /// Replays the depth-first block order produced by libaom's decode_partition. + /// Traverses the depth-first block order produced by tile parsing. private void DecodePartition(Point modeInfoPosition, Av1SuperblockInfo superblockInfo, Av1TileInfo tileInfo) { - foreach (Av1BlockModeInfo modeInfo in superblockInfo.GetModeInfos()) + foreach (ref Av1BlockModeInfo modeInfo in superblockInfo.GetModeInfos()) { Point subPosition = modeInfo.PositionInSuperblock; Av1BlockSize subSize = modeInfo.BlockSize; @@ -236,6 +181,11 @@ internal sealed class Av1FrameDecoder : IAv1FrameDecoder, IDisposable // Block positions are stored relative to the superblock; prediction and reconstruction require frame-relative mode-info coordinates. globalPosition.Offset(subPosition); this.blockDecoder.DecodeBlock(modeInfo, globalPosition, subSize, superblockInfo, tileInfo); + + // Palette maps are decoder-session scratch. Retained mode information must not keep views after the block + // has consumed them because the next superblock reuses the same storage. + modeInfo.SetPaletteColorIndexMap(Av1PlaneType.Y, default); + modeInfo.SetPaletteColorIndexMap(Av1PlaneType.Uv, default); } } } diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameEncoder.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameEncoder.cs index b5a847d40..105083eec 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameEncoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameEncoder.cs @@ -27,10 +27,9 @@ internal class Av1FrameEncoder /// /// Represents the not-yet-implemented entry point for encoding one AV1 still-image frame. /// - /// SVT-AV1: svt_av1_enc_init. public static void Encode() { // Still-image encoding needs the normative analysis, transform, quantization, entropy, and packetization stages, - // but it does not require SVT-AV1's application-level worker graph or video-sequence process orchestration. + // but it does not require the encoder's application-level worker graph or video-sequence process orchestration. } } diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Cdef/Av1CdefDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Cdef/Av1CdefDecoder.cs index 550c18853..63d09979a 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Cdef/Av1CdefDecoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Cdef/Av1CdefDecoder.cs @@ -257,7 +257,7 @@ internal class Av1CdefDecoder { int blockIndex = 0; - // libaom analyzes two listed 8x8 blocks together. The per-unit fixed list preserves that traversal + // the reference decoder analyzes two listed 8x8 blocks together. The per-unit fixed list preserves that traversal // without allocating a managed block list or repeating four skip-map lookups during filtering. for (; blockIndex < blockCount - 1; blockIndex += 2) { diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Cdef/Av1CdefFilter.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Cdef/Av1CdefFilter.cs index fe39e14c0..35f378a58 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Cdef/Av1CdefFilter.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Cdef/Av1CdefFilter.cs @@ -52,7 +52,7 @@ internal static partial class Av1CdefFilter if (Avx2.IsSupported) { // AV1 plane dimensions are multiples of four, so the CDEF copy has an even row count. Processing two rows - // together follows libaom's AVX2 scheduling while each conversion widens sixteen unsigned samples exactly. + // together follows the reference decoder's AVX2 scheduling while each conversion widens sixteen unsigned samples exactly. for (int row = 0; row < height; row += 2) { int firstSourceRow = sourceOffset + (row * sourceStride); @@ -363,7 +363,7 @@ internal static partial class Av1CdefFilter ref ushort sourceBase = ref MemoryMarshal.GetReference(source); ref TSample destinationBase = ref MemoryMarshal.GetReference(destination); - // libaom selects one of four closed kernels from the two strength flags. The semantic operator makes the same + // the reference decoder selects one of four closed kernels from the two strength flags. The semantic operator makes the same // choice once per block so the JIT removes primary/secondary mode branches from every row and tap. if (primaryStrength != 0) { @@ -602,7 +602,7 @@ internal static partial class Av1CdefFilter Vector256 one = Vector256.Create((short)1); int rowsPerBatch = blockWidth == 8 ? 2 : 4; - // The 256-bit lane layout follows libaom: two complete 8-wide rows, or four complete 4-wide rows. Directional + // The 256-bit lane layout follows the reference decoder: two complete 8-wide rows, or four complete 4-wide rows. Directional // offsets therefore remain ordinary source offsets, while all constrain, weight, clip, and round operations // advance several output rows together without crossing a row boundary inside any 128-bit lane. for (int row = 0; row < blockHeight; row += rowsPerBatch) @@ -702,7 +702,7 @@ internal static partial class Av1CdefFilter lines[row] = (samples >> coefficientShift).AsInt16() - analysisBias; } - // Vector lanes are written in memory order. These are the low-to-high forms of libaom's set-style constants. + // Vector lanes are written in memory order. These are the low-to-high forms of the reference decoder's set-style constants. Vector128 foldWeights0 = Vector128.Create(840, 420, 280, 210); Vector128 foldWeights1 = Vector128.Create(168, 140, 120, 105); Vector128 diagonalWeights0 = Vector128.Create(0, 0, 420, 210); @@ -711,7 +711,7 @@ internal static partial class Av1CdefFilter ref int costBase = ref costs[0]; // The first pass evaluates directions 4..7. Rotating the block counter-clockwise lets the identical arithmetic - // evaluate directions 0..3, exactly matching libaom's portable vector implementation. + // evaluate directions 0..3, exactly matching the reference decoder's portable vector implementation. ComputeDirectionCosts(ref lines, foldWeights0, foldWeights1, diagonalWeights0, diagonalWeights1).StoreUnsafe(ref costBase, 4); ReverseTranspose(ref lines); ComputeDirectionCosts(ref lines, foldWeights0, foldWeights1, diagonalWeights0, diagonalWeights1).StoreUnsafe(ref costBase); @@ -751,7 +751,7 @@ internal static partial class Av1CdefFilter Vector128 first = Vector128.LoadUnsafe(ref sourceBase, (nuint)(firstSourceOffset + (row * sourceStride))); Vector128 second = Vector128.LoadUnsafe(ref sourceBase, (nuint)(secondSourceOffset + (row * sourceStride))); - // Keeping one block in each 128-bit lane is the critical libaom layout: every byte shift, unpack, multiply, + // Keeping one block in each 128-bit lane is critical: every byte shift, unpack, multiply, // and transpose remains lane-local while one AVX2 instruction advances both direction searches. lines[row] = (Vector256.Create(first, second) >> coefficientShift).AsInt16() - analysisBias; } @@ -1548,7 +1548,7 @@ internal static partial class Av1CdefFilter } // Four-row batches use one 64-bit load per row. Pairing two rows in each 128-bit lane preserves the exact row - // boundaries required by libaom's lane-local shifts while avoiding reads beyond the frame sentinel border. + // boundaries required by the reference decoder's lane-local shifts while avoiding reads beyond the frame sentinel border. Vector64 row0 = LoadSamples(ref source, offset, 4).GetLower(); Vector64 row1 = LoadSamples(ref source, offset + stride, 4).GetLower(); Vector64 row2 = LoadSamples(ref source, offset + (2 * stride), 4).GetLower(); diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/FilmGrain/Av1FilmGrainDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/FilmGrain/Av1FilmGrainDecoder.cs index 1b5dcfdcb..89acc4038 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/FilmGrain/Av1FilmGrainDecoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/FilmGrain/Av1FilmGrainDecoder.cs @@ -359,7 +359,7 @@ internal sealed class Av1FilmGrainDecoder ? scratch.Slice(scratchOffset, chromaColumnLength) : Span.Empty; - // libaom zero-initializes the lookup structure before expanding control points. This matters + // the reference decoder zero-initializes the lookup structure before expanding control points. This matters // when chroma scaling is inherited from an empty luma scaling function. scalingY.Clear(); scalingCb.Clear(); diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1DeblockingFilter.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1DeblockingFilter.cs index b74e1b452..e9d36757b 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1DeblockingFilter.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1DeblockingFilter.cs @@ -481,7 +481,7 @@ internal static partial class Av1DeblockingFilter Vector128 signedQ0 = q0 - offset; Vector128 signedQ1 = q1 - offset; - // libaom performs every delta operation in the signed sample domain. Saturating only the final samples is + // the reference decoder performs every delta operation in the signed sample domain. Saturating only the final samples is // not equivalent because the intermediate delta can clip before the asymmetric +4/+3 rounding is applied. Vector128 filter = Vector128.ConditionalSelect(highEdgeVariance, Vector128.Clamp(signedP1 - signedQ1, minimum, maximum), Vector128.Zero); filter = Vector128.Clamp(filter + (3 * (signedQ0 - signedP0)), minimum, maximum) & filterEnabled; @@ -614,7 +614,7 @@ internal static partial class Av1DeblockingFilter Vector128 wideFilter = filterEnabled & flat & outerFlat; // The eight-tap routine first produces the normative fallback. Lanes satisfying the outer flatness mask are - // then replaced with the wider results, matching libaom's mask blend without evaluating lanes independently. + // then replaced with the wider results, matching the reference decoder's mask blend without evaluating lanes independently. Filter8(ref samples, filterEnabled, flat, highEdgeVarianceThreshold, bitDepth); if (Vector128.EqualsAll(wideFilter, Vector128.Zero)) { diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1LoopFilterDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1LoopFilterDecoder.cs index 0fec310ce..3e3616105 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1LoopFilterDecoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1LoopFilterDecoder.cs @@ -75,7 +75,7 @@ internal class Av1LoopFilterDecoder ObuColorConfig colorConfig = this.sequenceHeader.ColorConfig; int modeInfoRowsPerBand = 1 << (Av1Constants.MaxSuperBlockSizeLog2 - Av1Constants.ModeInfoSizeLog2); - // libaom's loop_filter_rows processes one MAX_MIB_SIZE band at a time so that a completed band can be + // the reference decoder's loop_filter_rows processes one MAX_MIB_SIZE band at a time so that a completed band can be // presented before the remainder of the frame. The ordering is observable because the vertical and // horizontal passes modify intersecting sample neighborhoods in place. for (int rowStart = 0; rowStart < this.frameHeader.ModeInfoRowCount; rowStart += modeInfoRowsPerBand) @@ -162,7 +162,7 @@ internal class Av1LoopFilterDecoder } // Horizontal edges are visited down each column. This ordering is observable because adjacent horizontal - // filters can modify samples that a later edge reads, so it must match libaom's av1_filter_block_plane_horz. + // filters can modify samples that a later edge reads, so it must match the reference decoder's av1_filter_block_plane_horz. for (int column = 0; column < this.frameHeader.ModeInfoColumnCount; column += columnStep) { for (int row = rowStart; row < rowEnd; row += rowStep) @@ -233,12 +233,12 @@ internal class Av1LoopFilterDecoder : planeY % transformSize.GetHeight() == 0; // A skipped intra block still has reconstructed prediction samples and is not a skipped inter transform. - // libaom therefore applies the skip predicate only when the corresponding primary reference is inter. + // The skip predicate therefore applies only when the corresponding primary reference is inter. bool currentSkippedTransform = modeInfo.Skip && modeInfo.ReferenceFrames[0] > Av1ReferenceFrameType.Intra; bool previousSkippedTransform = previousModeInfo.Skip && previousModeInfo.ReferenceFrames[0] > Av1ReferenceFrameType.Intra; // Every covered 4x4 position carries the owning block's storage index. Comparing those indices is the value-type - // equivalent of libaom's current-versus-previous MB_MODE_INFO pointer comparison at a prediction-unit boundary. + // equivalent of the reference decoder's current-versus-previous MB_MODE_INFO pointer comparison at a prediction-unit boundary. bool isBlockEdge = modeInfo.ModeInfoIndex != previousModeInfo.ModeInfoIndex; bool applyFilter = isTransformEdge && (isBlockEdge || !currentSkippedTransform || !previousSkippedTransform); if (!applyFilter) @@ -380,7 +380,7 @@ internal class Av1LoopFilterDecoder if (referenceFrame > Av1ReferenceFrameType.Intra) { // AV1's second mode-delta class contains every inter mode except the two global-motion modes. - // Keeping this classification next to the level arithmetic mirrors libaom's mode_lf_lut lookup. + // Keeping this classification next to the level arithmetic mirrors the reference decoder's mode_lf_lut lookup. int modeDeltaIndex = modeInfo.YMode is Av1PredictionMode.GlobalMotionVector or Av1PredictionMode.GlobalGlobalMotionVector ? 0 : 1; diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopRestoration/Av1SelfGuidedFilter.Operations.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopRestoration/Av1SelfGuidedFilter.Operations.cs index 30bcdd9fa..efe950622 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopRestoration/Av1SelfGuidedFilter.Operations.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopRestoration/Av1SelfGuidedFilter.Operations.cs @@ -256,7 +256,7 @@ internal static partial class Av1SelfGuidedFilter for (; column <= vectorEnd; column += Vector256.Count) { // Eight packed 16-bit samples become eight 32-bit lanes. The prefix scans mirror - // libaom's scan_32, and the replicated carry joins consecutive vector batches. + // the reference decoder's scan_32, and the replicated carry joins consecutive vector batches. Vector128 packed = Vector128.LoadUnsafe(ref sourceBase, (nuint)(sourceRowOffset + column)); Vector256 samples = Vector256.WidenLower(Vector256.Create(packed, Vector128.Zero)).AsInt32(); Vector256 squares = samples * samples; diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopRestoration/Av1WienerFilter.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopRestoration/Av1WienerFilter.cs index 735dd0a06..b00f5be9b 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopRestoration/Av1WienerFilter.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopRestoration/Av1WienerFilter.cs @@ -151,7 +151,7 @@ internal static class Av1WienerFilter filter[5] = (short)middle; filter[6] = (short)outer; - // libaom stores a seven-tap Wiener kernel in the shared eight-tap interpolation shape. + // the reference decoder stores a seven-tap Wiener kernel in the shared eight-tap interpolation shape. filter[7] = 0; } diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantizers/Av1DeQuantizationContext.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantizers/Av1DeQuantizationContext.cs index 0f795b3b2..13484d8bb 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantizers/Av1DeQuantizationContext.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantizers/Av1DeQuantizationContext.cs @@ -26,7 +26,6 @@ internal class Av1DeQuantizationContext /// /// The sequence header that supplies the coded bit depth. /// The frame header that supplies segmentation and quantization parameters. - /// Corresponds to setup_segmentation_dequant in libaom. public Av1DeQuantizationContext(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader) { Av1BitDepth bitDepth = sequenceHeader.ColorConfig.BitDepth; diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantizers/Av1InverseQuantizer.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantizers/Av1InverseQuantizer.cs index 97014e363..8c5aad539 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantizers/Av1InverseQuantizer.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Quantizers/Av1InverseQuantizer.cs @@ -80,7 +80,6 @@ internal class Av1InverseQuantizer /// The transform dimensions and scale. /// The color plane whose quantizer and matrix are used. /// The number of coefficient levels consumed. - /// Matches the coefficient dequantization arithmetic in libaom's read_coeffs_txb. public int InverseQuantize(Av1BlockModeInfo mode, Span level, Span qCoefficients, Av1TransformType transformType, Av1TransformSize transformSize, Av1Plane plane) { Guard.NotNull(this.deQuantsDeltaQ); @@ -159,7 +158,6 @@ internal class Av1InverseQuantizer /// The raster coefficient index into the inverse matrix. /// The inverse quantization matrix for the current level, plane, and transform size. /// The matrix-weighted dequantization value. - /// Corresponds to get_dqv in libaom. private static int GetDeQuantizedValue(short dequant, int coefficientIndex, ReadOnlySpan iqMatrix) { // Matrix elements use fixed-point precision; adding half a unit produces nearest-integer rounding on shift. diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/SuperResolution/Av1SuperResolutionDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/SuperResolution/Av1SuperResolutionDecoder.cs index 6f4eff0d3..73a6f2d19 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/SuperResolution/Av1SuperResolutionDecoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/SuperResolution/Av1SuperResolutionDecoder.cs @@ -125,7 +125,7 @@ internal class Av1SuperResolutionDecoder int sourceStart = Av1SuperResolutionFilter.SourceBorder; int bitDepth = this.frameBuffer.BitDepth.GetBitCount(); - // libaom partitions the same continuous phase progression by tile column but does not pad + // the reference decoder partitions the same continuous phase progression by tile column but does not pad // internal boundaries. Filtering the complete row therefore produces the identical samples. for (int row = 0; row < height; row++) { diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/SuperResolution/Av1SuperResolutionFilter.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/SuperResolution/Av1SuperResolutionFilter.cs index 05b25c560..8ca598c85 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/SuperResolution/Av1SuperResolutionFilter.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/SuperResolution/Av1SuperResolutionFilter.cs @@ -327,7 +327,7 @@ internal static class Av1SuperResolutionFilter Vector128 products2 = Vector128_.MultiplyAddAdjacent(samples2, filter2); Vector128 products3 = Vector128_.MultiplyAddAdjacent(samples3, filter3); - // libaom reduces four independent filters in two horizontal-add stages so the four complete sums occupy + // the reference decoder reduces four independent filters in two horizontal-add stages so the four complete sums occupy // consecutive lanes. Keeping that arrangement also allows both destination forms to use one packed store. Vector128 pairs01 = HorizontalAdd(products0, products1); Vector128 pairs23 = HorizontalAdd(products2, products3); diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1ChromaPredictionModeExtensions.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1ChromaPredictionModeExtensions.cs index 389e9daa0..1090a8037 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1ChromaPredictionModeExtensions.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1ChromaPredictionModeExtensions.cs @@ -30,7 +30,7 @@ internal static class Av1ChromaPredictionModeExtensions Av1ChromaPredictionMode.SmoothHorizontal => Av1PredictionMode.SmoothHorizontal, Av1ChromaPredictionMode.Paeth => Av1PredictionMode.Paeth, - // Chroma-from-luma adds its AC contribution to a DC prediction. libaom's get_uv_mode() therefore maps it + // Chroma-from-luma adds its AC contribution to a DC prediction. the reference decoder's get_uv_mode() therefore maps it // to DC when shared transform and neighbor metadata require the corresponding luma predictor. Av1ChromaPredictionMode.ChromaFromLuma => Av1PredictionMode.DC, _ => Av1PredictionMode.IntraInvalid, diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DirectionalIntraPredictor.Operations.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DirectionalIntraPredictor.Operations.cs index 4c5f7e7fc..927fb98eb 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DirectionalIntraPredictor.Operations.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1DirectionalIntraPredictor.Operations.cs @@ -566,7 +566,7 @@ internal static partial class Av1DirectionalIntraPredictor } else if (angle is > 180 and < 270) { - // libaom computes zone 3 as a zone 1 block with swapped dimensions, then transposes it. This preserves + // the reference decoder computes zone 3 as a zone 1 block with swapped dimensions, then transposes it. This preserves // contiguous reference reads and destination stores in both hot stages instead of scattering columns. Span transposed = scratch[..(width * height)]; PredictZone1(transposed, height, left, upsampleLeft, GetDeltaY(angle), height, width); diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1PredictionDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1PredictionDecoder.cs index 775ebcff0..4a11169e9 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1PredictionDecoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/Av1PredictionDecoder.cs @@ -85,7 +85,6 @@ internal class Av1PredictionDecoder /// The bit depth of the reconstructed samples. /// The transform block's horizontal offset within the mode-information block. /// The transform block's vertical offset within the mode-information block. - /// Corresponds to svt_av1_predict_intra in SVT-AV1. public void Decode( ref Av1PartitionInfo partitionInfo, Av1Plane plane, @@ -181,7 +180,7 @@ internal class Av1PredictionDecoder Span topNeighbor = referenceBuffer; ReadOnlySpan leftNeighbor = referenceBuffer[(referenceStride - 1)..]; - // Libaom predicts one maximum-transform-sized plane block for inter-intra. Destination storage is separate + // The reference decoder predicts one maximum-transform-sized plane block for inter-intra. Destination storage is separate // because the inter predictor must remain intact until the final mask blend consumes both complete blocks. this.PredictIntraBlock( ref partitionInfo, @@ -260,7 +259,7 @@ internal class Av1PredictionDecoder { int stride = pixelStride; - // Unlike SVT's separate destination and reference pointers, this span begins at the + // Unlike the encoder's separate destination and reference pointers, this span begins at the // previous row. That layout exposes the top, top-left, and strided left samples without copying. Span topNeighbor = pixelBuffer; Span leftNeighbor = pixelBuffer[(stride - 1)..]; @@ -298,7 +297,7 @@ internal class Av1PredictionDecoder if (plane != Av1Plane.Y) { // Chroma and luma modes are separate bitstream domains. Shared spatial predictors consume the explicit - // libaom get_uv_mode() equivalent rather than relying on their matching ordinal values. + // the reference decoder get_uv_mode() equivalent rather than relying on their matching ordinal values. mode = partitionInfo.ModeInfo.UvMode.ToLumaMode(); } @@ -1539,7 +1538,6 @@ internal class Av1PredictionDecoder /// The prediction angle relative to the edge's cardinal direction. /// A value indicating whether a neighboring smooth mode selects the alternate thresholds. /// when the edge must be upsampled; otherwise, . - /// Corresponds to svt_aom_use_intra_edge_upsample in SVT-AV1. private static bool UseIntraEdgeUpsample(int width, int height, int delta, bool filterType) { int d = Math.Abs(delta); @@ -1560,7 +1558,6 @@ internal class Av1PredictionDecoder /// The number of edge samples. /// The AV1 filter-strength index from zero through three. /// The reusable padded source workspace. - /// Corresponds to svt_av1_filter_intra_edge_c in SVT-AV1. private static void FilterIntraEdge(ref T buffer, int count, int strength, Span scratch) where T : unmanaged, IBinaryInteger { @@ -1825,7 +1822,6 @@ internal class Av1PredictionDecoder /// The prediction angle relative to the edge's cardinal direction. /// A value indicating whether a neighboring smooth mode selects the alternate thresholds. /// The filter strength from zero for no filtering through three for the strongest kernel. - /// Corresponds to svt_aom_intra_edge_filter_strength in SVT-AV1. private static int IntraEdgeFilterStrength(int width, int height, int delta, bool filterType) { int d = Math.Abs(delta); diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1CompoundInterPredictor.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1CompoundInterPredictor.cs index 2d07455ef..53ea21d18 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1CompoundInterPredictor.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1CompoundInterPredictor.cs @@ -232,7 +232,7 @@ internal static partial class Av1CompoundInterPredictor ReadOnlySpan horizontalCoefficients = GetCompoundCoefficients(horizontalFilter, horizontalPhase, width <= 4); ReadOnlySpan verticalCoefficients = GetCompoundCoefficients(verticalFilter, verticalPhase, height <= 4); - // Libaom increases the first-round shift only for 12-bit input. This keeps the signed horizontal + // The reference decoder increases the first-round shift only for 12-bit input. This keeps the signed horizontal // intermediate within sixteen bits while preserving the same total Q14 convolution precision. int intermediateRange = bitDepth + FilterBits - Round0Bits + 2; int round0 = Round0Bits + Math.Max(intermediateRange - 16, 0); diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterIntraMaskBuilder.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterIntraMaskBuilder.cs index 5f7244f7f..c1c671d10 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterIntraMaskBuilder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterIntraMaskBuilder.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Prediction.Inter; internal static partial class Av1InterIntraMaskBuilder { /// - /// Gets libaom's one-dimensional inter-intra alpha curve. + /// Gets the reference decoder's one-dimensional inter-intra alpha curve. /// private static ReadOnlySpan InterIntraWeights => [ diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterPredictor.Operator.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterPredictor.Operator.cs index 3f947a2f9..17aa2e5f4 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterPredictor.Operator.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterPredictor.Operator.cs @@ -474,7 +474,7 @@ internal static partial class Av1InterPredictor return; } - // Twelve-bit samples require two additional first-pass rounding bits to keep libaom's signed intermediate + // Twelve-bit samples require two additional first-pass rounding bits to keep the reference decoder's signed intermediate // within sixteen bits. The second pass gives those bits back, preserving a total Q14 shift. int intermediateRange = bitDepth + FilterBits - Round0Bits + 2; int round0 = Round0Bits + Math.Max(intermediateRange - 16, 0); @@ -757,7 +757,7 @@ internal static partial class Av1InterPredictor /// Receives the effective two-, four-, six-, or eight-tap length. public static void GetEffectiveKernel(ReadOnlySpan coefficients, out int firstCoefficient, out int tapCount) { - // This matches libaom's get_filter_tap decision. Reducing symmetric zero endpoints avoids source loads and + // This matches the reference decoder's get_filter_tap decision. Reducing symmetric zero endpoints avoids source loads and // multiply-adds while retaining the original tap-to-source alignment through firstCoefficient. if (coefficients[0] != 0 || coefficients[7] != 0) { diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterPredictor.TwoDimensions.Byte.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterPredictor.TwoDimensions.Byte.cs index c03309350..49f241da2 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterPredictor.TwoDimensions.Byte.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterPredictor.TwoDimensions.Byte.cs @@ -473,7 +473,7 @@ internal static partial class Av1InterPredictor int roundOffset = (1 << (offsetBits - round1)) + (1 << (offsetBits - round1 - 1)); // The biased first pass keeps every intermediate nonnegative and representable by a signed 16-bit lane. - // Removing both bias terms after the vertical Q7 filter reproduces libaom's single-reference rounding exactly. + // Removing both bias terms after the vertical Q7 filter reproduces the reference decoder's single-reference rounding exactly. for (int row = 0; row < height; row++) { ref short scratchRow = ref Unsafe.Add(ref scratchBase, row * scratchStride); diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterPredictor.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterPredictor.cs index 3a58297e3..efd3f4fd8 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterPredictor.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1InterPredictor.cs @@ -28,7 +28,7 @@ internal static partial class Av1InterPredictor internal const int FilterBits = 7; /// - /// The normal first-round shift used by libaom single-reference convolution. + /// The normal first-round shift used by the reference decoder single-reference convolution. /// internal const int Round0Bits = 3; diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1ReferenceScale.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1ReferenceScale.cs index 0ac3e11bb..822120c2e 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1ReferenceScale.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1ReferenceScale.cs @@ -79,7 +79,7 @@ internal readonly struct Av1ReferenceScale public int ScaleVertical(int value) => Scale(value, this.VerticalScale); /// - /// Applies libaom's signed fixed-point rounding without relying on implementation-defined negative shifts. + /// Applies the reference decoder's signed fixed-point rounding without relying on implementation-defined negative shifts. /// private static int Scale(int value, int scale) { diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1WedgeMask.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1WedgeMask.cs index ebef29bfc..f79da5774 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1WedgeMask.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/Inter/Av1WedgeMask.cs @@ -14,7 +14,7 @@ internal static class Av1WedgeMask private const int MasterSize = 64; /// - /// Gets the odd-row oblique prototype defined by libaom. + /// Gets the odd-row oblique prototype defined by the reference decoder. /// private static ReadOnlySpan MasterObliqueOdd => [ @@ -25,7 +25,7 @@ internal static class Av1WedgeMask ]; /// - /// Gets the even-row oblique prototype defined by libaom. + /// Gets the even-row oblique prototype defined by the reference decoder. /// private static ReadOnlySpan MasterObliqueEven => [ @@ -36,7 +36,7 @@ internal static class Av1WedgeMask ]; /// - /// Gets the vertical prototype defined by libaom. + /// Gets the vertical prototype defined by the reference decoder. /// private static ReadOnlySpan MasterVertical => [ @@ -183,7 +183,7 @@ internal static class Av1WedgeMask } /// - /// Gets libaom's canonical sign flip for a block and wedge index. + /// Gets the reference decoder's canonical sign flip for a block and wedge index. /// private static bool GetSignFlip(Av1BlockSize blockSize, int wedgeIndex) { diff --git a/src/ImageSharp/Formats/Heif/Av1/Prediction/IntraBlockCopy/Av1IntraBlockCopyBilinearPredictor.Operator.cs b/src/ImageSharp/Formats/Heif/Av1/Prediction/IntraBlockCopy/Av1IntraBlockCopyBilinearPredictor.Operator.cs index 20b9ba0ac..9454741fc 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Prediction/IntraBlockCopy/Av1IntraBlockCopyBilinearPredictor.Operator.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Prediction/IntraBlockCopy/Av1IntraBlockCopyBilinearPredictor.Operator.cs @@ -124,7 +124,7 @@ internal static partial class Av1IntraBlockCopyBilinearPredictor /// Applies the separable two-dimensional interpolation required when both source axes have a half-sample phase. /// /// - /// The offsets in libaom's separable two-pass implementation cancel algebraically to + /// The offsets in the reference decoder's separable two-pass implementation cancel algebraically to /// (topLeft + topRight + bottomLeft + bottomRight + 2) >> 2, so the closed operator produces the exact /// result directly without an intermediate image buffer. /// diff --git a/src/ImageSharp/Formats/Heif/Av1/ReferenceFrames/Av1ReferenceFrameDerivation.cs b/src/ImageSharp/Formats/Heif/Av1/ReferenceFrames/Av1ReferenceFrameDerivation.cs index 01149107e..48c73ebf6 100644 --- a/src/ImageSharp/Formats/Heif/Av1/ReferenceFrames/Av1ReferenceFrameDerivation.cs +++ b/src/ImageSharp/Formats/Heif/Av1/ReferenceFrames/Av1ReferenceFrameDerivation.cs @@ -74,7 +74,7 @@ internal static class Av1ReferenceFrameDerivation if (!slotOccupancy[lastMapIndex]) { // Unlike an unused empty slot, the explicitly signaled LAST slot must own a decoded frame before any - // derived mapping can be consumed. libaom rejects the missing reference at this frame-header boundary. + // derived mapping can be consumed. the reference decoder rejects the missing reference at this frame-header boundary. throw new InvalidImageContentException("An AV1 inter frame requests an unavailable LAST reference."); } @@ -98,7 +98,7 @@ internal static class Av1ReferenceFrameDerivation if (!slotOccupancy[mapIndex]) { - // libaom gives absent reference buffers sort index -1. Keeping empty managed slots in the same + // the reference decoder gives absent reference buffers sort index -1. Keeping empty managed slots in the same // leading partition prevents their stale order hints from participating in temporal selection. continue; } @@ -132,7 +132,7 @@ internal static class Av1ReferenceFrameDerivation throw new InvalidImageContentException("An AV1 inter frame requests a current or future frame as GOLDEN."); } - // libaom sorts first by shifted output order and then by reference-map index. The explicit tie break is + // the reference decoder sorts first by shifted output order and then by reference-map index. The explicit tie break is // normative: equal order hints select the highest map index for latest references and the lowest for earliest // references. Insertion sort is bounded to eight inline entries and does not allocate or require general sort // infrastructure at the frame-header boundary. @@ -194,7 +194,7 @@ internal static class Av1ReferenceFrameDerivation if (backwardStartIndex <= backwardEndIndex) { // ALTREF receives the frame farthest into the future. The sorted-map-index tie break selects the highest - // slot when multiple frames share that order hint, matching both the specification and libaom. + // slot when multiple frames share that order hint, matching both the specification and the reference decoder. referenceFrameIndices[alternateReferenceIndex] = (uint)referenceInfo[backwardEndIndex].MapIndex; assignedReferences[alternateReferenceIndex] = true; backwardEndIndex--; diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockModeInfo.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockModeInfo.cs index cdd03d8bc..2b6b0f48e 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockModeInfo.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockModeInfo.cs @@ -147,7 +147,7 @@ internal struct Av1BlockModeInfo /// Gets the interpolation filters used for vertical and horizontal subpixel prediction. /// /// - /// Index zero is the vertical filter and index one is the horizontal filter, matching libaom's + /// Index zero is the vertical filter and index one is the horizontal filter, matching the reference decoder's /// InterpFilters.y_filter and InterpFilters.x_filter layout. /// [UnscopedRef] diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.MotionField.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.MotionField.cs index 457f3434b..fbd64de86 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.MotionField.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.MotionField.cs @@ -129,7 +129,7 @@ internal partial class Av1FrameInfo if (frameHeader.IsIntra) { - // Intra frames retain an empty source field. They can occupy reference slots, but libaom rejects them as + // Intra frames retain an empty source field. They can occupy reference slots, but the reference decoder rejects them as // projection sources before consulting their reference-order-hint metadata. return; } @@ -138,7 +138,7 @@ internal partial class Av1FrameInfo ReadOnlySpan referenceFrameIndices = frameHeader.GetReferenceFrameIndices(); ObuOrderHintInfo orderHintInfo = sequenceHeader.OrderHintInfo; - // Capture the seven logical-role order hints before this frame refreshes any physical map slots. Libaom keeps + // Capture the seven logical-role order hints before this frame refreshes any physical map slots. The reference decoder keeps // the same snapshot on RefCntBuffer so a later frame can project this frame's stored motion vectors. for (int referenceIndex = 0; referenceIndex < Av1Constants.ReferencesPerFrame; referenceIndex++) { @@ -174,7 +174,7 @@ internal partial class Av1FrameInfo return; } - // libaom aligns the projected field stride to the largest superblock even for a 64x64 sequence. This keeps + // the reference decoder aligns the projected field stride to the largest superblock even for a 64x64 sequence. This keeps // later temporal-candidate addressing independent of the current sequence's selected superblock size. int alignedModeInfoColumnCount = Av1Math.AlignPowerOf2( this.activeModeInfoColumnCount, @@ -195,7 +195,7 @@ internal partial class Av1FrameInfo uint alternateOfLastOrderHint = lastFrame.FrameInfo.motionFieldReferenceOrderHints[(int)Av1ReferenceFrameType.Alternate]; // A LAST frame whose ALTREF order matches GOLDEN is an overlay. Projecting it would duplicate the overlay's - // temporal source, but libaom still consumes one position from the three-source projection budget. + // temporal source, but the reference decoder still consumes one position from the three-source projection budget. if (alternateOfLastOrderHint != goldenFrame.FrameHeader.OrderHint) { _ = this.ProjectMotionField(sequenceHeader, frameHeader, lastFrame, reverseDirection: true); @@ -327,7 +327,7 @@ internal partial class Av1FrameInfo Span referenceFrames = modeInfo.ReferenceFrames; Span motionVectors = modeInfo.MotionVectors; - // Compound blocks may offer two vectors. libaom retains the last eligible forward-or-past reference after + // Compound blocks may offer two vectors. the reference decoder retains the last eligible forward-or-past reference after // excluding same-order, future, and out-of-range vectors, so preserve that overwrite order exactly. for (int referenceIndex = 0; referenceIndex < 2; referenceIndex++) { @@ -493,16 +493,12 @@ internal partial class Av1FrameInfo this.ownerCount--; if (this.ownerCount == 0) { - // Frame-sized motion and palette storage remains addressable through retained mode information. Return - // all of it together only after tile, reference, presentation, and decoder-result owners are gone. + // Frame-sized motion storage remains addressable through retained references. Return it only after tile, + // reference, presentation, and decoder-result owners are gone. this.retainedMotionField?.Dispose(); this.retainedMotionField = null; this.temporalMotionField?.Dispose(); this.temporalMotionField = null; - this.lumaPaletteColorIndexMap?.Dispose(); - this.lumaPaletteColorIndexMap = null; - this.chromaPaletteColorIndexMap?.Dispose(); - this.chromaPaletteColorIndexMap = null; } } @@ -532,7 +528,7 @@ internal partial class Av1FrameInfo int baseBlockColumn = (blockColumn >> 3) << 3; // One field cell spans 8 samples, while vectors use one-eighth-sample units; dividing by 64 converts between - // them. C# integer division truncates toward zero, matching libaom's explicit signed-shift construction. + // them. C# integer division truncates toward zero, matching the reference decoder's explicit signed-shift construction. int rowOffset = motionVector.Row / (1 << MotionVectorToFieldOffsetShift); int columnOffset = motionVector.Column / (1 << MotionVectorToFieldOffsetShift); projectedRow = reverseDirection ? blockRow - rowOffset : blockRow + rowOffset; diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs index 46ff97db0..22c776757 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs @@ -56,36 +56,6 @@ internal partial class Av1FrameInfo : IDisposable /// private readonly int subsamplingFactor; - /// - /// The aligned luma palette-map width in samples. - /// - private readonly int lumaPaletteColorIndexMapWidth; - - /// - /// The aligned luma palette-map height in samples. - /// - private readonly int lumaPaletteColorIndexMapHeight; - - /// - /// The aligned chroma palette-map width in samples. - /// - private readonly int chromaPaletteColorIndexMapWidth; - - /// - /// The aligned chroma palette-map height in samples. - /// - private readonly int chromaPaletteColorIndexMapHeight; - - /// - /// Owns row-addressable luma palette indices for the frame. - /// - private Buffer2D? lumaPaletteColorIndexMap; - - /// - /// Owns row-addressable chroma palette indices for the frame. - /// - private Buffer2D? chromaPaletteColorIndexMap; - /// /// Stores one addressing view for each frame superblock. /// @@ -210,10 +180,6 @@ internal partial class Av1FrameInfo : IDisposable // Chroma capacity scales by two for each sampled axis: 4:4:4 => 0, 4:2:2 => 1, 4:2:0 => 2. this.subsamplingFactor = (subX && subY) ? 2 : (subX && !subY) ? 1 : (!subX && !subY) ? 0 : -1; Guard.IsFalse(this.subsamplingFactor == -1, nameof(this.subsamplingFactor), "Invalid combination of subsampling."); - this.lumaPaletteColorIndexMapWidth = superblockAlignedWidth; - this.lumaPaletteColorIndexMapHeight = superblockAlignedHeight; - this.chromaPaletteColorIndexMapWidth = superblockAlignedWidth >> (subX ? 1 : 0); - this.chromaPaletteColorIndexMapHeight = superblockAlignedHeight >> (subY ? 1 : 0); int lumaCoefficientCountPerSuperblock = this.modeInfoCountPerSuperblock * CoefficientCountPerModeInfo; int chromaCoefficientCountPerSuperblock = lumaCoefficientCountPerSuperblock >> this.subsamplingFactor; this.coefficientsY = new int[superblockCount * lumaCoefficientCountPerSuperblock]; @@ -238,51 +204,6 @@ internal partial class Av1FrameInfo : IDisposable /// public int SuperblockModeInfoSize => this.modeInfoSizePerSuperblock; - /// - /// Gets frame-owned row-addressable palette-map storage for one coding block. - /// - /// The decoder configuration providing frame storage. - /// The luma or shared chroma plane class. - /// The block bounds in plane samples. - /// The palette-map region assigned to the coding block. - public Buffer2DRegion GetPaletteColorIndexMap( - Configuration configuration, - Av1PlaneType planeType, - Rectangle bounds) - { - Buffer2D? buffer; - if (planeType == Av1PlaneType.Y) - { - buffer = this.lumaPaletteColorIndexMap; - if (buffer is null) - { - // A 2D allocation may contain multiple memory groups, but row alignment guarantees that every - // palette row remains contiguous for entropy decoding and SIMD reconstruction. - buffer = configuration.MemoryAllocator.Allocate2D( - this.lumaPaletteColorIndexMapWidth, - this.lumaPaletteColorIndexMapHeight); - - this.lumaPaletteColorIndexMap = buffer; - } - } - else - { - buffer = this.chromaPaletteColorIndexMap; - if (buffer is null) - { - buffer = configuration.MemoryAllocator.Allocate2D( - this.chromaPaletteColorIndexMapWidth, - this.chromaPaletteColorIndexMapHeight); - - this.chromaPaletteColorIndexMap = buffer; - } - } - - // Partition traversal assigns non-overlapping frame regions, so retaining a view records the complete - // identify-time syntax without copying block maps or allocating storage for each coding block. - return new Buffer2DRegion(buffer, bounds); - } - /// /// Initializes the active frame's contiguous segment map and applies whole-map inheritance when requested. /// @@ -341,7 +262,7 @@ internal partial class Av1FrameInfo : IDisposable primaryReferenceFrameInfo.segmentIdColumnCount != this.segmentIdColumnCount || primaryReferenceFrameInfo.segmentIdRowCount != this.segmentIdRowCount) { - // libaom exposes the prior map only when both mode-info dimensions match the active frame. Treating a + // the reference decoder exposes the prior map only when both mode-info dimensions match the active frame. Treating a // differently sized retained map as absent prevents coordinates from being reinterpreted with a new stride. return 0; } diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs index af43ed72b..31daba54d 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs @@ -101,6 +101,21 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable /// private readonly Av1LevelBuffer coefficientLevels; + /// + /// Reusable luma palette indices for the coding blocks in one superblock. + /// + private readonly Buffer2D lumaPaletteColorIndexMap; + + /// + /// Reusable chroma palette indices for the coding blocks in one superblock. + /// + private readonly Buffer2D chromaPaletteColorIndexMap; + + /// + /// Indicates whether this reader owns and disposes the palette maps. + /// + private readonly bool ownsPaletteColorIndexMaps; + /// /// Reusable storage for the eight spatial displacement-vector candidates permitted by AV1. /// @@ -131,11 +146,6 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable /// private readonly Configuration configuration; - /// - /// Reconstructs each parsed superblock when pixel decoding is requested; otherwise, tile parsing is metadata-only. - /// - private readonly IAv1FrameDecoder? frameDecoder; - /// /// The decoder-session entropy contexts reused by every tile in the current frame. /// @@ -182,12 +192,74 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable Av1FrameEntropyContexts entropyContexts, Av1FrameEntropyContext? primaryReferenceContext, Av1ReferenceFrameStore? referenceFrames) + : this(configuration, sequenceHeader, frameHeader, entropyContexts, primaryReferenceContext, referenceFrames, null, null, true) + { + } + + /// + /// Initializes a new instance of the class with decoder-session entropy and palette state. + /// + /// The decoder configuration. + /// The active AV1 sequence header. + /// The frame header whose tiles will be parsed. + /// The entropy contexts reused by the owning decoder session. + /// + /// The retained primary-reference entropy context, or when the frame selects defaults. + /// + /// The retained reconstructed frames. + /// The decoder-session luma palette scratch map. + /// The decoder-session chroma palette scratch map. + public Av1TileReader( + Configuration configuration, + ObuSequenceHeader sequenceHeader, + ObuFrameHeader frameHeader, + Av1FrameEntropyContexts entropyContexts, + Av1FrameEntropyContext? primaryReferenceContext, + Av1ReferenceFrameStore referenceFrames, + Buffer2D lumaPaletteColorIndexMap, + Buffer2D chromaPaletteColorIndexMap) + : this( + configuration, + sequenceHeader, + frameHeader, + entropyContexts, + primaryReferenceContext, + referenceFrames, + lumaPaletteColorIndexMap, + chromaPaletteColorIndexMap, + false) + { + } + + /// + /// Initializes a new instance of the class with explicit palette-map ownership. + /// + /// The decoder configuration. + /// The active AV1 sequence header. + /// The frame header whose tiles will be parsed. + /// The entropy contexts reused by the owning decoder session. + /// The retained primary-reference entropy context. + /// The retained reconstructed frames. + /// A shared luma palette map, or when the reader owns one. + /// A shared chroma palette map, or when the reader owns one. + /// Whether the reader owns and disposes the palette maps. + private Av1TileReader( + Configuration configuration, + ObuSequenceHeader sequenceHeader, + ObuFrameHeader frameHeader, + Av1FrameEntropyContexts entropyContexts, + Av1FrameEntropyContext? primaryReferenceContext, + Av1ReferenceFrameStore? referenceFrames, + Buffer2D? lumaPaletteColorIndexMap, + Buffer2D? chromaPaletteColorIndexMap, + bool ownsPaletteColorIndexMaps) { this.FrameHeader = frameHeader; this.configuration = configuration; this.SequenceHeader = sequenceHeader; this.entropyContexts = entropyContexts; this.referenceFrames = referenceFrames; + this.ownsPaletteColorIndexMaps = ownsPaletteColorIndexMaps; this.entropyContexts.BeginFrame(frameHeader.QuantizationParameters.BaseQIndex, primaryReferenceContext); // FrameInfo owns all traversal-order records and coefficient storage produced by the tile readers. @@ -245,6 +317,38 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable throw; } + if (ownsPaletteColorIndexMaps) + { + Buffer2D? ownedLumaPaletteColorIndexMap = null; + Buffer2D? ownedChromaPaletteColorIndexMap = null; + + try + { + // Standalone syntax readers have no decoder-session owner. They still use the same fixed + // maximum-superblock bound and return both maps when the reader is disposed. + int paletteMapLength = 1 << Av1Constants.MaxSuperBlockSizeLog2; + ownedLumaPaletteColorIndexMap = configuration.MemoryAllocator.Allocate2D(paletteMapLength, paletteMapLength); + ownedChromaPaletteColorIndexMap = configuration.MemoryAllocator.Allocate2D(paletteMapLength, paletteMapLength); + this.lumaPaletteColorIndexMap = ownedLumaPaletteColorIndexMap; + this.chromaPaletteColorIndexMap = ownedChromaPaletteColorIndexMap; + } + catch + { + ownedChromaPaletteColorIndexMap?.Dispose(); + ownedLumaPaletteColorIndexMap?.Dispose(); + this.coefficientLevels.Dispose(); + this.leftNeighborContext.Dispose(); + this.aboveNeighborContext.Dispose(); + this.FrameInfo.Dispose(); + throw; + } + } + else + { + this.lumaPaletteColorIndexMap = lumaPaletteColorIndexMap!; + this.chromaPaletteColorIndexMap = chromaPaletteColorIndexMap!; + } + if (referenceFrames is not null) { try @@ -255,9 +359,15 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable } catch { - this.aboveNeighborContext.Dispose(); - this.leftNeighborContext.Dispose(); + if (this.ownsPaletteColorIndexMaps) + { + this.chromaPaletteColorIndexMap.Dispose(); + this.lumaPaletteColorIndexMap.Dispose(); + } + this.coefficientLevels.Dispose(); + this.leftNeighborContext.Dispose(); + this.aboveNeighborContext.Dispose(); this.FrameInfo.Dispose(); throw; } @@ -273,7 +383,7 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable /// The frame decoder that reconstructs each parsed superblock. public Av1TileReader(Configuration configuration, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, IAv1FrameDecoder frameDecoder) : this(configuration, sequenceHeader, frameHeader) - => this.frameDecoder = frameDecoder; + => this.FrameDecoder = frameDecoder; /// /// Gets the default self-guided restoration projection coefficients for each color plane. @@ -332,6 +442,11 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable /// public Av1FrameInfo FrameInfo { get; } + /// + /// Gets or sets the optional decoder that reconstructs each superblock immediately after its syntax is parsed. + /// + public IAv1FrameDecoder? FrameDecoder { get; set; } + /// /// Gets the completed frame entropy context selected by the context-update tile. /// @@ -350,6 +465,12 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable this.aboveNeighborContext.Dispose(); this.leftNeighborContext.Dispose(); this.coefficientLevels.Dispose(); + if (this.ownsPaletteColorIndexMaps) + { + this.lumaPaletteColorIndexMap.Dispose(); + this.chromaPaletteColorIndexMap.Dispose(); + } + this.FrameInfo.Dispose(); } @@ -358,7 +479,6 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable /// /// The entropy-coded tile payload. /// The zero-based tile index in row-major order. - /// Corresponds to decode_tile in libaom. public void ReadTile(Span tileData, int tileNum) { // AV1 tiles never inherit adaptation from another tile in the same frame. Reusing one graph is safe because @@ -366,7 +486,7 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable // constructed. this.entropyContexts.Working.CopyFrom(this.entropyContexts.Base); - // The frame syntax exposes a disable flag, while the range reader follows libaom's positive + // The frame syntax exposes a disable flag, while the range reader follows the reference decoder's positive // allow_update_cdf convention. Av1SymbolDecoder reader = new( this.configuration, @@ -424,7 +544,7 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable this.ParsePartition(ref reader, modeInfoPosition, superBlockSize, superblockInfo, tileInfo); // Identify-only parsing omits a frame decoder but still populates the complete syntax model. - this.frameDecoder?.DecodeSuperblock(modeInfoPosition, superblockInfo, tileInfo); + this.FrameDecoder?.DecodeSuperblock(modeInfoPosition, superblockInfo, tileInfo); } } @@ -434,7 +554,7 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable if (!this.FrameHeader.DisableFrameEndUpdateCdf && tileNum == this.FrameHeader.TilesInfo.ContextUpdateTileId) { - // libaom publishes only context_update_tile_id after every tile has independently started from the frame + // the reference decoder publishes only context_update_tile_id after every tile has independently started from the frame // base, then clears its CDF counters. Snapshotting into a third reusable graph preserves the unchanged base // for tiles that follow the selected tile in bitstream order. this.entropyContexts.Working.SnapshotTo(this.entropyContexts.Published); @@ -692,7 +812,7 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable if (subSize.GetSubsampled(colorConfig.SubSamplingX, colorConfig.SubSamplingY) == Av1BlockSize.Invalid) { // Luma partition syntax can describe a sub-8x8 shape that has no legal representation after chroma - // subsampling. Reject it before any block state is published, matching libaom's decode_partition boundary. + // subsampling. Reject it before any block state is published, matching the reference decoder's decode_partition boundary. throw new InvalidImageContentException($"The decoded AV1 block size {subSize} is invalid for the sequence chroma subsampling."); } @@ -1113,7 +1233,7 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable int leftContextOffset = startY - superblockRow; // Above contexts are tile-column relative, while left contexts are reused from the start of each - // superblock row. Slicing both arrays here gives the entropy derivation the same pointer bases as libaom. + // superblock row. Slicing both arrays here gives the entropy derivation the same pointer bases as the reference decoder. Av1TransformBlockContext transformBlockContext = this.GetTransformBlockContext( transformSize, plane, @@ -1313,7 +1433,7 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable int transformBlockUnitWideCount = transformSize.Get4x4WideCount(); int transformBlockUnitHighCount = transformSize.Get4x4HighCount(); - // libaom tests the context bytes through packed native loads. Enumerating the same transform-width and + // the reference decoder tests the context bytes through packed native loads. Enumerating the same transform-width and // transform-height entries avoids unaligned reads while preserving the required any-nonzero result. for (int i = 0; i < transformBlockUnitWideCount; i++) { @@ -1442,7 +1562,6 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable /// The current coding block. /// The containing superblock. /// The active tile boundaries. - /// Implements AV1 section 5.11.16 and corresponds to read_tx_size in libaom. private void ReadBlockTransformSize( ref Av1SymbolDecoder reader, Point modeInfoLocation, @@ -1722,7 +1841,7 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable int planeColumn = idx >> (subX ? 1 : 0); // The 64x64 region cursor is expressed on the luma grid. Chroma transform offsets use the - // target plane's 4x4 grid, matching libaom's row/column subsampling before transform traversal. + // target plane's 4x4 grid, matching the reference decoder's row/column subsampling before transform traversal. for (int blockRow = planeRow; blockRow < unitHeight; blockRow += stepRow) { for (int blockColumn = planeColumn; blockColumn < unitWidth; blockColumn += stepColumn) @@ -1786,14 +1905,9 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable out int rows, out int columns); - Buffer2DRegion colorIndexMap = this.FrameInfo.GetPaletteColorIndexMap( - this.configuration, - Av1PlaneType.Y, - new Rectangle( - partitionInfo.ColumnIndex << Av1Constants.ModeInfoSizeLog2, - partitionInfo.RowIndex << Av1Constants.ModeInfoSizeLog2, - planeWidth, - planeHeight)); + Point position = modeInfo.PositionInSuperblock; + Rectangle bounds = new(position.X << Av1Constants.ModeInfoSizeLog2, position.Y << Av1Constants.ModeInfoSizeLog2, planeWidth, planeHeight); + Buffer2DRegion colorIndexMap = new(this.lumaPaletteColorIndexMap, bounds); DecodePaletteColorMap( ref reader, @@ -1805,7 +1919,10 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable columns, colorIndexMap); - modeInfo.SetPaletteColorIndexMap(Av1PlaneType.Y, colorIndexMap); + if (this.FrameDecoder is not null) + { + modeInfo.SetPaletteColorIndexMap(Av1PlaneType.Y, colorIndexMap); + } } if (modeInfo.GetPaletteSize(Av1PlaneType.Uv) != 0) @@ -1821,14 +1938,9 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable int subX = this.SequenceHeader.ColorConfig.SubSamplingX ? 1 : 0; int subY = this.SequenceHeader.ColorConfig.SubSamplingY ? 1 : 0; - Buffer2DRegion colorIndexMap = this.FrameInfo.GetPaletteColorIndexMap( - this.configuration, - Av1PlaneType.Uv, - new Rectangle( - (partitionInfo.ColumnIndex << Av1Constants.ModeInfoSizeLog2) >> subX, - (partitionInfo.RowIndex << Av1Constants.ModeInfoSizeLog2) >> subY, - planeWidth, - planeHeight)); + Point position = modeInfo.PositionInSuperblock; + Rectangle bounds = new((position.X << Av1Constants.ModeInfoSizeLog2) >> subX, (position.Y << Av1Constants.ModeInfoSizeLog2) >> subY, planeWidth, planeHeight); + Buffer2DRegion colorIndexMap = new(this.chromaPaletteColorIndexMap, bounds); DecodePaletteColorMap( ref reader, @@ -1840,7 +1952,10 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable columns, colorIndexMap); - modeInfo.SetPaletteColorIndexMap(Av1PlaneType.Uv, colorIndexMap); + if (this.FrameDecoder is not null) + { + modeInfo.SetPaletteColorIndexMap(Av1PlaneType.Uv, colorIndexMap); + } } } @@ -3011,7 +3126,7 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable if (segmentationParameters.SegmentationUpdateMap == 0) { // The frame map was inherited as one contiguous copy during reader construction. Resolve the same clipped - // minimum that libaom obtains from last_frame_seg_map so block state and the already copied map agree. + // minimum that the reference decoder obtains from last_frame_seg_map so block state and the already copied map agree. modeInfo.SegmentId = this.FrameInfo.GetPredictedSegmentId(this.primaryReferenceFrameInfo, modeInfo.BlockSize, modeInfoPosition); return; } @@ -3118,7 +3233,7 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable if (segmentId is < 0 || segmentId > lastActiveSegmentId) { // The coded alphabet always contains eight symbols, even when the frame activates fewer segments. - // Validate the reconstructed ID at the same corruption boundary as libaom's read_segment_id. + // Validate the reconstructed ID at the same corruption boundary as the reference decoder's read_segment_id. throw new InvalidImageContentException("The decoded AV1 segment identifier exceeds the active segment range."); } @@ -3131,7 +3246,6 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable /// /// The tile symbol decoder. /// The current coding block. - /// Implements AV1 section 5.11.56 and corresponds to read_cdef in libaom. private void ReadCdef(ref Av1SymbolDecoder reader, ref Av1PartitionInfo partitionInfo) { if (partitionInfo.ModeInfo.Skip || this.FrameHeader.CodedLossless || !this.SequenceHeader.EnableCdef || this.FrameHeader.AllowIntraBlockCopy) @@ -3155,7 +3269,7 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable int lastUnitRow = (rowInSuperblock + blockHeight4 - 1) / cdefSize4; int lastUnitColumn = (columnInSuperblock + blockWidth4 - 1) / cdefSize4; - // A coding block can cover the top-left cell of more than one 64x64 CDEF unit. libaom + // A coding block can cover the top-left cell of more than one 64x64 CDEF unit. the reference decoder // stores the index on shared mode information, so the frame-owned unit map must mirror it. for (int coveredUnitRow = unitRow; coveredUnitRow <= lastUnitRow; coveredUnitRow++) { @@ -3442,7 +3556,6 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable /// /// The tile symbol decoder. /// The current coding block and superblock quantizer storage. - /// Corresponds to read_delta_qindex in libaom. private void ReadDeltaQuantizerIndex(ref Av1SymbolDecoder reader, ref Av1PartitionInfo partitionInfo) { if (!this.FrameHeader.DeltaQParameters.IsPresent || partitionInfo.ModeInfo.PositionInSuperblock != Point.Empty) @@ -3484,7 +3597,6 @@ internal sealed class Av1TileReader : IAv1TileReader, IDisposable /// The active tile boundaries. /// The containing superblock. /// The partition entropy context. - /// Corresponds to partition_plane_context in libaom. private int GetPartitionPlaneContext(Point location, Av1BlockSize blockSize, Av1TileInfo tileInfo, Av1SuperblockInfo superblockInfo) { // The five stored split bits begin at the 8x8 partition point, so normalize the block-size log to that bit index. diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileWriter.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileWriter.cs index 8d422eb60..c6e845b4d 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileWriter.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileWriter.cs @@ -62,7 +62,6 @@ internal partial class Av1TileWriter /// The encoder decisions for the superblock. /// The transformed coefficients for the frame. /// The zero-based tile index. - /// Corresponds to svt_aom_write_sb in SVT-AV1. public static void WriteSuperblock( Av1PictureControlSet pcs, Av1EntropyCodingContext ec_ctx, @@ -112,39 +111,6 @@ internal partial class Av1TileWriter if (bsize >= Av1BlockSize.Block8x8) { - for (int plane = 0; plane < 3; ++plane) - { - /* TODO: Implement - if (svt_av1_loop_restoration_corners_in_sb(cm, - scs.SequenceHeader, - plane, - mi_row, - mi_col, - bsize, - out int rcol0, - out int rcol1, - out int rrow0, - out int rrow1, - out int tile_tl_idx)) - { - int rstride = pcs.RestorationInfos[plane].HorizontalUnitCountPerTile; - for (int rrow = rrow0; rrow < rrow1; ++rrow) - { - for (int rcol = rcol0; rcol < rcol1; ++rcol) - { - int runit_idx = tile_tl_idx + rcol + (rrow * rstride); - Av1RestorationUnitInfo rui = pcs.RestorationUnitInfos[plane].UnitInfo[runit_idx]; - loop_restoration_write_sb_coeffs( - pcs, - ref writer, - tileIndex, - rui, - plane); - } - } - }*/ - } - // Blocks below 8x8 cannot be partition points in the AV1 syntax. EncodePartition( pcs, @@ -307,7 +273,6 @@ internal partial class Av1TileWriter /// The selected partition type. /// The block origin in samples. /// The partition neighbor arrays for the tile. - /// Corresponds to encode_partition_av1 in SVT-AV1. private static void EncodePartition( Av1PictureControlSet pcs, ref Av1SymbolEncoder writer, @@ -382,7 +347,6 @@ internal partial class Av1TileWriter /// The final encoder decisions for the block. /// The zero-based tile index. /// The transformed coefficients for the frame. - /// Corresponds to write_modes_b in SVT-AV1. private static void WriteModesBlock( Av1PictureControlSet pcs, Av1EntropyCodingContext entropyCodingContext, @@ -539,26 +503,6 @@ internal partial class Av1TileWriter if (palette_size_plane > 0) { throw new NotImplementedException("Tokenizing palette not implemented."); - /* - Av1TransformSize tx_size = - blockGeometry.TransformSize[macroBlockModeInfo.Block.TransformDepth]; // inherit tx_size from 1st transform block; - svt_av1_tokenize_color_map( - frame_context, - blk_ptr, - plane, - tok, - blockSize, - tx_size, - PALETTE_MAP, - 0); // NO CDF update in entropy, the update will take place in arithmetic encode - assert(macroBlockModeInfo.Block.UseIntraBlockCopy); - assert(IsPaletteAllowed(pcs.Parent.FrameHeader.AllowScreenContentTools, blockGeometry.BlockSize)); - svt_aom_get_block_dimensions(blockGeometry.BlockSize, plane, blk_ptr.MacroBlock, null, null, out int rowCount, out int columnCount); - pack_map_tokens(ref writer, ref entropyCodingContext.tok, palette_size_plane, rowCount * columnCount); - - // advance the pointer - entropyCodingContext.tok = tok; - */ } } } @@ -650,7 +594,6 @@ internal partial class Av1TileWriter /// The current macroblock and its mapped neighbors. /// The context derived from the above luma mode. /// The context derived from the left luma mode. - /// Corresponds to svt_aom_get_kf_y_mode_ctx in SVT-AV1. private static void GetYModeContext(Av1MacroBlockD xd, out byte above_ctx, out byte left_ctx) { Av1PredictionMode intraLumaLeftMode = Av1PredictionMode.DC; @@ -678,7 +621,6 @@ internal partial class Av1TileWriter /// The encoder prediction-unit state. /// The block size. /// The selected luma prediction mode. - /// Corresponds to encode_intra_luma_mode_kf_av1 in SVT-AV1. private static void EncodeIntraLumaMode( ref Av1SymbolEncoder writer, Av1MacroBlockModeInfo macroBlockModeInfo, @@ -712,32 +654,7 @@ internal partial class Av1TileWriter Av1EncoderBlockStruct blk_ptr, Av1BlockSize blockSize, Point point) - {/* - Av1PredictionMode intra_luma_mode = macroBlockModeInfo.Mode; - Av1ChromaPredictionMode intra_chroma_mode = macroBlockModeInfo.Block.UvMode; - - Av1PaletteModeInfo pmi = blk_ptr.PaletteInfo.pmi; - int bsize_ctx = svt_aom_get_palette_bsize_ctx(bsize); - Guard.MustBeGreaterThanOrEqualTo(bsize_ctx, 0, nameof(bsize_ctx)); - if (intra_luma_mode == Av1PredictionMode.DC) - { - int n = blk_ptr.PaletteSize[0]; - int palette_y_mode_ctx = svt_aom_get_palette_mode_ctx(blk_ptr->av1xd); - writer.WriteYMode(n > 0, bsize_ctx, palette_y_mode_ctx); - if (n > 0) - { - writer.WriteYSize(n - PALETTE_MIN_SIZE, bsize_ctx); - write_palette_colors_y(blk_ptr.MacroBlock, pmi, scs.StaticConfig.EncoderBitDepth, ref writer, n); - } - } - - bool uv_dc_pred = intra_chroma_mode == Av1ChromaPredictionMode.DC && is_chroma_reference(point, blockSize, 1, 1); - if (uv_dc_pred) - { - // assert(blk_ptr->palette_size[1] == 0); //remove when chroma is on - bool palette_uv_mode_ctx = blk_ptr.PaletteSize[0] > 0; - writer.WriteUvMode(false, palette_uv_mode_ctx); - }*/ + { throw new NotImplementedException("Palette mode encoding not implemented."); } @@ -749,7 +666,6 @@ internal partial class Av1TileWriter /// The selected luma palette size. /// The selected luma prediction mode. /// when the block can use filter-intra prediction; otherwise, . - /// Corresponds to svt_aom_filter_intra_allowed in SVT-AV1. private static bool IsFilterIntraAllowed( bool enableFilterIntra, Av1BlockSize blockSize, @@ -763,7 +679,6 @@ internal partial class Av1TileWriter /// A value indicating whether the sequence enables filter-intra prediction. /// The block size. /// when filter-intra prediction supports the block dimensions; otherwise, . - /// Corresponds to svt_aom_filter_intra_allowed_bsize in SVT-AV1. private static bool IsFilterIntraAllowedBlockSize(bool enableFilterIntra, Av1BlockSize blockSize) { if (!enableFilterIntra) @@ -781,7 +696,6 @@ internal partial class Av1TileWriter /// The selected block modes. /// The encoder block state. /// The displacement-vector syntax is not implemented when intra block copy is selected. - /// Corresponds to write_intrabc_info in SVT-AV1. private static void WriteIntraBlockCopyInfo( ref Av1SymbolEncoder writer, Av1MacroBlockModeInfo macroBlockModeInfo, @@ -792,14 +706,6 @@ internal partial class Av1TileWriter if (use_intrabc) { throw new NotImplementedException("Intra block code encoding not implemented."); - /* - //assert(mbmi->mode == DC_PRED); - //assert(mbmi->uv_mode == UV_DC_PRED); - //assert(mbmi->motion_mode == SIMPLE_TRANSLATION); - IntMv dv_ref = block->predmv[0]; // mbmi_ext->ref_mv_stack[INTRA_FRAME][0].this_mv; - MV mv; - mv = macroBlockModeInfo.Block.mv[INTRA_FRAME].as_mv; - svt_av1_encode_dv(w, &mv, &dv_ref.as_mv, &ec_ctx->ndvc);*/ } } @@ -808,7 +714,6 @@ internal partial class Av1TileWriter /// /// The current frame header. /// when both screen-content tools and intra block copy are enabled; otherwise, . - /// Corresponds to svt_aom_allow_intrabc in SVT-AV1. private static bool IsIntraBlockCopyAllowed(ObuFrameHeader frameHeader) => frameHeader.AllowScreenContentTools && frameHeader.AllowIntraBlockCopy; @@ -821,7 +726,6 @@ internal partial class Av1TileWriter /// The encoder block state. /// The zero-based tile index. /// The block size. - /// Corresponds to ec_update_neighbors in SVT-AV1. private static void UpdateNeighbors( Av1PictureControlSet pcs, Av1EntropyCodingContext entropyCodingContext, @@ -887,7 +791,6 @@ internal partial class Av1TileWriter /// The nonzero encoder palette level. /// The block size. /// when palette mode is enabled for the block; otherwise, . - /// Corresponds to svt_av1_allow_palette in SVT-AV1. private static bool IsPaletteAllowed(int allowPalette, Av1BlockSize blockSize) { Guard.MustBeLessThan((int)blockSize, (int)Av1BlockSize.AllSizes, nameof(blockSize)); @@ -903,7 +806,6 @@ internal partial class Av1TileWriter /// A value indicating whether screen-content tools are enabled. /// The block size. /// when palette mode is available for the block; otherwise, . - /// Corresponds to svt_aom_allow_palette in SVT-AV1. private static bool IsPaletteAllowed(bool allowScreenContentTools, Av1BlockSize blockSize) => allowScreenContentTools && blockSize.GetWidth() <= 64 && @@ -919,7 +821,6 @@ internal partial class Av1TileWriter /// The zero-based tile index. /// A value indicating whether the current block omits residual coefficients. /// The block position in 4x4 mode-information units. - /// Corresponds to write_cdef in SVT-AV1. private static void WriteCdef( Av1SequenceControlSet scs, Av1PictureControlSet pcs, @@ -978,7 +879,6 @@ internal partial class Av1TileWriter /// The row stride of the mode-information grid. /// The coded frame height in mode-information rows. /// The coded frame width in mode-information columns. - /// Corresponds to set_mi_row_col in SVT-AV1. private static void SetModeInfoRowAndColumn( Av1PictureControlSet pcs, Av1MacroBlockD macroBlock, @@ -1056,7 +956,6 @@ internal partial class Av1TileWriter /// The red-difference chroma coefficient neighbor contexts. /// The blue-difference chroma coefficient neighbor contexts. /// The transform-depth path required by the block is not implemented. - /// Corresponds to av1_encode_coeff_1d in SVT-AV1. private static void EncodeCoefficients1d( Av1PictureControlSet pcs, Av1EntropyCodingContext ec_ctx, @@ -1117,7 +1016,6 @@ internal partial class Av1TileWriter /// The luma block size. /// The transformed coefficients for the frame. /// The luma coefficient neighbor contexts. - /// Corresponds to av1_encode_tx_coef_y in SVT-AV1. public static void EncodeTransformCoefficientsY( Av1PictureControlSet pcs, Av1EntropyCodingContext entropyCodingContext, @@ -1207,7 +1105,6 @@ internal partial class Av1TileWriter /// The transformed coefficients for the frame. /// The red-difference chroma coefficient neighbor contexts. /// The blue-difference chroma coefficient neighbor contexts. - /// Corresponds to av1_encode_tx_coef_uv in SVT-AV1. private static void EncodeTransformCoefficientsUv( Av1PictureControlSet pcs, Av1EntropyCodingContext entropyCodingContext, @@ -1328,7 +1225,6 @@ internal partial class Av1TileWriter /// The containing block size on the target plane. /// The transform size. /// The context object to populate. - /// Corresponds to svt_aom_get_txb_ctx in SVT-AV1. private static void GetTransformBlockContexts( Av1PictureControlSet pcs, Av1ComponentType plane, @@ -1514,7 +1410,6 @@ internal partial class Av1TileWriter /// The block origin in samples. /// The entropy context selected by matching neighbor identifiers. /// The spatially predicted segment identifier. - /// Corresponds to svt_av1_get_spatial_seg_prediction in SVT-AV1. private static int GetSpatialSegmentationPrediction( Av1PictureControlSet pcs, Av1MacroBlockD xd, diff --git a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1BlockDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1BlockDecoder.cs index ba3f2ab66..4f46ac8c5 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1BlockDecoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1BlockDecoder.cs @@ -364,7 +364,7 @@ internal sealed class Av1BlockDecoder : IDisposable int referenceCount = usesSub8x8ChromaPrediction ? 0 : isCompound ? 2 : 1; // Every compound predictor is combined before its final rounding step. Warped prediction has its own - // convolution kernels, but current libaom writes their output into the same unsigned no-round domain. + // convolution kernels, but the reference decoder writes their output into the same unsigned no-round domain. bool useHighBitDepthCompoundIntermediates = highBitDepth && modeInfo.CompoundType is ( @@ -391,7 +391,7 @@ internal sealed class Av1BlockDecoder : IDisposable activeReferenceFrameBuffer.Height != this.frameHeader.FrameSize.FrameHeight; // Warped prediction is selected per plane. In subsampled frames an otherwise qualifying 8x8 luma - // block has a 4x4 chroma prediction, which libaom deliberately reconstructs with the translational + // block has a 4x4 chroma prediction, which the reference decoder deliberately reconstructs with the translational // center motion vector. Scaled references and integer-only frames exclude both local and global warp. bool canUseWarpedPrediction = !isScaledReference && @@ -594,7 +594,7 @@ internal sealed class Av1BlockDecoder : IDisposable } // AV1 predicts the complete declared plane block even when its luma extent crosses the frame boundary. - // Subsampled dimensions retain the mandatory four-sample minimum used by set_plane_n4 in libaom. + // Subsampled dimensions retain the mandatory four-sample minimum used by set_plane_n4 in the reference decoder. int horizontalMotionQ4 = motionVector.Column << (1 - subX); int verticalMotionQ4 = motionVector.Row << (1 - subY); int horizontalExtensionQ4 = (4 + predictionWidth) << 4; @@ -773,7 +773,7 @@ internal sealed class Av1BlockDecoder : IDisposable subY, invert: false); - // Masked compound prediction must blend the same no-round intermediates as libaom's + // Masked compound prediction must blend the same no-round intermediates as the reference decoder's // high-bit-depth d16 path so the mask is applied before the sole final rounding step. Av1CompoundIntermediateMaskBlendPredictor.BlendIntermediate( highBitDepthDestination, @@ -1240,7 +1240,7 @@ internal sealed class Av1BlockDecoder : IDisposable // rules. Its validated displacement always references an earlier reconstructed region of this frame. if (modeInfo.UseIntraBlockCopy) { - // libaom predicts the complete coding block before traversing its residual transforms. The mandatory + // the reference decoder predicts the complete coding block before traversing its residual transforms. The mandatory // 256-pixel source delay prevents overlap, and the two-tap interpolation is translation-invariant, // so predicting the matching source rectangle for each transform unit produces the same samples. Point transformPixelPosition = new( @@ -1452,7 +1452,7 @@ internal sealed class Av1BlockDecoder : IDisposable int rowStart = isSub4Y ? -1 : 0; int columnStart = isSub4X ? -1 : 0; - // One chroma block can cover two or four independently decoded luma blocks. libaom enters this path only + // One chroma block can cover two or four independently decoded luma blocks. the reference decoder enters this path only // when every contributing owner is a conventional inter block; otherwise the current block supplies the // complete chroma prediction through the ordinary path. for (int row = rowStart; row <= 0; row++) @@ -1534,7 +1534,7 @@ internal sealed class Av1BlockDecoder : IDisposable // The block-relative UMV edges belong to the current coding block, while each contributing luma // owner supplies only its motion vector and interpolation filters. This is the same split used by - // libaom's sub-8x8 chroma builder. + // the reference decoder's sub-8x8 chroma builder. horizontalMotionQ4 = Av1Math.Clip3( (partitionInfo.ModeBlockToLeftEdge * horizontalEdgeScale) - horizontalExtensionQ4, (partitionInfo.ModeBlockToRightEdge * horizontalEdgeScale) + horizontalExtensionQ4 - 16, @@ -1830,7 +1830,7 @@ internal sealed class Av1BlockDecoder : IDisposable int step = Math.Min(candidate.BlockSize.Get4x4WideCount(), Av1BlockSize.Block64x64.Get4x4WideCount()); if (step == 1) { - // A four-sample neighbor is one half of the chroma-bearing eight-sample pair. libaom aligns + // A four-sample neighbor is one half of the chroma-bearing eight-sample pair. the reference decoder aligns // the traversal to the pair start and reads prediction state from its second mode record. aboveColumn &= ~1; candidate = partitionInfo.SuperblockInfo.GetModeInfoAt(new Point(aboveColumn + 1, blockRow - 1)); @@ -2034,7 +2034,7 @@ internal sealed class Av1BlockDecoder : IDisposable int framePlaneWidth = (this.frameHeader.ModeInfoColumnCount << Av1Constants.ModeInfoSizeLog2) >> subX; int framePlaneHeight = (this.frameHeader.ModeInfoRowCount << Av1Constants.ModeInfoSizeLog2) >> subY; - // libaom clamps the motion vector relative to each neighbor rectangle. Once the neighbor origin is added, the + // the reference decoder clamps the motion vector relative to each neighbor rectangle. Once the neighbor origin is added, the // prediction extent remains in the left/top limit but cancels from the right/bottom limit. Keeping this // asymmetry avoids counting the OBMC rectangle twice when the source lies beyond the far frame edge. sourceColumnQ4 = Av1Math.Clip3( diff --git a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1ForwardTransformer.cs b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1ForwardTransformer.cs index 3aaa2a358..d5f01327a 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1ForwardTransformer.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1ForwardTransformer.cs @@ -189,7 +189,7 @@ internal static partial class Av1ForwardTransformer where TRowOperator : struct, IAv1ForwardTransform1dOperator { // Highway keeps eight-bit transform stages in Int16 lanes and promotes only the large rectangular layouts. - // Scalar libaom uses Int32, so hardware without packed Int16 support follows that exact fallback instead. + // The independent scalar reference uses Int32, so hardware without packed Int16 support follows that exact fallback instead. if (bitDepth == 8 && Vector128.IsHardwareAccelerated) { TransformPacked(input, coefficients, stride, ref config, workspace); @@ -200,7 +200,7 @@ internal static partial class Av1ForwardTransformer } /// - /// Applies the libaom Int16 stage pipeline used for eight-bit residuals. + /// Applies the signed Int16 stage pipeline used for eight-bit residuals. /// /// The column transform operator. /// The row transform operator. @@ -298,7 +298,7 @@ internal static partial class Av1ForwardTransformer TransformPackedAxis(buffer1Packed, height, blockHeight, blockHeight, config.CosBitRow, workspace); // The second transform produces horizontal frequency in rows and vertical frequency in lanes. Transposing - // once more adapts libaom's native layout to the row-major coefficient contract used by ImageSharp. + // once more adapts the reference decoder's native layout to the row-major coefficient contract used by ImageSharp. TransposePacked( ref buffer1PackedBase, blockHeight, @@ -314,7 +314,7 @@ internal static partial class Av1ForwardTransformer } /// - /// Applies the libaom Int32 stage pipeline used for high-bit-depth residuals and scalar fallback. + /// Applies the signed Int32 stage pipeline used for high-bit-depth residuals and scalar fallback. /// /// The column transform operator. /// The row transform operator. @@ -881,7 +881,7 @@ internal static partial class Av1ForwardTransformer } /// - /// Promotes and transposes the large packed layouts at the same axis boundary as libaom. + /// Promotes and transposes the large packed layouts at the same axis boundary as the reference decoder. /// /// The first packed value in the source block. /// The number of packed values between source rows. diff --git a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseWalshHadamardTransformer.cs b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseWalshHadamardTransformer.cs index afe4c7ef9..80f173b32 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseWalshHadamardTransformer.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseWalshHadamardTransformer.cs @@ -206,7 +206,7 @@ internal static class Av1InverseWalshHadamardTransformer ref int intermediateBase = ref MemoryMarshal.GetReference(workspace); // Entropy decoding stores the transposed scan in row-major order, so each contiguous local row is one - // normative transform column. Writing those results down the intermediate columns preserves libaom's + // normative transform column. Writing those results down the intermediate columns preserves the reference decoder's // dimension order without a separate transpose or per-block allocation. for (int row = 0; row < 4; row++) { diff --git a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1Transform1dMath.cs b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1Transform1dMath.cs index 700c8956b..1a97c68e8 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1Transform1dMath.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1Transform1dMath.cs @@ -132,7 +132,7 @@ internal static class Av1Transform1dMath out Vector512 sum, out Vector512 difference) { - // Read both operands before either destination is written because libaom deliberately permits an input + // Read both operands before either destination is written because the reference decoder deliberately permits an input // buffer to alias one or both outputs while alternating between its two fixed transform-stage buffers. Vector512 left = input0; Vector512 right = input1; @@ -164,7 +164,7 @@ internal static class Av1Transform1dMath in Vector512 rounding) { // VPMADDWD evaluates adjacent Int16 products into Int32 lanes. Both outputs reuse the same interleaved - // inputs, matching libaom's whole butterfly instead of loading and unpacking each input pair twice. + // inputs, matching the reference decoder's whole butterfly instead of loading and unpacking each input pair twice. Vector512 left = input0; Vector512 right = input1; Vector512 interleavedLower = Avx512BW.UnpackLow(left, right); @@ -414,7 +414,7 @@ internal static class Av1Transform1dMath (Vector128 lower, Vector128 upper) = Vector128.Widen(value); Vector128 rounding = Vector128.Create(1L << (fractionalBits - 1)); - // Pinned libaom's high-bit-depth identity kernels multiply in signed 64-bit lanes. Widen before both the + // The reference decoder's high-bit-depth identity kernels multiply in signed 64-bit lanes. Widen before both the // product and rounding addition so a valid 20-bit twelve-bit row value cannot wrap through Int32. lower = ((lower * multiplier) + rounding) >> fractionalBits; upper = ((upper * multiplier) + rounding) >> fractionalBits; @@ -573,7 +573,7 @@ internal static class Av1Transform1dMath Vector128 input3, int fractionalBits) { - // libaom keeps conformant ADST4 sine products and their factorized sums in Int32, then widens the terminal + // the reference decoder keeps conformant ADST4 sine products and their factorized sums in Int32, then widens the terminal // scaling and rounding. Preserve that exact boundary instead of widening every transform multiplication. Vector128 weightedSum = (input0 * weight0) + (input1 * weight1) + (input2 * weight2) + (input3 * weight3); return MultiplyRoundWidened(weightedSum, 1, fractionalBits); diff --git a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1Transform2dOperations.cs b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1Transform2dOperations.cs index 91717a67f..5aa89f780 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1Transform2dOperations.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1Transform2dOperations.cs @@ -144,7 +144,7 @@ internal static class Av1Transform2dOperations if (bit > 0) { // Conformant low-bit-depth stage ranges leave room for the rounding bias, so this intentionally uses the - // wrapping add used by libaom rather than changing the normative result with a saturating instruction. + // wrapping add used by the reference decoder rather than changing the normative result with a saturating instruction. return (value + Vector256.Create((short)(1 << (bit - 1)))) >> bit; } @@ -382,7 +382,7 @@ internal static class Av1Transform2dOperations } // Once promoted, the same bounded transpose used by the high-bit-depth AVX-512 path supplies the exact - // libaom staging order and performs the axis-boundary shift in signed thirty-two-bit lanes. + // the reference decoder staging order and performs the axis-boundary shift in signed thirty-two-bit lanes. Transpose16x16Avx512( ref promotionBase, 16, @@ -415,7 +415,7 @@ internal static class Av1Transform2dOperations ref int promotionBase = ref MemoryMarshal.GetReference(promotionBuffer); // AVX2 processes eight Int32 transform axes at a time. Widening each packed row before the axis shift follows - // libaom's Repartition boundary and prevents valid Int32 intermediates from wrapping in Int16. + // the reference decoder's Repartition boundary and prevents valid Int32 intermediates from wrapping in Int16. for (int row = 0; row < 8; row++) { Vector128 packed = Vector128.LoadUnsafe(ref source, (nuint)(row * sourceStride)); @@ -663,7 +663,7 @@ internal static class Av1Transform2dOperations } /// - /// Transposes a sixteen-by-sixteen matrix of signed thirty-two-bit values with the libaom AVX-512 staging layout. + /// Transposes a sixteen-by-sixteen matrix of signed thirty-two-bit values with the AVX-512 staging layout. /// /// The first value in the source matrix. /// The number of values between source rows. @@ -683,7 +683,7 @@ internal static class Av1Transform2dOperations { ref long scratchBase = ref MemoryMarshal.GetReference(scratch); - // libaom widens the lane grouping after each local interleave rather than retaining all sixteen rows in + // the reference decoder widens the lane grouping after each local interleave rather than retaining all sixteen rows in // registers. The bounded scratch keeps the live register set small and prevents the JIT from spilling a // four-stage, sixteen-register cross-vector permutation network into its own stack frame. for (int row = 0; row < 16; row += 2) @@ -733,7 +733,7 @@ internal static class Av1Transform2dOperations } // The final 128-bit-block concatenations complete the transpose. The store order is the fixed permutation - // produced by libaom's three preceding local-interleave stages. + // produced by the reference decoder's three preceding local-interleave stages. for (int row = 0; row < 8; row++) { Vector512 lower = Vector512.LoadUnsafe(ref scratchBase, (nuint)(row * 8)); @@ -996,7 +996,7 @@ internal static class Av1Transform2dOperations } /// - /// Applies the terminal operations which libaom performs before transposing a signed sixteen-bit tile. + /// Applies the terminal operations which the reference decoder performs before transposing a signed sixteen-bit tile. /// /// The packed transform values. /// The signed AV1 pipeline shift. @@ -1015,7 +1015,7 @@ internal static class Av1Transform2dOperations } /// - /// Applies the terminal operations which libaom performs before transposing four signed thirty-two-bit lanes. + /// Applies the terminal operations which the reference decoder performs before transposing four signed thirty-two-bit lanes. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector128 Finish(Vector128 value, int roundShift, bool normalizeRectangle) @@ -1027,7 +1027,7 @@ internal static class Av1Transform2dOperations } /// - /// Applies the terminal operations which libaom performs before transposing eight signed thirty-two-bit lanes. + /// Applies the terminal operations which the reference decoder performs before transposing eight signed thirty-two-bit lanes. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector256 Finish(Vector256 value, int roundShift, bool normalizeRectangle) diff --git a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1TransformWorkspace.cs b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1TransformWorkspace.cs index f07fb8e9a..76e703342 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1TransformWorkspace.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1TransformWorkspace.cs @@ -21,7 +21,7 @@ internal static class Av1TransformWorkspace public const int Vector512StorageLength = 3 * Av1Constants.MaxTransformSize * 16; /// - /// The number of integer elements occupied by the libaom-shaped AVX-512 transpose scratch. + /// The number of integer elements occupied by the AVX-512 transpose scratch. /// public const int Vector512TransposeStorageLength = 16 * 8 * 2; diff --git a/src/ImageSharp/Formats/Heif/Av1/Transform/Inverse/Av1Inverse2dTransformer.Adst4Operator.cs b/src/ImageSharp/Formats/Heif/Av1/Transform/Inverse/Av1Inverse2dTransformer.Adst4Operator.cs index 89f890230..ed04c36b2 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Transform/Inverse/Av1Inverse2dTransformer.Adst4Operator.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Transform/Inverse/Av1Inverse2dTransformer.Adst4Operator.cs @@ -28,7 +28,7 @@ internal static partial class Av1Inverse2dTransformer { ReadOnlySpan sinpi = Av1SinusConstants.SinusPi(cosBit); - // libaom widens the complete four-point factorization because the products retain their fixed-point scale + // the reference decoder widens the complete four-point factorization because the products retain their fixed-point scale // until the final shift. The stage buffer is therefore unnecessary for this transform size. long x0 = input[0]; long x1 = input[1]; @@ -38,7 +38,7 @@ internal static partial class Av1Inverse2dTransformer _ = step; _ = stageRange; - // Avoid the multiplications for the all-zero coefficient vector, matching libaom's scalar kernel. + // Avoid the multiplications for the all-zero coefficient vector, matching the reference decoder's scalar kernel. if ((x0 | x1 | x2 | x3) == 0) { output[..4].Clear(); @@ -89,7 +89,7 @@ internal static partial class Av1Inverse2dTransformer Vector128 x2 = input.V2; Vector128 x3 = input.V3; - // Pinned libaom retains the sine-table scale in Int32 products and sums, but performs the twelve-bit row + // The reference decoder retains the sine-table scale in Int32 products and sums, but performs the twelve-bit row // kernel's terminal scaling and rounding in Int64. This is the only stage whose rounding bias can overflow // a valid Int32 fixed-point sum. if (widenedRound) diff --git a/src/ImageSharp/Formats/Heif/Av1/Transform/Inverse/Av1Inverse2dTransformer.Identity16Operator.cs b/src/ImageSharp/Formats/Heif/Av1/Transform/Inverse/Av1Inverse2dTransformer.Identity16Operator.cs index 3a06a5814..e9c435d9c 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Transform/Inverse/Av1Inverse2dTransformer.Identity16Operator.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Transform/Inverse/Av1Inverse2dTransformer.Identity16Operator.cs @@ -46,7 +46,7 @@ internal static partial class Av1Inverse2dTransformer Av1TransformStageRange stageRange) { // The doubled scale exceeds Int32 only for the 20-bit twelve-bit row range. Widen that exact product and - // rounding sequence, matching libaom without changing the established lower-range SIMD path. + // rounding sequence, matching the reference decoder without changing the established lower-range SIMD path. if (stageRange[0] >= Av1Transform1dMath.WidenedIntermediateBitCount) { Av1IdentityTransform1d.TransformWidened(ref input, ref output, 16, 2 * Av1Transform1dMath.NewSqrt2, Av1Transform1dMath.NewSqrt2Bits); diff --git a/src/ImageSharp/Formats/Heif/Av1/Transform/Inverse/Av1Inverse2dTransformer.Identity4Operator.cs b/src/ImageSharp/Formats/Heif/Av1/Transform/Inverse/Av1Inverse2dTransformer.Identity4Operator.cs index 035d29d4e..f95246628 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Transform/Inverse/Av1Inverse2dTransformer.Identity4Operator.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Transform/Inverse/Av1Inverse2dTransformer.Identity4Operator.cs @@ -46,7 +46,7 @@ internal static partial class Av1Inverse2dTransformer Av1TransformStageRange stageRange) { // Only a twelve-bit row transform has the 20-bit input range that can overflow this fixed-point product. - // Match libaom's high-bit-depth kernel there while retaining the compact Int32 path for narrower ranges. + // Match the reference decoder's high-bit-depth kernel there while retaining the compact Int32 path for narrower ranges. if (stageRange[0] >= Av1Transform1dMath.WidenedIntermediateBitCount) { Av1IdentityTransform1d.TransformWidened(ref input, ref output, 4, Av1Transform1dMath.NewSqrt2, Av1Transform1dMath.NewSqrt2Bits); diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CdefFilterTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CdefFilterTests.cs index 4a221f52b..46b69f955 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CdefFilterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CdefFilterTests.cs @@ -32,21 +32,21 @@ public class Av1CdefFilterTests /// Verifies direction selection and variance against an independent scalar definition. /// [Fact] - public void FindDirectionMatchesIndependentDefinitionAcrossIntrinsicTiers() + public void FindDirectionMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateDirections, Configurations); /// /// Verifies every CDEF block geometry and strength mode against an independent scalar definition. /// [Fact] - public void FilterBlockMatchesIndependentDefinitionAcrossIntrinsicTiers() + public void FilterBlockMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateFilters, Configurations); /// /// Verifies eight-bit widening and 16-bit copying across packed and scalar execution tiers. /// [Fact] - public void CopyPlaneMatchesIndependentDefinitionAcrossIntrinsicTiers() + public void CopyPlaneMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidatePlaneCopies, Configurations); /// diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ChromaFromLumaTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ChromaFromLumaTests.cs index 8cb84fa5c..5fef02ca0 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ChromaFromLumaTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ChromaFromLumaTests.cs @@ -31,7 +31,7 @@ public class Av1ChromaFromLumaTests [InlineData(false, false, new short[] { 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128 })] [InlineData(true, false, new short[] { 12, 28, 44, 60, 76, 92, 108, 124 })] [InlineData(true, true, new short[] { 28, 44, 92, 108 })] - public void Store8BitMatchesLibaomSubsampling(bool subX, bool subY, short[] expected) + public void Store8BitMatchesReference(bool subX, bool subY, short[] expected) { ObuColorConfig colorConfig = new() { SubSamplingX = subX, SubSamplingY = subY }; Av1ChromaFromLumaContext context = new(colorConfig); @@ -144,14 +144,14 @@ public class Av1ChromaFromLumaTests /// Verifies exact 8-, 10-, and 12-bit CfL output and padding preservation across all intrinsic tiers. /// [Fact] - public void PredictMatchesIndependentDefinitionAcrossIntrinsicWidths() + public void PredictMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidatePredictors, PredictorConfigurations); /// /// Verifies exact luma subsampling and average subtraction across all intrinsic tiers. /// [Fact] - public void ContextOperationsMatchIndependentDefinitionAcrossIntrinsicWidths() + public void ContextOperationsMatchReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateContextOperations, PredictorConfigurations); /// diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CompoundBlockDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CompoundBlockDecoderTests.cs index 80108b1d1..17032bbc7 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CompoundBlockDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CompoundBlockDecoderTests.cs @@ -40,7 +40,7 @@ public class Av1CompoundBlockDecoderTests [InlineData((int)Av1BitDepth.EightBit)] [InlineData((int)Av1BitDepth.TenBit)] [InlineData((int)Av1BitDepth.TwelveBit)] - public void DecodeBlockReconstructsEqualAverageCompoundPrediction(int bitDepthValue) + public void DecodeBlockWithAverageCompound(int bitDepthValue) { Av1BitDepth bitDepth = (Av1BitDepth)bitDepthValue; ushort firstValue = bitDepth == Av1BitDepth.EightBit ? (ushort)20 : (ushort)100; @@ -127,7 +127,7 @@ public class Av1CompoundBlockDecoderTests /// Verifies that high-bit-depth subpixel predictors retain their no-round precision until the compound average. /// [Fact] - public void DecodeBlockReconstructsSubpixelHighBitDepthEqualAverageCompoundPrediction() + public void DecodeBlockWithHighBitDepthAverageCompound() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateSubpixelHighBitDepthEqualAverageCompoundPrediction, CompoundPredictionConfigurations); @@ -136,7 +136,7 @@ public class Av1CompoundBlockDecoderTests /// Verifies that high-bit-depth subpixel predictors retain no-round precision until distance weighting. /// [Fact] - public void DecodeBlockReconstructsSubpixelHighBitDepthDistanceWeightedCompoundPrediction() + public void DecodeBlockWithHighBitDepthDistanceWeightedCompound() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateSubpixelHighBitDepthDistanceWeightedCompoundPrediction, CompoundPredictionConfigurations); @@ -145,7 +145,7 @@ public class Av1CompoundBlockDecoderTests /// Verifies that high-bit-depth subpixel predictors retain no-round precision until wedge blending. /// [Fact] - public void DecodeBlockReconstructsSubpixelHighBitDepthWedgeCompoundPrediction() + public void DecodeBlockWithHighBitDepthWedgeCompound() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateSubpixelHighBitDepthWedgeCompoundPrediction, CompoundPredictionConfigurations); @@ -154,7 +154,7 @@ public class Av1CompoundBlockDecoderTests /// Verifies that high-bit-depth subpixel predictors retain no-round precision through difference masking and blending. /// [Fact] - public void DecodeBlockReconstructsSubpixelHighBitDepthDifferenceWeightedCompoundPrediction() + public void DecodeBlockWithHighBitDepthDifferenceWeightedCompound() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateSubpixelHighBitDepthDifferenceWeightedCompoundPrediction, CompoundPredictionConfigurations); @@ -163,7 +163,7 @@ public class Av1CompoundBlockDecoderTests /// Verifies that both references of a GLOBAL_GLOBALMV block use their complete matrix before compound averaging. /// [Fact] - public void DecodeBlockReconstructsCompoundGlobalWarpPrediction() + public void DecodeBlockWithCompoundGlobalWarp() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateCompoundGlobalWarpPrediction, GlobalWarpConfigurations); @@ -176,7 +176,7 @@ public class Av1CompoundBlockDecoderTests [InlineData((int)Av1BitDepth.EightBit)] [InlineData((int)Av1BitDepth.TenBit)] [InlineData((int)Av1BitDepth.TwelveBit)] - public void DecodeBlockReconstructsScaledSingleReferencePrediction(int bitDepthValue) + public void DecodeBlockWithScaledReference(int bitDepthValue) { Av1BitDepth bitDepth = (Av1BitDepth)bitDepthValue; ObuSequenceHeader sequenceHeader = CreateSequenceHeader(bitDepth, 16); @@ -243,7 +243,7 @@ public class Av1CompoundBlockDecoderTests /// Verifies that scaled predictors retain their no-round precision until compound averaging. /// [Fact] - public void DecodeBlockReconstructsScaledCompoundPrediction() + public void DecodeBlockWithScaledCompound() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateScaledCompoundPrediction, CompoundPredictionConfigurations); @@ -263,7 +263,7 @@ public class Av1CompoundBlockDecoderTests [InlineData((int)Av1BitDepth.EightBit, (int)Av1CompoundType.DifferenceWeighted)] [InlineData((int)Av1BitDepth.TenBit, (int)Av1CompoundType.DifferenceWeighted)] [InlineData((int)Av1BitDepth.TwelveBit, (int)Av1CompoundType.DifferenceWeighted)] - public void DecodeBlockReconstructsSelectableCompoundPrediction(int bitDepthValue, int compoundTypeValue) + public void DecodeBlockWithSelectableCompound(int bitDepthValue, int compoundTypeValue) { Av1BitDepth bitDepth = (Av1BitDepth)bitDepthValue; Av1CompoundType compoundType = (Av1CompoundType)compoundTypeValue; @@ -381,7 +381,7 @@ public class Av1CompoundBlockDecoderTests [InlineData((int)Av1BitDepth.EightBit)] [InlineData((int)Av1BitDepth.TenBit)] [InlineData((int)Av1BitDepth.TwelveBit)] - public void DecodeBlockReconstructsSmoothInterIntraPrediction(int bitDepthValue) + public void DecodeBlockWithSmoothInterIntra(int bitDepthValue) { Av1BitDepth bitDepth = (Av1BitDepth)bitDepthValue; ushort interValue = bitDepth == Av1BitDepth.EightBit ? (ushort)20 : (ushort)100; @@ -464,7 +464,7 @@ public class Av1CompoundBlockDecoderTests [InlineData((int)Av1BitDepth.EightBit)] [InlineData((int)Av1BitDepth.TenBit)] [InlineData((int)Av1BitDepth.TwelveBit)] - public void DecodeBlockReconstructsOverlappedMotionCompensation(int bitDepthValue) + public void DecodeBlockWithObmc(int bitDepthValue) { const int frameSize = 24; const int blockOrigin = 8; @@ -556,7 +556,7 @@ public class Av1CompoundBlockDecoderTests [Theory] [InlineData((int)Av1ColorFormat.Yuv420)] [InlineData((int)Av1ColorFormat.Yuv422)] - public void DecodeBlockReconstructsSubsampledOverlappedMotionCompensation(int colorFormatValue) + public void DecodeBlockWithSubsampledObmc(int colorFormatValue) { const int frameSize = 48; const int blockOrigin = 16; @@ -1475,7 +1475,7 @@ public class Av1CompoundBlockDecoderTests { int predictionIndex = (row * blockSize) + column; - // Libaom truncates the equal average before removing the compound bias, then performs the sole final + // The reference decoder truncates the equal average before removing the compound bias, then performs the sole final // rounding step. Reconstructing each reference to native pixels first can differ from this result. int intermediate = ((firstHighBitDepthPrediction[predictionIndex] + secondHighBitDepthPrediction[predictionIndex]) >> 1) - compoundRoundOffset; diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CompoundInterPredictorTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CompoundInterPredictorTests.cs index 8990a73da..7a4178b22 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CompoundInterPredictorTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CompoundInterPredictorTests.cs @@ -24,27 +24,27 @@ public class Av1CompoundInterPredictorTests /// Verifies rounded 8-bit averaging, scalar tails, and untouched row padding under every SIMD configuration. /// [Fact] - public void ByteAverageMatchesIndependentOracleAcrossIntrinsicWidths() + public void ByteAverageMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateByteAverage, PredictorConfigurations); /// /// Verifies rounded 10/12-bit averaging, scalar tails, and untouched row padding under every SIMD configuration. /// [Fact] - public void HighBitDepthAverageMatchesIndependentOracleAcrossIntrinsicWidths() + public void HighBitDepthAverageMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateHighBitDepthAverage, PredictorConfigurations); /// /// Verifies 10/12-bit no-round prediction and compound finalization across every intrinsic width. /// [Fact] - public void HighBitDepthCompoundIntermediatesMatchIndependentOracleAcrossIntrinsicWidths() + public void HighBitDepthIntermediatesMatchReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateHighBitDepthCompoundIntermediates, PredictorConfigurations); /// - /// Verifies every current libaom display-distance quantization class in both temporal directions. + /// Verifies every display-distance quantization class in both temporal directions. /// /// The first reference order hint. /// The second reference order hint. @@ -61,7 +61,7 @@ public class Av1CompoundInterPredictorTests [InlineData(12, 17, 3, 13)] [InlineData(12, 16, 3, 13)] [InlineData(16, 20, 13, 3)] - public void DistanceWeightsMatchCurrentLibaomQuantization( + public void DistanceWeightsMatchReference( int firstOrderHint, int secondOrderHint, int expectedFirstWeight, @@ -95,21 +95,21 @@ public class Av1CompoundInterPredictorTests /// Verifies 8-bit distance and per-sample mask blending across every intrinsic width and scalar tail. /// [Fact] - public void ByteSelectableBlendsMatchIndependentOracleAcrossIntrinsicWidths() + public void ByteSelectableBlendsMatchReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateByteSelectableBlends, PredictorConfigurations); /// /// Verifies 10/12-bit distance and per-sample mask blending across every intrinsic width and scalar tail. /// [Fact] - public void HighBitDepthSelectableBlendsMatchIndependentOracleAcrossIntrinsicWidths() + public void HighBitDepthSelectableBlendsMatchReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateHighBitDepthSelectableBlends, PredictorConfigurations); /// /// Verifies the four smooth inter-intra modes and their complemented destination orientation. /// [Fact] - public void SmoothInterIntraMasksMatchCurrentLibaomWeights() + public void SmoothInterIntraMasksMatchReference() { ReadOnlySpan weights = [60, 34, 19, 11, 6, 4, 2, 1]; @@ -152,10 +152,10 @@ public class Av1CompoundInterPredictorTests } /// - /// Verifies the current libaom horizontal curve at the index exercised by a 32-by-16 inter-intra block. + /// Verifies the reference horizontal curve at the index exercised by a 32-by-16 inter-intra block. /// [Fact] - public void HorizontalInterIntraMaskMatchesCurrentLibaomThirtyTwoWideCurve() + public void HorizontalInterIntraMaskMatchesReference() { const int width = 32; const int height = 16; @@ -170,14 +170,14 @@ public class Av1CompoundInterPredictorTests } /// - /// Verifies the current libaom difference-mask formula in both orientations at each supported bit depth. + /// Verifies the reference difference-mask formula in both orientations at each supported bit depth. /// [Fact] - public void DifferenceWeightedMasksMatchCurrentLibaomFormula() + public void DifferenceWeightedMasksMatchReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateDifferenceWeightedMasks, PredictorConfigurations); /// - /// Applies the current libaom difference-mask formula at every bit depth and intrinsic width. + /// Applies the independent difference-mask formula at every bit depth and intrinsic width. /// private static void ValidateDifferenceWeightedMasks() { diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CompoundReferenceEntropyTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CompoundReferenceEntropyTests.cs index 0d10804f2..0a69afe44 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CompoundReferenceEntropyTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1CompoundReferenceEntropyTests.cs @@ -10,16 +10,16 @@ using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; /// -/// Verifies AV1 compound-reference selection and compound inter-mode entropy against current official libaom main. +/// Verifies AV1 compound-reference selection and compound inter-mode entropy against the current AV1 reference. /// [Trait("Format", "Avif")] public class Av1CompoundReferenceEntropyTests { /// - /// Verifies every binary compound-reference default against libaom's forward Q15 tables. + /// Verifies every binary compound-reference default against the reference decoder's forward Q15 tables. /// [Fact] - public void CompoundReferenceDefaultsMatchLibaom() + public void CompoundReferenceDefaultsMatchReference() { AssertBinaryDefaults( [1198, 2070, 9166, 7499, 22475], @@ -51,10 +51,10 @@ public class Av1CompoundReferenceEntropyTests } /// - /// Verifies all eight compound inter-mode defaults against libaom's forward Q15 tables. + /// Verifies all eight compound inter-mode defaults against the reference decoder's forward Q15 tables. /// [Fact] - public void InterCompoundModeDefaultsMatchLibaom() + public void InterCompoundModeDefaultsMatchReference() { uint[][] expected = [ @@ -151,7 +151,7 @@ public class Av1CompoundReferenceEntropyTests /// Verifies the compound-reference type context across intra, single, bidirectional, and unidirectional neighbors. /// [Fact] - public void CompoundReferenceTypeContextMatchesLibaom() + public void CompoundReferenceTypeContextMatchesReference() { Av1BlockModeInfo intra = CreateModeInfo(Av1ReferenceFrameType.Intra, Av1ReferenceFrameType.None); Av1BlockModeInfo singleForward = CreateModeInfo(Av1ReferenceFrameType.Last, Av1ReferenceFrameType.None); diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1DeblockingFilterTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1DeblockingFilterTests.cs index b27c8ae63..24b728037 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1DeblockingFilterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1DeblockingFilterTests.cs @@ -54,7 +54,7 @@ public class Av1DeblockingFilterTests /// Verifies skipped inter-edge decisions and reference and mode level deltas through the production frame filter. /// [Fact] - public void DecodeFrameMatchesCurrentLibaomInterEdgeAndDeltaDecisions() + public void DecodeFrameMatchesReference() { ValidateInterEdgeAndDeltaDecisions( Av1PredictionMode.GlobalMotionVector, diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ForwardTransformTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ForwardTransformTests.cs index f20111190..6fa3c6d64 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ForwardTransformTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ForwardTransformTests.cs @@ -58,7 +58,7 @@ public class Av1ForwardTransformTests /// Verifies every permitted size, type, and bit-depth combination against the direct scalar two-axis definition. /// [Fact] - public void TwoDimensionalPipelineMatchesScalarReferenceAcrossHardwareConfigurations() + public void TwoDimensionalPipelineMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertTwoDimensionalPipeline, TransformConfigurations); /// @@ -138,7 +138,7 @@ public class Av1ForwardTransformTests } /// - /// Compares one integer stage network with the analytical transform used by the libaom forward-transform tests. + /// Compares one integer stage network with the analytical reference transform. /// /// The transform operator. /// The analytical transform definition. @@ -170,7 +170,7 @@ public class Av1ForwardTransformTests TOperator.Transform(ref valuesBase, sizeof(int), sizeof(int), ref buffer0, ref buffer1, cosBit); Av1ReferenceTransform.ReferenceTransform1d(transformType, referenceInput, referenceOutput, length); - // libaom permits seven integer coefficient units because each fixed-point butterfly rounds independently. + // the reference decoder permits seven integer coefficient units because each fixed-point butterfly rounds independently. for (int index = 0; index < length; index++) { int expected = (int)Math.Round(referenceOutput[index], MidpointRounding.AwayFromZero); diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1GlobalMotionParametersTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1GlobalMotionParametersTests.cs index d6a5ac615..19d69f47c 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1GlobalMotionParametersTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1GlobalMotionParametersTests.cs @@ -84,10 +84,10 @@ public class Av1GlobalMotionParametersTests } /// - /// Verifies local least-squares projection against a multi-sample model traced from current libaom. + /// Verifies local least-squares projection against a multi-sample model traced from the reference decoder. /// [Fact] - public void LocalProjectionMatchesCurrentLibaomMultiSampleModel() + public void LocalProjectionMatchesReference() { Point[] sourcePoints = [new(24, -40), new(-40, 24), new(-24, -24), new(72, -24)]; Point[] referencePoints = [new(-16, -8), new(-72, 64), new(-64, 16), new(32, 8)]; diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterFrameIntraEntropyTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterFrameIntraEntropyTests.cs index 72524cd60..548e0a00a 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterFrameIntraEntropyTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterFrameIntraEntropyTests.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; public class Av1InterFrameIntraEntropyTests { /// - /// Gets libaom's four forward Q15 luma-mode CDF rows in block-size-group order. + /// Gets the reference decoder's four forward Q15 luma-mode CDF rows in block-size-group order. /// private static ReadOnlySpan FrameYModeForwardThresholds => [ @@ -28,10 +28,10 @@ public class Av1InterFrameIntraEntropyTests ]; /// - /// Verifies the four normative intra/inter distributions against libaom's forward Q15 defaults. + /// Verifies the four normative intra/inter distributions against the reference decoder's forward Q15 defaults. /// [Fact] - public void IntraInterDefaultsMatchLibaom() + public void IntraInterDefaultsMatchReference() { uint[] forwardThresholds = [806, 16662, 20186, 26538]; Av1Distribution[] distributions = Av1DefaultDistributions.IntraInter; @@ -39,7 +39,7 @@ public class Av1InterFrameIntraEntropyTests Assert.Equal(forwardThresholds.Length, distributions.Length); for (int context = 0; context < distributions.Length; context++) { - // Av1Distribution stores inverse cumulative thresholds, so compare each libaom default after the same + // Av1Distribution stores inverse cumulative thresholds, so compare each forward default after the same // forward-to-inverse conversion performed by its constructor. Assert.Equal((uint)Av1Distribution.ProbabilityTop - forwardThresholds[context], distributions[context][0]); Assert.Equal(2, distributions[context].NumberOfSymbols); @@ -47,10 +47,10 @@ public class Av1InterFrameIntraEntropyTests } /// - /// Verifies every inter-frame intra luma-mode threshold against libaom's forward Q15 defaults. + /// Verifies every inter-frame intra luma-mode threshold against the reference decoder's forward Q15 defaults. /// [Fact] - public void FrameYModeDefaultsMatchLibaom() + public void FrameYModeDefaultsMatchReference() { const int thresholdsPerGroup = 12; ReadOnlySpan forwardThresholds = FrameYModeForwardThresholds; @@ -229,7 +229,7 @@ public class Av1InterFrameIntraEntropyTests /// Every decoded block size paired with its luma-mode size group. public static TheoryData GetBlockSizeGroups() { - // This is size_group_lookup from AV1 section 9.3 and libaom common_data.h. Keeping expected values explicit + // This is size_group_lookup from AV1 section 9.3 and the normative lookup table. Keeping expected values explicit // ensures that the test does not reproduce the production formula it is intended to verify. int[] sizeGroups = [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 0, 0, 1, 1, 2, 2]; TheoryData result = []; diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterFrameModeInfoTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterFrameModeInfoTests.cs index 11419a348..ce60bddee 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterFrameModeInfoTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterFrameModeInfoTests.cs @@ -57,7 +57,7 @@ public class Av1InterFrameModeInfoTests /// Verifies that skip mode omits the residual-skip and intra-inter symbols and marks the block as inter coded. /// [Fact] - public void ReadInterFrameModeInfoSkipModeForcesInterBlockAndResidualSkip() + public void SkipModeForcesInterAndSkipsResidual() { ObuSequenceHeader sequenceHeader = CreateSequenceHeader(); sequenceHeader.OrderHintInfo.EnableOrderHint = true; @@ -150,7 +150,7 @@ public class Av1InterFrameModeInfoTests /// Verifies that an identity global-motion block omits switchable interpolation-filter symbols. /// [Fact] - public void ReadInterFrameModeInfoOmitsInterpolationFiltersForIdentityGlobalMotion() + public void IdentityGlobalMotionOmitsInterpolationFilters() { ObuSequenceHeader sequenceHeader = CreateSequenceHeader(); sequenceHeader.EnableDualFilter = true; @@ -167,8 +167,8 @@ public class Av1InterFrameModeInfoTests using Av1SymbolWriter writer = new(Configuration.Default, 3, updateCdf: true); writer.WriteSymbol(false, Av1DefaultDistributions.Skip[0]); - // Current libaom's is_nontrans_global_motion rejects only TRANSLATION, so the default identity model omits - // these sentinel symbols even though is_global_mv_block uses the separate greater-than-translation classification. + // Identity is distinct from Translation for this syntax gate. These sentinel symbols must remain unread even + // though the separate global-motion-block classification requires a model greater than Translation. writer.WriteSymbol((int)Av1InterpolationFilter.Smooth, Av1DefaultDistributions.SwitchableInterpolation[3]); writer.WriteSymbol((int)Av1InterpolationFilter.Sharp, Av1DefaultDistributions.SwitchableInterpolation[11]); using IMemoryOwner encoded = writer.Exit(); @@ -234,7 +234,7 @@ public class Av1InterFrameModeInfoTests [InlineData((int)Av1CompoundType.DistanceWeighted)] [InlineData((int)Av1CompoundType.Wedge)] [InlineData((int)Av1CompoundType.DifferenceWeighted)] - public void ReadInterFrameModeInfoReadsSelectableCompoundBeforeInterpolation(int compoundTypeValue) + public void ReadsSelectableCompoundBeforeInterpolation(int compoundTypeValue) { Av1CompoundType compoundType = (Av1CompoundType)compoundTypeValue; ObuSequenceHeader sequenceHeader = CreateSequenceHeader(); diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterIntraEntropyTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterIntraEntropyTests.cs index e31f38492..4aa4ab975 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterIntraEntropyTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterIntraEntropyTests.cs @@ -15,10 +15,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; public class Av1InterIntraEntropyTests { /// - /// Verifies the four block-size-group distributions against libaom's forward Q15 defaults. + /// Verifies the four block-size-group distributions against the reference decoder's forward Q15 defaults. /// [Fact] - public void DefaultsMatchLibaom() + public void DefaultsMatchReference() { ReadOnlySpan forwardThresholds = [16384, 26887, 27597, 30237]; Av1Distribution[] distributions = Av1DefaultDistributions.InterIntra; @@ -26,7 +26,7 @@ public class Av1InterIntraEntropyTests Assert.Equal(forwardThresholds.Length, distributions.Length); for (int group = 0; group < distributions.Length; group++) { - // Av1Distribution stores inverse cumulative thresholds, so convert libaom's forward threshold before + // Av1Distribution stores inverse cumulative thresholds, so convert the reference decoder's forward threshold before // comparing the exact Q15 state consumed by the range decoder. uint expected = (uint)Av1Distribution.ProbabilityTop - forwardThresholds[group]; @@ -155,7 +155,7 @@ public class Av1InterIntraEntropyTests /// Every decoded block size paired with its size group. public static TheoryData GetBlockSizeGroups() { - // These are the explicit Size_Group values from AV1 section 9.3 and libaom common_data.h. The test keeps the + // These are the explicit Size_Group values from AV1 section 9.3 and the normative lookup table. The test keeps the // expected table independent from the production geometry formula so a shared calculation cannot mask errors. int[] sizeGroups = [0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 0, 0, 1, 1, 2, 2]; TheoryData result = []; diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterModeEntropyTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterModeEntropyTests.cs index 316c73785..0340d4265 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterModeEntropyTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterModeEntropyTests.cs @@ -14,10 +14,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; public class Av1InterModeEntropyTests { /// - /// Verifies the normative single-reference inter-mode distributions against libaom's forward Q15 defaults. + /// Verifies the normative single-reference inter-mode distributions against the reference decoder's forward Q15 defaults. /// [Fact] - public void InterModeDefaultsMatchLibaom() + public void InterModeDefaultsMatchReference() { AssertBinaryDefaults(Av1DefaultDistributions.NewMv, [24035, 16630, 15339, 8386, 12222, 4676]); AssertBinaryDefaults(Av1DefaultDistributions.ZeroMv, [2175, 1054]); @@ -36,7 +36,7 @@ public class Av1InterModeEntropyTests [InlineData(0, 0, 0, 0)] [InlineData(77, 5, 1, 4)] [InlineData(93, 5, 1, 5)] - public void PackedInterModeContextMatchesLibaom(int modeContext, int expectedNewMv, int expectedZeroMv, int expectedRefMv) + public void PackedInterModeContextMatchesReference(int modeContext, int expectedNewMv, int expectedZeroMv, int expectedRefMv) { Assert.Equal(expectedNewMv, Av1SymbolContextHelper.GetNewMvContext(modeContext)); Assert.Equal(expectedZeroMv, Av1SymbolContextHelper.GetZeroMvContext(modeContext)); @@ -55,7 +55,7 @@ public class Av1InterModeEntropyTests [InlineData((int)Av1PredictionMode.GlobalMotionVector, 1, 0, -1)] [InlineData((int)Av1PredictionMode.NearestMotionVector, 1, 1, 0)] [InlineData((int)Av1PredictionMode.NearMotionVector, 1, 1, 1)] - public void ReadInterModeMatchesLibaomTree(int expectedMode, int newMvSymbol, int zeroMvSymbol, int refMvSymbol) + public void ReadInterModeMatchesReference(int expectedMode, int newMvSymbol, int zeroMvSymbol, int refMvSymbol) { const int modeContext = 77; Av1Distribution newMv = Av1DefaultDistributions.NewMv[5]; diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterPredictorTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterPredictorTests.cs index 253967a42..19a4a545d 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterPredictorTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterPredictorTests.cs @@ -91,14 +91,14 @@ public class Av1InterPredictorTests /// Verifies exact 8-bit copy and convolution output, scalar tails, and untouched destination padding under every SIMD configuration. /// [Fact] - public void BytePredictionMatchesLibaomOracleAcrossIntrinsicWidths() + public void BytePredictionMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateBytePredictions, PredictorConfigurations); /// /// Verifies exact 8-, 10-, and 12-bit ushort output, scalar tails, and untouched destination padding under every SIMD configuration. /// [Fact] - public void HighBitDepthPredictionMatchesLibaomOracleAcrossIntrinsicWidths() + public void HighBitDepthPredictionMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateHighBitDepthPredictions, PredictorConfigurations); /// @@ -334,7 +334,7 @@ public class Av1InterPredictorTests : new short[Math.Max(testCase.Width, 16) * (testCase.Height + FilterTapCount - 1)]; /// - /// Applies libaom's single-reference copy or convolution equations to an 8-bit prediction block. + /// Applies the reference decoder's single-reference copy or convolution equations to an 8-bit prediction block. /// /// The complete padded reference plane. /// The source-row stride. @@ -411,7 +411,7 @@ public class Av1InterPredictorTests } /// - /// Applies libaom's single-reference copy or convolution equations to a high-bit-depth prediction block. + /// Applies the reference decoder's single-reference copy or convolution equations to a high-bit-depth prediction block. /// /// The complete padded reference plane. /// The source-row stride. @@ -489,7 +489,7 @@ public class Av1InterPredictorTests } /// - /// Applies libaom's biased two-pass 8-bit convolution and removes both intermediate bias terms after vertical filtering. + /// Applies the reference decoder's biased two-pass 8-bit convolution and removes both intermediate bias terms after vertical filtering. /// /// The complete padded reference plane. /// The source-row stride. @@ -531,7 +531,7 @@ public class Av1InterPredictorTests } /// - /// Applies libaom's biased two-pass high-bit-depth convolution and removes both intermediate bias terms after vertical filtering. + /// Applies the reference decoder's biased two-pass high-bit-depth convolution and removes both intermediate bias terms after vertical filtering. /// /// The complete padded reference plane. /// The source-row stride. diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterpolationFilterEntropyTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterpolationFilterEntropyTests.cs index 129f4fe44..72dec76ce 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterpolationFilterEntropyTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InterpolationFilterEntropyTests.cs @@ -31,7 +31,7 @@ public class Av1InterpolationFilterEntropyTests private const int HorizontalDirection = 1; /// - /// Gets libaom's forward Q15 switchable interpolation-filter thresholds in context order. + /// Gets the reference decoder's forward Q15 switchable interpolation-filter thresholds in context order. /// private static ReadOnlySpan ForwardThresholds => [ @@ -54,10 +54,10 @@ public class Av1InterpolationFilterEntropyTests ]; /// - /// Verifies every normative switchable interpolation-filter distribution against libaom's forward Q15 defaults. + /// Verifies every normative switchable interpolation-filter distribution against the reference decoder's forward Q15 defaults. /// [Fact] - public void DefaultsMatchLibaom() + public void DefaultsMatchReference() { const int thresholdCount = 2; ReadOnlySpan forwardThresholds = ForwardThresholds; @@ -118,7 +118,7 @@ public class Av1InterpolationFilterEntropyTests /// Verifies all sixteen combinations of reference type, direction, and contributing neighbor filter state. /// [Fact] - public void ContextLayoutMatchesLibaom() + public void ContextLayoutMatchesReference() { Av1BlockModeInfo single = CreateModeInfo( Av1ReferenceFrameType.Last, diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1IntraBlockCopyPredictorTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1IntraBlockCopyPredictorTests.cs index 55a3dc640..06bec5fa6 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1IntraBlockCopyPredictorTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1IntraBlockCopyPredictorTests.cs @@ -23,14 +23,14 @@ public class Av1IntraBlockCopyPredictorTests /// Verifies all four source phases for 8-bit samples at every AV1 transform size. /// [Fact] - public void EightBitPredictionMatchesScalarAcrossIntrinsicWidths() + public void EightBitPredictionMatchesScalar() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateEightBitPrediction, PredictorConfigurations); /// /// Verifies all four source phases for high-bit-depth samples at every AV1 transform size. /// [Fact] - public void HighBitDepthPredictionMatchesScalarAcrossIntrinsicWidths() + public void HighBitDepthPredictionMatchesScalar() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateHighBitDepthPrediction, PredictorConfigurations); /// diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1IntraBlockCopyTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1IntraBlockCopyTests.cs index 124eb9a27..d0af7d9b3 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1IntraBlockCopyTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1IntraBlockCopyTests.cs @@ -18,7 +18,7 @@ public class Av1IntraBlockCopyTests /// Verifies the horizontal fallback used in the tile's first superblock row. /// [Fact] - public void FindReferenceUsesDelayedHorizontalFallbackInFirstSuperblockRow() + public void FindReferenceUsesFirstRowFallback() { ObuSequenceHeader sequenceHeader = CreateSequenceHeader(); Av1FrameInfo frameInfo = new(sequenceHeader); diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1IntraPredictionMemory.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1IntraPredictionMemory.cs deleted file mode 100644 index 3a74f5c45..000000000 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1IntraPredictionMemory.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Six Labors Split License. - -using System.Globalization; -using System.Security.Cryptography; -using System.Text; -using SixLabors.ImageSharp.Formats.Heif.Av1; - -namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; - -internal class Av1IntraPredictionMemory -{ - public const int Padding = 16; - private const int TopPadding = 7; - private const int MaxBlockSizeTimes2 = 1 << Av1Constants.MaxSuperBlockSizeLog2; - private const int TotalPixelCount = 4096; - private readonly byte[] destination = new byte[TotalPixelCount]; - private readonly byte[] referenceSource = new byte[TotalPixelCount]; - private readonly byte[] leftMemory = new byte[MaxBlockSizeTimes2 + Padding]; - private readonly byte[] topMemory = new byte[MaxBlockSizeTimes2 + Padding + TopPadding]; - private readonly int bitDepth; - - public Av1IntraPredictionMemory(int bitDepth) => this.bitDepth = bitDepth; - - public Span Destination => this.destination; - - public Span Left => this.leftMemory; - - public Span Top => this.topMemory; - - /// - /// Sets referenceSource, left and top to . - /// - public void Set(byte value) - { - for (int r = 0; r < this.referenceSource.Length; r++) - { - this.referenceSource[r] = value; - } - - // Upsampling in the directional predictors extends left/top[-1] to [-2]. - for (int i = Padding - 2; i < Padding + MaxBlockSizeTimes2; ++i) - { - this.leftMemory[i] = this.topMemory[i] = value; - } - } - - public void Scramble(Random rnd) - { - for (int i = 0; i < this.referenceSource.Length; i++) - { - this.referenceSource[i] = this.GetRandomValue(rnd); - } - - for (int i = Padding; i < (MaxBlockSizeTimes2 >> 1) + Padding; ++i) - { - this.leftMemory[i] = this.GetRandomValue(rnd); - } - - for (int i = Padding - 1; i < (MaxBlockSizeTimes2 >> 1) + Padding; ++i) - { - this.topMemory[i] = this.GetRandomValue(rnd); - } - - // Some directional predictors require top-right, bottom-left. - for (int i = MaxBlockSizeTimes2 >> 1; i < MaxBlockSizeTimes2; ++i) - { - this.leftMemory[Padding + i] = this.GetRandomValue(rnd); - this.topMemory[Padding + i] = this.GetRandomValue(rnd); - } - - // TODO(jzern): reorder this and regenerate the digests after switching - // random number generators. - // Upsampling in the directional predictors extends left/top[-1] to [-2]. - this.leftMemory[Padding - 1] = this.GetRandomValue(rnd); - this.leftMemory[Padding - 2] = this.GetRandomValue(rnd); - this.topMemory[Padding - 2] = this.GetRandomValue(rnd); - this.leftMemory.AsSpan(0, Padding - 2).Clear(); - this.topMemory.AsSpan(0, Padding - 2).Clear(); - this.topMemory.AsSpan(MaxBlockSizeTimes2 + Padding, TopPadding).Clear(); - } - - public void CopySourceToDestination() => this.referenceSource.CopyTo(this.destination.AsSpan()); - - /// - /// Return a hash string of a block of bytes. - /// - /// This test design is used extensively in 'libgav1' tests, some of which are ported here. - public static string GetDigest(byte[] input) - { - byte[] hash = MD5.HashData(input); - StringBuilder sb = new(); - for (int i = 0; i < hash.Length; i++) - { - sb.Append(hash[i].ToString("X2", CultureInfo.InvariantCulture)); - } - - return sb.ToString(); - } - - public string GetDestinationDigest() => GetDigest(this.destination); - - private byte GetRandomValue(Random random) => (byte)(random.Next(1 << 16) & ((1 << this.bitDepth) - 1)); -} diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InverseQuantizationTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InverseQuantizationTests.cs index b832ec808..cf6d44879 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InverseQuantizationTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InverseQuantizationTests.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; public class Av1InverseQuantizationTests { [Fact] - public void QuantizationMatricesCoverAllLevelsPlanesAndTransformSizes() + public void MatricesCoverAllLevelsPlanesAndTransformSizes() { for (int level = 0; level < Av1Constants.QuantificationMatrixLevelCount; level++) { diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InverseTransformTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InverseTransformTests.cs index 82f9c12b0..bde9ef4cd 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InverseTransformTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1InverseTransformTests.cs @@ -43,10 +43,10 @@ public class Av1InverseTransformTests => FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertIdentityOperatorParity, TransformConfigurations); /// - /// Verifies the current-libaom widened operations at the twelve-bit inverse row-stage bounds. + /// Verifies the reference widened operations at the twelve-bit inverse row-stage bounds. /// [Fact] - public void TwelveBitWideIntermediatesMatchCurrentLibaom() + public void TwelveBitWideIntermediatesMatchReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertTwelveBitWideIntermediateParity, TransformConfigurations); /// @@ -123,7 +123,7 @@ public class Av1InverseTransformTests cosBit, stageRange); - // These are the exact outputs of current libaom's signed Int64 terminal round. The first positive lane has an + // These are the exact outputs of the reference decoder's signed Int64 terminal round. The first positive lane has an // Int32 fixed-point sum of 2,147,482,471, so adding the 2,048 rounding bias in Int32 would wrap. Vector128 adstExpected0 = Vector128.Create(524_288, -524_288, 524_287, -524_287); Vector128 adstExpected1 = Vector128.Create(33_612, -33_612, 33_612, -33_612); @@ -167,7 +167,7 @@ public class Av1InverseTransformTests } /// - /// Verifies one identity operator against exact current-libaom widened fixed-point results. + /// Verifies one identity operator against exact reference widened fixed-point results. /// /// The inverse identity operator. /// The identity-transform length. @@ -291,7 +291,7 @@ public class Av1InverseTransformTests /// The coded sample bit depth. [Theory] [MemberData(nameof(Av1ForwardTransformTests.ValidTransformCases), MemberType = typeof(Av1ForwardTransformTests))] - public void TwoDimensionalSimdKernelsMatchScalarForEveryValidConfiguration( + public void TwoDimensionalKernelsMatchReference( int transformTypeValue, int transformSizeValue, int bitDepth) @@ -306,7 +306,7 @@ public class Av1InverseTransformTests /// Verifies lossless inverse Walsh-Hadamard reconstruction against an independent definition. /// [Fact] - public void LosslessWalshHadamardMatchesReferenceAcrossIntrinsicTiers() + public void LosslessWalshHadamardMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertLosslessWalshHadamardParity, TransformConfigurations); /// diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionModeEntropyTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionModeEntropyTests.cs index 58a447d2f..90a670add 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionModeEntropyTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionModeEntropyTests.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; public class Av1MotionModeEntropyTests { /// - /// Gets libaom's forward Q15 Simple Translation, OBMC, and Warped thresholds in block-size order. + /// Gets the reference decoder's forward Q15 Simple Translation, OBMC, and Warped thresholds in block-size order. /// private static ReadOnlySpan MotionModeForwardThresholds => [ @@ -45,7 +45,7 @@ public class Av1MotionModeEntropyTests ]; /// - /// Gets libaom's forward Q15 Simple Translation and OBMC thresholds in block-size order. + /// Gets the reference decoder's forward Q15 Simple Translation and OBMC thresholds in block-size order. /// private static ReadOnlySpan ObmcForwardThresholds => [ @@ -54,10 +54,10 @@ public class Av1MotionModeEntropyTests ]; /// - /// Verifies all twenty-two ternary and binary motion-mode distributions against libaom's forward Q15 defaults. + /// Verifies all twenty-two ternary and binary motion-mode distributions against the reference decoder's forward Q15 defaults. /// [Fact] - public void DefaultsMatchLibaomForEveryBlockSize() + public void DefaultsMatchReference() { const int blockSizeCount = (int)Av1BlockSize.AllSizes; const int ternaryThresholdCount = 2; @@ -78,7 +78,7 @@ public class Av1MotionModeEntropyTests for (int threshold = 0; threshold < ternaryThresholdCount; threshold++) { - // Av1Distribution stores inverse cumulative thresholds, so complement libaom's published forward + // Av1Distribution stores inverse cumulative thresholds, so complement the reference decoder's published forward // Q15 values before comparing the exact state consumed by the range decoder. uint expected = (uint)Av1Distribution.ProbabilityTop - motionModeForwardThresholds[(blockSize * ternaryThresholdCount) + threshold]; @@ -200,7 +200,7 @@ public class Av1MotionModeEntropyTests [Theory] [InlineData(false)] [InlineData(true)] - public void ReadMotionModePreservesFollowingInterpolationSymbolAlignment(bool allowWarpedMotion) + public void PreservesFollowingInterpolationSymbol(bool allowWarpedMotion) { Av1BlockSize blockSize = Av1BlockSize.Block16x16; const int interpolationContext = 3; diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionModeInfoTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionModeInfoTests.cs index 2ddb0a44a..3a7be2fe1 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionModeInfoTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionModeInfoTests.cs @@ -24,7 +24,7 @@ public class Av1MotionModeInfoTests /// Verifies that an extended 8x32 rectangle omits inter-intra syntax and reads the following interpolation filter. /// [Fact] - public void ReadInterFrameModeInfoOmitsInterIntraFlagForExtendedRectangle() + public void OmitsInterIntraForExtendedRectangle() { ObuSequenceHeader sequenceHeader = CreateSequenceHeader(); sequenceHeader.EnableInterIntraCompound = true; @@ -66,7 +66,7 @@ public class Av1MotionModeInfoTests [InlineData(true, true, (int)Av1MotionMode.SimpleTranslation)] [InlineData(true, false, (int)Av1MotionMode.Obmc)] [InlineData(true, true, (int)Av1MotionMode.Obmc)] - public void ReadInterFrameModeInfoContinuesFromFalseInterIntraThroughMotionModeIntoInterpolation( + public void ContinuesFromInterIntraToInterpolation( bool isMotionModeSwitchable, bool allowWarpedMotion, int selectedMotionModeValue) @@ -158,7 +158,7 @@ public class Av1MotionModeInfoTests [Theory] [InlineData(false)] [InlineData(true)] - public void ReadInterFrameModeInfoReadsSelectedInterIntraBeforeInterpolation(bool useWedge) + public void ReadsInterIntraBeforeInterpolation(bool useWedge) { ObuSequenceHeader sequenceHeader = CreateSequenceHeader(); sequenceHeader.EnableInterIntraCompound = true; diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionVectorEntropyTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionVectorEntropyTests.cs index 9c2ab1c92..c4818ccf1 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionVectorEntropyTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionVectorEntropyTests.cs @@ -14,10 +14,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; public class Av1MotionVectorEntropyTests { /// - /// Verifies both motion-vector contexts against every normative forward Q15 default from libaom. + /// Verifies both motion-vector contexts against every normative forward Q15 default from the reference decoder. /// [Fact] - public void MotionVectorDefaultsMatchLibaom() + public void MotionVectorDefaultsMatchReference() { Av1FrameEntropyContext context = new(0); diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionVectorTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionVectorTests.cs index 706e12f29..7aaaae538 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionVectorTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1MotionVectorTests.cs @@ -90,7 +90,7 @@ public class Av1MotionVectorTests /// Verifies the complete-block and sixteen-sample borders used to clamp spatial reference candidates. /// [Fact] - public void ClampReferenceMatchesLibaomSpatialLimits() + public void ClampReferenceMatchesSpatialLimits() { const int blockWidth = 16; const int blockHeight = 8; @@ -143,7 +143,7 @@ public class Av1MotionVectorTests [InlineData(2, -2, 1, 3, 1, -1)] [InlineData(31, -31, 40, 40, 31, -31)] [InlineData(4095, -4095, 31, 1, 16383, -16383)] - public void ProjectTemporalMatchesLibaom( + public void ProjectTemporalMatchesReference( int row, int column, int numerator, diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1PalettePredictorTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1PalettePredictorTests.cs index 7cb37e6bb..cc432f5fd 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1PalettePredictorTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1PalettePredictorTests.cs @@ -24,7 +24,7 @@ public class Av1PalettePredictorTests /// Verifies exact indexed reconstruction and destination-padding preservation for every palette size. /// [Fact] - public void PredictMatchesIndependentDefinitionAcrossIntrinsicWidths() + public void PredictMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidatePredictors, Configurations); /// diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1PredictorTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1PredictorTests.cs index 26425679f..952349abd 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1PredictorTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1PredictorTests.cs @@ -47,77 +47,77 @@ public class Av1PredictorTests /// Verifies DC prediction with each register-width tier and the scalar fallback. /// [Fact] - public void DcPredictorsMatchScalarDefinitionsAcrossIntrinsicWidths() + public void DcPredictorsMatchReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateDcPredictors, PredictorConfigurations); /// /// Verifies horizontal prediction with each register-width tier and the scalar fallback. /// [Fact] - public void HorizontalPredictorMatchesScalarDefinitionAcrossIntrinsicWidths() + public void HorizontalPredictorMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateHorizontalPredictor, PredictorConfigurations); /// /// Verifies vertical prediction with each register-width tier and the scalar fallback. /// [Fact] - public void VerticalPredictorMatchesScalarDefinitionAcrossIntrinsicWidths() + public void VerticalPredictorMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateVerticalPredictor, PredictorConfigurations); /// /// Verifies Paeth prediction with each register-width tier and the scalar fallback. /// [Fact] - public void PaethPredictorMatchesScalarDefinitionAcrossIntrinsicWidths() + public void PaethPredictorMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidatePaethPredictor, PredictorConfigurations); /// /// Verifies smooth prediction with each register-width tier and the scalar fallback. /// [Fact] - public void SmoothPredictorMatchesScalarDefinitionAcrossIntrinsicWidths() + public void SmoothPredictorMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateSmoothPredictor, PredictorConfigurations); /// /// Verifies horizontal smooth prediction with each register-width tier and the scalar fallback. /// [Fact] - public void SmoothHorizontalPredictorMatchesScalarDefinitionAcrossIntrinsicWidths() + public void SmoothHorizontalPredictorMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateSmoothHorizontalPredictor, PredictorConfigurations); /// /// Verifies vertical smooth prediction with each register-width tier and the scalar fallback. /// [Fact] - public void SmoothVerticalPredictorMatchesScalarDefinitionAcrossIntrinsicWidths() + public void SmoothVerticalPredictorMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateSmoothVerticalPredictor, PredictorConfigurations); /// /// Verifies directional prediction with each register-width tier and the scalar fallback. /// [Fact] - public void DirectionalPredictorsMatchScalarDefinitionsAcrossIntrinsicWidths() + public void DirectionalPredictorsMatchReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateDirectionalPredictors, PredictorConfigurations); /// /// Verifies filter-intra prediction with each register-width tier and the scalar fallback. /// [Fact] - public void FilterIntraPredictorsMatchScalarDefinitionsAcrossIntrinsicWidths() + public void FilterIntraPredictorsMatchReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateFilterIntraPredictors, PredictorConfigurations); /// /// Verifies intra-edge upsampling with Vector128 and the scalar fallback. /// [Fact] - public void EdgeUpsamplingMatchesScalarDefinitionsAcrossIntrinsicWidths() + public void EdgeUpsamplingMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateEdgeUpsampling, HwIntrinsics.AllowAll | HwIntrinsics.DisableHWIntrinsic); /// /// Verifies intra-edge filtering with Vector128 and the scalar fallback. /// [Fact] - public void EdgeFilteringMatchesScalarDefinitionsAcrossIntrinsicWidths() + public void EdgeFilteringMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateEdgeFiltering, HwIntrinsics.AllowAll | HwIntrinsics.DisableHWIntrinsic); /// @@ -523,7 +523,7 @@ public class Av1PredictorTests } /// - /// Retains byte-exact libaom vectors so scalar and SIMD code cannot share the same mistranslation unnoticed. + /// Retains byte-exact reference vectors so scalar and SIMD code cannot share the same mistranslation unnoticed. /// private static void ValidateKnownFilterIntraVectors() { diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReconstructionConformanceTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReconstructionConformanceTests.cs index 625d8f521..13115b2b5 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReconstructionConformanceTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReconstructionConformanceTests.cs @@ -158,137 +158,137 @@ public class Av1ReconstructionConformanceTests private const int AverageCompoundFixtureFrameCount = 19; /// - /// The number of shown frames in the official libaom all-intra sequence. + /// The number of shown frames in the official AV1 all-intra sequence. /// private const int OfficialAllIntraFixtureFrameCount = 39; /// - /// The number of shown frames in the official libaom CDF-update sequence. + /// The number of shown frames in the official AV1 CDF-update sequence. /// private const int OfficialCdfUpdateFixtureFrameCount = 2; /// - /// The number of shown frames in the official libaom temporal motion-field sequence. + /// The number of shown frames in the official AV1 temporal motion-field sequence. /// private const int OfficialMotionFieldFixtureFrameCount = 4; /// - /// The displayed width of the official libaom extreme-displacement intra-block-copy sequence. + /// The displayed width of the official AV1 extreme-displacement intra-block-copy sequence. /// private const int OfficialIntraBlockCopyFixtureWidth = 1920; /// - /// The displayed height of the official libaom extreme-displacement intra-block-copy sequence. + /// The displayed height of the official AV1 extreme-displacement intra-block-copy sequence. /// private const int OfficialIntraBlockCopyFixtureHeight = 1080; /// - /// The number of shown frames in the official libaom extreme-displacement intra-block-copy sequence. + /// The number of shown frames in the official AV1 extreme-displacement intra-block-copy sequence. /// private const int OfficialIntraBlockCopyFixtureFrameCount = 2; /// - /// The displayed width of the official libaom two-spatial-layer sequence. + /// The displayed width of the official AV1 two-spatial-layer sequence. /// private const int OfficialTwoSpatialLayerFixtureWidth = 1280; /// - /// The displayed height of the official libaom two-spatial-layer sequence. + /// The displayed height of the official AV1 two-spatial-layer sequence. /// private const int OfficialTwoSpatialLayerFixtureHeight = 720; /// - /// The number of default-operating-point frames in the official libaom two-spatial-layer sequence. + /// The number of default-operating-point frames in the official AV1 two-spatial-layer sequence. /// private const int OfficialTwoSpatialLayerFixtureFrameCount = 8; /// - /// The displayed width of the official libaom two-temporal-layer sequence. + /// The displayed width of the official AV1 two-temporal-layer sequence. /// private const int OfficialTwoTemporalLayerFixtureWidth = 640; /// - /// The displayed height of the official libaom two-temporal-layer sequence. + /// The displayed height of the official AV1 two-temporal-layer sequence. /// private const int OfficialTwoTemporalLayerFixtureHeight = 360; /// - /// The number of default-operating-point frames in the official libaom two-temporal-layer sequence. + /// The number of default-operating-point frames in the official AV1 two-temporal-layer sequence. /// private const int OfficialTwoTemporalLayerFixtureFrameCount = 8; /// - /// The displayed width of the official libaom spatial-and-temporal-layer sequence. + /// The displayed width of the official AV1 spatial-and-temporal-layer sequence. /// private const int OfficialSpatialTemporalLayerFixtureWidth = 1280; /// - /// The displayed height of the official libaom spatial-and-temporal-layer sequence. + /// The displayed height of the official AV1 spatial-and-temporal-layer sequence. /// private const int OfficialSpatialTemporalLayerFixtureHeight = 720; /// - /// The number of default-operating-point frames in the official libaom spatial-and-temporal-layer sequence. + /// The number of default-operating-point frames in the official AV1 spatial-and-temporal-layer sequence. /// private const int OfficialSpatialTemporalLayerFixtureFrameCount = 8; /// - /// The number of frames in the official libaom active-film-grain sequence. + /// The number of frames in the official AV1 active-film-grain sequence. /// private const int OfficialFilmGrainFixtureFrameCount = 10; /// - /// The width of the official libaom eight-bit monochrome sequence. + /// The width of the official AV1 eight-bit monochrome sequence. /// private const int OfficialMonochromeFixtureWidth = 320; /// - /// The height of the official libaom eight-bit monochrome sequence. + /// The height of the official AV1 eight-bit monochrome sequence. /// private const int OfficialMonochromeFixtureHeight = 180; /// - /// The number of frames in the official libaom eight-bit monochrome sequence. + /// The number of frames in the official AV1 eight-bit monochrome sequence. /// private const int OfficialMonochromeFixtureFrameCount = 10; /// - /// The width of the official libaom eight-bit quantizer-boundary sequences. + /// The width of the official AV1 eight-bit quantizer-boundary sequences. /// private const int OfficialEightBitQuantizerFixtureWidth = 352; /// - /// The height of the official libaom eight-bit quantizer-boundary sequences. + /// The height of the official AV1 eight-bit quantizer-boundary sequences. /// private const int OfficialEightBitQuantizerFixtureHeight = 288; /// - /// The width of the official libaom ten-bit quantizer-boundary sequences. + /// The width of the official AV1 ten-bit quantizer-boundary sequences. /// private const int OfficialTenBitQuantizerFixtureWidth = 640; /// - /// The height of the official libaom ten-bit quantizer-boundary sequences. + /// The height of the official AV1 ten-bit quantizer-boundary sequences. /// private const int OfficialTenBitQuantizerFixtureHeight = 360; /// - /// The number of frames in each official libaom quantizer-boundary sequence. + /// The number of frames in each official AV1 quantizer-boundary sequence. /// private const int OfficialQuantizerFixtureFrameCount = 2; /// - /// The minimum dimension retained from the official libaom frame-size matrix. + /// The minimum dimension retained from the official AV1 frame-size matrix. /// private const int OfficialFrameSizeFixtureMinimumDimension = 196; /// - /// The maximum dimension retained from the official libaom frame-size matrix. + /// The maximum dimension retained from the official AV1 frame-size matrix. /// private const int OfficialFrameSizeFixtureMaximumDimension = 226; /// - /// The number of frames in each official libaom frame-size sequence. + /// The number of frames in each official AV1 frame-size sequence. /// private const int OfficialFrameSizeFixtureFrameCount = 2; @@ -330,17 +330,17 @@ public class Av1ReconstructionConformanceTests (1 << (int)Av1TransformType.HorizontalDct); /// - /// The displayed width of the official libaom motion-vector sequence. + /// The displayed width of the official AV1 motion-vector sequence. /// private const int OfficialMotionVectorFixtureWidth = 352; /// - /// The displayed height of the official libaom motion-vector sequence. + /// The displayed height of the official AV1 motion-vector sequence. /// private const int OfficialMotionVectorFixtureHeight = 288; /// - /// The number of shown frames in the official libaom motion-vector sequence. + /// The number of shown frames in the official AV1 motion-vector sequence. /// private const int OfficialMotionVectorFixtureFrameCount = 4; @@ -421,7 +421,7 @@ public class Av1ReconstructionConformanceTests /// and twelve-bit AV1 and AVIF content. /// [Fact] - public void DecodeDeblockingFixturesMatchCurrentLibaomReference() + public void DecodeDeblockingMatchesReference() { ValidateFixture( TestImages.Heif.Av1Deblocking8BitAvif, @@ -457,11 +457,11 @@ public class Av1ReconstructionConformanceTests /// /// Verifies active CDEF syntax, strength selection, unit traversal, subsampling, frame edges, and final native - /// samples against scalar libaom for independently encoded eight-, ten-, and twelve-bit still-picture streams + /// samples against the independent scalar reference for independently encoded eight-, ten-, and twelve-bit still-picture streams /// under normal SIMD dispatch and with hardware intrinsics disabled. /// [Fact] - public void DecodeWithActiveCdefMatchesCurrentLibaomReference() + public void DecodeCdefNativeMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateActiveCdefFixtures, ReconstructionConfigurations); /// @@ -476,7 +476,7 @@ public class Av1ReconstructionConformanceTests [WithFile(TestImages.Heif.Av1Cdef8BitAvif, PixelTypes.Rgba32, 768, 512, HeifBitDepth.Bit8)] [WithFile(TestImages.Heif.Av1Cdef10BitAvif, PixelTypes.Rgba32, 1024, 428, HeifBitDepth.Bit10)] [WithFile(TestImages.Heif.Av1Cdef12BitAvif, PixelTypes.Rgba32, 1024, 428, HeifBitDepth.Bit12)] - public void DecodeWithActiveCdefMatchesPinnedLibavifPresentation( + public void DecodeCdefMatchesReference( TestImageProvider provider, int width, int height, @@ -495,7 +495,7 @@ public class Av1ReconstructionConformanceTests /// supported by AVIF across every available vector width and the scalar fallback. /// [Fact] - public void DecodeProfileMatrixMatchesPinnedLibaomReference() + public void DecodeProfileMatrixNativeMatchesReference() => ValidateProfileNativeFixtures(); /// @@ -503,7 +503,7 @@ public class Av1ReconstructionConformanceTests /// under each narrower vector width and the scalar fallback. /// [Fact] - public void DecodeProfileMatrixFallbacksMatchPinnedLibaomReference() + public void DecodeProfileMatrixFallbacksMatchReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateProfileNativeFixtures, ProfileFallbackConfigurations); /// @@ -525,7 +525,7 @@ public class Av1ReconstructionConformanceTests [WithFile(TestImages.Heif.Av1Profile12Bit420Avif, PixelTypes.Rgba32, HeifBitDepth.Bit12)] [WithFile(TestImages.Heif.Av1Profile12Bit422Avif, PixelTypes.Rgba32, HeifBitDepth.Bit12)] [WithFile(TestImages.Heif.Av1Profile12Bit444Avif, PixelTypes.Rgba32, HeifBitDepth.Bit12)] - public void DecodeProfileMatrixMatchesPinnedLibavifPresentation( + public void DecodeProfileMatrixMatchesReference( TestImageProvider provider, HeifBitDepth bitDepth) { @@ -547,15 +547,15 @@ public class Av1ReconstructionConformanceTests } /// - /// Verifies decoded luma and chroma palette syntax and exact native samples against current official libaom for an - /// independently encoded AV1 still-picture stream. + /// Verifies decoded luma and chroma palette syntax and exact native samples for an independently encoded AV1 + /// still-picture stream. /// [Fact] - public void DecodeWithPaletteMatchesCurrentLibaomReference() + public void DecodePaletteMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidatePaletteNativeFixture, PaletteConfigurations); /// - /// Verifies exact palette reconstruction through segmented frame-owned map storage and tracked disposal. + /// Verifies exact palette reconstruction through bounded reusable superblock maps and tracked disposal. /// [Fact] [ValidateDisposedMemoryAllocations] @@ -567,40 +567,19 @@ public class Av1ReconstructionConformanceTests configuration.MemoryAllocator = allocator; byte[] payload = TestFile.Create(TestImages.Heif.Av1Palette8BitPayload).Bytes; byte[] reference = TestFile.Create(TestImages.Heif.Av1Palette8BitReference).Bytes; - bool foundSegmentedLumaMap = false; - bool foundSegmentedChromaMap = false; using (Av1Decoder decoder = new(configuration)) { + int paletteMapLength = 1 << Av1Constants.MaxSuperBlockSizeLog2; + int expectedPaletteAllocationCount = (2 * paletteMapLength * paletteMapLength) / allocator.BufferCapacityInBytes; + Assert.Equal(expectedPaletteAllocationCount, allocator.AllocationLog.Count); + int finalPaletteAllocationId = allocator.AllocationLog[^1].AllocationId; + using Av1FrameBuffer frameBuffer = decoder.DecodeFrameBuffer(payload, null, null, out _); Assert.Equal(RequiredPaletteCoverage, GetPaletteCoverage(decoder)); AssertNativePlanesEqual(decoder, frameBuffer, reference); - Assert.NotNull(decoder.FrameHeader); - Assert.NotNull(decoder.FrameInfo); - int modeInfoWidth = Av1Math.DivideLog2Ceiling(decoder.FrameHeader.FrameSize.FrameWidth, Av1Constants.ModeInfoSizeLog2); - int modeInfoHeight = Av1Math.DivideLog2Ceiling(decoder.FrameHeader.FrameSize.FrameHeight, Av1Constants.ModeInfoSizeLog2); - for (int y = 0; y < modeInfoHeight && (!foundSegmentedLumaMap || !foundSegmentedChromaMap); y++) - { - for (int x = 0; x < modeInfoWidth && (!foundSegmentedLumaMap || !foundSegmentedChromaMap); x++) - { - Av1BlockModeInfo modeInfo = decoder.FrameInfo.GetModeInfoAt(new Point(x, y)); - if (!foundSegmentedLumaMap && modeInfo.GetPaletteSize(Av1PlaneType.Y) != 0) - { - Buffer2DRegion map = modeInfo.GetPaletteColorIndexMap(Av1Plane.Y); - foundSegmentedLumaMap = map.Buffer.MemoryGroup.Count > 1; - } - - if (!foundSegmentedChromaMap && modeInfo.GetPaletteSize(Av1PlaneType.Uv) != 0) - { - Buffer2DRegion map = modeInfo.GetPaletteColorIndexMap(Av1Plane.U); - foundSegmentedChromaMap = map.Buffer.MemoryGroup.Count > 1; - } - } - } - - Assert.True(foundSegmentedLumaMap); - Assert.True(foundSegmentedChromaMap); + Assert.DoesNotContain(allocator.ReturnLog, returned => returned.AllocationId <= finalPaletteAllocationId); } Assert.Equal(allocator.AllocationLog.Count, allocator.ReturnLog.Count); @@ -670,7 +649,7 @@ public class Av1ReconstructionConformanceTests /// The AVIF input and matching reference-output naming context. [Theory] [WithFile(TestImages.Heif.Av1Palette8BitAvif, PixelTypes.Rgba32)] - public void DecodeWithPaletteMatchesRetainedPresentationReference(TestImageProvider provider) + public void DecodePalettePresentationMatchesReference(TestImageProvider provider) => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidatePresentedFixture, PresentationConfigurations, @@ -713,11 +692,11 @@ public class Av1ReconstructionConformanceTests } /// - /// Verifies selected intra-block-copy prediction and exact native samples against scalar libaom for an + /// Verifies selected intra-block-copy prediction and exact native samples against the independent scalar reference for an /// independently encoded AV1 still pictures across every available vector width and the scalar fallback. /// [Fact] - public void DecodeWithIntraBlockCopyMatchesPinnedLibaomReference() + public void DecodeIntraBlockCopyNativeMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateIntraBlockCopyNativeFixtures, IntraBlockCopyConfigurations); /// @@ -729,7 +708,7 @@ public class Av1ReconstructionConformanceTests [WithFile(TestImages.Heif.Av1IntraBlockCopy8BitAvif, PixelTypes.Rgba32)] [WithFile(TestImages.Heif.Av1IntraBlockCopy10BitAvif, PixelTypes.Rgba32)] [WithFile(TestImages.Heif.Av1IntraBlockCopy12BitAvif, PixelTypes.Rgba32)] - public void DecodeWithIntraBlockCopyMatchesPinnedLibavifPresentation( + public void DecodeIntraBlockCopyMatchesReference( TestImageProvider provider) => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidatePresentedFixture, @@ -743,7 +722,7 @@ public class Av1ReconstructionConformanceTests /// The AVIF input and matching reference-output naming context. [Theory] [WithFile(TestImages.Heif.Av1Progressive8BitAvif, PixelTypes.Rgba32)] - public void DecodeProgressiveSingleReferenceMatchesCurrentLibaomReferences( + public void DecodeProgressiveSingleMatchesReference( TestImageProvider provider) => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateProgressiveSingleReferenceFixtureWithDefaultConfiguration, @@ -755,7 +734,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeProgressiveSingleReferenceWithConstrainedAllocator() + public void DecodeProgressiveSingleWithConstrainedAllocator() { TestMemoryAllocator allocator = new() { BufferCapacityInBytes = 1_024 }; allocator.EnableNonThreadSafeLogging(); @@ -774,12 +753,12 @@ public class Av1ReconstructionConformanceTests /// /// Verifies that an essential lsel property returns the selected base spatial layer rather than the final - /// progressive layer, with exact current-libaom native planes and the retained exact presentation reference. + /// progressive layer, with exact reference native planes and the retained exact presentation reference. /// /// The selected-layer AVIF input and matching reference-output naming context. [Theory] [WithFile(TestImages.Heif.Av1ScaledReferenceSelectedLayerAvif, PixelTypes.Rgba32)] - public void DecodeSelectedProgressiveSpatialLayerMatchesCurrentLibaomReferences( + public void DecodeSelectedProgressiveLayerMatchesReference( TestImageProvider provider) => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateSelectedProgressiveSpatialLayerWithDefaultConfiguration, @@ -791,7 +770,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeSelectedProgressiveSpatialLayerWithConstrainedAllocator() + public void DecodeSelectedProgressiveLayerWithConstrainedAllocator() { TestMemoryAllocator allocator = new() { BufferCapacityInBytes = 1_024 }; allocator.EnableNonThreadSafeLogging(); @@ -810,12 +789,12 @@ public class Av1ReconstructionConformanceTests /// /// Verifies an independently encoded 40x40 retained layer scaled into an 80x80 dependent layer against exact - /// current-libaom native planes and the retained exact presentation reference. + /// reference native planes and the retained exact presentation reference. /// /// The AVIF input and matching reference-output naming context. [Theory] [WithFile(TestImages.Heif.Av1ScaledReferenceAvif, PixelTypes.Rgba32)] - public void DecodeScaledReferenceMatchesCurrentLibaomReferences(TestImageProvider provider) + public void DecodeScaledReferenceMatchesReference(TestImageProvider provider) => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateScaledReferenceFixtureWithDefaultConfiguration, ReconstructionConfigurations, @@ -849,7 +828,7 @@ public class Av1ReconstructionConformanceTests /// Verifies that the production dependent-frame result owns its motion-field storage until decoder disposal. /// [Fact] - public void DecodeProgressiveSingleReferenceTracksMotionFieldResultOwnership() + public void DecodeProgressiveSingleTracksMotionFieldOwnership() { TestMemoryAllocator allocator = new(); allocator.EnableNonThreadSafeLogging(); @@ -905,11 +884,11 @@ public class Av1ReconstructionConformanceTests /// /// Verifies exact native reconstruction and presentation for an image sequence that exercises equal-weight - /// compound prediction. The native reference has been reverified against current official libaom main. + /// compound prediction. The native reference has been reverified against the current AV1 reference. /// [Theory] [WithFile(TestImages.Heif.Av1AverageCompoundSequenceAvif, PixelTypes.Rgba32)] - public void DecodeRealLibavifSequenceWithEqualAverageCompoundMatchesVerifiedReferences( + public void DecodeEqualAverageCompoundMatchesReference( TestImageProvider provider) => FeatureTestRunner.RunWithHwIntrinsicsFeature( @@ -922,7 +901,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeRealLibavifSequenceWithEqualAverageCompoundUsesContiguousPlanes() + public void DecodeEqualAverageCompoundWithConstrainedAllocator() { TestMemoryAllocator allocator = new() { BufferCapacityInBytes = 1_024 }; allocator.EnableNonThreadSafeLogging(); @@ -1066,7 +1045,7 @@ public class Av1ReconstructionConformanceTests [WithFile(TestImages.Heif.Av1WedgeCompoundSequenceAvif, PixelTypes.Rgba32)] [WithFile(TestImages.Heif.Av1DifferenceWeightedCompoundSequenceAvif, PixelTypes.Rgba32)] [WithFile(TestImages.Heif.Av1InterIntraSequenceAvif, PixelTypes.Rgba32)] - public void DecodeRealLibavifSequencesWithSelectableCompoundAndInterIntraMatchesRetainedReferences( + public void DecodeSelectableCompoundMatchesReference( TestImageProvider provider) => FeatureTestRunner.RunWithHwIntrinsicsFeature( @@ -1079,7 +1058,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeRealLibavifSequencesWithSelectableCompoundAndInterIntraUseContiguousPlanes() + public void DecodeSelectableCompoundWithConstrainedAllocator() { ValidateInterPredictionSequenceWithConstrainedAllocator( TestImages.Heif.Av1DistanceWeightedCompoundSequenceAvif, @@ -1112,11 +1091,11 @@ public class Av1ReconstructionConformanceTests /// /// Verifies production OBMC reconstruction against exact native and presentation references. The native reference - /// has been reverified against current official libaom main. + /// has been reverified against the current AV1 reference. /// [Theory] [WithFile(TestImages.Heif.Av1ObmcSequenceAvif, PixelTypes.Rgba32)] - public void DecodeRealLibavifObmcSequenceMatchesVerifiedReferences(TestImageProvider provider) + public void DecodeObmcMatchesReference(TestImageProvider provider) => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateObmcSequenceWithDefaultConfiguration, ReconstructionConfigurations, @@ -1127,7 +1106,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeRealLibavifObmcSequenceUsesContiguousPlanes() + public void DecodeObmcWithConstrainedAllocator() => ValidateInterPredictionSequenceWithConstrainedAllocator( TestImages.Heif.Av1ObmcSequenceAvif, TestImages.Heif.Av1ObmcSequenceNativeReference, @@ -1136,11 +1115,11 @@ public class Av1ReconstructionConformanceTests AverageCompoundFixtureFrameCount); /// - /// Verifies production local warped-motion reconstruction against current-libaom native and retained presentation references. + /// Verifies production local warped-motion reconstruction against reference native and retained presentation references. /// [Theory] [WithFile(TestImages.Heif.Av1LocalWarpSequenceAvif, PixelTypes.Rgba32)] - public void DecodeRealLibavifLocalWarpSequenceMatchesCurrentLibaomReferences(TestImageProvider provider) + public void DecodeLocalWarpMatchesReference(TestImageProvider provider) => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateLocalWarpSequenceWithDefaultConfiguration, ReconstructionConfigurations, @@ -1151,7 +1130,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeRealLibavifLocalWarpSequenceUsesContiguousPlanes() + public void DecodeLocalWarpWithConstrainedAllocator() { TestMemoryAllocator allocator = new() { BufferCapacityInBytes = 1_024 }; allocator.EnableNonThreadSafeLogging(); @@ -1177,11 +1156,11 @@ public class Av1ReconstructionConformanceTests } /// - /// Verifies production non-translational global motion against current-libaom native and retained presentation references. + /// Verifies production non-translational global motion against reference native and retained presentation references. /// [Theory] [WithFile(TestImages.Heif.Av1GlobalWarpSequenceAvif, PixelTypes.Rgba32)] - public void DecodeRealLibavifGlobalWarpSequenceMatchesCurrentLibaomReferences(TestImageProvider provider) + public void DecodeGlobalWarpMatchesReference(TestImageProvider provider) => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateGlobalWarpSequenceWithDefaultConfiguration, ReconstructionConfigurations, @@ -1192,7 +1171,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeRealLibavifGlobalWarpSequenceUsesContiguousPlanes() + public void DecodeGlobalWarpWithConstrainedAllocator() => ValidateInterPredictionSequenceWithConstrainedAllocator( TestImages.Heif.Av1GlobalWarpSequenceAvif, TestImages.Heif.Av1GlobalWarpSequenceNativeReference, @@ -1202,10 +1181,10 @@ public class Av1ReconstructionConformanceTests /// /// Verifies every intra prediction mode and the fixture's seven transform types against the official - /// current-libaom all-intra conformance sequence and its exact native output. + /// reference all-intra conformance sequence and its exact native output. /// [Fact] - public void DecodeOfficialAllIntraSequenceMatchesCurrentLibaomReference() => ValidateOfficialAllIntraFixture(); + public void DecodeAllIntraMatchesReference() => ValidateOfficialAllIntraFixture(); /// /// Decodes every all-intra IVF sample in one session, compares each frame exactly, and records the syntax @@ -1304,31 +1283,31 @@ public class Av1ReconstructionConformanceTests } /// - /// Verifies adaptive tile and frame-end CDF updates against the official pinned-libaom sequence and exact native + /// Verifies adaptive tile and frame-end CDF updates against the official reference sequence and exact native /// output under normal and scalar dispatch. /// [Fact] - public void DecodeOfficialCdfUpdateSequenceMatchesPinnedLibaomReference() + public void DecodeCdfUpdateMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateOfficialCdfUpdateFixture, ReconstructionConfigurations); /// - /// Verifies temporal reference-motion-vector projection against the official pinned-libaom sequence and exact + /// Verifies temporal reference-motion-vector projection against the official reference sequence and exact /// native output under normal and scalar dispatch. /// [Fact] - public void DecodeOfficialMotionFieldSequenceMatchesPinnedLibaomReference() + public void DecodeMotionFieldMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateOfficialMotionFieldFixture, ReconstructionConfigurations); /// - /// Verifies extreme intra-block-copy displacement vectors against the official pinned-libaom sequence and exact + /// Verifies extreme intra-block-copy displacement vectors against the official reference sequence and exact /// native output under normal and scalar dispatch. /// [Fact] - public void DecodeOfficialIntraBlockCopySequenceMatchesPinnedLibaomReference() + public void DecodeIntraBlockCopySequenceMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateOfficialIntraBlockCopyFixture, ReconstructionConfigurations); @@ -1406,7 +1385,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeOfficialMotionFieldSequenceWithConstrainedAllocator() + public void DecodeMotionFieldWithConstrainedAllocator() { TestMemoryAllocator allocator = new() { BufferCapacityInBytes = 2_048 }; allocator.EnableNonThreadSafeLogging(); @@ -1459,11 +1438,11 @@ public class Av1ReconstructionConformanceTests } /// - /// Verifies the default operating point of an official two-spatial-layer sequence against exact pinned-libaom + /// Verifies the default operating point of an official two-spatial-layer sequence against exact reference /// native output under normal and scalar dispatch. /// [Fact] - public void DecodeOfficialTwoSpatialLayerSequenceMatchesPinnedLibaomReference() + public void DecodeTwoSpatialLayersMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateOfficialTwoSpatialLayerFixture, ReconstructionConfigurations); @@ -1473,7 +1452,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeOfficialTwoSpatialLayerSequenceWithConstrainedAllocator() + public void DecodeTwoSpatialLayersWithConstrainedAllocator() { TestMemoryAllocator allocator = new() { BufferCapacityInBytes = 8_192 }; allocator.EnableNonThreadSafeLogging(); @@ -1509,11 +1488,11 @@ public class Av1ReconstructionConformanceTests OfficialTwoSpatialLayerFixtureHeight); /// - /// Verifies the default operating point of an official two-temporal-layer sequence against exact pinned-libaom + /// Verifies the default operating point of an official two-temporal-layer sequence against exact reference /// native output under normal and scalar dispatch. /// [Fact] - public void DecodeOfficialTwoTemporalLayerSequenceMatchesPinnedLibaomReference() + public void DecodeTwoTemporalLayersMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateOfficialTwoTemporalLayerFixture, ReconstructionConfigurations); @@ -1523,7 +1502,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeOfficialTwoTemporalLayerSequenceWithConstrainedAllocator() + public void DecodeTwoTemporalLayersWithConstrainedAllocator() { TestMemoryAllocator allocator = new() { BufferCapacityInBytes = 8_192 }; allocator.EnableNonThreadSafeLogging(); @@ -1560,10 +1539,10 @@ public class Av1ReconstructionConformanceTests /// /// Verifies the default operating point of an official spatial-and-temporal-layer sequence against exact - /// pinned-libaom native output under normal and scalar dispatch. + /// reference native output under normal and scalar dispatch. /// [Fact] - public void DecodeOfficialSpatialTemporalLayerSequenceMatchesPinnedLibaomReference() + public void DecodeSpatialTemporalLayersMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateOfficialSpatialTemporalLayerFixture, ReconstructionConfigurations); @@ -1573,7 +1552,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeOfficialSpatialTemporalLayerSequenceWithConstrainedAllocator() + public void DecodeSpatialTemporalLayersWithConstrainedAllocator() { TestMemoryAllocator allocator = new() { BufferCapacityInBytes = 8_192 }; allocator.EnableNonThreadSafeLogging(); @@ -1609,11 +1588,11 @@ public class Av1ReconstructionConformanceTests OfficialSpatialTemporalLayerFixtureHeight); /// - /// Verifies active film-grain presentation and dependent-frame reconstruction against exact pinned-libaom native + /// Verifies active film-grain presentation and dependent-frame reconstruction against exact reference native /// output under normal and scalar dispatch. /// [Fact] - public void DecodeOfficialFilmGrainSequenceMatchesPinnedLibaomReference() + public void DecodeFilmGrainSequenceMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateOfficialFilmGrainFixture, ReconstructionConfigurations); @@ -1623,7 +1602,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeOfficialFilmGrainSequenceWithConstrainedAllocator() + public void DecodeFilmGrainWithConstrainedAllocator() { TestMemoryAllocator allocator = new() { BufferCapacityInBytes = 2_048 }; allocator.EnableNonThreadSafeLogging(); @@ -1660,10 +1639,10 @@ public class Av1ReconstructionConformanceTests } /// - /// Verifies the official ten-bit film-grain sequence against exact pinned-libaom native output. + /// Verifies the official ten-bit film-grain sequence against exact reference native output. /// [Fact] - public void DecodeOfficialTenBitFilmGrainSequenceMatchesPinnedLibaomReference() + public void DecodeTenBitFilmGrainSequenceMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateOfficialTenBitFilmGrainFixture, ReconstructionConfigurations); @@ -1687,11 +1666,11 @@ public class Av1ReconstructionConformanceTests } /// - /// Verifies the official eight-bit monochrome sequence against exact pinned-libaom native output under normal and + /// Verifies the official eight-bit monochrome sequence against exact reference native output under normal and /// scalar dispatch. /// [Fact] - public void DecodeOfficialMonochromeSequenceMatchesPinnedLibaomReference() + public void DecodeMonochromeSequenceMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateOfficialMonochromeFixture, ReconstructionConfigurations); @@ -1701,7 +1680,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeOfficialMonochromeSequenceWithConstrainedAllocator() + public void DecodeMonochromeWithConstrainedAllocator() { TestMemoryAllocator allocator = new() { BufferCapacityInBytes = 2_048 }; allocator.EnableNonThreadSafeLogging(); @@ -1739,10 +1718,10 @@ public class Av1ReconstructionConformanceTests Av1ColorFormat.Yuv400); /// - /// Verifies the official ten-bit monochrome sequence against exact pinned-libaom native output. + /// Verifies the official ten-bit monochrome sequence against exact reference native output. /// [Fact] - public void DecodeOfficialTenBitMonochromeSequenceMatchesPinnedLibaomReference() + public void DecodeTenBitMonochromeSequenceMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateOfficialTenBitMonochromeFixture, ReconstructionConfigurations); @@ -1766,7 +1745,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeOfficialTenBitSequencesWithConstrainedAllocator() + public void DecodeTenBitWithConstrainedAllocator() { TestMemoryAllocator allocator = new() { BufferCapacityInBytes = 2_048 }; allocator.EnableNonThreadSafeLogging(); @@ -1803,10 +1782,10 @@ public class Av1ReconstructionConformanceTests } /// - /// Verifies the official eight-bit quantizer boundaries against exact current-libaom native output. + /// Verifies the official eight-bit quantizer boundaries against exact reference native output. /// [Fact] - public void DecodeOfficialEightBitQuantizerBoundarySequencesMatchCurrentLibaomReferences() + public void DecodeEightBitQuantizerBoundariesMatchReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateOfficialEightBitQuantizerBoundaryFixtures, ReconstructionConfigurations); @@ -1818,10 +1797,10 @@ public class Av1ReconstructionConformanceTests => ValidateOfficialEightBitQuantizerBoundaryFixturesWithConfiguration(Configuration.Default); /// - /// Verifies the official ten-bit quantizer boundaries against exact current-libaom native output. + /// Verifies the official ten-bit quantizer boundaries against exact reference native output. /// [Fact] - public void DecodeOfficialTenBitQuantizerBoundarySequencesMatchCurrentLibaomReferences() + public void DecodeTenBitQuantizerBoundariesMatchReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateOfficialTenBitQuantizerBoundaryFixtures, ReconstructionConfigurations); @@ -1837,7 +1816,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeOfficialQuantizerBoundarySequencesWithConstrainedAllocator() + public void DecodeQuantizerBoundariesWithConstrainedAllocator() { TestMemoryAllocator allocator = new() { BufferCapacityInBytes = 2_560 }; allocator.EnableNonThreadSafeLogging(); @@ -1916,10 +1895,10 @@ public class Av1ReconstructionConformanceTests } /// - /// Verifies all four corners of the official frame-size matrix against exact pinned-libaom native output. + /// Verifies all four corners of the official frame-size matrix against exact reference native output. /// [Fact] - public void DecodeOfficialFrameSizeCornerSequencesMatchPinnedLibaomReferences() + public void DecodeFrameSizeCornersMatchReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateOfficialFrameSizeCornerFixtures, ReconstructionConfigurations); @@ -1935,7 +1914,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeOfficialFrameSizeCornerSequencesWithConstrainedAllocator() + public void DecodeFrameSizeCornersWithConstrainedAllocator() { TestMemoryAllocator allocator = new() { BufferCapacityInBytes = 1_024 }; allocator.EnableNonThreadSafeLogging(); @@ -2100,10 +2079,10 @@ public class Av1ReconstructionConformanceTests /// /// Verifies every ordinary inter mode, motion mode, and switchable dual-filter pair against the official - /// pinned-libaom motion-vector conformance sequence and its exact native output. + /// reference motion-vector conformance sequence and its exact native output. /// [Fact] - public void DecodeOfficialMotionVectorSequenceMatchesPinnedLibaomReference() + public void DecodeMotionVectorSequenceMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateOfficialMotionVectorFixtureWithDefaultConfiguration, ReconstructionConfigurations); @@ -2113,7 +2092,7 @@ public class Av1ReconstructionConformanceTests /// [Fact] [ValidateDisposedMemoryAllocations] - public void DecodeOfficialMotionVectorSequenceUsesContiguousPlanes() + public void DecodeMotionVectorsWithConstrainedAllocator() { TestMemoryAllocator allocator = new() { BufferCapacityInBytes = 2_048 }; allocator.EnableNonThreadSafeLogging(); @@ -2509,11 +2488,11 @@ public class Av1ReconstructionConformanceTests } /// - /// Verifies lossless syntax, residual reconstruction, and exact native samples against scalar libaom for + /// Verifies lossless syntax, residual reconstruction, and exact native samples against the independent scalar reference for /// independently encoded eight-, ten-, and twelve-bit AVIF images. /// [Fact] - public void DecodeLosslessMatchesPinnedLibaomReference() + public void DecodeLosslessNativeMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateLosslessFixtures, LosslessConfigurations); /// @@ -2526,7 +2505,7 @@ public class Av1ReconstructionConformanceTests [WithFile(TestImages.Heif.Av1Lossless8BitAvif, PixelTypes.Rgba32, HeifBitDepth.Bit8)] [WithFile(TestImages.Heif.Av1Lossless10BitAvif, PixelTypes.Rgba32, HeifBitDepth.Bit10)] [WithFile(TestImages.Heif.Av1Lossless12BitAvif, PixelTypes.Rgba32, HeifBitDepth.Bit12)] - public void DecodeLosslessMatchesPinnedLibavifPresentation( + public void DecodeLosslessMatchesReference( TestImageProvider provider, HeifBitDepth bitDepth) { @@ -2540,10 +2519,10 @@ public class Av1ReconstructionConformanceTests /// /// Verifies active normative super-resolution, chroma-width rounding, replicated edges, and exact native samples - /// against scalar libaom for independently encoded eight-, ten-, and twelve-bit still-picture streams. + /// against the independent scalar reference for independently encoded eight-, ten-, and twelve-bit still-picture streams. /// [Fact] - public void DecodeWithSuperResolutionMatchesPinnedLibaomReference() + public void DecodeSuperResolutionNativeMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateSuperResolutionFixtures, ReconstructionConfigurations); /// @@ -2558,7 +2537,7 @@ public class Av1ReconstructionConformanceTests [WithFile(TestImages.Heif.Av1SuperResolution8BitAvif, PixelTypes.Rgba32, 768, 512, HeifBitDepth.Bit8)] [WithFile(TestImages.Heif.Av1SuperResolution10BitAvif, PixelTypes.Rgba32, 1024, 428, HeifBitDepth.Bit10)] [WithFile(TestImages.Heif.Av1SuperResolution12BitAvif, PixelTypes.Rgba32, 1024, 428, HeifBitDepth.Bit12)] - public void DecodeWithSuperResolutionMatchesPinnedLibavifPresentation( + public void DecodeSuperResolutionMatchesReference( TestImageProvider provider, int width, int height, @@ -2573,18 +2552,18 @@ public class Av1ReconstructionConformanceTests } /// - /// Verifies active normative loop restoration and exact native samples against scalar libaom for independently + /// Verifies active normative loop restoration and exact native samples against the independent scalar reference for independently /// encoded eight-, ten-, and twelve-bit still-picture streams. /// [Fact] - public void DecodeWithLoopRestorationMatchesPinnedLibaomReference() + public void DecodeLoopRestorationNativeMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateLoopRestorationFixtures, LoopRestorationConfigurations); /// /// Verifies combined super-resolution and loop-restoration geometry for independently encoded 8-bit 4:2:0 content. /// [Fact] - public void DecodeWithLoopRestorationAndSuperResolutionMatchesPinnedLibaomReference8Bit420() + public void DecodeRestorationSuperResolution8Bit420MatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateLoopRestorationAndSuperResolution8Bit420, LoopRestorationConfigurations); @@ -2593,7 +2572,7 @@ public class Av1ReconstructionConformanceTests /// Verifies combined super-resolution and loop-restoration geometry for independently encoded 10-bit 4:2:2 content. /// [Fact] - public void DecodeWithLoopRestorationAndSuperResolutionMatchesPinnedLibaomReference10Bit422() + public void DecodeRestorationSuperRes10Bit422MatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateLoopRestorationAndSuperResolution10Bit422, LoopRestorationConfigurations); @@ -2602,7 +2581,7 @@ public class Av1ReconstructionConformanceTests /// Verifies combined super-resolution and loop-restoration geometry for independently encoded 12-bit 4:4:4 content. /// [Fact] - public void DecodeWithLoopRestorationAndSuperResolutionMatchesPinnedLibaomReference12Bit444() + public void DecodeRestorationSuperRes12Bit444MatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateLoopRestorationAndSuperResolution12Bit444, LoopRestorationConfigurations); @@ -2619,7 +2598,7 @@ public class Av1ReconstructionConformanceTests [WithFile(TestImages.Heif.Av1Restoration8BitAvif, PixelTypes.Rgba32, 768, 512, HeifBitDepth.Bit8)] [WithFile(TestImages.Heif.Av1Restoration10BitAvif, PixelTypes.Rgba32, 1024, 428, HeifBitDepth.Bit10)] [WithFile(TestImages.Heif.Av1Restoration12BitAvif, PixelTypes.Rgba32, 1024, 428, HeifBitDepth.Bit12)] - public void DecodeWithLoopRestorationMatchesPinnedLibavifPresentation( + public void DecodeLoopRestorationMatchesReference( TestImageProvider provider, int width, int height, @@ -2649,10 +2628,10 @@ public class Av1ReconstructionConformanceTests /// /// Verifies film-grain template generation, block selection, overlap, chroma scaling, subsampling, high-bit-depth - /// arithmetic, and exact native presentation samples against scalar libaom. + /// arithmetic, and exact native presentation samples against the independent scalar reference. /// [Fact] - public void DecodeWithFilmGrainMatchesPinnedLibaomReference() + public void DecodeFilmGrainMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateFilmGrainFixtures, LoopRestorationConfigurations); /// @@ -2763,7 +2742,7 @@ public class Av1ReconstructionConformanceTests /// Validates one independently encoded AVIF against its native Y4M reference and signaled sequence profile. /// /// The complete AVIF container. - /// The native Y4M output produced by the pinned scalar libaom-backed decoder. + /// The independently decoded native Y4M output. /// The expected AV1 sample precision. /// The expected native chroma-sampling layout. /// The AV1 profile required by the bit-depth and chroma-format combination. @@ -2912,7 +2891,7 @@ public class Av1ReconstructionConformanceTests /// Validates one independently encoded intra-block-copy AVIF against its native Y4M reference. /// /// The complete AVIF container. - /// The native Y4M output produced by the pinned scalar libaom-backed decoder. + /// The independently decoded native Y4M output. /// The expected AV1 sample precision. private static void ValidateIntraBlockCopyNativeFixture(string imagePath, string referencePath, Av1BitDepth bitDepth) { @@ -3616,7 +3595,7 @@ public class Av1ReconstructionConformanceTests /// Validates lossless frame syntax and complete native reconstruction for one AVIF image. /// /// The independently encoded AVIF container. - /// The raw planar output produced by the pinned scalar libaom decoder. + /// The independently decoded raw planar output. /// The expected AV1 sample precision. private static void ValidateLosslessFixture(string imagePath, string referencePath, Av1BitDepth bitDepth) { @@ -3688,7 +3667,7 @@ public class Av1ReconstructionConformanceTests /// Validates one independently encoded stream that activates constrained directional enhancement filtering. /// /// The AV1 elementary-stream sample. - /// The native planar output produced by the pinned scalar libaom decoder. + /// The independently decoded native planar output. /// The expected reconstructed width. /// The expected reconstructed height. /// The expected AV1 sample precision. @@ -3706,7 +3685,7 @@ public class Av1ReconstructionConformanceTests /// Validates one independently encoded stream that activates normative super-resolution. /// /// The AV1 elementary-stream sample. - /// The native planar output produced by the pinned scalar libaom decoder. + /// The independently decoded native planar output. /// The expected upscaled width. /// The expected reconstructed height. /// The expected AV1 sample precision. @@ -3732,7 +3711,7 @@ public class Av1ReconstructionConformanceTests /// Validates one independently encoded stream that activates normative loop restoration. /// /// The AV1 elementary-stream sample. - /// The native planar output produced by the pinned scalar libaom decoder. + /// The independently decoded native planar output. /// The expected reconstructed width. /// The expected reconstructed height. /// The expected AV1 sample precision. @@ -3762,7 +3741,7 @@ public class Av1ReconstructionConformanceTests /// Validates one independently encoded stream that applies film grain to the displayed samples. /// /// The AV1 elementary-stream sample. - /// The native planar output produced by the pinned scalar libaom decoder. + /// The independently decoded native planar output. /// The expected displayed width. /// The expected displayed height. /// The expected AV1 sample precision. @@ -4104,7 +4083,7 @@ public class Av1ReconstructionConformanceTests /// /// The decoder state used to identify the coded block containing a mismatch. /// The reconstructed AV1 component planes. - /// The planar Y, U, and V samples produced by the current-main libaom decoder. + /// The independently decoded planar Y, U, and V samples. /// The zero-based sequence-frame index, or -1 for a standalone sample. private static void AssertNativePlanesEqual( Av1Decoder decoder, diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReferenceFrameStoreTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReferenceFrameStoreTests.cs index 7eaa25e72..6cd438ae8 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReferenceFrameStoreTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReferenceFrameStoreTests.cs @@ -207,7 +207,7 @@ public class Av1ReferenceFrameStoreTests /// Verifies motion-field ownership across frame initialization, reference aliases, shown output, and final disposal. /// [Fact] - public void MotionFieldsFollowReferenceAliasesAndPresentationOwnership() + public void MotionFieldsFollowAliasesAndPresentationOwnership() { TestMemoryAllocator allocator = new(); allocator.EnableNonThreadSafeLogging(); diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReferenceTransform.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReferenceTransform.cs index e7cf638ed..bf461db80 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReferenceTransform.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ReferenceTransform.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; internal class Av1ReferenceTransform { /// - /// Gets the analytical amplification used by current libaom's forward-transform tests. + /// Gets the analytical amplification used by the reference decoder's forward-transform tests. /// /// The transform configuration. /// The two-dimensional transform amplification. @@ -32,7 +32,7 @@ internal class Av1ReferenceTransform } /// - /// Applies the analytical two-dimensional transform used by current libaom's + /// Applies the analytical two-dimensional transform used by the reference decoder's /// test/av1_txfm_test.cc. /// /// The raster input samples. diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ScaledInterPredictorTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ScaledInterPredictorTests.cs index 31ccf0613..04472139c 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ScaledInterPredictorTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1ScaledInterPredictorTests.cs @@ -7,7 +7,7 @@ using SixLabors.ImageSharp.Tests.TestUtilities; namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; /// -/// Verifies AV1 reference scaling and variable-phase inter convolution against current libaom arithmetic. +/// Verifies AV1 reference scaling and variable-phase inter convolution against the reference decoder arithmetic. /// [Trait("Format", "Avif")] public class Av1ScaledInterPredictorTests @@ -68,10 +68,10 @@ public class Av1ScaledInterPredictorTests private const HwIntrinsics PredictorConfigurations = HwIntrinsics.AllowAll | HwIntrinsics.DisableHWIntrinsic; /// - /// Verifies current libaom's Q14 scale factors, Q10 steps, and signed coordinate rounding. + /// Verifies the reference decoder's Q14 scale factors, Q10 steps, and signed coordinate rounding. /// [Fact] - public void ReferenceScaleMatchesCurrentLibaomFixedPointRules() + public void ReferenceScaleMatchesFixedPointRules() { Av1ReferenceScale downscaledReference = new(40, 24, 64, 48); @@ -101,28 +101,28 @@ public class Av1ScaledInterPredictorTests /// Verifies exact scaled 8-bit output, variable filter phases, vector tails, and untouched destination padding. /// [Fact] - public void BytePredictionMatchesCurrentLibaomOracleAcrossIntrinsicConfigurations() + public void BytePredictionMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateBytePredictions, PredictorConfigurations); /// /// Verifies exact scaled 8-, 10-, and 12-bit output under the native vector and scalar configurations. /// [Fact] - public void HighBitDepthPredictionMatchesCurrentLibaomOracleAcrossIntrinsicConfigurations() + public void HighBitDepthPredictionMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateHighBitDepthPredictions, PredictorConfigurations); /// /// Verifies exact scaled 8-bit no-round compound intermediates under native vector and scalar configurations. /// [Fact] - public void ByteCompoundPredictionMatchesCurrentLibaomOracleAcrossIntrinsicConfigurations() + public void ByteCompoundPredictionMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateByteCompoundPredictions, PredictorConfigurations); /// /// Verifies exact scaled 8-, 10-, and 12-bit no-round compound intermediates under native vector and scalar configurations. /// [Fact] - public void HighBitDepthCompoundPredictionMatchesCurrentLibaomOracleAcrossIntrinsicConfigurations() + public void HighBitDepthCompoundPredictionMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateHighBitDepthCompoundPredictions, PredictorConfigurations); /// @@ -677,7 +677,7 @@ public class Av1ScaledInterPredictorTests } /// - /// Selects one current-libaom coefficient row without reading production filter storage. + /// Selects one reference coefficient row without reading production filter storage. /// private static void FillCoefficients(Av1InterpolationFilter filter, int phase, bool reduced, Span destination) { @@ -712,7 +712,7 @@ public class Av1ScaledInterPredictorTests } /// - /// Computes libaom's bit-depth-dependent first-pass shift. + /// Computes the reference decoder's bit-depth-dependent first-pass shift. /// private static int GetRound0Bits(int bitDepth) { @@ -726,7 +726,7 @@ public class Av1ScaledInterPredictorTests private static int RoundPowerOfTwo(int value, int bits) => (value + (1 << (bits - 1))) >> bits; /// - /// Independently applies libaom's signed Q14-to-Q10 scale conversion. + /// Independently applies the reference decoder's signed Q14-to-Q10 scale conversion. /// private static int ScaleCoordinate(int value, int scale) { diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SelectableCompoundEntropyTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SelectableCompoundEntropyTests.cs index fe9108442..ad67d9365 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SelectableCompoundEntropyTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SelectableCompoundEntropyTests.cs @@ -16,10 +16,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; public class Av1SelectableCompoundEntropyTests { /// - /// Verifies representative and complete multi-symbol defaults against pinned libaom's forward Q15 tables. + /// Verifies representative and complete multi-symbol defaults against the reference decoder's forward Q15 tables. /// [Fact] - public void DefaultsMatchPinnedLibaom() + public void DefaultsMatchReference() { AssertForwardThresholds(Av1DefaultDistributions.InterIntraMode[1], [1875, 11082, 27332]); AssertForwardThresholds(Av1DefaultDistributions.WedgeInterIntra[(int)Av1BlockSize.Block8x8], [20036]); diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SelfGuidedFilterTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SelfGuidedFilterTests.cs index fc882d89a..44b874bc0 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SelfGuidedFilterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SelfGuidedFilterTests.cs @@ -71,7 +71,7 @@ public class Av1SelfGuidedFilterTests /// Verifies every normative parameter set, sample precision, and processing-unit tail against the direct-window definition. /// [Fact] - public void FilterMatchesDirectWindowDefinitionAcrossIntrinsicWidths() + public void FilterMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateFilters, Configurations); /// diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SingleReferenceEntropyTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SingleReferenceEntropyTests.cs index 9e8908761..3eb5cb053 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SingleReferenceEntropyTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SingleReferenceEntropyTests.cs @@ -15,10 +15,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; public class Av1SingleReferenceEntropyTests { /// - /// Verifies all eighteen normative single-reference distributions against libaom's forward Q15 defaults. + /// Verifies all eighteen normative single-reference distributions against the reference decoder's forward Q15 defaults. /// [Fact] - public void SingleReferenceDefaultsMatchLibaom() + public void SingleReferenceDefaultsMatchReference() { uint[][] forwardThresholds = [ @@ -46,10 +46,10 @@ public class Av1SingleReferenceEntropyTests } /// - /// Verifies the five normative block reference-mode distributions against libaom's forward Q15 defaults. + /// Verifies the five normative block reference-mode distributions against the reference decoder's forward Q15 defaults. /// [Fact] - public void CompInterDefaultsMatchLibaom() + public void CompInterDefaultsMatchReference() { uint[] forwardThresholds = [26828, 24035, 12031, 10640, 2901]; Av1Distribution[] distributions = Av1DefaultDistributions.CompInter; @@ -125,7 +125,7 @@ public class Av1SingleReferenceEntropyTests /// Verifies one-pass neighbor collection, compound-neighbor votes, clearing, and intra-neighbor exclusion. /// [Fact] - public void CollectNeighborReferenceCountsMatchesLibaom() + public void CollectNeighborReferenceCountsMatchesReference() { Av1BlockModeInfo above = CreateModeInfo(Av1ReferenceFrameType.Last, Av1ReferenceFrameType.None); Av1BlockModeInfo left = CreateModeInfo(Av1ReferenceFrameType.Backward, Av1ReferenceFrameType.Alternate); @@ -152,10 +152,10 @@ public class Av1SingleReferenceEntropyTests } /// - /// Verifies that the six context functions aggregate the exact reference groups used by libaom. + /// Verifies that the six context functions aggregate the exact reference groups used by the reference decoder. /// [Fact] - public void SingleReferenceContextsAggregateNormativeReferenceGroups() + public void ContextsAggregateReferenceGroups() { InlineArray8 referenceCountStorage = default; Span referenceCounts = referenceCountStorage; @@ -176,10 +176,10 @@ public class Av1SingleReferenceEntropyTests } /// - /// Verifies every branch of libaom's five-state single-versus-compound reference-mode context. + /// Verifies every branch of the reference decoder's five-state single-versus-compound reference-mode context. /// [Fact] - public void ReferenceModeContextMatchesLibaom() + public void ReferenceModeContextMatchesReference() { Av1BlockModeInfo singleForward = CreateModeInfo(Av1ReferenceFrameType.Last, Av1ReferenceFrameType.None); Av1BlockModeInfo singleBackward = CreateModeInfo(Av1ReferenceFrameType.Backward, Av1ReferenceFrameType.None); @@ -226,7 +226,7 @@ public class Av1SingleReferenceEntropyTests /// Verifies that frame-context copies retain reference-selection adaptation without sharing mutable distributions. /// [Fact] - public void FrameEntropyCopyRetainsIndependentReferenceSelectionState() + public void EntropyCopyRetainsReferenceSelectionState() { Av1FrameEntropyContext source = new(0); Av1FrameEntropyContext destination = new(0); @@ -249,7 +249,7 @@ public class Av1SingleReferenceEntropyTests /// Verifies that publishing frame state resets the reference-selection distributions' update-rate history. /// [Fact] - public void FrameEntropySnapshotResetsReferenceSelectionUpdateCounts() + public void EntropySnapshotResetsReferenceSelectionCounts() { const int updateCount = 20; Av1FrameEntropyContext source = new(0); diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SymbolContextTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SymbolContextTests.cs index cfb812210..e026aa3b8 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SymbolContextTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1SymbolContextTests.cs @@ -79,7 +79,7 @@ public class Av1SymbolContextTests } /// - /// SVT: get_lower_levels_ctx_eob + /// Computes the expected lower-level coefficient context at the end of a transform block. /// internal static int GetExpectedLowerLevelContextEndOfBlock(int blockWidthLog2, int height, int scanIndex) { diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1TemporalSegmentationTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1TemporalSegmentationTests.cs index e3237ede2..97c87bf6e 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1TemporalSegmentationTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1TemporalSegmentationTests.cs @@ -12,7 +12,7 @@ using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; /// -/// Verifies AV1 temporal segment-map prediction against libaom's decoder rules. +/// Verifies AV1 temporal segment-map prediction against independent decoder results. /// [Trait("Format", "Avif")] public class Av1TemporalSegmentationTests @@ -189,7 +189,7 @@ public class Av1TemporalSegmentationTests /// Verifies that a skipped inter block uses the spatial predictor without reading a temporal-prediction symbol. /// [Fact] - public void SkippedInterBlockClearsTemporalPredictionAndUsesSpatialSegment() + public void SkippedInterUsesSpatialSegment() { ObuSequenceHeader sequenceHeader = CreateSequenceHeader(64, 64); ObuFrameHeader frameHeader = CreateFrameHeader(16, 16, segmentationUpdateMap: 1, segmentationTemporalUpdate: 1); diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1TilingTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1TilingTests.cs index 3f9221aa4..ce1cbb48b 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1TilingTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1TilingTests.cs @@ -35,10 +35,10 @@ public class Av1TilingTests } /// - /// Verifies the decoded block geometry and prediction modes against libaom inspection output for a real AVIF image item. + /// Verifies the decoded block geometry and prediction modes against the reference decoder inspection output for a real AVIF image item. /// [Fact] - public void ParsedRealAvifModeMapMatchesLibaom() + public void ParsedAvifModeMapMatchesReference() { string filePath = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Heif.ParisIccExifXmpAvif); byte[] content = File.ReadAllBytes(filePath); @@ -63,7 +63,7 @@ public class Av1TilingTests } } - // These counts come from the 102 by 76 mode-info maps emitted by libaom 3.14.1's inspect tool. + // These counts come from independently inspected 102 by 76 mode-info maps. int[] expectedBlockSizeCounts = new int[(int)Av1BlockSize.AllSizes]; expectedBlockSizeCounts[(int)Av1BlockSize.Block8x8] = 3176; expectedBlockSizeCounts[(int)Av1BlockSize.Block8x16] = 48; diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1WarpedInterPredictorTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1WarpedInterPredictorTests.cs index ae190e285..d251b7265 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1WarpedInterPredictorTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1WarpedInterPredictorTests.cs @@ -21,21 +21,21 @@ public class Av1WarpedInterPredictorTests HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX512F | HwIntrinsics.DisableAVX | HwIntrinsics.DisableHWIntrinsic; /// - /// Verifies exact 8-bit native and compound prediction against the current libaom scalar equations. + /// Verifies exact 8-bit native and compound prediction against independent scalar equations. /// [Fact] - public void ByteNativeAndCompoundPredictionMatchesCurrentLibaomOracleAcrossIntrinsicConfigurations() + public void BytePredictionMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateBytePrediction, PredictorConfigurations); /// - /// Verifies exact 8-, 10-, and 12-bit native and compound prediction against the current libaom scalar equations. + /// Verifies exact 8-, 10-, and 12-bit native and compound prediction against independent scalar equations. /// [Fact] - public void HighBitDepthNativeAndCompoundPredictionMatchesCurrentLibaomOracleAcrossIntrinsicConfigurations() + public void HighBitDepthPredictionMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature(ValidateHighBitDepthPrediction, PredictorConfigurations); /// - /// Applies the current-libaom multi-sample affine model to deterministic byte storage. + /// Applies the reference multi-sample affine model to deterministic byte storage. /// private static void ValidateBytePrediction() { @@ -54,7 +54,7 @@ public class Av1WarpedInterPredictorTests } } - Av1GlobalMotionParameters parameters = CreateCurrentLibaomParameters(); + Av1GlobalMotionParameters parameters = CreateReferenceParameters(); for (int subsampling = 0; subsampling <= 1; subsampling++) { byte[] expected = new byte[destinationStride * height]; @@ -64,7 +64,7 @@ public class Av1WarpedInterPredictorTests short[] actualScratch = new short[Av1WarpedInterPredictor.WarpedScratchLength]; Point destinationPosition = subsampling == 0 ? new Point(32, 24) : new Point(16, 12); - PredictCurrentLibaomReference( + PredictReference( source, sourceStride, new Point(padding, padding), @@ -104,7 +104,7 @@ public class Av1WarpedInterPredictorTests Array.Fill(expectedCompound, (ushort)0xDEAD); Array.Fill(actualCompound, (ushort)0xDEAD); - PredictCurrentLibaomReference( + PredictReference( source, sourceStride, new Point(padding, padding), @@ -142,7 +142,7 @@ public class Av1WarpedInterPredictorTests } /// - /// Applies the current-libaom multi-sample affine model to every supported high-bit-depth precision. + /// Applies the multi-sample affine model to every supported high-bit-depth precision. /// private static void ValidateHighBitDepthPrediction() { @@ -152,7 +152,7 @@ public class Av1WarpedInterPredictorTests const int width = 13; const int height = 11; const int destinationStride = width + 7; - Av1GlobalMotionParameters parameters = CreateCurrentLibaomParameters(); + Av1GlobalMotionParameters parameters = CreateReferenceParameters(); foreach (int bitDepth in new[] { 8, 10, 12 }) { int maximum = (1 << bitDepth) - 1; @@ -175,7 +175,7 @@ public class Av1WarpedInterPredictorTests short[] actualScratch = new short[Av1WarpedInterPredictor.WarpedScratchLength]; Point destinationPosition = subsampling == 0 ? new Point(32, 24) : new Point(16, 12); - PredictCurrentLibaomReference( + PredictReference( source, sourceStride, new Point(padding, padding), @@ -216,7 +216,7 @@ public class Av1WarpedInterPredictorTests Array.Fill(expectedCompound, (ushort)0xDEAD); Array.Fill(actualCompound, (ushort)0xDEAD); - PredictCurrentLibaomReference( + PredictReference( source, sourceStride, new Point(padding, padding), @@ -256,9 +256,9 @@ public class Av1WarpedInterPredictorTests } /// - /// Reconstructs one warped block by directly transcribing current libaom's scalar affine loops. + /// Reconstructs one warped block with scalar affine loops. /// - private static void PredictCurrentLibaomReference( + private static void PredictReference( ReadOnlySpan source, int sourceStride, Point sourceOrigin, @@ -285,7 +285,7 @@ public class Av1WarpedInterPredictorTests const int pixelPrecisionShifts = 64; Span intermediate = stackalloc int[15 * tileSize]; - // Current libaom raises round0 by two for 12-bit sources so the biased horizontal intermediate + // The reference decoder raises round0 by two for 12-bit sources so the biased horizontal intermediate // remains representable in 16 bits, then removes those two bits from the vertical rounding. int intermediateRange = bitDepth + filterBits - 3 + 2; int round0 = 3 + Math.Max(intermediateRange - 16, 0); @@ -334,7 +334,7 @@ public class Av1WarpedInterPredictorTests ((sourceOrigin.Y + sourceY) * sourceStride) + sourceOrigin.X + sampleX; int sample = int.CreateChecked(source[sourceIndex]); - sum += sample * CurrentLibaomWarpedFilter[coefficientOffset + tap]; + sum += sample * ReferenceWarpedFilter[coefficientOffset + tap]; } intermediate[((row + 7) * tileSize) + column + 4] = RoundPowerOfTwo(sum, round0); @@ -355,7 +355,7 @@ public class Av1WarpedInterPredictorTests for (int tap = 0; tap < filterTaps; tap++) { int intermediateIndex = ((row + tap + 4) * tileSize) + column + 4; - sum += intermediate[intermediateIndex] * CurrentLibaomWarpedFilter[coefficientOffset + tap]; + sum += intermediate[intermediateIndex] * ReferenceWarpedFilter[coefficientOffset + tap]; } int value = RoundPowerOfTwo(sum, verticalRound); @@ -381,9 +381,9 @@ public class Av1WarpedInterPredictorTests } /// - /// Gets the 193 current-libaom eight-tap warped-filter phases used by the independent scalar oracle. + /// Gets the 193 reference eight-tap warped-filter phases used by the independent scalar oracle. /// - private static ReadOnlySpan CurrentLibaomWarpedFilter => + private static ReadOnlySpan ReferenceWarpedFilter => [ 0, 0, 127, 1, 0, 0, 0, 0, 0, -1, 127, 2, 0, 0, 0, 0, @@ -581,15 +581,15 @@ public class Av1WarpedInterPredictorTests ]; /// - /// Divides a signed fixed-point value by a power of two with current libaom's rounding. + /// Divides a signed fixed-point value by a power of two with the reference decoder's rounding. /// private static int RoundPowerOfTwo(int value, int bitCount) => (value + (1 << (bitCount - 1))) >> bitCount; /// - /// Creates one nontrivial affine model traced from the current-libaom-verified two-frame local-warp fixture. + /// Creates one nontrivial affine model traced from the independently verified two-frame local-warp fixture. /// - private static Av1GlobalMotionParameters CreateCurrentLibaomParameters() + private static Av1GlobalMotionParameters CreateReferenceParameters() { Av1GlobalMotionParameters parameters = Av1GlobalMotionParameters.Identity; parameters.Type = Av1GlobalMotionType.Affine; diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1YuvConverterTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1YuvConverterTests.cs index 704230f40..e54ff09b9 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1YuvConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/Av1YuvConverterTests.cs @@ -264,7 +264,7 @@ public class Av1YuvConverterTests /// available intrinsic width and the scalar fallback. /// [Fact] - public void ScaleSelectedSpatialLayerMatchesPinnedLibyuvAcrossIntrinsicWidths() + public void ScaleSelectedSpatialLayerMatchesReference() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateSelectedSpatialLayerScaling, AlphaConfigurations); @@ -749,7 +749,7 @@ public class Av1YuvConverterTests [InlineData(Av1BitDepth.EightBit, ObuMatrixCoefficients.YCgCoRo, 31, 65, 255)] [InlineData(Av1BitDepth.TenBit, ObuMatrixCoefficients.YCgCoRo, 127, 257, 1023)] [InlineData(Av1BitDepth.TwelveBit, ObuMatrixCoefficients.YCgCoRo, 511, 1025, 4095)] - public void ReversibleYCgCoMatchesKnownPureRedValuesInBothDirections( + public void ReversibleYCgCoMatchesPureRed( int bitDepth, int matrixCoefficients, int expectedY, @@ -1028,7 +1028,7 @@ public class Av1YuvConverterTests /// without hardware intrinsics. /// [Fact] - public void ComposeAlphaMapsEightBitLumaExactlyAcrossIntrinsicWidths() + public void ComposeAlphaMapsEightBitLumaExactly() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateEightBitAlphaComposition, AlphaConfigurations); @@ -1038,7 +1038,7 @@ public class Av1YuvConverterTests /// with and without hardware intrinsics. /// [Fact] - public void ComposeAlphaScalesHighBitDepthLumaAcrossIntrinsicWidths() + public void ComposeAlphaScalesHighBitDepthLuma() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateHighBitDepthAlphaScaling, AlphaConfigurations); @@ -1057,7 +1057,7 @@ public class Av1YuvConverterTests /// Verifies exact limited-range endpoints and out-of-range clamping for every supported AV1 alpha bit depth. /// [Fact] - public void ComposeAlphaExpandsLimitedRangeAcrossIntrinsicWidths() + public void ComposeAlphaExpandsLimitedRange() => FeatureTestRunner.RunWithHwIntrinsicsFeature( ValidateLimitedRangeAlphaComposition, AlphaConfigurations); diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/ObuFrameHeaderTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/ObuFrameHeaderTests.cs index 3717fade6..b2fdc0759 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/ObuFrameHeaderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/ObuFrameHeaderTests.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; public class ObuFrameHeaderTests { /// - /// Identifies one current-libaom sequence-header conformance condition used by the malformed-input theory. + /// Identifies one reference sequence-header conformance condition used by the malformed-input theory. /// public enum InvalidSequenceHeaderCase { @@ -258,7 +258,7 @@ public class ObuFrameHeaderTests } /// - /// Verifies current-libaom sequence-header conformance failures through the complete bounded OBU parser. + /// Verifies reference sequence-header conformance failures through the complete bounded OBU parser. /// /// The single invalid syntax condition encoded into an otherwise valid sequence header. [Theory] @@ -270,7 +270,7 @@ public class ObuFrameHeaderTests [InlineData(InvalidSequenceHeaderCase.OverflowingTicksPerPicture)] [InlineData(InvalidSequenceHeaderCase.MainProfileSrgbIdentity)] [InlineData(InvalidSequenceHeaderCase.SubsampledIdentityMatrix)] - public void ReadSequenceHeaderRejectsCurrentLibaomConformanceFailure(InvalidSequenceHeaderCase invalidCase) + public void ReadSequenceHeaderRejectsConformanceFailure(InvalidSequenceHeaderCase invalidCase) { byte[] bitStream = CreateNonReducedSequenceHeaderObu(invalidCase); @@ -313,10 +313,10 @@ public class ObuFrameHeaderTests } /// - /// Verifies that metadata-type LEB128 values obey current libaom's shared unsigned 32-bit limit. + /// Verifies that metadata-type LEB128 values obey the reference decoder's shared unsigned 32-bit limit. /// [Fact] - public void ValidateItemDataRejectsMetadataTypeAboveCurrentLibaomLimit() + public void ValidateItemDataRejectsMetadataTypeAboveLimit() { byte[] bitStream = [ @@ -425,7 +425,7 @@ public class ObuFrameHeaderTests /// Verifies that the reduced sequence syntax cannot be used without declaring a still picture. /// [Fact] - public void ReadReducedHeaderWithoutStillPictureThrowsInvalidImageContent() + public void ReducedHeaderWithoutStillPictureThrows() { const int sequenceHeaderPayloadOffset = 2; byte[] bitStream = [.. DefaultSequenceHeaderBitStream]; @@ -445,7 +445,7 @@ public class ObuFrameHeaderTests [InlineData(0b1000_0000)] // show_existing_frame = 1 [InlineData(0b0101_0000)] // frame_type = INTRA_ONLY_FRAME, show_frame = 1 [InlineData(0b0000_0000)] // frame_type = KEY_FRAME, show_frame = 0 - public void ReadInvalidStillPictureFramePrefixThrowsInvalidImageContent(int invalidFramePrefix) + public void InvalidStillPicturePrefixThrows(int invalidFramePrefix) { ObuSequenceHeader sequenceHeader = GetDefaultSequenceHeader(); sequenceHeader.IsReducedStillPictureHeader = false; @@ -513,7 +513,7 @@ public class ObuFrameHeaderTests } /// - /// Verifies current libaom's doubled minimum inner-tile width for a super-resolution-scaled frame. + /// Verifies the reference decoder's doubled minimum inner-tile width for a super-resolution-scaled frame. /// [Fact] public void ReadTileInfoRejectsNarrowSuperResolutionInnerTile() @@ -693,7 +693,7 @@ public class ObuFrameHeaderTests writer.WriteBoolean(overflowingTicksPerPicture); if (overflowingTicksPerPicture) { - // Thirty-two leading zeros are the UVLC sentinel which current libaom rejects as UINT32_MAX. + // Thirty-two leading zeros are the UVLC sentinel which the reference decoder rejects as UINT32_MAX. writer.WriteLiteral(0U, 32); } diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/ObuFrameLifecycleTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/ObuFrameLifecycleTests.cs index bdb1d4630..442e58a55 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/ObuFrameLifecycleTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/ObuFrameLifecycleTests.cs @@ -96,7 +96,7 @@ public class ObuFrameLifecycleTests /// Verifies that invalid trailing data in a subsequent sequence header is rejected before that sequence can create frame state. /// [Fact] - public void ReadAllRejectsMalformedSubsequentSequenceBeforeCreatingItsFrameReader() + public void RejectsMalformedFollowingSequenceBeforeFrameReader() { byte[] firstLayer = ProgressiveTwoFrameObuStream[..FirstProgressiveLayerLength].ToArray(); byte[] malformedSequence = AddInvalidSequenceHeaderTrailingByte(ProgressiveTwoFrameObuStream[..ProgressiveSequencePrefixLength].ToArray()); @@ -148,7 +148,7 @@ public class ObuFrameLifecycleTests /// Verifies that malformed data after a completed real frame invalidates retained state without preventing reuse of the parser. /// [Fact] - public void ReadAllClearsCompletedFrameStateWhenFollowingObuHeaderIsInvalid() + public void ClearsCompletedFrameStateAfterInvalidObuHeader() { byte[] bitStream = [.. ProgressiveTwoFrameObuStream[..FirstProgressiveLayerLength], ForbiddenObuHeader]; using Av1ReferenceFrameStore referenceFrames = new(); @@ -176,7 +176,7 @@ public class ObuFrameLifecycleTests [ .. ProgressiveTwoFrameObuStream[..FirstProgressiveLayerLength], - // A one-byte combined-frame payload selecting retained slot zero. Current libaom rejects this form + // A one-byte combined-frame payload selecting retained slot zero. The reference decoder rejects this form // because show_existing_frame is permitted only in a standalone frame-header OBU. 0x32, 0x01, 0x80 ]; diff --git a/tests/ImageSharp.Tests/Formats/Heif/Av1/ObuSkipModeParametersTests.cs b/tests/ImageSharp.Tests/Formats/Heif/Av1/ObuSkipModeParametersTests.cs index 0511b615a..b5de74558 100644 --- a/tests/ImageSharp.Tests/Formats/Heif/Av1/ObuSkipModeParametersTests.cs +++ b/tests/ImageSharp.Tests/Formats/Heif/Av1/ObuSkipModeParametersTests.cs @@ -116,7 +116,7 @@ public class ObuSkipModeParametersTests /// Verifies that a forward-only frame selects the two closest distinct past reference orders. /// [Fact] - public void DeriveSelectsTwoNearestForwardReferencesWhenNoBackwardReferenceExists() + public void SelectsTwoForwardReferencesWithoutBackwardReference() { ObuOrderHintInfo orderHintInfo = CreateOrderHintInfo(); ObuFrameHeader frameHeader = CreateInterFrame(8, [7, 3, 6, 2, 1, 5, 4]); diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 4b798a2c7..5e038be9a 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -1292,13 +1292,13 @@ public static class TestImages public const string ParisIccExifXmpAvif = "Heif/paris_icc_exif_xmp.avif"; public const string ParisIccExifXmpPng = "Heif/paris_icc_exif_xmp.png"; - // Independently encoded from Png.Icc.Perceptual with libavif 1.4.2 and libaom 3.14.1. Unlike the + // Independently encoded from Png.Icc.Perceptual. Unlike the // canonical-sRGB Paris profile, this perceptual profile requires an observable color conversion. public const string PerceptualIccAvif = "Heif/perceptual_icc.avif"; public const string PerceptualIccGridAvif = "Heif/perceptual_icc_grid.avif"; public const string PerceptualIccSequenceAvif = "Heif/perceptual_icc_sequence.avif"; - // Independently encoded from Png.Ducky with libavif 1.4.2 and libaom 3.14.1. The ROMM RGB profile is + // Independently encoded from Png.Ducky. The ROMM RGB profile is // deliberately non-sRGB so that color conversion is observable while the auxiliary alpha item is composed. public const string DuckyRommIccAlphaAvif = "Heif/ducky_romm_icc_alpha.avif"; diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithActiveCdefMatchesPinnedLibavifPresentation_Rgba32_libavif-cdef-cosmos-10b.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeCdefMatchesReference_Rgba32_libavif-cdef-cosmos-10b.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithActiveCdefMatchesPinnedLibavifPresentation_Rgba32_libavif-cdef-cosmos-10b.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeCdefMatchesReference_Rgba32_libavif-cdef-cosmos-10b.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithActiveCdefMatchesPinnedLibavifPresentation_Rgba32_libavif-cdef-cosmos-12b.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeCdefMatchesReference_Rgba32_libavif-cdef-cosmos-12b.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithActiveCdefMatchesPinnedLibavifPresentation_Rgba32_libavif-cdef-cosmos-12b.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeCdefMatchesReference_Rgba32_libavif-cdef-cosmos-12b.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithActiveCdefMatchesPinnedLibavifPresentation_Rgba32_libavif-cdef-kodim23-8b.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeCdefMatchesReference_Rgba32_libavif-cdef-kodim23-8b.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithActiveCdefMatchesPinnedLibavifPresentation_Rgba32_libavif-cdef-kodim23-8b.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeCdefMatchesReference_Rgba32_libavif-cdef-kodim23-8b.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifSequenceWithEqualAverageCompoundMatchesVerifiedReferences_Rgba32_libavif-webp-logo-average-compound.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeEqualAverageCompoundMatchesReference_Rgba32_libavif-webp-logo-average-compound.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifSequenceWithEqualAverageCompoundMatchesVerifiedReferences_Rgba32_libavif-webp-logo-average-compound.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeEqualAverageCompoundMatchesReference_Rgba32_libavif-webp-logo-average-compound.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifGlobalWarpSequenceMatchesCurrentLibaomReferences_Rgba32_libavif-rotating-grid-global-warp.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeGlobalWarpMatchesReference_Rgba32_libavif-rotating-grid-global-warp.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifGlobalWarpSequenceMatchesCurrentLibaomReferences_Rgba32_libavif-rotating-grid-global-warp.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeGlobalWarpMatchesReference_Rgba32_libavif-rotating-grid-global-warp.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithIntraBlockCopyMatchesPinnedLibavifPresentation_Rgba32_libavif-intrabc-abc-10b-444.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeIntraBlockCopyMatchesReference_Rgba32_libavif-intrabc-abc-10b-444.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithIntraBlockCopyMatchesPinnedLibavifPresentation_Rgba32_libavif-intrabc-abc-10b-444.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeIntraBlockCopyMatchesReference_Rgba32_libavif-intrabc-abc-10b-444.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithIntraBlockCopyMatchesPinnedLibavifPresentation_Rgba32_libavif-intrabc-abc-12b-444.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeIntraBlockCopyMatchesReference_Rgba32_libavif-intrabc-abc-12b-444.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithIntraBlockCopyMatchesPinnedLibavifPresentation_Rgba32_libavif-intrabc-abc-12b-444.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeIntraBlockCopyMatchesReference_Rgba32_libavif-intrabc-abc-12b-444.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithIntraBlockCopyMatchesPinnedLibavifPresentation_Rgba32_libavif-intrabc-abc-8b-444.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeIntraBlockCopyMatchesReference_Rgba32_libavif-intrabc-abc-8b-444.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithIntraBlockCopyMatchesPinnedLibavifPresentation_Rgba32_libavif-intrabc-abc-8b-444.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeIntraBlockCopyMatchesReference_Rgba32_libavif-intrabc-abc-8b-444.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifLocalWarpSequenceMatchesCurrentLibaomReferences_Rgba32_libavif-rotating-grid-local-warp.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLocalWarpMatchesReference_Rgba32_libavif-rotating-grid-local-warp.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifLocalWarpSequenceMatchesCurrentLibaomReferences_Rgba32_libavif-rotating-grid-local-warp.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLocalWarpMatchesReference_Rgba32_libavif-rotating-grid-local-warp.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithLoopRestorationMatchesPinnedLibavifPresentation_Rgba32_libavif-restoration-cosmos-10b.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLoopRestorationMatchesReference_Rgba32_libavif-restoration-cosmos-10b.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithLoopRestorationMatchesPinnedLibavifPresentation_Rgba32_libavif-restoration-cosmos-10b.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLoopRestorationMatchesReference_Rgba32_libavif-restoration-cosmos-10b.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithLoopRestorationMatchesPinnedLibavifPresentation_Rgba32_libavif-restoration-cosmos-12b.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLoopRestorationMatchesReference_Rgba32_libavif-restoration-cosmos-12b.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithLoopRestorationMatchesPinnedLibavifPresentation_Rgba32_libavif-restoration-cosmos-12b.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLoopRestorationMatchesReference_Rgba32_libavif-restoration-cosmos-12b.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithLoopRestorationMatchesPinnedLibavifPresentation_Rgba32_libavif-restoration-kodim23-8b.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLoopRestorationMatchesReference_Rgba32_libavif-restoration-kodim23-8b.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithLoopRestorationMatchesPinnedLibavifPresentation_Rgba32_libavif-restoration-kodim23-8b.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLoopRestorationMatchesReference_Rgba32_libavif-restoration-kodim23-8b.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLosslessMatchesPinnedLibavifPresentation_Rgba32_libavif-lossless-circle-10b-444.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLosslessMatchesReference_Rgba32_libavif-lossless-circle-10b-444.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLosslessMatchesPinnedLibavifPresentation_Rgba32_libavif-lossless-circle-10b-444.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLosslessMatchesReference_Rgba32_libavif-lossless-circle-10b-444.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLosslessMatchesPinnedLibavifPresentation_Rgba32_libavif-lossless-circle-12b-444.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLosslessMatchesReference_Rgba32_libavif-lossless-circle-12b-444.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLosslessMatchesPinnedLibavifPresentation_Rgba32_libavif-lossless-circle-12b-444.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLosslessMatchesReference_Rgba32_libavif-lossless-circle-12b-444.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLosslessMatchesPinnedLibavifPresentation_Rgba32_libavif-lossless-circle-8b-444.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLosslessMatchesReference_Rgba32_libavif-lossless-circle-8b-444.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLosslessMatchesPinnedLibavifPresentation_Rgba32_libavif-lossless-circle-8b-444.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeLosslessMatchesReference_Rgba32_libavif-lossless-circle-8b-444.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifObmcSequenceMatchesVerifiedReferences_Rgba32_libavif-webp-logo-obmc.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeObmcMatchesReference_Rgba32_libavif-webp-logo-obmc.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifObmcSequenceMatchesVerifiedReferences_Rgba32_libavif-webp-logo-obmc.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeObmcMatchesReference_Rgba32_libavif-webp-logo-obmc.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithPaletteMatchesRetainedPresentationReference_Rgba32_libavif-palette-draw-points-8b.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodePalettePresentationMatchesReference_Rgba32_libavif-palette-draw-points-8b.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithPaletteMatchesRetainedPresentationReference_Rgba32_libavif-palette-draw-points-8b.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodePalettePresentationMatchesReference_Rgba32_libavif-palette-draw-points-8b.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-10b-400.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-10b-400.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-10b-400.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-10b-400.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-10b-420.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-10b-420.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-10b-420.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-10b-420.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-10b-422.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-10b-422.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-10b-422.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-10b-422.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-10b-444.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-10b-444.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-10b-444.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-10b-444.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-12b-400.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-12b-400.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-12b-400.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-12b-400.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-12b-420.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-12b-420.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-12b-420.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-12b-420.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-12b-422.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-12b-422.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-12b-422.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-12b-422.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-12b-444.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-12b-444.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-12b-444.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-12b-444.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-8b-400.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-8b-400.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-8b-400.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-8b-400.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-8b-420.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-8b-420.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-8b-420.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-8b-420.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-8b-422.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-8b-422.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-8b-422.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-8b-422.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-8b-444.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-8b-444.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesPinnedLibavifPresentation_Rgba32_libavif-profile-8b-444.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProfileMatrixMatchesReference_Rgba32_libavif-profile-8b-444.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProgressiveSingleReferenceMatchesCurrentLibaomReferences_Rgba32_libavif-progressive-draw-points-8b.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProgressiveSingleMatchesReference_Rgba32_libavif-progressive-draw-points-8b.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProgressiveSingleReferenceMatchesCurrentLibaomReferences_Rgba32_libavif-progressive-draw-points-8b.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeProgressiveSingleMatchesReference_Rgba32_libavif-progressive-draw-points-8b.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeScaledReferenceMatchesCurrentLibaomReferences_Rgba32_libavif-webp-logo-scaled-reference.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeScaledReferenceMatchesReference_Rgba32_libavif-webp-logo-scaled-reference.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeScaledReferenceMatchesCurrentLibaomReferences_Rgba32_libavif-webp-logo-scaled-reference.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeScaledReferenceMatchesReference_Rgba32_libavif-webp-logo-scaled-reference.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifSequencesWithSelectableCompoundAndInterIntraMatchesRetainedReferences_Rgba32_libavif-webp-logo-difference-weighted-compound.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSelectableCompoundMatchesReference_Rgba32_libavif-webp-logo-difference-weighted-compound.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifSequencesWithSelectableCompoundAndInterIntraMatchesRetainedReferences_Rgba32_libavif-webp-logo-difference-weighted-compound.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSelectableCompoundMatchesReference_Rgba32_libavif-webp-logo-difference-weighted-compound.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifSequencesWithSelectableCompoundAndInterIntraMatchesRetainedReferences_Rgba32_libavif-webp-logo-distance-weighted-compound.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSelectableCompoundMatchesReference_Rgba32_libavif-webp-logo-distance-weighted-compound.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifSequencesWithSelectableCompoundAndInterIntraMatchesRetainedReferences_Rgba32_libavif-webp-logo-distance-weighted-compound.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSelectableCompoundMatchesReference_Rgba32_libavif-webp-logo-distance-weighted-compound.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifSequencesWithSelectableCompoundAndInterIntraMatchesRetainedReferences_Rgba32_libavif-webp-logo-inter-intra.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSelectableCompoundMatchesReference_Rgba32_libavif-webp-logo-inter-intra.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifSequencesWithSelectableCompoundAndInterIntraMatchesRetainedReferences_Rgba32_libavif-webp-logo-inter-intra.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSelectableCompoundMatchesReference_Rgba32_libavif-webp-logo-inter-intra.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifSequencesWithSelectableCompoundAndInterIntraMatchesRetainedReferences_Rgba32_libavif-webp-logo-wedge-compound.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSelectableCompoundMatchesReference_Rgba32_libavif-webp-logo-wedge-compound.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeRealLibavifSequencesWithSelectableCompoundAndInterIntraMatchesRetainedReferences_Rgba32_libavif-webp-logo-wedge-compound.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSelectableCompoundMatchesReference_Rgba32_libavif-webp-logo-wedge-compound.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSelectedProgressiveSpatialLayerMatchesCurrentLibaomReferences_Rgba32_libavif-webp-logo-scaled-reference-lsel0.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSelectedProgressiveLayerMatchesReference_Rgba32_libavif-webp-logo-scaled-reference-lsel0.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSelectedProgressiveSpatialLayerMatchesCurrentLibaomReferences_Rgba32_libavif-webp-logo-scaled-reference-lsel0.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSelectedProgressiveLayerMatchesReference_Rgba32_libavif-webp-logo-scaled-reference-lsel0.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithSuperResolutionMatchesPinnedLibavifPresentation_Rgba32_libavif-superres-cosmos-10b.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSuperResolutionMatchesReference_Rgba32_libavif-superres-cosmos-10b.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithSuperResolutionMatchesPinnedLibavifPresentation_Rgba32_libavif-superres-cosmos-10b.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSuperResolutionMatchesReference_Rgba32_libavif-superres-cosmos-10b.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithSuperResolutionMatchesPinnedLibavifPresentation_Rgba32_libavif-superres-cosmos-12b.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSuperResolutionMatchesReference_Rgba32_libavif-superres-cosmos-12b.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithSuperResolutionMatchesPinnedLibavifPresentation_Rgba32_libavif-superres-cosmos-12b.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSuperResolutionMatchesReference_Rgba32_libavif-superres-cosmos-12b.png diff --git a/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithSuperResolutionMatchesPinnedLibavifPresentation_Rgba32_libavif-superres-kodim23-8b.png b/tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSuperResolutionMatchesReference_Rgba32_libavif-superres-kodim23-8b.png similarity index 100% rename from tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeWithSuperResolutionMatchesPinnedLibavifPresentation_Rgba32_libavif-superres-kodim23-8b.png rename to tests/Images/External/ReferenceOutput/Av1ReconstructionConformanceTests/DecodeSuperResolutionMatchesReference_Rgba32_libavif-superres-kodim23-8b.png diff --git a/tests/Images/Input/Heif/Av1/Conformance/README.md b/tests/Images/Input/Heif/Av1/Conformance/README.md index c8ae9c305..107e254b2 100644 --- a/tests/Images/Input/Heif/Av1/Conformance/README.md +++ b/tests/Images/Input/Heif/Av1/Conformance/README.md @@ -6,12 +6,8 @@ These fixtures provide independent reference output for AV1 reconstruction and A The source images and original AVIF files come from `libavif/tests/data` at commit `062e582e8afda88e6baf988fdcf046a801efa0f5`. Their licenses are recorded in libavif's `tests/data/README.md` and continue to apply to the derived fixtures. This includes the unrestricted Kodak image, the CC BY 3.0 Cosmos Laundromat frame, and files distributed under libavif's BSD-2-Clause license. -Original fixture-generation records name scalar builds of: - -- libaom commit `03087864cf4bea6abb0d28f95cf7843511413d8f`; -- libavif 1.4.2 from commit `062e582e8afda88e6baf988fdcf046a801efa0f5`, linked to that libaom build. - -Those revisions describe how the retained assets were originally produced; they do not pin the current +Original fixture-generation records identify libavif 1.4.2 from commit +`062e582e8afda88e6baf988fdcf046a801efa0f5` as the container tool. This does not pin the current verification checkout. Current AV1 algorithm, arithmetic, syntax, and native-output verification uses only the clean official libaom `main` checkout. Libavif commands record container and presentation provenance only and are not used as an AV1 implementation reference. @@ -87,7 +83,7 @@ edges, and skipped prediction-unit boundaries. ## Official ten-bit sequence fixtures -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 `test/test-data.sha1` at pinned libaom commit `03087864cf4bea6abb0d28f95cf7843511413d8f`. 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: @@ -100,7 +96,7 @@ The film-grain Y4M SHA-256 is `A1B553BE140F48ABDDB2A6D39917AB714BA03AC7FFD6359EA ## 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 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 the current official libaom `main` manifest. Their SHA-256 values, in the same order, are `6382DBD2BEFBBC93D4EA283586F4FB43FEA5F1C52400E3D2C5281A46B1104C00`, `0E4EC80680F7AF8DE9621B016E0F2D7C0858B2951DEBC173DDA50C6A051547D3`, `FE6053CE4EE20A1C0EC6F7FE35DB097E92AD25D8A3505598BD89162C74D7944F`, and `39759AB77483E1D11049DC38B5F5262158FD9C3CBC9D1F82A02462FC5DF30E0C`. The native references were originally generated with the historical generic `aomdec --threads=1` build. On 2026-08-31 current official libaom `main` at observed revision `441c439b9916474cac15d2822af47a9ad70674a8` reproduced all four references byte for byte. 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. @@ -130,9 +126,29 @@ the native reference SHA-256 is decodes all 39 frames in one decoder session, compares every native sample exactly, and requires coverage of every intra prediction mode and all seven transform types selected by the fixture. +## Adaptive reference-state fixtures + +On 2026-08-31 current official libaom `main` at observed revision +`441c439b9916474cac15d2822af47a9ad70674a8` decoded the `cdfupdate`, `mfmv`, `svc-L2T1`, +`svc-L1T2`, and `svc-L2T2` IVF streams with one thread, row threading disabled, and eight-bit output +depth. Every generated Y4M matches its retained native reference byte for byte. Their output SHA-256 +values, in that order, are: + +- `4FBFF73FF0DE2D9084DAE557D1D4BD677B0486516525BF4D327D2D795D5A7779`; +- `F7DB607694818C19E62FD9A27F53E1A3E2D00B72C39C0430C1B26399CC76777D`; +- `7A427631ECBF144F435AA4612F1201415FB1A9BCF9A67BA010AEF830B0C3AB81`; +- `4012DE2D4AFD095E7BB68EAE18B50B0674781BB4971CECABC0E5471E63373ED3`; +- `1ABB981CFF76BA9557DA437B258D8A95FCA755DED8E3949D857E8388AB1D6AE3`. + +The production tests compare every native sample under `FeatureTestRunner`. They require both adaptive +tile and frame-end CDF updates, active projected reference motion vectors, and the default operating point +of each spatial or temporal layer fixture. The motion-field and layer sequences also run through constrained +tracked allocators. Direct ownership tests cover initialization, retained-slot aliases, allocation-failure +unwinding, presentation ownership, decoder-result ownership, and exactly-once final disposal. + ## Official frame-size corner fixtures -The retained 196x196, 196x226, 226x196, and 226x226 streams are the four corners of libaom's official eight-bit frame-size matrix. Their SHA-1 values are `9F386D19C87DBFD6AC84A06D2393DD88863AC003`, `5525F7E312EC073F480ED5A2BE5BDC4F0CE51A09`, `1A57B913443B267F4A31A6925C39F5B58022F550`, and `40DD208EB525CD90D7C0674CF787097FB909AFAE`, exactly matching `test/test-data.sha1` at pinned libaom commit `03087864cf4bea6abb0d28f95cf7843511413d8f`. Their SHA-256 values, in the same order, are `ECACF9C2065EEC1A02248395412BE5E03ED7E3FEDFD6653622E09E73D1CAC747`, `2A2ECDDE60546FA8280039228B4BE541825EFAEE30F53EE50B91B11F2952BDA7`, `999522FBF3FCD9F8CC8DAC865BEF874B7BF655A4DAD93C397F50A7A1EC2C9027`, and `B5D9A30F24E33F8FA6A655961645650542DC2545FB7D557E2D55A043DAC69F50`. +The retained 196x196, 196x226, 226x196, and 226x226 streams are the four corners of libaom's official eight-bit frame-size matrix. Their SHA-1 values are `9F386D19C87DBFD6AC84A06D2393DD88863AC003`, `5525F7E312EC073F480ED5A2BE5BDC4F0CE51A09`, `1A57B913443B267F4A31A6925C39F5B58022F550`, and `40DD208EB525CD90D7C0674CF787097FB909AFAE`, exactly matching the current official libaom `main` manifest. Their SHA-256 values, in the same order, are `ECACF9C2065EEC1A02248395412BE5E03ED7E3FEDFD6653622E09E73D1CAC747`, `2A2ECDDE60546FA8280039228B4BE541825EFAEE30F53EE50B91B11F2952BDA7`, `999522FBF3FCD9F8CC8DAC865BEF874B7BF655A4DAD93C397F50A7A1EC2C9027`, and `B5D9A30F24E33F8FA6A655961645650542DC2545FB7D557E2D55A043DAC69F50`. The native references were generated with the pinned generic `aomdec --threads=1` build. Their SHA-256 values are `4479030861DD9D6AB9B00FA8CF77A34712BCECA06C31131927D3E7E9BF5DDA70`, `817FF76E70946763C000E19FCCD9F0258CF9358201B6771AA68FB8C84490D26F`, `F4A70BA358E8B4ED558B589BFE56354C9552469FDABD01B3F4D5754334B0CBD9`, and `44FC32FB1D24CE4A33830B67D927F038E0E1379C6B480C598F018382EC78E9CE`. 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 1 KiB constrained tracked allocator. @@ -146,7 +162,12 @@ The `libavif-progressive-draw-points-8b.avif` fixture is the unmodified `tests/d The primary color item's `a1lx` property divides its logical 72-byte AV1 payload into a 55-byte base layer and a 17-byte dependent layer. The container stores those layers in separate `iloc` extents at AVIF offsets 511 and 583. The `.bit` fixture concatenates those two logical color extents; it does not copy the physically adjacent auxiliary-alpha extent between them. -Exact pinned libaom decodes the corrected logical payload into two 33x11 YUV444 frames. Both frames' 1,089 color samples match the corresponding first three planes of the pinned libavif YUV444-alpha outputs exactly. The retained Y4M contains both progressive YUV444-alpha frames, and the PNG contains pinned libavif's final RGBA presentation. The production-path test selects the second native frame, requires inter-coded blocks in the final ImageSharp frame, and compares both native color and final presentation without a tolerance. +Current official libaom `main` decodes the corrected logical payload into two 33x11 YUV444 frames. Both +frames' 1,089 color samples match the corresponding first three planes of the retained YUV444-alpha +outputs exactly. The alpha and PNG record the original fixture's presentation provenance; they are not AV1 +implementation references. The production-path test selects the second native frame, requires inter-coded +blocks in the final ImageSharp frame, and compares both native color and final presentation without a +tolerance. ## Equal-average compound fixture