maru-camera: Rename files 15/37015/1
authorjinhyung.jo <jinhyung.jo@samsung.com>
Wed, 18 Mar 2015 05:43:50 +0000 (14:43 +0900)
committerjinhyung.jo <jinhyung.jo@samsung.com>
Wed, 18 Mar 2015 05:49:00 +0000 (14:49 +0900)
Delete unnecessary postfix, like '_pci'.
Integrate the format conversion utilities, separately implemented in Darwin & Win32.

Change-Id: Ie71cc57c8ed7c9e74eb19afed2e55259b720151f
Signed-off-by: Jinhyung Jo <jinhyung.jo@samsung.com>
18 files changed:
tizen/src/hw/pci/Makefile.objs
tizen/src/hw/pci/maru_camera.c [new file with mode: 0644]
tizen/src/hw/pci/maru_camera.h [new file with mode: 0644]
tizen/src/hw/pci/maru_camera_common.h [deleted file]
tizen/src/hw/pci/maru_camera_common_pci.c [deleted file]
tizen/src/hw/pci/maru_camera_convert.c [new file with mode: 0644]
tizen/src/hw/pci/maru_camera_convert.h [new file with mode: 0644]
tizen/src/hw/pci/maru_camera_darwin.h [deleted file]
tizen/src/hw/pci/maru_camera_darwin.m [new file with mode: 0644]
tizen/src/hw/pci/maru_camera_darwin_converter.c [deleted file]
tizen/src/hw/pci/maru_camera_darwin_pci.m [deleted file]
tizen/src/hw/pci/maru_camera_linux.c [new file with mode: 0644]
tizen/src/hw/pci/maru_camera_linux_pci.c [deleted file]
tizen/src/hw/pci/maru_camera_win32.c [new file with mode: 0644]
tizen/src/hw/pci/maru_camera_win32.h [new file with mode: 0644]
tizen/src/hw/pci/maru_camera_win32_interface.h [deleted file]
tizen/src/hw/pci/maru_camera_win32_pci.c [deleted file]
tizen/src/util/check_cam.c

index 408a68c57b5feb639d3057fbae0739ed4fd603d7..506305e75875b96b47b46758721db1ed8298557b 100644 (file)
@@ -8,18 +8,17 @@ obj-$(CONFIG_VAAPI) += maru_brillcodec_vaapi.o
 
 obj-y += maru_brightness.o
 
-obj-y += maru_camera_common_pci.o
+obj-y += maru_camera.o
 ifdef CONFIG_LINUX
-obj-y += maru_camera_linux_pci.o
+obj-y += maru_camera_linux.o
 LIBS += -lv4l2 -lv4lconvert
 endif
 ifdef CONFIG_WIN32
-obj-y += maru_camera_win32_pci.o
+obj-y += maru_camera_win32.o maru_camera_util.o
 LIBS += -lole32 -loleaut32 -luuid -lstrmiids
 endif
 ifdef CONFIG_DARWIN
-obj-y += maru_camera_darwin_converter.o
-obj-y += maru_camera_darwin_pci.o
+obj-y += maru_camera_darwin.o maru_camera_util.o
 LIBS += -framework Foundation -framework SystemConfiguration
 LIBS += -framework Cocoa -framework QTKit -framework CoreVideo
 LIBS += -framework AppKit
diff --git a/tizen/src/hw/pci/maru_camera.c b/tizen/src/hw/pci/maru_camera.c
new file mode 100644 (file)
index 0000000..112c286
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * Common implementation of MARU Virtual Camera device by PCI bus.
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <signal.h>
+
+#include "qemu-common.h"
+#include "qemu/main-loop.h"
+#include "exec/cpu-common.h"
+
+#include "maru_camera.h"
+#include "hw/maru_device_ids.h"
+#include "debug_ch.h"
+
+MULTI_DEBUG_CHANNEL(tizen, camera);
+
+#define MARU_PCI_CAMERA_DEVICE_NAME     "maru-camera"
+
+#define MARUCAM_MEM_SIZE    (4 * 1024 * 1024)   /* 4MB */
+#define MARUCAM_REG_SIZE    (256)               /* 64 * 4Byte */
+
+/*
+ *  I/O functions
+ */
+static inline uint32_t
+marucam_mmio_read(void *opaque, hwaddr offset)
+{
+    uint32_t ret = 0;
+    MaruCamState *state = (MaruCamState *)opaque;
+
+    switch (offset & 0xFF) {
+    case MARUCAM_CMD_ISR:
+        qemu_mutex_lock(&state->thread_mutex);
+        ret = state->isr;
+        if (ret != 0) {
+            pci_set_irq(&state->dev, 0);
+            state->isr = 0;
+        }
+        qemu_mutex_unlock(&state->thread_mutex);
+        break;
+    case MARUCAM_CMD_G_DATA:
+        ret = state->param->stack[state->param->top++];
+        break;
+    case MARUCAM_CMD_OPEN:
+    case MARUCAM_CMD_CLOSE:
+    case MARUCAM_CMD_START_PREVIEW:
+    case MARUCAM_CMD_STOP_PREVIEW:
+    case MARUCAM_CMD_S_PARAM:
+    case MARUCAM_CMD_G_PARAM:
+    case MARUCAM_CMD_ENUM_FMT:
+    case MARUCAM_CMD_TRY_FMT:
+    case MARUCAM_CMD_S_FMT:
+    case MARUCAM_CMD_G_FMT:
+    case MARUCAM_CMD_QCTRL:
+    case MARUCAM_CMD_S_CTRL:
+    case MARUCAM_CMD_G_CTRL:
+    case MARUCAM_CMD_ENUM_FSIZES:
+    case MARUCAM_CMD_ENUM_FINTV:
+        ret = state->param->errCode;
+        state->param->errCode = 0;
+        break;
+    default:
+        ERR("Not supported command: 0x%x\n", offset);
+        ret = EINVAL;
+        break;
+    }
+    return ret;
+}
+
+static inline void
+marucam_mmio_write(void *opaque, hwaddr offset, uint32_t value)
+{
+    MaruCamState *state = (MaruCamState *)opaque;
+
+    switch (offset & 0xFF) {
+    case MARUCAM_CMD_OPEN:
+        marucam_device_open(state);
+        break;
+    case MARUCAM_CMD_CLOSE:
+        marucam_device_close(state);
+        break;
+    case MARUCAM_CMD_START_PREVIEW:
+        marucam_device_start_preview(state);
+        break;
+    case MARUCAM_CMD_STOP_PREVIEW:
+        marucam_device_stop_preview(state);
+        memset(state->vaddr, 0, MARUCAM_MEM_SIZE);
+        break;
+    case MARUCAM_CMD_S_PARAM:
+        marucam_device_s_param(state);
+        break;
+    case MARUCAM_CMD_G_PARAM:
+        marucam_device_g_param(state);
+        break;
+    case MARUCAM_CMD_ENUM_FMT:
+        marucam_device_enum_fmt(state);
+        break;
+    case MARUCAM_CMD_TRY_FMT:
+        marucam_device_try_fmt(state);
+        break;
+    case MARUCAM_CMD_S_FMT:
+        marucam_device_s_fmt(state);
+        break;
+    case MARUCAM_CMD_G_FMT:
+        marucam_device_g_fmt(state);
+        break;
+    case MARUCAM_CMD_QCTRL:
+        marucam_device_qctrl(state);
+        break;
+    case MARUCAM_CMD_S_CTRL:
+        marucam_device_s_ctrl(state);
+        break;
+    case MARUCAM_CMD_G_CTRL:
+        marucam_device_g_ctrl(state);
+        break;
+    case MARUCAM_CMD_ENUM_FSIZES:
+        marucam_device_enum_fsizes(state);
+        break;
+    case MARUCAM_CMD_ENUM_FINTV:
+        marucam_device_enum_fintv(state);
+        break;
+    case MARUCAM_CMD_S_DATA:
+        state->param->stack[state->param->top++] = value;
+        break;
+    case MARUCAM_CMD_DATACLR:
+        memset(state->param, 0, sizeof(MaruCamParam));
+        break;
+    case MARUCAM_CMD_REQFRAME:
+        qemu_mutex_lock(&state->thread_mutex);
+        state->req_frame = value + 1;
+        qemu_mutex_unlock(&state->thread_mutex);
+        break;
+    default:
+        ERR("Not supported command: 0x%x\n", offset);
+        break;
+    }
+}
+
+static const MemoryRegionOps maru_camera_mmio_ops = {
+    .old_mmio = {
+        .read = {
+            marucam_mmio_read,
+            marucam_mmio_read,
+            marucam_mmio_read,
+        },
+        .write = {
+            marucam_mmio_write,
+            marucam_mmio_write,
+            marucam_mmio_write,
+        },
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+/*
+ *  QEMU bottom half funtion
+ */
+static void marucam_tx_bh(void *opaque)
+{
+    MaruCamState *state = (MaruCamState *)opaque;
+
+    qemu_mutex_lock(&state->thread_mutex);
+    if (state->isr) {
+        pci_set_irq(&state->dev, 1);
+    }
+    qemu_mutex_unlock(&state->thread_mutex);
+}
+
+/*
+ *  Initialization function
+ */
+
+static int marucam_initfn(PCIDevice *dev)
+{
+    MaruCamState *s = DO_UPCAST(MaruCamState, dev, dev);
+    uint8_t *pci_conf = s->dev.config;
+
+    /* Check available webcam
+     * If there is not one, you can't use the camera.
+     */
+    if (!marucam_device_check(1)) {
+        s->initialized = false;
+        ERR("Failed to check the camera device, "
+            "You can *not* use the camera\n");
+        return 0;
+    }
+
+    pci_config_set_interrupt_pin(pci_conf, 0x03);
+
+    memory_region_init_ram(&s->vram, OBJECT(s), "marucamera.ram", MARUCAM_MEM_SIZE,
+                            &error_abort);
+    s->vaddr = memory_region_get_ram_ptr(&s->vram);
+    memset(s->vaddr, 0, MARUCAM_MEM_SIZE);
+
+    memory_region_init_io(&s->mmio, OBJECT(s),
+                          &maru_camera_mmio_ops,
+                          s,
+                          "maru-camera-mmio",
+                          MARUCAM_REG_SIZE);
+
+    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
+    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio);
+
+    /* for worker thread */
+    s->param = (MaruCamParam *)g_malloc0(sizeof(MaruCamParam));
+    qemu_cond_init(&s->thread_cond);
+    qemu_mutex_init(&s->thread_mutex);
+
+    marucam_device_init(s);
+
+    s->tx_bh = qemu_bh_new(marucam_tx_bh, s);
+    s->initialized = true;
+    INFO("initialize maru-camera device\n");
+
+    return 0;
+}
+
+/*
+ *  Termination function
+ */
+static void marucam_exitfn(PCIDevice *pci_dev)
+{
+    MaruCamState *s =
+        OBJECT_CHECK(MaruCamState, pci_dev, MARU_PCI_CAMERA_DEVICE_NAME);
+
+    if (s->initialized) {
+        marucam_device_exit(s);
+        g_free(s->param);
+        qemu_cond_destroy(&s->thread_cond);
+        qemu_mutex_destroy(&s->thread_mutex);
+    }
+
+    INFO("finalize maru-camera device\n");
+}
+
+static void marucam_resetfn(DeviceState *d)
+{
+    MaruCamState *s = (MaruCamState *)d;
+
+    if (s->initialized) {
+        marucam_device_close(s);
+        qemu_mutex_lock(&s->thread_mutex);
+        s->isr = s->streamon = s->req_frame = s->buf_size = 0;
+        qemu_mutex_unlock(&s->thread_mutex);
+        memset(s->vaddr, 0, MARUCAM_MEM_SIZE);
+        memset(s->param, 0x00, sizeof(MaruCamParam));
+        INFO("reset maru-camera device\n");
+    }
+}
+
+int maru_camera_pci_init(PCIBus *bus)
+{
+    pci_create_simple(bus, -1, MARU_PCI_CAMERA_DEVICE_NAME);
+    return 0;
+}
+
+static void maru_camera_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = marucam_initfn;
+    k->exit = marucam_exitfn;
+    k->vendor_id = PCI_VENDOR_ID_TIZEN;
+    k->device_id = PCI_DEVICE_ID_VIRTUAL_CAMERA;
+    k->class_id = PCI_CLASS_OTHERS;
+    dc->reset = marucam_resetfn;
+    dc->desc = "MARU Virtual Camera device for Tizen emulator";
+}
+
+static TypeInfo maru_camera_info = {
+    .name          = MARU_PCI_CAMERA_DEVICE_NAME,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(MaruCamState),
+    .class_init    = maru_camera_pci_class_init,
+};
+
+static void maru_camera_pci_register_types(void)
+{
+    type_register_static(&maru_camera_info);
+}
+
+type_init(maru_camera_pci_register_types)
diff --git a/tizen/src/hw/pci/maru_camera.h b/tizen/src/hw/pci/maru_camera.h
new file mode 100644 (file)
index 0000000..4294460
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Common header of MARU Virtual Camera device.
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#ifndef _MARU_CAMERA_H_
+#define _MARU_CAMERA_H_
+
+#include "hw/pci/pci.h"
+#include "qemu/thread.h"
+
+#define MARUCAM_MAX_PARAM    20
+#define MARUCAM_SKIPFRAMES    2
+
+/* must sync with GUEST camera_driver */
+#define MARUCAM_CMD_INIT           0x00
+#define MARUCAM_CMD_OPEN           0x04
+#define MARUCAM_CMD_CLOSE          0x08
+#define MARUCAM_CMD_ISR            0x0C
+#define MARUCAM_CMD_START_PREVIEW  0x10
+#define MARUCAM_CMD_STOP_PREVIEW   0x14
+#define MARUCAM_CMD_S_PARAM        0x18
+#define MARUCAM_CMD_G_PARAM        0x1C
+#define MARUCAM_CMD_ENUM_FMT       0x20
+#define MARUCAM_CMD_TRY_FMT        0x24
+#define MARUCAM_CMD_S_FMT          0x28
+#define MARUCAM_CMD_G_FMT          0x2C
+#define MARUCAM_CMD_QCTRL          0x30
+#define MARUCAM_CMD_S_CTRL         0x34
+#define MARUCAM_CMD_G_CTRL         0x38
+#define MARUCAM_CMD_ENUM_FSIZES    0x3C
+#define MARUCAM_CMD_ENUM_FINTV     0x40
+#define MARUCAM_CMD_S_DATA         0x44
+#define MARUCAM_CMD_G_DATA         0x48
+#define MARUCAM_CMD_DATACLR        0x50
+#define MARUCAM_CMD_REQFRAME       0x54
+
+typedef struct MaruCamState MaruCamState;
+typedef struct MaruCamParam MaruCamParam;
+
+struct MaruCamParam {
+    uint32_t    top;
+    uint32_t    retVal;
+    uint32_t    errCode;
+    uint32_t    stack[MARUCAM_MAX_PARAM];
+};
+
+struct MaruCamState {
+    PCIDevice           dev;
+    MaruCamParam        *param;
+    QemuThread          thread_id;
+    QemuMutex           thread_mutex;;
+    QemuCond            thread_cond;
+    QEMUBH              *tx_bh;
+
+    bool                initialized;
+    bool                destroying;
+    void                *vaddr;     /* vram ptr */
+    uint32_t            isr;
+    uint32_t            streamon;
+    uint32_t            buf_size;
+    uint32_t            req_frame;
+
+    MemoryRegion        vram;
+    MemoryRegion        mmio;
+};
+
+/* ------------------------------------------------------------------------- */
+/* Fucntion prototype                                                        */
+/* ------------------------------------------------------------------------- */
+int marucam_device_check(int log_flag);
+void marucam_device_init(MaruCamState *state);
+void marucam_device_exit(MaruCamState *state);
+void marucam_device_open(MaruCamState *state);
+void marucam_device_close(MaruCamState *state);
+void marucam_device_start_preview(MaruCamState *state);
+void marucam_device_stop_preview(MaruCamState *state);
+void marucam_device_s_param(MaruCamState *state);
+void marucam_device_g_param(MaruCamState *state);
+void marucam_device_s_fmt(MaruCamState *state);
+void marucam_device_g_fmt(MaruCamState *state);
+void marucam_device_try_fmt(MaruCamState *state);
+void marucam_device_enum_fmt(MaruCamState *state);
+void marucam_device_qctrl(MaruCamState *state);
+void marucam_device_s_ctrl(MaruCamState *state);
+void marucam_device_g_ctrl(MaruCamState *state);
+void marucam_device_enum_fsizes(MaruCamState *state);
+void marucam_device_enum_fintv(MaruCamState *state);
+
+int maru_camera_pci_init(PCIBus *bus);
+
+#endif  /* _MARU_CAMERA_H_ */
diff --git a/tizen/src/hw/pci/maru_camera_common.h b/tizen/src/hw/pci/maru_camera_common.h
deleted file mode 100644 (file)
index 45b1a38..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Common header of MARU Virtual Camera device.
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Contact:
- * JinHyung Jo <jinhyung.jo@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-#ifndef _MARU_CAMERA_COMMON_H_
-#define _MARU_CAMERA_COMMON_H_
-
-#include "hw/pci/pci.h"
-#include "qemu/thread.h"
-
-#define MARUCAM_MAX_PARAM    20
-#define MARUCAM_SKIPFRAMES    2
-
-/* must sync with GUEST camera_driver */
-#define MARUCAM_CMD_INIT           0x00
-#define MARUCAM_CMD_OPEN           0x04
-#define MARUCAM_CMD_CLOSE          0x08
-#define MARUCAM_CMD_ISR            0x0C
-#define MARUCAM_CMD_START_PREVIEW  0x10
-#define MARUCAM_CMD_STOP_PREVIEW   0x14
-#define MARUCAM_CMD_S_PARAM        0x18
-#define MARUCAM_CMD_G_PARAM        0x1C
-#define MARUCAM_CMD_ENUM_FMT       0x20
-#define MARUCAM_CMD_TRY_FMT        0x24
-#define MARUCAM_CMD_S_FMT          0x28
-#define MARUCAM_CMD_G_FMT          0x2C
-#define MARUCAM_CMD_QCTRL          0x30
-#define MARUCAM_CMD_S_CTRL         0x34
-#define MARUCAM_CMD_G_CTRL         0x38
-#define MARUCAM_CMD_ENUM_FSIZES    0x3C
-#define MARUCAM_CMD_ENUM_FINTV     0x40
-#define MARUCAM_CMD_S_DATA         0x44
-#define MARUCAM_CMD_G_DATA         0x48
-#define MARUCAM_CMD_DATACLR        0x50
-#define MARUCAM_CMD_REQFRAME       0x54
-
-typedef struct MaruCamState MaruCamState;
-typedef struct MaruCamParam MaruCamParam;
-
-struct MaruCamParam {
-    uint32_t    top;
-    uint32_t    retVal;
-    uint32_t    errCode;
-    uint32_t    stack[MARUCAM_MAX_PARAM];
-};
-
-struct MaruCamState {
-    PCIDevice           dev;
-    MaruCamParam        *param;
-    QemuThread          thread_id;
-    QemuMutex           thread_mutex;;
-    QemuCond            thread_cond;
-    QEMUBH              *tx_bh;
-
-    bool                initialized;
-    bool                destroying;
-    void                *vaddr;     /* vram ptr */
-    uint32_t            isr;
-    uint32_t            streamon;
-    uint32_t            buf_size;
-    uint32_t            req_frame;
-
-    MemoryRegion        vram;
-    MemoryRegion        mmio;
-};
-
-/* ------------------------------------------------------------------------- */
-/* Fucntion prototype                                                        */
-/* ------------------------------------------------------------------------- */
-int marucam_device_check(int log_flag);
-void marucam_device_init(MaruCamState *state);
-void marucam_device_exit(MaruCamState *state);
-void marucam_device_open(MaruCamState *state);
-void marucam_device_close(MaruCamState *state);
-void marucam_device_start_preview(MaruCamState *state);
-void marucam_device_stop_preview(MaruCamState *state);
-void marucam_device_s_param(MaruCamState *state);
-void marucam_device_g_param(MaruCamState *state);
-void marucam_device_s_fmt(MaruCamState *state);
-void marucam_device_g_fmt(MaruCamState *state);
-void marucam_device_try_fmt(MaruCamState *state);
-void marucam_device_enum_fmt(MaruCamState *state);
-void marucam_device_qctrl(MaruCamState *state);
-void marucam_device_s_ctrl(MaruCamState *state);
-void marucam_device_g_ctrl(MaruCamState *state);
-void marucam_device_enum_fsizes(MaruCamState *state);
-void marucam_device_enum_fintv(MaruCamState *state);
-
-int maru_camera_pci_init(PCIBus *bus);
-
-#endif  /* _MARU_CAMERA_COMMON_H_ */
diff --git a/tizen/src/hw/pci/maru_camera_common_pci.c b/tizen/src/hw/pci/maru_camera_common_pci.c
deleted file mode 100644 (file)
index d44df52..0000000
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Common implementation of MARU Virtual Camera device by PCI bus.
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Contact:
- * JinHyung Jo <jinhyung.jo@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-#include <signal.h>
-
-#include "qemu-common.h"
-#include "qemu/main-loop.h"
-#include "exec/cpu-common.h"
-
-#include "maru_camera_common.h"
-#include "hw/maru_device_ids.h"
-#include "debug_ch.h"
-
-MULTI_DEBUG_CHANNEL(tizen, camera);
-
-#define MARU_PCI_CAMERA_DEVICE_NAME     "maru-camera"
-
-#define MARUCAM_MEM_SIZE    (4 * 1024 * 1024)   /* 4MB */
-#define MARUCAM_REG_SIZE    (256)               /* 64 * 4Byte */
-
-/*
- *  I/O functions
- */
-static inline uint32_t
-marucam_mmio_read(void *opaque, hwaddr offset)
-{
-    uint32_t ret = 0;
-    MaruCamState *state = (MaruCamState *)opaque;
-
-    switch (offset & 0xFF) {
-    case MARUCAM_CMD_ISR:
-        qemu_mutex_lock(&state->thread_mutex);
-        ret = state->isr;
-        if (ret != 0) {
-            pci_set_irq(&state->dev, 0);
-            state->isr = 0;
-        }
-        qemu_mutex_unlock(&state->thread_mutex);
-        break;
-    case MARUCAM_CMD_G_DATA:
-        ret = state->param->stack[state->param->top++];
-        break;
-    case MARUCAM_CMD_OPEN:
-    case MARUCAM_CMD_CLOSE:
-    case MARUCAM_CMD_START_PREVIEW:
-    case MARUCAM_CMD_STOP_PREVIEW:
-    case MARUCAM_CMD_S_PARAM:
-    case MARUCAM_CMD_G_PARAM:
-    case MARUCAM_CMD_ENUM_FMT:
-    case MARUCAM_CMD_TRY_FMT:
-    case MARUCAM_CMD_S_FMT:
-    case MARUCAM_CMD_G_FMT:
-    case MARUCAM_CMD_QCTRL:
-    case MARUCAM_CMD_S_CTRL:
-    case MARUCAM_CMD_G_CTRL:
-    case MARUCAM_CMD_ENUM_FSIZES:
-    case MARUCAM_CMD_ENUM_FINTV:
-        ret = state->param->errCode;
-        state->param->errCode = 0;
-        break;
-    default:
-        ERR("Not supported command: 0x%x\n", offset);
-        ret = EINVAL;
-        break;
-    }
-    return ret;
-}
-
-static inline void
-marucam_mmio_write(void *opaque, hwaddr offset, uint32_t value)
-{
-    MaruCamState *state = (MaruCamState *)opaque;
-
-    switch (offset & 0xFF) {
-    case MARUCAM_CMD_OPEN:
-        marucam_device_open(state);
-        break;
-    case MARUCAM_CMD_CLOSE:
-        marucam_device_close(state);
-        break;
-    case MARUCAM_CMD_START_PREVIEW:
-        marucam_device_start_preview(state);
-        break;
-    case MARUCAM_CMD_STOP_PREVIEW:
-        marucam_device_stop_preview(state);
-        memset(state->vaddr, 0, MARUCAM_MEM_SIZE);
-        break;
-    case MARUCAM_CMD_S_PARAM:
-        marucam_device_s_param(state);
-        break;
-    case MARUCAM_CMD_G_PARAM:
-        marucam_device_g_param(state);
-        break;
-    case MARUCAM_CMD_ENUM_FMT:
-        marucam_device_enum_fmt(state);
-        break;
-    case MARUCAM_CMD_TRY_FMT:
-        marucam_device_try_fmt(state);
-        break;
-    case MARUCAM_CMD_S_FMT:
-        marucam_device_s_fmt(state);
-        break;
-    case MARUCAM_CMD_G_FMT:
-        marucam_device_g_fmt(state);
-        break;
-    case MARUCAM_CMD_QCTRL:
-        marucam_device_qctrl(state);
-        break;
-    case MARUCAM_CMD_S_CTRL:
-        marucam_device_s_ctrl(state);
-        break;
-    case MARUCAM_CMD_G_CTRL:
-        marucam_device_g_ctrl(state);
-        break;
-    case MARUCAM_CMD_ENUM_FSIZES:
-        marucam_device_enum_fsizes(state);
-        break;
-    case MARUCAM_CMD_ENUM_FINTV:
-        marucam_device_enum_fintv(state);
-        break;
-    case MARUCAM_CMD_S_DATA:
-        state->param->stack[state->param->top++] = value;
-        break;
-    case MARUCAM_CMD_DATACLR:
-        memset(state->param, 0, sizeof(MaruCamParam));
-        break;
-    case MARUCAM_CMD_REQFRAME:
-        qemu_mutex_lock(&state->thread_mutex);
-        state->req_frame = value + 1;
-        qemu_mutex_unlock(&state->thread_mutex);
-        break;
-    default:
-        ERR("Not supported command: 0x%x\n", offset);
-        break;
-    }
-}
-
-static const MemoryRegionOps maru_camera_mmio_ops = {
-    .old_mmio = {
-        .read = {
-            marucam_mmio_read,
-            marucam_mmio_read,
-            marucam_mmio_read,
-        },
-        .write = {
-            marucam_mmio_write,
-            marucam_mmio_write,
-            marucam_mmio_write,
-        },
-    },
-    .endianness = DEVICE_LITTLE_ENDIAN,
-};
-
-/*
- *  QEMU bottom half funtion
- */
-static void marucam_tx_bh(void *opaque)
-{
-    MaruCamState *state = (MaruCamState *)opaque;
-
-    qemu_mutex_lock(&state->thread_mutex);
-    if (state->isr) {
-        pci_set_irq(&state->dev, 1);
-    }
-    qemu_mutex_unlock(&state->thread_mutex);
-}
-
-/*
- *  Initialization function
- */
-
-static int marucam_initfn(PCIDevice *dev)
-{
-    MaruCamState *s = DO_UPCAST(MaruCamState, dev, dev);
-    uint8_t *pci_conf = s->dev.config;
-
-    /* Check available webcam
-     * If there is not one, you can't use the camera.
-     */
-    if (!marucam_device_check(1)) {
-        s->initialized = false;
-        ERR("Failed to check the camera device, "
-            "You can *not* use the camera\n");
-        return 0;
-    }
-
-    pci_config_set_interrupt_pin(pci_conf, 0x03);
-
-    memory_region_init_ram(&s->vram, OBJECT(s), "marucamera.ram", MARUCAM_MEM_SIZE,
-                            &error_abort);
-    s->vaddr = memory_region_get_ram_ptr(&s->vram);
-    memset(s->vaddr, 0, MARUCAM_MEM_SIZE);
-
-    memory_region_init_io(&s->mmio, OBJECT(s),
-                          &maru_camera_mmio_ops,
-                          s,
-                          "maru-camera-mmio",
-                          MARUCAM_REG_SIZE);
-
-    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
-    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio);
-
-    /* for worker thread */
-    s->param = (MaruCamParam *)g_malloc0(sizeof(MaruCamParam));
-    qemu_cond_init(&s->thread_cond);
-    qemu_mutex_init(&s->thread_mutex);
-
-    marucam_device_init(s);
-
-    s->tx_bh = qemu_bh_new(marucam_tx_bh, s);
-    s->initialized = true;
-    INFO("initialize maru-camera device\n");
-
-    return 0;
-}
-
-/*
- *  Termination function
- */
-static void marucam_exitfn(PCIDevice *pci_dev)
-{
-    MaruCamState *s =
-        OBJECT_CHECK(MaruCamState, pci_dev, MARU_PCI_CAMERA_DEVICE_NAME);
-
-    if (s->initialized) {
-        marucam_device_exit(s);
-        g_free(s->param);
-        qemu_cond_destroy(&s->thread_cond);
-        qemu_mutex_destroy(&s->thread_mutex);
-    }
-
-    INFO("finalize maru-camera device\n");
-}
-
-static void marucam_resetfn(DeviceState *d)
-{
-    MaruCamState *s = (MaruCamState *)d;
-
-    if (s->initialized) {
-        marucam_device_close(s);
-        qemu_mutex_lock(&s->thread_mutex);
-        s->isr = s->streamon = s->req_frame = s->buf_size = 0;
-        qemu_mutex_unlock(&s->thread_mutex);
-        memset(s->vaddr, 0, MARUCAM_MEM_SIZE);
-        memset(s->param, 0x00, sizeof(MaruCamParam));
-        INFO("reset maru-camera device\n");
-    }
-}
-
-int maru_camera_pci_init(PCIBus *bus)
-{
-    pci_create_simple(bus, -1, MARU_PCI_CAMERA_DEVICE_NAME);
-    return 0;
-}
-
-static void maru_camera_pci_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = marucam_initfn;
-    k->exit = marucam_exitfn;
-    k->vendor_id = PCI_VENDOR_ID_TIZEN;
-    k->device_id = PCI_DEVICE_ID_VIRTUAL_CAMERA;
-    k->class_id = PCI_CLASS_OTHERS;
-    dc->reset = marucam_resetfn;
-    dc->desc = "MARU Virtual Camera device for Tizen emulator";
-}
-
-static TypeInfo maru_camera_info = {
-    .name          = MARU_PCI_CAMERA_DEVICE_NAME,
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(MaruCamState),
-    .class_init    = maru_camera_pci_class_init,
-};
-
-static void maru_camera_pci_register_types(void)
-{
-    type_register_static(&maru_camera_info);
-}
-
-type_init(maru_camera_pci_register_types)
diff --git a/tizen/src/hw/pci/maru_camera_convert.c b/tizen/src/hw/pci/maru_camera_convert.c
new file mode 100644 (file)
index 0000000..8be52ce
--- /dev/null
@@ -0,0 +1,663 @@
+/*
+ * Implementation of color conversion for MARU Virtual Camera device.
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ * Jun Tian <jun.j.tian@intel.com>
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#include "qemu-common.h"
+#include "maru_camera_convert.h"
+#include "debug_ch.h"
+
+MULTI_DEBUG_CHANNEL(tizen, camera);
+
+static void UYVYToYUV420(unsigned char *bufsrc, unsigned char *bufdest,
+                         uint32_t width, uint32_t height);
+static void YVU420ToYUV420(unsigned char *bufsrc, unsigned char *bufdest,
+                           uint32_t width, uint32_t height);
+static void YUYVToYUV420(unsigned char *bufsrc, unsigned char *bufdest,
+                         uint32_t width, uint32_t height);
+
+static void yuyv_to_yuv420(const unsigned char *src, unsigned char *dest,
+        uint32_t width, uint32_t height, uint32_t yvu);
+static void rgb24_to_yuv420(const unsigned char *src, unsigned char *dest,
+        uint32_t width, uint32_t height, uint32_t yvu);
+static void rgb24_to_yuyv(unsigned char *src, unsigned char *dest,
+        uint32_t width, uint32_t height);
+static void yuv420_to_yvu420(unsigned char *src, unsigned char *dest,
+        uint32_t width, uint32_t height);
+static void yuv420_to_yuyv(unsigned char *src, unsigned char *dest,
+        uint32_t width, uint32_t height);
+
+/* Convert pixel format to YUV420 */
+uint8_t convert_frame(uint32_t src_format, uint32_t dst_format,
+                    uint32_t width, uint32_t height, size_t frame_size,
+                    void *src_buf, void *dst_buf)
+{
+    switch (src_format) {
+    case V4L2_PIX_FMT_YUV420:
+        switch (dst_format) {
+        case V4L2_PIX_FMT_YUV420:
+            memcpy(dst_buf, (void *)src_buf, (size_t)frame_size);
+            break;
+        case V4L2_PIX_FMT_YVU420:
+            yuv420_to_yvu420(src_buf, dst_buf, width, height);
+            break;
+        case V4L2_PIX_FMT_YUYV:
+            yuv420_to_yuyv(src_buf, dst_buf, width, height);
+            break;
+        default:
+            ERR("Cannot convert from the pixel format (%.4s)...\n",
+                (const char *)&src_format);
+            return 1;
+        }
+        break;
+    case V4L2_PIX_FMT_YVU420:
+        switch (dst_format) {
+        case V4L2_PIX_FMT_YUV420:
+            YVU420ToYUV420(src_buf, dst_buf, width, height);
+            break;
+        default:
+            ERR("Cannot convert from the pixel format (%.4s)...\n",
+                (const char *)&src_format);
+            return 1;
+        }
+        break;
+    case V4L2_PIX_FMT_YUYV:
+        switch (dst_format) {
+        case V4L2_PIX_FMT_YUV420:
+            //YUYVToYUV420(src_buf, dst_buf, width, height);
+            yuyv_to_yuv420(src_buf, dst_buf, width, height, 0);
+            break;
+        case V4L2_PIX_FMT_YVU420:
+            yuyv_to_yuv420(src_buf, dst_buf, width, height, 1);
+            break;
+        case V4L2_PIX_FMT_YUYV:
+            memcpy(dst_buf, (void *)src_buf, (size_t)frame_size);
+            break;
+        default:
+            ERR("Cannot convert from the pixel format (%.4s)...\n",
+                (const char *)&src_format);
+            return 1;
+        }
+        break;
+    case V4L2_PIX_FMT_UYVY: /* Mac default format */
+        switch (dst_format) {
+        case V4L2_PIX_FMT_YUV420:
+            UYVYToYUV420(src_buf, dst_buf, width, height);
+            break;
+        default:
+            ERR("Cannot convert from the pixel format (%.4s)...\n",
+                (const char *)&src_format);
+            return 1;
+        }
+        break;
+   case V4L2_PIX_FMT_RGB24:
+        switch (dst_format) {
+        case V4L2_PIX_FMT_YUV420:
+            rgb24_to_yuv420(src_buf, dst_buf, width, height, 0);
+            break;
+        case V4L2_PIX_FMT_YVU420:
+            rgb24_to_yuv420(src_buf, dst_buf, width, height, 1);
+            break;
+        case V4L2_PIX_FMT_YUYV:
+            rgb24_to_yuyv(src_buf, dst_buf, width, height);
+            break;
+        default:
+            ERR("Cannot convert from the pixel format (%.4s)...\n",
+                (const char *)&src_format);
+            return 1;
+        }
+        break;
+    default:
+        ERR("Cannot convert from the pixel format (%.4s)...\n",
+               (const char *)&src_format);
+        return 1;
+    }
+
+    return 0;
+}
+
+static void UYVYToYUV420(unsigned char *bufsrc, unsigned char *bufdest,
+                         uint32_t width, uint32_t height)
+{
+    uint32_t i, j;
+
+    /* Source */
+    unsigned char *ptrsrcy1, *ptrsrcy2;
+    unsigned char *ptrsrcy3, *ptrsrcy4;
+    unsigned char *ptrsrccb1;
+    unsigned char *ptrsrccb3;
+    unsigned char *ptrsrccr1;
+    unsigned char *ptrsrccr3;
+    uint32_t srcystride, srcccstride;
+
+    ptrsrcy1  = bufsrc + 1;
+    ptrsrcy2  = bufsrc + (width << 1) + 1;
+    ptrsrcy3  = bufsrc + (width << 1) * 2 + 1;
+    ptrsrcy4  = bufsrc + (width << 1) * 3 + 1;
+
+    ptrsrccb1 = bufsrc;
+    ptrsrccb3 = bufsrc + (width << 1) * 2;
+
+    ptrsrccr1 = bufsrc + 2;
+    ptrsrccr3 = bufsrc + (width << 1) * 2 + 2;
+
+    srcystride  = (width << 1) * 3;
+    srcccstride = (width << 1) * 3;
+
+    /* Destination */
+    unsigned char *ptrdesty1, *ptrdesty2;
+    unsigned char *ptrdesty3, *ptrdesty4;
+    unsigned char *ptrdestcb1, *ptrdestcb2;
+    unsigned char *ptrdestcr1, *ptrdestcr2;
+    uint32_t destystride, destccstride;
+
+    ptrdesty1 = bufdest;
+    ptrdesty2 = bufdest + width;
+    ptrdesty3 = bufdest + width * 2;
+    ptrdesty4 = bufdest + width * 3;
+
+    ptrdestcb1 = bufdest + width * height;
+    ptrdestcb2 = bufdest + width * height + (width >> 1);
+
+    ptrdestcr1 = bufdest + width * height + ((width*height) >> 2);
+    ptrdestcr2 = bufdest + width * height + ((width*height) >> 2)
+                 + (width >> 1);
+
+    destystride  = (width)*3;
+    destccstride = (width>>1);
+
+    for (j = 0; j < (height / 4); j++) {
+        for (i = 0; i < (width / 2); i++) {
+            (*ptrdesty1++) = (*ptrsrcy1);
+            (*ptrdesty2++) = (*ptrsrcy2);
+            (*ptrdesty3++) = (*ptrsrcy3);
+            (*ptrdesty4++) = (*ptrsrcy4);
+
+            ptrsrcy1 += 2;
+            ptrsrcy2 += 2;
+            ptrsrcy3 += 2;
+            ptrsrcy4 += 2;
+
+            (*ptrdesty1++) = (*ptrsrcy1);
+            (*ptrdesty2++) = (*ptrsrcy2);
+            (*ptrdesty3++) = (*ptrsrcy3);
+            (*ptrdesty4++) = (*ptrsrcy4);
+
+            ptrsrcy1 += 2;
+            ptrsrcy2 += 2;
+            ptrsrcy3 += 2;
+            ptrsrcy4 += 2;
+
+            (*ptrdestcb1++) = (*ptrsrccb1);
+            (*ptrdestcb2++) = (*ptrsrccb3);
+
+            ptrsrccb1 += 4;
+            ptrsrccb3 += 4;
+
+            (*ptrdestcr1++) = (*ptrsrccr1);
+            (*ptrdestcr2++) = (*ptrsrccr3);
+
+            ptrsrccr1 += 4;
+            ptrsrccr3 += 4;
+
+        }
+
+        /* Update src pointers */
+        ptrsrcy1  += srcystride;
+        ptrsrcy2  += srcystride;
+        ptrsrcy3  += srcystride;
+        ptrsrcy4  += srcystride;
+
+        ptrsrccb1 += srcccstride;
+        ptrsrccb3 += srcccstride;
+
+        ptrsrccr1 += srcccstride;
+        ptrsrccr3 += srcccstride;
+
+        /* Update dest pointers */
+        ptrdesty1 += destystride;
+        ptrdesty2 += destystride;
+        ptrdesty3 += destystride;
+        ptrdesty4 += destystride;
+
+        ptrdestcb1 += destccstride;
+        ptrdestcb2 += destccstride;
+
+        ptrdestcr1 += destccstride;
+        ptrdestcr2 += destccstride;
+    }
+}
+
+static void YVU420ToYUV420(unsigned char *bufsrc, unsigned char *bufdest,
+                           uint32_t width, uint32_t height)
+{
+    uint32_t i, j;
+
+    /* Source*/
+    unsigned char *ptrsrcy1, *ptrsrcy2;
+    unsigned char *ptrsrcy3, *ptrsrcy4;
+    unsigned char *ptrsrccb1, *ptrsrccb2;
+    unsigned char *ptrsrccr1, *ptrsrccr2;
+    uint32_t srcystride, srcccstride;
+
+    ptrsrcy1 = bufsrc;
+    ptrsrcy2 = bufsrc + width;
+    ptrsrcy3 = bufsrc + width*2;
+    ptrsrcy4 = bufsrc + width*3;
+
+    ptrsrccr1 = bufsrc + width*height;
+    ptrsrccr2 = bufsrc + width*height + (width>>1);
+
+    ptrsrccb1 = bufsrc + width*height + ((width*height) >> 2);
+    ptrsrccb2 = bufsrc + width*height + ((width*height) >> 2) + (width>>1);
+
+    srcystride  = (width)*3;
+    srcccstride = (width>>1);
+
+    /* Destination */
+    unsigned char *ptrdesty1, *ptrdesty2;
+    unsigned char *ptrdesty3, *ptrdesty4;
+    unsigned char *ptrdestcb1, *ptrdestcb2;
+    unsigned char *ptrdestcr1, *ptrdestcr2;
+    uint32_t destystride, destccstride;
+
+    ptrdesty1 = bufdest;
+    ptrdesty2 = bufdest + width;
+    ptrdesty3 = bufdest + width * 2;
+    ptrdesty4 = bufdest + width * 3;
+
+    ptrdestcb1 = bufdest + width * height;
+    ptrdestcb2 = bufdest + width * height + (width >> 1);
+
+    ptrdestcr1 = bufdest + width * height + ((width*height) >> 2);
+    ptrdestcr2 = bufdest + width * height + ((width*height) >> 2)
+                 + (width >> 1);
+
+    destystride  = (width)*3;
+    destccstride = (width>>1);
+
+    for (j = 0; j < (height / 4); j++) {
+        for (i = 0; i < (width / 2); i++) {
+
+            (*ptrdesty1++) = (*ptrsrcy1++);
+            (*ptrdesty2++) = (*ptrsrcy2++);
+            (*ptrdesty3++) = (*ptrsrcy3++);
+            (*ptrdesty4++) = (*ptrsrcy4++);
+            (*ptrdesty1++) = (*ptrsrcy1++);
+            (*ptrdesty2++) = (*ptrsrcy2++);
+            (*ptrdesty3++) = (*ptrsrcy3++);
+            (*ptrdesty4++) = (*ptrsrcy4++);
+
+            (*ptrdestcb1++) = (*ptrsrccb1++);
+            (*ptrdestcr1++) = (*ptrsrccr1++);
+            (*ptrdestcb2++) = (*ptrsrccb2++);
+            (*ptrdestcr2++) = (*ptrsrccr2++);
+
+        }
+
+        /* Update src pointers */
+        ptrsrcy1  += srcystride;
+        ptrsrcy2  += srcystride;
+        ptrsrcy3  += srcystride;
+        ptrsrcy4  += srcystride;
+
+        ptrsrccb1 += srcccstride;
+        ptrsrccb2 += srcccstride;
+
+        ptrsrccr1 += srcccstride;
+        ptrsrccr2 += srcccstride;
+
+        /* Update dest pointers */
+        ptrdesty1 += destystride;
+        ptrdesty2 += destystride;
+        ptrdesty3 += destystride;
+        ptrdesty4 += destystride;
+
+        ptrdestcb1 += destccstride;
+        ptrdestcb2 += destccstride;
+
+        ptrdestcr1 += destccstride;
+        ptrdestcr2 += destccstride;
+
+    }
+
+}
+
+static void YUYVToYUV420(unsigned char *bufsrc, unsigned char *bufdest,
+                         uint32_t width, uint32_t height)
+{
+    uint32_t i, j;
+
+    /* Source*/
+    unsigned char *ptrsrcy1, *ptrsrcy2;
+    unsigned char *ptrsrcy3, *ptrsrcy4;
+    unsigned char *ptrsrccb1;
+    unsigned char *ptrsrccb3;
+    unsigned char *ptrsrccr1;
+    unsigned char *ptrsrccr3;
+    uint32_t srcystride, srcccstride;
+
+    ptrsrcy1  = bufsrc ;
+    ptrsrcy2  = bufsrc + (width << 1);
+    ptrsrcy3  = bufsrc + (width << 1) * 2;
+    ptrsrcy4  = bufsrc + (width << 1) * 3;
+
+    ptrsrccb1 = bufsrc + 1;
+    ptrsrccb3 = bufsrc + (width << 1) * 2 + 1;
+
+    ptrsrccr1 = bufsrc + 3;
+    ptrsrccr3 = bufsrc + (width << 1) * 2 + 3;
+
+    srcystride  = (width << 1) * 3;
+    srcccstride = (width << 1) * 3;
+
+    /* Destination */
+    unsigned char *ptrdesty1, *ptrdesty2;
+    unsigned char *ptrdesty3, *ptrdesty4;
+    unsigned char *ptrdestcb1, *ptrdestcb2;
+    unsigned char *ptrdestcr1, *ptrdestcr2;
+    uint32_t destystride, destccstride;
+
+    ptrdesty1 = bufdest;
+    ptrdesty2 = bufdest + width;
+    ptrdesty3 = bufdest + width * 2;
+    ptrdesty4 = bufdest + width * 3;
+
+    ptrdestcb1 = bufdest + width * height;
+    ptrdestcb2 = bufdest + width * height + (width >> 1);
+
+    ptrdestcr1 = bufdest + width * height + ((width * height) >> 2);
+    ptrdestcr2 = bufdest + width * height + ((width * height) >> 2)
+                 + (width >> 1);
+
+    destystride  = width * 3;
+    destccstride = (width >> 1);
+
+    for (j = 0; j < (height / 4); j++) {
+        for (i = 0; i < (width / 2); i++) {
+            (*ptrdesty1++) = (*ptrsrcy1);
+            (*ptrdesty2++) = (*ptrsrcy2);
+            (*ptrdesty3++) = (*ptrsrcy3);
+            (*ptrdesty4++) = (*ptrsrcy4);
+
+            ptrsrcy1 += 2;
+            ptrsrcy2 += 2;
+            ptrsrcy3 += 2;
+            ptrsrcy4 += 2;
+
+            (*ptrdesty1++) = (*ptrsrcy1);
+            (*ptrdesty2++) = (*ptrsrcy2);
+            (*ptrdesty3++) = (*ptrsrcy3);
+            (*ptrdesty4++) = (*ptrsrcy4);
+
+            ptrsrcy1 += 2;
+            ptrsrcy2 += 2;
+            ptrsrcy3 += 2;
+            ptrsrcy4 += 2;
+
+            (*ptrdestcb1++) = (*ptrsrccb1);
+            (*ptrdestcb2++) = (*ptrsrccb3);
+
+            ptrsrccb1 += 4;
+            ptrsrccb3 += 4;
+
+            (*ptrdestcr1++) = (*ptrsrccr1);
+            (*ptrdestcr2++) = (*ptrsrccr3);
+
+            ptrsrccr1 += 4;
+            ptrsrccr3 += 4;
+
+        }
+
+        /* Update src pointers */
+        ptrsrcy1  += srcystride;
+        ptrsrcy2  += srcystride;
+        ptrsrcy3  += srcystride;
+        ptrsrcy4  += srcystride;
+
+        ptrsrccb1 += srcccstride;
+        ptrsrccb3 += srcccstride;
+
+        ptrsrccr1 += srcccstride;
+        ptrsrccr3 += srcccstride;
+
+        /* Update dest pointers */
+        ptrdesty1 += destystride;
+        ptrdesty2 += destystride;
+        ptrdesty3 += destystride;
+        ptrdesty4 += destystride;
+
+        ptrdestcb1 += destccstride;
+        ptrdestcb2 += destccstride;
+
+        ptrdestcr1 += destccstride;
+        ptrdestcr2 += destccstride;
+    }
+}
+
+static void yuyv_to_yuv420(const unsigned char *src, unsigned char *dest,
+                           uint32_t width, uint32_t height, uint32_t yvu)
+{
+    uint32_t i, j;
+    const unsigned char *src1;
+    unsigned char *udest, *vdest;
+
+    /* copy the Y values */
+    src1 = src;
+    for (i = 0; i < height; i++) {
+        for (j = 0; j < width; j += 2) {
+            *dest++ = src1[0];
+            *dest++ = src1[2];
+            src1 += 4;
+        }
+    }
+
+    /* copy the U and V values */
+    src++;              /* point to V */
+    src1 = src + width * 2;     /* next line */
+    if (yvu) {
+        vdest = dest;
+        udest = dest + width * height / 4;
+    } else {
+        udest = dest;
+        vdest = dest + width * height / 4;
+    }
+    for (i = 0; i < height; i += 2) {
+        for (j = 0; j < width; j += 2) {
+            *udest++ = ((int) src[0] + src1[0]) / 2;    /* U */
+            *vdest++ = ((int) src[2] + src1[2]) / 2;    /* V */
+            src += 4;
+            src1 += 4;
+        }
+        src = src1;
+        src1 += width * 2;
+    }
+}
+
+#define RGB2Y(r, g, b, y)   \
+    (y) = ((8453 * (r) + 16594 * (g) + 3223 * (b) + 524288) >> 15)
+
+#define RGB2UV(r, g, b, u, v)   \
+    do {    \
+        (u) = ((-4878 * (r) - 9578 * (g) + 14456 * (b) + 4210688) >> 15);   \
+        (v) = ((14456 * (r) - 12105 * (g) - 2351 * (b) + 4210688) >> 15);   \
+    } while (0)
+
+#define CLIP(color) \
+    (unsigned char)(((color) > 0xFF) ? 0xff : (((color) < 0) ? 0 : (color)))
+
+static void rgb24_to_yuv420(const unsigned char *src, unsigned char *dest,
+                            uint32_t width, uint32_t height, uint32_t yvu)
+{
+    uint32_t x, y;
+    uint32_t halfWidth;
+    uint8_t *yplane, *uplane, *vplane;
+    uint8_t *yline, *uline, *vline;
+    const uint8_t *rgbIndex;
+
+    halfWidth = width >> 1;
+    yplane = dest;
+
+    if (yvu) {
+        vplane = dest + width * height;
+        uplane = vplane + ((width * height) >> 2);
+    } else {
+        uplane = dest + width * height;
+        vplane = uplane + ((width * height) >> 2);
+    }
+
+    for (y = 0; y < height; y++) {
+        yline = yplane + (y * width);
+        uline = uplane + ((y >> 1) * halfWidth);
+        vline = vplane + ((y >> 1) * halfWidth);
+
+        rgbIndex = src + (width * (height - 1 - y) * 3);
+        for (x = 0; x < (int)width; x+=2) {
+            RGB2Y(rgbIndex[2], rgbIndex[1], rgbIndex[0], *yline++);
+            rgbIndex += 3;
+            RGB2Y(rgbIndex[2], rgbIndex[1], rgbIndex[0], *yline++);
+            RGB2UV(rgbIndex[2], rgbIndex[1], rgbIndex[0], *uline++, *vline++);
+            rgbIndex += 3;
+        }
+    }
+}
+
+static void rgb24_to_yuyv(unsigned char *src, unsigned char *dest,
+                          uint32_t width, uint32_t height)
+{
+    uint32_t i, j;
+    uint8_t *ptr;
+
+    for (i = 0; i < height; i++) {
+        ptr = src + (width * (height - 1 - i) * 3);
+        for (j = 0; j < width; j += 2) {
+            /* y */
+            *dest++ = CLIP(0.299 * (ptr[2] - 128) +
+                           0.587 * (ptr[1] - 128) +
+                           0.114 * (ptr[0] - 128) + 128);
+            /* u */
+            *dest++ = CLIP(((-0.147 * (ptr[2] - 128) -
+                           0.289 * (ptr[1] - 128) +
+                           0.436 * (ptr[0] - 128) + 128) +
+                           (-0.147 * (ptr[5] - 128) -
+                           0.289 * (ptr[4] - 128) +
+                           0.436 * (ptr[3] - 128) + 128)) / 2);
+            /* y1 */
+            *dest++ = CLIP(0.299 * (ptr[5] - 128) +
+                           0.587 * (ptr[4] - 128) +
+                           0.114 * (ptr[3] - 128) + 128);
+            /* v */
+            *dest++ = CLIP(((0.615 * (ptr[2] - 128) -
+                           0.515 * (ptr[1] - 128) -
+                           0.100 * (ptr[0] - 128) + 128) +
+                           (0.615 * (ptr[5] - 128) -
+                           0.515 * (ptr[4] - 128) -
+                           0.100 * (ptr[3] - 128) + 128)) / 2);
+            ptr += 6;
+        }
+    }
+}
+
+static void yuv420_to_yvu420(unsigned char *src, unsigned char *dest,
+                             uint32_t width, uint32_t height)
+{
+    unsigned char *psrc_y, *pdst_y;
+    unsigned char *psrc_u, *pdst_u;
+    unsigned char *psrc_v, *pdst_v;
+
+    psrc_y = src;
+    psrc_u = psrc_y + (width * height);
+    psrc_v = psrc_u + (width * height / 4);
+
+    pdst_y = dest;
+    pdst_v = pdst_y + (width * height);
+    pdst_u = pdst_v + (width * height / 4);
+
+    memcpy(pdst_y, psrc_y, width * height);
+    memcpy(pdst_v, psrc_v, width * height / 4);
+    memcpy(pdst_u, psrc_u, width * height / 4);
+}
+
+static void yuv420_to_yuyv(unsigned char *src, unsigned char *dest,
+                           uint32_t width, uint32_t height)
+{
+    unsigned char *py;
+    unsigned char *pu;
+    unsigned char *pv;
+
+    uint32_t linesize = width * 2;
+    uint32_t uvlinesize = width / 2;
+    uint32_t offset = 0;
+    uint32_t offset1 = 0;
+    uint32_t offsety = 0;
+    uint32_t offsety1 = 0;
+    uint32_t offsetuv = 0;
+    uint32_t h = 0;
+    uint32_t w = 0;
+    uint32_t wy = 0;
+    uint32_t huv = 0;
+    uint32_t wuv = 0;
+
+    py = src;
+    pu = py + (width * height);
+    pv = pu + (width * height / 4);
+
+    for (h = 0; h < height; h += 2) {
+        wy = 0;
+        wuv = 0;
+        offset = h * linesize;
+        offset1 = (h + 1) * linesize;
+        offsety = h * width;
+        offsety1 = (h + 1) * width;
+        offsetuv = huv * uvlinesize;
+
+        for (w = 0; w < linesize; w += 4) {
+            /* y00 */
+            dest[w + offset] = py[wy + offsety];
+            /* u0 */
+            dest[(w + 1) + offset] = pu[wuv + offsetuv];
+            /* y01 */
+            dest[(w + 2) + offset] = py[(wy + 1) + offsety];
+            /* v0 */
+            dest[(w + 3) + offset] = pv[wuv + offsetuv];
+
+            /* y10 */
+            dest[w + offset1] = py[wy + offsety1];
+            /* u0 */
+            dest[(w + 1) + offset1] = pu[wuv + offsetuv];
+            /* y11 */
+            dest[(w + 2) + offset1] = py[(wy + 1) + offsety1];
+            /* v0 */
+            dest[(w + 3) + offset1] = pv[wuv + offsetuv];
+
+            wuv++;
+            wy += 2;
+        }
+        huv++;
+    }
+}
diff --git a/tizen/src/hw/pci/maru_camera_convert.h b/tizen/src/hw/pci/maru_camera_convert.h
new file mode 100644 (file)
index 0000000..8252d7d
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Convert header of MARU Virtual Camera device.
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ * Jun Tian <jun.j.tian@intel.com>
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#ifndef _MARU_CAMERA_CONVERT_H_
+#define _MARU_CAMERA_CONVERT_H_
+
+#define MAKEFOURCC(a, b, c, d) \
+    (((uint32_t)(a) << 0) | \
+     ((uint32_t)(b) << 8) | \
+     ((uint32_t)(c) << 16) | \
+     ((uint32_t)(d) << 24))
+
+/* 16  RGB-5-5-5     */
+#define V4L2_PIX_FMT_RGB555  MAKEFOURCC('R', 'G', 'B', 'O')
+/* 16  RGB-5-6-5     */
+#define V4L2_PIX_FMT_RGB565  MAKEFOURCC('R', 'G', 'B', 'P')
+/* 16  RGB-5-5-5 BE  */
+#define V4L2_PIX_FMT_RGB555X MAKEFOURCC('R', 'G', 'B', 'Q')
+/* 16  RGB-5-6-5 BE  */
+#define V4L2_PIX_FMT_RGB565X MAKEFOURCC('R', 'G', 'B', 'R')
+/* 24  BGR-8-8-8     */
+#define V4L2_PIX_FMT_BGR24   MAKEFOURCC('B', 'G', 'R', '3')
+/* 24  RGB-8-8-8     */
+#define V4L2_PIX_FMT_RGB24   MAKEFOURCC('R', 'G', 'B', '3')
+/* 32  BGR-8-8-8-8   */
+#define V4L2_PIX_FMT_BGR32   MAKEFOURCC('B', 'G', 'R', '4')
+/* 32  RGB-8-8-8-8   */
+#define V4L2_PIX_FMT_RGB32   MAKEFOURCC('R', 'G', 'B', '4')
+/*  9  YVU 4:1:0     */
+#define V4L2_PIX_FMT_YVU410  MAKEFOURCC('Y', 'V', 'U', '9')
+/* 12  YVU 4:2:0     */
+#define V4L2_PIX_FMT_YVU420  MAKEFOURCC('Y', 'V', '1', '2')
+/* 16  YUV 4:2:2     */
+#define V4L2_PIX_FMT_YUYV    MAKEFOURCC('Y', 'U', 'Y', 'V')
+/* 16  YUV 4:2:2     */
+#define V4L2_PIX_FMT_UYVY    MAKEFOURCC('U', 'Y', 'V', 'Y')
+/* 16  YVU422 planar */
+#define V4L2_PIX_FMT_YUV422P MAKEFOURCC('4', '2', '2', 'P')
+/* 16  YVU411 planar */
+#define V4L2_PIX_FMT_YUV411P MAKEFOURCC('4', '1', '1', 'P')
+/* 12  YUV 4:1:1     */
+#define V4L2_PIX_FMT_Y41P    MAKEFOURCC('Y', '4', '1', 'P')
+/* 16  xxxxyyyy uuuuvvvv */
+#define V4L2_PIX_FMT_YUV444  MAKEFOURCC('Y', '4', '4', '4')
+/* 16  YUV-5-5-5     */
+#define V4L2_PIX_FMT_YUV555  MAKEFOURCC('Y', 'U', 'V', 'O')
+/* 16  YUV-5-6-5     */
+#define V4L2_PIX_FMT_YUV565  MAKEFOURCC('Y', 'U', 'V', 'P')
+/* 32  YUV-8-8-8-8   */
+#define V4L2_PIX_FMT_YUV32   MAKEFOURCC('Y', 'U', 'V', '4')
+/*  9  YUV 4:1:0     */
+#define V4L2_PIX_FMT_YUV410  MAKEFOURCC('Y', 'U', 'V', '9')
+/* 12  YUV 4:2:0     */
+#define V4L2_PIX_FMT_YUV420  MAKEFOURCC('Y', 'U', '1', '2')
+/* 16  YUV 4:2:2     */
+#define V4L2_PIX_FMT_YYUV    MAKEFOURCC('Y', 'Y', 'U', 'V')
+
+/* V4L2 defines copy from videodev2.h */
+#define V4L2_CTRL_FLAG_SLIDER       0x0020
+
+#define V4L2_CTRL_CLASS_USER        0x00980000
+#define V4L2_CID_BASE               (V4L2_CTRL_CLASS_USER | 0x900)
+#define V4L2_CID_BRIGHTNESS         (V4L2_CID_BASE + 0)
+#define V4L2_CID_CONTRAST           (V4L2_CID_BASE + 1)
+#define V4L2_CID_SATURATION         (V4L2_CID_BASE + 2)
+#define V4L2_CID_SHARPNESS          (V4L2_CID_BASE + 27)
+
+inline uint32_t get_bytesperline(uint32_t pixfmt, uint32_t width)
+{
+    uint32_t bytesperline;
+
+    switch (pixfmt) {
+    case V4L2_PIX_FMT_YUV420:
+    case V4L2_PIX_FMT_YVU420:
+        bytesperline = (width * 12) >> 3;
+        break;
+    case V4L2_PIX_FMT_YUYV:
+    default:
+        bytesperline = width * 2;
+        break;
+    }
+
+    return bytesperline;
+}
+
+inline uint32_t get_sizeimage(uint32_t pixfmt, uint32_t width, uint32_t height)
+{
+    return get_bytesperline(pixfmt, width) * height;
+}
+
+uint8_t convert_frame(uint32_t src_format, uint32_t dst_format,
+                      uint32_t width, uint32_t height, size_t frame_size,
+                      void *src_buf, void *dst_buf)
+
+#endif /* _MARU_CAMERA_CONVERT_H_ */
diff --git a/tizen/src/hw/pci/maru_camera_darwin.h b/tizen/src/hw/pci/maru_camera_darwin.h
deleted file mode 100644 (file)
index 2ac39f9..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Header of MARU Virtual Camera device for MacOS.
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Contact:
- * Jun Tian <jun.j.tian@intel.com>
- * JinHyung Jo <jinhyung.jo@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-#ifndef _MARU_CAMERA_DARWIN_H_
-#define _MARU_CAMERA_DARWIN_H_
-
-#define MAKEFOURCC(a, b, c, d) \
-    (((uint32_t)(a) << 0) | \
-     ((uint32_t)(b) << 8) | \
-     ((uint32_t)(c) << 16) | \
-     ((uint32_t)(d) << 24))
-
-/* 16  RGB-5-5-5     */
-#define V4L2_PIX_FMT_RGB555  MAKEFOURCC('R', 'G', 'B', 'O')
-/* 16  RGB-5-6-5     */
-#define V4L2_PIX_FMT_RGB565  MAKEFOURCC('R', 'G', 'B', 'P')
-/* 16  RGB-5-5-5 BE  */
-#define V4L2_PIX_FMT_RGB555X MAKEFOURCC('R', 'G', 'B', 'Q')
-/* 16  RGB-5-6-5 BE  */
-#define V4L2_PIX_FMT_RGB565X MAKEFOURCC('R', 'G', 'B', 'R')
-/* 24  BGR-8-8-8     */
-#define V4L2_PIX_FMT_BGR24   MAKEFOURCC('B', 'G', 'R', '3')
-/* 24  RGB-8-8-8     */
-#define V4L2_PIX_FMT_RGB24   MAKEFOURCC('R', 'G', 'B', '3')
-/* 32  BGR-8-8-8-8   */
-#define V4L2_PIX_FMT_BGR32   MAKEFOURCC('B', 'G', 'R', '4')
-/* 32  RGB-8-8-8-8   */
-#define V4L2_PIX_FMT_RGB32   MAKEFOURCC('R', 'G', 'B', '4')
-/*  9  YVU 4:1:0     */
-#define V4L2_PIX_FMT_YVU410  MAKEFOURCC('Y', 'V', 'U', '9')
-/* 12  YVU 4:2:0     */
-#define V4L2_PIX_FMT_YVU420  MAKEFOURCC('Y', 'V', '1', '2')
-/* 16  YUV 4:2:2     */
-#define V4L2_PIX_FMT_YUYV    MAKEFOURCC('Y', 'U', 'Y', 'V')
-/* 16  YUV 4:2:2     */
-#define V4L2_PIX_FMT_UYVY    MAKEFOURCC('U', 'Y', 'V', 'Y')
-/* 16  YVU422 planar */
-#define V4L2_PIX_FMT_YUV422P MAKEFOURCC('4', '2', '2', 'P')
-/* 16  YVU411 planar */
-#define V4L2_PIX_FMT_YUV411P MAKEFOURCC('4', '1', '1', 'P')
-/* 12  YUV 4:1:1     */
-#define V4L2_PIX_FMT_Y41P    MAKEFOURCC('Y', '4', '1', 'P')
-/* 16  xxxxyyyy uuuuvvvv */
-#define V4L2_PIX_FMT_YUV444  MAKEFOURCC('Y', '4', '4', '4')
-/* 16  YUV-5-5-5     */
-#define V4L2_PIX_FMT_YUV555  MAKEFOURCC('Y', 'U', 'V', 'O')
-/* 16  YUV-5-6-5     */
-#define V4L2_PIX_FMT_YUV565  MAKEFOURCC('Y', 'U', 'V', 'P')
-/* 32  YUV-8-8-8-8   */
-#define V4L2_PIX_FMT_YUV32   MAKEFOURCC('Y', 'U', 'V', '4')
-/*  9  YUV 4:1:0     */
-#define V4L2_PIX_FMT_YUV410  MAKEFOURCC('Y', 'U', 'V', '9')
-/* 12  YUV 4:2:0     */
-#define V4L2_PIX_FMT_YUV420  MAKEFOURCC('Y', 'U', '1', '2')
-/* 16  YUV 4:2:2     */
-#define V4L2_PIX_FMT_YYUV    MAKEFOURCC('Y', 'Y', 'U', 'V')
-
-void convert_frame(uint32_t pixel_format, int frame_width, int frame_height,
-                   size_t frame_size, void *frame_pixels, void *video_buf);
-
-#endif /* _MARU_CAMERA_DARWIN_H_ */
diff --git a/tizen/src/hw/pci/maru_camera_darwin.m b/tizen/src/hw/pci/maru_camera_darwin.m
new file mode 100644 (file)
index 0000000..26f29af
--- /dev/null
@@ -0,0 +1,876 @@
+/*
+ * Implementation of MARU Virtual Camera device by PCI bus on MacOS.
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ * Jun Tian <jun.j.tian@intel.com>
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#import <Cocoa/Cocoa.h>
+#import <QTKit/QTKit.h>
+#import <CoreAudio/CoreAudio.h>
+
+#include <pthread.h>
+#include "qemu-common.h"
+#include "maru_camera.h"
+#include "maru_camera_convert.h"
+#include "debug_ch.h"
+
+MULTI_DEBUG_CHANNEL(tizen, camera);
+
+#define MARUCAM_THREAD_NAME    "marucam_worker_thread"
+
+typedef struct tagMaruCamConvertPixfmt {
+    uint32_t fmt;   /* fourcc */
+    uint32_t bpp;   /* bits per pixel, 0 for compressed formats */
+    uint32_t needs_conversion;
+} MaruCamConvertPixfmt;
+
+
+static MaruCamConvertPixfmt supported_dst_pixfmts[] = {
+    { V4L2_PIX_FMT_YUYV, 16, 0 },
+    { V4L2_PIX_FMT_UYVY, 16, 0 },
+    { V4L2_PIX_FMT_YUV420, 12, 0 },
+    { V4L2_PIX_FMT_YVU420, 12, 0 },
+};
+
+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 },
+};
+
+#define MARUCAM_CTRL_VALUE_MAX      20
+#define MARUCAM_CTRL_VALUE_MIN      1
+#define MARUCAM_CTRL_VALUE_MID      10
+#define MARUCAM_CTRL_VALUE_STEP     1
+
+enum {
+    _MC_THREAD_PAUSED,
+    _MC_THREAD_STREAMON,
+    _MC_THREAD_STREAMOFF,
+};
+
+#if 0
+struct marucam_qctrl {
+    uint32_t id;
+    uint32_t hit;
+    long min;
+    long max;
+    long step;
+    long init_val;
+};
+
+static struct marucam_qctrl qctrl_tbl[] = {
+    { V4L2_CID_BRIGHTNESS, 0, },
+    { V4L2_CID_CONTRAST, 0, },
+    { V4L2_CID_SATURATION, 0, },
+    { V4L2_CID_SHARPNESS, 0, },
+};
+#endif
+
+static MaruCamState *g_state;
+
+static uint32_t ready_count;
+static uint32_t cur_fmt_idx;
+static uint32_t cur_frame_idx;
+
+/***********************************
+ * Mac camera helper functions
+ ***********************************/
+
+/* Convert Core Video format to FOURCC */
+static uint32_t corevideo_to_fourcc(uint32_t cv_pix_fmt)
+{
+    switch (cv_pix_fmt) {
+    case kCVPixelFormatType_420YpCbCr8Planar:
+        return V4L2_PIX_FMT_YVU420;
+    case kCVPixelFormatType_422YpCbCr8:
+        return V4L2_PIX_FMT_UYVY;
+    case kCVPixelFormatType_422YpCbCr8_yuvs:
+        return V4L2_PIX_FMT_YUYV;
+    case kCVPixelFormatType_32ARGB:
+    case kCVPixelFormatType_32RGBA:
+        return V4L2_PIX_FMT_RGB32;
+    case kCVPixelFormatType_32BGRA:
+    case kCVPixelFormatType_32ABGR:
+        return V4L2_PIX_FMT_BGR32;
+    case kCVPixelFormatType_24RGB:
+        return V4L2_PIX_FMT_RGB24;
+    case kCVPixelFormatType_24BGR:
+        return V4L2_PIX_FMT_BGR32;
+    default:
+        ERR("Unknown pixel format '%.4s'", (const char *)&cv_pix_fmt);
+        return 0;
+    }
+}
+
+/******************************************************************
+ **   Maru Camera Implementation
+ *****************************************************************/
+
+@interface MaruCameraDriver : NSObject {
+    QTCaptureSession               *mCaptureSession;
+    QTCaptureDeviceInput           *mCaptureVideoDeviceInput;
+    QTCaptureVideoPreviewOutput    *mCaptureVideoPreviewOutput;
+
+    CVImageBufferRef               mCurrentImageBuffer;
+    BOOL mDeviceIsOpened;
+    BOOL mCaptureIsStarted;
+}
+
+- (MaruCameraDriver *)init;
+- (int)startCapture:(int)width :(int)height;
+- (void)stopCapture;
+- (int)readFrame:(void *)video_buf;
+- (int)setCaptureFormat:(int)width :(int)height :(int)pix_format;
+- (int)getCaptureFormat:(int)width :(int)height :(int)pix_format;
+- (BOOL)deviceStatus;
+
+@end
+
+@implementation MaruCameraDriver
+
+- (MaruCameraDriver *)init
+{
+    BOOL success = NO;
+    NSError *error;
+    mDeviceIsOpened = NO;
+    mCaptureIsStarted = NO;
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+    /* Create the capture session */
+    mCaptureSession = [[QTCaptureSession alloc] init];
+
+    /* Find a video device */
+    QTCaptureDevice *videoDevice = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeVideo];
+    success = [videoDevice open:&error];
+
+    /* If a video input device can't be found or opened, try to find and open a muxed input device */
+    if (!success) {
+        videoDevice = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeMuxed];
+        success = [videoDevice open:&error];
+        [pool release];
+        return nil;
+    }
+
+    if (!success) {
+        videoDevice = nil;
+        [pool release];
+        return nil;
+    }
+
+    if (videoDevice) {
+        /* Add the video device to the session as a device input */
+        mCaptureVideoDeviceInput = [[QTCaptureDeviceInput alloc] initWithDevice:videoDevice];
+        success = [mCaptureSession addInput:mCaptureVideoDeviceInput error:&error];
+
+        if (!success) {
+            [pool release];
+            return nil;
+        }
+
+        mCaptureVideoPreviewOutput = [[QTCaptureVideoPreviewOutput alloc] init];
+        success = [mCaptureSession addOutput:mCaptureVideoPreviewOutput error:&error];
+        if (!success) {
+            [pool release];
+            return nil;
+        }
+
+        mDeviceIsOpened = YES;
+        [mCaptureVideoPreviewOutput setDelegate:self];
+        INFO("Camera session bundling successfully!\n");
+        [pool release];
+        return self;
+    } else {
+        [pool release];
+        return nil;
+    }
+}
+
+- (int)startCapture:(int)width :(int)height
+{
+    int ret = -1;
+
+    if (![mCaptureSession isRunning]) {
+        /* Set width & height, using default pixel format to capture */
+        NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
+                                                      [NSNumber numberWithInt: width], (id)kCVPixelBufferWidthKey,
+                                                      [NSNumber numberWithInt: height], (id)kCVPixelBufferHeightKey,
+                                                 nil];
+        [mCaptureVideoPreviewOutput setPixelBufferAttributes:attributes];
+        [mCaptureSession startRunning];
+    } else {
+        ERR("Capture session is already running, exit\n");
+        return ret;
+    }
+
+    if ([mCaptureSession isRunning]) {
+        while(!mCaptureIsStarted) {
+            /* Wait Until Capture is started */
+            [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.5]];
+        }
+        ret = 0;
+    }
+    return ret;
+}
+
+- (void)stopCapture
+{
+    if ([mCaptureSession isRunning]) {
+        [mCaptureSession stopRunning];
+        while([mCaptureSession isRunning]) {
+            /* Wait Until Capture is stopped */
+            [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1]];
+        }
+
+    }
+    mCaptureIsStarted = NO;
+}
+
+- (int)readFrame:(void *)video_buf
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+    @synchronized (self) {
+        if (mCaptureIsStarted == NO) {
+            [pool release];
+            return 0;
+        }
+        if (mCurrentImageBuffer != nil) {
+            CVPixelBufferLockBaseAddress(mCurrentImageBuffer, 0);
+            const uint32_t pixel_format = corevideo_to_fourcc(CVPixelBufferGetPixelFormatType(mCurrentImageBuffer));
+            const int frame_width = CVPixelBufferGetWidth(mCurrentImageBuffer);
+            const int frame_height = CVPixelBufferGetHeight(mCurrentImageBuffer);
+            const size_t frame_size = CVPixelBufferGetBytesPerRow(mCurrentImageBuffer) * frame_height;
+            const void *frame_pixels = CVPixelBufferGetBaseAddress(mCurrentImageBuffer);
+            const uint32_t dst_format = supported_dst_pixfmts[cur_fmt_idx].fmt;
+
+            TRACE("buffer(%p), pixel_format(%d,%.4s), frame_width(%d), "
+                  "frame_height(%d), frame_size(%d)\n",
+                  mCurrentImageBuffer, (int)pixel_format,
+                  (const char *)&pixel_format, frame_width,
+                  frame_height, (int)frame_size);
+
+            /* convert frame to v4l2 format */
+            convert_frame(pixel_format, dst_format, frame_width, frame_height,
+                          frame_size, (void *)frame_pixels, video_buf);
+            CVPixelBufferUnlockBaseAddress(mCurrentImageBuffer, 0);
+            [pool release];
+            return 1;
+        }
+    }
+
+    [pool release];
+    return -1;
+}
+
+- (int)setCaptureFormat:(int)width :(int)height :(int)pix_format
+{
+    int ret = -1;
+    NSDictionary *attributes;
+
+    if (mCaptureSession == nil || mCaptureVideoPreviewOutput == nil) {
+        ERR("Capture session is not initiated.\n");
+        return ret;
+    }
+
+    /* Set the pixel buffer attributes before running the capture session */
+    if (![mCaptureSession isRunning]) {
+        if (pix_format) {
+            attributes = [NSDictionary dictionaryWithObjectsAndKeys:
+                                            [NSNumber numberWithInt: width], (id)kCVPixelBufferWidthKey,
+                                            [NSNumber numberWithInt: height], (id)kCVPixelBufferHeightKey,
+                                            [NSNumber numberWithInt: pix_format], (id)kCVPixelBufferPixelFormatTypeKey,
+                                       nil];
+        } else {
+            attributes = [NSDictionary dictionaryWithObjectsAndKeys:
+                                            [NSNumber numberWithInt: width], (id)kCVPixelBufferWidthKey,
+                                            [NSNumber numberWithInt: height], (id)kCVPixelBufferHeightKey,
+                                       nil];
+        }
+        [mCaptureVideoPreviewOutput setPixelBufferAttributes:attributes];
+        ret = 0;
+    } else {
+        ERR("Cannot set pixel buffer attributes when it's running.\n");
+        return ret;
+    }
+
+    return ret;
+}
+
+- (int)getCaptureFormat:(int)width :(int)height :(int)pix_format
+{
+    return 0;
+}
+
+/* Get the device bundling status */
+- (BOOL)deviceStatus
+{
+    return mDeviceIsOpened;
+}
+
+/* Handle deallocation of memory for your capture objects */
+
+- (void)dealloc
+{
+    [mCaptureSession release];
+    [mCaptureVideoDeviceInput release];
+    [mCaptureVideoPreviewOutput release];
+    [super dealloc];
+}
+
+/* Receive this method whenever the output decompresses and outputs a new video frame */
+- (void)captureOutput:(QTCaptureOutput *)captureOutput didOutputVideoFrame:(CVImageBufferRef)videoFrame
+     withSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection
+{
+    CVImageBufferRef imageBufferToRelease;
+    CVBufferRetain(videoFrame);
+
+    @synchronized (self)
+    {
+        imageBufferToRelease = mCurrentImageBuffer;
+        mCurrentImageBuffer = videoFrame;
+        mCaptureIsStarted = YES;
+    }
+    CVBufferRelease(imageBufferToRelease);
+}
+
+@end
+
+/******************************************************************
+ **   Maru Camera APIs
+ *****************************************************************/
+
+typedef struct MaruCameraDevice MaruCameraDevice;
+struct MaruCameraDevice {
+    /* Maru camera device object. */
+    MaruCameraDriver *driver;
+};
+
+/* Golbal representation of the Maru camera */
+MaruCameraDevice *mcd = NULL;
+
+static int is_streamon()
+{
+    int st;
+    qemu_mutex_lock(&g_state->thread_mutex);
+    st = g_state->streamon;
+    qemu_mutex_unlock(&g_state->thread_mutex);
+    return (st == _MC_THREAD_STREAMON);
+}
+
+static void __raise_err_intr()
+{
+    qemu_mutex_lock(&g_state->thread_mutex);
+    if (g_state->streamon == _MC_THREAD_STREAMON) {
+        g_state->req_frame = 0; /* clear request */
+        g_state->isr = 0x08;   /* set a error flag of rasing a interrupt */
+        qemu_bh_schedule(g_state->tx_bh);
+    }
+    qemu_mutex_unlock(&g_state->thread_mutex);
+}
+
+static int marucam_device_read_frame()
+{
+    int ret;
+    void *tmp_buf;
+
+    qemu_mutex_lock(&g_state->thread_mutex);
+    if (g_state->streamon == _MC_THREAD_STREAMON) {
+#if 0
+        if (ready_count < MARUCAM_SKIPFRAMES) {
+            /* skip a frame cause first some frame are distorted */
+            ++ready_count;
+            TRACE("Skip %d frame\n", ready_count);
+            qemu_mutex_unlock(&g_state->thread_mutex);
+            return 0;
+        }
+#endif
+        if (g_state->req_frame == 0) {
+            TRACE("There is no request\n");
+            qemu_mutex_unlock(&g_state->thread_mutex);
+            return 0;
+        }
+
+        /* Grab the camera frame into temp buffer */
+        tmp_buf = g_state->vaddr + g_state->buf_size * (g_state->req_frame - 1);
+        ret =  [mcd->driver readFrame: tmp_buf];
+        if (ret < 0) {
+            ERR("%s, Capture error\n", __func__);
+            qemu_mutex_unlock(&g_state->thread_mutex);
+            __raise_err_intr();
+            return -1;
+        } else if (!ret) {
+            qemu_mutex_unlock(&g_state->thread_mutex);
+            return 0;
+        }
+
+        g_state->req_frame = 0; /* clear request */
+        g_state->isr |= 0x01;   /* set a flag of rasing a interrupt */
+        qemu_bh_schedule(g_state->tx_bh);
+    } else {
+        qemu_mutex_unlock(&g_state->thread_mutex);
+        return -1;
+    }
+    qemu_mutex_unlock(&g_state->thread_mutex);
+    return 0;
+}
+
+/* Worker thread to grab frames to the preview window */
+static void *marucam_worker_thread(void *thread_param)
+{
+    while (1) {
+        qemu_mutex_lock(&g_state->thread_mutex);
+        g_state->streamon = _MC_THREAD_PAUSED;
+        qemu_cond_wait(&g_state->thread_cond, &g_state->thread_mutex);
+        qemu_mutex_unlock(&g_state->thread_mutex);
+
+        if (g_state->destroying) {
+            break;
+        }
+
+        ready_count = 0;
+        qemu_mutex_lock(&g_state->thread_mutex);
+        g_state->streamon = _MC_THREAD_STREAMON;
+        qemu_mutex_unlock(&g_state->thread_mutex);
+        INFO("Streaming on ......\n");
+
+        /* Loop: capture frame -> convert format -> render to screen */
+        while (1) {
+            if (is_streamon()) {
+                if (marucam_device_read_frame() < 0) {
+                    INFO("Streaming is off ...\n");
+                    break;
+                } else {
+                    /* wait until next frame is avalilable */
+                    usleep(22000);
+                }
+            } else {
+                INFO("Streaming is off ...\n");
+                break;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+int marucam_device_check(int log_flag)
+{
+    /* FIXME: check the device parameters */
+    INFO("Checking camera device\n");
+    return 1;
+}
+
+/**********************************************
+ * MARU camera routines
+ **********************************************/
+void marucam_device_init(MaruCamState *state)
+{
+    g_state = state;
+    g_state->destroying = false;
+    qemu_thread_create(&state->thread_id,
+                       MARUCAM_THREAD_NAME,
+                       marucam_worker_thread,
+                       NULL,
+                       QEMU_THREAD_JOINABLE);
+}
+
+void marucam_device_exit(MaruCamState *state)
+{
+    state->destroying = true;
+    qemu_mutex_lock(&state->thread_mutex);
+    qemu_cond_signal(&state->thread_cond);
+    qemu_mutex_unlock(&state->thread_mutex);
+    qemu_thread_join(&state->thread_id);
+}
+
+/* MARUCAM_CMD_OPEN */
+void marucam_device_open(MaruCamState *state)
+{
+    MaruCamParam *param = state->param;
+    param->top = 0;
+
+    mcd = (MaruCameraDevice *)malloc(sizeof(MaruCameraDevice));
+    if (mcd == NULL) {
+        ERR("%s: MaruCameraDevice allocate failed\n", __func__);
+        param->errCode = EINVAL;
+        return;
+    }
+    memset(mcd, 0, sizeof(MaruCameraDevice));
+    mcd->driver = [[MaruCameraDriver alloc] init];
+    if (mcd->driver == nil) {
+        ERR("Camera device open failed\n");
+        [mcd->driver dealloc];
+        free(mcd);
+        param->errCode = EINVAL;
+        return;
+    }
+    INFO("Camera opened!\n");
+}
+
+/* MARUCAM_CMD_CLOSE */
+void marucam_device_close(MaruCamState *state)
+{
+    MaruCamParam *param = state->param;
+    param->top = 0;
+
+    if (mcd != NULL) {
+        if (is_streamon()) {
+            marucam_device_stop_preview(state);
+        }
+        [mcd->driver dealloc];
+        free(mcd);
+        mcd = NULL;
+    }
+
+    /* marucam_reset_controls(); */
+    INFO("Camera closed\n");
+}
+
+/* MARUCAM_CMD_START_PREVIEW */
+void marucam_device_start_preview(MaruCamState *state)
+{
+    uint32_t width, height, pixfmt;
+    MaruCamParam *param = state->param;
+    param->top = 0;
+
+    width = supported_dst_frames[cur_frame_idx].width;
+    height = supported_dst_frames[cur_frame_idx].height;
+    pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
+    state->buf_size = get_sizeimage(pixfmt, width, height);
+
+    INFO("Pixfmt(%c%c%c%c), W:H(%d:%d), buf size(%u), frame idx(%d), fmt idx(%d)\n",
+      (char)(pixfmt), (char)(pixfmt >> 8),
+      (char)(pixfmt >> 16), (char)(pixfmt >> 24),
+      width, height, state->buf_size,
+      cur_frame_idx, cur_fmt_idx);
+
+    if (mcd->driver == nil) {
+        ERR("%s: Start capture failed: vaild device", __func__);
+        param->errCode = EINVAL;
+        return;
+    }
+
+    INFO("Starting preview ...\n");
+    [mcd->driver startCapture: width: height];
+
+    /* Enable the condition to capture frames now */
+    qemu_mutex_lock(&state->thread_mutex);
+    qemu_cond_signal(&state->thread_cond);
+    qemu_mutex_unlock(&state->thread_mutex);
+
+    while (!is_streamon()) {
+        usleep(10000);
+    }
+}
+
+/* MARUCAM_CMD_STOP_PREVIEW */
+void marucam_device_stop_preview(MaruCamState *state)
+{
+    MaruCamParam *param = state->param;
+    param->top = 0;
+
+    if (is_streamon()) {
+        qemu_mutex_lock(&state->thread_mutex);
+        state->streamon = _MC_THREAD_STREAMOFF;
+        qemu_mutex_unlock(&state->thread_mutex);
+
+        while (is_streamon()) {
+            usleep(10000);
+        }
+    }
+
+    if (mcd->driver != nil) {
+        [mcd->driver stopCapture];
+    }
+
+    state->buf_size = 0;
+    INFO("Stopping preview ...\n");
+}
+
+/* MARUCAM_CMD_S_PARAM */
+void marucam_device_s_param(MaruCamState *state)
+{
+    MaruCamParam *param = state->param;
+
+    /* We use default FPS of the webcam */
+    param->top = 0;
+}
+
+/* MARUCAM_CMD_G_PARAM */
+void marucam_device_g_param(MaruCamState *state)
+{
+    MaruCamParam *param = state->param;
+    /* 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 */
+}
+
+/* MARUCAM_CMD_S_FMT */
+void marucam_device_s_fmt(MaruCamState *state)
+{
+    MaruCamParam *param = state->param;
+    uint32_t width, height, pixfmt, pidx, fidx;
+
+    param->top = 0;
+    width = param->stack[0];
+    height = param->stack[1];
+    pixfmt = param->stack[2];
+
+    TRACE("Set format: width(%d), height(%d), pixfmt(%d, %.4s)\n",
+         width, height, pixfmt, (const char*)&pixfmt);
+
+    for (fidx = 0; fidx < ARRAY_SIZE(supported_dst_frames); fidx++) {
+        if ((supported_dst_frames[fidx].width == width) &&
+            (supported_dst_frames[fidx].height == height)) {
+            break;
+        }
+    }
+    if (fidx == ARRAY_SIZE(supported_dst_frames)) {
+        param->errCode = EINVAL;
+        return;
+    }
+
+    for (pidx = 0; pidx < ARRAY_SIZE(supported_dst_pixfmts); pidx++) {
+        if (supported_dst_pixfmts[pidx].fmt == pixfmt) {
+            TRACE("pixfmt index is match: %d\n", pidx);
+            break;
+        }
+    }
+    if (pidx == ARRAY_SIZE(supported_dst_pixfmts)) {
+        param->errCode = EINVAL;
+        return;
+    }
+
+    if ((supported_dst_frames[cur_frame_idx].width != width) &&
+        (supported_dst_frames[cur_frame_idx].height != height)) {
+        if (mcd->driver == nil || [mcd->driver setCaptureFormat: width: height: 0] < 0) {
+            ERR("Set pixel format failed\n");
+            param->errCode = EINVAL;
+            return;
+        }
+
+        TRACE("cur_frame_idx:%d, supported_dst_frames[cur_frame_idx].width:%d\n",
+             cur_frame_idx, supported_dst_frames[cur_frame_idx].width);
+    }
+
+    cur_frame_idx = fidx;
+    cur_fmt_idx = pidx;
+
+    pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
+    width = supported_dst_frames[cur_frame_idx].width;
+    height = supported_dst_frames[cur_frame_idx].height;
+
+    param->stack[0] = width;
+    param->stack[1] = height;
+    param->stack[2] = 1; /* V4L2_FIELD_NONE */
+    param->stack[3] = pixfmt;
+    param->stack[4] = get_bytesperline(pixfmt, width);
+    param->stack[5] = get_sizeimage(pixfmt, width, height);
+    param->stack[6] = 0;
+    param->stack[7] = 0;
+
+    TRACE("Set device pixel format ...\n");
+}
+
+/* MARUCAM_CMD_G_FMT */
+void marucam_device_g_fmt(MaruCamState *state)
+{
+    uint32_t width, height, pixfmt;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
+    width = supported_dst_frames[cur_frame_idx].width;
+    height = supported_dst_frames[cur_frame_idx].height;
+
+    param->stack[0] = width;
+    param->stack[1] = height;
+    param->stack[2] = 1; /* V4L2_FIELD_NONE */
+    param->stack[3] = pixfmt;
+    param->stack[4] = get_bytesperline(pixfmt, width);
+    param->stack[5] = get_sizeimage(pixfmt, width, height);
+    param->stack[6] = 0;
+    param->stack[7] = 0;
+
+    TRACE("Get device frame format ...\n");
+}
+
+void marucam_device_try_fmt(MaruCamState *state)
+{
+    TRACE("Try device frame format, use default setting ...\n");
+}
+
+/* Get specific pixelformat description */
+void marucam_device_enum_fmt(MaruCamState *state)
+{
+    uint32_t index;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    index = param->stack[0];
+
+    if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {
+        param->errCode = EINVAL;
+        return;
+    }
+    param->stack[1] = 0; /* flags = NONE */
+    param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */
+    switch (supported_dst_pixfmts[index].fmt) {
+    case V4L2_PIX_FMT_YUYV:
+        memcpy(&param->stack[3], "YUYV", 32);
+        break;
+    case V4L2_PIX_FMT_UYVY:
+        memcpy(&param->stack[3], "UYVY", 32);
+        break;
+    case V4L2_PIX_FMT_YUV420:
+        memcpy(&param->stack[3], "YU12", 32);
+        break;
+    case V4L2_PIX_FMT_YVU420:
+        memcpy(&param->stack[3], "YV12", 32);
+        break;
+    default:
+        param->errCode = EINVAL;
+        break;
+    }
+}
+
+/*
+ * QTKit don't support setting brightness, contrast, saturation & sharpness
+ */
+void marucam_device_qctrl(MaruCamState *state)
+{
+    uint32_t id, i;
+    /* long property, min, max, step, def_val, set_val; */
+    char name[32] = {0,};
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    id = param->stack[0];
+
+    switch (id) {
+    case V4L2_CID_BRIGHTNESS:
+        TRACE("V4L2_CID_BRIGHTNESS\n");
+        memcpy((void *)name, (void *)"brightness", 32);
+        i = 0;
+        break;
+    case V4L2_CID_CONTRAST:
+        TRACE("V4L2_CID_CONTRAST\n");
+        memcpy((void *)name, (void *)"contrast", 32);
+        i = 1;
+        break;
+    case V4L2_CID_SATURATION:
+        TRACE("V4L2_CID_SATURATION\n");
+        memcpy((void *)name, (void *)"saturation", 32);
+        i = 2;
+        break;
+    case V4L2_CID_SHARPNESS:
+        TRACE("V4L2_CID_SHARPNESS\n");
+        memcpy((void *)name, (void *)"sharpness", 32);
+        i = 3;
+        break;
+    default:
+        param->errCode = EINVAL;
+        return;
+    }
+
+    param->stack[0] = 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] = V4L2_CTRL_FLAG_SLIDER;
+    /* name field setting */
+    memcpy(&param->stack[6], (void *)name, sizeof(name)/sizeof(name[0]));
+}
+
+void marucam_device_s_ctrl(MaruCamState *state)
+{
+    INFO("Set control\n");
+}
+
+void marucam_device_g_ctrl(MaruCamState *state)
+{
+    INFO("Get control\n");
+}
+
+/* Get frame width & height */
+void marucam_device_enum_fsizes(MaruCamState *state)
+{
+    uint32_t index, pixfmt, i;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    index = param->stack[0];
+    pixfmt = param->stack[1];
+
+    if (index >= ARRAY_SIZE(supported_dst_frames)) {
+        param->errCode = EINVAL;
+        return;
+    }
+    for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
+        if (supported_dst_pixfmts[i].fmt == pixfmt) {
+            break;
+        }
+    }
+
+    if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
+        param->errCode = EINVAL;
+        return;
+    }
+
+    param->stack[0] = supported_dst_frames[index].width;
+    param->stack[1] = supported_dst_frames[index].height;
+}
+
+void marucam_device_enum_fintv(MaruCamState *state)
+{
+    MaruCamParam *param = state->param;
+    param->top = 0;
+
+    /* switch by index(param->stack[0]) */
+    switch (param->stack[0]) {
+    case 0:
+        param->stack[1] = 30; /* denominator */
+        break;
+    default:
+        param->errCode = EINVAL;
+        return;
+    }
+    param->stack[0] = 1; /* numerator */
+}
diff --git a/tizen/src/hw/pci/maru_camera_darwin_converter.c b/tizen/src/hw/pci/maru_camera_darwin_converter.c
deleted file mode 100644 (file)
index 3f9cec5..0000000
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * Implementation of color conversion for MARU Virtual Camera device on MacOS.
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Contact:
- * Jun Tian <jun.j.tian@intel.com>
- * JinHyung Jo <jinhyung.jo@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-#include "qemu-common.h"
-#include "maru_camera_darwin.h"
-#include "debug_ch.h"
-
-MULTI_DEBUG_CHANNEL(tizen, camera);
-
-static void UYVYToYUV420(unsigned char *bufsrc, unsigned char *bufdest,
-                         int width, int height);
-static void YVU420ToYUV420(unsigned char *bufsrc, unsigned char *bufdest,
-                           int width, int height);
-static void YUYVToYUV420(unsigned char *bufsrc, unsigned char *bufdest,
-                         int width, int height);
-
-/* Convert pixel format to YUV420 */
-void convert_frame(uint32_t pixel_format, int frame_width, int frame_height,
-                   size_t frame_size, void *frame_pixels, void *video_buf)
-{
-    switch (pixel_format) {
-    case V4L2_PIX_FMT_YUV420:
-        memcpy(video_buf, (void *)frame_pixels, (size_t)frame_size);
-        break;
-    case V4L2_PIX_FMT_YVU420:
-        YVU420ToYUV420(frame_pixels, video_buf, frame_width, frame_height);
-        break;
-    case V4L2_PIX_FMT_YUYV:
-        YUYVToYUV420(frame_pixels, video_buf, frame_width, frame_height);
-        break;
-    case V4L2_PIX_FMT_UYVY: /* Mac default format */
-        UYVYToYUV420(frame_pixels, video_buf, frame_width, frame_height);
-        break;
-    default:
-        ERR("Cannot convert the pixel format (%.4s)...\n",
-               (const char *)&pixel_format);
-        break;
-    }
-}
-
-static void UYVYToYUV420(unsigned char *bufsrc, unsigned char *bufdest,
-                         int width, int height)
-{
-    int i, j;
-
-    /* Source */
-    unsigned char *ptrsrcy1, *ptrsrcy2;
-    unsigned char *ptrsrcy3, *ptrsrcy4;
-    unsigned char *ptrsrccb1;
-    unsigned char *ptrsrccb3;
-    unsigned char *ptrsrccr1;
-    unsigned char *ptrsrccr3;
-    int srcystride, srcccstride;
-
-    ptrsrcy1  = bufsrc + 1;
-    ptrsrcy2  = bufsrc + (width << 1) + 1;
-    ptrsrcy3  = bufsrc + (width << 1) * 2 + 1;
-    ptrsrcy4  = bufsrc + (width << 1) * 3 + 1;
-
-    ptrsrccb1 = bufsrc;
-    ptrsrccb3 = bufsrc + (width << 1) * 2;
-
-    ptrsrccr1 = bufsrc + 2;
-    ptrsrccr3 = bufsrc + (width << 1) * 2 + 2;
-
-    srcystride  = (width << 1) * 3;
-    srcccstride = (width << 1) * 3;
-
-    /* Destination */
-    unsigned char *ptrdesty1, *ptrdesty2;
-    unsigned char *ptrdesty3, *ptrdesty4;
-    unsigned char *ptrdestcb1, *ptrdestcb2;
-    unsigned char *ptrdestcr1, *ptrdestcr2;
-    int destystride, destccstride;
-
-    ptrdesty1 = bufdest;
-    ptrdesty2 = bufdest + width;
-    ptrdesty3 = bufdest + width * 2;
-    ptrdesty4 = bufdest + width * 3;
-
-    ptrdestcb1 = bufdest + width * height;
-    ptrdestcb2 = bufdest + width * height + (width >> 1);
-
-    ptrdestcr1 = bufdest + width * height + ((width*height) >> 2);
-    ptrdestcr2 = bufdest + width * height + ((width*height) >> 2)
-                 + (width >> 1);
-
-    destystride  = (width)*3;
-    destccstride = (width>>1);
-
-    for (j = 0; j < (height / 4); j++) {
-        for (i = 0; i < (width / 2); i++) {
-            (*ptrdesty1++) = (*ptrsrcy1);
-            (*ptrdesty2++) = (*ptrsrcy2);
-            (*ptrdesty3++) = (*ptrsrcy3);
-            (*ptrdesty4++) = (*ptrsrcy4);
-
-            ptrsrcy1 += 2;
-            ptrsrcy2 += 2;
-            ptrsrcy3 += 2;
-            ptrsrcy4 += 2;
-
-            (*ptrdesty1++) = (*ptrsrcy1);
-            (*ptrdesty2++) = (*ptrsrcy2);
-            (*ptrdesty3++) = (*ptrsrcy3);
-            (*ptrdesty4++) = (*ptrsrcy4);
-
-            ptrsrcy1 += 2;
-            ptrsrcy2 += 2;
-            ptrsrcy3 += 2;
-            ptrsrcy4 += 2;
-
-            (*ptrdestcb1++) = (*ptrsrccb1);
-            (*ptrdestcb2++) = (*ptrsrccb3);
-
-            ptrsrccb1 += 4;
-            ptrsrccb3 += 4;
-
-            (*ptrdestcr1++) = (*ptrsrccr1);
-            (*ptrdestcr2++) = (*ptrsrccr3);
-
-            ptrsrccr1 += 4;
-            ptrsrccr3 += 4;
-
-        }
-
-        /* Update src pointers */
-        ptrsrcy1  += srcystride;
-        ptrsrcy2  += srcystride;
-        ptrsrcy3  += srcystride;
-        ptrsrcy4  += srcystride;
-
-        ptrsrccb1 += srcccstride;
-        ptrsrccb3 += srcccstride;
-
-        ptrsrccr1 += srcccstride;
-        ptrsrccr3 += srcccstride;
-
-        /* Update dest pointers */
-        ptrdesty1 += destystride;
-        ptrdesty2 += destystride;
-        ptrdesty3 += destystride;
-        ptrdesty4 += destystride;
-
-        ptrdestcb1 += destccstride;
-        ptrdestcb2 += destccstride;
-
-        ptrdestcr1 += destccstride;
-        ptrdestcr2 += destccstride;
-    }
-}
-
-static void YVU420ToYUV420(unsigned char *bufsrc, unsigned char *bufdest,
-                           int width, int height)
-{
-    int i, j;
-
-    /* Source*/
-    unsigned char *ptrsrcy1, *ptrsrcy2;
-    unsigned char *ptrsrcy3, *ptrsrcy4;
-    unsigned char *ptrsrccb1, *ptrsrccb2;
-    unsigned char *ptrsrccr1, *ptrsrccr2;
-    int srcystride, srcccstride;
-
-    ptrsrcy1 = bufsrc;
-    ptrsrcy2 = bufsrc + width;
-    ptrsrcy3 = bufsrc + width*2;
-    ptrsrcy4 = bufsrc + width*3;
-
-    ptrsrccr1 = bufsrc + width*height;
-    ptrsrccr2 = bufsrc + width*height + (width>>1);
-
-    ptrsrccb1 = bufsrc + width*height + ((width*height) >> 2);
-    ptrsrccb2 = bufsrc + width*height + ((width*height) >> 2) + (width>>1);
-
-    srcystride  = (width)*3;
-    srcccstride = (width>>1);
-
-    /* Destination */
-    unsigned char *ptrdesty1, *ptrdesty2;
-    unsigned char *ptrdesty3, *ptrdesty4;
-    unsigned char *ptrdestcb1, *ptrdestcb2;
-    unsigned char *ptrdestcr1, *ptrdestcr2;
-    int destystride, destccstride;
-
-    ptrdesty1 = bufdest;
-    ptrdesty2 = bufdest + width;
-    ptrdesty3 = bufdest + width * 2;
-    ptrdesty4 = bufdest + width * 3;
-
-    ptrdestcb1 = bufdest + width * height;
-    ptrdestcb2 = bufdest + width * height + (width >> 1);
-
-    ptrdestcr1 = bufdest + width * height + ((width*height) >> 2);
-    ptrdestcr2 = bufdest + width * height + ((width*height) >> 2)
-                 + (width >> 1);
-
-    destystride  = (width)*3;
-    destccstride = (width>>1);
-
-    for (j = 0; j < (height / 4); j++) {
-        for (i = 0; i < (width / 2); i++) {
-
-            (*ptrdesty1++) = (*ptrsrcy1++);
-            (*ptrdesty2++) = (*ptrsrcy2++);
-            (*ptrdesty3++) = (*ptrsrcy3++);
-            (*ptrdesty4++) = (*ptrsrcy4++);
-            (*ptrdesty1++) = (*ptrsrcy1++);
-            (*ptrdesty2++) = (*ptrsrcy2++);
-            (*ptrdesty3++) = (*ptrsrcy3++);
-            (*ptrdesty4++) = (*ptrsrcy4++);
-
-            (*ptrdestcb1++) = (*ptrsrccb1++);
-            (*ptrdestcr1++) = (*ptrsrccr1++);
-            (*ptrdestcb2++) = (*ptrsrccb2++);
-            (*ptrdestcr2++) = (*ptrsrccr2++);
-
-        }
-
-        /* Update src pointers */
-        ptrsrcy1  += srcystride;
-        ptrsrcy2  += srcystride;
-        ptrsrcy3  += srcystride;
-        ptrsrcy4  += srcystride;
-
-        ptrsrccb1 += srcccstride;
-        ptrsrccb2 += srcccstride;
-
-        ptrsrccr1 += srcccstride;
-        ptrsrccr2 += srcccstride;
-
-        /* Update dest pointers */
-        ptrdesty1 += destystride;
-        ptrdesty2 += destystride;
-        ptrdesty3 += destystride;
-        ptrdesty4 += destystride;
-
-        ptrdestcb1 += destccstride;
-        ptrdestcb2 += destccstride;
-
-        ptrdestcr1 += destccstride;
-        ptrdestcr2 += destccstride;
-
-    }
-
-}
-
-static void YUYVToYUV420(unsigned char *bufsrc, unsigned char *bufdest,
-                         int width, int height)
-{
-    int i, j;
-
-    /* Source*/
-    unsigned char *ptrsrcy1, *ptrsrcy2;
-    unsigned char *ptrsrcy3, *ptrsrcy4;
-    unsigned char *ptrsrccb1;
-    unsigned char *ptrsrccb3;
-    unsigned char *ptrsrccr1;
-    unsigned char *ptrsrccr3;
-    int srcystride, srcccstride;
-
-    ptrsrcy1  = bufsrc ;
-    ptrsrcy2  = bufsrc + (width << 1);
-    ptrsrcy3  = bufsrc + (width << 1) * 2;
-    ptrsrcy4  = bufsrc + (width << 1) * 3;
-
-    ptrsrccb1 = bufsrc + 1;
-    ptrsrccb3 = bufsrc + (width << 1) * 2 + 1;
-
-    ptrsrccr1 = bufsrc + 3;
-    ptrsrccr3 = bufsrc + (width << 1) * 2 + 3;
-
-    srcystride  = (width << 1) * 3;
-    srcccstride = (width << 1) * 3;
-
-    /* Destination */
-    unsigned char *ptrdesty1, *ptrdesty2;
-    unsigned char *ptrdesty3, *ptrdesty4;
-    unsigned char *ptrdestcb1, *ptrdestcb2;
-    unsigned char *ptrdestcr1, *ptrdestcr2;
-    int destystride, destccstride;
-
-    ptrdesty1 = bufdest;
-    ptrdesty2 = bufdest + width;
-    ptrdesty3 = bufdest + width * 2;
-    ptrdesty4 = bufdest + width * 3;
-
-    ptrdestcb1 = bufdest + width * height;
-    ptrdestcb2 = bufdest + width * height + (width >> 1);
-
-    ptrdestcr1 = bufdest + width * height + ((width * height) >> 2);
-    ptrdestcr2 = bufdest + width * height + ((width * height) >> 2)
-                 + (width >> 1);
-
-    destystride  = width * 3;
-    destccstride = (width >> 1);
-
-    for (j = 0; j < (height / 4); j++) {
-        for (i = 0; i < (width / 2); i++) {
-            (*ptrdesty1++) = (*ptrsrcy1);
-            (*ptrdesty2++) = (*ptrsrcy2);
-            (*ptrdesty3++) = (*ptrsrcy3);
-            (*ptrdesty4++) = (*ptrsrcy4);
-
-            ptrsrcy1 += 2;
-            ptrsrcy2 += 2;
-            ptrsrcy3 += 2;
-            ptrsrcy4 += 2;
-
-            (*ptrdesty1++) = (*ptrsrcy1);
-            (*ptrdesty2++) = (*ptrsrcy2);
-            (*ptrdesty3++) = (*ptrsrcy3);
-            (*ptrdesty4++) = (*ptrsrcy4);
-
-            ptrsrcy1 += 2;
-            ptrsrcy2 += 2;
-            ptrsrcy3 += 2;
-            ptrsrcy4 += 2;
-
-            (*ptrdestcb1++) = (*ptrsrccb1);
-            (*ptrdestcb2++) = (*ptrsrccb3);
-
-            ptrsrccb1 += 4;
-            ptrsrccb3 += 4;
-
-            (*ptrdestcr1++) = (*ptrsrccr1);
-            (*ptrdestcr2++) = (*ptrsrccr3);
-
-            ptrsrccr1 += 4;
-            ptrsrccr3 += 4;
-
-        }
-
-        /* Update src pointers */
-        ptrsrcy1  += srcystride;
-        ptrsrcy2  += srcystride;
-        ptrsrcy3  += srcystride;
-        ptrsrcy4  += srcystride;
-
-        ptrsrccb1 += srcccstride;
-        ptrsrccb3 += srcccstride;
-
-        ptrsrccr1 += srcccstride;
-        ptrsrccr3 += srcccstride;
-
-        /* Update dest pointers */
-        ptrdesty1 += destystride;
-        ptrdesty2 += destystride;
-        ptrdesty3 += destystride;
-        ptrdesty4 += destystride;
-
-        ptrdestcb1 += destccstride;
-        ptrdestcb2 += destccstride;
-
-        ptrdestcr1 += destccstride;
-        ptrdestcr2 += destccstride;
-    }
-}
diff --git a/tizen/src/hw/pci/maru_camera_darwin_pci.m b/tizen/src/hw/pci/maru_camera_darwin_pci.m
deleted file mode 100644 (file)
index b470da3..0000000
+++ /dev/null
@@ -1,909 +0,0 @@
-/*
- * Implementation of MARU Virtual Camera device by PCI bus on MacOS.
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Contact:
- * Jun Tian <jun.j.tian@intel.com>
- * JinHyung Jo <jinhyung.jo@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-#import <Cocoa/Cocoa.h>
-#import <QTKit/QTKit.h>
-#import <CoreAudio/CoreAudio.h>
-
-#include <pthread.h>
-#include "qemu-common.h"
-#include "maru_camera_common.h"
-#include "maru_camera_darwin.h"
-#include "debug_ch.h"
-
-MULTI_DEBUG_CHANNEL(tizen, camera);
-
-#define MARUCAM_THREAD_NAME    "marucam_worker_thread"
-
-/* V4L2 defines copy from videodev2.h */
-#define V4L2_CTRL_FLAG_SLIDER       0x0020
-
-#define V4L2_CTRL_CLASS_USER        0x00980000
-#define V4L2_CID_BASE               (V4L2_CTRL_CLASS_USER | 0x900)
-#define V4L2_CID_BRIGHTNESS         (V4L2_CID_BASE + 0)
-#define V4L2_CID_CONTRAST           (V4L2_CID_BASE + 1)
-#define V4L2_CID_SATURATION         (V4L2_CID_BASE + 2)
-#define V4L2_CID_SHARPNESS          (V4L2_CID_BASE + 27)
-
-typedef struct tagMaruCamConvertPixfmt {
-    uint32_t fmt;   /* fourcc */
-    uint32_t bpp;   /* bits per pixel, 0 for compressed formats */
-    uint32_t needs_conversion;
-} MaruCamConvertPixfmt;
-
-
-static MaruCamConvertPixfmt supported_dst_pixfmts[] = {
-    { V4L2_PIX_FMT_YUYV, 16, 0 },
-    { V4L2_PIX_FMT_UYVY, 16, 0 },
-    { V4L2_PIX_FMT_YUV420, 12, 0 },
-    { V4L2_PIX_FMT_YVU420, 12, 0 },
-};
-
-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 },
-};
-
-#define MARUCAM_CTRL_VALUE_MAX      20
-#define MARUCAM_CTRL_VALUE_MIN      1
-#define MARUCAM_CTRL_VALUE_MID      10
-#define MARUCAM_CTRL_VALUE_STEP     1
-
-enum {
-    _MC_THREAD_PAUSED,
-    _MC_THREAD_STREAMON,
-    _MC_THREAD_STREAMOFF,
-};
-
-#if 0
-struct marucam_qctrl {
-    uint32_t id;
-    uint32_t hit;
-    long min;
-    long max;
-    long step;
-    long init_val;
-};
-
-static struct marucam_qctrl qctrl_tbl[] = {
-    { V4L2_CID_BRIGHTNESS, 0, },
-    { V4L2_CID_CONTRAST, 0, },
-    { V4L2_CID_SATURATION, 0, },
-    { V4L2_CID_SHARPNESS, 0, },
-};
-#endif
-
-static MaruCamState *g_state;
-
-static uint32_t ready_count;
-static uint32_t cur_fmt_idx;
-static uint32_t cur_frame_idx;
-
-/***********************************
- * Mac camera helper functions
- ***********************************/
-
-/* Convert Core Video format to FOURCC */
-static uint32_t corevideo_to_fourcc(uint32_t cv_pix_fmt)
-{
-    switch (cv_pix_fmt) {
-    case kCVPixelFormatType_420YpCbCr8Planar:
-        return V4L2_PIX_FMT_YVU420;
-    case kCVPixelFormatType_422YpCbCr8:
-        return V4L2_PIX_FMT_UYVY;
-    case kCVPixelFormatType_422YpCbCr8_yuvs:
-        return V4L2_PIX_FMT_YUYV;
-    case kCVPixelFormatType_32ARGB:
-    case kCVPixelFormatType_32RGBA:
-        return V4L2_PIX_FMT_RGB32;
-    case kCVPixelFormatType_32BGRA:
-    case kCVPixelFormatType_32ABGR:
-        return V4L2_PIX_FMT_BGR32;
-    case kCVPixelFormatType_24RGB:
-        return V4L2_PIX_FMT_RGB24;
-    case kCVPixelFormatType_24BGR:
-        return V4L2_PIX_FMT_BGR32;
-    default:
-        ERR("Unknown pixel format '%.4s'", (const char *)&cv_pix_fmt);
-        return 0;
-    }
-}
-
-static uint32_t get_bytesperline(uint32_t pixfmt, uint32_t width)
-{
-    uint32_t bytesperline;
-
-    switch (pixfmt) {
-    case V4L2_PIX_FMT_YUV420:
-    case V4L2_PIX_FMT_YVU420:
-        bytesperline = (width * 12) >> 3;
-        break;
-    case V4L2_PIX_FMT_YUYV:
-    case V4L2_PIX_FMT_UYVY:
-    default:
-        bytesperline = width * 2;
-        break;
-    }
-
-    return bytesperline;
-}
-
-static uint32_t get_sizeimage(uint32_t pixfmt, uint32_t width, uint32_t height)
-{
-    return get_bytesperline(pixfmt, width) * height;
-}
-
-/******************************************************************
- **   Maru Camera Implementation
- *****************************************************************/
-
-@interface MaruCameraDriver : NSObject {
-    QTCaptureSession               *mCaptureSession;
-    QTCaptureDeviceInput           *mCaptureVideoDeviceInput;
-    QTCaptureVideoPreviewOutput    *mCaptureVideoPreviewOutput;
-
-    CVImageBufferRef               mCurrentImageBuffer;
-    BOOL mDeviceIsOpened;
-    BOOL mCaptureIsStarted;
-}
-
-- (MaruCameraDriver *)init;
-- (int)startCapture:(int)width :(int)height;
-- (void)stopCapture;
-- (int)readFrame:(void *)video_buf;
-- (int)setCaptureFormat:(int)width :(int)height :(int)pix_format;
-- (int)getCaptureFormat:(int)width :(int)height :(int)pix_format;
-- (BOOL)deviceStatus;
-
-@end
-
-@implementation MaruCameraDriver
-
-- (MaruCameraDriver *)init
-{
-    BOOL success = NO;
-    NSError *error;
-    mDeviceIsOpened = NO;
-    mCaptureIsStarted = NO;
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
-    /* Create the capture session */
-    mCaptureSession = [[QTCaptureSession alloc] init];
-
-    /* Find a video device */
-    QTCaptureDevice *videoDevice = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeVideo];
-    success = [videoDevice open:&error];
-
-    /* If a video input device can't be found or opened, try to find and open a muxed input device */
-    if (!success) {
-        videoDevice = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeMuxed];
-        success = [videoDevice open:&error];
-        [pool release];
-        return nil;
-    }
-
-    if (!success) {
-        videoDevice = nil;
-        [pool release];
-        return nil;
-    }
-
-    if (videoDevice) {
-        /* Add the video device to the session as a device input */
-        mCaptureVideoDeviceInput = [[QTCaptureDeviceInput alloc] initWithDevice:videoDevice];
-        success = [mCaptureSession addInput:mCaptureVideoDeviceInput error:&error];
-
-        if (!success) {
-            [pool release];
-            return nil;
-        }
-
-        mCaptureVideoPreviewOutput = [[QTCaptureVideoPreviewOutput alloc] init];
-        success = [mCaptureSession addOutput:mCaptureVideoPreviewOutput error:&error];
-        if (!success) {
-            [pool release];
-            return nil;
-        }
-
-        mDeviceIsOpened = YES;
-        [mCaptureVideoPreviewOutput setDelegate:self];
-        INFO("Camera session bundling successfully!\n");
-        [pool release];
-        return self;
-    } else {
-        [pool release];
-        return nil;
-    }
-}
-
-- (int)startCapture:(int)width :(int)height
-{
-    int ret = -1;
-
-    if (![mCaptureSession isRunning]) {
-        /* Set width & height, using default pixel format to capture */
-        NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
-                                                      [NSNumber numberWithInt: width], (id)kCVPixelBufferWidthKey,
-                                                      [NSNumber numberWithInt: height], (id)kCVPixelBufferHeightKey,
-                                                 nil];
-        [mCaptureVideoPreviewOutput setPixelBufferAttributes:attributes];
-        [mCaptureSession startRunning];
-    } else {
-        ERR("Capture session is already running, exit\n");
-        return ret;
-    }
-
-    if ([mCaptureSession isRunning]) {
-        while(!mCaptureIsStarted) {
-            /* Wait Until Capture is started */
-            [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.5]];
-        }
-        ret = 0;
-    }
-    return ret;
-}
-
-- (void)stopCapture
-{
-    if ([mCaptureSession isRunning]) {
-        [mCaptureSession stopRunning];
-        while([mCaptureSession isRunning]) {
-            /* Wait Until Capture is stopped */
-            [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1]];
-        }
-
-    }
-    mCaptureIsStarted = NO;
-}
-
-- (int)readFrame:(void *)video_buf
-{
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
-    @synchronized (self) {
-        if (mCaptureIsStarted == NO) {
-            [pool release];
-            return 0;
-        }
-        if (mCurrentImageBuffer != nil) {
-            CVPixelBufferLockBaseAddress(mCurrentImageBuffer, 0);
-            const uint32_t pixel_format = corevideo_to_fourcc(CVPixelBufferGetPixelFormatType(mCurrentImageBuffer));
-            const int frame_width = CVPixelBufferGetWidth(mCurrentImageBuffer);
-            const int frame_height = CVPixelBufferGetHeight(mCurrentImageBuffer);
-            const size_t frame_size = CVPixelBufferGetBytesPerRow(mCurrentImageBuffer) * frame_height;
-            const void *frame_pixels = CVPixelBufferGetBaseAddress(mCurrentImageBuffer);
-
-            TRACE("buffer(%p), pixel_format(%d,%.4s), frame_width(%d), "
-                  "frame_height(%d), frame_size(%d)\n",
-                  mCurrentImageBuffer, (int)pixel_format,
-                  (const char *)&pixel_format, frame_width,
-                  frame_height, (int)frame_size);
-
-            /* convert frame to v4l2 format */
-            convert_frame(pixel_format, frame_width, frame_height,
-                          frame_size, (void *)frame_pixels, video_buf);
-            CVPixelBufferUnlockBaseAddress(mCurrentImageBuffer, 0);
-            [pool release];
-            return 1;
-        }
-    }
-
-    [pool release];
-    return -1;
-}
-
-- (int)setCaptureFormat:(int)width :(int)height :(int)pix_format
-{
-    int ret = -1;
-    NSDictionary *attributes;
-
-    if (mCaptureSession == nil || mCaptureVideoPreviewOutput == nil) {
-        ERR("Capture session is not initiated.\n");
-        return ret;
-    }
-
-    /* Set the pixel buffer attributes before running the capture session */
-    if (![mCaptureSession isRunning]) {
-        if (pix_format) {
-            attributes = [NSDictionary dictionaryWithObjectsAndKeys:
-                                            [NSNumber numberWithInt: width], (id)kCVPixelBufferWidthKey,
-                                            [NSNumber numberWithInt: height], (id)kCVPixelBufferHeightKey,
-                                            [NSNumber numberWithInt: pix_format], (id)kCVPixelBufferPixelFormatTypeKey,
-                                       nil];
-        } else {
-            attributes = [NSDictionary dictionaryWithObjectsAndKeys:
-                                            [NSNumber numberWithInt: width], (id)kCVPixelBufferWidthKey,
-                                            [NSNumber numberWithInt: height], (id)kCVPixelBufferHeightKey,
-                                       nil];
-        }
-        [mCaptureVideoPreviewOutput setPixelBufferAttributes:attributes];
-        ret = 0;
-    } else {
-        ERR("Cannot set pixel buffer attributes when it's running.\n");
-        return ret;
-    }
-
-    return ret;
-}
-
-- (int)getCaptureFormat:(int)width :(int)height :(int)pix_format
-{
-    return 0;
-}
-
-/* Get the device bundling status */
-- (BOOL)deviceStatus
-{
-    return mDeviceIsOpened;
-}
-
-/* Handle deallocation of memory for your capture objects */
-
-- (void)dealloc
-{
-    [mCaptureSession release];
-    [mCaptureVideoDeviceInput release];
-    [mCaptureVideoPreviewOutput release];
-    [super dealloc];
-}
-
-/* Receive this method whenever the output decompresses and outputs a new video frame */
-- (void)captureOutput:(QTCaptureOutput *)captureOutput didOutputVideoFrame:(CVImageBufferRef)videoFrame
-     withSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection
-{
-    CVImageBufferRef imageBufferToRelease;
-    CVBufferRetain(videoFrame);
-
-    @synchronized (self)
-    {
-        imageBufferToRelease = mCurrentImageBuffer;
-        mCurrentImageBuffer = videoFrame;
-        mCaptureIsStarted = YES;
-    }
-    CVBufferRelease(imageBufferToRelease);
-}
-
-@end
-
-/******************************************************************
- **   Maru Camera APIs
- *****************************************************************/
-
-typedef struct MaruCameraDevice MaruCameraDevice;
-struct MaruCameraDevice {
-    /* Maru camera device object. */
-    MaruCameraDriver *driver;
-};
-
-/* Golbal representation of the Maru camera */
-MaruCameraDevice *mcd = NULL;
-
-static int is_streamon()
-{
-    int st;
-    qemu_mutex_lock(&g_state->thread_mutex);
-    st = g_state->streamon;
-    qemu_mutex_unlock(&g_state->thread_mutex);
-    return (st == _MC_THREAD_STREAMON);
-}
-
-static void __raise_err_intr()
-{
-    qemu_mutex_lock(&g_state->thread_mutex);
-    if (g_state->streamon == _MC_THREAD_STREAMON) {
-        g_state->req_frame = 0; /* clear request */
-        g_state->isr = 0x08;   /* set a error flag of rasing a interrupt */
-        qemu_bh_schedule(g_state->tx_bh);
-    }
-    qemu_mutex_unlock(&g_state->thread_mutex);
-}
-
-static int marucam_device_read_frame()
-{
-    int ret;
-    void *tmp_buf;
-
-    qemu_mutex_lock(&g_state->thread_mutex);
-    if (g_state->streamon == _MC_THREAD_STREAMON) {
-#if 0
-        if (ready_count < MARUCAM_SKIPFRAMES) {
-            /* skip a frame cause first some frame are distorted */
-            ++ready_count;
-            TRACE("Skip %d frame\n", ready_count);
-            qemu_mutex_unlock(&g_state->thread_mutex);
-            return 0;
-        }
-#endif
-        if (g_state->req_frame == 0) {
-            TRACE("There is no request\n");
-            qemu_mutex_unlock(&g_state->thread_mutex);
-            return 0;
-        }
-
-        /* Grab the camera frame into temp buffer */
-        tmp_buf = g_state->vaddr + g_state->buf_size * (g_state->req_frame - 1);
-        ret =  [mcd->driver readFrame: tmp_buf];
-        if (ret < 0) {
-            ERR("%s, Capture error\n", __func__);
-            qemu_mutex_unlock(&g_state->thread_mutex);
-            __raise_err_intr();
-            return -1;
-        } else if (!ret) {
-            qemu_mutex_unlock(&g_state->thread_mutex);
-            return 0;
-        }
-
-        g_state->req_frame = 0; /* clear request */
-        g_state->isr |= 0x01;   /* set a flag of rasing a interrupt */
-        qemu_bh_schedule(g_state->tx_bh);
-    } else {
-        qemu_mutex_unlock(&g_state->thread_mutex);
-        return -1;
-    }
-    qemu_mutex_unlock(&g_state->thread_mutex);
-    return 0;
-}
-
-/* Worker thread to grab frames to the preview window */
-static void *marucam_worker_thread(void *thread_param)
-{
-    while (1) {
-        qemu_mutex_lock(&g_state->thread_mutex);
-        g_state->streamon = _MC_THREAD_PAUSED;
-        qemu_cond_wait(&g_state->thread_cond, &g_state->thread_mutex);
-        qemu_mutex_unlock(&g_state->thread_mutex);
-
-        if (g_state->destroying) {
-            break;
-        }
-
-        ready_count = 0;
-        qemu_mutex_lock(&g_state->thread_mutex);
-        g_state->streamon = _MC_THREAD_STREAMON;
-        qemu_mutex_unlock(&g_state->thread_mutex);
-        INFO("Streaming on ......\n");
-
-        /* Loop: capture frame -> convert format -> render to screen */
-        while (1) {
-            if (is_streamon()) {
-                if (marucam_device_read_frame() < 0) {
-                    INFO("Streaming is off ...\n");
-                    break;
-                } else {
-                    /* wait until next frame is avalilable */
-                    usleep(22000);
-                }
-            } else {
-                INFO("Streaming is off ...\n");
-                break;
-            }
-        }
-    }
-
-    return NULL;
-}
-
-int marucam_device_check(int log_flag)
-{
-    /* FIXME: check the device parameters */
-    INFO("Checking camera device\n");
-    return 1;
-}
-
-/**********************************************
- * MARU camera routines
- **********************************************/
-void marucam_device_init(MaruCamState *state)
-{
-    g_state = state;
-    g_state->destroying = false;
-    qemu_thread_create(&state->thread_id,
-                       MARUCAM_THREAD_NAME,
-                       marucam_worker_thread,
-                       NULL,
-                       QEMU_THREAD_JOINABLE);
-}
-
-void marucam_device_exit(MaruCamState *state)
-{
-    state->destroying = true;
-    qemu_mutex_lock(&state->thread_mutex);
-    qemu_cond_signal(&state->thread_cond);
-    qemu_mutex_unlock(&state->thread_mutex);
-    qemu_thread_join(&state->thread_id);
-}
-
-/* MARUCAM_CMD_OPEN */
-void marucam_device_open(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
-    param->top = 0;
-
-    mcd = (MaruCameraDevice *)malloc(sizeof(MaruCameraDevice));
-    if (mcd == NULL) {
-        ERR("%s: MaruCameraDevice allocate failed\n", __func__);
-        param->errCode = EINVAL;
-        return;
-    }
-    memset(mcd, 0, sizeof(MaruCameraDevice));
-    mcd->driver = [[MaruCameraDriver alloc] init];
-    if (mcd->driver == nil) {
-        ERR("Camera device open failed\n");
-        [mcd->driver dealloc];
-        free(mcd);
-        param->errCode = EINVAL;
-        return;
-    }
-    INFO("Camera opened!\n");
-}
-
-/* MARUCAM_CMD_CLOSE */
-void marucam_device_close(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
-    param->top = 0;
-
-    if (mcd != NULL) {
-        if (is_streamon()) {
-            marucam_device_stop_preview(state);
-        }
-        [mcd->driver dealloc];
-        free(mcd);
-        mcd = NULL;
-    }
-
-    /* marucam_reset_controls(); */
-    INFO("Camera closed\n");
-}
-
-/* MARUCAM_CMD_START_PREVIEW */
-void marucam_device_start_preview(MaruCamState *state)
-{
-    uint32_t width, height, pixfmt;
-    MaruCamParam *param = state->param;
-    param->top = 0;
-
-    width = supported_dst_frames[cur_frame_idx].width;
-    height = supported_dst_frames[cur_frame_idx].height;
-    pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
-    state->buf_size = get_sizeimage(pixfmt, width, height);
-
-    INFO("Pixfmt(%c%c%c%c), W:H(%d:%d), buf size(%u), frame idx(%d), fmt idx(%d)\n",
-      (char)(pixfmt), (char)(pixfmt >> 8),
-      (char)(pixfmt >> 16), (char)(pixfmt >> 24),
-      width, height, state->buf_size,
-      cur_frame_idx, cur_fmt_idx);
-
-    if (mcd->driver == nil) {
-        ERR("%s: Start capture failed: vaild device", __func__);
-        param->errCode = EINVAL;
-        return;
-    }
-
-    INFO("Starting preview ...\n");
-    [mcd->driver startCapture: width: height];
-
-    /* Enable the condition to capture frames now */
-    qemu_mutex_lock(&state->thread_mutex);
-    qemu_cond_signal(&state->thread_cond);
-    qemu_mutex_unlock(&state->thread_mutex);
-
-    while (!is_streamon()) {
-        usleep(10000);
-    }
-}
-
-/* MARUCAM_CMD_STOP_PREVIEW */
-void marucam_device_stop_preview(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
-    param->top = 0;
-
-    if (is_streamon()) {
-        qemu_mutex_lock(&state->thread_mutex);
-        state->streamon = _MC_THREAD_STREAMOFF;
-        qemu_mutex_unlock(&state->thread_mutex);
-
-        while (is_streamon()) {
-            usleep(10000);
-        }
-    }
-
-    if (mcd->driver != nil) {
-        [mcd->driver stopCapture];
-    }
-
-    state->buf_size = 0;
-    INFO("Stopping preview ...\n");
-}
-
-/* MARUCAM_CMD_S_PARAM */
-void marucam_device_s_param(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
-
-    /* We use default FPS of the webcam */
-    param->top = 0;
-}
-
-/* MARUCAM_CMD_G_PARAM */
-void marucam_device_g_param(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
-    /* 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 */
-}
-
-/* MARUCAM_CMD_S_FMT */
-void marucam_device_s_fmt(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
-    uint32_t width, height, pixfmt, pidx, fidx;
-
-    param->top = 0;
-    width = param->stack[0];
-    height = param->stack[1];
-    pixfmt = param->stack[2];
-
-    TRACE("Set format: width(%d), height(%d), pixfmt(%d, %.4s)\n",
-         width, height, pixfmt, (const char*)&pixfmt);
-
-    for (fidx = 0; fidx < ARRAY_SIZE(supported_dst_frames); fidx++) {
-        if ((supported_dst_frames[fidx].width == width) &&
-            (supported_dst_frames[fidx].height == height)) {
-            break;
-        }
-    }
-    if (fidx == ARRAY_SIZE(supported_dst_frames)) {
-        param->errCode = EINVAL;
-        return;
-    }
-
-    for (pidx = 0; pidx < ARRAY_SIZE(supported_dst_pixfmts); pidx++) {
-        if (supported_dst_pixfmts[pidx].fmt == pixfmt) {
-            TRACE("pixfmt index is match: %d\n", pidx);
-            break;
-        }
-    }
-    if (pidx == ARRAY_SIZE(supported_dst_pixfmts)) {
-        param->errCode = EINVAL;
-        return;
-    }
-
-    if ((supported_dst_frames[cur_frame_idx].width != width) &&
-        (supported_dst_frames[cur_frame_idx].height != height)) {
-        if (mcd->driver == nil || [mcd->driver setCaptureFormat: width: height: 0] < 0) {
-            ERR("Set pixel format failed\n");
-            param->errCode = EINVAL;
-            return;
-        }
-
-        TRACE("cur_frame_idx:%d, supported_dst_frames[cur_frame_idx].width:%d\n",
-             cur_frame_idx, supported_dst_frames[cur_frame_idx].width);
-    }
-
-    cur_frame_idx = fidx;
-    cur_fmt_idx = pidx;
-
-    pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
-    width = supported_dst_frames[cur_frame_idx].width;
-    height = supported_dst_frames[cur_frame_idx].height;
-
-    param->stack[0] = width;
-    param->stack[1] = height;
-    param->stack[2] = 1; /* V4L2_FIELD_NONE */
-    param->stack[3] = pixfmt;
-    param->stack[4] = get_bytesperline(pixfmt, width);
-    param->stack[5] = get_sizeimage(pixfmt, width, height);
-    param->stack[6] = 0;
-    param->stack[7] = 0;
-
-    TRACE("Set device pixel format ...\n");
-}
-
-/* MARUCAM_CMD_G_FMT */
-void marucam_device_g_fmt(MaruCamState *state)
-{
-    uint32_t width, height, pixfmt;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
-    width = supported_dst_frames[cur_frame_idx].width;
-    height = supported_dst_frames[cur_frame_idx].height;
-
-    param->stack[0] = width;
-    param->stack[1] = height;
-    param->stack[2] = 1; /* V4L2_FIELD_NONE */
-    param->stack[3] = pixfmt;
-    param->stack[4] = get_bytesperline(pixfmt, width);
-    param->stack[5] = get_sizeimage(pixfmt, width, height);
-    param->stack[6] = 0;
-    param->stack[7] = 0;
-
-    TRACE("Get device frame format ...\n");
-}
-
-void marucam_device_try_fmt(MaruCamState *state)
-{
-    TRACE("Try device frame format, use default setting ...\n");
-}
-
-/* Get specific pixelformat description */
-void marucam_device_enum_fmt(MaruCamState *state)
-{
-    uint32_t index;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    index = param->stack[0];
-
-    if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {
-        param->errCode = EINVAL;
-        return;
-    }
-    param->stack[1] = 0; /* flags = NONE */
-    param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */
-    switch (supported_dst_pixfmts[index].fmt) {
-    case V4L2_PIX_FMT_YUYV:
-        memcpy(&param->stack[3], "YUYV", 32);
-        break;
-    case V4L2_PIX_FMT_UYVY:
-        memcpy(&param->stack[3], "UYVY", 32);
-        break;
-    case V4L2_PIX_FMT_YUV420:
-        memcpy(&param->stack[3], "YU12", 32);
-        break;
-    case V4L2_PIX_FMT_YVU420:
-        memcpy(&param->stack[3], "YV12", 32);
-        break;
-    default:
-        param->errCode = EINVAL;
-        break;
-    }
-}
-
-/*
- * QTKit don't support setting brightness, contrast, saturation & sharpness
- */
-void marucam_device_qctrl(MaruCamState *state)
-{
-    uint32_t id, i;
-    /* long property, min, max, step, def_val, set_val; */
-    char name[32] = {0,};
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    id = param->stack[0];
-
-    switch (id) {
-    case V4L2_CID_BRIGHTNESS:
-        TRACE("V4L2_CID_BRIGHTNESS\n");
-        memcpy((void *)name, (void *)"brightness", 32);
-        i = 0;
-        break;
-    case V4L2_CID_CONTRAST:
-        TRACE("V4L2_CID_CONTRAST\n");
-        memcpy((void *)name, (void *)"contrast", 32);
-        i = 1;
-        break;
-    case V4L2_CID_SATURATION:
-        TRACE("V4L2_CID_SATURATION\n");
-        memcpy((void *)name, (void *)"saturation", 32);
-        i = 2;
-        break;
-    case V4L2_CID_SHARPNESS:
-        TRACE("V4L2_CID_SHARPNESS\n");
-        memcpy((void *)name, (void *)"sharpness", 32);
-        i = 3;
-        break;
-    default:
-        param->errCode = EINVAL;
-        return;
-    }
-
-    param->stack[0] = 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] = V4L2_CTRL_FLAG_SLIDER;
-    /* name field setting */
-    memcpy(&param->stack[6], (void *)name, sizeof(name)/sizeof(name[0]));
-}
-
-void marucam_device_s_ctrl(MaruCamState *state)
-{
-    INFO("Set control\n");
-}
-
-void marucam_device_g_ctrl(MaruCamState *state)
-{
-    INFO("Get control\n");
-}
-
-/* Get frame width & height */
-void marucam_device_enum_fsizes(MaruCamState *state)
-{
-    uint32_t index, pixfmt, i;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    index = param->stack[0];
-    pixfmt = param->stack[1];
-
-    if (index >= ARRAY_SIZE(supported_dst_frames)) {
-        param->errCode = EINVAL;
-        return;
-    }
-    for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
-        if (supported_dst_pixfmts[i].fmt == pixfmt) {
-            break;
-        }
-    }
-
-    if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
-        param->errCode = EINVAL;
-        return;
-    }
-
-    param->stack[0] = supported_dst_frames[index].width;
-    param->stack[1] = supported_dst_frames[index].height;
-}
-
-void marucam_device_enum_fintv(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
-    param->top = 0;
-
-    /* switch by index(param->stack[0]) */
-    switch (param->stack[0]) {
-    case 0:
-        param->stack[1] = 30; /* denominator */
-        break;
-    default:
-        param->errCode = EINVAL;
-        return;
-    }
-    param->stack[0] = 1; /* numerator */
-}
diff --git a/tizen/src/hw/pci/maru_camera_linux.c b/tizen/src/hw/pci/maru_camera_linux.c
new file mode 100644 (file)
index 0000000..2a76c07
--- /dev/null
@@ -0,0 +1,1391 @@
+/*
+ * Implementation of MARU Virtual Camera device by PCI bus on Linux.
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#include "qemu-common.h"
+#include "sysemu/kvm.h"
+#include "maru_camera.h"
+#include "debug_ch.h"
+
+#include <linux/videodev2.h>
+
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <libv4l2.h>
+#include <libv4lconvert.h>
+
+MULTI_DEBUG_CHANNEL(tizen, camera);
+
+#define MARUCAM_THREAD_NAME    "marucam_worker_thread"
+
+#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
+
+enum {
+    _MC_THREAD_PAUSED,
+    _MC_THREAD_STREAMON,
+    _MC_THREAD_STREAMOFF,
+};
+
+typedef struct marucam_framebuffer {
+    void *data;
+    size_t size;
+} marucam_framebuffer;
+
+struct marucam_saved_frame {
+    void *data;
+    uint32_t pixelformat;
+    uint32_t width;
+    uint32_t height;
+    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;
+
+static const char *dev_name = "/dev/video0";
+static int v4l2_fd;
+static int convert_trial;
+static int ready_count;
+static int timeout_n;
+
+static struct v4l2_format dst_fmt;
+
+static void ScalePlaneSimple(int src_width, int src_height,
+                             int dst_width, int dst_height,
+                             int src_stride, int dst_stride,
+                             const uint8_t *src_ptr, uint8_t *dst_ptr) {
+    int i, j;
+    int dx = (src_width << 16) / dst_width;
+    int dy = (src_height << 16) / dst_height;
+    int y = (dy >= 65536) ? ((dy >> 1) - 32768) : (dy >> 1);
+    for (j = 0; j < dst_height; ++j) {
+        int x = (dx >= 65536) ? ((dx >> 1) - 32768) : (dx >> 1);
+        int yi = y >> 16;
+        const uint8_t *src = src_ptr + yi * src_stride;
+        uint8_t *dst = dst_ptr;
+        for (i = 0; i < dst_width; ++i) {
+            *dst++ = src[x >> 16];
+            x += dx;
+        }
+        dst_ptr += dst_stride;
+        y += dy;
+    }
+}
+
+static void make_yu12_black(unsigned char *dest, uint32_t width, uint32_t height)
+{
+    uint32_t x, y;
+    unsigned char *udest, *vdest;
+
+    /* Y */
+    for (y = 0; y < height; y++) {
+        for (x = 0; x < width; x++) {
+            *dest++ = 16;
+        }
+    }
+
+    /* U + V */
+    udest = dest;
+    vdest = dest + width * height / 4;
+
+    for (y = 0; y < height / 2; y++) {
+        for (x = 0; x < width / 2; x++) {
+            *udest++ = *vdest++ = 128;
+        }
+    }
+}
+
+static void marucam_scale_yuv420(void *src,
+                    uint32_t src_width, uint32_t src_height,
+                    void *dst, uint32_t dst_width, uint32_t dst_height)
+{
+    uint32_t src_halfwidth = (src_width + 1) >> 1;
+    uint32_t src_halfheight = (src_height + 1) >> 1;
+    uint32_t dst_halfwidth = (dst_width + 1) >> 1;
+    uint32_t dst_halfheight = (dst_height + 1) >> 1;
+
+    uint8_t *src_u = src + (src_width * src_height);
+    uint8_t *src_v = src_u + (src_width * src_height / 4);
+
+    uint8_t *dst_u = dst + (dst_width * dst_height);
+    uint8_t *dst_v = dst_u + (dst_width * dst_height /4);
+
+    ScalePlaneSimple(src_width, src_height,
+                     dst_width, dst_height,
+                     src_width, dst_width,
+                     src, dst);
+    ScalePlaneSimple(src_halfwidth, src_halfheight,
+                     dst_halfwidth, dst_halfheight,
+                     src_halfwidth, dst_halfwidth,
+                     src_u, dst_u);
+    ScalePlaneSimple(src_halfwidth, src_halfheight,
+                     dst_halfwidth, dst_halfheight,
+                     src_halfwidth, dst_halfwidth,
+                     src_v, dst_v);
+}
+
+static int yioctl(int fd, int req, void *arg)
+{
+    int r;
+
+    do {
+        r = ioctl(fd, req, arg);
+    } while (r < 0 && errno == EINTR);
+
+    return r;
+}
+
+static int xioctl(int fd, int req, void *arg)
+{
+    int r;
+
+    do {
+        r = v4l2_ioctl(fd, req, arg);
+    } while (r < 0 && errno == EINTR);
+
+    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)
+{
+    uint32_t i;
+    for (i = 0; i < ARRAY_SIZE(qctrl_tbl); i++) {
+        if (qctrl_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) {
+                ERR("Failed to reset control value: id(0x%x), errstr(%s)\n",
+                    ctrl.id, strerror(errno));
+            }
+        }
+    }
+    TRACE("[%s] Reset done\n", __func__);
+}
+
+static int32_t value_convert_from_guest(int32_t min, int32_t max, int32_t value)
+{
+    double rate = 0.0;
+    int32_t dist = 0, ret = 0;
+
+    dist = max - min;
+
+    if (dist < MARUCAM_CTRL_VALUE_MAX) {
+        rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;
+        ret = min + (int32_t)(value / rate);
+    } else {
+        rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;
+        ret = min + (int32_t)(rate * value);
+    }
+    return ret;
+}
+
+static int32_t value_convert_to_guest(int32_t min, int32_t max, int32_t value)
+{
+    double rate  = 0.0;
+    int32_t dist = 0, ret = 0;
+
+    dist = max - min;
+
+    if (dist < MARUCAM_CTRL_VALUE_MAX) {
+        rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;
+        ret = (int32_t)((double)(value - min) * rate);
+    } else {
+        rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;
+        ret = (int32_t)((double)(value - min) / rate);
+    }
+
+    return ret;
+}
+
+static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format,
+                        uint32_t width, uint32_t height)
+{
+    struct v4l2_frmivalenum fival;
+    struct v4l2_streamparm sp;
+    uint32_t min_num = 0, min_denom = 0;
+
+    CLEAR(fival);
+    fival.pixel_format = pixel_format;
+    fival.width = width;
+    fival.height = height;
+
+    if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) < 0) {
+        ERR("Unable to enumerate intervals for pixelformat(0x%x), (%d:%d)\n",
+            pixel_format, width, height);
+        return;
+    }
+
+    if (fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
+        float max_ival = -1.0;
+        do {
+            float cur_ival = (float)fival.discrete.numerator
+                        / (float)fival.discrete.denominator;
+            if (cur_ival > max_ival) {
+                max_ival = cur_ival;
+                min_num = fival.discrete.numerator;
+                min_denom = fival.discrete.denominator;
+            }
+            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);
+    } else if ((fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) ||
+                (fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)) {
+        TRACE("Frame intervals from %u/%u to %u/%u supported",
+            fival.stepwise.min.numerator, fival.stepwise.min.denominator,
+            fival.stepwise.max.numerator, fival.stepwise.max.denominator);
+        if (fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
+            TRACE("with %u/%u step", fival.stepwise.step.numerator,
+                  fival.stepwise.step.denominator);
+        }
+        if (((float)fival.stepwise.max.denominator /
+             (float)fival.stepwise.max.numerator) >
+            ((float)fival.stepwise.min.denominator /
+             (float)fival.stepwise.min.numerator)) {
+            min_num = fival.stepwise.max.numerator;
+            min_denom = fival.stepwise.max.denominator;
+        } else {
+            min_num = fival.stepwise.min.numerator;
+            min_denom = fival.stepwise.min.denominator;
+        }
+    }
+    TRACE("The actual min values: %u/%u\n", min_num, min_denom);
+
+    CLEAR(sp);
+    sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    sp.parm.capture.timeperframe.numerator = min_num;
+    sp.parm.capture.timeperframe.denominator = min_denom;
+
+    if (xioctl(v4l2_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)
+{
+    enum v4l2_buf_type type;
+
+    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    if (xioctl(v4l2_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)
+{
+    enum v4l2_buf_type type;
+
+    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    if (xioctl(v4l2_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)
+{
+    int i;
+
+    if (fb == NULL) {
+        ERR("The framebuffer is NULL. Failed to release the framebuffer\n");
+        return;
+    } else if (buf_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);
+    }
+
+    /* 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;
+        } else {
+            ERR("framebuffer[%d].data is NULL.\n", i);
+        }
+    }
+    previous_frame_index = -1;
+}
+
+static uint32_t
+mmap_framebuffers(marucam_framebuffer **fb, int *buf_num)
+{
+    struct v4l2_requestbuffers req;
+
+    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 (errno == EINVAL) {
+            ERR("%s does not support memory mapping: %s\n",
+                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);
+        return EINVAL;
+    }
+
+    *fb = g_new0(marucam_framebuffer, req.count);
+    if (*fb == NULL) {
+        ERR("Not enough memory to allocate framebuffers\n");
+        return ENOMEM;
+    }
+
+    for (*buf_num = 0; *buf_num < req.count; ++*buf_num) {
+        struct v4l2_buffer buf;
+        CLEAR(buf);
+        buf.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        buf.memory  = V4L2_MEMORY_MMAP;
+        buf.index   = *buf_num;
+        if (xioctl(v4l2_fd, VIDIOC_QUERYBUF, &buf) < 0) {
+            ERR("Failed to ioctl() with VIDIOC_QUERYBUF: %s\n",
+                strerror(errno));
+            return errno;
+        }
+
+        (*fb)[*buf_num].size = buf.length;
+        (*fb)[*buf_num].data = v4l2_mmap(NULL,
+                     buf.length,
+                     PROT_READ | PROT_WRITE,
+                     MAP_SHARED,
+                     v4l2_fd, buf.m.offset);
+        if (MAP_FAILED == (*fb)[*buf_num].data) {
+            ERR("Failed to mmap: %s\n", strerror(errno));
+            return errno;
+        }
+
+        /* Queue the mapped buffer. */
+        CLEAR(buf);
+        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        buf.memory = V4L2_MEMORY_MMAP;
+        buf.index = *buf_num;
+        if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) {
+            ERR("Failed to ioctl() with VIDIOC_QBUF: %s\n", strerror(errno));
+            return errno;
+        }
+    }
+    return 0;
+}
+
+static int is_streamon(MaruCamState *state)
+{
+    int st;
+    qemu_mutex_lock(&state->thread_mutex);
+    st = state->streamon;
+    qemu_mutex_unlock(&state->thread_mutex);
+    return (st == _MC_THREAD_STREAMON);
+}
+
+static int is_stream_paused(MaruCamState *state)
+{
+    int st;
+    qemu_mutex_lock(&state->thread_mutex);
+    st = state->streamon;
+    qemu_mutex_unlock(&state->thread_mutex);
+    return (st == _MC_THREAD_PAUSED);
+}
+
+/* sends a frame, YU12/black color  */
+/* TODO: add other pixel format method */
+static void __raise_dummy_intr(MaruCamState *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) {
+                TRACE("Copies the previuos frame\n");
+                memcpy(buf, saved_frame.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);
+            }
+        } else {
+            TRACE("Sends a black frame\n");
+            make_yu12_black(buf,
+                            dst_fmt.fmt.pix.width,
+                            dst_fmt.fmt.pix.height);
+        }
+        state->req_frame = 0; /* clear request */
+        state->isr |= 0x01;   /* set a flag of raising a interrupt */
+        qemu_bh_schedule(state->tx_bh);
+    }
+    qemu_mutex_unlock(&state->thread_mutex);
+}
+
+static void __raise_err_intr(MaruCamState *state)
+{
+    qemu_mutex_lock(&state->thread_mutex);
+    if (state->streamon == _MC_THREAD_STREAMON) {
+        state->req_frame = 0; /* clear request */
+        state->isr = 0x08;   /* set a error flag of raising a interrupt */
+        qemu_bh_schedule(state->tx_bh);
+    }
+    qemu_mutex_unlock(&state->thread_mutex);
+}
+
+static void
+notify_buffer_ready(MaruCamState *state, uint32_t buf_index)
+{
+    void *buf = NULL;
+
+    qemu_mutex_lock(&state->thread_mutex);
+    if (state->streamon == _MC_THREAD_STREAMON) {
+        if (ready_count < MARUCAM_SKIPFRAMES) {
+            /* skip a frame cause first some frame are distorted */
+            ++ready_count;
+            TRACE("Skip %d frame\n", ready_count);
+            qemu_mutex_unlock(&state->thread_mutex);
+            return;
+        }
+        if (state->req_frame == 0) {
+            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;
+        state->req_frame = 0; /* clear request */
+        state->isr |= 0x01;   /* set a flag of rasing a interrupt */
+        qemu_bh_schedule(state->tx_bh);
+    }
+    qemu_mutex_unlock(&state->thread_mutex);
+}
+
+static int read_frame(MaruCamState *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) {
+        switch (errno) {
+        case EAGAIN:
+        case EINTR:
+            ERR("DQBUF error, try again: %s\n", strerror(errno));
+            return 0;
+        case EIO:
+            ERR("The v4l2_read() met the EIO\n");
+            if (convert_trial-- == -1) {
+                ERR("Try count for v4l2_read is exceeded: %s\n",
+                    strerror(errno));
+                return -1;
+            }
+            return 0;
+        default:
+            ERR("DQBUF error: %s\n", strerror(errno));
+            return -1;
+        }
+    }
+
+    notify_buffer_ready(state, buf.index);
+
+    if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) {
+        ERR("QBUF error: %s\n", strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+
+static int __v4l2_streaming(MaruCamState *state)
+{
+    fd_set fds;
+    struct timeval tv;
+    int ret;
+
+    FD_ZERO(&fds);
+    FD_SET(v4l2_fd, &fds);
+
+    tv.tv_sec = 1;
+    tv.tv_usec = 0;
+
+    ret = select(v4l2_fd + 1, &fds, NULL, NULL, &tv);
+    if (ret < 0) {
+        if (errno == EAGAIN || errno == EINTR) {
+            ERR("Select again: %s\n", strerror(errno));
+            return 0;
+        }
+        ERR("Failed to select: %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) {
+            case 1:
+                ERR("Waiting for reading a frame data\n");
+                return 0;
+            case 2:
+            case 3:
+            case 4:
+                ERR("Sends dummy data to initialize the camera\n");
+                __raise_dummy_intr(state);
+                return 0;
+            default:
+                ERR("Webcam is busy, failed to a read frame."
+                    " Raises an error\n");
+                __raise_err_intr(state);
+                return -1;
+            }
+        }
+        if (timeout_n >= 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) {
+            ERR("Sends previous frame data\n");
+            notify_buffer_ready(state, previous_frame_index);
+        }
+        return 0;
+    }
+
+    if (!v4l2_fd || (v4l2_fd == -1)) {
+        ERR("The file descriptor is closed or not opened\n");
+        __raise_err_intr(state);
+        return -1;
+    }
+
+    ret = read_frame(state);
+    if (ret < 0) {
+        ERR("Failed to operate the read_frame()\n");
+        __raise_err_intr(state);
+        return -1;
+    }
+
+    /* clear the skip count for select time-out */
+    if (timeout_n > 0) {
+        timeout_n = 0;
+    }
+
+    return 0;
+}
+
+/* Worker thread */
+static void *marucam_worker_thread(void *thread_param)
+{
+    MaruCamState *state = (MaruCamState *)thread_param;
+
+    while (1) {
+        qemu_mutex_lock(&state->thread_mutex);
+        state->streamon = _MC_THREAD_PAUSED;
+        qemu_cond_wait(&state->thread_cond, &state->thread_mutex);
+        qemu_mutex_unlock(&state->thread_mutex);
+
+        if (state->destroying) {
+            break;
+        }
+
+        convert_trial = 10;
+        ready_count = 0;
+        timeout_n = 0;
+        has_success_frame = 0;
+        qemu_mutex_lock(&state->thread_mutex);
+        state->streamon = _MC_THREAD_STREAMON;
+        qemu_mutex_unlock(&state->thread_mutex);
+        INFO("Streaming on ......\n");
+
+        while (1) {
+            if (is_streamon(state)) {
+                if (__v4l2_streaming(state) < 0) {
+                    INFO("...... Streaming off\n");
+                    break;
+                }
+            } else {
+                INFO("...... Streaming off\n");
+                break;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+int marucam_device_check(int log_flag)
+{
+    int tmp_fd;
+    struct timeval t1, t2;
+    struct stat st;
+    struct v4l2_fmtdesc format;
+    struct v4l2_frmsizeenum size;
+    struct v4l2_capability cap;
+    int ret = 0;
+
+    gettimeofday(&t1, NULL);
+    if (stat(dev_name, &st) < 0) {
+        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);
+        }
+    }
+
+    tmp_fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);
+    if (tmp_fd < 0) {
+        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);
+        return ret;
+    }
+    if (ioctl(tmp_fd, VIDIOC_QUERYCAP, &cap) < 0) {
+        ERR("Could not qeury video capabilities\n");
+        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 (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ||
+            !(cap.capabilities & V4L2_CAP_STREAMING)) {
+        ERR("Not supported video driver\n");
+        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;
+    }
+    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);
+
+        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;
+
+            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);
+
+            }
+            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);
+    return ret;
+}
+
+void marucam_device_init(MaruCamState *state)
+{
+    state->destroying = false;
+    qemu_thread_create(&state->thread_id,
+                       MARUCAM_THREAD_NAME,
+                       marucam_worker_thread,
+                       (void *)state,
+                       QEMU_THREAD_JOINABLE);
+}
+
+void marucam_device_exit(MaruCamState *state)
+{
+    state->destroying = true;
+    qemu_mutex_lock(&state->thread_mutex);
+    qemu_cond_signal(&state->thread_cond);
+    qemu_mutex_unlock(&state->thread_mutex);
+    qemu_thread_join(&state->thread_id);
+}
+
+void marucam_device_open(MaruCamState *state)
+{
+    MaruCamParam *param = state->param;
+
+    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;
+        return;
+    }
+    INFO("Opened\n");
+
+    /* 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.height = 480;
+    dst_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+    dst_fmt.fmt.pix.field = V4L2_FIELD_ANY;
+
+    if (xioctl(v4l2_fd, VIDIOC_S_FMT, &dst_fmt) < 0) {
+        ERR("Failed to set video format: format(0x%x), width:height(%d:%d), "
+          "errstr(%s)\n", dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.width,
+          dst_fmt.fmt.pix.height, strerror(errno));
+        param->errCode = errno;
+        v4l2_close(v4l2_fd);
+        v4l2_fd = -1;
+        return;
+    }
+    TRACE("Set the default 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);
+}
+
+void marucam_device_start_preview(MaruCamState *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) {
+        ERR("Failed to mmap framebuffers\n");
+        if (framebuffer != NULL) {
+            free_framebuffers(framebuffer, n_framebuffer);
+            g_free(framebuffer);
+            framebuffer = NULL;
+            n_framebuffer = 0;
+        }
+        return;
+    }
+
+    param->errCode = start_capturing();
+    if (param->errCode) {
+        if (framebuffer != NULL) {
+            free_framebuffers(framebuffer, n_framebuffer);
+            g_free(framebuffer);
+            framebuffer = NULL;
+            n_framebuffer = 0;
+        }
+        return;
+    }
+
+    INFO("Starting preview\n");
+    state->buf_size = dst_fmt.fmt.pix.sizeimage;
+    qemu_mutex_lock(&state->thread_mutex);
+    qemu_cond_signal(&state->thread_cond);
+    qemu_mutex_unlock(&state->thread_mutex);
+
+    /* nanosleep until thread is streamon  */
+    while (!is_streamon(state)) {
+        nanosleep(&req, NULL);
+    }
+}
+
+void marucam_device_stop_preview(MaruCamState *state)
+{
+    struct timespec req;
+    struct v4l2_requestbuffers reqbuf;
+    MaruCamParam *param = state->param;
+    param->top = 0;
+    req.tv_sec = 0;
+    req.tv_nsec = 50000000;
+
+    if (is_streamon(state)) {
+        qemu_mutex_lock(&state->thread_mutex);
+        state->streamon = _MC_THREAD_STREAMOFF;
+        qemu_mutex_unlock(&state->thread_mutex);
+
+        /* nanosleep until thread is paused  */
+        while (!is_stream_paused(state)) {
+            nanosleep(&req, NULL);
+        }
+    }
+
+    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");
+    }
+
+    param->errCode = stop_capturing();
+    if (framebuffer != NULL) {
+        free_framebuffers(framebuffer, n_framebuffer);
+        g_free(framebuffer);
+        framebuffer = NULL;
+        n_framebuffer = 0;
+    }
+    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) {
+        ERR("Failed to ioctl() with VIDIOC_REQBUF in stop_preview: %s\n",
+            strerror(errno));
+    }
+    INFO("Stopping preview\n");
+}
+
+void marucam_device_s_param(MaruCamState *state)
+{
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+
+    /* 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);
+    }
+}
+
+void marucam_device_g_param(MaruCamState *state)
+{
+    MaruCamParam *param = state->param;
+
+    /* 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 */
+}
+
+void marucam_device_s_fmt(MaruCamState *state)
+{
+    struct v4l2_format format;
+    MaruCamParam *param = state->param;
+
+    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) {
+        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;
+        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;
+    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);
+}
+
+void marucam_device_g_fmt(MaruCamState *state)
+{
+    struct v4l2_format format;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    CLEAR(format);
+    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+    if (xioctl(v4l2_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);
+    }
+}
+
+void marucam_device_try_fmt(MaruCamState *state)
+{
+    struct v4l2_format format;
+    MaruCamParam *param = state->param;
+
+    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) {
+        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;
+        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);
+}
+
+void marucam_device_enum_fmt(MaruCamState *state)
+{
+    uint32_t index;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    index = param->stack[0];
+
+    if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {
+        param->errCode = EINVAL;
+        return;
+    }
+    param->stack[1] = 0; /* flags = NONE */
+    param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */
+    /* set description */
+    switch (supported_dst_pixfmts[index].fmt) {
+    case V4L2_PIX_FMT_YUYV:
+        strcpy((char *)&param->stack[3], "YUYV");
+        break;
+    case V4L2_PIX_FMT_YUV420:
+        strcpy((char *)&param->stack[3], "YU12");
+        break;
+    case V4L2_PIX_FMT_YVU420:
+        strcpy((char *)&param->stack[3], "YV12");
+        break;
+    default:
+        ERR("Invalid fixel format\n");
+        param->errCode = EINVAL;
+        break;
+    }
+}
+
+void marucam_device_qctrl(MaruCamState *state)
+{
+    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) {
+    case V4L2_CID_BRIGHTNESS:
+        TRACE("Query : BRIGHTNESS\n");
+        strcpy(name, "brightness");
+        i = 0;
+        break;
+    case V4L2_CID_CONTRAST:
+        TRACE("Query : CONTRAST\n");
+        strcpy(name, "contrast");
+        i = 1;
+        break;
+    case V4L2_CID_SATURATION:
+        TRACE("Query : SATURATION\n");
+        strcpy(name, "saturation");
+        i = 2;
+        break;
+    case V4L2_CID_SHARPNESS:
+        TRACE("Query : SHARPNESS\n");
+        strcpy(name, "sharpness");
+        i = 3;
+        break;
+    default:
+        ERR("Invalid control ID\n");
+        param->errCode = EINVAL;
+        return;
+    }
+
+    if (xioctl(v4l2_fd, VIDIOC_QUERYCTRL, &ctrl) < 0) {
+        if (errno != EINVAL) {
+            ERR("Failed to query video controls: %s\n", strerror(errno));
+        }
+        param->errCode = errno;
+        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) {
+            ERR("[%s] Failed to get video control value: id(0x%x), "
+                "errstr(%s)\n",
+                __func__, gctrl.id, strerror(errno));
+            param->errCode = errno;
+            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;
+
+        if ((ctrl.maximum + ctrl.minimum) == 0) {
+            sctrl.value = 0;
+        } else {
+            sctrl.value = (ctrl.maximum + ctrl.minimum) / 2;
+        }
+
+        if (xioctl(v4l2_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;
+            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,
+             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(&param->stack[6], (void *)name, sizeof(ctrl.name));
+}
+
+void marucam_device_s_ctrl(MaruCamState *state)
+{
+    uint32_t i;
+    struct v4l2_control ctrl;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    CLEAR(ctrl);
+    ctrl.id = param->stack[0];
+
+    switch (ctrl.id) {
+    case V4L2_CID_BRIGHTNESS:
+        i = 0;
+        TRACE("%d is set to the value of the BRIGHTNESS\n", param->stack[1]);
+        break;
+    case V4L2_CID_CONTRAST:
+        i = 1;
+        TRACE("%d is set to the value of the CONTRAST\n", param->stack[1]);
+        break;
+    case V4L2_CID_SATURATION:
+        i = 2;
+        TRACE("%d is set to the value of the SATURATION\n", param->stack[1]);
+        break;
+    case V4L2_CID_SHARPNESS:
+        i = 3;
+        TRACE("%d is set to the value of the SHARPNESS\n", param->stack[1]);
+        break;
+    default:
+        ERR("Our emulator does not support this control: 0x%x\n", ctrl.id);
+        param->errCode = EINVAL;
+        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;
+        return;
+    }
+}
+
+void marucam_device_g_ctrl(MaruCamState *state)
+{
+    uint32_t i;
+    struct v4l2_control ctrl;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    CLEAR(ctrl);
+    ctrl.id = param->stack[0];
+
+    switch (ctrl.id) {
+    case V4L2_CID_BRIGHTNESS:
+        TRACE("Gets the value of the BRIGHTNESS\n");
+        i = 0;
+        break;
+    case V4L2_CID_CONTRAST:
+        TRACE("Gets the value of the CONTRAST\n");
+        i = 1;
+        break;
+    case V4L2_CID_SATURATION:
+        TRACE("Gets the value of the SATURATION\n");
+        i = 2;
+        break;
+    case V4L2_CID_SHARPNESS:
+        TRACE("Gets the value of the SHARPNESS\n");
+        i = 3;
+        break;
+    default:
+        ERR("Our emulator does not support this control: 0x%x\n", ctrl.id);
+        param->errCode = EINVAL;
+        return;
+    }
+
+    if (xioctl(v4l2_fd, VIDIOC_G_CTRL, &ctrl) < 0) {
+        ERR("Failed to get video control value: %s\n", strerror(errno));
+        param->errCode = errno;
+        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]);
+}
+
+void marucam_device_enum_fsizes(MaruCamState *state)
+{
+    uint32_t index, pixfmt, i;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    index = param->stack[0];
+    pixfmt = param->stack[1];
+
+    if (index >= ARRAY_SIZE(supported_dst_frames)) {
+        param->errCode = EINVAL;
+        return;
+    }
+    for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
+        if (supported_dst_pixfmts[i].fmt == pixfmt) {
+            break;
+        }
+    }
+
+    if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
+        param->errCode = EINVAL;
+        return;
+    }
+
+    param->stack[0] = supported_dst_frames[index].width;
+    param->stack[1] = supported_dst_frames[index].height;
+}
+
+void marucam_device_enum_fintv(MaruCamState *state)
+{
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+
+    /* switch by index(param->stack[0]) */
+    switch (param->stack[0]) {
+    case 0:
+        /* we only use 1/30 frame interval */
+        param->stack[1] = 30;   /* denominator */
+        break;
+    default:
+        param->errCode = EINVAL;
+        return;
+    }
+    param->stack[0] = 1;    /* numerator */
+}
+
+void marucam_device_close(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");
+}
diff --git a/tizen/src/hw/pci/maru_camera_linux_pci.c b/tizen/src/hw/pci/maru_camera_linux_pci.c
deleted file mode 100644 (file)
index 406478b..0000000
+++ /dev/null
@@ -1,1391 +0,0 @@
-/*
- * Implementation of MARU Virtual Camera device by PCI bus on Linux.
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Contact:
- * JinHyung Jo <jinhyung.jo@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-#include "qemu-common.h"
-#include "sysemu/kvm.h"
-#include "maru_camera_common.h"
-#include "debug_ch.h"
-
-#include <linux/videodev2.h>
-
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-
-#include <libv4l2.h>
-#include <libv4lconvert.h>
-
-MULTI_DEBUG_CHANNEL(tizen, camera);
-
-#define MARUCAM_THREAD_NAME    "marucam_worker_thread"
-
-#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
-
-enum {
-    _MC_THREAD_PAUSED,
-    _MC_THREAD_STREAMON,
-    _MC_THREAD_STREAMOFF,
-};
-
-typedef struct marucam_framebuffer {
-    void *data;
-    size_t size;
-} marucam_framebuffer;
-
-struct marucam_saved_frame {
-    void *data;
-    uint32_t pixelformat;
-    uint32_t width;
-    uint32_t height;
-    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;
-
-static const char *dev_name = "/dev/video0";
-static int v4l2_fd;
-static int convert_trial;
-static int ready_count;
-static int timeout_n;
-
-static struct v4l2_format dst_fmt;
-
-static void ScalePlaneSimple(int src_width, int src_height,
-                             int dst_width, int dst_height,
-                             int src_stride, int dst_stride,
-                             const uint8_t *src_ptr, uint8_t *dst_ptr) {
-    int i, j;
-    int dx = (src_width << 16) / dst_width;
-    int dy = (src_height << 16) / dst_height;
-    int y = (dy >= 65536) ? ((dy >> 1) - 32768) : (dy >> 1);
-    for (j = 0; j < dst_height; ++j) {
-        int x = (dx >= 65536) ? ((dx >> 1) - 32768) : (dx >> 1);
-        int yi = y >> 16;
-        const uint8_t *src = src_ptr + yi * src_stride;
-        uint8_t *dst = dst_ptr;
-        for (i = 0; i < dst_width; ++i) {
-            *dst++ = src[x >> 16];
-            x += dx;
-        }
-        dst_ptr += dst_stride;
-        y += dy;
-    }
-}
-
-static void make_yu12_black(unsigned char *dest, uint32_t width, uint32_t height)
-{
-    uint32_t x, y;
-    unsigned char *udest, *vdest;
-
-    /* Y */
-    for (y = 0; y < height; y++) {
-        for (x = 0; x < width; x++) {
-            *dest++ = 16;
-        }
-    }
-
-    /* U + V */
-    udest = dest;
-    vdest = dest + width * height / 4;
-
-    for (y = 0; y < height / 2; y++) {
-        for (x = 0; x < width / 2; x++) {
-            *udest++ = *vdest++ = 128;
-        }
-    }
-}
-
-static void marucam_scale_yuv420(void *src,
-                    uint32_t src_width, uint32_t src_height,
-                    void *dst, uint32_t dst_width, uint32_t dst_height)
-{
-    uint32_t src_halfwidth = (src_width + 1) >> 1;
-    uint32_t src_halfheight = (src_height + 1) >> 1;
-    uint32_t dst_halfwidth = (dst_width + 1) >> 1;
-    uint32_t dst_halfheight = (dst_height + 1) >> 1;
-
-    uint8_t *src_u = src + (src_width * src_height);
-    uint8_t *src_v = src_u + (src_width * src_height / 4);
-
-    uint8_t *dst_u = dst + (dst_width * dst_height);
-    uint8_t *dst_v = dst_u + (dst_width * dst_height /4);
-
-    ScalePlaneSimple(src_width, src_height,
-                     dst_width, dst_height,
-                     src_width, dst_width,
-                     src, dst);
-    ScalePlaneSimple(src_halfwidth, src_halfheight,
-                     dst_halfwidth, dst_halfheight,
-                     src_halfwidth, dst_halfwidth,
-                     src_u, dst_u);
-    ScalePlaneSimple(src_halfwidth, src_halfheight,
-                     dst_halfwidth, dst_halfheight,
-                     src_halfwidth, dst_halfwidth,
-                     src_v, dst_v);
-}
-
-static int yioctl(int fd, int req, void *arg)
-{
-    int r;
-
-    do {
-        r = ioctl(fd, req, arg);
-    } while (r < 0 && errno == EINTR);
-
-    return r;
-}
-
-static int xioctl(int fd, int req, void *arg)
-{
-    int r;
-
-    do {
-        r = v4l2_ioctl(fd, req, arg);
-    } while (r < 0 && errno == EINTR);
-
-    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)
-{
-    uint32_t i;
-    for (i = 0; i < ARRAY_SIZE(qctrl_tbl); i++) {
-        if (qctrl_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) {
-                ERR("Failed to reset control value: id(0x%x), errstr(%s)\n",
-                    ctrl.id, strerror(errno));
-            }
-        }
-    }
-    TRACE("[%s] Reset done\n", __func__);
-}
-
-static int32_t value_convert_from_guest(int32_t min, int32_t max, int32_t value)
-{
-    double rate = 0.0;
-    int32_t dist = 0, ret = 0;
-
-    dist = max - min;
-
-    if (dist < MARUCAM_CTRL_VALUE_MAX) {
-        rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;
-        ret = min + (int32_t)(value / rate);
-    } else {
-        rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;
-        ret = min + (int32_t)(rate * value);
-    }
-    return ret;
-}
-
-static int32_t value_convert_to_guest(int32_t min, int32_t max, int32_t value)
-{
-    double rate  = 0.0;
-    int32_t dist = 0, ret = 0;
-
-    dist = max - min;
-
-    if (dist < MARUCAM_CTRL_VALUE_MAX) {
-        rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;
-        ret = (int32_t)((double)(value - min) * rate);
-    } else {
-        rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;
-        ret = (int32_t)((double)(value - min) / rate);
-    }
-
-    return ret;
-}
-
-static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format,
-                        uint32_t width, uint32_t height)
-{
-    struct v4l2_frmivalenum fival;
-    struct v4l2_streamparm sp;
-    uint32_t min_num = 0, min_denom = 0;
-
-    CLEAR(fival);
-    fival.pixel_format = pixel_format;
-    fival.width = width;
-    fival.height = height;
-
-    if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) < 0) {
-        ERR("Unable to enumerate intervals for pixelformat(0x%x), (%d:%d)\n",
-            pixel_format, width, height);
-        return;
-    }
-
-    if (fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
-        float max_ival = -1.0;
-        do {
-            float cur_ival = (float)fival.discrete.numerator
-                        / (float)fival.discrete.denominator;
-            if (cur_ival > max_ival) {
-                max_ival = cur_ival;
-                min_num = fival.discrete.numerator;
-                min_denom = fival.discrete.denominator;
-            }
-            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);
-    } else if ((fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) ||
-                (fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)) {
-        TRACE("Frame intervals from %u/%u to %u/%u supported",
-            fival.stepwise.min.numerator, fival.stepwise.min.denominator,
-            fival.stepwise.max.numerator, fival.stepwise.max.denominator);
-        if (fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
-            TRACE("with %u/%u step", fival.stepwise.step.numerator,
-                  fival.stepwise.step.denominator);
-        }
-        if (((float)fival.stepwise.max.denominator /
-             (float)fival.stepwise.max.numerator) >
-            ((float)fival.stepwise.min.denominator /
-             (float)fival.stepwise.min.numerator)) {
-            min_num = fival.stepwise.max.numerator;
-            min_denom = fival.stepwise.max.denominator;
-        } else {
-            min_num = fival.stepwise.min.numerator;
-            min_denom = fival.stepwise.min.denominator;
-        }
-    }
-    TRACE("The actual min values: %u/%u\n", min_num, min_denom);
-
-    CLEAR(sp);
-    sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    sp.parm.capture.timeperframe.numerator = min_num;
-    sp.parm.capture.timeperframe.denominator = min_denom;
-
-    if (xioctl(v4l2_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)
-{
-    enum v4l2_buf_type type;
-
-    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    if (xioctl(v4l2_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)
-{
-    enum v4l2_buf_type type;
-
-    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    if (xioctl(v4l2_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)
-{
-    int i;
-
-    if (fb == NULL) {
-        ERR("The framebuffer is NULL. Failed to release the framebuffer\n");
-        return;
-    } else if (buf_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);
-    }
-
-    /* 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;
-        } else {
-            ERR("framebuffer[%d].data is NULL.\n", i);
-        }
-    }
-    previous_frame_index = -1;
-}
-
-static uint32_t
-mmap_framebuffers(marucam_framebuffer **fb, int *buf_num)
-{
-    struct v4l2_requestbuffers req;
-
-    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 (errno == EINVAL) {
-            ERR("%s does not support memory mapping: %s\n",
-                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);
-        return EINVAL;
-    }
-
-    *fb = g_new0(marucam_framebuffer, req.count);
-    if (*fb == NULL) {
-        ERR("Not enough memory to allocate framebuffers\n");
-        return ENOMEM;
-    }
-
-    for (*buf_num = 0; *buf_num < req.count; ++*buf_num) {
-        struct v4l2_buffer buf;
-        CLEAR(buf);
-        buf.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-        buf.memory  = V4L2_MEMORY_MMAP;
-        buf.index   = *buf_num;
-        if (xioctl(v4l2_fd, VIDIOC_QUERYBUF, &buf) < 0) {
-            ERR("Failed to ioctl() with VIDIOC_QUERYBUF: %s\n",
-                strerror(errno));
-            return errno;
-        }
-
-        (*fb)[*buf_num].size = buf.length;
-        (*fb)[*buf_num].data = v4l2_mmap(NULL,
-                     buf.length,
-                     PROT_READ | PROT_WRITE,
-                     MAP_SHARED,
-                     v4l2_fd, buf.m.offset);
-        if (MAP_FAILED == (*fb)[*buf_num].data) {
-            ERR("Failed to mmap: %s\n", strerror(errno));
-            return errno;
-        }
-
-        /* Queue the mapped buffer. */
-        CLEAR(buf);
-        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-        buf.memory = V4L2_MEMORY_MMAP;
-        buf.index = *buf_num;
-        if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) {
-            ERR("Failed to ioctl() with VIDIOC_QBUF: %s\n", strerror(errno));
-            return errno;
-        }
-    }
-    return 0;
-}
-
-static int is_streamon(MaruCamState *state)
-{
-    int st;
-    qemu_mutex_lock(&state->thread_mutex);
-    st = state->streamon;
-    qemu_mutex_unlock(&state->thread_mutex);
-    return (st == _MC_THREAD_STREAMON);
-}
-
-static int is_stream_paused(MaruCamState *state)
-{
-    int st;
-    qemu_mutex_lock(&state->thread_mutex);
-    st = state->streamon;
-    qemu_mutex_unlock(&state->thread_mutex);
-    return (st == _MC_THREAD_PAUSED);
-}
-
-/* sends a frame, YU12/black color  */
-/* TODO: add other pixel format method */
-static void __raise_dummy_intr(MaruCamState *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) {
-                TRACE("Copies the previuos frame\n");
-                memcpy(buf, saved_frame.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);
-            }
-        } else {
-            TRACE("Sends a black frame\n");
-            make_yu12_black(buf,
-                            dst_fmt.fmt.pix.width,
-                            dst_fmt.fmt.pix.height);
-        }
-        state->req_frame = 0; /* clear request */
-        state->isr |= 0x01;   /* set a flag of raising a interrupt */
-        qemu_bh_schedule(state->tx_bh);
-    }
-    qemu_mutex_unlock(&state->thread_mutex);
-}
-
-static void __raise_err_intr(MaruCamState *state)
-{
-    qemu_mutex_lock(&state->thread_mutex);
-    if (state->streamon == _MC_THREAD_STREAMON) {
-        state->req_frame = 0; /* clear request */
-        state->isr = 0x08;   /* set a error flag of raising a interrupt */
-        qemu_bh_schedule(state->tx_bh);
-    }
-    qemu_mutex_unlock(&state->thread_mutex);
-}
-
-static void
-notify_buffer_ready(MaruCamState *state, uint32_t buf_index)
-{
-    void *buf = NULL;
-
-    qemu_mutex_lock(&state->thread_mutex);
-    if (state->streamon == _MC_THREAD_STREAMON) {
-        if (ready_count < MARUCAM_SKIPFRAMES) {
-            /* skip a frame cause first some frame are distorted */
-            ++ready_count;
-            TRACE("Skip %d frame\n", ready_count);
-            qemu_mutex_unlock(&state->thread_mutex);
-            return;
-        }
-        if (state->req_frame == 0) {
-            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;
-        state->req_frame = 0; /* clear request */
-        state->isr |= 0x01;   /* set a flag of rasing a interrupt */
-        qemu_bh_schedule(state->tx_bh);
-    }
-    qemu_mutex_unlock(&state->thread_mutex);
-}
-
-static int read_frame(MaruCamState *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) {
-        switch (errno) {
-        case EAGAIN:
-        case EINTR:
-            ERR("DQBUF error, try again: %s\n", strerror(errno));
-            return 0;
-        case EIO:
-            ERR("The v4l2_read() met the EIO\n");
-            if (convert_trial-- == -1) {
-                ERR("Try count for v4l2_read is exceeded: %s\n",
-                    strerror(errno));
-                return -1;
-            }
-            return 0;
-        default:
-            ERR("DQBUF error: %s\n", strerror(errno));
-            return -1;
-        }
-    }
-
-    notify_buffer_ready(state, buf.index);
-
-    if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) {
-        ERR("QBUF error: %s\n", strerror(errno));
-        return -1;
-    }
-    return 0;
-}
-
-static int __v4l2_streaming(MaruCamState *state)
-{
-    fd_set fds;
-    struct timeval tv;
-    int ret;
-
-    FD_ZERO(&fds);
-    FD_SET(v4l2_fd, &fds);
-
-    tv.tv_sec = 1;
-    tv.tv_usec = 0;
-
-    ret = select(v4l2_fd + 1, &fds, NULL, NULL, &tv);
-    if (ret < 0) {
-        if (errno == EAGAIN || errno == EINTR) {
-            ERR("Select again: %s\n", strerror(errno));
-            return 0;
-        }
-        ERR("Failed to select: %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) {
-            case 1:
-                ERR("Waiting for reading a frame data\n");
-                return 0;
-            case 2:
-            case 3:
-            case 4:
-                ERR("Sends dummy data to initialize the camera\n");
-                __raise_dummy_intr(state);
-                return 0;
-            default:
-                ERR("Webcam is busy, failed to a read frame."
-                    " Raises an error\n");
-                __raise_err_intr(state);
-                return -1;
-            }
-        }
-        if (timeout_n >= 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) {
-            ERR("Sends previous frame data\n");
-            notify_buffer_ready(state, previous_frame_index);
-        }
-        return 0;
-    }
-
-    if (!v4l2_fd || (v4l2_fd == -1)) {
-        ERR("The file descriptor is closed or not opened\n");
-        __raise_err_intr(state);
-        return -1;
-    }
-
-    ret = read_frame(state);
-    if (ret < 0) {
-        ERR("Failed to operate the read_frame()\n");
-        __raise_err_intr(state);
-        return -1;
-    }
-
-    /* clear the skip count for select time-out */
-    if (timeout_n > 0) {
-        timeout_n = 0;
-    }
-
-    return 0;
-}
-
-/* Worker thread */
-static void *marucam_worker_thread(void *thread_param)
-{
-    MaruCamState *state = (MaruCamState *)thread_param;
-
-    while (1) {
-        qemu_mutex_lock(&state->thread_mutex);
-        state->streamon = _MC_THREAD_PAUSED;
-        qemu_cond_wait(&state->thread_cond, &state->thread_mutex);
-        qemu_mutex_unlock(&state->thread_mutex);
-
-        if (state->destroying) {
-            break;
-        }
-
-        convert_trial = 10;
-        ready_count = 0;
-        timeout_n = 0;
-        has_success_frame = 0;
-        qemu_mutex_lock(&state->thread_mutex);
-        state->streamon = _MC_THREAD_STREAMON;
-        qemu_mutex_unlock(&state->thread_mutex);
-        INFO("Streaming on ......\n");
-
-        while (1) {
-            if (is_streamon(state)) {
-                if (__v4l2_streaming(state) < 0) {
-                    INFO("...... Streaming off\n");
-                    break;
-                }
-            } else {
-                INFO("...... Streaming off\n");
-                break;
-            }
-        }
-    }
-
-    return NULL;
-}
-
-int marucam_device_check(int log_flag)
-{
-    int tmp_fd;
-    struct timeval t1, t2;
-    struct stat st;
-    struct v4l2_fmtdesc format;
-    struct v4l2_frmsizeenum size;
-    struct v4l2_capability cap;
-    int ret = 0;
-
-    gettimeofday(&t1, NULL);
-    if (stat(dev_name, &st) < 0) {
-        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);
-        }
-    }
-
-    tmp_fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);
-    if (tmp_fd < 0) {
-        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);
-        return ret;
-    }
-    if (ioctl(tmp_fd, VIDIOC_QUERYCAP, &cap) < 0) {
-        ERR("Could not qeury video capabilities\n");
-        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 (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ||
-            !(cap.capabilities & V4L2_CAP_STREAMING)) {
-        ERR("Not supported video driver\n");
-        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;
-    }
-    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);
-
-        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;
-
-            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);
-
-            }
-            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);
-    return ret;
-}
-
-void marucam_device_init(MaruCamState *state)
-{
-    state->destroying = false;
-    qemu_thread_create(&state->thread_id,
-                       MARUCAM_THREAD_NAME,
-                       marucam_worker_thread,
-                       (void *)state,
-                       QEMU_THREAD_JOINABLE);
-}
-
-void marucam_device_exit(MaruCamState *state)
-{
-    state->destroying = true;
-    qemu_mutex_lock(&state->thread_mutex);
-    qemu_cond_signal(&state->thread_cond);
-    qemu_mutex_unlock(&state->thread_mutex);
-    qemu_thread_join(&state->thread_id);
-}
-
-void marucam_device_open(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
-
-    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;
-        return;
-    }
-    INFO("Opened\n");
-
-    /* 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.height = 480;
-    dst_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
-    dst_fmt.fmt.pix.field = V4L2_FIELD_ANY;
-
-    if (xioctl(v4l2_fd, VIDIOC_S_FMT, &dst_fmt) < 0) {
-        ERR("Failed to set video format: format(0x%x), width:height(%d:%d), "
-          "errstr(%s)\n", dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.width,
-          dst_fmt.fmt.pix.height, strerror(errno));
-        param->errCode = errno;
-        v4l2_close(v4l2_fd);
-        v4l2_fd = -1;
-        return;
-    }
-    TRACE("Set the default 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);
-}
-
-void marucam_device_start_preview(MaruCamState *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) {
-        ERR("Failed to mmap framebuffers\n");
-        if (framebuffer != NULL) {
-            free_framebuffers(framebuffer, n_framebuffer);
-            g_free(framebuffer);
-            framebuffer = NULL;
-            n_framebuffer = 0;
-        }
-        return;
-    }
-
-    param->errCode = start_capturing();
-    if (param->errCode) {
-        if (framebuffer != NULL) {
-            free_framebuffers(framebuffer, n_framebuffer);
-            g_free(framebuffer);
-            framebuffer = NULL;
-            n_framebuffer = 0;
-        }
-        return;
-    }
-
-    INFO("Starting preview\n");
-    state->buf_size = dst_fmt.fmt.pix.sizeimage;
-    qemu_mutex_lock(&state->thread_mutex);
-    qemu_cond_signal(&state->thread_cond);
-    qemu_mutex_unlock(&state->thread_mutex);
-
-    /* nanosleep until thread is streamon  */
-    while (!is_streamon(state)) {
-        nanosleep(&req, NULL);
-    }
-}
-
-void marucam_device_stop_preview(MaruCamState *state)
-{
-    struct timespec req;
-    struct v4l2_requestbuffers reqbuf;
-    MaruCamParam *param = state->param;
-    param->top = 0;
-    req.tv_sec = 0;
-    req.tv_nsec = 50000000;
-
-    if (is_streamon(state)) {
-        qemu_mutex_lock(&state->thread_mutex);
-        state->streamon = _MC_THREAD_STREAMOFF;
-        qemu_mutex_unlock(&state->thread_mutex);
-
-        /* nanosleep until thread is paused  */
-        while (!is_stream_paused(state)) {
-            nanosleep(&req, NULL);
-        }
-    }
-
-    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");
-    }
-
-    param->errCode = stop_capturing();
-    if (framebuffer != NULL) {
-        free_framebuffers(framebuffer, n_framebuffer);
-        g_free(framebuffer);
-        framebuffer = NULL;
-        n_framebuffer = 0;
-    }
-    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) {
-        ERR("Failed to ioctl() with VIDIOC_REQBUF in stop_preview: %s\n",
-            strerror(errno));
-    }
-    INFO("Stopping preview\n");
-}
-
-void marucam_device_s_param(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-
-    /* 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);
-    }
-}
-
-void marucam_device_g_param(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
-
-    /* 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 */
-}
-
-void marucam_device_s_fmt(MaruCamState *state)
-{
-    struct v4l2_format format;
-    MaruCamParam *param = state->param;
-
-    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) {
-        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;
-        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;
-    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);
-}
-
-void marucam_device_g_fmt(MaruCamState *state)
-{
-    struct v4l2_format format;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    CLEAR(format);
-    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-    if (xioctl(v4l2_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);
-    }
-}
-
-void marucam_device_try_fmt(MaruCamState *state)
-{
-    struct v4l2_format format;
-    MaruCamParam *param = state->param;
-
-    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) {
-        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;
-        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);
-}
-
-void marucam_device_enum_fmt(MaruCamState *state)
-{
-    uint32_t index;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    index = param->stack[0];
-
-    if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {
-        param->errCode = EINVAL;
-        return;
-    }
-    param->stack[1] = 0; /* flags = NONE */
-    param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */
-    /* set description */
-    switch (supported_dst_pixfmts[index].fmt) {
-    case V4L2_PIX_FMT_YUYV:
-        strcpy((char *)&param->stack[3], "YUYV");
-        break;
-    case V4L2_PIX_FMT_YUV420:
-        strcpy((char *)&param->stack[3], "YU12");
-        break;
-    case V4L2_PIX_FMT_YVU420:
-        strcpy((char *)&param->stack[3], "YV12");
-        break;
-    default:
-        ERR("Invalid fixel format\n");
-        param->errCode = EINVAL;
-        break;
-    }
-}
-
-void marucam_device_qctrl(MaruCamState *state)
-{
-    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) {
-    case V4L2_CID_BRIGHTNESS:
-        TRACE("Query : BRIGHTNESS\n");
-        strcpy(name, "brightness");
-        i = 0;
-        break;
-    case V4L2_CID_CONTRAST:
-        TRACE("Query : CONTRAST\n");
-        strcpy(name, "contrast");
-        i = 1;
-        break;
-    case V4L2_CID_SATURATION:
-        TRACE("Query : SATURATION\n");
-        strcpy(name, "saturation");
-        i = 2;
-        break;
-    case V4L2_CID_SHARPNESS:
-        TRACE("Query : SHARPNESS\n");
-        strcpy(name, "sharpness");
-        i = 3;
-        break;
-    default:
-        ERR("Invalid control ID\n");
-        param->errCode = EINVAL;
-        return;
-    }
-
-    if (xioctl(v4l2_fd, VIDIOC_QUERYCTRL, &ctrl) < 0) {
-        if (errno != EINVAL) {
-            ERR("Failed to query video controls: %s\n", strerror(errno));
-        }
-        param->errCode = errno;
-        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) {
-            ERR("[%s] Failed to get video control value: id(0x%x), "
-                "errstr(%s)\n",
-                __func__, gctrl.id, strerror(errno));
-            param->errCode = errno;
-            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;
-
-        if ((ctrl.maximum + ctrl.minimum) == 0) {
-            sctrl.value = 0;
-        } else {
-            sctrl.value = (ctrl.maximum + ctrl.minimum) / 2;
-        }
-
-        if (xioctl(v4l2_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;
-            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,
-             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(&param->stack[6], (void *)name, sizeof(ctrl.name));
-}
-
-void marucam_device_s_ctrl(MaruCamState *state)
-{
-    uint32_t i;
-    struct v4l2_control ctrl;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    CLEAR(ctrl);
-    ctrl.id = param->stack[0];
-
-    switch (ctrl.id) {
-    case V4L2_CID_BRIGHTNESS:
-        i = 0;
-        TRACE("%d is set to the value of the BRIGHTNESS\n", param->stack[1]);
-        break;
-    case V4L2_CID_CONTRAST:
-        i = 1;
-        TRACE("%d is set to the value of the CONTRAST\n", param->stack[1]);
-        break;
-    case V4L2_CID_SATURATION:
-        i = 2;
-        TRACE("%d is set to the value of the SATURATION\n", param->stack[1]);
-        break;
-    case V4L2_CID_SHARPNESS:
-        i = 3;
-        TRACE("%d is set to the value of the SHARPNESS\n", param->stack[1]);
-        break;
-    default:
-        ERR("Our emulator does not support this control: 0x%x\n", ctrl.id);
-        param->errCode = EINVAL;
-        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;
-        return;
-    }
-}
-
-void marucam_device_g_ctrl(MaruCamState *state)
-{
-    uint32_t i;
-    struct v4l2_control ctrl;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    CLEAR(ctrl);
-    ctrl.id = param->stack[0];
-
-    switch (ctrl.id) {
-    case V4L2_CID_BRIGHTNESS:
-        TRACE("Gets the value of the BRIGHTNESS\n");
-        i = 0;
-        break;
-    case V4L2_CID_CONTRAST:
-        TRACE("Gets the value of the CONTRAST\n");
-        i = 1;
-        break;
-    case V4L2_CID_SATURATION:
-        TRACE("Gets the value of the SATURATION\n");
-        i = 2;
-        break;
-    case V4L2_CID_SHARPNESS:
-        TRACE("Gets the value of the SHARPNESS\n");
-        i = 3;
-        break;
-    default:
-        ERR("Our emulator does not support this control: 0x%x\n", ctrl.id);
-        param->errCode = EINVAL;
-        return;
-    }
-
-    if (xioctl(v4l2_fd, VIDIOC_G_CTRL, &ctrl) < 0) {
-        ERR("Failed to get video control value: %s\n", strerror(errno));
-        param->errCode = errno;
-        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]);
-}
-
-void marucam_device_enum_fsizes(MaruCamState *state)
-{
-    uint32_t index, pixfmt, i;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    index = param->stack[0];
-    pixfmt = param->stack[1];
-
-    if (index >= ARRAY_SIZE(supported_dst_frames)) {
-        param->errCode = EINVAL;
-        return;
-    }
-    for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
-        if (supported_dst_pixfmts[i].fmt == pixfmt) {
-            break;
-        }
-    }
-
-    if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
-        param->errCode = EINVAL;
-        return;
-    }
-
-    param->stack[0] = supported_dst_frames[index].width;
-    param->stack[1] = supported_dst_frames[index].height;
-}
-
-void marucam_device_enum_fintv(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-
-    /* switch by index(param->stack[0]) */
-    switch (param->stack[0]) {
-    case 0:
-        /* we only use 1/30 frame interval */
-        param->stack[1] = 30;   /* denominator */
-        break;
-    default:
-        param->errCode = EINVAL;
-        return;
-    }
-    param->stack[0] = 1;    /* numerator */
-}
-
-void marucam_device_close(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");
-}
diff --git a/tizen/src/hw/pci/maru_camera_win32.c b/tizen/src/hw/pci/maru_camera_win32.c
new file mode 100644 (file)
index 0000000..337c371
--- /dev/null
@@ -0,0 +1,2499 @@
+/*
+ * Implementation of MARU Virtual Camera device by PCI bus on Windows.
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+
+#include "qemu-common.h"
+#include "sysemu/hax.h"
+#include "maru_camera.h"
+#include "debug_ch.h"
+
+#define CINTERFACE
+#define COBJMACROS
+#include "ocidl.h"
+#include "errors.h"      /* for VFW_E_XXXX */
+#include "mmsystem.h"    /* for MAKEFOURCC macro */
+#include "maru_camera_win32.h"
+
+MULTI_DEBUG_CHANNEL(tizen, camera);
+
+/*
+ * COM Interface implementations
+ *
+ */
+
+#define SAFE_RELEASE(x) \
+    do { \
+        if (x) { \
+            (x)->lpVtbl->Release(x); \
+            x = NULL; \
+        } \
+    } while (0)
+
+typedef HRESULT (STDAPICALLTYPE *CallbackFn)(ULONG dwSize, BYTE *pBuffer);
+
+/*
+ * HWCGrabCallback
+ */
+
+typedef struct HWCGrabCallback {
+    IGrabCallback IGrabCallback_iface;
+    long m_cRef;
+    CallbackFn m_pCallback;
+    STDMETHODIMP (*SetCallback)(IGrabCallback *iface, CallbackFn pCallbackFn);
+} HWCGrabCallback;
+
+static inline HWCGrabCallback *impl_from_IGrabCallback(IGrabCallback *iface)
+{
+    return CONTAINING_RECORD(iface, HWCGrabCallback, IGrabCallback_iface);
+}
+
+static STDMETHODIMP HWCGrabCallback_QueryInterface(IGrabCallback *iface,
+                                                   REFIID riid, void **ppv)
+{
+    if (IsEqualIID(riid, &IID_IUnknown)) {
+        *ppv = (IUnknown *)iface;
+    } else if (IsEqualIID(riid, &IID_IGrabCallback)) {
+        *ppv = (IGrabCallback *)iface;
+    } else {
+        *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+
+    IGrabCallback_AddRef(iface);
+    return S_OK;
+}
+
+static STDMETHODIMP_(ULONG) HWCGrabCallback_AddRef(IGrabCallback *iface)
+{
+    HWCGrabCallback *This = impl_from_IGrabCallback(iface);
+
+    return InterlockedIncrement(&This->m_cRef);
+}
+
+static STDMETHODIMP_(ULONG) HWCGrabCallback_Release(IGrabCallback *iface)
+{
+    HWCGrabCallback *This = impl_from_IGrabCallback(iface);
+
+    if (InterlockedDecrement(&This->m_cRef) == 0) {
+        This->m_pCallback = NULL;
+        g_free((void *)This);
+        This = NULL;
+        return 0;
+    }
+
+    return This->m_cRef;
+}
+
+static STDMETHODIMP HWCGrabCallback_Grab(IGrabCallback *iface,
+                                         ULONG dwSize, BYTE *pBuffer)
+{
+    HWCGrabCallback *This = impl_from_IGrabCallback(iface);
+
+    if (This->m_pCallback) {
+        HRESULT hr = This->m_pCallback(dwSize, pBuffer);
+        if (FAILED(hr)) {
+            return E_FAIL;
+        } else {
+            return S_OK;
+        }
+    }
+
+    return E_FAIL;
+}
+
+static STDMETHODIMP HWCGrabCallback_SetCallback(IGrabCallback *iface,
+                                                CallbackFn pCallbackFn)
+{
+    HWCGrabCallback *This = impl_from_IGrabCallback(iface);
+
+    This->m_pCallback = pCallbackFn;
+    return S_OK;
+}
+
+static IGrabCallbackVtbl HWCGrabCallback_Vtbl = {
+        HWCGrabCallback_QueryInterface,
+        HWCGrabCallback_AddRef,
+        HWCGrabCallback_Release,
+        HWCGrabCallback_Grab
+};
+
+static STDMETHODIMP HWCGrabCallback_Construct(IGrabCallback **ppv)
+{
+    HWCGrabCallback *This =
+            (HWCGrabCallback *)g_malloc0(sizeof(HWCGrabCallback));
+
+    if (!This) {
+        ERR("failed to HWCGrabCallback_Construct, E_OUTOFMEMORY\n");
+        return E_OUTOFMEMORY;
+    }
+
+    This->IGrabCallback_iface.lpVtbl = &HWCGrabCallback_Vtbl;
+    This->m_cRef = 1;
+    This->m_pCallback = NULL;
+    This->SetCallback = HWCGrabCallback_SetCallback;
+    *ppv = &This->IGrabCallback_iface;
+    return S_OK;
+}
+
+/*
+ * HWCPin
+ */
+
+typedef struct HWCInPin {
+    IPin IPin_iface;
+    IMemInputPin IMemInputPin_iface;
+    IBaseFilter *m_pCFilter;
+    IPin *m_pConnectedPin;
+    IGrabCallback *m_pCallback;
+    IMemAllocator *m_pAllocator;
+    BOOL m_bReadOnly;
+    long m_cRef;
+    STDMETHODIMP (*SetGrabCallbackIF)(IPin *iface, IGrabCallback *pCaptureCB);
+} HWCInPin;
+
+static inline HWCInPin *impl_from_IPin(IPin *iface)
+{
+    return CONTAINING_RECORD(iface, HWCInPin, IPin_iface);
+}
+
+static inline HWCInPin *impl_from_IMemInputPin(IMemInputPin *iface)
+{
+    return CONTAINING_RECORD(iface, HWCInPin, IMemInputPin_iface);
+}
+
+static STDMETHODIMP HWCPin_QueryInterface(IPin *iface, REFIID riid, void **ppv)
+{
+    HWCInPin *This = impl_from_IPin(iface);
+
+    if (IsEqualIID(riid, &IID_IUnknown)) {
+        *ppv = (IUnknown *)(&This->IPin_iface);
+        IPin_AddRef((IPin *)*ppv);
+    } else if (IsEqualIID(riid, &IID_IPin)) {
+        *ppv = (IPin *)(&This->IPin_iface);
+        IPin_AddRef((IPin *)*ppv);
+    } else if (IsEqualIID(riid, &IID_IMemInputPin)) {
+        *ppv = (IMemInputPin *)(&This->IMemInputPin_iface);
+        IPin_AddRef((IMemInputPin *)*ppv);
+    } else {
+        *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+
+    return S_OK;
+}
+
+static STDMETHODIMP_(ULONG) HWCPin_AddRef(IPin *iface)
+{
+    HWCInPin *This = impl_from_IPin(iface);
+
+    return InterlockedIncrement(&This->m_cRef);
+}
+
+static STDMETHODIMP_(ULONG) HWCPin_Release(IPin *iface)
+{
+    HWCInPin *This = impl_from_IPin(iface);
+
+    if (InterlockedDecrement(&This->m_cRef) == 0) {
+        if (This->m_pCallback) {
+            SAFE_RELEASE(This->m_pCallback);
+        }
+        if (This->m_pConnectedPin) {
+            SAFE_RELEASE(This->m_pConnectedPin);
+        }
+        if (This->m_pAllocator) {
+            IMemAllocator_Decommit(This->m_pAllocator);
+            SAFE_RELEASE(This->m_pAllocator);
+        }
+        g_free((void *)This);
+        This = NULL;
+        return 0;
+    }
+    return This->m_cRef;
+}
+
+static STDMETHODIMP HWCPin_Connect(IPin *iface,
+                                   IPin *pReceivePin,
+                                   const AM_MEDIA_TYPE *pmt)
+{
+    HWCInPin *This = impl_from_IPin(iface);
+
+    if (!pReceivePin) {
+        return E_POINTER;
+    }
+
+    if (This->m_pConnectedPin) {
+        return VFW_E_ALREADY_CONNECTED;
+    }
+
+    if (!pmt) {
+        return S_OK;
+    }
+    return S_FALSE;
+}
+
+static STDMETHODIMP HWCPin_ReceiveConnection(IPin *iface, IPin *pConnector,
+                                             const AM_MEDIA_TYPE *pmt)
+{
+    PIN_DIRECTION pd;
+    FILTER_STATE fs;
+    HWCInPin *This = impl_from_IPin(iface);
+
+    if (pConnector == NULL || pmt == NULL) {
+        return E_POINTER;
+    }
+
+    if (This->m_pConnectedPin) {
+        return VFW_E_ALREADY_CONNECTED;
+    }
+    IBaseFilter_GetState(This->m_pCFilter, 0, &fs);
+    if (fs != State_Stopped) {
+        return VFW_E_NOT_STOPPED;
+    }
+    IPin_QueryDirection(pConnector, &pd);
+    if (pd == PINDIR_INPUT) {
+        return VFW_E_INVALID_DIRECTION;
+    }
+
+    This->m_pConnectedPin = pConnector;
+    IPin_AddRef(This->m_pConnectedPin);
+    return S_OK;
+}
+
+static STDMETHODIMP HWCPin_Disconnect(IPin *iface)
+{
+    HWCInPin *This = impl_from_IPin(iface);
+
+    HRESULT hr;
+    FILTER_STATE fs;
+    IBaseFilter_GetState(This->m_pCFilter, 0, &fs);
+    if (fs != State_Stopped) {
+        return VFW_E_NOT_STOPPED;
+    }
+    if (This->m_pConnectedPin == NULL) {
+        hr = S_FALSE;
+    } else {
+        if (This->m_pAllocator) {
+            hr = IMemAllocator_Decommit(This->m_pAllocator);
+            if (FAILED(hr)) {
+                return hr;
+            }
+            SAFE_RELEASE(This->m_pAllocator);
+        }
+        SAFE_RELEASE(This->m_pConnectedPin);
+        hr = S_OK;
+    }
+    return hr;
+}
+
+static STDMETHODIMP HWCPin_ConnectedTo(IPin *iface, IPin **ppPin)
+{
+    HWCInPin *This = impl_from_IPin(iface);
+
+    if (ppPin == NULL) {
+        return E_POINTER;
+    }
+
+    if (This->m_pConnectedPin == NULL) {
+        *ppPin = NULL;
+        return VFW_E_NOT_CONNECTED;
+    } else {
+        *ppPin = This->m_pConnectedPin;
+        IPin_AddRef(This->m_pConnectedPin);
+    }
+    return S_OK;
+}
+
+static STDMETHODIMP HWCPin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *pmt)
+{
+    if (pmt == NULL) {
+        return E_POINTER;
+    }
+    return VFW_E_NOT_CONNECTED;
+}
+
+static STDMETHODIMP HWCPin_QueryPinInfo(IPin *iface, PIN_INFO *pInfo)
+{
+    HWCInPin *This = impl_from_IPin(iface);
+
+    if (pInfo == NULL) {
+        return E_POINTER;
+    }
+
+    pInfo->pFilter = This->m_pCFilter;
+    if (This->m_pCFilter) {
+        IBaseFilter_AddRef(This->m_pCFilter);
+    }
+    memcpy((void *)pInfo->achName, (void *)HWCPinName, sizeof(HWCPinName));
+    pInfo->dir = PINDIR_INPUT;
+    return S_OK;
+}
+
+static STDMETHODIMP HWCPin_QueryDirection(IPin *iface, PIN_DIRECTION *pPinDir)
+{
+    if (pPinDir == NULL) {
+        return E_POINTER;
+    }
+    *pPinDir = PINDIR_INPUT;
+    return S_OK;
+}
+
+static STDMETHODIMP HWCPin_QueryId(IPin *iface, LPWSTR *Id)
+{
+    PVOID pId;
+    if (Id == NULL) {
+        return E_POINTER;
+    }
+    pId = CoTaskMemAlloc(sizeof(HWCPinName));
+    memcpy((void *)pId, (void *)HWCPinName, sizeof(HWCPinName));
+    *Id = (LPWSTR)pId;
+    return S_OK;
+}
+
+static STDMETHODIMP HWCPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *pmt)
+{
+    if (pmt == NULL) {
+        return E_POINTER;
+    }
+    return S_OK;
+}
+
+static STDMETHODIMP HWCPin_EnumMediaTypes(IPin *iface,
+                                          IEnumMediaTypes **ppEnum)
+{
+    if (ppEnum == NULL) {
+            return E_POINTER;
+    }
+    return E_NOTIMPL;
+}
+
+static STDMETHODIMP HWCPin_QueryInternalConnections(IPin *iface,
+                                                    IPin **ppPin,
+                                                    ULONG *nPin)
+{
+    return E_NOTIMPL;
+}
+
+static STDMETHODIMP HWCPin_EndOfStream(IPin *iface)
+{
+    return S_OK;
+}
+
+static STDMETHODIMP HWCPin_BeginFlush(IPin *iface)
+{
+    return S_OK;
+}
+
+static STDMETHODIMP HWCPin_EndFlush(IPin *iface)
+{
+    return S_OK;
+}
+
+static STDMETHODIMP HWCPin_NewSegment(IPin *iface, REFERENCE_TIME tStart,
+                                      REFERENCE_TIME tStop, double dRate)
+{
+    return S_OK;
+}
+
+static STDMETHODIMP HWCMemInputPin_QueryInterface(IMemInputPin *iface,
+                                                  REFIID riid, void **ppv)
+{
+    HWCInPin *This = impl_from_IMemInputPin(iface);
+
+    if (IsEqualIID(riid, &IID_IUnknown)) {
+        *ppv = (IUnknown *)(&This->IMemInputPin_iface);
+        IPin_AddRef((IPin *)*ppv);
+    } else if (IsEqualIID(riid, &IID_IPin)) {
+        *ppv = (IPin *)(&This->IPin_iface);
+        IPin_AddRef((IPin *)*ppv);
+    } else if (IsEqualIID(riid, &IID_IMemInputPin)) {
+        *ppv = (IMemInputPin *)(&This->IMemInputPin_iface);
+        IPin_AddRef((IMemInputPin *)*ppv);
+    } else {
+        *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+
+    return S_OK;
+}
+
+static STDMETHODIMP_(ULONG) HWCMemInputPin_AddRef(IMemInputPin *iface)
+{
+    HWCInPin *This = impl_from_IMemInputPin(iface);
+
+    return InterlockedIncrement(&This->m_cRef);
+}
+
+static STDMETHODIMP_(ULONG) HWCMemInputPin_Release(IMemInputPin *iface)
+{
+    HWCInPin *This = impl_from_IMemInputPin(iface);
+
+    if (InterlockedDecrement(&This->m_cRef) == 0) {
+        if (This->m_pCallback) {
+            SAFE_RELEASE(This->m_pCallback);
+        }
+        if (This->m_pConnectedPin) {
+            SAFE_RELEASE(This->m_pConnectedPin);
+        }
+        if (This->m_pAllocator) {
+            IMemAllocator_Decommit(This->m_pAllocator);
+            SAFE_RELEASE(This->m_pAllocator);
+        }
+        g_free((void *)This);
+        This = NULL;
+        return 0;
+    }
+    return This->m_cRef;
+}
+
+static STDMETHODIMP HWCMemInputPin_GetAllocator(IMemInputPin *iface,
+                                                IMemAllocator **ppAllocator)
+{
+    HWCInPin *This = impl_from_IMemInputPin(iface);
+
+    if (ppAllocator == NULL) {
+        return E_POINTER;
+    }
+
+    if (This->m_pAllocator == NULL) {
+        HRESULT hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL,
+                                        CLSCTX_INPROC_SERVER,
+                                        &IID_IMemAllocator,
+                                        (void **)&(This->m_pAllocator));
+        if (FAILED(hr)) {
+            ERR("Failed to CoCreateInstance for retrieving MemoryAllocator\n");
+            return hr;
+        }
+    }
+    assert(This->m_pAllocator != NULL);
+    *ppAllocator = This->m_pAllocator;
+    IMemAllocator_AddRef(This->m_pAllocator);
+
+    return S_OK;
+}
+
+static STDMETHODIMP HWCMemInputPin_NotifyAllocator(IMemInputPin *iface,
+                                                   IMemAllocator *pAllocator,
+                                                   BOOL bReadOnly)
+{
+    HWCInPin *This = impl_from_IMemInputPin(iface);
+
+    if (pAllocator == NULL) {
+        return E_POINTER;
+    }
+
+    IMemAllocator *pOldAllocator = This->m_pAllocator;
+    IMemAllocator_AddRef(pAllocator);
+    This->m_pAllocator = pAllocator;
+
+    if (pOldAllocator != NULL) {
+        SAFE_RELEASE(pOldAllocator);
+    }
+
+    This->m_bReadOnly = bReadOnly;
+
+    return S_OK;
+}
+
+static STDMETHODIMP HWCMemInputPin_GetAllocatorRequirements(
+                                   IMemInputPin *iface,
+                                   ALLOCATOR_PROPERTIES *pProps)
+{
+    return E_NOTIMPL;
+}
+
+static STDMETHODIMP HWCMemInputPin_Receive(IMemInputPin *iface,
+                                           IMediaSample *pSample)
+{
+    HWCInPin *This = impl_from_IMemInputPin(iface);
+
+    if (pSample == NULL) {
+        ERR("pSample is NULL\n");
+        return E_POINTER;
+    }
+    if (This->m_pCallback != NULL) {
+        HRESULT hr;
+        BYTE *pBuffer = NULL;
+        DWORD dwSize = 0;
+        dwSize = IMediaSample_GetSize(pSample);
+        hr = IMediaSample_GetPointer(pSample, &pBuffer);
+        if (FAILED(hr)) {
+            ERR("Receive function : "
+                "failed to IMediaSample_GetPointer, 0x%ld\n", hr);
+            return hr;
+        }
+        hr = IGrabCallback_Grab(This->m_pCallback, dwSize, pBuffer);
+        if (FAILED(hr)) {
+            ERR("Receive function : failed to IGrabCallback_Grab, 0x%ld\n",
+                hr);
+            return hr;
+        }
+    }
+    return S_OK;
+}
+
+static STDMETHODIMP HWCMemInputPin_ReceiveMultiple(IMemInputPin *iface,
+                                                   IMediaSample **pSamples,
+                                                   long nSamples,
+                                                   long *nSamplesProcessed)
+{
+    HRESULT hr = S_OK;
+
+    if (pSamples == NULL) {
+        return E_POINTER;
+    }
+
+    *nSamplesProcessed = 0;
+
+    while (nSamples-- > 0) {
+        hr = IMemInputPin_Receive(iface, pSamples[*nSamplesProcessed]);
+        if (hr != S_OK) {
+            break;
+        }
+        (*nSamplesProcessed)++;
+    }
+    return hr;
+}
+
+static STDMETHODIMP HWCMemInputPin_ReceiveCanBlock(IMemInputPin *iface)
+{
+    return S_FALSE;
+}
+
+static STDMETHODIMP HWCPin_SetCallback(IPin *iface, IGrabCallback *pCaptureCB)
+{
+    HWCInPin *This = impl_from_IPin(iface);
+
+    if (pCaptureCB == NULL) {
+        SAFE_RELEASE(This->m_pCallback);
+    } else {
+        This->m_pCallback = pCaptureCB;
+        IGrabCallback_AddRef(This->m_pCallback);
+    }
+
+    return S_OK;
+}
+
+
+static IPinVtbl HWCPin_Vtbl = {
+    HWCPin_QueryInterface,
+    HWCPin_AddRef,
+    HWCPin_Release,
+    HWCPin_Connect,
+    HWCPin_ReceiveConnection,
+    HWCPin_Disconnect,
+    HWCPin_ConnectedTo,
+    HWCPin_ConnectionMediaType,
+    HWCPin_QueryPinInfo,
+    HWCPin_QueryDirection,
+    HWCPin_QueryId,
+    HWCPin_QueryAccept,
+    HWCPin_EnumMediaTypes,
+    HWCPin_QueryInternalConnections,
+    HWCPin_EndOfStream,
+    HWCPin_BeginFlush,
+    HWCPin_EndFlush,
+    HWCPin_NewSegment
+};
+
+static IMemInputPinVtbl HWCMemInputPin_Vtbl = {
+    HWCMemInputPin_QueryInterface,
+    HWCMemInputPin_AddRef,
+    HWCMemInputPin_Release,
+    HWCMemInputPin_GetAllocator,
+    HWCMemInputPin_NotifyAllocator,
+    HWCMemInputPin_GetAllocatorRequirements,
+    HWCMemInputPin_Receive,
+    HWCMemInputPin_ReceiveMultiple,
+    HWCMemInputPin_ReceiveCanBlock
+};
+
+static STDMETHODIMP HWCInPin_Construct(IBaseFilter *pFilter, IPin **ppv)
+{
+    HWCInPin *This = (HWCInPin *)g_malloc0(sizeof(HWCInPin));
+
+    if (!This) {
+        ERR("failed to HWCInPin_Construct, E_OUTOFMEMORY\n");
+        return E_OUTOFMEMORY;
+    }
+
+    This->IPin_iface.lpVtbl = &HWCPin_Vtbl;
+    This->IMemInputPin_iface.lpVtbl = &HWCMemInputPin_Vtbl;
+    This->m_bReadOnly = FALSE;
+    This->m_pCFilter = pFilter;
+    This->m_pConnectedPin = NULL;
+    This->m_pCallback = NULL;
+    This->m_pAllocator = NULL;
+    This->m_cRef = 1;
+    This->SetGrabCallbackIF = HWCPin_SetCallback;
+    *ppv = &This->IPin_iface;
+
+    return S_OK;
+}
+
+/*
+ * HWCEnumPins
+ */
+
+typedef struct HWCEnumPins {
+    IEnumPins IEnumPins_iface;
+    IBaseFilter *m_pFilter;
+    int m_nPos;
+    long m_cRef;
+} HWCEnumPins;
+
+static inline HWCEnumPins *impl_from_IEnumPins(IEnumPins *iface)
+{
+    return CONTAINING_RECORD(iface, HWCEnumPins, IEnumPins_iface);
+}
+
+static STDMETHODIMP HWCEnumPins_QueryInterface(IEnumPins *iface,
+                                               REFIID riid, void **ppv)
+{
+    if (ppv == NULL) {
+        return E_POINTER;
+    }
+
+    if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumPins)) {
+        *ppv = iface;
+    } else {
+        *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+
+    IEnumPins_AddRef(iface);
+    return S_OK;
+}
+
+static STDMETHODIMP_(ULONG) HWCEnumPins_AddRef(IEnumPins *iface)
+{
+    HWCEnumPins *This = impl_from_IEnumPins(iface);
+
+    return InterlockedIncrement(&This->m_cRef);
+}
+
+static STDMETHODIMP_(ULONG) HWCEnumPins_Release(IEnumPins *iface)
+{
+    HWCEnumPins *This = impl_from_IEnumPins(iface);
+
+    if (InterlockedDecrement(&This->m_cRef) == 0) {
+        if (This->m_pFilter) {
+            SAFE_RELEASE(This->m_pFilter);
+        }
+        This->m_nPos = 0;
+        g_free((void *)This);
+        This = NULL;
+        return 0;
+    }
+    return This->m_cRef;
+}
+
+static STDMETHODIMP HWCEnumPins_Next(IEnumPins *iface, ULONG cPins,
+                                     IPin **ppPins, ULONG *pcFetched)
+{
+    ULONG fetched;
+    HWCEnumPins *This = impl_from_IEnumPins(iface);
+
+    if (ppPins == NULL) {
+        return E_POINTER;
+    }
+
+    if (This->m_nPos < 1 && cPins > 0) {
+        IPin *pPin;
+        IBaseFilter_FindPin(This->m_pFilter, HWCPinName, &pPin);
+        *ppPins = pPin;
+        fetched = 1;
+        This->m_nPos++;
+    } else {
+        fetched = 0;
+    }
+
+    if (pcFetched != NULL) {
+        *pcFetched = fetched;
+    }
+
+    return (fetched == cPins) ? S_OK : S_FALSE;
+}
+
+static STDMETHODIMP HWCEnumPins_Skip(IEnumPins *iface, ULONG cPins)
+{
+    HWCEnumPins *This = impl_from_IEnumPins(iface);
+    This->m_nPos += cPins;
+    return (This->m_nPos >= 1) ? S_FALSE : S_OK;
+}
+
+static STDMETHODIMP HWCEnumPins_Reset(IEnumPins *iface)
+{
+    HWCEnumPins *This = impl_from_IEnumPins(iface);
+    This->m_nPos = 0;
+    return S_OK;
+}
+
+static STDMETHODIMP HWCEnumPins_Construct(IBaseFilter *pFilter,
+                                          int nPos, IEnumPins **ppv);
+
+static STDMETHODIMP HWCEnumPins_Clone(IEnumPins *iface, IEnumPins **ppEnum)
+{
+    HWCEnumPins *This = impl_from_IEnumPins(iface);
+
+    if (ppEnum == NULL) {
+        return E_POINTER;
+    }
+
+    HWCEnumPins_Construct(This->m_pFilter, This->m_nPos, ppEnum);
+    if (*ppEnum == NULL) {
+        ERR("failed to HWCEnumPins_Construct in clone, E_OUTOFMEMORY\n");
+        return E_OUTOFMEMORY;
+    }
+
+    return S_OK;
+}
+
+static IEnumPinsVtbl HWCEnumPins_Vtbl = {
+    HWCEnumPins_QueryInterface,
+    HWCEnumPins_AddRef,
+    HWCEnumPins_Release,
+    HWCEnumPins_Next,
+    HWCEnumPins_Skip,
+    HWCEnumPins_Reset,
+    HWCEnumPins_Clone
+};
+
+
+static STDMETHODIMP HWCEnumPins_Construct(IBaseFilter *pFilter,
+                                          int nPos, IEnumPins **ppv)
+{
+    HWCEnumPins *This = (HWCEnumPins *)g_malloc0(sizeof(HWCEnumPins));
+
+    if (!This) {
+        ERR("failed to HWCEnumPins_Construct, E_OUTOFMEMORY\n");
+        return E_OUTOFMEMORY;
+    }
+
+    This->IEnumPins_iface.lpVtbl = &HWCEnumPins_Vtbl;
+    This->m_pFilter = pFilter;
+    if (This->m_pFilter) {
+        IBaseFilter_AddRef(This->m_pFilter);
+    }
+    This->m_cRef = 1;
+    This->m_nPos = nPos;
+    *ppv = &This->IEnumPins_iface;
+
+    return S_OK;
+}
+
+/*
+ * HWCFilter
+ */
+
+typedef struct HWCFilter {
+    IBaseFilter IBaseFilter_iface;
+    IPin *m_pPin;
+    IFilterGraph *m_pFilterGraph;
+    FILTER_STATE m_state;
+    long m_cRef;
+} HWCFilter;
+
+static inline HWCFilter *impl_from_IBaseFilter(IBaseFilter *iface)
+{
+    return CONTAINING_RECORD(iface, HWCFilter, IBaseFilter_iface);
+}
+
+static STDMETHODIMP HWCFilter_QueryInterface(IBaseFilter *iface,
+                                             REFIID riid, void **ppv)
+{
+    if (IsEqualIID(riid, &IID_IUnknown)) {
+        *ppv = (IUnknown *)iface;
+    } else if (IsEqualIID(riid, &IID_IPersist)) {
+        *ppv = (IPersist *)iface;
+    } else if (IsEqualIID(riid, &IID_IMediaFilter)) {
+        *ppv = (IMediaFilter *)iface;
+    } else if (IsEqualIID(riid, &IID_IBaseFilter)) {
+        *ppv = (IBaseFilter *)iface;
+    } else {
+        *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+
+    IBaseFilter_AddRef(iface);
+    return S_OK;
+}
+
+static STDMETHODIMP_(ULONG) HWCFilter_AddRef(IBaseFilter *iface)
+{
+    HWCFilter *This = impl_from_IBaseFilter(iface);
+
+    return InterlockedIncrement(&This->m_cRef);
+}
+
+static STDMETHODIMP_(ULONG) HWCFilter_Release(IBaseFilter *iface)
+{
+    HWCFilter *This = impl_from_IBaseFilter(iface);
+
+    if (InterlockedDecrement(&This->m_cRef) == 0) {
+        if (This->m_pPin) {
+            SAFE_RELEASE(This->m_pPin);
+        }
+        g_free((void *)This);
+        This = NULL;
+        return 0;
+    }
+    return This->m_cRef;
+}
+
+static STDMETHODIMP HWCFilter_GetClassID(IBaseFilter *iface, CLSID *pClsID)
+{
+    if (pClsID == NULL) {
+        return E_POINTER;
+    }
+    return E_NOTIMPL;
+}
+
+static STDMETHODIMP HWCFilter_GetState(IBaseFilter *iface, DWORD dwMSecs,
+                                       FILTER_STATE *State)
+{
+    HWCFilter *This = impl_from_IBaseFilter(iface);
+    *State = This->m_state;
+    return S_OK;
+}
+
+static STDMETHODIMP HWCFilter_SetSyncSource(IBaseFilter *iface,
+                                            IReferenceClock *pClock)
+{
+    return S_OK;
+}
+
+static STDMETHODIMP HWCFilter_GetSyncSource(IBaseFilter *iface,
+                                            IReferenceClock **pClock)
+{
+    *pClock = NULL;
+    return S_OK;
+}
+
+static STDMETHODIMP HWCFilter_Stop(IBaseFilter *iface)
+{
+    HWCFilter *This = impl_from_IBaseFilter(iface);
+
+    IPin_EndFlush(This->m_pPin);
+    This->m_state = State_Stopped;
+    return S_OK;
+}
+
+static STDMETHODIMP HWCFilter_Pause(IBaseFilter *iface)
+{
+    HWCFilter *This = impl_from_IBaseFilter(iface);
+    This->m_state = State_Paused;
+    return S_OK;
+}
+
+static STDMETHODIMP HWCFilter_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
+{
+    HWCFilter *This = impl_from_IBaseFilter(iface);
+
+    if (This->m_state == State_Stopped) {
+        HRESULT hr;
+        hr = IBaseFilter_Pause(iface);
+        if (FAILED(hr)) {
+            ERR("HWCFilter_Run : Failed to IBaseFilter_Pause, ret=0xld%\n", hr);
+            return hr;
+        }
+    }
+
+    This->m_state = State_Running;
+    return S_OK;
+}
+
+static STDMETHODIMP HWCFilter_EnumPins(IBaseFilter *iface, IEnumPins **ppEnum)
+{
+    if (ppEnum == NULL) {
+        return E_POINTER;
+    }
+
+    HWCEnumPins_Construct(iface, 0, ppEnum);
+    return *ppEnum == NULL ? E_OUTOFMEMORY : S_OK;
+}
+
+static STDMETHODIMP HWCFilter_FindPin(IBaseFilter *iface, LPCWSTR Id,
+                                      IPin **ppPin)
+{
+    HWCFilter *This = impl_from_IBaseFilter(iface);
+
+    if (ppPin == NULL) {
+        return E_POINTER;
+    }
+
+    if (memcmp((void *)Id, (void *)HWCPinName, sizeof(HWCPinName))) {
+        return VFW_E_NOT_FOUND;
+    }
+
+    if (!This->m_pPin) {
+        HWCInPin_Construct(iface, &This->m_pPin);
+    }
+    *ppPin = This->m_pPin;
+
+    IPin_AddRef(This->m_pPin);
+    return S_OK;
+}
+
+static STDMETHODIMP HWCFilter_QueryFilterInfo(IBaseFilter *iface,
+                                              FILTER_INFO *pInfo)
+{
+    HWCFilter *This = impl_from_IBaseFilter(iface);
+
+    if (pInfo == NULL) {
+        return E_POINTER;
+    }
+
+    memcpy((void *)pInfo->achName,
+           (void *)HWCFilterName,
+           sizeof(HWCFilterName));
+    pInfo->pGraph = This->m_pFilterGraph;
+    if (This->m_pFilterGraph) {
+        IFilterGraph_AddRef(This->m_pFilterGraph);
+    }
+    return S_OK;
+}
+
+static STDMETHODIMP HWCFilter_JoinFilterGraph(IBaseFilter *iface,
+                                              IFilterGraph *pGraph,
+                                              LPCWSTR pName)
+{
+    HWCFilter *This = impl_from_IBaseFilter(iface);
+
+    This->m_pFilterGraph = pGraph;
+    return S_OK;
+}
+
+static STDMETHODIMP HWCFilter_QueryVendorInfo(IBaseFilter *iface,
+                                              LPWSTR *pVendorInfo)
+{
+    return E_NOTIMPL;
+}
+
+static IBaseFilterVtbl HWCFilter_Vtbl = {
+    HWCFilter_QueryInterface,
+    HWCFilter_AddRef,
+    HWCFilter_Release,
+    HWCFilter_GetClassID,
+    HWCFilter_Stop,
+    HWCFilter_Pause,
+    HWCFilter_Run,
+    HWCFilter_GetState,
+    HWCFilter_SetSyncSource,
+    HWCFilter_GetSyncSource,
+    HWCFilter_EnumPins,
+    HWCFilter_FindPin,
+    HWCFilter_QueryFilterInfo,
+    HWCFilter_JoinFilterGraph,
+    HWCFilter_QueryVendorInfo
+};
+
+static STDMETHODIMP HWCFilter_Construct(IBaseFilter **ppv)
+{
+    HWCFilter *This = (HWCFilter *)g_malloc0(sizeof(HWCFilter));
+
+    if (!This) {
+        ERR("failed to HWCFilter_Construct, E_OUTOFMEMORY\n");
+        return E_OUTOFMEMORY;
+    }
+
+    This->IBaseFilter_iface.lpVtbl = &HWCFilter_Vtbl;
+    This->m_pFilterGraph = NULL;
+    This->m_state = State_Stopped;
+    This->m_cRef = 1;
+    HWCInPin_Construct(&This->IBaseFilter_iface, &This->m_pPin);
+    *ppv = &This->IBaseFilter_iface;
+
+    return S_OK;
+}
+
+/**********************************************************
+ *
+ * Virtual device implementations
+ *
+ **********************************************************/
+
+
+/*
+ * Declaration global variables for Win32 COM Interfaces
+ */
+IGraphBuilder *g_pGB ;
+ICaptureGraphBuilder2 *g_pCGB;
+IMediaControl *g_pMediaControl;
+
+IPin *g_pOutputPin;
+IPin *g_pInputPin;
+IBaseFilter *g_pDstFilter;
+IBaseFilter *g_pSrcFilter;
+
+IGrabCallback *g_pCallback;
+
+typedef struct tagMaruCamConvertPixfmt {
+    uint32_t fmt;   /* fourcc */
+    uint32_t bpp;   /* bits per pixel, 0 for compressed formats */
+    uint32_t needs_conversion;
+} MaruCamConvertPixfmt;
+
+static MaruCamConvertPixfmt supported_dst_pixfmts[] = {
+        { V4L2_PIX_FMT_YUYV, 16, 0 },
+        { V4L2_PIX_FMT_YUV420, 12, 0 },
+        { V4L2_PIX_FMT_YVU420, 12, 0 },
+};
+
+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 },
+};
+
+#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 marucam_qctrl {
+    uint32_t id;
+    uint32_t hit;
+    long min;
+    long max;
+    long step;
+    long 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 MaruCamState *g_state;
+
+static uint32_t ready_count;
+static uint32_t cur_fmt_idx;
+static uint32_t cur_frame_idx;
+static void *grab_buf;
+static uint32_t g_dwSrcFmt;
+
+
+/*
+ * Helper functions - converting values
+ */
+
+static long value_convert_from_guest(long min, long max, long value)
+{
+    double rate = 0.0;
+    long dist = 0, ret = 0;
+
+    dist = max - min;
+
+    if (dist < MARUCAM_CTRL_VALUE_MAX) {
+        rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;
+        ret = min + (int32_t)(value / rate);
+    } else {
+        rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;
+        ret = min + (int32_t)(rate * value);
+    }
+    return ret;
+}
+
+static long value_convert_to_guest(long min, long max, long value)
+{
+    double rate  = 0.0;
+    long dist = 0, ret = 0;
+
+    dist = max - min;
+
+    if (dist < MARUCAM_CTRL_VALUE_MAX) {
+        rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;
+        ret = (int32_t)((double)(value - min) * rate);
+    } else {
+        rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;
+        ret = (int32_t)((double)(value - min) / rate);
+    }
+
+    return ret;
+}
+
+/*
+ * Callback function for grab frames
+ */
+static STDMETHODIMP marucam_device_callbackfn(ULONG dwSize, BYTE *pBuffer)
+{
+    void *tmp_buf;
+    uint32_t width, height, fmt, imgsize;
+
+    width = supported_dst_frames[cur_frame_idx].width;
+    height = supported_dst_frames[cur_frame_idx].height;
+    fmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
+    imgsize = get_sizeimage(fmt, width, height);
+
+    if (imgsize > (uint32_t)dwSize) {
+        ERR("Image size is mismatched\n");
+        return E_FAIL;
+    }
+
+    if (convert_frame(g_dwSrcFmt, fmt, width, height,
+                      (size_t)dwSize, pBuffer, grab_buf) > 0) {
+        return E_FAIL;
+    }
+
+    qemu_mutex_lock(&g_state->thread_mutex);
+    if (g_state->streamon) {
+        if (ready_count < MARUCAM_SKIPFRAMES) {
+            /* skip a frame cause first some frame are distorted */
+            ++ready_count;
+            TRACE("skip %d frame\n", ready_count);
+            qemu_mutex_unlock(&g_state->thread_mutex);
+            return S_OK;
+        }
+        if (g_state->req_frame == 0) {
+            TRACE("there is no request\n");
+            qemu_mutex_unlock(&g_state->thread_mutex);
+            return S_OK;
+        }
+        tmp_buf = g_state->vaddr + g_state->buf_size * (g_state->req_frame - 1);
+        memcpy(tmp_buf, grab_buf, g_state->buf_size);
+        g_state->req_frame = 0; /* clear request */
+        g_state->isr |= 0x01;   /* set a flag of rasing a interrupt */
+        qemu_bh_schedule(g_state->tx_bh);
+    }
+    qemu_mutex_unlock(&g_state->thread_mutex);
+    return S_OK;
+}
+
+/*
+ * Internal functions for manipulate interfaces
+ */
+
+static STDMETHODIMP_(void) CloseInterfaces(void)
+{
+    if (g_pMediaControl) {
+        g_pMediaControl->lpVtbl->Stop(g_pMediaControl);
+    }
+
+    if (g_pOutputPin) {
+        g_pOutputPin->lpVtbl->Disconnect(g_pOutputPin);
+    }
+
+    SAFE_RELEASE(g_pGB);
+    SAFE_RELEASE(g_pCGB);
+    SAFE_RELEASE(g_pMediaControl);
+    SAFE_RELEASE(g_pOutputPin);
+    SAFE_RELEASE(g_pInputPin);
+    SAFE_RELEASE(g_pDstFilter);
+    SAFE_RELEASE(g_pSrcFilter);
+    SAFE_RELEASE(g_pCallback);
+}
+
+static STDMETHODIMP_(void) DeleteMediaType(AM_MEDIA_TYPE *pmt)
+{
+    if (pmt == NULL) {
+        return;
+    }
+
+    if (pmt->cbFormat != 0) {
+        CoTaskMemFree((PVOID)pmt->pbFormat);
+        pmt->cbFormat = 0;
+        pmt->pbFormat = NULL;
+    }
+    if (pmt->pUnk != NULL) {
+        pmt->pUnk->lpVtbl->Release(pmt->pUnk);
+        pmt->pUnk = NULL;
+    }
+
+    CoTaskMemFree((PVOID)pmt);
+}
+
+static STDMETHODIMP GetPin(IBaseFilter *pFilter,
+                           PIN_DIRECTION PinDir, IPin **ppPin)
+{
+    HRESULT hr;
+    IEnumPins *pEnum = NULL;
+    IPin *pPin = NULL;
+
+    if (ppPin == NULL) {
+        return E_POINTER;
+    }
+
+    hr = pFilter->lpVtbl->EnumPins(pFilter, &pEnum);
+    if (FAILED(hr)) {
+        return hr;
+    }
+
+    while (pEnum->lpVtbl->Next(pEnum, 1, &pPin, 0) == S_OK) {
+        PIN_DIRECTION PinDirThis;
+        hr = pPin->lpVtbl->QueryDirection(pPin, &PinDirThis);
+        if (FAILED(hr)) {
+            SAFE_RELEASE(pPin);
+            SAFE_RELEASE(pEnum);
+            return hr;
+        }
+        if (PinDir == PinDirThis) {
+            *ppPin = pPin;
+            SAFE_RELEASE(pEnum);
+            return S_OK;
+        }
+        SAFE_RELEASE(pPin);
+    }
+
+    SAFE_RELEASE(pEnum);
+    return S_FALSE;
+}
+
+static STDMETHODIMP GraphBuilder_Init(void)
+{
+    HRESULT hr;
+
+    hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC,
+                          &IID_IGraphBuilder, (void **)&g_pGB);
+    if (FAILED(hr)) {
+        ERR("Failed to create instance of GraphBuilder, 0x%x\n", hr);
+        return hr;
+    }
+
+    hr = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC,
+                          &IID_ICaptureGraphBuilder2, (void **)&g_pCGB);
+    if (FAILED(hr)) {
+        ERR("Failed to create instance of CaptureGraphBuilder2, 0x%x\n", hr);
+        return hr;
+    }
+
+    hr = g_pCGB->lpVtbl->SetFiltergraph(g_pCGB, g_pGB);
+    if (FAILED(hr)) {
+        ERR("Failed to SetFiltergraph, 0x%x\n", hr);
+        return hr;
+    }
+
+    hr = g_pGB->lpVtbl->QueryInterface(g_pGB, &IID_IMediaControl,
+                                       (void **)&g_pMediaControl);
+    if (FAILED(hr)) {
+        ERR("Failed to QueryInterface for IMediaControl, 0x%x\n", hr);
+        return hr;
+    }
+
+    hr = HWCGrabCallback_Construct(&g_pCallback);
+    if (g_pCallback == NULL) {
+        hr = E_OUTOFMEMORY;
+    }
+
+    hr = ((HWCGrabCallback *)g_pCallback)->SetCallback(g_pCallback,
+                            (CallbackFn)marucam_device_callbackfn);
+
+    return hr;
+}
+
+static STDMETHODIMP BindSourceFilter(void)
+{
+    HRESULT hr;
+    ICreateDevEnum *pCreateDevEnum = NULL;
+    IEnumMoniker *pEnumMK = NULL;
+    IMoniker *pMoniKer;
+
+    hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
+                          &IID_ICreateDevEnum,
+                          (void **)&pCreateDevEnum);
+    if (FAILED(hr)) {
+        ERR("Failed to create instance of CreateDevEnum, 0x%x\n", hr);
+        return hr;
+    }
+
+    hr = pCreateDevEnum->lpVtbl->CreateClassEnumerator(pCreateDevEnum,
+                                      &CLSID_VideoInputDeviceCategory,
+                                      &pEnumMK, 0);
+    if (FAILED(hr)) {
+        ERR("Failed to get VideoInputDeviceCategory, 0x%x\n", hr);
+        SAFE_RELEASE(pCreateDevEnum);
+        return hr;
+    }
+
+    if (!pEnumMK) {
+        ERR("ClassEnumerator moniker is NULL\n");
+        SAFE_RELEASE(pCreateDevEnum);
+        return E_FAIL;
+    }
+    pEnumMK->lpVtbl->Reset(pEnumMK);
+
+    hr = pEnumMK->lpVtbl->Next(pEnumMK, 1, &pMoniKer, NULL);
+    if (hr == S_FALSE) {
+        hr = E_FAIL;
+    }
+    if (SUCCEEDED(hr)) {
+        IPropertyBag *pBag = NULL;
+        hr = pMoniKer->lpVtbl->BindToStorage(pMoniKer, 0, 0,
+                                             &IID_IPropertyBag,
+                                             (void **)&pBag);
+        if (SUCCEEDED(hr)) {
+            VARIANT var;
+            var.vt = VT_BSTR;
+            hr = pBag->lpVtbl->Read(pBag, L"FriendlyName", &var, NULL);
+            if (hr == NOERROR) {
+                hr = pMoniKer->lpVtbl->BindToObject(pMoniKer, NULL, NULL,
+                                                    &IID_IBaseFilter,
+                                                    (void **)&g_pSrcFilter);
+                if (FAILED(hr)) {
+                    ERR("Counldn't bind moniker to filter object!!\n");
+                } else {
+                    g_pSrcFilter->lpVtbl->AddRef(g_pSrcFilter);
+                }
+                SysFreeString(var.bstrVal);
+            }
+            SAFE_RELEASE(pBag);
+        }
+        SAFE_RELEASE(pMoniKer);
+    }
+
+    if (SUCCEEDED(hr)) {
+        hr = g_pGB->lpVtbl->AddFilter(g_pGB, g_pSrcFilter, L"Video Capture");
+        if (hr != S_OK && hr != S_FALSE) {
+            ERR("Counldn't add Video Capture filter to our graph!\n");
+            SAFE_RELEASE(g_pSrcFilter);
+        }
+    }
+    SAFE_RELEASE(pEnumMK);
+    SAFE_RELEASE(pCreateDevEnum);
+
+    return hr;
+}
+
+static STDMETHODIMP BindTargetFilter(void)
+{
+    HRESULT hr;
+    hr = HWCFilter_Construct(&g_pDstFilter);
+
+    if (SUCCEEDED(hr) && g_pDstFilter) {
+        hr = g_pGB->lpVtbl->AddFilter(g_pGB, g_pDstFilter, L"HWCFilter");
+        if (FAILED(hr)) {
+            ERR("Counldn't add HWCFilterr to our graph!\n");
+            SAFE_RELEASE(g_pDstFilter);
+        }
+    }
+    return hr;
+}
+
+static STDMETHODIMP ConnectFilters(void)
+{
+    HRESULT hr;
+
+    hr = GetPin(g_pSrcFilter, PINDIR_OUTPUT , &g_pOutputPin);
+    if (FAILED(hr)) {
+        ERR("Failed to get output pin. 0x%x\n", hr);
+        return hr;
+    }
+
+    hr = GetPin(g_pDstFilter, PINDIR_INPUT , &g_pInputPin);
+    if (FAILED(hr)) {
+        ERR("Failed to get input pin. 0x%x\n", hr);
+        return hr;
+    }
+
+    hr = g_pGB->lpVtbl->Connect(g_pGB, g_pOutputPin, g_pInputPin);
+    if (FAILED(hr)) {
+        ERR("Failed to connect pins. 0x%x\n", hr);
+    }
+    return hr;
+}
+
+static STDMETHODIMP DisconnectPins(void)
+{
+    HRESULT hr;
+
+    hr = g_pGB->lpVtbl->Disconnect(g_pGB, g_pOutputPin);
+    if (FAILED(hr)) {
+        ERR("Failed to disconnect output pin. 0x%x\n", hr);
+        return hr;
+    }
+
+    hr = g_pGB->lpVtbl->Disconnect(g_pGB, g_pInputPin);
+    if (FAILED(hr)) {
+        ERR("Failed to disconnect input pin. 0x%x\n", hr);
+    }
+
+    return hr;
+}
+
+static STDMETHODIMP RemoveFilters(void)
+{
+    HRESULT hr;
+
+    hr = g_pGB->lpVtbl->RemoveFilter(g_pGB, g_pSrcFilter);
+    if (FAILED(hr)) {
+        ERR("Failed to remove source filer. 0x%x\n", hr);
+        return hr;
+    }
+
+    hr = g_pGB->lpVtbl->RemoveFilter(g_pGB, g_pDstFilter);
+    if (FAILED(hr)) {
+        ERR("Failed to remove destination filer. 0x%x\n", hr);
+    }
+
+    return hr;
+}
+
+/* default fps is 15 */
+#define MARUCAM_DEFAULT_FRAMEINTERVAL    666666
+
+static STDMETHODIMP SetFormat(uint32_t dwWidth, uint32_t dwHeight,
+                              uint32_t dwDstFmt, uint32_t *dwSrcFmt)
+{
+    HRESULT hr;
+    IAMStreamConfig *pSConfig;
+    int iCount = 0, iSize = 0;
+    DWORD dwYUY2 = MAKEFOURCC('Y', 'U', 'Y', '2');
+    DWORD dwI420 = MAKEFOURCC('I', '4', '2', '0');
+
+    if (dwSrcFmt == NULL) {
+        ERR("invalid the source format pointer\n");
+        return E_FAIL;
+    }
+
+    hr = g_pCGB->lpVtbl->FindInterface(g_pCGB, &PIN_CATEGORY_CAPTURE, 0,
+                                       g_pSrcFilter, &IID_IAMStreamConfig,
+                                       (void **)&pSConfig);
+    if (FAILED(hr)) {
+        ERR("failed to FindInterface method\n");
+        return hr;
+    }
+
+    hr = pSConfig->lpVtbl->GetNumberOfCapabilities(pSConfig, &iCount, &iSize);
+    if (FAILED(hr)) {
+        ERR("failed to GetNumberOfCapabilities method\n");
+        SAFE_RELEASE(pSConfig);
+        return hr;
+    }
+
+    if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) {
+        int iFormat = 0;
+        for (iFormat = 0; iFormat < iCount; iFormat++) {
+            VIDEO_STREAM_CONFIG_CAPS scc;
+            AM_MEDIA_TYPE *pmtConfig;
+
+            hr = pSConfig->lpVtbl->GetStreamCaps(pSConfig, iFormat,
+                                                 &pmtConfig, (BYTE *)&scc);
+            if (hr == S_OK) {
+                if (IsEqualIID(&pmtConfig->formattype, &FORMAT_VideoInfo)) {
+                    VIDEOINFOHEADER *pvi =
+                                         (VIDEOINFOHEADER *)pmtConfig->pbFormat;
+                    if ((pvi->bmiHeader.biWidth == (LONG)dwWidth) &&
+                        (pvi->bmiHeader.biHeight == (LONG)dwHeight)) {
+                        if (pvi->bmiHeader.biCompression == dwYUY2) {
+                            *dwSrcFmt = V4L2_PIX_FMT_YUYV;
+                        } else if ((pvi->bmiHeader.biCompression == BI_RGB) &&
+                                (pvi->bmiHeader.biBitCount == 24)) {
+                            *dwSrcFmt = V4L2_PIX_FMT_RGB24;
+                        } else if (pvi->bmiHeader.biCompression == dwI420) {
+                            *dwSrcFmt = V4L2_PIX_FMT_YUV420;
+                        } else { /* not support format */
+                            DeleteMediaType(pmtConfig);
+                            continue;
+                        }
+                        /* use minimum FPS(maximum frameinterval)
+                           with non-VT system  */
+#ifdef CONFIG_HAX
+                        if (!hax_enabled()) {
+                            pvi->AvgTimePerFrame =
+                                    (REFERENCE_TIME)scc.MaxFrameInterval;
+                        } else {
+                            pvi->AvgTimePerFrame =
+                                (REFERENCE_TIME)MARUCAM_DEFAULT_FRAMEINTERVAL;
+                        }
+#else
+                        pvi->AvgTimePerFrame =
+                                (REFERENCE_TIME)scc.MaxFrameInterval;
+#endif
+                        hr = pSConfig->lpVtbl->SetFormat(pSConfig, pmtConfig);
+                        DeleteMediaType(pmtConfig);
+                        break;
+                    }
+                }
+                DeleteMediaType(pmtConfig);
+            }
+        }
+        if (iFormat >= iCount) {
+            ERR("Failed to Set format. "
+                "Maybe connected webcam does not support the (%ldx%ld) "
+                "resolution or image formats(YUY2, RGB24, I420).\n",
+                dwWidth, dwHeight);
+            hr = E_FAIL;
+        }
+    }
+    SAFE_RELEASE(pSConfig);
+    return hr;
+}
+
+static STDMETHODIMP QueryVideoProcAmp(long nProperty, long *pMin, long *pMax,
+                                      long *pStep, long *pDefault)
+{
+    HRESULT hr;
+    long Flags;
+    IAMVideoProcAmp *pProcAmp = NULL;
+
+    hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter,
+                                              &IID_IAMVideoProcAmp,
+                                              (void **)&pProcAmp);
+    if (FAILED(hr)) {
+        return hr;
+    }
+
+    hr = pProcAmp->lpVtbl->GetRange(pProcAmp, nProperty, pMin, pMax,
+                                    pStep, pDefault, &Flags);
+
+    SAFE_RELEASE(pProcAmp);
+    return hr;
+}
+
+static STDMETHODIMP GetVideoProcAmp(long nProperty, long *pValue)
+{
+    HRESULT hr;
+    long Flags;
+    IAMVideoProcAmp *pProcAmp = NULL;
+
+    hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter,
+                                              &IID_IAMVideoProcAmp,
+                                              (void **)&pProcAmp);
+    if (FAILED(hr)) {
+        return hr;
+    }
+
+    hr = pProcAmp->lpVtbl->Get(pProcAmp, nProperty, pValue, &Flags);
+    if (FAILED(hr)) {
+        ERR("Failed to get property for video\n");
+    }
+
+    SAFE_RELEASE(pProcAmp);
+    return hr;
+}
+
+static STDMETHODIMP SetVideoProcAmp(long nProperty, long value)
+{
+    HRESULT hr;
+
+    IAMVideoProcAmp *pProcAmp = NULL;
+    hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter,
+                                              &IID_IAMVideoProcAmp,
+                                              (void **)&pProcAmp);
+    if (FAILED(hr)) {
+        return hr;
+    }
+
+    hr = pProcAmp->lpVtbl->Set(pProcAmp, nProperty, value,
+                               VideoProcAmp_Flags_Manual);
+    if (FAILED(hr)) {
+        ERR("Failed to set property for video\n");
+    }
+    SAFE_RELEASE(pProcAmp);
+    return hr;
+}
+
+static char *__wchar_to_char(const WCHAR *pwstr)
+{
+    char *pstr = NULL;
+    int len = 0;
+
+    len = wcslen(pwstr) + 1;
+    pstr = (char *)g_malloc0(sizeof(char) * len);
+    wcstombs(pstr, pwstr, len + 1);
+
+    return pstr;
+}
+
+int marucam_device_check(int log_flag)
+{
+    struct timeval t1, t2;
+    int ret = 0;
+    char *device_name = NULL;
+    HRESULT hr = E_FAIL;
+    ICreateDevEnum *pCreateDevEnum = NULL;
+    IGraphBuilder *pGB = NULL;
+    ICaptureGraphBuilder2 *pCGB = NULL;
+    IBaseFilter *pSrcFilter = NULL;
+    IEnumMoniker *pEnumMK = NULL;
+    IMoniker *pMoniKer = NULL;
+    IAMStreamConfig *pSConfig = NULL;
+    int iCount = 0, iSize = 0;
+
+    gettimeofday(&t1, NULL);
+    hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+    if (FAILED(hr)) {
+        ERR("Failed to CoInitailizeEx\n");
+        gettimeofday(&t2, NULL);
+        ERR("Elapsed time : %lu.%06lu\n",
+                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+        return ret;
+    }
+
+    hr = CoCreateInstance(&CLSID_FilterGraph, NULL,
+                          CLSCTX_INPROC,
+                          &IID_IGraphBuilder,
+                          (void **)&pGB);
+    if (FAILED(hr)) {
+        ERR("Failed to create GraphBuilder, 0x%x\n", hr);
+        CoUninitialize();
+        gettimeofday(&t2, NULL);
+        ERR("Elapsed time : %lu.%06lu\n",
+                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+        return ret;
+    }
+
+    hr = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL,
+                          CLSCTX_INPROC,
+                          &IID_ICaptureGraphBuilder2,
+                          (void **)&pCGB);
+    if (FAILED(hr)) {
+        ERR("Failed to create CaptureGraphBuilder2, 0x%x\n", hr);
+        SAFE_RELEASE(pGB);
+        CoUninitialize();
+        gettimeofday(&t2, NULL);
+        ERR("Elapsed time : %lu.%06lu\n",
+                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+        return ret;
+    }
+
+    hr = pCGB->lpVtbl->SetFiltergraph(pCGB, pGB);
+    if (FAILED(hr)) {
+        ERR("Failed to SetFiltergraph, 0x%x\n", hr);
+        SAFE_RELEASE(pCGB);
+        SAFE_RELEASE(pGB);
+        CoUninitialize();
+        gettimeofday(&t2, NULL);
+        ERR("Elapsed time : %lu.%06lu\n",
+                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+        return ret;
+    }
+
+    hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL,
+                          CLSCTX_INPROC,
+                          &IID_ICreateDevEnum,
+                          (void **)&pCreateDevEnum);
+    if (FAILED(hr)) {
+        ERR("Failed to create instance of CLSID_SystemDeviceEnum\n");
+        SAFE_RELEASE(pCGB);
+        SAFE_RELEASE(pGB);
+        CoUninitialize();
+        gettimeofday(&t2, NULL);
+        ERR("Elapsed time : %lu.%06lu\n",
+                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+        return ret;
+    }
+
+    hr = pCreateDevEnum->lpVtbl->CreateClassEnumerator(pCreateDevEnum,
+                                  &CLSID_VideoInputDeviceCategory, &pEnumMK, 0);
+    if (FAILED(hr)) {
+        ERR("Failed to create class enumerator\n");
+        SAFE_RELEASE(pCreateDevEnum);
+        SAFE_RELEASE(pCGB);
+        SAFE_RELEASE(pGB);
+        CoUninitialize();
+        gettimeofday(&t2, NULL);
+        ERR("Elapsed time : %lu.%06lu\n",
+                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+        return ret;
+    }
+
+    if (!pEnumMK) {
+        ERR("Class enumerator is NULL!!\n");
+        SAFE_RELEASE(pCreateDevEnum);
+        SAFE_RELEASE(pCGB);
+        SAFE_RELEASE(pGB);
+        CoUninitialize();
+        gettimeofday(&t2, NULL);
+        ERR("Elapsed time : %lu.%06lu\n",
+                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+        return ret;
+    }
+    pEnumMK->lpVtbl->Reset(pEnumMK);
+
+    hr = pEnumMK->lpVtbl->Next(pEnumMK, 1, &pMoniKer, NULL);
+    if (FAILED(hr) || (hr == S_FALSE)) {
+        ERR("Enum moniker returns a invalid value.\n");
+        SAFE_RELEASE(pEnumMK);
+        SAFE_RELEASE(pCreateDevEnum);
+        SAFE_RELEASE(pCGB);
+        SAFE_RELEASE(pGB);
+        CoUninitialize();
+        gettimeofday(&t2, NULL);
+        ERR("Elapsed time : %lu.%06lu\n",
+                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+        return ret;
+    }
+
+    IPropertyBag *pBag = NULL;
+    hr = pMoniKer->lpVtbl->BindToStorage(pMoniKer, 0, 0,
+                                         &IID_IPropertyBag,
+                                         (void **)&pBag);
+    if (FAILED(hr)) {
+        ERR("Failed to bind to storage.\n");
+        SAFE_RELEASE(pEnumMK);
+        SAFE_RELEASE(pCreateDevEnum);
+        SAFE_RELEASE(pCGB);
+        SAFE_RELEASE(pGB);
+        CoUninitialize();
+        gettimeofday(&t2, NULL);
+        ERR("Elapsed time : %lu.%06lu\n",
+                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+        return ret;
+    } else {
+        VARIANT var;
+        var.vt = VT_BSTR;
+        hr = pBag->lpVtbl->Read(pBag, L"FriendlyName", &var, NULL);
+        if (hr == S_OK) {
+            ret = 1;
+            if (!log_flag) {
+                SysFreeString(var.bstrVal);
+                SAFE_RELEASE(pBag);
+                SAFE_RELEASE(pMoniKer);
+                SAFE_RELEASE(pEnumMK);
+                SAFE_RELEASE(pCreateDevEnum);
+                SAFE_RELEASE(pCGB);
+                SAFE_RELEASE(pGB);
+                CoUninitialize();
+                gettimeofday(&t2, NULL);
+                ERR("Elapsed time : %lu.%06lu\n",
+                                t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+                return ret;
+            }
+            device_name = __wchar_to_char(var.bstrVal);
+            INFO("Device name : %s\n", device_name);
+            g_free(device_name);
+            hr = pMoniKer->lpVtbl->BindToObject(pMoniKer, NULL, NULL,
+                                                &IID_IBaseFilter,
+                                                (void **)&pSrcFilter);
+            if (FAILED(hr)) {
+                ERR("Counldn't bind moniker to filter object!!\n");
+                SysFreeString(var.bstrVal);
+                SAFE_RELEASE(pBag);
+                SAFE_RELEASE(pMoniKer);
+                SAFE_RELEASE(pEnumMK);
+                SAFE_RELEASE(pCreateDevEnum);
+                SAFE_RELEASE(pCGB);
+                SAFE_RELEASE(pGB);
+                CoUninitialize();
+                gettimeofday(&t2, NULL);
+                ERR("Elapsed time : %lu.%06lu\n",
+                                t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+                return ret;
+            } else {
+                pSrcFilter->lpVtbl->AddRef(pSrcFilter);
+            }
+            SysFreeString(var.bstrVal);
+        }
+        SAFE_RELEASE(pBag);
+    }
+    SAFE_RELEASE(pMoniKer);
+
+    hr = pGB->lpVtbl->AddFilter(pGB, pSrcFilter, L"Video Capture");
+    if (hr != S_OK && hr != S_FALSE) {
+        ERR("Counldn't add Video Capture filter to our graph!\n");
+        SAFE_RELEASE(pSrcFilter);
+        SAFE_RELEASE(pEnumMK);
+        SAFE_RELEASE(pCreateDevEnum);
+        SAFE_RELEASE(pCGB);
+        SAFE_RELEASE(pGB);
+        CoUninitialize();
+        gettimeofday(&t2, NULL);
+        ERR("Elapsed time : %lu.%06lu\n",
+                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+        return ret;
+    }
+
+    hr = pCGB->lpVtbl->FindInterface(pCGB, &PIN_CATEGORY_CAPTURE, 0,
+                                       pSrcFilter, &IID_IAMStreamConfig,
+                                       (void **)&pSConfig);
+    if (FAILED(hr)) {
+        ERR("Failed to FindInterface method\n");
+        SAFE_RELEASE(pSrcFilter);
+        SAFE_RELEASE(pEnumMK);
+        SAFE_RELEASE(pCreateDevEnum);
+        SAFE_RELEASE(pCGB);
+        SAFE_RELEASE(pGB);
+        CoUninitialize();
+        gettimeofday(&t2, NULL);
+        ERR("Elapsed time : %lu.%06lu\n",
+                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+        return ret;
+    }
+
+    hr = pSConfig->lpVtbl->GetNumberOfCapabilities(pSConfig, &iCount, &iSize);
+    if (FAILED(hr)) {
+        ERR("Failed to GetNumberOfCapabilities method\n");
+        SAFE_RELEASE(pSConfig);
+        SAFE_RELEASE(pSrcFilter);
+        SAFE_RELEASE(pEnumMK);
+        SAFE_RELEASE(pCreateDevEnum);
+        SAFE_RELEASE(pCGB);
+        SAFE_RELEASE(pGB);
+        CoUninitialize();
+        gettimeofday(&t2, NULL);
+        ERR("Elapsed time : %lu.%06lu\n",
+                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+        return ret;
+    }
+
+    if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) {
+        int iFormat = 0;
+        for (iFormat = 0; iFormat < iCount; iFormat++) {
+            VIDEO_STREAM_CONFIG_CAPS scc;
+            AM_MEDIA_TYPE *pmtConfig;
+
+            hr = pSConfig->lpVtbl->GetStreamCaps(pSConfig, iFormat, &pmtConfig,
+                                                 (BYTE *)&scc);
+            if (hr == S_OK) {
+                if (IsEqualIID(&pmtConfig->formattype, &FORMAT_VideoInfo)) {
+                    VIDEOINFOHEADER *pvi =
+                                         (VIDEOINFOHEADER *)pmtConfig->pbFormat;
+                    if (pvi->bmiHeader.biCompression == BI_RGB) {
+                        INFO("RGB BitCount: %d, Frame size: %ux%u\n",
+                                pvi->bmiHeader.biBitCount,
+                                pvi->bmiHeader.biWidth,
+                                pvi->bmiHeader.biHeight);
+                    } else {
+                        INFO("PixelFormat: %c%c%c%c, Frame size: %ux%u\n",
+                            (char)(pvi->bmiHeader.biCompression),
+                            (char)(pvi->bmiHeader.biCompression >> 8),
+                            (char)(pvi->bmiHeader.biCompression >> 16),
+                            (char)(pvi->bmiHeader.biCompression >> 24),
+                            pvi->bmiHeader.biWidth,
+                            pvi->bmiHeader.biHeight);
+                    }
+                }
+                DeleteMediaType(pmtConfig);
+            }
+        }
+    }
+
+    hr = pGB->lpVtbl->RemoveFilter(pGB, pSrcFilter);
+    if (FAILED(hr)) {
+        ERR("Failed to remove source filer. 0x%x\n", hr);
+    }
+
+    SAFE_RELEASE(pSConfig);
+    SAFE_RELEASE(pSrcFilter);
+    SAFE_RELEASE(pCGB);
+    SAFE_RELEASE(pGB);
+    SAFE_RELEASE(pEnumMK);
+    SAFE_RELEASE(pCreateDevEnum);
+    CoUninitialize();
+    gettimeofday(&t2, NULL);
+    ERR("Elapsed time : %lu.%06lu\n",
+                    t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+
+    return ret;
+}
+
+/* MARUCAM_CMD_INIT */
+void marucam_device_init(MaruCamState *state)
+{
+    g_state = state;
+}
+
+void marucam_device_exit(MaruCamState *state)
+{
+}
+
+/* MARUCAM_CMD_OPEN */
+void marucam_device_open(MaruCamState *state)
+{
+    HRESULT hr;
+    uint32_t dwHeight, dwWidth, dwDstFmt;
+    MaruCamParam *param = state->param;
+    param->top = 0;
+
+    hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+    if (FAILED(hr)) {
+        ERR("CoInitailizeEx\n");
+        ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);
+        param->errCode = EINVAL;
+        return;
+    }
+
+    hr = GraphBuilder_Init();
+    if (FAILED(hr)) {
+        ERR("GraphBuilder_Init\n");
+        DisconnectPins();
+        RemoveFilters();
+        CloseInterfaces();
+        CoUninitialize();
+        param->errCode = EINVAL;
+        ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);
+        return;
+    }
+
+    hr = BindSourceFilter();
+    if (FAILED(hr)) {
+        ERR("BindSourceFilter\n");
+        DisconnectPins();
+        RemoveFilters();
+        CloseInterfaces();
+        CoUninitialize();
+        param->errCode = EINVAL;
+        ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);
+        return;
+    }
+
+    hr = BindTargetFilter();
+    if (FAILED(hr)) {
+        ERR("BindTargetFilter\n");
+        DisconnectPins();
+        RemoveFilters();
+        CloseInterfaces();
+        CoUninitialize();
+        param->errCode = EINVAL;
+        ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);
+        return;
+    }
+
+    hr = ConnectFilters();
+    if (FAILED(hr)) {
+        ERR("ConnectFilters\n");
+        DisconnectPins();
+        RemoveFilters();
+        CloseInterfaces();
+        CoUninitialize();
+        param->errCode = EINVAL;
+        ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);
+        return;
+    }
+
+    cur_frame_idx = 0;
+    cur_fmt_idx = 0;
+
+    dwHeight = supported_dst_frames[cur_frame_idx].height;
+    dwWidth = supported_dst_frames[cur_frame_idx].width;
+    dwDstFmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
+    hr = SetFormat(dwWidth, dwHeight, dwDstFmt, &g_dwSrcFmt);
+    if (hr != S_OK) {
+        ERR("failed to Set default values\n");
+        DisconnectPins();
+        RemoveFilters();
+        CloseInterfaces();
+        CoUninitialize();
+        param->errCode = EINVAL;
+        ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);
+        return;
+    }
+
+    INFO("Opened\n");
+    return;
+}
+
+/* MARUCAM_CMD_CLOSE */
+void marucam_device_close(MaruCamState *state)
+{
+    MaruCamParam *param = state->param;
+    int ret = 0;
+    param->top = 0;
+
+    qemu_mutex_lock(&state->thread_mutex);
+    ret = state->streamon;
+    qemu_mutex_unlock(&state->thread_mutex);
+    if (ret) {
+        marucam_device_stop_preview(state);
+    }
+
+    if (g_pGB) {
+        DisconnectPins();
+        RemoveFilters();
+    }
+    CloseInterfaces();
+    CoUninitialize();
+    INFO("Closed\n");
+}
+
+/* MARUCAM_CMD_START_PREVIEW */
+void marucam_device_start_preview(MaruCamState *state)
+{
+    HRESULT hr;
+    uint32_t pixfmt, width, height;
+    MaruCamParam *param = state->param;
+    param->top = 0;
+
+    ready_count = 0;
+    width = supported_dst_frames[cur_frame_idx].width;
+    height = supported_dst_frames[cur_frame_idx].height;
+    pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
+    state->buf_size = get_sizeimage(pixfmt, width, height);
+
+    INFO("Pixfmt(%c%c%c%c), W:H(%d:%d), buf size(%u)\n",
+         (char)(pixfmt), (char)(pixfmt >> 8),
+         (char)(pixfmt >> 16), (char)(pixfmt >> 24),
+         width, height, state->buf_size);
+    INFO("Starting preview\n");
+
+    assert(g_pCallback != NULL);
+    hr = ((HWCInPin *)g_pInputPin)->SetGrabCallbackIF(g_pInputPin,
+                                                       g_pCallback);
+    if (FAILED(hr)) {
+        ERR("Failed to set IGrabCallback interface.\n");
+        param->errCode = EINVAL;
+        return;
+    }
+
+    if (grab_buf) {
+        g_free(grab_buf);
+        grab_buf = NULL;
+    }
+    grab_buf = (void *)g_malloc0(state->buf_size);
+    if (grab_buf == NULL) {
+        param->errCode = ENOMEM;
+        return;
+    }
+
+    hr = g_pMediaControl->lpVtbl->Run(g_pMediaControl);
+    if (FAILED(hr)) {
+        ERR("Failed to run media control. hr=0x%x\n", hr);
+        param->errCode = EINVAL;
+        return;
+    }
+
+    qemu_mutex_lock(&state->thread_mutex);
+    state->streamon = 1;
+    qemu_mutex_unlock(&state->thread_mutex);
+
+    INFO("Streaming on ......\n");
+}
+
+/* MARUCAM_CMD_STOP_PREVIEW */
+void marucam_device_stop_preview(MaruCamState *state)
+{
+    HRESULT hr;
+    MaruCamParam *param = state->param;
+    param->top = 0;
+
+    INFO("...... Streaming off\n");
+    qemu_mutex_lock(&state->thread_mutex);
+    state->streamon = 0;
+    qemu_mutex_unlock(&state->thread_mutex);
+
+    hr = ((HWCInPin *)g_pInputPin)->SetGrabCallbackIF(g_pInputPin, NULL);
+    if (FAILED(hr)) {
+        ERR("Failed to set IGrabCallback interface.\n");
+        param->errCode = EINVAL;
+        return;
+    }
+
+    hr = g_pMediaControl->lpVtbl->Stop(g_pMediaControl);
+    if (FAILED(hr)) {
+        ERR("Failed to stop media control.\n");
+        param->errCode = EINVAL;
+        return;
+    }
+
+    if (grab_buf) {
+        g_free(grab_buf);
+        grab_buf = NULL;
+    }
+    state->buf_size = 0;
+
+    INFO("Stopping preview\n");
+}
+
+/* MARUCAM_CMD_S_PARAM */
+void marucam_device_s_param(MaruCamState *state)
+{
+    MaruCamParam *param = state->param;
+
+    /* We use default FPS of the webcam */
+    param->top = 0;
+}
+
+/* MARUCAM_CMD_G_PARAM */
+void marucam_device_g_param(MaruCamState *state)
+{
+    MaruCamParam *param = state->param;
+
+    /* 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 */
+}
+
+/* MARUCAM_CMD_S_FMT */
+void marucam_device_s_fmt(MaruCamState *state)
+{
+    uint32_t width, height, pixfmt, pidx, fidx;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    width = param->stack[0];
+    height = param->stack[1];
+    pixfmt = param->stack[2];
+
+    for (fidx = 0; fidx < ARRAY_SIZE(supported_dst_frames); fidx++) {
+        if ((supported_dst_frames[fidx].width == width) &&
+                (supported_dst_frames[fidx].height == height)) {
+            break;
+        }
+    }
+    if (fidx == ARRAY_SIZE(supported_dst_frames)) {
+        param->errCode = EINVAL;
+        return;
+    }
+    for (pidx = 0; pidx < ARRAY_SIZE(supported_dst_pixfmts); pidx++) {
+        if (supported_dst_pixfmts[pidx].fmt == pixfmt) {
+            break;
+        }
+    }
+    if (pidx == ARRAY_SIZE(supported_dst_pixfmts)) {
+        param->errCode = EINVAL;
+        return;
+    }
+
+    if ((supported_dst_frames[cur_frame_idx].width != width) &&
+            (supported_dst_frames[cur_frame_idx].height != height)) {
+        HRESULT hr = SetFormat(width, height, pixfmt, &g_dwSrcFmt);
+        if (FAILED(hr)) {
+            param->errCode = EINVAL;
+            return;
+        }
+    }
+
+    cur_frame_idx = fidx;
+    cur_fmt_idx = pidx;
+
+    pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
+    width = supported_dst_frames[cur_frame_idx].width;
+    height = supported_dst_frames[cur_frame_idx].height;
+
+    param->stack[0] = width;
+    param->stack[1] = height;
+    param->stack[2] = 1; /* V4L2_FIELD_NONE */
+    param->stack[3] = pixfmt;
+    param->stack[4] = get_bytesperline(pixfmt, width);
+    param->stack[5] = get_sizeimage(pixfmt, width, height);
+    param->stack[6] = 0;
+    param->stack[7] = 0;
+
+    TRACE("Set format...\n");
+}
+
+/* MARUCAM_CMD_G_FMT */
+void marucam_device_g_fmt(MaruCamState *state)
+{
+    uint32_t width, height, pixfmt;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
+    width = supported_dst_frames[cur_frame_idx].width;
+    height = supported_dst_frames[cur_frame_idx].height;
+
+    param->stack[0] = width;
+    param->stack[1] = height;
+    param->stack[2] = 1; /* V4L2_FIELD_NONE */
+    param->stack[3] = pixfmt;
+    param->stack[4] = get_bytesperline(pixfmt, width);
+    param->stack[5] = get_sizeimage(pixfmt, width, height);
+    param->stack[6] = 0;
+    param->stack[7] = 0;
+
+    TRACE("Get format...\n");
+}
+
+void marucam_device_try_fmt(MaruCamState *state)
+{
+    uint32_t width, height, pixfmt, i;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    width = param->stack[0];
+    height = param->stack[1];
+    pixfmt = param->stack[2];
+
+    for (i = 0; i < ARRAY_SIZE(supported_dst_frames); i++) {
+        if ((supported_dst_frames[i].width == width) &&
+                (supported_dst_frames[i].height == height)) {
+            break;
+        }
+    }
+    if (i == ARRAY_SIZE(supported_dst_frames)) {
+        param->errCode = EINVAL;
+        return;
+    }
+    for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
+        if (supported_dst_pixfmts[i].fmt == pixfmt) {
+            break;
+        }
+    }
+    if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
+        param->errCode = EINVAL;
+        return;
+    }
+
+    param->stack[0] = width;
+    param->stack[1] = height;
+    param->stack[2] = 1; /* V4L2_FIELD_NONE */
+    param->stack[3] = pixfmt;
+    param->stack[4] = get_bytesperline(pixfmt, width);
+    param->stack[5] = get_sizeimage(pixfmt, width, height);
+    param->stack[6] = 0;
+    param->stack[7] = 0;
+}
+
+void marucam_device_enum_fmt(MaruCamState *state)
+{
+    uint32_t index;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    index = param->stack[0];
+
+    if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {
+        param->errCode = EINVAL;
+        return;
+    }
+    param->stack[1] = 0; /* flags = NONE */
+    param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */
+    /* set description */
+    switch (supported_dst_pixfmts[index].fmt) {
+    case V4L2_PIX_FMT_YUYV:
+        memcpy(&param->stack[3], "YUYV", 32);
+        break;
+    case V4L2_PIX_FMT_YUV420:
+        memcpy(&param->stack[3], "YU12", 32);
+        break;
+    case V4L2_PIX_FMT_YVU420:
+        memcpy(&param->stack[3], "YV12", 32);
+        break;
+    default:
+        ERR("Invalid pixel format\n");
+        param->errCode = EINVAL;
+        break;
+    }
+}
+
+void marucam_device_qctrl(MaruCamState *state)
+{
+    HRESULT hr;
+    uint32_t id, i;
+    long property, min, max, step, def_val, set_val;
+    char name[32] = {0,};
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    id = param->stack[0];
+
+    switch (id) {
+    case V4L2_CID_BRIGHTNESS:
+        TRACE("V4L2_CID_BRIGHTNESS\n");
+        property = VideoProcAmp_Brightness;
+        memcpy((void *)name, (void *)"brightness", 32);
+        i = 0;
+        break;
+    case V4L2_CID_CONTRAST:
+        TRACE("V4L2_CID_CONTRAST\n");
+        property = VideoProcAmp_Contrast;
+        memcpy((void *)name, (void *)"contrast", 32);
+        i = 1;
+        break;
+    case V4L2_CID_SATURATION:
+        TRACE("V4L2_CID_SATURATION\n");
+        property = VideoProcAmp_Saturation;
+        memcpy((void *)name, (void *)"saturation", 32);
+        i = 2;
+        break;
+    case V4L2_CID_SHARPNESS:
+        TRACE("V4L2_CID_SHARPNESS\n");
+        property = VideoProcAmp_Sharpness;
+        memcpy((void *)name, (void *)"sharpness", 32);
+        i = 3;
+        break;
+    default:
+        ERR("Invalid control ID\n");
+        param->errCode = EINVAL;
+        return;
+    }
+    hr = QueryVideoProcAmp(property, &min, &max, &step, &def_val);
+    if (FAILED(hr)) {
+        param->errCode = EINVAL;
+        ERR("failed to query video controls [HRESULT : 0x%x]\n", hr);
+        return;
+    } else {
+        qctrl_tbl[i].hit = 1;
+        qctrl_tbl[i].min = min;
+        qctrl_tbl[i].max = max;
+        qctrl_tbl[i].step = step;
+        qctrl_tbl[i].init_val = def_val;
+
+        if ((qctrl_tbl[i].min + qctrl_tbl[i].max) == 0) {
+            set_val = 0;
+        } else {
+            set_val = (qctrl_tbl[i].min + qctrl_tbl[i].max) / 2;
+        }
+        hr = SetVideoProcAmp(property, set_val);
+        if (FAILED(hr)) {
+            param->errCode = EINVAL;
+            ERR("failed to set video control value, [HRESULT : 0x%x]\n", hr);
+            return;
+        }
+    }
+
+    param->stack[0] = 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] = V4L2_CTRL_FLAG_SLIDER;
+    /* name field setting */
+    memcpy(&param->stack[6], (void *)name, sizeof(name)/sizeof(name[0]));
+}
+
+void marucam_device_s_ctrl(MaruCamState *state)
+{
+    HRESULT hr;
+    uint32_t i;
+    long property, set_val;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+
+    switch (param->stack[0]) {
+    case V4L2_CID_BRIGHTNESS:
+        i = 0;
+        property = VideoProcAmp_Brightness;
+        break;
+    case V4L2_CID_CONTRAST:
+        i = 1;
+        property = VideoProcAmp_Contrast;
+        break;
+    case V4L2_CID_SATURATION:
+        i = 2;
+        property = VideoProcAmp_Saturation;
+        break;
+    case V4L2_CID_SHARPNESS:
+        i = 3;
+        property = VideoProcAmp_Sharpness;
+        break;
+    default:
+        param->errCode = EINVAL;
+        return;
+    }
+    set_val = value_convert_from_guest(qctrl_tbl[i].min,
+            qctrl_tbl[i].max, (long)param->stack[1]);
+    hr = SetVideoProcAmp(property, set_val);
+    if (FAILED(hr)) {
+        param->errCode = EINVAL;
+        ERR("failed to set video control value, [HRESULT : 0x%x]\n", hr);
+        return;
+    }
+}
+
+void marucam_device_g_ctrl(MaruCamState *state)
+{
+    HRESULT hr;
+    uint32_t i;
+    long property, get_val;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    switch (param->stack[0]) {
+    case V4L2_CID_BRIGHTNESS:
+        i = 0;
+        property = VideoProcAmp_Brightness;
+        break;
+    case V4L2_CID_CONTRAST:
+        i = 1;
+        property = VideoProcAmp_Contrast;
+        break;
+    case V4L2_CID_SATURATION:
+        i = 2;
+        property = VideoProcAmp_Saturation;
+        break;
+    case V4L2_CID_SHARPNESS:
+        i = 3;
+        property = VideoProcAmp_Sharpness;
+        break;
+    default:
+        param->errCode = EINVAL;
+        return;
+    }
+
+    hr = GetVideoProcAmp(property, &get_val);
+    if (FAILED(hr)) {
+        param->errCode = EINVAL;
+        ERR("failed to get video control value!!!, [HRESULT : 0x%x]\n", hr);
+        return;
+    }
+    param->stack[0] = (uint32_t)value_convert_to_guest(qctrl_tbl[i].min,
+                qctrl_tbl[i].max, get_val);
+}
+
+void marucam_device_enum_fsizes(MaruCamState *state)
+{
+    uint32_t index, pixfmt, i;
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+    index = param->stack[0];
+    pixfmt = param->stack[1];
+
+    if (index >= ARRAY_SIZE(supported_dst_frames)) {
+        param->errCode = EINVAL;
+        return;
+    }
+    for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
+        if (supported_dst_pixfmts[i].fmt == pixfmt) {
+            break;
+        }
+    }
+
+    if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
+        param->errCode = EINVAL;
+        return;
+    }
+
+    param->stack[0] = supported_dst_frames[index].width;
+    param->stack[1] = supported_dst_frames[index].height;
+}
+
+void marucam_device_enum_fintv(MaruCamState *state)
+{
+    MaruCamParam *param = state->param;
+
+    param->top = 0;
+
+    /* switch by index(param->stack[0]) */
+    switch (param->stack[0]) {
+    case 0:
+        param->stack[1] = 30; /* denominator */
+        break;
+    default:
+        param->errCode = EINVAL;
+        return;
+    }
+    param->stack[0] = 1; /* numerator */
+}
diff --git a/tizen/src/hw/pci/maru_camera_win32.h b/tizen/src/hw/pci/maru_camera_win32.h
new file mode 100644 (file)
index 0000000..f1dcd8b
--- /dev/null
@@ -0,0 +1,932 @@
+/*
+ * Interface definition header for Windows host.
+ *
+ * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ * Jinhyung Jo <jinhyung.jo@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#ifndef _MARU_CAMERA_WIN32_H_
+#define _MARU_CAMERA_WIN32_H_
+
+static const WCHAR HWCPinName[] = L"HWCInputPin\0";
+static const WCHAR HWCFilterName[] = L"HWCFilter\0";
+
+/* Forward Declarations */
+FWD_DECL(IBaseFilter);
+FWD_DECL(IFilterGraph);
+
+/* defines */
+#define MAX_PIN_NAME     128
+#define MAX_FILTER_NAME  128
+
+#define DECLARE_INTERFACE2(i) \
+   _COM_interface i { CONST_VTABLE struct i##Vtbl *lpVtbl; }; \
+   typedef CONST_VTABLE struct i##Vtbl i##Vtbl; \
+   CONST_VTABLE struct i##Vtbl
+#define DECLARE_INTERFACE2_(i, b) DECLARE_INTERFACE2(i)
+
+typedef LONGLONG REFERENCE_TIME;
+typedef long OAFilterState;
+typedef DWORD_PTR HSEMAPHORE;
+typedef DWORD_PTR HEVENT;
+
+typedef enum _FilterState {
+  State_Stopped,
+  State_Paused,
+  State_Running
+} FILTER_STATE;
+
+typedef struct _FilterInfo {
+  WCHAR achName[MAX_FILTER_NAME];
+  IFilterGraph *pGraph;
+} FILTER_INFO;
+
+typedef enum _PinDirection {
+    PINDIR_INPUT    = 0,
+    PINDIR_OUTPUT   = (PINDIR_INPUT + 1)
+} PIN_DIRECTION;
+
+typedef struct _PinInfo {
+  IBaseFilter *pFilter;
+  PIN_DIRECTION dir;
+  WCHAR achName[MAX_PIN_NAME];
+} PIN_INFO;
+
+typedef struct _AllocatorProperties {
+  long cBuffers;
+  long cbBuffer;
+  long cbAlign;
+  long cbPrefix;
+} ALLOCATOR_PROPERTIES;
+
+typedef struct _AMMediaType {
+  GUID majortype;
+  GUID subtype;
+  BOOL bFixedSizeSamples;
+  BOOL bTemporalCompression;
+  ULONG lSampleSize;
+  GUID formattype;
+  IUnknown *pUnk;
+  ULONG cbFormat;
+  BYTE *pbFormat;
+} AM_MEDIA_TYPE;
+
+typedef enum tagVideoProcAmpFlags {
+    VideoProcAmp_Flags_Auto = 0x0001,
+    VideoProcAmp_Flags_Manual = 0x0002
+} VideoProcAmpFlags;
+
+typedef enum tagVideoProcAmpProperty {
+    VideoProcAmp_Brightness,
+    VideoProcAmp_Contrast,
+    VideoProcAmp_Hue,
+    VideoProcAmp_Saturation,
+    VideoProcAmp_Sharpness,
+    VideoProcAmp_Gamma,
+    VideoProcAmp_ColorEnable,
+    VideoProcAmp_WhiteBalance,
+    VideoProcAmp_BacklightCompensation,
+    VideoProcAmp_Gain
+} VideoProcAmpProperty;
+
+typedef struct tagVIDEOINFOHEADER {
+    RECT rcSource;
+    RECT rcTarget;
+    DWORD dwBitRate;
+    DWORD dwBitErrorRate;
+    REFERENCE_TIME AvgTimePerFrame;
+    BITMAPINFOHEADER bmiHeader;
+} VIDEOINFOHEADER;
+
+typedef struct _VIDEO_STREAM_CONFIG_CAPS {
+  GUID guid;
+  ULONG VideoStandard;
+  SIZE InputSize;
+  SIZE MinCroppingSize;
+  SIZE MaxCroppingSize;
+  int CropGranularityX;
+  int CropGranularityY;
+  int CropAlignX;
+  int CropAlignY;
+  SIZE MinOutputSize;
+  SIZE MaxOutputSize;
+  int OutputGranularityX;
+  int OutputGranularityY;
+  int StretchTapsX;
+  int StretchTapsY;
+  int ShrinkTapsX;
+  int ShrinkTapsY;
+  LONGLONG MinFrameInterval;
+  LONGLONG MaxFrameInterval;
+  LONG MinBitsPerSecond;
+  LONG MaxBitsPerSecond;
+} VIDEO_STREAM_CONFIG_CAPS;
+
+
+/* Interface & Class GUIDs */
+static const IID IID_IGrabCallback   = {0x4C337035,0xC89E,0x4B42,{0x9B,0x0C,0x36,0x74,0x44,0xDD,0x70,0xDD}};
+
+EXTERN_C const IID IID_IBaseFilter;
+EXTERN_C const IID IID_ICreateDevEnum;
+EXTERN_C const IID IID_IGraphBuilder;
+EXTERN_C const IID IID_IMediaSeeking;
+EXTERN_C const IID IID_IMediaEventSink;
+EXTERN_C const IID IID_IMemInputPin;
+EXTERN_C const IID IID_IEnumPins;
+EXTERN_C const IID IID_IMediaFilter;
+EXTERN_C const IID IID_IEnumMediaTypes;
+EXTERN_C const IID IID_IMemAllocator;
+EXTERN_C const IID IID_IPin;
+EXTERN_C const IID IID_ICaptureGraphBuilder2;
+EXTERN_C const IID IID_IFileSinkFilter;
+EXTERN_C const IID IID_IAMCopyCaptureFileProgress;
+EXTERN_C const IID IID_IEnumFilters;
+EXTERN_C const IID IID_IMediaSample;
+EXTERN_C const IID IID_IMediaControl;
+EXTERN_C const IID IID_IAMStreamConfig;
+EXTERN_C const IID IID_IAMVideoProcAmp;
+
+EXTERN_C const IID CLSID_CaptureGraphBuilder2;
+EXTERN_C const IID CLSID_VideoInputDeviceCategory;
+EXTERN_C const IID CLSID_AudioRender;
+EXTERN_C const IID CLSID_SystemDeviceEnum;
+EXTERN_C const IID CLSID_AudioRendererCategory;
+EXTERN_C const IID CLSID_FilterGraph;
+EXTERN_C const IID CLSID_InfTee;
+EXTERN_C const IID CLSID_VideoMixingRenderer9;
+EXTERN_C const IID CLSID_MemoryAllocator;
+
+
+/* other types GUIDs*/
+EXTERN_C const IID MEDIATYPE_Audio;
+EXTERN_C const IID MEDIATYPE_Video;
+EXTERN_C const IID MEDIATYPE_Stream;
+EXTERN_C const IID MEDIASUBTYPE_PCM;
+EXTERN_C const IID MEDIASUBTYPE_WAVE;
+EXTERN_C const IID MEDIASUBTYPE_Avi;
+EXTERN_C const IID MEDIASUBTYPE_RGB32;
+EXTERN_C const IID MEDIASUBTYPE_YV12;
+EXTERN_C const IID MEDIASUBTYPE_YUY2;
+EXTERN_C const IID MEDIASUBTYPE_I420;
+EXTERN_C const IID MEDIASUBTYPE_YUYV;
+EXTERN_C const IID FORMAT_WaveFormatEx;
+EXTERN_C const IID FORMAT_VideoInfo;
+EXTERN_C const IID FORMAT_VideoInfo2;
+EXTERN_C const IID PIN_CATEGORY_CAPTURE;
+EXTERN_C const IID PIN_CATEGORY_PREVIEW;
+
+
+#define MEDIATYPE_NULL       GUID_NULL
+#define MEDIASUBTYPE_NULL    GUID_NULL
+
+#define INTERFACE IGrabCallback
+DECLARE_INTERFACE_(IGrabCallback, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(Grab)(THIS_ ULONG,BYTE*) PURE;
+};
+#undef INTERFACE
+
+#ifdef COBJMACROS
+#define IGrabCallback_QueryInterface(T,a,b) (T)->lpVtbl->QueryInterface(T,a,b)
+#define IGrabCallback_AddRef(T) (T)->lpVtbl->AddRef(T)
+#define IGrabCallback_Release(T) (T)->lpVtbl->Release(T)
+#define IGrabCallback_Grab(T,a,b) (T)->lpVtbl->Grab(T,a,b)
+#endif /* COBJMACROS */
+
+#define INTERFACE IAMCopyCaptureFileProgress
+DECLARE_INTERFACE_(IAMCopyCaptureFileProgress, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(Progress)(THIS_ int) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IReferenceClock
+DECLARE_INTERFACE_(IReferenceClock, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *) PURE;
+    STDMETHOD(AdviseTime)(THIS_ REFERENCE_TIME, REFERENCE_TIME, HEVENT, DWORD_PTR *) PURE;
+    STDMETHOD(AdvisePeriodic)(THIS_ REFERENCE_TIME, REFERENCE_TIME, HSEMAPHORE, DWORD_PTR *) PURE;
+    STDMETHOD(Unadvise)(THIS_ DWORD_PTR) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IEnumFilters
+DECLARE_INTERFACE_(IEnumFilters, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(Next)(THIS_ ULONG, IBaseFilter **, ULONG *) PURE;
+    STDMETHOD(Skip)(THIS_ ULONG) PURE;
+    STDMETHOD(Reset)(THIS) PURE;
+    STDMETHOD(Clone)(THIS_ IEnumFilters **) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IEnumMediaTypes
+DECLARE_INTERFACE_(IEnumMediaTypes, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(Next)(THIS_ ULONG, AM_MEDIA_TYPE **, ULONG *) PURE;
+    STDMETHOD(Skip)(THIS_ ULONG) PURE;
+    STDMETHOD(Reset)(THIS) PURE;
+    STDMETHOD(Clone)(THIS_ IEnumMediaTypes **) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IPin
+DECLARE_INTERFACE_(IPin, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(Connect)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE;
+    STDMETHOD(ReceiveConnection)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE;
+    STDMETHOD(Disconnect)(THIS) PURE;
+    STDMETHOD(ConnectedTo)(THIS_ IPin **) PURE;
+    STDMETHOD(ConnectionMediaType)(THIS_ AM_MEDIA_TYPE *) PURE;
+    STDMETHOD(QueryPinInfo)(THIS_ PIN_INFO *) PURE;
+    STDMETHOD(QueryDirection)(THIS_ PIN_DIRECTION *) PURE;
+    STDMETHOD(QueryId)(THIS_ LPWSTR *) PURE;
+    STDMETHOD(QueryAccept)(THIS_ const AM_MEDIA_TYPE *) PURE;
+    STDMETHOD(EnumMediaTypes)(THIS_ IEnumMediaTypes **) PURE;
+    STDMETHOD(QueryInternalConnections)(THIS_ IPin **, ULONG *) PURE;
+    STDMETHOD(EndOfStream)(THIS) PURE;
+    STDMETHOD(BeginFlush)(THIS) PURE;
+    STDMETHOD(EndFlush)(THIS) PURE;
+    STDMETHOD(NewSegment)(THIS_ REFERENCE_TIME, REFERENCE_TIME, double) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IEnumPins
+DECLARE_INTERFACE_(IEnumPins, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(Next)(THIS_ ULONG, IPin **, ULONG *) PURE;
+    STDMETHOD(Skip)(THIS_ ULONG) PURE;
+    STDMETHOD(Reset)(THIS) PURE;
+    STDMETHOD(Clone)(THIS_ IEnumPins **) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IMediaFilter
+DECLARE_INTERFACE_(IMediaFilter, IPersist)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(GetClassID)(THIS_ CLSID*) PURE;
+    STDMETHOD(Stop)(THIS) PURE;
+    STDMETHOD(Pause)(THIS) PURE;
+    STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE;
+    STDMETHOD(GetState)(THIS_ DWORD, FILTER_STATE *) PURE;
+    STDMETHOD(SetSyncSource)(THIS_ IReferenceClock *) PURE;
+    STDMETHOD(GetSyncSource)(THIS_ IReferenceClock **) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IBaseFilter
+DECLARE_INTERFACE2_(IBaseFilter, IMediaFilter)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(GetClassID)(THIS_ CLSID*) PURE;
+    STDMETHOD(Stop)(THIS) PURE;
+    STDMETHOD(Pause)(THIS) PURE;
+    STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE;
+    STDMETHOD(GetState)(THIS_ DWORD, FILTER_STATE *) PURE;
+    STDMETHOD(SetSyncSource)(THIS_ IReferenceClock *) PURE;
+    STDMETHOD(GetSyncSource)(THIS_ IReferenceClock **) PURE;
+    STDMETHOD(EnumPins)(THIS_ IEnumPins **) PURE;
+    STDMETHOD(FindPin)(THIS_ LPCWSTR, IPin **) PURE;
+    STDMETHOD(QueryFilterInfo)(THIS_ FILTER_INFO *) PURE;
+    STDMETHOD(JoinFilterGraph)(THIS_ IFilterGraph *, LPCWSTR) PURE;
+    STDMETHOD(QueryVendorInfo)(THIS_ LPWSTR *) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IFilterGraph
+DECLARE_INTERFACE2_(IFilterGraph, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(AddFilter)(THIS_ IBaseFilter *, LPCWSTR) PURE;
+    STDMETHOD(RemoveFilter)(THIS_ IBaseFilter *) PURE;
+    STDMETHOD(EnumFilters)(THIS_ IEnumFilters **) PURE;
+    STDMETHOD(FindFilterByName)(THIS_ LPCWSTR, IBaseFilter **) PURE;
+    STDMETHOD(ConnectDirect)(THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *) PURE;
+    STDMETHOD(Reconnect)(THIS_ IPin *) PURE;
+    STDMETHOD(Disconnect)(THIS_ IPin *) PURE;
+    STDMETHOD(SetDefaultSyncSource)(THIS) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IGraphBuilder
+DECLARE_INTERFACE_(IGraphBuilder ,IFilterGraph)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(AddFilter)(THIS_ IBaseFilter *, LPCWSTR) PURE;
+    STDMETHOD(RemoveFilter)(THIS_ IBaseFilter *) PURE;
+    STDMETHOD(EnumFilters)(THIS_ IEnumFilters **) PURE;
+    STDMETHOD(FindFilterByName)(THIS_ LPCWSTR, IBaseFilter **) PURE;
+    STDMETHOD(ConnectDirect)(THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *) PURE;
+    STDMETHOD(Reconnect)(THIS_ IPin *) PURE;
+    STDMETHOD(Disconnect)(THIS_ IPin *) PURE;
+    STDMETHOD(SetDefaultSyncSource)(THIS) PURE;
+    STDMETHOD(Connect)(THIS_ IPin *, IPin *) PURE;
+    STDMETHOD(Render)(THIS_ IPin *) PURE;
+    STDMETHOD(RenderFile)(THIS_ LPCWSTR, LPCWSTR) PURE;
+    STDMETHOD(AddSourceFilter)(THIS_ LPCWSTR, LPCWSTR, IBaseFilter **) PURE;
+    STDMETHOD(SetLogFile)(THIS_ DWORD_PTR) PURE;
+    STDMETHOD(Abort)(THIS) PURE;
+    STDMETHOD(ShouldOperationContinue)(THIS) PURE;
+};
+#undef INTERFACE
+#define INTERFACE ICreateDevEnum
+DECLARE_INTERFACE_(ICreateDevEnum, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(CreateClassEnumerator)(THIS_ REFCLSID, IEnumMoniker **, DWORD) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IMediaSample
+DECLARE_INTERFACE_(IMediaSample, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(GetPointer)(THIS_ BYTE **) PURE;
+    STDMETHOD_(long, GetSize)(THIS) PURE;
+    STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE;
+    STDMETHOD(SetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE;
+    STDMETHOD(IsSyncPoint)(THIS) PURE;
+    STDMETHOD(SetSyncPoint)(THIS_ BOOL) PURE;
+    STDMETHOD(IsPreroll)(THIS) PURE;
+    STDMETHOD(SetPreroll)(THIS_ BOOL) PURE;
+    STDMETHOD_(long, GetActualDataLength)(THIS) PURE;
+    STDMETHOD(SetActualDataLength)(THIS_ long) PURE;
+    STDMETHOD(GetMediaType)(THIS_ AM_MEDIA_TYPE **) PURE;
+    STDMETHOD(SetMediaType)(THIS_ AM_MEDIA_TYPE *) PURE;
+    STDMETHOD(IsDiscontinuity)(THIS) PURE;
+    STDMETHOD(SetDiscontinuity)(THIS_ BOOL) PURE;
+    STDMETHOD(GetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE;
+    STDMETHOD(SetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IMemAllocator
+DECLARE_INTERFACE_(IMemAllocator, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(SetProperties)(THIS_ ALLOCATOR_PROPERTIES *, ALLOCATOR_PROPERTIES *) PURE;
+    STDMETHOD(GetProperties)(THIS_ ALLOCATOR_PROPERTIES *) PURE;
+    STDMETHOD(Commit)(THIS) PURE;
+    STDMETHOD(Decommit)(THIS) PURE;
+    STDMETHOD(GetBuffer)(THIS_ IMediaSample **, REFERENCE_TIME *, REFERENCE_TIME *, DWORD) PURE;
+    STDMETHOD(ReleaseBuffer)(THIS_ IMediaSample *) PURE;
+
+};
+#undef INTERFACE
+#define INTERFACE IMemInputPin
+DECLARE_INTERFACE_(IMemInputPin, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(GetAllocator)(THIS_ IMemAllocator **) PURE;
+    STDMETHOD(NotifyAllocator)(THIS_ IMemAllocator *, BOOL) PURE;
+    STDMETHOD(GetAllocatorRequirements)(THIS_ ALLOCATOR_PROPERTIES *) PURE;
+    STDMETHOD(Receive)(THIS_ IMediaSample *) PURE;
+    STDMETHOD(ReceiveMultiple)(THIS_ IMediaSample **, long, long *) PURE;
+    STDMETHOD(ReceiveCanBlock)(THIS) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IFileSinkFilter
+DECLARE_INTERFACE_(IFileSinkFilter, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(SetFileName)(THIS_ LPCOLESTR,const AM_MEDIA_TYPE *) PURE;
+    STDMETHOD(GetCurFile)(THIS_ LPOLESTR *,AM_MEDIA_TYPE*) PURE;
+};
+#undef INTERFACE
+#define INTERFACE ICaptureGraphBuilder2
+DECLARE_INTERFACE_(ICaptureGraphBuilder2, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(SetFiltergraph)(THIS_ IGraphBuilder*) PURE;
+    STDMETHOD(GetFiltergraph)(THIS_ IGraphBuilder**) PURE;
+    STDMETHOD(SetOutputFileName)(THIS_ const GUID*,LPCOLESTR,IBaseFilter**,IFileSinkFilter**) PURE;
+    STDMETHOD(FindInterface)(THIS_ const GUID*,const GUID*,IBaseFilter*,REFIID,void**) PURE;
+    STDMETHOD(RenderStream)(THIS_ const GUID*,const GUID*,IUnknown*,IBaseFilter*,IBaseFilter*) PURE;
+    STDMETHOD(ControlStream)(THIS_ const GUID*,const GUID*,IBaseFilter*,REFERENCE_TIME*,REFERENCE_TIME*,WORD,WORD) PURE;
+    STDMETHOD(AllocCapFile)(THIS_ LPCOLESTR,DWORDLONG) PURE;
+    STDMETHOD(CopyCaptureFile)(THIS_ LPOLESTR,LPOLESTR,int,IAMCopyCaptureFileProgress*) PURE;
+    STDMETHOD(FindPin)(THIS_ IUnknown*,PIN_DIRECTION,const GUID*,const GUID*,BOOL,int,IPin**) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IAMStreamConfig
+DECLARE_INTERFACE_(IAMStreamConfig, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(SetFormat)(THIS_ AM_MEDIA_TYPE*) PURE;
+    STDMETHOD(GetFormat)(THIS_ AM_MEDIA_TYPE**) PURE;
+    STDMETHOD(GetNumberOfCapabilities)(THIS_ int*,int*) PURE;
+    STDMETHOD(GetStreamCaps)(THIS_ int,AM_MEDIA_TYPE**,BYTE*) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IAMVideoProcAmp
+DECLARE_INTERFACE_(IAMVideoProcAmp, IUnknown)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(GetRange)(THIS_ long,long*,long*,long*,long*,long*) PURE;
+    STDMETHOD(Set)(THIS_ long,long,long) PURE;
+    STDMETHOD(Get)(THIS_ long,long*,long*) PURE;
+};
+#undef INTERFACE
+#define INTERFACE IMediaControl
+DECLARE_INTERFACE_(IMediaControl, IDispatch)
+{
+    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
+    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG, Release)(THIS) PURE;
+    STDMETHOD(GetTypeInfoCount)(THIS_ UINT*);
+    STDMETHOD(GetTypeInfo)(THIS_ UINT,LCID,ITypeInfo**);
+    STDMETHOD(GetIDsOfNames)(THIS_ REFIID,LPOLESTR*,UINT,LCID,DISPID*);
+    STDMETHOD(Invoke)(THIS_ DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
+    STDMETHOD(Run)(THIS);
+    STDMETHOD(Pause)(THIS);
+    STDMETHOD(Stop)(THIS);
+    STDMETHOD(GetState)(THIS_ LONG, OAFilterState*);
+    STDMETHOD(RenderFile)(THIS_ BSTR);
+    STDMETHOD(AddSourceFilter)(THIS_ BSTR,IDispatch**);
+    STDMETHOD(get_FilterCollection)(THIS_ IDispatch**);
+    STDMETHOD(get_RegFilterCollection)(THIS_ IDispatch**);
+    STDMETHOD(StopWhenReady)(THIS);
+};
+#undef INTERFACE
+
+#ifdef COBJMACROS
+#define ICreateDevEnum_QueryInterface(This,riid,ppvObject)  \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define ICreateDevEnum_AddRef(This) \
+    ((This)->lpVtbl->AddRef(This))
+#define ICreateDevEnum_Release(This)    \
+    ((This)->lpVtbl->Release(This))
+#define ICreateDevEnum_CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags)   \
+    ((This)->lpVtbl->CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IPin_QueryInterface(This,riid,ppvObject)    \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IPin_AddRef(This)   \
+    ((This)->lpVtbl->AddRef(This))
+#define IPin_Release(This)  \
+    ((This)->lpVtbl->Release(This))
+#define IPin_Connect(This,pReceivePin,pmt)  \
+    ((This)->lpVtbl->Connect(This,pReceivePin,pmt))
+#define IPin_ReceiveConnection(This,pConnector,pmt) \
+    ((This)->lpVtbl->ReceiveConnection(This,pConnector,pmt))
+#define IPin_Disconnect(This)   \
+    ((This)->lpVtbl->Disconnect(This))
+#define IPin_ConnectedTo(This,pPin) \
+    ((This)->lpVtbl->ConnectedTo(This,pPin))
+#define IPin_ConnectionMediaType(This,pmt)  \
+    ((This)->lpVtbl->ConnectionMediaType(This,pmt))
+#define IPin_QueryPinInfo(This,pInfo)   \
+    ((This)->lpVtbl->QueryPinInfo(This,pInfo))
+#define IPin_QueryDirection(This,pPinDir)   \
+    ((This)->lpVtbl->QueryDirection(This,pPinDir))
+#define IPin_QueryId(This,Id)   \
+    ((This)->lpVtbl->QueryId(This,Id))
+#define IPin_QueryAccept(This,pmt)  \
+    ((This)->lpVtbl->QueryAccept(This,pmt))
+#define IPin_EnumMediaTypes(This,ppEnum)    \
+    ((This)->lpVtbl->EnumMediaTypes(This,ppEnum))
+#define IPin_QueryInternalConnections(This,apPin,nPin)  \
+    ((This)->lpVtbl->QueryInternalConnections(This,apPin,nPin))
+#define IPin_EndOfStream(This)  \
+    ((This)->lpVtbl->EndOfStream(This))
+#define IPin_BeginFlush(This)   \
+    ((This)->lpVtbl->BeginFlush(This))
+#define IPin_EndFlush(This) \
+    ((This)->lpVtbl->EndFlush(This))
+#define IPin_NewSegment(This,tStart,tStop,dRate)    \
+    ((This)->lpVtbl->NewSegment(This,tStart,tStop,dRate))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IEnumPins_QueryInterface(This,riid,ppvObject)   \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IEnumPins_AddRef(This)  \
+    ((This)->lpVtbl->AddRef(This))
+#define IEnumPins_Release(This) \
+    ((This)->lpVtbl->Release(This))
+#define IEnumPins_Next(This,cPins,ppPins,pcFetched) \
+    ((This)->lpVtbl->Next(This,cPins,ppPins,pcFetched))
+#define IEnumPins_Skip(This,cPins)  \
+    ((This)->lpVtbl->Skip(This,cPins))
+#define IEnumPins_Reset(This)   \
+    ((This)->lpVtbl->Reset(This))
+#define IEnumPins_Clone(This,ppEnum)    \
+    ((This)->lpVtbl->Clone(This,ppEnum))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IAMStreamConfig_QueryInterface(This,riid,ppvObject) \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IAMStreamConfig_AddRef(This)    \
+    ((This)->lpVtbl->AddRef(This))
+#define IAMStreamConfig_Release(This)   \
+    ((This)->lpVtbl->Release(This))
+#define IAMStreamConfig_SetFormat(This,pmt) \
+    ((This)->lpVtbl->SetFormat(This,pmt))
+#define IAMStreamConfig_GetFormat(This,ppmt)    \
+    ((This)->lpVtbl->GetFormat(This,ppmt))
+#define IAMStreamConfig_GetNumberOfCapabilities(This,piCount,piSize)    \
+    ((This)->lpVtbl->GetNumberOfCapabilities(This,piCount,piSize))
+#define IAMStreamConfig_GetStreamCaps(This,iIndex,ppmt,pSCC)    \
+    ((This)->lpVtbl->GetStreamCaps(This,iIndex,ppmt,pSCC))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IFilterGraph_QueryInterface(This,riid,ppvObject)    \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IFilterGraph_AddRef(This)   \
+    ((This)->lpVtbl->AddRef(This))
+#define IFilterGraph_Release(This)  \
+    ((This)->lpVtbl->Release(This))
+#define IFilterGraph_AddFilter(This,pFilter,pName)  \
+    ((This)->lpVtbl->AddFilter(This,pFilter,pName))
+#define IFilterGraph_RemoveFilter(This,pFilter) \
+    ((This)->lpVtbl->RemoveFilter(This,pFilter))
+#define IFilterGraph_EnumFilters(This,ppEnum)   \
+    ((This)->lpVtbl->EnumFilters(This,ppEnum))
+#define IFilterGraph_FindFilterByName(This,pName,ppFilter)  \
+    ((This)->lpVtbl->FindFilterByName(This,pName,ppFilter))
+#define IFilterGraph_ConnectDirect(This,ppinOut,ppinIn,pmt) \
+    ((This)->lpVtbl->ConnectDirect(This,ppinOut,ppinIn,pmt))
+#define IFilterGraph_Reconnect(This,ppin)   \
+    ((This)->lpVtbl->Reconnect(This,ppin))
+#define IFilterGraph_Disconnect(This,ppin)  \
+    ((This)->lpVtbl->Disconnect(This,ppin))
+#define IFilterGraph_SetDefaultSyncSource(This) \
+    ((This)->lpVtbl->SetDefaultSyncSource(This))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IMediaFilter_QueryInterface(This,riid,ppvObject)    \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IMediaFilter_AddRef(This)   \
+    ((This)->lpVtbl->AddRef(This))
+#define IMediaFilter_Release(This)  \
+    ((This)->lpVtbl->Release(This))
+#define IMediaFilter_GetClassID(This,pClassID)  \
+    ((This)->lpVtbl->GetClassID(This,pClassID))
+#define IMediaFilter_Stop(This) \
+    ((This)->lpVtbl->Stop(This))
+#define IMediaFilter_Pause(This)    \
+    ((This)->lpVtbl->Pause(This))
+#define IMediaFilter_Run(This,tStart)   \
+    ((This)->lpVtbl->Run(This,tStart))
+#define IMediaFilter_GetState(This,dwMilliSecsTimeout,State)    \
+    ((This)->lpVtbl->GetState(This,dwMilliSecsTimeout,State))
+#define IMediaFilter_SetSyncSource(This,pClock) \
+    ((This)->lpVtbl->SetSyncSource(This,pClock))
+#define IMediaFilter_GetSyncSource(This,pClock) \
+    ((This)->lpVtbl->GetSyncSource(This,pClock))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IBaseFilter_QueryInterface(This,riid,ppvObject) \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IBaseFilter_AddRef(This)    \
+    ((This)->lpVtbl->AddRef(This))
+#define IBaseFilter_Release(This)   \
+    ((This)->lpVtbl->Release(This))
+#define IBaseFilter_GetClassID(This,pClassID)   \
+    ((This)->lpVtbl->GetClassID(This,pClassID))
+#define IBaseFilter_Stop(This)  \
+    ((This)->lpVtbl->Stop(This))
+#define IBaseFilter_Pause(This) \
+    ((This)->lpVtbl->Pause(This))
+#define IBaseFilter_Run(This,tStart)    \
+    ((This)->lpVtbl->Run(This,tStart))
+#define IBaseFilter_GetState(This,dwMilliSecsTimeout,State) \
+    ((This)->lpVtbl->GetState(This,dwMilliSecsTimeout,State))
+#define IBaseFilter_SetSyncSource(This,pClock)  \
+    ((This)->lpVtbl->SetSyncSource(This,pClock))
+#define IBaseFilter_GetSyncSource(This,pClock)  \
+    ((This)->lpVtbl->GetSyncSource(This,pClock))
+#define IBaseFilter_EnumPins(This,ppEnum)   \
+    ((This)->lpVtbl->EnumPins(This,ppEnum))
+#define IBaseFilter_FindPin(This,Id,ppPin)  \
+    ((This)->lpVtbl->FindPin(This,Id,ppPin))
+#define IBaseFilter_QueryFilterInfo(This,pInfo) \
+    ((This)->lpVtbl->QueryFilterInfo(This,pInfo))
+#define IBaseFilter_JoinFilterGraph(This,pGraph,pName)  \
+    ((This)->lpVtbl->JoinFilterGraph(This,pGraph,pName))
+#define IBaseFilter_QueryVendorInfo(This,pVendorInfo)   \
+    ((This)->lpVtbl->QueryVendorInfo(This,pVendorInfo))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IMediaSample_QueryInterface(This,riid,ppvObject)    \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IMediaSample_AddRef(This)   \
+    ((This)->lpVtbl->AddRef(This))
+#define IMediaSample_Release(This)  \
+    ((This)->lpVtbl->Release(This))
+#define IMediaSample_GetPointer(This,ppBuffer)  \
+    ((This)->lpVtbl->GetPointer(This,ppBuffer))
+#define IMediaSample_GetSize(This)  \
+        ((This)->lpVtbl->GetSize(This))
+#define IMediaSample_GetTime(This,pTimeStart,pTimeEnd)  \
+    ((This)->lpVtbl->GetTime(This,pTimeStart,pTimeEnd))
+#define IMediaSample_SetTime(This,pTimeStart,pTimeEnd)  \
+    ((This)->lpVtbl->SetTime(This,pTimeStart,pTimeEnd))
+#define IMediaSample_IsSyncPoint(This)  \
+    ((This)->lpVtbl->IsSyncPoint(This))
+#define IMediaSample_SetSyncPoint(This,bIsSyncPoint)    \
+    ((This)->lpVtbl->SetSyncPoint(This,bIsSyncPoint))
+#define IMediaSample_IsPreroll(This)    \
+    ((This)->lpVtbl->IsPreroll(This))
+#define IMediaSample_SetPreroll(This,bIsPreroll)    \
+    ((This)->lpVtbl->SetPreroll(This,bIsPreroll))
+#define IMediaSample_GetActualDataLength(This)  \
+    ((This)->lpVtbl->GetActualDataLength(This))
+#define IMediaSample_SetActualDataLength(This,length)   \
+    ((This)->lpVtbl->SetActualDataLength(This,length))
+#define IMediaSample_GetMediaType(This,ppMediaType) \
+    ((This)->lpVtbl->GetMediaType(This,ppMediaType))
+#define IMediaSample_SetMediaType(This,pMediaType)  \
+    ((This)->lpVtbl->SetMediaType(This,pMediaType))
+#define IMediaSample_IsDiscontinuity(This)  \
+    ((This)->lpVtbl->IsDiscontinuity(This))
+#define IMediaSample_SetDiscontinuity(This,bDiscontinuity)  \
+    ((This)->lpVtbl->SetDiscontinuity(This,bDiscontinuity))
+#define IMediaSample_GetMediaTime(This,pTimeStart,pTimeEnd) \
+    ((This)->lpVtbl->GetMediaTime(This,pTimeStart,pTimeEnd))
+#define IMediaSample_SetMediaTime(This,pTimeStart,pTimeEnd) \
+    ((This)->lpVtbl->SetMediaTime(This,pTimeStart,pTimeEnd))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IEnumFilters_QueryInterface(This,riid,ppvObject)    \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IEnumFilters_AddRef(This)   \
+    ((This)->lpVtbl->AddRef(This))
+#define IEnumFilters_Release(This)  \
+    ((This)->lpVtbl->Release(This))
+#define IEnumFilters_Next(This,cFilters,ppFilter,pcFetched) \
+    ((This)->lpVtbl->Next(This,cFilters,ppFilter,pcFetched))
+#define IEnumFilters_Skip(This,cFilters)    \
+    ((This)->lpVtbl->Skip(This,cFilters))
+#define IEnumFilters_Reset(This)    \
+    ((This)->lpVtbl->Reset(This))
+#define IEnumFilters_Clone(This,ppEnum) \
+    ((This)->lpVtbl->Clone(This,ppEnum))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IMemAllocator_QueryInterface(This,riid,ppvObject)   \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IMemAllocator_AddRef(This)  \
+    ((This)->lpVtbl->AddRef(This))
+#define IMemAllocator_Release(This) \
+    ((This)->lpVtbl->Release(This))
+#define IMemAllocator_SetProperties(This,pRequest,pActual)  \
+    ((This)->lpVtbl->SetProperties(This,pRequest,pActual))
+#define IMemAllocator_GetProperties(This,pProps)    \
+    ((This)->lpVtbl->GetProperties(This,pProps))
+#define IMemAllocator_Commit(This)  \
+    ((This)->lpVtbl->Commit(This))
+#define IMemAllocator_Decommit(This)    \
+    ((This)->lpVtbl->Decommit(This))
+#define IMemAllocator_GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags)  \
+    ((This)->lpVtbl->GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags))
+#define IMemAllocator_ReleaseBuffer(This,pBuffer)   \
+    ((This)->lpVtbl->ReleaseBuffer(This,pBuffer))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IMemInputPin_QueryInterface(This,riid,ppvObject)    \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IMemInputPin_AddRef(This)   \
+    ((This)->lpVtbl->AddRef(This))
+#define IMemInputPin_Release(This)  \
+    ((This)->lpVtbl->Release(This))
+#define IMemInputPin_GetAllocator(This,ppAllocator) \
+    ((This)->lpVtbl->GetAllocator(This,ppAllocator))
+#define IMemInputPin_NotifyAllocator(This,pAllocator,bReadOnly) \
+    ((This)->lpVtbl->NotifyAllocator(This,pAllocator,bReadOnly))
+#define IMemInputPin_GetAllocatorRequirements(This,pProps)  \
+    ((This)->lpVtbl->GetAllocatorRequirements(This,pProps))
+#define IMemInputPin_Receive(This,pSample)  \
+    ((This)->lpVtbl->Receive(This,pSample))
+#define IMemInputPin_ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed)  \
+    ((This)->lpVtbl->ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed))
+#define IMemInputPin_ReceiveCanBlock(This)  \
+    ((This)->lpVtbl->ReceiveCanBlock(This))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IGraphBuilder_QueryInterface(This,riid,ppvObject)   \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IGraphBuilder_AddRef(This)  \
+    ((This)->lpVtbl->AddRef(This))
+#define IGraphBuilder_Release(This) \
+    ((This)->lpVtbl->Release(This))
+#define IGraphBuilder_AddFilter(This,pFilter,pName) \
+    ((This)->lpVtbl->AddFilter(This,pFilter,pName))
+#define IGraphBuilder_RemoveFilter(This,pFilter)    \
+    ((This)->lpVtbl->RemoveFilter(This,pFilter))
+#define IGraphBuilder_EnumFilters(This,ppEnum)  \
+    ((This)->lpVtbl->EnumFilters(This,ppEnum))
+#define IGraphBuilder_FindFilterByName(This,pName,ppFilter) \
+    ((This)->lpVtbl->FindFilterByName(This,pName,ppFilter))
+#define IGraphBuilder_ConnectDirect(This,ppinOut,ppinIn,pmt)    \
+    ((This)->lpVtbl->ConnectDirect(This,ppinOut,ppinIn,pmt))
+#define IGraphBuilder_Reconnect(This,ppin)  \
+    ((This)->lpVtbl->Reconnect(This,ppin))
+#define IGraphBuilder_Disconnect(This,ppin) \
+    ((This)->lpVtbl->Disconnect(This,ppin))
+#define IGraphBuilder_SetDefaultSyncSource(This)    \
+    ((This)->lpVtbl->SetDefaultSyncSource(This))
+#define IGraphBuilder_Connect(This,ppinOut,ppinIn)  \
+    ((This)->lpVtbl->Connect(This,ppinOut,ppinIn))
+#define IGraphBuilder_Render(This,ppinOut)  \
+    ((This)->lpVtbl->Render(This,ppinOut))
+#define IGraphBuilder_RenderFile(This,lpcwstrFile,lpcwstrPlayList)  \
+    ((This)->lpVtbl->RenderFile(This,lpcwstrFile,lpcwstrPlayList))
+#define IGraphBuilder_AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter)  \
+    ((This)->lpVtbl->AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter))
+#define IGraphBuilder_SetLogFile(This,hFile)    \
+    ((This)->lpVtbl->SetLogFile(This,hFile))
+#define IGraphBuilder_Abort(This)   \
+    ((This)->lpVtbl->Abort(This))
+#define IGraphBuilder_ShouldOperationContinue(This) \
+    ((This)->lpVtbl->ShouldOperationContinue(This))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IEnumMediaTypes_QueryInterface(This,riid,ppvObject) \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IEnumMediaTypes_AddRef(This)    \
+    ((This)->lpVtbl->AddRef(This))
+#define IEnumMediaTypes_Release(This)   \
+    ((This)->lpVtbl->Release(This))
+#define IEnumMediaTypes_Next(This,cMediaTypes,ppMediaTypes,pcFetched)   \
+    ((This)->lpVtbl->Next(This,cMediaTypes,ppMediaTypes,pcFetched))
+#define IEnumMediaTypes_Skip(This,cMediaTypes)  \
+    ((This)->lpVtbl->Skip(This,cMediaTypes))
+#define IEnumMediaTypes_Reset(This) \
+    ((This)->lpVtbl->Reset(This))
+#define IEnumMediaTypes_Clone(This,ppEnum)  \
+    ((This)->lpVtbl->Clone(This,ppEnum))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IMediaControl_QueryInterface(This,riid,ppvObject)   \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IMediaControl_AddRef(This)  \
+    ((This)->lpVtbl->AddRef(This))
+#define IMediaControl_Release(This) \
+    ((This)->lpVtbl->Release(This))
+#define IMediaControl_GetTypeInfoCount(This,pctinfo)    \
+    ((This)->lpVtbl->GetTypeInfoCount(This,pctinfo))
+#define IMediaControl_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
+    ((This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo))
+#define IMediaControl_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)   \
+    ((This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId))
+#define IMediaControl_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
+    ((This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr))
+#define IMediaControl_Run(This) \
+    ((This)->lpVtbl->Run(This))
+#define IMediaControl_Pause(This)   \
+    ((This)->lpVtbl->Pause(This))
+#define IMediaControl_Stop(This)    \
+    ((This)->lpVtbl->Stop(This))
+#define IMediaControl_GetState(This,msTimeout,pfs)  \
+    ((This)->lpVtbl->GetState(This,msTimeout,pfs))
+#define IMediaControl_RenderFile(This,strFilename)  \
+    ((This)->lpVtbl->RenderFile(This,strFilename))
+#define IMediaControl_AddSourceFilter(This,strFilename,ppUnk)   \
+    ((This)->lpVtbl->AddSourceFilter(This,strFilename,ppUnk))
+#define IMediaControl_get_FilterCollection(This,ppUnk)  \
+    ((This)->lpVtbl->get_FilterCollection(This,ppUnk))
+#define IMediaControl_get_RegFilterCollection(This,ppUnk)   \
+    ((This)->lpVtbl->get_RegFilterCollection(This,ppUnk))
+#define IMediaControl_StopWhenReady(This)   \
+    ((This)->lpVtbl->StopWhenReady(This))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IAMVideoProcAmp_QueryInterface(This,riid,ppvObject) \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IAMVideoProcAmp_AddRef(This)    \
+    ((This)->lpVtbl->AddRef(This))
+#define IAMVideoProcAmp_Release(This)   \
+    ((This)->lpVtbl->Release(This))
+#define IAMVideoProcAmp_GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags)    \
+    ((This)->lpVtbl->GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags))
+#define IAMVideoProcAmp_Set(This,Property,lValue,Flags) \
+    ((This)->lpVtbl->Set(This,Property,lValue,Flags))
+#define IAMVideoProcAmp_Get(This,Property,lValue,Flags) \
+    ((This)->lpVtbl->Get(This,Property,lValue,Flags))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IFileSinkFilter_QueryInterface(This,riid,ppvObject) \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IFileSinkFilter_AddRef(This)    \
+    ((This)->lpVtbl->AddRef(This))
+#define IFileSinkFilter_Release(This)   \
+    ((This)->lpVtbl->Release(This))
+#define IFileSinkFilter_SetFileName(This,pszFileName,pmt)   \
+    ((This)->lpVtbl->SetFileName(This,pszFileName,pmt))
+#define IFileSinkFilter_GetCurFile(This,ppszFileName,pmt)   \
+    ((This)->lpVtbl->GetCurFile(This,ppszFileName,pmt))
+#endif /* COBJMACROS */
+
+#ifdef COBJMACROS
+#define IAMCopyCaptureFileProgress_QueryInterface(This,riid,ppvObject)  \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define IAMCopyCaptureFileProgress_AddRef(This) \
+    ((This)->lpVtbl->AddRef(This))
+#define IAMCopyCaptureFileProgress_Release(This)    \
+    ((This)->lpVtbl->Release(This))
+#define IAMCopyCaptureFileProgress_Progress(This,iProgress) \
+    ((This)->lpVtbl->Progress(This,iProgress))
+#endif /* COBJMACROS */
+
+
+#ifdef COBJMACROS
+#define ICaptureGraphBuilder2_QueryInterface(This,riid,ppvObject)   \
+    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
+#define ICaptureGraphBuilder2_AddRef(This)  \
+    ((This)->lpVtbl->AddRef(This))
+#define ICaptureGraphBuilder2_Release(This) \
+    ((This)->lpVtbl->Release(This))
+#define ICaptureGraphBuilder2_SetFiltergraph(This,pfg)  \
+    ((This)->lpVtbl->SetFiltergraph(This,pfg))
+#define ICaptureGraphBuilder2_GetFiltergraph(This,ppfg) \
+    ((This)->lpVtbl->GetFiltergraph(This,ppfg))
+#define ICaptureGraphBuilder2_SetOutputFileName(This,pType,lpstrFile,ppf,ppSink)    \
+    ((This)->lpVtbl->SetOutputFileName(This,pType,lpstrFile,ppf,ppSink))
+#define ICaptureGraphBuilder2_FindInterface(This,pCategory,pType,pf,riid,ppint) \
+    ((This)->lpVtbl->FindInterface(This,pCategory,pType,pf,riid,ppint))
+#define ICaptureGraphBuilder2_RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer)    \
+    ((This)->lpVtbl->RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer))
+#define ICaptureGraphBuilder2_ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie) \
+    ((This)->lpVtbl->ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie))
+#define ICaptureGraphBuilder2_AllocCapFile(This,lpstr,dwlSize)  \
+    ((This)->lpVtbl->AllocCapFile(This,lpstr,dwlSize))
+#define ICaptureGraphBuilder2_CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback)    \
+    ((This)->lpVtbl->CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback))
+#define ICaptureGraphBuilder2_FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin)   \
+    ((This)->lpVtbl->FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin))
+#endif /* COBJMACROS */
+
+#endif /* _MARU_CAMERA_WIN32_H_ */
diff --git a/tizen/src/hw/pci/maru_camera_win32_interface.h b/tizen/src/hw/pci/maru_camera_win32_interface.h
deleted file mode 100644 (file)
index c38a785..0000000
+++ /dev/null
@@ -1,932 +0,0 @@
-/*
- * Interface definition header for Windows host.
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Contact:
- * JinHyung Jo <jinhyung.jo@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-#ifndef _MARU_CAMERA_INTERFACE_H_
-#define _MARU_CAMERA_INTERFACE_H_
-
-static const WCHAR HWCPinName[] = L"HWCInputPin\0";
-static const WCHAR HWCFilterName[] = L"HWCFilter\0";
-
-/* Forward Declarations */
-FWD_DECL(IBaseFilter);
-FWD_DECL(IFilterGraph);
-
-/* defines */
-#define MAX_PIN_NAME     128
-#define MAX_FILTER_NAME  128
-
-#define DECLARE_INTERFACE2(i) \
-   _COM_interface i { CONST_VTABLE struct i##Vtbl *lpVtbl; }; \
-   typedef CONST_VTABLE struct i##Vtbl i##Vtbl; \
-   CONST_VTABLE struct i##Vtbl
-#define DECLARE_INTERFACE2_(i, b) DECLARE_INTERFACE2(i)
-
-typedef LONGLONG REFERENCE_TIME;
-typedef long OAFilterState;
-typedef DWORD_PTR HSEMAPHORE;
-typedef DWORD_PTR HEVENT;
-
-typedef enum _FilterState {
-  State_Stopped,
-  State_Paused,
-  State_Running
-} FILTER_STATE;
-
-typedef struct _FilterInfo {
-  WCHAR achName[MAX_FILTER_NAME];
-  IFilterGraph *pGraph;
-} FILTER_INFO;
-
-typedef enum _PinDirection {
-    PINDIR_INPUT    = 0,
-    PINDIR_OUTPUT   = (PINDIR_INPUT + 1)
-} PIN_DIRECTION;
-
-typedef struct _PinInfo {
-  IBaseFilter *pFilter;
-  PIN_DIRECTION dir;
-  WCHAR achName[MAX_PIN_NAME];
-} PIN_INFO;
-
-typedef struct _AllocatorProperties {
-  long cBuffers;
-  long cbBuffer;
-  long cbAlign;
-  long cbPrefix;
-} ALLOCATOR_PROPERTIES;
-
-typedef struct _AMMediaType {
-  GUID majortype;
-  GUID subtype;
-  BOOL bFixedSizeSamples;
-  BOOL bTemporalCompression;
-  ULONG lSampleSize;
-  GUID formattype;
-  IUnknown *pUnk;
-  ULONG cbFormat;
-  BYTE *pbFormat;
-} AM_MEDIA_TYPE;
-
-typedef enum tagVideoProcAmpFlags {
-    VideoProcAmp_Flags_Auto = 0x0001,
-    VideoProcAmp_Flags_Manual = 0x0002
-} VideoProcAmpFlags;
-
-typedef enum tagVideoProcAmpProperty {
-    VideoProcAmp_Brightness,
-    VideoProcAmp_Contrast,
-    VideoProcAmp_Hue,
-    VideoProcAmp_Saturation,
-    VideoProcAmp_Sharpness,
-    VideoProcAmp_Gamma,
-    VideoProcAmp_ColorEnable,
-    VideoProcAmp_WhiteBalance,
-    VideoProcAmp_BacklightCompensation,
-    VideoProcAmp_Gain
-} VideoProcAmpProperty;
-
-typedef struct tagVIDEOINFOHEADER {
-    RECT rcSource;
-    RECT rcTarget;
-    DWORD dwBitRate;
-    DWORD dwBitErrorRate;
-    REFERENCE_TIME AvgTimePerFrame;
-    BITMAPINFOHEADER bmiHeader;
-} VIDEOINFOHEADER;
-
-typedef struct _VIDEO_STREAM_CONFIG_CAPS {
-  GUID guid;
-  ULONG VideoStandard;
-  SIZE InputSize;
-  SIZE MinCroppingSize;
-  SIZE MaxCroppingSize;
-  int CropGranularityX;
-  int CropGranularityY;
-  int CropAlignX;
-  int CropAlignY;
-  SIZE MinOutputSize;
-  SIZE MaxOutputSize;
-  int OutputGranularityX;
-  int OutputGranularityY;
-  int StretchTapsX;
-  int StretchTapsY;
-  int ShrinkTapsX;
-  int ShrinkTapsY;
-  LONGLONG MinFrameInterval;
-  LONGLONG MaxFrameInterval;
-  LONG MinBitsPerSecond;
-  LONG MaxBitsPerSecond;
-} VIDEO_STREAM_CONFIG_CAPS;
-
-
-/* Interface & Class GUIDs */
-static const IID IID_IGrabCallback   = {0x4C337035,0xC89E,0x4B42,{0x9B,0x0C,0x36,0x74,0x44,0xDD,0x70,0xDD}};
-
-EXTERN_C const IID IID_IBaseFilter;
-EXTERN_C const IID IID_ICreateDevEnum;
-EXTERN_C const IID IID_IGraphBuilder;
-EXTERN_C const IID IID_IMediaSeeking;
-EXTERN_C const IID IID_IMediaEventSink;
-EXTERN_C const IID IID_IMemInputPin;
-EXTERN_C const IID IID_IEnumPins;
-EXTERN_C const IID IID_IMediaFilter;
-EXTERN_C const IID IID_IEnumMediaTypes;
-EXTERN_C const IID IID_IMemAllocator;
-EXTERN_C const IID IID_IPin;
-EXTERN_C const IID IID_ICaptureGraphBuilder2;
-EXTERN_C const IID IID_IFileSinkFilter;
-EXTERN_C const IID IID_IAMCopyCaptureFileProgress;
-EXTERN_C const IID IID_IEnumFilters;
-EXTERN_C const IID IID_IMediaSample;
-EXTERN_C const IID IID_IMediaControl;
-EXTERN_C const IID IID_IAMStreamConfig;
-EXTERN_C const IID IID_IAMVideoProcAmp;
-
-EXTERN_C const IID CLSID_CaptureGraphBuilder2;
-EXTERN_C const IID CLSID_VideoInputDeviceCategory;
-EXTERN_C const IID CLSID_AudioRender;
-EXTERN_C const IID CLSID_SystemDeviceEnum;
-EXTERN_C const IID CLSID_AudioRendererCategory;
-EXTERN_C const IID CLSID_FilterGraph;
-EXTERN_C const IID CLSID_InfTee;
-EXTERN_C const IID CLSID_VideoMixingRenderer9;
-EXTERN_C const IID CLSID_MemoryAllocator;
-
-
-/* other types GUIDs*/
-EXTERN_C const IID MEDIATYPE_Audio;
-EXTERN_C const IID MEDIATYPE_Video;
-EXTERN_C const IID MEDIATYPE_Stream;
-EXTERN_C const IID MEDIASUBTYPE_PCM;
-EXTERN_C const IID MEDIASUBTYPE_WAVE;
-EXTERN_C const IID MEDIASUBTYPE_Avi;
-EXTERN_C const IID MEDIASUBTYPE_RGB32;
-EXTERN_C const IID MEDIASUBTYPE_YV12;
-EXTERN_C const IID MEDIASUBTYPE_YUY2;
-EXTERN_C const IID MEDIASUBTYPE_I420;
-EXTERN_C const IID MEDIASUBTYPE_YUYV;
-EXTERN_C const IID FORMAT_WaveFormatEx;
-EXTERN_C const IID FORMAT_VideoInfo;
-EXTERN_C const IID FORMAT_VideoInfo2;
-EXTERN_C const IID PIN_CATEGORY_CAPTURE;
-EXTERN_C const IID PIN_CATEGORY_PREVIEW;
-
-
-#define MEDIATYPE_NULL       GUID_NULL
-#define MEDIASUBTYPE_NULL    GUID_NULL
-
-#define INTERFACE IGrabCallback
-DECLARE_INTERFACE_(IGrabCallback, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(Grab)(THIS_ ULONG,BYTE*) PURE;
-};
-#undef INTERFACE
-
-#ifdef COBJMACROS
-#define IGrabCallback_QueryInterface(T,a,b) (T)->lpVtbl->QueryInterface(T,a,b)
-#define IGrabCallback_AddRef(T) (T)->lpVtbl->AddRef(T)
-#define IGrabCallback_Release(T) (T)->lpVtbl->Release(T)
-#define IGrabCallback_Grab(T,a,b) (T)->lpVtbl->Grab(T,a,b)
-#endif /* COBJMACROS */
-
-#define INTERFACE IAMCopyCaptureFileProgress
-DECLARE_INTERFACE_(IAMCopyCaptureFileProgress, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(Progress)(THIS_ int) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IReferenceClock
-DECLARE_INTERFACE_(IReferenceClock, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *) PURE;
-    STDMETHOD(AdviseTime)(THIS_ REFERENCE_TIME, REFERENCE_TIME, HEVENT, DWORD_PTR *) PURE;
-    STDMETHOD(AdvisePeriodic)(THIS_ REFERENCE_TIME, REFERENCE_TIME, HSEMAPHORE, DWORD_PTR *) PURE;
-    STDMETHOD(Unadvise)(THIS_ DWORD_PTR) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IEnumFilters
-DECLARE_INTERFACE_(IEnumFilters, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(Next)(THIS_ ULONG, IBaseFilter **, ULONG *) PURE;
-    STDMETHOD(Skip)(THIS_ ULONG) PURE;
-    STDMETHOD(Reset)(THIS) PURE;
-    STDMETHOD(Clone)(THIS_ IEnumFilters **) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IEnumMediaTypes
-DECLARE_INTERFACE_(IEnumMediaTypes, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(Next)(THIS_ ULONG, AM_MEDIA_TYPE **, ULONG *) PURE;
-    STDMETHOD(Skip)(THIS_ ULONG) PURE;
-    STDMETHOD(Reset)(THIS) PURE;
-    STDMETHOD(Clone)(THIS_ IEnumMediaTypes **) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IPin
-DECLARE_INTERFACE_(IPin, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(Connect)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE;
-    STDMETHOD(ReceiveConnection)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE;
-    STDMETHOD(Disconnect)(THIS) PURE;
-    STDMETHOD(ConnectedTo)(THIS_ IPin **) PURE;
-    STDMETHOD(ConnectionMediaType)(THIS_ AM_MEDIA_TYPE *) PURE;
-    STDMETHOD(QueryPinInfo)(THIS_ PIN_INFO *) PURE;
-    STDMETHOD(QueryDirection)(THIS_ PIN_DIRECTION *) PURE;
-    STDMETHOD(QueryId)(THIS_ LPWSTR *) PURE;
-    STDMETHOD(QueryAccept)(THIS_ const AM_MEDIA_TYPE *) PURE;
-    STDMETHOD(EnumMediaTypes)(THIS_ IEnumMediaTypes **) PURE;
-    STDMETHOD(QueryInternalConnections)(THIS_ IPin **, ULONG *) PURE;
-    STDMETHOD(EndOfStream)(THIS) PURE;
-    STDMETHOD(BeginFlush)(THIS) PURE;
-    STDMETHOD(EndFlush)(THIS) PURE;
-    STDMETHOD(NewSegment)(THIS_ REFERENCE_TIME, REFERENCE_TIME, double) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IEnumPins
-DECLARE_INTERFACE_(IEnumPins, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(Next)(THIS_ ULONG, IPin **, ULONG *) PURE;
-    STDMETHOD(Skip)(THIS_ ULONG) PURE;
-    STDMETHOD(Reset)(THIS) PURE;
-    STDMETHOD(Clone)(THIS_ IEnumPins **) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IMediaFilter
-DECLARE_INTERFACE_(IMediaFilter, IPersist)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(GetClassID)(THIS_ CLSID*) PURE;
-    STDMETHOD(Stop)(THIS) PURE;
-    STDMETHOD(Pause)(THIS) PURE;
-    STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE;
-    STDMETHOD(GetState)(THIS_ DWORD, FILTER_STATE *) PURE;
-    STDMETHOD(SetSyncSource)(THIS_ IReferenceClock *) PURE;
-    STDMETHOD(GetSyncSource)(THIS_ IReferenceClock **) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IBaseFilter
-DECLARE_INTERFACE2_(IBaseFilter, IMediaFilter)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(GetClassID)(THIS_ CLSID*) PURE;
-    STDMETHOD(Stop)(THIS) PURE;
-    STDMETHOD(Pause)(THIS) PURE;
-    STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE;
-    STDMETHOD(GetState)(THIS_ DWORD, FILTER_STATE *) PURE;
-    STDMETHOD(SetSyncSource)(THIS_ IReferenceClock *) PURE;
-    STDMETHOD(GetSyncSource)(THIS_ IReferenceClock **) PURE;
-    STDMETHOD(EnumPins)(THIS_ IEnumPins **) PURE;
-    STDMETHOD(FindPin)(THIS_ LPCWSTR, IPin **) PURE;
-    STDMETHOD(QueryFilterInfo)(THIS_ FILTER_INFO *) PURE;
-    STDMETHOD(JoinFilterGraph)(THIS_ IFilterGraph *, LPCWSTR) PURE;
-    STDMETHOD(QueryVendorInfo)(THIS_ LPWSTR *) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IFilterGraph
-DECLARE_INTERFACE2_(IFilterGraph, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(AddFilter)(THIS_ IBaseFilter *, LPCWSTR) PURE;
-    STDMETHOD(RemoveFilter)(THIS_ IBaseFilter *) PURE;
-    STDMETHOD(EnumFilters)(THIS_ IEnumFilters **) PURE;
-    STDMETHOD(FindFilterByName)(THIS_ LPCWSTR, IBaseFilter **) PURE;
-    STDMETHOD(ConnectDirect)(THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *) PURE;
-    STDMETHOD(Reconnect)(THIS_ IPin *) PURE;
-    STDMETHOD(Disconnect)(THIS_ IPin *) PURE;
-    STDMETHOD(SetDefaultSyncSource)(THIS) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IGraphBuilder
-DECLARE_INTERFACE_(IGraphBuilder ,IFilterGraph)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(AddFilter)(THIS_ IBaseFilter *, LPCWSTR) PURE;
-    STDMETHOD(RemoveFilter)(THIS_ IBaseFilter *) PURE;
-    STDMETHOD(EnumFilters)(THIS_ IEnumFilters **) PURE;
-    STDMETHOD(FindFilterByName)(THIS_ LPCWSTR, IBaseFilter **) PURE;
-    STDMETHOD(ConnectDirect)(THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *) PURE;
-    STDMETHOD(Reconnect)(THIS_ IPin *) PURE;
-    STDMETHOD(Disconnect)(THIS_ IPin *) PURE;
-    STDMETHOD(SetDefaultSyncSource)(THIS) PURE;
-    STDMETHOD(Connect)(THIS_ IPin *, IPin *) PURE;
-    STDMETHOD(Render)(THIS_ IPin *) PURE;
-    STDMETHOD(RenderFile)(THIS_ LPCWSTR, LPCWSTR) PURE;
-    STDMETHOD(AddSourceFilter)(THIS_ LPCWSTR, LPCWSTR, IBaseFilter **) PURE;
-    STDMETHOD(SetLogFile)(THIS_ DWORD_PTR) PURE;
-    STDMETHOD(Abort)(THIS) PURE;
-    STDMETHOD(ShouldOperationContinue)(THIS) PURE;
-};
-#undef INTERFACE
-#define INTERFACE ICreateDevEnum
-DECLARE_INTERFACE_(ICreateDevEnum, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(CreateClassEnumerator)(THIS_ REFCLSID, IEnumMoniker **, DWORD) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IMediaSample
-DECLARE_INTERFACE_(IMediaSample, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(GetPointer)(THIS_ BYTE **) PURE;
-    STDMETHOD_(long, GetSize)(THIS) PURE;
-    STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE;
-    STDMETHOD(SetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE;
-    STDMETHOD(IsSyncPoint)(THIS) PURE;
-    STDMETHOD(SetSyncPoint)(THIS_ BOOL) PURE;
-    STDMETHOD(IsPreroll)(THIS) PURE;
-    STDMETHOD(SetPreroll)(THIS_ BOOL) PURE;
-    STDMETHOD_(long, GetActualDataLength)(THIS) PURE;
-    STDMETHOD(SetActualDataLength)(THIS_ long) PURE;
-    STDMETHOD(GetMediaType)(THIS_ AM_MEDIA_TYPE **) PURE;
-    STDMETHOD(SetMediaType)(THIS_ AM_MEDIA_TYPE *) PURE;
-    STDMETHOD(IsDiscontinuity)(THIS) PURE;
-    STDMETHOD(SetDiscontinuity)(THIS_ BOOL) PURE;
-    STDMETHOD(GetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE;
-    STDMETHOD(SetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IMemAllocator
-DECLARE_INTERFACE_(IMemAllocator, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(SetProperties)(THIS_ ALLOCATOR_PROPERTIES *, ALLOCATOR_PROPERTIES *) PURE;
-    STDMETHOD(GetProperties)(THIS_ ALLOCATOR_PROPERTIES *) PURE;
-    STDMETHOD(Commit)(THIS) PURE;
-    STDMETHOD(Decommit)(THIS) PURE;
-    STDMETHOD(GetBuffer)(THIS_ IMediaSample **, REFERENCE_TIME *, REFERENCE_TIME *, DWORD) PURE;
-    STDMETHOD(ReleaseBuffer)(THIS_ IMediaSample *) PURE;
-
-};
-#undef INTERFACE
-#define INTERFACE IMemInputPin
-DECLARE_INTERFACE_(IMemInputPin, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(GetAllocator)(THIS_ IMemAllocator **) PURE;
-    STDMETHOD(NotifyAllocator)(THIS_ IMemAllocator *, BOOL) PURE;
-    STDMETHOD(GetAllocatorRequirements)(THIS_ ALLOCATOR_PROPERTIES *) PURE;
-    STDMETHOD(Receive)(THIS_ IMediaSample *) PURE;
-    STDMETHOD(ReceiveMultiple)(THIS_ IMediaSample **, long, long *) PURE;
-    STDMETHOD(ReceiveCanBlock)(THIS) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IFileSinkFilter
-DECLARE_INTERFACE_(IFileSinkFilter, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(SetFileName)(THIS_ LPCOLESTR,const AM_MEDIA_TYPE *) PURE;
-    STDMETHOD(GetCurFile)(THIS_ LPOLESTR *,AM_MEDIA_TYPE*) PURE;
-};
-#undef INTERFACE
-#define INTERFACE ICaptureGraphBuilder2
-DECLARE_INTERFACE_(ICaptureGraphBuilder2, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(SetFiltergraph)(THIS_ IGraphBuilder*) PURE;
-    STDMETHOD(GetFiltergraph)(THIS_ IGraphBuilder**) PURE;
-    STDMETHOD(SetOutputFileName)(THIS_ const GUID*,LPCOLESTR,IBaseFilter**,IFileSinkFilter**) PURE;
-    STDMETHOD(FindInterface)(THIS_ const GUID*,const GUID*,IBaseFilter*,REFIID,void**) PURE;
-    STDMETHOD(RenderStream)(THIS_ const GUID*,const GUID*,IUnknown*,IBaseFilter*,IBaseFilter*) PURE;
-    STDMETHOD(ControlStream)(THIS_ const GUID*,const GUID*,IBaseFilter*,REFERENCE_TIME*,REFERENCE_TIME*,WORD,WORD) PURE;
-    STDMETHOD(AllocCapFile)(THIS_ LPCOLESTR,DWORDLONG) PURE;
-    STDMETHOD(CopyCaptureFile)(THIS_ LPOLESTR,LPOLESTR,int,IAMCopyCaptureFileProgress*) PURE;
-    STDMETHOD(FindPin)(THIS_ IUnknown*,PIN_DIRECTION,const GUID*,const GUID*,BOOL,int,IPin**) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IAMStreamConfig
-DECLARE_INTERFACE_(IAMStreamConfig, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(SetFormat)(THIS_ AM_MEDIA_TYPE*) PURE;
-    STDMETHOD(GetFormat)(THIS_ AM_MEDIA_TYPE**) PURE;
-    STDMETHOD(GetNumberOfCapabilities)(THIS_ int*,int*) PURE;
-    STDMETHOD(GetStreamCaps)(THIS_ int,AM_MEDIA_TYPE**,BYTE*) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IAMVideoProcAmp
-DECLARE_INTERFACE_(IAMVideoProcAmp, IUnknown)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(GetRange)(THIS_ long,long*,long*,long*,long*,long*) PURE;
-    STDMETHOD(Set)(THIS_ long,long,long) PURE;
-    STDMETHOD(Get)(THIS_ long,long*,long*) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IMediaControl
-DECLARE_INTERFACE_(IMediaControl, IDispatch)
-{
-    STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE;
-    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
-    STDMETHOD_(ULONG, Release)(THIS) PURE;
-    STDMETHOD(GetTypeInfoCount)(THIS_ UINT*);
-    STDMETHOD(GetTypeInfo)(THIS_ UINT,LCID,ITypeInfo**);
-    STDMETHOD(GetIDsOfNames)(THIS_ REFIID,LPOLESTR*,UINT,LCID,DISPID*);
-    STDMETHOD(Invoke)(THIS_ DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
-    STDMETHOD(Run)(THIS);
-    STDMETHOD(Pause)(THIS);
-    STDMETHOD(Stop)(THIS);
-    STDMETHOD(GetState)(THIS_ LONG, OAFilterState*);
-    STDMETHOD(RenderFile)(THIS_ BSTR);
-    STDMETHOD(AddSourceFilter)(THIS_ BSTR,IDispatch**);
-    STDMETHOD(get_FilterCollection)(THIS_ IDispatch**);
-    STDMETHOD(get_RegFilterCollection)(THIS_ IDispatch**);
-    STDMETHOD(StopWhenReady)(THIS);
-};
-#undef INTERFACE
-
-#ifdef COBJMACROS
-#define ICreateDevEnum_QueryInterface(This,riid,ppvObject)  \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define ICreateDevEnum_AddRef(This) \
-    ((This)->lpVtbl->AddRef(This))
-#define ICreateDevEnum_Release(This)    \
-    ((This)->lpVtbl->Release(This))
-#define ICreateDevEnum_CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags)   \
-    ((This)->lpVtbl->CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IPin_QueryInterface(This,riid,ppvObject)    \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IPin_AddRef(This)   \
-    ((This)->lpVtbl->AddRef(This))
-#define IPin_Release(This)  \
-    ((This)->lpVtbl->Release(This))
-#define IPin_Connect(This,pReceivePin,pmt)  \
-    ((This)->lpVtbl->Connect(This,pReceivePin,pmt))
-#define IPin_ReceiveConnection(This,pConnector,pmt) \
-    ((This)->lpVtbl->ReceiveConnection(This,pConnector,pmt))
-#define IPin_Disconnect(This)   \
-    ((This)->lpVtbl->Disconnect(This))
-#define IPin_ConnectedTo(This,pPin) \
-    ((This)->lpVtbl->ConnectedTo(This,pPin))
-#define IPin_ConnectionMediaType(This,pmt)  \
-    ((This)->lpVtbl->ConnectionMediaType(This,pmt))
-#define IPin_QueryPinInfo(This,pInfo)   \
-    ((This)->lpVtbl->QueryPinInfo(This,pInfo))
-#define IPin_QueryDirection(This,pPinDir)   \
-    ((This)->lpVtbl->QueryDirection(This,pPinDir))
-#define IPin_QueryId(This,Id)   \
-    ((This)->lpVtbl->QueryId(This,Id))
-#define IPin_QueryAccept(This,pmt)  \
-    ((This)->lpVtbl->QueryAccept(This,pmt))
-#define IPin_EnumMediaTypes(This,ppEnum)    \
-    ((This)->lpVtbl->EnumMediaTypes(This,ppEnum))
-#define IPin_QueryInternalConnections(This,apPin,nPin)  \
-    ((This)->lpVtbl->QueryInternalConnections(This,apPin,nPin))
-#define IPin_EndOfStream(This)  \
-    ((This)->lpVtbl->EndOfStream(This))
-#define IPin_BeginFlush(This)   \
-    ((This)->lpVtbl->BeginFlush(This))
-#define IPin_EndFlush(This) \
-    ((This)->lpVtbl->EndFlush(This))
-#define IPin_NewSegment(This,tStart,tStop,dRate)    \
-    ((This)->lpVtbl->NewSegment(This,tStart,tStop,dRate))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IEnumPins_QueryInterface(This,riid,ppvObject)   \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IEnumPins_AddRef(This)  \
-    ((This)->lpVtbl->AddRef(This))
-#define IEnumPins_Release(This) \
-    ((This)->lpVtbl->Release(This))
-#define IEnumPins_Next(This,cPins,ppPins,pcFetched) \
-    ((This)->lpVtbl->Next(This,cPins,ppPins,pcFetched))
-#define IEnumPins_Skip(This,cPins)  \
-    ((This)->lpVtbl->Skip(This,cPins))
-#define IEnumPins_Reset(This)   \
-    ((This)->lpVtbl->Reset(This))
-#define IEnumPins_Clone(This,ppEnum)    \
-    ((This)->lpVtbl->Clone(This,ppEnum))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IAMStreamConfig_QueryInterface(This,riid,ppvObject) \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IAMStreamConfig_AddRef(This)    \
-    ((This)->lpVtbl->AddRef(This))
-#define IAMStreamConfig_Release(This)   \
-    ((This)->lpVtbl->Release(This))
-#define IAMStreamConfig_SetFormat(This,pmt) \
-    ((This)->lpVtbl->SetFormat(This,pmt))
-#define IAMStreamConfig_GetFormat(This,ppmt)    \
-    ((This)->lpVtbl->GetFormat(This,ppmt))
-#define IAMStreamConfig_GetNumberOfCapabilities(This,piCount,piSize)    \
-    ((This)->lpVtbl->GetNumberOfCapabilities(This,piCount,piSize))
-#define IAMStreamConfig_GetStreamCaps(This,iIndex,ppmt,pSCC)    \
-    ((This)->lpVtbl->GetStreamCaps(This,iIndex,ppmt,pSCC))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IFilterGraph_QueryInterface(This,riid,ppvObject)    \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IFilterGraph_AddRef(This)   \
-    ((This)->lpVtbl->AddRef(This))
-#define IFilterGraph_Release(This)  \
-    ((This)->lpVtbl->Release(This))
-#define IFilterGraph_AddFilter(This,pFilter,pName)  \
-    ((This)->lpVtbl->AddFilter(This,pFilter,pName))
-#define IFilterGraph_RemoveFilter(This,pFilter) \
-    ((This)->lpVtbl->RemoveFilter(This,pFilter))
-#define IFilterGraph_EnumFilters(This,ppEnum)   \
-    ((This)->lpVtbl->EnumFilters(This,ppEnum))
-#define IFilterGraph_FindFilterByName(This,pName,ppFilter)  \
-    ((This)->lpVtbl->FindFilterByName(This,pName,ppFilter))
-#define IFilterGraph_ConnectDirect(This,ppinOut,ppinIn,pmt) \
-    ((This)->lpVtbl->ConnectDirect(This,ppinOut,ppinIn,pmt))
-#define IFilterGraph_Reconnect(This,ppin)   \
-    ((This)->lpVtbl->Reconnect(This,ppin))
-#define IFilterGraph_Disconnect(This,ppin)  \
-    ((This)->lpVtbl->Disconnect(This,ppin))
-#define IFilterGraph_SetDefaultSyncSource(This) \
-    ((This)->lpVtbl->SetDefaultSyncSource(This))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IMediaFilter_QueryInterface(This,riid,ppvObject)    \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IMediaFilter_AddRef(This)   \
-    ((This)->lpVtbl->AddRef(This))
-#define IMediaFilter_Release(This)  \
-    ((This)->lpVtbl->Release(This))
-#define IMediaFilter_GetClassID(This,pClassID)  \
-    ((This)->lpVtbl->GetClassID(This,pClassID))
-#define IMediaFilter_Stop(This) \
-    ((This)->lpVtbl->Stop(This))
-#define IMediaFilter_Pause(This)    \
-    ((This)->lpVtbl->Pause(This))
-#define IMediaFilter_Run(This,tStart)   \
-    ((This)->lpVtbl->Run(This,tStart))
-#define IMediaFilter_GetState(This,dwMilliSecsTimeout,State)    \
-    ((This)->lpVtbl->GetState(This,dwMilliSecsTimeout,State))
-#define IMediaFilter_SetSyncSource(This,pClock) \
-    ((This)->lpVtbl->SetSyncSource(This,pClock))
-#define IMediaFilter_GetSyncSource(This,pClock) \
-    ((This)->lpVtbl->GetSyncSource(This,pClock))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IBaseFilter_QueryInterface(This,riid,ppvObject) \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IBaseFilter_AddRef(This)    \
-    ((This)->lpVtbl->AddRef(This))
-#define IBaseFilter_Release(This)   \
-    ((This)->lpVtbl->Release(This))
-#define IBaseFilter_GetClassID(This,pClassID)   \
-    ((This)->lpVtbl->GetClassID(This,pClassID))
-#define IBaseFilter_Stop(This)  \
-    ((This)->lpVtbl->Stop(This))
-#define IBaseFilter_Pause(This) \
-    ((This)->lpVtbl->Pause(This))
-#define IBaseFilter_Run(This,tStart)    \
-    ((This)->lpVtbl->Run(This,tStart))
-#define IBaseFilter_GetState(This,dwMilliSecsTimeout,State) \
-    ((This)->lpVtbl->GetState(This,dwMilliSecsTimeout,State))
-#define IBaseFilter_SetSyncSource(This,pClock)  \
-    ((This)->lpVtbl->SetSyncSource(This,pClock))
-#define IBaseFilter_GetSyncSource(This,pClock)  \
-    ((This)->lpVtbl->GetSyncSource(This,pClock))
-#define IBaseFilter_EnumPins(This,ppEnum)   \
-    ((This)->lpVtbl->EnumPins(This,ppEnum))
-#define IBaseFilter_FindPin(This,Id,ppPin)  \
-    ((This)->lpVtbl->FindPin(This,Id,ppPin))
-#define IBaseFilter_QueryFilterInfo(This,pInfo) \
-    ((This)->lpVtbl->QueryFilterInfo(This,pInfo))
-#define IBaseFilter_JoinFilterGraph(This,pGraph,pName)  \
-    ((This)->lpVtbl->JoinFilterGraph(This,pGraph,pName))
-#define IBaseFilter_QueryVendorInfo(This,pVendorInfo)   \
-    ((This)->lpVtbl->QueryVendorInfo(This,pVendorInfo))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IMediaSample_QueryInterface(This,riid,ppvObject)    \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IMediaSample_AddRef(This)   \
-    ((This)->lpVtbl->AddRef(This))
-#define IMediaSample_Release(This)  \
-    ((This)->lpVtbl->Release(This))
-#define IMediaSample_GetPointer(This,ppBuffer)  \
-    ((This)->lpVtbl->GetPointer(This,ppBuffer))
-#define IMediaSample_GetSize(This)  \
-        ((This)->lpVtbl->GetSize(This))
-#define IMediaSample_GetTime(This,pTimeStart,pTimeEnd)  \
-    ((This)->lpVtbl->GetTime(This,pTimeStart,pTimeEnd))
-#define IMediaSample_SetTime(This,pTimeStart,pTimeEnd)  \
-    ((This)->lpVtbl->SetTime(This,pTimeStart,pTimeEnd))
-#define IMediaSample_IsSyncPoint(This)  \
-    ((This)->lpVtbl->IsSyncPoint(This))
-#define IMediaSample_SetSyncPoint(This,bIsSyncPoint)    \
-    ((This)->lpVtbl->SetSyncPoint(This,bIsSyncPoint))
-#define IMediaSample_IsPreroll(This)    \
-    ((This)->lpVtbl->IsPreroll(This))
-#define IMediaSample_SetPreroll(This,bIsPreroll)    \
-    ((This)->lpVtbl->SetPreroll(This,bIsPreroll))
-#define IMediaSample_GetActualDataLength(This)  \
-    ((This)->lpVtbl->GetActualDataLength(This))
-#define IMediaSample_SetActualDataLength(This,length)   \
-    ((This)->lpVtbl->SetActualDataLength(This,length))
-#define IMediaSample_GetMediaType(This,ppMediaType) \
-    ((This)->lpVtbl->GetMediaType(This,ppMediaType))
-#define IMediaSample_SetMediaType(This,pMediaType)  \
-    ((This)->lpVtbl->SetMediaType(This,pMediaType))
-#define IMediaSample_IsDiscontinuity(This)  \
-    ((This)->lpVtbl->IsDiscontinuity(This))
-#define IMediaSample_SetDiscontinuity(This,bDiscontinuity)  \
-    ((This)->lpVtbl->SetDiscontinuity(This,bDiscontinuity))
-#define IMediaSample_GetMediaTime(This,pTimeStart,pTimeEnd) \
-    ((This)->lpVtbl->GetMediaTime(This,pTimeStart,pTimeEnd))
-#define IMediaSample_SetMediaTime(This,pTimeStart,pTimeEnd) \
-    ((This)->lpVtbl->SetMediaTime(This,pTimeStart,pTimeEnd))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IEnumFilters_QueryInterface(This,riid,ppvObject)    \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IEnumFilters_AddRef(This)   \
-    ((This)->lpVtbl->AddRef(This))
-#define IEnumFilters_Release(This)  \
-    ((This)->lpVtbl->Release(This))
-#define IEnumFilters_Next(This,cFilters,ppFilter,pcFetched) \
-    ((This)->lpVtbl->Next(This,cFilters,ppFilter,pcFetched))
-#define IEnumFilters_Skip(This,cFilters)    \
-    ((This)->lpVtbl->Skip(This,cFilters))
-#define IEnumFilters_Reset(This)    \
-    ((This)->lpVtbl->Reset(This))
-#define IEnumFilters_Clone(This,ppEnum) \
-    ((This)->lpVtbl->Clone(This,ppEnum))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IMemAllocator_QueryInterface(This,riid,ppvObject)   \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IMemAllocator_AddRef(This)  \
-    ((This)->lpVtbl->AddRef(This))
-#define IMemAllocator_Release(This) \
-    ((This)->lpVtbl->Release(This))
-#define IMemAllocator_SetProperties(This,pRequest,pActual)  \
-    ((This)->lpVtbl->SetProperties(This,pRequest,pActual))
-#define IMemAllocator_GetProperties(This,pProps)    \
-    ((This)->lpVtbl->GetProperties(This,pProps))
-#define IMemAllocator_Commit(This)  \
-    ((This)->lpVtbl->Commit(This))
-#define IMemAllocator_Decommit(This)    \
-    ((This)->lpVtbl->Decommit(This))
-#define IMemAllocator_GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags)  \
-    ((This)->lpVtbl->GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags))
-#define IMemAllocator_ReleaseBuffer(This,pBuffer)   \
-    ((This)->lpVtbl->ReleaseBuffer(This,pBuffer))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IMemInputPin_QueryInterface(This,riid,ppvObject)    \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IMemInputPin_AddRef(This)   \
-    ((This)->lpVtbl->AddRef(This))
-#define IMemInputPin_Release(This)  \
-    ((This)->lpVtbl->Release(This))
-#define IMemInputPin_GetAllocator(This,ppAllocator) \
-    ((This)->lpVtbl->GetAllocator(This,ppAllocator))
-#define IMemInputPin_NotifyAllocator(This,pAllocator,bReadOnly) \
-    ((This)->lpVtbl->NotifyAllocator(This,pAllocator,bReadOnly))
-#define IMemInputPin_GetAllocatorRequirements(This,pProps)  \
-    ((This)->lpVtbl->GetAllocatorRequirements(This,pProps))
-#define IMemInputPin_Receive(This,pSample)  \
-    ((This)->lpVtbl->Receive(This,pSample))
-#define IMemInputPin_ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed)  \
-    ((This)->lpVtbl->ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed))
-#define IMemInputPin_ReceiveCanBlock(This)  \
-    ((This)->lpVtbl->ReceiveCanBlock(This))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IGraphBuilder_QueryInterface(This,riid,ppvObject)   \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IGraphBuilder_AddRef(This)  \
-    ((This)->lpVtbl->AddRef(This))
-#define IGraphBuilder_Release(This) \
-    ((This)->lpVtbl->Release(This))
-#define IGraphBuilder_AddFilter(This,pFilter,pName) \
-    ((This)->lpVtbl->AddFilter(This,pFilter,pName))
-#define IGraphBuilder_RemoveFilter(This,pFilter)    \
-    ((This)->lpVtbl->RemoveFilter(This,pFilter))
-#define IGraphBuilder_EnumFilters(This,ppEnum)  \
-    ((This)->lpVtbl->EnumFilters(This,ppEnum))
-#define IGraphBuilder_FindFilterByName(This,pName,ppFilter) \
-    ((This)->lpVtbl->FindFilterByName(This,pName,ppFilter))
-#define IGraphBuilder_ConnectDirect(This,ppinOut,ppinIn,pmt)    \
-    ((This)->lpVtbl->ConnectDirect(This,ppinOut,ppinIn,pmt))
-#define IGraphBuilder_Reconnect(This,ppin)  \
-    ((This)->lpVtbl->Reconnect(This,ppin))
-#define IGraphBuilder_Disconnect(This,ppin) \
-    ((This)->lpVtbl->Disconnect(This,ppin))
-#define IGraphBuilder_SetDefaultSyncSource(This)    \
-    ((This)->lpVtbl->SetDefaultSyncSource(This))
-#define IGraphBuilder_Connect(This,ppinOut,ppinIn)  \
-    ((This)->lpVtbl->Connect(This,ppinOut,ppinIn))
-#define IGraphBuilder_Render(This,ppinOut)  \
-    ((This)->lpVtbl->Render(This,ppinOut))
-#define IGraphBuilder_RenderFile(This,lpcwstrFile,lpcwstrPlayList)  \
-    ((This)->lpVtbl->RenderFile(This,lpcwstrFile,lpcwstrPlayList))
-#define IGraphBuilder_AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter)  \
-    ((This)->lpVtbl->AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter))
-#define IGraphBuilder_SetLogFile(This,hFile)    \
-    ((This)->lpVtbl->SetLogFile(This,hFile))
-#define IGraphBuilder_Abort(This)   \
-    ((This)->lpVtbl->Abort(This))
-#define IGraphBuilder_ShouldOperationContinue(This) \
-    ((This)->lpVtbl->ShouldOperationContinue(This))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IEnumMediaTypes_QueryInterface(This,riid,ppvObject) \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IEnumMediaTypes_AddRef(This)    \
-    ((This)->lpVtbl->AddRef(This))
-#define IEnumMediaTypes_Release(This)   \
-    ((This)->lpVtbl->Release(This))
-#define IEnumMediaTypes_Next(This,cMediaTypes,ppMediaTypes,pcFetched)   \
-    ((This)->lpVtbl->Next(This,cMediaTypes,ppMediaTypes,pcFetched))
-#define IEnumMediaTypes_Skip(This,cMediaTypes)  \
-    ((This)->lpVtbl->Skip(This,cMediaTypes))
-#define IEnumMediaTypes_Reset(This) \
-    ((This)->lpVtbl->Reset(This))
-#define IEnumMediaTypes_Clone(This,ppEnum)  \
-    ((This)->lpVtbl->Clone(This,ppEnum))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IMediaControl_QueryInterface(This,riid,ppvObject)   \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IMediaControl_AddRef(This)  \
-    ((This)->lpVtbl->AddRef(This))
-#define IMediaControl_Release(This) \
-    ((This)->lpVtbl->Release(This))
-#define IMediaControl_GetTypeInfoCount(This,pctinfo)    \
-    ((This)->lpVtbl->GetTypeInfoCount(This,pctinfo))
-#define IMediaControl_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
-    ((This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo))
-#define IMediaControl_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)   \
-    ((This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId))
-#define IMediaControl_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
-    ((This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr))
-#define IMediaControl_Run(This) \
-    ((This)->lpVtbl->Run(This))
-#define IMediaControl_Pause(This)   \
-    ((This)->lpVtbl->Pause(This))
-#define IMediaControl_Stop(This)    \
-    ((This)->lpVtbl->Stop(This))
-#define IMediaControl_GetState(This,msTimeout,pfs)  \
-    ((This)->lpVtbl->GetState(This,msTimeout,pfs))
-#define IMediaControl_RenderFile(This,strFilename)  \
-    ((This)->lpVtbl->RenderFile(This,strFilename))
-#define IMediaControl_AddSourceFilter(This,strFilename,ppUnk)   \
-    ((This)->lpVtbl->AddSourceFilter(This,strFilename,ppUnk))
-#define IMediaControl_get_FilterCollection(This,ppUnk)  \
-    ((This)->lpVtbl->get_FilterCollection(This,ppUnk))
-#define IMediaControl_get_RegFilterCollection(This,ppUnk)   \
-    ((This)->lpVtbl->get_RegFilterCollection(This,ppUnk))
-#define IMediaControl_StopWhenReady(This)   \
-    ((This)->lpVtbl->StopWhenReady(This))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IAMVideoProcAmp_QueryInterface(This,riid,ppvObject) \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IAMVideoProcAmp_AddRef(This)    \
-    ((This)->lpVtbl->AddRef(This))
-#define IAMVideoProcAmp_Release(This)   \
-    ((This)->lpVtbl->Release(This))
-#define IAMVideoProcAmp_GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags)    \
-    ((This)->lpVtbl->GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags))
-#define IAMVideoProcAmp_Set(This,Property,lValue,Flags) \
-    ((This)->lpVtbl->Set(This,Property,lValue,Flags))
-#define IAMVideoProcAmp_Get(This,Property,lValue,Flags) \
-    ((This)->lpVtbl->Get(This,Property,lValue,Flags))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IFileSinkFilter_QueryInterface(This,riid,ppvObject) \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IFileSinkFilter_AddRef(This)    \
-    ((This)->lpVtbl->AddRef(This))
-#define IFileSinkFilter_Release(This)   \
-    ((This)->lpVtbl->Release(This))
-#define IFileSinkFilter_SetFileName(This,pszFileName,pmt)   \
-    ((This)->lpVtbl->SetFileName(This,pszFileName,pmt))
-#define IFileSinkFilter_GetCurFile(This,ppszFileName,pmt)   \
-    ((This)->lpVtbl->GetCurFile(This,ppszFileName,pmt))
-#endif /* COBJMACROS */
-
-#ifdef COBJMACROS
-#define IAMCopyCaptureFileProgress_QueryInterface(This,riid,ppvObject)  \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define IAMCopyCaptureFileProgress_AddRef(This) \
-    ((This)->lpVtbl->AddRef(This))
-#define IAMCopyCaptureFileProgress_Release(This)    \
-    ((This)->lpVtbl->Release(This))
-#define IAMCopyCaptureFileProgress_Progress(This,iProgress) \
-    ((This)->lpVtbl->Progress(This,iProgress))
-#endif /* COBJMACROS */
-
-
-#ifdef COBJMACROS
-#define ICaptureGraphBuilder2_QueryInterface(This,riid,ppvObject)   \
-    ((This)->lpVtbl->QueryInterface(This,riid,ppvObject))
-#define ICaptureGraphBuilder2_AddRef(This)  \
-    ((This)->lpVtbl->AddRef(This))
-#define ICaptureGraphBuilder2_Release(This) \
-    ((This)->lpVtbl->Release(This))
-#define ICaptureGraphBuilder2_SetFiltergraph(This,pfg)  \
-    ((This)->lpVtbl->SetFiltergraph(This,pfg))
-#define ICaptureGraphBuilder2_GetFiltergraph(This,ppfg) \
-    ((This)->lpVtbl->GetFiltergraph(This,ppfg))
-#define ICaptureGraphBuilder2_SetOutputFileName(This,pType,lpstrFile,ppf,ppSink)    \
-    ((This)->lpVtbl->SetOutputFileName(This,pType,lpstrFile,ppf,ppSink))
-#define ICaptureGraphBuilder2_FindInterface(This,pCategory,pType,pf,riid,ppint) \
-    ((This)->lpVtbl->FindInterface(This,pCategory,pType,pf,riid,ppint))
-#define ICaptureGraphBuilder2_RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer)    \
-    ((This)->lpVtbl->RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer))
-#define ICaptureGraphBuilder2_ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie) \
-    ((This)->lpVtbl->ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie))
-#define ICaptureGraphBuilder2_AllocCapFile(This,lpstr,dwlSize)  \
-    ((This)->lpVtbl->AllocCapFile(This,lpstr,dwlSize))
-#define ICaptureGraphBuilder2_CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback)    \
-    ((This)->lpVtbl->CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback))
-#define ICaptureGraphBuilder2_FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin)   \
-    ((This)->lpVtbl->FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin))
-#endif /* COBJMACROS */
-
-#endif /* _MARU_CAMERA_INTERFACE_H_ */
diff --git a/tizen/src/hw/pci/maru_camera_win32_pci.c b/tizen/src/hw/pci/maru_camera_win32_pci.c
deleted file mode 100644 (file)
index 72bfbbb..0000000
+++ /dev/null
@@ -1,2799 +0,0 @@
-/*
- * Implementation of MARU Virtual Camera device by PCI bus on Windows.
- *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Contact:
- * JinHyung Jo <jinhyung.jo@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-
-#include "qemu-common.h"
-#include "sysemu/hax.h"
-#include "maru_camera_common.h"
-#include "debug_ch.h"
-
-#define CINTERFACE
-#define COBJMACROS
-#include "ocidl.h"
-#include "errors.h"      /* for VFW_E_XXXX */
-#include "mmsystem.h"    /* for MAKEFOURCC macro */
-#include "maru_camera_win32_interface.h"
-
-MULTI_DEBUG_CHANNEL(tizen, camera);
-
-/*
- * COM Interface implementations
- *
- */
-
-#define SAFE_RELEASE(x) \
-    do { \
-        if (x) { \
-            (x)->lpVtbl->Release(x); \
-            x = NULL; \
-        } \
-    } while (0)
-
-typedef HRESULT (STDAPICALLTYPE *CallbackFn)(ULONG dwSize, BYTE *pBuffer);
-
-/*
- * HWCGrabCallback
- */
-
-typedef struct HWCGrabCallback {
-    IGrabCallback IGrabCallback_iface;
-    long m_cRef;
-    CallbackFn m_pCallback;
-    STDMETHODIMP (*SetCallback)(IGrabCallback *iface, CallbackFn pCallbackFn);
-} HWCGrabCallback;
-
-static inline HWCGrabCallback *impl_from_IGrabCallback(IGrabCallback *iface)
-{
-    return CONTAINING_RECORD(iface, HWCGrabCallback, IGrabCallback_iface);
-}
-
-static STDMETHODIMP HWCGrabCallback_QueryInterface(IGrabCallback *iface,
-                                                   REFIID riid, void **ppv)
-{
-    if (IsEqualIID(riid, &IID_IUnknown)) {
-        *ppv = (IUnknown *)iface;
-    } else if (IsEqualIID(riid, &IID_IGrabCallback)) {
-        *ppv = (IGrabCallback *)iface;
-    } else {
-        *ppv = NULL;
-        return E_NOINTERFACE;
-    }
-
-    IGrabCallback_AddRef(iface);
-    return S_OK;
-}
-
-static STDMETHODIMP_(ULONG) HWCGrabCallback_AddRef(IGrabCallback *iface)
-{
-    HWCGrabCallback *This = impl_from_IGrabCallback(iface);
-
-    return InterlockedIncrement(&This->m_cRef);
-}
-
-static STDMETHODIMP_(ULONG) HWCGrabCallback_Release(IGrabCallback *iface)
-{
-    HWCGrabCallback *This = impl_from_IGrabCallback(iface);
-
-    if (InterlockedDecrement(&This->m_cRef) == 0) {
-        This->m_pCallback = NULL;
-        g_free((void *)This);
-        This = NULL;
-        return 0;
-    }
-
-    return This->m_cRef;
-}
-
-static STDMETHODIMP HWCGrabCallback_Grab(IGrabCallback *iface,
-                                         ULONG dwSize, BYTE *pBuffer)
-{
-    HWCGrabCallback *This = impl_from_IGrabCallback(iface);
-
-    if (This->m_pCallback) {
-        HRESULT hr = This->m_pCallback(dwSize, pBuffer);
-        if (FAILED(hr)) {
-            return E_FAIL;
-        } else {
-            return S_OK;
-        }
-    }
-
-    return E_FAIL;
-}
-
-static STDMETHODIMP HWCGrabCallback_SetCallback(IGrabCallback *iface,
-                                                CallbackFn pCallbackFn)
-{
-    HWCGrabCallback *This = impl_from_IGrabCallback(iface);
-
-    This->m_pCallback = pCallbackFn;
-    return S_OK;
-}
-
-static IGrabCallbackVtbl HWCGrabCallback_Vtbl = {
-        HWCGrabCallback_QueryInterface,
-        HWCGrabCallback_AddRef,
-        HWCGrabCallback_Release,
-        HWCGrabCallback_Grab
-};
-
-static STDMETHODIMP HWCGrabCallback_Construct(IGrabCallback **ppv)
-{
-    HWCGrabCallback *This =
-            (HWCGrabCallback *)g_malloc0(sizeof(HWCGrabCallback));
-
-    if (!This) {
-        ERR("failed to HWCGrabCallback_Construct, E_OUTOFMEMORY\n");
-        return E_OUTOFMEMORY;
-    }
-
-    This->IGrabCallback_iface.lpVtbl = &HWCGrabCallback_Vtbl;
-    This->m_cRef = 1;
-    This->m_pCallback = NULL;
-    This->SetCallback = HWCGrabCallback_SetCallback;
-    *ppv = &This->IGrabCallback_iface;
-    return S_OK;
-}
-
-/*
- * HWCPin
- */
-
-typedef struct HWCInPin {
-    IPin IPin_iface;
-    IMemInputPin IMemInputPin_iface;
-    IBaseFilter *m_pCFilter;
-    IPin *m_pConnectedPin;
-    IGrabCallback *m_pCallback;
-    IMemAllocator *m_pAllocator;
-    BOOL m_bReadOnly;
-    long m_cRef;
-    STDMETHODIMP (*SetGrabCallbackIF)(IPin *iface, IGrabCallback *pCaptureCB);
-} HWCInPin;
-
-static inline HWCInPin *impl_from_IPin(IPin *iface)
-{
-    return CONTAINING_RECORD(iface, HWCInPin, IPin_iface);
-}
-
-static inline HWCInPin *impl_from_IMemInputPin(IMemInputPin *iface)
-{
-    return CONTAINING_RECORD(iface, HWCInPin, IMemInputPin_iface);
-}
-
-static STDMETHODIMP HWCPin_QueryInterface(IPin *iface, REFIID riid, void **ppv)
-{
-    HWCInPin *This = impl_from_IPin(iface);
-
-    if (IsEqualIID(riid, &IID_IUnknown)) {
-        *ppv = (IUnknown *)(&This->IPin_iface);
-        IPin_AddRef((IPin *)*ppv);
-    } else if (IsEqualIID(riid, &IID_IPin)) {
-        *ppv = (IPin *)(&This->IPin_iface);
-        IPin_AddRef((IPin *)*ppv);
-    } else if (IsEqualIID(riid, &IID_IMemInputPin)) {
-        *ppv = (IMemInputPin *)(&This->IMemInputPin_iface);
-        IPin_AddRef((IMemInputPin *)*ppv);
-    } else {
-        *ppv = NULL;
-        return E_NOINTERFACE;
-    }
-
-    return S_OK;
-}
-
-static STDMETHODIMP_(ULONG) HWCPin_AddRef(IPin *iface)
-{
-    HWCInPin *This = impl_from_IPin(iface);
-
-    return InterlockedIncrement(&This->m_cRef);
-}
-
-static STDMETHODIMP_(ULONG) HWCPin_Release(IPin *iface)
-{
-    HWCInPin *This = impl_from_IPin(iface);
-
-    if (InterlockedDecrement(&This->m_cRef) == 0) {
-        if (This->m_pCallback) {
-            SAFE_RELEASE(This->m_pCallback);
-        }
-        if (This->m_pConnectedPin) {
-            SAFE_RELEASE(This->m_pConnectedPin);
-        }
-        if (This->m_pAllocator) {
-            IMemAllocator_Decommit(This->m_pAllocator);
-            SAFE_RELEASE(This->m_pAllocator);
-        }
-        g_free((void *)This);
-        This = NULL;
-        return 0;
-    }
-    return This->m_cRef;
-}
-
-static STDMETHODIMP HWCPin_Connect(IPin *iface,
-                                   IPin *pReceivePin,
-                                   const AM_MEDIA_TYPE *pmt)
-{
-    HWCInPin *This = impl_from_IPin(iface);
-
-    if (!pReceivePin) {
-        return E_POINTER;
-    }
-
-    if (This->m_pConnectedPin) {
-        return VFW_E_ALREADY_CONNECTED;
-    }
-
-    if (!pmt) {
-        return S_OK;
-    }
-    return S_FALSE;
-}
-
-static STDMETHODIMP HWCPin_ReceiveConnection(IPin *iface, IPin *pConnector,
-                                             const AM_MEDIA_TYPE *pmt)
-{
-    PIN_DIRECTION pd;
-    FILTER_STATE fs;
-    HWCInPin *This = impl_from_IPin(iface);
-
-    if (pConnector == NULL || pmt == NULL) {
-        return E_POINTER;
-    }
-
-    if (This->m_pConnectedPin) {
-        return VFW_E_ALREADY_CONNECTED;
-    }
-    IBaseFilter_GetState(This->m_pCFilter, 0, &fs);
-    if (fs != State_Stopped) {
-        return VFW_E_NOT_STOPPED;
-    }
-    IPin_QueryDirection(pConnector, &pd);
-    if (pd == PINDIR_INPUT) {
-        return VFW_E_INVALID_DIRECTION;
-    }
-
-    This->m_pConnectedPin = pConnector;
-    IPin_AddRef(This->m_pConnectedPin);
-    return S_OK;
-}
-
-static STDMETHODIMP HWCPin_Disconnect(IPin *iface)
-{
-    HWCInPin *This = impl_from_IPin(iface);
-
-    HRESULT hr;
-    FILTER_STATE fs;
-    IBaseFilter_GetState(This->m_pCFilter, 0, &fs);
-    if (fs != State_Stopped) {
-        return VFW_E_NOT_STOPPED;
-    }
-    if (This->m_pConnectedPin == NULL) {
-        hr = S_FALSE;
-    } else {
-        if (This->m_pAllocator) {
-            hr = IMemAllocator_Decommit(This->m_pAllocator);
-            if (FAILED(hr)) {
-                return hr;
-            }
-            SAFE_RELEASE(This->m_pAllocator);
-        }
-        SAFE_RELEASE(This->m_pConnectedPin);
-        hr = S_OK;
-    }
-    return hr;
-}
-
-static STDMETHODIMP HWCPin_ConnectedTo(IPin *iface, IPin **ppPin)
-{
-    HWCInPin *This = impl_from_IPin(iface);
-
-    if (ppPin == NULL) {
-        return E_POINTER;
-    }
-
-    if (This->m_pConnectedPin == NULL) {
-        *ppPin = NULL;
-        return VFW_E_NOT_CONNECTED;
-    } else {
-        *ppPin = This->m_pConnectedPin;
-        IPin_AddRef(This->m_pConnectedPin);
-    }
-    return S_OK;
-}
-
-static STDMETHODIMP HWCPin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *pmt)
-{
-    if (pmt == NULL) {
-        return E_POINTER;
-    }
-    return VFW_E_NOT_CONNECTED;
-}
-
-static STDMETHODIMP HWCPin_QueryPinInfo(IPin *iface, PIN_INFO *pInfo)
-{
-    HWCInPin *This = impl_from_IPin(iface);
-
-    if (pInfo == NULL) {
-        return E_POINTER;
-    }
-
-    pInfo->pFilter = This->m_pCFilter;
-    if (This->m_pCFilter) {
-        IBaseFilter_AddRef(This->m_pCFilter);
-    }
-    memcpy((void *)pInfo->achName, (void *)HWCPinName, sizeof(HWCPinName));
-    pInfo->dir = PINDIR_INPUT;
-    return S_OK;
-}
-
-static STDMETHODIMP HWCPin_QueryDirection(IPin *iface, PIN_DIRECTION *pPinDir)
-{
-    if (pPinDir == NULL) {
-        return E_POINTER;
-    }
-    *pPinDir = PINDIR_INPUT;
-    return S_OK;
-}
-
-static STDMETHODIMP HWCPin_QueryId(IPin *iface, LPWSTR *Id)
-{
-    PVOID pId;
-    if (Id == NULL) {
-        return E_POINTER;
-    }
-    pId = CoTaskMemAlloc(sizeof(HWCPinName));
-    memcpy((void *)pId, (void *)HWCPinName, sizeof(HWCPinName));
-    *Id = (LPWSTR)pId;
-    return S_OK;
-}
-
-static STDMETHODIMP HWCPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *pmt)
-{
-    if (pmt == NULL) {
-        return E_POINTER;
-    }
-    return S_OK;
-}
-
-static STDMETHODIMP HWCPin_EnumMediaTypes(IPin *iface,
-                                          IEnumMediaTypes **ppEnum)
-{
-    if (ppEnum == NULL) {
-            return E_POINTER;
-    }
-    return E_NOTIMPL;
-}
-
-static STDMETHODIMP HWCPin_QueryInternalConnections(IPin *iface,
-                                                    IPin **ppPin,
-                                                    ULONG *nPin)
-{
-    return E_NOTIMPL;
-}
-
-static STDMETHODIMP HWCPin_EndOfStream(IPin *iface)
-{
-    return S_OK;
-}
-
-static STDMETHODIMP HWCPin_BeginFlush(IPin *iface)
-{
-    return S_OK;
-}
-
-static STDMETHODIMP HWCPin_EndFlush(IPin *iface)
-{
-    return S_OK;
-}
-
-static STDMETHODIMP HWCPin_NewSegment(IPin *iface, REFERENCE_TIME tStart,
-                                      REFERENCE_TIME tStop, double dRate)
-{
-    return S_OK;
-}
-
-static STDMETHODIMP HWCMemInputPin_QueryInterface(IMemInputPin *iface,
-                                                  REFIID riid, void **ppv)
-{
-    HWCInPin *This = impl_from_IMemInputPin(iface);
-
-    if (IsEqualIID(riid, &IID_IUnknown)) {
-        *ppv = (IUnknown *)(&This->IMemInputPin_iface);
-        IPin_AddRef((IPin *)*ppv);
-    } else if (IsEqualIID(riid, &IID_IPin)) {
-        *ppv = (IPin *)(&This->IPin_iface);
-        IPin_AddRef((IPin *)*ppv);
-    } else if (IsEqualIID(riid, &IID_IMemInputPin)) {
-        *ppv = (IMemInputPin *)(&This->IMemInputPin_iface);
-        IPin_AddRef((IMemInputPin *)*ppv);
-    } else {
-        *ppv = NULL;
-        return E_NOINTERFACE;
-    }
-
-    return S_OK;
-}
-
-static STDMETHODIMP_(ULONG) HWCMemInputPin_AddRef(IMemInputPin *iface)
-{
-    HWCInPin *This = impl_from_IMemInputPin(iface);
-
-    return InterlockedIncrement(&This->m_cRef);
-}
-
-static STDMETHODIMP_(ULONG) HWCMemInputPin_Release(IMemInputPin *iface)
-{
-    HWCInPin *This = impl_from_IMemInputPin(iface);
-
-    if (InterlockedDecrement(&This->m_cRef) == 0) {
-        if (This->m_pCallback) {
-            SAFE_RELEASE(This->m_pCallback);
-        }
-        if (This->m_pConnectedPin) {
-            SAFE_RELEASE(This->m_pConnectedPin);
-        }
-        if (This->m_pAllocator) {
-            IMemAllocator_Decommit(This->m_pAllocator);
-            SAFE_RELEASE(This->m_pAllocator);
-        }
-        g_free((void *)This);
-        This = NULL;
-        return 0;
-    }
-    return This->m_cRef;
-}
-
-static STDMETHODIMP HWCMemInputPin_GetAllocator(IMemInputPin *iface,
-                                                IMemAllocator **ppAllocator)
-{
-    HWCInPin *This = impl_from_IMemInputPin(iface);
-
-    if (ppAllocator == NULL) {
-        return E_POINTER;
-    }
-
-    if (This->m_pAllocator == NULL) {
-        HRESULT hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL,
-                                        CLSCTX_INPROC_SERVER,
-                                        &IID_IMemAllocator,
-                                        (void **)&(This->m_pAllocator));
-        if (FAILED(hr)) {
-            ERR("Failed to CoCreateInstance for retrieving MemoryAllocator\n");
-            return hr;
-        }
-    }
-    assert(This->m_pAllocator != NULL);
-    *ppAllocator = This->m_pAllocator;
-    IMemAllocator_AddRef(This->m_pAllocator);
-
-    return S_OK;
-}
-
-static STDMETHODIMP HWCMemInputPin_NotifyAllocator(IMemInputPin *iface,
-                                                   IMemAllocator *pAllocator,
-                                                   BOOL bReadOnly)
-{
-    HWCInPin *This = impl_from_IMemInputPin(iface);
-
-    if (pAllocator == NULL) {
-        return E_POINTER;
-    }
-
-    IMemAllocator *pOldAllocator = This->m_pAllocator;
-    IMemAllocator_AddRef(pAllocator);
-    This->m_pAllocator = pAllocator;
-
-    if (pOldAllocator != NULL) {
-        SAFE_RELEASE(pOldAllocator);
-    }
-
-    This->m_bReadOnly = bReadOnly;
-
-    return S_OK;
-}
-
-static STDMETHODIMP HWCMemInputPin_GetAllocatorRequirements(
-                                   IMemInputPin *iface,
-                                   ALLOCATOR_PROPERTIES *pProps)
-{
-    return E_NOTIMPL;
-}
-
-static STDMETHODIMP HWCMemInputPin_Receive(IMemInputPin *iface,
-                                           IMediaSample *pSample)
-{
-    HWCInPin *This = impl_from_IMemInputPin(iface);
-
-    if (pSample == NULL) {
-        ERR("pSample is NULL\n");
-        return E_POINTER;
-    }
-    if (This->m_pCallback != NULL) {
-        HRESULT hr;
-        BYTE *pBuffer = NULL;
-        DWORD dwSize = 0;
-        dwSize = IMediaSample_GetSize(pSample);
-        hr = IMediaSample_GetPointer(pSample, &pBuffer);
-        if (FAILED(hr)) {
-            ERR("Receive function : "
-                "failed to IMediaSample_GetPointer, 0x%ld\n", hr);
-            return hr;
-        }
-        hr = IGrabCallback_Grab(This->m_pCallback, dwSize, pBuffer);
-        if (FAILED(hr)) {
-            ERR("Receive function : failed to IGrabCallback_Grab, 0x%ld\n",
-                hr);
-            return hr;
-        }
-    }
-    return S_OK;
-}
-
-static STDMETHODIMP HWCMemInputPin_ReceiveMultiple(IMemInputPin *iface,
-                                                   IMediaSample **pSamples,
-                                                   long nSamples,
-                                                   long *nSamplesProcessed)
-{
-    HRESULT hr = S_OK;
-
-    if (pSamples == NULL) {
-        return E_POINTER;
-    }
-
-    *nSamplesProcessed = 0;
-
-    while (nSamples-- > 0) {
-        hr = IMemInputPin_Receive(iface, pSamples[*nSamplesProcessed]);
-        if (hr != S_OK) {
-            break;
-        }
-        (*nSamplesProcessed)++;
-    }
-    return hr;
-}
-
-static STDMETHODIMP HWCMemInputPin_ReceiveCanBlock(IMemInputPin *iface)
-{
-    return S_FALSE;
-}
-
-static STDMETHODIMP HWCPin_SetCallback(IPin *iface, IGrabCallback *pCaptureCB)
-{
-    HWCInPin *This = impl_from_IPin(iface);
-
-    if (pCaptureCB == NULL) {
-        SAFE_RELEASE(This->m_pCallback);
-    } else {
-        This->m_pCallback = pCaptureCB;
-        IGrabCallback_AddRef(This->m_pCallback);
-    }
-
-    return S_OK;
-}
-
-
-static IPinVtbl HWCPin_Vtbl = {
-    HWCPin_QueryInterface,
-    HWCPin_AddRef,
-    HWCPin_Release,
-    HWCPin_Connect,
-    HWCPin_ReceiveConnection,
-    HWCPin_Disconnect,
-    HWCPin_ConnectedTo,
-    HWCPin_ConnectionMediaType,
-    HWCPin_QueryPinInfo,
-    HWCPin_QueryDirection,
-    HWCPin_QueryId,
-    HWCPin_QueryAccept,
-    HWCPin_EnumMediaTypes,
-    HWCPin_QueryInternalConnections,
-    HWCPin_EndOfStream,
-    HWCPin_BeginFlush,
-    HWCPin_EndFlush,
-    HWCPin_NewSegment
-};
-
-static IMemInputPinVtbl HWCMemInputPin_Vtbl = {
-    HWCMemInputPin_QueryInterface,
-    HWCMemInputPin_AddRef,
-    HWCMemInputPin_Release,
-    HWCMemInputPin_GetAllocator,
-    HWCMemInputPin_NotifyAllocator,
-    HWCMemInputPin_GetAllocatorRequirements,
-    HWCMemInputPin_Receive,
-    HWCMemInputPin_ReceiveMultiple,
-    HWCMemInputPin_ReceiveCanBlock
-};
-
-static STDMETHODIMP HWCInPin_Construct(IBaseFilter *pFilter, IPin **ppv)
-{
-    HWCInPin *This = (HWCInPin *)g_malloc0(sizeof(HWCInPin));
-
-    if (!This) {
-        ERR("failed to HWCInPin_Construct, E_OUTOFMEMORY\n");
-        return E_OUTOFMEMORY;
-    }
-
-    This->IPin_iface.lpVtbl = &HWCPin_Vtbl;
-    This->IMemInputPin_iface.lpVtbl = &HWCMemInputPin_Vtbl;
-    This->m_bReadOnly = FALSE;
-    This->m_pCFilter = pFilter;
-    This->m_pConnectedPin = NULL;
-    This->m_pCallback = NULL;
-    This->m_pAllocator = NULL;
-    This->m_cRef = 1;
-    This->SetGrabCallbackIF = HWCPin_SetCallback;
-    *ppv = &This->IPin_iface;
-
-    return S_OK;
-}
-
-/*
- * HWCEnumPins
- */
-
-typedef struct HWCEnumPins {
-    IEnumPins IEnumPins_iface;
-    IBaseFilter *m_pFilter;
-    int m_nPos;
-    long m_cRef;
-} HWCEnumPins;
-
-static inline HWCEnumPins *impl_from_IEnumPins(IEnumPins *iface)
-{
-    return CONTAINING_RECORD(iface, HWCEnumPins, IEnumPins_iface);
-}
-
-static STDMETHODIMP HWCEnumPins_QueryInterface(IEnumPins *iface,
-                                               REFIID riid, void **ppv)
-{
-    if (ppv == NULL) {
-        return E_POINTER;
-    }
-
-    if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumPins)) {
-        *ppv = iface;
-    } else {
-        *ppv = NULL;
-        return E_NOINTERFACE;
-    }
-
-    IEnumPins_AddRef(iface);
-    return S_OK;
-}
-
-static STDMETHODIMP_(ULONG) HWCEnumPins_AddRef(IEnumPins *iface)
-{
-    HWCEnumPins *This = impl_from_IEnumPins(iface);
-
-    return InterlockedIncrement(&This->m_cRef);
-}
-
-static STDMETHODIMP_(ULONG) HWCEnumPins_Release(IEnumPins *iface)
-{
-    HWCEnumPins *This = impl_from_IEnumPins(iface);
-
-    if (InterlockedDecrement(&This->m_cRef) == 0) {
-        if (This->m_pFilter) {
-            SAFE_RELEASE(This->m_pFilter);
-        }
-        This->m_nPos = 0;
-        g_free((void *)This);
-        This = NULL;
-        return 0;
-    }
-    return This->m_cRef;
-}
-
-static STDMETHODIMP HWCEnumPins_Next(IEnumPins *iface, ULONG cPins,
-                                     IPin **ppPins, ULONG *pcFetched)
-{
-    ULONG fetched;
-    HWCEnumPins *This = impl_from_IEnumPins(iface);
-
-    if (ppPins == NULL) {
-        return E_POINTER;
-    }
-
-    if (This->m_nPos < 1 && cPins > 0) {
-        IPin *pPin;
-        IBaseFilter_FindPin(This->m_pFilter, HWCPinName, &pPin);
-        *ppPins = pPin;
-        fetched = 1;
-        This->m_nPos++;
-    } else {
-        fetched = 0;
-    }
-
-    if (pcFetched != NULL) {
-        *pcFetched = fetched;
-    }
-
-    return (fetched == cPins) ? S_OK : S_FALSE;
-}
-
-static STDMETHODIMP HWCEnumPins_Skip(IEnumPins *iface, ULONG cPins)
-{
-    HWCEnumPins *This = impl_from_IEnumPins(iface);
-    This->m_nPos += cPins;
-    return (This->m_nPos >= 1) ? S_FALSE : S_OK;
-}
-
-static STDMETHODIMP HWCEnumPins_Reset(IEnumPins *iface)
-{
-    HWCEnumPins *This = impl_from_IEnumPins(iface);
-    This->m_nPos = 0;
-    return S_OK;
-}
-
-static STDMETHODIMP HWCEnumPins_Construct(IBaseFilter *pFilter,
-                                          int nPos, IEnumPins **ppv);
-
-static STDMETHODIMP HWCEnumPins_Clone(IEnumPins *iface, IEnumPins **ppEnum)
-{
-    HWCEnumPins *This = impl_from_IEnumPins(iface);
-
-    if (ppEnum == NULL) {
-        return E_POINTER;
-    }
-
-    HWCEnumPins_Construct(This->m_pFilter, This->m_nPos, ppEnum);
-    if (*ppEnum == NULL) {
-        ERR("failed to HWCEnumPins_Construct in clone, E_OUTOFMEMORY\n");
-        return E_OUTOFMEMORY;
-    }
-
-    return S_OK;
-}
-
-static IEnumPinsVtbl HWCEnumPins_Vtbl = {
-    HWCEnumPins_QueryInterface,
-    HWCEnumPins_AddRef,
-    HWCEnumPins_Release,
-    HWCEnumPins_Next,
-    HWCEnumPins_Skip,
-    HWCEnumPins_Reset,
-    HWCEnumPins_Clone
-};
-
-
-static STDMETHODIMP HWCEnumPins_Construct(IBaseFilter *pFilter,
-                                          int nPos, IEnumPins **ppv)
-{
-    HWCEnumPins *This = (HWCEnumPins *)g_malloc0(sizeof(HWCEnumPins));
-
-    if (!This) {
-        ERR("failed to HWCEnumPins_Construct, E_OUTOFMEMORY\n");
-        return E_OUTOFMEMORY;
-    }
-
-    This->IEnumPins_iface.lpVtbl = &HWCEnumPins_Vtbl;
-    This->m_pFilter = pFilter;
-    if (This->m_pFilter) {
-        IBaseFilter_AddRef(This->m_pFilter);
-    }
-    This->m_cRef = 1;
-    This->m_nPos = nPos;
-    *ppv = &This->IEnumPins_iface;
-
-    return S_OK;
-}
-
-/*
- * HWCFilter
- */
-
-typedef struct HWCFilter {
-    IBaseFilter IBaseFilter_iface;
-    IPin *m_pPin;
-    IFilterGraph *m_pFilterGraph;
-    FILTER_STATE m_state;
-    long m_cRef;
-} HWCFilter;
-
-static inline HWCFilter *impl_from_IBaseFilter(IBaseFilter *iface)
-{
-    return CONTAINING_RECORD(iface, HWCFilter, IBaseFilter_iface);
-}
-
-static STDMETHODIMP HWCFilter_QueryInterface(IBaseFilter *iface,
-                                             REFIID riid, void **ppv)
-{
-    if (IsEqualIID(riid, &IID_IUnknown)) {
-        *ppv = (IUnknown *)iface;
-    } else if (IsEqualIID(riid, &IID_IPersist)) {
-        *ppv = (IPersist *)iface;
-    } else if (IsEqualIID(riid, &IID_IMediaFilter)) {
-        *ppv = (IMediaFilter *)iface;
-    } else if (IsEqualIID(riid, &IID_IBaseFilter)) {
-        *ppv = (IBaseFilter *)iface;
-    } else {
-        *ppv = NULL;
-        return E_NOINTERFACE;
-    }
-
-    IBaseFilter_AddRef(iface);
-    return S_OK;
-}
-
-static STDMETHODIMP_(ULONG) HWCFilter_AddRef(IBaseFilter *iface)
-{
-    HWCFilter *This = impl_from_IBaseFilter(iface);
-
-    return InterlockedIncrement(&This->m_cRef);
-}
-
-static STDMETHODIMP_(ULONG) HWCFilter_Release(IBaseFilter *iface)
-{
-    HWCFilter *This = impl_from_IBaseFilter(iface);
-
-    if (InterlockedDecrement(&This->m_cRef) == 0) {
-        if (This->m_pPin) {
-            SAFE_RELEASE(This->m_pPin);
-        }
-        g_free((void *)This);
-        This = NULL;
-        return 0;
-    }
-    return This->m_cRef;
-}
-
-static STDMETHODIMP HWCFilter_GetClassID(IBaseFilter *iface, CLSID *pClsID)
-{
-    if (pClsID == NULL) {
-        return E_POINTER;
-    }
-    return E_NOTIMPL;
-}
-
-static STDMETHODIMP HWCFilter_GetState(IBaseFilter *iface, DWORD dwMSecs,
-                                       FILTER_STATE *State)
-{
-    HWCFilter *This = impl_from_IBaseFilter(iface);
-    *State = This->m_state;
-    return S_OK;
-}
-
-static STDMETHODIMP HWCFilter_SetSyncSource(IBaseFilter *iface,
-                                            IReferenceClock *pClock)
-{
-    return S_OK;
-}
-
-static STDMETHODIMP HWCFilter_GetSyncSource(IBaseFilter *iface,
-                                            IReferenceClock **pClock)
-{
-    *pClock = NULL;
-    return S_OK;
-}
-
-static STDMETHODIMP HWCFilter_Stop(IBaseFilter *iface)
-{
-    HWCFilter *This = impl_from_IBaseFilter(iface);
-
-    IPin_EndFlush(This->m_pPin);
-    This->m_state = State_Stopped;
-    return S_OK;
-}
-
-static STDMETHODIMP HWCFilter_Pause(IBaseFilter *iface)
-{
-    HWCFilter *This = impl_from_IBaseFilter(iface);
-    This->m_state = State_Paused;
-    return S_OK;
-}
-
-static STDMETHODIMP HWCFilter_Run(IBaseFilter *iface, REFERENCE_TIME tStart)
-{
-    HWCFilter *This = impl_from_IBaseFilter(iface);
-
-    if (This->m_state == State_Stopped) {
-        HRESULT hr;
-        hr = IBaseFilter_Pause(iface);
-        if (FAILED(hr)) {
-            ERR("HWCFilter_Run : Failed to IBaseFilter_Pause, ret=0xld%\n", hr);
-            return hr;
-        }
-    }
-
-    This->m_state = State_Running;
-    return S_OK;
-}
-
-static STDMETHODIMP HWCFilter_EnumPins(IBaseFilter *iface, IEnumPins **ppEnum)
-{
-    if (ppEnum == NULL) {
-        return E_POINTER;
-    }
-
-    HWCEnumPins_Construct(iface, 0, ppEnum);
-    return *ppEnum == NULL ? E_OUTOFMEMORY : S_OK;
-}
-
-static STDMETHODIMP HWCFilter_FindPin(IBaseFilter *iface, LPCWSTR Id,
-                                      IPin **ppPin)
-{
-    HWCFilter *This = impl_from_IBaseFilter(iface);
-
-    if (ppPin == NULL) {
-        return E_POINTER;
-    }
-
-    if (memcmp((void *)Id, (void *)HWCPinName, sizeof(HWCPinName))) {
-        return VFW_E_NOT_FOUND;
-    }
-
-    if (!This->m_pPin) {
-        HWCInPin_Construct(iface, &This->m_pPin);
-    }
-    *ppPin = This->m_pPin;
-
-    IPin_AddRef(This->m_pPin);
-    return S_OK;
-}
-
-static STDMETHODIMP HWCFilter_QueryFilterInfo(IBaseFilter *iface,
-                                              FILTER_INFO *pInfo)
-{
-    HWCFilter *This = impl_from_IBaseFilter(iface);
-
-    if (pInfo == NULL) {
-        return E_POINTER;
-    }
-
-    memcpy((void *)pInfo->achName,
-           (void *)HWCFilterName,
-           sizeof(HWCFilterName));
-    pInfo->pGraph = This->m_pFilterGraph;
-    if (This->m_pFilterGraph) {
-        IFilterGraph_AddRef(This->m_pFilterGraph);
-    }
-    return S_OK;
-}
-
-static STDMETHODIMP HWCFilter_JoinFilterGraph(IBaseFilter *iface,
-                                              IFilterGraph *pGraph,
-                                              LPCWSTR pName)
-{
-    HWCFilter *This = impl_from_IBaseFilter(iface);
-
-    This->m_pFilterGraph = pGraph;
-    return S_OK;
-}
-
-static STDMETHODIMP HWCFilter_QueryVendorInfo(IBaseFilter *iface,
-                                              LPWSTR *pVendorInfo)
-{
-    return E_NOTIMPL;
-}
-
-static IBaseFilterVtbl HWCFilter_Vtbl = {
-    HWCFilter_QueryInterface,
-    HWCFilter_AddRef,
-    HWCFilter_Release,
-    HWCFilter_GetClassID,
-    HWCFilter_Stop,
-    HWCFilter_Pause,
-    HWCFilter_Run,
-    HWCFilter_GetState,
-    HWCFilter_SetSyncSource,
-    HWCFilter_GetSyncSource,
-    HWCFilter_EnumPins,
-    HWCFilter_FindPin,
-    HWCFilter_QueryFilterInfo,
-    HWCFilter_JoinFilterGraph,
-    HWCFilter_QueryVendorInfo
-};
-
-static STDMETHODIMP HWCFilter_Construct(IBaseFilter **ppv)
-{
-    HWCFilter *This = (HWCFilter *)g_malloc0(sizeof(HWCFilter));
-
-    if (!This) {
-        ERR("failed to HWCFilter_Construct, E_OUTOFMEMORY\n");
-        return E_OUTOFMEMORY;
-    }
-
-    This->IBaseFilter_iface.lpVtbl = &HWCFilter_Vtbl;
-    This->m_pFilterGraph = NULL;
-    This->m_state = State_Stopped;
-    This->m_cRef = 1;
-    HWCInPin_Construct(&This->IBaseFilter_iface, &This->m_pPin);
-    *ppv = &This->IBaseFilter_iface;
-
-    return S_OK;
-}
-
-/**********************************************************
- *
- * Virtual device implementations
- *
- **********************************************************/
-
-
-/*
- * Declaration global variables for Win32 COM Interfaces
- */
-IGraphBuilder *g_pGB ;
-ICaptureGraphBuilder2 *g_pCGB;
-IMediaControl *g_pMediaControl;
-
-IPin *g_pOutputPin;
-IPin *g_pInputPin;
-IBaseFilter *g_pDstFilter;
-IBaseFilter *g_pSrcFilter;
-
-IGrabCallback *g_pCallback;
-
-/* V4L2 defines copy from videodev2.h */
-#define V4L2_CTRL_FLAG_SLIDER       0x0020
-
-#define V4L2_CTRL_CLASS_USER        0x00980000
-#define V4L2_CID_BASE               (V4L2_CTRL_CLASS_USER | 0x900)
-#define V4L2_CID_BRIGHTNESS         (V4L2_CID_BASE+0)
-#define V4L2_CID_CONTRAST           (V4L2_CID_BASE+1)
-#define V4L2_CID_SATURATION         (V4L2_CID_BASE+2)
-#define V4L2_CID_SHARPNESS          (V4L2_CID_BASE+27)
-
-#define V4L2_PIX_FMT_YUYV    MAKEFOURCC('Y', 'U', 'Y', 'V') /* 16  YUV 4:2:2 */
-#define V4L2_PIX_FMT_YUV420  MAKEFOURCC('Y', 'U', '1', '2') /* 12  YUV 4:2:0 */
-#define V4L2_PIX_FMT_YVU420  MAKEFOURCC('Y', 'V', '1', '2') /* 12  YVU 4:2:0 */
-#define V4L2_PIX_FMT_RGB24   MAKEFOURCC('R', 'G', 'B', '3') /* 24  RGB-8-8-8 */
-
-typedef struct tagMaruCamConvertPixfmt {
-    uint32_t fmt;   /* fourcc */
-    uint32_t bpp;   /* bits per pixel, 0 for compressed formats */
-    uint32_t needs_conversion;
-} MaruCamConvertPixfmt;
-
-static MaruCamConvertPixfmt supported_dst_pixfmts[] = {
-        { V4L2_PIX_FMT_YUYV, 16, 0 },
-        { V4L2_PIX_FMT_YUV420, 12, 0 },
-        { V4L2_PIX_FMT_YVU420, 12, 0 },
-};
-
-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 },
-};
-
-#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 marucam_qctrl {
-    uint32_t id;
-    uint32_t hit;
-    long min;
-    long max;
-    long step;
-    long 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 MaruCamState *g_state;
-
-static uint32_t ready_count;
-static uint32_t cur_fmt_idx;
-static uint32_t cur_frame_idx;
-static void *grab_buf;
-static uint32_t g_dwSrcFmt;
-
-
-/*
- * Helper functions - converting image formats, converting values
- */
-
-static uint32_t get_bytesperline(uint32_t pixfmt, uint32_t width)
-{
-    uint32_t bytesperline;
-
-    switch (pixfmt) {
-    case V4L2_PIX_FMT_YUV420:
-    case V4L2_PIX_FMT_YVU420:
-        bytesperline = (width * 12) >> 3;
-        break;
-    case V4L2_PIX_FMT_YUYV:
-    default:
-        bytesperline = width * 2;
-        break;
-    }
-
-    return bytesperline;
-}
-
-static uint32_t get_sizeimage(uint32_t pixfmt, uint32_t width, uint32_t height)
-{
-    return get_bytesperline(pixfmt, width) * height;
-}
-
-void yuyv_to_yuv420(const unsigned char *src, unsigned char *dest,
-        uint32_t width, uint32_t height, uint32_t yvu);
-void rgb24_to_yuv420(const unsigned char *src, unsigned char *dest,
-        uint32_t width, uint32_t height, uint32_t yvu);
-void rgb24_to_yuyv(unsigned char *src, unsigned char *dest,
-        uint32_t width, uint32_t height);
-void yuv420_to_yvu420(unsigned char *src, unsigned char *dest,
-        uint32_t width, uint32_t height);
-void yuv420_to_yuyv(unsigned char *src, unsigned char *dest,
-        uint32_t width, uint32_t height);
-
-static long value_convert_from_guest(long min, long max, long value)
-{
-    double rate = 0.0;
-    long dist = 0, ret = 0;
-
-    dist = max - min;
-
-    if (dist < MARUCAM_CTRL_VALUE_MAX) {
-        rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;
-        ret = min + (int32_t)(value / rate);
-    } else {
-        rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;
-        ret = min + (int32_t)(rate * value);
-    }
-    return ret;
-}
-
-static long value_convert_to_guest(long min, long max, long value)
-{
-    double rate  = 0.0;
-    long dist = 0, ret = 0;
-
-    dist = max - min;
-
-    if (dist < MARUCAM_CTRL_VALUE_MAX) {
-        rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;
-        ret = (int32_t)((double)(value - min) * rate);
-    } else {
-        rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;
-        ret = (int32_t)((double)(value - min) / rate);
-    }
-
-    return ret;
-}
-
-/*
- * Callback function for grab frames
- */
-static STDMETHODIMP marucam_device_callbackfn(ULONG dwSize, BYTE *pBuffer)
-{
-    void *tmp_buf;
-    uint32_t width, height, fmt, imgsize;
-
-    width = supported_dst_frames[cur_frame_idx].width;
-    height = supported_dst_frames[cur_frame_idx].height;
-    fmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
-    imgsize = get_sizeimage(fmt, width, height);
-
-    if (imgsize > (uint32_t)dwSize) {
-        ERR("Image size is mismatched\n");
-        return E_FAIL;
-    }
-
-    switch (g_dwSrcFmt) {
-    case V4L2_PIX_FMT_YUYV:
-        switch (fmt) {
-        case V4L2_PIX_FMT_YUV420:
-            yuyv_to_yuv420(pBuffer, grab_buf, width, height, 0);
-            break;
-        case V4L2_PIX_FMT_YVU420:
-            yuyv_to_yuv420(pBuffer, grab_buf, width, height, 1);
-            break;
-        case V4L2_PIX_FMT_YUYV:
-            memcpy(grab_buf, (void *)pBuffer, (size_t)dwSize);
-            break;
-        default:
-            ERR("Invalid pixel format\n");
-            return E_FAIL;
-        }
-        break;
-    case V4L2_PIX_FMT_RGB24:
-        switch (fmt) {
-        case V4L2_PIX_FMT_YUV420:
-            rgb24_to_yuv420(pBuffer, grab_buf, width, height, 0);
-            break;
-        case V4L2_PIX_FMT_YVU420:
-            rgb24_to_yuv420(pBuffer, grab_buf, width, height, 1);
-            break;
-        case V4L2_PIX_FMT_YUYV:
-            rgb24_to_yuyv(pBuffer, grab_buf, width, height);
-            break;
-        default:
-            ERR("Invalid pixel format\n");
-            return E_FAIL;
-        }
-        break;
-    case V4L2_PIX_FMT_YUV420:
-        switch (fmt) {
-        case V4L2_PIX_FMT_YUV420:
-            memcpy(grab_buf, (void *)pBuffer, (size_t)dwSize);
-            break;
-        case V4L2_PIX_FMT_YVU420:
-            yuv420_to_yvu420(pBuffer, grab_buf, width, height);
-            break;
-        case V4L2_PIX_FMT_YUYV:
-            yuv420_to_yuyv(pBuffer, grab_buf, width, height);
-            break;
-        default:
-            ERR("Invalid pixel format\n");
-            return E_FAIL;
-        }
-        break;
-    default:
-        ERR("Invalid pixel format\n");
-        return E_FAIL;
-    }
-
-    qemu_mutex_lock(&g_state->thread_mutex);
-    if (g_state->streamon) {
-        if (ready_count < MARUCAM_SKIPFRAMES) {
-            /* skip a frame cause first some frame are distorted */
-            ++ready_count;
-            TRACE("skip %d frame\n", ready_count);
-            qemu_mutex_unlock(&g_state->thread_mutex);
-            return S_OK;
-        }
-        if (g_state->req_frame == 0) {
-            TRACE("there is no request\n");
-            qemu_mutex_unlock(&g_state->thread_mutex);
-            return S_OK;
-        }
-        tmp_buf = g_state->vaddr + g_state->buf_size * (g_state->req_frame - 1);
-        memcpy(tmp_buf, grab_buf, g_state->buf_size);
-        g_state->req_frame = 0; /* clear request */
-        g_state->isr |= 0x01;   /* set a flag of rasing a interrupt */
-        qemu_bh_schedule(g_state->tx_bh);
-    }
-    qemu_mutex_unlock(&g_state->thread_mutex);
-    return S_OK;
-}
-
-/*
- * Internal functions for manipulate interfaces
- */
-
-static STDMETHODIMP_(void) CloseInterfaces(void)
-{
-    if (g_pMediaControl) {
-        g_pMediaControl->lpVtbl->Stop(g_pMediaControl);
-    }
-
-    if (g_pOutputPin) {
-        g_pOutputPin->lpVtbl->Disconnect(g_pOutputPin);
-    }
-
-    SAFE_RELEASE(g_pGB);
-    SAFE_RELEASE(g_pCGB);
-    SAFE_RELEASE(g_pMediaControl);
-    SAFE_RELEASE(g_pOutputPin);
-    SAFE_RELEASE(g_pInputPin);
-    SAFE_RELEASE(g_pDstFilter);
-    SAFE_RELEASE(g_pSrcFilter);
-    SAFE_RELEASE(g_pCallback);
-}
-
-static STDMETHODIMP_(void) DeleteMediaType(AM_MEDIA_TYPE *pmt)
-{
-    if (pmt == NULL) {
-        return;
-    }
-
-    if (pmt->cbFormat != 0) {
-        CoTaskMemFree((PVOID)pmt->pbFormat);
-        pmt->cbFormat = 0;
-        pmt->pbFormat = NULL;
-    }
-    if (pmt->pUnk != NULL) {
-        pmt->pUnk->lpVtbl->Release(pmt->pUnk);
-        pmt->pUnk = NULL;
-    }
-
-    CoTaskMemFree((PVOID)pmt);
-}
-
-static STDMETHODIMP GetPin(IBaseFilter *pFilter,
-                           PIN_DIRECTION PinDir, IPin **ppPin)
-{
-    HRESULT hr;
-    IEnumPins *pEnum = NULL;
-    IPin *pPin = NULL;
-
-    if (ppPin == NULL) {
-        return E_POINTER;
-    }
-
-    hr = pFilter->lpVtbl->EnumPins(pFilter, &pEnum);
-    if (FAILED(hr)) {
-        return hr;
-    }
-
-    while (pEnum->lpVtbl->Next(pEnum, 1, &pPin, 0) == S_OK) {
-        PIN_DIRECTION PinDirThis;
-        hr = pPin->lpVtbl->QueryDirection(pPin, &PinDirThis);
-        if (FAILED(hr)) {
-            SAFE_RELEASE(pPin);
-            SAFE_RELEASE(pEnum);
-            return hr;
-        }
-        if (PinDir == PinDirThis) {
-            *ppPin = pPin;
-            SAFE_RELEASE(pEnum);
-            return S_OK;
-        }
-        SAFE_RELEASE(pPin);
-    }
-
-    SAFE_RELEASE(pEnum);
-    return S_FALSE;
-}
-
-static STDMETHODIMP GraphBuilder_Init(void)
-{
-    HRESULT hr;
-
-    hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC,
-                          &IID_IGraphBuilder, (void **)&g_pGB);
-    if (FAILED(hr)) {
-        ERR("Failed to create instance of GraphBuilder, 0x%x\n", hr);
-        return hr;
-    }
-
-    hr = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC,
-                          &IID_ICaptureGraphBuilder2, (void **)&g_pCGB);
-    if (FAILED(hr)) {
-        ERR("Failed to create instance of CaptureGraphBuilder2, 0x%x\n", hr);
-        return hr;
-    }
-
-    hr = g_pCGB->lpVtbl->SetFiltergraph(g_pCGB, g_pGB);
-    if (FAILED(hr)) {
-        ERR("Failed to SetFiltergraph, 0x%x\n", hr);
-        return hr;
-    }
-
-    hr = g_pGB->lpVtbl->QueryInterface(g_pGB, &IID_IMediaControl,
-                                       (void **)&g_pMediaControl);
-    if (FAILED(hr)) {
-        ERR("Failed to QueryInterface for IMediaControl, 0x%x\n", hr);
-        return hr;
-    }
-
-    hr = HWCGrabCallback_Construct(&g_pCallback);
-    if (g_pCallback == NULL) {
-        hr = E_OUTOFMEMORY;
-    }
-
-    hr = ((HWCGrabCallback *)g_pCallback)->SetCallback(g_pCallback,
-                            (CallbackFn)marucam_device_callbackfn);
-
-    return hr;
-}
-
-static STDMETHODIMP BindSourceFilter(void)
-{
-    HRESULT hr;
-    ICreateDevEnum *pCreateDevEnum = NULL;
-    IEnumMoniker *pEnumMK = NULL;
-    IMoniker *pMoniKer;
-
-    hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
-                          &IID_ICreateDevEnum,
-                          (void **)&pCreateDevEnum);
-    if (FAILED(hr)) {
-        ERR("Failed to create instance of CreateDevEnum, 0x%x\n", hr);
-        return hr;
-    }
-
-    hr = pCreateDevEnum->lpVtbl->CreateClassEnumerator(pCreateDevEnum,
-                                      &CLSID_VideoInputDeviceCategory,
-                                      &pEnumMK, 0);
-    if (FAILED(hr)) {
-        ERR("Failed to get VideoInputDeviceCategory, 0x%x\n", hr);
-        SAFE_RELEASE(pCreateDevEnum);
-        return hr;
-    }
-
-    if (!pEnumMK) {
-        ERR("ClassEnumerator moniker is NULL\n");
-        SAFE_RELEASE(pCreateDevEnum);
-        return E_FAIL;
-    }
-    pEnumMK->lpVtbl->Reset(pEnumMK);
-
-    hr = pEnumMK->lpVtbl->Next(pEnumMK, 1, &pMoniKer, NULL);
-    if (hr == S_FALSE) {
-        hr = E_FAIL;
-    }
-    if (SUCCEEDED(hr)) {
-        IPropertyBag *pBag = NULL;
-        hr = pMoniKer->lpVtbl->BindToStorage(pMoniKer, 0, 0,
-                                             &IID_IPropertyBag,
-                                             (void **)&pBag);
-        if (SUCCEEDED(hr)) {
-            VARIANT var;
-            var.vt = VT_BSTR;
-            hr = pBag->lpVtbl->Read(pBag, L"FriendlyName", &var, NULL);
-            if (hr == NOERROR) {
-                hr = pMoniKer->lpVtbl->BindToObject(pMoniKer, NULL, NULL,
-                                                    &IID_IBaseFilter,
-                                                    (void **)&g_pSrcFilter);
-                if (FAILED(hr)) {
-                    ERR("Counldn't bind moniker to filter object!!\n");
-                } else {
-                    g_pSrcFilter->lpVtbl->AddRef(g_pSrcFilter);
-                }
-                SysFreeString(var.bstrVal);
-            }
-            SAFE_RELEASE(pBag);
-        }
-        SAFE_RELEASE(pMoniKer);
-    }
-
-    if (SUCCEEDED(hr)) {
-        hr = g_pGB->lpVtbl->AddFilter(g_pGB, g_pSrcFilter, L"Video Capture");
-        if (hr != S_OK && hr != S_FALSE) {
-            ERR("Counldn't add Video Capture filter to our graph!\n");
-            SAFE_RELEASE(g_pSrcFilter);
-        }
-    }
-    SAFE_RELEASE(pEnumMK);
-    SAFE_RELEASE(pCreateDevEnum);
-
-    return hr;
-}
-
-static STDMETHODIMP BindTargetFilter(void)
-{
-    HRESULT hr;
-    hr = HWCFilter_Construct(&g_pDstFilter);
-
-    if (SUCCEEDED(hr) && g_pDstFilter) {
-        hr = g_pGB->lpVtbl->AddFilter(g_pGB, g_pDstFilter, L"HWCFilter");
-        if (FAILED(hr)) {
-            ERR("Counldn't add HWCFilterr to our graph!\n");
-            SAFE_RELEASE(g_pDstFilter);
-        }
-    }
-    return hr;
-}
-
-static STDMETHODIMP ConnectFilters(void)
-{
-    HRESULT hr;
-
-    hr = GetPin(g_pSrcFilter, PINDIR_OUTPUT , &g_pOutputPin);
-    if (FAILED(hr)) {
-        ERR("Failed to get output pin. 0x%x\n", hr);
-        return hr;
-    }
-
-    hr = GetPin(g_pDstFilter, PINDIR_INPUT , &g_pInputPin);
-    if (FAILED(hr)) {
-        ERR("Failed to get input pin. 0x%x\n", hr);
-        return hr;
-    }
-
-    hr = g_pGB->lpVtbl->Connect(g_pGB, g_pOutputPin, g_pInputPin);
-    if (FAILED(hr)) {
-        ERR("Failed to connect pins. 0x%x\n", hr);
-    }
-    return hr;
-}
-
-static STDMETHODIMP DisconnectPins(void)
-{
-    HRESULT hr;
-
-    hr = g_pGB->lpVtbl->Disconnect(g_pGB, g_pOutputPin);
-    if (FAILED(hr)) {
-        ERR("Failed to disconnect output pin. 0x%x\n", hr);
-        return hr;
-    }
-
-    hr = g_pGB->lpVtbl->Disconnect(g_pGB, g_pInputPin);
-    if (FAILED(hr)) {
-        ERR("Failed to disconnect input pin. 0x%x\n", hr);
-    }
-
-    return hr;
-}
-
-static STDMETHODIMP RemoveFilters(void)
-{
-    HRESULT hr;
-
-    hr = g_pGB->lpVtbl->RemoveFilter(g_pGB, g_pSrcFilter);
-    if (FAILED(hr)) {
-        ERR("Failed to remove source filer. 0x%x\n", hr);
-        return hr;
-    }
-
-    hr = g_pGB->lpVtbl->RemoveFilter(g_pGB, g_pDstFilter);
-    if (FAILED(hr)) {
-        ERR("Failed to remove destination filer. 0x%x\n", hr);
-    }
-
-    return hr;
-}
-
-/* default fps is 15 */
-#define MARUCAM_DEFAULT_FRAMEINTERVAL    666666
-
-static STDMETHODIMP SetFormat(uint32_t dwWidth, uint32_t dwHeight,
-                              uint32_t dwDstFmt, uint32_t *dwSrcFmt)
-{
-    HRESULT hr;
-    IAMStreamConfig *pSConfig;
-    int iCount = 0, iSize = 0;
-    DWORD dwYUY2 = MAKEFOURCC('Y', 'U', 'Y', '2');
-    DWORD dwI420 = MAKEFOURCC('I', '4', '2', '0');
-
-    if (dwSrcFmt == NULL) {
-        ERR("invalid the source format pointer\n");
-        return E_FAIL;
-    }
-
-    hr = g_pCGB->lpVtbl->FindInterface(g_pCGB, &PIN_CATEGORY_CAPTURE, 0,
-                                       g_pSrcFilter, &IID_IAMStreamConfig,
-                                       (void **)&pSConfig);
-    if (FAILED(hr)) {
-        ERR("failed to FindInterface method\n");
-        return hr;
-    }
-
-    hr = pSConfig->lpVtbl->GetNumberOfCapabilities(pSConfig, &iCount, &iSize);
-    if (FAILED(hr)) {
-        ERR("failed to GetNumberOfCapabilities method\n");
-        SAFE_RELEASE(pSConfig);
-        return hr;
-    }
-
-    if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) {
-        int iFormat = 0;
-        for (iFormat = 0; iFormat < iCount; iFormat++) {
-            VIDEO_STREAM_CONFIG_CAPS scc;
-            AM_MEDIA_TYPE *pmtConfig;
-
-            hr = pSConfig->lpVtbl->GetStreamCaps(pSConfig, iFormat,
-                                                 &pmtConfig, (BYTE *)&scc);
-            if (hr == S_OK) {
-                if (IsEqualIID(&pmtConfig->formattype, &FORMAT_VideoInfo)) {
-                    VIDEOINFOHEADER *pvi =
-                                         (VIDEOINFOHEADER *)pmtConfig->pbFormat;
-                    if ((pvi->bmiHeader.biWidth == (LONG)dwWidth) &&
-                        (pvi->bmiHeader.biHeight == (LONG)dwHeight)) {
-                        if (pvi->bmiHeader.biCompression == dwYUY2) {
-                            *dwSrcFmt = V4L2_PIX_FMT_YUYV;
-                        } else if ((pvi->bmiHeader.biCompression == BI_RGB) &&
-                                (pvi->bmiHeader.biBitCount == 24)) {
-                            *dwSrcFmt = V4L2_PIX_FMT_RGB24;
-                        } else if (pvi->bmiHeader.biCompression == dwI420) {
-                            *dwSrcFmt = V4L2_PIX_FMT_YUV420;
-                        } else { /* not support format */
-                            DeleteMediaType(pmtConfig);
-                            continue;
-                        }
-                        /* use minimum FPS(maximum frameinterval)
-                           with non-VT system  */
-#ifdef CONFIG_HAX
-                        if (!hax_enabled()) {
-                            pvi->AvgTimePerFrame =
-                                    (REFERENCE_TIME)scc.MaxFrameInterval;
-                        } else {
-                            pvi->AvgTimePerFrame =
-                                (REFERENCE_TIME)MARUCAM_DEFAULT_FRAMEINTERVAL;
-                        }
-#else
-                        pvi->AvgTimePerFrame =
-                                (REFERENCE_TIME)scc.MaxFrameInterval;
-#endif
-                        hr = pSConfig->lpVtbl->SetFormat(pSConfig, pmtConfig);
-                        DeleteMediaType(pmtConfig);
-                        break;
-                    }
-                }
-                DeleteMediaType(pmtConfig);
-            }
-        }
-        if (iFormat >= iCount) {
-            ERR("Failed to Set format. "
-                "Maybe connected webcam does not support the (%ldx%ld) "
-                "resolution or image formats(YUY2, RGB24, I420).\n",
-                dwWidth, dwHeight);
-            hr = E_FAIL;
-        }
-    }
-    SAFE_RELEASE(pSConfig);
-    return hr;
-}
-
-static STDMETHODIMP QueryVideoProcAmp(long nProperty, long *pMin, long *pMax,
-                                      long *pStep, long *pDefault)
-{
-    HRESULT hr;
-    long Flags;
-    IAMVideoProcAmp *pProcAmp = NULL;
-
-    hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter,
-                                              &IID_IAMVideoProcAmp,
-                                              (void **)&pProcAmp);
-    if (FAILED(hr)) {
-        return hr;
-    }
-
-    hr = pProcAmp->lpVtbl->GetRange(pProcAmp, nProperty, pMin, pMax,
-                                    pStep, pDefault, &Flags);
-
-    SAFE_RELEASE(pProcAmp);
-    return hr;
-}
-
-static STDMETHODIMP GetVideoProcAmp(long nProperty, long *pValue)
-{
-    HRESULT hr;
-    long Flags;
-    IAMVideoProcAmp *pProcAmp = NULL;
-
-    hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter,
-                                              &IID_IAMVideoProcAmp,
-                                              (void **)&pProcAmp);
-    if (FAILED(hr)) {
-        return hr;
-    }
-
-    hr = pProcAmp->lpVtbl->Get(pProcAmp, nProperty, pValue, &Flags);
-    if (FAILED(hr)) {
-        ERR("Failed to get property for video\n");
-    }
-
-    SAFE_RELEASE(pProcAmp);
-    return hr;
-}
-
-static STDMETHODIMP SetVideoProcAmp(long nProperty, long value)
-{
-    HRESULT hr;
-
-    IAMVideoProcAmp *pProcAmp = NULL;
-    hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter,
-                                              &IID_IAMVideoProcAmp,
-                                              (void **)&pProcAmp);
-    if (FAILED(hr)) {
-        return hr;
-    }
-
-    hr = pProcAmp->lpVtbl->Set(pProcAmp, nProperty, value,
-                               VideoProcAmp_Flags_Manual);
-    if (FAILED(hr)) {
-        ERR("Failed to set property for video\n");
-    }
-    SAFE_RELEASE(pProcAmp);
-    return hr;
-}
-
-static char *__wchar_to_char(const WCHAR *pwstr)
-{
-    char *pstr = NULL;
-    int len = 0;
-
-    len = wcslen(pwstr) + 1;
-    pstr = (char *)g_malloc0(sizeof(char) * len);
-    wcstombs(pstr, pwstr, len + 1);
-
-    return pstr;
-}
-
-int marucam_device_check(int log_flag)
-{
-    struct timeval t1, t2;
-    int ret = 0;
-    char *device_name = NULL;
-    HRESULT hr = E_FAIL;
-    ICreateDevEnum *pCreateDevEnum = NULL;
-    IGraphBuilder *pGB = NULL;
-    ICaptureGraphBuilder2 *pCGB = NULL;
-    IBaseFilter *pSrcFilter = NULL;
-    IEnumMoniker *pEnumMK = NULL;
-    IMoniker *pMoniKer = NULL;
-    IAMStreamConfig *pSConfig = NULL;
-    int iCount = 0, iSize = 0;
-
-    gettimeofday(&t1, NULL);
-    hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
-    if (FAILED(hr)) {
-        ERR("Failed to CoInitailizeEx\n");
-        gettimeofday(&t2, NULL);
-        ERR("Elapsed time : %lu.%06lu\n",
-                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-        return ret;
-    }
-
-    hr = CoCreateInstance(&CLSID_FilterGraph, NULL,
-                          CLSCTX_INPROC,
-                          &IID_IGraphBuilder,
-                          (void **)&pGB);
-    if (FAILED(hr)) {
-        ERR("Failed to create GraphBuilder, 0x%x\n", hr);
-        CoUninitialize();
-        gettimeofday(&t2, NULL);
-        ERR("Elapsed time : %lu.%06lu\n",
-                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-        return ret;
-    }
-
-    hr = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL,
-                          CLSCTX_INPROC,
-                          &IID_ICaptureGraphBuilder2,
-                          (void **)&pCGB);
-    if (FAILED(hr)) {
-        ERR("Failed to create CaptureGraphBuilder2, 0x%x\n", hr);
-        SAFE_RELEASE(pGB);
-        CoUninitialize();
-        gettimeofday(&t2, NULL);
-        ERR("Elapsed time : %lu.%06lu\n",
-                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-        return ret;
-    }
-
-    hr = pCGB->lpVtbl->SetFiltergraph(pCGB, pGB);
-    if (FAILED(hr)) {
-        ERR("Failed to SetFiltergraph, 0x%x\n", hr);
-        SAFE_RELEASE(pCGB);
-        SAFE_RELEASE(pGB);
-        CoUninitialize();
-        gettimeofday(&t2, NULL);
-        ERR("Elapsed time : %lu.%06lu\n",
-                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-        return ret;
-    }
-
-    hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL,
-                          CLSCTX_INPROC,
-                          &IID_ICreateDevEnum,
-                          (void **)&pCreateDevEnum);
-    if (FAILED(hr)) {
-        ERR("Failed to create instance of CLSID_SystemDeviceEnum\n");
-        SAFE_RELEASE(pCGB);
-        SAFE_RELEASE(pGB);
-        CoUninitialize();
-        gettimeofday(&t2, NULL);
-        ERR("Elapsed time : %lu.%06lu\n",
-                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-        return ret;
-    }
-
-    hr = pCreateDevEnum->lpVtbl->CreateClassEnumerator(pCreateDevEnum,
-                                  &CLSID_VideoInputDeviceCategory, &pEnumMK, 0);
-    if (FAILED(hr)) {
-        ERR("Failed to create class enumerator\n");
-        SAFE_RELEASE(pCreateDevEnum);
-        SAFE_RELEASE(pCGB);
-        SAFE_RELEASE(pGB);
-        CoUninitialize();
-        gettimeofday(&t2, NULL);
-        ERR("Elapsed time : %lu.%06lu\n",
-                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-        return ret;
-    }
-
-    if (!pEnumMK) {
-        ERR("Class enumerator is NULL!!\n");
-        SAFE_RELEASE(pCreateDevEnum);
-        SAFE_RELEASE(pCGB);
-        SAFE_RELEASE(pGB);
-        CoUninitialize();
-        gettimeofday(&t2, NULL);
-        ERR("Elapsed time : %lu.%06lu\n",
-                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-        return ret;
-    }
-    pEnumMK->lpVtbl->Reset(pEnumMK);
-
-    hr = pEnumMK->lpVtbl->Next(pEnumMK, 1, &pMoniKer, NULL);
-    if (FAILED(hr) || (hr == S_FALSE)) {
-        ERR("Enum moniker returns a invalid value.\n");
-        SAFE_RELEASE(pEnumMK);
-        SAFE_RELEASE(pCreateDevEnum);
-        SAFE_RELEASE(pCGB);
-        SAFE_RELEASE(pGB);
-        CoUninitialize();
-        gettimeofday(&t2, NULL);
-        ERR("Elapsed time : %lu.%06lu\n",
-                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-        return ret;
-    }
-
-    IPropertyBag *pBag = NULL;
-    hr = pMoniKer->lpVtbl->BindToStorage(pMoniKer, 0, 0,
-                                         &IID_IPropertyBag,
-                                         (void **)&pBag);
-    if (FAILED(hr)) {
-        ERR("Failed to bind to storage.\n");
-        SAFE_RELEASE(pEnumMK);
-        SAFE_RELEASE(pCreateDevEnum);
-        SAFE_RELEASE(pCGB);
-        SAFE_RELEASE(pGB);
-        CoUninitialize();
-        gettimeofday(&t2, NULL);
-        ERR("Elapsed time : %lu.%06lu\n",
-                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-        return ret;
-    } else {
-        VARIANT var;
-        var.vt = VT_BSTR;
-        hr = pBag->lpVtbl->Read(pBag, L"FriendlyName", &var, NULL);
-        if (hr == S_OK) {
-            ret = 1;
-            if (!log_flag) {
-                SysFreeString(var.bstrVal);
-                SAFE_RELEASE(pBag);
-                SAFE_RELEASE(pMoniKer);
-                SAFE_RELEASE(pEnumMK);
-                SAFE_RELEASE(pCreateDevEnum);
-                SAFE_RELEASE(pCGB);
-                SAFE_RELEASE(pGB);
-                CoUninitialize();
-                gettimeofday(&t2, NULL);
-                ERR("Elapsed time : %lu.%06lu\n",
-                                t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-                return ret;
-            }
-            device_name = __wchar_to_char(var.bstrVal);
-            INFO("Device name : %s\n", device_name);
-            g_free(device_name);
-            hr = pMoniKer->lpVtbl->BindToObject(pMoniKer, NULL, NULL,
-                                                &IID_IBaseFilter,
-                                                (void **)&pSrcFilter);
-            if (FAILED(hr)) {
-                ERR("Counldn't bind moniker to filter object!!\n");
-                SysFreeString(var.bstrVal);
-                SAFE_RELEASE(pBag);
-                SAFE_RELEASE(pMoniKer);
-                SAFE_RELEASE(pEnumMK);
-                SAFE_RELEASE(pCreateDevEnum);
-                SAFE_RELEASE(pCGB);
-                SAFE_RELEASE(pGB);
-                CoUninitialize();
-                gettimeofday(&t2, NULL);
-                ERR("Elapsed time : %lu.%06lu\n",
-                                t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-                return ret;
-            } else {
-                pSrcFilter->lpVtbl->AddRef(pSrcFilter);
-            }
-            SysFreeString(var.bstrVal);
-        }
-        SAFE_RELEASE(pBag);
-    }
-    SAFE_RELEASE(pMoniKer);
-
-    hr = pGB->lpVtbl->AddFilter(pGB, pSrcFilter, L"Video Capture");
-    if (hr != S_OK && hr != S_FALSE) {
-        ERR("Counldn't add Video Capture filter to our graph!\n");
-        SAFE_RELEASE(pSrcFilter);
-        SAFE_RELEASE(pEnumMK);
-        SAFE_RELEASE(pCreateDevEnum);
-        SAFE_RELEASE(pCGB);
-        SAFE_RELEASE(pGB);
-        CoUninitialize();
-        gettimeofday(&t2, NULL);
-        ERR("Elapsed time : %lu.%06lu\n",
-                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-        return ret;
-    }
-
-    hr = pCGB->lpVtbl->FindInterface(pCGB, &PIN_CATEGORY_CAPTURE, 0,
-                                       pSrcFilter, &IID_IAMStreamConfig,
-                                       (void **)&pSConfig);
-    if (FAILED(hr)) {
-        ERR("Failed to FindInterface method\n");
-        SAFE_RELEASE(pSrcFilter);
-        SAFE_RELEASE(pEnumMK);
-        SAFE_RELEASE(pCreateDevEnum);
-        SAFE_RELEASE(pCGB);
-        SAFE_RELEASE(pGB);
-        CoUninitialize();
-        gettimeofday(&t2, NULL);
-        ERR("Elapsed time : %lu.%06lu\n",
-                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-        return ret;
-    }
-
-    hr = pSConfig->lpVtbl->GetNumberOfCapabilities(pSConfig, &iCount, &iSize);
-    if (FAILED(hr)) {
-        ERR("Failed to GetNumberOfCapabilities method\n");
-        SAFE_RELEASE(pSConfig);
-        SAFE_RELEASE(pSrcFilter);
-        SAFE_RELEASE(pEnumMK);
-        SAFE_RELEASE(pCreateDevEnum);
-        SAFE_RELEASE(pCGB);
-        SAFE_RELEASE(pGB);
-        CoUninitialize();
-        gettimeofday(&t2, NULL);
-        ERR("Elapsed time : %lu.%06lu\n",
-                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-        return ret;
-    }
-
-    if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) {
-        int iFormat = 0;
-        for (iFormat = 0; iFormat < iCount; iFormat++) {
-            VIDEO_STREAM_CONFIG_CAPS scc;
-            AM_MEDIA_TYPE *pmtConfig;
-
-            hr = pSConfig->lpVtbl->GetStreamCaps(pSConfig, iFormat, &pmtConfig,
-                                                 (BYTE *)&scc);
-            if (hr == S_OK) {
-                if (IsEqualIID(&pmtConfig->formattype, &FORMAT_VideoInfo)) {
-                    VIDEOINFOHEADER *pvi =
-                                         (VIDEOINFOHEADER *)pmtConfig->pbFormat;
-                    if (pvi->bmiHeader.biCompression == BI_RGB) {
-                        INFO("RGB BitCount: %d, Frame size: %ux%u\n",
-                                pvi->bmiHeader.biBitCount,
-                                pvi->bmiHeader.biWidth,
-                                pvi->bmiHeader.biHeight);
-                    } else {
-                        INFO("PixelFormat: %c%c%c%c, Frame size: %ux%u\n",
-                            (char)(pvi->bmiHeader.biCompression),
-                            (char)(pvi->bmiHeader.biCompression >> 8),
-                            (char)(pvi->bmiHeader.biCompression >> 16),
-                            (char)(pvi->bmiHeader.biCompression >> 24),
-                            pvi->bmiHeader.biWidth,
-                            pvi->bmiHeader.biHeight);
-                    }
-                }
-                DeleteMediaType(pmtConfig);
-            }
-        }
-    }
-
-    hr = pGB->lpVtbl->RemoveFilter(pGB, pSrcFilter);
-    if (FAILED(hr)) {
-        ERR("Failed to remove source filer. 0x%x\n", hr);
-    }
-
-    SAFE_RELEASE(pSConfig);
-    SAFE_RELEASE(pSrcFilter);
-    SAFE_RELEASE(pCGB);
-    SAFE_RELEASE(pGB);
-    SAFE_RELEASE(pEnumMK);
-    SAFE_RELEASE(pCreateDevEnum);
-    CoUninitialize();
-    gettimeofday(&t2, NULL);
-    ERR("Elapsed time : %lu.%06lu\n",
-                    t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-
-    return ret;
-}
-
-/* MARUCAM_CMD_INIT */
-void marucam_device_init(MaruCamState *state)
-{
-    g_state = state;
-}
-
-void marucam_device_exit(MaruCamState *state)
-{
-}
-
-/* MARUCAM_CMD_OPEN */
-void marucam_device_open(MaruCamState *state)
-{
-    HRESULT hr;
-    uint32_t dwHeight, dwWidth, dwDstFmt;
-    MaruCamParam *param = state->param;
-    param->top = 0;
-
-    hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
-    if (FAILED(hr)) {
-        ERR("CoInitailizeEx\n");
-        ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);
-        param->errCode = EINVAL;
-        return;
-    }
-
-    hr = GraphBuilder_Init();
-    if (FAILED(hr)) {
-        ERR("GraphBuilder_Init\n");
-        DisconnectPins();
-        RemoveFilters();
-        CloseInterfaces();
-        CoUninitialize();
-        param->errCode = EINVAL;
-        ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);
-        return;
-    }
-
-    hr = BindSourceFilter();
-    if (FAILED(hr)) {
-        ERR("BindSourceFilter\n");
-        DisconnectPins();
-        RemoveFilters();
-        CloseInterfaces();
-        CoUninitialize();
-        param->errCode = EINVAL;
-        ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);
-        return;
-    }
-
-    hr = BindTargetFilter();
-    if (FAILED(hr)) {
-        ERR("BindTargetFilter\n");
-        DisconnectPins();
-        RemoveFilters();
-        CloseInterfaces();
-        CoUninitialize();
-        param->errCode = EINVAL;
-        ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);
-        return;
-    }
-
-    hr = ConnectFilters();
-    if (FAILED(hr)) {
-        ERR("ConnectFilters\n");
-        DisconnectPins();
-        RemoveFilters();
-        CloseInterfaces();
-        CoUninitialize();
-        param->errCode = EINVAL;
-        ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);
-        return;
-    }
-
-    cur_frame_idx = 0;
-    cur_fmt_idx = 0;
-
-    dwHeight = supported_dst_frames[cur_frame_idx].height;
-    dwWidth = supported_dst_frames[cur_frame_idx].width;
-    dwDstFmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
-    hr = SetFormat(dwWidth, dwHeight, dwDstFmt, &g_dwSrcFmt);
-    if (hr != S_OK) {
-        ERR("failed to Set default values\n");
-        DisconnectPins();
-        RemoveFilters();
-        CloseInterfaces();
-        CoUninitialize();
-        param->errCode = EINVAL;
-        ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);
-        return;
-    }
-
-    INFO("Opened\n");
-    return;
-}
-
-/* MARUCAM_CMD_CLOSE */
-void marucam_device_close(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
-    int ret = 0;
-    param->top = 0;
-
-    qemu_mutex_lock(&state->thread_mutex);
-    ret = state->streamon;
-    qemu_mutex_unlock(&state->thread_mutex);
-    if (ret) {
-        marucam_device_stop_preview(state);
-    }
-
-    if (g_pGB) {
-        DisconnectPins();
-        RemoveFilters();
-    }
-    CloseInterfaces();
-    CoUninitialize();
-    INFO("Closed\n");
-}
-
-/* MARUCAM_CMD_START_PREVIEW */
-void marucam_device_start_preview(MaruCamState *state)
-{
-    HRESULT hr;
-    uint32_t pixfmt, width, height;
-    MaruCamParam *param = state->param;
-    param->top = 0;
-
-    ready_count = 0;
-    width = supported_dst_frames[cur_frame_idx].width;
-    height = supported_dst_frames[cur_frame_idx].height;
-    pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
-    state->buf_size = get_sizeimage(pixfmt, width, height);
-
-    INFO("Pixfmt(%c%c%c%c), W:H(%d:%d), buf size(%u)\n",
-         (char)(pixfmt), (char)(pixfmt >> 8),
-         (char)(pixfmt >> 16), (char)(pixfmt >> 24),
-         width, height, state->buf_size);
-    INFO("Starting preview\n");
-
-    assert(g_pCallback != NULL);
-    hr = ((HWCInPin *)g_pInputPin)->SetGrabCallbackIF(g_pInputPin,
-                                                       g_pCallback);
-    if (FAILED(hr)) {
-        ERR("Failed to set IGrabCallback interface.\n");
-        param->errCode = EINVAL;
-        return;
-    }
-
-    if (grab_buf) {
-        g_free(grab_buf);
-        grab_buf = NULL;
-    }
-    grab_buf = (void *)g_malloc0(state->buf_size);
-    if (grab_buf == NULL) {
-        param->errCode = ENOMEM;
-        return;
-    }
-
-    hr = g_pMediaControl->lpVtbl->Run(g_pMediaControl);
-    if (FAILED(hr)) {
-        ERR("Failed to run media control. hr=0x%x\n", hr);
-        param->errCode = EINVAL;
-        return;
-    }
-
-    qemu_mutex_lock(&state->thread_mutex);
-    state->streamon = 1;
-    qemu_mutex_unlock(&state->thread_mutex);
-
-    INFO("Streaming on ......\n");
-}
-
-/* MARUCAM_CMD_STOP_PREVIEW */
-void marucam_device_stop_preview(MaruCamState *state)
-{
-    HRESULT hr;
-    MaruCamParam *param = state->param;
-    param->top = 0;
-
-    INFO("...... Streaming off\n");
-    qemu_mutex_lock(&state->thread_mutex);
-    state->streamon = 0;
-    qemu_mutex_unlock(&state->thread_mutex);
-
-    hr = ((HWCInPin *)g_pInputPin)->SetGrabCallbackIF(g_pInputPin, NULL);
-    if (FAILED(hr)) {
-        ERR("Failed to set IGrabCallback interface.\n");
-        param->errCode = EINVAL;
-        return;
-    }
-
-    hr = g_pMediaControl->lpVtbl->Stop(g_pMediaControl);
-    if (FAILED(hr)) {
-        ERR("Failed to stop media control.\n");
-        param->errCode = EINVAL;
-        return;
-    }
-
-    if (grab_buf) {
-        g_free(grab_buf);
-        grab_buf = NULL;
-    }
-    state->buf_size = 0;
-
-    INFO("Stopping preview\n");
-}
-
-/* MARUCAM_CMD_S_PARAM */
-void marucam_device_s_param(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
-
-    /* We use default FPS of the webcam */
-    param->top = 0;
-}
-
-/* MARUCAM_CMD_G_PARAM */
-void marucam_device_g_param(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
-
-    /* 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 */
-}
-
-/* MARUCAM_CMD_S_FMT */
-void marucam_device_s_fmt(MaruCamState *state)
-{
-    uint32_t width, height, pixfmt, pidx, fidx;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    width = param->stack[0];
-    height = param->stack[1];
-    pixfmt = param->stack[2];
-
-    for (fidx = 0; fidx < ARRAY_SIZE(supported_dst_frames); fidx++) {
-        if ((supported_dst_frames[fidx].width == width) &&
-                (supported_dst_frames[fidx].height == height)) {
-            break;
-        }
-    }
-    if (fidx == ARRAY_SIZE(supported_dst_frames)) {
-        param->errCode = EINVAL;
-        return;
-    }
-    for (pidx = 0; pidx < ARRAY_SIZE(supported_dst_pixfmts); pidx++) {
-        if (supported_dst_pixfmts[pidx].fmt == pixfmt) {
-            break;
-        }
-    }
-    if (pidx == ARRAY_SIZE(supported_dst_pixfmts)) {
-        param->errCode = EINVAL;
-        return;
-    }
-
-    if ((supported_dst_frames[cur_frame_idx].width != width) &&
-            (supported_dst_frames[cur_frame_idx].height != height)) {
-        HRESULT hr = SetFormat(width, height, pixfmt, &g_dwSrcFmt);
-        if (FAILED(hr)) {
-            param->errCode = EINVAL;
-            return;
-        }
-    }
-
-    cur_frame_idx = fidx;
-    cur_fmt_idx = pidx;
-
-    pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
-    width = supported_dst_frames[cur_frame_idx].width;
-    height = supported_dst_frames[cur_frame_idx].height;
-
-    param->stack[0] = width;
-    param->stack[1] = height;
-    param->stack[2] = 1; /* V4L2_FIELD_NONE */
-    param->stack[3] = pixfmt;
-    param->stack[4] = get_bytesperline(pixfmt, width);
-    param->stack[5] = get_sizeimage(pixfmt, width, height);
-    param->stack[6] = 0;
-    param->stack[7] = 0;
-
-    TRACE("Set format...\n");
-}
-
-/* MARUCAM_CMD_G_FMT */
-void marucam_device_g_fmt(MaruCamState *state)
-{
-    uint32_t width, height, pixfmt;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;
-    width = supported_dst_frames[cur_frame_idx].width;
-    height = supported_dst_frames[cur_frame_idx].height;
-
-    param->stack[0] = width;
-    param->stack[1] = height;
-    param->stack[2] = 1; /* V4L2_FIELD_NONE */
-    param->stack[3] = pixfmt;
-    param->stack[4] = get_bytesperline(pixfmt, width);
-    param->stack[5] = get_sizeimage(pixfmt, width, height);
-    param->stack[6] = 0;
-    param->stack[7] = 0;
-
-    TRACE("Get format...\n");
-}
-
-void marucam_device_try_fmt(MaruCamState *state)
-{
-    uint32_t width, height, pixfmt, i;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    width = param->stack[0];
-    height = param->stack[1];
-    pixfmt = param->stack[2];
-
-    for (i = 0; i < ARRAY_SIZE(supported_dst_frames); i++) {
-        if ((supported_dst_frames[i].width == width) &&
-                (supported_dst_frames[i].height == height)) {
-            break;
-        }
-    }
-    if (i == ARRAY_SIZE(supported_dst_frames)) {
-        param->errCode = EINVAL;
-        return;
-    }
-    for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
-        if (supported_dst_pixfmts[i].fmt == pixfmt) {
-            break;
-        }
-    }
-    if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
-        param->errCode = EINVAL;
-        return;
-    }
-
-    param->stack[0] = width;
-    param->stack[1] = height;
-    param->stack[2] = 1; /* V4L2_FIELD_NONE */
-    param->stack[3] = pixfmt;
-    param->stack[4] = get_bytesperline(pixfmt, width);
-    param->stack[5] = get_sizeimage(pixfmt, width, height);
-    param->stack[6] = 0;
-    param->stack[7] = 0;
-}
-
-void marucam_device_enum_fmt(MaruCamState *state)
-{
-    uint32_t index;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    index = param->stack[0];
-
-    if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {
-        param->errCode = EINVAL;
-        return;
-    }
-    param->stack[1] = 0; /* flags = NONE */
-    param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */
-    /* set description */
-    switch (supported_dst_pixfmts[index].fmt) {
-    case V4L2_PIX_FMT_YUYV:
-        memcpy(&param->stack[3], "YUYV", 32);
-        break;
-    case V4L2_PIX_FMT_YUV420:
-        memcpy(&param->stack[3], "YU12", 32);
-        break;
-    case V4L2_PIX_FMT_YVU420:
-        memcpy(&param->stack[3], "YV12", 32);
-        break;
-    default:
-        ERR("Invalid pixel format\n");
-        param->errCode = EINVAL;
-        break;
-    }
-}
-
-void marucam_device_qctrl(MaruCamState *state)
-{
-    HRESULT hr;
-    uint32_t id, i;
-    long property, min, max, step, def_val, set_val;
-    char name[32] = {0,};
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    id = param->stack[0];
-
-    switch (id) {
-    case V4L2_CID_BRIGHTNESS:
-        TRACE("V4L2_CID_BRIGHTNESS\n");
-        property = VideoProcAmp_Brightness;
-        memcpy((void *)name, (void *)"brightness", 32);
-        i = 0;
-        break;
-    case V4L2_CID_CONTRAST:
-        TRACE("V4L2_CID_CONTRAST\n");
-        property = VideoProcAmp_Contrast;
-        memcpy((void *)name, (void *)"contrast", 32);
-        i = 1;
-        break;
-    case V4L2_CID_SATURATION:
-        TRACE("V4L2_CID_SATURATION\n");
-        property = VideoProcAmp_Saturation;
-        memcpy((void *)name, (void *)"saturation", 32);
-        i = 2;
-        break;
-    case V4L2_CID_SHARPNESS:
-        TRACE("V4L2_CID_SHARPNESS\n");
-        property = VideoProcAmp_Sharpness;
-        memcpy((void *)name, (void *)"sharpness", 32);
-        i = 3;
-        break;
-    default:
-        ERR("Invalid control ID\n");
-        param->errCode = EINVAL;
-        return;
-    }
-    hr = QueryVideoProcAmp(property, &min, &max, &step, &def_val);
-    if (FAILED(hr)) {
-        param->errCode = EINVAL;
-        ERR("failed to query video controls [HRESULT : 0x%x]\n", hr);
-        return;
-    } else {
-        qctrl_tbl[i].hit = 1;
-        qctrl_tbl[i].min = min;
-        qctrl_tbl[i].max = max;
-        qctrl_tbl[i].step = step;
-        qctrl_tbl[i].init_val = def_val;
-
-        if ((qctrl_tbl[i].min + qctrl_tbl[i].max) == 0) {
-            set_val = 0;
-        } else {
-            set_val = (qctrl_tbl[i].min + qctrl_tbl[i].max) / 2;
-        }
-        hr = SetVideoProcAmp(property, set_val);
-        if (FAILED(hr)) {
-            param->errCode = EINVAL;
-            ERR("failed to set video control value, [HRESULT : 0x%x]\n", hr);
-            return;
-        }
-    }
-
-    param->stack[0] = 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] = V4L2_CTRL_FLAG_SLIDER;
-    /* name field setting */
-    memcpy(&param->stack[6], (void *)name, sizeof(name)/sizeof(name[0]));
-}
-
-void marucam_device_s_ctrl(MaruCamState *state)
-{
-    HRESULT hr;
-    uint32_t i;
-    long property, set_val;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-
-    switch (param->stack[0]) {
-    case V4L2_CID_BRIGHTNESS:
-        i = 0;
-        property = VideoProcAmp_Brightness;
-        break;
-    case V4L2_CID_CONTRAST:
-        i = 1;
-        property = VideoProcAmp_Contrast;
-        break;
-    case V4L2_CID_SATURATION:
-        i = 2;
-        property = VideoProcAmp_Saturation;
-        break;
-    case V4L2_CID_SHARPNESS:
-        i = 3;
-        property = VideoProcAmp_Sharpness;
-        break;
-    default:
-        param->errCode = EINVAL;
-        return;
-    }
-    set_val = value_convert_from_guest(qctrl_tbl[i].min,
-            qctrl_tbl[i].max, (long)param->stack[1]);
-    hr = SetVideoProcAmp(property, set_val);
-    if (FAILED(hr)) {
-        param->errCode = EINVAL;
-        ERR("failed to set video control value, [HRESULT : 0x%x]\n", hr);
-        return;
-    }
-}
-
-void marucam_device_g_ctrl(MaruCamState *state)
-{
-    HRESULT hr;
-    uint32_t i;
-    long property, get_val;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    switch (param->stack[0]) {
-    case V4L2_CID_BRIGHTNESS:
-        i = 0;
-        property = VideoProcAmp_Brightness;
-        break;
-    case V4L2_CID_CONTRAST:
-        i = 1;
-        property = VideoProcAmp_Contrast;
-        break;
-    case V4L2_CID_SATURATION:
-        i = 2;
-        property = VideoProcAmp_Saturation;
-        break;
-    case V4L2_CID_SHARPNESS:
-        i = 3;
-        property = VideoProcAmp_Sharpness;
-        break;
-    default:
-        param->errCode = EINVAL;
-        return;
-    }
-
-    hr = GetVideoProcAmp(property, &get_val);
-    if (FAILED(hr)) {
-        param->errCode = EINVAL;
-        ERR("failed to get video control value!!!, [HRESULT : 0x%x]\n", hr);
-        return;
-    }
-    param->stack[0] = (uint32_t)value_convert_to_guest(qctrl_tbl[i].min,
-                qctrl_tbl[i].max, get_val);
-}
-
-void marucam_device_enum_fsizes(MaruCamState *state)
-{
-    uint32_t index, pixfmt, i;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    index = param->stack[0];
-    pixfmt = param->stack[1];
-
-    if (index >= ARRAY_SIZE(supported_dst_frames)) {
-        param->errCode = EINVAL;
-        return;
-    }
-    for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
-        if (supported_dst_pixfmts[i].fmt == pixfmt) {
-            break;
-        }
-    }
-
-    if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
-        param->errCode = EINVAL;
-        return;
-    }
-
-    param->stack[0] = supported_dst_frames[index].width;
-    param->stack[1] = supported_dst_frames[index].height;
-}
-
-void marucam_device_enum_fintv(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-
-    /* switch by index(param->stack[0]) */
-    switch (param->stack[0]) {
-    case 0:
-        param->stack[1] = 30; /* denominator */
-        break;
-    default:
-        param->errCode = EINVAL;
-        return;
-    }
-    param->stack[0] = 1; /* numerator */
-}
-
-void yuyv_to_yuv420(const unsigned char *src, unsigned char *dest,
-        uint32_t width, uint32_t height, uint32_t yvu)
-{
-    uint32_t i, j;
-    const unsigned char *src1;
-    unsigned char *udest, *vdest;
-
-    /* copy the Y values */
-    src1 = src;
-    for (i = 0; i < height; i++) {
-        for (j = 0; j < width; j += 2) {
-            *dest++ = src1[0];
-            *dest++ = src1[2];
-            src1 += 4;
-        }
-    }
-
-    /* copy the U and V values */
-    src++;              /* point to V */
-    src1 = src + width * 2;     /* next line */
-    if (yvu) {
-        vdest = dest;
-        udest = dest + width * height / 4;
-    } else {
-        udest = dest;
-        vdest = dest + width * height / 4;
-    }
-    for (i = 0; i < height; i += 2) {
-        for (j = 0; j < width; j += 2) {
-            *udest++ = ((int) src[0] + src1[0]) / 2;    /* U */
-            *vdest++ = ((int) src[2] + src1[2]) / 2;    /* V */
-            src += 4;
-            src1 += 4;
-        }
-        src = src1;
-        src1 += width * 2;
-    }
-}
-
-#define RGB2Y(r, g, b, y)   \
-    (y) = ((8453 * (r) + 16594 * (g) + 3223 * (b) + 524288) >> 15)
-
-#define RGB2UV(r, g, b, u, v)   \
-    do {    \
-        (u) = ((-4878 * (r) - 9578 * (g) + 14456 * (b) + 4210688) >> 15);   \
-        (v) = ((14456 * (r) - 12105 * (g) - 2351 * (b) + 4210688) >> 15);   \
-    } while (0)
-
-#define CLIP(color) \
-    (unsigned char)(((color) > 0xFF) ? 0xff : (((color) < 0) ? 0 : (color)))
-
-void rgb24_to_yuv420(const unsigned char *src, unsigned char *dest,
-                     uint32_t width, uint32_t height, uint32_t yvu)
-{
-    uint32_t x, y;
-    uint32_t halfWidth;
-    uint8_t *yplane, *uplane, *vplane;
-    uint8_t *yline, *uline, *vline;
-    const uint8_t *rgbIndex;
-
-    halfWidth = width >> 1;
-    yplane = dest;
-
-    if (yvu) {
-        vplane = dest + width * height;
-        uplane = vplane + ((width * height) >> 2);
-    } else {
-        uplane = dest + width * height;
-        vplane = uplane + ((width * height) >> 2);
-    }
-
-    for (y = 0; y < height; y++) {
-        yline = yplane + (y * width);
-        uline = uplane + ((y >> 1) * halfWidth);
-        vline = vplane + ((y >> 1) * halfWidth);
-
-        rgbIndex = src + (width * (height - 1 - y) * 3);
-        for (x = 0; x < (int)width; x+=2) {
-            RGB2Y(rgbIndex[2], rgbIndex[1], rgbIndex[0], *yline++);
-            rgbIndex += 3;
-            RGB2Y(rgbIndex[2], rgbIndex[1], rgbIndex[0], *yline++);
-            RGB2UV(rgbIndex[2], rgbIndex[1], rgbIndex[0], *uline++, *vline++);
-            rgbIndex += 3;
-        }
-    }
-}
-
-void rgb24_to_yuyv(unsigned char *src, unsigned char *dest,
-                   uint32_t width, uint32_t height)
-{
-    uint32_t i, j;
-    uint8_t *ptr;
-
-    for (i = 0; i < height; i++) {
-        ptr = src + (width * (height - 1 - i) * 3);
-        for (j = 0; j < width; j += 2) {
-            /* y */
-            *dest++ = CLIP(0.299 * (ptr[2] - 128) +
-                           0.587 * (ptr[1] - 128) +
-                           0.114 * (ptr[0] - 128) + 128);
-            /* u */
-            *dest++ = CLIP(((-0.147 * (ptr[2] - 128) -
-                           0.289 * (ptr[1] - 128) +
-                           0.436 * (ptr[0] - 128) + 128) +
-                           (-0.147 * (ptr[5] - 128) -
-                           0.289 * (ptr[4] - 128) +
-                           0.436 * (ptr[3] - 128) + 128)) / 2);
-            /* y1 */
-            *dest++ = CLIP(0.299 * (ptr[5] - 128) +
-                           0.587 * (ptr[4] - 128) +
-                           0.114 * (ptr[3] - 128) + 128);
-            /* v */
-            *dest++ = CLIP(((0.615 * (ptr[2] - 128) -
-                           0.515 * (ptr[1] - 128) -
-                           0.100 * (ptr[0] - 128) + 128) +
-                           (0.615 * (ptr[5] - 128) -
-                           0.515 * (ptr[4] - 128) -
-                           0.100 * (ptr[3] - 128) + 128)) / 2);
-            ptr += 6;
-        }
-    }
-}
-
-void yuv420_to_yvu420(unsigned char *src, unsigned char *dest,
-                      uint32_t width, uint32_t height)
-{
-    unsigned char *psrc_y, *pdst_y;
-    unsigned char *psrc_u, *pdst_u;
-    unsigned char *psrc_v, *pdst_v;
-
-    psrc_y = src;
-    psrc_u = psrc_y + (width * height);
-    psrc_v = psrc_u + (width * height / 4);
-
-    pdst_y = dest;
-    pdst_v = pdst_y + (width * height);
-    pdst_u = pdst_v + (width * height / 4);
-
-    memcpy(pdst_y, psrc_y, width * height);
-    memcpy(pdst_v, psrc_v, width * height / 4);
-    memcpy(pdst_u, psrc_u, width * height / 4);
-}
-
-void yuv420_to_yuyv(unsigned char *src, unsigned char *dest,
-                    uint32_t width, uint32_t height)
-{
-    unsigned char *py;
-    unsigned char *pu;
-    unsigned char *pv;
-
-    uint32_t linesize = width * 2;
-    uint32_t uvlinesize = width / 2;
-    uint32_t offset = 0;
-    uint32_t offset1 = 0;
-    uint32_t offsety = 0;
-    uint32_t offsety1 = 0;
-    uint32_t offsetuv = 0;
-    uint32_t h = 0;
-    uint32_t w = 0;
-    uint32_t wy = 0;
-    uint32_t huv = 0;
-    uint32_t wuv = 0;
-
-    py = src;
-    pu = py + (width * height);
-    pv = pu + (width * height / 4);
-
-    for (h = 0; h < height; h += 2) {
-        wy = 0;
-        wuv = 0;
-        offset = h * linesize;
-        offset1 = (h + 1) * linesize;
-        offsety = h * width;
-        offsety1 = (h + 1) * width;
-        offsetuv = huv * uvlinesize;
-
-        for (w = 0; w < linesize; w += 4) {
-            /* y00 */
-            dest[w + offset] = py[wy + offsety];
-            /* u0 */
-            dest[(w + 1) + offset] = pu[wuv + offsetuv];
-            /* y01 */
-            dest[(w + 2) + offset] = py[(wy + 1) + offsety];
-            /* v0 */
-            dest[(w + 3) + offset] = pv[wuv + offsetuv];
-
-            /* y10 */
-            dest[w + offset1] = py[wy + offsety1];
-            /* u0 */
-            dest[(w + 1) + offset1] = pu[wuv + offsetuv];
-            /* y11 */
-            dest[(w + 2) + offset1] = py[(wy + 1) + offsety1];
-            /* v0 */
-            dest[(w + 3) + offset1] = pv[wuv + offsetuv];
-
-            wuv++;
-            wy += 2;
-        }
-        huv++;
-    }
-}
index 8a0fc40602211ea6b468db0d2a0414a9fa3f74c7..3d2ec9953fa963b014d5aa4139c793899897bc6d 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Contact:
  * Jinhyung Jo <jinhyung.jo@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ * Sangho Park <sangho1206.park@samsung.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -37,7 +37,7 @@
 #include "ocidl.h"
 #include "errors.h"      /* for VFW_E_XXXX */
 #include "mmsystem.h"    /* for MAKEFOURCC macro */
-#include "hw/pci/maru_camera_win32_interface.h"
+#include "hw/pci/maru_camera_win32.h"
 
 /*
  * COM Interface implementations