• 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 <memory>
17 #include "exif_metadata.h"
18 #include "picture.h"
19 #include "pixel_yuv.h"
20 #include "pixel_yuv_ext.h"
21 #include "image_utils.h"
22 #include "image_log.h"
23 #include "image_source.h"
24 #include "media_errors.h"                                                // Operation success
25 #ifdef IMAGE_COLORSPACE_FLAG
26 #include "color_space.h"
27 #endif
28 #include "surface_buffer.h"
29 #include "securec.h"
30 #include "tiff_parser.h"
31 #include "metadata_helper.h"
32 #include "v1_0/cm_color_space.h"
33 #include "vpe_utils.h"
34 #include "image_system_properties.h"
35 
36 namespace OHOS {
37 namespace Media {
38 using namespace OHOS::HDI::Display::Graphic::Common::V1_0;
39 namespace {
40     static const std::map<int32_t, PixelFormat> PIXEL_FORMAT_MAP = {
41         { GRAPHIC_PIXEL_FMT_RGBA_8888, PixelFormat::RGBA_8888 },
42         { GRAPHIC_PIXEL_FMT_YCBCR_420_SP, PixelFormat::NV12 },
43         { GRAPHIC_PIXEL_FMT_YCRCB_420_SP, PixelFormat::NV21 },
44         { GRAPHIC_PIXEL_FMT_RGBA_1010102, PixelFormat::RGBA_1010102 },
45         { GRAPHIC_PIXEL_FMT_BGRA_8888, PixelFormat::BGRA_8888 },
46         { GRAPHIC_PIXEL_FMT_RGB_888, PixelFormat::RGB_888 },
47         { GRAPHIC_PIXEL_FMT_RGB_565, PixelFormat::RGB_565 },
48         { GRAPHIC_PIXEL_FMT_RGBA16_FLOAT, PixelFormat::RGBA_F16 },
49         { GRAPHIC_PIXEL_FMT_YCBCR_P010, PixelFormat::YCBCR_P010 },
50         { GRAPHIC_PIXEL_FMT_YCRCB_P010, PixelFormat::YCRCB_P010 },
51     };
52 
53     static const std::map<CM_ColorSpaceType, ColorSpace> CM_COLORSPACE_MAP = {
54         { CM_COLORSPACE_NONE, ColorSpace::UNKNOWN },
55         { CM_BT709_FULL, ColorSpace::ITU_709 },
56         { CM_BT2020_HLG_FULL, ColorSpace::ITU_2020 },
57         { CM_BT2020_PQ_FULL, ColorSpace::ITU_2020 },
58         { CM_BT709_LIMIT, ColorSpace::ITU_709 },
59         { CM_BT2020_HLG_LIMIT, ColorSpace::ITU_2020 },
60         { CM_BT2020_PQ_LIMIT, ColorSpace::ITU_2020 },
61         { CM_SRGB_FULL, ColorSpace::SRGB },
62         { CM_P3_FULL, ColorSpace::DISPLAY_P3 },
63         { CM_P3_HLG_FULL, ColorSpace::DISPLAY_P3 },
64         { CM_P3_PQ_FULL, ColorSpace::DISPLAY_P3 },
65         { CM_ADOBERGB_FULL, ColorSpace::ADOBE_RGB_1998 },
66         { CM_SRGB_LIMIT, ColorSpace::SRGB },
67         { CM_P3_LIMIT, ColorSpace::DISPLAY_P3 },
68         { CM_P3_HLG_LIMIT, ColorSpace::DISPLAY_P3 },
69         { CM_P3_PQ_LIMIT, ColorSpace::DISPLAY_P3 },
70         { CM_ADOBERGB_LIMIT, ColorSpace::ADOBE_RGB_1998 },
71         { CM_LINEAR_SRGB, ColorSpace::LINEAR_SRGB },
72         { CM_LINEAR_BT709, ColorSpace::ITU_709 },
73         { CM_LINEAR_P3, ColorSpace::DISPLAY_P3 },
74         { CM_LINEAR_BT2020, ColorSpace::ITU_2020 },
75         { CM_DISPLAY_SRGB, ColorSpace::SRGB },
76         { CM_DISPLAY_P3_SRGB, ColorSpace::DISPLAY_P3 },
77         { CM_DISPLAY_P3_HLG, ColorSpace::DISPLAY_P3 },
78         { CM_DISPLAY_P3_PQ, ColorSpace::DISPLAY_P3 },
79         { CM_DISPLAY_BT2020_SRGB, ColorSpace::ITU_2020 },
80         { CM_DISPLAY_BT2020_HLG, ColorSpace::ITU_2020 },
81         { CM_DISPLAY_BT2020_PQ, ColorSpace::ITU_2020 },
82     };
83 
84 #ifdef IMAGE_COLORSPACE_FLAG
85     static const std::map<CM_ColorSpaceType, ColorManager::ColorSpaceName> CM_COLORSPACE_NAME_MAP = {
86         { CM_COLORSPACE_NONE, ColorManager::NONE },
87         { CM_BT601_EBU_FULL, ColorManager::BT601_EBU },
88         { CM_BT601_SMPTE_C_FULL, ColorManager::BT601_SMPTE_C },
89         { CM_BT709_FULL, ColorManager::BT709 },
90         { CM_BT2020_HLG_FULL, ColorManager::BT2020_HLG },
91         { CM_BT2020_PQ_FULL, ColorManager::BT2020_PQ },
92         { CM_BT601_EBU_LIMIT, ColorManager::BT601_EBU_LIMIT },
93         { CM_BT601_SMPTE_C_LIMIT, ColorManager::BT601_SMPTE_C_LIMIT },
94         { CM_BT709_LIMIT, ColorManager::BT709_LIMIT },
95         { CM_BT2020_HLG_LIMIT, ColorManager::BT2020_HLG_LIMIT },
96         { CM_BT2020_PQ_LIMIT, ColorManager::BT2020_PQ_LIMIT },
97         { CM_SRGB_FULL, ColorManager::SRGB },
98         { CM_P3_FULL, ColorManager::DISPLAY_P3 },
99         { CM_P3_HLG_FULL, ColorManager::P3_HLG },
100         { CM_P3_PQ_FULL, ColorManager::P3_PQ },
101         { CM_ADOBERGB_FULL, ColorManager::ADOBE_RGB },
102         { CM_SRGB_LIMIT, ColorManager::SRGB_LIMIT },
103         { CM_P3_LIMIT, ColorManager::DISPLAY_P3_LIMIT },
104         { CM_P3_HLG_LIMIT, ColorManager::P3_HLG_LIMIT },
105         { CM_P3_PQ_LIMIT, ColorManager::P3_PQ_LIMIT },
106         { CM_ADOBERGB_LIMIT, ColorManager::ADOBE_RGB_LIMIT },
107         { CM_LINEAR_SRGB, ColorManager::LINEAR_SRGB },
108         { CM_LINEAR_BT709, ColorManager::LINEAR_BT709 },
109         { CM_LINEAR_P3, ColorManager::LINEAR_P3 },
110         { CM_LINEAR_BT2020, ColorManager::LINEAR_BT2020 },
111         { CM_DISPLAY_SRGB, ColorManager::DISPLAY_SRGB },
112         { CM_DISPLAY_P3_SRGB, ColorManager::DISPLAY_P3_SRGB },
113         { CM_DISPLAY_P3_HLG, ColorManager::DISPLAY_P3_HLG },
114         { CM_DISPLAY_P3_PQ, ColorManager::DISPLAY_P3_PQ },
115         { CM_DISPLAY_BT2020_SRGB, ColorManager::DISPLAY_BT2020_SRGB },
116         { CM_DISPLAY_BT2020_HLG, ColorManager::DISPLAY_BT2020_HLG },
117         { CM_DISPLAY_BT2020_PQ, ColorManager::DISPLAY_BT2020_PQ },
118     };
119 #endif
120 }
121 const static uint64_t MAX_AUXILIARY_PICTURE_COUNT = 32;
122 const static uint64_t MAX_PICTURE_META_TYPE_COUNT = 64;
123 const static uint64_t MAX_EXIFMETADATA_SIZE = 1024 * 1024;
124 static const uint8_t NUM_0 = 0;
125 static const uint8_t NUM_1 = 1;
126 static const uint8_t NUM_2 = 2;
127 static const std::string EXIF_DATA_SIZE_TAG = "exifDataSize";
128 
IsYuvFormat(PixelFormat format)129 static bool IsYuvFormat(PixelFormat format)
130 {
131     return format == PixelFormat::NV21 || format == PixelFormat::NV12 ||
132         format == PixelFormat::YCRCB_P010 || format == PixelFormat::YCBCR_P010;
133 }
134 
IsAlphaFormat(PixelFormat format)135 static bool IsAlphaFormat(PixelFormat format)
136 {
137     return format == PixelFormat::RGBA_8888 || format == PixelFormat::BGRA_8888 ||
138         format == PixelFormat::RGBA_1010102 || format == PixelFormat::RGBA_F16;
139 }
140 
SbFormat2PixelFormat(int32_t sbFormat)141 static PixelFormat SbFormat2PixelFormat(int32_t sbFormat)
142 {
143     auto iter = PIXEL_FORMAT_MAP.find(sbFormat);
144     if (iter == PIXEL_FORMAT_MAP.end()) {
145         return PixelFormat::UNKNOWN;
146     }
147     return iter->second;
148 }
149 
GetCMColorSpaceType(sptr<SurfaceBuffer> buffer)150 static CM_ColorSpaceType GetCMColorSpaceType(sptr<SurfaceBuffer> buffer)
151 {
152     CHECK_ERROR_RETURN_RET(buffer == nullptr, CM_ColorSpaceType::CM_COLORSPACE_NONE);
153     CM_ColorSpaceType type;
154     MetadataHelper::GetColorSpaceType(buffer, type);
155     return type;
156 }
157 
CMColorSpaceType2ColorSpace(CM_ColorSpaceType type)158 static ColorSpace CMColorSpaceType2ColorSpace(CM_ColorSpaceType type)
159 {
160     auto iter = CM_COLORSPACE_MAP.find(type);
161     CHECK_ERROR_RETURN_RET(iter == CM_COLORSPACE_MAP.end(), ColorSpace::UNKNOWN);
162     return iter->second;
163 }
164 
165 #ifdef IMAGE_COLORSPACE_FLAG
CMColorSpaceType2ColorSpaceName(CM_ColorSpaceType type)166 static ColorManager::ColorSpaceName CMColorSpaceType2ColorSpaceName(CM_ColorSpaceType type)
167 {
168     auto iter = CM_COLORSPACE_NAME_MAP.find(type);
169     CHECK_ERROR_RETURN_RET(iter == CM_COLORSPACE_NAME_MAP.end(), ColorManager::NONE);
170     return iter->second;
171 }
172 #endif
173 
MakeImageInfo(int width,int height,PixelFormat pf,AlphaType at,ColorSpace cs)174 static ImageInfo MakeImageInfo(int width, int height, PixelFormat pf, AlphaType at, ColorSpace cs)
175 {
176     ImageInfo info;
177     info.size.width = width;
178     info.size.height = height;
179     info.pixelFormat = pf;
180     info.alphaType = at;
181     info.colorSpace = cs;
182     return info;
183 }
184 
SetYuvDataInfo(std::unique_ptr<PixelMap> & pixelMap,sptr<OHOS::SurfaceBuffer> & sBuffer)185 static void SetYuvDataInfo(std::unique_ptr<PixelMap> &pixelMap, sptr<OHOS::SurfaceBuffer> &sBuffer)
186 {
187     bool cond = pixelMap == nullptr || sBuffer == nullptr;
188     CHECK_ERROR_RETURN(cond);
189     int32_t width = sBuffer->GetWidth();
190     int32_t height = sBuffer->GetHeight();
191     OH_NativeBuffer_Planes *planes = nullptr;
192     GSError retVal = sBuffer->GetPlanesInfo(reinterpret_cast<void**>(&planes));
193     YUVDataInfo info;
194     info.imageSize = { width, height };
195     cond = retVal != OHOS::GSERROR_OK || planes == nullptr || planes->planeCount <= NUM_1;
196     CHECK_ERROR_RETURN_LOG(cond, "Get planesInfo failed, retVal:%{public}d", retVal);
197     if (planes->planeCount >= NUM_2) {
198         info.yWidth = static_cast<uint32_t>(info.imageSize.width);
199         info.yHeight = static_cast<uint32_t>(info.imageSize.height);
200         info.yStride = planes->planes[NUM_0].columnStride;
201         info.uvStride = planes->planes[NUM_1].columnStride;
202         info.yOffset = planes->planes[NUM_0].offset;
203         info.uvOffset = planes->planes[NUM_1].offset - NUM_1;
204     }
205     pixelMap->SetImageYUVInfo(info);
206 }
207 
SetImageInfoToHdr(std::shared_ptr<PixelMap> & mainPixelMap,std::unique_ptr<PixelMap> & hdrPixelMap)208 static void SetImageInfoToHdr(std::shared_ptr<PixelMap> &mainPixelMap, std::unique_ptr<PixelMap> &hdrPixelMap)
209 {
210     bool cond = mainPixelMap != nullptr && hdrPixelMap != nullptr;
211     if (cond) {
212         ImageInfo mainInfo;
213         mainPixelMap->GetImageInfo(mainInfo);
214         ImageInfo hdrInfo;
215         hdrPixelMap->GetImageInfo(hdrInfo);
216         hdrInfo.size = mainInfo.size;
217         hdrInfo.encodedFormat = mainInfo.encodedFormat;
218         hdrPixelMap->SetImageInfo(hdrInfo, true);
219     }
220 }
221 
~Picture()222 Picture::~Picture() {}
223 
Create(std::shared_ptr<PixelMap> & pixelMap)224 std::unique_ptr<Picture> Picture::Create(std::shared_ptr<PixelMap> &pixelMap)
225 {
226     if (pixelMap == nullptr) {
227         return nullptr;
228     }
229     std::unique_ptr<Picture> dstPicture = std::make_unique<Picture>();
230     if (pixelMap->GetExifMetadata() != nullptr) {
231         dstPicture->SetExifMetadata(pixelMap->GetExifMetadata());
232     }
233     dstPicture->mainPixelMap_ = pixelMap;
234     return dstPicture;
235 }
236 
Create(sptr<SurfaceBuffer> & surfaceBuffer)237 std::unique_ptr<Picture> Picture::Create(sptr<SurfaceBuffer> &surfaceBuffer)
238 {
239     std::shared_ptr<PixelMap> pixelmap = SurfaceBuffer2PixelMap(surfaceBuffer);
240     return Create(pixelmap);
241 }
242 
SurfaceBuffer2PixelMap(sptr<OHOS::SurfaceBuffer> & surfaceBuffer)243 std::unique_ptr<PixelMap> Picture::SurfaceBuffer2PixelMap(sptr<OHOS::SurfaceBuffer> &surfaceBuffer)
244 {
245     if (surfaceBuffer == nullptr) {
246         return nullptr;
247     }
248     PixelFormat pixelFormat = SbFormat2PixelFormat(surfaceBuffer->GetFormat());
249     ColorSpace colorSpace = CMColorSpaceType2ColorSpace(GetCMColorSpaceType(surfaceBuffer));
250     AlphaType alphaType = IsAlphaFormat(pixelFormat) ?
251              AlphaType::IMAGE_ALPHA_TYPE_PREMUL : AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
252     void* nativeBuffer = surfaceBuffer.GetRefPtr();
253     int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
254     CHECK_ERROR_RETURN_RET_LOG(err != OHOS::GSERROR_OK, nullptr, "NativeBufferReference failed");
255 
256     std::unique_ptr<PixelMap> pixelMap;
257     if (IsYuvFormat(pixelFormat)) {
258 #ifdef EXT_PIXEL
259         pixelMap = std::make_unique<PixelYuvExt>();
260 #else
261         pixelMap = std::make_unique<PixelYuv>();
262 #endif
263     } else {
264         pixelMap = std::make_unique<PixelMap>();
265     }
266     CHECK_ERROR_RETURN_RET(pixelMap == nullptr, nullptr);
267 
268     ImageInfo imageInfo = MakeImageInfo(surfaceBuffer->GetWidth(),
269                                         surfaceBuffer->GetHeight(), pixelFormat, alphaType, colorSpace);
270     pixelMap->SetImageInfo(imageInfo, true);
271     pixelMap->SetPixelsAddr(surfaceBuffer->GetVirAddr(),
272                             nativeBuffer, pixelMap->GetRowBytes() * pixelMap->GetHeight(),
273                             AllocatorType::DMA_ALLOC, nullptr);
274 #ifdef IMAGE_COLORSPACE_FLAG
275     ColorManager::ColorSpaceName colorSpaceName =
276         CMColorSpaceType2ColorSpaceName(GetCMColorSpaceType(surfaceBuffer));
277     pixelMap->InnerSetColorSpace(ColorManager::ColorSpace(colorSpaceName));
278 #endif
279     if (IsYuvFormat(pixelFormat)) {
280         SetYuvDataInfo(pixelMap, surfaceBuffer);
281     }
282     return pixelMap;
283 }
284 
GetMainPixel()285 std::shared_ptr<PixelMap> Picture::GetMainPixel()
286 {
287     return mainPixelMap_;
288 }
289 
SetMainPixel(std::shared_ptr<PixelMap> PixelMap)290 void Picture::SetMainPixel(std::shared_ptr<PixelMap> PixelMap)
291 {
292     mainPixelMap_ = PixelMap;
293 }
294 
GetHdrAllocFormat(PixelFormat pixelFormat)295 static int32_t GetHdrAllocFormat(PixelFormat pixelFormat)
296 {
297     int32_t hdrAllocFormat = GRAPHIC_PIXEL_FMT_RGBA_1010102;
298     switch (pixelFormat) {
299         case PixelFormat::RGBA_8888:
300             hdrAllocFormat = GRAPHIC_PIXEL_FMT_RGBA_1010102;
301             break;
302         case PixelFormat::NV21:
303             hdrAllocFormat = GRAPHIC_PIXEL_FMT_YCRCB_P010;
304             break;
305         case PixelFormat::NV12:
306             hdrAllocFormat = GRAPHIC_PIXEL_FMT_YCBCR_P010;
307             break;
308         default:
309             IMAGE_LOGW("%{public}s no corresponding hdrAllocFormat for format: %{public}d", __func__, pixelFormat);
310             break;
311     }
312     IMAGE_LOGD("%{public}s use hdrAllocFormat: %{public}d for format: %{public}d",
313         __func__, hdrAllocFormat, pixelFormat);
314     return hdrAllocFormat;
315 }
316 
TryFixGainmapHdrMetadata(sptr<SurfaceBuffer> & gainmapSptr)317 static void TryFixGainmapHdrMetadata(sptr<SurfaceBuffer> &gainmapSptr)
318 {
319     std::vector<uint8_t> gainmapDynamicMetadata;
320     VpeUtils::GetSbDynamicMetadata(gainmapSptr, gainmapDynamicMetadata);
321     if (gainmapDynamicMetadata.size() != sizeof(ISOMetadata)) {
322         IMAGE_LOGI("%{public}s no need to fix gainmap dynamic metadata, size: %{public}zu",
323             __func__, gainmapDynamicMetadata.size());
324         return;
325     }
326 
327     HDRVividExtendMetadata extendMetadata = {};
328     int32_t memCpyRes = memcpy_s(&extendMetadata.metaISO, sizeof(ISOMetadata),
329         gainmapDynamicMetadata.data(), gainmapDynamicMetadata.size());
330     CHECK_ERROR_RETURN_LOG(memCpyRes != EOK,
331         "%{public}s memcpy_s ISOMetadata fail, error: %{public}d", __func__, memCpyRes);
332     if (extendMetadata.metaISO.useBaseColorFlag != 0) {
333         extendMetadata.baseColorMeta.baseColorPrimary = COLORPRIMARIES_SRGB;
334         extendMetadata.gainmapColorMeta.combineColorPrimary = COLORPRIMARIES_SRGB;
335     } else {
336         extendMetadata.gainmapColorMeta.combineColorPrimary = COLORPRIMARIES_BT2020;
337         extendMetadata.gainmapColorMeta.alternateColorPrimary = COLORPRIMARIES_BT2020;
338     }
339     std::vector<uint8_t> extendMetadataVec(sizeof(HDRVividExtendMetadata));
340     memCpyRes = memcpy_s(extendMetadataVec.data(), extendMetadataVec.size(),
341         &extendMetadata, sizeof(HDRVividExtendMetadata));
342     CHECK_ERROR_RETURN_LOG(memCpyRes != EOK,
343         "%{public}s memcpy_s HDRVividExtendMetadata fail, error: %{public}d", __func__, memCpyRes);
344     VpeUtils::SetSbDynamicMetadata(gainmapSptr, extendMetadataVec);
345 }
346 
CreateGainmapByHdrAndSdr(std::shared_ptr<PixelMap> & hdrPixelMap,std::shared_ptr<PixelMap> & sdrPixelMap)347 sptr<SurfaceBuffer> CreateGainmapByHdrAndSdr(std::shared_ptr<PixelMap> &hdrPixelMap,
348                                              std::shared_ptr<PixelMap> &sdrPixelMap)
349 {
350     sptr<SurfaceBuffer> gainmapSptr = SurfaceBuffer::Create();
351     ImageInfo imageInfo;
352     sdrPixelMap->GetImageInfo(imageInfo);
353     BufferRequestConfig requestConfig = {
354         .width = imageInfo.size.width / 2,
355         .height = imageInfo.size.height / 2,
356         .strideAlignment = imageInfo.size.width / 2,
357         .format = GetHdrAllocFormat(imageInfo.pixelFormat),
358         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
359         .timeout = 0,
360     };
361     GSError error = gainmapSptr->Alloc(requestConfig);
362     CHECK_ERROR_RETURN_RET_LOG(error != GSERROR_OK, nullptr,
363         "HDR-IMAGE SurfaceBuffer Alloc failed, error : %{public}s", GSErrorStr(error).c_str());
364     sptr<SurfaceBuffer> hdrSptr(reinterpret_cast<SurfaceBuffer*>(hdrPixelMap->GetFd()));
365     sptr<SurfaceBuffer> sdrSptr(reinterpret_cast<SurfaceBuffer*>(sdrPixelMap->GetFd()));
366     VpeSurfaceBuffers buffers = {
367         .sdr = sdrSptr,
368         .gainmap = gainmapSptr,
369         .hdr = hdrSptr,
370     };
371     int32_t res = VpeUtils().ColorSpaceCalGainmap(buffers);
372     if (res != VPE_ERROR_OK) {
373         IMAGE_LOGE("HDR-IMAGE CalGainmap failed, res: %{public}d", res);
374         return nullptr;
375     }
376     return gainmapSptr;
377 }
378 
CreatePictureByHdrAndSdrPixelMap(std::shared_ptr<PixelMap> & hdrPixelMap,std::shared_ptr<PixelMap> & sdrPixelMap)379 std::unique_ptr<Picture> Picture::CreatePictureByHdrAndSdrPixelMap(std::shared_ptr<PixelMap> &hdrPixelMap,
380     std::shared_ptr<PixelMap> &sdrPixelMap)
381 {
382     bool cond = hdrPixelMap == nullptr || sdrPixelMap == nullptr;
383     CHECK_ERROR_RETURN_RET_LOG(cond, nullptr, "HDR-IMAGE do calgainmap input null error");
384     cond = (hdrPixelMap->GetAllocatorType() != AllocatorType::DMA_ALLOC) ||
385            (sdrPixelMap->GetAllocatorType() != AllocatorType::DMA_ALLOC);
386     CHECK_ERROR_RETURN_RET_LOG(cond, nullptr, "HDR-IMAGE calgainmap input AllocatorType type error");
387     std::unique_ptr<Picture> dstPicture = Create(sdrPixelMap);
388     sptr<SurfaceBuffer> gainmapSptr = CreateGainmapByHdrAndSdr(hdrPixelMap, sdrPixelMap);
389     CHECK_ERROR_RETURN_RET_LOG(gainmapSptr == nullptr, nullptr, "HDR-IMAGE CreateGainmapByHdrAndSdr failed");
390     Media::Size size = {gainmapSptr->GetWidth(), gainmapSptr->GetHeight()};
391     std::unique_ptr<AuxiliaryPicture> gainmap = AuxiliaryPicture::Create(gainmapSptr,
392         AuxiliaryPictureType::GAINMAP, size);
393     cond = dstPicture == nullptr || gainmap == nullptr;
394     CHECK_ERROR_RETURN_RET_LOG(cond, nullptr, "HDR-IMAGE calgainmap install output error");
395     std::shared_ptr<AuxiliaryPicture> gainmapPtr = std::move(gainmap);
396     dstPicture->SetAuxiliaryPicture(gainmapPtr);
397     return dstPicture;
398 }
399 
ShouldComposeAsCuva(const sptr<SurfaceBuffer> & baseSptr,const sptr<SurfaceBuffer> & gainmapSptr)400 static bool ShouldComposeAsCuva(const sptr<SurfaceBuffer> &baseSptr, const sptr<SurfaceBuffer> &gainmapSptr)
401 {
402     std::vector<uint8_t> baseStaticMetadata;
403     VpeUtils::GetSbStaticMetadata(baseSptr, baseStaticMetadata);
404     std::vector<uint8_t> baseDynamicMetadata;
405     VpeUtils::GetSbDynamicMetadata(gainmapSptr, baseDynamicMetadata);
406     CHECK_ERROR_RETURN_RET(baseStaticMetadata.size() == 0 || baseDynamicMetadata.size() == 0, true);
407     std::vector<uint8_t> gainmapDynamicMetadata;
408     VpeUtils::GetSbDynamicMetadata(gainmapSptr, gainmapDynamicMetadata);
409     CHECK_ERROR_RETURN_RET(gainmapDynamicMetadata.size() != sizeof(HDRVividExtendMetadata), true);
410     return false;
411 }
412 
ComposeHdrPixelMap(std::shared_ptr<PixelMap> & mainPixelMap,sptr<SurfaceBuffer> & baseSptr,sptr<SurfaceBuffer> & gainmapSptr)413 static std::unique_ptr<PixelMap> ComposeHdrPixelMap(
414     std::shared_ptr<PixelMap> &mainPixelMap, sptr<SurfaceBuffer> &baseSptr, sptr<SurfaceBuffer> &gainmapSptr)
415 {
416     sptr<SurfaceBuffer> hdrSptr = SurfaceBuffer::Create();
417     ImageInfo imageInfo;
418     mainPixelMap->GetImageInfo(imageInfo);
419     BufferRequestConfig requestConfig = {
420         .width = imageInfo.size.width,
421         .height = imageInfo.size.height,
422         .strideAlignment = imageInfo.size.width,
423         .format = GetHdrAllocFormat(imageInfo.pixelFormat),
424         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
425         .timeout = 0,
426     };
427 
428     GSError error = hdrSptr->Alloc(requestConfig);
429     CHECK_ERROR_RETURN_RET_LOG(error != GSERROR_OK, nullptr,
430         "HDR SurfaceBuffer Alloc failed, error: %{public}s", GSErrorStr(error).c_str());
431     VpeUtils::SetSbMetadataType(hdrSptr, CM_IMAGE_HDR_VIVID_SINGLE);
432     VpeUtils::SetSbColorSpaceType(hdrSptr, CM_BT2020_HLG_FULL);
433 
434     VpeSurfaceBuffers buffers = {
435         .sdr = baseSptr,
436         .gainmap = gainmapSptr,
437         .hdr = hdrSptr,
438     };
439     bool isCuva = ShouldComposeAsCuva(baseSptr, gainmapSptr);
440     IMAGE_LOGD("HDR-IMAGE Compose image, isCuva: %{public}d", isCuva);
441     int32_t res = VpeUtils().ColorSpaceConverterComposeImage(buffers, isCuva);
442     if (res != VPE_ERROR_OK) {
443         IMAGE_LOGE("Compose HDR image failed, res: %{public}d", res);
444         return nullptr;
445     }
446     return Picture::SurfaceBuffer2PixelMap(hdrSptr);
447 }
448 
GetHdrComposedPixelMap()449 std::unique_ptr<PixelMap> Picture::GetHdrComposedPixelMap()
450 {
451     std::shared_ptr<PixelMap> gainmap = GetGainmapPixelMap();
452     bool cond = mainPixelMap_ == nullptr || gainmap == nullptr;
453     CHECK_ERROR_RETURN_RET_LOG(cond, nullptr, "picture mainPixelMap_ or gainmap is empty.");
454     cond = mainPixelMap_->GetAllocatorType() != AllocatorType::DMA_ALLOC || mainPixelMap_->GetFd() == nullptr ||
455            gainmap->GetAllocatorType() != AllocatorType::DMA_ALLOC || gainmap->GetFd() == nullptr;
456     CHECK_ERROR_RETURN_RET_LOG(cond, nullptr, "Unsupport HDR compose, only support the DMA allocation.");
457     sptr<SurfaceBuffer> baseSptr(reinterpret_cast<SurfaceBuffer*>(mainPixelMap_->GetFd()));
458     VpeUtils::SetSbMetadataType(baseSptr, CM_IMAGE_HDR_VIVID_DUAL);
459     sptr<SurfaceBuffer> gainmapSptr(reinterpret_cast<SurfaceBuffer*>(gainmap->GetFd()));
460     VpeUtils::SetSbMetadataType(gainmapSptr, CM_METADATA_NONE);
461     TryFixGainmapHdrMetadata(gainmapSptr);
462     auto hdrPixelMap = ComposeHdrPixelMap(mainPixelMap_, baseSptr, gainmapSptr);
463     SetImageInfoToHdr(mainPixelMap_, hdrPixelMap);
464     return hdrPixelMap;
465 }
466 
GetGainmapPixelMap()467 std::shared_ptr<PixelMap> Picture::GetGainmapPixelMap()
468 {
469     if (!HasAuxiliaryPicture(AuxiliaryPictureType::GAINMAP)) {
470         IMAGE_LOGE("Unsupport gain map.");
471         return nullptr;
472     } else {
473         auto auxiliaryPicture = GetAuxiliaryPicture(AuxiliaryPictureType::GAINMAP);
474         CHECK_ERROR_RETURN_RET(auxiliaryPicture == nullptr, nullptr);
475         return auxiliaryPicture->GetContentPixel();
476     }
477 }
478 
GetAuxiliaryPicture(AuxiliaryPictureType type)479 std::shared_ptr<AuxiliaryPicture> Picture::GetAuxiliaryPicture(AuxiliaryPictureType type)
480 {
481     auto iter = auxiliaryPictures_.find(type);
482     if (iter == auxiliaryPictures_.end()) {
483         return nullptr;
484     }
485     return iter->second;
486 }
487 
SetAuxiliaryPicture(std::shared_ptr<AuxiliaryPicture> & picture)488 void Picture::SetAuxiliaryPicture(std::shared_ptr<AuxiliaryPicture> &picture)
489 {
490     if (picture == nullptr) {
491         IMAGE_LOGE("Auxiliary picture is nullptr.");
492         return;
493     }
494     CHECK_ERROR_RETURN_LOG(auxiliaryPictures_.size() >= MAX_AUXILIARY_PICTURE_COUNT,
495         "The size of auxiliary picture exceeds the maximum limit %{public}llu.",
496         static_cast<unsigned long long>(MAX_AUXILIARY_PICTURE_COUNT));
497     AuxiliaryPictureType type = picture->GetType();
498     auxiliaryPictures_[type] = picture;
499 }
500 
HasAuxiliaryPicture(AuxiliaryPictureType type)501 bool Picture::HasAuxiliaryPicture(AuxiliaryPictureType type)
502 {
503     auto item = auxiliaryPictures_.find(type);
504     return item != auxiliaryPictures_.end() && item->second != nullptr;
505 }
506 
DropAuxiliaryPicture(AuxiliaryPictureType type)507 void Picture::DropAuxiliaryPicture(AuxiliaryPictureType type)
508 {
509     auto it = auxiliaryPictures_.find(type);
510     if (it != auxiliaryPictures_.end()) {
511         auxiliaryPictures_.erase(it);
512     } else {
513         IMAGE_LOGE("Failed to drop auxiliary picture.");
514     }
515 }
516 
MarshalMetadata(Parcel & data) const517 bool Picture::MarshalMetadata(Parcel &data) const
518 {
519     if (!data.WriteBool(maintenanceData_ != nullptr)) {
520         IMAGE_LOGE("Failed to write maintenance data existence value.");
521         return false;
522     }
523 
524     if (maintenanceData_ != nullptr &&
525         (maintenanceData_->WriteToMessageParcel(reinterpret_cast<MessageParcel&>(data)) != GSError::GSERROR_OK)) {
526         IMAGE_LOGE("Failed to write maintenance data content.");
527         return false;
528     }
529 
530     if (metadatas_.size() > MAX_PICTURE_META_TYPE_COUNT) {
531         IMAGE_LOGE("The number of metadatas exceeds the maximum limit.");
532         return false;
533     }
534     if (!data.WriteUint64(static_cast<uint64_t>(metadatas_.size()))) {
535         return false;
536     }
537 
538     for (const auto &[type, metadata] : metadatas_) {
539         int32_t typeInt32 = static_cast<int32_t>(type);
540         if (metadata == nullptr) {
541             IMAGE_LOGE("Metadata %{public}d is nullptr.", typeInt32);
542             return false;
543         }
544         if (!(data.WriteInt32(typeInt32) && metadata->Marshalling(data))) {
545             IMAGE_LOGE("Failed to marshal metadata: %{public}d.", typeInt32);
546             return false;
547         }
548     }
549 
550     return true;
551 }
552 
Marshalling(Parcel & data) const553 bool Picture::Marshalling(Parcel &data) const
554 {
555     bool cond = false;
556     CHECK_ERROR_RETURN_RET_LOG(!mainPixelMap_, false, "Main PixelMap is null.");
557     cond = !mainPixelMap_->Marshalling(data);
558     CHECK_ERROR_RETURN_RET_LOG(cond, false, "Failed to marshal main PixelMap.");
559 
560     size_t numAuxiliaryPictures = auxiliaryPictures_.size();
561     cond = numAuxiliaryPictures > MAX_AUXILIARY_PICTURE_COUNT;
562     CHECK_ERROR_RETURN_RET(cond, false);
563     cond = !data.WriteUint64(numAuxiliaryPictures);
564     CHECK_ERROR_RETURN_RET_LOG(cond, false, "Failed to write number of auxiliary pictures.");
565 
566     for (const auto &auxiliaryPicture : auxiliaryPictures_) {
567         AuxiliaryPictureType type =  auxiliaryPicture.first;
568         cond = !data.WriteInt32(static_cast<int32_t>(type));
569         CHECK_ERROR_RETURN_RET_LOG(cond, false, "Failed to write auxiliary picture type.");
570         cond = !auxiliaryPicture.second || !auxiliaryPicture.second->Marshalling(data);
571         CHECK_ERROR_RETURN_RET_LOG(cond, false,
572             "Failed to marshal auxiliary picture of type %{public}d.", static_cast<int>(type));
573     }
574     CHECK_ERROR_RETURN_RET(!MarshalMetadata(data), false);
575 
576     return true;
577 }
578 
Unmarshalling(Parcel & data)579 Picture *Picture::Unmarshalling(Parcel &data)
580 {
581     PICTURE_ERR error;
582     Picture* dstPicture = Picture::Unmarshalling(data, error);
583     CHECK_ERROR_RETURN_RET_LOG(dstPicture == nullptr || error.errorCode != SUCCESS, dstPicture,
584         "unmarshalling failed errorCode:%{public}d, errorInfo:%{public}s",
585         error.errorCode, error.errorInfo.c_str());
586     return dstPicture;
587 }
588 
UnmarshalMetadata(Parcel & parcel,Picture & picture,PICTURE_ERR & error)589 bool Picture::UnmarshalMetadata(Parcel &parcel, Picture &picture, PICTURE_ERR &error)
590 {
591     bool hasMaintenanceData = parcel.ReadBool();
592     if (hasMaintenanceData) {
593         sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
594         CHECK_ERROR_RETURN_RET_LOG(surfaceBuffer == nullptr, false, "SurfaceBuffer failed to be created.");
595         CHECK_ERROR_RETURN_RET_LOG(
596             surfaceBuffer->ReadFromMessageParcel(reinterpret_cast<MessageParcel &>(parcel)) != GSError::GSERROR_OK,
597             false, "Failed to unmarshal maintenance data");
598         picture.maintenanceData_ = surfaceBuffer;
599     }
600 
601     uint64_t size = parcel.ReadUint64();
602     if (size > MAX_PICTURE_META_TYPE_COUNT) {
603         return false;
604     }
605     for (size_t i = 0; i < size; ++i) {
606         MetadataType type = static_cast<MetadataType>(parcel.ReadInt32());
607         std::shared_ptr<ImageMetadata> imagedataPtr(nullptr);
608         if (type == MetadataType::EXIF) {
609             imagedataPtr.reset(ExifMetadata::Unmarshalling(parcel));
610         } else if (type == MetadataType::GIF) {
611             imagedataPtr.reset(GifMetadata::Unmarshalling(parcel));
612         } else {
613             IMAGE_LOGE("Unsupported metadata type: %{public}d in picture", static_cast<int32_t>(type));
614         }
615         if (imagedataPtr == nullptr) {
616             return false;
617         }
618         if (picture.SetMetadata(type, imagedataPtr) != SUCCESS) {
619             IMAGE_LOGE("SetMetadata %{public}d in picture failed", static_cast<int32_t>(type));
620             return false;
621         }
622     }
623     return true;
624 }
625 
Unmarshalling(Parcel & parcel,PICTURE_ERR & error)626 Picture *Picture::Unmarshalling(Parcel &parcel, PICTURE_ERR &error)
627 {
628     std::unique_ptr<Picture> picture = std::make_unique<Picture>();
629     std::shared_ptr<PixelMap> pixelmapPtr(PixelMap::Unmarshalling(parcel));
630     CHECK_ERROR_RETURN_RET_LOG(!pixelmapPtr, nullptr, "Failed to unmarshal main PixelMap.");
631     picture->SetMainPixel(pixelmapPtr);
632     uint64_t numAuxiliaryPictures = parcel.ReadUint64();
633     CHECK_ERROR_RETURN_RET(numAuxiliaryPictures > MAX_AUXILIARY_PICTURE_COUNT, nullptr);
634 
635     for (size_t i = NUM_0; i < numAuxiliaryPictures; ++i) {
636         int32_t type = parcel.ReadInt32();
637         std::shared_ptr<AuxiliaryPicture> auxPtr(AuxiliaryPicture::Unmarshalling(parcel));
638         CHECK_ERROR_RETURN_RET_LOG(!auxPtr, nullptr, "Failed to unmarshal auxiliary picture of type %d.", type);
639         picture->SetAuxiliaryPicture(auxPtr);
640     }
641     CHECK_ERROR_RETURN_RET_LOG(!UnmarshalMetadata(parcel, *picture, error), nullptr, "Failed to unmarshal metadata.");
642     return picture.release();
643 }
644 
CreateExifMetadata()645 int32_t Picture::CreateExifMetadata()
646 {
647     CHECK_ERROR_RETURN_RET_LOG(GetExifMetadata() != nullptr, SUCCESS, "exifMetadata is already created");
648     auto exifMetadata = std::make_shared<OHOS::Media::ExifMetadata>();
649     if (exifMetadata == nullptr) {
650         IMAGE_LOGE("Failed to create ExifMetadata object");
651         return ERR_IMAGE_MALLOC_ABNORMAL;
652     }
653     if (!exifMetadata->CreateExifdata()) {
654         IMAGE_LOGE("Failed to create exif metadata data");
655         return ERR_IMAGE_INVALID_PARAMETER;
656     }
657     return SetExifMetadata(exifMetadata);
658 }
659 
SetExifMetadata(sptr<SurfaceBuffer> & surfaceBuffer)660 int32_t Picture::SetExifMetadata(sptr<SurfaceBuffer> &surfaceBuffer)
661 {
662     if (surfaceBuffer == nullptr) {
663         return ERR_IMAGE_INVALID_PARAMETER;
664     }
665 
666     auto extraData = surfaceBuffer->GetExtraData();
667     CHECK_ERROR_RETURN_RET(extraData == nullptr, ERR_IMAGE_INVALID_PARAMETER);
668 
669     int32_t size = NUM_0;
670     extraData->ExtraGet(EXIF_DATA_SIZE_TAG, size);
671     bool cond = size <= 0;
672     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_INVALID_PARAMETER, "Invalid buffer size: %d.", size);
673 
674     size_t tiffHeaderPos = TiffParser::FindTiffPos(reinterpret_cast<const byte *>(surfaceBuffer->GetVirAddr()), size);
675     cond = tiffHeaderPos == std::numeric_limits<size_t>::max();
676     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_SOURCE_DATA, "Input image stream is not tiff type.");
677 
678     cond = static_cast<uint32_t>(size) > surfaceBuffer->GetSize() || tiffHeaderPos > surfaceBuffer->GetSize();
679     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_INVALID_PARAMETER,
680                                "The size of exif metadata exceeds the buffer size.");
681 
682     cond = static_cast<uint32_t>(size) < tiffHeaderPos;
683     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_INVALID_PARAMETER,
684                                "Tiff header position exceeds the size of exif metadata.");
685 
686     cond = static_cast<uint32_t>(size) - tiffHeaderPos > MAX_EXIFMETADATA_SIZE;
687     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_INVALID_PARAMETER,
688                                "Failed to set exif metadata,"
689                                "the size of exif metadata exceeds the maximum limit %{public}llu.",
690                                static_cast<unsigned long long>(MAX_EXIFMETADATA_SIZE));
691     ExifData *exifData;
692     TiffParser::Decode(static_cast<const unsigned char *>(surfaceBuffer->GetVirAddr()) + tiffHeaderPos,
693         size - tiffHeaderPos, &exifData);
694     cond = exifData == nullptr;
695     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_EXIF_DECODE_FAILED, "Failed to decode EXIF data from image stream.");
696 
697     auto exifMetadata = std::make_shared<OHOS::Media::ExifMetadata>(exifData);
698     return SetExifMetadata(exifMetadata);
699 }
700 
SetExifMetadata(std::shared_ptr<ExifMetadata> exifMetadata)701 int32_t Picture::SetExifMetadata(std::shared_ptr<ExifMetadata> exifMetadata)
702 {
703     return SetMetadata(MetadataType::EXIF, exifMetadata);
704 }
705 
GetExifMetadata()706 std::shared_ptr<ExifMetadata> Picture::GetExifMetadata()
707 {
708     auto exifMetadata = GetMetadata(MetadataType::EXIF);
709     if (exifMetadata == nullptr) {
710         return nullptr;
711     }
712     return std::reinterpret_pointer_cast<ExifMetadata>(exifMetadata);
713 }
714 
SetMaintenanceData(sptr<SurfaceBuffer> & surfaceBuffer)715 bool Picture::SetMaintenanceData(sptr<SurfaceBuffer> &surfaceBuffer)
716 {
717     if (surfaceBuffer == nullptr) {
718         return false;
719     }
720     maintenanceData_ = surfaceBuffer;
721     return true;
722 }
723 
GetMaintenanceData() const724 sptr<SurfaceBuffer> Picture::GetMaintenanceData() const
725 {
726     return maintenanceData_;
727 }
728 
GetMetadata(MetadataType type)729 std::shared_ptr<ImageMetadata> Picture::GetMetadata(MetadataType type)
730 {
731     if (metadatas_.find(type) == metadatas_.end()) {
732         IMAGE_LOGE("metadata type(%{public}d) not exist.", static_cast<int32_t>(type));
733         return nullptr;
734     }
735     return metadatas_[type];
736 }
737 
SetMetadata(MetadataType type,std::shared_ptr<ImageMetadata> pictureMetadata)738 uint32_t Picture::SetMetadata(MetadataType type, std::shared_ptr<ImageMetadata> pictureMetadata)
739 {
740     if (pictureMetadata == nullptr) {
741         IMAGE_LOGE("pictureMetadata is null");
742         return ERR_MEDIA_NULL_POINTER;
743     }
744     if (type != pictureMetadata->GetType()) {
745         IMAGE_LOGE("pictureMetadata type dismatch, %{public}d vs %{public}d",
746             static_cast<int>(type), static_cast<int>(pictureMetadata->GetType()));
747         return ERR_IMAGE_INVALID_PARAMETER;
748     }
749     if (!Picture::IsValidPictureMetadataType(type)) {
750         IMAGE_LOGE("Unsupported pictureMetadata type: %{public}d", static_cast<int32_t>(type));
751         return ERR_IMAGE_INVALID_PARAMETER;
752     }
753     if (metadatas_.size() >= MAX_PICTURE_META_TYPE_COUNT) {
754         IMAGE_LOGE("Failed to set metadata, the size of metadata exceeds the maximum limit %{public}llu.",
755             static_cast<unsigned long long>(MAX_PICTURE_META_TYPE_COUNT));
756         return ERR_IMAGE_INVALID_PARAMETER;
757     }
758     metadatas_[type] = pictureMetadata;
759     if (type == MetadataType::EXIF && mainPixelMap_ != nullptr) {
760         auto exifMetadata = std::reinterpret_pointer_cast<ExifMetadata>(pictureMetadata);
761         mainPixelMap_->SetExifMetadata(exifMetadata);
762     }
763     return SUCCESS;
764 }
765 
DumpPictureIfDumpEnabled(Picture & picture,std::string dumpType)766 void Picture::DumpPictureIfDumpEnabled(Picture& picture, std::string dumpType)
767 {
768     CHECK_ERROR_RETURN(!ImageSystemProperties::GetDumpPictureEnabled());
769     CHECK_ERROR_RETURN_LOG(picture.GetMainPixel() == nullptr, "DumpPictureIfDumpEnabled mainPixelmap is null");
770     ImageUtils::DumpPixelMap(picture.GetMainPixel().get(), dumpType + "_MainPixelmap");
771     auto auxTypes = ImageUtils::GetAllAuxiliaryPictureType();
772     for (AuxiliaryPictureType auxType : auxTypes) {
773         auto auxPicture = picture.GetAuxiliaryPicture(auxType);
774         if (auxPicture == nullptr) {
775             continue;
776         }
777         auto pixelMap = auxPicture->GetContentPixel();
778         if (pixelMap != nullptr) {
779             ImageUtils::DumpPixelMap(pixelMap.get(), dumpType + "_AuxiliaryType", static_cast<uint64_t>(auxType));
780         }
781     }
782 }
783 
IsValidPictureMetadataType(MetadataType metadataType)784 bool Picture::IsValidPictureMetadataType(MetadataType metadataType)
785 {
786     const static std::set<MetadataType> pictureMetadataTypes = {
787         MetadataType::EXIF,
788         MetadataType::GIF,
789     };
790     return pictureMetadataTypes.find(metadataType) != pictureMetadataTypes.end();
791 }
792 } // namespace Media
793 } // namespace OHOS
794