v4l2采集视频
V4L2是Video for linux2的简称,为linux中关于视频设备的内核驱动。v4l2为linux下视频设备程序提供了一套接口规范。包括一套数据结构和底层V4L2驱动接口。只能在linux下使用。它使程序有发现设备和操作设备的能力。它主要是用一系列的回调函数来实现这些功能。像设置摄像头的频率、帧频、视频压缩格式和图像参数等等。当然也可以用于其他多媒体的开发,如音频等。
一、打开设备
open ("/dev/video0", O_RDWR | O_NONBLOCK, 0);
二、获取驱动信息
struct v4l2_capability cap;
struct v4l2_capability {
u8 driver[16]; // 驱动名字
u8 card[32]; // 设备名字
u8 bus_info[32]; // 设备在系统中的位置
u32 version; // 驱动版本号
u32 capabilities; // 设备支持的操作
u32 reserved[4]; // 保留字段
};
ret = ioctl (fd, VIDIOC_QUERYCAP, &cap);
三、设置图像格式
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //这是设置传输流类型
fmt.fmt.pix.width = this->config_.width_; //设置分辨率
fmt.fmt.pix.height = this->config_.hight_;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; //图像格式,此处是jpg
fmt.fmt.pix.priv = 1;
ret = ioctl (fd, VIDIOC_S_FMT, &fmt) ;
四、申请图像缓冲区
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
ret = ioctl (fd, VIDIOC_REQBUFS, &req)
五、获取图像缓冲区的信息
struct buffer
{
void* start;
unsigned int length;
};
struct buffer *buffers;
buffers = (buffer*)calloc (req.count, sizeof (*buffers));
for (n_buffers = 0; n_buffers < req.count; ++n_buffers)
{
/*获取图像缓冲区的信息*/
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
//ioctl (fd, VIDIOC_QUERYBUF, &buf);
ret = ioctl(fd, VIDIOC_QUERYBUF, &buf);
buffers[n_buffers].length = buf.length;
// 把内核空间中的图像缓冲区映射到用户空间
buffers[n_buffers].start = mmap (NULL , //通过mmap建立映射关系
buf.length,
PROT_READ | PROT_WRITE ,
MAP_SHARED ,
fd,
buf.m.offset);
}
六、图像缓冲入队
for (i = 0; i < n_buffers; ++i)
{
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
ret = ioctl (fd, VIDIOC_QBUF, &buf);
}
七、开始捕捉图像数据
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl (fd, VIDIOC_STREAMON, &type);
八、帧出列
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ret = ioctl (fd, VIDIOC_DQBUF, &buf);
write(file_fd,buffers[buf.index].start,buffers[buf.index].length);
九、buf入列
ret = ioctl(fd, VIDIOC_QBUF, &buf);
for (i = 0; i < n_buffers; ++i)
munmap (buffers[i].start, buffers[i].length);
十、关闭fd