Support vision-source 1.0.0 API
authorKwanghoon Son <k.son@samsung.com>
Wed, 18 Oct 2023 05:54:01 +0000 (14:54 +0900)
committerKwanghoon Son <k.son@samsung.com>
Thu, 19 Oct 2023 10:01:57 +0000 (19:01 +0900)
[Version] 1.0.0

Change-Id: I8687a05b9c1d88f51270311620052157a6393bba
Signed-off-by: Kwanghoon Son <k.son@samsung.com>
.clang-format
CMakeLists.txt
README.md [new file with mode: 0644]
packaging/vision-source-v4l2.spec
src/vision_source_v4l2.c [deleted file]
src/vision_source_v4l2.cpp [new file with mode: 0644]
src/vision_source_v4l2_private.h [deleted file]
test/CMakeLists.txt
test/test_vision_source_v4l2.cpp

index f50fddb065b41114d7c395aded9f3fcd244d9ad4..3ef5589bae8eb0110f82558d17615ffb92c22ee3 100644 (file)
@@ -5,10 +5,10 @@ Language:        Cpp
 
 #########################################
 # Turn off build breakable
-FixNamespaceComments: false
-ReflowComments:  false
-SortIncludes:    false # can break build; turning off
-SortUsingDeclarations: false # can break build; turning off
+FixNamespaceComments: true
+ReflowComments:  true
+SortIncludes:    true # can break build; turning off
+SortUsingDeclarations: true # can break build; turning off
 
 
 # Enterprise guide
@@ -38,22 +38,22 @@ BraceWrapping:
   BeforeElse:      false
 
   # M16
-  AfterEnum:       true
-  AfterStruct:     true
-  AfterUnion:      true
+  AfterEnum:       false
+  AfterStruct:     false
+  AfterUnion:      false
 
   # by inquiry
   AfterClass:      true
   AfterNamespace:  true
   AfterObjCDeclaration: true
-  AfterExternBlock: true
+  AfterExternBlock: false # mediavision want false
   IndentBraces:    false
   SplitEmptyFunction: false
   SplitEmptyRecord: false
   SplitEmptyNamespace: false
 
 # from pptx
-ColumnLimit:     80
+ColumnLimit:     120 # mediavision want 120
 
 # M11
 SpaceAfterCStyleCast: true
@@ -87,7 +87,7 @@ ConstructorInitializerIndentWidth: 8
 ContinuationIndentWidth: 8
 Cpp11BracedListStyle: false
 KeepEmptyLinesAtTheStartOfBlocks: false
-NamespaceIndentation: Inner
+NamespaceIndentation: None # mediavision want None
 PenaltyBreakAssignment: 10
 PenaltyBreakBeforeFirstCallParameter: 30
 PenaltyBreakComment: 10
index 7efd88a26761f0251b9d1b067090fa42e169f2ac..3223b7fb8faa04eb39191a1c7a3111fe268f3647 100644 (file)
@@ -1,29 +1,45 @@
 cmake_minimum_required(VERSION 3.0.0)
 project(vision-source-v4l2)
 
-OPTION(HAVE_LIBV4L2 "USE libv4l2" OFF)
-OPTION(BUILD_TEST "Build test binary" OFF)
+option(HAVE_LIBV4L2 "Option description" OFF)
+option(BUILD_TEST "Build test binary" 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()
 
+message("PROJECT_NAME = ${PROJECT_NAME}")
 add_library(${PROJECT_NAME}
-    src/vision_source_v4l2.c
+    src/vision_source_v4l2.cpp
 )
 
-target_link_libraries(${PROJECT_NAME}
+set(LIB_DEP dlog capi-media-tool)
+
+if(BUILD_TEST)
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -ggdb")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -ggdb")
+else()
+    target_compile_definitions(${PROJECT_NAME} PRIVATE -DUSE_DL)
+    list(APPEND LIB_DEP vision-source)
+endif()
+
+if(HAVE_LIBV4L2)
+    target_compile_definitions(${PROJECT_NAME} PRIVATE -DHAVE_LIBV4L2)
+    list(APPEND LIB_DEP libv4l2)
+endif()
+
+pkg_check_modules(${PROJECT_NAME}_DEP REQUIRED ${LIB_DEP})
+
+target_link_libraries(${PROJECT_NAME} PUBLIC
     ${${PROJECT_NAME}_DEP_LIBRARIES}
 )
-target_include_directories(${PROJECT_NAME} PUBLIC ${${PROJECT_NAME}_DEP_INCLUDE_DIRS})
+
+target_include_directories(${PROJECT_NAME} PRIVATE
+    ${${PROJECT_NAME}_DEP_INCLUDE_DIRS}
+    /usr/include/media
+)
 
 # install packages
 install(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR})
 
 if(BUILD_TEST)
-add_subdirectory(test)
-endif()
\ No newline at end of file
+    add_subdirectory(test)
+endif()
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..f146db2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,13 @@
+# vision-source-v4l2
+
+## build option
+HAVE_LIBV4L2 - libv4l2 is LGPL. default is off
+BUILD_TEST - compiler optimazation -O0 -ggdb , NOT used dlopen
+
+## TODO
+- [ ] refactoring vision_source_v4l2_s
+- [ ] multi-handler, multi-thread
+- [ ] resource management when stop called.
+- [ ] refactoring function names
+- [ ] runtime format change
+- [ ] support more format
index 24968a0a90b89a0118569c9cd71e93ca55033566..2ecbb7ad2b0fcc6f240410020fea583f9271f09a 100644 (file)
@@ -1,24 +1,28 @@
-%define enable_libv4l2 1
+%define enable_libv4l2 0
+%define build_test 0
 
 Name:        vision-source-v4l2
 Summary:     vision source-v4l2
-Version:     0.0.7
+Version:     1.0.0
 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: pkgconfig(capi-media-tool)
-BuildRequires: gtest-devel
 %if 0%{?enable_libv4l2}
 BuildRequires:  pkgconfig(libv4l2)
 %endif
+%if 0%{?build_test}
+BuildRequires: gtest-devel
+BuildRequires: vision-source-devel
+%else
+BuildRequires: pkgconfig(vision-source)
+%endif # build_test
 
 %description
 Vision source v4l2
@@ -36,6 +40,9 @@ export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE"
 %if 0%{?enable_libv4l2}
        -DHAVE_LIBV4L2=ON \
 %endif
+%if 0%{?build_test}
+       -DBUILD_TEST=ON \
+%endif # build_test
 .
 
 make %{?jobs:-j%jobs}
