mirror of https://github.com/SixLabors/ImageSharp
61 changed files with 3160 additions and 8 deletions
@ -1 +1 @@ |
|||
Subproject commit 1dbfb576c83507645265c79e03369b66cdc0379f |
|||
Subproject commit 922c5b21e5dfa02d4ef0d95334ab01c87a7a4309 |
|||
@ -0,0 +1,11 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1; |
|||
|
|||
internal enum Av1BitDepth : int |
|||
{ |
|||
EightBit = 0, |
|||
TenBit = 1, |
|||
TwelveBit = 2, |
|||
} |
|||
@ -0,0 +1,174 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1; |
|||
|
|||
internal ref struct Av1BitStreamReader |
|||
{ |
|||
private const int WordSize = 32; |
|||
|
|||
private readonly Span<uint> data; |
|||
private uint currentWord; |
|||
private uint nextWord; |
|||
private int wordPosition = 0; |
|||
private int bitOffset = 0; |
|||
|
|||
public Av1BitStreamReader(Span<byte> data) |
|||
{ |
|||
this.data = MemoryMarshal.Cast<byte, uint>(data); |
|||
this.wordPosition = -1; |
|||
this.AdvanceToNextWord(); |
|||
this.AdvanceToNextWord(); |
|||
} |
|||
|
|||
public readonly int BitPosition => ((this.wordPosition - 1) * WordSize) + this.bitOffset; |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of bytes in the readers buffer.
|
|||
/// </summary>
|
|||
public readonly int Length => this.data.Length; |
|||
|
|||
public void Reset() |
|||
{ |
|||
this.wordPosition = 0; |
|||
this.bitOffset = 0; |
|||
} |
|||
|
|||
public void Skip(int bitCount) |
|||
{ |
|||
this.bitOffset += bitCount; |
|||
while (this.bitOffset >= WordSize) |
|||
{ |
|||
this.bitOffset -= WordSize; |
|||
this.wordPosition++; |
|||
} |
|||
} |
|||
|
|||
public uint ReadLiteral(int bitCount) |
|||
{ |
|||
DebugGuard.MustBeBetweenOrEqualTo(bitCount, 0, 32, nameof(bitCount)); |
|||
|
|||
uint bits = (this.currentWord << this.bitOffset) >> (WordSize - bitCount); |
|||
this.bitOffset += bitCount; |
|||
if (this.bitOffset > WordSize) |
|||
{ |
|||
int overshoot = WordSize + WordSize - this.bitOffset; |
|||
if (overshoot < 32) |
|||
{ |
|||
bits |= this.nextWord >> overshoot; |
|||
} |
|||
} |
|||
|
|||
if (this.bitOffset >= WordSize) |
|||
{ |
|||
this.AdvanceToNextWord(); |
|||
this.bitOffset -= WordSize; |
|||
} |
|||
|
|||
return bits; |
|||
} |
|||
|
|||
internal bool ReadBoolean() => this.ReadLiteral(1) > 0; |
|||
|
|||
public ulong ReadLittleEndianBytes128(out int length) |
|||
{ |
|||
// See section 4.10.5 of the AV1-Specification
|
|||
DebugGuard.IsTrue((this.bitOffset & 0x07) == 0, $"Reading of Little Endian 128 value only allowed on byte alignment (offset {this.BitPosition})."); |
|||
|
|||
ulong value = 0; |
|||
length = 0; |
|||
for (int i = 0; i < 56; i += 7) |
|||
{ |
|||
uint leb128Byte = this.ReadLiteral(8); |
|||
value |= (leb128Byte & 0x7FUL) << i; |
|||
length++; |
|||
if ((leb128Byte & 0x80U) == 0) |
|||
{ |
|||
break; |
|||
} |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
public uint ReadUnsignedVariableLength() |
|||
{ |
|||
// See section 4.10.3 of the AV1-Specification
|
|||
int leadingZerosCount = 0; |
|||
while (leadingZerosCount < 32 && this.ReadLiteral(1) == 0U) |
|||
{ |
|||
leadingZerosCount++; |
|||
} |
|||
|
|||
if (leadingZerosCount == 32) |
|||
{ |
|||
return uint.MaxValue; |
|||
} |
|||
|
|||
uint basis = (1U << leadingZerosCount) - 1U; |
|||
uint value = this.ReadLiteral(leadingZerosCount); |
|||
return basis + value; |
|||
} |
|||
|
|||
public uint ReadNonSymmetric(uint n) |
|||
{ |
|||
// See section 4.10.7 of the AV1-Specification
|
|||
if (n <= 1) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
int w = (int)(Av1Math.FloorLog2(n) + 1); |
|||
uint m = (uint)((1 << w) - n); |
|||
uint v = this.ReadLiteral(w - 1); |
|||
if (v < m) |
|||
{ |
|||
return v; |
|||
} |
|||
|
|||
return (v << 1) - m + this.ReadLiteral(1); |
|||
} |
|||
|
|||
public int ReadSignedFromUnsigned(int n) |
|||
{ |
|||
// See section 4.10.6 of the AV1-Specification
|
|||
int signedValue; |
|||
uint value = this.ReadLiteral(n); |
|||
uint signMask = 1U << (n - 1); |
|||
if ((value & signMask) == signMask) |
|||
{ |
|||
// Prevent overflow by casting to long;
|
|||
signedValue = (int)((long)value - (signMask << 1)); |
|||
} |
|||
else |
|||
{ |
|||
signedValue = (int)value; |
|||
} |
|||
|
|||
return signedValue; |
|||
} |
|||
|
|||
public uint ReadLittleEndian(int n) |
|||
{ |
|||
// See section 4.10.4 of the AV1-Specification
|
|||
DebugGuard.IsTrue((this.bitOffset & (WordSize - 1)) == 0, "Reading of Little Endian value only allowed on byte alignment"); |
|||
|
|||
uint t = 0; |
|||
for (int i = 0; i < 8 * n; i += 8) |
|||
{ |
|||
t += this.ReadLiteral(8) << i; |
|||
} |
|||
|
|||
return t; |
|||
} |
|||
|
|||
public void AdvanceToNextWord() |
|||
{ |
|||
this.currentWord = this.nextWord; |
|||
this.wordPosition++; |
|||
uint temp = this.data[this.wordPosition]; |
|||
this.nextWord = (temp << 24) | ((temp & 0x0000ff00U) << 8) | ((temp & 0x00ff0000U) >> 8) | (temp >> 24); |
|||
} |
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1; |
|||
|
|||
internal ref struct Av1BitStreamWriter(Stream stream) |
|||
{ |
|||
private const int WordSize = 8; |
|||
private readonly Stream stream = stream; |
|||
private byte buffer = 0; |
|||
private int bitOffset = 0; |
|||
|
|||
public readonly int BitPosition => (int)(this.stream.Position * WordSize) + this.bitOffset; |
|||
|
|||
public readonly int Length => (int)this.stream.Length; |
|||
|
|||
public void Skip(int bitCount) |
|||
{ |
|||
this.bitOffset += bitCount; |
|||
while (this.bitOffset >= WordSize) |
|||
{ |
|||
this.bitOffset -= WordSize; |
|||
this.stream.WriteByte(this.buffer); |
|||
this.buffer = 0; |
|||
} |
|||
} |
|||
|
|||
public void Flush() |
|||
{ |
|||
this.stream.WriteByte(this.buffer); |
|||
this.bitOffset = 0; |
|||
} |
|||
|
|||
public void WriteLiteral(uint value, int bitCount) |
|||
{ |
|||
int shift = 24; |
|||
uint padded = value << ((32 - bitCount) - this.bitOffset); |
|||
while ((bitCount + this.bitOffset) >= 8) |
|||
{ |
|||
byte current = (byte)(((padded >> shift) & 0xff) | this.buffer); |
|||
this.stream.WriteByte(current); |
|||
shift -= 8; |
|||
bitCount -= 8; |
|||
this.buffer = 0; |
|||
this.bitOffset = 0; |
|||
} |
|||
|
|||
if (bitCount > 0) |
|||
{ |
|||
this.buffer = (byte)(((padded >> shift) & 0xff) | this.buffer); |
|||
this.bitOffset += bitCount; |
|||
} |
|||
} |
|||
|
|||
internal void WriteBoolean(bool value) |
|||
{ |
|||
byte boolByte = value ? (byte)1 : (byte)0; |
|||
this.buffer = (byte)(((boolByte << (7 - this.bitOffset)) & 0xff) | this.buffer); |
|||
this.bitOffset++; |
|||
if (this.bitOffset == WordSize) |
|||
{ |
|||
this.stream.WriteByte(this.buffer); |
|||
this.bitOffset = 0; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
// 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; } |
|||
|
|||
public int SegmentId { get; } |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1; |
|||
|
|||
internal enum Av1BlockSize |
|||
{ |
|||
Block4x4, |
|||
Block4x8, |
|||
Block8x4, |
|||
Block8x8, |
|||
Block8x16, |
|||
Block16x8, |
|||
Block16x16, |
|||
Block16x32, |
|||
Block32x16, |
|||
Block32x32, |
|||
Block32x64, |
|||
Block64x32, |
|||
Block64x64, |
|||
Block64x128, |
|||
Block128x64, |
|||
Block128x128, |
|||
Block4x16, |
|||
Block16x4, |
|||
Block8x32, |
|||
Block32x8, |
|||
Block16x64, |
|||
Block64x16, |
|||
BlockSizeSAll, |
|||
BlockSizeS = Block4x16, |
|||
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]; |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1; |
|||
|
|||
internal enum Av1ColorFormat |
|||
{ |
|||
Yuv400, |
|||
Yuv420, |
|||
Yuv422, |
|||
Yuv444, |
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1; |
|||
|
|||
internal class Av1Decoder |
|||
{ |
|||
public Av1Decoder() |
|||
{ |
|||
this.FrameInfo = new ObuFrameHeader(); |
|||
this.SequenceHeader = new ObuSequenceHeader(); |
|||
this.TileInfo = new ObuTileInfo(); |
|||
} |
|||
|
|||
public bool SequenceHeaderDone { get; set; } |
|||
|
|||
public bool ShowExistingFrame { get; set; } |
|||
|
|||
public bool SeenFrameHeader { get; set; } |
|||
|
|||
public ObuFrameHeader FrameInfo { get; } |
|||
|
|||
public ObuSequenceHeader SequenceHeader { get; } |
|||
|
|||
public ObuTileInfo TileInfo { get; } |
|||
|
|||
public void Decode(Span<byte> buffer) |
|||
{ |
|||
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
|
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1; |
|||
|
|||
internal class Av1MainParseContext |
|||
{ |
|||
} |
|||
@ -0,0 +1,142 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1; |
|||
|
|||
internal static class Av1Math |
|||
{ |
|||
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) |
|||
{ |
|||
uint result = 0U; |
|||
while ((n >>= 1) > 0) |
|||
{ |
|||
result++; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
public static int Log2(int n) |
|||
{ |
|||
int result = 0; |
|||
while ((n >>= 1) > 0) |
|||
{ |
|||
result++; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
public static uint FloorLog2(uint value) |
|||
{ |
|||
uint s = 0; |
|||
while (value != 0U) |
|||
{ |
|||
value >>= 1; |
|||
s++; |
|||
} |
|||
|
|||
return s - 1; |
|||
} |
|||
|
|||
public static uint CeilLog2(uint value) |
|||
{ |
|||
if (value < 2) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
uint i = 1; |
|||
uint p = 2; |
|||
while (p < value) |
|||
{ |
|||
i++; |
|||
p <<= 1; |
|||
} |
|||
|
|||
return i; |
|||
} |
|||
|
|||
public static uint Clip1(uint value, int bitDepth) => |
|||
Clip3(0, (1U << bitDepth) - 1, value); |
|||
|
|||
public static uint Clip3(uint x, uint y, uint z) |
|||
{ |
|||
if (z < x) |
|||
{ |
|||
return x; |
|||
} |
|||
|
|||
if (z > y) |
|||
{ |
|||
return y; |
|||
} |
|||
|
|||
return z; |
|||
} |
|||
|
|||
public static int Clip3(int x, int y, int z) |
|||
{ |
|||
if (z < x) |
|||
{ |
|||
return x; |
|||
} |
|||
|
|||
if (z > y) |
|||
{ |
|||
return y; |
|||
} |
|||
|
|||
return z; |
|||
} |
|||
|
|||
public static uint Round2(uint value, int n) |
|||
{ |
|||
if (n == 0) |
|||
{ |
|||
return value; |
|||
} |
|||
|
|||
return (uint)((value + (1 << (n - 1))) >> n); |
|||
} |
|||
|
|||
public static int Round2(int value, int n) |
|||
{ |
|||
if (value < 0) |
|||
{ |
|||
value = -value; |
|||
} |
|||
|
|||
return (int)Round2((uint)value, n); |
|||
} |
|||
|
|||
internal static int AlignPowerOf2(int value, int n) |
|||
{ |
|||
int mask = (1 << n) - 1; |
|||
return (value + mask) & ~mask; |
|||
} |
|||
|
|||
internal static int Clamp(int value, int low, int high) |
|||
=> value < low ? low : (value > high ? high : value); |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1; |
|||
|
|||
internal enum Av1PartitionType |
|||
{ |
|||
/// <summary>
|
|||
/// Not partitioned any further.
|
|||
/// </summary>
|
|||
None, |
|||
|
|||
/// <summary>
|
|||
/// Horizontally split in 2 partitions.
|
|||
/// </summary>
|
|||
Horizontal, |
|||
|
|||
/// <summary>
|
|||
/// Vertically split in 2 partitions.
|
|||
/// </summary>
|
|||
Vertical, |
|||
|
|||
/// <summary>
|
|||
/// 4 equally sized partitions.
|
|||
/// </summary>
|
|||
Split, |
|||
|
|||
/// <summary>
|
|||
/// Horizontal split and the top partition is split again.
|
|||
/// </summary>
|
|||
HorizontalA, |
|||
|
|||
/// <summary>
|
|||
/// Horizontal split and the bottom partition is split again.
|
|||
/// </summary>
|
|||
HorizontalB, |
|||
|
|||
/// <summary>
|
|||
/// Vertical split and the left partition is split again.
|
|||
/// </summary>
|
|||
VerticalA, |
|||
|
|||
/// <summary>
|
|||
/// Vertical split and the right partitino is split again.
|
|||
/// </summary>
|
|||
VerticalB, |
|||
|
|||
/// <summary>
|
|||
/// 4:1 horizontal partition.
|
|||
/// </summary>
|
|||
Horizontal4, |
|||
|
|||
/// <summary>
|
|||
/// 4:1 vertical partition.
|
|||
/// </summary>
|
|||
Vertical4, |
|||
|
|||
/// <summary>
|
|||
/// Invalid value.
|
|||
/// </summary>
|
|||
Invalid = 255 |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1; |
|||
|
|||
internal enum Av1Plane : int |
|||
{ |
|||
Y = 0, |
|||
U = 1, |
|||
V = 2, |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal enum ObuChromoSamplePosition : byte |
|||
{ |
|||
/// <summary>
|
|||
/// Unknown.
|
|||
/// </summary>
|
|||
Unknown = 0, |
|||
|
|||
/// <summary>
|
|||
/// Horizontally co-located with luma(0, 0) sample, between two vertical samples.
|
|||
/// </summary>
|
|||
Vertical = 1, |
|||
|
|||
/// <summary>
|
|||
/// Co-located with luma(0, 0) sample
|
|||
/// </summary>
|
|||
Colocated = 2, |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuColorConfig |
|||
{ |
|||
internal bool IsColorDescriptionPresent { get; set; } |
|||
|
|||
internal int ChannelCount { get; set; } |
|||
|
|||
internal bool Monochrome { get; set; } |
|||
|
|||
internal ObuColorPrimaries ColorPrimaries { get; set; } |
|||
|
|||
internal ObuTransferCharacteristics TransferCharacteristics { get; set; } |
|||
|
|||
internal ObuMatrixCoefficients MatrixCoefficients { get; set; } |
|||
|
|||
internal bool ColorRange { get; set; } |
|||
|
|||
internal bool SubSamplingX { get; set; } |
|||
|
|||
internal bool SubSamplingY { get; set; } |
|||
|
|||
internal bool HasSeparateUvDelta { get; set; } |
|||
|
|||
internal ObuChromoSamplePosition ChromaSamplePosition { get; set; } |
|||
|
|||
internal int BitDepth { get; set; } |
|||
|
|||
internal bool HasSeparateUvDeltaQ { get; set; } |
|||
|
|||
public Av1ColorFormat GetColorFormat() |
|||
{ |
|||
Av1ColorFormat format = Av1ColorFormat.Yuv400; |
|||
if (this.SubSamplingX && this.SubSamplingY) |
|||
{ |
|||
format = Av1ColorFormat.Yuv420; |
|||
} |
|||
else if (this.SubSamplingX & !this.SubSamplingY) |
|||
{ |
|||
format = Av1ColorFormat.Yuv422; |
|||
} |
|||
else if (!this.SubSamplingX && !this.SubSamplingY) |
|||
{ |
|||
format = Av1ColorFormat.Yuv444; |
|||
} |
|||
|
|||
return format; |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal enum ObuColorPrimaries |
|||
{ |
|||
None = 0, |
|||
Bt709 = 1, |
|||
Unspecified = 2, |
|||
Bt470M = 4, |
|||
Bt470BG = 5, |
|||
Bt601 = 6, |
|||
Smpte240 = 7, |
|||
GenericFilm = 8, |
|||
Bt2020 = 9, |
|||
Xyz = 10, |
|||
Smpte431 = 11, |
|||
Smpte432 = 12, |
|||
Ebu3213 = 22, |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal static class ObuConstants |
|||
{ |
|||
public const ObuSequenceProfile MaxSequenceProfile = ObuSequenceProfile.Professional; |
|||
|
|||
public const int LevelBits = 5; |
|||
|
|||
/// <summary>
|
|||
/// Number of fractional bits for computing position in upscaling.
|
|||
/// </summary>
|
|||
public const int SuperResolutionScaleBits = 14; |
|||
|
|||
public const int ScaleNumerator = -1; |
|||
|
|||
/// <summary>
|
|||
/// Number of reference frames that can be used for inter prediction.
|
|||
/// </summary>
|
|||
public const int ReferencesPerFrame = 7; |
|||
|
|||
/// <summary>
|
|||
/// Maximum area of a tile in units of luma samples.
|
|||
/// </summary>
|
|||
public const int MaxTileArea = 4096 * 2304; |
|||
|
|||
/// <summary>
|
|||
/// Maximum width of a tile in units of luma samples.
|
|||
/// </summary>
|
|||
public const int MaxTileWidth = 4096; |
|||
|
|||
/// <summary>
|
|||
/// Maximum number of tile columns.
|
|||
/// </summary>
|
|||
public const int MaxTileColumnCount = 64; |
|||
|
|||
/// <summary>
|
|||
/// Maximum number of tile rows.
|
|||
/// </summary>
|
|||
public const int MaxTileRowCount = 64; |
|||
|
|||
/// <summary>
|
|||
/// Number of frames that can be stored for future reference.
|
|||
/// </summary>
|
|||
public const int ReferenceFrameCount = 8; |
|||
|
|||
/// <summary>
|
|||
/// Value of 'PrimaryReferenceFrame' indicating that there is no primary reference frame.
|
|||
/// </summary>
|
|||
public const uint PrimaryReferenceFrameNone = 7; |
|||
|
|||
public const int PimaryReferenceBits = -1; |
|||
|
|||
/// <summary>
|
|||
/// Number of segments allowed in segmentation map.
|
|||
/// </summary>
|
|||
public const int MaxSegmentCount = 8; |
|||
|
|||
/// <summary>
|
|||
/// Smallest denominator for upscaling ratio.
|
|||
/// </summary>
|
|||
public const int SuperResolutionScaleDenominatorMinimum = 9; |
|||
|
|||
/// <summary>
|
|||
/// Base 2 logarithm of maximum size of a superblock in luma samples.
|
|||
/// </summary>
|
|||
public const int MaxSuperBlockSizeLog2 = 7; |
|||
|
|||
/// <summary>
|
|||
/// Base 2 logarithm of smallest size of a mode info block.
|
|||
/// </summary>
|
|||
public const int ModeInfoSizeLog2 = 2; |
|||
|
|||
public const int MaxQ = 255; |
|||
|
|||
/// <summary>
|
|||
/// Number of segmentation features.
|
|||
/// </summary>
|
|||
public const int SegmentationLevelMax = 8; |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuConstraintDirectionalEnhancementFilterParameters |
|||
{ |
|||
public int BitCount { get; internal set; } |
|||
|
|||
public int[] YStrength { get; internal set; } = new int[5]; |
|||
|
|||
public int[] UVStrength { get; internal set; } = new int[5]; |
|||
|
|||
public int Damping { get; internal set; } |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuDeltaLoopFilterParameters |
|||
{ |
|||
public bool IsPresent { get; internal set; } |
|||
|
|||
public int Resolution { get; internal set; } |
|||
|
|||
public bool Multi { get; internal set; } |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuDeltaQParameters |
|||
{ |
|||
public bool IsPresent { get; set; } |
|||
|
|||
public int Resolution { get; set; } |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuFilmGrainParameters |
|||
{ |
|||
public bool ApplyGrain { get; set; } |
|||
} |
|||
@ -0,0 +1,89 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using SixLabors.ImageSharp.Formats.Heif.Av1.Transform; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuFrameHeader |
|||
{ |
|||
public bool ForceIntegerMotionVector { get; set; } |
|||
|
|||
public bool AllowIntraBlockCopy { get; set; } |
|||
|
|||
public bool UseReferenceFrameMotionVectors { get; set; } |
|||
|
|||
public bool AllowHighPrecisionMotionVector { get; set; } |
|||
|
|||
public ObuTileInfo TilesInfo { get; set; } = new ObuTileInfo(); |
|||
|
|||
public bool CodedLossless { get; set; } |
|||
|
|||
public bool[] LosslessArray { get; set; } = new bool[ObuConstants.MaxSegmentCount]; |
|||
|
|||
public ObuQuantizationParameters QuantizationParameters { get; set; } = new ObuQuantizationParameters(); |
|||
|
|||
public ObuSegmentationParameters SegmentationParameters { get; set; } = new ObuSegmentationParameters(); |
|||
|
|||
public bool AllLossless { get; set; } |
|||
|
|||
public bool AllowWarpedMotion { get; set; } |
|||
|
|||
public ObuReferenceMode ReferenceMode { get; set; } |
|||
|
|||
public ObuFilmGrainParameters FilmGrainParameters { get; set; } = new ObuFilmGrainParameters(); |
|||
|
|||
public bool ReducedTransformSet { get; set; } |
|||
|
|||
public ObuLoopFilterParameters LoopFilterParameters { get; set; } = new ObuLoopFilterParameters(); |
|||
|
|||
public ObuLoopRestorationParameters[] LoopRestorationParameters { get; set; } = new ObuLoopRestorationParameters[3]; |
|||
|
|||
public ObuConstraintDirectionalEnhancementFilterParameters CdefParameters { get; set; } = new ObuConstraintDirectionalEnhancementFilterParameters(); |
|||
|
|||
public int ModeInfoStride { get; set; } |
|||
|
|||
public bool DisableFrameEndUpdateCdf { get; set; } |
|||
|
|||
public ObuSkipModeParameters SkipModeParameters { get; set; } = new ObuSkipModeParameters(); |
|||
|
|||
public Av1TransformMode TransformMode { get; set; } |
|||
|
|||
public ObuDeltaLoopFilterParameters DeltaLoopFilterParameters { get; set; } = new ObuDeltaLoopFilterParameters(); |
|||
|
|||
public ObuDeltaQParameters DeltaQParameters { get; set; } = new ObuDeltaQParameters(); |
|||
|
|||
internal ObuFrameSize FrameSize { get; set; } = new ObuFrameSize(); |
|||
|
|||
internal int ModeInfoColumnCount { get; set; } |
|||
|
|||
internal int ModeInfoRowCount { get; set; } |
|||
|
|||
internal bool ShowExistingFrame { get; set; } |
|||
|
|||
internal ObuFrameType FrameType { get; set; } |
|||
|
|||
internal bool[] ReferenceValid { get; set; } = new bool[ObuConstants.ReferenceFrameCount]; |
|||
|
|||
internal bool[] ReferenceOrderHint { get; set; } = new bool[ObuConstants.ReferenceFrameCount]; |
|||
|
|||
internal bool ShowFrame { get; set; } |
|||
|
|||
internal bool ShowableFrame { get; set; } |
|||
|
|||
internal bool ErrorResilientMode { get; set; } |
|||
|
|||
internal bool AllowScreenContentTools { get; set; } |
|||
|
|||
internal bool DisableCdfUpdate { get; set; } |
|||
|
|||
internal uint CurrentFrameId { get; set; } |
|||
|
|||
internal uint[] ReferenceFrameIndex { get; set; } = new uint[ObuConstants.ReferenceFrameCount]; |
|||
|
|||
internal uint OrderHint { get; set; } |
|||
|
|||
internal uint PrimaryReferenceFrame { get; set; } = ObuConstants.PrimaryReferenceFrameNone; |
|||
|
|||
internal uint RefreshFrameFlags { get; set; } |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuFrameSize |
|||
{ |
|||
internal int FrameWidth { get; set; } |
|||
|
|||
internal int FrameHeight { get; set; } |
|||
|
|||
internal int SuperResolutionDenominator { get; set; } |
|||
|
|||
internal int SuperResolutionUpscaledWidth { get; set; } |
|||
|
|||
internal int RenderWidth { get; set; } |
|||
|
|||
internal int RenderHeight { get; set; } |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal enum ObuFrameType |
|||
{ |
|||
KeyFrame = 0, |
|||
InterFrame = 1, |
|||
IntraOnlyFrame = 2, |
|||
SwitchFrame = 3, |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuHeader |
|||
{ |
|||
public int Size { get; set; } |
|||
|
|||
public ObuType Type { get; set; } |
|||
|
|||
public bool HasSize { get; set; } |
|||
|
|||
public bool HasExtension { get; set; } |
|||
|
|||
public int TemporalId { get; set; } |
|||
|
|||
public int SpatialId { get; set; } |
|||
|
|||
public int PayloadSize { get; set; } |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuLoopFilterParameters |
|||
{ |
|||
public int[] FilterLevel { get; internal set; } = new int[2]; |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuLoopRestorationParameters |
|||
{ |
|||
public ObuRestorationType FrameRestorationType { get; internal set; } = ObuRestorationType.RestoreNone; |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal enum ObuMatrixCoefficients |
|||
{ |
|||
Identity = 0, |
|||
Bt407 = 1, |
|||
Unspecified = 2, |
|||
Fcc = 4, |
|||
Bt470BG = 5, |
|||
Bt601 = 6, |
|||
Smpte240 = 7, |
|||
SmpteYCgCo = 8, |
|||
Bt2020NonConstantLuminance = 9, |
|||
Bt2020ConstantLuminance = 10, |
|||
Smpte2085 = 11, |
|||
ChromaticityDerivedNonConstantLuminance = 12, |
|||
ChromaticityDerivedConstandLuminance = 13, |
|||
Bt2100ICtCp = 14, |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal enum ObuMetadataType |
|||
{ |
|||
ItutT35, |
|||
HdrCll, |
|||
HdrMdcv, |
|||
Scalability, |
|||
Timecode |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuOperatingPoint |
|||
{ |
|||
internal int OperatorIndex { get; set; } |
|||
|
|||
internal int SequenceLevelIndex { get; set; } |
|||
|
|||
internal int SequenceTier { get; set; } |
|||
|
|||
internal bool IsDecoderModelPresent { get; set; } |
|||
|
|||
internal bool IsInitialDisplayDelayPresent { get; set; } |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuOrderHintInfo |
|||
{ |
|||
public bool EnableOrderHint { get; internal set; } |
|||
|
|||
internal bool EnableJointCompound { get; set; } |
|||
|
|||
internal bool EnableReferenceFrameMotionVectors { get; set; } |
|||
|
|||
internal int OrderHintBits { get; set; } |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuPartitionInfo |
|||
{ |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuQuantizationParameters |
|||
{ |
|||
public int BaseQIndex { get; set; } |
|||
|
|||
public int[] QIndex { get; set; } = new int[ObuConstants.MaxSegmentCount]; |
|||
|
|||
public bool IsUsingQMatrix { get; internal set; } |
|||
|
|||
public int[] DeltaQDc { get; internal set; } = new int[3]; |
|||
|
|||
public int[] DeltaQAc { get; internal set; } = new int[3]; |
|||
|
|||
public int[] QMatrix { get; internal set; } = new int[3]; |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,10 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal enum ObuReferenceMode |
|||
{ |
|||
ReferenceModeSelect, |
|||
SingleReference, |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal enum ObuRestorationType |
|||
{ |
|||
RestoreNone |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal enum ObuSegmentationLevelFeature |
|||
{ |
|||
AlternativeQuantizer, |
|||
AlternativeLoopFilterYVertical, |
|||
AlternativeLoopFilterYHorizontal, |
|||
AlternativeLoopFilterU, |
|||
AlternativeLoopFilterV, |
|||
ReferenceFrame, |
|||
Skip, |
|||
GlobalMotionVector, |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuSegmentationParameters |
|||
{ |
|||
public int[,] QMLevel { get; internal set; } = new int[3, ObuConstants.MaxSegmentCount]; |
|||
|
|||
public bool[,] FeatureEnabled { get; internal set; } = new bool[ObuConstants.MaxSegmentCount, ObuConstants.SegmentationLevelMax]; |
|||
|
|||
public bool SegmentationEnabled { get; internal set; } |
|||
|
|||
public int[,] FeatureData { get; internal set; } = new int[ObuConstants.MaxSegmentCount, ObuConstants.SegmentationLevelMax]; |
|||
} |
|||
@ -0,0 +1,71 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuSequenceHeader |
|||
{ |
|||
internal bool IsStillPicture { get; set; } |
|||
|
|||
internal bool IsReducedStillPictureHeader { get; set; } |
|||
|
|||
internal ObuSequenceProfile SequenceProfile { get; set; } |
|||
|
|||
internal ObuOperatingPoint[] OperatingPoint { get; set; } = new ObuOperatingPoint[1]; |
|||
|
|||
internal bool InitialDisplayDelayPresentFlag { get; set; } |
|||
|
|||
internal bool DecoderModelInfoPresentFlag { get; set; } |
|||
|
|||
internal object? TimingInfo { get; set; } |
|||
|
|||
internal bool IsFrameIdNumbersPresent { get; set; } |
|||
|
|||
internal int FrameWidthBits { get; set; } |
|||
|
|||
internal int FrameHeightBits { get; set; } |
|||
|
|||
internal int MaxFrameWidth { get; set; } |
|||
|
|||
internal int MaxFrameHeight { get; set; } |
|||
|
|||
internal bool Use128x128SuperBlock { get; set; } |
|||
|
|||
internal Av1BlockSize SuperBlockSize { get; set; } |
|||
|
|||
internal int ModeInfoSize { get; set; } |
|||
|
|||
internal int SuperBlockSizeLog2 { get; set; } |
|||
|
|||
internal int FilterIntraLevel { get; set; } |
|||
|
|||
internal bool EnableIntraEdgeFilter { get; set; } |
|||
|
|||
internal ObuOrderHintInfo OrderHintInfo { get; set; } = new ObuOrderHintInfo(); |
|||
|
|||
internal bool EnableInterIntraCompound { get; set; } |
|||
|
|||
internal bool EnableMaskedCompound { get; set; } |
|||
|
|||
internal bool EnableWarpedMotion { get; set; } |
|||
|
|||
internal bool EnableDualFilter { get; set; } |
|||
|
|||
internal int SequenceForceIntegerMotionVector { get; set; } |
|||
|
|||
internal int SequenceForceScreenContentTools { get; set; } |
|||
|
|||
internal bool EnableSuperResolution { get; set; } |
|||
|
|||
internal int CdefLevel { get; set; } |
|||
|
|||
internal bool EnableRestoration { get; set; } |
|||
|
|||
internal ObuColorConfig ColorConfig { get; set; } = new ObuColorConfig(); |
|||
|
|||
internal bool AreFilmGrainingParametersPresent { get; set; } |
|||
|
|||
internal int FrameIdLength { get; set; } |
|||
|
|||
internal int DeltaFrameIdLength { get; set; } |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal enum ObuSequenceProfile : uint |
|||
{ |
|||
Main = 0, |
|||
High = 1, |
|||
Professional = 2, |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuSkipModeParameters |
|||
{ |
|||
public bool SkipModeAllowed { get; set; } |
|||
|
|||
public bool SkipModeFlag { get; internal set; } |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal class ObuTileInfo |
|||
{ |
|||
internal int MaxTileWidthSuperBlock { get; set; } |
|||
|
|||
internal int MaxTileHeightSuperBlock { get; set; } |
|||
|
|||
internal int MinLog2TileColumnCount { get; set; } |
|||
|
|||
internal int MaxLog2TileColumnCount { get; set; } |
|||
|
|||
internal int MaxLog2TileRowCount { get; set; } |
|||
|
|||
internal int MinLog2TileCount { get; set; } |
|||
|
|||
public bool HasUniformTileSpacing { get; set; } |
|||
|
|||
internal int TileColumnCountLog2 { get; set; } |
|||
|
|||
internal int TileColumnCount { get; set; } |
|||
|
|||
internal int[] TileColumnStartModeInfo { get; set; } = new int[ObuConstants.MaxTileRowCount + 1]; |
|||
|
|||
internal int MinLog2TileRowCount { get; set; } |
|||
|
|||
internal int TileRowCountLog2 { get; set; } |
|||
|
|||
internal int[] TileRowStartModeInfo { get; set; } = new int[ObuConstants.MaxTileColumnCount + 1]; |
|||
|
|||
internal int TileRowCount { get; set; } |
|||
|
|||
internal uint ContextUpdateTileId { get; set; } |
|||
|
|||
internal int TileSizeBytes { get; set; } |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal enum ObuTransferCharacteristics |
|||
{ |
|||
Bt709 = 1, |
|||
Unspecified = 2, |
|||
Bt470M = 4, |
|||
Bt470BG = 5, |
|||
Bt601 = 6, |
|||
Smpte240 = 7, |
|||
Linear = 8, |
|||
Log100 = 9, |
|||
Log100Sqrt10 = 10, |
|||
Iec61966 = 11, |
|||
Bt1361 = 12, |
|||
Srgb = 13, |
|||
Bt202010Bit = 14, |
|||
Bt202012Bit = 15, |
|||
Smpte2084 = 16, |
|||
Smpte248 = 17, |
|||
Hlg = 18, |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
internal enum ObuType |
|||
{ |
|||
None = 0, |
|||
SequenceHeader = 1, |
|||
TemporalDelimiter = 2, |
|||
FrameHeader = 3, |
|||
RedundantFrameHeader = 7, |
|||
TileGroup = 4, |
|||
Metadata = 5, |
|||
Frame = 6, |
|||
TileList = 8, |
|||
Padding = 15, |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Prediction; |
|||
|
|||
// Inter modes are not defined here, as they do not apply to pictures.
|
|||
internal enum Av1PredictionMode |
|||
{ |
|||
DC, |
|||
Vertical, |
|||
Horizontal, |
|||
Directional45Degrees, |
|||
Directional135Degrees, |
|||
Directional113Degrees, |
|||
Directional157Degrees, |
|||
Directional203Degrees, |
|||
Directional67Degrees, |
|||
Smooth, |
|||
SmoothVertical, |
|||
SmoothHorizontal, |
|||
Paeth, |
|||
IntraModeStart = DC, |
|||
IntraModeEnd = Paeth + 1, |
|||
IntraModes = Paeth, |
|||
IntraInvalid = 25, |
|||
} |
|||
@ -0,0 +1,73 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
using SixLabors.ImageSharp.Formats.Heif.Av1.Transform; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Quantization; |
|||
|
|||
internal class Av1InverseQuantizer |
|||
{ |
|||
public static int InverseQuantize(ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader, ObuPartitionInfo part, Av1BlockModeInfo mode, int[] level, int[] qCoefficients, Av1TransformMode txType, Av1TransformSize txSize, Av1Plane plane) |
|||
{ |
|||
Av1ScanOrder scanOrder = Av1ScanOrderConstants.GetScanOrder(txSize, txType); |
|||
short[] scanIndices = scanOrder.Scan; |
|||
int maxValue = (1 << (7 + sequenceHeader.ColorConfig.BitDepth)) - 1; |
|||
int minValue = -(1 << (7 + sequenceHeader.ColorConfig.BitDepth)); |
|||
bool usingQuantizationMatrix = frameHeader.QuantizationParameters.IsUsingQMatrix; |
|||
bool lossless = frameHeader.LosslessArray[mode.SegmentId]; |
|||
short[] dequant = []; // Get from DecModCtx
|
|||
int qmLevel = (lossless || !usingQuantizationMatrix) ? Av1ScanOrderConstants.QuantizationMatrixLevelCount - 1 : frameHeader.QuantizationParameters.QMatrix[(int)plane]; |
|||
byte[] iqMatrix = []; // txType.Is2dTransform() ? Get from DecModCtx
|
|||
int shift = txSize.GetScale(); |
|||
|
|||
int coefficientCount = level[0]; |
|||
Span<int> levelSpan = level.AsSpan(1); |
|||
int lev = levelSpan[0]; |
|||
int qCoefficient; |
|||
if (lev != 0) |
|||
{ |
|||
int pos = scanIndices[0]; |
|||
qCoefficient = (int)(((long)Math.Abs(lev) * GetDequantizationValue(dequant[0], pos, iqMatrix)) & 0xffffff); |
|||
qCoefficient >>= shift; |
|||
|
|||
if (lev < 0) |
|||
{ |
|||
qCoefficient = -qCoefficient; |
|||
} |
|||
|
|||
qCoefficients[0] = Av1Math.Clamp(qCoefficient, minValue, maxValue); |
|||
} |
|||
|
|||
for (int i = 1; i < coefficientCount; i++) |
|||
{ |
|||
lev = levelSpan[i]; |
|||
if (lev != 0) |
|||
{ |
|||
int pos = scanIndices[i]; |
|||
qCoefficient = (int)(((long)Math.Abs(lev) * GetDequantizationValue(dequant[1], pos, iqMatrix)) & 0xffffff); |
|||
qCoefficient >>= shift; |
|||
|
|||
if (lev < 0) |
|||
{ |
|||
qCoefficient = -qCoefficient; |
|||
} |
|||
|
|||
qCoefficients[pos] = Av1Math.Clamp(qCoefficient, minValue, maxValue); |
|||
} |
|||
} |
|||
|
|||
return coefficientCount; |
|||
} |
|||
|
|||
private static int GetDequantizationValue(short dequant, int coefficientIndex, byte[] iqMatrix) |
|||
{ |
|||
int dqv = dequant; |
|||
if (iqMatrix != null) |
|||
{ |
|||
dqv = ((iqMatrix[coefficientIndex] * dqv) + (1 << (Av1ScanOrderConstants.QuantizationMatrixLevelBitCount - 1))) >> Av1ScanOrderConstants.QuantizationMatrixLevelBitCount; |
|||
} |
|||
|
|||
return dqv; |
|||
} |
|||
} |
|||
@ -0,0 +1,148 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Quantization; |
|||
|
|||
internal static class Av1InverseTransform |
|||
{ |
|||
public static readonly int[,] AcQLookup = new int[3, 256] |
|||
{ |
|||
{ |
|||
4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, |
|||
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, |
|||
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, |
|||
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, |
|||
83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, |
|||
102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, |
|||
140, 142, 144, 146, 148, 150, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179, 182, 185, 188, |
|||
191, 194, 197, 200, 203, 207, 211, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255, 260, |
|||
265, 270, 275, 280, 285, 290, 295, 300, 305, 311, 317, 323, 329, 335, 341, 347, 353, 359, 366, |
|||
373, 380, 387, 394, 401, 408, 416, 424, 432, 440, 448, 456, 465, 474, 483, 492, 501, 510, 520, |
|||
530, 540, 550, 560, 571, 582, 593, 604, 615, 627, 639, 651, 663, 676, 689, 702, 715, 729, 743, |
|||
757, 771, 786, 801, 816, 832, 848, 864, 881, 898, 915, 933, 951, 969, 988, 1007, 1026, 1046, 1066, |
|||
1087, 1108, 1129, 1151, 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343, 1369, 1396, 1423, 1451, 1479, 1508, 1537, |
|||
1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828, |
|||
}, |
|||
{ |
|||
4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 40, 44, 48, 51, 55, 59, 63, |
|||
67, 71, 75, 79, 83, 88, 92, 96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145, |
|||
149, 154, 158, 163, 168, 172, 177, 181, 186, 190, 195, 199, 204, 208, 213, 217, 222, 226, 231, |
|||
235, 240, 244, 249, 253, 258, 262, 267, 271, 275, 280, 284, 289, 293, 297, 302, 306, 311, 315, |
|||
319, 324, 328, 332, 337, 341, 345, 349, 354, 358, 362, 367, 371, 375, 379, 384, 388, 392, 396, |
|||
401, 409, 417, 425, 433, 441, 449, 458, 466, 474, 482, 490, 498, 506, 514, 523, 531, 539, 547, |
|||
555, 563, 571, 579, 588, 596, 604, 616, 628, 640, 652, 664, 676, 688, 700, 713, 725, 737, 749, |
|||
761, 773, 785, 797, 809, 825, 841, 857, 873, 889, 905, 922, 938, 954, 970, 986, 1002, 1018, 1038, |
|||
1058, 1078, 1098, 1118, 1138, 1158, 1178, 1198, 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386, 1411, 1435, 1463, |
|||
1491, 1519, 1547, 1575, 1603, 1631, 1663, 1695, 1727, 1759, 1791, 1823, 1859, 1895, 1931, 1967, 2003, 2039, 2079, |
|||
2119, 2159, 2199, 2239, 2283, 2327, 2371, 2415, 2459, 2507, 2555, 2603, 2651, 2703, 2755, 2807, 2859, 2915, 2971, |
|||
3027, 3083, 3143, 3203, 3263, 3327, 3391, 3455, 3523, 3591, 3659, 3731, 3803, 3876, 3952, 4028, 4104, 4184, 4264, |
|||
4348, 4432, 4516, 4604, 4692, 4784, 4876, 4972, 5068, 5168, 5268, 5372, 5476, 5584, 5692, 5804, 5916, 6032, 6148, |
|||
6268, 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312, |
|||
}, |
|||
{ |
|||
4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99, 112, 126, 139, 154, 168, |
|||
183, 199, 214, 230, 247, 263, 280, 297, 314, 331, 349, 366, 384, 402, 420, 438, |
|||
456, 475, 493, 511, 530, 548, 567, 586, 604, 623, 642, 660, 679, 698, 716, 735, |
|||
753, 772, 791, 809, 828, 846, 865, 884, 902, 920, 939, 957, 976, 994, 1012, 1030, |
|||
1049, 1067, 1085, 1103, 1121, 1139, 1157, 1175, 1193, 1211, 1229, 1246, 1264, 1282, 1299, 1317, |
|||
1335, 1352, 1370, 1387, 1405, 1422, 1440, 1457, 1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595, |
|||
1627, 1660, 1693, 1725, 1758, 1791, 1824, 1856, 1889, 1922, 1954, 1987, 2020, 2052, 2085, 2118, |
|||
2150, 2183, 2216, 2248, 2281, 2313, 2346, 2378, 2411, 2459, 2508, 2556, 2605, 2653, 2701, 2750, |
|||
2798, 2847, 2895, 2943, 2992, 3040, 3088, 3137, 3185, 3234, 3298, 3362, 3426, 3491, 3555, 3619, |
|||
3684, 3748, 3812, 3876, 3941, 4005, 4069, 4149, 4230, 4310, 4390, 4470, 4550, 4631, 4711, 4791, |
|||
4871, 4967, 5064, 5160, 5256, 5352, 5448, 5544, 5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410, |
|||
6522, 6650, 6778, 6906, 7034, 7162, 7290, 7435, 7579, 7723, 7867, 8011, 8155, 8315, 8475, 8635, |
|||
8795, 8956, 9132, 9308, 9484, 9660, 9836, 10028, 10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661, |
|||
11885, 12109, 12333, 12573, 12813, 13053, 13309, 13565, 13821, 14093, 14365, 14637, 14925, 15213, 15502, 15806, |
|||
16110, 16414, 16734, 17054, 17390, 17726, 18062, 18414, 18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486, |
|||
21902, 22334, 22766, 23214, 23662, 24126, 24590, 25070, 25551, 26047, 26559, 27071, 27599, 28143, 28687, 29247, |
|||
} |
|||
}; |
|||
|
|||
private static readonly int[,] DcQLookup = new int[3, 256] |
|||
{ |
|||
{ |
|||
4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, |
|||
24, 25, 26, 26, 27, 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40, |
|||
41, 42, 43, 43, 44, 45, 46, 47, 48, 48, 49, 50, 51, 52, 53, 53, 54, 55, 56, 57, |
|||
57, 58, 59, 60, 61, 62, 62, 63, 64, 65, 66, 66, 67, 68, 69, 70, 70, 71, 72, 73, |
|||
74, 74, 75, 76, 77, 78, 78, 79, 80, 81, 81, 82, 83, 84, 85, 85, 87, 88, 90, 92, |
|||
93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 108, 110, 111, 113, 114, 116, 117, 118, 120, 121, |
|||
123, 125, 127, 129, 131, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 161, 164, |
|||
166, 169, 172, 174, 177, 180, 182, 185, 187, 190, 192, 195, 199, 202, 205, 208, 211, 214, 217, 220, |
|||
223, 226, 230, 233, 237, 240, 243, 247, 250, 253, 257, 261, 265, 269, 272, 276, 280, 284, 288, 292, |
|||
296, 300, 304, 309, 313, 317, 322, 326, 330, 335, 340, 344, 349, 354, 359, 364, 369, 374, 379, 384, |
|||
389, 395, 400, 406, 411, 417, 423, 429, 435, 441, 447, 454, 461, 467, 475, 482, 489, 497, 505, 513, |
|||
522, 530, 539, 549, 559, 569, 579, 590, 602, 614, 626, 640, 654, 668, 684, 700, 717, 736, 755, 775, |
|||
796, 819, 843, 869, 896, 925, 955, 988, 1022, 1058, 1098, 1139, 1184, 1232, 1282, 1336, |
|||
}, |
|||
{ |
|||
4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34, 37, 40, 43, 47, 50, 53, 57, |
|||
60, 64, 68, 71, 75, 78, 82, 86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128, |
|||
132, 136, 140, 143, 147, 151, 155, 159, 163, 166, 170, 174, 178, 182, 185, 189, 193, 197, 200, |
|||
204, 208, 212, 215, 219, 223, 226, 230, 233, 237, 241, 244, 248, 251, 255, 259, 262, 266, 269, |
|||
273, 276, 280, 283, 287, 290, 293, 297, 300, 304, 307, 310, 314, 317, 321, 324, 327, 331, 334, |
|||
337, 343, 350, 356, 362, 369, 375, 381, 387, 394, 400, 406, 412, 418, 424, 430, 436, 442, 448, |
|||
454, 460, 466, 472, 478, 484, 490, 499, 507, 516, 525, 533, 542, 550, 559, 567, 576, 584, 592, |
|||
601, 609, 617, 625, 634, 644, 655, 666, 676, 687, 698, 708, 718, 729, 739, 749, 759, 770, 782, |
|||
795, 807, 819, 831, 844, 856, 868, 880, 891, 906, 920, 933, 947, 961, 975, 988, 1001, 1015, 1030, |
|||
1045, 1061, 1076, 1090, 1105, 1120, 1137, 1153, 1170, 1186, 1202, 1218, 1236, 1253, 1271, 1288, 1306, 1323, 1342, |
|||
1361, 1379, 1398, 1416, 1436, 1456, 1476, 1496, 1516, 1537, 1559, 1580, 1601, 1624, 1647, 1670, 1692, 1717, 1741, |
|||
1766, 1791, 1817, 1844, 1871, 1900, 1929, 1958, 1990, 2021, 2054, 2088, 2123, 2159, 2197, 2236, 2276, 2319, 2363, |
|||
2410, 2458, 2508, 2561, 2616, 2675, 2737, 2802, 2871, 2944, 3020, 3102, 3188, 3280, 3375, 3478, 3586, 3702, 3823, |
|||
3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347, |
|||
}, |
|||
{ |
|||
4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91, 103, 115, 127, 140, 153, |
|||
166, 180, 194, 208, 222, 237, 251, 266, 281, 296, 312, 327, 343, 358, 374, 390, |
|||
405, 421, 437, 453, 469, 484, 500, 516, 532, 548, 564, 580, 596, 611, 627, 643, |
|||
659, 674, 690, 706, 721, 737, 752, 768, 783, 798, 814, 829, 844, 859, 874, 889, |
|||
904, 919, 934, 949, 964, 978, 993, 1008, 1022, 1037, 1051, 1065, 1080, 1094, 1108, 1122, |
|||
1136, 1151, 1165, 1179, 1192, 1206, 1220, 1234, 1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342, |
|||
1368, 1393, 1419, 1444, 1469, 1494, 1519, 1544, 1569, 1594, 1618, 1643, 1668, 1692, 1717, 1741, |
|||
1765, 1789, 1814, 1838, 1862, 1885, 1909, 1933, 1957, 1992, 2027, 2061, 2096, 2130, 2165, 2199, |
|||
2233, 2267, 2300, 2334, 2367, 2400, 2434, 2467, 2499, 2532, 2575, 2618, 2661, 2704, 2746, 2788, |
|||
2830, 2872, 2913, 2954, 2995, 3036, 3076, 3127, 3177, 3226, 3275, 3324, 3373, 3421, 3469, 3517, |
|||
3565, 3621, 3677, 3733, 3788, 3843, 3897, 3951, 4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420, |
|||
4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942, 5013, 5083, 5153, 5222, 5291, 5367, 5442, 5517, |
|||
5591, 5665, 5745, 5825, 5905, 5984, 6063, 6149, 6234, 6319, 6404, 6495, 6587, 6678, 6769, 6867, |
|||
6966, 7064, 7163, 7269, 7376, 7483, 7599, 7715, 7832, 7958, 8085, 8214, 8352, 8492, 8635, 8788, |
|||
8945, 9104, 9275, 9450, 9639, 9832, 10031, 10245, 10465, 10702, 10946, 11210, 11482, 11776, 12081, 12409, |
|||
12750, 13118, 13501, 13913, 14343, 14807, 15290, 15812, 16356, 16943, 17575, 18237, 18949, 19718, 20521, 21387, |
|||
} |
|||
}; |
|||
|
|||
public static int GetDcQuantization(int qIndex, int delta, Av1BitDepth bitDepth) |
|||
=> DcQLookup[(int)bitDepth, Av1Math.Clip3(0, 255, qIndex + delta)]; |
|||
|
|||
public static int GetAcQuantization(int qIndex, int delta, Av1BitDepth bitDepth) |
|||
=> AcQLookup[(int)bitDepth, Av1Math.Clip3(0, 255, qIndex + delta)]; |
|||
|
|||
public static int GetQzbinFactor(int q, Av1BitDepth bitDepth) |
|||
{ |
|||
int quant = GetDcQuantization(q, 0, bitDepth); |
|||
|
|||
// Bit hack to get to:
|
|||
// EightBit => 148
|
|||
// TenBit => 592
|
|||
// TwelveBit => 2368
|
|||
int shift = (int)bitDepth << 1; |
|||
int threshold = (1 << shift) * 148; |
|||
return q == 0 ? 64 : (quant < threshold ? 84 : 80); |
|||
} |
|||
|
|||
public static void InvertQuantization(out int quantization, out int shift, int d) |
|||
{ |
|||
uint t; |
|||
int l, m; |
|||
t = (uint)d; |
|||
for (l = 0; t > 1; l++) |
|||
{ |
|||
t >>= 1; |
|||
} |
|||
|
|||
m = 1 + ((1 << (16 + l)) / d); |
|||
quantization = m - (1 << 16); |
|||
shift = 1 << (16 - l); |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform; |
|||
|
|||
internal readonly struct Av1ScanOrder |
|||
{ |
|||
public Av1ScanOrder(short[]? scan) |
|||
{ |
|||
this.Scan = scan ?? []; |
|||
this.IScan = []; |
|||
this.Neighbors = []; |
|||
} |
|||
|
|||
public Av1ScanOrder(short[] scan, short[] iscan, short[] neighbors) |
|||
{ |
|||
this.Scan = scan; |
|||
this.IScan = iscan; |
|||
this.Neighbors = neighbors; |
|||
} |
|||
|
|||
public short[] Scan { get; } |
|||
|
|||
public short[] IScan { get; } |
|||
|
|||
public short[] Neighbors { get; } |
|||
} |
|||
@ -0,0 +1,75 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using SixLabors.ImageSharp.Formats.Heif.Av1.Quantization; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform; |
|||
|
|||
internal static class Av1ScanOrderConstants |
|||
{ |
|||
public const int QuantizationMatrixLevelBitCount = 4; |
|||
public const int QuantizationMatrixLevelCount = 1 << QuantizationMatrixLevelBitCount; |
|||
|
|||
private static readonly Av1ScanOrder[][] ScanOrders = |
|||
[ |
|||
|
|||
// Transform size 4x4
|
|||
[ |
|||
new Av1ScanOrder(DefaultScan4x4), |
|||
new Av1ScanOrder(DefaultScan4x4), |
|||
new Av1ScanOrder(DefaultScan4x4), |
|||
new Av1ScanOrder(DefaultScan4x4), |
|||
new Av1ScanOrder(DefaultScan4x4), |
|||
new Av1ScanOrder(DefaultScan4x4), |
|||
new Av1ScanOrder(DefaultScan4x4), |
|||
new Av1ScanOrder(DefaultScan4x4), |
|||
new Av1ScanOrder(DefaultScan4x4), |
|||
new Av1ScanOrder(DefaultScan4x4), |
|||
new Av1ScanOrder(MatrixRowScan4x4), |
|||
new Av1ScanOrder(MatrixColumnScan4x4), |
|||
new Av1ScanOrder(MatrixRowScan4x4), |
|||
new Av1ScanOrder(MatrixColumnScan4x4), |
|||
new Av1ScanOrder(MatrixRowScan4x4), |
|||
new Av1ScanOrder(MatrixColumnScan4x4), |
|||
], |
|||
|
|||
// Transform size 8x8
|
|||
[ |
|||
new Av1ScanOrder(DefaultScan8x8), |
|||
new Av1ScanOrder(DefaultScan8x8), |
|||
new Av1ScanOrder(DefaultScan8x8), |
|||
new Av1ScanOrder(DefaultScan8x8), |
|||
new Av1ScanOrder(DefaultScan8x8), |
|||
new Av1ScanOrder(DefaultScan8x8), |
|||
new Av1ScanOrder(DefaultScan8x8), |
|||
new Av1ScanOrder(DefaultScan8x8), |
|||
new Av1ScanOrder(DefaultScan8x8), |
|||
new Av1ScanOrder(DefaultScan8x8), |
|||
new Av1ScanOrder(MatrixRowScan8x8), |
|||
new Av1ScanOrder(MatrixColumnScan8x8), |
|||
new Av1ScanOrder(MatrixRowScan8x8), |
|||
new Av1ScanOrder(MatrixColumnScan8x8), |
|||
new Av1ScanOrder(MatrixRowScan8x8), |
|||
new Av1ScanOrder(MatrixColumnScan8x8), |
|||
], |
|||
]; |
|||
|
|||
private static readonly short[] DefaultScan4x4 = [0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15]; |
|||
private static readonly short[] MatrixColumnScan4x4 = [0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15]; |
|||
private static readonly short[] MatrixRowScan4x4 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; |
|||
|
|||
private static readonly short[] DefaultScan8x8 = [0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, |
|||
41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, |
|||
30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63]; |
|||
|
|||
private static readonly short[] MatrixColumnScan8x8 = [0, 8, 16, 24, 32, 40, 48, 56, 1, 9, 17, 25, 33, 41, 49, 57, 2, 10, 18, 26, 34, 42, |
|||
50, 58, 3, 11, 19, 27, 35, 43, 51, 59, 4, 12, 20, 28, 36, 44, 52, 60, 5, 13, 21, 29, |
|||
37, 45, 53, 61, 6, 14, 22, 30, 38, 46, 54, 62, 7, 15, 23, 31, 39, 47, 55, 63]; |
|||
|
|||
private static readonly short[] MatrixRowScan8x8 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, |
|||
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, |
|||
44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]; |
|||
|
|||
public static Av1ScanOrder GetScanOrder(Av1TransformSize txSize, Av1TransformMode txMode) |
|||
=> ScanOrders[(int)txSize][(int)txMode]; |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform; |
|||
|
|||
internal enum Av1TransformMode : byte |
|||
{ |
|||
Only4x4 = 0, |
|||
Largest = 1, |
|||
Select = 2, |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Quantization; |
|||
|
|||
internal enum Av1TransformSize : byte |
|||
{ |
|||
Size4x4, |
|||
Size8x8, |
|||
Size16x16, |
|||
Size32x32, |
|||
Size64x64, |
|||
Size4x8, |
|||
Size8x4, |
|||
Size8x16, |
|||
Size16x8, |
|||
Size16x32, |
|||
Size32x16, |
|||
Size32x64, |
|||
Size64x32, |
|||
Size4x16, |
|||
Size16x4, |
|||
Size8x32, |
|||
Size32x8, |
|||
Size16x64, |
|||
Size64x16, |
|||
AllSizes, |
|||
SquareSizes = Size4x8, |
|||
Invalid = 255, |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Quantization; |
|||
|
|||
internal static class Av1TransformSizeExtensions |
|||
{ |
|||
private static readonly int[] Size2d = [ |
|||
16, 64, 256, 1024, 4096, 32, 32, 128, 128, 512, 512, 2048, 2048, 64, 64, 256, 256, 1024, 1024]; |
|||
|
|||
public static int GetScale(this Av1TransformSize size) |
|||
{ |
|||
int pels = Size2d[(int)size]; |
|||
return (pels > 1024) ? 2 : (pels > 256) ? 1 : 0; |
|||
} |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Heif.Av1.Transform; |
|||
|
|||
internal enum Av1TransformType : byte |
|||
{ |
|||
/// <summary>
|
|||
/// DCT in both horizontal and vertical.
|
|||
/// </summary>
|
|||
DctDct, |
|||
|
|||
/// <summary>
|
|||
/// ADST in vertical, DCT in horizontal.
|
|||
/// </summary>
|
|||
AdstDct, |
|||
|
|||
/// <summary>
|
|||
/// DCT in vertical, ADST in horizontal.
|
|||
/// </summary>
|
|||
DctAdst, |
|||
|
|||
/// <summary>
|
|||
/// ADST in both directions.
|
|||
/// </summary>
|
|||
AdstAdst, |
|||
FlipAdstDct, |
|||
DctFlipAdst, |
|||
FlipAdstFlipAdst, |
|||
AdstFlipAdst, |
|||
FlipAdstAdst, |
|||
Identity, |
|||
VerticalDct, |
|||
HorizontalDct, |
|||
VerticalAdst, |
|||
HorizontalAdst, |
|||
VerticalFlipAdst, |
|||
HorizontalFlipAdst, |
|||
|
|||
/// <summary>
|
|||
/// Number of Transform types.
|
|||
/// </summary>
|
|||
TransformTypes, |
|||
|
|||
/// <summary>
|
|||
/// Invalid value.
|
|||
/// </summary>
|
|||
Invalid, |
|||
} |
|||
@ -0,0 +1,86 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers.Binary; |
|||
using SixLabors.ImageSharp.Formats.Heif.Av1; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; |
|||
|
|||
[Trait("Format", "Avif")] |
|||
public class Av1BitsStreamTests |
|||
{ |
|||
[Theory] |
|||
[InlineData(42, new bool[] { false, false, true, false, true, false, true, false })] |
|||
[InlineData(52, new bool[] { false, false, true, true, false, true, false, false })] |
|||
public void ReadAsBoolean(byte value, bool[] bits) |
|||
{ |
|||
int bitCount = bits.Length; |
|||
byte[] buffer = new byte[8]; |
|||
buffer[0] = value; |
|||
Av1BitStreamReader reader = new(buffer); |
|||
bool[] actual = new bool[bitCount]; |
|||
for (int i = 0; i < bitCount; i++) |
|||
{ |
|||
actual[i] = reader.ReadBoolean(); |
|||
} |
|||
|
|||
Assert.Equal(bits, actual); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(6, 4)] |
|||
[InlineData(42, 8)] |
|||
[InlineData(52, 8)] |
|||
[InlineData(4050, 16)] |
|||
public void ReadAsLiteral(uint expected, int bitCount) |
|||
{ |
|||
byte[] buffer = new byte[8]; |
|||
BinaryPrimitives.WriteUInt32BigEndian(buffer, expected << (32 - bitCount)); |
|||
Av1BitStreamReader reader = new(buffer); |
|||
uint actual = reader.ReadLiteral(bitCount); |
|||
Assert.Equal(expected, actual); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(new bool[] { false, false, true, false, true, false, true, false })] |
|||
[InlineData(new bool[] { false, true, false, true })] |
|||
public void WriteAsBoolean(bool[] booleans) |
|||
{ |
|||
using MemoryStream stream = new(8); |
|||
Av1BitStreamWriter writer = new(stream); |
|||
for (int i = 0; i < booleans.Length; i++) |
|||
{ |
|||
writer.WriteBoolean(booleans[i]); |
|||
} |
|||
|
|||
writer.Flush(); |
|||
|
|||
// Read the written value back.
|
|||
Av1BitStreamReader reader = new(stream.GetBuffer()); |
|||
bool[] actual = new bool[booleans.Length]; |
|||
for (int i = 0; i < booleans.Length; i++) |
|||
{ |
|||
actual[i] = reader.ReadBoolean(); |
|||
} |
|||
|
|||
Assert.Equal(booleans, actual); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(6, 4)] |
|||
[InlineData(42, 8)] |
|||
[InlineData(52, 8)] |
|||
[InlineData(4050, 16)] |
|||
public void WriteAsLiteral(uint value, int bitCount) |
|||
{ |
|||
using MemoryStream stream = new(8); |
|||
Av1BitStreamWriter writer = new(stream); |
|||
writer.WriteLiteral(value, bitCount); |
|||
writer.Flush(); |
|||
|
|||
// Read the written value back.
|
|||
Av1BitStreamReader reader = new(stream.GetBuffer()); |
|||
uint actual = reader.ReadLiteral(bitCount); |
|||
Assert.Equal(value, actual); |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using SixLabors.ImageSharp.Formats.Heif.Av1; |
|||
using SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1; |
|||
|
|||
[Trait("Format", "Avif")] |
|||
public class ObuFrameHeaderTests |
|||
{ |
|||
[Theory] |
|||
// [InlineData(TestImages.Heif.IrvineAvif, 0x0102, 0x000D, false)]
|
|||
// [InlineData(TestImages.Heif.IrvineAvif, 0x0198, 0x6BD1, false)]
|
|||
[InlineData(TestImages.Heif.XnConvert, 0x010E, 0x03CC, false)] |
|||
public void ReadFrameHeader(string filename, int fileOffset, int blockSize, bool isAnnexB) |
|||
{ |
|||
// Assign
|
|||
string filePath = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, filename); |
|||
byte[] content = File.ReadAllBytes(filePath); |
|||
Span<byte> span = content.AsSpan(fileOffset, blockSize); |
|||
Av1Decoder decoder = new(); |
|||
|
|||
// Act
|
|||
decoder.Decode(span); |
|||
|
|||
// Assert
|
|||
Assert.True(decoder.SequenceHeaderDone); |
|||
Assert.False(decoder.SeenFrameHeader); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:73c0521c669759df918cd59865537cd9cef3b7502ce3da825d8d24d9997e0e0d |
|||
size 1242 |
|||
Loading…
Reference in new issue