Browse Source

Preparations for Tile writing

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
8d13aa5808
  1. 10
      src/ImageSharp/Formats/Heif/Av1/Entropy/Av1DefaultDistributions.cs
  2. 91
      src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolContextHelper.cs
  3. 7
      src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolDecoder.cs
  4. 28
      src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolEncoder.cs
  5. 71
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockGeometry.cs
  6. 19
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockStruct.cs
  7. 19
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1EncoderBlockStruct.cs
  8. 2
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1NeighborArrayUnit.cs
  9. 12
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1PartitionContext.cs
  10. 27
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1PictureControlSet.cs
  11. 2
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1PictureParentControlSet.cs
  12. 2
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SequenceControlSet.cs
  13. 16
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1Superblock.cs
  14. 9
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SuperblockGeometry.cs
  15. 9
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileInfo.cs
  16. 73
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs
  17. 1050
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileWriter.cs

10
src/ImageSharp/Formats/Heif/Av1/Entropy/Av1DefaultDistributions.cs

@ -119,8 +119,18 @@ internal static class Av1DefaultDistributions
new(711, 966, 1172, 32448, 32538, 32617, 32664) new(711, 966, 1172, 32448, 32538, 32617, 32664)
]; ];
/// <summary>
/// Gets the skip <see cref="Av1Distribution"/>.
/// </summary>
/// <remarks>SVT: default_skip_cdfs</remarks>
public static Av1Distribution[] Skip => [new(31671), new(16515), new(4576)]; public static Av1Distribution[] Skip => [new(31671), new(16515), new(4576)];
/// <summary>
/// Gets the skip mode <see cref="Av1Distribution"/>.
/// </summary>
/// <remarks>SVT: default_skip_mode_cdfs</remarks>
public static Av1Distribution[] SkipMode => [new(32621), new(20708), new(8127)];
public static Av1Distribution DeltaLoopFilterAbsolute => new(28160, 32120, 32677); public static Av1Distribution DeltaLoopFilterAbsolute => new(28160, 32120, 32677);
public static Av1Distribution DeltaQuantizerAbsolute => new(28160, 32120, 32677); public static Av1Distribution DeltaQuantizerAbsolute => new(28160, 32120, 32677);

91
src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolContextHelper.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
using SixLabors.ImageSharp.Formats.Heif.Av1.Prediction; using SixLabors.ImageSharp.Formats.Heif.Av1.Prediction;
using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; using SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
using SixLabors.ImageSharp.Formats.Heif.Av1.Transform; using SixLabors.ImageSharp.Formats.Heif.Av1.Transform;
@ -365,4 +366,94 @@ internal static class Av1SymbolContextHelper
extra = endOfBlock - EndOfBlockGroupStart[t]; extra = endOfBlock - EndOfBlockGroupStart[t];
return t; return t;
} }
public static int GetSegmentId(Av1PartitionInfo partitionInfo, ObuFrameHeader frameHeader, int[][] segmentIds, int rowIndex, int columnIndex)
{
int modeInfoOffset = (rowIndex * frameHeader.ModeInfoColumnCount) + columnIndex;
int bw4 = partitionInfo.ModeInfo.BlockSize.Get4x4WideCount();
int bh4 = partitionInfo.ModeInfo.BlockSize.Get4x4HighCount();
int xMin = Math.Min(frameHeader.ModeInfoColumnCount - columnIndex, bw4);
int yMin = Math.Min(frameHeader.ModeInfoRowCount - rowIndex, bh4);
int segmentId = Av1Constants.MaxSegmentCount - 1;
for (int y = 0; y < yMin; y++)
{
for (int x = 0; x < xMin; x++)
{
segmentId = Math.Min(segmentId, segmentIds[y][x]);
}
}
return segmentId;
}
/// <summary>
/// SVT: svt_aom_get_segment_id
/// </summary>
public static int GetSegmentId(Av1Common cm, ReadOnlySpan<byte> segment_ids, Av1BlockSize bsize, Point modeInfoPosition)
{
int mi_offset = (modeInfoPosition.Y * cm.ModeInfoColumnCount) + modeInfoPosition.X;
int bw = bsize.GetWidth();
int bh = bsize.GetHeight();
int xmis = Math.Min(cm.ModeInfoColumnCount - modeInfoPosition.X, bw);
int ymis = Math.Min(cm.ModeInfoRowCount - modeInfoPosition.Y, bh);
int segment_id = Av1Constants.MaxSegmentCount;
for (int y = 0; y < ymis; ++y)
{
int offset = mi_offset + (y * cm.ModeInfoColumnCount);
for (int x = 0; x < xmis; ++x)
{
segment_id = Math.Min(segment_id, segment_ids[offset + x]);
}
}
Guard.IsTrue(segment_id is >= 0 and < Av1Constants.MaxSegmentCount, nameof(segment_id), "Segment ID needs to be in proper range.");
return segment_id;
}
public static int NegativeDeinterleave(int diff, int reference, int max)
{
if (reference == 0)
{
return diff;
}
if (reference >= max - 1)
{
return max - diff - 1;
}
if (2 * reference < max)
{
if (diff <= 2 * reference)
{
if ((diff & 1) > 0)
{
return reference + ((diff + 1) >> 1);
}
else
{
return reference - (diff >> 1);
}
}
return diff;
}
else
{
if (diff <= 2 * (max - reference - 1))
{
if ((diff & 1) > 0)
{
return reference + ((diff + 1) >> 1);
}
else
{
return reference - (diff >> 1);
}
}
return max - (diff + 1);
}
}
} }

