diff --git a/src/ImageSharp/Formats/Heif/Av1/Av1BlockSize.cs b/src/ImageSharp/Formats/Heif/Av1/Av1BlockSize.cs index 6eca5bc638..f043208e98 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Av1BlockSize.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Av1BlockSize.cs @@ -32,3 +32,13 @@ internal enum Av1BlockSize BlockInvalid = 255, BlockLargest = BlockSizeS - 1, } + +internal static class Av1BlockSizeExtensions +{ + private static readonly int[] SizeWide = { 1, 1, 2, 2, 2, 4, 4, 4, 8, 8, 8, 16, 16, 16, 32, 32, 1, 4, 2, 8, 4, 16 }; + private static readonly int[] SizeHigh = { 1, 2, 1, 2, 4, 2, 4, 8, 4, 8, 16, 8, 16, 32, 16, 32, 4, 1, 8, 2, 16, 4 }; + + public static int Get4x4WideCount(this Av1BlockSize blockSize) => SizeWide[(int)blockSize]; + + public static int Get4x4HighCount(this Av1BlockSize blockSize) => SizeHigh[(int)blockSize]; +} diff --git a/src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs b/src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs index 7653fea9ce..c8bec52428 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs @@ -31,4 +31,21 @@ internal class Av1Decoder Av1BitStreamReader reader = new(buffer); ObuReader.Read(ref reader, buffer.Length, this, false); } + + internal void DecodeTile(ref Av1BitStreamReader reader, int tileNum) + { + // TODO: Implement + } + + internal void DecodeBlock(Av1BlockModeInfo blockMode, int rowIndex, int columnIndex) + { + int block4x4Width = blockMode.BlockSize.Get4x4WideCount(); + int block4x4Height = blockMode.BlockSize.Get4x4HighCount(); + + } + + internal void FinishDecodeTiles(ref Av1BitStreamReader reader, bool doCdef, bool doLoopRestoration) + { + // TODO: Implement + } } diff --git a/src/ImageSharp/Formats/Heif/Av1/Av1Math.cs b/src/ImageSharp/Formats/Heif/Av1/Av1Math.cs index 36929e3c65..ce5dd66269 100644 --- a/src/ImageSharp/Formats/Heif/Av1/Av1Math.cs +++ b/src/ImageSharp/Formats/Heif/Av1/Av1Math.cs @@ -5,7 +5,26 @@ namespace SixLabors.ImageSharp.Formats.Heif.Av1; internal static class Av1Math { - public static uint MostSignificantBit(uint value) => value >> 31; + public static int MostSignificantBit(uint value) + { + int log = 0; + int i; + + Guard.IsTrue(value != 0, nameof(value), "Must have al least 1 bit set"); + + for (i = 4; i >= 0; --i) + { + int shift = 1 << i; + uint x = value >> shift; + if (x != 0) + { + value = x; + log += shift; + } + } + + return log; + } public static uint Log2(uint n) { diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs index 656f3c57ea..6afd89a24c 100644 --- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs +++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs @@ -10,7 +10,7 @@ internal class ObuReader /// /// Decode all OBU's in a frame. /// - public static void Read(ref Av1BitStreamReader reader, int dataSize, Av1Decoder decoderHandle, bool isAnnexB) + public static void Read(ref Av1BitStreamReader reader, int dataSize, Av1Decoder decoder, bool isAnnexB) { bool frameDecodingFinished = false; while (!frameDecodingFinished) @@ -40,34 +40,34 @@ internal class ObuReader switch (header.Type) { case ObuType.SequenceHeader: - ReadSequenceHeader(ref reader, decoderHandle.SequenceHeader); - if (decoderHandle.SequenceHeader.ColorConfig.BitDepth == 12) + ReadSequenceHeader(ref reader, decoder.SequenceHeader); + if (decoder.SequenceHeader.ColorConfig.BitDepth == 12) { // TODO: Initialize 12 bit predictors } - decoderHandle.SequenceHeaderDone = true; + decoder.SequenceHeaderDone = true; break; case ObuType.FrameHeader: case ObuType.RedundantFrameHeader: case ObuType.Frame: if (header.Type != ObuType.Frame) { - decoderHandle.ShowExistingFrame = false; + decoder.ShowExistingFrame = false; } else if (header.Type != ObuType.FrameHeader) { - Guard.IsFalse(decoderHandle.SeenFrameHeader, nameof(Av1Decoder.SeenFrameHeader), "Frame header expected"); + Guard.IsFalse(decoder.SeenFrameHeader, nameof(Av1Decoder.SeenFrameHeader), "Frame header expected"); } else { - Guard.IsTrue(decoderHandle.SeenFrameHeader, nameof(Av1Decoder.SeenFrameHeader), "Already decoded a frame header"); + Guard.IsTrue(decoder.SeenFrameHeader, nameof(Av1Decoder.SeenFrameHeader), "Already decoded a frame header"); } - if (!decoderHandle.SeenFrameHeader) + if (!decoder.SeenFrameHeader) { - decoderHandle.SeenFrameHeader = true; - ReadFrameHeader(ref reader, decoderHandle.SequenceHeader, decoderHandle.FrameInfo, header, header.Type != ObuType.Frame); + decoder.SeenFrameHeader = true; + ReadFrameHeader(ref reader, decoder, header, header.Type != ObuType.Frame); } if (header.Type != ObuType.Frame) @@ -78,15 +78,15 @@ internal class ObuReader goto TILE_GROUP; case ObuType.TileGroup: TILE_GROUP: - if (!decoderHandle.SeenFrameHeader) + if (!decoder.SeenFrameHeader) { throw new InvalidImageContentException("Corrupt frame"); } - ReadTileGroup(ref reader, decoderHandle.SequenceHeader, decoderHandle.FrameInfo, decoderHandle.TileInfo, header, out frameDecodingFinished); + ReadTileGroup(ref reader, decoder, header, out frameDecodingFinished); if (frameDecodingFinished) { - decoderHandle.SeenFrameHeader = false; + decoder.SeenFrameHeader = false; } break; @@ -629,8 +629,10 @@ internal class ObuReader return tileInfo; } - private static void ReadUncompressedFrameHeader(ref Av1BitStreamReader reader, ObuHeader header, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, int planesCount) + private static void ReadUncompressedFrameHeader(ref Av1BitStreamReader reader, Av1Decoder decoder, ObuHeader header, int planesCount) { + ObuSequenceHeader sequenceHeader = decoder.SequenceHeader; + ObuFrameHeader frameInfo = decoder.FrameInfo; int idLength = 0; uint previousFrameId = 0; bool isIntraFrame = false; @@ -913,11 +915,13 @@ internal class ObuReader } } - private static void ReadFrameHeader(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, ObuHeader header, bool trailingBit) + private static void ReadFrameHeader(ref Av1BitStreamReader reader, Av1Decoder decoder, ObuHeader header, bool trailingBit) { + ObuSequenceHeader sequenceHeader = decoder.SequenceHeader; + ObuFrameHeader frameInfo = decoder.FrameInfo; int planeCount = sequenceHeader.ColorConfig.Monochrome ? 1 : 3; int startBitPosition = reader.BitPosition; - ReadUncompressedFrameHeader(ref reader, header, sequenceHeader, frameInfo, planeCount); + ReadUncompressedFrameHeader(ref reader, decoder, header, planeCount); if (trailingBit) { ReadTrailingBits(ref reader); @@ -930,8 +934,11 @@ internal class ObuReader header.PayloadSize -= headerBytes; } - private static void ReadTileGroup(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, ObuTileInfo tileInfo, ObuHeader header, out bool isLastTileGroup) + private static void ReadTileGroup(ref Av1BitStreamReader reader, Av1Decoder decoder, ObuHeader header, out bool isLastTileGroup) { + ObuSequenceHeader sequenceHeader = decoder.SequenceHeader; + ObuFrameHeader frameInfo = decoder.FrameInfo; + ObuTileInfo tileInfo = decoder.TileInfo; int tileCount = tileInfo.TileColumnCount * tileInfo.TileRowCount; int startBitPosition = reader.BitPosition; bool tileStartAndEndPresentFlag = false; @@ -984,7 +991,7 @@ internal class ObuReader } // TODO: Pass more info to the decoder. - // DecodeTile(sequenceHeader, frameInfo, tileInfo, tileNum); + decoder.DecodeTile(ref reader, tileNum); } if (tileGroupEnd != tileCount - 1) @@ -992,7 +999,7 @@ internal class ObuReader return; } - // FinishDecodeTiles(sequenceHeader, frameInfo, doCdef, doLoopRestoration); + decoder.FinishDecodeTiles(ref reader, doCdef, doLoopRestoration); } private static int ReadDeltaQ(ref Av1BitStreamReader reader) diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index b76a139019..63bc8131bd 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -241,9 +241,5 @@ - - - -