Support capture function 89/239289/5 accepted/tizen_6.0_unified_hotfix tizen_6.0_hotfix accepted/tizen/6.0/unified/20201030.123220 accepted/tizen/6.0/unified/hotfix/20201103.052707 accepted/tizen/unified/20200810.123216 submit/tizen/20200805.092003 submit/tizen/20200806.100558 submit/tizen_6.0/20201029.205101 submit/tizen_6.0_hotfix/20201102.192501 submit/tizen_6.0_hotfix/20201103.114801 tizen_6.0.m2_release
authorJeongmo Yang <jm80.yang@samsung.com>
Thu, 23 Jul 2020 10:56:57 +0000 (19:56 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Mon, 27 Jul 2020 09:51:45 +0000 (18:51 +0900)
- Additional changes
 : Remove or rename some member variables in camera_hal_handle
 : Move S_FMT/S_PARM code to __camera_start_stream()
 : Remove debug log

[Version] 0.0.12
[Profile] Common
[Issue Type] Update

Change-Id: If3737f434b0248b8e3df2b261844a48139b248a1
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 58bdca4..353c6a3 100644 (file)
@@ -1,6 +1,6 @@
 Name:       camera-hal-v4l2
 Summary:    Tizen Camera Hal for V4L2
-Version:    0.0.11
+Version:    0.0.12
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
index 2b4b06d..0ade153 100644 (file)
@@ -322,7 +322,7 @@ static int __camera_get_format(guint32 fourcc, int *pixel_format)
        return CAMERA_ERROR_NONE;
 }
 
