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