opencv/modules/androidcamera/src/camera_activity.cpp
Andrey Kamaev 2a6fb2867e Remove all using directives for STL namespace and members
Made all STL usages explicit to be able automatically find all usages of
particular class or function.
2013-02-25 15:04:17 +04:00

446 lines
13 KiB
C++

#include <dlfcn.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <android/log.h>
#include <cctype>
#include <string>
#include <vector>
#include <algorithm>
#include <opencv2/core/version.hpp>
#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 <stdio.h>
#include <sys/types.h>
#include <dirent.h>
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 std::string& folderPath, std::vector<std::string>& 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();
std::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());
std::vector<std::string> listLibs;
fillListWrapperLibs(folderPath, listLibs);
std::sort(listLibs.begin(), listLibs.end(), std::greater<std::string>());
void * libHandle=0;
std::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 std::string& folderPath, std::vector<std::string>& 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 std::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 std::string();
}
void CameraWrapperConnector::setPathLibFolder(const std::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);
}