| /* |
| * Copyright 2023 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <fuzzer/FuzzedDataProvider.h> |
| #include <algorithm> |
| #include <random> |
| #include <type_traits> |
| |
| #include "ultrahdr_api.h" |
| #include "ultrahdr/ultrahdrcommon.h" |
| #include "ultrahdr/jpegr.h" |
| |
| using namespace ultrahdr; |
| |
| // Color gamuts for image data, sync with ultrahdr_api.h |
| constexpr int kCgMin = UHDR_CG_UNSPECIFIED; |
| constexpr int kCgMax = UHDR_CG_BT_2100; |
| |
| // Color ranges for image data, sync with ultrahdr_api.h |
| constexpr int kCrMin = UHDR_CR_UNSPECIFIED; |
| constexpr int kCrMax = UHDR_CR_FULL_RANGE; |
| |
| // Transfer functions for image data, sync with ultrahdr_api.h |
| constexpr int kTfMin = UHDR_CT_UNSPECIFIED; |
| constexpr int kTfMax = UHDR_CT_SRGB; |
| |
| class UltraHdrEncFuzzer { |
| public: |
| UltraHdrEncFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {}; |
| void process(); |
| template <typename T> |
| void fillBuffer(T* data, int width, int height, int stride); |
| |
| private: |
| FuzzedDataProvider mFdp; |
| }; |
| |
| template <typename T> |
| void UltraHdrEncFuzzer::fillBuffer(T* data, int width, int height, int stride) { |
| if (!mFdp.remaining_bytes()) return; |
| |
| T* tmp = data; |
| std::vector<T> buffer(width); |
| for (int i = 0; i < buffer.size(); i++) { |
| buffer[i] = mFdp.ConsumeIntegral<T>(); |
| } |
| for (int j = 0; j < height; j++) { |
| for (int i = 0; i < width; i += buffer.size()) { |
| memcpy(tmp + i, buffer.data(), std::min((int)buffer.size(), (width - i)) * sizeof(*data)); |
| std::shuffle(buffer.begin(), buffer.end(), |
| std::default_random_engine(std::random_device{}())); |
| } |
| tmp += stride; |
| } |
| } |
| |
| void UltraHdrEncFuzzer::process() { |
| if (mFdp.remaining_bytes()) { |
| struct uhdr_raw_image hdrImg{}; |
| struct uhdr_raw_image sdrImg{}; |
| struct uhdr_raw_image gainmapImg{}; |
| |
| // which encode api to select |
| int muxSwitch = mFdp.ConsumeIntegralInRange<int8_t>(0, 4); |
| |
| // hdr_img_fmt |
| auto hdr_img_fmt = |
| mFdp.ConsumeBool() ? UHDR_IMG_FMT_24bppYCbCrP010 : UHDR_IMG_FMT_32bppRGBA1010102; |
| |
| // sdr_img_fmt |
| uhdr_img_fmt_t sdr_img_fmt = |
| mFdp.ConsumeBool() ? UHDR_IMG_FMT_12bppYCbCr420 : UHDR_IMG_FMT_32bppRGBA8888; |
| if (muxSwitch > 1) sdr_img_fmt = UHDR_IMG_FMT_12bppYCbCr420; |
| |
| // width |
| int width = mFdp.ConsumeIntegralInRange<uint16_t>(kMinWidth, kMaxWidth); |
| if (hdr_img_fmt == UHDR_IMG_FMT_24bppYCbCrP010 || sdr_img_fmt == UHDR_IMG_FMT_12bppYCbCr420) { |
| width = (width >> 1) << 1; |
| } |
| |
| // height |
| int height = mFdp.ConsumeIntegralInRange<uint16_t>(kMinHeight, kMaxHeight); |
| if (hdr_img_fmt == UHDR_IMG_FMT_24bppYCbCrP010 || sdr_img_fmt == UHDR_IMG_FMT_12bppYCbCr420) { |
| height = (height >> 1) << 1; |
| } |
| |
| // hdr Ct |
| auto hdr_ct = |
| static_cast<uhdr_color_transfer_t>(mFdp.ConsumeIntegralInRange<int8_t>(kTfMin, kTfMax)); |
| |
| // hdr Cg |
| auto hdr_cg = |
| static_cast<uhdr_color_gamut_t>(mFdp.ConsumeIntegralInRange<int8_t>(kCgMin, kCgMax)); |
| |
| // sdr Cg |
| auto sdr_cg = |
| static_cast<uhdr_color_gamut_t>(mFdp.ConsumeIntegralInRange<int8_t>(kCgMin, kCgMax)); |
| |
| // color range |
| auto hdr_cr = |
| static_cast<uhdr_color_range_t>(mFdp.ConsumeIntegralInRange<int8_t>(kCrMin, kCrMax)); |
| |
| // base quality factor |
| auto base_quality = mFdp.ConsumeIntegral<int8_t>(); |
| |
| // gain_map quality factor |
| auto gainmap_quality = mFdp.ConsumeIntegral<int8_t>(); |
| |
| // multi channel gainmap |
| auto multi_channel_gainmap = mFdp.ConsumeIntegral<int8_t>(); |
| |
| // gainmap scale factor |
| auto gm_scale_factor = mFdp.ConsumeIntegralInRange<int16_t>(-32, 192); |
| |
| // encoding speed preset |
| auto enc_preset = mFdp.ConsumeBool() ? UHDR_USAGE_REALTIME : UHDR_USAGE_BEST_QUALITY; |
| |
| // gainmap metadata |
| auto minBoost = mFdp.ConsumeFloatingPointInRange<float>(-4.0f, 64.0f); |
| auto maxBoost = mFdp.ConsumeFloatingPointInRange<float>(-4.0f, 64.0f); |
| auto gamma = mFdp.ConsumeFloatingPointInRange<float>(-1.0f, 5); |
| auto offsetSdr = mFdp.ConsumeFloatingPointInRange<float>(-1.0f, 1.0f); |
| auto offsetHdr = mFdp.ConsumeFloatingPointInRange<float>(-1.0f, 1.0f); |
| auto minCapacity = mFdp.ConsumeFloatingPointInRange<float>(-4.0f, 48.0f); |
| auto maxCapacity = mFdp.ConsumeFloatingPointInRange<float>(-4.0f, 48.0f); |
| |
| // target display peak brightness |
| auto targetDispPeakBrightness = mFdp.ConsumeFloatingPointInRange<float>(100.0f, 10500.0f); |
| |
| // raw buffer config |
| bool hasHdrStride = mFdp.ConsumeBool(); |
| size_t yHdrStride = mFdp.ConsumeIntegralInRange<uint16_t>(width, width + 128); |
| if (!hasHdrStride) yHdrStride = width; |
| bool isHdrUVContiguous = mFdp.ConsumeBool(); |
| bool hasHdrUVStride = mFdp.ConsumeBool(); |
| size_t uvHdrStride = mFdp.ConsumeIntegralInRange<uint16_t>(width, width + 128); |
| if (!hasHdrUVStride) uvHdrStride = width; |
| |
| bool hasSdrStride = mFdp.ConsumeBool(); |
| size_t ySdrStride = mFdp.ConsumeIntegralInRange<uint16_t>(width, width + 128); |
| if (!hasSdrStride) ySdrStride = width; |
| bool isSdrUVContiguous = mFdp.ConsumeBool(); |
| bool hasSdrUVStride = mFdp.ConsumeBool(); |
| size_t uvSdrStride = mFdp.ConsumeIntegralInRange<uint16_t>(width / 2, width / 2 + 128); |
| if (!hasSdrUVStride) uvSdrStride = width / 2; |
| |
| // editing effects |
| auto applyMirror = mFdp.ConsumeBool(); |
| uhdr_mirror_direction_t direction = |
| mFdp.ConsumeBool() ? UHDR_MIRROR_VERTICAL : UHDR_MIRROR_HORIZONTAL; |
| |
| auto applyRotate = mFdp.ConsumeBool(); |
| int degrees = degrees = mFdp.PickValueInArray({-90, 0, 90, 180, 270}); |
| |
| auto applyCrop = mFdp.ConsumeBool(); |
| int left = mFdp.ConsumeIntegral<int16_t>(); |
| int right = mFdp.ConsumeIntegral<int16_t>(); |
| int top = mFdp.ConsumeIntegral<int16_t>(); |
| int bottom = mFdp.ConsumeIntegral<int16_t>(); |
| |
| auto applyResize = mFdp.ConsumeBool(); |
| int resizeWidth = mFdp.ConsumeIntegralInRange<int32_t>(-32, kMaxWidth + 128); |
| int resizeHeight = mFdp.ConsumeIntegralInRange<int32_t>(-32, kMaxHeight + 128); |
| |
| // exif |
| char greeting[] = "Exif says hello world"; |
| uhdr_mem_block_t exif{greeting, mFdp.ConsumeIntegralInRange<uint8_t>(0, sizeof greeting * 2), |
| sizeof greeting}; |
| |
| ALOGV("encoding configuration options : "); |
| ALOGV("encoding api - %d ", (int)muxSwitch); |
| ALOGV("image dimensions %d x %d ", (int)width, (int)height); |
| ALOGV("hdr intent color aspects: gamut %d, transfer %d, range %d, format %d ", (int)hdr_cg, |
| (int)hdr_ct, (int)hdr_cr, (int)hdr_img_fmt); |
| ALOGV("sdr intent color aspects: gamut %d, format %d ", (int)sdr_cg, (int)sdr_img_fmt); |
| ALOGV( |
| "gainmap img config: scale factor %d, enabled multichannel gainmap %s, gainmap quality %d ", |
| (int)gm_scale_factor, (int)multi_channel_gainmap ? "Yes" : "No", (int)gainmap_quality); |
| ALOGV("base image quality %d ", (int)base_quality); |
| ALOGV("encoding preset %d ", (int)enc_preset); |
| ALOGV( |
| "gainmap metadata: min content boost %f, max content boost %f, gamma %f, offset sdr %f, " |
| "offset hdr %f, hdr min capacity %f, hdr max capacity %f", |
| (float)minBoost, (float)maxBoost, (float)gamma, (float)offsetSdr, (float)offsetHdr, |
| (float)minCapacity, (float)maxCapacity); |
| ALOGV("hdr intent luma stride %d, chroma stride %d", yHdrStride, uvHdrStride); |
| ALOGV("sdr intent luma stride %d, chroma stride %d", ySdrStride, uvSdrStride); |
| if (applyMirror) ALOGV("added mirror effect, direction %d", (int)direction); |
| if (applyRotate) ALOGV("added rotate effect, degrees %d", (int)degrees); |
| if (applyCrop) |
| ALOGV("added crop effect, crop-left %d, crop-right %d, crop-top %d, crop-bottom %d", left, |
| right, top, bottom); |
| if (applyResize) |
| ALOGV("added resize effect, resize wd %d, resize ht %d", resizeWidth, resizeHeight); |
| |
| std::unique_ptr<uint32_t[]> bufferHdr = nullptr; |
| std::unique_ptr<uint16_t[]> bufferYHdr = nullptr; |
| std::unique_ptr<uint16_t[]> bufferUVHdr = nullptr; |
| std::unique_ptr<uint8_t[]> bufferYSdr = nullptr; |
| std::unique_ptr<uint8_t[]> bufferUVSdr = nullptr; |
| std::unique_ptr<uint8_t[]> gainMapImageRaw = nullptr; |
| uhdr_codec_private_t* enc_handle = uhdr_create_encoder(); |
| if (!enc_handle) { |
| ALOGE("Failed to create encoder"); |
| return; |
| } |
| |
| #define ON_ERR(x) \ |
| { \ |
| uhdr_error_info_t status_ = (x); \ |
| if (status_.error_code != UHDR_CODEC_OK) { \ |
| if (status_.has_detail) { \ |
| ALOGE("%s", status_.detail); \ |
| } \ |
| } \ |
| } |
| if (muxSwitch != 4) { |
| // init p010/rgba1010102 image |
| hdrImg.w = width; |
| hdrImg.h = height; |
| hdrImg.cg = hdr_cg; |
| hdrImg.fmt = hdr_img_fmt; |
| hdrImg.ct = hdr_ct; |
| hdrImg.range = hdr_cr; |
| hdrImg.stride[UHDR_PLANE_Y] = yHdrStride; |
| if (hdr_img_fmt == UHDR_IMG_FMT_24bppYCbCrP010) { |
| if (isHdrUVContiguous) { |
| size_t p010Size = yHdrStride * height * 3 / 2; |
| bufferYHdr = std::make_unique<uint16_t[]>(p010Size); |
| hdrImg.planes[UHDR_PLANE_Y] = bufferYHdr.get(); |
| fillBuffer<uint16_t>(bufferYHdr.get(), width, height, yHdrStride); |
| fillBuffer<uint16_t>(bufferYHdr.get() + yHdrStride * height, width, height / 2, |
| yHdrStride); |
| hdrImg.planes[UHDR_PLANE_UV] = bufferYHdr.get() + yHdrStride * height; |
| hdrImg.stride[UHDR_PLANE_UV] = yHdrStride; |
| } else { |
| size_t p010Size = yHdrStride * height; |
| bufferYHdr = std::make_unique<uint16_t[]>(p010Size); |
| hdrImg.planes[UHDR_PLANE_Y] = bufferYHdr.get(); |
| fillBuffer<uint16_t>(bufferYHdr.get(), width, height, yHdrStride); |
| size_t p010UVSize = uvHdrStride * hdrImg.h / 2; |
| bufferUVHdr = std::make_unique<uint16_t[]>(p010UVSize); |
| hdrImg.planes[UHDR_PLANE_UV] = bufferUVHdr.get(); |
| hdrImg.stride[UHDR_PLANE_UV] = uvHdrStride; |
| fillBuffer<uint16_t>(bufferUVHdr.get(), width, height / 2, uvHdrStride); |
| } |
| } else if (hdr_img_fmt == UHDR_IMG_FMT_32bppRGBA1010102) { |
| size_t rgba1010102Size = yHdrStride * height; |
| bufferHdr = std::make_unique<uint32_t[]>(rgba1010102Size); |
| hdrImg.planes[UHDR_PLANE_PACKED] = bufferHdr.get(); |
| fillBuffer<uint32_t>(bufferHdr.get(), width, height, yHdrStride); |
| hdrImg.planes[UHDR_PLANE_U] = nullptr; |
| hdrImg.stride[UHDR_PLANE_U] = 0; |
| } |
| hdrImg.planes[UHDR_PLANE_V] = nullptr; |
| hdrImg.stride[UHDR_PLANE_V] = 0; |
| ON_ERR(uhdr_enc_set_raw_image(enc_handle, &hdrImg, UHDR_HDR_IMG)) |
| } else { |
| size_t map_width = width / ((gm_scale_factor <= 0) ? 1 : gm_scale_factor); |
| size_t map_height = height / ((gm_scale_factor <= 0) ? 1 : gm_scale_factor); |
| gainmapImg.fmt = UHDR_IMG_FMT_8bppYCbCr400; |
| gainmapImg.w = map_width; |
| gainmapImg.h = map_height; |
| gainmapImg.cg = UHDR_CG_UNSPECIFIED; |
| gainmapImg.ct = UHDR_CT_UNSPECIFIED; |
| gainmapImg.range = UHDR_CR_FULL_RANGE; |
| const size_t graySize = map_width * map_height; |
| gainMapImageRaw = std::make_unique<uint8_t[]>(graySize); |
| gainmapImg.planes[UHDR_PLANE_Y] = gainMapImageRaw.get(); |
| gainmapImg.stride[UHDR_PLANE_Y] = map_width; |
| gainmapImg.planes[UHDR_PLANE_U] = nullptr; |
| gainmapImg.planes[UHDR_PLANE_V] = nullptr; |
| gainmapImg.stride[UHDR_PLANE_U] = 0; |
| gainmapImg.stride[UHDR_PLANE_V] = 0; |
| fillBuffer<uint8_t>(gainMapImageRaw.get(), map_width, map_height, map_width); |
| } |
| |
| if (muxSwitch > 0) { |
| // init yuv420 Image |
| if (sdr_img_fmt == UHDR_IMG_FMT_12bppYCbCr420) { |
| sdrImg.w = width; |
| sdrImg.h = height; |
| sdrImg.cg = sdr_cg; |
| sdrImg.fmt = UHDR_IMG_FMT_12bppYCbCr420; |
| sdrImg.ct = UHDR_CT_SRGB; |
| sdrImg.range = UHDR_CR_FULL_RANGE; |
| sdrImg.stride[UHDR_PLANE_Y] = ySdrStride; |
| if (isSdrUVContiguous) { |
| size_t yuv420Size = ySdrStride * height * 3 / 2; |
| bufferYSdr = std::make_unique<uint8_t[]>(yuv420Size); |
| sdrImg.planes[UHDR_PLANE_Y] = bufferYSdr.get(); |
| sdrImg.planes[UHDR_PLANE_U] = bufferYSdr.get() + ySdrStride * height; |
| sdrImg.planes[UHDR_PLANE_V] = bufferYSdr.get() + ySdrStride * height * 5 / 4; |
| sdrImg.stride[UHDR_PLANE_U] = ySdrStride / 2; |
| sdrImg.stride[UHDR_PLANE_V] = ySdrStride / 2; |
| fillBuffer<uint8_t>(bufferYSdr.get(), width, height, ySdrStride); |
| fillBuffer<uint8_t>(bufferYSdr.get() + ySdrStride * height, width / 2, height / 2, |
| ySdrStride / 2); |
| fillBuffer<uint8_t>(bufferYSdr.get() + ySdrStride * height * 5 / 4, width / 2, height / 2, |
| ySdrStride / 2); |
| } else { |
| size_t yuv420YSize = ySdrStride * height; |
| bufferYSdr = std::make_unique<uint8_t[]>(yuv420YSize); |
| sdrImg.planes[UHDR_PLANE_Y] = bufferYSdr.get(); |
| fillBuffer<uint8_t>(bufferYSdr.get(), width, height, ySdrStride); |
| size_t yuv420UVSize = uvSdrStride * sdrImg.h / 2 * 2; |
| bufferUVSdr = std::make_unique<uint8_t[]>(yuv420UVSize); |
| sdrImg.planes[UHDR_PLANE_U] = bufferUVSdr.get(); |
| sdrImg.stride[UHDR_PLANE_U] = uvSdrStride; |
| fillBuffer<uint8_t>(bufferUVSdr.get(), width / 2, height / 2, uvSdrStride); |
| fillBuffer<uint8_t>(bufferUVSdr.get() + uvSdrStride * height / 2, width / 2, height / 2, |
| uvSdrStride); |
| sdrImg.planes[UHDR_PLANE_V] = bufferUVSdr.get() + uvSdrStride * height / 2; |
| sdrImg.stride[UHDR_PLANE_V] = uvSdrStride; |
| } |
| } else if (sdr_img_fmt == UHDR_IMG_FMT_32bppRGBA8888) { |
| sdrImg.w = width; |
| sdrImg.h = height; |
| sdrImg.cg = sdr_cg; |
| sdrImg.fmt = UHDR_IMG_FMT_32bppRGBA8888; |
| sdrImg.ct = UHDR_CT_SRGB; |
| sdrImg.range = UHDR_CR_FULL_RANGE; |
| sdrImg.stride[UHDR_PLANE_PACKED] = ySdrStride; |
| size_t rgba8888Size = ySdrStride * height; |
| bufferHdr = std::make_unique<uint32_t[]>(rgba8888Size); |
| sdrImg.planes[UHDR_PLANE_PACKED] = bufferHdr.get(); |
| fillBuffer<uint32_t>(bufferHdr.get(), width, height, ySdrStride); |
| sdrImg.planes[UHDR_PLANE_U] = nullptr; |
| sdrImg.planes[UHDR_PLANE_V] = nullptr; |
| sdrImg.stride[UHDR_PLANE_U] = 0; |
| sdrImg.stride[UHDR_PLANE_V] = 0; |
| } |
| } |
| if (muxSwitch == 1 || muxSwitch == 2) { |
| ON_ERR(uhdr_enc_set_raw_image(enc_handle, &sdrImg, UHDR_SDR_IMG)) |
| } |
| ON_ERR(uhdr_enc_set_quality(enc_handle, base_quality, UHDR_BASE_IMG)) |
| ON_ERR(uhdr_enc_set_quality(enc_handle, gainmap_quality, UHDR_GAIN_MAP_IMG)) |
| ON_ERR(uhdr_enc_set_exif_data(enc_handle, &exif)) |
| ON_ERR(uhdr_enc_set_using_multi_channel_gainmap(enc_handle, multi_channel_gainmap)) |
| ON_ERR(uhdr_enc_set_gainmap_scale_factor(enc_handle, gm_scale_factor)) |
| ON_ERR(uhdr_enc_set_gainmap_gamma(enc_handle, gamma)) |
| ON_ERR(uhdr_enc_set_min_max_content_boost(enc_handle, minBoost, maxBoost)) |
| ON_ERR(uhdr_enc_set_target_display_peak_brightness(enc_handle, targetDispPeakBrightness)) |
| ON_ERR(uhdr_enc_set_preset(enc_handle, enc_preset)) |
| ON_ERR(uhdr_enable_gpu_acceleration(enc_handle, 1)) |
| if (applyMirror) ON_ERR(uhdr_add_effect_mirror(enc_handle, direction)) |
| if (applyRotate) ON_ERR(uhdr_add_effect_rotate(enc_handle, degrees)) |
| if (applyCrop) ON_ERR(uhdr_add_effect_crop(enc_handle, left, right, top, bottom)) |
| if (applyResize) ON_ERR(uhdr_add_effect_resize(enc_handle, resizeWidth, resizeHeight)) |
| |
| uhdr_error_info_t status = {UHDR_CODEC_OK, 0, ""}; |
| if (muxSwitch == 0 || muxSwitch == 1) { // api 0 or api 1 |
| status = uhdr_encode(enc_handle); |
| } else { |
| // compressed img |
| JpegEncoderHelper encoder; |
| if (encoder.compressImage(&sdrImg, base_quality, nullptr, 0).error_code == UHDR_CODEC_OK) { |
| struct uhdr_compressed_image jpegImg = encoder.getCompressedImage(); |
| jpegImg.cg = sdr_cg; |
| if (muxSwitch != 4) { |
| // for api 4 compressed image will be set with UHDR_BASE_IMG intent |
| uhdr_enc_set_compressed_image(enc_handle, &jpegImg, UHDR_SDR_IMG); |
| } |
| if (muxSwitch == 2 || muxSwitch == 3) { // api 2 or api 3 |
| status = uhdr_encode(enc_handle); |
| } else if (muxSwitch == 4) { // api 4 |
| JpegEncoderHelper gainMapEncoder; |
| if (gainMapEncoder.compressImage(&gainmapImg, gainmap_quality, nullptr, 0).error_code == |
| UHDR_CODEC_OK) { |
| struct uhdr_compressed_image jpegGainMap = gainMapEncoder.getCompressedImage(); |
| uhdr_gainmap_metadata metadata; |
| metadata.max_content_boost = maxBoost; |
| metadata.min_content_boost = minBoost; |
| metadata.gamma = gamma; |
| metadata.offset_sdr = offsetSdr; |
| metadata.offset_hdr = offsetHdr; |
| metadata.hdr_capacity_min = minCapacity; |
| metadata.hdr_capacity_max = maxCapacity; |
| ON_ERR(uhdr_enc_set_compressed_image(enc_handle, &jpegImg, UHDR_BASE_IMG)) |
| ON_ERR(uhdr_enc_set_gainmap_image(enc_handle, &jpegGainMap, &metadata)) |
| status = uhdr_encode(enc_handle); |
| } |
| } |
| } |
| } |
| if (status.error_code == UHDR_CODEC_OK) { |
| auto output = uhdr_get_encoded_stream(enc_handle); |
| if (output != nullptr) { |
| uhdr_codec_private_t* dec_handle = uhdr_create_decoder(); |
| if (dec_handle) { |
| ON_ERR(uhdr_dec_set_image(dec_handle, output)) |
| ON_ERR(uhdr_dec_set_out_color_transfer(dec_handle, hdr_ct)) |
| if (hdr_ct == UHDR_CT_LINEAR) |
| ON_ERR(uhdr_dec_set_out_img_format(dec_handle, UHDR_IMG_FMT_64bppRGBAHalfFloat)) |
| else if (hdr_ct == UHDR_CT_SRGB) |
| ON_ERR(uhdr_dec_set_out_img_format(dec_handle, UHDR_IMG_FMT_32bppRGBA8888)) |
| else |
| ON_ERR(uhdr_dec_set_out_img_format(dec_handle, UHDR_IMG_FMT_32bppRGBA1010102)) |
| ON_ERR(uhdr_decode(dec_handle)) |
| uhdr_release_decoder(dec_handle); |
| } |
| } |
| } |
| uhdr_reset_encoder(enc_handle); |
| uhdr_release_encoder(enc_handle); |
| ON_ERR(status); |
| } |
| } |
| |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
| UltraHdrEncFuzzer fuzzHandle(data, size); |
| fuzzHandle.process(); |
| return 0; |
| } |