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

📄 video.c

📁 video motion detection of linux base
💻 C
📖 第 1 页 / 共 2 页
字号:
	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(char *devname, int width, int height, int type){	int dev;	struct video_picture vid_pic;	struct video_window vid_win;	if (!strcmp(devname, "-")) {		dev=v4l_open_vidpipe();	} else {		dev=open(devname, 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);}#endif /*WITHOUT_V4L*//*****************************************************************************	Wrappers calling the actual capture routines *****************************************************************************//* big lock for vid_start to ensure exclusive access to viddevs while adding  * devices during initialization of each thread */pthread_mutex_t vid_mutex;#ifndef WITHOUT_V4L/* Here we setup the viddevs structure which is used globally in the vid_* * functions. */struct video_dev **viddevs=NULL;/** * vid_init * * Called from motion.c at the very beginning before setting up the threads. * Function prepares the viddevs struct for the threads and the vid_mutex */void vid_init(void){	if (!viddevs) {		viddevs = mymalloc(sizeof(struct video_dev *));		viddevs[0] = NULL;	}	pthread_mutex_init(&vid_mutex, NULL);}/** * vid_close * * vid_close is called from motion.c when Motion is stopped or restarted * It gets rid of all open video devices. It is called BEFORE vid_cleanup. */void vid_close(void){	int i=-1;	if (viddevs) {		while(viddevs[++i]) {			close(viddevs[i]->fd);		}	}}/** * vid_cleanup * * vid_cleanup is called from motion.c when Motion is stopped or restarted * It free all the memory held by the viddevs structs. */void vid_cleanup(void){	int i=-1;	if (viddevs) {		while(viddevs[++i]) {			munmap(viddevs[i]->v4l_buffers[0],viddevs[i]->size_map);			free(viddevs[i]);		}		free(viddevs);		viddevs=NULL;	}}#endif /*WITHOUT_V4L*//** * vid_start * * vid_start setup the capture device. This will be either a V4L device or a netcam. * The function does the following: * - If the camera is a netcam - netcam_start is called and function returns * - Width and height are checked for valid value (multiple of 16) * - Copy the config height and width to the imgs struct. Note that height and width are *   only copied to the from the conf struct to the imgs struct during program startup *   The width and height can no later be changed via http remote control as this would *   require major re-memory allocations of all image buffers. * - Setup basic V4L properties incl palette incl setting  * - Open the device * - Returns the device number. * * Parameters: *     cnt        Pointer to the context for this thread * * "Global" variable *     viddevs    The viddevs struct is "global" within the context of video.c *                and used in functions vid_*. *     vid_mutex  Mutex needed to handle exclusive access to the viddevs struct when *                each thread adds a new video device during startup calling vid_start * * Returns *     device number *     -1 if failed to open device. */int vid_start(struct context *cnt){	struct config *conf = &cnt->conf;	int dev = -1;	if (conf->netcam_url) {		return netcam_start(cnt);	}#ifndef WITHOUT_V4L	/* Start a new block so we can make declarations without breaking good old	 * gcc 2.95 or older.	 */	{		int i = -1;		int width, height, input, norm, tuner_number;		unsigned long frequency;		/* We use width and height from conf in this function. They will be assigned		 * to width and height in imgs here, and cap_width and cap_height in 		 * rotate_data won't be set until in rotate_init.		 * Motion requires that width and height is a multiple of 16 so we check		 * for this first.		 */		if (conf->width % 16) {			motion_log(LOG_ERR, 0, "config image width (%d) is not modulo 16", conf->width);			return -1;		}		if (conf->height % 16) {			motion_log(LOG_ERR, 0, "config image height (%d) is not modulo 16", conf->height);			return -1;		}		width = conf->width;		height = conf->height;		input = conf->input;		norm = conf->norm;		frequency = conf->frequency;		tuner_number = conf->tuner_number;				pthread_mutex_lock(&vid_mutex);		/* Transfer width and height from conf to imgs. The imgs values are the ones		 * that is used internally in Motion. That way, setting width and height via		 * http remote control won't screw things up.		 */		cnt->imgs.width=width;		cnt->imgs.height=height;		/* First we walk through the already discovered video devices to see		 * if we have already setup the same device before. If this is the case		 * the device is a Round Robin device and we set the basic settings		 * and return the file descriptor		 */		while (viddevs[++i]) {			if (!strcmp(conf->video_device, viddevs[i]->video_device)) {				int fd;				cnt->imgs.type = viddevs[i]->v4l_fmt;				switch (cnt->imgs.type) {					case VIDEO_PALETTE_GREY:						cnt->imgs.motionsize = width * height;						cnt->imgs.size = width * height;						break;					case VIDEO_PALETTE_RGB24:					case VIDEO_PALETTE_YUV422:						cnt->imgs.type = VIDEO_PALETTE_YUV420P;					case VIDEO_PALETTE_YUV420P:						cnt->imgs.motionsize = width * height;						cnt->imgs.size = (width*height * 3) / 2;						break;				}				fd=viddevs[i]->fd;				pthread_mutex_unlock(&vid_mutex);				return fd;			}		}		viddevs = myrealloc(viddevs, sizeof(struct video_dev *)*(i+2), "vid_start");		viddevs[i] = mymalloc(sizeof(struct video_dev));		memset(viddevs[i], 0, sizeof(struct video_dev));		viddevs[i+1]=NULL;		pthread_mutexattr_init(&viddevs[i]->attr);		pthread_mutex_init(&viddevs[i]->mutex, NULL);		dev = open(conf->video_device, O_RDWR);		if (dev <0) {			motion_log(LOG_ERR, 1, "Failed to open video device %s", conf->video_device);			return -1;		}		viddevs[i]->video_device = conf->video_device;		viddevs[i]->fd = dev;		viddevs[i]->input = input;		viddevs[i]->height = height;		viddevs[i]->width = width;		viddevs[i]->freq = frequency;		viddevs[i]->tuner_number = tuner_number;				/* We set brightness, contrast, saturation and hue = 0 so that they only get		 * set if the config is not zero.		 */		viddevs[i]->brightness = 0;		viddevs[i]->contrast = 0;		viddevs[i]->saturation = 0;		viddevs[i]->hue = 0;		viddevs[i]->owner = -1;		viddevs[i]->v4l_fmt = VIDEO_PALETTE_YUV420P;		if (!v4l_start(cnt, viddevs[i], width, height, input, norm, frequency, tuner_number)) {			pthread_mutex_unlock(&vid_mutex);			return -1;		}		cnt->imgs.type = viddevs[i]->v4l_fmt;		switch (cnt->imgs.type) {			case VIDEO_PALETTE_GREY:				cnt->imgs.size = width*height;				cnt->imgs.motionsize = width*height;			break;			case VIDEO_PALETTE_RGB24:			case VIDEO_PALETTE_YUV422:				cnt->imgs.type = VIDEO_PALETTE_YUV420P;			case VIDEO_PALETTE_YUV420P:				cnt->imgs.size = (width*height*3)/2;				cnt->imgs.motionsize = width*height;			break;		}		pthread_mutex_unlock(&vid_mutex);	}#endif /*WITHOUT_V4L*/		return dev;}/** * vid_next * * vid_next fetches a video frame from a either v4l device or netcam * * Parameters: *     cnt        Pointer to the context for this thread *     map        Pointer to the buffer in which the function puts the new image * * Global variable *     viddevs    The viddevs struct is "global" within the context of video.c *                and used in functions vid_*. * Returns *     0                        Success *    -1                        Fatal V4L error *    -2                        Fatal Netcam error *    Positive numbers... *    with bit 0 set            Non fatal V4L error (not implemented) *    with bit 1 set            Non fatal Netcam error */int vid_next(struct context *cnt, unsigned char *map){	struct config *conf=&cnt->conf;	int ret = -1;			if (conf->netcam_url) {		if (cnt->video_dev == -1)			return NETCAM_GENERAL_ERROR;		ret = netcam_next(cnt, map);		return ret;	}#ifndef WITHOUT_V4L	/* We start a new block so we can make declarations without breaking	 * gcc 2.95 or older	 */	{		int i = -1;		int width, height;		int dev = cnt->video_dev;		/* NOTE: Since this is a capture, we need to use capture dimensions. */		width = cnt->rotate_data.cap_width;		height = cnt->rotate_data.cap_height;				while (viddevs[++i])			if (viddevs[i]->fd == dev)				break;		if (!viddevs[i])			return V4L_FATAL_ERROR;		if (viddevs[i]->owner != cnt->threadnr) {			pthread_mutex_lock(&viddevs[i]->mutex);			viddevs[i]->owner = cnt->threadnr;			viddevs[i]->frames = conf->roundrobin_frames;			cnt->switched = 1;		}		v4l_set_input(cnt, viddevs[i], map, width, height, conf->input, conf->norm,		               conf->roundrobin_skip, conf->frequency, conf->tuner_number);		ret = v4l_next(viddevs[i], map, width, height);		if (--viddevs[i]->frames <= 0) {			viddevs[i]->owner = -1;			pthread_mutex_unlock(&viddevs[i]->mutex);		}			if(cnt->rotate_data.degrees > 0) {			/* rotate the image as specified */			rotate_map(cnt, map);		}	}#endif /*WITHOUT_V4L*/	return ret;}#ifndef WITHOUT_V4Lint vid_startpipe(const char *devname, int width, int height, int type){	return v4l_startpipe( (char *)devname, 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 + -