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 6c92e988ea6ce8eecd111a946f0200f1f2454d81..dc85d9f7902abd21d6a00e6c84b7b0bc78c6860b 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 d4b1c9ebdae9682fe1f805aa6ed6bc8dd26f99cd..7609441cb1a34fd8e81b59f25842776ff88e400d 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 1277f04aeb0bba92a1fb9377c60dc65d8ee1ed5c..1285da3bce2888b730a0958beb76d55364560752 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