Browse Source

Return span of TransformInfos from FrameInfo

pull/2633/head
Ynse Hoornenborg 1 year ago
parent
commit
be75282afe
  1. 14
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs
  2. 4
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SuperblockInfo.cs
  3. 18
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs
  4. 23
      src/ImageSharp/Formats/Heif/Av1/Transform/Av1BlockDecoder.cs

14
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs

@ -113,28 +113,28 @@ internal partial class Av1FrameInfo
return this.modeInfos[index]; return this.modeInfos[index];
} }
public ref Av1TransformInfo GetSuperblockTransform(int plane, Point index) public Span<Av1TransformInfo> GetSuperblockTransform(int plane, Point index)
{ {
if (plane == 0) if (plane == 0)
{ {
return ref this.GetSuperblockTransformY(index); return this.GetSuperblockTransformY(index);
} }
return ref this.GetSuperblockTransformUv(index); return this.GetSuperblockTransformUv(index);
} }
public ref Av1TransformInfo GetSuperblockTransformY(Point index) public Span<Av1TransformInfo> GetSuperblockTransformY(Point index)
{ {
Span<Av1TransformInfo> span = this.transformInfosY; Span<Av1TransformInfo> span = this.transformInfosY;
int offset = ((index.Y * this.superblockColumnCount) + index.X) * this.modeInfoCountPerSuperblock; int offset = ((index.Y * this.superblockColumnCount) + index.X) * this.modeInfoCountPerSuperblock;
return ref span[offset]; return span.Slice(offset, this.modeInfoCountPerSuperblock);
} }
public ref Av1TransformInfo GetSuperblockTransformUv(Point index) public Span<Av1TransformInfo> GetSuperblockTransformUv(Point index)
{ {
Span<Av1TransformInfo> span = this.transformInfosUv; Span<Av1TransformInfo> span = this.transformInfosUv;
int offset = (((index.Y * this.superblockColumnCount) + index.X) * this.modeInfoCountPerSuperblock) << 1; int offset = (((index.Y * this.superblockColumnCount) + index.X) * this.modeInfoCountPerSuperblock) << 1;
return ref span[offset]; return span.Slice(offset, this.modeInfoCountPerSuperblock);
} }
public Span<int> GetCoefficients(int plane) => public Span<int> GetCoefficients(int plane) =>

4
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SuperblockInfo.cs

@ -43,9 +43,9 @@ internal class Av1SuperblockInfo
public int BlockCount { get; internal set; } public int BlockCount { get; internal set; }
public ref Av1TransformInfo GetTransformInfoY() => ref this.frameInfo.GetSuperblockTransformY(this.Position); public Span<Av1TransformInfo> GetTransformInfoY() => this.frameInfo.GetSuperblockTransformY(this.Position);
public ref Av1TransformInfo GetTransformInfoUv() => ref this.frameInfo.GetSuperblockTransformUv(this.Position); public Span<Av1TransformInfo> GetTransformInfoUv() => this.frameInfo.GetSuperblockTransformUv(this.Position);
public Av1BlockModeInfo GetModeInfo(Point index) => this.frameInfo.GetModeInfo(this.Position, index); public Av1BlockModeInfo GetModeInfo(Point index) => this.frameInfo.GetModeInfo(this.Position, index);

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

@ -413,13 +413,13 @@ internal class Av1TileReader : IAv1TileReader
continue; continue;
} }
ref Av1TransformInfo transformInfoRef = ref (plane == 0) ? ref superblockInfo.GetTransformInfoY() : ref superblockInfo.GetTransformInfoUv(); Span<Av1TransformInfo> transformInfoSpan = (plane == 0) ? superblockInfo.GetTransformInfoY() : superblockInfo.GetTransformInfoUv();
if (isLosslessBlock) if (isLosslessBlock)
{ {
// TODO: Implement. // TODO: Implement.
int unitHeight = Av1Math.RoundPowerOf2(Math.Min(modeUnitBlocksHigh + row, maxBlocksHigh), 0); int unitHeight = Av1Math.RoundPowerOf2(Math.Min(modeUnitBlocksHigh + row, maxBlocksHigh), 0);
int unitWidth = Av1Math.RoundPowerOf2(Math.Min(modeUnitBlocksWide + column, maxBlocksWide), 0); int unitWidth = Av1Math.RoundPowerOf2(Math.Min(modeUnitBlocksWide + column, maxBlocksWide), 0);
DebugGuard.IsTrue(Unsafe.Add(ref transformInfoRef, transformInfoIndices[plane]).Size == Av1TransformSize.Size4x4, "Lossless frame shall have transform units of size 4x4."); DebugGuard.IsTrue(transformInfoSpan[transformInfoIndices[plane]].Size == Av1TransformSize.Size4x4, "Lossless frame shall have transform units of size 4x4.");
transformUnitCount = ((unitWidth - column) * (unitHeight - row)) >> (subX + subY); transformUnitCount = ((unitWidth - column) * (unitHeight - row)) >> (subX + subY);
} }
else else
@ -439,7 +439,7 @@ internal class Av1TileReader : IAv1TileReader
DebugGuard.IsFalse(transformUnitCount == 0, nameof(transformUnitCount), string.Empty); DebugGuard.IsFalse(transformUnitCount == 0, nameof(transformUnitCount), string.Empty);
for (int tu = 0; tu < transformUnitCount; tu++) for (int tu = 0; tu < transformUnitCount; tu++)
{ {
Av1TransformInfo transformInfo = Unsafe.Add(ref transformInfoRef, transformInfoIndices[plane]); Av1TransformInfo transformInfo = transformInfoSpan[transformInfoIndices[plane]];
DebugGuard.MustBeLessThanOrEqualTo(transformInfo.OffsetX, maxBlocksWide, nameof(transformInfo)); DebugGuard.MustBeLessThanOrEqualTo(transformInfo.OffsetX, maxBlocksWide, nameof(transformInfo));
DebugGuard.MustBeLessThanOrEqualTo(transformInfo.OffsetY, maxBlocksHigh, nameof(transformInfo)); DebugGuard.MustBeLessThanOrEqualTo(transformInfo.OffsetY, maxBlocksHigh, nameof(transformInfo));
@ -830,8 +830,8 @@ internal class Av1TileReader : IAv1TileReader
{ {
int transformInfoYIndex = partitionInfo.ModeInfo.FirstTransformLocation[(int)Av1PlaneType.Y]; int transformInfoYIndex = partitionInfo.ModeInfo.FirstTransformLocation[(int)Av1PlaneType.Y];
int transformInfoUvIndex = partitionInfo.ModeInfo.FirstTransformLocation[(int)Av1PlaneType.Uv]; int transformInfoUvIndex = partitionInfo.ModeInfo.FirstTransformLocation[(int)Av1PlaneType.Uv];
ref Av1TransformInfo lumaTransformInfo = ref superblockInfo.GetTransformInfoY(); Span<Av1TransformInfo> lumaTransformInfo = superblockInfo.GetTransformInfoY();
ref Av1TransformInfo chromaTransformInfo = ref superblockInfo.GetTransformInfoUv(); Span<Av1TransformInfo> chromaTransformInfo = superblockInfo.GetTransformInfoUv();
int totalLumaTransformUnitCount = 0; int totalLumaTransformUnitCount = 0;
int totalChromaTransformUnitCount = 0; int totalChromaTransformUnitCount = 0;
int forceSplitCount = 0; int forceSplitCount = 0;
@ -864,7 +864,7 @@ internal class Av1TileReader : IAv1TileReader
{ {
for (int blockColumn = idx; blockColumn < unitWidth; blockColumn += stepColumn) for (int blockColumn = idx; blockColumn < unitWidth; blockColumn += stepColumn)
{ {
Unsafe.Add(ref lumaTransformInfo, transformInfoYIndex) = new Av1TransformInfo( lumaTransformInfo[transformInfoYIndex] = new Av1TransformInfo(
transformSize, blockColumn, blockRow); transformSize, blockColumn, blockRow);
transformInfoYIndex++; transformInfoYIndex++;
lumaTransformUnitCount++; lumaTransformUnitCount++;
@ -889,7 +889,7 @@ internal class Av1TileReader : IAv1TileReader
{ {
for (int blockColumn = idx; blockColumn < unitWidth; blockColumn += stepColumn) for (int blockColumn = idx; blockColumn < unitWidth; blockColumn += stepColumn)
{ {
Unsafe.Add(ref chromaTransformInfo, transformInfoUvIndex) = new Av1TransformInfo( chromaTransformInfo[transformInfoUvIndex] = new Av1TransformInfo(
transformSizeUv, blockColumn, blockRow); transformSizeUv, blockColumn, blockRow);
transformInfoUvIndex++; transformInfoUvIndex++;
chromaTransformUnitCount++; chromaTransformUnitCount++;
@ -910,8 +910,8 @@ internal class Av1TileReader : IAv1TileReader
partitionInfo.ModeInfo.FirstTransformLocation[(int)Av1PlaneType.Uv], partitionInfo.ModeInfo.FirstTransformLocation[(int)Av1PlaneType.Uv],
nameof(totalChromaTransformUnitCount)); nameof(totalChromaTransformUnitCount));
int originalIndex = transformInfoUvIndex - totalChromaTransformUnitCount; int originalIndex = transformInfoUvIndex - totalChromaTransformUnitCount;
ref Av1TransformInfo originalInfo = ref Unsafe.Add(ref chromaTransformInfo, originalIndex); ref Av1TransformInfo originalInfo = ref chromaTransformInfo[originalIndex];
ref Av1TransformInfo infoV = ref Unsafe.Add(ref chromaTransformInfo, transformInfoUvIndex); ref Av1TransformInfo infoV = ref chromaTransformInfo[transformInfoUvIndex];
for (int i = 0; i < totalChromaTransformUnitCount; i++) for (int i = 0; i < totalChromaTransformUnitCount; i++)
{ {
infoV = originalInfo; infoV = originalInfo;

23
src/ImageSharp/Formats/Heif/Av1/Transform/Av1BlockDecoder.cs

@ -75,8 +75,8 @@ internal class Av1BlockDecoder
for (int plane = 0; plane < colorConfig.PlaneCount; plane++) for (int plane = 0; plane < colorConfig.PlaneCount; plane++)
{ {
int subX = (plane > 0) ? colorConfig.SubSamplingX ? 1 : 0 : 0; int subX = (plane > 0) && colorConfig.SubSamplingX ? 1 : 0;
int subY = (plane > 0) ? colorConfig.SubSamplingY ? 1 : 0 : 0; int subY = (plane > 0) && colorConfig.SubSamplingY ? 1 : 0;
if (plane != 0 && !partitionInfo.IsChroma) if (plane != 0 && !partitionInfo.IsChroma)
{ {
@ -90,11 +90,12 @@ internal class Av1BlockDecoder
0 => superblockInfo.TransformInfoIndexY + modeInfo.FirstTransformLocation[plane], 0 => superblockInfo.TransformInfoIndexY + modeInfo.FirstTransformLocation[plane],
_ => throw new InvalidImageContentException("Maximum of 3 color planes") _ => throw new InvalidImageContentException("Maximum of 3 color planes")
}; };
ref Av1TransformInfo transformInfo = ref Unsafe.Add(ref this.frameInfo.GetSuperblockTransform(plane, superblockInfo.Position), transformInfoIndex); Span<Av1TransformInfo> transformInfo = this.frameInfo.GetSuperblockTransform(plane, superblockInfo.Position)[transformInfoIndex..];
Guard.NotNull(transformInfo[0]);
if (isLosslessBlock) if (isLosslessBlock)
{ {
Guard.IsTrue(transformInfo.Size == Av1TransformSize.Size4x4, nameof(transformInfo.Size), "Lossless may only have 4x4 blocks."); Guard.IsTrue(transformInfo[0].Size == Av1TransformSize.Size4x4, nameof(transformInfo), "Lossless may only have 4x4 blocks.");
transformUnitCount = (maxBlocksWide * maxBlocksHigh) >> (subX + subY); transformUnitCount = (maxBlocksWide * maxBlocksHigh) >> (subX + subY);
} }
else else
@ -120,10 +121,10 @@ internal class Av1BlockDecoder
Span<byte> transformBlockReconstructionBuffer; Span<byte> transformBlockReconstructionBuffer;
int transformBlockOffset; int transformBlockOffset;
transformSize = transformInfo.Size; transformSize = transformInfo[0].Size;
Span<int> coefficients = superblockInfo.GetCoefficients((Av1Plane)plane)[this.currentCoefficientIndex[plane]..]; Span<int> coefficients = superblockInfo.GetCoefficients((Av1Plane)plane)[this.currentCoefficientIndex[plane]..];
transformBlockOffset = ((transformInfo.OffsetY * reconstructionStride) + transformInfo.OffsetX) << Av1Constants.ModeInfoSizeLog2; transformBlockOffset = ((transformInfo[0].OffsetY * reconstructionStride) + transformInfo[0].OffsetX) << Av1Constants.ModeInfoSizeLog2;
transformBlockReconstructionBuffer = blockReconstructionBuffer.Slice(transformBlockOffset << (highBitDepth ? 1 : 0)); transformBlockReconstructionBuffer = blockReconstructionBuffer.Slice(transformBlockOffset << (highBitDepth ? 1 : 0));
if (this.isLoopFilterEnabled) if (this.isLoopFilterEnabled)
@ -156,18 +157,18 @@ internal class Av1BlockDecoder
transformBlockReconstructionBuffer, transformBlockReconstructionBuffer,
reconstructionStride, reconstructionStride,
this.frameBuffer.BitDepth, this.frameBuffer.BitDepth,
transformInfo.OffsetX, transformInfo[0].OffsetX,
transformInfo.OffsetY); transformInfo[0].OffsetY);
} }
int numberOfCoefficients = 0; int numberOfCoefficients = 0;
if (!modeInfo.Skip && transformInfo.CodeBlockFlag) if (!modeInfo.Skip && transformInfo[0].CodeBlockFlag)
{ {
Span<int> quantizationCoefficients = this.CurrentInverseQuantizationCoefficients; Span<int> quantizationCoefficients = this.CurrentInverseQuantizationCoefficients;
int inverseQuantizationSize = transformSize.GetWidth() * transformSize.GetHeight(); int inverseQuantizationSize = transformSize.GetWidth() * transformSize.GetHeight();
quantizationCoefficients[..inverseQuantizationSize].Clear(); quantizationCoefficients[..inverseQuantizationSize].Clear();
transformType = transformInfo.Type; transformType = transformInfo[0].Type;
// SVT: svt_aom_inverse_quantize // SVT: svt_aom_inverse_quantize
numberOfCoefficients = inverseQuantizer.InverseQuantize( numberOfCoefficients = inverseQuantizer.InverseQuantize(
@ -216,7 +217,7 @@ internal class Av1BlockDecoder
} }
// increment transform pointer // increment transform pointer
transformInfo = ref Unsafe.Add(ref transformInfo, 1); transformInfo = transformInfo[1..];
} }
} }
} }

Loading…
Cancel
Save