7
src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolDecoder.cs

@ -26,6 +26,7 @@ internal ref struct Av1SymbolDecoder
private readonly Av1Distribution[][] keyFrameYMode = Av1DefaultDistributions.KeyFrameYMode; private readonly Av1Distribution[][] keyFrameYMode = Av1DefaultDistributions.KeyFrameYMode;
private readonly Av1Distribution[][] uvMode = Av1DefaultDistributions.UvMode; private readonly Av1Distribution[][] uvMode = Av1DefaultDistributions.UvMode;
private readonly Av1Distribution[] skip = Av1DefaultDistributions.Skip; private readonly Av1Distribution[] skip = Av1DefaultDistributions.Skip;
private readonly Av1Distribution[] skipMode = Av1DefaultDistributions.SkipMode;
private readonly Av1Distribution deltaLoopFilterAbsolute = Av1DefaultDistributions.DeltaLoopFilterAbsolute; private readonly Av1Distribution deltaLoopFilterAbsolute = Av1DefaultDistributions.DeltaLoopFilterAbsolute;
private readonly Av1Distribution deltaQuantizerAbsolute = Av1DefaultDistributions.DeltaQuantizerAbsolute; private readonly Av1Distribution deltaQuantizerAbsolute = Av1DefaultDistributions.DeltaQuantizerAbsolute;
private readonly Av1Distribution[] segmentId = Av1DefaultDistributions.SegmentId; private readonly Av1Distribution[] segmentId = Av1DefaultDistributions.SegmentId;
@ -132,6 +133,12 @@ internal ref struct Av1SymbolDecoder
return r.ReadSymbol(this.skip[ctx]) > 0; return r.ReadSymbol(this.skip[ctx]) > 0;
} }
public bool ReadSkipMode(Av1BlockSize blockSize)
{
ref Av1SymbolReader r = ref this.reader;
return r.ReadSymbol(this.skipMode[(int)blockSize]) > 0;
}
public int ReadDeltaLoopFilterAbsolute() public int ReadDeltaLoopFilterAbsolute()
{ {
ref Av1SymbolReader r = ref this.reader; ref Av1SymbolReader r = ref this.reader;

28
src/ImageSharp/Formats/Heif/Av1/Entropy/Av1SymbolEncoder.cs

@ -27,9 +27,13 @@ internal class Av1SymbolEncoder : IDisposable
private readonly Av1Distribution[][][] coefficientsBaseRange; private readonly Av1Distribution[][][] coefficientsBaseRange;
private readonly Av1Distribution[][][] coefficientsBase; private readonly Av1Distribution[][][] coefficientsBase;
private readonly Av1Distribution[][][] coefficientsBaseEndOfBlock; private readonly Av1Distribution[][][] coefficientsBaseEndOfBlock;
private readonly Av1Distribution filterIntraMode = Av1DefaultDistributions.FilterIntraMode;
private readonly Av1Distribution[][] dcSign; private readonly Av1Distribution[][] dcSign;
private readonly Av1Distribution[][][] endOfBlockExtra; private readonly Av1Distribution[][][] endOfBlockExtra;
private readonly Av1Distribution[][][] intraExtendedTransform = Av1DefaultDistributions.IntraExtendedTransform; private readonly Av1Distribution[][][] intraExtendedTransform = Av1DefaultDistributions.IntraExtendedTransform;
private readonly Av1Distribution[] segmentId = Av1DefaultDistributions.SegmentId;
private readonly Av1Distribution[] skip = Av1DefaultDistributions.Skip;
private readonly Av1Distribution[] skipMode = Av1DefaultDistributions.SkipMode;
private bool isDisposed; private bool isDisposed;
private readonly Configuration configuration; private readonly Configuration configuration;
private Av1SymbolWriter writer; private Av1SymbolWriter writer;
@ -309,4 +313,28 @@ internal class Av1SymbolEncoder : IDisposable
this.intraExtendedTransform[extendedSet][(int)squareTransformSize][(int)intraMode]); this.intraExtendedTransform[extendedSet][(int)squareTransformSize][(int)intraMode]);
} }
} }
internal void WriteSegmentId(int segmentId, int context)
{
ref Av1SymbolWriter w = ref this.writer;
w.WriteSymbol(segmentId, this.segmentId[context]);
}
internal void WriteSkip(bool skip, int context)
{
ref Av1SymbolWriter w = ref this.writer;
w.WriteSymbol(skip, this.skip[context]);
}
internal void WriteSkipMode(bool skip, int context)
{
ref Av1SymbolWriter w = ref this.writer;
w.WriteSymbol(skip, this.skipMode[context]);
}
internal void WriteFilterIntraMode(Av1FilterIntraMode filterIntraMode)
{
ref Av1SymbolWriter w = ref this.writer;
w.WriteSymbol((int)filterIntraMode, this.filterIntraMode);
}
} }

