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