f5a713fe18907dd70cf2836fc0b858376752bf56
[profile/ivi/opencv.git] / modules / androidcamera / camera_wrapper / camera_wrapper.cpp
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.
3 #endif
4
5 #include <camera/Camera.h>
6 #include <camera/CameraParameters.h>
7
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)
11
12 #include "camera_wrapper.h"
13 #include "../include/camera_properties.h"
14
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)
23
24 #include <string>
25
26 //undef logging macro from /system/core/libcutils/loghack.h
27 #ifdef LOGD
28 # undef LOGD
29 #endif
30
31 #ifdef LOGI
32 # undef LOGI
33 #endif
34
35 #ifdef LOGW
36 # undef LOGW
37 #endif
38
39 #ifdef LOGE
40 # undef LOGE
41 #endif
42
43
44 // LOGGING
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__))
51
52 using namespace android;
53
54 void debugShowFPS()
55 {
56     static int mFrameCount = 0;
57     static int mLastFrameCount = 0;
58     static nsecs_t mLastFpsTime = systemTime();
59     static float mFps = 0;
60
61     mFrameCount++;
62
63     if (( mFrameCount % 30 ) != 0)
64         return;
65
66     nsecs_t now = systemTime();
67     nsecs_t diff = now - mLastFpsTime;
68
69     if (diff==0)
70         return;
71
72     mFps =  ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
73     mLastFpsTime = now;
74     mLastFrameCount = mFrameCount;
75     LOGI("### Camera FPS ### [%d] Frames, %.2f FPS", mFrameCount, mFps);
76 }
77
78 class CameraHandler: public CameraListener
79 {
80 protected:
81     int cameraId;
82     sp<Camera> camera;
83     CameraParameters params;
84     CameraCallback cameraCallback;
85     void* userData;
86
87     int emptyCameraCallbackReported;
88
89     void doCall(void* buffer, size_t bufferSize)
90     {
91         if (cameraCallback == 0)
92         {
93             if (!emptyCameraCallbackReported)
94                 LOGE("CameraHandler::doCall(void*, size_t): Camera callback is empty!");
95
96             emptyCameraCallbackReported++;
97         }
98         else
99         {
100             bool res = (*cameraCallback)(buffer, bufferSize, userData);
101
102             if(!res)
103             {
104                 LOGE("CameraHandler::doCall(void*, size_t): cameraCallback returns false (camera connection will be closed)");
105                 closeCameraConnect();
106             }
107         }
108     }
109
110     void doCall(const sp<IMemory>& dataPtr)
111     {
112         if (dataPtr == NULL)
113         {
114             LOGE("CameraHandler::doCall(const sp<IMemory>&): dataPtr==NULL (no frame to handle)");
115             return;
116         }
117
118         size_t size = dataPtr->size();
119         if (size <= 0)
120         {
121             LOGE("CameraHandler::doCall(const sp<IMemory>&): IMemory object is of zero size");
122             return;
123         }
124
125         void* buffer = (void *)dataPtr->pointer();
126         if (!buffer)
127         {
128             LOGE("CameraHandler::doCall(const sp<IMemory>&): Buffer pointer is NULL");
129             return;
130         }
131
132         doCall(buffer, size);
133     }
134
135     virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
136     {
137         static uint32_t count = 0;
138         count++;
139
140         LOGE("Recording cb: %d %lld %%p Offset:%%d Stride:%%d\n", msgType, timestamp);
141
142         if (dataPtr == NULL)
143         {
144             LOGE("postDataTimestamp: dataPtr IS ZERO -- returning");
145             camera->releaseRecordingFrame(dataPtr);
146             LOGE("postDataTimestamp:  camera->releaseRecordingFrame(dataPtr) is done");
147             return;
148         }
149
150         uint8_t *ptr = (uint8_t*) dataPtr->pointer();
151         if (ptr)
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]);
153         else
154             LOGE("postDataTimestamp: Ptr is zero");
155
156         camera->releaseRecordingFrame(dataPtr);
157     }
158
159 public:
160     CameraHandler(CameraCallback callback = 0, void* _userData = 0):
161         cameraId(0),
162         cameraCallback(callback),
163         userData(_userData),
164         emptyCameraCallbackReported(0)
165     {
166         LOGD("Instantiated new CameraHandler (%p, %p)", callback, _userData);
167     }
168
169     virtual ~CameraHandler()
170     {
171         LOGD("CameraHandler destructor is called");
172     }
173
174     virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2)
175     {
176         LOGE("CameraHandler::Notify: msgType=%d ext1=%d ext2=%d\n", msgType, ext1, ext2);
177 #if 0
178         if ( msgType & CAMERA_MSG_FOCUS )
179             LOGE("CameraHandler::Notify  AutoFocus %s in %llu us\n", (ext1) ? "OK" : "FAIL", timevalDelay(&autofocus_start));
180
181         if ( msgType & CAMERA_MSG_SHUTTER )
182             LOGE("CameraHandler::Notify  Shutter done in %llu us\n", timeval_delay(&picture_start));
183 #endif
184     }
185
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
189 #endif
190                           )
191     {
192         debugShowFPS();
193
194         if ( msgType & CAMERA_MSG_PREVIEW_FRAME )
195         {
196             doCall(dataPtr);
197             return;
198         }
199
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);
202
203         if ( msgType & CAMERA_MSG_RAW_IMAGE )
204             LOGE("CameraHandler::postData  Unexpected data format: RAW\n");
205
206         if (msgType & CAMERA_MSG_POSTVIEW_FRAME)
207             LOGE("CameraHandler::postData  Unexpected data format: Postview frame\n");
208
209         if (msgType & CAMERA_MSG_COMPRESSED_IMAGE )
210             LOGE("CameraHandler::postData  Unexpected data format: JPEG");
211     }
212
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);
218
219     std::string cameraPropertySupportedPreviewSizesString;
220     std::string cameraPropertyPreviewFormatString;
221 };
222
223
224 CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, int cameraId, void* userData, CameraParameters* prevCameraParameters)
225 {
226     LOGD("CameraHandler::initCameraConnect(%p, %d, %p, %p)", callback, cameraId, userData, prevCameraParameters);
227
228     sp<Camera> camera = 0;
229
230 #ifdef ANDROID_r2_2_0
231     camera = Camera::connect();
232 #else 
233     /* This is 2.3 or higher. The connect method has cameraID parameter */
234     camera = Camera::connect(cameraId);
235 #endif
236
237     if ( 0 == camera.get() )
238     {
239         LOGE("initCameraConnect: Unable to connect to CameraService\n");
240         return 0;
241     }
242
243     CameraHandler* handler = new CameraHandler(callback, userData);
244     camera->setListener(handler);
245
246     handler->camera = camera;
247     handler->cameraId = cameraId;
248
249     if (prevCameraParameters != 0)
250     {
251         LOGI("initCameraConnect: Setting paramers from previous camera handler");
252         camera->setParameters(prevCameraParameters->flatten());
253         handler->params.unflatten(prevCameraParameters->flatten());
254     }
255     else
256     {
257         android::String8 params_str = camera->getParameters();
258         LOGI("initCameraConnect: [%s]", params_str.string());
259
260         handler->params.unflatten(params_str);
261
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));
275
276
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)
280         {
281             const char* format_to_set = 0;
282             const char* pos = available_formats;
283             const char* ptr = pos;
284             while(true)
285             {
286                 while(*ptr != 0 && *ptr != ',') ++ptr;
287                 if (ptr != pos)
288                 {
289                     if (0 == strncmp(pos, "yuv420sp", ptr - pos))
290                     {
291                         format_to_set = "yuv420sp";
292                         break;
293                     }
294                     if (0 == strncmp(pos, "yvu420sp", ptr - pos))
295                         format_to_set = "yvu420sp";
296                 }
297                 if (*ptr == 0)
298                     break;
299                 pos = ++ptr;
300             }
301
302             if (0 != format_to_set)
303             {
304                 handler->params.setPreviewFormat(format_to_set);
305
306                 status_t resParams = handler->camera->setParameters(handler->params.flatten());
307
308                 if (resParams != 0)
309                     LOGE("initCameraConnect: failed to set preview format to %s", format_to_set);
310                 else
311                     LOGD("initCameraConnect: preview format is set to %s", format_to_set);
312             }
313         }
314     }
315
316     const char* available_focus_modes = handler->params.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES);
317     if (available_focus_modes != 0)
318     {
319         // find auto focus mode
320         if (strstr(available_focus_modes, "auto") != NULL)
321         {
322             handler->params.set(CameraParameters::KEY_FOCUS_MODE, CameraParameters::FOCUS_MODE_AUTO);
323             camera->autoFocus();
324         }
325     }
326
327     status_t pdstatus;
328 #if defined(ANDROID_r2_2_0)
329     pdstatus = camera->setPreviewDisplay(sp<ISurface>(0 /*new DummySurface*/));
330     if (pdstatus != 0)
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 */
334
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);
338     if (pdstatus != 0)
339         LOGE("initCameraConnect: failed setPreviewTexture call; camera migth not work correctly");
340 #endif
341
342 #if !(defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3))
343 # if 1
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
347 # else
348     camera->setPreviewCallbackFlags( FRAME_CALLBACK_FLAG_ENABLE_MASK );//without copy
349 # endif
350 #else
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))
353
354     status_t resStart = camera->startPreview();
355
356     if (resStart != 0)
357     {
358         LOGE("initCameraConnect: startPreview() fails. Closing camera connection...");
359         handler->closeCameraConnect();
360         handler = 0;
361     }
362
363     return handler;
364 }
365
366 void CameraHandler::closeCameraConnect()
367 {
368     if (camera == NULL)
369     {
370         LOGI("... camera is already NULL");
371         return;
372     }
373
374     camera->stopPreview();
375     camera->disconnect();
376     camera.clear();
377
378     camera=NULL;
379     // ATTENTION!!!!!!!!!!!!!!!!!!!!!!!!!!
380     // When we set 
381     //    camera=NULL
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.
385     //
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.
391     //
392     // It means, when that instance of the android::Camera object is destructed,
393     // it calls destructor for this CameraHandler instance too.
394     //
395     // So, this line `camera=NULL' causes to the call `delete this' 
396     // (see destructor of the template class android::sp)
397     //
398     // So, we must not call `delete this' after the line, since it just has been called indeed
399 }
400
401 double CameraHandler::getProperty(int propIdx)
402 {
403     LOGD("CameraHandler::getProperty(%d)", propIdx);
404
405     switch (propIdx)
406     {
407     case ANDROID_CAMERA_PROPERTY_FRAMEWIDTH:
408     {
409         int w,h;
410         params.getPreviewSize(&w, &h);
411         return w;
412     }
413     case ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT:
414     {
415         int w,h;
416         params.getPreviewSize(&w, &h);
417         return h;
418     }
419     case ANDROID_CAMERA_PROPERTY_SUPPORTED_PREVIEW_SIZES_STRING:
420     {
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();
425         return u.res;
426     }
427
428     case ANDROID_CAMERA_PROPERTY_PREVIEW_FORMAT_STRING:
429     {
430         const char* fmt = params.get(CameraParameters::KEY_PREVIEW_FORMAT);
431         if (fmt == CameraParameters::PIXEL_FORMAT_YUV422SP)
432             fmt = "yuv422sp";
433         else if (fmt == CameraParameters::PIXEL_FORMAT_YUV420SP)
434             fmt = "yuv420sp";
435         else if (fmt == CameraParameters::PIXEL_FORMAT_YUV422I)
436             fmt = "yuv422i";
437         else if (fmt == CameraParameters::PIXEL_FORMAT_RGB565)
438             fmt = "rgb565";
439         else if (fmt == CameraParameters::PIXEL_FORMAT_JPEG)
440             fmt = "jpeg";
441         cameraPropertyPreviewFormatString = fmt;
442
443         union {const char* str;double res;} u;
444         memset(&u.res, 0, sizeof(u.res));
445         u.str = cameraPropertyPreviewFormatString.c_str();
446         return u.res;
447     }
448
449     };
450     return -1;
451 }
452
453 void CameraHandler::setProperty(int propIdx, double value)
454 {
455     LOGD("CameraHandler::setProperty(%d, %f)", propIdx, value);
456
457     switch (propIdx)
458     {
459     case ANDROID_CAMERA_PROPERTY_FRAMEWIDTH:
460     {
461         int w,h;
462         params.getPreviewSize(&w, &h);
463         w = (int)value;
464         params.setPreviewSize(w, h);
465     }
466     break;
467     case ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT:
468     {
469         int w,h;
470         params.getPreviewSize(&w, &h);
471         h = (int)value;
472         params.setPreviewSize(w, h);
473     }
474     break;
475     };
476 }
477
478 void CameraHandler::applyProperties(CameraHandler** ppcameraHandler)
479 {
480     LOGD("CameraHandler::applyProperties()");
481
482     if (ppcameraHandler == 0)
483     {
484         LOGE("applyProperties: Passed NULL ppcameraHandler");
485         return;
486     }
487
488     if (*ppcameraHandler == 0)
489     {
490         LOGE("applyProperties: Passed null *ppcameraHandler");
491         return;
492     }
493
494     LOGD("CameraHandler::applyProperties()");
495     CameraHandler* previousCameraHandler=*ppcameraHandler;
496     CameraParameters curCameraParameters(previousCameraHandler->params.flatten());
497
498     CameraCallback cameraCallback=previousCameraHandler->cameraCallback;
499     void* userData=previousCameraHandler->userData;
500     int cameraId=previousCameraHandler->cameraId;
501
502     LOGD("CameraHandler::applyProperties(): before previousCameraHandler->closeCameraConnect");
503     previousCameraHandler->closeCameraConnect();
504     LOGD("CameraHandler::applyProperties(): after previousCameraHandler->closeCameraConnect");
505
506
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");
516         }
517     }
518     (*ppcameraHandler)=handler;
519 }
520
521
522 extern "C" {
523
524 void* initCameraConnectC(void* callback, int cameraId, void* userData)
525 {
526     return CameraHandler::initCameraConnect((CameraCallback)callback, cameraId, userData, NULL);
527 }
528
529 void closeCameraConnectC(void** camera)
530 {
531     CameraHandler** cc = (CameraHandler**)camera;
532     (*cc)->closeCameraConnect();
533     *cc = 0;
534 }
535
536 double getCameraPropertyC(void* camera, int propIdx)
537 {
538     return ((CameraHandler*)camera)->getProperty(propIdx);
539 }
540
541 void setCameraPropertyC(void* camera, int propIdx, double value)
542 {
543     ((CameraHandler*)camera)->setProperty(propIdx,value);
544 }
545
546 void applyCameraPropertiesC(void** camera)
547 {
548     CameraHandler::applyProperties((CameraHandler**)camera);
549 }
550
551 }