/* * Copyright (C) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "common_utils.h" #include <charconv> #include "effect_log.h" #include "effect_buffer.h" #include "image_source.h" #include "uri.h" #include "string_helper.h" #include "memcpy_helper.h" #include "colorspace_helper.h" #include "render_environment.h" #include "format_helper.h" #include "exif_metadata.h" namespace OHOS { namespace Media { namespace Effect { namespace { const std::string IMAGE_LENGTH = "ImageLength"; const std::string IMAGE_WIDTH = "ImageWidth"; const std::string DATE_TIME = "DateTime"; const std::string PIXEL_X_DIMENSION = "PixelXDimension"; const std::string PIXEL_Y_DIMENSION = "PixelYDimension"; const int32_t TIME_MAX = 64; } using namespace OHOS::ColorManager; using namespace OHOS::HDI::Display::Graphic::Common::V1_0; const std::unordered_map<PixelFormat, IEffectFormat> CommonUtils::pixelFmtToEffectFmt_ = { { PixelFormat::RGBA_8888, IEffectFormat::RGBA8888 }, { PixelFormat::NV21, IEffectFormat::YUVNV21 }, { PixelFormat::NV12, IEffectFormat::YUVNV12 }, { PixelFormat::RGBA_1010102, IEffectFormat::RGBA_1010102 }, }; const std::unordered_map<GraphicPixelFormat, IEffectFormat> CommonUtils::surfaceBufferFmtToEffectFmt_ = { { GraphicPixelFormat::GRAPHIC_PIXEL_FMT_RGBA_8888, IEffectFormat::RGBA8888}, { GraphicPixelFormat::GRAPHIC_PIXEL_FMT_YCBCR_420_SP, IEffectFormat::YUVNV12 }, { GraphicPixelFormat::GRAPHIC_PIXEL_FMT_YCRCB_420_SP, IEffectFormat::YUVNV21 }, { GraphicPixelFormat::GRAPHIC_PIXEL_FMT_RGBA_1010102, IEffectFormat::RGBA_1010102 }, { GraphicPixelFormat::GRAPHIC_PIXEL_FMT_YCBCR_P010, IEffectFormat::YCBCR_P010 }, { GraphicPixelFormat::GRAPHIC_PIXEL_FMT_YCRCB_P010, IEffectFormat::YCRCB_P010 }, }; const std::unordered_map<AllocatorType, BufferType> CommonUtils::allocatorTypeToEffectBuffType_ = { { AllocatorType::HEAP_ALLOC, BufferType::HEAP_MEMORY }, { AllocatorType::DMA_ALLOC, BufferType::DMA_BUFFER }, { AllocatorType::SHARE_MEM_ALLOC, BufferType::SHARED_MEMORY }, }; template <class ValueType> ErrorCode ParseJson(const std::string &key, Plugin::Any &any, EffectJsonPtr &json) { auto result = Plugin::AnyCast<ValueType>(&any); if (result == nullptr) { return ErrorCode::ERR_ANY_CAST_TYPE_NOT_MATCH; } json->Put(key, *result); return ErrorCode::SUCCESS; } ErrorCode CommonUtils::LockPixelMap(PixelMap *pixelMap, std::shared_ptr<EffectBuffer> &effectBuffer) { CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, ErrorCode::ERR_INPUT_NULL, "pixelMap is null!"); ColorSpaceName colorSpaceName = pixelMap->InnerGetGrColorSpacePtr() == nullptr ? ColorSpaceName::NONE : pixelMap->InnerGetGrColorSpacePtr()->GetColorSpaceName(); EFFECT_LOGD("pixelMapInfos: width=%{public}d, height=%{public}d, formatType=%{public}d " \ "rowStride=%{public}d, byteCount=%{public}d, addr=%{private}p, colorSpaceName=%{public}d", pixelMap->GetWidth(), pixelMap->GetHeight(), pixelMap->GetPixelFormat(), pixelMap->GetRowStride(), pixelMap->GetByteCount(), pixelMap->GetPixels(), colorSpaceName); IEffectFormat formatType = SwitchToEffectFormat(pixelMap->GetPixelFormat()); if (formatType == IEffectFormat::DEFAULT) { EFFECT_LOGE("pixelFormat not support! pixelFormat=%{public}d", pixelMap->GetPixelFormat()); return ErrorCode::ERR_UNSUPPORTED_PIXEL_FORMAT; } std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>(); bufferInfo->width_ = static_cast<uint32_t>(pixelMap->GetWidth()); bufferInfo->height_ = static_cast<uint32_t>(pixelMap->GetHeight()); bufferInfo->rowStride_ = static_cast<uint32_t>(pixelMap->GetRowStride()); bufferInfo->len_ = FormatHelper::CalculateSize(bufferInfo->width_, bufferInfo->height_, formatType); bufferInfo->formatType_ = formatType; bufferInfo->colorSpace_ = ColorSpaceHelper::ConvertToEffectColorSpace(colorSpaceName); uint8_t *pixels = const_cast<uint8_t *>(pixelMap->GetPixels()); void *srcData = static_cast<void *>(pixels); CHECK_AND_RETURN_RET_LOG(srcData != nullptr, ErrorCode::ERR_PIXELMAP_ACCESSPIXELS_FAIL, "fail exec GetPixels!"); EFFECT_LOGI("pixelMap bufferInfos: width=%{public}d, height=%{public}d, formatType=%{public}d, " \ "rowStride_=%{public}d, len=%{public}d, colorspace=%{public}d, addr=%{private}p", bufferInfo->width_, bufferInfo->height_, bufferInfo->formatType_, bufferInfo->rowStride_, bufferInfo->len_, bufferInfo->colorSpace_, pixels); std::shared_ptr<ExtraInfo> extraInfo = std::make_unique<ExtraInfo>(); extraInfo->dataType = DataType::PIXEL_MAP; extraInfo->bufferType = SwitchToEffectBuffType(pixelMap->GetAllocatorType()); extraInfo->pixelMap = pixelMap; extraInfo->surfaceBuffer = nullptr; if (extraInfo->bufferType == BufferType::DMA_BUFFER && pixelMap->GetFd() != nullptr) { extraInfo->surfaceBuffer = reinterpret_cast<SurfaceBuffer*> (pixelMap->GetFd()); } if (extraInfo->bufferType == BufferType::SHARED_MEMORY && pixelMap->GetFd() != nullptr) { extraInfo->fd = reinterpret_cast<int *>(pixelMap->GetFd()); } EFFECT_LOGI("pixelMap extraInfos: dataType=%{public}d, bufferType=%{public}d", extraInfo->dataType, extraInfo->bufferType); if (extraInfo->surfaceBuffer != nullptr) { SurfaceBuffer *sb = extraInfo->surfaceBuffer; EFFECT_LOGD("pixelMap surfaceBufferInfo: width=%{public}d, height=%{public}d, format=%{public}d, " "rowStride=%{public}d, size=%{public}d, addr=%{private}p", sb->GetWidth(), sb->GetHeight(), sb->GetFormat(), sb->GetStride(), sb->GetSize(), sb->GetVirAddr()); } effectBuffer = std::make_unique<EffectBuffer>(bufferInfo, srcData, extraInfo); return ErrorCode::SUCCESS; } ErrorCode CommonUtils::ParseNativeWindowData(std::shared_ptr<EffectBuffer> &effectBuffer, const DataType &dataType) { std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>(); bufferInfo->width_ = 0; bufferInfo->height_ = 0; bufferInfo->rowStride_ = 0; bufferInfo->len_ = 0; bufferInfo->formatType_ = IEffectFormat::DEFAULT; std::shared_ptr<ExtraInfo> extraInfo = std::make_unique<ExtraInfo>(); extraInfo->dataType = dataType; extraInfo->bufferType = BufferType::DMA_BUFFER; extraInfo->pixelMap = nullptr; extraInfo->surfaceBuffer = nullptr; effectBuffer = std::make_unique<EffectBuffer>(bufferInfo, nullptr, extraInfo); return ErrorCode::SUCCESS; } ErrorCode CommonUtils::ParseSurfaceData(OHOS::SurfaceBuffer *surfaceBuffer, std::shared_ptr<EffectBuffer> &effectBuffer, const DataType &dataType, int64_t timestamp) { CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, ErrorCode::ERR_INPUT_NULL, "surfaceBuffer is null!"); std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>(); bufferInfo->width_ = static_cast<uint32_t>(surfaceBuffer->GetWidth()); bufferInfo->height_ = static_cast<uint32_t>(surfaceBuffer->GetHeight()); bufferInfo->rowStride_ = static_cast<uint32_t>(surfaceBuffer->GetStride()); bufferInfo->len_ = surfaceBuffer->GetSize(); bufferInfo->formatType_ = SwitchToEffectFormat((GraphicPixelFormat)surfaceBuffer->GetFormat()); CM_ColorSpaceType colorSpaceType = CM_ColorSpaceType::CM_COLORSPACE_NONE; ColorSpaceHelper::GetSurfaceBufferColorSpaceType(surfaceBuffer, colorSpaceType); bufferInfo->colorSpace_ = ColorSpaceHelper::ConvertToEffectColorSpace(colorSpaceType); std::shared_ptr<ExtraInfo> extraInfo = std::make_unique<ExtraInfo>(); extraInfo->dataType = dataType; extraInfo->bufferType = BufferType::DMA_BUFFER; extraInfo->pixelMap = nullptr; extraInfo->surfaceBuffer = surfaceBuffer; extraInfo->timestamp = timestamp; effectBuffer = std::make_unique<EffectBuffer>(bufferInfo, surfaceBuffer->GetVirAddr(), extraInfo); EFFECT_LOGI("surfaceBuffer width=%{public}d, height=%{public}d, stride=%{public}d, format=%{public}d, " "size=%{public}d, usage = %{public}llu, addr=%{private}p, colorSpace=%{public}d", surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight(), surfaceBuffer->GetStride(), surfaceBuffer->GetFormat(), surfaceBuffer->GetSize(), static_cast<unsigned long long>(surfaceBuffer->GetUsage()), surfaceBuffer->GetVirAddr(), colorSpaceType); return ErrorCode::SUCCESS; } std::string CommonUtils::UrlToPath(const std::string &url) { OHOS::Uri uri = OHOS::Uri(url); return uri.GetPath(); } ErrorCode CommonUtils::ParseUri(std::string &uri, std::shared_ptr<EffectBuffer> &effectBuffer, bool isOutputData) { if (isOutputData) { std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>(); std::shared_ptr<ExtraInfo> extraInfo = std::make_unique<ExtraInfo>(); extraInfo->dataType = DataType::URI; extraInfo->uri = std::move(uri); effectBuffer = std::make_unique<EffectBuffer>(bufferInfo, nullptr, extraInfo); return ErrorCode::SUCCESS; } auto path = UrlToPath(uri); ErrorCode res = ParsePath(path, effectBuffer, isOutputData); CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "ParseUri: path name fail! uri=%{public}s, res=%{public}d", uri.c_str(), res); CHECK_AND_RETURN_RET_LOG(effectBuffer->extraInfo_ != nullptr, ErrorCode::ERR_EXTRA_INFO_NULL, "ParseUri: extra info is null! uri=%{public}s", uri.c_str()); effectBuffer->extraInfo_->dataType = DataType::URI; effectBuffer->extraInfo_->uri = std::move(uri); return ErrorCode::SUCCESS; } ErrorCode CommonUtils::ParsePath(std::string &path, std::shared_ptr<EffectBuffer> &effectBuffer, bool isOutputData) { if (isOutputData) { std::shared_ptr<BufferInfo> bufferInfo = std::make_unique<BufferInfo>(); std::shared_ptr<ExtraInfo> extraInfo = std::make_unique<ExtraInfo>(); extraInfo->dataType = DataType::PATH; extraInfo->path = std::move(path); effectBuffer = std::make_unique<EffectBuffer>(bufferInfo, nullptr, extraInfo); return ErrorCode::SUCCESS; } SourceOptions opts; uint32_t errorCode = 0; std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(path, opts, errorCode); CHECK_AND_RETURN_RET_LOG(imageSource != nullptr, ErrorCode::ERR_CREATE_IMAGESOURCE_FAIL, "ImageSource::CreateImageSource fail! path=%{public}s, errorCode=%{public}d", path.c_str(), errorCode); DecodeOptions options; options.desiredDynamicRange = DecodeDynamicRange::AUTO; std::unique_ptr<PixelMap> pixelMap = imageSource->CreatePixelMap(options, errorCode); CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, ErrorCode::ERR_CREATE_PIXELMAP_FAIL, "CreatePixelMap fail! path=%{public}s, errorCode=%{public}d", path.c_str(), errorCode); ErrorCode res = LockPixelMap(pixelMap.get(), effectBuffer); CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "ParsePath: lock pixel map fail! path=%{public}s, res=%{public}d", path.c_str(), res); CHECK_AND_RETURN_RET_LOG(effectBuffer->extraInfo_ != nullptr, ErrorCode::ERR_EXTRA_INFO_NULL, "ParsePath: extra info is null! uri=%{public}s", path.c_str()); effectBuffer->extraInfo_->dataType = DataType::PATH; effectBuffer->extraInfo_->path = std::move(path); effectBuffer->extraInfo_->pixelMap = nullptr; effectBuffer->extraInfo_->innerPixelMap = std::move(pixelMap); return ErrorCode::SUCCESS; } IEffectFormat CommonUtils::SwitchToEffectFormat(GraphicPixelFormat pixelFormat) { IEffectFormat formatType = IEffectFormat::DEFAULT; auto itr = surfaceBufferFmtToEffectFmt_.find(pixelFormat); if (itr != surfaceBufferFmtToEffectFmt_.end()) { formatType = itr->second; } return formatType; } IEffectFormat CommonUtils::SwitchToEffectFormat(PixelFormat pixelFormat) { IEffectFormat formatType = IEffectFormat::DEFAULT; auto itr = pixelFmtToEffectFmt_.find(pixelFormat); if (itr != pixelFmtToEffectFmt_.end()) { formatType = itr->second; } return formatType; } GraphicPixelFormat CommonUtils::SwitchToGraphicPixelFormat(IEffectFormat formatType) { GraphicPixelFormat pixelFormat = GraphicPixelFormat::GRAPHIC_PIXEL_FMT_BUTT; for (const auto &itr : surfaceBufferFmtToEffectFmt_) { if (itr.second == formatType) { pixelFormat = itr.first; break; } } return pixelFormat; } PixelFormat CommonUtils::SwitchToPixelFormat(IEffectFormat formatType) { PixelFormat pixelFormat = PixelFormat::UNKNOWN; for (const auto &itr : pixelFmtToEffectFmt_) { if (itr.second == formatType) { pixelFormat = itr.first; break; } } return pixelFormat; } BufferType CommonUtils::SwitchToEffectBuffType(AllocatorType allocatorType) { BufferType bufferType = BufferType::DEFAULT; auto itr = allocatorTypeToEffectBuffType_.find(allocatorType); if (itr != allocatorTypeToEffectBuffType_.end()) { bufferType = itr->second; } return bufferType; } void CommonUtils::UnlockPixelMap(const PixelMap *pixelMap) { EFFECT_LOGI("UnlockPixelMap!"); } ErrorCode CommonUtils::ParseAnyAndAddToJson(const std::string &key, Plugin::Any &any, EffectJsonPtr &result) { CHECK_AND_RETURN_RET(ParseJson<float>(key, any, result) != ErrorCode::SUCCESS, ErrorCode::SUCCESS); CHECK_AND_RETURN_RET(ParseJson<int32_t>(key, any, result) != ErrorCode::SUCCESS, ErrorCode::SUCCESS); CHECK_AND_RETURN_RET(ParseJson<uint32_t>(key, any, result) != ErrorCode::SUCCESS, ErrorCode::SUCCESS); #ifndef HST_ANY_WITH_NO_RTTI EFFECT_LOGE("inner any type not support switch to json! type:%{public}s", any.Type().name()); #else EFFECT_LOGE("inner any type not support switch to json! type:%{public}s", std::string(any.TypeName()).c_str()); #endif return ErrorCode::ERR_ANY_CAST_TYPE_NOT_MATCH; } bool CommonUtils::EndsWithJPG(const std::string &input) { return StringHelp::EndsWithIgnoreCase(input, "jpg") || StringHelp::EndsWithIgnoreCase(input, "jpeg"); } ErrorCode GetPixelsContext(std::shared_ptr<MemoryData> &memoryData, BufferType bufferType, void **context) { switch (bufferType) { case BufferType::HEAP_MEMORY: *context = nullptr; break; case BufferType::DMA_BUFFER: { void *extra = memoryData->memoryInfo.extra; auto surfaceBuffer = reinterpret_cast<SurfaceBuffer *>(extra); CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, ErrorCode::ERR_INVALID_SURFACE_BUFFER, "DMA_BUFFER: extra info error!"); *context = surfaceBuffer; break; } case BufferType::SHARED_MEMORY: { void *extra = memoryData->memoryInfo.extra; auto fd = static_cast<int *>(extra); CHECK_AND_RETURN_RET_LOG(fd != nullptr, ErrorCode::ERR_INVALID_FD, "SHARED_MEMORY: extra info error!"); *context = fd; break; } default: EFFECT_LOGE("bufferType not support! bufferType=%{public}d", bufferType); return ErrorCode::ERR_UNSUPPORTED_BUFFER_TYPE; } return ErrorCode::SUCCESS; } int32_t GetImagePropertyInt(const std::shared_ptr<ExifMetadata> &exifMetadata, const std::string &key, int32_t &value) { std::string strValue; int ret = exifMetadata->GetValue(key, strValue); if (ret != 0) { return ret; } std::from_chars_result res = std::from_chars(strValue.data(), strValue.data() + strValue.size(), value); if (res.ec != std::errc()) { return static_cast<int32_t>(ErrorCode::ERR_IMAGE_DATA); } return 0; } void PrintImageExifInfo(const std::shared_ptr<ExifMetadata> &exifMetadata, const std::string &tag) { if (exifMetadata == nullptr) { return; } int32_t width = 0; GetImagePropertyInt(exifMetadata, IMAGE_WIDTH, width); int32_t length = 0; GetImagePropertyInt(exifMetadata, IMAGE_LENGTH, length); std::string dateTime; exifMetadata->GetValue(DATE_TIME, dateTime); int32_t xDimension = 0; GetImagePropertyInt(exifMetadata, PIXEL_X_DIMENSION, xDimension); int32_t yDimension = 0; GetImagePropertyInt(exifMetadata, PIXEL_Y_DIMENSION, yDimension); EFFECT_LOGD("%{public}s: width=%{public}d, length=%{public}d, dateTime=%{public}s, xDimension=%{public}d, " "yDimension=%{public}d", tag.c_str(), width, length, dateTime.c_str(), xDimension, yDimension); } void UpdateExifDataTime(const std::shared_ptr<ExifMetadata> &exifMetadata) { CHECK_AND_RETURN_LOG(exifMetadata != nullptr, "UpdateExifDataTime: exifMetadata is null!"); std::string dateTime; if (exifMetadata->GetValue(DATE_TIME, dateTime) != 0 || dateTime.empty()) { return; } time_t now = time(nullptr); CHECK_AND_RETURN_LOG(now > 0, "UpdateExifDateTime: time fail!"); struct tm *locTime = localtime(&now); CHECK_AND_RETURN_LOG(locTime != nullptr, "UpdateExifDateTime: localtime fail!"); char tempTime[TIME_MAX]; auto size = strftime(tempTime, sizeof(tempTime), "%Y:%m:%d %H:%M:%S", locTime); CHECK_AND_RETURN_LOG(size > 0, "UpdateExifDateTime: strftime fail!"); std::string currentTime = std::string(tempTime, size); bool res = exifMetadata->SetValue(DATE_TIME, currentTime); CHECK_AND_RETURN_LOG(res, "UpdateExifDataTime: setValue fail!"); } void CommonUtils::UpdateImageExifDateTime(PixelMap *pixelMap) { CHECK_AND_RETURN_LOG(pixelMap != nullptr, "UpdateImageExifDateTime: pixelMap is null!"); UpdateExifDataTime(pixelMap->GetExifMetadata()); } void CommonUtils::UpdateImageExifDateTime(Picture *picture) { CHECK_AND_RETURN_LOG(picture != nullptr, "UpdateImageExifDateTime: picture is null!"); UpdateExifDataTime(picture->GetExifMetadata()); } void UpdateExifMetadata(const std::shared_ptr<ExifMetadata> &exifMetadata, PixelMap *pixelMap) { if (exifMetadata == nullptr) { EFFECT_LOGI("UpdateExifMetadata: no exif info."); return; } CHECK_AND_RETURN_LOG(pixelMap != nullptr, "UpdateExifMetadata: pixelMap is null"); PrintImageExifInfo(exifMetadata, "UpdateImageExifInfo::update before"); // Set Width int32_t width = 0; if (GetImagePropertyInt(exifMetadata, IMAGE_WIDTH, width) == 0 && pixelMap->GetWidth() != width) { exifMetadata->SetValue(IMAGE_WIDTH, std::to_string(pixelMap->GetWidth())); } // Set Length int32_t length = 0; if (GetImagePropertyInt(exifMetadata, IMAGE_LENGTH, width) == 0 && pixelMap->GetHeight() != length) { exifMetadata->SetValue(IMAGE_LENGTH, std::to_string(pixelMap->GetHeight())); } // Set DateTime UpdateExifDataTime(exifMetadata); // Set PixelXDimension int32_t xDimension = 0; if (GetImagePropertyInt(exifMetadata, PIXEL_X_DIMENSION, xDimension) == 0 && pixelMap->GetWidth() != xDimension) { exifMetadata->SetValue(PIXEL_X_DIMENSION, std::to_string(pixelMap->GetWidth())); } // Set PixelYDimension int32_t yDimension = 0; if (GetImagePropertyInt(exifMetadata, PIXEL_Y_DIMENSION, xDimension) == 0 && pixelMap->GetHeight() != yDimension) { exifMetadata->SetValue(PIXEL_Y_DIMENSION, std::to_string(pixelMap->GetHeight())); } PrintImageExifInfo(exifMetadata, "UpdateImageExifInfo::update after"); } void CommonUtils::UpdateImageExifInfo(PixelMap *pixelMap) { CHECK_AND_RETURN_LOG(pixelMap != nullptr, "UpdateImageExifInfo: pixelMap is null!"); UpdateExifMetadata(pixelMap->GetExifMetadata(), pixelMap); } void CommonUtils::UpdateImageExifInfo(Picture *picture) { CHECK_AND_RETURN_LOG(picture != nullptr, "UpdateImageExifInfo: picture is null!"); UpdateExifMetadata(picture->GetExifMetadata(), picture->GetMainPixel().get()); } ErrorCode CommonUtils::ParsePicture(Picture *picture, std::shared_ptr<EffectBuffer> &effectBuffer) { EFFECT_LOGI("CommonUtils::ParsePicture enter."); CHECK_AND_RETURN_RET_LOG(picture != nullptr, ErrorCode::ERR_INPUT_NULL, "ParsePicture: picture is null!"); std::shared_ptr<PixelMap> pixelMap = picture->GetMainPixel(); CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, ErrorCode::ERR_INPUT_NULL, "ParsePicture: main pixel is null!"); ErrorCode errorCode = CommonUtils::LockPixelMap(pixelMap.get(), effectBuffer); CHECK_AND_RETURN_RET_LOG(errorCode == ErrorCode::SUCCESS, errorCode, "ParsePicture: parse main pixel fail! errorCode=%{public}d", errorCode); effectBuffer->bufferInfo_->pixelmapType_ = EffectPixelmapType::PRIMARY; effectBuffer->bufferInfo_->bufferType_ = effectBuffer->extraInfo_->bufferType; effectBuffer->bufferInfo_->addr_ = effectBuffer->buffer_; effectBuffer->extraInfo_->dataType = DataType::PICTURE; effectBuffer->extraInfo_->picture = picture; std::shared_ptr<PixelMap> gainMap = picture->GetGainmapPixelMap(); if (gainMap == nullptr) { EFFECT_LOGD("CommonUtils::ParsePicture not contain gainmap!"); return ErrorCode::SUCCESS; } EFFECT_LOGD("CommonUtils::ParsePicture contain gainmap!"); std::shared_ptr<EffectBuffer> gainMapEffectBuffer; errorCode = CommonUtils::LockPixelMap(gainMap.get(), gainMapEffectBuffer); CHECK_AND_RETURN_RET_LOG(errorCode == ErrorCode::SUCCESS, errorCode, "ParsePicture: parse gainmap fail! errorCode=%{public}d", errorCode); gainMapEffectBuffer->bufferInfo_->pixelmapType_ = EffectPixelmapType::GAINMAP; gainMapEffectBuffer->bufferInfo_->bufferType_ = gainMapEffectBuffer->extraInfo_->bufferType; gainMapEffectBuffer->bufferInfo_->addr_ = gainMapEffectBuffer->buffer_; effectBuffer->auxiliaryBufferInfos = std::make_shared<std::unordered_map<EffectPixelmapType, std::shared_ptr<BufferInfo>>>(); effectBuffer->auxiliaryBufferInfos->emplace(EffectPixelmapType::GAINMAP, gainMapEffectBuffer->bufferInfo_); return ErrorCode::SUCCESS; } ErrorCode ModifyPixelMapPropertyInner(std::shared_ptr<MemoryData> &memoryData, PixelMap *pixelMap, AllocatorType &allocatorType, bool isUpdateExif) { void *context = nullptr; const MemoryInfo &memoryInfo = memoryData->memoryInfo; ErrorCode res = GetPixelsContext(memoryData, memoryInfo.bufferType, &context); CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "get pixels context fail! res=%{public}d", res); // not need to release the origin buffer in pixelMap, SetPixelsAddr will release it. pixelMap->SetPixelsAddr(memoryData->data, context, memoryInfo.bufferInfo.len_, allocatorType, nullptr); ImageInfo imageInfo; pixelMap->GetImageInfo(imageInfo); imageInfo.size.width = static_cast<int32_t>(memoryInfo.bufferInfo.width_); imageInfo.size.height = static_cast<int32_t>(memoryInfo.bufferInfo.height_); imageInfo.pixelFormat = CommonUtils::SwitchToPixelFormat(memoryInfo.bufferInfo.formatType_); uint32_t result = pixelMap->SetImageInfo(imageInfo, true); EFFECT_LOGI("ModifyPixelMapPropertyInner: SetImageInfo width=%{public}d, height=%{public}d, result: %{public}d", imageInfo.size.width, imageInfo.size.height, result); CHECK_AND_RETURN_RET_LOG(result == 0, ErrorCode::ERR_SET_IMAGE_INFO_FAIL, "ModifyPixelMapPropertyInner: exec SetImageInfo fail! result=%{public}d", result); // update rowStride pixelMap->SetRowStride(memoryInfo.bufferInfo.rowStride_); if (isUpdateExif) { // update exif CommonUtils::UpdateImageExifInfo(pixelMap); } EffectColorSpace colorSpace = memoryInfo.bufferInfo.colorSpace_; if (colorSpace != EffectColorSpace::DEFAULT) { OHOS::ColorManager::ColorSpace grColorSpace(ColorSpaceHelper::ConvertToColorSpaceName(colorSpace)); pixelMap->InnerSetColorSpace(grColorSpace); } // update colorspace if need if (memoryInfo.bufferType == BufferType::DMA_BUFFER) { res = ColorSpaceHelper::UpdateMetadata(static_cast<SurfaceBuffer *>(memoryInfo.extra), memoryInfo.bufferInfo.colorSpace_); CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "ModifyPixelMapPropertyInner: UpdateMetadata fail! res=%{public}d", res); } return ErrorCode::SUCCESS; } ErrorCode CommonUtils::ModifyPixelMapProperty(PixelMap *pixelMap, const std::shared_ptr<EffectBuffer> &buffer, const std::shared_ptr<EffectMemoryManager> &memoryManager, bool isUpdateExif) { EFFECT_LOGI("ModifyPixelMapProperty enter!"); CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, ErrorCode::ERR_INPUT_NULL, "pixel map is null"); AllocatorType allocatorType = pixelMap->GetAllocatorType(); BufferType bufferType = SwitchToEffectBuffType(allocatorType); EFFECT_LOGD("ModifyPixelMapProperty: allocatorType=%{public}d, bufferType=%{public}d", allocatorType, bufferType); std::shared_ptr<Memory> allocMemory = memoryManager->GetAllocMemoryByAddr(buffer->buffer_); std::shared_ptr<MemoryData> memoryData; if (allocMemory != nullptr && allocMemory->memoryData_->memoryInfo.bufferType == bufferType) { EFFECT_LOGD("ModifyPixelMapProperty reuse allocated memory. addr=%{public}p", buffer->buffer_); allocMemory->memoryData_->memoryInfo.isAutoRelease = false; memoryData = allocMemory->memoryData_; } else { EFFECT_LOGD("ModifyPixelMapProperty alloc memory."); std::unique_ptr<AbsMemory> memory = EffectMemory::CreateMemory(bufferType); CHECK_AND_RETURN_RET_LOG(memory != nullptr, ErrorCode::ERR_CREATE_MEMORY_FAIL, "memory create fail! allocatorType=%{public}d", allocatorType); MemoryInfo memoryInfo = { .isAutoRelease = false, .bufferInfo = *buffer->bufferInfo_, .extra = pixelMap->GetFd() }; if (bufferType != BufferType::DMA_BUFFER) { memoryInfo.bufferInfo.len_ = FormatHelper::CalculateSize(buffer->bufferInfo_->width_, buffer->bufferInfo_->height_, buffer->bufferInfo_->formatType_); } memoryData = memory->Alloc(memoryInfo); CHECK_AND_RETURN_RET_LOG(memoryData != nullptr, ErrorCode::ERR_ALLOC_MEMORY_FAIL, "Alloc fail!"); MemcpyHelper::CopyData(buffer.get(), memoryData.get()); } return ModifyPixelMapPropertyInner(memoryData, pixelMap, allocatorType, isUpdateExif); } ErrorCode CommonUtils::ModifyPixelMapPropertyForTexture(PixelMap *pixelMap, const std::shared_ptr<EffectBuffer> &buffer, const std::shared_ptr<EffectContext> &context, bool isUpdateExif) { EFFECT_LOGI("ModifyPixelMapPropertyForTexture enter!"); CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, ErrorCode::ERR_INPUT_NULL, "pixel map is null"); AllocatorType allocatorType = pixelMap->GetAllocatorType(); BufferType bufferType = SwitchToEffectBuffType(allocatorType); EFFECT_LOGD("ModifyPixelMapProperty: allocatorType=%{public}d, bufferType=%{public}d", allocatorType, bufferType); std::unique_ptr<AbsMemory> memory = EffectMemory::CreateMemory(bufferType); CHECK_AND_RETURN_RET_LOG(memory != nullptr, ErrorCode::ERR_CREATE_MEMORY_FAIL, "memory create fail! allocatorType=%{public}d", allocatorType); MemoryInfo memoryInfo = { .isAutoRelease = false, .bufferInfo = *buffer->bufferInfo_, .extra = pixelMap->GetFd() }; std::shared_ptr<MemoryData> memoryData = memory->Alloc(memoryInfo); CHECK_AND_RETURN_RET_LOG(memoryData != nullptr, ErrorCode::ERR_ALLOC_MEMORY_FAIL, "Alloc fail!"); context->renderEnvironment_->ReadPixelsFromTex(buffer->tex, memoryData->data, buffer->bufferInfo_->width_, buffer->bufferInfo_->height_, memoryData->memoryInfo.bufferInfo.rowStride_ / RGBA_BYTES_PER_PIXEL); return ModifyPixelMapPropertyInner(memoryData, pixelMap, allocatorType, isUpdateExif); } } // namespace Effect } // namespace Media } // namespace OHOS