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 ¶m,
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 ¶m)
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 ¶m, 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 ¶m)
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