From 4e4aefed3e1d9e7bd1f772a47c208168f6811c3e Mon Sep 17 00:00:00 2001
From: David Fries <David@Fries.net>
Date: Mon, 28 Jul 2014 23:27:53 -0500
Subject: [PATCH 1/4] alg_labeling give diffs feedback even when not over the
 threshold

This is especially useful when picking a threshold to see how
close to the threshold it was.
---
 alg.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/alg.c b/alg.c
index 93c260f..8890940 100644
--- a/alg.c
+++ b/alg.c
@@ -526,6 +526,8 @@ static int alg_labeling(struct context *cnt)
     int height = imgs->height;
     int labelsize = 0;
     int current_label = 2;
+    /* Keep track of the area just under the threshold.  */
+    int max_under = 0;
 
     cnt->current_image->total_labels = 0;
     imgs->labelsize_max = 0;
@@ -561,7 +563,8 @@ static int alg_labeling(struct context *cnt)
                     labelsize = iflood(ix, iy, width, height, out, labels, current_label + 32768, current_label);
                     imgs->labelgroup_max += labelsize;
                     imgs->labels_above++;
-                }
+                } else if(max_under < labelsize)
+                    max_under = labelsize;
                 
                 if (imgs->labelsize_max < labelsize) {
                     imgs->labelsize_max = labelsize;
@@ -579,8 +582,11 @@ static int alg_labeling(struct context *cnt)
                "Largest Label: %i", imgs->largest_label, imgs->labelsize_max, 
                cnt->current_image->total_labels);
     
-    /* Return group of significant labels. */
-    return imgs->labelgroup_max;
+    /* Return group of significant labels or if that's none, the next largest
+     * group (which is under the threshold, but especially for setup gives an
+     * idea how close it was).
+     */
+    return imgs->labelgroup_max ? imgs->labelgroup_max : max_under;
 }
 
 /** 
-- 
2.1.4


From 385df115fbf322a68ef6b11f6bb8f022e46c1d13 Mon Sep 17 00:00:00 2001
From: David Fries <David@Fries.net>
Date: Thu, 8 Nov 2012 23:59:32 -0600
Subject: [PATCH 2/4] accept a width specifier to mystrftime

Allow the user to specify field widths to keep the strings from
jumping around as the width changes.  This makes the values easier
to read.
---
 CHANGELOG |  1 +
 CREDITS   |  1 +
 motion.c  | 42 +++++++++++++++++++++++++++---------------
 3 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 9ac2de0..fe31cc4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -49,6 +49,7 @@ Features
      http://www.lavrsen.dk/foswiki/bin/view/Motion/OggTimelapse (Michael Luich)
    * Added support for ffmpeg 0.11 new API.
    * Added RSTP support for netcam ( merge https://github.com/hyperbolic2346/motion )
+   * Allow text format specifiers to take a width like printf would.  (David Fries)
 
 Bugfixes
    * Avoid segfault detecting strerror_r() version GNU or SUSv3. (Angel Carpintero)
diff --git a/CREDITS b/CREDITS
index d21549b..a656adb 100644
--- a/CREDITS
+++ b/CREDITS
@@ -475,6 +475,7 @@ Miguel Freitas
 
 David Fries
    * Fix webhttpd race condition crash with SIGHUP, add it to running thread counter
+   * Allow text format specifiers to take a width like printf would.
 
 Aaron Gage
    * Pointed me to the vid_mmap/int problem when calling SYNC in
diff --git a/motion.c b/motion.c
index 83c11e2..7bcdcb3 100644
--- a/motion.c
+++ b/motion.c
@@ -3176,6 +3176,7 @@ size_t mystrftime(const struct context *cnt, char *s, size_t max, const char *us
     char tempstring[PATH_MAX] = "";
     char *format, *tempstr;
     const char *pos_userformat;
+    int width;
 
     format = formatstring;
 
@@ -3195,6 +3196,12 @@ size_t mystrftime(const struct context *cnt, char *s, size_t max, const char *us
              */
             tempstr = tempstring;
             tempstr[0] = '\0';
