From 70d87d285e6536d76ac53e4157af39d52b29aaed Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Thu, 13 Jun 2019 11:29:03 +0900 Subject: [PATCH 01/16] Change camera command for brightness [Version] 0.0.8 [Profile] Common [Issue Type] Update Change-Id: I001c5d9359025e337b416134f93fdde7333a4cc1 Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index 908efe0..d22a8ed 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.7 +Version: 0.0.8 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index 262b0d6..5f96527 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -1662,7 +1662,7 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) LOGD("set command %"PRId64" - state %d", command, handle->state); switch (command) { - case CAMERA_COMMAND_EXPOSURE: + case CAMERA_COMMAND_BRIGHTNESS: cid = V4L2_CID_BRIGHTNESS; break; case CAMERA_COMMAND_CONTRAST: @@ -1751,7 +1751,7 @@ int camera_get_command(void *camera_handle, int64_t command, void **value) LOGD("get command %"PRId64" - state %d", command, handle->state); switch (command) { - case CAMERA_COMMAND_EXPOSURE: + case CAMERA_COMMAND_BRIGHTNESS: cid = V4L2_CID_BRIGHTNESS; break; case CAMERA_COMMAND_CONTRAST: -- 2.7.4 From 2150e4c44a29bc0e146ea1036091c13e62c3bd57 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Thu, 13 Jun 2019 15:24:54 +0900 Subject: [PATCH 02/16] Update set command function - Convert (void *) to (int *) and use it. [Version] 0.0.9 [Profile] Common [Issue Type] Update Change-Id: I24d185c4ddb5f7651c17a0a57573251a9c92a8cf Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index d22a8ed..cc1a87f 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.8 +Version: 0.0.9 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index 5f96527..5996772 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -1642,6 +1642,7 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) int ret = CAMERA_ERROR_NONE; int cid = 0; int ctrl_ret = 0; + int set_value = 0; camera_hal_handle *handle = NULL; if (!camera_handle) { @@ -1649,7 +1650,13 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) return CAMERA_ERROR_INVALID_PARAMETER; } + if (!value) { + LOGE("invalid pointer : value"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + handle = (camera_hal_handle *)camera_handle; + set_value = *(int *)value; g_mutex_lock(&handle->lock); @@ -1677,8 +1684,8 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) case CAMERA_COMMAND_PTZ_TYPE: g_mutex_unlock(&handle->lock); - if ((int)(long)value != CAMERA_PTZ_TYPE_ELECTRONIC) { - LOGE("not supported PTZ type %d", (int)(long)value); + if (set_value != CAMERA_PTZ_TYPE_ELECTRONIC) { + LOGE("not supported PTZ type %d", set_value); return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } @@ -1695,7 +1702,7 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } - ctrl_ret = _camera_v4l2_s_ctrl(handle->device_fd, cid, ((int)(long)value)); + ctrl_ret = _camera_v4l2_s_ctrl(handle->device_fd, cid, set_value); if (ctrl_ret < 0) { switch (errno) { case EACCES: -- 2.7.4 From a05da814de30ddfef5873ee5935aa07a9b852e1d Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Mon, 28 Oct 2019 16:07:29 +0900 Subject: [PATCH 03/16] Do not call DQBUF after stop_preview is called [Version] 0.0.10 [Profile] Common [Issue Type] Update Change-Id: I4ddc54a818b77cb6f4d4cec27eaa8bc03fe29e3c Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index cc1a87f..d77166d 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.9 +Version: 0.0.10 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index 5996772..6454cd6 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -609,14 +609,18 @@ static void *_camera_preview_handler_func(gpointer data) break; } + g_mutex_lock(&handle->preview_cb_lock); + + if (handle->preview_cb_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) { LOGE("dqbuf failed"); - g_mutex_lock(&handle->preview_cb_lock); break; } - g_mutex_lock(&handle->preview_cb_lock); - handle->live_buffer_num++; LOGD("live buffer num %d", handle->live_buffer_num); -- 2.7.4 From 8906a575c14afae24c58bf6de6107c2d893d5819 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Wed, 22 Jul 2020 09:37:08 +0900 Subject: [PATCH 04/16] Revise code - Apply missed tizen coding rule - Add sub function for start/stop stream - Reduce code line to check invalid parameter - Remove unused code - Change the name of some preview related field in camera_hal_handle [Version] 0.0.11 [Profile] Common [Issue Type] Update Change-Id: Ic9991b248a22e52633a089c04d7388514933f42d Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 543 +++++++++++++++++++--------------------- src/tizen_camera_v4l2_private.h | 22 +- 3 files changed, 265 insertions(+), 302 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index d77166d..58bdca4 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.10 +Version: 0.0.11 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index 6454cd6..2b4b06d 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -52,22 +52,23 @@ static camera_device_info_list_t *g_device_info_list; -static guint32 device_caps; +static guint32 g_device_caps; static GMutex g_device_info_lock; -static void _camera_hal_v4l2_destructor(void) __attribute__((destructor)); +static void __camera_hal_v4l2_destructor(void) __attribute__((destructor)); -static void _camera_hal_v4l2_destructor(void) +static void __camera_hal_v4l2_destructor(void) { LOGD("release device info list %p", g_device_info_list); g_free(g_device_info_list); + g_device_info_list = NULL; return; } -static int _camera_v4l2_wait_frame(int device_fd, int wait_time) +static int __camera_v4l2_wait_frame(int device_fd, int wait_time) { int ret = CAMERA_ERROR_NONE; fd_set fds; @@ -86,7 +87,7 @@ static int _camera_v4l2_wait_frame(int device_fd, int wait_time) timeout.tv_sec = wait_time; timeout.tv_usec = 0; - LOGD("select : %d sec", wait_time); + /*LOGD("select : %d sec", wait_time);*/ ret = select(device_fd + 1, &fds, NULL, NULL, &timeout); if (ret == -1) { @@ -103,13 +104,13 @@ static int _camera_v4l2_wait_frame(int device_fd, int wait_time) return CAMERA_ERROR_INTERNAL; } - LOGD("select done"); + /*LOGD("select done");*/ return CAMERA_ERROR_NONE; } -static int _camera_v4l2_g_ctrl(int device_fd, int cid, int *value) +static int __camera_v4l2_g_ctrl(int device_fd, int cid, int *value) { int ret = 0; struct v4l2_control ctrl; @@ -133,7 +134,7 @@ static int _camera_v4l2_g_ctrl(int device_fd, int cid, int *value) } -static int _camera_v4l2_s_ctrl(int device_fd, int cid, int value) +static int __camera_v4l2_s_ctrl(int device_fd, int cid, int value) { int ret = 0; struct v4l2_control ctrl; @@ -151,7 +152,7 @@ static int _camera_v4l2_s_ctrl(int device_fd, int cid, int value) } -static int _camera_v4l2_stream(int device_fd, int type, gboolean onoff) +static int __camera_v4l2_stream(int device_fd, int type, gboolean onoff) { if (device_fd < 0) { LOGE("invalid fd %d", device_fd); @@ -169,7 +170,7 @@ static int _camera_v4l2_stream(int device_fd, int type, gboolean onoff) } -static int _camera_v4l2_reqbufs(int device_fd, int type, int memory, int count, int *result_count) +static int __camera_v4l2_reqbufs(int device_fd, int type, int memory, uint32_t count, uint32_t *result_count) { struct v4l2_requestbuffers v4l2_reqbuf; @@ -203,7 +204,7 @@ static int _camera_v4l2_reqbufs(int device_fd, int type, int memory, int count, } -static int _camera_v4l2_qbuf(int device_fd, int type, int memory, int index) +static int __camera_v4l2_qbuf(int device_fd, int type, int memory, int index) { struct v4l2_buffer v4l2_buf; struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX]; @@ -229,14 +230,13 @@ static int _camera_v4l2_qbuf(int device_fd, int type, int memory, int index) return CAMERA_ERROR_INTERNAL; } - LOGD("QBUF done [i: %d, t: %d, m: %d]", - index, type, memory); + /*LOGD("QBUF done [i: %d, t: %d, m: %d]", index, type, memory);*/ return CAMERA_ERROR_NONE; } -static int _camera_v4l2_dqbuf(int device_fd, int type, int memory, int *index) +static int __camera_v4l2_dqbuf(int device_fd, int type, int memory, int *index) { int ret = CAMERA_ERROR_NONE; struct v4l2_buffer v4l2_buf; @@ -270,13 +270,13 @@ static int _camera_v4l2_dqbuf(int device_fd, int type, int memory, int *index) *index = v4l2_buf.index; - LOGD("dqbuf index %d", *index); + /*LOGD("dqbuf index %d", *index);*/ return CAMERA_ERROR_NONE; } -static int _camera_get_format(guint32 fourcc, int *pixel_format) +static int __camera_get_format(guint32 fourcc, int *pixel_format) { if (!pixel_format) { LOGE("NULL parameter"); @@ -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, uint8_t *plane_num) { if (!fourcc || !plane_num) { LOGE("NULL parameter %p %p", fourcc, plane_num); @@ -374,7 +374,7 @@ static int _camera_get_fourcc_plane_num(int pixel_format, guint32 *fourcc, uint8 } -static int _camera_get_device_info(int device_index, int device_fd, camera_device_info_t *device_info, char *node_path) +static int __camera_get_device_info(int device_index, int device_fd, camera_device_info_t *device_info, char *node_path) { int i = 0; int j = 0; @@ -404,7 +404,7 @@ static int _camera_get_device_info(int device_index, int device_fd, camera_devic LOGD("\tformat[%d] "FOURCC_FORMAT, i, FOURCC_CONVERT(v4l2_format.pixelformat)); - if (_camera_get_format(v4l2_format.pixelformat, &camera_format) != CAMERA_ERROR_NONE) + if (__camera_get_format(v4l2_format.pixelformat, &camera_format) != CAMERA_ERROR_NONE) continue; device_info->format_list.formats[format_count] = camera_format; @@ -479,7 +479,7 @@ static int _camera_get_device_info(int device_index, int device_fd, camera_devic return CAMERA_ERROR_NONE; } -static int _camera_get_device_info_list(void) +static int __camera_get_device_info_list(void) { int i = 0; int ret = 0; @@ -548,18 +548,18 @@ static int _camera_get_device_info_list(void) } if (v4l2_cap.capabilities & V4L2_CAP_DEVICE_CAPS) - device_caps = v4l2_cap.device_caps; + g_device_caps = v4l2_cap.device_caps; else - device_caps = v4l2_cap.capabilities; + g_device_caps = v4l2_cap.capabilities; - if (!(device_caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)) || - (device_caps & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE))) { - LOGW("[%s] is not a capture device 0x%x", glob_buf.gl_pathv[i], device_caps); + if (!(g_device_caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)) || + (g_device_caps & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE))) { + LOGW("[%s] is not a capture device 0x%x", glob_buf.gl_pathv[i], g_device_caps); close(device_fd); continue; } - ret = _camera_get_device_info(device_count, device_fd, + ret = __camera_get_device_info(device_count, device_fd, &device_info_list->device_info[device_count], glob_buf.gl_pathv[i]); close(device_fd); @@ -585,7 +585,142 @@ _GET_DEVICE_INFO_LIST_DONE: } -static void *_camera_preview_handler_func(gpointer data) +static int __camera_stop_stream(camera_hal_handle *handle, uint32_t buffer_count) +{ + int i = 0; + int ret = CAMERA_ERROR_NONE; + + if (!handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGD("buffer count[%d]", buffer_count); + + /* stream off */ + ret = __camera_v4l2_stream(handle->device_fd, handle->v4l2_type, FALSE); + + LOGD("stream off : 0x%x", ret); + + /* munmap */ + for (i = 0 ; i < buffer_count ; i++) { + if (handle->camera_buffers[i].planes[0].data != NULL) { + LOGW("munmap %p", handle->camera_buffers[i].planes[0].data); + + munmap(handle->camera_buffers[i].planes[0].data, handle->camera_buffers[i].planes[0].size); + + handle->camera_buffers[i].planes[0].data = 0; + handle->camera_buffers[i].planes[0].size = 0; + } else { + LOGW("NULL data [index %d]", i); + } + } + + /* reqbufs 0 */ + ret = __camera_v4l2_reqbufs(handle->device_fd, + handle->v4l2_type, V4L2_MEMORY_MMAP, 0, &buffer_count); + + LOGD("reqbufs 0 : 0x%x", ret); + + return ret; +} + + +static int __camera_start_stream(camera_hal_handle *handle, camera_format_t *format, + uint32_t request_buffer_count, uint32_t *result_buffer_count) +{ + int i = 0; + int ret = CAMERA_ERROR_NONE; + camera_buffer_t *buffer = NULL; + struct v4l2_buffer v4l2_buf; + struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX]; + + if (!handle || !format || !result_buffer_count) { + LOGE("NULL param %p %p", handle, result_buffer_count); + 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); + 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); + + /* query buffer, mmap and qbuf */ + for (i = 0 ; i < *result_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.memory = V4L2_MEMORY_MMAP; + v4l2_buf.index = i; + v4l2_buf.m.planes = v4l2_planes; + v4l2_buf.length = handle->plane_num; + + LOGD("%d", i); + + 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->total_size = v4l2_buf.length; + buffer->num_planes = handle->plane_num; + buffer->planes[0].size = v4l2_buf.length; + buffer->planes[0].data = mmap(0, + v4l2_buf.length, + PROT_READ | PROT_WRITE, + MAP_SHARED, + 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) { + 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); + if (ret != CAMERA_ERROR_NONE) { + LOGE("stream on failed"); + goto _START_STREAM_FAILED; + } + + return CAMERA_ERROR_NONE; + +_START_STREAM_FAILED: + __camera_stop_stream(handle, *result_buffer_count); + return ret; +} + + +static void *__camera_buffer_handler_func(gpointer data) { int index = 0; camera_hal_handle *handle = (camera_hal_handle *)data; @@ -600,10 +735,10 @@ static void *_camera_preview_handler_func(gpointer data) /* run buffer thread */ g_mutex_lock(&handle->preview_cb_lock); - while (handle->preview_cb_run) { + while (handle->buffer_thread_run) { g_mutex_unlock(&handle->preview_cb_lock); - if (_camera_v4l2_wait_frame(handle->device_fd, 5) != CAMERA_ERROR_NONE) { + if (__camera_v4l2_wait_frame(handle->device_fd, 5) != CAMERA_ERROR_NONE) { LOGE("frame wait failed"); g_mutex_lock(&handle->preview_cb_lock); break; @@ -611,24 +746,24 @@ static void *_camera_preview_handler_func(gpointer data) g_mutex_lock(&handle->preview_cb_lock); - if (handle->preview_cb_run == FALSE) { + 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->v4l2_type, V4L2_MEMORY_MMAP, &index) != CAMERA_ERROR_NONE) { LOGE("dqbuf failed"); break; } handle->live_buffer_num++; - LOGD("live buffer num %d", handle->live_buffer_num); + /*LOGD("live buffer num %d", handle->live_buffer_num);*/ g_mutex_unlock(&handle->preview_cb_lock); if (handle->preview_cb) { - ((camera_preview_frame_cb)handle->preview_cb)(&handle->preview_buffer[index], NULL, handle->preview_cb_data); + ((camera_preview_frame_cb)handle->preview_cb)(&handle->camera_buffers[index], NULL, handle->preview_cb_data); } else { LOGW("preview callback is NULL"); camera_release_preview_buffer((void *)handle, index); @@ -647,7 +782,7 @@ static void *_camera_preview_handler_func(gpointer data) } -static void _camera_message_release_func(gpointer data) +static void __camera_message_release_func(gpointer data) { camera_message_t *message = (camera_message_t *)data; @@ -720,7 +855,7 @@ static void *_camera_message_handler_func(gpointer data) } -void _camera_release_handle(camera_hal_handle *handle) +static void __camera_release_handle(camera_hal_handle *handle) { if (!handle) { LOGW("NULL handle"); @@ -733,7 +868,7 @@ void _camera_release_handle(camera_hal_handle *handle) 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); + g_queue_free_full(handle->message_list, (GDestroyNotify)__camera_message_release_func); handle->message_list = NULL; } @@ -805,7 +940,7 @@ int camera_init(void **camera_handle) new_handle->device_fd = CAMERA_HAL_INITIAL_FD; new_handle->state = CAMERA_STATE_INITIALIZED; - ret = _camera_get_device_info_list(); + ret = __camera_get_device_info_list(); if (ret != CAMERA_ERROR_NONE) { LOGE("get device info failed"); goto _INIT_ERROR; @@ -818,22 +953,20 @@ int camera_init(void **camera_handle) return CAMERA_ERROR_NONE; _INIT_ERROR: - _camera_release_handle(new_handle); + __camera_release_handle(new_handle); return ret; } int camera_deinit(void *camera_handle) { - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { + if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); if (handle->state != CAMERA_STATE_INITIALIZED) { @@ -844,7 +977,7 @@ int camera_deinit(void *camera_handle) g_mutex_unlock(&handle->lock); - _camera_release_handle(handle); + __camera_release_handle(handle); return CAMERA_ERROR_NONE; } @@ -858,7 +991,7 @@ int camera_get_device_info_list(camera_device_info_list_t *device_info_list) return CAMERA_ERROR_INVALID_PARAMETER; } - ret = _camera_get_device_info_list(); + ret = __camera_get_device_info_list(); if (ret != CAMERA_ERROR_NONE) { LOGE("get device info failed"); return ret; @@ -874,15 +1007,13 @@ int camera_open_device(void *camera_handle, int device_index) int ret = CAMERA_ERROR_NONE; int device_fd = CAMERA_HAL_INITIAL_FD; char *node_path = NULL; - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { + if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); if (handle->state != CAMERA_STATE_INITIALIZED) { @@ -929,7 +1060,7 @@ int camera_open_device(void *camera_handle, int device_index) goto _OPEN_DEVICE_DONE; } - if (device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) + if (g_device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) handle->v4l2_type = V4L2_CAP_VIDEO_CAPTURE_MPLANE; else handle->v4l2_type = V4L2_CAP_VIDEO_CAPTURE; @@ -949,15 +1080,13 @@ _OPEN_DEVICE_DONE: int camera_close_device(void *camera_handle) { - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { + if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); if (handle->state != CAMERA_STATE_OPENED) { @@ -987,9 +1116,9 @@ int camera_close_device(void *camera_handle) int camera_add_message_callback(void *camera_handle, camera_message_cb callback, void *user_data, uint32_t *cb_id) { uint32_t i = 0; - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { + if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } @@ -999,8 +1128,6 @@ int camera_add_message_callback(void *camera_handle, camera_message_cb callback, return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); if (handle->state != CAMERA_STATE_OPENED) { @@ -1029,9 +1156,9 @@ int camera_add_message_callback(void *camera_handle, camera_message_cb callback, int camera_remove_message_callback(void *camera_handle, uint32_t cb_id) { - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { + if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } @@ -1041,8 +1168,6 @@ int camera_remove_message_callback(void *camera_handle, uint32_t cb_id) return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); if (handle->state != CAMERA_STATE_OPENED) { @@ -1075,18 +1200,13 @@ int camera_set_preview_stream_format(void *camera_handle, camera_format_t *forma int ret = CAMERA_ERROR_NONE; gboolean capability_check = FALSE; guint32 fourcc = 0; - camera_hal_handle *handle = NULL; + 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 (!camera_handle) { - LOGE("NULL handle"); - return CAMERA_ERROR_INVALID_PARAMETER; - } - - if (!format) { - LOGE("NULL format"); + if (!handle || !format) { + LOGE("NULL param %p %p", handle, format); return CAMERA_ERROR_INVALID_PARAMETER; } @@ -1095,8 +1215,6 @@ int camera_set_preview_stream_format(void *camera_handle, camera_format_t *forma return CAMERA_ERROR_INTERNAL; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); if (handle->state != CAMERA_STATE_OPENED) { @@ -1139,7 +1257,7 @@ int camera_set_preview_stream_format(void *camera_handle, camera_format_t *forma } /* S_FMT */ - ret = _camera_get_fourcc_plane_num(format->stream_format, &fourcc, &handle->plane_num); + 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); @@ -1220,20 +1338,13 @@ int camera_set_preview_stream_format(void *camera_handle, camera_format_t *forma int camera_get_preview_stream_format(void *camera_handle, camera_format_t *format) { - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { - LOGE("NULL handle"); + if (!handle || !format) { + LOGE("NULL param %p %p", handle, format); return CAMERA_ERROR_INVALID_PARAMETER; } - if (!format) { - LOGE("NULL format"); - return CAMERA_ERROR_INVALID_PARAMETER; - } - - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); memcpy(format, &handle->preview_format, sizeof(camera_format_t)); @@ -1249,27 +1360,14 @@ int camera_get_preview_stream_format(void *camera_handle, camera_format_t *forma int camera_start_preview(void *camera_handle, camera_preview_frame_cb callback, void *user_data) { - int i = 0; int ret = 0; - int result_count = 0; - camera_hal_handle *handle = NULL; - camera_buffer_t *buffer = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - struct v4l2_buffer v4l2_buf; - struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX]; - - if (!camera_handle) { - LOGE("NULL handle"); - return CAMERA_ERROR_INVALID_PARAMETER; - } - - if (!callback) { - LOGE("NULL callback for preview"); + if (!handle || !callback) { + LOGE("NULL param %p %p", handle, callback); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); if (handle->state != CAMERA_STATE_OPENED) { @@ -1278,78 +1376,28 @@ int camera_start_preview(void *camera_handle, camera_preview_frame_cb callback, return CAMERA_ERROR_INVALID_STATE; } - /* request buffer */ - ret = _camera_v4l2_reqbufs(handle->device_fd, - handle->v4l2_type, V4L2_MEMORY_MMAP, PREVIEW_BUFFER_MAX, &result_count); + ret = __camera_start_stream(handle, &handle->preview_format, BUFFER_MAX, &handle->buffer_count); if (ret != CAMERA_ERROR_NONE) { + LOGE("__camera_start_stream failed[0x%x]", ret); g_mutex_unlock(&handle->lock); return ret; } - LOGD("REQUESTED buffer count %d", result_count); - - handle->preview_buffer_num = result_count; - - /* query buffer, mmap and qbuf */ - for (i = 0 ; i < handle->preview_buffer_num ; i++) { - memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer)); - memset(v4l2_planes, 0x0, sizeof(v4l2_planes)); - - v4l2_buf.type = handle->v4l2_type; - v4l2_buf.memory = V4L2_MEMORY_MMAP; - v4l2_buf.index = i; - v4l2_buf.m.planes = v4l2_planes; - v4l2_buf.length = handle->plane_num; - - if (ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) { - LOGE("[%d] query buf failed. errno %d", i, errno); - goto _START_PREVIEW_FAILED; - } - - buffer = &handle->preview_buffer[i]; - - buffer->index = i; - buffer->format = handle->preview_format.stream_format; - buffer->resolution = handle->preview_format.stream_resolution; - buffer->total_size = v4l2_buf.length; - buffer->num_planes = handle->plane_num; - buffer->planes[0].size = v4l2_buf.length; - buffer->planes[0].data = mmap(0, - v4l2_buf.length, - PROT_READ | PROT_WRITE, - MAP_SHARED, - handle->device_fd, - v4l2_buf.m.offset); - if (buffer->planes[0].data == MAP_FAILED) { - LOGE("[%d] mmap failed. errno %d", i, errno); - goto _START_PREVIEW_FAILED; - } - } + g_mutex_lock(&handle->preview_cb_lock); - for (i = 0 ; i < handle->preview_buffer_num ; i++) { - if (_camera_v4l2_qbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, i) != CAMERA_ERROR_NONE) { - LOGE("qbuf failed"); - goto _START_PREVIEW_FAILED; - } - } + handle->buffer_thread_run = TRUE; - /* stream on */ - ret = _camera_v4l2_stream(handle->device_fd, handle->v4l2_type, TRUE); - if (ret != CAMERA_ERROR_NONE) { - LOGE("stream on failed"); - goto _START_PREVIEW_FAILED; - } + handle->buffer_thread = g_thread_try_new("camera_hal_buffer_thread", + __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_lock(&handle->preview_cb_lock); + __camera_stop_stream(handle, handle->buffer_count); - handle->preview_cb_run = TRUE; + g_mutex_unlock(&handle->lock); - handle->preview_thread = g_thread_try_new("camera_hal_preview_thread", - _camera_preview_handler_func, (gpointer)handle, NULL); - if (!handle->preview_thread) { - LOGE("failed to create preview callback thread"); - g_mutex_unlock(&handle->preview_cb_lock); - goto _START_PREVIEW_FAILED; + return ret; } handle->preview_cb = callback; @@ -1364,51 +1412,24 @@ int camera_start_preview(void *camera_handle, camera_preview_frame_cb callback, g_mutex_unlock(&handle->lock); return CAMERA_ERROR_NONE; - -_START_PREVIEW_FAILED: - /* stream off */ - if (ioctl(handle->device_fd, VIDIOC_STREAMOFF, &handle->v4l2_type) < 0) - LOGE("stream off failed. errno %d", errno); - - /* munmap */ - for (i = 0 ; i < handle->preview_buffer_num ; i++) { - buffer = &handle->preview_buffer[i]; - if (buffer->planes[0].data != NULL && - buffer->planes[0].data != MAP_FAILED) { - LOGW("munmap %p", buffer->planes[0].data); - munmap(buffer->planes[0].data, buffer->planes[0].size); - } - memset(buffer, 0x0, sizeof(camera_buffer_t)); - } - - /* reqbufs 0 */ - if (_camera_v4l2_reqbufs(handle->device_fd, - handle->v4l2_type, V4L2_MEMORY_MMAP, 0, &result_count) != CAMERA_ERROR_NONE) - LOGE("reqbufs 0 failed"); - - g_mutex_unlock(&handle->lock); - - return ret; } int camera_release_preview_buffer(void *camera_handle, int buffer_index) { int ret = CAMERA_ERROR_NONE; - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { + if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - - if (buffer_index >= handle->preview_buffer_num) { + if (buffer_index >= handle->buffer_count) { LOGE("invalid buffer index %d", buffer_index); return CAMERA_ERROR_INVALID_PARAMETER; } - ret = _camera_v4l2_qbuf(handle->device_fd, + ret = __camera_v4l2_qbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, buffer_index); g_mutex_lock(&handle->preview_cb_lock); @@ -1428,21 +1449,18 @@ int camera_release_preview_buffer(void *camera_handle, int buffer_index) return ret; } + int camera_stop_preview(void *camera_handle) { int ret = CAMERA_ERROR_NONE; - int i = 0; - int result_count = 0; gint64 end_time; - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { + if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - LOGD("start"); g_mutex_lock(&handle->lock); @@ -1455,7 +1473,7 @@ int camera_stop_preview(void *camera_handle) g_mutex_lock(&handle->preview_cb_lock); - handle->preview_cb_run = FALSE; + handle->buffer_thread_run = FALSE; while (handle->live_buffer_num > 0) { LOGD("wait for live buffer [num %d]", handle->live_buffer_num); @@ -1470,38 +1488,15 @@ int camera_stop_preview(void *camera_handle) g_mutex_unlock(&handle->preview_cb_lock); - /* stream off */ - ret = _camera_v4l2_stream(handle->device_fd, handle->v4l2_type, FALSE); - - LOGD("stream off : 0x%x", ret); - - /* munmap */ - for (i = 0 ; i < handle->preview_buffer_num ; i++) { - if (handle->preview_buffer[i].planes[0].data != NULL) { - LOGW("munmap %p", handle->preview_buffer[i].planes[0].data); - - munmap(handle->preview_buffer[i].planes[0].data, handle->preview_buffer[i].planes[0].size); - - handle->preview_buffer[i].planes[0].data = 0; - handle->preview_buffer[i].planes[0].size = 0; - } else { - LOGW("NULL data [index %d]", i); - } - } - - /* reqbufs 0 */ - ret = _camera_v4l2_reqbufs(handle->device_fd, - handle->v4l2_type, V4L2_MEMORY_MMAP, 0, &result_count); - - LOGD("reqbufs 0 : 0x%x", ret); + ret = __camera_stop_stream(handle, handle->buffer_count); /* wait for preview thread exit */ - g_thread_join(handle->preview_thread); - handle->preview_thread = NULL; + g_thread_join(handle->buffer_thread); + handle->buffer_thread = NULL; handle->state = CAMERA_STATE_OPENED; - LOGD("stop preview done"); + LOGD("stop preview done [0x%x]", ret); g_mutex_unlock(&handle->lock); @@ -1515,7 +1510,7 @@ int camera_start_auto_focus(void *camera_handle) return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* auto focus is not supported */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1528,7 +1523,7 @@ int camera_stop_auto_focus(void *camera_handle) return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* auto focus is not supported */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1538,11 +1533,11 @@ 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) { - LOGE("NULL handle %p or callback %p", camera_handle, callback); + LOGE("NULL param %p %p", camera_handle, callback); return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* capture function is not supported */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1555,7 +1550,7 @@ int camera_stop_capture(void *camera_handle) return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* capture function is not supported */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1563,17 +1558,12 @@ int camera_stop_capture(void *camera_handle) int camera_set_video_stream_format(void *camera_handle, camera_format_t *format) { - if (!camera_handle) { - LOGE("NULL handle"); + if (!camera_handle || !format) { + LOGE("NULL param %p %p", camera_handle, format); return CAMERA_ERROR_INVALID_PARAMETER; } - if (!format) { - LOGE("NULL format"); - return CAMERA_ERROR_INVALID_PARAMETER; - } - - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* single stream device can not support video stream */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1581,17 +1571,12 @@ int camera_set_video_stream_format(void *camera_handle, camera_format_t *format) int camera_get_video_stream_format(void *camera_handle, camera_format_t *format) { - if (!camera_handle) { - LOGE("NULL handle"); - return CAMERA_ERROR_INVALID_PARAMETER; - } - - if (!format) { - LOGE("NULL format"); + if (!camera_handle || !format) { + LOGE("NULL param %p %p", camera_handle, format); return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* single stream device can not support video stream */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1599,17 +1584,12 @@ int camera_get_video_stream_format(void *camera_handle, camera_format_t *format) int camera_start_record(void *camera_handle, camera_video_frame_cb callback, void *user_data) { - if (!camera_handle) { - LOGE("NULL handle"); - return CAMERA_ERROR_INVALID_PARAMETER; - } - - if (!callback) { - LOGE("NULL callback for video"); + if (!camera_handle || !callback) { + LOGE("NULL param %p %p", camera_handle, callback); return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* single stream device can not support video stream */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1622,7 +1602,7 @@ int camera_release_video_buffer(void *camera_handle, int buffer_index) return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* single stream device can not support video stream */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1635,7 +1615,7 @@ int camera_stop_record(void *camera_handle) return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* single stream device can not support video stream */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1647,19 +1627,13 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) int cid = 0; int ctrl_ret = 0; int set_value = 0; - camera_hal_handle *handle = NULL; - - if (!camera_handle) { - LOGE("NULL handle"); - return CAMERA_ERROR_INVALID_PARAMETER; - } + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!value) { - LOGE("invalid pointer : value"); + if (!handle || !value) { + LOGE("NULL param %p %p", handle, value); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; set_value = *(int *)value; g_mutex_lock(&handle->lock); @@ -1700,13 +1674,22 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) case CAMERA_COMMAND_TILT: 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; + } + break; default: LOGE("NOT_SUPPORTED %"PRId64, command); g_mutex_unlock(&handle->lock); return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } - ctrl_ret = _camera_v4l2_s_ctrl(handle->device_fd, cid, set_value); + ctrl_ret = __camera_v4l2_s_ctrl(handle->device_fd, cid, set_value); if (ctrl_ret < 0) { switch (errno) { case EACCES: @@ -1743,20 +1726,13 @@ int camera_get_command(void *camera_handle, int64_t command, void **value) int ret = CAMERA_ERROR_NONE; int cid = 0; int ctrl_ret = 0; - camera_hal_handle *handle = NULL; - - if (!camera_handle) { - LOGE("NULL handle"); - return CAMERA_ERROR_INVALID_PARAMETER; - } + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!value) { - LOGE("invalid pointer for value"); + if (!handle || !value) { + LOGE("NULL param %p %p", handle, value); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); LOGD("get command %"PRId64" - state %d", command, handle->state); @@ -1780,7 +1756,7 @@ int camera_get_command(void *camera_handle, int64_t command, void **value) return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } - ctrl_ret = _camera_v4l2_g_ctrl(handle->device_fd, cid, (int *)value); + ctrl_ret = __camera_v4l2_g_ctrl(handle->device_fd, cid, (int *)value); if (ctrl_ret < 0) { switch (errno) { case EACCES: @@ -1814,20 +1790,13 @@ int camera_get_command(void *camera_handle, int64_t command, void **value) int camera_set_batch_command(void *camera_handle, camera_batch_command_control_t *batch_command, int64_t *error_command) { - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { - LOGE("NULL handle"); + if (!handle || !batch_command) { + LOGE("NULL param %p %p", handle, batch_command); return CAMERA_ERROR_INVALID_PARAMETER; } - if (!batch_command) { - LOGE("invalid pointer for batch_command"); - return CAMERA_ERROR_INVALID_PARAMETER; - } - - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); LOGD("set batch command - flag %"PRIx64", state %d", diff --git a/src/tizen_camera_v4l2_private.h b/src/tizen_camera_v4l2_private.h index e70ceac..2e4996f 100644 --- a/src/tizen_camera_v4l2_private.h +++ b/src/tizen_camera_v4l2_private.h @@ -28,8 +28,7 @@ #define CAMERA_HAL_INITIAL_INDEX -1 #define CAMERA_HAL_INITIAL_FD -1 #define MESSAGE_CALLBACK_MAX 10 -#define PREVIEW_BUFFER_MAX 4 -#define VIDEO_BUFFER_MAX 8 +#define BUFFER_MAX 4 #define V4L2_PLANES_MAX 4 typedef struct _camera_hal_handle { @@ -47,22 +46,17 @@ typedef struct _camera_hal_handle { int live_buffer_num; /* thread */ - GThread *preview_thread; + GThread *buffer_thread; GThread *message_thread; + gboolean buffer_thread_run; - /* preview callback */ + /* buffer handler */ camera_preview_frame_cb preview_cb; + camera_capture_cb capture_cb; void *preview_cb_data; - gboolean preview_cb_run; - uint32_t preview_buffer_num; - camera_buffer_t preview_buffer[PREVIEW_BUFFER_MAX]; - - /* video callback */ - camera_video_frame_cb video_cb; - void *video_cb_data; - gboolean video_cb_run; - uint32_t video_buffer_num; - camera_buffer_t video_buffer[VIDEO_BUFFER_MAX]; + void *capture_cb_data; + uint32_t buffer_count; + camera_buffer_t camera_buffers[BUFFER_MAX]; /* message callback */ camera_message_cb message_cb[MESSAGE_CALLBACK_MAX]; -- 2.7.4 From 0fecd7c40cbcf2438e5c32512b56b5d758d49496 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Thu, 23 Jul 2020 19:56:57 +0900 Subject: [PATCH 05/16] Support capture function - 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 --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 533 +++++++++++++++++++++++++++------------- src/tizen_camera_v4l2_private.h | 58 +++-- 3 files changed, 393 insertions(+), 200 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index 58bdca4..353c6a3 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -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 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index 2b4b06d..0ade153 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -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) diff --git a/src/tizen_camera_v4l2_private.h b/src/tizen_camera_v4l2_private.h index 2e4996f..c6abc44 100644 --- a/src/tizen_camera_v4l2_private.h +++ b/src/tizen_camera_v4l2_private.h @@ -32,44 +32,48 @@ #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__ */ -- 2.7.4 From 411b1395f719d092e8ca908ee5fdca3ce743b1dc Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Tue, 29 Dec 2020 17:59:44 +0900 Subject: [PATCH 06/16] Support continuous capture [Version] 0.0.13 [Issue Type] Update Change-Id: Id61d1eab11c10c8f11dae08bf65a15061e049323 Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 133 +++++++++++++++++++++++++--------------- src/tizen_camera_v4l2_private.h | 1 + 3 files changed, 85 insertions(+), 51 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index 353c6a3..61e7eee 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -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 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index 0ade153..11c1b32 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -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; diff --git a/src/tizen_camera_v4l2_private.h b/src/tizen_camera_v4l2_private.h index c6abc44..035316b 100644 --- a/src/tizen_camera_v4l2_private.h +++ b/src/tizen_camera_v4l2_private.h @@ -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; -- 2.7.4 From 7fa3027ab19c066471efa66b09e57cd3eb3da631 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Fri, 29 Jan 2021 21:36:21 +0900 Subject: [PATCH 07/16] Support Next HAL for tizen 6.5 [Version] 0.1.0 [Issue Type] Update Change-Id: I649fa88fef88033f2efe1ad263219e39c8db1452 Signed-off-by: Jeongmo Yang --- configure.ac | 6 + packaging/camera-hal-v4l2.spec | 10 +- src/Makefile.am | 28 +-- src/{tizen_camera_v4l2.c => hal_camera_v4l2.c} | 227 ++++++++++++++++++------- src/hal_camera_v4l2_private.h | 108 ++++++++++++ src/tizen_camera_v4l2_private.h | 80 --------- 6 files changed, 298 insertions(+), 161 deletions(-) rename src/{tizen_camera_v4l2.c => hal_camera_v4l2.c} (87%) create mode 100644 src/hal_camera_v4l2_private.h delete mode 100644 src/tizen_camera_v4l2_private.h diff --git a/configure.ac b/configure.ac index e605900..ef6f7fc 100644 --- a/configure.ac +++ b/configure.ac @@ -35,6 +35,12 @@ PKG_CHECK_MODULES(DLOG, dlog) AC_SUBST(DLOG_CFLAGS) AC_SUBST(DLOG_LIBS) +PKG_CHECK_MODULES(HAL_API_COMMON, hal-api-common) +AC_SUBST(HAL_API_COMMON_CFLAGS) + +PKG_CHECK_MODULES(HAL_API_CAMERA, hal-api-camera) +AC_SUBST(HAL_API_CAMERA_CFLAGS) + # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS([fcntl.h memory.h stdlib.h string.h sys/time.h unistd.h]) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index 61e7eee..fa0d652 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.13 +Version: 0.1.0 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 @@ -10,8 +10,8 @@ Requires(postun): /sbin/ldconfig BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(libtbm) BuildRequires: pkgconfig(dlog) -BuildRequires: mm-hal-interface-devel -BuildRequires: gtest-devel +BuildRequires: pkgconfig(hal-api-common) +BuildRequires: pkgconfig(hal-api-camera) %description Tizen Camera Hal for V4L2. @@ -23,7 +23,7 @@ Tizen Camera Hal for V4L2. %build ./autogen.sh -%configure --disable-static +%configure --disable-static --libdir=%{_hal_libdir} make %{?jobs:-j%jobs} %install @@ -39,5 +39,5 @@ make %{?jobs:-j%jobs} %manifest %{name}.manifest %license LICENSE.APLv2 %defattr(-,root,root,-) -%{_libdir}/*.so +%{_hal_libdir}/*.so diff --git a/src/Makefile.am b/src/Makefile.am index 46be497..58cb115 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,20 +1,24 @@ ACLOCAL_AMFLAGS='-I m4' -lib_LTLIBRARIES = libtizen-camera.la +lib_LTLIBRARIES = libhal-backend-camera.la -noinst_HEADERS = tizen_camera_v4l2_private.h +noinst_HEADERS = hal_camera_v4l2_private.h -libtizen_camera_la_SOURCES = tizen_camera_v4l2.c +libhal_backend_camera_la_SOURCES = hal_camera_v4l2.c -libtizen_camera_la_CFLAGS = -I$(srcdir)/include \ - $(GLIB_CFLAGS) \ - $(DLOG_CFLAGS) \ - $(TBM_CFLAGS) +libhal_backend_camera_la_CFLAGS = \ + -I$(srcdir)/include \ + $(GLIB_CFLAGS) \ + $(DLOG_CFLAGS) \ + $(HAL_API_COMMON_CFLAGS) \ + $(HAL_API_CAMERA_CFLAGS) \ + $(TBM_CFLAGS) -libtizen_camera_la_LIBADD = $(GLIB_LIBS) \ - $(DLOG_LIBS) \ - $(TBM_LIBS) +libhal_backend_camera_la_LIBADD = \ + $(GLIB_LIBS) \ + $(DLOG_LIBS) \ + $(TBM_LIBS) -libtizen_camera_la_CFLAGS += -fdata-sections -ffunction-sections -Wl,--gc-sections -libtizen_camera_la_LDFLAGS = -Wl,--gc-sections -avoid-version +libhal_backend_camera_la_CFLAGS += -fdata-sections -ffunction-sections -Wl,--gc-sections +libhal_backend_camera_la_LDFLAGS = -Wl,--gc-sections -avoid-version diff --git a/src/tizen_camera_v4l2.c b/src/hal_camera_v4l2.c similarity index 87% rename from src/tizen_camera_v4l2.c rename to src/hal_camera_v4l2.c index 11c1b32..e82d995 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/hal_camera_v4l2.c @@ -33,7 +33,7 @@ #include #include #include -#include "tizen_camera_v4l2_private.h" +#include "hal_camera_v4l2_private.h" #ifdef LOG_TAG #undef LOG_TAG @@ -51,13 +51,14 @@ (fourcc >> 24) & 0xff -static camera_device_info_list_t *g_device_info_list; +static camera_device_info_list_s *g_device_info_list; static guint32 g_device_caps; static GMutex g_device_info_lock; static void __camera_hal_v4l2_destructor(void) __attribute__((destructor)); + static void __camera_hal_v4l2_destructor(void) { LOGD("release device info list %p", g_device_info_list); @@ -68,6 +69,7 @@ static void __camera_hal_v4l2_destructor(void) return; } + static int __camera_v4l2_wait_frame(int device_fd, int wait_time) { int ret = CAMERA_ERROR_NONE; @@ -322,6 +324,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, guint32 *plane_num) { if (!fourcc || !plane_num) { @@ -374,7 +377,7 @@ static int __camera_get_fourcc_plane_num(int pixel_format, guint32 *fourcc, guin } -static int __camera_get_device_info(int device_index, int device_fd, camera_device_info_t *device_info, char *node_path) +static int __camera_get_device_info(int device_index, int device_fd, camera_device_info_s *device_info, char *node_path) { int i = 0; int j = 0; @@ -479,6 +482,7 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi return CAMERA_ERROR_NONE; } + static int __camera_get_device_info_list(void) { int i = 0; @@ -487,7 +491,7 @@ static int __camera_get_device_info_list(void) int device_fd = CAMERA_HAL_INITIAL_FD; glob_t glob_buf; struct v4l2_capability v4l2_cap; - camera_device_info_list_t *device_info_list = NULL; + camera_device_info_list_s *device_info_list = NULL; g_mutex_lock(&g_device_info_lock); @@ -497,7 +501,7 @@ static int __camera_get_device_info_list(void) goto _GET_DEVICE_INFO_LIST_DONE; } - device_info_list = g_new0(camera_device_info_list_t, 1); + device_info_list = g_new0(camera_device_info_list_s, 1); if (!device_info_list) { LOGE("failed to alloc device info structure"); ret = CAMERA_ERROR_OUT_OF_MEMORY; @@ -585,7 +589,7 @@ _GET_DEVICE_INFO_LIST_DONE: } -static int __camera_stop_stream(camera_hal_handle *handle, uint32_t buffer_count) +static int __camera_stop_stream(hal_camera_handle *handle, uint32_t buffer_count) { int i = 0; int ret = CAMERA_ERROR_NONE; @@ -626,12 +630,12 @@ static int __camera_stop_stream(camera_hal_handle *handle, uint32_t 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) +static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_e pixel_format, + camera_resolution_s *resolution, uint32_t fps, uint32_t request_buffer_count) { int i = 0; int ret = CAMERA_ERROR_NONE; - camera_buffer_t *buffer = NULL; + camera_buffer_s *buffer = NULL; struct v4l2_format v4l2_fmt; struct v4l2_streamparm v4l2_parm; struct v4l2_buffer v4l2_buf; @@ -770,7 +774,7 @@ _START_STREAM_FAILED: } -static void __camera_do_capture(camera_hal_handle *handle) +static void __camera_do_capture(hal_camera_handle *handle) { int ret = CAMERA_ERROR_NONE; int buffer_index = 0; @@ -851,7 +855,7 @@ static void __camera_do_capture(camera_hal_handle *handle) handle->capture_cb, buffer_index, handle->captured_count); if (handle->capture_cb) { - ((camera_capture_cb)handle->capture_cb)(&handle->camera_buffers[buffer_index], + handle->capture_cb(&handle->camera_buffers[buffer_index], NULL, NULL, handle->capture_cb_data); } else { LOGW("capture callback is NULL"); @@ -902,7 +906,7 @@ _CAPTURE_DONE: static void *__camera_buffer_handler_func(gpointer data) { int index = 0; - camera_hal_handle *handle = (camera_hal_handle *)data; + hal_camera_handle *handle = (hal_camera_handle *)data; if (!handle) { LOGE("NULL handle for buffer handler"); @@ -942,10 +946,10 @@ static void *__camera_buffer_handler_func(gpointer data) 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); + handle->preview_cb(&handle->camera_buffers[index], NULL, handle->preview_cb_data); } else { LOGW("preview callback is NULL"); - camera_release_preview_buffer((void *)handle, index); + camera_v4l2_release_preview_buffer((void *)handle, index); } /* check capture request flag */ @@ -969,7 +973,7 @@ static void *__camera_buffer_handler_func(gpointer data) static void __camera_message_release_func(gpointer data) { - camera_message_t *message = (camera_message_t *)data; + camera_message_s *message = (camera_message_s *)data; if (!message) { LOGW("NULL message"); @@ -987,8 +991,8 @@ static void __camera_message_release_func(gpointer data) static void *_camera_message_handler_func(gpointer data) { int i = 0; - camera_message_t *message = NULL; - camera_hal_handle *handle = (camera_hal_handle *)data; + camera_message_s *message = NULL; + hal_camera_handle *handle = (hal_camera_handle *)data; if (!handle) { LOGE("NULL handle for capture thread"); @@ -1022,7 +1026,7 @@ static void *_camera_message_handler_func(gpointer data) for (i = 0 ; i < MESSAGE_CALLBACK_MAX ; i++) { if (handle->msg_cb[i]) { LOGD("call message callback type %d", message->type); - ((camera_message_cb)handle->msg_cb[i])(message, handle->msg_cb_data[i]); + handle->msg_cb[i](message, handle->msg_cb_data[i]); } } @@ -1040,7 +1044,7 @@ static void *_camera_message_handler_func(gpointer data) } -static void __camera_release_handle(camera_hal_handle *handle) +static void __camera_release_handle(hal_camera_handle *handle) { if (!handle) { LOGW("NULL handle"); @@ -1076,10 +1080,10 @@ static void __camera_release_handle(camera_hal_handle *handle) } -int camera_init(void **camera_handle) +int camera_v4l2_init(void **camera_handle) { int ret = CAMERA_ERROR_NONE; - camera_hal_handle *new_handle = NULL; + hal_camera_handle *new_handle = NULL; tbm_bufmgr bufmgr = NULL; LOGD("enter"); @@ -1095,7 +1099,7 @@ int camera_init(void **camera_handle) return CAMERA_ERROR_INTERNAL; } - new_handle = g_new0(camera_hal_handle, 1); + new_handle = g_new0(hal_camera_handle, 1); if (!new_handle) { LOGE("failed to alloc camera hal handle"); tbm_bufmgr_deinit(bufmgr); @@ -1143,9 +1147,10 @@ _INIT_ERROR: return ret; } -int camera_deinit(void *camera_handle) + +int camera_v4l2_deinit(void *camera_handle) { - camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; if (!handle) { LOGE("NULL handle"); @@ -1167,7 +1172,8 @@ int camera_deinit(void *camera_handle) return CAMERA_ERROR_NONE; } -int camera_get_device_info_list(camera_device_info_list_t *device_info_list) + +int camera_v4l2_get_device_info_list(camera_device_info_list_s *device_info_list) { int ret = 0; @@ -1182,17 +1188,18 @@ int camera_get_device_info_list(camera_device_info_list_t *device_info_list) return ret; } - memcpy(device_info_list, g_device_info_list, sizeof(camera_device_info_list_t)); + memcpy(device_info_list, g_device_info_list, sizeof(camera_device_info_list_s)); return CAMERA_ERROR_NONE; } -int camera_open_device(void *camera_handle, int device_index) + +int camera_v4l2_open_device(void *camera_handle, int device_index) { int ret = CAMERA_ERROR_NONE; int device_fd = CAMERA_HAL_INITIAL_FD; char *node_path = NULL; - camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; if (!handle) { LOGE("NULL handle"); @@ -1263,9 +1270,17 @@ _OPEN_DEVICE_DONE: return ret; } -int camera_close_device(void *camera_handle) + +int camera_v4l2_open_device_ext(void *camera_handle, const char *device_name) +{ + LOGE("NOT SUPPORTED"); + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; +} + + +int camera_v4l2_close_device(void *camera_handle) { - camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; if (!handle) { LOGE("NULL handle"); @@ -1298,10 +1313,11 @@ int camera_close_device(void *camera_handle) return CAMERA_ERROR_NONE; } -int camera_add_message_callback(void *camera_handle, camera_message_cb callback, void *user_data, uint32_t *cb_id) + +int camera_v4l2_add_message_callback(void *camera_handle, hal_camera_message_cb callback, void *user_data, uint32_t *cb_id) { uint32_t i = 0; - camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; if (!handle) { LOGE("NULL handle"); @@ -1339,9 +1355,10 @@ int camera_add_message_callback(void *camera_handle, camera_message_cb callback, return CAMERA_ERROR_INTERNAL; } -int camera_remove_message_callback(void *camera_handle, uint32_t cb_id) + +int camera_v4l2_remove_message_callback(void *camera_handle, uint32_t cb_id) { - camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; if (!handle) { LOGE("NULL handle"); @@ -1378,14 +1395,15 @@ int camera_remove_message_callback(void *camera_handle, uint32_t cb_id) return CAMERA_ERROR_NONE; } -int camera_set_preview_stream_format(void *camera_handle, camera_format_t *format) + +int camera_v4l2_set_preview_stream_format(void *camera_handle, camera_format_s *format) { int i = 0; int j = 0; int ret = CAMERA_ERROR_NONE; gboolean capability_check = FALSE; - camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - camera_device_info_t *device_info = NULL; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; + camera_device_info_s *device_info = NULL; if (!handle || !format) { LOGE("NULL param %p %p", handle, format); @@ -1482,7 +1500,7 @@ _SET_PREVIEW_STREAM_FORMAT_DONE: else handle->capture_restart_stream = TRUE; - memcpy(&handle->preview_format, format, sizeof(camera_format_t)); + memcpy(&handle->preview_format, format, sizeof(camera_format_s)); LOGD("set format PREVIEW[%d:%dx%d,fps:%d], CAPTURE[%d:%dx%d,restart:%d]", format->stream_format, @@ -1499,9 +1517,10 @@ _SET_PREVIEW_STREAM_FORMAT_DONE: return CAMERA_ERROR_NONE; } -int camera_get_preview_stream_format(void *camera_handle, camera_format_t *format) + +int camera_v4l2_get_preview_stream_format(void *camera_handle, camera_format_s *format) { - camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; if (!handle || !format) { LOGE("NULL param %p %p", handle, format); @@ -1510,7 +1529,7 @@ int camera_get_preview_stream_format(void *camera_handle, camera_format_t *forma g_mutex_lock(&handle->lock); - memcpy(format, &handle->preview_format, sizeof(camera_format_t)); + memcpy(format, &handle->preview_format, sizeof(camera_format_s)); LOGD("get stream format %d, %dx%d", format->stream_format, format->stream_resolution.width, format->stream_resolution.height); @@ -1521,10 +1540,17 @@ int camera_get_preview_stream_format(void *camera_handle, camera_format_t *forma } -int camera_start_preview(void *camera_handle, camera_preview_frame_cb callback, void *user_data) +int camera_v4l2_set_user_buffer_fd(void *camera_handle, int *fds, int number) +{ + LOGE("NOT SUPPORTED"); + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; +} + + +int camera_v4l2_start_preview(void *camera_handle, hal_camera_preview_frame_cb callback, void *user_data) { int ret = 0; - camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; if (!handle || !callback) { LOGE("NULL param %p %p", handle, callback); @@ -1581,10 +1607,11 @@ int camera_start_preview(void *camera_handle, camera_preview_frame_cb callback, return CAMERA_ERROR_NONE; } -int camera_release_preview_buffer(void *camera_handle, int buffer_index) + +int camera_v4l2_release_preview_buffer(void *camera_handle, int buffer_index) { int ret = CAMERA_ERROR_NONE; - camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; if (!handle) { LOGE("NULL handle"); @@ -1621,11 +1648,11 @@ int camera_release_preview_buffer(void *camera_handle, int buffer_index) } -int camera_stop_preview(void *camera_handle) +int camera_v4l2_stop_preview(void *camera_handle) { int ret = CAMERA_ERROR_NONE; gint64 end_time; - camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; if (!handle) { LOGE("NULL handle"); @@ -1674,7 +1701,8 @@ int camera_stop_preview(void *camera_handle) return CAMERA_ERROR_NONE; } -int camera_start_auto_focus(void *camera_handle) + +int camera_v4l2_start_auto_focus(void *camera_handle) { if (!camera_handle) { LOGE("NULL handle"); @@ -1687,7 +1715,8 @@ int camera_start_auto_focus(void *camera_handle) return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } -int camera_stop_auto_focus(void *camera_handle) + +int camera_v4l2_stop_auto_focus(void *camera_handle) { if (!camera_handle) { LOGE("NULL handle"); @@ -1701,9 +1730,9 @@ int camera_stop_auto_focus(void *camera_handle) } -int camera_start_capture(void *camera_handle, camera_capture_cb callback, void *user_data) +int camera_v4l2_start_capture(void *camera_handle, hal_camera_capture_cb callback, void *user_data) { - camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; if (!handle || !callback) { LOGE("NULL param %p %p", camera_handle, callback); @@ -1737,9 +1766,10 @@ int camera_start_capture(void *camera_handle, camera_capture_cb callback, void * return CAMERA_ERROR_NONE; } -int camera_stop_capture(void *camera_handle) + +int camera_v4l2_stop_capture(void *camera_handle) { - camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; if (!handle) { LOGE("NULL handle"); @@ -1775,7 +1805,8 @@ int camera_stop_capture(void *camera_handle) return CAMERA_ERROR_NONE; } -int camera_set_video_stream_format(void *camera_handle, camera_format_t *format) + +int camera_v4l2_set_video_stream_format(void *camera_handle, camera_format_s *format) { if (!camera_handle || !format) { LOGE("NULL param %p %p", camera_handle, format); @@ -1788,7 +1819,8 @@ int camera_set_video_stream_format(void *camera_handle, camera_format_t *format) return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } -int camera_get_video_stream_format(void *camera_handle, camera_format_t *format) + +int camera_v4l2_get_video_stream_format(void *camera_handle, camera_format_s *format) { if (!camera_handle || !format) { LOGE("NULL param %p %p", camera_handle, format); @@ -1801,7 +1833,8 @@ int camera_get_video_stream_format(void *camera_handle, camera_format_t *format) return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } -int camera_start_record(void *camera_handle, camera_video_frame_cb callback, void *user_data) + +int camera_v4l2_start_record(void *camera_handle, hal_camera_video_frame_cb callback, void *user_data) { if (!camera_handle || !callback) { LOGE("NULL param %p %p", camera_handle, callback); @@ -1814,7 +1847,8 @@ int camera_start_record(void *camera_handle, camera_video_frame_cb callback, voi return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } -int camera_release_video_buffer(void *camera_handle, int buffer_index) + +int camera_v4l2_release_video_buffer(void *camera_handle, int buffer_index) { if (!camera_handle) { LOGE("NULL handle"); @@ -1827,7 +1861,8 @@ int camera_release_video_buffer(void *camera_handle, int buffer_index) return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } -int camera_stop_record(void *camera_handle) + +int camera_v4l2_stop_record(void *camera_handle) { if (!camera_handle) { LOGE("NULL handle"); @@ -1840,13 +1875,14 @@ int camera_stop_record(void *camera_handle) return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } -int camera_set_command(void *camera_handle, int64_t command, void *value) + +int camera_v4l2_set_command(void *camera_handle, int64_t command, void *value) { int ret = CAMERA_ERROR_NONE; int cid = 0; int ctrl_ret = 0; int set_value = 0; - camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; if (!handle || !value) { LOGE("NULL param %p %p", handle, value); @@ -1943,12 +1979,13 @@ _SET_COMMAND_DONE: return ret; } -int camera_get_command(void *camera_handle, int64_t command, void **value) + +int camera_v4l2_get_command(void *camera_handle, int64_t command, void **value) { int ret = CAMERA_ERROR_NONE; int cid = 0; int ctrl_ret = 0; - camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; if (!handle || !value) { LOGE("NULL param %p %p", handle, value); @@ -2010,9 +2047,10 @@ int camera_get_command(void *camera_handle, int64_t command, void **value) return ret; } -int camera_set_batch_command(void *camera_handle, camera_batch_command_control_t *batch_command, int64_t *error_command) + +int camera_v4l2_set_batch_command(void *camera_handle, camera_batch_command_control_s *batch_command, int64_t *error_command) { - camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; if (!handle || !batch_command) { LOGE("NULL param %p %p", handle, batch_command); @@ -2030,3 +2068,64 @@ int camera_set_batch_command(void *camera_handle, camera_batch_command_control_t return CAMERA_ERROR_NONE; } + + +static int camera_v4l2_backend_init(void **data) +{ + hal_backend_camera_funcs *funcs; + + funcs = calloc(1, sizeof(hal_backend_camera_funcs)); + if (!funcs) + return CAMERA_ERROR_OUT_OF_MEMORY; + + funcs->init = camera_v4l2_init; + funcs->deinit = camera_v4l2_deinit; + funcs->get_device_info_list = camera_v4l2_get_device_info_list; + funcs->open_device = camera_v4l2_open_device; + funcs->open_device_ext = camera_v4l2_open_device_ext; + funcs->close_device = camera_v4l2_close_device; + funcs->add_message_callback = camera_v4l2_add_message_callback; + funcs->remove_message_callback = camera_v4l2_remove_message_callback; + funcs->set_preview_stream_format = camera_v4l2_set_preview_stream_format; + funcs->get_preview_stream_format = camera_v4l2_get_preview_stream_format; + funcs->set_user_buffer_fd = camera_v4l2_set_user_buffer_fd; + funcs->start_preview = camera_v4l2_start_preview; + funcs->release_preview_buffer = camera_v4l2_release_preview_buffer; + funcs->stop_preview = camera_v4l2_stop_preview; + funcs->start_auto_focus = camera_v4l2_start_auto_focus; + funcs->stop_auto_focus = camera_v4l2_stop_auto_focus; + funcs->start_capture = camera_v4l2_start_capture; + funcs->stop_capture = camera_v4l2_stop_capture; + funcs->set_video_stream_format = camera_v4l2_set_video_stream_format; + funcs->get_video_stream_format = camera_v4l2_get_video_stream_format; + funcs->start_record = camera_v4l2_start_record; + funcs->release_video_buffer = camera_v4l2_release_video_buffer; + funcs->stop_record = camera_v4l2_stop_record; + funcs->set_command = camera_v4l2_set_command; + funcs->get_command = camera_v4l2_get_command; + funcs->set_batch_command = camera_v4l2_set_batch_command; + + *data = (void *)funcs; + + return 0; +} + + +static int camera_v4l2_backend_exit(void *data) +{ + if (!data) + return 0; + + free(data); + + return 0; +} + + +hal_backend hal_backend_camera_data = { + .name = "camera-v4l2", + .vendor = "TIZEN", + .abi_version = HAL_ABI_VERSION_TIZEN_6_5, + .init = camera_v4l2_backend_init, + .exit = camera_v4l2_backend_exit, +}; diff --git a/src/hal_camera_v4l2_private.h b/src/hal_camera_v4l2_private.h new file mode 100644 index 0000000..b6eb18a --- /dev/null +++ b/src/hal_camera_v4l2_private.h @@ -0,0 +1,108 @@ +/* + * hal_camera_v4l2_private.h + * + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __HAL_CAMERA_V4L2_PRIVATE_H__ +#define __HAL_CAMERA_V4L2_PRIVATE_H__ + +#include +#include +#include +#include +#include + +#define CAMERA_HAL_INITIAL_INDEX -1 +#define CAMERA_HAL_INITIAL_FD -1 +#define MESSAGE_CALLBACK_MAX 10 +#define BUFFER_MAX 4 +#define V4L2_PLANES_MAX 4 + +typedef struct _camera_hal_handle { + /* tbm */ + tbm_bufmgr bufmgr; + + /* device */ + gint32 device_index; + gint32 device_fd; + + /* buffer */ + guint32 buffer_dequeued_count; + GThread *buffer_thread; + gboolean buffer_thread_run; + guint32 buffer_count; + camera_buffer_s camera_buffers[BUFFER_MAX]; + enum v4l2_buf_type buffer_type; + GMutex buffer_lock; + GCond buffer_cond; + + /* preview */ + camera_format_s preview_format; + hal_camera_preview_frame_cb preview_cb; + gpointer preview_cb_data; + + /* capture */ + hal_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; + + /* message */ + GThread *msg_thread; + hal_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; + + /* etc */ + GMutex lock; + camera_state_e state; +} hal_camera_handle; + +int camera_v4l2_init(void **camera_handle); +int camera_v4l2_deinit(void *camera_handle); +int camera_v4l2_get_device_info_list(camera_device_info_list_s *device_info_list); +int camera_v4l2_open_device(void *camera_handle, int device_index); +int camera_v4l2_open_device_ext(void *camera_handle, const char *device_name); +int camera_v4l2_close_device(void *camera_handle); +int camera_v4l2_add_message_callback(void *camera_handle, hal_camera_message_cb callback, void *user_data, uint32_t *cb_id); +int camera_v4l2_remove_message_callback(void *camera_handle, uint32_t cb_id); +int camera_v4l2_set_preview_stream_format(void *camera_handle, camera_format_s *format); +int camera_v4l2_get_preview_stream_format(void *camera_handle, camera_format_s *format); +int camera_v4l2_set_user_buffer_fd(void *camera_handle, int *fds, int number); +int camera_v4l2_start_preview(void *camera_handle, hal_camera_preview_frame_cb callback, void *user_data); +int camera_v4l2_release_preview_buffer(void *camera_handle, int buffer_index); +int camera_v4l2_stop_preview(void *camera_handle); +int camera_v4l2_start_auto_focus(void *camera_handle); +int camera_v4l2_stop_auto_focus(void *camera_handle); +int camera_v4l2_start_capture(void *camera_handle, hal_camera_capture_cb callback, void *user_data); +int camera_v4l2_stop_capture(void *camera_handle); +int camera_v4l2_set_video_stream_format(void *camera_handle, camera_format_s *format); +int camera_v4l2_get_video_stream_format(void *camera_handle, camera_format_s *format); +int camera_v4l2_start_record(void *camera_handle, hal_camera_video_frame_cb callback, void *user_data); +int camera_v4l2_release_video_buffer(void *camera_handle, int buffer_index); +int camera_v4l2_stop_record(void *camera_handle); +int camera_v4l2_set_command(void *camera_handle, int64_t command, void *value); +int camera_v4l2_get_command(void *camera_handle, int64_t command, void **value); +int camera_v4l2_set_batch_command(void *camera_handle, camera_batch_command_control_s *batch_command, int64_t *error_command); + +#endif /* __HAL_CAMERA_V4L2_PRIVATE_H__ */ diff --git a/src/tizen_camera_v4l2_private.h b/src/tizen_camera_v4l2_private.h deleted file mode 100644 index 035316b..0000000 --- a/src/tizen_camera_v4l2_private.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * tizen_camera_private.c - * - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef __TIZEN_CAMERA_PRIVATE_H__ -#define __TIZEN_CAMERA_PRIVATE_H__ - -#include -#include -#include -#include - -#define CAMERA_HAL_INITIAL_INDEX -1 -#define CAMERA_HAL_INITIAL_FD -1 -#define MESSAGE_CALLBACK_MAX 10 -#define BUFFER_MAX 4 -#define V4L2_PLANES_MAX 4 - -typedef struct _camera_hal_handle { - /* tbm */ - tbm_bufmgr bufmgr; - - /* device */ - gint32 device_index; - gint32 device_fd; - - /* buffer */ - guint32 buffer_dequeued_count; - GThread *buffer_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; - - /* preview */ - camera_format_t preview_format; - camera_preview_frame_cb preview_cb; - gpointer preview_cb_data; - - /* capture */ - 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; - - /* 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; - - /* etc */ - GMutex lock; - camera_state_t state; -} camera_hal_handle; - -#endif /* __TIZEN_CAMERA_PRIVATE_H__ */ -- 2.7.4 From 87fde1b443fb19531c0ec84ea01cb21cd0f8f15b Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Tue, 20 Apr 2021 20:00:27 +0900 Subject: [PATCH 08/16] Change install path for license file [Version] 0.1.0-1 [Issue Type] Packaging Change-Id: I6dd76d0b98094aa523e6a05f59a190b63aaec13f Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index fa0d652..aa01d0f 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,7 +1,7 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 Version: 0.1.0 -Release: 0 +Release: 1 Group: Multimedia/Libraries License: Apache-2.0 Source0: %{name}-%{version}.tar.gz @@ -28,6 +28,8 @@ make %{?jobs:-j%jobs} %install %make_install +mkdir -p %{buildroot}%{_hal_licensedir}/%{name} +cp LICENSE.APLv2 %{buildroot}%{_hal_licensedir}/%{name} %post @@ -37,7 +39,7 @@ make %{?jobs:-j%jobs} %files %manifest %{name}.manifest -%license LICENSE.APLv2 +%{_hal_licensedir}/%{name}/* %defattr(-,root,root,-) %{_hal_libdir}/*.so -- 2.7.4 From caa7d9bbfcde4101cf4091fe1ffc5be3b6494331 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Tue, 27 Apr 2021 21:50:36 +0900 Subject: [PATCH 09/16] Add extra preview for test - It could be enabled with mmfw_camcorder.ini : SupportExtraPreview in [VideoInput] [Version] 0.1.1 [Issue Type] New feature Change-Id: Id0ee278c043b8fb7b099a789554945bbac0b7d51 Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 4 +-- src/hal_camera_v4l2.c | 75 ++++++++++++++++++++++++++++++++++++++++++ src/hal_camera_v4l2_private.h | 3 ++ 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index aa01d0f..f52c565 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,7 +1,7 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.1.0 -Release: 1 +Version: 0.1.1 +Release: 0 Group: Multimedia/Libraries License: Apache-2.0 Source0: %{name}-%{version}.tar.gz diff --git a/src/hal_camera_v4l2.c b/src/hal_camera_v4l2.c index e82d995..6738f85 100644 --- a/src/hal_camera_v4l2.c +++ b/src/hal_camera_v4l2.c @@ -952,6 +952,17 @@ static void *__camera_buffer_handler_func(gpointer data) camera_v4l2_release_preview_buffer((void *)handle, index); } + g_mutex_lock(&handle->extra_preview_lock); + + if (handle->extra_preview_cb) { + handle->extra_preview_cb(&handle->camera_buffers[index], NULL, 0, handle->extra_preview_cb_data); + handle->extra_preview_cb(&handle->camera_buffers[index], NULL, 1, handle->extra_preview_cb_data); + handle->extra_preview_cb(&handle->camera_buffers[index], NULL, 2, handle->extra_preview_cb_data); + handle->extra_preview_cb(&handle->camera_buffers[index], NULL, 3, handle->extra_preview_cb_data); + } + + g_mutex_unlock(&handle->extra_preview_lock); + /* check capture request flag */ if (handle->capture_request) { __camera_do_capture(handle); @@ -1064,6 +1075,7 @@ static void __camera_release_handle(hal_camera_handle *handle) g_mutex_clear(&handle->lock); g_mutex_clear(&handle->buffer_lock); g_mutex_clear(&handle->msg_cb_lock); + g_mutex_clear(&handle->extra_preview_lock); g_cond_clear(&handle->buffer_cond); g_cond_clear(&handle->msg_cb_cond); @@ -1111,6 +1123,7 @@ int camera_v4l2_init(void **camera_handle) g_mutex_init(&new_handle->lock); g_mutex_init(&new_handle->buffer_lock); g_mutex_init(&new_handle->msg_cb_lock); + g_mutex_init(&new_handle->extra_preview_lock); g_cond_init(&new_handle->buffer_cond); g_cond_init(&new_handle->msg_cb_cond); @@ -1876,6 +1889,65 @@ int camera_v4l2_stop_record(void *camera_handle) } +int camera_v4l2_set_extra_preview_frame_cb(void *camera_handle, hal_camera_extra_preview_frame_cb callback, void *user_data) +{ + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; + + if (!handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + g_mutex_lock(&handle->extra_preview_lock); + + handle->extra_preview_cb = callback; + handle->extra_preview_cb_data = user_data; + + g_mutex_unlock(&handle->extra_preview_lock); + + LOGI("done"); + + return CAMERA_ERROR_NONE; +} + + +int camera_v4l2_unset_extra_preview_frame_cb(void *camera_handle) +{ + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; + + if (!handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + g_mutex_lock(&handle->extra_preview_lock); + + handle->extra_preview_cb = NULL; + handle->extra_preview_cb_data = NULL; + + g_mutex_unlock(&handle->extra_preview_lock); + + LOGI("done"); + + return CAMERA_ERROR_NONE; +} + + +int camera_v4l2_release_extra_preview_buffer(void *camera_handle, int stream_id, int buffer_index) +{ + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; + + if (!handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGI("done - stream_id[%d], index[%d]", stream_id, buffer_index); + + return CAMERA_ERROR_NONE; +} + + int camera_v4l2_set_command(void *camera_handle, int64_t command, void *value) { int ret = CAMERA_ERROR_NONE; @@ -2104,6 +2176,9 @@ static int camera_v4l2_backend_init(void **data) funcs->set_command = camera_v4l2_set_command; funcs->get_command = camera_v4l2_get_command; funcs->set_batch_command = camera_v4l2_set_batch_command; + funcs->set_extra_preview_frame_cb = camera_v4l2_set_extra_preview_frame_cb; + funcs->unset_extra_preview_frame_cb = camera_v4l2_unset_extra_preview_frame_cb; + funcs->release_extra_preview_buffer = camera_v4l2_release_extra_preview_buffer; *data = (void *)funcs; diff --git a/src/hal_camera_v4l2_private.h b/src/hal_camera_v4l2_private.h index b6eb18a..d4e6397 100644 --- a/src/hal_camera_v4l2_private.h +++ b/src/hal_camera_v4l2_private.h @@ -54,6 +54,9 @@ typedef struct _camera_hal_handle { camera_format_s preview_format; hal_camera_preview_frame_cb preview_cb; gpointer preview_cb_data; + hal_camera_extra_preview_frame_cb extra_preview_cb; + gpointer extra_preview_cb_data; + GMutex extra_preview_lock; /* capture */ hal_camera_capture_cb capture_cb; -- 2.7.4 From 4eb9589845e1bdfaa979c51c1b07058af1e6ddca Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Thu, 13 May 2021 20:08:21 +0900 Subject: [PATCH 10/16] Support new command and camera_v4l2_set_batch_command() - Command list : CAMERA_COMMAND_FOCUS_MODE : CAMERA_COMMAND_FOCUS_RANGE : CAMERA_COMMAND_FOCUS_LEVEL [Version] 0.1.2 [Issue Type] New feature Change-Id: I521fe0ba81c60d341ecac70881d3bb94484b413e Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/hal_camera_v4l2.c | 167 +++++++++++++++++++++++++++++++++-------- src/hal_camera_v4l2_private.h | 10 +++ 3 files changed, 145 insertions(+), 34 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index f52c565..5550a84 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.1.1 +Version: 0.1.2 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/hal_camera_v4l2.c b/src/hal_camera_v4l2.c index 6738f85..8fbfb20 100644 --- a/src/hal_camera_v4l2.c +++ b/src/hal_camera_v4l2.c @@ -1948,13 +1948,11 @@ int camera_v4l2_release_extra_preview_buffer(void *camera_handle, int stream_id, } -int camera_v4l2_set_command(void *camera_handle, int64_t command, void *value) +static int __set_command(hal_camera_handle *handle, int64_t command, void *value) { - int ret = CAMERA_ERROR_NONE; int cid = 0; int ctrl_ret = 0; int set_value = 0; - hal_camera_handle *handle = (hal_camera_handle *)camera_handle; if (!handle || !value) { LOGE("NULL param %p %p", handle, value); @@ -1963,12 +1961,9 @@ int camera_v4l2_set_command(void *camera_handle, int64_t command, void *value) set_value = *(int *)value; - g_mutex_lock(&handle->lock); - if (handle->state < CAMERA_STATE_OPENED) { LOGE("invalid state %d", handle->state); - ret = CAMERA_ERROR_INVALID_STATE; - goto _SET_COMMAND_DONE; + return CAMERA_ERROR_INVALID_STATE; } LOGD("set command %"PRIx64" - state %d", command, handle->state); @@ -1989,9 +1984,9 @@ int camera_v4l2_set_command(void *camera_handle, int64_t command, void *value) case CAMERA_COMMAND_PTZ_TYPE: if (set_value != CAMERA_PTZ_TYPE_ELECTRONIC) { LOGE("not supported PTZ type %d", set_value); - ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED; + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } - goto _SET_COMMAND_DONE; + return CAMERA_ERROR_NONE; case CAMERA_COMMAND_PAN: cid = V4L2_CID_PAN_ABSOLUTE; break; @@ -2001,21 +1996,32 @@ int camera_v4l2_set_command(void *camera_handle, int64_t command, void *value) case CAMERA_COMMAND_FLIP: if (set_value != CAMERA_FLIP_NONE) { LOGE("NOT_SUPPORTED flip %d", set_value); - ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED; + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } - goto _SET_COMMAND_DONE; + return CAMERA_ERROR_NONE; case CAMERA_COMMAND_CAPTURE_COUNT: handle->capture_count = set_value; LOGI("capture count %u", handle->capture_count); - goto _SET_COMMAND_DONE; + return CAMERA_ERROR_NONE; case CAMERA_COMMAND_CAPTURE_INTERVAL: handle->capture_interval_ms = set_value; LOGI("capture interval %u ms", handle->capture_interval_ms); - goto _SET_COMMAND_DONE; + return CAMERA_ERROR_NONE; + case CAMERA_COMMAND_FOCUS_MODE: + LOGI("set focus mode [old:%d -> new:%d]", handle->focus_mode, set_value); + handle->focus_mode = set_value; + return CAMERA_ERROR_NONE; + case CAMERA_COMMAND_FOCUS_RANGE: + LOGI("set focus range [old:%d -> new:%d]", handle->focus_range, set_value); + handle->focus_range = set_value; + return CAMERA_ERROR_NONE; + case CAMERA_COMMAND_FOCUS_LEVEL: + LOGI("set focus level [old:%d -> new:%d]", handle->focus_level, set_value); + handle->focus_level = set_value; + return CAMERA_ERROR_NONE; default: LOGE("NOT_SUPPORTED command %"PRIx64, command); - ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED; - goto _SET_COMMAND_DONE; + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } ctrl_ret = __camera_v4l2_s_ctrl(handle->device_fd, cid, set_value); @@ -2024,28 +2030,35 @@ int camera_v4l2_set_command(void *camera_handle, int64_t command, void *value) case EACCES: case EPERM: LOGE("Permission denied %d", errno); - ret = CAMERA_ERROR_PERMISSION_DENIED; - break; + return CAMERA_ERROR_PERMISSION_DENIED; case EINVAL: LOGE("Invalid argument"); - ret = CAMERA_ERROR_INVALID_PARAMETER; - break; + return CAMERA_ERROR_INVALID_PARAMETER; case EBUSY: LOGE("Device busy"); - ret = CAMERA_ERROR_DEVICE_BUSY; - break; + return CAMERA_ERROR_DEVICE_BUSY; case ENOTSUP: LOGE("Not supported"); - ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED; - break; + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; default: LOGE("Unknown errro %d", errno); - ret = CAMERA_ERROR_INTERNAL; - break; + return CAMERA_ERROR_INTERNAL; } } -_SET_COMMAND_DONE: + return CAMERA_ERROR_NONE; +} + + +int camera_v4l2_set_command(void *camera_handle, int64_t command, void *value) +{ + int ret = CAMERA_ERROR_NONE; + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; + + g_mutex_lock(&handle->lock); + + ret = __set_command(handle, command, value); + g_mutex_unlock(&handle->lock); return ret; @@ -2066,7 +2079,7 @@ int camera_v4l2_get_command(void *camera_handle, int64_t command, void **value) g_mutex_lock(&handle->lock); - LOGD("get command %"PRId64" - state %d", command, handle->state); + LOGD("get command %"PRIx64" - state %d", command, handle->state); switch (command) { case CAMERA_COMMAND_BRIGHTNESS: @@ -2081,13 +2094,25 @@ int camera_v4l2_get_command(void *camera_handle, int64_t command, void **value) case CAMERA_COMMAND_SHARPNESS: cid = V4L2_CID_SHARPNESS; break; + case CAMERA_COMMAND_FOCUS_MODE: + **(int **)value = handle->focus_mode; + LOGI("get focus mode %d", **(int **)value); + goto _GET_COMMAND_DONE; + case CAMERA_COMMAND_FOCUS_RANGE: + **(int **)value = handle->focus_range; + LOGI("get focus range %d", **(int **)value); + goto _GET_COMMAND_DONE; + case CAMERA_COMMAND_FOCUS_LEVEL: + **(int **)value = handle->focus_level; + LOGI("get focus level %d", **(int **)value); + goto _GET_COMMAND_DONE; default: - LOGE("NOT_SUPPORTED %"PRId64, command); + LOGE("NOT_SUPPORTED %"PRIx64, command); g_mutex_unlock(&handle->lock); return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } - ctrl_ret = __camera_v4l2_g_ctrl(handle->device_fd, cid, (int *)value); + ctrl_ret = __camera_v4l2_g_ctrl(handle->device_fd, cid, (int *)*value); if (ctrl_ret < 0) { switch (errno) { case EACCES: @@ -2114,15 +2139,79 @@ int camera_v4l2_get_command(void *camera_handle, int64_t command, void **value) } } +_GET_COMMAND_DONE: g_mutex_unlock(&handle->lock); return ret; } +static void __dump_batch_command(camera_batch_command_control_s *batch_command) +{ + if (!batch_command) { + LOGE("NULL batch command"); + return; + } + + LOGI("[WHITE_BALANCE] %d", batch_command->white_balance); + LOGI("[ISO] %d", batch_command->iso); + LOGI("[CONTRAST] %d", batch_command->contrast); + LOGI("[HUE] %d", batch_command->hue); + LOGI("[SATURATION] %d", batch_command->saturation); + LOGI("[SHARPNESS] %d", batch_command->sharpness); + LOGI("[BRIGHTNESS] %d", batch_command->brightness); + LOGI("[EFFECT] %d", batch_command->effect); + LOGI("[SCENE_MODE] %d", batch_command->scene_mode); + LOGI("[EXPOSURE_MODE] %d", batch_command->exposure_mode); + LOGI("[EXPOSURE] %d", batch_command->exposure); + LOGI("[ROTATION] %d", batch_command->rotation); + LOGI("[FLIP] %d", batch_command->flip); + LOGI("[FOCUS_MODE] %d", batch_command->focus_mode); + LOGI("[FOCUS_RANGE] %d", batch_command->focus_range); + LOGI("[FOCUS_AREA] %d,%d,%dx%d", batch_command->focus_area.x, batch_command->focus_area.y, + batch_command->focus_area.width, batch_command->focus_area.height); + LOGI("[FOCUS_LEVEL] %d", batch_command->focus_level); + LOGI("[SHOT_MODE] %d", batch_command->shot_mode); + LOGI("[ANTI_SHAKE] %d", batch_command->anti_shake); + LOGI("[DIGITAL_ZOOM] %d", batch_command->digital_zoom); + LOGI("[OPTICAL_ZOOM] %d", batch_command->optical_zoom); + LOGI("[RECORDING_HINT] %d", batch_command->recording_hint); + LOGI("[WDR] %d", batch_command->wdr); + LOGI("[SHUTTER_SPEED] %d/%d", batch_command->shutter_speed.numerator, batch_command->shutter_speed.denominator); + LOGI("[FLASH_MODE] %d", batch_command->flash_mode); + LOGI("[FLASH_BRIGHTNESS] %d", batch_command->flash_brightness); + LOGI("[FACE_DETECTION] %d", batch_command->face_detection); + LOGI("[PTZ_TYPE] %d", batch_command->ptz_type); + LOGI("[PAN] %d", batch_command->pan); + LOGI("[TILT] %d", batch_command->tilt); + LOGI("[BITRATE] %d", batch_command->bitrate); + LOGI("[GOP_INTERVAL] %d", batch_command->gop_interval); + LOGI("[CAPTURE_COUNT] %d", batch_command->capture_count); + LOGI("[CAPTURE_INTERVAL] %d", batch_command->capture_interval); +} + + int camera_v4l2_set_batch_command(void *camera_handle, camera_batch_command_control_s *batch_command, int64_t *error_command) { + int ret = CAMERA_ERROR_NONE; + int i = 0; + int support_count = 0; hal_camera_handle *handle = (hal_camera_handle *)camera_handle; + set_batch_table_s set_table[] = { + {CAMERA_COMMAND_BRIGHTNESS, batch_command ? (void *)&batch_command->brightness : NULL}, + {CAMERA_COMMAND_CONTRAST, batch_command ? (void *)&batch_command->contrast : NULL}, + {CAMERA_COMMAND_SATURATION, batch_command ? (void *)&batch_command->saturation : NULL}, + {CAMERA_COMMAND_SHARPNESS, batch_command ? (void *)&batch_command->sharpness : NULL}, + {CAMERA_COMMAND_PTZ_TYPE, batch_command ? (void *)&batch_command->ptz_type : NULL}, + {CAMERA_COMMAND_PAN, batch_command ? (void *)&batch_command->pan : NULL}, + {CAMERA_COMMAND_TILT, batch_command ? (void *)&batch_command->tilt : NULL}, + {CAMERA_COMMAND_FLIP, batch_command ? (void *)&batch_command->flip : NULL}, + {CAMERA_COMMAND_CAPTURE_COUNT, batch_command ? (void *)&batch_command->capture_count : NULL}, + {CAMERA_COMMAND_CAPTURE_INTERVAL, batch_command ? (void *)&batch_command->capture_interval : NULL}, + {CAMERA_COMMAND_FOCUS_MODE, batch_command ? (void *)&batch_command->focus_mode : NULL}, + {CAMERA_COMMAND_FOCUS_RANGE, batch_command ? (void *)&batch_command->focus_range : NULL}, + {CAMERA_COMMAND_FOCUS_LEVEL, batch_command ? (void *)&batch_command->focus_level : NULL} + }; if (!handle || !batch_command) { LOGE("NULL param %p %p", handle, batch_command); @@ -2131,14 +2220,26 @@ int camera_v4l2_set_batch_command(void *camera_handle, camera_batch_command_cont g_mutex_lock(&handle->lock); - LOGD("set batch command - flag %"PRIx64", state %d", - batch_command->command_set_flag, handle->state); + support_count = sizeof(set_table) / sizeof(set_batch_table_s); + + LOGD("set batch command - support count %d", support_count); + + __dump_batch_command(batch_command); + + for (i = 0 ; i < support_count ; i++) { + if (!(batch_command->command_set_flag & set_table[i].command)) + continue; - /* TODO: to be implemented */ + ret = __set_command(handle, set_table[i].command, set_table[i].value); + if (ret != CAMERA_ERROR_NONE) { + LOGE("failed command %"PRIx64", ret 0x%x", set_table[i].command, ret); + break; + } + } g_mutex_unlock(&handle->lock); - return CAMERA_ERROR_NONE; + return ret; } diff --git a/src/hal_camera_v4l2_private.h b/src/hal_camera_v4l2_private.h index d4e6397..8c0761d 100644 --- a/src/hal_camera_v4l2_private.h +++ b/src/hal_camera_v4l2_private.h @@ -32,6 +32,11 @@ #define BUFFER_MAX 4 #define V4L2_PLANES_MAX 4 +typedef struct _set_batch_table_s { + int64_t command; + void *value; +} set_batch_table_s; + typedef struct _camera_hal_handle { /* tbm */ tbm_bufmgr bufmgr; @@ -76,6 +81,11 @@ typedef struct _camera_hal_handle { GMutex msg_cb_lock; GCond msg_cb_cond; + /* focus */ + gint32 focus_mode; + gint32 focus_range; + gint32 focus_level; + /* etc */ GMutex lock; camera_state_e state; -- 2.7.4 From 9fa783c5f532e333fd1c6197d7ba56a28b33e9d8 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Mon, 14 Jun 2021 08:34:00 +0900 Subject: [PATCH 11/16] Fix coverity - Unintentional integer overlfow [Version] 0.1.3 [Issue Type] Coverity Change-Id: I9ead8ed3962d566b615c1019326dc2373160ded0 Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/hal_camera_v4l2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index 5550a84..bde3403 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.1.2 +Version: 0.1.3 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/hal_camera_v4l2.c b/src/hal_camera_v4l2.c index 8fbfb20..92a3c19 100644 --- a/src/hal_camera_v4l2.c +++ b/src/hal_camera_v4l2.c @@ -790,7 +790,7 @@ static void __camera_do_capture(hal_camera_handle *handle) LOGD("start"); if (handle->capture_count > 1) - interval_us = handle->capture_interval_ms * 1000; + interval_us = (gint64)handle->capture_interval_ms * 1000; /* restart stream for capture */ if (handle->capture_restart_stream) { -- 2.7.4 From 19aa28f1098ef465594d9e674449df6944c6a5f7 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Thu, 17 Jun 2021 14:27:59 +0900 Subject: [PATCH 12/16] Support extra preview stream format functions for test [Version] 0.1.4 [Issue Type] New feature Change-Id: I63d3d68a734e8516d11c2714734f879f8b002ca9 Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/hal_camera_v4l2.c | 52 ++++++++++++++++++++++++++++++++++++++++++ src/hal_camera_v4l2_private.h | 2 ++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index bde3403..67deda2 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.1.3 +Version: 0.1.4 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/hal_camera_v4l2.c b/src/hal_camera_v4l2.c index 92a3c19..54f6a1b 100644 --- a/src/hal_camera_v4l2.c +++ b/src/hal_camera_v4l2.c @@ -1948,6 +1948,56 @@ int camera_v4l2_release_extra_preview_buffer(void *camera_handle, int stream_id, } +int camera_v4l2_set_extra_preview_stream_format(void *camera_handle, int stream_id, camera_format_s *format) +{ + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; + + if (!handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (stream_id < 0 || stream_id >= EXTRA_PREVIEW_STREAM_MAX) { + LOGE("invalid stream_id[%d]", stream_id); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGI("stream_id[%d], [%d,%dx%d,%d]", + stream_id, format->stream_format, + format->stream_resolution.width, format->stream_resolution.height, + format->stream_fps); + + memcpy(&handle->extra_preview_format[stream_id], format, sizeof(camera_format_s)); + + return CAMERA_ERROR_NONE; +} + + +int camera_v4l2_get_extra_preview_stream_format(void *camera_handle, int stream_id, camera_format_s *format) +{ + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; + + if (!handle || !format) { + LOGE("NULL param[%p,%p]", handle, format); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (stream_id < 0 || stream_id >= EXTRA_PREVIEW_STREAM_MAX) { + LOGE("invalid stream_id[%d]", stream_id); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + memcpy(format, &handle->extra_preview_format[stream_id], sizeof(camera_format_s)); + + LOGI("stream_id[%d], [%d,%dx%d,%d]", + stream_id, format->stream_format, + format->stream_resolution.width, format->stream_resolution.height, + format->stream_fps); + + return CAMERA_ERROR_NONE; +} + + static int __set_command(hal_camera_handle *handle, int64_t command, void *value) { int cid = 0; @@ -2280,6 +2330,8 @@ static int camera_v4l2_backend_init(void **data) funcs->set_extra_preview_frame_cb = camera_v4l2_set_extra_preview_frame_cb; funcs->unset_extra_preview_frame_cb = camera_v4l2_unset_extra_preview_frame_cb; funcs->release_extra_preview_buffer = camera_v4l2_release_extra_preview_buffer; + funcs->set_extra_preview_stream_format = camera_v4l2_set_extra_preview_stream_format; + funcs->get_extra_preview_stream_format = camera_v4l2_get_extra_preview_stream_format; *data = (void *)funcs; diff --git a/src/hal_camera_v4l2_private.h b/src/hal_camera_v4l2_private.h index 8c0761d..3e7f5fc 100644 --- a/src/hal_camera_v4l2_private.h +++ b/src/hal_camera_v4l2_private.h @@ -31,6 +31,7 @@ #define MESSAGE_CALLBACK_MAX 10 #define BUFFER_MAX 4 #define V4L2_PLANES_MAX 4 +#define EXTRA_PREVIEW_STREAM_MAX 10 typedef struct _set_batch_table_s { int64_t command; @@ -62,6 +63,7 @@ typedef struct _camera_hal_handle { hal_camera_extra_preview_frame_cb extra_preview_cb; gpointer extra_preview_cb_data; GMutex extra_preview_lock; + camera_format_s extra_preview_format[EXTRA_PREVIEW_STREAM_MAX]; /* capture */ hal_camera_capture_cb capture_cb; -- 2.7.4 From 0901fee0d8670248a74db4b9368ce7d1182b2087 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Tue, 24 Aug 2021 18:31:45 +0900 Subject: [PATCH 13/16] Use libv4l2 to emulate unsupported formats [Version] 0.1.5 [Issue Type] New feature Change-Id: I328e3cc2e8d178b44829b5a9c650ea47be5e09d4 Signed-off-by: Jeongmo Yang --- configure.ac | 15 +++++++++ packaging/camera-hal-v4l2.spec | 14 ++++++-- src/Makefile.am | 5 +++ src/hal_camera_v4l2.c | 72 ++++++++++++++++++++++++++++++------------ src/hal_camera_v4l2_private.h | 12 +++++++ 5 files changed, 96 insertions(+), 22 deletions(-) diff --git a/configure.ac b/configure.ac index ef6f7fc..177c598 100644 --- a/configure.ac +++ b/configure.ac @@ -41,6 +41,21 @@ AC_SUBST(HAL_API_COMMON_CFLAGS) PKG_CHECK_MODULES(HAL_API_CAMERA, hal-api-camera) AC_SUBST(HAL_API_CAMERA_CFLAGS) +AC_ARG_ENABLE(libv4l2, AC_HELP_STRING([--enable-libv4l2], [enable libv4l2]), +[ + case "${enableval}" in + yes) HAVE_LIBV4L2=yes ;; + no) HAVE_LIBV4L2=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-libv4l2) ;; + esac +],[HAVE_LIBV4L2=no]) +if test "x$HAVE_LIBV4L2" = "xyes"; then +PKG_CHECK_MODULES(LIBV4L2, libv4l2) +AC_SUBST(LIBV4L2_CFLAGS) +AC_SUBST(LIBV4L2_LIBS) +fi +AM_CONDITIONAL([HAVE_LIBV4L2], [test "x$HAVE_LIBV4L2" = "xyes"]) + # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS([fcntl.h memory.h stdlib.h string.h sys/time.h unistd.h]) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index 67deda2..67170a2 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,8 @@ +%define enable_libv4l2 1 + Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.1.4 +Version: 0.1.5 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 @@ -12,6 +14,9 @@ BuildRequires: pkgconfig(libtbm) BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(hal-api-common) BuildRequires: pkgconfig(hal-api-camera) +%if 0%{?enable_libv4l2} +BuildRequires: pkgconfig(libv4l2) +%endif %description Tizen Camera Hal for V4L2. @@ -23,7 +28,12 @@ Tizen Camera Hal for V4L2. %build ./autogen.sh -%configure --disable-static --libdir=%{_hal_libdir} +%configure \ +%if 0%{?enable_libv4l2} + --enable-libv4l2\ +%endif + --disable-static\ + --libdir=%{_hal_libdir} make %{?jobs:-j%jobs} %install diff --git a/src/Makefile.am b/src/Makefile.am index 58cb115..f10e540 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,6 +19,11 @@ libhal_backend_camera_la_LIBADD = \ $(DLOG_LIBS) \ $(TBM_LIBS) +if HAVE_LIBV4L2 +libhal_backend_camera_la_CFLAGS += $(LIBV4L2_CFLAGS) -DHAVE_LIBV4L2 +libhal_backend_camera_la_LIBADD += $(LIBV4L2_LIBS) +endif + libhal_backend_camera_la_CFLAGS += -fdata-sections -ffunction-sections -Wl,--gc-sections libhal_backend_camera_la_LDFLAGS = -Wl,--gc-sections -avoid-version diff --git a/src/hal_camera_v4l2.c b/src/hal_camera_v4l2.c index 54f6a1b..a3f136a 100644 --- a/src/hal_camera_v4l2.c +++ b/src/hal_camera_v4l2.c @@ -126,7 +126,7 @@ static int __camera_v4l2_g_ctrl(int device_fd, int cid, int *value) ctrl.id = cid; - ret = ioctl(device_fd, VIDIOC_G_CTRL, &ctrl); + ret = v4l2_ioctl(device_fd, VIDIOC_G_CTRL, &ctrl); *value = ctrl.value; @@ -146,7 +146,7 @@ static int __camera_v4l2_s_ctrl(int device_fd, int cid, int value) ctrl.id = cid; ctrl.value = value; - ret = ioctl(device_fd, VIDIOC_S_CTRL, &ctrl); + ret = v4l2_ioctl(device_fd, VIDIOC_S_CTRL, &ctrl); LOGD("S_CTRL id 0x%x, value %d, ret %d", cid, value, ret); @@ -161,7 +161,7 @@ static int __camera_v4l2_stream(int device_fd, int type, gboolean onoff) return CAMERA_ERROR_INVALID_PARAMETER; } - if (ioctl(device_fd, onoff ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, &type) < 0) { + if (v4l2_ioctl(device_fd, onoff ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, &type) < 0) { LOGE("stream %d failed. [t:%d] errno %d", onoff, type, errno); return CAMERA_ERROR_INTERNAL; } @@ -192,7 +192,7 @@ static int __camera_v4l2_reqbufs(int device_fd, int type, int memory, uint32_t c v4l2_reqbuf.memory = memory; v4l2_reqbuf.count = count; - if (ioctl(device_fd, VIDIOC_REQBUFS, &v4l2_reqbuf) < 0) { + if (v4l2_ioctl(device_fd, VIDIOC_REQBUFS, &v4l2_reqbuf) < 0) { LOGE("REQBUFS[count %d] failed. errno %d", count, errno); return CAMERA_ERROR_INTERNAL; } @@ -226,7 +226,7 @@ static int __camera_v4l2_qbuf(int device_fd, int type, int memory, int index) v4l2_buf.length = 460800; v4l2_buf.bytesused = 460800; - if (ioctl(device_fd, VIDIOC_QBUF, &v4l2_buf) < 0) { + if (v4l2_ioctl(device_fd, VIDIOC_QBUF, &v4l2_buf) < 0) { LOGE("qbuf failed. [i: %d, t: %d, m: %d] errno %d", index, type, memory, errno); return CAMERA_ERROR_INTERNAL; @@ -261,7 +261,7 @@ static int __camera_v4l2_dqbuf(int device_fd, int type, int memory, int *index) v4l2_buf.memory = memory; v4l2_buf.m.planes = v4l2_planes; - ret = ioctl(device_fd, VIDIOC_DQBUF, &v4l2_buf); + ret = v4l2_ioctl(device_fd, VIDIOC_DQBUF, &v4l2_buf); if (ret < 0) { if (errno != EIO) { LOGE("dqbuf failed. [t: %d, m: %d] errno %d", @@ -400,12 +400,14 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi v4l2_format.index = i; v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (ioctl(device_fd, VIDIOC_ENUM_FMT, &v4l2_format) < 0) { + if (v4l2_ioctl(device_fd, VIDIOC_ENUM_FMT, &v4l2_format) < 0) { LOGW("\tformat : end of enumeration"); break; } - LOGD("\tformat[%d] "FOURCC_FORMAT, i, FOURCC_CONVERT(v4l2_format.pixelformat)); + LOGD("\tformat[%d] "FOURCC_FORMAT" (emulated:%d)", + i, FOURCC_CONVERT(v4l2_format.pixelformat), + ((v4l2_format.flags & V4L2_FMT_FLAG_EMULATED) ? 1 : 0)); if (__camera_get_format(v4l2_format.pixelformat, &camera_format) != CAMERA_ERROR_NONE) continue; @@ -420,7 +422,7 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi v4l2_frame.index = j; v4l2_frame.pixel_format = v4l2_format.pixelformat; - if (ioctl(device_fd, VIDIOC_ENUM_FRAMESIZES, &v4l2_frame) < 0) { + if (v4l2_ioctl(device_fd, VIDIOC_ENUM_FRAMESIZES, &v4l2_frame) < 0) { LOGW("\t\tframe : end of enumeration "); break; } @@ -489,6 +491,9 @@ static int __camera_get_device_info_list(void) int ret = 0; int device_count = 0; int device_fd = CAMERA_HAL_INITIAL_FD; +#ifdef HAVE_LIBV4L2 + int libv4l2_fd = CAMERA_HAL_INITIAL_FD; +#endif /* HAVE_LIBV4L2 */ glob_t glob_buf; struct v4l2_capability v4l2_cap; camera_device_info_list_s *device_info_list = NULL; @@ -543,11 +548,20 @@ static int __camera_get_device_info_list(void) continue; } +#ifdef HAVE_LIBV4L2 + libv4l2_fd = v4l2_fd_open(device_fd, V4L2_ENABLE_ENUM_FMT_EMULATION); + + LOGI("device_fd[%d], libv4l2_fd[%d]", device_fd, libv4l2_fd); + + if (libv4l2_fd != CAMERA_HAL_INITIAL_FD) + device_fd = libv4l2_fd; +#endif /* HAVE_LIBV4L2 */ + memset(&v4l2_cap, 0x0, sizeof(struct v4l2_capability)); - if (ioctl(device_fd, VIDIOC_QUERYCAP, &v4l2_cap) < 0) { + if (v4l2_ioctl(device_fd, VIDIOC_QUERYCAP, &v4l2_cap) < 0) { LOGE("querycap failed. errno %d", errno); - close(device_fd); + v4l2_close(device_fd); continue; } @@ -559,14 +573,14 @@ static int __camera_get_device_info_list(void) if (!(g_device_caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)) || (g_device_caps & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE))) { LOGW("[%s] is not a capture device 0x%x", glob_buf.gl_pathv[i], g_device_caps); - close(device_fd); + v4l2_close(device_fd); continue; } ret = __camera_get_device_info(device_count, device_fd, &device_info_list->device_info[device_count], glob_buf.gl_pathv[i]); - close(device_fd); + v4l2_close(device_fd); if (ret == CAMERA_ERROR_NONE) device_count++; @@ -611,7 +625,7 @@ static int __camera_stop_stream(hal_camera_handle *handle, uint32_t buffer_count if (handle->camera_buffers[i].planes[0].data != NULL) { LOGW("munmap %p", handle->camera_buffers[i].planes[0].data); - munmap(handle->camera_buffers[i].planes[0].data, handle->camera_buffers[i].planes[0].size); + v4l2_munmap(handle->camera_buffers[i].planes[0].data, handle->camera_buffers[i].planes[0].size); handle->camera_buffers[i].planes[0].data = 0; handle->camera_buffers[i].planes[0].size = 0; @@ -670,7 +684,7 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_ v4l2_fmt.fmt.pix.bytesperline = resolution->width; } - if (ioctl(handle->device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) { + if (v4l2_ioctl(handle->device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) { LOGE("S_FMT failed. errno %d", errno); return CAMERA_ERROR_INTERNAL; } @@ -692,7 +706,7 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_ v4l2_parm.type = handle->buffer_type; - if (ioctl(handle->device_fd, VIDIOC_G_PARM, &v4l2_parm) < 0) { + if (v4l2_ioctl(handle->device_fd, VIDIOC_G_PARM, &v4l2_parm) < 0) { LOGE("G_PARM failed. errno %d", errno); return CAMERA_ERROR_INTERNAL; } @@ -701,7 +715,7 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_ 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) { + if (v4l2_ioctl(handle->device_fd, VIDIOC_S_PARM, &v4l2_parm) < 0) { LOGE("S_PARM failed. errno %d", errno); return CAMERA_ERROR_INTERNAL; } @@ -727,7 +741,7 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_ v4l2_buf.m.planes = v4l2_planes; v4l2_buf.length = plane_num; - if (ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) { + if (v4l2_ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) { LOGE("[%d] query buf failed. errno %d", i, errno); goto _START_STREAM_FAILED; } @@ -741,7 +755,7 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_ buffer->total_size = v4l2_buf.length; buffer->num_planes = plane_num; buffer->planes[0].size = v4l2_buf.length; - buffer->planes[0].data = mmap(0, + buffer->planes[0].data = v4l2_mmap(0, v4l2_buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, @@ -1148,6 +1162,12 @@ int camera_v4l2_init(void **camera_handle) goto _INIT_ERROR; } +#ifdef HAVE_LIBV4L2 + LOGI("libv4l2 ENABLED"); +#else /* HAVE_LIBV4L2 */ + LOGI("libv4l2 DISABLED"); +#endif /* HAVE_LIBV4L2 */ + *camera_handle = new_handle; LOGD("camera HAL handle %p", new_handle); @@ -1211,6 +1231,9 @@ int camera_v4l2_open_device(void *camera_handle, int device_index) { int ret = CAMERA_ERROR_NONE; int device_fd = CAMERA_HAL_INITIAL_FD; +#ifdef HAVE_LIBV4L2 + int libv4l2_fd = CAMERA_HAL_INITIAL_FD; +#endif /* HAVE_LIBV4L2 */ char *node_path = NULL; hal_camera_handle *handle = (hal_camera_handle *)camera_handle; @@ -1270,6 +1293,15 @@ int camera_v4l2_open_device(void *camera_handle, int device_index) else handle->buffer_type = V4L2_CAP_VIDEO_CAPTURE; +#ifdef HAVE_LIBV4L2 + libv4l2_fd = v4l2_fd_open(device_fd, V4L2_ENABLE_ENUM_FMT_EMULATION); + + LOGI("device_fd[%d], libv4l2_fd[%d]", device_fd, libv4l2_fd); + + if (libv4l2_fd != CAMERA_HAL_INITIAL_FD) + device_fd = libv4l2_fd; +#endif /* HAVE_LIBV4L2 */ + handle->state = CAMERA_STATE_OPENED; handle->device_index = device_index; handle->device_fd = device_fd; @@ -1311,7 +1343,7 @@ int camera_v4l2_close_device(void *camera_handle) if (handle->device_fd >= 0) { LOGD("close fd %d", handle->device_fd); - close(handle->device_fd); + v4l2_close(handle->device_fd); handle->device_fd = CAMERA_HAL_INITIAL_FD; } else { LOGW("invalid fd %d", handle->device_fd); diff --git a/src/hal_camera_v4l2_private.h b/src/hal_camera_v4l2_private.h index 3e7f5fc..65478d9 100644 --- a/src/hal_camera_v4l2_private.h +++ b/src/hal_camera_v4l2_private.h @@ -26,6 +26,18 @@ #include #include +#ifdef HAVE_LIBV4L2 +#include +#else +#define v4l2_fd_open(fd, flags) (fd) +#define v4l2_close close +#define v4l2_dup dup +#define v4l2_ioctl ioctl +#define v4l2_read read +#define v4l2_mmap mmap +#define v4l2_munmap munmap +#endif /* ENABLE_LIBV4L2 */ + #define CAMERA_HAL_INITIAL_INDEX -1 #define CAMERA_HAL_INITIAL_FD -1 #define MESSAGE_CALLBACK_MAX 10 -- 2.7.4 From a2e6e9d16334eef74702edf2034e68326108db13 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Wed, 1 Sep 2021 21:11:55 +0900 Subject: [PATCH 14/16] Support extra preview bitrate functions for test [Version] 0.1.6 [Issue Type] New feature Change-Id: I0bb662a4e7aa7e982578c20d9fffb0f4d0a92cb3 Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/hal_camera_v4l2.c | 46 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index 67170a2..f8647e5 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -2,7 +2,7 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.1.5 +Version: 0.1.6 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/hal_camera_v4l2.c b/src/hal_camera_v4l2.c index a3f136a..31536b7 100644 --- a/src/hal_camera_v4l2.c +++ b/src/hal_camera_v4l2.c @@ -2030,6 +2030,50 @@ int camera_v4l2_get_extra_preview_stream_format(void *camera_handle, int stream_ } +int camera_v4l2_set_extra_preview_bitrate(void *camera_handle, int stream_id, int bitrate) +{ + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; + + if (!handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (stream_id < 0 || stream_id >= EXTRA_PREVIEW_STREAM_MAX) { + LOGE("invalid stream_id[%d]", stream_id); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGI("set bitrate[%d] for stream_id[%d]", bitrate, stream_id); + + handle->extra_preview_format[stream_id].stream_bitrate = (uint32_t)bitrate; + + return CAMERA_ERROR_NONE; +} + + +int camera_v4l2_get_extra_preview_bitrate(void *camera_handle, int stream_id, int *bitrate) +{ + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; + + if (!handle || !bitrate) { + LOGE("NULL param[%p,%p]", handle, bitrate); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (stream_id < 0 || stream_id >= EXTRA_PREVIEW_STREAM_MAX) { + LOGE("invalid stream_id[%d]", stream_id); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + *bitrate = (int)handle->extra_preview_format[stream_id].stream_bitrate; + + LOGI("get bitrate[%d] for stream_id[%d]", *bitrate, stream_id); + + return CAMERA_ERROR_NONE; +} + + static int __set_command(hal_camera_handle *handle, int64_t command, void *value) { int cid = 0; @@ -2364,6 +2408,8 @@ static int camera_v4l2_backend_init(void **data) funcs->release_extra_preview_buffer = camera_v4l2_release_extra_preview_buffer; funcs->set_extra_preview_stream_format = camera_v4l2_set_extra_preview_stream_format; funcs->get_extra_preview_stream_format = camera_v4l2_get_extra_preview_stream_format; + funcs->set_extra_preview_bitrate = camera_v4l2_set_extra_preview_bitrate; + funcs->get_extra_preview_bitrate = camera_v4l2_get_extra_preview_bitrate; *data = (void *)funcs; -- 2.7.4 From a8a6d23b36749158cb6d68c76488868b65793e4c Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Tue, 14 Sep 2021 17:13:38 +0900 Subject: [PATCH 15/16] Add fps list for device info [Version] 0.1.7 [Issue Type] Update Change-Id: Iee50529675eaec651b0fcd2284d689ec525523b9 Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/hal_camera_v4l2.c | 47 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index f8647e5..0bcd5f2 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -2,7 +2,7 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.1.6 +Version: 0.1.7 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/hal_camera_v4l2.c b/src/hal_camera_v4l2.c index 31536b7..3167f4f 100644 --- a/src/hal_camera_v4l2.c +++ b/src/hal_camera_v4l2.c @@ -313,6 +313,9 @@ static int __camera_get_format(guint32 fourcc, int *pixel_format) case V4L2_PIX_FMT_H264: *pixel_format = CAMERA_PIXEL_FORMAT_H264; break; + case V4L2_PIX_FMT_MJPEG: + *pixel_format = CAMERA_PIXEL_FORMAT_MJPEG; + break; default: LOGE("unknown fourcc "FOURCC_FORMAT, FOURCC_CONVERT(fourcc)); return CAMERA_ERROR_INTERNAL; @@ -365,6 +368,10 @@ static int __camera_get_fourcc_plane_num(int pixel_format, guint32 *fourcc, guin *fourcc = V4L2_PIX_FMT_H264; *plane_num = 1; break; + case CAMERA_PIXEL_FORMAT_MJPEG: + *fourcc = V4L2_PIX_FMT_MJPEG; + *plane_num = 1; + break; default: LOGE("unknown format %d", pixel_format); return CAMERA_ERROR_INTERNAL; @@ -377,6 +384,39 @@ static int __camera_get_fourcc_plane_num(int pixel_format, guint32 *fourcc, guin } +static void __camera_get_fps_list(int device_fd, guint32 pixel_format, int width, int height, camera_fps_list_s *fps_list) +{ + struct v4l2_frmivalenum ival; + + if (device_fd < 0 || !fps_list) { + LOGE("invalid param %d %p", device_fd, fps_list); + return; + } + + ival.index = 0; + ival.pixel_format = pixel_format; + ival.width = width; + ival.height = height; + + if (v4l2_ioctl(device_fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0) { + LOGE("VIDIOC_ENUM_FRAMEINTERVALS failed[%d]", errno); + return; + } + + if (ival.type != V4L2_FRMIVAL_TYPE_DISCRETE) { + LOGE("NOT V4L2_FRMIVAL_TYPE_DISCRETE -> [%u]", ival.type); + return; + } + + do { + LOGI("\t\t\t\tFramerate[%u/%u]", ival.discrete.denominator, ival.discrete.numerator); + fps_list->fps[ival.index++] = ival.discrete.denominator; + } while (v4l2_ioctl(device_fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0); + + fps_list->count = ival.index; +} + + static int __camera_get_device_info(int device_index, int device_fd, camera_device_info_s *device_info, char *node_path) { int i = 0; @@ -441,6 +481,13 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi LOGD("\t\tsize[%d] %ux%u", j, v4l2_frame.discrete.width, v4l2_frame.discrete.height); + + __camera_get_fps_list(device_fd, + v4l2_frame.pixel_format, + v4l2_frame.discrete.width, + v4l2_frame.discrete.height, + &device_info->preview_fps_list[j]); + memcpy(&device_info->video_fps_list[j], &device_info->preview_fps_list[j], sizeof(camera_fps_list_s)); break; case V4L2_FRMSIZE_TYPE_CONTINUOUS: LOGW("\t\tsize[%d] %ux%u - %ux%u", j, -- 2.7.4 From b62657fec0a369f8bbea2e4101f21ebcb1b4e48a Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Wed, 15 Sep 2021 20:57:40 +0900 Subject: [PATCH 16/16] Support extra preview GOP interval functions for test [Version] 0.1.8 [Issue Type] New feature Change-Id: I16c67cfa54fccbf99a8aedadf3abd3283ad40eca Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/hal_camera_v4l2.c | 46 ++++++++++++++++++++++++++++++++++++++++++ src/hal_camera_v4l2_private.h | 1 + 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index 0bcd5f2..980d1f6 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -2,7 +2,7 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.1.7 +Version: 0.1.8 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/hal_camera_v4l2.c b/src/hal_camera_v4l2.c index 3167f4f..08b79a8 100644 --- a/src/hal_camera_v4l2.c +++ b/src/hal_camera_v4l2.c @@ -2121,6 +2121,50 @@ int camera_v4l2_get_extra_preview_bitrate(void *camera_handle, int stream_id, in } +int camera_v4l2_set_extra_preview_gop_interval(void *camera_handle, int stream_id, int interval) +{ + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; + + if (!handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (stream_id < 0 || stream_id >= EXTRA_PREVIEW_STREAM_MAX) { + LOGE("invalid stream_id[%d]", stream_id); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGI("set GOP interval[%d] for stream_id[%d]", interval, stream_id); + + handle->extra_preview_gop_interval[stream_id] = interval; + + return CAMERA_ERROR_NONE; +} + + +int camera_v4l2_get_extra_preview_gop_interval(void *camera_handle, int stream_id, int *interval) +{ + hal_camera_handle *handle = (hal_camera_handle *)camera_handle; + + if (!handle || !interval) { + LOGE("NULL param[%p,%p]", handle, interval); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (stream_id < 0 || stream_id >= EXTRA_PREVIEW_STREAM_MAX) { + LOGE("invalid stream_id[%d]", stream_id); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + *interval = (int)handle->extra_preview_gop_interval[stream_id]; + + LOGI("get GOP interval[%d] for stream_id[%d]", *interval, stream_id); + + return CAMERA_ERROR_NONE; +} + + static int __set_command(hal_camera_handle *handle, int64_t command, void *value) { int cid = 0; @@ -2457,6 +2501,8 @@ static int camera_v4l2_backend_init(void **data) funcs->get_extra_preview_stream_format = camera_v4l2_get_extra_preview_stream_format; funcs->set_extra_preview_bitrate = camera_v4l2_set_extra_preview_bitrate; funcs->get_extra_preview_bitrate = camera_v4l2_get_extra_preview_bitrate; + funcs->set_extra_preview_gop_interval = camera_v4l2_set_extra_preview_gop_interval; + funcs->get_extra_preview_gop_interval = camera_v4l2_get_extra_preview_gop_interval; *data = (void *)funcs; diff --git a/src/hal_camera_v4l2_private.h b/src/hal_camera_v4l2_private.h index 65478d9..1046da6 100644 --- a/src/hal_camera_v4l2_private.h +++ b/src/hal_camera_v4l2_private.h @@ -76,6 +76,7 @@ typedef struct _camera_hal_handle { gpointer extra_preview_cb_data; GMutex extra_preview_lock; camera_format_s extra_preview_format[EXTRA_PREVIEW_STREAM_MAX]; + gint32 extra_preview_gop_interval[EXTRA_PREVIEW_STREAM_MAX]; /* capture */ hal_camera_capture_cb capture_cb; -- 2.7.4