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