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