From: Hans de Goede <j.w.r.degoede@hhs.nl>
To: video4linux-list@redhat.com
Subject: PATCH: gspca-general-autogain_n_exposure-knee-algp.patch
Date: Wed, 09 Jul 2008 15:29:54 +0200 [thread overview]
Message-ID: <4874BD52.60601@hhs.nl> (raw)
[-- Attachment #1: Type: text/plain, Size: 427 bytes --]
Hi,
Make the knee auto gain and exposure algorithm, described here:
http://ytse.tricolour.net/docs/LowLightOptimization.html
And currently used in the pac207 generic (iow not pac207 specific) and move it
to gspca.c . This is a preperation patch for adding exposure setting and auto
gain and exposure to the sn9c10x driver (for selective sensors for now).
Signed-off-by: Hans de Goede <j.w.r.degoede@hhs.nl>
Regards,
Hans
[-- Attachment #2: gspca-general-autogain_n_exposure-knee-algp.patch --]
[-- Type: text/plain, Size: 6978 bytes --]
Make the knee auto gain and exposure algorithm, described here:
http://ytse.tricolour.net/docs/LowLightOptimization.html
And currently used in the pac207 generic (iow not pac207 specific) and move it
to gspca.c . This is a preperation patch for adding exposure setting and auto
gain and exposure to the sn9c10x driver (for selective sensors for now).
Signed-off-by: Hans de Goede <j.w.r.degoede@hhs.nl>
diff -r 5065159a99d4 linux/drivers/media/video/gspca/gspca.c
--- a/linux/drivers/media/video/gspca/gspca.c Sun Jul 06 09:27:19 2008 +0200
+++ b/linux/drivers/media/video/gspca/gspca.c Mon Jul 07 09:15:54 2008 +0200
@@ -1894,6 +1894,91 @@
}
EXPORT_SYMBOL(gspca_disconnect);
+/* -- cam driver utility functions -- */
+
+/* auto gain and exposure algorithm based on the knee algorithm described here:
+ http://ytse.tricolour.net/docs/LowLightOptimization.html
+
+ Returns 0 if no changes were made, 1 if the gain and or exposure settings
+ where changed. */
+int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
+ int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee)
+{
+ int i, steps, gain, orig_gain, exposure, orig_exposure, autogain;
+ const struct ctrl *gain_ctrl = NULL;
+ const struct ctrl *exposure_ctrl = NULL;
+ const struct ctrl *autogain_ctrl = NULL;
+ int retval = 0;
+
+ for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
+ if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_GAIN)
+ gain_ctrl = &gspca_dev->sd_desc->ctrls[i];
+ if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_EXPOSURE)
+ exposure_ctrl = &gspca_dev->sd_desc->ctrls[i];
+ if (gspca_dev->sd_desc->ctrls[i].qctrl.id == V4L2_CID_AUTOGAIN)
+ autogain_ctrl = &gspca_dev->sd_desc->ctrls[i];
+ }
+ if (!gain_ctrl || !exposure_ctrl || !autogain_ctrl) {
+ PDEBUG(D_ERR, "Error: gspca_auto_gain_n_exposure called "
+ "on cam without (auto)gain/exposure");
+ return 0;
+ }
+
+ if (gain_ctrl->get(gspca_dev, &gain) ||
+ exposure_ctrl->get(gspca_dev, &exposure) ||
+ autogain_ctrl->get(gspca_dev, &autogain) || !autogain)
+ return 0;
+
+ orig_gain = gain;
+ orig_exposure = exposure;
+
+ /* If we are of a multiple of deadzone, do multiple steps to reach the
+ desired lumination fast (with the risc of a slight overshoot) */
+ steps = abs(desired_avg_lum - avg_lum) / deadzone;
+
+ for (i = 0; i < steps; i++) {
+ if (avg_lum > desired_avg_lum) {
+ if (gain > gain_knee)
+ gain--;
+ else if (exposure > exposure_knee)
+ exposure--;
+ else if (gain > gain_ctrl->qctrl.default_value)
+ gain--;
+ else if (exposure > exposure_ctrl->qctrl.minimum)
+ exposure--;
+ else if (gain > gain_ctrl->qctrl.minimum)
+ gain--;
+ else
+ break;
+ } else {
+ if (gain < gain_ctrl->qctrl.default_value)
+ gain++;
+ else if (exposure < exposure_knee)
+ exposure++;
+ else if (gain < gain_knee)
+ gain++;
+ else if (exposure < exposure_ctrl->qctrl.maximum)
+ exposure++;
+ else if (gain < gain_ctrl->qctrl.maximum)
+ gain++;
+ else
+ break;
+ }
+ }
+
+ if (gain != orig_gain) {
+ gain_ctrl->set(gspca_dev, gain);
+ retval = 1;
+ }
+ if (exposure != orig_exposure) {
+ exposure_ctrl->set(gspca_dev, exposure);
+ retval = 1;
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(gspca_auto_gain_n_exposure);
+
/* -- module insert / remove -- */
static int __init gspca_init(void)
{
diff -r 5065159a99d4 linux/drivers/media/video/gspca/gspca.h
--- a/linux/drivers/media/video/gspca/gspca.h Sun Jul 06 09:27:19 2008 +0200
+++ b/linux/drivers/media/video/gspca/gspca.h Mon Jul 07 09:15:54 2008 +0200
@@ -172,4 +172,6 @@
struct gspca_frame *frame,
const __u8 *data,
int len);
+int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
+ int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee);
#endif /* GSPCAV2_H */
diff -r 5065159a99d4 linux/drivers/media/video/gspca/pac207.c
--- a/linux/drivers/media/video/gspca/pac207.c Sun Jul 06 09:27:19 2008 +0200
+++ b/linux/drivers/media/video/gspca/pac207.c Mon Jul 07 09:15:54 2008 +0200
@@ -357,70 +357,20 @@
{
}
-/* auto gain and exposure algorithm based on the knee algorithm described here:
- * <http://ytse.tricolour.net/docs/LowLightOptimization.html> */
static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- int i, steps, desired_avg_lum;
- int orig_gain = sd->gain;
- int orig_exposure = sd->exposure;
int avg_lum = atomic_read(&sd->avg_lum);
- if (!sd->autogain || avg_lum == -1)
+ if (avg_lum == -1)
return;
- if (sd->autogain_ignore_frames > 0) {
+ if (sd->autogain_ignore_frames > 0)
sd->autogain_ignore_frames--;
- return;
- }
-
- /* correct desired lumination for the configured brightness */
- desired_avg_lum = 100 + sd->brightness / 2;
-
- /* If we are of a multiple of deadzone, do multiple step to reach the
- desired lumination fast (with the risc of a slight overshoot) */
- steps = abs(desired_avg_lum - avg_lum) / PAC207_AUTOGAIN_DEADZONE;
-
- for (i = 0; i < steps; i++) {
- if (avg_lum > desired_avg_lum) {
- if (sd->gain > PAC207_GAIN_KNEE)
- sd->gain--;
- else if (sd->exposure > PAC207_EXPOSURE_KNEE)
- sd->exposure--;
- else if (sd->gain > PAC207_GAIN_DEFAULT)
- sd->gain--;
- else if (sd->exposure > PAC207_EXPOSURE_MIN)
- sd->exposure--;
- else if (sd->gain > PAC207_GAIN_MIN)
- sd->gain--;
- else
- break;
- } else {
- if (sd->gain < PAC207_GAIN_DEFAULT)
- sd->gain++;
- else if (sd->exposure < PAC207_EXPOSURE_KNEE)
- sd->exposure++;
- else if (sd->gain < PAC207_GAIN_KNEE)
- sd->gain++;
- else if (sd->exposure < PAC207_EXPOSURE_MAX)
- sd->exposure++;
- else if (sd->gain < PAC207_GAIN_MAX)
- sd->gain++;
- else
- break;
- }
- }
-
- if (sd->exposure != orig_exposure || sd->gain != orig_gain) {
- if (sd->exposure != orig_exposure)
- pac207_write_reg(gspca_dev, 0x0002, sd->exposure);
- if (sd->gain != orig_gain)
- pac207_write_reg(gspca_dev, 0x000e, sd->gain);
- pac207_write_reg(gspca_dev, 0x13, 0x01); /* load reg to sen */
- pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
+ else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
+ 100 + sd->brightness / 2, PAC207_AUTOGAIN_DEADZONE,
+ PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE))
sd->autogain_ignore_frames = PAC207_AUTOGAIN_IGNORE_FRAMES;
- }
}
static unsigned char *pac207_find_sof(struct gspca_dev *gspca_dev,
@@ -546,10 +496,6 @@
{
struct sd *sd = (struct sd *) gspca_dev;
- /* don't allow mucking with exposure when using autogain */
- if (sd->autogain)
- return -EINVAL;
-
sd->exposure = val;
if (gspca_dev->streaming)
setexposure(gspca_dev);
@@ -567,10 +513,6 @@
static int sd_setgain(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
-
- /* don't allow mucking with gain when using autogain */
- if (sd->autogain)
- return -EINVAL;
sd->gain = val;
if (gspca_dev->streaming)
[-- Attachment #3: Type: text/plain, Size: 164 bytes --]
--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list
reply other threads:[~2008-07-09 13:30 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4874BD52.60601@hhs.nl \
--to=j.w.r.degoede@hhs.nl \
--cc=video4linux-list@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.