Browse Source

Few Obu unit tests taken over from libgav1

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
6e10cc9960
  1. 6
      src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs
  2. 198
      tests/ImageSharp.Tests/Formats/Heif/Av1/ObuFrameHeaderTests.cs
  3. 70
      tests/ImageSharp.Tests/Formats/Heif/Av1/ObuPrettyPrint.cs

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

@ -169,7 +169,7 @@ internal class ObuReader
{
header.Size++;
header.TemporalId = (int)reader.ReadLiteral(3);
header.SpatialId = (int)reader.ReadLiteral(3);
header.SpatialId = (int)reader.ReadLiteral(2);
if (reader.ReadLiteral(3) != 0u)
{
throw new ImageFormatException("Reserved bits in header extension should be unset.");
@ -708,8 +708,8 @@ internal class ObuReader
tileInfo.MaxTileWidthSuperblock = Av1Constants.MaxTileWidth >> superblockSizeLog2;
tileInfo.MaxTileHeightSuperblock = (Av1Constants.MaxTileArea / Av1Constants.MaxTileWidth) >> superblockSizeLog2;
tileInfo.MinLog2TileColumnCount = TileLog2(tileInfo.MaxTileWidthSuperblock, superblockColumnCount);
tileInfo.MaxLog2TileColumnCount = TileLog2(1, Math.Min(superblockColumnCount, Av1Constants.MaxTileColumnCount));
tileInfo.MaxLog2TileRowCount = TileLog2(1, Math.Min(superblockRowCount, Av1Constants.MaxTileRowCount));
tileInfo.MaxLog2TileColumnCount = (int)Av1Math.CeilLog2((uint)Math.Min(superblockColumnCount, Av1Constants.MaxTileColumnCount));
tileInfo.MaxLog2TileRowCount = (int)Av1Math.CeilLog2((uint)Math.Min(superblockRowCount, Av1Constants.MaxTileRowCount));
tileInfo.MinLog2TileCount = Math.Max(tileInfo.MinLog2TileColumnCount, TileLog2(maxTileAreaOfSuperBlock, superblockColumnCount * superblockRowCount));
tileInfo.HasUniformTileSpacing = reader.ReadBoolean();
if (tileInfo.HasUniformTileSpacing)

198
tests/ImageSharp.Tests/Formats/Heif/Av1/ObuFrameHeaderTests.cs

@ -12,6 +12,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1;
[Trait("Format", "Avif")]
public class ObuFrameHeaderTests
{
private static readonly byte[] DefaultSequenceHeaderBitStream =
[0x0a, 0x0b, 0x00, 0x00, 0x00, 0x04, 0x3e, 0xa7, 0xbd, 0xf7, 0xf9, 0x80, 0x40];
[Theory]
// [InlineData(TestImages.Heif.IrvineAvif, 0x0102, 0x000D)]
// [InlineData(TestImages.Heif.IrvineAvif, 0x0198, 0x6BD1)]
@ -96,68 +99,161 @@ public class ObuFrameHeaderTests
obuReader2.Read(ref reader2, encodedBuffer.Length, tileDecoder2);
// Assert
Assert.Equal(PrettyPrintProperties(obuReader1.SequenceHeader.ColorConfig), PrettyPrintProperties(obuReader2.SequenceHeader.ColorConfig));
Assert.Equal(PrettyPrintProperties(obuReader1.SequenceHeader), PrettyPrintProperties(obuReader2.SequenceHeader));
Assert.Equal(PrettyPrintProperties(obuReader1.FrameHeader), PrettyPrintProperties(obuReader2.FrameHeader));
Assert.Equal(PrettyPrintProperties(obuReader1.FrameHeader.TilesInfo), PrettyPrintProperties(obuReader2.FrameHeader.TilesInfo));
Assert.Equal(ObuPrettyPrint.PrettyPrintProperties(obuReader1.SequenceHeader.ColorConfig), ObuPrettyPrint.PrettyPrintProperties(obuReader2.SequenceHeader.ColorConfig));
Assert.Equal(ObuPrettyPrint.PrettyPrintProperties(obuReader1.SequenceHeader), ObuPrettyPrint.PrettyPrintProperties(obuReader2.SequenceHeader));
Assert.Equal(ObuPrettyPrint.PrettyPrintProperties(obuReader1.FrameHeader), ObuPrettyPrint.PrettyPrintProperties(obuReader2.FrameHeader));
Assert.Equal(ObuPrettyPrint.PrettyPrintProperties(obuReader1.FrameHeader.TilesInfo), ObuPrettyPrint.PrettyPrintProperties(obuReader2.FrameHeader.TilesInfo));
}
private static readonly char[] spaces = " ".ToCharArray();
[Fact]
public void DefaultTemporalDelimiter()
{
// Arrange
byte[] bitStream = [0x12, 0x00];
Av1BitStreamReader reader = new(bitStream);
ObuReader obuReader = new();
IAv1TileDecoder tileDecoder = new Av1TileDecoderStub();
// Act
obuReader.Read(ref reader, bitStream.Length, tileDecoder);
private static string PrettyPrintProperties(object obj, int indent = 0)
// Assert
Assert.Null(obuReader.SequenceHeader);
Assert.Null(obuReader.FrameHeader);
}
[Fact]
public void DefaultTemporalDelimiterWithExtension()
{
StringBuilder builder = new();
builder.Append(obj.GetType().Name);
builder.AppendLine("{");
indent += 2;
MemberInfo[] properties = obj.GetType().FindMembers(MemberTypes.Property, BindingFlags.Instance | BindingFlags.Public, null, null);
foreach (MemberInfo member in properties)
{
builder.Append(spaces, 0, indent);
if (member is PropertyInfo property)
{
builder.Append(property.Name);
builder.Append(" = ");
object value = property.GetValue(obj) ?? "NULL";
PrettyPrintValue(builder, value, indent);
}
}
// Bits Syntax element Value
// 1 obu_forbidden_bit 0
// 4 obu_type 2 (OBU_TEMPORAL_DELIMITER)
// 1 obu_extension_flag 1
// 1 obu_has_size_field 1
// 1 obu_reserved_1bit 0
// 3 temporal_id 6
// 2 spatial_id 2
// 3 extension_header_reserved_3bits 0
// 8 obu_size 0
// Arrange
byte[] bitStream = [0x16, 0xd0, 0x00];
Av1BitStreamReader reader = new(bitStream);
ObuReader obuReader = new();
IAv1TileDecoder tileDecoder = new Av1TileDecoderStub();
indent -= 2;
builder.Append(spaces, 0, indent);
builder.AppendLine("}");
return builder.ToString();
// Act
obuReader.Read(ref reader, bitStream.Length, tileDecoder);
// Assert
Assert.Null(obuReader.SequenceHeader);
Assert.Null(obuReader.FrameHeader);
}
private static void PrettyPrintValue(StringBuilder builder, object value, int indent)
[Fact]
public void DefaultHeaderWithoutSizeField()
{
if (value.GetType() == typeof(string))
{
builder.AppendLine(value.ToString());
}
else if (value.GetType().IsArray)
// Arrange
byte[] bitStream = [0x10];
Av1BitStreamReader reader = new(bitStream);
ObuReader obuReader = new();
IAv1TileDecoder tileDecoder = new Av1TileDecoderStub();
// Act
obuReader.Read(ref reader, bitStream.Length, tileDecoder);
// Assert
Assert.Null(obuReader.SequenceHeader);
Assert.Null(obuReader.FrameHeader);
}
[Fact]
public void DefaultSequenceHeader()
{
// Offset Bits Syntax element Value
// 0 3 seq_profile 0
// 3 1 still_picture 0
// 4 1 reduced_still_picture_header 0
// 5 1 timing_info_present_flag 0
// 6 1 initial_display_delay_present_flag 0
// 7 5 operating_points_cnt_minus_1 0
// 12 12 operating_point_idc[ 0 ] 0
// 24 5 seq_level_idx[ 0 ] 0
// 29 4 frame_width_bits_minus_1 8
// 33 4 frame_height_bits_minus_1 7
// 37 9 max_frame_width_minus_1 425
// 46 8 max_frame_height_minus_1 239
// 54 1 frame_id_numbers_present_flag 0
// 55 1 use_128x128_superblock 1
// 56 1 enable_filter_intra 1
// 57 1 enable_intra_edge_filter 1
// 58 1 enable_interintra_compound 1
// 59 1 enable_masked_compound 1
// 60 1 enable_warped_motion 0
// 61 1 enable_dual_filter 1
// 62 1 enable_order_hint 1
// 63 1 enable_jnt_comp 1
// 64 1 enable_ref_frame_mvs 1
// 65 1 seq_choose_screen_content_tools 1
// 66 1 seq_choose_integer_mv 1
// 67 3 order_hint_bits_minus_1 6
// 70 1 enable_superres 0
// 71 1 enable_cdef 1
// 72 1 enable_restoration 1
// ...
// Arrange
byte[] bitStream = DefaultSequenceHeaderBitStream;
Av1BitStreamReader reader = new(bitStream);
ObuReader obuReader = new();
IAv1TileDecoder tileDecoder = new Av1TileDecoderStub();
ObuSequenceHeader expected = new()
{
builder.AppendLine("[");
indent += 2;
builder.Append(spaces, 0, indent);
Type elementType = value.GetType().GetElementType();
IList list = value as IList;
foreach (object item in list)
SequenceProfile = 0,
IsStillPicture = false,
IsReducedStillPictureHeader = false,
TimingInfoPresentFlag = false,
InitialDisplayDelayPresentFlag = false,
FrameWidthBits = 8 + 1,
FrameHeightBits = 7 + 1,
MaxFrameWidth = 425 + 1,
MaxFrameHeight = 239 + 1,
IsFrameIdNumbersPresent = false,
Use128x128Superblock = true,
EnableFilterIntra = true,
EnableIntraEdgeFilter = true,
EnableInterIntraCompound = true,
EnableMaskedCompound = true,
EnableWarpedMotion = false,
EnableDualFilter = true,
EnableOrderHint = true,
OperatingPoint = [new()],
// EnableJountCompound = true,
// EnableReferenceFrameMotionVectors = true,
ForceScreenContentTools = 2,
ForceIntegerMotionVector = 2,
EnableSuperResolution = false,
EnableCdef = true,
EnableRestoration = true,
ColorConfig = new()
{
PrettyPrintValue(builder, item, indent);
IsMonochrome = false,
ColorPrimaries = ObuColorPrimaries.Unspecified,
TransferCharacteristics = ObuTransferCharacteristics.Unspecified,
MatrixCoefficients = ObuMatrixCoefficients.Unspecified,
SubSamplingX = true,
SubSamplingY = true,
BitDepth = 8,
}
};
indent -= 2;
builder.Append(spaces, 0, indent);
builder.AppendLine("]");
}
else if (value.GetType().IsClass)
{
builder.AppendLine(PrettyPrintProperties(value, indent));
}
else
{
builder.AppendLine(value.ToString());
}
// Act
obuReader.Read(ref reader, bitStream.Length, tileDecoder);
// Assert
Assert.NotNull(obuReader.SequenceHeader);
Assert.Null(obuReader.FrameHeader);
Assert.Equal(ObuPrettyPrint.PrettyPrintProperties(expected), ObuPrettyPrint.PrettyPrintProperties(obuReader.SequenceHeader));
}
}

