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

📄 motion.c

📁 motion motion
💻 C
📖 第 1 页 / 共 5 页
字号:
/*	motion.c * *	Detect changes in a video stream. *	Copyright 2000 by Jeroen Vreeken (pe1rxq@amsat.org) *	This software is distributed under the GNU public license version 2 *	See also the file 'COPYING'. * */#include "ffmpeg.h"#include "motion.h"#if (defined(BSD) && !defined(PWCBSD))#include "video_freebsd.h"#else#include "video.h"#endif /* BSD */#include "conf.h"#include "alg.h"#include "track.h"#include "event.h"#include "picture.h"#include "rotate.h"/* Forward declarations */static int motion_init(struct context *cnt);static void motion_cleanup(struct context *cnt);/** * tls_key_threadnr * *   TLS key for storing thread number in thread-local storage. */pthread_key_t tls_key_threadnr;/** * global_lock * *   Protects any global variables (like 'threads_running') during updates, *   to prevent problems with multiple threads updating at the same time. *///pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t global_lock;/** * cnt_list * *   List of context structures, one for each main Motion thread. */struct context **cnt_list=NULL;/** * threads_running * *   Keeps track of number of Motion threads currently running. Also used *   by 'main' to know when all threads have exited. */volatile int threads_running=0;/* * debug_level is for developers, normally used to control which * types of messages get output. */unsigned short int debug_level;/* Set this when we want main to end or restart */volatile unsigned short int finish=0;/** * restart * *   Differentiates between a quit and a restart. When all threads have *   finished running, 'main' checks if 'restart' is true and if so starts *   up again (instead of just quitting). */unsigned short int restart=0;/** * image_ring_resize * * This routine is called from motion_loop to resize the image precapture ringbuffer * NOTE: This function clears all images in the old ring buffer  * Parameters: * *      cnt      Pointer to the motion context structure *      new_size The new size of the ring buffer * * Returns:     nothing */static void image_ring_resize(struct context *cnt, int new_size){	/* Only resize if :	 * Not in an event and	 * decreasing at last position in new buffer	 * increasing at last position in old buffer 	 * e.g. at end of smallest buffer */	if (cnt->event_nr != cnt->prev_event) {		int smallest;		if (new_size < cnt->imgs.image_ring_size) { /* Decreasing */			smallest = new_size;		} else { /* Increasing */			smallest = cnt->imgs.image_ring_size;		}		if (cnt->imgs.image_ring_in == smallest - 1 || smallest == 0) {			motion_log(LOG_INFO, 0, "Resizing pre_capture buffer to %d items", new_size);			/* Create memory for new ring buffer */			struct image_data *tmp;			tmp = mymalloc(new_size * sizeof(struct image_data));			/* Copy all information from old to new 			 * Smallest is 0 at initial init */			if (smallest > 0) {				memcpy(tmp, cnt->imgs.image_ring, sizeof(struct image_data) * smallest);			}			/* In the new buffers, allocate image memory */			{				int i;				for(i = smallest; i < new_size; i++) {					tmp[i].image = mymalloc(cnt->imgs.size);					memset(tmp[i].image, 0x80, cnt->imgs.size);  /* initialize to grey */				}			}						/* Free the old ring */			free(cnt->imgs.image_ring);			/* Point to the new ring */			cnt->imgs.image_ring = tmp;			cnt->imgs.image_ring_size = new_size;		}	}}/** * image_ring_destroy * * This routine is called when we want to free the ring * * Parameters: * *      cnt      Pointer to the motion context structure * * Returns:     nothing */static void image_ring_destroy(struct context *cnt){	unsigned short int i;		/* Exit if don't have any ring */	if (cnt->imgs.image_ring == NULL)		return;	/* Free all image buffers */	for (i = 0; i < cnt->imgs.image_ring_size; i++) {		free(cnt->imgs.image_ring[i].image);	}		/* Free the ring */	free(cnt->imgs.image_ring);	cnt->imgs.image_ring = NULL;	cnt->imgs.image_ring_size = 0;}/** * image_save_as_preview * * This routine is called when we detect motion and want to save a image in the preview buffer * * Parameters: * *      cnt      Pointer to the motion context structure *      img      Pointer to the image_data structure we want to set as preview image * * Returns:     nothing */static void image_save_as_preview(struct context *cnt, struct image_data *img){	void * image;	/* Save preview image pointer */	image = cnt->imgs.preview_image.image;	/* Copy all info */	memcpy(&cnt->imgs.preview_image.image, img, sizeof(struct image_data));	/* restore image pointer */	cnt->imgs.preview_image.image = image;	/* Copy image */	memcpy(cnt->imgs.preview_image.image, img->image, cnt->imgs.size);	/* If we set output_all to yes and during the event	 * there is no image with motion, diffs is 0, we are not going to save the preview event */	if (cnt->imgs.preview_image.diffs == 0)		cnt->imgs.preview_image.diffs = 1;	/* If we have locate on it is already done */	if (cnt->locate == LOCATE_PREVIEW) {		alg_draw_location(&img->location, &cnt->imgs, cnt->imgs.width, cnt->imgs.preview_image.image, LOCATE_NORMAL);	}}/** * context_init * *   Initializes a context struct with the default values for all the *   variables. * * Parameters: * *   cnt - the context struct to destroy * * Returns: nothing */static void context_init (struct context *cnt){	/*	* We first clear the entire structure to zero, then fill in any	* values which have non-zero default values.  Note that this	* assumes that a NULL address pointer has a value of binary 0	* (this is also assumed at other places within the code, i.e.	* there are instances of "if (ptr)").  Just for possible future	* changes to this assumption, any pointers which are intended	* to be initialised to NULL are listed within a comment.	*/	memset(cnt, 0, sizeof(struct context));	cnt->noise = 255;	cnt->lastrate = 25;	memcpy(&cnt->track, &track_template, sizeof(struct trackoptions));	cnt->pipe = -1;	cnt->mpipe = -1;}/** * context_destroy * *   Destroys a context struct by freeing allocated memory, calling the *   appropriate cleanup functions and finally freeing the struct itself. * * Parameters: * *   cnt - the context struct to destroy * * Returns: nothing */static void context_destroy(struct context *cnt){	unsigned short int j;	/* Free memory allocated for config parameters */	for (j = 0; config_params[j].param_name != NULL; j++) {		if (config_params[j].copy == copy_string) {			void **val;			val = (void *)((char *)cnt+(int)config_params[j].conf_value);			if (*val) {				free(*val);				*val = NULL;			}		}	}	free(cnt);}/** * sig_handler * *  Our SIGNAL-Handler. We need this to handle alarms and external signals. */static void sig_handler(int signo){	short int i;	switch(signo) {		case SIGALRM:			/* Somebody (maybe we ourself) wants us to make a snapshot			 * This feature triggers snapshots on ALL threads that have			 * snapshot_interval different from 0.			 */			if (cnt_list) {				i = -1;				while (cnt_list[++i]) {					if (cnt_list[i]->conf.snapshot_interval) {						cnt_list[i]->snapshot=1;					}				}			}			break;		case SIGUSR1:			/* Ouch! We have been hit from the outside! Someone wants us to			   make a movie! */			if (cnt_list) {				i = -1;				while (cnt_list[++i])					cnt_list[i]->makemovie=1;			}			break;		case SIGHUP:			restart = 1;			/* Fall through, as the value of 'restart' is the only difference			 * between SIGHUP and the ones below.			 */		case SIGINT:		case SIGQUIT:		case SIGTERM:			/* Somebody wants us to quit! We should better finish the actual			    movie and end up! */			if (cnt_list) {				i = -1;				while (cnt_list[++i]) {					cnt_list[i]->makemovie=1;					cnt_list[i]->finish=1;					/* don't restart thread when it ends, 					 * all threads restarts if global restart is set 					 */					cnt_list[i]->restart=0;				}			}			/* Set flag we want to quit main check threads loop			 * if restart is set (above) we start up again */			finish = 1;			break;		case SIGSEGV:			exit(0);	}}/** * sigchild_handler * *   This function is a POSIX compliant replacement of the commonly used *   signal(SIGCHLD, SIG_IGN). */static void sigchild_handler(int signo ATTRIBUTE_UNUSED){#ifdef WNOHANG	while (waitpid(-1, NULL, WNOHANG) > 0) {};#endif /* WNOHANG */	return;}/** *  motion_remove_pid * *  This function remove the process id file ( pid file ) before motion exit. * */static void motion_remove_pid(void){	if ((cnt_list[0]->daemon) && (cnt_list[0]->conf.pid_file) && (restart == 0)) {		if (!unlink(cnt_list[0]->conf.pid_file)) 		    motion_log(LOG_INFO, 0, "Removed process id file (pid file).");		else 		    motion_log(LOG_INFO, 1, "Error removing pid file");	}}/** * motion_detected * *   Called from 'motion_loop' when motion is detected *   Can be called when no motion if output_all is set! * * Parameters: * *   cnt      - current thread's context struct *   dev      - video device file descriptor *   img      - pointer to the captured image_data with detected motion */static void motion_detected(struct context *cnt, int dev, struct image_data *img){	struct config *conf = &cnt->conf;	struct images *imgs = &cnt->imgs;	struct coord *location = &img->location;

⌨️ 快捷键说明

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