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