-static int __camera_get_fourcc_plane_num(int pixel_format, guint32 *fourcc, uint8_t *plane_num)
+static int __camera_get_fourcc_plane_num(int pixel_format, guint32 *fourcc, guint32 *plane_num)
 {
        if (!fourcc || !plane_num) {
                LOGE("NULL parameter %p %p", fourcc, plane_num);
@@ -522,7 +522,7 @@ static int __camera_get_device_info_list(void)
                        ret = CAMERA_ERROR_INTERNAL;
                        goto _GET_DEVICE_INFO_LIST_DONE;
                default:
-                       LOGE("unknown eror : %d", ret);
+                       LOGE("unknown error : %d", ret);
                        ret = CAMERA_ERROR_INTERNAL;
                        goto _GET_DEVICE_INFO_LIST_DONE;
                }
@@ -598,7 +598,7 @@ static int __camera_stop_stream(camera_hal_handle *handle, uint32_t buffer_count
        LOGD("buffer count[%d]", buffer_count);
 
        /* stream off */
-       ret = __camera_v4l2_stream(handle->device_fd, handle->v4l2_type, FALSE);
+       ret = __camera_v4l2_stream(handle->device_fd, handle->buffer_type, FALSE);
 
        LOGD("stream off : 0x%x", ret);
 
@@ -618,7 +618,7 @@ static int __camera_stop_stream(camera_hal_handle *handle, uint32_t buffer_count
 
        /* reqbufs 0 */
        ret = __camera_v4l2_reqbufs(handle->device_fd,
-               handle->v4l2_type, V4L2_MEMORY_MMAP, 0, &buffer_count);
+               handle->buffer_type, V4L2_MEMORY_MMAP, 0, &buffer_count);
 
        LOGD("reqbufs 0 : 0x%x", ret);
 
@@ -626,60 +626,116 @@ static int __camera_stop_stream(camera_hal_handle *handle, uint32_t buffer_count
 }
 
 
-static int __camera_start_stream(camera_hal_handle *handle, camera_format_t *format,
-       uint32_t request_buffer_count, uint32_t *result_buffer_count)
+static int __camera_start_stream(camera_hal_handle *handle, camera_pixel_format_t pixel_format,
+       camera_resolution_t *resolution, uint32_t fps, uint32_t request_buffer_count)
 {
        int i = 0;
        int ret = CAMERA_ERROR_NONE;
        camera_buffer_t *buffer = NULL;
+       struct v4l2_format v4l2_fmt;
+       struct v4l2_streamparm v4l2_parm;
        struct v4l2_buffer v4l2_buf;
-       struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX];
+       struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX];;
+       guint32 fourcc = 0;
+       guint32 plane_num = 0;
+
+       if (!handle || !resolution) {
+               LOGE("NULL param %p %p", handle, resolution);
+               return CAMERA_ERROR_INTERNAL;
+       }
+
+       /* S_FMT */
+       ret = __camera_get_fourcc_plane_num(pixel_format, &fourcc, &plane_num);
+       if (ret != CAMERA_ERROR_NONE) {
+               LOGE("get fourcc failed [format %d]", pixel_format);
+               return ret;
+       }
+
+       memset(&v4l2_fmt, 0x0, sizeof(struct v4l2_format));
+
+       v4l2_fmt.type = handle->buffer_type;
+       if (V4L2_TYPE_IS_MULTIPLANAR(handle->buffer_type)) {
+               v4l2_fmt.fmt.pix_mp.width = resolution->width;
+               v4l2_fmt.fmt.pix_mp.height = resolution->height;
+               v4l2_fmt.fmt.pix_mp.pixelformat = fourcc;
+               v4l2_fmt.fmt.pix_mp.num_planes = plane_num;
+       } else {
+               v4l2_fmt.fmt.pix.width = resolution->width;
+               v4l2_fmt.fmt.pix.height = resolution->height;
+               v4l2_fmt.fmt.pix.pixelformat = fourcc;
+               v4l2_fmt.fmt.pix.bytesperline = resolution->width;
+       }
+
+       if (ioctl(handle->device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
+               LOGE("S_FMT failed. errno %d", errno);
+               return CAMERA_ERROR_INTERNAL;
+       }
+
+       if (V4L2_TYPE_IS_MULTIPLANAR(handle->buffer_type)) {
+               for (i = 0 ; i < v4l2_fmt.fmt.pix_mp.num_planes ; i++) {
+                       LOGD("plane[%d] stride %u, sizeimage %u", i,
+                               v4l2_fmt.fmt.pix_mp.plane_fmt[i].bytesperline,
+                               v4l2_fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
+               }
+       } else {
+               LOGD("stride %d, sizeimage %d",
+                       v4l2_fmt.fmt.pix.bytesperline,
+                       v4l2_fmt.fmt.pix.sizeimage);
+       }
+
+       /* G_PARM */
+       memset(&v4l2_parm, 0x0, sizeof(struct v4l2_streamparm));
 
-       if (!handle || !format || !result_buffer_count) {
-               LOGE("NULL param %p %p", handle, result_buffer_count);
+       v4l2_parm.type = handle->buffer_type;
+
+       if (ioctl(handle->device_fd, VIDIOC_G_PARM, &v4l2_parm) < 0) {
+               LOGE("G_PARM failed. errno %d", errno);
+               return CAMERA_ERROR_INTERNAL;
+       }
+
+       /* S_PARM to set fps */
+       v4l2_parm.parm.capture.timeperframe.numerator = 1;
+       v4l2_parm.parm.capture.timeperframe.denominator = fps;
+
+       if (ioctl(handle->device_fd, VIDIOC_S_PARM, &v4l2_parm) < 0) {
+               LOGE("S_PARM failed. errno %d", errno);
                return CAMERA_ERROR_INTERNAL;
        }
 
        /* request buffer */
        ret = __camera_v4l2_reqbufs(handle->device_fd,
-               handle->v4l2_type, V4L2_MEMORY_MMAP, request_buffer_count, result_buffer_count);
+               handle->buffer_type, V4L2_MEMORY_MMAP, request_buffer_count, &handle->buffer_count);
        if (ret != CAMERA_ERROR_NONE) {
-               g_mutex_unlock(&handle->lock);
                return ret;
        }
 
        LOGD("buffer count : request %d -> result %d",
-               request_buffer_count, *result_buffer_count);
+               request_buffer_count, handle->buffer_count);
 
        /* query buffer, mmap and qbuf */
-       for (i = 0 ; i < *result_buffer_count ; i++) {
+       for (i = 0 ; i < handle->buffer_count ; i++) {
                memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer));
                memset(v4l2_planes, 0x0, sizeof(v4l2_planes));
 
-               v4l2_buf.type = handle->v4l2_type;
+               v4l2_buf.type = handle->buffer_type;
                v4l2_buf.memory = V4L2_MEMORY_MMAP;
                v4l2_buf.index = i;
                v4l2_buf.m.planes = v4l2_planes;
-               v4l2_buf.length = handle->plane_num;
-
-               LOGD("%d", i);
+               v4l2_buf.length = plane_num;
 
                if (ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) {
                        LOGE("[%d] query buf failed. errno %d", i, errno);
                        goto _START_STREAM_FAILED;
                }
 
-               LOGD("%d", i);
-
                buffer = &handle->camera_buffers[i];
 
-               LOGD("%d", i);
-
                buffer->index = i;
-               buffer->format = format->stream_format;
-               buffer->resolution = format->stream_resolution;
+               buffer->format = pixel_format;
+               buffer->resolution.width = resolution->width;
+               buffer->resolution.height = resolution->height;
                buffer->total_size = v4l2_buf.length;
-               buffer->num_planes = handle->plane_num;
+               buffer->num_planes = plane_num;
                buffer->planes[0].size = v4l2_buf.length;
                buffer->planes[0].data = mmap(0,
                        v4l2_buf.length,
@@ -688,25 +744,19 @@ static int __camera_start_stream(camera_hal_handle *handle, camera_format_t *for
                        handle->device_fd,
                        v4l2_buf.m.offset);
 
-               LOGD("%d", i);
-
                if (buffer->planes[0].data == MAP_FAILED) {
                        LOGE("[%d] mmap failed (errno %d)", i, errno);
                        goto _START_STREAM_FAILED;
                }
 
-               LOGD("%d", i);
-
-               if (__camera_v4l2_qbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, i) != CAMERA_ERROR_NONE) {
+               if (__camera_v4l2_qbuf(handle->device_fd, handle->buffer_type, V4L2_MEMORY_MMAP, i) != CAMERA_ERROR_NONE) {
                        LOGE("[%d] qbuf failed (errno %d)", i, errno);
                        goto _START_STREAM_FAILED;
                }
-
-               LOGD("%d", i);
        }
 
        /* stream on */
-       ret = __camera_v4l2_stream(handle->device_fd, handle->v4l2_type, TRUE);
+       ret = __camera_v4l2_stream(handle->device_fd, handle->buffer_type, TRUE);
        if (ret != CAMERA_ERROR_NONE) {
                LOGE("stream on failed");
                goto _START_STREAM_FAILED;
@@ -715,11 +765,110 @@ static int __camera_start_stream(camera_hal_handle *handle, camera_format_t *for
        return CAMERA_ERROR_NONE;
 
 _START_STREAM_FAILED:
-       __camera_stop_stream(handle, *result_buffer_count);
+       __camera_stop_stream(handle, handle->buffer_count);
        return ret;
 }
 
 
+static void __camera_do_capture(camera_hal_handle *handle)
+{
+       int ret = CAMERA_ERROR_NONE;
+       int buffer_index = 0;
+
+       if (!handle) {
+               LOGE("NULL handle");
+               return;
+       }
+
+       LOGD("start");
+
+       /* restart stream for capture */
+       if (handle->capture_restart_stream) {
+               ret = __camera_stop_stream(handle, handle->buffer_count);
+               if (ret != CAMERA_ERROR_NONE) {
+                       LOGE("stop stream failed for capture[0x%x]", ret);
+                       goto _CAPTURE_DONE;
+               }
+
+               ret = __camera_start_stream(handle,
+                       handle->preview_format.capture_format,
+                       &handle->preview_format.capture_resolution,
+                       handle->preview_format.stream_fps,
+                       BUFFER_MAX);
+               if (ret != CAMERA_ERROR_NONE) {
+                       LOGE("start stream failed for capture[0x%x]", ret);
+                       goto _CAPTURE_DONE;
+               }
+       }
+
+       /* 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;
+       }
+
+       g_mutex_lock(&handle->buffer_lock);
+
+       handle->captured_count++;
+
+       g_mutex_unlock(&handle->buffer_lock);
+
+       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? */
+       }
+
+       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);
+
+       g_mutex_lock(&handle->buffer_lock);
+
+       if (handle->state == CAMERA_STATE_CAPTURING) {
+               LOGD("wait for capture stop signal");
+               g_cond_wait(&handle->buffer_cond, &handle->buffer_lock);
+               LOGD("signal received");
+       } else {
+               LOGD("The state is already changed.");
+       }
+
+       g_mutex_unlock(&handle->buffer_lock);
+
+_CAPTURE_DONE:
+       /* restart stream for preview */
+       if (handle->capture_restart_stream) {
+               ret = __camera_stop_stream(handle, handle->buffer_count);
+               if (ret != CAMERA_ERROR_NONE)
+                       LOGE("stop stream failed for preview[0x%x]", ret);
+
+               ret = __camera_start_stream(handle,
+                       handle->preview_format.stream_format,
+                       &handle->preview_format.stream_resolution,
+                       handle->preview_format.stream_fps,
+                       BUFFER_MAX);
+               if (ret != CAMERA_ERROR_NONE)
+                       LOGE("start stream failed for preview[0x%x]", ret);
+       }
+
+       LOGD("done");
+}
+
+
 static void *__camera_buffer_handler_func(gpointer data)
 {
        int index = 0;
@@ -733,34 +882,34 @@ static void *__camera_buffer_handler_func(gpointer data)
        LOGD("enter - preview handler thread");
 
        /* run buffer thread */
-       g_mutex_lock(&handle->preview_cb_lock);
+       g_mutex_lock(&handle->buffer_lock);
 
        while (handle->buffer_thread_run) {
-               g_mutex_unlock(&handle->preview_cb_lock);
+               g_mutex_unlock(&handle->buffer_lock);
 
                if (__camera_v4l2_wait_frame(handle->device_fd, 5) != CAMERA_ERROR_NONE) {
                        LOGE("frame wait failed");
-                       g_mutex_lock(&handle->preview_cb_lock);
+                       g_mutex_lock(&handle->buffer_lock);
                        break;
                }
 
-               g_mutex_lock(&handle->preview_cb_lock);
+               g_mutex_lock(&handle->buffer_lock);
 
                if (handle->buffer_thread_run == FALSE) {
                        LOGW("stop preview handler thread");
                        break;
                }
 
-               if (__camera_v4l2_dqbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, &index) != CAMERA_ERROR_NONE) {
+               if (__camera_v4l2_dqbuf(handle->device_fd, handle->buffer_type, V4L2_MEMORY_MMAP, &index) != CAMERA_ERROR_NONE) {
                        LOGE("dqbuf failed");
                        break;
                }
 
-               handle->live_buffer_num++;
+               handle->buffer_dequeued_count++;
 
-               /*LOGD("live buffer num %d", handle->live_buffer_num);*/
+               /*LOGD("dequeued buffer count %d", handle->buffer_dequeued_count);*/
 
-               g_mutex_unlock(&handle->preview_cb_lock);
+               g_mutex_unlock(&handle->buffer_lock);
 
                if (handle->preview_cb) {
                        ((camera_preview_frame_cb)handle->preview_cb)(&handle->camera_buffers[index], NULL, handle->preview_cb_data);
@@ -769,12 +918,18 @@ static void *__camera_buffer_handler_func(gpointer data)
                        camera_release_preview_buffer((void *)handle, index);
                }
 
+               /* check capture request flag */
+               if (handle->capture_request) {
+                       __camera_do_capture(handle);
+                       handle->capture_request = FALSE;
+               }
+
                sched_yield();
 
-               g_mutex_lock(&handle->preview_cb_lock);
+               g_mutex_lock(&handle->buffer_lock);
        }
 
-       g_mutex_unlock(&handle->preview_cb_lock);
+       g_mutex_unlock(&handle->buffer_lock);
 
        LOGD("leave - preview handler thread");
 
@@ -812,42 +967,42 @@ static void *_camera_message_handler_func(gpointer data)
 
        LOGD("enter - message thread");
 
-       g_mutex_lock(&handle->message_cb_lock);
+       g_mutex_lock(&handle->msg_cb_lock);
 
-       while (handle->message_cb_run) {
-               if (g_queue_is_empty(handle->message_list)) {
+       while (handle->msg_cb_run) {
+               if (g_queue_is_empty(handle->msg_list)) {
                        LOGD("wait for message");
-                       g_cond_wait(&handle->message_cb_cond, &handle->message_cb_lock);
+                       g_cond_wait(&handle->msg_cb_cond, &handle->msg_cb_lock);
                        LOGD("message signal received");
                }
 
-               if (!handle->message_cb_run) {
+               if (!handle->msg_cb_run) {
                        LOGW("break message thread");
                        break;
                }
 
-               message = g_queue_pop_head(handle->message_list);
+               message = g_queue_pop_head(handle->msg_list);
                if (!message) {
                        LOGW("NULL message");
                        continue;
                }
 
-               g_mutex_unlock(&handle->message_cb_lock);
+               g_mutex_unlock(&handle->msg_cb_lock);
 
                for (i = 0 ; i < MESSAGE_CALLBACK_MAX ; i++) {
-                       if (handle->message_cb[i]) {
+                       if (handle->msg_cb[i]) {
                                LOGD("call message callback type %d", message->type);
-                               ((camera_message_cb)handle->message_cb[i])(message, handle->message_cb_data[i]);
+                               ((camera_message_cb)handle->msg_cb[i])(message, handle->msg_cb_data[i]);
                        }
                }
 
                g_free(message);
                message = NULL;
 
-               g_mutex_lock(&handle->message_cb_lock);
+               g_mutex_lock(&handle->msg_cb_lock);
        }
 
-       g_mutex_unlock(&handle->message_cb_lock);
+       g_mutex_unlock(&handle->msg_cb_lock);
 
        LOGD("leave - message thread");
 
@@ -862,21 +1017,21 @@ static void __camera_release_handle(camera_hal_handle *handle)
                return;
        }
 
-       if (handle->message_thread) {
-               g_mutex_lock(&handle->message_cb_lock);
-               handle->message_cb_run = FALSE;
-               g_cond_signal(&handle->message_cb_cond);
-               g_mutex_unlock(&handle->message_cb_lock);
-               g_thread_join(handle->message_thread);
-               g_queue_free_full(handle->message_list, (GDestroyNotify)__camera_message_release_func);
-               handle->message_list = NULL;
+       if (handle->msg_thread) {
+               g_mutex_lock(&handle->msg_cb_lock);
+               handle->msg_cb_run = FALSE;
+               g_cond_signal(&handle->msg_cb_cond);
+               g_mutex_unlock(&handle->msg_cb_lock);
+               g_thread_join(handle->msg_thread);
+               g_queue_free_full(handle->msg_list, (GDestroyNotify)__camera_message_release_func);
+               handle->msg_list = NULL;
        }
 
        g_mutex_clear(&handle->lock);
-       g_mutex_clear(&handle->preview_cb_lock);
-       g_mutex_clear(&handle->message_cb_lock);
-       g_cond_clear(&handle->preview_cb_cond);
-       g_cond_clear(&handle->message_cb_cond);
+       g_mutex_clear(&handle->buffer_lock);
+       g_mutex_clear(&handle->msg_cb_lock);
+       g_cond_clear(&handle->buffer_cond);
+       g_cond_clear(&handle->msg_cb_cond);
 
        if (handle->bufmgr) {
                tbm_bufmgr_deinit(handle->bufmgr);
@@ -920,17 +1075,17 @@ int camera_init(void **camera_handle)
        new_handle->bufmgr = bufmgr;
 
        g_mutex_init(&new_handle->lock);
-       g_mutex_init(&new_handle->preview_cb_lock);
-       g_mutex_init(&new_handle->message_cb_lock);
-       g_cond_init(&new_handle->preview_cb_cond);
-       g_cond_init(&new_handle->message_cb_cond);
+       g_mutex_init(&new_handle->buffer_lock);
+       g_mutex_init(&new_handle->msg_cb_lock);
+       g_cond_init(&new_handle->buffer_cond);
+       g_cond_init(&new_handle->msg_cb_cond);
 
        /* message thread */
-       new_handle->message_list = g_queue_new();
-       new_handle->message_cb_run = TRUE;
-       new_handle->message_thread = g_thread_try_new("camera_hal_message_thread",
+       new_handle->msg_list = g_queue_new();
+       new_handle->msg_cb_run = TRUE;
+       new_handle->msg_thread = g_thread_try_new("camera_hal_msg_thread",
                _camera_message_handler_func, (gpointer)new_handle, NULL);
-       if (!new_handle->message_thread) {
+       if (!new_handle->msg_thread) {
                LOGE("failed to create message thread");
                ret = CAMERA_ERROR_INTERNAL;
                goto _INIT_ERROR;
@@ -1061,16 +1216,16 @@ int camera_open_device(void *camera_handle, int device_index)
        }
 
        if (g_device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
-               handle->v4l2_type = V4L2_CAP_VIDEO_CAPTURE_MPLANE;
+               handle->buffer_type = V4L2_CAP_VIDEO_CAPTURE_MPLANE;
        else
-               handle->v4l2_type = V4L2_CAP_VIDEO_CAPTURE;
+               handle->buffer_type = V4L2_CAP_VIDEO_CAPTURE;
 
        handle->state = CAMERA_STATE_OPENED;
        handle->device_index = device_index;
        handle->device_fd = device_fd;
 
        LOGD("[%d] device[%s] opened [fd %d, type %d]",
-               device_index, node_path, device_fd, handle->v4l2_type);
+               device_index, node_path, device_fd, handle->buffer_type);
 
 _OPEN_DEVICE_DONE:
        g_mutex_unlock(&handle->lock);
@@ -1137,9 +1292,9 @@ int camera_add_message_callback(void *camera_handle, camera_message_cb callback,
        }
 
        for (i = 0 ; i < MESSAGE_CALLBACK_MAX ; i++) {
-               if (handle->message_cb[i] == NULL) {
-                       handle->message_cb[i] = callback;
-                       handle->message_cb_data[i] = user_data;
+               if (handle->msg_cb[i] == NULL) {
+                       handle->msg_cb[i] = callback;
+                       handle->msg_cb_data[i] = user_data;
                        *cb_id = i;
                        LOGD("message cb [%p] added, user data %p - id %u", callback, user_data, i);
                        g_mutex_unlock(&handle->lock);
@@ -1176,12 +1331,12 @@ int camera_remove_message_callback(void *camera_handle, uint32_t cb_id)
                return CAMERA_ERROR_INVALID_STATE;
        }
 
-       if (handle->message_cb[cb_id]) {
+       if (handle->msg_cb[cb_id]) {
                LOGD("remove message callback %p, user data %p - cb_id %u",
-                       handle->message_cb[cb_id], handle->message_cb_data[cb_id], cb_id);
+                       handle->msg_cb[cb_id], handle->msg_cb_data[cb_id], cb_id);
 
-               handle->message_cb[cb_id] = NULL;
-               handle->message_cb_data[cb_id] = NULL;
+               handle->msg_cb[cb_id] = NULL;
+               handle->msg_cb_data[cb_id] = NULL;
        } else {
                LOGE("already removed message cb");
                g_mutex_unlock(&handle->lock);
@@ -1199,11 +1354,8 @@ int camera_set_preview_stream_format(void *camera_handle, camera_format_t *forma
        int j = 0;
        int ret = CAMERA_ERROR_NONE;
        gboolean capability_check = FALSE;
-       guint32 fourcc = 0;
        camera_hal_handle *handle = (camera_hal_handle *)camera_handle;
        camera_device_info_t *device_info = NULL;
-       struct v4l2_format v4l2_fmt;
-       struct v4l2_streamparm v4l2_parm;
 
        if (!handle || !format) {
                LOGE("NULL param %p %p", handle, format);
@@ -1217,7 +1369,8 @@ int camera_set_preview_stream_format(void *camera_handle, camera_format_t *forma
 
        g_mutex_lock(&handle->lock);
 
-       if (handle->state != CAMERA_STATE_OPENED) {
+       if (handle->state != CAMERA_STATE_OPENED &&
+               handle->state != CAMERA_STATE_PREVIEWING) {
                LOGE("invalid state %d", handle->state);
                g_mutex_unlock(&handle->lock);
                return CAMERA_ERROR_INVALID_STATE;
@@ -1256,80 +1409,60 @@ int camera_set_preview_stream_format(void *camera_handle, camera_format_t *forma
                return CAMERA_ERROR_INVALID_PARAMETER;
        }
 
-       /* S_FMT */
-       ret = __camera_get_fourcc_plane_num(format->stream_format, &fourcc, &handle->plane_num);
-       if (ret != CAMERA_ERROR_NONE) {
-               LOGE("get fourcc failed [format %d]", format->stream_format);
-               g_mutex_unlock(&handle->lock);
-               return ret;
-       }
-
-       memset(&v4l2_fmt, 0x0, sizeof(struct v4l2_format));
-
-       v4l2_fmt.type = handle->v4l2_type;
-       if (V4L2_TYPE_IS_MULTIPLANAR(handle->v4l2_type)) {
-               v4l2_fmt.fmt.pix_mp.width = format->stream_resolution.width;
-               v4l2_fmt.fmt.pix_mp.height = format->stream_resolution.height;
-               v4l2_fmt.fmt.pix_mp.pixelformat = fourcc;
-               v4l2_fmt.fmt.pix_mp.num_planes = handle->plane_num;
-       } else {
-               v4l2_fmt.fmt.pix.width = format->stream_resolution.width;
-               v4l2_fmt.fmt.pix.height = format->stream_resolution.height;
-               v4l2_fmt.fmt.pix.pixelformat = fourcc;
-               v4l2_fmt.fmt.pix.bytesperline = format->stream_resolution.width;
-       }
-
-       if (ioctl(handle->device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
-               LOGE("S_FMT failed. errno %d", errno);
-               g_mutex_unlock(&handle->lock);
-               return CAMERA_ERROR_INTERNAL;
-       }
-
-       if (V4L2_TYPE_IS_MULTIPLANAR(handle->v4l2_type)) {
-               for (i = 0 ; i < v4l2_fmt.fmt.pix_mp.num_planes ; i++) {
-                       LOGD("plane[%d] stride %u, sizeimage %u", i,
-                               v4l2_fmt.fmt.pix_mp.plane_fmt[i].bytesperline,
-                               v4l2_fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
+       /* compare with current settings */
+       if (handle->state == CAMERA_STATE_PREVIEWING) {
+               if (handle->preview_format.stream_format == format->stream_format &&
+                       handle->preview_format.stream_resolution.width == format->stream_resolution.width &&
+                       handle->preview_format.stream_resolution.height == format->stream_resolution.height &&
+                       handle->preview_format.stream_fps == format->stream_fps &&
+                       handle->preview_format.stream_rotation == format->stream_rotation) {
+                       LOGD("no need to restart preview stream");
+                       goto _SET_PREVIEW_STREAM_FORMAT_DONE;
                }
-       } else {
-               LOGD("stride %d, sizeimage %d",
-                       v4l2_fmt.fmt.pix.bytesperline,
-                       v4l2_fmt.fmt.pix.sizeimage);
-       }
 
-       /* G_PARM */
-       memset(&v4l2_parm, 0x0, sizeof(struct v4l2_streamparm));
+               LOGD("Preview setting is changed. Restart preview now.");
 
-       v4l2_parm.type = handle->v4l2_type;
+               /* stop preview stream to change it */
+               ret = __camera_stop_stream(handle, handle->buffer_count);
+               if (ret != CAMERA_ERROR_NONE) {
+                       LOGE("failed to stop stream");
+                       g_mutex_unlock(&handle->lock);
+                       return ret;
+               }
 
-       if (ioctl(handle->device_fd, VIDIOC_G_PARM, &v4l2_parm) < 0) {
-               LOGE("G_PARM failed. errno %d", errno);
-               g_mutex_unlock(&handle->lock);
-               return CAMERA_ERROR_INTERNAL;
+               /* restart preview stream to change it */
+               ret = __camera_start_stream(handle,
+                       format->stream_format,
+                       &format->stream_resolution,
+                       format->stream_fps,
+                       BUFFER_MAX);
+               if (ret != CAMERA_ERROR_NONE) {
+                       LOGE("failed to start stream");
+                       g_mutex_unlock(&handle->lock);
+                       return ret;
+               }
        }
 
-       /* S_PARM to set fps */
-       v4l2_parm.parm.capture.timeperframe.numerator = 1;
-       v4l2_parm.parm.capture.timeperframe.denominator = format->stream_fps;
-
-       if (ioctl(handle->device_fd, VIDIOC_S_PARM, &v4l2_parm) < 0) {
-               LOGE("S_PARM failed. errno %d", errno);
-               g_mutex_unlock(&handle->lock);
-               return CAMERA_ERROR_INTERNAL;
-       }
+_SET_PREVIEW_STREAM_FORMAT_DONE:
+       /* set capture restart flag */
+       if (format->stream_format == format->capture_format &&
+               format->stream_resolution.width == format->capture_resolution.width &&
+               format->stream_resolution.height == format->capture_resolution.height)
+               handle->capture_restart_stream = FALSE;
+       else
+               handle->capture_restart_stream = TRUE;
 
        memcpy(&handle->preview_format, format, sizeof(camera_format_t));
 
-       LOGD("set preview stream [%d: %dx%d, fps %d]",
+       LOGD("set format PREVIEW[%d:%dx%d,fps:%d], CAPTURE[%d:%dx%d,restart:%d]",
                format->stream_format,
                format->stream_resolution.width,
                format->stream_resolution.height,
-               format->stream_fps);
-
-       LOGW("CAPTURE STREAM [%d: %dx%d] IS NOT SUPPORTED",
+               format->stream_fps,
                format->capture_format,
                format->capture_resolution.width,
-               format->capture_resolution.height);
+               format->capture_resolution.height,
+               handle->capture_restart_stream);
 
        g_mutex_unlock(&handle->lock);
 
@@ -1376,14 +1509,18 @@ int camera_start_preview(void *camera_handle, camera_preview_frame_cb callback,
                return CAMERA_ERROR_INVALID_STATE;
        }
 
-       ret = __camera_start_stream(handle, &handle->preview_format, BUFFER_MAX, &handle->buffer_count);
+       ret = __camera_start_stream(handle,
+               handle->preview_format.stream_format,
+               &handle->preview_format.stream_resolution,
+               handle->preview_format.stream_fps,
+               BUFFER_MAX);
        if (ret != CAMERA_ERROR_NONE) {
                LOGE("__camera_start_stream failed[0x%x]", ret);
                g_mutex_unlock(&handle->lock);
                return ret;
        }
 
-       g_mutex_lock(&handle->preview_cb_lock);
+       g_mutex_lock(&handle->buffer_lock);
 
        handle->buffer_thread_run = TRUE;
 
@@ -1391,7 +1528,7 @@ int camera_start_preview(void *camera_handle, camera_preview_frame_cb callback,
                __camera_buffer_handler_func, (gpointer)handle, NULL);
        if (!handle->buffer_thread) {
                LOGE("failed to create buffer handler thread");
-               g_mutex_unlock(&handle->preview_cb_lock);
+               g_mutex_unlock(&handle->buffer_lock);
 
                __camera_stop_stream(handle, handle->buffer_count);
 
@@ -1403,7 +1540,7 @@ int camera_start_preview(void *camera_handle, camera_preview_frame_cb callback,
        handle->preview_cb = callback;
        handle->preview_cb_data = user_data;
 
-       g_mutex_unlock(&handle->preview_cb_lock);
+       g_mutex_unlock(&handle->buffer_lock);
 
        handle->state = CAMERA_STATE_PREVIEWING;
 
@@ -1430,21 +1567,25 @@ int camera_release_preview_buffer(void *camera_handle, int buffer_index)
        }
 
        ret = __camera_v4l2_qbuf(handle->device_fd,
-               handle->v4l2_type, V4L2_MEMORY_MMAP, buffer_index);
+               handle->buffer_type, V4L2_MEMORY_MMAP, buffer_index);
 
-       g_mutex_lock(&handle->preview_cb_lock);
+       g_mutex_lock(&handle->buffer_lock);
 
        if (ret == CAMERA_ERROR_NONE) {
-               handle->live_buffer_num--;
-               LOGD("qbud done : index %d, live buffer num %d",
-                       buffer_index, handle->live_buffer_num);
+               if (handle->buffer_dequeued_count > 0)
+                       handle->buffer_dequeued_count--;
+               else
+                       LOGW("invalid dequeued buffer count[%u]", handle->buffer_dequeued_count);
+
+               /*LOGD("qbud done : index %d, dequeued buffer count %d",
+                       buffer_index, handle->buffer_dequeued_count);*/
        } else {
                LOGE("qbuf failed [index %d]", buffer_index);
        }
 
-       g_cond_signal(&handle->preview_cb_cond);
+       g_cond_signal(&handle->buffer_cond);
 
-       g_mutex_unlock(&handle->preview_cb_lock);
+       g_mutex_unlock(&handle->buffer_lock);
 
        return ret;
 }
@@ -1471,14 +1612,14 @@ int camera_stop_preview(void *camera_handle)
                return CAMERA_ERROR_INVALID_STATE;
        }
 
-       g_mutex_lock(&handle->preview_cb_lock);
+       g_mutex_lock(&handle->buffer_lock);
 
        handle->buffer_thread_run = FALSE;
 
-       while (handle->live_buffer_num > 0) {
-               LOGD("wait for live buffer [num %d]", handle->live_buffer_num);
+       while (handle->buffer_dequeued_count > 0) {
+               LOGD("wait for dequeued buffer [%d]", handle->buffer_dequeued_count);
                end_time = g_get_monotonic_time() + 3 * G_TIME_SPAN_SECOND;
-               if (!g_cond_wait_until(&handle->preview_cb_cond, &handle->preview_cb_lock, end_time)) {
+               if (!g_cond_wait_until(&handle->buffer_cond, &handle->buffer_lock, end_time)) {
                        LOGE("buffer wait failed");
                        break;
                } else {
@@ -1486,7 +1627,7 @@ int camera_stop_preview(void *camera_handle)
                }
        }
 
-       g_mutex_unlock(&handle->preview_cb_lock);
+       g_mutex_unlock(&handle->buffer_lock);
 
        ret = __camera_stop_stream(handle, handle->buffer_count);
 
@@ -1532,28 +1673,76 @@ int camera_stop_auto_focus(void *camera_handle)
 
 int camera_start_capture(void *camera_handle, camera_capture_cb callback, void *user_data)
 {
-       if (!camera_handle || !callback) {
+       camera_hal_handle *handle = (camera_hal_handle *)camera_handle;
+
+       if (!handle || !callback) {
                LOGE("NULL param %p %p", camera_handle, callback);
                return CAMERA_ERROR_INVALID_PARAMETER;
        }
 
-       LOGE("NOT SUPPORTED");
+       g_mutex_lock(&handle->lock);
 
-       /* capture function is not supported */
-       return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+       if (handle->state != CAMERA_STATE_PREVIEWING) {
+               LOGE("invalid state %d", handle->state);
+               g_mutex_unlock(&handle->lock);
+               return CAMERA_ERROR_INVALID_STATE;
+       }
+
+       /* set callback and user data */
+       handle->capture_cb = callback;
+       handle->capture_cb_data = user_data;
+
+       /* reset captured count */
+       handle->captured_count = 0;
+
+       /* 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;
 }
 
 int camera_stop_capture(void *camera_handle)
 {
-       if (!camera_handle) {
+       camera_hal_handle *handle = (camera_hal_handle *)camera_handle;
+
+       if (!handle) {
                LOGE("NULL handle");
                return CAMERA_ERROR_INVALID_PARAMETER;
        }
 
-       LOGE("NOT SUPPORTED");
+       g_mutex_lock(&handle->lock);
 
-       /* capture function is not supported */
-       return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+       if (handle->state != CAMERA_STATE_CAPTURING) {
+               LOGE("invalid state %d", handle->state);
+               g_mutex_unlock(&handle->lock);
+               return CAMERA_ERROR_INVALID_STATE;
+       }
+
+       g_mutex_lock(&handle->buffer_lock);
+
+       if (handle->captured_count == 0) {
+               LOGE("No captured image yet.");
+               g_mutex_unlock(&handle->buffer_lock);
+               g_mutex_unlock(&handle->lock);
+               return CAMERA_ERROR_INTERNAL;
+       }
+
+       LOGD("send signal to start preview after capture");
+
+       g_cond_signal(&handle->buffer_cond);
+       g_mutex_unlock(&handle->buffer_lock);
+
+       handle->state = CAMERA_STATE_PREVIEWING;
+
+       g_mutex_unlock(&handle->lock);
+
+       return CAMERA_ERROR_NONE;
 }
 
 int camera_set_video_stream_format(void *camera_handle, camera_format_t *format)
index 2e4996f..c6abc44 100644 (file)
 #define V4L2_PLANES_MAX             4
 
 typedef struct _camera_hal_handle {
+       /* tbm */
        tbm_bufmgr bufmgr;
 
-       int device_index;
-       int device_fd;
-       camera_state_t state;
-       camera_format_t preview_format;
-       camera_format_t video_format;
+       /* device */
+       gint32 device_index;
+       gint32 device_fd;
 
-       /* V4L2 */
-       enum v4l2_buf_type v4l2_type;
-       uint8_t plane_num;
-       int live_buffer_num;
-
-       /* thread */
+       /* buffer */
+       guint32 buffer_dequeued_count;
        GThread *buffer_thread;
-       GThread *message_thread;
        gboolean buffer_thread_run;
+       guint32 buffer_count;
+       camera_buffer_t camera_buffers[BUFFER_MAX];
+       enum v4l2_buf_type buffer_type;
+       GMutex buffer_lock;
+       GCond buffer_cond;
 
-       /* buffer handler */
+       /* preview */
+       camera_format_t preview_format;
        camera_preview_frame_cb preview_cb;
+       gpointer preview_cb_data;
+
+       /* capture */
        camera_capture_cb capture_cb;
-       void *preview_cb_data;
-       void *capture_cb_data;
-       uint32_t buffer_count;
-       camera_buffer_t camera_buffers[BUFFER_MAX];
+       gpointer capture_cb_data;
+       guint32 capture_count;
+       guint32 captured_count;
+       gboolean capture_request;
+       gboolean capture_restart_stream;
 
-       /* message callback */
-       camera_message_cb message_cb[MESSAGE_CALLBACK_MAX];
-       void *message_cb_data[MESSAGE_CALLBACK_MAX];
-       gboolean message_cb_run;
-       GQueue *message_list;
+       /* message */
+       GThread *msg_thread;
+       camera_message_cb msg_cb[MESSAGE_CALLBACK_MAX];
+       gpointer msg_cb_data[MESSAGE_CALLBACK_MAX];
+       gboolean msg_cb_run;
+       GQueue *msg_list;
+       GMutex msg_cb_lock;
+       GCond msg_cb_cond;
 
-       /* thread safe */
+       /* etc */
        GMutex lock;
-       GMutex preview_cb_lock;
-       GMutex message_cb_lock;
-       GCond preview_cb_cond;
-       GCond message_cb_cond;
+       camera_state_t state;
 } camera_hal_handle;
 
 #endif /* __TIZEN_CAMERA_PRIVATE_H__ */