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 <random>
20*89a0ef05SAndroid Build Coastguard Worker #include <type_traits>
21*89a0ef05SAndroid Build Coastguard Worker
22*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr_api.h"
23*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/ultrahdrcommon.h"
24*89a0ef05SAndroid Build Coastguard Worker #include "ultrahdr/jpegr.h"
25*89a0ef05SAndroid Build Coastguard Worker
26*89a0ef05SAndroid Build Coastguard Worker using namespace ultrahdr;
27*89a0ef05SAndroid Build Coastguard Worker
28*89a0ef05SAndroid Build Coastguard Worker // Color gamuts for image data, sync with ultrahdr_api.h
29*89a0ef05SAndroid Build Coastguard Worker constexpr int kCgMin = UHDR_CG_UNSPECIFIED;
30*89a0ef05SAndroid Build Coastguard Worker constexpr int kCgMax = UHDR_CG_BT_2100;
31*89a0ef05SAndroid Build Coastguard Worker
32*89a0ef05SAndroid Build Coastguard Worker // Color ranges for image data, sync with ultrahdr_api.h
33*89a0ef05SAndroid Build Coastguard Worker constexpr int kCrMin = UHDR_CR_UNSPECIFIED;
34*89a0ef05SAndroid Build Coastguard Worker constexpr int kCrMax = UHDR_CR_FULL_RANGE;
35*89a0ef05SAndroid Build Coastguard Worker
36*89a0ef05SAndroid Build Coastguard Worker // Transfer functions for image data, sync with ultrahdr_api.h
37*89a0ef05SAndroid Build Coastguard Worker constexpr int kTfMin = UHDR_CT_UNSPECIFIED;
38*89a0ef05SAndroid Build Coastguard Worker constexpr int kTfMax = UHDR_CT_SRGB;
39*89a0ef05SAndroid Build Coastguard Worker
40*89a0ef05SAndroid Build Coastguard Worker class UltraHdrEncFuzzer {
41*89a0ef05SAndroid Build Coastguard Worker public:
UltraHdrEncFuzzer(const uint8_t * data,size_t size)42*89a0ef05SAndroid Build Coastguard Worker UltraHdrEncFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {};
43*89a0ef05SAndroid Build Coastguard Worker void process();
44*89a0ef05SAndroid Build Coastguard Worker template <typename T>
45*89a0ef05SAndroid Build Coastguard Worker void fillBuffer(T* data, int width, int height, int stride);
46*89a0ef05SAndroid Build Coastguard Worker
47*89a0ef05SAndroid Build Coastguard Worker private:
48*89a0ef05SAndroid Build Coastguard Worker FuzzedDataProvider mFdp;
49*89a0ef05SAndroid Build Coastguard Worker };
50*89a0ef05SAndroid Build Coastguard Worker
51*89a0ef05SAndroid Build Coastguard Worker template <typename T>
fillBuffer(T * data,int width,int height,int stride)52*89a0ef05SAndroid Build Coastguard Worker void UltraHdrEncFuzzer::fillBuffer(T* data, int width, int height, int stride) {
53*89a0ef05SAndroid Build Coastguard Worker if (!mFdp.remaining_bytes()) return;
54*89a0ef05SAndroid Build Coastguard Worker
55*89a0ef05SAndroid Build Coastguard Worker T* tmp = data;
56*89a0ef05SAndroid Build Coastguard Worker std::vector<T> buffer(width);
57*89a0ef05SAndroid Build Coastguard Worker for (int i = 0; i < buffer.size(); i++) {
58*89a0ef05SAndroid Build Coastguard Worker buffer[i] = mFdp.ConsumeIntegral<T>();
59*89a0ef05SAndroid Build Coastguard Worker }
60*89a0ef05SAndroid Build Coastguard Worker for (int j = 0; j < height; j++) {
61*89a0ef05SAndroid Build Coastguard Worker for (int i = 0; i < width; i += buffer.size()) {
62*89a0ef05SAndroid Build Coastguard Worker memcpy(tmp + i, buffer.data(), std::min((int)buffer.size(), (width - i)) * sizeof(*data));
63*89a0ef05SAndroid Build Coastguard Worker std::shuffle(buffer.begin(), buffer.end(),
64*89a0ef05SAndroid Build Coastguard Worker std::default_random_engine(std::random_device{}()));
65*89a0ef05SAndroid Build Coastguard Worker }
66*89a0ef05SAndroid Build Coastguard Worker tmp += stride;
67*89a0ef05SAndroid Build Coastguard Worker }
68*89a0ef05SAndroid Build Coastguard Worker }
69*89a0ef05SAndroid Build Coastguard Worker
process()70*89a0ef05SAndroid Build Coastguard Worker void UltraHdrEncFuzzer::process() {
71*89a0ef05SAndroid Build Coastguard Worker if (mFdp.remaining_bytes()) {
72*89a0ef05SAndroid Build Coastguard Worker struct uhdr_raw_image hdrImg{};
73*89a0ef05SAndroid Build Coastguard Worker struct uhdr_raw_image sdrImg{};
74*89a0ef05SAndroid Build Coastguard Worker struct uhdr_raw_image gainmapImg{};
75*89a0ef05SAndroid Build Coastguard Worker
76*89a0ef05SAndroid Build Coastguard Worker // which encode api to select
77*89a0ef05SAndroid Build Coastguard Worker int muxSwitch = mFdp.ConsumeIntegralInRange<int8_t>(0, 4);
78*89a0ef05SAndroid Build Coastguard Worker
79*89a0ef05SAndroid Build Coastguard Worker // hdr_img_fmt
80*89a0ef05SAndroid Build Coastguard Worker uhdr_img_fmt_t hdr_img_fmt =
81*89a0ef05SAndroid Build Coastguard Worker mFdp.PickValueInArray({UHDR_IMG_FMT_24bppYCbCrP010, UHDR_IMG_FMT_32bppRGBA1010102,
82*89a0ef05SAndroid Build Coastguard Worker UHDR_IMG_FMT_64bppRGBAHalfFloat});
83*89a0ef05SAndroid Build Coastguard Worker
84*89a0ef05SAndroid Build Coastguard Worker // sdr_img_fmt
85*89a0ef05SAndroid Build Coastguard Worker uhdr_img_fmt_t sdr_img_fmt =
86*89a0ef05SAndroid Build Coastguard Worker mFdp.ConsumeBool() ? UHDR_IMG_FMT_12bppYCbCr420 : UHDR_IMG_FMT_32bppRGBA8888;
87*89a0ef05SAndroid Build Coastguard Worker if (muxSwitch > 1) sdr_img_fmt = UHDR_IMG_FMT_12bppYCbCr420;
88*89a0ef05SAndroid Build Coastguard Worker
89*89a0ef05SAndroid Build Coastguard Worker // width
90*89a0ef05SAndroid Build Coastguard Worker int width = mFdp.ConsumeIntegralInRange<uint16_t>(kMinWidth, kMaxWidth);
91*89a0ef05SAndroid Build Coastguard Worker if (hdr_img_fmt == UHDR_IMG_FMT_24bppYCbCrP010 || sdr_img_fmt == UHDR_IMG_FMT_12bppYCbCr420) {
92*89a0ef05SAndroid Build Coastguard Worker width = (width >> 1) << 1;
93*89a0ef05SAndroid Build Coastguard Worker }
94*89a0ef05SAndroid Build Coastguard Worker
95*89a0ef05SAndroid Build Coastguard Worker // height
96*89a0ef05SAndroid Build Coastguard Worker int height = mFdp.ConsumeIntegralInRange<uint16_t>(kMinHeight, kMaxHeight);
97*89a0ef05SAndroid Build Coastguard Worker if (hdr_img_fmt == UHDR_IMG_FMT_24bppYCbCrP010 || sdr_img_fmt == UHDR_IMG_FMT_12bppYCbCr420) {
98*89a0ef05SAndroid Build Coastguard Worker height = (height >> 1) << 1;
99*89a0ef05SAndroid Build Coastguard Worker }
100*89a0ef05SAndroid Build Coastguard Worker
101*89a0ef05SAndroid Build Coastguard Worker // hdr Ct
102*89a0ef05SAndroid Build Coastguard Worker auto hdr_ct =
103*89a0ef05SAndroid Build Coastguard Worker static_cast<uhdr_color_transfer_t>(mFdp.ConsumeIntegralInRange<int8_t>(kTfMin, kTfMax));
104*89a0ef05SAndroid Build Coastguard Worker
105*89a0ef05SAndroid Build Coastguard Worker // hdr Cg
106*89a0ef05SAndroid Build Coastguard Worker auto hdr_cg =
107*89a0ef05SAndroid Build Coastguard Worker static_cast<uhdr_color_gamut_t>(mFdp.ConsumeIntegralInRange<int8_t>(kCgMin, kCgMax));
108*89a0ef05SAndroid Build Coastguard Worker
109*89a0ef05SAndroid Build Coastguard Worker // sdr Cg
110*89a0ef05SAndroid Build Coastguard Worker auto sdr_cg =
111*89a0ef05SAndroid Build Coastguard Worker static_cast<uhdr_color_gamut_t>(mFdp.ConsumeIntegralInRange<int8_t>(kCgMin, kCgMax));
112*89a0ef05SAndroid Build Coastguard Worker
113*89a0ef05SAndroid Build Coastguard Worker // color range
114*89a0ef05SAndroid Build Coastguard Worker auto hdr_cr =
115*89a0ef05SAndroid Build Coastguard Worker static_cast<uhdr_color_range_t>(mFdp.ConsumeIntegralInRange<int8_t>(kCrMin, kCrMax));
116*89a0ef05SAndroid Build Coastguard Worker
117*89a0ef05SAndroid Build Coastguard Worker // base quality factor
118*89a0ef05SAndroid Build Coastguard Worker auto base_quality = mFdp.ConsumeIntegral<int8_t>();
119*89a0ef05SAndroid Build Coastguard Worker
120*89a0ef05SAndroid Build Coastguard Worker // gain_map quality factor
121*89a0ef05SAndroid Build Coastguard Worker auto gainmap_quality = mFdp.ConsumeIntegral<int8_t>();
122*89a0ef05SAndroid Build Coastguard Worker
123*89a0ef05SAndroid Build Coastguard Worker // multi channel gainmap
124*89a0ef05SAndroid Build Coastguard Worker auto multi_channel_gainmap = mFdp.ConsumeIntegral<int8_t>();
125*89a0ef05SAndroid Build Coastguard Worker
126*89a0ef05SAndroid Build Coastguard Worker // gainmap scale factor
127*89a0ef05SAndroid Build Coastguard Worker auto gm_scale_factor = mFdp.ConsumeIntegralInRange<int16_t>(-32, 192);
128*89a0ef05SAndroid Build Coastguard Worker
129*89a0ef05SAndroid Build Coastguard Worker // encoding speed preset
130*89a0ef05SAndroid Build Coastguard Worker auto enc_preset = mFdp.ConsumeBool() ? UHDR_USAGE_REALTIME : UHDR_USAGE_BEST_QUALITY;
131*89a0ef05SAndroid Build Coastguard Worker
132*89a0ef05SAndroid Build Coastguard Worker // gainmap metadata
133*89a0ef05SAndroid Build Coastguard Worker auto minBoost = mFdp.ConsumeFloatingPointInRange<float>(-4.0f, 64.0f);
134*89a0ef05SAndroid Build Coastguard Worker auto maxBoost = mFdp.ConsumeFloatingPointInRange<float>(-4.0f, 64.0f);
135*89a0ef05SAndroid Build Coastguard Worker auto gamma = mFdp.ConsumeFloatingPointInRange<float>(-1.0f, 5);
136*89a0ef05SAndroid Build Coastguard Worker auto offsetSdr = mFdp.ConsumeFloatingPointInRange<float>(-1.0f, 1.0f);
137*89a0ef05SAndroid Build Coastguard Worker auto offsetHdr = mFdp.ConsumeFloatingPointInRange<float>(-1.0f, 1.0f);
138*89a0ef05SAndroid Build Coastguard Worker auto minCapacity = mFdp.ConsumeFloatingPointInRange<float>(-4.0f, 48.0f);
139*89a0ef05SAndroid Build Coastguard Worker auto maxCapacity = mFdp.ConsumeFloatingPointInRange<float>(-4.0f, 48.0f);
140*89a0ef05SAndroid Build Coastguard Worker
141*89a0ef05SAndroid Build Coastguard Worker // target display peak brightness
142*89a0ef05SAndroid Build Coastguard Worker auto targetDispPeakBrightness = mFdp.ConsumeFloatingPointInRange<float>(100.0f, 10500.0f);
143*89a0ef05SAndroid Build Coastguard Worker
144*89a0ef05SAndroid Build Coastguard Worker // raw buffer config
145*89a0ef05SAndroid Build Coastguard Worker bool hasHdrStride = mFdp.ConsumeBool();
146*89a0ef05SAndroid Build Coastguard Worker size_t yHdrStride = mFdp.ConsumeIntegralInRange<uint16_t>(width, width + 128);
147*89a0ef05SAndroid Build Coastguard Worker if (!hasHdrStride) yHdrStride = width;
148*89a0ef05SAndroid Build Coastguard Worker bool isHdrUVContiguous = mFdp.ConsumeBool();
149*89a0ef05SAndroid Build Coastguard Worker bool hasHdrUVStride = mFdp.ConsumeBool();
150*89a0ef05SAndroid Build Coastguard Worker size_t uvHdrStride = mFdp.ConsumeIntegralInRange<uint16_t>(width, width + 128);
151*89a0ef05SAndroid Build Coastguard Worker if (!hasHdrUVStride) uvHdrStride = width;
152*89a0ef05SAndroid Build Coastguard Worker
153*89a0ef05SAndroid Build Coastguard Worker bool hasSdrStride = mFdp.ConsumeBool();
154*89a0ef05SAndroid Build Coastguard Worker size_t ySdrStride = mFdp.ConsumeIntegralInRange<uint16_t>(width, width + 128);
155*89a0ef05SAndroid Build Coastguard Worker if (!hasSdrStride) ySdrStride = width;
156*89a0ef05SAndroid Build Coastguard Worker bool isSdrUVContiguous = mFdp.ConsumeBool();
157*89a0ef05SAndroid Build Coastguard Worker bool hasSdrUVStride = mFdp.ConsumeBool();
158*89a0ef05SAndroid Build Coastguard Worker size_t uvSdrStride = mFdp.ConsumeIntegralInRange<uint16_t>(width / 2, width / 2 + 128);
159*89a0ef05SAndroid Build Coastguard Worker if (!hasSdrUVStride) uvSdrStride = width / 2;
160*89a0ef05SAndroid Build Coastguard Worker
161*89a0ef05SAndroid Build Coastguard Worker // editing effects
162*89a0ef05SAndroid Build Coastguard Worker auto applyMirror = mFdp.ConsumeBool();
163*89a0ef05SAndroid Build Coastguard Worker uhdr_mirror_direction_t direction =
164*89a0ef05SAndroid Build Coastguard Worker mFdp.ConsumeBool() ? UHDR_MIRROR_VERTICAL : UHDR_MIRROR_HORIZONTAL;
165*89a0ef05SAndroid Build Coastguard Worker
166*89a0ef05SAndroid Build Coastguard Worker auto applyRotate = mFdp.ConsumeBool();
167*89a0ef05SAndroid Build Coastguard Worker int degrees = degrees = mFdp.PickValueInArray({-90, 0, 90, 180, 270});
168*89a0ef05SAndroid Build Coastguard Worker
169*89a0ef05SAndroid Build Coastguard Worker auto applyCrop = mFdp.ConsumeBool();
170*89a0ef05SAndroid Build Coastguard Worker int left = mFdp.ConsumeIntegral<int16_t>();
171*89a0ef05SAndroid Build Coastguard Worker int right = mFdp.ConsumeIntegral<int16_t>();
172*89a0ef05SAndroid Build Coastguard Worker int top = mFdp.ConsumeIntegral<int16_t>();
173*89a0ef05SAndroid Build Coastguard Worker int bottom = mFdp.ConsumeIntegral<int16_t>();
174*89a0ef05SAndroid Build Coastguard Worker
175*89a0ef05SAndroid Build Coastguard Worker auto applyResize = mFdp.ConsumeBool();
176*89a0ef05SAndroid Build Coastguard Worker int resizeWidth = mFdp.ConsumeIntegralInRange<int32_t>(-32, kMaxWidth + 128);
177*89a0ef05SAndroid Build Coastguard Worker int resizeHeight = mFdp.ConsumeIntegralInRange<int32_t>(-32, kMaxHeight + 128);
178*89a0ef05SAndroid Build Coastguard Worker
179*89a0ef05SAndroid Build Coastguard Worker // exif
180*89a0ef05SAndroid Build Coastguard Worker char greeting[] = "Exif says hello world";
181*89a0ef05SAndroid Build Coastguard Worker uhdr_mem_block_t exif{greeting, mFdp.ConsumeIntegralInRange<uint8_t>(0, sizeof greeting * 2),
182*89a0ef05SAndroid Build Coastguard Worker sizeof greeting};
183*89a0ef05SAndroid Build Coastguard Worker
184*89a0ef05SAndroid Build Coastguard Worker ALOGV("encoding configuration options : ");
185*89a0ef05SAndroid Build Coastguard Worker ALOGV("encoding api - %d ", (int)muxSwitch);
186*89a0ef05SAndroid Build Coastguard Worker ALOGV("image dimensions %d x %d ", (int)width, (int)height);
187*89a0ef05SAndroid Build Coastguard Worker ALOGV("hdr intent color aspects: gamut %d, transfer %d, range %d, format %d ", (int)hdr_cg,
188*89a0ef05SAndroid Build Coastguard Worker (int)hdr_ct, (int)hdr_cr, (int)hdr_img_fmt);
189*89a0ef05SAndroid Build Coastguard Worker ALOGV("sdr intent color aspects: gamut %d, format %d ", (int)sdr_cg, (int)sdr_img_fmt);
190*89a0ef05SAndroid Build Coastguard Worker ALOGV(
191*89a0ef05SAndroid Build Coastguard Worker "gainmap img config: scale factor %d, enabled multichannel gainmap %s, gainmap quality %d ",
192*89a0ef05SAndroid Build Coastguard Worker (int)gm_scale_factor, (int)multi_channel_gainmap ? "Yes" : "No", (int)gainmap_quality);
193*89a0ef05SAndroid Build Coastguard Worker ALOGV("base image quality %d ", (int)base_quality);
194*89a0ef05SAndroid Build Coastguard Worker ALOGV("encoding preset %d ", (int)enc_preset);
195*89a0ef05SAndroid Build Coastguard Worker ALOGV(
196*89a0ef05SAndroid Build Coastguard Worker "gainmap metadata: min content boost %f, max content boost %f, gamma %f, offset sdr %f, "
197*89a0ef05SAndroid Build Coastguard Worker "offset hdr %f, hdr min capacity %f, hdr max capacity %f",
198*89a0ef05SAndroid Build Coastguard Worker (float)minBoost, (float)maxBoost, (float)gamma, (float)offsetSdr, (float)offsetHdr,
199*89a0ef05SAndroid Build Coastguard Worker (float)minCapacity, (float)maxCapacity);
200*89a0ef05SAndroid Build Coastguard Worker ALOGV("hdr intent luma stride %d, chroma stride %d", yHdrStride, uvHdrStride);
201*89a0ef05SAndroid Build Coastguard Worker ALOGV("sdr intent luma stride %d, chroma stride %d", ySdrStride, uvSdrStride);
202*89a0ef05SAndroid Build Coastguard Worker if (applyMirror) ALOGV("added mirror effect, direction %d", (int)direction);
203*89a0ef05SAndroid Build Coastguard Worker if (applyRotate) ALOGV("added rotate effect, degrees %d", (int)degrees);
204*89a0ef05SAndroid Build Coastguard Worker if (applyCrop)
205*89a0ef05SAndroid Build Coastguard Worker ALOGV("added crop effect, crop-left %d, crop-right %d, crop-top %d, crop-bottom %d", left,
206*89a0ef05SAndroid Build Coastguard Worker right, top, bottom);
207*89a0ef05SAndroid Build Coastguard Worker if (applyResize)
208*89a0ef05SAndroid Build Coastguard Worker ALOGV("added resize effect, resize wd %d, resize ht %d", resizeWidth, resizeHeight);
209*89a0ef05SAndroid Build Coastguard Worker
210*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uint64_t[]> bufferFpHdr = nullptr;
211*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uint32_t[]> bufferHdr = nullptr;
212*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uint16_t[]> bufferYHdr = nullptr;
213*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uint16_t[]> bufferUVHdr = nullptr;
214*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uint8_t[]> bufferYSdr = nullptr;
215*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uint8_t[]> bufferUVSdr = nullptr;
216*89a0ef05SAndroid Build Coastguard Worker std::unique_ptr<uint8_t[]> gainMapImageRaw = nullptr;
217*89a0ef05SAndroid Build Coastguard Worker uhdr_codec_private_t* enc_handle = uhdr_create_encoder();
218*89a0ef05SAndroid Build Coastguard Worker if (!enc_handle) {
219*89a0ef05SAndroid Build Coastguard Worker ALOGE("Failed to create encoder");
220*89a0ef05SAndroid Build Coastguard Worker return;
221*89a0ef05SAndroid Build Coastguard Worker }
222*89a0ef05SAndroid Build Coastguard Worker
223*89a0ef05SAndroid Build Coastguard Worker #define ON_ERR(x) \
224*89a0ef05SAndroid Build Coastguard Worker { \
225*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status_ = (x); \
226*89a0ef05SAndroid Build Coastguard Worker if (status_.error_code != UHDR_CODEC_OK) { \
227*89a0ef05SAndroid Build Coastguard Worker if (status_.has_detail) { \
228*89a0ef05SAndroid Build Coastguard Worker ALOGE("%s", status_.detail); \
229*89a0ef05SAndroid Build Coastguard Worker } \
230*89a0ef05SAndroid Build Coastguard Worker } \
231*89a0ef05SAndroid Build Coastguard Worker }
232*89a0ef05SAndroid Build Coastguard Worker if (muxSwitch != 4) {
233*89a0ef05SAndroid Build Coastguard Worker // init p010/rgba1010102 image
234*89a0ef05SAndroid Build Coastguard Worker hdrImg.w = width;
235*89a0ef05SAndroid Build Coastguard Worker hdrImg.h = height;
236*89a0ef05SAndroid Build Coastguard Worker hdrImg.cg = hdr_cg;
237*89a0ef05SAndroid Build Coastguard Worker hdrImg.fmt = hdr_img_fmt;
238*89a0ef05SAndroid Build Coastguard Worker hdrImg.ct = hdr_ct;
239*89a0ef05SAndroid Build Coastguard Worker hdrImg.range = hdr_cr;
240*89a0ef05SAndroid Build Coastguard Worker hdrImg.stride[UHDR_PLANE_Y] = yHdrStride;
241*89a0ef05SAndroid Build Coastguard Worker if (hdr_img_fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
242*89a0ef05SAndroid Build Coastguard Worker if (isHdrUVContiguous) {
243*89a0ef05SAndroid Build Coastguard Worker size_t p010Size = yHdrStride * height * 3 / 2;
244*89a0ef05SAndroid Build Coastguard Worker bufferYHdr = std::make_unique<uint16_t[]>(p010Size);
245*89a0ef05SAndroid Build Coastguard Worker hdrImg.planes[UHDR_PLANE_Y] = bufferYHdr.get();
246*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint16_t>(bufferYHdr.get(), width, height, yHdrStride);
247*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint16_t>(bufferYHdr.get() + yHdrStride * height, width, height / 2,
248*89a0ef05SAndroid Build Coastguard Worker yHdrStride);
249*89a0ef05SAndroid Build Coastguard Worker hdrImg.planes[UHDR_PLANE_UV] = bufferYHdr.get() + yHdrStride * height;
250*89a0ef05SAndroid Build Coastguard Worker hdrImg.stride[UHDR_PLANE_UV] = yHdrStride;
251*89a0ef05SAndroid Build Coastguard Worker } else {
252*89a0ef05SAndroid Build Coastguard Worker size_t p010Size = yHdrStride * height;
253*89a0ef05SAndroid Build Coastguard Worker bufferYHdr = std::make_unique<uint16_t[]>(p010Size);
254*89a0ef05SAndroid Build Coastguard Worker hdrImg.planes[UHDR_PLANE_Y] = bufferYHdr.get();
255*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint16_t>(bufferYHdr.get(), width, height, yHdrStride);
256*89a0ef05SAndroid Build Coastguard Worker size_t p010UVSize = uvHdrStride * hdrImg.h / 2;
257*89a0ef05SAndroid Build Coastguard Worker bufferUVHdr = std::make_unique<uint16_t[]>(p010UVSize);
258*89a0ef05SAndroid Build Coastguard Worker hdrImg.planes[UHDR_PLANE_UV] = bufferUVHdr.get();
259*89a0ef05SAndroid Build Coastguard Worker hdrImg.stride[UHDR_PLANE_UV] = uvHdrStride;
260*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint16_t>(bufferUVHdr.get(), width, height / 2, uvHdrStride);
261*89a0ef05SAndroid Build Coastguard Worker }
262*89a0ef05SAndroid Build Coastguard Worker } else if (hdr_img_fmt == UHDR_IMG_FMT_32bppRGBA1010102) {
263*89a0ef05SAndroid Build Coastguard Worker size_t rgba1010102Size = yHdrStride * height;
264*89a0ef05SAndroid Build Coastguard Worker bufferHdr = std::make_unique<uint32_t[]>(rgba1010102Size);
265*89a0ef05SAndroid Build Coastguard Worker hdrImg.planes[UHDR_PLANE_PACKED] = bufferHdr.get();
266*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint32_t>(bufferHdr.get(), width, height, yHdrStride);
267*89a0ef05SAndroid Build Coastguard Worker hdrImg.planes[UHDR_PLANE_U] = nullptr;
268*89a0ef05SAndroid Build Coastguard Worker hdrImg.stride[UHDR_PLANE_U] = 0;
269*89a0ef05SAndroid Build Coastguard Worker } else if (hdr_img_fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat) {
270*89a0ef05SAndroid Build Coastguard Worker size_t rgbafp16Size = yHdrStride * height;
271*89a0ef05SAndroid Build Coastguard Worker bufferFpHdr = std::make_unique<uint64_t[]>(rgbafp16Size);
272*89a0ef05SAndroid Build Coastguard Worker hdrImg.planes[UHDR_PLANE_PACKED] = bufferFpHdr.get();
273*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint64_t>(bufferFpHdr.get(), width, height, yHdrStride);
274*89a0ef05SAndroid Build Coastguard Worker hdrImg.planes[UHDR_PLANE_U] = nullptr;
275*89a0ef05SAndroid Build Coastguard Worker hdrImg.stride[UHDR_PLANE_U] = 0;
276*89a0ef05SAndroid Build Coastguard Worker }
277*89a0ef05SAndroid Build Coastguard Worker hdrImg.planes[UHDR_PLANE_V] = nullptr;
278*89a0ef05SAndroid Build Coastguard Worker hdrImg.stride[UHDR_PLANE_V] = 0;
279*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_enc_set_raw_image(enc_handle, &hdrImg, UHDR_HDR_IMG))
280*89a0ef05SAndroid Build Coastguard Worker } else {
281*89a0ef05SAndroid Build Coastguard Worker size_t map_width = width / ((gm_scale_factor <= 0) ? 1 : gm_scale_factor);
282*89a0ef05SAndroid Build Coastguard Worker size_t map_height = height / ((gm_scale_factor <= 0) ? 1 : gm_scale_factor);
283*89a0ef05SAndroid Build Coastguard Worker gainmapImg.fmt = UHDR_IMG_FMT_8bppYCbCr400;
284*89a0ef05SAndroid Build Coastguard Worker gainmapImg.w = map_width;
285*89a0ef05SAndroid Build Coastguard Worker gainmapImg.h = map_height;
286*89a0ef05SAndroid Build Coastguard Worker gainmapImg.cg = UHDR_CG_UNSPECIFIED;
287*89a0ef05SAndroid Build Coastguard Worker gainmapImg.ct = UHDR_CT_UNSPECIFIED;
288*89a0ef05SAndroid Build Coastguard Worker gainmapImg.range = UHDR_CR_FULL_RANGE;
289*89a0ef05SAndroid Build Coastguard Worker const size_t graySize = map_width * map_height;
290*89a0ef05SAndroid Build Coastguard Worker gainMapImageRaw = std::make_unique<uint8_t[]>(graySize);
291*89a0ef05SAndroid Build Coastguard Worker gainmapImg.planes[UHDR_PLANE_Y] = gainMapImageRaw.get();
292*89a0ef05SAndroid Build Coastguard Worker gainmapImg.stride[UHDR_PLANE_Y] = map_width;
293*89a0ef05SAndroid Build Coastguard Worker gainmapImg.planes[UHDR_PLANE_U] = nullptr;
294*89a0ef05SAndroid Build Coastguard Worker gainmapImg.planes[UHDR_PLANE_V] = nullptr;
295*89a0ef05SAndroid Build Coastguard Worker gainmapImg.stride[UHDR_PLANE_U] = 0;
296*89a0ef05SAndroid Build Coastguard Worker gainmapImg.stride[UHDR_PLANE_V] = 0;
297*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint8_t>(gainMapImageRaw.get(), map_width, map_height, map_width);
298*89a0ef05SAndroid Build Coastguard Worker }
299*89a0ef05SAndroid Build Coastguard Worker
300*89a0ef05SAndroid Build Coastguard Worker if (muxSwitch > 0) {
301*89a0ef05SAndroid Build Coastguard Worker // init yuv420 Image
302*89a0ef05SAndroid Build Coastguard Worker if (sdr_img_fmt == UHDR_IMG_FMT_12bppYCbCr420) {
303*89a0ef05SAndroid Build Coastguard Worker sdrImg.w = width;
304*89a0ef05SAndroid Build Coastguard Worker sdrImg.h = height;
305*89a0ef05SAndroid Build Coastguard Worker sdrImg.cg = sdr_cg;
306*89a0ef05SAndroid Build Coastguard Worker sdrImg.fmt = UHDR_IMG_FMT_12bppYCbCr420;
307*89a0ef05SAndroid Build Coastguard Worker sdrImg.ct = UHDR_CT_SRGB;
308*89a0ef05SAndroid Build Coastguard Worker sdrImg.range = UHDR_CR_FULL_RANGE;
309*89a0ef05SAndroid Build Coastguard Worker sdrImg.stride[UHDR_PLANE_Y] = ySdrStride;
310*89a0ef05SAndroid Build Coastguard Worker if (isSdrUVContiguous) {
311*89a0ef05SAndroid Build Coastguard Worker size_t yuv420Size = ySdrStride * height * 3 / 2;
312*89a0ef05SAndroid Build Coastguard Worker bufferYSdr = std::make_unique<uint8_t[]>(yuv420Size);
313*89a0ef05SAndroid Build Coastguard Worker sdrImg.planes[UHDR_PLANE_Y] = bufferYSdr.get();
314*89a0ef05SAndroid Build Coastguard Worker sdrImg.planes[UHDR_PLANE_U] = bufferYSdr.get() + ySdrStride * height;
315*89a0ef05SAndroid Build Coastguard Worker sdrImg.planes[UHDR_PLANE_V] = bufferYSdr.get() + ySdrStride * height * 5 / 4;
316*89a0ef05SAndroid Build Coastguard Worker sdrImg.stride[UHDR_PLANE_U] = ySdrStride / 2;
317*89a0ef05SAndroid Build Coastguard Worker sdrImg.stride[UHDR_PLANE_V] = ySdrStride / 2;
318*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint8_t>(bufferYSdr.get(), width, height, ySdrStride);
319*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint8_t>(bufferYSdr.get() + ySdrStride * height, width / 2, height / 2,
320*89a0ef05SAndroid Build Coastguard Worker ySdrStride / 2);
321*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint8_t>(bufferYSdr.get() + ySdrStride * height * 5 / 4, width / 2, height / 2,
322*89a0ef05SAndroid Build Coastguard Worker ySdrStride / 2);
323*89a0ef05SAndroid Build Coastguard Worker } else {
324*89a0ef05SAndroid Build Coastguard Worker size_t yuv420YSize = ySdrStride * height;
325*89a0ef05SAndroid Build Coastguard Worker bufferYSdr = std::make_unique<uint8_t[]>(yuv420YSize);
326*89a0ef05SAndroid Build Coastguard Worker sdrImg.planes[UHDR_PLANE_Y] = bufferYSdr.get();
327*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint8_t>(bufferYSdr.get(), width, height, ySdrStride);
328*89a0ef05SAndroid Build Coastguard Worker size_t yuv420UVSize = uvSdrStride * sdrImg.h / 2 * 2;
329*89a0ef05SAndroid Build Coastguard Worker bufferUVSdr = std::make_unique<uint8_t[]>(yuv420UVSize);
330*89a0ef05SAndroid Build Coastguard Worker sdrImg.planes[UHDR_PLANE_U] = bufferUVSdr.get();
331*89a0ef05SAndroid Build Coastguard Worker sdrImg.stride[UHDR_PLANE_U] = uvSdrStride;
332*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint8_t>(bufferUVSdr.get(), width / 2, height / 2, uvSdrStride);
333*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint8_t>(bufferUVSdr.get() + uvSdrStride * height / 2, width / 2, height / 2,
334*89a0ef05SAndroid Build Coastguard Worker uvSdrStride);
335*89a0ef05SAndroid Build Coastguard Worker sdrImg.planes[UHDR_PLANE_V] = bufferUVSdr.get() + uvSdrStride * height / 2;
336*89a0ef05SAndroid Build Coastguard Worker sdrImg.stride[UHDR_PLANE_V] = uvSdrStride;
337*89a0ef05SAndroid Build Coastguard Worker }
338*89a0ef05SAndroid Build Coastguard Worker } else if (sdr_img_fmt == UHDR_IMG_FMT_32bppRGBA8888) {
339*89a0ef05SAndroid Build Coastguard Worker sdrImg.w = width;
340*89a0ef05SAndroid Build Coastguard Worker sdrImg.h = height;
341*89a0ef05SAndroid Build Coastguard Worker sdrImg.cg = sdr_cg;
342*89a0ef05SAndroid Build Coastguard Worker sdrImg.fmt = UHDR_IMG_FMT_32bppRGBA8888;
343*89a0ef05SAndroid Build Coastguard Worker sdrImg.ct = UHDR_CT_SRGB;
344*89a0ef05SAndroid Build Coastguard Worker sdrImg.range = UHDR_CR_FULL_RANGE;
345*89a0ef05SAndroid Build Coastguard Worker sdrImg.stride[UHDR_PLANE_PACKED] = ySdrStride;
346*89a0ef05SAndroid Build Coastguard Worker size_t rgba8888Size = ySdrStride * height;
347*89a0ef05SAndroid Build Coastguard Worker bufferHdr = std::make_unique<uint32_t[]>(rgba8888Size);
348*89a0ef05SAndroid Build Coastguard Worker sdrImg.planes[UHDR_PLANE_PACKED] = bufferHdr.get();
349*89a0ef05SAndroid Build Coastguard Worker fillBuffer<uint32_t>(bufferHdr.get(), width, height, ySdrStride);
350*89a0ef05SAndroid Build Coastguard Worker sdrImg.planes[UHDR_PLANE_U] = nullptr;
351*89a0ef05SAndroid Build Coastguard Worker sdrImg.planes[UHDR_PLANE_V] = nullptr;
352*89a0ef05SAndroid Build Coastguard Worker sdrImg.stride[UHDR_PLANE_U] = 0;
353*89a0ef05SAndroid Build Coastguard Worker sdrImg.stride[UHDR_PLANE_V] = 0;
354*89a0ef05SAndroid Build Coastguard Worker }
355*89a0ef05SAndroid Build Coastguard Worker }
356*89a0ef05SAndroid Build Coastguard Worker if (muxSwitch == 1 || muxSwitch == 2) {
357*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_enc_set_raw_image(enc_handle, &sdrImg, UHDR_SDR_IMG))
358*89a0ef05SAndroid Build Coastguard Worker }
359*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_enc_set_quality(enc_handle, base_quality, UHDR_BASE_IMG))
360*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_enc_set_quality(enc_handle, gainmap_quality, UHDR_GAIN_MAP_IMG))
361*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_enc_set_exif_data(enc_handle, &exif))
362*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_enc_set_using_multi_channel_gainmap(enc_handle, multi_channel_gainmap))
363*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_enc_set_gainmap_scale_factor(enc_handle, gm_scale_factor))
364*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_enc_set_gainmap_gamma(enc_handle, gamma))
365*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_enc_set_min_max_content_boost(enc_handle, minBoost, maxBoost))
366*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_enc_set_target_display_peak_brightness(enc_handle, targetDispPeakBrightness))
367*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_enc_set_preset(enc_handle, enc_preset))
368*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_enable_gpu_acceleration(enc_handle, 1))
369*89a0ef05SAndroid Build Coastguard Worker if (applyMirror) ON_ERR(uhdr_add_effect_mirror(enc_handle, direction))
370*89a0ef05SAndroid Build Coastguard Worker if (applyRotate) ON_ERR(uhdr_add_effect_rotate(enc_handle, degrees))
371*89a0ef05SAndroid Build Coastguard Worker if (applyCrop) ON_ERR(uhdr_add_effect_crop(enc_handle, left, right, top, bottom))
372*89a0ef05SAndroid Build Coastguard Worker if (applyResize) ON_ERR(uhdr_add_effect_resize(enc_handle, resizeWidth, resizeHeight))
373*89a0ef05SAndroid Build Coastguard Worker
374*89a0ef05SAndroid Build Coastguard Worker uhdr_error_info_t status = {UHDR_CODEC_OK, 0, ""};
375*89a0ef05SAndroid Build Coastguard Worker if (muxSwitch == 0 || muxSwitch == 1) { // api 0 or api 1
376*89a0ef05SAndroid Build Coastguard Worker status = uhdr_encode(enc_handle);
377*89a0ef05SAndroid Build Coastguard Worker } else {
378*89a0ef05SAndroid Build Coastguard Worker // compressed img
379*89a0ef05SAndroid Build Coastguard Worker JpegEncoderHelper encoder;
380*89a0ef05SAndroid Build Coastguard Worker if (encoder.compressImage(&sdrImg, base_quality, nullptr, 0).error_code == UHDR_CODEC_OK) {
381*89a0ef05SAndroid Build Coastguard Worker struct uhdr_compressed_image jpegImg = encoder.getCompressedImage();
382*89a0ef05SAndroid Build Coastguard Worker jpegImg.cg = sdr_cg;
383*89a0ef05SAndroid Build Coastguard Worker if (muxSwitch != 4) {
384*89a0ef05SAndroid Build Coastguard Worker // for api 4 compressed image will be set with UHDR_BASE_IMG intent
385*89a0ef05SAndroid Build Coastguard Worker uhdr_enc_set_compressed_image(enc_handle, &jpegImg, UHDR_SDR_IMG);
386*89a0ef05SAndroid Build Coastguard Worker }
387*89a0ef05SAndroid Build Coastguard Worker if (muxSwitch == 2 || muxSwitch == 3) { // api 2 or api 3
388*89a0ef05SAndroid Build Coastguard Worker status = uhdr_encode(enc_handle);
389*89a0ef05SAndroid Build Coastguard Worker } else if (muxSwitch == 4) { // api 4
390*89a0ef05SAndroid Build Coastguard Worker JpegEncoderHelper gainMapEncoder;
391*89a0ef05SAndroid Build Coastguard Worker if (gainMapEncoder.compressImage(&gainmapImg, gainmap_quality, nullptr, 0).error_code ==
392*89a0ef05SAndroid Build Coastguard Worker UHDR_CODEC_OK) {
393*89a0ef05SAndroid Build Coastguard Worker struct uhdr_compressed_image jpegGainMap = gainMapEncoder.getCompressedImage();
394*89a0ef05SAndroid Build Coastguard Worker uhdr_gainmap_metadata metadata;
395*89a0ef05SAndroid Build Coastguard Worker metadata.max_content_boost = maxBoost;
396*89a0ef05SAndroid Build Coastguard Worker metadata.min_content_boost = minBoost;
397*89a0ef05SAndroid Build Coastguard Worker metadata.gamma = gamma;
398*89a0ef05SAndroid Build Coastguard Worker metadata.offset_sdr = offsetSdr;
399*89a0ef05SAndroid Build Coastguard Worker metadata.offset_hdr = offsetHdr;
400*89a0ef05SAndroid Build Coastguard Worker metadata.hdr_capacity_min = minCapacity;
401*89a0ef05SAndroid Build Coastguard Worker metadata.hdr_capacity_max = maxCapacity;
402*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_enc_set_compressed_image(enc_handle, &jpegImg, UHDR_BASE_IMG))
403*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_enc_set_gainmap_image(enc_handle, &jpegGainMap, &metadata))
404*89a0ef05SAndroid Build Coastguard Worker status = uhdr_encode(enc_handle);
405*89a0ef05SAndroid Build Coastguard Worker }
406*89a0ef05SAndroid Build Coastguard Worker }
407*89a0ef05SAndroid Build Coastguard Worker }
408*89a0ef05SAndroid Build Coastguard Worker }
409*89a0ef05SAndroid Build Coastguard Worker if (status.error_code == UHDR_CODEC_OK) {
410*89a0ef05SAndroid Build Coastguard Worker auto output = uhdr_get_encoded_stream(enc_handle);
411*89a0ef05SAndroid Build Coastguard Worker if (output != nullptr) {
412*89a0ef05SAndroid Build Coastguard Worker uhdr_codec_private_t* dec_handle = uhdr_create_decoder();
413*89a0ef05SAndroid Build Coastguard Worker if (dec_handle) {
414*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_dec_set_image(dec_handle, output))
415*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_dec_set_out_color_transfer(dec_handle, hdr_ct))
416*89a0ef05SAndroid Build Coastguard Worker if (hdr_ct == UHDR_CT_LINEAR)
417*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_dec_set_out_img_format(dec_handle, UHDR_IMG_FMT_64bppRGBAHalfFloat))
418*89a0ef05SAndroid Build Coastguard Worker else if (hdr_ct == UHDR_CT_SRGB)
419*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_dec_set_out_img_format(dec_handle, UHDR_IMG_FMT_32bppRGBA8888))
420*89a0ef05SAndroid Build Coastguard Worker else
421*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_dec_set_out_img_format(dec_handle, UHDR_IMG_FMT_32bppRGBA1010102))
422*89a0ef05SAndroid Build Coastguard Worker ON_ERR(uhdr_decode(dec_handle))
423*89a0ef05SAndroid Build Coastguard Worker uhdr_release_decoder(dec_handle);
424*89a0ef05SAndroid Build Coastguard Worker }
425*89a0ef05SAndroid Build Coastguard Worker }
426*89a0ef05SAndroid Build Coastguard Worker }
427*89a0ef05SAndroid Build Coastguard Worker uhdr_reset_encoder(enc_handle);
428*89a0ef05SAndroid Build Coastguard Worker uhdr_release_encoder(enc_handle);
429*89a0ef05SAndroid Build Coastguard Worker ON_ERR(status);
430*89a0ef05SAndroid Build Coastguard Worker }
431*89a0ef05SAndroid Build Coastguard Worker }
432*89a0ef05SAndroid Build Coastguard Worker
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)433*89a0ef05SAndroid Build Coastguard Worker extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
434*89a0ef05SAndroid Build Coastguard Worker UltraHdrEncFuzzer fuzzHandle(data, size);
435*89a0ef05SAndroid Build Coastguard Worker fuzzHandle.process();
436*89a0ef05SAndroid Build Coastguard Worker return 0;
437*89a0ef05SAndroid Build Coastguard Worker }
438