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要做相应修改
复制代码

 



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


目录
打赏
0
0
0
0
64
分享
相关文章
|
22天前
|
AppSpider Pro 7.5.015 for Windows - Web 应用程序安全测试
AppSpider Pro 7.5.015 for Windows - Web 应用程序安全测试
33 12
AppSpider Pro 7.5.015 for Windows - Web 应用程序安全测试
HCL AppScan Standard 10.8.0 (Windows) - Web 应用程序安全测试
HCL AppScan Standard 10.8.0 (Windows) - Web 应用程序安全测试
23 0
HCL AppScan Standard 10.8.0 (Windows) - Web 应用程序安全测试
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
Midscene.js 是一款基于 AI 技术的 UI 自动化测试框架,通过自然语言交互简化测试流程,支持动作执行、数据查询和页面断言,提供可视化报告,适用于多种应用场景。
776 1
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
Benchmark.NET:让 C# 测试程序性能变得既酷又简单
Benchmark.NET是一款专为 .NET 平台设计的性能基准测试框架,它可以帮助你测量代码的执行时间、内存使用情况等性能指标。它就像是你代码的 "健身教练",帮助你找到瓶颈,优化性能,让你的应用跑得更快、更稳!希望这个小教程能让你在追求高性能的路上越走越远,享受编程带来的无限乐趣!
172 13
智能化软件测试:AI驱动的自动化测试策略与实践####
本文深入探讨了人工智能(AI)在软件测试领域的创新应用,通过分析AI技术如何优化测试流程、提升测试效率及质量,阐述了智能化软件测试的核心价值。文章首先概述了传统软件测试面临的挑战,随后详细介绍了AI驱动的自动化测试工具与框架,包括自然语言处理(NLP)、机器学习(ML)算法在缺陷预测、测试用例生成及自动化回归测试中的应用实例。最后,文章展望了智能化软件测试的未来发展趋势,强调了持续学习与适应能力对于保持测试策略有效性的重要性。 ####
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
106 1
探索AI驱动的自动化测试新纪元###
本文旨在探讨人工智能如何革新软件测试领域,通过AI技术提升测试效率、精准度和覆盖范围。在智能算法的支持下,自动化测试不再局限于简单的脚本回放,而是能够模拟复杂场景、预测潜在缺陷,并实现自我学习与优化。我们正步入一个测试更加主动、灵活且高效的新时代,本文将深入剖析这一变革的核心驱动力及其对未来软件开发的影响。 ###
数据驱动测试和关键词驱动测试的区别
数据驱动测试 数据驱动测试或 DDT 也被称为参数化测试。
72 1
Kali渗透测试:远程控制程序基础
Kali渗透测试:远程控制程序基础
81 0
Kali渗透测试:远程控制程序基础
Kali渗透测试:通过Web应用程序实现远程控制
Kali渗透测试:通过Web应用程序实现远程控制
74 0

热门文章

最新文章