⚝
One Hat Cyber Team
⚝
Your IP:
216.73.216.23
Server IP:
178.33.27.10
Server:
Linux cpanel.dev-unit.com 3.10.0-1160.108.1.el7.x86_64 #1 SMP Thu Jan 25 16:17:31 UTC 2024 x86_64
Server Software:
Apache/2.4.57 (Unix) OpenSSL/1.0.2k-fips
PHP Version:
8.2.11
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
local
/
src
/
libavif-0.11.1
/
tests
/
gtest
/
View File Name :
avifrgbtoyuvtest.cc
// Copyright 2022 Google LLC. All rights reserved. // SPDX-License-Identifier: BSD-2-Clause #include <algorithm> #include <cmath> #include <memory> #include <tuple> #include "avif/avif.h" #include "aviftest_helpers.h" #include "gtest/gtest.h" using ::testing::Combine; using ::testing::Values; using ::testing::ValuesIn; namespace libavif { namespace { //------------------------------------------------------------------------------ constexpr uint32_t kModifierSize = 4 * 4; // Modifies the pixel values of a channel in image by modifier[] (row-ordered). template <typename PixelType> void ModifyImageChannel(avifRGBImage* image, uint32_t channel_offset, const uint8_t modifier[kModifierSize]) { const uint32_t channel_count = avifRGBFormatChannelCount(image->format); assert(channel_offset < channel_count); for (uint32_t y = 0, i = 0; y < image->height; ++y) { PixelType* pixel = reinterpret_cast<PixelType*>(image->pixels + image->rowBytes * y); for (uint32_t x = 0; x < image->width; ++x, ++i) { pixel[channel_offset] += modifier[i % kModifierSize]; pixel += channel_count; } } } void ModifyImageChannel(avifRGBImage* image, uint32_t channel_offset, const uint8_t modifier[kModifierSize]) { if (image->depth <= 8) { ModifyImageChannel<uint8_t>(image, channel_offset, modifier); } else { ModifyImageChannel<uint16_t>(image, channel_offset, modifier); } } // Accumulates stats about the differences between the images a and b. template <typename PixelType> void GetDiffSumAndSqDiffSum(const avifRGBImage& a, const avifRGBImage& b, int64_t* diff_sum, int64_t* abs_diff_sum, int64_t* sq_diff_sum, int64_t* max_abs_diff) { const uint32_t channel_count = avifRGBFormatChannelCount(a.format); for (uint32_t y = 0; y < a.height; ++y) { const PixelType* row_a = reinterpret_cast<PixelType*>(a.pixels + a.rowBytes * y); const PixelType* row_b = reinterpret_cast<PixelType*>(b.pixels + b.rowBytes * y); for (uint32_t x = 0; x < a.width * channel_count; ++x) { const int64_t diff = static_cast<int64_t>(row_b[x]) - static_cast<int64_t>(row_a[x]); *diff_sum += diff; *abs_diff_sum += std::abs(diff); *sq_diff_sum += diff * diff; *max_abs_diff = std::max(*max_abs_diff, std::abs(diff)); } } } void GetDiffSumAndSqDiffSum(const avifRGBImage& a, const avifRGBImage& b, int64_t* diff_sum, int64_t* abs_diff_sum, int64_t* sq_diff_sum, int64_t* max_abs_diff) { (a.depth <= 8) ? GetDiffSumAndSqDiffSum<uint8_t>(a, b, diff_sum, abs_diff_sum, sq_diff_sum, max_abs_diff) : GetDiffSumAndSqDiffSum<uint16_t>( a, b, diff_sum, abs_diff_sum, sq_diff_sum, max_abs_diff); } // Returns the Peak Signal-to-Noise Ratio from accumulated stats. double GetPsnr(double sq_diff_sum, double num_diffs, double max_abs_diff) { if (sq_diff_sum == 0.) { return 99.; // Lossless. } const double distortion = sq_diff_sum / (num_diffs * max_abs_diff * max_abs_diff); return (distortion > 0.) ? std::min(-10 * std::log10(distortion), 98.9) : 98.9; // Not lossless. } //------------------------------------------------------------------------------ // To exercise the chroma subsampling loss, the input samples must differ in // each of the RGB channels. Chroma subsampling expects the input RGB channels // to be correlated to minimize the quality loss. constexpr uint8_t kRedNoise[kModifierSize] = { 7, 14, 11, 5, // Random permutation of 16 values. 4, 6, 8, 15, // 2, 9, 13, 3, // 12, 1, 10, 0}; constexpr uint8_t kGreenNoise[kModifierSize] = { 3, 2, 12, 15, // Random permutation of 16 values 14, 10, 7, 13, // that is somewhat close to kRedNoise. 5, 1, 9, 0, // 8, 4, 11, 6}; constexpr uint8_t kBlueNoise[kModifierSize] = { 0, 8, 14, 9, // Random permutation of 16 values 13, 12, 2, 7, // that is somewhat close to kGreenNoise. 3, 1, 11, 10, // 6, 15, 5, 4}; //------------------------------------------------------------------------------ class RGBToYUVTest : public testing::TestWithParam<std::tuple< /*rgb_depth=*/int, /*yuv_depth=*/int, avifRGBFormat, avifPixelFormat, avifRange, avifMatrixCoefficients, avifChromaDownsampling, /*add_noise=*/bool, /*rgb_step=*/uint32_t, /*max_abs_average_diff=*/double, /*min_psnr=*/double>> {}; // Converts from RGB to YUV and back to RGB for all RGB combinations, separated // by a color step for reasonable timing. If add_noise is true, also applies // some noise to the input samples to exercise chroma subsampling. TEST_P(RGBToYUVTest, ConvertWholeRange) { const int rgb_depth = std::get<0>(GetParam()); const int yuv_depth = std::get<1>(GetParam()); const avifRGBFormat rgb_format = std::get<2>(GetParam()); const avifPixelFormat yuv_format = std::get<3>(GetParam()); const avifRange yuv_range = std::get<4>(GetParam()); const avifMatrixCoefficients matrix_coefficients = std::get<5>(GetParam()); const avifChromaDownsampling chroma_downsampling = std::get<6>(GetParam()); // Whether to add noise to the input RGB samples. Should only impact // subsampled chroma (4:2:2 and 4:2:0). const bool add_noise = std::get<7>(GetParam()); // Testing each RGB combination would be more accurate but results are similar // with faster settings. const uint32_t rgb_step = std::get<8>(GetParam()); // Thresholds to pass. const double max_abs_average_diff = std::get<9>(GetParam()); const double min_psnr = std::get<10>(GetParam()); // Deduced constants. const bool is_monochrome = (yuv_format == AVIF_PIXEL_FORMAT_YUV400); // If so, only test grey input. const uint32_t rgb_max = (1 << rgb_depth) - 1; // The YUV upsampling treats the first and last rows and columns differently // than the remaining pairs of rows and columns. An image of 16 pixels is used // to test all these possibilities. static constexpr int width = 4; static constexpr int height = 4; std::unique_ptr<avifImage, decltype(&avifImageDestroy)> yuv( avifImageCreate(width, height, yuv_depth, yuv_format), avifImageDestroy); yuv->matrixCoefficients = matrix_coefficients; yuv->yuvRange = yuv_range; testutil::AvifRgbImage src_rgb(yuv.get(), rgb_depth, rgb_format); src_rgb.chromaDownsampling = chroma_downsampling; testutil::AvifRgbImage dst_rgb(yuv.get(), rgb_depth, rgb_format); const testutil::RgbChannelOffsets offsets = testutil::GetRgbChannelOffsets(rgb_format); // Alpha values are not tested here. Keep it opaque. if (avifRGBFormatHasAlpha(src_rgb.format)) { testutil::FillImageChannel(&src_rgb, offsets.a, rgb_max); } // Estimate the loss from converting RGB values to YUV and back. int64_t diff_sum = 0, abs_diff_sum = 0, sq_diff_sum = 0, max_abs_diff = 0; int64_t num_diffs = 0; const uint32_t max_value = rgb_max - (add_noise ? 15 : 0); for (uint32_t r = 0; r < max_value + rgb_step; r += rgb_step) { r = std::min(r, max_value); // Test the maximum sample value even if it is // not a multiple of rgb_step. testutil::FillImageChannel(&src_rgb, offsets.r, r); if (add_noise) { ModifyImageChannel(&src_rgb, offsets.r, kRedNoise); } if (is_monochrome) { // Test only greyish input when converting to a single channel. testutil::FillImageChannel(&src_rgb, offsets.g, r); testutil::FillImageChannel(&src_rgb, offsets.b, r); if (add_noise) { ModifyImageChannel(&src_rgb, offsets.g, kGreenNoise); ModifyImageChannel(&src_rgb, offsets.b, kBlueNoise); } ASSERT_EQ(avifImageRGBToYUV(yuv.get(), &src_rgb), AVIF_RESULT_OK); ASSERT_EQ(avifImageYUVToRGB(yuv.get(), &dst_rgb), AVIF_RESULT_OK); GetDiffSumAndSqDiffSum(src_rgb, dst_rgb, &diff_sum, &abs_diff_sum, &sq_diff_sum, &max_abs_diff); num_diffs += src_rgb.width * src_rgb.height * 3; // Alpha is lossless. } else { for (uint32_t g = 0; g < max_value + rgb_step; g += rgb_step) { g = std::min(g, max_value); testutil::FillImageChannel(&src_rgb, offsets.g, g); if (add_noise) { ModifyImageChannel(&src_rgb, offsets.g, kGreenNoise); } for (uint32_t b = 0; b < max_value + rgb_step; b += rgb_step) { b = std::min(b, max_value); testutil::FillImageChannel(&src_rgb, offsets.b, b); if (add_noise) { ModifyImageChannel(&src_rgb, offsets.b, kBlueNoise); } const avifResult result = avifImageRGBToYUV(yuv.get(), &src_rgb); if (result == AVIF_RESULT_NOT_IMPLEMENTED && src_rgb.chromaDownsampling == AVIF_CHROMA_DOWNSAMPLING_SHARP_YUV) { GTEST_SKIP() << "libsharpyuv unavailable, skip test."; } ASSERT_EQ(result, AVIF_RESULT_OK); ASSERT_EQ(avifImageYUVToRGB(yuv.get(), &dst_rgb), AVIF_RESULT_OK); GetDiffSumAndSqDiffSum(src_rgb, dst_rgb, &diff_sum, &abs_diff_sum, &sq_diff_sum, &max_abs_diff); num_diffs += src_rgb.width * src_rgb.height * 3; // Alpha is lossless. } } } } // Stats and thresholds. // Note: The thresholds defined in this test are calibrated for libyuv fast // paths. See reformat_libyuv.c. Slower non-libyuv conversions in // libavif have a higher precision (using floating point operations). const double average_diff = static_cast<double>(diff_sum) / static_cast<double>(num_diffs); const double average_abs_diff = static_cast<double>(abs_diff_sum) / static_cast<double>(num_diffs); const double psnr = GetPsnr(static_cast<double>(sq_diff_sum), static_cast<double>(num_diffs), rgb_max); EXPECT_LE(std::abs(average_diff), max_abs_average_diff); EXPECT_GE(psnr, min_psnr); // Print stats for convenience and easier threshold tuning. static constexpr const char* kAvifRgbFormatToString[] = { "RGB", "RGBA", "ARGB", "BGR", "BGRA", "ABGR"}; std::cout << " RGB " << rgb_depth << " bits, YUV " << yuv_depth << " bits, " << kAvifRgbFormatToString[rgb_format] << ", " << avifPixelFormatToString(yuv_format) << ", " << (yuv_range ? "full" : "lmtd") << ", MC " << matrix_coefficients << ", " << (add_noise ? "noisy" : "plain") << ", avg " << average_diff << ", abs avg " << average_abs_diff << ", max " << max_abs_diff << ", PSNR " << psnr << "dB" << std::endl; } // Converts from RGB to YUV and back to RGB for multiple buffer dimensions to // exercise stride computation and subsampling edge cases. TEST_P(RGBToYUVTest, ConvertWholeBuffer) { const int rgb_depth = std::get<0>(GetParam()); const int yuv_depth = std::get<1>(GetParam()); const avifRGBFormat rgb_format = std::get<2>(GetParam()); const avifPixelFormat yuv_format = std::get<3>(GetParam()); const avifRange yuv_range = std::get<4>(GetParam()); const avifMatrixCoefficients matrix_coefficients = std::get<5>(GetParam()); const avifChromaDownsampling chroma_downsampling = std::get<6>(GetParam()); // Whether to add noise to the input RGB samples. const bool add_noise = std::get<7>(GetParam()); // Threshold to pass. const double min_psnr = std::get<9>(GetParam()); // Deduced constants. const bool is_monochrome = (yuv_format == AVIF_PIXEL_FORMAT_YUV400); // If so, only test grey input. const uint32_t rgb_max = (1 << rgb_depth) - 1; // Estimate the loss from converting RGB values to YUV and back. int64_t diff_sum = 0, abs_diff_sum = 0, sq_diff_sum = 0, max_abs_diff = 0; int64_t num_diffs = 0; for (int width : {1, 2, 127}) { for (int height : {1, 2, 251}) { std::unique_ptr<avifImage, decltype(&avifImageDestroy)> yuv( avifImageCreate(width, height, yuv_depth, yuv_format), avifImageDestroy); yuv->matrixCoefficients = matrix_coefficients; yuv->yuvRange = yuv_range; testutil::AvifRgbImage src_rgb(yuv.get(), rgb_depth, rgb_format); src_rgb.chromaDownsampling = chroma_downsampling; testutil::AvifRgbImage dst_rgb(yuv.get(), rgb_depth, rgb_format); const testutil::RgbChannelOffsets offsets = testutil::GetRgbChannelOffsets(rgb_format); // Fill the input buffer with whatever content. testutil::FillImageChannel(&src_rgb, offsets.r, /*value=*/0); testutil::FillImageChannel(&src_rgb, offsets.g, /*value=*/0); testutil::FillImageChannel(&src_rgb, offsets.b, /*value=*/0); if (add_noise) { ModifyImageChannel(&src_rgb, offsets.r, kRedNoise); ModifyImageChannel(&src_rgb, offsets.g, is_monochrome ? kRedNoise : kGreenNoise); ModifyImageChannel(&src_rgb, offsets.b, is_monochrome ? kRedNoise : kBlueNoise); } // Alpha values are not tested here. Keep it opaque. if (avifRGBFormatHasAlpha(src_rgb.format)) { testutil::FillImageChannel(&src_rgb, offsets.a, rgb_max); } const avifResult result = avifImageRGBToYUV(yuv.get(), &src_rgb); if (result == AVIF_RESULT_NOT_IMPLEMENTED && src_rgb.chromaDownsampling == AVIF_CHROMA_DOWNSAMPLING_SHARP_YUV) { GTEST_SKIP() << "libsharpyuv unavailable, skip test."; } ASSERT_EQ(result, AVIF_RESULT_OK); ASSERT_EQ(avifImageYUVToRGB(yuv.get(), &dst_rgb), AVIF_RESULT_OK); GetDiffSumAndSqDiffSum(src_rgb, dst_rgb, &diff_sum, &abs_diff_sum, &sq_diff_sum, &max_abs_diff); num_diffs += src_rgb.width * src_rgb.height * 3; } } // max_abs_average_diff is not tested here because it is not meaningful for // only 3*3 conversions as it takes the maximum difference per conversion. // PSNR is averaged on all pixels so it can be tested here. EXPECT_GE(GetPsnr(static_cast<double>(sq_diff_sum), static_cast<double>(num_diffs), rgb_max), min_psnr); } constexpr avifRGBFormat kAllRgbFormats[] = { AVIF_RGB_FORMAT_RGB, AVIF_RGB_FORMAT_RGBA, AVIF_RGB_FORMAT_ARGB, AVIF_RGB_FORMAT_BGR, AVIF_RGB_FORMAT_BGRA, AVIF_RGB_FORMAT_ABGR}; // avifMatrixCoefficients-typed constants for testing::Values() to work on MSVC. constexpr avifMatrixCoefficients kMatrixCoefficientsBT601 = AVIF_MATRIX_COEFFICIENTS_BT601; constexpr avifMatrixCoefficients kMatrixCoefficientsBT709 = AVIF_MATRIX_COEFFICIENTS_BT709; constexpr avifMatrixCoefficients kMatrixCoefficientsIdentity = AVIF_MATRIX_COEFFICIENTS_IDENTITY; // This is the default avifenc setup when encoding from 8b PNG files to AVIF. INSTANTIATE_TEST_SUITE_P( DefaultFormat, RGBToYUVTest, Combine(/*rgb_depth=*/Values(8), /*yuv_depth=*/Values(8), Values(AVIF_RGB_FORMAT_RGBA), Values(AVIF_PIXEL_FORMAT_YUV420), Values(AVIF_RANGE_FULL), Values(kMatrixCoefficientsBT601), Values(AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC), /*add_noise=*/Values(true), /*rgb_step=*/Values(3), /*max_abs_average_diff=*/Values(0.1), // The color drift is almost // centered. /*min_psnr=*/Values(36.) // Subsampling distortion is acceptable. )); // Keeping RGB samples in full range and same or higher bit depth should not // bring any loss in the roundtrip. INSTANTIATE_TEST_SUITE_P(Identity8b, RGBToYUVTest, Combine(/*rgb_depth=*/Values(8), /*yuv_depth=*/Values(8, 10, 12), ValuesIn(kAllRgbFormats), Values(AVIF_PIXEL_FORMAT_YUV444), Values(AVIF_RANGE_FULL), Values(kMatrixCoefficientsIdentity), Values(AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC), /*add_noise=*/Values(true), /*rgb_step=*/Values(31), /*max_abs_average_diff=*/Values(0.), /*min_psnr=*/Values(99.))); INSTANTIATE_TEST_SUITE_P(Identity10b, RGBToYUVTest, Combine(/*rgb_depth=*/Values(10), /*yuv_depth=*/Values(10, 12), ValuesIn(kAllRgbFormats), Values(AVIF_PIXEL_FORMAT_YUV444), Values(AVIF_RANGE_FULL), Values(kMatrixCoefficientsIdentity), Values(AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC), /*add_noise=*/Values(true), /*rgb_step=*/Values(101), /*max_abs_average_diff=*/Values(0.), /*min_psnr=*/Values(99.))); INSTANTIATE_TEST_SUITE_P(Identity12b, RGBToYUVTest, Combine(/*rgb_depth=*/Values(12), /*yuv_depth=*/Values(12), ValuesIn(kAllRgbFormats), Values(AVIF_PIXEL_FORMAT_YUV444), Values(AVIF_RANGE_FULL), Values(kMatrixCoefficientsIdentity), Values(AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC), /*add_noise=*/Values(true), /*rgb_step=*/Values(401), /*max_abs_average_diff=*/Values(0.), /*min_psnr=*/Values(99.))); // 4:4:4 and chroma subsampling have similar distortions on plain color inputs. INSTANTIATE_TEST_SUITE_P( PlainAnySubsampling8b, RGBToYUVTest, Combine( /*rgb_depth=*/Values(8), /*yuv_depth=*/Values(8), ValuesIn(kAllRgbFormats), Values(AVIF_PIXEL_FORMAT_YUV444, AVIF_PIXEL_FORMAT_YUV422, AVIF_PIXEL_FORMAT_YUV420), Values(AVIF_RANGE_FULL), Values(kMatrixCoefficientsBT601), Values(AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC), /*add_noise=*/Values(false), /*rgb_step=*/Values(17), /*max_abs_average_diff=*/Values(0.02), // The color drift is centered. /*min_psnr=*/Values(49.) // RGB>YUV>RGB distortion is barely // noticeable. )); // Converting grey RGB samples to full-range monochrome of same or greater bit // depth should be lossless. INSTANTIATE_TEST_SUITE_P(MonochromeLossless8b, RGBToYUVTest, Combine(/*rgb_depth=*/Values(8), /*yuv_depth=*/Values(8, 10, 12), ValuesIn(kAllRgbFormats), Values(AVIF_PIXEL_FORMAT_YUV400), Values(AVIF_RANGE_FULL), Values(kMatrixCoefficientsBT601), Values(AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC), /*add_noise=*/Values(false), /*rgb_step=*/Values(1), /*max_abs_average_diff=*/Values(0.), /*min_psnr=*/Values(99.))); INSTANTIATE_TEST_SUITE_P(MonochromeLossless10b, RGBToYUVTest, Combine(/*rgb_depth=*/Values(10), /*yuv_depth=*/Values(10, 12), ValuesIn(kAllRgbFormats), Values(AVIF_PIXEL_FORMAT_YUV400), Values(AVIF_RANGE_FULL), Values(kMatrixCoefficientsBT601), Values(AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC), /*add_noise=*/Values(false), /*rgb_step=*/Values(1), /*max_abs_average_diff=*/Values(0.), /*min_psnr=*/Values(99.))); INSTANTIATE_TEST_SUITE_P(MonochromeLossless12b, RGBToYUVTest, Combine(/*rgb_depth=*/Values(12), /*yuv_depth=*/Values(12), ValuesIn(kAllRgbFormats), Values(AVIF_PIXEL_FORMAT_YUV400), Values(AVIF_RANGE_FULL), Values(kMatrixCoefficientsBT601), Values(AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC), /*add_noise=*/Values(false), /*rgb_step=*/Values(1), /*max_abs_average_diff=*/Values(0.), /*min_psnr=*/Values(99.))); // Can be used to print the drift of all RGB to YUV conversion possibilities. // Also used for coverage. INSTANTIATE_TEST_SUITE_P( SharpYuv8Bit, RGBToYUVTest, Combine( /*rgb_depth=*/Values(8), /*yuv_depth=*/Values(8, 10, 12), ValuesIn(kAllRgbFormats), Values(AVIF_PIXEL_FORMAT_YUV420), Values(AVIF_RANGE_LIMITED, AVIF_RANGE_FULL), Values(kMatrixCoefficientsBT601, kMatrixCoefficientsBT709), Values(AVIF_CHROMA_DOWNSAMPLING_SHARP_YUV), /*add_noise=*/Values(true), /*rgb_step=*/Values(17), /*max_abs_average_diff=*/Values(1.2), // Sharp YUV introduces some // color shift. /*min_psnr=*/Values(34.) // SharpYuv distortion is acceptable. )); INSTANTIATE_TEST_SUITE_P( SharpYuv10Bit, RGBToYUVTest, Combine( /*rgb_depth=*/Values(10), /*yuv_depth=*/Values(8, 10, 12), ValuesIn(kAllRgbFormats), Values(AVIF_PIXEL_FORMAT_YUV420), Values(AVIF_RANGE_LIMITED, AVIF_RANGE_FULL), Values(kMatrixCoefficientsBT601), Values(AVIF_CHROMA_DOWNSAMPLING_SHARP_YUV), /*add_noise=*/Values(true), /*rgb_step=*/Values(211), // High or it would be too slow. /*max_abs_average_diff=*/Values(1.2), // Sharp YUV introduces some // color shift. /*min_psnr=*/Values(34.) // SharpYuv distortion is acceptable. )); INSTANTIATE_TEST_SUITE_P( SharpYuv12Bit, RGBToYUVTest, Combine( /*rgb_depth=*/Values(12), /*yuv_depth=*/Values(8, 10, 12), ValuesIn(kAllRgbFormats), Values(AVIF_PIXEL_FORMAT_YUV420), Values(AVIF_RANGE_LIMITED, AVIF_RANGE_FULL), Values(kMatrixCoefficientsBT601), Values(AVIF_CHROMA_DOWNSAMPLING_SHARP_YUV), /*add_noise=*/Values(true), /*rgb_step=*/Values(840), // High or it would be too slow. /*max_abs_average_diff=*/Values(1.2), // Sharp YUV introduces some // color shift. /*min_psnr=*/Values(34.) // SharpYuv distortion is acceptable. )); // Can be used to print the drift of all RGB to YUV conversion possibilities. // Also used for coverage. INSTANTIATE_TEST_SUITE_P( All8b, RGBToYUVTest, Combine(/*rgb_depth=*/Values(8), /*yuv_depth=*/Values(8, 10, 12), ValuesIn(kAllRgbFormats), Values(AVIF_PIXEL_FORMAT_YUV444, AVIF_PIXEL_FORMAT_YUV422, AVIF_PIXEL_FORMAT_YUV420), Values(AVIF_RANGE_LIMITED, AVIF_RANGE_FULL), Values(kMatrixCoefficientsBT601), Values(AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC), /*add_noise=*/Values(false, true), /*rgb_step=*/Values(61), // High or it would be too slow. /*max_abs_average_diff=*/Values(1.), // Not very accurate because // of high rgb_step. /*min_psnr=*/Values(36.))); INSTANTIATE_TEST_SUITE_P( All10b, RGBToYUVTest, Combine(/*rgb_depth=*/Values(10), /*yuv_depth=*/Values(8, 10, 12), ValuesIn(kAllRgbFormats), Values(AVIF_PIXEL_FORMAT_YUV444, AVIF_PIXEL_FORMAT_YUV422, AVIF_PIXEL_FORMAT_YUV420), Values(AVIF_RANGE_LIMITED, AVIF_RANGE_FULL), Values(kMatrixCoefficientsBT601), Values(AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC), /*add_noise=*/Values(false, true), /*rgb_step=*/Values(211), // High or it would be too slow. /*max_abs_average_diff=*/Values(0.2), // Not very accurate because // of high rgb_step. /*min_psnr=*/Values(47.))); INSTANTIATE_TEST_SUITE_P( All12b, RGBToYUVTest, Combine(/*rgb_depth=*/Values(12), /*yuv_depth=*/Values(8, 10, 12), ValuesIn(kAllRgbFormats), Values(AVIF_PIXEL_FORMAT_YUV444, AVIF_PIXEL_FORMAT_YUV422, AVIF_PIXEL_FORMAT_YUV420), Values(AVIF_RANGE_LIMITED, AVIF_RANGE_FULL), Values(kMatrixCoefficientsBT601), Values(AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC), /*add_noise=*/Values(false, true), /*rgb_step=*/Values(809), // High or it would be too slow. /*max_abs_average_diff=*/Values(0.3), // Not very accurate because // of high rgb_step. /*min_psnr=*/Values(52.))); // TODO: Test other matrix coefficients than identity and bt.601. // This was used to estimate the quality loss of libyuv for RGB-to-YUV. // Disabled because it takes a few minutes. INSTANTIATE_TEST_SUITE_P( DISABLED_All8bTo8b, RGBToYUVTest, Combine(/*rgb_depth=*/Values(8), /*yuv_depth=*/Values(8), ValuesIn(kAllRgbFormats), Values(AVIF_PIXEL_FORMAT_YUV444, AVIF_PIXEL_FORMAT_YUV422, AVIF_PIXEL_FORMAT_YUV420, AVIF_PIXEL_FORMAT_YUV400), Values(AVIF_RANGE_FULL, AVIF_RANGE_LIMITED), Values(kMatrixCoefficientsBT601), Values(AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC), /*add_noise=*/Values(false, true), /*rgb_step=*/Values(3), // way faster and 99% similar to rgb_step=1 /*max_abs_average_diff=*/Values(10.), /*min_psnr=*/Values(10.))); } // namespace } // namespace libavif