• 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::DCI_P3 },
63         { CM_P3_HLG_FULL, ColorSpace::DCI_P3 },
64         { CM_P3_PQ_FULL, ColorSpace::DCI_P3 },
65         { CM_ADOBERGB_FULL, ColorSpace::ADOBE_RGB_1998 },
66         { CM_SRGB_LIMIT, ColorSpace::SRGB },
67         { CM_P3_LIMIT, ColorSpace::DCI_P3 },
68         { CM_P3_HLG_LIMIT, ColorSpace::DCI_P3 },
69         { CM_P3_PQ_LIMIT, ColorSpace::DCI_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::DCI_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_EXIFMETADATA_SIZE = 1024 * 1024;
123 static const uint8_t NUM_0 = 0;
124 static const uint8_t NUM_1 = 1;
125 static const uint8_t NUM_2 = 2;
126 static const std::string EXIF_DATA_SIZE_TAG = "exifDataSize";
127 
IsYuvFormat(PixelFormat format)128 static bool IsYuvFormat(PixelFormat format)
129 {
130     return format == PixelFormat::NV21 || format == PixelFormat::NV12 ||
131         format == PixelFormat::YCRCB_P010 || format == PixelFormat::YCBCR_P010;
132 }
133 
IsAlphaFormat(PixelFormat format)134 static bool IsAlphaFormat(PixelFormat format)
135 {
136     return format == PixelFormat::RGBA_8888 || format == PixelFormat::BGRA_8888 ||
137         format == PixelFormat::RGBA_1010102 || format == PixelFormat::RGBA_F16;
138 }
139 
SbFormat2PixelFormat(int32_t sbFormat)140 static PixelFormat SbFormat2PixelFormat(int32_t sbFormat)
141 {
142     auto iter = PIXEL_FORMAT_MAP.find(sbFormat);
143     if (iter == PIXEL_FORMAT_MAP.end()) {
144         return PixelFormat::UNKNOWN;
145     }
146     return iter->second;
147 }
148 
GetCMColorSpaceType(sptr<SurfaceBuffer> buffer)149 static CM_ColorSpaceType GetCMColorSpaceType(sptr<SurfaceBuffer> buffer)
150 {
151     if (buffer == nullptr) {
152         return CM_ColorSpaceType::CM_COLORSPACE_NONE;
153     }
154     CM_ColorSpaceType type;
155     MetadataHelper::GetColorSpaceType(buffer, type);
156     return type;
157 }
158 
CMColorSpaceType2ColorSpace(CM_ColorSpaceType type)159 static ColorSpace CMColorSpaceType2ColorSpace(CM_ColorSpaceType type)
160 {
161     auto iter = CM_COLORSPACE_MAP.find(type);
162     if (iter == CM_COLORSPACE_MAP.end()) {
163         return ColorSpace::UNKNOWN;
164     }
165     return iter->second;
166 }
167 
168 #ifdef IMAGE_COLORSPACE_FLAG
CMColorSpaceType2ColorSpaceName(CM_ColorSpaceType type)169 static ColorManager::ColorSpaceName CMColorSpaceType2ColorSpaceName(CM_ColorSpaceType type)
170 {
171     auto iter = CM_COLORSPACE_NAME_MAP.find(type);
172     if (iter == CM_COLORSPACE_NAME_MAP.end()) {
173         return ColorManager::NONE;
174     }
175     return iter->second;
176 }
177 #endif
178 
MakeImageInfo(int width,int height,PixelFormat pf,AlphaType at,ColorSpace cs)179 static ImageInfo MakeImageInfo(int width, int height, PixelFormat pf, AlphaType at, ColorSpace cs)
180 {
181     ImageInfo info;
182     info.size.width = width;
183     info.size.height = height;
184     info.pixelFormat = pf;
185     info.alphaType = at;
186     info.colorSpace = cs;
187     return info;
188 }
189 
SetYuvDataInfo(std::unique_ptr<PixelMap> & pixelMap,sptr<OHOS::SurfaceBuffer> & sBuffer)190 static void SetYuvDataInfo(std::unique_ptr<PixelMap> &pixelMap, sptr<OHOS::SurfaceBuffer> &sBuffer)
191 {
192     bool cond = pixelMap == nullptr || sBuffer == nullptr;
193     CHECK_ERROR_RETURN(cond);
194     int32_t width = sBuffer->GetWidth();
195     int32_t height = sBuffer->GetHeight();
196     OH_NativeBuffer_Planes *planes = nullptr;
197     GSError retVal = sBuffer->GetPlanesInfo(reinterpret_cast<void**>(&planes));
198     YUVDataInfo info;
199     info.imageSize = { width, height };
200     if (retVal != OHOS::GSERROR_OK || planes == nullptr || planes->planeCount <= NUM_1) {
201         IMAGE_LOGE("Get planesInfo failed, retVal:%{public}d", retVal);
202         return;
203     } else if (planes->planeCount >= NUM_2) {
204         info.yStride = planes->planes[NUM_0].columnStride;
205         info.uvStride = planes->planes[NUM_1].columnStride;
206         info.yOffset = planes->planes[NUM_0].offset;
207         info.uvOffset = planes->planes[NUM_1].offset - NUM_1;
208     }
209     pixelMap->SetImageYUVInfo(info);
210 }
211 
SetImageInfoToHdr(std::shared_ptr<PixelMap> & mainPixelMap,std::unique_ptr<PixelMap> & hdrPixelMap)212 static void SetImageInfoToHdr(std::shared_ptr<PixelMap> &mainPixelMap, std::unique_ptr<PixelMap> &hdrPixelMap)
213 {
214     if (mainPixelMap != nullptr && hdrPixelMap != nullptr) {
215         ImageInfo mainInfo;
216         mainPixelMap->GetImageInfo(mainInfo);
217         ImageInfo hdrInfo;
218         hdrPixelMap->GetImageInfo(hdrInfo);
219         hdrInfo.size = mainInfo.size;
220         hdrInfo.encodedFormat = mainInfo.encodedFormat;
221         hdrPixelMap->SetImageInfo(hdrInfo, true);
222     }
223 }
224 
~Picture()225 Picture::~Picture() {}
226 
Create(std::shared_ptr<PixelMap> & pixelMap)227 std::unique_ptr<Picture> Picture::Create(std::shared_ptr<PixelMap> &pixelMap)
228 {
229     if (pixelMap == nullptr) {
230         return nullptr;
231     }
232     std::unique_ptr<Picture> dstPicture = std::make_unique<Picture>();
233     if (pixelMap->GetExifMetadata() != nullptr) {
234         dstPicture->SetExifMetadata(pixelMap->GetExifMetadata());
235     }
236     dstPicture->mainPixelMap_ = pixelMap;
237     return dstPicture;
238 }
239 
Create(sptr<SurfaceBuffer> & surfaceBuffer)240 std::unique_ptr<Picture> Picture::Create(sptr<SurfaceBuffer> &surfaceBuffer)
241 {
242     std::shared_ptr<PixelMap> pixelmap = SurfaceBuffer2PixelMap(surfaceBuffer);
243     return Create(pixelmap);
244 }
245 
SurfaceBuffer2PixelMap(sptr<OHOS::SurfaceBuffer> & surfaceBuffer)246 std::unique_ptr<PixelMap> Picture::SurfaceBuffer2PixelMap(sptr<OHOS::SurfaceBuffer> &surfaceBuffer)
247 {
248     if (surfaceBuffer == nullptr) {
249         return nullptr;
250     }
251     PixelFormat pixelFormat = SbFormat2PixelFormat(surfaceBuffer->GetFormat());
252     ColorSpace colorSpace = CMColorSpaceType2ColorSpace(GetCMColorSpaceType(surfaceBuffer));
253     AlphaType alphaType = IsAlphaFormat(pixelFormat) ?
254              AlphaType::IMAGE_ALPHA_TYPE_PREMUL : AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
255     void* nativeBuffer = surfaceBuffer.GetRefPtr();
256     int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
257     if (err != OHOS::GSERROR_OK) {
258         IMAGE_LOGE("NativeBufferReference failed");
259         return nullptr;
260     }
261 
262     std::unique_ptr<PixelMap> pixelMap;
263     if (IsYuvFormat(pixelFormat)) {
264 #ifdef EXT_PIXEL
265         pixelMap = std::make_unique<PixelYuvExt>();
266 #else
267         pixelMap = std::make_unique<PixelYuv>();
268 #endif
269     } else {
270         pixelMap = std::make_unique<PixelMap>();
271     }
272     if (pixelMap == nullptr) {
273         return nullptr;
274     }
275 
276     ImageInfo imageInfo = MakeImageInfo(surfaceBuffer->GetWidth(),
277                                         surfaceBuffer->GetHeight(), pixelFormat, alphaType, colorSpace);
278     pixelMap->SetImageInfo(imageInfo, true);
279     pixelMap->SetPixelsAddr(surfaceBuffer->GetVirAddr(),
280                             nativeBuffer, pixelMap->GetRowBytes() * pixelMap->GetHeight(),
281                             AllocatorType::DMA_ALLOC, nullptr);
282 #ifdef IMAGE_COLORSPACE_FLAG
283     ColorManager::ColorSpaceName colorSpaceName =
284         CMColorSpaceType2ColorSpaceName(GetCMColorSpaceType(surfaceBuffer));
285     pixelMap->InnerSetColorSpace(ColorManager::ColorSpace(colorSpaceName));
286 #endif
287     if (IsYuvFormat(pixelFormat)) {
288         SetYuvDataInfo(pixelMap, surfaceBuffer);
289     }
290     return pixelMap;
291 }
292 
GetMainPixel()293 std::shared_ptr<PixelMap> Picture::GetMainPixel()
294 {
295     return mainPixelMap_;
296 }
297 
SetMainPixel(std::shared_ptr<PixelMap> PixelMap)298 void Picture::SetMainPixel(std::shared_ptr<PixelMap> PixelMap)
299 {
300     mainPixelMap_ = PixelMap;
301 }
302 
GetHdrAllocFormat(PixelFormat pixelFormat)303 static int32_t GetHdrAllocFormat(PixelFormat pixelFormat)
304 {
305     int32_t hdrAllocFormat = GRAPHIC_PIXEL_FMT_RGBA_1010102;
306     switch (pixelFormat) {
307         case PixelFormat::RGBA_8888:
308             hdrAllocFormat = GRAPHIC_PIXEL_FMT_RGBA_1010102;
309             break;
310         case PixelFormat::NV21:
311             hdrAllocFormat = GRAPHIC_PIXEL_FMT_YCRCB_P010;
312             break;
313         case PixelFormat::NV12:
314             hdrAllocFormat = GRAPHIC_PIXEL_FMT_YCBCR_P010;
315             break;
316         default:
317             IMAGE_LOGW("%{public}s no corresponding hdrAllocFormat for format: %{public}d", __func__, pixelFormat);
318             break;
319     }
320     IMAGE_LOGD("%{public}s use hdrAllocFormat: %{public}d for format: %{public}d",
321         __func__, hdrAllocFormat, pixelFormat);
322     return hdrAllocFormat;
323 }
324 
TryFixGainmapHdrMetadata(sptr<SurfaceBuffer> & gainmapSptr)325 static void TryFixGainmapHdrMetadata(sptr<SurfaceBuffer> &gainmapSptr)
326 {
327     std::vector<uint8_t> gainmapDynamicMetadata;
328     VpeUtils::GetSbDynamicMetadata(gainmapSptr, gainmapDynamicMetadata);
329     if (gainmapDynamicMetadata.size() != sizeof(ISOMetadata)) {
330         IMAGE_LOGI("%{public}s no need to fix gainmap dynamic metadata, size: %{public}zu",
331             __func__, gainmapDynamicMetadata.size());
332         return;
333     }
334 
335     HDRVividExtendMetadata extendMetadata = {};
336     int32_t memCpyRes = memcpy_s(&extendMetadata.metaISO, sizeof(ISOMetadata),
337         gainmapDynamicMetadata.data(), gainmapDynamicMetadata.size());
338     if (memCpyRes != EOK) {
339         IMAGE_LOGE("%{public}s memcpy_s ISOMetadata fail, error: %{public}d", __func__, memCpyRes);
340         return;
341     }
342     if (extendMetadata.metaISO.useBaseColorFlag != 0) {
343         extendMetadata.baseColorMeta.baseColorPrimary = COLORPRIMARIES_SRGB;
344         extendMetadata.gainmapColorMeta.combineColorPrimary = COLORPRIMARIES_SRGB;
345     } else {
346         extendMetadata.gainmapColorMeta.combineColorPrimary = COLORPRIMARIES_BT2020;
347         extendMetadata.gainmapColorMeta.alternateColorPrimary = COLORPRIMARIES_BT2020;
348     }
349     std::vector<uint8_t> extendMetadataVec(sizeof(HDRVividExtendMetadata));
350     memCpyRes = memcpy_s(extendMetadataVec.data(), extendMetadataVec.size(),
351         &extendMetadata, sizeof(HDRVividExtendMetadata));
352     if (memCpyRes != EOK) {
353         IMAGE_LOGE("%{public}s memcpy_s HDRVividExtendMetadata fail, error: %{public}d", __func__, memCpyRes);
354         return;
355     }
356     VpeUtils::SetSbDynamicMetadata(gainmapSptr, extendMetadataVec);
357 }
358 
ShouldComposeAsCuva(const sptr<SurfaceBuffer> & baseSptr,const sptr<SurfaceBuffer> & gainmapSptr)359 static bool ShouldComposeAsCuva(const sptr<SurfaceBuffer> &baseSptr, const sptr<SurfaceBuffer> &gainmapSptr)
360 {
361     std::vector<uint8_t> baseStaticMetadata;
362     VpeUtils::GetSbStaticMetadata(baseSptr, baseStaticMetadata);
363     std::vector<uint8_t> baseDynamicMetadata;
364     VpeUtils::GetSbDynamicMetadata(gainmapSptr, baseDynamicMetadata);
365     if (baseStaticMetadata.size() == 0 || baseDynamicMetadata.size() == 0) {
366         return true;
367     }
368 
369     std::vector<uint8_t> gainmapDynamicMetadata;
370     VpeUtils::GetSbDynamicMetadata(gainmapSptr, gainmapDynamicMetadata);
371     if (gainmapDynamicMetadata.size() != sizeof(HDRVividExtendMetadata)) {
372         return true;
373     }
374     return false;
375 }
376 
ComposeHdrPixelMap(std::shared_ptr<PixelMap> & mainPixelMap,sptr<SurfaceBuffer> & baseSptr,sptr<SurfaceBuffer> & gainmapSptr)377 static std::unique_ptr<PixelMap> ComposeHdrPixelMap(
378     std::shared_ptr<PixelMap> &mainPixelMap, sptr<SurfaceBuffer> &baseSptr, sptr<SurfaceBuffer> &gainmapSptr)
379 {
380     sptr<SurfaceBuffer> hdrSptr = SurfaceBuffer::Create();
381     ImageInfo imageInfo;
382     mainPixelMap->GetImageInfo(imageInfo);
383     BufferRequestConfig requestConfig = {
384         .width = imageInfo.size.width,
385         .height = imageInfo.size.height,
386         .strideAlignment = imageInfo.size.width,
387         .format = GetHdrAllocFormat(imageInfo.pixelFormat),
388         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
389         .timeout = 0,
390     };
391 
392     GSError error = hdrSptr->Alloc(requestConfig);
393     if (error != GSERROR_OK) {
394         IMAGE_LOGE("HDR SurfaceBuffer Alloc failed, error: %{public}s", GSErrorStr(error).c_str());
395         return nullptr;
396     }
397     VpeUtils::SetSbMetadataType(hdrSptr, CM_IMAGE_HDR_VIVID_SINGLE);
398     VpeUtils::SetSbColorSpaceType(hdrSptr, CM_BT2020_HLG_FULL);
399 
400     VpeSurfaceBuffers buffers = {
401         .sdr = baseSptr,
402         .gainmap = gainmapSptr,
403         .hdr = hdrSptr,
404     };
405     bool isCuva = ShouldComposeAsCuva(baseSptr, gainmapSptr);
406     IMAGE_LOGD("HDR Compose image, isCuva: %{public}d", isCuva);
407     int32_t res = VpeUtils().ColorSpaceConverterComposeImage(buffers, isCuva);
408     if (res != VPE_ERROR_OK) {
409         IMAGE_LOGE("Compose HDR image failed, res: %{public}d", res);
410         return nullptr;
411     }
412     return Picture::SurfaceBuffer2PixelMap(hdrSptr);
413 }
414 
GetHdrComposedPixelMap()415 std::unique_ptr<PixelMap> Picture::GetHdrComposedPixelMap()
416 {
417     std::shared_ptr<PixelMap> gainmap = GetGainmapPixelMap();
418     if (mainPixelMap_ == nullptr || gainmap == nullptr) {
419         IMAGE_LOGE("picture mainPixelMap_ or gainmap is empty.");
420         return nullptr;
421     }
422     if (mainPixelMap_->GetAllocatorType() != AllocatorType::DMA_ALLOC || mainPixelMap_->GetFd() == nullptr ||
423         gainmap->GetAllocatorType() != AllocatorType::DMA_ALLOC || gainmap->GetFd() == nullptr) {
424         IMAGE_LOGE("Unsupport HDR compose, only support the DMA allocation.");
425         return nullptr;
426     }
427     sptr<SurfaceBuffer> baseSptr(reinterpret_cast<SurfaceBuffer*>(mainPixelMap_->GetFd()));
428     VpeUtils::SetSbMetadataType(baseSptr, CM_IMAGE_HDR_VIVID_DUAL);
429     sptr<SurfaceBuffer> gainmapSptr(reinterpret_cast<SurfaceBuffer*>(gainmap->GetFd()));
430     VpeUtils::SetSbMetadataType(gainmapSptr, CM_METADATA_NONE);
431     TryFixGainmapHdrMetadata(gainmapSptr);
432     auto hdrPixelMap = ComposeHdrPixelMap(mainPixelMap_, baseSptr, gainmapSptr);
433     SetImageInfoToHdr(mainPixelMap_, hdrPixelMap);
434     return hdrPixelMap;
435 }
436 
GetGainmapPixelMap()437 std::shared_ptr<PixelMap> Picture::GetGainmapPixelMap()
438 {
439     if (!HasAuxiliaryPicture(AuxiliaryPictureType::GAINMAP)) {
440         IMAGE_LOGE("Unsupport gain map.");
441         return nullptr;
442     } else {
443         auto auxiliaryPicture = GetAuxiliaryPicture(AuxiliaryPictureType::GAINMAP);
444         if (auxiliaryPicture == nullptr) {
445             return nullptr;
446         }
447         return auxiliaryPicture->GetContentPixel();
448     }
449 }
450 
GetAuxiliaryPicture(AuxiliaryPictureType type)451 std::shared_ptr<AuxiliaryPicture> Picture::GetAuxiliaryPicture(AuxiliaryPictureType type)
452 {
453     auto iter = auxiliaryPictures_.find(type);
454     if (iter == auxiliaryPictures_.end()) {
455         return nullptr;
456     }
457     return iter->second;
458 }
459 
SetAuxiliaryPicture(std::shared_ptr<AuxiliaryPicture> & picture)460 void Picture::SetAuxiliaryPicture(std::shared_ptr<AuxiliaryPicture> &picture)
461 {
462     if (picture == nullptr) {
463         IMAGE_LOGE("Auxiliary picture is nullptr.");
464         return;
465     }
466     if (auxiliaryPictures_.size() >= MAX_AUXILIARY_PICTURE_COUNT) {
467         IMAGE_LOGE("The size of auxiliary picture exceeds the maximum limit %{public}llu.",
468             static_cast<unsigned long long>(MAX_AUXILIARY_PICTURE_COUNT));
469         return;
470     }
471     AuxiliaryPictureType type = picture->GetType();
472     auxiliaryPictures_[type] = picture;
473 }
474 
HasAuxiliaryPicture(AuxiliaryPictureType type)475 bool Picture::HasAuxiliaryPicture(AuxiliaryPictureType type)
476 {
477     auto item = auxiliaryPictures_.find(type);
478     return item != auxiliaryPictures_.end() && item->second != nullptr;
479 }
480 
Marshalling(Parcel & data) const481 bool Picture::Marshalling(Parcel &data) const
482 {
483     if (!mainPixelMap_) {
484         IMAGE_LOGE("Main PixelMap is null.");
485         return false;
486     }
487     if (!mainPixelMap_->Marshalling(data)) {
488         IMAGE_LOGE("Failed to marshal main PixelMap.");
489         return false;
490     }
491 
492     size_t numAuxiliaryPictures = auxiliaryPictures_.size();
493     if (numAuxiliaryPictures > MAX_AUXILIARY_PICTURE_COUNT) {
494         return false;
495     }
496     if (!data.WriteUint64(numAuxiliaryPictures)) {
497         IMAGE_LOGE("Failed to write number of auxiliary pictures.");
498         return false;
499     }
500 
501     for (const auto &auxiliaryPicture : auxiliaryPictures_) {
502         AuxiliaryPictureType type =  auxiliaryPicture.first;
503 
504         if (!data.WriteInt32(static_cast<int32_t>(type))) {
505             IMAGE_LOGE("Failed to write auxiliary picture type.");
506             return false;
507         }
508 
509         if (!auxiliaryPicture.second || !auxiliaryPicture.second->Marshalling(data)) {
510             IMAGE_LOGE("Failed to marshal auxiliary picture of type %d.", static_cast<int>(type));
511             return false;
512         }
513     }
514 
515     if (!data.WriteBool(maintenanceData_ != nullptr)) {
516         IMAGE_LOGE("Failed to write maintenance data existence value.");
517         return false;
518     }
519 
520     if (maintenanceData_ != nullptr) {
521         if (maintenanceData_->WriteToMessageParcel(reinterpret_cast<MessageParcel&>(data)) != GSError::GSERROR_OK) {
522             IMAGE_LOGE("Failed to write maintenance data content.");
523             return false;
524         }
525     }
526 
527     if (!data.WriteBool(exifMetadata_ != nullptr)) {
528         IMAGE_LOGE("Failed to write exif data existence value.");
529         return false;
530     }
531 
532     if (exifMetadata_ != nullptr) {
533         if (!exifMetadata_->Marshalling(data)) {
534             IMAGE_LOGE("Failed to marshal exif metadata.");
535             return false;
536         }
537     }
538 
539     return true;
540 }
541 
Unmarshalling(Parcel & data)542 Picture *Picture::Unmarshalling(Parcel &data)
543 {
544     PICTURE_ERR error;
545     Picture* dstPicture = Picture::Unmarshalling(data, error);
546     if (dstPicture == nullptr || error.errorCode != SUCCESS) {
547         IMAGE_LOGE("unmarshalling failed errorCode:%{public}d, errorInfo:%{public}s",
548             error.errorCode, error.errorInfo.c_str());
549     }
550     return dstPicture;
551 }
552 
Unmarshalling(Parcel & parcel,PICTURE_ERR & error)553 Picture *Picture::Unmarshalling(Parcel &parcel, PICTURE_ERR &error)
554 {
555     std::unique_ptr<Picture> picture = std::make_unique<Picture>();
556     std::shared_ptr<PixelMap> pixelmapPtr(PixelMap::Unmarshalling(parcel));
557 
558     if (!pixelmapPtr) {
559         IMAGE_LOGE("Failed to unmarshal main PixelMap.");
560         return nullptr;
561     }
562     picture->SetMainPixel(pixelmapPtr);
563     uint64_t numAuxiliaryPictures = parcel.ReadUint64();
564     if (numAuxiliaryPictures > MAX_AUXILIARY_PICTURE_COUNT) {
565         return nullptr;
566     }
567 
568     for (size_t i = NUM_0; i < numAuxiliaryPictures; ++i) {
569         int32_t type = parcel.ReadInt32();
570         std::shared_ptr<AuxiliaryPicture> auxPtr(AuxiliaryPicture::Unmarshalling(parcel));
571         if (!auxPtr) {
572             IMAGE_LOGE("Failed to unmarshal auxiliary picture of type %d.", type);
573             return nullptr;
574         }
575         picture->SetAuxiliaryPicture(auxPtr);
576     }
577 
578     bool hasMaintenanceData = parcel.ReadBool();
579     if (hasMaintenanceData) {
580         sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
581         if (surfaceBuffer == nullptr) {
582             IMAGE_LOGE("SurfaceBuffer failed to be created.");
583             return nullptr;
584         }
585         if (surfaceBuffer->ReadFromMessageParcel(reinterpret_cast<MessageParcel&>(parcel)) != GSError::GSERROR_OK) {
586             IMAGE_LOGE("Failed to unmarshal maintenance data");
587             return nullptr;
588         }
589         picture->maintenanceData_ = surfaceBuffer;
590     }
591 
592     bool hasExifData = parcel.ReadBool();
593     if (hasExifData) {
594         picture->exifMetadata_ = std::shared_ptr<ExifMetadata>(ExifMetadata::Unmarshalling(parcel));
595         if (picture->GetMainPixel() != nullptr) {
596             picture->GetMainPixel()->SetExifMetadata(picture->exifMetadata_);
597         }
598     }
599 
600     return picture.release();
601 }
602 
SetExifMetadata(sptr<SurfaceBuffer> & surfaceBuffer)603 int32_t Picture::SetExifMetadata(sptr<SurfaceBuffer> &surfaceBuffer)
604 {
605     if (surfaceBuffer == nullptr) {
606         return ERR_IMAGE_INVALID_PARAMETER;
607     }
608 
609     auto extraData = surfaceBuffer->GetExtraData();
610     if (extraData == nullptr) {
611         return ERR_IMAGE_INVALID_PARAMETER;
612     }
613 
614     int32_t size = NUM_0;
615     extraData->ExtraGet(EXIF_DATA_SIZE_TAG, size);
616     bool cond = size <= 0;
617     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_INVALID_PARAMETER, "Invalid buffer size: %d.", size);
618 
619     size_t tiffHeaderPos = TiffParser::FindTiffPos(reinterpret_cast<const byte *>(surfaceBuffer->GetVirAddr()), size);
620     cond = tiffHeaderPos == std::numeric_limits<size_t>::max();
621     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_SOURCE_DATA, "Input image stream is not tiff type.");
622 
623     cond = static_cast<uint32_t>(size) > surfaceBuffer->GetSize() || tiffHeaderPos > surfaceBuffer->GetSize();
624     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_INVALID_PARAMETER,
625                                "The size of exif metadata exceeds the buffer size.");
626 
627     cond = static_cast<uint32_t>(size) - tiffHeaderPos > MAX_EXIFMETADATA_SIZE;
628     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_INVALID_PARAMETER,
629                                "Failed to set exif metadata,"
630                                "the size of exif metadata exceeds the maximum limit %{public}llu.",
631                                static_cast<unsigned long long>(MAX_EXIFMETADATA_SIZE));
632     ExifData *exifData;
633     TiffParser::Decode(static_cast<const unsigned char *>(surfaceBuffer->GetVirAddr()) + tiffHeaderPos,
634         size - tiffHeaderPos, &exifData);
635     cond = exifData == nullptr;
636     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_EXIF_DECODE_FAILED, "Failed to decode EXIF data from image stream.");
637 
638     exifMetadata_ = std::make_shared<OHOS::Media::ExifMetadata>(exifData);
639     if (mainPixelMap_ != nullptr) {
640         mainPixelMap_->SetExifMetadata(exifMetadata_);
641     }
642     return SUCCESS;
643 }
644 
SetExifMetadata(std::shared_ptr<ExifMetadata> exifMetadata)645 int32_t Picture::SetExifMetadata(std::shared_ptr<ExifMetadata> exifMetadata)
646 {
647     if (exifMetadata == nullptr) {
648         return ERR_IMAGE_INVALID_PARAMETER;
649     }
650     exifMetadata_ = exifMetadata;
651     if (mainPixelMap_ != nullptr) {
652         mainPixelMap_->SetExifMetadata(exifMetadata_);
653     }
654     return SUCCESS;
655 }
656 
GetExifMetadata()657 std::shared_ptr<ExifMetadata> Picture::GetExifMetadata()
658 {
659     return exifMetadata_;
660 }
661 
SetMaintenanceData(sptr<SurfaceBuffer> & surfaceBuffer)662 bool Picture::SetMaintenanceData(sptr<SurfaceBuffer> &surfaceBuffer)
663 {
664     if (surfaceBuffer == nullptr) {
665         return false;
666     }
667     maintenanceData_ = surfaceBuffer;
668     return true;
669 }
670 
GetMaintenanceData() const671 sptr<SurfaceBuffer> Picture::GetMaintenanceData() const
672 {
673     return maintenanceData_;
674 }
675 
DumpPictureIfDumpEnabled(Picture & picture,std::string dumpType)676 void Picture::DumpPictureIfDumpEnabled(Picture& picture, std::string dumpType)
677 {
678     if (!ImageSystemProperties::GetDumpPictureEnabled()) {
679         return;
680     }
681     if (picture.GetMainPixel() == nullptr) {
682         IMAGE_LOGE("DumpPictureIfDumpEnabled mainPixelmap is null");
683         return;
684     }
685     ImageUtils::DumpPixelMap(picture.GetMainPixel().get(), dumpType + "_MainPixelmap");
686     auto auxTypes = ImageUtils::GetAllAuxiliaryPictureType();
687     for (AuxiliaryPictureType auxType : auxTypes) {
688         auto auxPicture = picture.GetAuxiliaryPicture(auxType);
689         if (auxPicture == nullptr) {
690             continue;
691         }
692         auto pixelMap = auxPicture->GetContentPixel();
693         if (pixelMap != nullptr) {
694             ImageUtils::DumpPixelMap(pixelMap.get(), dumpType + "_AuxiliaryType", static_cast<uint64_t>(auxType));
695         }
696     }
697 }
698 } // namespace Media
699 } // namespace OHOS
700