Index: alg.c
===================================================================
--- alg.c	(revision 439)
+++ alg.c	(working copy)
@@ -1242,7 +1242,7 @@
  *
  */
 /* Seconds */
-#define ACCEPT_STATIC_OBJECT_TIME 10
+#define ACCEPT_STATIC_OBJECT_TIME 0
 #define EXCLUDE_LEVEL_PERCENT 20
 void alg_update_reference_frame(struct context *cnt, int action) 
 {
Index: conf.c
===================================================================
--- conf.c	(revision 439)
+++ conf.c	(working copy)
@@ -82,6 +82,7 @@
     ffmpeg_output:                  0,
     extpipe:                        NULL,
     useextpipe:                     0,
+    smooth_video:                   0,
     ffmpeg_output_debug:            0,
     ffmpeg_bps:                     DEF_FFMPEG_BPS,
     ffmpeg_vbr:                     DEF_FFMPEG_VBR,
@@ -104,7 +105,7 @@
     tuner_device:                   NULL,
 #endif
     video_device:                   VIDEO_DEVICE,
-    v4l2_palette:                   11,        
+    v4l2_palette:                   DEF_PALETTE,
     vidpipe:                        NULL,
     filepath:                       NULL,
     imagepath:                      DEF_IMAGEPATH,
@@ -147,6 +148,7 @@
     text_left:                      NULL,
     text_right:                     DEF_TIMESTAMP,
     text_event:                     DEF_EVENTSTAMP,
+    cameraname:                     "CAMERA NAME",
     text_double:                    0,
     despeckle_filter:               NULL,
     area_detect:                    NULL,
@@ -317,6 +319,17 @@
     print_int
     },
     {
+    "force_framerate",
+    "# Force the number of frames per second set in framerate.\n"
+    "# This is useful for capture cards on busy system where motion\n"
+    "# often failed to detect the correct framerate.\n"
+    "# Valid range: 2-100. Default: 100 (almost no limit).",
+    0,
+    CONF_OFFSET(force_framerate),
+    copy_bool,
+    print_bool
+    },
+    {
     "minimum_frame_time",
     "# Minimum time in seconds between capturing picture frames from the camera.\n"
     "# Default: 0 = disabled - the capture rate is given by the camera framerate.\n"
@@ -750,6 +763,19 @@
     print_string
     },
     {
+    "smooth_video",
+    "\n############################################################\n"
+    "# Normally, video is recorded as __precap+motion+postcap____\n"
+    "# This option changes the default behavior of the video \n"
+    "# capturing so that it is __precap+event-start-->event-end__ \n"
+    "############################################################\n"
+    "# Use smooth_video on to enable this feature. \n",
+    0,
+    CONF_OFFSET(smooth_video),
+    copy_bool,
+    print_bool
+    },
+    {
     "snapshot_interval",
     "\n############################################################\n"
     "# Snapshots (Traditional Periodic Webcam File Output)\n"
@@ -826,6 +852,16 @@
     print_bool
     },
     {
+    "cameraname",
+     "# This option defines the value of the special event conversion specifier %e\n"
+     "# Default: Camera 1\n"
+     "# The idea is that %e can be used as part of the filename to identify a camera\n",
+    0,
+    CONF_OFFSET(cameraname),
+    copy_string,
+    print_string
+    },
+    {
     "text_event",
     "# This option defines the value of the special event conversion specifier %C\n"
     "# You can use any conversion specifier in this option except %C. Date and time\n"
Index: conf.h
===================================================================
--- conf.h	(revision 439)
+++ conf.h	(working copy)
@@ -37,7 +37,9 @@
     int input;
     int norm;
     int frame_limit;
+    int force_framerate;
     int quiet;
+    int smooth_video;
     int useextpipe; /* ext_pipe on or off */
     const char *extpipe; /* full command line for pipe -- must accept YUV420P images  */
     const char *picture_type;
@@ -118,6 +120,7 @@
     const char *text_left;
     const char *text_right;
     const char *text_event;
+    const char *cameraname;
     int text_double;
     const char *despeckle_filter;
     const char *area_detect;
Index: configure
===================================================================
--- configure	(revision 439)
+++ configure	(working copy)
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for motion trunk-r438.
+# Generated by GNU Autoconf 2.61 for motion trunk-r439.
 #
 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
 # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
@@ -572,8 +572,8 @@
 # Identity of this package.
 PACKAGE_NAME='motion'
 PACKAGE_TARNAME='motion'
-PACKAGE_VERSION='trunk-r438'
-PACKAGE_STRING='motion trunk-r438'
+PACKAGE_VERSION='trunk-r439'
+PACKAGE_STRING='motion trunk-r439'
 PACKAGE_BUGREPORT=''
 
 ac_unique_file="motion.c"
@@ -1177,7 +1177,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures motion trunk-r438 to adapt to many kinds of systems.
+\`configure' configures motion trunk-r439 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1238,7 +1238,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of motion trunk-r438:";;
+     short | recursive ) echo "Configuration of motion trunk-r439:";;
    esac
   cat <<\_ACEOF
 
@@ -1376,7 +1376,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-motion configure trunk-r438
+motion configure trunk-r439
 generated by GNU Autoconf 2.61
 
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1390,7 +1390,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by motion $as_me trunk-r438, which was
+It was created by motion $as_me trunk-r439, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
   $ $0 $@
@@ -8230,7 +8230,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by motion $as_me trunk-r438, which was
+This file was extended by motion $as_me trunk-r439, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -8279,7 +8279,7 @@
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-motion config.status trunk-r438
+motion config.status trunk-r439
 configured by $0, generated by GNU Autoconf 2.61,
   with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
Index: event.c
===================================================================
--- event.c	(revision 439)
+++ event.c	(working copy)
@@ -368,8 +368,10 @@
     if (cnt->extpipe_open) {
         cnt->extpipe_open = 0;
         fflush(cnt->extpipe);
-        motion_log(LOG_INFO, 0, "%s: CLOSING: extpipe file desc %d, error state %d", 
+        if (debug_level >= CAMERA_INFO) {
+            motion_log(LOG_INFO, 0, "%s: CLOSING: extpipe file desc %d, error state %d", 
                    __FUNCTION__, fileno(cnt->extpipe), ferror(cnt->extpipe));
+        }
         motion_log(LOG_INFO, 0, "%s: pclose return: %d", __FUNCTION__, pclose(cnt->extpipe));
         event(cnt, EVENT_FILECLOSE, NULL, cnt->extpipefilename, (void *)FTYPE_MPEG, NULL);
     }
@@ -451,8 +453,10 @@
                 motion_log(LOG_ERR, 1, "%s: Error writting in pipe , state error %d",
                            __FUNCTION__, ferror(cnt->extpipe));
         } else {    
+          if (debug_level >= CAMERA_DEBUG) {
             motion_log(LOG_ERR, 0, "%s: pipe %s not created or closed already ", 
-                       __FUNCTION__, cnt->extpipe);
+                       __FUNCTION__, cnt->extpipe); 
+          }
         }    
     }        
 }
@@ -469,10 +473,14 @@
     if (debug_level >= CAMERA_INFO) 
         motion_log(LOG_DEBUG, 0, "%s FPS %d", __FUNCTION__, cnt->movie_fps);
 
-    if (cnt->movie_fps > 30) 
+    if (cnt->conf.force_framerate)
+        cnt->movie_fps = cnt->conf.frame_limit;
+    else if (cnt->movie_fps > 30)
         cnt->movie_fps = 30;
     else if (cnt->movie_fps < 2) 
         cnt->movie_fps = 2;
+
+    cnt->usinterval = 1000000 / cnt->movie_fps;  /* less calculations are good... */
 }
 
 #ifdef HAVE_FFMPEG
@@ -768,10 +776,14 @@
     EVENT_IMAGE_SNAPSHOT,
     event_image_snapshot
     },
+    {
+    EVENT_IMAGEM,
+    event_vid_putpipe     
+    },
 #ifndef WITHOUT_V4L
 #if (!defined(BSD))
     {
-    EVENT_IMAGE | EVENT_IMAGEM,
+    EVENT_IMAGE,
     event_vid_putpipe
     },
 #endif /* BSD */
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 439)
+++ Makefile.in	(working copy)
@@ -34,8 +34,8 @@
 LDFLAGS      = @LDFLAGS@
 LIBS         = @LIBS@ 
 VIDEO_OBJ    = @VIDEO@
-OBJ          = motion.o logger.o conf.o draw.o jpegutils.o $(VIDEO_OBJ) netcam.o \
-			   netcam_ftp.o netcam_jpeg.o netcam_wget.o track.o \
+OBJ          = motion.o logger.o conf.o draw.o jpegutils.o vloopback_motion.o $(VIDEO_OBJ) \
+			   netcam.o netcam_ftp.o netcam_jpeg.o netcam_wget.o track.o \
 			   alg.o event.o picture.o rotate.o webhttpd.o \
 			   stream.o @FFMPEG_OBJ@
 SRC          = $(OBJ:.o=.c)
@@ -128,6 +128,18 @@
 dep depend fastdep: $(DEPEND_FILE)
 
 ################################################################################
+# CURRENT, BUILD current svn trunk.                                            #
+################################################################################
+current: distclean svn autotools all
+
+svn:
+	svn update
+
+autotools:
+	autoconf
+	./configure --with-developer-flags 
+
+################################################################################
 # INSTALL installs all relevant files.                                         #
 ################################################################################
 install:
Index: motion.c
===================================================================
--- motion.c	(revision 439)
+++ motion.c	(working copy)
@@ -531,49 +531,48 @@
                           cnt->imgs.width, t, cnt->conf.text_double);
             }
 
-            /* Output the picture to jpegs and ffmpeg */
-            event(cnt, EVENT_IMAGE_DETECTED,
-                  cnt->imgs.image_ring[cnt->imgs.image_ring_out].image, NULL, NULL, 
-                  &cnt->imgs.image_ring[cnt->imgs.image_ring_out].timestamp_tm);
+//smoothvideo: payne 10/15/2008
+//located in two places
+            /* process this only if we're outputting to a movie */
+            if (cnt->conf.smooth_video && (cnt->ffmpeg_output || cnt->conf.useextpipe)) {
+                if (cnt->prevtv.tv_sec > 0) {
+                    time_t elapsedus = ((cnt->imgs.image_ring[cnt->imgs.image_ring_out].tv.tv_sec - cnt->prevtv.tv_sec) * 1000000) +
+                                        (cnt->imgs.image_ring[cnt->imgs.image_ring_out].tv.tv_usec - cnt->prevtv.tv_usec);
+                    int myinsertnum = ((elapsedus + cnt->leftovers) / cnt->usinterval);
+                    /* the larger loop we're in is only called to process
+                     * motion -- there will be one frame processed later
+                     * REGARDLESS of what we do here, so, account for it */
+                    cnt->leftovers += elapsedus - (cnt->usinterval*(myinsertnum+1));
 
-//#ifdef HAVE_FFMPEG
-            /* Check if we must add any "filler" frames into movie to keep up fps */
-            if (cnt->imgs.image_ring[cnt->imgs.image_ring_out].shot == 0) {
-                /* movie_last_shoot is -1 when file is created,
-                 * we don't know how many frames there is in first sec */
-                if (cnt->movie_last_shot >= 0) {
-                    if (debug_level >= CAMERA_DEBUG) {
-                        int frames = cnt->movie_fps - (cnt->movie_last_shot + 1);
-                        if (frames > 0) {
-                            char tmp[15];
-                            motion_log(LOG_DEBUG, 0, "%s: Added %d fillerframes into movie", 
-                                       __FUNCTION__, frames);
-                            sprintf(tmp, "Fillerframes %d", frames);
-                            draw_text(cnt->imgs.image_ring[cnt->imgs.image_ring_out].image, 10, 40, 
-                                      cnt->imgs.width, tmp, cnt->conf.text_double);
+                    if (debug_level >= 2)
+                        motion_log(LOG_INFO, 0, "current, prev, fps, us, interval, insertnum, leftovers: "
+                                   "%d.%06ld, %d.%06ld, %d, %d, %d, %d, %d",
+                                   cnt->imgs.image_ring[cnt->imgs.image_ring_out].tv.tv_sec,
+                                   cnt->imgs.image_ring[cnt->imgs.image_ring_out].tv.tv_usec,
+                                   cnt->prevtv.tv_sec, cnt->prevtv.tv_usec, cnt->movie_fps, elapsedus,
+                                   cnt->usinterval, myinsertnum, cnt->leftovers);
+
+
+                    while (myinsertnum > 0) {
+                        event(cnt, EVENT_FFMPEG_PUT, cnt->previmg, NULL, NULL,
+                              &cnt->imgs.image_ring[cnt->imgs.image_ring_out].timestamp_tm);
+                        myinsertnum--;
+                    }
                         }
+                cnt->prevtv = cnt->imgs.image_ring[cnt->imgs.image_ring_out].tv;
+                memcpy(cnt->previmg, cnt->imgs.image_ring[cnt->imgs.image_ring_out].image, cnt->imgs.size);
                     }
-                    /* Check how many frames it was last sec */
-                    while ((cnt->movie_last_shot + 1) < cnt->movie_fps) {
-                        /* Add a filler frame into encoder */
+            /* Output the picture to jpegs (if motion), ffmpeg and extpipe (regardless)*/
+            if (cnt->imgs.image_ring[cnt->imgs.image_ring_out].flags & IMAGE_MOTION && 
+                ! cnt->imgs.image_ring[cnt->imgs.image_ring_out].flags & IMAGE_PRECAP) {
+                event(cnt, EVENT_IMAGE_DETECTED,
+                      cnt->imgs.image_ring[cnt->imgs.image_ring_out].image, NULL, NULL, 
+                      &cnt->imgs.image_ring[cnt->imgs.image_ring_out].timestamp_tm);
+            } else {
                         event(cnt, EVENT_FFMPEG_PUT,
                               cnt->imgs.image_ring[cnt->imgs.image_ring_out].image, NULL, NULL, 
                               &cnt->imgs.image_ring[cnt->imgs.image_ring_out].timestamp_tm);
-
-                        cnt->movie_last_shot++;
-                    }
                 }
-                cnt->movie_last_shot = 0;
-            } else if (cnt->imgs.image_ring[cnt->imgs.image_ring_out].shot != (cnt->movie_last_shot + 1)) {
-                /* We are out of sync! Properbly we got motion - no motion - motion */
-                cnt->movie_last_shot = -1;
-            }
-
-            /* Save last shot added to movie
-             * only when we not are within first sec */
-            if (cnt->movie_last_shot >= 0)
-                cnt->movie_last_shot = cnt->imgs.image_ring[cnt->imgs.image_ring_out].shot;
-//#endif            
         }
 
         /* Mark the image as saved */
@@ -674,6 +673,10 @@
         cnt->imgs.type = VIDEO_PALETTE_YUV420P;
     }
 
+    /* setup cnt->previmg (previous img for ffmpeg streaming) */
+    cnt->previmg = mymalloc(cnt->imgs.size);
+    memset(cnt->previmg, 0x80, cnt->imgs.size);  /* initialize to grey */
+
     image_ring_resize(cnt, 1); /* Create a initial precapture ring buffer with 1 frame */
 
     cnt->imgs.ref = mymalloc(cnt->imgs.size);
@@ -746,7 +749,7 @@
         cnt->pipe = vid_startpipe(cnt->conf.vidpipe, cnt->imgs.width, cnt->imgs.height, cnt->imgs.type);
 
         if (cnt->pipe < 0) {
-            motion_log(LOG_ERR, 0, "%s: Failed to open video loopback", __FUNCTION__);
+            motion_log(LOG_ERR, 0, "%s: Failed to open video loopback for normal pictures", __FUNCTION__);
             return -1;
         }
     }
@@ -761,7 +764,7 @@
         cnt->mpipe = vid_startpipe(cnt->conf.motionvidpipe, cnt->imgs.width, cnt->imgs.height, cnt->imgs.type);
 
         if (cnt->mpipe < 0) {
-            motion_log(LOG_ERR, 0, "%s: Failed to open video loopback", __FUNCTION__);
+            motion_log(LOG_ERR, 0, "%s: Failed to open video loopback for motion pictures", __FUNCTION__);
             return -1;
         }
     }
@@ -1013,6 +1016,12 @@
     if (cnt->conf.sqlite3_db)
         sqlite3_close(cnt->database_sqlite3);
 #endif /* HAVE_SQLITE3 */
+
+     /* Cleanup the previmg buffer */
+     if (cnt->previmg) {
+         free(cnt->previmg);
+         cnt->previmg = NULL;
+     }
 }
 
 /**
@@ -1149,8 +1158,10 @@
             image_ring_resize(cnt, frame_buffer_size);
         
         /* Get time for current frame */
-        cnt->currenttime = time(NULL);
+        gettimeofday(&cnt->tv, NULL);
+        cnt->currenttime = cnt->tv.tv_sec;
 
+
         /* localtime returns static data and is not threadsafe
          * so we use localtime_r which is reentrant and threadsafe
          */
@@ -1227,6 +1238,8 @@
 
             /* Store time with pre_captured image */
             cnt->current_image->timestamp = cnt->currenttime;
+            cnt->current_image->tv = cnt->tv;
+
             localtime_r(&cnt->current_image->timestamp, &cnt->current_image->timestamp_tm);
 
             /* Store shot number with pre_captured image */
@@ -1426,7 +1439,7 @@
                     /* Lightswitch feature - has light intensity changed?
                      * This can happen due to change of light conditions or due to a sudden change of the camera
                      * sensitivity. If alg_lightswitch detects lightswitch we suspend motion detection the next
-                     * 5 frames to allow the camera to settle.
+                     * 15 frames to allow the camera to settle.
                      * Don't check if we have lost connection, we detect "Lost signal" frame as lightswitch
                      */
                     if (cnt->conf.lightswitch && !cnt->lost_connection) {
@@ -1434,8 +1447,8 @@
                             if (debug_level >= CAMERA_DEBUG)
                                 motion_log(-1, 0, "%s: Lightswitch detected", __FUNCTION__);
 
-                            if (cnt->moved < 5)
-                                cnt->moved = 5;
+                            if (cnt->moved < 15)
+                                cnt->moved = 15;
 
                             cnt->current_image->diffs = 0;
                             alg_update_reference_frame(cnt, RESET_REF_FRAME);
@@ -1656,6 +1669,7 @@
              * If post_capture is enabled we also take care of this in the this
              * code section.
              */
+		
             if (cnt->conf.emulate_motion && (cnt->startup_frames == 0)) {
                 cnt->detecting_motion = 1;
                 /* Setup the postcap counter */
@@ -1715,9 +1729,8 @@
             }
 
             /* Update last frame saved time, so we can end event after gap time */
-            if (cnt->current_image->flags & IMAGE_SAVE) 
+            if (cnt->current_image->flags & IMAGE_SAVE)
                 cnt->lasttime = cnt->current_image->timestamp;
-            
 
             /* Simple hack to recognize motion in a specific area */
             /* Do we need a new coversion specifier as well?? */
@@ -1779,8 +1792,6 @@
                                    __FUNCTION__, cnt->event_nr);
 
                     cnt->makemovie = 0;
-                    /* Reset post capture */
-                    cnt->postcap = 0;
 
                     /* Finally we increase the event number */
                     cnt->event_nr++;
@@ -1790,12 +1801,59 @@
                      * images get a timestamp from previous event.
                      */
                     cnt->text_event_string[0] = '\0';
+
+                    /* And, finally again, we reset the prevtv structure. */
+                    cnt->prevtv.tv_sec = 0;
+                    cnt->prevtv.tv_usec = 0;
+
+                    /* Make sure postcap is fulfilled */
+                    if (cnt->postcap && !cnt->finish) {
+                        cnt->detecting_motion = 1;
+                        cnt->current_image->flags |= (IMAGE_TRIGGER | IMAGE_SAVE);
+                        motion_detected(cnt, cnt->video_dev, cnt->current_image);
+                    } else {
+                        /* Reset post capture */
+                        cnt->postcap = 0;
+                    }
                 }
             }
 
             /* Save/send to movie some images */
             process_image_ring(cnt, 2);
 
+            /* For movie realtime sync.  code needed here so we don't run into issues
+            with high numbers of queued images, which would slow down processing */
+            if (cnt->conf.smooth_video && (cnt->ffmpeg_output || (cnt->conf.useextpipe))) {
+                /* process this if we're outputting to a movie only.. */
+                if (cnt->prevtv.tv_sec > 0) { /* only run through this block of code if we're in an event --
+                                               minimal processing is KEY =) */
+                    time_t elapsedus = ((cnt->imgs.image_ring[cnt->imgs.image_ring_out].tv.tv_sec - cnt->prevtv.tv_sec) * 1000000) +
+                                        (cnt->imgs.image_ring[cnt->imgs.image_ring_out].tv.tv_usec - cnt->prevtv.tv_usec);
+                    int myinsertnum = ((elapsedus + cnt->leftovers) / cnt->usinterval);
+
+                    if (myinsertnum > 0) {
+                        cnt->leftovers += elapsedus - (cnt->usinterval*(myinsertnum));
+
+                        if (debug_level >= 2)
+                            motion_log(LOG_INFO, 0, "KEEPUP: current, prev, fps, us, interval, insertnum, leftovers: "
+                                       "%d.%06ld, %d.%06ld, %d, %d, %d, %d, %d",
+                                       cnt->imgs.image_ring[cnt->imgs.image_ring_out].tv.tv_sec,
+                                       cnt->imgs.image_ring[cnt->imgs.image_ring_out].tv.tv_usec,
+                                       cnt->prevtv.tv_sec, cnt->prevtv.tv_usec, cnt->movie_fps, elapsedus,
+                                       cnt->usinterval, myinsertnum, cnt->leftovers);
+
+                        while (myinsertnum > 0) {
+                            event(cnt, EVENT_FFMPEG_PUT, cnt->previmg, NULL, NULL,
+                                  &cnt->imgs.image_ring[cnt->imgs.image_ring_out].timestamp_tm);
+                            myinsertnum--;
+                        }
+
+                        cnt->prevtv = cnt->imgs.image_ring[cnt->imgs.image_ring_out].tv;
+                        memcpy(cnt->previmg, cnt->imgs.image_ring[cnt->imgs.image_ring_out].image, cnt->imgs.size);
+                    }
+                }
+            }
+
         /***** MOTION LOOP - SETUP MODE CONSOLE OUTPUT SECTION *****/
 
             /* If CAMERA_VERBOSE enabled output some numbers to console */
@@ -2861,6 +2919,13 @@
                         pthread_getspecific(tls_key_threadnr));
                 break;
 
+            case 'e': // cameraname
+                if (cnt->conf.cameraname && cnt->conf.cameraname[0])
+                    snprintf(tempstr, PATH_MAX, "%s", cnt->conf.cameraname);
+                else
+                    ++pos_userformat;
+                break;
+
             case 'C': // text_event
                 if (cnt->text_event_string && cnt->text_event_string[0])
                     snprintf(tempstr, PATH_MAX, "%s", cnt->text_event_string);
@@ -2888,6 +2953,18 @@
                     ++pos_userformat;
                 break;
 
+            case 'u': // tv_usec -- really "us" for micro time, returns microsecond part
+                switch(*++pos_userformat) {
+                case 's': // %us, just return microseconds (6 digits padded)
+                    sprintf(tempstr, "%06ld",cnt->current_image->tv.tv_usec);
+                    break;
+                }
+                if (tempstr[0])  //if %ut or %us
+                    break;
+                else
+                    --pos_userformat;
+
+
             default: // Any other code is copied with the %-sign
                 *format++ = '%';
                 *format++ = *pos_userformat;
Index: motion-dist.conf.in
===================================================================
--- motion-dist.conf.in	(revision 439)
+++ motion-dist.conf.in	(working copy)
@@ -300,7 +300,7 @@
 #############################################################
 
 # Bool to enable or disable extpipe (default: off)
-use_extpipe off
+useextpipe off
 
 # External program (full path and opts) to pipe raw video to
 # Generally, use '-' for STDIN...
@@ -365,6 +365,13 @@
 # a unique identifier for each event.
 text_event %Y%m%d%H%M%S
 
+# This option defines the value of the special event conversion specifier %e
+# You can use any conversion specifier in this option except %e.
+# Default: Camera %t
+# The idea is that %e can be used filenames and text_left/right for creating
+# a unique identifier for each camera.
+cameraname Camera %t
+
 # Draw characters at twice normal size on images. (default: off)
 text_double off
 
Index: motion.h
===================================================================
--- motion.h	(revision 439)
+++ motion.h	(working copy)
@@ -105,6 +105,8 @@
 #define VIDEO_PALETTE_COMPONENT 7       /* start of component entries */
 #endif
 
+#define DEF_PALETTE             11
+
 /* Default picture settings */
 #define DEF_WIDTH              352
 #define DEF_HEIGHT             288
@@ -212,6 +214,7 @@
 struct image_data {
     unsigned char *image;
     int diffs;
+    struct timeval tv;
     time_t timestamp;           /* Timestamp when image was captured */
     struct tm timestamp_tm;
     int shot;                   /* Sub second timestamp count */
@@ -316,6 +319,7 @@
 
     struct config conf;
     struct images imgs;
+    unsigned char *previmg;
     struct trackoptions track;
     struct netcam_context *netcam;
     struct image_data *current_image;        /* Pointer to a structure where the image, diffs etc is stored */
@@ -355,6 +359,10 @@
     struct tm *eventtime_tm;
 
     time_t currenttime;
+    struct timeval tv;                      /* store current time of image */
+    struct timeval prevtv;                  /* previous pic tv.. needs to stick around */
+    struct timeval prevmotiontv;            /* previous pic detection tv.. needs to stick around */
+    time_t leftovers;                       /* leftover microseconds */
     time_t lasttime;
     time_t eventtime;
     time_t connectionlosttime;               /* timestamp from connection lost */
@@ -393,6 +401,7 @@
 #endif
 
     short int movie_fps;
+    time_t usinterval;                 /* microsecond interval, 1000000 / movie_fps */
     char newfilename[PATH_MAX];
     char extpipefilename[PATH_MAX];
     short int movie_last_shot;
Index: video2.c
===================================================================
--- video2.c	(revision 439)
+++ video2.c	(working copy)
@@ -62,7 +62,6 @@
 #ifdef MOTION_V4L2
 
 #include "motion.h"
-#include "netcam.h"
 #include "video.h"
 
 #ifdef MOTION_V4L2_OLD
@@ -139,7 +138,7 @@
     struct v4l2_requestbuffers req;
     struct v4l2_buffer buf;
 
-    netcam_buff *buffers;
+    video_buff *buffers;
 
     s32 pframe;
 
@@ -273,7 +272,7 @@
 
         if (xioctl(vid_source->fd, VIDIOC_S_STD, &std_id) == -1) 
             motion_log(LOG_ERR, 1, "%s: Error selecting standard method %d VIDIOC_S_STD", 
-                       __FUNCTION__, std_id);
+                       __FUNCTION__, (int)std_id);
         
     }
 
@@ -375,7 +374,7 @@
         vid_source->fmt.fmt.pix.field = V4L2_FIELD_ANY;
 
         if (xioctl(vid_source->fd, VIDIOC_TRY_FMT, &vid_source->fmt) != -1 && vid_source->fmt.fmt.pix.pixelformat == pixformat) {
-            motion_log(LOG_INFO, 0, "%s: index_format %d Test palette %c%c%c%c (%dx%d)", 
+            motion_log(LOG_INFO, 0, "%s: index_format %d Testing palette %c%c%c%c (%dx%d)", 
                        __FUNCTION__, index_format, pixformat >> 0, pixformat >> 8, 
                        pixformat >> 16, pixformat >> 24, *width, *height);
 
@@ -465,7 +464,7 @@
 
     if (xioctl(vid_source->fd, VIDIOC_REQBUFS, &vid_source->req) == -1) {
         motion_log(LOG_ERR, 1, "%s: Error requesting buffers %d for memory map. VIDIOC_REQBUFS",
-                   vid_source->req.count ,__FUNCTION__);
+                   __FUNCTION__, vid_source->req.count);
         return -1;
     }
 
@@ -473,11 +472,11 @@
 
     if (vid_source->req.count < MIN_MMAP_BUFFERS) {
         motion_log(LOG_ERR, 1, "%s: Insufficient buffer memory %d < MIN_MMAP_BUFFERS.",
-                   vid_source->req.count, __FUNCTION__);
+                   __FUNCTION__, vid_source->req.count);
         return -1;
     }
 
-    vid_source->buffers = calloc(vid_source->req.count, sizeof(netcam_buff));
+    vid_source->buffers = calloc(vid_source->req.count, sizeof(video_buff));
 
     if (!vid_source->buffers) {
         motion_log(LOG_ERR, 1, "%s: Out of memory.", __FUNCTION__);
@@ -857,20 +856,20 @@
     pthread_sigmask(SIG_UNBLOCK, &old, NULL);    /*undo the signal blocking */
 
     {
-        netcam_buff *the_buffer = &vid_source->buffers[vid_source->buf.index];
+        video_buff *the_buffer = &vid_source->buffers[vid_source->buf.index];
 
         switch (vid_source->fmt.fmt.pix.pixelformat) {
         case V4L2_PIX_FMT_RGB24:
-            conv_rgb24toyuv420p(map, (unsigned char *) the_buffer->ptr, width, height);
+            conv_rgb24toyuv420p(map, the_buffer->ptr, width, height);
             return 0;
 
         case V4L2_PIX_FMT_UYVY:
-            conv_uyvyto420p(map, (unsigned char *) the_buffer->ptr, (unsigned)width, (unsigned)height);
+            conv_uyvyto420p(map, the_buffer->ptr, (unsigned)width, (unsigned)height);
             return 0;
 
         case V4L2_PIX_FMT_YUYV:
         case V4L2_PIX_FMT_YUV422P:
-            conv_yuv422to420p(map, (unsigned char *) the_buffer->ptr, width, height);
+            conv_yuv422to420p(map, the_buffer->ptr, width, height);
             return 0;
 
         case V4L2_PIX_FMT_YUV420:
@@ -880,23 +879,20 @@
         case V4L2_PIX_FMT_PJPG:            
         case V4L2_PIX_FMT_JPEG:            
         case V4L2_PIX_FMT_MJPEG:
-            return mjpegtoyuv420p(map, (unsigned char *) the_buffer->ptr, width, height, 
+            return mjpegtoyuv420p(map, the_buffer->ptr, width, height, 
                                   vid_source->buffers[vid_source->buf.index].content_length);
-/*            return 0;
-        case V4L2_PIX_FMT_JPEG:
-            return conv_jpeg2yuv420(cnt, map, the_buffer, width, height);
-*/
+        
         /* FIXME: quick hack to allow work all bayer formats */            
         case V4L2_PIX_FMT_SBGGR16:            
         case V4L2_PIX_FMT_SGBRG8:            
         case V4L2_PIX_FMT_SPCA561:            
         case V4L2_PIX_FMT_SBGGR8:    /* bayer */
-            bayer2rgb24(cnt->imgs.common_buffer, (unsigned char *) the_buffer->ptr, width, height);
+            bayer2rgb24(cnt->imgs.common_buffer, the_buffer->ptr, width, height);
             conv_rgb24toyuv420p(map, cnt->imgs.common_buffer, width, height);
             return 0;
 
         case V4L2_PIX_FMT_SN9C10X:
-            sonix_decompress(map, (unsigned char *) the_buffer->ptr, width, height);
+            sonix_decompress(map, the_buffer->ptr, width, height);
             bayer2rgb24(cnt->imgs.common_buffer, map, width, height);
             conv_rgb24toyuv420p(map, cnt->imgs.common_buffer, width, height);
             return 0;
Index: video.c
===================================================================
--- video.c	(revision 439)
+++ video.c	(working copy)
@@ -13,11 +13,6 @@
 #include "rotate.h"     /* already includes motion.h */
 #include "video.h"
 
-/* for vloopback */ 
-#include <sys/utsname.h>
-#include <dirent.h>
-
-
 static void v4l_picture_controls(struct context *cnt, struct video_dev *viddev)
 {
     int dev = viddev->fd;
@@ -413,217 +408,4 @@
         v4l_picture_controls(cnt, viddev);
     }
 }
-
-static int v4l_open_vidpipe(void)
-{
-    int pipe_fd = -1;
-    char pipepath[255];
-    char buffer[255];
-    char *major;
-    char *minor;
-    struct utsname uts;
-
-    if (uname(&uts) < 0) {
-        motion_log(LOG_ERR, 1, "%s: Unable to execute uname", __FUNCTION__);
-        return -1;
-    }
-
-    major = strtok(uts.release, ".");
-    minor = strtok(NULL, ".");
-
-    if ((major == NULL) || (minor == NULL) || (strcmp(major, "2"))) {
-        motion_log(LOG_ERR, 1, "%s: Unable to decipher OS version", __FUNCTION__);
-        return -1;
-    }
-
-    if (strcmp(minor, "5") < 0) {
-        FILE *vloopbacks;
-        char *loop;
-        char *input;
-        char *istatus;
-        char *output;
-        char *ostatus;
-
-        vloopbacks = fopen("/proc/video/vloopback/vloopbacks", "r");
-
-        if (!vloopbacks) {
-            motion_log(LOG_ERR, 1, "%s: Failed to open '/proc/video/vloopback/vloopbacks'", 
-                       __FUNCTION__);
-            return -1;
-        }
-        
-        /* Read vloopback version*/
-        if (!fgets(buffer, sizeof(buffer), vloopbacks)) {
-            motion_log(LOG_ERR, 1, "%s: Unable to read vloopback version", __FUNCTION__);
-            return -1;
-        }
-        
-        fprintf(stderr, "\t%s", buffer);
-        
-        /* Read explanation line */
-        
-        if (!fgets(buffer, sizeof(buffer), vloopbacks)) {
-            motion_log(LOG_ERR, 1, "%s: Unable to read vloopback explanation line", 
-                       __FUNCTION__);
-            return -1;
-        }
-        
-        while (fgets(buffer, sizeof(buffer), vloopbacks)) {
-            if (strlen(buffer) > 1) {
-                buffer[strlen(buffer)-1] = 0;
-                loop = strtok(buffer, "\t");
-                input = strtok(NULL, "\t");
-                istatus = strtok(NULL, "\t");
-                output = strtok(NULL, "\t");
-                ostatus = strtok(NULL, "\t");
-
-                if (istatus[0] == '-') {
-                    snprintf(pipepath, sizeof(pipepath), "/dev/%s", input);
-                    pipe_fd = open(pipepath, O_RDWR);
-
-                    if (pipe_fd >= 0) {
-                        motion_log(-1, 0, "%s: \tInput:  /dev/%s \tOutput: /dev/%s",
-                                   __FUNCTION__, input, output);
-                        break;
-                    }
-                }
-            }
-        }
-
-        fclose(vloopbacks);
-    } else {
-        DIR *dir;
-        struct dirent *dirp;
-        const char prefix[] = "/sys/class/video4linux/";
-        char *ptr, *io;
-        int fd;
-        int low = 9999;
-        int tfd;
-        int tnum;
-
-        if ((dir = opendir(prefix)) == NULL) {
-            motion_log(LOG_ERR, 1, "%s: Failed to open '%s'", __FUNCTION__, prefix);
-            return -1;
-        }
-
-        while ((dirp = readdir(dir)) != NULL) {
-            if (!strncmp(dirp->d_name, "video", 5)) {
-                strncpy(buffer, prefix, sizeof(buffer));
-                strncat(buffer, dirp->d_name, sizeof(buffer) - strlen(buffer));
-                strncat(buffer, "/name", sizeof(buffer) - strlen(buffer));
-
-                if ((fd = open(buffer, O_RDONLY)) >= 0) {
-                    if ((read(fd, buffer, sizeof(buffer)-1)) < 0) {
-                        close(fd);
-                        continue;
-                    }
-
-                    ptr = strtok(buffer, " ");
-
-                    if (strcmp(ptr, "Video")) {
-                        close(fd);
-                        continue;
-                    }
-
-                    major = strtok(NULL, " ");
-                    minor = strtok(NULL, " ");
-                    io  = strtok(NULL, " \n");
-                    
-                    if (strcmp(major, "loopback") || strcmp(io, "input")) {
-                        close(fd);
-                        continue;
-                    }
-
-                    if ((ptr = strtok(buffer, " ")) == NULL) {
-                        close(fd);
-                        continue;
-                    }
-
-                    tnum = atoi(minor);
-
-                    if (tnum < low) {
-                        strcpy(buffer, "/dev/");
-                        strncat(buffer, dirp->d_name, sizeof(buffer) - strlen(buffer));
-                        if ((tfd = open(buffer, O_RDWR)) >= 0) {
-                            strncpy(pipepath, buffer, sizeof(pipepath));
-
-                            if (pipe_fd >= 0) 
-                                close(pipe_fd);
-                            
-                            pipe_fd = tfd;
-                            low = tnum;
-                        }
-                    }
-                    close(fd);
-                }
-            }
-        }
-
-        closedir(dir);
-
-        if (pipe_fd >= 0)
-            motion_log(-1, 0, "%s: Opened input of %s", __FUNCTION__, pipepath);
-    }
-
-    return pipe_fd;
-}
-
-static int v4l_startpipe(const char *dev_name, int width, int height, int type)
-{
-    int dev;
-    struct video_picture vid_pic;
-    struct video_window vid_win;
-
-    if (!strcmp(dev_name, "-")) {
-        dev = v4l_open_vidpipe();
-    } else {
-        dev = open(dev_name, O_RDWR);
-    }
-
-    if (dev < 0)
-        return -1;
-
-    if (ioctl(dev, VIDIOCGPICT, &vid_pic) == -1) {
-        motion_log(LOG_ERR, 1, "%s: ioctl (VIDIOCGPICT)", __FUNCTION__);
-        return -1;
-    }
-
-    vid_pic.palette = type;
-
-    if (ioctl(dev, VIDIOCSPICT, &vid_pic) == -1) {
-        motion_log(LOG_ERR, 1, "%s: ioctl (VIDIOCSPICT)", __FUNCTION__);
-        return -1;
-    }
-
-    if (ioctl(dev, VIDIOCGWIN, &vid_win) == -1) {
-        motion_log(LOG_ERR, 1, "%s: ioctl (VIDIOCGWIN)", __FUNCTION__);
-        return -1;
-    }
-
-    vid_win.height = height;
-    vid_win.width = width;
-
-    if (ioctl(dev, VIDIOCSWIN, &vid_win) == -1) {
-        motion_log(LOG_ERR, 1, "%s: ioctl (VIDIOCSWIN)", __FUNCTION__);
-        return -1;
-    }
-
-    return dev;
-}
-
-static int v4l_putpipe (int dev, unsigned char *image, int size)
-{
-    return write(dev, image, size);
-}
-
-
-int vid_startpipe(const char *dev_name, int width, int height, int type)
-{
-    return v4l_startpipe(dev_name, width, height, type);
-}
-
-int vid_putpipe (int dev, unsigned char *image, int size)
-{
-    return v4l_putpipe(dev, image, size);
-}
 #endif /*WITHOUT_V4L*/
Index: video_common.c
===================================================================
--- video_common.c	(revision 439)
+++ video_common.c	(working copy)
@@ -3,7 +3,7 @@
  *      Video stream functions for motion.
  *      Copyright 2000 by Jeroen Vreeken (pe1rxq@amsat.org)
  *                2006 by Krzysztof Blaszkowski (kb@sysmikro.com.pl)    
- *                2007 by Angel Carpinteo (ack@telefonica.net)
+ *                2007 by Angel Carpintero (ack@telefonica.net)
  *      This software is distributed under the GNU public license version 2
  *      See also the file 'COPYING'.
  *
@@ -363,35 +363,6 @@
     }
 }
 
-int conv_jpeg2yuv420(struct context *cnt, unsigned char *dst, netcam_buff *buff, int width, int height)
-{
-    netcam_context netcam;
-
-    if (!buff || !dst)
-        return 3;
-
-    if (!buff->ptr)
-        return 2;    /* Error decoding MJPEG frame */
-
-    memset(&netcam, 0, sizeof(netcam));
-    netcam.imgcnt_last = 1;
-    netcam.latest = buff;
-    netcam.width = width;
-    netcam.height = height;
-    netcam.cnt = cnt;
-
-    pthread_mutex_init(&netcam.mutex, NULL);
-    pthread_cond_init(&netcam.cap_cond, NULL);
-    pthread_cond_init(&netcam.pic_ready, NULL);
-    pthread_cond_init(&netcam.exiting, NULL);
-
-    if (setjmp(netcam.setjmp_buffer)) 
-        return NETCAM_GENERAL_ERROR | NETCAM_JPEG_CONV_ERROR;
-
-    return netcam_proc_jpeg(&netcam, dst);
-}
-
-
 /*
  * mjpegtoyuv420p
  *
Index: video.h
===================================================================
--- video.h	(revision 439)
+++ video.h	(working copy)
@@ -14,6 +14,7 @@
 #ifndef WITHOUT_V4L
 #include <linux/videodev.h>
 #include <sys/mman.h>
+#include "vloopback_motion.h"
 #include "pwc-ioctl.h"
 #endif
 
@@ -36,6 +37,15 @@
 
 #define VIDEO_DEVICE "/dev/video0"
 
+typedef struct video_image_buff {
+    unsigned char *ptr;
+    int content_length;
+    size_t size;                    /* total allocated size */
+    size_t used;                    /* bytes already used */
+    struct timeval image_time;      /* time this image was received */
+} video_buff;
+
+
 struct video_dev {
     struct video_dev *next;
     int usage_count;
@@ -81,7 +91,6 @@
 void conv_yuv422to420p(unsigned char *map, unsigned char *cap_map, int width, int height);
 void conv_uyvyto420p(unsigned char *map, unsigned char *cap_map, unsigned int width, unsigned int height);
 void conv_rgb24toyuv420p(unsigned char *map, unsigned char *cap_map, int width, int height);
-int conv_jpeg2yuv420(struct context *cnt, unsigned char *dst, netcam_buff * buff, int width, int height);
 int sonix_decompress(unsigned char *outp, unsigned char *inp, int width, int height);
 void bayer2rgb24(unsigned char *dst, unsigned char *src, long int width, long int height);
 int vid_do_autobright(struct context *cnt, struct video_dev *viddev);
@@ -89,8 +98,6 @@
 
 #ifndef WITHOUT_V4L
 /* video functions, video.c */
-int vid_startpipe(const char *dev_name, int width, int height, int);
-int vid_putpipe(int dev, unsigned char *image, int);
 unsigned char *v4l_start(struct video_dev *viddev, int width, int height,
                          int input, int norm, unsigned long freq, int tuner_number);
 void v4l_set_input(struct context *cnt, struct video_dev *viddev, unsigned char *map, int width, int height, int input,
