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
21 #include "ext_pixel_convert.h"
22 #include "image_log.h"
23 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
24 #include "hisysevent.h"
25 #endif
26 #include "image_system_properties.h"
27 #include "image_utils.h"
28 #include "media_errors.h"
29 #include "securec.h"
30 #include "string_ex.h"
31 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
32 #include "surface_buffer.h"
33 #endif
34
35 #undef LOG_DOMAIN
36 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_PLUGIN
37
38 #undef LOG_TAG
39 #define LOG_TAG "ExtDecoder"
40
41 namespace {
42 constexpr static int32_t ZERO = 0;
43 constexpr static int32_t NUM_3 = 3;
44 constexpr static int32_t NUM_4 = 4;
45 constexpr static int32_t OFFSET = 1;
46 constexpr static size_t SIZE_ZERO = 0;
47 constexpr static uint32_t DEFAULT_SAMPLE_SIZE = 1;
48 constexpr static uint32_t NO_EXIF_TAG = 1;
49 constexpr static uint32_t OFFSET_0 = 0;
50 constexpr static uint32_t OFFSET_1 = 1;
51 constexpr static uint32_t OFFSET_2 = 2;
52 constexpr static uint32_t OFFSET_3 = 3;
53 constexpr static uint32_t OFFSET_5 = 5;
54 constexpr static uint32_t SHIFT_BITS_8 = 8;
55 constexpr static uint32_t SHIFT_BITS_16 = 16;
56 constexpr static uint32_t SHIFT_BITS_24 = 24;
57 constexpr static uint32_t DESC_SIGNATURE = 0x64657363;
58 constexpr static size_t SIZE_1 = 1;
59 constexpr static size_t SIZE_4 = 4;
60 constexpr static int HARDWARE_MIN_DIM = 1024;
61 constexpr static int HARDWARE_MAX_DIM = 8192;
62 constexpr static float HALF = 0.5;
63 constexpr static float QUARTER = 0.25;
64 constexpr static float ONE_EIGHTH = 0.125;
65 constexpr static uint64_t ICC_HEADER_SIZE = 132;
66 }
67
68 namespace OHOS {
69 namespace ImagePlugin {
70 using namespace Media;
71 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
72 using namespace OHOS::HDI::Base;
73 #endif
74 using namespace std;
75 const static string DEFAULT_EXIF_VALUE = "default_exif_value";
76 const static string CODEC_INITED_KEY = "CodecInited";
77 const static string ENCODED_FORMAT_KEY = "EncodedFormat";
78 const static string SUPPORT_SCALE_KEY = "SupportScale";
79 const static string SUPPORT_CROP_KEY = "SupportCrop";
80 const static string EXT_SHAREMEM_NAME = "EXT RawData";
81 const static string TAG_ORIENTATION_STRING = "Orientation";
82 const static string TAG_ORIENTATION_INT = "OrientationInt";
83 const static string GIF_IMAGE_DELAY_TIME = "GIFDelayTime";
84 const static std::string HW_MNOTE_TAG_HEADER = "HwMnote";
85 const static std::string HW_MNOTE_CAPTURE_MODE = "HwMnoteCaptureMode";
86 const static std::string HW_MNOTE_PHYSICAL_APERTURE = "HwMnotePhysicalAperture";
87 const static std::string HW_MNOTE_TAG_ROLL_ANGLE = "HwMnoteRollAngle";
88 const static std::string HW_MNOTE_TAG_PITCH_ANGLE = "HwMnotePitchAngle";
89 const static std::string HW_MNOTE_TAG_SCENE_FOOD_CONF = "HwMnoteSceneFoodConf";
90 const static std::string HW_MNOTE_TAG_SCENE_STAGE_CONF = "HwMnoteSceneStageConf";
91 const static std::string HW_MNOTE_TAG_SCENE_BLUE_SKY_CONF = "HwMnoteSceneBlueSkyConf";
92 const static std::string HW_MNOTE_TAG_SCENE_GREEN_PLANT_CONF = "HwMnoteSceneGreenPlantConf";
93 const static std::string HW_MNOTE_TAG_SCENE_BEACH_CONF = "HwMnoteSceneBeachConf";
94 const static std::string HW_MNOTE_TAG_SCENE_SNOW_CONF = "HwMnoteSceneSnowConf";
95 const static std::string HW_MNOTE_TAG_SCENE_SUNSET_CONF = "HwMnoteSceneSunsetConf";
96 const static std::string HW_MNOTE_TAG_SCENE_FLOWERS_CONF = "HwMnoteSceneFlowersConf";
97 const static std::string HW_MNOTE_TAG_SCENE_NIGHT_CONF = "HwMnoteSceneNightConf";
98 const static std::string HW_MNOTE_TAG_SCENE_TEXT_CONF = "HwMnoteSceneTextConf";
99 const static std::string HW_MNOTE_TAG_FACE_COUNT = "HwMnoteFaceCount";
100 const static std::string HW_MNOTE_TAG_FOCUS_MODE = "HwMnoteFocusMode";
101 // SUCCESS is existed in both OHOS::HiviewDFX and OHOS::Media
102 #define SUCCESS OHOS::Media::SUCCESS
103 const static std::string DEFAULT_PACKAGE_NAME = "entry";
104 const static std::string DEFAULT_VERSION_ID = "1";
105 const static std::string UNKNOWN_IMAGE = "unknown";
106
107 struct ColorTypeOutput {
108 PlPixelFormat outFormat;
109 SkColorType skFormat;
110 };
111
112 static const map<PlPixelFormat, ColorTypeOutput> COLOR_TYPE_MAP = {
113 { PlPixelFormat::UNKNOWN, { PlPixelFormat::RGBA_8888, kRGBA_8888_SkColorType } },
114 { PlPixelFormat::RGBA_8888, { PlPixelFormat::RGBA_8888, kRGBA_8888_SkColorType } },
115 { PlPixelFormat::BGRA_8888, { PlPixelFormat::BGRA_8888, kBGRA_8888_SkColorType } },
116 { PlPixelFormat::ALPHA_8, { PlPixelFormat::ALPHA_8, kAlpha_8_SkColorType } },
117 { PlPixelFormat::RGB_565, { PlPixelFormat::RGB_565, kRGB_565_SkColorType } },
118 { PlPixelFormat::RGB_888, { PlPixelFormat::RGB_888, kRGB_888x_SkColorType } },
119 };
120
121 static const map<PlAlphaType, SkAlphaType> ALPHA_TYPE_MAP = {
122 { PlAlphaType::IMAGE_ALPHA_TYPE_OPAQUE, kOpaque_SkAlphaType },
123 { PlAlphaType::IMAGE_ALPHA_TYPE_PREMUL, kPremul_SkAlphaType },
124 { PlAlphaType::IMAGE_ALPHA_TYPE_UNPREMUL, kUnpremul_SkAlphaType },
125 };
126
127 static const map<SkEncodedImageFormat, string> FORMAT_NAME = {
128 { SkEncodedImageFormat::kBMP, "image/bmp" },
129 { SkEncodedImageFormat::kGIF, "image/gif" },
130 { SkEncodedImageFormat::kICO, "image/png" },
131 { SkEncodedImageFormat::kJPEG, "image/jpeg" },
132 { SkEncodedImageFormat::kPNG, "image/png" },
133 { SkEncodedImageFormat::kWBMP, "image/bmp" },
134 { SkEncodedImageFormat::kWEBP, "image/webp" },
135 { SkEncodedImageFormat::kPKM, "" },
136 { SkEncodedImageFormat::kKTX, "" },
137 { SkEncodedImageFormat::kASTC, "" },
138 { SkEncodedImageFormat::kDNG, "" },
139 { SkEncodedImageFormat::kHEIF, "image/heif" },
140 };
141
SetDecodeContextBuffer(DecodeContext & context,AllocatorType type,uint8_t * ptr,uint64_t count,void * fd)142 static void SetDecodeContextBuffer(DecodeContext &context,
143 AllocatorType type, uint8_t* ptr, uint64_t count, void* fd)
144 {
145 context.allocatorType = type;
146 context.freeFunc = nullptr;
147 context.pixelsBuffer.buffer = ptr;
148 context.pixelsBuffer.bufferSize = count;
149 context.pixelsBuffer.context = fd;
150 }
151
ShareMemAlloc(DecodeContext & context,uint64_t count)152 static uint32_t ShareMemAlloc(DecodeContext &context, uint64_t count)
153 {
154 #if defined(_WIN32) || defined(_APPLE) || defined(A_PLATFORM) || defined(IOS_PLATFORM)
155 IMAGE_LOGE("Unsupport share mem alloc");
156 return ERR_IMAGE_DATA_UNSUPPORT;
157 #else
158 auto fd = make_unique<int32_t>();
159 *fd = AshmemCreate(EXT_SHAREMEM_NAME.c_str(), count);
160 if (*fd < 0) {
161 IMAGE_LOGE("AshmemCreate failed");
162 return ERR_SHAMEM_DATA_ABNORMAL;
163 }
164 int result = AshmemSetProt(*fd, PROT_READ | PROT_WRITE);
165 if (result < 0) {
166 ::close(*fd);
167 IMAGE_LOGE("AshmemSetProt failed");
168 return ERR_SHAMEM_DATA_ABNORMAL;
169 }
170 void* ptr = ::mmap(nullptr, count, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, ZERO);
171 if (ptr == MAP_FAILED) {
172 ::close(*fd);
173 IMAGE_LOGE("::mmap failed");
174 return ERR_SHAMEM_DATA_ABNORMAL;
175 }
176 SetDecodeContextBuffer(context,
177 AllocatorType::SHARE_MEM_ALLOC, static_cast<uint8_t*>(ptr), count, fd.release());
178 return SUCCESS;
179 #endif
180 }
181
DmaMemAlloc(DecodeContext & context,uint64_t count,SkImageInfo & dstInfo)182 static uint32_t DmaMemAlloc(DecodeContext &context, uint64_t count, SkImageInfo &dstInfo)
183 {
184 #if defined(_WIN32) || defined(_APPLE) || defined(A_PLATFORM) || defined(IOS_PLATFORM)
185 IMAGE_LOGE("Unsupport dma mem alloc");
186 return ERR_IMAGE_DATA_UNSUPPORT;
187 #else
188 sptr<SurfaceBuffer> sb = SurfaceBuffer::Create();
189 BufferRequestConfig requestConfig = {
190 .width = dstInfo.width(),
191 .height = dstInfo.height(),
192 .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
193 .format = GRAPHIC_PIXEL_FMT_RGBA_8888, // hardware decode only support rgba8888
194 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
195 .timeout = 0,
196 .colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB,
197 .transform = GraphicTransformType::GRAPHIC_ROTATE_NONE,
198 };
199 GSError ret = sb->Alloc(requestConfig);
200 if (ret != GSERROR_OK) {
201 IMAGE_LOGE("SurfaceBuffer Alloc failed, %{public}s", GSErrorStr(ret).c_str());
202 return ERR_DMA_NOT_EXIST;
203 }
204 void* nativeBuffer = sb.GetRefPtr();
205 int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
206 if (err != OHOS::GSERROR_OK) {
207 IMAGE_LOGE("NativeBufferReference failed");
208 return ERR_DMA_DATA_ABNORMAL;
209 }
210
211 SetDecodeContextBuffer(context,
212 AllocatorType::DMA_ALLOC, static_cast<uint8_t*>(sb->GetVirAddr()), count, nativeBuffer);
213 return SUCCESS;
214 #endif
215 }
216
HeapMemAlloc(DecodeContext & context,uint64_t count)217 static uint32_t HeapMemAlloc(DecodeContext &context, uint64_t count)
218 {
219 if (count == 0 || count > PIXEL_MAP_MAX_RAM_SIZE) {
220 IMAGE_LOGE("HeapMemAlloc Invalid value of bufferSize");
221 return ERR_IMAGE_DATA_ABNORMAL;
222 }
223 auto out = static_cast<uint8_t *>(malloc(count));
224 #ifdef _WIN32
225 if (memset_s(out, ZERO, count) != EOK) {
226 #else
227 if (memset_s(out, count, ZERO, count) != EOK) {
228 #endif
229 IMAGE_LOGE("Decode failed, memset buffer failed");
230 free(out);
231 return ERR_IMAGE_DECODE_FAILED;
232 }
233 SetDecodeContextBuffer(context, AllocatorType::HEAP_ALLOC, out, count, nullptr);
234 return SUCCESS;
235 }
236
237 ExtDecoder::ExtDecoder() : codec_(nullptr), frameCount_(ZERO)
238 {
239 }
240
241 ExtDecoder::~ExtDecoder()
242 {
243 if (gifCache_ != nullptr) {
244 free(gifCache_);
245 gifCache_ = nullptr;
246 }
247 }
248
249 void ExtDecoder::SetSource(InputDataStream &sourceStream)
250 {
251 stream_ = &sourceStream;
252 streamOff_ = sourceStream.Tell();
253 if (streamOff_ >= sourceStream.GetStreamSize()) {
254 streamOff_ = ZERO;
255 }
256 }
257
258 void ExtDecoder::Reset()
259 {
260 stream_ = nullptr;
261 codec_ = nullptr;
262 dstInfo_.reset();
263 dstSubset_ = SkIRect::MakeEmpty();
264 info_.reset();
265 }
266
267 static inline float Max(float a, float b)
268 {
269 return (a > b) ? a : b;
270 }
271
272 bool ExtDecoder::GetScaledSize(int &dWidth, int &dHeight, float &scale)
273 {
274 if (info_.isEmpty() && !DecodeHeader()) {
275 IMAGE_LOGE("DecodeHeader failed in GetScaledSize!");
276 return false;
277 }
278 if (info_.isEmpty()) {
279 IMAGE_LOGE("empty image info in GetScaledSize!");
280 return false;
281 }
282 float finalScale = scale;
283 if (scale == ZERO) {
284 finalScale = Max(static_cast<float>(dWidth) / info_.width(),
285 static_cast<float>(dHeight) / info_.height());
286 }
287 auto scaledDimension = codec_->getScaledDimensions(finalScale);
288 dWidth = scaledDimension.width();
289 dHeight = scaledDimension.height();
290 scale = finalScale;
291 IMAGE_LOGD("IsSupportScaleOnDecode info [%{public}d x %{public}d]", info_.width(), info_.height());
292 IMAGE_LOGD("IsSupportScaleOnDecode [%{public}d x %{public}d]", dWidth, dHeight);
293 IMAGE_LOGD("IsSupportScaleOnDecode [%{public}f]", scale);
294 return true;
295 }
296
297 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
298 bool ExtDecoder::GetHardwareScaledSize(int &dWidth, int &dHeight, float &scale) {
299 if (info_.isEmpty() && !DecodeHeader()) {
300 IMAGE_LOGE("DecodeHeader failed in GetHardwareScaledSize!");
301 return false;
302 }
303 if (info_.isEmpty()) {
304 IMAGE_LOGE("empty image info in GetHardwareScaledSize!");
305 return false;
306 }
307 float finalScale = scale;
308 int oriWidth = info_.width();
309 int oriHeight = info_.height();
310 if (scale == ZERO) {
311 finalScale = Max(static_cast<float>(dWidth) / oriWidth,
312 static_cast<float>(dHeight) / oriHeight);
313 }
314 // calculate sample size and dst size for hardware decode
315 if (finalScale > HALF) {
316 sampleSize_ = 1;
317 dWidth = oriWidth;
318 dHeight = oriHeight;
319 } else if (finalScale > QUARTER) {
320 sampleSize_ = 2;
321 dWidth = oriWidth * HALF;
322 dHeight = oriHeight * HALF;
323 } else if (finalScale > ONE_EIGHTH) {
324 sampleSize_ = 4;
325 dWidth = oriWidth * QUARTER;
326 dHeight = oriHeight * QUARTER;
327 } else {
328 sampleSize_ = 8;
329 dWidth = oriWidth * ONE_EIGHTH;
330 dHeight = oriHeight * ONE_EIGHTH;
331 }
332 return true;
333 }
334 #endif
335
336 bool ExtDecoder::IsSupportScaleOnDecode()
337 {
338 constexpr float HALF_SCALE = 0.5f;
339 int w = ZERO;
340 int h = ZERO;
341 float scale = HALF_SCALE;
342 return GetScaledSize(w, h, scale);
343 }
344
345 bool ExtDecoder::IsSupportCropOnDecode()
346 {
347 if (info_.isEmpty() && !DecodeHeader()) {
348 return false;
349 }
350 SkIRect innerRect = info_.bounds().makeInset(OFFSET, OFFSET);
351 return IsSupportCropOnDecode(innerRect);
352 }
353
354 bool ExtDecoder::IsSupportCropOnDecode(SkIRect &target)
355 {
356 if (info_.isEmpty() && !DecodeHeader()) {
357 return false;
358 }
359 SkIRect orgbounds = info_.bounds();
360 SkIRect source = target;
361 if (orgbounds.contains(target) && codec_->getValidSubset(&target)) {
362 return source == target;
363 }
364 return false;
365 }
366
367 bool ExtDecoder::HasProperty(string key)
368 {
369 if (CODEC_INITED_KEY.compare(key) == ZERO) {
370 return CheckCodec();
371 } else if (ENCODED_FORMAT_KEY.compare(key) == ZERO) {
372 return true;
373 } else if (SUPPORT_SCALE_KEY.compare(key) == ZERO) {
374 return IsSupportScaleOnDecode();
375 } else if (SUPPORT_CROP_KEY.compare(key) == ZERO) {
376 return IsSupportCropOnDecode();
377 }
378 return false;
379 }
380
381 uint32_t ExtDecoder::GetImageSize(uint32_t index, PlSize &size)
382 {
383 IMAGE_LOGD("GetImageSize index:%{public}u", index);
384 if (!CheckIndexValied(index)) {
385 IMAGE_LOGE("Invalid index:%{public}u, range:%{public}d", index, frameCount_);
386 return ERR_IMAGE_INVALID_PARAMETER;
387 }
388 IMAGE_LOGD("GetImageSize index:%{public}u, range:%{public}d", index, frameCount_);
389 // Info has been get in check process, or empty on get failed.
390 if (info_.isEmpty()) {
391 IMAGE_LOGE("GetImageSize failed, decode header failed.");
392 return ERR_IMAGE_DECODE_HEAD_ABNORMAL;
393 }
394 size.width = info_.width();
395 size.height = info_.height();
396 return SUCCESS;
397 }
398
399 static inline bool IsLowDownScale(const PlSize &size, SkImageInfo &info)
400 {
401 return size.width < static_cast<uint32_t>(info.width()) &&
402 size.height < static_cast<uint32_t>(info.height());
403 }
404
405 static inline bool IsValidCrop(const PlRect &crop, SkImageInfo &info, SkIRect &out)
406 {
407 out = SkIRect::MakeXYWH(crop.left, crop.top, crop.width, crop.height);
408 if (out.fLeft < ZERO || out.fTop < ZERO) {
409 return false;
410 }
411 if (out.fRight > info.width()) {
412 out.fRight = info.width();
413 }
414 if (out.fBottom > info.height()) {
415 out.fBottom = info.height();
416 }
417 return true;
418 }
419
420 static sk_sp<SkColorSpace> getDesiredColorSpace(SkImageInfo &srcInfo, const PixelDecodeOptions &opts)
421 {
422 if (opts.plDesiredColorSpace == nullptr) {
423 return srcInfo.refColorSpace();
424 }
425 return opts.plDesiredColorSpace->ToSkColorSpace();
426 }
427
428 uint32_t ExtDecoder::CheckDecodeOptions(uint32_t index, const PixelDecodeOptions &opts)
429 {
430 if (ImageUtils::CheckMulOverflow(dstInfo_.width(), dstInfo_.height(), dstInfo_.bytesPerPixel())) {
431 IMAGE_LOGE("SetDecodeOptions failed, width:%{public}d, height:%{public}d is too large",
432 dstInfo_.width(), dstInfo_.height());
433 return ERR_IMAGE_INVALID_PARAMETER;
434 }
435 if (!IsValidCrop(opts.CropRect, info_, dstSubset_)) {
436 IMAGE_LOGE("Invalid crop rect xy [%{public}d x %{public}d], wh [%{public}d x %{public}d]",
437 dstSubset_.left(), dstSubset_.top(), dstSubset_.width(), dstSubset_.height());
438 return ERR_IMAGE_INVALID_PARAMETER;
439 }
440
441 dstOptions_.fFrameIndex = index;
442 #ifdef IMAGE_COLORSPACE_FLAG
443 dstColorSpace_ = opts.plDesiredColorSpace;
444 #endif
445 if (IsSupportCropOnDecode(dstSubset_)) {
446 dstOptions_.fSubset = &dstSubset_;
447 }
448 return SUCCESS;
449 }
450
451 uint32_t ExtDecoder::SetDecodeOptions(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info)
452 {
453 if (!CheckIndexValied(index)) {
454 IMAGE_LOGE("Invalid index:%{public}u, range:%{public}d", index, frameCount_);
455 return ERR_IMAGE_INVALID_PARAMETER;
456 }
457 if (opts.sampleSize != DEFAULT_SAMPLE_SIZE) {
458 IMAGE_LOGE("Do not support sample size now!");
459 return ERR_IMAGE_INVALID_PARAMETER;
460 }
461 auto desireColor = ConvertToColorType(opts.desiredPixelFormat, info.pixelFormat);
462 auto desireAlpha = ConvertToAlphaType(opts.desireAlphaType, info.alphaType);
463 // SK only support low down scale
464 int dstWidth = opts.desiredSize.width;
465 int dstHeight = opts.desiredSize.height;
466 float scale = ZERO;
467 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
468 if (IsSupportHardwareDecode()) {
469 // get dstInfo for hardware decode
470 if (IsLowDownScale(opts.desiredSize, info_) && GetHardwareScaledSize(dstWidth, dstHeight, scale)) {
471 hwDstInfo_ = SkImageInfo::Make(dstWidth, dstHeight, desireColor, desireAlpha, info_.refColorSpace());
472 } else {
473 hwDstInfo_ = SkImageInfo::Make(info_.width(), info_.height(),
474 desireColor, desireAlpha, info_.refColorSpace());
475 }
476 // restore dstWidth and dstHeight
477 dstWidth = opts.desiredSize.width;
478 dstHeight = opts.desiredSize.height;
479 }
480 #endif
481 if (IsLowDownScale(opts.desiredSize, info_) && GetScaledSize(dstWidth, dstHeight, scale)) {
482 dstInfo_ = SkImageInfo::Make(dstWidth, dstHeight, desireColor, desireAlpha,
483 getDesiredColorSpace(info_, opts));
484 } else {
485 dstInfo_ = SkImageInfo::Make(info_.width(), info_.height(),
486 desireColor, desireAlpha, getDesiredColorSpace(info_, opts));
487 }
488 auto resCode = CheckDecodeOptions(index, opts);
489 if (resCode != SUCCESS) {
490 return resCode;
491 }
492
493 info.size.width = dstInfo_.width();
494 info.size.height = dstInfo_.height();
495 return SUCCESS;
496 }
497
498 uint32_t ExtDecoder::SetContextPixelsBuffer(uint64_t byteCount, DecodeContext &context)
499 {
500 if (byteCount == ZERO) {
501 return ERR_IMAGE_INVALID_PARAMETER;
502 }
503 if (context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC) {
504 return ShareMemAlloc(context, byteCount);
505 } else if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
506 return DmaMemAlloc(context, byteCount, dstInfo_);
507 }
508 return HeapMemAlloc(context, byteCount);
509 }
510
511 static void DebugInfo(SkImageInfo &info, SkImageInfo &dstInfo, SkCodec::Options &opts)
512 {
513 IMAGE_LOGD("Decode source info: WH[%{public}d x %{public}d], A %{public}d, C %{public}d.",
514 info.width(), info.height(),
515 info.alphaType(), info.colorType());
516 IMAGE_LOGD("Decode dst info: WH[%{public}d x %{public}d], A %{public}d, C %{public}d.",
517 dstInfo.width(), dstInfo.height(), dstInfo.alphaType(), dstInfo.colorType());
518 if (opts.fSubset != nullptr) {
519 IMAGE_LOGD("Decode dstOpts sub: (%{public}d, %{public}d), WH[%{public}d x %{public}d]",
520 opts.fSubset->fLeft, opts.fSubset->fTop,
521 opts.fSubset->width(), opts.fSubset->height());
522 }
523 }
524
525 static uint32_t RGBxToRGB(uint8_t* srcBuffer, size_t srsSize,
526 uint8_t* dstBuffer, size_t dstSize, size_t pixelCount)
527 {
528 ExtPixels src = {srcBuffer, srsSize, pixelCount};
529 ExtPixels dst = {dstBuffer, dstSize, pixelCount};
530 auto res = ExtPixelConvert::RGBxToRGB(src, dst);
531 if (res != SUCCESS) {
532 IMAGE_LOGE("RGBxToRGB failed %{public}d", res);
533 }
534 return res;
535 }
536
537 uint32_t ExtDecoder::PreDecodeCheck(uint32_t index)
538 {
539 if (!CheckIndexValied(index)) {
540 IMAGE_LOGE("Decode failed, invalid index:%{public}u, range:%{public}d", index, frameCount_);
541 return ERR_IMAGE_INVALID_PARAMETER;
542 }
543 if (codec_ == nullptr) {
544 IMAGE_LOGE("Decode failed, codec is null");
545 return ERR_IMAGE_DECODE_FAILED;
546 }
547 if (dstInfo_.isEmpty()) {
548 IMAGE_LOGE("Decode failed, dst info is empty");
549 return ERR_IMAGE_DECODE_FAILED;
550 }
551 return SUCCESS;
552 }
553
554 bool ExtDecoder::ResetCodec()
555 {
556 codec_ = nullptr;
557 stream_->Seek(streamOff_);
558 return ExtDecoder::CheckCodec();
559 }
560
561 #ifdef JPEG_HW_DECODE_ENABLE
562 uint32_t ExtDecoder::DoHardWareDecode(DecodeContext &context)
563 {
564 if (HardWareDecode(context) == SUCCESS) {
565 return SUCCESS;
566 }
567 return ERROR;
568 }
569 #endif
570
571 uint32_t ExtDecoder::Decode(uint32_t index, DecodeContext &context)
572 {
573 #ifdef JPEG_HW_DECODE_ENABLE
574 if (IsSupportHardwareDecode() && DoHardWareDecode(context) == SUCCESS) {
575 return SUCCESS;
576 }
577 #endif
578 uint32_t res = PreDecodeCheck(index);
579 if (res != SUCCESS) {
580 return res;
581 }
582 uint64_t byteCount = static_cast<uint64_t>(dstInfo_.computeMinByteSize());
583 uint8_t *dstBuffer = nullptr;
584 if (dstInfo_.colorType() == SkColorType::kRGB_888x_SkColorType) {
585 auto tmpBuffer = make_unique<uint8_t[]>(byteCount);
586 dstBuffer = tmpBuffer.get();
587 byteCount = byteCount / NUM_4 * NUM_3;
588 }
589 if (context.pixelsBuffer.buffer == nullptr) {
590 res = SetContextPixelsBuffer(byteCount, context);
591 if (res != SUCCESS) {
592 return res;
593 }
594 if (dstBuffer == nullptr) {
595 dstBuffer = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
596 }
597 }
598 dstOptions_.fFrameIndex = index;
599 DebugInfo(info_, dstInfo_, dstOptions_);
600 uint64_t rowStride = dstInfo_.minRowBytes64();
601 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
602 if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
603 SurfaceBuffer* sbBuffer = reinterpret_cast<SurfaceBuffer*> (context.pixelsBuffer.context);
604 rowStride = sbBuffer->GetStride();
605 }
606 #endif
607 SkEncodedImageFormat skEncodeFormat = codec_->getEncodedFormat();
608 ReportImageType(skEncodeFormat);
609 IMAGE_LOGD("decode format %{public}d", skEncodeFormat);
610 if (skEncodeFormat == SkEncodedImageFormat::kGIF || skEncodeFormat == SkEncodedImageFormat::kWEBP) {
611 return GifDecode(index, context, rowStride);
612 }
613 SkCodec::Result ret = codec_->getPixels(dstInfo_, dstBuffer, rowStride, &dstOptions_);
614 if (ret != SkCodec::kSuccess && ResetCodec()) {
615 // Try again
616 ret = codec_->getPixels(dstInfo_, dstBuffer, rowStride, &dstOptions_);
617 }
618 if (ret != SkCodec::kSuccess) {
619 IMAGE_LOGE("Decode failed, get pixels failed, ret=%{public}d", ret);
620 return ERR_IMAGE_DECODE_ABNORMAL;
621 }
622 if (dstInfo_.colorType() == SkColorType::kRGB_888x_SkColorType) {
623 return RGBxToRGB(dstBuffer, dstInfo_.computeMinByteSize(), static_cast<uint8_t*>(context.pixelsBuffer.buffer),
624 byteCount, dstInfo_.width() * dstInfo_.height());
625 }
626 return SUCCESS;
627 }
628
629 static std::string GetFormatStr(SkEncodedImageFormat format)
630 {
631 switch (format) {
632 case SkEncodedImageFormat::kBMP:
633 return "bmp";
634 case SkEncodedImageFormat::kGIF:
635 return "gif";
636 case SkEncodedImageFormat::kICO:
637 return "ico";
638 case SkEncodedImageFormat::kJPEG:
639 return "jpeg";
640 case SkEncodedImageFormat::kPNG:
641 return "png";
642 case SkEncodedImageFormat::kWBMP:
643 return "wbmp";
644 case SkEncodedImageFormat::kWEBP:
645 return "webp";
646 case SkEncodedImageFormat::kPKM:
647 return "pkm";
648 case SkEncodedImageFormat::kKTX:
649 return "ktx";
650 case SkEncodedImageFormat::kASTC:
651 return "astc";
652 case SkEncodedImageFormat::kDNG:
653 return "dng";
654 case SkEncodedImageFormat::kHEIF:
655 return "heif";
656 case SkEncodedImageFormat::kAVIF:
657 return "avif";
658 default:
659 return UNKNOWN_IMAGE;
660 }
661 }
662
663 void ExtDecoder::ReportImageType(SkEncodedImageFormat skEncodeFormat)
664 {
665 IMAGE_LOGD("ExtDecoder::ReportImageType format %{public}d start", skEncodeFormat);
666 static constexpr char IMAGE_FWK_UE[] = "IMAGE_FWK_UE";
667 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
668 int32_t ret = HiSysEventWrite(
669 IMAGE_FWK_UE,
670 "DECODED_IMAGE_TYPE_STATISTICS",
671 HiviewDFX::HiSysEvent::EventType::STATISTIC,
672 "PNAMEID", DEFAULT_PACKAGE_NAME,
673 "PVERSIONID", DEFAULT_VERSION_ID,
674 "IMAGE_TYPE", GetFormatStr(skEncodeFormat)
675 );
676 if (SUCCESS != ret) {
677 IMAGE_LOGD("ExtDecoder::ReportImageType failed, ret = %{public}d", ret);
678 return;
679 }
680 #endif
681 IMAGE_LOGD("ExtDecoder::ReportImageType format %{public}d success", skEncodeFormat);
682 }
683 #ifdef JPEG_HW_DECODE_ENABLE
684 uint32_t ExtDecoder::AllocOutputBuffer(DecodeContext &context)
685 {
686 uint64_t byteCount = static_cast<uint64_t>(dstInfo_.height()) * dstInfo_.width() * dstInfo_.bytesPerPixel();
687 uint32_t ret = DmaMemAlloc(context, byteCount, info_);
688 if (ret != SUCCESS) {
689 IMAGE_LOGE("Alloc OutputBuffer failed, ret=%{public}d", ret);
690 return ERR_IMAGE_DECODE_ABNORMAL;
691 }
692 BufferHandle *handle = (static_cast<SurfaceBuffer*>(context.pixelsBuffer.context))->GetBufferHandle();
693 if (outputColorFmt_ == PIXEL_FMT_RGBA_8888) {
694 outputBufferSize_.width = static_cast<uint32_t>(handle->stride) / NUM_4;
695 } else {
696 outputBufferSize_.width = static_cast<uint32_t>(handle->stride);
697 }
698 outputBufferSize_.height = static_cast<uint32_t>(handle->height);
699 outputBuffer_.buffer = new NativeBuffer(handle);
700 outputBuffer_.fenceFd = -1;
701 return SUCCESS;
702 }
703
704 bool CheckContext(const SkImageInfo &dstInfo)
705 {
706 if (dstInfo.colorType() != kRGBA_8888_SkColorType) {
707 IMAGE_LOGE("hardware decode only support rgba_8888 format");
708 return false;
709 }
710 return true;
711 }
712
713 void ExtDecoder::ReleaseOutputBuffer(DecodeContext &context, Media::AllocatorType allocatorType)
714 {
715 ImageUtils::SurfaceBuffer_Unreference(static_cast<SurfaceBuffer*>(context.pixelsBuffer.context));
716 context.pixelsBuffer.buffer = nullptr;
717 context.allocatorType = allocatorType;
718 context.freeFunc = nullptr;
719 context.pixelsBuffer.bufferSize = 0;
720 context.pixelsBuffer.context = nullptr;
721 outputBuffer_.buffer = nullptr;
722 }
723
724 uint32_t ExtDecoder::HardWareDecode(DecodeContext &context)
725 {
726 // check if the hwDstInfo is equal to the dstInfo
727 if (hwDstInfo_.width() != dstInfo_.width() || hwDstInfo_.height() != dstInfo_.height()) {
728 IMAGE_LOGI("hwDstInfo(%{public}d, %{public}d) != dstInfo(%{public}d, %{public}d)",
729 hwDstInfo_.width(), hwDstInfo_.height(), dstInfo_.width(), dstInfo_.height());
730 return ERROR;
731 }
732 JpegHardwareDecoder hwDecoder;
733 orgImgSize_.width = info_.width();
734 orgImgSize_.height = info_.height();
735
736 if (!CheckContext(dstInfo_)) {
737 return ERROR;
738 }
739
740 Media::AllocatorType tmpAllocatorType = context.allocatorType;
741 uint32_t ret = AllocOutputBuffer(context);
742 if (ret != SUCCESS) {
743 IMAGE_LOGE("Decode failed, Alloc OutputBuffer failed, ret=%{public}d", ret);
744 return ERR_IMAGE_DECODE_ABNORMAL;
745 }
746 ret = hwDecoder.Decode(codec_.get(), stream_, orgImgSize_, sampleSize_, outputBuffer_);
747 if (ret != SUCCESS) {
748 IMAGE_LOGE("failed to do jpeg hardware decode, err=%{public}d", ret);
749 ReleaseOutputBuffer(context, tmpAllocatorType);
750 return ERR_IMAGE_DECODE_ABNORMAL;
751 }
752 return SUCCESS;
753 }
754 #endif
755
756 static uint32_t handleGifCache(uint8_t* src, uint8_t* dst, SkImageInfo& info, const uint64_t rowStride) {
757 if (src == nullptr || dst == nullptr) {
758 return ERR_IMAGE_DECODE_ABNORMAL;
759 }
760 int dstHeight = info.height();
761 uint8_t* srcRow = src;
762 uint8_t* dstRow = dst;
763 for (int i = 0; i < dstHeight; i++) {
764 errno_t err = memcpy_s(dstRow, rowStride, srcRow, rowStride);
765 if (err != EOK) {
766 IMAGE_LOGE("handle gif memcpy failed. errno:%{public}d", err);
767 return ERR_IMAGE_DECODE_ABNORMAL;
768 }
769 srcRow += rowStride;
770 dstRow += rowStride;
771 }
772 return SUCCESS;
773 }
774
775 uint32_t ExtDecoder::GifDecode(uint32_t index, DecodeContext &context, const uint64_t rowStride)
776 {
777 SkCodec::FrameInfo curInfo {};
778 codec_->getFrameInfo(index, &curInfo);
779 if (index == 0 || gifCache_ == nullptr) {
780 dstOptions_.fPriorFrame = SkCodec::kNoFrame;
781 } else {
782 int preIndex = index - 1;
783 SkCodec::FrameInfo preInfo {};
784 codec_->getFrameInfo(preIndex, &preInfo);
785 if (preInfo.fDisposalMethod == SkCodecAnimation::DisposalMethod::kRestorePrevious) {
786 dstOptions_.fPriorFrame = gifCacheIndex_;
787 } else {
788 dstOptions_.fPriorFrame = gifCacheIndex_ == preIndex ? preIndex : SkCodec::kNoFrame;
789 }
790 }
791 uint8_t* dstBuffer = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
792 if (curInfo.fDisposalMethod != SkCodecAnimation::DisposalMethod::kRestorePrevious) {
793 if (gifCache_ == nullptr) {
794 int dstHeight = dstInfo_.height();
795 uint64_t byteCount = rowStride * dstHeight;
796 gifCache_ = static_cast<uint8_t *>(calloc(byteCount, 1));
797 }
798 dstBuffer = gifCache_;
799 } else if (gifCache_ != nullptr) {
800 handleGifCache(gifCache_, dstBuffer, dstInfo_, rowStride);
801 }
802 SkCodec::Result ret = codec_->getPixels(dstInfo_, dstBuffer, rowStride, &dstOptions_);
803 if (ret != SkCodec::kSuccess && ResetCodec()) {
804 // Try again
805 ret = codec_->getPixels(dstInfo_, dstBuffer, rowStride, &dstOptions_);
806 }
807 if (ret != SkCodec::kSuccess) {
808 IMAGE_LOGE("Gif decode failed, get pixels failed, ret=%{public}d", ret);
809 return ERR_IMAGE_DECODE_ABNORMAL;
810 }
811 if (curInfo.fDisposalMethod != SkCodecAnimation::DisposalMethod::kRestorePrevious) {
812 gifCacheIndex_ = index;
813 uint8_t* dst = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
814 return handleGifCache(dstBuffer, dst, dstInfo_, rowStride);
815 }
816 return SUCCESS;
817 }
818
819 uint32_t ExtDecoder::PromoteIncrementalDecode(uint32_t index, ProgDecodeContext &context)
820 {
821 // currently not support increment decode
822 return ERR_IMAGE_DATA_UNSUPPORT;
823 }
824
825 bool ExtDecoder::CheckCodec()
826 {
827 if (codec_ != nullptr) {
828 return true;
829 } else if (stream_ == nullptr) {
830 IMAGE_LOGE("create codec: input stream is nullptr.");
831 return false;
832 } else if (stream_->GetStreamSize() == SIZE_ZERO) {
833 IMAGE_LOGE("create codec: input stream size is zero.");
834 return false;
835 }
836 codec_ = SkCodec::MakeFromStream(make_unique<ExtStream>(stream_));
837 if (codec_ == nullptr) {
838 IMAGE_LOGE("create codec from stream failed");
839 return false;
840 }
841 return codec_ != nullptr;
842 }
843
844 bool ExtDecoder::DecodeHeader()
845 {
846 if (!CheckCodec()) {
847 IMAGE_LOGE("Check codec failed");
848 return false;
849 }
850 info_ = codec_->getInfo();
851 frameCount_ = codec_->getFrameCount();
852 IMAGE_LOGD("DecodeHeader: get frame count %{public}d.", frameCount_);
853 return true;
854 }
855
856 bool ExtDecoder::CheckIndexValied(uint32_t index)
857 {
858 if (frameCount_ == ZERO && !DecodeHeader()) {
859 return false;
860 }
861 return static_cast<int32_t>(index) >= ZERO && static_cast<int32_t>(index) < frameCount_;
862 }
863
864 static uint32_t GetFormatName(SkEncodedImageFormat format, std::string &name)
865 {
866 auto formatNameIter = FORMAT_NAME.find(format);
867 if (formatNameIter != FORMAT_NAME.end() && !formatNameIter->second.empty()) {
868 name = formatNameIter->second;
869 IMAGE_LOGD("GetFormatName: get encoded format name (%{public}d)=>[%{public}s].",
870 format, name.c_str());
871 return SUCCESS;
872 }
873 IMAGE_LOGE("GetFormatName: get encoded format name failed %{public}d.", format);
874 return ERR_IMAGE_DATA_UNSUPPORT;
875 }
876
877 bool ExtDecoder::ConvertInfoToAlphaType(SkAlphaType &alphaType, PlAlphaType &outputType)
878 {
879 if (info_.isEmpty()) {
880 return false;
881 }
882 alphaType = info_.alphaType();
883 auto findItem = std::find_if(ALPHA_TYPE_MAP.begin(), ALPHA_TYPE_MAP.end(),
884 [alphaType](const map<PlAlphaType, SkAlphaType>::value_type item) {
885 return item.second == alphaType;
886 });
887 if (findItem == ALPHA_TYPE_MAP.end()) {
888 return false;
889 }
890 outputType = findItem->first;
891 alphaType = findItem->second;
892 return true;
893 }
894
895 bool ExtDecoder::ConvertInfoToColorType(SkColorType &format, PlPixelFormat &outputFormat)
896 {
897 if (info_.isEmpty()) {
898 return false;
899 }
900 auto colorType = info_.colorType();
901 auto findItem = std::find_if(COLOR_TYPE_MAP.begin(), COLOR_TYPE_MAP.end(),
902 [colorType](const map<PlPixelFormat, ColorTypeOutput>::value_type item) {
903 return item.second.skFormat == colorType;
904 });
905 if (findItem == COLOR_TYPE_MAP.end()) {
906 return false;
907 }
908 format = findItem->second.skFormat;
909 outputFormat = findItem->second.outFormat;
910 return true;
911 }
912
913 SkAlphaType ExtDecoder::ConvertToAlphaType(PlAlphaType desiredType, PlAlphaType &outputType)
914 {
915 if (desiredType != PlAlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) {
916 auto alphaType = ALPHA_TYPE_MAP.find(desiredType);
917 if (alphaType != ALPHA_TYPE_MAP.end()) {
918 outputType = alphaType->first;
919 return alphaType->second;
920 }
921 }
922 IMAGE_LOGD("Unknown alpha type:%{public}d", desiredType);
923 SkAlphaType res;
924 if (ConvertInfoToAlphaType(res, outputType)) {
925 IMAGE_LOGD("Using alpha type:%{public}d", outputType);
926 return res;
927 }
928 IMAGE_LOGD("Using default alpha type:%{public}d", PlAlphaType::IMAGE_ALPHA_TYPE_PREMUL);
929 outputType = PlAlphaType::IMAGE_ALPHA_TYPE_PREMUL;
930 return SkAlphaType::kPremul_SkAlphaType;
931 }
932
933 SkColorType ExtDecoder::ConvertToColorType(PlPixelFormat format, PlPixelFormat &outputFormat)
934 {
935 if (format != PlPixelFormat::UNKNOWN) {
936 auto colorType = COLOR_TYPE_MAP.find(format);
937 if (colorType != COLOR_TYPE_MAP.end()) {
938 outputFormat = colorType->second.outFormat;
939 return colorType->second.skFormat;
940 }
941 }
942 IMAGE_LOGD("Unknown pixel format:%{public}d", format);
943 SkColorType res;
944 if (ConvertInfoToColorType(res, outputFormat)) {
945 IMAGE_LOGD("Using pixel format:%{public}d", outputFormat);
946 return res;
947 }
948 IMAGE_LOGD("Using default pixel format:%{public}d", PlPixelFormat::RGBA_8888);
949 outputFormat = PlPixelFormat::RGBA_8888;
950 return kRGBA_8888_SkColorType;
951 }
952
953 #ifdef IMAGE_COLORSPACE_FLAG
954 static uint32_t u8ToU32(const uint8_t* p)
955 {
956 return (p[OFFSET_0] << SHIFT_BITS_24) | (p[OFFSET_1] << SHIFT_BITS_16) |
957 (p[OFFSET_2] << SHIFT_BITS_8) | p[OFFSET_3];
958 }
959
960 struct ICCTag {
961 uint8_t signature[SIZE_4];
962 uint8_t offset[SIZE_4];
963 uint8_t size[SIZE_4];
964 };
965
966 struct ColorSpaceNameEnum {
967 std::string desc;
968 OHOS::ColorManager::ColorSpaceName name;
969 };
970
971 static std::vector<ColorSpaceNameEnum> sColorSpaceNamedMap = {
972 {"Display P3", OHOS::ColorManager::ColorSpaceName::DISPLAY_P3},
973 {"sRGB EOTF with DCI-P3 Color Gamut", OHOS::ColorManager::ColorSpaceName::DISPLAY_P3},
974 {"DCI-P3 D65 Gamut with sRGB Transfer", OHOS::ColorManager::ColorSpaceName::DISPLAY_P3},
975 {"Adobe RGB (1998)", OHOS::ColorManager::ColorSpaceName::ADOBE_RGB},
976 {"DCI P3", OHOS::ColorManager::ColorSpaceName::DCI_P3},
977 {"sRGB", OHOS::ColorManager::ColorSpaceName::SRGB}
978 /*{"BT.2020", OHOS::ColorManager::ColorSpaceName::BT2020}*/
979 };
980
981 static bool MatchColorSpaceName(const uint8_t* buf, uint32_t size, OHOS::ColorManager::ColorSpaceName &name)
982 {
983 if (buf == nullptr || size <= OFFSET_5) {
984 return false;
985 }
986 std::vector<char> desc;
987 // We need skip desc type
988 for (uint32_t i = OFFSET_5; i < size; i++) {
989 if (buf[i] != '\0') {
990 desc.push_back(buf[i]);
991 }
992 }
993 if (desc.size() <= SIZE_1) {
994 IMAGE_LOGI("empty buffer");
995 return false;
996 }
997 std::string descText(desc.begin() + OFFSET_1, desc.end());
998 for (auto nameEnum : sColorSpaceNamedMap) {
999 if (descText.find(nameEnum.desc) == std::string::npos) {
1000 continue;
1001 }
1002 name = nameEnum.name;
1003 return true;
1004 }
1005 IMAGE_LOGE("Failed to match desc [%{public}s]", descText.c_str());
1006 return false;
1007 }
1008
1009 static bool GetColorSpaceName(const skcms_ICCProfile* profile, OHOS::ColorManager::ColorSpaceName &name)
1010 {
1011 if (profile == nullptr || profile->buffer == nullptr) {
1012 IMAGE_LOGD("profile is nullptr");
1013 return false;
1014 }
1015 auto tags = reinterpret_cast<const ICCTag*>(profile->buffer + ICC_HEADER_SIZE);
1016 for (uint32_t i = SIZE_ZERO; i < profile->tag_count; i++) {
1017 auto signature = u8ToU32(tags[i].signature);
1018 if (signature != DESC_SIGNATURE) {
1019 continue;
1020 }
1021 auto size = u8ToU32(tags[i].size);
1022 auto offset = u8ToU32(tags[i].offset);
1023 if (size == SIZE_ZERO || offset >= profile->size) {
1024 continue;
1025 }
1026 auto buffer = u8ToU32(tags[i].offset) + profile->buffer;
1027 if (MatchColorSpaceName(buffer, size, name)) {
1028 return true;
1029 }
1030 }
1031 return false;
1032 }
1033
1034 OHOS::ColorManager::ColorSpace ExtDecoder::getGrColorSpace()
1035 {
1036 if (dstColorSpace_ != nullptr) {
1037 return *dstColorSpace_;
1038 }
1039 auto skColorSpace = dstInfo_.isEmpty() ? info_.refColorSpace() : dstInfo_.refColorSpace();
1040 OHOS::ColorManager::ColorSpaceName name = OHOS::ColorManager::ColorSpaceName::CUSTOM;
1041 if (codec_ != nullptr) {
1042 auto profile = codec_->getICCProfile();
1043 if (profile != nullptr) {
1044 IMAGE_LOGD("profile got !!!!");
1045 GetColorSpaceName(profile, name);
1046 }
1047 }
1048 return OHOS::ColorManager::ColorSpace(skColorSpace, name);
1049 }
1050
1051 bool ExtDecoder::IsSupportICCProfile()
1052 {
1053 if (dstColorSpace_ != nullptr) {
1054 return true;
1055 }
1056 if (info_.isEmpty()) {
1057 return false;
1058 }
1059 return info_.refColorSpace() != nullptr;
1060 }
1061 #endif
1062
1063 static uint32_t ProcessWithStreamData(InputDataStream *input,
1064 std::function<uint32_t(uint8_t*, size_t)> process)
1065 {
1066 size_t inputSize = input->GetStreamSize();
1067 if (inputSize == SIZE_ZERO) {
1068 return Media::ERR_MEDIA_INVALID_VALUE;
1069 }
1070
1071 auto tmpBuffer = std::make_unique<uint8_t[]>(inputSize);
1072 auto savePos = input->Tell();
1073 input->Seek(SIZE_ZERO);
1074 uint32_t readSize = 0;
1075 bool ret = input->Read(inputSize, tmpBuffer.get(), inputSize, readSize);
1076 input->Seek(savePos);
1077 if (!ret) {
1078 IMAGE_LOGE("InputDataStream read failed.");
1079 return Media::ERR_IMAGE_DATA_ABNORMAL;
1080 }
1081 return process(tmpBuffer.get(), inputSize);
1082 }
1083
1084 static bool ParseExifData(InputDataStream *input, EXIFInfo &info)
1085 {
1086 if (info.IsExifDataParsed()) {
1087 return true;
1088 }
1089 IMAGE_LOGD("ParseExifData enter");
1090 auto code = ProcessWithStreamData(input, [&info](uint8_t* buffer, size_t size) {
1091 return info.ParseExifData(buffer, size);
1092 });
1093 if (code != SUCCESS) {
1094 IMAGE_LOGE("Error parsing EXIF: code %{public}d", code);
1095 }
1096 return code == SUCCESS;
1097 }
1098
1099 bool ExtDecoder::GetPropertyCheck(uint32_t index, const std::string &key, uint32_t &res)
1100 {
1101 if (IsSameTextStr(key, ACTUAL_IMAGE_ENCODED_FORMAT)) {
1102 res = Media::ERR_MEDIA_VALUE_INVALID;
1103 return false;
1104 }
1105 if (!CheckIndexValied(index)) {
1106 res = Media::ERR_IMAGE_DECODE_HEAD_ABNORMAL;
1107 return false;
1108 }
1109 SkEncodedImageFormat format = codec_->getEncodedFormat();
1110 if (format != SkEncodedImageFormat::kJPEG) {
1111 res = Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
1112 return true;
1113 }
1114 auto result = ParseExifData(stream_, exifInfo_);
1115 if (!result) {
1116 res = Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
1117 }
1118 return result;
1119 }
1120
1121 static uint32_t GetDelayTime(SkCodec * codec, uint32_t index, int32_t &value)
1122 {
1123 if (codec->getEncodedFormat() != SkEncodedImageFormat::kGIF) {
1124 IMAGE_LOGE("[GetDelayTime] Should not get delay time in %{public}d", codec->getEncodedFormat());
1125 return ERR_MEDIA_INVALID_PARAM;
1126 }
1127 auto frameInfos = codec->getFrameInfo();
1128 if (index > frameInfos.size() - 1) {
1129 IMAGE_LOGE("[GetDelayTime] frame size %{public}zu, index:%{public}d", frameInfos.size(), index);
1130 return ERR_MEDIA_INVALID_PARAM;
1131 }
1132 value = frameInfos[index].fDuration;
1133 IMAGE_LOGD("[GetDelayTime] index[%{public}d]:%{public}d", index, value);
1134 return SUCCESS;
1135 }
1136
1137 uint32_t ExtDecoder::GetImagePropertyInt(uint32_t index, const std::string &key, int32_t &value)
1138 {
1139 IMAGE_LOGD("[GetImagePropertyInt] enter ExtDecoder plugin, key:%{public}s", key.c_str());
1140 uint32_t res = Media::ERR_IMAGE_DATA_ABNORMAL;
1141 if (!GetPropertyCheck(index, key, res)) {
1142 return res;
1143 }
1144 if (GIF_IMAGE_DELAY_TIME.compare(key) == ZERO) {
1145 return GetDelayTime(codec_.get(), index, value);
1146 }
1147 // There can add some not need exif property
1148 if (res == Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT) {
1149 return res;
1150 }
1151 // Need exif property following
1152 if (IsSameTextStr(key, TAG_ORIENTATION_STRING)) {
1153 std::string strValue;
1154 res = exifInfo_.GetExifData(TAG_ORIENTATION_INT, strValue);
1155 if (res != SUCCESS) {
1156 return res;
1157 }
1158 value = atoi(strValue.c_str());
1159 return res;
1160 }
1161 IMAGE_LOGE("[GetImagePropertyInt] The key:%{public}s is not supported int32_t", key.c_str());
1162 return Media::ERR_MEDIA_VALUE_INVALID;
1163 }
1164
1165 uint32_t ExtDecoder::GetImagePropertyString(uint32_t index, const std::string &key, std::string &value)
1166 {
1167 IMAGE_LOGD("[GetImagePropertyString] enter jpeg plugin, key:%{public}s", key.c_str());
1168 uint32_t res = Media::ERR_IMAGE_DATA_ABNORMAL;
1169 if (!GetPropertyCheck(index, key, res)) {
1170 return res;
1171 }
1172 // There can add some not need exif property
1173 if (ENCODED_FORMAT_KEY.compare(key) == ZERO) {
1174 SkEncodedImageFormat format = codec_->getEncodedFormat();
1175 return GetFormatName(format, value);
1176 } else if (GIF_IMAGE_DELAY_TIME.compare(key) == ZERO) {
1177 int delayTime = ZERO;
1178 res = GetDelayTime(codec_.get(), index, delayTime);
1179 value = std::to_string(delayTime);
1180 return res;
1181 }
1182 if (res == Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT) {
1183 return res;
1184 }
1185 // Need exif property following
1186 if (key.find(HW_MNOTE_TAG_HEADER) != std::string::npos) {
1187 res = GetMakerImagePropertyString(key, value);
1188 if (value.length() == 0) {
1189 value = DEFAULT_EXIF_VALUE;
1190 IMAGE_LOGE("[GetImagePropertyString]The image does not contain the %{public}s tag ", key.c_str());
1191 }
1192 return res;
1193 }
1194 res = exifInfo_.GetExifData(key, value);
1195 IMAGE_LOGD("[GetImagePropertyString] enter jpeg plugin, value:%{public}s", value.c_str());
1196 return res;
1197 }
1198
1199 uint32_t ExtDecoder::GetMakerImagePropertyString(const std::string &key, std::string &value)
1200 {
1201 if (exifInfo_.makerInfoTagValueMap.find(key) != exifInfo_.makerInfoTagValueMap.end()) {
1202 value = exifInfo_.makerInfoTagValueMap[key];
1203 return SUCCESS;
1204 }
1205 return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
1206 }
1207
1208 uint32_t ExtDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
1209 const std::string &value, const std::string &path)
1210 {
1211 IMAGE_LOGD("[ModifyImageProperty] with path:%{public}s, key:%{public}s, value:%{public}s",
1212 path.c_str(), key.c_str(), value.c_str());
1213 return exifInfo_.ModifyExifData(key, value, path);
1214 }
1215
1216 uint32_t ExtDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
1217 const std::string &value, const int fd)
1218 {
1219 IMAGE_LOGD("[ModifyImageProperty] with fd:%{public}d, key:%{public}s, value:%{public}s",
1220 fd, key.c_str(), value.c_str());
1221 return exifInfo_.ModifyExifData(key, value, fd);
1222 }
1223
1224 uint32_t ExtDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
1225 const std::string &value, uint8_t *data, uint32_t size)
1226 {
1227 IMAGE_LOGD("[ModifyImageProperty] with key:%{public}s, value:%{public}s",
1228 key.c_str(), value.c_str());
1229 return exifInfo_.ModifyExifData(key, value, data, size);
1230 }
1231
1232 uint32_t ExtDecoder::GetFilterArea(const int &privacyType, std::vector<std::pair<uint32_t, uint32_t>> &ranges)
1233 {
1234 IMAGE_LOGD("[GetFilterArea] with privacyType:%{public}d ", privacyType);
1235 if (!CheckCodec()) {
1236 IMAGE_LOGE("Check codec failed");
1237 return NO_EXIF_TAG;
1238 }
1239 SkEncodedImageFormat format = codec_->getEncodedFormat();
1240 if (format != SkEncodedImageFormat::kJPEG) {
1241 return NO_EXIF_TAG;
1242 }
1243 constexpr size_t APP1_SIZE_H_OFF = 4;
1244 constexpr size_t APP1_SIZE_L_OFF = 5;
1245 constexpr size_t U8_SHIFT = 8;
1246 return ProcessWithStreamData(stream_, [this, &privacyType, &ranges](uint8_t* buffer, size_t size) {
1247 size_t appSize = (static_cast<size_t>(buffer[APP1_SIZE_H_OFF]) << U8_SHIFT) | buffer[APP1_SIZE_L_OFF];
1248 IMAGE_LOGD("[GetFilterArea]: get app1 area size");
1249 appSize += APP1_SIZE_H_OFF;
1250 auto ret = exifInfo_.GetFilterArea(buffer, (appSize < size) ? appSize : size, privacyType, ranges);
1251 if (ret != SUCCESS) {
1252 IMAGE_LOGE("[GetFilterArea]: failed to get area %{public}d", ret);
1253 }
1254 return ret;
1255 });
1256 }
1257
1258 uint32_t ExtDecoder::GetTopLevelImageNum(uint32_t &num)
1259 {
1260 if (!CheckIndexValied(SIZE_ZERO) && frameCount_ <= ZERO) {
1261 return ERR_IMAGE_DECODE_HEAD_ABNORMAL;
1262 }
1263 num = frameCount_;
1264 return SUCCESS;
1265 }
1266
1267 bool ExtDecoder::IsSupportHardwareDecode() {
1268 if (info_.isEmpty() && !DecodeHeader()) {
1269 return false;
1270 }
1271 if (!(ImageSystemProperties::GetHardWareDecodeEnabled()
1272 && codec_->getEncodedFormat() == SkEncodedImageFormat::kJPEG)) {
1273 return false;
1274 }
1275 int width = info_.width();
1276 int height = info_.height();
1277 return width >= HARDWARE_MIN_DIM && width <= HARDWARE_MAX_DIM
1278 && height >= HARDWARE_MIN_DIM && height <= HARDWARE_MAX_DIM;
1279 }
1280 } // namespace ImagePlugin
1281 } // namespace OHOS
1282