/src/libwebp/tests/fuzzer/sharpyuv_fuzzer.cc
Line | Count | Source |
1 | | // Copyright 2026 Google Inc. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | // |
15 | | //////////////////////////////////////////////////////////////////////////////// |
16 | | |
17 | | #include <cstddef> |
18 | | #include <cstdint> |
19 | | #include <vector> |
20 | | |
21 | | #include "./fuzz_utils.h" |
22 | | #include "gtest/gtest.h" |
23 | | #include "sharpyuv/sharpyuv.h" |
24 | | #include "sharpyuv/sharpyuv_csp.h" |
25 | | |
26 | | namespace { |
27 | | |
28 | | void SharpYuvConvertFuzz(int width, int height, int rgb_bit_depth, |
29 | | int yuv_bit_depth, |
30 | | const std::vector<uint16_t>& r_samples, |
31 | | const std::vector<uint16_t>& g_samples, |
32 | | const std::vector<uint16_t>& b_samples, |
33 | 1.07k | int matrix_type_int, int transfer_type_int) { |
34 | 1.07k | const size_t num_pixels = static_cast<size_t>(width) * height; |
35 | 1.07k | ASSERT_LE(num_pixels, r_samples.size()); |
36 | 1.07k | ASSERT_LE(num_pixels, g_samples.size()); |
37 | 1.07k | ASSERT_LE(num_pixels, b_samples.size()); |
38 | | |
39 | 1.07k | const SharpYuvMatrixType matrix_type = |
40 | 1.07k | static_cast<SharpYuvMatrixType>(matrix_type_int); |
41 | 1.07k | const SharpYuvTransferFunctionType transfer_type = |
42 | 1.07k | static_cast<SharpYuvTransferFunctionType>(transfer_type_int); |
43 | | |
44 | 1.07k | const SharpYuvConversionMatrix* matrix = |
45 | 1.07k | SharpYuvGetConversionMatrix(matrix_type); |
46 | 1.07k | ASSERT_NE(matrix, nullptr); |
47 | | |
48 | 1.07k | SharpYuvOptions options; |
49 | 1.07k | ASSERT_TRUE(SharpYuvOptionsInit(matrix, &options)); |
50 | 1.07k | options.transfer_type = transfer_type; |
51 | | |
52 | 1.07k | const int yuv_bytes = (yuv_bit_depth > 8) ? 2 : 1; |
53 | 1.07k | const int y_stride = width * yuv_bytes; |
54 | 1.07k | const int uv_stride = ((width + 1) / 2) * yuv_bytes; |
55 | | |
56 | 1.07k | std::vector<uint8_t> y_dst(y_stride * height); |
57 | 1.07k | std::vector<uint8_t> u_dst(uv_stride * ((height + 1) / 2)); |
58 | 1.07k | std::vector<uint8_t> v_dst(uv_stride * ((height + 1) / 2)); |
59 | | |
60 | 1.07k | if (rgb_bit_depth == 8) { |
61 | 234 | std::vector<uint8_t> r8(num_pixels), g8(num_pixels), b8(num_pixels); |
62 | 101k | for (size_t i = 0; i < num_pixels; ++i) { |
63 | 101k | r8[i] = static_cast<uint8_t>(r_samples[i]); |
64 | 101k | g8[i] = static_cast<uint8_t>(g_samples[i]); |
65 | 101k | b8[i] = static_cast<uint8_t>(b_samples[i]); |
66 | 101k | } |
67 | 234 | EXPECT_TRUE(SharpYuvConvertWithOptions( |
68 | 234 | r8.data(), g8.data(), b8.data(), 1, width, rgb_bit_depth, y_dst.data(), |
69 | 234 | y_stride, u_dst.data(), uv_stride, v_dst.data(), uv_stride, |
70 | 234 | yuv_bit_depth, width, height, &options)); |
71 | 837 | } else { |
72 | 837 | EXPECT_TRUE(SharpYuvConvertWithOptions( |
73 | 837 | r_samples.data(), g_samples.data(), b_samples.data(), 2, width * 2, |
74 | 837 | rgb_bit_depth, y_dst.data(), y_stride, u_dst.data(), uv_stride, |
75 | 837 | v_dst.data(), uv_stride, yuv_bit_depth, width, height, &options)); |
76 | 837 | } |
77 | 1.07k | } |
78 | | |
79 | 3.95k | auto AnyTransferFunction() { |
80 | 3.95k | return fuzztest::ElementOf<int>({ |
81 | 3.95k | kSharpYuvTransferFunctionBt709, |
82 | 3.95k | kSharpYuvTransferFunctionBt470M, |
83 | 3.95k | kSharpYuvTransferFunctionBt470Bg, |
84 | 3.95k | kSharpYuvTransferFunctionBt601, |
85 | 3.95k | kSharpYuvTransferFunctionSmpte240, |
86 | 3.95k | kSharpYuvTransferFunctionLinear, |
87 | 3.95k | kSharpYuvTransferFunctionLog100, |
88 | 3.95k | kSharpYuvTransferFunctionLog100_Sqrt10, |
89 | 3.95k | kSharpYuvTransferFunctionIec61966, |
90 | 3.95k | kSharpYuvTransferFunctionBt1361, |
91 | 3.95k | kSharpYuvTransferFunctionSrgb, |
92 | 3.95k | kSharpYuvTransferFunctionBt2020_10Bit, |
93 | 3.95k | kSharpYuvTransferFunctionBt2020_12Bit, |
94 | 3.95k | kSharpYuvTransferFunctionSmpte2084, |
95 | 3.95k | kSharpYuvTransferFunctionSmpte428, |
96 | 3.95k | kSharpYuvTransferFunctionHlg, |
97 | 3.95k | }); |
98 | 3.95k | } |
99 | | |
100 | 2 | auto SharpYuvDomain() { |
101 | 2 | return fuzztest::FlatMap( |
102 | 3.95k | [](int w, int h, int rgb_bd, int yuv_bd) { |
103 | | // Create input/output buffers of the right size. |
104 | 3.95k | const size_t n = static_cast<size_t>(w * h); |
105 | 3.95k | return fuzztest::TupleOf( |
106 | 3.95k | fuzztest::Just(w), fuzztest::Just(h), fuzztest::Just(rgb_bd), |
107 | 3.95k | fuzztest::Just(yuv_bd), |
108 | 3.95k | fuzztest::VectorOf(fuzztest::Arbitrary<uint16_t>()).WithSize(n), |
109 | 3.95k | fuzztest::VectorOf(fuzztest::Arbitrary<uint16_t>()).WithSize(n), |
110 | 3.95k | fuzztest::VectorOf(fuzztest::Arbitrary<uint16_t>()).WithSize(n), |
111 | 3.95k | fuzztest::InRange(0, static_cast<int>(kSharpYuvMatrixNum) - 1), |
112 | 3.95k | AnyTransferFunction()); |
113 | 3.95k | }, |
114 | 2 | /*width=*/fuzztest::InRange(1, 128), |
115 | 2 | /*height=*/fuzztest::InRange(1, 128), |
116 | 2 | /*rgb_bit_depth=*/fuzztest::ElementOf({8, 10, 12, 16}), |
117 | 2 | /*yuv_bit_depth=*/fuzztest::ElementOf({8, 10, 12})); |
118 | 2 | } |
119 | | |
120 | | void SharpYuvConvertFuzzWrapped( |
121 | | const std::tuple<int, int, int, int, std::vector<uint16_t>, |
122 | | std::vector<uint16_t>, std::vector<uint16_t>, int, int>& |
123 | 1.07k | args) { |
124 | 1.07k | std::apply(SharpYuvConvertFuzz, args); |
125 | 1.07k | } |
126 | | |
127 | | FUZZ_TEST(SharpYuvFuzz, SharpYuvConvertFuzzWrapped) |
128 | | .WithDomains(SharpYuvDomain()); |
129 | | |
130 | | } // namespace |