diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameDecoder.cs
index ef3590ef4..6f9821cf6 100644
--- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameDecoder.cs
+++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameDecoder.cs
@@ -8,16 +8,53 @@ using SixLabors.ImageSharp.Formats.Heif.Av1.Transform;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline;
+///
+/// Reconstructs the coded blocks of one AV1 still-image frame into planar sample buffers.
+///
internal class Av1FrameDecoder : IAv1FrameDecoder
{
+ ///
+ /// The sequence-level superblock and color configuration.
+ ///
private readonly ObuSequenceHeader sequenceHeader;
+
+ ///
+ /// The frame-level tile, quantization, and reconstruction configuration.
+ ///
private readonly ObuFrameHeader frameHeader;
+
+ ///
+ /// The parsed superblock and block-mode information for the frame.
+ ///
private readonly Av1FrameInfo frameInfo;
+
+ ///
+ /// The destination planar sample buffers for reconstructed pixels.
+ ///
private readonly Av1FrameBuffer frameBuffer;
+
+ ///
+ /// The coefficient inverse-quantization stage shared across superblocks.
+ ///
private readonly Av1InverseQuantizer inverseQuantizer;
+
+ ///
+ /// The frame's base per-segment and per-plane dequantization values.
+ ///
private readonly Av1DeQuantizationContext deQuants;
+
+ ///
+ /// The block reconstruction stage that applies prediction and inverse transforms.
+ ///
private readonly Av1BlockDecoder blockDecoder;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The parsed AV1 sequence header.
+ /// The parsed AV1 frame header.
+ /// The parsed superblock and block-mode information.
+ /// The destination planar sample buffers.
public Av1FrameDecoder(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, Av1FrameInfo frameInfo, Av1FrameBuffer frameBuffer)
{
this.sequenceHeader = sequenceHeader;
@@ -29,8 +66,12 @@ internal class Av1FrameDecoder : IAv1FrameDecoder
this.blockDecoder = new(this.sequenceHeader, this.frameHeader, this.frameBuffer);
}
+ ///
+ /// Reconstructs every coded tile of the frame; in-loop post-processing stages remain disabled until implemented.
+ ///
public void DecodeFrame()
{
+ // 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);
@@ -39,6 +80,9 @@ internal class Av1FrameDecoder : IAv1FrameDecoder
bool doLoopFilterFlag = false;
bool doLoopRestoration = false;
bool doUpscale = false;
+
+ // These flags remain false until the corresponding normative stages have complete scalar implementations
+ // and independent still-image vectors; silently running partial filters would corrupt reconstructed pixels.
if (doLoopFilterFlag)
{
this.DecodeLoopFilterForFrame();
@@ -61,14 +105,18 @@ internal class Av1FrameDecoder : IAv1FrameDecoder
}
///
- /// SVT: decode_tile
+ /// Reconstructs every tile row in one tile column.
///
+ /// The zero-based tile-column index.
+ /// SVT-AV1: decode_tile.
private void DecodeFrameTiles(int tileColumn)
{
int tileRowCount = this.frameHeader.TilesInfo.TileRowCount;
int tileCount = tileRowCount * this.frameHeader.TilesInfo.TileColumnCount;
for (int row = 0; row < tileRowCount; row++)
{
+ // Tile row starts are signaled in 4x4 mode-info units. Convert to pixels and then to superblock rows
+ // so the frame-level superblock store and the tile-local syntax address the same region.
int superblockRowTileStart = this.frameHeader.TilesInfo.TileRowStartModeInfo[row] << Av1Constants.ModeInfoSizeLog2 >>
this.sequenceHeader.SuperblockSizeLog2;
int superblockRow = row + superblockRowTileStart;
@@ -82,8 +130,13 @@ internal class Av1FrameDecoder : IAv1FrameDecoder
}
///
- /// SVT: decode_tile_row
+ /// Reconstructs the superblocks in one tile row 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.
+ /// SVT-AV1: decode_tile_row.
private void DecodeTileRow(int tileRow, int tileColumn, int modeInfoRow, int superblockRow)
{
int superblockModeInfoSizeLog2 = this.sequenceHeader.SuperblockSizeLog2 - Av1Constants.ModeInfoSizeLog2;
@@ -96,6 +149,7 @@ internal class Av1FrameDecoder : IAv1FrameDecoder
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));
@@ -106,8 +160,12 @@ internal class Av1FrameDecoder : IAv1FrameDecoder
}
///
- /// SVT: svt_aom_decode_super_block
+ /// 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.
+ /// SVT-AV1: svt_aom_decode_super_block.
public void DecodeSuperblock(Point modeInfoPosition, Av1SuperblockInfo superblockInfo, Av1TileInfo tileInfo)
{
this.blockDecoder.UpdateSuperblock(superblockInfo);
@@ -116,8 +174,12 @@ internal class Av1FrameDecoder : IAv1FrameDecoder
}
///
- /// SVT: decode_partition
+ /// Reconstructs each decoded block in a superblock partition.
///
+ /// 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.
+ /// SVT-AV1: decode_partition.
private void DecodePartition(Point modeInfoPosition, Av1SuperblockInfo superblockInfo, Av1TileInfo tileInfo)
{
foreach (Av1BlockModeInfo modeInfo in superblockInfo.GetModeInfos())
@@ -125,18 +187,23 @@ internal class Av1FrameDecoder : IAv1FrameDecoder
Point subPosition = modeInfo.PositionInSuperblock;
Av1BlockSize subSize = modeInfo.BlockSize;
Point globalPosition = new(modeInfoPosition.X, modeInfoPosition.Y);
+
+ // 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);
}
}
+ ///
+ /// Traverses frame superblocks in the order required by the not-yet-implemented deblocking stage.
+ ///
private void DecodeLoopFilterForFrame()
{
int superblockSizeLog2 = this.sequenceHeader.SuperblockSizeLog2;
int pictureWidthInSuperblocks = Av1Math.DivideLog2Ceiling(this.frameHeader.FrameSize.FrameWidth, this.sequenceHeader.SuperblockSizeLog2);
int pictureHeightInSuperblocks = Av1Math.DivideLog2Ceiling(this.frameHeader.FrameSize.FrameHeight, this.sequenceHeader.SuperblockSizeLog2);
- // Loop over a frame : tregger dec_loop_filter_sb for each SB
+ // Deblocking uses raster traversal so each block can consume already reconstructed top and left edges.
for (int superblockIndexY = 0; superblockIndexY < pictureHeightInSuperblocks; ++superblockIndexY)
{
for (int superblockIndexX = 0; superblockIndexX < pictureWidthInSuperblocks; ++superblockIndexX)
@@ -148,7 +215,7 @@ internal class Av1FrameDecoder : IAv1FrameDecoder
Point superblockPoint = new(superblockOriginX, superblockOriginY);
Av1SuperblockInfo superblockInfo = this.frameInfo.GetSuperblock(superblockPoint);
- // LF function for a SB
+ // Superblock filtering remains disabled until its complete plane and edge-strength implementation is available.
/*
DecodeLoopFilterForSuperblock(
superblockInfo,
diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameEncoder.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameEncoder.cs
index 6bdd55ac5..b5a847d40 100644
--- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameEncoder.cs
+++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/Av1FrameEncoder.cs
@@ -5,70 +5,32 @@ using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline;
+///
+/// Defines the work-in-progress AV1 still-image frame-encoding boundary.
+///
internal class Av1FrameEncoder
{
+ ///
+ /// The source plane samples supplied for frame encoding.
+ ///
private readonly Av1FrameBuffer frameBuffer;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The source frame samples to encode.
public Av1FrameEncoder(Av1FrameBuffer frameBuffer)
{
this.frameBuffer = frameBuffer;
}
///
- /// SVT: svt_av1_enc_init
+ /// Represents the not-yet-implemented entry point for encoding one AV1 still-image frame.
///
+ /// SVT-AV1: svt_av1_enc_init.
public static void Encode()
{
- /************************************
- * Thread Handles
- ************************************/
-
- // Resource Coordination
- // Single thread calling svt_aom_resource_coordination_kernel with context enc_handle_ptr->resource_coordination_context_ptr
- // Multiple threads calling svt_aom_picture_analysis_kernel, with context enc_handle_ptr->picture_analysis_context_ptr_array
-
- // Picture Decision
- // Single thread calling svt_aom_picture_decision_kernel with context enc_handle_ptr->picture_decision_context_ptr
-
- // Motion Estimation
- // Multiple threads calling svt_aom_motion_estimation_kernel with context enc_handle_ptr->motion_estimation_context_ptr_array
-
- // Initial Rate Control
- // Single thread calling svt_aom_initial_rate_control_kernel with context enc_handle_ptr->initial_rate_control_context_ptr
-
- // Source Based Oprations
- // source_based_operations_context_ptr_array
-
- // TPL dispenser
- // Multiple threads calling svt_aom_tpl_disp_kernel with context enc_handle_ptr->tpl_disp_context_ptr_array
-
- // Picture Manager
- // Single thread calling svt_aom_picture_manager_kernel with context enc_handle_ptr->picture_manager_context_ptr
-
- // Rate Control
- // Single thread calling svt_aom_rate_control_kernel with context enc_handle_ptr->rate_control_context_ptr
-
- // Mode Decision Configuration Process
- // Multiple threads calling svt_aom_mode_decision_configuration_kernel with context enc_handle_ptr->mode_decision_configuration_context_ptr_array
-
- // EncDec Process
- // Multiple threads calling svt_aom_mode_decision_kernel enc_handle_ptr->enc_dec_context_ptr_array
-
- // Dlf Process
- // Multiple threads calling svt_aom_dlf_kernel with context enc_handle_ptr->dlf_context_ptr_array
-
- // Cdef Process
- // Multiple threads calling svt_aom_cdef_kernel enc_handle_ptr->cdef_context_ptr_array
-
- // Rest Process
- // Multiple threads calling svt_aom_rest_kernel enc_handle_ptr->rest_context_ptr_array
-
- // Entropy Coding Process
- // Multiple threads calling svt_aom_entropy_coding_kernel enc_handle_ptr->entropy_coding_context_ptr_array
-
- // Packetization
- // Single thread calling svt_aom_packetization_kernel with context enc_handle_ptr->packetization_context_ptr
-
- // svt_print_memory_usage();
+ // 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.
}
}
diff --git a/src/ImageSharp/Formats/Heif/Av1/Pipeline/IAv1FrameDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Pipeline/IAv1FrameDecoder.cs
index 1204e8bc1..ce1763015 100644
--- a/src/ImageSharp/Formats/Heif/Av1/Pipeline/IAv1FrameDecoder.cs
+++ b/src/ImageSharp/Formats/Heif/Av1/Pipeline/IAv1FrameDecoder.cs
@@ -6,15 +6,15 @@ using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Pipeline;
///
-/// Interface for decoder of a single frame.
+/// Defines reconstruction of decoded AV1 superblocks within a single still-image frame.
///
internal interface IAv1FrameDecoder
{
///
- /// Decode a single superblock.
+ /// Reconstructs one decoded superblock into the current frame buffer.
///
- /// The top left position of the superblock, in mode info units.
- /// The superblock to decode
- /// The tile in whcih the superblock is positioned.
+ /// 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.
void DecodeSuperblock(Point modeInfoPosition, Av1SuperblockInfo superblockInfo, Av1TileInfo tileInfo);
}