maru_camera_linux : modified a routine for grab frame
authorjinhyung.jo <jinhyung.jo@samsung.com>
Thu, 1 Nov 2012 12:00:07 +0000 (21:00 +0900)
committerjinhyung.jo <jinhyung.jo@samsung.com>
Thu, 1 Nov 2012 12:00:07 +0000 (21:00 +0900)
The linux camera module does not use the v4l2_read() function as a capture method.
Instead, the module uses a streaming routine(with mmmap) for the fast stream-off.

Signed-off-by: Jinhyung Jo <jinhyung.jo@samsung.com>
tizen/src/hw/maru_camera_linux_pci.c

index 8e1db29c97808275e653c5d9cc0a0b6005f24d5b..e078bc0f2cbb5a5ac1015e5a13e4c82188dd83f3 100644 (file)
@@ -26,7 +26,6 @@
  *\r
  */\r
 \r
-#include "qemu-common.h"\r
 #include "qemu-common.h"\r
 #include "maru_camera_common.h"\r
 #include "pci.h"\r
 \r
 #include <sys/stat.h>\r
 #include <sys/ioctl.h>\r
+#include <sys/mman.h>\r
 \r
 #include <libv4l2.h>\r
 #include <libv4lconvert.h>\r
 \r
 MULTI_DEBUG_CHANNEL(tizen, camera_linux);\r
 \r
+#define CLEAR(x) memset(&(x), 0, sizeof(x))\r
+\r
+#define MARUCAM_DEFAULT_BUFFER_COUNT    4\r
+\r
+#define MARUCAM_CTRL_VALUE_MAX      20\r
+#define MARUCAM_CTRL_VALUE_MIN      1\r
+#define MARUCAM_CTRL_VALUE_MID      10\r
+#define MARUCAM_CTRL_VALUE_STEP     1\r
+\r
 enum {\r
     _MC_THREAD_PAUSED,\r
     _MC_THREAD_STREAMON,\r
     _MC_THREAD_STREAMOFF,\r
 };\r
 \r
+typedef struct marucam_framebuffer {\r
+    void *data;\r
+    size_t size;\r
+} marucam_framebuffer;\r
+\r
+static int n_framebuffer;\r
+static struct marucam_framebuffer *framebuffer;\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
-static void *grab_buf;\r
 \r
 static struct v4l2_format dst_fmt;\r
 \r
-#define CLEAR(x) memset(&(x), 0, sizeof(x))\r
-\r
 static int yioctl(int fd, int req, void *arg)\r
 {\r
     int r;\r
 \r
     do {\r
         r = ioctl(fd, req, arg);\r
-    } while ( r < 0 && errno == EINTR);\r
+    } while (r < 0 && errno == EINTR);\r
 \r
     return r;\r
 }\r
@@ -76,7 +90,7 @@ static int xioctl(int fd, int req, void *arg)
 \r
     do {\r
         r = v4l2_ioctl(fd, req, arg);\r
-    } while ( r < 0 && errno == EINTR);\r
+    } while (r < 0 && errno == EINTR);\r
 \r
     return r;\r
 }\r
@@ -104,11 +118,6 @@ static MaruCamConvertFrameInfo supported_dst_frames[] = {
         { 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
-#define MARUCAM_CTRL_VALUE_STEP     1\r
-\r
 struct marucam_qctrl {\r
     uint32_t id;\r
     uint32_t hit;\r
@@ -135,7 +144,7 @@ static void marucam_reset_controls(void)
             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 reset control value : id(0x%x), errstr(%s)\n",\r
+                ERR("Failed to reset control value: id(0x%x), errstr(%s)\n",\r
                     ctrl.id, strerror(errno));\r
             }\r
         }\r
@@ -214,9 +223,10 @@ static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format,
         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 (fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {\r
+            TRACE("with %u/%u step", fival.stepwise.step.numerator,\r
+                  fival.stepwise.step.denominator);\r
+        }\r
         if (((float)fival.stepwise.max.denominator /\r
              (float)fival.stepwise.max.numerator) >\r
             ((float)fival.stepwise.min.denominator /\r
@@ -228,7 +238,7 @@ static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format,
             min_denom = fival.stepwise.min.denominator;\r
         }\r
     }\r
-    TRACE("actual min values : %u/%u\n", min_num, min_denom);\r
+    TRACE("The actual min values: %u/%u\n", min_num, min_denom);\r
 \r
     CLEAR(sp);\r
     sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
@@ -240,6 +250,121 @@ static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format,
     }\r
 }\r
 \r
