1 /*
2 * Copyright (C) 2024 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 "HeifDecoderImpl.h"
17
18 #ifdef HEIF_HW_DECODE_ENABLE
19 #include <dlfcn.h>
20 #include <sys/timerfd.h>
21 #include "ffrt.h"
22 #include "image_fwk_ext_manager.h"
23 #include "image_func_timer.h"
24 #include "image_system_properties.h"
25 #include "image_trace.h"
26 #include "image_utils.h"
27 #include "image_log.h"
28 #include "media_errors.h"
29
30 #include "hardware/heif_hw_decoder.h"
31 #include "heif_impl/hevc_sw_decode_param.h"
32
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 #include "libswscale/swscale.h"
37 #include "libavcodec/avcodec.h"
38 #ifdef __cplusplus
39 }
40 #endif
41
42 #include <cmath>
43 #include <sstream>
44
45 #undef LOG_DOMAIN
46 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_PLUGIN
47
48 #undef LOG_TAG
49 #define LOG_TAG "HeifDecoderImpl"
50
51 namespace OHOS {
52 namespace ImagePlugin {
53 using namespace Media;
54
55 const static int LUMA_8_BIT = 8;
56 const static int LUMA_10_BIT = 10;
57 const static int DEGREE_360 = 360;
58 const static int CHUNK_HEAD_OFFSET_1 = 1;
59 const static int CHUNK_HEAD_OFFSET_2 = 2;
60 const static int CHUNK_HEAD_OFFSET_3 = 3;
61 const static int CHUNK_HEAD_SHIFT_8 = 8;
62 const static int CHUNK_HEAD_SHIFT_16 = 16;
63 const static int CHUNK_HEAD_SHIFT_24 = 24;
64 const static int CHUNK_HEAD_SIZE = 4;
65 const static int PIXEL_OFFSET_0 = 0;
66 const static int PIXEL_OFFSET_1 = 1;
67 const static int PIXEL_OFFSET_2 = 2;
68 const static int PIXEL_OFFSET_3 = 3;
69 const static int PIXEL_SIZE_4 = 4;
70 const static int MAX_ALPHA = 255;
71
72 const static int GRID_NUM_2 = 2;
73 const static uint32_t PLANE_COUNT_TWO = 2;
74 const static uint32_t HEIF_HARDWARE_TILE_MIN_DIM = 128;
75 const static uint32_t HEIF_HARDWARE_TILE_MAX_DIM = 4096;
76 const static uint32_t HEIF_HARDWARE_DISPLAY_MIN_DIM = 128;
77 const static size_t MAX_INPUT_BUFFER_SIZE = 5 * 1024 * 1024;
78
79 const static uint16_t BT2020_PRIMARIES = 9;
80 const static int BIT_SHIFT_16BITS = 16;
81
82 typedef uint8_t uvec8[16];
83 typedef int16_t vec16[8];
84 struct YuvConstants {
85 uvec8 kUVCoeff;
86 vec16 kRGBCoeffBias;
87 };
88
89 typedef int (*FUNC_NV21ToARGBMatrix)(const uint8_t* src_y,
90 int src_stride_y,
91 const uint8_t* src_vu,
92 int src_stride_vu,
93 uint8_t* dst_argb,
94 int dst_stride_argb,
95 const struct YuvConstants* yuvconstants,
96 int width,
97 int height);
98
99 const std::string YUV_LIB_PATH = "libyuv.z.so";
100 static void* g_dlHandler = nullptr;
101 static FUNC_NV21ToARGBMatrix g_libyuvNV21ToARGBMatrixFunc = nullptr;
102 static struct YuvConstants* g_kYvuI601Constants = nullptr;
103 static struct YuvConstants* g_kYvuJPEGConstants = nullptr;
104
105 struct PixelFormatConvertParam {
106 uint8_t *data;
107 uint32_t width;
108 uint32_t height;
109 uint32_t stride;
110 uint8_t colorRangeFlag;
111 OH_NativeBuffer_Planes *planesInfo;
112 AVPixelFormat format;
113 };
114
115 const std::map<AuxiliaryPictureType, std::string> HEIF_AUXTTYPE_ID_MAP = {
116 {AuxiliaryPictureType::GAINMAP, HEIF_AUXTTYPE_ID_GAINMAP},
117 {AuxiliaryPictureType::DEPTH_MAP, HEIF_AUXTTYPE_ID_DEPTH_MAP},
118 {AuxiliaryPictureType::UNREFOCUS_MAP, HEIF_AUXTTYPE_ID_UNREFOCUS_MAP},
119 {AuxiliaryPictureType::LINEAR_MAP, HEIF_AUXTTYPE_ID_LINEAR_MAP},
120 {AuxiliaryPictureType::FRAGMENT_MAP, HEIF_AUXTTYPE_ID_FRAGMENT_MAP}
121 };
122
FillFrameInfoForPixelConvert(AVFrame * frame,PixelFormatConvertParam & param)123 static bool FillFrameInfoForPixelConvert(AVFrame *frame, PixelFormatConvertParam ¶m)
124 {
125 if (param.format == AV_PIX_FMT_NV12 || param.format == AV_PIX_FMT_NV21 || param.format == AV_PIX_FMT_P010) {
126 if (param.planesInfo == nullptr || param.planesInfo->planeCount < PLANE_COUNT_TWO) {
127 IMAGE_LOGE("planesInfo is invalid for yuv buffer");
128 return false;
129 }
130 const OH_NativeBuffer_Plane &planeY = param.planesInfo->planes[0];
131 const OH_NativeBuffer_Plane &planeUV = param.planesInfo->planes[param.format == AV_PIX_FMT_NV21 ? 2 : 1];
132 IMAGE_LOGI("planeY offset: %{public}llu, columnStride: %{public}u, rowStride: %{public}u,"
133 " planeUV offset: %{public}llu, columnStride: %{public}u, rowStride: %{public}u",
134 planeY.offset, planeY.columnStride, planeY.rowStride,
135 planeUV.offset, planeUV.columnStride, planeUV.rowStride);
136 frame->data[0] = param.data + planeY.offset;
137 frame->data[1] = param.data + planeUV.offset;
138 frame->linesize[0] = static_cast<int>(planeY.columnStride);
139 frame->linesize[1] = static_cast<int>(planeUV.columnStride);
140 } else {
141 IMAGE_LOGI("rgb stride: %{public}d", param.stride);
142 frame->data[0] = param.data;
143 frame->linesize[0] = static_cast<int>(param.stride);
144 }
145 return true;
146 }
147
UnloadLibYuv()148 static void UnloadLibYuv()
149 {
150 g_libyuvNV21ToARGBMatrixFunc = nullptr;
151 g_kYvuI601Constants = nullptr;
152 g_kYvuJPEGConstants = nullptr;
153 if (g_dlHandler) {
154 dlclose(g_dlHandler);
155 g_dlHandler = nullptr;
156 }
157 }
158
DeinitLibyuv()159 __attribute__((destructor)) void DeinitLibyuv()
160 {
161 UnloadLibYuv();
162 }
163
LoadLibyuv()164 static bool LoadLibyuv()
165 {
166 if (g_libyuvNV21ToARGBMatrixFunc && g_kYvuI601Constants && g_kYvuJPEGConstants) {
167 return true;
168 }
169 void* g_dlHandler = dlopen(YUV_LIB_PATH.c_str(), RTLD_LAZY | RTLD_NODELETE);
170 if (g_dlHandler == nullptr) {
171 IMAGE_LOGE("HeifDecoder dlopen libyuv, failed");
172 return false;
173 }
174 g_libyuvNV21ToARGBMatrixFunc = (FUNC_NV21ToARGBMatrix)dlsym(g_dlHandler, "NV21ToARGBMatrix");
175 g_kYvuI601Constants = (YuvConstants*)dlsym(g_dlHandler, "kYvuI601Constants");
176 g_kYvuJPEGConstants = (YuvConstants*)dlsym(g_dlHandler, "kYvuJPEGConstants");
177 if (!g_libyuvNV21ToARGBMatrixFunc || !g_kYvuI601Constants || !g_kYvuJPEGConstants) {
178 IMAGE_LOGE("HeifDecoder load func, failed");
179 return false;
180 }
181 return true;
182 }
183
ConvertNV12ToRGBA(PixelFormatConvertParam & srcParam,PixelFormatConvertParam & dstParam)184 static bool ConvertNV12ToRGBA(PixelFormatConvertParam &srcParam, PixelFormatConvertParam &dstParam)
185 {
186 ImageTrace trace(__func__);
187 if (!LoadLibyuv()) {
188 return false;
189 }
190 AVFrame *srcFrame = av_frame_alloc();
191 AVFrame *dstFrame = av_frame_alloc();
192 if (srcFrame == nullptr || dstFrame == nullptr) {
193 av_frame_free(&srcFrame);
194 av_frame_free(&dstFrame);
195 return false;
196 }
197 const YuvConstants *yuvConstants = g_kYvuI601Constants;
198 if (srcParam.colorRangeFlag == 1) {
199 yuvConstants = g_kYvuJPEGConstants;
200 }
201 bool res = FillFrameInfoForPixelConvert(srcFrame, srcParam) &&
202 FillFrameInfoForPixelConvert(dstFrame, dstParam) &&
203 0 == g_libyuvNV21ToARGBMatrixFunc(
204 srcFrame->data[0], srcFrame->linesize[0],
205 srcFrame->data[1], srcFrame->linesize[1],
206 dstFrame->data[0], dstFrame->linesize[0],
207 yuvConstants,
208 static_cast<int>(srcParam.width),
209 static_cast<int>(srcParam.height));
210 av_frame_free(&srcFrame);
211 av_frame_free(&dstFrame);
212 return res;
213 }
214
ConvertPixelFormat(PixelFormatConvertParam & srcParam,PixelFormatConvertParam & dstParam)215 static bool ConvertPixelFormat(PixelFormatConvertParam &srcParam, PixelFormatConvertParam &dstParam)
216 {
217 ImageTrace trace("ConvertPixelFormat %d %d", srcParam.format, dstParam.format);
218 IMAGE_LOGD("ConvertPixelFormat %{public}d %{public}d", srcParam.format, dstParam.format);
219 if (srcParam.format == AV_PIX_FMT_NV12 && dstParam.format == AV_PIX_FMT_RGBA &&
220 ConvertNV12ToRGBA(srcParam, dstParam)) {
221 return true;
222 }
223 bool res = false;
224 AVFrame *srcFrame = av_frame_alloc();
225 AVFrame *dstFrame = av_frame_alloc();
226 SwsContext *ctx = sws_getContext(static_cast<int>(srcParam.width), static_cast<int>(srcParam.height),
227 srcParam.format,
228 static_cast<int>(dstParam.width), static_cast<int>(dstParam.height),
229 dstParam.format,
230 SWS_BICUBIC, nullptr, nullptr, nullptr);
231
232 //if need applu colorspace in scale, change defult table;
233 auto srcColorTable = sws_getCoefficients(SWS_CS_DEFAULT);
234 auto dstColorTable = sws_getCoefficients(SWS_CS_DEFAULT);
235 sws_setColorspaceDetails(ctx, srcColorTable,
236 srcParam.colorRangeFlag,
237 dstColorTable, 0,
238 0, 1 << BIT_SHIFT_16BITS, 1 << BIT_SHIFT_16BITS);
239 if (srcFrame != nullptr && dstFrame != nullptr && ctx != nullptr) {
240 res = FillFrameInfoForPixelConvert(srcFrame, srcParam)
241 && FillFrameInfoForPixelConvert(dstFrame, dstParam)
242 && sws_scale(ctx, srcFrame->data, srcFrame->linesize, 0,
243 static_cast<int>(srcParam.height), dstFrame->data, dstFrame->linesize);
244 }
245
246 av_frame_free(&srcFrame);
247 av_frame_free(&dstFrame);
248 sws_freeContext(ctx);
249 return res;
250 }
251
GraphicPixFmt2AvPixFmtForYuv(GraphicPixelFormat pixelFormat)252 static AVPixelFormat GraphicPixFmt2AvPixFmtForYuv(GraphicPixelFormat pixelFormat)
253 {
254 AVPixelFormat res = AV_PIX_FMT_NV12;
255 switch (pixelFormat) {
256 case GRAPHIC_PIXEL_FMT_YCBCR_420_SP:
257 res = AV_PIX_FMT_NV12;
258 break;
259 case GRAPHIC_PIXEL_FMT_YCRCB_420_SP:
260 res = AV_PIX_FMT_NV21;
261 break;
262 case GRAPHIC_PIXEL_FMT_YCBCR_P010:
263 res = AV_PIX_FMT_P010;
264 break;
265 default:
266 break;
267 }
268 return res;
269 }
270
PixFmt2AvPixFmtForOutput(PixelFormat pixelFormat)271 static AVPixelFormat PixFmt2AvPixFmtForOutput(PixelFormat pixelFormat)
272 {
273 AVPixelFormat res = AV_PIX_FMT_RGBA;
274 switch (pixelFormat) {
275 case PixelFormat::RGBA_8888:
276 res = AV_PIX_FMT_RGBA;
277 break;
278 case PixelFormat::BGRA_8888:
279 res = AV_PIX_FMT_BGRA;
280 break;
281 case PixelFormat::RGB_565:
282 res = AV_PIX_FMT_RGB565;
283 break;
284 case PixelFormat::NV12:
285 res = AV_PIX_FMT_NV12;
286 break;
287 case PixelFormat::NV21:
288 res = AV_PIX_FMT_NV21;
289 break;
290 case PixelFormat::RGBA_1010102:
291 res = AV_PIX_FMT_X2BGR10;
292 break;
293 default:
294 break;
295 }
296 return res;
297 }
298
SkHeifColorFormat2PixelFormat(SkHeifColorFormat format)299 static PixelFormat SkHeifColorFormat2PixelFormat(SkHeifColorFormat format)
300 {
301 PixelFormat res = PixelFormat::UNKNOWN;
302 switch (format) {
303 case kHeifColorFormat_RGB565:
304 res = PixelFormat::RGB_565;
305 break;
306 case kHeifColorFormat_RGBA_8888:
307 res = PixelFormat::RGBA_8888;
308 break;
309 case kHeifColorFormat_BGRA_8888:
310 res = PixelFormat::BGRA_8888;
311 break;
312 case kHeifColorFormat_NV12:
313 res = PixelFormat::NV12;
314 break;
315 case kHeifColorFormat_NV21:
316 res = PixelFormat::NV21;
317 break;
318 case kHeifColorFormat_RGBA_1010102:
319 res = PixelFormat::RGBA_1010102;
320 break;
321 case kHeifColorFormat_P010_NV12:
322 res = PixelFormat::YCBCR_P010;
323 break;
324 case kHeifColorFormat_P010_NV21:
325 res = PixelFormat::YCRCB_P010;
326 break;
327 default:
328 IMAGE_LOGE("Unsupported dst pixel format: %{public}d", format);
329 break;
330 }
331 return res;
332 }
333
HeifDecoderImpl()334 HeifDecoderImpl::HeifDecoderImpl()
335 : outPixelFormat_(PixelFormat::RGBA_8888),
336 dstMemory_(nullptr), dstRowStride_(0), dstHwBuffer_(nullptr),
337 gainmapDstMemory_(nullptr), gainmapDstRowStride_(0),
338 auxiliaryDstMemory_(nullptr), auxiliaryDstRowStride_(0),
339 auxiliaryDstMemorySize_(0), isAuxiliaryDecode_(false),
340 auxiliaryDstHwbuffer_(nullptr) {}
341
~HeifDecoderImpl()342 HeifDecoderImpl::~HeifDecoderImpl()
343 {
344 if (srcMemory_ != nullptr) {
345 delete[] srcMemory_;
346 }
347 }
348
init(HeifStream * stream,HeifFrameInfo * frameInfo)349 bool HeifDecoderImpl::init(HeifStream *stream, HeifFrameInfo *frameInfo)
350 {
351 ImageTrace trace("HeifDecoderImpl::init");
352 if (stream == nullptr) {
353 return false;
354 }
355
356 size_t fileLength = stream->getLength();
357 if (srcMemory_ == nullptr) {
358 if (fileLength == 0) {
359 IMAGE_LOGE("file size is 0");
360 return false;
361 }
362 srcMemory_ = new uint8_t[fileLength];
363 if (srcMemory_ == nullptr) {
364 return false;
365 }
366 stream->read(srcMemory_, fileLength);
367 }
368 if (stream != nullptr) {
369 delete stream;
370 stream = nullptr;
371 }
372
373 heif_error err = HeifParser::MakeFromMemory(srcMemory_, fileLength, false, &parser_);
374 if (parser_ == nullptr || err != heif_error_ok) {
375 IMAGE_LOGE("make heif parser failed, err: %{public}d", err);
376 return false;
377 }
378 primaryImage_ = parser_->GetPrimaryImage();
379 if (primaryImage_ == nullptr) {
380 IMAGE_LOGE("heif primary image is null");
381 return false;
382 }
383 gainmapImage_ = parser_->GetGainmapImage();
384 std::shared_ptr<HeifImage> tmapImage = parser_->GetTmapImage();
385 if (tmapImage != nullptr) {
386 InitFrameInfo(&tmapInfo_, tmapImage);
387 }
388 return Reinit(frameInfo);
389 }
390
GetGridInfo()391 GridInfo HeifDecoderImpl::GetGridInfo()
392 {
393 return gridInfo_;
394 }
395
CheckAuxiliaryMap(AuxiliaryPictureType type)396 bool HeifDecoderImpl::CheckAuxiliaryMap(AuxiliaryPictureType type)
397 {
398 if (parser_ == nullptr) {
399 IMAGE_LOGE("Heif parser is nullptr.");
400 return false;
401 }
402
403 auto iter = HEIF_AUXTTYPE_ID_MAP.find(type);
404 switch (type) {
405 case AuxiliaryPictureType::GAINMAP:
406 auxiliaryImage_ = parser_->GetGainmapImage();
407 break;
408 case AuxiliaryPictureType::DEPTH_MAP:
409 case AuxiliaryPictureType::UNREFOCUS_MAP:
410 case AuxiliaryPictureType::LINEAR_MAP:
411 case AuxiliaryPictureType::FRAGMENT_MAP:
412 auxiliaryImage_ = parser_->GetAuxiliaryMapImage(iter->second);
413 break;
414 default:
415 auxiliaryImage_ = nullptr;
416 IMAGE_LOGE("Invalid AuxiliaryPictureType: %{public}d", type);
417 break;
418 }
419
420 if (auxiliaryImage_ == nullptr) {
421 IMAGE_LOGE("Auxiliary map type that does not exist");
422 return false;
423 }
424
425 return true;
426 }
427
setAuxiliaryMap(AuxiliaryPictureType type)428 bool HeifDecoderImpl::setAuxiliaryMap(AuxiliaryPictureType type)
429 {
430 bool cond = auxiliaryImage_ == nullptr && !CheckAuxiliaryMap(type);
431 CHECK_ERROR_RETURN_RET_LOG(cond, false, "make heif parser failed");
432
433 InitFrameInfo(&auxiliaryImageInfo_, auxiliaryImage_);
434 InitGridInfo(auxiliaryImage_, auxiliaryGridInfo_);
435 return true;
436 }
437
Reinit(HeifFrameInfo * frameInfo)438 bool HeifDecoderImpl::Reinit(HeifFrameInfo *frameInfo)
439 {
440 InitFrameInfo(&imageInfo_, primaryImage_);
441 InitGridInfo(primaryImage_, gridInfo_);
442 if (gainmapImage_ != nullptr) {
443 InitFrameInfo(&gainmapImageInfo_, gainmapImage_);
444 InitGridInfo(gainmapImage_, gainmapGridInfo_);
445 }
446 if (frameInfo != nullptr) {
447 *frameInfo = imageInfo_;
448 }
449 return true;
450 }
451
InitFrameInfo(HeifFrameInfo * info,const std::shared_ptr<HeifImage> & image)452 void HeifDecoderImpl::InitFrameInfo(HeifFrameInfo *info, const std::shared_ptr<HeifImage> &image)
453 {
454 if (info == nullptr || image == nullptr) {
455 IMAGE_LOGE("InitFrameInfo info or image is null");
456 return;
457 }
458 std::string imageType = parser_->GetItemType(image->GetItemId());
459 if (imageType == "iovl") {
460 std::vector<std::shared_ptr<HeifImage>> iovlImages;
461 parser_->GetIovlImages(image->GetItemId(), iovlImages);
462 if (iovlImages.empty() || iovlImages[0] == nullptr) {
463 IMAGE_LOGE("grid image has no tile image");
464 return;
465 }
466 info->mWidth = iovlImages[0]->GetOriginalWidth();
467 info->mHeight = iovlImages[0]->GetOriginalHeight();
468 } else {
469 info->mWidth = image->GetOriginalWidth();
470 info->mHeight = image->GetOriginalHeight();
471 }
472 info->mRotationAngle = (DEGREE_360 - image->GetRotateDegrees()) % DEGREE_360;
473 info->mBytesPerPixel = static_cast<uint32_t>(ImageUtils::GetPixelBytes(outPixelFormat_));
474 info->mDurationUs = 0;
475 SetColorSpaceInfo(info, image);
476 if (info->mIccData.empty() && !info->hasNclxColor && (parser_->GetItemType(image->GetItemId())== "grid")) {
477 std::vector<std::shared_ptr<HeifImage>> tileImages;
478 parser_->GetTileImages(image->GetItemId(), tileImages);
479 if (!tileImages.empty()) {
480 SetColorSpaceInfo(info, tileImages[0]);
481 }
482 }
483 }
484
SetColorSpaceInfo(HeifFrameInfo * info,const std::shared_ptr<HeifImage> & image)485 void HeifDecoderImpl::SetColorSpaceInfo(HeifFrameInfo* info, const std::shared_ptr<HeifImage>& image)
486 {
487 auto &iccProfile = image->GetRawColorProfile();
488 size_t iccSize = iccProfile != nullptr ? iccProfile->GetData().size() : 0;
489 if (iccSize > 0) {
490 auto iccProfileData = iccProfile->GetData().data();
491 info->mIccData.assign(iccProfileData, iccProfileData + iccSize);
492 } else {
493 info->mIccData.clear();
494 }
495 auto& nclx = image->GetNclxColorProfile();
496 if (nclx != nullptr) {
497 info->hasNclxColor = true;
498 info->nclxColor.colorPrimaries = nclx->GetColorPrimaries();
499 info->nclxColor.transferCharacteristics = nclx->GetTransferCharacteristics();
500 info->nclxColor.matrixCoefficients = nclx->GetMatrixCoefficients();
501 info->nclxColor.fullRangeFlag = nclx->GetFullRangeFlag();
502 } else {
503 info->hasNclxColor = false;
504 }
505 }
506
InitGridInfo(const std::shared_ptr<HeifImage> & image,GridInfo & gridInfo)507 void HeifDecoderImpl::InitGridInfo(const std::shared_ptr<HeifImage> &image, GridInfo &gridInfo)
508 {
509 if (!image) {
510 IMAGE_LOGE("InitGridInfo image is null");
511 return;
512 }
513 std::string imageType = parser_->GetItemType(image->GetItemId());
514 if (imageType == "iovl") {
515 std::vector<std::shared_ptr<HeifImage>> iovlImages;
516 parser_->GetIovlImages(image->GetItemId(), iovlImages);
517 if (iovlImages.empty() || iovlImages[0] == nullptr) {
518 IMAGE_LOGE("grid image has no tile image");
519 return;
520 }
521 gridInfo.displayWidth = iovlImages[0]->GetOriginalWidth();
522 gridInfo.displayHeight = iovlImages[0]->GetOriginalHeight();
523 } else {
524 gridInfo.displayWidth = image->GetOriginalWidth();
525 gridInfo.displayHeight = image->GetOriginalHeight();
526 }
527
528 gridInfo.colorRangeFlag = image->GetColorRangeFlag();
529 GetTileSize(image, gridInfo);
530 GetRowColNum(gridInfo);
531 }
532
GetTileSize(const std::shared_ptr<HeifImage> & image,GridInfo & gridInfo)533 void HeifDecoderImpl::GetTileSize(const std::shared_ptr<HeifImage> &image, GridInfo &gridInfo)
534 {
535 if (!image) {
536 IMAGE_LOGE("GetTileSize image is null");
537 return;
538 }
539
540 std::string imageType = parser_->GetItemType(image->GetItemId());
541 if (imageType == "hvc1" || image->IsMovieImage()) {
542 gridInfo.tileWidth = image->GetOriginalWidth();
543 gridInfo.tileHeight = image->GetOriginalHeight();
544 return;
545 }
546 if (imageType == "iovl") {
547 std::vector<std::shared_ptr<HeifImage>> iovlImages;
548 parser_->GetIovlImages(image->GetItemId(), iovlImages);
549 if (iovlImages.empty() || iovlImages[0] == nullptr) {
550 IMAGE_LOGE("grid image has no tile image");
551 return;
552 }
553 gridInfo.tileWidth = iovlImages[0]->GetOriginalWidth();
554 gridInfo.tileHeight = iovlImages[0]->GetOriginalHeight();
555 }
556 if (imageType == "iden") {
557 std::shared_ptr<HeifImage> idenImage;
558 parser_->GetIdenImage(image->GetItemId(), idenImage);
559 if (idenImage != nullptr && idenImage != image) {
560 GetTileSize(idenImage, gridInfo);
561 }
562 return;
563 }
564 if (imageType != "grid") {
565 IMAGE_LOGE("GetTileSize unsupported image type: %{public}s", imageType.c_str());
566 return;
567 }
568 std::vector<std::shared_ptr<HeifImage>> tileImages;
569 parser_->GetTileImages(image->GetItemId(), tileImages);
570 if (tileImages.empty() || tileImages[0] == nullptr) {
571 IMAGE_LOGE("grid image has no tile image");
572 return;
573 }
574 gridInfo.tileWidth = tileImages[0]->GetOriginalWidth();
575 gridInfo.tileHeight = tileImages[0]->GetOriginalHeight();
576 }
577
GetRowColNum(GridInfo & gridInfo)578 void HeifDecoderImpl::GetRowColNum(GridInfo &gridInfo)
579 {
580 if (gridInfo.tileWidth != 0) {
581 gridInfo.cols = static_cast<size_t>(ceil((double)gridInfo.displayWidth / (double)gridInfo.tileWidth));
582 }
583 if (gridInfo.tileHeight != 0) {
584 gridInfo.rows = static_cast<size_t>(ceil((double)gridInfo.displayHeight / (double)gridInfo.tileHeight));
585 }
586 }
587
GetInPixelFormat(const std::shared_ptr<HeifImage> & image)588 GraphicPixelFormat HeifDecoderImpl::GetInPixelFormat(const std::shared_ptr<HeifImage> &image)
589 {
590 return (image != nullptr && image->GetLumaBitNum() == LUMA_10_BIT) ?
591 GRAPHIC_PIXEL_FMT_YCBCR_P010 : GRAPHIC_PIXEL_FMT_YCBCR_420_SP;
592 }
593
getSequenceInfo(HeifFrameInfo * frameInfo,size_t * frameCount)594 bool HeifDecoderImpl::getSequenceInfo(HeifFrameInfo *frameInfo, size_t *frameCount)
595 {
596 // unimplemented
597 return false;
598 }
599
setOutputColor(SkHeifColorFormat heifColor)600 bool HeifDecoderImpl::setOutputColor(SkHeifColorFormat heifColor)
601 {
602 outPixelFormat_ = SkHeifColorFormat2PixelFormat(heifColor);
603 imageInfo_.mBytesPerPixel = static_cast<uint32_t>(ImageUtils::GetPixelBytes(outPixelFormat_));
604 return outPixelFormat_ != PixelFormat::UNKNOWN;
605 }
606
IsSupportHardwareDecode(const GridInfo & gridInfo)607 static bool IsSupportHardwareDecode(const GridInfo &gridInfo)
608 {
609 if (!ImageSystemProperties::GetHeifHardwareDecodeEnabled()) {
610 return false;
611 }
612 return gridInfo.tileWidth >= HEIF_HARDWARE_TILE_MIN_DIM &&
613 gridInfo.tileHeight >= HEIF_HARDWARE_TILE_MIN_DIM &&
614 gridInfo.tileWidth <= HEIF_HARDWARE_TILE_MAX_DIM &&
615 gridInfo.tileHeight <= HEIF_HARDWARE_TILE_MAX_DIM &&
616 gridInfo.displayWidth >= HEIF_HARDWARE_DISPLAY_MIN_DIM &&
617 gridInfo.displayHeight >= HEIF_HARDWARE_DISPLAY_MIN_DIM;
618 }
619
decode(HeifFrameInfo * frameInfo)620 bool HeifDecoderImpl::decode(HeifFrameInfo *frameInfo)
621 {
622 ImageTrace trace("HeifDecoderImpl::decode");
623 if (!IsSupportHardwareDecode(gridInfo_)) {
624 return SwDecode();
625 }
626 sptr<SurfaceBuffer> hwBuffer;
627 bool decodeRes = HwDecodeImage(nullptr, primaryImage_, gridInfo_, &hwBuffer, true);
628 if (!decodeRes) {
629 return SwDecode();
630 }
631
632 bool convertRes = IsDirectYUVDecode() ||
633 ConvertHwBufferPixelFormat(hwBuffer, gridInfo_, dstMemory_, dstRowStride_);
634 if (!convertRes) {
635 return false;
636 }
637 bool hwApplyAlphaImageRes = HwApplyAlphaImage(primaryImage_, dstMemory_, dstRowStride_);
638 if (!hwApplyAlphaImageRes) {
639 SwApplyAlphaImage(primaryImage_, dstMemory_, dstRowStride_);
640 }
641 if (hwBuffer && (hwBuffer->GetUsage() & BUFFER_USAGE_MEM_MMZ_CACHE)) {
642 GSError err = hwBuffer->InvalidateCache();
643 if (err != GSERROR_OK) {
644 IMAGE_LOGE("InvalidateCache failed, GSError=%{public}d", err);
645 }
646 }
647 return true;
648 }
649
SwDecode(bool isSharedMemory)650 bool HeifDecoderImpl::SwDecode(bool isSharedMemory)
651 {
652 HevcSoftDecodeParam param {
653 gridInfo_, outPixelFormat_,
654 dstMemory_, 0,
655 static_cast<uint32_t>(dstRowStride_), dstHwBuffer_,
656 isSharedMemory
657 };
658 bool decodeRes = SwDecodeImage(primaryImage_, param, gridInfo_, true);
659 if (!decodeRes) {
660 return false;
661 }
662 SwApplyAlphaImage(primaryImage_, dstMemory_, dstRowStride_);
663 if (dstHwBuffer_ && (dstHwBuffer_->GetUsage() & BUFFER_USAGE_MEM_MMZ_CACHE)) {
664 GSError err = dstHwBuffer_->Map();
665 if (err != GSERROR_OK) {
666 IMAGE_LOGE("SurfaceBuffer Map failed, GSError=%{public}d", err);
667 return true;
668 }
669 err = dstHwBuffer_->FlushCache();
670 if (err != GSERROR_OK) {
671 IMAGE_LOGE("FlushCache failed, GSError=%{public}d", err);
672 }
673 }
674 return true;
675 }
676
DodecodeGainmap(std::shared_ptr<HeifImage> & gainmap,GridInfo & gainmapGridInfo,uint8_t * gainmapDstMemory,size_t gainmapDstRowStride)677 bool HeifDecodeImpl::DodecodeGainmap(std::shared_ptr<HeifImage> &gainmap, GridInfo &gainmapGridInfo,
678 uint8_t *gainmapDstMemory, size_t gainmapDstRowStride)
679 {
680 sptr<SurfaceBuffer> hwBuffer;
681 bool decodeRes = HwDecodeImage(nullptr, gainmapImage, gainmapGridInfo, &hwBuffer, false);
682 if (!decodeRes) {
683 sptr<SurfaceBuffer> swHwBuffer;
684 bool swdecodeRes = SwDecodeGainmap(gainmapImage, gainmapGridInfo, &swHwBuffer);
685 if (!swdecodeRes) {
686 IMAGE_LOGE("HeifDecoderImpl::SwDecodeGainmap failed too");
687 return false;
688 }
689 bool swConvertRes = IsDirectYuvDecode() ||
690 ConvertHwBufferPixelFormat(swHwBuffer, gainmapGridInfo, gainmapDstMemory, gainmapDstRowStride);
691 if (!swConvertRes) {
692 return false;
693 }
694 return true;
695 }
696
697 bool ConvertRes = IsDirectYuvDecode() ||
698 ConvertHwBufferPixelFormat(hwBuffer, gainmapGridInfo, gainmapDstMemory, gainmapDstRowStride);
699 if (!ConvertRes) {
700 return false;
701 }
702 return true;
703 }
704
decodeGainmap()705 bool HeifDecoderImpl::decodeGainmap()
706 {
707 ImageTrace trace("HeifDecoderImpl::decodeGainmap");
708 return DodecodeGainmap(gainmapImage_, gainmapGridInfo_, gainmapDstMemory_, gainmapDstRowStride_);
709 }
710
decodeAuxiliaryMap()711 bool HeifDecoderImpl::decodeAuxiliaryMap()
712 {
713 ImageTrace trace("HeifDecoderImpl::decodeAuxiliaryMap");
714 if (auxiliaryImage_ != nullptr && parser_ != nullptr &&
715 parser_->GetItemType(auxiliaryImage_->GetItemId()) == "mime") {
716 return HwDecodeMimeImage(auxiliaryImage_);
717 }
718 return DodecodeGainmap(auxiliaryImage_, auxiliaryGridInfo_, auxiliaryDstMemory_, auxiliaryDstRowStride_);
719 }
720
ReleaseHwDecoder(HeifHardwareDecoder * hwDecoder,bool isReuse)721 void HeifDecoderImpl::ReleaseHwDecoder(HeifHardwareDecoder *hwDecoder, bool isReuse)
722 {
723 if (isReuse || hwDecoder == nullptr) {
724 return;
725 }
726 int timerFd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
727 if (timerFd >= 0) {
728 close(timerFd);
729 ffrt::submit([hwDecoder] {
730 ImageTrace trace("delete hwDecoder");
731 delete hwDecoder;
732 }, {}, {});
733 } else {
734 delete hwDecoder;
735 }
736 }
737
HwDecodeImage(HeifHardwareDecoder * hwDecoder,std::shared_ptr<HeifImage> & image,GridInfo & gridInfo,sptr<SurfaceBuffer> * outBuffer,bool isPrimary)738 bool HeifDecoderImpl::HwDecodeImage(HeifHardwareDecoder *hwDecoder,
739 std::shared_ptr<HeifImage> &image, GridInfo &gridInfo,
740 sptr<SurfaceBuffer> *outBuffer, bool isPrimary)
741 {
742 if (outPixelFormat_ == PixelFormat::UNKNOWN) {
743 IMAGE_LOGE("unknown pixel type: %{public}d", outPixelFormat_);
744 return false;
745 }
746
747 if (image == nullptr || outBuffer == nullptr) {
748 return false;
749 }
750
751 bool isReuseHwDecoder = hwDecoder != nullptr;
752 if (!isReuseHwDecoder) {
753 hwDecoder = new (std::nothrow) HeifHardwareDecoder();
754 if (hwDecoder == nullptr) {
755 IMAGE_LOGE("make HeifHardwareDecoder failed");
756 return false;
757 }
758 }
759
760 if (image->IsMovieImage()) {
761 sptr<SurfaceBuffer> hwMovieBuffer = IsDirectYUVDecode() ? sptr<SurfaceBuffer>(dstHwBuffer_) :
762 hwDecoder->AllocateOutputBuffer(gridInfo.tileWidth, gridInfo.tileHeight,
763 GRAPHIC_PIXEL_FMT_YCBCR_420_SP);
764 bool res = HwDecodeMovieFirstFrameImage(hwDecoder, image, gridInfo, hwMovieBuffer);
765 *outBuffer = hwMovieBuffer;
766 return res;
767 }
768
769 std::string imageType = parser_->GetItemType(image->GetItemId());
770 if (imageType == "iden") {
771 bool res = HwDecodeIdenImage(hwDecoder, image, gridInfo, outBuffer, isPrimary);
772 ReleaseHwDecoder(hwDecoder, isReuseHwDecoder);
773 return res;
774 }
775
776 GraphicPixelFormat inPixelFormat = GetInPixelFormat(image);
777 sptr<SurfaceBuffer> hwBuffer;
778 if (isAuxiliaryDecode_ && IsDirectYUVDecode()) {
779 hwBuffer = sptr<SurfaceBuffer>(auxiliaryDstHwbuffer_);
780 } else {
781 hwBuffer = isPrimary && IsDirectYUVDecode() ? sptr<SurfaceBuffer>(dstHwBuffer_) :
782 hwDecoder->AllocateOutputBuffer(gridInfo.displayWidth, gridInfo.displayHeight, inPixelFormat);
783 }
784 if (hwBuffer == nullptr) {
785 IMAGE_LOGE("decode AllocateOutputBuffer return null");
786 ReleaseHwDecoder(hwDecoder, isReuseHwDecoder);
787 return false;
788 }
789 if (IsDirectYUVDecode()) {
790 inPixelFormat = static_cast<GraphicPixelFormat>(hwBuffer->GetFormat());
791 }
792
793 bool res = false;
794 IMAGE_LOGI("HeifDecoderImpl::DecodeImage width: %{public}d, height: %{public}d, imageType: %{public}s,"
795 "inPixelFormat: %{public}d", gridInfo.displayWidth, gridInfo.displayHeight, imageType.c_str(), inPixelFormat);
796 if (imageType == "grid") {
797 gridInfo.enableGrid = true;
798 res = HwDecodeGrids(hwDecoder, image, gridInfo, hwBuffer);
799 } else if (imageType == "hvc1") {
800 gridInfo.enableGrid = false;
801 res = HwDecodeSingleImage(hwDecoder, image, gridInfo, hwBuffer);
802 } else if (imageType == "iovl") {
803 gridInfo.enableGrid = false;
804 res = HwDecodeIovls(hwDecoder, image, gridInfo, hwBuffer);
805 }
806 if (res) {
807 *outBuffer = hwBuffer;
808 }
809 ReleaseHwDecoder(hwDecoder, isReuseHwDecoder);
810 return res;
811 }
812
PreparePackedInput(HeifHardwareDecoder * hwDecoder,std::vector<std::shared_ptr<HeifImage>> tileImages,std::vector<std::vector<uint8_t>> & packedInput,size_t gridCount)813 void HeifDecoderImpl::PreparePackedInput(HeifHardwareDecoder *hwDecoder,
814 std::vector<std::shared_ptr<HeifImage>> tileImages,
815 std::vector<std::vector<uint8_t>> &packedInput, size_t gridCount)
816 {
817 if (hwDecoder->IsPackedInputSupported()) {
818 size_t gridLength = 0;
819 size_t inputIndex = 0;
820 packedInput.resize(GRID_NUM_2);
821 for (size_t index = 0; index < gridCount; ++index) {
822 std::shared_ptr<HeifImage> &tileImage = tileImages[index];
823 std::shared_ptr<HeifImage> nextTileImage;
824 if (index == 0) {
825 // get hvcc header
826 parser_->GetItemData(tileImage->GetItemId(), &packedInput[inputIndex], heif_only_header);
827 ProcessChunkHead(packedInput[inputIndex].data(), packedInput[inputIndex].size());
828 ++inputIndex;
829 }
830 if (packedInput[inputIndex].size() + gridLength >= MAX_INPUT_BUFFER_SIZE) {
831 ProcessChunkHead(packedInput[inputIndex].data(), packedInput[inputIndex].size());
832 ++inputIndex;
833 packedInput.emplace_back(std::vector<uint8_t>());
834 }
835 parser_->GetItemData(tileImage->GetItemId(), &packedInput[inputIndex], heif_no_header);
836 gridLength = 0;
837 if (index + 1 != gridCount) {
838 nextTileImage = tileImages[index + 1];
839 parser_->GetGridLength(nextTileImage->GetItemId(), gridLength);
840 }
841 }
842 ProcessChunkHead(packedInput[inputIndex].data(), packedInput[inputIndex].size());
843 } else {
844 packedInput.resize(gridCount + 1);
845 for (size_t index = 0; index < gridCount; ++index) {
846 std::shared_ptr<HeifImage> &tileImage = tileImages[index];
847 if (index == 0) {
848 // get hvcc header
849 parser_->GetItemData(tileImage->GetItemId(), &packedInput[index], heif_only_header);
850 ProcessChunkHead(packedInput[index].data(), packedInput[index].size());
851 }
852 parser_->GetItemData(tileImage->GetItemId(), &packedInput[index + 1], heif_no_header);
853 ProcessChunkHead(packedInput[index + 1].data(), packedInput[index + 1].size());
854 }
855 }
856 }
857
HwDecodeGrids(HeifHardwareDecoder * hwDecoder,std::shared_ptr<HeifImage> & image,GridInfo & gridInfo,sptr<SurfaceBuffer> & hwBuffer)858 bool HeifDecoderImpl::HwDecodeGrids(HeifHardwareDecoder *hwDecoder, std::shared_ptr<HeifImage> &image,
859 GridInfo &gridInfo, sptr<SurfaceBuffer> &hwBuffer)
860 {
861 if (hwDecoder == nullptr || image == nullptr) {
862 IMAGE_LOGE("HeifDecoderImpl::DecodeGrids hwDecoder or image is nullptr");
863 return false;
864 }
865 std::vector<std::shared_ptr<HeifImage>> tileImages;
866 parser_->GetTileImages(image->GetItemId(), tileImages);
867 if (tileImages.empty()) {
868 IMAGE_LOGE("grid image has no tile image");
869 return false;
870 }
871 size_t gridCount = tileImages.size();
872 if (gridCount != (gridInfo.cols * gridInfo.rows)) {
873 IMAGE_LOGE("grid count not equal actual decode quantity");
874 return false;
875 }
876 std::vector<std::vector<uint8_t>> packedInput;
877 PreparePackedInput(hwDecoder, tileImages, packedInput, gridCount);
878
879 uint32_t err = hwDecoder->DoDecode(gridInfo, packedInput, hwBuffer);
880 if (err != SUCCESS) {
881 IMAGE_LOGE("heif hw decoder return error: %{public}d, width: %{public}d, height: %{public}d,"
882 " imageType: grid, inPixelFormat: %{public}d, colNum: %{public}d, rowNum: %{public}d,"
883 " tileWidth: %{public}d, tileHeight: %{public}d, hvccLen: %{public}zu",
884 err, gridInfo.displayWidth, gridInfo.displayHeight,
885 hwBuffer->GetFormat(), gridInfo.cols, gridInfo.rows,
886 gridInfo.tileWidth, gridInfo.tileHeight, packedInput[0].size());
887 SetHardwareDecodeErrMsg(gridInfo.tileWidth, gridInfo.tileHeight);
888 return false;
889 }
890 return true;
891 }
892
HwDecodeIovls(HeifHardwareDecoder * hwDecoder,std::shared_ptr<HeifImage> & image,GridInfo & gridInfo,sptr<SurfaceBuffer> & hwBuffer)893 bool HeifDecoderImpl::HwDecodeIovls(HeifHardwareDecoder *hwDecoder, std::shared_ptr<HeifImage> &image,
894 GridInfo &gridInfo, sptr<SurfaceBuffer> &hwBuffer)
895 {
896 if (hwDecoder == nullptr || image == nullptr) {
897 IMAGE_LOGE("HeifDecoderImpl::HwDecodeIovls hwDecoder or image is nullptr");
898 return false;
899 }
900 std::vector<std::shared_ptr<HeifImage>> iovlImages;
901 parser_->GetIovlImages(image->GetItemId(), iovlImages);
902 if (iovlImages.empty()) {
903 IMAGE_LOGE("iovl image has no tile image");
904 return false;
905 }
906
907 return HwDecodeSingleImage(hwDecoder, iovlImages[0], gridInfo, hwBuffer);
908 }
909
HwDecodeIdenImage(HeifHardwareDecoder * hwDecoder,std::shared_ptr<HeifImage> & image,GridInfo & gridInfo,sptr<SurfaceBuffer> * outBuffer,bool isPrimary)910 bool HeifDecoderImpl::HwDecodeIdenImage(HeifHardwareDecoder *hwDecoder,
911 std::shared_ptr<HeifImage> &image, GridInfo &gridInfo,
912 sptr<SurfaceBuffer> *outBuffer, bool isPrimary)
913 {
914 bool cond = !image;
915 CHECK_ERROR_RETURN_RET(cond, false);
916 std::shared_ptr<HeifImage> idenImage;
917 parser_->GetIdenImage(image->GetItemId(), idenImage);
918 cond = idenImage == nullptr || idenImage == image;
919 CHECK_ERROR_RETURN_RET_LOG(cond, false, "invalid iden image");
920 return HwDecodeImage(hwDecoder, idenImage, gridInfo, outBuffer, isPrimary);
921 }
922
HwDecodeSingleImage(HeifHardwareDecoder * hwDecoder,std::shared_ptr<HeifImage> & image,GridInfo & gridInfo,sptr<SurfaceBuffer> & hwBuffer)923 bool HeifDecoderImpl::HwDecodeSingleImage(HeifHardwareDecoder *hwDecoder,
924 std::shared_ptr<HeifImage> &image,
925 GridInfo &gridInfo, sptr<SurfaceBuffer> &hwBuffer)
926 {
927 if (hwDecoder == nullptr || image == nullptr) {
928 IMAGE_LOGE("HeifDecoderImpl::DecodeSingleImage hwDecoder or image is nullptr");
929 return false;
930 }
931 std::vector<std::vector<uint8_t>> inputs(GRID_NUM_2);
932
933 parser_->GetItemData(image->GetItemId(), &inputs[0], heif_only_header);
934 ProcessChunkHead(inputs[0].data(), inputs[0].size());
935
936 parser_->GetItemData(image->GetItemId(), &inputs[1], heif_no_header);
937 ProcessChunkHead(inputs[1].data(), inputs[1].size());
938
939 uint32_t err = hwDecoder->DoDecode(gridInfo, inputs, hwBuffer);
940 if (err != SUCCESS) {
941 IMAGE_LOGE("heif hw decoder return error: %{public}d, width: %{public}d, height: %{public}d,"
942 " imageType: hvc1, inPixelFormat: %{public}d, colNum: %{public}d, rowNum: %{public}d,"
943 " tileWidth: %{public}d, tileHeight: %{public}d, hvccLen: %{public}zu, dataLen: %{public}zu",
944 err, gridInfo.displayWidth, gridInfo.displayHeight,
945 hwBuffer->GetFormat(), gridInfo.cols, gridInfo.rows,
946 gridInfo.tileWidth, gridInfo.tileHeight, inputs[0].size(), inputs[1].size());
947 SetHardwareDecodeErrMsg(gridInfo.tileWidth, gridInfo.tileHeight);
948 return false;
949 }
950 return true;
951 }
952
HwDecodeMimeImage(std::shared_ptr<HeifImage> & image)953 bool HeifDecoderImpl::HwDecodeMimeImage(std::shared_ptr<HeifImage> &image)
954 {
955 if (image == nullptr) {
956 IMAGE_LOGE("HeifDecoderImpl::DecodeSingleImage image is nullptr");
957 return false;
958 }
959 std::vector<uint8_t> inputs;
960 parser_->GetItemData(image->GetItemId(), &inputs, heif_only_header);
961 ProcessChunkHead(inputs.data(), inputs.size());
962
963 if (auxiliaryDstMemory_ == nullptr || auxiliaryDstMemorySize_ == 0 || inputs.size() == 0) {
964 IMAGE_LOGE("%{public}s: params fail auxiliaryDstMemorySize_ is %{public}zu, input size is %{public}zu",
965 __func__, auxiliaryDstMemorySize_, inputs.size());
966 return false;
967 }
968 if (memcpy_s(auxiliaryDstMemory_, auxiliaryDstMemorySize_, inputs.data(), inputs.size()) != EOK) {
969 IMAGE_LOGE("%{public}s: memcpy failed, auxiliaryDstMemorySize_ is %{public}zu, input size is %{public}ld",
970 __func__, auxiliaryDstMemorySize_, inputs.size());
971 return false;
972 }
973 return true;
974 }
975
HwDecodeMovieFirstFrameImage(HeifHardwareDecoder * hwDecoder,std::shared_ptr<HeifImage> & image,GridInfo & gridInfo,sptr<SurfaceBuffer> & hwBuffer)976 bool HeifDecoderImpl::HwDecodeMovieFirstFrameImage(HeifHardwareDecoder *hwDecoder,
977 std::shared_ptr<HeifImage> &image,
978 GridInfo &gridInfo, sptr<SurfaceBuffer> &hwBuffer)
979 {
980 if (hwDecoder == nullptr || image == nullptr) {
981 IMAGE_LOGE("HeifDecoderImpl::HwDecodeMovieFirstFrameImage hwDecoder or image is nullptr");
982 return false;
983 }
984 std::vector<std::vector<uint8_t>> inputs(GRID_NUM_2);
985
986 parser_->GetMovieFrameData(0, &inputs[0], heif_only_header);
987 ProcessChunkHead(inputs[0].data(), inputs[0].size());
988
989 parser_->GetMovieFrameData(0, &inputs[0], heif_no_header);
990 ProcessChunkHead(inputs[1].data(), inputs[1].size());
991
992 uint32_t err = hwDecoder->DoDecode(gridInfo, inputs, hwBuffer);
993 if (err != SUCCESS) {
994 IMAGE_LOGE("heif hw decoder return error: %{public}d, width: %{public}d, height: %{public}d,"
995 " imageType: hvc1, inPixelFormat: %{public}d, colNum: %{public}d, rowNum: %{public}d,"
996 " tileWidth: %{public}d, tileHeight: %{public}d, hvccLen: %{public}zu, dataLen: %{public}zu",
997 err, gridInfo.displayWidth, gridInfo.displayHeight,
998 hwBuffer->GetFormat(), gridInfo.cols, gridInfo.rows,
999 gridInfo.tileWidth, gridInfo.tileHeight, inputs[0].size(), inputs[1].size());
1000 SetHardwareDecodeErrMsg(gridInfo.tileWidth, gridInfo.tileHeight);
1001 return false;
1002 }
1003 return true;
1004 }
1005
SwDecodeImage(std::shared_ptr<HeifImage> & image,HevcSoftDecodeParam & param,GridInfo & gridInfo,bool isPrimary)1006 bool HeifDecoderImpl::SwDecodeImage(std::shared_ptr<HeifImage> &image, HevcSoftDecodeParam ¶m,
1007 GridInfo &gridInfo, bool isPrimary)
1008 {
1009 ImageFuncTimer imageFuncTime("HeifDecoderImpl::%s, desiredpixelformat: %d", __func__, outPixelFormat_);
1010 if (outPixelFormat_ == PixelFormat::UNKNOWN) {
1011 IMAGE_LOGE("unknown pixel type: %{public}d", outPixelFormat_);
1012 return false;
1013 }
1014 if (image == nullptr) {
1015 return false;
1016 }
1017
1018 static ImageFwkExtManager imageFwkExtManager;
1019 if (image->IsMovieImage()) {
1020 return SwDecodeMovieFirstFrameImage(imageFwkExtManager, image, param);
1021 }
1022 std::string imageType = parser_->GetItemType(image->GetItemId());
1023 if (imageType == "iden") {
1024 return SwDecodeIdenImage(image, param, gridInfo, isPrimary);
1025 }
1026
1027 bool res = false;
1028 if (imageType == "grid") {
1029 param.gridInfo.enableGrid = true;
1030 gridInfo.enableGrid = true;
1031 res = SwDecodeGrids(imageFwkExtManager, image, param);
1032 } else if (imageType == "hvc1") {
1033 param.gridInfo.enableGrid = false;
1034 gridInfo.enableGrid = false;
1035 res = SwDecodeSingleImage(imageFwkExtManager, image, param);
1036 } else if (imageType == "iovl") {
1037 param.gridInfo.enableGrid = false;
1038 gridInfo.enableGrid = false;
1039 res = SwDecodeIovls(imageFwkExtManager, image, param);
1040 }
1041 return res;
1042 }
1043
SwDecodeGrids(ImageFwkExtManager & extManager,std::shared_ptr<HeifImage> & image,HevcSoftDecodeParam & param)1044 bool HeifDecoderImpl::SwDecodeGrids(ImageFwkExtManager &extManager,
1045 std::shared_ptr<HeifImage> &image, HevcSoftDecodeParam ¶m)
1046 {
1047 bool cond = extManager.hevcSoftwareDecodeFunc_ == nullptr && !extManager.LoadImageFwkExtNativeSo();
1048 CHECK_ERROR_RETURN_RET(cond, false);
1049 cond = param.dstBuffer == nullptr || param.dstStride == 0;
1050 CHECK_ERROR_RETURN_RET(cond, false);
1051 std::vector<std::shared_ptr<HeifImage>> tileImages;
1052 parser_->GetTileImages(image->GetItemId(), tileImages);
1053 cond = tileImages.empty();
1054 CHECK_ERROR_RETURN_RET_LOG(cond, false, "grid image has no tile image");
1055 size_t numGrid = tileImages.size();
1056 std::vector<std::vector<uint8_t>> inputs(numGrid);
1057
1058 for (size_t index = 0; index < numGrid; ++index) {
1059 std::shared_ptr<HeifImage> &tileImage = tileImages[index];
1060 parser_->GetItemData(tileImage->GetItemId(),
1061 &inputs[index], index == 0 ? heif_header_data : heif_no_header);
1062 ProcessChunkHead(inputs[index].data(), inputs[index].size());
1063 }
1064
1065 int32_t retCode = extManager.hevcSoftwareDecodeFunc_(inputs, param);
1066 cond = retCode != 0;
1067 CHECK_ERROR_RETURN_RET_LOG(cond, false, "SwDecodeGrids decode failed: %{public}d", retCode);
1068 return true;
1069 }
1070
SwDecodeIovls(ImageFwkExtManager & extManager,std::shared_ptr<HeifImage> & image,HevcSoftDecodeParam & param)1071 bool HeifDecoderImpl::SwDecodeIovls(ImageFwkExtManager &extManager,
1072 std::shared_ptr<HeifImage> &image, HevcSoftDecodeParam ¶m)
1073 {
1074 if (extManager.hevcSoftwareDecodeFunc_ == nullptr && !extManager.LoadImageFwkExtNativeSo()) {
1075 return false;
1076 }
1077 if (param.dstBuffer == nullptr || param.dstStride == 0) {
1078 return false;
1079 }
1080 std::vector<std::shared_ptr<HeifImage>> iovlImages;
1081 parser_->GetIovlImages(image->GetItemId(), iovlImages);
1082 if (iovlImages.empty()) {
1083 IMAGE_LOGE("iovl image has no tile image");
1084 return false;
1085 }
1086
1087 return SwDecodeSingleImage(extManager, iovlImages[0], param);
1088 }
1089
SwDecodeIdenImage(std::shared_ptr<HeifImage> & image,HevcSoftDecodeParam & param,GridInfo & gridInfo,bool isPrimary)1090 bool HeifDecoderImpl::SwDecodeIdenImage(std::shared_ptr<HeifImage> &image,
1091 HevcSoftDecodeParam ¶m, GridInfo &gridInfo, bool isPrimary)
1092 {
1093 bool cond = !image;
1094 CHECK_ERROR_RETURN_RET(cond, false);
1095 std::shared_ptr<HeifImage> idenImage;
1096 parser_->GetIdenImage(image->GetItemId(), idenImage);
1097 cond = idenImage == nullptr || idenImage == image;
1098 CHECK_ERROR_RETURN_RET_LOG(cond, false, "invalid iden image");
1099 return SwDecodeImage(idenImage, param, gridInfo, isPrimary);
1100 }
1101
SwDecodeSingleImage(ImageFwkExtManager & extManager,std::shared_ptr<HeifImage> & image,HevcSoftDecodeParam & param)1102 bool HeifDecoderImpl::SwDecodeSingleImage(ImageFwkExtManager &extManager,
1103 std::shared_ptr<HeifImage> &image, HevcSoftDecodeParam ¶m)
1104 {
1105 if (extManager.hevcSoftwareDecodeFunc_ == nullptr && !extManager.LoadImageFwkExtNativeSo()) {
1106 return false;
1107 }
1108 bool cond = (param.dstBuffer == nullptr || param.dstStride == 0);
1109 CHECK_ERROR_RETURN_RET(cond, false);
1110 std::vector<std::vector<uint8_t>> inputs(1);
1111 parser_->GetItemData(image->GetItemId(), &inputs[0], heif_header_data);
1112 ProcessChunkHead(inputs[0].data(), inputs[0].size());
1113
1114 int32_t retCode = extManager.hevcSoftwareDecodeFunc_(inputs, param);
1115 if (retCode != 0) {
1116 IMAGE_LOGE("SwDecodeSingleImage decode failed: %{public}d", retCode);
1117 return false;
1118 }
1119 return true;
1120 }
1121
SwDecodeMovieFirstFrameImage(ImageFwkExtManager & extManager,std::shared_ptr<HeifImage> & image,HevcSoftDecodeParam & param)1122 bool HeifDecoderImpl::SwDecodeMovieFirstFrameImage(ImageFwkExtManager &extManager,
1123 std::shared_ptr<HeifImage> &image, HevcSoftDecodeParam ¶m)
1124 {
1125 if (extManager.hevcSoftwareDecodeFunc_ == nullptr && !extManager.LoadImageFwkExtNativeSo()) {
1126 return false;
1127 }
1128 bool cond = (param.dstBuffer == nullptr || param.dstStride == 0);
1129 CHECK_ERROR_RETURN_RET(cond, false);
1130 std::vector<std::vector<uint8_t>> inputs(1);
1131 parser_->GetMovieFrameData(0, &inputs[0], heif_header_data);
1132 ProcessChunkHead(inputs[0].data(), inputs[0].size());
1133
1134 int32_t retCode = extManager.hevcSoftwareDecodeFunc_(inputs, param);
1135 if (retCode != 0) {
1136 IMAGE_LOGE("SwDecodeMovieFirstFrameImage decode failed: %{public}d", retCode);
1137 return false;
1138 }
1139 return true;
1140 }
1141
SwdecodeGainmap(std::shared_ptr<HeifImage> & gainMapImage,GridInfo & gainmapGridInfo,sptr<SurfaceBuffer> * outputBuf)1142 bool HeifDecoderImpl::SwdecodeGainmap(std::shared_ptr<HeifImage> &gainMapImage,
1143 GridInfo &gainmapGridInfo, sptr<SurfaceBuffer> *outputBuf)
1144 {
1145 ImageTrace trace("HeifDecoderImpl::SwdecodeGainmap");
1146 uint32_t width = gainMapImage->GetOriginalWidth();
1147 uint32_t height = gainMapImage->GetOriginalHeight();
1148 PixelFormat gainMapDstFmt = PixelFormat::YUV_400;
1149 sptr<SurfaceBuffer> output = SurfaceBuffer::Create();
1150 BufferRequestConfig = {
1151 .width = width,
1152 .height = height,
1153 .format = GRAPHIC_PIXEL_FMT_YCBCR_420_SP,
1154 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
1155 .timeout = 0;
1156 }
1157 GSError ret = output->Alloc(config);
1158 bool cond = ret != GSERROR_OK;
1159 CHECK_ERROR_RETURN_RET_LOG(cond, false, "output->alloc(config)faild, GSError=%{public}d", ret);
1160 uint32_t gainMapStride = static_cast<uint32_t>(output->GetStride());
1161 uint32_t gainMapMemorySize = static_cast<uint32_t>(gainMapStride * output->GetHeight());
1162 OH_NativeBuffer_planes *dataplanesInfo = nullptr;
1163 output->GetplanesInfo((void **)&dataplanesInfo);
1164 cond = (dataplanesInfo == nullptr);
1165 CHECK_ERROR_RETURN_RET_LOG(cond, false, "failed to get src buffer planes info.");
1166 OH_NativeBuffer_planes &planeY = dataPlanesInfo->planes[0];
1167 void *nativeBuffer = output.GetRefPtr();
1168 uint8_t *data = static_cast<uint8_t *>(output->GetVirAddr());
1169 int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
1170 if (err != OHOS::GSERROR_OK) {
1171 return false;
1172 }
1173 HevcSoftDecodeParam gainMapparam {
1174 gainMapgridInfo, gainMapdstfmt,
1175 data + planeY.offset, gainMapMemorySize,
1176 gainMapStride, nullptr
1177 };
1178 bool decodeRes = SwDecodeImage(gainMapImage, gainMapParam, gainMapgridInfo, false);
1179 if (!decodeRes) {
1180 IMAGE_LOGE("SwDecodeGainmap failed");
1181 retur false;
1182 } else {
1183 *outputBuf = output;
1184 if (output != nullptr) {
1185 ImageUtils::SurfaceBuffer_Unreference(nativeBuffer);
1186 }
1187 }
1188 return true;
1189 }
IsEmptyBuffer(uint8_t * buffer,uint32_t width,uint32_t height,uint32_t bpp,uint32_t rowStride)1190 static bool IsEmptyBuffer(uint8_t *buffer, uint32_t width, uint32_t height, uint32_t bpp, uint32_t rowStride)
1191 {
1192 bool cond = buffer == nullptr;
1193 CHECK_ERROR_RETURN_RET(cond, true);
1194 uint8_t *bufferRowStart = buffer;
1195 uint32_t rowBytes = width * bpp;
1196 for (uint32_t row = 0; row < height; ++row) {
1197 for (uint32_t col = 0; col < rowBytes; ++col) {
1198 if (bufferRowStart[col] != 0) {
1199 return false;
1200 }
1201 }
1202 bufferRowStart += rowStride;
1203 }
1204 return true;
1205 }
1206
FillAlphaChannel(std::shared_ptr<HeifImage> & masterImage,uint8_t * alphaMemory,size_t alphaStride,uint8_t * dstMemory,size_t dstRowStride)1207 static bool FillAlphaChannel(std::shared_ptr<HeifImage> &masterImage, uint8_t *alphaMemory,
1208 size_t alphaStride, uint8_t *dstMemory, size_t dstRowStride)
1209 {
1210 // merge alpha channel
1211 uint8_t *alphaRowStart = alphaMemory;
1212 uint8_t *dstRowStart = dstMemory;
1213 uint32_t width = masterImage->GetOriginalWidth();
1214 uint32_t height = masterImage->GetOriginalHeight();
1215 bool cond = IsEmptyBuffer(reinterpret_cast<uint8_t*>(alphaMemory), width, height, 1, alphaStride);
1216 CHECK_ERROR_RETURN_RET(cond, false);
1217
1218 for (uint32_t row = 0; row < height; ++row) {
1219 uint8_t *dstPixel = dstRowStart;
1220 for (uint32_t col = 0; col < width; ++col) {
1221 uint32_t alphaVal = static_cast<uint32_t>(alphaRowStart[col]);
1222 dstPixel[PIXEL_OFFSET_0] = static_cast<uint8_t>(alphaVal * dstPixel[PIXEL_OFFSET_0] / MAX_ALPHA);
1223 dstPixel[PIXEL_OFFSET_1] = static_cast<uint8_t>(alphaVal * dstPixel[PIXEL_OFFSET_1] / MAX_ALPHA);
1224 dstPixel[PIXEL_OFFSET_2] = static_cast<uint8_t>(alphaVal * dstPixel[PIXEL_OFFSET_2] / MAX_ALPHA);
1225 dstPixel[PIXEL_OFFSET_3] = static_cast<uint8_t>(alphaVal);
1226 dstPixel += PIXEL_SIZE_4;
1227 }
1228 alphaRowStart += alphaStride;
1229 dstRowStart += dstRowStride;
1230 }
1231 return true;
1232 }
1233
IsValidAlphaImage(std::shared_ptr<HeifImage> & masterImage,std::shared_ptr<HeifImage> & alphaImage,PixelFormat dstPixFmt,bool isHardware)1234 static bool IsValidAlphaImage(std::shared_ptr<HeifImage> &masterImage, std::shared_ptr<HeifImage> &alphaImage,
1235 PixelFormat dstPixFmt, bool isHardware)
1236 {
1237 return alphaImage != nullptr && alphaImage != masterImage &&
1238 alphaImage->GetOriginalWidth() == masterImage->GetOriginalWidth() &&
1239 alphaImage->GetOriginalHeight() == masterImage->GetOriginalHeight() &&
1240 ((isHardware && alphaImage->GetDefaultPixelFormat() == HeifPixelFormat::YUV420) ||
1241 (!isHardware && (alphaImage->GetDefaultPixelFormat() == HeifPixelFormat::YUV420 ||
1242 alphaImage->GetDefaultPixelFormat() == HeifPixelFormat::MONOCHROME))) &&
1243 alphaImage->GetLumaBitNum() == LUMA_8_BIT &&
1244 (dstPixFmt == PixelFormat::RGBA_8888 || dstPixFmt == PixelFormat::BGRA_8888);
1245 }
1246
HwApplyAlphaImage(std::shared_ptr<HeifImage> & masterImage,uint8_t * dstMemory,size_t dstRowStride)1247 bool HeifDecoderImpl::HwApplyAlphaImage(std::shared_ptr<HeifImage> &masterImage,
1248 uint8_t *dstMemory, size_t dstRowStride)
1249 {
1250 // check alpha image is available
1251 if (masterImage == nullptr || IsDirectYUVDecode()) {
1252 return false;
1253 }
1254 std::shared_ptr<HeifImage> alphaImage = masterImage->GetAlphaImage();
1255 if (!IsValidAlphaImage(masterImage, alphaImage, outPixelFormat_, true)) {
1256 return false;
1257 }
1258
1259 // decode alpha image
1260 GridInfo alphaGridInfo;
1261 sptr<SurfaceBuffer> hwBuffer;
1262 InitGridInfo(alphaImage, alphaGridInfo);
1263 bool decodeRes = HwDecodeImage(nullptr, alphaImage, alphaGridInfo, &hwBuffer, false);
1264 if (!decodeRes) {
1265 IMAGE_LOGE("hw decode alpha image failed");
1266 return false;
1267 }
1268
1269 // merge alpha channel
1270 return FillAlphaChannel(masterImage, reinterpret_cast<uint8_t *>(hwBuffer->GetVirAddr()),
1271 hwBuffer->GetStride(), dstMemory, dstRowStride);
1272 }
1273
SwApplyAlphaImage(std::shared_ptr<HeifImage> & masterImage,uint8_t * dstMemory,size_t dstRowStride)1274 bool HeifDecoderImpl::SwApplyAlphaImage(std::shared_ptr<HeifImage> &masterImage,
1275 uint8_t *dstMemory, size_t dstRowStride)
1276 {
1277 // check alpha image is available
1278 if (masterImage == nullptr || IsDirectYUVDecode()) {
1279 return false;
1280 }
1281 std::shared_ptr<HeifImage> alphaImage = masterImage->GetAlphaImage();
1282 if (!IsValidAlphaImage(masterImage, alphaImage, outPixelFormat_, false)) {
1283 return false;
1284 }
1285
1286 GridInfo alphaGridInfo;
1287 InitGridInfo(alphaImage, alphaGridInfo);
1288 uint32_t alphaStride = alphaImage->GetOriginalWidth();
1289 uint32_t alphaMemorySize = alphaStride * alphaImage->GetOriginalHeight();
1290 PixelFormat alphaDstFmt = PixelFormat::ALPHA_8;
1291 std::unique_ptr<uint8_t[]> alphaMemory = std::make_unique<uint8_t[]>(alphaMemorySize);
1292 HevcSoftDecodeParam param {
1293 alphaGridInfo, alphaDstFmt, alphaMemory.get(), alphaMemorySize, alphaStride, nullptr
1294 };
1295 bool decodeRes = SwDecodeImage(alphaImage, param, alphaGridInfo, false);
1296 bool cond = !decodeRes;
1297 CHECK_ERROR_RETURN_RET(cond, false);
1298
1299 // merge alpha channel
1300 return FillAlphaChannel(masterImage, alphaMemory.get(), alphaStride, dstMemory, dstRowStride);
1301 }
1302
ConvertHwBufferPixelFormat(sptr<SurfaceBuffer> & hwBuffer,GridInfo & gridInfo,uint8_t * dstMemory,size_t dstRowStride)1303 bool HeifDecoderImpl::ConvertHwBufferPixelFormat(sptr<SurfaceBuffer> &hwBuffer, GridInfo &gridInfo,
1304 uint8_t *dstMemory, size_t dstRowStride)
1305 {
1306 OH_NativeBuffer_Planes *srcBufferPlanesInfo = nullptr;
1307 hwBuffer->GetPlanesInfo((void **)&srcBufferPlanesInfo);
1308 if (srcBufferPlanesInfo == nullptr) {
1309 IMAGE_LOGE("find to get src buffer planes info");
1310 return false;
1311 }
1312
1313 OH_NativeBuffer_Planes *dstBufferPlanesInfo = nullptr;
1314 if (dstHwBuffer_ != nullptr && dstHwBuffer_->GetFormat() != GRAPHIC_PIXEL_FMT_RGBA_1010102) {
1315 dstHwBuffer_->GetPlanesInfo((void **)&dstBufferPlanesInfo);
1316 if (dstBufferPlanesInfo == nullptr) {
1317 IMAGE_LOGE("fail to get dst buffer planes info");
1318 return false;
1319 }
1320 }
1321
1322 PixelFormatConvertParam srcParam = {static_cast<uint8_t *>(hwBuffer->GetVirAddr()),
1323 gridInfo.displayWidth, gridInfo.displayHeight,
1324 static_cast<uint32_t>(hwBuffer->GetStride()),
1325 gridInfo.colorRangeFlag,
1326 srcBufferPlanesInfo,
1327 GraphicPixFmt2AvPixFmtForYuv(
1328 static_cast<GraphicPixelFormat>(hwBuffer->GetFormat()))};
1329 PixelFormatConvertParam dstParam = {dstMemory, gridInfo.displayWidth, gridInfo.displayHeight,
1330 static_cast<uint32_t>(dstRowStride),
1331 gridInfo.colorRangeFlag,
1332 dstBufferPlanesInfo,
1333 PixFmt2AvPixFmtForOutput(outPixelFormat_)};
1334 return ConvertPixelFormat(srcParam, dstParam);
1335 }
1336
ProcessChunkHead(uint8_t * data,size_t len)1337 bool HeifDecoderImpl::ProcessChunkHead(uint8_t *data, size_t len)
1338 {
1339 if (len < CHUNK_HEAD_SIZE) {
1340 return false;
1341 }
1342 size_t index = 0;
1343 while (index < len - CHUNK_HEAD_SIZE) {
1344 size_t chunkLen = (data[index] << CHUNK_HEAD_SHIFT_24)
1345 | (data[index + CHUNK_HEAD_OFFSET_1] << CHUNK_HEAD_SHIFT_16)
1346 | (data[index + CHUNK_HEAD_OFFSET_2] << CHUNK_HEAD_SHIFT_8)
1347 | (data[index + CHUNK_HEAD_OFFSET_3]);
1348 data[index] = 0;
1349 data[index + CHUNK_HEAD_OFFSET_1] = 0;
1350 data[index + CHUNK_HEAD_OFFSET_2] = 0;
1351 data[index + CHUNK_HEAD_OFFSET_3] = 1;
1352 index += (chunkLen + CHUNK_HEAD_SIZE);
1353 }
1354 return true;
1355 }
1356
IsDirectYUVDecode()1357 bool HeifDecoderImpl::IsDirectYUVDecode()
1358 {
1359 if (dstHwBuffer_ == nullptr) {
1360 return false;
1361 }
1362 if (primaryImage_->GetLumaBitNum() == LUMA_10_BIT) {
1363 return outPixelFormat_ == Media::PixelFormat::YCRCB_P010 || outPixelFormat_ == Media::PixelFormat::YCBCR_P010;
1364 }
1365 return outPixelFormat_ == Media::PixelFormat::NV21 || outPixelFormat_ == Media::PixelFormat::NV12;
1366 }
1367
decodeSequence(int frameIndex,HeifFrameInfo * frameInfo)1368 bool HeifDecoderImpl::decodeSequence(int frameIndex, HeifFrameInfo *frameInfo)
1369 {
1370 // unimplemented
1371 return false;
1372 }
1373
setDstBuffer(uint8_t * dstBuffer,size_t rowStride,void * context)1374 void HeifDecoderImpl::setDstBuffer(uint8_t *dstBuffer, size_t rowStride, void *context)
1375 {
1376 dstMemory_ = dstBuffer;
1377 dstRowStride_ = rowStride;
1378 dstHwBuffer_ = reinterpret_cast<SurfaceBuffer*>(context);
1379 }
1380
setGainmapDstBuffer(uint8_t * dstBuffer,size_t rowStride)1381 void HeifDecoderImpl::setGainmapDstBuffer(uint8_t* dstBuffer, size_t rowStride)
1382 {
1383 if (gainmapDstMemory_ == nullptr) {
1384 gainmapDstMemory_ = dstBuffer;
1385 gainmapDstRowStride_ = rowStride;
1386 }
1387 }
1388
setAuxiliaryDstBuffer(uint8_t * dstBuffer,size_t dstSize,size_t rowStride,void * context)1389 void HeifDecoderImpl::setAuxiliaryDstBuffer(uint8_t* dstBuffer, size_t dstSize, size_t rowStride, void *context)
1390 {
1391 auxiliaryDstMemory_ = dstBuffer;
1392 auxiliaryDstMemorySize_ = dstSize;
1393 auxiliaryDstRowStride_ = rowStride;
1394 isAuxiliaryDecode_ = true;
1395 auxiliaryDstHwbuffer_ = reinterpret_cast<SurfaceBuffer*>(context);
1396 }
1397
getScanline(uint8_t * dst)1398 bool HeifDecoderImpl::getScanline(uint8_t *dst)
1399 {
1400 // no need to implement
1401 return true;
1402 }
1403
skipScanlines(int count)1404 size_t HeifDecoderImpl::skipScanlines(int count)
1405 {
1406 // no need to implement
1407 return true;
1408 }
1409
getImageInfo(HeifFrameInfo * frameInfo)1410 bool HeifDecoderImpl::getImageInfo(HeifFrameInfo *frameInfo)
1411 {
1412 if (frameInfo != nullptr) {
1413 *frameInfo = imageInfo_;
1414 }
1415 return true;
1416 }
1417
getGainmapInfo(HeifFrameInfo * frameInfo)1418 bool HeifDecoderImpl::getGainmapInfo(HeifFrameInfo* frameInfo)
1419 {
1420 if (frameInfo != nullptr) {
1421 *frameInfo = gainmapImageInfo_;
1422 }
1423 return true;
1424 }
1425
getAuxiliaryMapInfo(HeifFrameInfo * frameInfo)1426 bool HeifDecoderImpl::getAuxiliaryMapInfo(HeifFrameInfo* frameInfo)
1427 {
1428 if (frameInfo != nullptr) {
1429 *frameInfo = auxiliaryImageInfo_;
1430 }
1431 return true;
1432 }
1433
getTmapInfo(HeifFrameInfo * frameInfo)1434 bool HeifDecoderImpl::getTmapInfo(HeifFrameInfo* frameInfo)
1435 {
1436 if (frameInfo != nullptr) {
1437 *frameInfo = tmapInfo_;
1438 }
1439 return true;
1440 }
1441
getHdrType()1442 HeifImageHdrType HeifDecoderImpl::getHdrType()
1443 {
1444 std::vector<uint8_t> uwaInfo = primaryImage_->GetUWAInfo();
1445 if (primaryImage_->GetLumaBitNum() == LUMA_10_BIT && imageInfo_.hasNclxColor &&
1446 imageInfo_.nclxColor.colorPrimaries == BT2020_PRIMARIES) {
1447 return uwaInfo.empty() ? HeifImageHdrType::ISO_SINGLE : HeifImageHdrType::VIVID_SINGLE;
1448 }
1449 if (gainmapImage_ != nullptr) {
1450 return uwaInfo.empty() ? HeifImageHdrType::ISO_DUAL : HeifImageHdrType::VIVID_DUAL;
1451 }
1452 return HeifImageHdrType::UNKNOWN;
1453 }
1454
getVividMetadata(std::vector<uint8_t> & uwaInfo,std::vector<uint8_t> & displayInfo,std::vector<uint8_t> & lightInfo)1455 void HeifDecoderImpl::getVividMetadata(std::vector<uint8_t>& uwaInfo, std::vector<uint8_t>& displayInfo,
1456 std::vector<uint8_t>& lightInfo)
1457 {
1458 uwaInfo = primaryImage_->GetUWAInfo();
1459 displayInfo = primaryImage_->GetDisplayInfo();
1460 lightInfo = primaryImage_->GetLightInfo();
1461 }
1462
getISOMetadata(std::vector<uint8_t> & isoMetadata)1463 void HeifDecoderImpl::getISOMetadata(std::vector<uint8_t>& isoMetadata)
1464 {
1465 isoMetadata = primaryImage_->GetISOMetadata();
1466 }
1467
getFragmentMetadata(Media::Rect & fragmentMetadata)1468 void HeifDecoderImpl::getFragmentMetadata(Media::Rect& fragmentMetadata)
1469 {
1470 HeifFragmentMetadata metadata = primaryImage_->GetFragmentMetadata();
1471 fragmentMetadata.width = static_cast<int32_t>(metadata.width);
1472 fragmentMetadata.height = static_cast<int32_t>(metadata.height);
1473 fragmentMetadata.left = static_cast<int32_t>(metadata.horizontalOffset);
1474 fragmentMetadata.top = static_cast<int32_t>(metadata.verticalOffset);
1475 }
1476
getErrMsg(std::string & errMsg)1477 void HeifDecoderImpl::getErrMsg(std::string& errMsg)
1478 {
1479 errMsg = errMsg_;
1480 }
1481
SetHardwareDecodeErrMsg(const uint32_t width,const uint32_t height)1482 void HeifDecoderImpl::SetHardwareDecodeErrMsg(const uint32_t width, const uint32_t height)
1483 {
1484 std::stringstream sstream;
1485 sstream << "HEIF Hardware Decode Failed, Width: ";
1486 sstream << width;
1487 sstream << ", Height: ";
1488 sstream << height;
1489 errMsg_ = sstream.str();
1490 }
1491 } // namespace ImagePlugin
1492 } // namespace OHOS
1493 #endif
1494
CreateHeifDecoderImpl(void)1495 HeifDecoder* CreateHeifDecoderImpl(void)
1496 {
1497 #ifdef HEIF_HW_DECODE_ENABLE
1498 return new OHOS::ImagePlugin::HeifDecoderImpl();
1499 #else
1500 return nullptr;
1501 #endif
1502 }
1503