Use libv4l2 to emulate unsupported formats 95/262995/1 accepted/tizen/unified/20210830.103709 submit/tizen/20210830.041956
authorJeongmo Yang <jm80.yang@samsung.com>
Tue, 24 Aug 2021 09:31:45 +0000 (18:31 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Tue, 24 Aug 2021 09:31:45 +0000 (18:31 +0900)
[Version] 0.1.5
[Issue Type] New feature

Change-Id: I328e3cc2e8d178b44829b5a9c650ea47be5e09d4
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
configure.ac
packaging/camera-hal-v4l2.spec
src/Makefile.am
src/hal_camera_v4l2.c
src/hal_camera_v4l2_private.h

index ef6f7fc..177c598 100644 (file)
@@ -41,6 +41,21 @@ AC_SUBST(HAL_API_COMMON_CFLAGS)
 PKG_CHECK_MODULES(HAL_API_CAMERA, hal-api-camera)
 AC_SUBST(HAL_API_CAMERA_CFLAGS)
 
+AC_ARG_ENABLE(libv4l2, AC_HELP_STRING([--enable-libv4l2], [enable libv4l2]),
+[
+  case "${enableval}" in
+    yes) HAVE_LIBV4L2=yes ;;
+    no)  HAVE_LIBV4L2=no ;;
+    *) AC_MSG_ERROR(bad value ${enableval} for --enable-libv4l2) ;;
+  esac
+],[HAVE_LIBV4L2=no])
+if test "x$HAVE_LIBV4L2" = "xyes"; then
+PKG_CHECK_MODULES(LIBV4L2, libv4l2)
+AC_SUBST(LIBV4L2_CFLAGS)
+AC_SUBST(LIBV4L2_LIBS)
+fi
+AM_CONDITIONAL([HAVE_LIBV4L2], [test "x$HAVE_LIBV4L2" = "xyes"])
+
 # Checks for header files.
 AC_HEADER_STDC
 AC_CHECK_HEADERS([fcntl.h memory.h stdlib.h string.h sys/time.h unistd.h])
index 67deda2..67170a2 100644 (file)
@@ -1,6 +1,8 @@
+%define enable_libv4l2 1
+
 Name:       camera-hal-v4l2
 Summary:    Tizen Camera Hal for V4L2
-Version:    0.1.4
+Version:    0.1.5
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
@@ -12,6 +14,9 @@ BuildRequires:  pkgconfig(libtbm)
 BuildRequires:  pkgconfig(dlog)
 BuildRequires:  pkgconfig(hal-api-common)
 BuildRequires:  pkgconfig(hal-api-camera)
+%if 0%{?enable_libv4l2}
+BuildRequires:  pkgconfig(libv4l2)
+%endif
 
 %description
 Tizen Camera Hal for V4L2.
@@ -23,7 +28,12 @@ Tizen Camera Hal for V4L2.
 
 %build
 ./autogen.sh
-%configure --disable-static --libdir=%{_hal_libdir}
+%configure \
+%if 0%{?enable_libv4l2}
+       --enable-libv4l2\
+%endif
+       --disable-static\
+       --libdir=%{_hal_libdir}
 make %{?jobs:-j%jobs}
 
 %install
index 58cb115..f10e540 100644 (file)
@@ -19,6 +19,11 @@ libhal_backend_camera_la_LIBADD = \
        $(DLOG_LIBS) \
        $(TBM_LIBS)
 
+if HAVE_LIBV4L2
+libhal_backend_camera_la_CFLAGS += $(LIBV4L2_CFLAGS) -DHAVE_LIBV4L2
+libhal_backend_camera_la_LIBADD += $(LIBV4L2_LIBS)
+endif
+
 libhal_backend_camera_la_CFLAGS += -fdata-sections -ffunction-sections -Wl,--gc-sections
 libhal_backend_camera_la_LDFLAGS = -Wl,--gc-sections -avoid-version
 
index 54f6a1b..a3f136a 100644 (file)
@@ -126,7 +126,7 @@ static int __camera_v4l2_g_ctrl(int device_fd, int cid, int *value)
 
        ctrl.id = cid;
 
