Browse Source

Introduce Av1FrameBuffer class and renaming others

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
0ff8911047
  1. 17
      src/ImageSharp/Formats/Heif/Av1/Av1BlockModeInfo.cs
  2. 6
      src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs
  3. 188
      src/ImageSharp/Formats/Heif/Av1/Av1FrameBuffer.cs
  4. 252
      src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs
  5. 88
      src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs
  6. 2
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockModeInfo.cs
  7. 27
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs
  8. 4
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameModeInfoMap.cs
  9. 6
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1PartitionInfo.cs
  10. 26
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SuperblockInfo.cs
  11. 6
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileInfo.cs
  12. 172
      src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs
  13. 8
      src/ImageSharp/Formats/Heif/Av1/Transform/Av1FrameDecoder.cs
  14. 1
      src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseQuantizer.cs

17
src/ImageSharp/Formats/Heif/Av1/Av1BlockModeInfo.cs

@ -1,17 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Heif.Av1.Prediction;
namespace SixLabors.ImageSharp.Formats.Heif.Av1;
internal class Av1BlockModeInfo
{
public Av1BlockSize BlockSize { get; }
public Av1PredictionMode PredictionMode { get; }
public Av1PartitionType Partition { get; set; }
public int SegmentId { get; }
}

6
src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs

@ -19,7 +19,7 @@ internal class Av1Decoder : IAv1TileReader
public ObuSequenceHeader? SequenceHeader { get; private set; }
public Av1FrameBuffer? FrameBuffer { get; private set; }
public Av1FrameInfo? FrameInfo { get; private set; }
public void Decode(Span<byte> buffer)
{
@ -29,8 +29,8 @@ internal class Av1Decoder : IAv1TileReader
Guard.NotNull(this.SequenceHeader, nameof(this.SequenceHeader));
Guard.NotNull(this.FrameHeader, nameof(this.FrameHeader));
this.FrameBuffer = this.tileReader.FrameBuffer;
this.frameDecoder = new(this.SequenceHeader, this.FrameHeader, this.FrameBuffer);
this.FrameInfo = this.tileReader.FrameInfo;
this.frameDecoder = new(this.SequenceHeader, this.FrameHeader, this.FrameInfo);
this.frameDecoder.DecodeFrame();
}

188
src/ImageSharp/Formats/Heif/Av1/Av1FrameBuffer.cs

@ -0,0 +1,188 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Heif.Av1;
/// <summary>
/// Buffer for the pixels of a single frame.
/// </summary>
internal class Av1FrameBuffer : IDisposable
{
private const int DecoderPaddingValue = 72;
private const int PictureBufferYFlag = 1 << 0;
private const int PictureBufferCbFlag = 1 << 1;
private const int PictureBufferCrFlag = 1 << 2;
private const int PictureBufferLumaMask = PictureBufferYFlag;
private const int PictureBufferFullMask = PictureBufferYFlag | PictureBufferCbFlag | PictureBufferCrFlag;
public Av1FrameBuffer(Configuration configuration, ObuSequenceHeader sequenceHeader, Av1ColorFormat maxColorFormat, bool is16BitPipeline)
{
Av1ColorFormat colorFormat = sequenceHeader.ColorConfig.IsMonochrome ? Av1ColorFormat.Yuv400 : maxColorFormat;
this.MaxWidth = sequenceHeader.MaxFrameWidth;
this.MaxHeight = sequenceHeader.MaxFrameHeight;
this.BitDepth = (Av1BitDepth)sequenceHeader.ColorConfig.BitDepth;
int bitsPerPixel = this.BitDepth > Av1BitDepth.EightBit || is16BitPipeline ? 2 : 1;
this.ColorFormat = colorFormat;
this.BufferEnableMask = sequenceHeader.ColorConfig.IsMonochrome ? PictureBufferLumaMask : PictureBufferFullMask;
int leftPadding = DecoderPaddingValue;
int rightPadding = DecoderPaddingValue;
int topPadding = DecoderPaddingValue;
int bottomPadding = DecoderPaddingValue;
this.Width = this.MaxWidth;
this.Height = this.MaxHeight;
int strideY = this.MaxWidth + leftPadding + rightPadding;
int heightY = this.MaxHeight + topPadding + bottomPadding;
this.OriginX = leftPadding;
this.OriginY = topPadding;
this.OriginOriginY = bottomPadding;
int strideChroma = 0;
int heightChroma = 0;
switch (this.ColorFormat)
{
case Av1ColorFormat.Yuv420:
strideChroma = (strideY + 1) >> 1;
heightChroma = (this.Height + 1) >> 1;
break;
case Av1ColorFormat.Yuv422:
strideChroma = (strideY + 1) >> 1;
heightChroma = this.Height;
break;
case Av1ColorFormat.Yuv444:
strideChroma = strideY;
heightChroma = this.Height;
break;
}
this.PackedFlag = false;
this.BufferY = null;
this.BufferCb = null;
this.BufferCr = null;
if ((this.BufferEnableMask & PictureBufferYFlag) != 0)
{
this.BufferY = configuration.MemoryAllocator.Allocate2D<byte>(strideY * bitsPerPixel, heightY);
}
if ((this.BufferEnableMask & PictureBufferCbFlag) != 0)
{
this.BufferCb = configuration.MemoryAllocator.Allocate2D<byte>(strideChroma * bitsPerPixel, heightChroma);
}
if ((this.BufferEnableMask & PictureBufferCrFlag) != 0)
{
this.BufferCr = configuration.MemoryAllocator.Allocate2D<byte>(strideChroma * bitsPerPixel, heightChroma);
}
this.BitIncrementY = null;
this.BitIncrementCb = null;
this.BitIncrementCr = null;
this.BitIncrementY = null;
this.BitIncrementCb = null;
this.BitIncrementCr = null;
}
/// <summary>
/// Gets the Y luma buffer.
/// </summary>
public Buffer2D<byte>? BufferY { get; private set; }
/// <summary>
/// Gets the U chroma buffer.
/// </summary>
public Buffer2D<byte>? BufferCb { get; private set; }
/// <summary>
/// Gets the V chroma buffer.
/// </summary>
public Buffer2D<byte>? BufferCr { get; private set; }
public Buffer2D<byte>? BitIncrementY { get; private set; }
public Buffer2D<byte>? BitIncrementCb { get; private set; }
public Buffer2D<byte>? BitIncrementCr { get; private set; }
/// <summary>
/// Gets or sets the horizontal padding distance.
/// </summary>
public int OriginX { get; set; }
/// <summary>
/// Gets or sets the vertical padding distance.
/// </summary>
public int OriginY { get; set; }
/// <summary>
/// Gets or sets the vertical bottom padding distance
/// </summary>
public int OriginOriginY { get; set; }
/// <summary>
/// Gets or sets the Luma picture width, which excludes the padding.
/// </summary>
public int Width { get; set; }
/// <summary>
/// Gets or sets the Luma picture height, which excludes the padding.
/// </summary>
public int Height { get; set; }
/// <summary>
/// Gets or sets the Lume picture width.
/// </summary>
public int MaxWidth { get; set; }
/// <summary>
/// Gets or sets the pixel bit depth.
/// </summary>
public Av1BitDepth BitDepth { get; set; }
/// <summary>
/// Gets or sets the chroma subsampling.
/// </summary>
public Av1ColorFormat ColorFormat { get; set; }
/// <summary>
/// Gets or sets the Luma picture height.
/// </summary>
public int MaxHeight { get; set; }
public int LumaSize { get; }
public int ChromaSize { get; }
/// <summary>
/// Gets or sets a value indicating whether the bytes of the buffers are packed.
/// </summary>
public bool PackedFlag { get; set; }
/// <summary>
/// Gets or sets a value indicating whether film grain parameters are present for this frame.
/// </summary>
public bool FilmGrainFlag { get; set; }
public int BufferEnableMask { get; set; }
public bool Is16BitPipeline { get; set; }
public void Dispose()
{
this.BufferY?.Dispose();
this.BufferY = null;
this.BufferCb?.Dispose();
this.BufferCb = null;
this.BufferCr?.Dispose();
this.BufferCr = null;
this.BitIncrementY?.Dispose();
this.BitIncrementY = null;
this.BitIncrementCb?.Dispose();
this.BitIncrementCb = null;
this.BitIncrementCr?.Dispose();
this.BitIncrementCr = null;
}
}

252
src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs

@ -241,10 +241,10 @@ internal class ObuReader
private void ComputeImageSize(ObuSequenceHeader sequenceHeader)
{
ObuFrameHeader frameInfo = this.FrameHeader!;
frameInfo.ModeInfoColumnCount = 2 * ((frameInfo.FrameSize.FrameWidth + 7) >> 3);
frameInfo.ModeInfoRowCount = 2 * ((frameInfo.FrameSize.FrameHeight + 7) >> 3);
frameInfo.ModeInfoStride = Av1Math.AlignPowerOf2(sequenceHeader.MaxFrameWidth, Av1Constants.MaxSuperBlockSizeLog2) >> Av1Constants.ModeInfoSizeLog2;
ObuFrameHeader frameHeader = this.FrameHeader!;
frameHeader.ModeInfoColumnCount = 2 * ((frameHeader.FrameSize.FrameWidth + 7) >> 3);
frameHeader.ModeInfoRowCount = 2 * ((frameHeader.FrameSize.FrameHeight + 7) >> 3);
frameHeader.ModeInfoStride = Av1Math.AlignPowerOf2(sequenceHeader.MaxFrameWidth, Av1Constants.MaxSuperBlockSizeLog2) >> Av1Constants.ModeInfoSizeLog2;
}
/// <summary>
@ -582,7 +582,7 @@ internal class ObuReader
private void ReadSuperResolutionParameters(ref Av1BitStreamReader reader)
{
ObuSequenceHeader sequenceHeader = this.SequenceHeader!;
ObuFrameHeader frameInfo = this.FrameHeader!;
ObuFrameHeader frameHeader = this.FrameHeader!;
bool useSuperResolution = false;
if (sequenceHeader.EnableSuperResolution)
{
@ -591,24 +591,24 @@ internal class ObuReader
if (useSuperResolution)
{
frameInfo.FrameSize.SuperResolutionDenominator = (int)reader.ReadLiteral(Av1Constants.SuperResolutionScaleBits) + Av1Constants.SuperResolutionScaleDenominatorMinimum;
frameHeader.FrameSize.SuperResolutionDenominator = (int)reader.ReadLiteral(Av1Constants.SuperResolutionScaleBits) + Av1Constants.SuperResolutionScaleDenominatorMinimum;
}
else
{
frameInfo.FrameSize.SuperResolutionDenominator = Av1Constants.ScaleNumerator;
frameHeader.FrameSize.SuperResolutionDenominator = Av1Constants.ScaleNumerator;
}
frameInfo.FrameSize.SuperResolutionUpscaledWidth = frameInfo.FrameSize.FrameWidth;
frameInfo.FrameSize.FrameWidth =
((frameInfo.FrameSize.SuperResolutionUpscaledWidth * Av1Constants.ScaleNumerator) +
(frameInfo.FrameSize.SuperResolutionDenominator / 2)) /
frameInfo.FrameSize.SuperResolutionDenominator;
frameHeader.FrameSize.SuperResolutionUpscaledWidth = frameHeader.FrameSize.FrameWidth;
frameHeader.FrameSize.FrameWidth =
((frameHeader.FrameSize.SuperResolutionUpscaledWidth * Av1Constants.ScaleNumerator) +
(frameHeader.FrameSize.SuperResolutionDenominator / 2)) /
frameHeader.FrameSize.SuperResolutionDenominator;
/*
if (frameInfo.FrameSize.SuperResolutionDenominator != Av1Constants.ScaleNumerator)
if (frameHeader.FrameSize.SuperResolutionDenominator != Av1Constants.ScaleNumerator)
{
int manWidth = Math.Min(16, frameInfo.FrameSize.SuperResolutionUpscaledWidth);
frameInfo.FrameSize.FrameWidth = Math.Max(manWidth, frameInfo.FrameSize.FrameWidth);
int manWidth = Math.Min(16, frameHeader.FrameSize.SuperResolutionUpscaledWidth);
frameHeader.FrameSize.FrameWidth = Math.Max(manWidth, frameHeader.FrameSize.FrameWidth);
}
*/
}
@ -618,17 +618,17 @@ internal class ObuReader
/// </summary>
private void ReadRenderSize(ref Av1BitStreamReader reader)
{
ObuFrameHeader frameInfo = this.FrameHeader!;
ObuFrameHeader frameHeader = this.FrameHeader!;
bool renderSizeAndFrameSizeDifferent = reader.ReadBoolean();
if (renderSizeAndFrameSizeDifferent)
{
frameInfo.FrameSize.RenderWidth = (int)reader.ReadLiteral(16) + 1;
frameInfo.FrameSize.RenderHeight = (int)reader.ReadLiteral(16) + 1;
frameHeader.FrameSize.RenderWidth = (int)reader.ReadLiteral(16) + 1;
frameHeader.FrameSize.RenderHeight = (int)reader.ReadLiteral(16) + 1;
}
else
{
frameInfo.FrameSize.RenderWidth = frameInfo.FrameSize.SuperResolutionUpscaledWidth;
frameInfo.FrameSize.RenderHeight = frameInfo.FrameSize.FrameHeight;
frameHeader.FrameSize.RenderWidth = frameHeader.FrameSize.SuperResolutionUpscaledWidth;
frameHeader.FrameSize.RenderHeight = frameHeader.FrameSize.FrameHeight;
}
}
@ -638,16 +638,16 @@ internal class ObuReader
private void ReadFrameSize(ref Av1BitStreamReader reader, bool frameSizeOverrideFlag)
{
ObuSequenceHeader sequenceHeader = this.SequenceHeader!;
ObuFrameHeader frameInfo = this.FrameHeader!;
ObuFrameHeader frameHeader = this.FrameHeader!;
if (frameSizeOverrideFlag)
{
frameInfo.FrameSize.FrameWidth = (int)reader.ReadLiteral(sequenceHeader.FrameWidthBits) + 1;
frameInfo.FrameSize.FrameHeight = (int)reader.ReadLiteral(sequenceHeader.FrameHeightBits) + 1;
frameHeader.FrameSize.FrameWidth = (int)reader.ReadLiteral(sequenceHeader.FrameWidthBits) + 1;
frameHeader.FrameSize.FrameHeight = (int)reader.ReadLiteral(sequenceHeader.FrameHeightBits) + 1;
}
else
{
frameInfo.FrameSize.FrameWidth = sequenceHeader.MaxFrameWidth;
frameInfo.FrameSize.FrameHeight = sequenceHeader.MaxFrameHeight;
frameHeader.FrameSize.FrameWidth = sequenceHeader.MaxFrameWidth;
frameHeader.FrameSize.FrameHeight = sequenceHeader.MaxFrameHeight;
}
this.ReadSuperResolutionParameters(ref reader);
@ -657,15 +657,15 @@ internal class ObuReader
/// <summary>
/// 5.9.15. Tile info syntax.
/// </summary>
private static ObuTileGroupHeader ReadTileInfo(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo)
private static ObuTileGroupHeader ReadTileInfo(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{
ObuTileGroupHeader tileInfo = new();
int superblockColumnCount;
int superblockRowCount;
int superblockSizeLog2 = sequenceHeader.SuperblockSizeLog2;
int superblockShift = superblockSizeLog2 - Av1Constants.ModeInfoSizeLog2;
superblockColumnCount = (frameInfo.ModeInfoColumnCount + sequenceHeader.SuperblockModeInfoSize - 1) >> superblockShift;
superblockRowCount = (frameInfo.ModeInfoRowCount + sequenceHeader.SuperblockModeInfoSize - 1) >> superblockShift;
superblockColumnCount = (frameHeader.ModeInfoColumnCount + sequenceHeader.SuperblockModeInfoSize - 1) >> superblockShift;
superblockRowCount = (frameHeader.ModeInfoRowCount + sequenceHeader.SuperblockModeInfoSize - 1) >> superblockShift;
int maxTileAreaOfSuperBlock = Av1Constants.MaxTileArea >> (superblockSizeLog2 << 1);
@ -701,7 +701,7 @@ internal class ObuReader
i++;
}
tileInfo.TileColumnStartModeInfo[i] = frameInfo.ModeInfoColumnCount;
tileInfo.TileColumnStartModeInfo[i] = frameHeader.ModeInfoColumnCount;
tileInfo.TileColumnCount = i;
tileInfo.MinLog2TileRowCount = Math.Max(tileInfo.MinLog2TileCount - tileInfo.TileColumnCountLog2, 0);
@ -728,7 +728,7 @@ internal class ObuReader
i++;
}
tileInfo.TileRowStartModeInfo[i] = frameInfo.ModeInfoRowCount;
tileInfo.TileRowStartModeInfo[i] = frameHeader.ModeInfoRowCount;
tileInfo.TileRowCount = i;
}
else
@ -750,7 +750,7 @@ internal class ObuReader
throw new ImageFormatException("Super block tiles width does not add up to total width.");
}
tileInfo.TileColumnStartModeInfo[i] = frameInfo.ModeInfoColumnCount;
tileInfo.TileColumnStartModeInfo[i] = frameHeader.ModeInfoColumnCount;
tileInfo.TileColumnCount = i;
tileInfo.TileColumnCountLog2 = TileLog2(1, tileInfo.TileColumnCount);
if (tileInfo.MinLog2TileCount > 0)
@ -779,7 +779,7 @@ internal class ObuReader
throw new ImageFormatException("Super block tiles height does not add up to total height.");
}
tileInfo.TileRowStartModeInfo[i] = frameInfo.ModeInfoRowCount;
tileInfo.TileRowStartModeInfo[i] = frameHeader.ModeInfoRowCount;
tileInfo.TileRowCount = i;
tileInfo.TileRowCountLog2 = TileLog2(1, tileInfo.TileRowCount);
}
@ -1035,10 +1035,10 @@ internal class ObuReader
throw new InvalidImageContentException("AVIF image can only contain INTRA frames.");
}
// SetupFrameBufferReferences(sequenceHeader, frameInfo);
// CheckAddTemporalMotionVectorBuffer(sequenceHeader, frameInfo);
// SetupFrameBufferReferences(sequenceHeader, frameHeader);
// CheckAddTemporalMotionVectorBuffer(sequenceHeader, frameHeader);
// SetupFrameSignBias(sequenceHeader, frameInfo);
// SetupFrameSignBias(sequenceHeader, frameHeader);
if (sequenceHeader.IsReducedStillPictureHeader || frameHeader.DisableCdfUpdate)
{
frameHeader.DisableFrameEndUpdateCdf = true;
@ -1055,7 +1055,7 @@ internal class ObuReader
}
else
{
// LoadCdfs(frameInfo.PrimaryReferenceFrame);
// LoadCdfs(frameHeader.PrimaryReferenceFrame);
// LoadPrevious();
throw new NotImplementedException();
}
@ -1066,7 +1066,7 @@ internal class ObuReader
throw new NotImplementedException();
}
// GenerateNextReferenceFrameMap(sequenceHeader, frameInfo);
// GenerateNextReferenceFrameMap(sequenceHeader, frameHeader);
frameHeader.TilesInfo = ReadTileInfo(ref reader, sequenceHeader, frameHeader);
ReadQuantizationParameters(ref reader, sequenceHeader, frameHeader);
ReadSegmentationParameters(ref reader, frameHeader);
@ -1076,7 +1076,7 @@ internal class ObuReader
// SetupSegmentationDequantization();
if (frameHeader.PrimaryReferenceFrame == Av1Constants.PrimaryReferenceFrameNone)
{
// ResetParseContext(mainParseContext, frameInfo.QuantizationParameters.BaseQIndex);
// ResetParseContext(mainParseContext, frameHeader.QuantizationParameters.BaseQIndex);
}
else
{
@ -1190,7 +1190,7 @@ internal class ObuReader
private void ReadTileGroup(ref Av1BitStreamReader reader, IAv1TileReader decoder, ObuHeader header, out bool isLastTileGroup)
{
ObuSequenceHeader sequenceHeader = this.SequenceHeader!;
ObuFrameHeader frameInfo = this.FrameHeader!;
ObuFrameHeader frameHeader = this.FrameHeader!;
ObuTileGroupHeader tileInfo = this.FrameHeader!.TilesInfo;
int tileCount = tileInfo.TileColumnCount * tileInfo.TileRowCount;
int startBitPosition = reader.BitPosition;
@ -1220,16 +1220,16 @@ internal class ObuReader
int headerBytes = (endBitPosition - startBitPosition) / 8;
header.PayloadSize -= headerBytes;
bool noIbc = !frameInfo.AllowIntraBlockCopy;
bool doLoopFilter = noIbc && (frameInfo.LoopFilterParameters.FilterLevel[0] != 0 || frameInfo.LoopFilterParameters.FilterLevel[1] != 0);
bool doCdef = noIbc && (!frameInfo.CodedLossless &&
(frameInfo.CdefParameters.BitCount != 0 ||
frameInfo.CdefParameters.YStrength[0] != 0 ||
frameInfo.CdefParameters.UvStrength[0] != 0));
bool noIbc = !frameHeader.AllowIntraBlockCopy;
bool doLoopFilter = noIbc && (frameHeader.LoopFilterParameters.FilterLevel[0] != 0 || frameHeader.LoopFilterParameters.FilterLevel[1] != 0);
bool doCdef = noIbc && (!frameHeader.CodedLossless &&
(frameHeader.CdefParameters.BitCount != 0 ||
frameHeader.CdefParameters.YStrength[0] != 0 ||
frameHeader.CdefParameters.UvStrength[0] != 0));
bool doLoopRestoration = noIbc &&
(frameInfo.LoopRestorationParameters.Items[(int)Av1Plane.Y].Type != ObuRestorationType.None ||
frameInfo.LoopRestorationParameters.Items[(int)Av1Plane.U].Type != ObuRestorationType.None ||
frameInfo.LoopRestorationParameters.Items[(int)Av1Plane.V].Type != ObuRestorationType.None);
(frameHeader.LoopRestorationParameters.Items[(int)Av1Plane.Y].Type != ObuRestorationType.None ||
frameHeader.LoopRestorationParameters.Items[(int)Av1Plane.U].Type != ObuRestorationType.None ||
frameHeader.LoopRestorationParameters.Items[(int)Av1Plane.V].Type != ObuRestorationType.None);
for (int tileNum = tileGroupStart; tileNum <= tileGroupEnd; tileNum++)
{
@ -1270,40 +1270,40 @@ internal class ObuReader
/// <summary>
/// 5.9.17. Quantizer index delta parameters syntax.
/// </summary>
private static void ReadFrameDeltaQParameters(ref Av1BitStreamReader reader, ObuFrameHeader frameInfo)
private static void ReadFrameDeltaQParameters(ref Av1BitStreamReader reader, ObuFrameHeader frameHeader)
{
frameInfo.DeltaQParameters.Resolution = 0;
frameInfo.DeltaQParameters.IsPresent = false;
if (frameInfo.QuantizationParameters.BaseQIndex > 0)
frameHeader.DeltaQParameters.Resolution = 0;
frameHeader.DeltaQParameters.IsPresent = false;
if (frameHeader.QuantizationParameters.BaseQIndex > 0)
{
frameInfo.DeltaQParameters.IsPresent = reader.ReadBoolean();
frameHeader.DeltaQParameters.IsPresent = reader.ReadBoolean();
}
if (frameInfo.DeltaQParameters.IsPresent)
if (frameHeader.DeltaQParameters.IsPresent)
{
frameInfo.DeltaQParameters.Resolution = (int)reader.ReadLiteral(2);
frameHeader.DeltaQParameters.Resolution = (int)reader.ReadLiteral(2);
}
}
/// <summary>
/// 5.9.18. Loop filter delta parameters syntax.
/// </summary>
private static void ReadFrameDeltaLoopFilterParameters(ref Av1BitStreamReader reader, ObuFrameHeader frameInfo)
private static void ReadFrameDeltaLoopFilterParameters(ref Av1BitStreamReader reader, ObuFrameHeader frameHeader)
{
frameInfo.DeltaLoopFilterParameters.IsPresent = false;
frameInfo.DeltaLoopFilterParameters.Resolution = 0;
frameInfo.DeltaLoopFilterParameters.IsMulti = false;
if (frameInfo.DeltaQParameters.IsPresent)
frameHeader.DeltaLoopFilterParameters.IsPresent = false;
frameHeader.DeltaLoopFilterParameters.Resolution = 0;
frameHeader.DeltaLoopFilterParameters.IsMulti = false;
if (frameHeader.DeltaQParameters.IsPresent)
{
if (!frameInfo.AllowIntraBlockCopy)
if (!frameHeader.AllowIntraBlockCopy)
{
frameInfo.DeltaLoopFilterParameters.IsPresent = reader.ReadBoolean();
frameHeader.DeltaLoopFilterParameters.IsPresent = reader.ReadBoolean();
}
if (frameInfo.DeltaLoopFilterParameters.IsPresent)
if (frameHeader.DeltaLoopFilterParameters.IsPresent)
{
frameInfo.DeltaLoopFilterParameters.Resolution = (int)reader.ReadLiteral(2);
frameInfo.DeltaLoopFilterParameters.IsMulti = reader.ReadBoolean();
frameHeader.DeltaLoopFilterParameters.Resolution = (int)reader.ReadLiteral(2);
frameHeader.DeltaLoopFilterParameters.IsMulti = reader.ReadBoolean();
}
}
}
@ -1372,30 +1372,30 @@ internal class ObuReader
/// <summary>
/// 5.9.14. Segmentation params syntax.
/// </summary>
private static void ReadSegmentationParameters(ref Av1BitStreamReader reader, ObuFrameHeader frameInfo)
private static void ReadSegmentationParameters(ref Av1BitStreamReader reader, ObuFrameHeader frameHeader)
{
frameInfo.SegmentationParameters.Enabled = reader.ReadBoolean();
frameHeader.SegmentationParameters.Enabled = reader.ReadBoolean();
if (frameInfo.SegmentationParameters.Enabled)
if (frameHeader.SegmentationParameters.Enabled)
{
if (frameInfo.PrimaryReferenceFrame == PrimaryRefNone)
if (frameHeader.PrimaryReferenceFrame == PrimaryRefNone)
{
frameInfo.SegmentationParameters.SegmentationUpdateMap = 1;
frameInfo.SegmentationParameters.SegmentationTemporalUpdate = 0;
frameInfo.SegmentationParameters.SegmentationUpdateData = 1;
frameHeader.SegmentationParameters.SegmentationUpdateMap = 1;
frameHeader.SegmentationParameters.SegmentationTemporalUpdate = 0;
frameHeader.SegmentationParameters.SegmentationUpdateData = 1;
}
else
{
frameInfo.SegmentationParameters.SegmentationUpdateMap = reader.ReadBoolean() ? 1 : 0;
if (frameInfo.SegmentationParameters.SegmentationUpdateMap == 1)
frameHeader.SegmentationParameters.SegmentationUpdateMap = reader.ReadBoolean() ? 1 : 0;
if (frameHeader.SegmentationParameters.SegmentationUpdateMap == 1)
{
frameInfo.SegmentationParameters.SegmentationTemporalUpdate = reader.ReadBoolean() ? 1 : 0;
frameHeader.SegmentationParameters.SegmentationTemporalUpdate = reader.ReadBoolean() ? 1 : 0;
}
frameInfo.SegmentationParameters.SegmentationUpdateData = reader.ReadBoolean() ? 1 : 0;
frameHeader.SegmentationParameters.SegmentationUpdateData = reader.ReadBoolean() ? 1 : 0;
}
if (frameInfo.SegmentationParameters.SegmentationUpdateData == 1)
if (frameHeader.SegmentationParameters.SegmentationUpdateData == 1)
{
for (int i = 0; i < MaxSegments; i++)
{
@ -1403,7 +1403,7 @@ internal class ObuReader
{
int featureValue = 0;
bool featureEnabled = reader.ReadBoolean();
frameInfo.SegmentationParameters.FeatureEnabled[i, j] = featureEnabled;
frameHeader.SegmentationParameters.FeatureEnabled[i, j] = featureEnabled;
int clippedValue = 0;
if (featureEnabled)
{
@ -1420,7 +1420,7 @@ internal class ObuReader
}
}
frameInfo.SegmentationParameters.FeatureData[i, j] = clippedValue;
frameHeader.SegmentationParameters.FeatureData[i, j] = clippedValue;
}
}
}
@ -1431,24 +1431,24 @@ internal class ObuReader
{
for (int j = 0; j < Av1Constants.SegmentationLevelMax; j++)
{
frameInfo.SegmentationParameters.FeatureEnabled[i, j] = false;
frameInfo.SegmentationParameters.FeatureData[i, j] = 0;
frameHeader.SegmentationParameters.FeatureEnabled[i, j] = false;
frameHeader.SegmentationParameters.FeatureData[i, j] = 0;
}
}
}
frameInfo.SegmentationParameters.SegmentIdPrecedesSkip = false;
frameInfo.SegmentationParameters.LastActiveSegmentId = 0;
frameHeader.SegmentationParameters.SegmentIdPrecedesSkip = false;
frameHeader.SegmentationParameters.LastActiveSegmentId = 0;
for (int i = 0; i < Av1Constants.MaxSegmentCount; i++)
{
for (int j = 0; j < Av1Constants.SegmentationLevelMax; j++)
{
if (frameInfo.SegmentationParameters.FeatureEnabled[i, j])
if (frameHeader.SegmentationParameters.FeatureEnabled[i, j])
{
frameInfo.SegmentationParameters.LastActiveSegmentId = i;
frameHeader.SegmentationParameters.LastActiveSegmentId = i;
if (j >= SegLvlRefFrame)
{
frameInfo.SegmentationParameters.SegmentIdPrecedesSkip = true;
frameHeader.SegmentationParameters.SegmentIdPrecedesSkip = true;
}
}
}
@ -1460,36 +1460,36 @@ internal class ObuReader
/// </summary>
private void ReadLoopFilterParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader)
{
ObuFrameHeader frameInfo = this.FrameHeader!;
if (frameInfo.CodedLossless || frameInfo.AllowIntraBlockCopy)
ObuFrameHeader frameHeader = this.FrameHeader!;
if (frameHeader.CodedLossless || frameHeader.AllowIntraBlockCopy)
{
return;
}
frameInfo.LoopFilterParameters.FilterLevel[0] = (int)reader.ReadLiteral(6);
frameInfo.LoopFilterParameters.FilterLevel[1] = (int)reader.ReadLiteral(6);
frameHeader.LoopFilterParameters.FilterLevel[0] = (int)reader.ReadLiteral(6);
frameHeader.LoopFilterParameters.FilterLevel[1] = (int)reader.ReadLiteral(6);
if (sequenceHeader.ColorConfig.PlaneCount > 1)
{
if (frameInfo.LoopFilterParameters.FilterLevel[0] > 0 || frameInfo.LoopFilterParameters.FilterLevel[1] > 0)
if (frameHeader.LoopFilterParameters.FilterLevel[0] > 0 || frameHeader.LoopFilterParameters.FilterLevel[1] > 0)
{
frameInfo.LoopFilterParameters.FilterLevelU = (int)reader.ReadLiteral(6);
frameInfo.LoopFilterParameters.FilterLevelV = (int)reader.ReadLiteral(6);
frameHeader.LoopFilterParameters.FilterLevelU = (int)reader.ReadLiteral(6);
frameHeader.LoopFilterParameters.FilterLevelV = (int)reader.ReadLiteral(6);
}
}
frameInfo.LoopFilterParameters.SharpnessLevel = (int)reader.ReadLiteral(3);
frameInfo.LoopFilterParameters.ReferenceDeltaModeEnabled = reader.ReadBoolean();
if (frameInfo.LoopFilterParameters.ReferenceDeltaModeEnabled)
frameHeader.LoopFilterParameters.SharpnessLevel = (int)reader.ReadLiteral(3);
frameHeader.LoopFilterParameters.ReferenceDeltaModeEnabled = reader.ReadBoolean();
if (frameHeader.LoopFilterParameters.ReferenceDeltaModeEnabled)
{
frameInfo.LoopFilterParameters.ReferenceDeltaModeUpdate = reader.ReadBoolean();
if (frameInfo.LoopFilterParameters.ReferenceDeltaModeUpdate)
frameHeader.LoopFilterParameters.ReferenceDeltaModeUpdate = reader.ReadBoolean();
if (frameHeader.LoopFilterParameters.ReferenceDeltaModeUpdate)
{
for (int i = 0; i < Av1Constants.TotalReferencesPerFrame; i++)
{
if (reader.ReadBoolean())
{
frameInfo.LoopFilterParameters.ReferenceDeltas[i] = reader.ReadSignedFromUnsigned(7);
frameHeader.LoopFilterParameters.ReferenceDeltas[i] = reader.ReadSignedFromUnsigned(7);
}
}
@ -1497,7 +1497,7 @@ internal class ObuReader
{
if (reader.ReadBoolean())
{
frameInfo.LoopFilterParameters.ModeDeltas[i] = reader.ReadSignedFromUnsigned(7);
frameHeader.LoopFilterParameters.ModeDeltas[i] = reader.ReadSignedFromUnsigned(7);
}
}
}
@ -1507,21 +1507,21 @@ internal class ObuReader
/// <summary>
/// 5.9.21. TX mode syntax.
/// </summary>
private static void ReadTransformMode(ref Av1BitStreamReader reader, ObuFrameHeader frameInfo)
private static void ReadTransformMode(ref Av1BitStreamReader reader, ObuFrameHeader frameHeader)
{
if (frameInfo.CodedLossless)
if (frameHeader.CodedLossless)
{
frameInfo.TransformMode = Av1TransformMode.Only4x4;
frameHeader.TransformMode = Av1TransformMode.Only4x4;
}
else
{
if (reader.ReadBoolean())
{
frameInfo.TransformMode = Av1TransformMode.Select;
frameHeader.TransformMode = Av1TransformMode.Select;
}
else
{
frameInfo.TransformMode = Av1TransformMode.Largest;
frameHeader.TransformMode = Av1TransformMode.Largest;
}
}
}
@ -1529,54 +1529,54 @@ internal class ObuReader
/// <summary>
/// See section 5.9.20. Loop restoration params syntax.
/// </summary>
private static void ReadLoopRestorationParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo)
private static void ReadLoopRestorationParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{
if (frameInfo.CodedLossless || frameInfo.AllowIntraBlockCopy || !sequenceHeader.EnableRestoration)
if (frameHeader.CodedLossless || frameHeader.AllowIntraBlockCopy || !sequenceHeader.EnableRestoration)
{
return;
}
frameInfo.LoopRestorationParameters.UsesLoopRestoration = false;
frameInfo.LoopRestorationParameters.UsesChromaLoopRestoration = false;
frameHeader.LoopRestorationParameters.UsesLoopRestoration = false;
frameHeader.LoopRestorationParameters.UsesChromaLoopRestoration = false;
int planesCount = sequenceHeader.ColorConfig.PlaneCount;
for (int i = 0; i < planesCount; i++)
{
frameInfo.LoopRestorationParameters.Items[i].Type = (ObuRestorationType)reader.ReadLiteral(2);
frameHeader.LoopRestorationParameters.Items[i].Type = (ObuRestorationType)reader.ReadLiteral(2);
if (frameInfo.LoopRestorationParameters.Items[i].Type != ObuRestorationType.None)
if (frameHeader.LoopRestorationParameters.Items[i].Type != ObuRestorationType.None)
{
frameInfo.LoopRestorationParameters.UsesLoopRestoration = true;
frameHeader.LoopRestorationParameters.UsesLoopRestoration = true;
if (i > 0)
{
frameInfo.LoopRestorationParameters.UsesChromaLoopRestoration = true;
frameHeader.LoopRestorationParameters.UsesChromaLoopRestoration = true;
}
}
}
if (frameInfo.LoopRestorationParameters.UsesLoopRestoration)
if (frameHeader.LoopRestorationParameters.UsesLoopRestoration)
{
frameInfo.LoopRestorationParameters.UnitShift = (int)reader.ReadLiteral(1);
frameHeader.LoopRestorationParameters.UnitShift = (int)reader.ReadLiteral(1);
if (sequenceHeader.Use128x128Superblock)
{
frameInfo.LoopRestorationParameters.UnitShift++;
frameHeader.LoopRestorationParameters.UnitShift++;
}
else
{
if (reader.ReadBoolean())
{
frameInfo.LoopRestorationParameters.UnitShift += (int)reader.ReadLiteral(1);
frameHeader.LoopRestorationParameters.UnitShift += (int)reader.ReadLiteral(1);
}
}
frameInfo.LoopRestorationParameters.Items[0].Size = Av1Constants.RestorationMaxTileSize >> (2 - frameInfo.LoopRestorationParameters.UnitShift);
frameInfo.LoopRestorationParameters.UVShift = 0;
if (sequenceHeader.ColorConfig.SubSamplingX && sequenceHeader.ColorConfig.SubSamplingY && frameInfo.LoopRestorationParameters.UsesChromaLoopRestoration)
frameHeader.LoopRestorationParameters.Items[0].Size = Av1Constants.RestorationMaxTileSize >> (2 - frameHeader.LoopRestorationParameters.UnitShift);
frameHeader.LoopRestorationParameters.UVShift = 0;
if (sequenceHeader.ColorConfig.SubSamplingX && sequenceHeader.ColorConfig.SubSamplingY && frameHeader.LoopRestorationParameters.UsesChromaLoopRestoration)
{
frameInfo.LoopRestorationParameters.UVShift = (int)reader.ReadLiteral(1);
frameHeader.LoopRestorationParameters.UVShift = (int)reader.ReadLiteral(1);
}
frameInfo.LoopRestorationParameters.Items[1].Size = frameInfo.LoopRestorationParameters.Items[0].Size >> frameInfo.LoopRestorationParameters.UVShift;
frameInfo.LoopRestorationParameters.Items[2].Size = frameInfo.LoopRestorationParameters.Items[0].Size >> frameInfo.LoopRestorationParameters.UVShift;
frameHeader.LoopRestorationParameters.Items[1].Size = frameHeader.LoopRestorationParameters.Items[0].Size >> frameHeader.LoopRestorationParameters.UVShift;
frameHeader.LoopRestorationParameters.Items[2].Size = frameHeader.LoopRestorationParameters.Items[0].Size >> frameHeader.LoopRestorationParameters.UVShift;
}
}
@ -1668,10 +1668,10 @@ internal class ObuReader
/// <summary>
/// 5.9.30. Film grain params syntax.
/// </summary>
private static ObuFilmGrainParameters ReadFilmGrainFilterParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo)
private static ObuFilmGrainParameters ReadFilmGrainFilterParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{
ObuFilmGrainParameters grainParams = new();
if (!sequenceHeader.AreFilmGrainingParametersPresent || (!frameInfo.ShowFrame && !frameInfo.ShowableFrame))
if (!sequenceHeader.AreFilmGrainingParametersPresent || (!frameHeader.ShowFrame && !frameHeader.ShowableFrame))
{
return grainParams;
}
@ -1684,7 +1684,7 @@ internal class ObuReader
grainParams.GrainSeed = reader.ReadLiteral(16);
if (frameInfo.FrameType == ObuFrameType.InterFrame)
if (frameHeader.FrameType == ObuFrameType.InterFrame)
{
grainParams.UpdateGrain = reader.ReadBoolean();
}

88
src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs

@ -14,7 +14,7 @@ internal class ObuWriter
/// <summary>
/// Encode a single frame into OBU's.
/// </summary>
public void WriteAll(Configuration configuration, Stream stream, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, IAv1TileWriter tileWriter)
public void WriteAll(Configuration configuration, Stream stream, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, IAv1TileWriter tileWriter)
{
// TODO: Determine inital size dynamically
int initialBufferSize = 2000;
@ -30,12 +30,12 @@ internal class ObuWriter
WriteObuHeaderAndSize(stream, ObuType.SequenceHeader, buffer.GetSpan(bytesWritten));
}
if (frameInfo != null && sequenceHeader != null)
if (frameHeader != null && sequenceHeader != null)
{
this.WriteFrameHeader(ref writer, sequenceHeader, frameInfo, false);
if (frameInfo.TilesInfo != null)
this.WriteFrameHeader(ref writer, sequenceHeader, frameHeader, false);
if (frameHeader.TilesInfo != null)
{
WriteTileGroup(ref writer, frameInfo.TilesInfo, tileWriter);
WriteTileGroup(ref writer, frameHeader.TilesInfo, tileWriter);
}
int bytesWritten = (writer.BitPosition + 7) >> 3;
@ -192,7 +192,7 @@ internal class ObuWriter
}
}
private static void WriteSuperResolutionParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo)
private static void WriteSuperResolutionParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{
bool useSuperResolution = false;
if (sequenceHeader.EnableSuperResolution)
@ -202,22 +202,22 @@ internal class ObuWriter
if (useSuperResolution)
{
writer.WriteLiteral((uint)frameInfo.FrameSize.SuperResolutionDenominator - Av1Constants.SuperResolutionScaleDenominatorMinimum, Av1Constants.SuperResolutionScaleBits);
writer.WriteLiteral((uint)frameHeader.FrameSize.SuperResolutionDenominator - Av1Constants.SuperResolutionScaleDenominatorMinimum, Av1Constants.SuperResolutionScaleBits);
}
}
private static void WriteRenderSize(ref Av1BitStreamWriter writer, ObuFrameHeader frameInfo)
private static void WriteRenderSize(ref Av1BitStreamWriter writer, ObuFrameHeader frameHeader)
{
bool renderSizeAndFrameSizeDifferent = false;
writer.WriteBoolean(false);
if (renderSizeAndFrameSizeDifferent)
{
writer.WriteLiteral((uint)frameInfo.FrameSize.RenderWidth - 1, 16);
writer.WriteLiteral((uint)frameInfo.FrameSize.RenderHeight - 1, 16);
writer.WriteLiteral((uint)frameHeader.FrameSize.RenderWidth - 1, 16);
writer.WriteLiteral((uint)frameHeader.FrameSize.RenderHeight - 1, 16);
}
}
private static void WriteFrameSizeWithReferences(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, bool frameSizeOverrideFlag)
private static void WriteFrameSizeWithReferences(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, bool frameSizeOverrideFlag)
{
bool foundReference = false;
for (int i = 0; i < Av1Constants.ReferencesPerFrame; i++)
@ -232,35 +232,35 @@ internal class ObuWriter
if (!foundReference)
{
WriteFrameSize(ref writer, sequenceHeader, frameInfo, frameSizeOverrideFlag);
WriteRenderSize(ref writer, frameInfo);
WriteFrameSize(ref writer, sequenceHeader, frameHeader, frameSizeOverrideFlag);
WriteRenderSize(ref writer, frameHeader);
}
else
{
WriteSuperResolutionParameters(ref writer, sequenceHeader, frameInfo);
WriteSuperResolutionParameters(ref writer, sequenceHeader, frameHeader);
}
}
private static void WriteFrameSize(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, bool frameSizeOverrideFlag)
private static void WriteFrameSize(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, bool frameSizeOverrideFlag)
{
if (frameSizeOverrideFlag)
{
writer.WriteLiteral((uint)frameInfo.FrameSize.FrameWidth - 1, sequenceHeader.FrameWidthBits + 1);
writer.WriteLiteral((uint)frameInfo.FrameSize.FrameHeight - 1, sequenceHeader.FrameHeightBits + 1);
writer.WriteLiteral((uint)frameHeader.FrameSize.FrameWidth - 1, sequenceHeader.FrameWidthBits + 1);
writer.WriteLiteral((uint)frameHeader.FrameSize.FrameHeight - 1, sequenceHeader.FrameHeightBits + 1);
}
WriteSuperResolutionParameters(ref writer, sequenceHeader, frameInfo);
WriteSuperResolutionParameters(ref writer, sequenceHeader, frameHeader);
}
private static void WriteTileInfo(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo)
private static void WriteTileInfo(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{
ObuTileGroupHeader tileInfo = frameInfo.TilesInfo;
ObuTileGroupHeader tileInfo = frameHeader.TilesInfo;
int superblockColumnCount;
int superblockRowCount;
int superblockSizeLog2 = sequenceHeader.SuperblockSizeLog2;
int superblockShift = superblockSizeLog2 - Av1Constants.ModeInfoSizeLog2;
superblockColumnCount = (frameInfo.ModeInfoColumnCount + sequenceHeader.SuperblockModeInfoSize - 1) >> superblockShift;
superblockRowCount = (frameInfo.ModeInfoRowCount + sequenceHeader.SuperblockModeInfoSize - 1) >> superblockShift;
superblockColumnCount = (frameHeader.ModeInfoColumnCount + sequenceHeader.SuperblockModeInfoSize - 1) >> superblockShift;
superblockRowCount = (frameHeader.ModeInfoRowCount + sequenceHeader.SuperblockModeInfoSize - 1) >> superblockShift;
int superBlockSize = superblockShift + 2;
int maxTileAreaOfSuperBlock = Av1Constants.MaxTileArea >> (2 * superBlockSize);
@ -341,7 +341,7 @@ internal class ObuWriter
writer.WriteLiteral((uint)tileInfo.TileSizeBytes - 1, 2);
}
frameInfo.TilesInfo = tileInfo;
frameHeader.TilesInfo = tileInfo;
}
private void WriteUncompressedFrameHeader(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
@ -356,7 +356,7 @@ internal class ObuWriter
}
else
{
// Guard.IsTrue(frameInfo.AllowScreenContentTools == sequenceHeader.ForceScreenContentTools);
// Guard.IsTrue(frameHeader.AllowScreenContentTools == sequenceHeader.ForceScreenContentTools);
}
if (frameHeader.AllowScreenContentTools)
@ -367,7 +367,7 @@ internal class ObuWriter
}
else
{
// Guard.IsTrue(frameInfo.ForceIntegerMotionVector == sequenceHeader.ForceIntegerMotionVector, nameof(frameInfo.ForceIntegerMotionVector), "Frame and sequence must be in sync");
// Guard.IsTrue(frameHeader.ForceIntegerMotionVector == sequenceHeader.ForceIntegerMotionVector, nameof(frameHeader.ForceIntegerMotionVector), "Frame and sequence must be in sync");
}
}
@ -486,10 +486,10 @@ internal class ObuWriter
private static bool IsSegmentationFeatureActive(ObuSegmentationParameters segmentationParameters, int segmentId, ObuSegmentationLevelFeature feature)
=> segmentationParameters.Enabled && segmentationParameters.FeatureEnabled[segmentId, (int)feature];
private int WriteFrameHeader(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, bool writeTrailingBits)
private int WriteFrameHeader(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, bool writeTrailingBits)
{
int startBitPosition = writer.BitPosition;
this.WriteUncompressedFrameHeader(ref writer, sequenceHeader, frameInfo);
this.WriteUncompressedFrameHeader(ref writer, sequenceHeader, frameHeader);
if (writeTrailingBits)
{
WriteTrailingBits(ref writer);
@ -555,32 +555,32 @@ internal class ObuWriter
return deltaQ;
}
private static void WriteFrameDeltaQParameters(ref Av1BitStreamWriter writer, ObuFrameHeader frameInfo)
private static void WriteFrameDeltaQParameters(ref Av1BitStreamWriter writer, ObuFrameHeader frameHeader)
{
if (frameInfo.QuantizationParameters.BaseQIndex > 0)
if (frameHeader.QuantizationParameters.BaseQIndex > 0)
{
writer.WriteBoolean(frameInfo.DeltaQParameters.IsPresent);
writer.WriteBoolean(frameHeader.DeltaQParameters.IsPresent);
}
if (frameInfo.DeltaQParameters.IsPresent)
if (frameHeader.DeltaQParameters.IsPresent)
{
writer.WriteLiteral((uint)frameInfo.DeltaQParameters.Resolution, 2);
writer.WriteLiteral((uint)frameHeader.DeltaQParameters.Resolution, 2);
}
}
private static void WriteFrameDeltaLoopFilterParameters(ref Av1BitStreamWriter writer, ObuFrameHeader frameInfo)
private static void WriteFrameDeltaLoopFilterParameters(ref Av1BitStreamWriter writer, ObuFrameHeader frameHeader)
{
if (frameInfo.DeltaQParameters.IsPresent)
if (frameHeader.DeltaQParameters.IsPresent)
{
if (!frameInfo.AllowIntraBlockCopy)
if (!frameHeader.AllowIntraBlockCopy)
{
writer.WriteBoolean(frameInfo.DeltaLoopFilterParameters.IsPresent);
writer.WriteBoolean(frameHeader.DeltaLoopFilterParameters.IsPresent);
}
if (frameInfo.DeltaLoopFilterParameters.IsPresent)
if (frameHeader.DeltaLoopFilterParameters.IsPresent)
{
writer.WriteLiteral((uint)frameInfo.DeltaLoopFilterParameters.Resolution, 2);
writer.WriteBoolean(frameInfo.DeltaLoopFilterParameters.IsMulti);
writer.WriteLiteral((uint)frameHeader.DeltaLoopFilterParameters.Resolution, 2);
writer.WriteBoolean(frameHeader.DeltaLoopFilterParameters.IsMulti);
}
}
}
@ -621,10 +621,10 @@ internal class ObuWriter
}
}
private static void WriteSegmentationParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo)
private static void WriteSegmentationParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{
_ = sequenceHeader;
Guard.IsFalse(frameInfo.SegmentationParameters.Enabled, nameof(frameInfo.SegmentationParameters.Enabled), "Segmentation not supported yet.");
Guard.IsFalse(frameHeader.SegmentationParameters.Enabled, nameof(frameHeader.SegmentationParameters.Enabled), "Segmentation not supported yet.");
writer.WriteBoolean(false);
}
@ -664,11 +664,11 @@ internal class ObuWriter
/// <summary>
/// 5.9.21. TX mode syntax.
/// </summary>
private static void WriteTransformMode(ref Av1BitStreamWriter writer, ObuFrameHeader frameInfo)
private static void WriteTransformMode(ref Av1BitStreamWriter writer, ObuFrameHeader frameHeader)
{
if (!frameInfo.CodedLossless)
if (!frameHeader.CodedLossless)
{
writer.WriteBoolean(frameInfo.TransformMode == Av1TransformMode.Select);
writer.WriteBoolean(frameHeader.TransformMode == Av1TransformMode.Select);
}
}

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

