From: Bernd Zeimetz Date: Fri, 1 Apr 2011 00:44:36 +0200 Subject: Description: Linux 2.6.38 and later do not support the v4l1 API. Migrate to using the libv4l library to abstract our access to Linux video devices, instead. Author: Mauro Carvalho Chehab Bug-Ubuntu: http://bugs.launchpad.net/bugs/724997 Bug-Debian: http://bugs.debian.org/620220 Bug: http://sourceforge.net/tracker/?func=detail&aid=3128542&group_id=189236&atid=928517 --- configure.ac | 11 +- include/config.h.in | 13 +- zbar/Makefile.am.inc | 18 +-- zbar/video/v4l1.c | 435 ----------------------------------------------- zbar/video/v4l2.c | 70 +++++--- zbarcam/Makefile.am.inc | 2 + 6 files changed, 64 insertions(+), 485 deletions(-) delete mode 100644 zbar/video/v4l1.c diff --git a/configure.ac b/configure.ac index 56d3dd0..53168c0 100644 --- a/configure.ac +++ b/configure.ac @@ -147,20 +147,13 @@ AC_ARG_ENABLE([video], with_video="no" AS_IF([test "x$enable_video" != "xno"], [AS_IF([test "x$win32" = "xno"], - [AC_CHECK_HEADERS([linux/videodev.h], [with_video="v4l1"], - [AC_MSG_FAILURE([test for video support failed! -rebuild your kernel to include video4linux support or -configure --disable-video to skip building video support.])]) - AC_CHECK_HEADERS([linux/videodev2.h], [with_video="v4l2"], + [AC_CHECK_LIB([v4l2], [v4l2_open], [], [AC_MSG_WARN([v4l2 API not detected, upgrade your kernel!])])], [AC_CHECK_HEADERS([vfw.h], [with_video="vfw"], [AC_MSG_FAILURE([test for VfW video support failed! configure --disable-video to skip building vidoe support.])])]) ]) AM_CONDITIONAL([HAVE_VIDEO], [test "x$enable_video" != "xno"]) -AM_CONDITIONAL([HAVE_V4L1], - [test "x$with_video" = "xv4l1" || test "x$with_video" = "xv4l2"]) -AM_CONDITIONAL([HAVE_V4L2], [test "x$with_video" = "xv4l2"]) dnl X AC_ARG_VAR([XSHM_LIBS], [linker flags for X shared memory extension]) @@ -442,7 +435,7 @@ echo "please verify that the detected configuration matches your expectations:" echo "------------------------------------------------------------------------" echo "X --with-x=$have_x" echo "pthreads --enable-pthread=$enable_pthread" -echo "v4l --enable-video=$enable_video" +echo "v4l2 --enable-video=$enable_video" AS_IF([test "x$enable_video" != "xyes"], [echo " => zbarcam video scanner will *NOT* be built"]) echo "jpeg --with-jpeg=$with_jpeg" diff --git a/include/config.h.in b/include/config.h.in index 6950d05..aecc6b7 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -48,11 +48,8 @@ /* Define to 1 if you have the `pthread' library (-lpthread). */ #undef HAVE_LIBPTHREAD -/* Define to 1 if you have the header file. */ -#undef HAVE_LINUX_VIDEODEV2_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_LINUX_VIDEODEV_H +/* Define to 1 if you have the `v4l2' library (-lv4l2). */ +#undef HAVE_LIBV4L2 /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H @@ -93,6 +90,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MMAN_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SHM_H @@ -160,6 +160,9 @@ /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME +/* Define to the home page for this package. */ +#undef PACKAGE_URL + /* Define to the version of this package. */ #undef PACKAGE_VERSION diff --git a/zbar/Makefile.am.inc b/zbar/Makefile.am.inc index 8d38484..1a5ce8d 100644 --- a/zbar/Makefile.am.inc +++ b/zbar/Makefile.am.inc @@ -53,21 +53,17 @@ else zbar_libzbar_la_SOURCES += zbar/processor/posix.h zbar/processor/posix.c endif -if HAVE_V4L1 -zbar_libzbar_la_SOURCES += zbar/video/v4l1.c -if HAVE_V4L2 -zbar_libzbar_la_SOURCES += zbar/video/v4l2.c -endif -endif -if WIN32 if HAVE_VIDEO +if WIN32 zbar_libzbar_la_SOURCES += zbar/video/vfw.c zbar_libzbar_la_LIBADD += -lvfw32 -endif -endif -if !HAVE_VIDEO +else +zbar_libzbar_la_SOURCES += zbar/video/v4l2.c +zbar_libzbar_la_LDFLAGS += -lv4l2 +endif #WIN32 +else zbar_libzbar_la_SOURCES += zbar/video/null.c -endif +endif #HAVE_VIDEO if HAVE_JPEG zbar_libzbar_la_SOURCES += zbar/jpeg.c diff --git a/zbar/video/v4l1.c b/zbar/video/v4l1.c deleted file mode 100644 index 89b1da2..0000000 --- a/zbar/video/v4l1.c +++ /dev/null @@ -1,435 +0,0 @@ -/*------------------------------------------------------------------------ - * Copyright 2007-2009 (c) Jeff Brown - * - * This file is part of the ZBar Bar Code Reader. - * - * The ZBar Bar Code Reader is free software; you can redistribute it - * and/or modify it under the terms of the GNU Lesser Public License as - * published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * The ZBar Bar Code Reader 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 Public License for more details. - * - * You should have received a copy of the GNU Lesser Public License - * along with the ZBar Bar Code Reader; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301 USA - * - * http://sourceforge.net/projects/zbar - *------------------------------------------------------------------------*/ - -#include -#ifdef HAVE_INTTYPES_H -# include -#endif -#ifdef HAVE_STDLIB_H -# include -#endif -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_IOCTL_H -# include -#endif -#ifdef HAVE_SYS_MMAN_H -# include -#endif -#include - -#include "video.h" -#include "image.h" - -extern int _zbar_v4l2_probe(zbar_video_t*); - -typedef struct v4l1_format_s { - uint32_t format; - uint8_t bpp; -} v4l1_format_t; - -/* static v4l1 "palette" mappings - * documentation for v4l1 formats is terrible... - */ -static const v4l1_format_t v4l1_formats[17] = { - /* format bpp */ - { 0, 0 }, - { fourcc('G','R','E','Y'), 8 }, /* GREY */ - { fourcc('H','I','2','4'), 8 }, /* HI240 (BT848) */ - - /* component ordering for RGB palettes is unspecified, - * convention appears to place red in the most significant bits - * FIXME is this true for other drivers? big endian machines? - */ - { fourcc('R','G','B','P'), 16 }, /* RGB565 */ - { fourcc('B','G','R','3'), 24 }, /* RGB24 */ - { fourcc('B','G','R','4'), 32 }, /* RGB32 */ - { fourcc('R','G','B','O'), 16 }, /* RGB555 */ - { fourcc('Y','U','Y','2'), 16 }, /* YUV422 (8 bpp?!) */ - { fourcc('Y','U','Y','V'), 16 }, /* YUYV */ - { fourcc('U','Y','V','Y'), 16 }, /* UYVY */ - { 0, 12 }, /* YUV420 (24 bpp?) FIXME?! */ - { fourcc('Y','4','1','P'), 12 }, /* YUV411 */ - { 0, 0 }, /* Bt848 raw */ - { fourcc('4','2','2','P'), 16 }, /* YUV422P (24 bpp?) */ - { fourcc('4','1','1','P'), 12 }, /* YUV411P */ - { fourcc('Y','U','1','2'), 12 }, /* YUV420P */ - { fourcc('Y','U','V','9'), 9 }, /* YUV410P */ -}; - -static int v4l1_nq (zbar_video_t *vdo, - zbar_image_t *img) -{ - if(video_nq_image(vdo, img)) - return(-1); - - if(vdo->iomode != VIDEO_MMAP) - return(0); - - struct video_mmap vmap; - vmap.frame = img->srcidx; - vmap.width = vdo->width; - vmap.height = vdo->height; - vmap.format = vdo->palette; - if(ioctl(vdo->fd, VIDIOCMCAPTURE, &vmap) < 0) - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "initiating video capture (VIDIOCMCAPTURE)")); - - return(0); -} - -static zbar_image_t *v4l1_dq (zbar_video_t *vdo) -{ - video_iomode_t iomode = vdo->iomode; - int fd = vdo->fd; - zbar_image_t *img = video_dq_image(vdo); - if(!img) - return(NULL); - - if(iomode == VIDEO_MMAP) { - int frame = img->srcidx; - if(ioctl(fd, VIDIOCSYNC, &frame) < 0) - return(NULL); - } - else if(read(fd, (void*)img->data, img->datalen) != img->datalen) - return(NULL); - - return(img); -} - -static int v4l1_mmap_buffers (zbar_video_t *vdo) -{ -#ifdef HAVE_SYS_MMAN_H - /* map camera image to memory */ - struct video_mbuf vbuf; - memset(&vbuf, 0, sizeof(vbuf)); - if(ioctl(vdo->fd, VIDIOCGMBUF, &vbuf) < 0) - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "querying video frame buffers (VIDIOCGMBUF)")); - assert(vbuf.frames && vbuf.size); - - zprintf(1, "mapping %d buffers size=0x%x\n", vbuf.frames, vbuf.size); - vdo->buflen = vbuf.size; - vdo->buf = mmap(0, vbuf.size, PROT_READ | PROT_WRITE, MAP_SHARED, - vdo->fd, 0); - if(vdo->buf == MAP_FAILED) - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "mapping video frame buffers")); - - int i; - for(i = 0; i < vbuf.frames; i++) { - zbar_image_t *img = vdo->images[i]; - zprintf(2, " [%02d] @%08x\n", img->srcidx, vbuf.offsets[i]); - img->data = vdo->buf + vbuf.offsets[i]; - img->datalen = vdo->datalen; - int next_offset = ((i + 1 < vdo->num_images) - ? vbuf.offsets[i + 1] - : vbuf.size); - if(next_offset < vbuf.offsets[i] + vdo->datalen) - fprintf(stderr, "WARNING: insufficient v4l1 video buffer size:\n" - "\tvbuf[%d]=%x vbuf[%d]=%x datalen=%lx\n" - "\timage=%d x %d %.4s(%08x) palette=%d\n", - i, vbuf.offsets[i], i + 1, next_offset, - vdo->datalen, vdo->width, vdo->height, - (char*)&vdo->format, vdo->format, vdo->palette); - } - return(0); -#else - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, - "memory mapping not supported")); -#endif -} - -static int v4l1_start (zbar_video_t *vdo) -{ - return(0); -} - -static int v4l1_stop (zbar_video_t *vdo) -{ - return(0); -} - -static inline int v4l1_set_format (zbar_video_t *vdo, - uint32_t fmt) -{ - struct video_picture vpic; - memset(&vpic, 0, sizeof(vpic)); - if(ioctl(vdo->fd, VIDIOCGPICT, &vpic) < 0) - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "querying video format (VIDIOCGPICT)")); - - vdo->palette = 0; - int ifmt; - for(ifmt = 1; ifmt <= VIDEO_PALETTE_YUV410P; ifmt++) - if(v4l1_formats[ifmt].format == fmt) - break; - if(!fmt || ifmt >= VIDEO_PALETTE_YUV410P) - return(err_capture_int(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, - "invalid v4l1 format: %x", fmt)); - - vpic.palette = ifmt; - vpic.depth = v4l1_formats[ifmt].bpp; - if(ioctl(vdo->fd, VIDIOCSPICT, &vpic) < 0) - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "setting format (VIDIOCSPICT)")); - - memset(&vpic, 0, sizeof(vpic)); - if(ioctl(vdo->fd, VIDIOCGPICT, &vpic) < 0) - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "querying video format (VIDIOCGPICT)")); - - if(vpic.palette != ifmt || vpic.depth != v4l1_formats[ifmt].bpp) { - fprintf(stderr, - "WARNING: set v4l1 palette %d which should have depth %d bpp\n" - " but probed palette %d with depth %d bpp?" - " ...continuing anyway\n", - ifmt, v4l1_formats[ifmt].bpp, vpic.palette, vpic.depth); - err_capture_int(vdo, SEV_WARNING, ZBAR_ERR_INVALID, __func__, - "driver format (%x) inconsistency", fmt); - } - vdo->format = fmt; - vdo->palette = ifmt; - vdo->datalen = (vdo->width * vdo->height * v4l1_formats[ifmt].bpp + 7) >> 3; - - zprintf(1, "set new format: %.4s(%08x) depth=%d palette=%d size=0x%lx\n", - (char*)&vdo->format, vdo->format, vpic.depth, vdo->palette, - vdo->datalen); - return(0); -} - -static int v4l1_init (zbar_video_t *vdo, - uint32_t fmt) -{ - if(v4l1_set_format(vdo, fmt)) - return(-1); - if(vdo->iomode == VIDEO_MMAP && v4l1_mmap_buffers(vdo)) - return(-1); - return(0); -} - -static int v4l1_cleanup (zbar_video_t *vdo) -{ -#ifdef HAVE_SYS_MMAN_H - /* FIXME should avoid holding onto mmap'd buffers so long? */ - if(vdo->iomode == VIDEO_MMAP && vdo->buf) { - if(munmap(vdo->buf, vdo->buflen)) - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "unmapping video frame buffers")); - vdo->buf = NULL; - /* FIXME reset image */ - } -#endif - - /* close open device */ - if(vdo->fd >= 0) { - close(vdo->fd); - vdo->fd = -1; - } - return(0); -} - -static int v4l1_probe_iomode (zbar_video_t *vdo) -{ - vdo->iomode = VIDEO_READWRITE; -#ifdef HAVE_SYS_MMAN_H - struct video_mbuf vbuf; - memset(&vbuf, 0, sizeof(vbuf)); - if(ioctl(vdo->fd, VIDIOCGMBUF, &vbuf) < 0) { - if(errno != EINVAL) - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "querying video frame buffers (VIDIOCGMBUF)")); - /* not supported */ - return(0); - } - if(!vbuf.frames || !vbuf.size) - return(0); - vdo->iomode = VIDEO_MMAP; - if(vdo->num_images > vbuf.frames) - vdo->num_images = vbuf.frames; -#endif - zprintf(1, "using %d images in %s mode\n", vdo->num_images, - (vdo->iomode == VIDEO_READWRITE) ? "READ" : "MMAP"); - return(0); -} - -static inline int v4l1_probe_formats (zbar_video_t *vdo) -{ - struct video_picture vpic; - memset(&vpic, 0, sizeof(vpic)); - if(ioctl(vdo->fd, VIDIOCGPICT, &vpic) < 0) - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "querying format (VIDIOCGPICT)")); - - vdo->format = 0; - if(vpic.palette <= VIDEO_PALETTE_YUV410P) - vdo->format = v4l1_formats[vpic.palette].format; - - zprintf(1, "current format: %.4s(%08x) depth=%d palette=%d\n", - (char*)&vdo->format, vdo->format, vpic.depth, vpic.palette); - - vdo->formats = calloc(16, sizeof(uint32_t)); - if(!vdo->formats) - return(err_capture(vdo, SEV_FATAL, ZBAR_ERR_NOMEM, __func__, - "allocating format list")); - - int num_formats = 0; - zprintf(2, "probing supported formats:\n"); - int i; - for(i = 1; i <= VIDEO_PALETTE_YUV410P; i++) { - if(!v4l1_formats[i].format) - continue; - vpic.depth = v4l1_formats[i].bpp; - vpic.palette = i; - if(ioctl(vdo->fd, VIDIOCSPICT, &vpic) < 0) { - zprintf(2, " [%02d] %.4s...no (set fails)\n", - i, (char*)&v4l1_formats[i].format); - continue; - } - if(ioctl(vdo->fd, VIDIOCGPICT, &vpic) < 0 || - vpic.palette != i) { - zprintf(2, " [%02d] %.4s...no (set ignored)\n", - i, (char*)&v4l1_formats[i].format); - continue; - } - zprintf(2, " [%02d] %.4s...yes\n", - i, (char*)&v4l1_formats[i].format); - vdo->formats[num_formats++] = v4l1_formats[i].format; - } - vdo->formats = realloc(vdo->formats, (num_formats + 1) * sizeof(uint32_t)); - assert(vdo->formats); - - return(v4l1_set_format(vdo, vdo->format)); -} - -static inline int v4l1_init_window (zbar_video_t *vdo) -{ - struct video_window vwin; - memset(&vwin, 0, sizeof(vwin)); - if(ioctl(vdo->fd, VIDIOCGWIN, &vwin) < 0) - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "querying video window settings (VIDIOCGWIN)")); - - zprintf(1, "current window: %d x %d @(%d, %d)%s\n", - vwin.width, vwin.height, vwin.x, vwin.y, - (vwin.flags & 1) ? " INTERLACE" : ""); - - if(vwin.width == vdo->width && vwin.height == vdo->height) - /* max window already set */ - return(0); - - struct video_window maxwin; - memcpy(&maxwin, &vwin, sizeof(maxwin)); - maxwin.width = vdo->width; - maxwin.height = vdo->height; - - zprintf(1, "setting max win: %d x %d @(%d, %d)%s\n", - maxwin.width, maxwin.height, maxwin.x, maxwin.y, - (maxwin.flags & 1) ? " INTERLACE" : ""); - if(ioctl(vdo->fd, VIDIOCSWIN, &maxwin) < 0) { - zprintf(1, "set FAILED...trying to recover original window\n"); - /* ignore errors (driver broken anyway) */ - ioctl(vdo->fd, VIDIOCSWIN, &vwin); - } - - /* re-query resulting parameters */ - memset(&vwin, 0, sizeof(vwin)); - if(ioctl(vdo->fd, VIDIOCGWIN, &vwin) < 0) - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "querying video window settings (VIDIOCGWIN)")); - - zprintf(1, " final window: %d x %d @(%d, %d)%s\n", - vwin.width, vwin.height, vwin.x, vwin.y, - (vwin.flags & 1) ? " INTERLACE" : ""); - vdo->width = vwin.width; - vdo->height = vwin.height; - return(0); -} - -static int _zbar_v4l1_probe (zbar_video_t *vdo) -{ - /* check capabilities */ - struct video_capability vcap; - memset(&vcap, 0, sizeof(vcap)); - if(ioctl(vdo->fd, VIDIOCGCAP, &vcap) < 0) - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, - "video4linux version 1 not supported (VIDIOCGCAP)")); - - zprintf(1, "%s (%sCAPTURE) (%d x %d) - (%d x %d)\n", - vcap.name, (vcap.type & VID_TYPE_CAPTURE) ? "" : "*NO* ", - vcap.minwidth, vcap.minheight, vcap.maxwidth, vcap.maxheight); - - if(!(vcap.type & VID_TYPE_CAPTURE)) - return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, - "v4l1 device does not support CAPTURE")); - - if(!vdo->width || !vdo->height) { - vdo->width = vcap.maxwidth; - vdo->height = vcap.maxheight; - } - - if(v4l1_init_window(vdo) || - v4l1_probe_formats(vdo) || - v4l1_probe_iomode(vdo)) - return(-1); - - vdo->intf = VIDEO_V4L1; - vdo->init = v4l1_init; - vdo->cleanup = v4l1_cleanup; - vdo->start = v4l1_start; - vdo->stop = v4l1_stop; - vdo->nq = v4l1_nq; - vdo->dq = v4l1_dq; - return(0); -} - -int _zbar_video_open (zbar_video_t *vdo, - const char *dev) -{ - vdo->fd = open(dev, O_RDWR); - if(vdo->fd < 0) - return(err_capture_str(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, - "opening video device '%s'", dev)); - zprintf(1, "opened camera device %s (fd=%d)\n", dev, vdo->fd); - - int rc = -1; -#ifdef HAVE_LINUX_VIDEODEV2_H - if(vdo->intf != VIDEO_V4L1) - rc = _zbar_v4l2_probe(vdo); - if(rc) -#else - zprintf(1, "WARNING: not compiled with v4l2 support, trying v4l1\n"); -#endif - rc = _zbar_v4l1_probe(vdo); - - if(rc && vdo->fd >= 0) { - close(vdo->fd); - vdo->fd = -1; - } - return(rc); -} diff --git a/zbar/video/v4l2.c b/zbar/video/v4l2.c index ec59bd8..065091e 100644 --- a/zbar/video/v4l2.c +++ b/zbar/video/v4l2.c @@ -38,6 +38,8 @@ #ifdef HAVE_SYS_MMAN_H # include #endif +#include +#include #include #include "video.h" @@ -67,7 +69,7 @@ static int v4l2_nq (zbar_video_t *vdo, vbuf.length = img->datalen; vbuf.index = img->srcidx; /* FIXME workaround broken drivers */ } - if(ioctl(vdo->fd, VIDIOC_QBUF, &vbuf) < 0) + if(v4l2_ioctl(vdo->fd, VIDIOC_QBUF, &vbuf) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "queuing video buffer (VIDIOC_QBUF)")); return(0); @@ -91,7 +93,7 @@ static zbar_image_t *v4l2_dq (zbar_video_t *vdo) else vbuf.memory = V4L2_MEMORY_USERPTR; - if(ioctl(fd, VIDIOC_DQBUF, &vbuf) < 0) + if(v4l2_ioctl(fd, VIDIOC_DQBUF, &vbuf) < 0) return(NULL); if(iomode == VIDEO_MMAP) { @@ -132,7 +134,7 @@ static int v4l2_start (zbar_video_t *vdo) return(0); enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if(ioctl(vdo->fd, VIDIOC_STREAMON, &type) < 0) + if(v4l2_ioctl(vdo->fd, VIDIOC_STREAMON, &type) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "starting video stream (VIDIOC_STREAMON)")); return(0); @@ -144,7 +146,7 @@ static int v4l2_stop (zbar_video_t *vdo) return(0); enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if(ioctl(vdo->fd, VIDIOC_STREAMOFF, &type) < 0) + if(v4l2_ioctl(vdo->fd, VIDIOC_STREAMOFF, &type) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "stopping video stream (VIDIOC_STREAMOFF)")); return(0); @@ -164,7 +166,7 @@ static int v4l2_cleanup (zbar_video_t *vdo) for(i = 0; i < vdo->num_images; i++) { zbar_image_t *img = vdo->images[i]; if(img->data && - munmap((void*)img->data, img->datalen)) + v4l2_munmap((void*)img->data, img->datalen)) err_capture(vdo, SEV_WARNING, ZBAR_ERR_SYSTEM, __func__, "unmapping video frame buffers"); img->data = NULL; @@ -177,27 +179,27 @@ static int v4l2_cleanup (zbar_video_t *vdo) /* requesting 0 buffers * should implicitly disable streaming */ - if(ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0) + if(v4l2_ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0) err_capture(vdo, SEV_WARNING, ZBAR_ERR_SYSTEM, __func__, "releasing video frame buffers (VIDIOC_REQBUFS)"); - /* close open device */ + /* v4l2_close v4l2_open device */ if(vdo->fd >= 0) { - close(vdo->fd); + v4l2_close(vdo->fd); vdo->fd = -1; } return(0); } -static int v4l2_mmap_buffers (zbar_video_t *vdo) +static int v4l2_v4l2_mmap_buffers (zbar_video_t *vdo) { struct v4l2_requestbuffers rb; memset(&rb, 0, sizeof(rb)); rb.count = vdo->num_images; rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; rb.memory = V4L2_MEMORY_MMAP; - if(ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0) + if(v4l2_ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "requesting video frame buffers (VIDIOC_REQBUFS)")); zprintf(1, "mapping %u buffers (of %d requested)\n", @@ -216,7 +218,7 @@ static int v4l2_mmap_buffers (zbar_video_t *vdo) int i; for(i = 0; i < vdo->num_images; i++) { vbuf.index = i; - if(ioctl(vdo->fd, VIDIOC_QUERYBUF, &vbuf) < 0) + if(v4l2_ioctl(vdo->fd, VIDIOC_QUERYBUF, &vbuf) < 0) /* FIXME cleanup */ return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying video buffer (VIDIOC_QUERYBUF)")); @@ -229,7 +231,7 @@ static int v4l2_mmap_buffers (zbar_video_t *vdo) zbar_image_t *img = vdo->images[i]; img->datalen = vbuf.length; - img->data = mmap(NULL, vbuf.length, PROT_READ | PROT_WRITE, MAP_SHARED, + img->data = v4l2_mmap(NULL, vbuf.length, PROT_READ | PROT_WRITE, MAP_SHARED, vdo->fd, vbuf.m.offset); if(img->data == MAP_FAILED) /* FIXME cleanup */ @@ -253,7 +255,7 @@ static int v4l2_set_format (zbar_video_t *vdo, vpix->pixelformat = fmt; vpix->field = V4L2_FIELD_NONE; int rc = 0; - if((rc = ioctl(vdo->fd, VIDIOC_S_FMT, &vfmt)) < 0) { + if((rc = v4l2_ioctl(vdo->fd, VIDIOC_S_FMT, &vfmt)) < 0) { /* several broken drivers return an error if we request * no interlacing (NB v4l2 spec violation) * ...try again with an interlaced request @@ -264,7 +266,7 @@ static int v4l2_set_format (zbar_video_t *vdo, /* FIXME this might be _ANY once we can de-interlace */ vpix->field = V4L2_FIELD_INTERLACED; - if(ioctl(vdo->fd, VIDIOC_S_FMT, &vfmt) < 0) + if(v4l2_ioctl(vdo->fd, VIDIOC_S_FMT, &vfmt) < 0) return(err_capture_int(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "setting format %x (VIDIOC_S_FMT)", fmt)); @@ -276,7 +278,7 @@ static int v4l2_set_format (zbar_video_t *vdo, struct v4l2_pix_format *newpix = &newfmt.fmt.pix; memset(&newfmt, 0, sizeof(newfmt)); newfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if(ioctl(vdo->fd, VIDIOC_G_FMT, &newfmt) < 0) + if(v4l2_ioctl(vdo->fd, VIDIOC_G_FMT, &newfmt) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying format (VIDIOC_G_FMT)")); @@ -307,7 +309,7 @@ static int v4l2_init (zbar_video_t *vdo, if(v4l2_set_format(vdo, fmt)) return(-1); if(vdo->iomode == VIDEO_MMAP) - return(v4l2_mmap_buffers(vdo)); + return(v4l2_v4l2_mmap_buffers(vdo)); return(0); } @@ -322,7 +324,7 @@ static int v4l2_probe_iomode (zbar_video_t *vdo) else rb.memory = V4L2_MEMORY_USERPTR; - if(ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0) { + if(v4l2_ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0) { if(vdo->iomode) return(err_capture_int(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "unsupported iomode requested (%d)", @@ -350,7 +352,7 @@ static inline int v4l2_probe_formats (zbar_video_t *vdo) memset(&desc, 0, sizeof(desc)); desc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; for(desc.index = 0; desc.index < V4L2_FORMATS_MAX; desc.index++) { - if(ioctl(vdo->fd, VIDIOC_ENUM_FMT, &desc) < 0) + if(v4l2_ioctl(vdo->fd, VIDIOC_ENUM_FMT, &desc) < 0) break; zprintf(2, " [%d] %.4s : %s%s\n", desc.index, (char*)&desc.pixelformat, desc.description, @@ -368,7 +370,7 @@ static inline int v4l2_probe_formats (zbar_video_t *vdo) struct v4l2_pix_format *pix = &fmt.fmt.pix; memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if(ioctl(vdo->fd, VIDIOC_G_FMT, &fmt) < 0) + if(v4l2_ioctl(vdo->fd, VIDIOC_G_FMT, &fmt) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying current video format (VIDIO_G_FMT)")); @@ -390,15 +392,15 @@ static inline int v4l2_probe_formats (zbar_video_t *vdo) maxpix->height = vdo->height; zprintf(1, "setting requested size: %d x %d\n", vdo->width, vdo->height); - if(ioctl(vdo->fd, VIDIOC_S_FMT, &maxfmt) < 0) { + if(v4l2_ioctl(vdo->fd, VIDIOC_S_FMT, &maxfmt) < 0) { zprintf(1, "set FAILED...trying to recover original format\n"); /* ignore errors (driver broken anyway) */ - ioctl(vdo->fd, VIDIOC_S_FMT, &fmt); + v4l2_ioctl(vdo->fd, VIDIOC_S_FMT, &fmt); } memset(&fmt, 0, sizeof(fmt)); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if(ioctl(vdo->fd, VIDIOC_G_FMT, &fmt) < 0) + if(v4l2_ioctl(vdo->fd, VIDIOC_G_FMT, &fmt) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying current video format (VIDIOC_G_FMT)")); @@ -420,7 +422,7 @@ static inline int v4l2_reset_crop (zbar_video_t *vdo) struct v4l2_cropcap ccap; memset(&ccap, 0, sizeof(ccap)); ccap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if(ioctl(vdo->fd, VIDIOC_CROPCAP, &ccap) < 0) + if(v4l2_ioctl(vdo->fd, VIDIOC_CROPCAP, &ccap) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying crop support (VIDIOC_CROPCAP)")); @@ -442,7 +444,7 @@ static inline int v4l2_reset_crop (zbar_video_t *vdo) memset(&crop, 0, sizeof(crop)); crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = ccap.defrect; - if(ioctl(vdo->fd, VIDIOC_S_CROP, &crop) < 0 && errno != EINVAL) + if(v4l2_ioctl(vdo->fd, VIDIOC_S_CROP, &crop) < 0 && errno != EINVAL) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "setting default crop window (VIDIOC_S_CROP)")); return(0); @@ -453,7 +455,7 @@ int _zbar_v4l2_probe (zbar_video_t *vdo) /* check capabilities */ struct v4l2_capability vcap; memset(&vcap, 0, sizeof(vcap)); - if(ioctl(vdo->fd, VIDIOC_QUERYCAP, &vcap) < 0) + if(v4l2_ioctl(vdo->fd, VIDIOC_QUERYCAP, &vcap) < 0) return(err_capture(vdo, SEV_WARNING, ZBAR_ERR_UNSUPPORTED, __func__, "video4linux version 2 not supported (VIDIOC_QUERYCAP)")); @@ -507,3 +509,21 @@ int _zbar_v4l2_probe (zbar_video_t *vdo) vdo->dq = v4l2_dq; return(0); } + +int _zbar_video_open (zbar_video_t *vdo, + const char *dev) +{ + vdo->fd = v4l2_open(dev, O_RDWR); + if(vdo->fd < 0) + return(err_capture_str(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, + "opening video device '%s'", dev)); + zprintf(1, "opened camera device %s (fd=%d)\n", dev, vdo->fd); + + int rc = _zbar_v4l2_probe(vdo); + + if(rc && vdo->fd >= 0) { + v4l2_close(vdo->fd); + vdo->fd = -1; + } + return(rc); +} diff --git a/zbarcam/Makefile.am.inc b/zbarcam/Makefile.am.inc index ea869bc..78ce9b7 100644 --- a/zbarcam/Makefile.am.inc +++ b/zbarcam/Makefile.am.inc @@ -7,4 +7,6 @@ CLEANFILES += zbarcam/.libs/zbarcam if WIN32 zbarcam_zbarcam_SOURCES += zbarcam/zbarcam.rc zbarcam_zbarcam_LDADD += zbarcam/zbarcam-rc.o +else +zbarcam_zbarcam_LDADD += -lv4l2 endif --