Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow odd clap dimensions and offsets #2426

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

y-guyon
Copy link
Collaborator

@y-guyon y-guyon commented Sep 10, 2024

The constraint in MIAF was replaced by an upsampling step before cropping.

Notes:

  • avifdec does not crop anything when decoding.
  • the libavif API only outputs YUV samples along with a clap field in avifImage. It is the user's duty to upsample, hence the added output argument in avifCropRectFromCleanApertureBox().

See AOMediaCodec/av1-avif#202 (comment).

The constraint in MIAF was replaced by an upsampling step before
cropping.
@y-guyon
Copy link
Collaborator Author

y-guyon commented Sep 11, 2024

@wantehchang Do you plan on submitting #1749 first?

@wantehchang
Copy link
Collaborator

@wantehchang Do you plan on submitting #1749 first?

Done. The reason I had not submitted #1749 is that I am not sure whether only some of the members of the avifCleanApertureBox struct will be changed to int32_t in the next version of ISO BMFF. But it is fine to submit #1749 first because it describes how libavif interprets the members of the avifCleanApertureBox struct now. We can update the comment when the next version of ISO BMFF is released.

Copy link
Collaborator

@wantehchang wantehchang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to think about this issue more to see if we should take a different approach in this pull request. Here are some comments on the current approach.

@@ -722,6 +699,16 @@ avifBool avifCropRectConvertCleanApertureBox(avifCropRect * cropRect,
// positive or negative. For cleanApertureWidth and cleanApertureHeight,
// N shall be positive and D shall be strictly positive.

// ISO/IEC 23000-22:2024, Section 7.3.6.7:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is best to wait until ISO/IEC 23000-22:2024 is formally published. Its status is still Final Draft Internal Standard (FDIS) right now: https://www.iso.org/standard/87576.html

// - chroma is subsampled horizontally (i.e., 4:2:2 and 4:2:0) and cleanApertureWidth is odd
// - chroma is subsampled horizontally (i.e., 4:2:2 and 4:2:0) and left-most pixel is on an odd position
// - chroma is subsampled vertically (i.e., 4:2:0) and cleanApertureHeight is odd
// - chroma is subsampled vertically (i.e., 4:2:0) and topmost line is on an odd position
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For AVIF, the first and third conditions are too strict. They are equivalent to disallowing odd widths for 4:2:2 and 4:2:0 and disallowing odd heights for 4:2:0, but AV1 supports those two cases. In libavif we can consider ignoring the first and third conditions.

@@ -820,9 +827,10 @@ avifBool avifCleanApertureBoxConvertCropRect(avifCleanApertureBox * clap,
avifPixelFormat yuvFormat,
avifDiagnostics * diag)
{
(void)yuvFormat;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want to preserve the old behavior, we cannot ignore yuvFormat.

It would be useful to move lines 804-806 to a new function that takes const avifCropRect * cropRect and avifPixelFormat yuvFormat as input and returns the upsampleBeforeCropping boolean. Then we can call that new function here (to preserve the old behavior) and at line 804.

avifPixelFormat yuvFormat,
avifDiagnostics * diag)
{
// Keep the same pre-deprecation behavior.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not keep the old behavior exactly. The difference is the first and third conditions at lines 706-710. So to be precise, the comment should say "most of the pre-deprecation behavior".

If we ignore the first and third conditions as I suggested in my comment at line 710, then we keep the old behavior exactly.

@y-guyon
Copy link
Collaborator Author

y-guyon commented Sep 23, 2024

I need to think about this issue more to see if we should take a different approach in this pull request.

@wantehchang Did you find another approach?


*upsampleBeforeCropping = ((yuvFormat == AVIF_PIXEL_FORMAT_YUV420 || yuvFormat == AVIF_PIXEL_FORMAT_YUV422) &&
(cropRect->width % 2 || cropRect->x % 2)) ||
(yuvFormat == AVIF_PIXEL_FORMAT_YUV420 && (cropRect->height % 2 || cropRect->y % 2));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An alternative design is to remove the yuvFormat input parameter and the upsampleBeforeCropping output parameter from this function (avifCropRectFromCleanApertureBox), and then add another function that takes const avifCropRect * cropRect and yuvFormat as input parameters, and returns upsampleBeforeCropping as the return value.

Note that yuvFormat and upsampleBeforeCropping are only used in this statement (lines 804-806), so this statement can be cleanly moved to a separate function.

Another alternative is for libavif to upsample to 4:4:4 and crop automatically when necessary so that libavif users don't need to worry about this. But I am not sure if this is a good idea.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add another function that takes const avifCropRect * cropRect and yuvFormat as input parameters, and returns upsampleBeforeCropping as the return value

The issue with this new function and with the current avifImage::clap are that users can easily ignore them. The point of the "mandatory" upsampleBeforeCropping argument was to force users to at least consider upsampling (because there is no other function available to get a rect). But they can just ignore clap anyway so it has little effect.

Another alternative is for libavif to upsample to 4:4:4 and crop automatically when necessary so that libavif users don't need to worry about this. But I am not sure if this is a good idea.

I would lean towards that as a default behavior, and why not add an "ignoreClap" setting in avifDecoder to keep the old behavior back.
However existing files with clap will no longer display the same, in places where clap is ignored by users of libavif.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants