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

📄 video_common.c

📁 motion motion
💻 C
📖 第 1 页 / 共 2 页
字号:
		j++;	}	avg = avg / j;	/* average is above window - turn down brightness - go for the target */	if (avg > brightness_window_high) {		step = MIN2((avg - brightness_target) / AUTOBRIGHT_DAMPER + 1, viddev->brightness - AUTOBRIGHT_MIN);		if (viddev->brightness > step + 1 - AUTOBRIGHT_MIN) {			viddev->brightness -= step;			make_change = 1;		}	} else if (avg < brightness_window_low) {		/* average is below window - turn up brightness - go for the target */		step = MIN2((brightness_target - avg) / AUTOBRIGHT_DAMPER + 1, AUTOBRIGHT_MAX - viddev->brightness);		if (viddev->brightness < AUTOBRIGHT_MAX - step) {			viddev->brightness += step;			make_change = 1;		}	}	return make_change;}/*****************************************************************************	Wrappers calling the actual capture routines *****************************************************************************/#ifndef WITHOUT_V4L/* big lock for vid_start to ensure exclusive access to viddevs while adding  * devices during initialization of each thread */static pthread_mutex_t vid_mutex;/* for the v4l stuff: */#include <sys/mman.h>#include <sys/utsname.h>#include <dirent.h>/* Here we setup the viddevs structure which is used globally in the vid_* * functions. */static struct video_dev *viddevs = NULL;/** * vid_init * * Called from motion.c at the very beginning before setting up the threads. * Function prepares the vid_mutex */void vid_init(void){	pthread_mutex_init(&vid_mutex, NULL);}/** * vid_cleanup * * vid_cleanup is called from motion.c when Motion is stopped or restarted */void vid_cleanup(void){	pthread_mutex_destroy(&vid_mutex);}#endif	/* WITHOUT_V4L *//** * vid_close * * vid_close is called from motion.c when a Motion thread is stopped or restarted */void vid_close(struct context *cnt){#ifndef WITHOUT_V4L	struct video_dev *dev = viddevs;	struct video_dev *prev = NULL;#endif /* WITHOUT_V4L */ 	/* Cleanup the netcam part */	if(cnt->netcam) {		motion_log(LOG_DEBUG, 0, "vid_close: calling netcam_cleanup");		netcam_cleanup(cnt->netcam, 0);		cnt->netcam = NULL;		return;	}#ifndef WITHOUT_V4L	/* Cleanup the v4l part */	pthread_mutex_lock(&vid_mutex);	while (dev) {		if (dev->fd == cnt->video_dev)			break;		prev = dev;		dev = dev->next;	}	pthread_mutex_unlock(&vid_mutex);	/* Set it as closed in thread context */	cnt->video_dev = -1;	if (dev == NULL) {		motion_log(LOG_ERR, 0, "vid_close: Unable to find video device");		return;	}	if( --dev->usage_count == 0) {		motion_log(LOG_INFO, 0, "Closing video device %s", dev->video_device);#ifdef MOTION_V4L2		if (dev->v4l2) {			v4l2_close(dev);			v4l2_cleanup(dev);		} else {#endif			close(dev->fd);			munmap(viddevs->v4l_buffers[0], viddevs->size_map);			munmap(viddevs->v4l_buffers[1], viddevs->size_map);#ifdef MOTION_V4L2		}#endif		dev->fd = -1;		pthread_mutex_lock(&vid_mutex);		/* Remove from list */		if (prev == NULL)			viddevs = dev->next;		else			prev->next = dev->next;		pthread_mutex_unlock(&vid_mutex);		pthread_mutexattr_destroy(&dev->attr);		pthread_mutex_destroy(&dev->mutex);		free(dev);	} else {		motion_log(LOG_INFO, 0, "Still %d users of video device %s, so we don't close it now", dev->usage_count, dev->video_device);		/* There is still at least one thread using this device 		 * If we own it, release it		 */		if (dev->owner == cnt->threadnr) {			dev->frames = 0;			dev->owner = -1;			pthread_mutex_unlock(&dev->mutex);		}	}#endif /* WITHOUT_V4L */}#ifndef WITHOUT_V4L/** * vid_v4lx_start * * Called from vid_start setup the V4L/V4L2 capture device * The function does the following: *    * - Setup basic V4L/V4L2 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. */static int vid_v4lx_start(struct context *cnt){	struct config *conf = &cnt->conf;	int fd = -1;	struct video_dev *dev;	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	 */	dev = viddevs;	while (dev) {		if (!strcmp(conf->video_device, dev->video_device)) {			dev->usage_count++;			cnt->imgs.type = dev->v4l_fmt;			switch (cnt->imgs.type) {			case VIDEO_PALETTE_GREY:				cnt->imgs.motionsize = width * height;				cnt->imgs.size = width * height;				break;			case VIDEO_PALETTE_YUYV:			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;			}			pthread_mutex_unlock(&vid_mutex);			return dev->fd;		}		dev = dev->next;	}	dev = mymalloc(sizeof(struct video_dev));	memset(dev, 0, sizeof(struct video_dev));	dev->video_device = conf->video_device;	fd = open(dev->video_device, O_RDWR);	if (fd < 0) {		motion_log(LOG_ERR, 1, "Failed to open video device %s", conf->video_device);		free(dev);		pthread_mutex_unlock(&vid_mutex);		return -1;	}	pthread_mutexattr_init(&dev->attr);	pthread_mutex_init(&dev->mutex, &dev->attr);	dev->usage_count = 1;	dev->fd = fd;	dev->input = input;	dev->height = height;	dev->width = width;	dev->freq = frequency;	dev->tuner_number = tuner_number;	/* We set brightness, contrast, saturation and hue = 0 so that they only get	 * set if the config is not zero.	 */	dev->brightness = 0;	dev->contrast = 0;	dev->saturation = 0;	dev->hue = 0;	dev->owner = -1;	dev->v4l_fmt = VIDEO_PALETTE_YUV420P;#ifdef MOTION_V4L2	/* First lets try V4L2 and if it's not supported V4L1 */	dev->v4l2 = 1;	if (!v4l2_start(cnt, dev, width, height, input, norm, frequency, tuner_number)) {		/* restore width & height before test with v4l		 * because could be changed in v4l2_start ()		 */		dev->width = width;		dev->height = height;#endif		if (!v4l_start(cnt, dev, width, height, input, norm, frequency, tuner_number)) {			close(dev->fd);			pthread_mutexattr_destroy(&dev->attr);			pthread_mutex_destroy(&dev->mutex);			free(dev);			pthread_mutex_unlock(&vid_mutex);			return -1;		}#ifdef MOTION_V4L2		dev->v4l2 = 0;	}#endif	if (dev->v4l2 == 0) {		motion_log(-1, 0, "Using V4L1");	} else {		motion_log(-1, 0, "Using V4L2");		/* Update width & height because could be changed in v4l2_start () */		width = dev->width;		height = dev->height;		cnt->imgs.width = width;		cnt->imgs.height = height;	}	cnt->imgs.type = dev->v4l_fmt;	switch (cnt->imgs.type) {	case VIDEO_PALETTE_GREY:		cnt->imgs.size = width * height;		cnt->imgs.motionsize = width * height;		break;	case VIDEO_PALETTE_YUYV:	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;	}	/* Insert into linked list */	dev->next = viddevs;	viddevs = dev;	pthread_mutex_unlock(&vid_mutex);return fd;}#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. *     * - if the camera is V4L/V4L2 vid_v4lx_start is called  * * Parameters: *     cnt        Pointer to the context for this thread * * 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) {		dev = netcam_start(cnt);		if (dev < 0) {			netcam_cleanup(cnt->netcam, 1);			cnt->netcam = NULL;		}	}#ifdef WITHOUT_V4L        else			motion_log(LOG_ERR, 0,"You must setup netcam_url");#else	else		dev = vid_v4lx_start(cnt);#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){	int ret = -2;	struct config *conf = &cnt->conf;	if (conf->netcam_url) {		if (cnt->video_dev == -1)			return NETCAM_GENERAL_ERROR;		return netcam_next(cnt, map);	}#ifndef WITHOUT_V4L	/* We start a new block so we can make declarations without breaking	 * gcc 2.95 or older	 */	{		struct video_dev *dev;		int width, height;		/* NOTE: Since this is a capture, we need to use capture dimensions. */		width = cnt->rotate_data.cap_width;		height = cnt->rotate_data.cap_height;		pthread_mutex_lock(&vid_mutex);		dev = viddevs;		while (dev) {			if (dev->fd == cnt->video_dev)				break;			dev = dev->next;		}		pthread_mutex_unlock(&vid_mutex);		if (dev == NULL)			return V4L_FATAL_ERROR;		if (dev->owner != cnt->threadnr) {			pthread_mutex_lock(&dev->mutex);			dev->owner = cnt->threadnr;			dev->frames = conf->roundrobin_frames;		}#ifdef MOTION_V4L2		if (dev->v4l2) {			v4l2_set_input(cnt, dev, map, width, height, conf);			ret = v4l2_next(cnt, dev, map, width, height);		} else {#endif			v4l_set_input(cnt, dev, map, width, height, conf->input, conf->norm,				      conf->roundrobin_skip, conf->frequency, conf->tuner_number);			ret = v4l_next(dev, map, width, height);#ifdef MOTION_V4L2		}#endif		if (--dev->frames <= 0) {			dev->owner = -1;			dev->frames = 0;			pthread_mutex_unlock(&dev->mutex);		}		if (cnt->rotate_data.degrees > 0) {			/* rotate the image as specified */			rotate_map(cnt, map);		}	}#endif				/*WITHOUT_V4L */	return ret;}

⌨️ 快捷键说明

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