Merge pull request #1263 from abidrahmank:pyCLAHE_24
[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) && \
2  !defined(ANDROID_r4_0_0) && !defined(ANDROID_r4_0_3) && !defined(ANDROID_r4_1_1) && \
3  !defined(ANDROID_r4_2_0) && !defined(ANDROID_r4_3_0)
4 # error Building camera wrapper for your version of Android is not supported by OpenCV.\
5  You need to modify OpenCV sources in order to compile camera wrapper for your version of Android.
6 #endif
7
8 #include <camera/Camera.h>
9 #include <camera/CameraParameters.h>
10
11 #if defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3)
12 # include <system/camera.h>
13 #endif //defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3)
14
15 #include "camera_wrapper.h"
16 #include "../include/camera_properties.h"
17
18 #if defined(ANDROID_r3_0_1) || defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3) || defined(ANDROID_r4_1_1)
19 //Include SurfaceTexture.h file with the SurfaceTexture class
20 # include <gui/SurfaceTexture.h>
21 # define MAGIC_OPENCV_TEXTURE_ID (0x10)
22 #elif defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0)
23 # include <gui/ISurface.h>
24 # include <gui/BufferQueue.h>
25 #elif defined(ANDROID_r4_3_0)
26 # include <gui/IGraphicBufferProducer.h>
27 # include <gui/BufferQueue.h>
28 #else
29 # include <surfaceflinger/ISurface.h>
30 #endif
31
32 #include <string>
33 #include <fstream>
34
35 //undef logging macro from /system/core/libcutils/loghack.h
36 #ifdef LOGD
37 # undef LOGD
38 #endif
39
40 #ifdef LOGI
41 # undef LOGI
42 #endif
43
44 #ifdef LOGW
45 # undef LOGW
46 #endif
47
48 #ifdef LOGE
49 # undef LOGE
50 #endif
51
52 // LOGGING
53 #include <android/log.h>
54 #define CAMERA_LOG_TAG "OpenCV_NativeCamera"
55 #define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, CAMERA_LOG_TAG, __VA_ARGS__))
56 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, CAMERA_LOG_TAG, __VA_ARGS__))
57 #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, CAMERA_LOG_TAG, __VA_ARGS__))
58 #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, CAMERA_LOG_TAG, __VA_ARGS__))
59
60 #include <dlfcn.h>
61
62 using namespace android;
63
64 void debugShowFPS();
65
66 #if defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) || defined(ANDROID_r4_3_0)
67 class ConsumerListenerStub: public BufferQueue::ConsumerListener
68 {
69 public:
70     virtual void onFrameAvailable()
71     {
72     }
73     virtual void onBuffersReleased()
74     {
75     }
76 };
77 #endif
78
79 std::string getProcessName()
80 {
81     std::string result;
82     std::ifstream f;
83
84     f.open("/proc/self/cmdline");
85     if (f.is_open())
86     {
87         std::string fullPath;
88         std::getline(f, fullPath, '\0');
89         if (!fullPath.empty())
90         {
91             int i = fullPath.size()-1;
92             while ((i >= 0) && (fullPath[i] != '/')) i--;
93             result = fullPath.substr(i+1, std::string::npos);
94         }
95     }
96
97     f.close();
98
99     return result;
100 }
101
102 void debugShowFPS()
103 {
104     static int mFrameCount = 0;
105     static int mLastFrameCount = 0;
106     static nsecs_t mLastFpsTime = systemTime();
107     static float mFps = 0;
108
109     mFrameCount++;
110
111     if (( mFrameCount % 30 ) != 0)
112         return;
113
114     nsecs_t now = systemTime();
115     nsecs_t diff = now - mLastFpsTime;
116
117     if (diff==0)
118         return;
119
120     mFps =  ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
121     mLastFpsTime = now;
122     mLastFrameCount = mFrameCount;
123     LOGI("### Camera FPS ### [%d] Frames, %.2f FPS", mFrameCount, mFps);
124 }
125
126 class CameraHandler: public CameraListener
127 {
128 protected:
129     int cameraId;
130     sp<Camera> camera;
131     CameraParameters params;
132     CameraCallback cameraCallback;
133     void* userData;
134
135     int emptyCameraCallbackReported;
136
137     static const char* flashModesNames[ANDROID_CAMERA_FLASH_MODES_NUM];
138     static const char* focusModesNames[ANDROID_CAMERA_FOCUS_MODES_NUM];
139     static const char* whiteBalanceModesNames[ANDROID_CAMERA_WHITE_BALANCE_MODES_NUM];
140     static const char* antibandingModesNames[ANDROID_CAMERA_ANTIBANDING_MODES_NUM];
141
142     void doCall(void* buffer, size_t bufferSize)
143     {
144         if (cameraCallback == 0)
145         {
146             if (!emptyCameraCallbackReported)
147                 LOGE("CameraHandler::doCall(void*, size_t): Camera callback is empty!");
148
149             emptyCameraCallbackReported++;
150         }
151         else
152         {
153             bool res = (*cameraCallback)(buffer, bufferSize, userData);
154
155             if(!res)
156             {
157                 LOGE("CameraHandler::doCall(void*, size_t): cameraCallback returns false (camera connection will be closed)");
158                 closeCameraConnect();
159             }
160         }
161     }
162
163     void doCall(const sp<IMemory>& dataPtr)
164     {
165         if (dataPtr == NULL)
166         {
167             LOGE("CameraHandler::doCall(const sp<IMemory>&): dataPtr==NULL (no frame to handle)");
168             return;
169         }
170
171         size_t size = dataPtr->size();
172         if (size <= 0)
173         {
174             LOGE("CameraHandler::doCall(const sp<IMemory>&): IMemory object is of zero size");
175             return;
176         }
177
178         void* buffer = (void *)dataPtr->pointer();
179         if (!buffer)
180         {
181             LOGE("CameraHandler::doCall(const sp<IMemory>&): Buffer pointer is NULL");
182             return;
183         }
184
185         doCall(buffer, size);
186     }
187
188     virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
189     {
190         static uint32_t count = 0;
191         count++;
192
193         LOGE("Recording cb: %d %lld %%p Offset:%%d Stride:%%d\n", msgType, timestamp);
194
195         if (dataPtr == NULL)
196         {
197             LOGE("postDataTimestamp: dataPtr IS ZERO -- returning");
198             camera->releaseRecordingFrame(dataPtr);
199             LOGE("postDataTimestamp:  camera->releaseRecordingFrame(dataPtr) is done");
200             return;
201         }
202
203         uint8_t *ptr = (uint8_t*) dataPtr->pointer();
204         if (ptr)
205             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]);
206         else
207             LOGE("postDataTimestamp: Ptr is zero");
208
209         camera->releaseRecordingFrame(dataPtr);
210     }
211
212     // Split list of floats, returns number of floats found
213     static int split_float(const char *str, float* out, char delim, int max_elem_num,
214                            char **endptr = NULL)
215     {
216         // Find the first float.
217         char *end = const_cast<char*>(str);
218         int elem_num = 0;
219         for(; elem_num < max_elem_num; elem_num++ ){
220             char* curr_end;
221             out[elem_num] = (float)strtof(end, &curr_end);
222             // No other numbers found, finish the loop
223             if(end == curr_end){
224                 break;
225             }
226             if (*curr_end != delim) {
227                 // When end of string, finish the loop
228                 if (*curr_end == 0){
229                     elem_num++;
230                     break;
231                 }
232                 else {
233                     LOGE("Cannot find delimeter (%c) in str=%s", delim, str);
234                     return -1;
235                 }
236             }
237             // Skip the delimiter character
238             end = curr_end + 1;
239         }
240         if (endptr)
241             *endptr = end;
242         return elem_num;
243     }
244
245     int is_supported(const char* supp_modes_key, const char* mode)
246     {
247         const char* supported_modes = params.get(supp_modes_key);
248         return (supported_modes && mode && (strstr(supported_modes, mode) > 0));
249     }
250
251     float getFocusDistance(int focus_distance_type)
252     {
253 #if !defined(ANDROID_r2_2_0)
254         if (focus_distance_type >= 0 && focus_distance_type < 3)
255     {
256             float focus_distances[3];
257             const char* output = params.get(CameraParameters::KEY_FOCUS_DISTANCES);
258             int val_num = CameraHandler::split_float(output, focus_distances, ',', 3);
259             if(val_num == 3)
260         {
261                 return focus_distances[focus_distance_type];
262             }
263             else
264         {
265                 LOGE("Invalid focus distances.");
266             }
267         }
268 #endif
269     return -1;
270     }
271
272     static int getModeNum(const char** modes, const int modes_num, const char* mode_name)
273     {
274         for (int i = 0; i < modes_num; i++){
275             if(!strcmp(modes[i],mode_name))
276                 return i;
277         }
278         return -1;
279     }
280
281 public:
282     CameraHandler(CameraCallback callback = 0, void* _userData = 0):
283         cameraId(0),
284         cameraCallback(callback),
285         userData(_userData),
286         emptyCameraCallbackReported(0)
287     {
288         LOGD("Instantiated new CameraHandler (%p, %p)", callback, _userData);
289     }
290
291     virtual ~CameraHandler()
292     {
293         LOGD("CameraHandler destructor is called");
294     }
295
296     virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2)
297     {
298         LOGE("CameraHandler::Notify: msgType=%d ext1=%d ext2=%d\n", msgType, ext1, ext2);
299 #if 0
300         if ( msgType & CAMERA_MSG_FOCUS )
301             LOGE("CameraHandler::Notify  AutoFocus %s in %llu us\n", (ext1) ? "OK" : "FAIL", timevalDelay(&autofocus_start));
302
303         if ( msgType & CAMERA_MSG_SHUTTER )
304             LOGE("CameraHandler::Notify  Shutter done in %llu us\n", timeval_delay(&picture_start));
305 #endif
306     }
307
308     virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr
309     #if defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3) || defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) || defined(ANDROID_r4_3_0)
310                           ,camera_frame_metadata_t*
311 #endif
312                           )
313     {
314         debugShowFPS();
315
316         if ( msgType & CAMERA_MSG_PREVIEW_FRAME )
317         {
318             doCall(dataPtr);
319             return;
320         }
321
322         //if (msgType != CAMERA_MSG_PREVIEW_FRAME)
323             //LOGE("CameraHandler::postData  Recieved message %d is not equal to CAMERA_MSG_PREVIEW_FRAME (%d)", (int) msgType, CAMERA_MSG_PREVIEW_FRAME);
324
325         if ( msgType & CAMERA_MSG_RAW_IMAGE )
326             LOGE("CameraHandler::postData  Unexpected data format: RAW\n");
327
328         if (msgType & CAMERA_MSG_POSTVIEW_FRAME)
329             LOGE("CameraHandler::postData  Unexpected data format: Postview frame\n");
330
331         if (msgType & CAMERA_MSG_COMPRESSED_IMAGE )
332             LOGE("CameraHandler::postData  Unexpected data format: JPEG");
333     }
334
335     static CameraHandler* initCameraConnect(const CameraCallback& callback, int cameraId, void* userData, CameraParameters* prevCameraParameters);
336     void closeCameraConnect();
337     double getProperty(int propIdx);
338     void setProperty(int propIdx, double value);
339     static void applyProperties(CameraHandler** ppcameraHandler);
340
341     std::string cameraPropertySupportedPreviewSizesString;
342     std::string cameraPropertyPreviewFormatString;
343 };
344
345 const char* CameraHandler::flashModesNames[ANDROID_CAMERA_FLASH_MODES_NUM] =
346 {
347     CameraParameters::FLASH_MODE_AUTO,
348     CameraParameters::FLASH_MODE_OFF,
349     CameraParameters::FLASH_MODE_ON,
350     CameraParameters::FLASH_MODE_RED_EYE,
351     CameraParameters::FLASH_MODE_TORCH
352 };
353
354 const char* CameraHandler::focusModesNames[ANDROID_CAMERA_FOCUS_MODES_NUM] =
355 {
356     CameraParameters::FOCUS_MODE_AUTO,
357 #if !defined(ANDROID_r2_2_0)
358     CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO,
359 #endif
360     CameraParameters::FOCUS_MODE_EDOF,
361     CameraParameters::FOCUS_MODE_FIXED,
362     CameraParameters::FOCUS_MODE_INFINITY
363 };
364
365 const char* CameraHandler::whiteBalanceModesNames[ANDROID_CAMERA_WHITE_BALANCE_MODES_NUM] =
366 {
367     CameraParameters::WHITE_BALANCE_AUTO,
368     CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT,
369     CameraParameters::WHITE_BALANCE_DAYLIGHT,
370     CameraParameters::WHITE_BALANCE_FLUORESCENT,
371     CameraParameters::WHITE_BALANCE_INCANDESCENT,
372     CameraParameters::WHITE_BALANCE_SHADE,
373     CameraParameters::WHITE_BALANCE_TWILIGHT
374 };
375
376 const char* CameraHandler::antibandingModesNames[ANDROID_CAMERA_ANTIBANDING_MODES_NUM] =
377 {
378     CameraParameters::ANTIBANDING_50HZ,
379     CameraParameters::ANTIBANDING_60HZ,
380     CameraParameters::ANTIBANDING_AUTO
381 };
382
383
384 CameraHandler* CameraHandler::initCameraConnect(const CameraCallback& callback, int cameraId, void* userData, CameraParameters* prevCameraParameters)
385 {
386
387     typedef sp<Camera> (*Android22ConnectFuncType)();
388     typedef sp<Camera> (*Android23ConnectFuncType)(int);
389     typedef sp<Camera> (*Android3DConnectFuncType)(int, int);
390     typedef sp<Camera> (*Android43ConnectFuncType)(int, const String16&, int);
391
392     const int ANY_CAMERA_INDEX = -1;
393     const int BACK_CAMERA_INDEX = 99;
394     const int FRONT_CAMERA_INDEX = 98;
395
396     enum {
397     CAMERA_SUPPORT_MODE_2D = 0x01, /* Camera Sensor supports 2D mode. */
398     CAMERA_SUPPORT_MODE_3D = 0x02, /* Camera Sensor supports 3D mode. */
399     CAMERA_SUPPORT_MODE_NONZSL = 0x04, /* Camera Sensor in NON-ZSL mode. */
400     CAMERA_SUPPORT_MODE_ZSL = 0x08 /* Camera Sensor supports ZSL mode. */
401     };
402
403     // used for Android 4.3
404     enum {
405         USE_CALLING_UID = -1
406     };
407
408     const char Android22ConnectName[] = "_ZN7android6Camera7connectEv";
409     const char Android23ConnectName[] = "_ZN7android6Camera7connectEi";
410     const char Android3DConnectName[] = "_ZN7android6Camera7connectEii";
411     const char Android43ConnectName[] = "_ZN7android6Camera7connectEiRKNS_8String16Ei";
412
413     int localCameraIndex = cameraId;
414
415     if (cameraId == ANY_CAMERA_INDEX)
416     {
417         localCameraIndex = 0;
418     }
419 #if !defined(ANDROID_r2_2_0)
420     else if (cameraId == BACK_CAMERA_INDEX)
421     {
422         LOGD("Back camera selected");
423         for (int i = 0; i < Camera::getNumberOfCameras(); i++)
424         {
425             CameraInfo info;
426             Camera::getCameraInfo(i, &info);
427             if (info.facing == CAMERA_FACING_BACK)
428             {
429                 localCameraIndex = i;
430                 break;
431             }
432         }
433     }
434     else if (cameraId == FRONT_CAMERA_INDEX)
435     {
436         LOGD("Front camera selected");
437         for (int i = 0; i < Camera::getNumberOfCameras(); i++)
438         {
439             CameraInfo info;
440             Camera::getCameraInfo(i, &info);
441             if (info.facing == CAMERA_FACING_FRONT)
442             {
443                 localCameraIndex = i;
444                 break;
445             }
446         }
447     }
448
449     if (localCameraIndex == BACK_CAMERA_INDEX)
450     {
451         LOGE("Back camera not found!");
452         return NULL;
453     }
454     else if (localCameraIndex == FRONT_CAMERA_INDEX)
455     {
456         LOGE("Front camera not found!");
457         return NULL;
458     }
459 #endif
460
461     LOGD("CameraHandler::initCameraConnect(%p, %d, %p, %p)", callback, localCameraIndex, userData, prevCameraParameters);
462
463     sp<Camera> camera = 0;
464
465     void* CameraHALHandle = dlopen("libcamera_client.so", RTLD_LAZY);
466
467     if (!CameraHALHandle)
468     {
469         LOGE("Cannot link to \"libcamera_client.so\"");
470         return NULL;
471     }
472
473     // reset errors
474     dlerror();
475
476     if (Android22ConnectFuncType Android22Connect = (Android22ConnectFuncType)dlsym(CameraHALHandle, Android22ConnectName))
477     {
478         LOGD("Connecting to CameraService v 2.2");
479         camera = Android22Connect();
480     }
481     else if (Android23ConnectFuncType Android23Connect = (Android23ConnectFuncType)dlsym(CameraHALHandle, Android23ConnectName))
482     {
483         LOGD("Connecting to CameraService v 2.3");
484         camera = Android23Connect(localCameraIndex);
485     }
486     else if (Android3DConnectFuncType Android3DConnect = (Android3DConnectFuncType)dlsym(CameraHALHandle, Android3DConnectName))
487     {
488         LOGD("Connecting to CameraService v 3D");
489         camera = Android3DConnect(localCameraIndex, CAMERA_SUPPORT_MODE_2D);
490     }
491     else if (Android43ConnectFuncType Android43Connect = (Android43ConnectFuncType)dlsym(CameraHALHandle, Android43ConnectName))
492     {
493         std::string currentProcName = getProcessName();
494         LOGD("Current process name for camera init: %s", currentProcName.c_str());
495         camera = Android43Connect(localCameraIndex, String16(currentProcName.c_str()), USE_CALLING_UID);
496     }
497     else
498     {
499         dlclose(CameraHALHandle);
500         LOGE("Cannot connect to CameraService. Connect method was not found!");
501         return NULL;
502     }
503
504     dlclose(CameraHALHandle);
505
506     if ( 0 == camera.get() )
507     {
508         LOGE("initCameraConnect: Unable to connect to CameraService\n");
509         return 0;
510     }
511
512     CameraHandler* handler = new CameraHandler(callback, userData);
513     camera->setListener(handler);
514
515     handler->camera = camera;
516     handler->cameraId = localCameraIndex;
517
518     if (prevCameraParameters != NULL)
519     {
520         LOGI("initCameraConnect: Setting paramers from previous camera handler");
521         camera->setParameters(prevCameraParameters->flatten());
522         handler->params.unflatten(prevCameraParameters->flatten());
523     }
524     else
525     {
526         android::String8 params_str = camera->getParameters();
527         LOGI("initCameraConnect: [%s]", params_str.string());
528
529         handler->params.unflatten(params_str);
530
531         LOGD("Supported Cameras: %s", handler->params.get("camera-indexes"));
532         LOGD("Supported Picture Sizes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES));
533         LOGD("Supported Picture Formats: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS));
534         LOGD("Supported Preview Sizes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES));
535         LOGD("Supported Preview Formats: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS));
536         LOGD("Supported Preview Frame Rates: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES));
537         LOGD("Supported Thumbnail Sizes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES));
538         LOGD("Supported Whitebalance Modes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE));
539         LOGD("Supported Effects: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_EFFECTS));
540         LOGD("Supported Scene Modes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_SCENE_MODES));
541         LOGD("Supported Focus Modes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES));
542         LOGD("Supported Antibanding Options: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_ANTIBANDING));
543         LOGD("Supported Flash Modes: %s", handler->params.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES));
544
545 #if !defined(ANDROID_r2_2_0)
546         // Set focus mode to continuous-video if supported
547         const char* available_focus_modes = handler->params.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES);
548         if (available_focus_modes != 0)
549         {
550             if (strstr(available_focus_modes, "continuous-video") != NULL)
551             {
552                 handler->params.set(CameraParameters::KEY_FOCUS_MODE, CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO);
553
554                 status_t resParams = handler->camera->setParameters(handler->params.flatten());
555
556                 if (resParams != 0)
557                 {
558                     LOGE("initCameraConnect: failed to set autofocus mode to \"continuous-video\"");
559                 }
560                 else
561                 {
562                     LOGD("initCameraConnect: autofocus is set to mode \"continuous-video\"");
563                 }
564             }
565         }
566 #endif
567
568         //check if yuv420sp format available. Set this format as preview format.
569         const char* available_formats = handler->params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS);
570         if (available_formats != 0)
571         {
572             const char* format_to_set = 0;
573             const char* pos = available_formats;
574             const char* ptr = pos;
575             while(true)
576             {
577                 while(*ptr != 0 && *ptr != ',') ++ptr;
578                 if (ptr != pos)
579                 {
580                     if (0 == strncmp(pos, "yuv420sp", ptr - pos))
581                     {
582                         format_to_set = "yuv420sp";
583                         break;
584                     }
585                     if (0 == strncmp(pos, "yvu420sp", ptr - pos))
586                         format_to_set = "yvu420sp";
587                 }
588                 if (*ptr == 0)
589                     break;
590                 pos = ++ptr;
591             }
592
593             if (0 != format_to_set)
594             {
595                 handler->params.setPreviewFormat(format_to_set);
596
597                 status_t resParams = handler->camera->setParameters(handler->params.flatten());
598
599                 if (resParams != 0)
600                     LOGE("initCameraConnect: failed to set preview format to %s", format_to_set);
601                 else
602                     LOGD("initCameraConnect: preview format is set to %s", format_to_set);
603             }
604         }
605     }
606
607     status_t bufferStatus;
608 #if defined(ANDROID_r2_2_0)
609     bufferStatus = camera->setPreviewDisplay(sp<ISurface>(0 /*new DummySurface*/));
610     if (bufferStatus != 0)
611         LOGE("initCameraConnect: failed setPreviewDisplay(0) call (status %d); camera might not work correctly on some devices", bufferStatus);
612 #elif defined(ANDROID_r2_3_3)
613     /* Do nothing in case of 2.3 for now */
614 #elif defined(ANDROID_r3_0_1) || defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3)
615     sp<SurfaceTexture> surfaceTexture = new SurfaceTexture(MAGIC_OPENCV_TEXTURE_ID);
616     bufferStatus = camera->setPreviewTexture(surfaceTexture);
617     if (bufferStatus != 0)
618         LOGE("initCameraConnect: failed setPreviewTexture call (status %d); camera might not work correctly", bufferStatus);
619 #elif defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) || defined(ANDROID_r4_3_0)
620     sp<BufferQueue> bufferQueue = new BufferQueue();
621     sp<BufferQueue::ConsumerListener> queueListener = new ConsumerListenerStub();
622     bufferQueue->consumerConnect(queueListener);
623     bufferStatus = camera->setPreviewTexture(bufferQueue);
624     if (bufferStatus != 0)
625         LOGE("initCameraConnect: failed setPreviewTexture call; camera might not work correctly");
626 #endif
627
628 #if (defined(ANDROID_r2_2_0) || defined(ANDROID_r2_3_3) || defined(ANDROID_r3_0_1))
629 # if 1
630     ////ATTENTION: switching between two versions: with and without copying memory inside Android OS
631     //// see the method  CameraService::Client::copyFrameAndPostCopiedFrame and where it is used
632     camera->setPreviewCallbackFlags( FRAME_CALLBACK_FLAG_ENABLE_MASK | FRAME_CALLBACK_FLAG_COPY_OUT_MASK);//with copy
633 # else
634     camera->setPreviewCallbackFlags( FRAME_CALLBACK_FLAG_ENABLE_MASK );//without copy
635 # endif
636 #else
637     camera->setPreviewCallbackFlags( CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK | CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK);//with copy
638 #endif //!(defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3))
639
640     LOGD("Starting preview");
641     status_t previewStatus = camera->startPreview();
642
643     if (previewStatus != 0)
644     {
645         LOGE("initCameraConnect: startPreview() fails. Closing camera connection...");
646         handler->closeCameraConnect();
647         handler = 0;
648     }
649     else
650     {
651         LOGD("Preview started successfully");
652     }
653
654     return handler;
655 }
656
657 void CameraHandler::closeCameraConnect()
658 {
659     if (camera == NULL)
660     {
661         LOGI("... camera is already NULL");
662         return;
663     }
664
665     camera->stopPreview();
666 #if defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3) || defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) || defined(ANDROID_r4_3_0)
667     camera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP);
668 #endif
669     camera->disconnect();
670     camera.clear();
671     camera=NULL;
672     // ATTENTION!!!!!!!!!!!!!!!!!!!!!!!!!!
673     // When we set
674     //    camera=NULL
675     // above, the pointed instance of android::Camera object is destructed,
676     // since this member `camera' has type android::sp<Camera> (android smart pointer template class),
677     // and this is the only pointer to it.
678     //
679     // BUT this instance of CameraHandler is set as a listener for that android::Camera object
680     // (see the function CameraHandler::initCameraConnect above),
681     // so this instance of CameraHandler is pointed from that android::Camera object as
682     //     sp<CameraListener>  mListener
683     // and there is no other android smart pointers to this.
684     //
685     // It means, when that instance of the android::Camera object is destructed,
686     // it calls destructor for this CameraHandler instance too.
687     //
688     // So, this line `camera=NULL' causes to the call `delete this'
689     // (see destructor of the template class android::sp)
690     //
691     // So, we must not call `delete this' after the line, since it just has been called indeed
692 }
693
694 double CameraHandler::getProperty(int propIdx)
695 {
696     LOGD("CameraHandler::getProperty(%d)", propIdx);
697
698     switch (propIdx)
699     {
700     case ANDROID_CAMERA_PROPERTY_FRAMEWIDTH:
701     {
702         int w,h;
703         params.getPreviewSize(&w, &h);
704         return w;
705     }
706     case ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT:
707     {
708         int w,h;
709         params.getPreviewSize(&w, &h);
710         return h;
711     }
712     case ANDROID_CAMERA_PROPERTY_SUPPORTED_PREVIEW_SIZES_STRING:
713     {
714         cameraPropertySupportedPreviewSizesString = params.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES);
715         union {const char* str;double res;} u;
716         memset(&u.res, 0, sizeof(u.res));
717         u.str = cameraPropertySupportedPreviewSizesString.c_str();
718         return u.res;
719     }
720     case ANDROID_CAMERA_PROPERTY_PREVIEW_FORMAT_STRING:
721     {
722         const char* fmt = params.get(CameraParameters::KEY_PREVIEW_FORMAT);
723         if (fmt == CameraParameters::PIXEL_FORMAT_YUV422SP)
724             fmt = "yuv422sp";
725         else if (fmt == CameraParameters::PIXEL_FORMAT_YUV420SP)
726             fmt = "yuv420sp";
727         else if (fmt == CameraParameters::PIXEL_FORMAT_YUV422I)
728             fmt = "yuv422i";
729         else if (fmt == CameraParameters::PIXEL_FORMAT_RGB565)
730             fmt = "rgb565";
731         else if (fmt == CameraParameters::PIXEL_FORMAT_JPEG)
732             fmt = "jpeg";
733         cameraPropertyPreviewFormatString = fmt;
734
735         union {const char* str;double res;} u;
736         memset(&u.res, 0, sizeof(u.res));
737         u.str = cameraPropertyPreviewFormatString.c_str();
738         return u.res;
739     }
740     case ANDROID_CAMERA_PROPERTY_EXPOSURE:
741     {
742         int exposure = params.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION);
743         return exposure;
744     }
745     case ANDROID_CAMERA_PROPERTY_FPS:
746     {
747         return params.getPreviewFrameRate();
748     }
749     case ANDROID_CAMERA_PROPERTY_FLASH_MODE:
750     {
751         int flash_mode = getModeNum(CameraHandler::flashModesNames,
752                                     ANDROID_CAMERA_FLASH_MODES_NUM,
753                                     params.get(CameraParameters::KEY_FLASH_MODE));
754         return flash_mode;
755     }
756     case ANDROID_CAMERA_PROPERTY_FOCUS_MODE:
757     {
758         int focus_mode = getModeNum(CameraHandler::focusModesNames,
759                                     ANDROID_CAMERA_FOCUS_MODES_NUM,
760                                     params.get(CameraParameters::KEY_FOCUS_MODE));
761         return focus_mode;
762     }
763     case ANDROID_CAMERA_PROPERTY_WHITE_BALANCE:
764     {
765         int white_balance = getModeNum(CameraHandler::whiteBalanceModesNames,
766                                        ANDROID_CAMERA_WHITE_BALANCE_MODES_NUM,
767                                        params.get(CameraParameters::KEY_WHITE_BALANCE));
768         return white_balance;
769     }
770     case ANDROID_CAMERA_PROPERTY_ANTIBANDING:
771     {
772         int antibanding = getModeNum(CameraHandler::antibandingModesNames,
773                                      ANDROID_CAMERA_ANTIBANDING_MODES_NUM,
774                                      params.get(CameraParameters::KEY_ANTIBANDING));
775         return antibanding;
776     }
777     case ANDROID_CAMERA_PROPERTY_FOCAL_LENGTH:
778     {
779         float focal_length = params.getFloat(CameraParameters::KEY_FOCAL_LENGTH);
780         return focal_length;
781     }
782     case ANDROID_CAMERA_PROPERTY_FOCUS_DISTANCE_NEAR:
783     {
784         return getFocusDistance(ANDROID_CAMERA_FOCUS_DISTANCE_NEAR_INDEX);
785     }
786     case ANDROID_CAMERA_PROPERTY_FOCUS_DISTANCE_OPTIMAL:
787     {
788         return getFocusDistance(ANDROID_CAMERA_FOCUS_DISTANCE_OPTIMAL_INDEX);
789     }
790     case ANDROID_CAMERA_PROPERTY_FOCUS_DISTANCE_FAR:
791     {
792         return getFocusDistance(ANDROID_CAMERA_FOCUS_DISTANCE_FAR_INDEX);
793     }
794     default:
795         LOGW("CameraHandler::getProperty - Unsupported property.");
796     };
797     return -1;
798 }
799
800 void CameraHandler::setProperty(int propIdx, double value)
801 {
802     LOGD("CameraHandler::setProperty(%d, %f)", propIdx, value);
803
804     switch (propIdx)
805     {
806     case ANDROID_CAMERA_PROPERTY_FRAMEWIDTH:
807     {
808         int w,h;
809         params.getPreviewSize(&w, &h);
810         w = (int)value;
811         params.setPreviewSize(w, h);
812     }
813     break;
814     case ANDROID_CAMERA_PROPERTY_FRAMEHEIGHT:
815     {
816         int w,h;
817         params.getPreviewSize(&w, &h);
818         h = (int)value;
819         params.setPreviewSize(w, h);
820     }
821     break;
822     case ANDROID_CAMERA_PROPERTY_EXPOSURE:
823     {
824         int max_exposure = params.getInt("max-exposure-compensation");
825         int min_exposure = params.getInt("min-exposure-compensation");
826         if(max_exposure && min_exposure){
827             int exposure = (int)value;
828             if(exposure >= min_exposure && exposure <= max_exposure){
829                 params.set("exposure-compensation", exposure);
830             } else {
831                 LOGE("Exposure compensation not in valid range (%i,%i).", min_exposure, max_exposure);
832             }
833         } else {
834             LOGE("Exposure compensation adjust is not supported.");
835         }
836     }
837     break;
838     case ANDROID_CAMERA_PROPERTY_FLASH_MODE:
839     {
840         int new_val = (int)value;
841         if(new_val >= 0 && new_val < ANDROID_CAMERA_FLASH_MODES_NUM){
842             const char* mode_name = flashModesNames[new_val];
843             if(is_supported(CameraParameters::KEY_SUPPORTED_FLASH_MODES, mode_name))
844                 params.set(CameraParameters::KEY_FLASH_MODE, mode_name);
845             else
846                 LOGE("Flash mode %s is not supported.", mode_name);
847         } else {
848             LOGE("Flash mode value not in valid range.");
849         }
850     }
851     break;
852     case ANDROID_CAMERA_PROPERTY_FOCUS_MODE:
853     {
854         int new_val = (int)value;
855         if(new_val >= 0 && new_val < ANDROID_CAMERA_FOCUS_MODES_NUM){
856             const char* mode_name = focusModesNames[new_val];
857             if(is_supported(CameraParameters::KEY_SUPPORTED_FOCUS_MODES, mode_name))
858                 params.set(CameraParameters::KEY_FOCUS_MODE, mode_name);
859             else
860                 LOGE("Focus mode %s is not supported.", mode_name);
861         } else {
862             LOGE("Focus mode value not in valid range.");
863         }
864     }
865     break;
866     case ANDROID_CAMERA_PROPERTY_WHITE_BALANCE:
867     {
868         int new_val = (int)value;
869         if(new_val >= 0 && new_val < ANDROID_CAMERA_WHITE_BALANCE_MODES_NUM){
870             const char* mode_name = whiteBalanceModesNames[new_val];
871             if(is_supported(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE, mode_name))
872                 params.set(CameraParameters::KEY_WHITE_BALANCE, mode_name);
873             else
874                 LOGE("White balance mode %s is not supported.", mode_name);
875         } else {
876             LOGE("White balance mode value not in valid range.");
877         }
878     }
879     break;
880     case ANDROID_CAMERA_PROPERTY_ANTIBANDING:
881     {
882         int new_val = (int)value;
883         if(new_val >= 0 && new_val < ANDROID_CAMERA_ANTIBANDING_MODES_NUM){
884             const char* mode_name = antibandingModesNames[new_val];
885             if(is_supported(CameraParameters::KEY_SUPPORTED_ANTIBANDING, mode_name))
886                 params.set(CameraParameters::KEY_ANTIBANDING, mode_name);
887             else
888                 LOGE("Antibanding mode %s is not supported.", mode_name);
889         } else {
890             LOGE("Antibanding mode value not in valid range.");
891         }
892     }
893     break;
894     default:
895         LOGW("CameraHandler::setProperty - Unsupported property.");
896     };
897 }
898
899 void CameraHandler::applyProperties(CameraHandler** ppcameraHandler)
900 {
901     LOGD("CameraHandler::applyProperties()");
902
903     if (ppcameraHandler == 0)
904     {
905         LOGE("applyProperties: Passed NULL ppcameraHandler");
906         return;
907     }
908
909     if (*ppcameraHandler == 0)
910     {
911         LOGE("applyProperties: Passed NULL *ppcameraHandler");
912         return;
913     }
914
915     CameraParameters curCameraParameters((*ppcameraHandler)->params.flatten());
916
917 #if defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3) || defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) || defined(ANDROID_r4_3_0)
918     CameraHandler* handler=*ppcameraHandler;
919
920     handler->camera->stopPreview();
921     handler->camera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP);
922
923     status_t reconnectStatus = handler->camera->reconnect();
924     if (reconnectStatus != 0)
925     {
926         LOGE("applyProperties: failed to reconnect camera (status %d)", reconnectStatus);
927         return;
928     }
929
930     handler->camera->setParameters(curCameraParameters.flatten());
931     handler->params.unflatten(curCameraParameters.flatten());
932
933     status_t bufferStatus;
934 # if defined(ANDROID_r4_0_0) || defined(ANDROID_r4_0_3)
935     sp<SurfaceTexture> surfaceTexture = new SurfaceTexture(MAGIC_OPENCV_TEXTURE_ID);
936     bufferStatus = handler->camera->setPreviewTexture(surfaceTexture);
937     if (bufferStatus != 0)
938         LOGE("applyProperties: failed setPreviewTexture call (status %d); camera might not work correctly", bufferStatus);
939 # elif defined(ANDROID_r4_1_1) || defined(ANDROID_r4_2_0) || defined(ANDROID_r4_3_0)
940     sp<BufferQueue> bufferQueue = new BufferQueue();
941     sp<BufferQueue::ConsumerListener> queueListener = new ConsumerListenerStub();
942     bufferQueue->consumerConnect(queueListener);
943     bufferStatus = handler->camera->setPreviewTexture(bufferQueue);
944     if (bufferStatus != 0)
945         LOGE("applyProperties: failed setPreviewTexture call; camera might not work correctly");
946 # endif
947
948     handler->camera->setPreviewCallbackFlags( CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK | CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK);//with copy
949
950     LOGD("Starting preview");
951     status_t previewStatus = handler->camera->startPreview();
952
953     if (previewStatus != 0)
954     {
955         LOGE("initCameraConnect: startPreview() fails. Closing camera connection...");
956         handler->closeCameraConnect();
957         handler = NULL;
958     }
959     else
960     {
961         LOGD("Preview started successfully");
962     }
963 #else
964     CameraHandler* previousCameraHandler=*ppcameraHandler;
965     CameraCallback cameraCallback=previousCameraHandler->cameraCallback;
966     void* userData=previousCameraHandler->userData;
967     int cameraId=previousCameraHandler->cameraId;
968
969     LOGD("CameraHandler::applyProperties(): before previousCameraHandler->closeCameraConnect");
970     previousCameraHandler->closeCameraConnect();
971     LOGD("CameraHandler::applyProperties(): after previousCameraHandler->closeCameraConnect");
972
973     LOGD("CameraHandler::applyProperties(): before initCameraConnect");
974     CameraHandler* handler=initCameraConnect(cameraCallback, cameraId, userData, &curCameraParameters);
975     LOGD("CameraHandler::applyProperties(): after initCameraConnect, handler=0x%x", (int)handler);
976     if (handler == NULL) {
977         LOGE("ERROR in applyProperties --- cannot reinit camera");
978         handler=initCameraConnect(cameraCallback, cameraId, userData, NULL);
979         LOGD("CameraHandler::applyProperties(): repeate initCameraConnect after ERROR, handler=0x%x", (int)handler);
980         if (handler == NULL) {
981             LOGE("ERROR in applyProperties --- cannot reinit camera AGAIN --- cannot do anything else");
982         }
983     }
984     (*ppcameraHandler)=handler;
985 #endif
986 }
987
988
989 extern "C" {
990
991 void* initCameraConnectC(void* callback, int cameraId, void* userData)
992 {
993     return CameraHandler::initCameraConnect((CameraCallback)callback, cameraId, userData, NULL);
994 }
995
996 void closeCameraConnectC(void** camera)
997 {
998     CameraHandler** cc = (CameraHandler**)camera;
999     (*cc)->closeCameraConnect();
1000     *cc = 0;
1001 }
1002
1003 double getCameraPropertyC(void* camera, int propIdx)
1004 {
1005     return ((CameraHandler*)camera)->getProperty(propIdx);
1006 }
1007
1008 void setCameraPropertyC(void* camera, int propIdx, double value)
1009 {
1010     ((CameraHandler*)camera)->setProperty(propIdx,value);
1011 }
1012
1013 void applyCameraPropertiesC(void** camera)
1014 {
1015     CameraHandler::applyProperties((CameraHandler**)camera);
1016 }
1017
1018 }