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

📄 video2.c

📁 motion motion
💻 C
📖 第 1 页 / 共 2 页
字号:
	for (b = 0; b < s->req.count; b++) {		struct v4l2_buffer buf;		memset(&buf, 0, sizeof(struct v4l2_buffer));		buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;		buf.memory = V4L2_MEMORY_MMAP;		buf.index = b;		if (xioctl(s->fd, VIDIOC_QUERYBUF, &buf) == -1) {			motion_log(LOG_ERR, 0, "Error querying buffer %i", b);			motion_log(LOG_ERR, 0, "VIDIOC_QUERYBUF: %s", strerror(errno));			free(s->buffers);			return (-1);		}		s->buffers[b].size = buf.length;		s->buffers[b].ptr = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset);		if (s->buffers[b].ptr == MAP_FAILED) {			motion_log(LOG_ERR, 0, "Error mapping buffer %i", b);			motion_log(LOG_ERR, 0, "mmap: %s", strerror(errno));			free(s->buffers);			return (-1);		}		motion_log(LOG_DEBUG, 0, "%i length=%d", b, buf.length);	}	s->map = -1;	for (b = 0; b < s->req.count; b++) {		memset(&s->buf, 0, sizeof(struct v4l2_buffer));		s->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;		s->buf.memory = V4L2_MEMORY_MMAP;		s->buf.index = b;		if (xioctl(s->fd, VIDIOC_QBUF, &s->buf) == -1) {			motion_log(LOG_ERR, 0, "VIDIOC_QBUF: %s", strerror(errno));			return (-1);		}	}	type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	if (xioctl(s->fd, VIDIOC_STREAMON, &type) == -1) {		motion_log(LOG_ERR, 0, "Error starting stream.");		motion_log(LOG_ERR, 0, "VIDIOC_STREAMON: %s", strerror(errno));		return (-1);	}	return (0);}static int v4l2_scan_controls(src_v4l2_t * s){	int count, i;	struct v4l2_queryctrl queryctrl;	memset(&queryctrl, 0, sizeof(struct v4l2_queryctrl));	for (i = 0, count = 0; queried_ctrls[i]; i++) {		queryctrl.id = queried_ctrls[i];		if (xioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl))			continue;		count++;		s->ctrl_flags |= 1 << i;	}	if (count) {		struct v4l2_queryctrl *ctrl = s->controls = calloc(count, sizeof(struct v4l2_queryctrl));		if (!ctrl) {			motion_log(LOG_ERR, 0, "%s: Insufficient buffer memory.", __FUNCTION__);			return (-1);		}		for (i = 0; queried_ctrls[i]; i++) {			if (s->ctrl_flags & (1 << i)) {				struct v4l2_control control;				queryctrl.id = queried_ctrls[i];				if (xioctl(s->fd, VIDIOC_QUERYCTRL, &queryctrl))					continue;				memcpy(ctrl, &queryctrl, sizeof(struct v4l2_queryctrl));				motion_log(LOG_INFO, 0, "found control 0x%08x, \"%s\", range %d,%d %s", ctrl->id,					   ctrl->name, ctrl->minimum, ctrl->maximum,					   ctrl->flags & V4L2_CTRL_FLAG_DISABLED ? "!DISABLED!" : "");				memset (&control, 0, sizeof (control));				control.id = queried_ctrls[i];				xioctl(s->fd, VIDIOC_G_CTRL, &control);				motion_log(LOG_INFO, 0, "\t\"%s\", default %d, current %d", ctrl->name,					   ctrl->default_value, control.value);				ctrl++;			}		}	}	return 0;}static int v4l2_set_control(src_v4l2_t * s, u32 cid, int value){	int i, count;	if (!s->controls)		return -1;	for (i = 0, count = 0; queried_ctrls[i]; i++) {		if (s->ctrl_flags & (1 << i)) {			if (cid == queried_ctrls[i]) {				struct v4l2_queryctrl *ctrl = s->controls + count;				struct v4l2_control control;				int ret;				memset (&control, 0, sizeof (control));				control.id = queried_ctrls[i];				switch (ctrl->type) {				case V4L2_CTRL_TYPE_INTEGER:					value = control.value =					    (value * (ctrl->maximum - ctrl->minimum) / 256) + ctrl->minimum;					ret = xioctl(s->fd, VIDIOC_S_CTRL, &control);					break;				case V4L2_CTRL_TYPE_BOOLEAN:					value = control.value = value ? 1 : 0;					ret = xioctl(s->fd, VIDIOC_S_CTRL, &control);					break;				default:					motion_log(LOG_ERR, 0, "%s: control type not supported yet");					return -1;				}				if (debug_level > 5)					motion_log(LOG_INFO, 0, "setting control \"%s\" to %d (ret %d %s) %s", ctrl->name,						value, ret, ret ? strerror(errno) : "",						ctrl->flags & V4L2_CTRL_FLAG_DISABLED ? "Control is DISABLED!" : "");				return 0;			}			count++;		}	}	return -1;}static void v4l2_picture_controls(struct context *cnt, struct video_dev *viddev){	src_v4l2_t *s = (src_v4l2_t *) viddev->v4l2_private;	if (cnt->conf.contrast && cnt->conf.contrast != viddev->contrast) {		viddev->contrast = cnt->conf.contrast;		v4l2_set_control(s, V4L2_CID_CONTRAST, viddev->contrast);	}	if (cnt->conf.saturation && cnt->conf.saturation != viddev->saturation) {		viddev->saturation = cnt->conf.saturation;		v4l2_set_control(s, V4L2_CID_SATURATION, viddev->saturation);	}	if (cnt->conf.hue && cnt->conf.hue != viddev->hue) {		viddev->hue = cnt->conf.hue;		v4l2_set_control(s, V4L2_CID_HUE, viddev->hue);	}	if (cnt->conf.autobright) {		if (vid_do_autobright(cnt, viddev)) {			if (v4l2_set_control(s, V4L2_CID_BRIGHTNESS, viddev->brightness))				v4l2_set_control(s, V4L2_CID_GAIN, viddev->brightness);		}	} else {		if (cnt->conf.brightness && cnt->conf.brightness != viddev->brightness) {			viddev->brightness = cnt->conf.brightness;			if (v4l2_set_control(s, V4L2_CID_BRIGHTNESS, viddev->brightness))				v4l2_set_control(s, V4L2_CID_GAIN, viddev->brightness);		}	}}/* public functions */unsigned char *v4l2_start(struct context *cnt, struct video_dev *viddev, int width, int height,			  int input, int norm, unsigned long freq, int tuner_number){	src_v4l2_t *s;	/* Allocate memory for the state structure. */	if (!(s = calloc(sizeof(src_v4l2_t), 1))) {		motion_log(LOG_ERR, 0, "%s: Out of memory.", __FUNCTION__);		goto err;	}	viddev->v4l2_private = s;	s->fd = viddev->fd;	s->fps = cnt->conf.frame_limit;	s->pframe = -1;	if (v4l2_get_capability(s)) {		goto err;	}	if (v4l2_select_input(s, input, norm, freq, tuner_number)) {		goto err;	}	if (v4l2_set_pix_format(cnt ,s, &width, &height)) {		goto err;	}	if (v4l2_scan_controls(s)) {		goto err;	}#if 0	v4l2_set_fps(s);#endif	if (v4l2_set_mmap(s)) {		goto err;	}	viddev->size_map = 0;	viddev->v4l_buffers[0] = NULL;	viddev->v4l_maxbuffer = 1;	viddev->v4l_curbuffer = 0;	viddev->v4l_fmt = VIDEO_PALETTE_YUV420P;	viddev->v4l_bufsize = (width * height * 3) / 2;	/* Update width and height with supported values from camera driver */	viddev->width = width;	viddev->height = height;	return (void *) 1;      err:	if (s)		free(s);	viddev->v4l2_private = NULL;	viddev->v4l2 = 0;	return NULL;}void v4l2_set_input(struct context *cnt, struct video_dev *viddev, unsigned char *map, int width, int height,		    struct config *conf){	int i;	int input = conf->input;	int norm = conf->norm;	int skip = conf->roundrobin_skip;	unsigned long freq = conf->frequency;	int tuner_number = conf->tuner_number;	if (input != viddev->input || width != viddev->width || height != viddev->height ||	    freq != viddev->freq || tuner_number != viddev->tuner_number) {		struct timeval switchTime;		v4l2_select_input((src_v4l2_t *) viddev->v4l2_private, input, norm, freq, tuner_number);		gettimeofday(&switchTime, NULL);		v4l2_picture_controls(cnt, viddev);		viddev->input = input;		viddev->width = width;		viddev->height = height;		viddev->freq = freq;		viddev->tuner_number = tuner_number;		/* Skip all frames captured before switchtime, capture 1 after switchtime */		{			src_v4l2_t *s = (src_v4l2_t *) viddev->v4l2_private;			unsigned int counter = 0;			if (debug_level > 5)				motion_log(LOG_DEBUG, 0, "set_input_skip_frame switch_time=%ld:%ld", 						switchTime.tv_sec, switchTime.tv_usec);			/* Avoid hang using the number of mmap buffers */			while(counter < s->req.count)			{				counter++;				if (v4l2_next(cnt, viddev, map, width, height))					break;				if (s->buf.timestamp.tv_sec > switchTime.tv_sec || 				(s->buf.timestamp.tv_sec == switchTime.tv_sec && s->buf.timestamp.tv_usec > switchTime.tv_usec))					break;				if (debug_level > 5)					motion_log(LOG_DEBUG, 0, "got frame before switch timestamp=%ld:%ld", 						s->buf.timestamp.tv_sec, s->buf.timestamp.tv_usec);			}		}		/* skip a few frames if needed */		for (i = 1; i < skip; i++)			v4l2_next(cnt, viddev, map, width, height);	} else {		/* No round robin - we only adjust picture controls */		v4l2_picture_controls(cnt, viddev);	}}int v4l2_next(struct context *cnt, struct video_dev *viddev, unsigned char *map, int width, int height){	sigset_t set, old;	src_v4l2_t *s = (src_v4l2_t *) viddev->v4l2_private;	if (viddev->v4l_fmt != VIDEO_PALETTE_YUV420P) {		return V4L_FATAL_ERROR;	}	/* 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);	if (s->pframe >= 0) {		if (xioctl(s->fd, VIDIOC_QBUF, &s->buf) == -1) {			motion_log(LOG_ERR, 0, "%s: VIDIOC_QBUF: %s", __FUNCTION__, strerror(errno));			return (-1);		}	}	memset(&s->buf, 0, sizeof(struct v4l2_buffer));	s->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	s->buf.memory = V4L2_MEMORY_MMAP;	if (xioctl(s->fd, VIDIOC_DQBUF, &s->buf) == -1) {		/* some drivers return EIO when there is no signal, 		   driver might dequeue an (empty) buffer despite		   returning an error, or even stop capturing.		*/		if ( errno == EIO ){			s->pframe++; 			if ((u32)s->pframe >= s->req.count) s->pframe=0;			s->buf.index = s->pframe;			motion_log(LOG_ERR, 0, "%s: VIDIOC_DQBUF: EIO (s->pframe %d)", __FUNCTION__,s->pframe);			return (1);		}		motion_log(LOG_ERR, 0, "%s: VIDIOC_DQBUF: %s", __FUNCTION__, strerror(errno));		return (-1);	}	s->pframe = s->buf.index;	s->buffers[s->buf.index].used = s->buf.bytesused;	s->buffers[s->buf.index].content_length = s->buf.bytesused;	pthread_sigmask(SIG_UNBLOCK, &old, NULL);	/*undo the signal blocking */	{		netcam_buff *the_buffer = &s->buffers[s->buf.index];		switch (s->fmt.fmt.pix.pixelformat) {		case V4L2_PIX_FMT_RGB24:			conv_rgb24toyuv420p(map, (unsigned char *) the_buffer->ptr, width, height);			return 0;		case V4L2_PIX_FMT_UYVY:			conv_uyvyto420p(map, (unsigned char *) the_buffer->ptr, (unsigned)width, (unsigned)height);			return 0;		case V4L2_PIX_FMT_YUYV:		case V4L2_PIX_FMT_YUV422P:			conv_yuv422to420p(map, (unsigned char *) the_buffer->ptr, width, height);			return 0;		case V4L2_PIX_FMT_YUV420:			memcpy(map, the_buffer->ptr, viddev->v4l_bufsize);			return 0;		case V4L2_PIX_FMT_MJPEG:#ifdef MJPEGT			mjpegtoyuv420p(map, (unsigned char *) the_buffer->ptr, width, height, s->buffers[s->buf.index].content_length);			return 0;#endif		case V4L2_PIX_FMT_JPEG:			return conv_jpeg2yuv420(cnt, map, the_buffer, width, height);		case V4L2_PIX_FMT_SBGGR8:	/* bayer */			bayer2rgb24(cnt->imgs.common_buffer, (unsigned char *) the_buffer->ptr, width, height);			conv_rgb24toyuv420p(map, cnt->imgs.common_buffer, width, height);			return 0;		case V4L2_PIX_FMT_SN9C10X:			sonix_decompress(map, (unsigned char *) the_buffer->ptr, width, height);			bayer2rgb24(cnt->imgs.common_buffer, map, width, height);			conv_rgb24toyuv420p(map, cnt->imgs.common_buffer, width, height);			return 0;		}	}	return 1;}void v4l2_close(struct video_dev *viddev){	src_v4l2_t *s = (src_v4l2_t *) viddev->v4l2_private;	enum v4l2_buf_type type;	type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	xioctl(s->fd, VIDIOC_STREAMOFF, &type);	close(s->fd);	s->fd = -1;}void v4l2_cleanup(struct video_dev *viddev){	src_v4l2_t *s = (src_v4l2_t *) viddev->v4l2_private;	if (s->buffers) {		unsigned int i;		for (i = 0; i < s->req.count; i++)			munmap(s->buffers[i].ptr, s->buffers[i].size);		free(s->buffers);		s->buffers = NULL;	}	if (s->controls) {		free(s->controls);		s->controls = NULL;	}	free(s);	viddev->v4l2_private = NULL;}#endif#endif

⌨️ 快捷键说明

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