Browse Source

Sync method arguments

pull/2633/head
Ynse Hoornenborg 2 years ago
parent
commit
0b1639b82f
  1. 2
      src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuFrameHeader.cs
  2. 304
      src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuReader.cs
  3. 115
      src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs

2
src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuFrameHeader.cs

@ -53,6 +53,8 @@ internal class ObuFrameHeader
public ObuDeltaParameters DeltaQParameters { get; set; } = new ObuDeltaParameters(); public ObuDeltaParameters DeltaQParameters { get; set; } = new ObuDeltaParameters();
public bool IsIntra => this.FrameType is ObuFrameType.IntraOnlyFrame or ObuFrameType.KeyFrame;
internal ObuFrameSize FrameSize { get; set; } = new ObuFrameSize(); internal ObuFrameSize FrameSize { get; set; } = new ObuFrameSize();
internal int ModeInfoColumnCount { get; set; } internal int ModeInfoColumnCount { get; set; }

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

@ -846,13 +846,12 @@ internal class ObuReader
/// <summary> /// <summary>
/// 5.9.2. Uncompressed header syntax. /// 5.9.2. Uncompressed header syntax.
/// </summary> /// </summary>
private void ReadUncompressedFrameHeader(ref Av1BitStreamReader reader, ObuHeader header, int planesCount) private void ReadUncompressedFrameHeader(ref Av1BitStreamReader reader)
{ {
ObuSequenceHeader sequenceHeader = this.SequenceHeader!; ObuSequenceHeader sequenceHeader = this.SequenceHeader!;
ObuFrameHeader frameInfo = this.FrameHeader!; ObuFrameHeader frameHeader = this.FrameHeader!;
int idLength = 0; int idLength = 0;
uint previousFrameId = 0; uint previousFrameId = 0;
bool isIntraFrame = false;
bool frameSizeOverrideFlag = false; bool frameSizeOverrideFlag = false;
if (sequenceHeader.IsFrameIdNumbersPresent) if (sequenceHeader.IsFrameIdNumbersPresent)
{ {
@ -862,115 +861,113 @@ internal class ObuReader
if (sequenceHeader.IsReducedStillPictureHeader) if (sequenceHeader.IsReducedStillPictureHeader)
{ {
frameInfo.ShowExistingFrame = false; frameHeader.ShowExistingFrame = false;
frameInfo.FrameType = ObuFrameType.KeyFrame; frameHeader.FrameType = ObuFrameType.KeyFrame;
isIntraFrame = true; frameHeader.ShowFrame = true;
frameInfo.ShowFrame = true; frameHeader.ShowableFrame = false;
frameInfo.ShowableFrame = false; frameHeader.ErrorResilientMode = true;
frameInfo.ErrorResilientMode = true;
} }
else else
{ {
frameInfo.ShowExistingFrame = reader.ReadBoolean(); frameHeader.ShowExistingFrame = reader.ReadBoolean();
if (frameInfo.ShowExistingFrame) if (frameHeader.ShowExistingFrame)
{ {
frameInfo.FrameToShowMapIdx = reader.ReadLiteral(3); frameHeader.FrameToShowMapIdx = reader.ReadLiteral(3);
if (sequenceHeader.DecoderModelInfoPresentFlag && sequenceHeader.TimingInfo?.EqualPictureInterval == false) if (sequenceHeader.DecoderModelInfoPresentFlag && sequenceHeader.TimingInfo?.EqualPictureInterval == false)
{ {
// 5.9.31. Temporal point info syntax. // 5.9.31. Temporal point info syntax.
frameInfo.FramePresentationTime = reader.ReadLiteral((int)sequenceHeader!.DecoderModelInfo!.FramePresentationTimeLength); frameHeader.FramePresentationTime = reader.ReadLiteral((int)sequenceHeader!.DecoderModelInfo!.FramePresentationTimeLength);
} }
if (sequenceHeader.IsFrameIdNumbersPresent) if (sequenceHeader.IsFrameIdNumbersPresent)
{ {
frameInfo.DisplayFrameId = reader.ReadLiteral(idLength); frameHeader.DisplayFrameId = reader.ReadLiteral(idLength);
} }
// TODO: This is incomplete here, not sure how we can display an already decoded frame here or if this is really relevent for still pictures. // TODO: This is incomplete here, not sure how we can display an already decoded frame here or if this is really relevent for still pictures.
throw new NotImplementedException("ShowExistingFrame is not yet implemented"); throw new NotImplementedException("ShowExistingFrame is not yet implemented");
} }
frameInfo.FrameType = (ObuFrameType)reader.ReadLiteral(2); frameHeader.FrameType = (ObuFrameType)reader.ReadLiteral(2);
isIntraFrame = frameInfo.FrameType is ObuFrameType.IntraOnlyFrame or ObuFrameType.KeyFrame; frameHeader.ShowFrame = reader.ReadBoolean();
frameInfo.ShowFrame = reader.ReadBoolean();
if (frameInfo.ShowFrame && !sequenceHeader.DecoderModelInfoPresentFlag && sequenceHeader.TimingInfo?.EqualPictureInterval == false) if (frameHeader.ShowFrame && !sequenceHeader.DecoderModelInfoPresentFlag && sequenceHeader.TimingInfo?.EqualPictureInterval == false)
{ {
// 5.9.31. Temporal point info syntax. // 5.9.31. Temporal point info syntax.
frameInfo.FramePresentationTime = reader.ReadLiteral((int)sequenceHeader!.DecoderModelInfo!.FramePresentationTimeLength); frameHeader.FramePresentationTime = reader.ReadLiteral((int)sequenceHeader!.DecoderModelInfo!.FramePresentationTimeLength);
} }
if (frameInfo.ShowFrame) if (frameHeader.ShowFrame)
{ {
frameInfo.ShowableFrame = frameInfo.FrameType != ObuFrameType.KeyFrame; frameHeader.ShowableFrame = frameHeader.FrameType != ObuFrameType.KeyFrame;
} }
else else
{ {
frameInfo.ShowableFrame = reader.ReadBoolean(); frameHeader.ShowableFrame = reader.ReadBoolean();
} }
if (frameInfo.FrameType == ObuFrameType.SwitchFrame || (frameInfo.FrameType == ObuFrameType.KeyFrame && frameInfo.ShowFrame)) if (frameHeader.FrameType == ObuFrameType.SwitchFrame || (frameHeader.FrameType == ObuFrameType.KeyFrame && frameHeader.ShowFrame))
{ {
frameInfo.ErrorResilientMode = true; frameHeader.ErrorResilientMode = true;
} }
else else
{ {
frameInfo.ErrorResilientMode = reader.ReadBoolean(); frameHeader.ErrorResilientMode = reader.ReadBoolean();
} }
} }
if (frameInfo.FrameType == ObuFrameType.KeyFrame && frameInfo.ShowFrame) if (frameHeader.FrameType == ObuFrameType.KeyFrame && frameHeader.ShowFrame)
{ {
frameInfo.ReferenceValid = new bool[Av1Constants.ReferenceFrameCount]; frameHeader.ReferenceValid = new bool[Av1Constants.ReferenceFrameCount];
frameInfo.ReferenceOrderHint = new bool[Av1Constants.ReferenceFrameCount]; frameHeader.ReferenceOrderHint = new bool[Av1Constants.ReferenceFrameCount];
Array.Fill(frameInfo.ReferenceValid, false); Array.Fill(frameHeader.ReferenceValid, false);
Array.Fill(frameInfo.ReferenceOrderHint, false); Array.Fill(frameHeader.ReferenceOrderHint, false);
} }
frameInfo.DisableCdfUpdate = reader.ReadBoolean(); frameHeader.DisableCdfUpdate = reader.ReadBoolean();
frameInfo.AllowScreenContentTools = sequenceHeader.ForceScreenContentTools == 2; frameHeader.AllowScreenContentTools = sequenceHeader.ForceScreenContentTools == 2;
if (frameInfo.AllowScreenContentTools) if (frameHeader.AllowScreenContentTools)
{ {
frameInfo.AllowScreenContentTools = reader.ReadBoolean(); frameHeader.AllowScreenContentTools = reader.ReadBoolean();
} }
if (frameInfo.AllowScreenContentTools) if (frameHeader.AllowScreenContentTools)
{ {
if (sequenceHeader.ForceIntegerMotionVector == 1) if (sequenceHeader.ForceIntegerMotionVector == 1)
{ {
frameInfo.ForceIntegerMotionVector = reader.ReadBoolean(); frameHeader.ForceIntegerMotionVector = reader.ReadBoolean();
} }
else else
{ {
frameInfo.ForceIntegerMotionVector = sequenceHeader.ForceIntegerMotionVector != 0; frameHeader.ForceIntegerMotionVector = sequenceHeader.ForceIntegerMotionVector != 0;
} }
} }
else else
{ {
frameInfo.ForceIntegerMotionVector = false; frameHeader.ForceIntegerMotionVector = false;
} }
if (isIntraFrame) if (frameHeader.IsIntra)
{ {
frameInfo.ForceIntegerMotionVector = true; frameHeader.ForceIntegerMotionVector = true;
} }
bool havePreviousFrameId = !(frameInfo.FrameType == ObuFrameType.KeyFrame && frameInfo.ShowFrame); bool havePreviousFrameId = !(frameHeader.FrameType == ObuFrameType.KeyFrame && frameHeader.ShowFrame);
if (havePreviousFrameId) if (havePreviousFrameId)
{ {
previousFrameId = frameInfo.CurrentFrameId; previousFrameId = frameHeader.CurrentFrameId;
} }
if (sequenceHeader.IsFrameIdNumbersPresent) if (sequenceHeader.IsFrameIdNumbersPresent)
{ {
frameInfo.CurrentFrameId = reader.ReadLiteral(idLength); frameHeader.CurrentFrameId = reader.ReadLiteral(idLength);
if (havePreviousFrameId) if (havePreviousFrameId)
{ {
uint diffFrameId = (frameInfo.CurrentFrameId > previousFrameId) ? uint diffFrameId = (frameHeader.CurrentFrameId > previousFrameId) ?
frameInfo.CurrentFrameId - previousFrameId : frameHeader.CurrentFrameId - previousFrameId :
(uint)((1 << idLength) + (int)frameInfo.CurrentFrameId - previousFrameId); (uint)((1 << idLength) + (int)frameHeader.CurrentFrameId - previousFrameId);
if (frameInfo.CurrentFrameId == previousFrameId || diffFrameId >= 1 << (idLength - 1)) if (frameHeader.CurrentFrameId == previousFrameId || diffFrameId >= 1 << (idLength - 1))
{ {
throw new ImageFormatException("Current frame ID cannot be same as previous Frame ID"); throw new ImageFormatException("Current frame ID cannot be same as previous Frame ID");
} }
@ -979,27 +976,27 @@ internal class ObuReader
int diffLength = sequenceHeader.DeltaFrameIdLength; int diffLength = sequenceHeader.DeltaFrameIdLength;
for (int i = 0; i < Av1Constants.ReferenceFrameCount; i++) for (int i = 0; i < Av1Constants.ReferenceFrameCount; i++)
{ {
if (frameInfo.CurrentFrameId > (1U << diffLength)) if (frameHeader.CurrentFrameId > (1U << diffLength))
{ {
if ((frameInfo.ReferenceFrameIndex[i] > frameInfo.CurrentFrameId) || if ((frameHeader.ReferenceFrameIndex[i] > frameHeader.CurrentFrameId) ||
frameInfo.ReferenceFrameIndex[i] > (frameInfo.CurrentFrameId - (1 - diffLength))) frameHeader.ReferenceFrameIndex[i] > (frameHeader.CurrentFrameId - (1 - diffLength)))
{ {
frameInfo.ReferenceValid[i] = false; frameHeader.ReferenceValid[i] = false;
} }
} }
else if (frameInfo.ReferenceFrameIndex[i] > frameInfo.CurrentFrameId && else if (frameHeader.ReferenceFrameIndex[i] > frameHeader.CurrentFrameId &&
frameInfo.ReferenceFrameIndex[i] < ((1 << idLength) + (frameInfo.CurrentFrameId - (1 << diffLength)))) frameHeader.ReferenceFrameIndex[i] < ((1 << idLength) + (frameHeader.CurrentFrameId - (1 << diffLength))))
{ {
frameInfo.ReferenceValid[i] = false; frameHeader.ReferenceValid[i] = false;
} }
} }
} }
else else
{ {
frameInfo.CurrentFrameId = 0; frameHeader.CurrentFrameId = 0;
} }
if (frameInfo.FrameType == ObuFrameType.SwitchFrame) if (frameHeader.FrameType == ObuFrameType.SwitchFrame)
{ {
frameSizeOverrideFlag = true; frameSizeOverrideFlag = true;
} }
@ -1012,84 +1009,85 @@ internal class ObuReader
frameSizeOverrideFlag = reader.ReadBoolean(); frameSizeOverrideFlag = reader.ReadBoolean();
} }
frameInfo.OrderHint = reader.ReadLiteral(sequenceHeader.OrderHintInfo.OrderHintBits); frameHeader.OrderHint = reader.ReadLiteral(sequenceHeader.OrderHintInfo.OrderHintBits);
if (isIntraFrame || frameInfo.ErrorResilientMode) if (frameHeader.IsIntra || frameHeader.ErrorResilientMode)
{ {
frameInfo.PrimaryReferenceFrame = Av1Constants.PrimaryReferenceFrameNone; frameHeader.PrimaryReferenceFrame = Av1Constants.PrimaryReferenceFrameNone;
} }
else else
{ {
frameInfo.PrimaryReferenceFrame = reader.ReadLiteral(Av1Constants.PimaryReferenceBits); frameHeader.PrimaryReferenceFrame = reader.ReadLiteral(Av1Constants.PimaryReferenceBits);
} }
// Skipping, as no decoder info model present // Skipping, as no decoder info model present
frameInfo.AllowHighPrecisionMotionVector = false; frameHeader.AllowHighPrecisionMotionVector = false;
frameInfo.UseReferenceFrameMotionVectors = false; frameHeader.UseReferenceFrameMotionVectors = false;
frameInfo.AllowIntraBlockCopy = false; frameHeader.AllowIntraBlockCopy = false;
if (frameInfo.FrameType == ObuFrameType.SwitchFrame || (frameInfo.FrameType == ObuFrameType.KeyFrame && frameInfo.ShowFrame)) if (frameHeader.FrameType == ObuFrameType.SwitchFrame || (frameHeader.FrameType == ObuFrameType.KeyFrame && frameHeader.ShowFrame))
{ {
frameInfo.RefreshFrameFlags = 0xFFU; frameHeader.RefreshFrameFlags = 0xFFU;
} }
else else
{ {
frameInfo.RefreshFrameFlags = reader.ReadLiteral(8); frameHeader.RefreshFrameFlags = reader.ReadLiteral(8);
} }
if (frameInfo.FrameType == ObuFrameType.IntraOnlyFrame) if (frameHeader.FrameType == ObuFrameType.IntraOnlyFrame)
{ {
DebugGuard.IsTrue(frameInfo.RefreshFrameFlags != 0xFFU, nameof(frameInfo.RefreshFrameFlags)); DebugGuard.IsTrue(frameHeader.RefreshFrameFlags != 0xFFU, nameof(frameHeader.RefreshFrameFlags));
} }
if (!isIntraFrame || (frameInfo.RefreshFrameFlags != 0xFFU)) if (!frameHeader.IsIntra || (frameHeader.RefreshFrameFlags != 0xFFU))
{ {
if (frameInfo.ErrorResilientMode && sequenceHeader.OrderHintInfo != null) if (frameHeader.ErrorResilientMode && sequenceHeader.OrderHintInfo != null)
{ {
for (int i = 0; i < Av1Constants.ReferenceFrameCount; i++) for (int i = 0; i < Av1Constants.ReferenceFrameCount; i++)
{ {
int referenceOrderHint = (int)reader.ReadLiteral(sequenceHeader.OrderHintInfo.OrderHintBits); int referenceOrderHint = (int)reader.ReadLiteral(sequenceHeader.OrderHintInfo.OrderHintBits);
if (referenceOrderHint != (frameInfo.ReferenceOrderHint[i] ? 1U : 0U)) if (referenceOrderHint != (frameHeader.ReferenceOrderHint[i] ? 1U : 0U))
{ {
frameInfo.ReferenceValid[i] = false; frameHeader.ReferenceValid[i] = false;
} }
} }
} }
} }
if (isIntraFrame) if (frameHeader.IsIntra)
{ {
this.ReadFrameSize(ref reader, frameSizeOverrideFlag); this.ReadFrameSize(ref reader, frameSizeOverrideFlag);
this.ReadRenderSize(ref reader); this.ReadRenderSize(ref reader);
if (frameInfo.AllowScreenContentTools && frameInfo.FrameSize.RenderWidth != 0) if (frameHeader.AllowScreenContentTools && frameHeader.FrameSize.RenderWidth != 0)
{ {
if (frameInfo.FrameSize.FrameWidth == frameInfo.FrameSize.SuperResolutionUpscaledWidth) if (frameHeader.FrameSize.FrameWidth == frameHeader.FrameSize.SuperResolutionUpscaledWidth)
{ {
frameInfo.AllowIntraBlockCopy = reader.ReadBoolean(); frameHeader.AllowIntraBlockCopy = reader.ReadBoolean();
} }
} }
} }
else else
{ {
// Single image is always Intra. // Single image is always Intra.
throw new InvalidImageContentException("AVIF image can only contain INTRA frames.");
} }
// SetupFrameBufferReferences(sequenceHeader, frameInfo); // SetupFrameBufferReferences(sequenceHeader, frameInfo);
// CheckAddTemporalMotionVectorBuffer(sequenceHeader, frameInfo); // CheckAddTemporalMotionVectorBuffer(sequenceHeader, frameInfo);
// SetupFrameSignBias(sequenceHeader, frameInfo); // SetupFrameSignBias(sequenceHeader, frameInfo);
if (sequenceHeader.IsReducedStillPictureHeader || frameInfo.DisableCdfUpdate) if (sequenceHeader.IsReducedStillPictureHeader || frameHeader.DisableCdfUpdate)
{ {
frameInfo.DisableFrameEndUpdateCdf = true; frameHeader.DisableFrameEndUpdateCdf = true;
} }
else else
{ {
frameInfo.DisableFrameEndUpdateCdf = reader.ReadBoolean(); frameHeader.DisableFrameEndUpdateCdf = reader.ReadBoolean();
} }
if (frameInfo.PrimaryReferenceFrame == Av1Constants.PrimaryReferenceFrameNone) if (frameHeader.PrimaryReferenceFrame == Av1Constants.PrimaryReferenceFrameNone)
{ {
// InitConCoefficientCdfs(); // InitConCoefficientCdfs();
SetupPastIndependence(frameInfo); SetupPastIndependence(frameHeader);
} }
else else
{ {
@ -1098,21 +1096,21 @@ internal class ObuReader
throw new NotImplementedException(); throw new NotImplementedException();
} }
if (frameInfo.UseReferenceFrameMotionVectors) if (frameHeader.UseReferenceFrameMotionVectors)
{ {
// MotionFieldEstimations(); // MotionFieldEstimations();
throw new NotImplementedException(); throw new NotImplementedException();
} }
// GenerateNextReferenceFrameMap(sequenceHeader, frameInfo); // GenerateNextReferenceFrameMap(sequenceHeader, frameInfo);
frameInfo.TilesInfo = ReadTileInfo(ref reader, sequenceHeader, frameInfo); frameHeader.TilesInfo = ReadTileInfo(ref reader, sequenceHeader, frameHeader);
ReadQuantizationParameters(ref reader, frameInfo.QuantizationParameters, sequenceHeader.ColorConfig, planesCount); ReadQuantizationParameters(ref reader, sequenceHeader, frameHeader);
ReadSegmentationParameters(ref reader, sequenceHeader, frameInfo, planesCount); ReadSegmentationParameters(ref reader, frameHeader);
ReadFrameDeltaQParameters(ref reader, frameInfo); ReadFrameDeltaQParameters(ref reader, frameHeader);
ReadFrameDeltaLoopFilterParameters(ref reader, frameInfo); ReadFrameDeltaLoopFilterParameters(ref reader, frameHeader);
// SetupSegmentationDequantization(); // SetupSegmentationDequantization();
if (frameInfo.PrimaryReferenceFrame == Av1Constants.PrimaryReferenceFrameNone) if (frameHeader.PrimaryReferenceFrame == Av1Constants.PrimaryReferenceFrameNone)
{ {
// ResetParseContext(mainParseContext, frameInfo.QuantizationParameters.BaseQIndex); // ResetParseContext(mainParseContext, frameInfo.QuantizationParameters.BaseQIndex);
} }
@ -1122,72 +1120,74 @@ internal class ObuReader
throw new NotImplementedException(); throw new NotImplementedException();
} }
int tilesCount = frameInfo.TilesInfo.TileColumnCount * frameInfo.TilesInfo.TileRowCount; int tilesCount = frameHeader.TilesInfo.TileColumnCount * frameHeader.TilesInfo.TileRowCount;
frameInfo.CodedLossless = true; frameHeader.CodedLossless = true;
frameInfo.SegmentationParameters.QMLevel[0] = new int[Av1Constants.MaxSegmentCount]; frameHeader.SegmentationParameters.QMLevel[0] = new int[Av1Constants.MaxSegmentCount];
frameInfo.SegmentationParameters.QMLevel[1] = new int[Av1Constants.MaxSegmentCount]; frameHeader.SegmentationParameters.QMLevel[1] = new int[Av1Constants.MaxSegmentCount];
frameInfo.SegmentationParameters.QMLevel[2] = new int[Av1Constants.MaxSegmentCount]; frameHeader.SegmentationParameters.QMLevel[2] = new int[Av1Constants.MaxSegmentCount];
for (int segmentId = 0; segmentId < Av1Constants.MaxSegmentCount; segmentId++) for (int segmentId = 0; segmentId < Av1Constants.MaxSegmentCount; segmentId++)
{ {
int qIndex = GetQIndex(frameInfo.SegmentationParameters, segmentId, frameInfo.QuantizationParameters.BaseQIndex); int qIndex = GetQIndex(frameHeader.SegmentationParameters, segmentId, frameHeader.QuantizationParameters.BaseQIndex);
frameInfo.QuantizationParameters.QIndex[segmentId] = qIndex; frameHeader.QuantizationParameters.QIndex[segmentId] = qIndex;
frameInfo.LosslessArray[segmentId] = qIndex == 0 && frameHeader.LosslessArray[segmentId] = qIndex == 0 &&
frameInfo.QuantizationParameters.DeltaQDc[(int)Av1Plane.Y] == 0 && frameHeader.QuantizationParameters.DeltaQDc[(int)Av1Plane.Y] == 0 &&
frameInfo.QuantizationParameters.DeltaQAc[(int)Av1Plane.U] == 0 && frameHeader.QuantizationParameters.DeltaQAc[(int)Av1Plane.U] == 0 &&
frameInfo.QuantizationParameters.DeltaQDc[(int)Av1Plane.U] == 0 && frameHeader.QuantizationParameters.DeltaQDc[(int)Av1Plane.U] == 0 &&
frameInfo.QuantizationParameters.DeltaQAc[(int)Av1Plane.V] == 0 && frameHeader.QuantizationParameters.DeltaQAc[(int)Av1Plane.V] == 0 &&
frameInfo.QuantizationParameters.DeltaQDc[(int)Av1Plane.V] == 0; frameHeader.QuantizationParameters.DeltaQDc[(int)Av1Plane.V] == 0;
if (!frameInfo.LosslessArray[segmentId]) if (!frameHeader.LosslessArray[segmentId])
{ {
frameInfo.CodedLossless = false; frameHeader.CodedLossless = false;
} }
if (frameInfo.QuantizationParameters.IsUsingQMatrix) if (frameHeader.QuantizationParameters.IsUsingQMatrix)
{ {
if (frameInfo.LosslessArray[segmentId]) if (frameHeader.LosslessArray[segmentId])
{ {
frameInfo.SegmentationParameters.QMLevel[0][segmentId] = 15; frameHeader.SegmentationParameters.QMLevel[0][segmentId] = 15;
frameInfo.SegmentationParameters.QMLevel[1][segmentId] = 15; frameHeader.SegmentationParameters.QMLevel[1][segmentId] = 15;
frameInfo.SegmentationParameters.QMLevel[2][segmentId] = 15; frameHeader.SegmentationParameters.QMLevel[2][segmentId] = 15;
} }
else else
{ {
frameInfo.SegmentationParameters.QMLevel[0][segmentId] = frameInfo.QuantizationParameters.QMatrix[(int)Av1Plane.Y]; frameHeader.SegmentationParameters.QMLevel[0][segmentId] = frameHeader.QuantizationParameters.QMatrix[(int)Av1Plane.Y];
frameInfo.SegmentationParameters.QMLevel[1][segmentId] = frameInfo.QuantizationParameters.QMatrix[(int)Av1Plane.U]; frameHeader.SegmentationParameters.QMLevel[1][segmentId] = frameHeader.QuantizationParameters.QMatrix[(int)Av1Plane.U];
frameInfo.SegmentationParameters.QMLevel[2][segmentId] = frameInfo.QuantizationParameters.QMatrix[(int)Av1Plane.V]; frameHeader.SegmentationParameters.QMLevel[2][segmentId] = frameHeader.QuantizationParameters.QMatrix[(int)Av1Plane.V];
} }
} }
} }
if (frameInfo.CodedLossless) if (frameHeader.CodedLossless)
{ {
DebugGuard.IsFalse(frameInfo.DeltaQParameters.IsPresent, nameof(frameInfo.DeltaQParameters.IsPresent), "No Delta Q parameters are allowed for lossless frame."); DebugGuard.IsFalse(frameHeader.DeltaQParameters.IsPresent, nameof(frameHeader.DeltaQParameters.IsPresent), "No Delta Q parameters are allowed for lossless frame.");
} }
frameInfo.AllLossless = frameInfo.CodedLossless && frameInfo.FrameSize.FrameWidth == frameInfo.FrameSize.SuperResolutionUpscaledWidth; frameHeader.AllLossless = frameHeader.CodedLossless && frameHeader.FrameSize.FrameWidth == frameHeader.FrameSize.SuperResolutionUpscaledWidth;
this.ReadLoopFilterParameters(ref reader, planesCount); this.ReadLoopFilterParameters(ref reader, sequenceHeader);
ReadCdefParameters(ref reader, sequenceHeader, frameInfo, planesCount); ReadCdefParameters(ref reader, sequenceHeader, frameHeader);
ReadLoopRestorationParameters(ref reader, sequenceHeader, frameInfo, planesCount); ReadLoopRestorationParameters(ref reader, sequenceHeader, frameHeader);
ReadTransformMode(ref reader, frameInfo); ReadTransformMode(ref reader, frameHeader);
frameInfo.ReferenceMode = ReadFrameReferenceMode(ref reader, isIntraFrame); frameHeader.ReferenceMode = ReadFrameReferenceMode(ref reader, frameHeader);
ReadSkipModeParameters(ref reader, sequenceHeader, frameInfo, isIntraFrame, frameInfo.ReferenceMode); ReadSkipModeParameters(ref reader, sequenceHeader, frameHeader);
if (isIntraFrame || frameInfo.ErrorResilientMode || !sequenceHeader.EnableWarpedMotion) if (frameHeader.IsIntra || frameHeader.ErrorResilientMode || !sequenceHeader.EnableWarpedMotion)
{ {
frameInfo.AllowWarpedMotion = false; frameHeader.AllowWarpedMotion = false;
} }
else else
{ {
frameInfo.AllowWarpedMotion = reader.ReadBoolean(); frameHeader.AllowWarpedMotion = reader.ReadBoolean();
} }
frameInfo.UseReducedTransformSet = reader.ReadBoolean(); frameHeader.UseReducedTransformSet = reader.ReadBoolean();
ReadGlobalMotionParameters(ref reader, sequenceHeader, frameInfo, isIntraFrame); ReadGlobalMotionParameters(ref reader, sequenceHeader, frameHeader);
frameInfo.FilmGrainParameters = ReadFilmGrainFilterParameters(ref reader, sequenceHeader, frameInfo); frameHeader.FilmGrainParameters = ReadFilmGrainFilterParameters(ref reader, sequenceHeader, frameHeader);
} }
private static void SetupPastIndependence(ObuFrameHeader frameInfo) private static void SetupPastIndependence(ObuFrameHeader frameInfo)
{ {
_ = frameInfo;
// TODO: Implement. // TODO: Implement.
// The current frame can be decoded without dependencies on previous coded frame. // The current frame can be decoded without dependencies on previous coded frame.
} }
@ -1214,9 +1214,8 @@ internal class ObuReader
/// </summary> /// </summary>
internal void ReadFrameHeader(ref Av1BitStreamReader reader, ObuHeader header, bool trailingBit) internal void ReadFrameHeader(ref Av1BitStreamReader reader, ObuHeader header, bool trailingBit)
{ {
int planeCount = this.SequenceHeader!.ColorConfig.PlaneCount;
int startBitPosition = reader.BitPosition; int startBitPosition = reader.BitPosition;
this.ReadUncompressedFrameHeader(ref reader, header, planeCount); this.ReadUncompressedFrameHeader(ref reader);
if (trailingBit) if (trailingBit)
{ {
ReadTrailingBits(ref reader); ReadTrailingBits(ref reader);
@ -1356,12 +1355,14 @@ internal class ObuReader
/// <summary> /// <summary>
/// 5.9.12. Quantization params syntax. /// 5.9.12. Quantization params syntax.
/// </summary> /// </summary>
private static void ReadQuantizationParameters(ref Av1BitStreamReader reader, ObuQuantizationParameters quantParams, ObuColorConfig colorInfo, int planesCount) private static void ReadQuantizationParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{ {
ObuQuantizationParameters quantParams = frameHeader.QuantizationParameters;
ObuColorConfig colorInfo = sequenceHeader.ColorConfig;
quantParams.BaseQIndex = (int)reader.ReadLiteral(8); quantParams.BaseQIndex = (int)reader.ReadLiteral(8);
quantParams.DeltaQDc[(int)Av1Plane.Y] = ReadDeltaQ(ref reader); quantParams.DeltaQDc[(int)Av1Plane.Y] = ReadDeltaQ(ref reader);
quantParams.DeltaQAc[(int)Av1Plane.Y] = 0; quantParams.DeltaQAc[(int)Av1Plane.Y] = 0;
if (planesCount > 1) if (colorInfo.PlaneCount > 1)
{ {
quantParams.HasSeparateUvDelta = false; quantParams.HasSeparateUvDelta = false;
if (colorInfo.HasSeparateUvDelta) if (colorInfo.HasSeparateUvDelta)
@ -1415,7 +1416,7 @@ internal class ObuReader
/// <summary> /// <summary>
/// 5.9.14. Segmentation params syntax. /// 5.9.14. Segmentation params syntax.
/// </summary> /// </summary>
private static void ReadSegmentationParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, int planesCount) private static void ReadSegmentationParameters(ref Av1BitStreamReader reader, ObuFrameHeader frameInfo)
{ {
frameInfo.SegmentationParameters.Enabled = reader.ReadBoolean(); frameInfo.SegmentationParameters.Enabled = reader.ReadBoolean();
@ -1501,7 +1502,7 @@ internal class ObuReader
/// <summary> /// <summary>
/// 5.9.11. Loop filter params syntax /// 5.9.11. Loop filter params syntax
/// </summary> /// </summary>
private void ReadLoopFilterParameters(ref Av1BitStreamReader reader, int planesCount) private void ReadLoopFilterParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader)
{ {
ObuFrameHeader frameInfo = this.FrameHeader!; ObuFrameHeader frameInfo = this.FrameHeader!;
if (frameInfo.CodedLossless || frameInfo.AllowIntraBlockCopy) if (frameInfo.CodedLossless || frameInfo.AllowIntraBlockCopy)
@ -1512,7 +1513,7 @@ internal class ObuReader
frameInfo.LoopFilterParameters.FilterLevel[0] = (int)reader.ReadLiteral(6); frameInfo.LoopFilterParameters.FilterLevel[0] = (int)reader.ReadLiteral(6);
frameInfo.LoopFilterParameters.FilterLevel[1] = (int)reader.ReadLiteral(6); frameInfo.LoopFilterParameters.FilterLevel[1] = (int)reader.ReadLiteral(6);
if (planesCount > 1) if (sequenceHeader.ColorConfig.PlaneCount > 1)
{ {
if (frameInfo.LoopFilterParameters.FilterLevel[0] > 0 || frameInfo.LoopFilterParameters.FilterLevel[1] > 0) if (frameInfo.LoopFilterParameters.FilterLevel[0] > 0 || frameInfo.LoopFilterParameters.FilterLevel[1] > 0)
{ {
@ -1572,7 +1573,7 @@ internal class ObuReader
/// <summary> /// <summary>
/// See section 5.9.20. Loop restoration params syntax. /// See section 5.9.20. Loop restoration params syntax.
/// </summary> /// </summary>
private static void ReadLoopRestorationParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, int planesCount) private static void ReadLoopRestorationParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo)
{ {
if (frameInfo.CodedLossless || frameInfo.AllowIntraBlockCopy || !sequenceHeader.EnableRestoration) if (frameInfo.CodedLossless || frameInfo.AllowIntraBlockCopy || !sequenceHeader.EnableRestoration)
{ {
@ -1581,6 +1582,7 @@ internal class ObuReader
frameInfo.LoopRestorationParameters.UsesLoopRestoration = false; frameInfo.LoopRestorationParameters.UsesLoopRestoration = false;
frameInfo.LoopRestorationParameters.UsesChromaLoopRestoration = false; frameInfo.LoopRestorationParameters.UsesChromaLoopRestoration = false;
int planesCount = sequenceHeader.ColorConfig.PlaneCount;
for (int i = 0; i < planesCount; i++) for (int i = 0; i < planesCount; i++)
{ {
frameInfo.LoopRestorationParameters.Items[i].Type = (ObuRestorationType)reader.ReadLiteral(2); frameInfo.LoopRestorationParameters.Items[i].Type = (ObuRestorationType)reader.ReadLiteral(2);
@ -1625,10 +1627,11 @@ internal class ObuReader
/// <summary> /// <summary>
/// See section 5.9.19. CDEF params syntax. /// See section 5.9.19. CDEF params syntax.
/// </summary> /// </summary>
private static void ReadCdefParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, int planesCount) private static void ReadCdefParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{ {
ObuConstraintDirectionalEnhancementFilterParameters cdefInfo = frameInfo.CdefParameters; ObuConstraintDirectionalEnhancementFilterParameters cdefInfo = frameHeader.CdefParameters;
if (frameInfo.CodedLossless || frameInfo.AllowIntraBlockCopy || sequenceHeader.CdefLevel == 0) bool multiPlane = sequenceHeader.ColorConfig.PlaneCount > 1;
if (frameHeader.CodedLossless || frameHeader.AllowIntraBlockCopy || sequenceHeader.CdefLevel == 0)
{ {
cdefInfo.BitCount = 0; cdefInfo.BitCount = 0;
cdefInfo.YStrength[0] = 0; cdefInfo.YStrength[0] = 0;
@ -1641,11 +1644,11 @@ internal class ObuReader
cdefInfo.Damping = (int)reader.ReadLiteral(2) + 3; cdefInfo.Damping = (int)reader.ReadLiteral(2) + 3;
cdefInfo.BitCount = (int)reader.ReadLiteral(2); cdefInfo.BitCount = (int)reader.ReadLiteral(2);
for (int i = 0; i < (1 << frameInfo.CdefParameters.BitCount); i++) for (int i = 0; i < (1 << frameHeader.CdefParameters.BitCount); i++)
{ {
cdefInfo.YStrength[i] = (int)reader.ReadLiteral(6); cdefInfo.YStrength[i] = (int)reader.ReadLiteral(6);
if (planesCount > 1) if (multiPlane)
{ {
cdefInfo.UvStrength[i] = (int)reader.ReadLiteral(6); cdefInfo.UvStrength[i] = (int)reader.ReadLiteral(6);
} }
@ -1655,9 +1658,12 @@ internal class ObuReader
/// <summary> /// <summary>
/// 5.9.24. Global motion params syntax. /// 5.9.24. Global motion params syntax.
/// </summary> /// </summary>
private static void ReadGlobalMotionParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, bool isIntraFrame) private static void ReadGlobalMotionParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{ {
if (isIntraFrame) _ = reader;
_ = sequenceHeader;
if (frameHeader.IsIntra)
{ {
return; return;
} }
@ -1669,9 +1675,9 @@ internal class ObuReader
/// <summary> /// <summary>
/// 5.9.23. Frame reference mode syntax /// 5.9.23. Frame reference mode syntax
/// </summary> /// </summary>
private static ObuReferenceMode ReadFrameReferenceMode(ref Av1BitStreamReader reader, bool isIntraFrame) private static ObuReferenceMode ReadFrameReferenceMode(ref Av1BitStreamReader reader, ObuFrameHeader frameHeader)
{ {
if (isIntraFrame) if (frameHeader.IsIntra)
{ {
return ObuReferenceMode.SingleReference; return ObuReferenceMode.SingleReference;
} }
@ -1682,24 +1688,24 @@ internal class ObuReader
/// <summary> /// <summary>
/// 5.11.10. Skip mode syntax. /// 5.11.10. Skip mode syntax.
/// </summary> /// </summary>
private static void ReadSkipModeParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, bool isIntraFrame, ObuReferenceMode referenceSelect) private static void ReadSkipModeParameters(ref Av1BitStreamReader reader, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{ {
if (isIntraFrame || referenceSelect == ObuReferenceMode.ReferenceModeSelect || !sequenceHeader.OrderHintInfo.EnableOrderHint) if (frameHeader.IsIntra || frameHeader.ReferenceMode == ObuReferenceMode.ReferenceModeSelect || !sequenceHeader.OrderHintInfo.EnableOrderHint)
{ {
frameInfo.SkipModeParameters.SkipModeAllowed = false; frameHeader.SkipModeParameters.SkipModeAllowed = false;
} }
else else
{ {
// Not applicable for INTRA frames. // Not applicable for INTRA frames.
} }
if (frameInfo.SkipModeParameters.SkipModeAllowed) if (frameHeader.SkipModeParameters.SkipModeAllowed)
{ {
frameInfo.SkipModeParameters.SkipModeFlag = reader.ReadBoolean(); frameHeader.SkipModeParameters.SkipModeFlag = reader.ReadBoolean();
} }
else else
{ {
frameInfo.SkipModeParameters.SkipModeFlag = false; frameHeader.SkipModeParameters.SkipModeFlag = false;
} }
} }

115
src/ImageSharp/Formats/Heif/Av1/OpenBitstreamUnit/ObuWriter.cs

@ -407,8 +407,8 @@ internal class ObuWriter
} }
WriteTileInfo(ref writer, sequenceHeader, frameHeader); WriteTileInfo(ref writer, sequenceHeader, frameHeader);
WriteQuantizationParameters(ref writer, frameHeader.QuantizationParameters, sequenceHeader.ColorConfig, planesCount); WriteQuantizationParameters(ref writer, sequenceHeader, frameHeader);
WriteSegmentationParameters(ref writer, sequenceHeader, frameHeader, planesCount); WriteSegmentationParameters(ref writer, sequenceHeader, frameHeader);
if (frameHeader.QuantizationParameters.BaseQIndex > 0) if (frameHeader.QuantizationParameters.BaseQIndex > 0)
{ {
@ -454,16 +454,16 @@ internal class ObuWriter
{ {
if (!frameHeader.CodedLossless) if (!frameHeader.CodedLossless)
{ {
WriteLoopFilterParameters(ref writer, sequenceHeader, frameHeader, planesCount); WriteLoopFilterParameters(ref writer, sequenceHeader, frameHeader);
if (sequenceHeader.CdefLevel > 0) if (sequenceHeader.CdefLevel > 0)
{ {
WriteCdefParameters(ref writer, sequenceHeader, frameHeader, planesCount); WriteCdefParameters(ref writer, sequenceHeader, frameHeader);
} }
} }
if (sequenceHeader.EnableRestoration) if (sequenceHeader.EnableRestoration)
{ {
WriteLoopRestorationParameters(ref writer, sequenceHeader, frameHeader, planesCount); WriteLoopRestorationParameters(ref writer, sequenceHeader, frameHeader);
} }
} }
@ -471,15 +471,13 @@ internal class ObuWriter
WriteTransformMode(ref writer, frameHeader); WriteTransformMode(ref writer, frameHeader);
// No compound INTER-INTER for AVIF. // No compound INTER-INTER for AVIF.
if (frameHeader.SkipModeParameters.SkipModeAllowed) WriteFrameReferenceMode(ref writer, frameHeader);
{ WriteSkipModeParameters(ref writer, frameHeader);
writer.WriteBoolean(frameHeader.SkipModeParameters.SkipModeFlag);
}
// No warp motion for AVIF. // No warp motion for AVIF.
writer.WriteBoolean(frameHeader.UseReducedTransformSet); writer.WriteBoolean(frameHeader.UseReducedTransformSet);
// No global motion for AVIF. WriteGlobalMotionParameters(ref writer, frameHeader);
WriteFilmGrainFilterParameters(ref writer, sequenceHeader, frameHeader); WriteFilmGrainFilterParameters(ref writer, sequenceHeader, frameHeader);
} }
@ -585,13 +583,14 @@ internal class ObuWriter
/// <summary> /// <summary>
/// See section 5.9.12. /// See section 5.9.12.
/// </summary> /// </summary>
private static void WriteQuantizationParameters(ref Av1BitStreamWriter writer, ObuQuantizationParameters quantParams, ObuColorConfig colorInfo, int planesCount) private static void WriteQuantizationParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{ {
ObuQuantizationParameters quantParams = frameHeader.QuantizationParameters;
writer.WriteLiteral((uint)quantParams.BaseQIndex, 8); writer.WriteLiteral((uint)quantParams.BaseQIndex, 8);
WriteDeltaQ(ref writer, quantParams.DeltaQDc[(int)Av1Plane.Y]); WriteDeltaQ(ref writer, quantParams.DeltaQDc[(int)Av1Plane.Y]);
if (planesCount > 1) if (sequenceHeader.ColorConfig.PlaneCount > 1)
{ {
if (colorInfo.HasSeparateUvDelta) if (sequenceHeader.ColorConfig.HasSeparateUvDelta)
{ {
writer.WriteBoolean(quantParams.HasSeparateUvDelta); writer.WriteBoolean(quantParams.HasSeparateUvDelta);
} }
@ -610,43 +609,44 @@ internal class ObuWriter
{ {
writer.WriteLiteral((uint)quantParams.QMatrix[(int)Av1Plane.Y], 4); writer.WriteLiteral((uint)quantParams.QMatrix[(int)Av1Plane.Y], 4);
writer.WriteLiteral((uint)quantParams.QMatrix[(int)Av1Plane.U], 4); writer.WriteLiteral((uint)quantParams.QMatrix[(int)Av1Plane.U], 4);
if (colorInfo.HasSeparateUvDelta) if (sequenceHeader.ColorConfig.HasSeparateUvDelta)
{ {
writer.WriteLiteral((uint)quantParams.QMatrix[(int)Av1Plane.V], 4); writer.WriteLiteral((uint)quantParams.QMatrix[(int)Av1Plane.V], 4);
} }
} }
} }
private static void WriteSegmentationParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, int planesCount) private static void WriteSegmentationParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo)
{ {
Guard.IsFalse(frameInfo.SegmentationParameters.Enabled, nameof(frameInfo.SegmentationParameters.Enabled), "Segmentatino not supported yet."); _ = sequenceHeader;
Guard.IsFalse(frameInfo.SegmentationParameters.Enabled, nameof(frameInfo.SegmentationParameters.Enabled), "Segmentation not supported yet.");
writer.WriteBoolean(false); writer.WriteBoolean(false);
} }
private static void WriteLoopFilterParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, int planesCount) private static void WriteLoopFilterParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{ {
if (frameInfo.CodedLossless || frameInfo.AllowIntraBlockCopy) if (frameHeader.CodedLossless || frameHeader.AllowIntraBlockCopy)
{ {
return; return;
} }
writer.WriteLiteral((uint)frameInfo.LoopFilterParameters.FilterLevel[0], 6); writer.WriteLiteral((uint)frameHeader.LoopFilterParameters.FilterLevel[0], 6);
writer.WriteLiteral((uint)frameInfo.LoopFilterParameters.FilterLevel[1], 6); writer.WriteLiteral((uint)frameHeader.LoopFilterParameters.FilterLevel[1], 6);
if (sequenceHeader.ColorConfig.PlaneCount > 1) if (sequenceHeader.ColorConfig.PlaneCount > 1)
{ {
if (frameInfo.LoopFilterParameters.FilterLevel[0] > 0 || frameInfo.LoopFilterParameters.FilterLevel[1] > 0) if (frameHeader.LoopFilterParameters.FilterLevel[0] > 0 || frameHeader.LoopFilterParameters.FilterLevel[1] > 0)
{ {
writer.WriteLiteral((uint)frameInfo.LoopFilterParameters.FilterLevelU, 6); writer.WriteLiteral((uint)frameHeader.LoopFilterParameters.FilterLevelU, 6);
writer.WriteLiteral((uint)frameInfo.LoopFilterParameters.FilterLevelV, 6); writer.WriteLiteral((uint)frameHeader.LoopFilterParameters.FilterLevelV, 6);
} }
} }
writer.WriteLiteral((uint)frameInfo.LoopFilterParameters.SharpnessLevel, 3); writer.WriteLiteral((uint)frameHeader.LoopFilterParameters.SharpnessLevel, 3);
writer.WriteBoolean(frameInfo.LoopFilterParameters.ReferenceDeltaModeEnabled); writer.WriteBoolean(frameHeader.LoopFilterParameters.ReferenceDeltaModeEnabled);
if (frameInfo.LoopFilterParameters.ReferenceDeltaModeEnabled) if (frameHeader.LoopFilterParameters.ReferenceDeltaModeEnabled)
{ {
writer.WriteBoolean(frameInfo.LoopFilterParameters.ReferenceDeltaModeUpdate); writer.WriteBoolean(frameHeader.LoopFilterParameters.ReferenceDeltaModeUpdate);
if (frameInfo.LoopFilterParameters.ReferenceDeltaModeUpdate) if (frameHeader.LoopFilterParameters.ReferenceDeltaModeUpdate)
{ {
throw new NotImplementedException("Reference update of loop filter not supported yet."); throw new NotImplementedException("Reference update of loop filter not supported yet.");
} }
@ -664,21 +664,22 @@ internal class ObuWriter
} }
} }
private static void WriteLoopRestorationParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, int planesCount) private static void WriteLoopRestorationParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{ {
if (frameInfo.CodedLossless || frameInfo.AllowIntraBlockCopy || !sequenceHeader.EnableRestoration) if (frameHeader.CodedLossless || frameHeader.AllowIntraBlockCopy || !sequenceHeader.EnableRestoration)
{ {
return; return;
} }
int planesCount = sequenceHeader.ColorConfig.PlaneCount;
for (int i = 0; i < planesCount; i++) for (int i = 0; i < planesCount; i++)
{ {
writer.WriteLiteral((uint)frameInfo.LoopRestorationParameters.Items[i].Type, 2); writer.WriteLiteral((uint)frameHeader.LoopRestorationParameters.Items[i].Type, 2);
} }
if (frameInfo.LoopRestorationParameters.UsesLoopRestoration) if (frameHeader.LoopRestorationParameters.UsesLoopRestoration)
{ {
uint unitShift = (uint)frameInfo.LoopRestorationParameters.UnitShift; uint unitShift = (uint)frameHeader.LoopRestorationParameters.UnitShift;
if (sequenceHeader.Use128x128Superblock) if (sequenceHeader.Use128x128Superblock)
{ {
writer.WriteLiteral(unitShift - 1, 1); writer.WriteLiteral(unitShift - 1, 1);
@ -692,50 +693,58 @@ internal class ObuWriter
} }
} }
if (sequenceHeader.ColorConfig.SubSamplingX && sequenceHeader.ColorConfig.SubSamplingY && frameInfo.LoopRestorationParameters.UsesChromaLoopRestoration) if (sequenceHeader.ColorConfig.SubSamplingX && sequenceHeader.ColorConfig.SubSamplingY && frameHeader.LoopRestorationParameters.UsesChromaLoopRestoration)
{ {
writer.WriteLiteral((uint)frameInfo.LoopRestorationParameters.UVShift, 1); writer.WriteLiteral((uint)frameHeader.LoopRestorationParameters.UVShift, 1);
} }
} }
} }
private static void WriteCdefParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, int planesCount) private static void WriteCdefParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)
{ {
_ = writer; _ = writer;
_ = sequenceHeader; _ = sequenceHeader;
_ = frameInfo;
_ = planesCount;
if (!frameInfo.CodedLossless && !frameInfo.AllowIntraBlockCopy && sequenceHeader.EnableCdef) if (frameHeader.CodedLossless || frameHeader.AllowIntraBlockCopy || !sequenceHeader.EnableCdef)
{ {
throw new NotImplementedException("Didn't implment writing CDF yet."); return;
} }
throw new NotImplementedException("Didn't implement writing CDEF yet.");
} }
private static void WriteGlobalMotionParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameInfo, bool isIntraFrame) private static void WriteGlobalMotionParameters(ref Av1BitStreamWriter writer, ObuFrameHeader frameHeader)
{ {
_ = writer; _ = writer;
_ = sequenceHeader;
_ = frameInfo;
// Nothing to be written for INTRA frames. if (frameHeader.IsIntra)
Guard.IsTrue(isIntraFrame, nameof(isIntraFrame), "Still picture contains only INTRA frames."); {
// Nothing to be written for INTRA frames.
return;
}
throw new InvalidImageContentException("AVIF files can only contain INTRA frames.");
} }
private static void WriteFrameReferenceMode(ref Av1BitStreamWriter writer, bool isIntraFrame) private static void WriteFrameReferenceMode(ref Av1BitStreamWriter writer, ObuFrameHeader frameHeader)
{ {
_ = writer; _ = writer;
// Nothing to be written for INTRA frames. if (frameHeader.IsIntra)
Guard.IsTrue(isIntraFrame, nameof(isIntraFrame), "Still picture contains only INTRA frames."); {
// Nothing to be written for INTRA frames.
return;
}
throw new InvalidImageContentException("AVIF files can only contain INTRA frames.");
} }
private static void WriteSkipModeParameters(ref Av1BitStreamWriter writer, bool isIntraFrame) private static void WriteSkipModeParameters(ref Av1BitStreamWriter writer, ObuFrameHeader frameHeader)
{ {
_ = writer; if (frameHeader.SkipModeParameters.SkipModeAllowed)
{
// Nothing to be written for INTRA frames. writer.WriteBoolean(frameHeader.SkipModeParameters.SkipModeFlag);
Guard.IsTrue(isIntraFrame, nameof(isIntraFrame), "Still picture contains only INTRA frames."); }
} }
private static void WriteFilmGrainFilterParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader) private static void WriteFilmGrainFilterParameters(ref Av1BitStreamWriter writer, ObuSequenceHeader sequenceHeader, ObuFrameHeader frameHeader)

Loading…
Cancel
Save