Support continuous capture 47/250547/4 accepted/tizen/unified/20210105.125826 submit/tizen/20210105.053027
authorJeongmo Yang <jm80.yang@samsung.com>
Tue, 29 Dec 2020 08:59:44 +0000 (17:59 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Mon, 4 Jan 2021 09:49:05 +0000 (18:49 +0900)
[Version] 0.0.13
[Issue Type] Update

Change-Id: Id61d1eab11c10c8f11dae08bf65a15061e049323
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
packaging/camera-hal-v4l2.spec
src/tizen_camera_v4l2.c
src/tizen_camera_v4l2_private.h

index 353c6a3..61e7eee 100644 (file)
@@ -1,6 +1,6 @@
 Name:       camera-hal-v4l2
 Summary:    Tizen Camera Hal for V4L2
-Version:    0.0.12
+Version:    0.0.13
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
index 0ade153..11c1b32 100644 (file)
@@ -774,6 +774,9 @@ static void __camera_do_capture(camera_hal_handle *handle)
 {
        int ret = CAMERA_ERROR_NONE;
        int buffer_index = 0;
+       gint64 current_time = 0;
+       gint64 previous_time = 0;
+       gint64 interval_us = 0;
 
        if (!handle) {
                LOGE("NULL handle");
@@ -782,6 +785,9 @@ static void __camera_do_capture(camera_hal_handle *handle)
 
        LOGD("start");
 
+       if (handle->capture_count > 1)
+               interval_us = handle->capture_interval_ms * 1000;
+
        /* restart stream for capture */
        if (handle->capture_restart_stream) {
                ret = __camera_stop_stream(handle, handle->buffer_count);
@@ -801,41 +807,65 @@ static void __camera_do_capture(camera_hal_handle *handle)
                }
        }
 
-       /* get capture buffer */
-       ret = __camera_v4l2_wait_frame(handle->device_fd, 5);
-       if (ret != CAMERA_ERROR_NONE) {
-               LOGE("frame wait failed for capture[0x%x]", ret);
-               goto _CAPTURE_DONE;
-       }
+       do {
+               /* get capture buffer */
+               ret = __camera_v4l2_wait_frame(handle->device_fd, 5);
+               if (ret != CAMERA_ERROR_NONE) {
+                       LOGE("frame wait failed for capture[0x%x]", ret);
+                       goto _CAPTURE_DONE;
+               }
 
-       ret = __camera_v4l2_dqbuf(handle->device_fd,
-               handle->buffer_type, V4L2_MEMORY_MMAP, &buffer_index);
-       if (ret != CAMERA_ERROR_NONE) {
-               LOGE("dqbuf failed for capture[0x%x]", ret);
-               goto _CAPTURE_DONE;
-       }
+               ret = __camera_v4l2_dqbuf(handle->device_fd,
+                       handle->buffer_type, V4L2_MEMORY_MMAP, &buffer_index);
+               if (ret != CAMERA_ERROR_NONE) {
+                       LOGE("dqbuf failed for capture[0x%x]", ret);
+                       goto _CAPTURE_DONE;
+               }
 
-       g_mutex_lock(&handle->buffer_lock);
+               if (handle->captured_count > 0) {
+                       g_mutex_lock(&handle->buffer_lock);
+                       if (handle->state != CAMERA_STATE_CAPTURING) {
+                               LOGW("stop continuous capture");
+                               handle->captured_count = handle->capture_count;
+                               g_mutex_unlock(&handle->buffer_lock);
+                               goto _TRY_NEXT;
+                       }
+                       g_mutex_unlock(&handle->buffer_lock);
+               }
 
-       handle->captured_count++;
+               if (handle->capture_count > 1) {
+                       current_time = g_get_monotonic_time();
 
-       g_mutex_unlock(&handle->buffer_lock);
+                       LOGI("time[prev:%"PRId64", cur:%"PRId64"] interval[%"PRId64" us]",
+                               previous_time, current_time, interval_us);
 
-       LOGD("capture cb[%p], buffer index[%d],count[%d]",
-               handle->capture_cb, buffer_index, handle->captured_count);
+                       if (current_time < previous_time + interval_us)
+                               goto _TRY_NEXT;
+               }
 
-       if (handle->capture_cb) {
-               ((camera_capture_cb)handle->capture_cb)(&handle->camera_buffers[buffer_index],
-                       NULL, NULL, handle->capture_cb_data);
-       } else {
-               LOGW("capture callback is NULL");
-               /* Need to post error? */
-       }
+               g_mutex_lock(&handle->buffer_lock);
+               handle->captured_count++;
+               g_mutex_unlock(&handle->buffer_lock);
 
-       ret = __camera_v4l2_qbuf(handle->device_fd,
-               handle->buffer_type, V4L2_MEMORY_MMAP, buffer_index);
-       if (ret != CAMERA_ERROR_NONE)
-               LOGE("qbuf failed for capture[0x%x]", ret);
+               LOGD("capture cb[%p], buffer index[%d],count[%d]",
+                       handle->capture_cb, buffer_index, handle->captured_count);
+
+               if (handle->capture_cb) {
+                       ((camera_capture_cb)handle->capture_cb)(&handle->camera_buffers[buffer_index],
+                               NULL, NULL, handle->capture_cb_data);
+               } else {
+                       LOGW("capture callback is NULL");
+                       /* Need to post error? */
+               }
+
+               previous_time = current_time;
+
+_TRY_NEXT:
+               ret = __camera_v4l2_qbuf(handle->device_fd,
+                       handle->buffer_type, V4L2_MEMORY_MMAP, buffer_index);
+               if (ret != CAMERA_ERROR_NONE)
+                       LOGE("qbuf failed for capture[0x%x]", ret);
+       } while (handle->captured_count < handle->capture_count);
 
        g_mutex_lock(&handle->buffer_lock);
 
@@ -875,11 +905,11 @@ static void *__camera_buffer_handler_func(gpointer data)
        camera_hal_handle *handle = (camera_hal_handle *)data;
 
        if (!handle) {
-               LOGE("NULL handle for preview handler");
+               LOGE("NULL handle for buffer handler");
                return NULL;
        }
 
-       LOGD("enter - preview handler thread");
+       LOGD("enter");
 
        /* run buffer thread */
        g_mutex_lock(&handle->buffer_lock);
@@ -896,7 +926,7 @@ static void *__camera_buffer_handler_func(gpointer data)
                g_mutex_lock(&handle->buffer_lock);
 
                if (handle->buffer_thread_run == FALSE) {
-                       LOGW("stop preview handler thread");
+                       LOGW("stop buffer handler thread");
                        break;
                }
 
@@ -931,7 +961,7 @@ static void *__camera_buffer_handler_func(gpointer data)
 
        g_mutex_unlock(&handle->buffer_lock);
 
-       LOGD("leave - preview handler thread");
+       LOGD("leave");
 
        return NULL;
 }
@@ -1695,13 +1725,13 @@ int camera_start_capture(void *camera_handle, camera_capture_cb callback, void *
        /* reset captured count */
        handle->captured_count = 0;
 
+       LOGD("start capture - count %u", handle->capture_count);
+
        /* set capture request flag */
        handle->capture_request = TRUE;
 
        handle->state = CAMERA_STATE_CAPTURING;
 
-       LOGD("start capture");
-
        g_mutex_unlock(&handle->lock);
 
        return CAMERA_ERROR_NONE;
@@ -1829,11 +1859,11 @@ int camera_set_command(void *camera_handle, int64_t command, void *value)
 
        if (handle->state < CAMERA_STATE_OPENED) {
                LOGE("invalid state %d", handle->state);
-               g_mutex_unlock(&handle->lock);
-               return CAMERA_ERROR_INVALID_STATE;
+               ret = CAMERA_ERROR_INVALID_STATE;
+               goto _SET_COMMAND_DONE;
        }
 
-       LOGD("set command %"PRId64" - state %d", command, handle->state);
+       LOGD("set command %"PRIx64" - state %d", command, handle->state);
 
        switch (command) {
        case CAMERA_COMMAND_BRIGHTNESS:
@@ -1849,14 +1879,11 @@ int camera_set_command(void *camera_handle, int64_t command, void *value)
                cid = V4L2_CID_SHARPNESS;
                break;
        case CAMERA_COMMAND_PTZ_TYPE:
-               g_mutex_unlock(&handle->lock);
-
                if (set_value != CAMERA_PTZ_TYPE_ELECTRONIC) {
                        LOGE("not supported PTZ type %d", set_value);
-                       return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+                       ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
                }
-
-               return CAMERA_ERROR_NONE;
+               goto _SET_COMMAND_DONE;
        case CAMERA_COMMAND_PAN:
                cid = V4L2_CID_PAN_ABSOLUTE;
                break;
@@ -1864,18 +1891,23 @@ int camera_set_command(void *camera_handle, int64_t command, void *value)
                cid = V4L2_CID_TILT_ABSOLUTE;
                break;
        case CAMERA_COMMAND_FLIP:
-               g_mutex_unlock(&handle->lock);
                if (set_value != CAMERA_FLIP_NONE) {
                        LOGE("NOT_SUPPORTED flip %d", set_value);
-                       return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
-               } else {
-                       return CAMERA_ERROR_NONE;
+                       ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
                }
-               break;
+               goto _SET_COMMAND_DONE;
+       case CAMERA_COMMAND_CAPTURE_COUNT:
+               handle->capture_count = set_value;
+               LOGI("capture count %u", handle->capture_count);
+               goto _SET_COMMAND_DONE;
+       case CAMERA_COMMAND_CAPTURE_INTERVAL:
+               handle->capture_interval_ms = set_value;
+               LOGI("capture interval %u ms", handle->capture_interval_ms);
+               goto _SET_COMMAND_DONE;
        default:
-               LOGE("NOT_SUPPORTED %"PRId64, command);
-               g_mutex_unlock(&handle->lock);
-               return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+               LOGE("NOT_SUPPORTED command %"PRIx64, command);
+               ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+               goto _SET_COMMAND_DONE;
        }
 
        ctrl_ret = __camera_v4l2_s_ctrl(handle->device_fd, cid, set_value);
@@ -1905,6 +1937,7 @@ int camera_set_command(void *camera_handle, int64_t command, void *value)
                }
        }
 
+_SET_COMMAND_DONE:
        g_mutex_unlock(&handle->lock);
 
        return ret;
index c6abc44..035316b 100644 (file)
@@ -58,6 +58,7 @@ typedef struct _camera_hal_handle {
        camera_capture_cb capture_cb;
        gpointer capture_cb_data;
        guint32 capture_count;
+       guint32 capture_interval_ms;
        guint32 captured_count;
        gboolean capture_request;
        gboolean capture_restart_stream;