+static uint32_t stop_capturing(void)\r
+{\r
+    enum v4l2_buf_type type;\r
+\r
+    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
+    if (xioctl(v4l2_fd, VIDIOC_STREAMOFF, &type) < 0) {\r
+        ERR("Failed to ioctl() with VIDIOC_STREAMOFF: %s\n", strerror(errno));\r
+        return errno;\r
+    }\r
+    return 0;\r
+}\r
+\r
+static uint32_t start_capturing(void)\r
+{\r
+    enum v4l2_buf_type type;\r
+\r
+    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
+    if (xioctl(v4l2_fd, VIDIOC_STREAMON, &type) < 0) {\r
+        ERR("Failed to ioctl() with VIDIOC_STREAMON: %s\n", strerror(errno));\r
+        return errno;\r
+    }\r
+    return 0;\r
+}\r
+\r
+static void free_framebuffers(marucam_framebuffer *fb, int buf_num)\r
+{\r
+    int i;\r
+\r
+    if (fb == NULL) {\r
+        ERR("The framebuffer is NULL. Failed to release the framebuffer\n");\r
+        return;\r
+    } else if (buf_num == 0) {\r
+        ERR("The buffer count is 0. Failed to release the framebuffer\n");\r
+        return;\r
+    } else {\r
+        TRACE("[%s]:fb(0x%p), buf_num(%d)\n", __func__, fb, buf_num);\r
+    }\r
+\r
+    /* Unmap framebuffers. */\r
+    for (i = 0; i < buf_num; i++) {\r
+        if (fb[i].data != NULL) {\r
+            v4l2_munmap(fb[i].data, fb[i].size);\r
+            fb[i].data = NULL;\r
+            fb[i].size = 0;\r
+        } else {\r
+            ERR("framebuffer[%d].data is NULL.\n", i);\r
+        }\r
+    }\r
+}\r
+\r
+static uint32_t\r
+mmap_framebuffers(marucam_framebuffer **fb, int *buf_num)\r
+{\r
+    struct v4l2_requestbuffers req;\r
+\r
+    CLEAR(req);\r
+    req.count   = MARUCAM_DEFAULT_BUFFER_COUNT;\r
+    req.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
+    req.memory  = V4L2_MEMORY_MMAP;\r
+    if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &req) < 0) {\r
+        if (errno == EINVAL) {\r
+            ERR("%s does not support memory mapping: %s\n",\r
+                dev_name, strerror(errno));\r
+        } else {\r
+            ERR("Failed to request bufs: %s\n", strerror(errno));\r
+        }\r
+        return errno;\r
+    }\r
+    if (req.count == 0) {\r
+        ERR("Insufficient buffer memory on %s\n", dev_name);\r
+        return EINVAL;\r
+    }\r
+\r
+    *fb = g_new0(marucam_framebuffer, req.count);\r
+    if (*fb == NULL) {\r
+        ERR("Not enough memory to allocate framebuffers\n");\r
+        return ENOMEM;\r
+    }\r
+\r
+    for (*buf_num = 0; *buf_num < req.count; ++*buf_num) {\r
+        struct v4l2_buffer buf;\r
+        CLEAR(buf);\r
+        buf.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
+        buf.memory  = V4L2_MEMORY_MMAP;\r
+        buf.index   = *buf_num;\r
+        if (xioctl(v4l2_fd, VIDIOC_QUERYBUF, &buf) < 0) {\r
+            ERR("Failed to ioctl() with VIDIOC_QUERYBUF: %s\n",\r
+                strerror(errno));\r
+            return errno;\r
+        }\r
+\r
+        (*fb)[*buf_num].size = buf.length;\r
+        (*fb)[*buf_num].data = v4l2_mmap(NULL,\r
+                     buf.length,\r
+                     PROT_READ | PROT_WRITE,\r
+                     MAP_SHARED,\r
+                     v4l2_fd, buf.m.offset);\r
+        if (MAP_FAILED == (*fb)[*buf_num].data) {\r
+            ERR("Failed to mmap: %s\n", strerror(errno));\r
+            return errno;\r
+        }\r
+\r
+        /* Queue the mapped buffer. */\r
+        CLEAR(buf);\r
+        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
+        buf.memory = V4L2_MEMORY_MMAP;\r
+        buf.index = *buf_num;\r
+        if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) {\r
+            ERR("Failed to ioctl() with VIDIOC_QBUF: %s\n", strerror(errno));\r
+            return errno;\r
+        }\r
+    }\r
+    return 0;\r
+}\r
+\r
 static int is_streamon(MaruCamState *state)\r
 {\r
     int st;\r
@@ -269,13 +394,76 @@ static void __raise_err_intr(MaruCamState *state)
     qemu_mutex_unlock(&state->thread_mutex);\r
 }\r
 \r
