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

Layered encoding support #1100

Merged
merged 3 commits into from
Jan 20, 2023

Conversation

tongyuantongyu
Copy link
Contributor

This is the third part of #761.

Layered image can be encoded by calling avifEncoderAddImage() multiple times, one layer per call.

@y-guyon:

  • Rational to keep avifScalingMode: In very early version of Support for Progressive AVIF encoding #761 avifScalingMode is simply an alias of libaom's AOM_SCALING_MODE, and I later changed it to a struct representing a fraction. As @joedrago said directly using what libaom offers is not so good as libavif also supports other codecs, and available AOM_SCALING_MODE-s are also rather some arbitrary selected values instead of the only values supported by AV1. We may define some commonly used avifScalingMode as static constants for convenience, anyway.
  • AVIF_ADD_IMAGE_FLAG_LAYER: I found that I don't need this flag. We know whether we are dealing layer image by checking encoder->extraLayerCount.
  • Encoding of layered grid do works, and libavif decoder also decodes it correctly, but if you are concerned about corner cases, we can disable it for now.

@wantehchang:
This PR currently rely on libaom to scale the layers internally, so it's restricted to the modes defined by AOM_SCALING_MODE. Also there's still a bug in libaom's internal scaler that it doesn't scale YUV420 images with 4n+2 dimensions correctly. But other than that it looks good. Also once #1069 is done, directly encoding layers of different dimensions should also work.

Copy link
Collaborator

@y-guyon y-guyon left a comment

Choose a reason for hiding this comment

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

Thanks for this PR.

Encoding of layered grid do works, and libavif decoder also decodes it correctly, but if you are concerned about corner cases, we can disable it for now.

Let's keep them and rely on fuzzing to detect issues.

@@ -1026,6 +1034,8 @@ struct avifCodecSpecificOptions;
// image in less bytes. AVIF_SPEED_DEFAULT means "Leave the AV1 codec to its default speed settings"./
// If avifEncoder uses rav1e, the speed value is directly passed through (0-10). If libaom is used,
// a combination of settings are tweaked to simulate this speed range.
// * Extra layer: [0 - AVIF_MAX_AV1_LAYER_COUNT-1]. Non-zero value indicates a layered (progressive)
// image.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I suggest [0..AVIF_MAX_AV1_LAYER_COUNT[ or [0:AVIF_MAX_AV1_LAYER_COUNT[ or [0..AVIF_MAX_AV1_LAYER_COUNT) or [0:AVIF_MAX_AV1_LAYER_COUNT) or [0..AVIF_MAX_AV1_LAYER_COUNT - 1] or [0:AVIF_MAX_AV1_LAYER_COUNT - 1]

Same in src/write.c

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm following style of other fields above. Do you think [0 - AVIF_MAX_AV1_LAYER_COUNT) is OK?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm following style of other fields above.

Ah right, I missed these.

Do you think [0 - AVIF_MAX_AV1_LAYER_COUNT) is OK?

Yes.

include/avif/avif.h Outdated Show resolved Hide resolved
src/codec_aom.c Outdated Show resolved Hide resolved
src/codec_aom.c Outdated Show resolved Hide resolved
src/codec_aom.c Outdated Show resolved Hide resolved
src/write.c Outdated Show resolved Hide resolved
src/write.c Show resolved Hide resolved
tests/gtest/avifprogressivetest.cc Show resolved Hide resolved
}

// TODO Check decoder->image and image are similar,
// and better quality layer is more similar.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Extra space

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This space tells my IDE that this line is the continuation of the TODO above. I can remove it anyway.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I suggest to align the text then:

    // TODO Check decoder->image and image are similar,
    //      and better quality layer is more similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

