From 0fecd7c40cbcf2438e5c32512b56b5d758d49496 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Thu, 23 Jul 2020 19:56:57 +0900 Subject: [PATCH 01/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 02/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 03/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 04/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 05/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 06/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 07/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 08/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 09/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 10/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 11/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 12/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 From 17717877e0b97d60b7e15311eceeb9edec962a4b Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Wed, 3 Nov 2021 21:44:47 +0900 Subject: [PATCH 13/16] Prevent overflow for capability list [Version] 0.1.9 [Issue Type] Improvement Change-Id: Ib3bb81c0bcd4998f04bcc6ed8f797780dcfae0e7 Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/hal_camera_v4l2.c | 77 ++++++++++++++++++++++++------------------ 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index 980d1f6..cdb0b26 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.8 +Version: 0.1.9 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/hal_camera_v4l2.c b/src/hal_camera_v4l2.c index 08b79a8..9f28a01 100644 --- a/src/hal_camera_v4l2.c +++ b/src/hal_camera_v4l2.c @@ -386,6 +386,7 @@ 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) { + uint32_t fps_count = 0; struct v4l2_frmivalenum ival; if (device_fd < 0 || !fps_list) { @@ -398,30 +399,32 @@ static void __camera_get_fps_list(int device_fd, guint32 pixel_format, int width ival.width = width; ival.height = height; - if (v4l2_ioctl(device_fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0) { - LOGE("VIDIOC_ENUM_FRAMEINTERVALS failed[%d]", errno); - return; - } + while (v4l2_ioctl(device_fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0) { + if (ival.type != V4L2_FRMIVAL_TYPE_DISCRETE) { + LOGE("NOT DISCRETE type[%u] for [%dx%d]", ival.type, width, height); + return; + } - if (ival.type != V4L2_FRMIVAL_TYPE_DISCRETE) { - LOGE("NOT V4L2_FRMIVAL_TYPE_DISCRETE -> [%u]", ival.type); - return; - } + if (ival.index++ >= FPS_COUNT_MAX) { + LOGW("\t\t\t\tFramerate[i:%u][%u/%u] is available, but list is full[max:%d]", + ival.index - 1, ival.discrete.denominator, ival.discrete.numerator, FPS_COUNT_MAX); + continue; + } - 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->fps[fps_count++] = ival.discrete.denominator; + } - fps_list->count = ival.index; + + fps_list->count = fps_count; } 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; + int format_index = 0; int format_count = 0; + int resolution_index = 0; int resolution_count = 0; int camera_format = 0; struct v4l2_fmtdesc v4l2_format; @@ -432,12 +435,12 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("Get Supported format and resolution"); + LOGD("Get Supported format, resolution and fps"); - for (i = 0 ; ; i++) { + for (format_index = 0, format_count = 0 ; ; format_index++) { memset(&v4l2_format, 0x0, sizeof(struct v4l2_fmtdesc)); - v4l2_format.index = i; + v4l2_format.index = format_index; v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (v4l2_ioctl(device_fd, VIDIOC_ENUM_FMT, &v4l2_format) < 0) { @@ -445,28 +448,37 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi break; } - LOGD("\tformat[%d] "FOURCC_FORMAT" (emulated:%d)", - i, FOURCC_CONVERT(v4l2_format.pixelformat), + LOGD("\tTry [%d] format "FOURCC_FORMAT" (emulated:%d)", + format_count, 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; - device_info->format_list.formats[format_count] = camera_format; + if (format_count + 1 >= CAMERA_PIXEL_FORMAT_MAX) { + LOGW("format list is full[max:%u], skip format[i:%u][%d]", + CAMERA_PIXEL_FORMAT_MAX, v4l2_format.index, camera_format); + continue; + } - resolution_count = 0; + device_info->format_list.formats[format_count++] = camera_format; - for (j = 0 ; ; j++) { + for (resolution_index = 0, resolution_count = 0 ; ; resolution_index++) { memset(&v4l2_frame, 0x0, sizeof(struct v4l2_frmsizeenum)); - v4l2_frame.index = j; + v4l2_frame.index = resolution_index; v4l2_frame.pixel_format = v4l2_format.pixelformat; if (v4l2_ioctl(device_fd, VIDIOC_ENUM_FRAMESIZES, &v4l2_frame) < 0) { - LOGW("\t\tframe : end of enumeration "); + LOGW("\t\tframesize : end of enumeration"); break; } + if (resolution_count + 1 >= RESOLUTION_COUNT_MAX) { + LOGW("resolution list is full, skip resolution[%ux%u]", v4l2_frame.discrete.width, v4l2_frame.discrete.height); + continue; + } + switch (v4l2_frame.type) { case V4L2_FRMSIZE_TYPE_DISCRETE: device_info->preview_list.resolutions[resolution_count].width = v4l2_frame.discrete.width; @@ -476,9 +488,7 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi device_info->video_list.resolutions[resolution_count].width = v4l2_frame.discrete.width; device_info->video_list.resolutions[resolution_count].height = v4l2_frame.discrete.height; - resolution_count++; - - LOGD("\t\tsize[%d] %ux%u", j, + LOGD("\t\tsize[%d] %ux%u", resolution_count, v4l2_frame.discrete.width, v4l2_frame.discrete.height); @@ -486,18 +496,21 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi 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)); + &device_info->preview_fps_list[resolution_count]); + + memcpy(&device_info->video_fps_list[resolution_count], &device_info->preview_fps_list[resolution_count], sizeof(camera_fps_list_s)); + + resolution_count++; break; case V4L2_FRMSIZE_TYPE_CONTINUOUS: - LOGW("\t\tsize[%d] %ux%u - %ux%u", j, + LOGW("\t\tsize[%d] %ux%u - %ux%u", resolution_count, v4l2_frame.stepwise.min_width, v4l2_frame.stepwise.min_height, v4l2_frame.stepwise.max_width, v4l2_frame.stepwise.max_height); break; case V4L2_FRMSIZE_TYPE_STEPWISE: - LOGW("\t\tsize[%d] %ux%u - %ux%u (step %ux%u)", j, + LOGW("\t\tsize[%d] %ux%u - %ux%u (step %ux%u)", resolution_count, v4l2_frame.stepwise.min_width, v4l2_frame.stepwise.min_height, v4l2_frame.stepwise.max_width, @@ -516,8 +529,6 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi device_info->video_list.count = resolution_count; LOGD("\t\tresolution count [%d]", resolution_count); - - format_count++; } device_info->index = device_index; -- 2.7.4 From ac33b34fa3c6e7c2b69ed46596ebb94b8603ee20 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Wed, 10 Nov 2021 21:50:54 +0900 Subject: [PATCH 14/16] Send error message when DQBUF is failed - Additional change : Remove state condition check in camera_v4l2_add/remove_message_callback(). [Version] 0.1.10 [Issue Type] Improvement Change-Id: I83e480e42624617b46220632755534096b08495d Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/hal_camera_v4l2.c | 74 ++++++++++++++++++++++++++++++------------ 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index cdb0b26..a08a7f1 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.9 +Version: 0.1.10 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/hal_camera_v4l2.c b/src/hal_camera_v4l2.c index 9f28a01..4d8d994 100644 --- a/src/hal_camera_v4l2.c +++ b/src/hal_camera_v4l2.c @@ -57,6 +57,7 @@ static GMutex g_device_info_lock; static void __camera_hal_v4l2_destructor(void) __attribute__((destructor)); +static void __camera_send_message(hal_camera_handle *handle, camera_message_type_e type, int value); static void __camera_hal_v4l2_destructor(void) @@ -70,6 +71,48 @@ static void __camera_hal_v4l2_destructor(void) } +static void __camera_send_message(hal_camera_handle *handle, camera_message_type_e type, int value) +{ + camera_message_s *message = NULL; + + if (!handle) { + LOGE("NULL handle"); + return; + } + + message = g_new0(camera_message_s, 1); + + message->type = type; + + switch (type) { + case CAMERA_MESSAGE_TYPE_FOCUS_CHANGED: + message->focus_state = (camera_focus_state_e)value; + break; + case CAMERA_MESSAGE_TYPE_CAPTURED: + break; + case CAMERA_MESSAGE_TYPE_HDR_PROGRESS: + message->hdr_progress = (uint32_t)value; + break; + case CAMERA_MESSAGE_TYPE_ERROR: + message->error_code = (camera_error_e)value; + break; + default: + LOGE("unknown type[%d]", type); + g_free(message); + return; + } + + g_mutex_lock(&handle->msg_cb_lock); + + LOGD("type[%d], value[0x%x]", type, value); + + g_queue_push_tail(handle->msg_list, message); + g_cond_signal(&handle->msg_cb_cond); + + g_mutex_unlock(&handle->msg_cb_lock); +} + + static int __camera_v4l2_wait_frame(int device_fd, int wait_time) { int ret = CAMERA_ERROR_NONE; @@ -263,11 +306,9 @@ static int __camera_v4l2_dqbuf(int device_fd, int type, int memory, int *index) ret = v4l2_ioctl(device_fd, VIDIOC_DQBUF, &v4l2_buf); if (ret < 0) { - if (errno != EIO) { - LOGE("dqbuf failed. [t: %d, m: %d] errno %d", - type, memory, errno); - return CAMERA_ERROR_DEVICE_READ; - } + LOGE("dqbuf failed. [t: %d, m: %d] errno %d", + type, memory, errno); + return CAMERA_ERROR_DEVICE_READ; } *index = v4l2_buf.index; @@ -977,6 +1018,7 @@ _CAPTURE_DONE: static void *__camera_buffer_handler_func(gpointer data) { + int error = CAMERA_ERROR_NONE; int index = 0; hal_camera_handle *handle = (hal_camera_handle *)data; @@ -1006,8 +1048,9 @@ static void *__camera_buffer_handler_func(gpointer data) break; } - if (__camera_v4l2_dqbuf(handle->device_fd, handle->buffer_type, V4L2_MEMORY_MMAP, &index) != CAMERA_ERROR_NONE) { - LOGE("dqbuf failed"); + error = __camera_v4l2_dqbuf(handle->device_fd, handle->buffer_type, V4L2_MEMORY_MMAP, &index); + if (error != CAMERA_ERROR_NONE) { + LOGE("dqbuf failed[0x%x]", error); break; } @@ -1048,6 +1091,9 @@ static void *__camera_buffer_handler_func(gpointer data) g_mutex_unlock(&handle->buffer_lock); + if (error != CAMERA_ERROR_NONE) + __camera_send_message(handle, CAMERA_MESSAGE_TYPE_ERROR, error); + LOGD("leave"); return NULL; @@ -1108,7 +1154,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); + LOGD("call message callback[%d] type[%d]", i, message->type); handle->msg_cb[i](message, handle->msg_cb_data[i]); } } @@ -1434,12 +1480,6 @@ int camera_v4l2_add_message_callback(void *camera_handle, hal_camera_message_cb g_mutex_lock(&handle->lock); - if (handle->state != CAMERA_STATE_OPENED) { - LOGE("invalid state %d", handle->state); - g_mutex_unlock(&handle->lock); - return CAMERA_ERROR_INVALID_STATE; - } - for (i = 0 ; i < MESSAGE_CALLBACK_MAX ; i++) { if (handle->msg_cb[i] == NULL) { handle->msg_cb[i] = callback; @@ -1475,12 +1515,6 @@ int camera_v4l2_remove_message_callback(void *camera_handle, uint32_t cb_id) g_mutex_lock(&handle->lock); - if (handle->state != CAMERA_STATE_OPENED) { - LOGE("invalid state %d", handle->state); - g_mutex_unlock(&handle->lock); - return CAMERA_ERROR_INVALID_STATE; - } - if (handle->msg_cb[cb_id]) { LOGD("remove message callback %p, user data %p - cb_id %u", handle->msg_cb[cb_id], handle->msg_cb_data[cb_id], cb_id); -- 2.7.4 From dea9215ca1880614f77331bae8f824ec6166fbd7 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Thu, 14 Apr 2022 18:02:20 +0900 Subject: [PATCH 15/16] Support zero copy for preview buffer - Replace V4L2_MEMORY_MMAP by V4L2_MEMORY_DMABUF for memory type. [Version] 0.1.11 [Issue Type] New feature Change-Id: Ic154d252dbdb0952371bffa142248282041325f7 Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 10 +- src/hal_camera_v4l2.c | 243 ++++++++++++++++++++++++++++++++--------- src/hal_camera_v4l2_private.h | 8 ++ 3 files changed, 206 insertions(+), 55 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index a08a7f1..d628f0b 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,8 +1,13 @@ +%define enable_zero_copy 1 +%if 0%{?enable_zero_copy} +%define enable_libv4l2 0 +%else %define enable_libv4l2 1 +%endif Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.1.10 +Version: 0.1.11 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 @@ -27,6 +32,9 @@ Tizen Camera Hal for V4L2. %build +%if 0%{?enable_zero_copy} +export CFLAGS+=" -DTIZEN_FEATURE_ZERO_COPY_SUPPORT" +%endif ./autogen.sh %configure \ %if 0%{?enable_libv4l2} diff --git a/src/hal_camera_v4l2.c b/src/hal_camera_v4l2.c index 4d8d994..1e68952 100644 --- a/src/hal_camera_v4l2.c +++ b/src/hal_camera_v4l2.c @@ -229,6 +229,8 @@ static int __camera_v4l2_reqbufs(int device_fd, int type, int memory, uint32_t c return CAMERA_ERROR_INVALID_PARAMETER; } + LOGI("type[%d], memory[%d], count[%u]", type, memory, count); + memset(&v4l2_reqbuf, 0x0, sizeof(struct v4l2_requestbuffers)); v4l2_reqbuf.type = type; @@ -249,7 +251,7 @@ static int __camera_v4l2_reqbufs(int device_fd, int type, int memory, uint32_t c } -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, int dmabuf_fd) { struct v4l2_buffer v4l2_buf; struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX]; @@ -266,8 +268,13 @@ static int __camera_v4l2_qbuf(int device_fd, int type, int memory, int index) v4l2_buf.type = type; v4l2_buf.memory = memory; v4l2_buf.m.planes = v4l2_planes; - v4l2_buf.length = 460800; - v4l2_buf.bytesused = 460800; + + if (dmabuf_fd > CAMERA_HAL_INITIAL_FD) { + if (V4L2_TYPE_IS_MULTIPLANAR(type)) + v4l2_buf.m.planes[0].m.fd = dmabuf_fd; + else + v4l2_buf.m.fd = dmabuf_fd; + } if (v4l2_ioctl(device_fd, VIDIOC_QBUF, &v4l2_buf) < 0) { LOGE("qbuf failed. [i: %d, t: %d, m: %d] errno %d", @@ -275,13 +282,14 @@ 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, fd:%d]", + index, type, memory, dmabuf_fd); 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, uint32_t *bytesused) { int ret = CAMERA_ERROR_NONE; struct v4l2_buffer v4l2_buf; @@ -311,7 +319,12 @@ static int __camera_v4l2_dqbuf(int device_fd, int type, int memory, int *index) return CAMERA_ERROR_DEVICE_READ; } + LOGD("DQBUF[i:%d], bytesused[%u], length[%u]", + v4l2_buf.index, v4l2_buf.bytesused, v4l2_buf.length); + *index = v4l2_buf.index; + if (bytesused) + *bytesused = v4l2_buf.bytesused; /*LOGD("dqbuf index %d", *index);*/ @@ -595,6 +608,7 @@ static int __camera_get_device_info_list(void) #endif /* HAVE_LIBV4L2 */ glob_t glob_buf; struct v4l2_capability v4l2_cap; + guint32 device_caps; camera_device_info_list_s *device_info_list = NULL; g_mutex_lock(&g_device_info_lock); @@ -665,13 +679,13 @@ static int __camera_get_device_info_list(void) } if (v4l2_cap.capabilities & V4L2_CAP_DEVICE_CAPS) - g_device_caps = v4l2_cap.device_caps; + device_caps = v4l2_cap.device_caps; else - g_device_caps = v4l2_cap.capabilities; + device_caps = v4l2_cap.capabilities; - 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); + 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); v4l2_close(device_fd); continue; } @@ -681,8 +695,11 @@ static int __camera_get_device_info_list(void) v4l2_close(device_fd); - if (ret == CAMERA_ERROR_NONE) + if (ret == CAMERA_ERROR_NONE) { device_count++; + g_device_caps = device_caps; + LOGI("device caps [0x%08x]", g_device_caps); + } } device_info_list->count = device_count; @@ -706,38 +723,63 @@ static int __camera_stop_stream(hal_camera_handle *handle, uint32_t buffer_count { int i = 0; int ret = CAMERA_ERROR_NONE; + camera_buffer_s *buffer = NULL; +#ifdef TIZEN_FEATURE_ZERO_COPY_SUPPORT + camera_tbm_buffer_s *tbm_buffer = NULL; +#endif if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("buffer count[%d]", buffer_count); + LOGI("buffer count[%d]", buffer_count); /* stream off */ ret = __camera_v4l2_stream(handle->device_fd, handle->buffer_type, FALSE); - LOGD("stream off : 0x%x", ret); + LOGI("stream off[0x%x]", ret); - /* munmap */ + /* release buffer */ 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); + buffer = &handle->camera_buffers[i]; + + LOGI("release buffer[%d]", i); - v4l2_munmap(handle->camera_buffers[i].planes[0].data, handle->camera_buffers[i].planes[0].size); +#ifdef TIZEN_FEATURE_ZERO_COPY_SUPPORT + tbm_buffer = &handle->tbm_buffers[i]; - handle->camera_buffers[i].planes[0].data = 0; - handle->camera_buffers[i].planes[0].size = 0; + if (tbm_buffer->dmabuf_fd > CAMERA_HAL_INITIAL_FD) { + LOGI(" close dmabuf fd[%d]", tbm_buffer->dmabuf_fd); + close(tbm_buffer->dmabuf_fd); + tbm_buffer->dmabuf_fd = CAMERA_HAL_INITIAL_FD; + } + + if (tbm_buffer->bo) { + LOGI(" unref tbm bo[%p]", tbm_buffer->bo); + tbm_bo_unref(tbm_buffer->bo); + tbm_buffer->bo = NULL; + } + + tbm_buffer->bo_handle.ptr = NULL; +#endif + + if (buffer->planes[0].data) { +#ifndef TIZEN_FEATURE_ZERO_COPY_SUPPORT + LOGI(" munmap %p", buffer->planes[0].data); + v4l2_munmap(buffer->planes[0].data, buffer->planes[0].size); +#endif + buffer->planes[0].data = NULL; + buffer->planes[0].size = 0; } else { - LOGW("NULL data [index %d]", i); + LOGI(" NULL data [i:%d]", i); } } - /* reqbufs 0 */ ret = __camera_v4l2_reqbufs(handle->device_fd, - handle->buffer_type, V4L2_MEMORY_MMAP, 0, &buffer_count); + handle->buffer_type, handle->memory_type, 0, &buffer_count); - LOGD("reqbufs 0 : 0x%x", ret); + LOGI("reqbufs 0 [0x%x]", ret); return ret; } @@ -751,8 +793,13 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_ camera_buffer_s *buffer = NULL; struct v4l2_format v4l2_fmt; struct v4l2_streamparm v4l2_parm; +#ifdef TIZEN_FEATURE_ZERO_COPY_SUPPORT + uint32_t buffer_size = 0; + camera_tbm_buffer_s *tbm_buffer = NULL; +#else struct v4l2_buffer v4l2_buf; struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX];; +#endif guint32 fourcc = 0; guint32 plane_num = 0; @@ -761,6 +808,9 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_ return CAMERA_ERROR_INTERNAL; } + LOGI("[%dx%d], format[%d], fps[%u]", + resolution->width, resolution->height, pixel_format, fps); + /* S_FMT */ ret = __camera_get_fourcc_plane_num(pixel_format, &fourcc, &plane_num); if (ret != CAMERA_ERROR_NONE) { @@ -790,11 +840,18 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_ if (V4L2_TYPE_IS_MULTIPLANAR(handle->buffer_type)) { for (i = 0 ; i < v4l2_fmt.fmt.pix_mp.num_planes ; i++) { +#ifdef TIZEN_FEATURE_ZERO_COPY_SUPPORT + /* TODO: Is it needed to make array for each planes? */ + buffer_size += v4l2_fmt.fmt.pix_mp.plane_fmt[i].sizeimage; +#endif 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 { +#ifdef TIZEN_FEATURE_ZERO_COPY_SUPPORT + buffer_size = v4l2_fmt.fmt.pix.sizeimage; +#endif LOGD("stride %d, sizeimage %d", v4l2_fmt.fmt.pix.bytesperline, v4l2_fmt.fmt.pix.sizeimage); @@ -821,32 +878,78 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_ /* request buffer */ ret = __camera_v4l2_reqbufs(handle->device_fd, - handle->buffer_type, V4L2_MEMORY_MMAP, request_buffer_count, &handle->buffer_count); + handle->buffer_type, handle->memory_type, + request_buffer_count, &handle->buffer_count); if (ret != CAMERA_ERROR_NONE) { return ret; } - LOGD("buffer count : request %d -> result %d", + LOGI("buffer count : request %d -> result %d", request_buffer_count, handle->buffer_count); - /* query buffer, mmap and qbuf */ + /* alloc and queue buffer */ for (i = 0 ; i < handle->buffer_count ; i++) { + buffer = &handle->camera_buffers[i]; + + buffer->index = i; + buffer->format = pixel_format; + buffer->resolution.width = resolution->width; + buffer->resolution.height = resolution->height; + buffer->num_planes = plane_num; + +#ifdef TIZEN_FEATURE_ZERO_COPY_SUPPORT + tbm_buffer = &handle->tbm_buffers[i]; + + tbm_buffer->bo = tbm_bo_alloc(handle->bufmgr, (int)buffer_size, TBM_BO_DEFAULT); + if (!tbm_buffer->bo) { + LOGE("bo alloc failed[size:%u]", buffer_size); + ret = CAMERA_ERROR_OUT_OF_MEMORY; + goto _START_STREAM_FAILED; + } + + tbm_buffer->bo_handle = tbm_bo_get_handle(tbm_buffer->bo, TBM_DEVICE_CPU); + if (!tbm_buffer->bo_handle.ptr) { + LOGE("bo[%p] get handle failed", tbm_buffer->bo); + ret = CAMERA_ERROR_INTERNAL; + goto _START_STREAM_FAILED; + } + + tbm_buffer->dmabuf_fd = tbm_bo_export_fd(tbm_buffer->bo); + if (tbm_buffer->dmabuf_fd < 0) { + LOGE("export fd failed from bo[%p]", tbm_buffer->bo); + ret = CAMERA_ERROR_INTERNAL; + goto _START_STREAM_FAILED; + } + + buffer->total_size = buffer_size; + buffer->planes[0].size = buffer_size; + buffer->planes[0].data = tbm_buffer->bo_handle.ptr; + buffer->num_bos = 1; + buffer->bos[0] = tbm_buffer->bo; + + LOGD("buffer[%d], size[%d], data[%p], bo[%p], fd[%d]", + i, buffer->planes[0].size, buffer->planes[0].data, + tbm_buffer->bo, tbm_buffer->dmabuf_fd); + + ret = __camera_v4l2_qbuf(handle->device_fd, + handle->buffer_type, handle->memory_type, + i, tbm_buffer->dmabuf_fd); +#else /* TIZEN_FEATURE_ZERO_COPY_SUPPORT */ memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer)); memset(v4l2_planes, 0x0, sizeof(v4l2_planes)); v4l2_buf.type = handle->buffer_type; - v4l2_buf.memory = V4L2_MEMORY_MMAP; + v4l2_buf.memory = handle->memory_type; v4l2_buf.index = i; v4l2_buf.m.planes = v4l2_planes; v4l2_buf.length = plane_num; if (v4l2_ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) { LOGE("[%d] query buf failed. errno %d", i, errno); + ret = CAMERA_ERROR_INTERNAL; goto _START_STREAM_FAILED; } - buffer = &handle->camera_buffers[i]; - buffer->index = i; buffer->format = pixel_format; buffer->resolution.width = resolution->width; @@ -866,7 +969,15 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_ goto _START_STREAM_FAILED; } - if (__camera_v4l2_qbuf(handle->device_fd, handle->buffer_type, V4L2_MEMORY_MMAP, i) != CAMERA_ERROR_NONE) { + LOGI("buffer[%d], size[%d], data[%p]", + i, buffer->planes[0].size, buffer->planes[0].data); + + ret = __camera_v4l2_qbuf(handle->device_fd, + handle->buffer_type, handle->memory_type, + i, CAMERA_HAL_INITIAL_FD); +#endif /* TIZEN_FEATURE_ZERO_COPY_SUPPORT */ + + if (ret != CAMERA_ERROR_NONE) { LOGE("[%d] qbuf failed (errno %d)", i, errno); goto _START_STREAM_FAILED; } @@ -879,6 +990,8 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_ goto _START_STREAM_FAILED; } + LOGI("done"); + return CAMERA_ERROR_NONE; _START_STREAM_FAILED: @@ -890,10 +1003,11 @@ _START_STREAM_FAILED: static void __camera_do_capture(hal_camera_handle *handle) { int ret = CAMERA_ERROR_NONE; - int buffer_index = 0; + int index = 0; gint64 current_time = 0; gint64 previous_time = 0; gint64 interval_us = 0; + uint32_t bytesused = 0; if (!handle) { LOGE("NULL handle"); @@ -933,12 +1047,15 @@ static void __camera_do_capture(hal_camera_handle *handle) } ret = __camera_v4l2_dqbuf(handle->device_fd, - handle->buffer_type, V4L2_MEMORY_MMAP, &buffer_index); + handle->buffer_type, handle->memory_type, + &index, &bytesused); if (ret != CAMERA_ERROR_NONE) { LOGE("dqbuf failed for capture[0x%x]", ret); goto _CAPTURE_DONE; } + handle->camera_buffers[index].planes[0].bytesused = bytesused; + if (handle->captured_count > 0) { g_mutex_lock(&handle->buffer_lock); if (handle->state != CAMERA_STATE_CAPTURING) { @@ -965,10 +1082,10 @@ static void __camera_do_capture(hal_camera_handle *handle) g_mutex_unlock(&handle->buffer_lock); LOGD("capture cb[%p], buffer index[%d],count[%d]", - handle->capture_cb, buffer_index, handle->captured_count); + handle->capture_cb, index, handle->captured_count); if (handle->capture_cb) { - handle->capture_cb(&handle->camera_buffers[buffer_index], + handle->capture_cb(&handle->camera_buffers[index], NULL, NULL, handle->capture_cb_data); } else { LOGW("capture callback is NULL"); @@ -979,7 +1096,8 @@ static void __camera_do_capture(hal_camera_handle *handle) _TRY_NEXT: ret = __camera_v4l2_qbuf(handle->device_fd, - handle->buffer_type, V4L2_MEMORY_MMAP, buffer_index); + handle->buffer_type, handle->memory_type, + index, handle->tbm_buffers[index].dmabuf_fd); if (ret != CAMERA_ERROR_NONE) LOGE("qbuf failed for capture[0x%x]", ret); } while (handle->captured_count < handle->capture_count); @@ -1021,6 +1139,7 @@ static void *__camera_buffer_handler_func(gpointer data) int error = CAMERA_ERROR_NONE; int index = 0; hal_camera_handle *handle = (hal_camera_handle *)data; + uint32_t bytesused = 0; if (!handle) { LOGE("NULL handle for buffer handler"); @@ -1048,13 +1167,16 @@ static void *__camera_buffer_handler_func(gpointer data) break; } - error = __camera_v4l2_dqbuf(handle->device_fd, handle->buffer_type, V4L2_MEMORY_MMAP, &index); + error = __camera_v4l2_dqbuf(handle->device_fd, + handle->buffer_type, handle->memory_type, + &index, &bytesused); if (error != CAMERA_ERROR_NONE) { LOGE("dqbuf failed[0x%x]", error); break; } handle->buffer_dequeued_count++; + handle->camera_buffers[index].planes[0].bytesused = bytesused; /*LOGD("dequeued buffer count %d", handle->buffer_dequeued_count);*/ @@ -1212,6 +1334,7 @@ static void __camera_release_handle(hal_camera_handle *handle) int camera_v4l2_init(void **camera_handle) { + int i = 0; int ret = CAMERA_ERROR_NONE; hal_camera_handle *new_handle = NULL; tbm_bufmgr bufmgr = NULL; @@ -1223,6 +1346,12 @@ int camera_v4l2_init(void **camera_handle) return CAMERA_ERROR_INVALID_PARAMETER; } + ret = __camera_get_device_info_list(); + if (ret != CAMERA_ERROR_NONE) { + LOGE("get device info failed[0x%x]", ret); + return ret; + } + bufmgr = tbm_bufmgr_init(-1); if (bufmgr == NULL) { LOGE("get tbm bufmgr failed"); @@ -1260,11 +1389,8 @@ int camera_v4l2_init(void **camera_handle) new_handle->device_fd = CAMERA_HAL_INITIAL_FD; new_handle->state = CAMERA_STATE_INITIALIZED; - ret = __camera_get_device_info_list(); - if (ret != CAMERA_ERROR_NONE) { - LOGE("get device info failed"); - goto _INIT_ERROR; - } + for (i = 0 ; i < BUFFER_MAX ; i++) + new_handle->tbm_buffers[i].dmabuf_fd = CAMERA_HAL_INITIAL_FD; #ifdef HAVE_LIBV4L2 LOGI("libv4l2 ENABLED"); @@ -1393,9 +1519,15 @@ int camera_v4l2_open_device(void *camera_handle, int device_index) } if (g_device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) - handle->buffer_type = V4L2_CAP_VIDEO_CAPTURE_MPLANE; + handle->buffer_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; else - handle->buffer_type = V4L2_CAP_VIDEO_CAPTURE; + handle->buffer_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + +#ifdef TIZEN_FEATURE_ZERO_COPY_SUPPORT + handle->memory_type = V4L2_MEMORY_DMABUF; +#else + handle->memory_type = V4L2_MEMORY_MMAP; +#endif #ifdef HAVE_LIBV4L2 libv4l2_fd = v4l2_fd_open(device_fd, V4L2_ENABLE_ENUM_FMT_EMULATION); @@ -1745,7 +1877,7 @@ int camera_v4l2_start_preview(void *camera_handle, hal_camera_preview_frame_cb c } -int camera_v4l2_release_preview_buffer(void *camera_handle, int buffer_index) +int camera_v4l2_release_preview_buffer(void *camera_handle, int index) { int ret = CAMERA_ERROR_NONE; hal_camera_handle *handle = (hal_camera_handle *)camera_handle; @@ -1755,13 +1887,14 @@ int camera_v4l2_release_preview_buffer(void *camera_handle, int buffer_index) return CAMERA_ERROR_INVALID_PARAMETER; } - if (buffer_index >= handle->buffer_count) { - LOGE("invalid buffer index %d", buffer_index); + if (index >= handle->buffer_count) { + LOGE("invalid buffer index %d", index); return CAMERA_ERROR_INVALID_PARAMETER; } ret = __camera_v4l2_qbuf(handle->device_fd, - handle->buffer_type, V4L2_MEMORY_MMAP, buffer_index); + handle->buffer_type, handle->memory_type, + index, handle->tbm_buffers[index].dmabuf_fd); g_mutex_lock(&handle->buffer_lock); @@ -1772,9 +1905,9 @@ int camera_v4l2_release_preview_buffer(void *camera_handle, int buffer_index) 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);*/ + index, handle->buffer_dequeued_count);*/ } else { - LOGE("qbuf failed [index %d]", buffer_index); + LOGE("qbuf failed [index %d]", index); } g_cond_signal(&handle->buffer_cond); @@ -1823,12 +1956,14 @@ int camera_v4l2_stop_preview(void *camera_handle) g_mutex_unlock(&handle->buffer_lock); - ret = __camera_stop_stream(handle, handle->buffer_count); - /* wait for preview thread exit */ + LOGD("wait for buffer thread"); + g_thread_join(handle->buffer_thread); handle->buffer_thread = NULL; + ret = __camera_stop_stream(handle, handle->buffer_count); + handle->state = CAMERA_STATE_OPENED; LOGD("stop preview done [0x%x]", ret); @@ -1985,7 +2120,7 @@ int camera_v4l2_start_record(void *camera_handle, hal_camera_video_frame_cb call } -int camera_v4l2_release_video_buffer(void *camera_handle, int buffer_index) +int camera_v4l2_release_video_buffer(void *camera_handle, int index) { if (!camera_handle) { LOGE("NULL handle"); @@ -2057,7 +2192,7 @@ int camera_v4l2_unset_extra_preview_frame_cb(void *camera_handle) } -int camera_v4l2_release_extra_preview_buffer(void *camera_handle, int stream_id, int buffer_index) +int camera_v4l2_release_extra_preview_buffer(void *camera_handle, int stream_id, int index) { hal_camera_handle *handle = (hal_camera_handle *)camera_handle; @@ -2066,7 +2201,7 @@ int camera_v4l2_release_extra_preview_buffer(void *camera_handle, int stream_id, return CAMERA_ERROR_INVALID_PARAMETER; } - LOGI("done - stream_id[%d], index[%d]", stream_id, buffer_index); + LOGI("done - stream_id[%d], index[%d]", stream_id, index); return CAMERA_ERROR_NONE; } diff --git a/src/hal_camera_v4l2_private.h b/src/hal_camera_v4l2_private.h index 1046da6..d64843e 100644 --- a/src/hal_camera_v4l2_private.h +++ b/src/hal_camera_v4l2_private.h @@ -50,6 +50,12 @@ typedef struct _set_batch_table_s { void *value; } set_batch_table_s; +typedef struct _camera_tbm_buffer_s { + tbm_bo bo; + tbm_bo_handle bo_handle; + int dmabuf_fd; +} camera_tbm_buffer_s; + typedef struct _camera_hal_handle { /* tbm */ tbm_bufmgr bufmgr; @@ -64,7 +70,9 @@ typedef struct _camera_hal_handle { gboolean buffer_thread_run; guint32 buffer_count; camera_buffer_s camera_buffers[BUFFER_MAX]; + camera_tbm_buffer_s tbm_buffers[BUFFER_MAX]; enum v4l2_buf_type buffer_type; + enum v4l2_memory memory_type; GMutex buffer_lock; GCond buffer_cond; -- 2.7.4 From 68f7ed3d8e18d0a027e74961e6dd984356ccbd38 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Wed, 29 Jun 2022 12:42:49 +0900 Subject: [PATCH 16/16] Support exposure setting [Version] 0.1.12 [Issue Type] New feature Change-Id: I96ca6f1b9831ffb2cf020ea2fd0d9494ec0cfb03 Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/hal_camera_v4l2.c | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index d628f0b..cac7a60 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -7,7 +7,7 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.1.11 +Version: 0.1.12 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/hal_camera_v4l2.c b/src/hal_camera_v4l2.c index 1e68952..8dbb539 100644 --- a/src/hal_camera_v4l2.c +++ b/src/hal_camera_v4l2.c @@ -2363,7 +2363,7 @@ static int __set_command(hal_camera_handle *handle, int64_t command, void *value return CAMERA_ERROR_INVALID_STATE; } - LOGD("set command %"PRIx64" - state %d", command, handle->state); + LOGI("command[%"PRIx64"] -> [%d]", command, set_value); switch (command) { case CAMERA_COMMAND_BRIGHTNESS: @@ -2390,6 +2390,9 @@ static int __set_command(hal_camera_handle *handle, int64_t command, void *value case CAMERA_COMMAND_TILT: cid = V4L2_CID_TILT_ABSOLUTE; break; + case CAMERA_COMMAND_EXPOSURE: + cid = V4L2_CID_EXPOSURE; + break; case CAMERA_COMMAND_FLIP: if (set_value != CAMERA_FLIP_NONE) { LOGE("NOT_SUPPORTED flip %d", set_value); @@ -2398,22 +2401,17 @@ static int __set_command(hal_camera_handle *handle, int64_t command, void *value return CAMERA_ERROR_NONE; case CAMERA_COMMAND_CAPTURE_COUNT: handle->capture_count = set_value; - LOGI("capture count %u", handle->capture_count); return CAMERA_ERROR_NONE; case CAMERA_COMMAND_CAPTURE_INTERVAL: handle->capture_interval_ms = set_value; - LOGI("capture interval %u ms", handle->capture_interval_ms); 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: @@ -2476,7 +2474,7 @@ int camera_v4l2_get_command(void *camera_handle, int64_t command, void **value) g_mutex_lock(&handle->lock); - LOGD("get command %"PRIx64" - state %d", command, handle->state); + LOGI("command[%"PRIx64"]", command); switch (command) { case CAMERA_COMMAND_BRIGHTNESS: @@ -2491,20 +2489,20 @@ 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_EXPOSURE: + cid = V4L2_CID_EXPOSURE; + 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 %"PRIx64, command); + LOGE("Not supported command[%"PRIx64"]", command); g_mutex_unlock(&handle->lock); return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } @@ -2537,6 +2535,9 @@ int camera_v4l2_get_command(void *camera_handle, int64_t command, void **value) } _GET_COMMAND_DONE: + if (ret == CAMERA_ERROR_NONE) + LOGI("get[%d]", **(int **)value); + g_mutex_unlock(&handle->lock); return ret; -- 2.7.4