Coverage Report

Created: 2025-10-10 07:34

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