From: Kwanghoon Son Date: Thu, 21 Jul 2022 05:13:16 +0000 (-0400) Subject: Init vision-source-v4l2 project X-Git-Tag: submit/tizen/20220721.051349^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=16a2d11e7a493615cd9b6a014b4ba7f55ea49e59;p=platform%2Fcore%2Fmultimedia%2Fvision-source-v4l2.git Init vision-source-v4l2 project Change-Id: I813ee119602263852ba79364d4f0da9688e0085f Signed-off-by: Kwanghoon Son --- diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b98e204 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.0.0) +project(vision-source-v4l2) + +OPTION(HAVE_LIBV4L2 "Option description" OFF) + +include(FindPkgConfig) +if(HAVE_LIBV4L2) + add_definitions(-DHAVE_LIBV4L2) + pkg_check_modules(${PROJECT_NAME}_DEP REQUIRED libv4l2 dlog vision-source glib-2.0) +else() + pkg_check_modules(${PROJECT_NAME}_DEP REQUIRED dlog vision-source glib-2.0) +endif() + +add_library(${PROJECT_NAME} + src/vision_source_v4l2.c +) + +target_link_libraries(${PROJECT_NAME} + ${${PROJECT_NAME}_DEP_LIBRARIES} +) +target_include_directories(${PROJECT_NAME} PUBLIC ${${PROJECT_NAME}_DEP_INCLUDE_DIRS}) + +# install packages +install(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR}) + +add_subdirectory(test) \ No newline at end of file diff --git a/LICENSE.APLv2 b/LICENSE.APLv2 new file mode 100644 index 0000000..7d4506d --- /dev/null +++ b/LICENSE.APLv2 @@ -0,0 +1,204 @@ +Copyright (c) 2000 - 2022 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + diff --git a/packaging/vision-source-v4l2.spec b/packaging/vision-source-v4l2.spec new file mode 100644 index 0000000..64444b9 --- /dev/null +++ b/packaging/vision-source-v4l2.spec @@ -0,0 +1,52 @@ +%define enable_libv4l2 1 + +Name: vision-source-v4l2 +Summary: vision source-v4l2 +Version: 0.0.1 +Release: 0 +Group: Multimedia/Framework +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz + +BuildRequires: cmake +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(libtbm) +BuildRequires: pkgconfig(iniparser) +BuildRequires: pkgconfig(vision-source) +BuildRequires: gtest-devel +%if 0%{?enable_libv4l2} +BuildRequires: pkgconfig(libv4l2) +%endif + +%description +Vision source v4l2 + +%prep +%setup -q + +%build +%if 0%{?sec_build_binary_debug_enable} +export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE" +export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" +%endif + +%cmake \ +%if 0%{?enable_libv4l2} + -DHAVE_LIBV4L2=ON \ +%endif +. + +make %{?jobs:-j%jobs} + +%install + +%make_install + +%post -p /sbin/ldconfig +%postun -p /sbin/ldconfig + +%files +%{_libdir}/*.so +%{_bindir}/* +%license LICENSE.APLv2 diff --git a/src/vision_source_v4l2.c b/src/vision_source_v4l2.c new file mode 100644 index 0000000..c04aad1 --- /dev/null +++ b/src/vision_source_v4l2.c @@ -0,0 +1,433 @@ +/* + * vision_source_v4l2.c + * + * Copyright (c) 2022 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. + * + * Most of code is from hal_camera_v4l2 + */ + +#include +#include +#include + +#include "vision_source_v4l2_private.h" + +#define DEVICE_NODE_PATH_MAX 16 +#define DEVICE_NODE_PATH_PREFIX "/dev/video" +#define FOURCC_FORMAT "%c%c%c%c" +#define FOURCC_CONVERT(fourcc) \ + fourcc & 0xff, (fourcc >> 8) & 0xff, (fourcc >> 16) & 0xff, \ + (fourcc >> 24) & 0xff + +static vision_source_device_info_list_s *g_device_info_list; +static guint32 g_device_caps; +static GMutex g_device_info_lock; + +static int __vision_source_get_format(guint32 fourcc, int *pixel_format) +{ + if (!pixel_format) { + LOGE("NULL parameter"); + return VISION_SOURCE_ERROR_INVALID_PARAMETER; + } + + switch (fourcc) { + case V4L2_PIX_FMT_RGB24: + *pixel_format = VISION_SOURCE_PIXEL_FORMAT_RGB24; + break; + default: + LOGE("unknown fourcc " FOURCC_FORMAT, FOURCC_CONVERT(fourcc)); + return VISION_SOURCE_ERROR_INTERNAL; + } + + LOGD("fourcc " FOURCC_FORMAT " -> %d", FOURCC_CONVERT(fourcc), + *pixel_format); + + return VISION_SOURCE_ERROR_NONE; +} + +static int __vision_source_get_fourcc_plane_num(int pixel_format, + guint32 *fourcc, + guint32 *plane_num) +{ + if (!fourcc || !plane_num) { + LOGE("NULL parameter %p %p", fourcc, plane_num); + return VISION_SOURCE_ERROR_INVALID_PARAMETER; + } + + switch (pixel_format) { + case VISION_SOURCE_PIXEL_FORMAT_RGB24: + *fourcc = V4L2_PIX_FMT_RGB24; + *plane_num = 1; + break; + default: + LOGE("unknown format %d", pixel_format); + return VISION_SOURCE_ERROR_INTERNAL; + } + + LOGD("format %d -> fourcc " FOURCC_FORMAT, pixel_format, + FOURCC_CONVERT(*fourcc)); + + return VISION_SOURCE_ERROR_NONE; +} + +static void __vision_source_get_fps_list(int device_fd, guint32 pixel_format, + int width, int height, + vision_source_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 +__vision_source_get_device_info(int device_index, int device_fd, + vision_source_device_info_s *device_info, + char *node_path) +{ + int resolution_index = 0; + int resolution_count = 0; + int pixel_format = 0; + struct v4l2_fmtdesc v4l2_format; + struct v4l2_frmsizeenum v4l2_frame; + + if (device_fd < 0 || !device_info || !node_path) { + LOGE("invalid param %d %p %p", device_fd, device_info, node_path); + return VISION_SOURCE_ERROR_INVALID_PARAMETER; + } + + LOGD("Get Supported format and resolution"); + + int pixel_index = 0; + int pixel_count = 0; + + while (1) { + memset(&v4l2_format, 0x0, sizeof(struct v4l2_fmtdesc)); + + v4l2_format.index = pixel_index; + v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (v4l2_ioctl(device_fd, VIDIOC_ENUM_FMT, &v4l2_format) < 0) { + LOGW("\tformat : end of enumeration"); + break; + } + + LOGD("\tformat[%d] " FOURCC_FORMAT " (emulated:%d)", pixel_index, + FOURCC_CONVERT(v4l2_format.pixelformat), + ((v4l2_format.flags & V4L2_FMT_FLAG_EMULATED) ? 1 : 0)); + + if (__vision_source_get_format(v4l2_format.pixelformat, + &pixel_format) != + VISION_SOURCE_ERROR_NONE) { + pixel_index++; + continue; + } + + device_info->pixel_list.pixels[pixel_count].pixel_format = pixel_format; + + resolution_index = 0; + resolution_count = 0; + while (1) { + memset(&v4l2_frame, 0x0, sizeof(struct v4l2_frmsizeenum)); + + 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 "); + break; + } + + vision_source_resolution_match_fps_s *rmf = + &device_info->pixel_list.pixels[pixel_count] + .resolution_list.resolutions[resolution_count]; + + switch (v4l2_frame.type) { + case V4L2_FRMSIZE_TYPE_DISCRETE: + rmf->resolution.width = v4l2_frame.discrete.width; + rmf->resolution.height = v4l2_frame.discrete.height; + + LOGD("\t\tsize[%d] %ux%u", resolution_index, + v4l2_frame.discrete.width, v4l2_frame.discrete.height); + + __vision_source_get_fps_list(device_fd, v4l2_frame.pixel_format, + v4l2_frame.discrete.width, + v4l2_frame.discrete.height, + &rmf->fps_list); + resolution_count++; + break; + case V4L2_FRMSIZE_TYPE_CONTINUOUS: + LOGW("\t\tsize[%d] %ux%u - %ux%u", resolution_index, + 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)", + resolution_index, v4l2_frame.stepwise.min_width, + v4l2_frame.stepwise.min_height, + v4l2_frame.stepwise.max_width, + v4l2_frame.stepwise.max_height, + v4l2_frame.stepwise.step_width, + v4l2_frame.stepwise.step_height); + break; + default: + LOGE("\t\tunknown frame type %d", v4l2_frame.type); + break; + } + resolution_index++; + } + + device_info->pixel_list.pixels[pixel_count].resolution_list.count = + resolution_index; + LOGD("\t\tresolution count [%d]", resolution_index); + pixel_index++; + pixel_count++; + } + + device_info->index = device_index; + device_info->pixel_list.count = pixel_count; + snprintf(device_info->name, sizeof(device_info->name), "V4L2_CAMERA"); + snprintf(device_info->node_path, sizeof(device_info->node_path), "%s", + node_path); + + LOGD("\tformat count [%d]", pixel_count); + + return VISION_SOURCE_ERROR_NONE; +} + +static int __vision_source_get_device_info_list(void) +{ + int i = 0; + 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; + vision_source_device_info_list_s *device_info_list = NULL; + + g_mutex_lock(&g_device_info_lock); + + if (g_device_info_list) { + LOGD("device info list is already existed"); + ret = VISION_SOURCE_ERROR_NONE; + goto _GET_DEVICE_INFO_LIST_DONE; + } + + device_info_list = g_new0(vision_source_device_info_list_s, 1); + if (!device_info_list) { + LOGE("failed to alloc device info structure"); + ret = VISION_SOURCE_ERROR_INTERNAL; + goto _GET_DEVICE_INFO_LIST_DONE; + } + + memset(&glob_buf, 0x0, sizeof(glob_t)); + + ret = glob(DEVICE_NODE_PATH_PREFIX "*", 0, 0, &glob_buf); + if (ret != 0) { + switch (ret) { + case GLOB_NOSPACE: + LOGE("out of memory"); + ret = VISION_SOURCE_ERROR_INTERNAL; + goto _GET_DEVICE_INFO_LIST_DONE; + case GLOB_ABORTED: + LOGE("read error"); + ret = VISION_SOURCE_ERROR_INTERNAL; + goto _GET_DEVICE_INFO_LIST_DONE; + case GLOB_NOMATCH: + LOGE("match not found"); + ret = VISION_SOURCE_ERROR_INTERNAL; + goto _GET_DEVICE_INFO_LIST_DONE; + default: + LOGE("unknown error : %d", ret); + ret = VISION_SOURCE_ERROR_INTERNAL; + goto _GET_DEVICE_INFO_LIST_DONE; + } + } + + LOGD("device node count : %zu", glob_buf.gl_pathc); + + for (i = 0; i < glob_buf.gl_pathc; i++) { + LOGD("[%d] check device [%s]", i, glob_buf.gl_pathv[i]); + + device_fd = open(glob_buf.gl_pathv[i], O_RDWR); + if (device_fd < 0) { + LOGE("open failed [%s] errno %d", glob_buf.gl_pathv[i], errno); + 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 (v4l2_ioctl(device_fd, VIDIOC_QUERYCAP, &v4l2_cap) < 0) { + LOGE("querycap failed. errno %d", errno); + v4l2_close(device_fd); + continue; + } + + if (v4l2_cap.capabilities & V4L2_CAP_DEVICE_CAPS) + g_device_caps = v4l2_cap.device_caps; + else + g_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); + v4l2_close(device_fd); + continue; + } + + ret = __vision_source_get_device_info( + device_count, device_fd, + &device_info_list->device_info[device_count], + glob_buf.gl_pathv[i]); + + v4l2_close(device_fd); + + if (ret == VISION_SOURCE_ERROR_NONE) + device_count++; + } + + device_info_list->count = device_count; + g_device_info_list = device_info_list; + + LOGD("new g_device_info_list %p - device count %d", g_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) + g_free(device_info_list); + + return ret; +} + +static void __vision_source_release_handle(vision_source_v4l2_s *handle) +{ + if (!handle) { + LOGW("NULL handle"); + return; + } + + g_mutex_clear(&handle->lock); + g_mutex_clear(&handle->buffer_lock); + g_cond_clear(&handle->buffer_cond); + + LOGD("vision_source_v4l2_s %p destroy", handle); + + g_free(handle); + + return; +} + +int vision_source_v4l2_init(vision_source_h *handle) +{ + LOGD("enter"); + + VISION_SOURCE_NULL_ARG_CHECK(handle); + + vision_source_v4l2_s *v4l2_handle = g_new0(vision_source_v4l2_s, 1); + if (!v4l2_handle) { + LOGE("failed to alloc camera hal handle"); + // tbm_bufmgr_deinit(bufmgr); + return VISION_SOURCE_ERROR_INTERNAL; + } + + 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; + + int ret = __vision_source_get_device_info_list(); + if (ret != VISION_SOURCE_ERROR_NONE) { + LOGE("get device info failed"); + goto _INIT_ERROR; + } + + *handle = v4l2_handle; + + return VISION_SOURCE_ERROR_NONE; + +_INIT_ERROR: + __vision_source_release_handle(v4l2_handle); + + return ret; +} + +int vision_source_v4l2_exit(vision_source_h handle) +{ + if (!handle) { + LOGE("NULL handle"); + return VISION_SOURCE_ERROR_INVALID_PARAMETER; + } + + vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle; + + __vision_source_release_handle(v4l2_handle); + + return VISION_SOURCE_ERROR_NONE; +} + +void attach_backend(vision_source_func_s *funcp) +{ + funcp->init = vision_source_v4l2_init; + funcp->exit = vision_source_v4l2_exit; +} diff --git a/src/vision_source_v4l2_private.h b/src/vision_source_v4l2_private.h new file mode 100644 index 0000000..b9a6163 --- /dev/null +++ b/src/vision_source_v4l2_private.h @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2022s 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 __VISION_SOURCE_V4L2_PRIVATE_H__ +#define __VISION_SOURCE_V4L2_PRIVATE_H__ + +#include +#include +#include +#include +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#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 LOG_TAG "VISION_SOURCE_V4L2" + +#define VISION_SOURCE_CHECK_CONDITION(condition, error, msg) \ + do { \ + if (!(condition)) { \ + LOGE("[%s] %s(0x%08x)", __FUNCTION__, msg, error); \ + return error; \ + } \ + } while (0) + +#define VISION_SOURCE_NULL_ARG_CHECK(arg) \ + VISION_SOURCE_CHECK_CONDITION(arg != NULL, \ + VISION_SOURCE_ERROR_INVALID_PARAMETER, \ + "VISION_SOURCE_ERROR_INVALID_PARAMETER") + +#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 +#define EXTRA_PREVIEW_STREAM_MAX 10 + +typedef struct _vision_source_v4l2_s +{ + /* device */ + gint32 device_index; + gint32 device_fd; + + /* buffer */ + guint32 buffer_dequeued_count; + GThread *buffer_thread; + gboolean buffer_thread_run; + guint32 buffer_count; + struct vision_source_buffer vision_source_buffers[BUFFER_MAX]; + enum v4l2_buf_type buffer_type; + GMutex buffer_lock; + GCond buffer_cond; + + /* stream */ + struct vision_source_format stream_format; + + /* etc */ + GMutex lock; +} vision_source_v4l2_s; + +#endif /* __VISION_SOURCE_V4L2_PRIVATE_H__ */ \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..dbd2184 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.0.0) +project(test-vision-source-v4l2) + +include(FindPkgConfig) +pkg_check_modules(${PROJECT_NAME}_DEP REQUIRED vision-source) + +add_executable(${PROJECT_NAME} + test_vision_source_v4l2.cpp +) + +target_link_libraries(${PROJECT_NAME} + ${${PROJECT_NAME}_DEP_LIBRARIES} + gtest gtest_main +) +target_include_directories(${PROJECT_NAME} PUBLIC ${${PROJECT_NAME}_DEP_INCLUDE_DIRS}) + +# install packages +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) \ No newline at end of file diff --git a/test/test_vision_source_v4l2.cpp b/test/test_vision_source_v4l2.cpp new file mode 100644 index 0000000..15a9584 --- /dev/null +++ b/test/test_vision_source_v4l2.cpp @@ -0,0 +1,22 @@ +#include +#include + +class VisionV4L2 : public ::testing::Test +{ +protected: + void SetUp() override + { + ASSERT_EQ(vision_source_init(&ms_handle), VISION_SOURCE_ERROR_NONE); + } + + void TearDown() override + { + ASSERT_EQ(vision_source_exit(ms_handle), VISION_SOURCE_ERROR_NONE); + } + vision_source_h ms_handle; +}; + +TEST_F(VisionV4L2, Base) +{ + ASSERT_EQ(1, 1); +} \ No newline at end of file