开发者社区> sky-heaven> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

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

简介: 转自:http://blog.csdn.net/kickxxx/article/details/6336346 在网上找了一个测试程序, 看了看,是根据capture.c修改的。测试步骤如下 1.
+关注继续查看

转自: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
【twitter】 @sky2030_
【facebook】 张昺华 zhangbinghua
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
二进制安装Kubernetes(k8s) v1.24.1 IPv4/IPv6双栈 --- Ubuntu版本
本文是使用的是Ubuntu作为基底,其他文档请在GitHub上查看。 1.23.3 和 1.23.4 和 1.23.5 和 1.23.6 和 1.24.0 和1.24.1 文档以及安装包已生成。 我使用IPV6的目的是在公网进行访问,所以我配置了IPV6静态地址。 若您没有IPV6环境,或者不想使用IPv6,不对主机进行配置IPv6地址即可。 不配置IPV6,不影响后续,不过集群依旧是支持IPv6的。为后期留有扩展可能性。 https://github.com/cby-chen/Kubernetes/
94 0
团体程序设计天梯赛-练习集 - L2-012 关于堆的判断(25 分)
团体程序设计天梯赛-练习集 - L2-012 关于堆的判断(25 分)
12 0
SAP UI5 初学者教程之十二 - 使用 CSS 类对 UI 进行进一步美化试读版
一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 初学者教程之一:Hello World SAP UI5 初学者教程之二:SAP UI5 的引导过程 Bootstrap SAP UI5 初学者教程之三:开始接触第一个 SAP UI5 控件 SAP UI5 初学者教程之四:XML 视图初探 SAP UI5 初学者教程之五:视图控制器初探 SAP UI5 初学者教程之六 - 了解 SAP UI5 的模块(Module)概念 SAP UI5 初学者教程之七 - JSON 模型初探 SAP UI5 初学者教程之八 - 多语
35 0
【FFmpeg】ffplay 播放视频命令 ( 播放 | 暂停 | 停止 | 音量控制 | 进度控制 | 音频流 / 视频流 / 字幕流 / 节目切换 )(一)
【FFmpeg】ffplay 播放视频命令 ( 播放 | 暂停 | 停止 | 音量控制 | 进度控制 | 音频流 / 视频流 / 字幕流 / 节目切换 )(一)
292 0
【1-20 报名中】Kubernetes and Cloud Native Meetup 广州站
Kubernetes and Cloud Native Meetup 首次登陆广州,邀请到了来自阿里巴巴、阿里云的技术专家,Kubernetes 社区成员,视源股份(CVTE)技术专家和大家分享阿里内部的 Kubernetes 实践。
4092 0
C#进阶系列——使用Advanced Installer制作IIS安装包(二:配置安装包依赖项和自定义dll)
原文:C#进阶系列——使用Advanced Installer制作IIS安装包(二:配置安装包依赖项和自定义dll) 前言:上篇C#进阶系列——使用Advanced Installer制作IIS安装包(一:配置IIS和Web.config)介绍了下使用Advanced Installer配置IIS和Web.config的过程,操作起来是相对比较简单的,只要知道了博主提供的方法,相信都不是问题,其实博主当初寻找相关方法配置IIS和Web.config的时候也是费了九牛二虎之力的,毕竟资料太少,只能各种方式挨个尝试一遍,解决问题之后回过头来看,发现当初也是走了很多的弯路。
1048 0
Virtualbox报错------> '/etc/init.d/vboxdrv setup'
Ubuntu下VirtualBox本来可以很好地用的,今天早上一来就报错了,……提示如下内容: ------------------------------------------------------------------------- Kernel driver not inst...
763 0
+关注
sky-heaven
我是一个技术爱好者,喜欢分享交流技术心得
1191
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载