fix up! Remove thread for preview callback when stop preview 19/267519/1 accepted/tizen/unified/20211214.124906 submit/tizen/20211207.021806 submit/tizen/20211213.031250
authorJeongmo Yang <jm80.yang@samsung.com>
Mon, 6 Dec 2021 12:41:15 +0000 (21:41 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Mon, 6 Dec 2021 12:41:15 +0000 (21:41 +0900)
- The deadlock is occurred with below sequence.
  1. camera_start_preview() -> create thread for preview callback
  2. camera_start_capture()
  3. got capture_completed_cb()
  4. camera_start_preview() -> create new thread for preview callback and the old one is remained.
  5. camera_stop_preview() -> send signal to remove thread for preview callback, but 1 thread is remained.

[Version] 0.4.68
[Issue Type] Bug fix

Change-Id: Id137ef203b1e0c85f597c05ae818ecb2a1b6c679
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
packaging/capi-media-camera.spec
src/camera.c

index 9a4d5f8..8e2032b 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-camera
 Summary:    A Camera API
-Version:    0.4.67
+Version:    0.4.68
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index 2ec2d1f..578efee 100644 (file)
@@ -2606,6 +2606,7 @@ int camera_destroy(camera_h camera)
 int camera_start_preview(camera_h camera)
 {
        int ret = CAMERA_ERROR_NONE;
+       int *fds = NULL;
        muse_camera_api_e api = MUSE_CAMERA_API_START_PREVIEW;
        camera_cli_s *pc = (camera_cli_s *)camera;
        camera_state_e current_state = CAMERA_STATE_NONE;
@@ -2618,12 +2619,6 @@ int camera_start_preview(camera_h camera)
        CAM_LOG_INFO("Enter : preview format %d, display type %d",
                pc->cb_info->preview_format, pc->cb_info->dp_info.type);
 
-       ret = camera_get_state(camera, &current_state);
-       if (ret != CAMERA_ERROR_NONE) {
-               CAM_LOG_ERROR("failed to get current state 0x%x", ret);
-               return ret;
-       }
-
        if (pc->cb_info->preview_format == CAMERA_PIXEL_FORMAT_INVZ &&
                pc->cb_info->dp_info.type != CAMERA_DISPLAY_TYPE_NONE) {
                CAM_LOG_ERROR("CAMERA_DISPLAY_TYPE_NONE[current %d] should be set with INVZ format",
@@ -2631,36 +2626,55 @@ int camera_start_preview(camera_h camera)
                return CAMERA_ERROR_INVALID_OPERATION;
        }
 
-       /* message handler thread for preview callback */
-       if (!__create_msg_handler_thread(&pc->cb_info->preview_cb_info,
-               CAMERA_MESSAGE_HANDLER_TYPE_PREVIEW_CB, "camera_msg_handler:preview_cb", pc->cb_info)) {
-               CAM_LOG_ERROR("preview_cb_info failed");
-               return CAMERA_ERROR_INVALID_OPERATION;
+       ret = camera_get_state(camera, &current_state);
+       if (ret != CAMERA_ERROR_NONE) {
+               CAM_LOG_ERROR("failed to get current state 0x%x", ret);
+               return ret;
        }
 
-       if (current_state == CAMERA_STATE_CREATED && pc->cb_info->user_buffer_supported) {
-               if (__camera_allocate_preview_buffer(camera))
-                       _camera_msg_send(api, pc->cb_info->fds, pc->cb_info, &ret, CAMERA_CB_NO_TIMEOUT);
-               else
-                       ret = CAMERA_ERROR_INVALID_OPERATION;
-       } else {
-               _camera_msg_send(api, NULL, pc->cb_info, &ret, CAMERA_CB_NO_TIMEOUT);
-       }
+       if (current_state == CAMERA_STATE_CREATED) {
+               if (!__create_msg_handler_thread(&pc->cb_info->preview_cb_info,
+                       CAMERA_MESSAGE_HANDLER_TYPE_PREVIEW_CB, "camera_msg_handler:preview_cb", pc->cb_info)) {
+                       CAM_LOG_ERROR("preview_cb_info failed");
+                       return CAMERA_ERROR_INVALID_OPERATION;
+               }
 
-       if (ret == CAMERA_ERROR_NONE) {
-               if (pc->cb_info->is_evas_render) {
-                       ret = _camera_start_evas_rendering(camera);
-                       if (ret != CAMERA_ERROR_NONE) {
-                               CAM_LOG_ERROR("stop preview because of error");
-                               _camera_msg_send(MUSE_CAMERA_API_STOP_PREVIEW, NULL, pc->cb_info, NULL, 0);
+               if (pc->cb_info->user_buffer_supported) {
+                       if (!__camera_allocate_preview_buffer(camera)) {
+                               ret = CAMERA_ERROR_INVALID_OPERATION;
+                               goto _START_FAILED;
                        }
+
+                       fds = pc->cb_info->fds;
                }
        }
 
+       _camera_msg_send(api, fds, pc->cb_info, &ret, CAMERA_CB_NO_TIMEOUT);
        if (ret != CAMERA_ERROR_NONE)
+               goto _START_FAILED;
+
+       if (pc->cb_info->is_evas_render) {
+               ret = _camera_start_evas_rendering(camera);
+               if (ret != CAMERA_ERROR_NONE) {
+                       CAM_LOG_ERROR("stop preview because of error");
+                       _camera_msg_send(MUSE_CAMERA_API_STOP_PREVIEW, NULL, pc->cb_info, NULL, 0);
+                       goto _START_FAILED;
+               }
+       }
+
+       CAM_LOG_INFO("done");
+
+       return CAMERA_ERROR_NONE;
+
+_START_FAILED:
+       if (current_state == CAMERA_STATE_CREATED) {
+               if (pc->cb_info->user_buffer_supported)
+                       __camera_release_preview_buffer(camera);
+
                __destroy_msg_handler_thread(&pc->cb_info->preview_cb_info);
+       }
 
-       CAM_LOG_INFO("ret : 0x%x", ret);
+       CAM_LOG_ERROR("failed : 0x%x", ret);
 
        return ret;
 }