⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 v4l2.c.svn-base

📁 一个简单的摄像头播放程序,用qt做的界面
💻 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 + -