1 #if !defined(ANDROID_r2_2_0) && !defined(ANDROID_r2_3_3) && !defined(ANDROID_r3_0_1) && !defined(ANDROID_r4_0_0) && !defined(ANDROID_r4_0_3)
2 # error Building camera wrapper for your version of Android is not supported by OpenCV. You need to modify OpenCV sources in order to compile camera wrapper for your version of Android.
5 #include <camera/Camera.h>
6 #include <camera/CameraParameters.h>
8 #if defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3)
9 # include <system/camera.h>
10 #endif //defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3)
12 #include "camera_wrapper.h"
13 #include "../include/camera_properties.h"
15 #if defined(ANDROID_r3_0_1) || defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3)
16 //Include SurfaceTexture.h file with the SurfaceTexture class
17 # include <gui/SurfaceTexture.h>
18 # define MAGIC_OPENCV_TEXTURE_ID (0x10)
19 #else // defined(ANDROID_r3_0_1) || defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3)
20 //TODO: This is either 2.2 or 2.3. Include the headers for ISurface.h access
21 # include <surfaceflinger/ISurface.h>
22 #endif // defined(ANDROID_r3_0_1) || defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3)
26 //undef logging macro from /system/core/libcutils/loghack.h
45 #include <android/log.h>
46 #define CAMERA_LOG_TAG "OpenCV_NativeCamera"
47 #define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, CAMERA_LOG_TAG, __VA_ARGS__))
48 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, CAMERA_LOG_TAG, __VA_ARGS__))
49 #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, CAMERA_LOG_TAG, __VA_ARGS__))
50 #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, CAMERA_LOG_TAG, __VA_ARGS__))
52 using namespace android;
56 static int mFrameCount = 0;
57 static int mLastFrameCount = 0;
58 static nsecs_t mLastFpsTime = systemTime();
59 static float mFps = 0;
63 if (( mFrameCount % 30 ) != 0)
66 nsecs_t now = systemTime();
67 nsecs_t diff = now - mLastFpsTime;
72 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
74 mLastFrameCount = mFrameCount;
75 LOGI("### Camera FPS ### [%d] Frames, %.2f FPS", mFrameCount, mFps);
78 class CameraHandler: public CameraListener
83 CameraParameters params;
84 CameraCallback cameraCallback;
87 int emptyCameraCallbackReported;
89 void doCall(void* buffer, size_t bufferSize)
91 if (cameraCallback == 0)
93 if (!emptyCameraCallbackReported)
94 LOGE("CameraHandler::doCall(void*, size_t): Camera callback is empty!");
96 emptyCameraCallbackReported++;
100 bool res = (*cameraCallback)(buffer, bufferSize, userData);
104 LOGE("CameraHandler::doCall(void*, size_t): cameraCallback returns false (camera connection will be closed)");
105 closeCameraConnect();
110 void doCall(const sp<IMemory>& dataPtr)
114 LOGE("CameraHandler::doCall(const sp<IMemory>&): dataPtr==NULL (no frame to handle)");
118 size_t size = dataPtr->size();
121 LOGE("CameraHandler::doCall(const sp<IMemory>&): IMemory object is of zero size");
125 void* buffer = (void *)dataPtr->pointer();
128 LOGE("CameraHandler::doCall(const sp<IMemory>&): Buffer pointer is NULL");
132 doCall(buffer, size);
135 virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
137 static uint32_t count = 0;
140 LOGE("Recording cb: %d %lld %%p Offset:%%d Stride:%%d\n", msgType, timestamp);
144 LOGE("postDataTimestamp: dataPtr IS ZERO -- returning");
145 camera->releaseRecordingFrame(dataPtr);
146 LOGE("postDataTimestamp: camera->releaseRecordingFrame(dataPtr) is done");
150 uint8_t *ptr = (uint8_t*) dataPtr->pointer();
152 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]);
154 LOGE("postDataTimestamp: Ptr is zero");
156 camera->releaseRecordingFrame(dataPtr);
160 CameraHandler(CameraCallback callback = 0, void* _userData = 0):
162 cameraCallback(callback),
164 emptyCameraCallbackReported(0)
166 LOGD("Instantiated new CameraHandler (%p, %p)", callback, _userData);
169 virtual ~CameraHandler()
171 LOGD("CameraHandler destructor is called");
174 virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2)
176 LOGE("CameraHandler::Notify: msgType=%d ext1=%d ext2=%d\n", msgType, ext1, ext2);
178 if ( msgType & CAMERA_MSG_FOCUS )
179 LOGE("CameraHandler::Notify AutoFocus %s in %llu us\n", (ext1) ? "OK" : "FAIL", timevalDelay(&autofocus_start));
181 if ( msgType & CAMERA_MSG_SHUTTER )
182 LOGE("CameraHandler::Notify Shutter done in %llu us\n", timeval_delay(&picture_start));
186 virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr
187 #if defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3)
188 ,camera_frame_metadata_t* metadata
194 if ( msgType & CAMERA_MSG_PREVIEW_FRAME )
200 //if (msgType != CAMERA_MSG_PREVIEW_FRAME)
201 //LOGE("CameraHandler::postData Recieved message %d is not equal to CAMERA_MSG_PREVIEW_FRAME (%d)", (int) msgType, CAMERA_MSG_PREVIEW_FRAME);
203 if ( msgType & CAMERA_MSG_RAW_IMAGE )
204 LOGE("CameraHandler::postData Unexpected data format: RAW\n");
206 if (msgType & CAMERA_MSG_POSTVIEW_FRAME)
207 LOGE("CameraHandler::postData Unexpected data format: Postview frame\n");
209 if (msgType & CAMERA_MSG_COMPRESSED_IMAGE )
210 LOGE("CameraHandler::postData Unexpected data format: JPEG");
213 static CameraHandler* initCameraConnect(const CameraCallback& callback, int cameraId, void* userData, CameraParameters* prevCameraParameters);
214 void closeCameraConnect();
215 double getProperty(int propIdx);
216 void setProperty(int propIdx, double value);
217 static void applyProperties(CameraHandler** ppcameraHandler);
219 std::string cameraPropertySupportedPreviewSizesString;
220 std::string cameraPropertyPreviewFormatString;
224 CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, int cameraId, void* userData, CameraParameters* prevCameraParameters)
226 LOGD("CameraHandler::initCameraConnect(%p, %d, %p, %p)", callback, cameraId, userData, prevCameraParameters);
228 sp<Camera> camera = 0;
230 #ifdef ANDROID_r2_2_0
231 camera = Camera::connect();
233 /* This is 2.3 or higher. The connect method has cameraID parameter */
234 camera = Camera::connect(cameraId);
237 if ( 0 == camera.get() )
239 LOGE("initCameraConnect: Unable to connect to CameraService\n");
243 CameraHandler* handler = new CameraHandler(callback, userData);
244 camera->setListener(handler);
246 handler->camera = camera;
247 handler->cameraId = cameraId;
249 if (prevCameraParameters != 0)
251 LOGI("initCameraConnect: Setting paramers from previous camera handler");
252 camera->setParameters(prevCameraParameters->flatten());
253 handler->params.unflatten(prevCameraParameters->flatten());
257 android::String8 params_str = camera->getParameters();
258 LOGI("initCameraConnect: [%s]", params_str.string());
260 handler->params.unflatten(params_str);
262 LOGD("Supported Cameras: %s", handler->params.get("camera-indexes"));
263 LOGD("Supported Picture Sizes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES));
264 LOGD("Supported Picture Formats: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS));
265 LOGD("Supported Preview Sizes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES));
266 LOGD("Supported Preview Formats: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS));
267 LOGD("Supported Preview Frame Rates: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES));
268 LOGD("Supported Thumbnail Sizes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES));
269 LOGD("Supported Whitebalance Modes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE));
270 LOGD("Supported Effects: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_EFFECTS));
271 LOGD("Supported Scene Modes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_SCENE_MODES));
272 LOGD("Supported Focus Modes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES));
273 LOGD("Supported Antibanding Options: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_ANTIBANDING));
274 LOGD("Supported Flash Modes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES));
277 //check if yuv420sp format available. Set this format as preview format.
278 const char* available_formats = handler->params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS);
279 if (available_formats != 0)
281 const char* format_to_set = 0;
282 const char* pos = available_formats;
283 const char* ptr = pos;
286 while(*ptr != 0 && *ptr != ',') ++ptr;
289 if (0 == strncmp(pos, "yuv420sp", ptr - pos))
291 format_to_set = "yuv420sp";
294 if (0 == strncmp(pos, "yvu420sp", ptr - pos))
295 format_to_set = "yvu420sp";
302 if (0 != format_to_set)
304 handler->params.setPreviewFormat(format_to_set);
306 status_t resParams = handler->camera->setParameters(handler->params.flatten());
309 LOGE("initCameraConnect: failed to set preview format to %s", format_to_set);
311 LOGD("initCameraConnect: preview format is set to %s", format_to_set);
316 const char* available_focus_modes = handler->params.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES);
317 if (available_focus_modes != 0)
319 // find auto focus mode
320 if (strstr(available_focus_modes, "auto") != NULL)
322 handler->params.set(CameraParameters::KEY_FOCUS_MODE, CameraParameters::FOCUS_MODE_AUTO);
328 #if defined(ANDROID_r2_2_0)
329 pdstatus = camera->setPreviewDisplay(sp<ISurface>(0 /*new DummySurface*/));
331 LOGE("initCameraConnect: failed setPreviewDisplay(0) call; camera migth not work correctly on some devices");
332 #elif defined(ANDROID_r2_3_3)
333 /* Do nothing in case of 2.3 for now */
335 #elif defined(ANDROID_r3_0_1) || defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3)
336 sp<SurfaceTexture> surfaceTexture = new SurfaceTexture(MAGIC_OPENCV_TEXTURE_ID);
337 pdstatus = camera->setPreviewTexture(surfaceTexture);
339 LOGE("initCameraConnect: failed setPreviewTexture call; camera migth not work correctly");
342 #if !(defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3))
344 ////ATTENTION: switching between two versions: with and without copying memory inside Android OS
345 //// see the method CameraService::Client::copyFrameAndPostCopiedFrame and where it is used
346 camera->setPreviewCallbackFlags( FRAME_CALLBACK_FLAG_ENABLE_MASK | FRAME_CALLBACK_FLAG_COPY_OUT_MASK);//with copy
348 camera->setPreviewCallbackFlags( FRAME_CALLBACK_FLAG_ENABLE_MASK );//without copy
351 camera->setPreviewCallbackFlags( CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK | CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK);//with copy
352 #endif //!(defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3))
354 status_t resStart = camera->startPreview();
358 LOGE("initCameraConnect: startPreview() fails. Closing camera connection...");
359 handler->closeCameraConnect();
366 void CameraHandler::closeCameraConnect()
370 LOGI("... camera is already NULL");
374 camera->stopPreview();
375 camera->disconnect();
379 // ATTENTION!!!!!!!!!!!!!!!!!!!!!!!!!!
382 // above, the pointed instance of android::Camera object is destructed,
383 // since this member `camera' has type android::sp<Camera> (android smart pointer template class),
384 // and this is the only pointer to it.
386 // BUT this instance of CameraHandler is set as a listener for that android::Camera object
387 // (see the function CameraHandler::initCameraConnect above),
388 // so this instance of CameraHandler is pointed from that android::Camera object as
389 // sp<CameraListener> mListener
390 // and there is no other android smart pointers to this.
392 // It means, when that instance of the android::Camera object is destructed,
393 // it calls destructor for this CameraHandler instance too.
395 // So, this line `camera=NULL' causes to the call `delete this'
396 // (see destructor of the template class android::sp)
398 // So, we must not call `delete this' after the line, since it just has been called indeed
401 double CameraHandler::getProperty(int propIdx)
403 LOGD("CameraHandler::getProperty(%d)", propIdx);
407 case ANDROID_CAMERA_PROPERTY_FRAMEWIDTH:
410 params.getPreviewSize(&w, &h);
413 case ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT:
416 params.getPreviewSize(&w, &h);
419 case ANDROID_CAMERA_PROPERTY_SUPPORTED_PREVIEW_SIZES_STRING:
421 cameraPropertySupportedPreviewSizesString = params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES);
422 union {const char* str;double res;} u;
423 memset(&u.res, 0, sizeof(u.res));
424 u.str = cameraPropertySupportedPreviewSizesString.c_str();
428 case ANDROID_CAMERA_PROPERTY_PREVIEW_FORMAT_STRING:
430 const char* fmt = params.get(CameraParameters::KEY_PREVIEW_FORMAT);
431 if (fmt == CameraParameters::PIXEL_FORMAT_YUV422SP)
433 else if (fmt == CameraParameters::PIXEL_FORMAT_YUV420SP)
435 else if (fmt == CameraParameters::PIXEL_FORMAT_YUV422I)
437 else if (fmt == CameraParameters::PIXEL_FORMAT_RGB565)
439 else if (fmt == CameraParameters::PIXEL_FORMAT_JPEG)
441 cameraPropertyPreviewFormatString = fmt;
443 union {const char* str;double res;} u;
444 memset(&u.res, 0, sizeof(u.res));
445 u.str = cameraPropertyPreviewFormatString.c_str();
453 void CameraHandler::setProperty(int propIdx, double value)
455 LOGD("CameraHandler::setProperty(%d, %f)", propIdx, value);
459 case ANDROID_CAMERA_PROPERTY_FRAMEWIDTH:
462 params.getPreviewSize(&w, &h);
464 params.setPreviewSize(w, h);
467 case ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT:
470 params.getPreviewSize(&w, &h);
472 params.setPreviewSize(w, h);
478 void CameraHandler::applyProperties(CameraHandler** ppcameraHandler)
480 LOGD("CameraHandler::applyProperties()");
482 if (ppcameraHandler == 0)
484 LOGE("applyProperties: Passed NULL ppcameraHandler");
488 if (*ppcameraHandler == 0)
490 LOGE("applyProperties: Passed null *ppcameraHandler");
494 LOGD("CameraHandler::applyProperties()");
495 CameraHandler* previousCameraHandler=*ppcameraHandler;
496 CameraParameters curCameraParameters(previousCameraHandler->params.flatten());
498 CameraCallback cameraCallback=previousCameraHandler->cameraCallback;
499 void* userData=previousCameraHandler->userData;
500 int cameraId=previousCameraHandler->cameraId;
502 LOGD("CameraHandler::applyProperties(): before previousCameraHandler->closeCameraConnect");
503 previousCameraHandler->closeCameraConnect();
504 LOGD("CameraHandler::applyProperties(): after previousCameraHandler->closeCameraConnect");
507 LOGD("CameraHandler::applyProperties(): before initCameraConnect");
508 CameraHandler* handler=initCameraConnect(cameraCallback, cameraId, userData, &curCameraParameters);
509 LOGD("CameraHandler::applyProperties(): after initCameraConnect, handler=0x%x", (int)handler);
510 if (handler == NULL) {
511 LOGE("ERROR in applyProperties --- cannot reinit camera");
512 handler=initCameraConnect(cameraCallback, cameraId, userData, NULL);
513 LOGD("CameraHandler::applyProperties(): repeate initCameraConnect after ERROR, handler=0x%x", (int)handler);
514 if (handler == NULL) {
515 LOGE("ERROR in applyProperties --- cannot reinit camera AGAIN --- cannot do anything else");
518 (*ppcameraHandler)=handler;
524 void* initCameraConnectC(void* callback, int cameraId, void* userData)
526 return CameraHandler::initCameraConnect((CameraCallback)callback, cameraId, userData, NULL);
529 void closeCameraConnectC(void** camera)
531 CameraHandler** cc = (CameraHandler**)camera;
532 (*cc)->closeCameraConnect();
536 double getCameraPropertyC(void* camera, int propIdx)
538 return ((CameraHandler*)camera)->getProperty(propIdx);
541 void setCameraPropertyC(void* camera, int propIdx, double value)
543 ((CameraHandler*)camera)->setProperty(propIdx,value);
546 void applyCameraPropertiesC(void** camera)
548 CameraHandler::applyProperties((CameraHandler**)camera);