v4l2视频采集

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/ioctl.h>
#include<sys/mman.h>
#include<linux/videodev2.h>

int main()
{
    int fd = open("/dev/video0",O_RDWR);
    if(fd <0)
    {
       printf("open error");
       return -1;
    }
    
    struct v4l2_fmtdesc fmt;
    
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//must
    int i =0;
    while(1)
    {
            fmt.index=i++;//must 
        int ret =ioctl(fd,VIDIOC_ENUM_FMT,&fmt);
        if(ret <0){
           printf("----ioctl enum ok-- %d\n",fmt.index);
           break;
        }
        else{
            printf("fmt index:%d\n",fmt.index);
             printf("fmt flag:%d\n",fmt.flags);
              printf("fmt description: %s\n",fmt.description);
              unsigned char*ptr=&fmt.pixelformat;
               printf("fmt pixel fmt: %c %c %c %c\n",ptr[0],ptr[1],ptr[2],ptr[3]);
        }
    }
    //set cap fmt  video0:1jpeg,2YUV
    struct v4l2_format  sfmt;
    sfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    sfmt.fmt.pix.width = 1920;
    sfmt.fmt.pix.height =1080;
    sfmt.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;
    int ret =ioctl(fd,VIDIOC_S_FMT,&sfmt);
    if(ret <0)
    {
        printf("set fmt error\n");
        
    }
    
    struct v4l2_format  sfmt2;
    sfmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    
    ret =ioctl(fd,VIDIOC_G_FMT,&sfmt2);
    if(ret <0)
    {
        printf("set fmt error\n");
        
    }else{
    //设置的与实际采集得到的可能并不一样,比如设置1080P,实际采集的是720P
     printf("sfmt.fmt.pix.width %d\n",sfmt.fmt.pix.width);
     printf("sfmt.fmt.pix.height %d\n",sfmt.fmt.pix.height);
    
    }
    
    //malloc kernal space
    struct v4l2_requestbuffers v4l2buf;
    v4l2buf.type= V4L2_BUF_TYPE_VIDEO_CAPTURE;
    v4l2buf.count = 4;//max is 4
    v4l2buf.memory = V4L2_MEMORY_MMAP;//ying she
    ret =ioctl(fd,VIDIOC_REQBUFS,&v4l2buf);
    if(ret <0)
    {
        printf("req memory error");
    }
    //printf("-----------------2--------------\n");
    //map
    struct v4l2_buffer buf;
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    unsigned char* mptr[4];//save map to user mem first address
    int lensize[4];
    //check kernal memory
    for(int i =0;i<4;i++)
    {
        buf.index = i;
        ret =ioctl(fd,VIDIOC_QUERYBUF,&buf);
        if(ret <0)
        {
            printf("check kernal mem error\n");
        }else{
          //map user memory
          mptr[i]=mmap(NULL,buf.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,buf.m.offset);
          lensize[i] = buf.length;
          //use over
          ret =ioctl(fd,VIDIOC_QBUF,&buf);
          if(ret<0)
          {
             printf("mmp error");
          }
        }
    }
    //printf("-----------------3--------------\n");
    //start cap
    int type =V4L2_BUF_TYPE_VIDEO_CAPTURE;
    ret = ioctl(fd,VIDIOC_STREAMON,&type);
    if(ret <0)
    {
        printf("stream on error");
    }
    //printf("-----------------3-0-------------\n");
    
    //get data from queue
    FILE* fp=fopen("./m.yuyv","w+");
    int capnum =100;
    while(capnum-- >0)//帧率有单独的控制属性可以设置
    {
        
        struct v4l2_buffer readbuf;
        readbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        ret =ioctl(fd,VIDIOC_DQBUF,&readbuf);//use virtul machine usb 3.1,or not will hold
        if(ret <0)
        {
            printf("read data error");
        }else{
            
            int size = fwrite(mptr[readbuf.index],readbuf.length,1,fp);
            fflush(fp);
            printf("write size:%d",size);
            ret = ioctl(fd,VIDIOC_QBUF,&readbuf);
            
            if(ret <0)
            {
            printf("qbuf error\n");
            }
            
        }
    
    }
    printf("-----------------4--------------\n");
    //stop cap
    ret = ioctl(fd,VIDIOC_STREAMOFF,&type);
    if(ret <0)
    {
        printf("stop error\n");
    }
    //release map
    
    for(int i = 0;i<4;i++)
    {
      munmap(mptr[i],lensize[i]);
    }
    
    fclose(fp);
    close(fd);
    return 0;
}
 

 

 

posted on 2025-08-10 19:39  邗影  阅读(7)  评论(0)    收藏  举报

导航