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