+            width = 0;
+            while ('0' <= pos_userformat[1] && pos_userformat[1] <= '9') {
+                width *= 10;
+                width += pos_userformat[1] - '0';
+                ++pos_userformat;
+            }
 
             switch (*++pos_userformat) {
             case '\0': // end of string
@@ -3202,73 +3209,78 @@ size_t mystrftime(const struct context *cnt, char *s, size_t max, const char *us
                 break;
 
             case 'v': // event
-                sprintf(tempstr, "%02d", cnt->event_nr);
+                sprintf(tempstr, "%0*d", width ? width : 2, cnt->event_nr);
                 break;
 
             case 'q': // shots
-                sprintf(tempstr, "%02d", cnt->current_image->shot);
+                sprintf(tempstr, "%0*d", width ? width : 2,
+                    cnt->current_image->shot);
                 break;
 
             case 'D': // diffs
-                sprintf(tempstr, "%d", cnt->current_image->diffs);
+                sprintf(tempstr, "%*d", width, cnt->current_image->diffs);
                 break;
 
             case 'N': // noise
-                sprintf(tempstr, "%d", cnt->noise);
+                sprintf(tempstr, "%*d", width, cnt->noise);
                 break;
 
             case 'i': // motion width
-                sprintf(tempstr, "%d", cnt->current_image->location.width);
+                sprintf(tempstr, "%*d", width,
+                    cnt->current_image->location.width);
                 break;
 
             case 'J': // motion height
-                sprintf(tempstr, "%d", cnt->current_image->location.height);
+                sprintf(tempstr, "%*d", width,
+                    cnt->current_image->location.height);
                 break;
 
             case 'K': // motion center x
-                sprintf(tempstr, "%d", cnt->current_image->location.x);
+                sprintf(tempstr, "%*d", width, cnt->current_image->location.x);
                 break;
 
             case 'L': // motion center y
-                sprintf(tempstr, "%d", cnt->current_image->location.y);
+                sprintf(tempstr, "%*d", width, cnt->current_image->location.y);
                 break;
 
             case 'o': // threshold
-                sprintf(tempstr, "%d", cnt->threshold);
+                sprintf(tempstr, "%*d", width, cnt->threshold);
                 break;
 
             case 'Q': // number of labels
-                sprintf(tempstr, "%d", cnt->current_image->total_labels);
+                sprintf(tempstr, "%*d", width,
+                    cnt->current_image->total_labels);
                 break;
 
             case 't': // thread number
-                sprintf(tempstr, "%d",(int)(unsigned long)
+                sprintf(tempstr, "%*d", width, (int)(unsigned long)
                         pthread_getspecific(tls_key_threadnr));
                 break;
 
             case 'C': // text_event
                 if (cnt->text_event_string && cnt->text_event_string[0])
-                    snprintf(tempstr, PATH_MAX, "%s", cnt->text_event_string);
+                    snprintf(tempstr, PATH_MAX, "%*s", width,
+                        cnt->text_event_string);
                 else
                     ++pos_userformat;
                 break;
 
             case 'f': // filename -- or %fps
                 if ((*(pos_userformat+1) == 'p') && (*(pos_userformat+2) == 's')) {
-                    sprintf(tempstr, "%d", cnt->movie_fps);
+                    sprintf(tempstr, "%*d", width, cnt->movie_fps);
                     pos_userformat += 2;
                     break;
                 }
 
                 if (filename)
-                    snprintf(tempstr, PATH_MAX, "%s", filename);
+                    snprintf(tempstr, PATH_MAX, "%*s", width, filename);
                 else
                     ++pos_userformat;
                 break;
 
             case 'n': // sqltype
                 if (sqltype)
-                    sprintf(tempstr, "%d", sqltype);
+                    sprintf(tempstr, "%*d", width, sqltype);
                 else
                     ++pos_userformat;
                 break;
-- 
2.1.4


From fb73273c17502bd32205bb2bda0437c22299124b Mon Sep 17 00:00:00 2001
From: David Fries <David@Fries.net>
Date: Fri, 9 Nov 2012 23:54:12 -0600
Subject: [PATCH 3/4] add power_line_frequency configuration item

The USB webcam I have defaults to the wrong setting causing visible
flickering degrading the image quality.  This allows setting the
value to any of the currently available options or -1 to by default
not modify the value.
---
 CHANGELOG      |  1 +
 CREDITS        |  1 +
 conf.c         | 17 +++++++++++++++++
 conf.h         |  1 +
 video.h        |  1 +
 video2.c       | 19 +++++++++++++++++++
 video_common.c |  2 ++
 7 files changed, 42 insertions(+)

diff --git a/CHANGELOG b/CHANGELOG
index fe31cc4..c4e7d9e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -50,6 +50,7 @@ Features
    * Added support for ffmpeg 0.11 new API.
    * Added RSTP support for netcam ( merge https://github.com/hyperbolic2346/motion )
    * Allow text format specifiers to take a width like printf would.  (David Fries)
+   * Add power_line_frequency configuration item to improve image quality.  (David Fries)
 
 Bugfixes
    * Avoid segfault detecting strerror_r() version GNU or SUSv3. (Angel Carpintero)
diff --git a/CREDITS b/CREDITS
index a656adb..02434b1 100644
--- a/CREDITS
+++ b/CREDITS
@@ -476,6 +476,7 @@ Miguel Freitas
 David Fries
    * Fix webhttpd race condition crash with SIGHUP, add it to running thread counter
    * Allow text format specifiers to take a width like printf would.
+   * Add power_line_frequency configuration item to improve image quality.
 
 Aaron Gage
    * Pointed me to the vid_mmap/int problem when calling SYNC in
diff --git a/conf.c b/conf.c
index 2da0da6..f39f448 100644
--- a/conf.c
+++ b/conf.c
@@ -71,6 +71,7 @@ struct config conf_template = {
     contrast:                       0,
     saturation:                     0,
     hue:                            0,
+    power_line_frequency:           -1,
     roundrobin_frames:              1,
     roundrobin_skip:                1,
     pre_capture:                    0,
@@ -460,6 +461,22 @@ config_param config_params[] = {
     print_int
     },
     {
+    "power_line_frequency",
+    "# Set the power line frequency to help cancel flicker by compensating\n"
+    "# for light intensity ripple.  (default: -1).\n"
+    "# This can help reduce power line light flicker.\n"
+    "# Valuse :\n"
+    "# do not modify the device setting       : -1\n"
+    "# V4L2_CID_POWER_LINE_FREQUENCY_DISABLED : 0\n"
+    "# V4L2_CID_POWER_LINE_FREQUENCY_50HZ     : 1\n"
+    "# V4L2_CID_POWER_LINE_FREQUENCY_60HZ     : 2\n"
+    "# V4L2_CID_POWER_LINE_FREQUENCY_AUTO     : 3",
+    0,
+    CONF_OFFSET(power_line_frequency),
+    copy_int,
+    print_int
+    },
+    {
     "roundrobin_frames",
     "\n############################################################\n"
     "# Round Robin (multiple inputs on same video device name)\n"
diff --git a/conf.h b/conf.h
index b03397e..455311c 100644
--- a/conf.h
+++ b/conf.h
@@ -53,6 +53,7 @@ struct config {
     int contrast;
     int saturation;
     int hue;
+    int power_line_frequency;
     int roundrobin_frames;
     int roundrobin_skip;
     int pre_capture;
diff --git a/video.h b/video.h
index 12f2928..ee6aa05 100644
--- a/video.h
+++ b/video.h
@@ -61,6 +61,7 @@ struct video_dev {
     int contrast;
     int saturation;
     int hue;
+    int power_line_frequency;
     unsigned long freq;
     int tuner_number;
     int fps;
diff --git a/video2.c b/video2.c
index 32d80c1..68f2de7 100644
--- a/video2.c
+++ b/video2.c
@@ -144,6 +144,10 @@ static const u32 queried_ctrls[] = {
     V4L2_CID_CONTRAST,
     V4L2_CID_SATURATION,
     V4L2_CID_HUE,
+/* first added in Linux kernel v2.6.26 */
+#ifdef V4L2_CID_POWER_LINE_FREQUENCY
+    V4L2_CID_POWER_LINE_FREQUENCY,
+#endif
 
     V4L2_CID_RED_BALANCE,
     V4L2_CID_BLUE_BALANCE,
@@ -745,6 +749,13 @@ static int v4l2_set_control(src_v4l2_t * vid_source, u32 cid, int value)
                     ret = xioctl(vid_source, VIDIOC_S_CTRL, &control);
                     break;
 
+                case V4L2_CTRL_TYPE_MENU:
+                    /* set as is, no adjustments */
+                    control.value = value;
+                    ret = xioctl(vid_source, VIDIOC_S_CTRL, &control);
+                    break;
+
+
                 default:
                     MOTION_LOG(WRN, TYPE_VIDEO, NO_ERRNO, "%s: control type not supported yet");
                     return -1;
@@ -785,6 +796,14 @@ static void v4l2_picture_controls(struct context *cnt, struct video_dev *viddev)
         v4l2_set_control(vid_source, V4L2_CID_HUE, viddev->hue);
     }
 
+#ifdef V4L2_CID_POWER_LINE_FREQUENCY
+    /* -1 is don't modify as 0 is an option to disable the power line filter */
+    if (cnt->conf.power_line_frequency != -1 && cnt->conf.power_line_frequency != viddev->power_line_frequency) {
+        viddev->power_line_frequency = cnt->conf.power_line_frequency;
+        v4l2_set_control(vid_source, V4L2_CID_POWER_LINE_FREQUENCY, viddev->power_line_frequency);
+    }
+#endif
+
     if (cnt->conf.autobright) {
         if (vid_do_autobright(cnt, viddev)) {
             if (v4l2_set_control(vid_source, V4L2_CID_BRIGHTNESS, viddev->brightness))
diff --git a/video_common.c b/video_common.c
index 9f8d6a0..79a10a4 100644
--- a/video_common.c
+++ b/video_common.c
@@ -760,6 +760,8 @@ static int vid_v4lx_start(struct context *cnt)
     dev->contrast = 0;
     dev->saturation = 0;
     dev->hue = 0;
+    /* -1 is don't modify, (0 is a valid value) */
+    dev->power_line_frequency = -1;
     dev->owner = -1;
     dev->v4l_fmt = VIDEO_PALETTE_YUV420P;
     dev->fps = 0;
-- 
2.1.4


From 2496e21b8a1d4fe10b6cbf2f3b50861384e98dfc Mon Sep 17 00:00:00 2001
From: David Fries <David@Fries.net>
Date: Sat, 5 Jan 2013 16:42:13 -0600
Subject: [PATCH 4/4] add ffmpeg_duplicate_frames option

This lets the user decide which video problems they would rather see.
In my case a Raspberry Pi 2 with a 640x480 webcam sometimes can keep
up with 10fps so I don't want to set the framerate any lower, but
then sometimes it can't and with duplicate frames it looks like the
video output freezes every second.
---
 conf.c   | 9 +++++++++
 conf.h   | 1 +
 motion.c | 7 ++++++-
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/conf.c b/conf.c
index f39f448..5fed2da 100644
--- a/conf.c
+++ b/conf.c
@@ -668,6 +668,15 @@ config_param config_params[] = {
     print_string
     },
     {
+    "ffmpeg_duplicate_frames",
+    "# True to duplicate frames to achieve \"framerate\" fps, but enough\n"
+    "duplicated frames and the video appears to freeze once a second.",
+    0,
+    CONF_OFFSET(ffmpeg_duplicate_frames),
+    copy_bool,
+    print_bool
+    },
+    {
     "output_debug_pictures",
     "# Output pictures with only the pixels moving object (ghost images) (default: off)",
     0,
diff --git a/conf.h b/conf.h
index 455311c..04040db 100644
--- a/conf.h
+++ b/conf.h
@@ -30,6 +30,7 @@ struct config {
     int max_changes;
     int threshold_tune;
     const char *output_pictures;
+    int ffmpeg_duplicate_frames;
     int motion_img;
     int emulate_motion;
     int event_gap;
diff --git a/motion.c b/motion.c
index 7bcdcb3..5f0695f 100644
--- a/motion.c
+++ b/motion.c
@@ -570,8 +570,13 @@ static void process_image_ring(struct context *cnt, unsigned int max_images)
             /* 
              * Check if we must add any "filler" frames into movie to keep up fps 
              * Only if we are recording videos ( ffmpeg or extenal pipe )         
+             * While the overall elapsed time might be correct, if there are
+             * many duplicated frames, say 10 fps, 5 duplicated, the video will
+             * look like it is frozen every second for half a second.
              */
-            if ((cnt->imgs.image_ring[cnt->imgs.image_ring_out].shot == 0) &&
+            if (!cnt->conf.ffmpeg_duplicate_frames) {
+                /* don't duplicate frames */
+            } else if ((cnt->imgs.image_ring[cnt->imgs.image_ring_out].shot == 0) &&
 #ifdef HAVE_FFMPEG
                 (cnt->ffmpeg_output || (cnt->conf.useextpipe && cnt->extpipe))) {
 #else
-- 
2.1.4

