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, BlockInvalid = 255,
BlockLargest = BlockSizeS - 1, 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); Av1BitStreamReader reader = new(buffer);
ObuReader.Read(ref reader, buffer.Length, this, false); 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 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) public static uint Log2(uint n)
{ {

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

@ -10,7 +10,7 @@ internal class ObuReader
/// <summary> /// <summary>
/// Decode all OBU's in a frame. /// Decode all OBU's in a frame.
/// </summary> /// </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; bool frameDecodingFinished = false;
while (!frameDecodingFinished) while (!frameDecodingFinished)
@ -40,34 +40,34 @@ internal class ObuReader
switch (header.Type) switch (header.Type)
{ {
case ObuType.SequenceHeader: case ObuType.SequenceHeader:
ReadSequenceHeader(ref reader, decoderHandle.SequenceHeader); ReadSequenceHeader(ref reader, decoder.SequenceHeader);
if (decoderHandle.SequenceHeader.ColorConfig.BitDepth == 12) if (decoder.SequenceHeader.ColorConfig.BitDepth == 12)
{ {
// TODO: Initialize 12 bit predictors // TODO: Initialize 12 bit predictors
} }
decoderHandle.SequenceHeaderDone = true; decoder.SequenceHeaderDone = true;
break; break;
case ObuType.FrameHeader: case ObuType.FrameHeader:
case ObuType.RedundantFrameHeader: case ObuType.RedundantFrameHeader:
case ObuType.Frame: case ObuType.Frame:
if (header.Type != ObuType.Frame) if (header.Type != ObuType.Frame)
{ {
decoderHandle.ShowExistingFrame = false; decoder.ShowExistingFrame = false;
} }
else if (header.Type != ObuType.FrameHeader) 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 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; decoder.SeenFrameHeader = true;
ReadFrameHeader(ref reader, decoderHandle.SequenceHeader, decoderHandle.FrameInfo, header, header.Type != ObuType.Frame); ReadFrameHeader(ref reader, decoder, header, header.Type != ObuType.Frame);
} }
if (header.Type != ObuType.Frame) if (header.Type != ObuType.Frame)
@ -78,15 +78,15 @@ internal class ObuReader
goto TILE_GROUP; goto TILE_GROUP;
case ObuType.TileGroup: case ObuType.TileGroup:
TILE_GROUP: TILE_GROUP:
if (!decoderHandle.SeenFrameHeader) if (!decoder.SeenFrameHeader)
{ {
throw new InvalidImageContentException("Corrupt frame"); 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) if (frameDecodingFinished)
{ {
decoderHandle.SeenFrameHeader = false; decoder.SeenFrameHeader = false;
} }
break; break;
@ -629,8 +629,10 @@ internal class ObuReader
return tileInfo; 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; int idLength = 0;
uint previousFrameId = 0; uint previousFrameId = 0;
bool isIntraFrame = false; 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 planeCount = sequenceHeader.ColorConfig.Monochrome ? 1 : 3;
int startBitPosition = reader.BitPosition; int startBitPosition = reader.BitPosition;
ReadUncompressedFrameHeader(ref reader, header, sequenceHeader, frameInfo, planeCount); ReadUncompressedFrameHeader(ref reader, decoder, header, planeCount);
if (trailingBit) if (trailingBit)
{ {
ReadTrailingBits(ref reader); ReadTrailingBits(ref reader);
@ -930,8 +934,11 @@ internal class ObuReader
header.PayloadSize -= headerBytes; 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 tileCount = tileInfo.TileColumnCount * tileInfo.TileRowCount;
int startBitPosition = reader.BitPosition; int startBitPosition = reader.BitPosition;
bool tileStartAndEndPresentFlag = false; bool tileStartAndEndPresentFlag = false;
@ -984,7 +991,7 @@ internal class ObuReader
} }
// TODO: Pass more info to the decoder. // TODO: Pass more info to the decoder.
// DecodeTile(sequenceHeader, frameInfo, tileInfo, tileNum); decoder.DecodeTile(ref reader, tileNum);
} }
if (tileGroupEnd != tileCount - 1) if (tileGroupEnd != tileCount - 1)
@ -992,7 +999,7 @@ internal class ObuReader
return; return;
} }
// FinishDecodeTiles(sequenceHeader, frameInfo, doCdef, doLoopRestoration); decoder.FinishDecodeTiles(ref reader, doCdef, doLoopRestoration);
} }
private static int ReadDeltaQ(ref Av1BitStreamReader reader) private static int ReadDeltaQ(ref Av1BitStreamReader reader)

4
src/ImageSharp/ImageSharp.csproj

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

Loading…
Cancel
Save