From 1ea45536f0c98f1cc39a57a0276fe0e0d05d7550 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Mon, 2 Nov 2015 19:32:42 +0900 Subject: [PATCH] Release version 0.2.18 1. Support idle callback for 2.4 API compatibility 2. Remove unused pkgconfig - json, eom Change-Id: I59c0f84e0a26ecfd2c8f4984b591384142a2e615 Signed-off-by: Jeongmo Yang --- include/camera.h | 2 +- include/camera_private.h | 14 ++- packaging/capi-media-camera.spec | 4 +- src/camera.c | 236 ++++++++++++++++++++++++++++++--------- test/multimedia_camera_test.c | 37 ++++-- 5 files changed, 220 insertions(+), 73 deletions(-) diff --git a/include/camera.h b/include/camera.h index c08c8df..154458a 100644 --- a/include/camera.h +++ b/include/camera.h @@ -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. diff --git a/include/camera_private.h b/include/camera_private.h index c7daee5..3339ae8 100644 --- a/include/camera_private.h +++ b/include/camera_private.h @@ -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; diff --git a/packaging/capi-media-camera.spec b/packaging/capi-media-camera.spec index e481bf1..7a99abd 100644 --- a/packaging/capi-media-camera.spec +++ b/packaging/capi-media-camera.spec @@ -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 diff --git a/src/camera.c b/src/camera.c index 67c88de..698179f 100755 --- a/src/camera.c +++ b/src/camera.c @@ -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); diff --git a/test/multimedia_camera_test.c b/test/multimedia_camera_test.c index 24d40f5..a9597bb 100644 --- a/test/multimedia_camera_test.c +++ b/test/multimedia_camera_test.c @@ -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(¤t); - timersub(¤t, &previous, &res); + g_get_current_time(¤t_time); + timersub(¤t_time, &previous_time, &res); LOGD("Camera Starting Time : %ld.%lds", res.tv_sec, res.tv_usec); camera_print_state = CAMERA_STATE_PREVIEW; -- 2.7.4