zoukankan      html  css  js  c++  java
  • V4L2 camera 驱动 capture测试程序【转】

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

    在网上找了一个测试程序, 看了看,是根据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要做相应修改
  • 相关阅读:
    spring 定时任务@Scheduled
    SpringBoot几种定时任务的实现方式
    SpringBoot2.0+Mybatis+PageHelper+Redis实现缓存
    云计算之路-阿里云上-容器服务:移除节点引发博问站点短暂故障团队
    云计算之路-阿里云上:docker swarm 问题最新进展团队
    云计算之路-阿里云上:针对 docker swarm 故障的部署调整以及应急措施团队
    上周热点回顾(3.12-3.18)团队
    云计算之路-阿里云上:一夜之间竞价服务器全没了团队
    云计算之路-阿里云上:docker swarm 集群再次出现故障团队
    云计算之路-阿里云上:服务器CPU 100%问题是memcached连接数限制引起的团队
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/6904014.html
Copyright © 2011-2022 走看看