📄 v4l2.c.svn-base
字号:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <malloc.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/time.h>#include <sys/mman.h>#include <sys/ioctl.h>#include "v4l2.h"#define CLEAR(x) memset (&x, 0, sizeof(x))char *mpeg[] = {"./1.mpeg", "./2.mpeg", "./3.mpeg", "./4.mpeg", "./5.mpeg"};void init_dev (pass_data *s){ open_device(s); init_device(s); init_mmap(s); start_capturing(s); fprintf(stdout, "'%s' initialize finish ...\n", s->dev_name);}void stop_dev (pass_data *s){ stop_capturing(s); stop_device(s); close_device(s); fprintf(stdout, "close '%s' ...\n", s->dev_name);}void process_image(void *p, pass_data *s, int i){ fputc ('.', stdout); fflush (stdout); fprintf (stderr, "%s", mpeg[i]); int fd; if ((fd = open (mpeg[i], O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1) errno_exit("open"); if ((write (fd, (struct v4l2_buffer *)p, s->fmt.fmt.pix.sizeimage)) == -1) errno_exit("write"); close (fd);}void read_frame(pass_data *s){ CLEAR (s->buf); s->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; s->buf.memory = V4L2_MEMORY_MMAP; if (xioctl (s->fd, VIDIOC_DQBUF, &s->buf) == -1) { switch (errno) { case EAGAIN: errno_exit ("VIDIOC_DQBUF"); case EIO: /* could ignore EIO, see spec. */ default: errno_exit ("VIDIOC_DQBUF"); } } assert (s->buf.index < s->n_buffers);}void return_data (pass_data *s){ if (xioctl (s->fd, VIDIOC_QBUF, &s->buf) == -1) errno_exit ("VIDIOC_QBUF"); }void start_capturing(pass_data *s){ unsigned int i; enum v4l2_buf_type type; for (i = 0; i < s->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 (s->fd, VIDIOC_QBUF, &buf) == -1) errno_exit("VIDIOC_QBUF"); } type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (xioctl (s->fd, VIDIOC_STREAMON, &type)) errno_exit("VIDIOC_STREAMON");}void stop_capturing(pass_data *s){ enum v4l2_buf_type type; type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (xioctl (s->fd, VIDIOC_STREAMOFF, &type)) errno_exit("VIDIOC_STREAMOFF");}void init_mmap(pass_data *s){ struct v4l2_requestbuffers req; CLEAR (req); req.count = 20; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; if (xioctl (s->fd, VIDIOC_REQBUFS, &req)) { if (EINVAL == errno) { fprintf(stderr, "%s does not support 'memory mapping'\n", s->dev_name); exit (EXIT_FAILURE); } else { errno_exit ("VIDIOC_REQBUFS"); } } if (req.count < 2) { fprintf(stderr, "Insufficient buffer memory on %s\n", s->dev_name); exit (EXIT_FAILURE); } if ((s->buffers = (buffer *)calloc (req.count, sizeof (*s->buffers))) == NULL) { fprintf(stderr, "Out of memory\n"); exit ( EXIT_FAILURE); } for (s->n_buffers = 0; s->n_buffers < req.count; ++ s->n_buffers) { struct v4l2_buffer buf; CLEAR (buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = s->n_buffers; if (xioctl (s->fd, VIDIOC_QUERYBUF, &buf) == -1) errno_exit("VIDIOC_QUERYBUF"); s->buffers[s->n_buffers].length = buf.length; s->buffers[s->n_buffers].start = mmap( NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset ); if (s->buffers[s->n_buffers].start == MAP_FAILED) errno_exit ("mmap");#if _DEBUG_ fprintf(stdout, "%d -> %p\n", s->n_buffers, s->buffers[s->n_buffers].start);#endif }}void init_device(pass_data* s){ struct v4l2_capability cap; struct v4l2_cropcap cropcap; struct v4l2_crop crop; unsigned int min; if (xioctl (s->fd, VIDIOC_QUERYCAP, &cap) == -1) { if (EINVAL == errno) { fprintf (stderr, "%s is no V4L2 device\n", s->dev_name); exit (EXIT_FAILURE); } else { errno_exit ("VIDIOC_QUERYCAP"); } } if (! (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { fprintf(stderr, "%s is no video captrue device\n", s->dev_name); exit(EXIT_FAILURE); } if (! (cap.capabilities & V4L2_CAP_STREAMING)) { fprintf(stderr, "%s does not support straming I/O\n", s->dev_name); exit(EXIT_FAILURE); } CLEAR(cropcap); cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (xioctl (s->fd, VIDIOC_CROPCAP, &cropcap) == 0) { crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = cropcap.defrect; if (xioctl (s->fd, VIDIOC_S_CROP, &crop)) { switch (errno) { case EINVAL: break; default: break; } } else { /* Errors ignored */ } } CLEAR (s->fmt); s->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; s->fmt.fmt.pix.width = 640; s->fmt.fmt.pix.height = 480; s->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; s->fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; if (xioctl (s->fd, VIDIOC_S_FMT, &s->fmt) == -1) errno_exit("VIDIOC_S_FMT"); min = s->fmt.fmt.pix.width * 2; if (s->fmt.fmt.pix.bytesperline < min) s->fmt.fmt.pix.bytesperline = min; min = s->fmt.fmt.pix.bytesperline * s->fmt.fmt.pix.height; if (s->fmt.fmt.pix.sizeimage < min) s->fmt.fmt.pix.sizeimage = min;}void stop_device(pass_data *s){ unsigned int i; for (i = 0; i < s->n_buffers; ++i) if (munmap (s->buffers[i].start, s->buffers[i].length) == -1) errno_exit("munmap");}void open_device(pass_data *s){ struct stat st; if (stat (s->dev_name, &st) == -1) { fprintf(stderr, "Can't identify '%s':[%d] %s\n", s->dev_name, errno, strerror(errno)); exit(EXIT_FAILURE); } if (!S_ISCHR (st.st_mode)) { fprintf(stderr, "%s is no device\n", s->dev_name); exit(EXIT_FAILURE); } if ((s->fd = open (s->dev_name, O_RDWR, 0)) == -1 ) { fprintf(stderr, "Can't oprn '%s': error %d, %s\n", s->dev_name, errno, strerror(errno)); exit(EXIT_FAILURE); }}void close_device(pass_data *s){ close (s->fd);}int xioctl(int fd, int request, void *arg){ int r; do r = ioctl(fd, request, arg); while(r == -1 && EINTR == errno); return r;}void errno_exit(const char *s){ fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno)); exit(EXIT_FAILURE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -