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

📄 netcam.c

📁 video motion detection of linux base
💻 C
📖 第 1 页 / 共 4 页
字号:
				/* This will cause a 'continue' of the main loop */				bptr = NULL;				/* Return to do the boundary compare from the start */				break;			}             /* end of while(1) input buffer search */			/* !bptr shows we're processing split boundary */			if (!bptr)				continue;		}             /* end of if(bptr) */		/* boundary string not present, so just write out as much data as possible */		if (remaining) {			maxflush = MINVAL(netcam->response->buffer_left, remaining);			netcam_check_buffsize(buffer, maxflush);			retval = rbuf_flush(netcam, buffer->ptr + buffer->used, maxflush);			buffer->used += retval;			remaining -= retval;		}	}	/*	 * read is complete - set the current 'receiving' buffer atomically	 * as 'latest', and make the buffer previously in 'latest' become	 * the new 'receiving'	 */	if (gettimeofday(&curtime, NULL) < 0) {		motion_log(LOG_ERR, 1, "gettimeofday in netcam_read_jpeg");	}	netcam->receiving->image_time = curtime;	/*	 * Calculate our "running average" time for this netcam's	 * frame transmissions (except for the first time).	 * Note that the average frame time is held in microseconds.	 */	if (netcam->last_image.tv_sec) {		netcam->av_frame_time = (9.0 * netcam->av_frame_time +		                         1000000.0 * (curtime.tv_sec - netcam->last_image.tv_sec) +		                         (curtime.tv_usec- netcam->last_image.tv_usec)) / 10.0;		if (debug_level > 5)			motion_log(-1, 0, "Calculated frame time %f", netcam->av_frame_time);	}	netcam->last_image = curtime;	pthread_mutex_lock(&netcam->mutex);	xchg = netcam->latest;	netcam->latest = netcam->receiving;	netcam->receiving = xchg;	netcam->imgcnt++;	/*	 * We have a new frame ready.  We send a signal so that	 * any thread (e.g. the motion main loop) waiting for the	 * next frame to become available may proceed.	 */	pthread_cond_signal(&netcam->pic_ready);	pthread_mutex_unlock(&netcam->mutex);	if (!netcam->caps.streaming)		netcam_disconnect(netcam);	return 0;}/** * netcam_read_ftp_jpeg * *      This routine reads from a netcam using the FTP protocol. *      The current implementation is still a little experimental, *      and needs some additional code for error detection and *      recovery. */static int netcam_read_ftp_jpeg(netcam_context_ptr netcam){	netcam_buff_ptr buffer;	int len;	netcam_buff *xchg;	struct timeval curtime;	/* Point to our working buffer */	buffer = netcam->receiving;	buffer->used = 0;	/* Request the image from the remote server */	if (ftp_get_socket(netcam->ftp) <= 0) {		motion_log(LOG_ERR, 0, "ftp_get_socket failed in netcam_read_jpeg");		return -1;	}	/* Now fetch the image using ftp_read.  Note this is a blocking call */	do {		/* Assure there's enough room in the buffer */		netcam_check_buffsize(buffer, FTP_BUF_SIZE);		/* Do the read */		if ((len = ftp_read(netcam->ftp, buffer->ptr + buffer->used, FTP_BUF_SIZE)) < 0)			return -1;		buffer->used += len;	} while (len > 0);	if (gettimeofday(&curtime, NULL) < 0) {		motion_log(LOG_ERR, 1, "gettimeofday in netcam_read_jpeg");	}	netcam->receiving->image_time = curtime;	/*	 * Calculate our "running average" time for this netcam's	 * frame transmissions (except for the first time).	 * Note that the average frame time is held in microseconds.	 */	if (netcam->last_image.tv_sec) {		netcam->av_frame_time =		  ((9.0 * netcam->av_frame_time) + 1000000.0 *		  (curtime.tv_sec - netcam->last_image.tv_sec) +		  (curtime.tv_usec- netcam->last_image.tv_usec))		  / 10.0;		if (debug_level > 5)			motion_log(-1, 0, "Calculated frame time %f", netcam->av_frame_time);	}	netcam->last_image = curtime;	/*	 * read is complete - set the current 'receiving' buffer atomically	 * as 'latest', and make the buffer previously in 'latest' become	 * the new 'receiving'	 */	pthread_mutex_lock(&netcam->mutex);	xchg = netcam->latest;	netcam->latest = netcam->receiving;	netcam->receiving = xchg;	netcam->imgcnt++;	/*	 * We have a new frame ready.  We send a signal so that	 * any thread (e.g. the motion main loop) waiting for the	 * next frame to become available may proceed.	 */	pthread_cond_signal(&netcam->pic_ready);	pthread_mutex_unlock(&netcam->mutex);	return 0;}/** * netcam_handler_loop *      This is the "main loop" for the handler thread.  It is created *      in netcam_start when a streaming camera is detected. * * Parameters * *      arg     Pointer to the motion context for this camera * * Returns:     NULL pointer * */static void *netcam_handler_loop(void *arg){	int retval;	int open_error = 0;	netcam_context_ptr netcam = arg;	struct context *cnt = netcam->cnt; /* needed for the SETUP macro :-( */	/* Store the corresponding motion thread number in TLS also for this	 * thread (necessary for 'motion_log' to function properly).	 */	pthread_setspecific(tls_key_threadnr, (void *)((unsigned long)cnt->threadnr));	if (SETUP)		motion_log(LOG_INFO, 0, "Camera handler thread [%d]  started", netcam->threadnr);	/*	 * The logic of our loop is very simple.  If this is a non-	 * streaming camera, we re-establish connection with the camera	 * and read the header record.  If it's a streaming camera, we	 * position to the next "boundary string" in the input stream.	 * In either case, we then read the following JPEG image into the	 * next available buffer, updating the "next" and "latest" indices	 * in our netcam * structure.  The loop continues until netcam->finish	 * or cnt->finish is set.	 */	while (!netcam->finish) {		if (netcam->response) {    /* if html input */			if (!netcam->caps.streaming) {				if (netcam_connect(netcam, open_error) < 0) {					if (!open_error) { /* log first error */						motion_log(LOG_ERR, 0,						    "re-opening camera (non-streaming)");						open_error = 1;					}					/* need to have a dynamic delay here */					SLEEP(5,0);					continue;				}				if (open_error) {          /* log re-connection */					motion_log(LOG_ERR, 0,					    "camera re-connected");					open_error = 0;				}				/* Send our request and look at the response */				if ((retval = netcam_read_first_header(netcam)) != 1) {					if (retval > 0) {						motion_log(LOG_ERR, 0,						    "Unrecognized image header (%d)", retval);					} else if (retval != -1) {						motion_log(LOG_ERR, 0,						           "Error in header (%d)", retval);					}					/* need to have a dynamic delay here */					continue;				}			} else {				if (netcam_read_next_header(netcam) < 0) {					if (netcam_connect(netcam, open_error) < 0) {						if (!open_error) { /* log first error */							motion_log(LOG_ERR, 0,							    "re-opening camera (streaming)");							open_error = 1;						}						SLEEP(5,0);						continue;					}					if ((retval = netcam_read_first_header(netcam) != 2)) {						if (retval > 0) {							motion_log(LOG_ERR, 0,							    "Unrecognized image header (%d)",							     retval);						} else if (retval != -1) {							motion_log(LOG_ERR, 0,							    "Error in header (%d)", retval);						}						/* FIXME need some limit */						continue;					}				}				if (open_error) {          /* log re-connection */					motion_log(LOG_ERR, 0,					    "camera re-connected");					open_error = 0;				}			}		}		if (netcam->get_image(netcam) < 0) {			motion_log(LOG_ERR, 0, "Error getting jpeg image");			/* if FTP connection, attempt to re-connect to server */			if (netcam->ftp) {				close(netcam->ftp->control_file_desc);				if (ftp_connect(netcam) < 0) {					motion_log(LOG_ERR, 0, "Trying to re-connect");				}			}			continue;		}		/*		 * FIXME		 * Need to check whether the image was received / decoded		 * satisfactorily		 */		/*		 * If non-streaming, want to synchronize our thread with the		 * motion main-loop.		 */		if (!netcam->caps.streaming) {			pthread_mutex_lock(&netcam->mutex);			/* before anything else, check for system shutdown */			if (netcam->finish) {				pthread_mutex_unlock(&netcam->mutex);				break;			}			/*			 * If our current loop has finished before the next			 * request from the motion main-loop, we do a			 * conditional wait (wait for signal).  On the other			 * hand, if the motion main-loop has already signalled			 * us, we just continue.  In either event, we clear			 * the start_capture flag set by the main loop.			 */			if (!netcam->start_capture)				pthread_cond_wait(&netcam->cap_cond, &netcam->mutex);			netcam->start_capture = 0;			pthread_mutex_unlock(&netcam->mutex);		}	/* the loop continues forever, or until motion shutdown */	}	/* our thread is finished - decrement motion's thread count */	pthread_mutex_lock(&global_lock);	threads_running--;	pthread_mutex_unlock(&global_lock);	/* log out a termination message */	motion_log(LOG_INFO, 0, "netcam camera handler: finish set, exiting");	/* setting netcam->thread_id to zero shows netcam_cleanup we're done */	netcam->thread_id = 0;	/* signal netcam_cleanup that we're all done */	pthread_mutex_lock(&netcam->mutex);	pthread_cond_signal(&netcam->exiting);	pthread_mutex_unlock(&netcam->mutex);	/* Goodbye..... */	pthread_exit(NULL);}static int netcam_setup_html(netcam_context_ptr netcam, struct url_t *url) {	struct context *cnt = netcam->cnt;	const char *ptr;                  /* working var */	char *userpass;                   /* temp pointer to config value */	char *encuserpass;                /* temp storage for encoded ver */	char *request_pass = NULL;        /* temp storage for base64 conv */	int ix;	/* First the http context structure */	netcam->response = (struct rbuf *) mymalloc(sizeof(struct rbuf));	memset(netcam->response, 0, sizeof(struct rbuf));	/*	 * The network camera may require a username and password.  If	 * so, the information can come from two different places in the	 * motion configuration file.  Either it can be present in	 * the netcam_userpass, or it can be present as a part of the URL	 * for the camera.  We assume the first of these has a higher	 * relevance.	 */	if (cnt->conf.netcam_userpass)		ptr = cnt->conf.netcam_userpass;	else		ptr = url->userpass;	/* base64_encode needs up to 3 additional chars */	if (ptr) {		userpass = mymalloc(strlen(ptr) + 3);		strcpy(userpass, ptr);	} else		userpass = NULL;	/*	 * Now we want to create the actual string which will be used to	 * connect to the camera.  It may or may not contain a username /	 * password.  We first compose a basic connect message, then check	 * whether a username / password is required and, if so, just	 * concatenate it with the request.	 *	 */	/* space for final \r\n plus string terminator */	ix = 3;	/* See if username / password is required */	if (userpass) {         /* if either of the above are non-NULL */		/* Allocate space for the base64-encoded string */		encuserpass = mymalloc(BASE64_LENGTH(strlen(userpass)) + 1);		/* Fill in the value */		base64_encode(userpass, encuserpass, strlen(userpass));		/* Now create the last part (authorization) of the request */		request_pass = mymalloc(strlen(connect_auth_req) +		                        strlen(encuserpass) + 1);		ix += sprintf(request_pass, connect_auth_req, encuserpass);		/* free the working variables */		free(encuserpass);	}	/*	 * We are now ready to set up the netcam's "connect request".  Most of	 * this comes from the (preset) string 'connect_req', but additional	 * characters are required if there is a proxy server, or if there is	 * a username / password for the camera.  The variable 'ix' currently	 * has the number of characters required for username/password (which	 * could be zero) and for the \r\n and string terminator.  We will also	 * always need space for the netcam path, and if a proxy is being used	 * we also need space for a preceding  'http://{hostname}' for the	 * netcam path.	 */	if (cnt->conf.netcam_proxy) {		/*		 * Allocate space for a working string to contain the path.		 * The extra 4 is for "://" and string terminator.		 */		ptr = mymalloc(strlen(url->service) + strlen(url->host)		               + strlen(url->path) + 4);		sprintf((char *)ptr, "http://%s%s", url->host, url->path);	} else {		/* if no proxy, set as netcam_url path */		ptr = url->path;		/*		 * after generating the connect message the string		 * will be freed, so we don't want netcam_url_free		 * to free it as well.		 */		url->path = NULL;	}	ix += strlen(ptr);	/*	 * Now that we know how much space we need, we can allocate space	 * for the connect-request string.	 */	netcam->connect_request = mymalloc(strlen(connect_req) + ix +	                          strlen(netcam->connect_host));	/* Now create the request string with an sprintf */	sprintf(netcam->connect_request, connect_req, ptr,	        netcam->connect_host); 	if (userpass) {		strcat(netcam->connect_request, request_pass);		free(request_pass);		free(userpass);	}	/* put on the final CRLF onto the request */	strcat(netcam->connect_request, "\r\n");	free((void *)ptr);	netcam_url_free(url);         /* Cleanup the url data */	/*	 * Our basic initialisation has been completed.  Now we will attempt	 * to connect with the camera so that we can then get a "header"	 * in order to find out what kind of camera we are dealing with,	 * as well as what are the picture dimensions.  Note that for	 * this initial connection, any failure will cause an error	 * return from netcam_start (unlike later possible attempts at	 * re-connecting, if the network connection is later interrupted).	 */	for (ix = 0; ix < MAX_HEADER_RETRIES; ix++) {		/*		 * netcam_connect does an automatic netcam_close, so it's		 * safe to include it as part of this loop		 */		if (netcam_connect(netcam, 0) != 0) {			motion_log(LOG_ERR, 0,"Failed to open camera - check your config and that netcamera is online");			/* Fatal error on startup */			ix = MAX_HEADER_RETRIES;			break;;		}		if (netcam_read_first_header(netcam) >= 0)			break;		motion_log(LOG_ERR, 0, "Error reading first header - re-trying");	}	if (ix == MAX_HEADER_RETRIES) {		motion_log(LOG_ERR, 0, "Failed to read first camera header - giving up for now");		return -1;	}	/*	 * If this is a streaming camera, we need to position just	 * past the boundary string and read the image header	 */	if (netcam->caps.streaming) {		if (netcam_read_next_header(netcam) < 0) {			motion_log(LOG_ERR, 0,			           "Failed to read first stream header - giving up for now");			return -1;		}	}	netcam->get_image = netcam_read_html_jpeg;	return 0;}static int netcam_setup_ftp(netcam_context_ptr netcam, struct url_t *url) {	struct context *cnt = netcam->cnt;	const char *ptr;	if ((netcam->ftp = ftp_new_context()) == NULL)		return -1;

⌨️ 快捷键说明

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