#include <iostream>
#include <unistd.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <cstdio>
#include <fcntl.h>
#include <cstring>
#include <sys/mman.h>//for ying she
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <vector>
#include <pthread.h>
using namespace cv;
using namespace std;
unsigned char *mptr[2];//保存映射后用户空间的首地址
unsigned int length[2];
int ret;
int fd;
typedef struct{
Mat img;
}mystruct;
void* window1(void* args)
{
//pthread_detach(pthread_self());
mystruct *a = (mystruct *) args;
imshow("img1",a->img);
return NULL;
}
void* window2(void* args)
{
//pthread_detach(pthread_self());
mystruct *a = (mystruct *) args;
//if(waitKey(10)=='f')
{
imshow("img2",a->img);
}
return NULL;
}
int main() {
Mat img;
mystruct arg;
namedWindow("img1",WINDOW_AUTOSIZE);
namedWindow("img2",WINDOW_AUTOSIZE);
pthread_t th1;//定义一个新的线程
pthread_t th2;
/* 1.open the device */
fd = open("/dev/video0",O_RDWR);
if (fd < 0 )
{
perror("open fail\n");
return -1;
}
/* 2.get format */
struct v4l2_fmtdesc v4fmt;
v4fmt.index = 0;// ditterent from the video
v4fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd, VIDIOC_ENUM_FMT,&v4fmt);// ioctl(fd , command , struct related to the command)
if (ret < 0 )
{
perror("get fail\n");
return -1;
}
printf("index=%d\n",v4fmt.index);
printf("flags=%d\n",v4fmt.flags);
printf("description=%s\n",v4fmt.description);
unsigned char *p=(unsigned char *)&v4fmt.pixelformat;
printf("pixelformat=%c%c%c%c\n",p[0],p[1],p[2],p[3]);
printf("reserved=%d\n",v4fmt.reserved[0]);
/* 3.set capturing format */
struct v4l2_format vfmt;
vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
vfmt.fmt.pix.width = 640;
vfmt.fmt.pix.height = 480;
vfmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;//set capturing format
ret = ioctl(fd,VIDIOC_S_FMT,&vfmt);
if (ret < 0)
{
perror("set format fail\n");
}
memset(&vfmt,0,sizeof(vfmt));
vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd,VIDIOC_G_FMT,&vfmt);
if (ret < 0)
{
perror("get format fail\n");
}
if (vfmt.fmt.pix.width == 640 && vfmt.fmt.pix.height == 480 && vfmt.fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
{
printf("set succeed\n");
}else
{
printf("set failed\n");
}
/* 4.apply nei he kong jian */
struct v4l2_requestbuffers reqbuffer;
reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuffer.count = 2;//apply 4 huan chong qv
reqbuffer.memory = V4L2_MEMORY_MMAP;//set yin she fang shi
ret = ioctl(fd,VIDIOC_REQBUFS,&reqbuffer);
if (ret < 0)
{
perror("apply fail\n");
}
struct v4l2_buffer mapbuffer;
mapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
for(int i=0;i<2;i++)
{
mapbuffer.index = i;
ret = ioctl(fd,VIDIOC_QUERYBUF,&mapbuffer);//从内核空间中查询一个空间做映射
if (ret < 0)
{
perror("query fail\n");
}
mptr[i] = (unsigned char *)mmap(NULL,mapbuffer.length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,mapbuffer.m.offset);
length[i] = mapbuffer.length;
///通知使用完毕,放回去
ret = ioctl(fd,VIDIOC_QBUF,&mapbuffer);//不要mapbuffer了,还回去
if (ret < 0)
{
perror("return fail\n");
}
}
/* 6.start capturing */
//VIDIOC_DQBUF:告诉内核我要某一个数据,内核不可以修改
//VIDIOC_QBUF:告诉内核我已经使用完毕
//VIDIOC_STREAMON:开始采集,数据到队列中
//VIDIOC_STREAMOFF:停止采集,不再向队列中写数据
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd,VIDIOC_STREAMON,&type);
if (ret < 0)
{
perror("start fail\n");
}
while (1)
{
//从队列中提取一帧数据
struct v4l2_buffer readbuffer;
readbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
readbuffer.index = 6;//无效,下一行代码会设置index的值
ret = ioctl(fd,VIDIOC_DQBUF,&readbuffer);
if (ret < 0)
{
perror("extract fail\n");
}
vector<char>vec_data(mptr[readbuffer.index],mptr[readbuffer.index]+readbuffer.length);
img = imdecode(vec_data,IMREAD_COLOR);
arg.img=img;
pthread_create(&th1,NULL, window1,&arg);//正式创建
pthread_create(&th2,NULL, window2,&arg);//正式创建
//通知内核已经使用完毕
ret = ioctl(fd,VIDIOC_QBUF,&readbuffer);
if (ret < 0)
{
perror("return fail\n");
}
pthread_join(th1,NULL);
pthread_join(th2,NULL);
if (waitKey(30) == 'l')
{
break;
}
}
//pthread_join(th1,NULL);
//pthread_join(th2,NULL);
/* 7.stop capturing */
ret = ioctl(fd,VIDIOC_STREAMOFF,&type);
if (ret < 0)
{
perror("stop fail\n");
}
/* 8.release yin she */
for (int i = 0; i< 4; i++)
{
munmap(mptr[i],length[i]);
}
/* close the device */
close(fd);
return 0;
}
采用V4L2实现摄像头调用
最新推荐文章于 2023-10-13 14:05:55 发布