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

reformat_libyuv: use RAWToI444/RAWToJ444 if available #2598

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

jzern
Copy link
Collaborator

@jzern jzern commented Feb 7, 2025

These are available since libyuv 1903.

Bug: b:345259429

These are available since libyuv 1903.

Bug: b:345259429
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. Thanks!

It would be good to also have Vignesh or Yannis take a look.

@@ -80,6 +80,9 @@ unsigned int avifLibYUVVersion(void)
// These defines are used to create a NULL reference to libyuv functions that
// did not exist prior to a particular version of libyuv.
// Versions prior to 1755 are considered too old and not used (see CMakeLists.txt).
#if LIBYUV_VERSION < 1903
Copy link
Collaborator

Choose a reason for hiding this comment

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

Optional: RAWToJ444 was added in version 1902, but the Neon optimization was added later without bumping the version. And then RAWToI444 was added in version 1903. So it is fine to test 1903 here. I suggest citing the relevant CLs:

https://chromium-review.googlesource.com/c/libyuv/libyuv/+/6207845
https://chromium-review.googlesource.com/c/libyuv/libyuv/+/6220890
https://chromium-review.googlesource.com/c/libyuv/libyuv/+/6223658

See the comment at lines 96-97 as an example.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

See the comment at lines 96-97 as an example.

I'll add them, but they feel redundant given the LIBYUV_VERSION check. That and other examples are undocumented.

The gainmap sources use various color primaries.
@@ -991,6 +991,8 @@ void ToneMapImageAndCompareToReference(
&tone_mapped->clli, &diag);
ASSERT_EQ(result, AVIF_RESULT_OK)
<< avifResultToString(result) << " " << diag.error;
// libyuv RAWToJ444 uses BT.601 coefficients.
tone_mapped_rgb.avoidLibYUV = AVIF_TRUE;
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should look into this. RAWToJ444 should only be used when matrix_coefficients is BT.601. I remember the code in reformat_libyuv.c checks that properly. Let's double check.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I found the following code in reformat_libyuv.c at lines 276-284:

