Use libv4l2 to emulate unsupported formats 56/262856/4
authorJeongmo Yang <jm80.yang@samsung.com>
Fri, 20 Aug 2021 15:24:40 +0000 (00:24 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Mon, 23 Aug 2021 04:11:04 +0000 (13:11 +0900)
[Version] 0.1.14
[Issue Type] New feature

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

index e60590060f5849e37f77656b3bb9575459f47e99..773f0addebd63f4e19c6edf3cb0d41d8b4841a21 100644 (file)
@@ -35,6 +35,21 @@ PKG_CHECK_MODULES(DLOG, dlog)
 AC_SUBST(DLOG_CFLAGS)
 AC_SUBST(DLOG_LIBS)
 
+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 61e7eeee2581f6bdb54c6d5985b0302b1de2c4b8..74b8d2217a75a0f4d005a1239fd8ef30a886f29c 100644 (file)
@@ -1,6 +1,8 @@
+%define enable_libv4l2 1
+
 Name:       camera-hal-v4l2
 Summary:    Tizen Camera Hal for V4L2
-Version:    0.0.13
+Version:    0.0.14
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
@@ -9,6 +11,9 @@ Requires(post): /sbin/ldconfig
 Requires(postun): /sbin/ldconfig
 BuildRequires:  pkgconfig(glib-2.0)
 BuildRequires:  pkgconfig(libtbm)
+%if 0%{?enable_libv4l2}
+BuildRequires:  pkgconfig(libv4l2)
+%endif
 BuildRequires:  pkgconfig(dlog)
 BuildRequires:  mm-hal-interface-devel
 BuildRequires:  gtest-devel
@@ -23,7 +28,11 @@ Tizen Camera Hal for V4L2.
 
 %build
 ./autogen.sh
-%configure --disable-static
+%configure \
+%if 0%{?enable_libv4l2}
+       --enable-libv4l2\
+%endif
+       --disable-static
 make %{?jobs:-j%jobs}
 
 %install
index 46be497f5510df3453a0490d52c740bae4a7cec3..5f85a5542ec6b75e79ba7305c6c764092aaf1507 100644 (file)
@@ -15,6 +15,11 @@ libtizen_camera_la_LIBADD = $(GLIB_LIBS) \
                            $(DLOG_LIBS) \
                            $(TBM_LIBS)
 
+if HAVE_LIBV4L2
+libtizen_camera_la_CFLAGS += $(LIBV4L2_CFLAGS) -DHAVE_LIBV4L2
+libtizen_camera_la_LIBADD += $(LIBV4L2_LIBS)
+endif
+
 libtizen_camera_la_CFLAGS += -fdata-sections -ffunction-sections -Wl,--gc-sections
 libtizen_camera_la_LDFLAGS = -Wl,--gc-sections -avoid-version
 
index 11c1b32718572469a08a80a64eb98ad30127de01..bef5b7b3881eb02de04d2ac86c6176bd38cabac4 100644 (file)
@@ -124,7 +124,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;
 
@@ -144,7 +144,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);
 
@@ -159,7 +159,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;
        }
@@ -190,7 +190,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;
        }
@@ -224,7 +224,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;
@@ -259,7 +259,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",
@@ -397,12 +397,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;
@@ -417,7 +419,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;
                        }
@@ -485,6 +487,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_t *device_info_list = NULL;
@@ -539,9 +544,18 @@ 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);
                        continue;
@@ -562,7 +576,7 @@ static int __camera_get_device_info_list(void)
                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++;
@@ -607,7 +621,7 @@ static int __camera_stop_stream(camera_hal_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;
@@ -666,7 +680,7 @@ static int __camera_start_stream(camera_hal_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;
        }
@@ -688,7 +702,7 @@ static int __camera_start_stream(camera_hal_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;
        }
@@ -697,7 +711,7 @@ static int __camera_start_stream(camera_hal_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;
        }
@@ -723,7 +737,7 @@ static int __camera_start_stream(camera_hal_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;
                }
@@ -737,7 +751,7 @@ static int __camera_start_stream(camera_hal_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,
@@ -1131,6 +1145,12 @@ int camera_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);
@@ -1191,6 +1211,9 @@ int camera_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;
        camera_hal_handle *handle = (camera_hal_handle *)camera_handle;
 
@@ -1250,6 +1273,15 @@ int camera_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;
@@ -1283,7 +1315,7 @@ int camera_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 035316ba26648a707c906405b95b484f54372df7..da9aa4d0e9a86155986b2f6fcc37695f108289cd 100644 (file)
 #include <tbm_bufmgr.h>
 #include <tizen-camera.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