1*89a0ef05SAndroid Build Coastguard Worker /*
2*89a0ef05SAndroid Build Coastguard Worker * Copyright 2023 The Android Open Source Project
3*89a0ef05SAndroid Build Coastguard Worker *
4*89a0ef05SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*89a0ef05SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*89a0ef05SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*89a0ef05SAndroid Build Coastguard Worker *
8*89a0ef05SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*89a0ef05SAndroid Build Coastguard Worker *
10*89a0ef05SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*89a0ef05SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*89a0ef05SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*89a0ef05SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*89a0ef05SAndroid Build Coastguard Worker * limitations under the License.
15*89a0ef05SAndroid Build Coastguard Worker */
16*89a0ef05SAndroid Build Coastguard Worker
17*89a0ef05SAndroid Build Coastguard Worker #include <fuzzer/FuzzedDataProvider.h>
18*89a0ef05SAndroid Build Coastguard Worker #include <algorithm>
19*89a0ef05SAndroid Build Coastguard Worker #include <iostream>
20*89a0ef05SAndroid Build Coastguard Worker #include <memory>
21*89a0ef05SAndroid Build Coastguard Worker #include <random>
22*89a0ef05SAndroid Build Coastguard Worker
23*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/ultrahdrcommon.h"
24*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/gainmapmath.h"
25*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/jpegr.h"
26*89a0ef05SAndroid Build Coastguard Worker
27*89a0ef05SAndroid Build Coastguard Worker using namespace ultrahdr;
28*89a0ef05SAndroid Build Coastguard Worker
29*89a0ef05SAndroid Build Coastguard Worker // Color gamuts for image data, sync with ultrahdr.h
30*89a0ef05SAndroid Build Coastguard Worker const int kCgMin = ULTRAHDR_COLORGAMUT_UNSPECIFIED;
31*89a0ef05SAndroid Build Coastguard Worker const int kCgMax = ULTRAHDR_COLORGAMUT_BT2100;
32*89a0ef05SAndroid Build Coastguard Worker
33*89a0ef05SAndroid Build Coastguard Worker // Transfer functions for image data, sync with ultrahdr.h
34*89a0ef05SAndroid Build Coastguard Worker const int kTfMin = ULTRAHDR_TF_UNSPECIFIED;
35*89a0ef05SAndroid Build Coastguard Worker const int kTfMax = ULTRAHDR_TF_SRGB;
36*89a0ef05SAndroid Build Coastguard Worker
37*89a0ef05SAndroid Build Coastguard Worker // Transfer functions for image data, sync with ultrahdr.h
38*89a0ef05SAndroid Build Coastguard Worker const int kOfMin = ULTRAHDR_OUTPUT_UNSPECIFIED;
39*89a0ef05SAndroid Build Coastguard Worker const int kOfMax = ULTRAHDR_OUTPUT_HDR_HLG;
40*89a0ef05SAndroid Build Coastguard Worker
41*89a0ef05SAndroid Build Coastguard Worker // quality factor
42*89a0ef05SAndroid Build Coastguard Worker const int kQfMin = -10;
43*89a0ef05SAndroid Build Coastguard Worker const int kQfMax = 110;
44*89a0ef05SAndroid Build Coastguard Worker
45*89a0ef05SAndroid Build Coastguard Worker class UltraHdrEncFuzzer {
46*89a0ef05SAndroid Build Coastguard Worker public:
UltraHdrEncFuzzer(const uint8_t * data,size_t size)47*89a0ef05SAndroid Build Coastguard Worker UltraHdrEncFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {};
48*89a0ef05SAndroid Build Coastguard Worker void process();
49*89a0ef05SAndroid Build Coastguard Worker template <typename T>
50*89a0ef05SAndroid Build Coastguard Worker void fillBuffer(T* data, int width, int height, int stride);
51*89a0ef05SAndroid Build Coastguard Worker
52*89a0ef05SAndroid Build Coastguard Worker private:
53*89a0ef05SAndroid Build Coastguard Worker FuzzedDataProvider mFdp;
54*89a0ef05SAndroid Build Coastguard Worker };
55*89a0ef05SAndroid Build Coastguard Worker
56*89a0ef05SAndroid Build Coastguard Worker template <typename T>
fillBuffer(T * data,int width,int height,int stride)57*89a0ef05SAndroid Build Coastguard Worker void UltraHdrEncFuzzer::fillBuffer(T* data, int width, int height, int stride) {
58*89a0ef05SAndroid Build Coastguard Worker if (!mFdp.remaining_bytes()) return;
59*89a0ef05SAndroid Build Coastguard Worker
60*89a0ef05SAndroid Build Coastguard Worker T* tmp = data;
61*89a0ef05SAndroid Build Coastguard Worker std::vector<T> buffer(width);
62*89a0ef05SAndroid Build Coastguard Worker for (int i = 0; i < buffer.size(); i++) {
63*89a0ef05SAndroid Build Coastguard Worker buffer[i] = mFdp.ConsumeIntegral<T>();
64*89a0ef05SAndroid Build Coastguard Worker }
65*89a0ef05SAndroid Build Coastguard Worker for (int j = 0; j < height; j++) {
66*89a0ef05SAndroid Build Coastguard Worker for (int i = 0; i < width; i += buffer.size()) {
67*89a0ef05SAndroid Build Coastguard Worker memcpy(tmp + i, buffer.data(), std::min((int)buffer.size(), (width - i)) * sizeof(*data));
68*89a0ef05SAndroid Build Coastguard Worker std::shuffle(buffer.begin(), buffer.end(),
69*89a0ef05SAndroid Build Coastguard Worker std::default_random_engine(std::random_device{}()));
70*89a0ef05SAndroid Build Coastguard Worker }
71*89a0ef05SAndroid Build Coastguard Worker tmp += stride;
72*89a0ef05SAndroid Build Coastguard Worker }
73*89a0ef05SAndroid Build Coastguard Worker }
74*89a0ef05SAndroid Build Coastguard Worker
process()75*89a0ef05SAndroid Build Coastguard Worker void UltraHdrEncFuzzer::process() {
76*89a0ef05SAndroid Build Coastguard Worker if (mFdp.remaining_bytes()) {
77*89a0ef05SAndroid Build Coastguard Worker struct jpegr_uncompressed_struct p010Img{};
78*89a0ef05SAndroid Build Coastguard Worker struct jpegr_uncompressed_struct yuv420Img{};
79*89a0ef05SAndroid Build Coastguard Worker struct jpegr_uncompressed_struct grayImg{};
80*89a0ef05SAndroid Build Coastguard Worker struct jpegr_compressed_struct jpegImgR{};
81*89a0ef05SAndroid Build Coastguard Worker struct jpegr_compressed_struct jpegImg{};
82*89a0ef05SAndroid Build Coastguard Worker struct jpegr_compressed_struct jpegGainMap{};
83*89a0ef05SAndroid Build Coastguard Worker
84*89a0ef05SAndroid Build Coastguard Worker // which encode api to select
85*89a0ef05SAndroid Build Coastguard Worker int muxSwitch = mFdp.ConsumeIntegralInRange<int>(0, 4);
86*89a0ef05SAndroid Build Coastguard Worker
87*89a0ef05SAndroid Build Coastguard Worker // quality factor
88*89a0ef05SAndroid Build Coastguard Worker int quality = mFdp.ConsumeIntegralInRange<int>(kQfMin, kQfMax);
89*89a0ef05SAndroid Build Coastguard Worker
90*89a0ef05SAndroid Build Coastguard Worker // hdr_tf
91*89a0ef05SAndroid Build Coastguard Worker auto tf =
92*89a0ef05SAndroid Build Coastguard Worker static_cast<ultrahdr_transfer_function>(mFdp.ConsumeIntegralInRange<int>(kTfMin, kTfMax));
93*89a0ef05SAndroid Build Coastguard Worker
94*89a0ef05SAndroid Build Coastguard Worker // p010 Cg
95*89a0ef05SAndroid Build Coastguard Worker auto p010Cg =
96*89a0ef05SAndroid Build Coastguard Worker static_cast<ultrahdr_color_gamut>(mFdp.ConsumeIntegralInRange<int>(kCgMin, kCgMax));
97*89a0ef05SAndroid Build Coastguard Worker
98*89a0ef05SAndroid Build Coastguard Worker // 420 Cg
99*89a0ef05SAndroid Build Coastguard Worker auto yuv420Cg =
100*89a0ef05SAndroid Build Coastguard Worker static_cast<ultrahdr_color_gamut>(mFdp.ConsumeIntegralInRange<int>(kCgMin, kCgMax));
101*89a0ef05SAndroid Build Coastguard Worker
102*89a0ef05SAndroid Build Coastguard Worker // hdr_of
103*89a0ef05SAndroid Build Coastguard Worker auto of = static_cast<ultrahdr_output_format>(mFdp.ConsumeIntegralInRange<int>(kOfMin, kOfMax));
104*89a0ef05SAndroid Build Coastguard Worker
105*89a0ef05SAndroid Build Coastguard Worker int width = mFdp.ConsumeIntegralInRange<int>(kMinWidth, kMaxWidth);
106*89a0ef05SAndroid Build Coastguard Worker width = (width >> 1) << 1;
107*89a0ef05SAndroid Build Coastguard Worker
108*89a0ef05SAndroid Build Coastguard Worker int height = mFdp.ConsumeIntegralInRange<int>(kMinHeight, kMaxHeight);
109*89a0ef05SAndroid Build Coastguard Worker height = (height >> 1) << 1;
110*89a0ef05SAndroid Build Coastguard Worker
111*89a0ef05SAndroid Build Coastguard Worker // gain_map quality factor
112*89a0ef05SAndroid Build Coastguard Worker auto gainmap_quality = mFdp.ConsumeIntegral<int8_t>();
113*89a0ef05SAndroid Build Coastguard Worker
114*89a0ef05SAndroid Build Coastguard Worker // multi channel gainmap
115*89a0ef05SAndroid Build Coastguard Worker auto multi_channel_gainmap = mFdp.ConsumeIntegral<int8_t>();
116*89a0ef05SAndroid Build Coastguard Worker
117*89a0ef05SAndroid Build Coastguard Worker // gainmap scale factor
118*89a0ef05SAndroid Build Coastguard Worker auto gm_scale_factor = mFdp.ConsumeIntegralInRange<int16_t>(-32, 192);
119*89a0ef05SAndroid Build Coastguard Worker
120*89a0ef05SAndroid Build Coastguard Worker // encoding speed preset
121*89a0ef05SAndroid Build Coastguard Worker auto enc_preset = mFdp.ConsumeBool() ? UHDR_USAGE_REALTIME : UHDR_USAGE_BEST_QUALITY;
122*89a0ef05SAndroid Build Coastguard Worker
123*89a0ef05SAndroid Build Coastguard Worker // gainmap metadata
124*89a0ef05SAndroid Build Coastguard Worker auto minBoost = mFdp.ConsumeFloatingPointInRange<float>(-4.0f, 64.0f);
125*89a0ef05SAndroid Build Coastguard Worker auto maxBoost = mFdp.ConsumeFloatingPointInRange<float>(-4.0f, 64.0f);
126*89a0ef05SAndroid Build Coastguard Worker auto gamma = mFdp.ConsumeFloatingPointInRange<float>(-1.0f, 5);
127*89a0ef05SAndroid Build Coastguard Worker auto offsetSdr = mFdp.ConsumeFloatingPointInRange<float>(-1.0f, 1.0f);
128*89a0ef05SAndroid Build Coastguard Worker auto offsetHdr = mFdp.ConsumeFloatingPointInRange<float>(-1.0f, 1.0f);
129*89a0ef05SAndroid Build Coastguard Worker auto minCapacity = mFdp.ConsumeFloatingPointInRange<float>(-4.0f, 48.0f);
130*89a0ef05SAndroid Build Coastguard Worker auto maxCapacity = mFdp.ConsumeFloatingPointInRange<float>(-4.0f, 48.0f);
131*89a0ef05SAndroid Build Coastguard Worker
132*89a0ef05SAndroid Build Coastguard Worker // target display peak brightness
133*89a0ef05SAndroid Build Coastguard Worker auto targetDispPeakBrightness = mFdp.ConsumeFloatingPointInRange<float>(100.0f, 10500.0f);
134*89a0ef05SAndroid Build Coastguard Worker
135*89a0ef05SAndroid Build Coastguard Worker // raw buffer config
136*89a0ef05SAndroid Build Coastguard Worker bool hasP010Stride = mFdp.ConsumeBool();
137*89a0ef05SAndroid Build Coastguard Worker size_t yP010Stride = mFdp.ConsumeIntegralInRange<uint16_t>(width, width + 128);
138*89a0ef05SAndroid Build Coastguard Worker if (!hasP010Stride) yP010Stride = width;
139*89a0ef05SAndroid Build Coastguard Worker bool isP010UVContiguous = mFdp.ConsumeBool();
140*89a0ef05SAndroid Build Coastguard Worker bool hasP010UVStride = mFdp.ConsumeBool();
141*89a0ef05SAndroid Build Coastguard Worker size_t uvP010Stride = mFdp.ConsumeIntegralInRange<uint16_t>(width, width + 128);
142*89a0ef05SAndroid Build Coastguard Worker if (!hasP010UVStride) uvP010Stride = width;
143*89a0ef05SAndroid Build Coastguard Worker
144*89a0ef05SAndroid Build Coastguard Worker bool hasYuv420Stride = mFdp.ConsumeBool();
145*89a0ef05SAndroid Build Coastguard Worker size_t yYuv420Stride = mFdp.ConsumeIntegralInRange<uint16_t>(width, width + 128);
146*89a0ef05SAndroid Build Coastguard Worker if (!hasYuv420Stride) yYuv420Stride = width;
147*89a0ef05SAndroid Build Coastguard Worker bool isYuv420UVContiguous = mFdp.ConsumeBool();
148*89a0ef05SAndroid Build Coastguard Worker bool hasYuv420UVStride = mFdp.ConsumeBool();
149*89a0ef05SAndroid Build Coastguard Worker size_t uvYuv420Stride = mFdp.ConsumeIntegralInRange<uint16_t>(width / 2, width / 2 + 128);
150*89a0ef05SAndroid Build Coastguard Worker if (!hasYuv420UVStride) uvYuv420Stride = width / 2;
151*89a0ef05SAndroid Build Coastguard Worker
152*89a0ef05SAndroid Build Coastguard Worker // display boost
153*89a0ef05SAndroid Build Coastguard Worker float displayBoost = mFdp.ConsumeFloatingPointInRange<float>(1.0, FLT_MAX);
154*89a0ef05SAndroid Build Coastguard Worker
155*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uint16_t[]> bufferYHdr = nullptr;
156*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uint16_t[]> bufferUVHdr = nullptr;
157*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uint8_t[]> bufferYSdr = nullptr;
158*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uint8_t[]> bufferUVSdr = nullptr;
159*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uint8_t[]> grayImgRaw = nullptr;
160*89a0ef05SAndroid Build Coastguard Worker if (muxSwitch != 4) {
161*89a0ef05SAndroid Build Coastguard Worker // init p010 image
162*89a0ef05SAndroid Build Coastguard Worker p010Img.width = width;
163*89a0ef05SAndroid Build Coastguard Worker p010Img.height = height;
164*89a0ef05SAndroid Build Coastguard Worker p010Img.colorGamut = p010Cg;
165*89a0ef05SAndroid Build Coastguard Worker p010Img.luma_stride = yP010Stride;
166*89a0ef05SAndroid Build Coastguard Worker if (isP010UVContiguous) {
167*89a0ef05SAndroid Build Coastguard Worker size_t p010Size = yP010Stride * height * 3 / 2;
168*89a0ef05SAndroid Build Coastguard Worker bufferYHdr = std::make_unique<uint16_t[]>(p010Size);
169*89a0ef05SAndroid Build Coastguard Worker p010Img.data = bufferYHdr.get();
170*89a0ef05SAndroid Build Coastguard Worker p010Img.chroma_data = nullptr;
171*89a0ef05SAndroid Build Coastguard Worker p010Img.chroma_stride = 0;
172*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint16_t>(bufferYHdr.get(), width, height, yP010Stride);
173*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint16_t>(bufferYHdr.get() + yP010Stride * height, width, height / 2,
174*89a0ef05SAndroid Build Coastguard Worker yP010Stride);
175*89a0ef05SAndroid Build Coastguard Worker } else {
176*89a0ef05SAndroid Build Coastguard Worker size_t p010YSize = yP010Stride * height;
177*89a0ef05SAndroid Build Coastguard Worker bufferYHdr = std::make_unique<uint16_t[]>(p010YSize);
178*89a0ef05SAndroid Build Coastguard Worker p010Img.data = bufferYHdr.get();
179*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint16_t>(bufferYHdr.get(), width, height, yP010Stride);
180*89a0ef05SAndroid Build Coastguard Worker size_t p010UVSize = uvP010Stride * p010Img.height / 2;
181*89a0ef05SAndroid Build Coastguard Worker bufferUVHdr = std::make_unique<uint16_t[]>(p010UVSize);
182*89a0ef05SAndroid Build Coastguard Worker p010Img.chroma_data = bufferUVHdr.get();
183*89a0ef05SAndroid Build Coastguard Worker p010Img.chroma_stride = uvP010Stride;
184*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint16_t>(bufferUVHdr.get(), width, height / 2, uvP010Stride);
185*89a0ef05SAndroid Build Coastguard Worker }
186*89a0ef05SAndroid Build Coastguard Worker } else {
187*89a0ef05SAndroid Build Coastguard Worker size_t map_width = width / kMapDimensionScaleFactorDefault;
188*89a0ef05SAndroid Build Coastguard Worker size_t map_height = height / kMapDimensionScaleFactorDefault;
189*89a0ef05SAndroid Build Coastguard Worker // init 400 image
190*89a0ef05SAndroid Build Coastguard Worker grayImg.width = map_width;
191*89a0ef05SAndroid Build Coastguard Worker grayImg.height = map_height;
192*89a0ef05SAndroid Build Coastguard Worker grayImg.colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED;
193*89a0ef05SAndroid Build Coastguard Worker const size_t graySize = map_width * map_height;
194*89a0ef05SAndroid Build Coastguard Worker grayImgRaw = std::make_unique<uint8_t[]>(graySize);
195*89a0ef05SAndroid Build Coastguard Worker grayImg.data = grayImgRaw.get();
196*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint8_t>(grayImgRaw.get(), map_width, map_height, map_width);
197*89a0ef05SAndroid Build Coastguard Worker grayImg.chroma_data = nullptr;
198*89a0ef05SAndroid Build Coastguard Worker grayImg.luma_stride = 0;
199*89a0ef05SAndroid Build Coastguard Worker grayImg.chroma_stride = 0;
200*89a0ef05SAndroid Build Coastguard Worker }
201*89a0ef05SAndroid Build Coastguard Worker
202*89a0ef05SAndroid Build Coastguard Worker if (muxSwitch > 0) {
203*89a0ef05SAndroid Build Coastguard Worker // init 420 image
204*89a0ef05SAndroid Build Coastguard Worker yuv420Img.width = width;
205*89a0ef05SAndroid Build Coastguard Worker yuv420Img.height = height;
206*89a0ef05SAndroid Build Coastguard Worker yuv420Img.colorGamut = yuv420Cg;
207*89a0ef05SAndroid Build Coastguard Worker yuv420Img.luma_stride = yYuv420Stride;
208*89a0ef05SAndroid Build Coastguard Worker if (isYuv420UVContiguous) {
209*89a0ef05SAndroid Build Coastguard Worker size_t yuv420Size = yYuv420Stride * height * 3 / 2;
210*89a0ef05SAndroid Build Coastguard Worker bufferYSdr = std::make_unique<uint8_t[]>(yuv420Size);
211*89a0ef05SAndroid Build Coastguard Worker yuv420Img.data = bufferYSdr.get();
212*89a0ef05SAndroid Build Coastguard Worker yuv420Img.chroma_data = nullptr;
213*89a0ef05SAndroid Build Coastguard Worker yuv420Img.chroma_stride = 0;
214*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint8_t>(bufferYSdr.get(), width, height, yYuv420Stride);
215*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint8_t>(bufferYSdr.get() + yYuv420Stride * height, width / 2, height / 2,
216*89a0ef05SAndroid Build Coastguard Worker yYuv420Stride / 2);
217*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint8_t>(bufferYSdr.get() + yYuv420Stride * height * 5 / 4, width / 2,
218*89a0ef05SAndroid Build Coastguard Worker height / 2, yYuv420Stride / 2);
219*89a0ef05SAndroid Build Coastguard Worker } else {
220*89a0ef05SAndroid Build Coastguard Worker size_t yuv420YSize = yYuv420Stride * height;
221*89a0ef05SAndroid Build Coastguard Worker bufferYSdr = std::make_unique<uint8_t[]>(yuv420YSize);
222*89a0ef05SAndroid Build Coastguard Worker yuv420Img.data = bufferYSdr.get();
223*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint8_t>(bufferYSdr.get(), width, height, yYuv420Stride);
224*89a0ef05SAndroid Build Coastguard Worker size_t yuv420UVSize = uvYuv420Stride * yuv420Img.height / 2 * 2;
225*89a0ef05SAndroid Build Coastguard Worker bufferUVSdr = std::make_unique<uint8_t[]>(yuv420UVSize);
226*89a0ef05SAndroid Build Coastguard Worker yuv420Img.chroma_data = bufferUVSdr.get();
227*89a0ef05SAndroid Build Coastguard Worker yuv420Img.chroma_stride = uvYuv420Stride;
228*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint8_t>(bufferUVSdr.get(), width / 2, height / 2, uvYuv420Stride);
229*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint8_t>(bufferUVSdr.get() + uvYuv420Stride * height / 2, width / 2, height / 2,
230*89a0ef05SAndroid Build Coastguard Worker uvYuv420Stride);
231*89a0ef05SAndroid Build Coastguard Worker }
232*89a0ef05SAndroid Build Coastguard Worker }
233*89a0ef05SAndroid Build Coastguard Worker
234*89a0ef05SAndroid Build Coastguard Worker // dest
235*89a0ef05SAndroid Build Coastguard Worker // 2 * p010 size as input data is random, DCT compression might not behave as expected
236*89a0ef05SAndroid Build Coastguard Worker jpegImgR.maxLength = std::max(8 * 1024 /* min size 8kb */, width * height * 3 * 2);
237*89a0ef05SAndroid Build Coastguard Worker auto jpegImgRaw = std::make_unique<uint8_t[]>(jpegImgR.maxLength);
238*89a0ef05SAndroid Build Coastguard Worker jpegImgR.data = jpegImgRaw.get();
239*89a0ef05SAndroid Build Coastguard Worker // #define DUMP_PARAM
240*89a0ef05SAndroid Build Coastguard Worker #ifdef DUMP_PARAM
241*89a0ef05SAndroid Build Coastguard Worker std::cout << "Api Select " << muxSwitch << std::endl;
242*89a0ef05SAndroid Build Coastguard Worker std::cout << "image dimensions " << width << " x " << height << std::endl;
243*89a0ef05SAndroid Build Coastguard Worker std::cout << "p010 color gamut " << p010Img.colorGamut << std::endl;
244*89a0ef05SAndroid Build Coastguard Worker std::cout << "p010 luma stride " << p010Img.luma_stride << std::endl;
245*89a0ef05SAndroid Build Coastguard Worker std::cout << "p010 chroma stride " << p010Img.chroma_stride << std::endl;
246*89a0ef05SAndroid Build Coastguard Worker std::cout << "420 color gamut " << yuv420Img.colorGamut << std::endl;
247*89a0ef05SAndroid Build Coastguard Worker std::cout << "420 luma stride " << yuv420Img.luma_stride << std::endl;
248*89a0ef05SAndroid Build Coastguard Worker std::cout << "420 chroma stride " << yuv420Img.chroma_stride << std::endl;
249*89a0ef05SAndroid Build Coastguard Worker std::cout << "quality factor " << quality << std::endl;
250*89a0ef05SAndroid Build Coastguard Worker #endif
251*89a0ef05SAndroid Build Coastguard Worker JpegR jpegHdr(nullptr, gm_scale_factor, gainmap_quality, multi_channel_gainmap, gamma,
252*89a0ef05SAndroid Build Coastguard Worker enc_preset, minBoost, maxBoost, targetDispPeakBrightness);
253*89a0ef05SAndroid Build Coastguard Worker status_t status = JPEGR_UNKNOWN_ERROR;
254*89a0ef05SAndroid Build Coastguard Worker if (muxSwitch == 0) { // api 0
255*89a0ef05SAndroid Build Coastguard Worker jpegImgR.length = 0;
256*89a0ef05SAndroid Build Coastguard Worker status = jpegHdr.encodeJPEGR(&p010Img, tf, &jpegImgR, quality, nullptr);
257*89a0ef05SAndroid Build Coastguard Worker } else if (muxSwitch == 1) { // api 1
258*89a0ef05SAndroid Build Coastguard Worker jpegImgR.length = 0;
259*89a0ef05SAndroid Build Coastguard Worker status = jpegHdr.encodeJPEGR(&p010Img, &yuv420Img, tf, &jpegImgR, quality, nullptr);
260*89a0ef05SAndroid Build Coastguard Worker } else {
261*89a0ef05SAndroid Build Coastguard Worker // compressed img
262*89a0ef05SAndroid Build Coastguard Worker JpegEncoderHelper encoder;
263*89a0ef05SAndroid Build Coastguard Worker struct jpegr_uncompressed_struct yuv420ImgCopy = yuv420Img;
264*89a0ef05SAndroid Build Coastguard Worker if (yuv420ImgCopy.luma_stride == 0) yuv420ImgCopy.luma_stride = yuv420Img.width;
265*89a0ef05SAndroid Build Coastguard Worker if (!yuv420ImgCopy.chroma_data) {
266*89a0ef05SAndroid Build Coastguard Worker uint8_t* data = reinterpret_cast<uint8_t*>(yuv420Img.data);
267*89a0ef05SAndroid Build Coastguard Worker yuv420ImgCopy.chroma_data = data + yuv420Img.luma_stride * yuv420Img.height;
268*89a0ef05SAndroid Build Coastguard Worker yuv420ImgCopy.chroma_stride = yuv420Img.luma_stride >> 1;
269*89a0ef05SAndroid Build Coastguard Worker }
270*89a0ef05SAndroid Build Coastguard Worker const uint8_t* planes[3]{reinterpret_cast<uint8_t*>(yuv420ImgCopy.data),
271*89a0ef05SAndroid Build Coastguard Worker reinterpret_cast<uint8_t*>(yuv420ImgCopy.chroma_data),
272*89a0ef05SAndroid Build Coastguard Worker reinterpret_cast<uint8_t*>(yuv420ImgCopy.chroma_data) +
273*89a0ef05SAndroid Build Coastguard Worker yuv420ImgCopy.chroma_stride * yuv420ImgCopy.height / 2};
274*89a0ef05SAndroid Build Coastguard Worker const unsigned int strides[3]{yuv420ImgCopy.luma_stride, yuv420ImgCopy.chroma_stride,
275*89a0ef05SAndroid Build Coastguard Worker yuv420ImgCopy.chroma_stride};
276*89a0ef05SAndroid Build Coastguard Worker if (encoder
277*89a0ef05SAndroid Build Coastguard Worker .compressImage(planes, strides, yuv420ImgCopy.width, yuv420ImgCopy.height,
278*89a0ef05SAndroid Build Coastguard Worker UHDR_IMG_FMT_12bppYCbCr420, quality, nullptr, 0)
279*89a0ef05SAndroid Build Coastguard Worker .error_code == UHDR_CODEC_OK) {
280*89a0ef05SAndroid Build Coastguard Worker jpegImg.length = encoder.getCompressedImageSize();
281*89a0ef05SAndroid Build Coastguard Worker jpegImg.maxLength = jpegImg.length;
282*89a0ef05SAndroid Build Coastguard Worker jpegImg.data = encoder.getCompressedImagePtr();
283*89a0ef05SAndroid Build Coastguard Worker jpegImg.colorGamut = yuv420Cg;
284*89a0ef05SAndroid Build Coastguard Worker if (muxSwitch == 2) { // api 2
285*89a0ef05SAndroid Build Coastguard Worker jpegImgR.length = 0;
286*89a0ef05SAndroid Build Coastguard Worker status = jpegHdr.encodeJPEGR(&p010Img, &yuv420Img, &jpegImg, tf, &jpegImgR);
287*89a0ef05SAndroid Build Coastguard Worker } else if (muxSwitch == 3) { // api 3
288*89a0ef05SAndroid Build Coastguard Worker jpegImgR.length = 0;
289*89a0ef05SAndroid Build Coastguard Worker status = jpegHdr.encodeJPEGR(&p010Img, &jpegImg, tf, &jpegImgR);
290*89a0ef05SAndroid Build Coastguard Worker } else if (muxSwitch == 4) { // api 4
291*89a0ef05SAndroid Build Coastguard Worker jpegImgR.length = 0;
292*89a0ef05SAndroid Build Coastguard Worker JpegEncoderHelper gainMapEncoder;
293*89a0ef05SAndroid Build Coastguard Worker const uint8_t* planeGm[1]{reinterpret_cast<uint8_t*>(grayImg.data)};
294*89a0ef05SAndroid Build Coastguard Worker const unsigned int strideGm[1]{grayImg.width};
295*89a0ef05SAndroid Build Coastguard Worker if (gainMapEncoder
296*89a0ef05SAndroid Build Coastguard Worker .compressImage(planeGm, strideGm, grayImg.width, grayImg.height,
297*89a0ef05SAndroid Build Coastguard Worker UHDR_IMG_FMT_8bppYCbCr400, quality, nullptr, 0)
298*89a0ef05SAndroid Build Coastguard Worker .error_code == UHDR_CODEC_OK) {
299*89a0ef05SAndroid Build Coastguard Worker jpegGainMap.length = gainMapEncoder.getCompressedImageSize();
300*89a0ef05SAndroid Build Coastguard Worker jpegGainMap.maxLength = jpegImg.length;
301*89a0ef05SAndroid Build Coastguard Worker jpegGainMap.data = gainMapEncoder.getCompressedImagePtr();
302*89a0ef05SAndroid Build Coastguard Worker jpegGainMap.colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED;
303*89a0ef05SAndroid Build Coastguard Worker ultrahdr_metadata_struct metadata;
304*89a0ef05SAndroid Build Coastguard Worker metadata.version = kJpegrVersion;
305*89a0ef05SAndroid Build Coastguard Worker metadata.maxContentBoost = maxBoost;
306*89a0ef05SAndroid Build Coastguard Worker metadata.minContentBoost = minBoost;
307*89a0ef05SAndroid Build Coastguard Worker metadata.gamma = gamma;
308*89a0ef05SAndroid Build Coastguard Worker metadata.offsetSdr = offsetSdr;
309*89a0ef05SAndroid Build Coastguard Worker metadata.offsetHdr = offsetHdr;
310*89a0ef05SAndroid Build Coastguard Worker metadata.hdrCapacityMin = minCapacity;
311*89a0ef05SAndroid Build Coastguard Worker metadata.hdrCapacityMax = maxCapacity;
312*89a0ef05SAndroid Build Coastguard Worker status = jpegHdr.encodeJPEGR(&jpegImg, &jpegGainMap, &metadata, &jpegImgR);
313*89a0ef05SAndroid Build Coastguard Worker }
314*89a0ef05SAndroid Build Coastguard Worker }
315*89a0ef05SAndroid Build Coastguard Worker }
316*89a0ef05SAndroid Build Coastguard Worker }
317*89a0ef05SAndroid Build Coastguard Worker if (status == JPEGR_NO_ERROR) {
318*89a0ef05SAndroid Build Coastguard Worker jpegr_info_struct info{};
319*89a0ef05SAndroid Build Coastguard Worker status = jpegHdr.getJPEGRInfo(&jpegImgR, &info);
320*89a0ef05SAndroid Build Coastguard Worker if (status == JPEGR_NO_ERROR) {
321*89a0ef05SAndroid Build Coastguard Worker size_t outSize = info.width * info.height * ((of == ULTRAHDR_OUTPUT_HDR_LINEAR) ? 8 : 4);
322*89a0ef05SAndroid Build Coastguard Worker jpegr_uncompressed_struct decodedJpegR;
323*89a0ef05SAndroid Build Coastguard Worker auto decodedRaw = std::make_unique<uint8_t[]>(outSize);
324*89a0ef05SAndroid Build Coastguard Worker decodedJpegR.data = decodedRaw.get();
325*89a0ef05SAndroid Build Coastguard Worker ultrahdr_metadata_struct metadata;
326*89a0ef05SAndroid Build Coastguard Worker status = jpegHdr.decodeJPEGR(&jpegImgR, &decodedJpegR, displayBoost, nullptr, of, nullptr,
327*89a0ef05SAndroid Build Coastguard Worker &metadata);
328*89a0ef05SAndroid Build Coastguard Worker if (status != JPEGR_NO_ERROR) {
329*89a0ef05SAndroid Build Coastguard Worker ALOGE("encountered error during decoding %d", status);
330*89a0ef05SAndroid Build Coastguard Worker }
331*89a0ef05SAndroid Build Coastguard Worker } else {
332*89a0ef05SAndroid Build Coastguard Worker ALOGE("encountered error during get jpeg info %d", status);
333*89a0ef05SAndroid Build Coastguard Worker }
334*89a0ef05SAndroid Build Coastguard Worker } else {
335*89a0ef05SAndroid Build Coastguard Worker ALOGE("encountered error during encoding %d", status);
336*89a0ef05SAndroid Build Coastguard Worker }
337*89a0ef05SAndroid Build Coastguard Worker }
338*89a0ef05SAndroid Build Coastguard Worker }
339*89a0ef05SAndroid Build Coastguard Worker
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)340*89a0ef05SAndroid Build Coastguard Worker extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
341*89a0ef05SAndroid Build Coastguard Worker UltraHdrEncFuzzer fuzzHandle(data, size);
342*89a0ef05SAndroid Build Coastguard Worker fuzzHandle.process();
343*89a0ef05SAndroid Build Coastguard Worker return 0;
344*89a0ef05SAndroid Build Coastguard Worker }
345