MULTI_DEBUG_CHANNEL(tizen, camera);
-#define MARUCAM_THREAD_NAME "marucam_worker_thread"
+#define MAKE_BACKEND_V4L2(state) \
+ MCBackendV4l2 *backend = (MCBackendV4l2 *)(state->backend)
#define CLEAR(x) memset(&(x), 0, sizeof(x))
#define MARUCAM_DEFAULT_BUFFER_COUNT 4
-#define MARUCAM_CTRL_VALUE_MAX 20
-#define MARUCAM_CTRL_VALUE_MIN 1
-#define MARUCAM_CTRL_VALUE_MID 10
-#define MARUCAM_CTRL_VALUE_STEP 1
+struct MCFormat {
+ uint32_t fmt; /* fourcc */
+};
+
+static struct MCFormat support_fmts[] = {
+ { V4L2_PIX_FMT_YUYV },
+ { V4L2_PIX_FMT_YUV420 },
+ { V4L2_PIX_FMT_YVU420 },
+};
+
+struct MCFrame {
+ uint32_t width;
+ uint32_t height;
+};
+
+static struct MCFrame support_frames[] = {
+ { 640, 480 },
+ { 352, 288 },
+ { 320, 240 },
+ { 176, 144 },
+ { 160, 120 },
+};
+
+struct MCControls {
+ uint32_t id;
+ uint32_t hit;
+ int32_t min;
+ int32_t max;
+ int32_t step;
+ int32_t init_val;
+};
-enum {
- _MC_THREAD_PAUSED,
- _MC_THREAD_STREAMON,
- _MC_THREAD_STREAMOFF,
+static struct MCControls ctrl_tbl[] = {
+ { V4L2_CID_BRIGHTNESS, 0, },
+ { V4L2_CID_CONTRAST, 0, },
+ { V4L2_CID_SATURATION, 0, },
+ { V4L2_CID_SHARPNESS, 0, },
};
-typedef struct marucam_framebuffer {
+typedef struct MCBuffer {
void *data;
size_t size;
-} marucam_framebuffer;
+} MCBuffer;
-struct marucam_saved_frame {
+struct MCStoredFrame {
void *data;
uint32_t pixelformat;
uint32_t width;
uint32_t size;
};
-static struct marucam_saved_frame saved_frame;
-static char has_success_frame;
-static int n_framebuffer;
-static int previous_frame_index = -1;
-static struct marucam_framebuffer *framebuffer;
+typedef struct MCBackendV4l2 {
+ MaruCamBackend base;
+
+ char *dev_name;
+ int fd;
+ int convert_trial;
+ int ready_count;
+ int timeout;
+ int has_success;
+ int prev_index;
+ int fb_num;
-static const char *dev_name = "/dev/video0";
-static int v4l2_fd;
-static int convert_trial;
-static int ready_count;
-static int timeout_n;
+ struct v4l2_format src_fmt;
+ struct v4l2_format dst_fmt;
-static struct v4l2_format dst_fmt;
+ struct MCStoredFrame stored;
+ struct MCBuffer *fbs;
+} MCBackendV4l2;
static void ScalePlaneSimple(int src_width, int src_height,
int dst_width, int dst_height,
return r;
}
-typedef struct tagMaruCamConvertPixfmt {
- uint32_t fmt; /* fourcc */
-} MaruCamConvertPixfmt;
-
-static MaruCamConvertPixfmt supported_dst_pixfmts[] = {
- { V4L2_PIX_FMT_YUYV },
- { V4L2_PIX_FMT_YUV420 },
- { V4L2_PIX_FMT_YVU420 },
-};
-
-typedef struct tagMaruCamConvertFrameInfo {
- uint32_t width;
- uint32_t height;
-} MaruCamConvertFrameInfo;
-
-static MaruCamConvertFrameInfo supported_dst_frames[] = {
- { 640, 480 },
- { 352, 288 },
- { 320, 240 },
- { 176, 144 },
- { 160, 120 },
-};
-
-struct marucam_qctrl {
- uint32_t id;
- uint32_t hit;
- int32_t min;
- int32_t max;
- int32_t step;
- int32_t init_val;
-};
-
-static struct marucam_qctrl qctrl_tbl[] = {
- { V4L2_CID_BRIGHTNESS, 0, },
- { V4L2_CID_CONTRAST, 0, },
- { V4L2_CID_SATURATION, 0, },
- { V4L2_CID_SHARPNESS, 0, },
-};
-
-static void marucam_reset_controls(void)
+static void backend_v4l2_reset_controls(MCBackendV4l2 *backend)
{
uint32_t i;
- for (i = 0; i < ARRAY_SIZE(qctrl_tbl); i++) {
- if (qctrl_tbl[i].hit) {
+ for (i = 0; i < ARRAY_SIZE(ctrl_tbl); i++) {
+ if (ctrl_tbl[i].hit) {
struct v4l2_control ctrl = {0,};
- ctrl.id = qctrl_tbl[i].id;
- ctrl.value = qctrl_tbl[i].init_val;
- qctrl_tbl[i].hit = qctrl_tbl[i].init_val = 0;
- qctrl_tbl[i].min = qctrl_tbl[i].max = qctrl_tbl[i].step = 0;
- if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) {
+ ctrl.id = ctrl_tbl[i].id;
+ ctrl.value = ctrl_tbl[i].init_val;
+ ctrl_tbl[i].hit = ctrl_tbl[i].init_val = 0;
+ ctrl_tbl[i].min = ctrl_tbl[i].max = ctrl_tbl[i].step = 0;
+ if (xioctl(backend->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
ERR("Failed to reset control value: id(0x%x), errstr(%s)\n",
ctrl.id, strerror(errno));
}
return ret;
}
-static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format,
+static void set_maxframeinterval(int fd, uint32_t pixel_format,
uint32_t width, uint32_t height)
{
struct v4l2_frmivalenum fival;
fival.width = width;
fival.height = height;
- if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) < 0) {
+ if (xioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) < 0) {
ERR("Unable to enumerate intervals for pixelformat(0x%x), (%d:%d)\n",
pixel_format, width, height);
return;
TRACE("Discrete frame interval %u/%u supported\n",
fival.discrete.numerator, fival.discrete.denominator);
fival.index++;
- } while (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) >= 0);
+ } while (xioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) >= 0);
} else if ((fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) ||
(fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)) {
TRACE("Frame intervals from %u/%u to %u/%u supported",
sp.parm.capture.timeperframe.numerator = min_num;
sp.parm.capture.timeperframe.denominator = min_denom;
- if (xioctl(v4l2_fd, VIDIOC_S_PARM, &sp) < 0) {
+ if (xioctl(fd, VIDIOC_S_PARM, &sp) < 0) {
ERR("Failed to set to minimum FPS(%u/%u)\n", min_num, min_denom);
}
}
-static uint32_t stop_capturing(void)
+static uint32_t stop_capturing(MCBackendV4l2 *backend)
{
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (xioctl(v4l2_fd, VIDIOC_STREAMOFF, &type) < 0) {
+ if (xioctl(backend->fd, VIDIOC_STREAMOFF, &type) < 0) {
ERR("Failed to ioctl() with VIDIOC_STREAMOFF: %s\n", strerror(errno));
return errno;
}
return 0;
}
-static uint32_t start_capturing(void)
+static uint32_t start_capturing(MCBackendV4l2 *backend)
{
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (xioctl(v4l2_fd, VIDIOC_STREAMON, &type) < 0) {
+ if (xioctl(backend->fd, VIDIOC_STREAMON, &type) < 0) {
ERR("Failed to ioctl() with VIDIOC_STREAMON: %s\n", strerror(errno));
return errno;
}
return 0;
}
-static void free_framebuffers(marucam_framebuffer *fb, int buf_num)
+static void backend_v4l2_storedframe_clear(MCBackendV4l2 *backend)
+{
+ if (backend->stored.data) {
+ g_free(backend->stored.data);
+ backend->stored.data = NULL;
+ }
+ memset(&backend->stored, 0x00, sizeof(struct MCStoredFrame));
+}
+
+static void backend_v4l2_storedframe_set(MCBackendV4l2 *backend)
+{
+ backend->stored.width = backend->dst_fmt.fmt.pix.width;
+ backend->stored.height = backend->dst_fmt.fmt.pix.height;
+ backend->stored.pixelformat = backend->dst_fmt.fmt.pix.pixelformat;
+ backend->stored.size = backend->dst_fmt.fmt.pix.sizeimage;
+ if (backend->stored.data) {
+ g_free(backend->stored.data);
+ backend->stored.data = NULL;
+ }
+ backend->stored.data = (void *)g_malloc0(backend->stored.size);
+ memcpy(backend->stored.data,
+ backend->fbs[backend->prev_index].data,
+ backend->stored.size);
+ TRACE("Saves a frame data\n");
+}
+
+static void free_framebuffers(MCBackendV4l2 *backend)
{
int i;
- if (fb == NULL) {
+ if (backend->fbs == NULL) {
ERR("The framebuffer is NULL. Failed to release the framebuffer\n");
return;
- } else if (buf_num == 0) {
+ } else if (backend->fb_num == 0) {
ERR("The buffer count is 0. Failed to release the framebuffer\n");
return;
} else {
- TRACE("[%s]:fb(0x%p), buf_num(%d)\n", __func__, fb, buf_num);
+ TRACE("[%s]: fbs(0x%p), buf_num(%d)\n",
+ __func__, backend->fbs, backend->fb_num);
}
/* Unmap framebuffers. */
- for (i = 0; i < buf_num; i++) {
- if (fb[i].data != NULL) {
- v4l2_munmap(fb[i].data, fb[i].size);
- fb[i].data = NULL;
- fb[i].size = 0;
+ for (i = 0; i < backend->fb_num; i++) {
+ if (backend->fbs[i].data != NULL) {
+ v4l2_munmap(backend->fbs[i].data, backend->fbs[i].size);
+ backend->fbs[i].data = NULL;
+ backend->fbs[i].size = 0;
} else {
ERR("framebuffer[%d].data is NULL.\n", i);
}
}
- previous_frame_index = -1;
+ backend->prev_index = -1;
+ g_free(backend->fbs);
+ backend->fbs = NULL;
+ backend->fb_num = 0;
}
static uint32_t
-mmap_framebuffers(marucam_framebuffer **fb, int *buf_num)
+mmap_framebuffers(MCBackendV4l2 *backend)
{
struct v4l2_requestbuffers req;
+ MCBuffer **fb = &backend->fbs;
+ int *buf_num = &backend->fb_num;
CLEAR(req);
req.count = MARUCAM_DEFAULT_BUFFER_COUNT;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
- if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &req) < 0) {
+ if (xioctl(backend->fd, VIDIOC_REQBUFS, &req) < 0) {
if (errno == EINVAL) {
ERR("%s does not support memory mapping: %s\n",
- dev_name, strerror(errno));
+ backend->dev_name, strerror(errno));
} else {
ERR("Failed to request bufs: %s\n", strerror(errno));
}
return errno;
}
if (req.count == 0) {
- ERR("Insufficient buffer memory on %s\n", dev_name);
+ ERR("Insufficient buffer memory on %s\n", backend->dev_name);
return EINVAL;
}
- *fb = g_new0(marucam_framebuffer, req.count);
+ *fb = g_new0(MCBuffer, req.count);
if (*fb == NULL) {
ERR("Not enough memory to allocate framebuffers\n");
return ENOMEM;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = *buf_num;
- if (xioctl(v4l2_fd, VIDIOC_QUERYBUF, &buf) < 0) {
+ if (xioctl(backend->fd, VIDIOC_QUERYBUF, &buf) < 0) {
ERR("Failed to ioctl() with VIDIOC_QUERYBUF: %s\n",
strerror(errno));
return errno;
buf.length,
PROT_READ | PROT_WRITE,
MAP_SHARED,
- v4l2_fd, buf.m.offset);
+ backend->fd, buf.m.offset);
if (MAP_FAILED == (*fb)[*buf_num].data) {
ERR("Failed to mmap: %s\n", strerror(errno));
return errno;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = *buf_num;
- if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) {
+ if (xioctl(backend->fd, VIDIOC_QBUF, &buf) < 0) {
ERR("Failed to ioctl() with VIDIOC_QBUF: %s\n", strerror(errno));
return errno;
}
/* TODO: add other pixel format method */
static void __raise_dummy_intr(MaruCamState *state)
{
+ MAKE_BACKEND_V4L2(state);
void *buf = NULL;
+
qemu_mutex_lock(&state->thread_mutex);
if (state->streamon == _MC_THREAD_STREAMON && state->req_frame) {
- buf = state->vaddr + state->buf_size * (state->req_frame - 1);
- if (saved_frame.data) {
- if (saved_frame.width == dst_fmt.fmt.pix.width &&
- saved_frame.height == dst_fmt.fmt.pix.height) {
+ buf = state->fb_ptr + state->buf_size * (state->req_frame - 1);
+ if (backend->stored.data) {
+ if (backend->stored.width == backend->dst_fmt.fmt.pix.width &&
+ backend->stored.height == backend->dst_fmt.fmt.pix.height) {
TRACE("Copies the previuos frame\n");
- memcpy(buf, saved_frame.data, state->buf_size);
+ memcpy(buf, backend->stored.data, state->buf_size);
} else {
TRACE("Resizes the previous frame\n");
- marucam_scale_yuv420(saved_frame.data, saved_frame.width,
- saved_frame.height,
- buf, dst_fmt.fmt.pix.width,
- dst_fmt.fmt.pix.height);
+ marucam_scale_yuv420(backend->stored.data,
+ backend->stored.width,
+ backend->stored.height,
+ buf,
+ backend->dst_fmt.fmt.pix.width,
+ backend->dst_fmt.fmt.pix.height);
}
} else {
TRACE("Sends a black frame\n");
make_yu12_black(buf,
- dst_fmt.fmt.pix.width,
- dst_fmt.fmt.pix.height);
+ backend->dst_fmt.fmt.pix.width,
+ backend->dst_fmt.fmt.pix.height);
}
state->req_frame = 0; /* clear request */
state->isr |= 0x01; /* set a flag of raising a interrupt */
static void
notify_buffer_ready(MaruCamState *state, uint32_t buf_index)
{
+ MAKE_BACKEND_V4L2(state);
void *buf = NULL;
qemu_mutex_lock(&state->thread_mutex);
if (state->streamon == _MC_THREAD_STREAMON) {
- if (ready_count < MARUCAM_SKIPFRAMES) {
+ if (backend->ready_count < MARUCAM_SKIPFRAMES) {
/* skip a frame cause first some frame are distorted */
- ++ready_count;
- TRACE("Skip %d frame\n", ready_count);
+ ++backend->ready_count;
+ TRACE("Skip %d frame\n", backend->ready_count);
qemu_mutex_unlock(&state->thread_mutex);
return;
}
qemu_mutex_unlock(&state->thread_mutex);
return;
}
- buf = state->vaddr + state->buf_size * (state->req_frame - 1);
- memcpy(buf, framebuffer[buf_index].data, state->buf_size);
- previous_frame_index = buf_index;
- has_success_frame = 1;
+ buf = state->fb_ptr + state->buf_size * (state->req_frame - 1);
+ memcpy(buf, backend->fbs[buf_index].data, state->buf_size);
+ backend->prev_index = buf_index;
+ backend->has_success = 1;
state->req_frame = 0; /* clear request */
state->isr |= 0x01; /* set a flag of rasing a interrupt */
qemu_bh_schedule(state->tx_bh);
static int read_frame(MaruCamState *state)
{
+ MAKE_BACKEND_V4L2(state);
struct v4l2_buffer buf;
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
- if (xioctl(v4l2_fd, VIDIOC_DQBUF, &buf) < 0) {
+ if (xioctl(backend->fd, VIDIOC_DQBUF, &buf) < 0) {
switch (errno) {
case EAGAIN:
case EINTR:
return 0;
case EIO:
ERR("The v4l2_read() met the EIO\n");
- if (convert_trial-- == -1) {
+ if (backend->convert_trial-- == -1) {
ERR("Try count for v4l2_read is exceeded: %s\n",
strerror(errno));
return -1;
notify_buffer_ready(state, buf.index);
- if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) {
+ if (xioctl(backend->fd, VIDIOC_QBUF, &buf) < 0) {
ERR("QBUF error: %s\n", strerror(errno));
return -1;
}
static int __v4l2_streaming(MaruCamState *state)
{
+ MAKE_BACKEND_V4L2(state);
fd_set fds;
struct timeval tv;
int ret;
FD_ZERO(&fds);
- FD_SET(v4l2_fd, &fds);
+ FD_SET(backend->fd, &fds);
tv.tv_sec = 1;
tv.tv_usec = 0;
- ret = select(v4l2_fd + 1, &fds, NULL, NULL, &tv);
+ ret = select(backend->fd + 1, &fds, NULL, NULL, &tv);
if (ret < 0) {
if (errno == EAGAIN || errno == EINTR) {
ERR("Select again: %s\n", strerror(errno));
__raise_err_intr(state);
return -1;
} else if (!ret) {
- timeout_n++;
- ERR("Select timed out: count(%u)\n", timeout_n);
- if (ready_count <= MARUCAM_SKIPFRAMES) {
- switch (timeout_n) {
+ backend->timeout++;
+ ERR("Select timed out: count(%u)\n", backend->timeout);
+ if (backend->ready_count <= MARUCAM_SKIPFRAMES) {
+ switch (backend->timeout) {
case 1:
ERR("Waiting for reading a frame data\n");
return 0;
return -1;
}
}
- if (timeout_n >= 5) {
+ if (backend->timeout >= 5) {
ERR("Webcam is busy, failed to a read frame. Raises an error\n");
__raise_err_intr(state);
return -1;
}
- if (previous_frame_index != -1) {
+ if (backend->prev_index != -1) {
ERR("Sends previous frame data\n");
- notify_buffer_ready(state, previous_frame_index);
+ notify_buffer_ready(state, backend->prev_index);
}
return 0;
}
- if (!v4l2_fd || (v4l2_fd == -1)) {
+ if (!backend->fd || (backend->fd == -1)) {
ERR("The file descriptor is closed or not opened\n");
__raise_err_intr(state);
return -1;
}
/* clear the skip count for select time-out */
- if (timeout_n > 0) {
- timeout_n = 0;
+ if (backend->timeout > 0) {
+ backend->timeout = 0;
}
return 0;
static void *marucam_worker_thread(void *thread_param)
{
MaruCamState *state = (MaruCamState *)thread_param;
+ MAKE_BACKEND_V4L2(state);
while (1) {
qemu_mutex_lock(&state->thread_mutex);
break;
}
- convert_trial = 10;
- ready_count = 0;
- timeout_n = 0;
- has_success_frame = 0;
+ backend->convert_trial = 10;
+ backend->ready_count = 0;
+ backend->timeout = 0;
+ backend->has_success = 0;
qemu_mutex_lock(&state->thread_mutex);
state->streamon = _MC_THREAD_STREAMON;
qemu_mutex_unlock(&state->thread_mutex);
return NULL;
}
-int marucam_device_check(int log_flag)
+int marucam_device_check(void)
{
int tmp_fd;
struct timeval t1, t2;
struct v4l2_frmsizeenum size;
struct v4l2_capability cap;
int ret = 0;
+ const char *dev_name = "/dev/video0";
gettimeofday(&t1, NULL);
if (stat(dev_name, &st) < 0) {
- INFO("<WARNING> Cannot identify '%s': %s\n",
- dev_name, strerror(errno));
+ INFO("<WARNING> Cannot identify '%s': %s\n", dev_name, strerror(errno));
} else {
if (!S_ISCHR(st.st_mode)) {
- INFO("<WARNING>%s is no character device\n",
- dev_name);
+ INFO("<WARNING>%s is no character device\n", dev_name);
}
}
ERR("Camera device open failed: %s\n", dev_name);
gettimeofday(&t2, NULL);
ERR("Elapsed time: %lu:%06lu\n",
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+ t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
return ret;
}
if (ioctl(tmp_fd, VIDIOC_QUERYCAP, &cap) < 0) {
close(tmp_fd);
gettimeofday(&t2, NULL);
ERR("Elapsed time: %lu:%06lu\n",
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+ t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
return ret;
}
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ||
close(tmp_fd);
gettimeofday(&t2, NULL);
ERR("Elapsed time: %lu:%06lu\n",
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+ t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
return ret;
}
ret = 1;
- if (log_flag) {
- INFO("Driver: %s\n", cap.driver);
- INFO("Card: %s\n", cap.card);
- INFO("Bus info: %s\n", cap.bus_info);
+ INFO("Driver: %s\n", cap.driver);
+ INFO("Card: %s\n", cap.card);
+ INFO("Bus info: %s\n", cap.bus_info);
+
+ CLEAR(format);
+ format.index = 0;
+ format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ if (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) < 0) {
+ close(tmp_fd);
+ gettimeofday(&t2, NULL);
+ ERR("Elapsed time: %lu:%06lu\n",
+ t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+ return ret;
+ }
+
+ do {
+ CLEAR(size);
+ size.index = 0;
+ size.pixel_format = format.pixelformat;
- CLEAR(format);
- format.index = 0;
- format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ INFO("PixelFormat: %c%c%c%c\n",
+ (char)(format.pixelformat),
+ (char)(format.pixelformat >> 8),
+ (char)(format.pixelformat >> 16),
+ (char)(format.pixelformat >> 24));
- if (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) < 0) {
+ if (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0) {
close(tmp_fd);
gettimeofday(&t2, NULL);
ERR("Elapsed time: %lu:%06lu\n",
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+ t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
return ret;
}
- do {
- CLEAR(size);
- size.index = 0;
- size.pixel_format = format.pixelformat;
-
- INFO("PixelFormat: %c%c%c%c\n",
- (char)(format.pixelformat),
- (char)(format.pixelformat >> 8),
- (char)(format.pixelformat >> 16),
- (char)(format.pixelformat >> 24));
-
- if (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0) {
- close(tmp_fd);
- gettimeofday(&t2, NULL);
- ERR("Elapsed time: %lu:%06lu\n",
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
- return ret;
- }
+ if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
+ do {
+ INFO("\tGot a discrete frame size %dx%d\n",
+ size.discrete.width, size.discrete.height);
+ size.index++;
+ } while (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
+ } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
+ INFO("We have stepwise frame sizes:\n");
+ INFO("\tmin width: %d, min height: %d\n",
+ size.stepwise.min_width, size.stepwise.min_height);
+ INFO("\tmax width: %d, max height: %d\n",
+ size.stepwise.max_width, size.stepwise.max_height);
+ INFO("\tstep width: %d, step height: %d\n",
+ size.stepwise.step_width, size.stepwise.step_height);
+ } else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
+ INFO("We have continuous frame sizes:\n");
+ INFO("\tmin width: %d, min height: %d\n",
+ size.stepwise.min_width, size.stepwise.min_height);
+ INFO("\tmax width: %d, max height: %d\n",
+ size.stepwise.max_width, size.stepwise.max_height);
- if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
- do {
- INFO("\tGot a discrete frame size %dx%d\n",
- size.discrete.width, size.discrete.height);
- size.index++;
- } while (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
- } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
- INFO("We have stepwise frame sizes:\n");
- INFO("\tmin width: %d, min height: %d\n",
- size.stepwise.min_width, size.stepwise.min_height);
- INFO("\tmax width: %d, max height: %d\n",
- size.stepwise.max_width, size.stepwise.max_height);
- INFO("\tstep width: %d, step height: %d\n",
- size.stepwise.step_width, size.stepwise.step_height);
- } else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
- INFO("We have continuous frame sizes:\n");
- INFO("\tmin width: %d, min height: %d\n",
- size.stepwise.min_width, size.stepwise.min_height);
- INFO("\tmax width: %d, max height: %d\n",
- size.stepwise.max_width, size.stepwise.max_height);
-
- }
- format.index++;
- } while (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) >= 0);
- }
+ }
+ format.index++;
+ } while (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) >= 0);
close(tmp_fd);
gettimeofday(&t2, NULL);
INFO("Elapsed time: %lu:%06lu\n",
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+ t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
return ret;
}
-void marucam_device_init(MaruCamState *state)
+static void backend_v4l2_init(MaruCamState *state)
{
state->destroying = false;
qemu_thread_create(&state->thread_id,
QEMU_THREAD_JOINABLE);
}
-void marucam_device_exit(MaruCamState *state)
+static void backend_v4l2_reset(MaruCamState *state)
+{
+}
+
+static void backend_v4l2_release(MaruCamState *state)
{
state->destroying = true;
qemu_mutex_lock(&state->thread_mutex);
qemu_thread_join(&state->thread_id);
}
-void marucam_device_open(MaruCamState *state)
+static void backend_v4l2_open(MaruCamState *state)
{
- MaruCamParam *param = state->param;
+ MAKE_BACKEND_V4L2(state);
- param->top = 0;
- v4l2_fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);
- if (v4l2_fd < 0) {
- ERR("The v4l2 device open failed: %s\n", dev_name);
- param->errCode = EINVAL;
+ backend->fd = v4l2_open(backend->dev_name, O_RDWR | O_NONBLOCK, 0);
+ if (backend->fd < 0) {
+ ERR("The v4l2 device open failed: %s\n", backend->dev_name);
+ state->io_ptr->err_code = EINVAL;
+ state->io_ptr->ret_val = -1;
return;
}
INFO("Opened\n");
- /* FIXME : Do not use fixed values */
+ /* FIXME : Do not use fixed values
CLEAR(dst_fmt);
dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
dst_fmt.fmt.pix.width = 640;
dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height,
dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage,
dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field);
+ */
+}
+
+static void backend_v4l2_close(MaruCamState *state)
+{
+ MAKE_BACKEND_V4L2(state);
+
+ if (!is_stream_paused(state)) {
+ state->backend->stream_off(state);
+ }
+
+ backend_v4l2_reset_controls(backend);
+ backend_v4l2_storedframe_clear(backend);
+
+ v4l2_close(backend->fd);
+ backend->fd = 0;
+ INFO("Closed\n");
}
-void marucam_device_start_preview(MaruCamState *state)
+static void backend_v4l2_stream_on(MaruCamState *state)
{
+ MAKE_BACKEND_V4L2(state);
+
struct timespec req;
- MaruCamParam *param = state->param;
- param->top = 0;
req.tv_sec = 0;
req.tv_nsec = 10000000;
INFO("Pixfmt(%c%c%c%C), W:H(%d:%d), buf size(%u)\n",
- (char)(dst_fmt.fmt.pix.pixelformat),
- (char)(dst_fmt.fmt.pix.pixelformat >> 8),
- (char)(dst_fmt.fmt.pix.pixelformat >> 16),
- (char)(dst_fmt.fmt.pix.pixelformat >> 24),
- dst_fmt.fmt.pix.width,
- dst_fmt.fmt.pix.height,
- dst_fmt.fmt.pix.sizeimage);
-
- param->errCode = mmap_framebuffers(&framebuffer, &n_framebuffer);
- if (param->errCode) {
+ (char)(backend->dst_fmt.fmt.pix.pixelformat),
+ (char)(backend->dst_fmt.fmt.pix.pixelformat >> 8),
+ (char)(backend->dst_fmt.fmt.pix.pixelformat >> 16),
+ (char)(backend->dst_fmt.fmt.pix.pixelformat >> 24),
+ backend->dst_fmt.fmt.pix.width,
+ backend->dst_fmt.fmt.pix.height,
+ backend->dst_fmt.fmt.pix.sizeimage);
+
+ state->io_ptr->err_code = mmap_framebuffers(backend);
+ if (state->io_ptr->err_code) {
ERR("Failed to mmap framebuffers\n");
- if (framebuffer != NULL) {
- free_framebuffers(framebuffer, n_framebuffer);
- g_free(framebuffer);
- framebuffer = NULL;
- n_framebuffer = 0;
+ if (backend->fbs != NULL) {
+ free_framebuffers(backend);
}
+ state->io_ptr->ret_val = -1;
return;
}
- param->errCode = start_capturing();
- if (param->errCode) {
- if (framebuffer != NULL) {
- free_framebuffers(framebuffer, n_framebuffer);
- g_free(framebuffer);
- framebuffer = NULL;
- n_framebuffer = 0;
+ state->io_ptr->err_code = start_capturing(backend);
+ if (state->io_ptr->err_code) {
+ if (backend->fbs != NULL) {
+ free_framebuffers(backend);
}
+ state->io_ptr->ret_val = -1;
return;
}
INFO("Starting preview\n");
- state->buf_size = dst_fmt.fmt.pix.sizeimage;
+ state->buf_size = backend->dst_fmt.fmt.pix.sizeimage;
qemu_mutex_lock(&state->thread_mutex);
qemu_cond_signal(&state->thread_cond);
qemu_mutex_unlock(&state->thread_mutex);
}
}
-void marucam_device_stop_preview(MaruCamState *state)
+static void backend_v4l2_stream_off(MaruCamState *state)
{
+ MAKE_BACKEND_V4L2(state);
struct timespec req;
struct v4l2_requestbuffers reqbuf;
- MaruCamParam *param = state->param;
- param->top = 0;
req.tv_sec = 0;
req.tv_nsec = 50000000;
}
}
- if (has_success_frame) {
- saved_frame.width = dst_fmt.fmt.pix.width;
- saved_frame.height = dst_fmt.fmt.pix.height;
- saved_frame.size = dst_fmt.fmt.pix.sizeimage;
- if (saved_frame.data) {
- g_free(saved_frame.data);
- saved_frame.data = NULL;
- }
- saved_frame.data = (void *)g_malloc0(saved_frame.size);
- memcpy(saved_frame.data,
- framebuffer[previous_frame_index].data,
- saved_frame.size);
- TRACE("Saves a frame data\n");
+ if (backend->has_success) {
+ backend_v4l2_storedframe_set(backend);
}
- param->errCode = stop_capturing();
- if (framebuffer != NULL) {
- free_framebuffers(framebuffer, n_framebuffer);
- g_free(framebuffer);
- framebuffer = NULL;
- n_framebuffer = 0;
+ state->io_ptr->err_code = stop_capturing(backend);
+ if (state->io_ptr->err_code) {
+ ERR("Try again to turn off streaming\n");
+ state->io_ptr->err_code = stop_capturing(backend);
+ }
+ if (backend->fbs != NULL) {
+ free_framebuffers(backend);
}
state->buf_size = 0;
reqbuf.count = 0;
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
- if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
+ if (xioctl(backend->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
ERR("Failed to ioctl() with VIDIOC_REQBUF in stop_preview: %s\n",
strerror(errno));
}
+
+ if (state->io_ptr->err_code) {
+ state->io_ptr->ret_val = -1;
+ }
+
INFO("Stopping preview\n");
}
-void marucam_device_s_param(MaruCamState *state)
-{
- MaruCamParam *param = state->param;
- param->top = 0;
+static void backend_v4l2_s_parm(MaruCamState *state)
+{
+ MAKE_BACKEND_V4L2(state);
/* If KVM enabled, We use default FPS of the webcam.
* If KVM disabled, we use mininum FPS of the webcam */
if (!kvm_enabled()) {
- set_maxframeinterval(state, dst_fmt.fmt.pix.pixelformat,
- dst_fmt.fmt.pix.width,
- dst_fmt.fmt.pix.height);
+ set_maxframeinterval(backend->fd,
+ backend->dst_fmt.fmt.pix.pixelformat,
+ backend->dst_fmt.fmt.pix.width,
+ backend->dst_fmt.fmt.pix.height);
}
}
-void marucam_device_g_param(MaruCamState *state)
+static void backend_v4l2_g_parm(MaruCamState *state)
{
- MaruCamParam *param = state->param;
-
+ struct v4l2_captureparm *cp = (struct v4l2_captureparm *)state->io_ptr->data;
/* We use default FPS of the webcam
* return a fixed value on guest ini file (1/30).
*/
- param->top = 0;
- param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */
- param->stack[1] = 1; /* numerator */
- param->stack[2] = 30; /* denominator */
+ cp->capability = V4L2_CAP_TIMEPERFRAME;
+ cp->timeperframe.numerator = 1;
+ cp->timeperframe.denominator = 30;
}
-void marucam_device_s_fmt(MaruCamState *state)
+static void backend_v4l2_s_fmt(MaruCamState *state)
{
- struct v4l2_format format;
- MaruCamParam *param = state->param;
+ MAKE_BACKEND_V4L2(state);
+ struct v4l2_format *format = (struct v4l2_format *)state->io_ptr->data;
- param->top = 0;
- CLEAR(format);
- format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- format.fmt.pix.width = param->stack[0];
- format.fmt.pix.height = param->stack[1];
- format.fmt.pix.pixelformat = param->stack[2];
- format.fmt.pix.field = V4L2_FIELD_ANY;
-
- if (xioctl(v4l2_fd, VIDIOC_S_FMT, &format) < 0) {
+ if (xioctl(backend->fd, VIDIOC_S_FMT, format) < 0) {
ERR("Failed to set video format: format(0x%x), width:height(%d:%d), "
- "errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width,
- format.fmt.pix.height, strerror(errno));
- param->errCode = errno;
+ "errstr(%s)\n", format->fmt.pix.pixelformat, format->fmt.pix.width,
+ format->fmt.pix.height, strerror(errno));
+ state->io_ptr->err_code = errno;
+ state->io_ptr->ret_val = -1;
return;
}
- memcpy(&dst_fmt, &format, sizeof(format));
- param->stack[0] = dst_fmt.fmt.pix.width;
- param->stack[1] = dst_fmt.fmt.pix.height;
- param->stack[2] = dst_fmt.fmt.pix.field;
- param->stack[3] = dst_fmt.fmt.pix.pixelformat;
- param->stack[4] = dst_fmt.fmt.pix.bytesperline;
- param->stack[5] = dst_fmt.fmt.pix.sizeimage;
- param->stack[6] = dst_fmt.fmt.pix.colorspace;
- param->stack[7] = dst_fmt.fmt.pix.priv;
+ memcpy(&backend->dst_fmt, format, sizeof(struct v4l2_format));
TRACE("Set the format: w:h(%dx%d), fmt(0x%x), size(%d), "
"color(%d), field(%d)\n",
- dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height,
- dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage,
- dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field);
+ format->fmt.pix.width, format->fmt.pix.height,
+ format->fmt.pix.pixelformat, format->fmt.pix.sizeimage,
+ format->fmt.pix.colorspace, format->fmt.pix.field);
}
-void marucam_device_g_fmt(MaruCamState *state)
+static void backend_v4l2_g_fmt(MaruCamState *state)
{
- struct v4l2_format format;
- MaruCamParam *param = state->param;
-
- param->top = 0;
- CLEAR(format);
- format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ MAKE_BACKEND_V4L2(state);
+ struct v4l2_format *format = (struct v4l2_format *)state->io_ptr->data;
- if (xioctl(v4l2_fd, VIDIOC_G_FMT, &format) < 0) {
+ if (xioctl(backend->fd, VIDIOC_G_FMT, format) < 0) {
ERR("Failed to get video format: %s\n", strerror(errno));
- param->errCode = errno;
- } else {
- param->stack[0] = format.fmt.pix.width;
- param->stack[1] = format.fmt.pix.height;
- param->stack[2] = format.fmt.pix.field;
- param->stack[3] = format.fmt.pix.pixelformat;
- param->stack[4] = format.fmt.pix.bytesperline;
- param->stack[5] = format.fmt.pix.sizeimage;
- param->stack[6] = format.fmt.pix.colorspace;
- param->stack[7] = format.fmt.pix.priv;
- TRACE("Get the format: w:h(%dx%d), fmt(0x%x), size(%d), "
- "color(%d), field(%d)\n",
- format.fmt.pix.width, format.fmt.pix.height,
- format.fmt.pix.pixelformat, format.fmt.pix.sizeimage,
- format.fmt.pix.colorspace, format.fmt.pix.field);
+ state->io_ptr->err_code = errno;
+ state->io_ptr->ret_val = -1;
+ return;
}
+ TRACE("Get the format: w:h(%dx%d), fmt(0x%x), size(%d), "
+ "color(%d), field(%d)\n",
+ format->fmt.pix.width, format->fmt.pix.height,
+ format->fmt.pix.pixelformat, format->fmt.pix.sizeimage,
+ format->fmt.pix.colorspace, format->fmt.pix.field);
}
-void marucam_device_try_fmt(MaruCamState *state)
+static void backend_v4l2_try_fmt(MaruCamState *state)
{
- struct v4l2_format format;
- MaruCamParam *param = state->param;
+ MAKE_BACKEND_V4L2(state);
+ struct v4l2_format *format = (struct v4l2_format *)state->io_ptr->data;
- param->top = 0;
- CLEAR(format);
- format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- format.fmt.pix.width = param->stack[0];
- format.fmt.pix.height = param->stack[1];
- format.fmt.pix.pixelformat = param->stack[2];
- format.fmt.pix.field = V4L2_FIELD_ANY;
-
- if (xioctl(v4l2_fd, VIDIOC_TRY_FMT, &format) < 0) {
+ if (xioctl(backend->fd, VIDIOC_TRY_FMT, format) < 0) {
ERR("Failed to check video format: format(0x%x), width:height(%d:%d),"
- " errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width,
- format.fmt.pix.height, strerror(errno));
- param->errCode = errno;
+ " errstr(%s)\n", format->fmt.pix.pixelformat, format->fmt.pix.width,
+ format->fmt.pix.height, strerror(errno));
+ state->io_ptr->err_code = errno;
+ state->io_ptr->ret_val = -1;
return;
}
- param->stack[0] = format.fmt.pix.width;
- param->stack[1] = format.fmt.pix.height;
- param->stack[2] = format.fmt.pix.field;
- param->stack[3] = format.fmt.pix.pixelformat;
- param->stack[4] = format.fmt.pix.bytesperline;
- param->stack[5] = format.fmt.pix.sizeimage;
- param->stack[6] = format.fmt.pix.colorspace;
- param->stack[7] = format.fmt.pix.priv;
TRACE("Check the format: w:h(%dx%d), fmt(0x%x), size(%d), "
"color(%d), field(%d)\n",
- format.fmt.pix.width, format.fmt.pix.height,
- format.fmt.pix.pixelformat, format.fmt.pix.sizeimage,
- format.fmt.pix.colorspace, format.fmt.pix.field);
+ format->fmt.pix.width, format->fmt.pix.height,
+ format->fmt.pix.pixelformat, format->fmt.pix.sizeimage,
+ format->fmt.pix.colorspace, format->fmt.pix.field);
}
-void marucam_device_enum_fmt(MaruCamState *state)
+static void backend_v4l2_enum_fmt(MaruCamState *state)
{
- uint32_t index;
- MaruCamParam *param = state->param;
+ struct v4l2_fmtdesc *f = (struct v4l2_fmtdesc *)state->io_ptr->data;
- param->top = 0;
- index = param->stack[0];
-
- if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {
- param->errCode = EINVAL;
+ if (f->index >= ARRAY_SIZE(support_fmts)) {
+ state->io_ptr->err_code = errno;
+ state->io_ptr->ret_val = -1;
return;
}
- param->stack[1] = 0; /* flags = NONE */
- param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */
+
+ f->flags = 0; /* flags = NONE */
+ f->pixelformat = support_fmts[f->index].fmt; /* pixelformat */
+
/* set description */
- switch (supported_dst_pixfmts[index].fmt) {
+ switch (support_fmts[f->index].fmt) {
case V4L2_PIX_FMT_YUYV:
- strcpy((char *)¶m->stack[3], "YUYV");
+ pstrcpy((char *)f->description, sizeof(f->description), "YUYV");
break;
case V4L2_PIX_FMT_YUV420:
- strcpy((char *)¶m->stack[3], "YU12");
+ pstrcpy((char *)f->description, sizeof(f->description), "YU12");
break;
case V4L2_PIX_FMT_YVU420:
- strcpy((char *)¶m->stack[3], "YV12");
+ pstrcpy((char *)f->description, sizeof(f->description), "YV12");
break;
default:
ERR("Invalid fixel format\n");
- param->errCode = EINVAL;
+ state->io_ptr->err_code = EINVAL;
+ state->io_ptr->ret_val = -1;
break;
}
}
-void marucam_device_qctrl(MaruCamState *state)
+static void backend_v4l2_query_ctrl(MaruCamState *state)
{
+ MAKE_BACKEND_V4L2(state);
+ struct v4l2_queryctrl *qc = (struct v4l2_queryctrl *)state->io_ptr->data;
uint32_t i;
- char name[32] = {0,};
- struct v4l2_queryctrl ctrl;
- MaruCamParam *param = state->param;
-
- param->top = 0;
- CLEAR(ctrl);
- ctrl.id = param->stack[0];
/* NOTICE: Tizen MMFW hardcoded for control name
Do Not Modified the name
*/
- switch (ctrl.id) {
+ switch (qc->id) {
case V4L2_CID_BRIGHTNESS:
TRACE("Query : BRIGHTNESS\n");
- strcpy(name, "brightness");
+ pstrcpy((char *)qc->name, sizeof(qc->name), "brightness");
i = 0;
break;
case V4L2_CID_CONTRAST:
TRACE("Query : CONTRAST\n");
- strcpy(name, "contrast");
+ pstrcpy((char *)qc->name, sizeof(qc->name), "contrast");
i = 1;
break;
case V4L2_CID_SATURATION:
TRACE("Query : SATURATION\n");
- strcpy(name, "saturation");
+ pstrcpy((char *)qc->name, sizeof(qc->name), "saturation");
i = 2;
break;
case V4L2_CID_SHARPNESS:
TRACE("Query : SHARPNESS\n");
- strcpy(name, "sharpness");
+ pstrcpy((char *)qc->name, sizeof(qc->name), "sharpness");
i = 3;
break;
default:
ERR("Invalid control ID\n");
- param->errCode = EINVAL;
+ state->io_ptr->err_code = EINVAL;
+ state->io_ptr->ret_val = -1;
return;
}
- if (xioctl(v4l2_fd, VIDIOC_QUERYCTRL, &ctrl) < 0) {
+ if (xioctl(backend->fd, VIDIOC_QUERYCTRL, qc) < 0) {
if (errno != EINVAL) {
ERR("Failed to query video controls: %s\n", strerror(errno));
}
- param->errCode = errno;
+ state->io_ptr->err_code = errno;
+ state->io_ptr->ret_val = -1;
return;
} else {
struct v4l2_control sctrl, gctrl;
CLEAR(sctrl);
CLEAR(gctrl);
- sctrl.id = gctrl.id = ctrl.id;
- if (xioctl(v4l2_fd, VIDIOC_G_CTRL, &gctrl) < 0) {
+ sctrl.id = gctrl.id = qc->id;
+ if (xioctl(backend->fd, VIDIOC_G_CTRL, &gctrl) < 0) {
ERR("[%s] Failed to get video control value: id(0x%x), "
"errstr(%s)\n",
__func__, gctrl.id, strerror(errno));
- param->errCode = errno;
+ state->io_ptr->err_code = errno;
+ state->io_ptr->ret_val = -1;
return;
}
- qctrl_tbl[i].hit = 1;
- qctrl_tbl[i].min = ctrl.minimum;
- qctrl_tbl[i].max = ctrl.maximum;
- qctrl_tbl[i].step = ctrl.step;
- qctrl_tbl[i].init_val = gctrl.value;
+ ctrl_tbl[i].hit = 1;
+ ctrl_tbl[i].min = qc->minimum;
+ ctrl_tbl[i].max = qc->maximum;
+ ctrl_tbl[i].step = qc->step;
+ ctrl_tbl[i].init_val = gctrl.value;
- if ((ctrl.maximum + ctrl.minimum) == 0) {
+ if ((qc->maximum + qc->minimum) == 0) {
sctrl.value = 0;
} else {
- sctrl.value = (ctrl.maximum + ctrl.minimum) / 2;
+ sctrl.value = (qc->maximum + qc->minimum) / 2;
}
- if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &sctrl) < 0) {
+ if (xioctl(backend->fd, VIDIOC_S_CTRL, &sctrl) < 0) {
ERR("[%s] Failed to set control value: id(0x%x), value(%d), "
"errstr(%s)\n",
__func__, sctrl.id, sctrl.value, strerror(errno));
- param->errCode = errno;
+ state->io_ptr->err_code = errno;
+ state->io_ptr->ret_val = -1;
return;
}
INFO("Query Control: id(0x%x), name(%s), min(%d), max(%d), "
"step(%d), def_value(%d)\n"
"flags(0x%x), get_value(%d), set_value(%d)\n",
- ctrl.id, ctrl.name, ctrl.minimum, ctrl.maximum,
- ctrl.step, ctrl.default_value, ctrl.flags,
+ qc->id, qc->name, qc->minimum, qc->maximum,
+ qc->step, qc->default_value, qc->flags,
gctrl.value, sctrl.value);
}
/* set fixed values by FW configuration file */
- param->stack[0] = ctrl.id;
- param->stack[1] = MARUCAM_CTRL_VALUE_MIN; /* minimum */
- param->stack[2] = MARUCAM_CTRL_VALUE_MAX; /* maximum */
- param->stack[3] = MARUCAM_CTRL_VALUE_STEP; /* step */
- param->stack[4] = MARUCAM_CTRL_VALUE_MID; /* default_value */
- param->stack[5] = ctrl.flags;
- /* name field setting */
- memcpy(¶m->stack[6], (void *)name, sizeof(ctrl.name));
+ qc->minimum = MARUCAM_CTRL_VALUE_MIN; /* minimum */
+ qc->maximum = MARUCAM_CTRL_VALUE_MAX; /* maximum */
+ qc->step = MARUCAM_CTRL_VALUE_STEP; /* step */
+ qc->default_value = MARUCAM_CTRL_VALUE_MID; /* default_value */
}
-void marucam_device_s_ctrl(MaruCamState *state)
+static void backend_v4l2_s_ctrl(MaruCamState *state)
{
+ MAKE_BACKEND_V4L2(state);
+ struct v4l2_control *ctrl = (struct v4l2_control *)state->io_ptr->data;
uint32_t i;
- struct v4l2_control ctrl;
- MaruCamParam *param = state->param;
- param->top = 0;
- CLEAR(ctrl);
- ctrl.id = param->stack[0];
-
- switch (ctrl.id) {
+ switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
i = 0;
- TRACE("%d is set to the value of the BRIGHTNESS\n", param->stack[1]);
+ TRACE("%d is set to the value of the BRIGHTNESS\n", ctrl->value);
break;
case V4L2_CID_CONTRAST:
i = 1;
- TRACE("%d is set to the value of the CONTRAST\n", param->stack[1]);
+ TRACE("%d is set to the value of the CONTRAST\n", ctrl->value);
break;
case V4L2_CID_SATURATION:
i = 2;
- TRACE("%d is set to the value of the SATURATION\n", param->stack[1]);
+ TRACE("%d is set to the value of the SATURATION\n", ctrl->value);
break;
case V4L2_CID_SHARPNESS:
i = 3;
- TRACE("%d is set to the value of the SHARPNESS\n", param->stack[1]);
+ TRACE("%d is set to the value of the SHARPNESS\n", ctrl->value);
break;
default:
- ERR("Our emulator does not support this control: 0x%x\n", ctrl.id);
- param->errCode = EINVAL;
+ ERR("Our emulator does not support this control: 0x%x\n", ctrl->id);
+ state->io_ptr->err_code= EINVAL;
+ state->io_ptr->ret_val = -1;
return;
}
- ctrl.value = value_convert_from_guest(qctrl_tbl[i].min,
- qctrl_tbl[i].max, param->stack[1]);
- if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) {
- ERR("Failed to set control value: id(0x%x), value(r:%d, c:%d), "
- "errstr(%s)\n", ctrl.id, param->stack[1], ctrl.value,
- strerror(errno));
- param->errCode = errno;
+ ctrl->value = value_convert_from_guest(ctrl_tbl[i].min,
+ ctrl_tbl[i].max, ctrl->value);
+ if (xioctl(backend->fd, VIDIOC_S_CTRL, ctrl) < 0) {
+ ERR("Failed to set control value: id(0x%x), value(%d), errstr(%s)\n",
+ ctrl->id, ctrl->value, strerror(errno));
+ state->io_ptr->err_code = errno;
+ state->io_ptr->ret_val = -1;
return;
}
}
-void marucam_device_g_ctrl(MaruCamState *state)
+static void backend_v4l2_g_ctrl(MaruCamState *state)
{
+ MAKE_BACKEND_V4L2(state);
+ struct v4l2_control *ctrl = (struct v4l2_control *)state->io_ptr->data;
uint32_t i;
- struct v4l2_control ctrl;
- MaruCamParam *param = state->param;
-
- param->top = 0;
- CLEAR(ctrl);
- ctrl.id = param->stack[0];
- switch (ctrl.id) {
+ switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
TRACE("Gets the value of the BRIGHTNESS\n");
i = 0;
i = 3;
break;
default:
- ERR("Our emulator does not support this control: 0x%x\n", ctrl.id);
- param->errCode = EINVAL;
+ ERR("Our emulator does not support this control: 0x%x\n", ctrl->id);
+ state->io_ptr->err_code = EINVAL;
+ state->io_ptr->ret_val = -1;
return;
}
- if (xioctl(v4l2_fd, VIDIOC_G_CTRL, &ctrl) < 0) {
+ if (xioctl(backend->fd, VIDIOC_G_CTRL, ctrl) < 0) {
ERR("Failed to get video control value: %s\n", strerror(errno));
- param->errCode = errno;
+ state->io_ptr->err_code = errno;
+ state->io_ptr->ret_val = -1;
return;
}
- param->stack[0] = value_convert_to_guest(qctrl_tbl[i].min,
- qctrl_tbl[i].max, ctrl.value);
- TRACE("Value: %d\n", param->stack[0]);
+ ctrl->value = value_convert_to_guest(ctrl_tbl[i].min,
+ ctrl_tbl[i].max, ctrl->value);
+ TRACE("Value: %d\n", ctrl->value);
}
-void marucam_device_enum_fsizes(MaruCamState *state)
+static void backend_v4l2_enum_fsizes(MaruCamState *state)
{
- uint32_t index, pixfmt, i;
- MaruCamParam *param = state->param;
-
- param->top = 0;
- index = param->stack[0];
- pixfmt = param->stack[1];
+ struct v4l2_frmsizeenum *fsize = (struct v4l2_frmsizeenum *)state->io_ptr->data;
+ uint32_t i;
- if (index >= ARRAY_SIZE(supported_dst_frames)) {
- param->errCode = EINVAL;
+ if (fsize->index >= ARRAY_SIZE(support_frames)) {
+ state->io_ptr->err_code = EINVAL;
+ state->io_ptr->ret_val = -1;
return;
}
- for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
- if (supported_dst_pixfmts[i].fmt == pixfmt) {
+ for (i = 0; i < ARRAY_SIZE(support_fmts); i++) {
+ if (support_fmts[i].fmt == fsize->pixel_format) {
break;
}
}
- if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
- param->errCode = EINVAL;
+ if (i == ARRAY_SIZE(support_fmts)) {
+ state->io_ptr->err_code = EINVAL;
+ state->io_ptr->ret_val = -1;
return;
}
- param->stack[0] = supported_dst_frames[index].width;
- param->stack[1] = supported_dst_frames[index].height;
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete.width = support_frames[fsize->index].width;
+ fsize->discrete.height = support_frames[fsize->index].height;
}
-void marucam_device_enum_fintv(MaruCamState *state)
+static void backend_v4l2_enum_fintv(MaruCamState *state)
{
- MaruCamParam *param = state->param;
-
- param->top = 0;
+ struct v4l2_frmivalenum *fival = (struct v4l2_frmivalenum *)state->io_ptr->data;
- /* switch by index(param->stack[0]) */
- switch (param->stack[0]) {
+ /* switch by index) */
+ switch (fival->index) {
case 0:
/* we only use 1/30 frame interval */
- param->stack[1] = 30; /* denominator */
+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+ fival->discrete.numerator = 1;
+ fival->discrete.denominator = 30;
break;
default:
- param->errCode = EINVAL;
+ state->io_ptr->err_code = EINVAL;
+ state->io_ptr->ret_val = -1;
return;
}
- param->stack[0] = 1; /* numerator */
}
-void marucam_device_close(MaruCamState *state)
+MaruCamBackend *marucam_backend_create(MaruCamState *state)
{
- if (!is_stream_paused(state)) {
- marucam_device_stop_preview(state);
- }
-
- marucam_reset_controls();
-
- if (saved_frame.data) {
- g_free(saved_frame.data);
- saved_frame.data = NULL;
- }
- memset(&saved_frame, 0x00, sizeof(saved_frame));
-
- v4l2_close(v4l2_fd);
- v4l2_fd = 0;
- INFO("Closed\n");
+ MCBackendV4l2 *backend_v4l2;
+
+ backend_v4l2 = g_new0(MCBackendV4l2, 1);
+
+ backend_v4l2->base.init = backend_v4l2_init;
+ backend_v4l2->base.reset = backend_v4l2_reset;
+ backend_v4l2->base.release = backend_v4l2_release;
+ backend_v4l2->base.open = backend_v4l2_open;
+ backend_v4l2->base.close = backend_v4l2_close;
+ backend_v4l2->base.stream_on = backend_v4l2_stream_on;
+ backend_v4l2->base.stream_off = backend_v4l2_stream_off;
+ backend_v4l2->base.enum_fmt = backend_v4l2_enum_fmt;
+ backend_v4l2->base.try_fmt = backend_v4l2_try_fmt;
+ backend_v4l2->base.s_fmt = backend_v4l2_s_fmt;
+ backend_v4l2->base.g_fmt = backend_v4l2_g_fmt;
+ backend_v4l2->base.s_parm = backend_v4l2_s_parm;
+ backend_v4l2->base.g_parm = backend_v4l2_g_parm;
+ backend_v4l2->base.query_ctrl = backend_v4l2_query_ctrl;
+ backend_v4l2->base.s_ctrl = backend_v4l2_s_ctrl;
+ backend_v4l2->base.g_ctrl = backend_v4l2_g_ctrl;
+ backend_v4l2->base.enum_framesizes = backend_v4l2_enum_fsizes;
+ backend_v4l2->base.enum_frameintervals = backend_v4l2_enum_fintv;
+
+ return &backend_v4l2->base;
}