zoukankan      html  css  js  c++  java
  • 4412 使用usb摄像头拍照YUYV格式

    一、内核设置

    Linux内核中已经带有很完善的USB摄像头驱动,支持几乎所有的USB摄像头,我们只需要配置内核,选择上相应的Sensor型号即可。

    配置内核,支持USB摄像头:
        Device Drivers --->
            <*> Multimedia support --->
                <*> Video For Linux
                [*] Enable Video For Linux API 1 (DEPRECATED)
                [*] Video capture adapters --->
                    [*] V4L USB devices --->
                        <*> USB Video Class (UVC)
                        [*] UVC input events device support
                        [*] GSPCA based webcams --->
    到这里,我们就可以选择所需要的USB摄像头驱动,当然也可以选择所有的USB摄像头驱动支持(这样编译出的内核会比较大)
    GSPCA是一个万能摄像头驱动程序,进入GSPCA based webcams进行选择。
     
    插入USB摄像头(我使用的UVC摄像头),会提示:
    usb 1-1.1: new full speed USB device using s3c2410-ohci and address 3
    usb 1-1.1: New USB device found, idVendor=0ac8, idProduct=3450
    usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
    usb 1-1.1: Product: Deasy USB2.0 Camera
    usb 1-1.1: Manufacturer: Vimicro Corp.
    uvcvideo: Found UVC 1.00 device Deasy USB2.0 Camera (0ac8:3450)
    input: Deasy USB2.0 Camera as 
    /devices/platform/s3c2410-ohci/usb1/1-1/1-1.1/1-1.1:1.0/input/input3
     
    它的设备名称是:/dev/video0
    USB摄像头一般都是基于V4L2架构的,需要编写V4L2架构的程序来操作摄像头

    二、编写V4L2的应用程序

    #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 <malloc.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>
    
    #define CAMERA_DEVICE "/dev/video0"
    #define CAPTURE_FILE "frame.jpg"
    
    #define VIDEO_WIDTH  640
    #define VIDEO_HEIGHT 480
    #define VIDEO_FORMAT V4L2_PIX_FMT_YUYV
    #define BUFFER_COUNT 4
    
    typedef struct VideoBuffer {
        void *start;
        size_t length;
    }VideoBuffer;
    
    int fd;             //摄像头文件描述符
    
    void open_camera(char *path);
    void get_camera_info();
    void get_vedio_info();
    
    //打开设备
    void open_camera(char *path)
    {
        fd = open(CAMERA_DEVICE, O_RDWR, 0);
        if(fd < 0) {
            printf("Open %s failed
    ", CAMERA_DEVICE);
            exit(EXIT_FAILURE);
        }
    }
    
    //获取驱动信息
    void get_camera_info()
    {
        struct v4l2_capability cap;
        ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
        if(ret < 0) {
            printf("VIDIOC_QUERYCAP failed (%d)
    ", ret);
            return ret;
        }
        // Print capability informations
        printf("Capbility Informations:
    ");
        printf("*	driver: %s
    ", cap.driver);
        printf("*	card: %s
    ", cap.card);
        printf("*	bus_info: %s
    ", cap.bus_info);
        printf("*	version: %08X
    ", cap.version);
        printf("*	capabilities: %08X
    ", cap.capabilities);
    }
    
    //获取视频格式
    void get_vedio_info()
    {
        struct v4l2_format fmt;
        memset(&fmt, 0, sizeof(fmt));
        fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        ret = ioctl(fd, VIDIOC_G_FMT, &fmt);
        if(ret < 0) {
            printf("VIDIOC_G_FMT failed (%d)
    ", ret);
            return ret;
        }
        // Print Stream Format
        printf("Stream Format Informations:
    ");
        printf("*	type: %d
    ", fmt.type);
        printf("*	 %d
    ", fmt.fmt.pix.width);
        printf("*	height: %d
    ", fmt.fmt.pix.height);
    
        char fmtstr[8];
        memset(fmtstr, 0, 8);
        memcpy(fmtstr, &fmt.fmt.pix.pixelformat, 4);
        printf("*	pixelformat: %s
    ", fmtstr);
        printf("*	field: %d
    ", fmt.fmt.pix.field);
        printf("*	bytesperline: %d
    ", fmt.fmt.pix.bytesperline);
        printf("*	sizeimage: %d
    ", fmt.fmt.pix.sizeimage);
        printf("*	colorspace: %d
    ", fmt.fmt.pix.colorspace);
        printf("*	priv: %d
    ", fmt.fmt.pix.priv);
        //    printf("*	raw_data: %s
    ", fmt.fmt.raw_data);
    
        /* 显示所有支持的格式 */
        struct v4l2_fmtdesc fmtdesc;
        fmtdesc.index = 0;
        fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        printf("Support format:
    ");
        while(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) != -1) {
            printf("	%d.%s
    ", fmtdesc.index+1, fmtdesc.description);
            fmtdesc.index++;
        }
    }
    
    int main()
    {
        int i, ret;
        open_camera(CAMERA_DEVICE);
        
        get_camera_info();
        
        get_vedio_info();
    
        //请求分配内存
        struct v4l2_requestbuffers reqbuf;
        reqbuf.count = BUFFER_COUNT;
        reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        reqbuf.memory = V4L2_MEMORY_MMAP;
        ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuf);
        if(ret < 0) {
            printf("VIDIOC_REQBUFS failed (%d)
    ", ret);
            return ret;
        }
        //获取空间
        VideoBuffer *buffers = calloc(reqbuf.count, sizeof(*buffers));
        if(!buffers) {
            //映射
            fprintf(stderr, "Out of memory
    ");
            exit(EXIT_FAILURE);
        }    
    
        for(i=0;i<reqbuf.count;i++) {
            struct v4l2_buffer buf;
            memset(&buf, 0, sizeof(buf));
            buf.index = i;
            buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            buf.memory = V4L2_MEMORY_MMAP;
            ret = ioctl(fd, VIDIOC_QUERYBUF, &buf);
            if(ret < 0) {
                printf("VIDIOC_QUERYBUF (%d) failed (%d)
    ", i, ret);
                return ret;
            }
            // mmap buffer
            buffers[i].length = buf.length;
            buffers[i].start = (char *)mmap(0, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, 
                fd, buf.m.offset);
            if(buffers[i].start == MAP_FAILED) {
                printf("mmap (%d) failed: %s
    ", i, strerror(errno));
                return -1;
            }
    
            // Queen buffer
            ret = ioctl(fd, VIDIOC_QBUF, &buf);
            if(ret < 0) {
                printf("VIDIOC_QBUF (%d) failed (%d)
    ", i, ret);
                return -1;
            }
    
            printf("Frame buffer: %d: address=0x%x, length=%d
    ", i,
                (unsigned int)buffers[i].start, buffers[i].length);
        }
    
        // 开始录制
        struct v4l2_buffer buf;
        enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.index = 0;
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        ret = ioctl(fd, VIDIOC_STREAMON, &type);
        if (ret < 0) {
            printf("VIDIOC_STREAMON failed (%d)
    ", ret);
            return ret;
        }
    
        // Get frame
        ret = ioctl(fd, VIDIOC_DQBUF, &buf);
        if (ret < 0) {
            printf("VIDIOC_DQBUF failed (%d)
    ", ret);
            return ret;
        }
    
        // Process the frame
        FILE *fp = fopen(CAPTURE_FILE, "wb");
        if (fp < 0) {
            printf("open frame data file failed
    ");
            return -1;
        }
        fwrite(buffers[buf.index].start, 1, buf.length, fp);
        fclose(fp);
        printf("Capture one frame saved in %s
    ", CAPTURE_FILE);
    
        // Re-queen buffer
        ret = ioctl(fd, VIDIOC_QBUF, &buf);
        if (ret < 0) {
            printf("VIDIOC_QBUF failed (%d)
    ", ret);
            return ret;
        }
    
        // Release the resource
        for(i=0;i<4;i++) {
            munmap(buffers[i].start, buffers[i].length);
        }
    
        close(fd);
        printf("Camera test Done.
    ");
        return 0;
    }

    三、使用软件打开

    不过要选择对应的格式:

  • 相关阅读:
    Intel 编译器 线程安全检查 真心的很详细 转
    当前软件设计分析
    当代并行机系统
    多人游戏服务器
    ACE源代码目录结构
    (转!)Z buffer和W buffer简介
    数据库-视图(View)详解
    推荐一个vs自带工具分析代码的复杂度
    SCOPE_IDENTITY的用法
    vs2013开发调试cocos2d-x-Lua工程项目
  • 原文地址:https://www.cnblogs.com/ch122633/p/9821784.html
Copyright © 2011-2022 走看看