@@ -49,4 +56,7 @@ make %{?jobs:-j%jobs}
 
 %files
 %{_libdir}/*.so
+%if 0%{?build_test}
+%{_bindir}/*
+%endif # build_test
 %license LICENSE.APLv2
diff --git a/src/vision_source_v4l2.c b/src/vision_source_v4l2.c
deleted file mode 100644 (file)
index b58d7e0..0000000
+++ /dev/null
@@ -1,1193 +0,0 @@
-/*
- * 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 <glob.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-
-#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 guint32 g_device_caps;
-
-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_v4l2_qbuf(int device_fd, int type, int memory,
-                                                                        int index)
-{
-       struct v4l2_buffer v4l2_buf;
-       struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX];
-
-       if (device_fd < 0) {
-               LOGE("invalid fd %d", device_fd);
-               return VISION_SOURCE_ERROR_INVALID_PARAMETER;
-       }
-
-       memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer));
-       memset(v4l2_planes, 0x0, sizeof(v4l2_planes));
-
-       v4l2_buf.index = index;
-       v4l2_buf.type = type;
-       v4l2_buf.memory = memory;
-       v4l2_buf.m.planes = v4l2_planes;
-
-       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 VISION_SOURCE_ERROR_INTERNAL;
-       }
-
-       /*LOGD("QBUF done [i: %d, t: %d, m: %d]", index, type, memory);*/
-
-       return VISION_SOURCE_ERROR_NONE;
-}
-
-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(
-               vision_source_device_info_list_s **h_device_info_list)
-{
-       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;
-
-       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;
-       *h_device_info_list = device_info_list;
-
-       LOGD("new h_device_info_list %p - device count %d", *h_device_info_list,
-                device_count);
-
-_GET_DEVICE_INFO_LIST_DONE:
-       LOGD("ret 0x%x", ret);
-       globfree(&glob_buf);
-
-       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);
-       if (handle->device_info_list)
-               g_free(handle->device_info_list);
-
-       LOGD("vision_source_v4l2_s %p destroy", handle);
-
-       g_free(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;
-}
-
-static int __vision_source_set_stream(vision_source_v4l2_s *handle,
-                                                                         vision_source_pixel_format_e pixel_format,
-                                                                         vision_source_resolution_s *resolution,
-                                                                         uint32_t fps,
-                                                                         uint32_t request_buffer_count)
-{
-       struct v4l2_format v4l2_fmt;
-       struct v4l2_streamparm v4l2_parm;
-
-       guint32 fourcc = 0;
-       guint32 plane_num = 0;
-
-       if (!handle || !resolution) {
-               LOGE("NULL param %p %p", handle, resolution);
-               return VISION_SOURCE_ERROR_INTERNAL;
-       }
-
-       /* S_FMT */
-       int ret = __vision_source_get_fourcc_plane_num(pixel_format, &fourcc,
-                                                                                                  &plane_num);
-       if (ret != VISION_SOURCE_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 (v4l2_ioctl(handle->device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
-               LOGE("S_FMT failed. errno %d", errno);
-               return VISION_SOURCE_ERROR_INTERNAL;
-       }
-
-       if (V4L2_TYPE_IS_MULTIPLANAR(handle->buffer_type)) {
-               for (int 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 {
-               for (int i = 0; i < request_buffer_count; i++) {
-                       handle->vision_source_buffers[i].planes[0].align_width =
-                                       v4l2_fmt.fmt.pix.bytesperline;
-                       handle->vision_source_buffers[i].planes[0].size =
-                                       v4l2_fmt.fmt.pix.sizeimage;
-               }
-               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));
-
-       v4l2_parm.type = handle->buffer_type;
-
-       if (v4l2_ioctl(handle->device_fd, VIDIOC_G_PARM, &v4l2_parm) < 0) {
-               LOGE("G_PARM failed. errno %d", errno);
-               return VISION_SOURCE_ERROR_INTERNAL;
-       }
-
-       /* S_PARM to set fps */
-       v4l2_parm.parm.capture.timeperframe.numerator = 1;
-       v4l2_parm.parm.capture.timeperframe.denominator = fps;
-
-       if (v4l2_ioctl(handle->device_fd, VIDIOC_S_PARM, &v4l2_parm) < 0) {
-               LOGE("S_PARM failed. errno %d", errno);
-               return VISION_SOURCE_ERROR_INTERNAL;
-       }
-       return VISION_SOURCE_ERROR_NONE;
-}
-
-static int __vision_source_v4l2_dqbuf(int device_fd, int type, int memory,
-                                                                         int *index, unsigned int *used_size)
-{
-       int ret = VISION_SOURCE_ERROR_NONE;
-       struct v4l2_buffer v4l2_buf;
-       struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX];
-
-       if (device_fd < 0) {
-               LOGE("invalid fd %d", device_fd);
-               return VISION_SOURCE_ERROR_INVALID_PARAMETER;
-       }
-
-       if (!index) {
-               LOGE("NULL parameter");
-               return VISION_SOURCE_ERROR_INVALID_PARAMETER;
-       }
-
-       memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer));
-       memset(v4l2_planes, 0x0, sizeof(v4l2_planes));
-
-       v4l2_buf.type = type;
-       v4l2_buf.memory = memory;
-       v4l2_buf.m.planes = v4l2_planes;
-
-       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 VISION_SOURCE_ERROR_INTERNAL;
-               }
-       }
-
-       *index = v4l2_buf.index;
-       *used_size = v4l2_buf.bytesused;
-
-       return VISION_SOURCE_ERROR_NONE;
-}
-
-static int __vision_source_v4l2_wait_frame(int device_fd, int wait_time)
-{
-       int ret = VISION_SOURCE_ERROR_NONE;
-       fd_set fds;
-       struct timeval timeout;
-
-       if (device_fd < 0) {
-               LOGE("invalid fd %d", device_fd);
-               return VISION_SOURCE_ERROR_INVALID_PARAMETER;
-       }
-
-       FD_ZERO(&fds);
-       FD_SET(device_fd, &fds);
-
-       memset(&timeout, 0x0, sizeof(struct timeval));
-
-       timeout.tv_sec = wait_time;
-       timeout.tv_usec = 0;
-
-       /*LOGD("select : %d sec", wait_time);*/
-
-       ret = select(device_fd + 1, &fds, NULL, NULL, &timeout);
-       if (ret == -1) {
-               if (EINTR == errno) {
-                       LOGD("select error : EINTR");
-                       return VISION_SOURCE_ERROR_NONE;
-               }
-               LOGE("select failed. errno %d", errno);
-               return VISION_SOURCE_ERROR_INTERNAL;
-       }
-
-       if (ret == 0) {
-               LOGE("select timeout.");
-               return VISION_SOURCE_ERROR_INTERNAL;
-       }
-
-       /*LOGD("select done");*/
-
-       return VISION_SOURCE_ERROR_NONE;
-}
-
-static int
-__vision_source_start_stream(vision_source_v4l2_s *handle,
-                                                        vision_source_pixel_format_e pixel_format,
-                                                        vision_source_resolution_s *resolution,
-                                                        uint32_t fps, uint32_t request_buffer_count)
-{
-       vision_source_buffer_s *buffer = NULL;
-       struct v4l2_buffer v4l2_buf;
-       struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX];
-
-       int ret = __vision_source_set_stream(handle, pixel_format, resolution, fps,
-                                                                                request_buffer_count);
-       if (ret != VISION_SOURCE_ERROR_NONE) {
-               return ret;
-       }
-
-       /* request buffer */
-       ret = __vision_source_v4l2_reqbufs(handle->device_fd, handle->buffer_type,
-                                                                          V4L2_MEMORY_MMAP, request_buffer_count,
-                                                                          &handle->buffer_count);
-       if (ret != VISION_SOURCE_ERROR_NONE) {
-               return ret;
-       }
-
-       LOGD("buffer count : request %d -> result %d", request_buffer_count,
-                handle->buffer_count);
-
-       /* query buffer, mmap and qbuf */
-       for (int 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->buffer_type;
-               v4l2_buf.memory = V4L2_MEMORY_MMAP;
-               v4l2_buf.index = i;
-               v4l2_buf.m.planes = v4l2_planes;
-               v4l2_buf.length = 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;
-               }
-
-               buffer = &handle->vision_source_buffers[i];
-
-               buffer->index = i;
-               buffer->pixel_format = pixel_format;
-               buffer->resolution.width = resolution->width;
-               buffer->resolution.height = resolution->height;
-
-               if (V4L2_TYPE_IS_MULTIPLANAR(handle->buffer_type)) {
-                       buffer->num_planes = v4l2_buf.length;
-               } else {
-                       buffer->num_planes = 1;
-                       buffer->planes[0].size = buffer->total_size = v4l2_buf.length;
-               }
-
-               buffer->planes[0].data =
-                               v4l2_mmap(0, v4l2_buf.length, PROT_READ | PROT_WRITE,
-                                                 MAP_SHARED, handle->device_fd, v4l2_buf.m.offset);
-
-               if (buffer->planes[0].data == MAP_FAILED) {
-                       LOGE("[%d] mmap failed (errno %d)", i, errno);
-                       goto _START_STREAM_FAILED;
-               }
-
-               if (__vision_source_v4l2_qbuf(handle->device_fd, handle->buffer_type,
-                                                                         V4L2_MEMORY_MMAP,
-                                                                         i) != VISION_SOURCE_ERROR_NONE) {
-                       LOGE("[%d] qbuf failed (errno %d)", i, errno);
-                       goto _START_STREAM_FAILED;
-               }
-       }
-
-       /* stream on */
-       ret = __vision_source_v4l2_stream(handle->device_fd, handle->buffer_type,
-                                                                         TRUE);
-       if (ret != VISION_SOURCE_ERROR_NONE) {
-               LOGE("stream on failed");
-               goto _START_STREAM_FAILED;
-       }
-
-       return VISION_SOURCE_ERROR_NONE;
-
-_START_STREAM_FAILED:
-       __vision_source_stop_stream(handle, handle->buffer_count);
-       return ret;
-}
-
-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;
-       }
-
-       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);
-
-       *handle = v4l2_handle;
-
-       return VISION_SOURCE_ERROR_NONE;
-}
-
-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;
-}
-
-int vision_source_v4l2_enumerate_devices(
-               vision_source_h handle, vision_source_device_info_list_s *info_list)
-{
-       VISION_SOURCE_NULL_ARG_CHECK(handle);
-       VISION_SOURCE_NULL_ARG_CHECK(info_list);
-
-       vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle;
-
-       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;
-               }
-       }
-
-       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;
-}
-
-int vision_source_v4l2_set_stream_format(vision_source_h handle,
-                                                                                vision_source_format_s *format)
-{
-       VISION_SOURCE_NULL_ARG_CHECK(handle);
-       VISION_SOURCE_NULL_ARG_CHECK(format);
-       vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle;
-       int i = 0;
-       int j = 0;
-       int ret = VISION_SOURCE_ERROR_NONE;
-       gboolean capability_check = FALSE;
-       vision_source_device_info_s *device_info = NULL;
-
-       g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&v4l2_handle->lock);
-
-       if (!v4l2_handle->device_info_list) {
-               LOGE("no device info list");
-               return VISION_SOURCE_ERROR_INTERNAL;
-       }
-
-       /* check capability */
-       device_info = &v4l2_handle->device_info_list
-                                                  ->device_info[v4l2_handle->device_index];
-
-       /* format */
-       for (i = 0; i < device_info->pixel_list.count; i++) {
-               if (format->pixel_format ==
-                       device_info->pixel_list.pixels[i].pixel_format) {
-                       LOGD("format matched %d, check resolution.", format->pixel_format);
-
-                       vision_source_resolution_match_fps_list_s *res_match =
-                                       &device_info->pixel_list.pixels[i].resolution_list;
-
-                       /* resolution */
-                       for (j = 0; j < res_match->count; j++) {
-                               if (format->resolution.width ==
-                                                       res_match->resolutions[j].resolution.width &&
-                                       format->resolution.height ==
-                                                       res_match->resolutions[j].resolution.height) {
-                                       LOGD("resolution matched %dx%d", format->resolution.width,
-                                                format->resolution.height);
-                                       capability_check = TRUE;
-                                       break;
-                               }
-                       }
-
-                       break;
-               }
-       }
-
-       if (!capability_check) {
-               LOGE("capability failed - %d, %dx%d", format->pixel_format,
-                        format->resolution.width, format->resolution.height);
-               return VISION_SOURCE_ERROR_INTERNAL;
-       }
-
-       /* compare with current settings */
-       if (v4l2_handle->stream_format.pixel_format == format->pixel_format &&
-               v4l2_handle->stream_format.resolution.width ==
-                               format->resolution.width &&
-               v4l2_handle->stream_format.resolution.height ==
-                               format->resolution.height &&
-               v4l2_handle->stream_format.fps == format->fps) {
-               LOGD("no need to restart preview stream");
-               return VISION_SOURCE_ERROR_NONE;
-       }
-
-       LOGD("Preview setting is changed. Restart preview now.");
-
-       /* stop preview stream to change it */
-       ret = __vision_source_stop_stream(v4l2_handle, v4l2_handle->buffer_count);
-       if (ret != VISION_SOURCE_ERROR_NONE) {
-               LOGE("failed to stop stream");
-               return ret;
-       }
-
-       ret = __vision_source_set_stream(v4l2_handle, format->pixel_format,
-                                                                        &format->resolution, format->fps,
-                                                                        BUFFER_MAX);
-       if (ret != VISION_SOURCE_ERROR_NONE) {
-               LOGE("failed to set stream");
-               return ret;
-       }
-
-       memcpy(&v4l2_handle->stream_format, format, sizeof(vision_source_format_s));
-
-       return VISION_SOURCE_ERROR_NONE;
-}
-
-static int __convert_buffer_to_fmt(vision_source_buffer_s *buffer,
-                                                                  media_format_h fmt)
-{
-       media_format_mimetype_e mime;
-       switch (buffer->pixel_format) {
-       case VISION_SOURCE_PIXEL_FORMAT_RGB24:
-               mime = MEDIA_FORMAT_RGB888;
-               break;
-
-       default:
-               LOGE("Not supported format %d", buffer->pixel_format);
-               return VISION_SOURCE_ERROR_INVALID_PARAMETER;
-       }
-       if (media_format_set_video_mime(fmt, mime) != MEDIA_FORMAT_ERROR_NONE)
-               return VISION_SOURCE_ERROR_INTERNAL;
-       media_format_set_video_width(fmt, buffer->resolution.width);
-       media_format_set_video_height(fmt, buffer->resolution.height);
-
-       return VISION_SOURCE_ERROR_NONE;
-}
-
-static void __pkt_dispose_cb(media_packet_h packet, void *user_data)
-{
-       packet_context_s *pkt_ctx = (packet_context_s *) user_data;
-       if (__vision_source_v4l2_qbuf(pkt_ctx->device_fd, pkt_ctx->type,
-                                                                 pkt_ctx->memory,
-                                                                 pkt_ctx->index) != VISION_SOURCE_ERROR_NONE) {
-               LOGE("qbuf failed with device_fd: %d, type: %d, memory: %d, index: %d",
-                        pkt_ctx->device_fd, pkt_ctx->type, pkt_ctx->memory,
-                        pkt_ctx->index);
-       }
-
-       free(pkt_ctx);
-}
-
-static media_packet_h __make_media_packet(vision_source_buffer_s *buffer,
-                                                                                 int device_fd, int buffer_type,
-                                                                                 int index)
-{
-       media_packet_h pkt;
-       media_format_h fmt;
-       media_format_create(&fmt);
-       if (__convert_buffer_to_fmt(buffer, fmt) != VISION_SOURCE_ERROR_NONE) {
-               media_format_unref(fmt);
-               return NULL;
-       }
-
-       packet_context_s *pkt_ctx =
-                       (packet_context_s *) malloc(sizeof(packet_context_s));
-       if (!pkt_ctx) {
-               LOGE("packet_context_s malloc failed");
-               media_format_unref(fmt);
-               return NULL;
-       }
-
-       pkt_ctx->device_fd = device_fd;
-       pkt_ctx->type = buffer_type;
-       pkt_ctx->memory = V4L2_MEMORY_MMAP;
-       pkt_ctx->index = index;
-
-       media_packet_new_from_external_memory(fmt, buffer->planes[0].data,
-                                                                                 buffer->planes[0].used_size,
-                                                                                 __pkt_dispose_cb, pkt_ctx, &pkt);
-
-       media_format_unref(fmt);
-       return pkt;
-}
-
-static void *__fetch_buffer_and_callback(gpointer data)
-{
-       vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) data;
-       int index;
-       unsigned int byte_size;
-
-       /* run buffer thread */
-       g_mutex_lock(&v4l2_handle->buffer_lock);
-
-       while (v4l2_handle->buffer_thread_run) {
-               g_mutex_unlock(&v4l2_handle->buffer_lock);
-
-               if (__vision_source_v4l2_wait_frame(v4l2_handle->device_fd, 5) !=
-                       VISION_SOURCE_ERROR_NONE) {
-                       LOGE("frame wait failed");
-                       g_mutex_lock(&v4l2_handle->buffer_lock);
-                       break;
-               }
-
-               g_mutex_lock(&v4l2_handle->buffer_lock);
-
-               if (v4l2_handle->buffer_thread_run == FALSE) {
-                       LOGW("stop buffer handler thread");
-                       break;
-               }
-               if (__vision_source_v4l2_dqbuf(v4l2_handle->device_fd,
-                                                                          v4l2_handle->buffer_type,
-                                                                          V4L2_MEMORY_MMAP, &index, &byte_size) !=
-                       VISION_SOURCE_ERROR_NONE) {
-                       LOGE("dqbuf failed");
-                       break;
-               }
-               g_mutex_unlock(&v4l2_handle->buffer_lock);
-               vision_source_buffer_s *buffer =
-                               &v4l2_handle->vision_source_buffers[index];
-               buffer->planes[0].used_size = byte_size;
-
-               if (v4l2_handle->stream_callback) {
-                       media_packet_h pkt =
-                                       __make_media_packet(buffer, v4l2_handle->device_fd,
-                                                                               v4l2_handle->buffer_type, index);
-                       if (!pkt)
-                               return NULL;
-                       v4l2_handle->stream_callback(pkt,
-                                                                                v4l2_handle->stream_callback_data);
-                       media_packet_unref(pkt);
-               }
-               sched_yield();
-
-               g_mutex_lock(&v4l2_handle->buffer_lock);
-       }
-
-       g_mutex_unlock(&v4l2_handle->buffer_lock);
-
-       return NULL;
-}
-
-int source_v4l2_start_stream(vision_source_h handle, stream_cb callback,
-                                                        void *user_data)
-{
-       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_start_stream(
-                       v4l2_handle, v4l2_handle->stream_format.pixel_format,
-                       &v4l2_handle->stream_format.resolution,
-                       v4l2_handle->stream_format.fps, BUFFER_MAX);
-       if (ret != VISION_SOURCE_ERROR_NONE) {
-               LOGE("__vision_source_start_stream failed[0x%x]", ret);
-               g_mutex_unlock(&v4l2_handle->lock);
-               return ret;
-       }
-
-       g_mutex_lock(&v4l2_handle->buffer_lock);
-
-       v4l2_handle->buffer_thread_run = TRUE;
-       v4l2_handle->stream_callback = callback;
-       v4l2_handle->stream_callback_data = user_data;
-
-       v4l2_handle->buffer_thread = g_thread_try_new("vision_source_buffer_thread",
-                                                                                                 __fetch_buffer_and_callback,
-                                                                                                 (gpointer) v4l2_handle, NULL);
-       if (!v4l2_handle->buffer_thread) {
-               LOGE("failed to create buffer handler thread");
-               g_mutex_unlock(&v4l2_handle->buffer_lock);
-               __vision_source_stop_stream(v4l2_handle, v4l2_handle->buffer_count);
-
-               return ret;
-       }
-
-       g_mutex_unlock(&v4l2_handle->buffer_lock);
-
-       LOGD("start preview done");
-
-       return VISION_SOURCE_ERROR_NONE;
-}
-
-int source_v4l2_stop_stream(vision_source_h handle)
-{
-       VISION_SOURCE_NULL_ARG_CHECK(handle);
-
-       vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle;
-
-       LOGD("start");
-       g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&v4l2_handle->lock);
-
-       g_mutex_lock(&v4l2_handle->buffer_lock);
-
-       v4l2_handle->buffer_thread_run = FALSE;
-
-       g_mutex_unlock(&v4l2_handle->buffer_lock);
-
-       int ret =
-                       __vision_source_stop_stream(v4l2_handle, v4l2_handle->buffer_count);
-
-       /* wait for preview thread exit */
-       if (v4l2_handle->buffer_thread)
-               g_thread_join(v4l2_handle->buffer_thread);
-       v4l2_handle->buffer_thread = NULL;
-
-       LOGD("stop preview done [0x%x]", ret);
-
-       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;
-       funcp->enumerate_devices = vision_source_v4l2_enumerate_devices;
-       funcp->open_device = vision_source_v4l2_open_device;
-       funcp->close_device = vision_source_v4l2_close_device;
-       funcp->set_stream_format = vision_source_v4l2_set_stream_format;
-       funcp->start_stream = source_v4l2_start_stream;
-       funcp->stop_stream = source_v4l2_stop_stream;
-}
\ No newline at end of file
diff --git a/src/vision_source_v4l2.cpp b/src/vision_source_v4l2.cpp
new file mode 100644 (file)
index 0000000..ce9f396
--- /dev/null
@@ -0,0 +1,980 @@
+/*
+ * vision_source_v4l2.c
+ *
+ * Copyright (c) 2022 - 2023 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 <algorithm>
+#include <atomic>
+#include <cstdint>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <dlog.h>
+#include <fcntl.h>
+#include <glob.h>
+#include <linux/videodev2.h>
+#include <media_packet.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <vision_source_interface.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "VISION_SOURCE_V4L2"
+#ifdef HAVE_LIBV4L2
+#include <libv4l2.h>
+#else
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#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 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 VISION_SOURCE_INITIAL_FD -1
+#define BUFFER_MAX 4
+
+#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
+
+#ifdef USE_DL
+#define vision_source_init vision_source_v4l2_init
+#define vision_source_exit vision_source_v4l2_exit
+#define vision_source_list_devices vision_source_v4l2_list_devices
+#define vision_source_get_device_cap vision_source_v4l2_get_device_cap
+#define vision_source_open_device vision_source_v4l2_open_device
+#define vision_source_close_device vision_source_v4l2_close_device
+#define vision_source_set_stream_format vision_source_v4l2_set_stream_format
+#define vision_source_start_stream vision_source_v4l2_start_stream
+#define vision_source_stop_stream vision_source_v4l2_stop_stream
+#define vision_source_set_stream_cb vision_source_v4l2_set_stream_cb
+#else
+#include <vision_source.h>
+#endif
+
+using namespace std;
+
+struct fmt_info {
+       media_format_mimetype_e type;
+       uint32_t width;
+       uint32_t height;
+       uint32_t fps;
+
+       bool operator==(const fmt_info &rhs)
+       {
+               return (type == rhs.type) && (width == rhs.width) && (height == rhs.height) && (fps == rhs.fps);
+       }
+};
+
+struct pkt_dispose_cb_data {
+       int fd;
+       int index;
+};
+
+struct vision_source_v4l2_s {
+       /* device */
+       vision_source_device_info_s *dev_info {};
+       media_format_h **fmt {};
+       vector<string> dev_name {};
+       vector<vector<fmt_info> > fmt_list {};
+
+       /* current user setting */
+       int device_index = VISION_SOURCE_INITIAL_FD;
+       int device_fd = VISION_SOURCE_INITIAL_FD;
+       int fmt_index = VISION_SOURCE_INITIAL_FD;
+       vision_source_status_e status;
+
+       /* buffer */
+       vector<v4l2_buffer> v4l2_buf {};
+       vector<void *> mmap_addr {};
+       struct pkt_dispose_cb_data pkt_data[BUFFER_MAX];
+
+       /* thead */
+       thread buffer_thread;
+       atomic_bool buffer_thread_run {};
+       stream_cb stream_callback {};
+       void *stream_user_data {};
+};
+
+static int __vision_source_get_format(uint32_t fourcc, int *pixel_format)
+{
+       switch (fourcc) {
+       case V4L2_PIX_FMT_RGB24:
+               *pixel_format = MEDIA_FORMAT_RGB888;
+               break;
+       case V4L2_PIX_FMT_YUYV:
+               *pixel_format = MEDIA_FORMAT_YUYV;
+               break;
+       case V4L2_PIX_FMT_NV12:
+               *pixel_format = MEDIA_FORMAT_NV12;
+               break;
+       case V4L2_PIX_FMT_NV21:
+               *pixel_format = MEDIA_FORMAT_NV21;
+               break;
+       default:
+               LOGW("unknown fourcc " FOURCC_FORMAT, FOURCC_CONVERT(fourcc));
+               return VISION_SOURCE_ERROR_NOT_SUPPORTED_FORMAT;
+       }
+
+       LOGD("fourcc " FOURCC_FORMAT " -> %d", FOURCC_CONVERT(fourcc), *pixel_format);
+
+       return VISION_SOURCE_ERROR_NONE;
+}
+
+static int __vision_source_get_fourcc_plane_num(media_format_mimetype_e pixel_format, uint32_t *fourcc)
+{
+       switch (pixel_format) {
+       case MEDIA_FORMAT_RGB888:
+               *fourcc = V4L2_PIX_FMT_RGB24;
+               break;
+       case MEDIA_FORMAT_YUYV:
+               *fourcc = V4L2_PIX_FMT_YUYV;
+               break;
+       case MEDIA_FORMAT_NV12:
+               *fourcc = V4L2_PIX_FMT_NV12;
+               break;
+       case MEDIA_FORMAT_NV21:
+               *fourcc = V4L2_PIX_FMT_NV21;
+               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 vector<uint32_t> __vision_source_get_fps_list(int device_fd, uint32_t pixel_format, int width, int height)
+{
+       vector<uint32_t> fps_list;
+       struct v4l2_frmivalenum ival;
+
+       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 fps_list;
+       }
+
+       if (ival.type != V4L2_FRMIVAL_TYPE_DISCRETE) {
+               LOGE("NOT V4L2_FRMIVAL_TYPE_DISCRETE -> [%u]", ival.type);
+               return fps_list;
+       }
+
+       do {
+               LOGI("\t\t\t\tFramerate[%u/%u]", ival.discrete.denominator, ival.discrete.numerator);
+               fps_list.push_back(ival.discrete.denominator);
+               ival.index++;
+       } while (v4l2_ioctl(device_fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) >= 0);
+
+       return fps_list;
+}
+
+static int __vision_source_v4l2_qbuf(int device_fd, int type, int memory, int index)
+{
+       struct v4l2_buffer v4l2_buf;
+
+       memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer));
+
+       v4l2_buf.index = index;
+       v4l2_buf.type = type;
+       v4l2_buf.memory = memory;
+
+       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 VISION_SOURCE_ERROR_INTERNAL;
+       }
+
+       // LOGD("QBUF done [i: %d, t: %d, m: %d]", index, type, memory);
+
+       return VISION_SOURCE_ERROR_NONE;
+}
+
+static int __vision_source_get_valid_fmt(int device_fd, vector<fmt_info> &found_fmt)
+{
+       int pixel_format = 0;
+       int pixel_index = 0;
+       int pixel_count = 0;
+
+       while (1) {
+               struct v4l2_fmtdesc v4l2_format;
+               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;
+               }
+
+               int resolution_index = 0;
+               int resolution_count = 0;
+
+               while (1) {
+                       struct v4l2_frmsizeenum v4l2_frame;
+                       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;
+                       }
+
+                       // TODO : support other type
+                       if (v4l2_frame.type != V4L2_FRMSIZE_TYPE_DISCRETE) {
+                               LOGW("\t\tframe type %d needs to support", v4l2_frame.type);
+                               return VISION_SOURCE_ERROR_NONE;
+                       }
+
+                       uint32_t width = v4l2_frame.discrete.width;
+                       uint32_t height = v4l2_frame.discrete.height;
+
+                       LOGD("\t\tsize[%d] %ux%u", resolution_index, width, height);
+
+                       auto fps_list = __vision_source_get_fps_list(device_fd, v4l2_frame.pixel_format, width, height);
+                       if (fps_list.empty()) {
+                               return VISION_SOURCE_ERROR_NOT_SUPPORTED_FORMAT;
+                       }
+                       resolution_count++;
+                       resolution_index++;
+
+                       for (auto fps : fps_list) {
+                               fmt_info fmt { (media_format_mimetype_e) pixel_format, width, height, fps };
+                               found_fmt.push_back(fmt);
+                       }
+               }
+
+               LOGD("\t\tresolution count [%d]", resolution_count);
+               pixel_index++;
+               pixel_count++;
+       }
+
+       LOGD("\tformat count [%d]", pixel_count);
+
+       return VISION_SOURCE_ERROR_NONE;
+}
+
+static int __dev_info_from_path(const char *path, vector<fmt_info> &fmt_list)
+{
+       LOGD("check device [%s]", path);
+       int ret = VISION_SOURCE_ERROR_NONE;
+
+       int device_fd = open(path, O_RDWR);
+       if (device_fd < 0) {
+               LOGE("open failed [%s] errno %d", path, errno);
+               return ret;
+       }
+
+#ifdef HAVE_LIBV4L2
+       int 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 > 0)
+               device_fd = libv4l2_fd;
+#endif /* HAVE_LIBV4L2 */
+
+       struct v4l2_capability v4l2_cap;
+       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);
+               return ret;
+       }
+
+       unsigned int dev_caps;
+
+       if (v4l2_cap.capabilities & V4L2_CAP_DEVICE_CAPS)
+               dev_caps = v4l2_cap.device_caps;
+       else
+               dev_caps = v4l2_cap.capabilities;
+
+       if (!(dev_caps & V4L2_CAP_VIDEO_CAPTURE) || (dev_caps & V4L2_CAP_VIDEO_OUTPUT)) {
+               LOGW("[%s] is not a capture device 0x%x", path, dev_caps);
+               v4l2_close(device_fd);
+               return ret;
+       }
+
+       ret = __vision_source_get_valid_fmt(device_fd, fmt_list);
+
+       v4l2_close(device_fd);
+       return ret;
+}
+
+static int __vision_source_list_devices(vision_source_v4l2_s *vs_handle)
+{
+       glob_t glob_buf;
+       memset(&glob_buf, 0x0, sizeof(glob_t));
+       int ret = glob(DEVICE_NODE_PATH_PREFIX "*", 0, 0, &glob_buf);
+       if (ret != 0) {
+               switch (ret) {
+               case GLOB_NOSPACE:
+                       LOGE("out of memory");
+                       return VISION_SOURCE_ERROR_OUT_OF_MEMORY;
+               case GLOB_ABORTED:
+                       LOGE("read error");
+                       return VISION_SOURCE_ERROR_INTERNAL;
+               case GLOB_NOMATCH:
+                       LOGE("match not found");
+                       return VISION_SOURCE_ERROR_NO_DATA;
+               }
+       }
+
+       LOGD("device node count : %zu", glob_buf.gl_pathc);
+
+       vector<string> &dev_name = vs_handle->dev_name;
+       vector<vector<fmt_info> > &dev_fmt_list = vs_handle->fmt_list;
+
+       for (size_t i = 0; i < glob_buf.gl_pathc; i++) {
+               vector<fmt_info> fmt_list;
+               ret = __dev_info_from_path(glob_buf.gl_pathv[i], fmt_list);
+               if (ret != VISION_SOURCE_ERROR_NONE) {
+                       break;
+               }
+
+               if (!fmt_list.empty()) {
+                       dev_name.push_back(glob_buf.gl_pathv[i]);
+                       dev_fmt_list.push_back(fmt_list);
+               }
+       }
+       globfree(&glob_buf);
+
+       if (dev_name.empty())
+               return ret;
+
+       size_t dev_count = dev_name.size();
+
+       vs_handle->dev_info = (vision_source_device_info_s *) calloc(dev_count, sizeof(vision_source_device_info_s));
+       if (!vs_handle->dev_info) {
+               return VISION_SOURCE_ERROR_OUT_OF_MEMORY;
+       }
+
+       vs_handle->fmt = (media_format_h **) calloc(dev_count, sizeof(media_format_h *));
+       if (!vs_handle->fmt) {
+               return VISION_SOURCE_ERROR_OUT_OF_MEMORY;
+       }
+
+       for (size_t i = 0; i < dev_count; i++) {
+               vs_handle->dev_info[i].index = i;
+               strncpy(vs_handle->dev_info[i].name, dev_name[i].c_str(), DEVICE_NAME_LENGTH_MAX);
+               vs_handle->fmt[i] = (media_format_h *) calloc(dev_fmt_list[i].size(), sizeof(media_format_h));
+               if (!vs_handle->fmt[i]) {
+                       return VISION_SOURCE_ERROR_OUT_OF_MEMORY;
+               }
+
+               for (size_t j = 0; j < dev_fmt_list[i].size(); j++) {
+                       media_format_h fmt;
+                       media_format_create(&fmt);
+                       media_format_set_video_mime(fmt, dev_fmt_list[i][j].type);
+                       media_format_set_video_width(fmt, dev_fmt_list[i][j].width);
+                       media_format_set_video_height(fmt, dev_fmt_list[i][j].height);
+                       media_format_set_video_frame_rate(fmt, dev_fmt_list[i][j].fps);
+                       vs_handle->fmt[i][j] = fmt;
+               }
+       }
+
+       return ret;
+}
+
+static int __vision_source_v4l2_stream(int device_fd, int type, bool onoff)
+{
+       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 (1:on, 0:off) 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;
+
+       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) {
+               LOGE("different count [req:%d, result:%d]", count, v4l2_reqbuf.count);
+               return VISION_SOURCE_ERROR_INTERNAL;
+       }
+
+       *result_count = v4l2_reqbuf.count;
+
+       return VISION_SOURCE_ERROR_NONE;
+}
+
+static int __vision_source_stop_stream(vision_source_v4l2_s *handle)
+{
+       LOGD("__vision_source_stop_stream");
+
+       /* stream off */
+       int ret = __vision_source_v4l2_stream(handle->device_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, false);
+
+       /* munmap */
+       for (size_t i = 0; i < handle->mmap_addr.size(); i++) {
+               v4l2_munmap(handle->mmap_addr[i], handle->v4l2_buf[i].length);
+       }
+       handle->v4l2_buf.clear();
+       handle->mmap_addr.clear();
+
+       /* reqbufs 0 */
+       uint32_t buffer_count;
+       ret = __vision_source_v4l2_reqbufs(handle->device_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_MEMORY_MMAP, 0,
+                                                                          &buffer_count);
+
+       LOGD("reqbufs 0 : 0x%x", ret);
+
+       return ret;
+}
+
+static int __vision_source_set_stream(vision_source_v4l2_s *handle)
+{
+       fmt_info &fmt = handle->fmt_list[handle->device_index][handle->fmt_index];
+       struct v4l2_format v4l2_fmt;
+
+       unsigned int fourcc = 0;
+
+       int ret = __vision_source_get_fourcc_plane_num(fmt.type, &fourcc);
+       if (ret != VISION_SOURCE_ERROR_NONE)
+               return ret;
+
+       memset(&v4l2_fmt, 0x0, sizeof(struct v4l2_format));
+
+       v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       v4l2_fmt.fmt.pix.width = fmt.width;
+       v4l2_fmt.fmt.pix.height = fmt.height;
+       v4l2_fmt.fmt.pix.pixelformat = fourcc;
+
+       if (v4l2_ioctl(handle->device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
+               LOGE("S_FMT failed. errno %d", errno);
+               return VISION_SOURCE_ERROR_INTERNAL;
+       }
+
+       struct v4l2_streamparm v4l2_parm;
+       /* G_PARM */
+       memset(&v4l2_parm, 0x0, sizeof(struct v4l2_streamparm));
+
+       v4l2_parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       if (v4l2_ioctl(handle->device_fd, VIDIOC_G_PARM, &v4l2_parm) < 0) {
+               LOGE("G_PARM failed. errno %d", errno);
+               return VISION_SOURCE_ERROR_INTERNAL;
+       }
+
+       /* S_PARM to set fps */
+       v4l2_parm.parm.capture.timeperframe.numerator = 1;
+       v4l2_parm.parm.capture.timeperframe.denominator = fmt.fps;
+
+       if (v4l2_ioctl(handle->device_fd, VIDIOC_S_PARM, &v4l2_parm) < 0) {
+               LOGE("S_PARM failed. errno %d", errno);
+               return VISION_SOURCE_ERROR_INTERNAL;
+       }
+
+       return VISION_SOURCE_ERROR_NONE;
+}
+
+static int __vision_source_v4l2_dqbuf(int device_fd, int type, int memory, int *index, unsigned int *used_size)
+{
+       struct v4l2_buffer v4l2_buf;
+       memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer));
+
+       v4l2_buf.type = type;
+       v4l2_buf.memory = memory;
+
+       int ret = v4l2_ioctl(device_fd, VIDIOC_DQBUF, &v4l2_buf);
+       if (ret < 0) {
+               ret = errno;
+               LOGE("dqbuf failed. [t: %d, m: %d] errno %d", type, memory, ret);
+               if (ret == EIO)
+                       LOGE("EIO is internal hw error");
+
+               return VISION_SOURCE_ERROR_INTERNAL;
+       }
+
+       *index = v4l2_buf.index;
+       *used_size = v4l2_buf.bytesused;
+
+       return ret;
+}
+
+static int __vision_source_v4l2_wait_frame(int device_fd, int wait_time)
+{
+       fd_set fds;
+       FD_ZERO(&fds);
+       FD_SET(device_fd, &fds);
+
+       struct timeval timeout;
+       memset(&timeout, 0x0, sizeof(struct timeval));
+
+       timeout.tv_sec = wait_time;
+       timeout.tv_usec = 0;
+
+       /*LOGD("select : %d sec", wait_time);*/
+
+       int ret = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+       if (ret == -1) {
+               ret = errno;
+               if (ret == EINTR) {
+                       LOGD("select error : EINTR");
+                       return VISION_SOURCE_ERROR_NONE;
+               }
+               LOGE("select failed. errno %d", ret);
+               return VISION_SOURCE_ERROR_INTERNAL;
+       }
+       if (ret == 0) {
+               LOGE("select timeout.");
+               return VISION_SOURCE_ERROR_INTERNAL;
+       }
+
+       return VISION_SOURCE_ERROR_NONE;
+}
+
+static int __vision_source_mmap(vision_source_v4l2_s *handle)
+{
+       /* query buffer, mmap and qbuf */
+       for (int i = 0; i < BUFFER_MAX; i++) {
+               struct v4l2_buffer v4l2_buf;
+               memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer));
+
+               v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               v4l2_buf.memory = V4L2_MEMORY_MMAP;
+               v4l2_buf.index = i;
+
+               if (v4l2_ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) {
+                       LOGE("[%d] query buf failed. errno %d", i, errno);
+                       return VISION_SOURCE_ERROR_INTERNAL;
+               }
+
+               handle->v4l2_buf.push_back(v4l2_buf);
+
+               void *data =
+                               v4l2_mmap(0, v4l2_buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, handle->device_fd, v4l2_buf.m.offset);
+
+               if (data == MAP_FAILED) {
+                       LOGE("[%d] mmap failed (errno %d)", i, errno);
+                       return VISION_SOURCE_ERROR_INTERNAL;
+               }
+
+               handle->mmap_addr.push_back(data);
+
+               if (__vision_source_v4l2_qbuf(handle->device_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_MEMORY_MMAP, i) !=
+                       VISION_SOURCE_ERROR_NONE) {
+                       LOGE("[%d] qbuf failed (errno %d)", i, errno);
+                       return VISION_SOURCE_ERROR_INTERNAL;
+               }
+       }
+
+       /* stream on */
+       return __vision_source_v4l2_stream(handle->device_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, true);
+}
+
+static int __vision_source_start_stream(vision_source_v4l2_s *handle)
+{
+       uint32_t buffer_count = 0;
+       /* request buffer */
+       int ret = __vision_source_v4l2_reqbufs(handle->device_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_MEMORY_MMAP, BUFFER_MAX,
+                                                                                  &buffer_count);
+       if (ret != VISION_SOURCE_ERROR_NONE) {
+               return ret;
+       }
+
+       LOGD("buffer count : request %d -> result %d", BUFFER_MAX, buffer_count);
+
+       ret = __vision_source_mmap(handle);
+       if (ret != VISION_SOURCE_ERROR_NONE)
+               __vision_source_v4l2_reqbufs(handle->device_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_MEMORY_MMAP, 0,
+                                                                        &buffer_count);
+
+       return ret;
+}
+
+int vision_source_init(vision_source_h *handle)
+{
+       vision_source_v4l2_s *v4l2_handle = new vision_source_v4l2_s;
+
+       int ret = __vision_source_list_devices(v4l2_handle);
+       if (ret != VISION_SOURCE_ERROR_NONE) {
+               free(v4l2_handle);
+               LOGE("get device info failed");
+               return ret;
+       }
+
+       v4l2_handle->status = VISION_SOURCE_STATUS_INITIALIZED;
+       *handle = v4l2_handle;
+
+       return VISION_SOURCE_ERROR_NONE;
+}
+
+static void __vision_source_release_handle(vision_source_v4l2_s *handle)
+{
+       for (size_t i = 0; i < handle->fmt_list.size(); i++) {
+               for (size_t j = 0; j < handle->fmt_list[i].size(); j++) {
+                       media_format_unref(handle->fmt[i][j]);
+               }
+               free(handle->fmt[i]);
+       }
+       free(handle->fmt);
+       free(handle->dev_info);
+
+       LOGD("vision_source_v4l2_s %p destroy", handle);
+
+       return;
+}
+
+int vision_source_exit(vision_source_h handle)
+{
+       vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle;
+
+       if (v4l2_handle->dev_info)
+               __vision_source_release_handle(v4l2_handle);
+       delete v4l2_handle;
+
+       return VISION_SOURCE_ERROR_NONE;
+}
+
+int vision_source_list_devices(vision_source_h handle, vision_source_device_info_s **dev_list, int *dev_count)
+{
+       vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle;
+
+       *dev_list = v4l2_handle->dev_info;
+       *dev_count = v4l2_handle->dev_name.size();
+
+       return VISION_SOURCE_ERROR_NONE;
+}
+
+int vision_source_get_device_cap(vision_source_h handle, int dev_index, media_format_h **fmt_list, int *fmt_count)
+{
+       vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle;
+
+       if (dev_index < 0 || (size_t) dev_index >= v4l2_handle->fmt_list.size())
+               return VISION_SOURCE_ERROR_INVALID_PARAMETER;
+
+       *fmt_list = v4l2_handle->fmt[dev_index];
+       *fmt_count = v4l2_handle->fmt_list[dev_index].size();
+
+       return VISION_SOURCE_ERROR_NONE;
+}
+
+int vision_source_open_device(vision_source_h handle, int dev_index)
+{
+       vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle;
+
+       if (v4l2_handle->status != VISION_SOURCE_STATUS_INITIALIZED) {
+               return VISION_SOURCE_ERROR_INVALID_OPERATION;
+       }
+
+       if (dev_index < 0 || (size_t) dev_index >= v4l2_handle->fmt_list.size())
+               return VISION_SOURCE_ERROR_INVALID_PARAMETER;
+
+       int device_fd = VISION_SOURCE_INITIAL_FD;
+#ifdef HAVE_LIBV4L2
+       int libv4l2_fd = VISION_SOURCE_INITIAL_FD;
+#endif /* HAVE_LIBV4L2 */
+
+       char *node_path = v4l2_handle->dev_info[dev_index].name;
+
+       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;
+       }
+
+#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 != VISION_SOURCE_INITIAL_FD)
+               device_fd = libv4l2_fd;
+#endif /* HAVE_LIBV4L2 */
+
+       v4l2_handle->device_index = dev_index;
+       v4l2_handle->device_fd = device_fd;
+       v4l2_handle->status = VISION_SOURCE_STATUS_OPENDED;
+
+       LOGD("[%d] device[%s] opened [fd %d]", dev_index, node_path, device_fd);
+
+       return VISION_SOURCE_ERROR_NONE;
+}
+
+int vision_source_close_device(vision_source_h handle)
+{
+       vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle;
+
+       if (v4l2_handle->status != VISION_SOURCE_STATUS_OPENDED) {
+               return VISION_SOURCE_ERROR_INVALID_OPERATION;
+       }
+
+       if (v4l2_handle->device_fd < 0) {
+               LOGE("invalid fd %d", v4l2_handle->device_fd);
+               return VISION_SOURCE_ERROR_INTERNAL;
+       }
+
+       LOGD("close fd %d", v4l2_handle->device_fd);
+
+       v4l2_close(v4l2_handle->device_fd);
+
+       v4l2_handle->status = VISION_SOURCE_STATUS_INITIALIZED;
+       LOGD("device [%d] closed", v4l2_handle->device_index);
+       v4l2_handle->device_fd = VISION_SOURCE_INITIAL_FD;
+       v4l2_handle->device_index = VISION_SOURCE_INITIAL_FD;
+
+       return VISION_SOURCE_ERROR_NONE;
+}
+
+int vision_source_set_stream_format(vision_source_h handle, media_format_h fmt)
+{
+       vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle;
+
+       if (!v4l2_handle->fmt || v4l2_handle->status != VISION_SOURCE_STATUS_OPENDED) {
+               LOGE("Invalid state");
+               return VISION_SOURCE_ERROR_INVALID_OPERATION;
+       }
+
+       media_format_mimetype_e mimetype;
+       int width, height, fps;
+       int ret = media_format_get_video_info(fmt, &mimetype, &width, &height, nullptr, nullptr);
+       if (ret != MEDIA_FORMAT_ERROR_NONE) {
+               LOGE("media_format_get_video_info failed");
+               return VISION_SOURCE_ERROR_INTERNAL;
+       }
+       ret = media_format_get_video_frame_rate(fmt, &fps);
+       if (ret != MEDIA_FORMAT_ERROR_NONE) {
+               LOGE("media_format_get_video_info failed");
+               return VISION_SOURCE_ERROR_INTERNAL;
+       }
+
+       LOGI("Try set format width: %d, height: %d, fps: %d", width, height, fps);
+
+       fmt_info request { mimetype, (uint32_t) width, (uint32_t) height, (uint32_t) fps };
+       vector<fmt_info> &vec = v4l2_handle->fmt_list[v4l2_handle->device_index];
+       const auto pos = find(vec.begin(), vec.end(), request);
+       if (pos == vec.end()) {
+               LOGE("Not supported format");
+               return VISION_SOURCE_ERROR_INVALID_PARAMETER;
+       }
+
+       auto index = distance(vec.begin(), pos);
+       if (v4l2_handle->fmt_index == index) {
+               LOGD("no need to restart preview stream");
+               return VISION_SOURCE_ERROR_NONE;
+       }
+
+       v4l2_handle->fmt_index = index;
+
+       ret = __vision_source_set_stream(v4l2_handle);
+       if (ret != VISION_SOURCE_ERROR_NONE) {
+               LOGE("failed to set stream");
+               return ret;
+       }
+
+       return VISION_SOURCE_ERROR_NONE;
+}
+
+static void __vision_source_pkt_dispose_cb(media_packet_h packet, void *user_data)
+{
+       pkt_dispose_cb_data *data = (pkt_dispose_cb_data *) user_data;
+
+       int ret = __vision_source_v4l2_qbuf(data->fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_MEMORY_MMAP, data->index);
+       if (ret != VISION_SOURCE_ERROR_NONE)
+               LOGE("qbuf failed");
+}
+
+static void __fetch_buffer_and_callback(vision_source_v4l2_s *v4l2_handle)
+{
+       LOGD("__fetch_buffer_and_callback");
+
+       int index;
+       unsigned int byte_size;
+       int ret;
+
+       for (size_t i = 0; i < BUFFER_MAX; i++) {
+               v4l2_handle->pkt_data[i].fd = v4l2_handle->device_fd;
+               v4l2_handle->pkt_data[i].index = i;
+       }
+
+       while (v4l2_handle->buffer_thread_run) {
+               LOGD("__fetch_buffer_and_callback: waiting for buffer");
+               ret = __vision_source_v4l2_wait_frame(v4l2_handle->device_fd, 5);
+               if (ret != VISION_SOURCE_ERROR_NONE) {
+                       LOGE("frame wait failed");
+                       break;
+               }
+
+               if (v4l2_handle->buffer_thread_run == false) {
+                       LOGD("stop buffer handler thread");
+                       break;
+               }
+               ret = __vision_source_v4l2_dqbuf(v4l2_handle->device_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_MEMORY_MMAP, &index,
+                                                                                &byte_size);
+               if (ret != VISION_SOURCE_ERROR_NONE) {
+                       LOGE("dqbuf failed");
+                       break;
+               }
+
+               media_format_h fmt = v4l2_handle->fmt[v4l2_handle->device_index][v4l2_handle->fmt_index];
+
+               media_packet_h pkt;
+               ret = media_packet_new_from_external_memory(fmt, v4l2_handle->mmap_addr[index], byte_size,
+                                                                                                       __vision_source_pkt_dispose_cb, &v4l2_handle->pkt_data[index],
+                                                                                                       &pkt);
+               if (ret != MEDIA_PACKET_ERROR_NONE) {
+                       LOGE("media_packet_new_from_external_memory failed");
+                       continue;
+               }
+               if (v4l2_handle->stream_callback) {
+                       v4l2_handle->stream_callback(pkt, v4l2_handle->stream_user_data);
+               }
+
+               media_packet_unref(pkt);
+               sched_yield();
+       }
+
+       return;
+}
+
+int vision_source_start_stream(vision_source_h handle)
+{
+       vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle;
+
+       if (v4l2_handle->status != VISION_SOURCE_STATUS_OPENDED) {
+               LOGE("status is not VISION_SOURCE_STATUS_OPENDED");
+               return VISION_SOURCE_ERROR_INVALID_OPERATION;
+       }
+       if (v4l2_handle->fmt_index < 0) {
+               LOGE("format is not set");
+               return VISION_SOURCE_ERROR_INVALID_OPERATION;
+       }
+
+       int ret = __vision_source_start_stream(v4l2_handle);
+       if (ret != VISION_SOURCE_ERROR_NONE) {
+               LOGE("__vision_source_start_stream failed[0x%x]", ret);
+               return ret;
+       }
+
+       v4l2_handle->buffer_thread_run = true;
+       v4l2_handle->buffer_thread = thread(__fetch_buffer_and_callback, v4l2_handle);
+
+       v4l2_handle->status = VISION_SOURCE_STATUS_STARTED;
+       LOGD("start preview done");
+
+       return VISION_SOURCE_ERROR_NONE;
+}
+
+/*
+ * TODO: buffer_thread has some problem, what happend to buffer?
+ */
+int vision_source_stop_stream(vision_source_h handle)
+{
+       vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle;
+
+       if (v4l2_handle->status != VISION_SOURCE_STATUS_STARTED)
+               return VISION_SOURCE_ERROR_INVALID_OPERATION;
+
+       v4l2_handle->buffer_thread_run = false;
+       v4l2_handle->buffer_thread.join();
+       LOGI("buffer thread stopped and joined");
+
+       int ret = __vision_source_stop_stream(v4l2_handle);
+       if (ret != VISION_SOURCE_ERROR_NONE)
+               LOGE("__vision_source_stop_stream failed, but buffer thread will be stopped");
+
+       v4l2_handle->fmt_index = VISION_SOURCE_INITIAL_FD;
+       v4l2_handle->stream_callback = nullptr;
+       v4l2_handle->stream_user_data = nullptr;
+       v4l2_handle->status = VISION_SOURCE_STATUS_OPENDED;
+       LOGD("stop preview done [0x%x]", ret);
+
+       return ret;
+}
+
+/* TODO: run-time callback change*/
+int vision_source_set_stream_cb(vision_source_h handle, stream_cb callback, void *user_data)
+{
+       vision_source_v4l2_s *v4l2_handle = (vision_source_v4l2_s *) handle;
+
+       if (v4l2_handle->status != VISION_SOURCE_STATUS_OPENDED)
+               return VISION_SOURCE_ERROR_INVALID_OPERATION;
+
+       v4l2_handle->stream_callback = callback;
+       v4l2_handle->stream_user_data = user_data;
+       return VISION_SOURCE_ERROR_NONE;
+}
+
+#ifdef USE_DL
+void attach_backend(vision_source_func_s *funcp)
+{
+       funcp->init = vision_source_v4l2_init;
+       funcp->exit = vision_source_v4l2_exit;
+       funcp->list_devices = vision_source_v4l2_list_devices;
+       funcp->get_device_cap = vision_source_v4l2_get_device_cap;
+       funcp->open_device = vision_source_v4l2_open_device;
+       funcp->close_device = vision_source_v4l2_close_device;
+       funcp->set_stream_format = vision_source_v4l2_set_stream_format;
+       funcp->start_stream = vision_source_v4l2_start_stream;
+       funcp->stop_stream = vision_source_v4l2_stop_stream;
+       funcp->set_stream_cb = vision_source_v4l2_set_stream_cb;
+}
+#endif
diff --git a/src/vision_source_v4l2_private.h b/src/vision_source_v4l2_private.h
deleted file mode 100644 (file)
index 9c526d4..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * 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 <vision_source_interface.h>
-#include <glib.h>
-#include <linux/videodev2.h>
-#include <dlog.h>
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-
-#ifdef HAVE_LIBV4L2
-#include <libv4l2.h>
-#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;
-       vision_source_device_info_list_s *device_info_list;
-
-       /* 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;
-       stream_cb stream_callback;
-       gpointer stream_callback_data;
-
-       /* etc */
-       GMutex lock;
-} vision_source_v4l2_s;
-
-typedef struct _packet_context_s
-{
-       int device_fd;
-       int type;
-       int memory;
-       int index;
-} packet_context_s;
-#endif /* __VISION_SOURCE_V4L2_PRIVATE_H__ */
\ No newline at end of file
index dbd218479b58619ba65f304ddab460cfff1aa3d5..dedd78ad91437318f670f62a3c11c60884b4068e 100644 (file)
@@ -2,17 +2,19 @@ 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}
+target_link_libraries(${PROJECT_NAME} PRIVATE
+    vision-source-v4l2
     gtest gtest_main
 )
