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