V4L2 camera 驱动 capture测试程序【转】

转自:http://blog.csdn.net/kickxxx/article/details/6336346

V4L2 camera 驱动 capture测试程序【转】
在网上找了一个测试程序, 看了看,是根据capture.c修改的。测试步骤如下

1. gcc -o capture_image capture_image.c

2. ctrl+alt+f1 切换到ubuntu的控制台,切换到控制台模式是因为在图形模式下看不到测试图形,这可能和framebuffer的设置有关

3. sudo modprobe vivi

4. sudo ./capture_image -d /dev/video0

 

这时可以看到在屏幕左上角有一个640x480大小窗口,内容是彩色条格,彩色条格不停的移动,持续时间5秒

 

在ubuntu下还可以使用cheese测试

1.  sudo apt-get install cheese

2. sudo modprobe vivi

2. 启动 cheese后,就可以看到滚动的彩色条格


附上测试程序

[c-sharp] view plain copy

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <string.h>  
    #include <assert.h>  
    #include <getopt.h>    
    #include <fcntl.h>    
    #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>  
    #include <Linux/videodev2.h>  
    #include <linux/fb.h>  
    #define CLEAR(x) memset (&(x), 0, sizeof (x))  
       
    struct buffer {  
        void * start;  
        size_t length;  
    };  
       
    static char * dev_name = NULL;  
    static int fd = -1;  
    struct buffer * buffers = NULL;  
    static unsigned int n_buffers = 0;  
    static int time_in_sec_capture=5;  
    static int fbfd = -1;  
    static struct fb_var_screeninfo vinfo;  
    static struct fb_fix_screeninfo finfo;  
    static char *fbp=NULL;  
    static long screensize=0;  
       
    static void errno_exit (const char * s)  
    {  
        fprintf (stderr, "%s error %d, %s/n",s, errno, strerror (errno));  
        exit (EXIT_FAILURE);  
    }  
       
    static int xioctl (int fd,int request,void * arg)  
    {  
        int r;  
        do r = ioctl (fd, request, arg);  
        while (-1 == r && EINTR == errno);  
        return r;  
    }  
       
    inline int clip(int value, int min, int max) {  
        return (value > max ? max : value < min ? min : value);  
      }  
       
    static void process_image (const void * p){  
       
          
        //ConvertYUVToRGB32  
        1;  
        unsigned char* in=(char*)p;  
        int width=640;  
        int height=480;  
        int istride=1280;  
        int x,y,j;  
        int y0,u,y1,v,r,g,b;  
        long location=0;  
       
        for ( y = 100; y < height + 100; ++y) {  
            for (j = 0, x=100; j < width * 2 ; j += 4,x +=2) {  
              location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +  
                (y+vinfo.yoffset) * finfo.line_length;  
                  
              y0 = in[j];  
              u = in[j + 1] - 128;                  
              y1 = in[j + 2];          
              v = in[j + 3] - 128;          
       
              r = (298 * y0 + 409 * v + 128) >> 8;  
              g = (298 * y0 - 100 * u - 208 * v + 128) >> 8;  
              b = (298 * y0 + 516 * u + 128) >> 8;  
              
              fbp[ location + 0] = clip(b, 0, 255);  
              fbp[ location + 1] = clip(g, 0, 255);  
              fbp[ location + 2] = clip(r, 0, 255);      
              fbp[ location + 3] = 255;      
       
              r = (298 * y1 + 409 * v + 128) >> 8;  
              g = (298 * y1 - 100 * u - 208 * v + 128) >> 8;  
              b = (298 * y1 + 516 * u + 128) >> 8;  
       
               fbp[ location + 4] = clip(b, 0, 255);  
              fbp[ location + 5] = clip(g, 0, 255);  
              fbp[ location + 6] = clip(r, 0, 255);      
              fbp[ location + 7] = 255;      
              }  
            in +=istride;  
           }  
    }  
       
    static int read_frame (void)  
    {  
        struct v4l2_buffer buf;  
        unsigned int i;  
       
        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:      
       
              
       
            default:  
                errno_exit ("VIDIOC_DQBUF");  
            }  
        }  
       
        assert (buf.index < n_buffers);  
        printf("v4l2_pix_format->field(%d)/n", buf.field);  
        //assert (buf.field ==V4L2_FIELD_NONE);  
        process_image (buffers[buf.index].start);  
        if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))  
            errno_exit ("VIDIOC_QBUF");  
       
        return 1;  
    }  
       
    static void run (void)  
    {  
        unsigned int count;  
        int frames;  
        frames = 30 * time_in_sec_capture;  
       
        while (frames-- > 0) {  
            for (;;) {  
                fd_set fds;  
                struct timeval tv;  
                int r;  
                FD_ZERO (&fds);  
                FD_SET (fd, &fds);  
       
                  
                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;  
                  
                }  
        }  
    }  
       
    static void stop_capturing (void)  
    {  
        enum v4l2_buf_type type;  
       
        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
        if (-1 == xioctl (fd, VIDIOC_STREAMOFF, &type))  
            errno_exit ("VIDIOC_STREAMOFF");  
    }  
       
    static void start_capturing (void)  
    {  
        unsigned int i;  
        enum v4l2_buf_type type;  
       
        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");  
          
    }  
       
    static void uninit_device (void)  
    {  
        unsigned int i;  
       
        for (i = 0; i < n_buffers; ++i)  
            if (-1 == munmap (buffers[i].start, buffers[i].length))  
                errno_exit ("munmap");  
          
        if (-1 == munmap(fbp, screensize)) {  
              printf(" Error: framebuffer device munmap() failed./n");  
              exit (EXIT_FAILURE) ;  
            }      
        free (buffers);  
    }  
       
       
    static void init_mmap (void)  
    {  
        struct v4l2_requestbuffers req;  
       
        //mmap framebuffer  
            fbp = (char *)mmap(NULL,screensize,PROT_READ | PROT_WRITE,MAP_SHARED ,fbfd, 0);  
            if ((int)fbp == -1) {  
                printf("Error: failed to map framebuffer device to memory./n");  
                exit (EXIT_FAILURE) ;  
            }  
        memset(fbp, 0, screensize);  
        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 < 4) {    //if (req.count < 2)  
            fprintf (stderr, "Insufficient buffer memory on %s/n",dev_name);  
            exit (EXIT_FAILURE);  
        }  
       
        buffers = 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,buf.length,PROT_READ | PROT_WRITE ,MAP_SHARED,fd, buf.m.offset);  
       
            if (MAP_FAILED == buffers[n_buffers].start)  
                errno_exit ("mmap");  
        }  
       
    }  
       
       
       
    static void init_device (void)  
    {  
        struct v4l2_capability cap;  
        struct v4l2_cropcap cropcap;  
        struct v4l2_crop crop;  
        struct v4l2_format fmt;  
        unsigned int min;  
       
       
        // Get fixed screen information  
          if (-1==xioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)) {  
                printf("Error reading fixed information./n");  
                exit (EXIT_FAILURE);  
            }  
       
            // Get variable screen information  
         if (-1==xioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {  
                printf("Error reading variable information./n");  
                exit (EXIT_FAILURE);  
           }  
        screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;  
       
       
        if (-1 == xioctl (fd, VIDIOC_QUERYCAP, ∩)) {  
            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);  
        }  
       
        if (!(cap.capabilities & V4L2_CAP_STREAMING)) {  
            fprintf (stderr, "%s does not support streaming i/o/n",dev_name);  
            exit (EXIT_FAILURE);  
        }  
       
          
       
        CLEAR (cropcap);  
       
        cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
       
        if (0 == xioctl (fd, VIDIOC_CROPCAP, &cropcap)) {  
            crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
            crop.c = cropcap.defrect;  
       
            if (-1 == xioctl (fd, VIDIOC_S_CROP, &crop)) {  
                switch (errno) {  
                case EINVAL:      
                break;  
                default:  
                break;  
                }  
            }  
        }else {     }  
       
        CLEAR (fmt);  
       
        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
        fmt.fmt.pix.width = 640;    
        fmt.fmt.pix.height = 480;  
        fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;  
        fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;  
       
        if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt))  
            errno_exit ("VIDIOC_S_FMT");  
       
        init_mmap ();  
       
    }  
       
    static void close_device (void)  
    {  
        if (-1 == close (fd))  
        errno_exit ("close");  
        fd = -1;  
        close(fbfd);  
    }  
       
    static 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);  
        }  
       
        //open framebuffer  
            fbfd = open("/dev/fb0", O_RDWR);  
            if (fbfd==-1) {  
                printf("Error: cannot open framebuffer device./n");  
                exit (EXIT_FAILURE);  
            }  
       
        //open camera  
        fd = open (dev_name, O_RDWR| 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"  
    "-t | --how long will display in seconds/n"  
    "",  
    argv[0]);  
    }  
       
    static const char short_options [] = "d:ht:";  
    static const struct option long_options [] = {  
    { "device", required_argument, NULL, 'd' },  
    { "help", no_argument, NULL, 'h' },  
    { "time", no_argument, NULL, 't' },  
    { 0, 0, 0, 0 }  
    };  
       
    int main (int argc,char ** argv)  
        {  
        dev_name = "/dev/video0";  
       
        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 't':  
               time_in_sec_capture = atoi(optarg);  
                 break;  
       
            default:  
            usage (stderr, argc, argv);  
            exit (EXIT_FAILURE);  
            }  
    }  
       
        open_device ();  
       
        init_device ();  
       
        start_capturing ();  
       
        run ();  
       
        stop_capturing ();  
       
        uninit_device ();  
       
        close_device ();  
       
        exit (EXIT_SUCCESS);  
       
    return 0;  
    }  

 

这个测试程序是根据vivi驱动hard code的, 并不一定适合其他的camera驱动
比如,我手头上的logitech stv06xx usb camera, 因为不支持640x480模式,参见代码59 60行,
代码348行 if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt)) 应该是个协商的过程,
343   fmt.fmt.pix.width = 640;   
344   fmt.fmt.pix.height = 480; 
345   fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; 
346   fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; 
这几行只是应用的期望格式,驱动会根据这个格式选择一个相近的格式返回,应用最后的显示处理要根据返回的格式进行处理,即process_image要做相应修改
V4L2 camera 驱动 capture测试程序【转】

 



本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sky-heaven/p/6904014.html,如需转载请自行联系原作者


上一篇:在Winform开发框架中,利用DevExpress控件实现数据的快速录入和选择


下一篇:LG发布新专利,将为VR头显集成眼球追踪技术