CLAHE Python bindings
[profile/ivi/opencv.git] / modules / androidcamera / src / camera_activity.cpp
1 #include <dlfcn.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <dirent.h>
5 #include <android/log.h>
6 #include <cctype>
7 #include <string>
8 #include <vector>
9 #include <algorithm>
10 #include <opencv2/core/version.hpp>
11 #include "camera_activity.hpp"
12 #include "camera_wrapper.h"
13 #include "EngineCommon.h"
14
15 #undef LOG_TAG
16 #undef LOGE
17 #undef LOGD
18 #undef LOGI
19
20 #define LOG_TAG "OpenCV::camera"
21 #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
22 #define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
23 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
24
25 ///////
26 // Debug
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <dirent.h>
30
31
32 using namespace std;
33
34 class CameraWrapperConnector
35 {
36 public:
37     static CameraActivity::ErrorCode connect(int cameraId, CameraActivity* pCameraActivity, void** camera);
38     static CameraActivity::ErrorCode disconnect(void** camera);
39     static CameraActivity::ErrorCode setProperty(void* camera, int propIdx, double value);
40     static CameraActivity::ErrorCode getProperty(void* camera, int propIdx, double* value);
41     static CameraActivity::ErrorCode applyProperties(void** ppcamera);
42
43     static void setPathLibFolder(const std::string& path);
44
45 private:
46     static std::string pathLibFolder;
47     static bool isConnectedToLib;
48
49     static std::string getPathLibFolder();
50     static std::string getDefaultPathLibFolder();
51     static CameraActivity::ErrorCode connectToLib();
52     static CameraActivity::ErrorCode getSymbolFromLib(void * libHandle, const char* symbolName, void** ppSymbol);
53     static void fillListWrapperLibs(const string& folderPath, vector<string>& listLibs);
54
55     static InitCameraConnectC pInitCameraC;
56     static CloseCameraConnectC pCloseCameraC;
57     static GetCameraPropertyC pGetPropertyC;
58     static SetCameraPropertyC pSetPropertyC;
59     static ApplyCameraPropertiesC pApplyPropertiesC;
60
61     friend bool nextFrame(void* buffer, size_t bufferSize, void* userData);
62 };
63
64 std::string CameraWrapperConnector::pathLibFolder;
65
66 bool CameraWrapperConnector::isConnectedToLib = false;
67 InitCameraConnectC  CameraWrapperConnector::pInitCameraC = 0;
68 CloseCameraConnectC  CameraWrapperConnector::pCloseCameraC = 0;
69 GetCameraPropertyC CameraWrapperConnector::pGetPropertyC = 0;
70 SetCameraPropertyC CameraWrapperConnector::pSetPropertyC = 0;
71 ApplyCameraPropertiesC CameraWrapperConnector::pApplyPropertiesC = 0;
72
73 #define INIT_CAMERA_SYMBOL_NAME "initCameraConnectC"
74 #define CLOSE_CAMERA_SYMBOL_NAME "closeCameraConnectC"
75 #define SET_CAMERA_PROPERTY_SYMBOL_NAME "setCameraPropertyC"
76 #define GET_CAMERA_PROPERTY_SYMBOL_NAME "getCameraPropertyC"
77 #define APPLY_CAMERA_PROPERTIES_SYMBOL_NAME "applyCameraPropertiesC"
78 #define PREFIX_CAMERA_WRAPPER_LIB "libnative_camera"
79
80
81 bool nextFrame(void* buffer, size_t bufferSize, void* userData)
82 {
83     if (userData == NULL)
84         return true;
85
86     return ((CameraActivity*)userData)->onFrameBuffer(buffer, bufferSize);
87 }
88
89 CameraActivity::ErrorCode CameraWrapperConnector::connect(int cameraId, CameraActivity* pCameraActivity, void** camera)
90 {
91     if (pCameraActivity == NULL)
92     {
93         LOGE("CameraWrapperConnector::connect error: wrong pointer to CameraActivity object");
94         return CameraActivity::ERROR_WRONG_POINTER_CAMERA_WRAPPER;
95     }
96
97     CameraActivity::ErrorCode errcode=connectToLib();
98     if (errcode) return errcode;
99
100     void* cmr = (*pInitCameraC)((void*)nextFrame, cameraId, (void*)pCameraActivity);
101     if (!cmr)
102     {
103         LOGE("CameraWrapperConnector::connectWrapper ERROR: the initializing function returned false");
104         return CameraActivity::ERROR_CANNOT_INITIALIZE_CONNECTION;
105     }
106
107     *camera = cmr;
108     return CameraActivity::NO_ERROR;
109 }
110
111 CameraActivity::ErrorCode CameraWrapperConnector::disconnect(void** camera)
112 {
113     if (camera == NULL || *camera == NULL)
114     {
115         LOGE("CameraWrapperConnector::disconnect error: wrong pointer to camera object");
116         return CameraActivity::ERROR_WRONG_POINTER_CAMERA_WRAPPER;
117     }
118
119     CameraActivity::ErrorCode errcode=connectToLib();
120     if (errcode) return errcode;
121
122     (*pCloseCameraC)(camera);
123
124     return CameraActivity::NO_ERROR;
125 }
126
127 CameraActivity::ErrorCode CameraWrapperConnector::setProperty(void* camera, int propIdx, double value)
128 {
129     if (camera == NULL)
130     {
131         LOGE("CameraWrapperConnector::setProperty error: wrong pointer to camera object");
132         return CameraActivity::ERROR_WRONG_POINTER_CAMERA_WRAPPER;
133     }
134
135     (*pSetPropertyC)(camera, propIdx, value);
136
137     return CameraActivity::NO_ERROR;
138 }
139
140 CameraActivity::ErrorCode CameraWrapperConnector::getProperty(void* camera, int propIdx, double* value)
141 {
142     if (camera == NULL)
143     {
144         LOGE("CameraWrapperConnector::getProperty error: wrong pointer to camera object");
145         return CameraActivity::ERROR_WRONG_POINTER_CAMERA_WRAPPER;
146     }
147     LOGE("calling (*pGetPropertyC)(%p, %d)", camera, propIdx);
148     *value = (*pGetPropertyC)(camera, propIdx);
149     return CameraActivity::NO_ERROR;
150 }
151
152 CameraActivity::ErrorCode CameraWrapperConnector::applyProperties(void** ppcamera)
153 {
154     if ((ppcamera == NULL) || (*ppcamera == NULL))
155     {
156         LOGE("CameraWrapperConnector::applyProperties error: wrong pointer to camera object");
157         return CameraActivity::ERROR_WRONG_POINTER_CAMERA_WRAPPER;
158     }
159
160     (*pApplyPropertiesC)(ppcamera);
161     return CameraActivity::NO_ERROR;
162 }
163
164 CameraActivity::ErrorCode CameraWrapperConnector::connectToLib()
165 {
166     if (isConnectedToLib) {
167         return CameraActivity::NO_ERROR;
168     }
169
170     dlerror();
171     string folderPath = getPathLibFolder();
172     if (folderPath.empty())
173     {
174         LOGD("Trying to find native camera in default OpenCV packages");
175         folderPath = getDefaultPathLibFolder();
176     }
177
178     LOGD("CameraWrapperConnector::connectToLib: folderPath=%s", folderPath.c_str());
179
180     vector<string> listLibs;
181     fillListWrapperLibs(folderPath, listLibs);
182     std::sort(listLibs.begin(), listLibs.end(), std::greater<string>());
183
184     void * libHandle=0;
185     string cur_path;
186     for(size_t i = 0; i < listLibs.size(); i++) {
187         cur_path=folderPath + listLibs[i];
188         LOGD("try to load library '%s'", listLibs[i].c_str());
189         libHandle=dlopen(cur_path.c_str(), RTLD_LAZY);
190         if (libHandle) {
191             LOGD("Loaded library '%s'", cur_path.c_str());
192             break;
193         } else {
194             LOGD("CameraWrapperConnector::connectToLib ERROR: cannot dlopen camera wrapper library %s, dlerror=\"%s\"",
195                  cur_path.c_str(), dlerror());
196         }
197     }
198
199     if (!libHandle) {
200         LOGE("CameraWrapperConnector::connectToLib ERROR: cannot dlopen camera wrapper library");
201         return CameraActivity::ERROR_CANNOT_OPEN_CAMERA_WRAPPER_LIB;
202     }
203
204     InitCameraConnectC pInit_C;
205     CloseCameraConnectC pClose_C;
206     GetCameraPropertyC pGetProp_C;
207     SetCameraPropertyC pSetProp_C;
208     ApplyCameraPropertiesC pApplyProp_C;
209
210     CameraActivity::ErrorCode res;
211
212     res = getSymbolFromLib(libHandle, (const char*)INIT_CAMERA_SYMBOL_NAME, (void**)(&pInit_C));
213     if (res) return res;
214
215     res = getSymbolFromLib(libHandle, CLOSE_CAMERA_SYMBOL_NAME, (void**)(&pClose_C));
216     if (res) return res;
217
218     res = getSymbolFromLib(libHandle, GET_CAMERA_PROPERTY_SYMBOL_NAME, (void**)(&pGetProp_C));
219     if (res) return res;
220
221     res = getSymbolFromLib(libHandle, SET_CAMERA_PROPERTY_SYMBOL_NAME, (void**)(&pSetProp_C));
222     if (res) return res;
223
224     res = getSymbolFromLib(libHandle, APPLY_CAMERA_PROPERTIES_SYMBOL_NAME, (void**)(&pApplyProp_C));
225     if (res) return res;
226
227     pInitCameraC  = pInit_C;
228     pCloseCameraC = pClose_C;
229     pGetPropertyC = pGetProp_C;
230     pSetPropertyC = pSetProp_C;
231     pApplyPropertiesC = pApplyProp_C;
232     isConnectedToLib=true;
233
234     return CameraActivity::NO_ERROR;
235 }
236
237 CameraActivity::ErrorCode CameraWrapperConnector::getSymbolFromLib(void* libHandle, const char* symbolName, void** ppSymbol)
238 {
239     dlerror();
240     *(void **) (ppSymbol)=dlsym(libHandle, symbolName);
241
242     const char* error_dlsym_init=dlerror();
243     if (error_dlsym_init) {
244         LOGE("CameraWrapperConnector::getSymbolFromLib ERROR: cannot get symbol of the function '%s' from the camera wrapper library, dlerror=\"%s\"",
245              symbolName, error_dlsym_init);
246         return CameraActivity::ERROR_CANNOT_GET_FUNCTION_FROM_CAMERA_WRAPPER_LIB;
247     }
248     return CameraActivity::NO_ERROR;
249 }
250
251 void CameraWrapperConnector::fillListWrapperLibs(const string& folderPath, vector<string>& listLibs)
252 {
253     DIR *dp;
254     struct dirent *ep;
255
256     dp = opendir (folderPath.c_str());
257     if (dp != NULL)
258     {
259         while ((ep = readdir (dp))) {
260             const char* cur_name=ep->d_name;
261             if (strstr(cur_name, PREFIX_CAMERA_WRAPPER_LIB)) {
262                 listLibs.push_back(cur_name);
263                 LOGE("||%s", cur_name);
264             }
265         }
266         (void) closedir (dp);
267     }
268 }
269
270 std::string CameraWrapperConnector::getDefaultPathLibFolder()
271 {
272     #define BIN_PACKAGE_NAME(x) "org.opencv.lib_v" CVAUX_STR(CV_VERSION_EPOCH) CVAUX_STR(CV_VERSION_MAJOR) "_" x
273     const char* const packageList[] = {BIN_PACKAGE_NAME("armv7a"), OPENCV_ENGINE_PACKAGE};
274     for (size_t i = 0; i < sizeof(packageList)/sizeof(packageList[0]); i++)
275     {
276         char path[128];
277         sprintf(path, "/data/data/%s/lib/", packageList[i]);
278         LOGD("Trying package \"%s\" (\"%s\")", packageList[i], path);
279
280         DIR* dir = opendir(path);
281         if (!dir)
282         {
283             LOGD("Package not found");
284             continue;
285         }
286         else
287         {
288             closedir(dir);
289             return path;
290         }
291     }
292
293     return string();
294 }
295
296 std::string CameraWrapperConnector::getPathLibFolder()
297 {
298     if (!pathLibFolder.empty())
299         return pathLibFolder;
300
301     Dl_info dl_info;
302     if(0 != dladdr((void *)nextFrame, &dl_info))
303     {
304         LOGD("Library name: %s", dl_info.dli_fname);
305         LOGD("Library base address: %p", dl_info.dli_fbase);
306
307         const char* libName=dl_info.dli_fname;
308         while( ((*libName)=='/') || ((*libName)=='.') )
309         libName++;
310
311         char lineBuf[2048];
312         FILE* file = fopen("/proc/self/smaps", "rt");
313
314         if(file)
315         {
316             while (fgets(lineBuf, sizeof lineBuf, file) != NULL)
317             {
318                 //verify that line ends with library name
319                 int lineLength = strlen(lineBuf);
320                 int libNameLength = strlen(libName);
321
322                 //trim end
323                 for(int i = lineLength - 1; i >= 0 && isspace(lineBuf[i]); --i)
324                 {
325                     lineBuf[i] = 0;
326                     --lineLength;
327                 }
328
329                 if (0 != strncmp(lineBuf + lineLength - libNameLength, libName, libNameLength))
330                 {
331                 //the line does not contain the library name
332                     continue;
333                 }
334
335                 //extract path from smaps line
336                 char* pathBegin = strchr(lineBuf, '/');
337                 if (0 == pathBegin)
338                 {
339                     LOGE("Strange error: could not find path beginning in lin \"%s\"", lineBuf);
340                     continue;
341                 }
342
343                 char* pathEnd = strrchr(pathBegin, '/');
344                 pathEnd[1] = 0;
345
346                 LOGD("Libraries folder found: %s", pathBegin);
347
348                 fclose(file);
349                 return pathBegin;
350             }
351             fclose(file);
352             LOGE("Could not find library path");
353         }
354         else
355         {
356             LOGE("Could not read /proc/self/smaps");
357         }
358     }
359     else
360     {
361         LOGE("Could not get library name and base address");
362     }
363
364     return string();
365 }
366
367 void CameraWrapperConnector::setPathLibFolder(const string& path)
368 {
369     pathLibFolder=path;
370 }
371
372
373 /////////////////////////////////////////////////////////////////////////////////////////////////
374
375 CameraActivity::CameraActivity() : camera(0), frameWidth(-1), frameHeight(-1)
376 {
377 }
378
379 CameraActivity::~CameraActivity()
380 {
381     if (camera != 0)
382         disconnect();
383 }
384
385 bool CameraActivity::onFrameBuffer(void* /*buffer*/, int /*bufferSize*/)
386 {
387     LOGD("CameraActivity::onFrameBuffer - empty callback");
388     return true;
389 }
390
391 void CameraActivity::disconnect()
392 {
393     CameraWrapperConnector::disconnect(&camera);
394 }
395
396 bool CameraActivity::isConnected() const
397 {
398     return camera != 0;
399 }
400
401 CameraActivity::ErrorCode CameraActivity::connect(int cameraId)
402 {
403     ErrorCode rescode = CameraWrapperConnector::connect(cameraId, this, &camera);
404     if (rescode) return rescode;
405
406     return NO_ERROR;
407 }
408
409 double CameraActivity::getProperty(int propIdx)
410 {
411     double propVal;
412     ErrorCode rescode = CameraWrapperConnector::getProperty(camera, propIdx, &propVal);
413     if (rescode) return -1;
414     return propVal;
415 }
416
417 void CameraActivity::setProperty(int propIdx, double value)
418 {
419     CameraWrapperConnector::setProperty(camera, propIdx, value);
420 }
421
422 void CameraActivity::applyProperties()
423 {
424     frameWidth = -1;
425     frameHeight = -1;
426     CameraWrapperConnector::applyProperties(&camera);
427     frameWidth = getProperty(ANDROID_CAMERA_PROPERTY_FRAMEWIDTH);
428     frameHeight = getProperty(ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT);
429 }
430
431 int CameraActivity::getFrameWidth()
432 {
433     if (frameWidth <= 0)
434     frameWidth = getProperty(ANDROID_CAMERA_PROPERTY_FRAMEWIDTH);
435     return frameWidth;
436 }
437
438 int CameraActivity::getFrameHeight()
439 {
440     if (frameHeight <= 0)
441     frameHeight = getProperty(ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT);
442     return frameHeight;
443 }
444
445 void CameraActivity::setPathLibFolder(const char* path)
446 {
447     CameraWrapperConnector::setPathLibFolder(path);
448 }