71
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockGeometry.cs

@ -5,51 +5,58 @@ using SixLabors.ImageSharp.Formats.Heif.Av1.Transform;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
internal partial class Av1TileWriter internal class Av1BlockGeometry
{ {
internal class Av1BlockGeometry public Av1BlockGeometry()
{ {
public Av1BlockGeometry() this.TransformOrigin = new Point[Av1Constants.MaxVarTransform + 1][];
for (int i = 0; i < this.TransformOrigin.Length; i++)
{ {
this.TransformOrigin = new Point[Av1Constants.MaxVarTransform + 1][]; this.TransformOrigin[i] = new Point[Av1Constants.MaxTransformBlockCount];
for (int i = 0; i < this.TransformOrigin.Length; i++)
{
this.TransformOrigin[i] = new Point[Av1Constants.MaxTransformBlockCount];
}
} }
}
public Av1BlockSize BlockSize { get; internal set; } public Av1BlockSize BlockSize { get; internal set; }
public Av1BlockSize BlockSizeUv { get; internal set; } public Av1BlockSize BlockSizeUv { get; internal set; }
/// <summary> /// <summary>
/// Gets or sets the Origin point from lop left of the superblock. /// Gets or sets the Origin point from lop left of the superblock.
/// </summary> /// </summary>
public Point Origin { get; internal set; } public Point Origin { get; internal set; }
public bool HasUv { get; internal set; } public bool HasUv { get; internal set; }
/// <summary> /// <summary>
/// Gets or sets the blocks width. /// Gets or sets the blocks width.
/// </summary> /// </summary>
public int BlockWidth { get; internal set; } public int BlockWidth { get; internal set; }
/// <summary> /// <summary>
/// Gets or sets the blocks height. /// Gets or sets the blocks height.
/// </summary> /// </summary>
public int BlockHeight { get; internal set; } public int BlockHeight { get; internal set; }
public int[] TransformBlockCount { get; } = new int[Av1Constants.MaxVarTransform + 1]; public int[] TransformBlockCount { get; } = new int[Av1Constants.MaxVarTransform + 1];
public Av1TransformSize[] TransformSize { get; } = new Av1TransformSize[Av1Constants.MaxVarTransform + 1]; public Av1TransformSize[] TransformSize { get; } = new Av1TransformSize[Av1Constants.MaxVarTransform + 1];
public Av1TransformSize[] TransformSizeUv { get; } = new Av1TransformSize[Av1Constants.MaxVarTransform + 1]; public Av1TransformSize[] TransformSizeUv { get; } = new Av1TransformSize[Av1Constants.MaxVarTransform + 1];
public Point[][] TransformOrigin { get; private set; } public Point[][] TransformOrigin { get; private set; }
/// <summary> /// <summary>
/// Gets or sets the block index in md scan. /// Gets or sets the blocks index in the Mode Decision scan.
/// </summary> /// </summary>
public int BlockIndex { get; set; } public int ModeDecisionIndex { get; set; }
}
/// <summary>
/// Gets or sets the offset to the next nsq block (skip remaining d2 blocks).
/// </summary>
public int NextDepthSequenceOffset { get; set; }
/// <summary>
/// Gets or sets the offset to the next d1 sq block
/// </summary>
public int NextDepth1Offset { get; set; }
} }

