Release version 0.2.18 04/50804/1 accepted/tizen/mobile/20151103.024650 accepted/tizen/tv/20151103.024659 accepted/tizen/wearable/20151103.024712 submit/tizen/20151102.111246
authorJeongmo Yang <jm80.yang@samsung.com>
Mon, 2 Nov 2015 10:32:42 +0000 (19:32 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Mon, 2 Nov 2015 10:32:42 +0000 (19:32 +0900)
1. Support idle callback for 2.4 API compatibility
2. Remove unused pkgconfig - json, eom

Change-Id: I59c0f84e0a26ecfd2c8f4984b591384142a2e615
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
include/camera.h
include/camera_private.h
packaging/capi-media-camera.spec
src/camera.c
test/multimedia_camera_test.c

index c08c8df..154458a 100644 (file)
@@ -817,7 +817,7 @@ int camera_stop_preview(camera_h camera);
  * @see camera_attr_set_image_quality()
  * @see camera_attr_get_image_quality()
  */
-int camera_start_capture(camera_h camera, camera_capturing_cb capturing_cb , camera_capture_completed_cb completed_cb , void *user_data);
+int camera_start_capture(camera_h camera, camera_capturing_cb capturing_cb, camera_capture_completed_cb completed_cb, void *user_data);
 
 /**
  * @brief Starts continuously capturing still images.
index c7daee5..3339ae8 100644 (file)
@@ -70,16 +70,26 @@ typedef struct _callback_cb_info {
        GMutex *pMutex;
        GCond event_cond;
        GMutex event_mutex;
+       GList *idle_event_list;
+       GCond idle_event_cond;
+       GMutex idle_event_mutex;
        gint *activating;
        tbm_bufmgr bufmgr;
        GQueue *event_queue;
 } callback_cb_info_s;
 
-typedef struct _event_info_s {
+typedef struct _camera_event_s {
        callback_cb_info_s *cb_info;
        gchar recvMsg[MUSE_CAMERA_MSG_MAX_LENGTH];
        muse_camera_event_e event;
-} event_info_s;
+} camera_event_s;
+
+typedef struct _camera_idle_event_s {
+       callback_cb_info_s *cb_info;
+       gchar recvMsg[MUSE_CAMERA_MSG_MAX_LENGTH];
+       muse_camera_event_e event;
+       GMutex event_mutex;
+} camera_idle_event_s;
 
 typedef struct _camera_cli_s {
        intptr_t remote_handle;
index e481bf1..7a99abd 100644 (file)
@@ -3,7 +3,7 @@
 
 Name:       capi-media-camera
 Summary:    A Camera API
-Version:    0.2.17
+Version:    0.2.18
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
@@ -24,9 +24,7 @@ BuildRequires:  pkgconfig(mm-camcorder)
 %if %{with wayland}
 BuildRequires:  pkgconfig(ecore-wayland)
 %endif
-BuildRequires:  pkgconfig(json)
 BuildRequires:  pkgconfig(libtbm)
-BuildRequires:  pkgconfig(eom)
 
 Requires(post): /sbin/ldconfig
 Requires(postun): /sbin/ldconfig
index 67c88de..698179f 100755 (executable)
@@ -89,7 +89,7 @@ static void _release_imported_bo(tbm_bo *bo)
        return;
 }
 
-static int client_wait_for_cb_return(muse_camera_api_e api, callback_cb_info_s *cb_info, int time_out)
+static int _client_wait_for_cb_return(muse_camera_api_e api, callback_cb_info_s *cb_info, int time_out)
 {
        int ret = CAMERA_ERROR_NONE;
        gint64 end_time;
@@ -527,7 +527,7 @@ static void _client_user_callback(callback_cb_info_s *cb_info, char *recvMsg, mu
 
 static void *_event_handler(gpointer data)
 {
-       event_info_s *e_info = NULL;
+       camera_event_s *cam_event = NULL;
        callback_cb_info_s *cb_info = (callback_cb_info_s *)data;
 
        if (cb_info == NULL) {
@@ -551,14 +551,14 @@ static void *_event_handler(gpointer data)
                        }
                }
 
-               e_info = (event_info_s *)g_queue_pop_head(cb_info->event_queue);
+               cam_event = (camera_event_s *)g_queue_pop_head(cb_info->event_queue);
 
                g_mutex_unlock(&cb_info->event_mutex);
 
-               if (e_info) {
-                       _client_user_callback(e_info->cb_info, e_info->recvMsg, e_info->event);
-                       free(e_info);
-                       e_info = NULL;
+               if (cam_event) {
+                       _client_user_callback(cam_event->cb_info, cam_event->recvMsg, cam_event->event);
+                       free(cam_event);
+                       cam_event = NULL;
                } else {
                        LOGW("NULL event info");
                }
@@ -568,11 +568,11 @@ static void *_event_handler(gpointer data)
 
        /* remove remained event */
        while (!g_queue_is_empty(cb_info->event_queue)) {
-               e_info = (event_info_s *)g_queue_pop_head(cb_info->event_queue);
-               if (e_info) {
-                       LOGD("remove event info %p", e_info);
-                       free(e_info);
-                       e_info = NULL;
+               cam_event = (camera_event_s *)g_queue_pop_head(cb_info->event_queue);
+               if (cam_event) {
+                       LOGD("remove event info %p", cam_event);
+                       free(cam_event);
+                       cam_event = NULL;
                } else {
                        LOGW("NULL event info");
                }
@@ -587,21 +587,119 @@ static void *_event_handler(gpointer data)
 
 static bool _camera_idle_event_callback(void *data)
 {
-       event_info_s *e_info = (event_info_s *)data;
+       callback_cb_info_s *cb_info = NULL;
+       camera_idle_event_s *cam_idle_event = (camera_idle_event_s *)data;
 
-       if (e_info == NULL) {
-               LOGE("event info is NULL");
+       if (cam_idle_event == NULL) {
+               LOGE("cam_idle_event is NULL");
                return false;
        }
 
-       _client_user_callback(e_info->cb_info, e_info->recvMsg, e_info->event);
-       free(e_info);
-       e_info = NULL;
+       /* lock event */
+       g_mutex_lock(&cam_idle_event->event_mutex);
+
+       cb_info = cam_idle_event->cb_info;
+       if (cb_info == NULL) {
+               LOGW("cb_info is NULL. event %d", cam_idle_event->event);
+               goto IDLE_EVENT_CALLBACK_DONE;
+       }
+
+       /* remove event from list */
+       g_mutex_lock(&cb_info->idle_event_mutex);
+       if (cb_info->idle_event_list) {
+               cb_info->idle_event_list = g_list_remove(cb_info->idle_event_list, (gpointer)cam_idle_event);
+       }
+       g_mutex_unlock(&cb_info->idle_event_mutex);
+
+       /* user callback */
+       _client_user_callback(cam_idle_event->cb_info, cam_idle_event->recvMsg, cam_idle_event->event);
+
+       /* send signal for waiting thread */
+       g_cond_signal(&cb_info->idle_event_cond);
+
+IDLE_EVENT_CALLBACK_DONE:
+       /* unlock and release event */
+       g_mutex_unlock(&cam_idle_event->event_mutex);
+       g_mutex_clear(&cam_idle_event->event_mutex);
+
+       free(cam_idle_event);
+       cam_idle_event = NULL;
 
        return false;
 }
 
-static void *client_cb_handler(gpointer data)
+static void _camera_remove_idle_event_all(callback_cb_info_s *cb_info)
+{
+       camera_idle_event_s *cam_idle_event = NULL;
+       gboolean ret = TRUE;
+       GList *list = NULL;
+       gint64 end_time = 0;
+
+       if (cb_info == NULL) {
+               LOGE("cb_info is NULL");
+               return;
+       }
+
+       g_mutex_lock(&cb_info->idle_event_mutex);
+
+       if (cb_info->idle_event_list) {
+               LOGD("No idle event is remained.");
+       } else {
+               list = cb_info->idle_event_list;
+
+               while (list) {
+                       cam_idle_event = list->data;
+                       list = g_list_next(list);
+
+                       if (!cam_idle_event) {
+                               LOGW("Fail to remove idle event. The event is NULL");
+                       } else {
+                               if (g_mutex_trylock(&cam_idle_event->event_mutex)) {
+                                       ret = g_idle_remove_by_data(cam_idle_event);
+
+                                       LOGD("remove idle event [%p], ret[%d]", cam_idle_event, ret);
+
+                                       if (ret == FALSE) {
+                                               cam_idle_event->cb_info = NULL;
+                                               LOGW("idle callback for event %p will be called later", cam_idle_event);
+                                       }
+
+                                       cb_info->idle_event_list = g_list_remove(cb_info->idle_event_list, (gpointer)cam_idle_event);
+
+                                       g_mutex_unlock(&cam_idle_event->event_mutex);
+
+                                       if (ret == TRUE) {
+                                               g_mutex_clear(&cam_idle_event->event_mutex);
+
+                                               free(cam_idle_event);
+                                               cam_idle_event = NULL;
+
+                                               LOGD("remove idle event done");
+                                       }
+                               } else {
+                                       LOGW("event lock failed. it's being called...");
+
+                                       end_time = g_get_monotonic_time () + G_TIME_SPAN_MILLISECOND * 100;
+
+                                       if (g_cond_wait_until(&cb_info->idle_event_cond, &cb_info->idle_event_mutex, end_time)) {
+                                               LOGW("signal received");
+                                       } else {
+                                               LOGW("timeout");
+                                       }
+                               }
+                       }
+               }
+
+               g_list_free(cb_info->idle_event_list);
+               cb_info->idle_event_list = NULL;
+       }
+
+       g_mutex_unlock(&cb_info->idle_event_mutex);
+
+       return;
+}
+
+static void *_client_cb_handler(gpointer data)
 {
        int ret = 0;
        int api = 0;
@@ -703,37 +801,60 @@ static void *client_cb_handler(gpointer data)
                                } else if(api == MUSE_CAMERA_CB_EVENT) {
                                        int event = -1;
                                        int class = -1;
+                                       camera_event_s *cam_event = NULL;
+                                       camera_idle_event_s *cam_idle_event = NULL;
 
-                                       if (muse_camera_msg_get(event, parseStr[i]) &&
-                                           muse_camera_msg_get(class, parseStr[i])) {
-                                               event_info_s *e_info = NULL;
-
-                                               if (class == MUSE_CAMERA_EVENT_CLASS_NORMAL ||
-                                                   class == MUSE_CAMERA_EVENT_CLASS_IDLE) {
-                                                       e_info = (event_info_s *)malloc(sizeof(event_info_s));
-                                                       if (e_info) {
-                                                               e_info->event = event;
-                                                               e_info->cb_info = cb_info;
-                                                               memcpy(e_info->recvMsg, recvMsg, sizeof(e_info->recvMsg));
-
-                                                               if (class == MUSE_CAMERA_EVENT_CLASS_NORMAL) {
-                                                                       LOGD("add event to EVENT QUEUE : %d", event);
-                                                                       g_mutex_lock(&cb_info->event_mutex);
-                                                                       g_queue_push_tail(cb_info->event_queue, (gpointer)e_info);
-                                                                       g_cond_signal(&cb_info->event_cond);
-                                                                       g_mutex_unlock(&cb_info->event_mutex);
-                                                               } else {
-                                                                       LOGD("add event to IDLE : %d", event);
-                                                                       g_idle_add_full(G_PRIORITY_DEFAULT, (GSourceFunc)_camera_idle_event_callback, (gpointer)e_info, NULL);
-                                                               }
-                                                       } else {
-                                                               LOGE("e_info alloc failed");
-                                                       }
-                                               } else if (class == MUSE_CAMERA_EVENT_CLASS_IMMEDIATE) {
-                                                       _client_user_callback(cb_info, recvMsg, event);
+                                       if (!muse_camera_msg_get(event, parseStr[i]) ||
+                                           !muse_camera_msg_get(class, parseStr[i])) {
+                                               LOGE("failed to get event %d, class %d", event, class);
+                                               continue;
+                                       }
+
+                                       switch (class) {
+                                       case MUSE_CAMERA_EVENT_CLASS_NORMAL:
+                                               cam_event = (camera_event_s *)malloc(sizeof(camera_event_s));
+                                               if (cam_event) {
+                                                       cam_event->event = event;
+                                                       cam_event->cb_info = cb_info;
+                                                       memcpy(cam_event->recvMsg, recvMsg, sizeof(cam_event->recvMsg));
+
+                                                       LOGD("add event to EVENT QUEUE : %d", event);
+                                                       g_mutex_lock(&cb_info->event_mutex);
+                                                       g_queue_push_tail(cb_info->event_queue, (gpointer)cam_event);
+                                                       g_cond_signal(&cb_info->event_cond);
+                                                       g_mutex_unlock(&cb_info->event_mutex);
+                                               } else {
+                                                       LOGE("cam_event alloc failed");
+                                               }
+                                               break;
+                                       case MUSE_CAMERA_EVENT_CLASS_IMMEDIATE:
+                                               _client_user_callback(cb_info, recvMsg, event);
+                                               break;
+                                       case MUSE_CAMERA_EVENT_CLASS_IDLE:
+                                               cam_idle_event = (camera_idle_event_s *)malloc(sizeof(camera_idle_event_s));
+                                               if (cam_idle_event) {
+                                                       cam_idle_event->event = event;
+                                                       cam_idle_event->cb_info = cb_info;
+                                                       g_mutex_init(&cam_idle_event->event_mutex);
+                                                       memcpy(cam_idle_event->recvMsg, recvMsg, sizeof(cam_idle_event->recvMsg));
+
+                                                       LOGD("add event to IDLE : %d", event);
+
+                                                       g_mutex_lock(&cb_info->idle_event_mutex);
+                                                       cb_info->idle_event_list = g_list_append(cb_info->idle_event_list, (gpointer)cam_idle_event);
+                                                       g_mutex_unlock(&cb_info->idle_event_mutex);
+
+                                                       g_idle_add_full(G_PRIORITY_DEFAULT,
+                                                                       (GSourceFunc)_camera_idle_event_callback,
+                                                                       (gpointer)cam_idle_event,
+                                                                       NULL);
                                                } else {
-                                                       LOGE("unknown class %d", class);
+                                                       LOGE("cam_idle_event alloc failed");
                                                }
+                                               break;
+                                       default:
+                                               LOGE("unknown class %d", class);
+                                               break;
                                        }
                                } else {
                                        LOGW("unknown api : %d", api);
@@ -763,7 +884,7 @@ CB_HANDLER_EXIT:
        return NULL;
 }
 
-static callback_cb_info_s *client_callback_new(gint sockfd)
+static callback_cb_info_s *_client_callback_new(gint sockfd)
 {
        callback_cb_info_s *cb_info;
        GCond *camera_cond;
@@ -781,18 +902,20 @@ static callback_cb_info_s *client_callback_new(gint sockfd)
        cb_info->pCond = camera_cond;
        cb_info->pMutex = camera_mutex;
        cb_info->activating = camera_activ;
-       cb_info->msg_rcv_thread = g_thread_new("msg_rcv_thread", client_cb_handler, (gpointer)cb_info);
+       cb_info->msg_rcv_thread = g_thread_new("msg_rcv_thread", _client_cb_handler, (gpointer)cb_info);
 
        g_atomic_int_set(&cb_info->event_thread_running, 1);
        g_mutex_init(&cb_info->event_mutex);
        g_cond_init(&cb_info->event_cond);
+       g_mutex_init(&cb_info->idle_event_mutex);
+       g_cond_init(&cb_info->idle_event_cond);
        cb_info->event_queue = g_queue_new();
        cb_info->event_thread = g_thread_new("event_thread", _event_handler, (gpointer)cb_info);
 
        return cb_info;
 }
 
-static void client_callback_destroy(callback_cb_info_s * cb_info)
+static void _client_callback_destroy(callback_cb_info_s * cb_info)
 {
        g_return_if_fail(cb_info != NULL);
 
@@ -817,6 +940,8 @@ static void client_callback_destroy(callback_cb_info_s * cb_info)
        cb_info->event_queue = NULL;
        g_mutex_clear(&cb_info->event_mutex);
        g_cond_clear(&cb_info->event_cond);
+       g_mutex_clear(&cb_info->idle_event_mutex);
+       g_cond_clear(&cb_info->idle_event_cond);
 
        LOGD("event thread removed");
 
@@ -888,11 +1013,11 @@ int camera_create(camera_device_e device, camera_h* camera)
                goto ErrorExit;
        }
 
-       pc->cb_info = client_callback_new(sock_fd);
+       pc->cb_info = _client_callback_new(sock_fd);
 
        LOGD("cb info : %d", pc->cb_info->fd);
 
-       ret = client_wait_for_cb_return(api, pc->cb_info, CALLBACK_TIME_OUT);
+       ret = _client_wait_for_cb_return(api, pc->cb_info, CALLBACK_TIME_OUT);
        if (ret == CAMERA_ERROR_NONE) {
                intptr_t handle = 0;
                muse_camera_msg_get_pointer(handle, pc->cb_info->recvMsg);
@@ -918,7 +1043,7 @@ ErrorExit:
        bufmgr = NULL;
 
        if (pc) {
-               client_callback_destroy(pc->cb_info);
+               _client_callback_destroy(pc->cb_info);
                pc->cb_info = NULL;
                g_free(pc);
                pc = NULL;
@@ -951,7 +1076,8 @@ ErrorExit:
 
        muse_camera_msg_send(api, sock_fd, pc->cb_info, ret);
        if (ret == CAMERA_ERROR_NONE) {
-               client_callback_destroy(pc->cb_info);
+               _camera_remove_idle_event_all(pc->cb_info);
+               _client_callback_destroy(pc->cb_info);
                g_free(pc);
                pc = NULL;
        } else {
@@ -1035,7 +1161,7 @@ int camera_stop_preview(camera_h camera)
        return ret;
 }
 
-int camera_start_capture(camera_h camera, camera_capturing_cb capturing_cb , camera_capture_completed_cb completed_cb , void *user_data)
+int camera_start_capture(camera_h camera, camera_capturing_cb capturing_cb, camera_capture_completed_cb completed_cb, void *user_data)
 {
        if (camera == NULL) {
                LOGE("INVALID_PARAMETER(0x%08x)",CAMERA_ERROR_INVALID_PARAMETER);
index 24d40f5..a9597bb 100644 (file)
@@ -63,8 +63,8 @@ int camera_print_state;
 int multishot_num;
 static GTimer *timer = NULL;
 
-GTimeVal previous;
-GTimeVal current;
+GTimeVal previous_time;
+GTimeVal current_time;
 GTimeVal res;
 
 /*-----------------------------------------------------------------------
@@ -222,7 +222,7 @@ typedef struct{
 /*---------------------------------------------------------------------------
 |    LOCAL VARIABLE DEFINITIONS:                                            |
 ---------------------------------------------------------------------------*/
-static cam_handle_t *hcamcorder ;
+static cam_handle_t *hcamcorder;
 
 const char *wb[SENSOR_WHITEBALANCE_NUM]={
     "None",
@@ -437,6 +437,10 @@ static inline void flush_stdin()
     while ((ch=getchar()) != EOF && ch != '\n');
 }
 
+void _camera_state_changed_cb(camera_state_e previous, camera_state_e current,bool by_policy, void *user_data){
+    printf("camera state changed %d -> %d\n", previous , current);
+}
+
 bool preview_resolution_cb(int width, int height, void *user_data)
 {
     resolution_stack *data = (resolution_stack*)user_data;
@@ -620,6 +624,15 @@ void capturing_cb(camera_image_data_s* image, camera_image_data_s* postview, cam
     return;
 }
 
+void capture_completed_cb(void *user_data)
+{
+    camera_start_preview(hcamcorder->camera);
+
+    print_menu();
+
+    return;
+}
+
 static void print_menu()
 {
     switch (hcamcorder->menu_state)
@@ -701,9 +714,7 @@ static void main_menu(gchar buf)
             camera_get_state(hcamcorder->camera, &capi_state);
             camera_attr_set_image_quality(hcamcorder->camera, 100);
             camera_set_capture_format(hcamcorder->camera, CAMERA_PIXEL_FORMAT_JPEG);
-            camera_start_capture(hcamcorder->camera, capturing_cb,NULL, NULL);
-            sleep(3);
-            camera_start_preview(hcamcorder->camera);
+            camera_start_capture(hcamcorder->camera, capturing_cb, capture_completed_cb, hcamcorder);
             break;
 
         case '2' : //multishot Capture
@@ -727,6 +738,9 @@ static void main_menu(gchar buf)
             break;
 
         case 'b' : // back
+            camera_stop_preview(hcamcorder->camera);
+            camera_destroy(hcamcorder->camera);
+            hcamcorder->camera = NULL;
             hcamcorder->menu_state = MENU_STATE_MAIN;
             mode_change();
             break;
@@ -735,9 +749,7 @@ static void main_menu(gchar buf)
             g_print("\t Invalid input \n");
             break;
         }
-    }
-
-    else {
+    } else {
         g_print("\t Invalid mode, back to upper menu \n");
         hcamcorder->menu_state = MENU_STATE_MAIN;
         mode_change();
@@ -1362,7 +1374,7 @@ static gboolean mode_change()
     }
 
     LOGD("camcorder_create");
-    g_get_current_time(&previous);
+    g_get_current_time(&previous_time);
     g_timer_reset(timer);
 
     err = camera_create(cam_info,&hcamcorder->camera);
@@ -1376,12 +1388,13 @@ static gboolean mode_change()
     }
     camera_print_state = CAMERA_STATE_CREATED;
 
+    camera_set_state_changed_cb(hcamcorder->camera, _camera_state_changed_cb, NULL);
     camera_set_display_mode(hcamcorder->camera,0 ); //MM_DISPLAY_METHOD_LETTER_BOX
     camera_set_display(hcamcorder->camera,CAMERA_DISPLAY_TYPE_OVERLAY, GET_DISPLAY(eo));
 
     camera_start_preview(hcamcorder->camera);
-    g_get_current_time(&current);
-    timersub(&current, &previous, &res);
+    g_get_current_time(&current_time);
+    timersub(&current_time, &previous_time, &res);
     LOGD("Camera Starting Time  : %ld.%lds", res.tv_sec, res.tv_usec);
     camera_print_state = CAMERA_STATE_PREVIEW;