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 "common_utils.h"
17 
18 #include <charconv>
19 
20 #include "effect_log.h"
21 #include "effect_buffer.h"
22 #include "image_source.h"
23 #include "uri.h"
24 #include "string_helper.h"
25 #include "memcpy_helper.h"
26 #include "colorspace_helper.h"
27 #include "render_environment.h"
28 #include "format_helper.h"
29 #include "exif_metadata.h"
30 
31 namespace OHOS {
32 namespace Media {
33 namespace Effect {
34 namespace {
35     const std::string IMAGE_LENGTH = "ImageLength";
36     const std::string IMAGE_WIDTH = "ImageWidth";
37     const std::string DATE_TIME = "DateTime";
38     const std::string PIXEL_X_DIMENSION = "PixelXDimension";
39     const std::string PIXEL_Y_DIMENSION = "PixelYDimension";
40     const int32_t TIME_MAX = 64;
41 }
42 
43 using namespace OHOS::ColorManager;
44 using namespace OHOS::HDI::Display::Graphic::Common::V1_0;
45 
46 const std::unordered_map<PixelFormat, IEffectFormat> CommonUtils::pixelFmtToEffectFmt_ = {
47     { PixelFormat::RGBA_8888, IEffectFormat::RGBA8888 },
48     { PixelFormat::NV21, IEffectFormat::YUVNV21 },
49     { PixelFormat::NV12, IEffectFormat::YUVNV12 },
50     { PixelFormat::RGBA_1010102, IEffectFormat::RGBA_1010102 },
51 };
52 
53 const std::unordered_map<GraphicPixelFormat, IEffectFormat> CommonUtils::surfaceBufferFmtToEffectFmt_ = {
54     { GraphicPixelFormat::GRAPHIC_PIXEL_FMT_RGBA_8888, IEffectFormat::RGBA8888},
55     { GraphicPixelFormat::GRAPHIC_PIXEL_FMT_YCBCR_420_SP, IEffectFormat::YUVNV12 },
56     { GraphicPixelFormat::GRAPHIC_PIXEL_FMT_YCRCB_420_SP, IEffectFormat::YUVNV21 },
57     { GraphicPixelFormat::GRAPHIC_PIXEL_FMT_RGBA_1010102, IEffectFormat::RGBA_1010102 },
58     { GraphicPixelFormat::GRAPHIC_PIXEL_FMT_YCBCR_P010, IEffectFormat::YCBCR_P010 },
59     { GraphicPixelFormat::GRAPHIC_PIXEL_FMT_YCRCB_P010, IEffectFormat::YCRCB_P010 },
60 };
61 
62 const std::unordered_map<AllocatorType, BufferType> CommonUtils::allocatorTypeToEffectBuffType_ = {
63     { AllocatorType::HEAP_ALLOC, BufferType::HEAP_MEMORY },
64     { AllocatorType::DMA_ALLOC, BufferType::DMA_BUFFER },
65     { AllocatorType::SHARE_MEM_ALLOC, BufferType::SHARED_MEMORY },
66 };
67 
68 template <class ValueType>
ParseJson(const std::string &key, Plugin::Any &any, EffectJsonPtr &json)69 ErrorCode ParseJson(const std::string &key, Plugin::Any &any, EffectJsonPtr &json)
70 {
71     auto result = Plugin::AnyCast<ValueType>(&any);
72     if (result == nullptr) {
73         return ErrorCode::ERR_ANY_CAST_TYPE_NOT_MATCH;
74     }
75 
76     json->Put(key, *result);
77     return ErrorCode::SUCCESS;
78 }
79 
LockPixelMap(PixelMap *pixelMap, std::shared_ptr<EffectBuffer> &effectBuffer)80 ErrorCode CommonUtils::LockPixelMap(PixelMap *pixelMap, std::shared_ptr<EffectBuffer> &effectBuffer)
81 {
82     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, ErrorCode::ERR_INPUT_NULL, "pixelMap is null!");
83     ColorSpaceName colorSpaceName = pixelMap->InnerGetGrColorSpacePtr() == nullptr ? ColorSpaceName::NONE :
84         pixelMap->InnerGetGrColorSpacePtr()->GetColorSpaceName();
85     EFFECT_LOGD("pixelMapInfos: width=%{public}d, height=%{public}d, formatType=%{public}d " \
86         "rowStride=%{public}d, byteCount=%{public}d, addr=%{private}p, colorSpaceName=%{public}d",
87         pixelMap->GetWidth(), pixelMap->GetHeight(), pixelMap->GetPixelFormat(), pixelMap->GetRowStride(),
88         pixelMap->GetByteCount(), pixelMap->GetPixels(), colorSpaceName);
89 
90     IEffectFormat formatType = SwitchToEffectFormat(pixelMap->GetPixelFormat());
91     if (formatType == IEffectFormat::DEFAULT) {
92         EFFECT_LOGE("pixelFormat not support! pixelFormat=%{public}d", pixelMap->GetPixelFormat());
93         return ErrorCode::ERR_UNSUPPORTED_PIXEL_FORMAT;
94     }
95 
96     std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>();
97     bufferInfo->width_ = static_cast<uint32_t>(pixelMap->GetWidth());
98     bufferInfo->height_ = static_cast<uint32_t>(pixelMap->GetHeight());
99     bufferInfo->rowStride_ = static_cast<uint32_t>(pixelMap->GetRowStride());
100     bufferInfo->len_ = FormatHelper::CalculateSize(bufferInfo->width_, bufferInfo->height_, formatType);
101     bufferInfo->formatType_ = formatType;
102     bufferInfo->colorSpace_ = ColorSpaceHelper::ConvertToEffectColorSpace(colorSpaceName);
103 
104     uint8_t *pixels = const_cast<uint8_t *>(pixelMap->GetPixels());
105     void *srcData = static_cast<void *>(pixels);
106     CHECK_AND_RETURN_RET_LOG(srcData != nullptr, ErrorCode::ERR_PIXELMAP_ACCESSPIXELS_FAIL, "fail exec GetPixels!");
107 
108     EFFECT_LOGI("pixelMap bufferInfos: width=%{public}d, height=%{public}d, formatType=%{public}d, " \
109         "rowStride_=%{public}d, len=%{public}d, colorspace=%{public}d, addr=%{private}p",
110         bufferInfo->width_, bufferInfo->height_, bufferInfo->formatType_, bufferInfo->rowStride_,
111         bufferInfo->len_, bufferInfo->colorSpace_, pixels);
112 
113     std::shared_ptr<ExtraInfo> extraInfo = std::make_unique<ExtraInfo>();
114     extraInfo->dataType = DataType::PIXEL_MAP;
115     extraInfo->bufferType = SwitchToEffectBuffType(pixelMap->GetAllocatorType());
116     extraInfo->pixelMap = pixelMap;
117     extraInfo->surfaceBuffer = nullptr;
118     if (extraInfo->bufferType == BufferType::DMA_BUFFER && pixelMap->GetFd() != nullptr) {
119         extraInfo->surfaceBuffer = reinterpret_cast<SurfaceBuffer*> (pixelMap->GetFd());
120     }
121     if (extraInfo->bufferType == BufferType::SHARED_MEMORY && pixelMap->GetFd() != nullptr) {
122         extraInfo->fd = reinterpret_cast<int *>(pixelMap->GetFd());
123     }
124     EFFECT_LOGI("pixelMap extraInfos: dataType=%{public}d, bufferType=%{public}d, pixelMap=%{public}p, sb=%{public}p",
125         extraInfo->dataType, extraInfo->bufferType, extraInfo->pixelMap, extraInfo->surfaceBuffer);
126 
127     if (extraInfo->surfaceBuffer != nullptr) {
128         SurfaceBuffer *sb = extraInfo->surfaceBuffer;
129         EFFECT_LOGD("pixelMap surfaceBufferInfo: width=%{public}d, height=%{public}d, format=%{public}d, "
130             "rowStride=%{public}d, size=%{public}d, addr=%{private}p", sb->GetWidth(),
131             sb->GetHeight(), sb->GetFormat(), sb->GetStride(), sb->GetSize(), sb->GetVirAddr());
132     }
133 
134     effectBuffer = std::make_unique<EffectBuffer>(bufferInfo, srcData, extraInfo);
135     return ErrorCode::SUCCESS;
136 }
137 
ParseNativeWindowData(std::shared_ptr<EffectBuffer> &effectBuffer, const DataType &dataType)138 ErrorCode CommonUtils::ParseNativeWindowData(std::shared_ptr<EffectBuffer> &effectBuffer, const DataType &dataType)
139 {
140     std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>();
141     bufferInfo->width_ = 0;
142     bufferInfo->height_ = 0;
143     bufferInfo->rowStride_ = 0;
144     bufferInfo->len_ = 0;
145     bufferInfo->formatType_ = IEffectFormat::DEFAULT;
146     std::shared_ptr<ExtraInfo> extraInfo = std::make_unique<ExtraInfo>();
147     extraInfo->dataType = dataType;
148     extraInfo->bufferType = BufferType::DMA_BUFFER;
149     extraInfo->pixelMap = nullptr;
150     extraInfo->surfaceBuffer = nullptr;
151     effectBuffer = std::make_unique<EffectBuffer>(bufferInfo, nullptr, extraInfo);
152     return ErrorCode::SUCCESS;
153 }
154 
ParseSurfaceData(OHOS::SurfaceBuffer *surfaceBuffer, std::shared_ptr<EffectBuffer> &effectBuffer, const DataType &dataType, int64_t timestamp)155 ErrorCode CommonUtils::ParseSurfaceData(OHOS::SurfaceBuffer *surfaceBuffer,
156     std::shared_ptr<EffectBuffer> &effectBuffer, const DataType &dataType, int64_t timestamp)
157 {
158     CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, ErrorCode::ERR_INPUT_NULL, "surfaceBuffer is null!");
159 
160     std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>();
161     bufferInfo->width_ = static_cast<uint32_t>(surfaceBuffer->GetWidth());
162     bufferInfo->height_ = static_cast<uint32_t>(surfaceBuffer->GetHeight());
163     bufferInfo->rowStride_ = static_cast<uint32_t>(surfaceBuffer->GetStride());
164     bufferInfo->len_ = surfaceBuffer->GetSize();
165     bufferInfo->formatType_ = SwitchToEffectFormat((GraphicPixelFormat)surfaceBuffer->GetFormat());
166     CM_ColorSpaceType colorSpaceType = CM_ColorSpaceType::CM_COLORSPACE_NONE;
167     ColorSpaceHelper::GetSurfaceBufferColorSpaceType(surfaceBuffer, colorSpaceType);
168     bufferInfo->colorSpace_ = ColorSpaceHelper::ConvertToEffectColorSpace(colorSpaceType);
169 
170     std::shared_ptr<ExtraInfo> extraInfo = std::make_unique<ExtraInfo>();
171     extraInfo->dataType = dataType;
172     extraInfo->bufferType = BufferType::DMA_BUFFER;
173     extraInfo->pixelMap = nullptr;
174     extraInfo->surfaceBuffer = surfaceBuffer;
175     extraInfo->timestamp = timestamp;
176 
177     effectBuffer = std::make_unique<EffectBuffer>(bufferInfo, surfaceBuffer->GetVirAddr(), extraInfo);
178     EFFECT_LOGI("surfaceBuffer width=%{public}d, height=%{public}d, stride=%{public}d, format=%{public}d, "
179         "size=%{public}d, usage = %{public}llu, addr=%{private}p, colorSpace=%{public}d",
180         surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight(), surfaceBuffer->GetStride(), surfaceBuffer->GetFormat(),
181         surfaceBuffer->GetSize(), static_cast<unsigned long long>(surfaceBuffer->GetUsage()),
182         surfaceBuffer->GetVirAddr(), colorSpaceType);
183     return ErrorCode::SUCCESS;
184 }
185 
UrlToPath(const std::string &url)186 std::string CommonUtils::UrlToPath(const std::string &url)
187 {
188     OHOS::Uri uri = OHOS::Uri(url);
189     return uri.GetPath();
190 }
191 
ParseUri(std::string &uri, std::shared_ptr<EffectBuffer> &effectBuffer, bool isOutputData)192 ErrorCode CommonUtils::ParseUri(std::string &uri, std::shared_ptr<EffectBuffer> &effectBuffer, bool isOutputData)
193 {
194     if (isOutputData) {
195         std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>();
196         std::shared_ptr<ExtraInfo> extraInfo = std::make_unique<ExtraInfo>();
197         extraInfo->dataType = DataType::URI;
198         extraInfo->uri = std::move(uri);
199         effectBuffer = std::make_unique<EffectBuffer>(bufferInfo, nullptr, extraInfo);
200         return ErrorCode::SUCCESS;
201     }
202 
203     auto path = UrlToPath(uri);
204     ErrorCode res = ParsePath(path, effectBuffer, isOutputData);
205     CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res,
206         "ParseUri: path name fail! uri=%{public}s, res=%{public}d", uri.c_str(), res);
207 
208     CHECK_AND_RETURN_RET_LOG(effectBuffer->extraInfo_ != nullptr, ErrorCode::ERR_EXTRA_INFO_NULL,
209         "ParseUri: extra info is null! uri=%{public}s", uri.c_str());
210     effectBuffer->extraInfo_->dataType = DataType::URI;
211     effectBuffer->extraInfo_->uri = std::move(uri);
212 
213     return ErrorCode::SUCCESS;
214 }
215 
ParsePath(std::string &path, std::shared_ptr<EffectBuffer> &effectBuffer, bool isOutputData)216 ErrorCode CommonUtils::ParsePath(std::string &path, std::shared_ptr<EffectBuffer> &effectBuffer,
217     bool isOutputData)
218 {
219     if (isOutputData) {
220         std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>();
221         std::shared_ptr<ExtraInfo> extraInfo = std::make_unique<ExtraInfo>();
222         extraInfo->dataType = DataType::PATH;
223         extraInfo->path = std::move(path);
224         effectBuffer = std::make_unique<EffectBuffer>(bufferInfo, nullptr, extraInfo);
225         return ErrorCode::SUCCESS;
226     }
227 
228     SourceOptions opts;
229     uint32_t errorCode = 0;
230     std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(path, opts, errorCode);
231     CHECK_AND_RETURN_RET_LOG(imageSource != nullptr, ErrorCode::ERR_CREATE_IMAGESOURCE_FAIL,
232         "ImageSource::CreateImageSource fail! path=%{public}s, errorCode=%{public}d", path.c_str(), errorCode);
233 
234     DecodeOptions options;
235     options.desiredDynamicRange = DecodeDynamicRange::AUTO;
236     std::unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(options, errorCode);
237     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, ErrorCode::ERR_CREATE_PIXELMAP_FAIL,
238         "CreatePixelMap fail! path=%{public}s, errorCode=%{public}d", path.c_str(), errorCode);
239 
240     ErrorCode res = LockPixelMap(pixelMap.get(), effectBuffer);
241     CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res,
242         "ParsePath: lock pixel map fail! path=%{public}s, res=%{public}d", path.c_str(), res);
243 
244     CHECK_AND_RETURN_RET_LOG(effectBuffer->extraInfo_ != nullptr, ErrorCode::ERR_EXTRA_INFO_NULL,
245         "ParsePath: extra info is null! uri=%{public}s", path.c_str());
246     effectBuffer->extraInfo_->dataType = DataType::PATH;
247     effectBuffer->extraInfo_->path = std::move(path);
248     effectBuffer->extraInfo_->pixelMap = nullptr;
249     effectBuffer->extraInfo_->innerPixelMap = std::move(pixelMap);
250 
251     return ErrorCode::SUCCESS;
252 }
253 
SwitchToEffectFormat(GraphicPixelFormat pixelFormat)254 IEffectFormat CommonUtils::SwitchToEffectFormat(GraphicPixelFormat pixelFormat)
255 {
256     IEffectFormat formatType = IEffectFormat::DEFAULT;
257 
258     auto itr = surfaceBufferFmtToEffectFmt_.find(pixelFormat);
259     if (itr != surfaceBufferFmtToEffectFmt_.end()) {
260         formatType = itr->second;
261     }
262 
263     return formatType;
264 }
265 
SwitchToEffectFormat(PixelFormat pixelFormat)266 IEffectFormat CommonUtils::SwitchToEffectFormat(PixelFormat pixelFormat)
267 {
268     IEffectFormat formatType = IEffectFormat::DEFAULT;
269 
270     auto itr = pixelFmtToEffectFmt_.find(pixelFormat);
271     if (itr != pixelFmtToEffectFmt_.end()) {
272         formatType = itr->second;
273     }
274 
275     return formatType;
276 }
277 
SwitchToGraphicPixelFormat(IEffectFormat formatType)278 GraphicPixelFormat CommonUtils::SwitchToGraphicPixelFormat(IEffectFormat formatType)
279 {
280     GraphicPixelFormat pixelFormat = GraphicPixelFormat::GRAPHIC_PIXEL_FMT_BUTT;
281 
282     for (const auto &itr : surfaceBufferFmtToEffectFmt_) {
283         if (itr.second == formatType) {
284             pixelFormat = itr.first;
285             break;
286         }
287     }
288 
289     return pixelFormat;
290 }
291 
SwitchToPixelFormat(IEffectFormat formatType)292 PixelFormat CommonUtils::SwitchToPixelFormat(IEffectFormat formatType)
293 {
294     PixelFormat pixelFormat = PixelFormat::UNKNOWN;
295 
296     for (const auto &itr : pixelFmtToEffectFmt_) {
297         if (itr.second == formatType) {
298             pixelFormat = itr.first;
299             break;
300         }
301     }
302 
303     return pixelFormat;
304 }
305 
SwitchToEffectBuffType(AllocatorType allocatorType)306 BufferType CommonUtils::SwitchToEffectBuffType(AllocatorType allocatorType)
307 {
308     BufferType bufferType = BufferType::DEFAULT;
309 
310     auto itr = allocatorTypeToEffectBuffType_.find(allocatorType);
311     if (itr != allocatorTypeToEffectBuffType_.end()) {
312         bufferType = itr->second;
313     }
314 
315     return bufferType;
316 }
317 
UnlockPixelMap(const PixelMap *pixelMap)318 void CommonUtils::UnlockPixelMap(const PixelMap *pixelMap)
319 {
320     EFFECT_LOGI("UnlockPixelMap! pixelMap=%{public}p", pixelMap);
321 }
322 
ParseAnyAndAddToJson(const std::string &key, Plugin::Any &any, EffectJsonPtr &result)323 ErrorCode CommonUtils::ParseAnyAndAddToJson(const std::string &key, Plugin::Any &any, EffectJsonPtr &result)
324 {
325     CHECK_AND_RETURN_RET(ParseJson<float>(key, any, result) != ErrorCode::SUCCESS, ErrorCode::SUCCESS);
326     CHECK_AND_RETURN_RET(ParseJson<int32_t>(key, any, result) != ErrorCode::SUCCESS, ErrorCode::SUCCESS);
327     CHECK_AND_RETURN_RET(ParseJson<uint32_t>(key, any, result) != ErrorCode::SUCCESS, ErrorCode::SUCCESS);
328 #ifndef HST_ANY_WITH_NO_RTTI
329     EFFECT_LOGE("inner any type not support switch to json! type:%{public}s", any.Type().name());
330 #else
331     EFFECT_LOGE("inner any type not support switch to json! type:%{public}s", std::string(any.TypeName()).c_str());
332 #endif
333     return ErrorCode::ERR_ANY_CAST_TYPE_NOT_MATCH;
334 }
335 
EndsWithJPG(const std::string &input)336 bool CommonUtils::EndsWithJPG(const std::string &input)
337 {
338     return StringHelp::EndsWithIgnoreCase(input, "jpg") || StringHelp::EndsWithIgnoreCase(input, "jpeg");
339 }
340 
EndsWithHEIF(const std::string &input)341 bool CommonUtils::EndsWithHEIF(const std::string &input)
342 {
343     return StringHelp::EndsWithIgnoreCase(input, "heic");
344 }
345 
GetPixelsContext(std::shared_ptr<MemoryData> &memoryData, BufferType bufferType, void **context)346 ErrorCode GetPixelsContext(std::shared_ptr<MemoryData> &memoryData, BufferType bufferType, void **context)
347 {
348     switch (bufferType) {
349         case BufferType::HEAP_MEMORY:
350             *context = nullptr;
351             break;
352         case BufferType::DMA_BUFFER: {
353             void *extra = memoryData->memoryInfo.extra;
354             auto surfaceBuffer = reinterpret_cast<SurfaceBuffer *>(extra);
355             CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, ErrorCode::ERR_INVALID_SURFACE_BUFFER,
356                 "DMA_BUFFER: extra info error!");
357             *context = surfaceBuffer;
358             break;
359         }
360         case BufferType::SHARED_MEMORY: {
361             void *extra = memoryData->memoryInfo.extra;
362             auto fd = static_cast<int *>(extra);
363             CHECK_AND_RETURN_RET_LOG(fd != nullptr, ErrorCode::ERR_INVALID_FD, "SHARED_MEMORY: extra info error!");
364             *context = fd;
365             break;
366         }
367         default:
368             EFFECT_LOGE("bufferType not support! bufferType=%{public}d", bufferType);
369             return ErrorCode::ERR_UNSUPPORTED_BUFFER_TYPE;
370     }
371     return ErrorCode::SUCCESS;
372 }
373 
GetImagePropertyInt(const std::shared_ptr<ExifMetadata> &exifMetadata, const std::string &key, int32_t &value)374 int32_t  GetImagePropertyInt(const std::shared_ptr<ExifMetadata> &exifMetadata, const std::string &key, int32_t &value)
375 {
376     std::string strValue;
377     int ret = exifMetadata->GetValue(key, strValue);
378     if (ret != 0) {
379         return ret;
380     }
381 
382     std::from_chars_result res = std::from_chars(strValue.data(), strValue.data() + strValue.size(), value);
383     if (res.ec != std::errc()) {
384         return static_cast<int32_t>(ErrorCode::ERR_IMAGE_DATA);
385     }
386 
387     return 0;
388 }
389 
PrintImageExifInfo(const std::shared_ptr<ExifMetadata> &exifMetadata, const std::string &tag)390 void PrintImageExifInfo(const std::shared_ptr<ExifMetadata> &exifMetadata, const std::string &tag)
391 {
392     if (exifMetadata == nullptr) {
393         return;
394     }
395 
396     int32_t width = 0;
397     GetImagePropertyInt(exifMetadata, IMAGE_WIDTH, width);
398     int32_t length = 0;
399     GetImagePropertyInt(exifMetadata, IMAGE_LENGTH, length);
400     std::string dateTime;
401     exifMetadata->GetValue(DATE_TIME, dateTime);
402     int32_t xDimension = 0;
403     GetImagePropertyInt(exifMetadata, PIXEL_X_DIMENSION, xDimension);
404     int32_t yDimension = 0;
405     GetImagePropertyInt(exifMetadata, PIXEL_Y_DIMENSION, yDimension);
406 
407     EFFECT_LOGD("%{public}s: width=%{public}d, length=%{public}d, dateTime=%{public}s, xDimension=%{public}d, "
408         "yDimension=%{public}d", tag.c_str(), width, length, dateTime.c_str(), xDimension, yDimension);
409 }
410 
UpdateExifDataTime(const std::shared_ptr<ExifMetadata> &exifMetadata)411 void UpdateExifDataTime(const std::shared_ptr<ExifMetadata> &exifMetadata)
412 {
413     CHECK_AND_RETURN_LOG(exifMetadata != nullptr, "UpdateExifDataTime: exifMetadata is null!");
414 
415     std::string dateTime;
416     if (exifMetadata->GetValue(DATE_TIME, dateTime) != 0 || dateTime.empty()) {
417         return;
418     }
419 
420     time_t now = time(nullptr);
421     CHECK_AND_RETURN_LOG(now > 0, "UpdateExifDateTime: time fail!");
422 
423     struct tm *locTime = localtime(&now);
424     CHECK_AND_RETURN_LOG(locTime != nullptr, "UpdateExifDateTime: localtime fail!");
425 
426     char tempTime[TIME_MAX];
427     auto size = strftime(tempTime, sizeof(tempTime), "%Y:%m:%d %H:%M:%S", locTime);
428     CHECK_AND_RETURN_LOG(size > 0, "UpdateExifDateTime: strftime fail!");
429 
430     std::string currentTime = std::string(tempTime, size);
431     bool res = exifMetadata->SetValue(DATE_TIME, currentTime);
432     CHECK_AND_RETURN_LOG(res, "UpdateExifDataTime: setValue fail!");
433 }
434 
UpdateImageExifDateTime(PixelMap *pixelMap)435 void CommonUtils::UpdateImageExifDateTime(PixelMap *pixelMap)
436 {
437     CHECK_AND_RETURN_LOG(pixelMap != nullptr, "UpdateImageExifDateTime: pixelMap is null!");
438 
439     UpdateExifDataTime(pixelMap->GetExifMetadata());
440 }
441 
UpdateImageExifDateTime(Picture *picture)442 void CommonUtils::UpdateImageExifDateTime(Picture *picture)
443 {
444     CHECK_AND_RETURN_LOG(picture != nullptr, "UpdateImageExifDateTime: picture is null!");
445 
446     UpdateExifDataTime(picture->GetExifMetadata());
447 }
448 
UpdateExifMetadata(const std::shared_ptr<ExifMetadata> &exifMetadata, PixelMap *pixelMap)449 void UpdateExifMetadata(const std::shared_ptr<ExifMetadata> &exifMetadata, PixelMap *pixelMap)
450 {
451     if (exifMetadata == nullptr) {
452         EFFECT_LOGI("UpdateExifMetadata: no exif info.");
453         return;
454     }
455 
456     CHECK_AND_RETURN_LOG(pixelMap != nullptr, "UpdateExifMetadata: pixelMap is null");
457     PrintImageExifInfo(exifMetadata, "UpdateImageExifInfo::update before");
458 
459     // Set Width
460     int32_t width = 0;
461     if (GetImagePropertyInt(exifMetadata, IMAGE_WIDTH, width) == 0 && pixelMap->GetWidth() != width) {
462         exifMetadata->SetValue(IMAGE_WIDTH, std::to_string(pixelMap->GetWidth()));
463     }
464 
465     // Set Length
466     int32_t length = 0;
467     if (GetImagePropertyInt(exifMetadata, IMAGE_LENGTH, width) == 0 && pixelMap->GetHeight() != length) {
468         exifMetadata->SetValue(IMAGE_LENGTH, std::to_string(pixelMap->GetHeight()));
469     }
470 
471     // Set DateTime
472     UpdateExifDataTime(exifMetadata);
473 
474     // Set PixelXDimension
475     int32_t xDimension = 0;
476     if (GetImagePropertyInt(exifMetadata, PIXEL_X_DIMENSION, xDimension) == 0 && pixelMap->GetWidth() != xDimension) {
477         exifMetadata->SetValue(PIXEL_X_DIMENSION, std::to_string(pixelMap->GetWidth()));
478     }
479 
480     // Set PixelYDimension
481     int32_t yDimension = 0;
482     if (GetImagePropertyInt(exifMetadata, PIXEL_Y_DIMENSION, xDimension) == 0 && pixelMap->GetHeight() != yDimension) {
483         exifMetadata->SetValue(PIXEL_Y_DIMENSION, std::to_string(pixelMap->GetHeight()));
484     }
485 
486     PrintImageExifInfo(exifMetadata, "UpdateImageExifInfo::update after");
487 }
488 
UpdateImageExifInfo(PixelMap *pixelMap)489 void CommonUtils::UpdateImageExifInfo(PixelMap *pixelMap)
490 {
491     CHECK_AND_RETURN_LOG(pixelMap != nullptr, "UpdateImageExifInfo: pixelMap is null!");
492 
493     UpdateExifMetadata(pixelMap->GetExifMetadata(), pixelMap);
494 }
495 
UpdateImageExifInfo(Picture *picture)496 void CommonUtils::UpdateImageExifInfo(Picture *picture)
497 {
498     CHECK_AND_RETURN_LOG(picture != nullptr, "UpdateImageExifInfo: picture is null!");
499 
500     UpdateExifMetadata(picture->GetExifMetadata(), picture->GetMainPixel().get());
501 }
502 
ParsePicture(Picture *picture, std::shared_ptr<EffectBuffer> &effectBuffer)503 ErrorCode CommonUtils::ParsePicture(Picture *picture, std::shared_ptr<EffectBuffer> &effectBuffer)
504 {
505     EFFECT_LOGI("CommonUtils::ParsePicture enter.");
506     CHECK_AND_RETURN_RET_LOG(picture != nullptr, ErrorCode::ERR_INPUT_NULL, "ParsePicture: picture is null!");
507 
508     std::shared_ptr<PixelMap> pixelMap = picture->GetMainPixel();
509     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, ErrorCode::ERR_INPUT_NULL, "ParsePicture: main pixel is null!");
510     ErrorCode errorCode = CommonUtils::LockPixelMap(pixelMap.get(), effectBuffer);
511     CHECK_AND_RETURN_RET_LOG(errorCode == ErrorCode::SUCCESS, errorCode,
512         "ParsePicture: parse main pixel fail! errorCode=%{public}d", errorCode);
513 
514     effectBuffer->bufferInfo_->pixelmapType_ = EffectPixelmapType::PRIMARY;
515     effectBuffer->bufferInfo_->bufferType_ = effectBuffer->extraInfo_->bufferType;
516     effectBuffer->bufferInfo_->addr_ = effectBuffer->buffer_;
517     effectBuffer->extraInfo_->dataType = DataType::PICTURE;
518     effectBuffer->extraInfo_->picture = picture;
519 
520     std::shared_ptr<PixelMap> gainMap = picture->GetGainmapPixelMap();
521     if (gainMap == nullptr) {
522         EFFECT_LOGD("CommonUtils::ParsePicture not contain gainmap!");
523         return ErrorCode::SUCCESS;
524     }
525 
526     EFFECT_LOGD("CommonUtils::ParsePicture contain gainmap!");
527     std::shared_ptr<EffectBuffer> gainMapEffectBuffer;
528     errorCode = CommonUtils::LockPixelMap(gainMap.get(), gainMapEffectBuffer);
529     CHECK_AND_RETURN_RET_LOG(errorCode == ErrorCode::SUCCESS, errorCode,
530         "ParsePicture: parse gainmap fail! errorCode=%{public}d", errorCode);
531 
532     gainMapEffectBuffer->bufferInfo_->pixelmapType_ = EffectPixelmapType::GAINMAP;
533     gainMapEffectBuffer->bufferInfo_->bufferType_ = gainMapEffectBuffer->extraInfo_->bufferType;
534     gainMapEffectBuffer->bufferInfo_->addr_ = gainMapEffectBuffer->buffer_;
535 
536     effectBuffer->auxiliaryBufferInfos =
537         std::make_shared<std::unordered_map<EffectPixelmapType, std::shared_ptr<BufferInfo>>>();
538     effectBuffer->auxiliaryBufferInfos->emplace(EffectPixelmapType::GAINMAP, gainMapEffectBuffer->bufferInfo_);
539 
540     return ErrorCode::SUCCESS;
541 }
542 
ModifyPixelMapPropertyInner(std::shared_ptr<MemoryData> &memoryData, PixelMap *pixelMap, AllocatorType &allocatorType, bool isUpdateExif)543 ErrorCode ModifyPixelMapPropertyInner(std::shared_ptr<MemoryData> &memoryData, PixelMap *pixelMap,
544     AllocatorType &allocatorType, bool isUpdateExif)
545 {
546     void *context = nullptr;
547     const MemoryInfo &memoryInfo = memoryData->memoryInfo;
548     ErrorCode res = GetPixelsContext(memoryData, memoryInfo.bufferType, &context);
549     CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "get pixels context fail! res=%{public}d", res);
550 
551     // not need to release the origin buffer in pixelMap, SetPixelsAddr will release it.
552     pixelMap->SetPixelsAddr(memoryData->data, context, memoryInfo.bufferInfo.len_, allocatorType, nullptr);
553 
554     ImageInfo imageInfo;
555     pixelMap->GetImageInfo(imageInfo);
556     imageInfo.size.width = static_cast<int32_t>(memoryInfo.bufferInfo.width_);
557     imageInfo.size.height = static_cast<int32_t>(memoryInfo.bufferInfo.height_);
558     imageInfo.pixelFormat = CommonUtils::SwitchToPixelFormat(memoryInfo.bufferInfo.formatType_);
559     uint32_t result = pixelMap->SetImageInfo(imageInfo, true);
560     EFFECT_LOGI("ModifyPixelMapPropertyInner: SetImageInfo width=%{public}d, height=%{public}d, result: %{public}d",
561         imageInfo.size.width, imageInfo.size.height, result);
562     CHECK_AND_RETURN_RET_LOG(result == 0, ErrorCode::ERR_SET_IMAGE_INFO_FAIL,
563         "ModifyPixelMapPropertyInner: exec SetImageInfo fail! result=%{public}d", result);
564 
565     // update rowStride
566     pixelMap->SetRowStride(memoryInfo.bufferInfo.rowStride_);
567 
568     if (isUpdateExif) {
569         // update exif
570         CommonUtils::UpdateImageExifInfo(pixelMap);
571     }
572 
573     EffectColorSpace colorSpace = memoryInfo.bufferInfo.colorSpace_;
574     if (colorSpace != EffectColorSpace::DEFAULT) {
575         OHOS::ColorManager::ColorSpace grColorSpace(ColorSpaceHelper::ConvertToColorSpaceName(colorSpace));
576         pixelMap->InnerSetColorSpace(grColorSpace);
577     }
578 
579     // update colorspace if need
580     if (memoryInfo.bufferType == BufferType::DMA_BUFFER) {
581         res = ColorSpaceHelper::UpdateMetadata(static_cast<SurfaceBuffer *>(memoryInfo.extra),
582             memoryInfo.bufferInfo.colorSpace_);
583         CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res,
584             "ModifyPixelMapPropertyInner: UpdateMetadata fail! res=%{public}d", res);
585     }
586 
587     return ErrorCode::SUCCESS;
588 }
589 
ModifyPixelMapProperty(PixelMap *pixelMap, const std::shared_ptr<EffectBuffer> &buffer, const std::shared_ptr<EffectMemoryManager> &memoryManager, bool isUpdateExif)590 ErrorCode CommonUtils::ModifyPixelMapProperty(PixelMap *pixelMap, const std::shared_ptr<EffectBuffer> &buffer,
591     const std::shared_ptr<EffectMemoryManager> &memoryManager, bool isUpdateExif)
592 {
593     EFFECT_LOGI("ModifyPixelMapProperty enter!");
594     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, ErrorCode::ERR_INPUT_NULL, "pixel map is null");
595     AllocatorType allocatorType = pixelMap->GetAllocatorType();
596     BufferType bufferType = SwitchToEffectBuffType(allocatorType);
597     EFFECT_LOGD("ModifyPixelMapProperty: allocatorType=%{public}d, bufferType=%{public}d", allocatorType, bufferType);
598     std::shared_ptr<Memory> allocMemory = memoryManager->GetAllocMemoryByAddr(buffer->buffer_);
599     std::shared_ptr<MemoryData> memoryData;
600     if (allocMemory != nullptr && allocMemory->memoryData_->memoryInfo.bufferType == bufferType) {
601         EFFECT_LOGD("ModifyPixelMapProperty reuse allocated memory. addr=%{public}p", buffer->buffer_);
602         allocMemory->memoryData_->memoryInfo.isAutoRelease = false;
603         memoryData = allocMemory->memoryData_;
604     } else {
605         EFFECT_LOGD("ModifyPixelMapProperty alloc memory.");
606         std::unique_ptr<AbsMemory> memory = EffectMemory::CreateMemory(bufferType);
607         CHECK_AND_RETURN_RET_LOG(memory != nullptr, ErrorCode::ERR_CREATE_MEMORY_FAIL,
608             "memory create fail! allocatorType=%{public}d", allocatorType);
609 
610         MemoryInfo memoryInfo = {
611             .isAutoRelease = false,
612             .bufferInfo = *buffer->bufferInfo_,
613             .extra = pixelMap->GetFd()
614         };
615         if (bufferType != BufferType::DMA_BUFFER) {
616             memoryInfo.bufferInfo.len_ = FormatHelper::CalculateSize(buffer->bufferInfo_->width_,
617                 buffer->bufferInfo_->height_, buffer->bufferInfo_->formatType_);
618         }
619         memoryData = memory->Alloc(memoryInfo);
620         CHECK_AND_RETURN_RET_LOG(memoryData != nullptr, ErrorCode::ERR_ALLOC_MEMORY_FAIL, "Alloc fail!");
621         MemcpyHelper::CopyData(buffer.get(), memoryData.get());
622     }
623 
624     return ModifyPixelMapPropertyInner(memoryData, pixelMap, allocatorType, isUpdateExif);
625 }
626 
ModifyPixelMapPropertyForTexture(PixelMap *pixelMap, const std::shared_ptr<EffectBuffer> &buffer, const std::shared_ptr<EffectContext> &context, bool isUpdateExif)627 ErrorCode CommonUtils::ModifyPixelMapPropertyForTexture(PixelMap *pixelMap, const std::shared_ptr<EffectBuffer> &buffer,
628     const std::shared_ptr<EffectContext> &context, bool isUpdateExif)
629 {
630     EFFECT_LOGI("ModifyPixelMapPropertyForTexture enter!");
631     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, ErrorCode::ERR_INPUT_NULL, "pixel map is null");
632     AllocatorType allocatorType = pixelMap->GetAllocatorType();
633     BufferType bufferType = SwitchToEffectBuffType(allocatorType);
634     EFFECT_LOGD("ModifyPixelMapProperty: allocatorType=%{public}d, bufferType=%{public}d", allocatorType, bufferType);
635     std::unique_ptr<AbsMemory> memory = EffectMemory::CreateMemory(bufferType);
636     CHECK_AND_RETURN_RET_LOG(memory != nullptr, ErrorCode::ERR_CREATE_MEMORY_FAIL,
637         "memory create fail! allocatorType=%{public}d", allocatorType);
638 
639     MemoryInfo memoryInfo = {
640         .isAutoRelease = false,
641         .bufferInfo = *buffer->bufferInfo_,
642         .extra = pixelMap->GetFd()
643     };
644     std::shared_ptr<MemoryData> memoryData = memory->Alloc(memoryInfo);
645     CHECK_AND_RETURN_RET_LOG(memoryData != nullptr, ErrorCode::ERR_ALLOC_MEMORY_FAIL, "Alloc fail!");
646     context->renderEnvironment_->ReadPixelsFromTex(buffer->tex, memoryData->data, buffer->bufferInfo_->width_,
647         buffer->bufferInfo_->height_, memoryData->memoryInfo.bufferInfo.rowStride_ / RGBA_BYTES_PER_PIXEL);
648 
649     return ModifyPixelMapPropertyInner(memoryData, pixelMap, allocatorType, isUpdateExif);
650 }
651 } // namespace Effect
652 } // namespace Media
653 } // namespace OHOS