• 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 
22 #include "src/codec/SkJpegCodec.h"
23 #include "src/codec/SkJpegDecoderMgr.h"
24 #include "ext_pixel_convert.h"
25 #include "image_log.h"
26 #include "image_format_convert.h"
27 #include "image_mime_type.h"
28 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
29 #include "ffrt.h"
30 #include "hisysevent.h"
31 #endif
32 #include "image_system_properties.h"
33 #include "image_utils.h"
34 #include "media_errors.h"
35 #include "native_buffer.h"
36 #include "securec.h"
37 #include "string_ex.h"
38 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
39 #include "surface_buffer.h"
40 #include "hdr_helper.h"
41 #endif
42 #ifdef HEIF_HW_DECODE_ENABLE
43 #include "heif_impl/HeifDecoder.h"
44 #include "heif_impl/HeifDecoderImpl.h"
45 #include "hardware/heif_hw_decoder.h"
46 #endif
47 #include "color_utils.h"
48 #include "heif_parser.h"
49 #include "heif_format_agent.h"
50 #include "heif_type.h"
51 #include "image/image_plugin_type.h"
52 
53 #include "image_type_converter.h"
54 #include "include/core/SkBitmap.h"
55 #include "include/core/SkCanvas.h"
56 #include "include/core/SkImage.h"
57 
58 #undef LOG_DOMAIN
59 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_PLUGIN
60 
61 #undef LOG_TAG
62 #define LOG_TAG "ExtDecoder"
63 
64 namespace {
65     constexpr static int32_t ZERO = 0;
66     constexpr static int32_t NUM_2 = 2;
67     constexpr static int32_t NUM_3 = 3;
68     constexpr static int32_t NUM_4 = 4;
69     constexpr static int32_t OFFSET = 1;
70     constexpr static size_t SIZE_ZERO = 0;
71     constexpr static uint32_t DEFAULT_SAMPLE_SIZE = 1;
72     constexpr static uint32_t NO_EXIF_TAG = 1;
73     constexpr static uint32_t OFFSET_0 = 0;
74     constexpr static uint32_t OFFSET_1 = 1;
75     constexpr static uint32_t OFFSET_2 = 2;
76     constexpr static uint32_t OFFSET_3 = 3;
77     constexpr static uint32_t OFFSET_5 = 5;
78     constexpr static uint32_t SHIFT_BITS_8 = 8;
79     constexpr static uint32_t SHIFT_BITS_16 = 16;
80     constexpr static uint32_t SHIFT_BITS_24 = 24;
81     constexpr static uint32_t DESC_SIGNATURE = 0x64657363;
82     constexpr static size_t SIZE_1 = 1;
83     constexpr static size_t SIZE_4 = 4;
84     constexpr static int HARDWARE_MIN_DIM = 1024;
85     constexpr static int HARDWARE_MAX_DIM = 8192;
86     constexpr static float HALF = 0.5;
87     constexpr static float QUARTER = 0.25;
88     constexpr static float ONE_EIGHTH = 0.125;
89     constexpr static uint64_t ICC_HEADER_SIZE = 132;
90     constexpr static size_t SMALL_FILE_SIZE = 1000 * 1000 * 10;
91     constexpr static int32_t LOOP_COUNT_INFINITE = 0;
92     constexpr static int32_t SK_REPETITION_COUNT_INFINITE = -1;
93     constexpr static int32_t SK_REPETITION_COUNT_ERROR_VALUE = -2;
94     constexpr static int32_t BYTES_PER_YUV_SAMPLE = 2;
95 }
96 
97 namespace OHOS {
98 namespace ImagePlugin {
99 using namespace Media;
100 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
101 using namespace OHOS::HDI::Base;
102 #endif
103 using namespace std;
104 const static string DEFAULT_EXIF_VALUE = "default_exif_value";
105 const static string CODEC_INITED_KEY = "CodecInited";
106 const static string ENCODED_FORMAT_KEY = "EncodedFormat";
107 const static string SUPPORT_SCALE_KEY = "SupportScale";
108 const static string SUPPORT_CROP_KEY = "SupportCrop";
109 const static string EXT_SHAREMEM_NAME = "EXTRawData";
110 const static string TAG_ORIENTATION_STRING = "Orientation";
111 const static string TAG_ORIENTATION_INT = "OrientationInt";
112 const static string IMAGE_DELAY_TIME = "DelayTime";
113 const static string IMAGE_DISPOSAL_TYPE = "DisposalType";
114 const static string IMAGE_LOOP_COUNT = "GIFLoopCount";
115 const static std::string HW_MNOTE_TAG_HEADER = "HwMnote";
116 const static std::string HW_MNOTE_CAPTURE_MODE = "HwMnoteCaptureMode";
117 const static std::string HW_MNOTE_PHYSICAL_APERTURE = "HwMnotePhysicalAperture";
118 const static std::string HW_MNOTE_TAG_ROLL_ANGLE = "HwMnoteRollAngle";
119 const static std::string HW_MNOTE_TAG_PITCH_ANGLE = "HwMnotePitchAngle";
120 const static std::string HW_MNOTE_TAG_SCENE_FOOD_CONF = "HwMnoteSceneFoodConf";
121 const static std::string HW_MNOTE_TAG_SCENE_STAGE_CONF = "HwMnoteSceneStageConf";
122 const static std::string HW_MNOTE_TAG_SCENE_BLUE_SKY_CONF = "HwMnoteSceneBlueSkyConf";
123 const static std::string HW_MNOTE_TAG_SCENE_GREEN_PLANT_CONF = "HwMnoteSceneGreenPlantConf";
124 const static std::string HW_MNOTE_TAG_SCENE_BEACH_CONF = "HwMnoteSceneBeachConf";
125 const static std::string HW_MNOTE_TAG_SCENE_SNOW_CONF = "HwMnoteSceneSnowConf";
126 const static std::string HW_MNOTE_TAG_SCENE_SUNSET_CONF = "HwMnoteSceneSunsetConf";
127 const static std::string HW_MNOTE_TAG_SCENE_FLOWERS_CONF = "HwMnoteSceneFlowersConf";
128 const static std::string HW_MNOTE_TAG_SCENE_NIGHT_CONF = "HwMnoteSceneNightConf";
129 const static std::string HW_MNOTE_TAG_SCENE_TEXT_CONF = "HwMnoteSceneTextConf";
130 const static std::string HW_MNOTE_TAG_FACE_COUNT = "HwMnoteFaceCount";
131 const static std::string HW_MNOTE_TAG_FOCUS_MODE = "HwMnoteFocusMode";
132 // SUCCESS is existed in both OHOS::HiviewDFX and OHOS::Media
133 #define SUCCESS OHOS::Media::SUCCESS
134 const static std::string DEFAULT_PACKAGE_NAME = "entry";
135 const static std::string DEFAULT_VERSION_ID = "1";
136 const static std::string UNKNOWN_IMAGE = "unknown";
137 constexpr static int NUM_ONE = 1;
138 constexpr static uint64_t MALLOC_LIMIT = 300 * 1024 * 1024;
139 #ifdef JPEG_HW_DECODE_ENABLE
140 const static uint32_t PLANE_COUNT_TWO = 2;
141 #endif
142 
143 struct ColorTypeOutput {
144     PixelFormat outFormat;
145     SkColorType skFormat;
146 };
147 
148 struct SkTransInfo {
149     SkRect r;
150     SkImageInfo info;
151     SkBitmap bitmap;
152 };
153 
154 static const map<PixelFormat, ColorTypeOutput> COLOR_TYPE_MAP = {
155     { PixelFormat::UNKNOWN, { PixelFormat::RGBA_8888, kRGBA_8888_SkColorType } },
156     { PixelFormat::RGBA_8888, { PixelFormat::RGBA_8888, kRGBA_8888_SkColorType } },
157     { PixelFormat::BGRA_8888, { PixelFormat::BGRA_8888, kBGRA_8888_SkColorType } },
158     { PixelFormat::ALPHA_8, { PixelFormat::ALPHA_8, kAlpha_8_SkColorType } },
159     { PixelFormat::RGB_565, { PixelFormat::RGB_565, kRGB_565_SkColorType } },
160     { PixelFormat::RGB_888, { PixelFormat::RGB_888, kRGB_888x_SkColorType } },
161 };
162 
163 static const map<AlphaType, SkAlphaType> ALPHA_TYPE_MAP = {
164     { AlphaType::IMAGE_ALPHA_TYPE_OPAQUE, kOpaque_SkAlphaType },
165     { AlphaType::IMAGE_ALPHA_TYPE_PREMUL, kPremul_SkAlphaType },
166     { AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL, kUnpremul_SkAlphaType },
167 };
168 
169 static const map<SkEncodedImageFormat, string> FORMAT_NAME = {
170     { SkEncodedImageFormat::kBMP, "image/bmp" },
171     { SkEncodedImageFormat::kGIF, "image/gif" },
172     { SkEncodedImageFormat::kICO, "image/x-ico" },
173     { SkEncodedImageFormat::kJPEG, "image/jpeg" },
174     { SkEncodedImageFormat::kPNG, "image/png" },
175     { SkEncodedImageFormat::kWBMP, "image/bmp" },
176     { SkEncodedImageFormat::kWEBP, "image/webp" },
177     { SkEncodedImageFormat::kPKM, "" },
178     { SkEncodedImageFormat::kKTX, "" },
179     { SkEncodedImageFormat::kASTC, "" },
180     { SkEncodedImageFormat::kDNG, "image/raw" },
181     { SkEncodedImageFormat::kHEIF, "image/heif" },
182 };
183 
184 #if !defined(CROSS_PLATFORM)
185 static const map<PixelFormat, int32_t> PIXELFORMAT_TOGRAPHIC_MAP = {
186     {PixelFormat::RGBA_1010102, GRAPHIC_PIXEL_FMT_RGBA_1010102},
187     {PixelFormat::YCRCB_P010, GRAPHIC_PIXEL_FMT_YCRCB_P010},
188     {PixelFormat::YCBCR_P010, GRAPHIC_PIXEL_FMT_YCBCR_P010},
189     {PixelFormat::NV12, GRAPHIC_PIXEL_FMT_YCBCR_420_SP},
190     {PixelFormat::NV21, GRAPHIC_PIXEL_FMT_YCRCB_420_SP},
191     {PixelFormat::RGBA_F16, GRAPHIC_PIXEL_FMT_RGBA16_FLOAT},
192     {PixelFormat::BGRA_8888, GRAPHIC_PIXEL_FMT_BGRA_8888},
193     {PixelFormat::RGB_565, GRAPHIC_PIXEL_FMT_RGB_565},
194 };
195 #endif
196 
197 #ifdef HEIF_HW_DECODE_ENABLE
198 static const map<PixelFormat, SkHeifColorFormat> HEIF_FORMAT_MAP = {
199     { PixelFormat::RGBA_1010102, kHeifColorFormat_RGBA_1010102 },
200     { PixelFormat::YCBCR_P010, kHeifColorFormat_P010_NV12 },
201     { PixelFormat::YCRCB_P010, kHeifColorFormat_P010_NV21 },
202 };
203 #endif
204 
205 static const map<PixelFormat, JpegYuvFmt> PLPIXEL_FORMAT_YUV_JPG_MAP = {
206     { PixelFormat::NV21, JpegYuvFmt::OutFmt_NV21 }, { PixelFormat::NV12, JpegYuvFmt::OutFmt_NV12 }
207 };
208 
209 // LCOV_EXCL_START
SetDecodeContextBuffer(DecodeContext & context,AllocatorType type,uint8_t * ptr,uint64_t count,void * fd)210 static void SetDecodeContextBuffer(DecodeContext &context,
211     AllocatorType type, uint8_t* ptr, uint64_t count, void* fd)
212 {
213     context.allocatorType = type;
214     context.freeFunc = nullptr;
215     context.pixelsBuffer.buffer = ptr;
216     context.pixelsBuffer.bufferSize = count;
217     context.pixelsBuffer.context = fd;
218 }
219 
ShareMemAlloc(DecodeContext & context,uint64_t count)220 static uint32_t ShareMemAlloc(DecodeContext &context, uint64_t count)
221 {
222 #if defined(_WIN32) || defined(_APPLE) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
223     IMAGE_LOGE("Unsupport share mem alloc");
224     return ERR_IMAGE_DATA_UNSUPPORT;
225 #else
226     auto fd = make_unique<int32_t>();
227     *fd = AshmemCreate(EXT_SHAREMEM_NAME.c_str(), count);
228     if (*fd < 0) {
229         IMAGE_LOGE("AshmemCreate failed");
230         return ERR_SHAMEM_DATA_ABNORMAL;
231     }
232     int result = AshmemSetProt(*fd, PROT_READ | PROT_WRITE);
233     if (result < 0) {
234         ::close(*fd);
235         IMAGE_LOGE("AshmemSetProt failed");
236         return ERR_SHAMEM_DATA_ABNORMAL;
237     }
238     void* ptr = ::mmap(nullptr, count, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, ZERO);
239     if (ptr == MAP_FAILED) {
240         ::close(*fd);
241         IMAGE_LOGE("::mmap failed");
242         return ERR_SHAMEM_DATA_ABNORMAL;
243     }
244     SetDecodeContextBuffer(context,
245         AllocatorType::SHARE_MEM_ALLOC, static_cast<uint8_t*>(ptr), count, fd.release());
246     return SUCCESS;
247 #endif
248 }
249 
250 #if !defined(_WIN32) && !defined(_APPLE) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
CreateDmaRequestConfig(const SkImageInfo & dstInfo,uint64_t & count,PixelFormat pixelFormat)251 static BufferRequestConfig CreateDmaRequestConfig(const SkImageInfo &dstInfo, uint64_t &count, PixelFormat pixelFormat)
252 {
253     BufferRequestConfig requestConfig = {
254         .width = dstInfo.width(),
255         .height = dstInfo.height(),
256         .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
257         .format = GRAPHIC_PIXEL_FMT_RGBA_8888, // hardware decode only support rgba8888
258         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
259         .timeout = 0,
260         .colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB,
261         .transform = GraphicTransformType::GRAPHIC_ROTATE_NONE,
262     };
263     auto formatSearch = PIXELFORMAT_TOGRAPHIC_MAP.find(pixelFormat);
264     requestConfig.format = (formatSearch != PIXELFORMAT_TOGRAPHIC_MAP.end()) ?
265         formatSearch->second : GRAPHIC_PIXEL_FMT_RGBA_8888;
266     if (requestConfig.format == GRAPHIC_PIXEL_FMT_YCBCR_420_SP ||
267         requestConfig.format == GRAPHIC_PIXEL_FMT_YCRCB_420_SP) {
268         count = JpegDecoderYuv::GetYuvOutSize(dstInfo.width(), dstInfo.height());
269     } else if (requestConfig.format == GRAPHIC_PIXEL_FMT_RGBA16_FLOAT) {
270         count = dstInfo.width() * dstInfo.height() * ImageUtils::GetPixelBytes(PixelFormat::RGBA_F16);
271     }
272     return requestConfig;
273 }
274 #endif
275 
DmaMemAlloc(DecodeContext & context,uint64_t count,SkImageInfo & dstInfo)276 uint32_t ExtDecoder::DmaMemAlloc(DecodeContext &context, uint64_t count, SkImageInfo &dstInfo)
277 {
278 #if defined(_WIN32) || defined(_APPLE) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
279     IMAGE_LOGE("Unsupport dma mem alloc");
280     return ERR_IMAGE_DATA_UNSUPPORT;
281 #else
282     BufferRequestConfig requestConfig = CreateDmaRequestConfig(dstInfo, count, context.info.pixelFormat);
283     return DmaAlloc(context, count, requestConfig);
284 #endif
285 }
286 
JpegHwDmaMemAlloc(DecodeContext & context,uint64_t count,SkImageInfo & dstInfo)287 uint32_t ExtDecoder::JpegHwDmaMemAlloc(DecodeContext &context, uint64_t count, SkImageInfo &dstInfo)
288 {
289 #if defined(_WIN32) || defined(_APPLE) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
290     IMAGE_LOGE("Unsupport dma mem alloc");
291     return ERR_IMAGE_DATA_UNSUPPORT;
292 #else
293     BufferRequestConfig requestConfig = CreateDmaRequestConfig(dstInfo, count, context.info.pixelFormat);
294     if (outputColorFmt_ == PIXEL_FMT_YCRCB_420_SP) {
295         requestConfig.format = GRAPHIC_PIXEL_FMT_YCRCB_420_SP;
296         requestConfig.usage |= BUFFER_USAGE_VENDOR_PRI16; // height is 64-bytes aligned
297         IMAGE_LOGD("ExtDecoder::DmaMemAlloc desiredFormat is NV21");
298         count = JpegDecoderYuv::GetYuvOutSize(dstInfo.width(), dstInfo.height());
299     }
300     return DmaAlloc(context, count, requestConfig);
301 #endif
302 }
303 
DmaAlloc(DecodeContext & context,uint64_t count,const OHOS::BufferRequestConfig & requestConfig)304 uint32_t ExtDecoder::DmaAlloc(DecodeContext &context, uint64_t count, const OHOS::BufferRequestConfig &requestConfig)
305 {
306 #if defined(CROSS_PLATFORM)
307     IMAGE_LOGE("Unsupport dma mem alloc");
308     return ERR_IMAGE_DATA_UNSUPPORT;
309 #else
310     sptr<SurfaceBuffer> sb = SurfaceBuffer::Create();
311     GSError ret = sb->Alloc(requestConfig);
312     if (ret != GSERROR_OK) {
313         IMAGE_LOGE("SurfaceBuffer Alloc failed, %{public}s", GSErrorStr(ret).c_str());
314         return ERR_DMA_NOT_EXIST;
315     }
316     void* nativeBuffer = sb.GetRefPtr();
317     int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
318     if (err != OHOS::GSERROR_OK) {
319         IMAGE_LOGE("NativeBufferReference failed");
320         return ERR_DMA_DATA_ABNORMAL;
321     }
322 
323     IMAGE_LOGD("ExtDecoder::DmaMemAlloc sb stride is %{public}d, height is %{public}d, size is %{public}d",
324         sb->GetStride(), sb->GetHeight(), sb->GetSize());
325     SetDecodeContextBuffer(context, AllocatorType::DMA_ALLOC, static_cast<uint8_t*>(sb->GetVirAddr()), count,
326         nativeBuffer);
327     return SUCCESS;
328 #endif
329 }
330 
HeapMemAlloc(DecodeContext & context,uint64_t count)331 static uint32_t HeapMemAlloc(DecodeContext &context, uint64_t count)
332 {
333     if (count == 0 || count > PIXEL_MAP_MAX_RAM_SIZE) {
334         IMAGE_LOGE("HeapMemAlloc Invalid value of bufferSize");
335         return ERR_IMAGE_DATA_ABNORMAL;
336     }
337     auto out = static_cast<uint8_t *>(malloc(count));
338 #ifdef _WIN32
339     if (memset_s(out, ZERO, count) != EOK) {
340 #else
341     if (memset_s(out, count, ZERO, count) != EOK) {
342 #endif
343         IMAGE_LOGE("Decode failed, memset buffer failed");
344         free(out);
345         return ERR_IMAGE_DECODE_FAILED;
346     }
347     SetDecodeContextBuffer(context, AllocatorType::HEAP_ALLOC, out, count, nullptr);
348     return SUCCESS;
349 }
350 
351 uint32_t ExtDecoder::HeifYUVMemAlloc(OHOS::ImagePlugin::DecodeContext &context)
352 {
353 #ifdef HEIF_HW_DECODE_ENABLE
354     HeifHardwareDecoder decoder;
355     GraphicPixelFormat graphicPixelFormat = GRAPHIC_PIXEL_FMT_YCRCB_420_SP;
356     if (context.info.pixelFormat == PixelFormat::NV12) {
357         graphicPixelFormat = GRAPHIC_PIXEL_FMT_YCBCR_420_SP;
358     } else if (context.info.pixelFormat == PixelFormat::YCRCB_P010) {
359         graphicPixelFormat = GRAPHIC_PIXEL_FMT_YCRCB_P010;
360     } else if (context.info.pixelFormat == PixelFormat::YCBCR_P010) {
361         graphicPixelFormat = GRAPHIC_PIXEL_FMT_YCBCR_P010;
362     }
363     sptr<SurfaceBuffer> hwBuffer
364             = decoder.AllocateOutputBuffer(info_.width(), info_.height(), graphicPixelFormat);
365     if (hwBuffer == nullptr) {
366         IMAGE_LOGE("HeifHardwareDecoder AllocateOutputBuffer return null");
367         return ERR_DMA_NOT_EXIST;
368     }
369 
370     void* nativeBuffer = hwBuffer.GetRefPtr();
371     int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
372     if (err != OHOS::GSERROR_OK) {
373         IMAGE_LOGE("HeifYUVMemAlloc Reference failed");
374         return ERR_DMA_DATA_ABNORMAL;
375     }
376 
377     IMAGE_LOGI("ExtDecoder::HeifYUVMemAlloc sb stride is %{public}d, height is %{public}d, size is %{public}d",
378                hwBuffer->GetStride(), hwBuffer->GetHeight(), hwBuffer->GetSize());
379     uint64_t yuvBufferSize = JpegDecoderYuv::GetYuvOutSize(info_.width(), info_.height());
380     SetDecodeContextBuffer(context, AllocatorType::DMA_ALLOC,
381                            static_cast<uint8_t*>(hwBuffer->GetVirAddr()), yuvBufferSize, nativeBuffer);
382     OH_NativeBuffer_Planes *planes = nullptr;
383     GSError retVal = hwBuffer->GetPlanesInfo(reinterpret_cast<void**>(&planes));
384     if (retVal != OHOS::GSERROR_OK || planes == nullptr || planes->planeCount < NUM_2) {
385         IMAGE_LOGE("heif yuv decode, Get planesInfo failed, retVal:%{public}d", retVal);
386     } else {
387         uint32_t uvPlaneOffset = (context.info.pixelFormat == PixelFormat::NV12 ||
388                 context.info.pixelFormat == PixelFormat::YCBCR_P010) ? NUM_ONE : NUM_2;
389         context.yuvInfo.imageSize = { info_.width(), info_.height() };
390         context.yuvInfo.yWidth = info_.width();
391         context.yuvInfo.yHeight = info_.height();
392         context.yuvInfo.uvWidth = static_cast<uint32_t>((info_.width() + 1) / NUM_2);
393         context.yuvInfo.uvHeight = static_cast<uint32_t>((info_.height() + 1) / NUM_2);
394         context.yuvInfo.yStride = planes->planes[0].columnStride;
395         context.yuvInfo.uvStride = planes->planes[uvPlaneOffset].columnStride;
396         context.yuvInfo.yOffset = planes->planes[0].offset;
397         context.yuvInfo.uvOffset = planes->planes[uvPlaneOffset].offset;
398     }
399     return SUCCESS;
400 #else
401     return ERR_IMAGE_DATA_UNSUPPORT;
402 #endif
403 }
404 // LCOV_EXCL_STOP
405 
406 ExtDecoder::ExtDecoder() : codec_(nullptr), frameCount_(ZERO)
407 {
408 }
409 
410 ExtDecoder::~ExtDecoder()
411 {
412     if (gifCache_ != nullptr) {
413         free(gifCache_);
414         gifCache_ = nullptr;
415     }
416 }
417 
418 void ExtDecoder::SetSource(InputDataStream &sourceStream)
419 {
420     stream_ = &sourceStream;
421     streamOff_ = sourceStream.Tell();
422     if (streamOff_ >= sourceStream.GetStreamSize()) {
423         streamOff_ = ZERO;
424     }
425 }
426 
427 void ExtDecoder::Reset()
428 {
429     stream_ = nullptr;
430     codec_ = nullptr;
431     dstInfo_.reset();
432     dstSubset_ = SkIRect::MakeEmpty();
433     info_.reset();
434 }
435 
436 static inline float Max(float a, float b)
437 {
438     return (a > b) ? a : b;
439 }
440 
441 // LCOV_EXCL_START
442 bool ExtDecoder::GetScaledSize(int &dWidth, int &dHeight, float &scale)
443 {
444     if (info_.isEmpty() && !DecodeHeader()) {
445         IMAGE_LOGE("DecodeHeader failed in GetScaledSize!");
446         return false;
447     }
448     if (info_.isEmpty()) {
449         IMAGE_LOGE("empty image info in GetScaledSize!");
450         return false;
451     }
452     float finalScale = scale;
453     if (scale == ZERO) {
454         finalScale = Max(static_cast<float>(dWidth) / info_.width(),
455             static_cast<float>(dHeight) / info_.height());
456     }
457     if (codec_ == nullptr) {
458         IMAGE_LOGE("codec is null in GetScaledSize!");
459         return false;
460     }
461     auto scaledDimension = codec_->getScaledDimensions(finalScale);
462     dWidth = scaledDimension.width();
463     dHeight = scaledDimension.height();
464     scale = finalScale;
465     IMAGE_LOGD("IsSupportScaleOnDecode info [%{public}d x %{public}d]", info_.width(), info_.height());
466     IMAGE_LOGD("IsSupportScaleOnDecode [%{public}d x %{public}d]", dWidth, dHeight);
467     IMAGE_LOGD("IsSupportScaleOnDecode [%{public}f]", scale);
468     return true;
469 }
470 
471 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
472 bool ExtDecoder::GetHardwareScaledSize(int &dWidth, int &dHeight, float &scale) {
473     if (info_.isEmpty() && !DecodeHeader()) {
474         IMAGE_LOGE("DecodeHeader failed in GetHardwareScaledSize!");
475         return false;
476     }
477     if (info_.isEmpty()) {
478         IMAGE_LOGE("empty image info in GetHardwareScaledSize!");
479         return false;
480     }
481     float finalScale = scale;
482     int oriWidth = info_.width();
483     int oriHeight = info_.height();
484     if (scale == ZERO) {
485         finalScale = Max(static_cast<float>(dWidth) / oriWidth,
486                          static_cast<float>(dHeight) / oriHeight);
487     }
488     // calculate sample size and dst size for hardware decode
489     if (finalScale > HALF) {
490         sampleSize_ = 1;
491     } else if (finalScale > QUARTER) {
492         sampleSize_ = 2;
493     } else if (finalScale > ONE_EIGHTH) {
494         sampleSize_ = 4;
495     } else {
496         sampleSize_ = 8;
497     }
498     dWidth = (oriWidth + sampleSize_ - NUM_ONE) / sampleSize_;
499     dHeight = (oriHeight + sampleSize_ - NUM_ONE) / sampleSize_;
500     return true;
501 }
502 #endif
503 
504 bool ExtDecoder::IsSupportScaleOnDecode()
505 {
506     constexpr float HALF_SCALE = 0.5f;
507     int w = ZERO;
508     int h = ZERO;
509     float scale = HALF_SCALE;
510     return GetScaledSize(w, h, scale);
511 }
512 // LCOV_EXCL_STOP
513 
514 bool ExtDecoder::IsSupportCropOnDecode()
515 {
516     if (info_.isEmpty() && !DecodeHeader()) {
517         return false;
518     }
519     SkIRect innerRect = info_.bounds().makeInset(OFFSET, OFFSET);
520     return IsSupportCropOnDecode(innerRect);
521 }
522 
523 bool ExtDecoder::IsSupportCropOnDecode(SkIRect &target)
524 {
525     if (info_.isEmpty() && !DecodeHeader()) {
526         return false;
527     }
528     SkIRect orgbounds = info_.bounds();
529     SkIRect source = target;
530     if (orgbounds.contains(target) && codec_->getValidSubset(&target)) {
531         return source == target;
532     }
533     return false;
534 }
535 
536 // LCOV_EXCL_START
537 bool ExtDecoder::HasProperty(string key)
538 {
539     if (CODEC_INITED_KEY.compare(key) == ZERO) {
540         return CheckCodec();
541     } else if (ENCODED_FORMAT_KEY.compare(key) == ZERO) {
542         return true;
543     } else if (SUPPORT_SCALE_KEY.compare(key) == ZERO) {
544         return IsSupportScaleOnDecode();
545     } else if (SUPPORT_CROP_KEY.compare(key) == ZERO) {
546         return IsSupportCropOnDecode();
547     }
548     return false;
549 }
550 
551 uint32_t ExtDecoder::GetImageSize(uint32_t index, Size &size)
552 {
553     IMAGE_LOGD("GetImageSize index:%{public}u", index);
554     if (!CheckIndexValied(index)) {
555         IMAGE_LOGE("Invalid index:%{public}u, range:%{public}d", index, frameCount_);
556         return ERR_IMAGE_INVALID_PARAMETER;
557     }
558     IMAGE_LOGD("GetImageSize index:%{public}u, range:%{public}d", index, frameCount_);
559     // Info has been get in check process, or empty on get failed.
560     if (info_.isEmpty()) {
561         IMAGE_LOGE("GetImageSize failed, decode header failed.");
562         return ERR_IMAGE_DECODE_HEAD_ABNORMAL;
563     }
564     size.width = static_cast<uint32_t>(info_.width());
565     size.height = static_cast<uint32_t>(info_.height());
566     return SUCCESS;
567 }
568 // LCOV_EXCL_STOP
569 
570 static inline bool IsLowDownScale(const Size &size, SkImageInfo &info)
571 {
572     return size.width < info.width() &&
573         size.height < info.height();
574 }
575 
576 // LCOV_EXCL_START
577 static inline bool IsValidCrop(const OHOS::Media::Rect &crop, SkImageInfo &info, SkIRect &out)
578 {
579     out = SkIRect::MakeXYWH(crop.left, crop.top, crop.width, crop.height);
580     if (out.fLeft < ZERO || out.fTop < ZERO) {
581         return false;
582     }
583     if (out.fRight > info.width()) {
584         out.fRight = info.width();
585     }
586     if (out.fBottom > info.height()) {
587         out.fBottom = info.height();
588     }
589     return true;
590 }
591 // LCOV_EXCL_STOP
592 
593 static sk_sp<SkColorSpace> getDesiredColorSpace(SkImageInfo &srcInfo, const PixelDecodeOptions &opts)
594 {
595     if (opts.plDesiredColorSpace == nullptr) {
596         return srcInfo.refColorSpace();
597     }
598     return opts.plDesiredColorSpace->ToSkColorSpace();
599 }
600 
601 // LCOV_EXCL_START
602 uint32_t ExtDecoder::CheckDecodeOptions(uint32_t index, const PixelDecodeOptions &opts)
603 {
604     if (ImageUtils::CheckMulOverflow(dstInfo_.width(), dstInfo_.height(), dstInfo_.bytesPerPixel())) {
605         IMAGE_LOGE("SetDecodeOptions failed, width:%{public}d, height:%{public}d is too large",
606                      dstInfo_.width(), dstInfo_.height());
607         return ERR_IMAGE_INVALID_PARAMETER;
608     }
609     if (!IsValidCrop(opts.CropRect, info_, dstSubset_)) {
610         IMAGE_LOGE("Invalid crop rect xy [%{public}d x %{public}d], wh [%{public}d x %{public}d]",
611             dstSubset_.left(), dstSubset_.top(), dstSubset_.width(), dstSubset_.height());
612         return ERR_IMAGE_INVALID_PARAMETER;
613     }
614 
615     dstOptions_.fFrameIndex = static_cast<int>(index);
616 #ifdef IMAGE_COLORSPACE_FLAG
617     dstColorSpace_ = opts.plDesiredColorSpace;
618 #endif
619     return SUCCESS;
620 }
621 
622 uint32_t ExtDecoder::SetDecodeOptions(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info)
623 {
624     if (!CheckIndexValied(index)) {
625         IMAGE_LOGE("Invalid index:%{public}u, range:%{public}d", index, frameCount_);
626         return ERR_IMAGE_INVALID_PARAMETER;
627     }
628     if (opts.sampleSize != DEFAULT_SAMPLE_SIZE) {
629         IMAGE_LOGE("Do not support sample size now!");
630         return ERR_IMAGE_INVALID_PARAMETER;
631     }
632     auto desireColor = ConvertToColorType(opts.desiredPixelFormat, info.pixelFormat);
633     auto desireAlpha = ConvertToAlphaType(opts.desireAlphaType, info.alphaType);
634 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
635     outputColorFmt_ = (opts.desiredPixelFormat == PixelFormat::NV21 ? PIXEL_FMT_YCRCB_420_SP : PIXEL_FMT_RGBA_8888);
636 #endif
637 
638     if (codec_) {
639         SkEncodedImageFormat skEncodeFormat = codec_->getEncodedFormat();
640         if (skEncodeFormat == SkEncodedImageFormat::kJPEG && IsYuv420Format(opts.desiredPixelFormat)) {
641             info.pixelFormat = opts.desiredPixelFormat;
642             desiredSizeYuv_.width = opts.desiredSize.width;
643             desiredSizeYuv_.height = opts.desiredSize.height;
644         }
645         if (skEncodeFormat == SkEncodedImageFormat::kHEIF && IsYuv420Format(opts.desiredPixelFormat)) {
646             info.pixelFormat = opts.desiredPixelFormat;
647         }
648     }
649     // SK only support low down scale
650     int dstWidth = opts.desiredSize.width;
651     int dstHeight = opts.desiredSize.height;
652     float scale = ZERO;
653 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
654     if (IsSupportHardwareDecode()) {
655         // get dstInfo for hardware decode
656         if (IsLowDownScale(opts.desiredSize, info_) && GetHardwareScaledSize(dstWidth, dstHeight, scale)) {
657             hwDstInfo_ = SkImageInfo::Make(dstWidth, dstHeight, desireColor, desireAlpha, info_.refColorSpace());
658         } else {
659             hwDstInfo_ = SkImageInfo::Make(info_.width(), info_.height(),
660                                            desireColor, desireAlpha, info_.refColorSpace());
661         }
662         // restore dstWidth and dstHeight
663         dstWidth = opts.desiredSize.width;
664         dstHeight = opts.desiredSize.height;
665     }
666 #endif
667     if (IsLowDownScale(opts.desiredSize, info_) && GetScaledSize(dstWidth, dstHeight, scale)) {
668         dstInfo_ = SkImageInfo::Make(dstWidth, dstHeight, desireColor, desireAlpha,
669             getDesiredColorSpace(info_, opts));
670     } else {
671         dstInfo_ = SkImageInfo::Make(info_.width(), info_.height(),
672             desireColor, desireAlpha, getDesiredColorSpace(info_, opts));
673     }
674     auto resCode = CheckDecodeOptions(index, opts);
675     if (resCode != SUCCESS) {
676         return resCode;
677     }
678 
679     info.size.width = static_cast<uint32_t>(dstInfo_.width());
680     info.size.height = static_cast<uint32_t>(dstInfo_.height());
681     reusePixelmap_ = opts.plReusePixelmap;
682     return SUCCESS;
683 }
684 
685 uint32_t ExtDecoder::SetContextPixelsBuffer(uint64_t byteCount, DecodeContext &context)
686 {
687     if (byteCount == ZERO) {
688         return ERR_IMAGE_INVALID_PARAMETER;
689     }
690     if (context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC) {
691         return ShareMemAlloc(context, byteCount);
692     } else if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
693         return DmaMemAlloc(context, byteCount, dstInfo_);
694     }
695     return HeapMemAlloc(context, byteCount);
696 }
697 
698 static void DebugInfo(SkImageInfo &info, SkImageInfo &dstInfo, SkCodec::Options &opts)
699 {
700     IMAGE_LOGD("Decode source info: WH[%{public}d x %{public}d], A %{public}d, C %{public}d.",
701         info.width(), info.height(),
702         info.alphaType(), info.colorType());
703     IMAGE_LOGD("Decode dst info: WH[%{public}d x %{public}d], A %{public}d, C %{public}d.",
704         dstInfo.width(), dstInfo.height(), dstInfo.alphaType(), dstInfo.colorType());
705     if (opts.fSubset != nullptr) {
706         IMAGE_LOGD("Decode dstOpts sub: (%{public}d, %{public}d), WH[%{public}d x %{public}d]",
707             opts.fSubset->fLeft, opts.fSubset->fTop,
708             opts.fSubset->width(), opts.fSubset->height());
709     }
710 }
711 // LCOV_EXCL_STOP
712 
713 static uint64_t GetByteSize(int32_t width, int32_t height)
714 {
715     return static_cast<uint64_t>(width * height + ((width + 1) / NUM_2) * ((height + 1) / NUM_2) * NUM_2);
716 }
717 
718 static void UpdateContextYuvInfo(DecodeContext &context, DestConvertInfo &destInfo)
719 {
720     context.yuvInfo.yWidth = static_cast<uint32_t>(destInfo.width);
721     context.yuvInfo.yHeight = static_cast<uint32_t>(destInfo.height);
722     context.yuvInfo.yStride = destInfo.yStride;
723     context.yuvInfo.uvWidth = static_cast<uint32_t>((destInfo.width + 1) / NUM_2);
724     context.yuvInfo.uvHeight = static_cast<uint32_t>((destInfo.height + 1) / NUM_2);
725     context.yuvInfo.uvStride = destInfo.uvStride;
726     context.yuvInfo.yOffset = destInfo.yOffset;
727     context.yuvInfo.uvOffset = destInfo.uvOffset;
728 }
729 
730 static void FreeContextBuffer(const Media::CustomFreePixelMap &func, AllocatorType allocType, PlImageBuffer &buffer)
731 {
732     if (func != nullptr) {
733         func(buffer.buffer, buffer.context, buffer.bufferSize);
734         return;
735     }
736 
737 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
738     if (allocType == AllocatorType::SHARE_MEM_ALLOC) {
739         int *fd = static_cast<int *>(buffer.context);
740         if (buffer.buffer != nullptr) {
741             ::munmap(buffer.buffer, buffer.bufferSize);
742         }
743         if (fd != nullptr) {
744             ::close(*fd);
745         }
746         return;
747     } else if (allocType == AllocatorType::DMA_ALLOC) {
748         if (buffer.buffer != nullptr) {
749             ImageUtils::SurfaceBuffer_Unreference(static_cast<SurfaceBuffer *>(buffer.context));
750             buffer.context = nullptr;
751         }
752     } else if (allocType == AllocatorType::HEAP_ALLOC) {
753         if (buffer.buffer != nullptr) {
754             free(buffer.buffer);
755             buffer.buffer = nullptr;
756         }
757     }
758 #else
759     if (buffer.buffer != nullptr) {
760         free(buffer.buffer);
761         buffer.buffer = nullptr;
762     }
763 #endif
764 }
765 
766 uint32_t ExtDecoder::ConvertFormatToYUV(DecodeContext &context, SkImageInfo &skInfo,
767     uint64_t byteCount, PixelFormat format)
768 {
769     ConvertDataInfo srcDataInfo;
770     srcDataInfo.buffer = static_cast<uint8_buffer_type>(context.pixelsBuffer.buffer);
771     srcDataInfo.bufferSize = byteCount;
772     srcDataInfo.imageSize = {skInfo.width(), skInfo.height()};
773     srcDataInfo.pixelFormat = context.pixelFormat;
774     srcDataInfo.colorSpace = static_cast<ColorSpace>(context.colorSpace);
775 
776     DestConvertInfo destInfo = {skInfo.width(), skInfo.height()};
777     destInfo.format = format;
778     destInfo.allocType = context.allocatorType;
779     auto ret = Media::ImageFormatConvert::ConvertImageFormat(srcDataInfo, destInfo);
780     if (ret != SUCCESS) {
781         IMAGE_LOGE("Decode convert failed , ret=%{public}d", ret);
782         return ret;
783     }
784     FreeContextBuffer(context.freeFunc, context.allocatorType, context.pixelsBuffer);
785     SetDecodeContextBuffer(context, context.allocatorType, static_cast<uint8_t *>(destInfo.buffer),
786         destInfo.bufferSize, destInfo.context);
787     context.info.pixelFormat = format;
788     UpdateContextYuvInfo(context, destInfo);
789     return SUCCESS;
790 }
791 
792 static uint32_t RGBxToRGB(uint8_t* srcBuffer, size_t srsSize,
793     uint8_t* dstBuffer, size_t dstSize, size_t pixelCount)
794 {
795     ExtPixels src = {srcBuffer, srsSize, pixelCount};
796     ExtPixels dst = {dstBuffer, dstSize, pixelCount};
797     auto res = ExtPixelConvert::RGBxToRGB(src, dst);
798     if (res != SUCCESS) {
799         IMAGE_LOGE("RGBxToRGB failed %{public}d", res);
800     }
801     return res;
802 }
803 
804 // LCOV_EXCL_START
805 uint32_t ExtDecoder::PreDecodeCheck(uint32_t index)
806 {
807     if (!CheckIndexValied(index)) {
808         IMAGE_LOGE("Decode failed, invalid index:%{public}u, range:%{public}d", index, frameCount_);
809         return ERR_IMAGE_INVALID_PARAMETER;
810     }
811     if (codec_ == nullptr) {
812         IMAGE_LOGE("Decode failed, codec is null");
813         return ERR_IMAGE_DECODE_FAILED;
814     }
815     if (dstInfo_.isEmpty()) {
816         IMAGE_LOGE("Decode failed, dst info is empty");
817         return ERR_IMAGE_DECODE_FAILED;
818     }
819         return SUCCESS;
820 }
821 // LCOV_EXCL_STOP
822 
823 static bool IsColorSpaceSupport(SkJpegCodec* codec)
824 {
825     if (codec == nullptr || codec->decoderMgr() == nullptr || codec->decoderMgr()->dinfo() == nullptr) {
826         IMAGE_LOGE("SkJpegCodec is null");
827         return false;
828     }
829     struct jpeg_decompress_struct* pCinfo = codec->decoderMgr()->dinfo();
830     if (pCinfo->jpeg_color_space == JCS_YCbCr || pCinfo->jpeg_color_space == JCS_GRAYSCALE) {
831         return true;
832     }
833     IMAGE_LOGE("unsupported in color: %{public}d", pCinfo->jpeg_color_space);
834     return false;
835 }
836 
837 // LCOV_EXCL_START
838 uint32_t ExtDecoder::PreDecodeCheckYuv(uint32_t index, PixelFormat desiredFormat)
839 {
840     uint32_t ret = PreDecodeCheck(index);
841     if (ret != SUCCESS) {
842         return ret;
843     }
844     SkEncodedImageFormat skEncodeFormat = codec_->getEncodedFormat();
845     if (skEncodeFormat != SkEncodedImageFormat::kJPEG) {
846         IMAGE_LOGE("PreDecodeCheckYuv, not support to create 420 data from not jpeg");
847         return ERR_IMAGE_DESIRED_PIXELFORMAT_UNSUPPORTED;
848     }
849     if (stream_ == nullptr) {
850         return ERR_IMAGE_SOURCE_DATA;
851     }
852     auto iter = PLPIXEL_FORMAT_YUV_JPG_MAP.find(desiredFormat);
853     if (iter == PLPIXEL_FORMAT_YUV_JPG_MAP.end()) {
854         IMAGE_LOGE("PreDecodeCheckYuv desiredFormat format not valid");
855         return ERR_IMAGE_INVALID_PARAMETER;
856     }
857     uint32_t jpegBufferSize = stream_->GetStreamSize();
858     if (jpegBufferSize == 0) {
859         IMAGE_LOGE("PreDecodeCheckYuv jpegBufferSize 0");
860         return ERR_IMAGE_SOURCE_DATA;
861     }
862     if (!IsColorSpaceSupport(static_cast<SkJpegCodec*>(codec_.get()))) {
863         return ERR_IMAGE_SOURCE_DATA;
864     }
865     return SUCCESS;
866 }
867 // LCOV_EXCL_STOP
868 
869 bool ExtDecoder::ResetCodec()
870 {
871     codec_ = nullptr;
872     stream_->Seek(streamOff_);
873     return ExtDecoder::CheckCodec();
874 }
875 
876 #ifdef JPEG_HW_DECODE_ENABLE
877 uint32_t ExtDecoder::DoHardWareDecode(DecodeContext &context)
878 {
879     if (HardWareDecode(context) == SUCCESS) {
880         return SUCCESS;
881     }
882     return ERROR;
883 }
884 #endif
885 
886 static bool IsAllocatorTypeSupportHwDecode(const DecodeContext &context)
887 {
888     if (!context.isAppUseAllocator) {
889         return true;
890     }
891     return context.allocatorType == Media::AllocatorType::DMA_ALLOC;
892 }
893 
894 bool ExtDecoder::IsHeifSharedMemDecode(DecodeContext &context)
895 {
896     return codec_->getEncodedFormat() == SkEncodedImageFormat::kHEIF && context.isAppUseAllocator &&
897         context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC;
898 }
899 
900 void ExtDecoder::FillYuvInfo(DecodeContext &context, SkImageInfo &dstInfo)
901 {
902     if (context.allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
903         context.yuvInfo.imageSize = {dstInfo.width(), dstInfo.height()};
904         context.yuvInfo.yWidth = dstInfo.width();
905         context.yuvInfo.yHeight = dstInfo.height();
906         context.yuvInfo.uvWidth = static_cast<uint32_t>((dstInfo.width() + 1) / BYTES_PER_YUV_SAMPLE);
907         context.yuvInfo.uvHeight = static_cast<uint32_t>((dstInfo.height() + 1) / BYTES_PER_YUV_SAMPLE);
908         context.yuvInfo.yStride = dstInfo.width();
909         context.yuvInfo.uvStride = context.yuvInfo.uvWidth + context.yuvInfo.uvWidth;
910         context.yuvInfo.yOffset = 0;
911         context.yuvInfo.uvOffset = dstInfo.width() * dstInfo.height();
912     }
913 }
914 
915 #ifdef HEIF_HW_DECODE_ENABLE
916 bool SetOutPutFormat(OHOS::Media::PixelFormat pixelFormat, HeifDecoderImpl* decoder)
917 {
918     bool ret = true;
919     if (pixelFormat == PixelFormat::RGB_565) {
920         ret = decoder->setOutputColor(kHeifColorFormat_RGB565);
921     } else if (pixelFormat == PixelFormat::RGBA_8888) {
922         ret = decoder->setOutputColor(kHeifColorFormat_RGBA_8888);
923     } else if (pixelFormat == PixelFormat::BGRA_8888) {
924         ret = decoder->setOutputColor(kHeifColorFormat_BGRA_8888);
925     } else if (pixelFormat == PixelFormat::NV12) {
926         ret = decoder->setOutputColor(kHeifColorFormat_NV12);
927     } else if (pixelFormat == PixelFormat::NV21) {
928         ret = decoder->setOutputColor(kHeifColorFormat_NV21);
929     }
930     return ret;
931 }
932 #endif
933 
934 uint32_t ExtDecoder::DoHeifSharedMemDecode(DecodeContext &context)
935 {
936 #ifdef HEIF_HW_DECODE_ENABLE
937     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
938     if (decoder == nullptr) {
939         IMAGE_LOGE("Decode HeifDecoder is nullptr");
940         return ERR_IMAGE_DATA_UNSUPPORT;
941     }
942     uint64_t rowStride = dstInfo_.minRowBytes64();
943     uint64_t byteCount = dstInfo_.computeMinByteSize();
944     if (IsYuv420Format(context.info.pixelFormat)) {
945         rowStride = dstInfo_.width();
946         byteCount = JpegDecoderYuv::GetYuvOutSize(dstInfo_.width(), dstInfo_.height());
947     }
948     if (!SetOutPutFormat(context.info.pixelFormat, decoder)) {
949         return ERR_IMAGE_DATA_UNSUPPORT;
950     }
951     uint32_t res = ShareMemAlloc(context, byteCount);
952     if (res != SUCCESS) {
953         return res;
954     }
955     decoder->setDstBuffer(reinterpret_cast<uint8_t *>(context.pixelsBuffer.buffer), rowStride, nullptr);
956     bool decodeRet = decoder->SwDecode(context.isAppUseAllocator);
957     if (!decodeRet) {
958         decoder->getErrMsg(context.hardDecodeError);
959     } else if (IsYuv420Format(context.info.pixelFormat)) {
960         FillYuvInfo(context, dstInfo_);
961     }
962     return decodeRet ? SUCCESS : ERR_IMAGE_DATA_UNSUPPORT;
963 #else
964     return ERR_IMAGE_DATA_UNSUPPORT;
965 #endif
966 }
967 
968 uint32_t ExtDecoder::Decode(uint32_t index, DecodeContext &context)
969 {
970 #ifdef JPEG_HW_DECODE_ENABLE
971     if (IsAllocatorTypeSupportHwDecode(context) && IsSupportHardwareDecode() && DoHardWareDecode(context) == SUCCESS) {
972         context.isHardDecode = true;
973         return SUCCESS;
974     }
975 #endif
976     uint32_t res = PreDecodeCheck(index);
977     if (res != SUCCESS) {
978         return res;
979     }
980     context.outInfo.size.width = static_cast<uint32_t>(dstInfo_.width());
981     context.outInfo.size.height = static_cast<uint32_t>(dstInfo_.height());
982     if (IsHeifSharedMemDecode(context)) {
983         context.isHardDecode = false;
984         return DoHeifSharedMemDecode(context);
985     }
986     if (IsHeifToYuvDecode(context)) {
987         context.isHardDecode = true;
988         return DoHeifToYuvDecode(context);
989     }
990     if (IsHeifToSingleHdrDecode(context)) {
991         context.isHardDecode = true;
992         return DoHeifToSingleHdrDecode(context);
993     }
994     SkEncodedImageFormat skEncodeFormat = codec_->getEncodedFormat();
995     PixelFormat format = context.info.pixelFormat;
996     bool isOutputYuv420Format = IsYuv420Format(context.info.pixelFormat);
997     uint32_t result = 0;
998     if (isOutputYuv420Format && skEncodeFormat == SkEncodedImageFormat::kJPEG) {
999 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
1000         return 0;
1001 #else
1002         result = DecodeToYuv420(index, context);
1003         if (result != JpegYuvDecodeError_SubSampleNotSupport) {
1004             return result;
1005         }
1006         IMAGE_LOGI("Decode sample not support, apply rgb decode");
1007         context.pixelsBuffer.buffer = nullptr;
1008 #endif
1009     }
1010     if (skEncodeFormat == SkEncodedImageFormat::kHEIF) {
1011         context.isHardDecode = true;
1012     }
1013     size_t tempByteCount = dstInfo_.computeMinByteSize();
1014     if (SkImageInfo::ByteSizeOverflowed(tempByteCount)) {
1015         IMAGE_LOGE("Image too large, dstInfo_height: %{public}d, dstInfo_width: %{public}d",
1016             dstInfo_.height(), dstInfo_.width());
1017         return ERR_IMAGE_TOO_LARGE;
1018     }
1019     uint64_t byteCount = tempByteCount;
1020     uint8_t *dstBuffer = nullptr;
1021     std::unique_ptr<uint8_t[]> tmpBuffer;
1022     if (dstInfo_.colorType() == SkColorType::kRGB_888x_SkColorType) {
1023         tmpBuffer = make_unique<uint8_t[]>(byteCount);
1024         dstBuffer = tmpBuffer.get();
1025         byteCount = byteCount / NUM_4 * NUM_3;
1026     }
1027     if (context.pixelsBuffer.buffer == nullptr) {
1028         if (ImageUtils::IsSdrPixelMapReuseSuccess(context, info_.width(), info_.height(), reusePixelmap_)) {
1029             IMAGE_LOGI("Maindecode reusePixelmap success");
1030         } else {
1031             res = SetContextPixelsBuffer(byteCount, context);
1032             if (res != SUCCESS) {
1033                 return res;
1034             }
1035         }
1036         if (dstBuffer == nullptr) {
1037             dstBuffer = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
1038         }
1039     }
1040     dstOptions_.fFrameIndex = static_cast<int>(index);
1041     DebugInfo(info_, dstInfo_, dstOptions_);
1042     uint64_t rowStride = dstInfo_.minRowBytes64();
1043 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1044     if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
1045         SurfaceBuffer* sbBuffer = reinterpret_cast<SurfaceBuffer*> (context.pixelsBuffer.context);
1046         if (sbBuffer == nullptr) {
1047             IMAGE_LOGE("%{public}s: surface buffer is nullptr", __func__);
1048             return ERR_DMA_DATA_ABNORMAL;
1049         }
1050         rowStride = static_cast<uint64_t>(sbBuffer->GetStride());
1051     }
1052     ffrt::submit([skEncodeFormat] {
1053         ReportImageType(skEncodeFormat);
1054     }, {}, {});
1055 #endif
1056     IMAGE_LOGD("decode format %{public}d", skEncodeFormat);
1057     if (skEncodeFormat == SkEncodedImageFormat::kGIF || skEncodeFormat == SkEncodedImageFormat::kWEBP) {
1058         res = GifDecode(index, context, rowStride);
1059         ImageUtils::FlushContextSurfaceBuffer(context);
1060         return res;
1061     }
1062     SkCodec::Result ret = codec_->getPixels(dstInfo_, dstBuffer, rowStride, &dstOptions_);
1063     if (ret != SkCodec::kSuccess && ResetCodec() && skEncodeFormat != SkEncodedImageFormat::kHEIF) {
1064         ret = codec_->getPixels(dstInfo_, dstBuffer, rowStride, &dstOptions_); // Try again
1065     }
1066     if (ret != SkCodec::kSuccess) {
1067         IMAGE_LOGE("Decode failed, get pixels failed, ret=%{public}d", ret);
1068         SetHeifDecodeError(context);
1069         return ERR_IMAGE_DECODE_ABNORMAL;
1070     }
1071     if (dstInfo_.colorType() == SkColorType::kRGB_888x_SkColorType) {
1072         res = RGBxToRGB(dstBuffer, dstInfo_.computeMinByteSize(), static_cast<uint8_t*>(context.pixelsBuffer.buffer),
1073             byteCount, dstInfo_.width() * dstInfo_.height());
1074         if (res != SUCCESS) {
1075             IMAGE_LOGE("Decode failed, RGBxToRGB failed, res=%{public}d", res);
1076             return res;
1077         }
1078     }
1079     if (result == JpegYuvDecodeError_SubSampleNotSupport) {
1080         res = ConvertFormatToYUV(context, dstInfo_, byteCount, format);
1081         if (res != SUCCESS) {
1082             IMAGE_LOGE("Decode failed, ConvertFormatToYUV failed, res=%{public}d", res);
1083             return res;
1084         }
1085     }
1086     return SUCCESS;
1087 }
1088 
1089 uint32_t ExtDecoder::ReadJpegData(uint8_t* jpegBuffer, uint32_t jpegBufferSize)
1090 {
1091     if (stream_ == nullptr) {
1092         return ERR_IMAGE_SOURCE_DATA;
1093     }
1094     if (jpegBuffer == nullptr || jpegBufferSize == 0) {
1095         IMAGE_LOGE("ExtDecoder::ReadJpegData wrong parameter");
1096         return ERR_IMAGE_GET_DATA_ABNORMAL;
1097     }
1098     uint32_t savedPosition = stream_->Tell();
1099     if (!stream_->Seek(0)) {
1100         IMAGE_LOGE("ExtDecoder::ReadJpegData seek stream failed");
1101         return ERR_IMAGE_GET_DATA_ABNORMAL;
1102     }
1103     uint32_t readSize = 0;
1104     bool result = stream_->Read(jpegBufferSize, jpegBuffer, jpegBufferSize, readSize);
1105     if (!stream_->Seek(savedPosition)) {
1106         IMAGE_LOGE("ExtDecoder::ReadJpegData seek stream failed");
1107         return ERR_IMAGE_GET_DATA_ABNORMAL;
1108     }
1109     if (!result || readSize != jpegBufferSize) {
1110         IMAGE_LOGE("ReadJpegData read image data failed");
1111         return ERR_IMAGE_SOURCE_DATA;
1112     }
1113     return SUCCESS;
1114 }
1115 
1116 // LCOV_EXCL_START
1117 JpegYuvFmt ExtDecoder::GetJpegYuvOutFmt(PixelFormat desiredFormat)
1118 {
1119     auto iter = PLPIXEL_FORMAT_YUV_JPG_MAP.find(desiredFormat);
1120     if (iter == PLPIXEL_FORMAT_YUV_JPG_MAP.end()) {
1121         return JpegYuvFmt::OutFmt_NV12;
1122     } else {
1123         return iter->second;
1124     }
1125 }
1126 // LCOV_EXCL_STOP
1127 
1128 uint32_t ExtDecoder::DecodeToYuv420(uint32_t index, DecodeContext &context)
1129 {
1130 #if defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
1131     return 0;
1132 #endif
1133     uint32_t res = PreDecodeCheckYuv(index, context.info.pixelFormat);
1134     if (res != SUCCESS) {
1135         return res;
1136     }
1137     uint32_t jpegBufferSize = stream_->GetStreamSize();
1138     if (jpegBufferSize == 0) {
1139         IMAGE_LOGE("DecodeToYuv420 jpegBufferSize 0");
1140         return ERR_IMAGE_SOURCE_DATA;
1141     }
1142     uint8_t* jpegBuffer = NULL;
1143     if (stream_->GetStreamType() == ImagePlugin::BUFFER_SOURCE_TYPE) {
1144         jpegBuffer = stream_->GetDataPtr();
1145     }
1146     std::unique_ptr<uint8_t[]> jpegBufferPtr;
1147     if (jpegBuffer == nullptr) {
1148         jpegBufferPtr = std::make_unique<uint8_t[]>(jpegBufferSize);
1149         jpegBuffer = jpegBufferPtr.get();
1150         res = ReadJpegData(jpegBuffer, jpegBufferSize);
1151         if (res != SUCCESS) {
1152             return res;
1153         }
1154     }
1155     JpegYuvFmt decodeOutFormat = GetJpegYuvOutFmt(context.info.pixelFormat);
1156     Size jpgSize = {static_cast<uint32_t>(info_.width()), static_cast<uint32_t>(info_.height())};
1157     Size desiredSize = desiredSizeYuv_;
1158     bool bRet = JpegDecoderYuv::GetScaledSize(jpgSize.width, jpgSize.height, desiredSize.width, desiredSize.height);
1159     if (!bRet || desiredSize.width == 0 || desiredSize.height == 0) {
1160         IMAGE_LOGE("DecodeToYuv420 GetScaledSize failed");
1161         return ERR_IMAGE_INVALID_PARAMETER;
1162     }
1163     uint64_t yuvBufferSize = JpegDecoderYuv::GetYuvOutSize(desiredSize.width, desiredSize.height);
1164     dstInfo_ = dstInfo_.makeWH(desiredSize.width, desiredSize.height);
1165     res = SetContextPixelsBuffer(yuvBufferSize, context);
1166     if (res != SUCCESS) {
1167         IMAGE_LOGE("ExtDecoder::DecodeToYuv420 SetContextPixelsBuffer failed");
1168         return res;
1169     }
1170     uint8_t *yuvBuffer = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
1171     std::unique_ptr<JpegDecoderYuv> jpegYuvDecoder_ = std::make_unique<JpegDecoderYuv>();
1172     JpegDecoderYuvParameter para = {jpgSize.width, jpgSize.height, jpegBuffer, jpegBufferSize,
1173         yuvBuffer, yuvBufferSize, decodeOutFormat, desiredSize.width, desiredSize.height};
1174     int retDecode = jpegYuvDecoder_->DoDecode(context, para);
1175     if (retDecode != JpegYuvDecodeError_Success) {
1176         IMAGE_LOGE("DecodeToYuv420 DoDecode return %{public}d", retDecode);
1177     } else {
1178         // update yuv outInfo if decode success, same as jpeg hardware decode
1179         context.outInfo.size = desiredSize;
1180     }
1181     return retDecode;
1182 }
1183 
1184 // LCOV_EXCL_START
1185 static std::string GetFormatStr(SkEncodedImageFormat format)
1186 {
1187     switch (format) {
1188         case SkEncodedImageFormat::kBMP:
1189             return "bmp";
1190         case SkEncodedImageFormat::kGIF:
1191             return "gif";
1192         case SkEncodedImageFormat::kICO:
1193             return "ico";
1194         case SkEncodedImageFormat::kJPEG:
1195             return "jpeg";
1196         case SkEncodedImageFormat::kPNG:
1197             return "png";
1198         case SkEncodedImageFormat::kWBMP:
1199             return "wbmp";
1200         case SkEncodedImageFormat::kWEBP:
1201             return "webp";
1202         case SkEncodedImageFormat::kPKM:
1203             return "pkm";
1204         case SkEncodedImageFormat::kKTX:
1205             return "ktx";
1206         case SkEncodedImageFormat::kASTC:
1207             return "astc";
1208         case SkEncodedImageFormat::kDNG:
1209             return "dng";
1210         case SkEncodedImageFormat::kHEIF:
1211             return "heif";
1212         case SkEncodedImageFormat::kAVIF:
1213             return "avif";
1214         default:
1215             return UNKNOWN_IMAGE;
1216     }
1217 }
1218 
1219 void ExtDecoder::ReportImageType(SkEncodedImageFormat skEncodeFormat)
1220 {
1221     IMAGE_LOGD("ExtDecoder::ReportImageType format %{public}d start", skEncodeFormat);
1222     static constexpr char IMAGE_FWK_UE[] = "IMAGE_FWK_UE";
1223 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1224     int32_t ret = HiSysEventWrite(
1225             IMAGE_FWK_UE,
1226             "DECODED_IMAGE_TYPE_STATISTICS",
1227             HiviewDFX::HiSysEvent::EventType::STATISTIC,
1228             "PNAMEID", DEFAULT_PACKAGE_NAME,
1229             "PVERSIONID", DEFAULT_VERSION_ID,
1230             "IMAGE_TYPE", GetFormatStr(skEncodeFormat)
1231     );
1232     if (SUCCESS != ret) {
1233         IMAGE_LOGD("ExtDecoder::ReportImageType failed, ret = %{public}d", ret);
1234         return;
1235     }
1236 #endif
1237     IMAGE_LOGD("ExtDecoder::ReportImageType format %{public}d success", skEncodeFormat);
1238 }
1239 #ifdef JPEG_HW_DECODE_ENABLE
1240 uint32_t ExtDecoder::AllocOutputBuffer(DecodeContext &context,
1241     OHOS::HDI::Codec::Image::V2_0::CodecImageBuffer& outputBuffer)
1242 {
1243     if (ImageUtils::CheckMulOverflow(hwDstInfo_.height(), hwDstInfo_.width(), hwDstInfo_.bytesPerPixel())) {
1244         IMAGE_LOGE("Invalid dstInfo height:%{public}d, width:%{public}d", hwDstInfo_.height(), hwDstInfo_.width());
1245         return ERR_IMAGE_DECODE_ABNORMAL;
1246     }
1247     uint64_t byteCount = static_cast<uint64_t>(hwDstInfo_.height()) *
1248             static_cast<uint64_t>(hwDstInfo_.width()) *
1249             static_cast<uint64_t>(hwDstInfo_.bytesPerPixel());
1250     context.allocatorType = AllocatorType::DMA_ALLOC;
1251     if (ImageUtils::IsSdrPixelMapReuseSuccess(context, info_.width(), info_.height(), reusePixelmap_)) {
1252         IMAGE_LOGI("Jpeg hardware decode reusePixelmap success");
1253     } else {
1254         uint32_t ret = JpegHwDmaMemAlloc(context, byteCount, hwDstInfo_);
1255         if (ret != SUCCESS) {
1256             IMAGE_LOGE("Alloc OutputBuffer failed, ret=%{public}d", ret);
1257             return ERR_IMAGE_DECODE_ABNORMAL;
1258         }
1259     }
1260 
1261     if (context.pixelsBuffer.context == nullptr) {
1262         IMAGE_LOGE("Alloc OutputBuffer failed, context is null");
1263         return ERR_IMAGE_DECODE_ABNORMAL;
1264     }
1265     BufferHandle *handle = (static_cast<SurfaceBuffer*>(context.pixelsBuffer.context))->GetBufferHandle();
1266     if (outputColorFmt_ == PIXEL_FMT_RGBA_8888) {
1267         outputBufferSize_.width = static_cast<uint32_t>(handle->stride) / NUM_4;
1268     } else {
1269         outputBufferSize_.width = static_cast<uint32_t>(handle->stride);
1270     }
1271     outputBufferSize_.height = static_cast<uint32_t>(handle->height);
1272     outputBuffer.buffer = new NativeBuffer(handle);
1273     outputBuffer.fenceFd = -1;
1274     return SUCCESS;
1275 }
1276 
1277 bool ExtDecoder::CheckContext(const DecodeContext &context)
1278 {
1279     if (IsYuv420Format(context.info.pixelFormat)) {
1280         if (outputColorFmt_ == PIXEL_FMT_YCRCB_420_SP) {
1281             return true;
1282         }
1283         IMAGE_LOGI("yuv hardware decode only support NV21 format");
1284         return false;
1285     }
1286     if (dstInfo_.colorType() != kRGBA_8888_SkColorType) {
1287         IMAGE_LOGI("jpeg hardware decode only support rgba_8888 format");
1288         return false;
1289     }
1290     return true;
1291 }
1292 // LCOV_EXCL_STOP
1293 
1294 void ExtDecoder::ReleaseOutputBuffer(DecodeContext &context, Media::AllocatorType allocatorType)
1295 {
1296     ImageUtils::SurfaceBuffer_Unreference(static_cast<SurfaceBuffer*>(context.pixelsBuffer.context));
1297     context.pixelsBuffer.buffer = nullptr;
1298     context.allocatorType = allocatorType;
1299     context.freeFunc = nullptr;
1300     context.pixelsBuffer.bufferSize = 0;
1301     context.pixelsBuffer.context = nullptr;
1302 }
1303 
1304 uint32_t ExtDecoder::ApplyDesiredColorSpace(DecodeContext &context)
1305 {
1306     SurfaceBuffer* sbuffer = static_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
1307     int32_t width = sbuffer->GetWidth();
1308     int32_t height = sbuffer->GetHeight();
1309     uint64_t rowStride = static_cast<uint64_t>(sbuffer->GetStride());
1310 
1311     // build sk source information
1312     SkTransInfo src;
1313     uint8_t* srcData = static_cast<uint8_t*>(sbuffer->GetVirAddr());
1314     SkColorType colorType = ImageTypeConverter::ToSkColorType(context.pixelFormat);
1315     SkAlphaType alphaType = ImageTypeConverter::ToSkAlphaType(OHOS::Media::AlphaType::IMAGE_ALPHA_TYPE_PREMUL);
1316 
1317     if (!src.bitmap.installPixels(info_, srcData, rowStride)) {
1318         IMAGE_LOGE("apply colorspace get install failed.");
1319         return ERR_IMAGE_COLOR_CONVERT;
1320     }
1321 
1322     // build target information
1323     SkTransInfo dst;
1324     dst.info = SkImageInfo::Make(width, height, colorType, alphaType, dstColorSpace_->ToSkColorSpace());
1325 
1326     MemoryData memoryData = {nullptr, hwDstInfo_.computeMinByteSize(),
1327         "Trans ImageData", {hwDstInfo_.width(), hwDstInfo_.height()}, context.pixelFormat};
1328     AllocatorType allocatorType = context.allocatorType;
1329     auto m = MemoryManager::CreateMemory(allocatorType, memoryData);
1330     if (m == nullptr) {
1331         IMAGE_LOGE("applyColorSpace CreateMemory failed");
1332         return ERR_IMAGE_COLOR_CONVERT;
1333     }
1334 
1335     // Transfor pixels by readPixels
1336     if (!src.bitmap.readPixels(dst.info, m->data.data, rowStride, 0, 0)) {
1337         m->Release();
1338         IMAGE_LOGE("applyColorSpace ReadPixels failded");
1339         return ERR_IMAGE_COLOR_CONVERT;
1340     }
1341     FreeContextBuffer(context.freeFunc, context.allocatorType, context.pixelsBuffer);
1342     SetDecodeContextBuffer(context, context.allocatorType, static_cast<uint8_t *>(m->data.data),
1343                            m->data.size, m->extend.data);
1344     return SUCCESS;
1345 }
1346 
1347 void ExtDecoder::UpdateHardWareDecodeInfo(DecodeContext &context)
1348 {
1349     SurfaceBuffer* sbuffer = static_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
1350     if (sbuffer && sbuffer->GetFormat() != GRAPHIC_PIXEL_FMT_RGBA_8888) {
1351         OH_NativeBuffer_Planes *planes = nullptr;
1352         GSError retVal = sbuffer->GetPlanesInfo(reinterpret_cast<void**>(&planes));
1353         if (retVal != OHOS::GSERROR_OK || planes == nullptr) {
1354             IMAGE_LOGI("jpeg hardware decode, Get planesInfo failed, retVal:%{public}d", retVal);
1355         } else if (planes->planeCount >= PLANE_COUNT_TWO) {
1356             context.yuvInfo.yStride = planes->planes[0].columnStride;
1357             context.yuvInfo.uvStride = planes->planes[1].columnStride;
1358             context.yuvInfo.yOffset = planes->planes[0].offset;
1359             context.yuvInfo.uvOffset = planes->planes[1].offset - 1;
1360             context.yuvInfo.uvWidth = static_cast<uint32_t>((hwDstInfo_.width() + 1) / NUM_2);
1361             context.yuvInfo.uvHeight = static_cast<uint32_t>((hwDstInfo_.height() + 1) / NUM_2);
1362         }
1363     }
1364     context.outInfo.size.width = static_cast<uint32_t>(hwDstInfo_.width());
1365     context.outInfo.size.height = static_cast<uint32_t>(hwDstInfo_.height());
1366     if (outputColorFmt_ == PIXEL_FMT_YCRCB_420_SP) {
1367         context.yuvInfo.imageSize = {hwDstInfo_.width(), hwDstInfo_.height()};
1368     }
1369 }
1370 
1371 uint32_t ExtDecoder::HardWareDecode(DecodeContext &context)
1372 {
1373     JpegHardwareDecoder hwDecoder;
1374     orgImgSize_.width = static_cast<uint32_t>(info_.width());
1375     orgImgSize_.height = static_cast<uint32_t>(info_.height());
1376     if (!CheckContext(context)) {
1377         return ERROR;
1378     }
1379     Media::AllocatorType tmpAllocatorType = context.allocatorType;
1380     OHOS::HDI::Codec::Image::V2_0::CodecImageBuffer outputBuffer;
1381     uint32_t ret = AllocOutputBuffer(context, outputBuffer);
1382     if (ret != SUCCESS) {
1383         IMAGE_LOGE("Decode failed, Alloc OutputBuffer failed, ret=%{public}d", ret);
1384         context.hardDecodeError = "Decode failed, Alloc OutputBuffer failed, ret=" + std::to_string(ret);
1385         return ERR_IMAGE_DECODE_ABNORMAL;
1386     }
1387     ret = hwDecoder.Decode(codec_.get(), stream_, orgImgSize_, sampleSize_, outputBuffer);
1388     if (ret != SUCCESS) {
1389         IMAGE_LOGE("failed to do jpeg hardware decode, err=%{public}d", ret);
1390         context.hardDecodeError = "failed to do jpeg hardware decode, err=" + std::to_string(ret);
1391         ReleaseOutputBuffer(context, tmpAllocatorType);
1392         return ERR_IMAGE_DECODE_ABNORMAL;
1393     }
1394     if (srcColorSpace_ != nullptr && dstColorSpace_ != nullptr &&
1395         srcColorSpace_->GetColorSpaceName()!= dstColorSpace_->GetColorSpaceName()) {
1396         ApplyDesiredColorSpace(context);
1397     }
1398     UpdateHardWareDecodeInfo(context);
1399     return SUCCESS;
1400 }
1401 #endif
1402 
1403 uint32_t ExtDecoder::HandleGifCache(uint8_t* src, uint8_t* dst, uint64_t rowStride, int dstHeight)
1404 {
1405     if (src == nullptr || dst == nullptr) {
1406         return ERR_IMAGE_DECODE_ABNORMAL;
1407     }
1408     uint8_t* srcRow = src;
1409     uint8_t* dstRow = dst;
1410     for (int i = 0; i < dstHeight; i++) {
1411         errno_t err = memcpy_s(dstRow, rowStride, srcRow, rowStride);
1412         if (err != EOK) {
1413             IMAGE_LOGE("handle gif memcpy failed. errno:%{public}d", err);
1414             return ERR_IMAGE_DECODE_ABNORMAL;
1415         }
1416         if (i != (dstHeight - 1)) {
1417             srcRow += rowStride;
1418             dstRow += rowStride;
1419         }
1420     }
1421     return SUCCESS;
1422 }
1423 
1424 ExtDecoder::FrameCacheInfo ExtDecoder::InitFrameCacheInfo(const uint64_t rowStride, SkImageInfo info)
1425 {
1426     FrameCacheInfo cacheInfo = {0, 0, 0, 0};
1427     int width = info.width();
1428     int height = info.height();
1429     if (width < 0 || height < 0) {
1430         IMAGE_LOGI("InitFrameCacheInfo failed, width:[%{public}d<0], height:[%{public}d<0]", width, height);
1431         return cacheInfo;
1432     }
1433     cacheInfo.width = width;
1434     cacheInfo.height = height;
1435     cacheInfo.rowStride = rowStride;
1436     cacheInfo.byteCount = rowStride * static_cast<uint64_t>(cacheInfo.height);
1437     return cacheInfo;
1438 }
1439 
1440 bool ExtDecoder::FrameCacheInfoIsEqual(ExtDecoder::FrameCacheInfo& src, ExtDecoder::FrameCacheInfo& dst)
1441 {
1442     if (src.byteCount == 0 || src.rowStride == 0 || src.height == 0 || src.width == 0) {
1443         IMAGE_LOGE("FrameCacheInfoIsEqual, incorrect info");
1444         return false;
1445     }
1446     return (src.byteCount == dst.byteCount) && (src.rowStride == dst.rowStride) &&
1447         (src.height == dst.height) && (src.width == dst.width);
1448 }
1449 
1450 uint32_t ExtDecoder::GetFramePixels(SkImageInfo& info, uint8_t* buffer, uint64_t rowStride, SkCodec::Options options)
1451 {
1452     if (buffer == nullptr) {
1453         IMAGE_LOGE("get pixels failed, buffer is nullptr");
1454         return ERR_IMAGE_DECODE_ABNORMAL;
1455     }
1456     SkCodec::Result ret = codec_->getPixels(info, buffer, rowStride, &options);
1457     if (ret != SkCodec::kSuccess && ResetCodec()) {
1458         // Try again
1459         ret = codec_->getPixels(info, buffer, rowStride, &options);
1460     }
1461     if (ret != SkCodec::kSuccess) {
1462         IMAGE_LOGE("Gif decode failed, get pixels failed, ret=%{public}d", ret);
1463         return ERR_IMAGE_DECODE_ABNORMAL;
1464     }
1465     return SUCCESS;
1466 }
1467 
1468 uint32_t ExtDecoder::GifDecode(uint32_t index, DecodeContext &context, const uint64_t rowStride)
1469 {
1470     IMAGE_LOGD("In GifDecoder, frame index %{public}d", index);
1471     SkCodec::FrameInfo curInfo {};
1472     int signedIndex = static_cast<int>(index);
1473     codec_->getFrameInfo(signedIndex, &curInfo);
1474     if (signedIndex == 0 || gifCache_ == nullptr) {
1475         dstOptions_.fPriorFrame = SkCodec::kNoFrame;
1476     } else {
1477         int preIndex = signedIndex - 1;
1478         SkCodec::FrameInfo preInfo {};
1479         codec_->getFrameInfo(preIndex, &preInfo);
1480         if (preInfo.fDisposalMethod == SkCodecAnimation::DisposalMethod::kRestorePrevious) {
1481             dstOptions_.fPriorFrame = gifCacheIndex_;
1482         } else {
1483             dstOptions_.fPriorFrame = gifCacheIndex_ == preIndex ? preIndex : SkCodec::kNoFrame;
1484         }
1485     }
1486     ExtDecoder::FrameCacheInfo dstFrameCacheInfo = InitFrameCacheInfo(rowStride, dstInfo_);
1487     uint8_t* dstBuffer = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
1488     if (curInfo.fDisposalMethod != SkCodecAnimation::DisposalMethod::kRestorePrevious) {
1489         if (gifCache_ == nullptr) {
1490             frameCacheInfo_ = InitFrameCacheInfo(rowStride, dstInfo_);
1491             uint64_t memorySize = frameCacheInfo_.byteCount;
1492             if (memorySize == 0 || memorySize >= MALLOC_LIMIT) {
1493                 IMAGE_LOGE("%{public}s memorySize invalid: %{public}llu", __func__,
1494                     static_cast<unsigned long long>(memorySize));
1495                 return ERR_IMAGE_DECODE_ABNORMAL;
1496             }
1497             gifCache_ = static_cast<uint8_t *>(calloc(frameCacheInfo_.byteCount, 1));
1498         }
1499         if (!FrameCacheInfoIsEqual(frameCacheInfo_, dstFrameCacheInfo)) {
1500             IMAGE_LOGE("Frame info is not equal");
1501             return ERR_IMAGE_DECODE_ABNORMAL;
1502         }
1503         uint32_t ret = GetFramePixels(dstInfo_, gifCache_, rowStride, dstOptions_);
1504         if (ret != SUCCESS) {
1505             return ret;
1506         }
1507         gifCacheIndex_ = signedIndex;
1508         return HandleGifCache(gifCache_, dstBuffer, dstFrameCacheInfo.rowStride, dstFrameCacheInfo.height);
1509     }
1510     if (gifCache_ != nullptr && FrameCacheInfoIsEqual(frameCacheInfo_, dstFrameCacheInfo)) {
1511         HandleGifCache(gifCache_, dstBuffer, dstFrameCacheInfo.rowStride, dstFrameCacheInfo.height);
1512     } else {
1513         dstOptions_.fPriorFrame = SkCodec::kNoFrame;
1514     }
1515     return GetFramePixels(dstInfo_, dstBuffer, rowStride, dstOptions_);
1516 }
1517 
1518 uint32_t ExtDecoder::PromoteIncrementalDecode(uint32_t index, ProgDecodeContext &context)
1519 {
1520     // currently not support increment decode
1521     return ERR_IMAGE_DATA_UNSUPPORT;
1522 }
1523 
1524 // LCOV_EXCL_START
1525 bool ExtDecoder::CheckCodec()
1526 {
1527     if (codec_ != nullptr) {
1528         return true;
1529     } else if (stream_ == nullptr) {
1530         IMAGE_LOGE("create codec: input stream is nullptr.");
1531         return false;
1532     } else if (stream_->GetStreamSize() == SIZE_ZERO) {
1533         IMAGE_LOGD("create codec: input stream size is zero.");
1534         return false;
1535     }
1536     uint32_t src_offset = stream_->Tell();
1537     codec_ = SkCodec::MakeFromStream(make_unique<ExtStream>(stream_));
1538     if (codec_ == nullptr) {
1539         stream_->Seek(src_offset);
1540         IMAGE_LOGD("create codec from stream failed");
1541         SetHeifParseError();
1542         return false;
1543     }
1544     return codec_ != nullptr;
1545 }
1546 // LCOV_EXCL_STOP
1547 
1548 bool ExtDecoder::DecodeHeader()
1549 {
1550     if (!CheckCodec()) {
1551         IMAGE_LOGD("DecodeHeader Check codec failed");
1552         return false;
1553     }
1554     info_ = codec_->getInfo();
1555     frameCount_ = codec_->getFrameCount();
1556     IMAGE_LOGD("DecodeHeader: get frame count %{public}d.", frameCount_);
1557     return true;
1558 }
1559 
1560 bool ExtDecoder::CheckIndexValied(uint32_t index)
1561 {
1562     if (frameCount_ == ZERO && !DecodeHeader()) {
1563         return false;
1564     }
1565     return static_cast<int32_t>(index) >= ZERO && static_cast<int32_t>(index) < frameCount_;
1566 }
1567 
1568 static uint32_t GetFormatName(SkEncodedImageFormat format, std::string &name)
1569 {
1570     auto formatNameIter = FORMAT_NAME.find(format);
1571     if (formatNameIter != FORMAT_NAME.end() && !formatNameIter->second.empty()) {
1572         name = formatNameIter->second;
1573         if (name == IMAGE_HEIF_FORMAT && ImageUtils::GetAPIVersion() > APIVERSION_13) {
1574             name = IMAGE_HEIC_FORMAT;
1575         }
1576         IMAGE_LOGD("GetFormatName: get encoded format name (%{public}d)=>[%{public}s].",
1577             format, name.c_str());
1578         return SUCCESS;
1579     }
1580     IMAGE_LOGE("GetFormatName: get encoded format name failed %{public}d.", format);
1581     return ERR_IMAGE_DATA_UNSUPPORT;
1582 }
1583 
1584 // LCOV_EXCL_START
1585 bool ExtDecoder::ConvertInfoToAlphaType(SkAlphaType &alphaType, AlphaType &outputType)
1586 {
1587     if (info_.isEmpty()) {
1588         return false;
1589     }
1590     alphaType = info_.alphaType();
1591     auto findItem = std::find_if(ALPHA_TYPE_MAP.begin(), ALPHA_TYPE_MAP.end(),
1592         [alphaType](const map<AlphaType, SkAlphaType>::value_type item) {
1593         return item.second == alphaType;
1594     });
1595     if (findItem == ALPHA_TYPE_MAP.end()) {
1596         return false;
1597     }
1598     outputType = findItem->first;
1599     alphaType = findItem->second;
1600     return true;
1601 }
1602 
1603 bool ExtDecoder::ConvertInfoToColorType(SkColorType &format, PixelFormat &outputFormat)
1604 {
1605     if (info_.isEmpty()) {
1606         return false;
1607     }
1608     auto colorType = info_.colorType();
1609     auto findItem = std::find_if(COLOR_TYPE_MAP.begin(), COLOR_TYPE_MAP.end(),
1610         [colorType](const map<PixelFormat, ColorTypeOutput>::value_type item) {
1611         return item.second.skFormat == colorType;
1612     });
1613     if (findItem == COLOR_TYPE_MAP.end()) {
1614         return false;
1615     }
1616     format = findItem->second.skFormat;
1617     outputFormat = findItem->second.outFormat;
1618     return true;
1619 }
1620 
1621 SkAlphaType ExtDecoder::ConvertToAlphaType(AlphaType desiredType, AlphaType &outputType)
1622 {
1623     if (desiredType != AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) {
1624         auto alphaType = ALPHA_TYPE_MAP.find(desiredType);
1625         if (alphaType != ALPHA_TYPE_MAP.end()) {
1626             outputType = alphaType->first;
1627             return alphaType->second;
1628         }
1629     }
1630     IMAGE_LOGD("Unknown alpha type:%{public}d", desiredType);
1631     SkAlphaType res;
1632     if (ConvertInfoToAlphaType(res, outputType)) {
1633         IMAGE_LOGD("Using alpha type:%{public}d", outputType);
1634         return res;
1635     }
1636     IMAGE_LOGD("Using default alpha type:%{public}d", AlphaType::IMAGE_ALPHA_TYPE_PREMUL);
1637     outputType = AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
1638     return SkAlphaType::kPremul_SkAlphaType;
1639 }
1640 
1641 SkColorType ExtDecoder::ConvertToColorType(PixelFormat format, PixelFormat &outputFormat)
1642 {
1643     if (format != PixelFormat::UNKNOWN) {
1644         auto colorType = COLOR_TYPE_MAP.find(format);
1645         if (colorType != COLOR_TYPE_MAP.end()) {
1646             outputFormat = colorType->second.outFormat;
1647             return colorType->second.skFormat;
1648         }
1649     }
1650     IMAGE_LOGD("Unknown pixel format:%{public}d", format);
1651     SkColorType res;
1652     if (ConvertInfoToColorType(res, outputFormat)) {
1653         IMAGE_LOGD("Using pixel format:%{public}d", outputFormat);
1654         return res;
1655     }
1656     IMAGE_LOGD("Using default pixel format:%{public}d", PixelFormat::RGBA_8888);
1657     outputFormat = PixelFormat::RGBA_8888;
1658     return kRGBA_8888_SkColorType;
1659 }
1660 // LCOV_EXCL_STOP
1661 
1662 #ifdef IMAGE_COLORSPACE_FLAG
1663 static uint32_t u8ToU32(const uint8_t* p)
1664 {
1665     return (p[OFFSET_0] << SHIFT_BITS_24) | (p[OFFSET_1] << SHIFT_BITS_16) |
1666         (p[OFFSET_2] << SHIFT_BITS_8) | p[OFFSET_3];
1667 }
1668 
1669 struct ICCTag {
1670     uint8_t signature[SIZE_4];
1671     uint8_t offset[SIZE_4];
1672     uint8_t size[SIZE_4];
1673 };
1674 
1675 struct ColorSpaceNameEnum {
1676     std::string desc;
1677     OHOS::ColorManager::ColorSpaceName name;
1678 };
1679 
1680 static std::vector<ColorSpaceNameEnum> sColorSpaceNamedMap = {
1681     {"Display P3", OHOS::ColorManager::ColorSpaceName::DISPLAY_P3},
1682     {"sRGB EOTF with DCI-P3 Color Gamut", OHOS::ColorManager::ColorSpaceName::DISPLAY_P3},
1683     {"DCI-P3 D65 Gamut with sRGB Transfer", OHOS::ColorManager::ColorSpaceName::DISPLAY_P3},
1684     {"Adobe RGB (1998)", OHOS::ColorManager::ColorSpaceName::ADOBE_RGB},
1685     {"DCI P3", OHOS::ColorManager::ColorSpaceName::DCI_P3},
1686     {"sRGB", OHOS::ColorManager::ColorSpaceName::SRGB}
1687     /*{"BT.2020", OHOS::ColorManager::ColorSpaceName::BT2020}*/
1688 };
1689 
1690 static bool MatchColorSpaceName(const uint8_t* buf, uint32_t size, OHOS::ColorManager::ColorSpaceName &name)
1691 {
1692     if (buf == nullptr || size <= OFFSET_5) {
1693         return false;
1694     }
1695     std::vector<char> desc;
1696     // We need skip desc type
1697     for (uint32_t i = OFFSET_5; i < size; i++) {
1698         if (buf[i] != '\0') {
1699             desc.push_back(buf[i]);
1700         }
1701     }
1702     if (desc.size() <= SIZE_1) {
1703         IMAGE_LOGI("empty buffer");
1704         return false;
1705     }
1706     std::string descText(desc.begin() + OFFSET_1, desc.end());
1707     for (auto nameEnum : sColorSpaceNamedMap) {
1708         if (descText.find(nameEnum.desc) == std::string::npos) {
1709             continue;
1710         }
1711         name = nameEnum.name;
1712         return true;
1713     }
1714     IMAGE_LOGE("Failed to match desc");
1715     return false;
1716 }
1717 
1718 static bool GetColorSpaceName(const skcms_ICCProfile* profile, OHOS::ColorManager::ColorSpaceName &name)
1719 {
1720     if (profile == nullptr || profile->buffer == nullptr) {
1721         IMAGE_LOGD("profile is nullptr");
1722         return false;
1723     }
1724     auto tags = reinterpret_cast<const ICCTag*>(profile->buffer + ICC_HEADER_SIZE);
1725     for (uint32_t i = SIZE_ZERO; i < profile->tag_count; i++) {
1726         auto signature = u8ToU32(tags[i].signature);
1727         if (signature != DESC_SIGNATURE) {
1728             continue;
1729         }
1730         auto size = u8ToU32(tags[i].size);
1731         auto offset = u8ToU32(tags[i].offset);
1732         if (size == SIZE_ZERO || offset >= profile->size) {
1733             continue;
1734         }
1735         auto buffer = u8ToU32(tags[i].offset) + profile->buffer;
1736         if (MatchColorSpaceName(buffer, size, name)) {
1737             return true;
1738         }
1739     }
1740     return false;
1741 }
1742 
1743 static OHOS::ColorManager::ColorSpaceName GetHeifNclxColor(SkCodec* codec)
1744 {
1745 #ifdef HEIF_HW_DECODE_ENABLE
1746     auto decoder = reinterpret_cast<HeifDecoder *>(codec->getHeifContext());
1747     if (decoder == nullptr) {
1748         return ColorManager::NONE;
1749     }
1750     HeifFrameInfo info;
1751     if (!decoder->getImageInfo(&info)) {
1752         return ColorManager::NONE;
1753     }
1754     if (info.hasNclxColor) {
1755         return ColorUtils::CicpToColorSpace(info.nclxColor.colorPrimaries, info.nclxColor.transferCharacteristics,
1756             info.nclxColor.matrixCoefficients, info.nclxColor.fullRangeFlag);
1757     }
1758 #endif
1759     return ColorManager::NONE;
1760 }
1761 
1762 OHOS::ColorManager::ColorSpace ExtDecoder::GetSrcColorSpace()
1763 {
1764     auto skColorSpace = dstInfo_.isEmpty() ? info_.refColorSpace() : dstInfo_.refColorSpace();
1765     OHOS::ColorManager::ColorSpaceName name = OHOS::ColorManager::ColorSpaceName::CUSTOM;
1766     if (codec_ != nullptr) {
1767         auto profile = codec_->getICCProfile();
1768         if (profile != nullptr) {
1769             IMAGE_LOGD("profile got !!!!");
1770             GetColorSpaceName(profile, name);
1771         }
1772         if (profile != nullptr && profile->has_CICP) {
1773             ColorManager::ColorSpaceName cName = Media::ColorUtils::CicpToColorSpace(profile->cicp.colour_primaries,
1774                 profile->cicp.transfer_characteristics, profile->cicp.matrix_coefficients,
1775                 profile->cicp.full_range_flag);
1776             if (cName != ColorManager::NONE) {
1777                 return ColorManager::ColorSpace(skColorSpace, cName);
1778             }
1779         }
1780         if (codec_->getEncodedFormat() == SkEncodedImageFormat::kHEIF) {
1781             ColorManager::ColorSpaceName cName = GetHeifNclxColor(codec_.get());
1782             if (cName != ColorManager::NONE) {
1783                 return ColorManager::ColorSpace(skColorSpace, cName);
1784             }
1785         }
1786     }
1787     return OHOS::ColorManager::ColorSpace(skColorSpace, name);
1788 }
1789 
1790 OHOS::ColorManager::ColorSpace ExtDecoder::GetPixelMapColorSpace()
1791 {
1792     if (dstColorSpace_ != nullptr) {
1793         if (srcColorSpace_ == nullptr) {
1794             auto colorSpace = GetSrcColorSpace();
1795             srcColorSpace_ = std::make_shared<OHOS::ColorManager::ColorSpace>(colorSpace);
1796         }
1797         return *dstColorSpace_;
1798     }
1799     return GetSrcColorSpace();
1800 }
1801 
1802 bool ExtDecoder::IsSupportICCProfile()
1803 {
1804     if (dstColorSpace_ != nullptr) {
1805         return true;
1806     }
1807     if (info_.isEmpty()) {
1808         return false;
1809     }
1810     return info_.refColorSpace() != nullptr;
1811 }
1812 #endif
1813 
1814 static uint32_t ProcessWithStreamData(InputDataStream *input,
1815     std::function<uint32_t(uint8_t*, size_t)> process)
1816 {
1817     size_t inputSize = input->GetStreamSize();
1818     if (inputSize == SIZE_ZERO) {
1819         return Media::ERR_MEDIA_INVALID_VALUE;
1820     }
1821 
1822     size_t copySize = std::min(inputSize, SMALL_FILE_SIZE);
1823     auto tmpBuffer = std::make_unique<uint8_t[]>(copySize);
1824     auto savePos = input->Tell();
1825     input->Seek(SIZE_ZERO);
1826     uint32_t readSize = 0;
1827     bool ret = input->Read(copySize, tmpBuffer.get(), copySize, readSize);
1828     input->Seek(savePos);
1829     if (!ret) {
1830         IMAGE_LOGE("InputDataStream read failed.");
1831         return Media::ERR_IMAGE_DATA_ABNORMAL;
1832     }
1833     return process(tmpBuffer.get(), copySize);
1834 }
1835 
1836 static bool ParseExifData(InputDataStream *input, EXIFInfo &info)
1837 {
1838     if (info.IsExifDataParsed()) {
1839         return true;
1840     }
1841     IMAGE_LOGD("ParseExifData enter");
1842     auto code = ProcessWithStreamData(input, [&info](uint8_t* buffer, size_t size) {
1843         return info.ParseExifData(buffer, size);
1844     });
1845     if (code != SUCCESS) {
1846         IMAGE_LOGE("Error parsing EXIF: code %{public}d", code);
1847     }
1848     return code == SUCCESS;
1849 }
1850 
1851 bool ExtDecoder::GetPropertyCheck(uint32_t index, const std::string &key, uint32_t &res)
1852 {
1853     if (IsSameTextStr(key, ACTUAL_IMAGE_ENCODED_FORMAT)) {
1854         res = Media::ERR_MEDIA_VALUE_INVALID;
1855         return false;
1856     }
1857     if (!CheckIndexValied(index)) {
1858         res = Media::ERR_IMAGE_DECODE_HEAD_ABNORMAL;
1859         return false;
1860     }
1861     SkEncodedImageFormat format = codec_->getEncodedFormat();
1862     if (format != SkEncodedImageFormat::kJPEG) {
1863         res = Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
1864         return true;
1865     }
1866     if (ENCODED_FORMAT_KEY.compare(key) == ZERO) {
1867         res = Media::ERR_MEDIA_VALUE_INVALID;
1868         return true;
1869     }
1870     auto result = ParseExifData(stream_, exifInfo_);
1871     if (!result) {
1872         res = Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
1873     }
1874     return result;
1875 }
1876 
1877 // LCOV_EXCL_START
1878 static uint32_t GetDelayTime(SkCodec * codec, uint32_t index, int32_t &value)
1879 {
1880     if (codec->getEncodedFormat() != SkEncodedImageFormat::kGIF &&
1881         codec->getEncodedFormat() != SkEncodedImageFormat::kWEBP) {
1882         IMAGE_LOGE("[GetDelayTime] Should not get delay time in %{public}d", codec->getEncodedFormat());
1883         return ERR_MEDIA_INVALID_PARAM;
1884     }
1885     auto frameInfos = codec->getFrameInfo();
1886     if (index > frameInfos.size() - 1) {
1887         IMAGE_LOGE("[GetDelayTime] frame size %{public}zu, index:%{public}d", frameInfos.size(), index);
1888         return ERR_MEDIA_INVALID_PARAM;
1889     }
1890     value = frameInfos[index].fDuration;
1891     IMAGE_LOGD("[GetDelayTime] index[%{public}d]:%{public}d", index, value);
1892     return SUCCESS;
1893 }
1894 
1895 static uint32_t GetDisposalType(SkCodec * codec, uint32_t index, int32_t &value)
1896 {
1897     if (codec->getEncodedFormat() != SkEncodedImageFormat::kGIF) {
1898         IMAGE_LOGE("[GetDisposalType] Should not get disposal type in %{public}d", codec->getEncodedFormat());
1899         return ERR_MEDIA_INVALID_PARAM;
1900     }
1901     auto frameInfos = codec->getFrameInfo();
1902     if (index > frameInfos.size() - 1) {
1903         IMAGE_LOGE("[GetDisposalType] frame size %{public}zu, index:%{public}d", frameInfos.size(), index);
1904         return ERR_MEDIA_INVALID_PARAM;
1905     }
1906     value = static_cast<int>(frameInfos[index].fDisposalMethod);
1907     IMAGE_LOGD("[GetDisposalType] index[%{public}d]:%{public}d", index, value);
1908     return SUCCESS;
1909 }
1910 // LCOV_EXCL_STOP
1911 
1912 static uint32_t GetLoopCount(SkCodec *codec, int32_t &value)
1913 {
1914     if (codec->getEncodedFormat() != SkEncodedImageFormat::kGIF) {
1915         IMAGE_LOGE("[GetLoopCount] Should not get loop count in %{public}d", codec->getEncodedFormat());
1916         return ERR_MEDIA_INVALID_PARAM;
1917     }
1918     auto count = codec->getRepetitionCount();
1919     if (count == LOOP_COUNT_INFINITE || count <= SK_REPETITION_COUNT_ERROR_VALUE) {
1920         IMAGE_LOGE("[GetLoopCount] getRepetitionCount error");
1921         return ERR_IMAGE_SOURCE_DATA;
1922     }
1923     if (count == SK_REPETITION_COUNT_INFINITE) {
1924         count = LOOP_COUNT_INFINITE;
1925     }
1926     value = static_cast<int>(count);
1927     return SUCCESS;
1928 }
1929 
1930 // LCOV_EXCL_START
1931 uint32_t ExtDecoder::GetImagePropertyInt(uint32_t index, const std::string &key, int32_t &value)
1932 {
1933     IMAGE_LOGD("[GetImagePropertyInt] enter ExtDecoder plugin, key:%{public}s", key.c_str());
1934     uint32_t res = Media::ERR_IMAGE_DATA_ABNORMAL;
1935     if (!GetPropertyCheck(index, key, res)) {
1936         return res;
1937     }
1938     if (IMAGE_DELAY_TIME.compare(key) == ZERO) {
1939         return GetDelayTime(codec_.get(), index, value);
1940     }
1941     if (IMAGE_DISPOSAL_TYPE.compare(key) == ZERO) {
1942         return GetDisposalType(codec_.get(), index, value);
1943     }
1944     if (IMAGE_LOOP_COUNT.compare(key) == ZERO) {
1945         return GetLoopCount(codec_.get(), value);
1946     }
1947     // There can add some not need exif property
1948     if (res == Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT) {
1949         return res;
1950     }
1951     // Need exif property following
1952     if (IsSameTextStr(key, TAG_ORIENTATION_STRING)) {
1953         std::string strValue;
1954         res = exifInfo_.GetExifData(TAG_ORIENTATION_INT, strValue);
1955         if (res != SUCCESS) {
1956             return res;
1957         }
1958         value = atoi(strValue.c_str());
1959         return res;
1960     }
1961     IMAGE_LOGE("[GetImagePropertyInt] The key:%{public}s is not supported int32_t", key.c_str());
1962     return Media::ERR_MEDIA_VALUE_INVALID;
1963 }
1964 
1965 uint32_t ExtDecoder::GetImagePropertyString(uint32_t index, const std::string &key, std::string &value)
1966 {
1967     IMAGE_LOGD("[GetImagePropertyString] enter jpeg plugin, key:%{public}s", key.c_str());
1968     uint32_t res = Media::ERR_IMAGE_DATA_ABNORMAL;
1969     if (!GetPropertyCheck(index, key, res)) {
1970         return res;
1971     }
1972     // There can add some not need exif property
1973     if (ENCODED_FORMAT_KEY.compare(key) == ZERO) {
1974         SkEncodedImageFormat format = codec_->getEncodedFormat();
1975         return GetFormatName(format, value);
1976     } else if (IMAGE_DELAY_TIME.compare(key) == ZERO) {
1977         int delayTime = ZERO;
1978         res = GetDelayTime(codec_.get(), index, delayTime);
1979         value = std::to_string(delayTime);
1980         return res;
1981     } else if (IMAGE_DISPOSAL_TYPE.compare(key) == ZERO) {
1982         int disposalType = ZERO;
1983         res = GetDisposalType(codec_.get(), index, disposalType);
1984         value = std::to_string(disposalType);
1985         return res;
1986     } else if (IMAGE_LOOP_COUNT.compare(key) == ZERO) {
1987         int loopCount = ZERO;
1988         res = GetLoopCount(codec_.get(), loopCount);
1989         value = std::to_string(loopCount);
1990         return res;
1991     }
1992     if (res == Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT) {
1993         return res;
1994     }
1995     // Need exif property following
1996     if (key.find(HW_MNOTE_TAG_HEADER) != std::string::npos) {
1997         res = GetMakerImagePropertyString(key, value);
1998         if (value.length() == 0) {
1999             value = DEFAULT_EXIF_VALUE;
2000             IMAGE_LOGE("[GetImagePropertyString]The image does not contain the %{public}s  tag ", key.c_str());
2001         }
2002         return res;
2003     }
2004     res = exifInfo_.GetExifData(key, value);
2005     IMAGE_LOGD("[GetImagePropertyString] enter jpeg plugin, value:%{public}s", value.c_str());
2006     return res;
2007 }
2008 // LCOV_EXCL_STOP
2009 
2010 uint32_t ExtDecoder::GetMakerImagePropertyString(const std::string &key, std::string &value)
2011 {
2012     if (exifInfo_.makerInfoTagValueMap.find(key) != exifInfo_.makerInfoTagValueMap.end()) {
2013         value = exifInfo_.makerInfoTagValueMap[key];
2014         return SUCCESS;
2015     }
2016     return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
2017 }
2018 
2019 uint32_t ExtDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
2020     const std::string &value, const std::string &path)
2021 {
2022     IMAGE_LOGD("[ModifyImageProperty] with key:%{public}s", key.c_str());
2023     return exifInfo_.ModifyExifData(key, value, path);
2024 }
2025 
2026 uint32_t ExtDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
2027     const std::string &value, const int fd)
2028 {
2029     IMAGE_LOGD("[ModifyImageProperty] with fd:%{public}d, key:%{public}s, value:%{public}s",
2030         fd, key.c_str(), value.c_str());
2031     return exifInfo_.ModifyExifData(key, value, fd);
2032 }
2033 
2034 uint32_t ExtDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
2035     const std::string &value, uint8_t *data, uint32_t size)
2036 {
2037     IMAGE_LOGD("[ModifyImageProperty] with key:%{public}s, value:%{public}s",
2038         key.c_str(), value.c_str());
2039     return exifInfo_.ModifyExifData(key, value, data, size);
2040 }
2041 
2042 uint32_t ExtDecoder::GetFilterArea(const int &privacyType, std::vector<std::pair<uint32_t, uint32_t>> &ranges)
2043 {
2044     IMAGE_LOGD("[GetFilterArea] with privacyType:%{public}d ", privacyType);
2045     if (!CheckCodec()) {
2046         IMAGE_LOGD("[GetFilterArea] Check codec failed");
2047         return NO_EXIF_TAG;
2048     }
2049     SkEncodedImageFormat format = codec_->getEncodedFormat();
2050     if (format != SkEncodedImageFormat::kJPEG) {
2051         return NO_EXIF_TAG;
2052     }
2053     constexpr size_t APP1_SIZE_H_OFF = 4;
2054     constexpr size_t APP1_SIZE_L_OFF = 5;
2055     constexpr size_t U8_SHIFT = 8;
2056     return ProcessWithStreamData(stream_, [this, &privacyType, &ranges](uint8_t* buffer, size_t size) {
2057         size_t appSize = (static_cast<size_t>(buffer[APP1_SIZE_H_OFF]) << U8_SHIFT) | buffer[APP1_SIZE_L_OFF];
2058         IMAGE_LOGD("[GetFilterArea]: get app1 area size");
2059         appSize += APP1_SIZE_H_OFF;
2060         auto ret = exifInfo_.GetFilterArea(buffer, (appSize < size) ? appSize : size, privacyType, ranges);
2061         if (ret != SUCCESS) {
2062             IMAGE_LOGE("[GetFilterArea]: failed to get area %{public}d", ret);
2063         }
2064         return ret;
2065     });
2066 }
2067 
2068 uint32_t ExtDecoder::GetTopLevelImageNum(uint32_t &num)
2069 {
2070     if (!CheckIndexValied(SIZE_ZERO) && frameCount_ <= ZERO) {
2071         return ERR_IMAGE_DECODE_HEAD_ABNORMAL;
2072     }
2073     num = static_cast<uint32_t>(frameCount_);
2074     return SUCCESS;
2075 }
2076 
2077 // LCOV_EXCL_START
2078 bool ExtDecoder::IsSupportHardwareDecode() {
2079     if (info_.isEmpty() && !DecodeHeader()) {
2080         return false;
2081     }
2082     if (!(ImageSystemProperties::GetHardWareDecodeEnabled()
2083         && codec_->getEncodedFormat() == SkEncodedImageFormat::kJPEG)) {
2084         return false;
2085     }
2086     int width = info_.width();
2087     int height = info_.height();
2088     return width >= HARDWARE_MIN_DIM && width <= HARDWARE_MAX_DIM
2089         && height >= HARDWARE_MIN_DIM && height <= HARDWARE_MAX_DIM;
2090 }
2091 // LCOV_EXCL_STOP
2092 
2093 bool ExtDecoder::IsYuv420Format(PixelFormat format) const
2094 {
2095     if (format == PixelFormat::NV12 || format == PixelFormat::NV21) {
2096         return true;
2097     }
2098     return false;
2099 }
2100 
2101 bool ExtDecoder::IsHeifToYuvDecode(const DecodeContext &context) const
2102 {
2103     return codec_->getEncodedFormat() == SkEncodedImageFormat::kHEIF && IsYuv420Format(context.info.pixelFormat);
2104 }
2105 
2106 uint32_t ExtDecoder::DoHeifToYuvDecode(OHOS::ImagePlugin::DecodeContext &context)
2107 {
2108 #ifdef HEIF_HW_DECODE_ENABLE
2109     auto decoder = reinterpret_cast<HeifDecoder*>(codec_->getHeifContext());
2110     if (decoder == nullptr) {
2111         IMAGE_LOGE("YUV Decode HeifDecoder is nullptr");
2112         return ERR_IMAGE_DATA_UNSUPPORT;
2113     }
2114     if (ImageUtils::IsSdrPixelMapReuseSuccess(context, info_.width(), info_.height(), reusePixelmap_)) {
2115         IMAGE_LOGI("DoHeifToYuvDecode reusePixelmap success");
2116     } else {
2117         uint32_t allocRet = HeifYUVMemAlloc(context);
2118         if (allocRet != SUCCESS) {
2119             return allocRet;
2120         }
2121     }
2122     auto dstBuffer = reinterpret_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
2123     decoder->setOutputColor(context.info.pixelFormat
2124         == PixelFormat::NV12 ? kHeifColorFormat_NV12 : kHeifColorFormat_NV21);
2125     decoder->setDstBuffer(reinterpret_cast<uint8_t *>(context.pixelsBuffer.buffer),
2126                           dstBuffer->GetStride(), context.pixelsBuffer.context);
2127     bool decodeRet = decoder->decode(nullptr);
2128     if (!decodeRet) {
2129         decoder->getErrMsg(context.hardDecodeError);
2130     }
2131     return decodeRet ? SUCCESS : ERR_IMAGE_DATA_UNSUPPORT;
2132 #else
2133     return ERR_IMAGE_DATA_UNSUPPORT;
2134 #endif
2135 }
2136 
2137 bool ExtDecoder::IsHeifToSingleHdrDecode(const DecodeContext& context) const
2138 {
2139     return codec_->getEncodedFormat() == SkEncodedImageFormat::kHEIF &&
2140         (context.info.pixelFormat == PixelFormat::RGBA_1010102 ||
2141          context.info.pixelFormat == PixelFormat::YCBCR_P010 ||
2142          context.info.pixelFormat == PixelFormat::YCRCB_P010);
2143 }
2144 
2145 uint32_t ExtDecoder::DoHeifToSingleHdrDecode(DecodeContext &context)
2146 {
2147 #ifdef HEIF_HW_DECODE_ENABLE
2148     auto decoder = reinterpret_cast<HeifDecoder*>(codec_->getHeifContext());
2149     if (decoder == nullptr) {
2150         IMAGE_LOGE("SingleHdrDecode, HeifDecoder is nullptr");
2151         return ERR_IMAGE_DATA_UNSUPPORT;
2152     }
2153 
2154     uint64_t byteCount = static_cast<uint64_t>(info_.computeMinByteSize());
2155     if (context.info.pixelFormat == PixelFormat::YCBCR_P010 || context.info.pixelFormat == PixelFormat::YCRCB_P010) {
2156         uint32_t allocRet = HeifYUVMemAlloc(context);
2157         if (allocRet != SUCCESS) {
2158             return allocRet;
2159         }
2160     } else {
2161         if (DmaMemAlloc(context, byteCount, info_) != SUCCESS) {
2162             return ERR_IMAGE_DATA_UNSUPPORT;
2163         }
2164     }
2165 
2166     auto dstBuffer = reinterpret_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
2167     SkHeifColorFormat heifFormat = kHeifColorFormat_RGBA_1010102;
2168     auto formatSearch = HEIF_FORMAT_MAP.find(context.info.pixelFormat);
2169     heifFormat = (formatSearch != HEIF_FORMAT_MAP.end()) ? formatSearch->second : kHeifColorFormat_RGBA_1010102;
2170     decoder->setOutputColor(heifFormat);
2171     decoder->setDstBuffer(reinterpret_cast<uint8_t*>(context.pixelsBuffer.buffer),
2172         dstBuffer->GetStride(), context.pixelsBuffer.context);
2173     bool decodeRet = decoder->decode(nullptr);
2174     if (!decodeRet) {
2175         decoder->getErrMsg(context.hardDecodeError);
2176     }
2177     return decodeRet ? SUCCESS : ERR_IMAGE_DATA_UNSUPPORT;
2178 #else
2179     return ERR_IMAGE_DATA_UNSUPPORT;
2180 #endif
2181 }
2182 
2183 ImageHdrType ExtDecoder::CheckHdrType()
2184 {
2185 #if defined(_WIN32) || defined(_APPLE) || defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
2186     return Media::ImageHdrType::SDR;
2187 #else
2188     if (!CheckCodec()) {
2189         return Media::ImageHdrType::UNKNOWN;
2190     }
2191     SkEncodedImageFormat format = codec_->getEncodedFormat();
2192     if (format != SkEncodedImageFormat::kJPEG && format != SkEncodedImageFormat::kHEIF) {
2193         hdrType_ = Media::ImageHdrType::SDR;
2194         gainMapOffset_ = 0;
2195         return hdrType_;
2196     }
2197     hdrType_ = HdrHelper::CheckHdrType(codec_.get(), gainMapOffset_);
2198     return hdrType_;
2199 #endif
2200 }
2201 
2202 uint32_t ExtDecoder::GetGainMapOffset()
2203 {
2204 #if defined(_WIN32) || defined(_APPLE) || defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
2205     return OFFSET_0;
2206 #else
2207     if (codec_ == nullptr || codec_->getEncodedFormat() != SkEncodedImageFormat::kJPEG) {
2208         return 0;
2209     }
2210     if (hdrType_ == Media::ImageHdrType::UNKNOWN) {
2211         hdrType_ = HdrHelper::CheckHdrType(codec_.get(), gainMapOffset_);
2212     }
2213     return gainMapOffset_;
2214 #endif
2215 }
2216 
2217 HdrMetadata ExtDecoder::GetHdrMetadata(Media::ImageHdrType type)
2218 {
2219 #if defined(_WIN32) || defined(_APPLE) || defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
2220     return {};
2221 #else
2222     HdrMetadata metadata = {};
2223     if (type > Media::ImageHdrType::SDR && HdrHelper::GetMetadata(codec_.get(), type, metadata)) {
2224         return metadata;
2225     }
2226     IMAGE_LOGD("get hdr metadata failed, type is %{public}d, flag is %{public}d", type, metadata.extendMetaFlag);
2227     return {};
2228 #endif
2229 }
2230 
2231 bool ExtDecoder::GetHeifFragmentMetadata(Media::Rect &metadata)
2232 {
2233 #ifdef HEIF_HW_DECODE_ENABLE
2234     if (codec_ == nullptr || codec_->getEncodedFormat() != SkEncodedImageFormat::kHEIF) {
2235         IMAGE_LOGE("Check codec_ failed!");
2236         return false;
2237     }
2238 
2239     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
2240     if (decoder == nullptr) {
2241         IMAGE_LOGE("Get heif decoder failed.");
2242         return false;
2243     }
2244 
2245     decoder->getFragmentMetadata(metadata);
2246     return true;
2247 #endif
2248     return false;
2249 }
2250 
2251 bool ExtDecoder::DecodeHeifGainMap(DecodeContext& context)
2252 {
2253 #ifdef HEIF_HW_DECODE_ENABLE
2254     if (codec_ == nullptr || codec_->getEncodedFormat() != SkEncodedImageFormat::kHEIF) {
2255         IMAGE_LOGE("decode heif gainmap, codec error");
2256         return false;
2257     }
2258     auto decoder = reinterpret_cast<HeifDecoder*>(codec_->getHeifContext());
2259     if (decoder == nullptr) {
2260         IMAGE_LOGE("decode heif gainmap, decoder error");
2261         return false;
2262     }
2263     HeifFrameInfo gainmapInfo;
2264     decoder->getGainmapInfo(&gainmapInfo);
2265     uint32_t width = gainmapInfo.mWidth;
2266     uint32_t height = gainmapInfo.mHeight;
2267     if (width > INT_MAX || height > INT_MAX) {
2268         IMAGE_LOGI("DecodeHeifGainmap size exceeds the maximum value");
2269         return false;
2270     }
2271     IMAGE_LOGD("DecodeHeifGainmap size:%{public}d-%{public}d", width, height);
2272     SkImageInfo dstInfo = SkImageInfo::Make(static_cast<int>(width), static_cast<int>(height),
2273         dstInfo_.colorType(), dstInfo_.alphaType(), dstInfo_.refColorSpace());
2274     uint64_t byteCount = static_cast<uint64_t>(dstInfo.computeMinByteSize());
2275     context.info.size.width = width;
2276     context.info.size.height = height;
2277     if (DmaMemAlloc(context, byteCount, dstInfo) != SUCCESS) {
2278         return false;
2279     }
2280     auto* dstBuffer = static_cast<uint8_t*>(context.pixelsBuffer.buffer);
2281     auto* sbBuffer = reinterpret_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
2282     int32_t rowStride = sbBuffer->GetStride();
2283     if (rowStride <= 0) {
2284         return false;
2285     }
2286     decoder->setGainmapDstBuffer(dstBuffer, static_cast<size_t>(rowStride));
2287     if (!decoder->decodeGainmap()) {
2288         return false;
2289     }
2290     return true;
2291 #endif
2292     return false;
2293 }
2294 
2295 bool ExtDecoder::GetHeifHdrColorSpace(ColorManager::ColorSpaceName& gainmap, ColorManager::ColorSpaceName& hdr)
2296 {
2297 #ifdef HEIF_HW_DECODE_ENABLE
2298     if (codec_ == nullptr || codec_->getEncodedFormat() != SkEncodedImageFormat::kHEIF) {
2299         return false;
2300     }
2301     auto decoder = reinterpret_cast<HeifDecoder*>(codec_->getHeifContext());
2302     if (decoder == nullptr) {
2303         return false;
2304     }
2305     HeifFrameInfo gainmapInfo;
2306     decoder->getGainmapInfo(&gainmapInfo);
2307     if (gainmapInfo.hasNclxColor) {
2308         gainmap = ColorUtils::CicpToColorSpace(gainmapInfo.nclxColor.colorPrimaries,
2309             gainmapInfo.nclxColor.transferCharacteristics, gainmapInfo.nclxColor.matrixCoefficients,
2310             gainmapInfo.nclxColor.fullRangeFlag);
2311     }
2312     HeifFrameInfo tmapInfo;
2313     decoder->getTmapInfo(&tmapInfo);
2314     if (tmapInfo.hasNclxColor) {
2315         hdr = ColorUtils::CicpToColorSpace(tmapInfo.nclxColor.colorPrimaries,
2316             tmapInfo.nclxColor.transferCharacteristics, tmapInfo.nclxColor.matrixCoefficients,
2317             tmapInfo.nclxColor.fullRangeFlag);
2318     }
2319     return true;
2320 #endif
2321     return false;
2322 }
2323 
2324 uint32_t ExtDecoder::GetHeifParseErr()
2325 {
2326     return heifParseErr_;
2327 }
2328 
2329 void ExtDecoder::SetHeifDecodeError(OHOS::ImagePlugin::DecodeContext &context)
2330 {
2331 #ifdef HEIF_HW_DECODE_ENABLE
2332     if (codec_ == nullptr || codec_->getEncodedFormat() != SkEncodedImageFormat::kHEIF) {
2333         return;
2334     }
2335     auto decoder = reinterpret_cast<HeifDecoder*>(codec_->getHeifContext());
2336     if (decoder == nullptr) {
2337         return;
2338     }
2339     decoder->getErrMsg(context.hardDecodeError);
2340 #endif
2341 }
2342 
2343 void ExtDecoder::SetHeifParseError()
2344 {
2345     if (stream_ == nullptr) {
2346         return;
2347     }
2348     uint32_t originOffset = stream_->Tell();
2349     stream_->Seek(0);
2350 
2351     uint32_t readSize = 0;
2352     HeifFormatAgent agent;
2353     uint32_t headerSize = agent.GetHeaderSize();
2354     uint8_t headerBuf[headerSize];
2355     bool readRet = stream_->Peek(headerSize, headerBuf, headerSize, readSize);
2356     if (!readRet || readSize != headerSize) {
2357         stream_->Seek(originOffset);
2358         return;
2359     }
2360 
2361     if (!agent.CheckFormat(headerBuf, headerSize)) {
2362         stream_->Seek(originOffset);
2363         return;
2364     }
2365 
2366     size_t fileLength = stream_->GetStreamSize();
2367     if (fileLength <= 0) {
2368         return;
2369     }
2370     uint8_t *fileMem = reinterpret_cast<uint8_t*>(malloc(fileLength));
2371     if (fileMem == nullptr) {
2372         return;
2373     }
2374     readRet = stream_->Read(fileLength, fileMem, fileLength, readSize);
2375     if (!readRet || readSize != fileLength) {
2376         stream_->Seek(originOffset);
2377         free(fileMem);
2378         return;
2379     }
2380 
2381     std::shared_ptr<HeifParser> parser;
2382     heif_error parseRet = HeifParser::MakeFromMemory(fileMem, fileLength, false, &parser);
2383     if (parseRet != heif_error_ok) {
2384         heifParseErr_ = static_cast<uint32_t>(parseRet);
2385     }
2386 
2387     stream_->Seek(originOffset);
2388     free(fileMem);
2389 }
2390 
2391 bool ExtDecoder::CheckAuxiliaryMap(AuxiliaryPictureType type)
2392 {
2393 #ifdef HEIF_HW_DECODE_ENABLE
2394     if (codec_ == nullptr || codec_->getEncodedFormat() != SkEncodedImageFormat::kHEIF) {
2395         IMAGE_LOGE("Check heif auxiliaryMap failed! Invalid parameter, type %{public}d.", type);
2396         return false;
2397     }
2398 
2399     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
2400     if (decoder == nullptr) {
2401         IMAGE_LOGE("Get heif context failed, type %{public}d.", type);
2402         return false;
2403     }
2404 
2405     if (!decoder->CheckAuxiliaryMap(type)) {
2406         IMAGE_LOGE("Get heif auxiliary type %{public}d, decoder error", type);
2407         return false;
2408     }
2409     return true;
2410 #endif
2411     return false;
2412 }
2413 
2414 bool ExtDecoder::DecodeHeifAuxiliaryMap(DecodeContext& context, AuxiliaryPictureType type)
2415 {
2416 #ifdef HEIF_HW_DECODE_ENABLE
2417     if (codec_ == nullptr || codec_->getEncodedFormat() != SkEncodedImageFormat::kHEIF) {
2418         IMAGE_LOGE("decode heif auxiliaryMap type %{public}d, codec error", type);
2419         return false;
2420     }
2421 
2422     auto decoder = reinterpret_cast<HeifDecoderImpl*>(codec_->getHeifContext());
2423     if (decoder == nullptr) {
2424         IMAGE_LOGE("decode heif auxiliaryMap %{public}d, decoder error", type);
2425         return false;
2426     }
2427     if (!decoder->setAuxiliaryMap(type)) {
2428         IMAGE_LOGE("set auxiliary map type failed, type is %{public}d", type);
2429         return false;
2430     }
2431     HeifFrameInfo auxiliaryMapInfo;
2432     decoder->getAuxiliaryMapInfo(&auxiliaryMapInfo);
2433     uint32_t width = auxiliaryMapInfo.mWidth;
2434     uint32_t height = auxiliaryMapInfo.mHeight;
2435     if (width > INT_MAX || height > INT_MAX) {
2436         IMAGE_LOGI("DecodeHeifAuxiliaryMap size exceeds the maximum value");
2437         return false;
2438     }
2439     IMAGE_LOGD("DecodeHeifAuxiliaryMap size:%{public}d-%{public}d", width, height);
2440     SkImageInfo dstInfo = SkImageInfo::Make(static_cast<int>(width), static_cast<int>(height), dstInfo_.colorType(),
2441         dstInfo_.alphaType(), dstInfo_.refColorSpace());
2442     size_t tempByteCount = dstInfo.computeMinByteSize();
2443     if (SkImageInfo::ByteSizeOverflowed(tempByteCount)) {
2444         IMAGE_LOGE("Image too large, dstInfo_height: %{public}d, dstInfo_width: %{public}d",
2445             dstInfo.height(), dstInfo.width());
2446         return ERR_IMAGE_TOO_LARGE;
2447     }
2448     uint64_t byteCount = tempByteCount;
2449     context.info.size.width = width;
2450     context.info.size.height = height;
2451     if (DmaMemAlloc(context, byteCount, dstInfo) != SUCCESS) {
2452         IMAGE_LOGI("DmaMemAlloc execution failed.");
2453         return false;
2454     }
2455     auto* dstBuffer = static_cast<uint8_t*>(context.pixelsBuffer.buffer);
2456     auto* sbBuffer = reinterpret_cast<SurfaceBuffer*>(context.pixelsBuffer.context);
2457     int32_t rowStride = sbBuffer->GetStride();
2458     if (rowStride <= 0) {
2459         return false;
2460     }
2461     decoder->setAuxiliaryDstBuffer(dstBuffer, context.pixelsBuffer.bufferSize, static_cast<size_t>(rowStride));
2462     if (!decoder->decodeAuxiliaryMap()) {
2463         IMAGE_LOGE("Decoded auxiliary map type is not supported, or decoded failed. Type: %{public}d", type);
2464         return false;
2465     }
2466     context.outInfo.size.width = width;
2467     context.outInfo.size.height = height;
2468     return true;
2469 #endif
2470     return false;
2471 }
2472 } // namespace ImagePlugin
2473 } // namespace OHOS
2474