1获取设备信息cap
struct v4l2_capability cap;
ioctl(camrea_fd, VIDIOC_QUERYCAP, &cap);
2获取设备支持的标准制式 std
struct v4l2_standard std;
ioctl(camrea_fd, VIDIOC_ENUMSTD, &std)
3显示所有支持的帧格式 VIDIOC_ENUM_FMT
struct v4l2_fmtdesc fmtdesc;
ioctl(camrea_fd, VIDIOC_ENUM_FMT, &fmtdesc)
4查询当前帧格式 VIDIOC_G_FMT
struct v4l2_format fmt;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl(camrea_fd, VIDIOC_G_FMT, &fmt)
5设置帧格式 VIDIOC_S_FMT
struct v4l2_format fmt;
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24; // 采样类型,如 RGB 8:8:8 V4L2_PIX_FMT_JPEG;//YUYV格式
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
fmt.fmt.pix.width = width;
fmt.fmt.pix.height = height;
ioctl(camrea_fd, VIDIOC_S_FMT, &fmt)
6查询帧率 VIDIOC_G_PARM
*timeperframe 表示平均每一帧所占的时间,由其元素 numerator 和 denominator 共同决定
*capturemode 则表示采集模式,采集高质量图片值为 1,一般设为 0
struct v4l2_streamparm parm;
parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl(camrea_fd, VIDIOC_G_PARM, &parm)
7向驱动申请帧缓冲 VIDIOC_REQBUFS
struct v4l2_requestbuffers reqbuf;
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
reqbuf.count = count;
ioctl(camrea_fd, VIDIOC_REQBUFS, &reqbuf)
8建立内存映射
VIDIOC_QUERYBUF 来获取内核空间的视频缓冲区信息,
然后调用函数 mmap把内核空间地址映射到用户空间,
这样应用程序才能够访问位于内核空间的视频缓冲区
struct v4l2_buffer bufinfo;
bufinfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
bufinfo.memory = V4L2_MEMORY_MMAP;
bufinfo.index = i;
ioctl(camrea_fd, VIDIOC_QUERYBUF, &bufinfo)
buffers[i].length = bufinfo.length;
buffers[i].start = mmap(NULL, bufinfo.length, PROT_READ | PROT_WRITE,MAP_SHARED, camrea_fd, bufinfo.m.offset);
9释放内存映射
munmap(buffers[i].start, buffers[i].length)
10打开视频捕获 VIDIOC_QBUF
struct v4l2_buffer buf;
//申请了多少个缓冲区循环设置多少次
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
ioctl(camrea_fd, VIDIOC_QBUF, &buf)
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl(camrea_fd, VIDIOC_STREAMON, &type)
11关闭视频捕获VIDIOC_STREAMOFF
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl(camrea_fd, VIDIOC_STREAMOFF, &type)
12获取一帧数据
struct v4l2_buffer buf;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ioctl(camrea_fd, VIDIOC_DQBUF, &buf)
*frame_buf = buffers[buf.index].start;//buffers是映射到的地址
current_index = buf.index;
13释放一帧数据 VIDIOC_QBUF
struct v4l2_buffer buf;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = current_index;
ioctl(camrea_fd, VIDIOC_QBUF, &buf)
关于ioctl(camrea_fd, VIDIOC_S_FMT, &fmt);设置再读取v4l2_format没变化的问题
使用VIDIOC_S_FMT设置时如果该设备不支持该模式内核会自动把fmt设置成支持的数据
main函数的结构
camera_init();//初始化摄像头
get_v4l2_info();
set_cam_format(640, 480);//长, 宽
cam_req_bufs(3); //申请缓冲区
cam_mmap(); //用户地址映射
cam_start(); //开始视频捕获
char * jpg_buf = malloc(480*640*3);
int i;
//jpg_buf 里存的就是图片数据
printf("nr_buffers:%d\n",nr_buffers);
for(i = 0;i<10;i++)
{
cam_get_frame(&jpg_buf);
printf("buf : %x\n",jpg_buf);
cam_free_frame();
}
cam_munmap();
cam_stop();
close(camrea_fd);