-static int __v4l2_grab(MaruCamState *state)\r
+static void\r
+notify_buffer_ready(MaruCamState *state, void *ptr, size_t size)\r
+{\r
+    void *buf = NULL;\r
+\r
+    qemu_mutex_lock(&state->thread_mutex);\r
+    if (state->streamon == _MC_THREAD_STREAMON) {\r
+        if (ready_count < MARUCAM_SKIPFRAMES) {\r
+            /* skip a frame cause first some frame are distorted */\r
+            ++ready_count;\r
+            TRACE("Skip %d frame\n", ready_count);\r
+            qemu_mutex_unlock(&state->thread_mutex);\r
+            return;\r
+        }\r
+        if (state->req_frame == 0) {\r
+            TRACE("There is no request\n");\r
+            qemu_mutex_unlock(&state->thread_mutex);\r
+            return;\r
+        }\r
+        buf = state->vaddr + state->buf_size * (state->req_frame - 1);\r
+        memcpy(buf, ptr, state->buf_size);\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
+    }\r
+    qemu_mutex_unlock(&state->thread_mutex);\r
+}\r
+\r
+static int read_frame(MaruCamState *state)\r
+{\r
+    struct v4l2_buffer buf;\r
+\r
+    CLEAR(buf);\r
+    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
+    buf.memory = V4L2_MEMORY_MMAP;\r
+    if (xioctl(v4l2_fd, VIDIOC_DQBUF, &buf) < 0) {\r
+        switch (errno) {\r
+        case EAGAIN:\r
+        case EINTR:\r
+            ERR("DQBUF error, try again: %s\n", strerror(errno));\r
+            return 0;\r
+        case EIO:\r
+            ERR("The v4l2_read() met the EIO\n");\r
+            if (convert_trial-- == -1) {\r
+                ERR("Try count for v4l2_read is exceeded: %s\n",\r
+                    strerror(errno));\r
+                return -1;\r
+            }\r
+            return 0;\r
+        default:\r
+            ERR("DQBUF error: %s\n", strerror(errno));\r
+            return -1;\r
+        }\r
+    }\r
+\r
+    notify_buffer_ready(state, framebuffer[buf.index].data, buf.bytesused);\r
+\r
+    if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) {\r
+        ERR("QBUF error: %s\n", strerror(errno));\r
+        return -1;\r
+    }\r
+    return 0;\r
+}\r
+\r
+static int __v4l2_streaming(MaruCamState *state)\r
 {\r
     fd_set fds;\r
     struct timeval tv;\r
-    void *buf;\r
     int ret;\r
-    \r
+\r
     FD_ZERO(&fds);\r
     FD_SET(v4l2_fd, &fds);\r
 \r
@@ -285,77 +473,36 @@ static int __v4l2_grab(MaruCamState *state)
     ret = select(v4l2_fd + 1, &fds, NULL, NULL, &tv);\r
     if (ret < 0) {\r
         if (errno == EAGAIN || errno == EINTR) {\r
-            ERR("select again: %s\n", strerror(errno));\r
+            ERR("Select again: %s\n", strerror(errno));\r
             return 0;\r
         }\r
-        ERR("failed to select : %s\n", strerror(errno));\r
+        ERR("Failed to select: %s\n", strerror(errno));\r
         __raise_err_intr(state);\r
         return -1;\r
     } else if (!ret) {\r
-        ERR("select timed out\n");\r
+        ERR("Select timed out\n");\r
         return 0;\r
     }\r
 \r
     if (!v4l2_fd || (v4l2_fd == -1)) {\r
-        ERR("file descriptor is closed or not opened \n");\r
+        ERR("The file descriptor is closed or not opened\n");\r
         __raise_err_intr(state);\r
         return -1;\r
     }\r
 \r
-    ret = v4l2_read(v4l2_fd, grab_buf, state->buf_size);\r
+    ret = read_frame(state);\r
     if (ret < 0) {\r
-        switch (errno) {\r
-        case EAGAIN:\r
-        case EINTR:\r
-            ERR("v4l2_read met the error: %s\n", strerror(errno));\r
-            return 0;\r
-        case EIO:\r
-            ERR("v4l2_read met the EIO.\n");\r
-            if (convert_trial-- == -1) {\r
-                ERR("Try count for v4l2_read is exceeded: %s\n",\r
-                    strerror(errno));\r
-                __raise_err_intr(state);\r
-                return -1;\r
-            }\r
-            return 0;\r
-        default:\r
-            ERR("v4l2_read failed : %s\n", strerror(errno));\r
-            __raise_err_intr(state);\r
-            return -1;\r
-        }\r
-    }\r
-\r
-    qemu_mutex_lock(&state->thread_mutex);\r
-    if (state->streamon == _MC_THREAD_STREAMON) {\r
-        if (ready_count < MARUCAM_SKIPFRAMES) {\r
-            /* skip a frame cause first some frame are distorted */\r
-            ++ready_count;\r
-            TRACE("skip %d frame\n", ready_count);\r
-            qemu_mutex_unlock(&state->thread_mutex);\r
-            return 0;\r
-        }\r
-        if (state->req_frame == 0) {\r
-            TRACE("there is no request\n");\r
-            qemu_mutex_unlock(&state->thread_mutex);\r
-            return 0;\r
-        }\r
-        buf = state->vaddr + state->buf_size * (state->req_frame -1);\r
-        memcpy(buf, grab_buf, state->buf_size);\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
+        ERR("Failed to operate the read_frame()\n");\r
+        __raise_err_intr(state);\r
+        return -1;\r
     }\r
-    qemu_mutex_unlock(&state->thread_mutex);\r
-    return ret;\r
+    return 0;\r
 }\r
 \r
 /* Worker thread */\r
 static void *marucam_worker_thread(void *thread_param)\r
 {\r
-    MaruCamState *state = (MaruCamState*)thread_param;\r
+    MaruCamState *state = (MaruCamState *)thread_param;\r
 \r
 wait_worker_thread:\r
     qemu_mutex_lock(&state->thread_mutex);\r
@@ -372,7 +519,7 @@ wait_worker_thread:
 \r
     while (1) {\r
         if (is_streamon(state)) {\r
-            if (__v4l2_grab(state) < 0) {\r
+            if (__v4l2_streaming(state) < 0) {\r
                 INFO("...... Streaming off\n");\r
                 goto wait_worker_thread;\r
             }\r
@@ -400,14 +547,14 @@ int marucam_device_check(int log_flag)
                 dev_name, strerror(errno));\r
     } else {\r
         if (!S_ISCHR(st.st_mode)) {\r
-            fprintf(stdout, "[Webcam] <WARNING>%s is no character device.\n",\r
+            fprintf(stdout, "[Webcam] <WARNING>%s is no character device\n",\r
                     dev_name);\r
         }\r
     }\r
 \r
     tmp_fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);\r
     if (tmp_fd < 0) {\r
-        fprintf(stdout, "[Webcam] Camera device open failed.(%s)\n", dev_name);\r
+        fprintf(stdout, "[Webcam] Camera device open failed: %s\n", dev_name);\r
         goto error;\r
     }\r
     if (ioctl(tmp_fd, VIDIOC_QUERYCAP, &cap) < 0) {\r
@@ -416,15 +563,15 @@ int marucam_device_check(int log_flag)
     }\r
     if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ||\r
             !(cap.capabilities & V4L2_CAP_STREAMING)) {\r
-        fprintf(stdout, "[Webcam] Not supported video driver.\n");\r
+        fprintf(stdout, "[Webcam] Not supported video driver\n");\r
         goto error;\r
     }\r
     ret = 1;\r
 \r
     if (log_flag) {\r
-        fprintf(stdout, "[Webcam] Driver : %s\n", cap.driver);\r
-        fprintf(stdout, "[Webcam] Card : %s\n", cap.card);\r
-        fprintf(stdout, "[Webcam] Bus info : %s\n", cap.bus_info);\r
+        fprintf(stdout, "[Webcam] Driver: %s\n", cap.driver);\r
+        fprintf(stdout, "[Webcam] Card %s\n", cap.card);\r
+        fprintf(stdout, "[Webcam] Bus info: %s\n", cap.bus_info);\r
 \r
         CLEAR(format);\r
         format.index = 0;\r
@@ -439,7 +586,7 @@ int marucam_device_check(int log_flag)
             size.index = 0;\r
             size.pixel_format = format.pixelformat;\r
 \r
-            fprintf(stdout, "[Webcam] PixelFormat : %c%c%c%c\n",\r
+            fprintf(stdout, "[Webcam] PixelFormat: %c%c%c%c\n",\r
                              (char)(format.pixelformat),\r
                              (char)(format.pixelformat >> 8),\r
                              (char)(format.pixelformat >> 16),\r
@@ -477,30 +624,31 @@ int marucam_device_check(int log_flag)
 error:\r
     close(tmp_fd);\r
     gettimeofday(&t2, NULL);\r
-    fprintf(stdout, "[Webcam] Elapsed time : %lu:%06lu\n",\r
+    fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n",\r
                     t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
     return ret;\r
 }\r
 \r
-void marucam_device_init(MaruCamStatestate)\r
+void marucam_device_init(MaruCamState *state)\r
 {\r
-    qemu_thread_create(&state->thread_id, marucam_worker_thread, (void*)state,\r
+    qemu_thread_create(&state->thread_id, marucam_worker_thread, (void *)state,\r
             QEMU_THREAD_JOINABLE);\r
 }\r
 \r
-void marucam_device_open(MaruCamStatestate)\r
+void marucam_device_open(MaruCamState *state)\r
 {\r
     MaruCamParam *param = state->param;\r
 \r
     param->top = 0;\r
     v4l2_fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);\r
     if (v4l2_fd < 0) {\r
-        ERR("v4l2 device open failed.(%s)\n", dev_name);\r
+        ERR("The v4l2 device open failed: %s\n", dev_name);\r
         param->errCode = EINVAL;\r
         return;\r
     }\r
     INFO("Opened\n");\r
 \r
+    /* FIXME : Do not use fixed values */\r
     CLEAR(dst_fmt);\r
     dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
     dst_fmt.fmt.pix.width = 640;\r
@@ -509,20 +657,20 @@ void marucam_device_open(MaruCamState* state)
     dst_fmt.fmt.pix.field = V4L2_FIELD_ANY;\r
 \r
     if (xioctl(v4l2_fd, VIDIOC_S_FMT, &dst_fmt) < 0) {\r
-        ERR("failed to set video format: format(0x%x), width:height(%d:%d), "\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
-    TRACE("set the default format: w:h(%dx%d), fmt(0x%x), size(%d), "\r
+    TRACE("Set the default format: w:h(%dx%d), fmt(0x%x), size(%d), "\r
          "color(%d), field(%d)\n",\r
          dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height,\r
          dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage,\r
          dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field);\r
 }\r
 \r
-void marucam_device_start_preview(MaruCamStatestate)\r
+void marucam_device_start_preview(MaruCamState *state)\r
 {\r
     struct timespec req;\r
     MaruCamParam *param = state->param;\r
@@ -538,30 +686,47 @@ void marucam_device_start_preview(MaruCamState* state)
          dst_fmt.fmt.pix.width,\r
          dst_fmt.fmt.pix.height,\r
          dst_fmt.fmt.pix.sizeimage);\r
-    INFO("Starting preview\n");\r
 \r
-    if (grab_buf) {\r
-        g_free(grab_buf);\r
-        grab_buf = NULL;\r
+    param->errCode = mmap_framebuffers(&framebuffer, &n_framebuffer);\r
+    if (param->errCode) {\r
+        ERR("Failed to mmap framebuffers\n");\r
+        if (framebuffer != NULL) {\r
+            free_framebuffers(framebuffer, n_framebuffer);\r
+            g_free(framebuffer);\r
+            framebuffer = NULL;\r
+            n_framebuffer = 0;\r
+        }\r
+        return;\r
     }\r
-    grab_buf = (void *)g_malloc0(dst_fmt.fmt.pix.sizeimage);\r
-    if (grab_buf == NULL) {\r
-        param->errCode = ENOMEM;\r
+\r
+    param->errCode = start_capturing();\r
+    if (param->errCode) {\r
+        if (framebuffer != NULL) {\r
+            free_framebuffers(framebuffer, n_framebuffer);\r
+            g_free(framebuffer);\r
+            framebuffer = NULL;\r
+            n_framebuffer = 0;\r
+        }\r
         return;\r
     }\r
+\r
+    INFO("Starting preview\n");\r
     state->buf_size = dst_fmt.fmt.pix.sizeimage;\r
     qemu_mutex_lock(&state->thread_mutex);\r
     qemu_cond_signal(&state->thread_cond);\r
     qemu_mutex_unlock(&state->thread_mutex);\r
 \r
     /* nanosleep until thread is streamon  */\r
-    while (!is_streamon(state))\r
+    while (!is_streamon(state)) {\r
         nanosleep(&req, NULL);\r
+    }\r
 }\r
 \r
-void marucam_device_stop_preview(MaruCamStatestate)\r
+void marucam_device_stop_preview(MaruCamState *state)\r
 {\r
     struct timespec req;\r
+    MaruCamParam *param = state->param;\r
+    param->top = 0;\r
     req.tv_sec = 0;\r
     req.tv_nsec = 50000000;\r
 \r
@@ -571,20 +736,23 @@ void marucam_device_stop_preview(MaruCamState* state)
         qemu_mutex_unlock(&state->thread_mutex);\r
 \r
         /* nanosleep until thread is paused  */\r
-        while (!is_stream_paused(state))\r
+        while (!is_stream_paused(state)) {\r
             nanosleep(&req, NULL);\r
+        }\r
     }\r
 \r
-    if (grab_buf) {\r
-        g_free(grab_buf);\r
-        grab_buf = NULL;\r
+    param->errCode = stop_capturing();\r
+    if (framebuffer != NULL) {\r
+        free_framebuffers(framebuffer, n_framebuffer);\r
+        g_free(framebuffer);\r
+        framebuffer = NULL;\r
+        n_framebuffer = 0;\r
     }\r
     state->buf_size = 0;\r
-\r
     INFO("Stopping preview\n");\r
 }\r
 \r
-void marucam_device_s_param(MaruCamStatestate)\r
+void marucam_device_s_param(MaruCamState *state)\r
 {\r
     MaruCamParam *param = state->param;\r
 \r
@@ -599,7 +767,7 @@ void marucam_device_s_param(MaruCamState* state)
     }\r
 }\r
 \r
-void marucam_device_g_param(MaruCamStatestate)\r
+void marucam_device_g_param(MaruCamState *state)\r
 {\r
     MaruCamParam *param = state->param;\r
 \r
@@ -612,7 +780,7 @@ void marucam_device_g_param(MaruCamState* state)
     param->stack[2] = 30; /* denominator */\r
 }\r
 \r
-void marucam_device_s_fmt(MaruCamStatestate)\r
+void marucam_device_s_fmt(MaruCamState *state)\r
 {\r
     struct v4l2_format format;\r
     MaruCamParam *param = state->param;\r
@@ -626,7 +794,7 @@ void marucam_device_s_fmt(MaruCamState* state)
     format.fmt.pix.field = V4L2_FIELD_ANY;\r
 \r
     if (xioctl(v4l2_fd, VIDIOC_S_FMT, &format) < 0) {\r
-        ERR("failed to set video format: format(0x%x), width:height(%d:%d), "\r
+        ERR("Failed to set 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
@@ -642,14 +810,14 @@ void marucam_device_s_fmt(MaruCamState* state)
     param->stack[5] = dst_fmt.fmt.pix.sizeimage;\r
     param->stack[6] = dst_fmt.fmt.pix.colorspace;\r
     param->stack[7] = dst_fmt.fmt.pix.priv;\r
-    TRACE("set the format: w:h(%dx%d), fmt(0x%x), size(%d), "\r
+    TRACE("Set the format: w:h(%dx%d), fmt(0x%x), size(%d), "\r
          "color(%d), field(%d)\n",\r
          dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height,\r
          dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage,\r
          dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field);\r
 }\r
 \r
-void marucam_device_g_fmt(MaruCamStatestate)\r
+void marucam_device_g_fmt(MaruCamState *state)\r
 {\r
     struct v4l2_format format;\r
     MaruCamParam *param = state->param;\r
@@ -659,7 +827,7 @@ void marucam_device_g_fmt(MaruCamState* state)
     format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
 \r
     if (xioctl(v4l2_fd, VIDIOC_G_FMT, &format) < 0) {\r
-        ERR("failed to get video format: %s\n", strerror(errno));\r
+        ERR("Failed to get video format: %s\n", strerror(errno));\r
         param->errCode = errno;\r
     } else {\r
         param->stack[0] = format.fmt.pix.width;\r
@@ -670,7 +838,7 @@ void marucam_device_g_fmt(MaruCamState* state)
         param->stack[5] = format.fmt.pix.sizeimage;\r
         param->stack[6] = format.fmt.pix.colorspace;\r
         param->stack[7] = format.fmt.pix.priv;\r
-        TRACE("get the format: w:h(%dx%d), fmt(0x%x), size(%d), "\r
+        TRACE("Get the format: w:h(%dx%d), fmt(0x%x), size(%d), "\r
              "color(%d), field(%d)\n",\r
              format.fmt.pix.width, format.fmt.pix.height,\r
              format.fmt.pix.pixelformat, format.fmt.pix.sizeimage,\r
@@ -678,7 +846,7 @@ void marucam_device_g_fmt(MaruCamState* state)
     }\r
 }\r
 \r
-void marucam_device_try_fmt(MaruCamStatestate)\r
+void marucam_device_try_fmt(MaruCamState *state)\r
 {\r
     struct v4l2_format format;\r
     MaruCamParam *param = state->param;\r
@@ -692,7 +860,7 @@ void marucam_device_try_fmt(MaruCamState* state)
     format.fmt.pix.field = V4L2_FIELD_ANY;\r
 \r
     if (xioctl(v4l2_fd, VIDIOC_TRY_FMT, &format) < 0) {\r
-        ERR("failed to check video format: format(0x%x), width:height(%d:%d),"\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
@@ -706,14 +874,14 @@ void marucam_device_try_fmt(MaruCamState* state)
     param->stack[5] = format.fmt.pix.sizeimage;\r
     param->stack[6] = format.fmt.pix.colorspace;\r
     param->stack[7] = format.fmt.pix.priv;\r
-    TRACE("check the format: w:h(%dx%d), fmt(0x%x), size(%d), "\r
+    TRACE("Check the format: w:h(%dx%d), fmt(0x%x), size(%d), "\r
          "color(%d), field(%d)\n",\r
          format.fmt.pix.width, format.fmt.pix.height,\r
          format.fmt.pix.pixelformat, format.fmt.pix.sizeimage,\r
          format.fmt.pix.colorspace, format.fmt.pix.field);\r
 }\r
 \r
-void marucam_device_enum_fmt(MaruCamStatestate)\r
+void marucam_device_enum_fmt(MaruCamState *state)\r
 {\r
     uint32_t index;\r
     MaruCamParam *param = state->param;\r
@@ -741,7 +909,7 @@ void marucam_device_enum_fmt(MaruCamState* state)
     }\r
 }\r
 \r
-void marucam_device_qctrl(MaruCamStatestate)\r
+void marucam_device_qctrl(MaruCamState *state)\r
 {\r
     uint32_t i;\r
     char name[32] = {0,};\r
@@ -755,22 +923,22 @@ void marucam_device_qctrl(MaruCamState* state)
     switch (ctrl.id) {\r
     case V4L2_CID_BRIGHTNESS:\r
         TRACE("Query : BRIGHTNESS\n");\r
-        memcpy((void*)name, (void*)"brightness", 32);\r
+        memcpy((void *)name, (void *)"brightness", 32);\r
         i = 0;\r
         break;\r
     case V4L2_CID_CONTRAST:\r
         TRACE("Query : CONTRAST\n");\r
-        memcpy((void*)name, (void*)"contrast", 32);\r
+        memcpy((void *)name, (void *)"contrast", 32);\r
         i = 1;\r
         break;\r
     case V4L2_CID_SATURATION:\r
         TRACE("Query : SATURATION\n");\r
-        memcpy((void*)name, (void*)"saturation", 32);\r
+        memcpy((void *)name, (void *)"saturation", 32);\r
         i = 2;\r
         break;\r
     case V4L2_CID_SHARPNESS:\r
         TRACE("Query : SHARPNESS\n");\r
-        memcpy((void*)name, (void*)"sharpness", 32);\r
+        memcpy((void *)name, (void *)"sharpness", 32);\r
         i = 3;\r
         break;\r
     default:\r
@@ -779,8 +947,9 @@ void marucam_device_qctrl(MaruCamState* state)
     }\r
 \r
     if (xioctl(v4l2_fd, VIDIOC_QUERYCTRL, &ctrl) < 0) {\r
-        if (errno != EINVAL)\r
-            ERR("failed to query video controls : %s\n", strerror(errno));\r
+        if (errno != EINVAL) {\r
+            ERR("Failed to query video controls: %s\n", strerror(errno));\r
+        }\r
         param->errCode = errno;\r
         return;\r
     } else {\r
@@ -793,7 +962,7 @@ void marucam_device_qctrl(MaruCamState* state)
             sctrl.value = (ctrl.maximum + ctrl.minimum) / 2;\r
         }\r
         if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &sctrl) < 0) {\r
-            ERR("failed to set control value: id(0x%x), value(%d), "\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
@@ -805,18 +974,18 @@ void marucam_device_qctrl(MaruCamState* state)
         qctrl_tbl[i].init_val = ctrl.default_value;\r
     }\r
 \r
-    // set fixed values by FW configuration file\r
+    /* set fixed values by FW configuration file */\r
     param->stack[0] = ctrl.id;\r
-    param->stack[1] = MARUCAM_CTRL_VALUE_MIN;   // minimum\r
-    param->stack[2] = MARUCAM_CTRL_VALUE_MAX;   // maximum\r
-    param->stack[3] = MARUCAM_CTRL_VALUE_STEP;// step\r
-    param->stack[4] = MARUCAM_CTRL_VALUE_MID;   // default_value\r
+    param->stack[1] = MARUCAM_CTRL_VALUE_MIN;    /* minimum */\r
+    param->stack[2] = MARUCAM_CTRL_VALUE_MAX;    /* maximum */\r
+    param->stack[3] = MARUCAM_CTRL_VALUE_STEP;   /* step */\r
+    param->stack[4] = MARUCAM_CTRL_VALUE_MID;    /* default_value */\r
     param->stack[5] = ctrl.flags;\r
     /* name field setting */\r
-    memcpy(&param->stack[6], (void*)name, sizeof(ctrl.name));\r
+    memcpy(&param->stack[6], (void *)name, sizeof(ctrl.name));\r
 }\r
 \r
-void marucam_device_s_ctrl(MaruCamStatestate)\r
+void marucam_device_s_ctrl(MaruCamState *state)\r
 {\r
     uint32_t i;\r
     struct v4l2_control ctrl;\r
@@ -844,7 +1013,7 @@ void marucam_device_s_ctrl(MaruCamState* state)
         TRACE("%d is set to the value of the SHARPNESS\n", param->stack[1]);\r
         break;\r
     default:\r
-        ERR("our emulator does not support this control : 0x%x\n", ctrl.id);\r
+        ERR("Our emulator does not support this control: 0x%x\n", ctrl.id);\r
         param->errCode = EINVAL;\r
         return;\r
     }\r
@@ -852,7 +1021,7 @@ void marucam_device_s_ctrl(MaruCamState* state)
     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 control value : id0x%x), value(r:%d, c:%d), "\r
+        ERR("Failed to set control value: id(0x%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
@@ -860,7 +1029,7 @@ void marucam_device_s_ctrl(MaruCamState* state)
     }\r
 }\r
 \r
-void marucam_device_g_ctrl(MaruCamStatestate)\r
+void marucam_device_g_ctrl(MaruCamState *state)\r
 {\r
     uint32_t i;\r
     struct v4l2_control ctrl;\r
@@ -888,22 +1057,22 @@ void marucam_device_g_ctrl(MaruCamState* state)
         i = 3;\r
         break;\r
     default:\r
-        ERR("our emulator does not support this control : 0x%x\n", ctrl.id);\r
+        ERR("Our emulator does not support this control: 0x%x\n", ctrl.id);\r
         param->errCode = EINVAL;\r
         return;\r
     }\r
 \r
     if (xioctl(v4l2_fd, VIDIOC_G_CTRL, &ctrl) < 0) {\r
-        ERR("failed to get video control value : %s\n", strerror(errno));\r
+        ERR("Failed to get video control value: %s\n", strerror(errno));\r
         param->errCode = errno;\r
         return;\r
     }\r
     param->stack[0] = value_convert_to_guest(qctrl_tbl[i].min,\r
             qctrl_tbl[i].max, ctrl.value);\r
-    TRACE("Value : %d\n", param->stack[0]);\r
+    TRACE("Value: %d\n", param->stack[0]);\r
 }\r
 \r
-void marucam_device_enum_fsizes(MaruCamStatestate)\r
+void marucam_device_enum_fsizes(MaruCamState *state)\r
 {\r
     uint32_t index, pixfmt, i;\r
     MaruCamParam *param = state->param;\r
@@ -917,8 +1086,9 @@ void marucam_device_enum_fsizes(MaruCamState* state)
         return;\r
     }\r
     for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {\r
-        if (supported_dst_pixfmts[i].fmt == pixfmt)\r
+        if (supported_dst_pixfmts[i].fmt == pixfmt) {\r
             break;\r
+        }\r
     }\r
 \r
     if (i == ARRAY_SIZE(supported_dst_pixfmts)) {\r
@@ -930,7 +1100,7 @@ void marucam_device_enum_fsizes(MaruCamState* state)
     param->stack[1] = supported_dst_frames[index].height;\r
 }\r
 \r
-void marucam_device_enum_fintv(MaruCamStatestate)\r
+void marucam_device_enum_fintv(MaruCamState *state)\r
 {\r
     MaruCamParam *param = state->param;\r
 \r
@@ -949,10 +1119,11 @@ void marucam_device_enum_fintv(MaruCamState* state)
     param->stack[0] = 1;    /* numerator */\r
 }\r
 \r
-void marucam_device_close(MaruCamStatestate)\r
+void marucam_device_close(MaruCamState *state)\r
 {\r
-    if (!is_stream_paused(state))\r
+    if (!is_stream_paused(state)) {\r
         marucam_device_stop_preview(state);\r
+    }\r
 \r
     marucam_reset_controls();\r
 \r