The patch number 14289 was added via h...@rhel5-devel.localdomain
to http://linuxtv.org/hg/v4l-dvb master development tree.

Kernel patches in this development tree may be modified to be backward
compatible with older kernels. Compatibility modifications will be
removed before inclusion into the mainstream Kernel

If anyone has any objections, please let us know by sending a message to:
        Linux Media Mailing List <linux-me...@vger.kernel.org>

------

From: Hans de Goede  <hdego...@redhat.com>
libv4l: speedup software autogain settling


On camera's with a gine grained exposure control like some mr97310a models,
the autogain algorithm would take ages to get to the desired point. This
patch considerably speeds up the autogain algorithm.

Priority: normal

Signed-off-by: Hans de Goede <hdego...@redhat.com>


---

 v4l2-apps/libv4l/libv4lconvert/processing/autogain.c         |   94 ++++++----
 v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c |    4 
 2 files changed, 65 insertions(+), 33 deletions(-)

diff -r 84e7bbc90d54 -r 00c5ac380715 
v4l2-apps/libv4l/libv4lconvert/processing/autogain.c
--- a/v4l2-apps/libv4l/libv4lconvert/processing/autogain.c      Sun Jan 10 
04:08:59 2010 +0100
+++ b/v4l2-apps/libv4l/libv4lconvert/processing/autogain.c      Sun Jan 10 
08:40:17 2010 +0100
@@ -39,6 +39,30 @@
   return autogain;
 }
 
+/* Adjust ctrl value with steps steps, while not crossing limit */
+static int autogain_adjust(struct v4l2_queryctrl *ctrl, int *value,
+  int steps, int limit)
+{
+  int ctrl_range = (ctrl->maximum - ctrl->minimum) / ctrl->step;
+
+  /* If we are of 2 * deadzone or more, and we have a very fine grained
+     control, take larger steps, otherwise we take ages to get to the
+     right setting point. We use 256 as tripping point for determineing fine
+     grained controls here, as avg_lum has a range of 0 - 255. */
+  if (abs(steps) >= 2 && ctrl_range > 256)
+    *value += steps * ctrl->step * (ctrl_range / 256);
+  else
+    *value += steps * ctrl->step;
+
+  if (steps > 0) {
+    if (*value > limit)
+      *value = limit;
+  } else {
+    if (*value < limit)
+      *value = limit;
+  }
+}
+
 /* auto gain and exposure algorithm based on the knee algorithm described here:
    http://ytse.tricolour.net/docs/LowLightOptimization.html */
 static int autogain_calculate_lookup_tables(
@@ -63,9 +87,10 @@
      has hit this value */
   exposure_low = expoctrl.maximum / 10;
   /* If we have a fine grained exposure control only avoid the last 10 steps */
-  if (exposure_low > 10)
-    exposure_low = 10;
-  exposure_low += expoctrl.minimum;
+  steps = exposure_low / expoctrl.step;
+  if (steps > 10)
+    steps = 10;
+  exposure_low = steps * expoctrl.step + expoctrl.minimum;
 
   ctrl.id = V4L2_CID_GAIN;
   gainctrl.id = V4L2_CID_GAIN;
@@ -119,38 +144,43 @@
       (steps < 0 && data->last_gain_correction > 0))
     steps /= 2;
 
-  for (x = 0; x < abs(steps); x++) {
-    if (avg_lum > target) {
-      if (exposure > expoctrl.default_value)
-       exposure--;
-      else if (gain > gainctrl.default_value)
-       gain--;
-      else if (exposure > exposure_low)
-       exposure--;
-      else if (gain > gainctrl.minimum)
-       gain--;
-      else if (exposure > expoctrl.minimum)
-       exposure--;
-      else
-       break;
-    } else {
-      if (exposure < exposure_low)
-       exposure++;
-      else if (gain < gainctrl.default_value)
-       gain++;
-      else if (exposure < expoctrl.default_value)
-       exposure++;
-      else if (gain < gainctrl.maximum)
-       gain++;
-      else if (exposure < expoctrl.maximum)
-       exposure++;
-      else
-       break;
-    }
+  if (steps == 0)
+    return 0; /* Nothing to do */
+
+  if (steps < 0) {
+    if (exposure > expoctrl.default_value)
+      autogain_adjust(&expoctrl, &exposure, steps, expoctrl.default_value);
+    else if (gain > gainctrl.default_value)
+      autogain_adjust(&gainctrl, &gain, steps, gainctrl.default_value);
+    else if (exposure > exposure_low)
+      autogain_adjust(&expoctrl, &exposure, steps, exposure_low);
+    else if (gain > gainctrl.minimum)
+      autogain_adjust(&gainctrl, &gain, steps, gainctrl.minimum);
+    else if (exposure > expoctrl.minimum)
+      autogain_adjust(&expoctrl, &exposure, steps, expoctrl.minimum);
+    else
+      steps = 0;
+  } else {
+    if (exposure < exposure_low)
+      autogain_adjust(&expoctrl, &exposure, steps, exposure_low);
+    else if (gain < gainctrl.default_value)
+      autogain_adjust(&gainctrl, &gain, steps, gainctrl.default_value);
+    else if (exposure < expoctrl.default_value)
+      autogain_adjust(&expoctrl, &exposure, steps, expoctrl.default_value);
+    else if (gain < gainctrl.maximum)
+      autogain_adjust(&gainctrl, &gain, steps, gainctrl.maximum);
+    else if (exposure < expoctrl.maximum)
+      autogain_adjust(&expoctrl, &exposure, steps, expoctrl.maximum);
+    else
+      steps = 0;
   }
 
-  if (steps)
+  if (steps) {
     data->last_gain_correction = steps;
+    /* We are still settling down, force the next update sooner. Note we
+       skip the next frame as that is still captured with the old settings. */
+    data->lookup_table_update_counter = V4L2PROCESSING_UPDATE_RATE - 1;
+  }
 
   if (gain != orig_gain) {
     ctrl.id = V4L2_CID_GAIN;
diff -r 84e7bbc90d54 -r 00c5ac380715 
v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c
--- a/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c      Sun Jan 
10 04:08:59 2010 +0100
+++ b/v4l2-apps/libv4l/libv4lconvert/processing/libv4lprocessing.c      Sun Jan 
10 08:40:17 2010 +0100
@@ -173,9 +173,11 @@
 
   if (data->controls_changed ||
       data->lookup_table_update_counter == V4L2PROCESSING_UPDATE_RATE) {
-    v4lprocessing_update_lookup_tables(data, buf, fmt);
     data->controls_changed = 0;
     data->lookup_table_update_counter = 0;
+    /* Do this after resetting lookup_table_update_counter so that filters can
+       force the next update to be sooner when they changed camera settings */
+    v4lprocessing_update_lookup_tables(data, buf, fmt);
   } else
     data->lookup_table_update_counter++;
 


---

Patch is available at: 
http://linuxtv.org/hg/v4l-dvb/rev/00c5ac380715b61a2de6b4068b4ae7d63b8743a4

_______________________________________________
linuxtv-commits mailing list
linuxtv-commits@linuxtv.org
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits

Reply via email to