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

📄 motion.c

📁 video motion detection of linux base
💻 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)) #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"/** * 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. */int debug_level;/** * 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). */int restart=0;/** * 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){	int j;	if (cnt->imgs.out)		free(cnt->imgs.out);	if (cnt->imgs.ref)		free(cnt->imgs.ref);	if (cnt->imgs.image_virgin)		free(cnt->imgs.image_virgin);	if (cnt->imgs.image_ring_buffer)		free(cnt->imgs.image_ring_buffer);	if (cnt->imgs.labels)		free(cnt->imgs.labels);	if (cnt->imgs.labelsize)		free(cnt->imgs.labelsize);	if (cnt->imgs.smartmask)		free(cnt->imgs.smartmask);	if (cnt->imgs.smartmask_final)		free(cnt->imgs.smartmask_final);	if (cnt->imgs.smartmask_buffer)		free(cnt->imgs.smartmask_buffer);	if (cnt->imgs.common_buffer)		free(cnt->imgs.common_buffer);	if (cnt->imgs.timestamp)		free(cnt->imgs.timestamp);	if (cnt->imgs.shotstamp)		free(cnt->imgs.shotstamp);	if (cnt->imgs.preview_buffer)		free(cnt->imgs.preview_buffer);	rotate_deinit(cnt); /* cleanup image rotation data */	if(cnt->pipe != -1)		close(cnt->pipe);	if(cnt->mpipe != -1)		close(cnt->mpipe);	/* Cleanup the netcam part */	if(cnt->netcam)		netcam_cleanup(cnt->netcam, 0);	/* Cleanup the current time structure */	if (cnt->currenttime_tm)		free(cnt->currenttime_tm);	/* Cleanup the event time structure */	if (cnt->eventtime_tm)		free(cnt->eventtime_tm);	/* 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){	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;				}			}			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_detected * *   Called from 'motion_loop' when motion is detected, or when to act as if *   motion was detected (e.g. in post capture). * * Parameters: * *   cnt      - current thread's context struct *   diffs    - number of different pixels between the reference image and the *              new image (may be zero) *   dev      - video device file descriptor *   devpipe  - file descriptor of still image pipe *   devmpipe - file descriptor of motion pipe *   newimg   - pointer to the newly captured image */static void motion_detected(struct context *cnt, int diffs, int dev, unsigned char *newimg){	struct config *conf = &cnt->conf;	struct images *imgs = &cnt->imgs;	struct coord *location = &cnt->location;	cnt->lasttime = cnt->currenttime;	/* Take action if this is a new event */	if (cnt->event_nr != cnt->prev_event) {		int i, tmpshots;		struct tm tmptime;		cnt->preview_max = 0;		/* Reset prev_event number to current event and save event time		 * in both time_t and struct tm format.		 */		cnt->prev_event = cnt->event_nr;		cnt->eventtime = cnt->currenttime;		localtime_r(&cnt->eventtime, cnt->eventtime_tm);		/* Since this is a new event we create the event_text_string used for		 * the %C conversion specifier. We may already need it for		 * on_motion_detected_commend so it must be done now.		 */		mystrftime(cnt, cnt->text_event_string, sizeof(cnt->text_event_string),		           cnt->conf.text_event, cnt->eventtime_tm, NULL, 0);		/* EVENT_FIRSTMOTION triggers on_event_start_command and event_ffmpeg_newfile */		event(cnt, EVENT_FIRSTMOTION, newimg, NULL, NULL, cnt->currenttime_tm);		if (cnt->conf.setup_mode)			motion_log(-1, 0, "Motion detected - starting event %d", cnt->event_nr);		/* pre_capture frames are written as jpegs and to the ffmpeg film		 * We store the current cnt->shots temporarily until we are done with		 * the pre_capture stuff		 */		tmpshots = cnt->shots;		for (i=cnt->precap_cur; i < cnt->precap_nr; i++) {			localtime_r(cnt->imgs.timestamp + i, &tmptime);			cnt->shots = *(cnt->imgs.shotstamp + i);			event(cnt, EVENT_IMAGE_DETECTED,			    cnt->imgs.image_ring_buffer + (cnt->imgs.size * i), NULL, NULL, &tmptime);		}		if (cnt->precap_cur) {			localtime_r(cnt->imgs.timestamp+cnt->precap_nr, &tmptime);			cnt->shots = *(cnt->imgs.shotstamp + cnt->precap_nr);			event(cnt, EVENT_IMAGE_DETECTED,			      cnt->imgs.image_ring_buffer + (cnt->imgs.size * cnt->precap_nr),			      NULL, NULL, &tmptime);		}		for (i=0; i < cnt->precap_cur-1; i++) {			localtime_r(cnt->imgs.timestamp + i, &tmptime);			cnt->shots = *(cnt->imgs.shotstamp + i);			event(cnt, EVENT_IMAGE_DETECTED,			      cnt->imgs.image_ring_buffer + (cnt->imgs.size * i),			      NULL, NULL, &tmptime);		}		/* If output_normal=first always capture first motion frame as preview-shot */		if (cnt->new_img == NEWIMG_FIRST){			cnt->preview_shot = 1;			if (cnt->locate == LOCATE_PREVIEW){				alg_draw_location(location, imgs, imgs->width, newimg, LOCATE_NORMAL);			}		}		cnt->shots = tmpshots;	}	/* motion_detected is called with diffs = 0 during post_capture	 * and if cnt->conf.output_all is enabled. We only want to draw location	 * and call EVENT_MOTION when it is a picture frame with actual motion detected.	 */	if (diffs) {		if (cnt->locate == LOCATE_ON)			alg_draw_location(location, imgs, imgs->width, newimg, LOCATE_BOTH);		/* EVENT_MOTION triggers event_beep and on_motion_detected_command */		event(cnt, EVENT_MOTION, NULL, NULL, NULL, cnt->currenttime_tm);	}	/* Check for most significant preview-shot when output_normal=best */	if (cnt->new_img == NEWIMG_BEST && diffs > cnt->preview_max) {		memcpy(cnt->imgs.preview_buffer, newimg, cnt->imgs.size);		cnt->preview_max = diffs;		if (cnt->locate == LOCATE_PREVIEW){			alg_draw_location(location, imgs, imgs->width, cnt->imgs.preview_buffer, LOCATE_NORMAL);		}	}	if (cnt->shots < conf->frame_limit) {		cnt->lastshottime = cnt->currenttime;		/* Output the latest picture 'image_new' or image_out for motion picture. */		event(cnt, EVENT_IMAGE_DETECTED, newimg, NULL, NULL, cnt->currenttime_tm);		/* If config option webcam_motion is enabled, send the latest motion detected image		 * to the webcam but only if it is not the first shot within a second. This is to		 * avoid double frames since we already have sent a frame to the webcam.		 * We also disable this in setup_mode.		 */		if (conf->webcam_motion && !conf->setup_mode && cnt->shots != 1)			event(cnt, EVENT_WEBCAM, newimg, NULL, NULL, cnt->currenttime_tm);		cnt->preview_shot = 0;	}	if (cnt->track.type != 0 && diffs != 0)	{		cnt->moved = track_move(cnt, dev, &cnt->location, imgs, 0);	}}/** *  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)){		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");	}}

⌨️ 快捷键说明

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