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

📄 video.c

📁 motion motion
💻 C
字号:
/*	video.c * *	Video stream functions for motion. *	Copyright 2000 by Jeroen Vreeken (pe1rxq@amsat.org) *	This software is distributed under the GNU public license version 2 *	See also the file 'COPYING'. * */#ifndef WITHOUT_V4L/* Common stuff: *///#include "motion.h"///* for rotation */#include "rotate.h"     /* already includes motion.h */#include "video.h"/* for rotation *///#include "rotate.h"/* for the v4l stuff: *///#include "pwc-ioctl.h"	/* not needed here only in track */#include <sys/mman.h>#include <math.h>#include <sys/utsname.h>#include <dirent.h>static void v4l_picture_controls(struct context *cnt, struct video_dev *viddev){	int dev = viddev->fd;	struct video_picture vid_pic;	int make_change = 0;	if (cnt->conf.contrast && cnt->conf.contrast != viddev->contrast) {		if (ioctl(dev, VIDIOCGPICT, &vid_pic) == -1)			motion_log(LOG_ERR, 1, "ioctl (VIDIOCGPICT)");		make_change = 1;		vid_pic.contrast = cnt->conf.contrast * 256;		viddev->contrast = cnt->conf.contrast;	}	if (cnt->conf.saturation && cnt->conf.saturation != viddev->saturation) {		if (!make_change) {			if (ioctl(dev, VIDIOCGPICT, &vid_pic)==-1)				motion_log(LOG_ERR, 1, "ioctl (VIDIOCGPICT)");		}		make_change = 1;		vid_pic.colour = cnt->conf.saturation * 256;		viddev->saturation = cnt->conf.saturation;	}	if (cnt->conf.hue && cnt->conf.hue != viddev->hue) {		if (!make_change) {			if (ioctl(dev, VIDIOCGPICT, &vid_pic) == -1)				motion_log(LOG_ERR, 1, "ioctl (VIDIOCGPICT)");		}		make_change = 1;		vid_pic.hue = cnt->conf.hue * 256;		viddev->hue = cnt->conf.hue;	}		if (cnt->conf.autobright) {				if (vid_do_autobright(cnt, viddev)) {			/* If we already read the VIDIOGPICT - we should not do it again */			if (!make_change) {				if (ioctl(dev, VIDIOCGPICT, &vid_pic) == -1)					motion_log(LOG_ERR, 1, "ioctl (VIDIOCGPICT)");			}								vid_pic.brightness = viddev->brightness * 256;			make_change = 1;		}		} else {		if (cnt->conf.brightness && cnt->conf.brightness != viddev->brightness) {			if (!make_change) {				if (ioctl(dev, VIDIOCGPICT, &vid_pic) == -1)					motion_log(LOG_ERR, 1, "ioctl (VIDIOCGPICT)");			}				make_change = 1;			vid_pic.brightness = cnt->conf.brightness * 256;			viddev->brightness = cnt->conf.brightness;		}	}	if (make_change) {		if (ioctl(dev, VIDIOCSPICT, &vid_pic) == -1)			motion_log(LOG_ERR, 1, "ioctl (VIDIOCSPICT)");	}}/*******************************************************************************************	Video4linux capture routines*/unsigned char *v4l_start(struct context *cnt, struct video_dev *viddev, int width, int height,                                int input, int norm, unsigned long freq, int tuner_number){	int dev = viddev->fd;	struct video_capability vid_caps;	struct video_channel vid_chnl;	struct video_tuner vid_tuner;	struct video_mbuf vid_buf;	struct video_mmap vid_mmap;	void *map;	if (ioctl (dev, VIDIOCGCAP, &vid_caps) == -1) {		motion_log(LOG_ERR, 1, "ioctl (VIDIOCGCAP)");		return (NULL);	}	if (vid_caps.type & VID_TYPE_MONOCHROME)		viddev->v4l_fmt = VIDEO_PALETTE_GREY;	if (input != IN_DEFAULT) {		memset(&vid_chnl, 0, sizeof(struct video_channel));		vid_chnl.channel = input;		if (ioctl (dev, VIDIOCGCHAN, &vid_chnl) == -1) {			motion_log(LOG_ERR, 1, "ioctl (VIDIOCGCHAN)");		} else {			vid_chnl.channel = input;			vid_chnl.norm    = norm;			if (ioctl (dev, VIDIOCSCHAN, &vid_chnl) == -1) {				motion_log(LOG_ERR, 1, "ioctl (VIDIOCSCHAN)");				return (NULL);			}		}	}	if (freq) {		memset(&vid_tuner, 0, sizeof(struct video_tuner));		vid_tuner.tuner = tuner_number;		if (ioctl (dev, VIDIOCGTUNER, &vid_tuner) == -1) {			motion_log(LOG_ERR, 1, "ioctl (VIDIOCGTUNER)");		} else {			if (vid_tuner.flags & VIDEO_TUNER_LOW) {				freq = freq*16; /* steps of 1/16 KHz */			} else {				freq = (freq*10)/625;			}			if (ioctl(dev, VIDIOCSFREQ, &freq) == -1) {				motion_log(LOG_ERR, 1, "ioctl (VIDIOCSFREQ)");				return (NULL);			}			if (cnt->conf.setup_mode)				motion_log(-1, 0, "Frequency set");		}	}	if (ioctl (dev, VIDIOCGMBUF, &vid_buf) == -1) {		motion_log(LOG_ERR, 0, "ioctl(VIDIOCGMBUF) - Error device does not support memory map");		motion_log(LOG_ERR, 0, "V4L capturing using read is deprecated!");		motion_log(LOG_ERR, 0, "Motion only supports mmap.");		return NULL;	} else {		map = mmap(0, vid_buf.size, PROT_READ|PROT_WRITE, MAP_SHARED, dev, 0);		viddev->size_map = vid_buf.size;		if (vid_buf.frames > 1) {			viddev->v4l_maxbuffer = 2;			viddev->v4l_buffers[0] = map;			viddev->v4l_buffers[1] = (unsigned char *)map + vid_buf.offsets[1];		} else {			viddev->v4l_buffers[0] = map;			viddev->v4l_maxbuffer = 1;		}		if (MAP_FAILED == map) {			motion_log(LOG_ERR,1,"MAP_FAILED");			return (NULL);		}		viddev->v4l_curbuffer = 0;		vid_mmap.format = viddev->v4l_fmt;		vid_mmap.frame = viddev->v4l_curbuffer;		vid_mmap.width = width;		vid_mmap.height = height;		if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) {			motion_log(LOG_DEBUG, 1, "Failed with YUV420P, trying YUV422 palette");			viddev->v4l_fmt = VIDEO_PALETTE_YUV422;			vid_mmap.format = viddev->v4l_fmt;			/* Try again... */			if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) {				motion_log(LOG_DEBUG, 1, "Failed with YUV422, trying YUYV palette");				viddev->v4l_fmt = VIDEO_PALETTE_YUYV;				vid_mmap.format = viddev->v4l_fmt;								if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) {					motion_log(LOG_DEBUG, 1, "Failed with YUYV, trying RGB24 palette");					viddev->v4l_fmt = VIDEO_PALETTE_RGB24;					vid_mmap.format = viddev->v4l_fmt;					/* Try again... */									if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) {						motion_log(LOG_DEBUG, 1, "Failed with RGB24, trying GREYSCALE palette");						viddev->v4l_fmt = VIDEO_PALETTE_GREY;						vid_mmap.format = viddev->v4l_fmt;						/* Try one last time... */						if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) {							motion_log(LOG_ERR, 1, "Failed with all supported palettes "						                            "- giving up");							return (NULL);						}					}				}			}		}	}	switch (viddev->v4l_fmt) {		case VIDEO_PALETTE_YUV420P:			viddev->v4l_bufsize = (width*height*3)/2;			motion_log(LOG_DEBUG, 0, "Using VIDEO_PALETTE_YUV420P palette");			break;		case VIDEO_PALETTE_YUV422:			viddev->v4l_bufsize = (width*height*2);			motion_log(LOG_DEBUG, 0, "Using VIDEO_PALETTE_YUV422 palette");			break;		case VIDEO_PALETTE_YUYV:			viddev->v4l_bufsize = (width*height*2);			motion_log(LOG_DEBUG, 0, "Using VIDEO_PALETTE_YUYV palette");			break;		case VIDEO_PALETTE_RGB24:			viddev->v4l_bufsize = (width*height*3);			motion_log(LOG_DEBUG, 0, "Using VIDEO_PALETTE_RGB24 palette");			break;		case VIDEO_PALETTE_GREY:			viddev->v4l_bufsize = width*height;			motion_log(LOG_DEBUG, 0, "Using VIDEO_PALETTE_GREY palette");			break;	}	return map;}/** * v4l_next *                v4l_next fetches a video frame from a v4l device * * Parameters: *     viddev     Pointer to struct containing video device handle amd device parameters *     map        Pointer to the buffer in which the function puts the new image *     width      Width of image in pixels *     height     Height of image in pixels * * Returns *     0               Success *    V4L_FATAL_ERROR  Fatal error *    Positive with bit 0 set and bit 1 unset *                     Non fatal error (not implemented) */int v4l_next(struct video_dev *viddev, unsigned char *map, int width, int height){	int dev = viddev->fd;	int frame = viddev->v4l_curbuffer;	struct video_mmap vid_mmap;	unsigned char *cap_map;	sigset_t  set, old;	/* MMAP method is used */	vid_mmap.format = viddev->v4l_fmt;	vid_mmap.width = width;	vid_mmap.height = height;	/* Block signals during IOCTL */	sigemptyset(&set);	sigaddset(&set, SIGCHLD);	sigaddset(&set, SIGALRM);	sigaddset(&set, SIGUSR1);	sigaddset(&set, SIGTERM);	sigaddset(&set, SIGHUP);	pthread_sigmask (SIG_BLOCK, &set, &old);	cap_map = viddev->v4l_buffers[viddev->v4l_curbuffer];	viddev->v4l_curbuffer++;	if (viddev->v4l_curbuffer >= viddev->v4l_maxbuffer)		viddev->v4l_curbuffer = 0;	vid_mmap.frame = viddev->v4l_curbuffer;	if (ioctl(dev, VIDIOCMCAPTURE, &vid_mmap) == -1) {		motion_log(LOG_ERR, 1, "mcapture error in proc %d", getpid());		sigprocmask (SIG_UNBLOCK, &old, NULL);		return V4L_FATAL_ERROR;	}	vid_mmap.frame = frame;	if (ioctl(dev, VIDIOCSYNC, &vid_mmap.frame) == -1) {		motion_log(LOG_ERR, 1, "sync error in proc %d", getpid());		sigprocmask (SIG_UNBLOCK, &old, NULL);	}	pthread_sigmask (SIG_UNBLOCK, &old, NULL);        /*undo the signal blocking*/	switch (viddev->v4l_fmt) {		case VIDEO_PALETTE_RGB24:			conv_rgb24toyuv420p(map, cap_map, width, height);			break;		case VIDEO_PALETTE_YUYV:		case VIDEO_PALETTE_YUV422:			conv_yuv422to420p(map, cap_map, width, height);			break;		default:			memcpy(map, cap_map, viddev->v4l_bufsize);	}	return 0;}void v4l_set_input(struct context *cnt, struct video_dev *viddev, unsigned char *map, int width, int height, int input,                    int norm, int skip, unsigned long freq, int tuner_number){	int dev = viddev->fd;	int i;	struct video_channel vid_chnl;	struct video_tuner vid_tuner;	unsigned long frequnits = freq;		if (input != viddev->input || width != viddev->width || height != viddev->height ||	    freq != viddev->freq || tuner_number != viddev->tuner_number) {		if (freq) {			memset(&vid_tuner, 0, sizeof(struct video_tuner));			vid_tuner.tuner = tuner_number;			if (ioctl (dev, VIDIOCGTUNER, &vid_tuner) == -1) {				motion_log(LOG_ERR, 1, "ioctl (VIDIOCGTUNER)");			} else {				if (vid_tuner.flags & VIDEO_TUNER_LOW) {					frequnits = freq*16; /* steps of 1/16 KHz */				} else {					frequnits = (freq*10)/625;				}				if (ioctl(dev, VIDIOCSFREQ, &frequnits) == -1) {					motion_log(LOG_ERR, 1, "ioctl (VIDIOCSFREQ)");					return;				}			}		}		memset(&vid_chnl, 0, sizeof(struct video_channel));		vid_chnl.channel = input;				if (ioctl (dev, VIDIOCGCHAN, &vid_chnl) == -1) {			motion_log(LOG_ERR, 1, "ioctl (VIDIOCGCHAN)");		} else {			vid_chnl.channel = input;			vid_chnl.norm = norm;			if (ioctl (dev, VIDIOCSCHAN, &vid_chnl) == -1) {				motion_log(LOG_ERR, 1, "ioctl (VIDIOCSCHAN)");				return;			}		}		v4l_picture_controls(cnt, viddev);		viddev->input = input;		viddev->width = width;		viddev->height = height;		viddev->freq =freq;		viddev->tuner_number = tuner_number;		/* skip a few frames if needed */		for (i=0; i < skip; i++)			v4l_next(viddev, map, width, height);	} else {		/* No round robin - we only adjust picture controls */		v4l_picture_controls(cnt, viddev);	}}static int v4l_open_vidpipe(void){	int pipe_fd = -1;	char pipepath[255];	char buffer[255];	char *major;	char *minor;	struct utsname uts;	if (uname(&uts) < 0) {		motion_log(LOG_ERR, 1, "Unable to execute uname");		return -1;	}	major = strtok(uts.release, ".");	minor = strtok(NULL, ".");	if ((major == NULL) || (minor == NULL) || (strcmp(major, "2"))) {		motion_log(LOG_ERR, 1, "Unable to decipher OS version");		return -1;	}	if (strcmp(minor, "5") < 0) {		FILE *vloopbacks;		char *loop;		char *input;		char *istatus;		char *output;		char *ostatus;		vloopbacks = fopen("/proc/video/vloopback/vloopbacks", "r");		if (!vloopbacks) {			motion_log(LOG_ERR, 1, "Failed to open '/proc/video/vloopback/vloopbacks'");			return -1;		}				/* Read vloopback version*/		if (!fgets(buffer, 255, vloopbacks)) {			motion_log(LOG_ERR, 1, "Unable to read vloopback version");			return -1;		}				fprintf(stderr,"\t%s", buffer);				/* Read explanation line */				if (!fgets(buffer, 255, vloopbacks)) {			motion_log(LOG_ERR, 1, "Unable to read vloopback explanation line");			return -1;		}				while (fgets(buffer, 255, vloopbacks)) {			if (strlen(buffer) > 1) {				buffer[strlen(buffer)-1] = 0;				loop=strtok(buffer, "\t");				input=strtok(NULL, "\t");				istatus=strtok(NULL, "\t");				output=strtok(NULL, "\t");				ostatus=strtok(NULL, "\t");				if (istatus[0] == '-') {					snprintf(pipepath, 255, "/dev/%s", input);					pipe_fd = open(pipepath, O_RDWR);					if (pipe_fd >= 0) {						motion_log(-1, 0, "\tInput:  /dev/%s", input);						motion_log(-1, 0, "\tOutput: /dev/%s", output);						break;					}				}			}		}		fclose(vloopbacks);	} else {		DIR *dir;		struct dirent *dirp;		const char prefix[] = "/sys/class/video4linux/";		char *ptr, *io;		int fd;		int low = 9999;		int tfd;		int tnum;		if ((dir=opendir(prefix)) == NULL) {			motion_log(LOG_ERR, 1, "Failed to open '%s'", prefix);			return -1;		}		while ((dirp=readdir(dir)) != NULL) {			if (!strncmp(dirp->d_name, "video", 5)) {				strncpy(buffer, prefix, 255);				strncat(buffer, dirp->d_name, 255);				strncat(buffer, "/name", 255);				if ((fd = open(buffer, O_RDONLY)) >= 0) {					if ((read(fd, buffer, sizeof(buffer)-1)) < 0) {						close(fd);						continue;					}					ptr = strtok(buffer, " ");					if (strcmp(ptr,"Video")) {						close(fd);						continue;					}					major = strtok(NULL, " ");					minor = strtok(NULL, " ");					io  = strtok(NULL, " \n");					if (strcmp(major, "loopback") || strcmp(io, "input")) {						close(fd);						continue;					}					if ((ptr=strtok(buffer, " ")) == NULL) {						close(fd);						continue;					}					tnum = atoi(minor);					if (tnum < low) {						strcpy(buffer, "/dev/");						strcat(buffer, dirp->d_name);						if ((tfd=open(buffer, O_RDWR)) >= 0) {							strcpy(pipepath, buffer);							if (pipe_fd >= 0) {								close(pipe_fd);							}							pipe_fd = tfd;							low = tnum;						}					}					close(fd);				}			}		}		closedir(dir);		if (pipe_fd >= 0)			motion_log(-1, 0, "Opened input of %s", pipepath);	}	return pipe_fd;}static int v4l_startpipe(const char *dev_name, int width, int height, int type){	int dev;	struct video_picture vid_pic;	struct video_window vid_win;	if (!strcmp(dev_name, "-")) {		dev = v4l_open_vidpipe();	} else {		dev = open(dev_name, O_RDWR);	}	if (dev < 0)		return(-1);	if (ioctl(dev, VIDIOCGPICT, &vid_pic) == -1) {		motion_log(LOG_ERR, 1, "ioctl (VIDIOCGPICT)");		return(-1);	}	vid_pic.palette=type;	if (ioctl(dev, VIDIOCSPICT, &vid_pic) == -1) {		motion_log(LOG_ERR, 1, "ioctl (VIDIOCSPICT)");		return(-1);	}	if (ioctl(dev, VIDIOCGWIN, &vid_win) == -1) {		motion_log(LOG_ERR, 1, "ioctl (VIDIOCGWIN)");		return(-1);	}	vid_win.height = height;	vid_win.width = width;	if (ioctl(dev, VIDIOCSWIN, &vid_win) == -1) {		motion_log(LOG_ERR, 1, "ioctl (VIDIOCSWIN)");		return(-1);	}	return dev;}static int v4l_putpipe (int dev, unsigned char *image, int size){	return write(dev, image, size);}int vid_startpipe(const char *dev_name, int width, int height, int type){	return v4l_startpipe( dev_name, width, height, type);}int vid_putpipe (int dev, unsigned char *image, int size){	return v4l_putpipe(dev, image, size);}#endif /*WITHOUT_V4L*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -