diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuFrameHeader.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuFrameHeader.cs
index ffe384e688..b145a7a846 100644
--- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuFrameHeader.cs
+++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuFrameHeader.cs
@@ -71,6 +71,8 @@ internal class ObuFrameHeader
internal bool ShowableFrame { get; set; }
+ internal uint FrameToShowMapIdx { get; set; }
+
internal bool ErrorResilientMode { get; set; }
internal bool AllowScreenContentTools { get; set; }
diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuOperatingPoint.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuOperatingPoint.cs
index be3ad61f53..a398124e39 100644
--- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuOperatingPoint.cs
+++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuOperatingPoint.cs
@@ -11,7 +11,7 @@ internal class ObuOperatingPoint
internal int SequenceTier { get; set; }
- internal bool IsDecoderModelPresent { get; set; }
+ internal bool IsDecoderModelInfoPresent { get; set; }
internal bool IsInitialDisplayDelayPresent { get; set; }
diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs
index 2c2075f5df..9c2d791060 100644
--- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs
+++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs
@@ -281,7 +281,7 @@ internal class ObuReader
}
operatingPoint.SequenceTier = 0;
- operatingPoint.IsDecoderModelPresent = false;
+ operatingPoint.IsDecoderModelInfoPresent = false;
operatingPoint.IsInitialDisplayDelayPresent = false;
}
else
@@ -289,11 +289,16 @@ internal class ObuReader
sequenceHeader.TimingInfoPresentFlag = reader.ReadBoolean();
if (sequenceHeader.TimingInfoPresentFlag)
{
+ ReadTimingInfo(ref reader, sequenceHeader);
sequenceHeader.DecoderModelInfoPresentFlag = reader.ReadBoolean();
if (sequenceHeader.DecoderModelInfoPresentFlag)
{
ReadDecoderModelInfo(ref reader, sequenceHeader);
}
+ else
+ {
+ sequenceHeader.DecoderModelInfoPresentFlag = false;
+ }
}
sequenceHeader.InitialDisplayDelayPresentFlag = reader.ReadBoolean();
@@ -315,15 +320,15 @@ internal class ObuReader
if (sequenceHeader.DecoderModelInfoPresentFlag)
{
- sequenceHeader.OperatingPoint[i].IsDecoderModelPresent = reader.ReadBoolean();
- if (sequenceHeader.OperatingPoint[i].IsDecoderModelPresent)
+ sequenceHeader.OperatingPoint[i].IsDecoderModelInfoPresent = reader.ReadBoolean();
+ if (sequenceHeader.OperatingPoint[i].IsDecoderModelInfoPresent)
{
// TODO: operating_parameters_info( i )
}
}
else
{
- sequenceHeader.OperatingPoint[i].IsDecoderModelPresent = false;
+ sequenceHeader.OperatingPoint[i].IsDecoderModelInfoPresent = false;
}
if (sequenceHeader.InitialDisplayDelayPresentFlag)
@@ -543,6 +548,24 @@ internal class ObuReader
FramePresentationTimeLength = reader.ReadLiteral(5) + 1
};
+ ///
+ /// 5.5.3. Timing info syntax.
+ ///
+ private static void ReadTimingInfo(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader)
+ {
+ sequenceHeader.TimingInfo = new ObuTimingInfo
+ {
+ NumUnitsInDisplayTick = reader.ReadLiteral(32),
+ TimeScale = reader.ReadLiteral(32),
+ EqualPictureInterval = reader.ReadBoolean()
+ };
+
+ if (sequenceHeader.TimingInfo.EqualPictureInterval)
+ {
+ sequenceHeader.TimingInfo.NumTicksPerPicture = reader.ReadUnsignedVariableLength() + 1;
+ }
+ }
+
private static void ReadBitDepth(ref Av1BitStreamReader reader, ObuColorConfig colorConfig, ObuSequenceHeader sequenceHeader)
{
bool hasHighBitDepth = reader.ReadBoolean();
@@ -863,6 +886,16 @@ internal class ObuReader
frameInfo.ShowableFrame = false;
frameInfo.ErrorResilientMode = true;
}
+ else
+ {
+ frameInfo.ShowExistingFrame = reader.ReadBoolean();
+ if (frameInfo.ShowExistingFrame)
+ {
+ frameInfo.FrameToShowMapIdx = reader.ReadLiteral(3);
+ }
+
+ // TODO: There is still some parts not implemented here
+ }
if (frameInfo.FrameType == ObuFrameType.KeyFrame && frameInfo.ShowFrame)
{
diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuSequenceHeader.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuSequenceHeader.cs
index e7ce1b4e5c..b1afb7c7e3 100644
--- a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuSequenceHeader.cs
+++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuSequenceHeader.cs
@@ -25,7 +25,7 @@ internal class ObuSequenceHeader
public bool TimingInfoPresentFlag { get; set; }
- public object? TimingInfo { get; set; }
+ public ObuTimingInfo? TimingInfo { get; set; }
public bool IsFrameIdNumbersPresent { get; set; }
diff --git a/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuTimingInfo.cs b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuTimingInfo.cs
new file mode 100644
index 0000000000..d366157e78
--- /dev/null
+++ b/src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuTimingInfo.cs
@@ -0,0 +1,33 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+namespace SixLabors.ImageSharp.Formats.Heif.Av1.OpenBitstreamUnit;
+
+internal class ObuTimingInfo
+{
+ ///
+ /// Gets or sets NumUnitsInDisplayTick. NumUnitsInDisplayTick is the number of time units of a clock operating at the frequency TimeScale Hz that
+ /// corresponds to one increment of a clock tick counter. A display clock tick, in seconds, is equal to
+ /// NumUnitsInDisplayTick divided by TimeScale.
+ ///
+ public uint NumUnitsInDisplayTick { get; set; }
+
+ ///
+ /// Gets or sets TimeScale. TimeScale is the number of time units that pass in one second.
+ /// It is a requirement of bitstream conformance that TimeScale is greater than 0.
+ ///
+ public uint TimeScale { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether that pictures should be displayed according to their output order with the
+ /// number of ticks between two consecutive pictures (without dropping frames) specified by NumTicksPerPicture.
+ /// EqualPictureInterval equal to false indicates that the interval between two consecutive pictures is not specified.
+ ///
+ public bool EqualPictureInterval { get; set; }
+
+ ///
+ /// Gets or sets NumTicksPerPicture. NumTicksPerPicture specifies the number of clock ticks corresponding to output time between two
+ /// consecutive pictures in the output order.
+ ///
+ public uint NumTicksPerPicture { get; set; }
+}