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 "image_processing_loader.h"
17
18 #include <dlfcn.h>
19
20 #include "vpe_log.h"
21
22 namespace {
23 const std::string VPE_IMPL_LIBRARY_PATH = "libimage_processing_capi_impl.so";
24 }
25
Get()26 ImageProcessingNdkLoader& ImageProcessingNdkLoader::Get()
27 {
28 static ImageProcessingNdkLoader loader{};
29 return loader;
30 }
31
LoadLibrary()32 bool ImageProcessingNdkLoader::LoadLibrary()
33 {
34 std::lock_guard<std::mutex> lock(lock_);
35 if (refCount_ > 0) {
36 refCount_++;
37 return true;
38 }
39
40 if (!LoadLibraryLocked()) {
41 return false;
42 }
43 refCount_++;
44 return true;
45 }
46
UnloadLibrary()47 void ImageProcessingNdkLoader::UnloadLibrary()
48 {
49 std::lock_guard<std::mutex> lock(lock_);
50 if (refCount_ == 0) {
51 VPE_LOGW("Unload too many times!");
52 return;
53 }
54
55 refCount_--;
56 if (refCount_ > 0) {
57 return;
58 }
59 UnloadLibraryLocked();
60 }
61
IsValid() const62 bool ImageProcessingNdkLoader::IsValid() const
63 {
64 return isValid_.load();
65 }
66
InitializeEnvironment()67 ImageProcessing_ErrorCode ImageProcessingNdkLoader::InitializeEnvironment()
68 {
69 return CallNdk([](IImageProcessingNdk* intfNdk) { return intfNdk->InitializeEnvironment(); });
70 }
71
DeinitializeEnvironment()72 ImageProcessing_ErrorCode ImageProcessingNdkLoader::DeinitializeEnvironment()
73 {
74 return CallNdk([](IImageProcessingNdk* intfNdk) { return intfNdk->DeinitializeEnvironment(); });
75 }
76
IsColorSpaceConversionSupported(const ImageProcessing_ColorSpaceInfo * sourceImageInfo,const ImageProcessing_ColorSpaceInfo * destinationImageInfo)77 bool ImageProcessingNdkLoader::IsColorSpaceConversionSupported(
78 const ImageProcessing_ColorSpaceInfo* sourceImageInfo,
79 const ImageProcessing_ColorSpaceInfo* destinationImageInfo)
80 {
81 return CallSupportNdk([sourceImageInfo, destinationImageInfo](IImageProcessingNdk* intfNdk) {
82 return intfNdk->IsColorSpaceConversionSupported(sourceImageInfo, destinationImageInfo);
83 });
84 }
85
IsCompositionSupported(const ImageProcessing_ColorSpaceInfo * sourceImageInfo,const ImageProcessing_ColorSpaceInfo * sourceGainmapInfo,const ImageProcessing_ColorSpaceInfo * destinationImageInfo)86 bool ImageProcessingNdkLoader::IsCompositionSupported(
87 const ImageProcessing_ColorSpaceInfo* sourceImageInfo,
88 const ImageProcessing_ColorSpaceInfo* sourceGainmapInfo,
89 const ImageProcessing_ColorSpaceInfo* destinationImageInfo)
90 {
91 return CallSupportNdk([sourceImageInfo, sourceGainmapInfo, destinationImageInfo](IImageProcessingNdk* intfNdk) {
92 return intfNdk->IsCompositionSupported(sourceImageInfo, sourceGainmapInfo, destinationImageInfo);
93 });
94 }
95
IsDecompositionSupported(const ImageProcessing_ColorSpaceInfo * sourceImageInfo,const ImageProcessing_ColorSpaceInfo * destinationImageInfo,const ImageProcessing_ColorSpaceInfo * destinationGainmapInfo)96 bool ImageProcessingNdkLoader::IsDecompositionSupported(
97 const ImageProcessing_ColorSpaceInfo* sourceImageInfo,
98 const ImageProcessing_ColorSpaceInfo* destinationImageInfo,
99 const ImageProcessing_ColorSpaceInfo* destinationGainmapInfo)
100 {
101 return CallSupportNdk(
102 [sourceImageInfo, destinationImageInfo, destinationGainmapInfo](IImageProcessingNdk* intfNdk) {
103 return intfNdk->IsDecompositionSupported(sourceImageInfo, destinationImageInfo, destinationGainmapInfo);
104 });
105 }
106
IsMetadataGenerationSupported(const ImageProcessing_ColorSpaceInfo * sourceImageInfo)107 bool ImageProcessingNdkLoader::IsMetadataGenerationSupported(const ImageProcessing_ColorSpaceInfo* sourceImageInfo)
108 {
109 return CallSupportNdk([sourceImageInfo](IImageProcessingNdk* intfNdk) {
110 return intfNdk->IsMetadataGenerationSupported(sourceImageInfo);
111 });
112 }
113
Create(OH_ImageProcessing ** imageProcessor,int32_t type)114 ImageProcessing_ErrorCode ImageProcessingNdkLoader::Create(OH_ImageProcessing** imageProcessor, int32_t type)
115 {
116 return CallNdk([imageProcessor, type](IImageProcessingNdk* intfNdk) {
117 return intfNdk->Create(imageProcessor, type);
118 });
119 }
120
Destroy(OH_ImageProcessing * imageProcessor)121 ImageProcessing_ErrorCode ImageProcessingNdkLoader::Destroy(OH_ImageProcessing* imageProcessor)
122 {
123 return CallNdk([imageProcessor](IImageProcessingNdk* intfNdk) { return intfNdk->Destroy(imageProcessor); });
124 }
125
SetParameter(OH_ImageProcessing * imageProcessor,const OH_AVFormat * parameter)126 ImageProcessing_ErrorCode ImageProcessingNdkLoader::SetParameter(OH_ImageProcessing* imageProcessor,
127 const OH_AVFormat* parameter)
128 {
129 return CallNdk([imageProcessor, parameter](IImageProcessingNdk* intfNdk) {
130 return intfNdk->SetParameter(imageProcessor, parameter);
131 });
132 }
133
GetParameter(OH_ImageProcessing * imageProcessor,OH_AVFormat * parameter)134 ImageProcessing_ErrorCode ImageProcessingNdkLoader::GetParameter(OH_ImageProcessing* imageProcessor,
135 OH_AVFormat* parameter)
136 {
137 return CallNdk([imageProcessor, parameter](IImageProcessingNdk* intfNdk) {
138 return intfNdk->GetParameter(imageProcessor, parameter);
139 });
140 }
141
ConvertColorSpace(OH_ImageProcessing * imageProcessor,OH_PixelmapNative * sourceImage,OH_PixelmapNative * destinationImage)142 ImageProcessing_ErrorCode ImageProcessingNdkLoader::ConvertColorSpace(OH_ImageProcessing* imageProcessor,
143 OH_PixelmapNative* sourceImage, OH_PixelmapNative* destinationImage)
144 {
145 return CallNdk([imageProcessor, sourceImage, destinationImage](IImageProcessingNdk* intfNdk) {
146 return intfNdk->ConvertColorSpace(imageProcessor, sourceImage, destinationImage);
147 });
148 }
149
Compose(OH_ImageProcessing * imageProcessor,OH_PixelmapNative * sourceImage,OH_PixelmapNative * sourceGainmap,OH_PixelmapNative * destinationImage)150 ImageProcessing_ErrorCode ImageProcessingNdkLoader::Compose(OH_ImageProcessing* imageProcessor,
151 OH_PixelmapNative* sourceImage, OH_PixelmapNative* sourceGainmap, OH_PixelmapNative* destinationImage)
152 {
153 return CallNdk([imageProcessor, sourceImage, sourceGainmap, destinationImage](IImageProcessingNdk* intfNdk) {
154 return intfNdk->Compose(imageProcessor, sourceImage, sourceGainmap, destinationImage);
155 });
156 }
157
Decompose(OH_ImageProcessing * imageProcessor,OH_PixelmapNative * sourceImage,OH_PixelmapNative * destinationImage,OH_PixelmapNative * destinationGainmap)158 ImageProcessing_ErrorCode ImageProcessingNdkLoader::Decompose(OH_ImageProcessing* imageProcessor,
159 OH_PixelmapNative* sourceImage, OH_PixelmapNative* destinationImage, OH_PixelmapNative* destinationGainmap)
160 {
161 return CallNdk([imageProcessor, sourceImage, destinationImage, destinationGainmap](IImageProcessingNdk* intfNdk) {
162 return intfNdk->Decompose(imageProcessor, sourceImage, destinationImage, destinationGainmap);
163 });
164 }
165
GenerateMetadata(OH_ImageProcessing * imageProcessor,OH_PixelmapNative * sourceImage)166 ImageProcessing_ErrorCode ImageProcessingNdkLoader::GenerateMetadata(OH_ImageProcessing* imageProcessor,
167 OH_PixelmapNative* sourceImage)
168 {
169 return CallNdk([imageProcessor, sourceImage](IImageProcessingNdk* intfNdk) {
170 return intfNdk->GenerateMetadata(imageProcessor, sourceImage);
171 });
172 }
173
EnhanceDetail(OH_ImageProcessing * imageProcessor,OH_PixelmapNative * sourceImage,OH_PixelmapNative * destinationImage)174 ImageProcessing_ErrorCode ImageProcessingNdkLoader::EnhanceDetail(OH_ImageProcessing* imageProcessor,
175 OH_PixelmapNative* sourceImage, OH_PixelmapNative* destinationImage)
176 {
177 return CallNdk([imageProcessor, sourceImage, destinationImage](IImageProcessingNdk* intfNdk) {
178 return intfNdk->EnhanceDetail(imageProcessor, sourceImage, destinationImage);
179 });
180 }
181
LoadLibraryLocked()182 bool ImageProcessingNdkLoader::LoadLibraryLocked()
183 {
184 VPE_LOGI("Load library...");
185 const std::string& path = VPE_IMPL_LIBRARY_PATH;
186 if (!OpenLibraryLocked(path)) {
187 return false;
188 }
189
190 if (!LoadInterfaceLocked(imageProcessing_, destroyImageProcessingFunc_,
191 "CreateImageProcessingNdk", "DestroyImageProcessingNdk", path)) {
192 UnloadLibraryLocked();
193 return false;
194 }
195
196 isValid_ = true;
197 VPE_LOGI("Load library successfully.");
198 return true;
199 }
200
UnloadLibraryLocked()201 void ImageProcessingNdkLoader::UnloadLibraryLocked()
202 {
203 isValid_ = false;
204 if (destroyImageProcessingFunc_ != nullptr) {
205 destroyImageProcessingFunc_(imageProcessing_);
206 imageProcessing_ = nullptr;
207 destroyImageProcessingFunc_ = nullptr;
208 }
209
210 if (libHandle_ != nullptr) {
211 dlclose(libHandle_);
212 libHandle_ = nullptr;
213 }
214
215 VPE_LOGI("Unload library.");
216 }
217
OpenLibraryLocked(const std::string & path)218 bool ImageProcessingNdkLoader::OpenLibraryLocked(const std::string& path)
219 {
220 libHandle_ = dlopen(path.c_str(), RTLD_NOW);
221 if (libHandle_ == nullptr) {
222 VPE_LOGW("Can't open library %{public}s - %{public}s", path.c_str(), dlerror());
223 return false;
224 }
225 return true;
226 }
227
LoadInterfaceLocked(IImageProcessingNdk * & interface,destroyNdkFunc & destroyFunc,const std::string & createFuncName,const std::string & destroyFuncName,const std::string & path)228 bool ImageProcessingNdkLoader::LoadInterfaceLocked(IImageProcessingNdk*& interface, destroyNdkFunc& destroyFunc,
229 const std::string& createFuncName, const std::string& destroyFuncName, const std::string& path)
230 {
231 createNdkFunc createFunc = reinterpret_cast<createNdkFunc>(dlsym(libHandle_, createFuncName.c_str()));
232 if (createFunc == nullptr) {
233 VPE_LOGE("Failed to locate %{public}s in %{public}s - %{public}s",
234 createFuncName.c_str(), path.c_str(), path.c_str());
235 UnloadLibraryLocked();
236 return false;
237 }
238 destroyFunc = reinterpret_cast<destroyNdkFunc>(dlsym(libHandle_, destroyFuncName.c_str()));
239 if (destroyFunc == nullptr) {
240 VPE_LOGE("Failed to locate %{public}s in %{public}s - %{public}s",
241 destroyFuncName.c_str(), path.c_str(), path.c_str());
242 UnloadLibraryLocked();
243 return false;
244 }
245 interface = createFunc();
246 if (interface == nullptr) {
247 VPE_LOGW("Failed to create interface!");
248 UnloadLibraryLocked();
249 return false;
250 }
251 return true;
252 }
253
CallSupportNdk(std::function<bool (IImageProcessingNdk *)> && operation)254 bool ImageProcessingNdkLoader::CallSupportNdk(std::function<bool(IImageProcessingNdk*)>&& operation)
255 {
256 std::lock_guard<std::mutex> lock(lock_);
257 if (imageProcessing_ == nullptr) {
258 return false;
259 }
260 return operation(imageProcessing_);
261 }
262
CallNdk(std::function<ImageProcessing_ErrorCode (IImageProcessingNdk *)> && operation)263 ImageProcessing_ErrorCode ImageProcessingNdkLoader::CallNdk(
264 std::function<ImageProcessing_ErrorCode(IImageProcessingNdk*)>&& operation)
265 {
266 std::lock_guard<std::mutex> lock(lock_);
267 if (imageProcessing_ == nullptr) {
268 return IMAGE_PROCESSING_ERROR_UNKNOWN;
269 }
270 return operation(imageProcessing_);
271 }
272