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