/* 打开设备并进行错误检查 */
int fd = open ("/dev/video",O_RDONLY);
if (fd==-1){
perror ("Can't open device");
return -1;
}
/* 查询设备的输出格式 */
struct v4l2_format format;
memset (&format,0,sizoef(format));
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1==ioctl(fd,VIDIOC_G_FMT,&format)){
perror ("While getting format");
return -2;
}
/*
* 这里要将struct v4l2_format结构体置零,然后将
* format.type设定为V4L2_BUF_TYPE_VIDEO_CAPTURE,
* 这样在进行 VIDIOC_G_FMT 的ioctl时,驱动就会知
* 道是在捕获视频的情形下获取格式的内容。
* 成功返回后,format就含有捕获视频的尺寸大小及格
* 式。格式存储在 format.fmt.pix.pixelformat这个32
* 位的无符号整数中,共四个字节,以小头序存储。这里
* 介绍一种获取的方法。
*/
char code[5];
unsigned int i;
for (i=0;i<4;i++) {
code[i] = (format.fmt.pix.pixelformat & (0xff<<i*8))>>i*8;
}
code[4]=0;
/* 现在的code是一个以\0结束的字符串。很多摄像头都是以格式MJPG输出视频的。
* MJPG是Motion JPEG的缩写,其实就是一些没填霍夫曼表的JPEG图片。
*/
/* 请求一定数量的缓冲区。
* 但是不一定能请求到那么多。据体还得看返回的数量
*/
struct v4l2_requestbuffers req;
memset (&req,0,sizeof(req));
req.count = 10;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (-1==ioctl(fd,VIDIOC_REQBUFS,&req)){
perror ("While requesting buffers");
return -3;
}
if (req.count < 5){
fprintf (stderr, "Can't get enough buffers!\n");
return -4;
}
/* 这里请求了10块缓存区,并将其类型设为MMAP型。 */
/* 获取缓冲区的信息
* 在操作之前,我们必须要能记录下我们
* 申请的缓存区,并在最后使用munmap释放它们
* 这里使用结构体
* struct buffer {
* void * start;
* ssize_t length;
* } 以及buffer数量
* static int nbuffer
* 来表示
*/
struct buffer * buffers = (struct buffer *)malloc (nbuffer*sizeof(*buffers));
if (!buffers){
perror ("Can't allocate memory for buffers!");
return -4;
}
struct v4l2_buffer buf;
for (nbuffer=0;nbuffer<req.count;++nbuffer) {
memset (&buf,0,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = nbuffer;
if (-1==ioctl(fd,VIDIOC_QUERYBUF,&buf)){
perror ("While querying buffer");
return -5;
}
buffers[nbuffer].length = buf.length;
buffers[nbuffer].start = mmap (
NULL,
buf.length,
PROT_READ, /* 官方文档说要加上PROT_WRITE,但加上会出错 */
MAP_SHARED,
fd,
buf.m.offset
);
if (MAP_FAILED == buffers[nbuffer].start) {
perror ("While mapping memory");
return -6;
}
}
|