Linux下摄像头图像数据的获取(2)

for (n_buffers = 0; n_buffers < req.count; ++n_buffers)
 {
  struct v4l2_buffer buf;  //驱动中的一帧
  CLEAR (buf);
  buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  buf.memory      = V4L2_MEMORY_MMAP;
  buf.index      = n_buffers;

if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buf)) //映射用户空间
   printf ("VIDIOC_QUERYBUF error\n");

buffers[n_buffers].length = buf.length;
  buffers[n_buffers].start =
  mmap (NULL /* start anywhere */,    //通过mmap建立映射关系
   buf.length,
   PROT_READ | PROT_WRITE /* required */,
   MAP_SHARED /* recommended */,
   fd, buf.m.offset);

if (MAP_FAILED == buffers[n_buffers].start)
  printf ("mmap failed\n");
    }

for (i = 0; i < n_buffers; ++i)
 {
  struct v4l2_buffer buf;
  CLEAR (buf);

buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  buf.memory      = V4L2_MEMORY_MMAP;
  buf.index      = i;

if (-1 == ioctl (fd, VIDIOC_QBUF, &buf))//申请到的缓冲进入列队
   printf ("VIDIOC_QBUF failed\n");
 }
               
 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

if (-1 == ioctl (fd, VIDIOC_STREAMON, &type)) //开始捕捉图像数据
  printf ("VIDIOC_STREAMON failed\n");

for (;;) //这一段涉及到异步IO
 {
  fd_set fds;
  struct timeval tv;
  int r;

FD_ZERO (&fds);//将指定的文件描述符集清空
  FD_SET (fd, &fds);//在文件描述符集合中增加一个新的文件描述符

/* Timeout. */
  tv.tv_sec = 2;
  tv.tv_usec = 0;

r = select (fd + 1, &fds, NULL, NULL, &tv);//判断是否可读(即摄像头是否准备好),tv是定时

if (-1 == r)
  {
   if (EINTR == errno)
    continue;
   printf ("select err\n");
  }
  if (0 == r)
  {
   fprintf (stderr, "select timeout\n");
   exit (EXIT_FAILURE);
  }

if (read_frame ())//如果可读,执行read_frame ()函数,并跳出循环
   break;
 }

unmap:
 for (i = 0; i < n_buffers; ++i)
  if (-1 == munmap (buffers[i].start, buffers[i].length))
   printf ("munmap error");
 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 
    if (-1 == ioctl(fd, VIDIOC_STREAMOFF, &type)) 
        printf("VIDIOC_STREAMOFF");
 close (fd);
 fclose (file_fd);
return 0;
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/1264d47a74b0f997775dee7240fe32b9.html