19
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockStruct.cs

@ -1,19 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
internal class Av1BlockStruct
{
public Av1TransformUnit[] TransformBlocks { get; } = new Av1TransformUnit[Av1Constants.MaxTransformUnitCount];
public required Av1MacroBlockD MacroBlock { get; set; }
public int MdScanIndex { get; set; }
public int QIndex { get; set; }
public int SegmentId { get; set; }
public Av1FilterIntraMode FilterIntraMode { get; set; }
}

19
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1EncoderBlockStruct.cs

@ -3,14 +3,19 @@
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
internal partial class Av1TileWriter internal class Av1EncoderBlockStruct
{ {
internal class Av1EncoderBlockStruct public Av1TransformUnit[] TransformBlocks { get; } = new Av1TransformUnit[Av1Constants.MaxTransformUnitCount];
{
public required Av1MacroBlockD MacroBlock { get; internal set; }
public required int[] PaletteSize { get; internal set; } public required Av1MacroBlockD MacroBlock { get; set; }
public int QIndex { get; internal set; } public int ModeDecisionScanIndex { get; set; }
}
public int QuantizationIndex { get; set; }
public int SegmentId { get; set; }
public Av1FilterIntraMode FilterIntraMode { get; set; }
public required int[] PaletteSize { get; internal set; }
} }

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