70
tests/ImageSharp.Tests/Formats/Heif/Av1/ObuPrettyPrint.cs

@ -0,0 +1,70 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Collections;
using System.Reflection;
using System.Text;
namespace SixLabors.ImageSharp.Tests.Formats.Heif.Av1;
internal class ObuPrettyPrint
{
private static readonly char[] spaces = " ".ToCharArray();
public static string PrettyPrintProperties(object obj, int indent = 0)
{
StringBuilder builder = new();
builder.Append(obj.GetType().Name);
builder.AppendLine("{");
indent += 2;
MemberInfo[] properties = obj.GetType().FindMembers(MemberTypes.Property, BindingFlags.Instance | BindingFlags.Public, null, null);
foreach (MemberInfo member in properties)
{
builder.Append(spaces, 0, indent);
if (member is PropertyInfo property)
{
builder.Append(property.Name);
builder.Append(" = ");
object value = property.GetValue(obj) ?? "NULL";
PrettyPrintValue(builder, value, indent);
}
}
indent -= 2;
builder.Append(spaces, 0, indent);
builder.AppendLine("}");
return builder.ToString();
}
private static void PrettyPrintValue(StringBuilder builder, object value, int indent)
{
if (value.GetType() == typeof(string))
{
builder.AppendLine(value.ToString());
}
else if (value.GetType().IsArray)
{
builder.AppendLine("[");
indent += 2;
builder.Append(spaces, 0, indent);
Type elementType = value.GetType().GetElementType();
IList list = value as IList;
foreach (object item in list)
{
PrettyPrintValue(builder, item, indent);
}
indent -= 2;
builder.Append(spaces, 0, indent);
builder.AppendLine("]");
}
else if (value.GetType().IsClass)
{
builder.AppendLine(PrettyPrintProperties(value, indent));
}
else
{
builder.AppendLine(value.ToString());
}
}
}
Loading…
Cancel
Save