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