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