-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Update libavif #1381
Update libavif #1381
Conversation
* Update libavif for improved compression and speed * v1.0.0 deprecates usage of min and max-quantizers; we use `quality` and `qualityAlpha` instead * Renamed `maxSpeed` to `MAX_EFFORT` for better readability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor nit to avoid magic numbers, otherwise LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Aryan,
I will review this pull request tomorrow. Please wait for my review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Aryan,
I reviewed all the files that look human readable. For avif_enc.cpp, I read the entire file.
I suggest some changes. Note that where I suggest the name qualityAlpha
, you may replace it with alphaQuality
. (qualityAlpha
is the name used in avif/avif.h.)
@wantehchang I'll go through your reviews now, thanks for replying so quickly 😄 |
29cc9bc
to
642ac6d
Compare
Changes `cqlevel` to `quality`, and `cqAlphaLevel` to `qualityAlpha`
Hi Aryan, I am receiving notifications of changes to this pull request. I am afraid that I may miss something, so please ping me when you'd like me to review this pull request again. Thanks. |
@wantehchang Yep I'm just resolving conversations as and when I push changes, maybe that's why you're getting so many notifications. My mid-terms just got over so I finally have some time to work on the PR - I'll send you a review request when I finish! |
@wantehchang thanks for your reviews, I've fixed and refactored the code you suggested. Also, you mentioned on the AV1 Discussion forum:
I went through the avif.h documentation for the If so, then maybe a checkbox called "Enable sharp YUV chroma downsampling" can be used to toggle between |
@wantehchang I think we got |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Aryan,
I read avif_enc.cpp carefully. I tried to read index.tsx and meta.ts as much as I could, but I only skimmed through the parts in index.tsx that you didn't modify.
$(OUT_NODE_ENC_JS) $(OUT_NODE_ENC_MT_JS): ENVIRONMENT=node | ||
$(OUT_NODE_ENC_JS) $(OUT_ENC_JS): $(OUT_ENC_CPP) $(CODEC_DIR)/CMakeLists.txt $(LIBAOM_DIR)/CMakeLists.txt | ||
# ST-Encoding | ||
$(OUT_ENC_JS): $(OUT_ENC_CPP) $(CODEC_DIR)/CMakeLists.txt $(LIBAOM_DIR)/CMakeLists.txt $(LIBSHARPYUV) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed you pass -DCONFIG_AV1_HIGHBITDEPTH=0
to libaom (e.g., in line 47). Do you only support bit depth 8 when encoding AVIF?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, for all codecs on Squoosh.
Aryan wrote:
Some of those "(same as AVERAGE)" should be changed to "(same as AVERAGE in the current implementation)". The reason is that the average filter is the only downsampling filter that libavif uses automatically. The Sharp YUV downsampling filter was added later and we are not sure if it should be one of the automatically-used downsampling filters. NOTE: AVIF_CHROMA_DOWNSAMPLING_FASTEST will always be the same as AVERAGE.
Agreed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Just a few final minor issues.
do { \ | ||
if (val1 == val2) \ | ||
return val::null(); \ | ||
} while (false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: You can merge these two macros into RETURN_NULL_IF_FALSE
that takes a conditional expression as the argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's so much better than the current macro LOL, thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: I probably would not use a macro that saves only one line. But some people like to use this kind of macro so that the main flow of the code is not cluttered with error handling code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep that was my line of thinking. I'm pretty sure we'll be repeating that line again for other optimizations, so it's better to just have a macro for it.
// 100 = lossless | ||
int quality; | ||
// As above, but -1 means 'use quality' | ||
int qualityAlpha; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In a follow-up pull request, we should look into using the new autoTiling
option of the AVIF encoder.
I suggest Squoosh set autoTiling
to AVIF_TRUE
by default. (The default of autoTiling
in libavif is AVIF_FALSE
for backward compatibility.) The Squoosh UI can have a "manual tiling" box, which when checked, shows the tileRowsLog2
and tileColsLog2
fields (both default to 0, meaning no tiling).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha, I'll try to add it to this PR or at least make raise an issue for it. I assume autoTiling
automatically chooses the best tileRowsLog2
and tileColsLog2
, is there any more documentation about it that I can link to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless this requires just simple changes, I suggest filing an issue for this and implementing this in a follow-up pull request. The review of this pull request has been going on for a while. We need to watch out for "code review fatigue."
You understand autoTiling
correctly. The autoTiling
algorithm may be tweaked in the future, so we didn't document the current algorithm in the public header avif/avif.h. You can find the current algorithm in libavif/src/write.c:
if (encoder->autoTiling) {
// Use as many tiles as allowed by the minimum tile area requirement and impose a maximum
// of 8 tiles.
const int threads = 8;
avifSetTileConfiguration(threads, firstCell->width, firstCell->height, &encoder->data->tileRowsLog2, &encoder->data->tileColsLog2);
}
I do think all the automatic tiling algorithms have some common elements, such as imposing a minimum tile area or tile width and height, and potentially imposing a maximum number of tiles. But I am not sure if you need to mention this. You can, however, say that the use of tiles makes it easier for the decoder to decode an AVIF image with multiple threads in parallel.
@wantehchang implemented the changes, please give it a once-over if you find the time. |
Enabling the error: undefined symbol: setjmp (referenced by top-level compiled C/C++ code)
warning: Link with `-s LLD_REPORT_UNDEFINED` to get more information on undefined symbols
warning: To disable errors for undefined symbols use `-s ERROR_ON_UNDEFINED_SYMBOLS=0`
warning: _setjmp may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library It might be a compiler bug. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
any idea about when this will get merged and pushed to squoosh.app? thanks! |
you can always check at the bottom of the page where it says "changes approved" & you should click on "Details" to the right of deploy/netlify |
@wantehchang it won't block this PR, but is the experimental progressive stuff in |
@jakearchibald Hi Jake, You can expose the encoding of progressive (layered) images if it is clearly marked as experimental in the UI. There could be compression benefit to premultiplying alpha (see Note below). But the main benefit that after the image is decoded, we don't need to multiply it with alpha. We just need to multiply the backgroud with 1 - alpha. So the decoder has less work to do. Note: If the alpha channel has a lot of zero or near-zero values, the alpha-premultiplied image will have a lot of zero or near-zero values, so it should result in a smaller compressed file. |
Seems like single threaded AVIF encoding may have broken with this change. From my limited debugging it looks like a memory issue. The output handle seems to be no longer available when passing the value back to JS? 🤔
|
@jamsinclair thank you. We'll look into it. |
@wantehchang Thanks for the details! Do any browsers support rendering of progressive AVIF? (as in, rendering before the file has fully downloaded) |
@jakearchibald Jake: Chrome and Microsoft Edge (Edge 121 supports AVIF) support progressive rendering of AVIF layered images. Firefox doesn't support progressive rendering of AVIF layered images, based on inspection of its source code (by searching for "layer" and "progressive" in image/decoders/nsAVIFDecoder.{h,cpp}). I will get back to you on Safari's support. |
It should be supported in Safari to the best of my knowledge. |
Chrome support at least makes it interesting 😀 |
quality
andqualityAlpha
insteadmaxSpeed
toMAX_EFFORT
for better readability