@ -56,7 +56,7 @@ internal class Av1BlockModeInfo
public Av1IntraFilterModeInfo FilterIntraModeInfo { get; internal set; }
/// <summary>
/// Gets the index of the first <see cref="Av1TransformInfo"/> of this Mode Info in the <see cref="Av1FrameBuffer"/>.
/// Gets the index of the first <see cref="Av1TransformInfo"/> of this Mode Info in the <see cref="Av1FrameInfo"/>.
/// </summary>
public int[] FirstTransformLocation { get; }

27
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameBuffer.cs → src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs

@ -5,7 +5,10 @@ using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
internal partial class Av1FrameBuffer
/// <summary>
/// Collection of all information for a single frame.
/// </summary>
internal partial class Av1FrameInfo
{
// Number of Coefficients in a single ModeInfo 4x4 block of pixels (1 length + 4 x 4).
public const int CoefficientCountPerModeInfo = 1 + 16;
@ -29,7 +32,7 @@ internal partial class Av1FrameBuffer
private readonly int deltaLoopFactorLog2 = 2;
private readonly int[] deltaLoopFilter;
public Av1FrameBuffer(ObuSequenceHeader sequenceHeader)
public Av1FrameInfo(ObuSequenceHeader sequenceHeader)
{
// init_main_frame_ctxt
int superblockSizeLog2 = sequenceHeader.SuperblockSizeLog2;
@ -102,20 +105,28 @@ internal partial class Av1FrameBuffer
return this.modeInfos[index];
}
public Span<Av1TransformInfo> GetSuperblockTransformY(Point index)
public ref Av1TransformInfo GetSuperblockTransform(int plane, Point index)
{
if (plane == 0)
{
return ref this.GetSuperblockTransformY(index);
}
return ref this.GetSuperblockTransformUv(index);
}
public ref Av1TransformInfo GetSuperblockTransformY(Point index)
{
Span<Av1TransformInfo> span = this.transformInfosY;
int offset = ((index.Y * this.superblockColumnCount) + index.X) * this.modeInfoCountPerSuperblock;
int length = this.modeInfoCountPerSuperblock;
return span.Slice(offset, length);
return ref span[offset];
}
public Span<Av1TransformInfo> GetSuperblockTransformUv(Point index)
public ref Av1TransformInfo GetSuperblockTransformUv(Point index)
{
Span<Av1TransformInfo> span = this.transformInfosUv;
int offset = (((index.Y * this.superblockColumnCount) + index.X) * this.modeInfoCountPerSuperblock) << 1;
int length = this.modeInfoCountPerSuperblock << 1;
return span.Slice(offset, length);
return ref span[offset];
}
public Span<int> GetCoefficients(int plane) =>

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

@ -3,10 +3,10 @@
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
internal partial class Av1FrameBuffer
internal partial class Av1FrameInfo
{
/// <summary>
/// Mapping of <see cref="Av1BlockModeInfo"/> instances, from position to index into the <see cref="Av1FrameBuffer"/>.
/// Mapping of <see cref="Av1BlockModeInfo"/> instances, from position to index into the <see cref="Av1FrameInfo"/>.
/// </summary>
/// <remarks>
/// For a visual representation of how this map looks in practice, see <seealso href="https://gitlab.com/AOMediaCodec/SVT-AV1/-/blob/v2.1.0/Docs/svt-av1-decoder-design.md?ref_type=tags#blockmodeinfo"/>

6
src/ImageSharp/Formats/Heif/Av1/Tiling/Av1PartitionInfo.cs

@ -75,7 +75,7 @@ internal class Av1PartitionInfo
public int ModeBlockToBottomEdge => this.modeBlockToBottomEdge;
public void ComputeBoundaryOffsets(ObuFrameHeader frameInfo, Av1TileInfo tileInfo)
public void ComputeBoundaryOffsets(ObuFrameHeader frameHeader, Av1TileInfo tileInfo)
{
Av1BlockSize blockSize = this.ModeInfo.BlockSize;
int bw4 = blockSize.Get4x4WideCount();
@ -86,9 +86,9 @@ internal class Av1PartitionInfo
this.AvailableLeftForChroma = this.AvailableLeft;
int shift = Av1Constants.ModeInfoSizeLog2 + 3;
this.modeBlockToLeftEdge = -this.ColumnIndex << shift;
this.modeBlockToRightEdge = (frameInfo.ModeInfoColumnCount - bw4 - this.ColumnIndex) << shift;
this.modeBlockToRightEdge = (frameHeader.ModeInfoColumnCount - bw4 - this.ColumnIndex) << shift;
this.modeBlockToTopEdge = -this.RowIndex << shift;
this.modeBlockToBottomEdge = (frameInfo.ModeInfoRowCount - bh4 - this.RowIndex) << shift;
this.modeBlockToBottomEdge = (frameHeader.ModeInfoRowCount - bh4 - this.RowIndex) << shift;
}
public int GetMaxBlockWide(Av1BlockSize blockSize, bool subX)

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

@ -5,12 +5,12 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
internal class Av1SuperblockInfo
{
private readonly Av1FrameBuffer frameBuffer;
private readonly Av1FrameInfo frameInfo;
public Av1SuperblockInfo(Av1FrameBuffer frameBuffer, Point position)
public Av1SuperblockInfo(Av1FrameInfo frameInfo, Point position)
{
this.Position = position;
this.frameBuffer = frameBuffer;
this.frameInfo = frameInfo;
}
/// <summary>
@ -18,27 +18,29 @@ internal class Av1SuperblockInfo
/// </summary>
public Point Position { get; }
public ref int SuperblockDeltaQ => ref this.frameBuffer.GetDeltaQuantizationIndex(this.Position);
public ref int SuperblockDeltaQ => ref this.frameInfo.GetDeltaQuantizationIndex(this.Position);
public Av1BlockModeInfo SuperblockModeInfo => this.GetModeInfo(new Point(0, 0));
public Span<int> CoefficientsY => this.frameBuffer.GetCoefficientsY(this.Position);
public Span<int> CoefficientsY => this.frameInfo.GetCoefficientsY(this.Position);
public Span<int> CoefficientsU => this.frameBuffer.GetCoefficientsU(this.Position);
public Span<int> CoefficientsU => this.frameInfo.GetCoefficientsU(this.Position);
public Span<int> CoefficientsV => this.frameBuffer.GetCoefficientsV(this.Position);
public Span<int> CoefficientsV => this.frameInfo.GetCoefficientsV(this.Position);
public Span<int> CdefStrength => this.frameBuffer.GetCdefStrength(this.Position);
public Span<int> CdefStrength => this.frameInfo.GetCdefStrength(this.Position);
public Span<int> SuperblockDeltaLoopFilter => this.frameBuffer.GetDeltaLoopFilter(this.Position);
public Span<int> SuperblockDeltaLoopFilter => this.frameInfo.GetDeltaLoopFilter(this.Position);
public int TransformInfoIndexY { get; internal set; }
public int TransformInfoIndexUv { get; internal set; }
public Span<Av1TransformInfo> GetTransformInfoY() => this.frameBuffer.GetSuperblockTransformY(this.Position);
public int BlockCount { get; internal set; }
public Span<Av1TransformInfo> GetTransformInfoUv() => this.frameBuffer.GetSuperblockTransformUv(this.Position);
public ref Av1TransformInfo GetTransformInfoY() => ref this.frameInfo.GetSuperblockTransformY(this.Position);
public Av1BlockModeInfo GetModeInfo(Point index) => this.frameBuffer.GetModeInfo(this.Position, index);
public ref Av1TransformInfo GetTransformInfoUv() => ref this.frameInfo.GetSuperblockTransformUv(this.Position);
public Av1BlockModeInfo GetModeInfo(Point index) => this.frameInfo.GetModeInfo(this.Position, index);
}

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

@ -7,10 +7,10 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling;
internal class Av1TileInfo
{
public Av1TileInfo(int row, int column, ObuFrameHeader frameInfo)
public Av1TileInfo(int row, int column, ObuFrameHeader frameHeader)
{
this.SetTileRow(frameInfo.TilesInfo, frameInfo.ModeInfoRowCount, row);
this.SetTileColumn(frameInfo.TilesInfo, frameInfo.ModeInfoColumnCount, column);
this.SetTileRow(frameHeader.TilesInfo, frameHeader.ModeInfoRowCount, row);
this.SetTileColumn(frameHeader.TilesInfo, frameHeader.ModeInfoColumnCount, column);
}
public int ModeInfoRowStart { get; private set; }

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

@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Formats.Heif.Av1;
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
using SixLabors.ImageSharp.Formats.Heif.Av1.Prediction;
@ -34,17 +35,17 @@ internal class Av1TileReader : IAv1TileReader
private readonly int[] firstTransformOffset = new int[2];
private readonly int[] coefficientIndex = [];
public Av1TileReader(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo)
public Av1TileReader(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{
this.FrameInfo = frameInfo;
this.FrameHeader = frameHeader;
this.SequenceHeader = sequenceHeader;
// init_main_frame_ctxt
this.FrameBuffer = new(this.SequenceHeader);
this.segmentIds = new int[this.FrameInfo.ModeInfoRowCount][];
for (int y = 0; y < this.FrameInfo.ModeInfoRowCount; y++)
this.FrameInfo = new(this.SequenceHeader);
this.segmentIds = new int[this.FrameHeader.ModeInfoRowCount][];
for (int y = 0; y < this.FrameHeader.ModeInfoRowCount; y++)
{
this.segmentIds[y] = new int[this.FrameInfo.ModeInfoColumnCount];
this.segmentIds[y] = new int[this.FrameHeader.ModeInfoColumnCount];
}
// reallocate_parse_context_memory
@ -57,28 +58,28 @@ internal class Av1TileReader : IAv1TileReader
this.aboveNeighborContext = new Av1ParseAboveNeighbor4x4Context(planesCount, modeInfoWideColumnCount);
this.leftNeighborContext = new Av1ParseLeftNeighbor4x4Context(planesCount, sequenceHeader.SuperblockModeInfoSize);
this.transformUnitCount = new int[Av1Constants.MaxPlanes][];
this.transformUnitCount[0] = new int[this.FrameBuffer.ModeInfoCount];
this.transformUnitCount[1] = new int[this.FrameBuffer.ModeInfoCount];
this.transformUnitCount[2] = new int[this.FrameBuffer.ModeInfoCount];
this.transformUnitCount[0] = new int[this.FrameInfo.ModeInfoCount];
this.transformUnitCount[1] = new int[this.FrameInfo.ModeInfoCount];
this.transformUnitCount[2] = new int[this.FrameInfo.ModeInfoCount];
this.coefficientIndex = new int[Av1Constants.MaxPlanes];
}
public ObuFrameHeader FrameInfo { get; }
public ObuFrameHeader FrameHeader { get; }
public ObuSequenceHeader SequenceHeader { get; }
public Av1FrameBuffer FrameBuffer { get; }
public Av1FrameInfo FrameInfo { get; }
public void ReadTile(Span<byte> tileData, int tileNum)
{
Av1SymbolDecoder reader = new(tileData, this.FrameInfo.QuantizationParameters.BaseQIndex);
int tileColumnIndex = tileNum % this.FrameInfo.TilesInfo.TileColumnCount;
int tileRowIndex = tileNum / this.FrameInfo.TilesInfo.TileColumnCount;
int modeInfoColumnStart = this.FrameInfo.TilesInfo.TileColumnStartModeInfo[tileColumnIndex];
int modeInfoColumnEnd = this.FrameInfo.TilesInfo.TileColumnStartModeInfo[tileColumnIndex + 1];
int modeInfoRowStart = this.FrameInfo.TilesInfo.TileRowStartModeInfo[tileRowIndex];
int modeInfoRowEnd = this.FrameInfo.TilesInfo.TileRowStartModeInfo[tileRowIndex + 1];
Av1SymbolDecoder reader = new(tileData, this.FrameHeader.QuantizationParameters.BaseQIndex);
int tileColumnIndex = tileNum % this.FrameHeader.TilesInfo.TileColumnCount;
int tileRowIndex = tileNum / this.FrameHeader.TilesInfo.TileColumnCount;
int modeInfoColumnStart = this.FrameHeader.TilesInfo.TileColumnStartModeInfo[tileColumnIndex];
int modeInfoColumnEnd = this.FrameHeader.TilesInfo.TileColumnStartModeInfo[tileColumnIndex + 1];
int modeInfoRowStart = this.FrameHeader.TilesInfo.TileRowStartModeInfo[tileRowIndex];
int modeInfoRowEnd = this.FrameHeader.TilesInfo.TileRowStartModeInfo[tileRowIndex + 1];
this.aboveNeighborContext.Clear(this.SequenceHeader, modeInfoColumnStart, modeInfoColumnEnd);
this.ClearLoopFilterDelta();
int planesCount = this.SequenceHeader.ColorConfig.PlaneCount;
@ -98,7 +99,7 @@ internal class Av1TileReader : IAv1TileReader
}
}
Av1TileInfo tileInfo = new(tileRowIndex, tileColumnIndex, this.FrameInfo);
Av1TileInfo tileInfo = new(tileRowIndex, tileColumnIndex, this.FrameHeader);
Av1BlockSize superBlockSize = this.SequenceHeader.SuperblockSize;
int superBlock4x4Size = this.SequenceHeader.SuperblockSizeLog2;
for (int row = modeInfoRowStart; row < modeInfoRowEnd; row += superBlock4x4Size)
@ -109,10 +110,10 @@ internal class Av1TileReader : IAv1TileReader
{
int superBlockColumn = (column << Av1Constants.ModeInfoSizeLog2) >> superBlock4x4Size;
Point superblockPosition = new(superBlockColumn, superBlockRow);
Av1SuperblockInfo superblockInfo = this.FrameBuffer.GetSuperblock(superblockPosition);
Av1SuperblockInfo superblockInfo = this.FrameInfo.GetSuperblock(superblockPosition);
Point modeInfoPosition = new(column, row);
this.FrameBuffer.ClearCdef(superblockPosition);
this.FrameInfo.ClearCdef(superblockPosition);
this.firstTransformOffset[0] = 0;
this.firstTransformOffset[1] = 0;
this.ReadLoopRestoration(modeInfoPosition, superBlockSize);
@ -122,14 +123,14 @@ internal class Av1TileReader : IAv1TileReader
}
private void ClearLoopFilterDelta()
=> this.FrameBuffer.ClearDeltaLoopFilter();
=> this.FrameInfo.ClearDeltaLoopFilter();
private void ReadLoopRestoration(Point modeInfoLocation, Av1BlockSize superBlockSize)
{
int planesCount = this.SequenceHeader.ColorConfig.PlaneCount;
for (int plane = 0; plane < planesCount; plane++)
{
if (this.FrameInfo.LoopRestorationParameters.Items[plane].Type != ObuRestorationType.None)
if (this.FrameHeader.LoopRestorationParameters.Items[plane].Type != ObuRestorationType.None)
{
// TODO: Implement.
throw new NotImplementedException("No loop restoration filter support.");
@ -144,7 +145,7 @@ internal class Av1TileReader : IAv1TileReader
{
int columnIndex = modeInfoLocation.X;
int rowIndex = modeInfoLocation.Y;
if (modeInfoLocation.Y >= this.FrameInfo.ModeInfoRowCount || modeInfoLocation.X >= this.FrameInfo.ModeInfoColumnCount)
if (modeInfoLocation.Y >= this.FrameHeader.ModeInfoRowCount || modeInfoLocation.X >= this.FrameHeader.ModeInfoColumnCount)
{
return;
}
@ -152,8 +153,8 @@ internal class Av1TileReader : IAv1TileReader
int block4x4Size = blockSize.Get4x4WideCount();
int halfBlock4x4Size = block4x4Size >> 1;
int quarterBlock4x4Size = halfBlock4x4Size >> 1;
bool hasRows = (modeInfoLocation.Y + halfBlock4x4Size) < this.FrameInfo.ModeInfoRowCount;
bool hasColumns = (modeInfoLocation.X + halfBlock4x4Size) < this.FrameInfo.ModeInfoColumnCount;
bool hasRows = (modeInfoLocation.Y + halfBlock4x4Size) < this.FrameHeader.ModeInfoRowCount;
bool hasColumns = (modeInfoLocation.X + halfBlock4x4Size) < this.FrameHeader.ModeInfoColumnCount;
Av1PartitionType partitionType = Av1PartitionType.None;
if (blockSize >= Av1BlockSize.Block8x8)
{
@ -245,7 +246,7 @@ internal class Av1TileReader : IAv1TileReader
for (int i = 0; i < 4; i++)
{
int currentBlockRow = rowIndex + (i * quarterBlock4x4Size);
if (i > 0 && currentBlockRow > this.FrameInfo.ModeInfoRowCount)
if (i > 0 && currentBlockRow > this.FrameHeader.ModeInfoRowCount)
{
break;
}
@ -259,7 +260,7 @@ internal class Av1TileReader : IAv1TileReader
for (int i = 0; i < 4; i++)
{
int currentBlockColumn = columnIndex + (i * quarterBlock4x4Size);
if (i > 0 && currentBlockColumn > this.FrameInfo.ModeInfoColumnCount)
if (i > 0 && currentBlockColumn > this.FrameHeader.ModeInfoColumnCount)
{
break;
}
@ -289,11 +290,12 @@ internal class Av1TileReader : IAv1TileReader
blockModeInfo.PartitionType = partitionType;
blockModeInfo.FirstTransformLocation[0] = this.firstTransformOffset[0];
blockModeInfo.FirstTransformLocation[1] = this.firstTransformOffset[1];
bool hasChroma = this.HasChroma(modeInfoLocation, blockSize);
bool hasChroma = HasChroma(this.SequenceHeader, modeInfoLocation, blockSize);
Av1PartitionInfo partitionInfo = new(blockModeInfo, superblockInfo, hasChroma, partitionType);
partitionInfo.ColumnIndex = columnIndex;
partitionInfo.RowIndex = rowIndex;
partitionInfo.ComputeBoundaryOffsets(this.FrameInfo, tileInfo);
superblockInfo.BlockCount++;
partitionInfo.ComputeBoundaryOffsets(this.FrameHeader, tileInfo);
if (hasChroma)
{
if (this.SequenceHeader.ColorConfig.SubSamplingY && block4x4Height == 1)
@ -328,7 +330,7 @@ internal class Av1TileReader : IAv1TileReader
this.Residual(ref reader, partitionInfo, superblockInfo, tileInfo, blockSize);
// Update the Frame buffer for this ModeInfo.
this.FrameBuffer.UpdateModeInfo(blockModeInfo, superblockInfo);
this.FrameInfo.UpdateModeInfo(blockModeInfo, superblockInfo);
}
private void ResetSkipContext(Av1PartitionInfo partitionInfo)
@ -342,8 +344,8 @@ internal class Av1TileReader : IAv1TileReader
DebugGuard.IsTrue(planeBlockSize != Av1BlockSize.Invalid, nameof(planeBlockSize));
int txsWide = planeBlockSize.GetWidth() >> 2;
int txsHigh = planeBlockSize.GetHeight() >> 2;
int aboveOffset = (partitionInfo.ColumnIndex - this.FrameInfo.TilesInfo.TileColumnStartModeInfo[partitionInfo.ColumnIndex]) >> subX;
int leftOffset = (partitionInfo.RowIndex - this.FrameInfo.TilesInfo.TileRowStartModeInfo[partitionInfo.RowIndex]) >> subY;
int aboveOffset = (partitionInfo.ColumnIndex - this.FrameHeader.TilesInfo.TileColumnStartModeInfo[partitionInfo.ColumnIndex]) >> subX;
int leftOffset = (partitionInfo.RowIndex - this.FrameHeader.TilesInfo.TileRowStartModeInfo[partitionInfo.RowIndex]) >> subY;
this.aboveNeighborContext.ClearContext(i, aboveOffset, txsWide);
this.leftNeighborContext.ClearContext(i, leftOffset, txsHigh);
}
@ -362,7 +364,7 @@ internal class Av1TileReader : IAv1TileReader
modeUnitBlocksWide = Math.Min(maxBlocksWide, modeUnitBlocksWide);
modeUnitBlocksHigh = Math.Min(maxBlocksHigh, modeUnitBlocksHigh);
int planeCount = this.SequenceHeader.ColorConfig.PlaneCount;
bool isLossless = this.FrameInfo.LosslessArray[partitionInfo.ModeInfo.SegmentId];
bool isLossless = this.FrameHeader.LosslessArray[partitionInfo.ModeInfo.SegmentId];
bool isLosslessBlock = isLossless && (blockSize >= Av1BlockSize.Block64x64) && (blockSize <= Av1BlockSize.Block128x128);
int subSampling = (this.SequenceHeader.ColorConfig.SubSamplingX ? 1 : 0) + (this.SequenceHeader.ColorConfig.SubSamplingY ? 1 : 0);
int chromaTransformUnitCount = isLosslessBlock ? ((maxBlocksWide * maxBlocksHigh) >> subSampling) : partitionInfo.ModeInfo.TransformUnitsCount[(int)Av1PlaneType.Uv];
@ -389,13 +391,13 @@ internal class Av1TileReader : IAv1TileReader
continue;
}
Span<Av1TransformInfo> transformInfos = plane == 0 ? superblockInfo.GetTransformInfoY() : superblockInfo.GetTransformInfoUv();
ref Av1TransformInfo transformInfoRef = ref (plane == 0) ? ref superblockInfo.GetTransformInfoY() : ref superblockInfo.GetTransformInfoUv();
if (isLosslessBlock)
{
// TODO: Implement.
int unitHeight = Av1Math.RoundPowerOf2(Math.Min(modeUnitBlocksHigh + row, maxBlocksHigh), 0);
int unitWidth = Av1Math.RoundPowerOf2(Math.Min(modeUnitBlocksWide + column, maxBlocksWide), 0);
DebugGuard.IsTrue(transformInfos[transformInfoIndices[plane]].Size == Av1TransformSize.Size4x4, "Lossless frame shall have transform units of size 4x4.");
DebugGuard.IsTrue(Unsafe.Add(ref transformInfoRef, transformInfoIndices[plane]).Size == Av1TransformSize.Size4x4, "Lossless frame shall have transform units of size 4x4.");
transformUnitCount = ((unitWidth - column) * (unitHeight - row)) >> (subX + subY);
}
else
@ -415,7 +417,7 @@ internal class Av1TileReader : IAv1TileReader
DebugGuard.IsFalse(transformUnitCount == 0, nameof(transformUnitCount), string.Empty);
for (int tu = 0; tu < transformUnitCount; tu++)
{
Av1TransformInfo transformInfo = transformInfos[transformInfoIndices[plane]];
Av1TransformInfo transformInfo = Unsafe.Add(ref transformInfoRef, transformInfoIndices[plane]);
DebugGuard.MustBeLessThanOrEqualTo(transformInfo.OffsetX, maxBlocksWide, nameof(transformInfo));
DebugGuard.MustBeLessThanOrEqualTo(transformInfo.OffsetY, maxBlocksHigh, nameof(transformInfo));
@ -426,8 +428,8 @@ internal class Av1TileReader : IAv1TileReader
int startX = (partitionInfo.ColumnIndex >> subX) + blockColumn;
int startY = (partitionInfo.RowIndex >> subY) + blockRow;
if (startX >= (this.FrameInfo.ModeInfoColumnCount >> subX) ||
startY >= (this.FrameInfo.ModeInfoRowCount >> subY))
if (startX >= (this.FrameHeader.ModeInfoColumnCount >> subX) ||
startY >= (this.FrameHeader.ModeInfoRowCount >> subY))
{
return;
}
@ -456,12 +458,12 @@ internal class Av1TileReader : IAv1TileReader
}
}
private bool HasChroma(Point modeInfoLocation, Av1BlockSize blockSize)
public static bool HasChroma(ObuSequenceHeader sequenceHeader, Point modeInfoLocation, Av1BlockSize blockSize)
{
int blockWide = blockSize.Get4x4WideCount();
int blockHigh = blockSize.Get4x4HighCount();
bool subX = this.SequenceHeader.ColorConfig.SubSamplingX;
bool subY = this.SequenceHeader.ColorConfig.SubSamplingY;
bool subX = sequenceHeader.ColorConfig.SubSamplingX;
bool subY = sequenceHeader.ColorConfig.SubSamplingY;
bool hasChroma = ((modeInfoLocation.Y & 0x01) != 0 || (blockHigh & 0x01) == 0 || !subY) &&
((modeInfoLocation.X & 0x01) != 0 || (blockWide & 0x01) == 0 || !subX);
return hasChroma;
@ -534,7 +536,7 @@ internal class Av1TileReader : IAv1TileReader
/// </remarks>
private int ParseCoefficients(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInfo, int blockRow, int blockColumn, int aboveOffset, int leftOffset, int plane, Av1TransformBlockContext transformBlockContext, Av1TransformSize transformSize, int coefficientIndex, Av1TransformInfo transformInfo)
{
Span<int> coefficientBuffer = this.FrameBuffer.GetCoefficients(plane);
Span<int> coefficientBuffer = this.FrameInfo.GetCoefficients(plane);
int width = transformSize.GetWidth();
int height = transformSize.GetHeight();
Av1TransformSize transformSizeContext = (Av1TransformSize)(((int)transformSize.GetSquareSize() + ((int)transformSize.GetSquareUpSize() + 1)) >> 1);
@ -955,7 +957,7 @@ internal class Av1TileReader : IAv1TileReader
private Av1TransformType ComputeTransformType(Av1PlaneType planeType, Av1PartitionInfo partitionInfo, Av1TransformSize transformSize, Av1TransformInfo transformInfo)
{
Av1TransformType transformType = Av1TransformType.DctDct;
if (this.FrameInfo.LosslessArray[partitionInfo.ModeInfo.SegmentId] || transformSize.GetSquareUpSize() > Av1TransformSize.Size32x32)
if (this.FrameHeader.LosslessArray[partitionInfo.ModeInfo.SegmentId] || transformSize.GetSquareUpSize() > Av1TransformSize.Size32x32)
{
transformType = Av1TransformType.DctDct;
}
@ -973,7 +975,7 @@ internal class Av1TileReader : IAv1TileReader
}
}
Av1TransformSetType transformSetType = GetExtendedTransformSetType(transformSize, this.FrameInfo.UseReducedTransformSet);
Av1TransformSetType transformSetType = GetExtendedTransformSetType(transformSize, this.FrameHeader.UseReducedTransformSet);
if (!transformType.IsExtendedSetUsed(transformSetType))
{
transformType = Av1TransformType.DctDct;
@ -1219,12 +1221,12 @@ internal class Av1TileReader : IAv1TileReader
private Av1TransformSize ReadTransformSize(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInfo, Av1SuperblockInfo superblockInfo, Av1TileInfo tileInfo, bool allowSelect)
{
Av1BlockModeInfo modeInfo = partitionInfo.ModeInfo;
if (this.FrameInfo.LosslessArray[modeInfo.SegmentId])
if (this.FrameHeader.LosslessArray[modeInfo.SegmentId])
{
return Av1TransformSize.Size4x4;
}
if (modeInfo.BlockSize > Av1BlockSize.Block4x4 && allowSelect && this.FrameInfo.TransformMode == Av1TransformMode.Select)
if (modeInfo.BlockSize > Av1BlockSize.Block4x4 && allowSelect && this.FrameHeader.TransformMode == Av1TransformMode.Select)
{
return this.ReadSelectedTransformSize(ref reader, partitionInfo, superblockInfo, tileInfo);
}
@ -1283,8 +1285,8 @@ internal class Av1TileReader : IAv1TileReader
{
int transformInfoYIndex = partitionInfo.ModeInfo.FirstTransformLocation[(int)Av1PlaneType.Y];
int transformInfoUvIndex = partitionInfo.ModeInfo.FirstTransformLocation[(int)Av1PlaneType.Uv];
Span<Av1TransformInfo> lumaTransformInfo = superblockInfo.GetTransformInfoY();
Span<Av1TransformInfo> chromaTransformInfo = superblockInfo.GetTransformInfoUv();
ref Av1TransformInfo lumaTransformInfo = ref superblockInfo.GetTransformInfoY();
ref Av1TransformInfo chromaTransformInfo = ref superblockInfo.GetTransformInfoUv();
int totalLumaTransformUnitCount = 0;
int totalChromaTransformUnitCount = 0;
int forceSplitCount = 0;
@ -1297,7 +1299,7 @@ internal class Av1TileReader : IAv1TileReader
width = Math.Min(width, maxBlockWide);
height = Math.Min(height, maxBlockHigh);
bool isLossLess = this.FrameInfo.LosslessArray[partitionInfo.ModeInfo.SegmentId];
bool isLossLess = this.FrameHeader.LosslessArray[partitionInfo.ModeInfo.SegmentId];
Av1TransformSize transformSizeUv = isLossLess ? Av1TransformSize.Size4x4 : blockSize.GetMaxUvTransformSize(subX, subY);
for (int idy = 0; idy < maxBlockHigh; idy += height)
@ -1317,7 +1319,7 @@ internal class Av1TileReader : IAv1TileReader
{
for (int blockColumn = idx; blockColumn < unitWidth; blockColumn += stepColumn)
{
lumaTransformInfo[transformInfoYIndex] = new Av1TransformInfo(
Unsafe.Add(ref lumaTransformInfo, transformInfoYIndex) = new Av1TransformInfo(
transformSize, blockColumn, blockRow);
transformInfoYIndex++;
lumaTransformUnitCount++;
@ -1342,7 +1344,7 @@ internal class Av1TileReader : IAv1TileReader
{
for (int blockColumn = idx; blockColumn < unitWidth; blockColumn += stepColumn)
{
chromaTransformInfo[transformInfoUvIndex] = new Av1TransformInfo(
Unsafe.Add(ref chromaTransformInfo, transformInfoUvIndex) = new Av1TransformInfo(
transformSizeUv, blockColumn, blockRow);
transformInfoUvIndex++;
chromaTransformUnitCount++;
@ -1363,9 +1365,13 @@ internal class Av1TileReader : IAv1TileReader
partitionInfo.ModeInfo.FirstTransformLocation[(int)Av1PlaneType.Uv],
nameof(totalChromaTransformUnitCount));
int originalIndex = transformInfoUvIndex - totalChromaTransformUnitCount;
ref Av1TransformInfo originalInfo = ref Unsafe.Add(ref chromaTransformInfo, originalIndex);
ref Av1TransformInfo infoV = ref Unsafe.Add(ref chromaTransformInfo, transformInfoUvIndex);
for (int i = 0; i < totalChromaTransformUnitCount; i++)
{
chromaTransformInfo[transformInfoUvIndex + i] = chromaTransformInfo[originalIndex + i];
infoV = originalInfo;
originalInfo = ref Unsafe.Add(ref originalInfo, 1);
infoV = ref Unsafe.Add(ref infoV, 1);
}
}
@ -1399,7 +1405,7 @@ internal class Av1TileReader : IAv1TileReader
/// </summary>
private void ReadModeInfo(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInfo)
{
DebugGuard.IsTrue(this.FrameInfo.FrameType is ObuFrameType.KeyFrame or ObuFrameType.IntraOnlyFrame, "Only INTRA frames supported.");
DebugGuard.IsTrue(this.FrameHeader.FrameType is ObuFrameType.KeyFrame or ObuFrameType.IntraOnlyFrame, "Only INTRA frames supported.");
this.ReadIntraFrameModeInfo(ref reader, partitionInfo);
}
@ -1408,21 +1414,21 @@ internal class Av1TileReader : IAv1TileReader
/// </summary>
private void ReadIntraFrameModeInfo(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInfo)
{
if (this.FrameInfo.SegmentationParameters.SegmentIdPrecedesSkip)
if (this.FrameHeader.SegmentationParameters.SegmentIdPrecedesSkip)
{
this.IntraSegmentId(ref reader, partitionInfo);
}
// this.skipMode = false;
partitionInfo.ModeInfo.Skip = this.ReadSkip(ref reader, partitionInfo);
if (!this.FrameInfo.SegmentationParameters.SegmentIdPrecedesSkip)
if (!this.FrameHeader.SegmentationParameters.SegmentIdPrecedesSkip)
{
this.IntraSegmentId(ref reader, partitionInfo);
}
this.ReadCdef(ref reader, partitionInfo);
if (this.FrameInfo.DeltaQParameters.IsPresent)
if (this.FrameHeader.DeltaQParameters.IsPresent)
{
this.ReadDeltaQuantizerIndex(ref reader, partitionInfo);
this.ReadDeltaLoopFilter(ref reader, partitionInfo);
@ -1468,7 +1474,7 @@ internal class Av1TileReader : IAv1TileReader
if (partitionInfo.ModeInfo.BlockSize >= Av1BlockSize.Block8x8 &&
partitionInfo.ModeInfo.BlockSize.GetWidth() <= 64 &&
partitionInfo.ModeInfo.BlockSize.GetHeight() <= 64 &&
this.FrameInfo.AllowScreenContentTools)
this.FrameHeader.AllowScreenContentTools)
{
this.PaletteModeInfo(ref reader, partitionInfo);
}
@ -1478,13 +1484,13 @@ internal class Av1TileReader : IAv1TileReader
}
private bool AllowIntraBlockCopy()
=> (this.FrameInfo.FrameType is ObuFrameType.KeyFrame or ObuFrameType.IntraOnlyFrame) &&
=> (this.FrameHeader.FrameType is ObuFrameType.KeyFrame or ObuFrameType.IntraOnlyFrame) &&
(this.SequenceHeader.ForceScreenContentTools > 0) &&
this.FrameInfo.AllowIntraBlockCopy;
this.FrameHeader.AllowIntraBlockCopy;
private bool IsChromaForLumaAllowed(Av1PartitionInfo partitionInfo)
{
if (this.FrameInfo.LosslessArray[partitionInfo.ModeInfo.SegmentId])
if (this.FrameHeader.LosslessArray[partitionInfo.ModeInfo.SegmentId])
{
// In lossless, CfL is available when the partition size is equal to the
// transform size.
@ -1569,15 +1575,15 @@ internal class Av1TileReader : IAv1TileReader
/// </summary>
private void IntraSegmentId(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInfo)
{
if (this.FrameInfo.SegmentationParameters.Enabled)
if (this.FrameHeader.SegmentationParameters.Enabled)
{
this.ReadSegmentId(ref reader, partitionInfo);
}
int blockWidth4x4 = partitionInfo.ModeInfo.BlockSize.Get4x4WideCount();
int blockHeight4x4 = partitionInfo.ModeInfo.BlockSize.Get4x4HighCount();
int modeInfoCountX = Math.Min(this.FrameInfo.ModeInfoColumnCount - partitionInfo.ColumnIndex, blockWidth4x4);
int modeInfoCountY = Math.Min(this.FrameInfo.ModeInfoRowCount - partitionInfo.RowIndex, blockHeight4x4);
int modeInfoCountX = Math.Min(this.FrameHeader.ModeInfoColumnCount - partitionInfo.ColumnIndex, blockWidth4x4);
int modeInfoCountY = Math.Min(this.FrameHeader.ModeInfoRowCount - partitionInfo.RowIndex, blockHeight4x4);
int segmentId = partitionInfo.ModeInfo.SegmentId;
for (int y = 0; y < modeInfoCountY; y++)
{
@ -1637,18 +1643,18 @@ internal class Av1TileReader : IAv1TileReader
int ctx = prevUL < 0 ? 0 /* Edge cases */
: prevUL == prevU && prevUL == prevL ? 2
: prevUL == prevU || prevUL == prevL || prevU == prevL ? 1 : 0;
int lastActiveSegmentId = this.FrameInfo.SegmentationParameters.LastActiveSegmentId;
int lastActiveSegmentId = this.FrameHeader.SegmentationParameters.LastActiveSegmentId;
partitionInfo.ModeInfo.SegmentId = NegativeDeinterleave(reader.ReadSegmentId(ctx), predictor, lastActiveSegmentId + 1);
}
}
private int GetSegmentId(Av1PartitionInfo partitionInfo, int rowIndex, int columnIndex)
{
int modeInfoOffset = (rowIndex * this.FrameInfo.ModeInfoColumnCount) + 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.FrameInfo.ModeInfoColumnCount - columnIndex, bw4);
int yMin = Math.Min(this.FrameInfo.ModeInfoRowCount - rowIndex, bh4);
int xMin = Math.Min(this.FrameHeader.ModeInfoColumnCount - columnIndex, bw4);
int yMin = Math.Min(this.FrameHeader.ModeInfoRowCount - rowIndex, bh4);
int segmentId = Av1Constants.MaxSegments - 1;
for (int y = 0; y < yMin; y++)
{
@ -1712,7 +1718,7 @@ internal class Av1TileReader : IAv1TileReader
/// </summary>
private void ReadCdef(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInfo)
{
if (partitionInfo.ModeInfo.Skip || this.FrameInfo.CodedLossless || !this.SequenceHeader.EnableCdef || this.FrameInfo.AllowIntraBlockCopy)
if (partitionInfo.ModeInfo.Skip || this.FrameHeader.CodedLossless || !this.SequenceHeader.EnableCdef || this.FrameHeader.AllowIntraBlockCopy)
{
return;
}
@ -1723,7 +1729,7 @@ internal class Av1TileReader : IAv1TileReader
int c = partitionInfo.ColumnIndex & cdefMask4;
if (partitionInfo.CdefStrength[r][c] == -1)
{
partitionInfo.CdefStrength[r][c] = reader.ReadLiteral(this.FrameInfo.CdefParameters.BitCount);
partitionInfo.CdefStrength[r][c] = reader.ReadLiteral(this.FrameHeader.CdefParameters.BitCount);
if (this.SequenceHeader.SuperblockSize == Av1BlockSize.Block128x128)
{
int w4 = partitionInfo.ModeInfo.BlockSize.Get4x4WideCount();
@ -1742,16 +1748,16 @@ internal class Av1TileReader : IAv1TileReader
private void ReadDeltaLoopFilter(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInfo)
{
Av1BlockSize superBlockSize = this.SequenceHeader.Use128x128Superblock ? Av1BlockSize.Block128x128 : Av1BlockSize.Block64x64;
if (this.FrameInfo.DeltaLoopFilterParameters.IsPresent ||
if (this.FrameHeader.DeltaLoopFilterParameters.IsPresent ||
(partitionInfo.ModeInfo.BlockSize == superBlockSize && partitionInfo.ModeInfo.Skip))
{
return;
}
if (this.FrameInfo.DeltaLoopFilterParameters.IsPresent)
if (this.FrameHeader.DeltaLoopFilterParameters.IsPresent)
{
int frameLoopFilterCount = 1;
if (this.FrameInfo.DeltaLoopFilterParameters.IsMulti)
if (this.FrameHeader.DeltaLoopFilterParameters.IsMulti)
{
frameLoopFilterCount = this.SequenceHeader.ColorConfig.PlaneCount > 1 ? Av1Constants.FrameLoopFilterCount : Av1Constants.FrameLoopFilterCount - 2;
}
@ -1771,7 +1777,7 @@ internal class Av1TileReader : IAv1TileReader
{
bool deltaLoopFilterSign = reader.ReadLiteral(1) > 0;
int reducedDeltaLoopFilterLevel = deltaLoopFilterSign ? -deltaLoopFilterAbsolute : deltaLoopFilterAbsolute;
int deltaLoopFilterResolution = this.FrameInfo.DeltaLoopFilterParameters.Resolution;
int deltaLoopFilterResolution = this.FrameHeader.DeltaLoopFilterParameters.Resolution;
currentDeltaLoopFilter[i] = Av1Math.Clip3(-Av1Constants.MaxLoopFilter, Av1Constants.MaxLoopFilter, currentDeltaLoopFilter[i] + (reducedDeltaLoopFilterLevel << deltaLoopFilterResolution));
}
}
@ -1781,8 +1787,8 @@ internal class Av1TileReader : IAv1TileReader
private bool ReadSkip(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInfo)
{
int segmentId = partitionInfo.ModeInfo.SegmentId;
if (this.FrameInfo.SegmentationParameters.SegmentIdPrecedesSkip &&
this.FrameInfo.SegmentationParameters.IsFeatureActive(segmentId, ObuSegmentationLevelFeature.Skip))
if (this.FrameHeader.SegmentationParameters.SegmentIdPrecedesSkip &&
this.FrameHeader.SegmentationParameters.IsFeatureActive(segmentId, ObuSegmentationLevelFeature.Skip))
{
return true;
}
@ -1797,7 +1803,7 @@ internal class Av1TileReader : IAv1TileReader
private void ReadDeltaQuantizerIndex(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInfo)
{
Av1BlockSize superBlockSize = this.SequenceHeader.Use128x128Superblock ? Av1BlockSize.Block128x128 : Av1BlockSize.Block64x64;
if (!this.FrameInfo.DeltaQParameters.IsPresent ||
if (!this.FrameHeader.DeltaQParameters.IsPresent ||
(partitionInfo.ModeInfo.BlockSize == superBlockSize && partitionInfo.ModeInfo.Skip))
{
return;
@ -1817,7 +1823,7 @@ internal class Av1TileReader : IAv1TileReader
{
bool deltaQuantizerSignBit = reader.ReadLiteral(1) > 0;
int reducedDeltaQuantizerIndex = deltaQuantizerSignBit ? -deltaQuantizerAbsolute : deltaQuantizerAbsolute;
int deltaQuantizerResolution = this.FrameInfo.DeltaQParameters.Resolution;
int deltaQuantizerResolution = this.FrameHeader.DeltaQParameters.Resolution;
this.currentQuantizerIndex = Av1Math.Clip3(1, 255, this.currentQuantizerIndex + (reducedDeltaQuantizerIndex << deltaQuantizerResolution));
partitionInfo.SuperblockInfo.SuperblockDeltaQ = this.currentQuantizerIndex;
}
@ -1825,10 +1831,10 @@ internal class Av1TileReader : IAv1TileReader
}
private bool IsInside(int rowIndex, int columnIndex) =>
columnIndex >= this.FrameInfo.TilesInfo.TileColumnCount &&
columnIndex < this.FrameInfo.TilesInfo.TileColumnCount &&
rowIndex >= this.FrameInfo.TilesInfo.TileRowCount &&
rowIndex < this.FrameInfo.TilesInfo.TileRowCount;
columnIndex >= this.FrameHeader.TilesInfo.TileColumnCount &&
columnIndex < this.FrameHeader.TilesInfo.TileColumnCount &&
rowIndex >= this.FrameHeader.TilesInfo.TileRowCount &&
rowIndex < this.FrameHeader.TilesInfo.TileRowCount;
/*
private static bool IsChroma(int rowIndex, int columnIndex, Av1BlockModeInfo blockMode, bool subSamplingX, bool subSamplingY)

8
src/ImageSharp/Formats/Heif/Av1/Transform/Av1FrameDecoder.cs

@ -10,20 +10,20 @@ internal class Av1FrameDecoder
{
private readonly ObuSequenceHeader sequenceHeader;
private readonly ObuFrameHeader frameHeader;
private readonly Av1FrameBuffer frameBuffer;
private readonly Av1FrameInfo frameInfo;
public Av1FrameDecoder(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, Av1FrameBuffer frameBuffer)
public Av1FrameDecoder(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, Av1FrameInfo frameInfo)
{
this.sequenceHeader = sequenceHeader;
this.frameHeader = frameHeader;
this.frameBuffer = frameBuffer;
this.frameInfo = frameInfo;
}
public void DecodeFrame()
{
Guard.NotNull(this.sequenceHeader);
Guard.NotNull(this.frameHeader);
Guard.NotNull(this.frameBuffer);
Guard.NotNull(this.frameInfo);
// TODO: Implement.
}

1
src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseQuantizer.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;
using SixLabors.ImageSharp.Formats.Heif.Av1.Transform;
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Quantization;

Loading…
Cancel
Save