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