From: Dominic L. <ma...@us...> - 2005-10-19 20:20:27
|
Update of /cvsroot/robotflow/RobotFlow/Devices/include In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16126/include Modified Files: V4L2Capture.h Log Message: testing new driver Index: V4L2Capture.h =================================================================== RCS file: /cvsroot/robotflow/RobotFlow/Devices/include/V4L2Capture.h,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** V4L2Capture.h 14 Jun 2004 14:54:48 -0000 1.8 --- V4L2Capture.h 19 Oct 2005 20:20:19 -0000 1.9 *************** *** 1,112 **** ! /*========================================================================= ! capture.h ! ------------------------------------------------------------------------- ! Example code for video capture under Video4Linux II ! ------------------------------------------------------------------------- ! Copyright 1999, 2000 ! Anna Helena Reali Costa, James R. Bruce ! School of Computer Science ! Carnegie Mellon University ! ------------------------------------------------------------------------- ! This source code is distributed "as is" with absolutely no warranty. ! It is covered under the GNU General Public Licence, Version 2.0; ! See COPYING, which should be included with this distribution. ! ------------------------------------------------------------------------- ! Revision History: ! 2000-02-05: Ported to work with V4L2 API ! 1999-11-23: Quick C++ port to simplify & wrap in an object (jbruce) ! 1999-05-01: Initial version (annar) ! =========================================================================*/ ! ! #ifndef __CAPTURE_H__ ! #define __CAPTURE_H__ ! #include <sys/mman.h> ! #include <sys/ioctl.h> ! #include <sys/time.h> ! #include <fcntl.h> #include <stdlib.h> #include <unistd.h> - #include <stdio.h> #include <errno.h> ! // ! //#include <linux/fs.h> ! //#include <linux/kernel.h> ! //#include <linux/videodev.h> ! //#include "videodev.h" ! // ! #include <linux/fs.h> ! #include <linux/kernel.h> ! //#include <linux/videodev.h> /* Video for Linux Two */ ! //#include <linux/videodev2.h> ! //#include <linux/videodev.h> ! //fix for videodev ! //#include "videodevfix.h" ! #include "videodev2.h" ! #define DEFAULT_VIDEO_DEVICE "/dev/video" ! #define VIDEO_STANDARD "NTSC" ! #ifdef USE_METEOR ! #define DEFAULT_VIDEO_FORMAT V4L2_PIX_FMT_UYVY ! #else ! #define DEFAULT_VIDEO_FORMAT V4L2_PIX_FMT_YUYV ! #endif ! #define DEFAULT_IMAGE_WIDTH 320 ! #define DEFAULT_IMAGE_HEIGHT 240 ! // if you get a message like "DQBUF returned error", "DQBUF error: invalid" ! // then you need to use a higher value for STREAMBUFS or process frames faster ! #define STREAMBUFS 10 ! class capture { ! struct vimage_t { ! v4l2_buffer vidbuf; ! char *data; ! }; ! int vid_fd; // video device ! vimage_t vimage[STREAMBUFS]; // buffers for images ! struct v4l2_format fmt; // video format request ! unsigned char *current; // most recently captured frame ! // stamp_t timestamp; // frame time stamp ! int width,height; // dimensions of video frame ! struct v4l2_buffer tempbuf; ! bool captured_frame; ! public: ! capture() {vid_fd = 0; current=NULL; captured_frame = false;} ! ~capture() {close();} - bool initialize(const char *device,int nwidth,int nheight,int nfmt, bool continuous); - bool initialize(int nwidth,int nheight) - {return(initialize(NULL,nwidth,nheight,0,false));} - bool initialize() - {return(initialize(NULL,0,0,0,false));} - void close(); - int getFD(){return vid_fd;} - unsigned char *captureFrame(int &index,int &field); - unsigned char *captureFrame(); - void releaseFrame(unsigned char* frame, int index); ! unsigned char *getFrame() {return(current);} ! bool set_contrast(int contrast); ! bool set_brightness(int brightness); ! bool set_hue(int hue); ! bool set_saturation(int color); ! bool set_auto_white_balance(bool white_balance); ! //stamp_t getFrameTime() {return(timestamp);} ! //double getFrameTimeSec() {return(timestamp * 1.0E-9);} ! int getWidth() {return(width);} ! int getHeight() {return(height);} ! }; ! #endif // __CAPTURE_H__ --- 1,680 ---- ! #ifndef _V4L2CAPTURE_H_ ! /* ! * V4L2 video capture example ! */ + #include <stdio.h> #include <stdlib.h> + #include <string.h> + #include <assert.h> + + #include <getopt.h> /* getopt_long() */ + + #include <fcntl.h> /* low-level i/o */ #include <unistd.h> #include <errno.h> + #include <sys/stat.h> + #include <sys/types.h> + #include <sys/time.h> + #include <sys/mman.h> + #include <sys/ioctl.h> ! #include <asm/types.h> /* for videodev2.h */ ! #include <linux/videodev2.h> ! namespace RobotFlow { ! #define CLEAR(x) memset (&(x), 0, sizeof (x)) ! #define DEFAULT_DEVNAME "/dev/video0" ! #define DEFAULT_WIDTH 320 ! #define DEFAULT_HEIGHT 240 ! #define DEFAULT_FORMAT V4L2_PIX_FMT_RGB555 ! class capture { ! public: ! typedef enum { ! IO_METHOD_READ, ! IO_METHOD_MMAP, ! IO_METHOD_USERPTR, ! } io_method; ! struct buffer { ! void * start; ! size_t length; ! }; ! char * dev_name; ! io_method io; ! int fd; ! buffer * buffers; ! unsigned int n_buffers; ! capture() { ! //initialize variables ! dev_name = DEFAULT_DEVNAME; ! io = IO_METHOD_MMAP; ! fd = -1; ! buffers = NULL; ! n_buffers = 0; ! } ! void init(const char* devname, io_method method=IO_METHOD_MMAP) { ! //dev_name = devname; ! //io = method; ! open_device (); ! init_device (); ! start_capturing (); ! } ! ~capture() { ! stop_capturing (); ! uninit_device (); ! close_device (); ! } ! ! void errno_exit(const char *s) { ! fprintf (stderr, "%s error %d, %s\n", ! s, errno, strerror (errno)); ! ! exit (EXIT_FAILURE); ! } ! ! int xioctl(int fd, int request, void *arg) { ! int r; ! ! do r = ioctl (fd, request, arg); ! while (-1 == r && EINTR == errno); ! return r; ! } ! ! void process_image(const void *p) { ! fputc ('.', stdout); ! fflush (stdout); ! } ! ! int read_frame(void) { ! ! struct v4l2_buffer buf; ! unsigned int i; ! ! switch (io) { ! case IO_METHOD_READ: ! if (-1 == read (fd, buffers[0].start, buffers[0].length)) { ! switch (errno) { ! case EAGAIN: ! return 0; ! ! case EIO: ! /* Could ignore EIO, see spec. */ ! ! /* fall through */ ! ! default: ! errno_exit ("read"); ! } ! } ! ! process_image (buffers[0].start); ! ! break; ! ! case IO_METHOD_MMAP: ! CLEAR (buf); ! ! buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ! buf.memory = V4L2_MEMORY_MMAP; ! ! if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) { ! switch (errno) { ! case EAGAIN: ! return 0; ! ! case EIO: ! /* Could ignore EIO, see spec. */ ! ! /* fall through */ ! ! default: ! errno_exit ("VIDIOC_DQBUF"); ! } ! } ! ! assert (buf.index < n_buffers); ! ! process_image (buffers[buf.index].start); ! ! if (-1 == xioctl (fd, VIDIOC_QBUF, &buf)) ! errno_exit ("VIDIOC_QBUF"); ! ! break; ! ! case IO_METHOD_USERPTR: ! CLEAR (buf); ! ! buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ! buf.memory = V4L2_MEMORY_USERPTR; ! ! if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) { ! switch (errno) { ! case EAGAIN: ! return 0; ! ! case EIO: ! /* Could ignore EIO, see spec. */ ! ! /* fall through */ ! ! default: ! errno_exit ("VIDIOC_DQBUF"); ! } ! } ! ! for (i = 0; i < n_buffers; ++i) ! if (buf.m.userptr == (unsigned long) buffers[i].start ! && buf.length == buffers[i].length) ! break; ! ! assert (i < n_buffers); ! ! process_image ((void *) buf.m.userptr); ! ! if (-1 == xioctl (fd, VIDIOC_QBUF, &buf)) ! errno_exit ("VIDIOC_QBUF"); ! ! break; ! } ! ! return 1; ! } ! ! Image* mainloop (void) { ! ! for (;;) { ! fd_set fds; ! struct timeval tv; ! int r; ! ! FD_ZERO (&fds); ! FD_SET (fd, &fds); ! ! // Timeout ! tv.tv_sec = 2; ! tv.tv_usec = 0; ! ! r = select (fd + 1, &fds, NULL, NULL, &tv); ! ! if (-1 == r) { ! if (EINTR == errno) ! continue; ! ! errno_exit ("select"); ! } ! ! if (0 == r) { ! fprintf (stderr, "select timeout\n"); ! exit (EXIT_FAILURE); ! } ! ! if (read_frame ()) ! break; ! ! // EAGAIN - continue select loop. ! } ! ! return NULL; ! } ! ! void stop_capturing (void) { ! ! enum v4l2_buf_type type; ! ! switch (io) { ! case IO_METHOD_READ: ! // Nothing to do. ! break; ! ! case IO_METHOD_MMAP: ! case IO_METHOD_USERPTR: ! type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ! ! if (-1 == xioctl (fd, VIDIOC_STREAMOFF, &type)) ! errno_exit ("VIDIOC_STREAMOFF"); ! ! break; ! } ! } ! ! void start_capturing(void) { ! unsigned int i; ! enum v4l2_buf_type type; ! ! switch (io) { ! case IO_METHOD_READ: ! // Nothing to do. ! break; ! ! case IO_METHOD_MMAP: ! for (i = 0; i < n_buffers; ++i) { ! struct v4l2_buffer buf; ! ! CLEAR (buf); ! ! buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ! buf.memory = V4L2_MEMORY_MMAP; ! buf.index = i; ! ! if (-1 == xioctl (fd, VIDIOC_QBUF, &buf)) ! errno_exit ("VIDIOC_QBUF"); ! } ! ! type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ! ! if (-1 == xioctl (fd, VIDIOC_STREAMON, &type)) ! errno_exit ("VIDIOC_STREAMON"); ! ! break; ! ! case IO_METHOD_USERPTR: ! for (i = 0; i < n_buffers; ++i) { ! struct v4l2_buffer buf; ! ! CLEAR (buf); ! ! buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ! buf.memory = V4L2_MEMORY_USERPTR; ! buf.m.userptr = (unsigned long) buffers[i].start; ! buf.length = buffers[i].length; ! ! if (-1 == xioctl (fd, VIDIOC_QBUF, &buf)) ! errno_exit ("VIDIOC_QBUF"); ! } ! ! ! type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ! ! if (-1 == xioctl (fd, VIDIOC_STREAMON, &type)) ! errno_exit ("VIDIOC_STREAMON"); ! ! break; ! } ! } ! ! void uninit_device(void) { ! unsigned int i; ! ! switch (io) { ! case IO_METHOD_READ: ! free (buffers[0].start); ! break; ! ! case IO_METHOD_MMAP: ! for (i = 0; i < n_buffers; ++i) ! if (-1 == munmap (buffers[i].start, buffers[i].length)) ! errno_exit ("munmap"); ! break; ! ! case IO_METHOD_USERPTR: ! for (i = 0; i < n_buffers; ++i) ! free (buffers[i].start); ! break; ! } ! ! free (buffers); ! } ! ! void init_read (unsigned int buffer_size) { ! buffers = (buffer*) calloc (1, sizeof (*buffers)); ! ! ! if (!buffers) { ! fprintf (stderr, "Out of memory\n"); ! exit (EXIT_FAILURE); ! } ! ! buffers[0].length = buffer_size; ! buffers[0].start = malloc (buffer_size); ! ! if (!buffers[0].start) { ! fprintf (stderr, "Out of memory\n"); ! exit (EXIT_FAILURE); ! } ! } ! ! void init_mmap (void) { ! struct v4l2_requestbuffers req; ! ! CLEAR (req); ! ! req.count = 4; ! req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ! req.memory = V4L2_MEMORY_MMAP; ! ! if (-1 == xioctl (fd, VIDIOC_REQBUFS, &req)) { ! if (EINVAL == errno) { ! fprintf (stderr, "%s does not support " ! "memory mapping\n", dev_name); ! exit (EXIT_FAILURE); ! } else { ! errno_exit ("VIDIOC_REQBUFS"); ! } ! } ! ! if (req.count < 2) { ! fprintf (stderr, "Insufficient buffer memory on %s\n", ! dev_name); ! exit (EXIT_FAILURE); ! } ! ! buffers = (buffer*) calloc (req.count, sizeof (*buffers)); ! ! ! if (!buffers) { ! fprintf (stderr, "Out of memory\n"); ! exit (EXIT_FAILURE); ! } ! ! for (n_buffers = 0; n_buffers < req.count; ++n_buffers) { ! struct v4l2_buffer buf; ! ! CLEAR (buf); ! ! buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ! buf.memory = V4L2_MEMORY_MMAP; ! buf.index = n_buffers; ! ! if (-1 == xioctl (fd, VIDIOC_QUERYBUF, &buf)) ! errno_exit ("VIDIOC_QUERYBUF"); ! ! buffers[n_buffers].length = buf.length; ! buffers[n_buffers].start = ! mmap (NULL /* start anywhere */, ! buf.length, ! PROT_READ | PROT_WRITE /* required */, ! MAP_SHARED /* recommended */, ! fd, buf.m.offset); ! ! if (MAP_FAILED == buffers[n_buffers].start) ! errno_exit ("mmap"); ! } ! } ! ! void init_userp (unsigned int buffer_size) { ! struct v4l2_requestbuffers req; ! ! CLEAR (req); ! ! req.count = 4; ! req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ! req.memory = V4L2_MEMORY_USERPTR; ! ! if (-1 == xioctl (fd, VIDIOC_REQBUFS, &req)) { ! if (EINVAL == errno) { ! fprintf (stderr, "%s does not support " ! "user pointer i/o\n", dev_name); ! exit (EXIT_FAILURE); ! } else { ! errno_exit ("VIDIOC_REQBUFS"); ! } ! } ! ! buffers = (buffer*) calloc (4, sizeof (*buffers)); ! ! ! if (!buffers) { ! fprintf (stderr, "Out of memory\n"); ! exit (EXIT_FAILURE); ! } ! ! for (n_buffers = 0; n_buffers < 4; ++n_buffers) { ! buffers[n_buffers].length = buffer_size; ! buffers[n_buffers].start = malloc (buffer_size); ! ! if (!buffers[n_buffers].start) { ! fprintf (stderr, "Out of memory\n"); ! exit (EXIT_FAILURE); ! } ! } ! } ! ! void init_device (void) { ! struct v4l2_capability cap; ! struct v4l2_cropcap cropcap; ! struct v4l2_crop crop; ! struct v4l2_format fmt; ! unsigned int min; ! ! if (-1 == xioctl (fd, VIDIOC_QUERYCAP, &cap)) { ! if (EINVAL == errno) { ! fprintf (stderr, "%s is no V4L2 device\n", ! dev_name); ! exit (EXIT_FAILURE); ! } else { ! errno_exit ("VIDIOC_QUERYCAP"); ! } ! } ! ! if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { ! fprintf (stderr, "%s is no video capture device\n", ! dev_name); ! exit (EXIT_FAILURE); ! } ! ! switch (io) { ! case IO_METHOD_READ: ! if (!(cap.capabilities & V4L2_CAP_READWRITE)) { ! fprintf (stderr, "%s does not support read i/o\n", ! dev_name); ! exit (EXIT_FAILURE); ! } ! ! break; ! ! case IO_METHOD_MMAP: ! case IO_METHOD_USERPTR: ! if (!(cap.capabilities & V4L2_CAP_STREAMING)) { ! fprintf (stderr, "%s does not support streaming i/o\n", ! dev_name); ! exit (EXIT_FAILURE); ! } ! ! break; ! } ! ! /* Select video input, video standard and tune here. */ ! ! cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ! ! if (-1 == xioctl (fd, VIDIOC_CROPCAP, &cropcap)) { ! /* Errors ignored. */ ! } ! ! crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ! crop.c = cropcap.defrect; /* reset to default */ ! ! if (-1 == xioctl (fd, VIDIOC_S_CROP, &crop)) { ! switch (errno) { ! case EINVAL: ! /* Cropping not supported. */ ! break; ! default: ! /* Errors ignored. */ ! break; ! } ! } ! ! CLEAR (fmt); ! ! fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ! fmt.fmt.pix.width = DEFAULT_WIDTH; ! fmt.fmt.pix.height = DEFAULT_HEIGHT; ! fmt.fmt.pix.pixelformat = DEFAULT_FORMAT; ! fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; ! ! if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt)) ! errno_exit ("VIDIOC_S_FMT"); ! ! /* Note VIDIOC_S_FMT may change width and height. */ ! ! /* Buggy driver paranoia. */ ! min = fmt.fmt.pix.width * 2; ! if (fmt.fmt.pix.bytesperline < min) ! fmt.fmt.pix.bytesperline = min; ! min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height; ! if (fmt.fmt.pix.sizeimage < min) ! fmt.fmt.pix.sizeimage = min; ! ! switch (io) { ! case IO_METHOD_READ: ! init_read (fmt.fmt.pix.sizeimage); ! break; ! ! case IO_METHOD_MMAP: ! init_mmap (); ! break; ! ! case IO_METHOD_USERPTR: ! init_userp (fmt.fmt.pix.sizeimage); ! break; ! } ! } ! ! void close_device(void) ! { ! if (-1 == close (fd)) ! errno_exit ("close"); ! ! fd = -1; ! } ! ! void open_device(void) { ! struct stat st; ! ! if (-1 == stat (dev_name, &st)) { ! fprintf (stderr, "Cannot identify '%s': %d, %s\n", ! dev_name, errno, strerror (errno)); ! exit (EXIT_FAILURE); ! } ! ! if (!S_ISCHR (st.st_mode)) { ! fprintf (stderr, "%s is no device\n", dev_name); ! exit (EXIT_FAILURE); ! } ! ! fd = open (dev_name, O_RDWR /* required */ | O_NONBLOCK, 0); ! ! if (-1 == fd) { ! fprintf (stderr, "Cannot open '%s': %d, %s\n", ! dev_name, errno, strerror (errno)); ! exit (EXIT_FAILURE); ! } ! } ! ! ! /* ! static void ! usage (FILE * fp, ! int argc, ! char ** argv) ! { ! fprintf (fp, ! "Usage: %s [options]\n\n" ! "Options:\n" ! "-d | --device name Video device name [/dev/video]\n" ! "-h | --help Print this message\n" ! "-m | --mmap Use memory mapped buffers\n" ! "-r | --read Use read() calls\n" ! "-u | --userp Use application allocated buffers\n" ! "", ! argv[0]); ! } ! ! static const char short_options [] = "d:hmru"; ! ! static const struct option ! long_options [] = { ! { "device", required_argument, NULL, 'd' }, ! { "help", no_argument, NULL, 'h' }, ! { "mmap", no_argument, NULL, 'm' }, ! { "read", no_argument, NULL, 'r' }, ! { "userp", no_argument, NULL, 'u' }, ! { 0, 0, 0, 0 } ! }; ! */ ! /* ! int ! main (int argc, ! char ** argv) ! { ! dev_name = "/dev/video"; ! ! for (;;) { ! int index; ! int c; ! ! c = getopt_long (argc, argv, ! short_options, long_options, ! &index); ! ! if (-1 == c) ! break; ! ! switch (c) { ! case 0: ! break; ! ! case 'd': ! dev_name = optarg; ! break; ! ! case 'h': ! usage (stdout, argc, argv); ! exit (EXIT_SUCCESS); ! ! case 'm': ! io = IO_METHOD_MMAP; ! break; ! ! case 'r': ! io = IO_METHOD_READ; ! break; ! ! case 'u': ! io = IO_METHOD_USERPTR; ! break; ! ! default: ! usage (stderr, argc, argv); ! exit (EXIT_FAILURE); ! } ! } ! ! open_device (); ! ! init_device (); ! ! start_capturing (); ! ! mainloop (); ! ! stop_capturing (); ! ! uninit_device (); ! ! close_device (); ! ! exit (EXIT_SUCCESS); ! ! return 0; ! } ! */ ! };//class capture ! }//namespace RobotFlow ! #endif |