\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
+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 r;\r
}\r
\r
+typedef struct tagMaruCamConvertPixfmt {\r
+ uint32_t fmt; /* fourcc */\r
+} MaruCamConvertPixfmt;\r
+\r
+static MaruCamConvertPixfmt supported_dst_pixfmts[] = {\r
+ { V4L2_PIX_FMT_YUYV },\r
+ { V4L2_PIX_FMT_YUV420 },\r
+ { V4L2_PIX_FMT_YVU420 },\r
+};\r
+\r
+typedef struct tagMaruCamConvertFrameInfo {\r
+ uint32_t width;\r
+ uint32_t height;\r
+} MaruCamConvertFrameInfo;\r
+\r
+static MaruCamConvertFrameInfo supported_dst_frames[] = {\r
+ { 640, 480 },\r
+ { 352, 288 },\r
+ { 320, 240 },\r
+ { 176, 144 },\r
+ { 160, 120 },\r
+};\r
+\r
#define MARUCAM_CTRL_VALUE_MAX 20\r
#define MARUCAM_CTRL_VALUE_MIN 1\r
#define MARUCAM_CTRL_VALUE_MID 10\r
static struct marucam_qctrl qctrl_tbl[] = {\r
{ V4L2_CID_BRIGHTNESS, 0, },\r
{ V4L2_CID_CONTRAST, 0, },\r
- { V4L2_CID_SATURATION,0, },\r
+ { V4L2_CID_SATURATION, 0, },\r
{ V4L2_CID_SHARPNESS, 0, },\r
};\r
\r
for (i = 0; i < ARRAY_SIZE(qctrl_tbl); i++) {\r
if (qctrl_tbl[i].hit) {\r
struct v4l2_control ctrl = {0,};\r
+ qctrl_tbl[i].hit = 0;\r
ctrl.id = qctrl_tbl[i].id;\r
ctrl.value = qctrl_tbl[i].init_val;\r
if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) {\r
- ERR("failed to set video control value while reset values : %s\n", strerror(errno));\r
+ ERR("failed to reset control value : id(0x%x), errstr(%s)\n",\r
+ ctrl.id, strerror(errno));\r
}\r
}\r
}\r
return ret;\r
}\r
\r
+static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format,\r
+ uint32_t width, uint32_t height)\r
+{\r
+ struct v4l2_frmivalenum fival;\r
+ struct v4l2_streamparm sp;\r
+ uint32_t min_num = 0, min_denom = 0;\r
+\r
+ CLEAR(fival);\r
+ fival.pixel_format = pixel_format;\r
+ fival.width = width;\r
+ fival.height = height;\r
+\r
+ if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) < 0) {\r
+ ERR("Unable to enumerate intervals for pixelformat(0x%x), (%d:%d)\n",\r
+ pixel_format, width, height);\r
+ return;\r
+ }\r
+\r
+ if (fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {\r
+ float max_ival = -1.0;\r
+ do {\r
+ float cur_ival = (float)fival.discrete.numerator\r
+ / (float)fival.discrete.denominator;\r
+ if (cur_ival > max_ival) {\r
+ max_ival = cur_ival;\r
+ min_num = fival.discrete.numerator;\r
+ min_denom = fival.discrete.denominator;\r
+ }\r
+ TRACE("Discrete frame interval %u/%u supported\n",\r
+ fival.discrete.numerator, fival.discrete.denominator);\r
+ fival.index++;\r
+ } while (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) >= 0);\r
+ } else if ((fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) ||\r
+ (fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)) {\r
+ TRACE("Frame intervals from %u/%u to %u/%u supported",\r
+ fival.stepwise.min.numerator, fival.stepwise.min.denominator,\r
+ fival.stepwise.max.numerator, fival.stepwise.max.denominator);\r
+ if(fival.type == V4L2_FRMIVAL_TYPE_STEPWISE)\r
+ TRACE("with %u/%u step",\r
+ fival.stepwise.step.numerator, fival.stepwise.step.denominator);\r
+ if (((float)fival.stepwise.max.denominator /\r
+ (float)fival.stepwise.max.numerator) >\r
+ ((float)fival.stepwise.min.denominator /\r
+ (float)fival.stepwise.min.numerator)) {\r
+ min_num = fival.stepwise.max.numerator;\r
+ min_denom = fival.stepwise.max.denominator;\r
+ } else {\r
+ min_num = fival.stepwise.min.numerator;\r
+ min_denom = fival.stepwise.min.denominator;\r
+ }\r
+ }\r
+ TRACE("actual min values : %u/%u\n", min_num, min_denom);\r
+\r
+ CLEAR(sp);\r
+ sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
+ sp.parm.capture.timeperframe.numerator = min_num;\r
+ sp.parm.capture.timeperframe.denominator = min_denom;\r
+\r
+ if (xioctl(v4l2_fd, VIDIOC_S_PARM, &sp) < 0) {\r
+ ERR("Failed to set to minimum FPS(%u/%u)\n", min_num, min_denom);\r
+ }\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
- static uint32_t index = 0;\r
struct timeval tv;\r
void *buf;\r
int ret;\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
+ qemu_mutex_lock(&state->thread_mutex);\r
+ if (state->req_frame == 0) {\r
+ qemu_mutex_unlock(&state->thread_mutex);\r
+ return 0;\r
+ }\r
+ buf = state->vaddr + state->buf_size * (state->req_frame -1);\r
+ qemu_mutex_unlock(&state->thread_mutex);\r
\r
- buf = state->vaddr + (state->buf_size * index);\r
ret = v4l2_read(v4l2_fd, buf, state->buf_size);\r
if ( ret < 0) {\r
switch (errno) {\r
}\r
}\r
\r
- index = !index;\r
-\r
qemu_mutex_lock(&state->thread_mutex);\r
- if (state->streamon) {\r
- if (state->req_frame) {\r
- qemu_irq_raise(state->dev.irq[2]);\r
- state->req_frame = 0;\r
- }\r
+ if (ready_count < MARUCAM_SKIPFRAMES) {\r
+ ++ready_count; /* skip a frame cause first some frame are distorted */\r
+ qemu_mutex_unlock(&state->thread_mutex);\r
+ return 0;\r
+ }\r
+ if (state->streamon == _MC_THREAD_STREAMON) {\r
+ state->req_frame = 0; /* clear request */\r
+ state->isr |= 0x01; /* set a flag of rasing a interrupt */\r
+ qemu_bh_schedule(state->tx_bh);\r
ret = 1;\r
} else {\r
ret = -1;\r
}\r
qemu_mutex_unlock(&state->thread_mutex);\r
-\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
+ if (stat(dev_name, &st) < 0) {\r
+ INFO("<WARNING>Cannot identify '%s': %s\n", dev_name, strerror(errno));\r
+ } else {\r
+ if (!S_ISCHR(st.st_mode)) {\r
+ INFO("<WARNING>%s is no character device.\n", dev_name);\r
+ }\r
+ }\r
+\r
+ tmp_fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);\r
+ if (tmp_fd < 0) {\r
+ ERR("Camera device open failed.(%s)\n", dev_name);\r
+ return 0;\r
+ }\r
+ if (ioctl(tmp_fd, VIDIOC_QUERYCAP, &cap) < 0) {\r
+ ERR("Could not qeury video capabilities\n");\r
+ close(tmp_fd);\r
+ return 0;\r
+ }\r
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ||\r
+ !(cap.capabilities & V4L2_CAP_STREAMING)) {\r
+ ERR("Not supported video driver.\n");\r
+ close(tmp_fd);\r
+ return 0;\r
+ }\r
+\r
+ close(tmp_fd);\r
+ return 1;\r
}\r
\r
void marucam_device_init(MaruCamState* state)\r
QEMU_THREAD_JOINABLE);\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
+ struct timespec req;\r
+ req.tv_sec = 0;\r
+ req.tv_nsec = 10000000;\r
+\r
+ INFO("Starting preview!\n");\r
qemu_mutex_lock(&state->thread_mutex);\r
- state->streamon = 1;\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
+\r
+ /* nanosleep until thread is streamon */\r
+ while (!is_streamon(state))\r
+ nanosleep(&req, NULL);\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
{\r
- struct v4l2_streamparm sp;\r
MaruCamParam *param = state->param;\r
\r
param->top = 0;\r
- memset(&sp, 0, sizeof(struct v4l2_streamparm));\r
- sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
- sp.parm.capture.timeperframe.numerator = param->stack[0];\r
- sp.parm.capture.timeperframe.denominator = param->stack[1];\r
\r
- if (xioctl(v4l2_fd, VIDIOC_S_PARM, &sp) < 0) {\r
- ERR("failed to set FPS: %s\n", strerror(errno));\r
- param->errCode = errno;\r
+ /* If KVM enabled, We use default FPS of the webcam.\r
+ * If KVM disabled, we use mininum FPS of the webcam */\r
+ if (!kvm_enabled()) {\r
+ set_maxframeinterval(state, dst_fmt.fmt.pix.pixelformat,\r
+ dst_fmt.fmt.pix.width,\r
+ dst_fmt.fmt.pix.height);\r
}\r
}\r
\r
void marucam_device_g_param(MaruCamState* state)\r
{\r
- struct v4l2_streamparm sp;\r
MaruCamParam *param = state->param;\r
- \r
- param->top = 0;\r
- memset(&sp, 0, sizeof(struct v4l2_streamparm));\r
- sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
\r
- if (xioctl(v4l2_fd, VIDIOC_G_PARM, &sp) < 0) {\r
- ERR("failed to get FPS: %s\n", strerror(errno));\r
- param->errCode = errno;\r
- return;\r
- }\r
- param->stack[0] = sp.parm.capture.capability;\r
- param->stack[1] = sp.parm.capture.timeperframe.numerator;\r
- param->stack[2] = sp.parm.capture.timeperframe.denominator;\r
+ /* We use default FPS of the webcam\r
+ * return a fixed value on guest ini file (1/30).\r
+ */\r
+ param->top = 0;\r
+ param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */\r
+ param->stack[1] = 1; /* numerator */\r
+ param->stack[2] = 30; /* denominator */\r
}\r
\r
void marucam_device_s_fmt(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
dst_fmt.fmt.pix.field = param->stack[3];\r
\r
if (xioctl(v4l2_fd, VIDIOC_S_FMT, &dst_fmt) < 0) {\r
- ERR("failed to set video format: %s\n", strerror(errno));\r
+ ERR("failed to set video format: format(0x%x), width:height(%d:%d), "\r
+ "errstr(%s)\n", dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.width,\r
+ dst_fmt.fmt.pix.height, strerror(errno));\r
param->errCode = errno;\r
return;\r
}\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
format.fmt.pix.field = param->stack[3];\r
\r
if (xioctl(v4l2_fd, VIDIOC_TRY_FMT, &format) < 0) {\r
- ERR("failed to check video format: %s\n", strerror(errno));\r
+ ERR("failed to check video format: format(0x%x), width:height(%d:%d),"\r
+ " errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width,\r
+ format.fmt.pix.height, strerror(errno));\r
param->errCode = errno;\r
return;\r
}\r
\r
void marucam_device_enum_fmt(MaruCamState* state)\r
{\r
- struct v4l2_fmtdesc format;\r
+ uint32_t index;\r
MaruCamParam *param = state->param;\r
\r
param->top = 0;\r
- memset(&format, 0, sizeof(struct v4l2_fmtdesc));\r
- format.index = param->stack[0];\r
- format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
+ index = param->stack[0];\r
\r
- if (xioctl(v4l2_fd, VIDIOC_ENUM_FMT, &format) < 0) {\r
- if (errno != EINVAL)\r
- ERR("failed to enumerate video formats: %s\n", strerror(errno));\r
- param->errCode = errno;\r
+ if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {\r
+ param->errCode = EINVAL;\r
return;\r
}\r
- param->stack[0] = format.index;\r
- param->stack[1] = format.flags;\r
- param->stack[2] = format.pixelformat;\r
+ param->stack[1] = 0; /* flags = NONE */\r
+ param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */\r
/* set description */\r
- memcpy(¶m->stack[3], format.description, sizeof(format.description));\r
+ switch (supported_dst_pixfmts[index].fmt) {\r
+ case V4L2_PIX_FMT_YUYV:\r
+ memcpy(¶m->stack[3], "YUYV", 32);\r
+ break;\r
+ case V4L2_PIX_FMT_YUV420:\r
+ memcpy(¶m->stack[3], "YU12", 32);\r
+ break;\r
+ case V4L2_PIX_FMT_YVU420:\r
+ memcpy(¶m->stack[3], "YV12", 32);\r
+ break;\r
+ }\r
}\r
\r
void marucam_device_qctrl(MaruCamState* state)\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
sctrl.value = (ctrl.maximum + ctrl.minimum) / 2;\r
}\r
if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &sctrl) < 0) {\r
- ERR("failed to set video control value : %s\n", strerror(errno));\r
+ ERR("failed to set control value: id(0x%x), value(%d), "\r
+ "errstr(%s)\n", sctrl.id, sctrl.value, strerror(errno));\r
param->errCode = errno;\r
return;\r
}\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
ctrl.value = value_convert_from_guest(qctrl_tbl[i].min,\r
qctrl_tbl[i].max, param->stack[1]);\r
if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) {\r
- ERR("failed to set video control value : value(%d), %s\n", param->stack[1], strerror(errno));\r
+ ERR("failed to set control value : id0x%x), value(r:%d, c:%d), "\r
+ "errstr(%s)\n", ctrl.id, param->stack[1], ctrl.value,\r
+ strerror(errno));\r
param->errCode = errno;\r
return;\r
}\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
\r
void marucam_device_enum_fsizes(MaruCamState* state)\r
{\r
- struct v4l2_frmsizeenum fsize;\r
+ uint32_t index, pixfmt, i;\r
MaruCamParam *param = state->param;\r
\r
param->top = 0;\r
- memset(&fsize, 0, sizeof(struct v4l2_frmsizeenum));\r
- fsize.index = param->stack[0];\r
- fsize.pixel_format = param->stack[1];\r
+ index = param->stack[0];\r
+ pixfmt = param->stack[1];\r
\r
- if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMESIZES, &fsize) < 0) {\r
- if (errno != EINVAL)\r
- ERR("failed to get frame sizes : %s\n", strerror(errno));\r
- param->errCode = errno;\r
+ if (index >= ARRAY_SIZE(supported_dst_frames)) {\r
+ param->errCode = EINVAL;\r
return;\r
}\r
+ for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {\r
+ if (supported_dst_pixfmts[i].fmt == pixfmt)\r
+ break;\r
+ }\r
\r
- if (fsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {\r
- param->stack[0] = fsize.discrete.width;\r
- param->stack[1] = fsize.discrete.height;\r
- } else {\r
+ if (i == ARRAY_SIZE(supported_dst_pixfmts)) {\r
param->errCode = EINVAL;\r
- ERR("Not Supported mode, we only support DISCRETE\n");\r
+ return;\r
}\r
+\r
+ param->stack[0] = supported_dst_frames[index].width;\r
+ param->stack[1] = supported_dst_frames[index].height;\r
}\r
\r
void marucam_device_enum_fintv(MaruCamState* state)\r
{\r
- struct v4l2_frmivalenum ival;\r
MaruCamParam *param = state->param;\r
\r
param->top = 0;\r
- memset(&ival, 0, sizeof(struct v4l2_frmivalenum));\r
- ival.index = param->stack[0];\r
- ival.pixel_format = param->stack[1];\r
- ival.width = param->stack[2];\r
- ival.height = param->stack[3];\r
-\r
- if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0) {\r
- if (errno != EINVAL)\r
- ERR("failed to get frame intervals : %s\n", strerror(errno));\r
- param->errCode = errno;\r
- return;\r
- }\r
\r
- if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {\r
- param->stack[0] = ival.discrete.numerator;\r
- param->stack[1] = ival.discrete.denominator;\r
- } else {\r
+ /* switch by index(param->stack[0]) */\r
+ switch (param->stack[0]) {\r
+ case 0:\r
+ /* we only use 1/30 frame interval */\r
+ param->stack[1] = 30; /* denominator */\r
+ break;\r
+ default:\r
param->errCode = EINVAL;\r
- ERR("Not Supported mode, we only support DISCRETE\n");\r
+ return;\r
}\r
+ param->stack[0] = 1; /* numerator */\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