Browse Source

Tile decoding interface

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
f2bfd5a25a
  1. 10
      src/ImageSharp/Formats/Heif/Av1/Av1BlockSize.cs
  2. 17
      src/ImageSharp/Formats/Heif/Av1/Av1Decoder.cs
  3. 21
      src/ImageSharp/Formats/Heif/Av1/Av1Math.cs
  4. 45
      src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs
  5. 4
      src/ImageSharp/ImageSharp.csproj

10
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];
}

17
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
}
}

21
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)
{

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

@ -10,7 +10,7 @@ internal class ObuReader
/// <summary>
/// Decode all OBU's in a frame.
/// </summary>
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)

4
src/ImageSharp/ImageSharp.csproj

@ -241,9 +241,5 @@
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup>
<ItemGroup>
<Folder Include="Formats\Heif\Av1\Entropy\" />
</ItemGroup>
<Import Project="..\..\shared-infrastructure\src\SharedInfrastructure\SharedInfrastructure.projitems" Label="Shared" />
</Project>

Loading…
Cancel
Save