\r
#include <linux/videodev2.h>\r
\r
+#include <sys/stat.h>\r
+#include <sys/ioctl.h>\r
+\r
#include <libv4l2.h>\r
#include <libv4lconvert.h>\r
\r
MULTI_DEBUG_CHANNEL(tizen, camera_linux);\r
\r
+#define MARUCAM_SKIPFRAMES 2\r
+\r
+enum {\r
+ _MC_THREAD_PAUSED,\r
+ _MC_THREAD_STREAMON,\r
+ _MC_THREAD_STREAMOFF,\r
+};\r
+\r
+static const char *dev_name = "/dev/video0";\r
static int v4l2_fd;\r
static int convert_trial;\r
static int ready_count;\r
\r
static struct v4l2_format dst_fmt;\r
\r
+#define CLEAR(x) memset(&(x), 0, sizeof(x))\r
+\r
static int xioctl(int fd, int req, void *arg)\r
{\r
int r;\r
return ret;\r
}\r
\r
+static int is_streamon(MaruCamState *state)\r
+{\r
+ int st;\r
+ qemu_mutex_lock(&state->thread_mutex);\r
+ st = state->streamon;\r
+ qemu_mutex_unlock(&state->thread_mutex);\r
+ return (st == _MC_THREAD_STREAMON);\r
+}\r
+\r
+static int is_stream_paused(MaruCamState *state)\r
+{\r
+ int st;\r
+ qemu_mutex_lock(&state->thread_mutex);\r
+ st = state->streamon;\r
+ qemu_mutex_unlock(&state->thread_mutex);\r
+ return (st == _MC_THREAD_PAUSED);\r
+}\r
+\r
static int __v4l2_grab(MaruCamState *state)\r
{\r
fd_set fds;\r
FD_ZERO(&fds);\r
FD_SET(v4l2_fd, &fds);\r
\r
- tv.tv_sec = 2;\r
- tv.tv_usec = 0;\r
+ tv.tv_sec = 0;\r
+ tv.tv_usec = 500000;\r
\r
ret = select(v4l2_fd + 1, &fds, NULL, NULL, &tv);\r
if ( ret < 0) {\r
return -1;\r
}\r
\r
- qemu_mutex_lock(&state->thread_mutex);\r
- ret = state->streamon;\r
- qemu_mutex_unlock(&state->thread_mutex);\r
- if (!ret)\r
- return -1;\r
+ if (!is_streamon(state))\r
+ return -1;\r
\r
buf = state->vaddr + (state->buf_size * index);\r
ret = v4l2_read(v4l2_fd, buf, state->buf_size);\r
index = !index;\r
\r
qemu_mutex_lock(&state->thread_mutex);\r
- if (state->streamon) {\r
- if (ready_count >= 4) {\r
+ if (state->streamon == _MC_THREAD_STREAMON) {\r
+ if (ready_count >= MARUCAM_SKIPFRAMES) {\r
if (state->req_frame) {\r
state->req_frame = 0; // clear request\r
state->isr |= 0x01; // set a flag of rasing a interrupt.\r
return ret;\r
}\r
\r
-// Worker thread\r
+/* Worker thread */\r
static void *marucam_worker_thread(void *thread_param)\r
{\r
MaruCamState *state = (MaruCamState*)thread_param;\r
\r
wait_worker_thread:\r
qemu_mutex_lock(&state->thread_mutex);\r
- state->streamon = 0;\r
- convert_trial = 10;\r
+ state->streamon = _MC_THREAD_PAUSED;\r
qemu_cond_wait(&state->thread_cond, &state->thread_mutex);\r
qemu_mutex_unlock(&state->thread_mutex);\r
+\r
+ convert_trial = 10;\r
+ ready_count = 0;\r
+ qemu_mutex_lock(&state->thread_mutex);\r
+ state->buf_size = dst_fmt.fmt.pix.sizeimage;\r
+ state->streamon = _MC_THREAD_STREAMON;\r
+ qemu_mutex_unlock(&state->thread_mutex);\r
INFO("Streaming on ......\n");\r
\r
while (1)\r
{\r
- qemu_mutex_lock(&state->thread_mutex);\r
- if (state->streamon) {\r
- qemu_mutex_unlock(&state->thread_mutex);\r
+ if (is_streamon(state)) {\r
if (__v4l2_grab(state) < 0) {\r
INFO("...... Streaming off\n");\r
goto wait_worker_thread;\r
}\r
} else {\r
- qemu_mutex_unlock(&state->thread_mutex);\r
INFO("...... Streaming off\n");\r
goto wait_worker_thread;\r
}\r
}\r
- qemu_thread_exit((void*)0);\r
+ return NULL;\r
}\r
\r
int marucam_device_check(void)\r
{\r
int tmp_fd;\r
+ struct stat st;\r
struct v4l2_capability cap;\r
\r
- tmp_fd = open("/dev/video0", O_RDWR);\r
+ if (stat(dev_name, &st) < 0) {\r
+ ERR("Cannot identify '%s': %s\n", dev_name, strerror(errno));\r
+ return 0;\r
+ }\r
+\r
+ if (!S_ISCHR(st.st_mode)) {\r
+ ERR("%s is no device.\n", dev_name);\r
+ return 0;\r
+ }\r
+\r
+ tmp_fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);\r
if (tmp_fd < 0) {\r
- ERR("camera device open failed.(/dev/video0)\n");\r
+ ERR("camera device open failed.(%s)\n", dev_name);\r
return 0;\r
}\r
if (ioctl(tmp_fd, VIDIOC_QUERYCAP, &cap) < 0) {\r
qemu_thread_create(&state->thread_id, marucam_worker_thread, (void*)state);\r
}\r
\r
-// MARUCAM_CMD_OPEN\r
void marucam_device_open(MaruCamState* state)\r
{\r
- struct v4l2_capability cap;\r
MaruCamParam *param = state->param;\r
\r
param->top = 0;\r
- v4l2_fd = v4l2_open("/dev/video0", O_RDWR);\r
+ v4l2_fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);\r
if (v4l2_fd < 0) {\r
- ERR("v4l2 device open failed.(/dev/video0)\n");\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
- if (xioctl(v4l2_fd, VIDIOC_QUERYCAP, &cap) < 0) {\r
- ERR("Could not qeury video capabilities\n");\r
- v4l2_close(v4l2_fd);\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
- if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ||\r
- !(cap.capabilities & V4L2_CAP_STREAMING)) {\r
- ERR("Not supported video driver.\n");\r
- v4l2_close(v4l2_fd);\r
+ ERR("v4l2 device open failed.(%s)\n", dev_name);\r
param->errCode = EINVAL;\r
return;\r
}\r
\r
- memset(&dst_fmt, 0, sizeof(dst_fmt));\r
+ CLEAR(dst_fmt);\r
INFO("Opened\n");\r
}\r
\r
-// MARUCAM_CMD_START_PREVIEW\r
void marucam_device_start_preview(MaruCamState* state)\r
{\r
qemu_mutex_lock(&state->thread_mutex);\r
- state->streamon = 1;\r
- ready_count = 0;\r
- state->buf_size = dst_fmt.fmt.pix.sizeimage;\r
qemu_cond_signal(&state->thread_cond);\r
qemu_mutex_unlock(&state->thread_mutex);\r
- INFO("Starting preview!\n");\r
+ INFO("Starting preview!\n");\r
}\r
\r
-// MARUCAM_CMD_STOP_PREVIEW\r
void marucam_device_stop_preview(MaruCamState* state)\r
{\r
- struct timespec req;\r
- req.tv_sec = 0;\r
- req.tv_nsec = 333333333;\r
+ struct timespec req;\r
+ req.tv_sec = 0;\r
+ req.tv_nsec = 50000000;\r
\r
qemu_mutex_lock(&state->thread_mutex);\r
- state->streamon = 0;\r
+ state->streamon = _MC_THREAD_STREAMOFF;\r
state->buf_size = 0;\r
qemu_mutex_unlock(&state->thread_mutex);\r
- nanosleep(&req, NULL);\r
- INFO("Stopping preview!\n");\r
+\r
+ /* nanosleep until thread is paused */\r
+ while (!is_stream_paused(state))\r
+ nanosleep(&req, NULL);\r
+\r
+ INFO("Stopping preview!\n");\r
}\r
\r
void marucam_device_s_param(MaruCamState* state)\r
MaruCamParam *param = state->param;\r
\r
param->top = 0;\r
- memset(&dst_fmt, 0, sizeof(struct v4l2_format));\r
+ CLEAR(dst_fmt);\r
dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
dst_fmt.fmt.pix.width = param->stack[0];\r
dst_fmt.fmt.pix.height = param->stack[1];\r
MaruCamParam *param = state->param;\r
\r
param->top = 0;\r
- memset(&format, 0, sizeof(struct v4l2_format));\r
+ CLEAR(format);\r
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
\r
if (xioctl(v4l2_fd, VIDIOC_G_FMT, &format) < 0) {\r
MaruCamParam *param = state->param;\r
\r
param->top = 0;\r
- memset(&format, 0, sizeof(struct v4l2_format));\r
+ CLEAR(format);\r
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
format.fmt.pix.width = param->stack[0];\r
format.fmt.pix.height = param->stack[1];\r
MaruCamParam *param = state->param;\r
\r
param->top = 0;\r
- memset(&format, 0, sizeof(struct v4l2_fmtdesc));\r
+ CLEAR(format);\r
format.index = param->stack[0];\r
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
\r
MaruCamParam *param = state->param;\r
\r
param->top = 0;\r
- memset(&ctrl, 0, sizeof(struct v4l2_queryctrl));\r
+ CLEAR(ctrl);\r
ctrl.id = param->stack[0];\r
\r
switch (ctrl.id) {\r
return;\r
} else {\r
struct v4l2_control sctrl;\r
- memset(&sctrl, 0, sizeof(struct v4l2_control));\r
+ CLEAR(sctrl);\r
sctrl.id = ctrl.id;\r
if ((ctrl.maximum + ctrl.minimum) == 0) {\r
sctrl.value = 0;\r
MaruCamParam *param = state->param;\r
\r
param->top = 0;\r
- memset(&ctrl, 0, sizeof(struct v4l2_control));\r
+ CLEAR(ctrl);\r
ctrl.id = param->stack[0];\r
\r
switch (ctrl.id) {\r
MaruCamParam *param = state->param;\r
\r
param->top = 0;\r
- memset(&ctrl, 0, sizeof(struct v4l2_control));\r
+ CLEAR(ctrl);\r
ctrl.id = param->stack[0];\r
\r
switch (ctrl.id) {\r
MaruCamParam *param = state->param;\r
\r
param->top = 0;\r
- memset(&fsize, 0, sizeof(struct v4l2_frmsizeenum));\r
+ CLEAR(fsize);\r
fsize.index = param->stack[0];\r
fsize.pixel_format = param->stack[1];\r
\r
MaruCamParam *param = state->param;\r
\r
param->top = 0;\r
- memset(&ival, 0, sizeof(struct v4l2_frmivalenum));\r
+ CLEAR(ival);\r
ival.index = param->stack[0];\r
ival.pixel_format = param->stack[1];\r
ival.width = param->stack[2];\r
}\r
}\r
\r
-// MARUCAM_CMD_CLOSE\r
void marucam_device_close(MaruCamState* state)\r
{\r
- uint32_t is_streamon;\r
-\r
- qemu_mutex_lock(&state->thread_mutex);\r
- is_streamon = state->streamon;\r
- qemu_mutex_unlock(&state->thread_mutex);\r
-\r
- if (is_streamon)\r
- marucam_device_stop_preview(state);\r
+ if (!is_stream_paused(state))\r
+ marucam_device_stop_preview(state);\r
\r
marucam_reset_controls();\r
\r
v4l2_close(v4l2_fd);\r
- v4l2_fd = 0;\r
+ v4l2_fd = -1;\r
INFO("Closed\n");\r
}\r