Browse Source

Document HEIF loop filter pipeline

pull/2633/head
James Jackson-South 1 week ago
parent
commit
50ae1237fd
  1. 3
      src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1LoopFilterContext.cs
  2. 50
      src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1LoopFilterDecoder.cs

3
src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1LoopFilterContext.cs

@ -3,6 +3,9 @@
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline.LoopFilter;
/// <summary>
/// Defines the per-frame state boundary used while applying the AV1 deblocking loop filter.
/// </summary>
internal class Av1LoopFilterContext
{
}

50
src/ImageSharp/Formats/Heif/Av1/Pipeline/LoopFilter/Av1LoopFilterDecoder.cs

@ -6,14 +6,43 @@ using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline.LoopFilter;
/// <summary>
/// Provides frame traversal for the AV1 in-loop deblocking stage.
/// </summary>
internal class Av1LoopFilterDecoder
{
/// <summary>
/// The sequence-level superblock configuration.
/// </summary>
private readonly ObuSequenceHeader sequenceHeader;
/// <summary>
/// The frame dimensions and loop-filter parameters.
/// </summary>
private readonly ObuFrameHeader frameHeader;
/// <summary>
/// The decoded block-mode information addressed by superblock origin.
/// </summary>
private readonly Av1FrameInfo frameInfo;
/// <summary>
/// The reconstructed plane samples supplied to in-loop filtering.
/// </summary>
private readonly Av1FrameBuffer<byte> frameBuffer;
/// <summary>
/// The per-frame filter context retained across superblocks.
/// </summary>
private readonly Av1LoopFilterContext loopFilterContext;
/// <summary>
/// Initializes a new instance of the <see cref="Av1LoopFilterDecoder"/> class.
/// </summary>
/// <param name="sequenceHeader">The sequence header that supplies the superblock size.</param>
/// <param name="frameHeader">The frame header that supplies dimensions and filter parameters.</param>
/// <param name="frameInfo">The decoded block-mode information for the frame.</param>
/// <param name="frameBuffer">The reconstructed frame samples to filter.</param>
public Av1LoopFilterDecoder(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, Av1FrameInfo frameInfo, Av1FrameBuffer<byte> frameBuffer)
{
this.sequenceHeader = sequenceHeader;
@ -23,6 +52,11 @@ internal class Av1LoopFilterDecoder
this.loopFilterContext = new();
}
/// <summary>
/// Traverses each superblock in raster order when loop filtering is enabled for the decode pass.
/// </summary>
/// <param name="doLoopFilterFlag">Whether the frame should run the deblocking stage.</param>
/// <exception cref="NotImplementedException">The superblock filtering operation has not been implemented.</exception>
public void DecodeFrame(bool doLoopFilterFlag)
{
Guard.NotNull(this.sequenceHeader);
@ -38,7 +72,8 @@ internal class Av1LoopFilterDecoder
int frameWidthInSuperblocks = Av1Math.DivideLog2Ceiling(this.frameHeader.FrameSize.FrameWidth, this.sequenceHeader.SuperblockSizeLog2);
int frameHeightInSuperblocks = Av1Math.DivideLog2Ceiling(this.frameHeader.FrameSize.FrameHeight, this.sequenceHeader.SuperblockSizeLog2);
// Loop over a frame : tregger dec_loop_filter_sb for each SB
// Filtering proceeds in raster order because vertical and horizontal edges depend on already reconstructed
// neighboring blocks, while the final superblock in each row requires distinct delayed-edge handling.
for (int superblockIndexY = 0; superblockIndexY < frameHeightInSuperblocks; ++superblockIndexY)
{
for (int superblockIndexX = 0; superblockIndexX < frameWidthInSuperblocks; ++superblockIndexX)
@ -49,9 +84,10 @@ internal class Av1LoopFilterDecoder
Point superblockPoint = new(superblockOriginX, superblockOriginY);
Av1SuperblockInfo superblockInfo = this.frameInfo.GetSuperblock(superblockPoint);
// Mode-info coordinates are measured in 4x4 units, whereas the frame and superblock origins are pixels.
Point superblockOriginInModeInfo = new(superblockOriginX >> 2, superblockOriginY >> 2);
// LF function for a SB
this.DecodeForSuperblock(
superblockInfo,
superblockOriginInModeInfo,
@ -63,6 +99,16 @@ internal class Av1LoopFilterDecoder
}
}
/// <summary>
/// Represents the not-yet-implemented deblocking operation for one superblock and plane range.
/// </summary>
/// <param name="superblockInfo">The decoded modes and delta values for the superblock.</param>
/// <param name="modeInfoLocation">The superblock origin in 4x4 mode-info units.</param>
/// <param name="startPlane">The first color plane to filter.</param>
/// <param name="endPlane">The exclusive color-plane index at which filtering stops.</param>
/// <param name="endOfRowFlag">Whether the superblock is the final block in its raster row.</param>
/// <param name="superblockDeltaLoopFilter">The per-superblock loop-filter strength adjustments.</param>
/// <exception cref="NotImplementedException">Always thrown because superblock deblocking has not been implemented.</exception>
private void DecodeForSuperblock(Av1SuperblockInfo superblockInfo, Point modeInfoLocation, Av1Plane startPlane, int endPlane, bool endOfRowFlag, Span<int> superblockDeltaLoopFilter)
=> throw new NotImplementedException();
}

Loading…
Cancel
Save