-target_include_directories(${PROJECT_NAME} PUBLIC ${${PROJECT_NAME}_DEP_INCLUDE_DIRS})
+
+target_include_directories(${PROJECT_NAME} PRIVATE
+    /usr/include/media
+)
 
 # install packages
-INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
\ No newline at end of file
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
index 3d78475e3f8a3ca008d48f96dcfb2ae53216b699..2e58f2ad568eb9c394ad79d18d6d0e65eb366761 100644 (file)
@@ -1,4 +1,5 @@
 #include <gtest/gtest.h>
+#include <media_packet.h>
 #include <vision_source.h>
 
 class VisionV4L2 : public ::testing::Test
@@ -16,58 +17,57 @@ protected:
        vision_source_h ms_handle;
 };
 
-TEST_F(VisionV4L2, EnumerateDev)
+TEST_F(VisionV4L2, ListDevices)
 {
-       vision_source_device_info_list_s dev_list;
-       ASSERT_EQ(vision_source_enumerate_devices(ms_handle, &dev_list),
-                         VISION_SOURCE_ERROR_NONE);
-       EXPECT_GT(dev_list.count, 0);
+       vision_source_device_info_s *dev_list;
+       int dev_cnt;
+       ASSERT_EQ(vision_source_list_devices(ms_handle, &dev_list, &dev_cnt), VISION_SOURCE_ERROR_NONE);
+       EXPECT_GT(dev_cnt, 0);
+}
+
+TEST_F(VisionV4L2, DevCap)
+{
+       vision_source_device_info_s *dev_list;
+       media_format_h *fmt_list;
+       int fmt_count;
+       int dev_cnt;
+       ASSERT_EQ(vision_source_list_devices(ms_handle, &dev_list, &dev_cnt), VISION_SOURCE_ERROR_NONE);
+       ASSERT_GT(dev_cnt, 0);
+       ASSERT_EQ(vision_source_get_device_cap(ms_handle, 0, &fmt_list, &fmt_count), VISION_SOURCE_ERROR_NONE);
+       ASSERT_GT(fmt_count, 0);
 }
 
 TEST_F(VisionV4L2, OpenDev0)
 {
-       ASSERT_EQ(vision_source_open_device(ms_handle, 0),
-                         VISION_SOURCE_ERROR_NONE);
+       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);
 }
 
