Add task thread for some APIs related preview restart internally 39/96839/3
authorJeongmo Yang <jm80.yang@samsung.com>
Thu, 10 Nov 2016 10:32:07 +0000 (19:32 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Mon, 14 Nov 2016 05:00:28 +0000 (14:00 +0900)
The timeout could be occurred in camerasrc if app sets preview callback and call some APIs related preview restart internally,
because, for restarting preview, all camera buffers should be returned to camerasrc,
but, return buffer event can not be processed while calling some APIs which restarts preview internally.(deadlock)
so, added task thread and the APIs are processed in the task thread to process return buffer event immediately.

[Version] 0.2.56
[Profile] Common
[Issue Type] Update
[Dependency module] N/A
[Test] [M(T) - Boot=(OK), sdb=(OK), Home=(OK), Touch=(OK), Version=tizen-mobile_20161110.1]

Change-Id: I6a55b0aa5f71f6595b75bce823f71c35b1a61287
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
muse/include/muse_camera_internal.h
muse/src/muse_camera_dispatcher.c
packaging/mmsvc-camera.spec

index 6c92e98..dc85d9f 100644 (file)
@@ -26,6 +26,7 @@ extern "C" {
   * @brief This file contains the muse camera internal API for framework, related structures and enumerations.
   */
 
+#include <muse_core_ipc.h>
 #include <muse_camera.h>
 #include <legacy_camera_internal.h>
 
@@ -36,6 +37,13 @@ extern "C" {
 #define SET_PREVIEW_CB_TYPE(muse_camera, cb_type) ((muse_camera)->preview_cb_flag |= cb_type)
 #define UNSET_PREVIEW_CB_TYPE(muse_camera, cb_type) ((muse_camera)->preview_cb_flag &= ~cb_type)
 
+
+typedef struct {
+       int api;
+       int class;
+       int value;
+} muse_camera_task_job_s;
+
 typedef struct {
        camera_h camera_handle;
        tbm_bufmgr bufmgr;
@@ -46,6 +54,12 @@ typedef struct {
        GCond preview_cb_cond;
        guint preview_cb_flag;
        MMCamWaylandInfo wl_info;
+       GThread *task_thread;
+       GMutex task_lock;
+       GCond task_cond;
+       GQueue task_queue;
+       gboolean task_run;
+       muse_module_h module;
 } muse_camera_handle_s;
 
 
index d4b1c9e..7609441 100644 (file)
@@ -24,8 +24,6 @@
 #include <dlog.h>
 #include "muse_camera_msg.h"
 #include "muse_camera_internal.h"
-#include <muse_core.h>
-#include <muse_core_ipc.h>
 #include <mm_types.h>
 #include <muse_core_security.h>
 #include <gst/gst.h>
@@ -477,6 +475,7 @@ static int _camera_remove_export_data(muse_module_h module, int key, int remove_
        return FALSE;
 }
 
+
 void _camera_dispatcher_capturing_cb(camera_image_data_s* image, camera_image_data_s* postview, camera_image_data_s* thumbnail, void *user_data)
 {
        muse_camera_handle_s *muse_camera = NULL;
@@ -1136,6 +1135,139 @@ void _camera_dispatcher_hdr_progress_cb(int percent, void *user_data)
 }
 
 
+static void _camera_task_add_job(muse_camera_handle_s *muse_camera, int api, int class, int value)
+{
+       muse_camera_task_job_s *job = NULL;
+
+       if (!muse_camera) {
+               LOGE("NULL handle");
+               return;
+       }
+
+       job = g_new0(muse_camera_task_job_s, 1);
+
+       job->api = api;
+       job->class = class;
+       job->value = value;
+
+       LOGD("push job - api %d", api);
+
+       g_mutex_lock(&muse_camera->task_lock);
+       g_queue_push_tail(&muse_camera->task_queue, (gpointer)job);
+       g_cond_signal(&muse_camera->task_cond);
+       g_mutex_unlock(&muse_camera->task_lock);
+
+       return;
+}
+
+
+static void __camera_task_process_job(muse_camera_handle_s *muse_camera, muse_camera_task_job_s *job)
+{
+       int ret = CAMERA_ERROR_NONE;
+
+       if (!job) {
+               LOGE("NULL job");
+               return;
+       }
+
+       if (!muse_camera) {
+               LOGE("NULL handle");
+               goto _PROCESS_DONE;
+       }
+
+       LOGD("job start - api %d, value 0x%x", job->api, job->value);
+
+       switch (job->api) {
+       case MUSE_CAMERA_API_STOP_PREVIEW:
+               ret = legacy_camera_stop_preview(muse_camera->camera_handle);
+               break;
+       case MUSE_CAMERA_API_START_CAPTURE:
+               ret = legacy_camera_start_capture(muse_camera->camera_handle,
+                       (camera_capturing_cb)_camera_dispatcher_capturing_cb,
+                       (camera_capture_completed_cb)_camera_dispatcher_capture_completed_cb,
+                       (void *)muse_camera->module);
+               break;
+       case MUSE_CAMERA_API_SET_PREVIEW_RESOLUTION:
+               ret = legacy_camera_set_preview_resolution(muse_camera->camera_handle, \
+                       job->value >> 16, 0x0000ffff & job->value);
+               break;
+       case MUSE_CAMERA_API_SET_CAPTURE_RESOLUTION:
+               ret = legacy_camera_set_capture_resolution(muse_camera->camera_handle, \
+                       job->value >> 16, 0x0000ffff & job->value);
+               break;
+       case MUSE_CAMERA_API_ATTR_SET_HDR_MODE:
+               ret = legacy_camera_attr_set_hdr_mode(muse_camera->camera_handle, \
+                       (camera_attr_hdr_mode_e)job->value);
+               break;
+       default:
+               LOGE("unhandled task - api %d", job->api);
+               goto _PROCESS_DONE;
+       }
+
+       LOGD("job done - api %d, ret 0x%x", job->api, ret);
+
+       muse_camera_msg_return(job->api, job->class, ret, muse_camera->module);
+
+_PROCESS_DONE:
+       g_free(job);
+       job = NULL;
+
+       return;
+}
+
+
+static void *_camera_dispatcher_task_func(gpointer data)
+{
+       muse_camera_handle_s *muse_camera = (muse_camera_handle_s *)data;
+       muse_camera_task_job_s *job = NULL;
+
+       if (!muse_camera) {
+               LOGE("NULL handle");
+               return NULL;
+       }
+
+       LOGD("enter");
+
+       g_mutex_lock(&muse_camera->task_lock);
+
+       while (true) {
+               if (g_queue_is_empty(&muse_camera->task_queue)) {
+                       LOGD("empty queue. wait signal");
+                       g_cond_wait(&muse_camera->task_cond, &muse_camera->task_lock);
+                       LOGD("signal received");
+               }
+
+               if (!muse_camera->task_run) {
+                       LOGD("stop task thread");
+                       break;
+               }
+
+               job = (muse_camera_task_job_s *)g_queue_pop_head(&muse_camera->task_queue);
+
+               g_mutex_unlock(&muse_camera->task_lock);
+
+               __camera_task_process_job(muse_camera, job);
+
+               g_mutex_lock(&muse_camera->task_lock);
+       }
+
+       while (!g_queue_is_empty(&muse_camera->task_queue)) {
+               job = (muse_camera_task_job_s *)g_queue_pop_head(&muse_camera->task_queue);
+
+               if (job)
+                       LOGW("remained job - api %d", job->api);
+
+               __camera_task_process_job(muse_camera, job);
+       }
+
+       g_mutex_unlock(&muse_camera->task_lock);
+
+       LOGD("leave");
+
+       return NULL;
+}
+
+
 int camera_dispatcher_create(muse_module_h module)
 {
        int ret = CAMERA_ERROR_NONE;
@@ -1194,6 +1326,18 @@ int camera_dispatcher_create(muse_module_h module)
                return MUSE_CAMERA_ERROR_NONE;
        }
 
+       g_mutex_init(&muse_camera->task_lock);
+       g_cond_init(&muse_camera->task_cond);
+       g_queue_init(&muse_camera->task_queue);
+
+       muse_camera->task_run = true;
+       muse_camera->task_thread = g_thread_try_new("camera_task_thread",
+               _camera_dispatcher_task_func, (gpointer)muse_camera, NULL);
+       if (!muse_camera->task_thread) {
+               LOGE("failed to create new thread for task");
+               goto _CREATE_ERROR;
+       }
+
        ret = legacy_camera_set_state_changed_cb(muse_camera->camera_handle,
                (camera_state_changed_cb)_camera_dispatcher_state_changed_cb,
                (void *)module);
@@ -1219,14 +1363,33 @@ int camera_dispatcher_create(muse_module_h module)
        g_mutex_init(&muse_camera->preview_cb_lock);
        g_cond_init(&muse_camera->preview_cb_cond);
        muse_camera->preview_cb_flag = 0;
+       muse_camera->module = module;
 
        LOGD("handle : 0x%x", muse_camera);
+
        muse_core_ipc_set_handle(module, (intptr_t)muse_camera);
        muse_camera_msg_return1(api, class, ret, module, MUSE_CAMERA_GET_TYPE_POINTER, -1, "handle", 0, muse_camera);
 
        return MUSE_CAMERA_ERROR_NONE;
 
 _CREATE_ERROR:
+       if (muse_camera->task_thread) {
+               g_mutex_lock(&muse_camera->task_lock);
+               muse_camera->task_run = false;
+               g_cond_signal(&muse_camera->task_cond);
+               g_mutex_unlock(&muse_camera->task_lock);
+
+               LOGE("task thread join");
+
+               g_thread_join(muse_camera->task_thread);
+               g_thread_unref(muse_camera->task_thread);
+               muse_camera->task_thread = NULL;
+       }
+
+       g_mutex_clear(&muse_camera->task_lock);
+       g_cond_clear(&muse_camera->task_cond);
+       g_queue_clear(&muse_camera->task_queue);
+
        legacy_camera_destroy(muse_camera->camera_handle);
        muse_camera->camera_handle = NULL;
 
@@ -1282,6 +1445,23 @@ int camera_dispatcher_destroy(muse_module_h module)
 
                muse_camera->bufmgr = NULL;
 
+               if (muse_camera->task_thread) {
+                       g_mutex_lock(&muse_camera->task_lock);
+                       muse_camera->task_run = false;
+                       g_cond_signal(&muse_camera->task_cond);
+                       g_mutex_unlock(&muse_camera->task_lock);
+
+                       LOGE("task thread join");
+
+                       g_thread_join(muse_camera->task_thread);
+                       g_thread_unref(muse_camera->task_thread);
+                       muse_camera->task_thread = NULL;
+               }
+
+               g_mutex_clear(&muse_camera->task_lock);
+               g_cond_clear(&muse_camera->task_cond);
+               g_queue_clear(&muse_camera->task_queue);
+
                free(muse_camera);
                muse_camera = NULL;
        }
@@ -1311,39 +1491,28 @@ int camera_dispatcher_start_preview(muse_module_h module)
 
 int camera_dispatcher_stop_preview(muse_module_h module)
 {
-       int ret = CAMERA_ERROR_NONE;
        muse_camera_handle_s *muse_camera = NULL;
-       muse_camera_api_e api = MUSE_CAMERA_API_STOP_PREVIEW;
-       muse_camera_api_class_e class = MUSE_CAMERA_API_CLASS_IMMEDIATE;
 
        muse_camera = (muse_camera_handle_s *)muse_core_ipc_get_handle(module);
 
        LOGD("handle : %p", muse_camera);
 
-       ret = legacy_camera_stop_preview(muse_camera->camera_handle);
-
-       muse_camera_msg_return(api, class, ret, module);
+       _camera_task_add_job(muse_camera, MUSE_CAMERA_API_STOP_PREVIEW,
+               MUSE_CAMERA_API_CLASS_IMMEDIATE, 0);
 
        return MUSE_CAMERA_ERROR_NONE;
 }
 
 int camera_dispatcher_start_capture(muse_module_h module)
 {
-       int ret = CAMERA_ERROR_NONE;
        muse_camera_handle_s *muse_camera = NULL;
-       muse_camera_api_e api = MUSE_CAMERA_API_START_CAPTURE;
-       muse_camera_api_class_e class = MUSE_CAMERA_API_CLASS_IMMEDIATE;
 
        muse_camera = (muse_camera_handle_s *)muse_core_ipc_get_handle(module);
 
-       LOGD("Enter, handle : %p, module : %p", muse_camera, module);
-
-       ret = legacy_camera_start_capture(muse_camera->camera_handle,
-               (camera_capturing_cb)_camera_dispatcher_capturing_cb,
-               (camera_capture_completed_cb)_camera_dispatcher_capture_completed_cb,
-               (void *)module);
+       LOGD("handle : %p", muse_camera);
 
-       muse_camera_msg_return(api, class, ret, module);
+       _camera_task_add_job(muse_camera, MUSE_CAMERA_API_START_CAPTURE,
+               MUSE_CAMERA_API_CLASS_IMMEDIATE, 0);
 
        return MUSE_CAMERA_ERROR_NONE;
 }
@@ -1653,52 +1822,30 @@ int camera_dispatcher_set_display(muse_module_h module)
 
 int camera_dispatcher_set_preview_resolution(muse_module_h module)
 {
-       int ret = CAMERA_ERROR_NONE;
-       muse_camera_handle_s *muse_camera = NULL;
        int value = 0;
-       int width = 0;
-       int height = 0;
-       muse_camera_api_e api = MUSE_CAMERA_API_SET_PREVIEW_RESOLUTION;
-       muse_camera_api_class_e class = MUSE_CAMERA_API_CLASS_IMMEDIATE;
+       muse_camera_handle_s *muse_camera = NULL;
 
        muse_camera = (muse_camera_handle_s *)muse_core_ipc_get_handle(module);
 
        muse_camera_msg_get(value, muse_core_client_get_msg(module));
 
-       width = value >> 16;
-       height = 0x0000ffff & value;
-
-       LOGD("0x%x -> %dx%d", value, width, height);
-
-       ret = legacy_camera_set_preview_resolution(muse_camera->camera_handle, width, height);
-
-       muse_camera_msg_return(api, class, ret, module);
+       _camera_task_add_job(muse_camera, MUSE_CAMERA_API_SET_PREVIEW_RESOLUTION,
+               MUSE_CAMERA_API_CLASS_IMMEDIATE, value);
 
        return MUSE_CAMERA_ERROR_NONE;
 }
 
 int camera_dispatcher_set_capture_resolution(muse_module_h module)
 {
-       int ret = CAMERA_ERROR_NONE;
-       muse_camera_handle_s *muse_camera = NULL;
        int value = 0;
-       int width = 0;
-       int height = 0;
-       muse_camera_api_e api = MUSE_CAMERA_API_SET_CAPTURE_RESOLUTION;
-       muse_camera_api_class_e class = MUSE_CAMERA_API_CLASS_IMMEDIATE;
+       muse_camera_handle_s *muse_camera = NULL;
 
        muse_camera = (muse_camera_handle_s *)muse_core_ipc_get_handle(module);
 
        muse_camera_msg_get(value, muse_core_client_get_msg(module));
 
-       width = value >> 16;
-       height = 0x0000ffff & value;
-
-       LOGD("handle : 0x%x, set_width : %d, set_height : %d", muse_camera, width, height);
-
-       ret = legacy_camera_set_capture_resolution(muse_camera->camera_handle, width, height);
-
-       muse_camera_msg_return(api, class, ret, module);
+       _camera_task_add_job(muse_camera, MUSE_CAMERA_API_SET_CAPTURE_RESOLUTION,
+               MUSE_CAMERA_API_CLASS_IMMEDIATE, value);
 
        return MUSE_CAMERA_ERROR_NONE;
 }
@@ -3912,23 +4059,17 @@ int camera_dispatcher_attr_get_stream_flip(muse_module_h module)
 
 int camera_dispatcher_attr_set_hdr_mode(muse_module_h module)
 {
-       int ret = CAMERA_ERROR_NONE;
+       int set_mode = 0;
        muse_camera_handle_s *muse_camera = NULL;
-       muse_camera_api_e api = MUSE_CAMERA_API_ATTR_SET_HDR_MODE;
-       muse_camera_api_class_e class = MUSE_CAMERA_API_CLASS_IMMEDIATE;
-       int set_mode;
 
        muse_camera = (muse_camera_handle_s *)muse_core_ipc_get_handle(module);
 
-       muse_camera_msg_get(set_mode, muse_core_client_get_msg(module));
-
        LOGD("handle : %p", muse_camera);
 
-       ret = legacy_camera_attr_set_hdr_mode(muse_camera->camera_handle, (camera_attr_hdr_mode_e)set_mode);
-
-       LOGD("ret : 0x%x", ret);
+       muse_camera_msg_get(set_mode, muse_core_client_get_msg(module));
 
-       muse_camera_msg_return(api, class, ret, module);
+       _camera_task_add_job(muse_camera, MUSE_CAMERA_API_ATTR_SET_HDR_MODE,
+               MUSE_CAMERA_API_CLASS_IMMEDIATE, set_mode);
 
        return MUSE_CAMERA_ERROR_NONE;
 }
index 1277f04..1285da3 100644 (file)
@@ -1,6 +1,6 @@
 Name:       mmsvc-camera
 Summary:    A Camera module for muse server
-Version:    0.2.55
+Version:    0.2.56
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0