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 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 if (mainPixelMap != nullptr && hdrPixelMap != nullptr) {
211 ImageInfo mainInfo;
212 mainPixelMap->GetImageInfo(mainInfo);
213 ImageInfo hdrInfo;
214 hdrPixelMap->GetImageInfo(hdrInfo);
215 hdrInfo.size = mainInfo.size;
216 hdrInfo.encodedFormat = mainInfo.encodedFormat;
217 hdrPixelMap->SetImageInfo(hdrInfo, true);
218 }
219 }
220
~Picture()221 Picture::~Picture() {}
222
Create(std::shared_ptr<PixelMap> &pixelMap)223 std::unique_ptr<Picture> Picture::Create(std::shared_ptr<PixelMap> &pixelMap)
224 {
225 if (pixelMap == nullptr) {
226 return nullptr;
227 }
228 std::unique_ptr<Picture> dstPicture = std::make_unique<Picture>();
229 if (pixelMap->GetExifMetadata() != nullptr) {
230 dstPicture->SetExifMetadata(pixelMap->GetExifMetadata());
231 }
232 dstPicture->mainPixelMap_ = pixelMap;
233 return dstPicture;
234 }
235
Create(sptr<SurfaceBuffer> &surfaceBuffer)236 std::unique_ptr<Picture> Picture::Create(sptr<SurfaceBuffer> &surfaceBuffer)
237 {
238 std::shared_ptr<PixelMap> pixelmap = SurfaceBuffer2PixelMap(surfaceBuffer);
239 return Create(pixelmap);
240 }
241
SurfaceBuffer2PixelMap(sptr<OHOS::SurfaceBuffer> &surfaceBuffer)242 std::unique_ptr<PixelMap> Picture::SurfaceBuffer2PixelMap(sptr<OHOS::SurfaceBuffer> &surfaceBuffer)
243 {
244 if (surfaceBuffer == nullptr) {
245 return nullptr;
246 }
247 PixelFormat pixelFormat = SbFormat2PixelFormat(surfaceBuffer->GetFormat());
248 ColorSpace colorSpace = CMColorSpaceType2ColorSpace(GetCMColorSpaceType(surfaceBuffer));
249 AlphaType alphaType = IsAlphaFormat(pixelFormat) ?
250 AlphaType::IMAGE_ALPHA_TYPE_PREMUL : AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
251 void* nativeBuffer = surfaceBuffer.GetRefPtr();
252 int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
253 if (err != OHOS::GSERROR_OK) {
254 IMAGE_LOGE("NativeBufferReference failed");
255 return nullptr;
256 }
257
258 std::unique_ptr<PixelMap> pixelMap;
259 if (IsYuvFormat(pixelFormat)) {
260 #ifdef EXT_PIXEL
261 pixelMap = std::make_unique<PixelYuvExt>();
262 #else
263 pixelMap = std::make_unique<PixelYuv>();
264 #endif
265 } else {
266 pixelMap = std::make_unique<PixelMap>();
267 }
268 if (pixelMap == nullptr) {
269 return nullptr;
270 }
271
272 ImageInfo imageInfo = MakeImageInfo(surfaceBuffer->GetWidth(),
273 surfaceBuffer->GetHeight(), pixelFormat, alphaType, colorSpace);
274 pixelMap->SetImageInfo(imageInfo, true);
275 pixelMap->SetPixelsAddr(surfaceBuffer->GetVirAddr(),
276 nativeBuffer, pixelMap->GetRowBytes() * pixelMap->GetHeight(),
277 AllocatorType::DMA_ALLOC, nullptr);
278 #ifdef IMAGE_COLORSPACE_FLAG
279 ColorManager::ColorSpaceName colorSpaceName =
280 CMColorSpaceType2ColorSpaceName(GetCMColorSpaceType(surfaceBuffer));
281 pixelMap->InnerSetColorSpace(ColorManager::ColorSpace(colorSpaceName));
282 #endif
283 if (IsYuvFormat(pixelFormat)) {
284 SetYuvDataInfo(pixelMap, surfaceBuffer);
285 }
286 return pixelMap;
287 }
288
GetMainPixel()289 std::shared_ptr<PixelMap> Picture::GetMainPixel()
290 {
291 return mainPixelMap_;
292 }
293
SetMainPixel(std::shared_ptr<PixelMap> PixelMap)294 void Picture::SetMainPixel(std::shared_ptr<PixelMap> PixelMap)
295 {
296 mainPixelMap_ = PixelMap;
297 }
298
ComposeHdrPixelMap( ImageHdrType hdrType, CM_ColorSpaceType hdrCmColor, std::shared_ptr<PixelMap> &mainPixelMap, sptr<SurfaceBuffer> &baseSptr, sptr<SurfaceBuffer> &gainmapSptr)299 static std::unique_ptr<PixelMap> ComposeHdrPixelMap(
300 ImageHdrType hdrType, CM_ColorSpaceType hdrCmColor,
301 std::shared_ptr<PixelMap> &mainPixelMap, sptr<SurfaceBuffer> &baseSptr, sptr<SurfaceBuffer> &gainmapSptr)
302 {
303 sptr<SurfaceBuffer> hdrSptr = SurfaceBuffer::Create();
304 ImageInfo imageInfo;
305 mainPixelMap->GetImageInfo(imageInfo);
306 BufferRequestConfig requestConfig = {
307 .width = imageInfo.size.width,
308 .height = imageInfo.size.height,
309 .strideAlignment = imageInfo.size.width,
310 .format = GRAPHIC_PIXEL_FMT_RGBA_1010102,
311 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
312 .timeout = 0,
313 };
314
315 GSError error = hdrSptr->Alloc(requestConfig);
316 if (error != GSERROR_OK) {
317 IMAGE_LOGE("HDR SurfaceBuffer Alloc failed, %{public}d", ERR_DMA_NOT_EXIST);
318 return nullptr;
319 }
320 CM_HDR_Metadata_Type type;
321 if (hdrType == ImageHdrType::HDR_VIVID_DUAL || hdrType == ImageHdrType::HDR_CUVA) {
322 type = CM_IMAGE_HDR_VIVID_SINGLE;
323 } else if (hdrType == ImageHdrType::HDR_ISO_DUAL) {
324 type = CM_IMAGE_HDR_ISO_SINGLE;
325 }
326 VpeUtils::SetSbMetadataType(hdrSptr, type);
327 VpeUtils::SetSbColorSpaceType(hdrSptr, hdrCmColor);
328
329 VpeSurfaceBuffers buffers = {
330 .sdr = baseSptr,
331 .gainmap = gainmapSptr,
332 .hdr = hdrSptr,
333 };
334 auto res = VpeUtils().ColorSpaceConverterComposeImage(buffers, (hdrType == ImageHdrType::HDR_CUVA));
335 if (res != VPE_ERROR_OK) {
336 IMAGE_LOGE("Compose HDR image failed");
337 return nullptr;
338 } else {
339 return Picture::SurfaceBuffer2PixelMap(hdrSptr);
340 }
341 }
342
GetHdrComposedPixelMap()343 std::unique_ptr<PixelMap> Picture::GetHdrComposedPixelMap()
344 {
345 if (!HasAuxiliaryPicture(AuxiliaryPictureType::GAINMAP) ||
346 mainPixelMap_->GetAllocatorType() != AllocatorType::DMA_ALLOC) {
347 IMAGE_LOGE("Unsupport HDR compose.");
348 return nullptr;
349 }
350 std::shared_ptr<PixelMap> gainmap = Picture::GetAuxiliaryPicture(AuxiliaryPictureType::GAINMAP)->GetContentPixel();
351 ImageHdrType hdrType = gainmap->GetHdrType();
352 std::shared_ptr<HdrMetadata> metadata = gainmap->GetHdrMetadata();
353
354 CM_ColorSpaceType baseCmColor =
355 ImageSource::ConvertColorSpaceType(mainPixelMap_->InnerGetGrColorSpace().GetColorSpaceName(), true);
356 sptr<SurfaceBuffer> baseSptr(reinterpret_cast<SurfaceBuffer*>(mainPixelMap_->GetFd()));
357 VpeUtils::SetSurfaceBufferInfo(baseSptr, false, hdrType, baseCmColor, *metadata);
358
359 sptr<SurfaceBuffer> gainmapSptr(reinterpret_cast<SurfaceBuffer*>(gainmap->GetFd()));
360 CM_ColorSpaceType hdrCmColor = CM_BT2020_HLG_FULL;
361 CM_ColorSpaceType gainmapCmColor = metadata->extendMeta.metaISO.useBaseColorFlag == 0x01 ? baseCmColor : hdrCmColor;
362 IMAGE_LOGD("ComposeHdrImage color flag = %{public}d, gainmapChannelNum = %{public}d",
363 metadata->extendMeta.metaISO.useBaseColorFlag, metadata->extendMeta.metaISO.gainmapChannelNum);
364 ImageSource::SetVividMetaColor(*metadata, baseCmColor, gainmapCmColor, hdrCmColor);
365 VpeUtils::SetSurfaceBufferInfo(gainmapSptr, true, hdrType, gainmapCmColor, *metadata);
366
367 auto hdrPixelMap = ComposeHdrPixelMap(hdrType, hdrCmColor, mainPixelMap_, baseSptr, gainmapSptr);
368 SetImageInfoToHdr(mainPixelMap_, hdrPixelMap);
369 return hdrPixelMap;
370 }
371
GetGainmapPixelMap()372 std::shared_ptr<PixelMap> Picture::GetGainmapPixelMap()
373 {
374 if (!HasAuxiliaryPicture(AuxiliaryPictureType::GAINMAP)) {
375 IMAGE_LOGE("Unsupport gain map.");
376 return nullptr;
377 } else {
378 return GetAuxiliaryPicture(AuxiliaryPictureType::GAINMAP)->GetContentPixel();
379 }
380 }
381
GetAuxiliaryPicture(AuxiliaryPictureType type)382 std::shared_ptr<AuxiliaryPicture> Picture::GetAuxiliaryPicture(AuxiliaryPictureType type)
383 {
384 auto iter = auxiliaryPictures_.find(type);
385 if (iter == auxiliaryPictures_.end()) {
386 return nullptr;
387 }
388 return iter->second;
389 }
390
SetAuxiliaryPicture(std::shared_ptr<AuxiliaryPicture> &picture)391 void Picture::SetAuxiliaryPicture(std::shared_ptr<AuxiliaryPicture> &picture)
392 {
393 auxiliaryPictures_[picture->GetType()] = picture;
394 if (picture != nullptr && picture->GetType() == AuxiliaryPictureType::GAINMAP) {
395 std::shared_ptr<PixelMap> gainmapPixel = GetGainmapPixelMap();
396 if (gainmapPixel != nullptr && mainPixelMap_ != nullptr) {
397 mainPixelMap_->SetHdrMetadata(gainmapPixel->GetHdrMetadata());
398 mainPixelMap_->SetHdrType(gainmapPixel->GetHdrType());
399 }
400 }
401 }
402
HasAuxiliaryPicture(AuxiliaryPictureType type)403 bool Picture::HasAuxiliaryPicture(AuxiliaryPictureType type)
404 {
405 return auxiliaryPictures_.find(type) != auxiliaryPictures_.end();
406 }
407
Marshalling(Parcel &data) const408 bool Picture::Marshalling(Parcel &data) const
409 {
410 if (!mainPixelMap_) {
411 IMAGE_LOGE("Main PixelMap is null.");
412 return false;
413 }
414 if (!mainPixelMap_->Marshalling(data)) {
415 IMAGE_LOGE("Failed to marshal main PixelMap.");
416 return false;
417 }
418
419 size_t numAuxiliaryPictures = auxiliaryPictures_.size();
420 if (!data.WriteUint64(numAuxiliaryPictures)) {
421 IMAGE_LOGE("Failed to write number of auxiliary pictures.");
422 return false;
423 }
424
425 for (const auto &auxiliaryPicture : auxiliaryPictures_) {
426 AuxiliaryPictureType type = auxiliaryPicture.first;
427
428 if (!data.WriteInt32(static_cast<int32_t>(type))) {
429 IMAGE_LOGE("Failed to write auxiliary picture type.");
430 return false;
431 }
432
433 if (!auxiliaryPicture.second || !auxiliaryPicture.second->Marshalling(data)) {
434 IMAGE_LOGE("Failed to marshal auxiliary picture of type %d.", static_cast<int>(type));
435 return false;
436 }
437 }
438
439 if (!data.WriteBool(maintenanceData_ != nullptr)) {
440 IMAGE_LOGE("Failed to write maintenance data existence value.");
441 return false;
442 }
443
444 if (maintenanceData_ != nullptr) {
445 if (maintenanceData_->WriteToMessageParcel(reinterpret_cast<MessageParcel&>(data)) != GSError::GSERROR_OK) {
446 IMAGE_LOGE("Failed to write maintenance data content.");
447 return false;
448 }
449 }
450
451 if (!data.WriteBool(exifMetadata_ != nullptr)) {
452 IMAGE_LOGE("Failed to write exif data existence value.");
453 return false;
454 }
455
456 if (exifMetadata_ != nullptr) {
457 if (!exifMetadata_->Marshalling(data)) {
458 IMAGE_LOGE("Failed to marshal exif metadata.");
459 return false;
460 }
461 }
462
463 return true;
464 }
465
Unmarshalling(Parcel &data)466 Picture *Picture::Unmarshalling(Parcel &data)
467 {
468 PICTURE_ERR error;
469 Picture* dstPicture = Picture::Unmarshalling(data, error);
470 if (dstPicture == nullptr || error.errorCode != SUCCESS) {
471 IMAGE_LOGE("unmarshalling failed errorCode:%{public}d, errorInfo:%{public}s",
472 error.errorCode, error.errorInfo.c_str());
473 }
474 return dstPicture;
475 }
476
Unmarshalling(Parcel &parcel, PICTURE_ERR &error)477 Picture *Picture::Unmarshalling(Parcel &parcel, PICTURE_ERR &error)
478 {
479 std::unique_ptr<Picture> picture = std::make_unique<Picture>();
480 std::shared_ptr<PixelMap> pixelmapPtr(PixelMap::Unmarshalling(parcel));
481
482 if (!pixelmapPtr) {
483 IMAGE_LOGE("Failed to unmarshal main PixelMap.");
484 return nullptr;
485 }
486 picture->SetMainPixel(pixelmapPtr);
487 uint64_t numAuxiliaryPictures = parcel.ReadUint64();
488 if (numAuxiliaryPictures > MAX_AUXILIARY_PICTURE_COUNT) {
489 return nullptr;
490 }
491
492 for (size_t i = NUM_0; i < numAuxiliaryPictures; ++i) {
493 int32_t type = parcel.ReadInt32();
494 std::shared_ptr<AuxiliaryPicture> auxPtr(AuxiliaryPicture::Unmarshalling(parcel));
495 if (!auxPtr) {
496 IMAGE_LOGE("Failed to unmarshal auxiliary picture of type %d.", type);
497 return nullptr;
498 }
499 picture->SetAuxiliaryPicture(auxPtr);
500 }
501
502 bool hasMaintenanceData = parcel.ReadBool();
503 if (hasMaintenanceData) {
504 sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
505 if (surfaceBuffer->ReadFromMessageParcel(reinterpret_cast<MessageParcel&>(parcel)) != GSError::GSERROR_OK) {
506 IMAGE_LOGE("Failed to unmarshal maintenance data");
507 return nullptr;
508 }
509 picture->maintenanceData_ = surfaceBuffer;
510 }
511
512 bool hasExifData = parcel.ReadBool();
513 if (hasExifData) {
514 picture->exifMetadata_ = std::shared_ptr<ExifMetadata>(ExifMetadata::Unmarshalling(parcel));
515 }
516
517 return picture.release();
518 }
519
SetExifMetadata(sptr<SurfaceBuffer> &surfaceBuffer)520 int32_t Picture::SetExifMetadata(sptr<SurfaceBuffer> &surfaceBuffer)
521 {
522 if (surfaceBuffer == nullptr) {
523 return ERR_IMAGE_INVALID_PARAMETER;
524 }
525
526 auto extraData = surfaceBuffer->GetExtraData();
527 if (extraData == nullptr) {
528 return ERR_IMAGE_INVALID_PARAMETER;
529 }
530
531 int32_t size = NUM_0;
532 extraData->ExtraGet(EXIF_DATA_SIZE_TAG, size);
533 if (size <= 0) {
534 IMAGE_LOGE("Invalid buffer size: %d.", size);
535 return ERR_IMAGE_INVALID_PARAMETER;
536 }
537
538 size_t tiffHeaderPos = TiffParser::FindTiffPos(reinterpret_cast<const byte *>(surfaceBuffer->GetVirAddr()), size);
539 if (tiffHeaderPos == std::numeric_limits<size_t>::max()) {
540 IMAGE_LOGE("Input image stream is not tiff type.");
541 return ERR_IMAGE_SOURCE_DATA;
542 }
543
544 ExifData *exifData;
545 TiffParser::Decode(static_cast<const unsigned char *>(surfaceBuffer->GetVirAddr()) + tiffHeaderPos,
546 size - tiffHeaderPos, &exifData);
547 if (exifData == nullptr) {
548 IMAGE_LOGE("Failed to decode EXIF data from image stream.");
549 return ERR_EXIF_DECODE_FAILED;
550 }
551
552 exifMetadata_ = std::make_shared<OHOS::Media::ExifMetadata>(exifData);
553 return SUCCESS;
554 }
555
SetExifMetadata(std::shared_ptr<ExifMetadata> exifMetadata)556 int32_t Picture::SetExifMetadata(std::shared_ptr<ExifMetadata> exifMetadata)
557 {
558 if (exifMetadata == nullptr) {
559 return ERR_IMAGE_INVALID_PARAMETER;
560 }
561 exifMetadata_ = exifMetadata;
562 return SUCCESS;
563 }
564
GetExifMetadata()565 std::shared_ptr<ExifMetadata> Picture::GetExifMetadata()
566 {
567 return exifMetadata_;
568 }
569
SetMaintenanceData(sptr<SurfaceBuffer> &surfaceBuffer)570 bool Picture::SetMaintenanceData(sptr<SurfaceBuffer> &surfaceBuffer)
571 {
572 if (surfaceBuffer == nullptr) {
573 return false;
574 }
575 maintenanceData_ = surfaceBuffer;
576 return true;
577 }
578
GetMaintenanceData() const579 sptr<SurfaceBuffer> Picture::GetMaintenanceData() const
580 {
581 return maintenanceData_;
582 }
583
584 } // namespace Media
585 } // namespace OHOS
586