+TEST_F(VisionV4L2, NotOpenDev)
+{
+       vision_source_device_info_s *dev_list;
+       media_format_h *fmt_list;
+       int fmt_count;
+       int dev_cnt;
+       ASSERT_EQ(vision_source_list_devices(ms_handle, &dev_list, &dev_cnt), VISION_SOURCE_ERROR_NONE);
+       ASSERT_GT(dev_cnt, 0);
+       ASSERT_EQ(vision_source_get_device_cap(ms_handle, 0, &fmt_list, &fmt_count), VISION_SOURCE_ERROR_NONE);
+       ASSERT_GT(fmt_count, 2);
+       EXPECT_EQ(vision_source_set_stream_format(ms_handle, fmt_list[2]), VISION_SOURCE_ERROR_INVALID_OPERATION);
+}
+
 TEST_F(VisionV4L2, SetStream)
 {
-       vision_source_device_info_list_s dev_list;
-       ASSERT_EQ(vision_source_enumerate_devices(ms_handle, &dev_list),
-                         VISION_SOURCE_ERROR_NONE);
-       ASSERT_GT(dev_list.count, 0);
-
-       ASSERT_GT(dev_list.device_info[0].pixel_list.count, 0);
-       vision_source_format_s format;
-       format.pixel_format =
-                       dev_list.device_info[0].pixel_list.pixels[0].pixel_format;
-       ASSERT_GT(
-                       dev_list.device_info[0].pixel_list.pixels[0].resolution_list.count,
-                       0);
-
-       format.resolution.width = dev_list.device_info[0]
-                                                                         .pixel_list.pixels[0]
-                                                                         .resolution_list.resolutions[0]
-                                                                         .resolution.width;
-       format.resolution.height = dev_list.device_info[0]
-                                                                          .pixel_list.pixels[0]
-                                                                          .resolution_list.resolutions[0]
-                                                                          .resolution.height;
-       ASSERT_GT(dev_list.device_info[0]
-                                         .pixel_list.pixels[0]
-                                         .resolution_list.resolutions[0]
-                                         .fps_list.count,
-                         0);
-       format.fps = dev_list.device_info[0]
-                                                .pixel_list.pixels[0]
-                                                .resolution_list.resolutions[0]
-                                                .fps_list.fps[0];
-
-       ASSERT_EQ(vision_source_open_device(ms_handle, 0),
-                         VISION_SOURCE_ERROR_NONE);
-       EXPECT_EQ(vision_source_set_stream_format(ms_handle, &format),
-                         VISION_SOURCE_ERROR_NONE);
+       vision_source_device_info_s *dev_list;
+       media_format_h *fmt_list;
+       int fmt_count;
+       int dev_cnt;
+       ASSERT_EQ(vision_source_list_devices(ms_handle, &dev_list, &dev_cnt), VISION_SOURCE_ERROR_NONE);
+       ASSERT_GT(dev_cnt, 0);
+       ASSERT_EQ(vision_source_get_device_cap(ms_handle, 0, &fmt_list, &fmt_count), VISION_SOURCE_ERROR_NONE);
+       ASSERT_GT(fmt_count, 2);
+       ASSERT_EQ(vision_source_open_device(ms_handle, 0), VISION_SOURCE_ERROR_NONE);
+       EXPECT_EQ(vision_source_set_stream_format(ms_handle, fmt_list[2]), VISION_SOURCE_ERROR_NONE);
        EXPECT_EQ(vision_source_close_device(ms_handle), VISION_SOURCE_ERROR_NONE);
 }
 
