linux打开V4L2摄像头视频流(MJPEG格式)

    参考链接:https://blog.csdn.net/tugouxp/article/details/118516385
    源码:ls /dev/ 查看摄像头是video编号比如:video0 video1

    点击查看代码
     
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/mman.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <string.h>
    #include <stdlib.h>
    #include <linux/videodev2.h>
    #include<sys/ioctl.h>
    #include <setjmp.h>
    #include <unistd.h>
     
    #define CAM_DEV "/dev/video14"
    #define   WIDTH   1920                       // 图片的宽度
    #define   HEIGHT  1080                       // 图片的高度
    #define  NB_BUFFER  4   //memory block number
    struct pic_data 
    {
        unsigned char *tmpbuffer[NB_BUFFER];
        unsigned int tmpbytesused[NB_BUFFER];
    }pic;
     
    int cam_fd;
     
    /*
    Description.:Initalize V4L2 driver.
    */
    int v4l2_init(void)
    {
        int i;
        int ret = 0;
     
        // 1、Open camera device
        if((cam_fd = open(CAM_DEV,O_RDWR)) == -1)
        {
            perror("ERROR opening V4L interface.");
            return -1;
        }
     
        // 2、Judge if the device is a camera device 
        struct v4l2_capability cam_cap;
        if(ioctl(cam_fd,VIDIOC_QUERYCAP,&cam_cap) == -1)
        {
            perror("Error opening device %s: unable to query device.");
            return -1;
        }
        if((cam_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) 
        {
            perror("ERROR video capture not supported.");
            return -1;
        }
     
        // 3、Setting output parameter.
        struct v4l2_format v4l2_fmt;
        v4l2_fmt.type = V4L2_CAP_VIDEO_CAPTURE;
        v4l2_fmt.fmt.pix.width = WIDTH;
        v4l2_fmt.fmt.pix.height = HEIGHT;
        v4l2_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
        if (ioctl (cam_fd, VIDIOC_S_FMT, &v4l2_fmt) == -1) 
        {   
            perror("ERROR camera VIDIOC_S_FMT Failed.");
            return -1;
        }
        // 4、Check whether the parameters are set successfully 
        if (ioctl (cam_fd, VIDIOC_G_FMT, &v4l2_fmt) == -1) 
        {
            perror("ERROR camera VIDIOC_G_FMT Failed.");
            return -1;
        }
        if (v4l2_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
        {
            printf("Set VIDIOC_S_FMT sucessful\n");
        }
        // 5、Require buffer to store image data
        struct v4l2_requestbuffers v4l2_req;
        v4l2_req.count = NB_BUFFER;
        v4l2_req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        v4l2_req.memory = V4L2_MEMORY_MMAP;
        if (ioctl (cam_fd, VIDIOC_REQBUFS, &v4l2_req) == -1) 
        {
            perror("ERROR camera VIDIOC_REQBUFS Failed.");
            return -1;
        } 
        // 6、Start memory map
        struct v4l2_buffer v4l2_buf;
        v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        v4l2_buf.memory = V4L2_MEMORY_MMAP;
          for(i = 0; i < NB_BUFFER; i++) 
       {
            v4l2_buf.index = i;
            if(ioctl(cam_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0)
            {
                perror("Unable to query buffer.");
                return -1;
            }
     
            pic.tmpbuffer[i] = (unsigned char*)mmap(NULL, v4l2_buf.length, PROT_READ, MAP_SHARED, cam_fd, v4l2_buf.m.offset);
            if(pic.tmpbuffer[i] == MAP_FAILED)
            {
                 perror("Unable to map buffer.");
                 return -1;
            }
            if(ioctl(cam_fd, VIDIOC_QBUF, &v4l2_buf) < 0)
            {
                perror("Unable to queue buffer.");
                return -1;
            }
       }
        //7、Open stream input 
        int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        if(ioctl(cam_fd, VIDIOC_STREAMON, &type) < 0)
        {
            perror("Unable to start capture.");
            return -1;
        }
        return 0;
    }
     
    /*
    Description.:Get a jpeg image and save.
    */
    int v4l2Grab(void)
    {
        //8、Get a image 
        struct v4l2_buffer buff;
        buff.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buff.memory = V4L2_MEMORY_MMAP;
        if(ioctl(cam_fd, VIDIOC_DQBUF, &buff) < 0)
        {
            printf("camera VIDIOC_DQBUF Failed.\n");
            usleep(1000*1000);
            return -1;
        }
     
        pic.tmpbytesused[buff.index] = buff.bytesused;
        printf("size : %d\n",pic.tmpbytesused[buff.index]);           
     
        //9、Save image.
        /*
        int jpg_fd = open("1.jpeg",O_RDWR|O_CREAT,00700);
        if(jpg_fd == -1)
        {
            printf("open ipg Failed!\n ");
            return -1;      
        }
        int writesize = write(jpg_fd, pic.tmpbuffer[buff.index], pic.tmpbytesused[buff.index]);
        printf("Write successfully size : %d\n",writesize);
        close(jpg_fd);
        */
        //10、Queue the buffers.
        if(ioctl(cam_fd, VIDIOC_QBUF, &buff) < 0)
        {
            printf("camera VIDIOC_QBUF Failed.");
            usleep(1000*1000);
            return -1;
        }
        return 0;
    }
     
    /*
    Description.:Release resource
    */
    int v4l2_close(void)
    {
        // Remove mmap.
        int i;
        for(i=0; i<NB_BUFFER; i++)
            munmap(pic[0].tmpbuffer[i],pic[0].tmpbytesused[i]);
        close(cam_fd);
        return 0;
    }
     
    /*
    Description.:main
    */
    int main(int argc, char* argv[])
    {
        v4l2_init();
        while(1)
        {        
            v4l2Grab();
        }
        v4l2_close();            
        return 0;
    }
    
    posted @   相对维度  阅读(751)  评论(0编辑  收藏  举报
    相关博文:
    阅读排行:
    · 全程不用写代码,我用AI程序员写了一个飞机大战
    · DeepSeek 开源周回顾「GitHub 热点速览」
    · MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
    · 记一次.NET内存居高不下排查解决与启示
    · 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
    点击右上角即可分享
    微信分享提示