Modified the boilerplates.
Modified to suit the QEMU coding conventions.
Changed the file format from Windows text to Linux text.
Signed-off-by: Jinhyung Jo <jinhyung.jo@samsung.com>
-/*\r
- * Common header of MARU Virtual Camera device.\r
- *\r
- * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd All Rights Reserved\r
- *\r
- * Contact:\r
- * JinHyung Jo <jinhyung.jo@samsung.com>\r
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>\r
- *\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * of the License, or (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
- *\r
- * Contributors:\r
- * - S-Core Co., Ltd\r
- *\r
- */\r
-\r
-#ifndef _MARU_CAMERA_COMMON_H_\r
-#define _MARU_CAMERA_COMMON_H_\r
-\r
-#include "pci.h"\r
-#include "qemu-thread.h"\r
-\r
-#define MARUCAM_MAX_PARAM 20\r
-#define MARUCAM_SKIPFRAMES 2\r
-\r
-/* must sync with GUEST camera_driver */\r
-#define MARUCAM_CMD_INIT 0x00\r
-#define MARUCAM_CMD_OPEN 0x04\r
-#define MARUCAM_CMD_CLOSE 0x08\r
-#define MARUCAM_CMD_ISR 0x0C\r
-#define MARUCAM_CMD_START_PREVIEW 0x10\r
-#define MARUCAM_CMD_STOP_PREVIEW 0x14\r
-#define MARUCAM_CMD_S_PARAM 0x18\r
-#define MARUCAM_CMD_G_PARAM 0x1C\r
-#define MARUCAM_CMD_ENUM_FMT 0x20\r
-#define MARUCAM_CMD_TRY_FMT 0x24\r
-#define MARUCAM_CMD_S_FMT 0x28\r
-#define MARUCAM_CMD_G_FMT 0x2C\r
-#define MARUCAM_CMD_QCTRL 0x30\r
-#define MARUCAM_CMD_S_CTRL 0x34\r
-#define MARUCAM_CMD_G_CTRL 0x38\r
-#define MARUCAM_CMD_ENUM_FSIZES 0x3C\r
-#define MARUCAM_CMD_ENUM_FINTV 0x40\r
-#define MARUCAM_CMD_S_DATA 0x44\r
-#define MARUCAM_CMD_G_DATA 0x48\r
-#define MARUCAM_CMD_DATACLR 0x50\r
-#define MARUCAM_CMD_REQFRAME 0x54\r
-\r
-typedef struct MaruCamState MaruCamState;\r
-typedef struct MaruCamParam MaruCamParam;\r
-\r
-struct MaruCamParam {\r
- uint32_t top;\r
- uint32_t retVal;\r
- uint32_t errCode;\r
- uint32_t stack[MARUCAM_MAX_PARAM];\r
-};\r
-\r
-struct MaruCamState {\r
- PCIDevice dev;\r
- MaruCamParam *param;\r
- QemuThread thread_id;\r
- QemuMutex thread_mutex;;\r
- QemuCond thread_cond;\r
- QEMUBH *tx_bh;\r
-\r
- bool destroying;\r
- void *vaddr; /* vram ptr */\r
- uint32_t isr;\r
- uint32_t streamon;\r
- uint32_t buf_size;\r
- uint32_t req_frame;\r
-\r
- MemoryRegion vram;\r
- MemoryRegion mmio;\r
-};\r
-\r
-/* ------------------------------------------------------------------------- */\r
-/* Fucntion prototype */\r
-/* ------------------------------------------------------------------------- */\r
-int marucam_device_check(int log_flag);\r
-void marucam_device_init(MaruCamState *state);\r
-void marucam_device_exit(MaruCamState *state);\r
-void marucam_device_open(MaruCamState *state);\r
-void marucam_device_close(MaruCamState *state);\r
-void marucam_device_start_preview(MaruCamState *state);\r
-void marucam_device_stop_preview(MaruCamState *state);\r
-void marucam_device_s_param(MaruCamState *state);\r
-void marucam_device_g_param(MaruCamState *state);\r
-void marucam_device_s_fmt(MaruCamState *state);\r
-void marucam_device_g_fmt(MaruCamState *state);\r
-void marucam_device_try_fmt(MaruCamState *state);\r
-void marucam_device_enum_fmt(MaruCamState *state);\r
-void marucam_device_qctrl(MaruCamState *state);\r
-void marucam_device_s_ctrl(MaruCamState *state);\r
-void marucam_device_g_ctrl(MaruCamState *state);\r
-void marucam_device_enum_fsizes(MaruCamState *state);\r
-void marucam_device_enum_fintv(MaruCamState *state);\r
-\r
-int maru_camera_pci_init(PCIBus *bus);\r
-\r
-#endif /* _MARU_CAMERA_COMMON_H_ */\r
+/*
+ * 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 "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 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_ */
-/*\r
- * Common implementation of MARU Virtual Camera device by PCI bus.\r
- *\r
- * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd All Rights Reserved\r
- *\r
- * Contact:\r
- * JinHyung Jo <jinhyung.jo@samsung.com>\r
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>\r
- *\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * of the License, or (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
- *\r
- * Contributors:\r
- * - S-Core Co., Ltd\r
- *\r
- */\r
-\r
-\r
-#include <stdarg.h>\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include <inttypes.h>\r
-#include <signal.h>\r
-\r
-#include "qemu-common.h"\r
-#include "cpu-common.h"\r
-\r
-#include "pci.h"\r
-#include "pci_ids.h"\r
-#include "maru_device_ids.h"\r
-\r
-#include "maru_camera_common.h"\r
-#include "tizen/src/debug_ch.h"\r
-\r
-MULTI_DEBUG_CHANNEL(tizen, camera_pci);\r
-\r
-#define MARU_PCI_CAMERA_DEVICE_NAME "maru_camera_pci"\r
-\r
-#define MARUCAM_MEM_SIZE (4 * 1024 * 1024) /* 4MB */\r
-#define MARUCAM_REG_SIZE (256) /* 64 * 4Byte */\r
-\r
-/*\r
- * I/O functions\r
- */\r
-static inline uint32_t\r
-marucam_mmio_read(void *opaque, target_phys_addr_t offset)\r
-{\r
- uint32_t ret = 0;\r
- MaruCamState *state = (MaruCamState*)opaque;\r
-\r
- switch (offset & 0xFF) {\r
- case MARUCAM_CMD_ISR:\r
- qemu_mutex_lock(&state->thread_mutex);\r
- ret = state->isr;\r
- if (ret != 0) {\r
- qemu_irq_lower(state->dev.irq[2]);\r
- state->isr = 0;\r
- }\r
- qemu_mutex_unlock(&state->thread_mutex);\r
- break;\r
- case MARUCAM_CMD_G_DATA:\r
- ret = state->param->stack[state->param->top++];\r
- break;\r
- case MARUCAM_CMD_OPEN:\r
- case MARUCAM_CMD_CLOSE:\r
- case MARUCAM_CMD_START_PREVIEW:\r
- case MARUCAM_CMD_STOP_PREVIEW:\r
- case MARUCAM_CMD_S_PARAM:\r
- case MARUCAM_CMD_G_PARAM:\r
- case MARUCAM_CMD_ENUM_FMT:\r
- case MARUCAM_CMD_TRY_FMT:\r
- case MARUCAM_CMD_S_FMT:\r
- case MARUCAM_CMD_G_FMT:\r
- case MARUCAM_CMD_QCTRL:\r
- case MARUCAM_CMD_S_CTRL:\r
- case MARUCAM_CMD_G_CTRL:\r
- case MARUCAM_CMD_ENUM_FSIZES:\r
- case MARUCAM_CMD_ENUM_FINTV:\r
- ret = state->param->errCode;\r
- state->param->errCode = 0;\r
- break;\r
- default:\r
- ERR("Not supported command: 0x%x\n", offset);\r
- ret = EINVAL;\r
- break;\r
- }\r
- return ret;\r
-}\r
-\r
-static inline void\r
-marucam_mmio_write(void *opaque, target_phys_addr_t offset, uint32_t value)\r
-{\r
- MaruCamState *state = (MaruCamState*)opaque;\r
- \r
- switch(offset & 0xFF) {\r
- case MARUCAM_CMD_OPEN:\r
- marucam_device_open(state);\r
- break;\r
- case MARUCAM_CMD_CLOSE:\r
- marucam_device_close(state);\r
- break;\r
- case MARUCAM_CMD_START_PREVIEW:\r
- marucam_device_start_preview(state);\r
- break;\r
- case MARUCAM_CMD_STOP_PREVIEW:\r
- marucam_device_stop_preview(state);\r
- memset(state->vaddr, 0, MARUCAM_MEM_SIZE);\r
- break;\r
- case MARUCAM_CMD_S_PARAM:\r
- marucam_device_s_param(state);\r
- break;\r
- case MARUCAM_CMD_G_PARAM:\r
- marucam_device_g_param(state);\r
- break;\r
- case MARUCAM_CMD_ENUM_FMT:\r
- marucam_device_enum_fmt(state);\r
- break;\r
- case MARUCAM_CMD_TRY_FMT:\r
- marucam_device_try_fmt(state);\r
- break;\r
- case MARUCAM_CMD_S_FMT:\r
- marucam_device_s_fmt(state);\r
- break;\r
- case MARUCAM_CMD_G_FMT:\r
- marucam_device_g_fmt(state);\r
- break;\r
- case MARUCAM_CMD_QCTRL:\r
- marucam_device_qctrl(state);\r
- break;\r
- case MARUCAM_CMD_S_CTRL:\r
- marucam_device_s_ctrl(state);\r
- break;\r
- case MARUCAM_CMD_G_CTRL:\r
- marucam_device_g_ctrl(state);\r
- break;\r
- case MARUCAM_CMD_ENUM_FSIZES:\r
- marucam_device_enum_fsizes(state);\r
- break;\r
- case MARUCAM_CMD_ENUM_FINTV:\r
- marucam_device_enum_fintv(state);\r
- break;\r
- case MARUCAM_CMD_S_DATA:\r
- state->param->stack[state->param->top++] = value;\r
- break;\r
- case MARUCAM_CMD_DATACLR:\r
- memset(state->param, 0, sizeof(MaruCamParam));\r
- break;\r
- case MARUCAM_CMD_REQFRAME:\r
- qemu_mutex_lock(&state->thread_mutex);\r
- state->req_frame = value + 1;\r
- qemu_mutex_unlock(&state->thread_mutex);\r
- break;\r
- default:\r
- ERR("Not supported command: 0x%x\n", offset);\r
- break;\r
- }\r
-}\r
-\r
-static const MemoryRegionOps maru_camera_mmio_ops = {\r
- .old_mmio = {\r
- .read = {\r
- marucam_mmio_read,\r
- marucam_mmio_read,\r
- marucam_mmio_read,\r
- },\r
- .write = {\r
- marucam_mmio_write,\r
- marucam_mmio_write,\r
- marucam_mmio_write,\r
- },\r
- },\r
- .endianness = DEVICE_LITTLE_ENDIAN,\r
-};\r
-\r
-/*\r
- * QEMU bottom half funtion\r
- */\r
-static void marucam_tx_bh(void *opaque)\r
-{\r
- MaruCamState *state = (MaruCamState *)opaque;\r
-\r
- qemu_mutex_lock(&state->thread_mutex);\r
- if (state->isr) {\r
- qemu_irq_raise(state->dev.irq[2]);\r
- }\r
- qemu_mutex_unlock(&state->thread_mutex);\r
-}\r
-\r
-/*\r
- * Initialization function\r
- */\r
-static int marucam_initfn(PCIDevice *dev)\r
-{\r
- MaruCamState *s = DO_UPCAST(MaruCamState, dev, dev);\r
- uint8_t *pci_conf = s->dev.config;\r
-\r
- pci_config_set_interrupt_pin(pci_conf, 0x03);\r
-\r
- memory_region_init_ram(&s->vram, "marucamera.ram", MARUCAM_MEM_SIZE);\r
- s->vaddr = memory_region_get_ram_ptr(&s->vram);\r
- memset(s->vaddr, 0, MARUCAM_MEM_SIZE);\r
-\r
- memory_region_init_io (&s->mmio, &maru_camera_mmio_ops, s,\r
- "maru-camera-mmio", MARUCAM_REG_SIZE);\r
- pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);\r
- pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio);\r
-\r
- /* for worker thread */\r
- s->param = (MaruCamParam*)g_malloc0(sizeof(MaruCamParam));\r
- qemu_cond_init(&s->thread_cond);\r
- qemu_mutex_init(&s->thread_mutex);\r
-\r
- marucam_device_init(s);\r
-\r
- s->tx_bh = qemu_bh_new(marucam_tx_bh, s);\r
- INFO("[%s] camera device was initialized.\n", __func__);\r
-\r
- return 0;\r
-}\r
-\r
-/*\r
- * Termination function\r
- */\r
-static void marucam_exitfn(PCIDevice *pci_dev)\r
-{\r
- MaruCamState *s =\r
- OBJECT_CHECK(MaruCamState, pci_dev, MARU_PCI_CAMERA_DEVICE_NAME);\r
-\r
- marucam_device_exit(s);\r
- g_free(s->param);\r
- qemu_cond_destroy(&s->thread_cond);\r
- qemu_mutex_destroy(&s->thread_mutex);\r
-\r
- memory_region_destroy(&s->vram);\r
- memory_region_destroy(&s->mmio);\r
-\r
-\r
- INFO("[%s] camera device was released.\n", __func__);\r
-}\r
-\r
-int maru_camera_pci_init(PCIBus *bus)\r
-{\r
- INFO("[%s] camera device was initialized.\n", __func__);\r
- pci_create_simple(bus, -1, MARU_PCI_CAMERA_DEVICE_NAME);\r
- return 0;\r
-}\r
-\r
-static void maru_camera_pci_class_init(ObjectClass *klass, void *data)\r
-{\r
- DeviceClass *dc = DEVICE_CLASS(klass);\r
- PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);\r
-\r
- k->no_hotplug = 1;\r
- k->init = marucam_initfn;\r
- k->exit = marucam_exitfn;\r
- k->vendor_id = PCI_VENDOR_ID_TIZEN;\r
- k->device_id = PCI_DEVICE_ID_VIRTUAL_CAMERA;\r
- k->class_id = PCI_CLASS_OTHERS;\r
- dc->desc = "MARU Virtual Camera device for Tizen emulator";\r
-}\r
-\r
-static TypeInfo maru_camera_info = {\r
- .name = MARU_PCI_CAMERA_DEVICE_NAME,\r
- .parent = TYPE_PCI_DEVICE,\r
- .instance_size = sizeof(MaruCamState),\r
- .class_init = maru_camera_pci_class_init,\r
-};\r
-\r
-static void maru_camera_pci_register_types(void)\r
-{\r
- type_register_static(&maru_camera_info);\r
-}\r
-\r
-type_init(maru_camera_pci_register_types)\r
+/*
+ * 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 "cpu-common.h"
+
+#include "pci.h"
+#include "pci_ids.h"
+#include "maru_device_ids.h"
+
+#include "maru_camera_common.h"
+#include "tizen/src/debug_ch.h"
+
+MULTI_DEBUG_CHANNEL(tizen, camera_pci);
+
+#define MARU_PCI_CAMERA_DEVICE_NAME "maru_camera_pci"
+
+#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, target_phys_addr_t 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) {
+ qemu_irq_lower(state->dev.irq[2]);
+ 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, target_phys_addr_t 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) {
+ qemu_irq_raise(state->dev.irq[2]);
+ }
+ 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;
+
+ pci_config_set_interrupt_pin(pci_conf, 0x03);
+
+ memory_region_init_ram(&s->vram, "marucamera.ram", MARUCAM_MEM_SIZE);
+ s->vaddr = memory_region_get_ram_ptr(&s->vram);
+ memset(s->vaddr, 0, MARUCAM_MEM_SIZE);
+
+ memory_region_init_io(&s->mmio,
+ &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);
+ INFO("[%s] camera device was initialized.\n", __func__);
+
+ return 0;
+}
+
+/*
+ * Termination function
+ */
+static void marucam_exitfn(PCIDevice *pci_dev)
+{
+ MaruCamState *s =
+ OBJECT_CHECK(MaruCamState, pci_dev, MARU_PCI_CAMERA_DEVICE_NAME);
+
+ marucam_device_exit(s);
+ g_free(s->param);
+ qemu_cond_destroy(&s->thread_cond);
+ qemu_mutex_destroy(&s->thread_mutex);
+
+ memory_region_destroy(&s->vram);
+ memory_region_destroy(&s->mmio);
+
+
+ INFO("[%s] camera device was released.\n", __func__);
+}
+
+int maru_camera_pci_init(PCIBus *bus)
+{
+ INFO("[%s] camera device was initialized.\n", __func__);
+ 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->no_hotplug = 1;
+ 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->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)
/*
+ * 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
* 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.
+ * 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))
+#define MAKEFOURCC(a, b, c, d) \
+ (((uint32_t)(a) << 0) | \
+ ((uint32_t)(b) << 8) | \
+ ((uint32_t)(c) << 16) | \
+ ((uint32_t)(d) << 24))
-/* Pixel format FOURCC depth Description */
-#define V4L2_PIX_FMT_RGB555 MAKEFOURCC('R','G','B','O') /* 16 RGB-5-5-5 */
-#define V4L2_PIX_FMT_RGB565 MAKEFOURCC('R','G','B','P') /* 16 RGB-5-6-5 */
-#define V4L2_PIX_FMT_RGB555X MAKEFOURCC('R','G','B','Q') /* 16 RGB-5-5-5 BE */
-#define V4L2_PIX_FMT_RGB565X MAKEFOURCC('R','G','B','R') /* 16 RGB-5-6-5 BE */
-#define V4L2_PIX_FMT_BGR24 MAKEFOURCC('B','G','R','3') /* 24 BGR-8-8-8 */
-#define V4L2_PIX_FMT_RGB24 MAKEFOURCC('R','G','B','3') /* 24 RGB-8-8-8 */
-#define V4L2_PIX_FMT_BGR32 MAKEFOURCC('B','G','R','4') /* 32 BGR-8-8-8-8 */
-#define V4L2_PIX_FMT_RGB32 MAKEFOURCC('R','G','B','4') /* 32 RGB-8-8-8-8 */
-#define V4L2_PIX_FMT_YVU410 MAKEFOURCC('Y','V','U','9') /* 9 YVU 4:1:0 */
-#define V4L2_PIX_FMT_YVU420 MAKEFOURCC('Y','V','1','2') /* 12 YVU 4:2:0 */
-#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 YUV 4:2:2 */
-#define V4L2_PIX_FMT_YUV422P MAKEFOURCC('4','2','2','P') /* 16 YVU422 planar */
-#define V4L2_PIX_FMT_YUV411P MAKEFOURCC('4','1','1','P') /* 16 YVU411 planar */
-#define V4L2_PIX_FMT_Y41P MAKEFOURCC('Y','4','1','P') /* 12 YUV 4:1:1 */
-#define V4L2_PIX_FMT_YUV444 MAKEFOURCC('Y','4','4','4') /* 16 xxxxyyyy uuuuvvvv */
-#define V4L2_PIX_FMT_YUV555 MAKEFOURCC('Y','U','V','O') /* 16 YUV-5-5-5 */
-#define V4L2_PIX_FMT_YUV565 MAKEFOURCC('Y','U','V','P') /* 16 YUV-5-6-5 */
-#define V4L2_PIX_FMT_YUV32 MAKEFOURCC('Y','U','V','4') /* 32 YUV-8-8-8-8 */
-#define V4L2_PIX_FMT_YUV410 MAKEFOURCC('Y','U','V','9') /* 9 YUV 4:1:0 */
-#define V4L2_PIX_FMT_YUV420 MAKEFOURCC('Y','U','1','2') /* 12 YUV 4:2:0 */
-#define V4L2_PIX_FMT_YYUV MAKEFOURCC('Y','Y','U','V') /* 16 YUV 4:2:2 */
+/* 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);
+ size_t frame_size, void *frame_pixels, void *video_buf);
#endif /* _MARU_CAMERA_DARWIN_H_ */
/*
+ * 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
* 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.
+ * MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
*
*/
/*
- * Implementation of MARU Virtual Camera device by PCI bus on Linux.
+ * Implementation of MARU Virtual Camera device by PCI bus on MacOS.
*
- * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ * 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>
- * Jun Tian <jun.j.tian@intel.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
*
* 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
*
* Contributors:
* - S-Core Co., Ltd
usleep(10000);
}
}
-
+
if (mcd->driver != nil) {
[mcd->driver stopCapture];
}
-/*\r
- * Implementation of MARU Virtual Camera device by PCI bus on Linux.\r
- *\r
- * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd All Rights Reserved\r
- *\r
- * Contact:\r
- * JinHyung Jo <jinhyung.jo@samsung.com>\r
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>\r
- *\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * of the License, or (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
- *\r
- * Contributors:\r
- * - S-Core Co., Ltd\r
- *\r
- */\r
-\r
-#include "qemu-common.h"\r
-#include "maru_camera_common.h"\r
-#include "pci.h"\r
-#include "kvm.h"\r
-#include "tizen/src/debug_ch.h"\r
-\r
-#include <linux/videodev2.h>\r
-\r
-#include <sys/stat.h>\r
-#include <sys/ioctl.h>\r
-#include <sys/mman.h>\r
-\r
-#include <libv4l2.h>\r
-#include <libv4lconvert.h>\r
-\r
-MULTI_DEBUG_CHANNEL(tizen, camera_linux);\r
-\r
-#define CLEAR(x) memset(&(x), 0, sizeof(x))\r
-\r
-#define MARUCAM_DEFAULT_BUFFER_COUNT 4\r
-\r
-#define MARUCAM_CTRL_VALUE_MAX 20\r
-#define MARUCAM_CTRL_VALUE_MIN 1\r
-#define MARUCAM_CTRL_VALUE_MID 10\r
-#define MARUCAM_CTRL_VALUE_STEP 1\r
-\r
-enum {\r
- _MC_THREAD_PAUSED,\r
- _MC_THREAD_STREAMON,\r
- _MC_THREAD_STREAMOFF,\r
-};\r
-\r
-typedef struct marucam_framebuffer {\r
- void *data;\r
- size_t size;\r
-} marucam_framebuffer;\r
-\r
-static int n_framebuffer;\r
-static struct marucam_framebuffer *framebuffer;\r
-\r
-static const char *dev_name = "/dev/video0";\r
-static int v4l2_fd;\r
-static int convert_trial;\r
-static int ready_count;\r
-\r
-static struct v4l2_format dst_fmt;\r
-\r
-static int yioctl(int fd, int req, void *arg)\r
-{\r
- int r;\r
-\r
- do {\r
- r = ioctl(fd, req, arg);\r
- } while (r < 0 && errno == EINTR);\r
-\r
- return r;\r
-}\r
-\r
-static int xioctl(int fd, int req, void *arg)\r
-{\r
- int r;\r
-\r
- do {\r
- r = v4l2_ioctl(fd, req, arg);\r
- } while (r < 0 && errno == EINTR);\r
-\r
- return r;\r
-}\r
-\r
-typedef struct tagMaruCamConvertPixfmt {\r
- uint32_t fmt; /* fourcc */\r
-} MaruCamConvertPixfmt;\r
-\r
-static MaruCamConvertPixfmt supported_dst_pixfmts[] = {\r
- { V4L2_PIX_FMT_YUYV },\r
- { V4L2_PIX_FMT_YUV420 },\r
- { V4L2_PIX_FMT_YVU420 },\r
-};\r
-\r
-typedef struct tagMaruCamConvertFrameInfo {\r
- uint32_t width;\r
- uint32_t height;\r
-} MaruCamConvertFrameInfo;\r
-\r
-static MaruCamConvertFrameInfo supported_dst_frames[] = {\r
- { 640, 480 },\r
- { 352, 288 },\r
- { 320, 240 },\r
- { 176, 144 },\r
- { 160, 120 },\r
-};\r
-\r
-struct marucam_qctrl {\r
- uint32_t id;\r
- uint32_t hit;\r
- int32_t min;\r
- int32_t max;\r
- int32_t step;\r
- int32_t init_val;\r
-};\r
-\r
-static struct marucam_qctrl qctrl_tbl[] = {\r
- { V4L2_CID_BRIGHTNESS, 0, },\r
- { V4L2_CID_CONTRAST, 0, },\r
- { V4L2_CID_SATURATION, 0, },\r
- { V4L2_CID_SHARPNESS, 0, },\r
-};\r
-\r
-static void marucam_reset_controls(void)\r
-{\r
- uint32_t i;\r
- for (i = 0; i < ARRAY_SIZE(qctrl_tbl); i++) {\r
- if (qctrl_tbl[i].hit) {\r
- struct v4l2_control ctrl = {0,};\r
- qctrl_tbl[i].hit = 0;\r
- ctrl.id = qctrl_tbl[i].id;\r
- ctrl.value = qctrl_tbl[i].init_val;\r
- if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) {\r
- ERR("Failed to reset control value: id(0x%x), errstr(%s)\n",\r
- ctrl.id, strerror(errno));\r
- }\r
- }\r
- }\r
-}\r
-\r
-static int32_t value_convert_from_guest(int32_t min, int32_t max, int32_t value)\r
-{\r
- double rate = 0.0;\r
- int32_t dist = 0, ret = 0;\r
-\r
- dist = max - min;\r
-\r
- if (dist < MARUCAM_CTRL_VALUE_MAX) {\r
- rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;\r
- ret = min + (int32_t)(value / rate);\r
- } else {\r
- rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;\r
- ret = min + (int32_t)(rate * value);\r
- }\r
- return ret;\r
-}\r
-\r
-static int32_t value_convert_to_guest(int32_t min, int32_t max, int32_t value)\r
-{\r
- double rate = 0.0;\r
- int32_t dist = 0, ret = 0;\r
-\r
- dist = max - min;\r
-\r
- if (dist < MARUCAM_CTRL_VALUE_MAX) {\r
- rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;\r
- ret = (int32_t)((double)(value - min) * rate);\r
- } else {\r
- rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;\r
- ret = (int32_t)((double)(value - min) / rate);\r
- }\r
-\r
- return ret;\r
-}\r
-\r
-static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format,\r
- uint32_t width, uint32_t height)\r
-{\r
- struct v4l2_frmivalenum fival;\r
- struct v4l2_streamparm sp;\r
- uint32_t min_num = 0, min_denom = 0;\r
-\r
- CLEAR(fival);\r
- fival.pixel_format = pixel_format;\r
- fival.width = width;\r
- fival.height = height;\r
-\r
- if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) < 0) {\r
- ERR("Unable to enumerate intervals for pixelformat(0x%x), (%d:%d)\n",\r
- pixel_format, width, height);\r
- return;\r
- }\r
-\r
- if (fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {\r
- float max_ival = -1.0;\r
- do {\r
- float cur_ival = (float)fival.discrete.numerator\r
- / (float)fival.discrete.denominator;\r
- if (cur_ival > max_ival) {\r
- max_ival = cur_ival;\r
- min_num = fival.discrete.numerator;\r
- min_denom = fival.discrete.denominator;\r
- }\r
- TRACE("Discrete frame interval %u/%u supported\n",\r
- fival.discrete.numerator, fival.discrete.denominator);\r
- fival.index++;\r
- } while (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) >= 0);\r
- } else if ((fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) ||\r
- (fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)) {\r
- TRACE("Frame intervals from %u/%u to %u/%u supported",\r
- fival.stepwise.min.numerator, fival.stepwise.min.denominator,\r
- fival.stepwise.max.numerator, fival.stepwise.max.denominator);\r
- if (fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {\r
- TRACE("with %u/%u step", fival.stepwise.step.numerator,\r
- fival.stepwise.step.denominator);\r
- }\r
- if (((float)fival.stepwise.max.denominator /\r
- (float)fival.stepwise.max.numerator) >\r
- ((float)fival.stepwise.min.denominator /\r
- (float)fival.stepwise.min.numerator)) {\r
- min_num = fival.stepwise.max.numerator;\r
- min_denom = fival.stepwise.max.denominator;\r
- } else {\r
- min_num = fival.stepwise.min.numerator;\r
- min_denom = fival.stepwise.min.denominator;\r
- }\r
- }\r
- TRACE("The actual min values: %u/%u\n", min_num, min_denom);\r
-\r
- CLEAR(sp);\r
- sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
- sp.parm.capture.timeperframe.numerator = min_num;\r
- sp.parm.capture.timeperframe.denominator = min_denom;\r
-\r
- if (xioctl(v4l2_fd, VIDIOC_S_PARM, &sp) < 0) {\r
- ERR("Failed to set to minimum FPS(%u/%u)\n", min_num, min_denom);\r
- }\r
-}\r
-\r
-static uint32_t stop_capturing(void)\r
-{\r
- enum v4l2_buf_type type;\r
-\r
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
- if (xioctl(v4l2_fd, VIDIOC_STREAMOFF, &type) < 0) {\r
- ERR("Failed to ioctl() with VIDIOC_STREAMOFF: %s\n", strerror(errno));\r
- return errno;\r
- }\r
- return 0;\r
-}\r
-\r
-static uint32_t start_capturing(void)\r
-{\r
- enum v4l2_buf_type type;\r
-\r
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
- if (xioctl(v4l2_fd, VIDIOC_STREAMON, &type) < 0) {\r
- ERR("Failed to ioctl() with VIDIOC_STREAMON: %s\n", strerror(errno));\r
- return errno;\r
- }\r
- return 0;\r
-}\r
-\r
-static void free_framebuffers(marucam_framebuffer *fb, int buf_num)\r
-{\r
- int i;\r
-\r
- if (fb == NULL) {\r
- ERR("The framebuffer is NULL. Failed to release the framebuffer\n");\r
- return;\r
- } else if (buf_num == 0) {\r
- ERR("The buffer count is 0. Failed to release the framebuffer\n");\r
- return;\r
- } else {\r
- TRACE("[%s]:fb(0x%p), buf_num(%d)\n", __func__, fb, buf_num);\r
- }\r
-\r
- /* Unmap framebuffers. */\r
- for (i = 0; i < buf_num; i++) {\r
- if (fb[i].data != NULL) {\r
- v4l2_munmap(fb[i].data, fb[i].size);\r
- fb[i].data = NULL;\r
- fb[i].size = 0;\r
- } else {\r
- ERR("framebuffer[%d].data is NULL.\n", i);\r
- }\r
- }\r
-}\r
-\r
-static uint32_t\r
-mmap_framebuffers(marucam_framebuffer **fb, int *buf_num)\r
-{\r
- struct v4l2_requestbuffers req;\r
-\r
- CLEAR(req);\r
- req.count = MARUCAM_DEFAULT_BUFFER_COUNT;\r
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
- req.memory = V4L2_MEMORY_MMAP;\r
- if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &req) < 0) {\r
- if (errno == EINVAL) {\r
- ERR("%s does not support memory mapping: %s\n",\r
- dev_name, strerror(errno));\r
- } else {\r
- ERR("Failed to request bufs: %s\n", strerror(errno));\r
- }\r
- return errno;\r
- }\r
- if (req.count == 0) {\r
- ERR("Insufficient buffer memory on %s\n", dev_name);\r
- return EINVAL;\r
- }\r
-\r
- *fb = g_new0(marucam_framebuffer, req.count);\r
- if (*fb == NULL) {\r
- ERR("Not enough memory to allocate framebuffers\n");\r
- return ENOMEM;\r
- }\r
-\r
- for (*buf_num = 0; *buf_num < req.count; ++*buf_num) {\r
- struct v4l2_buffer buf;\r
- CLEAR(buf);\r
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
- buf.memory = V4L2_MEMORY_MMAP;\r
- buf.index = *buf_num;\r
- if (xioctl(v4l2_fd, VIDIOC_QUERYBUF, &buf) < 0) {\r
- ERR("Failed to ioctl() with VIDIOC_QUERYBUF: %s\n",\r
- strerror(errno));\r
- return errno;\r
- }\r
-\r
- (*fb)[*buf_num].size = buf.length;\r
- (*fb)[*buf_num].data = v4l2_mmap(NULL,\r
- buf.length,\r
- PROT_READ | PROT_WRITE,\r
- MAP_SHARED,\r
- v4l2_fd, buf.m.offset);\r
- if (MAP_FAILED == (*fb)[*buf_num].data) {\r
- ERR("Failed to mmap: %s\n", strerror(errno));\r
- return errno;\r
- }\r
-\r
- /* Queue the mapped buffer. */\r
- CLEAR(buf);\r
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
- buf.memory = V4L2_MEMORY_MMAP;\r
- buf.index = *buf_num;\r
- if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) {\r
- ERR("Failed to ioctl() with VIDIOC_QBUF: %s\n", strerror(errno));\r
- return errno;\r
- }\r
- }\r
- return 0;\r
-}\r
-\r
-static int is_streamon(MaruCamState *state)\r
-{\r
- int st;\r
- qemu_mutex_lock(&state->thread_mutex);\r
- st = state->streamon;\r
- qemu_mutex_unlock(&state->thread_mutex);\r
- return (st == _MC_THREAD_STREAMON);\r
-}\r
-\r
-static int is_stream_paused(MaruCamState *state)\r
-{\r
- int st;\r
- qemu_mutex_lock(&state->thread_mutex);\r
- st = state->streamon;\r
- qemu_mutex_unlock(&state->thread_mutex);\r
- return (st == _MC_THREAD_PAUSED);\r
-}\r
-\r
-static void __raise_err_intr(MaruCamState *state)\r
-{\r
- qemu_mutex_lock(&state->thread_mutex);\r
- if (state->streamon == _MC_THREAD_STREAMON) {\r
- state->req_frame = 0; /* clear request */\r
- state->isr = 0x08; /* set a error flag of rasing a interrupt */\r
- qemu_bh_schedule(state->tx_bh);\r
- }\r
- qemu_mutex_unlock(&state->thread_mutex);\r
-}\r
-\r
-static void\r
-notify_buffer_ready(MaruCamState *state, void *ptr, size_t size)\r
-{\r
- void *buf = NULL;\r
-\r
- qemu_mutex_lock(&state->thread_mutex);\r
- if (state->streamon == _MC_THREAD_STREAMON) {\r
- if (ready_count < MARUCAM_SKIPFRAMES) {\r
- /* skip a frame cause first some frame are distorted */\r
- ++ready_count;\r
- TRACE("Skip %d frame\n", ready_count);\r
- qemu_mutex_unlock(&state->thread_mutex);\r
- return;\r
- }\r
- if (state->req_frame == 0) {\r
- TRACE("There is no request\n");\r
- qemu_mutex_unlock(&state->thread_mutex);\r
- return;\r
- }\r
- buf = state->vaddr + state->buf_size * (state->req_frame - 1);\r
- memcpy(buf, ptr, state->buf_size);\r
- state->req_frame = 0; /* clear request */\r
- state->isr |= 0x01; /* set a flag of rasing a interrupt */\r
- qemu_bh_schedule(state->tx_bh);\r
- }\r
- qemu_mutex_unlock(&state->thread_mutex);\r
-}\r
-\r
-static int read_frame(MaruCamState *state)\r
-{\r
- struct v4l2_buffer buf;\r
-\r
- CLEAR(buf);\r
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
- buf.memory = V4L2_MEMORY_MMAP;\r
- if (xioctl(v4l2_fd, VIDIOC_DQBUF, &buf) < 0) {\r
- switch (errno) {\r
- case EAGAIN:\r
- case EINTR:\r
- ERR("DQBUF error, try again: %s\n", strerror(errno));\r
- return 0;\r
- case EIO:\r
- ERR("The v4l2_read() met the EIO\n");\r
- if (convert_trial-- == -1) {\r
- ERR("Try count for v4l2_read is exceeded: %s\n",\r
- strerror(errno));\r
- return -1;\r
- }\r
- return 0;\r
- default:\r
- ERR("DQBUF error: %s\n", strerror(errno));\r
- return -1;\r
- }\r
- }\r
-\r
- notify_buffer_ready(state, framebuffer[buf.index].data, buf.bytesused);\r
-\r
- if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) {\r
- ERR("QBUF error: %s\n", strerror(errno));\r
- return -1;\r
- }\r
- return 0;\r
-}\r
-\r
-static int __v4l2_streaming(MaruCamState *state)\r
-{\r
- fd_set fds;\r
- struct timeval tv;\r
- int ret;\r
-\r
- FD_ZERO(&fds);\r
- FD_SET(v4l2_fd, &fds);\r
-\r
- tv.tv_sec = 1;\r
- tv.tv_usec = 0;\r
-\r
- ret = select(v4l2_fd + 1, &fds, NULL, NULL, &tv);\r
- if (ret < 0) {\r
- if (errno == EAGAIN || errno == EINTR) {\r
- ERR("Select again: %s\n", strerror(errno));\r
- return 0;\r
- }\r
- ERR("Failed to select: %s\n", strerror(errno));\r
- __raise_err_intr(state);\r
- return -1;\r
- } else if (!ret) {\r
- ERR("Select timed out\n");\r
- return 0;\r
- }\r
-\r
- if (!v4l2_fd || (v4l2_fd == -1)) {\r
- ERR("The file descriptor is closed or not opened\n");\r
- __raise_err_intr(state);\r
- return -1;\r
- }\r
-\r
- ret = read_frame(state);\r
- if (ret < 0) {\r
- ERR("Failed to operate the read_frame()\n");\r
- __raise_err_intr(state);\r
- return -1;\r
- }\r
- return 0;\r
-}\r
-\r
-/* Worker thread */\r
-static void *marucam_worker_thread(void *thread_param)\r
-{\r
- MaruCamState *state = (MaruCamState *)thread_param;\r
-\r
- while (1) {\r
- qemu_mutex_lock(&state->thread_mutex);\r
- state->streamon = _MC_THREAD_PAUSED;\r
- qemu_cond_wait(&state->thread_cond, &state->thread_mutex);\r
- qemu_mutex_unlock(&state->thread_mutex);\r
-\r
- if (state->destroying) {\r
- break;\r
- }\r
-\r
- convert_trial = 10;\r
- ready_count = 0;\r
- qemu_mutex_lock(&state->thread_mutex);\r
- state->streamon = _MC_THREAD_STREAMON;\r
- qemu_mutex_unlock(&state->thread_mutex);\r
- INFO("Streaming on ......\n");\r
-\r
- while (1) {\r
- if (is_streamon(state)) {\r
- if (__v4l2_streaming(state) < 0) {\r
- INFO("...... Streaming off\n");\r
- break;\r
- }\r
- } else {\r
- INFO("...... Streaming off\n");\r
- break;\r
- }\r
- }\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-int marucam_device_check(int log_flag)\r
-{\r
- int tmp_fd;\r
- struct timeval t1, t2;\r
- struct stat st;\r
- struct v4l2_fmtdesc format;\r
- struct v4l2_frmsizeenum size;\r
- struct v4l2_capability cap;\r
- int ret = 0;\r
-\r
- gettimeofday(&t1, NULL);\r
- if (stat(dev_name, &st) < 0) {\r
- fprintf(stdout, "[Webcam] <WARNING> Cannot identify '%s': %s\n",\r
- dev_name, strerror(errno));\r
- } else {\r
- if (!S_ISCHR(st.st_mode)) {\r
- fprintf(stdout, "[Webcam] <WARNING>%s is no character device\n",\r
- dev_name);\r
- }\r
- }\r
-\r
- tmp_fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);\r
- if (tmp_fd < 0) {\r
- fprintf(stdout, "[Webcam] Camera device open failed: %s\n", dev_name);\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
- if (ioctl(tmp_fd, VIDIOC_QUERYCAP, &cap) < 0) {\r
- fprintf(stdout, "[Webcam] Could not qeury video capabilities\n");\r
- close(tmp_fd);\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
- if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ||\r
- !(cap.capabilities & V4L2_CAP_STREAMING)) {\r
- fprintf(stdout, "[Webcam] Not supported video driver\n");\r
- close(tmp_fd);\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
- ret = 1;\r
-\r
- if (log_flag) {\r
- fprintf(stdout, "[Webcam] Driver: %s\n", cap.driver);\r
- fprintf(stdout, "[Webcam] Card: %s\n", cap.card);\r
- fprintf(stdout, "[Webcam] Bus info: %s\n", cap.bus_info);\r
-\r
- CLEAR(format);\r
- format.index = 0;\r
- format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
-\r
- if (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) < 0) {\r
- close(tmp_fd);\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
-\r
- do {\r
- CLEAR(size);\r
- size.index = 0;\r
- size.pixel_format = format.pixelformat;\r
-\r
- fprintf(stdout, "[Webcam] PixelFormat: %c%c%c%c\n",\r
- (char)(format.pixelformat),\r
- (char)(format.pixelformat >> 8),\r
- (char)(format.pixelformat >> 16),\r
- (char)(format.pixelformat >> 24));\r
-\r
- if (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0) {\r
- close(tmp_fd);\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
-\r
- if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {\r
- do {\r
- fprintf(stdout, "[Webcam] got discrete frame size %dx%d\n",\r
- size.discrete.width, size.discrete.height);\r
- size.index++;\r
- } while (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);\r
- } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {\r
- fprintf(stdout, "[Webcam] we have stepwise frame sizes:\n");\r
- fprintf(stdout, "[Webcam] min width: %d, min height: %d\n",\r
- size.stepwise.min_width, size.stepwise.min_height);\r
- fprintf(stdout, "[Webcam] max width: %d, max height: %d\n",\r
- size.stepwise.max_width, size.stepwise.max_height);\r
- fprintf(stdout, "[Webcam] step width: %d, step height: %d\n",\r
- size.stepwise.step_width, size.stepwise.step_height);\r
- } else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {\r
- fprintf(stdout, "[Webcam] we have continuous frame sizes:\n");\r
- fprintf(stdout, "[Webcam] min width: %d, min height: %d\n",\r
- size.stepwise.min_width, size.stepwise.min_height);\r
- fprintf(stdout, "[Webcam] max width: %d, max height: %d\n",\r
- size.stepwise.max_width, size.stepwise.max_height);\r
-\r
- }\r
- format.index++;\r
- } while (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) >= 0);\r
- }\r
-\r
- close(tmp_fd);\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
-}\r
-\r
-void marucam_device_init(MaruCamState *state)\r
-{\r
- state->destroying = false;\r
- qemu_thread_create(&state->thread_id, marucam_worker_thread, (void *)state,\r
- QEMU_THREAD_JOINABLE);\r
-}\r
-\r
-void marucam_device_exit(MaruCamState *state)\r
-{\r
- state->destroying = true;\r
- qemu_mutex_lock(&state->thread_mutex);\r
- qemu_cond_signal(&state->thread_cond);\r
- qemu_mutex_unlock(&state->thread_mutex);\r
- qemu_thread_join(&state->thread_id);\r
-}\r
-\r
-void marucam_device_open(MaruCamState *state)\r
-{\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- v4l2_fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);\r
- if (v4l2_fd < 0) {\r
- ERR("The v4l2 device open failed: %s\n", dev_name);\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
- INFO("Opened\n");\r
-\r
- /* FIXME : Do not use fixed values */\r
- CLEAR(dst_fmt);\r
- dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
- dst_fmt.fmt.pix.width = 640;\r
- dst_fmt.fmt.pix.height = 480;\r
- dst_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;\r
- dst_fmt.fmt.pix.field = V4L2_FIELD_ANY;\r
-\r
- if (xioctl(v4l2_fd, VIDIOC_S_FMT, &dst_fmt) < 0) {\r
- ERR("Failed to set video format: format(0x%x), width:height(%d:%d), "\r
- "errstr(%s)\n", dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.width,\r
- dst_fmt.fmt.pix.height, strerror(errno));\r
- param->errCode = errno;\r
- return;\r
- }\r
- TRACE("Set the default format: w:h(%dx%d), fmt(0x%x), size(%d), "\r
- "color(%d), field(%d)\n",\r
- dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height,\r
- dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage,\r
- dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field);\r
-}\r
-\r
-void marucam_device_start_preview(MaruCamState *state)\r
-{\r
- struct timespec req;\r
- MaruCamParam *param = state->param;\r
- param->top = 0;\r
- req.tv_sec = 0;\r
- req.tv_nsec = 10000000;\r
-\r
- INFO("Pixfmt(%c%c%c%C), W:H(%d:%d), buf size(%u)\n",\r
- (char)(dst_fmt.fmt.pix.pixelformat),\r
- (char)(dst_fmt.fmt.pix.pixelformat >> 8),\r
- (char)(dst_fmt.fmt.pix.pixelformat >> 16),\r
- (char)(dst_fmt.fmt.pix.pixelformat >> 24),\r
- dst_fmt.fmt.pix.width,\r
- dst_fmt.fmt.pix.height,\r
- dst_fmt.fmt.pix.sizeimage);\r
-\r
- param->errCode = mmap_framebuffers(&framebuffer, &n_framebuffer);\r
- if (param->errCode) {\r
- ERR("Failed to mmap framebuffers\n");\r
- if (framebuffer != NULL) {\r
- free_framebuffers(framebuffer, n_framebuffer);\r
- g_free(framebuffer);\r
- framebuffer = NULL;\r
- n_framebuffer = 0;\r
- }\r
- return;\r
- }\r
-\r
- param->errCode = start_capturing();\r
- if (param->errCode) {\r
- if (framebuffer != NULL) {\r
- free_framebuffers(framebuffer, n_framebuffer);\r
- g_free(framebuffer);\r
- framebuffer = NULL;\r
- n_framebuffer = 0;\r
- }\r
- return;\r
- }\r
-\r
- INFO("Starting preview\n");\r
- state->buf_size = dst_fmt.fmt.pix.sizeimage;\r
- qemu_mutex_lock(&state->thread_mutex);\r
- qemu_cond_signal(&state->thread_cond);\r
- qemu_mutex_unlock(&state->thread_mutex);\r
-\r
- /* nanosleep until thread is streamon */\r
- while (!is_streamon(state)) {\r
- nanosleep(&req, NULL);\r
- }\r
-}\r
-\r
-void marucam_device_stop_preview(MaruCamState *state)\r
-{\r
- struct timespec req;\r
- struct v4l2_requestbuffers reqbuf;\r
- MaruCamParam *param = state->param;\r
- param->top = 0;\r
- req.tv_sec = 0;\r
- req.tv_nsec = 50000000;\r
-\r
- if (is_streamon(state)) {\r
- qemu_mutex_lock(&state->thread_mutex);\r
- state->streamon = _MC_THREAD_STREAMOFF;\r
- qemu_mutex_unlock(&state->thread_mutex);\r
-\r
- /* nanosleep until thread is paused */\r
- while (!is_stream_paused(state)) {\r
- nanosleep(&req, NULL);\r
- }\r
- }\r
-\r
- param->errCode = stop_capturing();\r
- if (framebuffer != NULL) {\r
- free_framebuffers(framebuffer, n_framebuffer);\r
- g_free(framebuffer);\r
- framebuffer = NULL;\r
- n_framebuffer = 0;\r
- }\r
- state->buf_size = 0;\r
-\r
- reqbuf.count = 0;\r
- reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
- reqbuf.memory = V4L2_MEMORY_MMAP;\r
- if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &reqbuf) < 0) {\r
- ERR("Failed to ioctl() with VIDIOC_REQBUF in stop_preview: %s\n",\r
- strerror(errno));\r
- }\r
- INFO("Stopping preview\n");\r
-}\r
-\r
-void marucam_device_s_param(MaruCamState *state)\r
-{\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
-\r
- /* If KVM enabled, We use default FPS of the webcam.\r
- * If KVM disabled, we use mininum FPS of the webcam */\r
- if (!kvm_enabled()) {\r
- set_maxframeinterval(state, dst_fmt.fmt.pix.pixelformat,\r
- dst_fmt.fmt.pix.width,\r
- dst_fmt.fmt.pix.height);\r
- }\r
-}\r
-\r
-void marucam_device_g_param(MaruCamState *state)\r
-{\r
- MaruCamParam *param = state->param;\r
-\r
- /* We use default FPS of the webcam\r
- * return a fixed value on guest ini file (1/30).\r
- */\r
- param->top = 0;\r
- param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */\r
- param->stack[1] = 1; /* numerator */\r
- param->stack[2] = 30; /* denominator */\r
-}\r
-\r
-void marucam_device_s_fmt(MaruCamState *state)\r
-{\r
- struct v4l2_format format;\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- CLEAR(format);\r
- format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
- format.fmt.pix.width = param->stack[0];\r
- format.fmt.pix.height = param->stack[1];\r
- format.fmt.pix.pixelformat = param->stack[2];\r
- format.fmt.pix.field = V4L2_FIELD_ANY;\r
-\r
- if (xioctl(v4l2_fd, VIDIOC_S_FMT, &format) < 0) {\r
- ERR("Failed to set video format: format(0x%x), width:height(%d:%d), "\r
- "errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width,\r
- format.fmt.pix.height, strerror(errno));\r
- param->errCode = errno;\r
- return;\r
- }\r
-\r
- memcpy(&dst_fmt, &format, sizeof(format));\r
- param->stack[0] = dst_fmt.fmt.pix.width;\r
- param->stack[1] = dst_fmt.fmt.pix.height;\r
- param->stack[2] = dst_fmt.fmt.pix.field;\r
- param->stack[3] = dst_fmt.fmt.pix.pixelformat;\r
- param->stack[4] = dst_fmt.fmt.pix.bytesperline;\r
- param->stack[5] = dst_fmt.fmt.pix.sizeimage;\r
- param->stack[6] = dst_fmt.fmt.pix.colorspace;\r
- param->stack[7] = dst_fmt.fmt.pix.priv;\r
- TRACE("Set the format: w:h(%dx%d), fmt(0x%x), size(%d), "\r
- "color(%d), field(%d)\n",\r
- dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height,\r
- dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage,\r
- dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field);\r
-}\r
-\r
-void marucam_device_g_fmt(MaruCamState *state)\r
-{\r
- struct v4l2_format format;\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- CLEAR(format);\r
- format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
-\r
- if (xioctl(v4l2_fd, VIDIOC_G_FMT, &format) < 0) {\r
- ERR("Failed to get video format: %s\n", strerror(errno));\r
- param->errCode = errno;\r
- } else {\r
- param->stack[0] = format.fmt.pix.width;\r
- param->stack[1] = format.fmt.pix.height;\r
- param->stack[2] = format.fmt.pix.field;\r
- param->stack[3] = format.fmt.pix.pixelformat;\r
- param->stack[4] = format.fmt.pix.bytesperline;\r
- param->stack[5] = format.fmt.pix.sizeimage;\r
- param->stack[6] = format.fmt.pix.colorspace;\r
- param->stack[7] = format.fmt.pix.priv;\r
- TRACE("Get the format: w:h(%dx%d), fmt(0x%x), size(%d), "\r
- "color(%d), field(%d)\n",\r
- format.fmt.pix.width, format.fmt.pix.height,\r
- format.fmt.pix.pixelformat, format.fmt.pix.sizeimage,\r
- format.fmt.pix.colorspace, format.fmt.pix.field);\r
- }\r
-}\r
-\r
-void marucam_device_try_fmt(MaruCamState *state)\r
-{\r
- struct v4l2_format format;\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- CLEAR(format);\r
- format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
- format.fmt.pix.width = param->stack[0];\r
- format.fmt.pix.height = param->stack[1];\r
- format.fmt.pix.pixelformat = param->stack[2];\r
- format.fmt.pix.field = V4L2_FIELD_ANY;\r
-\r
- if (xioctl(v4l2_fd, VIDIOC_TRY_FMT, &format) < 0) {\r
- ERR("Failed to check video format: format(0x%x), width:height(%d:%d),"\r
- " errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width,\r
- format.fmt.pix.height, strerror(errno));\r
- param->errCode = errno;\r
- return;\r
- }\r
- param->stack[0] = format.fmt.pix.width;\r
- param->stack[1] = format.fmt.pix.height;\r
- param->stack[2] = format.fmt.pix.field;\r
- param->stack[3] = format.fmt.pix.pixelformat;\r
- param->stack[4] = format.fmt.pix.bytesperline;\r
- param->stack[5] = format.fmt.pix.sizeimage;\r
- param->stack[6] = format.fmt.pix.colorspace;\r
- param->stack[7] = format.fmt.pix.priv;\r
- TRACE("Check the format: w:h(%dx%d), fmt(0x%x), size(%d), "\r
- "color(%d), field(%d)\n",\r
- format.fmt.pix.width, format.fmt.pix.height,\r
- format.fmt.pix.pixelformat, format.fmt.pix.sizeimage,\r
- format.fmt.pix.colorspace, format.fmt.pix.field);\r
-}\r
-\r
-void marucam_device_enum_fmt(MaruCamState *state)\r
-{\r
- uint32_t index;\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- index = param->stack[0];\r
-\r
- if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
- param->stack[1] = 0; /* flags = NONE */\r
- param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */\r
- /* set description */\r
- switch (supported_dst_pixfmts[index].fmt) {\r
- case V4L2_PIX_FMT_YUYV:\r
- memcpy(¶m->stack[3], "YUYV", 32);\r
- break;\r
- case V4L2_PIX_FMT_YUV420:\r
- memcpy(¶m->stack[3], "YU12", 32);\r
- break;\r
- case V4L2_PIX_FMT_YVU420:\r
- memcpy(¶m->stack[3], "YV12", 32);\r
- break;\r
- default:\r
- ERR("Invalid fixel format\n");\r
- param->errCode = EINVAL;\r
- break;\r
- }\r
-}\r
-\r
-void marucam_device_qctrl(MaruCamState *state)\r
-{\r
- uint32_t i;\r
- char name[32] = {0,};\r
- struct v4l2_queryctrl ctrl;\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- CLEAR(ctrl);\r
- ctrl.id = param->stack[0];\r
-\r
- switch (ctrl.id) {\r
- case V4L2_CID_BRIGHTNESS:\r
- TRACE("Query : BRIGHTNESS\n");\r
- memcpy((void *)name, (void *)"brightness", 32);\r
- i = 0;\r
- break;\r
- case V4L2_CID_CONTRAST:\r
- TRACE("Query : CONTRAST\n");\r
- memcpy((void *)name, (void *)"contrast", 32);\r
- i = 1;\r
- break;\r
- case V4L2_CID_SATURATION:\r
- TRACE("Query : SATURATION\n");\r
- memcpy((void *)name, (void *)"saturation", 32);\r
- i = 2;\r
- break;\r
- case V4L2_CID_SHARPNESS:\r
- TRACE("Query : SHARPNESS\n");\r
- memcpy((void *)name, (void *)"sharpness", 32);\r
- i = 3;\r
- break;\r
- default:\r
- ERR("Invalid control ID\n");\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
-\r
- if (xioctl(v4l2_fd, VIDIOC_QUERYCTRL, &ctrl) < 0) {\r
- if (errno != EINVAL) {\r
- ERR("Failed to query video controls: %s\n", strerror(errno));\r
- }\r
- param->errCode = errno;\r
- return;\r
- } else {\r
- struct v4l2_control sctrl;\r
- CLEAR(sctrl);\r
- sctrl.id = ctrl.id;\r
- if ((ctrl.maximum + ctrl.minimum) == 0) {\r
- sctrl.value = 0;\r
- } else {\r
- sctrl.value = (ctrl.maximum + ctrl.minimum) / 2;\r
- }\r
- if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &sctrl) < 0) {\r
- ERR("Failed to set control value: id(0x%x), value(%d), "\r
- "errstr(%s)\n", sctrl.id, sctrl.value, strerror(errno));\r
- param->errCode = errno;\r
- return;\r
- }\r
- qctrl_tbl[i].hit = 1;\r
- qctrl_tbl[i].min = ctrl.minimum;\r
- qctrl_tbl[i].max = ctrl.maximum;\r
- qctrl_tbl[i].step = ctrl.step;\r
- qctrl_tbl[i].init_val = ctrl.default_value;\r
- }\r
-\r
- /* set fixed values by FW configuration file */\r
- param->stack[0] = ctrl.id;\r
- param->stack[1] = MARUCAM_CTRL_VALUE_MIN; /* minimum */\r
- param->stack[2] = MARUCAM_CTRL_VALUE_MAX; /* maximum */\r
- param->stack[3] = MARUCAM_CTRL_VALUE_STEP; /* step */\r
- param->stack[4] = MARUCAM_CTRL_VALUE_MID; /* default_value */\r
- param->stack[5] = ctrl.flags;\r
- /* name field setting */\r
- memcpy(¶m->stack[6], (void *)name, sizeof(ctrl.name));\r
-}\r
-\r
-void marucam_device_s_ctrl(MaruCamState *state)\r
-{\r
- uint32_t i;\r
- struct v4l2_control ctrl;\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- CLEAR(ctrl);\r
- ctrl.id = param->stack[0];\r
-\r
- switch (ctrl.id) {\r
- case V4L2_CID_BRIGHTNESS:\r
- i = 0;\r
- TRACE("%d is set to the value of the BRIGHTNESS\n", param->stack[1]);\r
- break;\r
- case V4L2_CID_CONTRAST:\r
- i = 1;\r
- TRACE("%d is set to the value of the CONTRAST\n", param->stack[1]);\r
- break;\r
- case V4L2_CID_SATURATION:\r
- i = 2;\r
- TRACE("%d is set to the value of the SATURATION\n", param->stack[1]);\r
- break;\r
- case V4L2_CID_SHARPNESS:\r
- i = 3;\r
- TRACE("%d is set to the value of the SHARPNESS\n", param->stack[1]);\r
- break;\r
- default:\r
- ERR("Our emulator does not support this control: 0x%x\n", ctrl.id);\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
-\r
- ctrl.value = value_convert_from_guest(qctrl_tbl[i].min,\r
- qctrl_tbl[i].max, param->stack[1]);\r
- if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) {\r
- ERR("Failed to set control value: id(0x%x), value(r:%d, c:%d), "\r
- "errstr(%s)\n", ctrl.id, param->stack[1], ctrl.value,\r
- strerror(errno));\r
- param->errCode = errno;\r
- return;\r
- }\r
-}\r
-\r
-void marucam_device_g_ctrl(MaruCamState *state)\r
-{\r
- uint32_t i;\r
- struct v4l2_control ctrl;\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- CLEAR(ctrl);\r
- ctrl.id = param->stack[0];\r
-\r
- switch (ctrl.id) {\r
- case V4L2_CID_BRIGHTNESS:\r
- TRACE("Gets the value of the BRIGHTNESS\n");\r
- i = 0;\r
- break;\r
- case V4L2_CID_CONTRAST:\r
- TRACE("Gets the value of the CONTRAST\n");\r
- i = 1;\r
- break;\r
- case V4L2_CID_SATURATION:\r
- TRACE("Gets the value of the SATURATION\n");\r
- i = 2;\r
- break;\r
- case V4L2_CID_SHARPNESS:\r
- TRACE("Gets the value of the SHARPNESS\n");\r
- i = 3;\r
- break;\r
- default:\r
- ERR("Our emulator does not support this control: 0x%x\n", ctrl.id);\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
-\r
- if (xioctl(v4l2_fd, VIDIOC_G_CTRL, &ctrl) < 0) {\r
- ERR("Failed to get video control value: %s\n", strerror(errno));\r
- param->errCode = errno;\r
- return;\r
- }\r
- param->stack[0] = value_convert_to_guest(qctrl_tbl[i].min,\r
- qctrl_tbl[i].max, ctrl.value);\r
- TRACE("Value: %d\n", param->stack[0]);\r
-}\r
-\r
-void marucam_device_enum_fsizes(MaruCamState *state)\r
-{\r
- uint32_t index, pixfmt, i;\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- index = param->stack[0];\r
- pixfmt = param->stack[1];\r
-\r
- if (index >= ARRAY_SIZE(supported_dst_frames)) {\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
- for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {\r
- if (supported_dst_pixfmts[i].fmt == pixfmt) {\r
- break;\r
- }\r
- }\r
-\r
- if (i == ARRAY_SIZE(supported_dst_pixfmts)) {\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
-\r
- param->stack[0] = supported_dst_frames[index].width;\r
- param->stack[1] = supported_dst_frames[index].height;\r
-}\r
-\r
-void marucam_device_enum_fintv(MaruCamState *state)\r
-{\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
-\r
- /* switch by index(param->stack[0]) */\r
- switch (param->stack[0]) {\r
- case 0:\r
- /* we only use 1/30 frame interval */\r
- param->stack[1] = 30; /* denominator */\r
- break;\r
- default:\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
- param->stack[0] = 1; /* numerator */\r
-}\r
-\r
-void marucam_device_close(MaruCamState *state)\r
-{\r
- if (!is_stream_paused(state)) {\r
- marucam_device_stop_preview(state);\r
- }\r
-\r
- marucam_reset_controls();\r
-\r
- v4l2_close(v4l2_fd);\r
- v4l2_fd = 0;\r
- INFO("Closed\n");\r
-}\r
+/*
+ * 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 "maru_camera_common.h"
+#include "pci.h"
+#include "kvm.h"
+#include "tizen/src/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_linux);
+
+#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;
+
+static int n_framebuffer;
+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 struct v4l2_format dst_fmt;
+
+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,};
+ qctrl_tbl[i].hit = 0;
+ ctrl.id = qctrl_tbl[i].id;
+ ctrl.value = qctrl_tbl[i].init_val;
+ 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));
+ }
+ }
+ }
+}
+
+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);
+ }
+ }
+}
+
+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);
+}
+
+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 rasing a interrupt */
+ qemu_bh_schedule(state->tx_bh);
+ }
+ qemu_mutex_unlock(&state->thread_mutex);
+}
+
+static void
+notify_buffer_ready(MaruCamState *state, void *ptr, size_t size)
+{
+ 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) {
+ TRACE("There is no request\n");
+ qemu_mutex_unlock(&state->thread_mutex);
+ return;
+ }
+ buf = state->vaddr + state->buf_size * (state->req_frame - 1);
+ memcpy(buf, ptr, state->buf_size);
+ 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, framebuffer[buf.index].data, buf.bytesused);
+
+ 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) {
+ ERR("Select timed out\n");
+ 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;
+ }
+ 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;
+ 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) {
+ fprintf(stdout, "[Webcam] <WARNING> Cannot identify '%s': %s\n",
+ dev_name, strerror(errno));
+ } else {
+ if (!S_ISCHR(st.st_mode)) {
+ fprintf(stdout, "[Webcam] <WARNING>%s is no character device\n",
+ dev_name);
+ }
+ }
+
+ tmp_fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);
+ if (tmp_fd < 0) {
+ fprintf(stdout, "[Webcam] Camera device open failed: %s\n", dev_name);
+ gettimeofday(&t2, NULL);
+ fprintf(stdout, "[Webcam] 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) {
+ fprintf(stdout, "[Webcam] Could not qeury video capabilities\n");
+ close(tmp_fd);
+ gettimeofday(&t2, NULL);
+ fprintf(stdout, "[Webcam] 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)) {
+ fprintf(stdout, "[Webcam] Not supported video driver\n");
+ close(tmp_fd);
+ gettimeofday(&t2, NULL);
+ fprintf(stdout, "[Webcam] Elapsed time: %lu:%06lu\n",
+ t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+ return ret;
+ }
+ ret = 1;
+
+ if (log_flag) {
+ fprintf(stdout, "[Webcam] Driver: %s\n", cap.driver);
+ fprintf(stdout, "[Webcam] Card: %s\n", cap.card);
+ fprintf(stdout, "[Webcam] 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);
+ fprintf(stdout, "[Webcam] 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;
+
+ fprintf(stdout, "[Webcam] 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);
+ fprintf(stdout, "[Webcam] 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 {
+ fprintf(stdout, "[Webcam] got 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) {
+ fprintf(stdout, "[Webcam] we have stepwise frame sizes:\n");
+ fprintf(stdout, "[Webcam] min width: %d, min height: %d\n",
+ size.stepwise.min_width, size.stepwise.min_height);
+ fprintf(stdout, "[Webcam] max width: %d, max height: %d\n",
+ size.stepwise.max_width, size.stepwise.max_height);
+ fprintf(stdout, "[Webcam] step width: %d, step height: %d\n",
+ size.stepwise.step_width, size.stepwise.step_height);
+ } else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
+ fprintf(stdout, "[Webcam] we have continuous frame sizes:\n");
+ fprintf(stdout, "[Webcam] min width: %d, min height: %d\n",
+ size.stepwise.min_width, size.stepwise.min_height);
+ fprintf(stdout, "[Webcam] max 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);
+ fprintf(stdout, "[Webcam] 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_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;
+ 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);
+ }
+ }
+
+ 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:
+ memcpy(¶m->stack[3], "YUYV", 32);
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ memcpy(¶m->stack[3], "YU12", 32);
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ memcpy(¶m->stack[3], "YV12", 32);
+ 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];
+
+ switch (ctrl.id) {
+ case V4L2_CID_BRIGHTNESS:
+ TRACE("Query : BRIGHTNESS\n");
+ memcpy((void *)name, (void *)"brightness", 32);
+ i = 0;
+ break;
+ case V4L2_CID_CONTRAST:
+ TRACE("Query : CONTRAST\n");
+ memcpy((void *)name, (void *)"contrast", 32);
+ i = 1;
+ break;
+ case V4L2_CID_SATURATION:
+ TRACE("Query : SATURATION\n");
+ memcpy((void *)name, (void *)"saturation", 32);
+ i = 2;
+ break;
+ case V4L2_CID_SHARPNESS:
+ TRACE("Query : SHARPNESS\n");
+ memcpy((void *)name, (void *)"sharpness", 32);
+ 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;
+ CLEAR(sctrl);
+ sctrl.id = ctrl.id;
+ 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("Failed to set control value: id(0x%x), value(%d), "
+ "errstr(%s)\n", sctrl.id, sctrl.value, 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 = ctrl.default_value;
+ }
+
+ /* set fixed values by FW configuration file */
+ param->stack[0] = ctrl.id;
+ param->stack[1] = MARUCAM_CTRL_VALUE_MIN; /* minimum */
+ param->stack[2] = MARUCAM_CTRL_VALUE_MAX; /* maximum */
+ param->stack[3] = MARUCAM_CTRL_VALUE_STEP; /* step */
+ param->stack[4] = MARUCAM_CTRL_VALUE_MID; /* default_value */
+ param->stack[5] = ctrl.flags;
+ /* name field setting */
+ memcpy(¶m->stack[6], (void *)name, sizeof(ctrl.name));
+}
+
+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();
+
+ v4l2_close(v4l2_fd);
+ v4l2_fd = 0;
+ INFO("Closed\n");
+}
-/*\r
- * Interface definition header for Windows host.\r
- *\r
- * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd All Rights Reserved\r
- *\r
- * Contact:\r
- * JinHyung Jo <jinhyung.jo@samsung.com>\r
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>\r
- *\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * of the License, or (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
- *\r
- * Contributors:\r
- * - S-Core Co., Ltd\r
- *\r
- */\r
-\r
-#ifndef _MARU_CAMERA_INTERFACE_H_\r
-#define _MARU_CAMERA_INTERFACE_H_\r
-\r
-static const WCHAR HWCPinName[] = L"HWCInputPin\0";\r
-static const WCHAR HWCFilterName[] = L"HWCFilter\0";\r
-\r
-/* Forward Declarations */\r
-FWD_DECL(IBaseFilter);\r
-FWD_DECL(IFilterGraph);\r
-\r
-/* defines */\r
-#define MAX_PIN_NAME 128\r
-#define MAX_FILTER_NAME 128\r
-\r
-#define DECLARE_INTERFACE2(i) \\r
- _COM_interface i { CONST_VTABLE struct i##Vtbl *lpVtbl; }; \\r
- typedef CONST_VTABLE struct i##Vtbl i##Vtbl; \\r
- CONST_VTABLE struct i##Vtbl\r
-#define DECLARE_INTERFACE2_(i,b) DECLARE_INTERFACE2(i)\r
-\r
-typedef LONGLONG REFERENCE_TIME;\r
-typedef long OAFilterState;\r
-typedef DWORD_PTR HSEMAPHORE;\r
-typedef DWORD_PTR HEVENT;\r
-\r
-typedef enum _FilterState {\r
- State_Stopped,\r
- State_Paused,\r
- State_Running\r
-} FILTER_STATE;\r
-\r
-typedef struct _FilterInfo {\r
- WCHAR achName[MAX_FILTER_NAME];\r
- IFilterGraph *pGraph;\r
-} FILTER_INFO;\r
-\r
-typedef enum _PinDirection\r
-{ PINDIR_INPUT = 0,\r
- PINDIR_OUTPUT = ( PINDIR_INPUT + 1 )\r
-} PIN_DIRECTION;\r
-\r
-typedef struct _PinInfo {\r
- IBaseFilter *pFilter;\r
- PIN_DIRECTION dir;\r
- WCHAR achName[MAX_PIN_NAME];\r
-} PIN_INFO;\r
-\r
-typedef struct _AllocatorProperties {\r
- long cBuffers;\r
- long cbBuffer;\r
- long cbAlign;\r
- long cbPrefix;\r
-} ALLOCATOR_PROPERTIES;\r
-\r
-typedef struct _AMMediaType {\r
- GUID majortype;\r
- GUID subtype;\r
- BOOL bFixedSizeSamples;\r
- BOOL bTemporalCompression;\r
- ULONG lSampleSize;\r
- GUID formattype;\r
- IUnknown *pUnk;\r
- ULONG cbFormat;\r
- BYTE *pbFormat;\r
-} AM_MEDIA_TYPE;\r
-\r
-typedef enum tagVideoProcAmpFlags {\r
- VideoProcAmp_Flags_Auto = 0x0001,\r
- VideoProcAmp_Flags_Manual = 0x0002\r
-} VideoProcAmpFlags;\r
-\r
-typedef enum tagVideoProcAmpProperty {\r
- VideoProcAmp_Brightness,\r
- VideoProcAmp_Contrast,\r
- VideoProcAmp_Hue,\r
- VideoProcAmp_Saturation,\r
- VideoProcAmp_Sharpness,\r
- VideoProcAmp_Gamma,\r
- VideoProcAmp_ColorEnable,\r
- VideoProcAmp_WhiteBalance,\r
- VideoProcAmp_BacklightCompensation,\r
- VideoProcAmp_Gain\r
-} VideoProcAmpProperty;\r
-\r
-typedef struct tagVIDEOINFOHEADER {\r
- RECT rcSource;\r
- RECT rcTarget;\r
- DWORD dwBitRate;\r
- DWORD dwBitErrorRate;\r
- REFERENCE_TIME AvgTimePerFrame;\r
- BITMAPINFOHEADER bmiHeader;\r
-} VIDEOINFOHEADER;\r
-\r
-typedef struct _VIDEO_STREAM_CONFIG_CAPS\r
-{\r
- GUID guid;\r
- ULONG VideoStandard;\r
- SIZE InputSize;\r
- SIZE MinCroppingSize;\r
- SIZE MaxCroppingSize;\r
- int CropGranularityX;\r
- int CropGranularityY;\r
- int CropAlignX;\r
- int CropAlignY;\r
- SIZE MinOutputSize;\r
- SIZE MaxOutputSize;\r
- int OutputGranularityX;\r
- int OutputGranularityY;\r
- int StretchTapsX;\r
- int StretchTapsY;\r
- int ShrinkTapsX;\r
- int ShrinkTapsY;\r
- LONGLONG MinFrameInterval;\r
- LONGLONG MaxFrameInterval;\r
- LONG MinBitsPerSecond;\r
- LONG MaxBitsPerSecond;\r
-} VIDEO_STREAM_CONFIG_CAPS;\r
-\r
-\r
-/* Interface & Class GUIDs */\r
-static const IID IID_IGrabCallback = {0x4C337035,0xC89E,0x4B42,{0x9B,0x0C,0x36,0x74,0x44,0xDD,0x70,0xDD}};\r
-\r
-EXTERN_C const IID IID_IBaseFilter;\r
-EXTERN_C const IID IID_ICreateDevEnum;\r
-EXTERN_C const IID IID_IGraphBuilder;\r
-EXTERN_C const IID IID_IMediaSeeking;\r
-EXTERN_C const IID IID_IMediaEventSink;\r
-EXTERN_C const IID IID_IMemInputPin;\r
-EXTERN_C const IID IID_IEnumPins;\r
-EXTERN_C const IID IID_IMediaFilter;\r
-EXTERN_C const IID IID_IEnumMediaTypes;\r
-EXTERN_C const IID IID_IMemAllocator;\r
-EXTERN_C const IID IID_IPin;\r
-EXTERN_C const IID IID_ICaptureGraphBuilder2;\r
-EXTERN_C const IID IID_IFileSinkFilter;\r
-EXTERN_C const IID IID_IAMCopyCaptureFileProgress;\r
-EXTERN_C const IID IID_IEnumFilters;\r
-EXTERN_C const IID IID_IMediaSample;\r
-EXTERN_C const IID IID_IMediaControl;\r
-EXTERN_C const IID IID_IAMStreamConfig;\r
-EXTERN_C const IID IID_IAMVideoProcAmp;\r
-\r
-EXTERN_C const IID CLSID_CaptureGraphBuilder2;\r
-EXTERN_C const IID CLSID_VideoInputDeviceCategory;\r
-EXTERN_C const IID CLSID_AudioRender;\r
-EXTERN_C const IID CLSID_SystemDeviceEnum;\r
-EXTERN_C const IID CLSID_AudioRendererCategory;\r
-EXTERN_C const IID CLSID_FilterGraph;\r
-EXTERN_C const IID CLSID_InfTee;\r
-EXTERN_C const IID CLSID_VideoMixingRenderer9;\r
-EXTERN_C const IID CLSID_MemoryAllocator;\r
-\r
-\r
-/* other types GUIDs*/\r
-EXTERN_C const IID MEDIATYPE_Audio;\r
-EXTERN_C const IID MEDIATYPE_Video;\r
-EXTERN_C const IID MEDIATYPE_Stream;\r
-EXTERN_C const IID MEDIASUBTYPE_PCM;\r
-EXTERN_C const IID MEDIASUBTYPE_WAVE;\r
-EXTERN_C const IID MEDIASUBTYPE_Avi;\r
-EXTERN_C const IID MEDIASUBTYPE_RGB32;\r
-EXTERN_C const IID MEDIASUBTYPE_YV12;\r
-EXTERN_C const IID MEDIASUBTYPE_YUY2;\r
-EXTERN_C const IID MEDIASUBTYPE_I420;\r
-EXTERN_C const IID MEDIASUBTYPE_YUYV;\r
-EXTERN_C const IID FORMAT_WaveFormatEx;\r
-EXTERN_C const IID FORMAT_VideoInfo;\r
-EXTERN_C const IID FORMAT_VideoInfo2;\r
-EXTERN_C const IID PIN_CATEGORY_CAPTURE;\r
-EXTERN_C const IID PIN_CATEGORY_PREVIEW;\r
-\r
-\r
-#define MEDIATYPE_NULL GUID_NULL\r
-#define MEDIASUBTYPE_NULL GUID_NULL\r
-\r
-#define INTERFACE IGrabCallback\r
-DECLARE_INTERFACE_(IGrabCallback, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(Grab)(THIS_ ULONG,BYTE*) PURE;\r
-};\r
-#undef INTERFACE\r
-\r
-#ifdef COBJMACROS\r
-#define IGrabCallback_QueryInterface(T,a,b) (T)->lpVtbl->QueryInterface(T,a,b)\r
-#define IGrabCallback_AddRef(T) (T)->lpVtbl->AddRef(T)\r
-#define IGrabCallback_Release(T) (T)->lpVtbl->Release(T)\r
-#define IGrabCallback_Grab(T,a,b) (T)->lpVtbl->Grab(T,a,b)\r
-#endif /* COBJMACROS */\r
-\r
-#define INTERFACE IAMCopyCaptureFileProgress\r
-DECLARE_INTERFACE_(IAMCopyCaptureFileProgress, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(Progress)(THIS_ int) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IReferenceClock\r
-DECLARE_INTERFACE_(IReferenceClock, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *) PURE;\r
- STDMETHOD(AdviseTime)(THIS_ REFERENCE_TIME, REFERENCE_TIME, HEVENT, DWORD_PTR *) PURE;\r
- STDMETHOD(AdvisePeriodic)(THIS_ REFERENCE_TIME, REFERENCE_TIME, HSEMAPHORE, DWORD_PTR *) PURE;\r
- STDMETHOD(Unadvise)(THIS_ DWORD_PTR) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IEnumFilters\r
-DECLARE_INTERFACE_(IEnumFilters, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(Next)(THIS_ ULONG, IBaseFilter **, ULONG *) PURE;\r
- STDMETHOD(Skip)(THIS_ ULONG) PURE;\r
- STDMETHOD(Reset)(THIS) PURE;\r
- STDMETHOD(Clone)(THIS_ IEnumFilters **) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IEnumMediaTypes\r
-DECLARE_INTERFACE_(IEnumMediaTypes, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(Next)(THIS_ ULONG, AM_MEDIA_TYPE **, ULONG *) PURE;\r
- STDMETHOD(Skip)(THIS_ ULONG) PURE;\r
- STDMETHOD(Reset)(THIS) PURE;\r
- STDMETHOD(Clone)(THIS_ IEnumMediaTypes **) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IPin\r
-DECLARE_INTERFACE_(IPin, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(Connect)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE;\r
- STDMETHOD(ReceiveConnection)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE;\r
- STDMETHOD(Disconnect)(THIS) PURE;\r
- STDMETHOD(ConnectedTo)(THIS_ IPin **) PURE;\r
- STDMETHOD(ConnectionMediaType)(THIS_ AM_MEDIA_TYPE *) PURE;\r
- STDMETHOD(QueryPinInfo)(THIS_ PIN_INFO *) PURE;\r
- STDMETHOD(QueryDirection)(THIS_ PIN_DIRECTION *) PURE;\r
- STDMETHOD(QueryId)(THIS_ LPWSTR *) PURE;\r
- STDMETHOD(QueryAccept)(THIS_ const AM_MEDIA_TYPE *) PURE;\r
- STDMETHOD(EnumMediaTypes)(THIS_ IEnumMediaTypes **) PURE;\r
- STDMETHOD(QueryInternalConnections)(THIS_ IPin **, ULONG *) PURE;\r
- STDMETHOD(EndOfStream)(THIS) PURE;\r
- STDMETHOD(BeginFlush)(THIS) PURE;\r
- STDMETHOD(EndFlush)(THIS) PURE;\r
- STDMETHOD(NewSegment)(THIS_ REFERENCE_TIME, REFERENCE_TIME, double) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IEnumPins\r
-DECLARE_INTERFACE_(IEnumPins, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(Next)(THIS_ ULONG, IPin **, ULONG *) PURE;\r
- STDMETHOD(Skip)(THIS_ ULONG) PURE;\r
- STDMETHOD(Reset)(THIS) PURE;\r
- STDMETHOD(Clone)(THIS_ IEnumPins **) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IMediaFilter\r
-DECLARE_INTERFACE_(IMediaFilter, IPersist)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(GetClassID)(THIS_ CLSID*) PURE;\r
- STDMETHOD(Stop)(THIS) PURE;\r
- STDMETHOD(Pause)(THIS) PURE;\r
- STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE;\r
- STDMETHOD(GetState)(THIS_ DWORD, FILTER_STATE *) PURE;\r
- STDMETHOD(SetSyncSource)(THIS_ IReferenceClock *) PURE;\r
- STDMETHOD(GetSyncSource)(THIS_ IReferenceClock **) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IBaseFilter\r
-DECLARE_INTERFACE2_(IBaseFilter, IMediaFilter)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(GetClassID)(THIS_ CLSID*) PURE;\r
- STDMETHOD(Stop)(THIS) PURE;\r
- STDMETHOD(Pause)(THIS) PURE;\r
- STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE;\r
- STDMETHOD(GetState)(THIS_ DWORD, FILTER_STATE *) PURE;\r
- STDMETHOD(SetSyncSource)(THIS_ IReferenceClock *) PURE;\r
- STDMETHOD(GetSyncSource)(THIS_ IReferenceClock **) PURE;\r
- STDMETHOD(EnumPins)(THIS_ IEnumPins **) PURE;\r
- STDMETHOD(FindPin)(THIS_ LPCWSTR, IPin **) PURE;\r
- STDMETHOD(QueryFilterInfo)(THIS_ FILTER_INFO *) PURE;\r
- STDMETHOD(JoinFilterGraph)(THIS_ IFilterGraph *, LPCWSTR) PURE;\r
- STDMETHOD(QueryVendorInfo)(THIS_ LPWSTR *) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IFilterGraph\r
-DECLARE_INTERFACE2_(IFilterGraph, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(AddFilter)(THIS_ IBaseFilter *, LPCWSTR) PURE;\r
- STDMETHOD(RemoveFilter)(THIS_ IBaseFilter *) PURE;\r
- STDMETHOD(EnumFilters)(THIS_ IEnumFilters **) PURE;\r
- STDMETHOD(FindFilterByName)(THIS_ LPCWSTR, IBaseFilter **) PURE;\r
- STDMETHOD(ConnectDirect)(THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *) PURE;\r
- STDMETHOD(Reconnect)(THIS_ IPin *) PURE;\r
- STDMETHOD(Disconnect)(THIS_ IPin *) PURE;\r
- STDMETHOD(SetDefaultSyncSource)(THIS) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IGraphBuilder\r
-DECLARE_INTERFACE_(IGraphBuilder ,IFilterGraph)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(AddFilter)(THIS_ IBaseFilter *, LPCWSTR) PURE;\r
- STDMETHOD(RemoveFilter)(THIS_ IBaseFilter *) PURE;\r
- STDMETHOD(EnumFilters)(THIS_ IEnumFilters **) PURE;\r
- STDMETHOD(FindFilterByName)(THIS_ LPCWSTR, IBaseFilter **) PURE;\r
- STDMETHOD(ConnectDirect)(THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *) PURE;\r
- STDMETHOD(Reconnect)(THIS_ IPin *) PURE;\r
- STDMETHOD(Disconnect)(THIS_ IPin *) PURE;\r
- STDMETHOD(SetDefaultSyncSource)(THIS) PURE;\r
- STDMETHOD(Connect)(THIS_ IPin *, IPin *) PURE;\r
- STDMETHOD(Render)(THIS_ IPin *) PURE;\r
- STDMETHOD(RenderFile)(THIS_ LPCWSTR, LPCWSTR) PURE;\r
- STDMETHOD(AddSourceFilter)(THIS_ LPCWSTR, LPCWSTR, IBaseFilter **) PURE;\r
- STDMETHOD(SetLogFile)(THIS_ DWORD_PTR) PURE;\r
- STDMETHOD(Abort)(THIS) PURE;\r
- STDMETHOD(ShouldOperationContinue)(THIS) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE ICreateDevEnum\r
-DECLARE_INTERFACE_(ICreateDevEnum, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(CreateClassEnumerator)(THIS_ REFCLSID, IEnumMoniker **, DWORD) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IMediaSample\r
-DECLARE_INTERFACE_(IMediaSample, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(GetPointer)(THIS_ BYTE **) PURE;\r
- STDMETHOD_(long, GetSize)(THIS) PURE;\r
- STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE;\r
- STDMETHOD(SetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE;\r
- STDMETHOD(IsSyncPoint)(THIS) PURE;\r
- STDMETHOD(SetSyncPoint)(THIS_ BOOL) PURE;\r
- STDMETHOD(IsPreroll)(THIS) PURE;\r
- STDMETHOD(SetPreroll)(THIS_ BOOL) PURE;\r
- STDMETHOD_(long, GetActualDataLength)(THIS) PURE;\r
- STDMETHOD(SetActualDataLength)(THIS_ long) PURE;\r
- STDMETHOD(GetMediaType)(THIS_ AM_MEDIA_TYPE **) PURE;\r
- STDMETHOD(SetMediaType)(THIS_ AM_MEDIA_TYPE *) PURE;\r
- STDMETHOD(IsDiscontinuity)(THIS) PURE;\r
- STDMETHOD(SetDiscontinuity)(THIS_ BOOL) PURE;\r
- STDMETHOD(GetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE;\r
- STDMETHOD(SetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IMemAllocator\r
-DECLARE_INTERFACE_(IMemAllocator, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(SetProperties)(THIS_ ALLOCATOR_PROPERTIES *, ALLOCATOR_PROPERTIES *) PURE;\r
- STDMETHOD(GetProperties)(THIS_ ALLOCATOR_PROPERTIES *) PURE;\r
- STDMETHOD(Commit)(THIS) PURE;\r
- STDMETHOD(Decommit)(THIS) PURE;\r
- STDMETHOD(GetBuffer)(THIS_ IMediaSample **, REFERENCE_TIME *, REFERENCE_TIME *, DWORD) PURE;\r
- STDMETHOD(ReleaseBuffer)(THIS_ IMediaSample *) PURE;\r
-\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IMemInputPin\r
-DECLARE_INTERFACE_(IMemInputPin, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(GetAllocator)(THIS_ IMemAllocator **) PURE;\r
- STDMETHOD(NotifyAllocator)(THIS_ IMemAllocator *, BOOL) PURE;\r
- STDMETHOD(GetAllocatorRequirements)(THIS_ ALLOCATOR_PROPERTIES *) PURE;\r
- STDMETHOD(Receive)(THIS_ IMediaSample *) PURE;\r
- STDMETHOD(ReceiveMultiple)(THIS_ IMediaSample **, long, long *) PURE;\r
- STDMETHOD(ReceiveCanBlock)(THIS) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IFileSinkFilter\r
-DECLARE_INTERFACE_(IFileSinkFilter, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(SetFileName)(THIS_ LPCOLESTR,const AM_MEDIA_TYPE *) PURE;\r
- STDMETHOD(GetCurFile)(THIS_ LPOLESTR *,AM_MEDIA_TYPE*) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE ICaptureGraphBuilder2\r
-DECLARE_INTERFACE_(ICaptureGraphBuilder2, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(SetFiltergraph)(THIS_ IGraphBuilder*) PURE;\r
- STDMETHOD(GetFiltergraph)(THIS_ IGraphBuilder**) PURE;\r
- STDMETHOD(SetOutputFileName)(THIS_ const GUID*,LPCOLESTR,IBaseFilter**,IFileSinkFilter**) PURE;\r
- STDMETHOD(FindInterface)(THIS_ const GUID*,const GUID*,IBaseFilter*,REFIID,void**) PURE;\r
- STDMETHOD(RenderStream)(THIS_ const GUID*,const GUID*,IUnknown*,IBaseFilter*,IBaseFilter*) PURE;\r
- STDMETHOD(ControlStream)(THIS_ const GUID*,const GUID*,IBaseFilter*,REFERENCE_TIME*,REFERENCE_TIME*,WORD,WORD) PURE;\r
- STDMETHOD(AllocCapFile)(THIS_ LPCOLESTR,DWORDLONG) PURE;\r
- STDMETHOD(CopyCaptureFile)(THIS_ LPOLESTR,LPOLESTR,int,IAMCopyCaptureFileProgress*) PURE;\r
- STDMETHOD(FindPin)(THIS_ IUnknown*,PIN_DIRECTION,const GUID*,const GUID*,BOOL,int,IPin**) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IAMStreamConfig\r
-DECLARE_INTERFACE_(IAMStreamConfig, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(SetFormat)(THIS_ AM_MEDIA_TYPE*) PURE;\r
- STDMETHOD(GetFormat)(THIS_ AM_MEDIA_TYPE**) PURE;\r
- STDMETHOD(GetNumberOfCapabilities)(THIS_ int*,int*) PURE;\r
- STDMETHOD(GetStreamCaps)(THIS_ int,AM_MEDIA_TYPE**,BYTE*) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IAMVideoProcAmp\r
-DECLARE_INTERFACE_(IAMVideoProcAmp, IUnknown)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(GetRange)(THIS_ long,long*,long*,long*,long*,long*) PURE;\r
- STDMETHOD(Set)(THIS_ long,long,long) PURE;\r
- STDMETHOD(Get)(THIS_ long,long*,long*) PURE;\r
-};\r
-#undef INTERFACE\r
-#define INTERFACE IMediaControl\r
-DECLARE_INTERFACE_(IMediaControl, IDispatch)\r
-{\r
- STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;\r
- STDMETHOD_(ULONG,AddRef)(THIS) PURE;\r
- STDMETHOD_(ULONG,Release)(THIS) PURE;\r
- STDMETHOD(GetTypeInfoCount)(THIS_ UINT*);\r
- STDMETHOD(GetTypeInfo)(THIS_ UINT,LCID,ITypeInfo**);\r
- STDMETHOD(GetIDsOfNames)(THIS_ REFIID,LPOLESTR*,UINT,LCID,DISPID*);\r
- STDMETHOD(Invoke)(THIS_ DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);\r
- STDMETHOD(Run)(THIS);\r
- STDMETHOD(Pause)(THIS);\r
- STDMETHOD(Stop)(THIS);\r
- STDMETHOD(GetState)(THIS_ LONG, OAFilterState*);\r
- STDMETHOD(RenderFile)(THIS_ BSTR);\r
- STDMETHOD(AddSourceFilter)(THIS_ BSTR,IDispatch**);\r
- STDMETHOD(get_FilterCollection)(THIS_ IDispatch**);\r
- STDMETHOD(get_RegFilterCollection)(THIS_ IDispatch**);\r
- STDMETHOD(StopWhenReady)(THIS);\r
-};\r
-#undef INTERFACE\r
-\r
-#ifdef COBJMACROS\r
-#define ICreateDevEnum_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define ICreateDevEnum_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define ICreateDevEnum_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define ICreateDevEnum_CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags) \\r
- ( (This)->lpVtbl -> CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IPin_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IPin_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IPin_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IPin_Connect(This,pReceivePin,pmt) \\r
- ( (This)->lpVtbl -> Connect(This,pReceivePin,pmt) )\r
-#define IPin_ReceiveConnection(This,pConnector,pmt) \\r
- ( (This)->lpVtbl -> ReceiveConnection(This,pConnector,pmt) )\r
-#define IPin_Disconnect(This) \\r
- ( (This)->lpVtbl -> Disconnect(This) )\r
-#define IPin_ConnectedTo(This,pPin) \\r
- ( (This)->lpVtbl -> ConnectedTo(This,pPin) )\r
-#define IPin_ConnectionMediaType(This,pmt) \\r
- ( (This)->lpVtbl -> ConnectionMediaType(This,pmt) )\r
-#define IPin_QueryPinInfo(This,pInfo) \\r
- ( (This)->lpVtbl -> QueryPinInfo(This,pInfo) )\r
-#define IPin_QueryDirection(This,pPinDir) \\r
- ( (This)->lpVtbl -> QueryDirection(This,pPinDir) )\r
-#define IPin_QueryId(This,Id) \\r
- ( (This)->lpVtbl -> QueryId(This,Id) )\r
-#define IPin_QueryAccept(This,pmt) \\r
- ( (This)->lpVtbl -> QueryAccept(This,pmt) )\r
-#define IPin_EnumMediaTypes(This,ppEnum) \\r
- ( (This)->lpVtbl -> EnumMediaTypes(This,ppEnum) )\r
-#define IPin_QueryInternalConnections(This,apPin,nPin) \\r
- ( (This)->lpVtbl -> QueryInternalConnections(This,apPin,nPin) )\r
-#define IPin_EndOfStream(This) \\r
- ( (This)->lpVtbl -> EndOfStream(This) )\r
-#define IPin_BeginFlush(This) \\r
- ( (This)->lpVtbl -> BeginFlush(This) )\r
-#define IPin_EndFlush(This) \\r
- ( (This)->lpVtbl -> EndFlush(This) )\r
-#define IPin_NewSegment(This,tStart,tStop,dRate) \\r
- ( (This)->lpVtbl -> NewSegment(This,tStart,tStop,dRate) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IEnumPins_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IEnumPins_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IEnumPins_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IEnumPins_Next(This,cPins,ppPins,pcFetched) \\r
- ( (This)->lpVtbl -> Next(This,cPins,ppPins,pcFetched) )\r
-#define IEnumPins_Skip(This,cPins) \\r
- ( (This)->lpVtbl -> Skip(This,cPins) )\r
-#define IEnumPins_Reset(This) \\r
- ( (This)->lpVtbl -> Reset(This) )\r
-#define IEnumPins_Clone(This,ppEnum) \\r
- ( (This)->lpVtbl -> Clone(This,ppEnum) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IAMStreamConfig_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IAMStreamConfig_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IAMStreamConfig_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IAMStreamConfig_SetFormat(This,pmt) \\r
- ( (This)->lpVtbl -> SetFormat(This,pmt) )\r
-#define IAMStreamConfig_GetFormat(This,ppmt) \\r
- ( (This)->lpVtbl -> GetFormat(This,ppmt) )\r
-#define IAMStreamConfig_GetNumberOfCapabilities(This,piCount,piSize) \\r
- ( (This)->lpVtbl -> GetNumberOfCapabilities(This,piCount,piSize) )\r
-#define IAMStreamConfig_GetStreamCaps(This,iIndex,ppmt,pSCC) \\r
- ( (This)->lpVtbl -> GetStreamCaps(This,iIndex,ppmt,pSCC) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IFilterGraph_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IFilterGraph_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IFilterGraph_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IFilterGraph_AddFilter(This,pFilter,pName) \\r
- ( (This)->lpVtbl -> AddFilter(This,pFilter,pName) )\r
-#define IFilterGraph_RemoveFilter(This,pFilter) \\r
- ( (This)->lpVtbl -> RemoveFilter(This,pFilter) )\r
-#define IFilterGraph_EnumFilters(This,ppEnum) \\r
- ( (This)->lpVtbl -> EnumFilters(This,ppEnum) )\r
-#define IFilterGraph_FindFilterByName(This,pName,ppFilter) \\r
- ( (This)->lpVtbl -> FindFilterByName(This,pName,ppFilter) )\r
-#define IFilterGraph_ConnectDirect(This,ppinOut,ppinIn,pmt) \\r
- ( (This)->lpVtbl -> ConnectDirect(This,ppinOut,ppinIn,pmt) )\r
-#define IFilterGraph_Reconnect(This,ppin) \\r
- ( (This)->lpVtbl -> Reconnect(This,ppin) )\r
-#define IFilterGraph_Disconnect(This,ppin) \\r
- ( (This)->lpVtbl -> Disconnect(This,ppin) )\r
-#define IFilterGraph_SetDefaultSyncSource(This) \\r
- ( (This)->lpVtbl -> SetDefaultSyncSource(This) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IMediaFilter_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IMediaFilter_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IMediaFilter_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IMediaFilter_GetClassID(This,pClassID) \\r
- ( (This)->lpVtbl -> GetClassID(This,pClassID) )\r
-#define IMediaFilter_Stop(This) \\r
- ( (This)->lpVtbl -> Stop(This) )\r
-#define IMediaFilter_Pause(This) \\r
- ( (This)->lpVtbl -> Pause(This) )\r
-#define IMediaFilter_Run(This,tStart) \\r
- ( (This)->lpVtbl -> Run(This,tStart) )\r
-#define IMediaFilter_GetState(This,dwMilliSecsTimeout,State) \\r
- ( (This)->lpVtbl -> GetState(This,dwMilliSecsTimeout,State) )\r
-#define IMediaFilter_SetSyncSource(This,pClock) \\r
- ( (This)->lpVtbl -> SetSyncSource(This,pClock) )\r
-#define IMediaFilter_GetSyncSource(This,pClock) \\r
- ( (This)->lpVtbl -> GetSyncSource(This,pClock) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IBaseFilter_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IBaseFilter_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IBaseFilter_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IBaseFilter_GetClassID(This,pClassID) \\r
- ( (This)->lpVtbl -> GetClassID(This,pClassID) )\r
-#define IBaseFilter_Stop(This) \\r
- ( (This)->lpVtbl -> Stop(This) )\r
-#define IBaseFilter_Pause(This) \\r
- ( (This)->lpVtbl -> Pause(This) )\r
-#define IBaseFilter_Run(This,tStart) \\r
- ( (This)->lpVtbl -> Run(This,tStart) )\r
-#define IBaseFilter_GetState(This,dwMilliSecsTimeout,State) \\r
- ( (This)->lpVtbl -> GetState(This,dwMilliSecsTimeout,State) )\r
-#define IBaseFilter_SetSyncSource(This,pClock) \\r
- ( (This)->lpVtbl -> SetSyncSource(This,pClock) )\r
-#define IBaseFilter_GetSyncSource(This,pClock) \\r
- ( (This)->lpVtbl -> GetSyncSource(This,pClock) )\r
-#define IBaseFilter_EnumPins(This,ppEnum) \\r
- ( (This)->lpVtbl -> EnumPins(This,ppEnum) )\r
-#define IBaseFilter_FindPin(This,Id,ppPin) \\r
- ( (This)->lpVtbl -> FindPin(This,Id,ppPin) )\r
-#define IBaseFilter_QueryFilterInfo(This,pInfo) \\r
- ( (This)->lpVtbl -> QueryFilterInfo(This,pInfo) )\r
-#define IBaseFilter_JoinFilterGraph(This,pGraph,pName) \\r
- ( (This)->lpVtbl -> JoinFilterGraph(This,pGraph,pName) )\r
-#define IBaseFilter_QueryVendorInfo(This,pVendorInfo) \\r
- ( (This)->lpVtbl -> QueryVendorInfo(This,pVendorInfo) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IMediaSample_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IMediaSample_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IMediaSample_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IMediaSample_GetPointer(This,ppBuffer) \\r
- ( (This)->lpVtbl -> GetPointer(This,ppBuffer) )\r
-#define IMediaSample_GetSize(This) \\r
- ( (This)->lpVtbl -> GetSize(This) )\r
-#define IMediaSample_GetTime(This,pTimeStart,pTimeEnd) \\r
- ( (This)->lpVtbl -> GetTime(This,pTimeStart,pTimeEnd) )\r
-#define IMediaSample_SetTime(This,pTimeStart,pTimeEnd) \\r
- ( (This)->lpVtbl -> SetTime(This,pTimeStart,pTimeEnd) )\r
-#define IMediaSample_IsSyncPoint(This) \\r
- ( (This)->lpVtbl -> IsSyncPoint(This) )\r
-#define IMediaSample_SetSyncPoint(This,bIsSyncPoint) \\r
- ( (This)->lpVtbl -> SetSyncPoint(This,bIsSyncPoint) )\r
-#define IMediaSample_IsPreroll(This) \\r
- ( (This)->lpVtbl -> IsPreroll(This) )\r
-#define IMediaSample_SetPreroll(This,bIsPreroll) \\r
- ( (This)->lpVtbl -> SetPreroll(This,bIsPreroll) )\r
-#define IMediaSample_GetActualDataLength(This) \\r
- ( (This)->lpVtbl -> GetActualDataLength(This) )\r
-#define IMediaSample_SetActualDataLength(This,length) \\r
- ( (This)->lpVtbl -> SetActualDataLength(This,length) )\r
-#define IMediaSample_GetMediaType(This,ppMediaType) \\r
- ( (This)->lpVtbl -> GetMediaType(This,ppMediaType) )\r
-#define IMediaSample_SetMediaType(This,pMediaType) \\r
- ( (This)->lpVtbl -> SetMediaType(This,pMediaType) )\r
-#define IMediaSample_IsDiscontinuity(This) \\r
- ( (This)->lpVtbl -> IsDiscontinuity(This) )\r
-#define IMediaSample_SetDiscontinuity(This,bDiscontinuity) \\r
- ( (This)->lpVtbl -> SetDiscontinuity(This,bDiscontinuity) )\r
-#define IMediaSample_GetMediaTime(This,pTimeStart,pTimeEnd) \\r
- ( (This)->lpVtbl -> GetMediaTime(This,pTimeStart,pTimeEnd) )\r
-#define IMediaSample_SetMediaTime(This,pTimeStart,pTimeEnd) \\r
- ( (This)->lpVtbl -> SetMediaTime(This,pTimeStart,pTimeEnd) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IEnumFilters_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IEnumFilters_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IEnumFilters_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IEnumFilters_Next(This,cFilters,ppFilter,pcFetched) \\r
- ( (This)->lpVtbl -> Next(This,cFilters,ppFilter,pcFetched) )\r
-#define IEnumFilters_Skip(This,cFilters) \\r
- ( (This)->lpVtbl -> Skip(This,cFilters) )\r
-#define IEnumFilters_Reset(This) \\r
- ( (This)->lpVtbl -> Reset(This) )\r
-#define IEnumFilters_Clone(This,ppEnum) \\r
- ( (This)->lpVtbl -> Clone(This,ppEnum) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IMemAllocator_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IMemAllocator_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IMemAllocator_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IMemAllocator_SetProperties(This,pRequest,pActual) \\r
- ( (This)->lpVtbl -> SetProperties(This,pRequest,pActual) )\r
-#define IMemAllocator_GetProperties(This,pProps) \\r
- ( (This)->lpVtbl -> GetProperties(This,pProps) )\r
-#define IMemAllocator_Commit(This) \\r
- ( (This)->lpVtbl -> Commit(This) )\r
-#define IMemAllocator_Decommit(This) \\r
- ( (This)->lpVtbl -> Decommit(This) )\r
-#define IMemAllocator_GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags) \\r
- ( (This)->lpVtbl -> GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags) )\r
-#define IMemAllocator_ReleaseBuffer(This,pBuffer) \\r
- ( (This)->lpVtbl -> ReleaseBuffer(This,pBuffer) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IMemInputPin_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IMemInputPin_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IMemInputPin_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IMemInputPin_GetAllocator(This,ppAllocator) \\r
- ( (This)->lpVtbl -> GetAllocator(This,ppAllocator) )\r
-#define IMemInputPin_NotifyAllocator(This,pAllocator,bReadOnly) \\r
- ( (This)->lpVtbl -> NotifyAllocator(This,pAllocator,bReadOnly) )\r
-#define IMemInputPin_GetAllocatorRequirements(This,pProps) \\r
- ( (This)->lpVtbl -> GetAllocatorRequirements(This,pProps) )\r
-#define IMemInputPin_Receive(This,pSample) \\r
- ( (This)->lpVtbl -> Receive(This,pSample) )\r
-#define IMemInputPin_ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed) \\r
- ( (This)->lpVtbl -> ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed) )\r
-#define IMemInputPin_ReceiveCanBlock(This) \\r
- ( (This)->lpVtbl -> ReceiveCanBlock(This) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IGraphBuilder_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IGraphBuilder_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IGraphBuilder_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IGraphBuilder_AddFilter(This,pFilter,pName) \\r
- ( (This)->lpVtbl -> AddFilter(This,pFilter,pName) )\r
-#define IGraphBuilder_RemoveFilter(This,pFilter) \\r
- ( (This)->lpVtbl -> RemoveFilter(This,pFilter) )\r
-#define IGraphBuilder_EnumFilters(This,ppEnum) \\r
- ( (This)->lpVtbl -> EnumFilters(This,ppEnum) )\r
-#define IGraphBuilder_FindFilterByName(This,pName,ppFilter) \\r
- ( (This)->lpVtbl -> FindFilterByName(This,pName,ppFilter) )\r
-#define IGraphBuilder_ConnectDirect(This,ppinOut,ppinIn,pmt) \\r
- ( (This)->lpVtbl -> ConnectDirect(This,ppinOut,ppinIn,pmt) )\r
-#define IGraphBuilder_Reconnect(This,ppin) \\r
- ( (This)->lpVtbl -> Reconnect(This,ppin) )\r
-#define IGraphBuilder_Disconnect(This,ppin) \\r
- ( (This)->lpVtbl -> Disconnect(This,ppin) )\r
-#define IGraphBuilder_SetDefaultSyncSource(This) \\r
- ( (This)->lpVtbl -> SetDefaultSyncSource(This) )\r
-#define IGraphBuilder_Connect(This,ppinOut,ppinIn) \\r
- ( (This)->lpVtbl -> Connect(This,ppinOut,ppinIn) )\r
-#define IGraphBuilder_Render(This,ppinOut) \\r
- ( (This)->lpVtbl -> Render(This,ppinOut) )\r
-#define IGraphBuilder_RenderFile(This,lpcwstrFile,lpcwstrPlayList) \\r
- ( (This)->lpVtbl -> RenderFile(This,lpcwstrFile,lpcwstrPlayList) )\r
-#define IGraphBuilder_AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter) \\r
- ( (This)->lpVtbl -> AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter) )\r
-#define IGraphBuilder_SetLogFile(This,hFile) \\r
- ( (This)->lpVtbl -> SetLogFile(This,hFile) )\r
-#define IGraphBuilder_Abort(This) \\r
- ( (This)->lpVtbl -> Abort(This) )\r
-#define IGraphBuilder_ShouldOperationContinue(This) \\r
- ( (This)->lpVtbl -> ShouldOperationContinue(This) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IEnumMediaTypes_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IEnumMediaTypes_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IEnumMediaTypes_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IEnumMediaTypes_Next(This,cMediaTypes,ppMediaTypes,pcFetched) \\r
- ( (This)->lpVtbl -> Next(This,cMediaTypes,ppMediaTypes,pcFetched) )\r
-#define IEnumMediaTypes_Skip(This,cMediaTypes) \\r
- ( (This)->lpVtbl -> Skip(This,cMediaTypes) )\r
-#define IEnumMediaTypes_Reset(This) \\r
- ( (This)->lpVtbl -> Reset(This) )\r
-#define IEnumMediaTypes_Clone(This,ppEnum) \\r
- ( (This)->lpVtbl -> Clone(This,ppEnum) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IMediaControl_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IMediaControl_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IMediaControl_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IMediaControl_GetTypeInfoCount(This,pctinfo) \\r
- ( (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) )\r
-#define IMediaControl_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \\r
- ( (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) )\r
-#define IMediaControl_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \\r
- ( (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) )\r
-#define IMediaControl_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \\r
- ( (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) )\r
-#define IMediaControl_Run(This) \\r
- ( (This)->lpVtbl -> Run(This) )\r
-#define IMediaControl_Pause(This) \\r
- ( (This)->lpVtbl -> Pause(This) )\r
-#define IMediaControl_Stop(This) \\r
- ( (This)->lpVtbl -> Stop(This) )\r
-#define IMediaControl_GetState(This,msTimeout,pfs) \\r
- ( (This)->lpVtbl -> GetState(This,msTimeout,pfs) )\r
-#define IMediaControl_RenderFile(This,strFilename) \\r
- ( (This)->lpVtbl -> RenderFile(This,strFilename) )\r
-#define IMediaControl_AddSourceFilter(This,strFilename,ppUnk) \\r
- ( (This)->lpVtbl -> AddSourceFilter(This,strFilename,ppUnk) )\r
-#define IMediaControl_get_FilterCollection(This,ppUnk) \\r
- ( (This)->lpVtbl -> get_FilterCollection(This,ppUnk) )\r
-#define IMediaControl_get_RegFilterCollection(This,ppUnk) \\r
- ( (This)->lpVtbl -> get_RegFilterCollection(This,ppUnk) )\r
-#define IMediaControl_StopWhenReady(This) \\r
- ( (This)->lpVtbl -> StopWhenReady(This) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IAMVideoProcAmp_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IAMVideoProcAmp_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IAMVideoProcAmp_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IAMVideoProcAmp_GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags) \\r
- ( (This)->lpVtbl -> GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags) )\r
-#define IAMVideoProcAmp_Set(This,Property,lValue,Flags) \\r
- ( (This)->lpVtbl -> Set(This,Property,lValue,Flags) )\r
-#define IAMVideoProcAmp_Get(This,Property,lValue,Flags) \\r
- ( (This)->lpVtbl -> Get(This,Property,lValue,Flags) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IFileSinkFilter_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IFileSinkFilter_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IFileSinkFilter_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IFileSinkFilter_SetFileName(This,pszFileName,pmt) \\r
- ( (This)->lpVtbl -> SetFileName(This,pszFileName,pmt) )\r
-#define IFileSinkFilter_GetCurFile(This,ppszFileName,pmt) \\r
- ( (This)->lpVtbl -> GetCurFile(This,ppszFileName,pmt) )\r
-#endif /* COBJMACROS */\r
-\r
-#ifdef COBJMACROS\r
-#define IAMCopyCaptureFileProgress_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define IAMCopyCaptureFileProgress_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define IAMCopyCaptureFileProgress_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define IAMCopyCaptureFileProgress_Progress(This,iProgress) \\r
- ( (This)->lpVtbl -> Progress(This,iProgress) )\r
-#endif /* COBJMACROS */\r
-\r
-\r
-#ifdef COBJMACROS\r
-#define ICaptureGraphBuilder2_QueryInterface(This,riid,ppvObject) \\r
- ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )\r
-#define ICaptureGraphBuilder2_AddRef(This) \\r
- ( (This)->lpVtbl -> AddRef(This) )\r
-#define ICaptureGraphBuilder2_Release(This) \\r
- ( (This)->lpVtbl -> Release(This) )\r
-#define ICaptureGraphBuilder2_SetFiltergraph(This,pfg) \\r
- ( (This)->lpVtbl -> SetFiltergraph(This,pfg) )\r
-#define ICaptureGraphBuilder2_GetFiltergraph(This,ppfg) \\r
- ( (This)->lpVtbl -> GetFiltergraph(This,ppfg) )\r
-#define ICaptureGraphBuilder2_SetOutputFileName(This,pType,lpstrFile,ppf,ppSink) \\r
- ( (This)->lpVtbl -> SetOutputFileName(This,pType,lpstrFile,ppf,ppSink) )\r
-#define ICaptureGraphBuilder2_FindInterface(This,pCategory,pType,pf,riid,ppint) \\r
- ( (This)->lpVtbl -> FindInterface(This,pCategory,pType,pf,riid,ppint) )\r
-#define ICaptureGraphBuilder2_RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer) \\r
- ( (This)->lpVtbl -> RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer) )\r
-#define ICaptureGraphBuilder2_ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie) \\r
- ( (This)->lpVtbl -> ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie) )\r
-#define ICaptureGraphBuilder2_AllocCapFile(This,lpstr,dwlSize) \\r
- ( (This)->lpVtbl -> AllocCapFile(This,lpstr,dwlSize) )\r
-#define ICaptureGraphBuilder2_CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback) \\r
- ( (This)->lpVtbl -> CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback) )\r
-#define ICaptureGraphBuilder2_FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin) \\r
- ( (This)->lpVtbl -> FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin) )\r
-#endif /* COBJMACROS */\r
-\r
-#endif // _MARU_CAMERA_INTERFACE_H_\r
+/*
+ * 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_
+
+extern int hax_enabled(void);
+
+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_ */
-/*\r
- * Implementation of MARU Virtual Camera device by PCI bus on Windows.\r
- *\r
- * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd All Rights Reserved\r
- *\r
- * Contact:\r
- * JinHyung Jo <jinhyung.jo@samsung.com>\r
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>\r
- *\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * of the License, or (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
- *\r
- * Contributors:\r
- * - S-Core Co., Ltd\r
- *\r
- */\r
-\r
-\r
-#include "qemu-common.h"\r
-#include "maru_camera_common.h"\r
-#include "tizen/src/debug_ch.h"\r
-\r
-#define CINTERFACE\r
-#define COBJMACROS\r
-#include "ocidl.h"\r
-#include "errors.h" /* for VFW_E_XXXX */\r
-#include "mmsystem.h" /* for MAKEFOURCC macro */\r
-#include "maru_camera_win32_interface.h"\r
-\r
-MULTI_DEBUG_CHANNEL(tizen, camera_win32);\r
-\r
-extern int hax_enabled(void);\r
-\r
-/*\r
- * COM Interface implementations\r
- *\r
- */\r
-\r
-#define SAFE_RELEASE(x) \\r
- do { \\r
- if (x) { \\r
- (x)->lpVtbl->Release(x); \\r
- x = NULL; \\r
- } \\r
- } while (0)\r
-\r
-typedef HRESULT (STDAPICALLTYPE *CallbackFn)(ULONG dwSize, BYTE *pBuffer);\r
-\r
-/*\r
- * HWCGrabCallback\r
- */\r
-\r
-typedef struct HWCGrabCallback {\r
- IGrabCallback IGrabCallback_iface;\r
- long m_cRef;\r
- CallbackFn m_pCallback;\r
- STDMETHODIMP (*SetCallback)(IGrabCallback *iface, CallbackFn pCallbackFn);\r
-} HWCGrabCallback;\r
-\r
-static inline HWCGrabCallback *impl_from_IGrabCallback(IGrabCallback *iface)\r
-{\r
- return CONTAINING_RECORD(iface, HWCGrabCallback, IGrabCallback_iface);\r
-}\r
-\r
-static STDMETHODIMP HWCGrabCallback_QueryInterface(IGrabCallback *iface,\r
- REFIID riid, void **ppv)\r
-{\r
- if (IsEqualIID(riid, &IID_IUnknown)) {\r
- *ppv = (IUnknown *)iface;\r
- } else if (IsEqualIID(riid, &IID_IGrabCallback)) {\r
- *ppv = (IGrabCallback *)iface;\r
- } else {\r
- *ppv = NULL;\r
- return E_NOINTERFACE;\r
- }\r
-\r
- IGrabCallback_AddRef(iface);\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP_(ULONG) HWCGrabCallback_AddRef(IGrabCallback *iface)\r
-{\r
- HWCGrabCallback *This = impl_from_IGrabCallback(iface);\r
-\r
- return InterlockedIncrement(&This->m_cRef);\r
-}\r
-\r
-static STDMETHODIMP_(ULONG) HWCGrabCallback_Release(IGrabCallback *iface)\r
-{\r
- HWCGrabCallback *This = impl_from_IGrabCallback(iface);\r
-\r
- if (InterlockedDecrement(&This->m_cRef) == 0) {\r
- This->m_pCallback = NULL;\r
- g_free((void *)This);\r
- This = NULL;\r
- return 0;\r
- }\r
-\r
- return This->m_cRef;\r
-}\r
-\r
-static STDMETHODIMP HWCGrabCallback_Grab(IGrabCallback *iface,\r
- ULONG dwSize, BYTE *pBuffer)\r
-{\r
- HWCGrabCallback *This = impl_from_IGrabCallback(iface);\r
-\r
- if (This->m_pCallback) {\r
- HRESULT hr = This->m_pCallback(dwSize, pBuffer);\r
- if (FAILED(hr)) {\r
- return E_FAIL;\r
- } else {\r
- return S_OK;\r
- }\r
- }\r
-\r
- return E_FAIL;\r
-}\r
-\r
-static STDMETHODIMP HWCGrabCallback_SetCallback(IGrabCallback *iface,\r
- CallbackFn pCallbackFn)\r
-{\r
- HWCGrabCallback *This = impl_from_IGrabCallback(iface);\r
-\r
- This->m_pCallback = pCallbackFn;\r
- return S_OK;\r
-}\r
-\r
-static IGrabCallbackVtbl HWCGrabCallback_Vtbl = {\r
- HWCGrabCallback_QueryInterface,\r
- HWCGrabCallback_AddRef,\r
- HWCGrabCallback_Release,\r
- HWCGrabCallback_Grab\r
-};\r
-\r
-static STDMETHODIMP HWCGrabCallback_Construct(IGrabCallback **ppv)\r
-{\r
- HWCGrabCallback *This =\r
- (HWCGrabCallback *)g_malloc0(sizeof(HWCGrabCallback));\r
-\r
- if (!This) {\r
- ERR("failed to HWCGrabCallback_Construct, E_OUTOFMEMORY\n");\r
- return E_OUTOFMEMORY;\r
- }\r
-\r
- This->IGrabCallback_iface.lpVtbl = &HWCGrabCallback_Vtbl;\r
- This->m_cRef = 1;\r
- This->m_pCallback = NULL;\r
- This->SetCallback = HWCGrabCallback_SetCallback;\r
- *ppv = &This->IGrabCallback_iface;\r
- return S_OK;\r
-}\r
-\r
-/*\r
- * HWCPin\r
- */\r
-\r
-typedef struct HWCInPin {\r
- IPin IPin_iface;\r
- IMemInputPin IMemInputPin_iface;\r
- IBaseFilter *m_pCFilter;\r
- IPin *m_pConnectedPin;\r
- IGrabCallback *m_pCallback;\r
- IMemAllocator *m_pAllocator;\r
- BOOL m_bReadOnly;\r
- long m_cRef;\r
- STDMETHODIMP (*SetGrabCallbackIF)(IPin *iface, IGrabCallback *pCaptureCB);\r
-} HWCInPin;\r
-\r
-static inline HWCInPin *impl_from_IPin(IPin *iface)\r
-{\r
- return CONTAINING_RECORD(iface, HWCInPin, IPin_iface);\r
-}\r
-\r
-static inline HWCInPin *impl_from_IMemInputPin(IMemInputPin *iface)\r
-{\r
- return CONTAINING_RECORD(iface, HWCInPin, IMemInputPin_iface);\r
-}\r
-\r
-static STDMETHODIMP HWCPin_QueryInterface(IPin *iface, REFIID riid, void **ppv)\r
-{\r
- HWCInPin *This = impl_from_IPin(iface);\r
-\r
- if (IsEqualIID(riid, &IID_IUnknown)) {\r
- *ppv = (IUnknown *)(&This->IPin_iface);\r
- IPin_AddRef((IPin *)*ppv);\r
- } else if (IsEqualIID(riid, &IID_IPin)) {\r
- *ppv = (IPin *)(&This->IPin_iface);\r
- IPin_AddRef((IPin *)*ppv);\r
- } else if (IsEqualIID(riid, &IID_IMemInputPin)) {\r
- *ppv = (IMemInputPin *)(&This->IMemInputPin_iface);\r
- IPin_AddRef((IMemInputPin *)*ppv);\r
- } else {\r
- *ppv = NULL;\r
- return E_NOINTERFACE;\r
- }\r
-\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP_(ULONG) HWCPin_AddRef(IPin *iface)\r
-{\r
- HWCInPin *This = impl_from_IPin(iface);\r
-\r
- return InterlockedIncrement(&This->m_cRef);\r
-}\r
-\r
-static STDMETHODIMP_(ULONG) HWCPin_Release(IPin *iface)\r
-{\r
- HWCInPin *This = impl_from_IPin(iface);\r
-\r
- if (InterlockedDecrement(&This->m_cRef) == 0) {\r
- if (This->m_pCallback) {\r
- SAFE_RELEASE(This->m_pCallback);\r
- }\r
- if (This->m_pConnectedPin) {\r
- SAFE_RELEASE(This->m_pConnectedPin);\r
- }\r
- if (This->m_pAllocator) {\r
- IMemAllocator_Decommit(This->m_pAllocator);\r
- SAFE_RELEASE(This->m_pAllocator);\r
- }\r
- g_free((void *)This);\r
- This = NULL;\r
- return 0;\r
- }\r
- return This->m_cRef;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_Connect(IPin *iface,\r
- IPin *pReceivePin,\r
- const AM_MEDIA_TYPE *pmt)\r
-{\r
- HWCInPin *This = impl_from_IPin(iface);\r
-\r
- if (!pReceivePin) {\r
- return E_POINTER;\r
- }\r
-\r
- if (This->m_pConnectedPin) {\r
- return VFW_E_ALREADY_CONNECTED;\r
- }\r
-\r
- if (!pmt) {\r
- return S_OK;\r
- }\r
- return S_FALSE;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_ReceiveConnection(IPin *iface, IPin *pConnector,\r
- const AM_MEDIA_TYPE *pmt)\r
-{\r
- PIN_DIRECTION pd;\r
- FILTER_STATE fs;\r
- HWCInPin *This = impl_from_IPin(iface);\r
-\r
- if (pConnector == NULL || pmt == NULL) {\r
- return E_POINTER;\r
- }\r
-\r
- if (This->m_pConnectedPin) {\r
- return VFW_E_ALREADY_CONNECTED;\r
- }\r
- IBaseFilter_GetState(This->m_pCFilter, 0, &fs);\r
- if (fs != State_Stopped) {\r
- return VFW_E_NOT_STOPPED;\r
- }\r
- IPin_QueryDirection(pConnector, &pd);\r
- if (pd == PINDIR_INPUT) {\r
- return VFW_E_INVALID_DIRECTION;\r
- }\r
-\r
- This->m_pConnectedPin = pConnector;\r
- IPin_AddRef(This->m_pConnectedPin);\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_Disconnect(IPin *iface)\r
-{\r
- HWCInPin *This = impl_from_IPin(iface);\r
-\r
- HRESULT hr;\r
- FILTER_STATE fs;\r
- IBaseFilter_GetState(This->m_pCFilter, 0, &fs);\r
- if (fs != State_Stopped) {\r
- return VFW_E_NOT_STOPPED;\r
- }\r
- if (This->m_pConnectedPin == NULL) {\r
- hr = S_FALSE;\r
- } else {\r
- if (This->m_pAllocator) {\r
- hr = IMemAllocator_Decommit(This->m_pAllocator);\r
- if (FAILED(hr)) {\r
- return hr;\r
- }\r
- SAFE_RELEASE(This->m_pAllocator);\r
- }\r
- SAFE_RELEASE(This->m_pConnectedPin);\r
- hr = S_OK;\r
- }\r
- return hr;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_ConnectedTo(IPin *iface, IPin **ppPin)\r
-{\r
- HWCInPin *This = impl_from_IPin(iface);\r
-\r
- if (ppPin == NULL) {\r
- return E_POINTER;\r
- }\r
-\r
- if (This->m_pConnectedPin == NULL) {\r
- *ppPin = NULL;\r
- return VFW_E_NOT_CONNECTED;\r
- } else {\r
- *ppPin = This->m_pConnectedPin;\r
- IPin_AddRef(This->m_pConnectedPin);\r
- }\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *pmt)\r
-{\r
- if (pmt == NULL) {\r
- return E_POINTER;\r
- }\r
- return VFW_E_NOT_CONNECTED;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_QueryPinInfo(IPin *iface, PIN_INFO *pInfo)\r
-{\r
- HWCInPin *This = impl_from_IPin(iface);\r
-\r
- if (pInfo == NULL) {\r
- return E_POINTER;\r
- }\r
-\r
- pInfo->pFilter = This->m_pCFilter;\r
- if (This->m_pCFilter) {\r
- IBaseFilter_AddRef(This->m_pCFilter);\r
- }\r
- memcpy((void *)pInfo->achName, (void *)HWCPinName, sizeof(HWCPinName));\r
- pInfo->dir = PINDIR_INPUT;\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_QueryDirection(IPin *iface, PIN_DIRECTION *pPinDir)\r
-{\r
- if (pPinDir == NULL) {\r
- return E_POINTER;\r
- }\r
- *pPinDir = PINDIR_INPUT;\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_QueryId(IPin *iface, LPWSTR *Id)\r
-{\r
- PVOID pId;\r
- if (Id == NULL) {\r
- return E_POINTER;\r
- }\r
- pId = CoTaskMemAlloc(sizeof(HWCPinName));\r
- memcpy((void *)pId, (void *)HWCPinName, sizeof(HWCPinName));\r
- *Id = (LPWSTR)pId;\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *pmt)\r
-{\r
- if (pmt == NULL) {\r
- return E_POINTER;\r
- }\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_EnumMediaTypes(IPin *iface,\r
- IEnumMediaTypes **ppEnum)\r
-{\r
- if (ppEnum == NULL) {\r
- return E_POINTER;\r
- }\r
- return E_NOTIMPL;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_QueryInternalConnections(IPin *iface,\r
- IPin **ppPin,\r
- ULONG *nPin)\r
-{\r
- return E_NOTIMPL;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_EndOfStream(IPin *iface)\r
-{\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_BeginFlush(IPin *iface)\r
-{\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_EndFlush(IPin *iface)\r
-{\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_NewSegment(IPin *iface, REFERENCE_TIME tStart,\r
- REFERENCE_TIME tStop, double dRate)\r
-{\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCMemInputPin_QueryInterface(IMemInputPin *iface,\r
- REFIID riid, void **ppv)\r
-{\r
- HWCInPin *This = impl_from_IMemInputPin(iface);\r
-\r
- if (IsEqualIID(riid, &IID_IUnknown)) {\r
- *ppv = (IUnknown *)(&This->IMemInputPin_iface);\r
- IPin_AddRef((IPin *)*ppv);\r
- } else if (IsEqualIID(riid, &IID_IPin)) {\r
- *ppv = (IPin *)(&This->IPin_iface);\r
- IPin_AddRef((IPin *)*ppv);\r
- } else if (IsEqualIID(riid, &IID_IMemInputPin)) {\r
- *ppv = (IMemInputPin *)(&This->IMemInputPin_iface);\r
- IPin_AddRef((IMemInputPin *)*ppv);\r
- } else {\r
- *ppv = NULL;\r
- return E_NOINTERFACE;\r
- }\r
-\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP_(ULONG) HWCMemInputPin_AddRef(IMemInputPin *iface)\r
-{\r
- HWCInPin *This = impl_from_IMemInputPin(iface);\r
-\r
- return InterlockedIncrement(&This->m_cRef);\r
-}\r
-\r
-static STDMETHODIMP_(ULONG) HWCMemInputPin_Release(IMemInputPin *iface)\r
-{\r
- HWCInPin *This = impl_from_IMemInputPin(iface);\r
-\r
- if (InterlockedDecrement(&This->m_cRef) == 0) {\r
- if (This->m_pCallback) {\r
- SAFE_RELEASE(This->m_pCallback);\r
- }\r
- if (This->m_pConnectedPin) {\r
- SAFE_RELEASE(This->m_pConnectedPin);\r
- }\r
- if (This->m_pAllocator) {\r
- IMemAllocator_Decommit(This->m_pAllocator);\r
- SAFE_RELEASE(This->m_pAllocator);\r
- }\r
- g_free((void *)This);\r
- This = NULL;\r
- return 0;\r
- }\r
- return This->m_cRef;\r
-}\r
-\r
-static STDMETHODIMP HWCMemInputPin_GetAllocator(IMemInputPin *iface,\r
- IMemAllocator **ppAllocator)\r
-{\r
- HWCInPin *This = impl_from_IMemInputPin(iface);\r
-\r
- if (ppAllocator == NULL) {\r
- return E_POINTER;\r
- }\r
-\r
- if (This->m_pAllocator == NULL) {\r
- HRESULT hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL,\r
- CLSCTX_INPROC_SERVER,\r
- &IID_IMemAllocator,\r
- (void **)&(This->m_pAllocator));\r
- if (FAILED(hr)) {\r
- ERR("Failed to CoCreateInstance for retrieving MemoryAllocator\n");\r
- return hr;\r
- }\r
- }\r
- ASSERT(This->m_pAllocator != NULL);\r
- *ppAllocator = This->m_pAllocator;\r
- IMemAllocator_AddRef(This->m_pAllocator);\r
-\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCMemInputPin_NotifyAllocator(IMemInputPin *iface,\r
- IMemAllocator *pAllocator,\r
- BOOL bReadOnly)\r
-{\r
- HWCInPin *This = impl_from_IMemInputPin(iface);\r
-\r
- if (pAllocator == NULL) {\r
- return E_POINTER;\r
- }\r
-\r
- IMemAllocator *pOldAllocator = This->m_pAllocator;\r
- IMemAllocator_AddRef(pAllocator);\r
- This->m_pAllocator = pAllocator;\r
-\r
- if (pOldAllocator != NULL) {\r
- SAFE_RELEASE(pOldAllocator);\r
- }\r
-\r
- This->m_bReadOnly = bReadOnly;\r
-\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCMemInputPin_GetAllocatorRequirements(\r
- IMemInputPin *iface,\r
- ALLOCATOR_PROPERTIES *pProps)\r
-{\r
- return E_NOTIMPL;\r
-}\r
-\r
-static STDMETHODIMP HWCMemInputPin_Receive(IMemInputPin *iface,\r
- IMediaSample *pSample)\r
-{\r
- HWCInPin *This = impl_from_IMemInputPin(iface);\r
-\r
- if (pSample == NULL) {\r
- ERR("pSample is NULL\n");\r
- return E_POINTER;\r
- }\r
- if (This->m_pCallback != NULL) {\r
- HRESULT hr;\r
- BYTE *pBuffer = NULL;\r
- DWORD dwSize = 0;\r
- dwSize = IMediaSample_GetSize(pSample);\r
- hr = IMediaSample_GetPointer(pSample, &pBuffer);\r
- if (FAILED(hr)) {\r
- ERR("Receive function : "\r
- "failed to IMediaSample_GetPointer, 0x%ld\n", hr);\r
- return hr;\r
- }\r
- hr = IGrabCallback_Grab(This->m_pCallback, dwSize, pBuffer);\r
- if (FAILED(hr)) {\r
- ERR("Receive function : failed to IGrabCallback_Grab, 0x%ld\n",\r
- hr);\r
- return hr;\r
- }\r
- }\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCMemInputPin_ReceiveMultiple(IMemInputPin *iface,\r
- IMediaSample **pSamples,\r
- long nSamples,\r
- long *nSamplesProcessed)\r
-{\r
- HRESULT hr = S_OK;\r
-\r
- if (pSamples == NULL) {\r
- return E_POINTER;\r
- }\r
-\r
- *nSamplesProcessed = 0;\r
-\r
- while (nSamples-- > 0) {\r
- hr = IMemInputPin_Receive(iface, pSamples[*nSamplesProcessed]);\r
- if (hr != S_OK) {\r
- break;\r
- }\r
- (*nSamplesProcessed)++;\r
- }\r
- return hr;\r
-}\r
-\r
-static STDMETHODIMP HWCMemInputPin_ReceiveCanBlock(IMemInputPin *iface)\r
-{\r
- return S_FALSE;\r
-}\r
-\r
-static STDMETHODIMP HWCPin_SetCallback(IPin *iface, IGrabCallback *pCaptureCB)\r
-{\r
- HWCInPin *This = impl_from_IPin(iface);\r
-\r
- if (pCaptureCB == NULL) {\r
- SAFE_RELEASE(This->m_pCallback);\r
- } else {\r
- This->m_pCallback = pCaptureCB;\r
- IGrabCallback_AddRef(This->m_pCallback);\r
- }\r
-\r
- return S_OK;\r
-}\r
-\r
-\r
-static IPinVtbl HWCPin_Vtbl = {\r
- HWCPin_QueryInterface,\r
- HWCPin_AddRef,\r
- HWCPin_Release,\r
- HWCPin_Connect,\r
- HWCPin_ReceiveConnection,\r
- HWCPin_Disconnect,\r
- HWCPin_ConnectedTo,\r
- HWCPin_ConnectionMediaType,\r
- HWCPin_QueryPinInfo,\r
- HWCPin_QueryDirection,\r
- HWCPin_QueryId,\r
- HWCPin_QueryAccept,\r
- HWCPin_EnumMediaTypes,\r
- HWCPin_QueryInternalConnections,\r
- HWCPin_EndOfStream,\r
- HWCPin_BeginFlush,\r
- HWCPin_EndFlush,\r
- HWCPin_NewSegment\r
-};\r
-\r
-static IMemInputPinVtbl HWCMemInputPin_Vtbl = {\r
- HWCMemInputPin_QueryInterface,\r
- HWCMemInputPin_AddRef,\r
- HWCMemInputPin_Release,\r
- HWCMemInputPin_GetAllocator,\r
- HWCMemInputPin_NotifyAllocator,\r
- HWCMemInputPin_GetAllocatorRequirements,\r
- HWCMemInputPin_Receive,\r
- HWCMemInputPin_ReceiveMultiple,\r
- HWCMemInputPin_ReceiveCanBlock\r
-};\r
-\r
-static STDMETHODIMP HWCInPin_Construct(IBaseFilter *pFilter, IPin **ppv)\r
-{\r
- HWCInPin *This = (HWCInPin *)g_malloc0(sizeof(HWCInPin));\r
-\r
- if (!This) {\r
- ERR("failed to HWCInPin_Construct, E_OUTOFMEMORY\n");\r
- return E_OUTOFMEMORY;\r
- }\r
-\r
- This->IPin_iface.lpVtbl = &HWCPin_Vtbl;\r
- This->IMemInputPin_iface.lpVtbl = &HWCMemInputPin_Vtbl;\r
- This->m_bReadOnly = FALSE;\r
- This->m_pCFilter = pFilter;\r
- This->m_pConnectedPin = NULL;\r
- This->m_pCallback = NULL;\r
- This->m_pAllocator = NULL;\r
- This->m_cRef = 1;\r
- This->SetGrabCallbackIF = HWCPin_SetCallback;\r
- *ppv = &This->IPin_iface;\r
-\r
- return S_OK;\r
-}\r
-\r
-/*\r
- * HWCEnumPins\r
- */\r
-\r
-typedef struct HWCEnumPins {\r
- IEnumPins IEnumPins_iface;\r
- IBaseFilter *m_pFilter;\r
- int m_nPos;\r
- long m_cRef;\r
-} HWCEnumPins;\r
-\r
-static inline HWCEnumPins *impl_from_IEnumPins(IEnumPins *iface)\r
-{\r
- return CONTAINING_RECORD(iface, HWCEnumPins, IEnumPins_iface);\r
-}\r
-\r
-static STDMETHODIMP HWCEnumPins_QueryInterface(IEnumPins *iface,\r
- REFIID riid, void **ppv)\r
-{\r
- if (ppv == NULL) {\r
- return E_POINTER;\r
- }\r
-\r
- if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumPins)) {\r
- *ppv = iface;\r
- } else {\r
- *ppv = NULL;\r
- return E_NOINTERFACE;\r
- }\r
-\r
- IEnumPins_AddRef(iface);\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP_(ULONG) HWCEnumPins_AddRef(IEnumPins *iface)\r
-{\r
- HWCEnumPins *This = impl_from_IEnumPins(iface);\r
-\r
- return InterlockedIncrement(&This->m_cRef);\r
-}\r
-\r
-static STDMETHODIMP_(ULONG) HWCEnumPins_Release(IEnumPins *iface)\r
-{\r
- HWCEnumPins *This = impl_from_IEnumPins(iface);\r
-\r
- if (InterlockedDecrement(&This->m_cRef) == 0) {\r
- if (This->m_pFilter) {\r
- SAFE_RELEASE(This->m_pFilter);\r
- }\r
- This->m_nPos = 0;\r
- g_free((void *)This);\r
- This = NULL;\r
- return 0;\r
- }\r
- return This->m_cRef;\r
-}\r
-\r
-static STDMETHODIMP HWCEnumPins_Next(IEnumPins *iface, ULONG cPins,\r
- IPin **ppPins, ULONG *pcFetched)\r
-{\r
- ULONG fetched;\r
- HWCEnumPins *This = impl_from_IEnumPins(iface);\r
-\r
- if (ppPins == NULL) {\r
- return E_POINTER;\r
- }\r
-\r
- if (This->m_nPos < 1 && cPins > 0) {\r
- IPin *pPin;\r
- IBaseFilter_FindPin(This->m_pFilter, HWCPinName, &pPin);\r
- *ppPins = pPin;\r
- fetched = 1;\r
- This->m_nPos++;\r
- } else {\r
- fetched = 0;\r
- }\r
-\r
- if (pcFetched != NULL) {\r
- *pcFetched = fetched;\r
- }\r
-\r
- return (fetched == cPins) ? S_OK : S_FALSE;\r
-}\r
-\r
-static STDMETHODIMP HWCEnumPins_Skip(IEnumPins *iface, ULONG cPins)\r
-{\r
- HWCEnumPins *This = impl_from_IEnumPins(iface);\r
- This->m_nPos += cPins;\r
- return (This->m_nPos >= 1) ? S_FALSE : S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCEnumPins_Reset(IEnumPins *iface)\r
-{\r
- HWCEnumPins *This = impl_from_IEnumPins(iface);\r
- This->m_nPos = 0;\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCEnumPins_Construct(IBaseFilter *pFilter,\r
- int nPos, IEnumPins **ppv);\r
-\r
-static STDMETHODIMP HWCEnumPins_Clone(IEnumPins *iface, IEnumPins **ppEnum)\r
-{\r
- HWCEnumPins *This = impl_from_IEnumPins(iface);\r
-\r
- if (ppEnum == NULL) {\r
- return E_POINTER;\r
- }\r
-\r
- HWCEnumPins_Construct(This->m_pFilter, This->m_nPos, ppEnum);\r
- if (*ppEnum == NULL) {\r
- ERR("failed to HWCEnumPins_Construct in clone, E_OUTOFMEMORY\n");\r
- return E_OUTOFMEMORY;\r
- }\r
-\r
- return S_OK;\r
-}\r
-\r
-static IEnumPinsVtbl HWCEnumPins_Vtbl = {\r
- HWCEnumPins_QueryInterface,\r
- HWCEnumPins_AddRef,\r
- HWCEnumPins_Release,\r
- HWCEnumPins_Next,\r
- HWCEnumPins_Skip,\r
- HWCEnumPins_Reset,\r
- HWCEnumPins_Clone\r
-};\r
-\r
-\r
-static STDMETHODIMP HWCEnumPins_Construct(IBaseFilter *pFilter,\r
- int nPos, IEnumPins **ppv)\r
-{\r
- HWCEnumPins *This = (HWCEnumPins *)g_malloc0(sizeof(HWCEnumPins));\r
-\r
- if (!This) {\r
- ERR("failed to HWCEnumPins_Construct, E_OUTOFMEMORY\n");\r
- return E_OUTOFMEMORY;\r
- }\r
-\r
- This->IEnumPins_iface.lpVtbl = &HWCEnumPins_Vtbl;\r
- This->m_pFilter = pFilter;\r
- if (This->m_pFilter) {\r
- IBaseFilter_AddRef(This->m_pFilter);\r
- }\r
- This->m_cRef = 1;\r
- This->m_nPos = nPos;\r
- *ppv = &This->IEnumPins_iface;\r
-\r
- return S_OK;\r
-}\r
-\r
-/*\r
- * HWCFilter\r
- */\r
-\r
-typedef struct HWCFilter {\r
- IBaseFilter IBaseFilter_iface;\r
- IPin *m_pPin;\r
- IFilterGraph *m_pFilterGraph;\r
- FILTER_STATE m_state;\r
- long m_cRef;\r
-} HWCFilter;\r
-\r
-static inline HWCFilter *impl_from_IBaseFilter(IBaseFilter *iface)\r
-{\r
- return CONTAINING_RECORD(iface, HWCFilter, IBaseFilter_iface);\r
-}\r
-\r
-static STDMETHODIMP HWCFilter_QueryInterface(IBaseFilter *iface,\r
- REFIID riid, void **ppv)\r
-{\r
- if (IsEqualIID(riid, &IID_IUnknown)) {\r
- *ppv = (IUnknown *)iface;\r
- } else if (IsEqualIID(riid, &IID_IPersist)) {\r
- *ppv = (IPersist *)iface;\r
- } else if (IsEqualIID(riid, &IID_IMediaFilter)) {\r
- *ppv = (IMediaFilter *)iface;\r
- } else if (IsEqualIID(riid, &IID_IBaseFilter)) {\r
- *ppv = (IBaseFilter *)iface;\r
- } else {\r
- *ppv = NULL;\r
- return E_NOINTERFACE;\r
- }\r
-\r
- IBaseFilter_AddRef(iface);\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP_(ULONG) HWCFilter_AddRef(IBaseFilter *iface)\r
-{\r
- HWCFilter *This = impl_from_IBaseFilter(iface);\r
-\r
- return InterlockedIncrement(&This->m_cRef);\r
-}\r
-\r
-static STDMETHODIMP_(ULONG) HWCFilter_Release(IBaseFilter *iface)\r
-{\r
- HWCFilter *This = impl_from_IBaseFilter(iface);\r
-\r
- if (InterlockedDecrement(&This->m_cRef) == 0) {\r
- if (This->m_pPin) {\r
- SAFE_RELEASE(This->m_pPin);\r
- }\r
- g_free((void *)This);\r
- This = NULL;\r
- return 0;\r
- }\r
- return This->m_cRef;\r
-}\r
-\r
-static STDMETHODIMP HWCFilter_GetClassID(IBaseFilter *iface, CLSID *pClsID)\r
-{\r
- if (pClsID == NULL) {\r
- return E_POINTER;\r
- }\r
- return E_NOTIMPL;\r
-}\r
-\r
-static STDMETHODIMP HWCFilter_GetState(IBaseFilter *iface, DWORD dwMSecs,\r
- FILTER_STATE *State)\r
-{\r
- HWCFilter *This = impl_from_IBaseFilter(iface);\r
- *State = This->m_state;\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCFilter_SetSyncSource(IBaseFilter *iface,\r
- IReferenceClock *pClock)\r
-{\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCFilter_GetSyncSource(IBaseFilter *iface,\r
- IReferenceClock **pClock)\r
-{\r
- *pClock = NULL;\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCFilter_Stop(IBaseFilter *iface)\r
-{\r
- HWCFilter *This = impl_from_IBaseFilter(iface);\r
-\r
- IPin_EndFlush(This->m_pPin);\r
- This->m_state = State_Stopped;\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCFilter_Pause(IBaseFilter *iface)\r
-{\r
- HWCFilter *This = impl_from_IBaseFilter(iface);\r
- This->m_state = State_Paused;\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCFilter_Run(IBaseFilter *iface, REFERENCE_TIME tStart)\r
-{\r
- HWCFilter *This = impl_from_IBaseFilter(iface);\r
-\r
- if (This->m_state == State_Stopped) {\r
- HRESULT hr;\r
- hr = IBaseFilter_Pause(iface);\r
- if (FAILED(hr)) {\r
- ERR("HWCFilter_Run : Failed to IBaseFilter_Pause, ret=0xld%\n", hr);\r
- return hr;\r
- }\r
- }\r
-\r
- This->m_state = State_Running;\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCFilter_EnumPins(IBaseFilter *iface, IEnumPins **ppEnum)\r
-{\r
- if (ppEnum == NULL) {\r
- return E_POINTER;\r
- }\r
-\r
- HWCEnumPins_Construct(iface, 0, ppEnum);\r
- return *ppEnum == NULL ? E_OUTOFMEMORY : S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCFilter_FindPin(IBaseFilter *iface, LPCWSTR Id,\r
- IPin **ppPin)\r
-{\r
- HWCFilter *This = impl_from_IBaseFilter(iface);\r
-\r
- if (ppPin == NULL) {\r
- return E_POINTER;\r
- }\r
-\r
- if (memcmp((void *)Id, (void *)HWCPinName, sizeof(HWCPinName))) {\r
- return VFW_E_NOT_FOUND;\r
- }\r
-\r
- if (!This->m_pPin) {\r
- HWCInPin_Construct(iface, &This->m_pPin);\r
- }\r
- *ppPin = This->m_pPin;\r
-\r
- IPin_AddRef(This->m_pPin);\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCFilter_QueryFilterInfo(IBaseFilter *iface,\r
- FILTER_INFO *pInfo)\r
-{\r
- HWCFilter *This = impl_from_IBaseFilter(iface);\r
-\r
- if (pInfo == NULL) {\r
- return E_POINTER;\r
- }\r
-\r
- memcpy((void *)pInfo->achName,\r
- (void *)HWCFilterName,\r
- sizeof(HWCFilterName));\r
- pInfo->pGraph = This->m_pFilterGraph;\r
- if (This->m_pFilterGraph) {\r
- IFilterGraph_AddRef(This->m_pFilterGraph);\r
- }\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCFilter_JoinFilterGraph(IBaseFilter *iface,\r
- IFilterGraph *pGraph,\r
- LPCWSTR pName)\r
-{\r
- HWCFilter *This = impl_from_IBaseFilter(iface);\r
-\r
- This->m_pFilterGraph = pGraph;\r
- return S_OK;\r
-}\r
-\r
-static STDMETHODIMP HWCFilter_QueryVendorInfo(IBaseFilter *iface,\r
- LPWSTR *pVendorInfo)\r
-{\r
- return E_NOTIMPL;\r
-}\r
-\r
-static IBaseFilterVtbl HWCFilter_Vtbl = {\r
- HWCFilter_QueryInterface,\r
- HWCFilter_AddRef,\r
- HWCFilter_Release,\r
- HWCFilter_GetClassID,\r
- HWCFilter_Stop,\r
- HWCFilter_Pause,\r
- HWCFilter_Run,\r
- HWCFilter_GetState,\r
- HWCFilter_SetSyncSource,\r
- HWCFilter_GetSyncSource,\r
- HWCFilter_EnumPins,\r
- HWCFilter_FindPin,\r
- HWCFilter_QueryFilterInfo,\r
- HWCFilter_JoinFilterGraph,\r
- HWCFilter_QueryVendorInfo\r
-};\r
-\r
-static STDMETHODIMP HWCFilter_Construct(IBaseFilter **ppv)\r
-{\r
- HWCFilter *This = (HWCFilter *)g_malloc0(sizeof(HWCFilter));\r
-\r
- if (!This) {\r
- ERR("failed to HWCFilter_Construct, E_OUTOFMEMORY\n");\r
- return E_OUTOFMEMORY;\r
- }\r
-\r
- This->IBaseFilter_iface.lpVtbl = &HWCFilter_Vtbl;\r
- This->m_pFilterGraph = NULL;\r
- This->m_state = State_Stopped;\r
- This->m_cRef = 1;\r
- HWCInPin_Construct(&This->IBaseFilter_iface, &This->m_pPin);\r
- *ppv = &This->IBaseFilter_iface;\r
-\r
- return S_OK;\r
-}\r
-\r
-/**********************************************************\r
- *\r
- * Virtual device implementations\r
- *\r
- **********************************************************/\r
-\r
-\r
-/*\r
- * Declaration global variables for Win32 COM Interfaces\r
- */\r
-IGraphBuilder *g_pGB ;\r
-ICaptureGraphBuilder2 *g_pCGB;\r
-IMediaControl *g_pMediaControl;\r
-\r
-IPin *g_pOutputPin;\r
-IPin *g_pInputPin;\r
-IBaseFilter *g_pDstFilter;\r
-IBaseFilter *g_pSrcFilter;\r
-\r
-IGrabCallback *g_pCallback;\r
-\r
-/* V4L2 defines copy from videodev2.h */\r
-#define V4L2_CTRL_FLAG_SLIDER 0x0020\r
-\r
-#define V4L2_CTRL_CLASS_USER 0x00980000\r
-#define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900)\r
-#define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE+0)\r
-#define V4L2_CID_CONTRAST (V4L2_CID_BASE+1)\r
-#define V4L2_CID_SATURATION (V4L2_CID_BASE+2)\r
-#define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27)\r
-\r
-#define V4L2_PIX_FMT_YUYV MAKEFOURCC('Y', 'U', 'Y', 'V') /* 16 YUV 4:2:2 */\r
-#define V4L2_PIX_FMT_YUV420 MAKEFOURCC('Y', 'U', '1', '2') /* 12 YUV 4:2:0 */\r
-#define V4L2_PIX_FMT_YVU420 MAKEFOURCC('Y', 'V', '1', '2') /* 12 YVU 4:2:0 */\r
-#define V4L2_PIX_FMT_RGB24 MAKEFOURCC('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */\r
-\r
-typedef struct tagMaruCamConvertPixfmt {\r
- uint32_t fmt; /* fourcc */\r
- uint32_t bpp; /* bits per pixel, 0 for compressed formats */\r
- uint32_t needs_conversion;\r
-} MaruCamConvertPixfmt;\r
-\r
-static MaruCamConvertPixfmt supported_dst_pixfmts[] = {\r
- { V4L2_PIX_FMT_YUYV, 16, 0 },\r
- { V4L2_PIX_FMT_YUV420, 12, 0 },\r
- { V4L2_PIX_FMT_YVU420, 12, 0 },\r
-};\r
-\r
-typedef struct tagMaruCamConvertFrameInfo {\r
- uint32_t width;\r
- uint32_t height;\r
-} MaruCamConvertFrameInfo;\r
-\r
-static MaruCamConvertFrameInfo supported_dst_frames[] = {\r
- { 640, 480 },\r
- { 352, 288 },\r
- { 320, 240 },\r
- { 176, 144 },\r
- { 160, 120 },\r
-};\r
-\r
-#define MARUCAM_CTRL_VALUE_MAX 20\r
-#define MARUCAM_CTRL_VALUE_MIN 1\r
-#define MARUCAM_CTRL_VALUE_MID 10\r
-#define MARUCAM_CTRL_VALUE_STEP 1\r
-\r
-struct marucam_qctrl {\r
- uint32_t id;\r
- uint32_t hit;\r
- long min;\r
- long max;\r
- long step;\r
- long init_val;\r
-};\r
-\r
-static struct marucam_qctrl qctrl_tbl[] = {\r
- { V4L2_CID_BRIGHTNESS, 0, },\r
- { V4L2_CID_CONTRAST, 0, },\r
- { V4L2_CID_SATURATION, 0, },\r
- { V4L2_CID_SHARPNESS, 0, },\r
-};\r
-\r
-static MaruCamState *g_state;\r
-\r
-static uint32_t ready_count;\r
-static uint32_t cur_fmt_idx;\r
-static uint32_t cur_frame_idx;\r
-static void *grab_buf;\r
-static uint32_t g_dwSrcFmt;\r
-\r
-\r
-/*\r
- * Helper functions - converting image formats, converting values\r
- */\r
-\r
-static uint32_t get_bytesperline(uint32_t pixfmt, uint32_t width)\r
-{\r
- uint32_t bytesperline;\r
-\r
- switch (pixfmt) {\r
- case V4L2_PIX_FMT_YUV420:\r
- case V4L2_PIX_FMT_YVU420:\r
- bytesperline = (width * 12) >> 3;\r
- break;\r
- case V4L2_PIX_FMT_YUYV:\r
- default:\r
- bytesperline = width * 2;\r
- break;\r
- }\r
-\r
- return bytesperline;\r
-}\r
-\r
-static uint32_t get_sizeimage(uint32_t pixfmt, uint32_t width, uint32_t height)\r
-{\r
- return get_bytesperline(pixfmt, width) * height;\r
-}\r
-\r
-void yuyv_to_yuv420(const unsigned char *src, unsigned char *dest,\r
- uint32_t width, uint32_t height, uint32_t yvu);\r
-void rgb24_to_yuv420(const unsigned char *src, unsigned char *dest,\r
- uint32_t width, uint32_t height, uint32_t yvu);\r
-void rgb24_to_yuyv(unsigned char *src, unsigned char *dest,\r
- uint32_t width, uint32_t height);\r
-void yuv420_to_yvu420(unsigned char *src, unsigned char *dest,\r
- uint32_t width, uint32_t height);\r
-void yuv420_to_yuyv(unsigned char *src, unsigned char *dest,\r
- uint32_t width, uint32_t height);\r
-\r
-static long value_convert_from_guest(long min, long max, long value)\r
-{\r
- double rate = 0.0;\r
- long dist = 0, ret = 0;\r
-\r
- dist = max - min;\r
-\r
- if (dist < MARUCAM_CTRL_VALUE_MAX) {\r
- rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;\r
- ret = min + (int32_t)(value / rate);\r
- } else {\r
- rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;\r
- ret = min + (int32_t)(rate * value);\r
- }\r
- return ret;\r
-}\r
-\r
-static long value_convert_to_guest(long min, long max, long value)\r
-{\r
- double rate = 0.0;\r
- long dist = 0, ret = 0;\r
-\r
- dist = max - min;\r
-\r
- if (dist < MARUCAM_CTRL_VALUE_MAX) {\r
- rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;\r
- ret = (int32_t)((double)(value - min) * rate);\r
- } else {\r
- rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;\r
- ret = (int32_t)((double)(value - min) / rate);\r
- }\r
-\r
- return ret;\r
-}\r
-\r
-/*\r
- * Callback function for grab frames\r
- */\r
-static STDMETHODIMP marucam_device_callbackfn(ULONG dwSize, BYTE *pBuffer)\r
-{\r
- void *tmp_buf;\r
- uint32_t width, height, fmt, imgsize;\r
-\r
- width = supported_dst_frames[cur_frame_idx].width;\r
- height = supported_dst_frames[cur_frame_idx].height;\r
- fmt = supported_dst_pixfmts[cur_fmt_idx].fmt;\r
- imgsize = get_sizeimage(fmt, width, height);\r
-\r
- if (imgsize > (uint32_t)dwSize) {\r
- ERR("Image size is mismatched\n");\r
- return E_FAIL;\r
- }\r
-\r
- switch (g_dwSrcFmt) {\r
- case V4L2_PIX_FMT_YUYV:\r
- switch (fmt) {\r
- case V4L2_PIX_FMT_YUV420:\r
- yuyv_to_yuv420(pBuffer, grab_buf, width, height, 0);\r
- break;\r
- case V4L2_PIX_FMT_YVU420:\r
- yuyv_to_yuv420(pBuffer, grab_buf, width, height, 1);\r
- break;\r
- case V4L2_PIX_FMT_YUYV:\r
- memcpy(grab_buf, (void *)pBuffer, (size_t)dwSize);\r
- break;\r
- default:\r
- ERR("Invalid pixel format\n");\r
- return E_FAIL;\r
- }\r
- break;\r
- case V4L2_PIX_FMT_RGB24:\r
- switch (fmt) {\r
- case V4L2_PIX_FMT_YUV420:\r
- rgb24_to_yuv420(pBuffer, grab_buf, width, height, 0);\r
- break;\r
- case V4L2_PIX_FMT_YVU420:\r
- rgb24_to_yuv420(pBuffer, grab_buf, width, height, 1);\r
- break;\r
- case V4L2_PIX_FMT_YUYV:\r
- rgb24_to_yuyv(pBuffer, grab_buf, width, height);\r
- break;\r
- default:\r
- ERR("Invalid pixel format\n");\r
- return E_FAIL;\r
- }\r
- break;\r
- case V4L2_PIX_FMT_YUV420:\r
- switch (fmt) {\r
- case V4L2_PIX_FMT_YUV420:\r
- memcpy(grab_buf, (void *)pBuffer, (size_t)dwSize);\r
- break;\r
- case V4L2_PIX_FMT_YVU420:\r
- yuv420_to_yvu420(pBuffer, grab_buf, width, height);\r
- break;\r
- case V4L2_PIX_FMT_YUYV:\r
- yuv420_to_yuyv(pBuffer, grab_buf, width, height);\r
- break;\r
- default:\r
- ERR("Invalid pixel format\n");\r
- return E_FAIL;\r
- }\r
- break;\r
- default:\r
- ERR("Invalid pixel format\n");\r
- return E_FAIL;\r
- }\r
-\r
- qemu_mutex_lock(&g_state->thread_mutex);\r
- if (g_state->streamon) {\r
- if (ready_count < MARUCAM_SKIPFRAMES) {\r
- /* skip a frame cause first some frame are distorted */\r
- ++ready_count;\r
- TRACE("skip %d frame\n", ready_count);\r
- qemu_mutex_unlock(&g_state->thread_mutex);\r
- return S_OK;\r
- }\r
- if (g_state->req_frame == 0) {\r
- TRACE("there is no request\n");\r
- qemu_mutex_unlock(&g_state->thread_mutex);\r
- return S_OK;\r
- }\r
- tmp_buf = g_state->vaddr + g_state->buf_size * (g_state->req_frame - 1);\r
- memcpy(tmp_buf, grab_buf, g_state->buf_size);\r
- g_state->req_frame = 0; /* clear request */\r
- g_state->isr |= 0x01; /* set a flag of rasing a interrupt */\r
- qemu_bh_schedule(g_state->tx_bh);\r
- }\r
- qemu_mutex_unlock(&g_state->thread_mutex);\r
- return S_OK;\r
-}\r
-\r
-/*\r
- * Internal functions for manipulate interfaces\r
- */\r
-\r
-static STDMETHODIMP_(void) CloseInterfaces(void)\r
-{\r
- if (g_pMediaControl) {\r
- g_pMediaControl->lpVtbl->Stop(g_pMediaControl);\r
- }\r
-\r
- if (g_pOutputPin) {\r
- g_pOutputPin->lpVtbl->Disconnect(g_pOutputPin);\r
- }\r
-\r
- SAFE_RELEASE(g_pGB);\r
- SAFE_RELEASE(g_pCGB);\r
- SAFE_RELEASE(g_pMediaControl);\r
- SAFE_RELEASE(g_pOutputPin);\r
- SAFE_RELEASE(g_pInputPin);\r
- SAFE_RELEASE(g_pDstFilter);\r
- SAFE_RELEASE(g_pSrcFilter);\r
- SAFE_RELEASE(g_pCallback);\r
-}\r
-\r
-static STDMETHODIMP_(void) DeleteMediaType(AM_MEDIA_TYPE *pmt)\r
-{\r
- if (pmt == NULL) {\r
- return;\r
- }\r
-\r
- if (pmt->cbFormat != 0) {\r
- CoTaskMemFree((PVOID)pmt->pbFormat);\r
- pmt->cbFormat = 0;\r
- pmt->pbFormat = NULL;\r
- }\r
- if (pmt->pUnk != NULL) {\r
- pmt->pUnk->lpVtbl->Release(pmt->pUnk);\r
- pmt->pUnk = NULL;\r
- }\r
-\r
- CoTaskMemFree((PVOID)pmt);\r
-}\r
-\r
-static STDMETHODIMP GetPin(IBaseFilter *pFilter,\r
- PIN_DIRECTION PinDir, IPin **ppPin)\r
-{\r
- HRESULT hr;\r
- IEnumPins *pEnum = NULL;\r
- IPin *pPin = NULL;\r
-\r
- if (ppPin == NULL) {\r
- return E_POINTER;\r
- }\r
-\r
- hr = pFilter->lpVtbl->EnumPins(pFilter, &pEnum);\r
- if (FAILED(hr)) {\r
- return hr;\r
- }\r
-\r
- while (pEnum->lpVtbl->Next(pEnum, 1, &pPin, 0) == S_OK) {\r
- PIN_DIRECTION PinDirThis;\r
- hr = pPin->lpVtbl->QueryDirection(pPin, &PinDirThis);\r
- if (FAILED(hr)) {\r
- SAFE_RELEASE(pPin);\r
- SAFE_RELEASE(pEnum);\r
- return hr;\r
- }\r
- if (PinDir == PinDirThis) {\r
- *ppPin = pPin;\r
- SAFE_RELEASE(pEnum);\r
- return S_OK;\r
- }\r
- SAFE_RELEASE(pPin);\r
- }\r
-\r
- SAFE_RELEASE(pEnum);\r
- return S_FALSE;\r
-}\r
-\r
-static STDMETHODIMP GraphBuilder_Init(void)\r
-{\r
- HRESULT hr;\r
-\r
- hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC,\r
- &IID_IGraphBuilder, (void **)&g_pGB);\r
- if (FAILED(hr)) {\r
- ERR("Failed to create instance of GraphBuilder, 0x%x\n", hr);\r
- return hr;\r
- }\r
-\r
- hr = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC,\r
- &IID_ICaptureGraphBuilder2, (void **)&g_pCGB);\r
- if (FAILED(hr)) {\r
- ERR("Failed to create instance of CaptureGraphBuilder2, 0x%x\n", hr);\r
- return hr;\r
- }\r
-\r
- hr = g_pCGB->lpVtbl->SetFiltergraph(g_pCGB, g_pGB);\r
- if (FAILED(hr)) {\r
- ERR("Failed to SetFiltergraph, 0x%x\n", hr);\r
- return hr;\r
- }\r
-\r
- hr = g_pGB->lpVtbl->QueryInterface(g_pGB, &IID_IMediaControl,\r
- (void **)&g_pMediaControl);\r
- if (FAILED(hr)) {\r
- ERR("Failed to QueryInterface for IMediaControl, 0x%x\n", hr);\r
- return hr;\r
- }\r
-\r
- hr = HWCGrabCallback_Construct(&g_pCallback);\r
- if (g_pCallback == NULL) {\r
- hr = E_OUTOFMEMORY;\r
- }\r
-\r
- hr = ((HWCGrabCallback *)g_pCallback)->SetCallback(g_pCallback,\r
- (CallbackFn)marucam_device_callbackfn);\r
-\r
- return hr;\r
-}\r
-\r
-static STDMETHODIMP BindSourceFilter(void)\r
-{\r
- HRESULT hr;\r
- ICreateDevEnum *pCreateDevEnum = NULL;\r
- IEnumMoniker *pEnumMK = NULL;\r
- IMoniker *pMoniKer;\r
-\r
- hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,\r
- &IID_ICreateDevEnum,\r
- (void **)&pCreateDevEnum);\r
- if (FAILED(hr)) {\r
- ERR("Failed to create instance of CreateDevEnum, 0x%x\n", hr);\r
- return hr;\r
- }\r
-\r
- hr = pCreateDevEnum->lpVtbl->CreateClassEnumerator(pCreateDevEnum,\r
- &CLSID_VideoInputDeviceCategory,\r
- &pEnumMK, 0);\r
- if (FAILED(hr)) {\r
- ERR("Failed to get VideoInputDeviceCategory, 0x%x\n", hr);\r
- SAFE_RELEASE(pCreateDevEnum);\r
- return hr;\r
- }\r
-\r
- if (!pEnumMK) {\r
- ERR("ClassEnumerator moniker is NULL\n");\r
- SAFE_RELEASE(pCreateDevEnum);\r
- return E_FAIL;\r
- }\r
- pEnumMK->lpVtbl->Reset(pEnumMK);\r
-\r
- hr = pEnumMK->lpVtbl->Next(pEnumMK, 1, &pMoniKer, NULL);\r
- if (hr == S_FALSE) {\r
- hr = E_FAIL;\r
- }\r
- if (SUCCEEDED(hr)) {\r
- IPropertyBag *pBag = NULL;\r
- hr = pMoniKer->lpVtbl->BindToStorage(pMoniKer, 0, 0,\r
- &IID_IPropertyBag,\r
- (void **)&pBag);\r
- if (SUCCEEDED(hr)) {\r
- VARIANT var;\r
- var.vt = VT_BSTR;\r
- hr = pBag->lpVtbl->Read(pBag, L"FriendlyName", &var, NULL);\r
- if (hr == NOERROR) {\r
- hr = pMoniKer->lpVtbl->BindToObject(pMoniKer, NULL, NULL,\r
- &IID_IBaseFilter,\r
- (void **)&g_pSrcFilter);\r
- if (FAILED(hr)) {\r
- ERR("Counldn't bind moniker to filter object!!\n");\r
- } else {\r
- g_pSrcFilter->lpVtbl->AddRef(g_pSrcFilter);\r
- }\r
- SysFreeString(var.bstrVal);\r
- }\r
- SAFE_RELEASE(pBag);\r
- }\r
- SAFE_RELEASE(pMoniKer);\r
- }\r
-\r
- if (SUCCEEDED(hr)) {\r
- hr = g_pGB->lpVtbl->AddFilter(g_pGB, g_pSrcFilter, L"Video Capture");\r
- if (hr != S_OK && hr != S_FALSE) {\r
- ERR("Counldn't add Video Capture filter to our graph!\n");\r
- SAFE_RELEASE(g_pSrcFilter);\r
- }\r
- }\r
- SAFE_RELEASE(pEnumMK);\r
- SAFE_RELEASE(pCreateDevEnum);\r
-\r
- return hr;\r
-}\r
-\r
-static STDMETHODIMP BindTargetFilter(void)\r
-{\r
- HRESULT hr;\r
- hr = HWCFilter_Construct(&g_pDstFilter);\r
-\r
- if (SUCCEEDED(hr) && g_pDstFilter) {\r
- hr = g_pGB->lpVtbl->AddFilter(g_pGB, g_pDstFilter, L"HWCFilter");\r
- if (FAILED(hr)) {\r
- ERR("Counldn't add HWCFilterr to our graph!\n");\r
- SAFE_RELEASE(g_pDstFilter);\r
- }\r
- }\r
- return hr;\r
-}\r
-\r
-static STDMETHODIMP ConnectFilters(void)\r
-{\r
- HRESULT hr;\r
-\r
- hr = GetPin(g_pSrcFilter, PINDIR_OUTPUT , &g_pOutputPin);\r
- if (FAILED(hr)) {\r
- ERR("Failed to get output pin. 0x%x\n", hr);\r
- return hr;\r
- }\r
-\r
- hr = GetPin(g_pDstFilter, PINDIR_INPUT , &g_pInputPin);\r
- if (FAILED(hr)) {\r
- ERR("Failed to get input pin. 0x%x\n", hr);\r
- return hr;\r
- }\r
-\r
- hr = g_pGB->lpVtbl->Connect(g_pGB, g_pOutputPin, g_pInputPin);\r
- if (FAILED(hr)) {\r
- ERR("Failed to connect pins. 0x%x\n", hr);\r
- }\r
- return hr;\r
-}\r
-\r
-static STDMETHODIMP DisconnectPins(void)\r
-{\r
- HRESULT hr;\r
-\r
- hr = g_pGB->lpVtbl->Disconnect(g_pGB, g_pOutputPin);\r
- if (FAILED(hr)) {\r
- ERR("Failed to disconnect output pin. 0x%x\n", hr);\r
- return hr;\r
- }\r
-\r
- hr = g_pGB->lpVtbl->Disconnect(g_pGB, g_pInputPin);\r
- if (FAILED(hr)) {\r
- ERR("Failed to disconnect input pin. 0x%x\n", hr);\r
- }\r
-\r
- return hr;\r
-}\r
-\r
-static STDMETHODIMP RemoveFilters(void)\r
-{\r
- HRESULT hr;\r
-\r
- hr = g_pGB->lpVtbl->RemoveFilter(g_pGB, g_pSrcFilter);\r
- if (FAILED(hr)) {\r
- ERR("Failed to remove source filer. 0x%x\n", hr);\r
- return hr;\r
- }\r
-\r
- hr = g_pGB->lpVtbl->RemoveFilter(g_pGB, g_pDstFilter);\r
- if (FAILED(hr)) {\r
- ERR("Failed to remove destination filer. 0x%x\n", hr);\r
- }\r
-\r
- return hr;\r
-}\r
-\r
-/* default fps is 15 */\r
-#define MARUCAM_DEFAULT_FRAMEINTERVAL 666666\r
-\r
-static STDMETHODIMP SetFormat(uint32_t dwWidth, uint32_t dwHeight,\r
- uint32_t dwDstFmt, uint32_t *dwSrcFmt)\r
-{\r
- HRESULT hr;\r
- IAMStreamConfig *pSConfig;\r
- int iCount = 0, iSize = 0;\r
- DWORD dwYUY2 = MAKEFOURCC('Y', 'U', 'Y', '2');\r
- DWORD dwI420 = MAKEFOURCC('I', '4', '2', '0');\r
-\r
- if (dwSrcFmt == NULL) {\r
- ERR("invalid the source format pointer\n");\r
- return E_FAIL;\r
- }\r
-\r
- hr = g_pCGB->lpVtbl->FindInterface(g_pCGB, &PIN_CATEGORY_CAPTURE, 0,\r
- g_pSrcFilter, &IID_IAMStreamConfig,\r
- (void **)&pSConfig);\r
- if (FAILED(hr)) {\r
- ERR("failed to FindInterface method\n");\r
- return hr;\r
- }\r
-\r
- hr = pSConfig->lpVtbl->GetNumberOfCapabilities(pSConfig, &iCount, &iSize);\r
- if (FAILED(hr)) {\r
- ERR("failed to GetNumberOfCapabilities method\n");\r
- SAFE_RELEASE(pSConfig);\r
- return hr;\r
- }\r
-\r
- if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) {\r
- int iFormat = 0;\r
- for (iFormat = 0; iFormat < iCount; iFormat++) {\r
- VIDEO_STREAM_CONFIG_CAPS scc;\r
- AM_MEDIA_TYPE *pmtConfig;\r
-\r
- hr = pSConfig->lpVtbl->GetStreamCaps(pSConfig, iFormat,\r
- &pmtConfig, (BYTE *)&scc);\r
- if (hr == S_OK) {\r
- if (IsEqualIID(&pmtConfig->formattype, &FORMAT_VideoInfo)) {\r
- VIDEOINFOHEADER *pvi =\r
- (VIDEOINFOHEADER *)pmtConfig->pbFormat;\r
- if ((pvi->bmiHeader.biWidth == (LONG)dwWidth) &&\r
- (pvi->bmiHeader.biHeight == (LONG)dwHeight)) {\r
- if (pvi->bmiHeader.biCompression == dwYUY2) {\r
- *dwSrcFmt = V4L2_PIX_FMT_YUYV;\r
- } else if ((pvi->bmiHeader.biCompression == BI_RGB) &&\r
- (pvi->bmiHeader.biBitCount == 24)) {\r
- *dwSrcFmt = V4L2_PIX_FMT_RGB24;\r
- } else if (pvi->bmiHeader.biCompression == dwI420) {\r
- *dwSrcFmt = V4L2_PIX_FMT_YUV420;\r
- } else { /* not support format */\r
- DeleteMediaType(pmtConfig);\r
- continue;\r
- }\r
- /* use minimum FPS(maximum frameinterval)\r
- with non-VT system */\r
-#ifdef CONFIG_HAX\r
- if (!hax_enabled()) {\r
- pvi->AvgTimePerFrame =\r
- (REFERENCE_TIME)scc.MaxFrameInterval;\r
- } else {\r
- pvi->AvgTimePerFrame =\r
- (REFERENCE_TIME)MARUCAM_DEFAULT_FRAMEINTERVAL;\r
- }\r
-#else\r
- pvi->AvgTimePerFrame =\r
- (REFERENCE_TIME)scc.MaxFrameInterval;\r
-#endif\r
- hr = pSConfig->lpVtbl->SetFormat(pSConfig, pmtConfig);\r
- DeleteMediaType(pmtConfig);\r
- break;\r
- }\r
- }\r
- DeleteMediaType(pmtConfig);\r
- }\r
- }\r
- if (iFormat >= iCount) {\r
- ERR("Failed to Set format. "\r
- "Maybe connected webcam does not support the (%ldx%ld) "\r
- "resolution or image formats(YUY2, RGB24, I420).\n",\r
- dwWidth, dwHeight);\r
- hr = E_FAIL;\r
- }\r
- }\r
- SAFE_RELEASE(pSConfig);\r
- return hr;\r
-}\r
-\r
-static STDMETHODIMP QueryVideoProcAmp(long nProperty, long *pMin, long *pMax,\r
- long *pStep, long *pDefault)\r
-{\r
- HRESULT hr;\r
- long Flags;\r
- IAMVideoProcAmp *pProcAmp = NULL;\r
-\r
- hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter,\r
- &IID_IAMVideoProcAmp,\r
- (void **)&pProcAmp);\r
- if (FAILED(hr)) {\r
- return hr;\r
- }\r
-\r
- hr = pProcAmp->lpVtbl->GetRange(pProcAmp, nProperty, pMin, pMax,\r
- pStep, pDefault, &Flags);\r
-\r
- SAFE_RELEASE(pProcAmp);\r
- return hr;\r
-}\r
-\r
-static STDMETHODIMP GetVideoProcAmp(long nProperty, long *pValue)\r
-{\r
- HRESULT hr;\r
- long Flags;\r
- IAMVideoProcAmp *pProcAmp = NULL;\r
-\r
- hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter,\r
- &IID_IAMVideoProcAmp,\r
- (void **)&pProcAmp);\r
- if (FAILED(hr)) {\r
- return hr;\r
- }\r
-\r
- hr = pProcAmp->lpVtbl->Get(pProcAmp, nProperty, pValue, &Flags);\r
- if (FAILED(hr)) {\r
- ERR("Failed to get property for video\n");\r
- }\r
-\r
- SAFE_RELEASE(pProcAmp);\r
- return hr;\r
-}\r
-\r
-static STDMETHODIMP SetVideoProcAmp(long nProperty, long value)\r
-{\r
- HRESULT hr;\r
-\r
- IAMVideoProcAmp *pProcAmp = NULL;\r
- hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter,\r
- &IID_IAMVideoProcAmp,\r
- (void **)&pProcAmp);\r
- if (FAILED(hr)) {\r
- return hr;\r
- }\r
-\r
- hr = pProcAmp->lpVtbl->Set(pProcAmp, nProperty, value,\r
- VideoProcAmp_Flags_Manual);\r
- if (FAILED(hr)) {\r
- ERR("Failed to set property for video\n");\r
- }\r
- SAFE_RELEASE(pProcAmp);\r
- return hr;\r
-}\r
-\r
-static char *__wchar_to_char(const WCHAR *pwstr)\r
-{\r
- char *pstr = NULL;\r
- int len = 0;\r
-\r
- len = wcslen(pwstr) + 1;\r
- pstr = (char *)g_malloc0(sizeof(char) * len);\r
- wcstombs(pstr, pwstr, len + 1);\r
-\r
- return pstr;\r
-}\r
-\r
-int marucam_device_check(int log_flag)\r
-{\r
- struct timeval t1, t2;\r
- int ret = 0;\r
- char *device_name = NULL;\r
- HRESULT hr = E_FAIL;\r
- ICreateDevEnum *pCreateDevEnum = NULL;\r
- IGraphBuilder *pGB = NULL;\r
- ICaptureGraphBuilder2 *pCGB = NULL;\r
- IBaseFilter *pSrcFilter = NULL;\r
- IEnumMoniker *pEnumMK = NULL;\r
- IMoniker *pMoniKer = NULL;\r
- IAMStreamConfig *pSConfig = NULL;\r
- int iCount = 0, iSize = 0;\r
-\r
- gettimeofday(&t1, NULL);\r
- hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);\r
- if (FAILED(hr)) {\r
- fprintf(stdout, "[Webcam] failed to CoInitailizeEx\n");\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
-\r
- hr = CoCreateInstance(&CLSID_FilterGraph, NULL,\r
- CLSCTX_INPROC,\r
- &IID_IGraphBuilder,\r
- (void **)&pGB);\r
- if (FAILED(hr)) {\r
- fprintf(stdout, "[Webcam] Failed to create GraphBuilder, 0x%x\n", hr);\r
- CoUninitialize();\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
-\r
- hr = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL,\r
- CLSCTX_INPROC,\r
- &IID_ICaptureGraphBuilder2,\r
- (void **)&pCGB);\r
- if (FAILED(hr)) {\r
- fprintf(stdout,\r
- "[Webcam] Failed to create CaptureGraphBuilder2, 0x%x\n", hr);\r
- SAFE_RELEASE(pGB);\r
- CoUninitialize();\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
-\r
- hr = pCGB->lpVtbl->SetFiltergraph(pCGB, pGB);\r
- if (FAILED(hr)) {\r
- fprintf(stdout, "[Webcam] Failed to SetFiltergraph, 0x%x\n", hr);\r
- SAFE_RELEASE(pCGB);\r
- SAFE_RELEASE(pGB);\r
- CoUninitialize();\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
-\r
- hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL,\r
- CLSCTX_INPROC,\r
- &IID_ICreateDevEnum,\r
- (void **)&pCreateDevEnum);\r
- if (FAILED(hr)) {\r
- fprintf(stdout,\r
- "[Webcam] failed to create instance of CLSID_SystemDeviceEnum\n");\r
- SAFE_RELEASE(pCGB);\r
- SAFE_RELEASE(pGB);\r
- CoUninitialize();\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
-\r
- hr = pCreateDevEnum->lpVtbl->CreateClassEnumerator(pCreateDevEnum,\r
- &CLSID_VideoInputDeviceCategory, &pEnumMK, 0);\r
- if (FAILED(hr)) {\r
- fprintf(stdout, "[Webcam] failed to create class enumerator\n");\r
- SAFE_RELEASE(pCreateDevEnum);\r
- SAFE_RELEASE(pCGB);\r
- SAFE_RELEASE(pGB);\r
- CoUninitialize();\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
-\r
- if (!pEnumMK) {\r
- fprintf(stdout, "[Webcam] class enumerator is NULL!!\n");\r
- SAFE_RELEASE(pCreateDevEnum);\r
- SAFE_RELEASE(pCGB);\r
- SAFE_RELEASE(pGB);\r
- CoUninitialize();\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
- pEnumMK->lpVtbl->Reset(pEnumMK);\r
-\r
- hr = pEnumMK->lpVtbl->Next(pEnumMK, 1, &pMoniKer, NULL);\r
- if (FAILED(hr) || (hr == S_FALSE)) {\r
- fprintf(stdout, "[Webcam] enum moniker returns a invalid value.\n");\r
- SAFE_RELEASE(pEnumMK);\r
- SAFE_RELEASE(pCreateDevEnum);\r
- SAFE_RELEASE(pCGB);\r
- SAFE_RELEASE(pGB);\r
- CoUninitialize();\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
-\r
- IPropertyBag *pBag = NULL;\r
- hr = pMoniKer->lpVtbl->BindToStorage(pMoniKer, 0, 0,\r
- &IID_IPropertyBag,\r
- (void **)&pBag);\r
- if (FAILED(hr)) {\r
- fprintf(stdout, "[Webcam] failed to bind to storage.\n");\r
- SAFE_RELEASE(pEnumMK);\r
- SAFE_RELEASE(pCreateDevEnum);\r
- SAFE_RELEASE(pCGB);\r
- SAFE_RELEASE(pGB);\r
- CoUninitialize();\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- } else {\r
- VARIANT var;\r
- var.vt = VT_BSTR;\r
- hr = pBag->lpVtbl->Read(pBag, L"FriendlyName", &var, NULL);\r
- if (hr == S_OK) {\r
- ret = 1;\r
- if (!log_flag) {\r
- SysFreeString(var.bstrVal);\r
- SAFE_RELEASE(pBag);\r
- SAFE_RELEASE(pMoniKer);\r
- SAFE_RELEASE(pEnumMK);\r
- SAFE_RELEASE(pCreateDevEnum);\r
- SAFE_RELEASE(pCGB);\r
- SAFE_RELEASE(pGB);\r
- CoUninitialize();\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
- device_name = __wchar_to_char(var.bstrVal);\r
- fprintf(stdout, "[Webcam] Device name : %s\n", device_name);\r
- g_free(device_name);\r
- hr = pMoniKer->lpVtbl->BindToObject(pMoniKer, NULL, NULL,\r
- &IID_IBaseFilter,\r
- (void **)&pSrcFilter);\r
- if (FAILED(hr)) {\r
- fprintf(stdout,\r
- "[Webcam] Counldn't bind moniker to filter object!!\n");\r
- SysFreeString(var.bstrVal);\r
- SAFE_RELEASE(pBag);\r
- SAFE_RELEASE(pMoniKer);\r
- SAFE_RELEASE(pEnumMK);\r
- SAFE_RELEASE(pCreateDevEnum);\r
- SAFE_RELEASE(pCGB);\r
- SAFE_RELEASE(pGB);\r
- CoUninitialize();\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- } else {\r
- pSrcFilter->lpVtbl->AddRef(pSrcFilter);\r
- }\r
- SysFreeString(var.bstrVal);\r
- }\r
- SAFE_RELEASE(pBag);\r
- }\r
- SAFE_RELEASE(pMoniKer);\r
-\r
- hr = pGB->lpVtbl->AddFilter(pGB, pSrcFilter, L"Video Capture");\r
- if (hr != S_OK && hr != S_FALSE) {\r
- fprintf(stdout,\r
- "[Webcam] Counldn't add Video Capture filter to our graph!\n");\r
- SAFE_RELEASE(pSrcFilter);\r
- SAFE_RELEASE(pEnumMK);\r
- SAFE_RELEASE(pCreateDevEnum);\r
- SAFE_RELEASE(pCGB);\r
- SAFE_RELEASE(pGB);\r
- CoUninitialize();\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
-\r
- hr = pCGB->lpVtbl->FindInterface(pCGB, &PIN_CATEGORY_CAPTURE, 0,\r
- pSrcFilter, &IID_IAMStreamConfig,\r
- (void **)&pSConfig);\r
- if (FAILED(hr)) {\r
- fprintf(stdout, "[Webcam] failed to FindInterface method\n");\r
- SAFE_RELEASE(pSrcFilter);\r
- SAFE_RELEASE(pEnumMK);\r
- SAFE_RELEASE(pCreateDevEnum);\r
- SAFE_RELEASE(pCGB);\r
- SAFE_RELEASE(pGB);\r
- CoUninitialize();\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
-\r
- hr = pSConfig->lpVtbl->GetNumberOfCapabilities(pSConfig, &iCount, &iSize);\r
- if (FAILED(hr)) {\r
- fprintf(stdout, "[Webcam] failed to GetNumberOfCapabilities method\n");\r
- SAFE_RELEASE(pSConfig);\r
- SAFE_RELEASE(pSrcFilter);\r
- SAFE_RELEASE(pEnumMK);\r
- SAFE_RELEASE(pCreateDevEnum);\r
- SAFE_RELEASE(pCGB);\r
- SAFE_RELEASE(pGB);\r
- CoUninitialize();\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
- return ret;\r
- }\r
-\r
- if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) {\r
- int iFormat = 0;\r
- for (iFormat = 0; iFormat < iCount; iFormat++) {\r
- VIDEO_STREAM_CONFIG_CAPS scc;\r
- AM_MEDIA_TYPE *pmtConfig;\r
-\r
- hr = pSConfig->lpVtbl->GetStreamCaps(pSConfig, iFormat, &pmtConfig,\r
- (BYTE *)&scc);\r
- if (hr == S_OK) {\r
- if (IsEqualIID(&pmtConfig->formattype, &FORMAT_VideoInfo)) {\r
- VIDEOINFOHEADER *pvi =\r
- (VIDEOINFOHEADER *)pmtConfig->pbFormat;\r
- if (pvi->bmiHeader.biCompression == BI_RGB) {\r
- fprintf(stdout, "[Webcam] RGB BitCount: %d, %ux%u\n",\r
- pvi->bmiHeader.biBitCount,\r
- pvi->bmiHeader.biWidth,\r
- pvi->bmiHeader.biHeight);\r
- } else {\r
- fprintf(stdout,\r
- "[Webcam] PixelFormat: %c%c%c%c, %ux%u\n",\r
- (char)(pvi->bmiHeader.biCompression),\r
- (char)(pvi->bmiHeader.biCompression >> 8),\r
- (char)(pvi->bmiHeader.biCompression >> 16),\r
- (char)(pvi->bmiHeader.biCompression >> 24),\r
- pvi->bmiHeader.biWidth,\r
- pvi->bmiHeader.biHeight);\r
- }\r
- }\r
- DeleteMediaType(pmtConfig);\r
- }\r
- }\r
- }\r
-\r
- hr = pGB->lpVtbl->RemoveFilter(pGB, pSrcFilter);\r
- if (FAILED(hr)) {\r
- fprintf(stdout, "[Webcam] Failed to remove source filer. 0x%x\n", hr);\r
- }\r
-\r
- SAFE_RELEASE(pSConfig);\r
- SAFE_RELEASE(pSrcFilter);\r
- SAFE_RELEASE(pCGB);\r
- SAFE_RELEASE(pGB);\r
- SAFE_RELEASE(pEnumMK);\r
- SAFE_RELEASE(pCreateDevEnum);\r
- CoUninitialize();\r
- gettimeofday(&t2, NULL);\r
- fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",\r
- t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);\r
-\r
- return ret;\r
-}\r
-\r
-/* MARUCAM_CMD_INIT */\r
-void marucam_device_init(MaruCamState *state)\r
-{\r
- g_state = state;\r
-}\r
-\r
-void marucam_device_exit(MaruCamState *state)\r
-{\r
-}\r
-\r
-/* MARUCAM_CMD_OPEN */\r
-void marucam_device_open(MaruCamState *state)\r
-{\r
- HRESULT hr;\r
- uint32_t dwHeight, dwWidth, dwDstFmt;\r
- MaruCamParam *param = state->param;\r
- param->top = 0;\r
-\r
- hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);\r
- if (FAILED(hr)) {\r
- ERR("CoInitailizeEx\n");\r
- ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
-\r
- hr = GraphBuilder_Init();\r
- if (FAILED(hr)) {\r
- ERR("GraphBuilder_Init\n");\r
- DisconnectPins();\r
- RemoveFilters();\r
- CloseInterfaces();\r
- CoUninitialize();\r
- param->errCode = EINVAL;\r
- ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);\r
- return;\r
- }\r
-\r
- hr = BindSourceFilter();\r
- if (FAILED(hr)) {\r
- ERR("BindSourceFilter\n");\r
- DisconnectPins();\r
- RemoveFilters();\r
- CloseInterfaces();\r
- CoUninitialize();\r
- param->errCode = EINVAL;\r
- ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);\r
- return;\r
- }\r
-\r
- hr = BindTargetFilter();\r
- if (FAILED(hr)) {\r
- ERR("BindTargetFilter\n");\r
- DisconnectPins();\r
- RemoveFilters();\r
- CloseInterfaces();\r
- CoUninitialize();\r
- param->errCode = EINVAL;\r
- ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);\r
- return;\r
- }\r
-\r
- hr = ConnectFilters();\r
- if (FAILED(hr)) {\r
- ERR("ConnectFilters\n");\r
- DisconnectPins();\r
- RemoveFilters();\r
- CloseInterfaces();\r
- CoUninitialize();\r
- param->errCode = EINVAL;\r
- ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);\r
- return;\r
- }\r
-\r
- cur_frame_idx = 0;\r
- cur_fmt_idx = 0;\r
-\r
- dwHeight = supported_dst_frames[cur_frame_idx].height;\r
- dwWidth = supported_dst_frames[cur_frame_idx].width;\r
- dwDstFmt = supported_dst_pixfmts[cur_fmt_idx].fmt;\r
- hr = SetFormat(dwWidth, dwHeight, dwDstFmt, &g_dwSrcFmt);\r
- if (hr != S_OK) {\r
- ERR("failed to Set default values\n");\r
- DisconnectPins();\r
- RemoveFilters();\r
- CloseInterfaces();\r
- CoUninitialize();\r
- param->errCode = EINVAL;\r
- ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);\r
- return;\r
- }\r
-\r
- INFO("Opened\n");\r
- return;\r
-}\r
-\r
-/* MARUCAM_CMD_CLOSE */\r
-void marucam_device_close(MaruCamState *state)\r
-{\r
- MaruCamParam *param = state->param;\r
- param->top = 0;\r
-\r
- DisconnectPins();\r
- RemoveFilters();\r
- CloseInterfaces();\r
- CoUninitialize();\r
- INFO("Closed\n");\r
-}\r
-\r
-/* MARUCAM_CMD_START_PREVIEW */\r
-void marucam_device_start_preview(MaruCamState *state)\r
-{\r
- HRESULT hr;\r
- uint32_t pixfmt, width, height;\r
- MaruCamParam *param = state->param;\r
- param->top = 0;\r
-\r
- ready_count = 0;\r
- width = supported_dst_frames[cur_frame_idx].width;\r
- height = supported_dst_frames[cur_frame_idx].height;\r
- pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;\r
- state->buf_size = get_sizeimage(pixfmt, width, height);\r
-\r
- INFO("Pixfmt(%c%c%c%c), W:H(%d:%d), buf size(%u)\n",\r
- (char)(pixfmt), (char)(pixfmt >> 8),\r
- (char)(pixfmt >> 16), (char)(pixfmt >> 24),\r
- width, height, state->buf_size);\r
- INFO("Starting preview\n");\r
-\r
- assert(g_pCallback != NULL);\r
- hr = ((HWCInPin *)g_pInputPin)->SetGrabCallbackIF(g_pInputPin,\r
- g_pCallback);\r
- if (FAILED(hr)) {\r
- ERR("Failed to set IGrabCallback interface.\n");\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
-\r
- if (grab_buf) {\r
- g_free(grab_buf);\r
- grab_buf = NULL;\r
- }\r
- grab_buf = (void *)g_malloc0(state->buf_size);\r
- if (grab_buf == NULL) {\r
- param->errCode = ENOMEM;\r
- return;\r
- }\r
-\r
- hr = g_pMediaControl->lpVtbl->Run(g_pMediaControl);\r
- if (FAILED(hr)) {\r
- ERR("Failed to run media control. hr=0x%x\n", hr);\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
-\r
- qemu_mutex_lock(&state->thread_mutex);\r
- state->streamon = 1;\r
- qemu_mutex_unlock(&state->thread_mutex);\r
-\r
- INFO("Streaming on ......\n");\r
-}\r
-\r
-/* MARUCAM_CMD_STOP_PREVIEW */\r
-void marucam_device_stop_preview(MaruCamState *state)\r
-{\r
- HRESULT hr;\r
- MaruCamParam *param = state->param;\r
- param->top = 0;\r
-\r
- INFO("...... Streaming off\n");\r
- qemu_mutex_lock(&state->thread_mutex);\r
- state->streamon = 0;\r
- qemu_mutex_unlock(&state->thread_mutex);\r
-\r
- hr = ((HWCInPin *)g_pInputPin)->SetGrabCallbackIF(g_pInputPin, NULL);\r
- if (FAILED(hr)) {\r
- ERR("Failed to set IGrabCallback interface.\n");\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
-\r
- hr = g_pMediaControl->lpVtbl->Stop(g_pMediaControl);\r
- if (FAILED(hr)) {\r
- ERR("Failed to stop media control.\n");\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
-\r
- if (grab_buf) {\r
- g_free(grab_buf);\r
- grab_buf = NULL;\r
- }\r
- state->buf_size = 0;\r
-\r
- INFO("Stopping preview\n");\r
-}\r
-\r
-/* MARUCAM_CMD_S_PARAM */\r
-void marucam_device_s_param(MaruCamState *state)\r
-{\r
- MaruCamParam *param = state->param;\r
-\r
- /* We use default FPS of the webcam */\r
- param->top = 0;\r
-}\r
-\r
-/* MARUCAM_CMD_G_PARAM */\r
-void marucam_device_g_param(MaruCamState *state)\r
-{\r
- MaruCamParam *param = state->param;\r
-\r
- /* We use default FPS of the webcam\r
- * return a fixed value on guest ini file (1/30).\r
- */\r
- param->top = 0;\r
- param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */\r
- param->stack[1] = 1; /* numerator */\r
- param->stack[2] = 30; /* denominator */\r
-}\r
-\r
-/* MARUCAM_CMD_S_FMT */\r
-void marucam_device_s_fmt(MaruCamState *state)\r
-{\r
- uint32_t width, height, pixfmt, pidx, fidx;\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- width = param->stack[0];\r
- height = param->stack[1];\r
- pixfmt = param->stack[2];\r
-\r
- for (fidx = 0; fidx < ARRAY_SIZE(supported_dst_frames); fidx++) {\r
- if ((supported_dst_frames[fidx].width == width) &&\r
- (supported_dst_frames[fidx].height == height)) {\r
- break;\r
- }\r
- }\r
- if (fidx == ARRAY_SIZE(supported_dst_frames)) {\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
- for (pidx = 0; pidx < ARRAY_SIZE(supported_dst_pixfmts); pidx++) {\r
- if (supported_dst_pixfmts[pidx].fmt == pixfmt) {\r
- break;\r
- }\r
- }\r
- if (pidx == ARRAY_SIZE(supported_dst_pixfmts)) {\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
-\r
- if ((supported_dst_frames[cur_frame_idx].width != width) &&\r
- (supported_dst_frames[cur_frame_idx].height != height)) {\r
- HRESULT hr = SetFormat(width, height, pixfmt, &g_dwSrcFmt);\r
- if (FAILED(hr)) {\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
- }\r
-\r
- cur_frame_idx = fidx;\r
- cur_fmt_idx = pidx;\r
-\r
- pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;\r
- width = supported_dst_frames[cur_frame_idx].width;\r
- height = supported_dst_frames[cur_frame_idx].height;\r
-\r
- param->stack[0] = width;\r
- param->stack[1] = height;\r
- param->stack[2] = 1; /* V4L2_FIELD_NONE */\r
- param->stack[3] = pixfmt;\r
- param->stack[4] = get_bytesperline(pixfmt, width);\r
- param->stack[5] = get_sizeimage(pixfmt, width, height);\r
- param->stack[6] = 0;\r
- param->stack[7] = 0;\r
-\r
- TRACE("Set format...\n");\r
-}\r
-\r
-/* MARUCAM_CMD_G_FMT */\r
-void marucam_device_g_fmt(MaruCamState *state)\r
-{\r
- uint32_t width, height, pixfmt;\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt;\r
- width = supported_dst_frames[cur_frame_idx].width;\r
- height = supported_dst_frames[cur_frame_idx].height;\r
-\r
- param->stack[0] = width;\r
- param->stack[1] = height;\r
- param->stack[2] = 1; /* V4L2_FIELD_NONE */\r
- param->stack[3] = pixfmt;\r
- param->stack[4] = get_bytesperline(pixfmt, width);\r
- param->stack[5] = get_sizeimage(pixfmt, width, height);\r
- param->stack[6] = 0;\r
- param->stack[7] = 0;\r
-\r
- TRACE("Get format...\n");\r
-}\r
-\r
-void marucam_device_try_fmt(MaruCamState *state)\r
-{\r
- uint32_t width, height, pixfmt, i;\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- width = param->stack[0];\r
- height = param->stack[1];\r
- pixfmt = param->stack[2];\r
-\r
- for (i = 0; i < ARRAY_SIZE(supported_dst_frames); i++) {\r
- if ((supported_dst_frames[i].width == width) &&\r
- (supported_dst_frames[i].height == height)) {\r
- break;\r
- }\r
- }\r
- if (i == ARRAY_SIZE(supported_dst_frames)) {\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
- for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {\r
- if (supported_dst_pixfmts[i].fmt == pixfmt) {\r
- break;\r
- }\r
- }\r
- if (i == ARRAY_SIZE(supported_dst_pixfmts)) {\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
-\r
- param->stack[0] = width;\r
- param->stack[1] = height;\r
- param->stack[2] = 1; /* V4L2_FIELD_NONE */\r
- param->stack[3] = pixfmt;\r
- param->stack[4] = get_bytesperline(pixfmt, width);\r
- param->stack[5] = get_sizeimage(pixfmt, width, height);\r
- param->stack[6] = 0;\r
- param->stack[7] = 0;\r
-}\r
-\r
-void marucam_device_enum_fmt(MaruCamState *state)\r
-{\r
- uint32_t index;\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- index = param->stack[0];\r
-\r
- if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
- param->stack[1] = 0; /* flags = NONE */\r
- param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */\r
- /* set description */\r
- switch (supported_dst_pixfmts[index].fmt) {\r
- case V4L2_PIX_FMT_YUYV:\r
- memcpy(¶m->stack[3], "YUYV", 32);\r
- break;\r
- case V4L2_PIX_FMT_YUV420:\r
- memcpy(¶m->stack[3], "YU12", 32);\r
- break;\r
- case V4L2_PIX_FMT_YVU420:\r
- memcpy(¶m->stack[3], "YV12", 32);\r
- break;\r
- default:\r
- ERR("Invalid pixel format\n");\r
- param->errCode = EINVAL;\r
- break;\r
- }\r
-}\r
-\r
-void marucam_device_qctrl(MaruCamState *state)\r
-{\r
- HRESULT hr;\r
- uint32_t id, i;\r
- long property, min, max, step, def_val, set_val;\r
- char name[32] = {0,};\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- id = param->stack[0];\r
-\r
- switch (id) {\r
- case V4L2_CID_BRIGHTNESS:\r
- TRACE("V4L2_CID_BRIGHTNESS\n");\r
- property = VideoProcAmp_Brightness;\r
- memcpy((void *)name, (void *)"brightness", 32);\r
- i = 0;\r
- break;\r
- case V4L2_CID_CONTRAST:\r
- TRACE("V4L2_CID_CONTRAST\n");\r
- property = VideoProcAmp_Contrast;\r
- memcpy((void *)name, (void *)"contrast", 32);\r
- i = 1;\r
- break;\r
- case V4L2_CID_SATURATION:\r
- TRACE("V4L2_CID_SATURATION\n");\r
- property = VideoProcAmp_Saturation;\r
- memcpy((void *)name, (void *)"saturation", 32);\r
- i = 2;\r
- break;\r
- case V4L2_CID_SHARPNESS:\r
- TRACE("V4L2_CID_SHARPNESS\n");\r
- property = VideoProcAmp_Sharpness;\r
- memcpy((void *)name, (void *)"sharpness", 32);\r
- i = 3;\r
- break;\r
- default:\r
- ERR("Invalid control ID\n");\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
- hr = QueryVideoProcAmp(property, &min, &max, &step, &def_val);\r
- if (FAILED(hr)) {\r
- param->errCode = EINVAL;\r
- ERR("failed to query video controls [HRESULT : 0x%x]\n", hr);\r
- return;\r
- } else {\r
- qctrl_tbl[i].hit = 1;\r
- qctrl_tbl[i].min = min;\r
- qctrl_tbl[i].max = max;\r
- qctrl_tbl[i].step = step;\r
- qctrl_tbl[i].init_val = def_val;\r
-\r
- if ((qctrl_tbl[i].min + qctrl_tbl[i].max) == 0) {\r
- set_val = 0;\r
- } else {\r
- set_val = (qctrl_tbl[i].min + qctrl_tbl[i].max) / 2;\r
- }\r
- hr = SetVideoProcAmp(property, set_val);\r
- if (FAILED(hr)) {\r
- param->errCode = EINVAL;\r
- ERR("failed to set video control value, [HRESULT : 0x%x]\n", hr);\r
- return;\r
- }\r
- }\r
-\r
- param->stack[0] = id;\r
- param->stack[1] = MARUCAM_CTRL_VALUE_MIN; /* minimum */\r
- param->stack[2] = MARUCAM_CTRL_VALUE_MAX; /* maximum */\r
- param->stack[3] = MARUCAM_CTRL_VALUE_STEP; /* step */\r
- param->stack[4] = MARUCAM_CTRL_VALUE_MID; /* default_value */\r
- param->stack[5] = V4L2_CTRL_FLAG_SLIDER;\r
- /* name field setting */\r
- memcpy(¶m->stack[6], (void *)name, sizeof(name)/sizeof(name[0]));\r
-}\r
-\r
-void marucam_device_s_ctrl(MaruCamState *state)\r
-{\r
- HRESULT hr;\r
- uint32_t i;\r
- long property, set_val;\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
-\r
- switch (param->stack[0]) {\r
- case V4L2_CID_BRIGHTNESS:\r
- i = 0;\r
- property = VideoProcAmp_Brightness;\r
- break;\r
- case V4L2_CID_CONTRAST:\r
- i = 1;\r
- property = VideoProcAmp_Contrast;\r
- break;\r
- case V4L2_CID_SATURATION:\r
- i = 2;\r
- property = VideoProcAmp_Saturation;\r
- break;\r
- case V4L2_CID_SHARPNESS:\r
- i = 3;\r
- property = VideoProcAmp_Sharpness;\r
- break;\r
- default:\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
- set_val = value_convert_from_guest(qctrl_tbl[i].min,\r
- qctrl_tbl[i].max, (long)param->stack[1]);\r
- hr = SetVideoProcAmp(property, set_val);\r
- if (FAILED(hr)) {\r
- param->errCode = EINVAL;\r
- ERR("failed to set video control value, [HRESULT : 0x%x]\n", hr);\r
- return;\r
- }\r
-}\r
-\r
-void marucam_device_g_ctrl(MaruCamState *state)\r
-{\r
- HRESULT hr;\r
- uint32_t i;\r
- long property, get_val;\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- switch (param->stack[0]) {\r
- case V4L2_CID_BRIGHTNESS:\r
- i = 0;\r
- property = VideoProcAmp_Brightness;\r
- break;\r
- case V4L2_CID_CONTRAST:\r
- i = 1;\r
- property = VideoProcAmp_Contrast;\r
- break;\r
- case V4L2_CID_SATURATION:\r
- i = 2;\r
- property = VideoProcAmp_Saturation;\r
- break;\r
- case V4L2_CID_SHARPNESS:\r
- i = 3;\r
- property = VideoProcAmp_Sharpness;\r
- break;\r
- default:\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
-\r
- hr = GetVideoProcAmp(property, &get_val);\r
- if (FAILED(hr)) {\r
- param->errCode = EINVAL;\r
- ERR("failed to get video control value!!!, [HRESULT : 0x%x]\n", hr);\r
- return;\r
- }\r
- param->stack[0] = (uint32_t)value_convert_to_guest(qctrl_tbl[i].min,\r
- qctrl_tbl[i].max, get_val);\r
-}\r
-\r
-void marucam_device_enum_fsizes(MaruCamState *state)\r
-{\r
- uint32_t index, pixfmt, i;\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
- index = param->stack[0];\r
- pixfmt = param->stack[1];\r
-\r
- if (index >= ARRAY_SIZE(supported_dst_frames)) {\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
- for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {\r
- if (supported_dst_pixfmts[i].fmt == pixfmt) {\r
- break;\r
- }\r
- }\r
-\r
- if (i == ARRAY_SIZE(supported_dst_pixfmts)) {\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
-\r
- param->stack[0] = supported_dst_frames[index].width;\r
- param->stack[1] = supported_dst_frames[index].height;\r
-}\r
-\r
-void marucam_device_enum_fintv(MaruCamState *state)\r
-{\r
- MaruCamParam *param = state->param;\r
-\r
- param->top = 0;\r
-\r
- /* switch by index(param->stack[0]) */\r
- switch (param->stack[0]) {\r
- case 0:\r
- param->stack[1] = 30; /* denominator */\r
- break;\r
- default:\r
- param->errCode = EINVAL;\r
- return;\r
- }\r
- param->stack[0] = 1; /* numerator */\r
-}\r
-\r
-void yuyv_to_yuv420(const unsigned char *src, unsigned char *dest,\r
- uint32_t width, uint32_t height, uint32_t yvu)\r
-{\r
- uint32_t i, j;\r
- const unsigned char *src1;\r
- unsigned char *udest, *vdest;\r
-\r
- /* copy the Y values */\r
- src1 = src;\r
- for (i = 0; i < height; i++) {\r
- for (j = 0; j < width; j += 2) {\r
- *dest++ = src1[0];\r
- *dest++ = src1[2];\r
- src1 += 4;\r
- }\r
- }\r
-\r
- /* copy the U and V values */\r
- src++; /* point to V */\r
- src1 = src + width * 2; /* next line */\r
- if (yvu) {\r
- vdest = dest;\r
- udest = dest + width * height / 4;\r
- } else {\r
- udest = dest;\r
- vdest = dest + width * height / 4;\r
- }\r
- for (i = 0; i < height; i += 2) {\r
- for (j = 0; j < width; j += 2) {\r
- *udest++ = ((int) src[0] + src1[0]) / 2; /* U */\r
- *vdest++ = ((int) src[2] + src1[2]) / 2; /* V */\r
- src += 4;\r
- src1 += 4;\r
- }\r
- src = src1;\r
- src1 += width * 2;\r
- }\r
-}\r
-\r
-#define RGB2Y(r, g, b, y) \\r
- (y) = ((8453 * (r) + 16594 * (g) + 3223 * (b) + 524288) >> 15)\r
-\r
-#define RGB2UV(r, g, b, u, v) \\r
- do { \\r
- (u) = ((-4878 * (r) - 9578 * (g) + 14456 * (b) + 4210688) >> 15); \\r
- (v) = ((14456 * (r) - 12105 * (g) - 2351 * (b) + 4210688) >> 15); \\r
- } while (0)\r
-\r
-#define CLIP(color) \\r
- (unsigned char)(((color) > 0xFF) ? 0xff : (((color) < 0) ? 0 : (color)))\r
-\r
-void rgb24_to_yuv420(const unsigned char *src, unsigned char *dest,\r
- uint32_t width, uint32_t height, uint32_t yvu)\r
-{\r
- uint32_t x, y;\r
- unsigned char *udest, *vdest;\r
- uint32_t bytesperline = width * 3;\r
-\r
- /* Y */\r
- for (y = 0; y < height; y++) {\r
- for (x = 0; x < width; x++) {\r
- RGB2Y(src[2], src[1], src[0], *dest++);\r
- src += 3;\r
- }\r
- src += bytesperline - 3 * width;\r
- }\r
- src -= height * bytesperline;\r
-\r
- /* U + V */\r
- if (yvu) {\r
- vdest = dest;\r
- udest = dest + width * height / 4;\r
- } else {\r
- udest = dest;\r
- vdest = dest + width * height / 4;\r
- }\r
-\r
- for (y = 0; y < height / 2; y++) {\r
- for (x = 0; x < width / 2; x++) {\r
- uint32_t avg_src[3];\r
-\r
- avg_src[0] = (src[0] + src[3] + src[bytesperline] +\r
- src[bytesperline + 3]) / 4;\r
- avg_src[1] = (src[1] + src[4] + src[bytesperline + 1] +\r
- src[bytesperline + 4]) / 4;\r
- avg_src[2] = (src[2] + src[5] + src[bytesperline + 2] +\r
- src[bytesperline + 5]) / 4;\r
- RGB2UV(avg_src[2], avg_src[1], avg_src[0], *udest++, *vdest++);\r
- src += 6;\r
- }\r
- src += 2 * bytesperline - 3 * width;\r
- }\r
-}\r
-\r
-void rgb24_to_yuyv(unsigned char *src, unsigned char *dest,\r
- uint32_t width, uint32_t height)\r
-{\r
- uint32_t i = 0;\r
-\r
- for (i = 0; i < (width * height * 3); i = i + 6) {\r
- /* y */\r
- *dest++ = CLIP(0.299 * (src[i + 2] - 128) +\r
- 0.587 * (src[i + 1] - 128) +\r
- 0.114 * (src[i] - 128) + 128);\r
- /* u */\r
- *dest++ = CLIP(((-0.147 * (src[i + 2] - 128) -\r
- 0.289 * (src[i + 1] - 128) +\r
- 0.436 * (src[i] - 128) + 128) +\r
- (-0.147 * (src[i + 5] - 128) -\r
- 0.289 * (src[i + 4] - 128) +\r
- 0.436 * (src[i + 3] - 128) + 128)) / 2);\r
- /* y1 */\r
- *dest++ = CLIP(0.299 * (src[i + 5] - 128) +\r
- 0.587 * (src[i + 4] - 128) +\r
- 0.114 * (src[i + 3] - 128) + 128);\r
- /* v */\r
- *dest++ = CLIP(((0.615 * (src[i + 2] - 128) -\r
- 0.515 * (src[i + 1] - 128) -\r
- 0.100 * (src[i] - 128) + 128) +\r
- (0.615 * (src[i + 5] - 128) -\r
- 0.515 * (src[i + 4] - 128) -\r
- 0.100 * (src[i + 3] - 128) + 128)) / 2);\r
- }\r
-}\r
-\r
-void yuv420_to_yvu420(unsigned char *src, unsigned char *dest,\r
- uint32_t width, uint32_t height)\r
-{\r
- unsigned char *psrc_y, *pdst_y;\r
- unsigned char *psrc_u, *pdst_u;\r
- unsigned char *psrc_v, *pdst_v;\r
-\r
- psrc_y = src;\r
- psrc_u = psrc_y + (width * height);\r
- psrc_v = psrc_u + (width * height / 4);\r
-\r
- pdst_y = dest;\r
- pdst_v = pdst_y + (width * height);\r
- pdst_u = pdst_v + (width * height / 4);\r
-\r
- memcpy(pdst_y, psrc_y, width * height);\r
- memcpy(pdst_v, psrc_v, width * height / 4);\r
- memcpy(pdst_u, psrc_u, width * height / 4);\r
-}\r
-\r
-void yuv420_to_yuyv(unsigned char *src, unsigned char *dest,\r
- uint32_t width, uint32_t height)\r
-{\r
- unsigned char *py;\r
- unsigned char *pu;\r
- unsigned char *pv;\r
-\r
- uint32_t linesize = width * 2;\r
- uint32_t uvlinesize = width / 2;\r
- uint32_t offset = 0;\r
- uint32_t offset1 = 0;\r
- uint32_t offsety = 0;\r
- uint32_t offsety1 = 0;\r
- uint32_t offsetuv = 0;\r
- uint32_t h = 0;\r
- uint32_t w = 0;\r
- uint32_t wy = 0;\r
- uint32_t huv = 0;\r
- uint32_t wuv = 0;\r
-\r
- py = src;\r
- pu = py + (width * height);\r
- pv = pu + (width * height / 4);\r
-\r
- for (h = 0; h < height; h += 2) {\r
- wy = 0;\r
- wuv = 0;\r
- offset = h * linesize;\r
- offset1 = (h + 1) * linesize;\r
- offsety = h * width;\r
- offsety1 = (h + 1) * width;\r
- offsetuv = huv * uvlinesize;\r
-\r
- for (w = 0; w < linesize; w += 4) {\r
- /* y00 */\r
- dest[w + offset] = py[wy + offsety];\r
- /* u0 */\r
- dest[(w + 1) + offset] = pu[wuv + offsetuv];\r
- /* y01 */\r
- dest[(w + 2) + offset] = py[(wy + 1) + offsety];\r
- /* v0 */\r
- dest[(w + 3) + offset] = pv[wuv + offsetuv];\r
-\r
- /* y10 */\r
- dest[w + offset1] = py[wy + offsety1];\r
- /* u0 */\r
- dest[(w + 1) + offset1] = pu[wuv + offsetuv];\r
- /* y11 */\r
- dest[(w + 2) + offset1] = py[(wy + 1) + offsety1];\r
- /* v0 */\r
- dest[(w + 3) + offset1] = pv[wuv + offsetuv];\r
-\r
- wuv++;\r
- wy += 2;\r
- }\r
- huv++;\r
- }\r
-}\r
+/*
+ * 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 "maru_camera_common.h"
+#include "tizen/src/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_win32);
+
+/*
+ * 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)) {
+ fprintf(stdout, "[Webcam] failed to CoInitailizeEx\n");
+ gettimeofday(&t2, NULL);
+ fprintf(stdout, "[Webcam] 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)) {
+ fprintf(stdout, "[Webcam] Failed to create GraphBuilder, 0x%x\n", hr);
+ CoUninitialize();
+ gettimeofday(&t2, NULL);
+ fprintf(stdout, "[Webcam] 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)) {
+ fprintf(stdout,
+ "[Webcam] Failed to create CaptureGraphBuilder2, 0x%x\n", hr);
+ SAFE_RELEASE(pGB);
+ CoUninitialize();
+ gettimeofday(&t2, NULL);
+ fprintf(stdout, "[Webcam] 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)) {
+ fprintf(stdout, "[Webcam] Failed to SetFiltergraph, 0x%x\n", hr);
+ SAFE_RELEASE(pCGB);
+ SAFE_RELEASE(pGB);
+ CoUninitialize();
+ gettimeofday(&t2, NULL);
+ fprintf(stdout, "[Webcam] 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)) {
+ fprintf(stdout,
+ "[Webcam] failed to create instance of CLSID_SystemDeviceEnum\n");
+ SAFE_RELEASE(pCGB);
+ SAFE_RELEASE(pGB);
+ CoUninitialize();
+ gettimeofday(&t2, NULL);
+ fprintf(stdout, "[Webcam] 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)) {
+ fprintf(stdout, "[Webcam] failed to create class enumerator\n");
+ SAFE_RELEASE(pCreateDevEnum);
+ SAFE_RELEASE(pCGB);
+ SAFE_RELEASE(pGB);
+ CoUninitialize();
+ gettimeofday(&t2, NULL);
+ fprintf(stdout, "[Webcam] Elapsed time : %lu.%06lu\n",
+ t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+ return ret;
+ }
+
+ if (!pEnumMK) {
+ fprintf(stdout, "[Webcam] class enumerator is NULL!!\n");
+ SAFE_RELEASE(pCreateDevEnum);
+ SAFE_RELEASE(pCGB);
+ SAFE_RELEASE(pGB);
+ CoUninitialize();
+ gettimeofday(&t2, NULL);
+ fprintf(stdout, "[Webcam] 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)) {
+ fprintf(stdout, "[Webcam] enum moniker returns a invalid value.\n");
+ SAFE_RELEASE(pEnumMK);
+ SAFE_RELEASE(pCreateDevEnum);
+ SAFE_RELEASE(pCGB);
+ SAFE_RELEASE(pGB);
+ CoUninitialize();
+ gettimeofday(&t2, NULL);
+ fprintf(stdout, "[Webcam] 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)) {
+ fprintf(stdout, "[Webcam] failed to bind to storage.\n");
+ SAFE_RELEASE(pEnumMK);
+ SAFE_RELEASE(pCreateDevEnum);
+ SAFE_RELEASE(pCGB);
+ SAFE_RELEASE(pGB);
+ CoUninitialize();
+ gettimeofday(&t2, NULL);
+ fprintf(stdout, "[Webcam] 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);
+ fprintf(stdout, "[Webcam] 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);
+ fprintf(stdout, "[Webcam] Device name : %s\n", device_name);
+ g_free(device_name);
+ hr = pMoniKer->lpVtbl->BindToObject(pMoniKer, NULL, NULL,
+ &IID_IBaseFilter,
+ (void **)&pSrcFilter);
+ if (FAILED(hr)) {
+ fprintf(stdout,
+ "[Webcam] 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);
+ fprintf(stdout, "[Webcam] 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) {
+ fprintf(stdout,
+ "[Webcam] 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);
+ fprintf(stdout, "[Webcam] 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)) {
+ fprintf(stdout, "[Webcam] failed to FindInterface method\n");
+ SAFE_RELEASE(pSrcFilter);
+ SAFE_RELEASE(pEnumMK);
+ SAFE_RELEASE(pCreateDevEnum);
+ SAFE_RELEASE(pCGB);
+ SAFE_RELEASE(pGB);
+ CoUninitialize();
+ gettimeofday(&t2, NULL);
+ fprintf(stdout, "[Webcam] 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)) {
+ fprintf(stdout, "[Webcam] 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);
+ fprintf(stdout, "[Webcam] 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) {
+ fprintf(stdout, "[Webcam] RGB BitCount: %d, %ux%u\n",
+ pvi->bmiHeader.biBitCount,
+ pvi->bmiHeader.biWidth,
+ pvi->bmiHeader.biHeight);
+ } else {
+ fprintf(stdout,
+ "[Webcam] PixelFormat: %c%c%c%c, %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)) {
+ fprintf(stdout, "[Webcam] 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);
+ fprintf(stdout, "[Webcam] 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;
+ param->top = 0;
+
+ 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(¶m->stack[3], "YUYV", 32);
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ memcpy(¶m->stack[3], "YU12", 32);
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ memcpy(¶m->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(¶m->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;
+ unsigned char *udest, *vdest;
+ uint32_t bytesperline = width * 3;
+
+ /* Y */
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ RGB2Y(src[2], src[1], src[0], *dest++);
+ src += 3;
+ }
+ src += bytesperline - 3 * width;
+ }
+ src -= height * bytesperline;
+
+ /* U + V */
+ if (yvu) {
+ vdest = dest;
+ udest = dest + width * height / 4;
+ } else {
+ udest = dest;
+ vdest = dest + width * height / 4;
+ }
+
+ for (y = 0; y < height / 2; y++) {
+ for (x = 0; x < width / 2; x++) {
+ uint32_t avg_src[3];
+
+ avg_src[0] = (src[0] + src[3] + src[bytesperline] +
+ src[bytesperline + 3]) / 4;
+ avg_src[1] = (src[1] + src[4] + src[bytesperline + 1] +
+ src[bytesperline + 4]) / 4;
+ avg_src[2] = (src[2] + src[5] + src[bytesperline + 2] +
+ src[bytesperline + 5]) / 4;
+ RGB2UV(avg_src[2], avg_src[1], avg_src[0], *udest++, *vdest++);
+ src += 6;
+ }
+ src += 2 * bytesperline - 3 * width;
+ }
+}
+
+void rgb24_to_yuyv(unsigned char *src, unsigned char *dest,
+ uint32_t width, uint32_t height)
+{
+ uint32_t i = 0;
+
+ for (i = 0; i < (width * height * 3); i = i + 6) {
+ /* y */
+ *dest++ = CLIP(0.299 * (src[i + 2] - 128) +
+ 0.587 * (src[i + 1] - 128) +
+ 0.114 * (src[i] - 128) + 128);
+ /* u */
+ *dest++ = CLIP(((-0.147 * (src[i + 2] - 128) -
+ 0.289 * (src[i + 1] - 128) +
+ 0.436 * (src[i] - 128) + 128) +
+ (-0.147 * (src[i + 5] - 128) -
+ 0.289 * (src[i + 4] - 128) +
+ 0.436 * (src[i + 3] - 128) + 128)) / 2);
+ /* y1 */
+ *dest++ = CLIP(0.299 * (src[i + 5] - 128) +
+ 0.587 * (src[i + 4] - 128) +
+ 0.114 * (src[i + 3] - 128) + 128);
+ /* v */
+ *dest++ = CLIP(((0.615 * (src[i + 2] - 128) -
+ 0.515 * (src[i + 1] - 128) -
+ 0.100 * (src[i] - 128) + 128) +
+ (0.615 * (src[i + 5] - 128) -
+ 0.515 * (src[i + 4] - 128) -
+ 0.100 * (src[i + 3] - 128) + 128)) / 2);
+ }
+}
+
+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++;
+ }
+}