From 682b05c5d0816b15adadb845f47d28da74eb5dc6 Mon Sep 17 00:00:00 2001 From: Ynse Hoornenborg Date: Wed, 20 Nov 2024 20:43:43 +0100 Subject: [PATCH] Fill some more data structures --- .../Formats/Heif/Av1/Av1Constants.cs | 15 ++ .../Heif/Av1/Tiling/Av1BlockGeometry.cs | 33 +++- .../Formats/Heif/Av1/Tiling/Av1BlockStruct.cs | 11 ++ .../Av1/Tiling/Av1EntropyCodingContext.cs | 4 + .../Formats/Heif/Av1/Tiling/Av1MacroBlockD.cs | 17 +- .../Heif/Av1/Tiling/Av1NeighborArrayUnit.cs | 163 +++++++++++++++++- .../Av1/Tiling/Av1PictureParentControlSet.cs | 2 + .../Heif/Av1/Tiling/Av1TransformUnit.cs | 13 ++ 8 files changed, 244 insertions(+), 14 deletions(-) create mode 100644 src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TransformUnit.cs diff --git a/src/ImageSharp/Formats/Heif/Av1/Av1Constants.cs b/src/ImageSharp/Formats/Heif/Av1/Av1Constants.cs index 089415d25c..dc0e9e68b2 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Av1Constants.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Av1Constants.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; +using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; namespace SixLabors.ImageSharp.Formats.Heif.Av1; @@ -187,4 +188,18 @@ internal static class Av1Constants // Number of transform sizes that use extended transforms. public const int ExtendedTransformCount = 4; + + public const int MaxVarTransform = 2; + + /// + /// Maximum number of transform blocks per depth + /// + public const int MaxTransformBlockCount = 16; + + /// + /// Number of items in the enumeration. + /// + public const int PlaneTypeCount = 2; + + public const int MaxTransformUnitCount = 16; } diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockGeometry.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockGeometry.cs index 104099eea8..a6e24821d6 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockGeometry.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockGeometry.cs @@ -9,16 +9,47 @@ internal partial class Av1TileWriter { internal class Av1BlockGeometry { + public Av1BlockGeometry() + { + this.TransformOrigin = new Point[Av1Constants.MaxVarTransform + 1][]; + for (int i = 0; i < this.TransformOrigin.Length; i++) + { + this.TransformOrigin[i] = new Point[Av1Constants.MaxTransformBlockCount]; + } + } + public Av1BlockSize BlockSize { get; internal set; } + public Av1BlockSize BlockSizeUv { get; internal set; } + + /// + /// Gets or sets the Origin point from lop left of the superblock. + /// public Point Origin { get; internal set; } public bool HasUv { get; internal set; } + /// + /// Gets or sets the blocks width. + /// public int BlockWidth { get; internal set; } + /// + /// Gets or sets the blocks height. + /// public int BlockHeight { get; internal set; } - public required Av1TransformSize[] TransformSize { get; internal set; } + public int[] TransformBlockCount { get; } = new int[Av1Constants.MaxVarTransform + 1]; + + public Av1TransformSize[] TransformSize { get; } = new Av1TransformSize[Av1Constants.MaxVarTransform + 1]; + + public Av1TransformSize[] TransformSizeUv { get; } = new Av1TransformSize[Av1Constants.MaxVarTransform + 1]; + + public Point[][] TransformOrigin { get; private set; } + + /// + /// Gets or sets the block index in md scan. + /// + public int BlockIndex { get; set; } } } diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockStruct.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockStruct.cs index 53ee7ef8bb..44bceded44 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockStruct.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockStruct.cs @@ -5,4 +5,15 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; internal class Av1BlockStruct { + public Av1TransformUnit[] TransformBlocks { get; } = new Av1TransformUnit[Av1Constants.MaxTransformUnitCount]; + + public required Av1MacroBlockD av1xd { get; set; } + + public int MdScanIndex { get; set; } + + public int QIndex { get; set; } + + public int SegmentId { get; set; } + + public Av1FilterIntraMode FilterIntraMode { get; set; } } diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1EntropyCodingContext.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1EntropyCodingContext.cs index 05c501d4d9..ead8f44623 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1EntropyCodingContext.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1EntropyCodingContext.cs @@ -10,5 +10,9 @@ internal partial class Av1TileWriter public required Av1MacroBlockModeInfo MacroBlockModeInfo { get; internal set; } public Point SuperblockOrigin { get; internal set; } + + public int CodedAreaSuperblock { get; internal set; } + + public int CodedAreaSuperblockUv { get; internal set; } } } diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1MacroBlockD.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1MacroBlockD.cs index da1469173b..62dd3972bb 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1MacroBlockD.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1MacroBlockD.cs @@ -3,20 +3,17 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; -internal partial class Av1TileWriter +internal class Av1MacroBlockD { - internal class Av1MacroBlockD - { - public required Av1BlockModeInfo ModeInfo { get; internal set; } + public required Av1BlockModeInfo ModeInfo { get; internal set; } - public required Av1TileInfo Tile { get; internal set; } + public required Av1TileInfo Tile { get; internal set; } - public bool IsUpAvailable { get; } + public bool IsUpAvailable { get; } - public bool IsLeftAvailable { get; } + public bool IsLeftAvailable { get; } - public Av1MacroBlockModeInfo? AboveMacroBlock { get; internal set; } + public Av1MacroBlockModeInfo? AboveMacroBlock { get; internal set; } - public Av1MacroBlockModeInfo? LeftMacroBlock { get; internal set; } - } + public Av1MacroBlockModeInfo? LeftMacroBlock { get; internal set; } } diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1NeighborArrayUnit.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1NeighborArrayUnit.cs index 0aa6a68b09..7607d1bffd 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1NeighborArrayUnit.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1NeighborArrayUnit.cs @@ -1,11 +1,168 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Numerics; +using System.Runtime.CompilerServices; + namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; -internal partial class Av1TileWriter +internal class Av1NeighborArrayUnit + where T : struct, IMinMaxValue { - internal class Av1NeighborArrayUnit + public static readonly T InvalidNeighborData = T.MaxValue; + + [Flags] + public enum UnitMask + { + Left = 1, + Top = 2, + TopLeft = 4, + } + + private readonly T[] left; + private readonly T[] top; + private readonly T[] topLeft; + + public Av1NeighborArrayUnit(int leftSize, int topSize, int topLeftSize) + { + this.left = new T[leftSize]; + this.top = new T[topSize]; + this.topLeft = new T[topLeftSize]; + } + + public Span Left => this.left; + + public Span Top => this.top; + + public Span TopLeft => this.topLeft; + + public required int GranularityNormalLog2 { get; set; } + + public required int GranularityTopLeftLog2 { get; set; } + + public int UnitSize { get; private set; } + + public int GetLeftIndex(Point loc) => loc.Y >> this.GranularityNormalLog2; + + public int GetTopIndex(Point loc) => loc.X >> this.GranularityNormalLog2; + + public int GetTopLeftIndex(Point loc) + => this.left.Length + (loc.X >> this.GranularityTopLeftLog2) - (loc.Y >> this.GranularityTopLeftLog2); + + public void UnitModeWrite(Span value, Point origin, Size blockSize, UnitMask mask) { + int idx, j; + + int count; + int na_offset; + int na_unit_size; + + na_unit_size = this.UnitSize; + + if ((mask & UnitMask.Top) == UnitMask.Top) + { + // Top Neighbor Array + // ----------12345678--------------------- + // ^ ^ + // | | + // | | + // xxxxxxxx + // x x + // x x + // 12345678 + // + // The top neighbor array is updated with the samples from the + // bottom row of the source block + // + // Index = org_x + na_offset = this.GetTopIndex(origin); + + ref T dst_ptr = ref this.Top[na_offset * na_unit_size]; + + count = blockSize.Width >> this.GranularityNormalLog2; + + for (idx = 0; idx < count; ++idx) + { + /* svt_memcpy less that 10 bytes*/ + for (j = 0; j < na_unit_size; ++j) + { + dst_ptr = value[j]; + dst_ptr = Unsafe.Add(ref dst_ptr, 1); + } + } + } + + if ((mask & UnitMask.Left) == UnitMask.Left) + { + // Left Neighbor Array + // + // | + // | + // 1 xxxxxxx1 + // 2 <---- x 2 + // 3 <---- x 3 + // 4 xxxxxxx4 + // | + // | + // + // The left neighbor array is updated with the samples from the + // right column of the source block + // + // Index = org_y + na_offset = this.GetLeftIndex(origin); + + ref T dst_ptr = ref this.Left[na_offset * na_unit_size]; + + count = blockSize.Height >> this.GranularityNormalLog2; + + for (idx = 0; idx < count; ++idx) + { + /* svt_memcpy less that 10 bytes*/ + for (j = 0; j < na_unit_size; ++j) + { + dst_ptr = value[j]; + dst_ptr = Unsafe.Add(ref dst_ptr, 1); + } + } + } + + if ((mask & UnitMask.TopLeft) == UnitMask.TopLeft) + { + // Top-left Neighbor Array + // + // 4-5--6--7------------ + // 3 \ \ + // 2 \ \ + // 1 \ \ + // |\ xxxxxx7 + // | \ x 6 + // | \ x 5 + // | \1x2x3x4 + // | + // + // The top-left neighbor array is updated with the reversed samples + // from the right column and bottom row of the source block + // + // Index = org_x - org_y + Point topLeft = origin; + topLeft.Offset(0, blockSize.Height - 1); + na_offset = this.GetTopLeftIndex(topLeft); + + // Copy bottom-row + right-column + // *Note - start from the bottom-left corner + ref T dst_ptr = ref this.TopLeft[na_offset * na_unit_size]; + + count = ((blockSize.Width + blockSize.Height) >> this.GranularityTopLeftLog2) - 1; + + for (idx = 0; idx < count; ++idx) + { + /* svt_memcpy less that 10 bytes*/ + for (j = 0; j < na_unit_size; ++j) + { + dst_ptr = value[j]; + dst_ptr = Unsafe.Add(ref dst_ptr, 1); + } + } + } } } diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1PictureParentControlSet.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1PictureParentControlSet.cs index 6bbc651eac..bf79f5a5c3 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1PictureParentControlSet.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1PictureParentControlSet.cs @@ -16,5 +16,7 @@ internal partial class Av1TileWriter public required int[] PreviousQIndex { get; internal set; } public int PaletteLevel { get; internal set; } + public int AlignedWidth { get; internal set; } + public int AlignedHeight { get; internal set; } } } diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TransformUnit.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TransformUnit.cs new file mode 100644 index 0000000000..6670f99eda --- /dev/null +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TransformUnit.cs @@ -0,0 +1,13 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using SixLabors.ImageSharp.Formats.Heif.Av1.Transform; + +namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; + +internal class Av1TransformUnit +{ + public ushort[] NzCoefficientCount { get; } = new ushort[3]; + + public Av1TransformType[] TransformType { get; } = new Av1TransformType[Av1Constants.PlaneTypeCount]; +}