From 45b5ddaa81ecda875e4b04dc3088e11c1168dae0 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Tue, 17 Apr 2018 16:23:51 +0900 Subject: [PATCH 02/14] Initial release [Version] 0.0.1 [Profile] Common [Issue Type] New [Dependency module] N/A Change-Id: I1ba12660a4e2cfa6ba151a61faebf750c8adc5fb Signed-off-by: Jeongmo Yang --- AUTHORS | 1 + LICENSE.APLv2 | 206 +++++ Makefile.am | 1 + NOTICE | 3 + autogen.sh | 7 + camera-hal-v4l2.manifest | 5 + configure.ac | 59 ++ packaging/camera-hal-v4l2.spec | 43 + src/Makefile.am | 20 + src/tizen_camera_v4l2.c | 1685 +++++++++++++++++++++++++++++++++++++++ src/tizen_camera_v4l2_private.h | 81 ++ 11 files changed, 2111 insertions(+) create mode 100644 AUTHORS create mode 100644 LICENSE.APLv2 create mode 100644 Makefile.am create mode 100644 NOTICE create mode 100755 autogen.sh create mode 100644 camera-hal-v4l2.manifest create mode 100644 configure.ac create mode 100644 packaging/camera-hal-v4l2.spec create mode 100644 src/Makefile.am create mode 100644 src/tizen_camera_v4l2.c create mode 100644 src/tizen_camera_v4l2_private.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..7e88032 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Jeongmo Yang diff --git a/LICENSE.APLv2 b/LICENSE.APLv2 new file mode 100644 index 0000000..bbe9d02 --- /dev/null +++ b/LICENSE.APLv2 @@ -0,0 +1,206 @@ +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..af437a6 --- /dev/null +++ b/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..0e0f016 --- /dev/null +++ b/NOTICE @@ -0,0 +1,3 @@ +Copyright (c) Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under Apache License, Version 2. +Please, see the LICENSE.APLv2 file for Apache License terms and conditions. diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..f5469d7 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,7 @@ +#! /bin/sh + +libtoolize --copy --force +aclocal +autoheader +autoconf +automake -a -c diff --git a/camera-hal-v4l2.manifest b/camera-hal-v4l2.manifest new file mode 100644 index 0000000..a76fdba --- /dev/null +++ b/camera-hal-v4l2.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..e605900 --- /dev/null +++ b/configure.ac @@ -0,0 +1,59 @@ +AC_PREREQ(2.52) + +AC_INIT([camera-hal-v4l2], [0.8.0]) +AM_INIT_AUTOMAKE([-Wall -Werror foreign]) +AC_CONFIG_HEADERS([config.h:config.hin]) +AC_CONFIG_MACRO_DIR([m4]) + +# Checks for programs. +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) +AC_PROG_CC +AC_PROG_CXX +AM_PROG_CC_C_O +AC_C_CONST +dnl AC_FUNC_MALLOC +AC_FUNC_MMAP +AC_FUNC_REALLOC +AC_FUNC_SELECT_ARGTYPES +AC_FUNC_STAT +AC_FUNC_VPRINTF +AC_HEADER_STDBOOL +AC_HEADER_STDC +AC_HEADER_TIME +AC_PROG_GCC_TRADITIONAL +AC_PROG_LIBTOOL + +PKG_CHECK_MODULES(GLIB, glib-2.0) +AC_SUBST(GLIB_CFLAGS) +AC_SUBST(GLIB_LIBS) + +PKG_CHECK_MODULES(TBM, libtbm) +AC_SUBST(TBM_CFLAGS) +AC_SUBST(TBM_LIBS) + +PKG_CHECK_MODULES(DLOG, dlog) +AC_SUBST(DLOG_CFLAGS) +AC_SUBST(DLOG_LIBS) + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([fcntl.h memory.h stdlib.h string.h sys/time.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_PID_T +AC_TYPE_SIZE_T + +# Checks for library functions. +AC_FUNC_ALLOCA +AC_FUNC_FORK +AC_FUNC_MALLOC +AC_FUNC_MEMCMP +AC_FUNC_SELECT_ARGTYPES +AC_TYPE_SIGNAL +AC_CHECK_FUNCS([memset select]) +AC_CONFIG_FILES([ +Makefile +src/Makefile +]) +AC_OUTPUT diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec new file mode 100644 index 0000000..73acc1f --- /dev/null +++ b/packaging/camera-hal-v4l2.spec @@ -0,0 +1,43 @@ +Name: camera-hal-v4l2 +Summary: Tizen Camera Hal for V4L2 +Version: 0.0.1 +Release: 0 +Group: Multimedia/Libraries +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(libtbm) +BuildRequires: pkgconfig(dlog) +BuildRequires: mm-hal-interface-devel +BuildRequires: gtest-devel + +%description +Tizen Camera Hal for V4L2. + + +%prep +%setup -q + + +%build +./autogen.sh +%configure --disable-static +make %{?jobs:-j%jobs} + +%install +%make_install + + +%post +/sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files +%manifest %{name}.manifest +%license LICENSE.APLv2 +%defattr(-,root,root,-) +%{_libdir}/*.so + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..46be497 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,20 @@ +ACLOCAL_AMFLAGS='-I m4' + +lib_LTLIBRARIES = libtizen-camera.la + +noinst_HEADERS = tizen_camera_v4l2_private.h + +libtizen_camera_la_SOURCES = tizen_camera_v4l2.c + +libtizen_camera_la_CFLAGS = -I$(srcdir)/include \ + $(GLIB_CFLAGS) \ + $(DLOG_CFLAGS) \ + $(TBM_CFLAGS) + +libtizen_camera_la_LIBADD = $(GLIB_LIBS) \ + $(DLOG_LIBS) \ + $(TBM_LIBS) + +libtizen_camera_la_CFLAGS += -fdata-sections -ffunction-sections -Wl,--gc-sections +libtizen_camera_la_LDFLAGS = -Wl,--gc-sections -avoid-version + diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c new file mode 100644 index 0000000..f24bf92 --- /dev/null +++ b/src/tizen_camera_v4l2.c @@ -0,0 +1,1685 @@ +/* + * tizen_camera_v4l2.c + * + * Copyright (c) 2018 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. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tizen_camera_v4l2_private.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif /* LOG_TAG */ +#define LOG_TAG "CAMERA_HAL" + +#define TEST_JPEG_PATH "/home/owner/media/Images/test.jpg" +#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 camera_device_info_list_t *g_device_info_list; +static guint32 device_caps; +static GMutex g_device_info_lock; + + +static void _camera_hal_v4l2_destructor(void) __attribute__((destructor)); + +static void _camera_hal_v4l2_destructor(void) +{ + LOGD("release device info list %p", g_device_info_list); + + g_free(g_device_info_list); + + return; +} + +static int _camera_v4l2_wait_frame(int device_fd, int wait_time) +{ + int ret = CAMERA_ERROR_NONE; + fd_set fds; + struct timeval timeout; + + if (device_fd < 0) { + LOGE("invalid fd %d", device_fd); + return CAMERA_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 CAMERA_ERROR_NONE; + } + LOGE("select failed. errno %d", errno); + return CAMERA_ERROR_INTERNAL; + } + + if (ret == 0) { + LOGE("select timeout."); + return CAMERA_ERROR_INTERNAL; + } + + LOGD("select done"); + + return CAMERA_ERROR_NONE; +} + + +static int _camera_v4l2_stream(int device_fd, int type, gboolean onoff) +{ + if (device_fd < 0) { + LOGE("invalid fd %d", device_fd); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (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; + } + + LOGD("stream %d done [t:%d]", onoff, type); + + return CAMERA_ERROR_NONE; +} + + +static int _camera_v4l2_reqbufs(int device_fd, int type, int memory, int count, int *result_count) +{ + struct v4l2_requestbuffers v4l2_reqbuf; + + if (device_fd < 0) { + LOGE("invalid fd %d", device_fd); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (!result_count) { + LOGE("NULL parameter"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + memset(&v4l2_reqbuf, 0x0, sizeof(struct v4l2_requestbuffers)); + + v4l2_reqbuf.type = type; + v4l2_reqbuf.memory = memory; + v4l2_reqbuf.count = count; + + if (ioctl(device_fd, VIDIOC_REQBUFS, &v4l2_reqbuf) < 0) { + LOGE("REQBUFS[count %d] failed. errno %d", count, errno); + return CAMERA_ERROR_INTERNAL; + } + + if (v4l2_reqbuf.count != count) + LOGW("different count [req:%d, result:%d]", count, v4l2_reqbuf.count); + + *result_count = v4l2_reqbuf.count; + + return CAMERA_ERROR_NONE; +} + + +static int _camera_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 CAMERA_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; + v4l2_buf.length = 460800; + v4l2_buf.bytesused = 460800; + + if (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; + } + + LOGD("QBUF done [i: %d, t: %d, m: %d]", + index, type, memory); + + return CAMERA_ERROR_NONE; +} + + +static int _camera_v4l2_dqbuf(int device_fd, int type, int memory, int *index) +{ + int ret = CAMERA_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 CAMERA_ERROR_INVALID_PARAMETER; + } + + if (!index) { + LOGE("NULL parameter"); + return CAMERA_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 = 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 CAMERA_ERROR_DEVICE_READ; + } + } + + *index = v4l2_buf.index; + + LOGD("dqbuf index %d", *index); + + return CAMERA_ERROR_NONE; +} + + +static int _camera_get_format(guint32 fourcc, int *pixel_format) +{ + if (!pixel_format) { + LOGE("NULL parameter"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + switch (fourcc) { + case V4L2_PIX_FMT_NV12: + case V4L2_PIX_FMT_NV12M: + case V4L2_PIX_FMT_NV12MT: + *pixel_format = CAMERA_PIXEL_FORMAT_NV12; + break; + case V4L2_PIX_FMT_NV21: + case V4L2_PIX_FMT_NV21M: + *pixel_format = CAMERA_PIXEL_FORMAT_NV21; + break; + case V4L2_PIX_FMT_YUV420: + *pixel_format = CAMERA_PIXEL_FORMAT_I420; + break; + case V4L2_PIX_FMT_YVU420: + *pixel_format = CAMERA_PIXEL_FORMAT_YV12; + break; + case V4L2_PIX_FMT_YUYV: + *pixel_format = CAMERA_PIXEL_FORMAT_YUYV; + break; + case V4L2_PIX_FMT_UYVY: + *pixel_format = CAMERA_PIXEL_FORMAT_UYVY; + break; + case V4L2_PIX_FMT_JPEG: + *pixel_format = CAMERA_PIXEL_FORMAT_JPEG; + break; + case V4L2_PIX_FMT_H264: + *pixel_format = CAMERA_PIXEL_FORMAT_H264; + break; + default: + LOGE("unknown fourcc "FOURCC_FORMAT, FOURCC_CONVERT(fourcc)); + return CAMERA_ERROR_INTERNAL; + } + + LOGD("fourcc "FOURCC_FORMAT" -> %d", + FOURCC_CONVERT(fourcc), *pixel_format); + + return CAMERA_ERROR_NONE; +} + +static int _camera_get_fourcc_plane_num(int pixel_format, guint32 *fourcc, uint8_t *plane_num) +{ + if (!fourcc || !plane_num) { + LOGE("NULL parameter %p %p", fourcc, plane_num); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + switch (pixel_format) { + case CAMERA_PIXEL_FORMAT_NV12: + *fourcc = V4L2_PIX_FMT_NV12; + *plane_num = 2; + break; + case CAMERA_PIXEL_FORMAT_NV21: + *fourcc = V4L2_PIX_FMT_NV21; + *plane_num = 2; + break; + case CAMERA_PIXEL_FORMAT_I420: + *fourcc = V4L2_PIX_FMT_YUV420; + *plane_num = 3; + break; + case CAMERA_PIXEL_FORMAT_YV12: + *fourcc = V4L2_PIX_FMT_YVU420; + *plane_num = 3; + break; + case CAMERA_PIXEL_FORMAT_YUYV: + *fourcc = V4L2_PIX_FMT_YUYV; + *plane_num = 1; + break; + case CAMERA_PIXEL_FORMAT_UYVY: + *fourcc = V4L2_PIX_FMT_UYVY; + *plane_num = 1; + break; + case CAMERA_PIXEL_FORMAT_JPEG: + *fourcc = V4L2_PIX_FMT_JPEG; + *plane_num = 1; + break; + case CAMERA_PIXEL_FORMAT_H264: + *fourcc = V4L2_PIX_FMT_H264; + *plane_num = 1; + break; + default: + LOGE("unknown format %d", pixel_format); + return CAMERA_ERROR_INTERNAL; + } + + LOGD("format %d -> fourcc "FOURCC_FORMAT, + pixel_format, FOURCC_CONVERT(*fourcc)); + + return CAMERA_ERROR_NONE; +} + + +static int _camera_get_device_info(int device_index, int device_fd, camera_device_info_t *device_info, char *node_path) +{ + int i = 0; + int j = 0; + int format_count = 0; + int resolution_count = 0; + int camera_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 CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGD("Get Supported format and resolution"); + + for (i = 0 ; ; i++) { + memset(&v4l2_format, 0x0, sizeof(struct v4l2_fmtdesc)); + + v4l2_format.index = i; + v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (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)); + + if (_camera_get_format(v4l2_format.pixelformat, &camera_format) != CAMERA_ERROR_NONE) + continue; + + device_info->format_list.formats[format_count] = camera_format; + + resolution_count = 0; + + for (j = 0 ; ; j++) { + memset(&v4l2_frame, 0x0, sizeof(struct v4l2_frmsizeenum)); + + v4l2_frame.index = j; + v4l2_frame.pixel_format = v4l2_format.pixelformat; + + if (ioctl(device_fd, VIDIOC_ENUM_FRAMESIZES, &v4l2_frame) < 0) { + LOGW("\t\tframe : end of enumeration "); + break; + } + + switch (v4l2_frame.type) { + case V4L2_FRMSIZE_TYPE_DISCRETE: + device_info->preview_list.resolutions[resolution_count].width = v4l2_frame.discrete.width; + device_info->preview_list.resolutions[resolution_count].height = v4l2_frame.discrete.height; + device_info->capture_list.resolutions[resolution_count].width = v4l2_frame.discrete.width; + device_info->capture_list.resolutions[resolution_count].height = v4l2_frame.discrete.height; + device_info->video_list.resolutions[resolution_count].width = v4l2_frame.discrete.width; + device_info->video_list.resolutions[resolution_count].height = v4l2_frame.discrete.height; + + resolution_count++; + + LOGD("\t\tsize[%d] %ux%u", j, + v4l2_frame.discrete.width, + v4l2_frame.discrete.height); + break; + case V4L2_FRMSIZE_TYPE_CONTINUOUS: + LOGW("\t\tsize[%d] %ux%u - %ux%u", j, + 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)", + 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; + } + } + + device_info->preview_list.count = resolution_count; + device_info->capture_list.count = resolution_count; + device_info->video_list.count = resolution_count; + + LOGD("\t\tresolution count [%d]", resolution_count); + + format_count++; + } + + device_info->index = device_index; + device_info->format_list.count = format_count; + device_info->facing_direction = CAMERA_FACING_DIRECTION_EXTERNAL; + 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]", format_count); + + return CAMERA_ERROR_NONE; +} + +static int _camera_get_device_info_list(void) +{ + int i = 0; + int ret = 0; + int device_count = 0; + int device_fd = CAMERA_HAL_INITIAL_FD; + glob_t glob_buf; + struct v4l2_capability v4l2_cap; + camera_device_info_list_t *device_info_list = NULL; + + g_mutex_lock(&g_device_info_lock); + + if (g_device_info_list) { + LOGD("device info list is already existed"); + ret = CAMERA_ERROR_NONE; + goto _GET_DEVICE_INFO_LIST_DONE; + } + + device_info_list = g_new0(camera_device_info_list_t, 1); + if (!device_info_list) { + LOGE("failed to alloc device info structure"); + ret = CAMERA_ERROR_OUT_OF_MEMORY; + 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 = CAMERA_ERROR_OUT_OF_MEMORY; + goto _GET_DEVICE_INFO_LIST_DONE; + case GLOB_ABORTED: + LOGE("read error"); + ret = CAMERA_ERROR_INTERNAL; + goto _GET_DEVICE_INFO_LIST_DONE; + case GLOB_NOMATCH: + LOGE("match not found"); + ret = CAMERA_ERROR_INTERNAL; + goto _GET_DEVICE_INFO_LIST_DONE; + default: + LOGE("unknown eror : %d", ret); + ret = CAMERA_ERROR_INTERNAL; + goto _GET_DEVICE_INFO_LIST_DONE; + } + } + + LOGD("device node count : %d", 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; + } + + memset(&v4l2_cap, 0x0, sizeof(struct v4l2_capability)); + + if (ioctl(device_fd, VIDIOC_QUERYCAP, &v4l2_cap) < 0) { + LOGE("querycap failed. errno %d", errno); + close(device_fd); + continue; + } + + if (v4l2_cap.capabilities & V4L2_CAP_DEVICE_CAPS) + device_caps = v4l2_cap.device_caps; + else + device_caps = v4l2_cap.capabilities; + + if (!(device_caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)) || + (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], device_caps); + 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); + + if (ret == CAMERA_ERROR_NONE) + device_count++; + } + + device_info_list->count = device_count; + g_device_info_list = device_info_list; + + LOGD("new g_device_info_list %p - device count %d", + g_device_info_list, device_count); + +_GET_DEVICE_INFO_LIST_DONE: + g_mutex_unlock(&g_device_info_lock); + LOGD("ret 0x%x", ret); + + if (ret != CAMERA_ERROR_NONE) + g_free(device_info_list); + + return ret; +} + + +static void *_camera_preview_handler_func(gpointer data) +{ + int index = 0; + camera_hal_handle *handle = (camera_hal_handle *)data; + + if (!handle) { + LOGE("NULL handle for preview handler"); + return NULL; + } + + LOGD("enter - preview handler thread"); + + /* run buffer thread */ + g_mutex_lock(&handle->preview_cb_lock); + + while (handle->preview_cb_run) { + if (_camera_v4l2_wait_frame(handle->device_fd, 5) != CAMERA_ERROR_NONE) { + LOGE("frame wait failed"); + break; + } + + if (_camera_v4l2_dqbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, &index) != CAMERA_ERROR_NONE) { + LOGE("dqbuf failed"); + break; + } + + handle->live_buffer_num++; + + LOGD("live buffer num %d", handle->live_buffer_num); + + g_mutex_unlock(&handle->preview_cb_lock); + + if (handle->preview_cb) { + ((camera_preview_frame_cb)handle->preview_cb)(&handle->preview_buffer[index], NULL, handle->preview_cb_data); + } else { + LOGW("preview callback is NULL"); + camera_release_preview_buffer((void *)handle, index); + } + + sched_yield(); + + g_mutex_lock(&handle->preview_cb_lock); + } + + g_mutex_unlock(&handle->preview_cb_lock); + + LOGD("leave - preview handler thread"); + + return NULL; +} + + +static void _camera_message_release_func(gpointer data) +{ + camera_message_t *message = (camera_message_t *)data; + + if (!message) { + LOGW("NULL message"); + return; + } + + LOGD("release message %p, type %d", message, message->type); + + g_free(message); + + return; +} + + +static void *_camera_message_handler_func(gpointer data) +{ + int i = 0; + camera_message_t *message = NULL; + camera_hal_handle *handle = (camera_hal_handle *)data; + + if (!handle) { + LOGE("NULL handle for capture thread"); + return NULL; + } + + LOGD("enter - message thread"); + + g_mutex_lock(&handle->message_cb_lock); + + while (handle->message_cb_run) { + if (g_queue_is_empty(handle->message_list)) { + LOGD("wait for message"); + g_cond_wait(&handle->message_cb_cond, &handle->message_cb_lock); + LOGD("message signal received"); + } + + if (!handle->message_cb_run) { + LOGW("break message thread"); + break; + } + + message = g_queue_pop_head(handle->message_list); + if (!message) { + LOGW("NULL message"); + continue; + } + + g_mutex_unlock(&handle->message_cb_lock); + + for (i = 0 ; i < MESSAGE_CALLBACK_MAX ; i++) { + if (handle->message_cb[i]) { + LOGD("call message callback type %d", message->type); + ((camera_message_cb)handle->message_cb[i])(message, handle->message_cb_data[i]); + } + } + + g_free(message); + message = NULL; + + g_mutex_lock(&handle->message_cb_lock); + } + + g_mutex_unlock(&handle->message_cb_lock); + + LOGD("leave - message thread"); + + return NULL; +} + + +void _camera_release_handle(camera_hal_handle *handle) +{ + if (!handle) { + LOGW("NULL handle"); + return; + } + + if (handle->message_thread) { + g_mutex_lock(&handle->message_cb_lock); + handle->message_cb_run = FALSE; + g_cond_signal(&handle->message_cb_cond); + g_mutex_unlock(&handle->message_cb_lock); + g_thread_join(handle->message_thread); + g_queue_free_full(handle->message_list, (GDestroyNotify)_camera_message_release_func); + handle->message_list = NULL; + } + + g_mutex_clear(&handle->lock); + g_mutex_clear(&handle->preview_cb_lock); + g_mutex_clear(&handle->message_cb_lock); + g_cond_clear(&handle->preview_cb_cond); + g_cond_clear(&handle->message_cb_cond); + + if (handle->bufmgr) { + tbm_bufmgr_deinit(handle->bufmgr); + handle->bufmgr = NULL; + } + + LOGD("camera HAL handle %p destroy", handle); + + g_free(handle); + + return; +} + + +int camera_init(void **camera_handle) +{ + int ret = CAMERA_ERROR_NONE; + camera_hal_handle *new_handle = NULL; + tbm_bufmgr bufmgr = NULL; + + LOGD("enter"); + + if (!camera_handle) { + LOGE("NULL pointer for handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + bufmgr = tbm_bufmgr_init(-1); + if (bufmgr == NULL) { + LOGE("get tbm bufmgr failed"); + return CAMERA_ERROR_INTERNAL; + } + + new_handle = g_new0(camera_hal_handle, 1); + if (!new_handle) { + LOGE("failed to alloc camera hal handle"); + tbm_bufmgr_deinit(bufmgr); + return CAMERA_ERROR_OUT_OF_MEMORY; + } + + new_handle->bufmgr = bufmgr; + + g_mutex_init(&new_handle->lock); + g_mutex_init(&new_handle->preview_cb_lock); + g_mutex_init(&new_handle->message_cb_lock); + g_cond_init(&new_handle->preview_cb_cond); + g_cond_init(&new_handle->message_cb_cond); + + /* message thread */ + new_handle->message_list = g_queue_new(); + new_handle->message_cb_run = TRUE; + new_handle->message_thread = g_thread_try_new("camera_hal_message_thread", + _camera_message_handler_func, (gpointer)new_handle, NULL); + if (!new_handle->message_thread) { + LOGE("failed to create message thread"); + ret = CAMERA_ERROR_INTERNAL; + goto _INIT_ERROR; + } + + new_handle->device_index = CAMERA_HAL_INITIAL_INDEX; + new_handle->device_fd = CAMERA_HAL_INITIAL_FD; + new_handle->state = CAMERA_STATE_INITIALIZED; + + ret = _camera_get_device_info_list(); + if (ret != CAMERA_ERROR_NONE) { + LOGE("get device info failed"); + goto _INIT_ERROR; + } + + *camera_handle = new_handle; + + LOGD("camera HAL handle %p", new_handle); + + return CAMERA_ERROR_NONE; + +_INIT_ERROR: + _camera_release_handle(new_handle); + + return ret; +} + +int camera_deinit(void *camera_handle) +{ + camera_hal_handle *handle = NULL; + + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + handle = (camera_hal_handle *)camera_handle; + + g_mutex_lock(&handle->lock); + + if (handle->state != CAMERA_STATE_INITIALIZED) { + LOGE("invalid state %d, can not destroy handle", handle->state); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INVALID_STATE; + } + + g_mutex_unlock(&handle->lock); + + _camera_release_handle(handle); + + return CAMERA_ERROR_NONE; +} + +int camera_get_device_info_list(camera_device_info_list_t *device_info_list) +{ + int ret = 0; + + if (!device_info_list) { + LOGE("NULL pointer for device_info_list"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + ret = _camera_get_device_info_list(); + if (ret != CAMERA_ERROR_NONE) { + LOGE("get device info failed"); + return ret; + } + + memcpy(device_info_list, g_device_info_list, sizeof(camera_device_info_list_t)); + + return CAMERA_ERROR_NONE; +} + +int camera_open_device(void *camera_handle, int device_index) +{ + int ret = CAMERA_ERROR_NONE; + int device_fd = CAMERA_HAL_INITIAL_FD; + char *node_path = NULL; + camera_hal_handle *handle = NULL; + + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + handle = (camera_hal_handle *)camera_handle; + + g_mutex_lock(&handle->lock); + + if (handle->state != CAMERA_STATE_INITIALIZED) { + LOGE("invalid state %d", handle->state); + ret = CAMERA_ERROR_INVALID_STATE; + goto _OPEN_DEVICE_DONE; + } + + if (!g_device_info_list) { + LOGE("NO DEVICE INFO"); + ret = CAMERA_ERROR_INTERNAL; + goto _OPEN_DEVICE_DONE; + } + + if (device_index >= g_device_info_list->count) { + LOGE("invalid index %d [info:%d]", device_index, g_device_info_list->count); + ret = CAMERA_ERROR_INVALID_PARAMETER; + goto _OPEN_DEVICE_DONE; + } + + node_path = g_device_info_list->device_info[device_index].node_path; + + device_fd = open(node_path, O_RDWR); + if (device_fd < 0) { + switch (errno) { + case EACCES: + case EPERM: + ret = CAMERA_ERROR_PERMISSION_DENIED; + break; + case ENOENT: + ret = CAMERA_ERROR_DEVICE_NOT_FOUND; + break; + case EBUSY: + ret = CAMERA_ERROR_DEVICE_BUSY; + break; + default: + ret = CAMERA_ERROR_DEVICE_OPEN; + break; + } + + LOGE("open [%s] failed 0x%x [errno %d]", + node_path, ret, errno); + + goto _OPEN_DEVICE_DONE; + } + + if (device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) + handle->v4l2_type = V4L2_CAP_VIDEO_CAPTURE_MPLANE; + else + handle->v4l2_type = V4L2_CAP_VIDEO_CAPTURE; + + handle->state = CAMERA_STATE_OPENED; + handle->device_index = device_index; + handle->device_fd = device_fd; + + LOGD("[%d] device[%s] opened [fd %d, type %d]", + device_index, node_path, device_fd, handle->v4l2_type); + +_OPEN_DEVICE_DONE: + g_mutex_unlock(&handle->lock); + + return ret; +} + +int camera_close_device(void *camera_handle) +{ + camera_hal_handle *handle = NULL; + + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + handle = (camera_hal_handle *)camera_handle; + + g_mutex_lock(&handle->lock); + + if (handle->state != CAMERA_STATE_OPENED) { + LOGE("invalid state %d", handle->state); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INVALID_STATE; + } + + if (handle->device_fd >= 0) { + LOGD("close fd %d", handle->device_fd); + + close(handle->device_fd); + handle->device_fd = CAMERA_HAL_INITIAL_FD; + } else { + LOGW("invalid fd %d", handle->device_fd); + } + + handle->state = CAMERA_STATE_INITIALIZED; + + LOGD("device [%d] closed", handle->device_index); + + g_mutex_unlock(&handle->lock); + + return CAMERA_ERROR_NONE; +} + +int camera_add_message_callback(void *camera_handle, camera_message_cb callback, void *user_data, uint32_t *cb_id) +{ + uint32_t i = 0; + camera_hal_handle *handle = NULL; + + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (!callback || !cb_id) { + LOGE("NULL pointer for callback %p or cb_id %p", callback, cb_id); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + handle = (camera_hal_handle *)camera_handle; + + g_mutex_lock(&handle->lock); + + if (handle->state != CAMERA_STATE_OPENED) { + LOGE("invalid state %d", handle->state); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INVALID_STATE; + } + + for (i = 0 ; i < MESSAGE_CALLBACK_MAX ; i++) { + if (handle->message_cb[i] == NULL) { + handle->message_cb[i] = callback; + handle->message_cb_data[i] = user_data; + *cb_id = i; + LOGD("message cb [%p] added, user data %p - id %u", callback, user_data, i); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_NONE; + } + } + + g_mutex_unlock(&handle->lock); + + LOGE("no available message cb slot"); + + return CAMERA_ERROR_INTERNAL; +} + +int camera_remove_message_callback(void *camera_handle, uint32_t cb_id) +{ + camera_hal_handle *handle = NULL; + + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (cb_id >= MESSAGE_CALLBACK_MAX) { + LOGE("invalid cb_id %u", cb_id); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + handle = (camera_hal_handle *)camera_handle; + + g_mutex_lock(&handle->lock); + + if (handle->state != CAMERA_STATE_OPENED) { + LOGE("invalid state %d", handle->state); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INVALID_STATE; + } + + if (cb_id >= MESSAGE_CALLBACK_MAX) { + LOGE("invalid id %u", cb_id); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (handle->message_cb[cb_id]) { + LOGD("remove message callback %p, user data %p - cb_id %u", + handle->message_cb[cb_id], handle->message_cb_data[cb_id], cb_id); + + handle->message_cb[cb_id] = NULL; + handle->message_cb_data[cb_id] = NULL; + } else { + LOGE("already removed message cb"); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INTERNAL; + } + + g_mutex_unlock(&handle->lock); + + return CAMERA_ERROR_NONE; +} + +int camera_set_preview_stream_format(void *camera_handle, camera_format_t *format) +{ + int i = 0; + int j = 0; + int ret = CAMERA_ERROR_NONE; + gboolean capability_check = FALSE; + guint32 fourcc = 0; + camera_hal_handle *handle = NULL; + camera_device_info_t *device_info = NULL; + struct v4l2_format v4l2_fmt; + struct v4l2_streamparm v4l2_parm; + + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (!format) { + LOGE("NULL format"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (!g_device_info_list) { + LOGE("no device info list"); + return CAMERA_ERROR_INTERNAL; + } + + handle = (camera_hal_handle *)camera_handle; + + g_mutex_lock(&handle->lock); + + if (handle->state != CAMERA_STATE_OPENED) { + LOGE("invalid state %d", handle->state); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INVALID_STATE; + } + + /* check capability */ + device_info = &g_device_info_list->device_info[handle->device_index]; + + /* format */ + for (i = 0 ; i < device_info->format_list.count ; i++) { + if (format->stream_format == device_info->format_list.formats[i]) { + LOGD("format matched %d, check resolution.", format->stream_format); + + /* resolution */ + for (j = 0 ; j < device_info->preview_list.count ; j++) { + if (format->stream_resolution.width == device_info->preview_list.resolutions[j].width && + format->stream_resolution.height == device_info->preview_list.resolutions[j].height) { + LOGD("resolution matched %dx%d", + format->stream_resolution.width, + format->stream_resolution.height); + capability_check = TRUE; + break; + } + } + + break; + } + } + + if (!capability_check) { + LOGE("capability failed - %d, %dx%d", + format->stream_format, + format->stream_resolution.width, + format->stream_resolution.height); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + /* S_FMT */ + ret = _camera_get_fourcc_plane_num(format->stream_format, &fourcc, &handle->plane_num); + if (ret != CAMERA_ERROR_NONE) { + LOGE("get fourcc failed [format %d]", format->stream_format); + g_mutex_unlock(&handle->lock); + return ret; + } + + memset(&v4l2_fmt, 0x0, sizeof(struct v4l2_format)); + + v4l2_fmt.type = handle->v4l2_type; + if (V4L2_TYPE_IS_MULTIPLANAR(handle->v4l2_type)) { + v4l2_fmt.fmt.pix_mp.width = format->stream_resolution.width; + v4l2_fmt.fmt.pix_mp.height = format->stream_resolution.height; + v4l2_fmt.fmt.pix_mp.pixelformat = fourcc; + v4l2_fmt.fmt.pix_mp.num_planes = handle->plane_num; + } else { + v4l2_fmt.fmt.pix.width = format->stream_resolution.width; + v4l2_fmt.fmt.pix.height = format->stream_resolution.height; + v4l2_fmt.fmt.pix.pixelformat = fourcc; + v4l2_fmt.fmt.pix.bytesperline = format->stream_resolution.width; + } + + if (ioctl(handle->device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) { + LOGE("S_FMT failed. errno %d", errno); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INTERNAL; + } + + if (V4L2_TYPE_IS_MULTIPLANAR(handle->v4l2_type)) { + for (i = 0 ; i < v4l2_fmt.fmt.pix_mp.num_planes ; i++) { + LOGD("plane[%d] stride %d, sizeimage %d", + v4l2_fmt.fmt.pix_mp.plane_fmt[i].bytesperline, + v4l2_fmt.fmt.pix_mp.plane_fmt[i].sizeimage); + } + } else { + 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->v4l2_type; + + if (ioctl(handle->device_fd, VIDIOC_G_PARM, &v4l2_parm) < 0) { + LOGE("G_PARM failed. errno %d", errno); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INTERNAL; + } + + /* S_PARM to set fps */ + v4l2_parm.parm.capture.timeperframe.numerator = 1; + v4l2_parm.parm.capture.timeperframe.denominator = format->stream_fps; + + if (ioctl(handle->device_fd, VIDIOC_S_PARM, &v4l2_parm) < 0) { + LOGE("S_PARM failed. errno %d", errno); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INTERNAL; + } + + memcpy(&handle->preview_format, format, sizeof(camera_format_t)); + + LOGD("set preview stream [%d: %dx%d, fps %d]", + format->stream_format, + format->stream_resolution.width, + format->stream_resolution.height, + format->stream_fps); + + LOGW("CAPTURE STREAM [%d: %dx%d] IS NOT SUPPORTED", + format->capture_format, + format->capture_resolution.width, + format->capture_resolution.height); + + g_mutex_unlock(&handle->lock); + + return CAMERA_ERROR_NONE; +} + +int camera_get_preview_stream_format(void *camera_handle, camera_format_t *format) +{ + camera_hal_handle *handle = NULL; + + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (!format) { + LOGE("NULL format"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + handle = (camera_hal_handle *)camera_handle; + + g_mutex_lock(&handle->lock); + + memcpy(format, &handle->preview_format, sizeof(camera_format_t)); + + LOGD("get stream format %d, %dx%d", format->stream_format, + format->stream_resolution.width, format->stream_resolution.height); + + g_mutex_unlock(&handle->lock); + + return CAMERA_ERROR_NONE; +} + + +int camera_start_preview(void *camera_handle, camera_preview_frame_cb callback, void *user_data) +{ + int i = 0; + int ret = 0; + int result_count = 0; + camera_hal_handle *handle = NULL; + camera_buffer_t *buffer = NULL; + + struct v4l2_buffer v4l2_buf; + struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX]; + + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (!callback) { + LOGE("NULL callback for preview"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + handle = (camera_hal_handle *)camera_handle; + + g_mutex_lock(&handle->lock); + + if (handle->state != CAMERA_STATE_OPENED) { + LOGE("invalid state %d", handle->state); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INVALID_STATE; + } + + /* request buffer */ + ret = _camera_v4l2_reqbufs(handle->device_fd, + handle->v4l2_type, V4L2_MEMORY_MMAP, PREVIEW_BUFFER_MAX, &result_count); + if (ret != CAMERA_ERROR_NONE) { + g_mutex_unlock(&handle->lock); + return ret; + } + + LOGD("REQUESTED buffer count %d", result_count); + + handle->preview_buffer_num = result_count; + + /* query buffer, mmap and qbuf */ + for (i = 0 ; i < handle->preview_buffer_num ; i++) { + memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer)); + memset(v4l2_planes, 0x0, sizeof(v4l2_planes)); + + v4l2_buf.type = handle->v4l2_type; + v4l2_buf.memory = V4L2_MEMORY_MMAP; + v4l2_buf.index = i; + v4l2_buf.m.planes = v4l2_planes; + v4l2_buf.length = handle->plane_num; + + if (ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) { + LOGE("[%d] query buf failed. errno %d", i, errno); + goto _START_PREVIEW_FAILED; + } + + buffer = &handle->preview_buffer[i]; + + buffer->index = i; + buffer->format = handle->preview_format.stream_format; + buffer->resolution = handle->preview_format.stream_resolution; + buffer->total_size = v4l2_buf.length; + buffer->num_planes = handle->plane_num; + buffer->planes[0].size = v4l2_buf.length; + buffer->planes[0].data = 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_PREVIEW_FAILED; + } + } + + for (i = 0 ; i < handle->preview_buffer_num ; i++) { + if (_camera_v4l2_qbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, i) != CAMERA_ERROR_NONE) { + LOGE("qbuf failed"); + goto _START_PREVIEW_FAILED; + } + } + + /* stream on */ + ret = _camera_v4l2_stream(handle->device_fd, handle->v4l2_type, TRUE); + if (ret != CAMERA_ERROR_NONE) { + LOGE("stream on failed"); + goto _START_PREVIEW_FAILED; + } + + g_mutex_lock(&handle->preview_cb_lock); + + handle->preview_cb_run = TRUE; + + handle->preview_thread = g_thread_try_new("camera_hal_preview_thread", + _camera_preview_handler_func, (gpointer)handle, NULL); + if (!handle->preview_thread) { + LOGE("failed to create preview callback thread"); + g_mutex_unlock(&handle->preview_cb_lock); + goto _START_PREVIEW_FAILED; + } + + handle->preview_cb = callback; + handle->preview_cb_data = user_data; + + g_mutex_unlock(&handle->preview_cb_lock); + + handle->state = CAMERA_STATE_PREVIEWING; + + LOGD("start preview done"); + + g_mutex_unlock(&handle->lock); + + return CAMERA_ERROR_NONE; + +_START_PREVIEW_FAILED: + /* stream off */ + if (ioctl(handle->device_fd, VIDIOC_STREAMOFF, &handle->v4l2_type) < 0) + LOGE("stream off failed. errno %d", errno); + + /* munmap */ + for (i = 0 ; i < handle->preview_buffer_num ; i++) { + buffer = &handle->preview_buffer[i]; + if (buffer->planes[0].data != NULL && + buffer->planes[0].data != MAP_FAILED) { + LOGW("munmap %p", buffer->planes[0].data); + munmap(buffer->planes[0].data, buffer->planes[0].size); + } + memset(buffer, 0x0, sizeof(camera_buffer_t)); + } + + /* reqbufs 0 */ + if (_camera_v4l2_reqbufs(handle->device_fd, + handle->v4l2_type, V4L2_MEMORY_MMAP, 0, &result_count) != CAMERA_ERROR_NONE) + LOGE("reqbufs 0 failed"); + + g_mutex_unlock(&handle->lock); + + return ret; +} + +int camera_release_preview_buffer(void *camera_handle, int buffer_index) +{ + int ret = CAMERA_ERROR_NONE; + camera_hal_handle *handle = NULL; + + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + handle = (camera_hal_handle *)camera_handle; + + g_mutex_lock(&handle->preview_cb_lock); + + if (buffer_index >= handle->preview_buffer_num) { + LOGE("invalid buffer index %d", buffer_index); + g_mutex_unlock(&handle->preview_cb_lock); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + ret = _camera_v4l2_qbuf(handle->device_fd, + handle->v4l2_type, V4L2_MEMORY_MMAP, buffer_index); + + if (ret == CAMERA_ERROR_NONE) { + handle->live_buffer_num--; + LOGD("qbud done : index %d, live buffer num %d", + buffer_index, handle->live_buffer_num); + } else { + LOGE("qbuf failed [index %d]", buffer_index); + } + + g_cond_signal(&handle->preview_cb_cond); + + g_mutex_unlock(&handle->preview_cb_lock); + + return ret; +} + +int camera_stop_preview(void *camera_handle) +{ + int ret = CAMERA_ERROR_NONE; + int i = 0; + int result_count = 0; + gint64 end_time; + camera_hal_handle *handle = NULL; + + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + handle = (camera_hal_handle *)camera_handle; + + LOGD("start"); + + g_mutex_lock(&handle->lock); + + if (handle->state != CAMERA_STATE_PREVIEWING) { + LOGE("invalid state %d", handle->state); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INVALID_STATE; + } + + g_mutex_lock(&handle->preview_cb_lock); + + handle->preview_cb_run = FALSE; + + while (handle->live_buffer_num > 0) { + LOGD("wait for live buffer [num %d]", handle->live_buffer_num); + end_time = g_get_monotonic_time() + 3 * G_TIME_SPAN_SECOND; + if (!g_cond_wait_until(&handle->preview_cb_cond, &handle->preview_cb_lock, end_time)) { + LOGE("buffer wait failed"); + break; + } else { + LOGD("signal received. check again..."); + } + } + + g_mutex_unlock(&handle->preview_cb_lock); + + /* stream off */ + ret = _camera_v4l2_stream(handle->device_fd, handle->v4l2_type, FALSE); + + LOGD("stream off : 0x%x", ret); + + /* munmap */ + for (i = 0 ; i < handle->preview_buffer_num ; i++) { + if (handle->preview_buffer[i].planes[0].data != NULL) { + LOGW("munmap %p", handle->preview_buffer[i].planes[0].data); + + munmap(handle->preview_buffer[i].planes[0].data, handle->preview_buffer[i].planes[0].size); + + handle->preview_buffer[i].planes[0].data = 0; + handle->preview_buffer[i].planes[0].size = 0; + } else { + LOGW("NULL data [index %d]", i); + } + } + + /* reqbufs 0 */ + ret = _camera_v4l2_reqbufs(handle->device_fd, + handle->v4l2_type, V4L2_MEMORY_MMAP, 0, &result_count); + + LOGD("reqbufs 0 : 0x%x", ret); + + /* wait for preview thread exit */ + g_thread_join(handle->preview_thread); + handle->preview_thread = NULL; + + handle->state = CAMERA_STATE_OPENED; + + LOGD("stop preview done"); + + g_mutex_unlock(&handle->lock); + + return CAMERA_ERROR_NONE; +} + +int camera_start_auto_focus(void *camera_handle) +{ + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGD("NOT SUPPORTED"); + + /* auto focus is not supported */ + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; +} + +int camera_stop_auto_focus(void *camera_handle) +{ + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGD("NOT SUPPORTED"); + + /* auto focus is not supported */ + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; +} + + +int camera_start_capture(void *camera_handle, camera_capture_cb callback, void *user_data) +{ + if (!camera_handle || !callback) { + LOGE("NULL handle %p or callback %p", camera_handle, callback); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGD("NOT SUPPORTED"); + + /* capture function is not supported */ + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; +} + +int camera_stop_capture(void *camera_handle) +{ + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGD("NOT SUPPORTED"); + + /* capture function is not supported */ + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; +} + +int camera_set_video_stream_format(void *camera_handle, camera_format_t *format) +{ + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (!format) { + LOGE("NULL format"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGD("NOT SUPPORTED"); + + /* single stream device can not support video stream */ + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; +} + +int camera_get_video_stream_format(void *camera_handle, camera_format_t *format) +{ + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (!format) { + LOGE("NULL format"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGD("NOT SUPPORTED"); + + /* single stream device can not support video stream */ + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; +} + +int camera_start_record(void *camera_handle, camera_video_frame_cb callback, void *user_data) +{ + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (!callback) { + LOGE("NULL callback for video"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGD("NOT SUPPORTED"); + + /* single stream device can not support video stream */ + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; +} + +int camera_release_video_buffer(void *camera_handle, int buffer_index) +{ + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGD("NOT SUPPORTED"); + + /* single stream device can not support video stream */ + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; +} + +int camera_stop_record(void *camera_handle) +{ + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGD("NOT SUPPORTED"); + + /* single stream device can not support video stream */ + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; +} + +int camera_set_command(void *camera_handle, int64_t command, void *value) +{ + camera_hal_handle *handle = NULL; + + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (!value) { + LOGE("invalid pointer for value"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + handle = (camera_hal_handle *)camera_handle; + + g_mutex_lock(&handle->lock); + + if (handle->state < CAMERA_STATE_OPENED) { + LOGE("invalid state %d", handle->state); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INVALID_STATE; + } + + LOGD("set command %lld - state %d", command, handle->state); + + /* TODO: to be implemented */ + + g_mutex_unlock(&handle->lock); + + return CAMERA_ERROR_NONE; +} + +int camera_get_command(void *camera_handle, int64_t command, void **value) +{ + camera_hal_handle *handle = NULL; + + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (!value) { + LOGE("invalid pointer for value"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + handle = (camera_hal_handle *)camera_handle; + + g_mutex_lock(&handle->lock); + + LOGD("get command %lld - state %d", command, handle->state); + + /* TODO: to be implemented */ + + g_mutex_unlock(&handle->lock); + + return CAMERA_ERROR_NONE; +} + +int camera_set_batch_command(void *camera_handle, camera_batch_command_control_t *batch_command, int64_t *error_command) +{ + camera_hal_handle *handle = NULL; + + if (!camera_handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (!batch_command) { + LOGE("invalid pointer for batch_command"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + handle = (camera_hal_handle *)camera_handle; + + g_mutex_lock(&handle->lock); + + LOGD("set batch command - flag 0x"PRIx64", state %d", + batch_command->command_set_flag, handle->state); + + /* TODO: to be implemented */ + + g_mutex_unlock(&handle->lock); + + return CAMERA_ERROR_NONE; +} diff --git a/src/tizen_camera_v4l2_private.h b/src/tizen_camera_v4l2_private.h new file mode 100644 index 0000000..e70ceac --- /dev/null +++ b/src/tizen_camera_v4l2_private.h @@ -0,0 +1,81 @@ +/* + * tizen_camera_private.c + * + * Copyright (c) 2018 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 __TIZEN_CAMERA_PRIVATE_H__ +#define __TIZEN_CAMERA_PRIVATE_H__ + +#include +#include +#include +#include + +#define CAMERA_HAL_INITIAL_INDEX -1 +#define CAMERA_HAL_INITIAL_FD -1 +#define MESSAGE_CALLBACK_MAX 10 +#define PREVIEW_BUFFER_MAX 4 +#define VIDEO_BUFFER_MAX 8 +#define V4L2_PLANES_MAX 4 + +typedef struct _camera_hal_handle { + tbm_bufmgr bufmgr; + + int device_index; + int device_fd; + camera_state_t state; + camera_format_t preview_format; + camera_format_t video_format; + + /* V4L2 */ + enum v4l2_buf_type v4l2_type; + uint8_t plane_num; + int live_buffer_num; + + /* thread */ + GThread *preview_thread; + GThread *message_thread; + + /* preview callback */ + camera_preview_frame_cb preview_cb; + void *preview_cb_data; + gboolean preview_cb_run; + uint32_t preview_buffer_num; + camera_buffer_t preview_buffer[PREVIEW_BUFFER_MAX]; + + /* video callback */ + camera_video_frame_cb video_cb; + void *video_cb_data; + gboolean video_cb_run; + uint32_t video_buffer_num; + camera_buffer_t video_buffer[VIDEO_BUFFER_MAX]; + + /* message callback */ + camera_message_cb message_cb[MESSAGE_CALLBACK_MAX]; + void *message_cb_data[MESSAGE_CALLBACK_MAX]; + gboolean message_cb_run; + GQueue *message_list; + + /* thread safe */ + GMutex lock; + GMutex preview_cb_lock; + GMutex message_cb_lock; + GCond preview_cb_cond; + GCond message_cb_cond; +} camera_hal_handle; + +#endif /* __TIZEN_CAMERA_PRIVATE_H__ */ -- 2.7.4 From e1621483eeb5733a879668f19e3c818f3ba19e84 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Wed, 8 Aug 2018 18:15:26 +0900 Subject: [PATCH 03/14] Update for camera_set/get_command function [Version] 0.0.2 [Profile] Common [Issue Type] Update [Dependency module] N/A Change-Id: Ia109d37b9f36258f06581425d0b791dee7fa84e2 Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 148 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 143 insertions(+), 7 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index 73acc1f..f589367 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.1 +Version: 0.0.2 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index f24bf92..fb7c87e 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -109,6 +109,48 @@ static int _camera_v4l2_wait_frame(int device_fd, int wait_time) } +static int _camera_v4l2_g_ctrl(int device_fd, int cid, int *value) +{ + int ret = 0; + struct v4l2_control ctrl; + + if (!value) { + LOGE("NULL param"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + memset(&ctrl, 0x0, sizeof(struct v4l2_control)); + + ctrl.id = cid; + + ret = ioctl(device_fd, VIDIOC_G_CTRL, &ctrl); + + *value = ctrl.value; + + LOGD("G_CTRL id 0x%x, value %d, ret %d", cid, *value, ret); + + return ret; +} + + +static int _camera_v4l2_s_ctrl(int device_fd, int cid, int value) +{ + int ret = 0; + struct v4l2_control ctrl; + + memset(&ctrl, 0x0, sizeof(struct v4l2_control)); + + ctrl.id = cid; + ctrl.value = value; + + ret = ioctl(device_fd, VIDIOC_S_CTRL, &ctrl); + + LOGD("S_CTRL id 0x%x, value %d, ret %d", cid, value, ret); + + return ret; +} + + static int _camera_v4l2_stream(int device_fd, int type, gboolean onoff) { if (device_fd < 0) { @@ -1598,6 +1640,9 @@ int camera_stop_record(void *camera_handle) int camera_set_command(void *camera_handle, int64_t command, void *value) { + int ret = CAMERA_ERROR_NONE; + int cid = 0; + int ctrl_ret = 0; camera_hal_handle *handle = NULL; if (!camera_handle) { @@ -1620,17 +1665,64 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) return CAMERA_ERROR_INVALID_STATE; } - LOGD("set command %lld - state %d", command, handle->state); + LOGD("set command %llx - state %d", command, handle->state); - /* TODO: to be implemented */ + switch (command) { + case CAMERA_COMMAND_EXPOSURE: + cid = V4L2_CID_BRIGHTNESS; + break; + case CAMERA_COMMAND_CONTRAST: + cid = V4L2_CID_CONTRAST; + break; + case CAMERA_COMMAND_SATURATION: + cid = V4L2_CID_SATURATION; + break; + case CAMERA_COMMAND_SHARPNESS: + cid = V4L2_CID_SHARPNESS; + break; + default: + LOGE("NOT_SUPPORTED %llx", command); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; + } + + ctrl_ret = _camera_v4l2_s_ctrl(handle->device_fd, cid, (int)value); + if (ctrl_ret < 0) { + switch (errno) { + case EACCES: + case EPERM: + LOGE("Permission denied %d", errno); + ret = CAMERA_ERROR_PERMISSION_DENIED; + break; + case EINVAL: + LOGE("Invalid argument"); + ret = CAMERA_ERROR_INVALID_PARAMETER; + break; + case EBUSY: + LOGE("Device busy"); + ret = CAMERA_ERROR_DEVICE_BUSY; + break; + case ENOTSUP: + LOGE("Not supported"); + ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED; + break; + default: + LOGE("Unknown errro %d", errno); + ret = CAMERA_ERROR_INTERNAL; + break; + } + } g_mutex_unlock(&handle->lock); - return CAMERA_ERROR_NONE; + return ret; } int camera_get_command(void *camera_handle, int64_t command, void **value) { + int ret = CAMERA_ERROR_NONE; + int cid = 0; + int ctrl_ret = 0; camera_hal_handle *handle = NULL; if (!camera_handle) { @@ -1647,13 +1739,57 @@ int camera_get_command(void *camera_handle, int64_t command, void **value) g_mutex_lock(&handle->lock); - LOGD("get command %lld - state %d", command, handle->state); + LOGD("get command %llx - state %d", command, handle->state); - /* TODO: to be implemented */ + switch (command) { + case CAMERA_COMMAND_EXPOSURE: + cid = V4L2_CID_BRIGHTNESS; + break; + case CAMERA_COMMAND_CONTRAST: + cid = V4L2_CID_CONTRAST; + break; + case CAMERA_COMMAND_SATURATION: + cid = V4L2_CID_SATURATION; + break; + case CAMERA_COMMAND_SHARPNESS: + cid = V4L2_CID_SHARPNESS; + break; + default: + LOGE("NOT_SUPPORTED %llx", command); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; + } + + ctrl_ret = _camera_v4l2_g_ctrl(handle->device_fd, cid, (int *)value); + if (ctrl_ret < 0) { + switch (errno) { + case EACCES: + case EPERM: + LOGE("Permission denied %d", errno); + ret = CAMERA_ERROR_PERMISSION_DENIED; + break; + case EINVAL: + LOGE("Invalid argument"); + ret = CAMERA_ERROR_INVALID_PARAMETER; + break; + case EBUSY: + LOGE("Device busy"); + ret = CAMERA_ERROR_DEVICE_BUSY; + break; + case ENOTSUP: + LOGE("Not supported"); + ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED; + break; + default: + LOGE("Unknown errro %d", errno); + ret = CAMERA_ERROR_INTERNAL; + break; + } + } g_mutex_unlock(&handle->lock); - return CAMERA_ERROR_NONE; + return ret; } int camera_set_batch_command(void *camera_handle, camera_batch_command_control_t *batch_command, int64_t *error_command) -- 2.7.4 From ff7ebca284823af0b138c7de1d0b96ca6dd1b3ee Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Fri, 7 Dec 2018 16:37:17 +0900 Subject: [PATCH 04/14] Fix invalid format usage [Version] 0.0.3 [Profile] Common [Issue Type] Bug fix [Dependency module] N/A Change-Id: I1845061b43cf8f662a469d482905fc69590df7c9 Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index f589367..f0ed83b 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.2 +Version: 0.0.3 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index fb7c87e..5184ac1 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -445,7 +445,7 @@ static int _camera_get_device_info(int device_index, int device_fd, camera_devic v4l2_frame.stepwise.max_height); break; case V4L2_FRMSIZE_TYPE_STEPWISE: - LOGW("\t\tsize[%d] %ux%u - %ux%u (step %ux%u)", + LOGW("\t\tsize[%d] %ux%u - %ux%u (step %ux%u)", j, v4l2_frame.stepwise.min_width, v4l2_frame.stepwise.min_height, v4l2_frame.stepwise.max_width, @@ -528,7 +528,7 @@ static int _camera_get_device_info_list(void) } } - LOGD("device node count : %d", glob_buf.gl_pathc); + 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]); @@ -1165,7 +1165,7 @@ int camera_set_preview_stream_format(void *camera_handle, camera_format_t *forma if (V4L2_TYPE_IS_MULTIPLANAR(handle->v4l2_type)) { for (i = 0 ; i < v4l2_fmt.fmt.pix_mp.num_planes ; i++) { - LOGD("plane[%d] stride %d, sizeimage %d", + 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); } @@ -1665,7 +1665,7 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) return CAMERA_ERROR_INVALID_STATE; } - LOGD("set command %llx - state %d", command, handle->state); + LOGD("set command %lx - state %d", command, handle->state); switch (command) { case CAMERA_COMMAND_EXPOSURE: @@ -1681,12 +1681,12 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) cid = V4L2_CID_SHARPNESS; break; default: - LOGE("NOT_SUPPORTED %llx", command); + LOGE("NOT_SUPPORTED %lx", command); g_mutex_unlock(&handle->lock); return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } - ctrl_ret = _camera_v4l2_s_ctrl(handle->device_fd, cid, (int)value); + ctrl_ret = _camera_v4l2_s_ctrl(handle->device_fd, cid, ((int)(long)value)); if (ctrl_ret < 0) { switch (errno) { case EACCES: @@ -1739,7 +1739,7 @@ int camera_get_command(void *camera_handle, int64_t command, void **value) g_mutex_lock(&handle->lock); - LOGD("get command %llx - state %d", command, handle->state); + LOGD("get command %lx - state %d", command, handle->state); switch (command) { case CAMERA_COMMAND_EXPOSURE: @@ -1755,7 +1755,7 @@ int camera_get_command(void *camera_handle, int64_t command, void **value) cid = V4L2_CID_SHARPNESS; break; default: - LOGE("NOT_SUPPORTED %llx", command); + LOGE("NOT_SUPPORTED %lx", command); g_mutex_unlock(&handle->lock); return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } @@ -1810,7 +1810,7 @@ int camera_set_batch_command(void *camera_handle, camera_batch_command_control_t g_mutex_lock(&handle->lock); - LOGD("set batch command - flag 0x"PRIx64", state %d", + LOGD("set batch command - flag 0x%lx, state %d", batch_command->command_set_flag, handle->state); /* TODO: to be implemented */ -- 2.7.4 From 8e299c246148640f243ce4ee16b4fc78d8be65bb Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Fri, 14 Dec 2018 10:39:58 +0900 Subject: [PATCH 05/14] Fix invalid format usage - Phase#2 [Version] 0.0.4 [Profile] Common [Issue Type] Bug fix [Dependency module] N/A Change-Id: I4ec0c4bfa11c5dc91a7aa21dc974bf418b9032de Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index f0ed83b..df55bef 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.3 +Version: 0.0.4 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index 5184ac1..923d70b 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -1665,7 +1665,7 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) return CAMERA_ERROR_INVALID_STATE; } - LOGD("set command %lx - state %d", command, handle->state); + LOGD("set command %"PRId64" - state %d", command, handle->state); switch (command) { case CAMERA_COMMAND_EXPOSURE: @@ -1681,7 +1681,7 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) cid = V4L2_CID_SHARPNESS; break; default: - LOGE("NOT_SUPPORTED %lx", command); + LOGE("NOT_SUPPORTED %"PRId64, command); g_mutex_unlock(&handle->lock); return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } @@ -1739,7 +1739,7 @@ int camera_get_command(void *camera_handle, int64_t command, void **value) g_mutex_lock(&handle->lock); - LOGD("get command %lx - state %d", command, handle->state); + LOGD("get command %"PRId64" - state %d", command, handle->state); switch (command) { case CAMERA_COMMAND_EXPOSURE: @@ -1755,7 +1755,7 @@ int camera_get_command(void *camera_handle, int64_t command, void **value) cid = V4L2_CID_SHARPNESS; break; default: - LOGE("NOT_SUPPORTED %lx", command); + LOGE("NOT_SUPPORTED %"PRId64, command); g_mutex_unlock(&handle->lock); return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } @@ -1810,7 +1810,7 @@ int camera_set_batch_command(void *camera_handle, camera_batch_command_control_t g_mutex_lock(&handle->lock); - LOGD("set batch command - flag 0x%lx, state %d", + LOGD("set batch command - flag %"PRIx64", state %d", batch_command->command_set_flag, handle->state); /* TODO: to be implemented */ -- 2.7.4 From d7a831b31c3414a8c815f35b0e10ae264b638c4f Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Thu, 10 Jan 2019 15:20:21 +0900 Subject: [PATCH 06/14] Fix deadlock issue between buffer release and preview handler functions [Version] 0.0.5 [Profile] Common [Issue Type] Bug fix [Dependency module] N/A Change-Id: Ifba0db26daf09ab7c7ab5e4dd99c9cc7704807db Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index df55bef..2ced257 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.4 +Version: 0.0.5 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index 923d70b..80b5f3c 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -601,16 +601,22 @@ static void *_camera_preview_handler_func(gpointer data) g_mutex_lock(&handle->preview_cb_lock); while (handle->preview_cb_run) { + g_mutex_unlock(&handle->preview_cb_lock); + if (_camera_v4l2_wait_frame(handle->device_fd, 5) != CAMERA_ERROR_NONE) { LOGE("frame wait failed"); + g_mutex_lock(&handle->preview_cb_lock); break; } if (_camera_v4l2_dqbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, &index) != CAMERA_ERROR_NONE) { LOGE("dqbuf failed"); + g_mutex_lock(&handle->preview_cb_lock); break; } + g_mutex_lock(&handle->preview_cb_lock); + handle->live_buffer_num++; LOGD("live buffer num %d", handle->live_buffer_num); @@ -1399,8 +1405,6 @@ int camera_release_preview_buffer(void *camera_handle, int buffer_index) handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->preview_cb_lock); - if (buffer_index >= handle->preview_buffer_num) { LOGE("invalid buffer index %d", buffer_index); g_mutex_unlock(&handle->preview_cb_lock); @@ -1410,6 +1414,8 @@ int camera_release_preview_buffer(void *camera_handle, int buffer_index) ret = _camera_v4l2_qbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, buffer_index); + g_mutex_lock(&handle->preview_cb_lock); + if (ret == CAMERA_ERROR_NONE) { handle->live_buffer_num--; LOGD("qbud done : index %d, live buffer num %d", -- 2.7.4 From c643fa1d227919b08f40ff7237083f6565b7999d Mon Sep 17 00:00:00 2001 From: Hyunil Date: Tue, 29 Jan 2019 13:08:11 +0900 Subject: [PATCH 07/14] Fix SVACE bug issue [Version] 0.0.6 [Profile] Common [Issue Type] Bug fix [Dependency module] N/A Change-Id: I387fe1c834304e02b7f376916d51ad32c4bcd3f7 Signed-off-by: Hyunil --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index 2ced257..3315fa4 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.5 +Version: 0.0.6 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index 80b5f3c..bd822b1 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -1047,12 +1047,6 @@ int camera_remove_message_callback(void *camera_handle, uint32_t cb_id) return CAMERA_ERROR_INVALID_STATE; } - if (cb_id >= MESSAGE_CALLBACK_MAX) { - LOGE("invalid id %u", cb_id); - g_mutex_unlock(&handle->lock); - return CAMERA_ERROR_INVALID_PARAMETER; - } - if (handle->message_cb[cb_id]) { LOGD("remove message callback %p, user data %p - cb_id %u", handle->message_cb[cb_id], handle->message_cb_data[cb_id], cb_id); -- 2.7.4 From 8a2c4ae5277603412da243befdb203427bb7988d Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Tue, 11 Jun 2019 18:30:54 +0900 Subject: [PATCH 08/14] Update set command function - Remove NULL check for value parameter, because it could be 0. - Support new camera control : PTZ type, Pan, Tilt [Version] 0.0.7 [Profile] Common [Issue Type] Update Change-Id: I7b3bb78789a50fa52f648ea3fc28e57cf1fbcbec Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index 3315fa4..908efe0 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.6 +Version: 0.0.7 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index bd822b1..e4d3ef3 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -1650,11 +1650,6 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) return CAMERA_ERROR_INVALID_PARAMETER; } - if (!value) { - LOGE("invalid pointer for value"); - return CAMERA_ERROR_INVALID_PARAMETER; - } - handle = (camera_hal_handle *)camera_handle; g_mutex_lock(&handle->lock); @@ -1680,6 +1675,21 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) case CAMERA_COMMAND_SHARPNESS: cid = V4L2_CID_SHARPNESS; break; + case CAMERA_COMMAND_PTZ_TYPE: + g_mutex_unlock(&handle->lock); + + if ((int)(long)value != CAMERA_PTZ_TYPE_ELECTRONIC) { + LOGE("not supported PTZ type %d", (int)(long)value); + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; + } + + return CAMERA_ERROR_NONE; + case CAMERA_COMMAND_PAN: + cid = V4L2_CID_PAN_ABSOLUTE; + break; + case CAMERA_COMMAND_TILT: + cid = V4L2_CID_TILT_ABSOLUTE; + break; default: LOGE("NOT_SUPPORTED %"PRId64, command); g_mutex_unlock(&handle->lock); -- 2.7.4 From cb6137278075bc5d3bebf45db6f51e0c750add32 Mon Sep 17 00:00:00 2001 From: Hyuntae Kim Date: Wed, 12 Jun 2019 15:15:14 +0900 Subject: [PATCH 09/14] Fix deadlock unlock fault Remove unlock code in return [Version] 0.0.7 [Profile] Common [Issue Type] Bug fix Change-Id: I90daaa0eb499dbdb0c3f63d88cc8b06b15312e34 --- src/tizen_camera_v4l2.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index e4d3ef3..262b0d6 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -1401,7 +1401,6 @@ int camera_release_preview_buffer(void *camera_handle, int buffer_index) if (buffer_index >= handle->preview_buffer_num) { LOGE("invalid buffer index %d", buffer_index); - g_mutex_unlock(&handle->preview_cb_lock); return CAMERA_ERROR_INVALID_PARAMETER; } -- 2.7.4 From 70d87d285e6536d76ac53e4157af39d52b29aaed Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Thu, 13 Jun 2019 11:29:03 +0900 Subject: [PATCH 10/14] Change camera command for brightness [Version] 0.0.8 [Profile] Common [Issue Type] Update Change-Id: I001c5d9359025e337b416134f93fdde7333a4cc1 Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index 908efe0..d22a8ed 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.7 +Version: 0.0.8 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index 262b0d6..5f96527 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -1662,7 +1662,7 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) LOGD("set command %"PRId64" - state %d", command, handle->state); switch (command) { - case CAMERA_COMMAND_EXPOSURE: + case CAMERA_COMMAND_BRIGHTNESS: cid = V4L2_CID_BRIGHTNESS; break; case CAMERA_COMMAND_CONTRAST: @@ -1751,7 +1751,7 @@ int camera_get_command(void *camera_handle, int64_t command, void **value) LOGD("get command %"PRId64" - state %d", command, handle->state); switch (command) { - case CAMERA_COMMAND_EXPOSURE: + case CAMERA_COMMAND_BRIGHTNESS: cid = V4L2_CID_BRIGHTNESS; break; case CAMERA_COMMAND_CONTRAST: -- 2.7.4 From 2150e4c44a29bc0e146ea1036091c13e62c3bd57 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Thu, 13 Jun 2019 15:24:54 +0900 Subject: [PATCH 11/14] Update set command function - Convert (void *) to (int *) and use it. [Version] 0.0.9 [Profile] Common [Issue Type] Update Change-Id: I24d185c4ddb5f7651c17a0a57573251a9c92a8cf Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index d22a8ed..cc1a87f 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.8 +Version: 0.0.9 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index 5f96527..5996772 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -1642,6 +1642,7 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) int ret = CAMERA_ERROR_NONE; int cid = 0; int ctrl_ret = 0; + int set_value = 0; camera_hal_handle *handle = NULL; if (!camera_handle) { @@ -1649,7 +1650,13 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) return CAMERA_ERROR_INVALID_PARAMETER; } + if (!value) { + LOGE("invalid pointer : value"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + handle = (camera_hal_handle *)camera_handle; + set_value = *(int *)value; g_mutex_lock(&handle->lock); @@ -1677,8 +1684,8 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) case CAMERA_COMMAND_PTZ_TYPE: g_mutex_unlock(&handle->lock); - if ((int)(long)value != CAMERA_PTZ_TYPE_ELECTRONIC) { - LOGE("not supported PTZ type %d", (int)(long)value); + if (set_value != CAMERA_PTZ_TYPE_ELECTRONIC) { + LOGE("not supported PTZ type %d", set_value); return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } @@ -1695,7 +1702,7 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } - ctrl_ret = _camera_v4l2_s_ctrl(handle->device_fd, cid, ((int)(long)value)); + ctrl_ret = _camera_v4l2_s_ctrl(handle->device_fd, cid, set_value); if (ctrl_ret < 0) { switch (errno) { case EACCES: -- 2.7.4 From a05da814de30ddfef5873ee5935aa07a9b852e1d Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Mon, 28 Oct 2019 16:07:29 +0900 Subject: [PATCH 12/14] Do not call DQBUF after stop_preview is called [Version] 0.0.10 [Profile] Common [Issue Type] Update Change-Id: I4ddc54a818b77cb6f4d4cec27eaa8bc03fe29e3c Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index cc1a87f..d77166d 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.9 +Version: 0.0.10 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index 5996772..6454cd6 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -609,14 +609,18 @@ static void *_camera_preview_handler_func(gpointer data) break; } + g_mutex_lock(&handle->preview_cb_lock); + + if (handle->preview_cb_run == FALSE) { + LOGW("stop preview handler thread"); + break; + } + if (_camera_v4l2_dqbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, &index) != CAMERA_ERROR_NONE) { LOGE("dqbuf failed"); - g_mutex_lock(&handle->preview_cb_lock); break; } - g_mutex_lock(&handle->preview_cb_lock); - handle->live_buffer_num++; LOGD("live buffer num %d", handle->live_buffer_num); -- 2.7.4 From 8906a575c14afae24c58bf6de6107c2d893d5819 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Wed, 22 Jul 2020 09:37:08 +0900 Subject: [PATCH 13/14] Revise code - Apply missed tizen coding rule - Add sub function for start/stop stream - Reduce code line to check invalid parameter - Remove unused code - Change the name of some preview related field in camera_hal_handle [Version] 0.0.11 [Profile] Common [Issue Type] Update Change-Id: Ic9991b248a22e52633a089c04d7388514933f42d Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 543 +++++++++++++++++++--------------------- src/tizen_camera_v4l2_private.h | 22 +- 3 files changed, 265 insertions(+), 302 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index d77166d..58bdca4 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.10 +Version: 0.0.11 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index 6454cd6..2b4b06d 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -52,22 +52,23 @@ static camera_device_info_list_t *g_device_info_list; -static guint32 device_caps; +static guint32 g_device_caps; static GMutex g_device_info_lock; -static void _camera_hal_v4l2_destructor(void) __attribute__((destructor)); +static void __camera_hal_v4l2_destructor(void) __attribute__((destructor)); -static void _camera_hal_v4l2_destructor(void) +static void __camera_hal_v4l2_destructor(void) { LOGD("release device info list %p", g_device_info_list); g_free(g_device_info_list); + g_device_info_list = NULL; return; } -static int _camera_v4l2_wait_frame(int device_fd, int wait_time) +static int __camera_v4l2_wait_frame(int device_fd, int wait_time) { int ret = CAMERA_ERROR_NONE; fd_set fds; @@ -86,7 +87,7 @@ static int _camera_v4l2_wait_frame(int device_fd, int wait_time) timeout.tv_sec = wait_time; timeout.tv_usec = 0; - LOGD("select : %d sec", wait_time); + /*LOGD("select : %d sec", wait_time);*/ ret = select(device_fd + 1, &fds, NULL, NULL, &timeout); if (ret == -1) { @@ -103,13 +104,13 @@ static int _camera_v4l2_wait_frame(int device_fd, int wait_time) return CAMERA_ERROR_INTERNAL; } - LOGD("select done"); + /*LOGD("select done");*/ return CAMERA_ERROR_NONE; } -static int _camera_v4l2_g_ctrl(int device_fd, int cid, int *value) +static int __camera_v4l2_g_ctrl(int device_fd, int cid, int *value) { int ret = 0; struct v4l2_control ctrl; @@ -133,7 +134,7 @@ static int _camera_v4l2_g_ctrl(int device_fd, int cid, int *value) } -static int _camera_v4l2_s_ctrl(int device_fd, int cid, int value) +static int __camera_v4l2_s_ctrl(int device_fd, int cid, int value) { int ret = 0; struct v4l2_control ctrl; @@ -151,7 +152,7 @@ static int _camera_v4l2_s_ctrl(int device_fd, int cid, int value) } -static int _camera_v4l2_stream(int device_fd, int type, gboolean onoff) +static int __camera_v4l2_stream(int device_fd, int type, gboolean onoff) { if (device_fd < 0) { LOGE("invalid fd %d", device_fd); @@ -169,7 +170,7 @@ static int _camera_v4l2_stream(int device_fd, int type, gboolean onoff) } -static int _camera_v4l2_reqbufs(int device_fd, int type, int memory, int count, int *result_count) +static int __camera_v4l2_reqbufs(int device_fd, int type, int memory, uint32_t count, uint32_t *result_count) { struct v4l2_requestbuffers v4l2_reqbuf; @@ -203,7 +204,7 @@ static int _camera_v4l2_reqbufs(int device_fd, int type, int memory, int count, } -static int _camera_v4l2_qbuf(int device_fd, int type, int memory, int index) +static int __camera_v4l2_qbuf(int device_fd, int type, int memory, int index) { struct v4l2_buffer v4l2_buf; struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX]; @@ -229,14 +230,13 @@ static int _camera_v4l2_qbuf(int device_fd, int type, int memory, int index) return CAMERA_ERROR_INTERNAL; } - LOGD("QBUF done [i: %d, t: %d, m: %d]", - index, type, memory); + /*LOGD("QBUF done [i: %d, t: %d, m: %d]", index, type, memory);*/ return CAMERA_ERROR_NONE; } -static int _camera_v4l2_dqbuf(int device_fd, int type, int memory, int *index) +static int __camera_v4l2_dqbuf(int device_fd, int type, int memory, int *index) { int ret = CAMERA_ERROR_NONE; struct v4l2_buffer v4l2_buf; @@ -270,13 +270,13 @@ static int _camera_v4l2_dqbuf(int device_fd, int type, int memory, int *index) *index = v4l2_buf.index; - LOGD("dqbuf index %d", *index); + /*LOGD("dqbuf index %d", *index);*/ return CAMERA_ERROR_NONE; } -static int _camera_get_format(guint32 fourcc, int *pixel_format) +static int __camera_get_format(guint32 fourcc, int *pixel_format) { if (!pixel_format) { LOGE("NULL parameter"); @@ -322,7 +322,7 @@ static int _camera_get_format(guint32 fourcc, int *pixel_format) return CAMERA_ERROR_NONE; } -static int _camera_get_fourcc_plane_num(int pixel_format, guint32 *fourcc, uint8_t *plane_num) +static int __camera_get_fourcc_plane_num(int pixel_format, guint32 *fourcc, uint8_t *plane_num) { if (!fourcc || !plane_num) { LOGE("NULL parameter %p %p", fourcc, plane_num); @@ -374,7 +374,7 @@ static int _camera_get_fourcc_plane_num(int pixel_format, guint32 *fourcc, uint8 } -static int _camera_get_device_info(int device_index, int device_fd, camera_device_info_t *device_info, char *node_path) +static int __camera_get_device_info(int device_index, int device_fd, camera_device_info_t *device_info, char *node_path) { int i = 0; int j = 0; @@ -404,7 +404,7 @@ static int _camera_get_device_info(int device_index, int device_fd, camera_devic LOGD("\tformat[%d] "FOURCC_FORMAT, i, FOURCC_CONVERT(v4l2_format.pixelformat)); - if (_camera_get_format(v4l2_format.pixelformat, &camera_format) != CAMERA_ERROR_NONE) + if (__camera_get_format(v4l2_format.pixelformat, &camera_format) != CAMERA_ERROR_NONE) continue; device_info->format_list.formats[format_count] = camera_format; @@ -479,7 +479,7 @@ static int _camera_get_device_info(int device_index, int device_fd, camera_devic return CAMERA_ERROR_NONE; } -static int _camera_get_device_info_list(void) +static int __camera_get_device_info_list(void) { int i = 0; int ret = 0; @@ -548,18 +548,18 @@ static int _camera_get_device_info_list(void) } if (v4l2_cap.capabilities & V4L2_CAP_DEVICE_CAPS) - device_caps = v4l2_cap.device_caps; + g_device_caps = v4l2_cap.device_caps; else - device_caps = v4l2_cap.capabilities; + g_device_caps = v4l2_cap.capabilities; - if (!(device_caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)) || - (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], device_caps); + 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); continue; } - ret = _camera_get_device_info(device_count, device_fd, + ret = __camera_get_device_info(device_count, device_fd, &device_info_list->device_info[device_count], glob_buf.gl_pathv[i]); close(device_fd); @@ -585,7 +585,142 @@ _GET_DEVICE_INFO_LIST_DONE: } -static void *_camera_preview_handler_func(gpointer data) +static int __camera_stop_stream(camera_hal_handle *handle, uint32_t buffer_count) +{ + int i = 0; + int ret = CAMERA_ERROR_NONE; + + if (!handle) { + LOGE("NULL handle"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGD("buffer count[%d]", buffer_count); + + /* stream off */ + ret = __camera_v4l2_stream(handle->device_fd, handle->v4l2_type, FALSE); + + LOGD("stream off : 0x%x", ret); + + /* munmap */ + for (i = 0 ; i < buffer_count ; i++) { + 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); + + handle->camera_buffers[i].planes[0].data = 0; + handle->camera_buffers[i].planes[0].size = 0; + } else { + LOGW("NULL data [index %d]", i); + } + } + + /* reqbufs 0 */ + ret = __camera_v4l2_reqbufs(handle->device_fd, + handle->v4l2_type, V4L2_MEMORY_MMAP, 0, &buffer_count); + + LOGD("reqbufs 0 : 0x%x", ret); + + return ret; +} + + +static int __camera_start_stream(camera_hal_handle *handle, camera_format_t *format, + uint32_t request_buffer_count, uint32_t *result_buffer_count) +{ + int i = 0; + int ret = CAMERA_ERROR_NONE; + camera_buffer_t *buffer = NULL; + struct v4l2_buffer v4l2_buf; + struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX]; + + if (!handle || !format || !result_buffer_count) { + LOGE("NULL param %p %p", handle, result_buffer_count); + return CAMERA_ERROR_INTERNAL; + } + + /* request buffer */ + ret = __camera_v4l2_reqbufs(handle->device_fd, + handle->v4l2_type, V4L2_MEMORY_MMAP, request_buffer_count, result_buffer_count); + if (ret != CAMERA_ERROR_NONE) { + g_mutex_unlock(&handle->lock); + return ret; + } + + LOGD("buffer count : request %d -> result %d", + request_buffer_count, *result_buffer_count); + + /* query buffer, mmap and qbuf */ + for (i = 0 ; i < *result_buffer_count ; i++) { + memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer)); + memset(v4l2_planes, 0x0, sizeof(v4l2_planes)); + + v4l2_buf.type = handle->v4l2_type; + v4l2_buf.memory = V4L2_MEMORY_MMAP; + v4l2_buf.index = i; + v4l2_buf.m.planes = v4l2_planes; + v4l2_buf.length = handle->plane_num; + + LOGD("%d", i); + + if (ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) { + LOGE("[%d] query buf failed. errno %d", i, errno); + goto _START_STREAM_FAILED; + } + + LOGD("%d", i); + + buffer = &handle->camera_buffers[i]; + + LOGD("%d", i); + + buffer->index = i; + buffer->format = format->stream_format; + buffer->resolution = format->stream_resolution; + buffer->total_size = v4l2_buf.length; + buffer->num_planes = handle->plane_num; + buffer->planes[0].size = v4l2_buf.length; + buffer->planes[0].data = mmap(0, + v4l2_buf.length, + PROT_READ | PROT_WRITE, + MAP_SHARED, + handle->device_fd, + v4l2_buf.m.offset); + + LOGD("%d", i); + + if (buffer->planes[0].data == MAP_FAILED) { + LOGE("[%d] mmap failed (errno %d)", i, errno); + goto _START_STREAM_FAILED; + } + + LOGD("%d", i); + + if (__camera_v4l2_qbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, i) != CAMERA_ERROR_NONE) { + LOGE("[%d] qbuf failed (errno %d)", i, errno); + goto _START_STREAM_FAILED; + } + + LOGD("%d", i); + } + + /* stream on */ + ret = __camera_v4l2_stream(handle->device_fd, handle->v4l2_type, TRUE); + if (ret != CAMERA_ERROR_NONE) { + LOGE("stream on failed"); + goto _START_STREAM_FAILED; + } + + return CAMERA_ERROR_NONE; + +_START_STREAM_FAILED: + __camera_stop_stream(handle, *result_buffer_count); + return ret; +} + + +static void *__camera_buffer_handler_func(gpointer data) { int index = 0; camera_hal_handle *handle = (camera_hal_handle *)data; @@ -600,10 +735,10 @@ static void *_camera_preview_handler_func(gpointer data) /* run buffer thread */ g_mutex_lock(&handle->preview_cb_lock); - while (handle->preview_cb_run) { + while (handle->buffer_thread_run) { g_mutex_unlock(&handle->preview_cb_lock); - if (_camera_v4l2_wait_frame(handle->device_fd, 5) != CAMERA_ERROR_NONE) { + if (__camera_v4l2_wait_frame(handle->device_fd, 5) != CAMERA_ERROR_NONE) { LOGE("frame wait failed"); g_mutex_lock(&handle->preview_cb_lock); break; @@ -611,24 +746,24 @@ static void *_camera_preview_handler_func(gpointer data) g_mutex_lock(&handle->preview_cb_lock); - if (handle->preview_cb_run == FALSE) { + if (handle->buffer_thread_run == FALSE) { LOGW("stop preview handler thread"); break; } - if (_camera_v4l2_dqbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, &index) != CAMERA_ERROR_NONE) { + if (__camera_v4l2_dqbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, &index) != CAMERA_ERROR_NONE) { LOGE("dqbuf failed"); break; } handle->live_buffer_num++; - LOGD("live buffer num %d", handle->live_buffer_num); + /*LOGD("live buffer num %d", handle->live_buffer_num);*/ g_mutex_unlock(&handle->preview_cb_lock); if (handle->preview_cb) { - ((camera_preview_frame_cb)handle->preview_cb)(&handle->preview_buffer[index], NULL, handle->preview_cb_data); + ((camera_preview_frame_cb)handle->preview_cb)(&handle->camera_buffers[index], NULL, handle->preview_cb_data); } else { LOGW("preview callback is NULL"); camera_release_preview_buffer((void *)handle, index); @@ -647,7 +782,7 @@ static void *_camera_preview_handler_func(gpointer data) } -static void _camera_message_release_func(gpointer data) +static void __camera_message_release_func(gpointer data) { camera_message_t *message = (camera_message_t *)data; @@ -720,7 +855,7 @@ static void *_camera_message_handler_func(gpointer data) } -void _camera_release_handle(camera_hal_handle *handle) +static void __camera_release_handle(camera_hal_handle *handle) { if (!handle) { LOGW("NULL handle"); @@ -733,7 +868,7 @@ void _camera_release_handle(camera_hal_handle *handle) g_cond_signal(&handle->message_cb_cond); g_mutex_unlock(&handle->message_cb_lock); g_thread_join(handle->message_thread); - g_queue_free_full(handle->message_list, (GDestroyNotify)_camera_message_release_func); + g_queue_free_full(handle->message_list, (GDestroyNotify)__camera_message_release_func); handle->message_list = NULL; } @@ -805,7 +940,7 @@ int camera_init(void **camera_handle) new_handle->device_fd = CAMERA_HAL_INITIAL_FD; new_handle->state = CAMERA_STATE_INITIALIZED; - ret = _camera_get_device_info_list(); + ret = __camera_get_device_info_list(); if (ret != CAMERA_ERROR_NONE) { LOGE("get device info failed"); goto _INIT_ERROR; @@ -818,22 +953,20 @@ int camera_init(void **camera_handle) return CAMERA_ERROR_NONE; _INIT_ERROR: - _camera_release_handle(new_handle); + __camera_release_handle(new_handle); return ret; } int camera_deinit(void *camera_handle) { - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { + if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); if (handle->state != CAMERA_STATE_INITIALIZED) { @@ -844,7 +977,7 @@ int camera_deinit(void *camera_handle) g_mutex_unlock(&handle->lock); - _camera_release_handle(handle); + __camera_release_handle(handle); return CAMERA_ERROR_NONE; } @@ -858,7 +991,7 @@ int camera_get_device_info_list(camera_device_info_list_t *device_info_list) return CAMERA_ERROR_INVALID_PARAMETER; } - ret = _camera_get_device_info_list(); + ret = __camera_get_device_info_list(); if (ret != CAMERA_ERROR_NONE) { LOGE("get device info failed"); return ret; @@ -874,15 +1007,13 @@ int camera_open_device(void *camera_handle, int device_index) int ret = CAMERA_ERROR_NONE; int device_fd = CAMERA_HAL_INITIAL_FD; char *node_path = NULL; - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { + if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); if (handle->state != CAMERA_STATE_INITIALIZED) { @@ -929,7 +1060,7 @@ int camera_open_device(void *camera_handle, int device_index) goto _OPEN_DEVICE_DONE; } - if (device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) + if (g_device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) handle->v4l2_type = V4L2_CAP_VIDEO_CAPTURE_MPLANE; else handle->v4l2_type = V4L2_CAP_VIDEO_CAPTURE; @@ -949,15 +1080,13 @@ _OPEN_DEVICE_DONE: int camera_close_device(void *camera_handle) { - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { + if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); if (handle->state != CAMERA_STATE_OPENED) { @@ -987,9 +1116,9 @@ int camera_close_device(void *camera_handle) int camera_add_message_callback(void *camera_handle, camera_message_cb callback, void *user_data, uint32_t *cb_id) { uint32_t i = 0; - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { + if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } @@ -999,8 +1128,6 @@ int camera_add_message_callback(void *camera_handle, camera_message_cb callback, return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); if (handle->state != CAMERA_STATE_OPENED) { @@ -1029,9 +1156,9 @@ int camera_add_message_callback(void *camera_handle, camera_message_cb callback, int camera_remove_message_callback(void *camera_handle, uint32_t cb_id) { - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { + if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } @@ -1041,8 +1168,6 @@ int camera_remove_message_callback(void *camera_handle, uint32_t cb_id) return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); if (handle->state != CAMERA_STATE_OPENED) { @@ -1075,18 +1200,13 @@ int camera_set_preview_stream_format(void *camera_handle, camera_format_t *forma int ret = CAMERA_ERROR_NONE; gboolean capability_check = FALSE; guint32 fourcc = 0; - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; camera_device_info_t *device_info = NULL; struct v4l2_format v4l2_fmt; struct v4l2_streamparm v4l2_parm; - if (!camera_handle) { - LOGE("NULL handle"); - return CAMERA_ERROR_INVALID_PARAMETER; - } - - if (!format) { - LOGE("NULL format"); + if (!handle || !format) { + LOGE("NULL param %p %p", handle, format); return CAMERA_ERROR_INVALID_PARAMETER; } @@ -1095,8 +1215,6 @@ int camera_set_preview_stream_format(void *camera_handle, camera_format_t *forma return CAMERA_ERROR_INTERNAL; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); if (handle->state != CAMERA_STATE_OPENED) { @@ -1139,7 +1257,7 @@ int camera_set_preview_stream_format(void *camera_handle, camera_format_t *forma } /* S_FMT */ - ret = _camera_get_fourcc_plane_num(format->stream_format, &fourcc, &handle->plane_num); + ret = __camera_get_fourcc_plane_num(format->stream_format, &fourcc, &handle->plane_num); if (ret != CAMERA_ERROR_NONE) { LOGE("get fourcc failed [format %d]", format->stream_format); g_mutex_unlock(&handle->lock); @@ -1220,20 +1338,13 @@ int camera_set_preview_stream_format(void *camera_handle, camera_format_t *forma int camera_get_preview_stream_format(void *camera_handle, camera_format_t *format) { - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { - LOGE("NULL handle"); + if (!handle || !format) { + LOGE("NULL param %p %p", handle, format); return CAMERA_ERROR_INVALID_PARAMETER; } - if (!format) { - LOGE("NULL format"); - return CAMERA_ERROR_INVALID_PARAMETER; - } - - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); memcpy(format, &handle->preview_format, sizeof(camera_format_t)); @@ -1249,27 +1360,14 @@ int camera_get_preview_stream_format(void *camera_handle, camera_format_t *forma int camera_start_preview(void *camera_handle, camera_preview_frame_cb callback, void *user_data) { - int i = 0; int ret = 0; - int result_count = 0; - camera_hal_handle *handle = NULL; - camera_buffer_t *buffer = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - struct v4l2_buffer v4l2_buf; - struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX]; - - if (!camera_handle) { - LOGE("NULL handle"); - return CAMERA_ERROR_INVALID_PARAMETER; - } - - if (!callback) { - LOGE("NULL callback for preview"); + if (!handle || !callback) { + LOGE("NULL param %p %p", handle, callback); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); if (handle->state != CAMERA_STATE_OPENED) { @@ -1278,78 +1376,28 @@ int camera_start_preview(void *camera_handle, camera_preview_frame_cb callback, return CAMERA_ERROR_INVALID_STATE; } - /* request buffer */ - ret = _camera_v4l2_reqbufs(handle->device_fd, - handle->v4l2_type, V4L2_MEMORY_MMAP, PREVIEW_BUFFER_MAX, &result_count); + ret = __camera_start_stream(handle, &handle->preview_format, BUFFER_MAX, &handle->buffer_count); if (ret != CAMERA_ERROR_NONE) { + LOGE("__camera_start_stream failed[0x%x]", ret); g_mutex_unlock(&handle->lock); return ret; } - LOGD("REQUESTED buffer count %d", result_count); - - handle->preview_buffer_num = result_count; - - /* query buffer, mmap and qbuf */ - for (i = 0 ; i < handle->preview_buffer_num ; i++) { - memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer)); - memset(v4l2_planes, 0x0, sizeof(v4l2_planes)); - - v4l2_buf.type = handle->v4l2_type; - v4l2_buf.memory = V4L2_MEMORY_MMAP; - v4l2_buf.index = i; - v4l2_buf.m.planes = v4l2_planes; - v4l2_buf.length = handle->plane_num; - - if (ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) { - LOGE("[%d] query buf failed. errno %d", i, errno); - goto _START_PREVIEW_FAILED; - } - - buffer = &handle->preview_buffer[i]; - - buffer->index = i; - buffer->format = handle->preview_format.stream_format; - buffer->resolution = handle->preview_format.stream_resolution; - buffer->total_size = v4l2_buf.length; - buffer->num_planes = handle->plane_num; - buffer->planes[0].size = v4l2_buf.length; - buffer->planes[0].data = 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_PREVIEW_FAILED; - } - } + g_mutex_lock(&handle->preview_cb_lock); - for (i = 0 ; i < handle->preview_buffer_num ; i++) { - if (_camera_v4l2_qbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, i) != CAMERA_ERROR_NONE) { - LOGE("qbuf failed"); - goto _START_PREVIEW_FAILED; - } - } + handle->buffer_thread_run = TRUE; - /* stream on */ - ret = _camera_v4l2_stream(handle->device_fd, handle->v4l2_type, TRUE); - if (ret != CAMERA_ERROR_NONE) { - LOGE("stream on failed"); - goto _START_PREVIEW_FAILED; - } + handle->buffer_thread = g_thread_try_new("camera_hal_buffer_thread", + __camera_buffer_handler_func, (gpointer)handle, NULL); + if (!handle->buffer_thread) { + LOGE("failed to create buffer handler thread"); + g_mutex_unlock(&handle->preview_cb_lock); - g_mutex_lock(&handle->preview_cb_lock); + __camera_stop_stream(handle, handle->buffer_count); - handle->preview_cb_run = TRUE; + g_mutex_unlock(&handle->lock); - handle->preview_thread = g_thread_try_new("camera_hal_preview_thread", - _camera_preview_handler_func, (gpointer)handle, NULL); - if (!handle->preview_thread) { - LOGE("failed to create preview callback thread"); - g_mutex_unlock(&handle->preview_cb_lock); - goto _START_PREVIEW_FAILED; + return ret; } handle->preview_cb = callback; @@ -1364,51 +1412,24 @@ int camera_start_preview(void *camera_handle, camera_preview_frame_cb callback, g_mutex_unlock(&handle->lock); return CAMERA_ERROR_NONE; - -_START_PREVIEW_FAILED: - /* stream off */ - if (ioctl(handle->device_fd, VIDIOC_STREAMOFF, &handle->v4l2_type) < 0) - LOGE("stream off failed. errno %d", errno); - - /* munmap */ - for (i = 0 ; i < handle->preview_buffer_num ; i++) { - buffer = &handle->preview_buffer[i]; - if (buffer->planes[0].data != NULL && - buffer->planes[0].data != MAP_FAILED) { - LOGW("munmap %p", buffer->planes[0].data); - munmap(buffer->planes[0].data, buffer->planes[0].size); - } - memset(buffer, 0x0, sizeof(camera_buffer_t)); - } - - /* reqbufs 0 */ - if (_camera_v4l2_reqbufs(handle->device_fd, - handle->v4l2_type, V4L2_MEMORY_MMAP, 0, &result_count) != CAMERA_ERROR_NONE) - LOGE("reqbufs 0 failed"); - - g_mutex_unlock(&handle->lock); - - return ret; } int camera_release_preview_buffer(void *camera_handle, int buffer_index) { int ret = CAMERA_ERROR_NONE; - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { + if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - - if (buffer_index >= handle->preview_buffer_num) { + if (buffer_index >= handle->buffer_count) { LOGE("invalid buffer index %d", buffer_index); return CAMERA_ERROR_INVALID_PARAMETER; } - ret = _camera_v4l2_qbuf(handle->device_fd, + ret = __camera_v4l2_qbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, buffer_index); g_mutex_lock(&handle->preview_cb_lock); @@ -1428,21 +1449,18 @@ int camera_release_preview_buffer(void *camera_handle, int buffer_index) return ret; } + int camera_stop_preview(void *camera_handle) { int ret = CAMERA_ERROR_NONE; - int i = 0; - int result_count = 0; gint64 end_time; - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { + if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - LOGD("start"); g_mutex_lock(&handle->lock); @@ -1455,7 +1473,7 @@ int camera_stop_preview(void *camera_handle) g_mutex_lock(&handle->preview_cb_lock); - handle->preview_cb_run = FALSE; + handle->buffer_thread_run = FALSE; while (handle->live_buffer_num > 0) { LOGD("wait for live buffer [num %d]", handle->live_buffer_num); @@ -1470,38 +1488,15 @@ int camera_stop_preview(void *camera_handle) g_mutex_unlock(&handle->preview_cb_lock); - /* stream off */ - ret = _camera_v4l2_stream(handle->device_fd, handle->v4l2_type, FALSE); - - LOGD("stream off : 0x%x", ret); - - /* munmap */ - for (i = 0 ; i < handle->preview_buffer_num ; i++) { - if (handle->preview_buffer[i].planes[0].data != NULL) { - LOGW("munmap %p", handle->preview_buffer[i].planes[0].data); - - munmap(handle->preview_buffer[i].planes[0].data, handle->preview_buffer[i].planes[0].size); - - handle->preview_buffer[i].planes[0].data = 0; - handle->preview_buffer[i].planes[0].size = 0; - } else { - LOGW("NULL data [index %d]", i); - } - } - - /* reqbufs 0 */ - ret = _camera_v4l2_reqbufs(handle->device_fd, - handle->v4l2_type, V4L2_MEMORY_MMAP, 0, &result_count); - - LOGD("reqbufs 0 : 0x%x", ret); + ret = __camera_stop_stream(handle, handle->buffer_count); /* wait for preview thread exit */ - g_thread_join(handle->preview_thread); - handle->preview_thread = NULL; + g_thread_join(handle->buffer_thread); + handle->buffer_thread = NULL; handle->state = CAMERA_STATE_OPENED; - LOGD("stop preview done"); + LOGD("stop preview done [0x%x]", ret); g_mutex_unlock(&handle->lock); @@ -1515,7 +1510,7 @@ int camera_start_auto_focus(void *camera_handle) return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* auto focus is not supported */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1528,7 +1523,7 @@ int camera_stop_auto_focus(void *camera_handle) return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* auto focus is not supported */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1538,11 +1533,11 @@ int camera_stop_auto_focus(void *camera_handle) int camera_start_capture(void *camera_handle, camera_capture_cb callback, void *user_data) { if (!camera_handle || !callback) { - LOGE("NULL handle %p or callback %p", camera_handle, callback); + LOGE("NULL param %p %p", camera_handle, callback); return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* capture function is not supported */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1555,7 +1550,7 @@ int camera_stop_capture(void *camera_handle) return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* capture function is not supported */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1563,17 +1558,12 @@ int camera_stop_capture(void *camera_handle) int camera_set_video_stream_format(void *camera_handle, camera_format_t *format) { - if (!camera_handle) { - LOGE("NULL handle"); + if (!camera_handle || !format) { + LOGE("NULL param %p %p", camera_handle, format); return CAMERA_ERROR_INVALID_PARAMETER; } - if (!format) { - LOGE("NULL format"); - return CAMERA_ERROR_INVALID_PARAMETER; - } - - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* single stream device can not support video stream */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1581,17 +1571,12 @@ int camera_set_video_stream_format(void *camera_handle, camera_format_t *format) int camera_get_video_stream_format(void *camera_handle, camera_format_t *format) { - if (!camera_handle) { - LOGE("NULL handle"); - return CAMERA_ERROR_INVALID_PARAMETER; - } - - if (!format) { - LOGE("NULL format"); + if (!camera_handle || !format) { + LOGE("NULL param %p %p", camera_handle, format); return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* single stream device can not support video stream */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1599,17 +1584,12 @@ int camera_get_video_stream_format(void *camera_handle, camera_format_t *format) int camera_start_record(void *camera_handle, camera_video_frame_cb callback, void *user_data) { - if (!camera_handle) { - LOGE("NULL handle"); - return CAMERA_ERROR_INVALID_PARAMETER; - } - - if (!callback) { - LOGE("NULL callback for video"); + if (!camera_handle || !callback) { + LOGE("NULL param %p %p", camera_handle, callback); return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* single stream device can not support video stream */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1622,7 +1602,7 @@ int camera_release_video_buffer(void *camera_handle, int buffer_index) return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* single stream device can not support video stream */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1635,7 +1615,7 @@ int camera_stop_record(void *camera_handle) return CAMERA_ERROR_INVALID_PARAMETER; } - LOGD("NOT SUPPORTED"); + LOGE("NOT SUPPORTED"); /* single stream device can not support video stream */ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; @@ -1647,19 +1627,13 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) int cid = 0; int ctrl_ret = 0; int set_value = 0; - camera_hal_handle *handle = NULL; - - if (!camera_handle) { - LOGE("NULL handle"); - return CAMERA_ERROR_INVALID_PARAMETER; - } + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!value) { - LOGE("invalid pointer : value"); + if (!handle || !value) { + LOGE("NULL param %p %p", handle, value); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; set_value = *(int *)value; g_mutex_lock(&handle->lock); @@ -1700,13 +1674,22 @@ int camera_set_command(void *camera_handle, int64_t command, void *value) case CAMERA_COMMAND_TILT: cid = V4L2_CID_TILT_ABSOLUTE; break; + case CAMERA_COMMAND_FLIP: + g_mutex_unlock(&handle->lock); + if (set_value != CAMERA_FLIP_NONE) { + LOGE("NOT_SUPPORTED flip %d", set_value); + return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; + } else { + return CAMERA_ERROR_NONE; + } + break; default: LOGE("NOT_SUPPORTED %"PRId64, command); g_mutex_unlock(&handle->lock); return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } - ctrl_ret = _camera_v4l2_s_ctrl(handle->device_fd, cid, set_value); + ctrl_ret = __camera_v4l2_s_ctrl(handle->device_fd, cid, set_value); if (ctrl_ret < 0) { switch (errno) { case EACCES: @@ -1743,20 +1726,13 @@ int camera_get_command(void *camera_handle, int64_t command, void **value) int ret = CAMERA_ERROR_NONE; int cid = 0; int ctrl_ret = 0; - camera_hal_handle *handle = NULL; - - if (!camera_handle) { - LOGE("NULL handle"); - return CAMERA_ERROR_INVALID_PARAMETER; - } + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!value) { - LOGE("invalid pointer for value"); + if (!handle || !value) { + LOGE("NULL param %p %p", handle, value); return CAMERA_ERROR_INVALID_PARAMETER; } - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); LOGD("get command %"PRId64" - state %d", command, handle->state); @@ -1780,7 +1756,7 @@ int camera_get_command(void *camera_handle, int64_t command, void **value) return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; } - ctrl_ret = _camera_v4l2_g_ctrl(handle->device_fd, cid, (int *)value); + ctrl_ret = __camera_v4l2_g_ctrl(handle->device_fd, cid, (int *)value); if (ctrl_ret < 0) { switch (errno) { case EACCES: @@ -1814,20 +1790,13 @@ int camera_get_command(void *camera_handle, int64_t command, void **value) int camera_set_batch_command(void *camera_handle, camera_batch_command_control_t *batch_command, int64_t *error_command) { - camera_hal_handle *handle = NULL; + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; - if (!camera_handle) { - LOGE("NULL handle"); + if (!handle || !batch_command) { + LOGE("NULL param %p %p", handle, batch_command); return CAMERA_ERROR_INVALID_PARAMETER; } - if (!batch_command) { - LOGE("invalid pointer for batch_command"); - return CAMERA_ERROR_INVALID_PARAMETER; - } - - handle = (camera_hal_handle *)camera_handle; - g_mutex_lock(&handle->lock); LOGD("set batch command - flag %"PRIx64", state %d", diff --git a/src/tizen_camera_v4l2_private.h b/src/tizen_camera_v4l2_private.h index e70ceac..2e4996f 100644 --- a/src/tizen_camera_v4l2_private.h +++ b/src/tizen_camera_v4l2_private.h @@ -28,8 +28,7 @@ #define CAMERA_HAL_INITIAL_INDEX -1 #define CAMERA_HAL_INITIAL_FD -1 #define MESSAGE_CALLBACK_MAX 10 -#define PREVIEW_BUFFER_MAX 4 -#define VIDEO_BUFFER_MAX 8 +#define BUFFER_MAX 4 #define V4L2_PLANES_MAX 4 typedef struct _camera_hal_handle { @@ -47,22 +46,17 @@ typedef struct _camera_hal_handle { int live_buffer_num; /* thread */ - GThread *preview_thread; + GThread *buffer_thread; GThread *message_thread; + gboolean buffer_thread_run; - /* preview callback */ + /* buffer handler */ camera_preview_frame_cb preview_cb; + camera_capture_cb capture_cb; void *preview_cb_data; - gboolean preview_cb_run; - uint32_t preview_buffer_num; - camera_buffer_t preview_buffer[PREVIEW_BUFFER_MAX]; - - /* video callback */ - camera_video_frame_cb video_cb; - void *video_cb_data; - gboolean video_cb_run; - uint32_t video_buffer_num; - camera_buffer_t video_buffer[VIDEO_BUFFER_MAX]; + void *capture_cb_data; + uint32_t buffer_count; + camera_buffer_t camera_buffers[BUFFER_MAX]; /* message callback */ camera_message_cb message_cb[MESSAGE_CALLBACK_MAX]; -- 2.7.4 From 0fecd7c40cbcf2438e5c32512b56b5d758d49496 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Thu, 23 Jul 2020 19:56:57 +0900 Subject: [PATCH 14/14] Support capture function - Additional changes : Remove or rename some member variables in camera_hal_handle : Move S_FMT/S_PARM code to __camera_start_stream() : Remove debug log [Version] 0.0.12 [Profile] Common [Issue Type] Update Change-Id: If3737f434b0248b8e3df2b261844a48139b248a1 Signed-off-by: Jeongmo Yang --- packaging/camera-hal-v4l2.spec | 2 +- src/tizen_camera_v4l2.c | 533 +++++++++++++++++++++++++++------------- src/tizen_camera_v4l2_private.h | 58 +++-- 3 files changed, 393 insertions(+), 200 deletions(-) diff --git a/packaging/camera-hal-v4l2.spec b/packaging/camera-hal-v4l2.spec index 58bdca4..353c6a3 100644 --- a/packaging/camera-hal-v4l2.spec +++ b/packaging/camera-hal-v4l2.spec @@ -1,6 +1,6 @@ Name: camera-hal-v4l2 Summary: Tizen Camera Hal for V4L2 -Version: 0.0.11 +Version: 0.0.12 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 diff --git a/src/tizen_camera_v4l2.c b/src/tizen_camera_v4l2.c index 2b4b06d..0ade153 100644 --- a/src/tizen_camera_v4l2.c +++ b/src/tizen_camera_v4l2.c @@ -322,7 +322,7 @@ static int __camera_get_format(guint32 fourcc, int *pixel_format) return CAMERA_ERROR_NONE; } -static int __camera_get_fourcc_plane_num(int pixel_format, guint32 *fourcc, uint8_t *plane_num) +static int __camera_get_fourcc_plane_num(int pixel_format, guint32 *fourcc, guint32 *plane_num) { if (!fourcc || !plane_num) { LOGE("NULL parameter %p %p", fourcc, plane_num); @@ -522,7 +522,7 @@ static int __camera_get_device_info_list(void) ret = CAMERA_ERROR_INTERNAL; goto _GET_DEVICE_INFO_LIST_DONE; default: - LOGE("unknown eror : %d", ret); + LOGE("unknown error : %d", ret); ret = CAMERA_ERROR_INTERNAL; goto _GET_DEVICE_INFO_LIST_DONE; } @@ -598,7 +598,7 @@ static int __camera_stop_stream(camera_hal_handle *handle, uint32_t buffer_count LOGD("buffer count[%d]", buffer_count); /* stream off */ - ret = __camera_v4l2_stream(handle->device_fd, handle->v4l2_type, FALSE); + ret = __camera_v4l2_stream(handle->device_fd, handle->buffer_type, FALSE); LOGD("stream off : 0x%x", ret); @@ -618,7 +618,7 @@ static int __camera_stop_stream(camera_hal_handle *handle, uint32_t buffer_count /* reqbufs 0 */ ret = __camera_v4l2_reqbufs(handle->device_fd, - handle->v4l2_type, V4L2_MEMORY_MMAP, 0, &buffer_count); + handle->buffer_type, V4L2_MEMORY_MMAP, 0, &buffer_count); LOGD("reqbufs 0 : 0x%x", ret); @@ -626,60 +626,116 @@ static int __camera_stop_stream(camera_hal_handle *handle, uint32_t buffer_count } -static int __camera_start_stream(camera_hal_handle *handle, camera_format_t *format, - uint32_t request_buffer_count, uint32_t *result_buffer_count) +static int __camera_start_stream(camera_hal_handle *handle, camera_pixel_format_t pixel_format, + camera_resolution_t *resolution, uint32_t fps, uint32_t request_buffer_count) { int i = 0; int ret = CAMERA_ERROR_NONE; camera_buffer_t *buffer = NULL; + struct v4l2_format v4l2_fmt; + struct v4l2_streamparm v4l2_parm; struct v4l2_buffer v4l2_buf; - struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX]; + struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX];; + guint32 fourcc = 0; + guint32 plane_num = 0; + + if (!handle || !resolution) { + LOGE("NULL param %p %p", handle, resolution); + return CAMERA_ERROR_INTERNAL; + } + + /* S_FMT */ + ret = __camera_get_fourcc_plane_num(pixel_format, &fourcc, &plane_num); + if (ret != CAMERA_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 (ioctl(handle->device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) { + LOGE("S_FMT failed. errno %d", errno); + return CAMERA_ERROR_INTERNAL; + } + + if (V4L2_TYPE_IS_MULTIPLANAR(handle->buffer_type)) { + for (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 { + 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)); - if (!handle || !format || !result_buffer_count) { - LOGE("NULL param %p %p", handle, result_buffer_count); + v4l2_parm.type = handle->buffer_type; + + if (ioctl(handle->device_fd, VIDIOC_G_PARM, &v4l2_parm) < 0) { + LOGE("G_PARM failed. errno %d", errno); + return CAMERA_ERROR_INTERNAL; + } + + /* S_PARM to set fps */ + 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) { + LOGE("S_PARM failed. errno %d", errno); return CAMERA_ERROR_INTERNAL; } /* request buffer */ ret = __camera_v4l2_reqbufs(handle->device_fd, - handle->v4l2_type, V4L2_MEMORY_MMAP, request_buffer_count, result_buffer_count); + handle->buffer_type, V4L2_MEMORY_MMAP, request_buffer_count, &handle->buffer_count); if (ret != CAMERA_ERROR_NONE) { - g_mutex_unlock(&handle->lock); return ret; } LOGD("buffer count : request %d -> result %d", - request_buffer_count, *result_buffer_count); + request_buffer_count, handle->buffer_count); /* query buffer, mmap and qbuf */ - for (i = 0 ; i < *result_buffer_count ; i++) { + for (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->v4l2_type; + 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 = handle->plane_num; - - LOGD("%d", i); + v4l2_buf.length = plane_num; if (ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) { LOGE("[%d] query buf failed. errno %d", i, errno); goto _START_STREAM_FAILED; } - LOGD("%d", i); - buffer = &handle->camera_buffers[i]; - LOGD("%d", i); - buffer->index = i; - buffer->format = format->stream_format; - buffer->resolution = format->stream_resolution; + buffer->format = pixel_format; + buffer->resolution.width = resolution->width; + buffer->resolution.height = resolution->height; buffer->total_size = v4l2_buf.length; - buffer->num_planes = handle->plane_num; + buffer->num_planes = plane_num; buffer->planes[0].size = v4l2_buf.length; buffer->planes[0].data = mmap(0, v4l2_buf.length, @@ -688,25 +744,19 @@ static int __camera_start_stream(camera_hal_handle *handle, camera_format_t *for handle->device_fd, v4l2_buf.m.offset); - LOGD("%d", i); - if (buffer->planes[0].data == MAP_FAILED) { LOGE("[%d] mmap failed (errno %d)", i, errno); goto _START_STREAM_FAILED; } - LOGD("%d", i); - - if (__camera_v4l2_qbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, i) != CAMERA_ERROR_NONE) { + if (__camera_v4l2_qbuf(handle->device_fd, handle->buffer_type, V4L2_MEMORY_MMAP, i) != CAMERA_ERROR_NONE) { LOGE("[%d] qbuf failed (errno %d)", i, errno); goto _START_STREAM_FAILED; } - - LOGD("%d", i); } /* stream on */ - ret = __camera_v4l2_stream(handle->device_fd, handle->v4l2_type, TRUE); + ret = __camera_v4l2_stream(handle->device_fd, handle->buffer_type, TRUE); if (ret != CAMERA_ERROR_NONE) { LOGE("stream on failed"); goto _START_STREAM_FAILED; @@ -715,11 +765,110 @@ static int __camera_start_stream(camera_hal_handle *handle, camera_format_t *for return CAMERA_ERROR_NONE; _START_STREAM_FAILED: - __camera_stop_stream(handle, *result_buffer_count); + __camera_stop_stream(handle, handle->buffer_count); return ret; } +static void __camera_do_capture(camera_hal_handle *handle) +{ + int ret = CAMERA_ERROR_NONE; + int buffer_index = 0; + + if (!handle) { + LOGE("NULL handle"); + return; + } + + LOGD("start"); + + /* restart stream for capture */ + if (handle->capture_restart_stream) { + ret = __camera_stop_stream(handle, handle->buffer_count); + if (ret != CAMERA_ERROR_NONE) { + LOGE("stop stream failed for capture[0x%x]", ret); + goto _CAPTURE_DONE; + } + + ret = __camera_start_stream(handle, + handle->preview_format.capture_format, + &handle->preview_format.capture_resolution, + handle->preview_format.stream_fps, + BUFFER_MAX); + if (ret != CAMERA_ERROR_NONE) { + LOGE("start stream failed for capture[0x%x]", ret); + goto _CAPTURE_DONE; + } + } + + /* get capture buffer */ + ret = __camera_v4l2_wait_frame(handle->device_fd, 5); + if (ret != CAMERA_ERROR_NONE) { + LOGE("frame wait failed for capture[0x%x]", ret); + goto _CAPTURE_DONE; + } + + ret = __camera_v4l2_dqbuf(handle->device_fd, + handle->buffer_type, V4L2_MEMORY_MMAP, &buffer_index); + if (ret != CAMERA_ERROR_NONE) { + LOGE("dqbuf failed for capture[0x%x]", ret); + goto _CAPTURE_DONE; + } + + g_mutex_lock(&handle->buffer_lock); + + handle->captured_count++; + + g_mutex_unlock(&handle->buffer_lock); + + LOGD("capture cb[%p], buffer index[%d],count[%d]", + handle->capture_cb, buffer_index, handle->captured_count); + + if (handle->capture_cb) { + ((camera_capture_cb)handle->capture_cb)(&handle->camera_buffers[buffer_index], + NULL, NULL, handle->capture_cb_data); + } else { + LOGW("capture callback is NULL"); + /* Need to post error? */ + } + + ret = __camera_v4l2_qbuf(handle->device_fd, + handle->buffer_type, V4L2_MEMORY_MMAP, buffer_index); + if (ret != CAMERA_ERROR_NONE) + LOGE("qbuf failed for capture[0x%x]", ret); + + g_mutex_lock(&handle->buffer_lock); + + if (handle->state == CAMERA_STATE_CAPTURING) { + LOGD("wait for capture stop signal"); + g_cond_wait(&handle->buffer_cond, &handle->buffer_lock); + LOGD("signal received"); + } else { + LOGD("The state is already changed."); + } + + g_mutex_unlock(&handle->buffer_lock); + +_CAPTURE_DONE: + /* restart stream for preview */ + if (handle->capture_restart_stream) { + ret = __camera_stop_stream(handle, handle->buffer_count); + if (ret != CAMERA_ERROR_NONE) + LOGE("stop stream failed for preview[0x%x]", ret); + + ret = __camera_start_stream(handle, + handle->preview_format.stream_format, + &handle->preview_format.stream_resolution, + handle->preview_format.stream_fps, + BUFFER_MAX); + if (ret != CAMERA_ERROR_NONE) + LOGE("start stream failed for preview[0x%x]", ret); + } + + LOGD("done"); +} + + static void *__camera_buffer_handler_func(gpointer data) { int index = 0; @@ -733,34 +882,34 @@ static void *__camera_buffer_handler_func(gpointer data) LOGD("enter - preview handler thread"); /* run buffer thread */ - g_mutex_lock(&handle->preview_cb_lock); + g_mutex_lock(&handle->buffer_lock); while (handle->buffer_thread_run) { - g_mutex_unlock(&handle->preview_cb_lock); + g_mutex_unlock(&handle->buffer_lock); if (__camera_v4l2_wait_frame(handle->device_fd, 5) != CAMERA_ERROR_NONE) { LOGE("frame wait failed"); - g_mutex_lock(&handle->preview_cb_lock); + g_mutex_lock(&handle->buffer_lock); break; } - g_mutex_lock(&handle->preview_cb_lock); + g_mutex_lock(&handle->buffer_lock); if (handle->buffer_thread_run == FALSE) { LOGW("stop preview handler thread"); break; } - if (__camera_v4l2_dqbuf(handle->device_fd, handle->v4l2_type, V4L2_MEMORY_MMAP, &index) != CAMERA_ERROR_NONE) { + if (__camera_v4l2_dqbuf(handle->device_fd, handle->buffer_type, V4L2_MEMORY_MMAP, &index) != CAMERA_ERROR_NONE) { LOGE("dqbuf failed"); break; } - handle->live_buffer_num++; + handle->buffer_dequeued_count++; - /*LOGD("live buffer num %d", handle->live_buffer_num);*/ + /*LOGD("dequeued buffer count %d", handle->buffer_dequeued_count);*/ - g_mutex_unlock(&handle->preview_cb_lock); + g_mutex_unlock(&handle->buffer_lock); if (handle->preview_cb) { ((camera_preview_frame_cb)handle->preview_cb)(&handle->camera_buffers[index], NULL, handle->preview_cb_data); @@ -769,12 +918,18 @@ static void *__camera_buffer_handler_func(gpointer data) camera_release_preview_buffer((void *)handle, index); } + /* check capture request flag */ + if (handle->capture_request) { + __camera_do_capture(handle); + handle->capture_request = FALSE; + } + sched_yield(); - g_mutex_lock(&handle->preview_cb_lock); + g_mutex_lock(&handle->buffer_lock); } - g_mutex_unlock(&handle->preview_cb_lock); + g_mutex_unlock(&handle->buffer_lock); LOGD("leave - preview handler thread"); @@ -812,42 +967,42 @@ static void *_camera_message_handler_func(gpointer data) LOGD("enter - message thread"); - g_mutex_lock(&handle->message_cb_lock); + g_mutex_lock(&handle->msg_cb_lock); - while (handle->message_cb_run) { - if (g_queue_is_empty(handle->message_list)) { + while (handle->msg_cb_run) { + if (g_queue_is_empty(handle->msg_list)) { LOGD("wait for message"); - g_cond_wait(&handle->message_cb_cond, &handle->message_cb_lock); + g_cond_wait(&handle->msg_cb_cond, &handle->msg_cb_lock); LOGD("message signal received"); } - if (!handle->message_cb_run) { + if (!handle->msg_cb_run) { LOGW("break message thread"); break; } - message = g_queue_pop_head(handle->message_list); + message = g_queue_pop_head(handle->msg_list); if (!message) { LOGW("NULL message"); continue; } - g_mutex_unlock(&handle->message_cb_lock); + g_mutex_unlock(&handle->msg_cb_lock); for (i = 0 ; i < MESSAGE_CALLBACK_MAX ; i++) { - if (handle->message_cb[i]) { + if (handle->msg_cb[i]) { LOGD("call message callback type %d", message->type); - ((camera_message_cb)handle->message_cb[i])(message, handle->message_cb_data[i]); + ((camera_message_cb)handle->msg_cb[i])(message, handle->msg_cb_data[i]); } } g_free(message); message = NULL; - g_mutex_lock(&handle->message_cb_lock); + g_mutex_lock(&handle->msg_cb_lock); } - g_mutex_unlock(&handle->message_cb_lock); + g_mutex_unlock(&handle->msg_cb_lock); LOGD("leave - message thread"); @@ -862,21 +1017,21 @@ static void __camera_release_handle(camera_hal_handle *handle) return; } - if (handle->message_thread) { - g_mutex_lock(&handle->message_cb_lock); - handle->message_cb_run = FALSE; - g_cond_signal(&handle->message_cb_cond); - g_mutex_unlock(&handle->message_cb_lock); - g_thread_join(handle->message_thread); - g_queue_free_full(handle->message_list, (GDestroyNotify)__camera_message_release_func); - handle->message_list = NULL; + if (handle->msg_thread) { + g_mutex_lock(&handle->msg_cb_lock); + handle->msg_cb_run = FALSE; + g_cond_signal(&handle->msg_cb_cond); + g_mutex_unlock(&handle->msg_cb_lock); + g_thread_join(handle->msg_thread); + g_queue_free_full(handle->msg_list, (GDestroyNotify)__camera_message_release_func); + handle->msg_list = NULL; } g_mutex_clear(&handle->lock); - g_mutex_clear(&handle->preview_cb_lock); - g_mutex_clear(&handle->message_cb_lock); - g_cond_clear(&handle->preview_cb_cond); - g_cond_clear(&handle->message_cb_cond); + g_mutex_clear(&handle->buffer_lock); + g_mutex_clear(&handle->msg_cb_lock); + g_cond_clear(&handle->buffer_cond); + g_cond_clear(&handle->msg_cb_cond); if (handle->bufmgr) { tbm_bufmgr_deinit(handle->bufmgr); @@ -920,17 +1075,17 @@ int camera_init(void **camera_handle) new_handle->bufmgr = bufmgr; g_mutex_init(&new_handle->lock); - g_mutex_init(&new_handle->preview_cb_lock); - g_mutex_init(&new_handle->message_cb_lock); - g_cond_init(&new_handle->preview_cb_cond); - g_cond_init(&new_handle->message_cb_cond); + g_mutex_init(&new_handle->buffer_lock); + g_mutex_init(&new_handle->msg_cb_lock); + g_cond_init(&new_handle->buffer_cond); + g_cond_init(&new_handle->msg_cb_cond); /* message thread */ - new_handle->message_list = g_queue_new(); - new_handle->message_cb_run = TRUE; - new_handle->message_thread = g_thread_try_new("camera_hal_message_thread", + new_handle->msg_list = g_queue_new(); + new_handle->msg_cb_run = TRUE; + new_handle->msg_thread = g_thread_try_new("camera_hal_msg_thread", _camera_message_handler_func, (gpointer)new_handle, NULL); - if (!new_handle->message_thread) { + if (!new_handle->msg_thread) { LOGE("failed to create message thread"); ret = CAMERA_ERROR_INTERNAL; goto _INIT_ERROR; @@ -1061,16 +1216,16 @@ int camera_open_device(void *camera_handle, int device_index) } if (g_device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) - handle->v4l2_type = V4L2_CAP_VIDEO_CAPTURE_MPLANE; + handle->buffer_type = V4L2_CAP_VIDEO_CAPTURE_MPLANE; else - handle->v4l2_type = V4L2_CAP_VIDEO_CAPTURE; + handle->buffer_type = V4L2_CAP_VIDEO_CAPTURE; handle->state = CAMERA_STATE_OPENED; handle->device_index = device_index; handle->device_fd = device_fd; LOGD("[%d] device[%s] opened [fd %d, type %d]", - device_index, node_path, device_fd, handle->v4l2_type); + device_index, node_path, device_fd, handle->buffer_type); _OPEN_DEVICE_DONE: g_mutex_unlock(&handle->lock); @@ -1137,9 +1292,9 @@ int camera_add_message_callback(void *camera_handle, camera_message_cb callback, } for (i = 0 ; i < MESSAGE_CALLBACK_MAX ; i++) { - if (handle->message_cb[i] == NULL) { - handle->message_cb[i] = callback; - handle->message_cb_data[i] = user_data; + if (handle->msg_cb[i] == NULL) { + handle->msg_cb[i] = callback; + handle->msg_cb_data[i] = user_data; *cb_id = i; LOGD("message cb [%p] added, user data %p - id %u", callback, user_data, i); g_mutex_unlock(&handle->lock); @@ -1176,12 +1331,12 @@ int camera_remove_message_callback(void *camera_handle, uint32_t cb_id) return CAMERA_ERROR_INVALID_STATE; } - if (handle->message_cb[cb_id]) { + if (handle->msg_cb[cb_id]) { LOGD("remove message callback %p, user data %p - cb_id %u", - handle->message_cb[cb_id], handle->message_cb_data[cb_id], cb_id); + handle->msg_cb[cb_id], handle->msg_cb_data[cb_id], cb_id); - handle->message_cb[cb_id] = NULL; - handle->message_cb_data[cb_id] = NULL; + handle->msg_cb[cb_id] = NULL; + handle->msg_cb_data[cb_id] = NULL; } else { LOGE("already removed message cb"); g_mutex_unlock(&handle->lock); @@ -1199,11 +1354,8 @@ int camera_set_preview_stream_format(void *camera_handle, camera_format_t *forma int j = 0; int ret = CAMERA_ERROR_NONE; gboolean capability_check = FALSE; - guint32 fourcc = 0; camera_hal_handle *handle = (camera_hal_handle *)camera_handle; camera_device_info_t *device_info = NULL; - struct v4l2_format v4l2_fmt; - struct v4l2_streamparm v4l2_parm; if (!handle || !format) { LOGE("NULL param %p %p", handle, format); @@ -1217,7 +1369,8 @@ int camera_set_preview_stream_format(void *camera_handle, camera_format_t *forma g_mutex_lock(&handle->lock); - if (handle->state != CAMERA_STATE_OPENED) { + if (handle->state != CAMERA_STATE_OPENED && + handle->state != CAMERA_STATE_PREVIEWING) { LOGE("invalid state %d", handle->state); g_mutex_unlock(&handle->lock); return CAMERA_ERROR_INVALID_STATE; @@ -1256,80 +1409,60 @@ int camera_set_preview_stream_format(void *camera_handle, camera_format_t *forma return CAMERA_ERROR_INVALID_PARAMETER; } - /* S_FMT */ - ret = __camera_get_fourcc_plane_num(format->stream_format, &fourcc, &handle->plane_num); - if (ret != CAMERA_ERROR_NONE) { - LOGE("get fourcc failed [format %d]", format->stream_format); - g_mutex_unlock(&handle->lock); - return ret; - } - - memset(&v4l2_fmt, 0x0, sizeof(struct v4l2_format)); - - v4l2_fmt.type = handle->v4l2_type; - if (V4L2_TYPE_IS_MULTIPLANAR(handle->v4l2_type)) { - v4l2_fmt.fmt.pix_mp.width = format->stream_resolution.width; - v4l2_fmt.fmt.pix_mp.height = format->stream_resolution.height; - v4l2_fmt.fmt.pix_mp.pixelformat = fourcc; - v4l2_fmt.fmt.pix_mp.num_planes = handle->plane_num; - } else { - v4l2_fmt.fmt.pix.width = format->stream_resolution.width; - v4l2_fmt.fmt.pix.height = format->stream_resolution.height; - v4l2_fmt.fmt.pix.pixelformat = fourcc; - v4l2_fmt.fmt.pix.bytesperline = format->stream_resolution.width; - } - - if (ioctl(handle->device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) { - LOGE("S_FMT failed. errno %d", errno); - g_mutex_unlock(&handle->lock); - return CAMERA_ERROR_INTERNAL; - } - - if (V4L2_TYPE_IS_MULTIPLANAR(handle->v4l2_type)) { - for (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); + /* compare with current settings */ + if (handle->state == CAMERA_STATE_PREVIEWING) { + if (handle->preview_format.stream_format == format->stream_format && + handle->preview_format.stream_resolution.width == format->stream_resolution.width && + handle->preview_format.stream_resolution.height == format->stream_resolution.height && + handle->preview_format.stream_fps == format->stream_fps && + handle->preview_format.stream_rotation == format->stream_rotation) { + LOGD("no need to restart preview stream"); + goto _SET_PREVIEW_STREAM_FORMAT_DONE; } - } else { - 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)); + LOGD("Preview setting is changed. Restart preview now."); - v4l2_parm.type = handle->v4l2_type; + /* stop preview stream to change it */ + ret = __camera_stop_stream(handle, handle->buffer_count); + if (ret != CAMERA_ERROR_NONE) { + LOGE("failed to stop stream"); + g_mutex_unlock(&handle->lock); + return ret; + } - if (ioctl(handle->device_fd, VIDIOC_G_PARM, &v4l2_parm) < 0) { - LOGE("G_PARM failed. errno %d", errno); - g_mutex_unlock(&handle->lock); - return CAMERA_ERROR_INTERNAL; + /* restart preview stream to change it */ + ret = __camera_start_stream(handle, + format->stream_format, + &format->stream_resolution, + format->stream_fps, + BUFFER_MAX); + if (ret != CAMERA_ERROR_NONE) { + LOGE("failed to start stream"); + g_mutex_unlock(&handle->lock); + return ret; + } } - /* S_PARM to set fps */ - v4l2_parm.parm.capture.timeperframe.numerator = 1; - v4l2_parm.parm.capture.timeperframe.denominator = format->stream_fps; - - if (ioctl(handle->device_fd, VIDIOC_S_PARM, &v4l2_parm) < 0) { - LOGE("S_PARM failed. errno %d", errno); - g_mutex_unlock(&handle->lock); - return CAMERA_ERROR_INTERNAL; - } +_SET_PREVIEW_STREAM_FORMAT_DONE: + /* set capture restart flag */ + if (format->stream_format == format->capture_format && + format->stream_resolution.width == format->capture_resolution.width && + format->stream_resolution.height == format->capture_resolution.height) + handle->capture_restart_stream = FALSE; + else + handle->capture_restart_stream = TRUE; memcpy(&handle->preview_format, format, sizeof(camera_format_t)); - LOGD("set preview stream [%d: %dx%d, fps %d]", + LOGD("set format PREVIEW[%d:%dx%d,fps:%d], CAPTURE[%d:%dx%d,restart:%d]", format->stream_format, format->stream_resolution.width, format->stream_resolution.height, - format->stream_fps); - - LOGW("CAPTURE STREAM [%d: %dx%d] IS NOT SUPPORTED", + format->stream_fps, format->capture_format, format->capture_resolution.width, - format->capture_resolution.height); + format->capture_resolution.height, + handle->capture_restart_stream); g_mutex_unlock(&handle->lock); @@ -1376,14 +1509,18 @@ int camera_start_preview(void *camera_handle, camera_preview_frame_cb callback, return CAMERA_ERROR_INVALID_STATE; } - ret = __camera_start_stream(handle, &handle->preview_format, BUFFER_MAX, &handle->buffer_count); + ret = __camera_start_stream(handle, + handle->preview_format.stream_format, + &handle->preview_format.stream_resolution, + handle->preview_format.stream_fps, + BUFFER_MAX); if (ret != CAMERA_ERROR_NONE) { LOGE("__camera_start_stream failed[0x%x]", ret); g_mutex_unlock(&handle->lock); return ret; } - g_mutex_lock(&handle->preview_cb_lock); + g_mutex_lock(&handle->buffer_lock); handle->buffer_thread_run = TRUE; @@ -1391,7 +1528,7 @@ int camera_start_preview(void *camera_handle, camera_preview_frame_cb callback, __camera_buffer_handler_func, (gpointer)handle, NULL); if (!handle->buffer_thread) { LOGE("failed to create buffer handler thread"); - g_mutex_unlock(&handle->preview_cb_lock); + g_mutex_unlock(&handle->buffer_lock); __camera_stop_stream(handle, handle->buffer_count); @@ -1403,7 +1540,7 @@ int camera_start_preview(void *camera_handle, camera_preview_frame_cb callback, handle->preview_cb = callback; handle->preview_cb_data = user_data; - g_mutex_unlock(&handle->preview_cb_lock); + g_mutex_unlock(&handle->buffer_lock); handle->state = CAMERA_STATE_PREVIEWING; @@ -1430,21 +1567,25 @@ int camera_release_preview_buffer(void *camera_handle, int buffer_index) } ret = __camera_v4l2_qbuf(handle->device_fd, - handle->v4l2_type, V4L2_MEMORY_MMAP, buffer_index); + handle->buffer_type, V4L2_MEMORY_MMAP, buffer_index); - g_mutex_lock(&handle->preview_cb_lock); + g_mutex_lock(&handle->buffer_lock); if (ret == CAMERA_ERROR_NONE) { - handle->live_buffer_num--; - LOGD("qbud done : index %d, live buffer num %d", - buffer_index, handle->live_buffer_num); + if (handle->buffer_dequeued_count > 0) + handle->buffer_dequeued_count--; + else + LOGW("invalid dequeued buffer count[%u]", handle->buffer_dequeued_count); + + /*LOGD("qbud done : index %d, dequeued buffer count %d", + buffer_index, handle->buffer_dequeued_count);*/ } else { LOGE("qbuf failed [index %d]", buffer_index); } - g_cond_signal(&handle->preview_cb_cond); + g_cond_signal(&handle->buffer_cond); - g_mutex_unlock(&handle->preview_cb_lock); + g_mutex_unlock(&handle->buffer_lock); return ret; } @@ -1471,14 +1612,14 @@ int camera_stop_preview(void *camera_handle) return CAMERA_ERROR_INVALID_STATE; } - g_mutex_lock(&handle->preview_cb_lock); + g_mutex_lock(&handle->buffer_lock); handle->buffer_thread_run = FALSE; - while (handle->live_buffer_num > 0) { - LOGD("wait for live buffer [num %d]", handle->live_buffer_num); + while (handle->buffer_dequeued_count > 0) { + LOGD("wait for dequeued buffer [%d]", handle->buffer_dequeued_count); end_time = g_get_monotonic_time() + 3 * G_TIME_SPAN_SECOND; - if (!g_cond_wait_until(&handle->preview_cb_cond, &handle->preview_cb_lock, end_time)) { + if (!g_cond_wait_until(&handle->buffer_cond, &handle->buffer_lock, end_time)) { LOGE("buffer wait failed"); break; } else { @@ -1486,7 +1627,7 @@ int camera_stop_preview(void *camera_handle) } } - g_mutex_unlock(&handle->preview_cb_lock); + g_mutex_unlock(&handle->buffer_lock); ret = __camera_stop_stream(handle, handle->buffer_count); @@ -1532,28 +1673,76 @@ int camera_stop_auto_focus(void *camera_handle) int camera_start_capture(void *camera_handle, camera_capture_cb callback, void *user_data) { - if (!camera_handle || !callback) { + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + + if (!handle || !callback) { LOGE("NULL param %p %p", camera_handle, callback); return CAMERA_ERROR_INVALID_PARAMETER; } - LOGE("NOT SUPPORTED"); + g_mutex_lock(&handle->lock); - /* capture function is not supported */ - return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; + if (handle->state != CAMERA_STATE_PREVIEWING) { + LOGE("invalid state %d", handle->state); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INVALID_STATE; + } + + /* set callback and user data */ + handle->capture_cb = callback; + handle->capture_cb_data = user_data; + + /* reset captured count */ + handle->captured_count = 0; + + /* set capture request flag */ + handle->capture_request = TRUE; + + handle->state = CAMERA_STATE_CAPTURING; + + LOGD("start capture"); + + g_mutex_unlock(&handle->lock); + + return CAMERA_ERROR_NONE; } int camera_stop_capture(void *camera_handle) { - if (!camera_handle) { + camera_hal_handle *handle = (camera_hal_handle *)camera_handle; + + if (!handle) { LOGE("NULL handle"); return CAMERA_ERROR_INVALID_PARAMETER; } - LOGE("NOT SUPPORTED"); + g_mutex_lock(&handle->lock); - /* capture function is not supported */ - return CAMERA_ERROR_DEVICE_NOT_SUPPORTED; + if (handle->state != CAMERA_STATE_CAPTURING) { + LOGE("invalid state %d", handle->state); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INVALID_STATE; + } + + g_mutex_lock(&handle->buffer_lock); + + if (handle->captured_count == 0) { + LOGE("No captured image yet."); + g_mutex_unlock(&handle->buffer_lock); + g_mutex_unlock(&handle->lock); + return CAMERA_ERROR_INTERNAL; + } + + LOGD("send signal to start preview after capture"); + + g_cond_signal(&handle->buffer_cond); + g_mutex_unlock(&handle->buffer_lock); + + handle->state = CAMERA_STATE_PREVIEWING; + + g_mutex_unlock(&handle->lock); + + return CAMERA_ERROR_NONE; } int camera_set_video_stream_format(void *camera_handle, camera_format_t *format) diff --git a/src/tizen_camera_v4l2_private.h b/src/tizen_camera_v4l2_private.h index 2e4996f..c6abc44 100644 --- a/src/tizen_camera_v4l2_private.h +++ b/src/tizen_camera_v4l2_private.h @@ -32,44 +32,48 @@ #define V4L2_PLANES_MAX 4 typedef struct _camera_hal_handle { + /* tbm */ tbm_bufmgr bufmgr; - int device_index; - int device_fd; - camera_state_t state; - camera_format_t preview_format; - camera_format_t video_format; + /* device */ + gint32 device_index; + gint32 device_fd; - /* V4L2 */ - enum v4l2_buf_type v4l2_type; - uint8_t plane_num; - int live_buffer_num; - - /* thread */ + /* buffer */ + guint32 buffer_dequeued_count; GThread *buffer_thread; - GThread *message_thread; gboolean buffer_thread_run; + guint32 buffer_count; + camera_buffer_t camera_buffers[BUFFER_MAX]; + enum v4l2_buf_type buffer_type; + GMutex buffer_lock; + GCond buffer_cond; - /* buffer handler */ + /* preview */ + camera_format_t preview_format; camera_preview_frame_cb preview_cb; + gpointer preview_cb_data; + + /* capture */ camera_capture_cb capture_cb; - void *preview_cb_data; - void *capture_cb_data; - uint32_t buffer_count; - camera_buffer_t camera_buffers[BUFFER_MAX]; + gpointer capture_cb_data; + guint32 capture_count; + guint32 captured_count; + gboolean capture_request; + gboolean capture_restart_stream; - /* message callback */ - camera_message_cb message_cb[MESSAGE_CALLBACK_MAX]; - void *message_cb_data[MESSAGE_CALLBACK_MAX]; - gboolean message_cb_run; - GQueue *message_list; + /* message */ + GThread *msg_thread; + camera_message_cb msg_cb[MESSAGE_CALLBACK_MAX]; + gpointer msg_cb_data[MESSAGE_CALLBACK_MAX]; + gboolean msg_cb_run; + GQueue *msg_list; + GMutex msg_cb_lock; + GCond msg_cb_cond; - /* thread safe */ + /* etc */ GMutex lock; - GMutex preview_cb_lock; - GMutex message_cb_lock; - GCond preview_cb_cond; - GCond message_cb_cond; + camera_state_t state; } camera_hal_handle; #endif /* __TIZEN_CAMERA_PRIVATE_H__ */ -- 2.7.4