zoukankan      html  css  js  c++  java
  • [国嵌攻略][171][V4L2图像编程接口深度学习]

    V4L2摄像编程模型

    1.打开摄像头设备文件

    2.获取驱动信息-VIDIOC_QUERYCAP

    3.设置图像格式-VIDIOC_S_FMT

    4.申请帧缓冲-VIDIOC_REQBUFS

    5.获取帧缓冲的地址长度信息-VIDIOC_QUERYBUF

    6.使用mmap把内核空间的帧缓冲映射到用户空间

    7.帧缓冲入队列-VIDIOC_QBUF

    8.开始采集图像-VIDIOC_STREAMON

    9.取出帧缓冲(出队)-VIDIOC_DQBUF

    10.访问帧缓冲

    11.帧缓冲重新入队-VIDIOC_QBUF

    USB摄像头驱动工作流程

    摄像头驱动从输入队列中取出一个帧缓冲,放到输出队列中。

    应用程序从输出队列中取出一个帧缓冲,读取数据后,再把帧缓冲放入输入缓存中。

    camera.c

    #include <stdio.h>
    #include <malloc.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    #include <linux/videodev2.h>
    
    struct buffer{
        void *start;   //帧缓冲地址
        int  length;   //帧缓冲长度
    };
    
    int main(int argc, char **argv){
        //创建图片文件
        int fd_img;
        
        fd_img = open("img.jpg", O_RDWR | O_CREAT, 0777);
        
        //打开设备文件
        int fd_dev;
        
        fd_dev = open("/dev/video0", O_RDWR | O_NONBLOCK, 0);
        
        //获取驱动信息
        struct v4l2_capability cap;
        
        ioctl(fd_dev, VIDIOC_QUERYCAP, &cap);
        
        printf("Driver name:%s
    Card name:%s
    Bus info:%s
    
    ", cap.driver, cap.card, cap.bus_info);
        
        //设置图像格式
        struct v4l2_format fmt;
        
        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        fmt.fmt.pix.width = 320;
        fmt.fmt.pix.height = 240;
        fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
        fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
        
        ioctl(fd_dev, VIDIOC_S_FMT, &fmt);
        
        //申请图像缓冲
        struct v4l2_requestbuffers req;
        
        req.count = 4;
        req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        req.memory = V4L2_MEMORY_MMAP;
        
        ioctl(fd_dev, VIDIOC_REQBUFS, &req);
        
        //映射用户空间
        int i;
        struct buffer *buffs;
        struct v4l2_buffer buff;
    
        buffs = calloc(req.count, sizeof(*buffs));
        
        for(i = 0; i < req.count; i++){
            //获取缓冲长度
            buff.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            buff.memory = V4L2_MEMORY_MMAP;
            buff.index = i;
            
            ioctl(fd_dev, VIDIOC_QUERYBUF, &buff);
            
            buffs[i].length = buff.length;
            
            //映射缓冲地址
            buffs[i].start = mmap(NULL, buff.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd_dev, buff.m.offset);
        }
        
        //图像缓冲入队
        for(i = 0; i < req.count; i++){
            buff.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            buff.memory = V4L2_MEMORY_MMAP;
            buff.index = i;
            
            ioctl(fd_dev, VIDIOC_QBUF, &buff);
        }
        
        //捕获图像数据
        enum v4l2_buf_type type;
        
        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        ioctl(fd_dev, VIDIOC_STREAMON, &type);
        
        //等待捕获完成
        fd_set fds;
        
        FD_ZERO(&fds);
        FD_SET(fd_dev, &fds);
        
        select(fd_dev + 1, &fds, NULL, NULL, NULL);
        
        //图像缓冲出队
        buff.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buff.memory = V4L2_MEMORY_MMAP;
        
        ioctl(fd_dev, VIDIOC_DQBUF, &buff);
        
        //读取图像数据
        write(fd_img, buffs[buff.index].start, buffs[buff.index].length);
        
        //图像缓冲入队
        ioctl(fd_dev, VIDIOC_QBUF, &buff);
        
        //释放用户空间
        for(i = 0; i < req.count; i++){
            munmap(buffs[i].start, buffs[i].length);
        }
        
        //关闭打开文件
        close(fd_dev);
        close(fd_img);
        
        printf("Camera done!
    ");
        
        return 0;
    }
  • 相关阅读:
    2018年4月22日笔记
    2018年4月19日笔记
    2018年4月17日笔记
    2018年4月14日笔记
    2018年4月12日笔记
    课堂练习找水王
    评价软件
    第十一周进度条
    典型用户场景、用户场景描述
    构建之法阅读笔记04
  • 原文地址:https://www.cnblogs.com/d442130165/p/5341147.html
Copyright © 2011-2022 走看看