Index: conf.c
===================================================================
--- conf.c	(revision 203)
+++ conf.c	(working copy)
@@ -134,6 +134,7 @@
 	text_double:           0,
 	despeckle:             NULL,
 	minimum_motion_frames: 1,
+	minimum_motion_base:   1,
 	pid_file:              NULL,
 	// debug_parameter:       0
 };
@@ -447,6 +448,15 @@
 	print_int
 	},
 	{
+	"minimum_motion_base",
+	"# If there is motion in more than minimum_motion_frames of the latest\n"
+	"# minimum_motion_base frames a event is triggerd.\n"
+	"# Valid range: 1 to thousands, recommended 1-10",
+	CONF_OFFSET(minimum_motion_base),
+	copy_int,
+	print_int
+	},
+	{
 	"pre_capture",
 	"# Specifies the number of pre-captured (buffered) pictures from before motion\n"
 	"# was detected that will be output at motion detection.\n"
Index: conf.h
===================================================================
--- conf.h	(revision 203)
+++ conf.h	(working copy)
@@ -118,6 +118,7 @@
 	int text_double;
 	const char *despeckle;
 	int minimum_motion_frames;
+	int minimum_motion_base;
 	char *pid_file;
 	// int debug_parameter;
 	int argc;
Index: motion.c
===================================================================
--- motion.c	(revision 203)
+++ motion.c	(working copy)
@@ -138,10 +138,12 @@
 		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.timestamp_ring_buffer)
+		free(cnt->imgs.timestamp_ring_buffer);
+	if (cnt->imgs.shotstamp_ring_buffer)
+		free(cnt->imgs.shotstamp_ring_buffer);
+	if (cnt->imgs.diffs_ring_buffer)
+		free(cnt->imgs.diffs_ring_buffer);
 	if (cnt->imgs.preview_buffer)
 		free(cnt->imgs.preview_buffer);
 	rotate_deinit(cnt); /* cleanup image rotation data */
@@ -249,6 +251,20 @@
 }
 
 /**
+ *  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, or when to act as if
@@ -270,12 +286,18 @@
 	struct images *imgs = &cnt->imgs;
 	struct coord *location = &cnt->location;
 
+	/* sanity check */
+	if(newimg != cnt->imgs.image_ring_buffer + (cnt->imgs.size * cnt->imgs.ring_buffer_last_in)) {
+		motion_log(LOG_ERR, 0, "Error in %s: newimg is not at last_in pos in ringbuffer", __FUNCTION__);
+		motion_log(-1, 0, "Thread finishing...");
+		motion_remove_pid();
+		exit(1);	
+	}
+
 	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
@@ -298,43 +320,14 @@
 		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 output_normal=first save first motion frame as preview-shot */
 		if (cnt->new_img == NEWIMG_FIRST){
-			cnt->preview_shot = 1;
+			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, newimg, LOCATE_NORMAL);
+				alg_draw_location(location, imgs, imgs->width, cnt->imgs.preview_buffer, LOCATE_NORMAL);
 			}
 		}
-		cnt->shots = tmpshots;
 	}
 
 	/* motion_detected is called with diffs = 0 during post_capture
@@ -347,7 +340,20 @@
 
 		/* EVENT_MOTION triggers event_beep and on_motion_detected_command */
 		event(cnt, EVENT_MOTION, NULL, NULL, NULL, cnt->currenttime_tm);
+		cnt->postcap = cnt->conf.post_capture;
 	}
+	else {
+		/* sanity check */
+		if(cnt->postcap == 0)
+		{
+			motion_log(LOG_ERR, 0, "Error in %s: cnt->postcap == 0 when called with diff == 0", __FUNCTION__);
+			motion_log(-1, 0, "Thread finishing...");
+			motion_remove_pid();
+			exit(1);	
+		}
+		if(cnt->postcap > 0)
+			cnt->postcap--;
+	}
 
 	/* Check for most significant preview-shot when output_normal=best */
 	if (cnt->new_img == NEWIMG_BEST && diffs > cnt->preview_max) {
@@ -358,46 +364,65 @@
 		}
 	}
 
-
+	/* Limit framerate */
 	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)
