diff --git a/src/ImageSharp/Formats/Heif/Av1/Av1BlockModeInfo.cs b/src/ImageSharp/Formats/Heif/Av1/Av1BlockModeInfo.cs deleted file mode 100644 index 4f41d47082..0000000000 --- a/src/ImageSharp/Formats/Heif/Av1/Av1BlockModeInfo.cs +++ /dev/null @@ -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; } -} diff --git a/src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs b/src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs index 16897aba40..ac753a5da6 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs +++ b/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 buffer) { @@ -29,8 +29,8 @@ public void Decode(Span buffer) 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(); } diff --git a/src/ImageSharp/Formats/Heif/Av1/Av1FrameBuffer.cs b/src/ImageSharp/Formats/Heif/Av1/Av1FrameBuffer.cs new file mode 100644 index 0000000000..1267502eb8 --- /dev/null +++ b/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; + +/// +/// Buffer for the pixels of a single frame. +/// +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(strideY * bitsPerPixel, heightY); + } + + if ((this.BufferEnableMask & PictureBufferCbFlag) != 0) + { + this.BufferCb = configuration.MemoryAllocator.Allocate2D(strideChroma * bitsPerPixel, heightChroma); + } + + if ((this.BufferEnableMask & PictureBufferCrFlag) != 0) + { + this.BufferCr = configuration.MemoryAllocator.Allocate2D(strideChroma * bitsPerPixel, heightChroma); + } + + this.BitIncrementY = null; + this.BitIncrementCb = null; + this.BitIncrementCr = null; + this.BitIncrementY = null; + this.BitIncrementCb = null; + this.BitIncrementCr = null; + } + + /// + /// Gets the Y luma buffer. + /// + public Buffer2D? BufferY { get; private set; } + + /// + /// Gets the U chroma buffer. + /// + public Buffer2D? BufferCb { get; private set; } + + /// + /// Gets the V chroma buffer. + /// + public Buffer2D? BufferCr { get; private set; } + + public Buffer2D? BitIncrementY { get; private set; } + + public Buffer2D? BitIncrementCb { get; private set; } + + public Buffer2D? BitIncrementCr { get; private set; } + + /// + /// Gets or sets the horizontal padding distance. + /// + public int OriginX { get; set; } + + /// + /// Gets or sets the vertical padding distance. + /// + public int OriginY { get; set; } + + /// + /// Gets or sets the vertical bottom padding distance + /// + public int OriginOriginY { get; set; } + + /// + /// Gets or sets the Luma picture width, which excludes the padding. + /// + public int Width { get; set; } + + /// + /// Gets or sets the Luma picture height, which excludes the padding. + /// + public int Height { get; set; } + + /// + /// Gets or sets the Lume picture width. + /// + public int MaxWidth { get; set; } + + /// + /// Gets or sets the pixel bit depth. + /// + public Av1BitDepth BitDepth { get; set; } + + /// + /// Gets or sets the chroma subsampling. + /// + public Av1ColorFormat ColorFormat { get; set; } + + /// + /// Gets or sets the Luma picture height. + /// + public int MaxHeight { get; set; } + + public int LumaSize { get; } + + public int ChromaSize { get; } + + /// + /// Gets or sets a value indicating whether the bytes of the buffers are packed. + /// + public bool PackedFlag { get; set; } + + /// + /// Gets or sets a value indicating whether film grain parameters are present for this frame. + /// + 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; + } +} diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs index c0d5c63f1e..c933055afe 100644 --- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs +++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs @@ -241,10 +241,10 @@ private static void AlignToByteBoundary(ref Av1BitStreamReader reader) 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; } /// @@ -582,7 +582,7 @@ private static void ReadBitDepth(ref Av1BitStreamReader reader, ObuColorConfig c 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 @@ private void ReadSuperResolutionParameters(ref Av1BitStreamReader reader) 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 @@ private void ReadSuperResolutionParameters(ref Av1BitStreamReader reader) /// 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 @@ private void ReadRenderSize(ref Av1BitStreamReader reader) 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 @@ private void ReadFrameSize(ref Av1BitStreamReader reader, bool frameSizeOverride /// /// 5.9.15. Tile info syntax. /// - 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 @@ private static ObuTileGroupHeader ReadTileInfo(ref Av1BitStreamReader reader, Ob 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 @@ private static ObuTileGroupHeader ReadTileInfo(ref Av1BitStreamReader reader, Ob i++; } - tileInfo.TileRowStartModeInfo[i] = frameInfo.ModeInfoRowCount; + tileInfo.TileRowStartModeInfo[i] = frameHeader.ModeInfoRowCount; tileInfo.TileRowCount = i; } else @@ -750,7 +750,7 @@ private static ObuTileGroupHeader ReadTileInfo(ref Av1BitStreamReader reader, Ob 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 @@ private static ObuTileGroupHeader ReadTileInfo(ref Av1BitStreamReader reader, Ob 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 @@ private void ReadUncompressedFrameHeader(ref Av1BitStreamReader reader) 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 @@ private void ReadUncompressedFrameHeader(ref Av1BitStreamReader reader) } else { - // LoadCdfs(frameInfo.PrimaryReferenceFrame); + // LoadCdfs(frameHeader.PrimaryReferenceFrame); // LoadPrevious(); throw new NotImplementedException(); } @@ -1066,7 +1066,7 @@ private void ReadUncompressedFrameHeader(ref Av1BitStreamReader reader) 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 @@ private void ReadUncompressedFrameHeader(ref Av1BitStreamReader reader) // SetupSegmentationDequantization(); if (frameHeader.PrimaryReferenceFrame == Av1Constants.PrimaryReferenceFrameNone) { - // ResetParseContext(mainParseContext, frameInfo.QuantizationParameters.BaseQIndex); + // ResetParseContext(mainParseContext, frameHeader.QuantizationParameters.BaseQIndex); } else { @@ -1190,7 +1190,7 @@ internal void ReadFrameHeader(ref Av1BitStreamReader reader, ObuHeader header, b 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 @@ private void ReadTileGroup(ref Av1BitStreamReader reader, IAv1TileReader decoder 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 @@ private static int ReadDeltaQ(ref Av1BitStreamReader reader) /// /// 5.9.17. Quantizer index delta parameters syntax. /// - 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); } } /// /// 5.9.18. Loop filter delta parameters syntax. /// - 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 @@ private static void ReadQuantizationParameters(ref Av1BitStreamReader reader, Ob /// /// 5.9.14. Segmentation params syntax. /// - 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 @@ private static void ReadSegmentationParameters(ref Av1BitStreamReader reader, Ob { 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 @@ private static void ReadSegmentationParameters(ref Av1BitStreamReader reader, Ob } } - frameInfo.SegmentationParameters.FeatureData[i, j] = clippedValue; + frameHeader.SegmentationParameters.FeatureData[i, j] = clippedValue; } } } @@ -1431,24 +1431,24 @@ private static void ReadSegmentationParameters(ref Av1BitStreamReader reader, Ob { 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 @@ private static void ReadSegmentationParameters(ref Av1BitStreamReader reader, Ob /// 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 @@ private void ReadLoopFilterParameters(ref Av1BitStreamReader reader, ObuSequence { if (reader.ReadBoolean()) { - frameInfo.LoopFilterParameters.ModeDeltas[i] = reader.ReadSignedFromUnsigned(7); + frameHeader.LoopFilterParameters.ModeDeltas[i] = reader.ReadSignedFromUnsigned(7); } } } @@ -1507,21 +1507,21 @@ private void ReadLoopFilterParameters(ref Av1BitStreamReader reader, ObuSequence /// /// 5.9.21. TX mode syntax. /// - 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 @@ private static void ReadTransformMode(ref Av1BitStreamReader reader, ObuFrameHea /// /// See section 5.9.20. Loop restoration params syntax. /// - 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 @@ private static void ReadSkipModeParameters(ref Av1BitStreamReader reader, ObuSeq /// /// 5.9.30. Film grain params syntax. /// - 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 @@ private static ObuFilmGrainParameters ReadFilmGrainFilterParameters(ref Av1BitSt grainParams.GrainSeed = reader.ReadLiteral(16); - if (frameInfo.FrameType == ObuFrameType.InterFrame) + if (frameHeader.FrameType == ObuFrameType.InterFrame) { grainParams.UpdateGrain = reader.ReadBoolean(); } diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs index 1772daf722..16452799d7 100644 --- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs +++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs @@ -14,7 +14,7 @@ internal class ObuWriter /// /// Encode a single frame into OBU's. /// - 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 @@ public void WriteAll(Configuration configuration, Stream stream, ObuSequenceHead 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 @@ private static void WriteBitDepth(ref Av1BitStreamWriter writer, ObuColorConfig } } - 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 @@ private static void WriteSuperResolutionParameters(ref Av1BitStreamWriter writer 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 @@ private static void WriteFrameSizeWithReferences(ref Av1BitStreamWriter writer, 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 @@ private static void WriteTileInfo(ref Av1BitStreamWriter writer, ObuSequenceHead 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 @@ private void WriteUncompressedFrameHeader(ref Av1BitStreamWriter writer, ObuSequ } else { - // Guard.IsTrue(frameInfo.AllowScreenContentTools == sequenceHeader.ForceScreenContentTools); + // Guard.IsTrue(frameHeader.AllowScreenContentTools == sequenceHeader.ForceScreenContentTools); } if (frameHeader.AllowScreenContentTools) @@ -367,7 +367,7 @@ private void WriteUncompressedFrameHeader(ref Av1BitStreamWriter writer, ObuSequ } 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 @@ private void WriteUncompressedFrameHeader(ref Av1BitStreamWriter writer, ObuSequ 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 @@ private static int WriteDeltaQ(ref Av1BitStreamWriter writer, int deltaQ) 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 @@ private static void WriteQuantizationParameters(ref Av1BitStreamWriter writer, O } } - 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 @@ private static void WriteLoopFilterParameters(ref Av1BitStreamWriter writer, Obu /// /// 5.9.21. TX mode syntax. /// - 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); } } diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockModeInfo.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockModeInfo.cs index 6d742c97c2..dbbbf4f50d 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockModeInfo.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1BlockModeInfo.cs @@ -56,7 +56,7 @@ public Av1BlockModeInfo(int numPlanes, Av1BlockSize blockSize, Point positionInS public Av1IntraFilterModeInfo FilterIntraModeInfo { get; internal set; } /// - /// Gets the index of the first of this Mode Info in the . + /// Gets the index of the first of this Mode Info in the . /// public int[] FirstTransformLocation { get; } diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameBuffer.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs similarity index 92% rename from src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameBuffer.cs rename to src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs index 96643183dd..41011d93fd 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameBuffer.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameInfo.cs @@ -5,7 +5,10 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1.Tiling; -internal partial class Av1FrameBuffer +/// +/// Collection of all information for a single frame. +/// +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 @@ public Av1BlockModeInfo GetModeInfo(Point superblockIndex, Point modeInfoIndex) return this.modeInfos[index]; } - public Span 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 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 GetSuperblockTransformUv(Point index) + public ref Av1TransformInfo GetSuperblockTransformUv(Point index) { Span 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 GetCoefficients(int plane) => diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameModeInfoMap.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameModeInfoMap.cs index 196a409352..6867b3966d 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1FrameModeInfoMap.cs +++ b/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 { /// - /// Mapping of instances, from position to index into the . + /// Mapping of instances, from position to index into the . /// /// /// For a visual representation of how this map looks in practice, see diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1PartitionInfo.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1PartitionInfo.cs index c1e733bfbe..1c706c34e0 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1PartitionInfo.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1PartitionInfo.cs @@ -75,7 +75,7 @@ public Av1PartitionInfo(Av1BlockModeInfo modeInfo, Av1SuperblockInfo superblockI 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 @@ public void ComputeBoundaryOffsets(ObuFrameHeader frameInfo, Av1TileInfo tileInf 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) diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SuperblockInfo.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SuperblockInfo.cs index bb5a90d0d0..f2484c264b 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1SuperblockInfo.cs +++ b/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; } /// @@ -18,27 +18,29 @@ public Av1SuperblockInfo(Av1FrameBuffer frameBuffer, Point position) /// 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 CoefficientsY => this.frameBuffer.GetCoefficientsY(this.Position); + public Span CoefficientsY => this.frameInfo.GetCoefficientsY(this.Position); - public Span CoefficientsU => this.frameBuffer.GetCoefficientsU(this.Position); + public Span CoefficientsU => this.frameInfo.GetCoefficientsU(this.Position); - public Span CoefficientsV => this.frameBuffer.GetCoefficientsV(this.Position); + public Span CoefficientsV => this.frameInfo.GetCoefficientsV(this.Position); - public Span CdefStrength => this.frameBuffer.GetCdefStrength(this.Position); + public Span CdefStrength => this.frameInfo.GetCdefStrength(this.Position); - public Span SuperblockDeltaLoopFilter => this.frameBuffer.GetDeltaLoopFilter(this.Position); + public Span SuperblockDeltaLoopFilter => this.frameInfo.GetDeltaLoopFilter(this.Position); public int TransformInfoIndexY { get; internal set; } public int TransformInfoIndexUv { get; internal set; } - public Span GetTransformInfoY() => this.frameBuffer.GetSuperblockTransformY(this.Position); + public int BlockCount { get; internal set; } - public Span 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); } diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileInfo.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileInfo.cs index f4058b9183..4a5e503c83 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileInfo.cs +++ b/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; } diff --git a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs b/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs index 656cbc6055..47780069e8 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Tiling/Av1TileReader.cs +++ b/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 @@ public Av1TileReader(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo) 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 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 @@ public void ReadTile(Span tileData, int tileNum) } } - 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 @@ public void ReadTile(Span tileData, int tileNum) { 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 @@ public void ReadTile(Span tileData, int tileNum) } 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 @@ private void ParsePartition(ref Av1SymbolDecoder reader, Point modeInfoLocation, { 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 @@ private void ParsePartition(ref Av1SymbolDecoder reader, Point modeInfoLocation, 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 @@ private void ParsePartition(ref Av1SymbolDecoder reader, Point modeInfoLocation, 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 @@ private void ParsePartition(ref Av1SymbolDecoder reader, Point modeInfoLocation, 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 @@ private void ParseBlock(ref Av1SymbolDecoder reader, Point modeInfoLocation, Av1 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 @@ private void ParseBlock(ref Av1SymbolDecoder reader, Point modeInfoLocation, Av1 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 @@ private void ResetSkipContext(Av1PartitionInfo partitionInfo) 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 @@ private void Residual(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInf 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 @@ private void Residual(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInf continue; } - Span 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 @@ private void Residual(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInf 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 @@ private void Residual(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInf 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 @@ private void Residual(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInf } } - 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 @@ private int ParseTransformBlock( /// 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 coefficientBuffer = this.FrameBuffer.GetCoefficients(plane); + Span 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 @@ private static int RecordEndOfBlockPosition(int endOfBlockPoint, int endOfBlockE 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 @@ private Av1TransformType ComputeTransformType(Av1PlaneType planeType, Av1Partiti } } - 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 @@ private static int GetEntropyContext(Av1TransformSize transformSize, int[] above 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 @@ private unsafe void UpdateTransformInfo(Av1PartitionInfo partitionInfo, Av1Super { int transformInfoYIndex = partitionInfo.ModeInfo.FirstTransformLocation[(int)Av1PlaneType.Y]; int transformInfoUvIndex = partitionInfo.ModeInfo.FirstTransformLocation[(int)Av1PlaneType.Uv]; - Span lumaTransformInfo = superblockInfo.GetTransformInfoY(); - Span 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 @@ private unsafe void UpdateTransformInfo(Av1PartitionInfo partitionInfo, Av1Super 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 @@ private unsafe void UpdateTransformInfo(Av1PartitionInfo partitionInfo, Av1Super { 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 @@ private unsafe void UpdateTransformInfo(Av1PartitionInfo partitionInfo, Av1Super { 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 @@ private unsafe void UpdateTransformInfo(Av1PartitionInfo partitionInfo, Av1Super 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 @@ private static void ReadPaletteTokens(ref Av1SymbolDecoder reader, Av1PartitionI /// 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 @@ private void ReadModeInfo(ref Av1SymbolDecoder reader, Av1PartitionInfo partitio /// 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 @@ private void ReadIntraFrameModeInfo(ref Av1SymbolDecoder reader, Av1PartitionInf 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 @@ private void ReadIntraFrameModeInfo(ref Av1SymbolDecoder reader, Av1PartitionInf } 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 @@ private static bool IsDirectionalMode(Av1PredictionMode mode) /// 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 @@ private void ReadSegmentId(ref Av1SymbolDecoder reader, Av1PartitionInfo partiti 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 @@ private static int NegativeDeinterleave(int diff, int reference, int max) /// 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 @@ private void ReadCdef(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInf 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 @@ private void ReadCdef(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInf 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 @@ private void ReadDeltaLoopFilter(ref Av1SymbolDecoder reader, Av1PartitionInfo p { 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 @@ private void ReadDeltaLoopFilter(ref Av1SymbolDecoder reader, Av1PartitionInfo p 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 @@ private bool ReadSkip(ref Av1SymbolDecoder reader, Av1PartitionInfo partitionInf 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 @@ private void ReadDeltaQuantizerIndex(ref Av1SymbolDecoder reader, Av1PartitionIn { 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 @@ private void ReadDeltaQuantizerIndex(ref Av1SymbolDecoder reader, Av1PartitionIn } 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) diff --git a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1FrameDecoder.cs b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1FrameDecoder.cs index 040ce87b9c..981075d83f 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1FrameDecoder.cs +++ b/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. } diff --git a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseQuantizer.cs b/src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseQuantizer.cs index 312891c85e..c3213378cb 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Transform/Av1InverseQuantizer.cs +++ b/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;