@@ -77,48 +77,23 @@ protected:
        void SetUp() override
        {
                ASSERT_EQ(vision_source_init(&ms_handle), VISION_SOURCE_ERROR_NONE);
-               vision_source_device_info_list_s dev_list;
-               ASSERT_EQ(vision_source_enumerate_devices(ms_handle, &dev_list),
-                                 VISION_SOURCE_ERROR_NONE);
-               ASSERT_GT(dev_list.count, 0);
-
-               ASSERT_GT(dev_list.device_info[0].pixel_list.count, 0);
-               vision_source_format_s format;
-               format.pixel_format =
-                               dev_list.device_info[0].pixel_list.pixels[0].pixel_format;
-               ASSERT_GT(dev_list.device_info[0]
-                                                 .pixel_list.pixels[0]
-                                                 .resolution_list.count,
-                                 0);
-
-               format.resolution.width = dev_list.device_info[0]
-                                                                                 .pixel_list.pixels[0]
-                                                                                 .resolution_list.resolutions[0]
-                                                                                 .resolution.width;
-               format.resolution.height = dev_list.device_info[0]
-                                                                                  .pixel_list.pixels[0]
-                                                                                  .resolution_list.resolutions[0]
-                                                                                  .resolution.height;
-               ASSERT_GT(dev_list.device_info[0]
-                                                 .pixel_list.pixels[0]
-                                                 .resolution_list.resolutions[0]
-                                                 .fps_list.count,
-                                 0);
-               format.fps = dev_list.device_info[0]
-                                                        .pixel_list.pixels[0]
-                                                        .resolution_list.resolutions[0]
-                                                        .fps_list.fps[0];
-
-               ASSERT_EQ(vision_source_open_device(ms_handle, 0),
-                                 VISION_SOURCE_ERROR_NONE);
-               EXPECT_EQ(vision_source_set_stream_format(ms_handle, &format),
-                                 VISION_SOURCE_ERROR_NONE);
+               vision_source_device_info_s *dev_list;
+               media_format_h *fmt_list;
+               int fmt_count;
+               int dev_cnt;
+
+               ASSERT_EQ(vision_source_list_devices(ms_handle, &dev_list, &dev_cnt), VISION_SOURCE_ERROR_NONE);
+               ASSERT_GT(dev_cnt, 0);
+               ASSERT_EQ(vision_source_get_device_cap(ms_handle, 0, &fmt_list, &fmt_count), VISION_SOURCE_ERROR_NONE);
+               ASSERT_GT(fmt_count, 2);
+
+               ASSERT_EQ(vision_source_open_device(ms_handle, 0), VISION_SOURCE_ERROR_NONE);
+               ASSERT_EQ(vision_source_set_stream_format(ms_handle, fmt_list[2]), VISION_SOURCE_ERROR_NONE);
        }
 
        void TearDown() override
        {
-               EXPECT_EQ(vision_source_close_device(ms_handle),
-                                 VISION_SOURCE_ERROR_NONE);
+               EXPECT_EQ(vision_source_close_device(ms_handle), VISION_SOURCE_ERROR_NONE);
                ASSERT_EQ(vision_source_exit(ms_handle), VISION_SOURCE_ERROR_NONE);
        }
        vision_source_h ms_handle;
