From: jinhyung.jo Date: Wed, 18 Mar 2015 05:43:50 +0000 (+0900) Subject: maru-camera: Rename files X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bc311cc486e45586959212cfae95787b7971f09e;p=sdk%2Femulator%2Fqemu.git maru-camera: Rename files Delete unnecessary postfix, like '_pci'. Integrate the format conversion utilities, separately implemented in Darwin & Win32. Change-Id: Ie71cc57c8ed7c9e74eb19afed2e55259b720151f Signed-off-by: Jinhyung Jo --- diff --git a/tizen/src/hw/pci/Makefile.objs b/tizen/src/hw/pci/Makefile.objs index 408a68c57b..506305e758 100644 --- a/tizen/src/hw/pci/Makefile.objs +++ b/tizen/src/hw/pci/Makefile.objs @@ -8,18 +8,17 @@ obj-$(CONFIG_VAAPI) += maru_brillcodec_vaapi.o obj-y += maru_brightness.o -obj-y += maru_camera_common_pci.o +obj-y += maru_camera.o ifdef CONFIG_LINUX -obj-y += maru_camera_linux_pci.o +obj-y += maru_camera_linux.o LIBS += -lv4l2 -lv4lconvert endif ifdef CONFIG_WIN32 -obj-y += maru_camera_win32_pci.o +obj-y += maru_camera_win32.o maru_camera_util.o LIBS += -lole32 -loleaut32 -luuid -lstrmiids endif ifdef CONFIG_DARWIN -obj-y += maru_camera_darwin_converter.o -obj-y += maru_camera_darwin_pci.o +obj-y += maru_camera_darwin.o maru_camera_util.o LIBS += -framework Foundation -framework SystemConfiguration LIBS += -framework Cocoa -framework QTKit -framework CoreVideo LIBS += -framework AppKit diff --git a/tizen/src/hw/pci/maru_camera.c b/tizen/src/hw/pci/maru_camera.c new file mode 100644 index 0000000000..112c2866b4 --- /dev/null +++ b/tizen/src/hw/pci/maru_camera.c @@ -0,0 +1,314 @@ +/* + * Common implementation of MARU Virtual Camera device by PCI bus. + * + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jinhyung Jo + * Sangho Park + * + * 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 +#include +#include +#include +#include +#include + +#include "qemu-common.h" +#include "qemu/main-loop.h" +#include "exec/cpu-common.h" + +#include "maru_camera.h" +#include "hw/maru_device_ids.h" +#include "debug_ch.h" + +MULTI_DEBUG_CHANNEL(tizen, camera); + +#define MARU_PCI_CAMERA_DEVICE_NAME "maru-camera" + +#define MARUCAM_MEM_SIZE (4 * 1024 * 1024) /* 4MB */ +#define MARUCAM_REG_SIZE (256) /* 64 * 4Byte */ + +/* + * I/O functions + */ +static inline uint32_t +marucam_mmio_read(void *opaque, hwaddr offset) +{ + uint32_t ret = 0; + MaruCamState *state = (MaruCamState *)opaque; + + switch (offset & 0xFF) { + case MARUCAM_CMD_ISR: + qemu_mutex_lock(&state->thread_mutex); + ret = state->isr; + if (ret != 0) { + pci_set_irq(&state->dev, 0); + state->isr = 0; + } + qemu_mutex_unlock(&state->thread_mutex); + break; + case MARUCAM_CMD_G_DATA: + ret = state->param->stack[state->param->top++]; + break; + case MARUCAM_CMD_OPEN: + case MARUCAM_CMD_CLOSE: + case MARUCAM_CMD_START_PREVIEW: + case MARUCAM_CMD_STOP_PREVIEW: + case MARUCAM_CMD_S_PARAM: + case MARUCAM_CMD_G_PARAM: + case MARUCAM_CMD_ENUM_FMT: + case MARUCAM_CMD_TRY_FMT: + case MARUCAM_CMD_S_FMT: + case MARUCAM_CMD_G_FMT: + case MARUCAM_CMD_QCTRL: + case MARUCAM_CMD_S_CTRL: + case MARUCAM_CMD_G_CTRL: + case MARUCAM_CMD_ENUM_FSIZES: + case MARUCAM_CMD_ENUM_FINTV: + ret = state->param->errCode; + state->param->errCode = 0; + break; + default: + ERR("Not supported command: 0x%x\n", offset); + ret = EINVAL; + break; + } + return ret; +} + +static inline void +marucam_mmio_write(void *opaque, hwaddr offset, uint32_t value) +{ + MaruCamState *state = (MaruCamState *)opaque; + + switch (offset & 0xFF) { + case MARUCAM_CMD_OPEN: + marucam_device_open(state); + break; + case MARUCAM_CMD_CLOSE: + marucam_device_close(state); + break; + case MARUCAM_CMD_START_PREVIEW: + marucam_device_start_preview(state); + break; + case MARUCAM_CMD_STOP_PREVIEW: + marucam_device_stop_preview(state); + memset(state->vaddr, 0, MARUCAM_MEM_SIZE); + break; + case MARUCAM_CMD_S_PARAM: + marucam_device_s_param(state); + break; + case MARUCAM_CMD_G_PARAM: + marucam_device_g_param(state); + break; + case MARUCAM_CMD_ENUM_FMT: + marucam_device_enum_fmt(state); + break; + case MARUCAM_CMD_TRY_FMT: + marucam_device_try_fmt(state); + break; + case MARUCAM_CMD_S_FMT: + marucam_device_s_fmt(state); + break; + case MARUCAM_CMD_G_FMT: + marucam_device_g_fmt(state); + break; + case MARUCAM_CMD_QCTRL: + marucam_device_qctrl(state); + break; + case MARUCAM_CMD_S_CTRL: + marucam_device_s_ctrl(state); + break; + case MARUCAM_CMD_G_CTRL: + marucam_device_g_ctrl(state); + break; + case MARUCAM_CMD_ENUM_FSIZES: + marucam_device_enum_fsizes(state); + break; + case MARUCAM_CMD_ENUM_FINTV: + marucam_device_enum_fintv(state); + break; + case MARUCAM_CMD_S_DATA: + state->param->stack[state->param->top++] = value; + break; + case MARUCAM_CMD_DATACLR: + memset(state->param, 0, sizeof(MaruCamParam)); + break; + case MARUCAM_CMD_REQFRAME: + qemu_mutex_lock(&state->thread_mutex); + state->req_frame = value + 1; + qemu_mutex_unlock(&state->thread_mutex); + break; + default: + ERR("Not supported command: 0x%x\n", offset); + break; + } +} + +static const MemoryRegionOps maru_camera_mmio_ops = { + .old_mmio = { + .read = { + marucam_mmio_read, + marucam_mmio_read, + marucam_mmio_read, + }, + .write = { + marucam_mmio_write, + marucam_mmio_write, + marucam_mmio_write, + }, + }, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +/* + * QEMU bottom half funtion + */ +static void marucam_tx_bh(void *opaque) +{ + MaruCamState *state = (MaruCamState *)opaque; + + qemu_mutex_lock(&state->thread_mutex); + if (state->isr) { + pci_set_irq(&state->dev, 1); + } + qemu_mutex_unlock(&state->thread_mutex); +} + +/* + * Initialization function + */ + +static int marucam_initfn(PCIDevice *dev) +{ + MaruCamState *s = DO_UPCAST(MaruCamState, dev, dev); + uint8_t *pci_conf = s->dev.config; + + /* Check available webcam + * If there is not one, you can't use the camera. + */ + if (!marucam_device_check(1)) { + s->initialized = false; + ERR("Failed to check the camera device, " + "You can *not* use the camera\n"); + return 0; + } + + pci_config_set_interrupt_pin(pci_conf, 0x03); + + memory_region_init_ram(&s->vram, OBJECT(s), "marucamera.ram", MARUCAM_MEM_SIZE, + &error_abort); + s->vaddr = memory_region_get_ram_ptr(&s->vram); + memset(s->vaddr, 0, MARUCAM_MEM_SIZE); + + memory_region_init_io(&s->mmio, OBJECT(s), + &maru_camera_mmio_ops, + s, + "maru-camera-mmio", + MARUCAM_REG_SIZE); + + pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); + pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio); + + /* for worker thread */ + s->param = (MaruCamParam *)g_malloc0(sizeof(MaruCamParam)); + qemu_cond_init(&s->thread_cond); + qemu_mutex_init(&s->thread_mutex); + + marucam_device_init(s); + + s->tx_bh = qemu_bh_new(marucam_tx_bh, s); + s->initialized = true; + INFO("initialize maru-camera device\n"); + + return 0; +} + +/* + * Termination function + */ +static void marucam_exitfn(PCIDevice *pci_dev) +{ + MaruCamState *s = + OBJECT_CHECK(MaruCamState, pci_dev, MARU_PCI_CAMERA_DEVICE_NAME); + + if (s->initialized) { + marucam_device_exit(s); + g_free(s->param); + qemu_cond_destroy(&s->thread_cond); + qemu_mutex_destroy(&s->thread_mutex); + } + + INFO("finalize maru-camera device\n"); +} + +static void marucam_resetfn(DeviceState *d) +{ + MaruCamState *s = (MaruCamState *)d; + + if (s->initialized) { + marucam_device_close(s); + qemu_mutex_lock(&s->thread_mutex); + s->isr = s->streamon = s->req_frame = s->buf_size = 0; + qemu_mutex_unlock(&s->thread_mutex); + memset(s->vaddr, 0, MARUCAM_MEM_SIZE); + memset(s->param, 0x00, sizeof(MaruCamParam)); + INFO("reset maru-camera device\n"); + } +} + +int maru_camera_pci_init(PCIBus *bus) +{ + pci_create_simple(bus, -1, MARU_PCI_CAMERA_DEVICE_NAME); + return 0; +} + +static void maru_camera_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->init = marucam_initfn; + k->exit = marucam_exitfn; + k->vendor_id = PCI_VENDOR_ID_TIZEN; + k->device_id = PCI_DEVICE_ID_VIRTUAL_CAMERA; + k->class_id = PCI_CLASS_OTHERS; + dc->reset = marucam_resetfn; + dc->desc = "MARU Virtual Camera device for Tizen emulator"; +} + +static TypeInfo maru_camera_info = { + .name = MARU_PCI_CAMERA_DEVICE_NAME, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(MaruCamState), + .class_init = maru_camera_pci_class_init, +}; + +static void maru_camera_pci_register_types(void) +{ + type_register_static(&maru_camera_info); +} + +type_init(maru_camera_pci_register_types) diff --git a/tizen/src/hw/pci/maru_camera.h b/tizen/src/hw/pci/maru_camera.h new file mode 100644 index 0000000000..429446023e --- /dev/null +++ b/tizen/src/hw/pci/maru_camera.h @@ -0,0 +1,116 @@ +/* + * Common header of MARU Virtual Camera device. + * + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jinhyung Jo + * Sangho Park + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef _MARU_CAMERA_H_ +#define _MARU_CAMERA_H_ + +#include "hw/pci/pci.h" +#include "qemu/thread.h" + +#define MARUCAM_MAX_PARAM 20 +#define MARUCAM_SKIPFRAMES 2 + +/* must sync with GUEST camera_driver */ +#define MARUCAM_CMD_INIT 0x00 +#define MARUCAM_CMD_OPEN 0x04 +#define MARUCAM_CMD_CLOSE 0x08 +#define MARUCAM_CMD_ISR 0x0C +#define MARUCAM_CMD_START_PREVIEW 0x10 +#define MARUCAM_CMD_STOP_PREVIEW 0x14 +#define MARUCAM_CMD_S_PARAM 0x18 +#define MARUCAM_CMD_G_PARAM 0x1C +#define MARUCAM_CMD_ENUM_FMT 0x20 +#define MARUCAM_CMD_TRY_FMT 0x24 +#define MARUCAM_CMD_S_FMT 0x28 +#define MARUCAM_CMD_G_FMT 0x2C +#define MARUCAM_CMD_QCTRL 0x30 +#define MARUCAM_CMD_S_CTRL 0x34 +#define MARUCAM_CMD_G_CTRL 0x38 +#define MARUCAM_CMD_ENUM_FSIZES 0x3C +#define MARUCAM_CMD_ENUM_FINTV 0x40 +#define MARUCAM_CMD_S_DATA 0x44 +#define MARUCAM_CMD_G_DATA 0x48 +#define MARUCAM_CMD_DATACLR 0x50 +#define MARUCAM_CMD_REQFRAME 0x54 + +typedef struct MaruCamState MaruCamState; +typedef struct MaruCamParam MaruCamParam; + +struct MaruCamParam { + uint32_t top; + uint32_t retVal; + uint32_t errCode; + uint32_t stack[MARUCAM_MAX_PARAM]; +}; + +struct MaruCamState { + PCIDevice dev; + MaruCamParam *param; + QemuThread thread_id; + QemuMutex thread_mutex;; + QemuCond thread_cond; + QEMUBH *tx_bh; + + bool initialized; + bool destroying; + void *vaddr; /* vram ptr */ + uint32_t isr; + uint32_t streamon; + uint32_t buf_size; + uint32_t req_frame; + + MemoryRegion vram; + MemoryRegion mmio; +}; + +/* ------------------------------------------------------------------------- */ +/* Fucntion prototype */ +/* ------------------------------------------------------------------------- */ +int marucam_device_check(int log_flag); +void marucam_device_init(MaruCamState *state); +void marucam_device_exit(MaruCamState *state); +void marucam_device_open(MaruCamState *state); +void marucam_device_close(MaruCamState *state); +void marucam_device_start_preview(MaruCamState *state); +void marucam_device_stop_preview(MaruCamState *state); +void marucam_device_s_param(MaruCamState *state); +void marucam_device_g_param(MaruCamState *state); +void marucam_device_s_fmt(MaruCamState *state); +void marucam_device_g_fmt(MaruCamState *state); +void marucam_device_try_fmt(MaruCamState *state); +void marucam_device_enum_fmt(MaruCamState *state); +void marucam_device_qctrl(MaruCamState *state); +void marucam_device_s_ctrl(MaruCamState *state); +void marucam_device_g_ctrl(MaruCamState *state); +void marucam_device_enum_fsizes(MaruCamState *state); +void marucam_device_enum_fintv(MaruCamState *state); + +int maru_camera_pci_init(PCIBus *bus); + +#endif /* _MARU_CAMERA_H_ */ diff --git a/tizen/src/hw/pci/maru_camera_common.h b/tizen/src/hw/pci/maru_camera_common.h deleted file mode 100644 index 45b1a38f15..0000000000 --- a/tizen/src/hw/pci/maru_camera_common.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Common header of MARU Virtual Camera device. - * - * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: - * JinHyung Jo - * YeongKyoon Lee - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - * Contributors: - * - S-Core Co., Ltd - * - */ - -#ifndef _MARU_CAMERA_COMMON_H_ -#define _MARU_CAMERA_COMMON_H_ - -#include "hw/pci/pci.h" -#include "qemu/thread.h" - -#define MARUCAM_MAX_PARAM 20 -#define MARUCAM_SKIPFRAMES 2 - -/* must sync with GUEST camera_driver */ -#define MARUCAM_CMD_INIT 0x00 -#define MARUCAM_CMD_OPEN 0x04 -#define MARUCAM_CMD_CLOSE 0x08 -#define MARUCAM_CMD_ISR 0x0C -#define MARUCAM_CMD_START_PREVIEW 0x10 -#define MARUCAM_CMD_STOP_PREVIEW 0x14 -#define MARUCAM_CMD_S_PARAM 0x18 -#define MARUCAM_CMD_G_PARAM 0x1C -#define MARUCAM_CMD_ENUM_FMT 0x20 -#define MARUCAM_CMD_TRY_FMT 0x24 -#define MARUCAM_CMD_S_FMT 0x28 -#define MARUCAM_CMD_G_FMT 0x2C -#define MARUCAM_CMD_QCTRL 0x30 -#define MARUCAM_CMD_S_CTRL 0x34 -#define MARUCAM_CMD_G_CTRL 0x38 -#define MARUCAM_CMD_ENUM_FSIZES 0x3C -#define MARUCAM_CMD_ENUM_FINTV 0x40 -#define MARUCAM_CMD_S_DATA 0x44 -#define MARUCAM_CMD_G_DATA 0x48 -#define MARUCAM_CMD_DATACLR 0x50 -#define MARUCAM_CMD_REQFRAME 0x54 - -typedef struct MaruCamState MaruCamState; -typedef struct MaruCamParam MaruCamParam; - -struct MaruCamParam { - uint32_t top; - uint32_t retVal; - uint32_t errCode; - uint32_t stack[MARUCAM_MAX_PARAM]; -}; - -struct MaruCamState { - PCIDevice dev; - MaruCamParam *param; - QemuThread thread_id; - QemuMutex thread_mutex;; - QemuCond thread_cond; - QEMUBH *tx_bh; - - bool initialized; - bool destroying; - void *vaddr; /* vram ptr */ - uint32_t isr; - uint32_t streamon; - uint32_t buf_size; - uint32_t req_frame; - - MemoryRegion vram; - MemoryRegion mmio; -}; - -/* ------------------------------------------------------------------------- */ -/* Fucntion prototype */ -/* ------------------------------------------------------------------------- */ -int marucam_device_check(int log_flag); -void marucam_device_init(MaruCamState *state); -void marucam_device_exit(MaruCamState *state); -void marucam_device_open(MaruCamState *state); -void marucam_device_close(MaruCamState *state); -void marucam_device_start_preview(MaruCamState *state); -void marucam_device_stop_preview(MaruCamState *state); -void marucam_device_s_param(MaruCamState *state); -void marucam_device_g_param(MaruCamState *state); -void marucam_device_s_fmt(MaruCamState *state); -void marucam_device_g_fmt(MaruCamState *state); -void marucam_device_try_fmt(MaruCamState *state); -void marucam_device_enum_fmt(MaruCamState *state); -void marucam_device_qctrl(MaruCamState *state); -void marucam_device_s_ctrl(MaruCamState *state); -void marucam_device_g_ctrl(MaruCamState *state); -void marucam_device_enum_fsizes(MaruCamState *state); -void marucam_device_enum_fintv(MaruCamState *state); - -int maru_camera_pci_init(PCIBus *bus); - -#endif /* _MARU_CAMERA_COMMON_H_ */ diff --git a/tizen/src/hw/pci/maru_camera_common_pci.c b/tizen/src/hw/pci/maru_camera_common_pci.c deleted file mode 100644 index d44df52439..0000000000 --- a/tizen/src/hw/pci/maru_camera_common_pci.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Common implementation of MARU Virtual Camera device by PCI bus. - * - * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: - * JinHyung Jo - * YeongKyoon Lee - * - * 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 -#include -#include -#include -#include -#include - -#include "qemu-common.h" -#include "qemu/main-loop.h" -#include "exec/cpu-common.h" - -#include "maru_camera_common.h" -#include "hw/maru_device_ids.h" -#include "debug_ch.h" - -MULTI_DEBUG_CHANNEL(tizen, camera); - -#define MARU_PCI_CAMERA_DEVICE_NAME "maru-camera" - -#define MARUCAM_MEM_SIZE (4 * 1024 * 1024) /* 4MB */ -#define MARUCAM_REG_SIZE (256) /* 64 * 4Byte */ - -/* - * I/O functions - */ -static inline uint32_t -marucam_mmio_read(void *opaque, hwaddr offset) -{ - uint32_t ret = 0; - MaruCamState *state = (MaruCamState *)opaque; - - switch (offset & 0xFF) { - case MARUCAM_CMD_ISR: - qemu_mutex_lock(&state->thread_mutex); - ret = state->isr; - if (ret != 0) { - pci_set_irq(&state->dev, 0); - state->isr = 0; - } - qemu_mutex_unlock(&state->thread_mutex); - break; - case MARUCAM_CMD_G_DATA: - ret = state->param->stack[state->param->top++]; - break; - case MARUCAM_CMD_OPEN: - case MARUCAM_CMD_CLOSE: - case MARUCAM_CMD_START_PREVIEW: - case MARUCAM_CMD_STOP_PREVIEW: - case MARUCAM_CMD_S_PARAM: - case MARUCAM_CMD_G_PARAM: - case MARUCAM_CMD_ENUM_FMT: - case MARUCAM_CMD_TRY_FMT: - case MARUCAM_CMD_S_FMT: - case MARUCAM_CMD_G_FMT: - case MARUCAM_CMD_QCTRL: - case MARUCAM_CMD_S_CTRL: - case MARUCAM_CMD_G_CTRL: - case MARUCAM_CMD_ENUM_FSIZES: - case MARUCAM_CMD_ENUM_FINTV: - ret = state->param->errCode; - state->param->errCode = 0; - break; - default: - ERR("Not supported command: 0x%x\n", offset); - ret = EINVAL; - break; - } - return ret; -} - -static inline void -marucam_mmio_write(void *opaque, hwaddr offset, uint32_t value) -{ - MaruCamState *state = (MaruCamState *)opaque; - - switch (offset & 0xFF) { - case MARUCAM_CMD_OPEN: - marucam_device_open(state); - break; - case MARUCAM_CMD_CLOSE: - marucam_device_close(state); - break; - case MARUCAM_CMD_START_PREVIEW: - marucam_device_start_preview(state); - break; - case MARUCAM_CMD_STOP_PREVIEW: - marucam_device_stop_preview(state); - memset(state->vaddr, 0, MARUCAM_MEM_SIZE); - break; - case MARUCAM_CMD_S_PARAM: - marucam_device_s_param(state); - break; - case MARUCAM_CMD_G_PARAM: - marucam_device_g_param(state); - break; - case MARUCAM_CMD_ENUM_FMT: - marucam_device_enum_fmt(state); - break; - case MARUCAM_CMD_TRY_FMT: - marucam_device_try_fmt(state); - break; - case MARUCAM_CMD_S_FMT: - marucam_device_s_fmt(state); - break; - case MARUCAM_CMD_G_FMT: - marucam_device_g_fmt(state); - break; - case MARUCAM_CMD_QCTRL: - marucam_device_qctrl(state); - break; - case MARUCAM_CMD_S_CTRL: - marucam_device_s_ctrl(state); - break; - case MARUCAM_CMD_G_CTRL: - marucam_device_g_ctrl(state); - break; - case MARUCAM_CMD_ENUM_FSIZES: - marucam_device_enum_fsizes(state); - break; - case MARUCAM_CMD_ENUM_FINTV: - marucam_device_enum_fintv(state); - break; - case MARUCAM_CMD_S_DATA: - state->param->stack[state->param->top++] = value; - break; - case MARUCAM_CMD_DATACLR: - memset(state->param, 0, sizeof(MaruCamParam)); - break; - case MARUCAM_CMD_REQFRAME: - qemu_mutex_lock(&state->thread_mutex); - state->req_frame = value + 1; - qemu_mutex_unlock(&state->thread_mutex); - break; - default: - ERR("Not supported command: 0x%x\n", offset); - break; - } -} - -static const MemoryRegionOps maru_camera_mmio_ops = { - .old_mmio = { - .read = { - marucam_mmio_read, - marucam_mmio_read, - marucam_mmio_read, - }, - .write = { - marucam_mmio_write, - marucam_mmio_write, - marucam_mmio_write, - }, - }, - .endianness = DEVICE_LITTLE_ENDIAN, -}; - -/* - * QEMU bottom half funtion - */ -static void marucam_tx_bh(void *opaque) -{ - MaruCamState *state = (MaruCamState *)opaque; - - qemu_mutex_lock(&state->thread_mutex); - if (state->isr) { - pci_set_irq(&state->dev, 1); - } - qemu_mutex_unlock(&state->thread_mutex); -} - -/* - * Initialization function - */ - -static int marucam_initfn(PCIDevice *dev) -{ - MaruCamState *s = DO_UPCAST(MaruCamState, dev, dev); - uint8_t *pci_conf = s->dev.config; - - /* Check available webcam - * If there is not one, you can't use the camera. - */ - if (!marucam_device_check(1)) { - s->initialized = false; - ERR("Failed to check the camera device, " - "You can *not* use the camera\n"); - return 0; - } - - pci_config_set_interrupt_pin(pci_conf, 0x03); - - memory_region_init_ram(&s->vram, OBJECT(s), "marucamera.ram", MARUCAM_MEM_SIZE, - &error_abort); - s->vaddr = memory_region_get_ram_ptr(&s->vram); - memset(s->vaddr, 0, MARUCAM_MEM_SIZE); - - memory_region_init_io(&s->mmio, OBJECT(s), - &maru_camera_mmio_ops, - s, - "maru-camera-mmio", - MARUCAM_REG_SIZE); - - pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); - pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio); - - /* for worker thread */ - s->param = (MaruCamParam *)g_malloc0(sizeof(MaruCamParam)); - qemu_cond_init(&s->thread_cond); - qemu_mutex_init(&s->thread_mutex); - - marucam_device_init(s); - - s->tx_bh = qemu_bh_new(marucam_tx_bh, s); - s->initialized = true; - INFO("initialize maru-camera device\n"); - - return 0; -} - -/* - * Termination function - */ -static void marucam_exitfn(PCIDevice *pci_dev) -{ - MaruCamState *s = - OBJECT_CHECK(MaruCamState, pci_dev, MARU_PCI_CAMERA_DEVICE_NAME); - - if (s->initialized) { - marucam_device_exit(s); - g_free(s->param); - qemu_cond_destroy(&s->thread_cond); - qemu_mutex_destroy(&s->thread_mutex); - } - - INFO("finalize maru-camera device\n"); -} - -static void marucam_resetfn(DeviceState *d) -{ - MaruCamState *s = (MaruCamState *)d; - - if (s->initialized) { - marucam_device_close(s); - qemu_mutex_lock(&s->thread_mutex); - s->isr = s->streamon = s->req_frame = s->buf_size = 0; - qemu_mutex_unlock(&s->thread_mutex); - memset(s->vaddr, 0, MARUCAM_MEM_SIZE); - memset(s->param, 0x00, sizeof(MaruCamParam)); - INFO("reset maru-camera device\n"); - } -} - -int maru_camera_pci_init(PCIBus *bus) -{ - pci_create_simple(bus, -1, MARU_PCI_CAMERA_DEVICE_NAME); - return 0; -} - -static void maru_camera_pci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->init = marucam_initfn; - k->exit = marucam_exitfn; - k->vendor_id = PCI_VENDOR_ID_TIZEN; - k->device_id = PCI_DEVICE_ID_VIRTUAL_CAMERA; - k->class_id = PCI_CLASS_OTHERS; - dc->reset = marucam_resetfn; - dc->desc = "MARU Virtual Camera device for Tizen emulator"; -} - -static TypeInfo maru_camera_info = { - .name = MARU_PCI_CAMERA_DEVICE_NAME, - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(MaruCamState), - .class_init = maru_camera_pci_class_init, -}; - -static void maru_camera_pci_register_types(void) -{ - type_register_static(&maru_camera_info); -} - -type_init(maru_camera_pci_register_types) diff --git a/tizen/src/hw/pci/maru_camera_convert.c b/tizen/src/hw/pci/maru_camera_convert.c new file mode 100644 index 0000000000..8be52ce9ba --- /dev/null +++ b/tizen/src/hw/pci/maru_camera_convert.c @@ -0,0 +1,663 @@ +/* + * Implementation of color conversion for MARU Virtual Camera device. + * + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jun Tian + * Jinhyung Jo + * Sangho Park + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "qemu-common.h" +#include "maru_camera_convert.h" +#include "debug_ch.h" + +MULTI_DEBUG_CHANNEL(tizen, camera); + +static void UYVYToYUV420(unsigned char *bufsrc, unsigned char *bufdest, + uint32_t width, uint32_t height); +static void YVU420ToYUV420(unsigned char *bufsrc, unsigned char *bufdest, + uint32_t width, uint32_t height); +static void YUYVToYUV420(unsigned char *bufsrc, unsigned char *bufdest, + uint32_t width, uint32_t height); + +static void yuyv_to_yuv420(const unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height, uint32_t yvu); +static void rgb24_to_yuv420(const unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height, uint32_t yvu); +static void rgb24_to_yuyv(unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height); +static void yuv420_to_yvu420(unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height); +static void yuv420_to_yuyv(unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height); + +/* Convert pixel format to YUV420 */ +uint8_t convert_frame(uint32_t src_format, uint32_t dst_format, + uint32_t width, uint32_t height, size_t frame_size, + void *src_buf, void *dst_buf) +{ + switch (src_format) { + case V4L2_PIX_FMT_YUV420: + switch (dst_format) { + case V4L2_PIX_FMT_YUV420: + memcpy(dst_buf, (void *)src_buf, (size_t)frame_size); + break; + case V4L2_PIX_FMT_YVU420: + yuv420_to_yvu420(src_buf, dst_buf, width, height); + break; + case V4L2_PIX_FMT_YUYV: + yuv420_to_yuyv(src_buf, dst_buf, width, height); + break; + default: + ERR("Cannot convert from the pixel format (%.4s)...\n", + (const char *)&src_format); + return 1; + } + break; + case V4L2_PIX_FMT_YVU420: + switch (dst_format) { + case V4L2_PIX_FMT_YUV420: + YVU420ToYUV420(src_buf, dst_buf, width, height); + break; + default: + ERR("Cannot convert from the pixel format (%.4s)...\n", + (const char *)&src_format); + return 1; + } + break; + case V4L2_PIX_FMT_YUYV: + switch (dst_format) { + case V4L2_PIX_FMT_YUV420: + //YUYVToYUV420(src_buf, dst_buf, width, height); + yuyv_to_yuv420(src_buf, dst_buf, width, height, 0); + break; + case V4L2_PIX_FMT_YVU420: + yuyv_to_yuv420(src_buf, dst_buf, width, height, 1); + break; + case V4L2_PIX_FMT_YUYV: + memcpy(dst_buf, (void *)src_buf, (size_t)frame_size); + break; + default: + ERR("Cannot convert from the pixel format (%.4s)...\n", + (const char *)&src_format); + return 1; + } + break; + case V4L2_PIX_FMT_UYVY: /* Mac default format */ + switch (dst_format) { + case V4L2_PIX_FMT_YUV420: + UYVYToYUV420(src_buf, dst_buf, width, height); + break; + default: + ERR("Cannot convert from the pixel format (%.4s)...\n", + (const char *)&src_format); + return 1; + } + break; + case V4L2_PIX_FMT_RGB24: + switch (dst_format) { + case V4L2_PIX_FMT_YUV420: + rgb24_to_yuv420(src_buf, dst_buf, width, height, 0); + break; + case V4L2_PIX_FMT_YVU420: + rgb24_to_yuv420(src_buf, dst_buf, width, height, 1); + break; + case V4L2_PIX_FMT_YUYV: + rgb24_to_yuyv(src_buf, dst_buf, width, height); + break; + default: + ERR("Cannot convert from the pixel format (%.4s)...\n", + (const char *)&src_format); + return 1; + } + break; + default: + ERR("Cannot convert from the pixel format (%.4s)...\n", + (const char *)&src_format); + return 1; + } + + return 0; +} + +static void UYVYToYUV420(unsigned char *bufsrc, unsigned char *bufdest, + uint32_t width, uint32_t height) +{ + uint32_t i, j; + + /* Source */ + unsigned char *ptrsrcy1, *ptrsrcy2; + unsigned char *ptrsrcy3, *ptrsrcy4; + unsigned char *ptrsrccb1; + unsigned char *ptrsrccb3; + unsigned char *ptrsrccr1; + unsigned char *ptrsrccr3; + uint32_t srcystride, srcccstride; + + ptrsrcy1 = bufsrc + 1; + ptrsrcy2 = bufsrc + (width << 1) + 1; + ptrsrcy3 = bufsrc + (width << 1) * 2 + 1; + ptrsrcy4 = bufsrc + (width << 1) * 3 + 1; + + ptrsrccb1 = bufsrc; + ptrsrccb3 = bufsrc + (width << 1) * 2; + + ptrsrccr1 = bufsrc + 2; + ptrsrccr3 = bufsrc + (width << 1) * 2 + 2; + + srcystride = (width << 1) * 3; + srcccstride = (width << 1) * 3; + + /* Destination */ + unsigned char *ptrdesty1, *ptrdesty2; + unsigned char *ptrdesty3, *ptrdesty4; + unsigned char *ptrdestcb1, *ptrdestcb2; + unsigned char *ptrdestcr1, *ptrdestcr2; + uint32_t destystride, destccstride; + + ptrdesty1 = bufdest; + ptrdesty2 = bufdest + width; + ptrdesty3 = bufdest + width * 2; + ptrdesty4 = bufdest + width * 3; + + ptrdestcb1 = bufdest + width * height; + ptrdestcb2 = bufdest + width * height + (width >> 1); + + ptrdestcr1 = bufdest + width * height + ((width*height) >> 2); + ptrdestcr2 = bufdest + width * height + ((width*height) >> 2) + + (width >> 1); + + destystride = (width)*3; + destccstride = (width>>1); + + for (j = 0; j < (height / 4); j++) { + for (i = 0; i < (width / 2); i++) { + (*ptrdesty1++) = (*ptrsrcy1); + (*ptrdesty2++) = (*ptrsrcy2); + (*ptrdesty3++) = (*ptrsrcy3); + (*ptrdesty4++) = (*ptrsrcy4); + + ptrsrcy1 += 2; + ptrsrcy2 += 2; + ptrsrcy3 += 2; + ptrsrcy4 += 2; + + (*ptrdesty1++) = (*ptrsrcy1); + (*ptrdesty2++) = (*ptrsrcy2); + (*ptrdesty3++) = (*ptrsrcy3); + (*ptrdesty4++) = (*ptrsrcy4); + + ptrsrcy1 += 2; + ptrsrcy2 += 2; + ptrsrcy3 += 2; + ptrsrcy4 += 2; + + (*ptrdestcb1++) = (*ptrsrccb1); + (*ptrdestcb2++) = (*ptrsrccb3); + + ptrsrccb1 += 4; + ptrsrccb3 += 4; + + (*ptrdestcr1++) = (*ptrsrccr1); + (*ptrdestcr2++) = (*ptrsrccr3); + + ptrsrccr1 += 4; + ptrsrccr3 += 4; + + } + + /* Update src pointers */ + ptrsrcy1 += srcystride; + ptrsrcy2 += srcystride; + ptrsrcy3 += srcystride; + ptrsrcy4 += srcystride; + + ptrsrccb1 += srcccstride; + ptrsrccb3 += srcccstride; + + ptrsrccr1 += srcccstride; + ptrsrccr3 += srcccstride; + + /* Update dest pointers */ + ptrdesty1 += destystride; + ptrdesty2 += destystride; + ptrdesty3 += destystride; + ptrdesty4 += destystride; + + ptrdestcb1 += destccstride; + ptrdestcb2 += destccstride; + + ptrdestcr1 += destccstride; + ptrdestcr2 += destccstride; + } +} + +static void YVU420ToYUV420(unsigned char *bufsrc, unsigned char *bufdest, + uint32_t width, uint32_t height) +{ + uint32_t i, j; + + /* Source*/ + unsigned char *ptrsrcy1, *ptrsrcy2; + unsigned char *ptrsrcy3, *ptrsrcy4; + unsigned char *ptrsrccb1, *ptrsrccb2; + unsigned char *ptrsrccr1, *ptrsrccr2; + uint32_t srcystride, srcccstride; + + ptrsrcy1 = bufsrc; + ptrsrcy2 = bufsrc + width; + ptrsrcy3 = bufsrc + width*2; + ptrsrcy4 = bufsrc + width*3; + + ptrsrccr1 = bufsrc + width*height; + ptrsrccr2 = bufsrc + width*height + (width>>1); + + ptrsrccb1 = bufsrc + width*height + ((width*height) >> 2); + ptrsrccb2 = bufsrc + width*height + ((width*height) >> 2) + (width>>1); + + srcystride = (width)*3; + srcccstride = (width>>1); + + /* Destination */ + unsigned char *ptrdesty1, *ptrdesty2; + unsigned char *ptrdesty3, *ptrdesty4; + unsigned char *ptrdestcb1, *ptrdestcb2; + unsigned char *ptrdestcr1, *ptrdestcr2; + uint32_t destystride, destccstride; + + ptrdesty1 = bufdest; + ptrdesty2 = bufdest + width; + ptrdesty3 = bufdest + width * 2; + ptrdesty4 = bufdest + width * 3; + + ptrdestcb1 = bufdest + width * height; + ptrdestcb2 = bufdest + width * height + (width >> 1); + + ptrdestcr1 = bufdest + width * height + ((width*height) >> 2); + ptrdestcr2 = bufdest + width * height + ((width*height) >> 2) + + (width >> 1); + + destystride = (width)*3; + destccstride = (width>>1); + + for (j = 0; j < (height / 4); j++) { + for (i = 0; i < (width / 2); i++) { + + (*ptrdesty1++) = (*ptrsrcy1++); + (*ptrdesty2++) = (*ptrsrcy2++); + (*ptrdesty3++) = (*ptrsrcy3++); + (*ptrdesty4++) = (*ptrsrcy4++); + (*ptrdesty1++) = (*ptrsrcy1++); + (*ptrdesty2++) = (*ptrsrcy2++); + (*ptrdesty3++) = (*ptrsrcy3++); + (*ptrdesty4++) = (*ptrsrcy4++); + + (*ptrdestcb1++) = (*ptrsrccb1++); + (*ptrdestcr1++) = (*ptrsrccr1++); + (*ptrdestcb2++) = (*ptrsrccb2++); + (*ptrdestcr2++) = (*ptrsrccr2++); + + } + + /* Update src pointers */ + ptrsrcy1 += srcystride; + ptrsrcy2 += srcystride; + ptrsrcy3 += srcystride; + ptrsrcy4 += srcystride; + + ptrsrccb1 += srcccstride; + ptrsrccb2 += srcccstride; + + ptrsrccr1 += srcccstride; + ptrsrccr2 += srcccstride; + + /* Update dest pointers */ + ptrdesty1 += destystride; + ptrdesty2 += destystride; + ptrdesty3 += destystride; + ptrdesty4 += destystride; + + ptrdestcb1 += destccstride; + ptrdestcb2 += destccstride; + + ptrdestcr1 += destccstride; + ptrdestcr2 += destccstride; + + } + +} + +static void YUYVToYUV420(unsigned char *bufsrc, unsigned char *bufdest, + uint32_t width, uint32_t height) +{ + uint32_t i, j; + + /* Source*/ + unsigned char *ptrsrcy1, *ptrsrcy2; + unsigned char *ptrsrcy3, *ptrsrcy4; + unsigned char *ptrsrccb1; + unsigned char *ptrsrccb3; + unsigned char *ptrsrccr1; + unsigned char *ptrsrccr3; + uint32_t srcystride, srcccstride; + + ptrsrcy1 = bufsrc ; + ptrsrcy2 = bufsrc + (width << 1); + ptrsrcy3 = bufsrc + (width << 1) * 2; + ptrsrcy4 = bufsrc + (width << 1) * 3; + + ptrsrccb1 = bufsrc + 1; + ptrsrccb3 = bufsrc + (width << 1) * 2 + 1; + + ptrsrccr1 = bufsrc + 3; + ptrsrccr3 = bufsrc + (width << 1) * 2 + 3; + + srcystride = (width << 1) * 3; + srcccstride = (width << 1) * 3; + + /* Destination */ + unsigned char *ptrdesty1, *ptrdesty2; + unsigned char *ptrdesty3, *ptrdesty4; + unsigned char *ptrdestcb1, *ptrdestcb2; + unsigned char *ptrdestcr1, *ptrdestcr2; + uint32_t destystride, destccstride; + + ptrdesty1 = bufdest; + ptrdesty2 = bufdest + width; + ptrdesty3 = bufdest + width * 2; + ptrdesty4 = bufdest + width * 3; + + ptrdestcb1 = bufdest + width * height; + ptrdestcb2 = bufdest + width * height + (width >> 1); + + ptrdestcr1 = bufdest + width * height + ((width * height) >> 2); + ptrdestcr2 = bufdest + width * height + ((width * height) >> 2) + + (width >> 1); + + destystride = width * 3; + destccstride = (width >> 1); + + for (j = 0; j < (height / 4); j++) { + for (i = 0; i < (width / 2); i++) { + (*ptrdesty1++) = (*ptrsrcy1); + (*ptrdesty2++) = (*ptrsrcy2); + (*ptrdesty3++) = (*ptrsrcy3); + (*ptrdesty4++) = (*ptrsrcy4); + + ptrsrcy1 += 2; + ptrsrcy2 += 2; + ptrsrcy3 += 2; + ptrsrcy4 += 2; + + (*ptrdesty1++) = (*ptrsrcy1); + (*ptrdesty2++) = (*ptrsrcy2); + (*ptrdesty3++) = (*ptrsrcy3); + (*ptrdesty4++) = (*ptrsrcy4); + + ptrsrcy1 += 2; + ptrsrcy2 += 2; + ptrsrcy3 += 2; + ptrsrcy4 += 2; + + (*ptrdestcb1++) = (*ptrsrccb1); + (*ptrdestcb2++) = (*ptrsrccb3); + + ptrsrccb1 += 4; + ptrsrccb3 += 4; + + (*ptrdestcr1++) = (*ptrsrccr1); + (*ptrdestcr2++) = (*ptrsrccr3); + + ptrsrccr1 += 4; + ptrsrccr3 += 4; + + } + + /* Update src pointers */ + ptrsrcy1 += srcystride; + ptrsrcy2 += srcystride; + ptrsrcy3 += srcystride; + ptrsrcy4 += srcystride; + + ptrsrccb1 += srcccstride; + ptrsrccb3 += srcccstride; + + ptrsrccr1 += srcccstride; + ptrsrccr3 += srcccstride; + + /* Update dest pointers */ + ptrdesty1 += destystride; + ptrdesty2 += destystride; + ptrdesty3 += destystride; + ptrdesty4 += destystride; + + ptrdestcb1 += destccstride; + ptrdestcb2 += destccstride; + + ptrdestcr1 += destccstride; + ptrdestcr2 += destccstride; + } +} + +static void yuyv_to_yuv420(const unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height, uint32_t yvu) +{ + uint32_t i, j; + const unsigned char *src1; + unsigned char *udest, *vdest; + + /* copy the Y values */ + src1 = src; + for (i = 0; i < height; i++) { + for (j = 0; j < width; j += 2) { + *dest++ = src1[0]; + *dest++ = src1[2]; + src1 += 4; + } + } + + /* copy the U and V values */ + src++; /* point to V */ + src1 = src + width * 2; /* next line */ + if (yvu) { + vdest = dest; + udest = dest + width * height / 4; + } else { + udest = dest; + vdest = dest + width * height / 4; + } + for (i = 0; i < height; i += 2) { + for (j = 0; j < width; j += 2) { + *udest++ = ((int) src[0] + src1[0]) / 2; /* U */ + *vdest++ = ((int) src[2] + src1[2]) / 2; /* V */ + src += 4; + src1 += 4; + } + src = src1; + src1 += width * 2; + } +} + +#define RGB2Y(r, g, b, y) \ + (y) = ((8453 * (r) + 16594 * (g) + 3223 * (b) + 524288) >> 15) + +#define RGB2UV(r, g, b, u, v) \ + do { \ + (u) = ((-4878 * (r) - 9578 * (g) + 14456 * (b) + 4210688) >> 15); \ + (v) = ((14456 * (r) - 12105 * (g) - 2351 * (b) + 4210688) >> 15); \ + } while (0) + +#define CLIP(color) \ + (unsigned char)(((color) > 0xFF) ? 0xff : (((color) < 0) ? 0 : (color))) + +static void rgb24_to_yuv420(const unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height, uint32_t yvu) +{ + uint32_t x, y; + uint32_t halfWidth; + uint8_t *yplane, *uplane, *vplane; + uint8_t *yline, *uline, *vline; + const uint8_t *rgbIndex; + + halfWidth = width >> 1; + yplane = dest; + + if (yvu) { + vplane = dest + width * height; + uplane = vplane + ((width * height) >> 2); + } else { + uplane = dest + width * height; + vplane = uplane + ((width * height) >> 2); + } + + for (y = 0; y < height; y++) { + yline = yplane + (y * width); + uline = uplane + ((y >> 1) * halfWidth); + vline = vplane + ((y >> 1) * halfWidth); + + rgbIndex = src + (width * (height - 1 - y) * 3); + for (x = 0; x < (int)width; x+=2) { + RGB2Y(rgbIndex[2], rgbIndex[1], rgbIndex[0], *yline++); + rgbIndex += 3; + RGB2Y(rgbIndex[2], rgbIndex[1], rgbIndex[0], *yline++); + RGB2UV(rgbIndex[2], rgbIndex[1], rgbIndex[0], *uline++, *vline++); + rgbIndex += 3; + } + } +} + +static void rgb24_to_yuyv(unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height) +{ + uint32_t i, j; + uint8_t *ptr; + + for (i = 0; i < height; i++) { + ptr = src + (width * (height - 1 - i) * 3); + for (j = 0; j < width; j += 2) { + /* y */ + *dest++ = CLIP(0.299 * (ptr[2] - 128) + + 0.587 * (ptr[1] - 128) + + 0.114 * (ptr[0] - 128) + 128); + /* u */ + *dest++ = CLIP(((-0.147 * (ptr[2] - 128) - + 0.289 * (ptr[1] - 128) + + 0.436 * (ptr[0] - 128) + 128) + + (-0.147 * (ptr[5] - 128) - + 0.289 * (ptr[4] - 128) + + 0.436 * (ptr[3] - 128) + 128)) / 2); + /* y1 */ + *dest++ = CLIP(0.299 * (ptr[5] - 128) + + 0.587 * (ptr[4] - 128) + + 0.114 * (ptr[3] - 128) + 128); + /* v */ + *dest++ = CLIP(((0.615 * (ptr[2] - 128) - + 0.515 * (ptr[1] - 128) - + 0.100 * (ptr[0] - 128) + 128) + + (0.615 * (ptr[5] - 128) - + 0.515 * (ptr[4] - 128) - + 0.100 * (ptr[3] - 128) + 128)) / 2); + ptr += 6; + } + } +} + +static void yuv420_to_yvu420(unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height) +{ + unsigned char *psrc_y, *pdst_y; + unsigned char *psrc_u, *pdst_u; + unsigned char *psrc_v, *pdst_v; + + psrc_y = src; + psrc_u = psrc_y + (width * height); + psrc_v = psrc_u + (width * height / 4); + + pdst_y = dest; + pdst_v = pdst_y + (width * height); + pdst_u = pdst_v + (width * height / 4); + + memcpy(pdst_y, psrc_y, width * height); + memcpy(pdst_v, psrc_v, width * height / 4); + memcpy(pdst_u, psrc_u, width * height / 4); +} + +static void yuv420_to_yuyv(unsigned char *src, unsigned char *dest, + uint32_t width, uint32_t height) +{ + unsigned char *py; + unsigned char *pu; + unsigned char *pv; + + uint32_t linesize = width * 2; + uint32_t uvlinesize = width / 2; + uint32_t offset = 0; + uint32_t offset1 = 0; + uint32_t offsety = 0; + uint32_t offsety1 = 0; + uint32_t offsetuv = 0; + uint32_t h = 0; + uint32_t w = 0; + uint32_t wy = 0; + uint32_t huv = 0; + uint32_t wuv = 0; + + py = src; + pu = py + (width * height); + pv = pu + (width * height / 4); + + for (h = 0; h < height; h += 2) { + wy = 0; + wuv = 0; + offset = h * linesize; + offset1 = (h + 1) * linesize; + offsety = h * width; + offsety1 = (h + 1) * width; + offsetuv = huv * uvlinesize; + + for (w = 0; w < linesize; w += 4) { + /* y00 */ + dest[w + offset] = py[wy + offsety]; + /* u0 */ + dest[(w + 1) + offset] = pu[wuv + offsetuv]; + /* y01 */ + dest[(w + 2) + offset] = py[(wy + 1) + offsety]; + /* v0 */ + dest[(w + 3) + offset] = pv[wuv + offsetuv]; + + /* y10 */ + dest[w + offset1] = py[wy + offsety1]; + /* u0 */ + dest[(w + 1) + offset1] = pu[wuv + offsetuv]; + /* y11 */ + dest[(w + 2) + offset1] = py[(wy + 1) + offsety1]; + /* v0 */ + dest[(w + 3) + offset1] = pv[wuv + offsetuv]; + + wuv++; + wy += 2; + } + huv++; + } +} diff --git a/tizen/src/hw/pci/maru_camera_convert.h b/tizen/src/hw/pci/maru_camera_convert.h new file mode 100644 index 0000000000..8252d7db88 --- /dev/null +++ b/tizen/src/hw/pci/maru_camera_convert.h @@ -0,0 +1,122 @@ +/* + * Convert header of MARU Virtual Camera device. + * + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jun Tian + * Jinhyung Jo + * Sangho Park + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef _MARU_CAMERA_CONVERT_H_ +#define _MARU_CAMERA_CONVERT_H_ + +#define MAKEFOURCC(a, b, c, d) \ + (((uint32_t)(a) << 0) | \ + ((uint32_t)(b) << 8) | \ + ((uint32_t)(c) << 16) | \ + ((uint32_t)(d) << 24)) + +/* 16 RGB-5-5-5 */ +#define V4L2_PIX_FMT_RGB555 MAKEFOURCC('R', 'G', 'B', 'O') +/* 16 RGB-5-6-5 */ +#define V4L2_PIX_FMT_RGB565 MAKEFOURCC('R', 'G', 'B', 'P') +/* 16 RGB-5-5-5 BE */ +#define V4L2_PIX_FMT_RGB555X MAKEFOURCC('R', 'G', 'B', 'Q') +/* 16 RGB-5-6-5 BE */ +#define V4L2_PIX_FMT_RGB565X MAKEFOURCC('R', 'G', 'B', 'R') +/* 24 BGR-8-8-8 */ +#define V4L2_PIX_FMT_BGR24 MAKEFOURCC('B', 'G', 'R', '3') +/* 24 RGB-8-8-8 */ +#define V4L2_PIX_FMT_RGB24 MAKEFOURCC('R', 'G', 'B', '3') +/* 32 BGR-8-8-8-8 */ +#define V4L2_PIX_FMT_BGR32 MAKEFOURCC('B', 'G', 'R', '4') +/* 32 RGB-8-8-8-8 */ +#define V4L2_PIX_FMT_RGB32 MAKEFOURCC('R', 'G', 'B', '4') +/* 9 YVU 4:1:0 */ +#define V4L2_PIX_FMT_YVU410 MAKEFOURCC('Y', 'V', 'U', '9') +/* 12 YVU 4:2:0 */ +#define V4L2_PIX_FMT_YVU420 MAKEFOURCC('Y', 'V', '1', '2') +/* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YUYV MAKEFOURCC('Y', 'U', 'Y', 'V') +/* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_UYVY MAKEFOURCC('U', 'Y', 'V', 'Y') +/* 16 YVU422 planar */ +#define V4L2_PIX_FMT_YUV422P MAKEFOURCC('4', '2', '2', 'P') +/* 16 YVU411 planar */ +#define V4L2_PIX_FMT_YUV411P MAKEFOURCC('4', '1', '1', 'P') +/* 12 YUV 4:1:1 */ +#define V4L2_PIX_FMT_Y41P MAKEFOURCC('Y', '4', '1', 'P') +/* 16 xxxxyyyy uuuuvvvv */ +#define V4L2_PIX_FMT_YUV444 MAKEFOURCC('Y', '4', '4', '4') +/* 16 YUV-5-5-5 */ +#define V4L2_PIX_FMT_YUV555 MAKEFOURCC('Y', 'U', 'V', 'O') +/* 16 YUV-5-6-5 */ +#define V4L2_PIX_FMT_YUV565 MAKEFOURCC('Y', 'U', 'V', 'P') +/* 32 YUV-8-8-8-8 */ +#define V4L2_PIX_FMT_YUV32 MAKEFOURCC('Y', 'U', 'V', '4') +/* 9 YUV 4:1:0 */ +#define V4L2_PIX_FMT_YUV410 MAKEFOURCC('Y', 'U', 'V', '9') +/* 12 YUV 4:2:0 */ +#define V4L2_PIX_FMT_YUV420 MAKEFOURCC('Y', 'U', '1', '2') +/* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YYUV MAKEFOURCC('Y', 'Y', 'U', 'V') + +/* V4L2 defines copy from videodev2.h */ +#define V4L2_CTRL_FLAG_SLIDER 0x0020 + +#define V4L2_CTRL_CLASS_USER 0x00980000 +#define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900) +#define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE + 0) +#define V4L2_CID_CONTRAST (V4L2_CID_BASE + 1) +#define V4L2_CID_SATURATION (V4L2_CID_BASE + 2) +#define V4L2_CID_SHARPNESS (V4L2_CID_BASE + 27) + +inline uint32_t get_bytesperline(uint32_t pixfmt, uint32_t width) +{ + uint32_t bytesperline; + + switch (pixfmt) { + case V4L2_PIX_FMT_YUV420: + case V4L2_PIX_FMT_YVU420: + bytesperline = (width * 12) >> 3; + break; + case V4L2_PIX_FMT_YUYV: + default: + bytesperline = width * 2; + break; + } + + return bytesperline; +} + +inline uint32_t get_sizeimage(uint32_t pixfmt, uint32_t width, uint32_t height) +{ + return get_bytesperline(pixfmt, width) * height; +} + +uint8_t convert_frame(uint32_t src_format, uint32_t dst_format, + uint32_t width, uint32_t height, size_t frame_size, + void *src_buf, void *dst_buf) + +#endif /* _MARU_CAMERA_CONVERT_H_ */ diff --git a/tizen/src/hw/pci/maru_camera_darwin.h b/tizen/src/hw/pci/maru_camera_darwin.h deleted file mode 100644 index 2ac39f9172..0000000000 --- a/tizen/src/hw/pci/maru_camera_darwin.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Header of MARU Virtual Camera device for MacOS. - * - * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: - * Jun Tian - * JinHyung Jo - * YeongKyoon Lee - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - * Contributors: - * - S-Core Co., Ltd - * - */ - -#ifndef _MARU_CAMERA_DARWIN_H_ -#define _MARU_CAMERA_DARWIN_H_ - -#define MAKEFOURCC(a, b, c, d) \ - (((uint32_t)(a) << 0) | \ - ((uint32_t)(b) << 8) | \ - ((uint32_t)(c) << 16) | \ - ((uint32_t)(d) << 24)) - -/* 16 RGB-5-5-5 */ -#define V4L2_PIX_FMT_RGB555 MAKEFOURCC('R', 'G', 'B', 'O') -/* 16 RGB-5-6-5 */ -#define V4L2_PIX_FMT_RGB565 MAKEFOURCC('R', 'G', 'B', 'P') -/* 16 RGB-5-5-5 BE */ -#define V4L2_PIX_FMT_RGB555X MAKEFOURCC('R', 'G', 'B', 'Q') -/* 16 RGB-5-6-5 BE */ -#define V4L2_PIX_FMT_RGB565X MAKEFOURCC('R', 'G', 'B', 'R') -/* 24 BGR-8-8-8 */ -#define V4L2_PIX_FMT_BGR24 MAKEFOURCC('B', 'G', 'R', '3') -/* 24 RGB-8-8-8 */ -#define V4L2_PIX_FMT_RGB24 MAKEFOURCC('R', 'G', 'B', '3') -/* 32 BGR-8-8-8-8 */ -#define V4L2_PIX_FMT_BGR32 MAKEFOURCC('B', 'G', 'R', '4') -/* 32 RGB-8-8-8-8 */ -#define V4L2_PIX_FMT_RGB32 MAKEFOURCC('R', 'G', 'B', '4') -/* 9 YVU 4:1:0 */ -#define V4L2_PIX_FMT_YVU410 MAKEFOURCC('Y', 'V', 'U', '9') -/* 12 YVU 4:2:0 */ -#define V4L2_PIX_FMT_YVU420 MAKEFOURCC('Y', 'V', '1', '2') -/* 16 YUV 4:2:2 */ -#define V4L2_PIX_FMT_YUYV MAKEFOURCC('Y', 'U', 'Y', 'V') -/* 16 YUV 4:2:2 */ -#define V4L2_PIX_FMT_UYVY MAKEFOURCC('U', 'Y', 'V', 'Y') -/* 16 YVU422 planar */ -#define V4L2_PIX_FMT_YUV422P MAKEFOURCC('4', '2', '2', 'P') -/* 16 YVU411 planar */ -#define V4L2_PIX_FMT_YUV411P MAKEFOURCC('4', '1', '1', 'P') -/* 12 YUV 4:1:1 */ -#define V4L2_PIX_FMT_Y41P MAKEFOURCC('Y', '4', '1', 'P') -/* 16 xxxxyyyy uuuuvvvv */ -#define V4L2_PIX_FMT_YUV444 MAKEFOURCC('Y', '4', '4', '4') -/* 16 YUV-5-5-5 */ -#define V4L2_PIX_FMT_YUV555 MAKEFOURCC('Y', 'U', 'V', 'O') -/* 16 YUV-5-6-5 */ -#define V4L2_PIX_FMT_YUV565 MAKEFOURCC('Y', 'U', 'V', 'P') -/* 32 YUV-8-8-8-8 */ -#define V4L2_PIX_FMT_YUV32 MAKEFOURCC('Y', 'U', 'V', '4') -/* 9 YUV 4:1:0 */ -#define V4L2_PIX_FMT_YUV410 MAKEFOURCC('Y', 'U', 'V', '9') -/* 12 YUV 4:2:0 */ -#define V4L2_PIX_FMT_YUV420 MAKEFOURCC('Y', 'U', '1', '2') -/* 16 YUV 4:2:2 */ -#define V4L2_PIX_FMT_YYUV MAKEFOURCC('Y', 'Y', 'U', 'V') - -void convert_frame(uint32_t pixel_format, int frame_width, int frame_height, - size_t frame_size, void *frame_pixels, void *video_buf); - -#endif /* _MARU_CAMERA_DARWIN_H_ */ diff --git a/tizen/src/hw/pci/maru_camera_darwin.m b/tizen/src/hw/pci/maru_camera_darwin.m new file mode 100644 index 0000000000..26f29afb7a --- /dev/null +++ b/tizen/src/hw/pci/maru_camera_darwin.m @@ -0,0 +1,876 @@ +/* + * Implementation of MARU Virtual Camera device by PCI bus on MacOS. + * + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jun Tian + * Jinhyung Jo + * Sangho Park + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#import +#import +#import + +#include +#include "qemu-common.h" +#include "maru_camera.h" +#include "maru_camera_convert.h" +#include "debug_ch.h" + +MULTI_DEBUG_CHANNEL(tizen, camera); + +#define MARUCAM_THREAD_NAME "marucam_worker_thread" + +typedef struct tagMaruCamConvertPixfmt { + uint32_t fmt; /* fourcc */ + uint32_t bpp; /* bits per pixel, 0 for compressed formats */ + uint32_t needs_conversion; +} MaruCamConvertPixfmt; + + +static MaruCamConvertPixfmt supported_dst_pixfmts[] = { + { V4L2_PIX_FMT_YUYV, 16, 0 }, + { V4L2_PIX_FMT_UYVY, 16, 0 }, + { V4L2_PIX_FMT_YUV420, 12, 0 }, + { V4L2_PIX_FMT_YVU420, 12, 0 }, +}; + +typedef struct tagMaruCamConvertFrameInfo { + uint32_t width; + uint32_t height; +} MaruCamConvertFrameInfo; + +static MaruCamConvertFrameInfo supported_dst_frames[] = { + { 640, 480 }, + { 352, 288 }, + { 320, 240 }, + { 176, 144 }, + { 160, 120 }, +}; + +#define MARUCAM_CTRL_VALUE_MAX 20 +#define MARUCAM_CTRL_VALUE_MIN 1 +#define MARUCAM_CTRL_VALUE_MID 10 +#define MARUCAM_CTRL_VALUE_STEP 1 + +enum { + _MC_THREAD_PAUSED, + _MC_THREAD_STREAMON, + _MC_THREAD_STREAMOFF, +}; + +#if 0 +struct marucam_qctrl { + uint32_t id; + uint32_t hit; + long min; + long max; + long step; + long init_val; +}; + +static struct marucam_qctrl qctrl_tbl[] = { + { V4L2_CID_BRIGHTNESS, 0, }, + { V4L2_CID_CONTRAST, 0, }, + { V4L2_CID_SATURATION, 0, }, + { V4L2_CID_SHARPNESS, 0, }, +}; +#endif + +static MaruCamState *g_state; + +static uint32_t ready_count; +static uint32_t cur_fmt_idx; +static uint32_t cur_frame_idx; + +/*********************************** + * Mac camera helper functions + ***********************************/ + +/* Convert Core Video format to FOURCC */ +static uint32_t corevideo_to_fourcc(uint32_t cv_pix_fmt) +{ + switch (cv_pix_fmt) { + case kCVPixelFormatType_420YpCbCr8Planar: + return V4L2_PIX_FMT_YVU420; + case kCVPixelFormatType_422YpCbCr8: + return V4L2_PIX_FMT_UYVY; + case kCVPixelFormatType_422YpCbCr8_yuvs: + return V4L2_PIX_FMT_YUYV; + case kCVPixelFormatType_32ARGB: + case kCVPixelFormatType_32RGBA: + return V4L2_PIX_FMT_RGB32; + case kCVPixelFormatType_32BGRA: + case kCVPixelFormatType_32ABGR: + return V4L2_PIX_FMT_BGR32; + case kCVPixelFormatType_24RGB: + return V4L2_PIX_FMT_RGB24; + case kCVPixelFormatType_24BGR: + return V4L2_PIX_FMT_BGR32; + default: + ERR("Unknown pixel format '%.4s'", (const char *)&cv_pix_fmt); + return 0; + } +} + +/****************************************************************** + ** Maru Camera Implementation + *****************************************************************/ + +@interface MaruCameraDriver : NSObject { + QTCaptureSession *mCaptureSession; + QTCaptureDeviceInput *mCaptureVideoDeviceInput; + QTCaptureVideoPreviewOutput *mCaptureVideoPreviewOutput; + + CVImageBufferRef mCurrentImageBuffer; + BOOL mDeviceIsOpened; + BOOL mCaptureIsStarted; +} + +- (MaruCameraDriver *)init; +- (int)startCapture:(int)width :(int)height; +- (void)stopCapture; +- (int)readFrame:(void *)video_buf; +- (int)setCaptureFormat:(int)width :(int)height :(int)pix_format; +- (int)getCaptureFormat:(int)width :(int)height :(int)pix_format; +- (BOOL)deviceStatus; + +@end + +@implementation MaruCameraDriver + +- (MaruCameraDriver *)init +{ + BOOL success = NO; + NSError *error; + mDeviceIsOpened = NO; + mCaptureIsStarted = NO; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + /* Create the capture session */ + mCaptureSession = [[QTCaptureSession alloc] init]; + + /* Find a video device */ + QTCaptureDevice *videoDevice = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeVideo]; + success = [videoDevice open:&error]; + + /* If a video input device can't be found or opened, try to find and open a muxed input device */ + if (!success) { + videoDevice = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeMuxed]; + success = [videoDevice open:&error]; + [pool release]; + return nil; + } + + if (!success) { + videoDevice = nil; + [pool release]; + return nil; + } + + if (videoDevice) { + /* Add the video device to the session as a device input */ + mCaptureVideoDeviceInput = [[QTCaptureDeviceInput alloc] initWithDevice:videoDevice]; + success = [mCaptureSession addInput:mCaptureVideoDeviceInput error:&error]; + + if (!success) { + [pool release]; + return nil; + } + + mCaptureVideoPreviewOutput = [[QTCaptureVideoPreviewOutput alloc] init]; + success = [mCaptureSession addOutput:mCaptureVideoPreviewOutput error:&error]; + if (!success) { + [pool release]; + return nil; + } + + mDeviceIsOpened = YES; + [mCaptureVideoPreviewOutput setDelegate:self]; + INFO("Camera session bundling successfully!\n"); + [pool release]; + return self; + } else { + [pool release]; + return nil; + } +} + +- (int)startCapture:(int)width :(int)height +{ + int ret = -1; + + if (![mCaptureSession isRunning]) { + /* Set width & height, using default pixel format to capture */ + NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt: width], (id)kCVPixelBufferWidthKey, + [NSNumber numberWithInt: height], (id)kCVPixelBufferHeightKey, + nil]; + [mCaptureVideoPreviewOutput setPixelBufferAttributes:attributes]; + [mCaptureSession startRunning]; + } else { + ERR("Capture session is already running, exit\n"); + return ret; + } + + if ([mCaptureSession isRunning]) { + while(!mCaptureIsStarted) { + /* Wait Until Capture is started */ + [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.5]]; + } + ret = 0; + } + return ret; +} + +- (void)stopCapture +{ + if ([mCaptureSession isRunning]) { + [mCaptureSession stopRunning]; + while([mCaptureSession isRunning]) { + /* Wait Until Capture is stopped */ + [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1]]; + } + + } + mCaptureIsStarted = NO; +} + +- (int)readFrame:(void *)video_buf +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + @synchronized (self) { + if (mCaptureIsStarted == NO) { + [pool release]; + return 0; + } + if (mCurrentImageBuffer != nil) { + CVPixelBufferLockBaseAddress(mCurrentImageBuffer, 0); + const uint32_t pixel_format = corevideo_to_fourcc(CVPixelBufferGetPixelFormatType(mCurrentImageBuffer)); + const int frame_width = CVPixelBufferGetWidth(mCurrentImageBuffer); + const int frame_height = CVPixelBufferGetHeight(mCurrentImageBuffer); + const size_t frame_size = CVPixelBufferGetBytesPerRow(mCurrentImageBuffer) * frame_height; + const void *frame_pixels = CVPixelBufferGetBaseAddress(mCurrentImageBuffer); + const uint32_t dst_format = supported_dst_pixfmts[cur_fmt_idx].fmt; + + TRACE("buffer(%p), pixel_format(%d,%.4s), frame_width(%d), " + "frame_height(%d), frame_size(%d)\n", + mCurrentImageBuffer, (int)pixel_format, + (const char *)&pixel_format, frame_width, + frame_height, (int)frame_size); + + /* convert frame to v4l2 format */ + convert_frame(pixel_format, dst_format, frame_width, frame_height, + frame_size, (void *)frame_pixels, video_buf); + CVPixelBufferUnlockBaseAddress(mCurrentImageBuffer, 0); + [pool release]; + return 1; + } + } + + [pool release]; + return -1; +} + +- (int)setCaptureFormat:(int)width :(int)height :(int)pix_format +{ + int ret = -1; + NSDictionary *attributes; + + if (mCaptureSession == nil || mCaptureVideoPreviewOutput == nil) { + ERR("Capture session is not initiated.\n"); + return ret; + } + + /* Set the pixel buffer attributes before running the capture session */ + if (![mCaptureSession isRunning]) { + if (pix_format) { + attributes = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt: width], (id)kCVPixelBufferWidthKey, + [NSNumber numberWithInt: height], (id)kCVPixelBufferHeightKey, + [NSNumber numberWithInt: pix_format], (id)kCVPixelBufferPixelFormatTypeKey, + nil]; + } else { + attributes = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt: width], (id)kCVPixelBufferWidthKey, + [NSNumber numberWithInt: height], (id)kCVPixelBufferHeightKey, + nil]; + } + [mCaptureVideoPreviewOutput setPixelBufferAttributes:attributes]; + ret = 0; + } else { + ERR("Cannot set pixel buffer attributes when it's running.\n"); + return ret; + } + + return ret; +} + +- (int)getCaptureFormat:(int)width :(int)height :(int)pix_format +{ + return 0; +} + +/* Get the device bundling status */ +- (BOOL)deviceStatus +{ + return mDeviceIsOpened; +} + +/* Handle deallocation of memory for your capture objects */ + +- (void)dealloc +{ + [mCaptureSession release]; + [mCaptureVideoDeviceInput release]; + [mCaptureVideoPreviewOutput release]; + [super dealloc]; +} + +/* Receive this method whenever the output decompresses and outputs a new video frame */ +- (void)captureOutput:(QTCaptureOutput *)captureOutput didOutputVideoFrame:(CVImageBufferRef)videoFrame + withSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection +{ + CVImageBufferRef imageBufferToRelease; + CVBufferRetain(videoFrame); + + @synchronized (self) + { + imageBufferToRelease = mCurrentImageBuffer; + mCurrentImageBuffer = videoFrame; + mCaptureIsStarted = YES; + } + CVBufferRelease(imageBufferToRelease); +} + +@end + +/****************************************************************** + ** Maru Camera APIs + *****************************************************************/ + +typedef struct MaruCameraDevice MaruCameraDevice; +struct MaruCameraDevice { + /* Maru camera device object. */ + MaruCameraDriver *driver; +}; + +/* Golbal representation of the Maru camera */ +MaruCameraDevice *mcd = NULL; + +static int is_streamon() +{ + int st; + qemu_mutex_lock(&g_state->thread_mutex); + st = g_state->streamon; + qemu_mutex_unlock(&g_state->thread_mutex); + return (st == _MC_THREAD_STREAMON); +} + +static void __raise_err_intr() +{ + qemu_mutex_lock(&g_state->thread_mutex); + if (g_state->streamon == _MC_THREAD_STREAMON) { + g_state->req_frame = 0; /* clear request */ + g_state->isr = 0x08; /* set a error flag of rasing a interrupt */ + qemu_bh_schedule(g_state->tx_bh); + } + qemu_mutex_unlock(&g_state->thread_mutex); +} + +static int marucam_device_read_frame() +{ + int ret; + void *tmp_buf; + + qemu_mutex_lock(&g_state->thread_mutex); + if (g_state->streamon == _MC_THREAD_STREAMON) { +#if 0 + if (ready_count < MARUCAM_SKIPFRAMES) { + /* skip a frame cause first some frame are distorted */ + ++ready_count; + TRACE("Skip %d frame\n", ready_count); + qemu_mutex_unlock(&g_state->thread_mutex); + return 0; + } +#endif + if (g_state->req_frame == 0) { + TRACE("There is no request\n"); + qemu_mutex_unlock(&g_state->thread_mutex); + return 0; + } + + /* Grab the camera frame into temp buffer */ + tmp_buf = g_state->vaddr + g_state->buf_size * (g_state->req_frame - 1); + ret = [mcd->driver readFrame: tmp_buf]; + if (ret < 0) { + ERR("%s, Capture error\n", __func__); + qemu_mutex_unlock(&g_state->thread_mutex); + __raise_err_intr(); + return -1; + } else if (!ret) { + qemu_mutex_unlock(&g_state->thread_mutex); + return 0; + } + + g_state->req_frame = 0; /* clear request */ + g_state->isr |= 0x01; /* set a flag of rasing a interrupt */ + qemu_bh_schedule(g_state->tx_bh); + } else { + qemu_mutex_unlock(&g_state->thread_mutex); + return -1; + } + qemu_mutex_unlock(&g_state->thread_mutex); + return 0; +} + +/* Worker thread to grab frames to the preview window */ +static void *marucam_worker_thread(void *thread_param) +{ + while (1) { + qemu_mutex_lock(&g_state->thread_mutex); + g_state->streamon = _MC_THREAD_PAUSED; + qemu_cond_wait(&g_state->thread_cond, &g_state->thread_mutex); + qemu_mutex_unlock(&g_state->thread_mutex); + + if (g_state->destroying) { + break; + } + + ready_count = 0; + qemu_mutex_lock(&g_state->thread_mutex); + g_state->streamon = _MC_THREAD_STREAMON; + qemu_mutex_unlock(&g_state->thread_mutex); + INFO("Streaming on ......\n"); + + /* Loop: capture frame -> convert format -> render to screen */ + while (1) { + if (is_streamon()) { + if (marucam_device_read_frame() < 0) { + INFO("Streaming is off ...\n"); + break; + } else { + /* wait until next frame is avalilable */ + usleep(22000); + } + } else { + INFO("Streaming is off ...\n"); + break; + } + } + } + + return NULL; +} + +int marucam_device_check(int log_flag) +{ + /* FIXME: check the device parameters */ + INFO("Checking camera device\n"); + return 1; +} + +/********************************************** + * MARU camera routines + **********************************************/ +void marucam_device_init(MaruCamState *state) +{ + g_state = state; + g_state->destroying = false; + qemu_thread_create(&state->thread_id, + MARUCAM_THREAD_NAME, + marucam_worker_thread, + NULL, + QEMU_THREAD_JOINABLE); +} + +void marucam_device_exit(MaruCamState *state) +{ + state->destroying = true; + qemu_mutex_lock(&state->thread_mutex); + qemu_cond_signal(&state->thread_cond); + qemu_mutex_unlock(&state->thread_mutex); + qemu_thread_join(&state->thread_id); +} + +/* MARUCAM_CMD_OPEN */ +void marucam_device_open(MaruCamState *state) +{ + MaruCamParam *param = state->param; + param->top = 0; + + mcd = (MaruCameraDevice *)malloc(sizeof(MaruCameraDevice)); + if (mcd == NULL) { + ERR("%s: MaruCameraDevice allocate failed\n", __func__); + param->errCode = EINVAL; + return; + } + memset(mcd, 0, sizeof(MaruCameraDevice)); + mcd->driver = [[MaruCameraDriver alloc] init]; + if (mcd->driver == nil) { + ERR("Camera device open failed\n"); + [mcd->driver dealloc]; + free(mcd); + param->errCode = EINVAL; + return; + } + INFO("Camera opened!\n"); +} + +/* MARUCAM_CMD_CLOSE */ +void marucam_device_close(MaruCamState *state) +{ + MaruCamParam *param = state->param; + param->top = 0; + + if (mcd != NULL) { + if (is_streamon()) { + marucam_device_stop_preview(state); + } + [mcd->driver dealloc]; + free(mcd); + mcd = NULL; + } + + /* marucam_reset_controls(); */ + INFO("Camera closed\n"); +} + +/* MARUCAM_CMD_START_PREVIEW */ +void marucam_device_start_preview(MaruCamState *state) +{ + uint32_t width, height, pixfmt; + MaruCamParam *param = state->param; + param->top = 0; + + width = supported_dst_frames[cur_frame_idx].width; + height = supported_dst_frames[cur_frame_idx].height; + pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; + state->buf_size = get_sizeimage(pixfmt, width, height); + + INFO("Pixfmt(%c%c%c%c), W:H(%d:%d), buf size(%u), frame idx(%d), fmt idx(%d)\n", + (char)(pixfmt), (char)(pixfmt >> 8), + (char)(pixfmt >> 16), (char)(pixfmt >> 24), + width, height, state->buf_size, + cur_frame_idx, cur_fmt_idx); + + if (mcd->driver == nil) { + ERR("%s: Start capture failed: vaild device", __func__); + param->errCode = EINVAL; + return; + } + + INFO("Starting preview ...\n"); + [mcd->driver startCapture: width: height]; + + /* Enable the condition to capture frames now */ + qemu_mutex_lock(&state->thread_mutex); + qemu_cond_signal(&state->thread_cond); + qemu_mutex_unlock(&state->thread_mutex); + + while (!is_streamon()) { + usleep(10000); + } +} + +/* MARUCAM_CMD_STOP_PREVIEW */ +void marucam_device_stop_preview(MaruCamState *state) +{ + MaruCamParam *param = state->param; + param->top = 0; + + if (is_streamon()) { + qemu_mutex_lock(&state->thread_mutex); + state->streamon = _MC_THREAD_STREAMOFF; + qemu_mutex_unlock(&state->thread_mutex); + + while (is_streamon()) { + usleep(10000); + } + } + + if (mcd->driver != nil) { + [mcd->driver stopCapture]; + } + + state->buf_size = 0; + INFO("Stopping preview ...\n"); +} + +/* MARUCAM_CMD_S_PARAM */ +void marucam_device_s_param(MaruCamState *state) +{ + MaruCamParam *param = state->param; + + /* We use default FPS of the webcam */ + param->top = 0; +} + +/* MARUCAM_CMD_G_PARAM */ +void marucam_device_g_param(MaruCamState *state) +{ + MaruCamParam *param = state->param; + /* We use default FPS of the webcam + * return a fixed value on guest ini file (1/30). + */ + param->top = 0; + param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */ + param->stack[1] = 1; /* numerator */ + param->stack[2] = 30; /* denominator */ +} + +/* MARUCAM_CMD_S_FMT */ +void marucam_device_s_fmt(MaruCamState *state) +{ + MaruCamParam *param = state->param; + uint32_t width, height, pixfmt, pidx, fidx; + + param->top = 0; + width = param->stack[0]; + height = param->stack[1]; + pixfmt = param->stack[2]; + + TRACE("Set format: width(%d), height(%d), pixfmt(%d, %.4s)\n", + width, height, pixfmt, (const char*)&pixfmt); + + for (fidx = 0; fidx < ARRAY_SIZE(supported_dst_frames); fidx++) { + if ((supported_dst_frames[fidx].width == width) && + (supported_dst_frames[fidx].height == height)) { + break; + } + } + if (fidx == ARRAY_SIZE(supported_dst_frames)) { + param->errCode = EINVAL; + return; + } + + for (pidx = 0; pidx < ARRAY_SIZE(supported_dst_pixfmts); pidx++) { + if (supported_dst_pixfmts[pidx].fmt == pixfmt) { + TRACE("pixfmt index is match: %d\n", pidx); + break; + } + } + if (pidx == ARRAY_SIZE(supported_dst_pixfmts)) { + param->errCode = EINVAL; + return; + } + + if ((supported_dst_frames[cur_frame_idx].width != width) && + (supported_dst_frames[cur_frame_idx].height != height)) { + if (mcd->driver == nil || [mcd->driver setCaptureFormat: width: height: 0] < 0) { + ERR("Set pixel format failed\n"); + param->errCode = EINVAL; + return; + } + + TRACE("cur_frame_idx:%d, supported_dst_frames[cur_frame_idx].width:%d\n", + cur_frame_idx, supported_dst_frames[cur_frame_idx].width); + } + + cur_frame_idx = fidx; + cur_fmt_idx = pidx; + + pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; + width = supported_dst_frames[cur_frame_idx].width; + height = supported_dst_frames[cur_frame_idx].height; + + param->stack[0] = width; + param->stack[1] = height; + param->stack[2] = 1; /* V4L2_FIELD_NONE */ + param->stack[3] = pixfmt; + param->stack[4] = get_bytesperline(pixfmt, width); + param->stack[5] = get_sizeimage(pixfmt, width, height); + param->stack[6] = 0; + param->stack[7] = 0; + + TRACE("Set device pixel format ...\n"); +} + +/* MARUCAM_CMD_G_FMT */ +void marucam_device_g_fmt(MaruCamState *state) +{ + uint32_t width, height, pixfmt; + MaruCamParam *param = state->param; + + param->top = 0; + pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; + width = supported_dst_frames[cur_frame_idx].width; + height = supported_dst_frames[cur_frame_idx].height; + + param->stack[0] = width; + param->stack[1] = height; + param->stack[2] = 1; /* V4L2_FIELD_NONE */ + param->stack[3] = pixfmt; + param->stack[4] = get_bytesperline(pixfmt, width); + param->stack[5] = get_sizeimage(pixfmt, width, height); + param->stack[6] = 0; + param->stack[7] = 0; + + TRACE("Get device frame format ...\n"); +} + +void marucam_device_try_fmt(MaruCamState *state) +{ + TRACE("Try device frame format, use default setting ...\n"); +} + +/* Get specific pixelformat description */ +void marucam_device_enum_fmt(MaruCamState *state) +{ + uint32_t index; + MaruCamParam *param = state->param; + + param->top = 0; + index = param->stack[0]; + + if (index >= ARRAY_SIZE(supported_dst_pixfmts)) { + param->errCode = EINVAL; + return; + } + param->stack[1] = 0; /* flags = NONE */ + param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */ + switch (supported_dst_pixfmts[index].fmt) { + case V4L2_PIX_FMT_YUYV: + memcpy(¶m->stack[3], "YUYV", 32); + break; + case V4L2_PIX_FMT_UYVY: + memcpy(¶m->stack[3], "UYVY", 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: + param->errCode = EINVAL; + break; + } +} + +/* + * QTKit don't support setting brightness, contrast, saturation & sharpness + */ +void marucam_device_qctrl(MaruCamState *state) +{ + uint32_t id, i; + /* long property, min, max, step, def_val, set_val; */ + char name[32] = {0,}; + MaruCamParam *param = state->param; + + param->top = 0; + id = param->stack[0]; + + switch (id) { + case V4L2_CID_BRIGHTNESS: + TRACE("V4L2_CID_BRIGHTNESS\n"); + memcpy((void *)name, (void *)"brightness", 32); + i = 0; + break; + case V4L2_CID_CONTRAST: + TRACE("V4L2_CID_CONTRAST\n"); + memcpy((void *)name, (void *)"contrast", 32); + i = 1; + break; + case V4L2_CID_SATURATION: + TRACE("V4L2_CID_SATURATION\n"); + memcpy((void *)name, (void *)"saturation", 32); + i = 2; + break; + case V4L2_CID_SHARPNESS: + TRACE("V4L2_CID_SHARPNESS\n"); + memcpy((void *)name, (void *)"sharpness", 32); + i = 3; + break; + default: + param->errCode = EINVAL; + return; + } + + param->stack[0] = id; + param->stack[1] = MARUCAM_CTRL_VALUE_MIN; /* minimum */ + param->stack[2] = MARUCAM_CTRL_VALUE_MAX; /* maximum */ + param->stack[3] = MARUCAM_CTRL_VALUE_STEP; /* step */ + param->stack[4] = MARUCAM_CTRL_VALUE_MID; /* default_value */ + param->stack[5] = V4L2_CTRL_FLAG_SLIDER; + /* name field setting */ + memcpy(¶m->stack[6], (void *)name, sizeof(name)/sizeof(name[0])); +} + +void marucam_device_s_ctrl(MaruCamState *state) +{ + INFO("Set control\n"); +} + +void marucam_device_g_ctrl(MaruCamState *state) +{ + INFO("Get control\n"); +} + +/* Get frame width & height */ +void marucam_device_enum_fsizes(MaruCamState *state) +{ + uint32_t index, pixfmt, i; + MaruCamParam *param = state->param; + + param->top = 0; + index = param->stack[0]; + pixfmt = param->stack[1]; + + if (index >= ARRAY_SIZE(supported_dst_frames)) { + param->errCode = EINVAL; + return; + } + for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) { + if (supported_dst_pixfmts[i].fmt == pixfmt) { + break; + } + } + + if (i == ARRAY_SIZE(supported_dst_pixfmts)) { + param->errCode = EINVAL; + return; + } + + param->stack[0] = supported_dst_frames[index].width; + param->stack[1] = supported_dst_frames[index].height; +} + +void marucam_device_enum_fintv(MaruCamState *state) +{ + MaruCamParam *param = state->param; + param->top = 0; + + /* switch by index(param->stack[0]) */ + switch (param->stack[0]) { + case 0: + param->stack[1] = 30; /* denominator */ + break; + default: + param->errCode = EINVAL; + return; + } + param->stack[0] = 1; /* numerator */ +} diff --git a/tizen/src/hw/pci/maru_camera_darwin_converter.c b/tizen/src/hw/pci/maru_camera_darwin_converter.c deleted file mode 100644 index 3f9cec5f4f..0000000000 --- a/tizen/src/hw/pci/maru_camera_darwin_converter.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Implementation of color conversion for MARU Virtual Camera device on MacOS. - * - * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: - * Jun Tian - * JinHyung Jo - * YeongKyoon Lee - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - * Contributors: - * - S-Core Co., Ltd - * - */ - -#include "qemu-common.h" -#include "maru_camera_darwin.h" -#include "debug_ch.h" - -MULTI_DEBUG_CHANNEL(tizen, camera); - -static void UYVYToYUV420(unsigned char *bufsrc, unsigned char *bufdest, - int width, int height); -static void YVU420ToYUV420(unsigned char *bufsrc, unsigned char *bufdest, - int width, int height); -static void YUYVToYUV420(unsigned char *bufsrc, unsigned char *bufdest, - int width, int height); - -/* Convert pixel format to YUV420 */ -void convert_frame(uint32_t pixel_format, int frame_width, int frame_height, - size_t frame_size, void *frame_pixels, void *video_buf) -{ - switch (pixel_format) { - case V4L2_PIX_FMT_YUV420: - memcpy(video_buf, (void *)frame_pixels, (size_t)frame_size); - break; - case V4L2_PIX_FMT_YVU420: - YVU420ToYUV420(frame_pixels, video_buf, frame_width, frame_height); - break; - case V4L2_PIX_FMT_YUYV: - YUYVToYUV420(frame_pixels, video_buf, frame_width, frame_height); - break; - case V4L2_PIX_FMT_UYVY: /* Mac default format */ - UYVYToYUV420(frame_pixels, video_buf, frame_width, frame_height); - break; - default: - ERR("Cannot convert the pixel format (%.4s)...\n", - (const char *)&pixel_format); - break; - } -} - -static void UYVYToYUV420(unsigned char *bufsrc, unsigned char *bufdest, - int width, int height) -{ - int i, j; - - /* Source */ - unsigned char *ptrsrcy1, *ptrsrcy2; - unsigned char *ptrsrcy3, *ptrsrcy4; - unsigned char *ptrsrccb1; - unsigned char *ptrsrccb3; - unsigned char *ptrsrccr1; - unsigned char *ptrsrccr3; - int srcystride, srcccstride; - - ptrsrcy1 = bufsrc + 1; - ptrsrcy2 = bufsrc + (width << 1) + 1; - ptrsrcy3 = bufsrc + (width << 1) * 2 + 1; - ptrsrcy4 = bufsrc + (width << 1) * 3 + 1; - - ptrsrccb1 = bufsrc; - ptrsrccb3 = bufsrc + (width << 1) * 2; - - ptrsrccr1 = bufsrc + 2; - ptrsrccr3 = bufsrc + (width << 1) * 2 + 2; - - srcystride = (width << 1) * 3; - srcccstride = (width << 1) * 3; - - /* Destination */ - unsigned char *ptrdesty1, *ptrdesty2; - unsigned char *ptrdesty3, *ptrdesty4; - unsigned char *ptrdestcb1, *ptrdestcb2; - unsigned char *ptrdestcr1, *ptrdestcr2; - int destystride, destccstride; - - ptrdesty1 = bufdest; - ptrdesty2 = bufdest + width; - ptrdesty3 = bufdest + width * 2; - ptrdesty4 = bufdest + width * 3; - - ptrdestcb1 = bufdest + width * height; - ptrdestcb2 = bufdest + width * height + (width >> 1); - - ptrdestcr1 = bufdest + width * height + ((width*height) >> 2); - ptrdestcr2 = bufdest + width * height + ((width*height) >> 2) - + (width >> 1); - - destystride = (width)*3; - destccstride = (width>>1); - - for (j = 0; j < (height / 4); j++) { - for (i = 0; i < (width / 2); i++) { - (*ptrdesty1++) = (*ptrsrcy1); - (*ptrdesty2++) = (*ptrsrcy2); - (*ptrdesty3++) = (*ptrsrcy3); - (*ptrdesty4++) = (*ptrsrcy4); - - ptrsrcy1 += 2; - ptrsrcy2 += 2; - ptrsrcy3 += 2; - ptrsrcy4 += 2; - - (*ptrdesty1++) = (*ptrsrcy1); - (*ptrdesty2++) = (*ptrsrcy2); - (*ptrdesty3++) = (*ptrsrcy3); - (*ptrdesty4++) = (*ptrsrcy4); - - ptrsrcy1 += 2; - ptrsrcy2 += 2; - ptrsrcy3 += 2; - ptrsrcy4 += 2; - - (*ptrdestcb1++) = (*ptrsrccb1); - (*ptrdestcb2++) = (*ptrsrccb3); - - ptrsrccb1 += 4; - ptrsrccb3 += 4; - - (*ptrdestcr1++) = (*ptrsrccr1); - (*ptrdestcr2++) = (*ptrsrccr3); - - ptrsrccr1 += 4; - ptrsrccr3 += 4; - - } - - /* Update src pointers */ - ptrsrcy1 += srcystride; - ptrsrcy2 += srcystride; - ptrsrcy3 += srcystride; - ptrsrcy4 += srcystride; - - ptrsrccb1 += srcccstride; - ptrsrccb3 += srcccstride; - - ptrsrccr1 += srcccstride; - ptrsrccr3 += srcccstride; - - /* Update dest pointers */ - ptrdesty1 += destystride; - ptrdesty2 += destystride; - ptrdesty3 += destystride; - ptrdesty4 += destystride; - - ptrdestcb1 += destccstride; - ptrdestcb2 += destccstride; - - ptrdestcr1 += destccstride; - ptrdestcr2 += destccstride; - } -} - -static void YVU420ToYUV420(unsigned char *bufsrc, unsigned char *bufdest, - int width, int height) -{ - int i, j; - - /* Source*/ - unsigned char *ptrsrcy1, *ptrsrcy2; - unsigned char *ptrsrcy3, *ptrsrcy4; - unsigned char *ptrsrccb1, *ptrsrccb2; - unsigned char *ptrsrccr1, *ptrsrccr2; - int srcystride, srcccstride; - - ptrsrcy1 = bufsrc; - ptrsrcy2 = bufsrc + width; - ptrsrcy3 = bufsrc + width*2; - ptrsrcy4 = bufsrc + width*3; - - ptrsrccr1 = bufsrc + width*height; - ptrsrccr2 = bufsrc + width*height + (width>>1); - - ptrsrccb1 = bufsrc + width*height + ((width*height) >> 2); - ptrsrccb2 = bufsrc + width*height + ((width*height) >> 2) + (width>>1); - - srcystride = (width)*3; - srcccstride = (width>>1); - - /* Destination */ - unsigned char *ptrdesty1, *ptrdesty2; - unsigned char *ptrdesty3, *ptrdesty4; - unsigned char *ptrdestcb1, *ptrdestcb2; - unsigned char *ptrdestcr1, *ptrdestcr2; - int destystride, destccstride; - - ptrdesty1 = bufdest; - ptrdesty2 = bufdest + width; - ptrdesty3 = bufdest + width * 2; - ptrdesty4 = bufdest + width * 3; - - ptrdestcb1 = bufdest + width * height; - ptrdestcb2 = bufdest + width * height + (width >> 1); - - ptrdestcr1 = bufdest + width * height + ((width*height) >> 2); - ptrdestcr2 = bufdest + width * height + ((width*height) >> 2) - + (width >> 1); - - destystride = (width)*3; - destccstride = (width>>1); - - for (j = 0; j < (height / 4); j++) { - for (i = 0; i < (width / 2); i++) { - - (*ptrdesty1++) = (*ptrsrcy1++); - (*ptrdesty2++) = (*ptrsrcy2++); - (*ptrdesty3++) = (*ptrsrcy3++); - (*ptrdesty4++) = (*ptrsrcy4++); - (*ptrdesty1++) = (*ptrsrcy1++); - (*ptrdesty2++) = (*ptrsrcy2++); - (*ptrdesty3++) = (*ptrsrcy3++); - (*ptrdesty4++) = (*ptrsrcy4++); - - (*ptrdestcb1++) = (*ptrsrccb1++); - (*ptrdestcr1++) = (*ptrsrccr1++); - (*ptrdestcb2++) = (*ptrsrccb2++); - (*ptrdestcr2++) = (*ptrsrccr2++); - - } - - /* Update src pointers */ - ptrsrcy1 += srcystride; - ptrsrcy2 += srcystride; - ptrsrcy3 += srcystride; - ptrsrcy4 += srcystride; - - ptrsrccb1 += srcccstride; - ptrsrccb2 += srcccstride; - - ptrsrccr1 += srcccstride; - ptrsrccr2 += srcccstride; - - /* Update dest pointers */ - ptrdesty1 += destystride; - ptrdesty2 += destystride; - ptrdesty3 += destystride; - ptrdesty4 += destystride; - - ptrdestcb1 += destccstride; - ptrdestcb2 += destccstride; - - ptrdestcr1 += destccstride; - ptrdestcr2 += destccstride; - - } - -} - -static void YUYVToYUV420(unsigned char *bufsrc, unsigned char *bufdest, - int width, int height) -{ - int i, j; - - /* Source*/ - unsigned char *ptrsrcy1, *ptrsrcy2; - unsigned char *ptrsrcy3, *ptrsrcy4; - unsigned char *ptrsrccb1; - unsigned char *ptrsrccb3; - unsigned char *ptrsrccr1; - unsigned char *ptrsrccr3; - int srcystride, srcccstride; - - ptrsrcy1 = bufsrc ; - ptrsrcy2 = bufsrc + (width << 1); - ptrsrcy3 = bufsrc + (width << 1) * 2; - ptrsrcy4 = bufsrc + (width << 1) * 3; - - ptrsrccb1 = bufsrc + 1; - ptrsrccb3 = bufsrc + (width << 1) * 2 + 1; - - ptrsrccr1 = bufsrc + 3; - ptrsrccr3 = bufsrc + (width << 1) * 2 + 3; - - srcystride = (width << 1) * 3; - srcccstride = (width << 1) * 3; - - /* Destination */ - unsigned char *ptrdesty1, *ptrdesty2; - unsigned char *ptrdesty3, *ptrdesty4; - unsigned char *ptrdestcb1, *ptrdestcb2; - unsigned char *ptrdestcr1, *ptrdestcr2; - int destystride, destccstride; - - ptrdesty1 = bufdest; - ptrdesty2 = bufdest + width; - ptrdesty3 = bufdest + width * 2; - ptrdesty4 = bufdest + width * 3; - - ptrdestcb1 = bufdest + width * height; - ptrdestcb2 = bufdest + width * height + (width >> 1); - - ptrdestcr1 = bufdest + width * height + ((width * height) >> 2); - ptrdestcr2 = bufdest + width * height + ((width * height) >> 2) - + (width >> 1); - - destystride = width * 3; - destccstride = (width >> 1); - - for (j = 0; j < (height / 4); j++) { - for (i = 0; i < (width / 2); i++) { - (*ptrdesty1++) = (*ptrsrcy1); - (*ptrdesty2++) = (*ptrsrcy2); - (*ptrdesty3++) = (*ptrsrcy3); - (*ptrdesty4++) = (*ptrsrcy4); - - ptrsrcy1 += 2; - ptrsrcy2 += 2; - ptrsrcy3 += 2; - ptrsrcy4 += 2; - - (*ptrdesty1++) = (*ptrsrcy1); - (*ptrdesty2++) = (*ptrsrcy2); - (*ptrdesty3++) = (*ptrsrcy3); - (*ptrdesty4++) = (*ptrsrcy4); - - ptrsrcy1 += 2; - ptrsrcy2 += 2; - ptrsrcy3 += 2; - ptrsrcy4 += 2; - - (*ptrdestcb1++) = (*ptrsrccb1); - (*ptrdestcb2++) = (*ptrsrccb3); - - ptrsrccb1 += 4; - ptrsrccb3 += 4; - - (*ptrdestcr1++) = (*ptrsrccr1); - (*ptrdestcr2++) = (*ptrsrccr3); - - ptrsrccr1 += 4; - ptrsrccr3 += 4; - - } - - /* Update src pointers */ - ptrsrcy1 += srcystride; - ptrsrcy2 += srcystride; - ptrsrcy3 += srcystride; - ptrsrcy4 += srcystride; - - ptrsrccb1 += srcccstride; - ptrsrccb3 += srcccstride; - - ptrsrccr1 += srcccstride; - ptrsrccr3 += srcccstride; - - /* Update dest pointers */ - ptrdesty1 += destystride; - ptrdesty2 += destystride; - ptrdesty3 += destystride; - ptrdesty4 += destystride; - - ptrdestcb1 += destccstride; - ptrdestcb2 += destccstride; - - ptrdestcr1 += destccstride; - ptrdestcr2 += destccstride; - } -} diff --git a/tizen/src/hw/pci/maru_camera_darwin_pci.m b/tizen/src/hw/pci/maru_camera_darwin_pci.m deleted file mode 100644 index b470da3662..0000000000 --- a/tizen/src/hw/pci/maru_camera_darwin_pci.m +++ /dev/null @@ -1,909 +0,0 @@ -/* - * Implementation of MARU Virtual Camera device by PCI bus on MacOS. - * - * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: - * Jun Tian - * JinHyung Jo - * YeongKyoon Lee - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - * Contributors: - * - S-Core Co., Ltd - * - */ - -#import -#import -#import - -#include -#include "qemu-common.h" -#include "maru_camera_common.h" -#include "maru_camera_darwin.h" -#include "debug_ch.h" - -MULTI_DEBUG_CHANNEL(tizen, camera); - -#define MARUCAM_THREAD_NAME "marucam_worker_thread" - -/* V4L2 defines copy from videodev2.h */ -#define V4L2_CTRL_FLAG_SLIDER 0x0020 - -#define V4L2_CTRL_CLASS_USER 0x00980000 -#define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900) -#define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE + 0) -#define V4L2_CID_CONTRAST (V4L2_CID_BASE + 1) -#define V4L2_CID_SATURATION (V4L2_CID_BASE + 2) -#define V4L2_CID_SHARPNESS (V4L2_CID_BASE + 27) - -typedef struct tagMaruCamConvertPixfmt { - uint32_t fmt; /* fourcc */ - uint32_t bpp; /* bits per pixel, 0 for compressed formats */ - uint32_t needs_conversion; -} MaruCamConvertPixfmt; - - -static MaruCamConvertPixfmt supported_dst_pixfmts[] = { - { V4L2_PIX_FMT_YUYV, 16, 0 }, - { V4L2_PIX_FMT_UYVY, 16, 0 }, - { V4L2_PIX_FMT_YUV420, 12, 0 }, - { V4L2_PIX_FMT_YVU420, 12, 0 }, -}; - -typedef struct tagMaruCamConvertFrameInfo { - uint32_t width; - uint32_t height; -} MaruCamConvertFrameInfo; - -static MaruCamConvertFrameInfo supported_dst_frames[] = { - { 640, 480 }, - { 352, 288 }, - { 320, 240 }, - { 176, 144 }, - { 160, 120 }, -}; - -#define MARUCAM_CTRL_VALUE_MAX 20 -#define MARUCAM_CTRL_VALUE_MIN 1 -#define MARUCAM_CTRL_VALUE_MID 10 -#define MARUCAM_CTRL_VALUE_STEP 1 - -enum { - _MC_THREAD_PAUSED, - _MC_THREAD_STREAMON, - _MC_THREAD_STREAMOFF, -}; - -#if 0 -struct marucam_qctrl { - uint32_t id; - uint32_t hit; - long min; - long max; - long step; - long init_val; -}; - -static struct marucam_qctrl qctrl_tbl[] = { - { V4L2_CID_BRIGHTNESS, 0, }, - { V4L2_CID_CONTRAST, 0, }, - { V4L2_CID_SATURATION, 0, }, - { V4L2_CID_SHARPNESS, 0, }, -}; -#endif - -static MaruCamState *g_state; - -static uint32_t ready_count; -static uint32_t cur_fmt_idx; -static uint32_t cur_frame_idx; - -/*********************************** - * Mac camera helper functions - ***********************************/ - -/* Convert Core Video format to FOURCC */ -static uint32_t corevideo_to_fourcc(uint32_t cv_pix_fmt) -{ - switch (cv_pix_fmt) { - case kCVPixelFormatType_420YpCbCr8Planar: - return V4L2_PIX_FMT_YVU420; - case kCVPixelFormatType_422YpCbCr8: - return V4L2_PIX_FMT_UYVY; - case kCVPixelFormatType_422YpCbCr8_yuvs: - return V4L2_PIX_FMT_YUYV; - case kCVPixelFormatType_32ARGB: - case kCVPixelFormatType_32RGBA: - return V4L2_PIX_FMT_RGB32; - case kCVPixelFormatType_32BGRA: - case kCVPixelFormatType_32ABGR: - return V4L2_PIX_FMT_BGR32; - case kCVPixelFormatType_24RGB: - return V4L2_PIX_FMT_RGB24; - case kCVPixelFormatType_24BGR: - return V4L2_PIX_FMT_BGR32; - default: - ERR("Unknown pixel format '%.4s'", (const char *)&cv_pix_fmt); - return 0; - } -} - -static uint32_t get_bytesperline(uint32_t pixfmt, uint32_t width) -{ - uint32_t bytesperline; - - switch (pixfmt) { - case V4L2_PIX_FMT_YUV420: - case V4L2_PIX_FMT_YVU420: - bytesperline = (width * 12) >> 3; - break; - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_UYVY: - default: - bytesperline = width * 2; - break; - } - - return bytesperline; -} - -static uint32_t get_sizeimage(uint32_t pixfmt, uint32_t width, uint32_t height) -{ - return get_bytesperline(pixfmt, width) * height; -} - -/****************************************************************** - ** Maru Camera Implementation - *****************************************************************/ - -@interface MaruCameraDriver : NSObject { - QTCaptureSession *mCaptureSession; - QTCaptureDeviceInput *mCaptureVideoDeviceInput; - QTCaptureVideoPreviewOutput *mCaptureVideoPreviewOutput; - - CVImageBufferRef mCurrentImageBuffer; - BOOL mDeviceIsOpened; - BOOL mCaptureIsStarted; -} - -- (MaruCameraDriver *)init; -- (int)startCapture:(int)width :(int)height; -- (void)stopCapture; -- (int)readFrame:(void *)video_buf; -- (int)setCaptureFormat:(int)width :(int)height :(int)pix_format; -- (int)getCaptureFormat:(int)width :(int)height :(int)pix_format; -- (BOOL)deviceStatus; - -@end - -@implementation MaruCameraDriver - -- (MaruCameraDriver *)init -{ - BOOL success = NO; - NSError *error; - mDeviceIsOpened = NO; - mCaptureIsStarted = NO; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - /* Create the capture session */ - mCaptureSession = [[QTCaptureSession alloc] init]; - - /* Find a video device */ - QTCaptureDevice *videoDevice = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeVideo]; - success = [videoDevice open:&error]; - - /* If a video input device can't be found or opened, try to find and open a muxed input device */ - if (!success) { - videoDevice = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeMuxed]; - success = [videoDevice open:&error]; - [pool release]; - return nil; - } - - if (!success) { - videoDevice = nil; - [pool release]; - return nil; - } - - if (videoDevice) { - /* Add the video device to the session as a device input */ - mCaptureVideoDeviceInput = [[QTCaptureDeviceInput alloc] initWithDevice:videoDevice]; - success = [mCaptureSession addInput:mCaptureVideoDeviceInput error:&error]; - - if (!success) { - [pool release]; - return nil; - } - - mCaptureVideoPreviewOutput = [[QTCaptureVideoPreviewOutput alloc] init]; - success = [mCaptureSession addOutput:mCaptureVideoPreviewOutput error:&error]; - if (!success) { - [pool release]; - return nil; - } - - mDeviceIsOpened = YES; - [mCaptureVideoPreviewOutput setDelegate:self]; - INFO("Camera session bundling successfully!\n"); - [pool release]; - return self; - } else { - [pool release]; - return nil; - } -} - -- (int)startCapture:(int)width :(int)height -{ - int ret = -1; - - if (![mCaptureSession isRunning]) { - /* Set width & height, using default pixel format to capture */ - NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt: width], (id)kCVPixelBufferWidthKey, - [NSNumber numberWithInt: height], (id)kCVPixelBufferHeightKey, - nil]; - [mCaptureVideoPreviewOutput setPixelBufferAttributes:attributes]; - [mCaptureSession startRunning]; - } else { - ERR("Capture session is already running, exit\n"); - return ret; - } - - if ([mCaptureSession isRunning]) { - while(!mCaptureIsStarted) { - /* Wait Until Capture is started */ - [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.5]]; - } - ret = 0; - } - return ret; -} - -- (void)stopCapture -{ - if ([mCaptureSession isRunning]) { - [mCaptureSession stopRunning]; - while([mCaptureSession isRunning]) { - /* Wait Until Capture is stopped */ - [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1]]; - } - - } - mCaptureIsStarted = NO; -} - -- (int)readFrame:(void *)video_buf -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - @synchronized (self) { - if (mCaptureIsStarted == NO) { - [pool release]; - return 0; - } - if (mCurrentImageBuffer != nil) { - CVPixelBufferLockBaseAddress(mCurrentImageBuffer, 0); - const uint32_t pixel_format = corevideo_to_fourcc(CVPixelBufferGetPixelFormatType(mCurrentImageBuffer)); - const int frame_width = CVPixelBufferGetWidth(mCurrentImageBuffer); - const int frame_height = CVPixelBufferGetHeight(mCurrentImageBuffer); - const size_t frame_size = CVPixelBufferGetBytesPerRow(mCurrentImageBuffer) * frame_height; - const void *frame_pixels = CVPixelBufferGetBaseAddress(mCurrentImageBuffer); - - TRACE("buffer(%p), pixel_format(%d,%.4s), frame_width(%d), " - "frame_height(%d), frame_size(%d)\n", - mCurrentImageBuffer, (int)pixel_format, - (const char *)&pixel_format, frame_width, - frame_height, (int)frame_size); - - /* convert frame to v4l2 format */ - convert_frame(pixel_format, frame_width, frame_height, - frame_size, (void *)frame_pixels, video_buf); - CVPixelBufferUnlockBaseAddress(mCurrentImageBuffer, 0); - [pool release]; - return 1; - } - } - - [pool release]; - return -1; -} - -- (int)setCaptureFormat:(int)width :(int)height :(int)pix_format -{ - int ret = -1; - NSDictionary *attributes; - - if (mCaptureSession == nil || mCaptureVideoPreviewOutput == nil) { - ERR("Capture session is not initiated.\n"); - return ret; - } - - /* Set the pixel buffer attributes before running the capture session */ - if (![mCaptureSession isRunning]) { - if (pix_format) { - attributes = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt: width], (id)kCVPixelBufferWidthKey, - [NSNumber numberWithInt: height], (id)kCVPixelBufferHeightKey, - [NSNumber numberWithInt: pix_format], (id)kCVPixelBufferPixelFormatTypeKey, - nil]; - } else { - attributes = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt: width], (id)kCVPixelBufferWidthKey, - [NSNumber numberWithInt: height], (id)kCVPixelBufferHeightKey, - nil]; - } - [mCaptureVideoPreviewOutput setPixelBufferAttributes:attributes]; - ret = 0; - } else { - ERR("Cannot set pixel buffer attributes when it's running.\n"); - return ret; - } - - return ret; -} - -- (int)getCaptureFormat:(int)width :(int)height :(int)pix_format -{ - return 0; -} - -/* Get the device bundling status */ -- (BOOL)deviceStatus -{ - return mDeviceIsOpened; -} - -/* Handle deallocation of memory for your capture objects */ - -- (void)dealloc -{ - [mCaptureSession release]; - [mCaptureVideoDeviceInput release]; - [mCaptureVideoPreviewOutput release]; - [super dealloc]; -} - -/* Receive this method whenever the output decompresses and outputs a new video frame */ -- (void)captureOutput:(QTCaptureOutput *)captureOutput didOutputVideoFrame:(CVImageBufferRef)videoFrame - withSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection -{ - CVImageBufferRef imageBufferToRelease; - CVBufferRetain(videoFrame); - - @synchronized (self) - { - imageBufferToRelease = mCurrentImageBuffer; - mCurrentImageBuffer = videoFrame; - mCaptureIsStarted = YES; - } - CVBufferRelease(imageBufferToRelease); -} - -@end - -/****************************************************************** - ** Maru Camera APIs - *****************************************************************/ - -typedef struct MaruCameraDevice MaruCameraDevice; -struct MaruCameraDevice { - /* Maru camera device object. */ - MaruCameraDriver *driver; -}; - -/* Golbal representation of the Maru camera */ -MaruCameraDevice *mcd = NULL; - -static int is_streamon() -{ - int st; - qemu_mutex_lock(&g_state->thread_mutex); - st = g_state->streamon; - qemu_mutex_unlock(&g_state->thread_mutex); - return (st == _MC_THREAD_STREAMON); -} - -static void __raise_err_intr() -{ - qemu_mutex_lock(&g_state->thread_mutex); - if (g_state->streamon == _MC_THREAD_STREAMON) { - g_state->req_frame = 0; /* clear request */ - g_state->isr = 0x08; /* set a error flag of rasing a interrupt */ - qemu_bh_schedule(g_state->tx_bh); - } - qemu_mutex_unlock(&g_state->thread_mutex); -} - -static int marucam_device_read_frame() -{ - int ret; - void *tmp_buf; - - qemu_mutex_lock(&g_state->thread_mutex); - if (g_state->streamon == _MC_THREAD_STREAMON) { -#if 0 - if (ready_count < MARUCAM_SKIPFRAMES) { - /* skip a frame cause first some frame are distorted */ - ++ready_count; - TRACE("Skip %d frame\n", ready_count); - qemu_mutex_unlock(&g_state->thread_mutex); - return 0; - } -#endif - if (g_state->req_frame == 0) { - TRACE("There is no request\n"); - qemu_mutex_unlock(&g_state->thread_mutex); - return 0; - } - - /* Grab the camera frame into temp buffer */ - tmp_buf = g_state->vaddr + g_state->buf_size * (g_state->req_frame - 1); - ret = [mcd->driver readFrame: tmp_buf]; - if (ret < 0) { - ERR("%s, Capture error\n", __func__); - qemu_mutex_unlock(&g_state->thread_mutex); - __raise_err_intr(); - return -1; - } else if (!ret) { - qemu_mutex_unlock(&g_state->thread_mutex); - return 0; - } - - g_state->req_frame = 0; /* clear request */ - g_state->isr |= 0x01; /* set a flag of rasing a interrupt */ - qemu_bh_schedule(g_state->tx_bh); - } else { - qemu_mutex_unlock(&g_state->thread_mutex); - return -1; - } - qemu_mutex_unlock(&g_state->thread_mutex); - return 0; -} - -/* Worker thread to grab frames to the preview window */ -static void *marucam_worker_thread(void *thread_param) -{ - while (1) { - qemu_mutex_lock(&g_state->thread_mutex); - g_state->streamon = _MC_THREAD_PAUSED; - qemu_cond_wait(&g_state->thread_cond, &g_state->thread_mutex); - qemu_mutex_unlock(&g_state->thread_mutex); - - if (g_state->destroying) { - break; - } - - ready_count = 0; - qemu_mutex_lock(&g_state->thread_mutex); - g_state->streamon = _MC_THREAD_STREAMON; - qemu_mutex_unlock(&g_state->thread_mutex); - INFO("Streaming on ......\n"); - - /* Loop: capture frame -> convert format -> render to screen */ - while (1) { - if (is_streamon()) { - if (marucam_device_read_frame() < 0) { - INFO("Streaming is off ...\n"); - break; - } else { - /* wait until next frame is avalilable */ - usleep(22000); - } - } else { - INFO("Streaming is off ...\n"); - break; - } - } - } - - return NULL; -} - -int marucam_device_check(int log_flag) -{ - /* FIXME: check the device parameters */ - INFO("Checking camera device\n"); - return 1; -} - -/********************************************** - * MARU camera routines - **********************************************/ -void marucam_device_init(MaruCamState *state) -{ - g_state = state; - g_state->destroying = false; - qemu_thread_create(&state->thread_id, - MARUCAM_THREAD_NAME, - marucam_worker_thread, - NULL, - QEMU_THREAD_JOINABLE); -} - -void marucam_device_exit(MaruCamState *state) -{ - state->destroying = true; - qemu_mutex_lock(&state->thread_mutex); - qemu_cond_signal(&state->thread_cond); - qemu_mutex_unlock(&state->thread_mutex); - qemu_thread_join(&state->thread_id); -} - -/* MARUCAM_CMD_OPEN */ -void marucam_device_open(MaruCamState *state) -{ - MaruCamParam *param = state->param; - param->top = 0; - - mcd = (MaruCameraDevice *)malloc(sizeof(MaruCameraDevice)); - if (mcd == NULL) { - ERR("%s: MaruCameraDevice allocate failed\n", __func__); - param->errCode = EINVAL; - return; - } - memset(mcd, 0, sizeof(MaruCameraDevice)); - mcd->driver = [[MaruCameraDriver alloc] init]; - if (mcd->driver == nil) { - ERR("Camera device open failed\n"); - [mcd->driver dealloc]; - free(mcd); - param->errCode = EINVAL; - return; - } - INFO("Camera opened!\n"); -} - -/* MARUCAM_CMD_CLOSE */ -void marucam_device_close(MaruCamState *state) -{ - MaruCamParam *param = state->param; - param->top = 0; - - if (mcd != NULL) { - if (is_streamon()) { - marucam_device_stop_preview(state); - } - [mcd->driver dealloc]; - free(mcd); - mcd = NULL; - } - - /* marucam_reset_controls(); */ - INFO("Camera closed\n"); -} - -/* MARUCAM_CMD_START_PREVIEW */ -void marucam_device_start_preview(MaruCamState *state) -{ - uint32_t width, height, pixfmt; - MaruCamParam *param = state->param; - param->top = 0; - - width = supported_dst_frames[cur_frame_idx].width; - height = supported_dst_frames[cur_frame_idx].height; - pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; - state->buf_size = get_sizeimage(pixfmt, width, height); - - INFO("Pixfmt(%c%c%c%c), W:H(%d:%d), buf size(%u), frame idx(%d), fmt idx(%d)\n", - (char)(pixfmt), (char)(pixfmt >> 8), - (char)(pixfmt >> 16), (char)(pixfmt >> 24), - width, height, state->buf_size, - cur_frame_idx, cur_fmt_idx); - - if (mcd->driver == nil) { - ERR("%s: Start capture failed: vaild device", __func__); - param->errCode = EINVAL; - return; - } - - INFO("Starting preview ...\n"); - [mcd->driver startCapture: width: height]; - - /* Enable the condition to capture frames now */ - qemu_mutex_lock(&state->thread_mutex); - qemu_cond_signal(&state->thread_cond); - qemu_mutex_unlock(&state->thread_mutex); - - while (!is_streamon()) { - usleep(10000); - } -} - -/* MARUCAM_CMD_STOP_PREVIEW */ -void marucam_device_stop_preview(MaruCamState *state) -{ - MaruCamParam *param = state->param; - param->top = 0; - - if (is_streamon()) { - qemu_mutex_lock(&state->thread_mutex); - state->streamon = _MC_THREAD_STREAMOFF; - qemu_mutex_unlock(&state->thread_mutex); - - while (is_streamon()) { - usleep(10000); - } - } - - if (mcd->driver != nil) { - [mcd->driver stopCapture]; - } - - state->buf_size = 0; - INFO("Stopping preview ...\n"); -} - -/* MARUCAM_CMD_S_PARAM */ -void marucam_device_s_param(MaruCamState *state) -{ - MaruCamParam *param = state->param; - - /* We use default FPS of the webcam */ - param->top = 0; -} - -/* MARUCAM_CMD_G_PARAM */ -void marucam_device_g_param(MaruCamState *state) -{ - MaruCamParam *param = state->param; - /* We use default FPS of the webcam - * return a fixed value on guest ini file (1/30). - */ - param->top = 0; - param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */ - param->stack[1] = 1; /* numerator */ - param->stack[2] = 30; /* denominator */ -} - -/* MARUCAM_CMD_S_FMT */ -void marucam_device_s_fmt(MaruCamState *state) -{ - MaruCamParam *param = state->param; - uint32_t width, height, pixfmt, pidx, fidx; - - param->top = 0; - width = param->stack[0]; - height = param->stack[1]; - pixfmt = param->stack[2]; - - TRACE("Set format: width(%d), height(%d), pixfmt(%d, %.4s)\n", - width, height, pixfmt, (const char*)&pixfmt); - - for (fidx = 0; fidx < ARRAY_SIZE(supported_dst_frames); fidx++) { - if ((supported_dst_frames[fidx].width == width) && - (supported_dst_frames[fidx].height == height)) { - break; - } - } - if (fidx == ARRAY_SIZE(supported_dst_frames)) { - param->errCode = EINVAL; - return; - } - - for (pidx = 0; pidx < ARRAY_SIZE(supported_dst_pixfmts); pidx++) { - if (supported_dst_pixfmts[pidx].fmt == pixfmt) { - TRACE("pixfmt index is match: %d\n", pidx); - break; - } - } - if (pidx == ARRAY_SIZE(supported_dst_pixfmts)) { - param->errCode = EINVAL; - return; - } - - if ((supported_dst_frames[cur_frame_idx].width != width) && - (supported_dst_frames[cur_frame_idx].height != height)) { - if (mcd->driver == nil || [mcd->driver setCaptureFormat: width: height: 0] < 0) { - ERR("Set pixel format failed\n"); - param->errCode = EINVAL; - return; - } - - TRACE("cur_frame_idx:%d, supported_dst_frames[cur_frame_idx].width:%d\n", - cur_frame_idx, supported_dst_frames[cur_frame_idx].width); - } - - cur_frame_idx = fidx; - cur_fmt_idx = pidx; - - pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; - width = supported_dst_frames[cur_frame_idx].width; - height = supported_dst_frames[cur_frame_idx].height; - - param->stack[0] = width; - param->stack[1] = height; - param->stack[2] = 1; /* V4L2_FIELD_NONE */ - param->stack[3] = pixfmt; - param->stack[4] = get_bytesperline(pixfmt, width); - param->stack[5] = get_sizeimage(pixfmt, width, height); - param->stack[6] = 0; - param->stack[7] = 0; - - TRACE("Set device pixel format ...\n"); -} - -/* MARUCAM_CMD_G_FMT */ -void marucam_device_g_fmt(MaruCamState *state) -{ - uint32_t width, height, pixfmt; - MaruCamParam *param = state->param; - - param->top = 0; - pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; - width = supported_dst_frames[cur_frame_idx].width; - height = supported_dst_frames[cur_frame_idx].height; - - param->stack[0] = width; - param->stack[1] = height; - param->stack[2] = 1; /* V4L2_FIELD_NONE */ - param->stack[3] = pixfmt; - param->stack[4] = get_bytesperline(pixfmt, width); - param->stack[5] = get_sizeimage(pixfmt, width, height); - param->stack[6] = 0; - param->stack[7] = 0; - - TRACE("Get device frame format ...\n"); -} - -void marucam_device_try_fmt(MaruCamState *state) -{ - TRACE("Try device frame format, use default setting ...\n"); -} - -/* Get specific pixelformat description */ -void marucam_device_enum_fmt(MaruCamState *state) -{ - uint32_t index; - MaruCamParam *param = state->param; - - param->top = 0; - index = param->stack[0]; - - if (index >= ARRAY_SIZE(supported_dst_pixfmts)) { - param->errCode = EINVAL; - return; - } - param->stack[1] = 0; /* flags = NONE */ - param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */ - switch (supported_dst_pixfmts[index].fmt) { - case V4L2_PIX_FMT_YUYV: - memcpy(¶m->stack[3], "YUYV", 32); - break; - case V4L2_PIX_FMT_UYVY: - memcpy(¶m->stack[3], "UYVY", 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: - param->errCode = EINVAL; - break; - } -} - -/* - * QTKit don't support setting brightness, contrast, saturation & sharpness - */ -void marucam_device_qctrl(MaruCamState *state) -{ - uint32_t id, i; - /* long property, min, max, step, def_val, set_val; */ - char name[32] = {0,}; - MaruCamParam *param = state->param; - - param->top = 0; - id = param->stack[0]; - - switch (id) { - case V4L2_CID_BRIGHTNESS: - TRACE("V4L2_CID_BRIGHTNESS\n"); - memcpy((void *)name, (void *)"brightness", 32); - i = 0; - break; - case V4L2_CID_CONTRAST: - TRACE("V4L2_CID_CONTRAST\n"); - memcpy((void *)name, (void *)"contrast", 32); - i = 1; - break; - case V4L2_CID_SATURATION: - TRACE("V4L2_CID_SATURATION\n"); - memcpy((void *)name, (void *)"saturation", 32); - i = 2; - break; - case V4L2_CID_SHARPNESS: - TRACE("V4L2_CID_SHARPNESS\n"); - memcpy((void *)name, (void *)"sharpness", 32); - i = 3; - break; - default: - param->errCode = EINVAL; - return; - } - - param->stack[0] = id; - param->stack[1] = MARUCAM_CTRL_VALUE_MIN; /* minimum */ - param->stack[2] = MARUCAM_CTRL_VALUE_MAX; /* maximum */ - param->stack[3] = MARUCAM_CTRL_VALUE_STEP; /* step */ - param->stack[4] = MARUCAM_CTRL_VALUE_MID; /* default_value */ - param->stack[5] = V4L2_CTRL_FLAG_SLIDER; - /* name field setting */ - memcpy(¶m->stack[6], (void *)name, sizeof(name)/sizeof(name[0])); -} - -void marucam_device_s_ctrl(MaruCamState *state) -{ - INFO("Set control\n"); -} - -void marucam_device_g_ctrl(MaruCamState *state) -{ - INFO("Get control\n"); -} - -/* Get frame width & height */ -void marucam_device_enum_fsizes(MaruCamState *state) -{ - uint32_t index, pixfmt, i; - MaruCamParam *param = state->param; - - param->top = 0; - index = param->stack[0]; - pixfmt = param->stack[1]; - - if (index >= ARRAY_SIZE(supported_dst_frames)) { - param->errCode = EINVAL; - return; - } - for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) { - if (supported_dst_pixfmts[i].fmt == pixfmt) { - break; - } - } - - if (i == ARRAY_SIZE(supported_dst_pixfmts)) { - param->errCode = EINVAL; - return; - } - - param->stack[0] = supported_dst_frames[index].width; - param->stack[1] = supported_dst_frames[index].height; -} - -void marucam_device_enum_fintv(MaruCamState *state) -{ - MaruCamParam *param = state->param; - param->top = 0; - - /* switch by index(param->stack[0]) */ - switch (param->stack[0]) { - case 0: - param->stack[1] = 30; /* denominator */ - break; - default: - param->errCode = EINVAL; - return; - } - param->stack[0] = 1; /* numerator */ -} diff --git a/tizen/src/hw/pci/maru_camera_linux.c b/tizen/src/hw/pci/maru_camera_linux.c new file mode 100644 index 0000000000..2a76c07ab1 --- /dev/null +++ b/tizen/src/hw/pci/maru_camera_linux.c @@ -0,0 +1,1391 @@ +/* + * Implementation of MARU Virtual Camera device by PCI bus on Linux. + * + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jinhyung Jo + * Sangho Park + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "qemu-common.h" +#include "sysemu/kvm.h" +#include "maru_camera.h" +#include "debug_ch.h" + +#include + +#include +#include +#include + +#include +#include + +MULTI_DEBUG_CHANNEL(tizen, camera); + +#define MARUCAM_THREAD_NAME "marucam_worker_thread" + +#define CLEAR(x) memset(&(x), 0, sizeof(x)) + +#define MARUCAM_DEFAULT_BUFFER_COUNT 4 + +#define MARUCAM_CTRL_VALUE_MAX 20 +#define MARUCAM_CTRL_VALUE_MIN 1 +#define MARUCAM_CTRL_VALUE_MID 10 +#define MARUCAM_CTRL_VALUE_STEP 1 + +enum { + _MC_THREAD_PAUSED, + _MC_THREAD_STREAMON, + _MC_THREAD_STREAMOFF, +}; + +typedef struct marucam_framebuffer { + void *data; + size_t size; +} marucam_framebuffer; + +struct marucam_saved_frame { + void *data; + uint32_t pixelformat; + uint32_t width; + uint32_t height; + uint32_t size; +}; + +static struct marucam_saved_frame saved_frame; +static char has_success_frame; +static int n_framebuffer; +static int previous_frame_index = -1; +static struct marucam_framebuffer *framebuffer; + +static const char *dev_name = "/dev/video0"; +static int v4l2_fd; +static int convert_trial; +static int ready_count; +static int timeout_n; + +static struct v4l2_format dst_fmt; + +static void ScalePlaneSimple(int src_width, int src_height, + int dst_width, int dst_height, + int src_stride, int dst_stride, + const uint8_t *src_ptr, uint8_t *dst_ptr) { + int i, j; + int dx = (src_width << 16) / dst_width; + int dy = (src_height << 16) / dst_height; + int y = (dy >= 65536) ? ((dy >> 1) - 32768) : (dy >> 1); + for (j = 0; j < dst_height; ++j) { + int x = (dx >= 65536) ? ((dx >> 1) - 32768) : (dx >> 1); + int yi = y >> 16; + const uint8_t *src = src_ptr + yi * src_stride; + uint8_t *dst = dst_ptr; + for (i = 0; i < dst_width; ++i) { + *dst++ = src[x >> 16]; + x += dx; + } + dst_ptr += dst_stride; + y += dy; + } +} + +static void make_yu12_black(unsigned char *dest, uint32_t width, uint32_t height) +{ + uint32_t x, y; + unsigned char *udest, *vdest; + + /* Y */ + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + *dest++ = 16; + } + } + + /* U + V */ + udest = dest; + vdest = dest + width * height / 4; + + for (y = 0; y < height / 2; y++) { + for (x = 0; x < width / 2; x++) { + *udest++ = *vdest++ = 128; + } + } +} + +static void marucam_scale_yuv420(void *src, + uint32_t src_width, uint32_t src_height, + void *dst, uint32_t dst_width, uint32_t dst_height) +{ + uint32_t src_halfwidth = (src_width + 1) >> 1; + uint32_t src_halfheight = (src_height + 1) >> 1; + uint32_t dst_halfwidth = (dst_width + 1) >> 1; + uint32_t dst_halfheight = (dst_height + 1) >> 1; + + uint8_t *src_u = src + (src_width * src_height); + uint8_t *src_v = src_u + (src_width * src_height / 4); + + uint8_t *dst_u = dst + (dst_width * dst_height); + uint8_t *dst_v = dst_u + (dst_width * dst_height /4); + + ScalePlaneSimple(src_width, src_height, + dst_width, dst_height, + src_width, dst_width, + src, dst); + ScalePlaneSimple(src_halfwidth, src_halfheight, + dst_halfwidth, dst_halfheight, + src_halfwidth, dst_halfwidth, + src_u, dst_u); + ScalePlaneSimple(src_halfwidth, src_halfheight, + dst_halfwidth, dst_halfheight, + src_halfwidth, dst_halfwidth, + src_v, dst_v); +} + +static int yioctl(int fd, int req, void *arg) +{ + int r; + + do { + r = ioctl(fd, req, arg); + } while (r < 0 && errno == EINTR); + + return r; +} + +static int xioctl(int fd, int req, void *arg) +{ + int r; + + do { + r = v4l2_ioctl(fd, req, arg); + } while (r < 0 && errno == EINTR); + + return r; +} + +typedef struct tagMaruCamConvertPixfmt { + uint32_t fmt; /* fourcc */ +} MaruCamConvertPixfmt; + +static MaruCamConvertPixfmt supported_dst_pixfmts[] = { + { V4L2_PIX_FMT_YUYV }, + { V4L2_PIX_FMT_YUV420 }, + { V4L2_PIX_FMT_YVU420 }, +}; + +typedef struct tagMaruCamConvertFrameInfo { + uint32_t width; + uint32_t height; +} MaruCamConvertFrameInfo; + +static MaruCamConvertFrameInfo supported_dst_frames[] = { + { 640, 480 }, + { 352, 288 }, + { 320, 240 }, + { 176, 144 }, + { 160, 120 }, +}; + +struct marucam_qctrl { + uint32_t id; + uint32_t hit; + int32_t min; + int32_t max; + int32_t step; + int32_t init_val; +}; + +static struct marucam_qctrl qctrl_tbl[] = { + { V4L2_CID_BRIGHTNESS, 0, }, + { V4L2_CID_CONTRAST, 0, }, + { V4L2_CID_SATURATION, 0, }, + { V4L2_CID_SHARPNESS, 0, }, +}; + +static void marucam_reset_controls(void) +{ + uint32_t i; + for (i = 0; i < ARRAY_SIZE(qctrl_tbl); i++) { + if (qctrl_tbl[i].hit) { + struct v4l2_control ctrl = {0,}; + ctrl.id = qctrl_tbl[i].id; + ctrl.value = qctrl_tbl[i].init_val; + qctrl_tbl[i].hit = qctrl_tbl[i].init_val = 0; + qctrl_tbl[i].min = qctrl_tbl[i].max = qctrl_tbl[i].step = 0; + if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) { + ERR("Failed to reset control value: id(0x%x), errstr(%s)\n", + ctrl.id, strerror(errno)); + } + } + } + TRACE("[%s] Reset done\n", __func__); +} + +static int32_t value_convert_from_guest(int32_t min, int32_t max, int32_t value) +{ + double rate = 0.0; + int32_t dist = 0, ret = 0; + + dist = max - min; + + if (dist < MARUCAM_CTRL_VALUE_MAX) { + rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; + ret = min + (int32_t)(value / rate); + } else { + rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; + ret = min + (int32_t)(rate * value); + } + return ret; +} + +static int32_t value_convert_to_guest(int32_t min, int32_t max, int32_t value) +{ + double rate = 0.0; + int32_t dist = 0, ret = 0; + + dist = max - min; + + if (dist < MARUCAM_CTRL_VALUE_MAX) { + rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; + ret = (int32_t)((double)(value - min) * rate); + } else { + rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; + ret = (int32_t)((double)(value - min) / rate); + } + + return ret; +} + +static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format, + uint32_t width, uint32_t height) +{ + struct v4l2_frmivalenum fival; + struct v4l2_streamparm sp; + uint32_t min_num = 0, min_denom = 0; + + CLEAR(fival); + fival.pixel_format = pixel_format; + fival.width = width; + fival.height = height; + + if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) < 0) { + ERR("Unable to enumerate intervals for pixelformat(0x%x), (%d:%d)\n", + pixel_format, width, height); + return; + } + + if (fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { + float max_ival = -1.0; + do { + float cur_ival = (float)fival.discrete.numerator + / (float)fival.discrete.denominator; + if (cur_ival > max_ival) { + max_ival = cur_ival; + min_num = fival.discrete.numerator; + min_denom = fival.discrete.denominator; + } + TRACE("Discrete frame interval %u/%u supported\n", + fival.discrete.numerator, fival.discrete.denominator); + fival.index++; + } while (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) >= 0); + } else if ((fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) || + (fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)) { + TRACE("Frame intervals from %u/%u to %u/%u supported", + fival.stepwise.min.numerator, fival.stepwise.min.denominator, + fival.stepwise.max.numerator, fival.stepwise.max.denominator); + if (fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) { + TRACE("with %u/%u step", fival.stepwise.step.numerator, + fival.stepwise.step.denominator); + } + if (((float)fival.stepwise.max.denominator / + (float)fival.stepwise.max.numerator) > + ((float)fival.stepwise.min.denominator / + (float)fival.stepwise.min.numerator)) { + min_num = fival.stepwise.max.numerator; + min_denom = fival.stepwise.max.denominator; + } else { + min_num = fival.stepwise.min.numerator; + min_denom = fival.stepwise.min.denominator; + } + } + TRACE("The actual min values: %u/%u\n", min_num, min_denom); + + CLEAR(sp); + sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + sp.parm.capture.timeperframe.numerator = min_num; + sp.parm.capture.timeperframe.denominator = min_denom; + + if (xioctl(v4l2_fd, VIDIOC_S_PARM, &sp) < 0) { + ERR("Failed to set to minimum FPS(%u/%u)\n", min_num, min_denom); + } +} + +static uint32_t stop_capturing(void) +{ + enum v4l2_buf_type type; + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (xioctl(v4l2_fd, VIDIOC_STREAMOFF, &type) < 0) { + ERR("Failed to ioctl() with VIDIOC_STREAMOFF: %s\n", strerror(errno)); + return errno; + } + return 0; +} + +static uint32_t start_capturing(void) +{ + enum v4l2_buf_type type; + + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (xioctl(v4l2_fd, VIDIOC_STREAMON, &type) < 0) { + ERR("Failed to ioctl() with VIDIOC_STREAMON: %s\n", strerror(errno)); + return errno; + } + return 0; +} + +static void free_framebuffers(marucam_framebuffer *fb, int buf_num) +{ + int i; + + if (fb == NULL) { + ERR("The framebuffer is NULL. Failed to release the framebuffer\n"); + return; + } else if (buf_num == 0) { + ERR("The buffer count is 0. Failed to release the framebuffer\n"); + return; + } else { + TRACE("[%s]:fb(0x%p), buf_num(%d)\n", __func__, fb, buf_num); + } + + /* Unmap framebuffers. */ + for (i = 0; i < buf_num; i++) { + if (fb[i].data != NULL) { + v4l2_munmap(fb[i].data, fb[i].size); + fb[i].data = NULL; + fb[i].size = 0; + } else { + ERR("framebuffer[%d].data is NULL.\n", i); + } + } + previous_frame_index = -1; +} + +static uint32_t +mmap_framebuffers(marucam_framebuffer **fb, int *buf_num) +{ + struct v4l2_requestbuffers req; + + CLEAR(req); + req.count = MARUCAM_DEFAULT_BUFFER_COUNT; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; + if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &req) < 0) { + if (errno == EINVAL) { + ERR("%s does not support memory mapping: %s\n", + dev_name, strerror(errno)); + } else { + ERR("Failed to request bufs: %s\n", strerror(errno)); + } + return errno; + } + if (req.count == 0) { + ERR("Insufficient buffer memory on %s\n", dev_name); + return EINVAL; + } + + *fb = g_new0(marucam_framebuffer, req.count); + if (*fb == NULL) { + ERR("Not enough memory to allocate framebuffers\n"); + return ENOMEM; + } + + for (*buf_num = 0; *buf_num < req.count; ++*buf_num) { + struct v4l2_buffer buf; + CLEAR(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = *buf_num; + if (xioctl(v4l2_fd, VIDIOC_QUERYBUF, &buf) < 0) { + ERR("Failed to ioctl() with VIDIOC_QUERYBUF: %s\n", + strerror(errno)); + return errno; + } + + (*fb)[*buf_num].size = buf.length; + (*fb)[*buf_num].data = v4l2_mmap(NULL, + buf.length, + PROT_READ | PROT_WRITE, + MAP_SHARED, + v4l2_fd, buf.m.offset); + if (MAP_FAILED == (*fb)[*buf_num].data) { + ERR("Failed to mmap: %s\n", strerror(errno)); + return errno; + } + + /* Queue the mapped buffer. */ + CLEAR(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = *buf_num; + if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) { + ERR("Failed to ioctl() with VIDIOC_QBUF: %s\n", strerror(errno)); + return errno; + } + } + return 0; +} + +static int is_streamon(MaruCamState *state) +{ + int st; + qemu_mutex_lock(&state->thread_mutex); + st = state->streamon; + qemu_mutex_unlock(&state->thread_mutex); + return (st == _MC_THREAD_STREAMON); +} + +static int is_stream_paused(MaruCamState *state) +{ + int st; + qemu_mutex_lock(&state->thread_mutex); + st = state->streamon; + qemu_mutex_unlock(&state->thread_mutex); + return (st == _MC_THREAD_PAUSED); +} + +/* sends a frame, YU12/black color */ +/* TODO: add other pixel format method */ +static void __raise_dummy_intr(MaruCamState *state) +{ + void *buf = NULL; + qemu_mutex_lock(&state->thread_mutex); + if (state->streamon == _MC_THREAD_STREAMON && state->req_frame) { + buf = state->vaddr + state->buf_size * (state->req_frame - 1); + if (saved_frame.data) { + if (saved_frame.width == dst_fmt.fmt.pix.width && + saved_frame.height == dst_fmt.fmt.pix.height) { + TRACE("Copies the previuos frame\n"); + memcpy(buf, saved_frame.data, state->buf_size); + } else { + TRACE("Resizes the previous frame\n"); + marucam_scale_yuv420(saved_frame.data, saved_frame.width, + saved_frame.height, + buf, dst_fmt.fmt.pix.width, + dst_fmt.fmt.pix.height); + } + } else { + TRACE("Sends a black frame\n"); + make_yu12_black(buf, + dst_fmt.fmt.pix.width, + dst_fmt.fmt.pix.height); + } + state->req_frame = 0; /* clear request */ + state->isr |= 0x01; /* set a flag of raising a interrupt */ + qemu_bh_schedule(state->tx_bh); + } + qemu_mutex_unlock(&state->thread_mutex); +} + +static void __raise_err_intr(MaruCamState *state) +{ + qemu_mutex_lock(&state->thread_mutex); + if (state->streamon == _MC_THREAD_STREAMON) { + state->req_frame = 0; /* clear request */ + state->isr = 0x08; /* set a error flag of raising a interrupt */ + qemu_bh_schedule(state->tx_bh); + } + qemu_mutex_unlock(&state->thread_mutex); +} + +static void +notify_buffer_ready(MaruCamState *state, uint32_t buf_index) +{ + void *buf = NULL; + + qemu_mutex_lock(&state->thread_mutex); + if (state->streamon == _MC_THREAD_STREAMON) { + if (ready_count < MARUCAM_SKIPFRAMES) { + /* skip a frame cause first some frame are distorted */ + ++ready_count; + TRACE("Skip %d frame\n", ready_count); + qemu_mutex_unlock(&state->thread_mutex); + return; + } + if (state->req_frame == 0) { + qemu_mutex_unlock(&state->thread_mutex); + return; + } + buf = state->vaddr + state->buf_size * (state->req_frame - 1); + memcpy(buf, framebuffer[buf_index].data, state->buf_size); + previous_frame_index = buf_index; + has_success_frame = 1; + state->req_frame = 0; /* clear request */ + state->isr |= 0x01; /* set a flag of rasing a interrupt */ + qemu_bh_schedule(state->tx_bh); + } + qemu_mutex_unlock(&state->thread_mutex); +} + +static int read_frame(MaruCamState *state) +{ + struct v4l2_buffer buf; + + CLEAR(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + if (xioctl(v4l2_fd, VIDIOC_DQBUF, &buf) < 0) { + switch (errno) { + case EAGAIN: + case EINTR: + ERR("DQBUF error, try again: %s\n", strerror(errno)); + return 0; + case EIO: + ERR("The v4l2_read() met the EIO\n"); + if (convert_trial-- == -1) { + ERR("Try count for v4l2_read is exceeded: %s\n", + strerror(errno)); + return -1; + } + return 0; + default: + ERR("DQBUF error: %s\n", strerror(errno)); + return -1; + } + } + + notify_buffer_ready(state, buf.index); + + if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) { + ERR("QBUF error: %s\n", strerror(errno)); + return -1; + } + return 0; +} + +static int __v4l2_streaming(MaruCamState *state) +{ + fd_set fds; + struct timeval tv; + int ret; + + FD_ZERO(&fds); + FD_SET(v4l2_fd, &fds); + + tv.tv_sec = 1; + tv.tv_usec = 0; + + ret = select(v4l2_fd + 1, &fds, NULL, NULL, &tv); + if (ret < 0) { + if (errno == EAGAIN || errno == EINTR) { + ERR("Select again: %s\n", strerror(errno)); + return 0; + } + ERR("Failed to select: %s\n", strerror(errno)); + __raise_err_intr(state); + return -1; + } else if (!ret) { + timeout_n++; + ERR("Select timed out: count(%u)\n", timeout_n); + if (ready_count <= MARUCAM_SKIPFRAMES) { + switch (timeout_n) { + case 1: + ERR("Waiting for reading a frame data\n"); + return 0; + case 2: + case 3: + case 4: + ERR("Sends dummy data to initialize the camera\n"); + __raise_dummy_intr(state); + return 0; + default: + ERR("Webcam is busy, failed to a read frame." + " Raises an error\n"); + __raise_err_intr(state); + return -1; + } + } + if (timeout_n >= 5) { + ERR("Webcam is busy, failed to a read frame. Raises an error\n"); + __raise_err_intr(state); + return -1; + } + if (previous_frame_index != -1) { + ERR("Sends previous frame data\n"); + notify_buffer_ready(state, previous_frame_index); + } + return 0; + } + + if (!v4l2_fd || (v4l2_fd == -1)) { + ERR("The file descriptor is closed or not opened\n"); + __raise_err_intr(state); + return -1; + } + + ret = read_frame(state); + if (ret < 0) { + ERR("Failed to operate the read_frame()\n"); + __raise_err_intr(state); + return -1; + } + + /* clear the skip count for select time-out */ + if (timeout_n > 0) { + timeout_n = 0; + } + + return 0; +} + +/* Worker thread */ +static void *marucam_worker_thread(void *thread_param) +{ + MaruCamState *state = (MaruCamState *)thread_param; + + while (1) { + qemu_mutex_lock(&state->thread_mutex); + state->streamon = _MC_THREAD_PAUSED; + qemu_cond_wait(&state->thread_cond, &state->thread_mutex); + qemu_mutex_unlock(&state->thread_mutex); + + if (state->destroying) { + break; + } + + convert_trial = 10; + ready_count = 0; + timeout_n = 0; + has_success_frame = 0; + qemu_mutex_lock(&state->thread_mutex); + state->streamon = _MC_THREAD_STREAMON; + qemu_mutex_unlock(&state->thread_mutex); + INFO("Streaming on ......\n"); + + while (1) { + if (is_streamon(state)) { + if (__v4l2_streaming(state) < 0) { + INFO("...... Streaming off\n"); + break; + } + } else { + INFO("...... Streaming off\n"); + break; + } + } + } + + return NULL; +} + +int marucam_device_check(int log_flag) +{ + int tmp_fd; + struct timeval t1, t2; + struct stat st; + struct v4l2_fmtdesc format; + struct v4l2_frmsizeenum size; + struct v4l2_capability cap; + int ret = 0; + + gettimeofday(&t1, NULL); + if (stat(dev_name, &st) < 0) { + INFO(" Cannot identify '%s': %s\n", + dev_name, strerror(errno)); + } else { + if (!S_ISCHR(st.st_mode)) { + INFO("%s is no character device\n", + dev_name); + } + } + + tmp_fd = open(dev_name, O_RDWR | O_NONBLOCK, 0); + if (tmp_fd < 0) { + ERR("Camera device open failed: %s\n", dev_name); + gettimeofday(&t2, NULL); + ERR("Elapsed time: %lu:%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + if (ioctl(tmp_fd, VIDIOC_QUERYCAP, &cap) < 0) { + ERR("Could not qeury video capabilities\n"); + close(tmp_fd); + gettimeofday(&t2, NULL); + ERR("Elapsed time: %lu:%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) || + !(cap.capabilities & V4L2_CAP_STREAMING)) { + ERR("Not supported video driver\n"); + close(tmp_fd); + gettimeofday(&t2, NULL); + ERR("Elapsed time: %lu:%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + ret = 1; + + if (log_flag) { + INFO("Driver: %s\n", cap.driver); + INFO("Card: %s\n", cap.card); + INFO("Bus info: %s\n", cap.bus_info); + + CLEAR(format); + format.index = 0; + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) < 0) { + close(tmp_fd); + gettimeofday(&t2, NULL); + ERR("Elapsed time: %lu:%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + do { + CLEAR(size); + size.index = 0; + size.pixel_format = format.pixelformat; + + INFO("PixelFormat: %c%c%c%c\n", + (char)(format.pixelformat), + (char)(format.pixelformat >> 8), + (char)(format.pixelformat >> 16), + (char)(format.pixelformat >> 24)); + + if (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0) { + close(tmp_fd); + gettimeofday(&t2, NULL); + ERR("Elapsed time: %lu:%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) { + do { + INFO("\tGot a discrete frame size %dx%d\n", + size.discrete.width, size.discrete.height); + size.index++; + } while (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0); + } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) { + INFO("We have stepwise frame sizes:\n"); + INFO("\tmin width: %d, min height: %d\n", + size.stepwise.min_width, size.stepwise.min_height); + INFO("\tmax width: %d, max height: %d\n", + size.stepwise.max_width, size.stepwise.max_height); + INFO("\tstep width: %d, step height: %d\n", + size.stepwise.step_width, size.stepwise.step_height); + } else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) { + INFO("We have continuous frame sizes:\n"); + INFO("\tmin width: %d, min height: %d\n", + size.stepwise.min_width, size.stepwise.min_height); + INFO("\tmax width: %d, max height: %d\n", + size.stepwise.max_width, size.stepwise.max_height); + + } + format.index++; + } while (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) >= 0); + } + + close(tmp_fd); + gettimeofday(&t2, NULL); + INFO("Elapsed time: %lu:%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; +} + +void marucam_device_init(MaruCamState *state) +{ + state->destroying = false; + qemu_thread_create(&state->thread_id, + MARUCAM_THREAD_NAME, + marucam_worker_thread, + (void *)state, + QEMU_THREAD_JOINABLE); +} + +void marucam_device_exit(MaruCamState *state) +{ + state->destroying = true; + qemu_mutex_lock(&state->thread_mutex); + qemu_cond_signal(&state->thread_cond); + qemu_mutex_unlock(&state->thread_mutex); + qemu_thread_join(&state->thread_id); +} + +void marucam_device_open(MaruCamState *state) +{ + MaruCamParam *param = state->param; + + param->top = 0; + v4l2_fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0); + if (v4l2_fd < 0) { + ERR("The v4l2 device open failed: %s\n", dev_name); + param->errCode = EINVAL; + return; + } + INFO("Opened\n"); + + /* FIXME : Do not use fixed values */ + CLEAR(dst_fmt); + dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + dst_fmt.fmt.pix.width = 640; + dst_fmt.fmt.pix.height = 480; + dst_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + dst_fmt.fmt.pix.field = V4L2_FIELD_ANY; + + if (xioctl(v4l2_fd, VIDIOC_S_FMT, &dst_fmt) < 0) { + ERR("Failed to set video format: format(0x%x), width:height(%d:%d), " + "errstr(%s)\n", dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.width, + dst_fmt.fmt.pix.height, strerror(errno)); + param->errCode = errno; + v4l2_close(v4l2_fd); + v4l2_fd = -1; + return; + } + TRACE("Set the default format: w:h(%dx%d), fmt(0x%x), size(%d), " + "color(%d), field(%d)\n", + dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height, + dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage, + dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field); +} + +void marucam_device_start_preview(MaruCamState *state) +{ + struct timespec req; + MaruCamParam *param = state->param; + param->top = 0; + req.tv_sec = 0; + req.tv_nsec = 10000000; + + INFO("Pixfmt(%c%c%c%C), W:H(%d:%d), buf size(%u)\n", + (char)(dst_fmt.fmt.pix.pixelformat), + (char)(dst_fmt.fmt.pix.pixelformat >> 8), + (char)(dst_fmt.fmt.pix.pixelformat >> 16), + (char)(dst_fmt.fmt.pix.pixelformat >> 24), + dst_fmt.fmt.pix.width, + dst_fmt.fmt.pix.height, + dst_fmt.fmt.pix.sizeimage); + + param->errCode = mmap_framebuffers(&framebuffer, &n_framebuffer); + if (param->errCode) { + ERR("Failed to mmap framebuffers\n"); + if (framebuffer != NULL) { + free_framebuffers(framebuffer, n_framebuffer); + g_free(framebuffer); + framebuffer = NULL; + n_framebuffer = 0; + } + return; + } + + param->errCode = start_capturing(); + if (param->errCode) { + if (framebuffer != NULL) { + free_framebuffers(framebuffer, n_framebuffer); + g_free(framebuffer); + framebuffer = NULL; + n_framebuffer = 0; + } + return; + } + + INFO("Starting preview\n"); + state->buf_size = dst_fmt.fmt.pix.sizeimage; + qemu_mutex_lock(&state->thread_mutex); + qemu_cond_signal(&state->thread_cond); + qemu_mutex_unlock(&state->thread_mutex); + + /* nanosleep until thread is streamon */ + while (!is_streamon(state)) { + nanosleep(&req, NULL); + } +} + +void marucam_device_stop_preview(MaruCamState *state) +{ + struct timespec req; + struct v4l2_requestbuffers reqbuf; + MaruCamParam *param = state->param; + param->top = 0; + req.tv_sec = 0; + req.tv_nsec = 50000000; + + if (is_streamon(state)) { + qemu_mutex_lock(&state->thread_mutex); + state->streamon = _MC_THREAD_STREAMOFF; + qemu_mutex_unlock(&state->thread_mutex); + + /* nanosleep until thread is paused */ + while (!is_stream_paused(state)) { + nanosleep(&req, NULL); + } + } + + if (has_success_frame) { + saved_frame.width = dst_fmt.fmt.pix.width; + saved_frame.height = dst_fmt.fmt.pix.height; + saved_frame.size = dst_fmt.fmt.pix.sizeimage; + if (saved_frame.data) { + g_free(saved_frame.data); + saved_frame.data = NULL; + } + saved_frame.data = (void *)g_malloc0(saved_frame.size); + memcpy(saved_frame.data, + framebuffer[previous_frame_index].data, + saved_frame.size); + TRACE("Saves a frame data\n"); + } + + param->errCode = stop_capturing(); + if (framebuffer != NULL) { + free_framebuffers(framebuffer, n_framebuffer); + g_free(framebuffer); + framebuffer = NULL; + n_framebuffer = 0; + } + state->buf_size = 0; + + reqbuf.count = 0; + reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + reqbuf.memory = V4L2_MEMORY_MMAP; + if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &reqbuf) < 0) { + ERR("Failed to ioctl() with VIDIOC_REQBUF in stop_preview: %s\n", + strerror(errno)); + } + INFO("Stopping preview\n"); +} + +void marucam_device_s_param(MaruCamState *state) +{ + MaruCamParam *param = state->param; + + param->top = 0; + + /* If KVM enabled, We use default FPS of the webcam. + * If KVM disabled, we use mininum FPS of the webcam */ + if (!kvm_enabled()) { + set_maxframeinterval(state, dst_fmt.fmt.pix.pixelformat, + dst_fmt.fmt.pix.width, + dst_fmt.fmt.pix.height); + } +} + +void marucam_device_g_param(MaruCamState *state) +{ + MaruCamParam *param = state->param; + + /* We use default FPS of the webcam + * return a fixed value on guest ini file (1/30). + */ + param->top = 0; + param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */ + param->stack[1] = 1; /* numerator */ + param->stack[2] = 30; /* denominator */ +} + +void marucam_device_s_fmt(MaruCamState *state) +{ + struct v4l2_format format; + MaruCamParam *param = state->param; + + param->top = 0; + CLEAR(format); + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + format.fmt.pix.width = param->stack[0]; + format.fmt.pix.height = param->stack[1]; + format.fmt.pix.pixelformat = param->stack[2]; + format.fmt.pix.field = V4L2_FIELD_ANY; + + if (xioctl(v4l2_fd, VIDIOC_S_FMT, &format) < 0) { + ERR("Failed to set video format: format(0x%x), width:height(%d:%d), " + "errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width, + format.fmt.pix.height, strerror(errno)); + param->errCode = errno; + return; + } + + memcpy(&dst_fmt, &format, sizeof(format)); + param->stack[0] = dst_fmt.fmt.pix.width; + param->stack[1] = dst_fmt.fmt.pix.height; + param->stack[2] = dst_fmt.fmt.pix.field; + param->stack[3] = dst_fmt.fmt.pix.pixelformat; + param->stack[4] = dst_fmt.fmt.pix.bytesperline; + param->stack[5] = dst_fmt.fmt.pix.sizeimage; + param->stack[6] = dst_fmt.fmt.pix.colorspace; + param->stack[7] = dst_fmt.fmt.pix.priv; + TRACE("Set the format: w:h(%dx%d), fmt(0x%x), size(%d), " + "color(%d), field(%d)\n", + dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height, + dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage, + dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field); +} + +void marucam_device_g_fmt(MaruCamState *state) +{ + struct v4l2_format format; + MaruCamParam *param = state->param; + + param->top = 0; + CLEAR(format); + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (xioctl(v4l2_fd, VIDIOC_G_FMT, &format) < 0) { + ERR("Failed to get video format: %s\n", strerror(errno)); + param->errCode = errno; + } else { + param->stack[0] = format.fmt.pix.width; + param->stack[1] = format.fmt.pix.height; + param->stack[2] = format.fmt.pix.field; + param->stack[3] = format.fmt.pix.pixelformat; + param->stack[4] = format.fmt.pix.bytesperline; + param->stack[5] = format.fmt.pix.sizeimage; + param->stack[6] = format.fmt.pix.colorspace; + param->stack[7] = format.fmt.pix.priv; + TRACE("Get the format: w:h(%dx%d), fmt(0x%x), size(%d), " + "color(%d), field(%d)\n", + format.fmt.pix.width, format.fmt.pix.height, + format.fmt.pix.pixelformat, format.fmt.pix.sizeimage, + format.fmt.pix.colorspace, format.fmt.pix.field); + } +} + +void marucam_device_try_fmt(MaruCamState *state) +{ + struct v4l2_format format; + MaruCamParam *param = state->param; + + param->top = 0; + CLEAR(format); + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + format.fmt.pix.width = param->stack[0]; + format.fmt.pix.height = param->stack[1]; + format.fmt.pix.pixelformat = param->stack[2]; + format.fmt.pix.field = V4L2_FIELD_ANY; + + if (xioctl(v4l2_fd, VIDIOC_TRY_FMT, &format) < 0) { + ERR("Failed to check video format: format(0x%x), width:height(%d:%d)," + " errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width, + format.fmt.pix.height, strerror(errno)); + param->errCode = errno; + return; + } + param->stack[0] = format.fmt.pix.width; + param->stack[1] = format.fmt.pix.height; + param->stack[2] = format.fmt.pix.field; + param->stack[3] = format.fmt.pix.pixelformat; + param->stack[4] = format.fmt.pix.bytesperline; + param->stack[5] = format.fmt.pix.sizeimage; + param->stack[6] = format.fmt.pix.colorspace; + param->stack[7] = format.fmt.pix.priv; + TRACE("Check the format: w:h(%dx%d), fmt(0x%x), size(%d), " + "color(%d), field(%d)\n", + format.fmt.pix.width, format.fmt.pix.height, + format.fmt.pix.pixelformat, format.fmt.pix.sizeimage, + format.fmt.pix.colorspace, format.fmt.pix.field); +} + +void marucam_device_enum_fmt(MaruCamState *state) +{ + uint32_t index; + MaruCamParam *param = state->param; + + param->top = 0; + index = param->stack[0]; + + if (index >= ARRAY_SIZE(supported_dst_pixfmts)) { + param->errCode = EINVAL; + return; + } + param->stack[1] = 0; /* flags = NONE */ + param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */ + /* set description */ + switch (supported_dst_pixfmts[index].fmt) { + case V4L2_PIX_FMT_YUYV: + strcpy((char *)¶m->stack[3], "YUYV"); + break; + case V4L2_PIX_FMT_YUV420: + strcpy((char *)¶m->stack[3], "YU12"); + break; + case V4L2_PIX_FMT_YVU420: + strcpy((char *)¶m->stack[3], "YV12"); + break; + default: + ERR("Invalid fixel format\n"); + param->errCode = EINVAL; + break; + } +} + +void marucam_device_qctrl(MaruCamState *state) +{ + uint32_t i; + char name[32] = {0,}; + struct v4l2_queryctrl ctrl; + MaruCamParam *param = state->param; + + param->top = 0; + CLEAR(ctrl); + ctrl.id = param->stack[0]; + + /* NOTICE: Tizen MMFW hardcoded for control name + Do Not Modified the name + */ + switch (ctrl.id) { + case V4L2_CID_BRIGHTNESS: + TRACE("Query : BRIGHTNESS\n"); + strcpy(name, "brightness"); + i = 0; + break; + case V4L2_CID_CONTRAST: + TRACE("Query : CONTRAST\n"); + strcpy(name, "contrast"); + i = 1; + break; + case V4L2_CID_SATURATION: + TRACE("Query : SATURATION\n"); + strcpy(name, "saturation"); + i = 2; + break; + case V4L2_CID_SHARPNESS: + TRACE("Query : SHARPNESS\n"); + strcpy(name, "sharpness"); + i = 3; + break; + default: + ERR("Invalid control ID\n"); + param->errCode = EINVAL; + return; + } + + if (xioctl(v4l2_fd, VIDIOC_QUERYCTRL, &ctrl) < 0) { + if (errno != EINVAL) { + ERR("Failed to query video controls: %s\n", strerror(errno)); + } + param->errCode = errno; + return; + } else { + struct v4l2_control sctrl, gctrl; + CLEAR(sctrl); + CLEAR(gctrl); + sctrl.id = gctrl.id = ctrl.id; + if (xioctl(v4l2_fd, VIDIOC_G_CTRL, &gctrl) < 0) { + ERR("[%s] Failed to get video control value: id(0x%x), " + "errstr(%s)\n", + __func__, gctrl.id, strerror(errno)); + param->errCode = errno; + return; + } + + qctrl_tbl[i].hit = 1; + qctrl_tbl[i].min = ctrl.minimum; + qctrl_tbl[i].max = ctrl.maximum; + qctrl_tbl[i].step = ctrl.step; + qctrl_tbl[i].init_val = gctrl.value; + + if ((ctrl.maximum + ctrl.minimum) == 0) { + sctrl.value = 0; + } else { + sctrl.value = (ctrl.maximum + ctrl.minimum) / 2; + } + + if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &sctrl) < 0) { + ERR("[%s] Failed to set control value: id(0x%x), value(%d), " + "errstr(%s)\n", + __func__, sctrl.id, sctrl.value, strerror(errno)); + param->errCode = errno; + return; + } + + INFO("Query Control: id(0x%x), name(%s), min(%d), max(%d), " + "step(%d), def_value(%d)\n" + "flags(0x%x), get_value(%d), set_value(%d)\n", + ctrl.id, ctrl.name, ctrl.minimum, ctrl.maximum, + ctrl.step, ctrl.default_value, ctrl.flags, + gctrl.value, sctrl.value); + } + + /* set fixed values by FW configuration file */ + param->stack[0] = ctrl.id; + param->stack[1] = MARUCAM_CTRL_VALUE_MIN; /* minimum */ + param->stack[2] = MARUCAM_CTRL_VALUE_MAX; /* maximum */ + param->stack[3] = MARUCAM_CTRL_VALUE_STEP; /* step */ + param->stack[4] = MARUCAM_CTRL_VALUE_MID; /* default_value */ + param->stack[5] = ctrl.flags; + /* name field setting */ + memcpy(¶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(); + + if (saved_frame.data) { + g_free(saved_frame.data); + saved_frame.data = NULL; + } + memset(&saved_frame, 0x00, sizeof(saved_frame)); + + v4l2_close(v4l2_fd); + v4l2_fd = 0; + INFO("Closed\n"); +} diff --git a/tizen/src/hw/pci/maru_camera_linux_pci.c b/tizen/src/hw/pci/maru_camera_linux_pci.c deleted file mode 100644 index 406478b838..0000000000 --- a/tizen/src/hw/pci/maru_camera_linux_pci.c +++ /dev/null @@ -1,1391 +0,0 @@ -/* - * Implementation of MARU Virtual Camera device by PCI bus on Linux. - * - * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: - * JinHyung Jo - * YeongKyoon Lee - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - * Contributors: - * - S-Core Co., Ltd - * - */ - -#include "qemu-common.h" -#include "sysemu/kvm.h" -#include "maru_camera_common.h" -#include "debug_ch.h" - -#include - -#include -#include -#include - -#include -#include - -MULTI_DEBUG_CHANNEL(tizen, camera); - -#define MARUCAM_THREAD_NAME "marucam_worker_thread" - -#define CLEAR(x) memset(&(x), 0, sizeof(x)) - -#define MARUCAM_DEFAULT_BUFFER_COUNT 4 - -#define MARUCAM_CTRL_VALUE_MAX 20 -#define MARUCAM_CTRL_VALUE_MIN 1 -#define MARUCAM_CTRL_VALUE_MID 10 -#define MARUCAM_CTRL_VALUE_STEP 1 - -enum { - _MC_THREAD_PAUSED, - _MC_THREAD_STREAMON, - _MC_THREAD_STREAMOFF, -}; - -typedef struct marucam_framebuffer { - void *data; - size_t size; -} marucam_framebuffer; - -struct marucam_saved_frame { - void *data; - uint32_t pixelformat; - uint32_t width; - uint32_t height; - uint32_t size; -}; - -static struct marucam_saved_frame saved_frame; -static char has_success_frame; -static int n_framebuffer; -static int previous_frame_index = -1; -static struct marucam_framebuffer *framebuffer; - -static const char *dev_name = "/dev/video0"; -static int v4l2_fd; -static int convert_trial; -static int ready_count; -static int timeout_n; - -static struct v4l2_format dst_fmt; - -static void ScalePlaneSimple(int src_width, int src_height, - int dst_width, int dst_height, - int src_stride, int dst_stride, - const uint8_t *src_ptr, uint8_t *dst_ptr) { - int i, j; - int dx = (src_width << 16) / dst_width; - int dy = (src_height << 16) / dst_height; - int y = (dy >= 65536) ? ((dy >> 1) - 32768) : (dy >> 1); - for (j = 0; j < dst_height; ++j) { - int x = (dx >= 65536) ? ((dx >> 1) - 32768) : (dx >> 1); - int yi = y >> 16; - const uint8_t *src = src_ptr + yi * src_stride; - uint8_t *dst = dst_ptr; - for (i = 0; i < dst_width; ++i) { - *dst++ = src[x >> 16]; - x += dx; - } - dst_ptr += dst_stride; - y += dy; - } -} - -static void make_yu12_black(unsigned char *dest, uint32_t width, uint32_t height) -{ - uint32_t x, y; - unsigned char *udest, *vdest; - - /* Y */ - for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - *dest++ = 16; - } - } - - /* U + V */ - udest = dest; - vdest = dest + width * height / 4; - - for (y = 0; y < height / 2; y++) { - for (x = 0; x < width / 2; x++) { - *udest++ = *vdest++ = 128; - } - } -} - -static void marucam_scale_yuv420(void *src, - uint32_t src_width, uint32_t src_height, - void *dst, uint32_t dst_width, uint32_t dst_height) -{ - uint32_t src_halfwidth = (src_width + 1) >> 1; - uint32_t src_halfheight = (src_height + 1) >> 1; - uint32_t dst_halfwidth = (dst_width + 1) >> 1; - uint32_t dst_halfheight = (dst_height + 1) >> 1; - - uint8_t *src_u = src + (src_width * src_height); - uint8_t *src_v = src_u + (src_width * src_height / 4); - - uint8_t *dst_u = dst + (dst_width * dst_height); - uint8_t *dst_v = dst_u + (dst_width * dst_height /4); - - ScalePlaneSimple(src_width, src_height, - dst_width, dst_height, - src_width, dst_width, - src, dst); - ScalePlaneSimple(src_halfwidth, src_halfheight, - dst_halfwidth, dst_halfheight, - src_halfwidth, dst_halfwidth, - src_u, dst_u); - ScalePlaneSimple(src_halfwidth, src_halfheight, - dst_halfwidth, dst_halfheight, - src_halfwidth, dst_halfwidth, - src_v, dst_v); -} - -static int yioctl(int fd, int req, void *arg) -{ - int r; - - do { - r = ioctl(fd, req, arg); - } while (r < 0 && errno == EINTR); - - return r; -} - -static int xioctl(int fd, int req, void *arg) -{ - int r; - - do { - r = v4l2_ioctl(fd, req, arg); - } while (r < 0 && errno == EINTR); - - return r; -} - -typedef struct tagMaruCamConvertPixfmt { - uint32_t fmt; /* fourcc */ -} MaruCamConvertPixfmt; - -static MaruCamConvertPixfmt supported_dst_pixfmts[] = { - { V4L2_PIX_FMT_YUYV }, - { V4L2_PIX_FMT_YUV420 }, - { V4L2_PIX_FMT_YVU420 }, -}; - -typedef struct tagMaruCamConvertFrameInfo { - uint32_t width; - uint32_t height; -} MaruCamConvertFrameInfo; - -static MaruCamConvertFrameInfo supported_dst_frames[] = { - { 640, 480 }, - { 352, 288 }, - { 320, 240 }, - { 176, 144 }, - { 160, 120 }, -}; - -struct marucam_qctrl { - uint32_t id; - uint32_t hit; - int32_t min; - int32_t max; - int32_t step; - int32_t init_val; -}; - -static struct marucam_qctrl qctrl_tbl[] = { - { V4L2_CID_BRIGHTNESS, 0, }, - { V4L2_CID_CONTRAST, 0, }, - { V4L2_CID_SATURATION, 0, }, - { V4L2_CID_SHARPNESS, 0, }, -}; - -static void marucam_reset_controls(void) -{ - uint32_t i; - for (i = 0; i < ARRAY_SIZE(qctrl_tbl); i++) { - if (qctrl_tbl[i].hit) { - struct v4l2_control ctrl = {0,}; - ctrl.id = qctrl_tbl[i].id; - ctrl.value = qctrl_tbl[i].init_val; - qctrl_tbl[i].hit = qctrl_tbl[i].init_val = 0; - qctrl_tbl[i].min = qctrl_tbl[i].max = qctrl_tbl[i].step = 0; - if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) { - ERR("Failed to reset control value: id(0x%x), errstr(%s)\n", - ctrl.id, strerror(errno)); - } - } - } - TRACE("[%s] Reset done\n", __func__); -} - -static int32_t value_convert_from_guest(int32_t min, int32_t max, int32_t value) -{ - double rate = 0.0; - int32_t dist = 0, ret = 0; - - dist = max - min; - - if (dist < MARUCAM_CTRL_VALUE_MAX) { - rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; - ret = min + (int32_t)(value / rate); - } else { - rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; - ret = min + (int32_t)(rate * value); - } - return ret; -} - -static int32_t value_convert_to_guest(int32_t min, int32_t max, int32_t value) -{ - double rate = 0.0; - int32_t dist = 0, ret = 0; - - dist = max - min; - - if (dist < MARUCAM_CTRL_VALUE_MAX) { - rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; - ret = (int32_t)((double)(value - min) * rate); - } else { - rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; - ret = (int32_t)((double)(value - min) / rate); - } - - return ret; -} - -static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format, - uint32_t width, uint32_t height) -{ - struct v4l2_frmivalenum fival; - struct v4l2_streamparm sp; - uint32_t min_num = 0, min_denom = 0; - - CLEAR(fival); - fival.pixel_format = pixel_format; - fival.width = width; - fival.height = height; - - if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) < 0) { - ERR("Unable to enumerate intervals for pixelformat(0x%x), (%d:%d)\n", - pixel_format, width, height); - return; - } - - if (fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { - float max_ival = -1.0; - do { - float cur_ival = (float)fival.discrete.numerator - / (float)fival.discrete.denominator; - if (cur_ival > max_ival) { - max_ival = cur_ival; - min_num = fival.discrete.numerator; - min_denom = fival.discrete.denominator; - } - TRACE("Discrete frame interval %u/%u supported\n", - fival.discrete.numerator, fival.discrete.denominator); - fival.index++; - } while (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) >= 0); - } else if ((fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) || - (fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)) { - TRACE("Frame intervals from %u/%u to %u/%u supported", - fival.stepwise.min.numerator, fival.stepwise.min.denominator, - fival.stepwise.max.numerator, fival.stepwise.max.denominator); - if (fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) { - TRACE("with %u/%u step", fival.stepwise.step.numerator, - fival.stepwise.step.denominator); - } - if (((float)fival.stepwise.max.denominator / - (float)fival.stepwise.max.numerator) > - ((float)fival.stepwise.min.denominator / - (float)fival.stepwise.min.numerator)) { - min_num = fival.stepwise.max.numerator; - min_denom = fival.stepwise.max.denominator; - } else { - min_num = fival.stepwise.min.numerator; - min_denom = fival.stepwise.min.denominator; - } - } - TRACE("The actual min values: %u/%u\n", min_num, min_denom); - - CLEAR(sp); - sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - sp.parm.capture.timeperframe.numerator = min_num; - sp.parm.capture.timeperframe.denominator = min_denom; - - if (xioctl(v4l2_fd, VIDIOC_S_PARM, &sp) < 0) { - ERR("Failed to set to minimum FPS(%u/%u)\n", min_num, min_denom); - } -} - -static uint32_t stop_capturing(void) -{ - enum v4l2_buf_type type; - - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (xioctl(v4l2_fd, VIDIOC_STREAMOFF, &type) < 0) { - ERR("Failed to ioctl() with VIDIOC_STREAMOFF: %s\n", strerror(errno)); - return errno; - } - return 0; -} - -static uint32_t start_capturing(void) -{ - enum v4l2_buf_type type; - - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (xioctl(v4l2_fd, VIDIOC_STREAMON, &type) < 0) { - ERR("Failed to ioctl() with VIDIOC_STREAMON: %s\n", strerror(errno)); - return errno; - } - return 0; -} - -static void free_framebuffers(marucam_framebuffer *fb, int buf_num) -{ - int i; - - if (fb == NULL) { - ERR("The framebuffer is NULL. Failed to release the framebuffer\n"); - return; - } else if (buf_num == 0) { - ERR("The buffer count is 0. Failed to release the framebuffer\n"); - return; - } else { - TRACE("[%s]:fb(0x%p), buf_num(%d)\n", __func__, fb, buf_num); - } - - /* Unmap framebuffers. */ - for (i = 0; i < buf_num; i++) { - if (fb[i].data != NULL) { - v4l2_munmap(fb[i].data, fb[i].size); - fb[i].data = NULL; - fb[i].size = 0; - } else { - ERR("framebuffer[%d].data is NULL.\n", i); - } - } - previous_frame_index = -1; -} - -static uint32_t -mmap_framebuffers(marucam_framebuffer **fb, int *buf_num) -{ - struct v4l2_requestbuffers req; - - CLEAR(req); - req.count = MARUCAM_DEFAULT_BUFFER_COUNT; - req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - req.memory = V4L2_MEMORY_MMAP; - if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &req) < 0) { - if (errno == EINVAL) { - ERR("%s does not support memory mapping: %s\n", - dev_name, strerror(errno)); - } else { - ERR("Failed to request bufs: %s\n", strerror(errno)); - } - return errno; - } - if (req.count == 0) { - ERR("Insufficient buffer memory on %s\n", dev_name); - return EINVAL; - } - - *fb = g_new0(marucam_framebuffer, req.count); - if (*fb == NULL) { - ERR("Not enough memory to allocate framebuffers\n"); - return ENOMEM; - } - - for (*buf_num = 0; *buf_num < req.count; ++*buf_num) { - struct v4l2_buffer buf; - CLEAR(buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = *buf_num; - if (xioctl(v4l2_fd, VIDIOC_QUERYBUF, &buf) < 0) { - ERR("Failed to ioctl() with VIDIOC_QUERYBUF: %s\n", - strerror(errno)); - return errno; - } - - (*fb)[*buf_num].size = buf.length; - (*fb)[*buf_num].data = v4l2_mmap(NULL, - buf.length, - PROT_READ | PROT_WRITE, - MAP_SHARED, - v4l2_fd, buf.m.offset); - if (MAP_FAILED == (*fb)[*buf_num].data) { - ERR("Failed to mmap: %s\n", strerror(errno)); - return errno; - } - - /* Queue the mapped buffer. */ - CLEAR(buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = *buf_num; - if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) { - ERR("Failed to ioctl() with VIDIOC_QBUF: %s\n", strerror(errno)); - return errno; - } - } - return 0; -} - -static int is_streamon(MaruCamState *state) -{ - int st; - qemu_mutex_lock(&state->thread_mutex); - st = state->streamon; - qemu_mutex_unlock(&state->thread_mutex); - return (st == _MC_THREAD_STREAMON); -} - -static int is_stream_paused(MaruCamState *state) -{ - int st; - qemu_mutex_lock(&state->thread_mutex); - st = state->streamon; - qemu_mutex_unlock(&state->thread_mutex); - return (st == _MC_THREAD_PAUSED); -} - -/* sends a frame, YU12/black color */ -/* TODO: add other pixel format method */ -static void __raise_dummy_intr(MaruCamState *state) -{ - void *buf = NULL; - qemu_mutex_lock(&state->thread_mutex); - if (state->streamon == _MC_THREAD_STREAMON && state->req_frame) { - buf = state->vaddr + state->buf_size * (state->req_frame - 1); - if (saved_frame.data) { - if (saved_frame.width == dst_fmt.fmt.pix.width && - saved_frame.height == dst_fmt.fmt.pix.height) { - TRACE("Copies the previuos frame\n"); - memcpy(buf, saved_frame.data, state->buf_size); - } else { - TRACE("Resizes the previous frame\n"); - marucam_scale_yuv420(saved_frame.data, saved_frame.width, - saved_frame.height, - buf, dst_fmt.fmt.pix.width, - dst_fmt.fmt.pix.height); - } - } else { - TRACE("Sends a black frame\n"); - make_yu12_black(buf, - dst_fmt.fmt.pix.width, - dst_fmt.fmt.pix.height); - } - state->req_frame = 0; /* clear request */ - state->isr |= 0x01; /* set a flag of raising a interrupt */ - qemu_bh_schedule(state->tx_bh); - } - qemu_mutex_unlock(&state->thread_mutex); -} - -static void __raise_err_intr(MaruCamState *state) -{ - qemu_mutex_lock(&state->thread_mutex); - if (state->streamon == _MC_THREAD_STREAMON) { - state->req_frame = 0; /* clear request */ - state->isr = 0x08; /* set a error flag of raising a interrupt */ - qemu_bh_schedule(state->tx_bh); - } - qemu_mutex_unlock(&state->thread_mutex); -} - -static void -notify_buffer_ready(MaruCamState *state, uint32_t buf_index) -{ - void *buf = NULL; - - qemu_mutex_lock(&state->thread_mutex); - if (state->streamon == _MC_THREAD_STREAMON) { - if (ready_count < MARUCAM_SKIPFRAMES) { - /* skip a frame cause first some frame are distorted */ - ++ready_count; - TRACE("Skip %d frame\n", ready_count); - qemu_mutex_unlock(&state->thread_mutex); - return; - } - if (state->req_frame == 0) { - qemu_mutex_unlock(&state->thread_mutex); - return; - } - buf = state->vaddr + state->buf_size * (state->req_frame - 1); - memcpy(buf, framebuffer[buf_index].data, state->buf_size); - previous_frame_index = buf_index; - has_success_frame = 1; - state->req_frame = 0; /* clear request */ - state->isr |= 0x01; /* set a flag of rasing a interrupt */ - qemu_bh_schedule(state->tx_bh); - } - qemu_mutex_unlock(&state->thread_mutex); -} - -static int read_frame(MaruCamState *state) -{ - struct v4l2_buffer buf; - - CLEAR(buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - if (xioctl(v4l2_fd, VIDIOC_DQBUF, &buf) < 0) { - switch (errno) { - case EAGAIN: - case EINTR: - ERR("DQBUF error, try again: %s\n", strerror(errno)); - return 0; - case EIO: - ERR("The v4l2_read() met the EIO\n"); - if (convert_trial-- == -1) { - ERR("Try count for v4l2_read is exceeded: %s\n", - strerror(errno)); - return -1; - } - return 0; - default: - ERR("DQBUF error: %s\n", strerror(errno)); - return -1; - } - } - - notify_buffer_ready(state, buf.index); - - if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) { - ERR("QBUF error: %s\n", strerror(errno)); - return -1; - } - return 0; -} - -static int __v4l2_streaming(MaruCamState *state) -{ - fd_set fds; - struct timeval tv; - int ret; - - FD_ZERO(&fds); - FD_SET(v4l2_fd, &fds); - - tv.tv_sec = 1; - tv.tv_usec = 0; - - ret = select(v4l2_fd + 1, &fds, NULL, NULL, &tv); - if (ret < 0) { - if (errno == EAGAIN || errno == EINTR) { - ERR("Select again: %s\n", strerror(errno)); - return 0; - } - ERR("Failed to select: %s\n", strerror(errno)); - __raise_err_intr(state); - return -1; - } else if (!ret) { - timeout_n++; - ERR("Select timed out: count(%u)\n", timeout_n); - if (ready_count <= MARUCAM_SKIPFRAMES) { - switch (timeout_n) { - case 1: - ERR("Waiting for reading a frame data\n"); - return 0; - case 2: - case 3: - case 4: - ERR("Sends dummy data to initialize the camera\n"); - __raise_dummy_intr(state); - return 0; - default: - ERR("Webcam is busy, failed to a read frame." - " Raises an error\n"); - __raise_err_intr(state); - return -1; - } - } - if (timeout_n >= 5) { - ERR("Webcam is busy, failed to a read frame. Raises an error\n"); - __raise_err_intr(state); - return -1; - } - if (previous_frame_index != -1) { - ERR("Sends previous frame data\n"); - notify_buffer_ready(state, previous_frame_index); - } - return 0; - } - - if (!v4l2_fd || (v4l2_fd == -1)) { - ERR("The file descriptor is closed or not opened\n"); - __raise_err_intr(state); - return -1; - } - - ret = read_frame(state); - if (ret < 0) { - ERR("Failed to operate the read_frame()\n"); - __raise_err_intr(state); - return -1; - } - - /* clear the skip count for select time-out */ - if (timeout_n > 0) { - timeout_n = 0; - } - - return 0; -} - -/* Worker thread */ -static void *marucam_worker_thread(void *thread_param) -{ - MaruCamState *state = (MaruCamState *)thread_param; - - while (1) { - qemu_mutex_lock(&state->thread_mutex); - state->streamon = _MC_THREAD_PAUSED; - qemu_cond_wait(&state->thread_cond, &state->thread_mutex); - qemu_mutex_unlock(&state->thread_mutex); - - if (state->destroying) { - break; - } - - convert_trial = 10; - ready_count = 0; - timeout_n = 0; - has_success_frame = 0; - qemu_mutex_lock(&state->thread_mutex); - state->streamon = _MC_THREAD_STREAMON; - qemu_mutex_unlock(&state->thread_mutex); - INFO("Streaming on ......\n"); - - while (1) { - if (is_streamon(state)) { - if (__v4l2_streaming(state) < 0) { - INFO("...... Streaming off\n"); - break; - } - } else { - INFO("...... Streaming off\n"); - break; - } - } - } - - return NULL; -} - -int marucam_device_check(int log_flag) -{ - int tmp_fd; - struct timeval t1, t2; - struct stat st; - struct v4l2_fmtdesc format; - struct v4l2_frmsizeenum size; - struct v4l2_capability cap; - int ret = 0; - - gettimeofday(&t1, NULL); - if (stat(dev_name, &st) < 0) { - INFO(" Cannot identify '%s': %s\n", - dev_name, strerror(errno)); - } else { - if (!S_ISCHR(st.st_mode)) { - INFO("%s is no character device\n", - dev_name); - } - } - - tmp_fd = open(dev_name, O_RDWR | O_NONBLOCK, 0); - if (tmp_fd < 0) { - ERR("Camera device open failed: %s\n", dev_name); - gettimeofday(&t2, NULL); - ERR("Elapsed time: %lu:%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - if (ioctl(tmp_fd, VIDIOC_QUERYCAP, &cap) < 0) { - ERR("Could not qeury video capabilities\n"); - close(tmp_fd); - gettimeofday(&t2, NULL); - ERR("Elapsed time: %lu:%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) || - !(cap.capabilities & V4L2_CAP_STREAMING)) { - ERR("Not supported video driver\n"); - close(tmp_fd); - gettimeofday(&t2, NULL); - ERR("Elapsed time: %lu:%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - ret = 1; - - if (log_flag) { - INFO("Driver: %s\n", cap.driver); - INFO("Card: %s\n", cap.card); - INFO("Bus info: %s\n", cap.bus_info); - - CLEAR(format); - format.index = 0; - format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) < 0) { - close(tmp_fd); - gettimeofday(&t2, NULL); - ERR("Elapsed time: %lu:%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - do { - CLEAR(size); - size.index = 0; - size.pixel_format = format.pixelformat; - - INFO("PixelFormat: %c%c%c%c\n", - (char)(format.pixelformat), - (char)(format.pixelformat >> 8), - (char)(format.pixelformat >> 16), - (char)(format.pixelformat >> 24)); - - if (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0) { - close(tmp_fd); - gettimeofday(&t2, NULL); - ERR("Elapsed time: %lu:%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) { - do { - INFO("\tGot a discrete frame size %dx%d\n", - size.discrete.width, size.discrete.height); - size.index++; - } while (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0); - } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) { - INFO("We have stepwise frame sizes:\n"); - INFO("\tmin width: %d, min height: %d\n", - size.stepwise.min_width, size.stepwise.min_height); - INFO("\tmax width: %d, max height: %d\n", - size.stepwise.max_width, size.stepwise.max_height); - INFO("\tstep width: %d, step height: %d\n", - size.stepwise.step_width, size.stepwise.step_height); - } else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) { - INFO("We have continuous frame sizes:\n"); - INFO("\tmin width: %d, min height: %d\n", - size.stepwise.min_width, size.stepwise.min_height); - INFO("\tmax width: %d, max height: %d\n", - size.stepwise.max_width, size.stepwise.max_height); - - } - format.index++; - } while (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) >= 0); - } - - close(tmp_fd); - gettimeofday(&t2, NULL); - INFO("Elapsed time: %lu:%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; -} - -void marucam_device_init(MaruCamState *state) -{ - state->destroying = false; - qemu_thread_create(&state->thread_id, - MARUCAM_THREAD_NAME, - marucam_worker_thread, - (void *)state, - QEMU_THREAD_JOINABLE); -} - -void marucam_device_exit(MaruCamState *state) -{ - state->destroying = true; - qemu_mutex_lock(&state->thread_mutex); - qemu_cond_signal(&state->thread_cond); - qemu_mutex_unlock(&state->thread_mutex); - qemu_thread_join(&state->thread_id); -} - -void marucam_device_open(MaruCamState *state) -{ - MaruCamParam *param = state->param; - - param->top = 0; - v4l2_fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0); - if (v4l2_fd < 0) { - ERR("The v4l2 device open failed: %s\n", dev_name); - param->errCode = EINVAL; - return; - } - INFO("Opened\n"); - - /* FIXME : Do not use fixed values */ - CLEAR(dst_fmt); - dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - dst_fmt.fmt.pix.width = 640; - dst_fmt.fmt.pix.height = 480; - dst_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - dst_fmt.fmt.pix.field = V4L2_FIELD_ANY; - - if (xioctl(v4l2_fd, VIDIOC_S_FMT, &dst_fmt) < 0) { - ERR("Failed to set video format: format(0x%x), width:height(%d:%d), " - "errstr(%s)\n", dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.width, - dst_fmt.fmt.pix.height, strerror(errno)); - param->errCode = errno; - v4l2_close(v4l2_fd); - v4l2_fd = -1; - return; - } - TRACE("Set the default format: w:h(%dx%d), fmt(0x%x), size(%d), " - "color(%d), field(%d)\n", - dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height, - dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage, - dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field); -} - -void marucam_device_start_preview(MaruCamState *state) -{ - struct timespec req; - MaruCamParam *param = state->param; - param->top = 0; - req.tv_sec = 0; - req.tv_nsec = 10000000; - - INFO("Pixfmt(%c%c%c%C), W:H(%d:%d), buf size(%u)\n", - (char)(dst_fmt.fmt.pix.pixelformat), - (char)(dst_fmt.fmt.pix.pixelformat >> 8), - (char)(dst_fmt.fmt.pix.pixelformat >> 16), - (char)(dst_fmt.fmt.pix.pixelformat >> 24), - dst_fmt.fmt.pix.width, - dst_fmt.fmt.pix.height, - dst_fmt.fmt.pix.sizeimage); - - param->errCode = mmap_framebuffers(&framebuffer, &n_framebuffer); - if (param->errCode) { - ERR("Failed to mmap framebuffers\n"); - if (framebuffer != NULL) { - free_framebuffers(framebuffer, n_framebuffer); - g_free(framebuffer); - framebuffer = NULL; - n_framebuffer = 0; - } - return; - } - - param->errCode = start_capturing(); - if (param->errCode) { - if (framebuffer != NULL) { - free_framebuffers(framebuffer, n_framebuffer); - g_free(framebuffer); - framebuffer = NULL; - n_framebuffer = 0; - } - return; - } - - INFO("Starting preview\n"); - state->buf_size = dst_fmt.fmt.pix.sizeimage; - qemu_mutex_lock(&state->thread_mutex); - qemu_cond_signal(&state->thread_cond); - qemu_mutex_unlock(&state->thread_mutex); - - /* nanosleep until thread is streamon */ - while (!is_streamon(state)) { - nanosleep(&req, NULL); - } -} - -void marucam_device_stop_preview(MaruCamState *state) -{ - struct timespec req; - struct v4l2_requestbuffers reqbuf; - MaruCamParam *param = state->param; - param->top = 0; - req.tv_sec = 0; - req.tv_nsec = 50000000; - - if (is_streamon(state)) { - qemu_mutex_lock(&state->thread_mutex); - state->streamon = _MC_THREAD_STREAMOFF; - qemu_mutex_unlock(&state->thread_mutex); - - /* nanosleep until thread is paused */ - while (!is_stream_paused(state)) { - nanosleep(&req, NULL); - } - } - - if (has_success_frame) { - saved_frame.width = dst_fmt.fmt.pix.width; - saved_frame.height = dst_fmt.fmt.pix.height; - saved_frame.size = dst_fmt.fmt.pix.sizeimage; - if (saved_frame.data) { - g_free(saved_frame.data); - saved_frame.data = NULL; - } - saved_frame.data = (void *)g_malloc0(saved_frame.size); - memcpy(saved_frame.data, - framebuffer[previous_frame_index].data, - saved_frame.size); - TRACE("Saves a frame data\n"); - } - - param->errCode = stop_capturing(); - if (framebuffer != NULL) { - free_framebuffers(framebuffer, n_framebuffer); - g_free(framebuffer); - framebuffer = NULL; - n_framebuffer = 0; - } - state->buf_size = 0; - - reqbuf.count = 0; - reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - reqbuf.memory = V4L2_MEMORY_MMAP; - if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &reqbuf) < 0) { - ERR("Failed to ioctl() with VIDIOC_REQBUF in stop_preview: %s\n", - strerror(errno)); - } - INFO("Stopping preview\n"); -} - -void marucam_device_s_param(MaruCamState *state) -{ - MaruCamParam *param = state->param; - - param->top = 0; - - /* If KVM enabled, We use default FPS of the webcam. - * If KVM disabled, we use mininum FPS of the webcam */ - if (!kvm_enabled()) { - set_maxframeinterval(state, dst_fmt.fmt.pix.pixelformat, - dst_fmt.fmt.pix.width, - dst_fmt.fmt.pix.height); - } -} - -void marucam_device_g_param(MaruCamState *state) -{ - MaruCamParam *param = state->param; - - /* We use default FPS of the webcam - * return a fixed value on guest ini file (1/30). - */ - param->top = 0; - param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */ - param->stack[1] = 1; /* numerator */ - param->stack[2] = 30; /* denominator */ -} - -void marucam_device_s_fmt(MaruCamState *state) -{ - struct v4l2_format format; - MaruCamParam *param = state->param; - - param->top = 0; - CLEAR(format); - format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - format.fmt.pix.width = param->stack[0]; - format.fmt.pix.height = param->stack[1]; - format.fmt.pix.pixelformat = param->stack[2]; - format.fmt.pix.field = V4L2_FIELD_ANY; - - if (xioctl(v4l2_fd, VIDIOC_S_FMT, &format) < 0) { - ERR("Failed to set video format: format(0x%x), width:height(%d:%d), " - "errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width, - format.fmt.pix.height, strerror(errno)); - param->errCode = errno; - return; - } - - memcpy(&dst_fmt, &format, sizeof(format)); - param->stack[0] = dst_fmt.fmt.pix.width; - param->stack[1] = dst_fmt.fmt.pix.height; - param->stack[2] = dst_fmt.fmt.pix.field; - param->stack[3] = dst_fmt.fmt.pix.pixelformat; - param->stack[4] = dst_fmt.fmt.pix.bytesperline; - param->stack[5] = dst_fmt.fmt.pix.sizeimage; - param->stack[6] = dst_fmt.fmt.pix.colorspace; - param->stack[7] = dst_fmt.fmt.pix.priv; - TRACE("Set the format: w:h(%dx%d), fmt(0x%x), size(%d), " - "color(%d), field(%d)\n", - dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height, - dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage, - dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field); -} - -void marucam_device_g_fmt(MaruCamState *state) -{ - struct v4l2_format format; - MaruCamParam *param = state->param; - - param->top = 0; - CLEAR(format); - format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (xioctl(v4l2_fd, VIDIOC_G_FMT, &format) < 0) { - ERR("Failed to get video format: %s\n", strerror(errno)); - param->errCode = errno; - } else { - param->stack[0] = format.fmt.pix.width; - param->stack[1] = format.fmt.pix.height; - param->stack[2] = format.fmt.pix.field; - param->stack[3] = format.fmt.pix.pixelformat; - param->stack[4] = format.fmt.pix.bytesperline; - param->stack[5] = format.fmt.pix.sizeimage; - param->stack[6] = format.fmt.pix.colorspace; - param->stack[7] = format.fmt.pix.priv; - TRACE("Get the format: w:h(%dx%d), fmt(0x%x), size(%d), " - "color(%d), field(%d)\n", - format.fmt.pix.width, format.fmt.pix.height, - format.fmt.pix.pixelformat, format.fmt.pix.sizeimage, - format.fmt.pix.colorspace, format.fmt.pix.field); - } -} - -void marucam_device_try_fmt(MaruCamState *state) -{ - struct v4l2_format format; - MaruCamParam *param = state->param; - - param->top = 0; - CLEAR(format); - format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - format.fmt.pix.width = param->stack[0]; - format.fmt.pix.height = param->stack[1]; - format.fmt.pix.pixelformat = param->stack[2]; - format.fmt.pix.field = V4L2_FIELD_ANY; - - if (xioctl(v4l2_fd, VIDIOC_TRY_FMT, &format) < 0) { - ERR("Failed to check video format: format(0x%x), width:height(%d:%d)," - " errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width, - format.fmt.pix.height, strerror(errno)); - param->errCode = errno; - return; - } - param->stack[0] = format.fmt.pix.width; - param->stack[1] = format.fmt.pix.height; - param->stack[2] = format.fmt.pix.field; - param->stack[3] = format.fmt.pix.pixelformat; - param->stack[4] = format.fmt.pix.bytesperline; - param->stack[5] = format.fmt.pix.sizeimage; - param->stack[6] = format.fmt.pix.colorspace; - param->stack[7] = format.fmt.pix.priv; - TRACE("Check the format: w:h(%dx%d), fmt(0x%x), size(%d), " - "color(%d), field(%d)\n", - format.fmt.pix.width, format.fmt.pix.height, - format.fmt.pix.pixelformat, format.fmt.pix.sizeimage, - format.fmt.pix.colorspace, format.fmt.pix.field); -} - -void marucam_device_enum_fmt(MaruCamState *state) -{ - uint32_t index; - MaruCamParam *param = state->param; - - param->top = 0; - index = param->stack[0]; - - if (index >= ARRAY_SIZE(supported_dst_pixfmts)) { - param->errCode = EINVAL; - return; - } - param->stack[1] = 0; /* flags = NONE */ - param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */ - /* set description */ - switch (supported_dst_pixfmts[index].fmt) { - case V4L2_PIX_FMT_YUYV: - strcpy((char *)¶m->stack[3], "YUYV"); - break; - case V4L2_PIX_FMT_YUV420: - strcpy((char *)¶m->stack[3], "YU12"); - break; - case V4L2_PIX_FMT_YVU420: - strcpy((char *)¶m->stack[3], "YV12"); - break; - default: - ERR("Invalid fixel format\n"); - param->errCode = EINVAL; - break; - } -} - -void marucam_device_qctrl(MaruCamState *state) -{ - uint32_t i; - char name[32] = {0,}; - struct v4l2_queryctrl ctrl; - MaruCamParam *param = state->param; - - param->top = 0; - CLEAR(ctrl); - ctrl.id = param->stack[0]; - - /* NOTICE: Tizen MMFW hardcoded for control name - Do Not Modified the name - */ - switch (ctrl.id) { - case V4L2_CID_BRIGHTNESS: - TRACE("Query : BRIGHTNESS\n"); - strcpy(name, "brightness"); - i = 0; - break; - case V4L2_CID_CONTRAST: - TRACE("Query : CONTRAST\n"); - strcpy(name, "contrast"); - i = 1; - break; - case V4L2_CID_SATURATION: - TRACE("Query : SATURATION\n"); - strcpy(name, "saturation"); - i = 2; - break; - case V4L2_CID_SHARPNESS: - TRACE("Query : SHARPNESS\n"); - strcpy(name, "sharpness"); - i = 3; - break; - default: - ERR("Invalid control ID\n"); - param->errCode = EINVAL; - return; - } - - if (xioctl(v4l2_fd, VIDIOC_QUERYCTRL, &ctrl) < 0) { - if (errno != EINVAL) { - ERR("Failed to query video controls: %s\n", strerror(errno)); - } - param->errCode = errno; - return; - } else { - struct v4l2_control sctrl, gctrl; - CLEAR(sctrl); - CLEAR(gctrl); - sctrl.id = gctrl.id = ctrl.id; - if (xioctl(v4l2_fd, VIDIOC_G_CTRL, &gctrl) < 0) { - ERR("[%s] Failed to get video control value: id(0x%x), " - "errstr(%s)\n", - __func__, gctrl.id, strerror(errno)); - param->errCode = errno; - return; - } - - qctrl_tbl[i].hit = 1; - qctrl_tbl[i].min = ctrl.minimum; - qctrl_tbl[i].max = ctrl.maximum; - qctrl_tbl[i].step = ctrl.step; - qctrl_tbl[i].init_val = gctrl.value; - - if ((ctrl.maximum + ctrl.minimum) == 0) { - sctrl.value = 0; - } else { - sctrl.value = (ctrl.maximum + ctrl.minimum) / 2; - } - - if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &sctrl) < 0) { - ERR("[%s] Failed to set control value: id(0x%x), value(%d), " - "errstr(%s)\n", - __func__, sctrl.id, sctrl.value, strerror(errno)); - param->errCode = errno; - return; - } - - INFO("Query Control: id(0x%x), name(%s), min(%d), max(%d), " - "step(%d), def_value(%d)\n" - "flags(0x%x), get_value(%d), set_value(%d)\n", - ctrl.id, ctrl.name, ctrl.minimum, ctrl.maximum, - ctrl.step, ctrl.default_value, ctrl.flags, - gctrl.value, sctrl.value); - } - - /* set fixed values by FW configuration file */ - param->stack[0] = ctrl.id; - param->stack[1] = MARUCAM_CTRL_VALUE_MIN; /* minimum */ - param->stack[2] = MARUCAM_CTRL_VALUE_MAX; /* maximum */ - param->stack[3] = MARUCAM_CTRL_VALUE_STEP; /* step */ - param->stack[4] = MARUCAM_CTRL_VALUE_MID; /* default_value */ - param->stack[5] = ctrl.flags; - /* name field setting */ - memcpy(¶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(); - - if (saved_frame.data) { - g_free(saved_frame.data); - saved_frame.data = NULL; - } - memset(&saved_frame, 0x00, sizeof(saved_frame)); - - v4l2_close(v4l2_fd); - v4l2_fd = 0; - INFO("Closed\n"); -} diff --git a/tizen/src/hw/pci/maru_camera_win32.c b/tizen/src/hw/pci/maru_camera_win32.c new file mode 100644 index 0000000000..337c371ae0 --- /dev/null +++ b/tizen/src/hw/pci/maru_camera_win32.c @@ -0,0 +1,2499 @@ +/* + * Implementation of MARU Virtual Camera device by PCI bus on Windows. + * + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jinhyung Jo + * Sangho Park + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + + +#include "qemu-common.h" +#include "sysemu/hax.h" +#include "maru_camera.h" +#include "debug_ch.h" + +#define CINTERFACE +#define COBJMACROS +#include "ocidl.h" +#include "errors.h" /* for VFW_E_XXXX */ +#include "mmsystem.h" /* for MAKEFOURCC macro */ +#include "maru_camera_win32.h" + +MULTI_DEBUG_CHANNEL(tizen, camera); + +/* + * COM Interface implementations + * + */ + +#define SAFE_RELEASE(x) \ + do { \ + if (x) { \ + (x)->lpVtbl->Release(x); \ + x = NULL; \ + } \ + } while (0) + +typedef HRESULT (STDAPICALLTYPE *CallbackFn)(ULONG dwSize, BYTE *pBuffer); + +/* + * HWCGrabCallback + */ + +typedef struct HWCGrabCallback { + IGrabCallback IGrabCallback_iface; + long m_cRef; + CallbackFn m_pCallback; + STDMETHODIMP (*SetCallback)(IGrabCallback *iface, CallbackFn pCallbackFn); +} HWCGrabCallback; + +static inline HWCGrabCallback *impl_from_IGrabCallback(IGrabCallback *iface) +{ + return CONTAINING_RECORD(iface, HWCGrabCallback, IGrabCallback_iface); +} + +static STDMETHODIMP HWCGrabCallback_QueryInterface(IGrabCallback *iface, + REFIID riid, void **ppv) +{ + if (IsEqualIID(riid, &IID_IUnknown)) { + *ppv = (IUnknown *)iface; + } else if (IsEqualIID(riid, &IID_IGrabCallback)) { + *ppv = (IGrabCallback *)iface; + } else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IGrabCallback_AddRef(iface); + return S_OK; +} + +static STDMETHODIMP_(ULONG) HWCGrabCallback_AddRef(IGrabCallback *iface) +{ + HWCGrabCallback *This = impl_from_IGrabCallback(iface); + + return InterlockedIncrement(&This->m_cRef); +} + +static STDMETHODIMP_(ULONG) HWCGrabCallback_Release(IGrabCallback *iface) +{ + HWCGrabCallback *This = impl_from_IGrabCallback(iface); + + if (InterlockedDecrement(&This->m_cRef) == 0) { + This->m_pCallback = NULL; + g_free((void *)This); + This = NULL; + return 0; + } + + return This->m_cRef; +} + +static STDMETHODIMP HWCGrabCallback_Grab(IGrabCallback *iface, + ULONG dwSize, BYTE *pBuffer) +{ + HWCGrabCallback *This = impl_from_IGrabCallback(iface); + + if (This->m_pCallback) { + HRESULT hr = This->m_pCallback(dwSize, pBuffer); + if (FAILED(hr)) { + return E_FAIL; + } else { + return S_OK; + } + } + + return E_FAIL; +} + +static STDMETHODIMP HWCGrabCallback_SetCallback(IGrabCallback *iface, + CallbackFn pCallbackFn) +{ + HWCGrabCallback *This = impl_from_IGrabCallback(iface); + + This->m_pCallback = pCallbackFn; + return S_OK; +} + +static IGrabCallbackVtbl HWCGrabCallback_Vtbl = { + HWCGrabCallback_QueryInterface, + HWCGrabCallback_AddRef, + HWCGrabCallback_Release, + HWCGrabCallback_Grab +}; + +static STDMETHODIMP HWCGrabCallback_Construct(IGrabCallback **ppv) +{ + HWCGrabCallback *This = + (HWCGrabCallback *)g_malloc0(sizeof(HWCGrabCallback)); + + if (!This) { + ERR("failed to HWCGrabCallback_Construct, E_OUTOFMEMORY\n"); + return E_OUTOFMEMORY; + } + + This->IGrabCallback_iface.lpVtbl = &HWCGrabCallback_Vtbl; + This->m_cRef = 1; + This->m_pCallback = NULL; + This->SetCallback = HWCGrabCallback_SetCallback; + *ppv = &This->IGrabCallback_iface; + return S_OK; +} + +/* + * HWCPin + */ + +typedef struct HWCInPin { + IPin IPin_iface; + IMemInputPin IMemInputPin_iface; + IBaseFilter *m_pCFilter; + IPin *m_pConnectedPin; + IGrabCallback *m_pCallback; + IMemAllocator *m_pAllocator; + BOOL m_bReadOnly; + long m_cRef; + STDMETHODIMP (*SetGrabCallbackIF)(IPin *iface, IGrabCallback *pCaptureCB); +} HWCInPin; + +static inline HWCInPin *impl_from_IPin(IPin *iface) +{ + return CONTAINING_RECORD(iface, HWCInPin, IPin_iface); +} + +static inline HWCInPin *impl_from_IMemInputPin(IMemInputPin *iface) +{ + return CONTAINING_RECORD(iface, HWCInPin, IMemInputPin_iface); +} + +static STDMETHODIMP HWCPin_QueryInterface(IPin *iface, REFIID riid, void **ppv) +{ + HWCInPin *This = impl_from_IPin(iface); + + if (IsEqualIID(riid, &IID_IUnknown)) { + *ppv = (IUnknown *)(&This->IPin_iface); + IPin_AddRef((IPin *)*ppv); + } else if (IsEqualIID(riid, &IID_IPin)) { + *ppv = (IPin *)(&This->IPin_iface); + IPin_AddRef((IPin *)*ppv); + } else if (IsEqualIID(riid, &IID_IMemInputPin)) { + *ppv = (IMemInputPin *)(&This->IMemInputPin_iface); + IPin_AddRef((IMemInputPin *)*ppv); + } else { + *ppv = NULL; + return E_NOINTERFACE; + } + + return S_OK; +} + +static STDMETHODIMP_(ULONG) HWCPin_AddRef(IPin *iface) +{ + HWCInPin *This = impl_from_IPin(iface); + + return InterlockedIncrement(&This->m_cRef); +} + +static STDMETHODIMP_(ULONG) HWCPin_Release(IPin *iface) +{ + HWCInPin *This = impl_from_IPin(iface); + + if (InterlockedDecrement(&This->m_cRef) == 0) { + if (This->m_pCallback) { + SAFE_RELEASE(This->m_pCallback); + } + if (This->m_pConnectedPin) { + SAFE_RELEASE(This->m_pConnectedPin); + } + if (This->m_pAllocator) { + IMemAllocator_Decommit(This->m_pAllocator); + SAFE_RELEASE(This->m_pAllocator); + } + g_free((void *)This); + This = NULL; + return 0; + } + return This->m_cRef; +} + +static STDMETHODIMP HWCPin_Connect(IPin *iface, + IPin *pReceivePin, + const AM_MEDIA_TYPE *pmt) +{ + HWCInPin *This = impl_from_IPin(iface); + + if (!pReceivePin) { + return E_POINTER; + } + + if (This->m_pConnectedPin) { + return VFW_E_ALREADY_CONNECTED; + } + + if (!pmt) { + return S_OK; + } + return S_FALSE; +} + +static STDMETHODIMP HWCPin_ReceiveConnection(IPin *iface, IPin *pConnector, + const AM_MEDIA_TYPE *pmt) +{ + PIN_DIRECTION pd; + FILTER_STATE fs; + HWCInPin *This = impl_from_IPin(iface); + + if (pConnector == NULL || pmt == NULL) { + return E_POINTER; + } + + if (This->m_pConnectedPin) { + return VFW_E_ALREADY_CONNECTED; + } + IBaseFilter_GetState(This->m_pCFilter, 0, &fs); + if (fs != State_Stopped) { + return VFW_E_NOT_STOPPED; + } + IPin_QueryDirection(pConnector, &pd); + if (pd == PINDIR_INPUT) { + return VFW_E_INVALID_DIRECTION; + } + + This->m_pConnectedPin = pConnector; + IPin_AddRef(This->m_pConnectedPin); + return S_OK; +} + +static STDMETHODIMP HWCPin_Disconnect(IPin *iface) +{ + HWCInPin *This = impl_from_IPin(iface); + + HRESULT hr; + FILTER_STATE fs; + IBaseFilter_GetState(This->m_pCFilter, 0, &fs); + if (fs != State_Stopped) { + return VFW_E_NOT_STOPPED; + } + if (This->m_pConnectedPin == NULL) { + hr = S_FALSE; + } else { + if (This->m_pAllocator) { + hr = IMemAllocator_Decommit(This->m_pAllocator); + if (FAILED(hr)) { + return hr; + } + SAFE_RELEASE(This->m_pAllocator); + } + SAFE_RELEASE(This->m_pConnectedPin); + hr = S_OK; + } + return hr; +} + +static STDMETHODIMP HWCPin_ConnectedTo(IPin *iface, IPin **ppPin) +{ + HWCInPin *This = impl_from_IPin(iface); + + if (ppPin == NULL) { + return E_POINTER; + } + + if (This->m_pConnectedPin == NULL) { + *ppPin = NULL; + return VFW_E_NOT_CONNECTED; + } else { + *ppPin = This->m_pConnectedPin; + IPin_AddRef(This->m_pConnectedPin); + } + return S_OK; +} + +static STDMETHODIMP HWCPin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *pmt) +{ + if (pmt == NULL) { + return E_POINTER; + } + return VFW_E_NOT_CONNECTED; +} + +static STDMETHODIMP HWCPin_QueryPinInfo(IPin *iface, PIN_INFO *pInfo) +{ + HWCInPin *This = impl_from_IPin(iface); + + if (pInfo == NULL) { + return E_POINTER; + } + + pInfo->pFilter = This->m_pCFilter; + if (This->m_pCFilter) { + IBaseFilter_AddRef(This->m_pCFilter); + } + memcpy((void *)pInfo->achName, (void *)HWCPinName, sizeof(HWCPinName)); + pInfo->dir = PINDIR_INPUT; + return S_OK; +} + +static STDMETHODIMP HWCPin_QueryDirection(IPin *iface, PIN_DIRECTION *pPinDir) +{ + if (pPinDir == NULL) { + return E_POINTER; + } + *pPinDir = PINDIR_INPUT; + return S_OK; +} + +static STDMETHODIMP HWCPin_QueryId(IPin *iface, LPWSTR *Id) +{ + PVOID pId; + if (Id == NULL) { + return E_POINTER; + } + pId = CoTaskMemAlloc(sizeof(HWCPinName)); + memcpy((void *)pId, (void *)HWCPinName, sizeof(HWCPinName)); + *Id = (LPWSTR)pId; + return S_OK; +} + +static STDMETHODIMP HWCPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *pmt) +{ + if (pmt == NULL) { + return E_POINTER; + } + return S_OK; +} + +static STDMETHODIMP HWCPin_EnumMediaTypes(IPin *iface, + IEnumMediaTypes **ppEnum) +{ + if (ppEnum == NULL) { + return E_POINTER; + } + return E_NOTIMPL; +} + +static STDMETHODIMP HWCPin_QueryInternalConnections(IPin *iface, + IPin **ppPin, + ULONG *nPin) +{ + return E_NOTIMPL; +} + +static STDMETHODIMP HWCPin_EndOfStream(IPin *iface) +{ + return S_OK; +} + +static STDMETHODIMP HWCPin_BeginFlush(IPin *iface) +{ + return S_OK; +} + +static STDMETHODIMP HWCPin_EndFlush(IPin *iface) +{ + return S_OK; +} + +static STDMETHODIMP HWCPin_NewSegment(IPin *iface, REFERENCE_TIME tStart, + REFERENCE_TIME tStop, double dRate) +{ + return S_OK; +} + +static STDMETHODIMP HWCMemInputPin_QueryInterface(IMemInputPin *iface, + REFIID riid, void **ppv) +{ + HWCInPin *This = impl_from_IMemInputPin(iface); + + if (IsEqualIID(riid, &IID_IUnknown)) { + *ppv = (IUnknown *)(&This->IMemInputPin_iface); + IPin_AddRef((IPin *)*ppv); + } else if (IsEqualIID(riid, &IID_IPin)) { + *ppv = (IPin *)(&This->IPin_iface); + IPin_AddRef((IPin *)*ppv); + } else if (IsEqualIID(riid, &IID_IMemInputPin)) { + *ppv = (IMemInputPin *)(&This->IMemInputPin_iface); + IPin_AddRef((IMemInputPin *)*ppv); + } else { + *ppv = NULL; + return E_NOINTERFACE; + } + + return S_OK; +} + +static STDMETHODIMP_(ULONG) HWCMemInputPin_AddRef(IMemInputPin *iface) +{ + HWCInPin *This = impl_from_IMemInputPin(iface); + + return InterlockedIncrement(&This->m_cRef); +} + +static STDMETHODIMP_(ULONG) HWCMemInputPin_Release(IMemInputPin *iface) +{ + HWCInPin *This = impl_from_IMemInputPin(iface); + + if (InterlockedDecrement(&This->m_cRef) == 0) { + if (This->m_pCallback) { + SAFE_RELEASE(This->m_pCallback); + } + if (This->m_pConnectedPin) { + SAFE_RELEASE(This->m_pConnectedPin); + } + if (This->m_pAllocator) { + IMemAllocator_Decommit(This->m_pAllocator); + SAFE_RELEASE(This->m_pAllocator); + } + g_free((void *)This); + This = NULL; + return 0; + } + return This->m_cRef; +} + +static STDMETHODIMP HWCMemInputPin_GetAllocator(IMemInputPin *iface, + IMemAllocator **ppAllocator) +{ + HWCInPin *This = impl_from_IMemInputPin(iface); + + if (ppAllocator == NULL) { + return E_POINTER; + } + + if (This->m_pAllocator == NULL) { + HRESULT hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, + CLSCTX_INPROC_SERVER, + &IID_IMemAllocator, + (void **)&(This->m_pAllocator)); + if (FAILED(hr)) { + ERR("Failed to CoCreateInstance for retrieving MemoryAllocator\n"); + return hr; + } + } + assert(This->m_pAllocator != NULL); + *ppAllocator = This->m_pAllocator; + IMemAllocator_AddRef(This->m_pAllocator); + + return S_OK; +} + +static STDMETHODIMP HWCMemInputPin_NotifyAllocator(IMemInputPin *iface, + IMemAllocator *pAllocator, + BOOL bReadOnly) +{ + HWCInPin *This = impl_from_IMemInputPin(iface); + + if (pAllocator == NULL) { + return E_POINTER; + } + + IMemAllocator *pOldAllocator = This->m_pAllocator; + IMemAllocator_AddRef(pAllocator); + This->m_pAllocator = pAllocator; + + if (pOldAllocator != NULL) { + SAFE_RELEASE(pOldAllocator); + } + + This->m_bReadOnly = bReadOnly; + + return S_OK; +} + +static STDMETHODIMP HWCMemInputPin_GetAllocatorRequirements( + IMemInputPin *iface, + ALLOCATOR_PROPERTIES *pProps) +{ + return E_NOTIMPL; +} + +static STDMETHODIMP HWCMemInputPin_Receive(IMemInputPin *iface, + IMediaSample *pSample) +{ + HWCInPin *This = impl_from_IMemInputPin(iface); + + if (pSample == NULL) { + ERR("pSample is NULL\n"); + return E_POINTER; + } + if (This->m_pCallback != NULL) { + HRESULT hr; + BYTE *pBuffer = NULL; + DWORD dwSize = 0; + dwSize = IMediaSample_GetSize(pSample); + hr = IMediaSample_GetPointer(pSample, &pBuffer); + if (FAILED(hr)) { + ERR("Receive function : " + "failed to IMediaSample_GetPointer, 0x%ld\n", hr); + return hr; + } + hr = IGrabCallback_Grab(This->m_pCallback, dwSize, pBuffer); + if (FAILED(hr)) { + ERR("Receive function : failed to IGrabCallback_Grab, 0x%ld\n", + hr); + return hr; + } + } + return S_OK; +} + +static STDMETHODIMP HWCMemInputPin_ReceiveMultiple(IMemInputPin *iface, + IMediaSample **pSamples, + long nSamples, + long *nSamplesProcessed) +{ + HRESULT hr = S_OK; + + if (pSamples == NULL) { + return E_POINTER; + } + + *nSamplesProcessed = 0; + + while (nSamples-- > 0) { + hr = IMemInputPin_Receive(iface, pSamples[*nSamplesProcessed]); + if (hr != S_OK) { + break; + } + (*nSamplesProcessed)++; + } + return hr; +} + +static STDMETHODIMP HWCMemInputPin_ReceiveCanBlock(IMemInputPin *iface) +{ + return S_FALSE; +} + +static STDMETHODIMP HWCPin_SetCallback(IPin *iface, IGrabCallback *pCaptureCB) +{ + HWCInPin *This = impl_from_IPin(iface); + + if (pCaptureCB == NULL) { + SAFE_RELEASE(This->m_pCallback); + } else { + This->m_pCallback = pCaptureCB; + IGrabCallback_AddRef(This->m_pCallback); + } + + return S_OK; +} + + +static IPinVtbl HWCPin_Vtbl = { + HWCPin_QueryInterface, + HWCPin_AddRef, + HWCPin_Release, + HWCPin_Connect, + HWCPin_ReceiveConnection, + HWCPin_Disconnect, + HWCPin_ConnectedTo, + HWCPin_ConnectionMediaType, + HWCPin_QueryPinInfo, + HWCPin_QueryDirection, + HWCPin_QueryId, + HWCPin_QueryAccept, + HWCPin_EnumMediaTypes, + HWCPin_QueryInternalConnections, + HWCPin_EndOfStream, + HWCPin_BeginFlush, + HWCPin_EndFlush, + HWCPin_NewSegment +}; + +static IMemInputPinVtbl HWCMemInputPin_Vtbl = { + HWCMemInputPin_QueryInterface, + HWCMemInputPin_AddRef, + HWCMemInputPin_Release, + HWCMemInputPin_GetAllocator, + HWCMemInputPin_NotifyAllocator, + HWCMemInputPin_GetAllocatorRequirements, + HWCMemInputPin_Receive, + HWCMemInputPin_ReceiveMultiple, + HWCMemInputPin_ReceiveCanBlock +}; + +static STDMETHODIMP HWCInPin_Construct(IBaseFilter *pFilter, IPin **ppv) +{ + HWCInPin *This = (HWCInPin *)g_malloc0(sizeof(HWCInPin)); + + if (!This) { + ERR("failed to HWCInPin_Construct, E_OUTOFMEMORY\n"); + return E_OUTOFMEMORY; + } + + This->IPin_iface.lpVtbl = &HWCPin_Vtbl; + This->IMemInputPin_iface.lpVtbl = &HWCMemInputPin_Vtbl; + This->m_bReadOnly = FALSE; + This->m_pCFilter = pFilter; + This->m_pConnectedPin = NULL; + This->m_pCallback = NULL; + This->m_pAllocator = NULL; + This->m_cRef = 1; + This->SetGrabCallbackIF = HWCPin_SetCallback; + *ppv = &This->IPin_iface; + + return S_OK; +} + +/* + * HWCEnumPins + */ + +typedef struct HWCEnumPins { + IEnumPins IEnumPins_iface; + IBaseFilter *m_pFilter; + int m_nPos; + long m_cRef; +} HWCEnumPins; + +static inline HWCEnumPins *impl_from_IEnumPins(IEnumPins *iface) +{ + return CONTAINING_RECORD(iface, HWCEnumPins, IEnumPins_iface); +} + +static STDMETHODIMP HWCEnumPins_QueryInterface(IEnumPins *iface, + REFIID riid, void **ppv) +{ + if (ppv == NULL) { + return E_POINTER; + } + + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumPins)) { + *ppv = iface; + } else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IEnumPins_AddRef(iface); + return S_OK; +} + +static STDMETHODIMP_(ULONG) HWCEnumPins_AddRef(IEnumPins *iface) +{ + HWCEnumPins *This = impl_from_IEnumPins(iface); + + return InterlockedIncrement(&This->m_cRef); +} + +static STDMETHODIMP_(ULONG) HWCEnumPins_Release(IEnumPins *iface) +{ + HWCEnumPins *This = impl_from_IEnumPins(iface); + + if (InterlockedDecrement(&This->m_cRef) == 0) { + if (This->m_pFilter) { + SAFE_RELEASE(This->m_pFilter); + } + This->m_nPos = 0; + g_free((void *)This); + This = NULL; + return 0; + } + return This->m_cRef; +} + +static STDMETHODIMP HWCEnumPins_Next(IEnumPins *iface, ULONG cPins, + IPin **ppPins, ULONG *pcFetched) +{ + ULONG fetched; + HWCEnumPins *This = impl_from_IEnumPins(iface); + + if (ppPins == NULL) { + return E_POINTER; + } + + if (This->m_nPos < 1 && cPins > 0) { + IPin *pPin; + IBaseFilter_FindPin(This->m_pFilter, HWCPinName, &pPin); + *ppPins = pPin; + fetched = 1; + This->m_nPos++; + } else { + fetched = 0; + } + + if (pcFetched != NULL) { + *pcFetched = fetched; + } + + return (fetched == cPins) ? S_OK : S_FALSE; +} + +static STDMETHODIMP HWCEnumPins_Skip(IEnumPins *iface, ULONG cPins) +{ + HWCEnumPins *This = impl_from_IEnumPins(iface); + This->m_nPos += cPins; + return (This->m_nPos >= 1) ? S_FALSE : S_OK; +} + +static STDMETHODIMP HWCEnumPins_Reset(IEnumPins *iface) +{ + HWCEnumPins *This = impl_from_IEnumPins(iface); + This->m_nPos = 0; + return S_OK; +} + +static STDMETHODIMP HWCEnumPins_Construct(IBaseFilter *pFilter, + int nPos, IEnumPins **ppv); + +static STDMETHODIMP HWCEnumPins_Clone(IEnumPins *iface, IEnumPins **ppEnum) +{ + HWCEnumPins *This = impl_from_IEnumPins(iface); + + if (ppEnum == NULL) { + return E_POINTER; + } + + HWCEnumPins_Construct(This->m_pFilter, This->m_nPos, ppEnum); + if (*ppEnum == NULL) { + ERR("failed to HWCEnumPins_Construct in clone, E_OUTOFMEMORY\n"); + return E_OUTOFMEMORY; + } + + return S_OK; +} + +static IEnumPinsVtbl HWCEnumPins_Vtbl = { + HWCEnumPins_QueryInterface, + HWCEnumPins_AddRef, + HWCEnumPins_Release, + HWCEnumPins_Next, + HWCEnumPins_Skip, + HWCEnumPins_Reset, + HWCEnumPins_Clone +}; + + +static STDMETHODIMP HWCEnumPins_Construct(IBaseFilter *pFilter, + int nPos, IEnumPins **ppv) +{ + HWCEnumPins *This = (HWCEnumPins *)g_malloc0(sizeof(HWCEnumPins)); + + if (!This) { + ERR("failed to HWCEnumPins_Construct, E_OUTOFMEMORY\n"); + return E_OUTOFMEMORY; + } + + This->IEnumPins_iface.lpVtbl = &HWCEnumPins_Vtbl; + This->m_pFilter = pFilter; + if (This->m_pFilter) { + IBaseFilter_AddRef(This->m_pFilter); + } + This->m_cRef = 1; + This->m_nPos = nPos; + *ppv = &This->IEnumPins_iface; + + return S_OK; +} + +/* + * HWCFilter + */ + +typedef struct HWCFilter { + IBaseFilter IBaseFilter_iface; + IPin *m_pPin; + IFilterGraph *m_pFilterGraph; + FILTER_STATE m_state; + long m_cRef; +} HWCFilter; + +static inline HWCFilter *impl_from_IBaseFilter(IBaseFilter *iface) +{ + return CONTAINING_RECORD(iface, HWCFilter, IBaseFilter_iface); +} + +static STDMETHODIMP HWCFilter_QueryInterface(IBaseFilter *iface, + REFIID riid, void **ppv) +{ + if (IsEqualIID(riid, &IID_IUnknown)) { + *ppv = (IUnknown *)iface; + } else if (IsEqualIID(riid, &IID_IPersist)) { + *ppv = (IPersist *)iface; + } else if (IsEqualIID(riid, &IID_IMediaFilter)) { + *ppv = (IMediaFilter *)iface; + } else if (IsEqualIID(riid, &IID_IBaseFilter)) { + *ppv = (IBaseFilter *)iface; + } else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IBaseFilter_AddRef(iface); + return S_OK; +} + +static STDMETHODIMP_(ULONG) HWCFilter_AddRef(IBaseFilter *iface) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + + return InterlockedIncrement(&This->m_cRef); +} + +static STDMETHODIMP_(ULONG) HWCFilter_Release(IBaseFilter *iface) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + + if (InterlockedDecrement(&This->m_cRef) == 0) { + if (This->m_pPin) { + SAFE_RELEASE(This->m_pPin); + } + g_free((void *)This); + This = NULL; + return 0; + } + return This->m_cRef; +} + +static STDMETHODIMP HWCFilter_GetClassID(IBaseFilter *iface, CLSID *pClsID) +{ + if (pClsID == NULL) { + return E_POINTER; + } + return E_NOTIMPL; +} + +static STDMETHODIMP HWCFilter_GetState(IBaseFilter *iface, DWORD dwMSecs, + FILTER_STATE *State) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + *State = This->m_state; + return S_OK; +} + +static STDMETHODIMP HWCFilter_SetSyncSource(IBaseFilter *iface, + IReferenceClock *pClock) +{ + return S_OK; +} + +static STDMETHODIMP HWCFilter_GetSyncSource(IBaseFilter *iface, + IReferenceClock **pClock) +{ + *pClock = NULL; + return S_OK; +} + +static STDMETHODIMP HWCFilter_Stop(IBaseFilter *iface) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + + IPin_EndFlush(This->m_pPin); + This->m_state = State_Stopped; + return S_OK; +} + +static STDMETHODIMP HWCFilter_Pause(IBaseFilter *iface) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + This->m_state = State_Paused; + return S_OK; +} + +static STDMETHODIMP HWCFilter_Run(IBaseFilter *iface, REFERENCE_TIME tStart) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + + if (This->m_state == State_Stopped) { + HRESULT hr; + hr = IBaseFilter_Pause(iface); + if (FAILED(hr)) { + ERR("HWCFilter_Run : Failed to IBaseFilter_Pause, ret=0xld%\n", hr); + return hr; + } + } + + This->m_state = State_Running; + return S_OK; +} + +static STDMETHODIMP HWCFilter_EnumPins(IBaseFilter *iface, IEnumPins **ppEnum) +{ + if (ppEnum == NULL) { + return E_POINTER; + } + + HWCEnumPins_Construct(iface, 0, ppEnum); + return *ppEnum == NULL ? E_OUTOFMEMORY : S_OK; +} + +static STDMETHODIMP HWCFilter_FindPin(IBaseFilter *iface, LPCWSTR Id, + IPin **ppPin) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + + if (ppPin == NULL) { + return E_POINTER; + } + + if (memcmp((void *)Id, (void *)HWCPinName, sizeof(HWCPinName))) { + return VFW_E_NOT_FOUND; + } + + if (!This->m_pPin) { + HWCInPin_Construct(iface, &This->m_pPin); + } + *ppPin = This->m_pPin; + + IPin_AddRef(This->m_pPin); + return S_OK; +} + +static STDMETHODIMP HWCFilter_QueryFilterInfo(IBaseFilter *iface, + FILTER_INFO *pInfo) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + + if (pInfo == NULL) { + return E_POINTER; + } + + memcpy((void *)pInfo->achName, + (void *)HWCFilterName, + sizeof(HWCFilterName)); + pInfo->pGraph = This->m_pFilterGraph; + if (This->m_pFilterGraph) { + IFilterGraph_AddRef(This->m_pFilterGraph); + } + return S_OK; +} + +static STDMETHODIMP HWCFilter_JoinFilterGraph(IBaseFilter *iface, + IFilterGraph *pGraph, + LPCWSTR pName) +{ + HWCFilter *This = impl_from_IBaseFilter(iface); + + This->m_pFilterGraph = pGraph; + return S_OK; +} + +static STDMETHODIMP HWCFilter_QueryVendorInfo(IBaseFilter *iface, + LPWSTR *pVendorInfo) +{ + return E_NOTIMPL; +} + +static IBaseFilterVtbl HWCFilter_Vtbl = { + HWCFilter_QueryInterface, + HWCFilter_AddRef, + HWCFilter_Release, + HWCFilter_GetClassID, + HWCFilter_Stop, + HWCFilter_Pause, + HWCFilter_Run, + HWCFilter_GetState, + HWCFilter_SetSyncSource, + HWCFilter_GetSyncSource, + HWCFilter_EnumPins, + HWCFilter_FindPin, + HWCFilter_QueryFilterInfo, + HWCFilter_JoinFilterGraph, + HWCFilter_QueryVendorInfo +}; + +static STDMETHODIMP HWCFilter_Construct(IBaseFilter **ppv) +{ + HWCFilter *This = (HWCFilter *)g_malloc0(sizeof(HWCFilter)); + + if (!This) { + ERR("failed to HWCFilter_Construct, E_OUTOFMEMORY\n"); + return E_OUTOFMEMORY; + } + + This->IBaseFilter_iface.lpVtbl = &HWCFilter_Vtbl; + This->m_pFilterGraph = NULL; + This->m_state = State_Stopped; + This->m_cRef = 1; + HWCInPin_Construct(&This->IBaseFilter_iface, &This->m_pPin); + *ppv = &This->IBaseFilter_iface; + + return S_OK; +} + +/********************************************************** + * + * Virtual device implementations + * + **********************************************************/ + + +/* + * Declaration global variables for Win32 COM Interfaces + */ +IGraphBuilder *g_pGB ; +ICaptureGraphBuilder2 *g_pCGB; +IMediaControl *g_pMediaControl; + +IPin *g_pOutputPin; +IPin *g_pInputPin; +IBaseFilter *g_pDstFilter; +IBaseFilter *g_pSrcFilter; + +IGrabCallback *g_pCallback; + +typedef struct tagMaruCamConvertPixfmt { + uint32_t fmt; /* fourcc */ + uint32_t bpp; /* bits per pixel, 0 for compressed formats */ + uint32_t needs_conversion; +} MaruCamConvertPixfmt; + +static MaruCamConvertPixfmt supported_dst_pixfmts[] = { + { V4L2_PIX_FMT_YUYV, 16, 0 }, + { V4L2_PIX_FMT_YUV420, 12, 0 }, + { V4L2_PIX_FMT_YVU420, 12, 0 }, +}; + +typedef struct tagMaruCamConvertFrameInfo { + uint32_t width; + uint32_t height; +} MaruCamConvertFrameInfo; + +static MaruCamConvertFrameInfo supported_dst_frames[] = { + { 640, 480 }, + { 352, 288 }, + { 320, 240 }, + { 176, 144 }, + { 160, 120 }, +}; + +#define MARUCAM_CTRL_VALUE_MAX 20 +#define MARUCAM_CTRL_VALUE_MIN 1 +#define MARUCAM_CTRL_VALUE_MID 10 +#define MARUCAM_CTRL_VALUE_STEP 1 + +struct marucam_qctrl { + uint32_t id; + uint32_t hit; + long min; + long max; + long step; + long init_val; +}; + +static struct marucam_qctrl qctrl_tbl[] = { + { V4L2_CID_BRIGHTNESS, 0, }, + { V4L2_CID_CONTRAST, 0, }, + { V4L2_CID_SATURATION, 0, }, + { V4L2_CID_SHARPNESS, 0, }, +}; + +static MaruCamState *g_state; + +static uint32_t ready_count; +static uint32_t cur_fmt_idx; +static uint32_t cur_frame_idx; +static void *grab_buf; +static uint32_t g_dwSrcFmt; + + +/* + * Helper functions - converting values + */ + +static long value_convert_from_guest(long min, long max, long value) +{ + double rate = 0.0; + long dist = 0, ret = 0; + + dist = max - min; + + if (dist < MARUCAM_CTRL_VALUE_MAX) { + rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; + ret = min + (int32_t)(value / rate); + } else { + rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; + ret = min + (int32_t)(rate * value); + } + return ret; +} + +static long value_convert_to_guest(long min, long max, long value) +{ + double rate = 0.0; + long dist = 0, ret = 0; + + dist = max - min; + + if (dist < MARUCAM_CTRL_VALUE_MAX) { + rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; + ret = (int32_t)((double)(value - min) * rate); + } else { + rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; + ret = (int32_t)((double)(value - min) / rate); + } + + return ret; +} + +/* + * Callback function for grab frames + */ +static STDMETHODIMP marucam_device_callbackfn(ULONG dwSize, BYTE *pBuffer) +{ + void *tmp_buf; + uint32_t width, height, fmt, imgsize; + + width = supported_dst_frames[cur_frame_idx].width; + height = supported_dst_frames[cur_frame_idx].height; + fmt = supported_dst_pixfmts[cur_fmt_idx].fmt; + imgsize = get_sizeimage(fmt, width, height); + + if (imgsize > (uint32_t)dwSize) { + ERR("Image size is mismatched\n"); + return E_FAIL; + } + + if (convert_frame(g_dwSrcFmt, fmt, width, height, + (size_t)dwSize, pBuffer, grab_buf) > 0) { + return E_FAIL; + } + + qemu_mutex_lock(&g_state->thread_mutex); + if (g_state->streamon) { + if (ready_count < MARUCAM_SKIPFRAMES) { + /* skip a frame cause first some frame are distorted */ + ++ready_count; + TRACE("skip %d frame\n", ready_count); + qemu_mutex_unlock(&g_state->thread_mutex); + return S_OK; + } + if (g_state->req_frame == 0) { + TRACE("there is no request\n"); + qemu_mutex_unlock(&g_state->thread_mutex); + return S_OK; + } + tmp_buf = g_state->vaddr + g_state->buf_size * (g_state->req_frame - 1); + memcpy(tmp_buf, grab_buf, g_state->buf_size); + g_state->req_frame = 0; /* clear request */ + g_state->isr |= 0x01; /* set a flag of rasing a interrupt */ + qemu_bh_schedule(g_state->tx_bh); + } + qemu_mutex_unlock(&g_state->thread_mutex); + return S_OK; +} + +/* + * Internal functions for manipulate interfaces + */ + +static STDMETHODIMP_(void) CloseInterfaces(void) +{ + if (g_pMediaControl) { + g_pMediaControl->lpVtbl->Stop(g_pMediaControl); + } + + if (g_pOutputPin) { + g_pOutputPin->lpVtbl->Disconnect(g_pOutputPin); + } + + SAFE_RELEASE(g_pGB); + SAFE_RELEASE(g_pCGB); + SAFE_RELEASE(g_pMediaControl); + SAFE_RELEASE(g_pOutputPin); + SAFE_RELEASE(g_pInputPin); + SAFE_RELEASE(g_pDstFilter); + SAFE_RELEASE(g_pSrcFilter); + SAFE_RELEASE(g_pCallback); +} + +static STDMETHODIMP_(void) DeleteMediaType(AM_MEDIA_TYPE *pmt) +{ + if (pmt == NULL) { + return; + } + + if (pmt->cbFormat != 0) { + CoTaskMemFree((PVOID)pmt->pbFormat); + pmt->cbFormat = 0; + pmt->pbFormat = NULL; + } + if (pmt->pUnk != NULL) { + pmt->pUnk->lpVtbl->Release(pmt->pUnk); + pmt->pUnk = NULL; + } + + CoTaskMemFree((PVOID)pmt); +} + +static STDMETHODIMP GetPin(IBaseFilter *pFilter, + PIN_DIRECTION PinDir, IPin **ppPin) +{ + HRESULT hr; + IEnumPins *pEnum = NULL; + IPin *pPin = NULL; + + if (ppPin == NULL) { + return E_POINTER; + } + + hr = pFilter->lpVtbl->EnumPins(pFilter, &pEnum); + if (FAILED(hr)) { + return hr; + } + + while (pEnum->lpVtbl->Next(pEnum, 1, &pPin, 0) == S_OK) { + PIN_DIRECTION PinDirThis; + hr = pPin->lpVtbl->QueryDirection(pPin, &PinDirThis); + if (FAILED(hr)) { + SAFE_RELEASE(pPin); + SAFE_RELEASE(pEnum); + return hr; + } + if (PinDir == PinDirThis) { + *ppPin = pPin; + SAFE_RELEASE(pEnum); + return S_OK; + } + SAFE_RELEASE(pPin); + } + + SAFE_RELEASE(pEnum); + return S_FALSE; +} + +static STDMETHODIMP GraphBuilder_Init(void) +{ + HRESULT hr; + + hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC, + &IID_IGraphBuilder, (void **)&g_pGB); + if (FAILED(hr)) { + ERR("Failed to create instance of GraphBuilder, 0x%x\n", hr); + return hr; + } + + hr = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, + &IID_ICaptureGraphBuilder2, (void **)&g_pCGB); + if (FAILED(hr)) { + ERR("Failed to create instance of CaptureGraphBuilder2, 0x%x\n", hr); + return hr; + } + + hr = g_pCGB->lpVtbl->SetFiltergraph(g_pCGB, g_pGB); + if (FAILED(hr)) { + ERR("Failed to SetFiltergraph, 0x%x\n", hr); + return hr; + } + + hr = g_pGB->lpVtbl->QueryInterface(g_pGB, &IID_IMediaControl, + (void **)&g_pMediaControl); + if (FAILED(hr)) { + ERR("Failed to QueryInterface for IMediaControl, 0x%x\n", hr); + return hr; + } + + hr = HWCGrabCallback_Construct(&g_pCallback); + if (g_pCallback == NULL) { + hr = E_OUTOFMEMORY; + } + + hr = ((HWCGrabCallback *)g_pCallback)->SetCallback(g_pCallback, + (CallbackFn)marucam_device_callbackfn); + + return hr; +} + +static STDMETHODIMP BindSourceFilter(void) +{ + HRESULT hr; + ICreateDevEnum *pCreateDevEnum = NULL; + IEnumMoniker *pEnumMK = NULL; + IMoniker *pMoniKer; + + hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, + &IID_ICreateDevEnum, + (void **)&pCreateDevEnum); + if (FAILED(hr)) { + ERR("Failed to create instance of CreateDevEnum, 0x%x\n", hr); + return hr; + } + + hr = pCreateDevEnum->lpVtbl->CreateClassEnumerator(pCreateDevEnum, + &CLSID_VideoInputDeviceCategory, + &pEnumMK, 0); + if (FAILED(hr)) { + ERR("Failed to get VideoInputDeviceCategory, 0x%x\n", hr); + SAFE_RELEASE(pCreateDevEnum); + return hr; + } + + if (!pEnumMK) { + ERR("ClassEnumerator moniker is NULL\n"); + SAFE_RELEASE(pCreateDevEnum); + return E_FAIL; + } + pEnumMK->lpVtbl->Reset(pEnumMK); + + hr = pEnumMK->lpVtbl->Next(pEnumMK, 1, &pMoniKer, NULL); + if (hr == S_FALSE) { + hr = E_FAIL; + } + if (SUCCEEDED(hr)) { + IPropertyBag *pBag = NULL; + hr = pMoniKer->lpVtbl->BindToStorage(pMoniKer, 0, 0, + &IID_IPropertyBag, + (void **)&pBag); + if (SUCCEEDED(hr)) { + VARIANT var; + var.vt = VT_BSTR; + hr = pBag->lpVtbl->Read(pBag, L"FriendlyName", &var, NULL); + if (hr == NOERROR) { + hr = pMoniKer->lpVtbl->BindToObject(pMoniKer, NULL, NULL, + &IID_IBaseFilter, + (void **)&g_pSrcFilter); + if (FAILED(hr)) { + ERR("Counldn't bind moniker to filter object!!\n"); + } else { + g_pSrcFilter->lpVtbl->AddRef(g_pSrcFilter); + } + SysFreeString(var.bstrVal); + } + SAFE_RELEASE(pBag); + } + SAFE_RELEASE(pMoniKer); + } + + if (SUCCEEDED(hr)) { + hr = g_pGB->lpVtbl->AddFilter(g_pGB, g_pSrcFilter, L"Video Capture"); + if (hr != S_OK && hr != S_FALSE) { + ERR("Counldn't add Video Capture filter to our graph!\n"); + SAFE_RELEASE(g_pSrcFilter); + } + } + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + + return hr; +} + +static STDMETHODIMP BindTargetFilter(void) +{ + HRESULT hr; + hr = HWCFilter_Construct(&g_pDstFilter); + + if (SUCCEEDED(hr) && g_pDstFilter) { + hr = g_pGB->lpVtbl->AddFilter(g_pGB, g_pDstFilter, L"HWCFilter"); + if (FAILED(hr)) { + ERR("Counldn't add HWCFilterr to our graph!\n"); + SAFE_RELEASE(g_pDstFilter); + } + } + return hr; +} + +static STDMETHODIMP ConnectFilters(void) +{ + HRESULT hr; + + hr = GetPin(g_pSrcFilter, PINDIR_OUTPUT , &g_pOutputPin); + if (FAILED(hr)) { + ERR("Failed to get output pin. 0x%x\n", hr); + return hr; + } + + hr = GetPin(g_pDstFilter, PINDIR_INPUT , &g_pInputPin); + if (FAILED(hr)) { + ERR("Failed to get input pin. 0x%x\n", hr); + return hr; + } + + hr = g_pGB->lpVtbl->Connect(g_pGB, g_pOutputPin, g_pInputPin); + if (FAILED(hr)) { + ERR("Failed to connect pins. 0x%x\n", hr); + } + return hr; +} + +static STDMETHODIMP DisconnectPins(void) +{ + HRESULT hr; + + hr = g_pGB->lpVtbl->Disconnect(g_pGB, g_pOutputPin); + if (FAILED(hr)) { + ERR("Failed to disconnect output pin. 0x%x\n", hr); + return hr; + } + + hr = g_pGB->lpVtbl->Disconnect(g_pGB, g_pInputPin); + if (FAILED(hr)) { + ERR("Failed to disconnect input pin. 0x%x\n", hr); + } + + return hr; +} + +static STDMETHODIMP RemoveFilters(void) +{ + HRESULT hr; + + hr = g_pGB->lpVtbl->RemoveFilter(g_pGB, g_pSrcFilter); + if (FAILED(hr)) { + ERR("Failed to remove source filer. 0x%x\n", hr); + return hr; + } + + hr = g_pGB->lpVtbl->RemoveFilter(g_pGB, g_pDstFilter); + if (FAILED(hr)) { + ERR("Failed to remove destination filer. 0x%x\n", hr); + } + + return hr; +} + +/* default fps is 15 */ +#define MARUCAM_DEFAULT_FRAMEINTERVAL 666666 + +static STDMETHODIMP SetFormat(uint32_t dwWidth, uint32_t dwHeight, + uint32_t dwDstFmt, uint32_t *dwSrcFmt) +{ + HRESULT hr; + IAMStreamConfig *pSConfig; + int iCount = 0, iSize = 0; + DWORD dwYUY2 = MAKEFOURCC('Y', 'U', 'Y', '2'); + DWORD dwI420 = MAKEFOURCC('I', '4', '2', '0'); + + if (dwSrcFmt == NULL) { + ERR("invalid the source format pointer\n"); + return E_FAIL; + } + + hr = g_pCGB->lpVtbl->FindInterface(g_pCGB, &PIN_CATEGORY_CAPTURE, 0, + g_pSrcFilter, &IID_IAMStreamConfig, + (void **)&pSConfig); + if (FAILED(hr)) { + ERR("failed to FindInterface method\n"); + return hr; + } + + hr = pSConfig->lpVtbl->GetNumberOfCapabilities(pSConfig, &iCount, &iSize); + if (FAILED(hr)) { + ERR("failed to GetNumberOfCapabilities method\n"); + SAFE_RELEASE(pSConfig); + return hr; + } + + if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) { + int iFormat = 0; + for (iFormat = 0; iFormat < iCount; iFormat++) { + VIDEO_STREAM_CONFIG_CAPS scc; + AM_MEDIA_TYPE *pmtConfig; + + hr = pSConfig->lpVtbl->GetStreamCaps(pSConfig, iFormat, + &pmtConfig, (BYTE *)&scc); + if (hr == S_OK) { + if (IsEqualIID(&pmtConfig->formattype, &FORMAT_VideoInfo)) { + VIDEOINFOHEADER *pvi = + (VIDEOINFOHEADER *)pmtConfig->pbFormat; + if ((pvi->bmiHeader.biWidth == (LONG)dwWidth) && + (pvi->bmiHeader.biHeight == (LONG)dwHeight)) { + if (pvi->bmiHeader.biCompression == dwYUY2) { + *dwSrcFmt = V4L2_PIX_FMT_YUYV; + } else if ((pvi->bmiHeader.biCompression == BI_RGB) && + (pvi->bmiHeader.biBitCount == 24)) { + *dwSrcFmt = V4L2_PIX_FMT_RGB24; + } else if (pvi->bmiHeader.biCompression == dwI420) { + *dwSrcFmt = V4L2_PIX_FMT_YUV420; + } else { /* not support format */ + DeleteMediaType(pmtConfig); + continue; + } + /* use minimum FPS(maximum frameinterval) + with non-VT system */ +#ifdef CONFIG_HAX + if (!hax_enabled()) { + pvi->AvgTimePerFrame = + (REFERENCE_TIME)scc.MaxFrameInterval; + } else { + pvi->AvgTimePerFrame = + (REFERENCE_TIME)MARUCAM_DEFAULT_FRAMEINTERVAL; + } +#else + pvi->AvgTimePerFrame = + (REFERENCE_TIME)scc.MaxFrameInterval; +#endif + hr = pSConfig->lpVtbl->SetFormat(pSConfig, pmtConfig); + DeleteMediaType(pmtConfig); + break; + } + } + DeleteMediaType(pmtConfig); + } + } + if (iFormat >= iCount) { + ERR("Failed to Set format. " + "Maybe connected webcam does not support the (%ldx%ld) " + "resolution or image formats(YUY2, RGB24, I420).\n", + dwWidth, dwHeight); + hr = E_FAIL; + } + } + SAFE_RELEASE(pSConfig); + return hr; +} + +static STDMETHODIMP QueryVideoProcAmp(long nProperty, long *pMin, long *pMax, + long *pStep, long *pDefault) +{ + HRESULT hr; + long Flags; + IAMVideoProcAmp *pProcAmp = NULL; + + hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter, + &IID_IAMVideoProcAmp, + (void **)&pProcAmp); + if (FAILED(hr)) { + return hr; + } + + hr = pProcAmp->lpVtbl->GetRange(pProcAmp, nProperty, pMin, pMax, + pStep, pDefault, &Flags); + + SAFE_RELEASE(pProcAmp); + return hr; +} + +static STDMETHODIMP GetVideoProcAmp(long nProperty, long *pValue) +{ + HRESULT hr; + long Flags; + IAMVideoProcAmp *pProcAmp = NULL; + + hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter, + &IID_IAMVideoProcAmp, + (void **)&pProcAmp); + if (FAILED(hr)) { + return hr; + } + + hr = pProcAmp->lpVtbl->Get(pProcAmp, nProperty, pValue, &Flags); + if (FAILED(hr)) { + ERR("Failed to get property for video\n"); + } + + SAFE_RELEASE(pProcAmp); + return hr; +} + +static STDMETHODIMP SetVideoProcAmp(long nProperty, long value) +{ + HRESULT hr; + + IAMVideoProcAmp *pProcAmp = NULL; + hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter, + &IID_IAMVideoProcAmp, + (void **)&pProcAmp); + if (FAILED(hr)) { + return hr; + } + + hr = pProcAmp->lpVtbl->Set(pProcAmp, nProperty, value, + VideoProcAmp_Flags_Manual); + if (FAILED(hr)) { + ERR("Failed to set property for video\n"); + } + SAFE_RELEASE(pProcAmp); + return hr; +} + +static char *__wchar_to_char(const WCHAR *pwstr) +{ + char *pstr = NULL; + int len = 0; + + len = wcslen(pwstr) + 1; + pstr = (char *)g_malloc0(sizeof(char) * len); + wcstombs(pstr, pwstr, len + 1); + + return pstr; +} + +int marucam_device_check(int log_flag) +{ + struct timeval t1, t2; + int ret = 0; + char *device_name = NULL; + HRESULT hr = E_FAIL; + ICreateDevEnum *pCreateDevEnum = NULL; + IGraphBuilder *pGB = NULL; + ICaptureGraphBuilder2 *pCGB = NULL; + IBaseFilter *pSrcFilter = NULL; + IEnumMoniker *pEnumMK = NULL; + IMoniker *pMoniKer = NULL; + IAMStreamConfig *pSConfig = NULL; + int iCount = 0, iSize = 0; + + gettimeofday(&t1, NULL); + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + if (FAILED(hr)) { + ERR("Failed to CoInitailizeEx\n"); + gettimeofday(&t2, NULL); + ERR("Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + hr = CoCreateInstance(&CLSID_FilterGraph, NULL, + CLSCTX_INPROC, + &IID_IGraphBuilder, + (void **)&pGB); + if (FAILED(hr)) { + ERR("Failed to create GraphBuilder, 0x%x\n", hr); + CoUninitialize(); + gettimeofday(&t2, NULL); + ERR("Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + hr = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL, + CLSCTX_INPROC, + &IID_ICaptureGraphBuilder2, + (void **)&pCGB); + if (FAILED(hr)) { + ERR("Failed to create CaptureGraphBuilder2, 0x%x\n", hr); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + ERR("Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + hr = pCGB->lpVtbl->SetFiltergraph(pCGB, pGB); + if (FAILED(hr)) { + ERR("Failed to SetFiltergraph, 0x%x\n", hr); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + ERR("Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, + CLSCTX_INPROC, + &IID_ICreateDevEnum, + (void **)&pCreateDevEnum); + if (FAILED(hr)) { + ERR("Failed to create instance of CLSID_SystemDeviceEnum\n"); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + ERR("Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + hr = pCreateDevEnum->lpVtbl->CreateClassEnumerator(pCreateDevEnum, + &CLSID_VideoInputDeviceCategory, &pEnumMK, 0); + if (FAILED(hr)) { + ERR("Failed to create class enumerator\n"); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + ERR("Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + if (!pEnumMK) { + ERR("Class enumerator is NULL!!\n"); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + ERR("Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + pEnumMK->lpVtbl->Reset(pEnumMK); + + hr = pEnumMK->lpVtbl->Next(pEnumMK, 1, &pMoniKer, NULL); + if (FAILED(hr) || (hr == S_FALSE)) { + ERR("Enum moniker returns a invalid value.\n"); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + ERR("Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + IPropertyBag *pBag = NULL; + hr = pMoniKer->lpVtbl->BindToStorage(pMoniKer, 0, 0, + &IID_IPropertyBag, + (void **)&pBag); + if (FAILED(hr)) { + ERR("Failed to bind to storage.\n"); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + ERR("Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } else { + VARIANT var; + var.vt = VT_BSTR; + hr = pBag->lpVtbl->Read(pBag, L"FriendlyName", &var, NULL); + if (hr == S_OK) { + ret = 1; + if (!log_flag) { + SysFreeString(var.bstrVal); + SAFE_RELEASE(pBag); + SAFE_RELEASE(pMoniKer); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + ERR("Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + device_name = __wchar_to_char(var.bstrVal); + INFO("Device name : %s\n", device_name); + g_free(device_name); + hr = pMoniKer->lpVtbl->BindToObject(pMoniKer, NULL, NULL, + &IID_IBaseFilter, + (void **)&pSrcFilter); + if (FAILED(hr)) { + ERR("Counldn't bind moniker to filter object!!\n"); + SysFreeString(var.bstrVal); + SAFE_RELEASE(pBag); + SAFE_RELEASE(pMoniKer); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + ERR("Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } else { + pSrcFilter->lpVtbl->AddRef(pSrcFilter); + } + SysFreeString(var.bstrVal); + } + SAFE_RELEASE(pBag); + } + SAFE_RELEASE(pMoniKer); + + hr = pGB->lpVtbl->AddFilter(pGB, pSrcFilter, L"Video Capture"); + if (hr != S_OK && hr != S_FALSE) { + ERR("Counldn't add Video Capture filter to our graph!\n"); + SAFE_RELEASE(pSrcFilter); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + ERR("Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + hr = pCGB->lpVtbl->FindInterface(pCGB, &PIN_CATEGORY_CAPTURE, 0, + pSrcFilter, &IID_IAMStreamConfig, + (void **)&pSConfig); + if (FAILED(hr)) { + ERR("Failed to FindInterface method\n"); + SAFE_RELEASE(pSrcFilter); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + ERR("Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + hr = pSConfig->lpVtbl->GetNumberOfCapabilities(pSConfig, &iCount, &iSize); + if (FAILED(hr)) { + ERR("Failed to GetNumberOfCapabilities method\n"); + SAFE_RELEASE(pSConfig); + SAFE_RELEASE(pSrcFilter); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + CoUninitialize(); + gettimeofday(&t2, NULL); + ERR("Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + return ret; + } + + if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) { + int iFormat = 0; + for (iFormat = 0; iFormat < iCount; iFormat++) { + VIDEO_STREAM_CONFIG_CAPS scc; + AM_MEDIA_TYPE *pmtConfig; + + hr = pSConfig->lpVtbl->GetStreamCaps(pSConfig, iFormat, &pmtConfig, + (BYTE *)&scc); + if (hr == S_OK) { + if (IsEqualIID(&pmtConfig->formattype, &FORMAT_VideoInfo)) { + VIDEOINFOHEADER *pvi = + (VIDEOINFOHEADER *)pmtConfig->pbFormat; + if (pvi->bmiHeader.biCompression == BI_RGB) { + INFO("RGB BitCount: %d, Frame size: %ux%u\n", + pvi->bmiHeader.biBitCount, + pvi->bmiHeader.biWidth, + pvi->bmiHeader.biHeight); + } else { + INFO("PixelFormat: %c%c%c%c, Frame size: %ux%u\n", + (char)(pvi->bmiHeader.biCompression), + (char)(pvi->bmiHeader.biCompression >> 8), + (char)(pvi->bmiHeader.biCompression >> 16), + (char)(pvi->bmiHeader.biCompression >> 24), + pvi->bmiHeader.biWidth, + pvi->bmiHeader.biHeight); + } + } + DeleteMediaType(pmtConfig); + } + } + } + + hr = pGB->lpVtbl->RemoveFilter(pGB, pSrcFilter); + if (FAILED(hr)) { + ERR("Failed to remove source filer. 0x%x\n", hr); + } + + SAFE_RELEASE(pSConfig); + SAFE_RELEASE(pSrcFilter); + SAFE_RELEASE(pCGB); + SAFE_RELEASE(pGB); + SAFE_RELEASE(pEnumMK); + SAFE_RELEASE(pCreateDevEnum); + CoUninitialize(); + gettimeofday(&t2, NULL); + ERR("Elapsed time : %lu.%06lu\n", + t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); + + return ret; +} + +/* MARUCAM_CMD_INIT */ +void marucam_device_init(MaruCamState *state) +{ + g_state = state; +} + +void marucam_device_exit(MaruCamState *state) +{ +} + +/* MARUCAM_CMD_OPEN */ +void marucam_device_open(MaruCamState *state) +{ + HRESULT hr; + uint32_t dwHeight, dwWidth, dwDstFmt; + MaruCamParam *param = state->param; + param->top = 0; + + hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + if (FAILED(hr)) { + ERR("CoInitailizeEx\n"); + ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); + param->errCode = EINVAL; + return; + } + + hr = GraphBuilder_Init(); + if (FAILED(hr)) { + ERR("GraphBuilder_Init\n"); + DisconnectPins(); + RemoveFilters(); + CloseInterfaces(); + CoUninitialize(); + param->errCode = EINVAL; + ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); + return; + } + + hr = BindSourceFilter(); + if (FAILED(hr)) { + ERR("BindSourceFilter\n"); + DisconnectPins(); + RemoveFilters(); + CloseInterfaces(); + CoUninitialize(); + param->errCode = EINVAL; + ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); + return; + } + + hr = BindTargetFilter(); + if (FAILED(hr)) { + ERR("BindTargetFilter\n"); + DisconnectPins(); + RemoveFilters(); + CloseInterfaces(); + CoUninitialize(); + param->errCode = EINVAL; + ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); + return; + } + + hr = ConnectFilters(); + if (FAILED(hr)) { + ERR("ConnectFilters\n"); + DisconnectPins(); + RemoveFilters(); + CloseInterfaces(); + CoUninitialize(); + param->errCode = EINVAL; + ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); + return; + } + + cur_frame_idx = 0; + cur_fmt_idx = 0; + + dwHeight = supported_dst_frames[cur_frame_idx].height; + dwWidth = supported_dst_frames[cur_frame_idx].width; + dwDstFmt = supported_dst_pixfmts[cur_fmt_idx].fmt; + hr = SetFormat(dwWidth, dwHeight, dwDstFmt, &g_dwSrcFmt); + if (hr != S_OK) { + ERR("failed to Set default values\n"); + DisconnectPins(); + RemoveFilters(); + CloseInterfaces(); + CoUninitialize(); + param->errCode = EINVAL; + ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); + return; + } + + INFO("Opened\n"); + return; +} + +/* MARUCAM_CMD_CLOSE */ +void marucam_device_close(MaruCamState *state) +{ + MaruCamParam *param = state->param; + int ret = 0; + param->top = 0; + + qemu_mutex_lock(&state->thread_mutex); + ret = state->streamon; + qemu_mutex_unlock(&state->thread_mutex); + if (ret) { + marucam_device_stop_preview(state); + } + + if (g_pGB) { + DisconnectPins(); + RemoveFilters(); + } + CloseInterfaces(); + CoUninitialize(); + INFO("Closed\n"); +} + +/* MARUCAM_CMD_START_PREVIEW */ +void marucam_device_start_preview(MaruCamState *state) +{ + HRESULT hr; + uint32_t pixfmt, width, height; + MaruCamParam *param = state->param; + param->top = 0; + + ready_count = 0; + width = supported_dst_frames[cur_frame_idx].width; + height = supported_dst_frames[cur_frame_idx].height; + pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; + state->buf_size = get_sizeimage(pixfmt, width, height); + + INFO("Pixfmt(%c%c%c%c), W:H(%d:%d), buf size(%u)\n", + (char)(pixfmt), (char)(pixfmt >> 8), + (char)(pixfmt >> 16), (char)(pixfmt >> 24), + width, height, state->buf_size); + INFO("Starting preview\n"); + + assert(g_pCallback != NULL); + hr = ((HWCInPin *)g_pInputPin)->SetGrabCallbackIF(g_pInputPin, + g_pCallback); + if (FAILED(hr)) { + ERR("Failed to set IGrabCallback interface.\n"); + param->errCode = EINVAL; + return; + } + + if (grab_buf) { + g_free(grab_buf); + grab_buf = NULL; + } + grab_buf = (void *)g_malloc0(state->buf_size); + if (grab_buf == NULL) { + param->errCode = ENOMEM; + return; + } + + hr = g_pMediaControl->lpVtbl->Run(g_pMediaControl); + if (FAILED(hr)) { + ERR("Failed to run media control. hr=0x%x\n", hr); + param->errCode = EINVAL; + return; + } + + qemu_mutex_lock(&state->thread_mutex); + state->streamon = 1; + qemu_mutex_unlock(&state->thread_mutex); + + INFO("Streaming on ......\n"); +} + +/* MARUCAM_CMD_STOP_PREVIEW */ +void marucam_device_stop_preview(MaruCamState *state) +{ + HRESULT hr; + MaruCamParam *param = state->param; + param->top = 0; + + INFO("...... Streaming off\n"); + qemu_mutex_lock(&state->thread_mutex); + state->streamon = 0; + qemu_mutex_unlock(&state->thread_mutex); + + hr = ((HWCInPin *)g_pInputPin)->SetGrabCallbackIF(g_pInputPin, NULL); + if (FAILED(hr)) { + ERR("Failed to set IGrabCallback interface.\n"); + param->errCode = EINVAL; + return; + } + + hr = g_pMediaControl->lpVtbl->Stop(g_pMediaControl); + if (FAILED(hr)) { + ERR("Failed to stop media control.\n"); + param->errCode = EINVAL; + return; + } + + if (grab_buf) { + g_free(grab_buf); + grab_buf = NULL; + } + state->buf_size = 0; + + INFO("Stopping preview\n"); +} + +/* MARUCAM_CMD_S_PARAM */ +void marucam_device_s_param(MaruCamState *state) +{ + MaruCamParam *param = state->param; + + /* We use default FPS of the webcam */ + param->top = 0; +} + +/* MARUCAM_CMD_G_PARAM */ +void marucam_device_g_param(MaruCamState *state) +{ + MaruCamParam *param = state->param; + + /* We use default FPS of the webcam + * return a fixed value on guest ini file (1/30). + */ + param->top = 0; + param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */ + param->stack[1] = 1; /* numerator */ + param->stack[2] = 30; /* denominator */ +} + +/* MARUCAM_CMD_S_FMT */ +void marucam_device_s_fmt(MaruCamState *state) +{ + uint32_t width, height, pixfmt, pidx, fidx; + MaruCamParam *param = state->param; + + param->top = 0; + width = param->stack[0]; + height = param->stack[1]; + pixfmt = param->stack[2]; + + for (fidx = 0; fidx < ARRAY_SIZE(supported_dst_frames); fidx++) { + if ((supported_dst_frames[fidx].width == width) && + (supported_dst_frames[fidx].height == height)) { + break; + } + } + if (fidx == ARRAY_SIZE(supported_dst_frames)) { + param->errCode = EINVAL; + return; + } + for (pidx = 0; pidx < ARRAY_SIZE(supported_dst_pixfmts); pidx++) { + if (supported_dst_pixfmts[pidx].fmt == pixfmt) { + break; + } + } + if (pidx == ARRAY_SIZE(supported_dst_pixfmts)) { + param->errCode = EINVAL; + return; + } + + if ((supported_dst_frames[cur_frame_idx].width != width) && + (supported_dst_frames[cur_frame_idx].height != height)) { + HRESULT hr = SetFormat(width, height, pixfmt, &g_dwSrcFmt); + if (FAILED(hr)) { + param->errCode = EINVAL; + return; + } + } + + cur_frame_idx = fidx; + cur_fmt_idx = pidx; + + pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; + width = supported_dst_frames[cur_frame_idx].width; + height = supported_dst_frames[cur_frame_idx].height; + + param->stack[0] = width; + param->stack[1] = height; + param->stack[2] = 1; /* V4L2_FIELD_NONE */ + param->stack[3] = pixfmt; + param->stack[4] = get_bytesperline(pixfmt, width); + param->stack[5] = get_sizeimage(pixfmt, width, height); + param->stack[6] = 0; + param->stack[7] = 0; + + TRACE("Set format...\n"); +} + +/* MARUCAM_CMD_G_FMT */ +void marucam_device_g_fmt(MaruCamState *state) +{ + uint32_t width, height, pixfmt; + MaruCamParam *param = state->param; + + param->top = 0; + pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; + width = supported_dst_frames[cur_frame_idx].width; + height = supported_dst_frames[cur_frame_idx].height; + + param->stack[0] = width; + param->stack[1] = height; + param->stack[2] = 1; /* V4L2_FIELD_NONE */ + param->stack[3] = pixfmt; + param->stack[4] = get_bytesperline(pixfmt, width); + param->stack[5] = get_sizeimage(pixfmt, width, height); + param->stack[6] = 0; + param->stack[7] = 0; + + TRACE("Get format...\n"); +} + +void marucam_device_try_fmt(MaruCamState *state) +{ + uint32_t width, height, pixfmt, i; + MaruCamParam *param = state->param; + + param->top = 0; + width = param->stack[0]; + height = param->stack[1]; + pixfmt = param->stack[2]; + + for (i = 0; i < ARRAY_SIZE(supported_dst_frames); i++) { + if ((supported_dst_frames[i].width == width) && + (supported_dst_frames[i].height == height)) { + break; + } + } + if (i == ARRAY_SIZE(supported_dst_frames)) { + param->errCode = EINVAL; + return; + } + for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) { + if (supported_dst_pixfmts[i].fmt == pixfmt) { + break; + } + } + if (i == ARRAY_SIZE(supported_dst_pixfmts)) { + param->errCode = EINVAL; + return; + } + + param->stack[0] = width; + param->stack[1] = height; + param->stack[2] = 1; /* V4L2_FIELD_NONE */ + param->stack[3] = pixfmt; + param->stack[4] = get_bytesperline(pixfmt, width); + param->stack[5] = get_sizeimage(pixfmt, width, height); + param->stack[6] = 0; + param->stack[7] = 0; +} + +void marucam_device_enum_fmt(MaruCamState *state) +{ + uint32_t index; + MaruCamParam *param = state->param; + + param->top = 0; + index = param->stack[0]; + + if (index >= ARRAY_SIZE(supported_dst_pixfmts)) { + param->errCode = EINVAL; + return; + } + param->stack[1] = 0; /* flags = NONE */ + param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */ + /* set description */ + switch (supported_dst_pixfmts[index].fmt) { + case V4L2_PIX_FMT_YUYV: + memcpy(¶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 */ +} diff --git a/tizen/src/hw/pci/maru_camera_win32.h b/tizen/src/hw/pci/maru_camera_win32.h new file mode 100644 index 0000000000..f1dcd8b212 --- /dev/null +++ b/tizen/src/hw/pci/maru_camera_win32.h @@ -0,0 +1,932 @@ +/* + * Interface definition header for Windows host. + * + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jinhyung Jo + * Sangho Park + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef _MARU_CAMERA_WIN32_H_ +#define _MARU_CAMERA_WIN32_H_ + +static const WCHAR HWCPinName[] = L"HWCInputPin\0"; +static const WCHAR HWCFilterName[] = L"HWCFilter\0"; + +/* Forward Declarations */ +FWD_DECL(IBaseFilter); +FWD_DECL(IFilterGraph); + +/* defines */ +#define MAX_PIN_NAME 128 +#define MAX_FILTER_NAME 128 + +#define DECLARE_INTERFACE2(i) \ + _COM_interface i { CONST_VTABLE struct i##Vtbl *lpVtbl; }; \ + typedef CONST_VTABLE struct i##Vtbl i##Vtbl; \ + CONST_VTABLE struct i##Vtbl +#define DECLARE_INTERFACE2_(i, b) DECLARE_INTERFACE2(i) + +typedef LONGLONG REFERENCE_TIME; +typedef long OAFilterState; +typedef DWORD_PTR HSEMAPHORE; +typedef DWORD_PTR HEVENT; + +typedef enum _FilterState { + State_Stopped, + State_Paused, + State_Running +} FILTER_STATE; + +typedef struct _FilterInfo { + WCHAR achName[MAX_FILTER_NAME]; + IFilterGraph *pGraph; +} FILTER_INFO; + +typedef enum _PinDirection { + PINDIR_INPUT = 0, + PINDIR_OUTPUT = (PINDIR_INPUT + 1) +} PIN_DIRECTION; + +typedef struct _PinInfo { + IBaseFilter *pFilter; + PIN_DIRECTION dir; + WCHAR achName[MAX_PIN_NAME]; +} PIN_INFO; + +typedef struct _AllocatorProperties { + long cBuffers; + long cbBuffer; + long cbAlign; + long cbPrefix; +} ALLOCATOR_PROPERTIES; + +typedef struct _AMMediaType { + GUID majortype; + GUID subtype; + BOOL bFixedSizeSamples; + BOOL bTemporalCompression; + ULONG lSampleSize; + GUID formattype; + IUnknown *pUnk; + ULONG cbFormat; + BYTE *pbFormat; +} AM_MEDIA_TYPE; + +typedef enum tagVideoProcAmpFlags { + VideoProcAmp_Flags_Auto = 0x0001, + VideoProcAmp_Flags_Manual = 0x0002 +} VideoProcAmpFlags; + +typedef enum tagVideoProcAmpProperty { + VideoProcAmp_Brightness, + VideoProcAmp_Contrast, + VideoProcAmp_Hue, + VideoProcAmp_Saturation, + VideoProcAmp_Sharpness, + VideoProcAmp_Gamma, + VideoProcAmp_ColorEnable, + VideoProcAmp_WhiteBalance, + VideoProcAmp_BacklightCompensation, + VideoProcAmp_Gain +} VideoProcAmpProperty; + +typedef struct tagVIDEOINFOHEADER { + RECT rcSource; + RECT rcTarget; + DWORD dwBitRate; + DWORD dwBitErrorRate; + REFERENCE_TIME AvgTimePerFrame; + BITMAPINFOHEADER bmiHeader; +} VIDEOINFOHEADER; + +typedef struct _VIDEO_STREAM_CONFIG_CAPS { + GUID guid; + ULONG VideoStandard; + SIZE InputSize; + SIZE MinCroppingSize; + SIZE MaxCroppingSize; + int CropGranularityX; + int CropGranularityY; + int CropAlignX; + int CropAlignY; + SIZE MinOutputSize; + SIZE MaxOutputSize; + int OutputGranularityX; + int OutputGranularityY; + int StretchTapsX; + int StretchTapsY; + int ShrinkTapsX; + int ShrinkTapsY; + LONGLONG MinFrameInterval; + LONGLONG MaxFrameInterval; + LONG MinBitsPerSecond; + LONG MaxBitsPerSecond; +} VIDEO_STREAM_CONFIG_CAPS; + + +/* Interface & Class GUIDs */ +static const IID IID_IGrabCallback = {0x4C337035,0xC89E,0x4B42,{0x9B,0x0C,0x36,0x74,0x44,0xDD,0x70,0xDD}}; + +EXTERN_C const IID IID_IBaseFilter; +EXTERN_C const IID IID_ICreateDevEnum; +EXTERN_C const IID IID_IGraphBuilder; +EXTERN_C const IID IID_IMediaSeeking; +EXTERN_C const IID IID_IMediaEventSink; +EXTERN_C const IID IID_IMemInputPin; +EXTERN_C const IID IID_IEnumPins; +EXTERN_C const IID IID_IMediaFilter; +EXTERN_C const IID IID_IEnumMediaTypes; +EXTERN_C const IID IID_IMemAllocator; +EXTERN_C const IID IID_IPin; +EXTERN_C const IID IID_ICaptureGraphBuilder2; +EXTERN_C const IID IID_IFileSinkFilter; +EXTERN_C const IID IID_IAMCopyCaptureFileProgress; +EXTERN_C const IID IID_IEnumFilters; +EXTERN_C const IID IID_IMediaSample; +EXTERN_C const IID IID_IMediaControl; +EXTERN_C const IID IID_IAMStreamConfig; +EXTERN_C const IID IID_IAMVideoProcAmp; + +EXTERN_C const IID CLSID_CaptureGraphBuilder2; +EXTERN_C const IID CLSID_VideoInputDeviceCategory; +EXTERN_C const IID CLSID_AudioRender; +EXTERN_C const IID CLSID_SystemDeviceEnum; +EXTERN_C const IID CLSID_AudioRendererCategory; +EXTERN_C const IID CLSID_FilterGraph; +EXTERN_C const IID CLSID_InfTee; +EXTERN_C const IID CLSID_VideoMixingRenderer9; +EXTERN_C const IID CLSID_MemoryAllocator; + + +/* other types GUIDs*/ +EXTERN_C const IID MEDIATYPE_Audio; +EXTERN_C const IID MEDIATYPE_Video; +EXTERN_C const IID MEDIATYPE_Stream; +EXTERN_C const IID MEDIASUBTYPE_PCM; +EXTERN_C const IID MEDIASUBTYPE_WAVE; +EXTERN_C const IID MEDIASUBTYPE_Avi; +EXTERN_C const IID MEDIASUBTYPE_RGB32; +EXTERN_C const IID MEDIASUBTYPE_YV12; +EXTERN_C const IID MEDIASUBTYPE_YUY2; +EXTERN_C const IID MEDIASUBTYPE_I420; +EXTERN_C const IID MEDIASUBTYPE_YUYV; +EXTERN_C const IID FORMAT_WaveFormatEx; +EXTERN_C const IID FORMAT_VideoInfo; +EXTERN_C const IID FORMAT_VideoInfo2; +EXTERN_C const IID PIN_CATEGORY_CAPTURE; +EXTERN_C const IID PIN_CATEGORY_PREVIEW; + + +#define MEDIATYPE_NULL GUID_NULL +#define MEDIASUBTYPE_NULL GUID_NULL + +#define INTERFACE IGrabCallback +DECLARE_INTERFACE_(IGrabCallback, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(Grab)(THIS_ ULONG,BYTE*) PURE; +}; +#undef INTERFACE + +#ifdef COBJMACROS +#define IGrabCallback_QueryInterface(T,a,b) (T)->lpVtbl->QueryInterface(T,a,b) +#define IGrabCallback_AddRef(T) (T)->lpVtbl->AddRef(T) +#define IGrabCallback_Release(T) (T)->lpVtbl->Release(T) +#define IGrabCallback_Grab(T,a,b) (T)->lpVtbl->Grab(T,a,b) +#endif /* COBJMACROS */ + +#define INTERFACE IAMCopyCaptureFileProgress +DECLARE_INTERFACE_(IAMCopyCaptureFileProgress, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(Progress)(THIS_ int) PURE; +}; +#undef INTERFACE +#define INTERFACE IReferenceClock +DECLARE_INTERFACE_(IReferenceClock, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *) PURE; + STDMETHOD(AdviseTime)(THIS_ REFERENCE_TIME, REFERENCE_TIME, HEVENT, DWORD_PTR *) PURE; + STDMETHOD(AdvisePeriodic)(THIS_ REFERENCE_TIME, REFERENCE_TIME, HSEMAPHORE, DWORD_PTR *) PURE; + STDMETHOD(Unadvise)(THIS_ DWORD_PTR) PURE; +}; +#undef INTERFACE +#define INTERFACE IEnumFilters +DECLARE_INTERFACE_(IEnumFilters, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(Next)(THIS_ ULONG, IBaseFilter **, ULONG *) PURE; + STDMETHOD(Skip)(THIS_ ULONG) PURE; + STDMETHOD(Reset)(THIS) PURE; + STDMETHOD(Clone)(THIS_ IEnumFilters **) PURE; +}; +#undef INTERFACE +#define INTERFACE IEnumMediaTypes +DECLARE_INTERFACE_(IEnumMediaTypes, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(Next)(THIS_ ULONG, AM_MEDIA_TYPE **, ULONG *) PURE; + STDMETHOD(Skip)(THIS_ ULONG) PURE; + STDMETHOD(Reset)(THIS) PURE; + STDMETHOD(Clone)(THIS_ IEnumMediaTypes **) PURE; +}; +#undef INTERFACE +#define INTERFACE IPin +DECLARE_INTERFACE_(IPin, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(Connect)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE; + STDMETHOD(ReceiveConnection)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE; + STDMETHOD(Disconnect)(THIS) PURE; + STDMETHOD(ConnectedTo)(THIS_ IPin **) PURE; + STDMETHOD(ConnectionMediaType)(THIS_ AM_MEDIA_TYPE *) PURE; + STDMETHOD(QueryPinInfo)(THIS_ PIN_INFO *) PURE; + STDMETHOD(QueryDirection)(THIS_ PIN_DIRECTION *) PURE; + STDMETHOD(QueryId)(THIS_ LPWSTR *) PURE; + STDMETHOD(QueryAccept)(THIS_ const AM_MEDIA_TYPE *) PURE; + STDMETHOD(EnumMediaTypes)(THIS_ IEnumMediaTypes **) PURE; + STDMETHOD(QueryInternalConnections)(THIS_ IPin **, ULONG *) PURE; + STDMETHOD(EndOfStream)(THIS) PURE; + STDMETHOD(BeginFlush)(THIS) PURE; + STDMETHOD(EndFlush)(THIS) PURE; + STDMETHOD(NewSegment)(THIS_ REFERENCE_TIME, REFERENCE_TIME, double) PURE; +}; +#undef INTERFACE +#define INTERFACE IEnumPins +DECLARE_INTERFACE_(IEnumPins, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(Next)(THIS_ ULONG, IPin **, ULONG *) PURE; + STDMETHOD(Skip)(THIS_ ULONG) PURE; + STDMETHOD(Reset)(THIS) PURE; + STDMETHOD(Clone)(THIS_ IEnumPins **) PURE; +}; +#undef INTERFACE +#define INTERFACE IMediaFilter +DECLARE_INTERFACE_(IMediaFilter, IPersist) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(GetClassID)(THIS_ CLSID*) PURE; + STDMETHOD(Stop)(THIS) PURE; + STDMETHOD(Pause)(THIS) PURE; + STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE; + STDMETHOD(GetState)(THIS_ DWORD, FILTER_STATE *) PURE; + STDMETHOD(SetSyncSource)(THIS_ IReferenceClock *) PURE; + STDMETHOD(GetSyncSource)(THIS_ IReferenceClock **) PURE; +}; +#undef INTERFACE +#define INTERFACE IBaseFilter +DECLARE_INTERFACE2_(IBaseFilter, IMediaFilter) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(GetClassID)(THIS_ CLSID*) PURE; + STDMETHOD(Stop)(THIS) PURE; + STDMETHOD(Pause)(THIS) PURE; + STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE; + STDMETHOD(GetState)(THIS_ DWORD, FILTER_STATE *) PURE; + STDMETHOD(SetSyncSource)(THIS_ IReferenceClock *) PURE; + STDMETHOD(GetSyncSource)(THIS_ IReferenceClock **) PURE; + STDMETHOD(EnumPins)(THIS_ IEnumPins **) PURE; + STDMETHOD(FindPin)(THIS_ LPCWSTR, IPin **) PURE; + STDMETHOD(QueryFilterInfo)(THIS_ FILTER_INFO *) PURE; + STDMETHOD(JoinFilterGraph)(THIS_ IFilterGraph *, LPCWSTR) PURE; + STDMETHOD(QueryVendorInfo)(THIS_ LPWSTR *) PURE; +}; +#undef INTERFACE +#define INTERFACE IFilterGraph +DECLARE_INTERFACE2_(IFilterGraph, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(AddFilter)(THIS_ IBaseFilter *, LPCWSTR) PURE; + STDMETHOD(RemoveFilter)(THIS_ IBaseFilter *) PURE; + STDMETHOD(EnumFilters)(THIS_ IEnumFilters **) PURE; + STDMETHOD(FindFilterByName)(THIS_ LPCWSTR, IBaseFilter **) PURE; + STDMETHOD(ConnectDirect)(THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *) PURE; + STDMETHOD(Reconnect)(THIS_ IPin *) PURE; + STDMETHOD(Disconnect)(THIS_ IPin *) PURE; + STDMETHOD(SetDefaultSyncSource)(THIS) PURE; +}; +#undef INTERFACE +#define INTERFACE IGraphBuilder +DECLARE_INTERFACE_(IGraphBuilder ,IFilterGraph) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(AddFilter)(THIS_ IBaseFilter *, LPCWSTR) PURE; + STDMETHOD(RemoveFilter)(THIS_ IBaseFilter *) PURE; + STDMETHOD(EnumFilters)(THIS_ IEnumFilters **) PURE; + STDMETHOD(FindFilterByName)(THIS_ LPCWSTR, IBaseFilter **) PURE; + STDMETHOD(ConnectDirect)(THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *) PURE; + STDMETHOD(Reconnect)(THIS_ IPin *) PURE; + STDMETHOD(Disconnect)(THIS_ IPin *) PURE; + STDMETHOD(SetDefaultSyncSource)(THIS) PURE; + STDMETHOD(Connect)(THIS_ IPin *, IPin *) PURE; + STDMETHOD(Render)(THIS_ IPin *) PURE; + STDMETHOD(RenderFile)(THIS_ LPCWSTR, LPCWSTR) PURE; + STDMETHOD(AddSourceFilter)(THIS_ LPCWSTR, LPCWSTR, IBaseFilter **) PURE; + STDMETHOD(SetLogFile)(THIS_ DWORD_PTR) PURE; + STDMETHOD(Abort)(THIS) PURE; + STDMETHOD(ShouldOperationContinue)(THIS) PURE; +}; +#undef INTERFACE +#define INTERFACE ICreateDevEnum +DECLARE_INTERFACE_(ICreateDevEnum, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(CreateClassEnumerator)(THIS_ REFCLSID, IEnumMoniker **, DWORD) PURE; +}; +#undef INTERFACE +#define INTERFACE IMediaSample +DECLARE_INTERFACE_(IMediaSample, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(GetPointer)(THIS_ BYTE **) PURE; + STDMETHOD_(long, GetSize)(THIS) PURE; + STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE; + STDMETHOD(SetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE; + STDMETHOD(IsSyncPoint)(THIS) PURE; + STDMETHOD(SetSyncPoint)(THIS_ BOOL) PURE; + STDMETHOD(IsPreroll)(THIS) PURE; + STDMETHOD(SetPreroll)(THIS_ BOOL) PURE; + STDMETHOD_(long, GetActualDataLength)(THIS) PURE; + STDMETHOD(SetActualDataLength)(THIS_ long) PURE; + STDMETHOD(GetMediaType)(THIS_ AM_MEDIA_TYPE **) PURE; + STDMETHOD(SetMediaType)(THIS_ AM_MEDIA_TYPE *) PURE; + STDMETHOD(IsDiscontinuity)(THIS) PURE; + STDMETHOD(SetDiscontinuity)(THIS_ BOOL) PURE; + STDMETHOD(GetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE; + STDMETHOD(SetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE; +}; +#undef INTERFACE +#define INTERFACE IMemAllocator +DECLARE_INTERFACE_(IMemAllocator, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(SetProperties)(THIS_ ALLOCATOR_PROPERTIES *, ALLOCATOR_PROPERTIES *) PURE; + STDMETHOD(GetProperties)(THIS_ ALLOCATOR_PROPERTIES *) PURE; + STDMETHOD(Commit)(THIS) PURE; + STDMETHOD(Decommit)(THIS) PURE; + STDMETHOD(GetBuffer)(THIS_ IMediaSample **, REFERENCE_TIME *, REFERENCE_TIME *, DWORD) PURE; + STDMETHOD(ReleaseBuffer)(THIS_ IMediaSample *) PURE; + +}; +#undef INTERFACE +#define INTERFACE IMemInputPin +DECLARE_INTERFACE_(IMemInputPin, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(GetAllocator)(THIS_ IMemAllocator **) PURE; + STDMETHOD(NotifyAllocator)(THIS_ IMemAllocator *, BOOL) PURE; + STDMETHOD(GetAllocatorRequirements)(THIS_ ALLOCATOR_PROPERTIES *) PURE; + STDMETHOD(Receive)(THIS_ IMediaSample *) PURE; + STDMETHOD(ReceiveMultiple)(THIS_ IMediaSample **, long, long *) PURE; + STDMETHOD(ReceiveCanBlock)(THIS) PURE; +}; +#undef INTERFACE +#define INTERFACE IFileSinkFilter +DECLARE_INTERFACE_(IFileSinkFilter, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(SetFileName)(THIS_ LPCOLESTR,const AM_MEDIA_TYPE *) PURE; + STDMETHOD(GetCurFile)(THIS_ LPOLESTR *,AM_MEDIA_TYPE*) PURE; +}; +#undef INTERFACE +#define INTERFACE ICaptureGraphBuilder2 +DECLARE_INTERFACE_(ICaptureGraphBuilder2, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(SetFiltergraph)(THIS_ IGraphBuilder*) PURE; + STDMETHOD(GetFiltergraph)(THIS_ IGraphBuilder**) PURE; + STDMETHOD(SetOutputFileName)(THIS_ const GUID*,LPCOLESTR,IBaseFilter**,IFileSinkFilter**) PURE; + STDMETHOD(FindInterface)(THIS_ const GUID*,const GUID*,IBaseFilter*,REFIID,void**) PURE; + STDMETHOD(RenderStream)(THIS_ const GUID*,const GUID*,IUnknown*,IBaseFilter*,IBaseFilter*) PURE; + STDMETHOD(ControlStream)(THIS_ const GUID*,const GUID*,IBaseFilter*,REFERENCE_TIME*,REFERENCE_TIME*,WORD,WORD) PURE; + STDMETHOD(AllocCapFile)(THIS_ LPCOLESTR,DWORDLONG) PURE; + STDMETHOD(CopyCaptureFile)(THIS_ LPOLESTR,LPOLESTR,int,IAMCopyCaptureFileProgress*) PURE; + STDMETHOD(FindPin)(THIS_ IUnknown*,PIN_DIRECTION,const GUID*,const GUID*,BOOL,int,IPin**) PURE; +}; +#undef INTERFACE +#define INTERFACE IAMStreamConfig +DECLARE_INTERFACE_(IAMStreamConfig, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(SetFormat)(THIS_ AM_MEDIA_TYPE*) PURE; + STDMETHOD(GetFormat)(THIS_ AM_MEDIA_TYPE**) PURE; + STDMETHOD(GetNumberOfCapabilities)(THIS_ int*,int*) PURE; + STDMETHOD(GetStreamCaps)(THIS_ int,AM_MEDIA_TYPE**,BYTE*) PURE; +}; +#undef INTERFACE +#define INTERFACE IAMVideoProcAmp +DECLARE_INTERFACE_(IAMVideoProcAmp, IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(GetRange)(THIS_ long,long*,long*,long*,long*,long*) PURE; + STDMETHOD(Set)(THIS_ long,long,long) PURE; + STDMETHOD(Get)(THIS_ long,long*,long*) PURE; +}; +#undef INTERFACE +#define INTERFACE IMediaControl +DECLARE_INTERFACE_(IMediaControl, IDispatch) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + STDMETHOD(GetTypeInfoCount)(THIS_ UINT*); + STDMETHOD(GetTypeInfo)(THIS_ UINT,LCID,ITypeInfo**); + STDMETHOD(GetIDsOfNames)(THIS_ REFIID,LPOLESTR*,UINT,LCID,DISPID*); + STDMETHOD(Invoke)(THIS_ DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*); + STDMETHOD(Run)(THIS); + STDMETHOD(Pause)(THIS); + STDMETHOD(Stop)(THIS); + STDMETHOD(GetState)(THIS_ LONG, OAFilterState*); + STDMETHOD(RenderFile)(THIS_ BSTR); + STDMETHOD(AddSourceFilter)(THIS_ BSTR,IDispatch**); + STDMETHOD(get_FilterCollection)(THIS_ IDispatch**); + STDMETHOD(get_RegFilterCollection)(THIS_ IDispatch**); + STDMETHOD(StopWhenReady)(THIS); +}; +#undef INTERFACE + +#ifdef COBJMACROS +#define ICreateDevEnum_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define ICreateDevEnum_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define ICreateDevEnum_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define ICreateDevEnum_CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags) \ + ((This)->lpVtbl->CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IPin_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IPin_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IPin_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IPin_Connect(This,pReceivePin,pmt) \ + ((This)->lpVtbl->Connect(This,pReceivePin,pmt)) +#define IPin_ReceiveConnection(This,pConnector,pmt) \ + ((This)->lpVtbl->ReceiveConnection(This,pConnector,pmt)) +#define IPin_Disconnect(This) \ + ((This)->lpVtbl->Disconnect(This)) +#define IPin_ConnectedTo(This,pPin) \ + ((This)->lpVtbl->ConnectedTo(This,pPin)) +#define IPin_ConnectionMediaType(This,pmt) \ + ((This)->lpVtbl->ConnectionMediaType(This,pmt)) +#define IPin_QueryPinInfo(This,pInfo) \ + ((This)->lpVtbl->QueryPinInfo(This,pInfo)) +#define IPin_QueryDirection(This,pPinDir) \ + ((This)->lpVtbl->QueryDirection(This,pPinDir)) +#define IPin_QueryId(This,Id) \ + ((This)->lpVtbl->QueryId(This,Id)) +#define IPin_QueryAccept(This,pmt) \ + ((This)->lpVtbl->QueryAccept(This,pmt)) +#define IPin_EnumMediaTypes(This,ppEnum) \ + ((This)->lpVtbl->EnumMediaTypes(This,ppEnum)) +#define IPin_QueryInternalConnections(This,apPin,nPin) \ + ((This)->lpVtbl->QueryInternalConnections(This,apPin,nPin)) +#define IPin_EndOfStream(This) \ + ((This)->lpVtbl->EndOfStream(This)) +#define IPin_BeginFlush(This) \ + ((This)->lpVtbl->BeginFlush(This)) +#define IPin_EndFlush(This) \ + ((This)->lpVtbl->EndFlush(This)) +#define IPin_NewSegment(This,tStart,tStop,dRate) \ + ((This)->lpVtbl->NewSegment(This,tStart,tStop,dRate)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IEnumPins_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IEnumPins_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IEnumPins_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IEnumPins_Next(This,cPins,ppPins,pcFetched) \ + ((This)->lpVtbl->Next(This,cPins,ppPins,pcFetched)) +#define IEnumPins_Skip(This,cPins) \ + ((This)->lpVtbl->Skip(This,cPins)) +#define IEnumPins_Reset(This) \ + ((This)->lpVtbl->Reset(This)) +#define IEnumPins_Clone(This,ppEnum) \ + ((This)->lpVtbl->Clone(This,ppEnum)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IAMStreamConfig_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IAMStreamConfig_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IAMStreamConfig_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IAMStreamConfig_SetFormat(This,pmt) \ + ((This)->lpVtbl->SetFormat(This,pmt)) +#define IAMStreamConfig_GetFormat(This,ppmt) \ + ((This)->lpVtbl->GetFormat(This,ppmt)) +#define IAMStreamConfig_GetNumberOfCapabilities(This,piCount,piSize) \ + ((This)->lpVtbl->GetNumberOfCapabilities(This,piCount,piSize)) +#define IAMStreamConfig_GetStreamCaps(This,iIndex,ppmt,pSCC) \ + ((This)->lpVtbl->GetStreamCaps(This,iIndex,ppmt,pSCC)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IFilterGraph_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IFilterGraph_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IFilterGraph_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IFilterGraph_AddFilter(This,pFilter,pName) \ + ((This)->lpVtbl->AddFilter(This,pFilter,pName)) +#define IFilterGraph_RemoveFilter(This,pFilter) \ + ((This)->lpVtbl->RemoveFilter(This,pFilter)) +#define IFilterGraph_EnumFilters(This,ppEnum) \ + ((This)->lpVtbl->EnumFilters(This,ppEnum)) +#define IFilterGraph_FindFilterByName(This,pName,ppFilter) \ + ((This)->lpVtbl->FindFilterByName(This,pName,ppFilter)) +#define IFilterGraph_ConnectDirect(This,ppinOut,ppinIn,pmt) \ + ((This)->lpVtbl->ConnectDirect(This,ppinOut,ppinIn,pmt)) +#define IFilterGraph_Reconnect(This,ppin) \ + ((This)->lpVtbl->Reconnect(This,ppin)) +#define IFilterGraph_Disconnect(This,ppin) \ + ((This)->lpVtbl->Disconnect(This,ppin)) +#define IFilterGraph_SetDefaultSyncSource(This) \ + ((This)->lpVtbl->SetDefaultSyncSource(This)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IMediaFilter_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IMediaFilter_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IMediaFilter_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IMediaFilter_GetClassID(This,pClassID) \ + ((This)->lpVtbl->GetClassID(This,pClassID)) +#define IMediaFilter_Stop(This) \ + ((This)->lpVtbl->Stop(This)) +#define IMediaFilter_Pause(This) \ + ((This)->lpVtbl->Pause(This)) +#define IMediaFilter_Run(This,tStart) \ + ((This)->lpVtbl->Run(This,tStart)) +#define IMediaFilter_GetState(This,dwMilliSecsTimeout,State) \ + ((This)->lpVtbl->GetState(This,dwMilliSecsTimeout,State)) +#define IMediaFilter_SetSyncSource(This,pClock) \ + ((This)->lpVtbl->SetSyncSource(This,pClock)) +#define IMediaFilter_GetSyncSource(This,pClock) \ + ((This)->lpVtbl->GetSyncSource(This,pClock)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IBaseFilter_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IBaseFilter_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IBaseFilter_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IBaseFilter_GetClassID(This,pClassID) \ + ((This)->lpVtbl->GetClassID(This,pClassID)) +#define IBaseFilter_Stop(This) \ + ((This)->lpVtbl->Stop(This)) +#define IBaseFilter_Pause(This) \ + ((This)->lpVtbl->Pause(This)) +#define IBaseFilter_Run(This,tStart) \ + ((This)->lpVtbl->Run(This,tStart)) +#define IBaseFilter_GetState(This,dwMilliSecsTimeout,State) \ + ((This)->lpVtbl->GetState(This,dwMilliSecsTimeout,State)) +#define IBaseFilter_SetSyncSource(This,pClock) \ + ((This)->lpVtbl->SetSyncSource(This,pClock)) +#define IBaseFilter_GetSyncSource(This,pClock) \ + ((This)->lpVtbl->GetSyncSource(This,pClock)) +#define IBaseFilter_EnumPins(This,ppEnum) \ + ((This)->lpVtbl->EnumPins(This,ppEnum)) +#define IBaseFilter_FindPin(This,Id,ppPin) \ + ((This)->lpVtbl->FindPin(This,Id,ppPin)) +#define IBaseFilter_QueryFilterInfo(This,pInfo) \ + ((This)->lpVtbl->QueryFilterInfo(This,pInfo)) +#define IBaseFilter_JoinFilterGraph(This,pGraph,pName) \ + ((This)->lpVtbl->JoinFilterGraph(This,pGraph,pName)) +#define IBaseFilter_QueryVendorInfo(This,pVendorInfo) \ + ((This)->lpVtbl->QueryVendorInfo(This,pVendorInfo)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IMediaSample_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IMediaSample_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IMediaSample_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IMediaSample_GetPointer(This,ppBuffer) \ + ((This)->lpVtbl->GetPointer(This,ppBuffer)) +#define IMediaSample_GetSize(This) \ + ((This)->lpVtbl->GetSize(This)) +#define IMediaSample_GetTime(This,pTimeStart,pTimeEnd) \ + ((This)->lpVtbl->GetTime(This,pTimeStart,pTimeEnd)) +#define IMediaSample_SetTime(This,pTimeStart,pTimeEnd) \ + ((This)->lpVtbl->SetTime(This,pTimeStart,pTimeEnd)) +#define IMediaSample_IsSyncPoint(This) \ + ((This)->lpVtbl->IsSyncPoint(This)) +#define IMediaSample_SetSyncPoint(This,bIsSyncPoint) \ + ((This)->lpVtbl->SetSyncPoint(This,bIsSyncPoint)) +#define IMediaSample_IsPreroll(This) \ + ((This)->lpVtbl->IsPreroll(This)) +#define IMediaSample_SetPreroll(This,bIsPreroll) \ + ((This)->lpVtbl->SetPreroll(This,bIsPreroll)) +#define IMediaSample_GetActualDataLength(This) \ + ((This)->lpVtbl->GetActualDataLength(This)) +#define IMediaSample_SetActualDataLength(This,length) \ + ((This)->lpVtbl->SetActualDataLength(This,length)) +#define IMediaSample_GetMediaType(This,ppMediaType) \ + ((This)->lpVtbl->GetMediaType(This,ppMediaType)) +#define IMediaSample_SetMediaType(This,pMediaType) \ + ((This)->lpVtbl->SetMediaType(This,pMediaType)) +#define IMediaSample_IsDiscontinuity(This) \ + ((This)->lpVtbl->IsDiscontinuity(This)) +#define IMediaSample_SetDiscontinuity(This,bDiscontinuity) \ + ((This)->lpVtbl->SetDiscontinuity(This,bDiscontinuity)) +#define IMediaSample_GetMediaTime(This,pTimeStart,pTimeEnd) \ + ((This)->lpVtbl->GetMediaTime(This,pTimeStart,pTimeEnd)) +#define IMediaSample_SetMediaTime(This,pTimeStart,pTimeEnd) \ + ((This)->lpVtbl->SetMediaTime(This,pTimeStart,pTimeEnd)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IEnumFilters_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IEnumFilters_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IEnumFilters_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IEnumFilters_Next(This,cFilters,ppFilter,pcFetched) \ + ((This)->lpVtbl->Next(This,cFilters,ppFilter,pcFetched)) +#define IEnumFilters_Skip(This,cFilters) \ + ((This)->lpVtbl->Skip(This,cFilters)) +#define IEnumFilters_Reset(This) \ + ((This)->lpVtbl->Reset(This)) +#define IEnumFilters_Clone(This,ppEnum) \ + ((This)->lpVtbl->Clone(This,ppEnum)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IMemAllocator_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IMemAllocator_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IMemAllocator_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IMemAllocator_SetProperties(This,pRequest,pActual) \ + ((This)->lpVtbl->SetProperties(This,pRequest,pActual)) +#define IMemAllocator_GetProperties(This,pProps) \ + ((This)->lpVtbl->GetProperties(This,pProps)) +#define IMemAllocator_Commit(This) \ + ((This)->lpVtbl->Commit(This)) +#define IMemAllocator_Decommit(This) \ + ((This)->lpVtbl->Decommit(This)) +#define IMemAllocator_GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags) \ + ((This)->lpVtbl->GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags)) +#define IMemAllocator_ReleaseBuffer(This,pBuffer) \ + ((This)->lpVtbl->ReleaseBuffer(This,pBuffer)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IMemInputPin_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IMemInputPin_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IMemInputPin_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IMemInputPin_GetAllocator(This,ppAllocator) \ + ((This)->lpVtbl->GetAllocator(This,ppAllocator)) +#define IMemInputPin_NotifyAllocator(This,pAllocator,bReadOnly) \ + ((This)->lpVtbl->NotifyAllocator(This,pAllocator,bReadOnly)) +#define IMemInputPin_GetAllocatorRequirements(This,pProps) \ + ((This)->lpVtbl->GetAllocatorRequirements(This,pProps)) +#define IMemInputPin_Receive(This,pSample) \ + ((This)->lpVtbl->Receive(This,pSample)) +#define IMemInputPin_ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed) \ + ((This)->lpVtbl->ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed)) +#define IMemInputPin_ReceiveCanBlock(This) \ + ((This)->lpVtbl->ReceiveCanBlock(This)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IGraphBuilder_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IGraphBuilder_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IGraphBuilder_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IGraphBuilder_AddFilter(This,pFilter,pName) \ + ((This)->lpVtbl->AddFilter(This,pFilter,pName)) +#define IGraphBuilder_RemoveFilter(This,pFilter) \ + ((This)->lpVtbl->RemoveFilter(This,pFilter)) +#define IGraphBuilder_EnumFilters(This,ppEnum) \ + ((This)->lpVtbl->EnumFilters(This,ppEnum)) +#define IGraphBuilder_FindFilterByName(This,pName,ppFilter) \ + ((This)->lpVtbl->FindFilterByName(This,pName,ppFilter)) +#define IGraphBuilder_ConnectDirect(This,ppinOut,ppinIn,pmt) \ + ((This)->lpVtbl->ConnectDirect(This,ppinOut,ppinIn,pmt)) +#define IGraphBuilder_Reconnect(This,ppin) \ + ((This)->lpVtbl->Reconnect(This,ppin)) +#define IGraphBuilder_Disconnect(This,ppin) \ + ((This)->lpVtbl->Disconnect(This,ppin)) +#define IGraphBuilder_SetDefaultSyncSource(This) \ + ((This)->lpVtbl->SetDefaultSyncSource(This)) +#define IGraphBuilder_Connect(This,ppinOut,ppinIn) \ + ((This)->lpVtbl->Connect(This,ppinOut,ppinIn)) +#define IGraphBuilder_Render(This,ppinOut) \ + ((This)->lpVtbl->Render(This,ppinOut)) +#define IGraphBuilder_RenderFile(This,lpcwstrFile,lpcwstrPlayList) \ + ((This)->lpVtbl->RenderFile(This,lpcwstrFile,lpcwstrPlayList)) +#define IGraphBuilder_AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter) \ + ((This)->lpVtbl->AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter)) +#define IGraphBuilder_SetLogFile(This,hFile) \ + ((This)->lpVtbl->SetLogFile(This,hFile)) +#define IGraphBuilder_Abort(This) \ + ((This)->lpVtbl->Abort(This)) +#define IGraphBuilder_ShouldOperationContinue(This) \ + ((This)->lpVtbl->ShouldOperationContinue(This)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IEnumMediaTypes_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IEnumMediaTypes_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IEnumMediaTypes_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IEnumMediaTypes_Next(This,cMediaTypes,ppMediaTypes,pcFetched) \ + ((This)->lpVtbl->Next(This,cMediaTypes,ppMediaTypes,pcFetched)) +#define IEnumMediaTypes_Skip(This,cMediaTypes) \ + ((This)->lpVtbl->Skip(This,cMediaTypes)) +#define IEnumMediaTypes_Reset(This) \ + ((This)->lpVtbl->Reset(This)) +#define IEnumMediaTypes_Clone(This,ppEnum) \ + ((This)->lpVtbl->Clone(This,ppEnum)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IMediaControl_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IMediaControl_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IMediaControl_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IMediaControl_GetTypeInfoCount(This,pctinfo) \ + ((This)->lpVtbl->GetTypeInfoCount(This,pctinfo)) +#define IMediaControl_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + ((This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo)) +#define IMediaControl_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + ((This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)) +#define IMediaControl_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + ((This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)) +#define IMediaControl_Run(This) \ + ((This)->lpVtbl->Run(This)) +#define IMediaControl_Pause(This) \ + ((This)->lpVtbl->Pause(This)) +#define IMediaControl_Stop(This) \ + ((This)->lpVtbl->Stop(This)) +#define IMediaControl_GetState(This,msTimeout,pfs) \ + ((This)->lpVtbl->GetState(This,msTimeout,pfs)) +#define IMediaControl_RenderFile(This,strFilename) \ + ((This)->lpVtbl->RenderFile(This,strFilename)) +#define IMediaControl_AddSourceFilter(This,strFilename,ppUnk) \ + ((This)->lpVtbl->AddSourceFilter(This,strFilename,ppUnk)) +#define IMediaControl_get_FilterCollection(This,ppUnk) \ + ((This)->lpVtbl->get_FilterCollection(This,ppUnk)) +#define IMediaControl_get_RegFilterCollection(This,ppUnk) \ + ((This)->lpVtbl->get_RegFilterCollection(This,ppUnk)) +#define IMediaControl_StopWhenReady(This) \ + ((This)->lpVtbl->StopWhenReady(This)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IAMVideoProcAmp_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IAMVideoProcAmp_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IAMVideoProcAmp_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IAMVideoProcAmp_GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags) \ + ((This)->lpVtbl->GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags)) +#define IAMVideoProcAmp_Set(This,Property,lValue,Flags) \ + ((This)->lpVtbl->Set(This,Property,lValue,Flags)) +#define IAMVideoProcAmp_Get(This,Property,lValue,Flags) \ + ((This)->lpVtbl->Get(This,Property,lValue,Flags)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IFileSinkFilter_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IFileSinkFilter_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IFileSinkFilter_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IFileSinkFilter_SetFileName(This,pszFileName,pmt) \ + ((This)->lpVtbl->SetFileName(This,pszFileName,pmt)) +#define IFileSinkFilter_GetCurFile(This,ppszFileName,pmt) \ + ((This)->lpVtbl->GetCurFile(This,ppszFileName,pmt)) +#endif /* COBJMACROS */ + +#ifdef COBJMACROS +#define IAMCopyCaptureFileProgress_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define IAMCopyCaptureFileProgress_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define IAMCopyCaptureFileProgress_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define IAMCopyCaptureFileProgress_Progress(This,iProgress) \ + ((This)->lpVtbl->Progress(This,iProgress)) +#endif /* COBJMACROS */ + + +#ifdef COBJMACROS +#define ICaptureGraphBuilder2_QueryInterface(This,riid,ppvObject) \ + ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) +#define ICaptureGraphBuilder2_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) +#define ICaptureGraphBuilder2_Release(This) \ + ((This)->lpVtbl->Release(This)) +#define ICaptureGraphBuilder2_SetFiltergraph(This,pfg) \ + ((This)->lpVtbl->SetFiltergraph(This,pfg)) +#define ICaptureGraphBuilder2_GetFiltergraph(This,ppfg) \ + ((This)->lpVtbl->GetFiltergraph(This,ppfg)) +#define ICaptureGraphBuilder2_SetOutputFileName(This,pType,lpstrFile,ppf,ppSink) \ + ((This)->lpVtbl->SetOutputFileName(This,pType,lpstrFile,ppf,ppSink)) +#define ICaptureGraphBuilder2_FindInterface(This,pCategory,pType,pf,riid,ppint) \ + ((This)->lpVtbl->FindInterface(This,pCategory,pType,pf,riid,ppint)) +#define ICaptureGraphBuilder2_RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer) \ + ((This)->lpVtbl->RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer)) +#define ICaptureGraphBuilder2_ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie) \ + ((This)->lpVtbl->ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie)) +#define ICaptureGraphBuilder2_AllocCapFile(This,lpstr,dwlSize) \ + ((This)->lpVtbl->AllocCapFile(This,lpstr,dwlSize)) +#define ICaptureGraphBuilder2_CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback) \ + ((This)->lpVtbl->CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback)) +#define ICaptureGraphBuilder2_FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin) \ + ((This)->lpVtbl->FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin)) +#endif /* COBJMACROS */ + +#endif /* _MARU_CAMERA_WIN32_H_ */ diff --git a/tizen/src/hw/pci/maru_camera_win32_interface.h b/tizen/src/hw/pci/maru_camera_win32_interface.h deleted file mode 100644 index c38a785d99..0000000000 --- a/tizen/src/hw/pci/maru_camera_win32_interface.h +++ /dev/null @@ -1,932 +0,0 @@ -/* - * Interface definition header for Windows host. - * - * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: - * JinHyung Jo - * YeongKyoon Lee - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - * Contributors: - * - S-Core Co., Ltd - * - */ - -#ifndef _MARU_CAMERA_INTERFACE_H_ -#define _MARU_CAMERA_INTERFACE_H_ - -static const WCHAR HWCPinName[] = L"HWCInputPin\0"; -static const WCHAR HWCFilterName[] = L"HWCFilter\0"; - -/* Forward Declarations */ -FWD_DECL(IBaseFilter); -FWD_DECL(IFilterGraph); - -/* defines */ -#define MAX_PIN_NAME 128 -#define MAX_FILTER_NAME 128 - -#define DECLARE_INTERFACE2(i) \ - _COM_interface i { CONST_VTABLE struct i##Vtbl *lpVtbl; }; \ - typedef CONST_VTABLE struct i##Vtbl i##Vtbl; \ - CONST_VTABLE struct i##Vtbl -#define DECLARE_INTERFACE2_(i, b) DECLARE_INTERFACE2(i) - -typedef LONGLONG REFERENCE_TIME; -typedef long OAFilterState; -typedef DWORD_PTR HSEMAPHORE; -typedef DWORD_PTR HEVENT; - -typedef enum _FilterState { - State_Stopped, - State_Paused, - State_Running -} FILTER_STATE; - -typedef struct _FilterInfo { - WCHAR achName[MAX_FILTER_NAME]; - IFilterGraph *pGraph; -} FILTER_INFO; - -typedef enum _PinDirection { - PINDIR_INPUT = 0, - PINDIR_OUTPUT = (PINDIR_INPUT + 1) -} PIN_DIRECTION; - -typedef struct _PinInfo { - IBaseFilter *pFilter; - PIN_DIRECTION dir; - WCHAR achName[MAX_PIN_NAME]; -} PIN_INFO; - -typedef struct _AllocatorProperties { - long cBuffers; - long cbBuffer; - long cbAlign; - long cbPrefix; -} ALLOCATOR_PROPERTIES; - -typedef struct _AMMediaType { - GUID majortype; - GUID subtype; - BOOL bFixedSizeSamples; - BOOL bTemporalCompression; - ULONG lSampleSize; - GUID formattype; - IUnknown *pUnk; - ULONG cbFormat; - BYTE *pbFormat; -} AM_MEDIA_TYPE; - -typedef enum tagVideoProcAmpFlags { - VideoProcAmp_Flags_Auto = 0x0001, - VideoProcAmp_Flags_Manual = 0x0002 -} VideoProcAmpFlags; - -typedef enum tagVideoProcAmpProperty { - VideoProcAmp_Brightness, - VideoProcAmp_Contrast, - VideoProcAmp_Hue, - VideoProcAmp_Saturation, - VideoProcAmp_Sharpness, - VideoProcAmp_Gamma, - VideoProcAmp_ColorEnable, - VideoProcAmp_WhiteBalance, - VideoProcAmp_BacklightCompensation, - VideoProcAmp_Gain -} VideoProcAmpProperty; - -typedef struct tagVIDEOINFOHEADER { - RECT rcSource; - RECT rcTarget; - DWORD dwBitRate; - DWORD dwBitErrorRate; - REFERENCE_TIME AvgTimePerFrame; - BITMAPINFOHEADER bmiHeader; -} VIDEOINFOHEADER; - -typedef struct _VIDEO_STREAM_CONFIG_CAPS { - GUID guid; - ULONG VideoStandard; - SIZE InputSize; - SIZE MinCroppingSize; - SIZE MaxCroppingSize; - int CropGranularityX; - int CropGranularityY; - int CropAlignX; - int CropAlignY; - SIZE MinOutputSize; - SIZE MaxOutputSize; - int OutputGranularityX; - int OutputGranularityY; - int StretchTapsX; - int StretchTapsY; - int ShrinkTapsX; - int ShrinkTapsY; - LONGLONG MinFrameInterval; - LONGLONG MaxFrameInterval; - LONG MinBitsPerSecond; - LONG MaxBitsPerSecond; -} VIDEO_STREAM_CONFIG_CAPS; - - -/* Interface & Class GUIDs */ -static const IID IID_IGrabCallback = {0x4C337035,0xC89E,0x4B42,{0x9B,0x0C,0x36,0x74,0x44,0xDD,0x70,0xDD}}; - -EXTERN_C const IID IID_IBaseFilter; -EXTERN_C const IID IID_ICreateDevEnum; -EXTERN_C const IID IID_IGraphBuilder; -EXTERN_C const IID IID_IMediaSeeking; -EXTERN_C const IID IID_IMediaEventSink; -EXTERN_C const IID IID_IMemInputPin; -EXTERN_C const IID IID_IEnumPins; -EXTERN_C const IID IID_IMediaFilter; -EXTERN_C const IID IID_IEnumMediaTypes; -EXTERN_C const IID IID_IMemAllocator; -EXTERN_C const IID IID_IPin; -EXTERN_C const IID IID_ICaptureGraphBuilder2; -EXTERN_C const IID IID_IFileSinkFilter; -EXTERN_C const IID IID_IAMCopyCaptureFileProgress; -EXTERN_C const IID IID_IEnumFilters; -EXTERN_C const IID IID_IMediaSample; -EXTERN_C const IID IID_IMediaControl; -EXTERN_C const IID IID_IAMStreamConfig; -EXTERN_C const IID IID_IAMVideoProcAmp; - -EXTERN_C const IID CLSID_CaptureGraphBuilder2; -EXTERN_C const IID CLSID_VideoInputDeviceCategory; -EXTERN_C const IID CLSID_AudioRender; -EXTERN_C const IID CLSID_SystemDeviceEnum; -EXTERN_C const IID CLSID_AudioRendererCategory; -EXTERN_C const IID CLSID_FilterGraph; -EXTERN_C const IID CLSID_InfTee; -EXTERN_C const IID CLSID_VideoMixingRenderer9; -EXTERN_C const IID CLSID_MemoryAllocator; - - -/* other types GUIDs*/ -EXTERN_C const IID MEDIATYPE_Audio; -EXTERN_C const IID MEDIATYPE_Video; -EXTERN_C const IID MEDIATYPE_Stream; -EXTERN_C const IID MEDIASUBTYPE_PCM; -EXTERN_C const IID MEDIASUBTYPE_WAVE; -EXTERN_C const IID MEDIASUBTYPE_Avi; -EXTERN_C const IID MEDIASUBTYPE_RGB32; -EXTERN_C const IID MEDIASUBTYPE_YV12; -EXTERN_C const IID MEDIASUBTYPE_YUY2; -EXTERN_C const IID MEDIASUBTYPE_I420; -EXTERN_C const IID MEDIASUBTYPE_YUYV; -EXTERN_C const IID FORMAT_WaveFormatEx; -EXTERN_C const IID FORMAT_VideoInfo; -EXTERN_C const IID FORMAT_VideoInfo2; -EXTERN_C const IID PIN_CATEGORY_CAPTURE; -EXTERN_C const IID PIN_CATEGORY_PREVIEW; - - -#define MEDIATYPE_NULL GUID_NULL -#define MEDIASUBTYPE_NULL GUID_NULL - -#define INTERFACE IGrabCallback -DECLARE_INTERFACE_(IGrabCallback, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(Grab)(THIS_ ULONG,BYTE*) PURE; -}; -#undef INTERFACE - -#ifdef COBJMACROS -#define IGrabCallback_QueryInterface(T,a,b) (T)->lpVtbl->QueryInterface(T,a,b) -#define IGrabCallback_AddRef(T) (T)->lpVtbl->AddRef(T) -#define IGrabCallback_Release(T) (T)->lpVtbl->Release(T) -#define IGrabCallback_Grab(T,a,b) (T)->lpVtbl->Grab(T,a,b) -#endif /* COBJMACROS */ - -#define INTERFACE IAMCopyCaptureFileProgress -DECLARE_INTERFACE_(IAMCopyCaptureFileProgress, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(Progress)(THIS_ int) PURE; -}; -#undef INTERFACE -#define INTERFACE IReferenceClock -DECLARE_INTERFACE_(IReferenceClock, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *) PURE; - STDMETHOD(AdviseTime)(THIS_ REFERENCE_TIME, REFERENCE_TIME, HEVENT, DWORD_PTR *) PURE; - STDMETHOD(AdvisePeriodic)(THIS_ REFERENCE_TIME, REFERENCE_TIME, HSEMAPHORE, DWORD_PTR *) PURE; - STDMETHOD(Unadvise)(THIS_ DWORD_PTR) PURE; -}; -#undef INTERFACE -#define INTERFACE IEnumFilters -DECLARE_INTERFACE_(IEnumFilters, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(Next)(THIS_ ULONG, IBaseFilter **, ULONG *) PURE; - STDMETHOD(Skip)(THIS_ ULONG) PURE; - STDMETHOD(Reset)(THIS) PURE; - STDMETHOD(Clone)(THIS_ IEnumFilters **) PURE; -}; -#undef INTERFACE -#define INTERFACE IEnumMediaTypes -DECLARE_INTERFACE_(IEnumMediaTypes, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(Next)(THIS_ ULONG, AM_MEDIA_TYPE **, ULONG *) PURE; - STDMETHOD(Skip)(THIS_ ULONG) PURE; - STDMETHOD(Reset)(THIS) PURE; - STDMETHOD(Clone)(THIS_ IEnumMediaTypes **) PURE; -}; -#undef INTERFACE -#define INTERFACE IPin -DECLARE_INTERFACE_(IPin, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(Connect)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE; - STDMETHOD(ReceiveConnection)(THIS_ IPin *, const AM_MEDIA_TYPE *) PURE; - STDMETHOD(Disconnect)(THIS) PURE; - STDMETHOD(ConnectedTo)(THIS_ IPin **) PURE; - STDMETHOD(ConnectionMediaType)(THIS_ AM_MEDIA_TYPE *) PURE; - STDMETHOD(QueryPinInfo)(THIS_ PIN_INFO *) PURE; - STDMETHOD(QueryDirection)(THIS_ PIN_DIRECTION *) PURE; - STDMETHOD(QueryId)(THIS_ LPWSTR *) PURE; - STDMETHOD(QueryAccept)(THIS_ const AM_MEDIA_TYPE *) PURE; - STDMETHOD(EnumMediaTypes)(THIS_ IEnumMediaTypes **) PURE; - STDMETHOD(QueryInternalConnections)(THIS_ IPin **, ULONG *) PURE; - STDMETHOD(EndOfStream)(THIS) PURE; - STDMETHOD(BeginFlush)(THIS) PURE; - STDMETHOD(EndFlush)(THIS) PURE; - STDMETHOD(NewSegment)(THIS_ REFERENCE_TIME, REFERENCE_TIME, double) PURE; -}; -#undef INTERFACE -#define INTERFACE IEnumPins -DECLARE_INTERFACE_(IEnumPins, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(Next)(THIS_ ULONG, IPin **, ULONG *) PURE; - STDMETHOD(Skip)(THIS_ ULONG) PURE; - STDMETHOD(Reset)(THIS) PURE; - STDMETHOD(Clone)(THIS_ IEnumPins **) PURE; -}; -#undef INTERFACE -#define INTERFACE IMediaFilter -DECLARE_INTERFACE_(IMediaFilter, IPersist) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(GetClassID)(THIS_ CLSID*) PURE; - STDMETHOD(Stop)(THIS) PURE; - STDMETHOD(Pause)(THIS) PURE; - STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE; - STDMETHOD(GetState)(THIS_ DWORD, FILTER_STATE *) PURE; - STDMETHOD(SetSyncSource)(THIS_ IReferenceClock *) PURE; - STDMETHOD(GetSyncSource)(THIS_ IReferenceClock **) PURE; -}; -#undef INTERFACE -#define INTERFACE IBaseFilter -DECLARE_INTERFACE2_(IBaseFilter, IMediaFilter) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(GetClassID)(THIS_ CLSID*) PURE; - STDMETHOD(Stop)(THIS) PURE; - STDMETHOD(Pause)(THIS) PURE; - STDMETHOD(Run)(THIS_ REFERENCE_TIME) PURE; - STDMETHOD(GetState)(THIS_ DWORD, FILTER_STATE *) PURE; - STDMETHOD(SetSyncSource)(THIS_ IReferenceClock *) PURE; - STDMETHOD(GetSyncSource)(THIS_ IReferenceClock **) PURE; - STDMETHOD(EnumPins)(THIS_ IEnumPins **) PURE; - STDMETHOD(FindPin)(THIS_ LPCWSTR, IPin **) PURE; - STDMETHOD(QueryFilterInfo)(THIS_ FILTER_INFO *) PURE; - STDMETHOD(JoinFilterGraph)(THIS_ IFilterGraph *, LPCWSTR) PURE; - STDMETHOD(QueryVendorInfo)(THIS_ LPWSTR *) PURE; -}; -#undef INTERFACE -#define INTERFACE IFilterGraph -DECLARE_INTERFACE2_(IFilterGraph, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(AddFilter)(THIS_ IBaseFilter *, LPCWSTR) PURE; - STDMETHOD(RemoveFilter)(THIS_ IBaseFilter *) PURE; - STDMETHOD(EnumFilters)(THIS_ IEnumFilters **) PURE; - STDMETHOD(FindFilterByName)(THIS_ LPCWSTR, IBaseFilter **) PURE; - STDMETHOD(ConnectDirect)(THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *) PURE; - STDMETHOD(Reconnect)(THIS_ IPin *) PURE; - STDMETHOD(Disconnect)(THIS_ IPin *) PURE; - STDMETHOD(SetDefaultSyncSource)(THIS) PURE; -}; -#undef INTERFACE -#define INTERFACE IGraphBuilder -DECLARE_INTERFACE_(IGraphBuilder ,IFilterGraph) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(AddFilter)(THIS_ IBaseFilter *, LPCWSTR) PURE; - STDMETHOD(RemoveFilter)(THIS_ IBaseFilter *) PURE; - STDMETHOD(EnumFilters)(THIS_ IEnumFilters **) PURE; - STDMETHOD(FindFilterByName)(THIS_ LPCWSTR, IBaseFilter **) PURE; - STDMETHOD(ConnectDirect)(THIS_ IPin *, IPin *, const AM_MEDIA_TYPE *) PURE; - STDMETHOD(Reconnect)(THIS_ IPin *) PURE; - STDMETHOD(Disconnect)(THIS_ IPin *) PURE; - STDMETHOD(SetDefaultSyncSource)(THIS) PURE; - STDMETHOD(Connect)(THIS_ IPin *, IPin *) PURE; - STDMETHOD(Render)(THIS_ IPin *) PURE; - STDMETHOD(RenderFile)(THIS_ LPCWSTR, LPCWSTR) PURE; - STDMETHOD(AddSourceFilter)(THIS_ LPCWSTR, LPCWSTR, IBaseFilter **) PURE; - STDMETHOD(SetLogFile)(THIS_ DWORD_PTR) PURE; - STDMETHOD(Abort)(THIS) PURE; - STDMETHOD(ShouldOperationContinue)(THIS) PURE; -}; -#undef INTERFACE -#define INTERFACE ICreateDevEnum -DECLARE_INTERFACE_(ICreateDevEnum, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(CreateClassEnumerator)(THIS_ REFCLSID, IEnumMoniker **, DWORD) PURE; -}; -#undef INTERFACE -#define INTERFACE IMediaSample -DECLARE_INTERFACE_(IMediaSample, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(GetPointer)(THIS_ BYTE **) PURE; - STDMETHOD_(long, GetSize)(THIS) PURE; - STDMETHOD(GetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE; - STDMETHOD(SetTime)(THIS_ REFERENCE_TIME *, REFERENCE_TIME *) PURE; - STDMETHOD(IsSyncPoint)(THIS) PURE; - STDMETHOD(SetSyncPoint)(THIS_ BOOL) PURE; - STDMETHOD(IsPreroll)(THIS) PURE; - STDMETHOD(SetPreroll)(THIS_ BOOL) PURE; - STDMETHOD_(long, GetActualDataLength)(THIS) PURE; - STDMETHOD(SetActualDataLength)(THIS_ long) PURE; - STDMETHOD(GetMediaType)(THIS_ AM_MEDIA_TYPE **) PURE; - STDMETHOD(SetMediaType)(THIS_ AM_MEDIA_TYPE *) PURE; - STDMETHOD(IsDiscontinuity)(THIS) PURE; - STDMETHOD(SetDiscontinuity)(THIS_ BOOL) PURE; - STDMETHOD(GetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE; - STDMETHOD(SetMediaTime)(THIS_ LONGLONG *, LONGLONG *) PURE; -}; -#undef INTERFACE -#define INTERFACE IMemAllocator -DECLARE_INTERFACE_(IMemAllocator, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(SetProperties)(THIS_ ALLOCATOR_PROPERTIES *, ALLOCATOR_PROPERTIES *) PURE; - STDMETHOD(GetProperties)(THIS_ ALLOCATOR_PROPERTIES *) PURE; - STDMETHOD(Commit)(THIS) PURE; - STDMETHOD(Decommit)(THIS) PURE; - STDMETHOD(GetBuffer)(THIS_ IMediaSample **, REFERENCE_TIME *, REFERENCE_TIME *, DWORD) PURE; - STDMETHOD(ReleaseBuffer)(THIS_ IMediaSample *) PURE; - -}; -#undef INTERFACE -#define INTERFACE IMemInputPin -DECLARE_INTERFACE_(IMemInputPin, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(GetAllocator)(THIS_ IMemAllocator **) PURE; - STDMETHOD(NotifyAllocator)(THIS_ IMemAllocator *, BOOL) PURE; - STDMETHOD(GetAllocatorRequirements)(THIS_ ALLOCATOR_PROPERTIES *) PURE; - STDMETHOD(Receive)(THIS_ IMediaSample *) PURE; - STDMETHOD(ReceiveMultiple)(THIS_ IMediaSample **, long, long *) PURE; - STDMETHOD(ReceiveCanBlock)(THIS) PURE; -}; -#undef INTERFACE -#define INTERFACE IFileSinkFilter -DECLARE_INTERFACE_(IFileSinkFilter, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(SetFileName)(THIS_ LPCOLESTR,const AM_MEDIA_TYPE *) PURE; - STDMETHOD(GetCurFile)(THIS_ LPOLESTR *,AM_MEDIA_TYPE*) PURE; -}; -#undef INTERFACE -#define INTERFACE ICaptureGraphBuilder2 -DECLARE_INTERFACE_(ICaptureGraphBuilder2, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(SetFiltergraph)(THIS_ IGraphBuilder*) PURE; - STDMETHOD(GetFiltergraph)(THIS_ IGraphBuilder**) PURE; - STDMETHOD(SetOutputFileName)(THIS_ const GUID*,LPCOLESTR,IBaseFilter**,IFileSinkFilter**) PURE; - STDMETHOD(FindInterface)(THIS_ const GUID*,const GUID*,IBaseFilter*,REFIID,void**) PURE; - STDMETHOD(RenderStream)(THIS_ const GUID*,const GUID*,IUnknown*,IBaseFilter*,IBaseFilter*) PURE; - STDMETHOD(ControlStream)(THIS_ const GUID*,const GUID*,IBaseFilter*,REFERENCE_TIME*,REFERENCE_TIME*,WORD,WORD) PURE; - STDMETHOD(AllocCapFile)(THIS_ LPCOLESTR,DWORDLONG) PURE; - STDMETHOD(CopyCaptureFile)(THIS_ LPOLESTR,LPOLESTR,int,IAMCopyCaptureFileProgress*) PURE; - STDMETHOD(FindPin)(THIS_ IUnknown*,PIN_DIRECTION,const GUID*,const GUID*,BOOL,int,IPin**) PURE; -}; -#undef INTERFACE -#define INTERFACE IAMStreamConfig -DECLARE_INTERFACE_(IAMStreamConfig, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(SetFormat)(THIS_ AM_MEDIA_TYPE*) PURE; - STDMETHOD(GetFormat)(THIS_ AM_MEDIA_TYPE**) PURE; - STDMETHOD(GetNumberOfCapabilities)(THIS_ int*,int*) PURE; - STDMETHOD(GetStreamCaps)(THIS_ int,AM_MEDIA_TYPE**,BYTE*) PURE; -}; -#undef INTERFACE -#define INTERFACE IAMVideoProcAmp -DECLARE_INTERFACE_(IAMVideoProcAmp, IUnknown) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(GetRange)(THIS_ long,long*,long*,long*,long*,long*) PURE; - STDMETHOD(Set)(THIS_ long,long,long) PURE; - STDMETHOD(Get)(THIS_ long,long*,long*) PURE; -}; -#undef INTERFACE -#define INTERFACE IMediaControl -DECLARE_INTERFACE_(IMediaControl, IDispatch) -{ - STDMETHOD(QueryInterface)(THIS_ REFIID, PVOID *) PURE; - STDMETHOD_(ULONG, AddRef)(THIS) PURE; - STDMETHOD_(ULONG, Release)(THIS) PURE; - STDMETHOD(GetTypeInfoCount)(THIS_ UINT*); - STDMETHOD(GetTypeInfo)(THIS_ UINT,LCID,ITypeInfo**); - STDMETHOD(GetIDsOfNames)(THIS_ REFIID,LPOLESTR*,UINT,LCID,DISPID*); - STDMETHOD(Invoke)(THIS_ DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*); - STDMETHOD(Run)(THIS); - STDMETHOD(Pause)(THIS); - STDMETHOD(Stop)(THIS); - STDMETHOD(GetState)(THIS_ LONG, OAFilterState*); - STDMETHOD(RenderFile)(THIS_ BSTR); - STDMETHOD(AddSourceFilter)(THIS_ BSTR,IDispatch**); - STDMETHOD(get_FilterCollection)(THIS_ IDispatch**); - STDMETHOD(get_RegFilterCollection)(THIS_ IDispatch**); - STDMETHOD(StopWhenReady)(THIS); -}; -#undef INTERFACE - -#ifdef COBJMACROS -#define ICreateDevEnum_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define ICreateDevEnum_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define ICreateDevEnum_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define ICreateDevEnum_CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags) \ - ((This)->lpVtbl->CreateClassEnumerator(This,clsidDeviceClass,ppEnumMoniker,dwFlags)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IPin_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IPin_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IPin_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IPin_Connect(This,pReceivePin,pmt) \ - ((This)->lpVtbl->Connect(This,pReceivePin,pmt)) -#define IPin_ReceiveConnection(This,pConnector,pmt) \ - ((This)->lpVtbl->ReceiveConnection(This,pConnector,pmt)) -#define IPin_Disconnect(This) \ - ((This)->lpVtbl->Disconnect(This)) -#define IPin_ConnectedTo(This,pPin) \ - ((This)->lpVtbl->ConnectedTo(This,pPin)) -#define IPin_ConnectionMediaType(This,pmt) \ - ((This)->lpVtbl->ConnectionMediaType(This,pmt)) -#define IPin_QueryPinInfo(This,pInfo) \ - ((This)->lpVtbl->QueryPinInfo(This,pInfo)) -#define IPin_QueryDirection(This,pPinDir) \ - ((This)->lpVtbl->QueryDirection(This,pPinDir)) -#define IPin_QueryId(This,Id) \ - ((This)->lpVtbl->QueryId(This,Id)) -#define IPin_QueryAccept(This,pmt) \ - ((This)->lpVtbl->QueryAccept(This,pmt)) -#define IPin_EnumMediaTypes(This,ppEnum) \ - ((This)->lpVtbl->EnumMediaTypes(This,ppEnum)) -#define IPin_QueryInternalConnections(This,apPin,nPin) \ - ((This)->lpVtbl->QueryInternalConnections(This,apPin,nPin)) -#define IPin_EndOfStream(This) \ - ((This)->lpVtbl->EndOfStream(This)) -#define IPin_BeginFlush(This) \ - ((This)->lpVtbl->BeginFlush(This)) -#define IPin_EndFlush(This) \ - ((This)->lpVtbl->EndFlush(This)) -#define IPin_NewSegment(This,tStart,tStop,dRate) \ - ((This)->lpVtbl->NewSegment(This,tStart,tStop,dRate)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IEnumPins_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IEnumPins_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IEnumPins_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IEnumPins_Next(This,cPins,ppPins,pcFetched) \ - ((This)->lpVtbl->Next(This,cPins,ppPins,pcFetched)) -#define IEnumPins_Skip(This,cPins) \ - ((This)->lpVtbl->Skip(This,cPins)) -#define IEnumPins_Reset(This) \ - ((This)->lpVtbl->Reset(This)) -#define IEnumPins_Clone(This,ppEnum) \ - ((This)->lpVtbl->Clone(This,ppEnum)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IAMStreamConfig_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IAMStreamConfig_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IAMStreamConfig_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IAMStreamConfig_SetFormat(This,pmt) \ - ((This)->lpVtbl->SetFormat(This,pmt)) -#define IAMStreamConfig_GetFormat(This,ppmt) \ - ((This)->lpVtbl->GetFormat(This,ppmt)) -#define IAMStreamConfig_GetNumberOfCapabilities(This,piCount,piSize) \ - ((This)->lpVtbl->GetNumberOfCapabilities(This,piCount,piSize)) -#define IAMStreamConfig_GetStreamCaps(This,iIndex,ppmt,pSCC) \ - ((This)->lpVtbl->GetStreamCaps(This,iIndex,ppmt,pSCC)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IFilterGraph_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IFilterGraph_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IFilterGraph_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IFilterGraph_AddFilter(This,pFilter,pName) \ - ((This)->lpVtbl->AddFilter(This,pFilter,pName)) -#define IFilterGraph_RemoveFilter(This,pFilter) \ - ((This)->lpVtbl->RemoveFilter(This,pFilter)) -#define IFilterGraph_EnumFilters(This,ppEnum) \ - ((This)->lpVtbl->EnumFilters(This,ppEnum)) -#define IFilterGraph_FindFilterByName(This,pName,ppFilter) \ - ((This)->lpVtbl->FindFilterByName(This,pName,ppFilter)) -#define IFilterGraph_ConnectDirect(This,ppinOut,ppinIn,pmt) \ - ((This)->lpVtbl->ConnectDirect(This,ppinOut,ppinIn,pmt)) -#define IFilterGraph_Reconnect(This,ppin) \ - ((This)->lpVtbl->Reconnect(This,ppin)) -#define IFilterGraph_Disconnect(This,ppin) \ - ((This)->lpVtbl->Disconnect(This,ppin)) -#define IFilterGraph_SetDefaultSyncSource(This) \ - ((This)->lpVtbl->SetDefaultSyncSource(This)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IMediaFilter_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IMediaFilter_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IMediaFilter_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IMediaFilter_GetClassID(This,pClassID) \ - ((This)->lpVtbl->GetClassID(This,pClassID)) -#define IMediaFilter_Stop(This) \ - ((This)->lpVtbl->Stop(This)) -#define IMediaFilter_Pause(This) \ - ((This)->lpVtbl->Pause(This)) -#define IMediaFilter_Run(This,tStart) \ - ((This)->lpVtbl->Run(This,tStart)) -#define IMediaFilter_GetState(This,dwMilliSecsTimeout,State) \ - ((This)->lpVtbl->GetState(This,dwMilliSecsTimeout,State)) -#define IMediaFilter_SetSyncSource(This,pClock) \ - ((This)->lpVtbl->SetSyncSource(This,pClock)) -#define IMediaFilter_GetSyncSource(This,pClock) \ - ((This)->lpVtbl->GetSyncSource(This,pClock)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IBaseFilter_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IBaseFilter_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IBaseFilter_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IBaseFilter_GetClassID(This,pClassID) \ - ((This)->lpVtbl->GetClassID(This,pClassID)) -#define IBaseFilter_Stop(This) \ - ((This)->lpVtbl->Stop(This)) -#define IBaseFilter_Pause(This) \ - ((This)->lpVtbl->Pause(This)) -#define IBaseFilter_Run(This,tStart) \ - ((This)->lpVtbl->Run(This,tStart)) -#define IBaseFilter_GetState(This,dwMilliSecsTimeout,State) \ - ((This)->lpVtbl->GetState(This,dwMilliSecsTimeout,State)) -#define IBaseFilter_SetSyncSource(This,pClock) \ - ((This)->lpVtbl->SetSyncSource(This,pClock)) -#define IBaseFilter_GetSyncSource(This,pClock) \ - ((This)->lpVtbl->GetSyncSource(This,pClock)) -#define IBaseFilter_EnumPins(This,ppEnum) \ - ((This)->lpVtbl->EnumPins(This,ppEnum)) -#define IBaseFilter_FindPin(This,Id,ppPin) \ - ((This)->lpVtbl->FindPin(This,Id,ppPin)) -#define IBaseFilter_QueryFilterInfo(This,pInfo) \ - ((This)->lpVtbl->QueryFilterInfo(This,pInfo)) -#define IBaseFilter_JoinFilterGraph(This,pGraph,pName) \ - ((This)->lpVtbl->JoinFilterGraph(This,pGraph,pName)) -#define IBaseFilter_QueryVendorInfo(This,pVendorInfo) \ - ((This)->lpVtbl->QueryVendorInfo(This,pVendorInfo)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IMediaSample_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IMediaSample_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IMediaSample_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IMediaSample_GetPointer(This,ppBuffer) \ - ((This)->lpVtbl->GetPointer(This,ppBuffer)) -#define IMediaSample_GetSize(This) \ - ((This)->lpVtbl->GetSize(This)) -#define IMediaSample_GetTime(This,pTimeStart,pTimeEnd) \ - ((This)->lpVtbl->GetTime(This,pTimeStart,pTimeEnd)) -#define IMediaSample_SetTime(This,pTimeStart,pTimeEnd) \ - ((This)->lpVtbl->SetTime(This,pTimeStart,pTimeEnd)) -#define IMediaSample_IsSyncPoint(This) \ - ((This)->lpVtbl->IsSyncPoint(This)) -#define IMediaSample_SetSyncPoint(This,bIsSyncPoint) \ - ((This)->lpVtbl->SetSyncPoint(This,bIsSyncPoint)) -#define IMediaSample_IsPreroll(This) \ - ((This)->lpVtbl->IsPreroll(This)) -#define IMediaSample_SetPreroll(This,bIsPreroll) \ - ((This)->lpVtbl->SetPreroll(This,bIsPreroll)) -#define IMediaSample_GetActualDataLength(This) \ - ((This)->lpVtbl->GetActualDataLength(This)) -#define IMediaSample_SetActualDataLength(This,length) \ - ((This)->lpVtbl->SetActualDataLength(This,length)) -#define IMediaSample_GetMediaType(This,ppMediaType) \ - ((This)->lpVtbl->GetMediaType(This,ppMediaType)) -#define IMediaSample_SetMediaType(This,pMediaType) \ - ((This)->lpVtbl->SetMediaType(This,pMediaType)) -#define IMediaSample_IsDiscontinuity(This) \ - ((This)->lpVtbl->IsDiscontinuity(This)) -#define IMediaSample_SetDiscontinuity(This,bDiscontinuity) \ - ((This)->lpVtbl->SetDiscontinuity(This,bDiscontinuity)) -#define IMediaSample_GetMediaTime(This,pTimeStart,pTimeEnd) \ - ((This)->lpVtbl->GetMediaTime(This,pTimeStart,pTimeEnd)) -#define IMediaSample_SetMediaTime(This,pTimeStart,pTimeEnd) \ - ((This)->lpVtbl->SetMediaTime(This,pTimeStart,pTimeEnd)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IEnumFilters_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IEnumFilters_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IEnumFilters_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IEnumFilters_Next(This,cFilters,ppFilter,pcFetched) \ - ((This)->lpVtbl->Next(This,cFilters,ppFilter,pcFetched)) -#define IEnumFilters_Skip(This,cFilters) \ - ((This)->lpVtbl->Skip(This,cFilters)) -#define IEnumFilters_Reset(This) \ - ((This)->lpVtbl->Reset(This)) -#define IEnumFilters_Clone(This,ppEnum) \ - ((This)->lpVtbl->Clone(This,ppEnum)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IMemAllocator_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IMemAllocator_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IMemAllocator_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IMemAllocator_SetProperties(This,pRequest,pActual) \ - ((This)->lpVtbl->SetProperties(This,pRequest,pActual)) -#define IMemAllocator_GetProperties(This,pProps) \ - ((This)->lpVtbl->GetProperties(This,pProps)) -#define IMemAllocator_Commit(This) \ - ((This)->lpVtbl->Commit(This)) -#define IMemAllocator_Decommit(This) \ - ((This)->lpVtbl->Decommit(This)) -#define IMemAllocator_GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags) \ - ((This)->lpVtbl->GetBuffer(This,ppBuffer,pStartTime,pEndTime,dwFlags)) -#define IMemAllocator_ReleaseBuffer(This,pBuffer) \ - ((This)->lpVtbl->ReleaseBuffer(This,pBuffer)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IMemInputPin_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IMemInputPin_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IMemInputPin_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IMemInputPin_GetAllocator(This,ppAllocator) \ - ((This)->lpVtbl->GetAllocator(This,ppAllocator)) -#define IMemInputPin_NotifyAllocator(This,pAllocator,bReadOnly) \ - ((This)->lpVtbl->NotifyAllocator(This,pAllocator,bReadOnly)) -#define IMemInputPin_GetAllocatorRequirements(This,pProps) \ - ((This)->lpVtbl->GetAllocatorRequirements(This,pProps)) -#define IMemInputPin_Receive(This,pSample) \ - ((This)->lpVtbl->Receive(This,pSample)) -#define IMemInputPin_ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed) \ - ((This)->lpVtbl->ReceiveMultiple(This,pSamples,nSamples,nSamplesProcessed)) -#define IMemInputPin_ReceiveCanBlock(This) \ - ((This)->lpVtbl->ReceiveCanBlock(This)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IGraphBuilder_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IGraphBuilder_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IGraphBuilder_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IGraphBuilder_AddFilter(This,pFilter,pName) \ - ((This)->lpVtbl->AddFilter(This,pFilter,pName)) -#define IGraphBuilder_RemoveFilter(This,pFilter) \ - ((This)->lpVtbl->RemoveFilter(This,pFilter)) -#define IGraphBuilder_EnumFilters(This,ppEnum) \ - ((This)->lpVtbl->EnumFilters(This,ppEnum)) -#define IGraphBuilder_FindFilterByName(This,pName,ppFilter) \ - ((This)->lpVtbl->FindFilterByName(This,pName,ppFilter)) -#define IGraphBuilder_ConnectDirect(This,ppinOut,ppinIn,pmt) \ - ((This)->lpVtbl->ConnectDirect(This,ppinOut,ppinIn,pmt)) -#define IGraphBuilder_Reconnect(This,ppin) \ - ((This)->lpVtbl->Reconnect(This,ppin)) -#define IGraphBuilder_Disconnect(This,ppin) \ - ((This)->lpVtbl->Disconnect(This,ppin)) -#define IGraphBuilder_SetDefaultSyncSource(This) \ - ((This)->lpVtbl->SetDefaultSyncSource(This)) -#define IGraphBuilder_Connect(This,ppinOut,ppinIn) \ - ((This)->lpVtbl->Connect(This,ppinOut,ppinIn)) -#define IGraphBuilder_Render(This,ppinOut) \ - ((This)->lpVtbl->Render(This,ppinOut)) -#define IGraphBuilder_RenderFile(This,lpcwstrFile,lpcwstrPlayList) \ - ((This)->lpVtbl->RenderFile(This,lpcwstrFile,lpcwstrPlayList)) -#define IGraphBuilder_AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter) \ - ((This)->lpVtbl->AddSourceFilter(This,lpcwstrFileName,lpcwstrFilterName,ppFilter)) -#define IGraphBuilder_SetLogFile(This,hFile) \ - ((This)->lpVtbl->SetLogFile(This,hFile)) -#define IGraphBuilder_Abort(This) \ - ((This)->lpVtbl->Abort(This)) -#define IGraphBuilder_ShouldOperationContinue(This) \ - ((This)->lpVtbl->ShouldOperationContinue(This)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IEnumMediaTypes_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IEnumMediaTypes_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IEnumMediaTypes_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IEnumMediaTypes_Next(This,cMediaTypes,ppMediaTypes,pcFetched) \ - ((This)->lpVtbl->Next(This,cMediaTypes,ppMediaTypes,pcFetched)) -#define IEnumMediaTypes_Skip(This,cMediaTypes) \ - ((This)->lpVtbl->Skip(This,cMediaTypes)) -#define IEnumMediaTypes_Reset(This) \ - ((This)->lpVtbl->Reset(This)) -#define IEnumMediaTypes_Clone(This,ppEnum) \ - ((This)->lpVtbl->Clone(This,ppEnum)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IMediaControl_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IMediaControl_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IMediaControl_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IMediaControl_GetTypeInfoCount(This,pctinfo) \ - ((This)->lpVtbl->GetTypeInfoCount(This,pctinfo)) -#define IMediaControl_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ - ((This)->lpVtbl->GetTypeInfo(This,iTInfo,lcid,ppTInfo)) -#define IMediaControl_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ - ((This)->lpVtbl->GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)) -#define IMediaControl_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ - ((This)->lpVtbl->Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)) -#define IMediaControl_Run(This) \ - ((This)->lpVtbl->Run(This)) -#define IMediaControl_Pause(This) \ - ((This)->lpVtbl->Pause(This)) -#define IMediaControl_Stop(This) \ - ((This)->lpVtbl->Stop(This)) -#define IMediaControl_GetState(This,msTimeout,pfs) \ - ((This)->lpVtbl->GetState(This,msTimeout,pfs)) -#define IMediaControl_RenderFile(This,strFilename) \ - ((This)->lpVtbl->RenderFile(This,strFilename)) -#define IMediaControl_AddSourceFilter(This,strFilename,ppUnk) \ - ((This)->lpVtbl->AddSourceFilter(This,strFilename,ppUnk)) -#define IMediaControl_get_FilterCollection(This,ppUnk) \ - ((This)->lpVtbl->get_FilterCollection(This,ppUnk)) -#define IMediaControl_get_RegFilterCollection(This,ppUnk) \ - ((This)->lpVtbl->get_RegFilterCollection(This,ppUnk)) -#define IMediaControl_StopWhenReady(This) \ - ((This)->lpVtbl->StopWhenReady(This)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IAMVideoProcAmp_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IAMVideoProcAmp_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IAMVideoProcAmp_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IAMVideoProcAmp_GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags) \ - ((This)->lpVtbl->GetRange(This,Property,pMin,pMax,pSteppingDelta,pDefault,pCapsFlags)) -#define IAMVideoProcAmp_Set(This,Property,lValue,Flags) \ - ((This)->lpVtbl->Set(This,Property,lValue,Flags)) -#define IAMVideoProcAmp_Get(This,Property,lValue,Flags) \ - ((This)->lpVtbl->Get(This,Property,lValue,Flags)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IFileSinkFilter_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IFileSinkFilter_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IFileSinkFilter_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IFileSinkFilter_SetFileName(This,pszFileName,pmt) \ - ((This)->lpVtbl->SetFileName(This,pszFileName,pmt)) -#define IFileSinkFilter_GetCurFile(This,ppszFileName,pmt) \ - ((This)->lpVtbl->GetCurFile(This,ppszFileName,pmt)) -#endif /* COBJMACROS */ - -#ifdef COBJMACROS -#define IAMCopyCaptureFileProgress_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define IAMCopyCaptureFileProgress_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define IAMCopyCaptureFileProgress_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define IAMCopyCaptureFileProgress_Progress(This,iProgress) \ - ((This)->lpVtbl->Progress(This,iProgress)) -#endif /* COBJMACROS */ - - -#ifdef COBJMACROS -#define ICaptureGraphBuilder2_QueryInterface(This,riid,ppvObject) \ - ((This)->lpVtbl->QueryInterface(This,riid,ppvObject)) -#define ICaptureGraphBuilder2_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) -#define ICaptureGraphBuilder2_Release(This) \ - ((This)->lpVtbl->Release(This)) -#define ICaptureGraphBuilder2_SetFiltergraph(This,pfg) \ - ((This)->lpVtbl->SetFiltergraph(This,pfg)) -#define ICaptureGraphBuilder2_GetFiltergraph(This,ppfg) \ - ((This)->lpVtbl->GetFiltergraph(This,ppfg)) -#define ICaptureGraphBuilder2_SetOutputFileName(This,pType,lpstrFile,ppf,ppSink) \ - ((This)->lpVtbl->SetOutputFileName(This,pType,lpstrFile,ppf,ppSink)) -#define ICaptureGraphBuilder2_FindInterface(This,pCategory,pType,pf,riid,ppint) \ - ((This)->lpVtbl->FindInterface(This,pCategory,pType,pf,riid,ppint)) -#define ICaptureGraphBuilder2_RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer) \ - ((This)->lpVtbl->RenderStream(This,pCategory,pType,pSource,pfCompressor,pfRenderer)) -#define ICaptureGraphBuilder2_ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie) \ - ((This)->lpVtbl->ControlStream(This,pCategory,pType,pFilter,pstart,pstop,wStartCookie,wStopCookie)) -#define ICaptureGraphBuilder2_AllocCapFile(This,lpstr,dwlSize) \ - ((This)->lpVtbl->AllocCapFile(This,lpstr,dwlSize)) -#define ICaptureGraphBuilder2_CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback) \ - ((This)->lpVtbl->CopyCaptureFile(This,lpwstrOld,lpwstrNew,fAllowEscAbort,pCallback)) -#define ICaptureGraphBuilder2_FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin) \ - ((This)->lpVtbl->FindPin(This,pSource,pindir,pCategory,pType,fUnconnected,num,ppPin)) -#endif /* COBJMACROS */ - -#endif /* _MARU_CAMERA_INTERFACE_H_ */ diff --git a/tizen/src/hw/pci/maru_camera_win32_pci.c b/tizen/src/hw/pci/maru_camera_win32_pci.c deleted file mode 100644 index 72bfbbb2ab..0000000000 --- a/tizen/src/hw/pci/maru_camera_win32_pci.c +++ /dev/null @@ -1,2799 +0,0 @@ -/* - * Implementation of MARU Virtual Camera device by PCI bus on Windows. - * - * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved - * - * Contact: - * JinHyung Jo - * YeongKyoon Lee - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - * Contributors: - * - S-Core Co., Ltd - * - */ - - -#include "qemu-common.h" -#include "sysemu/hax.h" -#include "maru_camera_common.h" -#include "debug_ch.h" - -#define CINTERFACE -#define COBJMACROS -#include "ocidl.h" -#include "errors.h" /* for VFW_E_XXXX */ -#include "mmsystem.h" /* for MAKEFOURCC macro */ -#include "maru_camera_win32_interface.h" - -MULTI_DEBUG_CHANNEL(tizen, camera); - -/* - * COM Interface implementations - * - */ - -#define SAFE_RELEASE(x) \ - do { \ - if (x) { \ - (x)->lpVtbl->Release(x); \ - x = NULL; \ - } \ - } while (0) - -typedef HRESULT (STDAPICALLTYPE *CallbackFn)(ULONG dwSize, BYTE *pBuffer); - -/* - * HWCGrabCallback - */ - -typedef struct HWCGrabCallback { - IGrabCallback IGrabCallback_iface; - long m_cRef; - CallbackFn m_pCallback; - STDMETHODIMP (*SetCallback)(IGrabCallback *iface, CallbackFn pCallbackFn); -} HWCGrabCallback; - -static inline HWCGrabCallback *impl_from_IGrabCallback(IGrabCallback *iface) -{ - return CONTAINING_RECORD(iface, HWCGrabCallback, IGrabCallback_iface); -} - -static STDMETHODIMP HWCGrabCallback_QueryInterface(IGrabCallback *iface, - REFIID riid, void **ppv) -{ - if (IsEqualIID(riid, &IID_IUnknown)) { - *ppv = (IUnknown *)iface; - } else if (IsEqualIID(riid, &IID_IGrabCallback)) { - *ppv = (IGrabCallback *)iface; - } else { - *ppv = NULL; - return E_NOINTERFACE; - } - - IGrabCallback_AddRef(iface); - return S_OK; -} - -static STDMETHODIMP_(ULONG) HWCGrabCallback_AddRef(IGrabCallback *iface) -{ - HWCGrabCallback *This = impl_from_IGrabCallback(iface); - - return InterlockedIncrement(&This->m_cRef); -} - -static STDMETHODIMP_(ULONG) HWCGrabCallback_Release(IGrabCallback *iface) -{ - HWCGrabCallback *This = impl_from_IGrabCallback(iface); - - if (InterlockedDecrement(&This->m_cRef) == 0) { - This->m_pCallback = NULL; - g_free((void *)This); - This = NULL; - return 0; - } - - return This->m_cRef; -} - -static STDMETHODIMP HWCGrabCallback_Grab(IGrabCallback *iface, - ULONG dwSize, BYTE *pBuffer) -{ - HWCGrabCallback *This = impl_from_IGrabCallback(iface); - - if (This->m_pCallback) { - HRESULT hr = This->m_pCallback(dwSize, pBuffer); - if (FAILED(hr)) { - return E_FAIL; - } else { - return S_OK; - } - } - - return E_FAIL; -} - -static STDMETHODIMP HWCGrabCallback_SetCallback(IGrabCallback *iface, - CallbackFn pCallbackFn) -{ - HWCGrabCallback *This = impl_from_IGrabCallback(iface); - - This->m_pCallback = pCallbackFn; - return S_OK; -} - -static IGrabCallbackVtbl HWCGrabCallback_Vtbl = { - HWCGrabCallback_QueryInterface, - HWCGrabCallback_AddRef, - HWCGrabCallback_Release, - HWCGrabCallback_Grab -}; - -static STDMETHODIMP HWCGrabCallback_Construct(IGrabCallback **ppv) -{ - HWCGrabCallback *This = - (HWCGrabCallback *)g_malloc0(sizeof(HWCGrabCallback)); - - if (!This) { - ERR("failed to HWCGrabCallback_Construct, E_OUTOFMEMORY\n"); - return E_OUTOFMEMORY; - } - - This->IGrabCallback_iface.lpVtbl = &HWCGrabCallback_Vtbl; - This->m_cRef = 1; - This->m_pCallback = NULL; - This->SetCallback = HWCGrabCallback_SetCallback; - *ppv = &This->IGrabCallback_iface; - return S_OK; -} - -/* - * HWCPin - */ - -typedef struct HWCInPin { - IPin IPin_iface; - IMemInputPin IMemInputPin_iface; - IBaseFilter *m_pCFilter; - IPin *m_pConnectedPin; - IGrabCallback *m_pCallback; - IMemAllocator *m_pAllocator; - BOOL m_bReadOnly; - long m_cRef; - STDMETHODIMP (*SetGrabCallbackIF)(IPin *iface, IGrabCallback *pCaptureCB); -} HWCInPin; - -static inline HWCInPin *impl_from_IPin(IPin *iface) -{ - return CONTAINING_RECORD(iface, HWCInPin, IPin_iface); -} - -static inline HWCInPin *impl_from_IMemInputPin(IMemInputPin *iface) -{ - return CONTAINING_RECORD(iface, HWCInPin, IMemInputPin_iface); -} - -static STDMETHODIMP HWCPin_QueryInterface(IPin *iface, REFIID riid, void **ppv) -{ - HWCInPin *This = impl_from_IPin(iface); - - if (IsEqualIID(riid, &IID_IUnknown)) { - *ppv = (IUnknown *)(&This->IPin_iface); - IPin_AddRef((IPin *)*ppv); - } else if (IsEqualIID(riid, &IID_IPin)) { - *ppv = (IPin *)(&This->IPin_iface); - IPin_AddRef((IPin *)*ppv); - } else if (IsEqualIID(riid, &IID_IMemInputPin)) { - *ppv = (IMemInputPin *)(&This->IMemInputPin_iface); - IPin_AddRef((IMemInputPin *)*ppv); - } else { - *ppv = NULL; - return E_NOINTERFACE; - } - - return S_OK; -} - -static STDMETHODIMP_(ULONG) HWCPin_AddRef(IPin *iface) -{ - HWCInPin *This = impl_from_IPin(iface); - - return InterlockedIncrement(&This->m_cRef); -} - -static STDMETHODIMP_(ULONG) HWCPin_Release(IPin *iface) -{ - HWCInPin *This = impl_from_IPin(iface); - - if (InterlockedDecrement(&This->m_cRef) == 0) { - if (This->m_pCallback) { - SAFE_RELEASE(This->m_pCallback); - } - if (This->m_pConnectedPin) { - SAFE_RELEASE(This->m_pConnectedPin); - } - if (This->m_pAllocator) { - IMemAllocator_Decommit(This->m_pAllocator); - SAFE_RELEASE(This->m_pAllocator); - } - g_free((void *)This); - This = NULL; - return 0; - } - return This->m_cRef; -} - -static STDMETHODIMP HWCPin_Connect(IPin *iface, - IPin *pReceivePin, - const AM_MEDIA_TYPE *pmt) -{ - HWCInPin *This = impl_from_IPin(iface); - - if (!pReceivePin) { - return E_POINTER; - } - - if (This->m_pConnectedPin) { - return VFW_E_ALREADY_CONNECTED; - } - - if (!pmt) { - return S_OK; - } - return S_FALSE; -} - -static STDMETHODIMP HWCPin_ReceiveConnection(IPin *iface, IPin *pConnector, - const AM_MEDIA_TYPE *pmt) -{ - PIN_DIRECTION pd; - FILTER_STATE fs; - HWCInPin *This = impl_from_IPin(iface); - - if (pConnector == NULL || pmt == NULL) { - return E_POINTER; - } - - if (This->m_pConnectedPin) { - return VFW_E_ALREADY_CONNECTED; - } - IBaseFilter_GetState(This->m_pCFilter, 0, &fs); - if (fs != State_Stopped) { - return VFW_E_NOT_STOPPED; - } - IPin_QueryDirection(pConnector, &pd); - if (pd == PINDIR_INPUT) { - return VFW_E_INVALID_DIRECTION; - } - - This->m_pConnectedPin = pConnector; - IPin_AddRef(This->m_pConnectedPin); - return S_OK; -} - -static STDMETHODIMP HWCPin_Disconnect(IPin *iface) -{ - HWCInPin *This = impl_from_IPin(iface); - - HRESULT hr; - FILTER_STATE fs; - IBaseFilter_GetState(This->m_pCFilter, 0, &fs); - if (fs != State_Stopped) { - return VFW_E_NOT_STOPPED; - } - if (This->m_pConnectedPin == NULL) { - hr = S_FALSE; - } else { - if (This->m_pAllocator) { - hr = IMemAllocator_Decommit(This->m_pAllocator); - if (FAILED(hr)) { - return hr; - } - SAFE_RELEASE(This->m_pAllocator); - } - SAFE_RELEASE(This->m_pConnectedPin); - hr = S_OK; - } - return hr; -} - -static STDMETHODIMP HWCPin_ConnectedTo(IPin *iface, IPin **ppPin) -{ - HWCInPin *This = impl_from_IPin(iface); - - if (ppPin == NULL) { - return E_POINTER; - } - - if (This->m_pConnectedPin == NULL) { - *ppPin = NULL; - return VFW_E_NOT_CONNECTED; - } else { - *ppPin = This->m_pConnectedPin; - IPin_AddRef(This->m_pConnectedPin); - } - return S_OK; -} - -static STDMETHODIMP HWCPin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *pmt) -{ - if (pmt == NULL) { - return E_POINTER; - } - return VFW_E_NOT_CONNECTED; -} - -static STDMETHODIMP HWCPin_QueryPinInfo(IPin *iface, PIN_INFO *pInfo) -{ - HWCInPin *This = impl_from_IPin(iface); - - if (pInfo == NULL) { - return E_POINTER; - } - - pInfo->pFilter = This->m_pCFilter; - if (This->m_pCFilter) { - IBaseFilter_AddRef(This->m_pCFilter); - } - memcpy((void *)pInfo->achName, (void *)HWCPinName, sizeof(HWCPinName)); - pInfo->dir = PINDIR_INPUT; - return S_OK; -} - -static STDMETHODIMP HWCPin_QueryDirection(IPin *iface, PIN_DIRECTION *pPinDir) -{ - if (pPinDir == NULL) { - return E_POINTER; - } - *pPinDir = PINDIR_INPUT; - return S_OK; -} - -static STDMETHODIMP HWCPin_QueryId(IPin *iface, LPWSTR *Id) -{ - PVOID pId; - if (Id == NULL) { - return E_POINTER; - } - pId = CoTaskMemAlloc(sizeof(HWCPinName)); - memcpy((void *)pId, (void *)HWCPinName, sizeof(HWCPinName)); - *Id = (LPWSTR)pId; - return S_OK; -} - -static STDMETHODIMP HWCPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *pmt) -{ - if (pmt == NULL) { - return E_POINTER; - } - return S_OK; -} - -static STDMETHODIMP HWCPin_EnumMediaTypes(IPin *iface, - IEnumMediaTypes **ppEnum) -{ - if (ppEnum == NULL) { - return E_POINTER; - } - return E_NOTIMPL; -} - -static STDMETHODIMP HWCPin_QueryInternalConnections(IPin *iface, - IPin **ppPin, - ULONG *nPin) -{ - return E_NOTIMPL; -} - -static STDMETHODIMP HWCPin_EndOfStream(IPin *iface) -{ - return S_OK; -} - -static STDMETHODIMP HWCPin_BeginFlush(IPin *iface) -{ - return S_OK; -} - -static STDMETHODIMP HWCPin_EndFlush(IPin *iface) -{ - return S_OK; -} - -static STDMETHODIMP HWCPin_NewSegment(IPin *iface, REFERENCE_TIME tStart, - REFERENCE_TIME tStop, double dRate) -{ - return S_OK; -} - -static STDMETHODIMP HWCMemInputPin_QueryInterface(IMemInputPin *iface, - REFIID riid, void **ppv) -{ - HWCInPin *This = impl_from_IMemInputPin(iface); - - if (IsEqualIID(riid, &IID_IUnknown)) { - *ppv = (IUnknown *)(&This->IMemInputPin_iface); - IPin_AddRef((IPin *)*ppv); - } else if (IsEqualIID(riid, &IID_IPin)) { - *ppv = (IPin *)(&This->IPin_iface); - IPin_AddRef((IPin *)*ppv); - } else if (IsEqualIID(riid, &IID_IMemInputPin)) { - *ppv = (IMemInputPin *)(&This->IMemInputPin_iface); - IPin_AddRef((IMemInputPin *)*ppv); - } else { - *ppv = NULL; - return E_NOINTERFACE; - } - - return S_OK; -} - -static STDMETHODIMP_(ULONG) HWCMemInputPin_AddRef(IMemInputPin *iface) -{ - HWCInPin *This = impl_from_IMemInputPin(iface); - - return InterlockedIncrement(&This->m_cRef); -} - -static STDMETHODIMP_(ULONG) HWCMemInputPin_Release(IMemInputPin *iface) -{ - HWCInPin *This = impl_from_IMemInputPin(iface); - - if (InterlockedDecrement(&This->m_cRef) == 0) { - if (This->m_pCallback) { - SAFE_RELEASE(This->m_pCallback); - } - if (This->m_pConnectedPin) { - SAFE_RELEASE(This->m_pConnectedPin); - } - if (This->m_pAllocator) { - IMemAllocator_Decommit(This->m_pAllocator); - SAFE_RELEASE(This->m_pAllocator); - } - g_free((void *)This); - This = NULL; - return 0; - } - return This->m_cRef; -} - -static STDMETHODIMP HWCMemInputPin_GetAllocator(IMemInputPin *iface, - IMemAllocator **ppAllocator) -{ - HWCInPin *This = impl_from_IMemInputPin(iface); - - if (ppAllocator == NULL) { - return E_POINTER; - } - - if (This->m_pAllocator == NULL) { - HRESULT hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, - CLSCTX_INPROC_SERVER, - &IID_IMemAllocator, - (void **)&(This->m_pAllocator)); - if (FAILED(hr)) { - ERR("Failed to CoCreateInstance for retrieving MemoryAllocator\n"); - return hr; - } - } - assert(This->m_pAllocator != NULL); - *ppAllocator = This->m_pAllocator; - IMemAllocator_AddRef(This->m_pAllocator); - - return S_OK; -} - -static STDMETHODIMP HWCMemInputPin_NotifyAllocator(IMemInputPin *iface, - IMemAllocator *pAllocator, - BOOL bReadOnly) -{ - HWCInPin *This = impl_from_IMemInputPin(iface); - - if (pAllocator == NULL) { - return E_POINTER; - } - - IMemAllocator *pOldAllocator = This->m_pAllocator; - IMemAllocator_AddRef(pAllocator); - This->m_pAllocator = pAllocator; - - if (pOldAllocator != NULL) { - SAFE_RELEASE(pOldAllocator); - } - - This->m_bReadOnly = bReadOnly; - - return S_OK; -} - -static STDMETHODIMP HWCMemInputPin_GetAllocatorRequirements( - IMemInputPin *iface, - ALLOCATOR_PROPERTIES *pProps) -{ - return E_NOTIMPL; -} - -static STDMETHODIMP HWCMemInputPin_Receive(IMemInputPin *iface, - IMediaSample *pSample) -{ - HWCInPin *This = impl_from_IMemInputPin(iface); - - if (pSample == NULL) { - ERR("pSample is NULL\n"); - return E_POINTER; - } - if (This->m_pCallback != NULL) { - HRESULT hr; - BYTE *pBuffer = NULL; - DWORD dwSize = 0; - dwSize = IMediaSample_GetSize(pSample); - hr = IMediaSample_GetPointer(pSample, &pBuffer); - if (FAILED(hr)) { - ERR("Receive function : " - "failed to IMediaSample_GetPointer, 0x%ld\n", hr); - return hr; - } - hr = IGrabCallback_Grab(This->m_pCallback, dwSize, pBuffer); - if (FAILED(hr)) { - ERR("Receive function : failed to IGrabCallback_Grab, 0x%ld\n", - hr); - return hr; - } - } - return S_OK; -} - -static STDMETHODIMP HWCMemInputPin_ReceiveMultiple(IMemInputPin *iface, - IMediaSample **pSamples, - long nSamples, - long *nSamplesProcessed) -{ - HRESULT hr = S_OK; - - if (pSamples == NULL) { - return E_POINTER; - } - - *nSamplesProcessed = 0; - - while (nSamples-- > 0) { - hr = IMemInputPin_Receive(iface, pSamples[*nSamplesProcessed]); - if (hr != S_OK) { - break; - } - (*nSamplesProcessed)++; - } - return hr; -} - -static STDMETHODIMP HWCMemInputPin_ReceiveCanBlock(IMemInputPin *iface) -{ - return S_FALSE; -} - -static STDMETHODIMP HWCPin_SetCallback(IPin *iface, IGrabCallback *pCaptureCB) -{ - HWCInPin *This = impl_from_IPin(iface); - - if (pCaptureCB == NULL) { - SAFE_RELEASE(This->m_pCallback); - } else { - This->m_pCallback = pCaptureCB; - IGrabCallback_AddRef(This->m_pCallback); - } - - return S_OK; -} - - -static IPinVtbl HWCPin_Vtbl = { - HWCPin_QueryInterface, - HWCPin_AddRef, - HWCPin_Release, - HWCPin_Connect, - HWCPin_ReceiveConnection, - HWCPin_Disconnect, - HWCPin_ConnectedTo, - HWCPin_ConnectionMediaType, - HWCPin_QueryPinInfo, - HWCPin_QueryDirection, - HWCPin_QueryId, - HWCPin_QueryAccept, - HWCPin_EnumMediaTypes, - HWCPin_QueryInternalConnections, - HWCPin_EndOfStream, - HWCPin_BeginFlush, - HWCPin_EndFlush, - HWCPin_NewSegment -}; - -static IMemInputPinVtbl HWCMemInputPin_Vtbl = { - HWCMemInputPin_QueryInterface, - HWCMemInputPin_AddRef, - HWCMemInputPin_Release, - HWCMemInputPin_GetAllocator, - HWCMemInputPin_NotifyAllocator, - HWCMemInputPin_GetAllocatorRequirements, - HWCMemInputPin_Receive, - HWCMemInputPin_ReceiveMultiple, - HWCMemInputPin_ReceiveCanBlock -}; - -static STDMETHODIMP HWCInPin_Construct(IBaseFilter *pFilter, IPin **ppv) -{ - HWCInPin *This = (HWCInPin *)g_malloc0(sizeof(HWCInPin)); - - if (!This) { - ERR("failed to HWCInPin_Construct, E_OUTOFMEMORY\n"); - return E_OUTOFMEMORY; - } - - This->IPin_iface.lpVtbl = &HWCPin_Vtbl; - This->IMemInputPin_iface.lpVtbl = &HWCMemInputPin_Vtbl; - This->m_bReadOnly = FALSE; - This->m_pCFilter = pFilter; - This->m_pConnectedPin = NULL; - This->m_pCallback = NULL; - This->m_pAllocator = NULL; - This->m_cRef = 1; - This->SetGrabCallbackIF = HWCPin_SetCallback; - *ppv = &This->IPin_iface; - - return S_OK; -} - -/* - * HWCEnumPins - */ - -typedef struct HWCEnumPins { - IEnumPins IEnumPins_iface; - IBaseFilter *m_pFilter; - int m_nPos; - long m_cRef; -} HWCEnumPins; - -static inline HWCEnumPins *impl_from_IEnumPins(IEnumPins *iface) -{ - return CONTAINING_RECORD(iface, HWCEnumPins, IEnumPins_iface); -} - -static STDMETHODIMP HWCEnumPins_QueryInterface(IEnumPins *iface, - REFIID riid, void **ppv) -{ - if (ppv == NULL) { - return E_POINTER; - } - - if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumPins)) { - *ppv = iface; - } else { - *ppv = NULL; - return E_NOINTERFACE; - } - - IEnumPins_AddRef(iface); - return S_OK; -} - -static STDMETHODIMP_(ULONG) HWCEnumPins_AddRef(IEnumPins *iface) -{ - HWCEnumPins *This = impl_from_IEnumPins(iface); - - return InterlockedIncrement(&This->m_cRef); -} - -static STDMETHODIMP_(ULONG) HWCEnumPins_Release(IEnumPins *iface) -{ - HWCEnumPins *This = impl_from_IEnumPins(iface); - - if (InterlockedDecrement(&This->m_cRef) == 0) { - if (This->m_pFilter) { - SAFE_RELEASE(This->m_pFilter); - } - This->m_nPos = 0; - g_free((void *)This); - This = NULL; - return 0; - } - return This->m_cRef; -} - -static STDMETHODIMP HWCEnumPins_Next(IEnumPins *iface, ULONG cPins, - IPin **ppPins, ULONG *pcFetched) -{ - ULONG fetched; - HWCEnumPins *This = impl_from_IEnumPins(iface); - - if (ppPins == NULL) { - return E_POINTER; - } - - if (This->m_nPos < 1 && cPins > 0) { - IPin *pPin; - IBaseFilter_FindPin(This->m_pFilter, HWCPinName, &pPin); - *ppPins = pPin; - fetched = 1; - This->m_nPos++; - } else { - fetched = 0; - } - - if (pcFetched != NULL) { - *pcFetched = fetched; - } - - return (fetched == cPins) ? S_OK : S_FALSE; -} - -static STDMETHODIMP HWCEnumPins_Skip(IEnumPins *iface, ULONG cPins) -{ - HWCEnumPins *This = impl_from_IEnumPins(iface); - This->m_nPos += cPins; - return (This->m_nPos >= 1) ? S_FALSE : S_OK; -} - -static STDMETHODIMP HWCEnumPins_Reset(IEnumPins *iface) -{ - HWCEnumPins *This = impl_from_IEnumPins(iface); - This->m_nPos = 0; - return S_OK; -} - -static STDMETHODIMP HWCEnumPins_Construct(IBaseFilter *pFilter, - int nPos, IEnumPins **ppv); - -static STDMETHODIMP HWCEnumPins_Clone(IEnumPins *iface, IEnumPins **ppEnum) -{ - HWCEnumPins *This = impl_from_IEnumPins(iface); - - if (ppEnum == NULL) { - return E_POINTER; - } - - HWCEnumPins_Construct(This->m_pFilter, This->m_nPos, ppEnum); - if (*ppEnum == NULL) { - ERR("failed to HWCEnumPins_Construct in clone, E_OUTOFMEMORY\n"); - return E_OUTOFMEMORY; - } - - return S_OK; -} - -static IEnumPinsVtbl HWCEnumPins_Vtbl = { - HWCEnumPins_QueryInterface, - HWCEnumPins_AddRef, - HWCEnumPins_Release, - HWCEnumPins_Next, - HWCEnumPins_Skip, - HWCEnumPins_Reset, - HWCEnumPins_Clone -}; - - -static STDMETHODIMP HWCEnumPins_Construct(IBaseFilter *pFilter, - int nPos, IEnumPins **ppv) -{ - HWCEnumPins *This = (HWCEnumPins *)g_malloc0(sizeof(HWCEnumPins)); - - if (!This) { - ERR("failed to HWCEnumPins_Construct, E_OUTOFMEMORY\n"); - return E_OUTOFMEMORY; - } - - This->IEnumPins_iface.lpVtbl = &HWCEnumPins_Vtbl; - This->m_pFilter = pFilter; - if (This->m_pFilter) { - IBaseFilter_AddRef(This->m_pFilter); - } - This->m_cRef = 1; - This->m_nPos = nPos; - *ppv = &This->IEnumPins_iface; - - return S_OK; -} - -/* - * HWCFilter - */ - -typedef struct HWCFilter { - IBaseFilter IBaseFilter_iface; - IPin *m_pPin; - IFilterGraph *m_pFilterGraph; - FILTER_STATE m_state; - long m_cRef; -} HWCFilter; - -static inline HWCFilter *impl_from_IBaseFilter(IBaseFilter *iface) -{ - return CONTAINING_RECORD(iface, HWCFilter, IBaseFilter_iface); -} - -static STDMETHODIMP HWCFilter_QueryInterface(IBaseFilter *iface, - REFIID riid, void **ppv) -{ - if (IsEqualIID(riid, &IID_IUnknown)) { - *ppv = (IUnknown *)iface; - } else if (IsEqualIID(riid, &IID_IPersist)) { - *ppv = (IPersist *)iface; - } else if (IsEqualIID(riid, &IID_IMediaFilter)) { - *ppv = (IMediaFilter *)iface; - } else if (IsEqualIID(riid, &IID_IBaseFilter)) { - *ppv = (IBaseFilter *)iface; - } else { - *ppv = NULL; - return E_NOINTERFACE; - } - - IBaseFilter_AddRef(iface); - return S_OK; -} - -static STDMETHODIMP_(ULONG) HWCFilter_AddRef(IBaseFilter *iface) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - - return InterlockedIncrement(&This->m_cRef); -} - -static STDMETHODIMP_(ULONG) HWCFilter_Release(IBaseFilter *iface) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - - if (InterlockedDecrement(&This->m_cRef) == 0) { - if (This->m_pPin) { - SAFE_RELEASE(This->m_pPin); - } - g_free((void *)This); - This = NULL; - return 0; - } - return This->m_cRef; -} - -static STDMETHODIMP HWCFilter_GetClassID(IBaseFilter *iface, CLSID *pClsID) -{ - if (pClsID == NULL) { - return E_POINTER; - } - return E_NOTIMPL; -} - -static STDMETHODIMP HWCFilter_GetState(IBaseFilter *iface, DWORD dwMSecs, - FILTER_STATE *State) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - *State = This->m_state; - return S_OK; -} - -static STDMETHODIMP HWCFilter_SetSyncSource(IBaseFilter *iface, - IReferenceClock *pClock) -{ - return S_OK; -} - -static STDMETHODIMP HWCFilter_GetSyncSource(IBaseFilter *iface, - IReferenceClock **pClock) -{ - *pClock = NULL; - return S_OK; -} - -static STDMETHODIMP HWCFilter_Stop(IBaseFilter *iface) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - - IPin_EndFlush(This->m_pPin); - This->m_state = State_Stopped; - return S_OK; -} - -static STDMETHODIMP HWCFilter_Pause(IBaseFilter *iface) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - This->m_state = State_Paused; - return S_OK; -} - -static STDMETHODIMP HWCFilter_Run(IBaseFilter *iface, REFERENCE_TIME tStart) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - - if (This->m_state == State_Stopped) { - HRESULT hr; - hr = IBaseFilter_Pause(iface); - if (FAILED(hr)) { - ERR("HWCFilter_Run : Failed to IBaseFilter_Pause, ret=0xld%\n", hr); - return hr; - } - } - - This->m_state = State_Running; - return S_OK; -} - -static STDMETHODIMP HWCFilter_EnumPins(IBaseFilter *iface, IEnumPins **ppEnum) -{ - if (ppEnum == NULL) { - return E_POINTER; - } - - HWCEnumPins_Construct(iface, 0, ppEnum); - return *ppEnum == NULL ? E_OUTOFMEMORY : S_OK; -} - -static STDMETHODIMP HWCFilter_FindPin(IBaseFilter *iface, LPCWSTR Id, - IPin **ppPin) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - - if (ppPin == NULL) { - return E_POINTER; - } - - if (memcmp((void *)Id, (void *)HWCPinName, sizeof(HWCPinName))) { - return VFW_E_NOT_FOUND; - } - - if (!This->m_pPin) { - HWCInPin_Construct(iface, &This->m_pPin); - } - *ppPin = This->m_pPin; - - IPin_AddRef(This->m_pPin); - return S_OK; -} - -static STDMETHODIMP HWCFilter_QueryFilterInfo(IBaseFilter *iface, - FILTER_INFO *pInfo) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - - if (pInfo == NULL) { - return E_POINTER; - } - - memcpy((void *)pInfo->achName, - (void *)HWCFilterName, - sizeof(HWCFilterName)); - pInfo->pGraph = This->m_pFilterGraph; - if (This->m_pFilterGraph) { - IFilterGraph_AddRef(This->m_pFilterGraph); - } - return S_OK; -} - -static STDMETHODIMP HWCFilter_JoinFilterGraph(IBaseFilter *iface, - IFilterGraph *pGraph, - LPCWSTR pName) -{ - HWCFilter *This = impl_from_IBaseFilter(iface); - - This->m_pFilterGraph = pGraph; - return S_OK; -} - -static STDMETHODIMP HWCFilter_QueryVendorInfo(IBaseFilter *iface, - LPWSTR *pVendorInfo) -{ - return E_NOTIMPL; -} - -static IBaseFilterVtbl HWCFilter_Vtbl = { - HWCFilter_QueryInterface, - HWCFilter_AddRef, - HWCFilter_Release, - HWCFilter_GetClassID, - HWCFilter_Stop, - HWCFilter_Pause, - HWCFilter_Run, - HWCFilter_GetState, - HWCFilter_SetSyncSource, - HWCFilter_GetSyncSource, - HWCFilter_EnumPins, - HWCFilter_FindPin, - HWCFilter_QueryFilterInfo, - HWCFilter_JoinFilterGraph, - HWCFilter_QueryVendorInfo -}; - -static STDMETHODIMP HWCFilter_Construct(IBaseFilter **ppv) -{ - HWCFilter *This = (HWCFilter *)g_malloc0(sizeof(HWCFilter)); - - if (!This) { - ERR("failed to HWCFilter_Construct, E_OUTOFMEMORY\n"); - return E_OUTOFMEMORY; - } - - This->IBaseFilter_iface.lpVtbl = &HWCFilter_Vtbl; - This->m_pFilterGraph = NULL; - This->m_state = State_Stopped; - This->m_cRef = 1; - HWCInPin_Construct(&This->IBaseFilter_iface, &This->m_pPin); - *ppv = &This->IBaseFilter_iface; - - return S_OK; -} - -/********************************************************** - * - * Virtual device implementations - * - **********************************************************/ - - -/* - * Declaration global variables for Win32 COM Interfaces - */ -IGraphBuilder *g_pGB ; -ICaptureGraphBuilder2 *g_pCGB; -IMediaControl *g_pMediaControl; - -IPin *g_pOutputPin; -IPin *g_pInputPin; -IBaseFilter *g_pDstFilter; -IBaseFilter *g_pSrcFilter; - -IGrabCallback *g_pCallback; - -/* V4L2 defines copy from videodev2.h */ -#define V4L2_CTRL_FLAG_SLIDER 0x0020 - -#define V4L2_CTRL_CLASS_USER 0x00980000 -#define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900) -#define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE+0) -#define V4L2_CID_CONTRAST (V4L2_CID_BASE+1) -#define V4L2_CID_SATURATION (V4L2_CID_BASE+2) -#define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27) - -#define V4L2_PIX_FMT_YUYV MAKEFOURCC('Y', 'U', 'Y', 'V') /* 16 YUV 4:2:2 */ -#define V4L2_PIX_FMT_YUV420 MAKEFOURCC('Y', 'U', '1', '2') /* 12 YUV 4:2:0 */ -#define V4L2_PIX_FMT_YVU420 MAKEFOURCC('Y', 'V', '1', '2') /* 12 YVU 4:2:0 */ -#define V4L2_PIX_FMT_RGB24 MAKEFOURCC('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */ - -typedef struct tagMaruCamConvertPixfmt { - uint32_t fmt; /* fourcc */ - uint32_t bpp; /* bits per pixel, 0 for compressed formats */ - uint32_t needs_conversion; -} MaruCamConvertPixfmt; - -static MaruCamConvertPixfmt supported_dst_pixfmts[] = { - { V4L2_PIX_FMT_YUYV, 16, 0 }, - { V4L2_PIX_FMT_YUV420, 12, 0 }, - { V4L2_PIX_FMT_YVU420, 12, 0 }, -}; - -typedef struct tagMaruCamConvertFrameInfo { - uint32_t width; - uint32_t height; -} MaruCamConvertFrameInfo; - -static MaruCamConvertFrameInfo supported_dst_frames[] = { - { 640, 480 }, - { 352, 288 }, - { 320, 240 }, - { 176, 144 }, - { 160, 120 }, -}; - -#define MARUCAM_CTRL_VALUE_MAX 20 -#define MARUCAM_CTRL_VALUE_MIN 1 -#define MARUCAM_CTRL_VALUE_MID 10 -#define MARUCAM_CTRL_VALUE_STEP 1 - -struct marucam_qctrl { - uint32_t id; - uint32_t hit; - long min; - long max; - long step; - long init_val; -}; - -static struct marucam_qctrl qctrl_tbl[] = { - { V4L2_CID_BRIGHTNESS, 0, }, - { V4L2_CID_CONTRAST, 0, }, - { V4L2_CID_SATURATION, 0, }, - { V4L2_CID_SHARPNESS, 0, }, -}; - -static MaruCamState *g_state; - -static uint32_t ready_count; -static uint32_t cur_fmt_idx; -static uint32_t cur_frame_idx; -static void *grab_buf; -static uint32_t g_dwSrcFmt; - - -/* - * Helper functions - converting image formats, converting values - */ - -static uint32_t get_bytesperline(uint32_t pixfmt, uint32_t width) -{ - uint32_t bytesperline; - - switch (pixfmt) { - case V4L2_PIX_FMT_YUV420: - case V4L2_PIX_FMT_YVU420: - bytesperline = (width * 12) >> 3; - break; - case V4L2_PIX_FMT_YUYV: - default: - bytesperline = width * 2; - break; - } - - return bytesperline; -} - -static uint32_t get_sizeimage(uint32_t pixfmt, uint32_t width, uint32_t height) -{ - return get_bytesperline(pixfmt, width) * height; -} - -void yuyv_to_yuv420(const unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height, uint32_t yvu); -void rgb24_to_yuv420(const unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height, uint32_t yvu); -void rgb24_to_yuyv(unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height); -void yuv420_to_yvu420(unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height); -void yuv420_to_yuyv(unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height); - -static long value_convert_from_guest(long min, long max, long value) -{ - double rate = 0.0; - long dist = 0, ret = 0; - - dist = max - min; - - if (dist < MARUCAM_CTRL_VALUE_MAX) { - rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; - ret = min + (int32_t)(value / rate); - } else { - rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; - ret = min + (int32_t)(rate * value); - } - return ret; -} - -static long value_convert_to_guest(long min, long max, long value) -{ - double rate = 0.0; - long dist = 0, ret = 0; - - dist = max - min; - - if (dist < MARUCAM_CTRL_VALUE_MAX) { - rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist; - ret = (int32_t)((double)(value - min) * rate); - } else { - rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX; - ret = (int32_t)((double)(value - min) / rate); - } - - return ret; -} - -/* - * Callback function for grab frames - */ -static STDMETHODIMP marucam_device_callbackfn(ULONG dwSize, BYTE *pBuffer) -{ - void *tmp_buf; - uint32_t width, height, fmt, imgsize; - - width = supported_dst_frames[cur_frame_idx].width; - height = supported_dst_frames[cur_frame_idx].height; - fmt = supported_dst_pixfmts[cur_fmt_idx].fmt; - imgsize = get_sizeimage(fmt, width, height); - - if (imgsize > (uint32_t)dwSize) { - ERR("Image size is mismatched\n"); - return E_FAIL; - } - - switch (g_dwSrcFmt) { - case V4L2_PIX_FMT_YUYV: - switch (fmt) { - case V4L2_PIX_FMT_YUV420: - yuyv_to_yuv420(pBuffer, grab_buf, width, height, 0); - break; - case V4L2_PIX_FMT_YVU420: - yuyv_to_yuv420(pBuffer, grab_buf, width, height, 1); - break; - case V4L2_PIX_FMT_YUYV: - memcpy(grab_buf, (void *)pBuffer, (size_t)dwSize); - break; - default: - ERR("Invalid pixel format\n"); - return E_FAIL; - } - break; - case V4L2_PIX_FMT_RGB24: - switch (fmt) { - case V4L2_PIX_FMT_YUV420: - rgb24_to_yuv420(pBuffer, grab_buf, width, height, 0); - break; - case V4L2_PIX_FMT_YVU420: - rgb24_to_yuv420(pBuffer, grab_buf, width, height, 1); - break; - case V4L2_PIX_FMT_YUYV: - rgb24_to_yuyv(pBuffer, grab_buf, width, height); - break; - default: - ERR("Invalid pixel format\n"); - return E_FAIL; - } - break; - case V4L2_PIX_FMT_YUV420: - switch (fmt) { - case V4L2_PIX_FMT_YUV420: - memcpy(grab_buf, (void *)pBuffer, (size_t)dwSize); - break; - case V4L2_PIX_FMT_YVU420: - yuv420_to_yvu420(pBuffer, grab_buf, width, height); - break; - case V4L2_PIX_FMT_YUYV: - yuv420_to_yuyv(pBuffer, grab_buf, width, height); - break; - default: - ERR("Invalid pixel format\n"); - return E_FAIL; - } - break; - default: - ERR("Invalid pixel format\n"); - return E_FAIL; - } - - qemu_mutex_lock(&g_state->thread_mutex); - if (g_state->streamon) { - if (ready_count < MARUCAM_SKIPFRAMES) { - /* skip a frame cause first some frame are distorted */ - ++ready_count; - TRACE("skip %d frame\n", ready_count); - qemu_mutex_unlock(&g_state->thread_mutex); - return S_OK; - } - if (g_state->req_frame == 0) { - TRACE("there is no request\n"); - qemu_mutex_unlock(&g_state->thread_mutex); - return S_OK; - } - tmp_buf = g_state->vaddr + g_state->buf_size * (g_state->req_frame - 1); - memcpy(tmp_buf, grab_buf, g_state->buf_size); - g_state->req_frame = 0; /* clear request */ - g_state->isr |= 0x01; /* set a flag of rasing a interrupt */ - qemu_bh_schedule(g_state->tx_bh); - } - qemu_mutex_unlock(&g_state->thread_mutex); - return S_OK; -} - -/* - * Internal functions for manipulate interfaces - */ - -static STDMETHODIMP_(void) CloseInterfaces(void) -{ - if (g_pMediaControl) { - g_pMediaControl->lpVtbl->Stop(g_pMediaControl); - } - - if (g_pOutputPin) { - g_pOutputPin->lpVtbl->Disconnect(g_pOutputPin); - } - - SAFE_RELEASE(g_pGB); - SAFE_RELEASE(g_pCGB); - SAFE_RELEASE(g_pMediaControl); - SAFE_RELEASE(g_pOutputPin); - SAFE_RELEASE(g_pInputPin); - SAFE_RELEASE(g_pDstFilter); - SAFE_RELEASE(g_pSrcFilter); - SAFE_RELEASE(g_pCallback); -} - -static STDMETHODIMP_(void) DeleteMediaType(AM_MEDIA_TYPE *pmt) -{ - if (pmt == NULL) { - return; - } - - if (pmt->cbFormat != 0) { - CoTaskMemFree((PVOID)pmt->pbFormat); - pmt->cbFormat = 0; - pmt->pbFormat = NULL; - } - if (pmt->pUnk != NULL) { - pmt->pUnk->lpVtbl->Release(pmt->pUnk); - pmt->pUnk = NULL; - } - - CoTaskMemFree((PVOID)pmt); -} - -static STDMETHODIMP GetPin(IBaseFilter *pFilter, - PIN_DIRECTION PinDir, IPin **ppPin) -{ - HRESULT hr; - IEnumPins *pEnum = NULL; - IPin *pPin = NULL; - - if (ppPin == NULL) { - return E_POINTER; - } - - hr = pFilter->lpVtbl->EnumPins(pFilter, &pEnum); - if (FAILED(hr)) { - return hr; - } - - while (pEnum->lpVtbl->Next(pEnum, 1, &pPin, 0) == S_OK) { - PIN_DIRECTION PinDirThis; - hr = pPin->lpVtbl->QueryDirection(pPin, &PinDirThis); - if (FAILED(hr)) { - SAFE_RELEASE(pPin); - SAFE_RELEASE(pEnum); - return hr; - } - if (PinDir == PinDirThis) { - *ppPin = pPin; - SAFE_RELEASE(pEnum); - return S_OK; - } - SAFE_RELEASE(pPin); - } - - SAFE_RELEASE(pEnum); - return S_FALSE; -} - -static STDMETHODIMP GraphBuilder_Init(void) -{ - HRESULT hr; - - hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC, - &IID_IGraphBuilder, (void **)&g_pGB); - if (FAILED(hr)) { - ERR("Failed to create instance of GraphBuilder, 0x%x\n", hr); - return hr; - } - - hr = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, - &IID_ICaptureGraphBuilder2, (void **)&g_pCGB); - if (FAILED(hr)) { - ERR("Failed to create instance of CaptureGraphBuilder2, 0x%x\n", hr); - return hr; - } - - hr = g_pCGB->lpVtbl->SetFiltergraph(g_pCGB, g_pGB); - if (FAILED(hr)) { - ERR("Failed to SetFiltergraph, 0x%x\n", hr); - return hr; - } - - hr = g_pGB->lpVtbl->QueryInterface(g_pGB, &IID_IMediaControl, - (void **)&g_pMediaControl); - if (FAILED(hr)) { - ERR("Failed to QueryInterface for IMediaControl, 0x%x\n", hr); - return hr; - } - - hr = HWCGrabCallback_Construct(&g_pCallback); - if (g_pCallback == NULL) { - hr = E_OUTOFMEMORY; - } - - hr = ((HWCGrabCallback *)g_pCallback)->SetCallback(g_pCallback, - (CallbackFn)marucam_device_callbackfn); - - return hr; -} - -static STDMETHODIMP BindSourceFilter(void) -{ - HRESULT hr; - ICreateDevEnum *pCreateDevEnum = NULL; - IEnumMoniker *pEnumMK = NULL; - IMoniker *pMoniKer; - - hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, - &IID_ICreateDevEnum, - (void **)&pCreateDevEnum); - if (FAILED(hr)) { - ERR("Failed to create instance of CreateDevEnum, 0x%x\n", hr); - return hr; - } - - hr = pCreateDevEnum->lpVtbl->CreateClassEnumerator(pCreateDevEnum, - &CLSID_VideoInputDeviceCategory, - &pEnumMK, 0); - if (FAILED(hr)) { - ERR("Failed to get VideoInputDeviceCategory, 0x%x\n", hr); - SAFE_RELEASE(pCreateDevEnum); - return hr; - } - - if (!pEnumMK) { - ERR("ClassEnumerator moniker is NULL\n"); - SAFE_RELEASE(pCreateDevEnum); - return E_FAIL; - } - pEnumMK->lpVtbl->Reset(pEnumMK); - - hr = pEnumMK->lpVtbl->Next(pEnumMK, 1, &pMoniKer, NULL); - if (hr == S_FALSE) { - hr = E_FAIL; - } - if (SUCCEEDED(hr)) { - IPropertyBag *pBag = NULL; - hr = pMoniKer->lpVtbl->BindToStorage(pMoniKer, 0, 0, - &IID_IPropertyBag, - (void **)&pBag); - if (SUCCEEDED(hr)) { - VARIANT var; - var.vt = VT_BSTR; - hr = pBag->lpVtbl->Read(pBag, L"FriendlyName", &var, NULL); - if (hr == NOERROR) { - hr = pMoniKer->lpVtbl->BindToObject(pMoniKer, NULL, NULL, - &IID_IBaseFilter, - (void **)&g_pSrcFilter); - if (FAILED(hr)) { - ERR("Counldn't bind moniker to filter object!!\n"); - } else { - g_pSrcFilter->lpVtbl->AddRef(g_pSrcFilter); - } - SysFreeString(var.bstrVal); - } - SAFE_RELEASE(pBag); - } - SAFE_RELEASE(pMoniKer); - } - - if (SUCCEEDED(hr)) { - hr = g_pGB->lpVtbl->AddFilter(g_pGB, g_pSrcFilter, L"Video Capture"); - if (hr != S_OK && hr != S_FALSE) { - ERR("Counldn't add Video Capture filter to our graph!\n"); - SAFE_RELEASE(g_pSrcFilter); - } - } - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - - return hr; -} - -static STDMETHODIMP BindTargetFilter(void) -{ - HRESULT hr; - hr = HWCFilter_Construct(&g_pDstFilter); - - if (SUCCEEDED(hr) && g_pDstFilter) { - hr = g_pGB->lpVtbl->AddFilter(g_pGB, g_pDstFilter, L"HWCFilter"); - if (FAILED(hr)) { - ERR("Counldn't add HWCFilterr to our graph!\n"); - SAFE_RELEASE(g_pDstFilter); - } - } - return hr; -} - -static STDMETHODIMP ConnectFilters(void) -{ - HRESULT hr; - - hr = GetPin(g_pSrcFilter, PINDIR_OUTPUT , &g_pOutputPin); - if (FAILED(hr)) { - ERR("Failed to get output pin. 0x%x\n", hr); - return hr; - } - - hr = GetPin(g_pDstFilter, PINDIR_INPUT , &g_pInputPin); - if (FAILED(hr)) { - ERR("Failed to get input pin. 0x%x\n", hr); - return hr; - } - - hr = g_pGB->lpVtbl->Connect(g_pGB, g_pOutputPin, g_pInputPin); - if (FAILED(hr)) { - ERR("Failed to connect pins. 0x%x\n", hr); - } - return hr; -} - -static STDMETHODIMP DisconnectPins(void) -{ - HRESULT hr; - - hr = g_pGB->lpVtbl->Disconnect(g_pGB, g_pOutputPin); - if (FAILED(hr)) { - ERR("Failed to disconnect output pin. 0x%x\n", hr); - return hr; - } - - hr = g_pGB->lpVtbl->Disconnect(g_pGB, g_pInputPin); - if (FAILED(hr)) { - ERR("Failed to disconnect input pin. 0x%x\n", hr); - } - - return hr; -} - -static STDMETHODIMP RemoveFilters(void) -{ - HRESULT hr; - - hr = g_pGB->lpVtbl->RemoveFilter(g_pGB, g_pSrcFilter); - if (FAILED(hr)) { - ERR("Failed to remove source filer. 0x%x\n", hr); - return hr; - } - - hr = g_pGB->lpVtbl->RemoveFilter(g_pGB, g_pDstFilter); - if (FAILED(hr)) { - ERR("Failed to remove destination filer. 0x%x\n", hr); - } - - return hr; -} - -/* default fps is 15 */ -#define MARUCAM_DEFAULT_FRAMEINTERVAL 666666 - -static STDMETHODIMP SetFormat(uint32_t dwWidth, uint32_t dwHeight, - uint32_t dwDstFmt, uint32_t *dwSrcFmt) -{ - HRESULT hr; - IAMStreamConfig *pSConfig; - int iCount = 0, iSize = 0; - DWORD dwYUY2 = MAKEFOURCC('Y', 'U', 'Y', '2'); - DWORD dwI420 = MAKEFOURCC('I', '4', '2', '0'); - - if (dwSrcFmt == NULL) { - ERR("invalid the source format pointer\n"); - return E_FAIL; - } - - hr = g_pCGB->lpVtbl->FindInterface(g_pCGB, &PIN_CATEGORY_CAPTURE, 0, - g_pSrcFilter, &IID_IAMStreamConfig, - (void **)&pSConfig); - if (FAILED(hr)) { - ERR("failed to FindInterface method\n"); - return hr; - } - - hr = pSConfig->lpVtbl->GetNumberOfCapabilities(pSConfig, &iCount, &iSize); - if (FAILED(hr)) { - ERR("failed to GetNumberOfCapabilities method\n"); - SAFE_RELEASE(pSConfig); - return hr; - } - - if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) { - int iFormat = 0; - for (iFormat = 0; iFormat < iCount; iFormat++) { - VIDEO_STREAM_CONFIG_CAPS scc; - AM_MEDIA_TYPE *pmtConfig; - - hr = pSConfig->lpVtbl->GetStreamCaps(pSConfig, iFormat, - &pmtConfig, (BYTE *)&scc); - if (hr == S_OK) { - if (IsEqualIID(&pmtConfig->formattype, &FORMAT_VideoInfo)) { - VIDEOINFOHEADER *pvi = - (VIDEOINFOHEADER *)pmtConfig->pbFormat; - if ((pvi->bmiHeader.biWidth == (LONG)dwWidth) && - (pvi->bmiHeader.biHeight == (LONG)dwHeight)) { - if (pvi->bmiHeader.biCompression == dwYUY2) { - *dwSrcFmt = V4L2_PIX_FMT_YUYV; - } else if ((pvi->bmiHeader.biCompression == BI_RGB) && - (pvi->bmiHeader.biBitCount == 24)) { - *dwSrcFmt = V4L2_PIX_FMT_RGB24; - } else if (pvi->bmiHeader.biCompression == dwI420) { - *dwSrcFmt = V4L2_PIX_FMT_YUV420; - } else { /* not support format */ - DeleteMediaType(pmtConfig); - continue; - } - /* use minimum FPS(maximum frameinterval) - with non-VT system */ -#ifdef CONFIG_HAX - if (!hax_enabled()) { - pvi->AvgTimePerFrame = - (REFERENCE_TIME)scc.MaxFrameInterval; - } else { - pvi->AvgTimePerFrame = - (REFERENCE_TIME)MARUCAM_DEFAULT_FRAMEINTERVAL; - } -#else - pvi->AvgTimePerFrame = - (REFERENCE_TIME)scc.MaxFrameInterval; -#endif - hr = pSConfig->lpVtbl->SetFormat(pSConfig, pmtConfig); - DeleteMediaType(pmtConfig); - break; - } - } - DeleteMediaType(pmtConfig); - } - } - if (iFormat >= iCount) { - ERR("Failed to Set format. " - "Maybe connected webcam does not support the (%ldx%ld) " - "resolution or image formats(YUY2, RGB24, I420).\n", - dwWidth, dwHeight); - hr = E_FAIL; - } - } - SAFE_RELEASE(pSConfig); - return hr; -} - -static STDMETHODIMP QueryVideoProcAmp(long nProperty, long *pMin, long *pMax, - long *pStep, long *pDefault) -{ - HRESULT hr; - long Flags; - IAMVideoProcAmp *pProcAmp = NULL; - - hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter, - &IID_IAMVideoProcAmp, - (void **)&pProcAmp); - if (FAILED(hr)) { - return hr; - } - - hr = pProcAmp->lpVtbl->GetRange(pProcAmp, nProperty, pMin, pMax, - pStep, pDefault, &Flags); - - SAFE_RELEASE(pProcAmp); - return hr; -} - -static STDMETHODIMP GetVideoProcAmp(long nProperty, long *pValue) -{ - HRESULT hr; - long Flags; - IAMVideoProcAmp *pProcAmp = NULL; - - hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter, - &IID_IAMVideoProcAmp, - (void **)&pProcAmp); - if (FAILED(hr)) { - return hr; - } - - hr = pProcAmp->lpVtbl->Get(pProcAmp, nProperty, pValue, &Flags); - if (FAILED(hr)) { - ERR("Failed to get property for video\n"); - } - - SAFE_RELEASE(pProcAmp); - return hr; -} - -static STDMETHODIMP SetVideoProcAmp(long nProperty, long value) -{ - HRESULT hr; - - IAMVideoProcAmp *pProcAmp = NULL; - hr = g_pSrcFilter->lpVtbl->QueryInterface(g_pSrcFilter, - &IID_IAMVideoProcAmp, - (void **)&pProcAmp); - if (FAILED(hr)) { - return hr; - } - - hr = pProcAmp->lpVtbl->Set(pProcAmp, nProperty, value, - VideoProcAmp_Flags_Manual); - if (FAILED(hr)) { - ERR("Failed to set property for video\n"); - } - SAFE_RELEASE(pProcAmp); - return hr; -} - -static char *__wchar_to_char(const WCHAR *pwstr) -{ - char *pstr = NULL; - int len = 0; - - len = wcslen(pwstr) + 1; - pstr = (char *)g_malloc0(sizeof(char) * len); - wcstombs(pstr, pwstr, len + 1); - - return pstr; -} - -int marucam_device_check(int log_flag) -{ - struct timeval t1, t2; - int ret = 0; - char *device_name = NULL; - HRESULT hr = E_FAIL; - ICreateDevEnum *pCreateDevEnum = NULL; - IGraphBuilder *pGB = NULL; - ICaptureGraphBuilder2 *pCGB = NULL; - IBaseFilter *pSrcFilter = NULL; - IEnumMoniker *pEnumMK = NULL; - IMoniker *pMoniKer = NULL; - IAMStreamConfig *pSConfig = NULL; - int iCount = 0, iSize = 0; - - gettimeofday(&t1, NULL); - hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - if (FAILED(hr)) { - ERR("Failed to CoInitailizeEx\n"); - gettimeofday(&t2, NULL); - ERR("Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - hr = CoCreateInstance(&CLSID_FilterGraph, NULL, - CLSCTX_INPROC, - &IID_IGraphBuilder, - (void **)&pGB); - if (FAILED(hr)) { - ERR("Failed to create GraphBuilder, 0x%x\n", hr); - CoUninitialize(); - gettimeofday(&t2, NULL); - ERR("Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - hr = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL, - CLSCTX_INPROC, - &IID_ICaptureGraphBuilder2, - (void **)&pCGB); - if (FAILED(hr)) { - ERR("Failed to create CaptureGraphBuilder2, 0x%x\n", hr); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - ERR("Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - hr = pCGB->lpVtbl->SetFiltergraph(pCGB, pGB); - if (FAILED(hr)) { - ERR("Failed to SetFiltergraph, 0x%x\n", hr); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - ERR("Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, - CLSCTX_INPROC, - &IID_ICreateDevEnum, - (void **)&pCreateDevEnum); - if (FAILED(hr)) { - ERR("Failed to create instance of CLSID_SystemDeviceEnum\n"); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - ERR("Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - hr = pCreateDevEnum->lpVtbl->CreateClassEnumerator(pCreateDevEnum, - &CLSID_VideoInputDeviceCategory, &pEnumMK, 0); - if (FAILED(hr)) { - ERR("Failed to create class enumerator\n"); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - ERR("Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - if (!pEnumMK) { - ERR("Class enumerator is NULL!!\n"); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - ERR("Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - pEnumMK->lpVtbl->Reset(pEnumMK); - - hr = pEnumMK->lpVtbl->Next(pEnumMK, 1, &pMoniKer, NULL); - if (FAILED(hr) || (hr == S_FALSE)) { - ERR("Enum moniker returns a invalid value.\n"); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - ERR("Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - IPropertyBag *pBag = NULL; - hr = pMoniKer->lpVtbl->BindToStorage(pMoniKer, 0, 0, - &IID_IPropertyBag, - (void **)&pBag); - if (FAILED(hr)) { - ERR("Failed to bind to storage.\n"); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - ERR("Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } else { - VARIANT var; - var.vt = VT_BSTR; - hr = pBag->lpVtbl->Read(pBag, L"FriendlyName", &var, NULL); - if (hr == S_OK) { - ret = 1; - if (!log_flag) { - SysFreeString(var.bstrVal); - SAFE_RELEASE(pBag); - SAFE_RELEASE(pMoniKer); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - ERR("Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - device_name = __wchar_to_char(var.bstrVal); - INFO("Device name : %s\n", device_name); - g_free(device_name); - hr = pMoniKer->lpVtbl->BindToObject(pMoniKer, NULL, NULL, - &IID_IBaseFilter, - (void **)&pSrcFilter); - if (FAILED(hr)) { - ERR("Counldn't bind moniker to filter object!!\n"); - SysFreeString(var.bstrVal); - SAFE_RELEASE(pBag); - SAFE_RELEASE(pMoniKer); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - ERR("Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } else { - pSrcFilter->lpVtbl->AddRef(pSrcFilter); - } - SysFreeString(var.bstrVal); - } - SAFE_RELEASE(pBag); - } - SAFE_RELEASE(pMoniKer); - - hr = pGB->lpVtbl->AddFilter(pGB, pSrcFilter, L"Video Capture"); - if (hr != S_OK && hr != S_FALSE) { - ERR("Counldn't add Video Capture filter to our graph!\n"); - SAFE_RELEASE(pSrcFilter); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - ERR("Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - hr = pCGB->lpVtbl->FindInterface(pCGB, &PIN_CATEGORY_CAPTURE, 0, - pSrcFilter, &IID_IAMStreamConfig, - (void **)&pSConfig); - if (FAILED(hr)) { - ERR("Failed to FindInterface method\n"); - SAFE_RELEASE(pSrcFilter); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - ERR("Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - hr = pSConfig->lpVtbl->GetNumberOfCapabilities(pSConfig, &iCount, &iSize); - if (FAILED(hr)) { - ERR("Failed to GetNumberOfCapabilities method\n"); - SAFE_RELEASE(pSConfig); - SAFE_RELEASE(pSrcFilter); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - CoUninitialize(); - gettimeofday(&t2, NULL); - ERR("Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - return ret; - } - - if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)) { - int iFormat = 0; - for (iFormat = 0; iFormat < iCount; iFormat++) { - VIDEO_STREAM_CONFIG_CAPS scc; - AM_MEDIA_TYPE *pmtConfig; - - hr = pSConfig->lpVtbl->GetStreamCaps(pSConfig, iFormat, &pmtConfig, - (BYTE *)&scc); - if (hr == S_OK) { - if (IsEqualIID(&pmtConfig->formattype, &FORMAT_VideoInfo)) { - VIDEOINFOHEADER *pvi = - (VIDEOINFOHEADER *)pmtConfig->pbFormat; - if (pvi->bmiHeader.biCompression == BI_RGB) { - INFO("RGB BitCount: %d, Frame size: %ux%u\n", - pvi->bmiHeader.biBitCount, - pvi->bmiHeader.biWidth, - pvi->bmiHeader.biHeight); - } else { - INFO("PixelFormat: %c%c%c%c, Frame size: %ux%u\n", - (char)(pvi->bmiHeader.biCompression), - (char)(pvi->bmiHeader.biCompression >> 8), - (char)(pvi->bmiHeader.biCompression >> 16), - (char)(pvi->bmiHeader.biCompression >> 24), - pvi->bmiHeader.biWidth, - pvi->bmiHeader.biHeight); - } - } - DeleteMediaType(pmtConfig); - } - } - } - - hr = pGB->lpVtbl->RemoveFilter(pGB, pSrcFilter); - if (FAILED(hr)) { - ERR("Failed to remove source filer. 0x%x\n", hr); - } - - SAFE_RELEASE(pSConfig); - SAFE_RELEASE(pSrcFilter); - SAFE_RELEASE(pCGB); - SAFE_RELEASE(pGB); - SAFE_RELEASE(pEnumMK); - SAFE_RELEASE(pCreateDevEnum); - CoUninitialize(); - gettimeofday(&t2, NULL); - ERR("Elapsed time : %lu.%06lu\n", - t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec); - - return ret; -} - -/* MARUCAM_CMD_INIT */ -void marucam_device_init(MaruCamState *state) -{ - g_state = state; -} - -void marucam_device_exit(MaruCamState *state) -{ -} - -/* MARUCAM_CMD_OPEN */ -void marucam_device_open(MaruCamState *state) -{ - HRESULT hr; - uint32_t dwHeight, dwWidth, dwDstFmt; - MaruCamParam *param = state->param; - param->top = 0; - - hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - if (FAILED(hr)) { - ERR("CoInitailizeEx\n"); - ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); - param->errCode = EINVAL; - return; - } - - hr = GraphBuilder_Init(); - if (FAILED(hr)) { - ERR("GraphBuilder_Init\n"); - DisconnectPins(); - RemoveFilters(); - CloseInterfaces(); - CoUninitialize(); - param->errCode = EINVAL; - ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); - return; - } - - hr = BindSourceFilter(); - if (FAILED(hr)) { - ERR("BindSourceFilter\n"); - DisconnectPins(); - RemoveFilters(); - CloseInterfaces(); - CoUninitialize(); - param->errCode = EINVAL; - ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); - return; - } - - hr = BindTargetFilter(); - if (FAILED(hr)) { - ERR("BindTargetFilter\n"); - DisconnectPins(); - RemoveFilters(); - CloseInterfaces(); - CoUninitialize(); - param->errCode = EINVAL; - ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); - return; - } - - hr = ConnectFilters(); - if (FAILED(hr)) { - ERR("ConnectFilters\n"); - DisconnectPins(); - RemoveFilters(); - CloseInterfaces(); - CoUninitialize(); - param->errCode = EINVAL; - ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); - return; - } - - cur_frame_idx = 0; - cur_fmt_idx = 0; - - dwHeight = supported_dst_frames[cur_frame_idx].height; - dwWidth = supported_dst_frames[cur_frame_idx].width; - dwDstFmt = supported_dst_pixfmts[cur_fmt_idx].fmt; - hr = SetFormat(dwWidth, dwHeight, dwDstFmt, &g_dwSrcFmt); - if (hr != S_OK) { - ERR("failed to Set default values\n"); - DisconnectPins(); - RemoveFilters(); - CloseInterfaces(); - CoUninitialize(); - param->errCode = EINVAL; - ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr); - return; - } - - INFO("Opened\n"); - return; -} - -/* MARUCAM_CMD_CLOSE */ -void marucam_device_close(MaruCamState *state) -{ - MaruCamParam *param = state->param; - int ret = 0; - param->top = 0; - - qemu_mutex_lock(&state->thread_mutex); - ret = state->streamon; - qemu_mutex_unlock(&state->thread_mutex); - if (ret) { - marucam_device_stop_preview(state); - } - - if (g_pGB) { - DisconnectPins(); - RemoveFilters(); - } - CloseInterfaces(); - CoUninitialize(); - INFO("Closed\n"); -} - -/* MARUCAM_CMD_START_PREVIEW */ -void marucam_device_start_preview(MaruCamState *state) -{ - HRESULT hr; - uint32_t pixfmt, width, height; - MaruCamParam *param = state->param; - param->top = 0; - - ready_count = 0; - width = supported_dst_frames[cur_frame_idx].width; - height = supported_dst_frames[cur_frame_idx].height; - pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; - state->buf_size = get_sizeimage(pixfmt, width, height); - - INFO("Pixfmt(%c%c%c%c), W:H(%d:%d), buf size(%u)\n", - (char)(pixfmt), (char)(pixfmt >> 8), - (char)(pixfmt >> 16), (char)(pixfmt >> 24), - width, height, state->buf_size); - INFO("Starting preview\n"); - - assert(g_pCallback != NULL); - hr = ((HWCInPin *)g_pInputPin)->SetGrabCallbackIF(g_pInputPin, - g_pCallback); - if (FAILED(hr)) { - ERR("Failed to set IGrabCallback interface.\n"); - param->errCode = EINVAL; - return; - } - - if (grab_buf) { - g_free(grab_buf); - grab_buf = NULL; - } - grab_buf = (void *)g_malloc0(state->buf_size); - if (grab_buf == NULL) { - param->errCode = ENOMEM; - return; - } - - hr = g_pMediaControl->lpVtbl->Run(g_pMediaControl); - if (FAILED(hr)) { - ERR("Failed to run media control. hr=0x%x\n", hr); - param->errCode = EINVAL; - return; - } - - qemu_mutex_lock(&state->thread_mutex); - state->streamon = 1; - qemu_mutex_unlock(&state->thread_mutex); - - INFO("Streaming on ......\n"); -} - -/* MARUCAM_CMD_STOP_PREVIEW */ -void marucam_device_stop_preview(MaruCamState *state) -{ - HRESULT hr; - MaruCamParam *param = state->param; - param->top = 0; - - INFO("...... Streaming off\n"); - qemu_mutex_lock(&state->thread_mutex); - state->streamon = 0; - qemu_mutex_unlock(&state->thread_mutex); - - hr = ((HWCInPin *)g_pInputPin)->SetGrabCallbackIF(g_pInputPin, NULL); - if (FAILED(hr)) { - ERR("Failed to set IGrabCallback interface.\n"); - param->errCode = EINVAL; - return; - } - - hr = g_pMediaControl->lpVtbl->Stop(g_pMediaControl); - if (FAILED(hr)) { - ERR("Failed to stop media control.\n"); - param->errCode = EINVAL; - return; - } - - if (grab_buf) { - g_free(grab_buf); - grab_buf = NULL; - } - state->buf_size = 0; - - INFO("Stopping preview\n"); -} - -/* MARUCAM_CMD_S_PARAM */ -void marucam_device_s_param(MaruCamState *state) -{ - MaruCamParam *param = state->param; - - /* We use default FPS of the webcam */ - param->top = 0; -} - -/* MARUCAM_CMD_G_PARAM */ -void marucam_device_g_param(MaruCamState *state) -{ - MaruCamParam *param = state->param; - - /* We use default FPS of the webcam - * return a fixed value on guest ini file (1/30). - */ - param->top = 0; - param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */ - param->stack[1] = 1; /* numerator */ - param->stack[2] = 30; /* denominator */ -} - -/* MARUCAM_CMD_S_FMT */ -void marucam_device_s_fmt(MaruCamState *state) -{ - uint32_t width, height, pixfmt, pidx, fidx; - MaruCamParam *param = state->param; - - param->top = 0; - width = param->stack[0]; - height = param->stack[1]; - pixfmt = param->stack[2]; - - for (fidx = 0; fidx < ARRAY_SIZE(supported_dst_frames); fidx++) { - if ((supported_dst_frames[fidx].width == width) && - (supported_dst_frames[fidx].height == height)) { - break; - } - } - if (fidx == ARRAY_SIZE(supported_dst_frames)) { - param->errCode = EINVAL; - return; - } - for (pidx = 0; pidx < ARRAY_SIZE(supported_dst_pixfmts); pidx++) { - if (supported_dst_pixfmts[pidx].fmt == pixfmt) { - break; - } - } - if (pidx == ARRAY_SIZE(supported_dst_pixfmts)) { - param->errCode = EINVAL; - return; - } - - if ((supported_dst_frames[cur_frame_idx].width != width) && - (supported_dst_frames[cur_frame_idx].height != height)) { - HRESULT hr = SetFormat(width, height, pixfmt, &g_dwSrcFmt); - if (FAILED(hr)) { - param->errCode = EINVAL; - return; - } - } - - cur_frame_idx = fidx; - cur_fmt_idx = pidx; - - pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; - width = supported_dst_frames[cur_frame_idx].width; - height = supported_dst_frames[cur_frame_idx].height; - - param->stack[0] = width; - param->stack[1] = height; - param->stack[2] = 1; /* V4L2_FIELD_NONE */ - param->stack[3] = pixfmt; - param->stack[4] = get_bytesperline(pixfmt, width); - param->stack[5] = get_sizeimage(pixfmt, width, height); - param->stack[6] = 0; - param->stack[7] = 0; - - TRACE("Set format...\n"); -} - -/* MARUCAM_CMD_G_FMT */ -void marucam_device_g_fmt(MaruCamState *state) -{ - uint32_t width, height, pixfmt; - MaruCamParam *param = state->param; - - param->top = 0; - pixfmt = supported_dst_pixfmts[cur_fmt_idx].fmt; - width = supported_dst_frames[cur_frame_idx].width; - height = supported_dst_frames[cur_frame_idx].height; - - param->stack[0] = width; - param->stack[1] = height; - param->stack[2] = 1; /* V4L2_FIELD_NONE */ - param->stack[3] = pixfmt; - param->stack[4] = get_bytesperline(pixfmt, width); - param->stack[5] = get_sizeimage(pixfmt, width, height); - param->stack[6] = 0; - param->stack[7] = 0; - - TRACE("Get format...\n"); -} - -void marucam_device_try_fmt(MaruCamState *state) -{ - uint32_t width, height, pixfmt, i; - MaruCamParam *param = state->param; - - param->top = 0; - width = param->stack[0]; - height = param->stack[1]; - pixfmt = param->stack[2]; - - for (i = 0; i < ARRAY_SIZE(supported_dst_frames); i++) { - if ((supported_dst_frames[i].width == width) && - (supported_dst_frames[i].height == height)) { - break; - } - } - if (i == ARRAY_SIZE(supported_dst_frames)) { - param->errCode = EINVAL; - return; - } - for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) { - if (supported_dst_pixfmts[i].fmt == pixfmt) { - break; - } - } - if (i == ARRAY_SIZE(supported_dst_pixfmts)) { - param->errCode = EINVAL; - return; - } - - param->stack[0] = width; - param->stack[1] = height; - param->stack[2] = 1; /* V4L2_FIELD_NONE */ - param->stack[3] = pixfmt; - param->stack[4] = get_bytesperline(pixfmt, width); - param->stack[5] = get_sizeimage(pixfmt, width, height); - param->stack[6] = 0; - param->stack[7] = 0; -} - -void marucam_device_enum_fmt(MaruCamState *state) -{ - uint32_t index; - MaruCamParam *param = state->param; - - param->top = 0; - index = param->stack[0]; - - if (index >= ARRAY_SIZE(supported_dst_pixfmts)) { - param->errCode = EINVAL; - return; - } - param->stack[1] = 0; /* flags = NONE */ - param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */ - /* set description */ - switch (supported_dst_pixfmts[index].fmt) { - case V4L2_PIX_FMT_YUYV: - memcpy(¶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; - uint32_t halfWidth; - uint8_t *yplane, *uplane, *vplane; - uint8_t *yline, *uline, *vline; - const uint8_t *rgbIndex; - - halfWidth = width >> 1; - yplane = dest; - - if (yvu) { - vplane = dest + width * height; - uplane = vplane + ((width * height) >> 2); - } else { - uplane = dest + width * height; - vplane = uplane + ((width * height) >> 2); - } - - for (y = 0; y < height; y++) { - yline = yplane + (y * width); - uline = uplane + ((y >> 1) * halfWidth); - vline = vplane + ((y >> 1) * halfWidth); - - rgbIndex = src + (width * (height - 1 - y) * 3); - for (x = 0; x < (int)width; x+=2) { - RGB2Y(rgbIndex[2], rgbIndex[1], rgbIndex[0], *yline++); - rgbIndex += 3; - RGB2Y(rgbIndex[2], rgbIndex[1], rgbIndex[0], *yline++); - RGB2UV(rgbIndex[2], rgbIndex[1], rgbIndex[0], *uline++, *vline++); - rgbIndex += 3; - } - } -} - -void rgb24_to_yuyv(unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height) -{ - uint32_t i, j; - uint8_t *ptr; - - for (i = 0; i < height; i++) { - ptr = src + (width * (height - 1 - i) * 3); - for (j = 0; j < width; j += 2) { - /* y */ - *dest++ = CLIP(0.299 * (ptr[2] - 128) + - 0.587 * (ptr[1] - 128) + - 0.114 * (ptr[0] - 128) + 128); - /* u */ - *dest++ = CLIP(((-0.147 * (ptr[2] - 128) - - 0.289 * (ptr[1] - 128) + - 0.436 * (ptr[0] - 128) + 128) + - (-0.147 * (ptr[5] - 128) - - 0.289 * (ptr[4] - 128) + - 0.436 * (ptr[3] - 128) + 128)) / 2); - /* y1 */ - *dest++ = CLIP(0.299 * (ptr[5] - 128) + - 0.587 * (ptr[4] - 128) + - 0.114 * (ptr[3] - 128) + 128); - /* v */ - *dest++ = CLIP(((0.615 * (ptr[2] - 128) - - 0.515 * (ptr[1] - 128) - - 0.100 * (ptr[0] - 128) + 128) + - (0.615 * (ptr[5] - 128) - - 0.515 * (ptr[4] - 128) - - 0.100 * (ptr[3] - 128) + 128)) / 2); - ptr += 6; - } - } -} - -void yuv420_to_yvu420(unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height) -{ - unsigned char *psrc_y, *pdst_y; - unsigned char *psrc_u, *pdst_u; - unsigned char *psrc_v, *pdst_v; - - psrc_y = src; - psrc_u = psrc_y + (width * height); - psrc_v = psrc_u + (width * height / 4); - - pdst_y = dest; - pdst_v = pdst_y + (width * height); - pdst_u = pdst_v + (width * height / 4); - - memcpy(pdst_y, psrc_y, width * height); - memcpy(pdst_v, psrc_v, width * height / 4); - memcpy(pdst_u, psrc_u, width * height / 4); -} - -void yuv420_to_yuyv(unsigned char *src, unsigned char *dest, - uint32_t width, uint32_t height) -{ - unsigned char *py; - unsigned char *pu; - unsigned char *pv; - - uint32_t linesize = width * 2; - uint32_t uvlinesize = width / 2; - uint32_t offset = 0; - uint32_t offset1 = 0; - uint32_t offsety = 0; - uint32_t offsety1 = 0; - uint32_t offsetuv = 0; - uint32_t h = 0; - uint32_t w = 0; - uint32_t wy = 0; - uint32_t huv = 0; - uint32_t wuv = 0; - - py = src; - pu = py + (width * height); - pv = pu + (width * height / 4); - - for (h = 0; h < height; h += 2) { - wy = 0; - wuv = 0; - offset = h * linesize; - offset1 = (h + 1) * linesize; - offsety = h * width; - offsety1 = (h + 1) * width; - offsetuv = huv * uvlinesize; - - for (w = 0; w < linesize; w += 4) { - /* y00 */ - dest[w + offset] = py[wy + offsety]; - /* u0 */ - dest[(w + 1) + offset] = pu[wuv + offsetuv]; - /* y01 */ - dest[(w + 2) + offset] = py[(wy + 1) + offsety]; - /* v0 */ - dest[(w + 3) + offset] = pv[wuv + offsetuv]; - - /* y10 */ - dest[w + offset1] = py[wy + offsety1]; - /* u0 */ - dest[(w + 1) + offset1] = pu[wuv + offsetuv]; - /* y11 */ - dest[(w + 2) + offset1] = py[(wy + 1) + offsety1]; - /* v0 */ - dest[(w + 3) + offset1] = pv[wuv + offsetuv]; - - wuv++; - wy += 2; - } - huv++; - } -} diff --git a/tizen/src/util/check_cam.c b/tizen/src/util/check_cam.c index 8a0fc40602..3d2ec9953f 100644 --- a/tizen/src/util/check_cam.c +++ b/tizen/src/util/check_cam.c @@ -5,7 +5,7 @@ * * Contact: * Jinhyung Jo - * YeongKyoon Lee + * Sangho Park * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -37,7 +37,7 @@ #include "ocidl.h" #include "errors.h" /* for VFW_E_XXXX */ #include "mmsystem.h" /* for MAKEFOURCC macro */ -#include "hw/pci/maru_camera_win32_interface.h" +#include "hw/pci/maru_camera_win32.h" /* * COM Interface implementations