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