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; }