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