@@ -126,14 +101,13 @@ protected:
 
 TEST_F(VisionV4L2FixedFormat, OnlyStopStream)
 {
-       EXPECT_EQ(vision_source_stop_stream(ms_handle), VISION_SOURCE_ERROR_NONE);
+       EXPECT_EQ(vision_source_stop_stream(ms_handle), VISION_SOURCE_ERROR_INVALID_OPERATION);
 }
 
 TEST_F(VisionV4L2FixedFormat, StartStream)
 {
-       ASSERT_EQ(vision_source_start_stream(ms_handle, nullptr, nullptr),
-                         VISION_SOURCE_ERROR_NONE);
-       sleep(1);
+       ASSERT_EQ(vision_source_start_stream(ms_handle), VISION_SOURCE_ERROR_NONE);
+       sleep(5);
        EXPECT_EQ(vision_source_stop_stream(ms_handle), VISION_SOURCE_ERROR_NONE);
 }
 
@@ -146,15 +120,14 @@ static int test_cb(media_packet_h pkt, void *user_data)
 
        double delta_ms = (double) (end - *start) / CLOCKS_PER_SEC * 1000;
 
-       snprintf(filename, 127, "out_%04u.data", (unsigned) delta_ms);
+       snprintf(filename, 127, "/opt/usr/home/owner/media/Images/out_%04u.data", (unsigned) delta_ms);
        file = fopen(filename, "w");
-       if (!file)
-               return VISION_SOURCE_ERROR_INTERNAL;
 
-       char *data;
+       void *data;
        uint64_t size;
-       media_packet_get_buffer_data_ptr(pkt, (void **) &data);
+       media_packet_get_buffer_data_ptr(pkt, &data);
        media_packet_get_buffer_size(pkt, &size);
+
        fwrite(data, sizeof(unsigned char), size, file);
        fclose(file);
        return 0;
@@ -163,8 +136,8 @@ static int test_cb(media_packet_h pkt, void *user_data)
 TEST_F(VisionV4L2FixedFormat, StartWithCallback)
 {
        clock_t start = clock();
-       ASSERT_EQ(vision_source_start_stream(ms_handle, test_cb, &start),
-                         VISION_SOURCE_ERROR_NONE);
-       sleep(1);
+       ASSERT_EQ(vision_source_set_stream_cb(ms_handle, test_cb, &start), VISION_SOURCE_ERROR_NONE);
+       ASSERT_EQ(vision_source_start_stream(ms_handle), VISION_SOURCE_ERROR_NONE);
+       sleep(5);
        EXPECT_EQ(vision_source_stop_stream(ms_handle), VISION_SOURCE_ERROR_NONE);
-}
\ No newline at end of file
+}