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 
35 namespace OHOS {
36 namespace Media {
37 using namespace OHOS::HDI::Display::Graphic::Common::V1_0;
38 namespace {
39     static const std::map<int32_t, PixelFormat> PIXEL_FORMAT_MAP = {
40         { GRAPHIC_PIXEL_FMT_RGBA_8888, PixelFormat::RGBA_8888 },
41         { GRAPHIC_PIXEL_FMT_YCBCR_420_SP, PixelFormat::NV12 },
42         { GRAPHIC_PIXEL_FMT_YCRCB_420_SP, PixelFormat::NV21 },
43         { GRAPHIC_PIXEL_FMT_RGBA_1010102, PixelFormat::RGBA_1010102 },
44         { GRAPHIC_PIXEL_FMT_BGRA_8888, PixelFormat::BGRA_8888 },
45         { GRAPHIC_PIXEL_FMT_RGB_888, PixelFormat::RGB_888 },
46         { GRAPHIC_PIXEL_FMT_RGB_565, PixelFormat::RGB_565 },
47         { GRAPHIC_PIXEL_FMT_RGBA16_FLOAT, PixelFormat::RGBA_F16 },
48         { GRAPHIC_PIXEL_FMT_YCBCR_P010, PixelFormat::YCBCR_P010 },
49         { GRAPHIC_PIXEL_FMT_YCRCB_P010, PixelFormat::YCRCB_P010 },
50     };
51 
52     static const std::map<CM_ColorSpaceType, ColorSpace> CM_COLORSPACE_MAP = {
53         { CM_COLORSPACE_NONE, ColorSpace::UNKNOWN },
54         { CM_BT709_FULL, ColorSpace::ITU_709 },
55         { CM_BT2020_HLG_FULL, ColorSpace::ITU_2020 },
56         { CM_BT2020_PQ_FULL, ColorSpace::ITU_2020 },
57         { CM_BT709_LIMIT, ColorSpace::ITU_709 },
58         { CM_BT2020_HLG_LIMIT, ColorSpace::ITU_2020 },
59         { CM_BT2020_PQ_LIMIT, ColorSpace::ITU_2020 },
60         { CM_SRGB_FULL, ColorSpace::SRGB },
61         { CM_P3_FULL, ColorSpace::DCI_P3 },
62         { CM_P3_HLG_FULL, ColorSpace::DCI_P3 },
63         { CM_P3_PQ_FULL, ColorSpace::DCI_P3 },
64         { CM_ADOBERGB_FULL, ColorSpace::ADOBE_RGB_1998 },
65         { CM_SRGB_LIMIT, ColorSpace::SRGB },
66         { CM_P3_LIMIT, ColorSpace::DCI_P3 },
67         { CM_P3_HLG_LIMIT, ColorSpace::DCI_P3 },
68         { CM_P3_PQ_LIMIT, ColorSpace::DCI_P3 },
69         { CM_ADOBERGB_LIMIT, ColorSpace::ADOBE_RGB_1998 },
70         { CM_LINEAR_SRGB, ColorSpace::LINEAR_SRGB },
71         { CM_LINEAR_BT709, ColorSpace::ITU_709 },
72         { CM_LINEAR_P3, ColorSpace::DISPLAY_P3 },
73         { CM_LINEAR_BT2020, ColorSpace::ITU_2020 },
74         { CM_DISPLAY_SRGB, ColorSpace::SRGB },
75         { CM_DISPLAY_P3_SRGB, ColorSpace::DISPLAY_P3 },
76         { CM_DISPLAY_P3_HLG, ColorSpace::DISPLAY_P3 },
77         { CM_DISPLAY_P3_PQ, ColorSpace::DISPLAY_P3 },
78         { CM_DISPLAY_BT2020_SRGB, ColorSpace::ITU_2020 },
79         { CM_DISPLAY_BT2020_HLG, ColorSpace::ITU_2020 },
80         { CM_DISPLAY_BT2020_PQ, ColorSpace::ITU_2020 },
81     };
82 
83 #ifdef IMAGE_COLORSPACE_FLAG
84     static const std::map<CM_ColorSpaceType, ColorManager::ColorSpaceName> CM_COLORSPACE_NAME_MAP = {
85         { CM_COLORSPACE_NONE, ColorManager::NONE },
86         { CM_BT601_EBU_FULL, ColorManager::BT601_EBU },
87         { CM_BT601_SMPTE_C_FULL, ColorManager::BT601_SMPTE_C },
88         { CM_BT709_FULL, ColorManager::BT709 },
89         { CM_BT2020_HLG_FULL, ColorManager::BT2020_HLG },
90         { CM_BT2020_PQ_FULL, ColorManager::BT2020_PQ },
91         { CM_BT601_EBU_LIMIT, ColorManager::BT601_EBU_LIMIT },
92         { CM_BT601_SMPTE_C_LIMIT, ColorManager::BT601_SMPTE_C_LIMIT },
93         { CM_BT709_LIMIT, ColorManager::BT709_LIMIT },
94         { CM_BT2020_HLG_LIMIT, ColorManager::BT2020_HLG_LIMIT },
95         { CM_BT2020_PQ_LIMIT, ColorManager::BT2020_PQ_LIMIT },
96         { CM_SRGB_FULL, ColorManager::SRGB },
97         { CM_P3_FULL, ColorManager::DCI_P3 },
98         { CM_P3_HLG_FULL, ColorManager::P3_HLG },
99         { CM_P3_PQ_FULL, ColorManager::P3_PQ },
100         { CM_ADOBERGB_FULL, ColorManager::ADOBE_RGB },
101         { CM_SRGB_LIMIT, ColorManager::SRGB_LIMIT },
102         { CM_P3_LIMIT, ColorManager::DISPLAY_P3_LIMIT },
103         { CM_P3_HLG_LIMIT, ColorManager::P3_HLG_LIMIT },
104         { CM_P3_PQ_LIMIT, ColorManager::P3_PQ_LIMIT },
105         { CM_ADOBERGB_LIMIT, ColorManager::ADOBE_RGB_LIMIT },
106         { CM_LINEAR_SRGB, ColorManager::LINEAR_SRGB },
107         { CM_LINEAR_BT709, ColorManager::LINEAR_BT709 },
108         { CM_LINEAR_P3, ColorManager::LINEAR_P3 },
109         { CM_LINEAR_BT2020, ColorManager::LINEAR_BT2020 },
110         { CM_DISPLAY_SRGB, ColorManager::DISPLAY_SRGB },
111         { CM_DISPLAY_P3_SRGB, ColorManager::DISPLAY_P3_SRGB },
112         { CM_DISPLAY_P3_HLG, ColorManager::DISPLAY_P3_HLG },
113         { CM_DISPLAY_P3_PQ, ColorManager::DISPLAY_P3_PQ },
114         { CM_DISPLAY_BT2020_SRGB, ColorManager::DISPLAY_BT2020_SRGB },
115         { CM_DISPLAY_BT2020_HLG, ColorManager::DISPLAY_BT2020_HLG },
116         { CM_DISPLAY_BT2020_PQ, ColorManager::DISPLAY_BT2020_PQ },
117     };
118 #endif
119 }
120 const static uint64_t MAX_AUXILIARY_PICTURE_COUNT = 32;
121 const static uint64_t MAX_EXIFMETADATA_SIZE = 1024 * 1024;
122 static const uint8_t NUM_0 = 0;
123 static const uint8_t NUM_1 = 1;
124 static const uint8_t NUM_2 = 2;
125 static const std::string EXIF_DATA_SIZE_TAG = "exifDataSize";
126 
IsYuvFormat(PixelFormat format)127 static bool IsYuvFormat(PixelFormat format)
128 {
129     return format == PixelFormat::NV21 || format == PixelFormat::NV12 ||
130         format == PixelFormat::YCRCB_P010 || format == PixelFormat::YCBCR_P010;
131 }
132 
IsAlphaFormat(PixelFormat format)133 static bool IsAlphaFormat(PixelFormat format)
134 {
135     return format == PixelFormat::RGBA_8888 || format == PixelFormat::BGRA_8888 ||
136         format == PixelFormat::RGBA_1010102 || format == PixelFormat::RGBA_F16;
137 }
138 
SbFormat2PixelFormat(int32_t sbFormat)139 static PixelFormat SbFormat2PixelFormat(int32_t sbFormat)
140 {
141     auto iter = PIXEL_FORMAT_MAP.find(sbFormat);
142     if (iter == PIXEL_FORMAT_MAP.end()) {
143         return PixelFormat::UNKNOWN;
144     }
145     return iter->second;
146 }
147 
GetCMColorSpaceType(sptr<SurfaceBuffer> buffer)148 static CM_ColorSpaceType GetCMColorSpaceType(sptr<SurfaceBuffer> buffer)
149 {
150     if (buffer == nullptr) {
151         return CM_ColorSpaceType::CM_COLORSPACE_NONE;
152     }
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     if (iter == CM_COLORSPACE_MAP.end()) {
162         return ColorSpace::UNKNOWN;
163     }
164     return iter->second;
165 }
166 
167 #ifdef IMAGE_COLORSPACE_FLAG
CMColorSpaceType2ColorSpaceName(CM_ColorSpaceType type)168 static ColorManager::ColorSpaceName CMColorSpaceType2ColorSpaceName(CM_ColorSpaceType type)
169 {
170     auto iter = CM_COLORSPACE_NAME_MAP.find(type);
171     if (iter == CM_COLORSPACE_NAME_MAP.end()) {
172         return ColorManager::NONE;
173     }
174     return iter->second;
175 }
176 #endif
177 
MakeImageInfo(int width,int height,PixelFormat pf,AlphaType at,ColorSpace cs)178 static ImageInfo MakeImageInfo(int width, int height, PixelFormat pf, AlphaType at, ColorSpace cs)
179 {
180     ImageInfo info;
181     info.size.width = width;
182     info.size.height = height;
183     info.pixelFormat = pf;
184     info.alphaType = at;
185     info.colorSpace = cs;
186     return info;
187 }
188 
SetYuvDataInfo(std::unique_ptr<PixelMap> & pixelMap,sptr<OHOS::SurfaceBuffer> & sBuffer)189 static void SetYuvDataInfo(std::unique_ptr<PixelMap> &pixelMap, sptr<OHOS::SurfaceBuffer> &sBuffer)
190 {
191     if (pixelMap == nullptr || sBuffer == nullptr) {
192         return;
193     }
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         int32_t pixelFmt = sBuffer->GetFormat();
205         int uvPlaneOffset = (pixelFmt == GRAPHIC_PIXEL_FMT_YCBCR_420_SP || pixelFmt == GRAPHIC_PIXEL_FMT_YCBCR_P010) ?
206                 NUM_1 : NUM_2;
207         info.yStride = planes->planes[NUM_0].columnStride;
208         info.uvStride = planes->planes[uvPlaneOffset].columnStride;
209         info.yOffset = planes->planes[NUM_0].offset;
210         info.uvOffset = planes->planes[uvPlaneOffset].offset;
211     }
212     pixelMap->SetImageYUVInfo(info);
213 }
214 
SetImageInfoToHdr(std::shared_ptr<PixelMap> & mainPixelMap,std::unique_ptr<PixelMap> & hdrPixelMap)215 static void SetImageInfoToHdr(std::shared_ptr<PixelMap> &mainPixelMap, std::unique_ptr<PixelMap> &hdrPixelMap)
216 {
217     if (mainPixelMap != nullptr && hdrPixelMap != nullptr) {
218         ImageInfo mainInfo;
219         mainPixelMap->GetImageInfo(mainInfo);
220         ImageInfo hdrInfo;
221         hdrPixelMap->GetImageInfo(hdrInfo);
222         hdrInfo.size = mainInfo.size;
223         hdrInfo.encodedFormat = mainInfo.encodedFormat;
224         hdrPixelMap->SetImageInfo(hdrInfo, true);
225     }
226 }
227 
~Picture()228 Picture::~Picture() {}
229 
Create(std::shared_ptr<PixelMap> & pixelMap)230 std::unique_ptr<Picture> Picture::Create(std::shared_ptr<PixelMap> &pixelMap)
231 {
232     if (pixelMap == nullptr) {
233         return nullptr;
234     }
235     std::unique_ptr<Picture> dstPicture = std::make_unique<Picture>();
236     if (pixelMap->GetExifMetadata() != nullptr) {
237         dstPicture->SetExifMetadata(pixelMap->GetExifMetadata());
238     }
239     dstPicture->mainPixelMap_ = pixelMap;
240     return dstPicture;
241 }
242 
Create(sptr<SurfaceBuffer> & surfaceBuffer)243 std::unique_ptr<Picture> Picture::Create(sptr<SurfaceBuffer> &surfaceBuffer)
244 {
245     std::shared_ptr<PixelMap> pixelmap = SurfaceBuffer2PixelMap(surfaceBuffer);
246     return Create(pixelmap);
247 }
248 
SurfaceBuffer2PixelMap(sptr<OHOS::SurfaceBuffer> & surfaceBuffer)249 std::unique_ptr<PixelMap> Picture::SurfaceBuffer2PixelMap(sptr<OHOS::SurfaceBuffer> &surfaceBuffer)
250 {
251     if (surfaceBuffer == nullptr) {
252         return nullptr;
253     }
254     PixelFormat pixelFormat = SbFormat2PixelFormat(surfaceBuffer->GetFormat());
255     ColorSpace colorSpace = CMColorSpaceType2ColorSpace(GetCMColorSpaceType(surfaceBuffer));
256     AlphaType alphaType = IsAlphaFormat(pixelFormat) ?
257              AlphaType::IMAGE_ALPHA_TYPE_PREMUL : AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
258     void* nativeBuffer = surfaceBuffer.GetRefPtr();
259     int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
260     if (err != OHOS::GSERROR_OK) {
261         IMAGE_LOGE("NativeBufferReference failed");
262         return nullptr;
263     }
264 
265     std::unique_ptr<PixelMap> pixelMap;
266     if (IsYuvFormat(pixelFormat)) {
267 #ifdef EXT_PIXEL
268         pixelMap = std::make_unique<PixelYuvExt>();
269 #else
270         pixelMap = std::make_unique<PixelYuv>();
271 #endif
272     } else {
273         pixelMap = std::make_unique<PixelMap>();
274     }
275     if (pixelMap == nullptr) {
276         return nullptr;
277     }
278 
279     ImageInfo imageInfo = MakeImageInfo(surfaceBuffer->GetWidth(),
280                                         surfaceBuffer->GetHeight(), pixelFormat, alphaType, colorSpace);
281     pixelMap->SetImageInfo(imageInfo, true);
282     pixelMap->SetPixelsAddr(surfaceBuffer->GetVirAddr(),
283                             nativeBuffer, pixelMap->GetRowBytes() * pixelMap->GetHeight(),
284                             AllocatorType::DMA_ALLOC, nullptr);
285 #ifdef IMAGE_COLORSPACE_FLAG
286     ColorManager::ColorSpaceName colorSpaceName =
287         CMColorSpaceType2ColorSpaceName(GetCMColorSpaceType(surfaceBuffer));
288     pixelMap->InnerSetColorSpace(ColorManager::ColorSpace(colorSpaceName));
289 #endif
290     if (IsYuvFormat(pixelFormat)) {
291         SetYuvDataInfo(pixelMap, surfaceBuffer);
292     }
293     return pixelMap;
294 }
295 
GetMainPixel()296 std::shared_ptr<PixelMap> Picture::GetMainPixel()
297 {
298     return mainPixelMap_;
299 }
300 
SetMainPixel(std::shared_ptr<PixelMap> PixelMap)301 void Picture::SetMainPixel(std::shared_ptr<PixelMap> PixelMap)
302 {
303     mainPixelMap_ = PixelMap;
304 }
305 
GetHdrAllocFormat(PixelFormat pixelFormat)306 static int32_t GetHdrAllocFormat(PixelFormat pixelFormat)
307 {
308     int32_t hdrAllocFormat = GRAPHIC_PIXEL_FMT_RGBA_1010102;
309     switch (pixelFormat) {
310         case PixelFormat::RGBA_8888:
311             hdrAllocFormat = GRAPHIC_PIXEL_FMT_RGBA_1010102;
312             break;
313         case PixelFormat::NV21:
314             hdrAllocFormat = GRAPHIC_PIXEL_FMT_YCRCB_P010;
315             break;
316         case PixelFormat::NV12:
317             hdrAllocFormat = GRAPHIC_PIXEL_FMT_YCBCR_P010;
318             break;
319         default:
320             IMAGE_LOGW("%{public}s no corresponding hdrAllocFormat for format: %{public}d", __func__, pixelFormat);
321             break;
322     }
323     IMAGE_LOGD("%{public}s use hdrAllocFormat: %{public}d for format: %{public}d",
324         __func__, hdrAllocFormat, pixelFormat);
325     return hdrAllocFormat;
326 }
327 
TryFixGainmapHdrMetadata(sptr<SurfaceBuffer> & gainmapSptr)328 static void TryFixGainmapHdrMetadata(sptr<SurfaceBuffer> &gainmapSptr)
329 {
330     std::vector<uint8_t> gainmapDynamicMetadata;
331     VpeUtils::GetSbDynamicMetadata(gainmapSptr, gainmapDynamicMetadata);
332     if (gainmapDynamicMetadata.size() != sizeof(ISOMetadata)) {
333         IMAGE_LOGI("%{public}s no need to fix gainmap dynamic metadata, size: %{public}zu",
334             __func__, gainmapDynamicMetadata.size());
335         return;
336     }
337 
338     HDRVividExtendMetadata extendMetadata = {};
339     int32_t memCpyRes = memcpy_s(&extendMetadata.metaISO, sizeof(ISOMetadata),
340         gainmapDynamicMetadata.data(), gainmapDynamicMetadata.size());
341     if (memCpyRes != EOK) {
342         IMAGE_LOGE("%{public}s memcpy_s ISOMetadata fail, error: %{public}d", __func__, memCpyRes);
343         return;
344     }
345     if (extendMetadata.metaISO.useBaseColorFlag != 0) {
346         extendMetadata.baseColorMeta.baseColorPrimary = COLORPRIMARIES_SRGB;
347         extendMetadata.gainmapColorMeta.combineColorPrimary = COLORPRIMARIES_SRGB;
348     } else {
349         extendMetadata.gainmapColorMeta.combineColorPrimary = COLORPRIMARIES_BT2020;
350         extendMetadata.gainmapColorMeta.alternateColorPrimary = COLORPRIMARIES_BT2020;
351     }
352     std::vector<uint8_t> extendMetadataVec(sizeof(HDRVividExtendMetadata));
353     memCpyRes = memcpy_s(extendMetadataVec.data(), extendMetadataVec.size(),
354         &extendMetadata, sizeof(HDRVividExtendMetadata));
355     if (memCpyRes != EOK) {
356         IMAGE_LOGE("%{public}s memcpy_s HDRVividExtendMetadata fail, error: %{public}d", __func__, memCpyRes);
357         return;
358     }
359     VpeUtils::SetSbDynamicMetadata(gainmapSptr, extendMetadataVec);
360 }
361 
ShouldComposeAsCuva(const sptr<SurfaceBuffer> & baseSptr,const sptr<SurfaceBuffer> & gainmapSptr)362 static bool ShouldComposeAsCuva(const sptr<SurfaceBuffer> &baseSptr, const sptr<SurfaceBuffer> &gainmapSptr)
363 {
364     std::vector<uint8_t> baseStaticMetadata;
365     VpeUtils::GetSbStaticMetadata(baseSptr, baseStaticMetadata);
366     std::vector<uint8_t> baseDynamicMetadata;
367     VpeUtils::GetSbDynamicMetadata(gainmapSptr, baseDynamicMetadata);
368     if (baseStaticMetadata.size() == 0 || baseDynamicMetadata.size() == 0) {
369         return true;
370     }
371 
372     std::vector<uint8_t> gainmapDynamicMetadata;
373     VpeUtils::GetSbDynamicMetadata(gainmapSptr, gainmapDynamicMetadata);
374     if (gainmapDynamicMetadata.size() != sizeof(HDRVividExtendMetadata)) {
375         return true;
376     }
377     return false;
378 }
379 
ComposeHdrPixelMap(std::shared_ptr<PixelMap> & mainPixelMap,sptr<SurfaceBuffer> & baseSptr,sptr<SurfaceBuffer> & gainmapSptr)380 static std::unique_ptr<PixelMap> ComposeHdrPixelMap(
381     std::shared_ptr<PixelMap> &mainPixelMap, sptr<SurfaceBuffer> &baseSptr, sptr<SurfaceBuffer> &gainmapSptr)
382 {
383     sptr<SurfaceBuffer> hdrSptr = SurfaceBuffer::Create();
384     ImageInfo imageInfo;
385     mainPixelMap->GetImageInfo(imageInfo);
386     BufferRequestConfig requestConfig = {
387         .width = imageInfo.size.width,
388         .height = imageInfo.size.height,
389         .strideAlignment = imageInfo.size.width,
390         .format = GetHdrAllocFormat(imageInfo.pixelFormat),
391         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
392         .timeout = 0,
393     };
394 
395     GSError error = hdrSptr->Alloc(requestConfig);
396     if (error != GSERROR_OK) {
397         IMAGE_LOGE("HDR SurfaceBuffer Alloc failed, error: %{public}s", GSErrorStr(error).c_str());
398         return nullptr;
399     }
400     VpeUtils::SetSbMetadataType(hdrSptr, CM_IMAGE_HDR_VIVID_SINGLE);
401     VpeUtils::SetSbColorSpaceType(hdrSptr, CM_BT2020_HLG_FULL);
402 
403     VpeSurfaceBuffers buffers = {
404         .sdr = baseSptr,
405         .gainmap = gainmapSptr,
406         .hdr = hdrSptr,
407     };
408     bool isCuva = ShouldComposeAsCuva(baseSptr, gainmapSptr);
409     IMAGE_LOGD("HDR Compose image, isCuva: %{public}d", isCuva);
410     int32_t res = VpeUtils().ColorSpaceConverterComposeImage(buffers, isCuva);
411     if (res != VPE_ERROR_OK) {
412         IMAGE_LOGE("Compose HDR image failed, res: %{public}d", res);
413         return nullptr;
414     }
415     return Picture::SurfaceBuffer2PixelMap(hdrSptr);
416 }
417 
GetHdrComposedPixelMap()418 std::unique_ptr<PixelMap> Picture::GetHdrComposedPixelMap()
419 {
420     std::shared_ptr<PixelMap> gainmap = GetGainmapPixelMap();
421     if (mainPixelMap_ == nullptr || gainmap == nullptr) {
422         IMAGE_LOGE("picture mainPixelMap_ or gainmap is empty.");
423         return nullptr;
424     }
425     if (mainPixelMap_->GetAllocatorType() != AllocatorType::DMA_ALLOC || mainPixelMap_->GetFd() == nullptr ||
426         gainmap->GetAllocatorType() != AllocatorType::DMA_ALLOC || gainmap->GetFd() == nullptr) {
427         IMAGE_LOGE("Unsupport HDR compose, only support the DMA allocation.");
428         return nullptr;
429     }
430     sptr<SurfaceBuffer> baseSptr(reinterpret_cast<SurfaceBuffer*>(mainPixelMap_->GetFd()));
431     VpeUtils::SetSbMetadataType(baseSptr, CM_IMAGE_HDR_VIVID_DUAL);
432     sptr<SurfaceBuffer> gainmapSptr(reinterpret_cast<SurfaceBuffer*>(gainmap->GetFd()));
433     VpeUtils::SetSbMetadataType(gainmapSptr, CM_METADATA_NONE);
434     TryFixGainmapHdrMetadata(gainmapSptr);
435     auto hdrPixelMap = ComposeHdrPixelMap(mainPixelMap_, baseSptr, gainmapSptr);
436     SetImageInfoToHdr(mainPixelMap_, hdrPixelMap);
437     return hdrPixelMap;
438 }
439 
GetGainmapPixelMap()440 std::shared_ptr<PixelMap> Picture::GetGainmapPixelMap()
441 {
442     if (!HasAuxiliaryPicture(AuxiliaryPictureType::GAINMAP)) {
443         IMAGE_LOGE("Unsupport gain map.");
444         return nullptr;
445     } else {
446         auto auxiliaryPicture = GetAuxiliaryPicture(AuxiliaryPictureType::GAINMAP);
447         if (auxiliaryPicture == nullptr) {
448             return nullptr;
449         }
450         return auxiliaryPicture->GetContentPixel();
451     }
452 }
453 
GetAuxiliaryPicture(AuxiliaryPictureType type)454 std::shared_ptr<AuxiliaryPicture> Picture::GetAuxiliaryPicture(AuxiliaryPictureType type)
455 {
456     auto iter = auxiliaryPictures_.find(type);
457     if (iter == auxiliaryPictures_.end()) {
458         return nullptr;
459     }
460     return iter->second;
461 }
462 
SetAuxiliaryPicture(std::shared_ptr<AuxiliaryPicture> & picture)463 void Picture::SetAuxiliaryPicture(std::shared_ptr<AuxiliaryPicture> &picture)
464 {
465     if (picture == nullptr) {
466         IMAGE_LOGE("Auxiliary picture is nullptr.");
467         return;
468     }
469     if (auxiliaryPictures_.size() >= MAX_AUXILIARY_PICTURE_COUNT) {
470         IMAGE_LOGE("The size of auxiliary picture exceeds the maximum limit %{public}llu.",
471             static_cast<unsigned long long>(MAX_AUXILIARY_PICTURE_COUNT));
472         return;
473     }
474     AuxiliaryPictureType type = picture->GetType();
475     auxiliaryPictures_[type] = picture;
476 }
477 
HasAuxiliaryPicture(AuxiliaryPictureType type)478 bool Picture::HasAuxiliaryPicture(AuxiliaryPictureType type)
479 {
480     auto item = auxiliaryPictures_.find(type);
481     return item != auxiliaryPictures_.end() && item->second != nullptr;
482 }
483 
Marshalling(Parcel & data) const484 bool Picture::Marshalling(Parcel &data) const
485 {
486     if (!mainPixelMap_) {
487         IMAGE_LOGE("Main PixelMap is null.");
488         return false;
489     }
490     if (!mainPixelMap_->Marshalling(data)) {
491         IMAGE_LOGE("Failed to marshal main PixelMap.");
492         return false;
493     }
494 
495     size_t numAuxiliaryPictures = auxiliaryPictures_.size();
496     if (numAuxiliaryPictures > MAX_AUXILIARY_PICTURE_COUNT) {
497         return false;
498     }
499     if (!data.WriteUint64(numAuxiliaryPictures)) {
500         IMAGE_LOGE("Failed to write number of auxiliary pictures.");
501         return false;
502     }
503 
504     for (const auto &auxiliaryPicture : auxiliaryPictures_) {
505         AuxiliaryPictureType type =  auxiliaryPicture.first;
506 
507         if (!data.WriteInt32(static_cast<int32_t>(type))) {
508             IMAGE_LOGE("Failed to write auxiliary picture type.");
509             return false;
510         }
511 
512         if (!auxiliaryPicture.second || !auxiliaryPicture.second->Marshalling(data)) {
513             IMAGE_LOGE("Failed to marshal auxiliary picture of type %d.", static_cast<int>(type));
514             return false;
515         }
516     }
517 
518     if (!data.WriteBool(maintenanceData_ != nullptr)) {
519         IMAGE_LOGE("Failed to write maintenance data existence value.");
520         return false;
521     }
522 
523     if (maintenanceData_ != nullptr) {
524         if (maintenanceData_->WriteToMessageParcel(reinterpret_cast<MessageParcel&>(data)) != GSError::GSERROR_OK) {
525             IMAGE_LOGE("Failed to write maintenance data content.");
526             return false;
527         }
528     }
529 
530     if (!data.WriteBool(exifMetadata_ != nullptr)) {
531         IMAGE_LOGE("Failed to write exif data existence value.");
532         return false;
533     }
534 
535     if (exifMetadata_ != nullptr) {
536         if (!exifMetadata_->Marshalling(data)) {
537             IMAGE_LOGE("Failed to marshal exif metadata.");
538             return false;
539         }
540     }
541 
542     return true;
543 }
544 
Unmarshalling(Parcel & data)545 Picture *Picture::Unmarshalling(Parcel &data)
546 {
547     PICTURE_ERR error;
548     Picture* dstPicture = Picture::Unmarshalling(data, error);
549     if (dstPicture == nullptr || error.errorCode != SUCCESS) {
550         IMAGE_LOGE("unmarshalling failed errorCode:%{public}d, errorInfo:%{public}s",
551             error.errorCode, error.errorInfo.c_str());
552     }
553     return dstPicture;
554 }
555 
Unmarshalling(Parcel & parcel,PICTURE_ERR & error)556 Picture *Picture::Unmarshalling(Parcel &parcel, PICTURE_ERR &error)
557 {
558     std::unique_ptr<Picture> picture = std::make_unique<Picture>();
559     std::shared_ptr<PixelMap> pixelmapPtr(PixelMap::Unmarshalling(parcel));
560 
561     if (!pixelmapPtr) {
562         IMAGE_LOGE("Failed to unmarshal main PixelMap.");
563         return nullptr;
564     }
565     picture->SetMainPixel(pixelmapPtr);
566     uint64_t numAuxiliaryPictures = parcel.ReadUint64();
567     if (numAuxiliaryPictures > MAX_AUXILIARY_PICTURE_COUNT) {
568         return nullptr;
569     }
570 
571     for (size_t i = NUM_0; i < numAuxiliaryPictures; ++i) {
572         int32_t type = parcel.ReadInt32();
573         std::shared_ptr<AuxiliaryPicture> auxPtr(AuxiliaryPicture::Unmarshalling(parcel));
574         if (!auxPtr) {
575             IMAGE_LOGE("Failed to unmarshal auxiliary picture of type %d.", type);
576             return nullptr;
577         }
578         picture->SetAuxiliaryPicture(auxPtr);
579     }
580 
581     bool hasMaintenanceData = parcel.ReadBool();
582     if (hasMaintenanceData) {
583         sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
584         if (surfaceBuffer == nullptr) {
585             IMAGE_LOGE("SurfaceBuffer failed to be created.");
586             return nullptr;
587         }
588         if (surfaceBuffer->ReadFromMessageParcel(reinterpret_cast<MessageParcel&>(parcel)) != GSError::GSERROR_OK) {
589             IMAGE_LOGE("Failed to unmarshal maintenance data");
590             return nullptr;
591         }
592         picture->maintenanceData_ = surfaceBuffer;
593     }
594 
595     bool hasExifData = parcel.ReadBool();
596     if (hasExifData) {
597         picture->exifMetadata_ = std::shared_ptr<ExifMetadata>(ExifMetadata::Unmarshalling(parcel));
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     if (size <= 0) {
617         IMAGE_LOGE("Invalid buffer size: %d.", size);
618         return ERR_IMAGE_INVALID_PARAMETER;
619     }
620 
621     size_t tiffHeaderPos = TiffParser::FindTiffPos(reinterpret_cast<const byte *>(surfaceBuffer->GetVirAddr()), size);
622     if (tiffHeaderPos == std::numeric_limits<size_t>::max()) {
623         IMAGE_LOGE("Input image stream is not tiff type.");
624         return ERR_IMAGE_SOURCE_DATA;
625     }
626 
627     if (size > surfaceBuffer->GetSize() || tiffHeaderPos > surfaceBuffer->GetSize()) {
628         IMAGE_LOGE("The size of exif metadata exceeds the buffer size.");
629         return ERR_IMAGE_INVALID_PARAMETER;
630     }
631 
632     if (size - tiffHeaderPos > MAX_EXIFMETADATA_SIZE) {
633         IMAGE_LOGE("Failed to set exif metadata, the size of exif metadata exceeds the maximum limit %{public}llu.",
634             static_cast<unsigned long long>(MAX_EXIFMETADATA_SIZE));
635         return ERR_IMAGE_INVALID_PARAMETER;
636     }
637     ExifData *exifData;
638     TiffParser::Decode(static_cast<const unsigned char *>(surfaceBuffer->GetVirAddr()) + tiffHeaderPos,
639         size - tiffHeaderPos, &exifData);
640     if (exifData == nullptr) {
641         IMAGE_LOGE("Failed to decode EXIF data from image stream.");
642         return ERR_EXIF_DECODE_FAILED;
643     }
644 
645     exifMetadata_ = std::make_shared<OHOS::Media::ExifMetadata>(exifData);
646     return SUCCESS;
647 }
648 
SetExifMetadata(std::shared_ptr<ExifMetadata> exifMetadata)649 int32_t Picture::SetExifMetadata(std::shared_ptr<ExifMetadata> exifMetadata)
650 {
651     if (exifMetadata == nullptr) {
652         return ERR_IMAGE_INVALID_PARAMETER;
653     }
654     exifMetadata_ = exifMetadata;
655     return SUCCESS;
656 }
657 
GetExifMetadata()658 std::shared_ptr<ExifMetadata> Picture::GetExifMetadata()
659 {
660     return exifMetadata_;
661 }
662 
SetMaintenanceData(sptr<SurfaceBuffer> & surfaceBuffer)663 bool Picture::SetMaintenanceData(sptr<SurfaceBuffer> &surfaceBuffer)
664 {
665     if (surfaceBuffer == nullptr) {
666         return false;
667     }
668     maintenanceData_ = surfaceBuffer;
669     return true;
670 }
671 
GetMaintenanceData() const672 sptr<SurfaceBuffer> Picture::GetMaintenanceData() const
673 {
674     return maintenanceData_;
675 }
676 
677 } // namespace Media
678 } // namespace OHOS
679