From: Kwanghoon Son Date: Wed, 27 Jul 2022 02:09:20 +0000 (-0400) Subject: Add vision_source_v4l2_{open,close}_devices X-Git-Tag: accepted/tizen/unified/20220729.131711~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F48%2F278848%2F3;p=platform%2Fcore%2Fmultimedia%2Fvision-source-v4l2.git Add vision_source_v4l2_{open,close}_devices [Version] : 0.0.3 [Issue type] New function Add v4l2 backend open, close function Change-Id: I2ced7b3fa7e2c41f959d67954cc16c72159bd720 Signed-off-by: Kwanghoon Son --- diff --git a/packaging/vision-source-v4l2.spec b/packaging/vision-source-v4l2.spec index b34babd..e58a090 100644 --- a/packaging/vision-source-v4l2.spec +++ b/packaging/vision-source-v4l2.spec @@ -2,7 +2,7 @@ Name: vision-source-v4l2 Summary: vision source-v4l2 -Version: 0.0.2 +Version: 0.0.3 Release: 0 Group: Multimedia/Framework License: Apache-2.0 diff --git a/src/vision_source_v4l2.c b/src/vision_source_v4l2.c index f310b6d..86cbcc7 100644 --- a/src/vision_source_v4l2.c +++ b/src/vision_source_v4l2.c @@ -32,7 +32,6 @@ (fourcc >> 24) & 0xff static guint32 g_device_caps; -static GMutex g_device_info_lock; static int __vision_source_get_format(guint32 fourcc, int *pixel_format) { @@ -248,8 +247,6 @@ static int __vision_source_get_device_info_list( struct v4l2_capability v4l2_cap; vision_source_device_info_list_s *device_info_list = NULL; - g_mutex_lock(&g_device_info_lock); - device_info_list = g_new0(vision_source_device_info_list_s, 1); if (!device_info_list) { LOGE("failed to alloc device info structure"); @@ -342,7 +339,6 @@ static int __vision_source_get_device_info_list( device_count); _GET_DEVICE_INFO_LIST_DONE: - g_mutex_unlock(&g_device_info_lock); LOGD("ret 0x%x", ret); if (ret != VISION_SOURCE_ERROR_NONE) @@ -371,6 +367,101 @@ static void __vision_source_release_handle(vision_source_v4l2_s *handle) return; } +static int __vision_source_v4l2_stream(int device_fd, int type, gboolean onoff) +{ + if (device_fd < 0) { + LOGE("invalid fd %d", device_fd); + return VISION_SOURCE_ERROR_INVALID_PARAMETER; + } + + if (v4l2_ioctl(device_fd, onoff ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, + &type) < 0) { + LOGE("stream %d failed. [t:%d] errno %d", onoff, type, errno); + return VISION_SOURCE_ERROR_INTERNAL; + } + + LOGD("stream %d done [t:%d]", onoff, type); + + return VISION_SOURCE_ERROR_NONE; +} + +static int __vision_source_v4l2_reqbufs(int device_fd, int type, int memory, + uint32_t count, uint32_t *result_count) +{ + struct v4l2_requestbuffers v4l2_reqbuf; + + if (device_fd < 0) { + LOGE("invalid fd %d", device_fd); + return VISION_SOURCE_ERROR_INVALID_PARAMETER; + } + + if (!result_count) { + LOGE("NULL parameter"); + return VISION_SOURCE_ERROR_INVALID_PARAMETER; + } + + memset(&v4l2_reqbuf, 0x0, sizeof(struct v4l2_requestbuffers)); + + v4l2_reqbuf.type = type; + v4l2_reqbuf.memory = memory; + v4l2_reqbuf.count = count; + + if (v4l2_ioctl(device_fd, VIDIOC_REQBUFS, &v4l2_reqbuf) < 0) { + LOGE("REQBUFS[count %d] failed. errno %d", count, errno); + return VISION_SOURCE_ERROR_INTERNAL; + } + + if (v4l2_reqbuf.count != count) + LOGW("different count [req:%d, result:%d]", count, v4l2_reqbuf.count); + + *result_count = v4l2_reqbuf.count; + + return VISION_SOURCE_ERROR_NONE; +} + +static int __vision_source_stop_stream(vision_source_v4l2_s *handle, + uint32_t buffer_count) +{ + int i = 0; + int ret = VISION_SOURCE_ERROR_NONE; + + if (!handle) { + LOGE("NULL handle"); + return VISION_SOURCE_ERROR_INVALID_PARAMETER; + } + + LOGD("buffer count[%d]", buffer_count); + + /* stream off */ + ret = __vision_source_v4l2_stream(handle->device_fd, handle->buffer_type, + FALSE); + + LOGD("stream off : 0x%x", ret); + + /* munmap */ + for (i = 0; i < buffer_count; i++) { + if (handle->vision_source_buffers[i].planes[0].data != NULL) { + LOGW("munmap %p", handle->vision_source_buffers[i].planes[0].data); + + v4l2_munmap(handle->vision_source_buffers[i].planes[0].data, + handle->vision_source_buffers[i].planes[0].size); + + handle->vision_source_buffers[i].planes[0].data = 0; + handle->vision_source_buffers[i].planes[0].size = 0; + } else { + LOGW("NULL data [index %d]", i); + } + } + + /* reqbufs 0 */ + ret = __vision_source_v4l2_reqbufs(handle->device_fd, handle->buffer_type, + V4L2_MEMORY_MMAP, 0, &buffer_count); + + LOGD("reqbufs 0 : 0x%x", ret); + + return ret; +} + int vision_source_v4l2_init(vision_source_h *handle) { LOGD("enter"); @@ -384,15 +475,19 @@ int vision_source_v4l2_init(vision_source_h *handle) return VISION_SOURCE_ERROR_INTERNAL; } + int ret = __vision_source_get_device_info_list( + &v4l2_handle->device_info_list); + + if (ret != VISION_SOURCE_ERROR_NONE) { + g_free(v4l2_handle); + LOGE("get device info failed"); + return ret; + } + g_mutex_init(&v4l2_handle->lock); g_mutex_init(&v4l2_handle->buffer_lock); g_cond_init(&v4l2_handle->buffer_cond); - v4l2_handle->device_index = CAMERA_HAL_INITIAL_INDEX; - v4l2_handle->device_fd = CAMERA_HAL_INITIAL_FD; - v4l2_handle->buffer_thread = NULL; - v4l2_handle->device_info_list = NULL; - *handle = v4l2_handle; return VISION_SOURCE_ERROR_NONE; @@ -419,19 +514,103 @@ int vision_source_v4l2_enumerate_devices( VISION_SOURCE_NULL_ARG_CHECK(info_list); vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle; - int ret; - if (!v4l2_handle->device_info_list) - ret = __vision_source_get_device_info_list( + if (!v4l2_handle->device_info_list) { + int ret = __vision_source_get_device_info_list( &v4l2_handle->device_info_list); - if (ret != VISION_SOURCE_ERROR_NONE) { - LOGE("get device info failed"); - return ret; + if (ret != VISION_SOURCE_ERROR_NONE) { + LOGE("get device info failed"); + return ret; + } } memcpy(info_list, v4l2_handle->device_info_list, sizeof(vision_source_device_info_list_s)); + + return VISION_SOURCE_ERROR_NONE; +} + +int vision_source_v4l2_open_device(vision_source_h handle, int device_index) +{ + VISION_SOURCE_NULL_ARG_CHECK(handle); + + int device_fd = CAMERA_HAL_INITIAL_FD; +#ifdef HAVE_LIBV4L2 + int libv4l2_fd = CAMERA_HAL_INITIAL_FD; +#endif /* HAVE_LIBV4L2 */ + vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle; + + g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&v4l2_handle->lock); + + if (!v4l2_handle->device_info_list) { + LOGE("NO DEVICE INFO"); + return VISION_SOURCE_ERROR_INTERNAL; + } + + if (device_index >= v4l2_handle->device_info_list->count) { + LOGE("invalid index %d [info:%d]", device_index, + v4l2_handle->device_info_list->count); + return VISION_SOURCE_ERROR_INVALID_PARAMETER; + } + + char *node_path = + v4l2_handle->device_info_list->device_info[device_index].node_path; + + device_fd = open(node_path, O_RDWR); + if (device_fd < 0) { + LOGE("open [%s] failed [errno %d]", node_path, errno); + return VISION_SOURCE_ERROR_INTERNAL; + } + + if (g_device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) + v4l2_handle->buffer_type = V4L2_CAP_VIDEO_CAPTURE_MPLANE; + else + v4l2_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 */ + + v4l2_handle->device_index = device_index; + v4l2_handle->device_fd = device_fd; + + LOGD("[%d] device[%s] opened [fd %d, type %d]", device_index, node_path, + device_fd, v4l2_handle->buffer_type); + + return VISION_SOURCE_ERROR_NONE; +} + +int vision_source_v4l2_close_device(vision_source_h handle) +{ + VISION_SOURCE_NULL_ARG_CHECK(handle); + vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle; + + g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&v4l2_handle->lock); + + int ret = + __vision_source_stop_stream(v4l2_handle, v4l2_handle->buffer_count); + if (ret != VISION_SOURCE_ERROR_NONE) { + LOGE("failed to stop stream"); + return ret; + } + + if (v4l2_handle->device_fd >= 0) { + LOGD("close fd %d", v4l2_handle->device_fd); + + v4l2_close(v4l2_handle->device_fd); + v4l2_handle->device_fd = CAMERA_HAL_INITIAL_FD; + } else { + LOGW("invalid fd %d", v4l2_handle->device_fd); + } + + LOGD("device [%d] closed", v4l2_handle->device_index); + return VISION_SOURCE_ERROR_NONE; } @@ -440,4 +619,6 @@ void attach_backend(vision_source_func_s *funcp) funcp->init = vision_source_v4l2_init; funcp->exit = vision_source_v4l2_exit; funcp->enumerate_devices = vision_source_v4l2_enumerate_devices; + funcp->open_device = vision_source_v4l2_open_device; + funcp->close_device = vision_source_v4l2_close_device; } \ No newline at end of file diff --git a/test/test_vision_source_v4l2.cpp b/test/test_vision_source_v4l2.cpp index 8ea0f42..5dfa5f0 100644 --- a/test/test_vision_source_v4l2.cpp +++ b/test/test_vision_source_v4l2.cpp @@ -22,4 +22,11 @@ TEST_F(VisionV4L2, EnumerateDev) ASSERT_EQ(vision_source_enumerate_devices(ms_handle, &dev_list), VISION_SOURCE_ERROR_NONE); EXPECT_GT(dev_list.count, 0); +} + +TEST_F(VisionV4L2, OpenDev0) +{ + ASSERT_EQ(vision_source_open_device(ms_handle, 0), + VISION_SOURCE_ERROR_NONE); + EXPECT_EQ(vision_source_close_device(ms_handle), VISION_SOURCE_ERROR_NONE); } \ No newline at end of file