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 @@
-
-
-
-