Index: conf.c =================================================================== --- conf.c (revision 213) +++ conf.c (working copy) @@ -134,6 +134,7 @@ text_double: 0, despeckle: NULL, minimum_motion_frames: 1, + referense_image_age: 1, pid_file: NULL, // debug_parameter: 0 }; @@ -438,6 +439,15 @@ print_int }, { + "referense_image_age", + "# When picking referense image, how old should it be in frames.\n" + "# Valid range: 1 to hundreds\n" + "# Default is 1, previous frame\n", + CONF_OFFSET(referense_image_age), + copy_int, + print_int + }, + { "minimum_motion_frames", "# Picture frames must contain motion at least the specified number of frames\n" "# in a row before they are detected as true motion. At the default of 1, all\n" Index: conf.h =================================================================== --- conf.h (revision 213) +++ conf.h (working copy) @@ -117,6 +117,10 @@ const char *text_event; int text_double; const char *despeckle; + + /* Frame cont before a frame becomes the referense image */ + int referense_image_age; + int minimum_motion_frames; char *pid_file; // int debug_parameter; Index: motion.c =================================================================== --- motion.c (revision 213) +++ motion.c (working copy) @@ -523,7 +523,9 @@ memset(cnt->imgs.image_ring_buffer, 0x80, cnt->imgs.size); /* initialize to grey */ cnt->imgs.ref = mymalloc(cnt->imgs.size); cnt->imgs.out = mymalloc(cnt->imgs.size); - cnt->imgs.image_virgin = mymalloc(cnt->imgs.size); + cnt->imgs.image_virgin_ring_buffer = mymalloc(cnt->imgs.size); /* Allocate buffer for 1 frame */ + cnt->imgs.image_virgin_ring_size = 1; + cnt->imgs.image_virgin = cnt->imgs.image_virgin_ring_buffer; memset(cnt->imgs.image_virgin, 0x80, cnt->imgs.size); /* initialize to grey */ cnt->imgs.smartmask = mymalloc(cnt->imgs.motionsize); cnt->imgs.smartmask_final = mymalloc(cnt->imgs.motionsize); @@ -833,6 +835,34 @@ } } + /* Check if our virgin buffer is still the right size + */ + { + int new_virgin_size = cnt->conf.referense_image_age; + + if (cnt->imgs.image_virgin_ring_size != new_virgin_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 (new_virgin_size < cnt->conf.referense_image_age) { /* Decreasing */ + smallest = new_virgin_size; + } else { /* Increasing */ + smallest = cnt->imgs.image_virgin_ring_size; + } + if (cnt->imgs.image_virgin_ring_last_in == smallest - 1) { + void *tmp; + tmp = mymalloc(cnt->imgs.size * new_virgin_size); + /* Copy old content into new buffer */ + memcpy(tmp, cnt->imgs.image_virgin_ring_buffer, cnt->imgs.size * smallest); + free(cnt->imgs.image_virgin_ring_buffer); + cnt->imgs.image_virgin_ring_buffer = tmp; + cnt->imgs.image_virgin_ring_size = new_virgin_size; + } + } + } + /* Get time for current frame */ cnt->currenttime = time(NULL); @@ -891,6 +921,21 @@ /* 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); + /* Update pos in virgin ring buffer */ + if (++cnt->imgs.image_virgin_ring_last_in >= cnt->imgs.image_virgin_ring_size) { + cnt->imgs.image_virgin_ring_last_in = 0; + } + + /* Update end (oldest) pos */ + if (cnt->imgs.image_virgin_ring_last_in == cnt->imgs.image_virgin_ring_referense_image_out) { + cnt->imgs.image_virgin_ring_referense_image_out = cnt->imgs.image_virgin_ring_last_in + 1; + if(cnt->imgs.image_virgin_ring_referense_image_out >= cnt->imgs.image_virgin_ring_size) + cnt->imgs.image_virgin_ring_referense_image_out = 0; + } + + /* image_virgin points to position in ring where to store image */ + cnt->imgs.image_virgin = cnt->imgs.image_virgin_ring_buffer + (cnt->imgs.size * cnt->imgs.image_virgin_ring_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. @@ -1307,16 +1352,26 @@ * more accurate. */ memcpy(cnt->imgs.ref, cnt->imgs.image_virgin, cnt->imgs.size); + cnt->imgs.image_virgin_ring_referense_image_out = cnt->imgs.image_virgin_ring_last_in; } else if (cnt->threshold) { - /* Old image slowly decays, this will make it even harder on - * a slow moving object to stay undetected - */ - unsigned char *imgs_ref_ptr = cnt->imgs.ref; - unsigned char *newimg_ptr = cnt->imgs.image_virgin; - for (i=cnt->imgs.size-1; i>=0; i--) { - *imgs_ref_ptr = (*imgs_ref_ptr + *newimg_ptr)/2; - imgs_ref_ptr++; - newimg_ptr++; + if (cnt->imgs.image_virgin_ring_size <= 1 || detecting_motion) { + /* Old image slowly decays, this will make it even harder on + * a slow moving object to stay undetected + */ + unsigned char *imgs_ref_ptr = cnt->imgs.ref; + unsigned char *newimg_ptr = cnt->imgs.image_virgin; + for (i=cnt->imgs.size-1; i>=0; i--) { + *imgs_ref_ptr = (*imgs_ref_ptr + *newimg_ptr)/2; + imgs_ref_ptr++; + newimg_ptr++; + } + cnt->imgs.image_virgin_ring_referense_image_out = cnt->imgs.image_virgin_ring_last_in; + } else { + /* Take older image as ref. image + */ + memcpy(cnt->imgs.ref, + cnt->imgs.image_virgin_ring_buffer + (cnt->imgs.size * cnt->imgs.image_virgin_ring_referense_image_out), + cnt->imgs.size); } } Index: motion.h =================================================================== --- motion.h (revision 213) +++ motion.h (working copy) @@ -209,6 +209,12 @@ int ring_buffer_size; int ring_buffer_last_in; int ring_buffer_last_out; + + unsigned char *image_virgin_ring_buffer; /* Ring buffer of image_virgin images, used to delay reference image */ + int image_virgin_ring_size; /* Size of the ring buffer */ + int image_virgin_ring_last_in; /* Last inserted */ + int image_virgin_ring_referense_image_out; /* Oldest image */ + 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 */