-       ret = ioctl(device_fd, VIDIOC_G_CTRL, &ctrl);
+       ret = v4l2_ioctl(device_fd, VIDIOC_G_CTRL, &ctrl);
 
        *value = ctrl.value;
 
@@ -146,7 +146,7 @@ static int __camera_v4l2_s_ctrl(int device_fd, int cid, int value)
        ctrl.id = cid;
        ctrl.value = value;
 
-       ret = ioctl(device_fd, VIDIOC_S_CTRL, &ctrl);
+       ret = v4l2_ioctl(device_fd, VIDIOC_S_CTRL, &ctrl);
 
        LOGD("S_CTRL id 0x%x, value %d, ret %d", cid, value, ret);
 
@@ -161,7 +161,7 @@ static int __camera_v4l2_stream(int device_fd, int type, gboolean onoff)
                return CAMERA_ERROR_INVALID_PARAMETER;
        }
 
-       if (ioctl(device_fd, onoff ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, &type) < 0) {
+       if (v4l2_ioctl(device_fd, onoff ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, &type) < 0) {
                LOGE("stream %d failed. [t:%d] errno %d", onoff, type, errno);
                return CAMERA_ERROR_INTERNAL;
        }
@@ -192,7 +192,7 @@ static int __camera_v4l2_reqbufs(int device_fd, int type, int memory, uint32_t c
        v4l2_reqbuf.memory = memory;
        v4l2_reqbuf.count = count;
 
-       if (ioctl(device_fd, VIDIOC_REQBUFS, &v4l2_reqbuf) < 0) {
+       if (v4l2_ioctl(device_fd, VIDIOC_REQBUFS, &v4l2_reqbuf) < 0) {
                LOGE("REQBUFS[count %d] failed. errno %d", count, errno);
                return CAMERA_ERROR_INTERNAL;
        }
@@ -226,7 +226,7 @@ static int __camera_v4l2_qbuf(int device_fd, int type, int memory, int index)
        v4l2_buf.length = 460800;
        v4l2_buf.bytesused = 460800;
 
-       if (ioctl(device_fd, VIDIOC_QBUF, &v4l2_buf) < 0) {
+       if (v4l2_ioctl(device_fd, VIDIOC_QBUF, &v4l2_buf) < 0) {
                LOGE("qbuf failed.  [i: %d, t: %d, m: %d] errno %d",
                        index, type, memory, errno);
                return CAMERA_ERROR_INTERNAL;
@@ -261,7 +261,7 @@ static int __camera_v4l2_dqbuf(int device_fd, int type, int memory, int *index)
        v4l2_buf.memory = memory;
        v4l2_buf.m.planes = v4l2_planes;
 
-       ret = ioctl(device_fd, VIDIOC_DQBUF, &v4l2_buf);
+       ret = v4l2_ioctl(device_fd, VIDIOC_DQBUF, &v4l2_buf);
        if (ret < 0) {
                if (errno != EIO) {
                        LOGE("dqbuf failed. [t: %d, m: %d] errno %d",
@@ -400,12 +400,14 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi
                v4l2_format.index = i;
                v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
-               if (ioctl(device_fd, VIDIOC_ENUM_FMT, &v4l2_format) < 0) {
+               if (v4l2_ioctl(device_fd, VIDIOC_ENUM_FMT, &v4l2_format) < 0) {
                        LOGW("\tformat : end of enumeration");
                        break;
                }
 
-               LOGD("\tformat[%d] "FOURCC_FORMAT, i, FOURCC_CONVERT(v4l2_format.pixelformat));
+               LOGD("\tformat[%d] "FOURCC_FORMAT" (emulated:%d)",
+                       i, FOURCC_CONVERT(v4l2_format.pixelformat),
+                       ((v4l2_format.flags & V4L2_FMT_FLAG_EMULATED) ? 1 : 0));
 
                if (__camera_get_format(v4l2_format.pixelformat, &camera_format) != CAMERA_ERROR_NONE)
                        continue;
@@ -420,7 +422,7 @@ static int __camera_get_device_info(int device_index, int device_fd, camera_devi
                        v4l2_frame.index = j;
                        v4l2_frame.pixel_format = v4l2_format.pixelformat;
 
-                       if (ioctl(device_fd, VIDIOC_ENUM_FRAMESIZES, &v4l2_frame) < 0) {
+                       if (v4l2_ioctl(device_fd, VIDIOC_ENUM_FRAMESIZES, &v4l2_frame) < 0) {
                                LOGW("\t\tframe : end of enumeration ");
                                break;
                        }
@@ -489,6 +491,9 @@ static int __camera_get_device_info_list(void)
        int ret = 0;
        int device_count = 0;
        int device_fd = CAMERA_HAL_INITIAL_FD;
+#ifdef HAVE_LIBV4L2
+       int libv4l2_fd = CAMERA_HAL_INITIAL_FD;
+#endif /* HAVE_LIBV4L2 */
        glob_t glob_buf;
        struct v4l2_capability v4l2_cap;
        camera_device_info_list_s *device_info_list = NULL;
@@ -543,11 +548,20 @@ static int __camera_get_device_info_list(void)
                        continue;
                }
 
+#ifdef HAVE_LIBV4L2
+               libv4l2_fd = v4l2_fd_open(device_fd, V4L2_ENABLE_ENUM_FMT_EMULATION);
+
+               LOGI("device_fd[%d], libv4l2_fd[%d]", device_fd, libv4l2_fd);
+
+               if (libv4l2_fd != CAMERA_HAL_INITIAL_FD)
+                       device_fd = libv4l2_fd;
+#endif /* HAVE_LIBV4L2 */
+
                memset(&v4l2_cap, 0x0, sizeof(struct v4l2_capability));
 
-               if (ioctl(device_fd, VIDIOC_QUERYCAP, &v4l2_cap) < 0) {
+               if (v4l2_ioctl(device_fd, VIDIOC_QUERYCAP, &v4l2_cap) < 0) {
                        LOGE("querycap failed. errno %d", errno);
-                       close(device_fd);
+                       v4l2_close(device_fd);
                        continue;
                }
 
@@ -559,14 +573,14 @@ static int __camera_get_device_info_list(void)
                if (!(g_device_caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)) ||
                        (g_device_caps & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE))) {
                        LOGW("[%s] is not a capture device 0x%x", glob_buf.gl_pathv[i], g_device_caps);
-                       close(device_fd);
+                       v4l2_close(device_fd);
                        continue;
                }
 
                ret = __camera_get_device_info(device_count, device_fd,
                        &device_info_list->device_info[device_count], glob_buf.gl_pathv[i]);
 
-               close(device_fd);
+               v4l2_close(device_fd);
 
                if (ret == CAMERA_ERROR_NONE)
                        device_count++;
@@ -611,7 +625,7 @@ static int __camera_stop_stream(hal_camera_handle *handle, uint32_t buffer_count
                if (handle->camera_buffers[i].planes[0].data != NULL) {
                        LOGW("munmap %p", handle->camera_buffers[i].planes[0].data);
 
-                       munmap(handle->camera_buffers[i].planes[0].data, handle->camera_buffers[i].planes[0].size);
+                       v4l2_munmap(handle->camera_buffers[i].planes[0].data, handle->camera_buffers[i].planes[0].size);
 
                        handle->camera_buffers[i].planes[0].data = 0;
                        handle->camera_buffers[i].planes[0].size = 0;
@@ -670,7 +684,7 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_
                v4l2_fmt.fmt.pix.bytesperline = resolution->width;
        }
 
-       if (ioctl(handle->device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
+       if (v4l2_ioctl(handle->device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
                LOGE("S_FMT failed. errno %d", errno);
                return CAMERA_ERROR_INTERNAL;
        }
@@ -692,7 +706,7 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_
 
        v4l2_parm.type = handle->buffer_type;
 
-       if (ioctl(handle->device_fd, VIDIOC_G_PARM, &v4l2_parm) < 0) {
+       if (v4l2_ioctl(handle->device_fd, VIDIOC_G_PARM, &v4l2_parm) < 0) {
                LOGE("G_PARM failed. errno %d", errno);
                return CAMERA_ERROR_INTERNAL;
        }
@@ -701,7 +715,7 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_
        v4l2_parm.parm.capture.timeperframe.numerator = 1;
        v4l2_parm.parm.capture.timeperframe.denominator = fps;
 
-       if (ioctl(handle->device_fd, VIDIOC_S_PARM, &v4l2_parm) < 0) {
+       if (v4l2_ioctl(handle->device_fd, VIDIOC_S_PARM, &v4l2_parm) < 0) {
                LOGE("S_PARM failed. errno %d", errno);
                return CAMERA_ERROR_INTERNAL;
        }
@@ -727,7 +741,7 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_
                v4l2_buf.m.planes = v4l2_planes;
                v4l2_buf.length = plane_num;
 
-               if (ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) {
+               if (v4l2_ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) {
                        LOGE("[%d] query buf failed. errno %d", i, errno);
                        goto _START_STREAM_FAILED;
                }
@@ -741,7 +755,7 @@ static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_
                buffer->total_size = v4l2_buf.length;
                buffer->num_planes = plane_num;
                buffer->planes[0].size = v4l2_buf.length;
-               buffer->planes[0].data = mmap(0,
+               buffer->planes[0].data = v4l2_mmap(0,
                        v4l2_buf.length,
                        PROT_READ | PROT_WRITE,
                        MAP_SHARED,
@@ -1148,6 +1162,12 @@ int camera_v4l2_init(void **camera_handle)
                goto _INIT_ERROR;
        }
 
+#ifdef HAVE_LIBV4L2
+       LOGI("libv4l2 ENABLED");
+#else /* HAVE_LIBV4L2 */
+       LOGI("libv4l2 DISABLED");
+#endif /* HAVE_LIBV4L2 */
+
        *camera_handle = new_handle;
 
        LOGD("camera HAL handle %p", new_handle);
@@ -1211,6 +1231,9 @@ int camera_v4l2_open_device(void *camera_handle, int device_index)
 {
        int ret = CAMERA_ERROR_NONE;
        int device_fd = CAMERA_HAL_INITIAL_FD;
+#ifdef HAVE_LIBV4L2
+       int libv4l2_fd = CAMERA_HAL_INITIAL_FD;
+#endif /* HAVE_LIBV4L2 */
        char *node_path = NULL;
        hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
 
@@ -1270,6 +1293,15 @@ int camera_v4l2_open_device(void *camera_handle, int device_index)
        else
                handle->buffer_type = V4L2_CAP_VIDEO_CAPTURE;
 
+#ifdef HAVE_LIBV4L2
+       libv4l2_fd = v4l2_fd_open(device_fd, V4L2_ENABLE_ENUM_FMT_EMULATION);
+
+       LOGI("device_fd[%d], libv4l2_fd[%d]", device_fd, libv4l2_fd);
+
+       if (libv4l2_fd != CAMERA_HAL_INITIAL_FD)
+               device_fd = libv4l2_fd;
+#endif /* HAVE_LIBV4L2 */
+
        handle->state = CAMERA_STATE_OPENED;
        handle->device_index = device_index;
        handle->device_fd = device_fd;
@@ -1311,7 +1343,7 @@ int camera_v4l2_close_device(void *camera_handle)
        if (handle->device_fd >= 0) {
                LOGD("close fd %d", handle->device_fd);
 
-               close(handle->device_fd);
+               v4l2_close(handle->device_fd);
                handle->device_fd = CAMERA_HAL_INITIAL_FD;
        } else {
                LOGW("invalid fd %d", handle->device_fd);
index 3e7f5fc..65478d9 100644 (file)
 #include <hal/hal-common-interface.h>
 #include <hal/hal-camera-interface.h>
 
+#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 CAMERA_HAL_INITIAL_INDEX    -1
 #define CAMERA_HAL_INITIAL_FD       -1
 #define MESSAGE_CALLBACK_MAX        10