This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project gfxprim.git.
The branch, master has been updated via f874ce61275191ecdd5aae7938b0d56e368820ec (commit) via 800afa4e6dcb7ae2bd05b5847a99824755fae03a (commit) from 69da631cdcad26baa4ba500942f0c6d74cebff44 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- http://repo.or.cz/w/gfxprim.git/commit/f874ce61275191ecdd5aae7938b0d56e36882...
commit f874ce61275191ecdd5aae7938b0d56e368820ec Author: Cyril Hrubis metan@ucw.cz Date: Tue Jun 19 20:58:21 2012 +0200
grabbers: Introduce grabbers library and V4L2 grabber.
diff --git a/configure b/configure index bd08e4b..4a59e25 100755 --- a/configure +++ b/configure @@ -188,7 +188,7 @@ def write_config_mk(cfg, libs): # Generate app compilation helper # def write_gfxprim_config(cfg, libs): - modules = ['loaders', 'backends'] + modules = ['loaders', 'backends', 'grabbers']
f = open('gfxprim-config', 'w') f.write('#!/bin/shn' @@ -212,6 +212,8 @@ def write_gfxprim_config(cfg, libs): ldflags = '' if i == 'backends': ldflags += '-lGP_backends ' + if i == 'grabbers': + ldflags += '-lGP_grabbers ' ldflags += libs.get_linker_flags(i) f.write('t--libs-%s) echo -n "%s ";;n' % (i, ldflags))
@@ -253,7 +255,10 @@ if __name__ == '__main__': [header_exists, "X11/Xlib.h"], "", "-lX11", ["backends"]], ["freetype", "A high-quality and portable font engine", - [header_exists, "ft2build.h"], "", "`freetype-config --libs`", ["core"]]], cfg) + [header_exists, "ft2build.h"], "", "`freetype-config --libs`", ["core"]], + ["V4L2", + "Video for linux 2", + [header_exists, "linux/videodev2.h"], "", "", ["grabbers"]]], cfg)
parser = OptionParser();
diff --git a/demos/c_simple/Makefile b/demos/c_simple/Makefile index 6e3b7d7..2107993 100644 --- a/demos/c_simple/Makefile +++ b/demos/c_simple/Makefile @@ -6,7 +6,11 @@ INCLUDE= LDLIBS+=-lGP -lGP_backends -lSDL -L$(TOPDIR)/build/
APPS=backend_example loaders_example loaders filters_symmetry gfx_koch- virtual_backend_example meta_data meta_data_dump tmp_file showimage + virtual_backend_example meta_data meta_data_dump tmp_file showimage+ v4l2_show v4l2_grab + +v4l2_show: LDLIBS+=-lGP_grabbers +v4l2_grab: LDLIBS+=-lGP_grabbers
include $(TOPDIR)/pre.mk include $(TOPDIR)/app.mk diff --git a/demos/c_simple/v4l2_grab.c b/demos/c_simple/v4l2_grab.c new file mode 100644 index 0000000..7aa8469 --- /dev/null +++ b/demos/c_simple/v4l2_grab.c @@ -0,0 +1,141 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * + * * + *****************************************************************************/ + + /* + + Gets an image from v4l2 device. + + */ + +#include <string.h> +#include <errno.h> + +#include <GP.h> + +static int get_image(const char *filename, GP_Grabber *grabber) +{ + /* turn on grabber */ + if (GP_GrabberStart(grabber)) { + fprintf(stderr, "Failed to start grabbern"); + return 1; + } + + /* throw away first frame, it's usually wrong */ + while (!GP_GrabberPoll(grabber)) + usleep(100000); + + while (!GP_GrabberPoll(grabber)) + usleep(100000); + + /* save image */ + if (GP_SaveJPG(grabber->frame, filename, NULL)) { + fprintf(stderr, "Failed to save image '%s': %s", + filename, strerror(errno)); + return 1; + } + + /* turn off grabber */ + if (GP_GrabberStop(grabber)) { + fprintf(stderr, "Failed to start grabbern"); + return 1; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + const char *v4l2_device = "/dev/video0"; + const char *image_filename = "frame.jpg"; + unsigned int w = 640, h = 480; + int secs = 0; + int opt; + + while ((opt = getopt(argc, argv, "d:hH:o:W:l:s:")) != -1) { + switch (opt) { + case 'o': + image_filename = optarg; + break; + case 'd': + v4l2_device = optarg; + break; + case 'W': + w = atoi(optarg); + break; + case 'H': + h = atoi(optarg); + break; + case 's': + secs = atoi(optarg); + break; + case 'l': + GP_SetDebugLevel(atoi(optarg)); + break; + case 'h': + printf("Usage; %s optsn", argv[0]); + printf("-o output image file, default is 'frame.jpg'n" + "-d v4l2 device name (default is '/dev/video0'n" + "-W output image width, default is 640n" + "-H output image height, default is 480n" + "-l sets GFXprim debug level (default is 0)n" + "-s take image every s seconds (the images are stored as frameX.jpg)n" + "-h prints this helpn"); + return 0; + break; + default: + fprintf(stderr, "Invalid paramter '%c'n", opt); + return 1; + } + } + + GP_Grabber *grabber = GP_GrabberV4L2Init(v4l2_device, w, h); + + if (grabber == NULL) { + fprintf(stderr, "Failed to initalize grabber '%s': %sn", + v4l2_device, strerror(errno)); + return 1; + } + + if (secs == 0) { + get_image(image_filename, grabber); + GP_GrabberExit(grabber); + return 0; + } + + int i = 0; + + for (;;) { + char buf[128]; + + snprintf(buf, sizeof(buf), "frame%03i.jpg", i++); + + if (get_image(buf, grabber)) { + fprintf(stderr, "Failed to get image, exitting...n"); + return 1; + } + + sleep(secs); + } + + + return 0; +} diff --git a/demos/c_simple/v4l2_show.c b/demos/c_simple/v4l2_show.c new file mode 100644 index 0000000..077ba7b --- /dev/null +++ b/demos/c_simple/v4l2_show.c @@ -0,0 +1,162 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * + * * + *****************************************************************************/ + + /* + + Simple V4L2 grabber interactive example. + + */ + +#include <errno.h> +#include <string.h> + +#include <GP.h> +#include <backends/GP_X11.h> + +int main(int argc, char *argv[]) +{ + GP_Backend *backend; + GP_Grabber *grabber; + const char *v4l2_device = "/dev/video0"; + unsigned int w = 320, h = 240; + int mode = 0; + int opt; + + /* Turn on debug messages */ + //GP_SetDebugLevel(10); + + while ((opt = getopt(argc, argv, "d:hH:W:l:")) != -1) { + switch (opt) { + case 'd': + v4l2_device = optarg; + break; + case 'W': + w = atoi(optarg); + break; + case 'H': + h = atoi(optarg); + break; + case 'l': + GP_SetDebugLevel(atoi(optarg)); + break; + case 'h': + printf("Usage; %s optsn", argv[0]); + printf("-d v4l2 device name (default is '/dev/video0'n" + "-W output image width, default is 640n" + "-H output image height, default is 480n" + "-l sets GFXprim debug level (default is 0)n" + "-h prints this helpn"); + return 0; + break; + default: + fprintf(stderr, "Invalid paramter '%c'n", opt); + return 1; + } + } + + grabber = GP_GrabberV4L2Init(v4l2_device, w, h); + + if (grabber == NULL) { + fprintf(stderr, "Failed to initalize grabber '%s': %sn", + v4l2_device, strerror(errno)); + return 1; + } + + backend = GP_BackendX11Init(NULL, 0, 0, grabber->frame->w, + grabber->frame->h, "V4L2", 0); + + if (backend == NULL) { + GP_GrabberExit(grabber); + return 1; + } + + if (GP_GrabberStart(grabber)) { + fprintf(stderr, "Failed to start grabbern"); + GP_BackendExit(backend); + GP_GrabberExit(grabber); + return 1; + } + + printf("Press SPACE to change mode and Q to exit.n"); + + for (;;) { + if (GP_GrabberPoll(grabber) > 0) { + GP_Context *res, *img = grabber->frame; + + switch (mode) { + case 0: + res = img; + break; + case 1: + GP_FilterEdgePrewitt(img, &res, NULL, NULL); + break; + case 2: + GP_FilterGaussianBlur(img, img, 1, 1, NULL); + res = GP_FilterFloydSteinberg_RGB888_Alloc(img, GP_PIXEL_G2, NULL); + break; + } + + GP_Blit_Clipped(res, 0, 0, res->w, res->h, backend->context, 0, 0); + GP_BackendFlip(backend); + + if (mode) + GP_ContextFree(res); + } + + usleep(1000); + + GP_BackendPoll(backend); + + /* Read and parse events */ + GP_Event ev; + + while (GP_EventGet(&ev)) { + switch (ev.type) { + case GP_EV_KEY: + + /* ignore key up events */ + if (!ev.code) + continue; + + switch (ev.val.key.key) { + case GP_KEY_ESC: + case GP_KEY_Q: + GP_BackendExit(backend); + GP_GrabberExit(grabber); + return 0; + break; + case GP_KEY_SPACE: + + mode++; + + if (mode > 2) + mode = 0; + break; + } + } + } + } + + GP_BackendExit(backend); + + return 0; +} diff --git a/include/GP.h b/include/GP.h index b01e512..4b622e6 100644 --- a/include/GP.h +++ b/include/GP.h @@ -47,4 +47,7 @@ /* bitmap filters */ #include "filters/GP_Filters.h"
+/* grabbers */ +#include "grabbers/GP_Grabbers.h" + #endif /* GP_H */ diff --git a/include/GP.h b/include/grabbers/GP_Grabber.h similarity index 58% copy from include/GP.h copy to include/grabbers/GP_Grabber.h index b01e512..5591297 100644 --- a/include/GP.h +++ b/include/grabbers/GP_Grabber.h @@ -16,35 +16,75 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2011 Jiri "BlueBear" Dluhos * - * jiri.bluebear.dluhos@gmail.com * - * * * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * * * *****************************************************************************/
-#ifndef GP_H -#define GP_H +#ifndef GP_GRABBERS_GRABBER_H +#define GP_GRABBERS_GRABBER_H + +struct GP_Context; + +typedef struct GP_Grabber { + /* + * Context with current frame. + */ + struct GP_Context *frame; + + /* + * Returns 0 if there are no images in queue and 1 otherwise. + */ + int (*Poll)(struct GP_Grabber *self); + + /* + * Grabber fd, may be set -1 if grabber doesn't have one. + */ + int fd; + + /* + * Starts the actuall grabbing. May be NULL if not needed. + */ + int (*Start)(struct GP_Grabber *self); + + /* + * Stops the grabbing. May be NULL if not needed. + */ + int (*Stop)(struct GP_Grabber *self);
-/* library core */ -#include "core/GP_Core.h" + /* + * Exit functions. Closes fd, frees memory. + */ + void (*Exit)(struct GP_Grabber *self);
-/* public drawing API */ -#include "gfx/GP_Gfx.h" + char priv[]; +} GP_Grabber;
-/* fonts and text drawing */ -#include "text/GP_Text.h" +#define GP_GRABBER_PRIV(grabber) ((void*)(grabber)->priv)
-/* backends */ -#include "backends/GP_Backend.h" +static inline void GP_GrabberExit(struct GP_Grabber *self) +{ + self->Exit(self); +}
-/* input and events */ -#include "input/GP_Input.h" +static inline int GP_GrabberPoll(struct GP_Grabber *self) +{ + return self->Poll(self); +}
-/* bitmap loaders */ -#include "loaders/GP_Loaders.h" +static inline int GP_GrabberStart(struct GP_Grabber *self) +{ + if (self->Start) + return self->Start(self); + + return 0; +}
-/* bitmap filters */ -#include "filters/GP_Filters.h" +static inline int GP_GrabberStop(struct GP_Grabber *self) +{ + if (self->Stop) + return self->Stop(self); + + return 0; +}
-#endif /* GP_H */ +#endif /* GP_GRABBERS_GRABBER_H */ diff --git a/include/GP.h b/include/grabbers/GP_Grabbers.h similarity index 72% copy from include/GP.h copy to include/grabbers/GP_Grabbers.h index b01e512..d305edf 100644 --- a/include/GP.h +++ b/include/grabbers/GP_Grabbers.h @@ -16,35 +16,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2011 Jiri "BlueBear" Dluhos * - * jiri.bluebear.dluhos@gmail.com * - * * * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * * * *****************************************************************************/
-#ifndef GP_H -#define GP_H - -/* library core */ -#include "core/GP_Core.h" - -/* public drawing API */ -#include "gfx/GP_Gfx.h" - -/* fonts and text drawing */ -#include "text/GP_Text.h" - -/* backends */ -#include "backends/GP_Backend.h" - -/* input and events */ -#include "input/GP_Input.h" - -/* bitmap loaders */ -#include "loaders/GP_Loaders.h" +#ifndef GP_GRABBERS_GRABBERS_H +#define GP_GRABBERS_GRABBERS_H
-/* bitmap filters */ -#include "filters/GP_Filters.h" +#include "grabbers/GP_Grabber.h" +#include "grabbers/GP_V4L2.h"
-#endif /* GP_H */ +#endif /* GP_GRABBERS_GRABBERS_H */ diff --git a/include/GP.h b/include/grabbers/GP_V4L2.h similarity index 72% copy from include/GP.h copy to include/grabbers/GP_V4L2.h index b01e512..aa6bf08 100644 --- a/include/GP.h +++ b/include/grabbers/GP_V4L2.h @@ -16,35 +16,23 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * - * Copyright (C) 2009-2011 Jiri "BlueBear" Dluhos * - * jiri.bluebear.dluhos@gmail.com * - * * * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * * * *****************************************************************************/
-#ifndef GP_H -#define GP_H - -/* library core */ -#include "core/GP_Core.h" - -/* public drawing API */ -#include "gfx/GP_Gfx.h" - -/* fonts and text drawing */ -#include "text/GP_Text.h" - -/* backends */ -#include "backends/GP_Backend.h" - -/* input and events */ -#include "input/GP_Input.h" +#ifndef GP_GRABBERS_V4L2_H +#define GP_GRABBERS_V4L2_H
-/* bitmap loaders */ -#include "loaders/GP_Loaders.h" +struct GP_Grabber;
-/* bitmap filters */ -#include "filters/GP_Filters.h" +/* + * Create V4L2 grabber. + * + * The prefered_width and height may not be used if driver does support only + * fixed image size. + */ +struct GP_Grabber *GP_GrabberV4L2Init(const char *device, + unsigned int prefered_width, + unsigned int prefered_height);
-#endif /* GP_H */ +#endif /* GP_GRABBERS_V4L2_H */ diff --git a/libs/Makefile b/libs/Makefile index 01fbd7a..5fe3d19 100644 --- a/libs/Makefile +++ b/libs/Makefile @@ -1,3 +1,3 @@ TOPDIR=.. -SUBDIRS=core gfx text loaders filters input backends SDL +SUBDIRS=core gfx text loaders filters input backends grabbers SDL include $(TOPDIR)/post.mk diff --git a/libs/grabbers/GP_V4L2.c b/libs/grabbers/GP_V4L2.c new file mode 100644 index 0000000..418839f --- /dev/null +++ b/libs/grabbers/GP_V4L2.c @@ -0,0 +1,434 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * + * * + *****************************************************************************/ + + /* + + Based on V4L2 example code. + + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <string.h> +#include <errno.h> +#include <sys/mman.h> + +#include <stdint.h> + +#include "core/GP_Context.h" + +#include "core/GP_Debug.h" + +#include "../../config.h" + +#ifdef HAVE_V4L2 + +#include <linux/videodev2.h> + +#include "GP_Grabber.h" +#include "GP_V4L2.h" + +struct v4l2_priv { + int mode; + + /* pointer to page aligned user buffer */ + void *bufptr[4]; + size_t buf_len[4]; + + char device[]; +}; + +static int v4l2_stop(struct GP_Grabber *self); + +static void v4l2_exit(struct GP_Grabber *self) +{ + struct v4l2_priv *priv = GP_GRABBER_PRIV(self); + int i; + + GP_DEBUG(1, "Grabber '%s' exitting", priv->device); + + v4l2_stop(self); + + if (priv->mode == 2) { + for (i = 0; i < 4; i++) + munmap(priv->bufptr[i], priv->buf_len[i]); + } + + close(self->fd); + GP_ContextFree(self->frame); + free(self); +} + +#define CLAMP(x, max) + if (x > max) + x = max; + if (x < 0) + x = 0; + +#define MUL 1024 + +static void v4l2_yuv422_fillframe(struct GP_Grabber *self, void *buf) +{ + unsigned int i, j; + unsigned char *py, *pu, *pv; + unsigned char *tmp = self->frame->pixels; + + py = buf; + pu = buf + 1; + pv = buf + 3; + + for (i = 0; i < self->frame->h; i++) { + for (j = 0; j < self->frame->w; j++) { + int32_t PU = ((int32_t)*pu) - 128; + int32_t PV = ((int32_t)*pv) - 128; + + int32_t R = MUL * (*py) + ((int32_t)(MUL * 1.772)) * PU; + int32_t G = MUL * (*py) - ((int32_t)(MUL * 0.344)) * PU + - ((int32_t)(MUL * 0.714)) * PV; + int32_t B = MUL * (*py) + ((int32_t)(MUL * 1.402)) * PV; + + R = (R + MUL/2)/MUL; + G = (G + MUL/2)/MUL; + B = (B + MUL/2)/MUL; + + CLAMP(R, 255); + CLAMP(G, 255); + CLAMP(B, 255); + + *tmp++ = R; + *tmp++ = G; + *tmp++ = G; + + py += 2; + + if ((j & 1) == 1) { + pu += 4; + pv += 4; + } + } + } +} + +static int v4l2_poll(struct GP_Grabber *self) +{ + struct v4l2_priv *priv = GP_GRABBER_PRIV(self); + + GP_DEBUG(3, "Grabber '%s' poll", priv->device); + + /* read/write interface */ + if (priv->mode == 1) { + GP_WARN("Read/write I/O not implemented."); + return 0; + } + + /* mmaped interface */ + struct v4l2_buffer buf; + + memset(&buf, 0, sizeof(buf)); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + + if (ioctl(self->fd, VIDIOC_DQBUF, &buf)) { + switch (errno) { + case EAGAIN: + return 0; + default: + GP_WARN("Failed to ioctl VIDIOC_DQBUF on '%s' : %s", + priv->device, strerror(errno)); + return 0; + } + } + + if (buf.index >= 4) { + GP_WARN("Got invalid buffer index on '%s'", priv->device); + return 0; + } + + v4l2_yuv422_fillframe(self, priv->bufptr[buf.index]); + + if (ioctl(self->fd, VIDIOC_QBUF, &buf)) { + GP_WARN("Failed to ioctl VIDIOC_QBUF on '%s' : %s", + priv->device, strerror(errno)); + } + + return 1; +} + +static int v4l2_start(struct GP_Grabber *self) +{ + struct v4l2_priv *priv = GP_GRABBER_PRIV(self); + + /* read/write interface */ + if (priv->mode == 1) + return 0; + + /* mmap interface */ + int i; + struct v4l2_buffer buf; + memset(&buf, 0, sizeof(buf)); + + for (i = 0; i < 4; i++) { + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + + if (ioctl(self->fd, VIDIOC_QBUF, &buf)) { + GP_WARN("Failed to ioclt VIDIOC_QBUF on '%s': %s", + priv->device, strerror(errno)); + return 1; + } + } + + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (ioctl(self->fd, VIDIOC_STREAMON, &type)) { + GP_WARN("Failed to ioclt VIDIOC_STREAMON on '%s': %s", + priv->device, strerror(errno)); + return 1; + } + + return 0; +} + +static int v4l2_stop(struct GP_Grabber *self) +{ + struct v4l2_priv *priv = GP_GRABBER_PRIV(self); + + /* read/write interface */ + if (priv->mode == 1) + return 0; + + /* mmap interface */ + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (ioctl(self->fd, VIDIOC_STREAMOFF, &type)) { + GP_WARN("Failed to ioclt VIDIOC_STREAMON on '%s': %s", + priv->device, strerror(errno)); + return 1; + } + + return 0; +} + +struct GP_Grabber *GP_GrabberV4L2Init(const char *device, + unsigned int prefered_width, + unsigned int prefered_height) +{ + int fd, i, err; + int mode = 0; + + GP_DEBUG(1, "Opening V4L2 grabber '%s'", device); + + fd = open(device, O_RDWR | O_NONBLOCK); + + if (fd < 0) { + err = errno; + GP_WARN("Failed to open V4L2 grabber '%s'", device); + goto err; + } + + struct v4l2_capability cap; + + if (ioctl(fd, VIDIOC_QUERYCAP, &cap)) { + err = errno; + GP_WARN("ioctl VIDIOC_QUERYCAP failed, '%s' not V4L2 device?", + device); + goto err0; + } + + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { + err = ENOSYS; + GP_WARN("Device '%s' has no capture capability", device); + goto err0; + } + + + if (!(cap.capabilities & V4L2_CAP_READWRITE)) { + GP_DEBUG(1, "Device '%s' doesn't support read write I/O", device); + } else { + mode = 1; + } + + if (!(cap.capabilities & V4L2_CAP_STREAMING)) { + GP_DEBUG(1, "Device '%s' doesn't support streaming I/O", device); + } else { + mode = 2; + } + + if (mode == 0) { + err = ENOSYS; + GP_WARN("No suitable mode found for '%s'", device); + goto err0; + } + + struct v4l2_cropcap cropcap; + struct v4l2_crop crop; + + memset(&cropcap, 0, sizeof(cropcap)); + + cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (ioctl(fd, VIDIOC_CROPCAP, &cropcap) == 0) { + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + /* reset to default */ + crop.c = cropcap.defrect; + + if (ioctl(fd, VIDIOC_S_CROP, &crop)) { + /* error/cropping not supported */ + } + + } else { + /* errors ignored? */ + } + + struct v4l2_format fmt; + + memset(&fmt, 0, sizeof(fmt)); + + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = prefered_width; + fmt.fmt.pix.height = prefered_height; + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; + + if (ioctl(fd, VIDIOC_S_FMT, &fmt)) { + err = errno; + GP_WARN("Failed to set video format for device '%s'", device); + goto err0; + } + + GP_Grabber *new = malloc(sizeof(GP_Grabber) + sizeof(struct v4l2_priv) + strlen(device) + 1); + + if (new == NULL) { + err = ENOMEM; + GP_WARN("Malloc failed :("); + goto err0; + } + + new->frame = GP_ContextAlloc(fmt.fmt.pix.width, fmt.fmt.pix.height, GP_PIXEL_RGB888); + + if (new->frame == NULL) { + err = ENOMEM; + goto err1; + } + + struct v4l2_priv *priv = GP_GRABBER_PRIV(new); + + strcpy(priv->device, device); + priv->mode = mode; + + switch (mode) { + case 1: + break; + case 2: { + /* setup mmap interface */ + struct v4l2_requestbuffers req; + + memset(&req, 0, sizeof(req)); + + req.count = 4; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; + + if (ioctl(fd, VIDIOC_REQBUFS, &req)) { + err = errno; + GP_WARN("Failed to ioctl VIDIOC_REQBUFS on '%s' : %s", + device, strerror(errno)); + goto err2; + } + + if (req.count != 4) { + err = ENOSYS; + GP_WARN("Unexpected number of buffers on '%s'", device); + goto err2; + } + + struct v4l2_buffer buf; + memset(&buf, 0, sizeof(buf)); + + priv->bufptr[0] = NULL; + priv->bufptr[1] = NULL; + priv->bufptr[2] = NULL; + priv->bufptr[3] = NULL; + + for (i = 0; i < 4; i++) { + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + + if (ioctl(fd, VIDIOC_QUERYBUF, &buf)) { + err = errno; + GP_WARN("Failed to ioclt VIDIOC_QUERYBUF on '%s': %s", + device, strerror(errno)); + goto err2; + } + + priv->bufptr[i] = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset); + priv->buf_len[i] = buf.length; + + if (priv->bufptr[i] == MAP_FAILED) { + err = errno; + GP_WARN("mmap failed on '%s': %s", device, strerror(errno)); + goto err3; + } + } + } break; + } + + new->fd = fd; + new->Exit = v4l2_exit; + new->Poll = v4l2_poll; + new->Start = v4l2_start; + new->Stop = v4l2_stop; + + return new; +err3: + for (i = 0; i < 4; i++) + if (priv->bufptr[i] != NULL) + munmap(priv->bufptr[i], priv->buf_len[i]); +err2: + GP_ContextFree(new->frame); +err1: + free(new); +err0: + close(fd); +err: + errno = err; + return NULL; +} + +#else + +struct GP_Grabber *GP_GrabberV4L2Init(const char GP_UNUSED(*device), + unsigned int GP_UNUSED(prefered_width), + unsigned int GP_UNUSED(prefered_height)) +{ + GP_WARN("V4L2 support not compiled in."); + + errno = ENOSYS; + return NULL; +} + +#endif /* HAVE_V4L2 */ diff --git a/libs/grabbers/Makefile b/libs/grabbers/Makefile new file mode 100644 index 0000000..4df5769 --- /dev/null +++ b/libs/grabbers/Makefile @@ -0,0 +1,8 @@ +TOPDIR=../.. +CSOURCES=$(shell ls *.c) +LIBNAME=grabbers +BUILDLIB=yes + +include $(TOPDIR)/pre.mk +include $(TOPDIR)/lib.mk +include $(TOPDIR)/post.mk
http://repo.or.cz/w/gfxprim.git/commit/800afa4e6dcb7ae2bd05b5847a99824755fae...
commit 800afa4e6dcb7ae2bd05b5847a99824755fae03a Author: Cyril Hrubis metan@ucw.cz Date: Tue Jun 19 18:36:07 2012 +0200
pywrap: filters: Fix warning.
diff --git a/pylib/gfxprim/filters/filters.i b/pylib/gfxprim/filters/filters.i index abcb96d..e321b1a 100644 --- a/pylib/gfxprim/filters/filters.i +++ b/pylib/gfxprim/filters/filters.i @@ -3,6 +3,7 @@
%{ #include "filters/GP_Filters.h" +#include "core/GP_Debug.h" %}
%import ../core/core.i
-----------------------------------------------------------------------
Summary of changes: configure | 9 +- demos/c_simple/Makefile | 6 +- demos/c_simple/v4l2_grab.c | 141 +++++++ .../particle_demo.c => c_simple/v4l2_show.c} | 161 ++++---- include/GP.h | 3 + .../loaders.c => include/grabbers/GP_Grabber.h | 105 +++--- .../{input/GP_Input.h => grabbers/GP_Grabbers.h} | 12 +- .../GP_InputDriverKBD.h => grabbers/GP_V4L2.h} | 20 +- libs/Makefile | 2 +- libs/grabbers/GP_V4L2.c | 434 ++++++++++++++++++++ libs/{backends => grabbers}/Makefile | 2 +- pylib/gfxprim/filters/filters.i | 1 + 12 files changed, 749 insertions(+), 147 deletions(-) create mode 100644 demos/c_simple/v4l2_grab.c copy demos/{particle/particle_demo.c => c_simple/v4l2_show.c} (53%) copy demos/c_simple/loaders.c => include/grabbers/GP_Grabber.h (59%) copy include/{input/GP_Input.h => grabbers/GP_Grabbers.h} (91%) copy include/{input/GP_InputDriverKBD.h => grabbers/GP_V4L2.h} (80%) create mode 100644 libs/grabbers/GP_V4L2.c copy libs/{backends => grabbers}/Makefile (88%)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos@gmail.com if you want to unsubscribe, or site admin admin@repo.or.cz if you receive no reply.