static int start_capturing(void) { unsigned int i; enum v4l2_buf_type type; for (i = 0; i < cam_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 (xioctl(cam_fd, VIDIOC_QBUF, &buf) == -1) { return errno_report("VIDIOC_QBUF"); } } type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (xioctl(cam_fd, VIDIOC_STREAMON, &type)) { return errno_report("VIDIOC_STREAMON"); } return 0; }
static int init_device(void) { struct v4l2_capability cap; struct v4l2_cropcap cropcap; struct v4l2_crop crop; struct v4l2_format fmt; unsigned int min; if (xioctl(cam_fd, VIDIOC_QUERYCAP, &cap)) { if (EINVAL == errno) { fprintf(stderr, "%s is no V4L2 device\n", cam_dev_name); return -1; } else { return errno_report("VIDIOC_QUERYCAP"); } } if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { fprintf(stderr, "%s is no video capture device\n", cam_dev_name); return -1; } /* Using MMAP */ if (!(cap.capabilities & V4L2_CAP_STREAMING)) { fprintf(stderr, "%s does not support streaming i/o\n", cam_dev_name); return -1; } CLEAR(cropcap); cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (xioctl(cam_fd, VIDIOC_CROPCAP, &cropcap) == 0) { /* If cropping is supported, do not crop */ crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = cropcap.defrect; xioctl(cam_fd, VIDIOC_S_CROP, &crop); } CLEAR(fmt); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = cam_width; fmt.fmt.pix.height = cam_height; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; fmt.fmt.pix.field = V4L2_FIELD_NONE; /* No interlacing, please */ if (xioctl(cam_fd, VIDIOC_S_FMT, &fmt) == -1) { return errno_report("VIDIOC_S_FMT"); } /* Buggy driver paranoia. */ min = fmt.fmt.pix.width * 2; if (fmt.fmt.pix.bytesperline < min) fmt.fmt.pix.bytesperline = min; min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height; if (fmt.fmt.pix.sizeimage < min) fmt.fmt.pix.sizeimage = min; return init_mmap(); }
static int init_mmap(void) { struct v4l2_requestbuffers req; CLEAR(req); req.count = 4; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; if (xioctl(cam_fd, VIDIOC_REQBUFS, &req) == -1) { if (errno == EINVAL) { fprintf(stderr, "%s does not support memory mapping\n", cam_dev_name); return -1; } else { return errno_report("VIDIOC_REQBUFS"); } } if (req.count < 2) { fprintf(stderr, "Insufficient buffer memory on %s\n", cam_dev_name); return -1; } cam_buffers = (struct buffer*)calloc (req.count, sizeof(*cam_buffers)); if (!cam_buffers) { fprintf(stderr, "Out of memory\n"); return -1; } /* Stuff buffers with pretty things */ for (cam_n_buffers = 0; cam_n_buffers < req.count; cam_n_buffers++) { struct v4l2_buffer buf; CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = cam_n_buffers; if (xioctl(cam_fd, VIDIOC_QUERYBUF, &buf) == -1) return errno_report("VIDIOC_QUERYBUF"); cam_buffers[cam_n_buffers].len = buf.length; cam_buffers[cam_n_buffers].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, cam_fd, buf.m.offset); if (cam_buffers[cam_n_buffers].start == MAP_FAILED) return errno_report("mmap"); } return 0; }
static int do_capture(void) { fd_set fds; struct timeval tv; int r; for (;;) { FD_ZERO(&fds); FD_SET(cam_fd, &fds); /* Timeout. */ tv.tv_sec = 2; tv.tv_usec = 0; r = select(cam_fd + 1, &fds, NULL, NULL, &tv); if (r == -1) { if (errno != EINTR) return errno_report("select"); } if (r == 0) { fprintf(stderr, "select timeout\n"); return -1; } if (read_frame() == 0) break; } return 0; }
static int close_device(void) { if (close(cam_fd) == -1) { return errno_report("close_device()"); } cam_fd = -1; return 0; }
static int stop_capturing(void) { enum v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (xioctl(cam_fd, VIDIOC_STREAMOFF, &type) == -1) return errno_report("VIDIOC_STREAMOFF"); return 0; }
static int uninit_device(void) { unsigned int i; for (i = 0; i < cam_n_buffers; i++) { if (munmap(cam_buffers[i].start, cam_buffers[i].len) == -1) { return errno_report("munmap"); } } return 0; }
static int read_frame(void) { struct v4l2_buffer buf; CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; if (xioctl(cam_fd, VIDIOC_DQBUF, &buf)) { switch (errno) { case EAGAIN: return -1; case EIO: default: return errno_report("VIDIOC_DQBUF"); } } process_image(cam_buffers[buf.index].start); if (xioctl(cam_fd, VIDIOC_QBUF, &buf) == -1) { return errno_report("VIDIOC_QBUF"); } return 0; }
struct buffer* oss_record(int fd) { if ((buffers[0].length = read(fd, buffers[0].start, buffers[0].length)) == -1) errno_report("Audio read"); return buffers; }