+		if (conf->webcam_motion && !conf->setup_mode && cnt->shots != 1) {
 			event(cnt, EVENT_WEBCAM, newimg, NULL, NULL, cnt->currenttime_tm);
-		cnt->preview_shot = 0;
+		}
+
+		/* Save motion jpeg, if configured */
+		/* Output the image_out (motion) picture. */
+		if (conf->motion_img) {
+			event(cnt, EVENT_IMAGEM_DETECTED,
+				NULL, NULL, NULL, cnt->currenttime_tm);
+		}
 	}
 
+	/* Send some images from ring buffer to jpegs and ffmpeg */
+	{
+		int tmpshots;
+		struct tm tmptime;
+		int frames_handled = 0;
+
+		/* 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 ring_buffer stuff
+		 */
+		tmpshots = cnt->shots;
+		while(cnt->imgs.ring_buffer_last_out != cnt->imgs.ring_buffer_last_in)
+		{
+			cnt->imgs.ring_buffer_last_out++;
+			if(cnt->imgs.ring_buffer_last_out >= cnt->imgs.ring_buffer_size)
+				cnt->imgs.ring_buffer_last_out = 0;
+			localtime_r(&cnt->imgs.timestamp_ring_buffer[cnt->imgs.ring_buffer_last_out], &tmptime);
+			cnt->shots = cnt->imgs.shotstamp_ring_buffer[cnt->imgs.ring_buffer_last_out] & 0x0fff;
+			if (cnt->shots < conf->frame_limit) {
+				/* Output the picture to jpegs and ffmpeg */
+				event(cnt, EVENT_IMAGE_DETECTED,
+				    cnt->imgs.image_ring_buffer + (cnt->imgs.size * cnt->imgs.ring_buffer_last_out), NULL, NULL, &tmptime);
+			}
+			frames_handled++;
+			/* breakout if we have done some images (>=2), 
+			 * but if we are at end of postcap send 
+			 * everything left in ring_buffer 
+			 */
+			if(frames_handled >= 2 && !(cnt->postcap == 0))
+				break;
+		}
+		cnt->shots = tmpshots;
+	}
+
 	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) && (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_init
  *
  * This routine is called from motion_loop (the main thread of the program) to do
@@ -470,9 +495,13 @@
 	cnt->imgs.smartmask_buffer = mymalloc(cnt->imgs.motionsize * sizeof(int));
 	cnt->imgs.labels = mymalloc(cnt->imgs.motionsize * sizeof(cnt->imgs.labels));
 	cnt->imgs.labelsize = mymalloc((cnt->imgs.motionsize/2+1) * sizeof(cnt->imgs.labelsize));
-	cnt->imgs.timestamp = mymalloc(sizeof(time_t));
-	cnt->imgs.shotstamp = mymalloc(sizeof(int));
+	cnt->imgs.timestamp_ring_buffer = mymalloc(sizeof(cnt->imgs.timestamp_ring_buffer[0]));
+	cnt->imgs.shotstamp_ring_buffer  = mymalloc(sizeof(cnt->imgs.shotstamp_ring_buffer[0]));
+	cnt->imgs.diffs_ring_buffer  = mymalloc(sizeof(cnt->imgs.diffs_ring_buffer[0]));
 
+	/* allocate buffer here for preview buffer */
+	cnt->imgs.preview_buffer = mymalloc(cnt->imgs.size);
+
 	/* Allocate a buffer for temp. usage in some places */
 	/* Only despeckle & bayer2rgb24() for now for now... */
 	cnt->imgs.common_buffer = mymalloc(3 * cnt->imgs.width * cnt->imgs.height);
@@ -655,7 +684,6 @@
 	struct context *cnt = arg;
 	int i, j, detecting_motion = 0;
 	time_t lastframetime = 0;
-	int postcap = 0;
 	int frame_buffer_size;
 	int smartmask_ratio = 0;
 	int smartmask_count = 20;
@@ -722,8 +750,13 @@
 		/* since we don't have sanity checks done when options are set,
 		 * this sanity check must go in the main loop :(, before pre_captures
 		 * are attempted. */
+
+		if (cnt->conf.minimum_motion_base < 1)
+			cnt->conf.minimum_motion_base = 1;
 		if (cnt->conf.minimum_motion_frames < 1)
 			cnt->conf.minimum_motion_frames = 1;
+		if (cnt->conf.minimum_motion_base < cnt->conf.minimum_motion_frames)
+			cnt->conf.minimum_motion_base = cnt->conf.minimum_motion_frames;
 		if (cnt->conf.pre_capture < 0)
 			cnt->conf.pre_capture = 0;
 
@@ -731,28 +764,42 @@
 		 * If pre_capture or minimum_motion_frames has been changed
 		 * via the http remote control we need to re-size the ring buffer
 		 */
-		frame_buffer_size = cnt->conf.pre_capture + cnt->conf.minimum_motion_frames - 1;
-		if (cnt->precap_nr != frame_buffer_size) {
-			/* Only decrease if at last position in new buffer */
-			if (frame_buffer_size > cnt->precap_nr || frame_buffer_size == cnt->precap_cur) {
-				unsigned char *tmp;
-				time_t *tmp2;
-				int *tmp3;
-				int smallest;
-				smallest = (cnt->precap_nr < frame_buffer_size) ? cnt->precap_nr : frame_buffer_size;
-				tmp=mymalloc(cnt->imgs.size*(1+frame_buffer_size));
-				tmp2=mymalloc(sizeof(time_t)*(1+frame_buffer_size));
-				tmp3=mymalloc(sizeof(int)*(1+frame_buffer_size));
-				memcpy(tmp, cnt->imgs.image_ring_buffer, cnt->imgs.size * (1+smallest));
-				memcpy(tmp2, cnt->imgs.timestamp, sizeof(time_t) * (1+smallest));
-				memcpy(tmp3, cnt->imgs.shotstamp, sizeof(int) * (1+smallest));
+		frame_buffer_size = cnt->conf.pre_capture + cnt->conf.minimum_motion_base;
+		if (cnt->imgs.ring_buffer_size != frame_buffer_size) {
+			/* Only resize if :
+			 * decreasing at last position in new buffer
+			 * increasing at last position in old buffer 
+			 * e.g. at end of smallest buffer */
+			int smallest;
+			if(frame_buffer_size < cnt->imgs.ring_buffer_size) { /* Decreasing */
+				smallest = frame_buffer_size;
+			}
+			else { /* Increasing */
+				smallest = cnt->imgs.ring_buffer_size;
+			};
+			if (cnt->imgs.ring_buffer_last_in == smallest) {
+				void *tmp;
+				void *tmp2;
+				void *tmp3;
+				void *tmp4;
+				tmp=mymalloc(cnt->imgs.size * frame_buffer_size);
+				tmp2=mymalloc(sizeof(cnt->imgs.timestamp_ring_buffer[0]) * frame_buffer_size);
+				tmp3=mymalloc(sizeof(cnt->imgs.shotstamp_ring_buffer[0]) * frame_buffer_size);
+				tmp4=mymalloc(sizeof(cnt->imgs.diffs_ring_buffer[0]) * frame_buffer_size);
+				memcpy(tmp, cnt->imgs.image_ring_buffer, cnt->imgs.size * smallest);
+				memcpy(tmp2, cnt->imgs.timestamp_ring_buffer, sizeof(cnt->imgs.timestamp_ring_buffer[0]) * smallest);
+				memcpy(tmp3, cnt->imgs.shotstamp_ring_buffer, sizeof(cnt->imgs.shotstamp_ring_buffer[0]) * smallest);
+				memcpy(tmp4, cnt->imgs.diffs_ring_buffer, sizeof(cnt->imgs.diffs_ring_buffer[0]) * smallest);
 				free(cnt->imgs.image_ring_buffer);
-				free(cnt->imgs.timestamp);
-				free(cnt->imgs.shotstamp);
+				free(cnt->imgs.timestamp_ring_buffer);
+				free(cnt->imgs.shotstamp_ring_buffer);
+				free(cnt->imgs.diffs_ring_buffer);
 				cnt->imgs.image_ring_buffer = tmp;
-				cnt->imgs.timestamp = tmp2;
-				cnt->imgs.shotstamp = tmp3;
-				cnt->precap_nr = frame_buffer_size;
+				cnt->imgs.timestamp_ring_buffer = tmp2;
+				cnt->imgs.shotstamp_ring_buffer = tmp3;
+				cnt->imgs.diffs_ring_buffer = tmp4;
+				cnt->imgs.ring_buffer_size = frame_buffer_size;
+				cnt->minimum_motion_base = cnt->conf.minimum_motion_base;
 			}
 		}
 
@@ -792,27 +839,29 @@
 				get_image = 0;
 			}
 
-			/* Store time with pre_captured image*/
-			*(cnt->imgs.timestamp + cnt->precap_cur) = cnt->currenttime;
+			/* ring_buffer_last_in is pointing to current pos, update before put in a new image */
+			if(++cnt->imgs.ring_buffer_last_in >= cnt->imgs.ring_buffer_size)
+				cnt->imgs.ring_buffer_last_in = 0;
 
-			/* Store shot number with pre_captured image*/
-			*(cnt->imgs.shotstamp+cnt->precap_cur) = cnt->shots;
+			/* Check if we have filled the ring buffer, throw away last image */
+			if(cnt->imgs.ring_buffer_last_in == cnt->imgs.ring_buffer_last_out) {
+				if(++cnt->imgs.ring_buffer_last_out >= cnt->imgs.ring_buffer_size)
+					cnt->imgs.ring_buffer_last_out = 0;
+			}
 
-			/* newimg now points to the current image. With precap_cur incremented it
-			 * will be pointing to the position in the buffer for the NEXT image frame
-			 * not the current!!! So newimg points to current frame about to be loaded
-			 * and the cnt->precap_cur already have been incremented to point to the
-			 * next frame.
-			 */
-			newimg = cnt->imgs.image_ring_buffer + (cnt->imgs.size * (cnt->precap_cur++));
+			/* Store time with pre_captured image */
+			cnt->imgs.timestamp_ring_buffer[cnt->imgs.ring_buffer_last_in] = cnt->currenttime;
 
-			/* If we are at the end of the ring buffer go to the start */
-			if (cnt->precap_cur > cnt->precap_nr)
-				cnt->precap_cur=0;
+			/* Store shot number with pre_captured image */
+			cnt->imgs.shotstamp_ring_buffer[cnt->imgs.ring_buffer_last_in] = cnt->shots;
 
+			/* set diffs to 0 now, will be written after we calculated diffs in new image */
+			cnt->imgs.diffs_ring_buffer[cnt->imgs.ring_buffer_last_in] = 0;
 
+			/* newimg points to position in ring where to store image */
+			newimg = cnt->imgs.image_ring_buffer + (cnt->imgs.size * cnt->imgs.ring_buffer_last_in);
+
 		/***** MOTION LOOP - RETRY INITIALIZING NETCAM SECTION *****/
-
 			/* If a network camera is not available we keep on retrying every 10 seconds
 			 * until it shows up.
 			 */
@@ -1038,6 +1087,8 @@
 				cnt->diffs = 0;
 			}
 
+			/* save diffs in ring buffer */
+			cnt->imgs.diffs_ring_buffer[cnt->imgs.ring_buffer_last_in] = cnt->diffs;
 
 		/***** MOTION LOOP - TUNING SECTION *****/
 
@@ -1073,6 +1124,12 @@
 			 * picture frame is captured.
 			 */
 
+			/* If motion is detected (cnt->diffs > cnt->threshold) and before we add text to the pictures
+			   we find the center and size coordinates of the motion to be used for text overlays and later
+			   for adding the locate rectangle */
+			if (cnt->diffs > cnt->threshold)
+				 alg_locate_center_size(&cnt->imgs, cnt->imgs.width, cnt->imgs.height, &cnt->location);
+
 			/* Fixed mask overlay */
 			if (cnt->imgs.mask && (cnt->conf.motion_img || cnt->conf.ffmpeg_cap_motion || cnt->conf.setup_mode) )
 				overlay_fixed_mask(cnt, cnt->imgs.out);
@@ -1085,12 +1142,6 @@
 			if (cnt->imgs.largest_label && (cnt->conf.motion_img || cnt->conf.ffmpeg_cap_motion || cnt->conf.setup_mode) )
 				overlay_largest_label(cnt, cnt->imgs.out);
 
-			/* If motion is detected (cnt->diffs > cnt->threshold) and before we add text to the pictures
-			   we find the center and size coordinates of the motion to be used for text overlays and later
-			   for adding the locate rectangle */
-			if (cnt->diffs > cnt->threshold)
-				 alg_locate_center_size(&cnt->imgs, cnt->imgs.width, cnt->imgs.height, &cnt->location);
-
 			/* Initialize the double sized characters if needed. */
 			if(cnt->conf.text_double && text_size_factor == 1)
 				text_size_factor = 2;
@@ -1158,19 +1209,37 @@
 				 * is set, and take action by calling motion_detected().
 				 * pre_capture is handled by motion_detected(), and we handle
 				 * post_capture here. */
-				if (!detecting_motion)
+
+				/* There will be at least one as we saved cnt->diffs in cnt->diffs_ring_buffer */
+				int frame_count = 0;
+				{
+					int i;
+					int pos = cnt->imgs.ring_buffer_last_in;
+					for(i = 0; i < cnt->minimum_motion_base; i++)
+					{
+						if(cnt->imgs.diffs_ring_buffer[pos] > cnt->threshold)
+							frame_count++;
+						if(--pos < 0)
+							pos = cnt->imgs.ring_buffer_size-1;
+					}
+				}
+				if (frame_count >= cnt->conf.minimum_motion_frames) {
+draw_text(newimg, cnt->imgs.width - 10, 10, cnt->imgs.width, "Trigger", cnt->conf.text_double);
 					detecting_motion = 1;
-
-				detecting_motion++;
-
-				if (detecting_motion > cnt->conf.minimum_motion_frames) {
 					motion_detected(cnt, cnt->diffs, cnt->video_dev, newimg);
-					postcap = cnt->conf.post_capture;
 				}
-			} else if (postcap) {
+				else if (cnt->postcap) { /* we have motion in this frame, but not enought frames for trigger. Check postcap */
+draw_text(newimg, cnt->imgs.width - 10, 10, cnt->imgs.width, "MPost", cnt->conf.text_double);
+					motion_detected(cnt, 0, cnt->video_dev, newimg);
+				}
+else
+draw_text(newimg, cnt->imgs.width - 10, 10, cnt->imgs.width, "MIdle", cnt->conf.text_double);
+
+			} else if (cnt->postcap) {
+draw_text(newimg, cnt->imgs.width - 10, 10, cnt->imgs.width, "Post", cnt->conf.text_double);
 				motion_detected(cnt, 0, cnt->video_dev, newimg);
-				postcap--;
 			} else {
+draw_text(newimg, cnt->imgs.width - 10, 10, cnt->imgs.width, "Pre", cnt->conf.text_double);
 				detecting_motion = 0;
 			}
 
@@ -1187,7 +1256,7 @@
 			if (((cnt->currenttime - cnt->lasttime >= cnt->conf.gap) && cnt->conf.gap > 0) || cnt->makemovie) {
 				if (cnt->event_nr == cnt->prev_event || cnt->makemovie) {
 
-					/* When output_normal=best save best preview_shot here at the end of event */
+					/* save preview_shot here at the end of event */
 					if (cnt->new_img == NEWIMG_BEST && cnt->preview_max) {
 						preview_best(cnt);
 						cnt->preview_max = 0;
@@ -1407,12 +1476,6 @@
 				cnt->new_img=NEWIMG_FIRST;
 			else if (strcasecmp(cnt->conf.output_normal, "best") == 0){
 				cnt->new_img=NEWIMG_BEST;
-				/* allocate buffer here when not yet done */
-				if (!cnt->imgs.preview_buffer){
-					cnt->imgs.preview_buffer = mymalloc(cnt->imgs.size);
-					if (cnt->conf.setup_mode)
-						motion_log(-1, 0, "Preview buffer allocated");
-				}
 			}
 			else
 				cnt->new_img = NEWIMG_OFF;
Index: motion.h
===================================================================
--- motion.h	(revision 203)
+++ motion.h	(working copy)
@@ -201,6 +201,12 @@
 
 struct images {
 	unsigned char *image_ring_buffer; /* The base address of the image ring buffer */
+	time_t *timestamp_ring_buffer;
+	int *shotstamp_ring_buffer;
+	int *diffs_ring_buffer;
+	int ring_buffer_size;
+	int ring_buffer_last_in;
+	int ring_buffer_last_out;
 	unsigned char *ref;               /* The reference frame */
 	unsigned char *out;               /* Picture buffer for motion images */
 	unsigned char *image_virgin;      /* Last picture frame with no text or locate overlay */
@@ -222,8 +228,6 @@
 	int labelgroup_max;
 	int labels_above;
 	int largest_label;
-	time_t *timestamp;
-	int *shotstamp;
 };
 
 /* Contains data for image rotation, see rotate.c. */
@@ -261,10 +265,7 @@
 	struct images imgs;
 	struct trackoptions track;
 	struct netcam_context *netcam;
-	int precap_nr;
-	int precap_cur;
 	int new_img;
-	int preview_shot;
 	int preview_max;            /* Stores max diff number seen in an event of output_normal==best */
 	int locate;
 	struct coord location;      /* coordinates for center and size of last motion detection*/
@@ -284,6 +285,8 @@
 	int prev_event;
 	char text_event_string[PATH_MAX]; /* The text for conv. spec. %C -
 	                                     we assume PATH_MAX normally 4096 characters is fine */
+	int postcap;		/* downcounter, frames left to to send post event */
+	int minimum_motion_base;	/* Copied from conf at a "safe" place */
 
 	int shots;
 	struct tm *currenttime_tm;
@@ -292,7 +295,6 @@
 	time_t currenttime;
 	time_t lasttime;
 	time_t eventtime;
-	time_t lastshottime;
 	time_t connectionlosttime;   /* timestamp from connection lost */
 
 	int lastrate;
Index: event.c
===================================================================
--- event.c	(revision 203)
+++ event.c	(working copy)
@@ -240,10 +240,34 @@
 	struct config *conf=&cnt->conf;
 	char fullfilename[PATH_MAX];
 	char filename[PATH_MAX];
+
+	if (cnt->new_img==NEWIMG_ON) {
+		const char *jpegpath;
+
+		/* conf.jpegpath would normally be defined but if someone deleted it by control interface
+		   it is better to revert to the default than fail */
+		if (cnt->conf.jpegpath)
+			jpegpath = cnt->conf.jpegpath;
+		else
+			jpegpath = DEF_JPEGPATH;
+			
+		mystrftime(cnt, filename, sizeof(filename), jpegpath, currenttime_tm, NULL, 0);
+		snprintf(fullfilename, PATH_MAX, "%s/%s.%s", cnt->conf.filepath, filename, imageext(cnt));
+
+		put_picture(cnt, fullfilename, newimg, FTYPE_IMAGE);
+	}
+}
+
+static void event_imagem_detect(struct context *cnt, int type ATTRIBUTE_UNUSED,
+            unsigned char *newimg_UNUSED, char *dummy1 ATTRIBUTE_UNUSED,
+            void *dummy2 ATTRIBUTE_UNUSED, struct tm *currenttime_tm)
+{
+	struct config *conf=&cnt->conf;
 	char fullfilenamem[PATH_MAX];
+	char filename[PATH_MAX];
 	char filenamem[PATH_MAX];
 
-	if (conf->motion_img || cnt->new_img==NEWIMG_ON || cnt->preview_shot) {
+	if (conf->motion_img) {
 		const char *jpegpath;
 
 		/* conf.jpegpath would normally be defined but if someone deleted it by control interface
@@ -256,15 +280,10 @@
 		mystrftime(cnt, filename, sizeof(filename), jpegpath, currenttime_tm, NULL, 0);
 		/* motion images gets same name as normal images plus an appended 'm' */
 		snprintf(filenamem, PATH_MAX, "%sm", filename);
-		snprintf(fullfilename, PATH_MAX, "%s/%s.%s", cnt->conf.filepath, filename, imageext(cnt));
 		snprintf(fullfilenamem, PATH_MAX, "%s/%s.%s", cnt->conf.filepath, filenamem, imageext(cnt));
-	}
-	if (conf->motion_img) {
+
 		put_picture(cnt, fullfilenamem, cnt->imgs.out, FTYPE_IMAGE_MOTION);
 	}
-	if (cnt->new_img==NEWIMG_ON || cnt->preview_shot) {
-		put_picture(cnt, fullfilename, newimg, FTYPE_IMAGE);
-	}
 }
 
 static void event_image_snapshot(struct context *cnt, int type ATTRIBUTE_UNUSED,
@@ -594,6 +613,10 @@
 	event_image_detect
 	},
 	{
+	EVENT_IMAGEM_DETECTED,
+	event_imagem_detect
+	},
+	{
 	EVENT_IMAGE_SNAPSHOT,
 	event_image_snapshot
 	},
Index: video2.c
===================================================================
--- video2.c	(revision 203)
+++ video2.c	(working copy)
@@ -136,6 +136,7 @@
 	u32 ctrl_flags;
 	struct v4l2_queryctrl *controls;
 
+	int log_details;
 } src_v4l2_t;
 
 static int xioctl(int fd, int request, void *arg)
@@ -212,12 +213,15 @@
 		return (-1);
 	}
 
-	motion_log(LOG_INFO, 0, "%s: name = \"%s\", type 0x%08X, status %08x", __FUNCTION__, input.name, input.type,
-		   input.status);
-	if (input.type & V4L2_INPUT_TYPE_TUNER)
-		motion_log(LOG_INFO, 0, "- TUNER");
-	if (input.type & V4L2_INPUT_TYPE_CAMERA)
-		motion_log(LOG_INFO, 0, "- CAMERA");
+	if(s->log_details)
+	{
+		motion_log(LOG_INFO, 0, "%s: name = \"%s\", type 0x%08X, status %08x", __FUNCTION__, input.name, 
+		   input.type, input.status);
+		if (input.type & V4L2_INPUT_TYPE_TUNER)
+			motion_log(LOG_INFO, 0, "- TUNER");
+		if (input.type & V4L2_INPUT_TYPE_CAMERA)
+			motion_log(LOG_INFO, 0, "- CAMERA");
+	}
 
 	if (xioctl(s->fd, VIDIOC_S_INPUT, &in) == -1) {
 		motion_log(LOG_ERR, 0, "Error selecting input %d", in);
@@ -235,11 +239,14 @@
 		memset(&standard, 0, sizeof(standard));
 		standard.index = 0;
 
-		while (xioctl(s->fd, VIDIOC_ENUMSTD, &standard) == 0) {
-			if (standard.id & std_id) {
-				motion_log(LOG_INFO, 0, "- video standard %s", standard.name);
+		if(s->log_details)
+		{
+			while (xioctl(s->fd, VIDIOC_ENUMSTD, &standard) == 0) {
+				if (standard.id & std_id) {
+					motion_log(LOG_INFO, 0, "- video standard %s", standard.name);
+				}
+				standard.index++;
 			}
-			standard.index++;
 		}
 
 		switch (norm) {
@@ -640,6 +647,8 @@
 	s->fps = cnt->conf.frame_limit;
 	s->pframe = -1;
 
+	s->log_details = 1;
+
 	if (v4l2_get_capability(s)) {
 		goto err;
 	}
@@ -676,6 +685,8 @@
 	viddev->width = width;
 	viddev->height = height;
 
+	s->log_details = 0;
+
 	return (void *) 1;
 
       err:
@@ -718,25 +729,30 @@
 		{
 			src_v4l2_t *s = (src_v4l2_t *) viddev->v4l2_private;
 			unsigned int counter = 0;
-			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))
+				{
+					/* error get a frame, also skip roundrobin_skip frames */
+					skip = 0;
 					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;
-				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);
+		{
+			/* If we get any errors break out skip frames */
+			if(v4l2_next(cnt, viddev, map, width, height) != 0)
+				break;
+		}
 	} else {
 		/* No round robin - we only adjust picture controls */
 		v4l2_picture_controls(cnt, viddev);
@@ -780,12 +796,13 @@
 		   returning an error, or even stop capturing.
 		*/
 		if ( errno == EIO ){
+			/* This is a fix for SAA7134 drivers, it returns a buffer but dosn't update the index */
 			s->pframe++; 
 			if(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);
-	
+
+			motion_log(LOG_ERR, 0, "%s: VIDIOC_DQBUF: EIO (s->pframe %d)", __FUNCTION__,s->pframe);		
+			
 			return (1);
 		}
 