@ -49,7 +49,7 @@ internal class Av1NeighborArrayUnit<T>
public int GetTopLeftIndex(Point loc) public int GetTopLeftIndex(Point loc)
=> this.left.Length + (loc.X >> this.GranularityTopLeftLog2) - (loc.Y >> this.GranularityTopLeftLog2); => this.left.Length + (loc.X >> this.GranularityTopLeftLog2) - (loc.Y >> this.GranularityTopLeftLog2);
public void UnitModeWrite(Span<T> value, Point origin, Size blockSize, UnitMask mask) public void UnitModeWrite(ReadOnlySpan<T> value, Point origin, Size blockSize, UnitMask mask)
{ {
int idx, j; int idx, j;

12
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1PartitionContext.cs

@ -1,12 +1,14 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using System.Numerics;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
// Generates 5 bit field in which each bit set to 1 represents // Generates 5 bit field in which each bit set to 1 represents
// a BlockSize partition 11111 means we split 128x128, 64x64, 32x32, 16x16 // a BlockSize partition 11111 means we split 128x128, 64x64, 32x32, 16x16
// and 8x8. 10000 means we just split the 128x128 to 64x64 // and 8x8. 10000 means we just split the 128x128 to 64x64
internal class Av1PartitionContext internal struct Av1PartitionContext : IMinMaxValue<Av1PartitionContext>
{ {
private static readonly int[] AboveLookup = private static readonly int[] AboveLookup =
[31, 31, 30, 30, 30, 28, 28, 28, 24, 24, 24, 16, 16, 16, 0, 0, 31, 28, 30, 24, 28, 16]; [31, 31, 30, 30, 30, 28, 28, 28, 24, 24, 24, 16, 16, 16, 0, 0, 31, 28, 30, 24, 28, 16];
@ -17,6 +19,14 @@ internal class Av1PartitionContext
// Mask to extract ModeInfo offset within max ModeInfoBlock // Mask to extract ModeInfo offset within max ModeInfoBlock
public const int Mask = (1 << (7 - 2)) - 1; public const int Mask = (1 << (7 - 2)) - 1;
public static Av1PartitionContext MaxValue => throw new NotImplementedException();
public static Av1PartitionContext MinValue => throw new NotImplementedException();
public byte Left { get; internal set; }
public byte Above { get; internal set; }
public static int GetAboveContext(Av1BlockSize blockSize) => AboveLookup[(int)blockSize]; public static int GetAboveContext(Av1BlockSize blockSize) => AboveLookup[(int)blockSize];
public static int GetLeftContext(Av1BlockSize blockSize) => LeftLookup[(int)blockSize]; public static int GetLeftContext(Av1BlockSize blockSize) => LeftLookup[(int)blockSize];

27
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1PictureControlSet.cs

@ -5,6 +5,8 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
internal class Av1PictureControlSet internal class Av1PictureControlSet
{ {
public required Av1NeighborArrayUnit<Av1PartitionContext>[] PartitionContexts { get; internal set; }
public required Av1NeighborArrayUnit<byte>[] LuminanceDcSignLevelCoefficientNeighbors { get; internal set; } public required Av1NeighborArrayUnit<byte>[] LuminanceDcSignLevelCoefficientNeighbors { get; internal set; }
public required Av1NeighborArrayUnit<byte>[] CrDcSignLevelCoefficientNeighbors { get; internal set; } public required Av1NeighborArrayUnit<byte>[] CrDcSignLevelCoefficientNeighbors { get; internal set; }
@ -16,4 +18,29 @@ internal class Av1PictureControlSet
public required Av1SequenceControlSet Sequence { get; internal set; } public required Av1SequenceControlSet Sequence { get; internal set; }
public required Av1PictureParentControlSet Parent { get; internal set; } public required Av1PictureParentControlSet Parent { get; internal set; }
public required byte[] SegmentationNeighborMap { get; internal set; }
public required Av1BlockModeInfo[] ModeInfoGrid { get; internal set; }
/// <summary>
/// SVT: svt_av1_update_segmentation_map
/// </summary>
internal void UpdateSegmentation(Av1BlockSize blockSize, Point origin, int segmentId)
{
Av1Common cm = this.Parent.Common;
Span<byte> segment_ids = this.SegmentationNeighborMap;
int mi_col = origin.X >> Av1Constants.ModeInfoSizeLog2;
int mi_row = origin.Y >> Av1Constants.ModeInfoSizeLog2;
int mi_offset = (mi_row * cm.ModeInfoColumnCount) + mi_col;
int bw = blockSize.GetWidth();
int bh = blockSize.GetHeight();
int xmis = Math.Min(cm.ModeInfoColumnCount - mi_col, bw);
int ymis = Math.Min(cm.ModeInfoRowCount - mi_row, bh);
for (int y = 0; y < ymis; ++y)
{
int offset = mi_offset + (y * cm.ModeInfoColumnCount);
segment_ids.Slice(offset, xmis).Fill((byte)segmentId);
}
}
} }

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

@ -18,4 +18,6 @@ internal class Av1PictureParentControlSet
public int AlignedWidth { get; internal set; } public int AlignedWidth { get; internal set; }
public int AlignedHeight { get; internal set; } public int AlignedHeight { get; internal set; }
public required Av1SuperblockGeometry[] SuperblockGeometry { get; internal set; }
} }

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

@ -8,4 +8,6 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
internal class Av1SequenceControlSet internal class Av1SequenceControlSet
{ {
public required ObuSequenceHeader SequenceHeader { get; internal set; } public required ObuSequenceHeader SequenceHeader { get; internal set; }
public int MaxBlockCount { get; internal set; }
} }

16
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1Superblock.cs

@ -1,11 +1,17 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using static SixLabors.ImageSharp.Formats.Heif.Av1.Tiling.Av1TileWriter;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
internal partial class Av1TileWriter internal class Av1Superblock
{ {
internal class Av1Superblock public required Av1EncoderBlockStruct[] FinalBlocks { get; set; }
{
} public required Av1TileInfo TileInfo { get; set; }
public required Av1PartitionType[] CodingUnitPartitionTypes { get; internal set; }
public int Index { get; internal set; }
} }

9
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SuperblockGeometry.cs

@ -0,0 +1,9 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
internal class Av1SuperblockGeometry
{
public bool IsComplete { get; internal set; }
}

9
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileInfo.cs

@ -13,6 +13,15 @@ internal class Av1TileInfo
this.SetTileColumn(frameHeader.TilesInfo, frameHeader.ModeInfoColumnCount, column); this.SetTileColumn(frameHeader.TilesInfo, frameHeader.ModeInfoColumnCount, column);
} }
public Av1TileInfo(Av1TileInfo tileInfo)
{
this.ModeInfoColumnStart = tileInfo.ModeInfoColumnStart;
this.ModeInfoColumnEnd = tileInfo.ModeInfoColumnEnd;
this.ModeInfoRowStart = tileInfo.ModeInfoRowStart;
this.ModeInfoRowEnd = tileInfo.ModeInfoRowEnd;
this.TileIndex = tileInfo.TileIndex;
}
public int ModeInfoRowStart { get; private set; } public int ModeInfoRowStart { get; private set; }
public int ModeInfoRowEnd { get; private set; } public int ModeInfoRowEnd { get; private set; }

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

@ -1153,17 +1153,17 @@ internal class Av1TileReader : IAv1TileReader
int rowIndex = partitionInfo.RowIndex; int rowIndex = partitionInfo.RowIndex;
if (partitionInfo.AvailableAbove && partitionInfo.AvailableLeft) if (partitionInfo.AvailableAbove && partitionInfo.AvailableLeft)
{ {
prevUL = this.GetSegmentId(partitionInfo, rowIndex - 1, columnIndex - 1); prevUL = Av1SymbolContextHelper.GetSegmentId(partitionInfo, this.FrameHeader, this.segmentIds, rowIndex - 1, columnIndex - 1);
} }
if (partitionInfo.AvailableAbove) if (partitionInfo.AvailableAbove)
{ {
prevU = this.GetSegmentId(partitionInfo, rowIndex - 1, columnIndex); prevU = Av1SymbolContextHelper.GetSegmentId(partitionInfo, this.FrameHeader, this.segmentIds, rowIndex - 1, columnIndex);
} }
if (partitionInfo.AvailableLeft) if (partitionInfo.AvailableLeft)
{ {
prevU = this.GetSegmentId(partitionInfo, rowIndex, columnIndex - 1); prevU = Av1SymbolContextHelper.GetSegmentId(partitionInfo, this.FrameHeader, this.segmentIds, rowIndex, columnIndex - 1);
} }
if (prevU == -1) if (prevU == -1)
@ -1189,72 +1189,7 @@ internal class Av1TileReader : IAv1TileReader
: prevUL == prevU && prevUL == prevL ? 2 : prevUL == prevU && prevUL == prevL ? 2
: prevUL == prevU || prevUL == prevL || prevU == prevL ? 1 : 0; : prevUL == prevU || prevUL == prevL || prevU == prevL ? 1 : 0;
int lastActiveSegmentId = this.FrameHeader.SegmentationParameters.LastActiveSegmentId; int lastActiveSegmentId = this.FrameHeader.SegmentationParameters.LastActiveSegmentId;
partitionInfo.ModeInfo.SegmentId = NegativeDeinterleave(reader.ReadSegmentId(ctx), predictor, lastActiveSegmentId + 1); partitionInfo.ModeInfo.SegmentId = Av1SymbolContextHelper.NegativeDeinterleave(reader.ReadSegmentId(ctx), predictor, lastActiveSegmentId + 1);
}
}
private int GetSegmentId(Av1PartitionInfo partitionInfo, int rowIndex, int columnIndex)
{
int modeInfoOffset = (rowIndex * this.FrameHeader.ModeInfoColumnCount) + columnIndex;
int bw4 = partitionInfo.ModeInfo.BlockSize.Get4x4WideCount();
int bh4 = partitionInfo.ModeInfo.BlockSize.Get4x4HighCount();
int xMin = Math.Min(this.FrameHeader.ModeInfoColumnCount - columnIndex, bw4);
int yMin = Math.Min(this.FrameHeader.ModeInfoRowCount - rowIndex, bh4);
int segmentId = Av1Constants.MaxSegmentCount - 1;
for (int y = 0; y < yMin; y++)
{
for (int x = 0; x < xMin; x++)
{
segmentId = Math.Min(segmentId, this.segmentIds[y][x]);
}
}
return segmentId;
}
private static int NegativeDeinterleave(int diff, int reference, int max)
{
if (reference == 0)
{
return diff;
}
if (reference >= max - 1)
{
return max - diff - 1;
}
if (2 * reference < max)
{
if (diff <= 2 * reference)
{
if ((diff & 1) > 0)
{
return reference + ((diff + 1) >> 1);
}
else
{
return reference - (diff >> 1);
}
}
return diff;
}
else
{
if (diff <= 2 * (max - reference - 1))
{
if ((diff & 1) > 0)
{
return reference + ((diff + 1) >> 1);
}
else
{
return reference - (diff >> 1);
}
}
return max - (diff + 1);
} }
} }

1050
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileWriter.cs

File diff suppressed because it is too large
Loading…
Cancel
Save