AC_SUBST(DLOG_CFLAGS)
AC_SUBST(DLOG_LIBS)
+PKG_CHECK_MODULES(HAL_API_COMMON, hal-api-common)
+AC_SUBST(HAL_API_COMMON_CFLAGS)
+
+PKG_CHECK_MODULES(HAL_API_CAMERA, hal-api-camera)
+AC_SUBST(HAL_API_CAMERA_CFLAGS)
+
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([fcntl.h memory.h stdlib.h string.h sys/time.h unistd.h])
Name: camera-hal-v4l2
Summary: Tizen Camera Hal for V4L2
-Version: 0.0.13
+Version: 0.1.0
Release: 0
Group: Multimedia/Libraries
License: Apache-2.0
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(libtbm)
BuildRequires: pkgconfig(dlog)
-BuildRequires: mm-hal-interface-devel
-BuildRequires: gtest-devel
+BuildRequires: pkgconfig(hal-api-common)
+BuildRequires: pkgconfig(hal-api-camera)
%description
Tizen Camera Hal for V4L2.
%build
./autogen.sh
-%configure --disable-static
+%configure --disable-static --libdir=%{_hal_libdir}
make %{?jobs:-j%jobs}
%install
%manifest %{name}.manifest
%license LICENSE.APLv2
%defattr(-,root,root,-)
-%{_libdir}/*.so
+%{_hal_libdir}/*.so
ACLOCAL_AMFLAGS='-I m4'
-lib_LTLIBRARIES = libtizen-camera.la
+lib_LTLIBRARIES = libhal-backend-camera.la
-noinst_HEADERS = tizen_camera_v4l2_private.h
+noinst_HEADERS = hal_camera_v4l2_private.h
-libtizen_camera_la_SOURCES = tizen_camera_v4l2.c
+libhal_backend_camera_la_SOURCES = hal_camera_v4l2.c
-libtizen_camera_la_CFLAGS = -I$(srcdir)/include \
- $(GLIB_CFLAGS) \
- $(DLOG_CFLAGS) \
- $(TBM_CFLAGS)
+libhal_backend_camera_la_CFLAGS = \
+ -I$(srcdir)/include \
+ $(GLIB_CFLAGS) \
+ $(DLOG_CFLAGS) \
+ $(HAL_API_COMMON_CFLAGS) \
+ $(HAL_API_CAMERA_CFLAGS) \
+ $(TBM_CFLAGS)
-libtizen_camera_la_LIBADD = $(GLIB_LIBS) \
- $(DLOG_LIBS) \
- $(TBM_LIBS)
+libhal_backend_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
+libhal_backend_camera_la_CFLAGS += -fdata-sections -ffunction-sections -Wl,--gc-sections
+libhal_backend_camera_la_LDFLAGS = -Wl,--gc-sections -avoid-version
--- /dev/null
+/*
+ * 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 <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <glob.h>
+#include <dlog.h>
+#include <sched.h>
+#include "hal_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_s *g_device_info_list;
+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)
+{
+ 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)
+{
+ 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_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) {
+ 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, uint32_t count, uint32_t *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, guint32 *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_s *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)", j,
+ 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_s *device_info_list = NULL;
+
+ g_mutex_lock(&g_device_info_lock);
+
+ if (g_device_info_list) {
+ LOGD("device info list is already existed");
+ ret = CAMERA_ERROR_NONE;
+ goto _GET_DEVICE_INFO_LIST_DONE;
+ }
+
+ device_info_list = g_new0(camera_device_info_list_s, 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 error : %d", ret);
+ ret = CAMERA_ERROR_INTERNAL;
+ goto _GET_DEVICE_INFO_LIST_DONE;
+ }
+ }
+
+ LOGD("device node count : %zu", glob_buf.gl_pathc);
+
+ for (i = 0 ; i < glob_buf.gl_pathc ; i++) {
+ LOGD("[%d] check device [%s]", i, glob_buf.gl_pathv[i]);
+
+ device_fd = open(glob_buf.gl_pathv[i], O_RDWR);
+ if (device_fd < 0) {
+ LOGE("open failed [%s] errno %d", glob_buf.gl_pathv[i], errno);
+ continue;
+ }
+
+ 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)
+ g_device_caps = v4l2_cap.device_caps;
+ else
+ g_device_caps = v4l2_cap.capabilities;
+
+ if (!(g_device_caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)) ||
+ (g_device_caps & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE))) {
+ LOGW("[%s] is not a capture device 0x%x", glob_buf.gl_pathv[i], g_device_caps);
+ 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 int __camera_stop_stream(hal_camera_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->buffer_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->buffer_type, V4L2_MEMORY_MMAP, 0, &buffer_count);
+
+ LOGD("reqbufs 0 : 0x%x", ret);
+
+ return ret;
+}
+
+
+static int __camera_start_stream(hal_camera_handle *handle, camera_pixel_format_e pixel_format,
+ camera_resolution_s *resolution, uint32_t fps, uint32_t request_buffer_count)
+{
+ int i = 0;
+ int ret = CAMERA_ERROR_NONE;
+ camera_buffer_s *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];;
+ 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));
+
+ 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->buffer_type, V4L2_MEMORY_MMAP, request_buffer_count, &handle->buffer_count);
+ if (ret != CAMERA_ERROR_NONE) {
+ return ret;
+ }
+
+ LOGD("buffer count : request %d -> result %d",
+ request_buffer_count, handle->buffer_count);
+
+ /* query buffer, mmap and qbuf */
+ 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->buffer_type;
+ v4l2_buf.memory = V4L2_MEMORY_MMAP;
+ v4l2_buf.index = i;
+ v4l2_buf.m.planes = v4l2_planes;
+ 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;
+ }
+
+ buffer = &handle->camera_buffers[i];
+
+ buffer->index = i;
+ buffer->format = pixel_format;
+ buffer->resolution.width = resolution->width;
+ buffer->resolution.height = resolution->height;
+ buffer->total_size = v4l2_buf.length;
+ buffer->num_planes = 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_STREAM_FAILED;
+ }
+
+ 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;
+ }
+ }
+
+ /* stream on */
+ ret = __camera_v4l2_stream(handle->device_fd, handle->buffer_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, handle->buffer_count);
+ return ret;
+}
+
+
+static void __camera_do_capture(hal_camera_handle *handle)
+{
+ int ret = CAMERA_ERROR_NONE;
+ int buffer_index = 0;
+ gint64 current_time = 0;
+ gint64 previous_time = 0;
+ gint64 interval_us = 0;
+
+ if (!handle) {
+ LOGE("NULL handle");
+ return;
+ }
+
+ LOGD("start");
+
+ if (handle->capture_count > 1)
+ interval_us = handle->capture_interval_ms * 1000;
+
+ /* 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;
+ }
+ }
+
+ do {
+ /* 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;
+ }
+
+ if (handle->captured_count > 0) {
+ g_mutex_lock(&handle->buffer_lock);
+ if (handle->state != CAMERA_STATE_CAPTURING) {
+ LOGW("stop continuous capture");
+ handle->captured_count = handle->capture_count;
+ g_mutex_unlock(&handle->buffer_lock);
+ goto _TRY_NEXT;
+ }
+ g_mutex_unlock(&handle->buffer_lock);
+ }
+
+ if (handle->capture_count > 1) {
+ current_time = g_get_monotonic_time();
+
+ LOGI("time[prev:%"PRId64", cur:%"PRId64"] interval[%"PRId64" us]",
+ previous_time, current_time, interval_us);
+
+ if (current_time < previous_time + interval_us)
+ goto _TRY_NEXT;
+ }
+
+ 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) {
+ handle->capture_cb(&handle->camera_buffers[buffer_index],
+ NULL, NULL, handle->capture_cb_data);
+ } else {
+ LOGW("capture callback is NULL");
+ /* Need to post error? */
+ }
+
+ previous_time = current_time;
+
+_TRY_NEXT:
+ 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);
+ } while (handle->captured_count < handle->capture_count);
+
+ 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;
+ hal_camera_handle *handle = (hal_camera_handle *)data;
+
+ if (!handle) {
+ LOGE("NULL handle for buffer handler");
+ return NULL;
+ }
+
+ LOGD("enter");
+
+ /* run buffer thread */
+ g_mutex_lock(&handle->buffer_lock);
+
+ while (handle->buffer_thread_run) {
+ 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->buffer_lock);
+ break;
+ }
+
+ g_mutex_lock(&handle->buffer_lock);
+
+ if (handle->buffer_thread_run == FALSE) {
+ LOGW("stop buffer handler thread");
+ break;
+ }
+
+ if (__camera_v4l2_dqbuf(handle->device_fd, handle->buffer_type, V4L2_MEMORY_MMAP, &index) != CAMERA_ERROR_NONE) {
+ LOGE("dqbuf failed");
+ break;
+ }
+
+ handle->buffer_dequeued_count++;
+
+ /*LOGD("dequeued buffer count %d", handle->buffer_dequeued_count);*/
+
+ g_mutex_unlock(&handle->buffer_lock);
+
+ if (handle->preview_cb) {
+ handle->preview_cb(&handle->camera_buffers[index], NULL, handle->preview_cb_data);
+ } else {
+ LOGW("preview callback is NULL");
+ camera_v4l2_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->buffer_lock);
+ }
+
+ g_mutex_unlock(&handle->buffer_lock);
+
+ LOGD("leave");
+
+ return NULL;
+}
+
+
+static void __camera_message_release_func(gpointer data)
+{
+ camera_message_s *message = (camera_message_s *)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_s *message = NULL;
+ hal_camera_handle *handle = (hal_camera_handle *)data;
+
+ if (!handle) {
+ LOGE("NULL handle for capture thread");
+ return NULL;
+ }
+
+ LOGD("enter - message thread");
+
+ g_mutex_lock(&handle->msg_cb_lock);
+
+ while (handle->msg_cb_run) {
+ if (g_queue_is_empty(handle->msg_list)) {
+ LOGD("wait for message");
+ g_cond_wait(&handle->msg_cb_cond, &handle->msg_cb_lock);
+ LOGD("message signal received");
+ }
+
+ if (!handle->msg_cb_run) {
+ LOGW("break message thread");
+ break;
+ }
+
+ message = g_queue_pop_head(handle->msg_list);
+ if (!message) {
+ LOGW("NULL message");
+ continue;
+ }
+
+ g_mutex_unlock(&handle->msg_cb_lock);
+
+ for (i = 0 ; i < MESSAGE_CALLBACK_MAX ; i++) {
+ if (handle->msg_cb[i]) {
+ LOGD("call message callback type %d", message->type);
+ handle->msg_cb[i](message, handle->msg_cb_data[i]);
+ }
+ }
+
+ g_free(message);
+ message = NULL;
+
+ g_mutex_lock(&handle->msg_cb_lock);
+ }
+
+ g_mutex_unlock(&handle->msg_cb_lock);
+
+ LOGD("leave - message thread");
+
+ return NULL;
+}
+
+
+static void __camera_release_handle(hal_camera_handle *handle)
+{
+ if (!handle) {
+ LOGW("NULL handle");
+ return;
+ }
+
+ 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->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);
+ handle->bufmgr = NULL;
+ }
+
+ LOGD("camera HAL handle %p destroy", handle);
+
+ g_free(handle);
+
+ return;
+}
+
+
+int camera_v4l2_init(void **camera_handle)
+{
+ int ret = CAMERA_ERROR_NONE;
+ hal_camera_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(hal_camera_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->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->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->msg_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_v4l2_deinit(void *camera_handle)
+{
+ hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
+
+ if (!handle) {
+ LOGE("NULL handle");
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ 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_v4l2_get_device_info_list(camera_device_info_list_s *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_s));
+
+ return CAMERA_ERROR_NONE;
+}
+
+
+int camera_v4l2_open_device(void *camera_handle, int device_index)
+{
+ int ret = CAMERA_ERROR_NONE;
+ int device_fd = CAMERA_HAL_INITIAL_FD;
+ char *node_path = NULL;
+ hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
+
+ if (!handle) {
+ LOGE("NULL handle");
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ 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 (g_device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
+ handle->buffer_type = V4L2_CAP_VIDEO_CAPTURE_MPLANE;
+ else
+ 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->buffer_type);
+
+_OPEN_DEVICE_DONE:
+ g_mutex_unlock(&handle->lock);
+
+ return ret;
+}
+
+
+int camera_v4l2_open_device_ext(void *camera_handle, const char *device_name)
+{
+ LOGE("NOT SUPPORTED");
+ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+}
+
+
+int camera_v4l2_close_device(void *camera_handle)
+{
+ hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
+
+ if (!handle) {
+ LOGE("NULL handle");
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ 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_v4l2_add_message_callback(void *camera_handle, hal_camera_message_cb callback, void *user_data, uint32_t *cb_id)
+{
+ uint32_t i = 0;
+ hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
+
+ if (!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;
+ }
+
+ 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->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);
+ return CAMERA_ERROR_NONE;
+ }
+ }
+
+ g_mutex_unlock(&handle->lock);
+
+ LOGE("no available message cb slot");
+
+ return CAMERA_ERROR_INTERNAL;
+}
+
+
+int camera_v4l2_remove_message_callback(void *camera_handle, uint32_t cb_id)
+{
+ hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
+
+ if (!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;
+ }
+
+ 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->msg_cb[cb_id]) {
+ LOGD("remove message callback %p, user data %p - cb_id %u",
+ handle->msg_cb[cb_id], handle->msg_cb_data[cb_id], cb_id);
+
+ handle->msg_cb[cb_id] = NULL;
+ handle->msg_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_v4l2_set_preview_stream_format(void *camera_handle, camera_format_s *format)
+{
+ int i = 0;
+ int j = 0;
+ int ret = CAMERA_ERROR_NONE;
+ gboolean capability_check = FALSE;
+ hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
+ camera_device_info_s *device_info = NULL;
+
+ if (!handle || !format) {
+ LOGE("NULL param %p %p", handle, format);
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ if (!g_device_info_list) {
+ LOGE("no device info list");
+ return CAMERA_ERROR_INTERNAL;
+ }
+
+ g_mutex_lock(&handle->lock);
+
+ 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;
+ }
+
+ /* 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;
+ }
+
+ /* 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;
+ }
+
+ LOGD("Preview setting is changed. Restart preview now.");
+
+ /* 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;
+ }
+
+ /* 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;
+ }
+ }
+
+_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_s));
+
+ 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,
+ format->capture_format,
+ format->capture_resolution.width,
+ format->capture_resolution.height,
+ handle->capture_restart_stream);
+
+ g_mutex_unlock(&handle->lock);
+
+ return CAMERA_ERROR_NONE;
+}
+
+
+int camera_v4l2_get_preview_stream_format(void *camera_handle, camera_format_s *format)
+{
+ hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
+
+ if (!handle || !format) {
+ LOGE("NULL param %p %p", handle, format);
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ g_mutex_lock(&handle->lock);
+
+ memcpy(format, &handle->preview_format, sizeof(camera_format_s));
+
+ 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_v4l2_set_user_buffer_fd(void *camera_handle, int *fds, int number)
+{
+ LOGE("NOT SUPPORTED");
+ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+}
+
+
+int camera_v4l2_start_preview(void *camera_handle, hal_camera_preview_frame_cb callback, void *user_data)
+{
+ int ret = 0;
+ hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
+
+ if (!handle || !callback) {
+ LOGE("NULL param %p %p", handle, callback);
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ 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;
+ }
+
+ 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->buffer_lock);
+
+ handle->buffer_thread_run = TRUE;
+
+ 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->buffer_lock);
+
+ __camera_stop_stream(handle, handle->buffer_count);
+
+ g_mutex_unlock(&handle->lock);
+
+ return ret;
+ }
+
+ handle->preview_cb = callback;
+ handle->preview_cb_data = user_data;
+
+ g_mutex_unlock(&handle->buffer_lock);
+
+ handle->state = CAMERA_STATE_PREVIEWING;
+
+ LOGD("start preview done");
+
+ g_mutex_unlock(&handle->lock);
+
+ return CAMERA_ERROR_NONE;
+}
+
+
+int camera_v4l2_release_preview_buffer(void *camera_handle, int buffer_index)
+{
+ int ret = CAMERA_ERROR_NONE;
+ hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
+
+ if (!handle) {
+ LOGE("NULL handle");
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ 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,
+ handle->buffer_type, V4L2_MEMORY_MMAP, buffer_index);
+
+ g_mutex_lock(&handle->buffer_lock);
+
+ if (ret == CAMERA_ERROR_NONE) {
+ 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->buffer_cond);
+
+ g_mutex_unlock(&handle->buffer_lock);
+
+ return ret;
+}
+
+
+int camera_v4l2_stop_preview(void *camera_handle)
+{
+ int ret = CAMERA_ERROR_NONE;
+ gint64 end_time;
+ hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
+
+ if (!handle) {
+ LOGE("NULL handle");
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ 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->buffer_lock);
+
+ handle->buffer_thread_run = FALSE;
+
+ 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->buffer_cond, &handle->buffer_lock, end_time)) {
+ LOGE("buffer wait failed");
+ break;
+ } else {
+ LOGD("signal received. check again...");
+ }
+ }
+
+ g_mutex_unlock(&handle->buffer_lock);
+
+ ret = __camera_stop_stream(handle, handle->buffer_count);
+
+ /* wait for preview thread exit */
+ g_thread_join(handle->buffer_thread);
+ handle->buffer_thread = NULL;
+
+ handle->state = CAMERA_STATE_OPENED;
+
+ LOGD("stop preview done [0x%x]", ret);
+
+ g_mutex_unlock(&handle->lock);
+
+ return CAMERA_ERROR_NONE;
+}
+
+
+int camera_v4l2_start_auto_focus(void *camera_handle)
+{
+ if (!camera_handle) {
+ LOGE("NULL handle");
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ LOGE("NOT SUPPORTED");
+
+ /* auto focus is not supported */
+ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+}
+
+
+int camera_v4l2_stop_auto_focus(void *camera_handle)
+{
+ if (!camera_handle) {
+ LOGE("NULL handle");
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ LOGE("NOT SUPPORTED");
+
+ /* auto focus is not supported */
+ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+}
+
+
+int camera_v4l2_start_capture(void *camera_handle, hal_camera_capture_cb callback, void *user_data)
+{
+ hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
+
+ if (!handle || !callback) {
+ LOGE("NULL param %p %p", camera_handle, callback);
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ 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;
+ }
+
+ /* set callback and user data */
+ handle->capture_cb = callback;
+ handle->capture_cb_data = user_data;
+
+ /* reset captured count */
+ handle->captured_count = 0;
+
+ LOGD("start capture - count %u", handle->capture_count);
+
+ /* set capture request flag */
+ handle->capture_request = TRUE;
+
+ handle->state = CAMERA_STATE_CAPTURING;
+
+ g_mutex_unlock(&handle->lock);
+
+ return CAMERA_ERROR_NONE;
+}
+
+
+int camera_v4l2_stop_capture(void *camera_handle)
+{
+ hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
+
+ if (!handle) {
+ LOGE("NULL handle");
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ g_mutex_lock(&handle->lock);
+
+ 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_v4l2_set_video_stream_format(void *camera_handle, camera_format_s *format)
+{
+ if (!camera_handle || !format) {
+ LOGE("NULL param %p %p", camera_handle, format);
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ LOGE("NOT SUPPORTED");
+
+ /* single stream device can not support video stream */
+ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+}
+
+
+int camera_v4l2_get_video_stream_format(void *camera_handle, camera_format_s *format)
+{
+ if (!camera_handle || !format) {
+ LOGE("NULL param %p %p", camera_handle, format);
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ LOGE("NOT SUPPORTED");
+
+ /* single stream device can not support video stream */
+ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+}
+
+
+int camera_v4l2_start_record(void *camera_handle, hal_camera_video_frame_cb callback, void *user_data)
+{
+ if (!camera_handle || !callback) {
+ LOGE("NULL param %p %p", camera_handle, callback);
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ LOGE("NOT SUPPORTED");
+
+ /* single stream device can not support video stream */
+ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+}
+
+
+int camera_v4l2_release_video_buffer(void *camera_handle, int buffer_index)
+{
+ if (!camera_handle) {
+ LOGE("NULL handle");
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ LOGE("NOT SUPPORTED");
+
+ /* single stream device can not support video stream */
+ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+}
+
+
+int camera_v4l2_stop_record(void *camera_handle)
+{
+ if (!camera_handle) {
+ LOGE("NULL handle");
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ LOGE("NOT SUPPORTED");
+
+ /* single stream device can not support video stream */
+ return CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+}
+
+
+int camera_v4l2_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;
+ hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
+
+ if (!handle || !value) {
+ LOGE("NULL param %p %p", handle, value);
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ set_value = *(int *)value;
+
+ g_mutex_lock(&handle->lock);
+
+ if (handle->state < CAMERA_STATE_OPENED) {
+ LOGE("invalid state %d", handle->state);
+ ret = CAMERA_ERROR_INVALID_STATE;
+ goto _SET_COMMAND_DONE;
+ }
+
+ LOGD("set command %"PRIx64" - state %d", command, handle->state);
+
+ switch (command) {
+ case CAMERA_COMMAND_BRIGHTNESS:
+ 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;
+ case CAMERA_COMMAND_PTZ_TYPE:
+ if (set_value != CAMERA_PTZ_TYPE_ELECTRONIC) {
+ LOGE("not supported PTZ type %d", set_value);
+ ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+ }
+ goto _SET_COMMAND_DONE;
+ case CAMERA_COMMAND_PAN:
+ cid = V4L2_CID_PAN_ABSOLUTE;
+ break;
+ case CAMERA_COMMAND_TILT:
+ cid = V4L2_CID_TILT_ABSOLUTE;
+ break;
+ case CAMERA_COMMAND_FLIP:
+ if (set_value != CAMERA_FLIP_NONE) {
+ LOGE("NOT_SUPPORTED flip %d", set_value);
+ ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+ }
+ goto _SET_COMMAND_DONE;
+ case CAMERA_COMMAND_CAPTURE_COUNT:
+ handle->capture_count = set_value;
+ LOGI("capture count %u", handle->capture_count);
+ goto _SET_COMMAND_DONE;
+ case CAMERA_COMMAND_CAPTURE_INTERVAL:
+ handle->capture_interval_ms = set_value;
+ LOGI("capture interval %u ms", handle->capture_interval_ms);
+ goto _SET_COMMAND_DONE;
+ default:
+ LOGE("NOT_SUPPORTED command %"PRIx64, command);
+ ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
+ goto _SET_COMMAND_DONE;
+ }
+
+ ctrl_ret = __camera_v4l2_s_ctrl(handle->device_fd, cid, set_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;
+ }
+ }
+
+_SET_COMMAND_DONE:
+ g_mutex_unlock(&handle->lock);
+
+ return ret;
+}
+
+
+int camera_v4l2_get_command(void *camera_handle, int64_t command, void **value)
+{
+ int ret = CAMERA_ERROR_NONE;
+ int cid = 0;
+ int ctrl_ret = 0;
+ hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
+
+ if (!handle || !value) {
+ LOGE("NULL param %p %p", handle, value);
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ g_mutex_lock(&handle->lock);
+
+ LOGD("get command %"PRId64" - state %d", command, handle->state);
+
+ switch (command) {
+ case CAMERA_COMMAND_BRIGHTNESS:
+ 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 %"PRId64, 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 ret;
+}
+
+
+int camera_v4l2_set_batch_command(void *camera_handle, camera_batch_command_control_s *batch_command, int64_t *error_command)
+{
+ hal_camera_handle *handle = (hal_camera_handle *)camera_handle;
+
+ if (!handle || !batch_command) {
+ LOGE("NULL param %p %p", handle, batch_command);
+ return CAMERA_ERROR_INVALID_PARAMETER;
+ }
+
+ g_mutex_lock(&handle->lock);
+
+ LOGD("set batch command - flag %"PRIx64", state %d",
+ batch_command->command_set_flag, handle->state);
+
+ /* TODO: to be implemented */
+
+ g_mutex_unlock(&handle->lock);
+
+ return CAMERA_ERROR_NONE;
+}
+
+
+static int camera_v4l2_backend_init(void **data)
+{
+ hal_backend_camera_funcs *funcs;
+
+ funcs = calloc(1, sizeof(hal_backend_camera_funcs));
+ if (!funcs)
+ return CAMERA_ERROR_OUT_OF_MEMORY;
+
+ funcs->init = camera_v4l2_init;
+ funcs->deinit = camera_v4l2_deinit;
+ funcs->get_device_info_list = camera_v4l2_get_device_info_list;
+ funcs->open_device = camera_v4l2_open_device;
+ funcs->open_device_ext = camera_v4l2_open_device_ext;
+ funcs->close_device = camera_v4l2_close_device;
+ funcs->add_message_callback = camera_v4l2_add_message_callback;
+ funcs->remove_message_callback = camera_v4l2_remove_message_callback;
+ funcs->set_preview_stream_format = camera_v4l2_set_preview_stream_format;
+ funcs->get_preview_stream_format = camera_v4l2_get_preview_stream_format;
+ funcs->set_user_buffer_fd = camera_v4l2_set_user_buffer_fd;
+ funcs->start_preview = camera_v4l2_start_preview;
+ funcs->release_preview_buffer = camera_v4l2_release_preview_buffer;
+ funcs->stop_preview = camera_v4l2_stop_preview;
+ funcs->start_auto_focus = camera_v4l2_start_auto_focus;
+ funcs->stop_auto_focus = camera_v4l2_stop_auto_focus;
+ funcs->start_capture = camera_v4l2_start_capture;
+ funcs->stop_capture = camera_v4l2_stop_capture;
+ funcs->set_video_stream_format = camera_v4l2_set_video_stream_format;
+ funcs->get_video_stream_format = camera_v4l2_get_video_stream_format;
+ funcs->start_record = camera_v4l2_start_record;
+ funcs->release_video_buffer = camera_v4l2_release_video_buffer;
+ funcs->stop_record = camera_v4l2_stop_record;
+ funcs->set_command = camera_v4l2_set_command;
+ funcs->get_command = camera_v4l2_get_command;
+ funcs->set_batch_command = camera_v4l2_set_batch_command;
+
+ *data = (void *)funcs;
+
+ return 0;
+}
+
+
+static int camera_v4l2_backend_exit(void *data)
+{
+ if (!data)
+ return 0;
+
+ free(data);
+
+ return 0;
+}
+
+
+hal_backend hal_backend_camera_data = {
+ .name = "camera-v4l2",
+ .vendor = "TIZEN",
+ .abi_version = HAL_ABI_VERSION_TIZEN_6_5,
+ .init = camera_v4l2_backend_init,
+ .exit = camera_v4l2_backend_exit,
+};
--- /dev/null
+/*
+ * hal_camera_v4l2_private.h
+ *
+ * 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 __HAL_CAMERA_V4L2_PRIVATE_H__
+#define __HAL_CAMERA_V4L2_PRIVATE_H__
+
+#include <linux/videodev2.h>
+#include <glib.h>
+#include <tbm_bufmgr.h>
+#include <hal/hal-common-interface.h>
+#include <hal/hal-camera-interface.h>
+
+#define CAMERA_HAL_INITIAL_INDEX -1
+#define CAMERA_HAL_INITIAL_FD -1
+#define MESSAGE_CALLBACK_MAX 10
+#define BUFFER_MAX 4
+#define V4L2_PLANES_MAX 4
+
+typedef struct _camera_hal_handle {
+ /* tbm */
+ tbm_bufmgr bufmgr;
+
+ /* device */
+ gint32 device_index;
+ gint32 device_fd;
+
+ /* buffer */
+ guint32 buffer_dequeued_count;
+ GThread *buffer_thread;
+ gboolean buffer_thread_run;
+ guint32 buffer_count;
+ camera_buffer_s camera_buffers[BUFFER_MAX];
+ enum v4l2_buf_type buffer_type;
+ GMutex buffer_lock;
+ GCond buffer_cond;
+
+ /* preview */
+ camera_format_s preview_format;
+ hal_camera_preview_frame_cb preview_cb;
+ gpointer preview_cb_data;
+
+ /* capture */
+ hal_camera_capture_cb capture_cb;
+ gpointer capture_cb_data;
+ guint32 capture_count;
+ guint32 capture_interval_ms;
+ guint32 captured_count;
+ gboolean capture_request;
+ gboolean capture_restart_stream;
+
+ /* message */
+ GThread *msg_thread;
+ hal_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;
+
+ /* etc */
+ GMutex lock;
+ camera_state_e state;
+} hal_camera_handle;
+
+int camera_v4l2_init(void **camera_handle);
+int camera_v4l2_deinit(void *camera_handle);
+int camera_v4l2_get_device_info_list(camera_device_info_list_s *device_info_list);
+int camera_v4l2_open_device(void *camera_handle, int device_index);
+int camera_v4l2_open_device_ext(void *camera_handle, const char *device_name);
+int camera_v4l2_close_device(void *camera_handle);
+int camera_v4l2_add_message_callback(void *camera_handle, hal_camera_message_cb callback, void *user_data, uint32_t *cb_id);
+int camera_v4l2_remove_message_callback(void *camera_handle, uint32_t cb_id);
+int camera_v4l2_set_preview_stream_format(void *camera_handle, camera_format_s *format);
+int camera_v4l2_get_preview_stream_format(void *camera_handle, camera_format_s *format);
+int camera_v4l2_set_user_buffer_fd(void *camera_handle, int *fds, int number);
+int camera_v4l2_start_preview(void *camera_handle, hal_camera_preview_frame_cb callback, void *user_data);
+int camera_v4l2_release_preview_buffer(void *camera_handle, int buffer_index);
+int camera_v4l2_stop_preview(void *camera_handle);
+int camera_v4l2_start_auto_focus(void *camera_handle);
+int camera_v4l2_stop_auto_focus(void *camera_handle);
+int camera_v4l2_start_capture(void *camera_handle, hal_camera_capture_cb callback, void *user_data);
+int camera_v4l2_stop_capture(void *camera_handle);
+int camera_v4l2_set_video_stream_format(void *camera_handle, camera_format_s *format);
+int camera_v4l2_get_video_stream_format(void *camera_handle, camera_format_s *format);
+int camera_v4l2_start_record(void *camera_handle, hal_camera_video_frame_cb callback, void *user_data);
+int camera_v4l2_release_video_buffer(void *camera_handle, int buffer_index);
+int camera_v4l2_stop_record(void *camera_handle);
+int camera_v4l2_set_command(void *camera_handle, int64_t command, void *value);
+int camera_v4l2_get_command(void *camera_handle, int64_t command, void **value);
+int camera_v4l2_set_batch_command(void *camera_handle, camera_batch_command_control_s *batch_command, int64_t *error_command);
+
+#endif /* __HAL_CAMERA_V4L2_PRIVATE_H__ */
+++ /dev/null
-/*
- * 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 <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <glob.h>
-#include <dlog.h>
-#include <sched.h>
-#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 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)
-{
- 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)
-{
- 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_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) {
- 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, uint32_t count, uint32_t *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, guint32 *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)", j,
- 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 error : %d", ret);
- ret = CAMERA_ERROR_INTERNAL;
- goto _GET_DEVICE_INFO_LIST_DONE;
- }
- }
-
- LOGD("device node count : %zu", glob_buf.gl_pathc);
-
- for (i = 0 ; i < glob_buf.gl_pathc ; i++) {
- LOGD("[%d] check device [%s]", i, glob_buf.gl_pathv[i]);
-
- device_fd = open(glob_buf.gl_pathv[i], O_RDWR);
- if (device_fd < 0) {
- LOGE("open failed [%s] errno %d", glob_buf.gl_pathv[i], errno);
- continue;
- }
-
- 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)
- g_device_caps = v4l2_cap.device_caps;
- else
- g_device_caps = v4l2_cap.capabilities;
-
- if (!(g_device_caps & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE)) ||
- (g_device_caps & (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE))) {
- LOGW("[%s] is not a capture device 0x%x", glob_buf.gl_pathv[i], g_device_caps);
- 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 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->buffer_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->buffer_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_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];;
- 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));
-
- 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->buffer_type, V4L2_MEMORY_MMAP, request_buffer_count, &handle->buffer_count);
- if (ret != CAMERA_ERROR_NONE) {
- return ret;
- }
-
- LOGD("buffer count : request %d -> result %d",
- request_buffer_count, handle->buffer_count);
-
- /* query buffer, mmap and qbuf */
- 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->buffer_type;
- v4l2_buf.memory = V4L2_MEMORY_MMAP;
- v4l2_buf.index = i;
- v4l2_buf.m.planes = v4l2_planes;
- 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;
- }
-
- buffer = &handle->camera_buffers[i];
-
- buffer->index = i;
- buffer->format = pixel_format;
- buffer->resolution.width = resolution->width;
- buffer->resolution.height = resolution->height;
- buffer->total_size = v4l2_buf.length;
- buffer->num_planes = 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_STREAM_FAILED;
- }
-
- 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;
- }
- }
-
- /* stream on */
- ret = __camera_v4l2_stream(handle->device_fd, handle->buffer_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, handle->buffer_count);
- return ret;
-}
-
-
-static void __camera_do_capture(camera_hal_handle *handle)
-{
- int ret = CAMERA_ERROR_NONE;
- int buffer_index = 0;
- gint64 current_time = 0;
- gint64 previous_time = 0;
- gint64 interval_us = 0;
-
- if (!handle) {
- LOGE("NULL handle");
- return;
- }
-
- LOGD("start");
-
- if (handle->capture_count > 1)
- interval_us = handle->capture_interval_ms * 1000;
-
- /* 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;
- }
- }
-
- do {
- /* 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;
- }
-
- if (handle->captured_count > 0) {
- g_mutex_lock(&handle->buffer_lock);
- if (handle->state != CAMERA_STATE_CAPTURING) {
- LOGW("stop continuous capture");
- handle->captured_count = handle->capture_count;
- g_mutex_unlock(&handle->buffer_lock);
- goto _TRY_NEXT;
- }
- g_mutex_unlock(&handle->buffer_lock);
- }
-
- if (handle->capture_count > 1) {
- current_time = g_get_monotonic_time();
-
- LOGI("time[prev:%"PRId64", cur:%"PRId64"] interval[%"PRId64" us]",
- previous_time, current_time, interval_us);
-
- if (current_time < previous_time + interval_us)
- goto _TRY_NEXT;
- }
-
- 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? */
- }
-
- previous_time = current_time;
-
-_TRY_NEXT:
- 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);
- } while (handle->captured_count < handle->capture_count);
-
- 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;
- camera_hal_handle *handle = (camera_hal_handle *)data;
-
- if (!handle) {
- LOGE("NULL handle for buffer handler");
- return NULL;
- }
-
- LOGD("enter");
-
- /* run buffer thread */
- g_mutex_lock(&handle->buffer_lock);
-
- while (handle->buffer_thread_run) {
- 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->buffer_lock);
- break;
- }
-
- g_mutex_lock(&handle->buffer_lock);
-
- if (handle->buffer_thread_run == FALSE) {
- LOGW("stop buffer handler thread");
- break;
- }
-
- if (__camera_v4l2_dqbuf(handle->device_fd, handle->buffer_type, V4L2_MEMORY_MMAP, &index) != CAMERA_ERROR_NONE) {
- LOGE("dqbuf failed");
- break;
- }
-
- handle->buffer_dequeued_count++;
-
- /*LOGD("dequeued buffer count %d", handle->buffer_dequeued_count);*/
-
- 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);
- } else {
- LOGW("preview callback is NULL");
- 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->buffer_lock);
- }
-
- g_mutex_unlock(&handle->buffer_lock);
-
- LOGD("leave");
-
- 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->msg_cb_lock);
-
- while (handle->msg_cb_run) {
- if (g_queue_is_empty(handle->msg_list)) {
- LOGD("wait for message");
- g_cond_wait(&handle->msg_cb_cond, &handle->msg_cb_lock);
- LOGD("message signal received");
- }
-
- if (!handle->msg_cb_run) {
- LOGW("break message thread");
- break;
- }
-
- message = g_queue_pop_head(handle->msg_list);
- if (!message) {
- LOGW("NULL message");
- continue;
- }
-
- g_mutex_unlock(&handle->msg_cb_lock);
-
- for (i = 0 ; i < MESSAGE_CALLBACK_MAX ; i++) {
- if (handle->msg_cb[i]) {
- LOGD("call message callback type %d", message->type);
- ((camera_message_cb)handle->msg_cb[i])(message, handle->msg_cb_data[i]);
- }
- }
-
- g_free(message);
- message = NULL;
-
- g_mutex_lock(&handle->msg_cb_lock);
- }
-
- g_mutex_unlock(&handle->msg_cb_lock);
-
- LOGD("leave - message thread");
-
- return NULL;
-}
-
-
-static void __camera_release_handle(camera_hal_handle *handle)
-{
- if (!handle) {
- LOGW("NULL handle");
- return;
- }
-
- 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->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);
- 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->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->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->msg_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 = (camera_hal_handle *)camera_handle;
-
- if (!handle) {
- LOGE("NULL handle");
- return CAMERA_ERROR_INVALID_PARAMETER;
- }
-
- 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 = (camera_hal_handle *)camera_handle;
-
- if (!handle) {
- LOGE("NULL handle");
- return CAMERA_ERROR_INVALID_PARAMETER;
- }
-
- 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 (g_device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE)
- handle->buffer_type = V4L2_CAP_VIDEO_CAPTURE_MPLANE;
- else
- 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->buffer_type);
-
-_OPEN_DEVICE_DONE:
- g_mutex_unlock(&handle->lock);
-
- return ret;
-}
-
-int camera_close_device(void *camera_handle)
-{
- camera_hal_handle *handle = (camera_hal_handle *)camera_handle;
-
- if (!handle) {
- LOGE("NULL handle");
- return CAMERA_ERROR_INVALID_PARAMETER;
- }
-
- 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 = (camera_hal_handle *)camera_handle;
-
- if (!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;
- }
-
- 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->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);
- 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 = (camera_hal_handle *)camera_handle;
-
- if (!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;
- }
-
- 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->msg_cb[cb_id]) {
- LOGD("remove message callback %p, user data %p - cb_id %u",
- handle->msg_cb[cb_id], handle->msg_cb_data[cb_id], cb_id);
-
- handle->msg_cb[cb_id] = NULL;
- handle->msg_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;
- camera_hal_handle *handle = (camera_hal_handle *)camera_handle;
- camera_device_info_t *device_info = NULL;
-
- if (!handle || !format) {
- LOGE("NULL param %p %p", handle, format);
- return CAMERA_ERROR_INVALID_PARAMETER;
- }
-
- if (!g_device_info_list) {
- LOGE("no device info list");
- return CAMERA_ERROR_INTERNAL;
- }
-
- g_mutex_lock(&handle->lock);
-
- 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;
- }
-
- /* 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;
- }
-
- /* 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;
- }
-
- LOGD("Preview setting is changed. Restart preview now.");
-
- /* 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;
- }
-
- /* 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;
- }
- }
-
-_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 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,
- format->capture_format,
- format->capture_resolution.width,
- format->capture_resolution.height,
- handle->capture_restart_stream);
-
- 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 = (camera_hal_handle *)camera_handle;
-
- if (!handle || !format) {
- LOGE("NULL param %p %p", handle, format);
- return CAMERA_ERROR_INVALID_PARAMETER;
- }
-
- 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 ret = 0;
- camera_hal_handle *handle = (camera_hal_handle *)camera_handle;
-
- if (!handle || !callback) {
- LOGE("NULL param %p %p", handle, callback);
- return CAMERA_ERROR_INVALID_PARAMETER;
- }
-
- 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;
- }
-
- 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->buffer_lock);
-
- handle->buffer_thread_run = TRUE;
-
- 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->buffer_lock);
-
- __camera_stop_stream(handle, handle->buffer_count);
-
- g_mutex_unlock(&handle->lock);
-
- return ret;
- }
-
- handle->preview_cb = callback;
- handle->preview_cb_data = user_data;
-
- g_mutex_unlock(&handle->buffer_lock);
-
- handle->state = CAMERA_STATE_PREVIEWING;
-
- LOGD("start preview done");
-
- g_mutex_unlock(&handle->lock);
-
- return CAMERA_ERROR_NONE;
-}
-
-int camera_release_preview_buffer(void *camera_handle, int buffer_index)
-{
- int ret = CAMERA_ERROR_NONE;
- camera_hal_handle *handle = (camera_hal_handle *)camera_handle;
-
- if (!handle) {
- LOGE("NULL handle");
- return CAMERA_ERROR_INVALID_PARAMETER;
- }
-
- 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,
- handle->buffer_type, V4L2_MEMORY_MMAP, buffer_index);
-
- g_mutex_lock(&handle->buffer_lock);
-
- if (ret == CAMERA_ERROR_NONE) {
- 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->buffer_cond);
-
- g_mutex_unlock(&handle->buffer_lock);
-
- return ret;
-}
-
-
-int camera_stop_preview(void *camera_handle)
-{
- int ret = CAMERA_ERROR_NONE;
- gint64 end_time;
- camera_hal_handle *handle = (camera_hal_handle *)camera_handle;
-
- if (!handle) {
- LOGE("NULL handle");
- return CAMERA_ERROR_INVALID_PARAMETER;
- }
-
- 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->buffer_lock);
-
- handle->buffer_thread_run = FALSE;
-
- 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->buffer_cond, &handle->buffer_lock, end_time)) {
- LOGE("buffer wait failed");
- break;
- } else {
- LOGD("signal received. check again...");
- }
- }
-
- g_mutex_unlock(&handle->buffer_lock);
-
- ret = __camera_stop_stream(handle, handle->buffer_count);
-
- /* wait for preview thread exit */
- g_thread_join(handle->buffer_thread);
- handle->buffer_thread = NULL;
-
- handle->state = CAMERA_STATE_OPENED;
-
- LOGD("stop preview done [0x%x]", ret);
-
- 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;
- }
-
- LOGE("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;
- }
-
- LOGE("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)
-{
- 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;
- }
-
- 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;
- }
-
- /* set callback and user data */
- handle->capture_cb = callback;
- handle->capture_cb_data = user_data;
-
- /* reset captured count */
- handle->captured_count = 0;
-
- LOGD("start capture - count %u", handle->capture_count);
-
- /* set capture request flag */
- handle->capture_request = TRUE;
-
- handle->state = CAMERA_STATE_CAPTURING;
-
- g_mutex_unlock(&handle->lock);
-
- return CAMERA_ERROR_NONE;
-}
-
-int camera_stop_capture(void *camera_handle)
-{
- camera_hal_handle *handle = (camera_hal_handle *)camera_handle;
-
- if (!handle) {
- LOGE("NULL handle");
- return CAMERA_ERROR_INVALID_PARAMETER;
- }
-
- g_mutex_lock(&handle->lock);
-
- 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)
-{
- if (!camera_handle || !format) {
- LOGE("NULL param %p %p", camera_handle, format);
- return CAMERA_ERROR_INVALID_PARAMETER;
- }
-
- LOGE("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 || !format) {
- LOGE("NULL param %p %p", camera_handle, format);
- return CAMERA_ERROR_INVALID_PARAMETER;
- }
-
- LOGE("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 || !callback) {
- LOGE("NULL param %p %p", camera_handle, callback);
- return CAMERA_ERROR_INVALID_PARAMETER;
- }
-
- LOGE("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;
- }
-
- LOGE("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;
- }
-
- LOGE("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)
-{
- int ret = CAMERA_ERROR_NONE;
- int cid = 0;
- int ctrl_ret = 0;
- int set_value = 0;
- camera_hal_handle *handle = (camera_hal_handle *)camera_handle;
-
- if (!handle || !value) {
- LOGE("NULL param %p %p", handle, value);
- return CAMERA_ERROR_INVALID_PARAMETER;
- }
-
- set_value = *(int *)value;
-
- g_mutex_lock(&handle->lock);
-
- if (handle->state < CAMERA_STATE_OPENED) {
- LOGE("invalid state %d", handle->state);
- ret = CAMERA_ERROR_INVALID_STATE;
- goto _SET_COMMAND_DONE;
- }
-
- LOGD("set command %"PRIx64" - state %d", command, handle->state);
-
- switch (command) {
- case CAMERA_COMMAND_BRIGHTNESS:
- 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;
- case CAMERA_COMMAND_PTZ_TYPE:
- if (set_value != CAMERA_PTZ_TYPE_ELECTRONIC) {
- LOGE("not supported PTZ type %d", set_value);
- ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
- }
- goto _SET_COMMAND_DONE;
- case CAMERA_COMMAND_PAN:
- cid = V4L2_CID_PAN_ABSOLUTE;
- break;
- case CAMERA_COMMAND_TILT:
- cid = V4L2_CID_TILT_ABSOLUTE;
- break;
- case CAMERA_COMMAND_FLIP:
- if (set_value != CAMERA_FLIP_NONE) {
- LOGE("NOT_SUPPORTED flip %d", set_value);
- ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
- }
- goto _SET_COMMAND_DONE;
- case CAMERA_COMMAND_CAPTURE_COUNT:
- handle->capture_count = set_value;
- LOGI("capture count %u", handle->capture_count);
- goto _SET_COMMAND_DONE;
- case CAMERA_COMMAND_CAPTURE_INTERVAL:
- handle->capture_interval_ms = set_value;
- LOGI("capture interval %u ms", handle->capture_interval_ms);
- goto _SET_COMMAND_DONE;
- default:
- LOGE("NOT_SUPPORTED command %"PRIx64, command);
- ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED;
- goto _SET_COMMAND_DONE;
- }
-
- ctrl_ret = __camera_v4l2_s_ctrl(handle->device_fd, cid, set_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;
- }
- }
-
-_SET_COMMAND_DONE:
- g_mutex_unlock(&handle->lock);
-
- 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 = (camera_hal_handle *)camera_handle;
-
- if (!handle || !value) {
- LOGE("NULL param %p %p", handle, value);
- return CAMERA_ERROR_INVALID_PARAMETER;
- }
-
- g_mutex_lock(&handle->lock);
-
- LOGD("get command %"PRId64" - state %d", command, handle->state);
-
- switch (command) {
- case CAMERA_COMMAND_BRIGHTNESS:
- 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 %"PRId64, 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 ret;
-}
-
-int camera_set_batch_command(void *camera_handle, camera_batch_command_control_t *batch_command, int64_t *error_command)
-{
- camera_hal_handle *handle = (camera_hal_handle *)camera_handle;
-
- if (!handle || !batch_command) {
- LOGE("NULL param %p %p", handle, batch_command);
- return CAMERA_ERROR_INVALID_PARAMETER;
- }
-
- g_mutex_lock(&handle->lock);
-
- LOGD("set batch command - flag %"PRIx64", state %d",
- batch_command->command_set_flag, handle->state);
-
- /* TODO: to be implemented */
-
- g_mutex_unlock(&handle->lock);
-
- return CAMERA_ERROR_NONE;
-}
+++ /dev/null
-/*
- * 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 <linux/videodev2.h>
-#include <glib.h>
-#include <tbm_bufmgr.h>
-#include <tizen-camera.h>
-
-#define CAMERA_HAL_INITIAL_INDEX -1
-#define CAMERA_HAL_INITIAL_FD -1
-#define MESSAGE_CALLBACK_MAX 10
-#define BUFFER_MAX 4
-#define V4L2_PLANES_MAX 4
-
-typedef struct _camera_hal_handle {
- /* tbm */
- tbm_bufmgr bufmgr;
-
- /* device */
- gint32 device_index;
- gint32 device_fd;
-
- /* buffer */
- guint32 buffer_dequeued_count;
- GThread *buffer_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;
-
- /* preview */
- camera_format_t preview_format;
- camera_preview_frame_cb preview_cb;
- gpointer preview_cb_data;
-
- /* capture */
- camera_capture_cb capture_cb;
- gpointer capture_cb_data;
- guint32 capture_count;
- guint32 capture_interval_ms;
- guint32 captured_count;
- gboolean capture_request;
- gboolean capture_restart_stream;
-
- /* 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;
-
- /* etc */
- GMutex lock;
- camera_state_t state;
-} camera_hal_handle;
-
-#endif /* __TIZEN_CAMERA_PRIVATE_H__ */