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 "native_common_utils.h"
17 
18 #include <set>
19 #include <algorithm>
20 
21 #include "effect_log.h"
22 #include "efilter_factory.h"
23 #include "native_effect_base.h"
24 #include "pixelmap_native_impl.h"
25 #include "event_report.h"
26 
27 namespace OHOS {
28 namespace Media {
29 namespace Effect {
30 static const std::map<IEffectFormat, ImageEffect_Format> FORMAT_TABLE = {
31     { IEffectFormat::RGBA8888, ImageEffect_Format::EFFECT_PIXEL_FORMAT_RGBA8888 },
32     { IEffectFormat::YUVNV12, ImageEffect_Format::EFFECT_PIXEL_FORMAT_NV12 },
33     { IEffectFormat::YUVNV21, ImageEffect_Format::EFFECT_PIXEL_FORMAT_NV21 },
34     { IEffectFormat::RGBA_1010102, ImageEffect_Format::EFFECT_PIXEL_FORMAT_RGBA1010102 },
35     { IEffectFormat::YCBCR_P010, ImageEffect_Format::EFFECT_PIXEL_FORMAT_YCBCR_P010 },
36     { IEffectFormat::YCRCB_P010, ImageEffect_Format::EFFECT_PIXEL_FORMAT_YCRCB_P010 }
37 };
38 
39 static const std::unordered_map<std::string, std::unordered_map<std::string, uint32_t>> LOOK_UP_CAPABILITY = {
40     { "Format",
41         {
42             { "default", static_cast<uint32_t>(IEffectFormat::DEFAULT) },
43             { "rgba_8888", static_cast<uint32_t>(IEffectFormat::RGBA8888) },
44             { "nv21", static_cast<uint32_t>(IEffectFormat::YUVNV21) },
45             { "nv12", static_cast<uint32_t>(IEffectFormat::YUVNV12) },
46         }
47     },
48 };
49 
50 static const std::map<IPType, ImageEffect_BufferType> IPTYPE_TABLE = {
51     { IPType::CPU, ImageEffect_BufferType::EFFECT_BUFFER_TYPE_PIXEL },
52     { IPType::GPU, ImageEffect_BufferType::EFFECT_BUFFER_TYPE_TEXTURE },
53 };
54 
55 static const std::map<ErrorCode, ImageEffect_ErrorCode> ERRORCODE_TABLE = {
56     { ErrorCode::ERR_ALLOC_MEMORY_FAIL, ImageEffect_ErrorCode::EFFECT_ALLOCATE_MEMORY_FAILED },
57     { ErrorCode::ERR_NOT_SUPPORT_DIFF_DATATYPE, ImageEffect_ErrorCode::EFFECT_INPUT_OUTPUT_NOT_MATCH },
58     { ErrorCode::ERR_UNSUPPORTED_FORMAT_TYPE, ImageEffect_ErrorCode ::EFFECT_INPUT_OUTPUT_NOT_SUPPORTED },
59     { ErrorCode::ERR_NOT_SUPPORT_INPUT_OUTPUT_COLORSPACE, ImageEffect_ErrorCode::EFFECT_COLOR_SPACE_NOT_MATCH },
60 };
61 
62 template <class ValueType>
AnyCastOHAny(const Plugin::Any & any,ImageEffect_DataType & ohDataType,ImageEffect_DataType ohDataTypeValue,ValueType & value)63 ErrorCode AnyCastOHAny(const Plugin::Any &any, ImageEffect_DataType &ohDataType, ImageEffect_DataType ohDataTypeValue,
64     ValueType &value)
65 {
66     auto result = Plugin::AnyCast<ValueType>(&any);
67     if (result == nullptr) {
68         return ErrorCode::ERR_ANY_CAST_TYPE_NOT_MATCH;
69     }
70     ohDataType = ohDataTypeValue;
71     value = *result;
72     return ErrorCode::SUCCESS;
73 }
74 
ParseOHAny(const ImageEffect_Any * value,Plugin::Any & any)75 ErrorCode NativeCommonUtils::ParseOHAny(const ImageEffect_Any *value, Plugin::Any &any)
76 {
77     switch (value->dataType) {
78         case ImageEffect_DataType::EFFECT_DATA_TYPE_INT32:
79             any = value->dataValue.int32Value;
80             break;
81         case ImageEffect_DataType::EFFECT_DATA_TYPE_FLOAT:
82             any = value->dataValue.floatValue;
83             break;
84         case ImageEffect_DataType::EFFECT_DATA_TYPE_DOUBLE:
85             any = value->dataValue.doubleValue;
86             break;
87         case ImageEffect_DataType::EFFECT_DATA_TYPE_CHAR:
88             any = value->dataValue.charValue;
89             break;
90         case ImageEffect_DataType::EFFECT_DATA_TYPE_LONG:
91             any = value->dataValue.longValue;
92             break;
93         case ImageEffect_DataType::EFFECT_DATA_TYPE_BOOL:
94             any = value->dataValue.boolValue;
95             break;
96         case ImageEffect_DataType::EFFECT_DATA_TYPE_PTR:
97             any = value->dataValue.ptrValue;
98             break;
99         default:
100             EFFECT_LOGE("input any data type not support! dataType=%{public}d", value->dataType);
101             return ErrorCode::ERR_UNSUPPORTED_INPUT_ANYTYPE;
102     }
103     return ErrorCode::SUCCESS;
104 }
105 
SwitchToOHAny(const Plugin::Any & any,ImageEffect_Any * value)106 ErrorCode NativeCommonUtils::SwitchToOHAny(const Plugin::Any &any, ImageEffect_Any *value)
107 {
108     CHECK_AND_RETURN_RET(AnyCastOHAny(any, value->dataType, ImageEffect_DataType::EFFECT_DATA_TYPE_INT32,
109         value->dataValue.int32Value) != ErrorCode::SUCCESS, ErrorCode::SUCCESS);
110     CHECK_AND_RETURN_RET(AnyCastOHAny(any, value->dataType, ImageEffect_DataType::EFFECT_DATA_TYPE_FLOAT,
111         value->dataValue.floatValue) != ErrorCode::SUCCESS, ErrorCode::SUCCESS);
112     CHECK_AND_RETURN_RET(AnyCastOHAny(any, value->dataType, ImageEffect_DataType::EFFECT_DATA_TYPE_DOUBLE,
113         value->dataValue.doubleValue) != ErrorCode::SUCCESS, ErrorCode::SUCCESS);
114     CHECK_AND_RETURN_RET(AnyCastOHAny(any, value->dataType, ImageEffect_DataType::EFFECT_DATA_TYPE_CHAR,
115         value->dataValue.charValue) != ErrorCode::SUCCESS, ErrorCode::SUCCESS);
116     CHECK_AND_RETURN_RET(AnyCastOHAny(any, value->dataType, ImageEffect_DataType::EFFECT_DATA_TYPE_LONG,
117         value->dataValue.longValue) != ErrorCode::SUCCESS, ErrorCode::SUCCESS);
118     CHECK_AND_RETURN_RET(AnyCastOHAny(any, value->dataType, ImageEffect_DataType::EFFECT_DATA_TYPE_PTR,
119         value->dataValue.ptrValue) != ErrorCode::SUCCESS, ErrorCode::SUCCESS);
120     CHECK_AND_RETURN_RET(AnyCastOHAny(any, value->dataType, ImageEffect_DataType::EFFECT_DATA_TYPE_BOOL,
121         value->dataValue.boolValue) != ErrorCode::SUCCESS, ErrorCode::SUCCESS);
122 
123 #ifndef HST_ANY_WITH_NO_RTTI
124     EFFECT_LOGE("inner any type not support switch to oh_any! type:%{public}s", any.Type().name());
125 #else
126     EFFECT_LOGE("inner any type not support switch to oh_any! type:%{public}s", std::string(any.TypeName()).c_str());
127 #endif
128     return ErrorCode::ERR_NOT_SUPPORT_SWITCH_TO_OHANY;
129 }
130 
SwitchToOHFormatType(const IEffectFormat & formatType,ImageEffect_Format & ohFormatType)131 void NativeCommonUtils::SwitchToOHFormatType(const IEffectFormat &formatType, ImageEffect_Format &ohFormatType)
132 {
133     auto it = FORMAT_TABLE.find(formatType);
134     if (it != FORMAT_TABLE.end()) {
135         ohFormatType = it->second;
136     } else {
137         ohFormatType = ImageEffect_Format::EFFECT_PIXEL_FORMAT_UNKNOWN;
138     }
139 }
140 
SwitchToFormatType(const ImageEffect_Format & ohFormatType,IEffectFormat & formatType)141 void NativeCommonUtils::SwitchToFormatType(const ImageEffect_Format &ohFormatType, IEffectFormat &formatType)
142 {
143     auto formatIter = std::find_if(FORMAT_TABLE.begin(), FORMAT_TABLE.end(),
144         [&ohFormatType](const std::pair<IEffectFormat, ImageEffect_Format> &format) {
145             return format.second == ohFormatType;
146     });
147     if (formatIter != FORMAT_TABLE.end()) {
148         formatType = formatIter->first;
149     } else {
150         formatType = IEffectFormat::DEFAULT;
151     }
152 }
153 
SwitchToOHBufferType(const IPType & ipType,ImageEffect_BufferType & ohBufferType)154 void SwitchToOHBufferType(const IPType &ipType, ImageEffect_BufferType &ohBufferType)
155 {
156     auto it = IPTYPE_TABLE.find(ipType);
157     if (it != IPTYPE_TABLE.end()) {
158         ohBufferType = it->second;
159     } else {
160         ohBufferType = ImageEffect_BufferType::EFFECT_BUFFER_TYPE_UNKNOWN;
161     }
162 }
163 
SwitchToOHEffectInfo(const EffectInfo * effectInfo,OH_EffectFilterInfo * ohFilterInfo)164 void NativeCommonUtils::SwitchToOHEffectInfo(const EffectInfo *effectInfo, OH_EffectFilterInfo *ohFilterInfo)
165 {
166     CHECK_AND_RETURN_LOG(effectInfo != nullptr, "effectInfo is null!");
167     CHECK_AND_RETURN_LOG(ohFilterInfo != nullptr, "ohFilterInfo is null!");
168 
169     ohFilterInfo->supportedBufferTypes.clear();
170     ohFilterInfo->supportedFormats.clear();
171     for (const auto &format : effectInfo->formats_) {
172         for (auto ipType : format.second) {
173             ImageEffect_BufferType bufferType = ImageEffect_BufferType::EFFECT_BUFFER_TYPE_UNKNOWN;
174             SwitchToOHBufferType(ipType, bufferType);
175             if (bufferType == ImageEffect_BufferType::EFFECT_BUFFER_TYPE_UNKNOWN) {
176                 continue;
177             }
178             ohFilterInfo->supportedBufferTypes.emplace(bufferType);
179         }
180 
181         ImageEffect_Format ohFormatType = ImageEffect_Format::EFFECT_PIXEL_FORMAT_UNKNOWN;
182         SwitchToOHFormatType(format.first, ohFormatType);
183         ohFilterInfo->supportedFormats.emplace(ohFormatType);
184     }
185 }
186 
GetPixelMapFromOHPixelmap(OH_PixelmapNative * pixelmapNative)187 PixelMap *NativeCommonUtils::GetPixelMapFromOHPixelmap(OH_PixelmapNative *pixelmapNative)
188 {
189     CHECK_AND_RETURN_RET_LOG(pixelmapNative != nullptr, nullptr, "input pixelmapNative is null!");
190 
191     std::shared_ptr<PixelMap> pixelMap = pixelmapNative->GetInnerPixelmap();
192     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "pixelMap is null!");
193 
194     return pixelMap.get();
195 }
196 
GetPictureFromNativePicture(OH_PictureNative * pictureNative)197 Picture *NativeCommonUtils::GetPictureFromNativePicture(OH_PictureNative *pictureNative)
198 {
199     CHECK_AND_RETURN_RET_LOG(pictureNative != nullptr, nullptr, "input pictureNative is null!");
200 
201     std::shared_ptr<OHOS::Media::Picture> picture = pictureNative->GetInnerPicture();
202     CHECK_AND_RETURN_RET_LOG(picture != nullptr, nullptr, "GetPictureFromNativePicture: picture is null!");
203 
204     return picture.get();
205 }
206 
IsMatchLookupCondition(std::shared_ptr<EffectInfo> & effectInfo,std::string & type,uint32_t enumValue)207 bool IsMatchLookupCondition(std::shared_ptr<EffectInfo> &effectInfo, std::string &type, uint32_t enumValue)
208 {
209     if (type.compare("Format") == 0) {
210         auto formatType = static_cast<IEffectFormat>(enumValue);
211         if (formatType == IEffectFormat::DEFAULT) {
212             return true;
213         }
214 
215         auto it = std::find_if(effectInfo->formats_.begin(), effectInfo->formats_.end(),
216             [&formatType](const std::pair<IEffectFormat, std::vector<IPType>> &format) {
217                 return formatType == format.first;
218             });
219         return it != effectInfo->formats_.end();
220     } else {
221         return false;
222     }
223 }
224 
IsMatchLookupCondition(std::shared_ptr<IFilterDelegate> & filterDelegate,std::string & type,uint32_t enumValue)225 bool IsMatchLookupCondition(std::shared_ptr<IFilterDelegate> &filterDelegate, std::string &type, uint32_t enumValue)
226 {
227     auto effectInfo = static_cast<OH_EffectFilterInfo *>(filterDelegate->GetEffectInfo());
228 
229     if (type.compare("Format") == 0) {
230         auto formatType = static_cast<IEffectFormat>(enumValue);
231         if (formatType == IEffectFormat::DEFAULT) {
232             return true;
233         }
234         ImageEffect_Format ohFormatType = ImageEffect_Format::EFFECT_PIXEL_FORMAT_UNKNOWN;
235         NativeCommonUtils::SwitchToOHFormatType(formatType, ohFormatType);
236         return ohFormatType != ImageEffect_Format::EFFECT_PIXEL_FORMAT_UNKNOWN && effectInfo != nullptr &&
237             effectInfo->supportedFormats.find(ohFormatType) != effectInfo->supportedFormats.end();
238     } else {
239         return false;
240     }
241 }
242 
ParseLookupKey(std::string & key,std::vector<const char * > & matchEFilter)243 void NativeCommonUtils::ParseLookupKey(std::string &key, std::vector<const char *> &matchEFilter)
244 {
245     auto pos = key.find(':');
246     CHECK_AND_RETURN_LOG(pos != std::string::npos, "key is invalid! key=%{public}s", key.c_str());
247 
248     std::string type = key.substr(0, pos);
249     auto it = LOOK_UP_CAPABILITY.find(type);
250     CHECK_AND_RETURN_LOG(it != LOOK_UP_CAPABILITY.end(),
251         "type is invalid! key=%{public}s, type=%{public}s", key.c_str(), type.c_str());
252 
253     std::string value = key.substr(pos + 1);
254     auto valueIterator = it->second.find(value);
255     CHECK_AND_RETURN_LOG(valueIterator != it->second.end(),
256         "value is invalid! key=%{public}s, type=%{public}s, value=%{public}s",
257         key.c_str(), type.c_str(), value.c_str());
258 
259     std::vector<const char *> efilterNames;
260     EFilterFactory::Instance()->GetAllEffectNames(efilterNames);
261     std::shared_ptr<EffectInfo> effectInfo;
262     std::shared_ptr<IFilterDelegate> filterDelegate;
263     for (const auto &efilterName : efilterNames) {
264         // custom efilter
265         filterDelegate = EFilterFactory::Instance()->GetDelegate(efilterName);
266         if (filterDelegate != nullptr) {
267             if (IsMatchLookupCondition(filterDelegate, type, valueIterator->second)) {
268                 matchEFilter.emplace_back(efilterName);
269             }
270             continue;
271         }
272 
273         effectInfo = EFilterFactory::Instance()->GetEffectInfo(efilterName);
274         if (effectInfo == nullptr) {
275             EFFECT_LOGW("effectInfo is null! efilterName=%{public}s", efilterName);
276             continue;
277         }
278         if (IsMatchLookupCondition(effectInfo, type, valueIterator->second)) {
279             matchEFilter.emplace_back(efilterName);
280         }
281     }
282 }
283 
SwitchToEffectInfo(const OH_EffectFilterInfo * info,const std::shared_ptr<EffectInfo> & effectInfo)284 void NativeCommonUtils::SwitchToEffectInfo(const OH_EffectFilterInfo *info,
285     const std::shared_ptr<EffectInfo> &effectInfo)
286 {
287     CHECK_AND_RETURN_LOG(info != nullptr, "SwitchToEffectInfo: info is null!");
288     effectInfo->category_ = Category::DEFAULT;
289     for (const auto &format: FORMAT_TABLE) {
290         ImageEffect_Format ohFormat = format.second;
291         if (ohFormat != ImageEffect_Format::EFFECT_PIXEL_FORMAT_UNKNOWN &&
292             info->supportedFormats.find(ohFormat) != info->supportedFormats.end()) {
293             effectInfo->formats_.emplace(format.first, std::vector<IPType>{ IPType::CPU });
294         }
295     }
296 
297     // color space for custom filter
298     effectInfo->colorSpaces_.emplace_back(EffectColorSpace::SRGB);
299     effectInfo->colorSpaces_.emplace_back(EffectColorSpace::SRGB_LIMIT);
300     effectInfo->colorSpaces_.emplace_back(EffectColorSpace::DISPLAY_P3);
301     effectInfo->colorSpaces_.emplace_back(EffectColorSpace::DISPLAY_P3_LIMIT);
302 }
303 
GetSupportedFormats(const OH_EffectFilterInfo * ohFilterInfo)304 uint32_t NativeCommonUtils::GetSupportedFormats(const OH_EffectFilterInfo *ohFilterInfo)
305 {
306     if (ohFilterInfo == nullptr) {
307         return 0;
308     }
309 
310     uint32_t supportedFormats = 0;
311     auto formatBitLen = sizeof(supportedFormats);
312     for (auto format : ohFilterInfo->supportedFormats) {
313         if (format >= formatBitLen) {
314             continue;
315         }
316         supportedFormats |= (1 << format);
317     }
318 
319     return supportedFormats;
320 }
321 
ReportEventStartFailed(ImageEffect_ErrorCode errorCode,const char * errorMsg)322 void NativeCommonUtils::ReportEventStartFailed(ImageEffect_ErrorCode errorCode, const char *errorMsg)
323 {
324     EventInfo eventInfo = {
325         .errorInfo = {
326             .errorCode = errorCode,
327             .errorMsg = errorMsg,
328         }
329     };
330     EventReport::ReportHiSysEvent(RENDER_FAILED_FAULT, eventInfo);
331 }
332 
ConvertStartResult(ErrorCode errorCode)333 ImageEffect_ErrorCode NativeCommonUtils::ConvertStartResult(ErrorCode errorCode)
334 {
335     auto iter = ERRORCODE_TABLE.find(errorCode);
336     if (iter == ERRORCODE_TABLE.end()) {
337         return ImageEffect_ErrorCode::EFFECT_UNKNOWN;
338     }
339     return iter->second;
340 }
341 } // namespace Effect
342 } // namespace Media
343 } // namespace OHOS