set(JASPER_LIBRARIES libjasper)
endif()
-if (ANDROID)
- #android camera support
- set(NativeCamera_DIR "${OpenCV_SOURCE_DIR}/android/native-camera/build")
- FIND_PACKAGE(NativeCamera QUIET)
- if(NativeCamera_FOUND)
- set(HAVE_ANDROID_NATIVE_CAMERA TRUE)
- set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${NativeCamera_LIBS})
- else()
- set(HAVE_ANDROID_NATIVE_CAMERA FALSE)
- message(STATUS "Could NOT find NativeCamera for Android")
- endif()
-endif()
-
#message(STATUS "Graphic libraries: ${PNG_LIBRARIES} ${JPEG_LIBRARIES} ${TIFF_LIBRARIES} ${JASPER_LIBRARIES}")
if(WITH_OPENEXR)
############################### TBB ################################
if (WITH_TBB)
- if (UNIX AND NOT APPLE)
+ if (UNIX AND NOT APPLE AND NOT ANDROID)
PKG_CHECK_MODULES(TBB tbb)
message(STATUS "TBB detected: ${TBBLIB_FOUND}")
endif()
if (NOT HAVE_TBB)
- set(TBB_DEFAULT_INCLUDE_DIRS "/opt/intel/tbb" "/usr/local/include" "/usr/include" "C:/Program Files/Intel/TBB" "C:/Program Files (x86)/Intel/TBB" "C:/Program Files (x86)/TBB")
+ set(TBB_DEFAULT_INCLUDE_DIRS "/opt/intel/tbb" "/usr/local/include" "/usr/include" "C:/Program Files/Intel/TBB" "C:/Program Files (x86)/Intel/TBB" "C:/Program Files (x86)/TBB" "${CMAKE_INSTALL_PREFIX}/include")
find_path(TBB_INCLUDE_DIR "tbb/tbb.h" PATHS ${TBB_DEFAULT_INCLUDE_DIRS} DOC "The path to TBB headers")
if (TBB_INCLUDE_DIR)
endif()
if (APPLE)
set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} libtbb.dylib)
+ elseif (ANDROID)
+ set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} tbbmalloc tbb)
+ add_definitions(-DTBB_USE_GCC_BUILTINS)
elseif (UNIX)
set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} tbb)
elseif (WIN32)
set(CMAKE_LIB_DIRS_CONFIGCMAKE "${LIBRARY_OUTPUT_PATH}")
-if( HAVE_ANDROID_NATIVE_CAMERA )
- set(CMAKE_LIB_DIRS_CONFIGCMAKE ${CMAKE_LIB_DIRS_CONFIGCMAKE} ${NativeCamera_LIB_DIR})
-endif()
-
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/OpenCVConfig.cmake.in" "${CMAKE_BINARY_DIR}/OpenCVConfig.cmake" IMMEDIATE @ONLY)
# --------------------------------------------------------------------------------------------
endif()
message(STATUS " Xine: ${HAVE_XINE}")
if(ANDROID)
-message(STATUS " AndroidNativeCamera: ${HAVE_ANDROID_NATIVE_CAMERA}")
+message(STATUS " AndroidNativeCamera: build")
endif()
endif() #if(UNIX AND NOT APPLE)
else()\r
#libraries order is very important because linker from Android NDK is one-pass linker\r
set(OPENCV_LIB_COMPONENTS opencv_contrib opencv_calib3d opencv_objdetect opencv_features2d opencv_imgproc opencv_video opencv_highgui opencv_ml opencv_legacy opencv_flann opencv_core )\r
+ IF (NOT @BUILD_SHARED_LIBS@)\r
+ set(OPENCV_LIB_COMPONENTS opencv_androidcamera ${OPENCV_LIB_COMPONENTS})\r
+ ENDIF()\r
endif()\r
\r
SET(OpenCV_LIBS "")\r
\r
ENDIF(NOT @BUILD_SHARED_LIBS@)\r
\r
+# ======================================================\r
+# Android camera helper macro\r
+# ======================================================\r
+IF (ANDROID)\r
+ macro( COPY_NATIVE_CAMERA_LIBS target )\r
+ get_target_property(target_location ${target} LOCATION)\r
+ get_filename_component(target_location "${target_location}" PATH)\r
+ file(GLOB camera_wrappers "${OpenCV_LIB_DIR}/libnative_camera_r*.so")\r
+ foreach(wrapper ${camera_wrappers})\r
+ ADD_CUSTOM_COMMAND(\r
+ TARGET ${target}\r
+ POST_BUILD\r
+ COMMAND ${CMAKE_COMMAND} -E copy "${wrapper}" "${target_location}"\r
+ )\r
+ endforeach()\r
+ endmacro()\r
+ENDIF(ANDROID)\r
\r
# ======================================================\r
# Version variables:\r
#-L${LIBCPP_LINK_DIR} -lstdc++ -lsupc++
#Also, this is *required* to use the following linker flags that routes around
#a CPU bug in some Cortex-A8 implementations:
-set( LINKER_FLAGS "-Wl,--fix-cortex-a8 -L${STL_LIBRARIES_PATH} -lstdc++ -lsupc++ " )
+set( LINKER_FLAGS "-Wl,--fix-cortex-a8 -L${STL_LIBRARIES_PATH} -L${CMAKE_INSTALL_PREFIX}/lib -lstdc++ -lsupc++ " )
set( NO_UNDEFINED ON CACHE BOOL "Don't all undefined symbols" )
if( NO_UNDEFINED )
if(ANDROID_API_LEVEL LESS 8)
ADD_DEFINITIONS(-DGTEST_HAS_CLONE=0)
endif()
+
+ add_subdirectory(androidcamera)
endif()
add_subdirectory(calib3d)
--- /dev/null
+IF(NOT ANDROID)
+ MESSAGE( FATAL_ERROR "This project is for ANDROID only" )
+ENDIF()
+
+if (BUILD_ANDROID_CAMERA_WRAPPER)
+ add_subdirectory(camera_wrapper)
+endif()
+
+project(opencv_androidcamera)
+
+INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/camera_wrapper )
+SET( LIBRARY_DEPS ${LIBRARY_DEPS} log dl )
+
+SET( the_target opencv_androidcamera )
+
+ADD_LIBRARY( ${the_target} STATIC src/camera_activity.cpp )
+
+if (BUILD_SHARED_LIBS)
+ add_definitions(-DCVAPI_EXPORTS)
+endif()
+
+TARGET_LINK_LIBRARIES( ${the_target} ${LIBRARY_DEPS} )
+
+SET_TARGET_PROPERTIES(${the_target} PROPERTIES
+ DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}"
+ OUTPUT_NAME "${the_target}${OPENCV_DLLVERSION}"
+ DEFINE_SYMBOL "CVAPI_EXPORTS"
+ ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}
+ RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}
+ )
+
+IF (NOT BUILD_SHARED_LIBS)
+ install(TARGETS ${the_target}
+ RUNTIME DESTINATION bin COMPONENT main
+ ARCHIVE DESTINATION lib COMPONENT main
+ LIBRARY DESTINATION lib COMPONENT main
+ )
+ENDIF()
+
+file(GLOB camera_wrappers "${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/lib/libnative_camera_r*.so")
+
+foreach(wrapper ${camera_wrappers})
+ ADD_CUSTOM_COMMAND(
+ TARGET ${the_target}
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy "${wrapper}" "${LIBRARY_OUTPUT_PATH}"
+ )
+endforeach()
\ No newline at end of file
--- /dev/null
+#define USE_RECORDING_INSTEAD_PREVIEW 0
+
+#if !defined(ANDROID_r2_2_2) && !defined(ANDROID_r2_3_3) && !defined(ANDROID_r3_0_1)
+#error unsupported version of Android
+#endif
+
+#include <camera/CameraHardwareInterface.h>
+#include "camera_wrapper.h"
+#include "../camera_wrapper_connector/camera_properties.h"
+#include <string>
+
+using namespace android;
+
+void debugShowFPS()
+{
+ static int mFrameCount = 0;
+ static int mLastFrameCount = 0;
+ static nsecs_t mLastFpsTime = systemTime();;
+ static float mFps = 0;
+
+ mFrameCount++;
+
+ if ( ( mFrameCount % 30 ) == 0 ) {
+ nsecs_t now = systemTime();
+ nsecs_t diff = now - mLastFpsTime;
+ if (diff==0)
+ return;
+
+ mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
+ mLastFpsTime = now;
+ mLastFrameCount = mFrameCount;
+ LOGI("####### [%d] Frames, %f FPS", mFrameCount, mFps);
+ }
+}
+
+class CameraHandler: public CameraListener
+{
+protected:
+ sp<Camera> camera;
+ CameraCallback cameraCallback;
+ CameraParameters params;
+ void* userData;
+ int cameraId;
+
+ bool isEmptyCameraCallbackReported;
+ virtual void doCall(void* buffer, size_t bufferSize)
+ {
+ if (cameraCallback == 0)
+ {
+ if (!isEmptyCameraCallbackReported)
+ LOGE("Camera callback is empty!");
+
+ isEmptyCameraCallbackReported = true;
+ return;
+ }
+
+ bool res = (*cameraCallback)(buffer, bufferSize, userData);
+
+ if(!res) closeCameraConnect();
+ }
+
+ virtual void doCall(const sp<IMemory>& dataPtr)
+ {
+ LOGI("doCall started");
+
+ if (dataPtr == NULL)
+ {
+ LOGE("CameraBuffer: dataPtr==NULL");
+ return;
+ }
+
+ size_t size = dataPtr->size();
+ if (size <= 0)
+ {
+ LOGE("CameraBuffer: IMemory object is of zero size");
+ return;
+ }
+
+ unsigned char* buffer = (unsigned char *)dataPtr->pointer();
+ if (!buffer)
+ {
+ LOGE("CameraBuffer: Buffer pointer is invalid");
+ return;
+ }
+
+ doCall(buffer, size);
+ }
+
+public:
+ CameraHandler(CameraCallback callback = 0, void* _userData = 0):cameraCallback(callback), userData(_userData), cameraId(0), isEmptyCameraCallbackReported(false) {}
+ virtual ~CameraHandler()
+ {
+ LOGW("CameraHandler destructor is called!");
+ }
+
+ virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2)
+ {
+ LOGE("Notify cb: %d %d %d\n", msgType, ext1, ext2);
+#if 0
+ if ( msgType & CAMERA_MSG_FOCUS )
+ LOGE("AutoFocus %s in %llu us\n", (ext1) ? "OK" : "FAIL", timevalDelay(&autofocus_start));
+
+ if ( msgType & CAMERA_MSG_SHUTTER )
+ LOGE("Shutter done in %llu us\n", timeval_delay(&picture_start));
+#endif
+ }
+
+ virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr)
+ {
+ debugShowFPS();
+
+ if ( msgType & CAMERA_MSG_PREVIEW_FRAME )
+ {
+ doCall(dataPtr);
+ return;
+ }
+
+ if (msgType != CAMERA_MSG_PREVIEW_FRAME)
+ LOGE("Recieved not CAMERA_MSG_PREVIEW_FRAME message %d", (int) msgType);
+
+ if ( msgType & CAMERA_MSG_RAW_IMAGE )
+ LOGE("Unexpected data format: RAW\n");
+
+ if (msgType & CAMERA_MSG_POSTVIEW_FRAME)
+ LOGE("Unexpected data format: Postview frame\n");
+
+ if (msgType & CAMERA_MSG_COMPRESSED_IMAGE )
+ LOGE("Unexpected data format: JPEG");
+ }
+
+ virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
+ {
+ static uint32_t count = 0;
+ count++;
+
+ LOGE("Recording cb: %d %lld %%p Offset:%%d Stride:%%d\n", msgType, timestamp);
+
+ if (dataPtr == NULL)
+ {
+ LOGE("postDataTimestamp: dataPtr IS ZERO -- returning");
+ camera->releaseRecordingFrame(dataPtr);
+ LOGE("postDataTimestamp: camera->releaseRecordingFrame(dataPtr) is done");
+ return;
+ }
+
+ uint8_t *ptr = (uint8_t*) dataPtr->pointer();
+ if (ptr)
+ LOGE("VID_CB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], ptr[8], ptr[9]);
+ else
+ LOGE("postDataTimestamp: Ptr is zero");
+
+ camera->releaseRecordingFrame(dataPtr);
+ }
+
+ static CameraHandler* initCameraConnect(const CameraCallback& callback, int cameraId, void* userData, CameraParameters* prevCameraParameters);
+ void closeCameraConnect();
+ double getProperty(int propIdx);
+ void setProperty(int propIdx, double value);
+ static void applyProperties(CameraHandler** ppcameraHandler);
+
+ std::string cameraPropertySupportedPreviewSizesString;
+};
+
+
+CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, int cameraId, void* userData, CameraParameters* prevCameraParameters)
+{
+// if (camera != NULL)
+// {
+// LOGE("initCameraConnect: camera have been connected already");
+// return false;
+// }
+
+ sp<Camera> camera = 0;
+
+#ifdef ANDROID_r2_2_2
+ camera = Camera::connect();
+#endif
+#ifdef ANDROID_r2_3_3
+ camera = Camera::connect(cameraId);
+#endif
+
+ if ( NULL == camera.get() )
+ {
+ LOGE("initCameraConnect: Unable to connect to CameraService\n");
+ return 0;
+ }
+
+ CameraHandler* handler = new CameraHandler(callback, userData);
+ camera->setListener(handler);
+
+ handler->camera = camera;
+ handler->cameraId=cameraId;
+#if 1
+ //setting paramers from previous camera handler
+ if (prevCameraParameters != NULL) {
+ camera->setParameters(prevCameraParameters->flatten());
+ }
+#endif
+ handler->params.unflatten(camera->getParameters());
+
+
+ LOGD("Supported Cameras: %s", handler->params.get("camera-indexes"));
+ LOGD("Supported Picture Sizes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES));
+ LOGD("Supported Picture Formats: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS));
+ LOGD("Supported Preview Sizes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES));
+ LOGD("Supported Preview Formats: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS));
+ LOGD("Supported Preview Frame Rates: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES));
+ LOGD("Supported Thumbnail Sizes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES));
+ LOGD("Supported Whitebalance Modes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE));
+ LOGD("Supported Effects: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_EFFECTS));
+ LOGD("Supported Scene Modes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_SCENE_MODES));
+ LOGD("Supported Focus Modes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES));
+ LOGD("Supported Antibanding Options: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_ANTIBANDING));
+ LOGD("Supported Flash Modes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES));
+
+
+ //TODO: check if yuv420i format available. Set this format as preview format.
+
+#if USE_RECORDING_INSTEAD_PREVIEW
+ status_t err = camera->setPreviewDisplay(sp<ISurface>(NULL /*new DummySurface1*/));
+#endif
+
+ ////ATTENTION: switching between two versions: with and without copying memory inside Android OS
+ //// see the method CameraService::Client::copyFrameAndPostCopiedFrame and where it is used
+#if 1
+ camera->setPreviewCallbackFlags( FRAME_CALLBACK_FLAG_ENABLE_MASK | FRAME_CALLBACK_FLAG_COPY_OUT_MASK);//with copy
+#else
+ camera->setPreviewCallbackFlags( FRAME_CALLBACK_FLAG_ENABLE_MASK );//without copy
+#endif
+
+#if USE_RECORDING_INSTEAD_PREVIEW
+ status_t resStart = camera->startRecording();
+#else
+ status_t resStart = camera->startPreview();
+#endif
+
+ if (resStart != 0)
+ {
+ handler->closeCameraConnect();
+ handler = 0;
+ }
+ return handler;
+}
+
+void CameraHandler::closeCameraConnect()
+{
+ if (camera == NULL)
+ {
+ LOGI("... camera is NULL");
+ return;
+ }
+
+ //TODO: ATTENTION! should we do it ALWAYS???
+#if USE_RECORDING_INSTEAD_PREVIEW
+ camera->stopRecording();
+#else
+ camera->stopPreview();
+#endif
+
+ camera->disconnect();
+ camera.clear();
+
+ camera=NULL;
+ // ATTENTION!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // When we set
+ // camera=NULL
+ // above, the pointed instance of android::Camera object is destructed,
+ // since this member `camera' has type android::sp<Camera> (android smart pointer template class),
+ // and this is the only pointer to it.
+ //
+ // BUT this instance of CameraHandler is set as a listener for that android::Camera object
+ // (see the function CameraHandler::initCameraConnect above),
+ // so this instance of CameraHandler is pointed from that android::Camera object as
+ // sp<CameraListener> mListener
+ // and there is no other android smart pointers to this.
+ //
+ // It means, when that instance of the android::Camera object is destructed,
+ // it calls destructor for this CameraHandler instance too.
+ //
+ // So, this line `camera=NULL' causes to the call `delete this'
+ // (see destructor of the template class android::sp)
+ //
+ // So, we must not call `delete this' after the line, since it just has been called indeed
+}
+
+double CameraHandler::getProperty(int propIdx)
+{
+ switch (propIdx)
+ {
+ case ANDROID_CAMERA_PROPERTY_FRAMEWIDTH:
+ {
+ int w,h;
+ params.getPreviewSize(&w,&h);
+ return w;
+ }
+ case ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT:
+ {
+ int w,h;
+ params.getPreviewSize(&w,&h);
+ return h;
+ }
+ case ANDROID_CAMERA_PROPERTY_SUPPORTED_PREVIEW_SIZES_STRING:
+ {
+ cameraPropertySupportedPreviewSizesString=params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES);
+ double res;
+ memset(&res, 0, sizeof(res));
+ (*( (void**)&res ))= (void*)( cameraPropertySupportedPreviewSizesString.c_str() );
+
+ return res;
+ }
+
+ };
+ return -1;
+}
+
+void CameraHandler::setProperty(int propIdx, double value)
+{
+ switch (propIdx)
+ {
+ case ANDROID_CAMERA_PROPERTY_FRAMEWIDTH:
+ {
+ int w,h;
+ params.getPreviewSize(&w,&h);
+ w = (int)value;
+ params.setPreviewSize(w,h);
+ }
+ break;
+ case ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT:
+ {
+ int w,h;
+ params.getPreviewSize(&w,&h);
+ h = (int)value;
+ params.setPreviewSize(w,h);
+ }
+ break;
+ };
+}
+
+void CameraHandler::applyProperties(CameraHandler** ppcameraHandler)
+{
+ LOGD("CameraHandler::applyProperties()");
+ CameraHandler* previousCameraHandler=*ppcameraHandler;
+ CameraParameters curCameraParameters(previousCameraHandler->params.flatten());
+
+ CameraCallback cameraCallback=previousCameraHandler->cameraCallback;
+ void* userData=previousCameraHandler->userData;
+ int cameraId=previousCameraHandler->cameraId;
+
+ LOGD("CameraHandler::applyProperties(): before previousCameraHandler->closeCameraConnect");
+ previousCameraHandler->closeCameraConnect();
+ LOGD("CameraHandler::applyProperties(): after previousCameraHandler->closeCameraConnect");
+
+
+ LOGD("CameraHandler::applyProperties(): before initCameraConnect");
+ CameraHandler* handler=initCameraConnect(cameraCallback, cameraId, userData, &curCameraParameters);
+ LOGD("CameraHandler::applyProperties(): after initCameraConnect, handler=0x%x", (int)handler);
+ if (handler == NULL) {
+ LOGE("ERROR in applyProperties --- cannot reinit camera");
+ handler=initCameraConnect(cameraCallback, cameraId, userData, NULL);
+ LOGD("CameraHandler::applyProperties(): repeate initCameraConnect after ERROR, handler=0x%x", (int)handler);
+ if (handler == NULL) {
+ LOGE("ERROR in applyProperties --- cannot reinit camera AGAIN --- cannot do anything else");
+ }
+ }
+ (*ppcameraHandler)=handler;
+}
+
+
+extern "C" {
+
+void* initCameraConnectC(void* callback, int cameraId, void* userData)
+{
+ return CameraHandler::initCameraConnect((CameraCallback)callback, cameraId, userData, NULL);
+}
+
+void closeCameraConnectC(void** camera)
+{
+ CameraHandler** cc = (CameraHandler**)camera;
+ (*cc)->closeCameraConnect();
+ *cc = 0;
+}
+
+double getCameraPropertyC(void* camera, int propIdx)
+{
+ return ((CameraHandler*)camera)->getProperty(propIdx);
+}
+
+void setCameraPropertyC(void* camera, int propIdx, double value)
+{
+ ((CameraHandler*)camera)->setProperty(propIdx,value);
+}
+
+void applyCameraPropertiesC(void** camera)
+{
+ CameraHandler::applyProperties((CameraHandler**)camera);
+}
+
+}
--- /dev/null
+enum CameraWrapperErrorCode {
+ ERROR_NATIVE_CAMERA_WRAPPER_NOERROR = 0,
+ ERROR_NATIVE_CAMERA_WRAPPER_CANNOT_FIND_CLASS = 1,
+ ERROR_NATIVE_CAMERA_WRAPPER_CANNOT_FIND_FIELD = 2,
+ ERROR_NATIVE_CAMERA_WRAPPER_CANNOT_SET_PREVIEW_DISPLAY = 3
+};
+
+typedef bool (*CameraCallback)(void* buffer, size_t bufferSize, void* userData);
+
+typedef void* (*InitCameraConnectC)(void* cameraCallback, int cameraId, void* userData);
+typedef void (*CloseCameraConnectC)(void**);
+typedef double (*GetCameraPropertyC)(void* camera, int propIdx);
+typedef void (*SetCameraPropertyC)(void* camera, int propIdx, double value);
+typedef void (*ApplyCameraPropertiesC)(void** camera);
+
+extern "C"
+{
+void* initCameraConnectC(void* cameraCallback, int cameraId, void* userData);
+void closeCameraConnectC(void**);
+double getCameraPropertyC(void* camera, int propIdx);
+void setCameraPropertyC(void* camera, int propIdx, double value);
+void applyCameraPropertiesC(void** camera);
+}
+
--- /dev/null
+#ifndef _CAMERAACTIVITY_H_
+#define _CAMERAACTIVITY_H_
+
+#include <camera_properties.h>
+//#include <opencv2/core/core.hpp>
+
+class CameraActivity
+{
+public:
+ enum ErrorCode {
+ NO_ERROR=0,
+ ERROR_WRONG_FRAME_SIZE,
+ ERROR_WRONG_POINTER_CAMERA_WRAPPER,
+ ERROR_CAMERA_CONNECTED,
+ ERROR_CANNOT_OPEN_CAMERA_WRAPPER_LIB,
+ ERROR_CANNOT_GET_FUNCTION_FROM_CAMERA_WRAPPER_LIB,
+ ERROR_CANNOT_INITIALIZE_CONNECTION,
+ ERROR_ISNT_CONNECTED,
+ ERROR_JAVA_VM_CANNOT_GET_CLASS,
+ ERROR_JAVA_VM_CANNOT_GET_FIELD,
+ ERROR_CANNOT_SET_PREVIEW_DISPLAY,
+
+ ERROR_UNKNOWN=255
+ };
+
+ CameraActivity();
+ virtual ~CameraActivity();
+ virtual bool onFrameBuffer(void* buffer, int bufferSize);
+
+ ErrorCode connect(int cameraId = 0);
+ void disconnect();
+ bool isConnected() const;
+
+ double getProperty(int propIdx);
+ void setProperty(int propIdx, double value);
+ void applyProperties();
+
+ int getFrameWidth();
+ int getFrameHeight();
+
+ static void setPathLibFolder(const char* path);
+private:
+ void* camera;
+ int frameWidth;
+ int frameHeight;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#ifndef CAMERA_PROPERTIES_H
+#define CAMERA_PROPERTIES_H
+
+enum {
+ ANDROID_CAMERA_PROPERTY_FRAMEWIDTH = 0,
+ ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT = 1,
+ ANDROID_CAMERA_PROPERTY_SUPPORTED_PREVIEW_SIZES_STRING = 2
+};
+
+#endif // CAMERA_PROPERTIES_H
--- /dev/null
+#include <dlfcn.h>
+#include <android/log.h>
+#include <string>
+#include <vector>
+#include "camera_activity.hpp"
+#include "camera_wrapper.h"
+
+#define LOG_TAG "CAMERA_ACTIVITY"
+#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__))
+#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+
+///////
+// Debug
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+
+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 CameraActivity::ErrorCode connectToLib();
+ static CameraActivity::ErrorCode getSymbolFromLib(void * libHandle, const char* symbolName, void** ppSymbol);
+ static void fillListWrapperLibs(const string& folderPath, vector<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;
+#define DEFAULT_WRAPPER_PACKAGE_NAME "com.NativeCamera"
+#define DEFAULT_PATH_LIB_FOLDER "/data/data/" DEFAULT_WRAPPER_PACKAGE_NAME "/lib/"
+
+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;
+ }
+
+ *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();
+ LOGD("CameraWrapperConnector::connectToLib: folderPath=%s", folderPath.c_str());
+
+ vector<string> listLibs;
+ fillListWrapperLibs(folderPath, listLibs);
+
+ 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<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::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);
+
+ char addrBuf[18];
+ sprintf(addrBuf, "%x-", dl_info.dli_fbase);
+ int addrLength = strlen(addrBuf);
+
+ char lineBuf[2048];
+ FILE* file = fopen("/proc/self/smaps", "rt");
+
+ if(file)
+ {
+ while (fgets(lineBuf, sizeof lineBuf, file) != NULL)
+ {
+ if(0 == strncmp(lineBuf, addrBuf, addrLength))
+ {
+ //verify that line ends with library name
+ int lineLength = strlen(lineBuf);
+ int libNameLength = strlen(dl_info.dli_fname);
+
+ //trim end
+ for(int i = lineLength - 1; i >= 0 && isspace(lineBuf[i]); --i)
+ {
+ lineBuf[i] = 0;
+ --lineLength;
+ }
+
+ if (0 != strncmp(lineBuf + lineLength - libNameLength, dl_info.dli_fname, libNameLength))
+ {
+ LOGE("Strange error: line \"%s\" does not ends with library name %s", lineBuf, dl_info.dli_fname);
+ 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 DEFAULT_PATH_LIB_FOLDER ;
+}
+
+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);
+}
+
+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);
+}
endif()
endif(APPLE)
-if(HAVE_ANDROID_NATIVE_CAMERA)
+if(ANDROID)
+ include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../androidcamera/include")
set(highgui_srcs ${highgui_srcs} src/cap_android.cpp)
add_definitions(-DHAVE_ANDROID_NATIVE_CAMERA)
+ set(HIGHGUI_LIBRARIES ${HIGHGUI_LIBRARIES} opencv_androidcamera)
endif()
if(COMMAND get_module_external_sources)
add_dependencies(${the_target} zlib)
endif()
+if(ANDROID)
+ add_dependencies(${the_target} opencv_androidcamera)
+endif()
+
#message(STATUS "GRFMT: ${GRFMT_LIBS}")
#message(STATUS "HIGHGUI_LIBS: ${HIGHGUI_LIBRARIES}")
#message(STATUS "OPENCV_LIBS: ${OPENCV_LINKER_LIBS}")
"${CMAKE_CURRENT_BINARY_DIR}")
set(test_deps opencv_ts opencv_highgui opencv_imgproc)
+ if(ANDROID)
+ set(test_deps ${test_deps} opencv_androidcamera)
+ endif()
foreach(d ${test_deps})
if(${d} MATCHES "opencv_")
#include <opencv2/imgproc/imgproc.hpp>
#include <pthread.h>
#include <android/log.h>
-#include "camera_activity.h"
+#include <camera_activity.hpp>
#if !defined(LOGD) && !defined(LOGI) && !defined(LOGE)
#define LOG_TAG "CV_CAP"