src/write.c Outdated
}
if (memcmp(&lastEncoder->heightScale, &encoder->heightScale, sizeof(avifScalingMode)) != 0) {
*encoderChanges |= AVIF_ENCODER_CHANGE_HEIGHT_SCALE;
if (memcmp(&lastEncoder->scaleMode, &encoder->scaleMode, sizeof(avifScalingMode)) != 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Note: This is a false positive in case lastEncoder->scaleMode = { {1, 1}, {1, 1} } and lastEncoder->scaleMode = { {2, 2}, {3, 3} } but this is not important, leave it as is.

src/write.c Show resolved Hide resolved
@wantehchang
Copy link
Collaborator

Yannis: Thank you for reviewing this pull request. I'd like to review this PR, too. Please wait for my review.

Yuan: Could you confirm that this PR does not require #1069?

@tongyuantongyu
Copy link
Contributor Author

Yuan: Could you confirm that this PR does not require #1069?

Yes I can confirm this PR does not require #1069, as the unit tests shows. I believe real usage wants #1069 as well, anyway.

wantehchang added a commit to wantehchang/libavif that referenced this pull request Jan 11, 2023
Originally reported by Yuan Tong in
AOMediaCodec#1100.
wantehchang added a commit to wantehchang/libavif that referenced this pull request Jan 11, 2023
Originally reported by Yuan Tong in
AOMediaCodec#1100.
wantehchang added a commit that referenced this pull request Jan 12, 2023
Originally reported by Yuan Tong in
#1100.
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.

LGTM. Thank you very much for your contribution.

I did the code review at https://aomedia-review.googlesource.com/c/libavif/+/167643.

@wantehchang wantehchang merged commit 5d16f1f into AOMediaCodec:main Jan 20, 2023
TEST_F(ProgressiveTest, DimensionChange) {
if (avifLibYUVVersion() == 0) {
GTEST_SKIP() << "libyuv not available, skip test.";
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

@tongyuantongyu Yuan: I guess the reason we need to skip this test when libyuv is not available is because this test needs the avifImageScale() function, which is only implemented if libyuv is available. Correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes.
I just noticed the assertion failure when using libaom head as well. Seems like a regression after v3.5.0 release.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I have only tested with libaom v3.5.0 and v3.6.0-rc1. If it's a regression, I can do a git bisect.

Copy link
Collaborator

Choose a reason for hiding this comment

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

git bisect says:

fbebe9d771f485272d6dd9f3829d9389160d89e1 is the first bad commit
commit fbebe9d771f485272d6dd9f3829d9389160d89e1
Author: chiyotsai <[email protected]>
Date:   Mon May 23 13:31:41 2022 -0700

    RESIZE_MODE: Fix incorrect strides being used for motion search
    
    Currently during motion search, the encoder always assumes that the ref
    frame's stride is the same as that of source frame. But this assumption
    breaks when resize mode/superres feature is turned on, leading to
    unexpected motion search result and invalid memory access.
    
    This commit actively checks for the ref stride with what's stored in
    MotionVectorSearchParams::search_site_config, and creates a new
    search_site_config if there is a mismatch.
    
    BUG=aomedia:3283
    
    Change-Id: Ia99a88326bf716027b5a652ec519fb13cfa0a345

 av1/av1.cmake                      |   1 +
 av1/encoder/block.h                |  10 ++++
 av1/encoder/encoder.c              |  13 -----
 av1/encoder/mcomp.c                |   2 +
 av1/encoder/mcomp.h                | 111 ++++++++++---------------------------
 av1/encoder/mcomp_structs.h        |  83 +++++++++++++++++++++++++++
 av1/encoder/motion_search_facade.c |  35 ++++++++----
 av1/encoder/motion_search_facade.h |  22 ++++++++
 av1/encoder/nonrd_pickmode.c       |   9 ++-
 av1/encoder/temporal_filter.c      |   5 +-
 10 files changed, 182 insertions(+), 109 deletions(-)
 create mode 100644 av1/encoder/mcomp_structs.h

But that is the commit that added the assertion that fails. I will ask Chi Yo (the author of that commit) about that assertion.

@tongyuantongyu tongyuantongyu deleted the layered_encoding branch September 13, 2023 12:36
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.

3 participants