avifResult avifImageRGBToYUVLibYUV8bpc(avifImage * image, const avifRGBImage * rgb)
{
    assert((image->depth == 8) && (rgb->depth == 8));
    // libavif uses byte-order when describing pixel formats, such that the R in RGBA is the lowest address,
    // similar to PNG. libyuv orders in word-order, so libavif's RGBA would be referred to in libyuv as ABGR.
    // libyuv only handles BT.601 for RGB to YUV, and not all range/order/subsampling combinations.
    // BT.470BG has the same coefficients as BT.601.
    if ((image->matrixCoefficients == AVIF_MATRIX_COEFFICIENTS_BT470BG) || (image->matrixCoefficients == AVIF_MATRIX_COEFFICIENTS_BT601)) {

Is it not doing the right thing? Or is RAWToJ444 not accurate enough?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I found the following code in reformat_libyuv.c at lines 276-284:

avifResult avifImageRGBToYUVLibYUV8bpc(avifImage * image, const avifRGBImage * rgb)
{
    assert((image->depth == 8) && (rgb->depth == 8));
    // libavif uses byte-order when describing pixel formats, such that the R in RGBA is the lowest address,
    // similar to PNG. libyuv orders in word-order, so libavif's RGBA would be referred to in libyuv as ABGR.
    // libyuv only handles BT.601 for RGB to YUV, and not all range/order/subsampling combinations.
    // BT.470BG has the same coefficients as BT.601.
    if ((image->matrixCoefficients == AVIF_MATRIX_COEFFICIENTS_BT470BG) || (image->matrixCoefficients == AVIF_MATRIX_COEFFICIENTS_BT601)) {

Is it not doing the right thing? Or is RAWToJ444 not accurate enough?

With a single test image the output was bit exact. I didn't inspect the path for this test all that closely.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I found the following code in reformat_libyuv.c at lines 276-284:

avifResult avifImageRGBToYUVLibYUV8bpc(avifImage * image, const avifRGBImage * rgb)
{
    assert((image->depth == 8) && (rgb->depth == 8));
    // libavif uses byte-order when describing pixel formats, such that the R in RGBA is the lowest address,
    // similar to PNG. libyuv orders in word-order, so libavif's RGBA would be referred to in libyuv as ABGR.
    // libyuv only handles BT.601 for RGB to YUV, and not all range/order/subsampling combinations.
    // BT.470BG has the same coefficients as BT.601.
    if ((image->matrixCoefficients == AVIF_MATRIX_COEFFICIENTS_BT470BG) || (image->matrixCoefficients == AVIF_MATRIX_COEFFICIENTS_BT601)) {

Is it not doing the right thing? Or is RAWToJ444 not accurate enough?

With a single test image the output was bit exact. I didn't inspect the path for this test all that closely.

I also made an assumption about the files based on their names: colors_hdr_rec2020.avif and colors_wcg_hdr_rec2020.avif.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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


[ RUN      ] All/CreateGainMapTest.Create/8
PSNR (tone mapped vs reference): 99
PSNR (tone mapped vs reference): 54.0596
tests/gtest/avifgainmaptest.cc:1002: Failure
Expected: (psnr) >= (min_psnr), actual: 54.0596 vs 55
Google Test trace:
tests/gtest/avifgainmaptest.cc:973: hdr_headroom: 0.000000
PSNR (tone mapped vs reference): 54.0596
tests/gtest/avifgainmaptest.cc:1002: Failure
Expected: (psnr) >= (min_psnr), actual: 54.0596 vs 55
Google Test trace:
tests/gtest/avifgainmaptest.cc:973: hdr_headroom: 0.000000
PSNR (tone mapped vs reference): 99
[  FAILED  ] All/CreateGainMapTest.Create/8, where GetParam() = ("colors_sdr_srgb.avif", "colors_hdr_rec2020.avif", 1, 10, 1, 55, 100) (50 ms)
...
[ RUN      ] All/CreateGainMapTest.Create/10
PSNR (tone mapped vs reference): 58.7199
PSNR (tone mapped vs reference): 53.6957
tests/gtest/avifgainmaptest.cc:1002: Failure
Expected: (psnr) >= (min_psnr), actual: 53.6957 vs 55
Google Test trace:
tests/gtest/avifgainmaptest.cc:973: hdr_headroom: 0.000000
PSNR (tone mapped vs reference): 53.6957
tests/gtest/avifgainmaptest.cc:1002: Failure
Expected: (psnr) >= (min_psnr), actual: 53.6957 vs 55
Google Test trace:
tests/gtest/avifgainmaptest.cc:973: hdr_headroom: 0.000000
PSNR (tone mapped vs reference): 58.7199
[  FAILED  ] All/CreateGainMapTest.Create/10, where GetParam() = ("colors_sdr_srgb.avif", "colors_wcg_hdr_rec2020.avif", 1, 10, 1, 55, 80) (50 ms)

@jzern
Copy link
Collaborator Author

jzern commented Feb 7, 2025

With a single test image the output was bit exact. I didn't inspect the path for this test all that closely.

I'll look at this further. I only posted the workaround to make sure there were no other failures and was planning on coming back to this after looking at some other things.

@jzern
Copy link
Collaborator Author

jzern commented Feb 7, 2025

Prior to this change:

[ RUN      ] All/CreateGainMapTest.Create/8
PSNR (tone mapped vs reference): 99
PSNR (tone mapped vs reference): 60.8035
PSNR (tone mapped vs reference): 60.8035
PSNR (tone mapped vs reference): 99

With this change:

[ RUN      ] All/CreateGainMapTest.Create/8
PSNR (tone mapped vs reference): 99
PSNR (tone mapped vs reference): 54.0596
PSNR (tone mapped vs reference): 54.0596
PSNR (tone mapped vs reference): 99

At issue are some of the swaps, where the source is BT.601; the other steps are BT.2020 and are likely being skipped as you noted. I'll dump the images to have a look.

@jzern
Copy link
Collaborator Author

jzern commented Feb 7, 2025

Prior to this change:

[ RUN      ] All/CreateGainMapTest.Create/8
PSNR (tone mapped vs reference): 99
PSNR (tone mapped vs reference): 60.8035
PSNR (tone mapped vs reference): 60.8035
PSNR (tone mapped vs reference): 99

With this change:

[ RUN      ] All/CreateGainMapTest.Create/8
PSNR (tone mapped vs reference): 99
PSNR (tone mapped vs reference): 54.0596
PSNR (tone mapped vs reference): 54.0596
PSNR (tone mapped vs reference): 99

At issue are some of the swaps, where the source is BT.601; the other steps are BT.2020 and are likely being skipped as you noted. I'll dump the images to have a look.

Looking at the other CreateGainMapTests with -DCONFIG_LIBYUV=0 there are some changes to PSNR, but mostly in the 0.1-0.3dB range. These are high PSNR values and I haven't checked if the non-libyuv case uses float. This may be acceptable, but I'll look a little more closely.

@wantehchang wantehchang modified the milestone: v1.2.0 Feb 8, 2025
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