• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ext_decoder.h"
17 
18 #include <algorithm>
19 #include <map>
20 #include <sstream>
21 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
22 #include <sys/ioctl.h>
23 #include <sys/timerfd.h>
24 #include <linux/dma-buf.h>
25 #endif
26 
27 #include "src/codec/SkJpegCodec.h"
28 #include "src/codec/SkJpegDecoderMgr.h"
29 #include "ext_pixel_convert.h"
30 #ifdef SK_ENABLE_OHOS_CODEC
31 #include "sk_ohoscodec.h"
32 #endif
33 #include "image_log.h"
34 #include "image_format_convert.h"
35 #include "image_mime_type.h"
36 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
37 #include "ffrt.h"
38 #include "hisysevent.h"
39 #endif
40 #include "image_system_properties.h"
41 #include "image_utils.h"
42 #include "image_func_timer.h"
43 #include "media_errors.h"
44 #include "native_buffer.h"
45 #include "securec.h"
46 #include "string_ex.h"
47 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
48 #include "surface_buffer.h"
49 #include "hdr_helper.h"
50 #endif
51 #ifdef HEIF_HW_DECODE_ENABLE
52 #include "heif_impl/HeifDecoder.h"
53 #include "heif_impl/HeifDecoderImpl.h"
54 #endif
55 #include "color_utils.h"
56 #include "heif_parser.h"
57 #include "heif_format_agent.h"
58 #include "image_trace.h"
59 #include "heif_type.h"
60 #include "image/image_plugin_type.h"
61 
62 #include "image_type_converter.h"
63 #include "include/core/SkBitmap.h"
64 #include "include/core/SkCanvas.h"
65 #include "include/core/SkImage.h"
66 #ifdef USE_M133_SKIA
67 #include "include/codec/SkCodecAnimation.h"
68 #include "modules/skcms/src/skcms_public.h"
69 #endif
70 #include "src/binary_parse/range_checked_byte_ptr.h"
71 #include "src/image_type_recognition/image_type_recognition_lite.h"
72 
73 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
74 #define DMA_BUF_SET_TYPE _IOW(DMA_BUF_BASE, 2, const char *)
75 #endif
76 
77 #undef LOG_DOMAIN
78 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_PLUGIN
79 
80 #undef LOG_TAG
81 #define LOG_TAG "ExtDecoder"
82 
83 namespace {
84     constexpr static int32_t ZERO = 0;
85     constexpr static int32_t NUM_1 = 1;
86     constexpr static int32_t NUM_2 = 2;
87     constexpr static int32_t NUM_3 = 3;
88     constexpr static int32_t NUM_4 = 4;
89     constexpr static int32_t OFFSET = 1;
90     constexpr static size_t SIZE_ZERO = 0;
91     constexpr static uint32_t DEFAULT_SAMPLE_SIZE = 1;
92     constexpr static uint32_t NO_EXIF_TAG = 1;
93     constexpr static uint32_t OFFSET_0 = 0;
94     constexpr static uint32_t OFFSET_1 = 1;
95     constexpr static uint32_t OFFSET_2 = 2;
96     constexpr static uint32_t OFFSET_3 = 3;
97     constexpr static uint32_t OFFSET_5 = 5;
98     constexpr static uint32_t SHIFT_BITS_8 = 8;
99     constexpr static uint32_t SHIFT_BITS_16 = 16;
100     constexpr static uint32_t SHIFT_BITS_24 = 24;
101     constexpr static uint32_t DESC_SIGNATURE = 0x64657363;
102     constexpr static size_t SIZE_1 = 1;
103     constexpr static size_t SIZE_4 = 4;
104     constexpr static int HARDWARE_MIN_DIM = 512;
105     constexpr static int HARDWARE_MID_DIM = 1024;
106     constexpr static int HARDWARE_MAX_DIM = 8192;
107     constexpr static int HARDWARE_ALIGN_SIZE = 16;
108     constexpr static int DEFAULT_SCALE_SIZE = 1;
109     constexpr static int DOUBLE_SCALE_SIZE = 2;
110     constexpr static int FOURTH_SCALE_SIZE = 4;
111     constexpr static int MAX_SCALE_SIZE = 8;
112     constexpr static float HALF = 0.5;
113     constexpr static float QUARTER = 0.25;
114     constexpr static float ONE_EIGHTH = 0.125;
115     constexpr static uint64_t ICC_HEADER_SIZE = 132;
116     constexpr static size_t SMALL_FILE_SIZE = 1000 * 1000 * 10;
117     constexpr static int32_t LOOP_COUNT_INFINITE = 0;
118     constexpr static int32_t SK_REPETITION_COUNT_INFINITE = -1;
119     constexpr static int32_t SK_REPETITION_COUNT_ERROR_VALUE = -2;
120     constexpr static int32_t BYTES_PER_YUV_SAMPLE = 2;
121     constexpr static int32_t RGBA8888_PIXEL_BYTE_SIZE = 4;
122     constexpr static uint32_t HEIF_HARDWARE_TILE_MIN_DIM = 128;
123     constexpr static uint32_t HEIF_HARDWARE_TILE_MAX_DIM = 4096;
124     constexpr static uint32_t HEIF_HARDWARE_DISPLAY_MIN_DIM = 128;
125     constexpr static int LUMA_8_BIT = 8;
126     constexpr static int LUMA_10_BIT = 10;
127     constexpr static int JPEG_MARKER_LENGTH = 2;
128     static constexpr uint8_t JPEG_SOI_HEADER[] = { 0xFF, 0xD8 };
129 }
130 
131 namespace OHOS {
132 namespace ImagePlugin {
133 using namespace Media;
134 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
135 using namespace OHOS::HDI::Base;
136 using namespace OHOS::HDI::Display::Composer;
137 #endif
138 using namespace std;
139 using piex::binary_parse::RangeCheckedBytePtr;
140 using piex::image_type_recognition::RecognizeRawImageTypeLite;
141 
142 const static string DEFAULT_EXIF_VALUE = "default_exif_value";
143 const static string CODEC_INITED_KEY = "CodecInited";
144 const static string ENCODED_FORMAT_KEY = "EncodedFormat";
145 const static string SUPPORT_SCALE_KEY = "SupportScale";
146 const static string SUPPORT_CROP_KEY = "SupportCrop";
147 const static string EXT_SHAREMEM_NAME = "EXTRawData";
148 const static string TAG_ORIENTATION_STRING = "Orientation";
149 const static string TAG_ORIENTATION_INT = "OrientationInt";
150 const static string IMAGE_DELAY_TIME = "DelayTime";
151 const static string IMAGE_DISPOSAL_TYPE = "DisposalType";
152 const static string IMAGE_LOOP_COUNT = "GIFLoopCount";
153 const static std::string HW_MNOTE_TAG_HEADER = "HwMnote";
154 const static std::string HW_MNOTE_CAPTURE_MODE = "HwMnoteCaptureMode";
155 const static std::string HW_MNOTE_PHYSICAL_APERTURE = "HwMnotePhysicalAperture";
156 const static std::string HW_MNOTE_TAG_ROLL_ANGLE = "HwMnoteRollAngle";
157 const static std::string HW_MNOTE_TAG_PITCH_ANGLE = "HwMnotePitchAngle";
158 const static std::string HW_MNOTE_TAG_SCENE_FOOD_CONF = "HwMnoteSceneFoodConf";
159 const static std::string HW_MNOTE_TAG_SCENE_STAGE_CONF = "HwMnoteSceneStageConf";
160 const static std::string HW_MNOTE_TAG_SCENE_BLUE_SKY_CONF = "HwMnoteSceneBlueSkyConf";
161 const static std::string HW_MNOTE_TAG_SCENE_GREEN_PLANT_CONF = "HwMnoteSceneGreenPlantConf";
162 const static std::string HW_MNOTE_TAG_SCENE_BEACH_CONF = "HwMnoteSceneBeachConf";
163 const static std::string HW_MNOTE_TAG_SCENE_SNOW_CONF = "HwMnoteSceneSnowConf";
164 const static std::string HW_MNOTE_TAG_SCENE_SUNSET_CONF = "HwMnoteSceneSunsetConf";
165 const static std::string HW_MNOTE_TAG_SCENE_FLOWERS_CONF = "HwMnoteSceneFlowersConf";
166 const static std::string HW_MNOTE_TAG_SCENE_NIGHT_CONF = "HwMnoteSceneNightConf";
167 const static std::string HW_MNOTE_TAG_SCENE_TEXT_CONF = "HwMnoteSceneTextConf";
168 const static std::string HW_MNOTE_TAG_FACE_COUNT = "HwMnoteFaceCount";
169 const static std::string HW_MNOTE_TAG_FOCUS_MODE = "HwMnoteFocusMode";
170 // SUCCESS is existed in both OHOS::HiviewDFX and OHOS::Media
171 #define SUCCESS OHOS::Media::SUCCESS
172 const static std::string DEFAULT_PACKAGE_NAME = "entry";
173 const static std::string DEFAULT_VERSION_ID = "1";
174 const static std::string UNKNOWN_IMAGE = "unknown";
175 constexpr static int NUM_ONE = 1;
176 constexpr static uint64_t MALLOC_LIMIT = 300 * 1024 * 1024;
177 constexpr static int RAW_MIN_BYTEREAD = 10000;
178 #ifdef JPEG_HW_DECODE_ENABLE
179 const static uint32_t PLANE_COUNT_TWO = 2;
180 #endif
181 
182 struct ColorTypeOutput {
183     PixelFormat outFormat;
184     SkColorType skFormat;
185 };
186 
187 struct SkTransInfo {
188     SkRect r;
189     SkImageInfo info;
190     SkBitmap bitmap;
191 };
192 
193 static const map<PixelFormat, ColorTypeOutput> COLOR_TYPE_MAP = {
194     { PixelFormat::UNKNOWN, { PixelFormat::RGBA_8888, kRGBA_8888_SkColorType } },
195     { PixelFormat::RGBA_8888, { PixelFormat::RGBA_8888, kRGBA_8888_SkColorType } },
196     { PixelFormat::BGRA_8888, { PixelFormat::BGRA_8888, kBGRA_8888_SkColorType } },
197     { PixelFormat::ALPHA_8, { PixelFormat::ALPHA_8, kAlpha_8_SkColorType } },
198     { PixelFormat::RGB_565, { PixelFormat::RGB_565, kRGB_565_SkColorType } },
199     { PixelFormat::RGB_888, { PixelFormat::RGB_888, kRGB_888x_SkColorType } },
200 };
201 
202 static const map<AlphaType, SkAlphaType> ALPHA_TYPE_MAP = {
203     { AlphaType::IMAGE_ALPHA_TYPE_OPAQUE, kOpaque_SkAlphaType },
204     { AlphaType::IMAGE_ALPHA_TYPE_PREMUL, kPremul_SkAlphaType },
205     { AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL, kUnpremul_SkAlphaType },
206 };
207 
208 static const map<SkEncodedImageFormat, string> FORMAT_NAME = {
209     { SkEncodedImageFormat::kBMP, "image/bmp" },
210     { SkEncodedImageFormat::kGIF, "image/gif" },
211     { SkEncodedImageFormat::kICO, "image/x-ico" },
212     { SkEncodedImageFormat::kJPEG, "image/jpeg" },
213     { SkEncodedImageFormat::kPNG, "image/png" },
214     { SkEncodedImageFormat::kWBMP, "image/bmp" },
215     { SkEncodedImageFormat::kWEBP, "image/webp" },
216     { SkEncodedImageFormat::kPKM, "" },
217     { SkEncodedImageFormat::kKTX, "" },
218     { SkEncodedImageFormat::kASTC, "" },
219     { SkEncodedImageFormat::kDNG, "image/raw" },
220     { SkEncodedImageFormat::kHEIF, "image/heif" },
221 };
222 
223 static const map<piex::image_type_recognition::RawImageTypes, string> RAW_FORMAT_NAME = {
224     { piex::image_type_recognition::kArwImage, "image/x-sony-arw" },
225     { piex::image_type_recognition::kCr2Image, "image/x-canon-cr2" },
226     { piex::image_type_recognition::kDngImage, "image/x-adobe-dng" },
227     { piex::image_type_recognition::kNefImage, "image/x-nikon-nef" },
228     { piex::image_type_recognition::kNrwImage, "image/x-nikon-nrw" },
229     { piex::image_type_recognition::kOrfImage, "image/x-olympus-orf" },
230     { piex::image_type_recognition::kPefImage, "image/x-pentax-pef" },
231     { piex::image_type_recognition::kRafImage, "image/x-fuji-raf" },
232     { piex::image_type_recognition::kRw2Image, "image/x-panasonic-rw2" },
233     { piex::image_type_recognition::kSrwImage, "image/x-samsung-srw" },
234 };
235 
236 #if !defined(CROSS_PLATFORM)
237 static const map<PixelFormat, int32_t> PIXELFORMAT_TOGRAPHIC_MAP = {
238     {PixelFormat::RGBA_1010102, GRAPHIC_PIXEL_FMT_RGBA_1010102},
239     {PixelFormat::YCRCB_P010, GRAPHIC_PIXEL_FMT_YCRCB_P010},
240     {PixelFormat::YCBCR_P010, GRAPHIC_PIXEL_FMT_YCBCR_P010},
241     {PixelFormat::NV12, GRAPHIC_PIXEL_FMT_YCBCR_420_SP},
242     {PixelFormat::NV21, GRAPHIC_PIXEL_FMT_YCRCB_420_SP},
243     {PixelFormat::RGBA_F16, GRAPHIC_PIXEL_FMT_RGBA16_FLOAT},
244     {PixelFormat::BGRA_8888, GRAPHIC_PIXEL_FMT_BGRA_8888},
245     {PixelFormat::RGB_565, GRAPHIC_PIXEL_FMT_RGB_565},
246 };
247 #endif
248 
249 #ifdef HEIF_HW_DECODE_ENABLE
250 static const map<PixelFormat, SkHeifColorFormat> HEIF_FORMAT_MAP = {
251     { PixelFormat::RGBA_1010102, kHeifColorFormat_RGBA_1010102 },
252     { PixelFormat::YCBCR_P010, kHeifColorFormat_P010_NV12 },
253     { PixelFormat::YCRCB_P010, kHeifColorFormat_P010_NV21 },
254 };
255 #endif
256 
257 static const map<PixelFormat, JpegYuvFmt> PLPIXEL_FORMAT_YUV_JPG_MAP = {
258     { PixelFormat::NV21, JpegYuvFmt::OutFmt_NV21 }, { PixelFormat::NV12, JpegYuvFmt::OutFmt_NV12 }
259 };
260 
SetDecodeContextBuffer(DecodeContext & context,AllocatorType type,uint8_t * ptr,uint64_t count,void * fd)261 static void SetDecodeContextBuffer(DecodeContext &context,
262     AllocatorType type, uint8_t* ptr, uint64_t count, void* fd)
263 {
264     context.allocatorType = type;
265     context.freeFunc = nullptr;
266     context.pixelsBuffer.buffer = ptr;
267     context.pixelsBuffer.bufferSize = count;
268     context.pixelsBuffer.context = fd;
269 }
270 
ShareMemAlloc(DecodeContext & context,uint64_t count)271 static uint32_t ShareMemAlloc(DecodeContext &context, uint64_t count)
272 {
273 #if defined(_WIN32) || defined(_APPLE) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
274     IMAGE_LOGE("Unsupport share mem alloc");
275     return ERR_IMAGE_DATA_UNSUPPORT;
276 #else
277     auto fd = make_unique<int32_t>();
278     *fd = AshmemCreate(EXT_SHAREMEM_NAME.c_str(), count);
279     CHECK_ERROR_RETURN_RET_LOG(*fd < 0, ERR_SHAMEM_DATA_ABNORMAL, "AshmemCreate failed");
280     int result = AshmemSetProt(*fd, PROT_READ | PROT_WRITE);
281     if (result < 0) {
282         ::close(*fd);
283         IMAGE_LOGE("AshmemSetProt failed");
284         return ERR_SHAMEM_DATA_ABNORMAL;
285     }
286     void* ptr = ::mmap(nullptr, count, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, ZERO);
287     if (ptr == MAP_FAILED) {
288         ::close(*fd);
289         IMAGE_LOGE("::mmap failed");
290         return ERR_SHAMEM_DATA_ABNORMAL;
291     }
292     SetDecodeContextBuffer(context,
293         AllocatorType::SHARE_MEM_ALLOC, static_cast<uint8_t*>(ptr), count, fd.release());
294     IMAGE_LOGD("%{public}s count is %{public}llu", __func__, static_cast<unsigned long long>(count));
295     return SUCCESS;
296 #endif
297 }
298 
299 #if !defined(_WIN32) && !defined(_APPLE) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
CreateDmaRequestConfig(const SkImageInfo & dstInfo,uint64_t & count,PixelFormat pixelFormat)300 static BufferRequestConfig CreateDmaRequestConfig(const SkImageInfo &dstInfo, uint64_t &count, PixelFormat pixelFormat)
301 {
302     BufferRequestConfig requestConfig = {
303         .width = dstInfo.width(),
304         .height = dstInfo.height(),
305         .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
306         .format = GRAPHIC_PIXEL_FMT_RGBA_8888, // hardware decode only support rgba8888
307         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
308         .timeout = 0,
309         .colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB,
310         .transform = GraphicTransformType::GRAPHIC_ROTATE_NONE,
311     };
312     auto formatSearch = PIXELFORMAT_TOGRAPHIC_MAP.find(pixelFormat);
313     requestConfig.format = (formatSearch != PIXELFORMAT_TOGRAPHIC_MAP.end()) ?
314         formatSearch->second : GRAPHIC_PIXEL_FMT_RGBA_8888;
315     if (requestConfig.format == GRAPHIC_PIXEL_FMT_YCBCR_420_SP ||
316         requestConfig.format == GRAPHIC_PIXEL_FMT_YCRCB_420_SP) {
317         count = JpegDecoderYuv::GetYuvOutSize(dstInfo.width(), dstInfo.height());
318     } else if (requestConfig.format == GRAPHIC_PIXEL_FMT_RGBA16_FLOAT) {
319         count = (uint32_t)dstInfo.width() * (uint32_t)dstInfo.height() *
320             (uint32_t)ImageUtils::GetPixelBytes(PixelFormat::RGBA_F16);
321     }
322     return requestConfig;
323 }
324 #endif
325 
DmaMemAlloc(DecodeContext & context,uint64_t count,SkImageInfo & dstInfo)326 uint32_t ExtDecoder::DmaMemAlloc(DecodeContext &context, uint64_t count, SkImageInfo &dstInfo)
327 {
328 #if defined(_WIN32) || defined(_APPLE) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
329     IMAGE_LOGE("Unsupport dma mem alloc");
330     return ERR_IMAGE_DATA_UNSUPPORT;
331 #else
332     BufferRequestConfig requestConfig = CreateDmaRequestConfig(dstInfo, count, context.info.pixelFormat);
333     if (context.useNoPadding) {
334         IMAGE_LOGI("%{public}s no padding enabled", __func__);
335         requestConfig.usage |= BUFFER_USAGE_PREFER_NO_PADDING | BUFFER_USAGE_ALLOC_NO_IPC;
336     }
337     return DmaAlloc(context, count, requestConfig);
338 #endif
339 }
340 
JpegHwDmaMemAlloc(DecodeContext & context,uint64_t count,SkImageInfo & dstInfo)341 uint32_t ExtDecoder::JpegHwDmaMemAlloc(DecodeContext &context, uint64_t count, SkImageInfo &dstInfo)
342 {
343 #if defined(_WIN32) || defined(_APPLE) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
344     IMAGE_LOGE("Unsupport dma mem alloc");
345     return ERR_IMAGE_DATA_UNSUPPORT;
346 #else
347     BufferRequestConfig requestConfig = CreateDmaRequestConfig(dstInfo, count, context.info.pixelFormat);
348     if (outputColorFmt_ == V1_2::PIXEL_FMT_YCRCB_420_SP) {
349         requestConfig.format = GRAPHIC_PIXEL_FMT_YCRCB_420_SP;
350         requestConfig.usage |= BUFFER_USAGE_VENDOR_PRI16; // height is 64-bytes aligned
351         IMAGE_LOGD("ExtDecoder::DmaMemAlloc desiredFormat is NV21");
352         count = JpegDecoderYuv::GetYuvOutSize(dstInfo.width(), dstInfo.height());
353     }
354     return DmaAlloc(context, count, requestConfig);
355 #endif
356 }
357 
DmaAlloc(DecodeContext & context,uint64_t count,const OHOS::BufferRequestConfig & requestConfig)358 uint32_t ExtDecoder::DmaAlloc(DecodeContext &context, uint64_t count, const OHOS::BufferRequestConfig &requestConfig)
359 {
360 #if defined(CROSS_PLATFORM)
361     IMAGE_LOGE("Unsupport dma mem alloc");
362     return ERR_IMAGE_DATA_UNSUPPORT;
363 #else
364     sptr<SurfaceBuffer> sb = SurfaceBuffer::Create();
365     GSError ret = sb->Alloc(requestConfig);
366     bool cond = ret != GSERROR_OK;
367     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_DMA_NOT_EXIST,
368                                "SurfaceBuffer Alloc failed, %{public}s", GSErrorStr(ret).c_str());
369     int fd = sb->GetFileDescriptor();
370     if (fd > 0) {
371         ioctl(fd, DMA_BUF_SET_TYPE, "pixelmap");
372     }
373     void* nativeBuffer = sb.GetRefPtr();
374     int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
375     CHECK_ERROR_RETURN_RET_LOG(err != OHOS::GSERROR_OK, ERR_DMA_DATA_ABNORMAL, "NativeBufferReference failed");
376 
377     IMAGE_LOGD("ExtDecoder::DmaMemAlloc sb stride is %{public}d, height is %{public}d, size is %{public}d",
378         sb->GetStride(), sb->GetHeight(), sb->GetSize());
379     SetDecodeContextBuffer(context, AllocatorType::DMA_ALLOC, static_cast<uint8_t*>(sb->GetVirAddr()), count,
380         nativeBuffer);
381     return SUCCESS;
382 #endif
383 }
384 
HeapMemAlloc(DecodeContext & context,uint64_t count)385 static uint32_t HeapMemAlloc(DecodeContext &context, uint64_t count)
386 {
387     if (count == 0 || count > PIXEL_MAP_MAX_RAM_SIZE) {
388         IMAGE_LOGE("HeapMemAlloc Invalid value of bufferSize");
389         return ERR_IMAGE_DATA_ABNORMAL;
390     }
391     auto out = static_cast<uint8_t *>(malloc(count));
392     if (out == nullptr) {
393         IMAGE_LOGE("HeapMemAlloc malloc memory failed");
394         return ERR_IMAGE_MALLOC_ABNORMAL;
395     }
396 #ifdef _WIN32
397     if (memset_s(out, ZERO, count) != EOK) {
398 #else
399     if (memset_s(out, count, ZERO, count) != EOK) {
400 #endif
401         IMAGE_LOGE("Decode failed, memset buffer failed");
402         free(out);
403         return ERR_IMAGE_DECODE_FAILED;
404     }
405     SetDecodeContextBuffer(context, AllocatorType::HEAP_ALLOC, out, count, nullptr);
406     return SUCCESS;
407 }
408 
409 uint32_t ExtDecoder::UpdateHeifYuvDataInfo(DecodeContext &context, SkImageInfo &heifInfo,
410     uint32_t gridTileWidth, uint32_t gridTileHeight)
411 {
412 #ifdef HEIF_HW_DECODE_ENABLE
413     SurfaceBuffer* sbBuffer = static_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
414     if (sbBuffer == nullptr) {
415         return ERR_DMA_DATA_ABNORMAL;
416     }
417     OH_NativeBuffer_Planes *planes = nullptr;
418     GSError retVal = sbBuffer->GetPlanesInfo(reinterpret_cast<void**>(&planes));
419     if (retVal != OHOS::GSERROR_OK || planes == nullptr || planes->planeCount < NUM_2) {
420         IMAGE_LOGE("heif yuv decode, Get planesInfo failed, retVal:%{public}d", retVal);
421     } else {
422         uint32_t uvPlaneIndex = (context.info.pixelFormat == PixelFormat::NV12 ||
423                 context.info.pixelFormat == PixelFormat::YCBCR_P010) ? NUM_1 : NUM_2;
424         if (IsHeifRegionDecode()) {
425             context.yuvInfo.imageSize = { heifGridRegionInfo_.colCount * static_cast<int32_t>(gridTileWidth) -
426                 heifGridRegionInfo_.widthPadding,
427                 heifGridRegionInfo_.rowCount * static_cast<int32_t>(gridTileHeight) -
428                 heifGridRegionInfo_.heightPadding };
429         } else {
430             context.yuvInfo.imageSize = { heifInfo.width(), heifInfo.height() };
431         }
432         context.yuvInfo.yWidth = static_cast<uint32_t>(heifInfo.width());
433         context.yuvInfo.yHeight = static_cast<uint32_t>(heifInfo.height());
434         context.yuvInfo.uvWidth = static_cast<uint32_t>((heifInfo.width() + 1) / NUM_2);
435         context.yuvInfo.uvHeight = static_cast<uint32_t>((heifInfo.height() + 1) / NUM_2);
436         context.yuvInfo.yStride = planes->planes[0].columnStride;
437         context.yuvInfo.uvStride = planes->planes[uvPlaneIndex].columnStride;
438         context.yuvInfo.yOffset = planes->planes[0].offset;
439         context.yuvInfo.uvOffset = planes->planes[uvPlaneIndex].offset;
440     }
441     return SUCCESS;
442 #else
443     return ERR_IMAGE_DATA_UNSUPPORT;
444 #endif
445 }
446 
447 uint32_t ExtDecoder::HeifYUVMemAlloc(OHOS::ImagePlugin::DecodeContext &context, SkImageInfo &heifInfo)
448 {
449 #ifdef HEIF_HW_DECODE_ENABLE
450     auto heifContext = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
451     if (heifContext == nullptr) {
452         return ERR_IMAGE_INVALID_PARAMETER;
453     }
454     GridInfo gridInfo = heifContext->GetGridInfo();
455     if (IsHeifRegionDecode()) {
456         SetHeifDecodeRegion(context, static_cast<int32_t>(gridInfo.tileWidth),
457             static_cast<int32_t>(gridInfo.tileHeight));
458         SkImageInfo dstInfo = SkImageInfo::Make(static_cast<int>(heifGridRegionInfo_.colCount * gridInfo.tileWidth),
459             static_cast<int>(heifGridRegionInfo_.rowCount * gridInfo.tileHeight), dstInfo_.colorType(),
460             dstInfo_.alphaType(), dstInfo_.refColorSpace());
461         uint64_t byteCount = static_cast<uint64_t>(dstInfo.computeMinByteSize());
462         CHECK_ERROR_RETURN_RET_LOG(SkImageInfo::ByteSizeOverflowed(byteCount), ERR_IMAGE_TOO_LARGE,
463             "%{public}s too large byteCount: %{public}llu", __func__, static_cast<unsigned long long>(byteCount));
464         bool cond = DmaMemAlloc(context, byteCount, dstInfo) != SUCCESS;
465         CHECK_INFO_RETURN_RET_LOG(cond, ERR_DMA_NOT_EXIST, "DmaMemAlloc execution failed.");
466         IMAGE_LOGI("Do Heif YUV Type Region Decode, xy [%{public}d , %{public}d], wh [%{public}d x %{public}d]",
467             desiredRegion_.left, desiredRegion_.top, desiredRegion_.width, desiredRegion_.height);
468     } else {
469         uint64_t byteCount = static_cast<uint64_t>(heifInfo.computeMinByteSize());
470         CHECK_ERROR_RETURN_RET_LOG(SkImageInfo::ByteSizeOverflowed(byteCount), ERR_IMAGE_TOO_LARGE,
471             "%{public}s too large byteCount: %{public}llu", __func__, static_cast<unsigned long long>(byteCount));
472         bool cond = DmaMemAlloc(context, byteCount, heifInfo) != SUCCESS;
473         CHECK_INFO_RETURN_RET_LOG(cond, ERR_DMA_NOT_EXIST, "DmaMemAlloc execution failed.");
474     }
475     auto* dstBuffer = static_cast<uint8_t*>(context.pixelsBuffer.buffer);
476     auto* sbBuffer = reinterpret_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
477     int32_t rowStride = sbBuffer->GetStride();
478     if (rowStride <= 0) {
479         return ERR_DMA_DATA_ABNORMAL;
480     }
481     IMAGE_LOGI("ExtDecoder::HeifYUVMemAlloc sb stride is %{public}d, height is %{public}d, size is %{public}d",
482         sbBuffer->GetStride(), sbBuffer->GetHeight(), sbBuffer->GetSize());
483     return UpdateHeifYuvDataInfo(context, heifInfo, gridInfo.tileWidth, gridInfo.tileHeight);
484 #else
485     return ERR_IMAGE_DATA_UNSUPPORT;
486 #endif
487 }
488 
489 ExtDecoder::ExtDecoder() : codec_(nullptr), frameCount_(ZERO)
490 {
491 }
492 
493 ExtDecoder::~ExtDecoder()
494 {
495     if (gifCache_ != nullptr) {
496         free(gifCache_);
497         gifCache_ = nullptr;
498     }
499 }
500 
501 void ExtDecoder::SetSource(InputDataStream &sourceStream)
502 {
503     stream_ = &sourceStream;
504     streamOff_ = sourceStream.Tell();
505     if (streamOff_ >= sourceStream.GetStreamSize()) {
506         streamOff_ = ZERO;
507     }
508 }
509 
510 void ExtDecoder::Reset()
511 {
512     stream_ = nullptr;
513     codec_ = nullptr;
514     dstInfo_.reset();
515     dstSubset_ = SkIRect::MakeEmpty();
516     info_.reset();
517 }
518 
519 static inline float Max(float a, float b)
520 {
521     return (a > b) ? a : b;
522 }
523 
524 bool ExtDecoder::GetScaledSize(int &dWidth, int &dHeight, float &scale)
525 {
526     bool cond = info_.isEmpty() && !DecodeHeader();
527     CHECK_ERROR_RETURN_RET_LOG(cond, false, "DecodeHeader failed in GetScaledSize!");
528     cond = info_.isEmpty();
529     CHECK_ERROR_RETURN_RET_LOG(cond, false, "empty image info in GetScaledSize!");
530     if (cropAndScaleStrategy_ == OHOS::Media::CropAndScaleStrategy::CROP_FIRST) {
531         dWidth = info_.width();
532         dHeight = info_.height();
533         IMAGE_LOGI("do not scale while decoding");
534         return true;
535     }
536     float finalScale = scale;
537     if (scale == ZERO) {
538         finalScale = Max(static_cast<float>(dWidth) / info_.width(),
539             static_cast<float>(dHeight) / info_.height());
540     }
541     cond = codec_ == nullptr;
542     CHECK_ERROR_RETURN_RET_LOG(cond, false, "codec is null in GetScaledSize!");
543     auto scaledDimension = codec_->getScaledDimensions(finalScale);
544     dWidth = scaledDimension.width();
545     dHeight = scaledDimension.height();
546     scale = finalScale;
547     IMAGE_LOGD("IsSupportScaleOnDecode info [%{public}d x %{public}d]", info_.width(), info_.height());
548     IMAGE_LOGD("IsSupportScaleOnDecode [%{public}d x %{public}d]", dWidth, dHeight);
549     IMAGE_LOGD("IsSupportScaleOnDecode [%{public}f]", scale);
550     return true;
551 }
552 
553 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
554 bool ExtDecoder::GetHardwareScaledSize(int &dWidth, int &dHeight, float &scale) {
555     bool cond = info_.isEmpty() && !DecodeHeader();
556     CHECK_ERROR_RETURN_RET_LOG(cond, false, "DecodeHeader failed in GetHardwareScaledSize!");
557     cond = info_.isEmpty();
558     CHECK_ERROR_RETURN_RET_LOG(cond, false, "empty image info in GetHardwareScaledSize!");
559     float finalScale = scale;
560     int oriWidth = info_.width();
561     int oriHeight = info_.height();
562     if (scale == ZERO) {
563         finalScale = Max(static_cast<float>(dWidth) / oriWidth,
564                          static_cast<float>(dHeight) / oriHeight);
565     }
566     // calculate sample size and dst size for hardware decode
567     if (finalScale > HALF) {
568         sampleSize_ = 1;
569     } else if (finalScale > QUARTER) {
570         sampleSize_ = 2;
571     } else if (finalScale > ONE_EIGHTH) {
572         sampleSize_ = 4;
573     } else {
574         sampleSize_ = 8;
575     }
576     dWidth = (oriWidth + (int)sampleSize_ - NUM_ONE) / (int)sampleSize_;
577     dHeight = (oriHeight + (int)sampleSize_ - NUM_ONE) / (int)sampleSize_;
578     return true;
579 }
580 #endif
581 
582 int ExtDecoder::GetSoftwareScaledSize(int dwidth, int dheight) {
583     bool cond = dstSubset_.isEmpty() && !DecodeHeader();
584     CHECK_INFO_RETURN_RET_LOG(cond, DEFAULT_SCALE_SIZE, "DecodeHeader failed in GetSoftwareScaledSize!");
585     int softSampleSize;
586     int oriWidth = dstSubset_.width();
587     int oriHeight = dstSubset_.height();
588     cond = (oriWidth == 0 || oriHeight == 0);
589     CHECK_INFO_RETURN_RET_LOG(cond, DEFAULT_SCALE_SIZE,
590         "oriWidth or oriHeight is zero, %{public}d, %{public}d", oriWidth, oriHeight);
591     float finalScale = Max(static_cast<float>(dwidth) / oriWidth,
592                         static_cast<float>(dheight) / oriHeight);
593     // calculate sample size and dst size for hardware decode
594     if (finalScale > HALF) {
595         softSampleSize = DEFAULT_SCALE_SIZE;
596     } else if (finalScale > QUARTER) {
597         softSampleSize = DOUBLE_SCALE_SIZE;
598     } else if (finalScale > ONE_EIGHTH) {
599         softSampleSize = FOURTH_SCALE_SIZE;
600     } else {
601         softSampleSize = MAX_SCALE_SIZE;
602     }
603     return softSampleSize;
604 }
605 
606 bool ExtDecoder::GetSampleSize(int dstWidth, int dstHeight)
607 {
608     int oriWidth = info_.width();
609     int oriHeight = info_.height();
610     bool cond = oriWidth == 0 || oriHeight == 0;
611     CHECK_ERROR_RETURN_RET(cond, false);
612     if (dstWidth >= oriWidth || dstHeight >= oriHeight) {
613         softSampleSize_ = 1;
614         return true;
615     }
616     float finalScale = Max(static_cast<float>(dstWidth) / oriWidth, static_cast<float>(dstHeight) / oriHeight);
617     // calculate sample size for sample decode
618     if (finalScale > HALF) {
619         softSampleSize_ = 1;
620     } else if (finalScale > QUARTER) {
621         softSampleSize_ = 2;
622     } else if (finalScale > ONE_EIGHTH) {
623         softSampleSize_ = 4;
624     } else {
625         softSampleSize_ = 8;
626     }
627     return true;
628 }
629 
630 bool ExtDecoder::IsSupportScaleOnDecode()
631 {
632     constexpr float HALF_SCALE = 0.5f;
633     int w = ZERO;
634     int h = ZERO;
635     float scale = HALF_SCALE;
636     return GetScaledSize(w, h, scale);
637 }
638 
639 bool ExtDecoder::IsSupportCropOnDecode()
640 {
641     bool cond = info_.isEmpty() && !DecodeHeader();
642     CHECK_ERROR_RETURN_RET(cond, false);
643     SkIRect innerRect = info_.bounds().makeInset(OFFSET, OFFSET);
644     return IsSupportCropOnDecode(innerRect);
645 }
646 
647 bool ExtDecoder::IsSupportCropOnDecode(SkIRect &target)
648 {
649     bool cond = info_.isEmpty() && !DecodeHeader();
650     CHECK_ERROR_RETURN_RET(cond, false);
651     if (SupportRegionFlag_) {
652         return true;
653     }
654     SkIRect orgbounds = info_.bounds();
655     SkIRect source = target;
656     if (orgbounds.contains(target) && codec_->getValidSubset(&target)) {
657         return source == target;
658     }
659     return false;
660 }
661 
662 bool ExtDecoder::IsSupportSampleDecode(OHOS::Media::PixelFormat desiredFormat)
663 {
664     bool cond = info_.isEmpty() && !DecodeHeader();
665     CHECK_ERROR_RETURN_RET(cond, false);
666     cond = static_cast<int32_t>(desiredFormat) > static_cast<int32_t>(PixelFormat::BGRA_8888);
667     CHECK_ERROR_RETURN_RET(cond, false);
668     cond = dstSubset_.left() != 0 || dstSubset_.top() != 0 || dstSubset_.right() != 0 || dstSubset_.bottom() != 0;
669     CHECK_ERROR_RETURN_RET(cond, false);
670     return ImageSystemProperties::GetPngSampleDecodeEnabled() &&
671         codec_->getEncodedFormat() == SkEncodedImageFormat::kPNG;
672 }
673 
674 bool ExtDecoder::HasProperty(string key)
675 {
676     if (CODEC_INITED_KEY.compare(key) == ZERO) {
677         return CheckCodec();
678     } else if (ENCODED_FORMAT_KEY.compare(key) == ZERO) {
679         return true;
680     } else if (SUPPORT_SCALE_KEY.compare(key) == ZERO) {
681         return IsSupportScaleOnDecode();
682     } else if (SUPPORT_CROP_KEY.compare(key) == ZERO) {
683         return IsSupportCropOnDecode();
684     }
685     return false;
686 }
687 
688 uint32_t ExtDecoder::GetImageSize(uint32_t index, Size &size)
689 {
690     IMAGE_LOGD("GetImageSize index:%{public}u", index);
691     if (!CheckIndexValied(index)) {
692         IMAGE_LOGE("Invalid index:%{public}u, range:%{public}d", index, frameCount_);
693         return ERR_IMAGE_INVALID_PARAMETER;
694     }
695     IMAGE_LOGD("GetImageSize index:%{public}u, range:%{public}d", index, frameCount_);
696     // Info has been get in check process, or empty on get failed.
697     CHECK_ERROR_RETURN_RET_LOG(info_.isEmpty(), ERR_IMAGE_DECODE_HEAD_ABNORMAL,
698         "GetImageSize failed, decode header failed.");
699     size.width = info_.width();
700     size.height = info_.height();
701     return SUCCESS;
702 }
703 
704 static inline bool IsLowDownScale(const Size &size, SkImageInfo &info)
705 {
706     return size.width < info.width() &&
707         size.height < info.height();
708 }
709 
710 static inline bool IsValidCrop(const OHOS::Media::Rect &crop, SkImageInfo &info, SkIRect &out)
711 {
712     out = SkIRect::MakeXYWH(crop.left, crop.top, crop.width, crop.height);
713     bool cond = out.fLeft < ZERO || out.fTop < ZERO;
714     CHECK_ERROR_RETURN_RET(cond, false);
715     if (out.fRight > info.width()) {
716         out.fRight = info.width();
717     }
718     if (out.fBottom > info.height()) {
719         out.fBottom = info.height();
720     }
721     return true;
722 }
723 
724 static sk_sp<SkColorSpace> getDesiredColorSpace(SkImageInfo &srcInfo, const PixelDecodeOptions &opts)
725 {
726     if (opts.plDesiredColorSpace == nullptr) {
727         return srcInfo.refColorSpace();
728     }
729     return opts.plDesiredColorSpace->ToSkColorSpace();
730 }
731 
732 bool ExtDecoder::IsHeifValidCrop(OHOS::Media::Rect &crop, SkImageInfo &info,
733     int32_t gridInfoCols, int32_t gridInfoRows)
734 {
735     if (crop.height < ZERO || crop.width < ZERO || crop.left < ZERO || crop.top < ZERO) {
736         return false;
737     }
738     if (crop.height > info.height() - crop.top) {
739         heifGridRegionInfo_.heightPadding = gridInfoRows * heifGridRegionInfo_.tileHeight - info.height();
740         crop.height = info.height() - crop.top;
741     }
742     if (crop.width > info.width() - crop.left) {
743         heifGridRegionInfo_.widthPadding = gridInfoCols * heifGridRegionInfo_.tileWidth - info.width();
744         crop.width = info.width() - crop.left;
745     }
746     desiredRegion_.left = crop.left;
747     desiredRegion_.top = crop.top;
748     desiredRegion_.width = crop.width;
749     desiredRegion_.height = crop.height;
750     return true;
751 }
752 
753 uint32_t ExtDecoder::ExtractHeifRegion(const PixelDecodeOptions &opts)
754 {
755 #ifdef HEIF_HW_DECODE_ENABLE
756     if (opts.CropRect.width <= ZERO || opts.CropRect.height <= ZERO) {
757         desiredRegion_ = {0, 0, 0, 0};
758         heifGridRegionInfo_ = {0, 0, 0, 0, 0, 0, false};
759         return SUCCESS;
760     }
761     bool cond = codec_ == nullptr;
762     CHECK_ERROR_RETURN_RET_LOG(cond, SUCCESS, "Decode failed, codec is null");
763     SkEncodedImageFormat skEncodeFormat = codec_->getEncodedFormat();
764     if (skEncodeFormat == SkEncodedImageFormat::kHEIF) {
765         auto heifContext = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
766         if (heifContext == nullptr) {
767             IMAGE_LOGE("Decode heifContext is nullptr");
768             return ERR_IMAGE_DECODE_FAILED;
769         }
770         GridInfo gridInfo = heifContext->GetGridInfo();
771         if (gridInfo.tileWidth != static_cast<uint32_t>(info_.width()) ||
772             gridInfo.tileHeight != static_cast<uint32_t>(info_.height())) {
773             heifGridRegionInfo_.isGridType = true;
774             heifGridRegionInfo_.tileWidth = static_cast<int32_t>(gridInfo.tileWidth);
775             heifGridRegionInfo_.tileHeight = static_cast<uint32_t>(gridInfo.tileHeight);
776         }
777         PixelDecodeOptions heifOpts = opts;
778         if (!IsHeifValidCrop(heifOpts.CropRect, info_, static_cast<int32_t>(gridInfo.cols),
779             static_cast<int32_t>(gridInfo.rows))) {
780             IMAGE_LOGE("Invalid heif crop rect xy [%{public}d x %{public}d], wh [%{public}d x %{public}d]",
781                 opts.CropRect.left, opts.CropRect.top, opts.CropRect.width, opts.CropRect.height);
782             return ERR_IMAGE_INVALID_PARAMETER;
783         }
784     }
785     return SUCCESS;
786 #else
787     return SUCCESS;
788 #endif
789 }
790 
791 uint32_t ExtDecoder::CheckDecodeOptions(uint32_t index, const PixelDecodeOptions &opts)
792 {
793     bool cond = ImageUtils::CheckMulOverflow(dstInfo_.width(), dstInfo_.height(), dstInfo_.bytesPerPixel());
794     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_INVALID_PARAMETER,
795         "SetDecodeOptions failed, width:%{public}d, height:%{public}d is too large",
796         dstInfo_.width(), dstInfo_.height());
797     cond = ExtractHeifRegion(opts) != SUCCESS;
798     CHECK_ERROR_RETURN_RET(cond, ERR_IMAGE_INVALID_PARAMETER);
799     IMAGE_LOGD("%{public}s IN, dstSubset_: xy [%{public}d x %{public}d] right,bottom: [%{public}d x %{public}d]",
800         __func__, dstSubset_.left(), dstSubset_.top(), dstSubset_.right(), dstSubset_.bottom());
801     size_t tempSrcByteCount = info_.computeMinByteSize();
802     size_t tempDstByteCount = dstInfo_.computeMinByteSize();
803     cond = SkImageInfo::ByteSizeOverflowed(tempSrcByteCount) || SkImageInfo::ByteSizeOverflowed(tempDstByteCount);
804     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_TOO_LARGE,
805         "Image too large, srcInfo_height: %{public}d, srcInfo_width: %{public}d, "
806         "dstInfo_height: %{public}d, dstInfo_width: %{public}d",
807         info_.height(), info_.width(), dstInfo_.height(), dstInfo_.width());
808 
809     dstOptions_.fFrameIndex = static_cast<int>(index);
810 #ifdef IMAGE_COLORSPACE_FLAG
811     dstColorSpace_ = opts.plDesiredColorSpace;
812 #endif
813     return SUCCESS;
814 }
815 
816 bool ExtDecoder::IsRegionDecodeSupported(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info)
817 {
818     CHECK_ERROR_RETURN_RET(PreDecodeCheck(index) != SUCCESS, false);
819     if (static_cast<int32_t>(opts.desiredPixelFormat) > static_cast<int32_t>(PixelFormat::BGRA_8888)) {
820         return false;
821     }
822     if (opts.cropAndScaleStrategy == OHOS::Media::CropAndScaleStrategy::CROP_FIRST) {
823         return codec_->getEncodedFormat() == SkEncodedImageFormat::kJPEG ||
824             codec_->getEncodedFormat() == SkEncodedImageFormat::kPNG;
825     }
826     return false;
827 }
828 
829 uint32_t ExtDecoder::SetDecodeOptions(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info)
830 {
831     bool cond = !CheckIndexValied(index);
832     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_INVALID_PARAMETER,
833         "Invalid index:%{public}u, range:%{public}d", index, frameCount_);
834     cond = opts.sampleSize != DEFAULT_SAMPLE_SIZE;
835     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_INVALID_PARAMETER, "Do not support sample size now!");
836     cropAndScaleStrategy_ = opts.cropAndScaleStrategy;
837     auto desireColor = ConvertToColorType(opts.desiredPixelFormat, info.pixelFormat);
838     auto desireAlpha = ConvertToAlphaType(opts.desireAlphaType, info.alphaType);
839 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
840     outputColorFmt_ = (opts.desiredPixelFormat == PixelFormat::NV21 ||
841                        opts.desiredPixelFormat == PixelFormat::YCBCR_P010) ?
842                        V1_2::PIXEL_FMT_YCRCB_420_SP : V1_2::PIXEL_FMT_RGBA_8888;
843 #endif
844 
845     if (codec_) {
846         SkEncodedImageFormat skEncodeFormat = codec_->getEncodedFormat();
847         if (skEncodeFormat == SkEncodedImageFormat::kJPEG && IsYuv420Format(opts.desiredPixelFormat)) {
848             info.pixelFormat = opts.desiredPixelFormat;
849             desiredSizeYuv_.width = opts.desiredSize.width;
850             desiredSizeYuv_.height = opts.desiredSize.height;
851         }
852         if (skEncodeFormat == SkEncodedImageFormat::kHEIF && IsYuv420Format(opts.desiredPixelFormat)) {
853             info.pixelFormat = opts.desiredPixelFormat;
854         }
855     }
856     RegiondesiredSize_.width = opts.desiredSize.width;
857     RegiondesiredSize_.height = opts.desiredSize.height;
858     // SK only support low down scale
859     int dstWidth = opts.desiredSize.width;
860     int dstHeight = opts.desiredSize.height;
861     float scale = ZERO;
862 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
863     if (IsSupportHardwareDecode()) {
864         // get dstInfo for hardware decode
865         if (IsLowDownScale(opts.desiredSize, info_) && GetHardwareScaledSize(dstWidth, dstHeight, scale)) {
866             hwDstInfo_ = SkImageInfo::Make(dstWidth, dstHeight, desireColor, desireAlpha, info_.refColorSpace());
867         } else {
868             hwDstInfo_ = SkImageInfo::Make(info_.width(), info_.height(),
869                                            desireColor, desireAlpha, info_.refColorSpace());
870         }
871         // restore dstWidth and dstHeight
872         dstWidth = opts.desiredSize.width;
873         dstHeight = opts.desiredSize.height;
874     }
875 #endif
876     if (codec_->getEncodedFormat() != SkEncodedImageFormat::kHEIF) {
877         if (IsLowDownScale(opts.desiredSize, info_) && GetScaledSize(dstWidth, dstHeight, scale)) {
878             dstInfo_ = SkImageInfo::Make(dstWidth, dstHeight, desireColor, desireAlpha,
879                 getDesiredColorSpace(info_, opts));
880         } else {
881             dstInfo_ = SkImageInfo::Make(info_.width(), info_.height(),
882                 desireColor, desireAlpha, getDesiredColorSpace(info_, opts));
883         }
884     } else {
885         SetHeifSampleSize(opts, dstWidth, dstHeight, desireColor, desireAlpha);
886     }
887     auto resCode = CheckDecodeOptions(index, opts);
888     CHECK_ERROR_RETURN_RET(resCode != SUCCESS, resCode);
889     SupportRegionFlag_ = IsRegionDecodeSupported(index, opts, info);
890 #ifdef SK_ENABLE_OHOS_CODEC
891     if (IsSupportSampleDecode(opts.desiredPixelFormat) &&
892         GetSampleSize(opts.desiredSize.width, opts.desiredSize.height)) {
893         dstWidth = info_.width() / softSampleSize_;
894         dstHeight = info_.height() / softSampleSize_;
895         dstInfo_ = SkImageInfo::Make(dstWidth, dstHeight, desireColor, desireAlpha,
896             getDesiredColorSpace(info_, opts));
897     }
898 #endif
899     info.size.width = dstInfo_.width();
900     info.size.height = dstInfo_.height();
901     reusePixelmap_ = opts.plReusePixelmap;
902     return SUCCESS;
903 }
904 
905 uint32_t ExtDecoder::SetContextPixelsBuffer(uint64_t byteCount, DecodeContext &context)
906 {
907     CHECK_ERROR_RETURN_RET(byteCount == ZERO, ERR_IMAGE_INVALID_PARAMETER);
908     if (context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC) {
909         return ShareMemAlloc(context, byteCount);
910     } else if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
911         return DmaMemAlloc(context, byteCount, dstInfo_);
912     }
913     return HeapMemAlloc(context, byteCount);
914 }
915 
916 static void DebugInfo(SkImageInfo &info, SkImageInfo &dstInfo, SkCodec::Options &opts)
917 {
918     IMAGE_LOGD("Decode source info: WH[%{public}d x %{public}d], A %{public}d, C %{public}d.",
919         info.width(), info.height(),
920         info.alphaType(), info.colorType());
921     IMAGE_LOGD("Decode dst info: WH[%{public}d x %{public}d], A %{public}d, C %{public}d.",
922         dstInfo.width(), dstInfo.height(), dstInfo.alphaType(), dstInfo.colorType());
923     if (opts.fSubset != nullptr) {
924         IMAGE_LOGD("Decode dstOpts sub: (%{public}d, %{public}d), WH[%{public}d x %{public}d]",
925             opts.fSubset->fLeft, opts.fSubset->fTop,
926             opts.fSubset->width(), opts.fSubset->height());
927     }
928 }
929 
930 static uint64_t GetByteSize(int32_t width, int32_t height)
931 {
932     return static_cast<uint64_t>(width * height + ((width + 1) / NUM_2) * ((height + 1) / NUM_2) * NUM_2);
933 }
934 
935 static void UpdateContextYuvInfo(DecodeContext &context, DestConvertInfo &destInfo)
936 {
937     context.yuvInfo.yWidth = static_cast<uint32_t>(destInfo.width);
938     context.yuvInfo.yHeight = static_cast<uint32_t>(destInfo.height);
939     context.yuvInfo.yStride = destInfo.yStride;
940     context.yuvInfo.uvWidth = static_cast<uint32_t>((destInfo.width + 1) / NUM_2);
941     context.yuvInfo.uvHeight = static_cast<uint32_t>((destInfo.height + 1) / NUM_2);
942     context.yuvInfo.uvStride = destInfo.uvStride;
943     context.yuvInfo.yOffset = destInfo.yOffset;
944     context.yuvInfo.uvOffset = destInfo.uvOffset;
945 }
946 
947 static void FreeContextBuffer(const Media::CustomFreePixelMap &func, AllocatorType allocType, PlImageBuffer &buffer)
948 {
949     if (func != nullptr) {
950         func(buffer.buffer, buffer.context, buffer.bufferSize);
951         return;
952     }
953 
954 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
955     if (allocType == AllocatorType::SHARE_MEM_ALLOC) {
956         int *fd = static_cast<int *>(buffer.context);
957         if (buffer.buffer != nullptr) {
958             ::munmap(buffer.buffer, buffer.bufferSize);
959         }
960         if (fd != nullptr) {
961             ::close(*fd);
962         }
963         return;
964     } else if (allocType == AllocatorType::DMA_ALLOC) {
965         if (buffer.buffer != nullptr) {
966             ImageUtils::SurfaceBuffer_Unreference(static_cast<SurfaceBuffer *>(buffer.context));
967             buffer.context = nullptr;
968         }
969     } else if (allocType == AllocatorType::HEAP_ALLOC) {
970         if (buffer.buffer != nullptr) {
971             free(buffer.buffer);
972             buffer.buffer = nullptr;
973         }
974     }
975 #else
976     if (buffer.buffer != nullptr) {
977         free(buffer.buffer);
978         buffer.buffer = nullptr;
979     }
980 #endif
981 }
982 
983 uint32_t ExtDecoder::ConvertFormatToYUV(DecodeContext &context, SkImageInfo &skInfo,
984     uint64_t byteCount, PixelFormat format)
985 {
986     ConvertDataInfo srcDataInfo;
987     srcDataInfo.buffer = static_cast<uint8_buffer_type>(context.pixelsBuffer.buffer);
988     srcDataInfo.bufferSize = byteCount;
989     srcDataInfo.imageSize = {skInfo.width(), skInfo.height()};
990     srcDataInfo.pixelFormat = context.pixelFormat;
991     srcDataInfo.colorSpace = static_cast<ColorSpace>(context.colorSpace);
992 
993     DestConvertInfo destInfo = {skInfo.width(), skInfo.height()};
994     destInfo.format = format;
995     destInfo.allocType = context.allocatorType;
996     auto ret = Media::ImageFormatConvert::ConvertImageFormat(srcDataInfo, destInfo);
997     CHECK_ERROR_RETURN_RET_LOG(ret != SUCCESS, ret, "Decode convert failed , ret=%{public}d", ret);
998     FreeContextBuffer(context.freeFunc, context.allocatorType, context.pixelsBuffer);
999     SetDecodeContextBuffer(context, context.allocatorType, static_cast<uint8_t *>(destInfo.buffer),
1000         destInfo.bufferSize, destInfo.context);
1001     context.info.pixelFormat = format;
1002     UpdateContextYuvInfo(context, destInfo);
1003     return SUCCESS;
1004 }
1005 
1006 static uint32_t RGBxToRGB(uint8_t* srcBuffer, size_t srsSize,
1007     uint8_t* dstBuffer, size_t dstSize, size_t pixelCount)
1008 {
1009     ExtPixels src = {srcBuffer, srsSize, pixelCount};
1010     ExtPixels dst = {dstBuffer, dstSize, pixelCount};
1011     auto res = ExtPixelConvert::RGBxToRGB(src, dst);
1012     bool cond = res != SUCCESS;
1013     CHECK_ERROR_PRINT_LOG(cond, "RGBxToRGB failed %{public}d", res);
1014     return res;
1015 }
1016 
1017 uint32_t ExtDecoder::PreDecodeCheck(uint32_t index)
1018 {
1019     CHECK_ERROR_RETURN_RET_LOG(!CheckIndexValied(index), ERR_IMAGE_INVALID_PARAMETER,
1020         "Decode failed, invalid index:%{public}u, range:%{public}d", index, frameCount_);
1021     CHECK_ERROR_RETURN_RET_LOG(codec_ == nullptr, ERR_IMAGE_DECODE_FAILED, "Decode failed, codec is null");
1022     CHECK_ERROR_RETURN_RET_LOG(dstInfo_.isEmpty(), ERR_IMAGE_DECODE_FAILED, "Decode failed, dst info is empty");
1023     return SUCCESS;
1024 }
1025 
1026 static bool IsColorSpaceSupport(SkJpegCodec* codec)
1027 {
1028     bool cond = codec == nullptr || codec->decoderMgr() == nullptr || codec->decoderMgr()->dinfo() == nullptr;
1029     CHECK_ERROR_RETURN_RET_LOG(cond, false, "SkJpegCodec is null");
1030     struct jpeg_decompress_struct* pCinfo = codec->decoderMgr()->dinfo();
1031     if (pCinfo->jpeg_color_space == JCS_YCbCr || pCinfo->jpeg_color_space == JCS_GRAYSCALE) {
1032         return true;
1033     }
1034     IMAGE_LOGE("unsupported in color: %{public}d", pCinfo->jpeg_color_space);
1035     return false;
1036 }
1037 
1038 uint32_t ExtDecoder::PreDecodeCheckYuv(uint32_t index, PixelFormat desiredFormat)
1039 {
1040     uint32_t ret = PreDecodeCheck(index);
1041     CHECK_ERROR_RETURN_RET(ret != SUCCESS, ret);
1042     SkEncodedImageFormat skEncodeFormat = codec_->getEncodedFormat();
1043     bool cond = skEncodeFormat != SkEncodedImageFormat::kJPEG;
1044     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_DESIRED_PIXELFORMAT_UNSUPPORTED,
1045                                "PreDecodeCheckYuv, not support to create 420 data from not jpeg");
1046     CHECK_ERROR_RETURN_RET(stream_ == nullptr, ERR_IMAGE_SOURCE_DATA);
1047     auto iter = PLPIXEL_FORMAT_YUV_JPG_MAP.find(desiredFormat);
1048     CHECK_ERROR_RETURN_RET_LOG(iter == PLPIXEL_FORMAT_YUV_JPG_MAP.end(), ERR_IMAGE_INVALID_PARAMETER,
1049         "PreDecodeCheckYuv desiredFormat format not valid");
1050     uint32_t jpegBufferSize = stream_->GetStreamSize();
1051     CHECK_ERROR_RETURN_RET_LOG(jpegBufferSize == 0, ERR_IMAGE_SOURCE_DATA, "PreDecodeCheckYuv jpegBufferSize 0");
1052     cond = !IsColorSpaceSupport(static_cast<SkJpegCodec*>(codec_.get()));
1053     CHECK_ERROR_RETURN_RET(cond, ERR_IMAGE_SOURCE_DATA);
1054     return SUCCESS;
1055 }
1056 
1057 bool ExtDecoder::ResetCodec()
1058 {
1059     codec_ = nullptr;
1060     stream_->Seek(streamOff_);
1061     return ExtDecoder::CheckCodec();
1062 }
1063 
1064 #ifdef JPEG_HW_DECODE_ENABLE
1065 uint32_t ExtDecoder::DoHardWareDecode(DecodeContext &context)
1066 {
1067     if (HardWareDecode(context) == SUCCESS) {
1068         return SUCCESS;
1069     }
1070     return ERROR;
1071 }
1072 #endif
1073 
1074 static bool IsAllocatorTypeSupportHwDecode(const DecodeContext &context)
1075 {
1076     if (!context.isAppUseAllocator) {
1077         return true;
1078     }
1079     return context.allocatorType == Media::AllocatorType::DMA_ALLOC;
1080 }
1081 
1082 bool ExtDecoder::IsHeifSharedMemDecode(DecodeContext &context)
1083 {
1084     return codec_->getEncodedFormat() == SkEncodedImageFormat::kHEIF && context.isAppUseAllocator &&
1085         context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC;
1086 }
1087 
1088 void ExtDecoder::FillYuvInfo(DecodeContext &context, SkImageInfo &dstInfo)
1089 {
1090     if (context.allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
1091         if (IsHeifRegionDecode()) {
1092             context.yuvInfo.imageSize = { heifGridRegionInfo_.colCount * heifGridRegionInfo_.tileWidth -
1093                 heifGridRegionInfo_.widthPadding,
1094                 heifGridRegionInfo_.rowCount * heifGridRegionInfo_.tileHeight -
1095                 heifGridRegionInfo_.heightPadding };
1096         } else {
1097             context.yuvInfo.imageSize = { dstInfo.width(), dstInfo.height() };
1098         }
1099         context.yuvInfo.imageSize = {dstInfo.width(), dstInfo.height()};
1100         context.yuvInfo.yWidth = static_cast<uint32_t>(dstInfo.width());
1101         context.yuvInfo.yHeight = static_cast<uint32_t>(dstInfo.height());
1102         context.yuvInfo.uvWidth = static_cast<uint32_t>((dstInfo.width() + 1) / BYTES_PER_YUV_SAMPLE);
1103         context.yuvInfo.uvHeight = static_cast<uint32_t>((dstInfo.height() + 1) / BYTES_PER_YUV_SAMPLE);
1104         context.yuvInfo.yStride = static_cast<uint32_t>(dstInfo.width());
1105         context.yuvInfo.uvStride = context.yuvInfo.uvWidth + context.yuvInfo.uvWidth;
1106         context.yuvInfo.yOffset = 0;
1107         context.yuvInfo.uvOffset = static_cast<uint32_t>(dstInfo.width() * dstInfo.height());
1108     }
1109 }
1110 
1111 #ifdef HEIF_HW_DECODE_ENABLE
1112 bool SetOutPutFormat(OHOS::Media::PixelFormat pixelFormat, HeifDecoderImpl* decoder)
1113 {
1114     bool ret = true;
1115     if (pixelFormat == PixelFormat::RGB_565) {
1116         ret = decoder->setOutputColor(kHeifColorFormat_RGB565);
1117     } else if (pixelFormat == PixelFormat::RGBA_8888) {
1118         ret = decoder->setOutputColor(kHeifColorFormat_RGBA_8888);
1119     } else if (pixelFormat == PixelFormat::BGRA_8888) {
1120         ret = decoder->setOutputColor(kHeifColorFormat_BGRA_8888);
1121     } else if (pixelFormat == PixelFormat::NV12) {
1122         ret = decoder->setOutputColor(kHeifColorFormat_NV12);
1123     } else if (pixelFormat == PixelFormat::NV21) {
1124         ret = decoder->setOutputColor(kHeifColorFormat_NV21);
1125     }
1126     return ret;
1127 }
1128 #endif
1129 
1130 void ExtDecoder::UpdateDstInfoAndOutInfo(DecodeContext &context)
1131 {
1132     if (sampleSize_ != DEFAULT_SAMPLE_SIZE) {
1133         sampleSize_ = DEFAULT_SAMPLE_SIZE;
1134         dstInfo_ = SkImageInfo::Make(info_.width(), info_.height(), dstInfo_.colorType(),
1135             dstInfo_.alphaType(), dstInfo_.refColorSpace());
1136         context.outInfo.size.width = info_.width();
1137         context.outInfo.size.height = info_.height();
1138     }
1139 }
1140 
1141 uint32_t ExtDecoder::DoHeifSharedMemDecode(DecodeContext &context)
1142 {
1143 #ifdef HEIF_HW_DECODE_ENABLE
1144     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
1145     CHECK_ERROR_RETURN_RET_LOG(decoder == nullptr, ERR_IMAGE_DATA_UNSUPPORT, "Decode HeifDecoder is nullptr");
1146     uint64_t byteCount;
1147     uint64_t rowStride;
1148     if (IsHeifRegionDecode()) {
1149         UpdateHeifRegionDstInfo(context);
1150     }
1151     UpdateDstInfoAndOutInfo(context);
1152     rowStride = dstInfo_.minRowBytes64();
1153     byteCount = dstInfo_.computeMinByteSize();
1154     GridInfo gridInfo = decoder->GetGridInfo();
1155     if (IsYuv420Format(context.info.pixelFormat)) {
1156         if (IsHeifRegionDecode()) {
1157             UpdateHeifRegionDstInfo(context);
1158             rowStride = gridInfo.tileWidth * static_cast<uint32_t>(heifGridRegionInfo_.colCount) -
1159                 static_cast<uint32_t>(heifGridRegionInfo_.widthPadding);
1160             byteCount = JpegDecoderYuv::GetYuvOutSize(dstInfo_.width(), dstInfo_.height());
1161         } else {
1162             rowStride = static_cast<uint32_t>(dstInfo_.width());
1163             byteCount = JpegDecoderYuv::GetYuvOutSize(dstInfo_.width(), dstInfo_.height());
1164         }
1165     }
1166     CHECK_ERROR_RETURN_RET_LOG(SkImageInfo::ByteSizeOverflowed(byteCount), ERR_IMAGE_TOO_LARGE,
1167         "%{public}s too large byteCount: %{public}llu", __func__, static_cast<unsigned long long>(byteCount));
1168     CHECK_ERROR_RETURN_RET(!SetOutPutFormat(context.info.pixelFormat, decoder), ERR_IMAGE_DATA_UNSUPPORT);
1169     uint32_t res = ShareMemAlloc(context, byteCount);
1170     CHECK_ERROR_RETURN_RET(res != SUCCESS, res);
1171     if (IsHeifRegionDecode()) {
1172         decoder->SetDecodeRegion(heifGridRegionInfo_.colCount, heifGridRegionInfo_.rowCount,
1173             desiredRegion_.left, desiredRegion_.top, rowStride);
1174         decoder->SetPadding(heifGridRegionInfo_.widthPadding, heifGridRegionInfo_.heightPadding);
1175     }
1176     decoder->setDstBuffer(reinterpret_cast<uint8_t *>(context.pixelsBuffer.buffer), rowStride, nullptr);
1177     bool decodeRet = decoder->SwDecode(context.isAppUseAllocator);
1178     if (!decodeRet) {
1179         decoder->getErrMsg(context.hardDecodeError);
1180     } else if (IsYuv420Format(context.info.pixelFormat)) {
1181         FillYuvInfo(context, dstInfo_);
1182     }
1183     return decodeRet ? SUCCESS : ERR_IMAGE_DATA_UNSUPPORT;
1184 #else
1185     return ERR_IMAGE_DATA_UNSUPPORT;
1186 #endif
1187 }
1188 
1189 OHOS::Media::Size ExtDecoder::GetHeifRegionGridSize()
1190 {
1191     OHOS::Media::Size heifGridSize = {gridTileWidth_, gridTileHeight_};
1192     return heifGridSize;
1193 }
1194 
1195 void ExtDecoder::SetHeifDecodeRegion(DecodeContext &context, int32_t gridTileWidth, int32_t gridTileHeight)
1196 {
1197     if (gridTileWidth == ZERO || gridTileHeight == ZERO) {
1198         return;
1199     }
1200     double tempRegionColCount = ((desiredRegion_.left % gridTileWidth) + desiredRegion_.width) /
1201         static_cast<double>(gridTileWidth);
1202     double tempRegionRowCount = ((desiredRegion_.top % gridTileHeight) + desiredRegion_.height) /
1203         static_cast<double>(gridTileHeight);
1204     heifGridRegionInfo_.colCount = ceil(tempRegionColCount);
1205     heifGridRegionInfo_.rowCount = ceil(tempRegionRowCount);
1206     gridTileWidth_ = gridTileWidth;
1207     gridTileHeight_ = gridTileHeight;
1208     context.outInfo.size.height = heifGridRegionInfo_.rowCount *
1209         gridTileHeight - heifGridRegionInfo_.heightPadding;
1210     context.outInfo.size.width = heifGridRegionInfo_.colCount *
1211         gridTileWidth - heifGridRegionInfo_.widthPadding;
1212 }
1213 
1214 void ExtDecoder::UpdateHeifRegionDstInfo(DecodeContext &context)
1215 {
1216 #ifdef HEIF_HW_DECODE_ENABLE
1217     auto heifContext = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
1218     if (heifContext == nullptr) {
1219         IMAGE_LOGE("Decode heifContext is nullptr");
1220         return;
1221     }
1222     GridInfo gridInfo = heifContext->GetGridInfo();
1223     SetHeifDecodeRegion(context, static_cast<int32_t>(gridInfo.tileWidth), static_cast<int32_t>(gridInfo.tileHeight));
1224     if (context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC) {
1225         dstInfo_ = SkImageInfo::Make(heifGridRegionInfo_.colCount * gridInfo.tileWidth -
1226             heifGridRegionInfo_.widthPadding, heifGridRegionInfo_.rowCount *
1227             gridInfo.tileHeight - heifGridRegionInfo_.heightPadding,
1228             dstInfo_.colorType(), dstInfo_.alphaType(), dstInfo_.refColorSpace());
1229     } else {
1230         dstInfo_ = SkImageInfo::Make(heifGridRegionInfo_.colCount * gridInfo.tileWidth,
1231             heifGridRegionInfo_.rowCount * gridInfo.tileHeight,
1232             dstInfo_.colorType(), dstInfo_.alphaType(), dstInfo_.refColorSpace());
1233     }
1234 #else
1235     return;
1236 #endif
1237 }
1238 
1239 void ExtDecoder::UpdateHeifSKInfo(DecodeContext &context, uint64_t &rowStride)
1240 {
1241 #ifdef HEIF_HW_DECODE_ENABLE
1242     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
1243     if (decoder == nullptr) {
1244         IMAGE_LOGE("Decode HeifDecoder is nullptr");
1245         return;
1246     }
1247     auto dstBuffer = reinterpret_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
1248     decoder->SetDecodeRegion(heifGridRegionInfo_.colCount, heifGridRegionInfo_.rowCount,
1249         desiredRegion_.left, desiredRegion_.top, dstBuffer->GetStride());
1250     dstInfo_ = SkImageInfo::Make(info_.width(), info_.height(), dstInfo_.colorType(),
1251         dstInfo_.alphaType(), dstInfo_.refColorSpace());
1252     rowStride = dstInfo_.minRowBytes64();
1253 #else
1254     return;
1255 #endif
1256 }
1257 
1258 bool ExtDecoder::IsHeifRegionDecode()
1259 {
1260 #ifdef HEIF_HW_DECODE_ENABLE
1261     if (desiredRegion_.width > ZERO && desiredRegion_.height > ZERO && heifGridRegionInfo_.isGridType &&
1262         cropAndScaleStrategy_ != OHOS::Media::CropAndScaleStrategy::SCALE_FIRST) {
1263         auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
1264         bool cond = decoder == nullptr;
1265         CHECK_ERROR_RETURN_RET_LOG(cond, false, "Decode Heifdecoder is nullptr");
1266         if (decoder->IsHeifHasAlphaImage() || !decoder->IsHeifGainmapDivisibility(info_.width(), info_.height()) ||
1267             decoder->IsHeifGainmapYuv400()) {
1268             IMAGE_LOGI("Heif image contains alpha channels, or the size not be an integer multiple of GainMap");
1269             return false;
1270         }
1271         return true;
1272     }
1273     return false;
1274 #else
1275     return false;
1276 #endif
1277 }
1278 
1279 SkCodec::Result ExtDecoder::DoRegionDecode(DecodeContext &context)
1280 {
1281 #ifdef SK_ENABLE_OHOS_CODEC
1282     auto SkOHOSCodec = SkOHOSCodec::MakeFromCodec(std::move(codec_));
1283     // Ask the codec for a scaled subset
1284     SkIRect decodeSubset = dstSubset_;
1285     bool cond = SkOHOSCodec == nullptr || !SkOHOSCodec->getSupportedSubset(&decodeSubset);
1286     CHECK_ERROR_RETURN_RET_LOG(cond, SkCodec::kErrorInInput, "Error: Could not get subset");
1287     int sampleSize = GetSoftwareScaledSize(RegiondesiredSize_.width, RegiondesiredSize_.height);
1288     ImageFuncTimer imageFuncTimer("%s, decodeSubset: left:%d, top:%d, width:%d, height:%d, sampleSize:%d", __func__,
1289         decodeSubset.left(), decodeSubset.top(), decodeSubset.width(), decodeSubset.height(), sampleSize);
1290     SkISize scaledSize = SkOHOSCodec->getSampledSubsetDimensions(sampleSize, decodeSubset);
1291     SkImageInfo decodeInfo = dstInfo_.makeWH(scaledSize.width(), scaledSize.height());
1292 
1293     uint64_t byteCount = decodeInfo.computeMinByteSize();
1294     uint32_t res = 0;
1295     if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
1296         res = DmaMemAlloc(context, byteCount, decodeInfo);
1297     } else if (context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC) {
1298         ShareMemAlloc(context, byteCount);
1299     }
1300     CHECK_ERROR_RETURN_RET_LOG(res != SUCCESS, SkCodec::kErrorInInput,
1301         "do region decode failed, SetContextPixelsBuffer failed");
1302 
1303     uint8_t* dstBuffer = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
1304     uint64_t rowStride = decodeInfo.minRowBytes64();
1305     if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
1306         SurfaceBuffer* sbBuffer = reinterpret_cast<SurfaceBuffer*> (context.pixelsBuffer.context);
1307         if (sbBuffer == nullptr) {
1308             IMAGE_LOGE("%{public}s: surface buffer is nullptr", __func__);
1309             return SkCodec::kErrorInInput;
1310         }
1311         rowStride = static_cast<uint64_t>(sbBuffer->GetStride());
1312     }
1313 
1314     // Decode into the destination bitmap
1315     SkOHOSCodec::OHOSOptions options;
1316     options.fSampleSize = sampleSize;
1317     options.fSubset = &decodeSubset;
1318     SkCodec::Result result = SkOHOSCodec->getOHOSPixels(decodeInfo, dstBuffer, rowStride, &options);
1319     switch (result) {
1320         case SkCodec::kSuccess:
1321         case SkCodec::kIncompleteInput:
1322         case SkCodec::kErrorInInput:
1323             context.outInfo.size.width = decodeInfo.width();
1324             context.outInfo.size.height = decodeInfo.height();
1325             return SkCodec::kSuccess;
1326         default:
1327             IMAGE_LOGE("Error: Could not get pixels with message %{public}s", SkCodec::ResultToString(result));
1328             return result;
1329     }
1330 #else
1331     return SkCodec::kSuccess;
1332 #endif
1333 }
1334 
1335 SkCodec::Result ExtDecoder::DoSampleDecode(DecodeContext &context)
1336 {
1337 #ifdef SK_ENABLE_OHOS_CODEC
1338     uint64_t byteCount = dstInfo_.computeMinByteSize();
1339     uint32_t res = SetContextPixelsBuffer(byteCount, context);
1340     CHECK_ERROR_RETURN_RET_LOG(res != SUCCESS, SkCodec::kErrorInInput,
1341         "%{public}s failed, SetContextPixelsBuffer failed", __func__);
1342 
1343     uint8_t* dstBuffer = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
1344     uint64_t rowStride = dstInfo_.minRowBytes64();
1345     if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
1346         SurfaceBuffer* sbBuffer = reinterpret_cast<SurfaceBuffer*> (context.pixelsBuffer.context);
1347         CHECK_ERROR_RETURN_RET_LOG(sbBuffer == nullptr, SkCodec::kErrorInInput,
1348             "%{public}s: surface buffer is nullptr", __func__);
1349         rowStride = static_cast<uint64_t>(sbBuffer->GetStride());
1350     }
1351 
1352     auto SkOHOSCodec = SkOHOSCodec::MakeFromCodec(std::move(codec_));
1353     SkOHOSCodec::OHOSOptions options;
1354     options.fSampleSize = softSampleSize_;
1355     if (SkOHOSCodec == nullptr) {
1356         IMAGE_LOGE("%{public}s failed, SkOHOSCodec is nullptr", __func__);
1357         return SkCodec::kErrorInInput;
1358     }
1359     SkCodec::Result result = SkOHOSCodec->getOHOSPixels(dstInfo_, dstBuffer, rowStride, &options);
1360     switch (result) {
1361         case SkCodec::kSuccess:
1362         case SkCodec::kIncompleteInput:
1363         case SkCodec::kErrorInInput:
1364             context.outInfo.size.width = dstInfo_.width();
1365             context.outInfo.size.height = dstInfo_.height();
1366             return SkCodec::kSuccess;
1367         default:
1368             IMAGE_LOGE("Error: Could not get pixels with message %{public}s", SkCodec::ResultToString(result));
1369             return result;
1370     }
1371 #else
1372     return SkCodec::kSuccess;
1373 #endif
1374 }
1375 
1376 #ifdef JPEG_HW_DECODE_ENABLE
1377 void ExtDecoder::InitJpegDecoder()
1378 {
1379     if (ImageSystemProperties::GetHardWareDecodeEnabled()) {
1380         IMAGE_LOGD("Init hardware jpeg decoder");
1381         if (hwDecoderPtr_ == nullptr) {
1382             hwDecoderPtr_ = std::make_shared<JpegHardwareDecoder>();
1383         }
1384         if (!hwDecoderPtr_->InitDecoder()) {
1385             IMAGE_LOGE("Init jpeg hardware decoder failed");
1386             initJpegErr_ = true;
1387         }
1388     }
1389     return;
1390 }
1391 #endif
1392 
1393 bool ExtDecoder::IsSupportHeifHardwareDecode(const PixelDecodeOptions &opts)
1394 {
1395 #ifdef HEIF_HW_DECODE_ENABLE
1396     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
1397     if (decoder == nullptr) {
1398         IMAGE_LOGE("Decode HeifDecoder is nullptr");
1399         return false;
1400     }
1401     GridInfo gridInfo = decoder->GetGridInfo();
1402     if (!ImageSystemProperties::GetHeifHardwareDecodeEnabled()) {
1403         return false;
1404     }
1405     if (decoder->IsHeifGainmapYuv400() || decoder->IsHeifAlphaYuv400()) {
1406         IMAGE_LOGD("The gainmap or alpha channel of the HEIF is not YUV420 format");
1407         return false;
1408     }
1409     if (opts.CropRect.width > ZERO || opts.CropRect.height > ZERO) {
1410         IMAGE_LOGD("HEIF regiondecode does not set sampleSize");
1411         return false;
1412     }
1413     if (decoder->GetPrimaryLumaBitNum() == LUMA_10_BIT) {
1414         IMAGE_LOGD("HEIF primary image is Luma 10bit, not support set samplesize");
1415         return false;
1416     }
1417     return gridInfo.tileWidth >= HEIF_HARDWARE_TILE_MIN_DIM &&
1418         gridInfo.tileHeight >= HEIF_HARDWARE_TILE_MIN_DIM &&
1419         gridInfo.tileWidth <= HEIF_HARDWARE_TILE_MAX_DIM &&
1420         gridInfo.tileHeight <= HEIF_HARDWARE_TILE_MAX_DIM &&
1421         gridInfo.displayWidth >= HEIF_HARDWARE_DISPLAY_MIN_DIM &&
1422         gridInfo.displayHeight >= HEIF_HARDWARE_DISPLAY_MIN_DIM;
1423 #else
1424     return false;
1425 #endif
1426 }
1427 
1428 bool ExtDecoder::IsDivisibleBySampleSize()
1429 {
1430 #ifdef HEIF_HW_DECODE_ENABLE
1431     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
1432     bool cond = decoder == nullptr;
1433     CHECK_ERROR_RETURN_RET_LOG(cond, false, "Decode Heifdecoder is nullptr");
1434     GridInfo gridInfo = decoder->GetGridInfo();
1435     if (gridInfo.tileWidth % sampleSize_ != 0 || gridInfo.tileHeight % sampleSize_ != 0) {
1436         return false;
1437     }
1438     if (IsYuv420Format(heifPixelFormat_) &&
1439         (info_.height() / static_cast<int32_t>(sampleSize_)) % NUM_2 != 0) {
1440         return false;
1441     }
1442     if (decoder->IsGainmapDivisibleBySampleSize(sampleSize_) &&
1443         info_.width() % static_cast<int32_t>(sampleSize_) == 0 &&
1444         info_.height() % static_cast<int32_t>(sampleSize_) == 0) {
1445         return true;
1446     }
1447     return false;
1448 #else
1449     return false;
1450 #endif
1451 }
1452 
1453 void ExtDecoder::SetHeifSampleSize(const PixelDecodeOptions &opts, int &dstWidth, int &dstHeight,
1454     SkColorType desireColor, SkAlphaType desireAlpha)
1455 {
1456 #ifdef HEIF_HW_DECODE_ENABLE
1457     float scale = ZERO;
1458     if (IsSupportHeifHardwareDecode(opts) && IsLowDownScale(opts.desiredSize, info_) &&
1459         GetHardwareScaledSize(dstWidth, dstHeight, scale) && IsDivisibleBySampleSize()) {
1460             dstInfo_ = SkImageInfo::Make(dstWidth, dstHeight,
1461                 desireColor, desireAlpha, getDesiredColorSpace(info_, opts));
1462     } else {
1463         sampleSize_ = DEFAULT_SAMPLE_SIZE;
1464         dstInfo_ = SkImageInfo::Make(info_.width(), info_.height(),
1465             desireColor, desireAlpha, getDesiredColorSpace(info_, opts));
1466     }
1467 #endif
1468 }
1469 
1470 bool ExtDecoder::DoHeifSwDecode(OHOS::ImagePlugin::DecodeContext &context)
1471 {
1472 #ifdef HEIF_HW_DECODE_ENABLE
1473     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
1474     bool cond = decoder == nullptr;
1475     CHECK_ERROR_RETURN_RET_LOG(cond, false, "Decode Heifdecoder is nullptr");
1476     ReleaseOutputBuffer(context, context.allocatorType);
1477     uint64_t byteCount = info_.computeMinByteSize();
1478     //If the HWdecode failed, software does not support setting samplesize, allocate memory based on original image.
1479     cond = false;
1480     sampleSize_ = DEFAULT_SAMPLE_SIZE;
1481     context.outInfo.size.width = info_.width();
1482     context.outInfo.size.height = info_.height();
1483     if (IsHeifToYuvDecode(context)) {
1484         cond = HeifYUVMemAlloc(context, info_) != SUCCESS;
1485     } else {
1486         CHECK_ERROR_RETURN_RET_LOG(SkImageInfo::ByteSizeOverflowed(byteCount), false,
1487             "%{public}s too large byteCount: %{public}llu", __func__, static_cast<unsigned long long>(byteCount));
1488         cond = DmaMemAlloc(context, byteCount, info_) != SUCCESS;
1489     }
1490     CHECK_ERROR_RETURN_RET(cond, false);
1491     auto dstBuffer = reinterpret_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
1492     decoder->SetSampleFormat(DEFAULT_SCALE_SIZE, heifColorSpaceName_, heifIsColorSpaceFromCicp_);
1493     decoder->setDstBuffer(reinterpret_cast<uint8_t *>(context.pixelsBuffer.buffer),
1494         dstBuffer->GetStride(), context.pixelsBuffer.context);
1495     bool decodeRet = decoder->SwDecode(false);
1496     return decodeRet;
1497 #else
1498     return false;
1499 #endif
1500 }
1501 
1502 uint32_t ExtDecoder::DoHeifToRgbDecode(OHOS::ImagePlugin::DecodeContext &context)
1503 {
1504 #ifdef HEIF_HW_DECODE_ENABLE
1505     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
1506     bool cond = decoder == nullptr;
1507     CHECK_ERROR_RETURN_RET_LOG(cond, false, "Decode Heifdecoder is nullptr");
1508 
1509     if (IsHeifRegionDecode()) {
1510         UpdateHeifRegionDstInfo(context);
1511     }
1512     uint64_t byteCount = dstInfo_.computeMinByteSize();
1513     if (ImageUtils::IsSdrPixelMapReuseSuccess(context, info_.width(), info_.height(), reusePixelmap_)) {
1514         IMAGE_LOGI("HEIF RGB Maindecode reusePixelmap success");
1515     } else {
1516         CHECK_ERROR_RETURN_RET_LOG(SkImageInfo::ByteSizeOverflowed(byteCount), ERR_IMAGE_TOO_LARGE,
1517             "%{public}s too large byteCount: %{public}llu", __func__, static_cast<unsigned long long>(byteCount));
1518         bool cond = DmaMemAlloc(context, byteCount, dstInfo_) != SUCCESS;
1519         CHECK_ERROR_RETURN_RET(cond, ERR_IMAGE_DATA_UNSUPPORT);
1520     }
1521     auto dstBuffer = reinterpret_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
1522     if (IsHeifRegionDecode()) {
1523         decoder->SetDecodeRegion(heifGridRegionInfo_.colCount, heifGridRegionInfo_.rowCount,
1524             desiredRegion_.left, desiredRegion_.top, dstBuffer->GetStride());
1525         IMAGE_LOGI("Do Heif RGB Type Region Decode, xy [%{public}d , %{public}d], wh [%{public}d x %{public}d]",
1526             desiredRegion_.left, desiredRegion_.top, desiredRegion_.width, desiredRegion_.height);
1527     }
1528     decoder->SetSampleFormat(sampleSize_, heifColorSpaceName_, heifIsColorSpaceFromCicp_);
1529     decoder->setDstBuffer(reinterpret_cast<uint8_t *>(context.pixelsBuffer.buffer),
1530         dstBuffer->GetStride(), context.pixelsBuffer.context);
1531     SetOutPutFormat(context.info.pixelFormat, decoder);
1532     bool decodeRet = decoder->decode(nullptr);
1533     if (!decodeRet && sampleSize_ != DEFAULT_SAMPLE_SIZE) {
1534         decodeRet = DoHeifSwDecode(context);
1535     }
1536     if (!decodeRet) {
1537         decoder->getErrMsg(context.hardDecodeError);
1538     }
1539     return decodeRet ? SUCCESS : ERR_IMAGE_DATA_UNSUPPORT;
1540 #else
1541     return ERR_IMAGE_DATA_UNSUPPORT;
1542 #endif
1543 }
1544 
1545 uint32_t ExtDecoder::DoHeifDecode(DecodeContext &context)
1546 {
1547 #ifdef HEIF_HW_DECODE_ENABLE
1548     context.isHardDecode = true;
1549     if (IsHeifSharedMemDecode(context)) {
1550         context.isHardDecode = false;
1551         return DoHeifSharedMemDecode(context);
1552     }
1553     if (IsHeifToYuvDecode(context)) {
1554         return DoHeifToYuvDecode(context);
1555     }
1556     if (IsHeifToSingleHdrDecode(context)) {
1557         return DoHeifToSingleHdrDecode(context);
1558     }
1559     return DoHeifToRgbDecode(context);
1560 #else
1561     return ERR_IMAGE_DATA_UNSUPPORT;
1562 #endif
1563 }
1564 
1565 uint32_t ExtDecoder::Decode(uint32_t index, DecodeContext &context)
1566 {
1567 #ifdef SK_ENABLE_OHOS_CODEC
1568     if (SupportRegionFlag_) {
1569         DebugInfo(info_, dstInfo_, dstOptions_);
1570         SkCodec::Result regionDecodeRes = DoRegionDecode(context);
1571         ResetCodec();
1572         if (SkCodec::kSuccess == regionDecodeRes) {
1573             return SUCCESS;
1574         } else {
1575             IMAGE_LOGE("do region decode failed");
1576             return ERR_IMAGE_DECODE_FAILED;
1577         }
1578     }
1579     if (IsSupportSampleDecode(context.info.pixelFormat)) {
1580         DebugInfo(info_, dstInfo_, dstOptions_);
1581         SkCodec::Result sampleDecodeRes = DoSampleDecode(context);
1582         ResetCodec();
1583         if (SkCodec::kSuccess == sampleDecodeRes) {
1584             return SUCCESS;
1585         } else {
1586             IMAGE_LOGE("do sample decode failed");
1587             return ERR_IMAGE_DECODE_FAILED;
1588         }
1589     }
1590 #endif
1591 #ifdef JPEG_HW_DECODE_ENABLE
1592     if (!initJpegErr_ && IsAllocatorTypeSupportHwDecode(context) && IsSupportHardwareDecode()
1593         && DoHardWareDecode(context) == SUCCESS) {
1594         context.isHardDecode = true;
1595         return SUCCESS;
1596     }
1597 #endif
1598     uint32_t res = PreDecodeCheck(index);
1599     CHECK_ERROR_RETURN_RET(res != SUCCESS, res);
1600     context.outInfo.size.width = dstInfo_.width();
1601     context.outInfo.size.height = dstInfo_.height();
1602     SkEncodedImageFormat skEncodeFormat = codec_->getEncodedFormat();
1603 #if !defined(CROSS_PLATFORM)
1604     int timerFd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
1605     if (timerFd >= 0) {
1606         close(timerFd);
1607         ffrt::submit([skEncodeFormat] {
1608             ReportImageType(skEncodeFormat);
1609         }, {}, {});
1610     }
1611 #endif
1612     if (skEncodeFormat == SkEncodedImageFormat::kHEIF) {
1613         return DoHeifDecode(context);
1614     }
1615     PixelFormat format = context.info.pixelFormat;
1616     bool isOutputYuv420Format = IsYuv420Format(context.info.pixelFormat);
1617     uint32_t result = 0;
1618     if (isOutputYuv420Format && skEncodeFormat == SkEncodedImageFormat::kJPEG) {
1619 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
1620         return 0;
1621 #else
1622         result = DecodeToYuv420(index, context);
1623         if (result == JpegYuvDecodeError_Success) {
1624             return result;
1625         }
1626         IMAGE_LOGI("DecodeToYuv420 failed, decode rgba then convert");
1627         context.pixelsBuffer.buffer = nullptr;
1628         context.info.pixelFormat = PixelFormat::RGBA_8888;
1629 #endif
1630     }
1631     uint64_t byteCount = dstInfo_.computeMinByteSize();
1632     uint8_t *dstBuffer = nullptr;
1633     std::unique_ptr<uint8_t[]> tmpBuffer;
1634     if (dstInfo_.colorType() == SkColorType::kRGB_888x_SkColorType) {
1635         tmpBuffer = make_unique<uint8_t[]>(byteCount);
1636         if (tmpBuffer == nullptr) {
1637             IMAGE_LOGE("Make unique pointer failed, byteCount: %{public}llu",
1638                 static_cast<unsigned long long>(byteCount));
1639             return ERR_IMAGE_DECODE_FAILED;
1640         }
1641         dstBuffer = tmpBuffer.get();
1642         byteCount = byteCount / NUM_4 * NUM_3;
1643     }
1644     if (context.pixelsBuffer.buffer == nullptr) {
1645         if (ImageUtils::IsSdrPixelMapReuseSuccess(context, info_.width(), info_.height(), reusePixelmap_)) {
1646             IMAGE_LOGI("Maindecode reusePixelmap success");
1647         } else {
1648             res = SetContextPixelsBuffer(byteCount, context);
1649             CHECK_ERROR_RETURN_RET(res != SUCCESS, res);
1650         }
1651         if (dstBuffer == nullptr) {
1652             dstBuffer = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
1653         }
1654     }
1655     dstOptions_.fFrameIndex = static_cast<int>(index);
1656     DebugInfo(info_, dstInfo_, dstOptions_);
1657     uint64_t rowStride = dstInfo_.minRowBytes64();
1658 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1659     if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
1660         SurfaceBuffer* sbBuffer = reinterpret_cast<SurfaceBuffer*> (context.pixelsBuffer.context);
1661         CHECK_ERROR_RETURN_RET_LOG(sbBuffer == nullptr, ERR_DMA_DATA_ABNORMAL,
1662             "%{public}s: surface buffer is nullptr", __func__);
1663         rowStride = static_cast<uint64_t>(sbBuffer->GetStride());
1664     }
1665 #endif
1666     IMAGE_LOGD("decode format %{public}d", skEncodeFormat);
1667     if (skEncodeFormat == SkEncodedImageFormat::kGIF || skEncodeFormat == SkEncodedImageFormat::kWEBP) {
1668         res = GifDecode(index, context, rowStride);
1669         ImageUtils::FlushContextSurfaceBuffer(context);
1670         return res;
1671     }
1672     SkCodec::Result ret = codec_->getPixels(dstInfo_, dstBuffer, rowStride, &dstOptions_);
1673     if (ret == SkCodec::kIncompleteInput || ret == SkCodec::kErrorInInput) {
1674         IMAGE_LOGI("Decode broken data success. Triggered kIncompleteInput feature of skia!");
1675     } else if (ret != SkCodec::kSuccess && ResetCodec()) {
1676         ret = codec_->getPixels(dstInfo_, dstBuffer, rowStride, &dstOptions_); // Try again
1677     }
1678     if (ret != SkCodec::kSuccess && ret != SkCodec::kIncompleteInput && ret != SkCodec::kErrorInInput) {
1679         IMAGE_LOGE("Decode failed, get pixels failed, ret=%{public}d", ret);
1680         SetHeifDecodeError(context);
1681         ResetCodec(); // release old jpeg codec
1682         return ERR_IMAGE_DECODE_ABNORMAL;
1683     }
1684     if (dstInfo_.colorType() == SkColorType::kRGB_888x_SkColorType) {
1685         res = RGBxToRGB(dstBuffer, dstInfo_.computeMinByteSize(), static_cast<uint8_t*>(context.pixelsBuffer.buffer),
1686             byteCount, dstInfo_.width() * dstInfo_.height());
1687         CHECK_ERROR_RETURN_RET_LOG(res != SUCCESS, res, "Decode failed, RGBxToRGB failed, res=%{public}d", res);
1688     }
1689     if (isOutputYuv420Format && skEncodeFormat == SkEncodedImageFormat::kJPEG && result != JpegYuvDecodeError_Success) {
1690         res = ConvertFormatToYUV(context, dstInfo_, byteCount, format);
1691         CHECK_ERROR_RETURN_RET_LOG(res != SUCCESS, res,
1692             "Decode failed, ConvertFormatToYUV failed, res=%{public}d", res);
1693     }
1694 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1695     if (context.allocatorType == AllocatorType::DMA_ALLOC) {
1696         SurfaceBuffer* surfaceBuffer = reinterpret_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
1697         if (surfaceBuffer && (surfaceBuffer->GetUsage() & BUFFER_USAGE_MEM_MMZ_CACHE)) {
1698             GSError err = surfaceBuffer->FlushCache();
1699             if (err != GSERROR_OK) {
1700                 IMAGE_LOGE("FlushCache failed, GSError=%{public}d", err);
1701             }
1702         }
1703     }
1704 #endif
1705     return SUCCESS;
1706 }
1707 
1708 uint32_t ExtDecoder::ReadJpegData(uint8_t* jpegBuffer, uint32_t jpegBufferSize)
1709 {
1710     CHECK_ERROR_RETURN_RET(stream_ == nullptr, ERR_IMAGE_SOURCE_DATA);
1711     bool cond = jpegBuffer == nullptr || jpegBufferSize == 0;
1712     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_GET_DATA_ABNORMAL, "ExtDecoder::ReadJpegData wrong parameter");
1713     uint32_t savedPosition = stream_->Tell();
1714     cond = !stream_->Seek(0);
1715     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_GET_DATA_ABNORMAL, "ExtDecoder::ReadJpegData seek stream failed");
1716     uint32_t readSize = 0;
1717     bool result = stream_->Read(jpegBufferSize, jpegBuffer, jpegBufferSize, readSize);
1718     cond = !stream_->Seek(savedPosition);
1719     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_GET_DATA_ABNORMAL, "ExtDecoder::ReadJpegData seek stream failed");
1720     cond = !result || readSize != jpegBufferSize;
1721     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_SOURCE_DATA, "ReadJpegData read image data failed");
1722     return SUCCESS;
1723 }
1724 
1725 JpegYuvFmt ExtDecoder::GetJpegYuvOutFmt(PixelFormat desiredFormat)
1726 {
1727     auto iter = PLPIXEL_FORMAT_YUV_JPG_MAP.find(desiredFormat);
1728     if (iter == PLPIXEL_FORMAT_YUV_JPG_MAP.end()) {
1729         return JpegYuvFmt::OutFmt_NV12;
1730     } else {
1731         return iter->second;
1732     }
1733 }
1734 
1735 uint32_t ExtDecoder::DecodeToYuv420(uint32_t index, DecodeContext &context)
1736 {
1737 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
1738     return 0;
1739 #endif
1740     uint32_t res = PreDecodeCheckYuv(index, context.info.pixelFormat);
1741     CHECK_ERROR_RETURN_RET(res != SUCCESS, res);
1742     uint32_t jpegBufferSize = stream_->GetStreamSize();
1743     CHECK_ERROR_RETURN_RET_LOG(jpegBufferSize == 0, ERR_IMAGE_SOURCE_DATA, "DecodeToYuv420 jpegBufferSize 0");
1744     uint8_t* jpegBuffer = NULL;
1745     if (stream_->GetStreamType() == ImagePlugin::BUFFER_SOURCE_TYPE) {
1746         jpegBuffer = stream_->GetDataPtr();
1747     }
1748     std::unique_ptr<uint8_t[]> jpegBufferPtr;
1749     if (jpegBuffer == nullptr) {
1750         jpegBufferPtr = std::make_unique<uint8_t[]>(jpegBufferSize);
1751         jpegBuffer = jpegBufferPtr.get();
1752         res = ReadJpegData(jpegBuffer, jpegBufferSize);
1753         CHECK_ERROR_RETURN_RET(res != SUCCESS, res);
1754     }
1755     JpegYuvFmt decodeOutFormat = GetJpegYuvOutFmt(context.info.pixelFormat);
1756     Size jpgSize = {static_cast<uint32_t>(info_.width()), static_cast<uint32_t>(info_.height())};
1757     Size desiredSize = desiredSizeYuv_;
1758     bool bRet = JpegDecoderYuv::GetScaledSize(jpgSize.width, jpgSize.height, desiredSize.width, desiredSize.height);
1759     bool cond = !bRet || desiredSize.width == 0 || desiredSize.height == 0;
1760     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_INVALID_PARAMETER, "DecodeToYuv420 GetScaledSize failed");
1761     uint64_t yuvBufferSize = JpegDecoderYuv::GetYuvOutSize(desiredSize.width, desiredSize.height);
1762     dstInfo_ = dstInfo_.makeWH(desiredSize.width, desiredSize.height);
1763     res = SetContextPixelsBuffer(yuvBufferSize, context);
1764     cond = res != SUCCESS;
1765     CHECK_ERROR_RETURN_RET_LOG(cond, res, "ExtDecoder::DecodeToYuv420 SetContextPixelsBuffer failed");
1766     uint8_t *yuvBuffer = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
1767     std::unique_ptr<JpegDecoderYuv> jpegYuvDecoder_ = std::make_unique<JpegDecoderYuv>();
1768     JpegDecoderYuvParameter para = {jpgSize.width, jpgSize.height, jpegBuffer, jpegBufferSize,
1769         yuvBuffer, yuvBufferSize, decodeOutFormat, desiredSize.width, desiredSize.height};
1770     int retDecode = jpegYuvDecoder_->DoDecode(context, para);
1771     if (retDecode != JpegYuvDecodeError_Success) {
1772         IMAGE_LOGE("DecodeToYuv420 DoDecode return %{public}d", retDecode);
1773     } else {
1774         // update yuv outInfo if decode success, same as jpeg hardware decode
1775         context.outInfo.size = desiredSize;
1776     }
1777     return retDecode;
1778 }
1779 
1780 static std::string GetFormatStr(SkEncodedImageFormat format)
1781 {
1782     switch (format) {
1783         case SkEncodedImageFormat::kBMP:
1784             return "bmp";
1785         case SkEncodedImageFormat::kGIF:
1786             return "gif";
1787         case SkEncodedImageFormat::kICO:
1788             return "ico";
1789         case SkEncodedImageFormat::kJPEG:
1790             return "jpeg";
1791         case SkEncodedImageFormat::kPNG:
1792             return "png";
1793         case SkEncodedImageFormat::kWBMP:
1794             return "wbmp";
1795         case SkEncodedImageFormat::kWEBP:
1796             return "webp";
1797         case SkEncodedImageFormat::kPKM:
1798             return "pkm";
1799         case SkEncodedImageFormat::kKTX:
1800             return "ktx";
1801         case SkEncodedImageFormat::kASTC:
1802             return "astc";
1803         case SkEncodedImageFormat::kDNG:
1804             return "dng";
1805         case SkEncodedImageFormat::kHEIF:
1806             return "heif";
1807         case SkEncodedImageFormat::kAVIF:
1808             return "avif";
1809         default:
1810             return UNKNOWN_IMAGE;
1811     }
1812 }
1813 
1814 void ExtDecoder::ReportImageType(SkEncodedImageFormat skEncodeFormat)
1815 {
1816     IMAGE_LOGD("ExtDecoder::ReportImageType format %{public}d start", skEncodeFormat);
1817     static constexpr char IMAGE_FWK_UE[] = "IMAGE_FWK_UE";
1818 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1819     int32_t ret = HiSysEventWrite(
1820             IMAGE_FWK_UE,
1821             "DECODED_IMAGE_TYPE_STATISTICS",
1822             HiviewDFX::HiSysEvent::EventType::STATISTIC,
1823             "PNAMEID", DEFAULT_PACKAGE_NAME,
1824             "PVERSIONID", DEFAULT_VERSION_ID,
1825             "IMAGE_TYPE", GetFormatStr(skEncodeFormat)
1826     );
1827     uint32_t tmpRet = static_cast<uint32_t>(ret);
1828     CHECK_DEBUG_RETURN_LOG(SUCCESS != tmpRet, "ExtDecoder::ReportImageType failed, ret = %{public}d", ret);
1829 #endif
1830     IMAGE_LOGD("ExtDecoder::ReportImageType format %{public}d success", skEncodeFormat);
1831 }
1832 #ifdef JPEG_HW_DECODE_ENABLE
1833 uint32_t ExtDecoder::AllocOutputBuffer(DecodeContext &context,
1834     OHOS::HDI::Codec::Image::V2_1::CodecImageBuffer& outputBuffer)
1835 {
1836     ImageTrace imageTrace("Ext AllocOutputBuffer");
1837     bool cond = ImageUtils::CheckMulOverflow(hwDstInfo_.height(), hwDstInfo_.width(), hwDstInfo_.bytesPerPixel());
1838     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_DECODE_ABNORMAL,
1839         "Invalid dstInfo height:%{public}d, width:%{public}d", hwDstInfo_.height(), hwDstInfo_.width());
1840     uint64_t byteCount = static_cast<uint64_t>(hwDstInfo_.height()) *
1841             static_cast<uint64_t>(hwDstInfo_.width()) *
1842             static_cast<uint64_t>(hwDstInfo_.bytesPerPixel());
1843     context.allocatorType = AllocatorType::DMA_ALLOC;
1844     if (ImageUtils::IsSdrPixelMapReuseSuccess(context, info_.width(), info_.height(), reusePixelmap_)) {
1845         IMAGE_LOGI("Jpeg hardware decode reusePixelmap success");
1846     } else {
1847         uint32_t ret = JpegHwDmaMemAlloc(context, byteCount, hwDstInfo_);
1848         CHECK_ERROR_RETURN_RET_LOG(ret != SUCCESS, ERR_IMAGE_DECODE_ABNORMAL,
1849             "Alloc OutputBuffer failed, ret=%{public}d", ret);
1850     }
1851 
1852     CHECK_ERROR_RETURN_RET_LOG(context.pixelsBuffer.context == nullptr, ERR_IMAGE_DECODE_ABNORMAL,
1853         "Alloc OutputBuffer failed, context is null");
1854     BufferHandle *handle = (static_cast<SurfaceBuffer*>(context.pixelsBuffer.context))->GetBufferHandle();
1855     if (outputColorFmt_ == V1_2::PIXEL_FMT_RGBA_8888) {
1856         outputBufferSize_.width = handle->stride / NUM_4;
1857     } else {
1858         outputBufferSize_.width = handle->stride;
1859     }
1860     outputBufferSize_.height = handle->height;
1861     outputBuffer.buffer = new NativeBuffer(handle);
1862     outputBuffer.fenceFd = -1;
1863     return SUCCESS;
1864 }
1865 
1866 bool ExtDecoder::CheckContext(const DecodeContext &context)
1867 {
1868     if (IsYuv420Format(context.info.pixelFormat)) {
1869         if (outputColorFmt_ == V1_2::PIXEL_FMT_YCRCB_420_SP) {
1870             return true;
1871         }
1872         IMAGE_LOGI("yuv hardware decode only support NV21 format");
1873         return false;
1874     }
1875     if (dstInfo_.colorType() != kRGBA_8888_SkColorType) {
1876         IMAGE_LOGI("jpeg hardware decode only support rgba_8888 format");
1877         return false;
1878     }
1879     return true;
1880 }
1881 
1882 void ExtDecoder::ReleaseOutputBuffer(DecodeContext &context, Media::AllocatorType allocatorType)
1883 {
1884     ImageUtils::SurfaceBuffer_Unreference(static_cast<SurfaceBuffer*>(context.pixelsBuffer.context));
1885     context.pixelsBuffer.buffer = nullptr;
1886     context.allocatorType = allocatorType;
1887     context.freeFunc = nullptr;
1888     context.pixelsBuffer.bufferSize = 0;
1889     context.pixelsBuffer.context = nullptr;
1890 }
1891 
1892 uint32_t ExtDecoder::ApplyDesiredColorSpace(DecodeContext &context)
1893 {
1894     SurfaceBuffer* sbuffer = static_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
1895     int32_t width = sbuffer->GetWidth();
1896     int32_t height = sbuffer->GetHeight();
1897     uint64_t rowStride = static_cast<uint64_t>(sbuffer->GetStride());
1898 
1899     // build sk source information
1900     SkTransInfo src;
1901     uint8_t* srcData = static_cast<uint8_t*>(sbuffer->GetVirAddr());
1902     SkColorType colorType = ImageTypeConverter::ToSkColorType(context.pixelFormat);
1903     SkAlphaType alphaType = ImageTypeConverter::ToSkAlphaType(OHOS::Media::AlphaType::IMAGE_ALPHA_TYPE_PREMUL);
1904 
1905     bool cond = !src.bitmap.installPixels(info_, srcData, rowStride);
1906     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_COLOR_CONVERT, "apply colorspace get install failed.");
1907 
1908     // build target information
1909     SkTransInfo dst;
1910     dst.info = SkImageInfo::Make(width, height, colorType, alphaType, dstColorSpace_->ToSkColorSpace());
1911 
1912     MemoryData memoryData = {nullptr, hwDstInfo_.computeMinByteSize(),
1913         "Trans ImageData", {hwDstInfo_.width(), hwDstInfo_.height()}, context.pixelFormat};
1914     AllocatorType allocatorType = context.allocatorType;
1915     auto m = MemoryManager::CreateMemory(allocatorType, memoryData);
1916     CHECK_ERROR_RETURN_RET_LOG(m == nullptr, ERR_IMAGE_COLOR_CONVERT, "applyColorSpace CreateMemory failed");
1917 
1918     // Transfor pixels by readPixels
1919     if (!src.bitmap.readPixels(dst.info, m->data.data, rowStride, 0, 0)) {
1920         m->Release();
1921         IMAGE_LOGE("applyColorSpace ReadPixels failded");
1922         return ERR_IMAGE_COLOR_CONVERT;
1923     }
1924     FreeContextBuffer(context.freeFunc, context.allocatorType, context.pixelsBuffer);
1925     SetDecodeContextBuffer(context, context.allocatorType, static_cast<uint8_t *>(m->data.data),
1926                            m->data.size, m->extend.data);
1927     return SUCCESS;
1928 }
1929 
1930 uint32_t ExtDecoder::UpdateHardWareDecodeInfo(DecodeContext &context)
1931 {
1932     if (context.pixelsBuffer.context == nullptr) {
1933         return ERR_IMAGE_PROPERTY_NOT_EXIST;
1934     }
1935     SurfaceBuffer* sbuffer = static_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
1936     if (sbuffer && sbuffer->GetFormat() != GRAPHIC_PIXEL_FMT_RGBA_8888) {
1937         OH_NativeBuffer_Planes *planes = nullptr;
1938         GSError retVal = sbuffer->GetPlanesInfo(reinterpret_cast<void**>(&planes));
1939         if (retVal != OHOS::GSERROR_OK || planes == nullptr) {
1940             IMAGE_LOGI("jpeg hardware decode, Get planesInfo failed, retVal:%{public}d", retVal);
1941         } else if (planes->planeCount >= PLANE_COUNT_TWO) {
1942             context.yuvInfo.yStride = planes->planes[0].columnStride;
1943             context.yuvInfo.uvStride = planes->planes[1].columnStride;
1944             context.yuvInfo.yOffset = planes->planes[0].offset;
1945             context.yuvInfo.uvOffset = planes->planes[1].offset - 1;
1946             context.yuvInfo.uvWidth = static_cast<uint32_t>((hwDstInfo_.width() + 1) / NUM_2);
1947             context.yuvInfo.uvHeight = static_cast<uint32_t>((hwDstInfo_.height() + 1) / NUM_2);
1948         }
1949     }
1950     context.outInfo.size.width = hwDstInfo_.width();
1951     context.outInfo.size.height = hwDstInfo_.height();
1952     if (outputColorFmt_ == V1_2::PIXEL_FMT_YCRCB_420_SP) {
1953         context.yuvInfo.imageSize = {hwDstInfo_.width(), hwDstInfo_.height()};
1954     }
1955 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1956     if (sbuffer && (sbuffer->GetUsage() & BUFFER_USAGE_MEM_MMZ_CACHE)) {
1957         GSError err = sbuffer->InvalidateCache();
1958         if (err != GSERROR_OK) {
1959             IMAGE_LOGE("InvalidateCache failed, GSError=%{public}d", err);
1960         }
1961         return ERR_IMAGE_PROPERTY_NOT_EXIST;
1962     }
1963 #endif
1964     return SUCCESS;
1965 }
1966 
1967 uint32_t ExtDecoder::HardWareDecode(DecodeContext &context)
1968 {
1969     orgImgSize_.width = info_.width();
1970     orgImgSize_.height = info_.height();
1971     if (!CheckContext(context)) {
1972         return ERROR;
1973     }
1974     Media::AllocatorType tmpAllocatorType = context.allocatorType;
1975     OHOS::HDI::Codec::Image::V2_1::CodecImageBuffer outputBuffer;
1976     uint32_t ret = AllocOutputBuffer(context, outputBuffer);
1977     if (ret != SUCCESS) {
1978         IMAGE_LOGE("Decode failed, Alloc OutputBuffer failed, ret=%{public}d", ret);
1979         context.hardDecodeError = "Decode failed, Alloc OutputBuffer failed, ret=" + std::to_string(ret);
1980         return ERR_IMAGE_DECODE_ABNORMAL;
1981     }
1982     if (hwDecoderPtr_ == nullptr) {
1983         hwDecoderPtr_ = std::make_shared<JpegHardwareDecoder>();
1984         if (!hwDecoderPtr_->InitDecoder()) {
1985             IMAGE_LOGE("failed to init jpeg hardware decoder");
1986             context.hardDecodeError = "failed to init jpeg hardware decoder";
1987             ReleaseOutputBuffer(context, tmpAllocatorType);
1988             return ERR_IMAGE_DECODE_ABNORMAL;
1989         }
1990     }
1991     ret = hwDecoderPtr_->Decode(codec_.get(), stream_, orgImgSize_, sampleSize_, outputBuffer);
1992     if (ret != SUCCESS) {
1993         IMAGE_LOGE("failed to do jpeg hardware decode, err=%{public}d", ret);
1994         context.hardDecodeError = "failed to do jpeg hardware decode, err=" + std::to_string(ret);
1995         ReleaseOutputBuffer(context, tmpAllocatorType);
1996         return ERR_IMAGE_DECODE_ABNORMAL;
1997     }
1998     if (srcColorSpace_ != nullptr && dstColorSpace_ != nullptr &&
1999         srcColorSpace_->GetColorSpaceName()!= dstColorSpace_->GetColorSpaceName()) {
2000         ret = ApplyDesiredColorSpace(context);
2001         if (ret != SUCCESS) {
2002             IMAGE_LOGE("failed to hardware decode ApplyDesiredColorSpace, err=%{public}d", ret);
2003             ReleaseOutputBuffer(context, tmpAllocatorType);
2004             return ERR_IMAGE_DECODE_ABNORMAL;
2005         }
2006     }
2007     ret = UpdateHardWareDecodeInfo(context);
2008     if (ret != SUCCESS) {
2009         IMAGE_LOGE("failed to UpdateHardWareDecodeInfo when hardware decode, err=%{public}d", ret);
2010         ReleaseOutputBuffer(context, tmpAllocatorType);
2011         return ERR_IMAGE_DECODE_ABNORMAL;
2012     }
2013     return SUCCESS;
2014 }
2015 #endif
2016 
2017 uint32_t ExtDecoder::HandleGifCache(uint8_t* src, uint8_t* dst, uint64_t rowStride, int dstHeight)
2018 {
2019     if (src == nullptr || dst == nullptr) {
2020         return ERR_IMAGE_DECODE_ABNORMAL;
2021     }
2022     uint8_t* srcRow = src;
2023     uint8_t* dstRow = dst;
2024     for (int i = 0; i < dstHeight; i++) {
2025         errno_t err = memcpy_s(dstRow, rowStride, srcRow, rowStride);
2026         CHECK_ERROR_RETURN_RET_LOG(err != EOK, ERR_IMAGE_DECODE_ABNORMAL,
2027             "handle gif memcpy failed. errno:%{public}d", err);
2028         if (i != (dstHeight - 1)) {
2029             srcRow += rowStride;
2030             dstRow += rowStride;
2031         }
2032     }
2033     return SUCCESS;
2034 }
2035 
2036 ExtDecoder::FrameCacheInfo ExtDecoder::InitFrameCacheInfo(const uint64_t rowStride, SkImageInfo info)
2037 {
2038     FrameCacheInfo cacheInfo = {0, 0, 0, 0};
2039     int width = info.width();
2040     int height = info.height();
2041     bool cond = width < 0 || height < 0;
2042     CHECK_ERROR_RETURN_RET_LOG(cond, cacheInfo,
2043                                "InitFrameCacheInfo failed, width:[%{public}d<0], height:[%{public}d<0]",
2044                                width, height);
2045     cacheInfo.width = width;
2046     cacheInfo.height = height;
2047     cacheInfo.rowStride = rowStride;
2048     cacheInfo.byteCount = rowStride * static_cast<uint64_t>(cacheInfo.height);
2049     return cacheInfo;
2050 }
2051 
2052 bool ExtDecoder::FrameCacheInfoIsEqual(ExtDecoder::FrameCacheInfo& src, ExtDecoder::FrameCacheInfo& dst)
2053 {
2054     bool cond = src.byteCount == 0 || src.rowStride == 0 || src.height == 0 || src.width == 0;
2055     CHECK_ERROR_RETURN_RET_LOG(cond, false, "FrameCacheInfoIsEqual, incorrect info");
2056     return (src.byteCount == dst.byteCount) && (src.rowStride == dst.rowStride) &&
2057         (src.height == dst.height) && (src.width == dst.width);
2058 }
2059 
2060 uint32_t ExtDecoder::GetFramePixels(SkImageInfo& info, uint8_t* buffer, uint64_t rowStride, SkCodec::Options options)
2061 {
2062     bool cond = buffer == nullptr;
2063     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_DECODE_ABNORMAL, "get pixels failed, buffer is nullptr");
2064     SkCodec::Result ret = codec_->getPixels(info, buffer, rowStride, &options);
2065     if (ret == SkCodec::kIncompleteInput || ret == SkCodec::kErrorInInput) {
2066         IMAGE_LOGI("Decode broken data success. Triggered kIncompleteInput feature of skia!");
2067         return SUCCESS;
2068     } else if (ret == SkCodec::kSuccess) {
2069         return SUCCESS;
2070     }
2071     // Try again
2072     ResetCodec();
2073     ret = codec_->getPixels(info, buffer, rowStride, &options);
2074     cond = (ret != SkCodec::kSuccess && ret != SkCodec::kIncompleteInput && ret != SkCodec::kErrorInInput);
2075     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_DECODE_ABNORMAL,
2076                                "Gif decode failed, get pixels failed, ret=%{public}d", ret);
2077     return SUCCESS;
2078 }
2079 
2080 uint32_t ExtDecoder::GifDecode(uint32_t index, DecodeContext &context, const uint64_t rowStride)
2081 {
2082     IMAGE_LOGD("In GifDecoder, frame index %{public}d", index);
2083     SkCodec::FrameInfo curInfo {};
2084     int signedIndex = static_cast<int>(index);
2085     codec_->getFrameInfo(signedIndex, &curInfo);
2086     if (signedIndex == 0 || gifCache_ == nullptr) {
2087         dstOptions_.fPriorFrame = SkCodec::kNoFrame;
2088     } else {
2089         int preIndex = signedIndex - 1;
2090         SkCodec::FrameInfo preInfo {};
2091         codec_->getFrameInfo(preIndex, &preInfo);
2092         if (preInfo.fDisposalMethod == SkCodecAnimation::DisposalMethod::kRestorePrevious) {
2093             dstOptions_.fPriorFrame = gifCacheIndex_;
2094         } else {
2095             dstOptions_.fPriorFrame = gifCacheIndex_ == preIndex ? preIndex : SkCodec::kNoFrame;
2096         }
2097     }
2098     ExtDecoder::FrameCacheInfo dstFrameCacheInfo = InitFrameCacheInfo(rowStride, dstInfo_);
2099     uint8_t* dstBuffer = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
2100     if (curInfo.fDisposalMethod != SkCodecAnimation::DisposalMethod::kRestorePrevious) {
2101         if (gifCache_ == nullptr) {
2102             frameCacheInfo_ = InitFrameCacheInfo(rowStride, dstInfo_);
2103             uint64_t memorySize = frameCacheInfo_.byteCount;
2104             bool cond = memorySize == 0 || memorySize >= MALLOC_LIMIT;
2105             CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_DECODE_ABNORMAL,
2106                 "%{public}s memorySize invalid: %{public}llu", __func__,
2107                 static_cast<unsigned long long>(memorySize));
2108             gifCache_ = static_cast<uint8_t *>(calloc(frameCacheInfo_.byteCount, 1));
2109         }
2110         bool cond = !FrameCacheInfoIsEqual(frameCacheInfo_, dstFrameCacheInfo);
2111         CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_DECODE_ABNORMAL, "Frame info is not equal");
2112         uint32_t ret = GetFramePixels(dstInfo_, gifCache_, rowStride, dstOptions_);
2113         cond = ret != SUCCESS;
2114         CHECK_ERROR_RETURN_RET(cond, ret);
2115         gifCacheIndex_ = signedIndex;
2116         return HandleGifCache(gifCache_, dstBuffer, dstFrameCacheInfo.rowStride, dstFrameCacheInfo.height);
2117     }
2118     if (gifCache_ != nullptr && FrameCacheInfoIsEqual(frameCacheInfo_, dstFrameCacheInfo)) {
2119         HandleGifCache(gifCache_, dstBuffer, dstFrameCacheInfo.rowStride, dstFrameCacheInfo.height);
2120     } else {
2121         dstOptions_.fPriorFrame = SkCodec::kNoFrame;
2122     }
2123     return GetFramePixels(dstInfo_, dstBuffer, rowStride, dstOptions_);
2124 }
2125 
2126 uint32_t ExtDecoder::PromoteIncrementalDecode(uint32_t index, ProgDecodeContext &context)
2127 {
2128     // currently not support increment decode
2129     return ERR_IMAGE_DATA_UNSUPPORT;
2130 }
2131 
2132 bool ExtDecoder::CheckCodec()
2133 {
2134     if (codec_ != nullptr) {
2135         return true;
2136     } else if (stream_ == nullptr) {
2137         IMAGE_LOGE("create codec: input stream is nullptr.");
2138         return false;
2139     } else if (stream_->GetStreamSize() == SIZE_ZERO) {
2140         IMAGE_LOGD("create codec: input stream size is zero.");
2141         return false;
2142     }
2143     uint32_t src_offset = stream_->Tell();
2144 #ifdef USE_M133_SKIA
2145     codec_ = SkCodec::MakeFromStream(make_unique<ExtStream>(stream_), nullptr, nullptr,
2146         SkCodec::SelectionPolicy::kPreferAnimation);
2147 #else
2148     codec_ = SkCodec::MakeFromStream(make_unique<ExtStream>(stream_));
2149 #endif
2150     if (codec_ == nullptr) {
2151         stream_->Seek(src_offset);
2152         IMAGE_LOGD("create codec from stream failed");
2153         SetHeifParseError();
2154         return false;
2155     }
2156     return codec_ != nullptr;
2157 }
2158 
2159 bool ExtDecoder::DecodeHeader()
2160 {
2161     if (!CheckCodec()) {
2162         IMAGE_LOGD("DecodeHeader Check codec failed");
2163         return false;
2164     }
2165     info_ = codec_->getInfo();
2166     frameCount_ = codec_->getFrameCount();
2167     IMAGE_LOGD("DecodeHeader: get frame count %{public}d.", frameCount_);
2168     return true;
2169 }
2170 
2171 bool ExtDecoder::CheckIndexValied(uint32_t index)
2172 {
2173     if (frameCount_ == ZERO && !DecodeHeader()) {
2174         return false;
2175     }
2176     return static_cast<int32_t>(index) >= ZERO && static_cast<int32_t>(index) < frameCount_;
2177 }
2178 
2179 static uint32_t GetFormatName(SkEncodedImageFormat format, std::string &name)
2180 {
2181     auto formatNameIter = FORMAT_NAME.find(format);
2182     if (formatNameIter != FORMAT_NAME.end() && !formatNameIter->second.empty()) {
2183         name = formatNameIter->second;
2184         if (name == IMAGE_HEIF_FORMAT && ImageUtils::GetAPIVersion() > APIVERSION_13) {
2185             name = IMAGE_HEIC_FORMAT;
2186         }
2187         if (format == SkEncodedImageFormat::kWBMP && ImageUtils::GetAPIVersion() >= APIVERSION_20) {
2188             name = IMAGE_WBMP_FORMAT;
2189         }
2190         if (format == SkEncodedImageFormat::kICO && ImageUtils::GetAPIVersion() >= APIVERSION_20) {
2191             name = IMAGE_ICON_FORMAT;
2192         }
2193         IMAGE_LOGD("GetFormatName: get encoded format name (%{public}d)=>[%{public}s].",
2194             format, name.c_str());
2195         return SUCCESS;
2196     }
2197     IMAGE_LOGE("GetFormatName: get encoded format name failed %{public}d.", format);
2198     return ERR_IMAGE_DATA_UNSUPPORT;
2199 }
2200 
2201 bool ExtDecoder::ConvertInfoToAlphaType(SkAlphaType &alphaType, AlphaType &outputType)
2202 {
2203     if (info_.isEmpty()) {
2204         return false;
2205     }
2206     alphaType = info_.alphaType();
2207     auto findItem = std::find_if(ALPHA_TYPE_MAP.begin(), ALPHA_TYPE_MAP.end(),
2208         [alphaType](const map<AlphaType, SkAlphaType>::value_type item) {
2209         return item.second == alphaType;
2210     });
2211     if (findItem == ALPHA_TYPE_MAP.end()) {
2212         return false;
2213     }
2214     outputType = findItem->first;
2215     alphaType = findItem->second;
2216     return true;
2217 }
2218 
2219 bool ExtDecoder::ConvertInfoToColorType(SkColorType &format, PixelFormat &outputFormat)
2220 {
2221     if (info_.isEmpty()) {
2222         return false;
2223     }
2224     auto colorType = info_.colorType();
2225     auto findItem = std::find_if(COLOR_TYPE_MAP.begin(), COLOR_TYPE_MAP.end(),
2226         [colorType](const map<PixelFormat, ColorTypeOutput>::value_type item) {
2227         return item.second.skFormat == colorType;
2228     });
2229     if (findItem == COLOR_TYPE_MAP.end()) {
2230         return false;
2231     }
2232     format = findItem->second.skFormat;
2233     outputFormat = findItem->second.outFormat;
2234     return true;
2235 }
2236 
2237 SkAlphaType ExtDecoder::ConvertToAlphaType(AlphaType desiredType, AlphaType &outputType)
2238 {
2239     if (desiredType != AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) {
2240         auto alphaType = ALPHA_TYPE_MAP.find(desiredType);
2241         if (alphaType != ALPHA_TYPE_MAP.end()) {
2242             outputType = alphaType->first;
2243             return alphaType->second;
2244         }
2245     }
2246     IMAGE_LOGD("Unknown alpha type:%{public}d", desiredType);
2247     SkAlphaType res;
2248     if (ConvertInfoToAlphaType(res, outputType)) {
2249         IMAGE_LOGD("Using alpha type:%{public}d", outputType);
2250         return res;
2251     }
2252     IMAGE_LOGD("Using default alpha type:%{public}d", AlphaType::IMAGE_ALPHA_TYPE_PREMUL);
2253     outputType = AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
2254     return SkAlphaType::kPremul_SkAlphaType;
2255 }
2256 
2257 SkColorType ExtDecoder::ConvertToColorType(PixelFormat format, PixelFormat &outputFormat)
2258 {
2259     if (format != PixelFormat::UNKNOWN) {
2260         auto colorType = COLOR_TYPE_MAP.find(format);
2261         if (colorType != COLOR_TYPE_MAP.end()) {
2262             outputFormat = colorType->second.outFormat;
2263             return colorType->second.skFormat;
2264         }
2265     }
2266     IMAGE_LOGD("Unknown pixel format:%{public}d", format);
2267     SkColorType res;
2268     if (ConvertInfoToColorType(res, outputFormat)) {
2269         IMAGE_LOGD("Using pixel format:%{public}d", outputFormat);
2270         return res;
2271     }
2272     IMAGE_LOGD("Using default pixel format:%{public}d", PixelFormat::RGBA_8888);
2273     outputFormat = PixelFormat::RGBA_8888;
2274     return kRGBA_8888_SkColorType;
2275 }
2276 
2277 #ifdef IMAGE_COLORSPACE_FLAG
2278 static uint32_t u8ToU32(const uint8_t* p)
2279 {
2280     return (p[OFFSET_0] << SHIFT_BITS_24) | (p[OFFSET_1] << SHIFT_BITS_16) |
2281         (p[OFFSET_2] << SHIFT_BITS_8) | p[OFFSET_3];
2282 }
2283 
2284 struct ICCTag {
2285     uint8_t signature[SIZE_4];
2286     uint8_t offset[SIZE_4];
2287     uint8_t size[SIZE_4];
2288 };
2289 
2290 struct ColorSpaceNameEnum {
2291     std::string desc;
2292     OHOS::ColorManager::ColorSpaceName name;
2293 };
2294 
2295 static std::vector<ColorSpaceNameEnum> sColorSpaceNamedMap = {
2296     {"Display P3", OHOS::ColorManager::ColorSpaceName::DISPLAY_P3},
2297     {"sRGB EOTF with DCI-P3 Color Gamut", OHOS::ColorManager::ColorSpaceName::DISPLAY_P3},
2298     {"DCI-P3 D65 Gamut with sRGB Transfer", OHOS::ColorManager::ColorSpaceName::DISPLAY_P3},
2299     {"Adobe RGB (1998)", OHOS::ColorManager::ColorSpaceName::ADOBE_RGB},
2300     {"DCI P3", OHOS::ColorManager::ColorSpaceName::DCI_P3},
2301     {"sRGB", OHOS::ColorManager::ColorSpaceName::SRGB},
2302     {"BT.2020", OHOS::ColorManager::ColorSpaceName::BT2020},
2303     {"Rec2020 Gamut with HLG Transfer", OHOS::ColorManager::ColorSpaceName::BT2020_HLG}
2304 };
2305 
2306 static bool MatchColorSpaceName(const uint8_t* buf, uint32_t size, OHOS::ColorManager::ColorSpaceName &name)
2307 {
2308     bool cond = buf == nullptr || size <= OFFSET_5;
2309     CHECK_ERROR_RETURN_RET(cond, false);
2310     std::vector<char> desc;
2311     // We need skip desc type
2312     for (uint32_t i = OFFSET_5; i < size; i++) {
2313         if (buf[i] != '\0') {
2314             desc.push_back(buf[i]);
2315         }
2316     }
2317     cond = desc.size() <= SIZE_1;
2318     CHECK_INFO_RETURN_RET_LOG(cond, false, "empty buffer");
2319     std::string descText(desc.begin() + OFFSET_1, desc.end());
2320     for (auto nameEnum : sColorSpaceNamedMap) {
2321         if (descText.find(nameEnum.desc) == std::string::npos) {
2322             continue;
2323         }
2324         name = nameEnum.name;
2325         return true;
2326     }
2327     IMAGE_LOGE("Failed to match desc");
2328     return false;
2329 }
2330 
2331 static bool GetColorSpaceName(const skcms_ICCProfile* profile, OHOS::ColorManager::ColorSpaceName &name)
2332 {
2333     if (profile == nullptr || profile->buffer == nullptr) {
2334         IMAGE_LOGD("profile is nullptr");
2335         return false;
2336     }
2337     auto tags = reinterpret_cast<const ICCTag*>(profile->buffer + ICC_HEADER_SIZE);
2338     for (uint32_t i = SIZE_ZERO; i < profile->tag_count; i++) {
2339         auto signature = u8ToU32(tags[i].signature);
2340         if (signature != DESC_SIGNATURE) {
2341             continue;
2342         }
2343         auto size = u8ToU32(tags[i].size);
2344         auto offset = u8ToU32(tags[i].offset);
2345         if (size == SIZE_ZERO || offset >= profile->size) {
2346             continue;
2347         }
2348         auto buffer = u8ToU32(tags[i].offset) + profile->buffer;
2349         if (MatchColorSpaceName(buffer, size, name)) {
2350             return true;
2351         }
2352     }
2353     return false;
2354 }
2355 
2356 static OHOS::ColorManager::ColorSpaceName GetHeifNclxColor(SkCodec* codec)
2357 {
2358 #ifdef HEIF_HW_DECODE_ENABLE
2359     auto decoder = reinterpret_cast<HeifDecoder *>(codec->getHeifContext());
2360     if (decoder == nullptr) {
2361         return ColorManager::NONE;
2362     }
2363     HeifFrameInfo info;
2364     if (!decoder->getImageInfo(&info)) {
2365         return ColorManager::NONE;
2366     }
2367     if (info.hasNclxColor) {
2368         return ColorUtils::CicpToColorSpace(info.nclxColor.colorPrimaries, info.nclxColor.transferCharacteristics,
2369             info.nclxColor.matrixCoefficients, info.nclxColor.fullRangeFlag);
2370     }
2371 #endif
2372     return ColorManager::NONE;
2373 }
2374 
2375 OHOS::ColorManager::ColorSpace ExtDecoder::GetSrcColorSpace()
2376 {
2377     auto skColorSpace = info_.refColorSpace();
2378     OHOS::ColorManager::ColorSpaceName name = OHOS::ColorManager::ColorSpaceName::CUSTOM;
2379     if (codec_ != nullptr) {
2380         auto profile = codec_->getICCProfile();
2381         if (profile != nullptr) {
2382             IMAGE_LOGD("profile got !!!!");
2383             GetColorSpaceName(profile, name);
2384         }
2385         if (profile != nullptr && profile->has_CICP) {
2386 #ifdef USE_M133_SKIA
2387             ColorManager::ColorSpaceName cName = Media::ColorUtils::CicpToColorSpace(profile->CICP.color_primaries,
2388                 profile->CICP.transfer_characteristics, profile->CICP.matrix_coefficients,
2389                 profile->CICP.video_full_range_flag);
2390 #else
2391             ColorManager::ColorSpaceName cName = Media::ColorUtils::CicpToColorSpace(profile->cicp.colour_primaries,
2392                 profile->cicp.transfer_characteristics, profile->cicp.matrix_coefficients,
2393                 profile->cicp.full_range_flag);
2394 #endif
2395             if (cName != ColorManager::NONE) {
2396                 heifColorSpaceName_ = cName;
2397                 heifIsColorSpaceFromCicp_ = true;
2398                 IMAGE_LOGI("%{public}s profile has CICP, cName: %{public}u", __func__, static_cast<uint32_t>(cName));
2399                 return ColorManager::ColorSpace(cName);
2400             }
2401         }
2402         if (codec_->getEncodedFormat() == SkEncodedImageFormat::kHEIF) {
2403             ColorManager::ColorSpaceName cName = GetHeifNclxColor(codec_.get());
2404             if (cName != ColorManager::NONE) {
2405                 heifColorSpaceName_ = cName;
2406                 IMAGE_LOGI("%{public}s profile has HEIF NCLX color, cName: %{public}u",
2407                     __func__, static_cast<uint32_t>(cName));
2408                 return ColorManager::ColorSpace(cName);
2409             }
2410         }
2411     }
2412     // use info_ to make a custom graphic colorspace.
2413     if (name == OHOS::ColorManager::ColorSpaceName::CUSTOM ||
2414         name == OHOS::ColorManager::ColorSpaceName::NONE) {
2415         IMAGE_LOGD("%{public}s Use info_ to make a custom graphic colorspace. name: %{public}u",
2416             __func__, static_cast<uint32_t>(name));
2417         return OHOS::ColorManager::ColorSpace(skColorSpace, name);
2418     }
2419     IMAGE_LOGD("%{public}s Use name to make a custom graphic colorspace. name: %{public}u",
2420         __func__, static_cast<uint32_t>(name));
2421     heifColorSpaceName_ = name;
2422     return OHOS::ColorManager::ColorSpace(name);
2423 }
2424 
2425 // get graphic ColorSpace and set to pixelMap
2426 OHOS::ColorManager::ColorSpace ExtDecoder::GetPixelMapColorSpace()
2427 {
2428     if (dstColorSpace_ != nullptr) {
2429         if (srcColorSpace_ == nullptr) {
2430             auto colorSpace = GetSrcColorSpace();
2431             srcColorSpace_ = std::make_shared<OHOS::ColorManager::ColorSpace>(colorSpace);
2432         }
2433         return *dstColorSpace_;
2434     }
2435     return GetSrcColorSpace();
2436 }
2437 
2438 bool ExtDecoder::IsSupportICCProfile()
2439 {
2440     bool cond = dstColorSpace_ != nullptr;
2441     CHECK_ERROR_RETURN_RET(cond, true);
2442     cond = info_.isEmpty();
2443     CHECK_ERROR_RETURN_RET(cond, false);
2444     return info_.refColorSpace() != nullptr;
2445 }
2446 #endif
2447 
2448 static uint32_t ProcessWithStreamData(InputDataStream *input,
2449     std::function<uint32_t(uint8_t*, size_t)> process)
2450 {
2451     size_t inputSize = input->GetStreamSize();
2452     bool cond = inputSize == SIZE_ZERO;
2453     CHECK_ERROR_RETURN_RET(cond, Media::ERR_MEDIA_INVALID_VALUE);
2454 
2455     size_t copySize = std::min(inputSize, SMALL_FILE_SIZE);
2456     auto tmpBuffer = std::make_unique<uint8_t[]>(copySize);
2457     auto savePos = input->Tell();
2458     input->Seek(SIZE_ZERO);
2459     uint32_t readSize = 0;
2460     bool ret = input->Read(copySize, tmpBuffer.get(), copySize, readSize);
2461     input->Seek(savePos);
2462     cond = !ret;
2463     CHECK_ERROR_RETURN_RET_LOG(cond, Media::ERR_IMAGE_DATA_ABNORMAL, "InputDataStream read failed.");
2464     return process(tmpBuffer.get(), copySize);
2465 }
2466 
2467 static bool ParseExifData(InputDataStream *input, EXIFInfo &info)
2468 {
2469     if (info.IsExifDataParsed()) {
2470         return true;
2471     }
2472     IMAGE_LOGD("ParseExifData enter");
2473     auto code = ProcessWithStreamData(input, [&info](uint8_t* buffer, size_t size) {
2474         return info.ParseExifData(buffer, size);
2475     });
2476     bool cond = code != SUCCESS;
2477     CHECK_ERROR_PRINT_LOG(cond, "Error parsing EXIF: code %{public}d", code);
2478     return code == SUCCESS;
2479 }
2480 
2481 bool ExtDecoder::GetPropertyCheck(uint32_t index, const std::string &key, uint32_t &res)
2482 {
2483     if (IsSameTextStr(key, ACTUAL_IMAGE_ENCODED_FORMAT)) {
2484         res = Media::ERR_MEDIA_VALUE_INVALID;
2485         return false;
2486     }
2487     if (!CheckIndexValied(index)) {
2488         res = Media::ERR_IMAGE_DECODE_HEAD_ABNORMAL;
2489         return false;
2490     }
2491     SkEncodedImageFormat format = codec_->getEncodedFormat();
2492     if (format != SkEncodedImageFormat::kJPEG) {
2493         res = Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
2494         return true;
2495     }
2496     if (ENCODED_FORMAT_KEY.compare(key) == ZERO) {
2497         res = Media::ERR_MEDIA_VALUE_INVALID;
2498         return true;
2499     }
2500     auto result = ParseExifData(stream_, exifInfo_);
2501     if (!result) {
2502         res = Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
2503     }
2504     return result;
2505 }
2506 
2507 static uint32_t GetDelayTime(SkCodec * codec, uint32_t index, int32_t &value)
2508 {
2509     if (codec->getEncodedFormat() != SkEncodedImageFormat::kGIF &&
2510         codec->getEncodedFormat() != SkEncodedImageFormat::kWEBP) {
2511         IMAGE_LOGE("[GetDelayTime] Should not get delay time in %{public}d", codec->getEncodedFormat());
2512         return ERR_MEDIA_INVALID_PARAM;
2513     }
2514     auto frameInfos = codec->getFrameInfo();
2515     CHECK_ERROR_RETURN_RET_LOG(index >= frameInfos.size(), ERR_MEDIA_INVALID_PARAM,
2516         "[GetDelayTime] frame size %{public}zu, index:%{public}d", frameInfos.size(), index);
2517     value = frameInfos[index].fDuration;
2518     IMAGE_LOGD("[GetDelayTime] index[%{public}d]:%{public}d", index, value);
2519     return SUCCESS;
2520 }
2521 
2522 static uint32_t GetDisposalType(SkCodec * codec, uint32_t index, int32_t &value)
2523 {
2524     if (codec->getEncodedFormat() != SkEncodedImageFormat::kGIF) {
2525         IMAGE_LOGE("[GetDisposalType] Should not get disposal type in %{public}d", codec->getEncodedFormat());
2526         return ERR_MEDIA_INVALID_PARAM;
2527     }
2528     auto frameInfos = codec->getFrameInfo();
2529     CHECK_ERROR_RETURN_RET_LOG(index >= frameInfos.size(), ERR_MEDIA_INVALID_PARAM,
2530         "[GetDisposalType] frame size %{public}zu, index:%{public}d", frameInfos.size(), index);
2531     value = static_cast<int>(frameInfos[index].fDisposalMethod);
2532     IMAGE_LOGD("[GetDisposalType] index[%{public}d]:%{public}d", index, value);
2533     return SUCCESS;
2534 }
2535 
2536 static uint32_t GetLoopCount(SkCodec *codec, int32_t &value)
2537 {
2538     if (codec->getEncodedFormat() != SkEncodedImageFormat::kGIF) {
2539         IMAGE_LOGE("[GetLoopCount] Should not get loop count in %{public}d", codec->getEncodedFormat());
2540         return ERR_MEDIA_INVALID_PARAM;
2541     }
2542     auto count = codec->getRepetitionCount();
2543     bool cond = count == LOOP_COUNT_INFINITE || count <= SK_REPETITION_COUNT_ERROR_VALUE;
2544     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_SOURCE_DATA, "[GetLoopCount] getRepetitionCount error");
2545     if (count == SK_REPETITION_COUNT_INFINITE) {
2546         count = LOOP_COUNT_INFINITE;
2547     }
2548     value = static_cast<int>(count);
2549     return SUCCESS;
2550 }
2551 
2552 uint32_t ExtDecoder::GetImagePropertyInt(uint32_t index, const std::string &key, int32_t &value)
2553 {
2554     IMAGE_LOGD("[GetImagePropertyInt] enter ExtDecoder plugin, key:%{public}s", key.c_str());
2555     uint32_t res = Media::ERR_IMAGE_DATA_ABNORMAL;
2556     if (!GetPropertyCheck(index, key, res)) {
2557         return res;
2558     }
2559     if (IMAGE_DELAY_TIME.compare(key) == ZERO) {
2560         return GetDelayTime(codec_.get(), index, value);
2561     }
2562     if (IMAGE_DISPOSAL_TYPE.compare(key) == ZERO) {
2563         return GetDisposalType(codec_.get(), index, value);
2564     }
2565     if (IMAGE_LOOP_COUNT.compare(key) == ZERO) {
2566         return GetLoopCount(codec_.get(), value);
2567     }
2568     // There can add some not need exif property
2569     if (res == Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT) {
2570         return res;
2571     }
2572     // Need exif property following
2573     if (IsSameTextStr(key, TAG_ORIENTATION_STRING)) {
2574         std::string strValue;
2575         res = exifInfo_.GetExifData(TAG_ORIENTATION_INT, strValue);
2576         if (res != SUCCESS) {
2577             return res;
2578         }
2579         value = atoi(strValue.c_str());
2580         return res;
2581     }
2582     IMAGE_LOGE("[GetImagePropertyInt] The key:%{public}s is not supported int32_t", key.c_str());
2583     return Media::ERR_MEDIA_VALUE_INVALID;
2584 }
2585 
2586 bool ExtDecoder::IsRawFormat(std::string &name)
2587 {
2588     CHECK_ERROR_RETURN_RET(stream_ == nullptr, false);
2589     ImagePlugin::DataStreamBuffer outData;
2590     uint32_t savedPosition = stream_->Tell();
2591     stream_->Seek(0);
2592     if (!stream_->Peek(RAW_MIN_BYTEREAD, outData)) {
2593         IMAGE_LOGE("IsRawFormat peek data fail.");
2594         stream_->Seek(savedPosition);
2595         return false;
2596     } else {
2597         stream_->Seek(savedPosition);
2598         piex::binary_parse::RangeCheckedBytePtr header_buffer(outData.inputStreamBuffer, outData.dataSize);
2599         piex::image_type_recognition::RawImageTypes type = RecognizeRawImageTypeLite(header_buffer);
2600         auto rawFormatNameIter = RAW_FORMAT_NAME.find(type);
2601         if (rawFormatNameIter != RAW_FORMAT_NAME.end() && !rawFormatNameIter->second.empty()) {
2602             name = rawFormatNameIter->second;
2603             return true;
2604         }
2605     }
2606     return false;
2607 }
2608 
2609 OHOS::Media::Size ExtDecoder::GetHeifGridTileSize()
2610 {
2611 #ifdef HEIF_HW_DECODE_ENABLE
2612     if (codec_ == nullptr || codec_->getEncodedFormat() != SkEncodedImageFormat::kHEIF) {
2613         return {0, 0};
2614     }
2615     auto heifContext = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
2616     if (heifContext == nullptr) {
2617         return {0, 0};
2618     }
2619     GridInfo gridInfo = heifContext->GetGridInfo();
2620     return {gridInfo.tileWidth, gridInfo.tileHeight};
2621 #else
2622     return {0, 0};
2623 #endif
2624 }
2625 
2626 uint32_t ExtDecoder::GetImagePropertyString(uint32_t index, const std::string &key, std::string &value)
2627 {
2628     IMAGE_LOGD("[GetImagePropertyString] enter jpeg plugin, key:%{public}s", key.c_str());
2629     uint32_t res = Media::ERR_IMAGE_DATA_ABNORMAL;
2630     if (!GetPropertyCheck(index, key, res)) {
2631         return res;
2632     }
2633     // There can add some not need exif property
2634     if (ENCODED_FORMAT_KEY.compare(key) == ZERO) {
2635         SkEncodedImageFormat format = codec_->getEncodedFormat();
2636         if ((format == SkEncodedImageFormat::kJPEG || format == SkEncodedImageFormat::kDNG) &&
2637             ImageUtils::GetAPIVersion() >= APIVERSION_20 && IsRawFormat(value)) {
2638             return SUCCESS;
2639         } else {
2640             return GetFormatName(format, value);
2641         }
2642     } else if (IMAGE_DELAY_TIME.compare(key) == ZERO) {
2643         int delayTime = ZERO;
2644         res = GetDelayTime(codec_.get(), index, delayTime);
2645         value = std::to_string(delayTime);
2646         return res;
2647     } else if (IMAGE_DISPOSAL_TYPE.compare(key) == ZERO) {
2648         int disposalType = ZERO;
2649         res = GetDisposalType(codec_.get(), index, disposalType);
2650         value = std::to_string(disposalType);
2651         return res;
2652     } else if (IMAGE_LOOP_COUNT.compare(key) == ZERO) {
2653         int loopCount = ZERO;
2654         res = GetLoopCount(codec_.get(), loopCount);
2655         value = std::to_string(loopCount);
2656         return res;
2657     }
2658     if (res == Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT) {
2659         return res;
2660     }
2661     // Need exif property following
2662     if (key.find(HW_MNOTE_TAG_HEADER) != std::string::npos) {
2663         res = GetMakerImagePropertyString(key, value);
2664         if (value.length() == 0) {
2665             value = DEFAULT_EXIF_VALUE;
2666             IMAGE_LOGE("[GetImagePropertyString]The image does not contain the %{public}s  tag ", key.c_str());
2667         }
2668         return res;
2669     }
2670     res = exifInfo_.GetExifData(key, value);
2671     IMAGE_LOGD("[GetImagePropertyString] enter jpeg plugin, value:%{public}s", value.c_str());
2672     return res;
2673 }
2674 
2675 uint32_t ExtDecoder::GetMakerImagePropertyString(const std::string &key, std::string &value)
2676 {
2677     if (exifInfo_.makerInfoTagValueMap.find(key) != exifInfo_.makerInfoTagValueMap.end()) {
2678         value = exifInfo_.makerInfoTagValueMap[key];
2679         return SUCCESS;
2680     }
2681     return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
2682 }
2683 
2684 uint32_t ExtDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
2685     const std::string &value, const std::string &path)
2686 {
2687     IMAGE_LOGD("[ModifyImageProperty] with key:%{public}s", key.c_str());
2688     return exifInfo_.ModifyExifData(key, value, path);
2689 }
2690 
2691 uint32_t ExtDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
2692     const std::string &value, const int fd)
2693 {
2694     IMAGE_LOGD("[ModifyImageProperty] with fd:%{public}d, key:%{public}s, value:%{public}s",
2695         fd, key.c_str(), value.c_str());
2696     return exifInfo_.ModifyExifData(key, value, fd);
2697 }
2698 
2699 uint32_t ExtDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
2700     const std::string &value, uint8_t *data, uint32_t size)
2701 {
2702     IMAGE_LOGD("[ModifyImageProperty] with key:%{public}s, value:%{public}s",
2703         key.c_str(), value.c_str());
2704     return exifInfo_.ModifyExifData(key, value, data, size);
2705 }
2706 
2707 uint32_t ExtDecoder::GetFilterArea(const int &privacyType, std::vector<std::pair<uint32_t, uint32_t>> &ranges)
2708 {
2709     IMAGE_LOGD("[GetFilterArea] with privacyType:%{public}d ", privacyType);
2710     if (!CheckCodec()) {
2711         IMAGE_LOGD("[GetFilterArea] Check codec failed");
2712         return NO_EXIF_TAG;
2713     }
2714     SkEncodedImageFormat format = codec_->getEncodedFormat();
2715     if (format != SkEncodedImageFormat::kJPEG) {
2716         return NO_EXIF_TAG;
2717     }
2718     constexpr size_t APP1_SIZE_H_OFF = 4;
2719     constexpr size_t APP1_SIZE_L_OFF = 5;
2720     constexpr size_t U8_SHIFT = 8;
2721     return ProcessWithStreamData(stream_, [this, &privacyType, &ranges](uint8_t* buffer, size_t size) {
2722         size_t appSize = (static_cast<size_t>(buffer[APP1_SIZE_H_OFF]) << U8_SHIFT) | buffer[APP1_SIZE_L_OFF];
2723         IMAGE_LOGD("[GetFilterArea]: get app1 area size");
2724         appSize += APP1_SIZE_H_OFF;
2725         auto ret = exifInfo_.GetFilterArea(buffer, (appSize < size) ? appSize : size, privacyType, ranges);
2726         bool cond = (ret != SUCCESS);
2727         CHECK_ERROR_PRINT_LOG(cond, "[GetFilterArea]: failed to get area %{public}d", ret);
2728         return ret;
2729     });
2730 }
2731 
2732 uint32_t ExtDecoder::GetTopLevelImageNum(uint32_t &num)
2733 {
2734     if (!CheckIndexValied(SIZE_ZERO) && frameCount_ <= ZERO) {
2735         return ERR_IMAGE_DECODE_HEAD_ABNORMAL;
2736     }
2737     num = static_cast<uint32_t>(frameCount_);
2738     return SUCCESS;
2739 }
2740 
2741 bool ExtDecoder::IsSupportHardwareDecode() {
2742     if (info_.isEmpty() && !DecodeHeader()) {
2743         return false;
2744     }
2745     if (!(ImageSystemProperties::GetHardWareDecodeEnabled()
2746         && codec_->getEncodedFormat() == SkEncodedImageFormat::kJPEG)) {
2747         return false;
2748     }
2749     int width = info_.width();
2750     int height = info_.height();
2751     if (width >= HARDWARE_MIN_DIM && width <= HARDWARE_MAX_DIM
2752         && height >= HARDWARE_MIN_DIM && height <= HARDWARE_MAX_DIM) {
2753         if (width < HARDWARE_MID_DIM || height < HARDWARE_MID_DIM) {
2754             int remWidth = width % HARDWARE_ALIGN_SIZE;
2755             int remHeight = height % HARDWARE_ALIGN_SIZE;
2756             if (remWidth == 0 && remHeight == 0) {
2757                 return true;
2758             }
2759         } else {
2760             return true;
2761         }
2762     }
2763     return false;
2764 }
2765 
2766 bool ExtDecoder::IsYuv420Format(PixelFormat format) const
2767 {
2768     if (format == PixelFormat::NV12 || format == PixelFormat::NV21) {
2769         return true;
2770     }
2771     return false;
2772 }
2773 
2774 bool ExtDecoder::IsHeifToYuvDecode(const DecodeContext &context) const
2775 {
2776     return codec_->getEncodedFormat() == SkEncodedImageFormat::kHEIF && IsYuv420Format(context.info.pixelFormat);
2777 }
2778 
2779 uint32_t ExtDecoder::DoHeifToYuvDecode(OHOS::ImagePlugin::DecodeContext &context)
2780 {
2781 #ifdef HEIF_HW_DECODE_ENABLE
2782     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
2783     CHECK_ERROR_RETURN_RET_LOG(decoder == nullptr, ERR_IMAGE_DATA_UNSUPPORT, "YUV Decode HeifDecoder is nullptr");
2784     if (ImageUtils::IsSdrPixelMapReuseSuccess(context, info_.width(), info_.height(), reusePixelmap_)) {
2785         IMAGE_LOGI("DoHeifToYuvDecode reusePixelmap success");
2786     } else {
2787         uint32_t allocRet = HeifYUVMemAlloc(context, dstInfo_);
2788         CHECK_ERROR_RETURN_RET(allocRet != SUCCESS, allocRet);
2789     }
2790     auto dstBuffer = reinterpret_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
2791     decoder->setOutputColor(context.info.pixelFormat
2792         == PixelFormat::NV12 ? kHeifColorFormat_NV12 : kHeifColorFormat_NV21);
2793     if (IsHeifRegionDecode()) {
2794         decoder->SetDecodeRegion(heifGridRegionInfo_.colCount, heifGridRegionInfo_.rowCount,
2795             desiredRegion_.left, desiredRegion_.top, dstBuffer->GetStride());
2796     }
2797     decoder->SetSampleFormat(sampleSize_, heifColorSpaceName_, heifIsColorSpaceFromCicp_);
2798     decoder->setDstBuffer(reinterpret_cast<uint8_t *>(context.pixelsBuffer.buffer),
2799         dstBuffer->GetStride(), context.pixelsBuffer.context);
2800     bool decodeRet = decoder->decode(nullptr);
2801     if (!decodeRet && sampleSize_ != DEFAULT_SAMPLE_SIZE) {
2802         decodeRet = DoHeifSwDecode(context);
2803     }
2804     if (!decodeRet) {
2805         decoder->getErrMsg(context.hardDecodeError);
2806     }
2807     return decodeRet ? SUCCESS : ERR_IMAGE_DATA_UNSUPPORT;
2808 #else
2809     return ERR_IMAGE_DATA_UNSUPPORT;
2810 #endif
2811 }
2812 
2813 bool ExtDecoder::IsHeifToSingleHdrDecode(const DecodeContext& context) const
2814 {
2815     return codec_->getEncodedFormat() == SkEncodedImageFormat::kHEIF &&
2816         (context.info.pixelFormat == PixelFormat::RGBA_1010102 ||
2817          context.info.pixelFormat == PixelFormat::YCBCR_P010 ||
2818          context.info.pixelFormat == PixelFormat::YCRCB_P010);
2819 }
2820 
2821 uint32_t ExtDecoder::AllocHeifSingleHdrBuffer(DecodeContext &context)
2822 {
2823 #ifdef HEIF_HW_DECODE_ENABLE
2824     uint64_t byteCount = static_cast<uint64_t>(dstInfo_.computeMinByteSize());
2825     if (context.info.pixelFormat == PixelFormat::YCBCR_P010 || context.info.pixelFormat == PixelFormat::YCRCB_P010) {
2826         uint32_t allocRet = HeifYUVMemAlloc(context, dstInfo_);
2827         bool cond = allocRet != SUCCESS;
2828         CHECK_ERROR_RETURN_RET(cond, allocRet);
2829     } else {
2830         if (IsHeifRegionDecode()) {
2831             UpdateHeifRegionDstInfo(context);
2832             byteCount = dstInfo_.computeMinByteSize();
2833             IMAGE_LOGI("Do Heif Single Hdr Region Decode, xy [%{public}d , %{public}d], wh [%{public}d x %{public}d]",
2834                 desiredRegion_.left, desiredRegion_.top, desiredRegion_.width, desiredRegion_.height);
2835         }
2836         CHECK_ERROR_RETURN_RET_LOG(SkImageInfo::ByteSizeOverflowed(byteCount), ERR_IMAGE_TOO_LARGE,
2837             "%{public}s too large byteCount: %{public}llu", __func__, static_cast<unsigned long long>(byteCount));
2838         bool cond = DmaMemAlloc(context, byteCount, dstInfo_) != SUCCESS;
2839         CHECK_ERROR_RETURN_RET(cond, ERR_IMAGE_DATA_UNSUPPORT);
2840     }
2841     return SUCCESS;
2842 #else
2843     return ERR_IMAGE_DATA_UNSUPPORT;
2844 #endif
2845 }
2846 
2847 uint32_t ExtDecoder::DoHeifToSingleHdrDecode(DecodeContext &context)
2848 {
2849 #ifdef HEIF_HW_DECODE_ENABLE
2850     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
2851     bool cond = decoder == nullptr;
2852     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_DATA_UNSUPPORT, "SingleHdrDecode, HeifDecoder is nullptr");
2853     uint32_t ret = AllocHeifSingleHdrBuffer(context);
2854     CHECK_ERROR_RETURN_RET_LOG(ret != SUCCESS, ret, "SingleHdrDecode, alloc dstBuffer failed");
2855     auto dstBuffer = reinterpret_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
2856     cond = dstBuffer == nullptr;
2857     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_DATA_UNSUPPORT, "SingleHdrDecode, dstBuffer is nullptr");
2858     SkHeifColorFormat heifFormat = kHeifColorFormat_RGBA_1010102;
2859     auto formatSearch = HEIF_FORMAT_MAP.find(context.info.pixelFormat);
2860     heifFormat = (formatSearch != HEIF_FORMAT_MAP.end()) ? formatSearch->second : kHeifColorFormat_RGBA_1010102;
2861     decoder->setOutputColor(heifFormat);
2862     if (IsHeifRegionDecode()) {
2863         decoder->SetDecodeRegion(heifGridRegionInfo_.colCount, heifGridRegionInfo_.rowCount,
2864             desiredRegion_.left, desiredRegion_.top, dstBuffer->GetStride());
2865     }
2866     decoder->SetSampleFormat(DEFAULT_SAMPLE_SIZE, heifColorSpaceName_, heifIsColorSpaceFromCicp_);
2867     decoder->setDstBuffer(reinterpret_cast<uint8_t*>(context.pixelsBuffer.buffer),
2868         dstBuffer->GetStride(), context.pixelsBuffer.context);
2869     bool decodeRet = decoder->decode(nullptr);
2870     if (!decodeRet) {
2871         decoder->getErrMsg(context.hardDecodeError);
2872     }
2873     return decodeRet ? SUCCESS : ERR_IMAGE_DATA_UNSUPPORT;
2874 #else
2875     return ERR_IMAGE_DATA_UNSUPPORT;
2876 #endif
2877 }
2878 
2879 ImageHdrType ExtDecoder::CheckHdrType()
2880 {
2881 #if defined(_WIN32) || defined(_APPLE) || defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
2882     return Media::ImageHdrType::SDR;
2883 #else
2884     if (!CheckCodec()) {
2885         return Media::ImageHdrType::UNKNOWN;
2886     }
2887     SkEncodedImageFormat format = codec_->getEncodedFormat();
2888     if (format != SkEncodedImageFormat::kJPEG && format != SkEncodedImageFormat::kHEIF) {
2889         hdrType_ = Media::ImageHdrType::SDR;
2890         gainMapOffset_ = 0;
2891         return hdrType_;
2892     }
2893     hdrType_ = HdrHelper::CheckHdrType(codec_.get(), gainMapOffset_);
2894     if (hdrType_ <= Media::ImageHdrType::SDR || format != SkEncodedImageFormat::kJPEG) {
2895         return hdrType_;
2896     }
2897     // Verify the legitimacy of the offset.
2898     if (!HdrHelper::CheckGainmapOffset(hdrType_, stream_, gainMapOffset_)) {
2899         return Media::ImageHdrType::SDR;
2900     }
2901     return hdrType_;
2902 #endif
2903 }
2904 
2905 void ExtDecoder::ValidateAndCorrectMetaData(HdrMetadata& metadata)
2906 {
2907 #if !defined(CROSS_PLATFORM)
2908     HdrHelper::ValidateAndCorrectMetaData(metadata, hdrType_);
2909 #else
2910     return;
2911 #endif
2912 }
2913 
2914 uint32_t ExtDecoder::GetGainMapOffset()
2915 {
2916 #if defined(_WIN32) || defined(_APPLE) || defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
2917     return OFFSET_0;
2918 #else
2919     if (codec_ == nullptr || codec_->getEncodedFormat() != SkEncodedImageFormat::kJPEG) {
2920         return 0;
2921     }
2922     if (hdrType_ == Media::ImageHdrType::UNKNOWN) {
2923         hdrType_ = HdrHelper::CheckHdrType(codec_.get(), gainMapOffset_);
2924     }
2925     return gainMapOffset_;
2926 #endif
2927 }
2928 
2929 HdrMetadata ExtDecoder::GetHdrMetadata(Media::ImageHdrType type)
2930 {
2931 #if defined(_WIN32) || defined(_APPLE) || defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
2932     return {};
2933 #else
2934     HdrMetadata metadata = {};
2935     if (type > Media::ImageHdrType::SDR && HdrHelper::GetMetadata(codec_.get(), type, metadata)) {
2936         return metadata;
2937     }
2938     IMAGE_LOGD("get hdr metadata failed, type is %{public}d, flag is %{public}d", type, metadata.extendMetaFlag);
2939     return {};
2940 #endif
2941 }
2942 
2943 bool ExtDecoder::GetHeifFragmentMetadata(Media::Rect &metadata)
2944 {
2945 #ifdef HEIF_HW_DECODE_ENABLE
2946     bool cond = codec_ == nullptr || codec_->getEncodedFormat() != SkEncodedImageFormat::kHEIF;
2947     CHECK_ERROR_RETURN_RET_LOG(cond, false, "Check codec_ failed!");
2948 
2949     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
2950     CHECK_ERROR_RETURN_RET_LOG(decoder == nullptr, false, "Get heif decoder failed.");
2951 
2952     decoder->getFragmentMetadata(metadata);
2953     return true;
2954 #endif
2955     return false;
2956 }
2957 
2958 bool ExtDecoder::HeifGainMapRegionCrop(DecodeContext &gainmapRegionContext, int32_t rowStride, uint8_t* dstBuffer,
2959     uint32_t gainmapWidth, uint32_t gainmapHeight)
2960 {
2961 #ifdef HEIF_HW_DECODE_ENABLE
2962     bool cond = (gainmapWidth == ZERO || gainmapHeight == ZERO);
2963     CHECK_ERROR_RETURN_RET_LOG(cond, false, "gainmap width or gainmap height is ZERO");
2964     int32_t gainmapWidthRatio = info_.width() / static_cast<int32_t>(gainmapWidth);
2965     int32_t gainmapHeightRatio = info_.height() / static_cast<int32_t>(gainmapHeight);
2966     cond = (gainmapWidthRatio == ZERO || gainmapHeightRatio == ZERO);
2967     CHECK_ERROR_RETURN_RET_LOG(cond, false, "gainmap widthRatio or gainmap heightRatio is ZERO");
2968     SkImageInfo dstRegionInfo = SkImageInfo::Make(static_cast<int>(heifGridRegionInfo_.tileWidth *
2969         heifGridRegionInfo_.colCount / gainmapWidthRatio),
2970         static_cast<int>(heifGridRegionInfo_.tileHeight * heifGridRegionInfo_.rowCount /
2971         gainmapHeightRatio), dstInfo_.colorType(), dstInfo_.alphaType(), dstInfo_.refColorSpace());
2972     uint64_t byteCount = static_cast<uint64_t>(dstRegionInfo.computeMinByteSize());
2973     gainmapRegionContext.info.size.width = heifGridRegionInfo_.tileWidth *
2974         heifGridRegionInfo_.colCount / gainmapWidthRatio;
2975     gainmapRegionContext.info.size.height = heifGridRegionInfo_.tileHeight *
2976         heifGridRegionInfo_.rowCount / gainmapHeightRatio;
2977     cond = DmaMemAlloc(gainmapRegionContext, byteCount, dstRegionInfo) != SUCCESS;
2978     CHECK_ERROR_RETURN_RET(cond, false);
2979     auto* sbBuffer = reinterpret_cast<SurfaceBuffer*>(gainmapRegionContext.pixelsBuffer.context);
2980     int32_t rowRegionStride = sbBuffer->GetStride();
2981     auto* dstRegionBuffer = static_cast<uint8_t*>(gainmapRegionContext.pixelsBuffer.buffer);
2982     int32_t left = desiredRegion_.left / heifGridRegionInfo_.tileWidth *
2983         heifGridRegionInfo_.tileWidth / gainmapWidthRatio;
2984     int32_t top = desiredRegion_.top / heifGridRegionInfo_.tileHeight *
2985         heifGridRegionInfo_.tileHeight / gainmapHeightRatio;
2986     int32_t srcOffset = rowStride * top + left * RGBA8888_PIXEL_BYTE_SIZE;
2987     for (int32_t index = 0; index < (heifGridRegionInfo_.tileHeight * heifGridRegionInfo_.rowCount -
2988         heifGridRegionInfo_.heightPadding) / gainmapHeightRatio; index++) {
2989         uint8_t* srcRow = dstBuffer + srcOffset + index * rowStride;
2990         uint8_t* dstRow = dstRegionBuffer + index * rowRegionStride;
2991         int32_t cropLength = (heifGridRegionInfo_.tileWidth * heifGridRegionInfo_.colCount -
2992             heifGridRegionInfo_.widthPadding) / gainmapWidthRatio * RGBA8888_PIXEL_BYTE_SIZE;
2993         errno_t err = memcpy_s(dstRow, cropLength, srcRow, cropLength);
2994         cond = err != EOK;
2995         CHECK_ERROR_RETURN_RET_LOG(cond, false, "handle heifgainmap memcpy failed.");
2996     }
2997     return true;
2998 #endif
2999     return false;
3000 }
3001 
3002 bool ExtDecoder::DecodeHeifGainMap(DecodeContext& context)
3003 {
3004 #ifdef HEIF_HW_DECODE_ENABLE
3005     bool cond = codec_ == nullptr || codec_->getEncodedFormat() != SkEncodedImageFormat::kHEIF;
3006     CHECK_ERROR_RETURN_RET_LOG(cond, false, "decode heif gainmap, codec error");
3007     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
3008     cond = decoder == nullptr;
3009     CHECK_ERROR_RETURN_RET_LOG(cond, false, "decode heif gainmap, decoder error");
3010     HeifFrameInfo gainmapInfo;
3011     decoder->getGainmapInfo(&gainmapInfo);
3012     uint32_t width = gainmapInfo.mWidth;
3013     uint32_t height = gainmapInfo.mHeight;
3014     cond = width > INT_MAX || height > INT_MAX;
3015     CHECK_INFO_RETURN_RET_LOG(cond, false, "DecodeHeifGainmap size exceeds the maximum value");
3016     IMAGE_LOGD("DecodeHeifGainmap size:%{public}d-%{public}d", width, height);
3017     uint32_t dstGainmapWidth = width / sampleSize_;
3018     uint32_t dstGainmapHeight = height / sampleSize_;
3019     IMAGE_LOGD("DecodeHeifGainmap sample size:%{public}d-%{public}d", dstGainmapWidth, dstGainmapHeight);
3020     SkImageInfo dstInfo = SkImageInfo::Make(static_cast<int>(dstGainmapWidth), static_cast<int>(dstGainmapHeight),
3021         dstInfo_.colorType(), dstInfo_.alphaType(), dstInfo_.refColorSpace());
3022     uint64_t byteCount = static_cast<uint64_t>(dstInfo.computeMinByteSize());
3023     context.info.size.width = static_cast<int32_t>(dstGainmapWidth);
3024     context.info.size.height = static_cast<int32_t>(dstGainmapWidth);
3025     cond = DmaMemAlloc(context, byteCount, dstInfo) != SUCCESS;
3026     CHECK_ERROR_RETURN_RET(cond, false);
3027     auto* dstBuffer = static_cast<uint8_t*>(context.pixelsBuffer.buffer);
3028     auto* sbBuffer = reinterpret_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
3029     int32_t rowStride = sbBuffer->GetStride();
3030     if (rowStride <= 0) {
3031         FreeContextBuffer(context.freeFunc, context.allocatorType, context.pixelsBuffer);
3032         return false;
3033     }
3034     decoder->setGainmapDstBuffer(dstBuffer, static_cast<size_t>(rowStride), context.pixelsBuffer.context);
3035     if (!decoder->decodeGainmap()) {
3036         FreeContextBuffer(context.freeFunc, context.allocatorType, context.pixelsBuffer);
3037         return false;
3038     }
3039     if (IsHeifRegionDecode()) {
3040         DecodeContext gainmapRegionContext;
3041         if (HeifGainMapRegionCrop(gainmapRegionContext, rowStride, dstBuffer, width, height)) {
3042             context = gainmapRegionContext;
3043             IMAGE_LOGI("Do Heif GainMap Region Decode success");
3044         } else {
3045             FreeContextBuffer(context.freeFunc, context.allocatorType, context.pixelsBuffer);
3046             FreeContextBuffer(gainmapRegionContext.freeFunc, gainmapRegionContext.allocatorType,
3047                 gainmapRegionContext.pixelsBuffer);
3048             IMAGE_LOGE("Heif gainmap region decode failed.");
3049             return false;
3050         }
3051     }
3052     return true;
3053 #endif
3054     return false;
3055 }
3056 
3057 bool ExtDecoder::GetHeifHdrColorSpace(ColorManager::ColorSpaceName& gainmap, ColorManager::ColorSpaceName& hdr)
3058 {
3059 #ifdef HEIF_HW_DECODE_ENABLE
3060     bool cond = codec_ == nullptr || codec_->getEncodedFormat() != SkEncodedImageFormat::kHEIF;
3061     CHECK_ERROR_RETURN_RET(cond, false);
3062     auto decoder = reinterpret_cast<HeifDecoder*>(codec_->getHeifContext());
3063     cond = decoder == nullptr;
3064     CHECK_ERROR_RETURN_RET(cond, false);
3065     HeifFrameInfo gainmapInfo;
3066     decoder->getGainmapInfo(&gainmapInfo);
3067     if (gainmapInfo.hasNclxColor) {
3068         gainmap = ColorUtils::CicpToColorSpace(gainmapInfo.nclxColor.colorPrimaries,
3069             gainmapInfo.nclxColor.transferCharacteristics, gainmapInfo.nclxColor.matrixCoefficients,
3070             gainmapInfo.nclxColor.fullRangeFlag);
3071     }
3072     HeifFrameInfo tmapInfo;
3073     decoder->getTmapInfo(&tmapInfo);
3074     if (tmapInfo.hasNclxColor) {
3075         hdr = ColorUtils::CicpToColorSpace(tmapInfo.nclxColor.colorPrimaries,
3076             tmapInfo.nclxColor.transferCharacteristics, tmapInfo.nclxColor.matrixCoefficients,
3077             tmapInfo.nclxColor.fullRangeFlag);
3078     }
3079     return true;
3080 #endif
3081     return false;
3082 }
3083 
3084 uint32_t ExtDecoder::GetHeifParseErr()
3085 {
3086     return heifParseErr_;
3087 }
3088 
3089 void ExtDecoder::SetHeifDecodeError(OHOS::ImagePlugin::DecodeContext &context)
3090 {
3091 #ifdef HEIF_HW_DECODE_ENABLE
3092     if (codec_ == nullptr || codec_->getEncodedFormat() != SkEncodedImageFormat::kHEIF) {
3093         return;
3094     }
3095     auto decoder = reinterpret_cast<HeifDecoder*>(codec_->getHeifContext());
3096     if (decoder == nullptr) {
3097         return;
3098     }
3099     decoder->getErrMsg(context.hardDecodeError);
3100 #endif
3101 }
3102 
3103 void ExtDecoder::SetHeifParseError()
3104 {
3105     if (stream_ == nullptr) {
3106         return;
3107     }
3108     uint32_t originOffset = stream_->Tell();
3109     stream_->Seek(0);
3110 
3111     uint32_t readSize = 0;
3112     HeifFormatAgent agent;
3113     uint32_t headerSize = agent.GetHeaderSize();
3114     uint8_t headerBuf[headerSize];
3115     bool readRet = stream_->Peek(headerSize, headerBuf, headerSize, readSize);
3116     if (!readRet || readSize != headerSize) {
3117         stream_->Seek(originOffset);
3118         return;
3119     }
3120 
3121     if (!agent.CheckFormat(headerBuf, headerSize)) {
3122         stream_->Seek(originOffset);
3123         return;
3124     }
3125 
3126     size_t fileLength = stream_->GetStreamSize();
3127     if (fileLength <= 0) {
3128         return;
3129     }
3130     uint8_t *fileMem = reinterpret_cast<uint8_t*>(malloc(fileLength));
3131     if (fileMem == nullptr) {
3132         return;
3133     }
3134     readRet = stream_->Read(fileLength, fileMem, fileLength, readSize);
3135     if (!readRet || readSize != fileLength) {
3136         stream_->Seek(originOffset);
3137         free(fileMem);
3138         return;
3139     }
3140 
3141     std::shared_ptr<HeifParser> parser;
3142     heif_error parseRet = HeifParser::MakeFromMemory(fileMem, fileLength, false, &parser);
3143     if (parseRet != heif_error_ok) {
3144         heifParseErr_ = static_cast<uint32_t>(parseRet);
3145     }
3146 
3147     stream_->Seek(originOffset);
3148     free(fileMem);
3149 }
3150 
3151 bool ExtDecoder::CheckAuxiliaryMap(AuxiliaryPictureType type)
3152 {
3153 #ifdef HEIF_HW_DECODE_ENABLE
3154     bool cond = codec_ == nullptr || codec_->getEncodedFormat() != SkEncodedImageFormat::kHEIF;
3155     CHECK_ERROR_RETURN_RET_LOG(cond, false,
3156         "Check heif auxiliaryMap failed! Invalid parameter, type %{public}d.", type);
3157 
3158     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
3159     CHECK_ERROR_RETURN_RET_LOG(decoder == nullptr, false, "Get heif context failed, type %{public}d.", type);
3160 
3161     if (!decoder->CheckAuxiliaryMap(type)) {
3162         IMAGE_LOGE("Get heif auxiliary type %{public}d, decoder error", type);
3163         return false;
3164     }
3165     return true;
3166 #endif
3167     return false;
3168 }
3169 
3170 bool ExtDecoder::DecodeHeifAuxiliaryMap(DecodeContext& context, AuxiliaryPictureType type)
3171 {
3172 #ifdef HEIF_HW_DECODE_ENABLE
3173     bool cond = codec_ == nullptr || codec_->getEncodedFormat() != SkEncodedImageFormat::kHEIF;
3174     CHECK_ERROR_RETURN_RET_LOG(cond, false, "decode heif auxiliaryMap type %{public}d, codec error", type);
3175 
3176     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
3177     cond = decoder == nullptr;
3178     CHECK_ERROR_RETURN_RET_LOG(cond, false, "decode heif auxiliaryMap %{public}d, decoder error", type);
3179     cond = !decoder->setAuxiliaryMap(type);
3180     CHECK_ERROR_RETURN_RET_LOG(cond, false, "set auxiliary map type failed, type is %{public}d", type);
3181     HeifFrameInfo auxiliaryMapInfo;
3182     decoder->getAuxiliaryMapInfo(&auxiliaryMapInfo);
3183     uint32_t width = auxiliaryMapInfo.mWidth;
3184     uint32_t height = auxiliaryMapInfo.mHeight;
3185     cond = width > INT_MAX || height > INT_MAX;
3186     CHECK_INFO_RETURN_RET_LOG(cond, false, "DecodeHeifAuxiliaryMap size exceeds the maximum value");
3187     IMAGE_LOGD("DecodeHeifAuxiliaryMap size:%{public}d-%{public}d", width, height);
3188     SkImageInfo dstInfo = SkImageInfo::Make(static_cast<int>(width), static_cast<int>(height), dstInfo_.colorType(),
3189         dstInfo_.alphaType(), dstInfo_.refColorSpace());
3190     size_t tempByteCount = dstInfo.computeMinByteSize();
3191     if (SkImageInfo::ByteSizeOverflowed(tempByteCount)) {
3192         IMAGE_LOGE("Image too large, dstInfo_height: %{public}d, dstInfo_width: %{public}d",
3193             dstInfo.height(), dstInfo.width());
3194         return false;
3195     }
3196     uint64_t byteCount = tempByteCount;
3197     context.info.size.width = static_cast<int32_t>(width);
3198     context.info.size.height = static_cast<int32_t>(height);
3199     cond = DmaMemAlloc(context, byteCount, dstInfo) != SUCCESS;
3200     CHECK_INFO_RETURN_RET_LOG(cond, false, "DmaMemAlloc execution failed.");
3201     auto* dstBuffer = static_cast<uint8_t*>(context.pixelsBuffer.buffer);
3202     auto* sbBuffer = reinterpret_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
3203     int32_t rowStride = sbBuffer->GetStride();
3204     if (rowStride <= 0) {
3205         return false;
3206     }
3207     decoder->setAuxiliaryDstBuffer(dstBuffer, context.pixelsBuffer.bufferSize,
3208         static_cast<size_t>(rowStride), context.pixelsBuffer.context);
3209     }
3210     cond = !decoder->decodeAuxiliaryMap();
3211     CHECK_ERROR_RETURN_RET_LOG(cond, false,
3212         "Decoded auxiliary map type is not supported, or decoded failed. Type: %{public}d", type);
3213     context.outInfo.size.width = static_cast<int32_t>(width);
3214     context.outInfo.size.height = static_cast<int32_t>(height);
3215     return true;
3216 #endif
3217     return false;
3218 }
3219 } // namespace ImagePlugin
3220 } // namespace OHOS
3221