• 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 
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     };
49 
50     static const std::map<CM_ColorSpaceType, ColorSpace> CM_COLORSPACE_MAP = {
51         { CM_COLORSPACE_NONE, ColorSpace::UNKNOWN },
52         { CM_BT709_FULL, ColorSpace::ITU_709 },
53         { CM_BT2020_HLG_FULL, ColorSpace::ITU_2020 },
54         { CM_BT2020_PQ_FULL, ColorSpace::ITU_2020 },
55         { CM_BT709_LIMIT, ColorSpace::ITU_709 },
56         { CM_BT2020_HLG_LIMIT, ColorSpace::ITU_2020 },
57         { CM_BT2020_PQ_LIMIT, ColorSpace::ITU_2020 },
58         { CM_SRGB_FULL, ColorSpace::SRGB },
59         { CM_P3_FULL, ColorSpace::DCI_P3 },
60         { CM_P3_HLG_FULL, ColorSpace::DCI_P3 },
61         { CM_P3_PQ_FULL, ColorSpace::DCI_P3 },
62         { CM_ADOBERGB_FULL, ColorSpace::ADOBE_RGB_1998 },
63         { CM_SRGB_LIMIT, ColorSpace::SRGB },
64         { CM_P3_LIMIT, ColorSpace::DCI_P3 },
65         { CM_P3_HLG_LIMIT, ColorSpace::DCI_P3 },
66         { CM_P3_PQ_LIMIT, ColorSpace::DCI_P3 },
67         { CM_ADOBERGB_LIMIT, ColorSpace::ADOBE_RGB_1998 },
68         { CM_LINEAR_SRGB, ColorSpace::LINEAR_SRGB },
69         { CM_LINEAR_BT709, ColorSpace::ITU_709 },
70         { CM_LINEAR_P3, ColorSpace::DISPLAY_P3 },
71         { CM_LINEAR_BT2020, ColorSpace::ITU_2020 },
72         { CM_DISPLAY_SRGB, ColorSpace::SRGB },
73         { CM_DISPLAY_P3_SRGB, ColorSpace::DISPLAY_P3 },
74         { CM_DISPLAY_P3_HLG, ColorSpace::DISPLAY_P3 },
75         { CM_DISPLAY_P3_PQ, ColorSpace::DISPLAY_P3 },
76         { CM_DISPLAY_BT2020_SRGB, ColorSpace::ITU_2020 },
77         { CM_DISPLAY_BT2020_HLG, ColorSpace::ITU_2020 },
78         { CM_DISPLAY_BT2020_PQ, ColorSpace::ITU_2020 },
79     };
80 
81 #ifdef IMAGE_COLORSPACE_FLAG
82     static const std::map<CM_ColorSpaceType, ColorManager::ColorSpaceName> CM_COLORSPACE_NAME_MAP = {
83         { CM_COLORSPACE_NONE, ColorManager::NONE },
84         { CM_BT601_EBU_FULL, ColorManager::BT601_EBU },
85         { CM_BT601_SMPTE_C_FULL, ColorManager::BT601_SMPTE_C },
86         { CM_BT709_FULL, ColorManager::BT709 },
87         { CM_BT2020_HLG_FULL, ColorManager::BT2020_HLG },
88         { CM_BT2020_PQ_FULL, ColorManager::BT2020_PQ },
89         { CM_BT601_EBU_LIMIT, ColorManager::BT601_EBU_LIMIT },
90         { CM_BT601_SMPTE_C_LIMIT, ColorManager::BT601_SMPTE_C_LIMIT },
91         { CM_BT709_LIMIT, ColorManager::BT709_LIMIT },
92         { CM_BT2020_HLG_LIMIT, ColorManager::BT2020_HLG_LIMIT },
93         { CM_BT2020_PQ_LIMIT, ColorManager::BT2020_PQ_LIMIT },
94         { CM_SRGB_FULL, ColorManager::SRGB },
95         { CM_P3_FULL, ColorManager::DCI_P3 },
96         { CM_P3_HLG_FULL, ColorManager::P3_HLG },
97         { CM_P3_PQ_FULL, ColorManager::P3_PQ },
98         { CM_ADOBERGB_FULL, ColorManager::ADOBE_RGB },
99         { CM_SRGB_LIMIT, ColorManager::SRGB_LIMIT },
100         { CM_P3_LIMIT, ColorManager::DISPLAY_P3_LIMIT },
101         { CM_P3_HLG_LIMIT, ColorManager::P3_HLG_LIMIT },
102         { CM_P3_PQ_LIMIT, ColorManager::P3_PQ_LIMIT },
103         { CM_ADOBERGB_LIMIT, ColorManager::ADOBE_RGB_LIMIT },
104         { CM_LINEAR_SRGB, ColorManager::LINEAR_SRGB },
105         { CM_LINEAR_BT709, ColorManager::LINEAR_BT709 },
106         { CM_LINEAR_P3, ColorManager::LINEAR_P3 },
107         { CM_LINEAR_BT2020, ColorManager::LINEAR_BT2020 },
108         { CM_DISPLAY_SRGB, ColorManager::DISPLAY_SRGB },
109         { CM_DISPLAY_P3_SRGB, ColorManager::DISPLAY_P3_SRGB },
110         { CM_DISPLAY_P3_HLG, ColorManager::DISPLAY_P3_HLG },
111         { CM_DISPLAY_P3_PQ, ColorManager::DISPLAY_P3_PQ },
112         { CM_DISPLAY_BT2020_SRGB, ColorManager::DISPLAY_BT2020_SRGB },
113         { CM_DISPLAY_BT2020_HLG, ColorManager::DISPLAY_BT2020_HLG },
114         { CM_DISPLAY_BT2020_PQ, ColorManager::DISPLAY_BT2020_PQ },
115     };
116 #endif
117 }
118 const static uint64_t MAX_AUXILIARY_PICTURE_COUNT = 32;
119 static const uint8_t NUM_0 = 0;
120 static const uint8_t NUM_1 = 1;
121 static const uint8_t NUM_2 = 2;
122 static const std::string EXIF_DATA_SIZE_TAG = "exifDataSize";
123 
IsYuvFormat(PixelFormat format)124 static bool IsYuvFormat(PixelFormat format)
125 {
126     return format == PixelFormat::NV21 || format == PixelFormat::NV12;
127 }
128 
IsAlphaFormat(PixelFormat format)129 static bool IsAlphaFormat(PixelFormat format)
130 {
131     return format == PixelFormat::RGBA_8888 || format == PixelFormat::BGRA_8888 ||
132         format == PixelFormat::RGBA_1010102 || format == PixelFormat::RGBA_F16;
133 }
134 
SbFormat2PixelFormat(int32_t sbFormat)135 static PixelFormat SbFormat2PixelFormat(int32_t sbFormat)
136 {
137     auto iter = PIXEL_FORMAT_MAP.find(sbFormat);
138     if (iter == PIXEL_FORMAT_MAP.end()) {
139         return PixelFormat::UNKNOWN;
140     }
141     return iter->second;
142 }
143 
GetCMColorSpaceType(sptr<SurfaceBuffer> buffer)144 static CM_ColorSpaceType GetCMColorSpaceType(sptr<SurfaceBuffer> buffer)
145 {
146     if (buffer == nullptr) {
147         return CM_ColorSpaceType::CM_COLORSPACE_NONE;
148     }
149     CM_ColorSpaceType type;
150     MetadataHelper::GetColorSpaceType(buffer, type);
151     return type;
152 }
153 
CMColorSpaceType2ColorSpace(CM_ColorSpaceType type)154 static ColorSpace CMColorSpaceType2ColorSpace(CM_ColorSpaceType type)
155 {
156     auto iter = CM_COLORSPACE_MAP.find(type);
157     if (iter == CM_COLORSPACE_MAP.end()) {
158         return ColorSpace::UNKNOWN;
159     }
160     return iter->second;
161 }
162 
163 #ifdef IMAGE_COLORSPACE_FLAG
CMColorSpaceType2ColorSpaceName(CM_ColorSpaceType type)164 static ColorManager::ColorSpaceName CMColorSpaceType2ColorSpaceName(CM_ColorSpaceType type)
165 {
166     auto iter = CM_COLORSPACE_NAME_MAP.find(type);
167     if (iter == CM_COLORSPACE_NAME_MAP.end()) {
168         return ColorManager::NONE;
169     }
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     if (pixelMap == nullptr || sBuffer == nullptr) {
188         return;
189     }
190     int32_t width = sBuffer->GetWidth();
191     int32_t height = sBuffer->GetHeight();
192     OH_NativeBuffer_Planes *planes = nullptr;
193     GSError retVal = sBuffer->GetPlanesInfo(reinterpret_cast<void**>(&planes));
194     YUVDataInfo info;
195     info.imageSize = { width, height };
196     if (retVal != OHOS::GSERROR_OK || planes == nullptr || planes->planeCount <= NUM_1) {
197         IMAGE_LOGE("Get planesInfo failed, retVal:%{public}d", retVal);
198         return;
199     } else if (planes->planeCount >= NUM_2) {
200         int32_t pixelFmt = sBuffer->GetFormat();
201         int uvPlaneOffset = (pixelFmt == GRAPHIC_PIXEL_FMT_YCBCR_420_SP || pixelFmt == GRAPHIC_PIXEL_FMT_YCBCR_P010) ?
202                 NUM_1 : NUM_2;
203         info.yStride = planes->planes[NUM_0].columnStride;
204         info.uvStride = planes->planes[uvPlaneOffset].columnStride;
205         info.yOffset = planes->planes[NUM_0].offset;
206         info.uvOffset = planes->planes[uvPlaneOffset].offset;
207     }
208     pixelMap->SetImageYUVInfo(info);
209 }
210 
SetImageInfoToHdr(std::shared_ptr<PixelMap> & mainPixelMap,std::unique_ptr<PixelMap> & hdrPixelMap)211 static void SetImageInfoToHdr(std::shared_ptr<PixelMap> &mainPixelMap, std::unique_ptr<PixelMap> &hdrPixelMap)
212 {
213     if (mainPixelMap != nullptr && hdrPixelMap != nullptr) {
214         ImageInfo mainInfo;
215         mainPixelMap->GetImageInfo(mainInfo);
216         ImageInfo hdrInfo;
217         hdrPixelMap->GetImageInfo(hdrInfo);
218         hdrInfo.size = mainInfo.size;
219         hdrInfo.encodedFormat = mainInfo.encodedFormat;
220         hdrPixelMap->SetImageInfo(hdrInfo, true);
221     }
222 }
223 
~Picture()224 Picture::~Picture() {}
225 
Create(std::shared_ptr<PixelMap> & pixelMap)226 std::unique_ptr<Picture> Picture::Create(std::shared_ptr<PixelMap> &pixelMap)
227 {
228     if (pixelMap == nullptr) {
229         return nullptr;
230     }
231     std::unique_ptr<Picture> dstPicture = std::make_unique<Picture>();
232     if (pixelMap->GetExifMetadata() != nullptr) {
233         dstPicture->SetExifMetadata(pixelMap->GetExifMetadata());
234     }
235     dstPicture->mainPixelMap_ = pixelMap;
236     return dstPicture;
237 }
238 
Create(sptr<SurfaceBuffer> & surfaceBuffer)239 std::unique_ptr<Picture> Picture::Create(sptr<SurfaceBuffer> &surfaceBuffer)
240 {
241     std::shared_ptr<PixelMap> pixelmap = SurfaceBuffer2PixelMap(surfaceBuffer);
242     return Create(pixelmap);
243 }
244 
SurfaceBuffer2PixelMap(sptr<OHOS::SurfaceBuffer> & surfaceBuffer)245 std::unique_ptr<PixelMap> Picture::SurfaceBuffer2PixelMap(sptr<OHOS::SurfaceBuffer> &surfaceBuffer)
246 {
247     if (surfaceBuffer == nullptr) {
248         return nullptr;
249     }
250     PixelFormat pixelFormat = SbFormat2PixelFormat(surfaceBuffer->GetFormat());
251     ColorSpace colorSpace = CMColorSpaceType2ColorSpace(GetCMColorSpaceType(surfaceBuffer));
252     AlphaType alphaType = IsAlphaFormat(pixelFormat) ?
253              AlphaType::IMAGE_ALPHA_TYPE_PREMUL : AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
254     void* nativeBuffer = surfaceBuffer.GetRefPtr();
255     int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
256     if (err != OHOS::GSERROR_OK) {
257         IMAGE_LOGE("NativeBufferReference failed");
258         return nullptr;
259     }
260 
261     std::unique_ptr<PixelMap> pixelMap;
262     if (IsYuvFormat(pixelFormat)) {
263 #ifdef EXT_PIXEL
264         pixelMap = std::make_unique<PixelYuvExt>();
265 #else
266         pixelMap = std::make_unique<PixelYuv>();
267 #endif
268     } else {
269         pixelMap = std::make_unique<PixelMap>();
270     }
271     if (pixelMap == nullptr) {
272         return nullptr;
273     }
274 
275     ImageInfo imageInfo = MakeImageInfo(surfaceBuffer->GetWidth(),
276                                         surfaceBuffer->GetHeight(), pixelFormat, alphaType, colorSpace);
277     pixelMap->SetImageInfo(imageInfo, true);
278     pixelMap->SetPixelsAddr(surfaceBuffer->GetVirAddr(),
279                             nativeBuffer, pixelMap->GetRowBytes() * pixelMap->GetHeight(),
280                             AllocatorType::DMA_ALLOC, nullptr);
281 #ifdef IMAGE_COLORSPACE_FLAG
282     ColorManager::ColorSpaceName colorSpaceName =
283         CMColorSpaceType2ColorSpaceName(GetCMColorSpaceType(surfaceBuffer));
284     pixelMap->InnerSetColorSpace(ColorManager::ColorSpace(colorSpaceName));
285 #endif
286     if (IsYuvFormat(pixelFormat)) {
287         SetYuvDataInfo(pixelMap, surfaceBuffer);
288     }
289     return pixelMap;
290 }
291 
GetMainPixel()292 std::shared_ptr<PixelMap> Picture::GetMainPixel()
293 {
294     return mainPixelMap_;
295 }
296 
SetMainPixel(std::shared_ptr<PixelMap> PixelMap)297 void Picture::SetMainPixel(std::shared_ptr<PixelMap> PixelMap)
298 {
299     mainPixelMap_ = PixelMap;
300 }
301 
ComposeHdrPixelMap(ImageHdrType hdrType,CM_ColorSpaceType hdrCmColor,std::shared_ptr<PixelMap> & mainPixelMap,sptr<SurfaceBuffer> & baseSptr,sptr<SurfaceBuffer> & gainmapSptr)302 static std::unique_ptr<PixelMap> ComposeHdrPixelMap(
303     ImageHdrType hdrType, CM_ColorSpaceType hdrCmColor,
304     std::shared_ptr<PixelMap> &mainPixelMap, sptr<SurfaceBuffer> &baseSptr, sptr<SurfaceBuffer> &gainmapSptr)
305 {
306     sptr<SurfaceBuffer> hdrSptr = SurfaceBuffer::Create();
307     ImageInfo imageInfo;
308     mainPixelMap->GetImageInfo(imageInfo);
309     BufferRequestConfig requestConfig = {
310         .width = imageInfo.size.width,
311         .height = imageInfo.size.height,
312         .strideAlignment = imageInfo.size.width,
313         .format = GRAPHIC_PIXEL_FMT_RGBA_1010102,
314         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
315         .timeout = 0,
316     };
317 
318     GSError error = hdrSptr->Alloc(requestConfig);
319     if (error != GSERROR_OK) {
320         IMAGE_LOGE("HDR SurfaceBuffer Alloc failed, %{public}d", ERR_DMA_NOT_EXIST);
321         return nullptr;
322     }
323     CM_HDR_Metadata_Type type;
324     if (hdrType == ImageHdrType::HDR_VIVID_DUAL || hdrType == ImageHdrType::HDR_CUVA) {
325         type = CM_IMAGE_HDR_VIVID_SINGLE;
326     } else if (hdrType == ImageHdrType::HDR_ISO_DUAL) {
327         type = CM_IMAGE_HDR_ISO_SINGLE;
328     }
329     VpeUtils::SetSbMetadataType(hdrSptr, type);
330     VpeUtils::SetSbColorSpaceType(hdrSptr, hdrCmColor);
331 
332     VpeSurfaceBuffers buffers = {
333         .sdr = baseSptr,
334         .gainmap = gainmapSptr,
335         .hdr = hdrSptr,
336     };
337     auto res = VpeUtils().ColorSpaceConverterComposeImage(buffers, (hdrType == ImageHdrType::HDR_CUVA));
338     if (res != VPE_ERROR_OK) {
339         IMAGE_LOGE("Compose HDR image failed");
340         return nullptr;
341     } else {
342         return Picture::SurfaceBuffer2PixelMap(hdrSptr);
343     }
344 }
345 
GetHdrComposedPixelMap()346 std::unique_ptr<PixelMap> Picture::GetHdrComposedPixelMap()
347 {
348     std::shared_ptr<PixelMap> gainmap = GetGainmapPixelMap();
349     if (mainPixelMap_ == nullptr || gainmap == nullptr) {
350         IMAGE_LOGE("picture mainPixelMap_ or gainmap is empty.");
351         return nullptr;
352     }
353     if (mainPixelMap_->GetAllocatorType() != AllocatorType::DMA_ALLOC || mainPixelMap_->GetFd() == nullptr ||
354         gainmap->GetAllocatorType() != AllocatorType::DMA_ALLOC || gainmap->GetFd() == nullptr) {
355         IMAGE_LOGE("Unsupport HDR compose, only support the DMA allocation.");
356         return nullptr;
357     }
358     ImageHdrType hdrType = gainmap->GetHdrType();
359     HdrMetadata metadata;
360     if (gainmap->GetHdrMetadata() != nullptr) {
361         metadata = *(gainmap->GetHdrMetadata());
362     }
363 
364     CM_ColorSpaceType baseCmColor =
365         ImageSource::ConvertColorSpaceType(mainPixelMap_->InnerGetGrColorSpace().GetColorSpaceName(), true);
366     sptr<SurfaceBuffer> baseSptr(reinterpret_cast<SurfaceBuffer*>(mainPixelMap_->GetFd()));
367     VpeUtils::SetSurfaceBufferInfo(baseSptr, false, hdrType, baseCmColor, metadata);
368 
369     sptr<SurfaceBuffer> gainmapSptr(reinterpret_cast<SurfaceBuffer*>(gainmap->GetFd()));
370     CM_ColorSpaceType hdrCmColor = CM_BT2020_HLG_FULL;
371     CM_ColorSpaceType gainmapCmColor = metadata.extendMeta.metaISO.useBaseColorFlag == 0x01 ? baseCmColor : hdrCmColor;
372     IMAGE_LOGD("ComposeHdrImage color flag = %{public}d, gainmapChannelNum = %{public}d",
373         metadata.extendMeta.metaISO.useBaseColorFlag, metadata.extendMeta.metaISO.gainmapChannelNum);
374     ImageSource::SetVividMetaColor(metadata, baseCmColor, gainmapCmColor, hdrCmColor);
375     VpeUtils::SetSurfaceBufferInfo(gainmapSptr, true, hdrType, gainmapCmColor, metadata);
376 
377     auto hdrPixelMap = ComposeHdrPixelMap(hdrType, hdrCmColor, mainPixelMap_, baseSptr, gainmapSptr);
378     SetImageInfoToHdr(mainPixelMap_, hdrPixelMap);
379     return hdrPixelMap;
380 }
381 
GetGainmapPixelMap()382 std::shared_ptr<PixelMap> Picture::GetGainmapPixelMap()
383 {
384     if (!HasAuxiliaryPicture(AuxiliaryPictureType::GAINMAP)) {
385         IMAGE_LOGE("Unsupport gain map.");
386         return nullptr;
387     } else {
388         auto auxiliaryPicture = GetAuxiliaryPicture(AuxiliaryPictureType::GAINMAP);
389         if (auxiliaryPicture == nullptr) {
390             return nullptr;
391         }
392         return auxiliaryPicture->GetContentPixel();
393     }
394 }
395 
GetAuxiliaryPicture(AuxiliaryPictureType type)396 std::shared_ptr<AuxiliaryPicture> Picture::GetAuxiliaryPicture(AuxiliaryPictureType type)
397 {
398     auto iter = auxiliaryPictures_.find(type);
399     if (iter == auxiliaryPictures_.end()) {
400         return nullptr;
401     }
402     return iter->second;
403 }
404 
SetAuxiliaryPicture(std::shared_ptr<AuxiliaryPicture> & picture)405 void Picture::SetAuxiliaryPicture(std::shared_ptr<AuxiliaryPicture> &picture)
406 {
407     if (picture == nullptr) {
408         IMAGE_LOGE("Auxiliary picture is nullptr.");
409         return;
410     }
411     AuxiliaryPictureType type = picture->GetType();
412     auxiliaryPictures_[type] = picture;
413     if (type == AuxiliaryPictureType::GAINMAP) {
414         std::shared_ptr<PixelMap> gainmapPixel = GetGainmapPixelMap();
415         if (gainmapPixel != nullptr && mainPixelMap_ != nullptr) {
416             mainPixelMap_->SetHdrMetadata(gainmapPixel->GetHdrMetadata());
417             mainPixelMap_->SetHdrType(gainmapPixel->GetHdrType());
418         }
419     }
420 }
421 
HasAuxiliaryPicture(AuxiliaryPictureType type)422 bool Picture::HasAuxiliaryPicture(AuxiliaryPictureType type)
423 {
424     auto item = auxiliaryPictures_.find(type);
425     return item != auxiliaryPictures_.end() && item->second != nullptr;
426 }
427 
Marshalling(Parcel & data) const428 bool Picture::Marshalling(Parcel &data) const
429 {
430     if (!mainPixelMap_) {
431         IMAGE_LOGE("Main PixelMap is null.");
432         return false;
433     }
434     if (!mainPixelMap_->Marshalling(data)) {
435         IMAGE_LOGE("Failed to marshal main PixelMap.");
436         return false;
437     }
438 
439     size_t numAuxiliaryPictures = auxiliaryPictures_.size();
440     if (!data.WriteUint64(numAuxiliaryPictures)) {
441         IMAGE_LOGE("Failed to write number of auxiliary pictures.");
442         return false;
443     }
444 
445     for (const auto &auxiliaryPicture : auxiliaryPictures_) {
446         AuxiliaryPictureType type =  auxiliaryPicture.first;
447 
448         if (!data.WriteInt32(static_cast<int32_t>(type))) {
449             IMAGE_LOGE("Failed to write auxiliary picture type.");
450             return false;
451         }
452 
453         if (!auxiliaryPicture.second || !auxiliaryPicture.second->Marshalling(data)) {
454             IMAGE_LOGE("Failed to marshal auxiliary picture of type %d.", static_cast<int>(type));
455             return false;
456         }
457     }
458 
459     if (!data.WriteBool(maintenanceData_ != nullptr)) {
460         IMAGE_LOGE("Failed to write maintenance data existence value.");
461         return false;
462     }
463 
464     if (maintenanceData_ != nullptr) {
465         if (maintenanceData_->WriteToMessageParcel(reinterpret_cast<MessageParcel&>(data)) != GSError::GSERROR_OK) {
466             IMAGE_LOGE("Failed to write maintenance data content.");
467             return false;
468         }
469     }
470 
471     if (!data.WriteBool(exifMetadata_ != nullptr)) {
472         IMAGE_LOGE("Failed to write exif data existence value.");
473         return false;
474     }
475 
476     if (exifMetadata_ != nullptr) {
477         if (!exifMetadata_->Marshalling(data)) {
478             IMAGE_LOGE("Failed to marshal exif metadata.");
479             return false;
480         }
481     }
482 
483     return true;
484 }
485 
Unmarshalling(Parcel & data)486 Picture *Picture::Unmarshalling(Parcel &data)
487 {
488     PICTURE_ERR error;
489     Picture* dstPicture = Picture::Unmarshalling(data, error);
490     if (dstPicture == nullptr || error.errorCode != SUCCESS) {
491         IMAGE_LOGE("unmarshalling failed errorCode:%{public}d, errorInfo:%{public}s",
492             error.errorCode, error.errorInfo.c_str());
493     }
494     return dstPicture;
495 }
496 
Unmarshalling(Parcel & parcel,PICTURE_ERR & error)497 Picture *Picture::Unmarshalling(Parcel &parcel, PICTURE_ERR &error)
498 {
499     std::unique_ptr<Picture> picture = std::make_unique<Picture>();
500     std::shared_ptr<PixelMap> pixelmapPtr(PixelMap::Unmarshalling(parcel));
501 
502     if (!pixelmapPtr) {
503         IMAGE_LOGE("Failed to unmarshal main PixelMap.");
504         return nullptr;
505     }
506     picture->SetMainPixel(pixelmapPtr);
507     uint64_t numAuxiliaryPictures = parcel.ReadUint64();
508     if (numAuxiliaryPictures > MAX_AUXILIARY_PICTURE_COUNT) {
509         return nullptr;
510     }
511 
512     for (size_t i = NUM_0; i < numAuxiliaryPictures; ++i) {
513         int32_t type = parcel.ReadInt32();
514         std::shared_ptr<AuxiliaryPicture> auxPtr(AuxiliaryPicture::Unmarshalling(parcel));
515         if (!auxPtr) {
516             IMAGE_LOGE("Failed to unmarshal auxiliary picture of type %d.", type);
517             return nullptr;
518         }
519         picture->SetAuxiliaryPicture(auxPtr);
520     }
521 
522     bool hasMaintenanceData = parcel.ReadBool();
523     if (hasMaintenanceData) {
524         sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
525         if (surfaceBuffer == nullptr) {
526             IMAGE_LOGE("SurfaceBuffer failed to be created.");
527             return nullptr;
528         }
529         if (surfaceBuffer->ReadFromMessageParcel(reinterpret_cast<MessageParcel&>(parcel)) != GSError::GSERROR_OK) {
530             IMAGE_LOGE("Failed to unmarshal maintenance data");
531             return nullptr;
532         }
533         picture->maintenanceData_ = surfaceBuffer;
534     }
535 
536     bool hasExifData = parcel.ReadBool();
537     if (hasExifData) {
538         picture->exifMetadata_ = std::shared_ptr<ExifMetadata>(ExifMetadata::Unmarshalling(parcel));
539     }
540 
541     return picture.release();
542 }
543 
SetExifMetadata(sptr<SurfaceBuffer> & surfaceBuffer)544 int32_t Picture::SetExifMetadata(sptr<SurfaceBuffer> &surfaceBuffer)
545 {
546     if (surfaceBuffer == nullptr) {
547         return ERR_IMAGE_INVALID_PARAMETER;
548     }
549 
550     auto extraData = surfaceBuffer->GetExtraData();
551     if (extraData == nullptr) {
552         return ERR_IMAGE_INVALID_PARAMETER;
553     }
554 
555     int32_t size = NUM_0;
556     extraData->ExtraGet(EXIF_DATA_SIZE_TAG, size);
557     if (size <= 0) {
558         IMAGE_LOGE("Invalid buffer size: %d.", size);
559         return ERR_IMAGE_INVALID_PARAMETER;
560     }
561 
562     size_t tiffHeaderPos = TiffParser::FindTiffPos(reinterpret_cast<const byte *>(surfaceBuffer->GetVirAddr()), size);
563     if (tiffHeaderPos == std::numeric_limits<size_t>::max()) {
564         IMAGE_LOGE("Input image stream is not tiff type.");
565         return ERR_IMAGE_SOURCE_DATA;
566     }
567 
568     ExifData *exifData;
569     TiffParser::Decode(static_cast<const unsigned char *>(surfaceBuffer->GetVirAddr()) + tiffHeaderPos,
570         size - tiffHeaderPos, &exifData);
571     if (exifData == nullptr) {
572         IMAGE_LOGE("Failed to decode EXIF data from image stream.");
573         return ERR_EXIF_DECODE_FAILED;
574     }
575 
576     exifMetadata_ = std::make_shared<OHOS::Media::ExifMetadata>(exifData);
577     return SUCCESS;
578 }
579 
SetExifMetadata(std::shared_ptr<ExifMetadata> exifMetadata)580 int32_t Picture::SetExifMetadata(std::shared_ptr<ExifMetadata> exifMetadata)
581 {
582     if (exifMetadata == nullptr) {
583         return ERR_IMAGE_INVALID_PARAMETER;
584     }
585     exifMetadata_ = exifMetadata;
586     return SUCCESS;
587 }
588 
GetExifMetadata()589 std::shared_ptr<ExifMetadata> Picture::GetExifMetadata()
590 {
591     return exifMetadata_;
592 }
593 
SetMaintenanceData(sptr<SurfaceBuffer> & surfaceBuffer)594 bool Picture::SetMaintenanceData(sptr<SurfaceBuffer> &surfaceBuffer)
595 {
596     if (surfaceBuffer == nullptr) {
597         return false;
598     }
599     maintenanceData_ = surfaceBuffer;
600     return true;
601 }
602 
GetMaintenanceData() const603 sptr<SurfaceBuffer> Picture::GetMaintenanceData() const
604 {
605     return maintenanceData_;
606 }
607 
608 } // namespace Media
609 } // namespace OHOS
610