#include #include #include #include #include #include #include #include #include #include #include #include #include "camera_activity.hpp" #include "camera_wrapper.h" #include "EngineCommon.h" #undef LOG_TAG #undef LOGE #undef LOGD #undef LOGI #define LOG_TAG "OpenCV::camera" #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) #define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) /////// // Debug #include #include #include using namespace std; class CameraWrapperConnector { public: static CameraActivity::ErrorCode connect(int cameraId, CameraActivity* pCameraActivity, void** camera); static CameraActivity::ErrorCode disconnect(void** camera); static CameraActivity::ErrorCode setProperty(void* camera, int propIdx, double value); static CameraActivity::ErrorCode getProperty(void* camera, int propIdx, double* value); static CameraActivity::ErrorCode applyProperties(void** ppcamera); static void setPathLibFolder(const std::string& path); private: static std::string pathLibFolder; static bool isConnectedToLib; static std::string getPathLibFolder(); static std::string getDefaultPathLibFolder(); static CameraActivity::ErrorCode connectToLib(); static CameraActivity::ErrorCode getSymbolFromLib(void * libHandle, const char* symbolName, void** ppSymbol); static void fillListWrapperLibs(const string& folderPath, vector& listLibs); static InitCameraConnectC pInitCameraC; static CloseCameraConnectC pCloseCameraC; static GetCameraPropertyC pGetPropertyC; static SetCameraPropertyC pSetPropertyC; static ApplyCameraPropertiesC pApplyPropertiesC; friend bool nextFrame(void* buffer, size_t bufferSize, void* userData); }; std::string CameraWrapperConnector::pathLibFolder; bool CameraWrapperConnector::isConnectedToLib = false; InitCameraConnectC CameraWrapperConnector::pInitCameraC = 0; CloseCameraConnectC CameraWrapperConnector::pCloseCameraC = 0; GetCameraPropertyC CameraWrapperConnector::pGetPropertyC = 0; SetCameraPropertyC CameraWrapperConnector::pSetPropertyC = 0; ApplyCameraPropertiesC CameraWrapperConnector::pApplyPropertiesC = 0; #define INIT_CAMERA_SYMBOL_NAME "initCameraConnectC" #define CLOSE_CAMERA_SYMBOL_NAME "closeCameraConnectC" #define SET_CAMERA_PROPERTY_SYMBOL_NAME "setCameraPropertyC" #define GET_CAMERA_PROPERTY_SYMBOL_NAME "getCameraPropertyC" #define APPLY_CAMERA_PROPERTIES_SYMBOL_NAME "applyCameraPropertiesC" #define PREFIX_CAMERA_WRAPPER_LIB "libnative_camera" bool nextFrame(void* buffer, size_t bufferSize, void* userData) { if (userData == NULL) return true; return ((CameraActivity*)userData)->onFrameBuffer(buffer, bufferSize); } CameraActivity::ErrorCode CameraWrapperConnector::connect(int cameraId, CameraActivity* pCameraActivity, void** camera) { if (pCameraActivity == NULL) { LOGE("CameraWrapperConnector::connect error: wrong pointer to CameraActivity object"); return CameraActivity::ERROR_WRONG_POINTER_CAMERA_WRAPPER; } CameraActivity::ErrorCode errcode=connectToLib(); if (errcode) return errcode; void* cmr = (*pInitCameraC)((void*)nextFrame, cameraId, (void*)pCameraActivity); if (!cmr) { LOGE("CameraWrapperConnector::connectWrapper ERROR: the initializing function returned false"); return CameraActivity::ERROR_CANNOT_INITIALIZE_CONNECTION; } *camera = cmr; return CameraActivity::NO_ERROR; } CameraActivity::ErrorCode CameraWrapperConnector::disconnect(void** camera) { if (camera == NULL || *camera == NULL) { LOGE("CameraWrapperConnector::disconnect error: wrong pointer to camera object"); return CameraActivity::ERROR_WRONG_POINTER_CAMERA_WRAPPER; } CameraActivity::ErrorCode errcode=connectToLib(); if (errcode) return errcode; (*pCloseCameraC)(camera); return CameraActivity::NO_ERROR; } CameraActivity::ErrorCode CameraWrapperConnector::setProperty(void* camera, int propIdx, double value) { if (camera == NULL) { LOGE("CameraWrapperConnector::setProperty error: wrong pointer to camera object"); return CameraActivity::ERROR_WRONG_POINTER_CAMERA_WRAPPER; } (*pSetPropertyC)(camera, propIdx, value); return CameraActivity::NO_ERROR; } CameraActivity::ErrorCode CameraWrapperConnector::getProperty(void* camera, int propIdx, double* value) { if (camera == NULL) { LOGE("CameraWrapperConnector::getProperty error: wrong pointer to camera object"); return CameraActivity::ERROR_WRONG_POINTER_CAMERA_WRAPPER; } LOGE("calling (*pGetPropertyC)(%p, %d)", camera, propIdx); *value = (*pGetPropertyC)(camera, propIdx); return CameraActivity::NO_ERROR; } CameraActivity::ErrorCode CameraWrapperConnector::applyProperties(void** ppcamera) { if ((ppcamera == NULL) || (*ppcamera == NULL)) { LOGE("CameraWrapperConnector::applyProperties error: wrong pointer to camera object"); return CameraActivity::ERROR_WRONG_POINTER_CAMERA_WRAPPER; } (*pApplyPropertiesC)(ppcamera); return CameraActivity::NO_ERROR; } CameraActivity::ErrorCode CameraWrapperConnector::connectToLib() { if (isConnectedToLib) { return CameraActivity::NO_ERROR; } dlerror(); string folderPath = getPathLibFolder(); if (folderPath.empty()) { LOGD("Trying to find native camera in default OpenCV packages"); folderPath = getDefaultPathLibFolder(); } LOGD("CameraWrapperConnector::connectToLib: folderPath=%s", folderPath.c_str()); vector listLibs; fillListWrapperLibs(folderPath, listLibs); std::sort(listLibs.begin(), listLibs.end(), std::greater()); void * libHandle=0; string cur_path; for(size_t i = 0; i < listLibs.size(); i++) { cur_path=folderPath + listLibs[i]; LOGD("try to load library '%s'", listLibs[i].c_str()); libHandle=dlopen(cur_path.c_str(), RTLD_LAZY); if (libHandle) { LOGD("Loaded library '%s'", cur_path.c_str()); break; } else { LOGD("CameraWrapperConnector::connectToLib ERROR: cannot dlopen camera wrapper library %s, dlerror=\"%s\"", cur_path.c_str(), dlerror()); } } if (!libHandle) { LOGE("CameraWrapperConnector::connectToLib ERROR: cannot dlopen camera wrapper library"); return CameraActivity::ERROR_CANNOT_OPEN_CAMERA_WRAPPER_LIB; } InitCameraConnectC pInit_C; CloseCameraConnectC pClose_C; GetCameraPropertyC pGetProp_C; SetCameraPropertyC pSetProp_C; ApplyCameraPropertiesC pApplyProp_C; CameraActivity::ErrorCode res; res = getSymbolFromLib(libHandle, (const char*)INIT_CAMERA_SYMBOL_NAME, (void**)(&pInit_C)); if (res) return res; res = getSymbolFromLib(libHandle, CLOSE_CAMERA_SYMBOL_NAME, (void**)(&pClose_C)); if (res) return res; res = getSymbolFromLib(libHandle, GET_CAMERA_PROPERTY_SYMBOL_NAME, (void**)(&pGetProp_C)); if (res) return res; res = getSymbolFromLib(libHandle, SET_CAMERA_PROPERTY_SYMBOL_NAME, (void**)(&pSetProp_C)); if (res) return res; res = getSymbolFromLib(libHandle, APPLY_CAMERA_PROPERTIES_SYMBOL_NAME, (void**)(&pApplyProp_C)); if (res) return res; pInitCameraC = pInit_C; pCloseCameraC = pClose_C; pGetPropertyC = pGetProp_C; pSetPropertyC = pSetProp_C; pApplyPropertiesC = pApplyProp_C; isConnectedToLib=true; return CameraActivity::NO_ERROR; } CameraActivity::ErrorCode CameraWrapperConnector::getSymbolFromLib(void* libHandle, const char* symbolName, void** ppSymbol) { dlerror(); *(void **) (ppSymbol)=dlsym(libHandle, symbolName); const char* error_dlsym_init=dlerror(); if (error_dlsym_init) { LOGE("CameraWrapperConnector::getSymbolFromLib ERROR: cannot get symbol of the function '%s' from the camera wrapper library, dlerror=\"%s\"", symbolName, error_dlsym_init); return CameraActivity::ERROR_CANNOT_GET_FUNCTION_FROM_CAMERA_WRAPPER_LIB; } return CameraActivity::NO_ERROR; } void CameraWrapperConnector::fillListWrapperLibs(const string& folderPath, vector& listLibs) { DIR *dp; struct dirent *ep; dp = opendir (folderPath.c_str()); if (dp != NULL) { while ((ep = readdir (dp))) { const char* cur_name=ep->d_name; if (strstr(cur_name, PREFIX_CAMERA_WRAPPER_LIB)) { listLibs.push_back(cur_name); LOGE("||%s", cur_name); } } (void) closedir (dp); } } std::string CameraWrapperConnector::getDefaultPathLibFolder() { #define BIN_PACKAGE_NAME(x) "org.opencv.lib_v" CVAUX_STR(CV_VERSION_EPOCH) CVAUX_STR(CV_VERSION_MAJOR) "_" x const char* const packageList[] = {BIN_PACKAGE_NAME("armv7a"), OPENCV_ENGINE_PACKAGE}; for (size_t i = 0; i < sizeof(packageList)/sizeof(packageList[0]); i++) { char path[128]; sprintf(path, "/data/data/%s/lib/", packageList[i]); LOGD("Trying package \"%s\" (\"%s\")", packageList[i], path); DIR* dir = opendir(path); if (!dir) { LOGD("Package not found"); continue; } else { closedir(dir); return path; } } return string(); } std::string CameraWrapperConnector::getPathLibFolder() { if (!pathLibFolder.empty()) return pathLibFolder; Dl_info dl_info; if(0 != dladdr((void *)nextFrame, &dl_info)) { LOGD("Library name: %s", dl_info.dli_fname); LOGD("Library base address: %p", dl_info.dli_fbase); const char* libName=dl_info.dli_fname; while( ((*libName)=='/') || ((*libName)=='.') ) libName++; char lineBuf[2048]; FILE* file = fopen("/proc/self/smaps", "rt"); if(file) { while (fgets(lineBuf, sizeof lineBuf, file) != NULL) { //verify that line ends with library name int lineLength = strlen(lineBuf); int libNameLength = strlen(libName); //trim end for(int i = lineLength - 1; i >= 0 && isspace(lineBuf[i]); --i) { lineBuf[i] = 0; --lineLength; } if (0 != strncmp(lineBuf + lineLength - libNameLength, libName, libNameLength)) { //the line does not contain the library name continue; } //extract path from smaps line char* pathBegin = strchr(lineBuf, '/'); if (0 == pathBegin) { LOGE("Strange error: could not find path beginning in lin \"%s\"", lineBuf); continue; } char* pathEnd = strrchr(pathBegin, '/'); pathEnd[1] = 0; LOGD("Libraries folder found: %s", pathBegin); fclose(file); return pathBegin; } fclose(file); LOGE("Could not find library path"); } else { LOGE("Could not read /proc/self/smaps"); } } else { LOGE("Could not get library name and base address"); } return string(); } void CameraWrapperConnector::setPathLibFolder(const string& path) { pathLibFolder=path; } ///////////////////////////////////////////////////////////////////////////////////////////////// CameraActivity::CameraActivity() : camera(0), frameWidth(-1), frameHeight(-1) { } CameraActivity::~CameraActivity() { if (camera != 0) disconnect(); } bool CameraActivity::onFrameBuffer(void* /*buffer*/, int /*bufferSize*/) { LOGD("CameraActivity::onFrameBuffer - empty callback"); return true; } void CameraActivity::disconnect() { CameraWrapperConnector::disconnect(&camera); } bool CameraActivity::isConnected() const { return camera != 0; } CameraActivity::ErrorCode CameraActivity::connect(int cameraId) { ErrorCode rescode = CameraWrapperConnector::connect(cameraId, this, &camera); if (rescode) return rescode; return NO_ERROR; } double CameraActivity::getProperty(int propIdx) { double propVal; ErrorCode rescode = CameraWrapperConnector::getProperty(camera, propIdx, &propVal); if (rescode) return -1; return propVal; } void CameraActivity::setProperty(int propIdx, double value) { CameraWrapperConnector::setProperty(camera, propIdx, value); } void CameraActivity::applyProperties() { frameWidth = -1; frameHeight = -1; CameraWrapperConnector::applyProperties(&camera); frameWidth = getProperty(ANDROID_CAMERA_PROPERTY_FRAMEWIDTH); frameHeight = getProperty(ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT); } int CameraActivity::getFrameWidth() { if (frameWidth <= 0) frameWidth = getProperty(ANDROID_CAMERA_PROPERTY_FRAMEWIDTH); return frameWidth; } int CameraActivity::getFrameHeight() { if (frameHeight <= 0) frameHeight = getProperty(ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT); return frameHeight; } void CameraActivity::setPathLibFolder(const char* path) { CameraWrapperConnector::setPathLibFolder(path); }