summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-03-16 15:48:30 +0100
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-05-01 12:13:56 +0200
commitf030d07589524d07d5eaf7c2dfff607656889b8b (patch)
treebe57ed8735b8ffbc6fb9cd7ca461f037c1e61978
parentb0e966a8488e19fcc1c7eb86a217c5f7675a4da0 (diff)
iq: Make the IQ parameters configurable
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--iq.c134
-rw-r--r--iq.h32
-rw-r--r--live.c26
-rw-r--r--snapshot.c26
4 files changed, 181 insertions, 37 deletions
diff --git a/iq.c b/iq.c
index b02c297..c407b6e 100644
--- a/iq.c
+++ b/iq.c
@@ -37,22 +37,14 @@ struct iq_tuning {
unsigned int frame_count;
unsigned int pix_max;
- float mean_level;
- unsigned int exposure;
- unsigned int exposure_min;
- unsigned int exposure_max;
-
- unsigned int gain;
- unsigned int gain_min;
- unsigned int gain_max;
-
- unsigned int black_level;
+ struct iq_params params;
};
void iq_aewb_process(struct iq_tuning *iq,
const struct omap3_isp_aewb_stats *stats)
{
+ struct iq_params *iqp = &iq->params;
unsigned int i;
float gains[4];
double factor;
@@ -77,24 +69,104 @@ void iq_aewb_process(struct iq_tuning *iq,
+ stats->accum[2] + stats->accum[3];
mean /= 4 * stats->npix;
- factor = (iq->pix_max * iq->mean_level) / mean;
+ factor = (iq->pix_max * iqp->mean_level) / mean;
- gain = factor * iq->exposure * iq->gain / iq->gain_min;
- iq->exposure = clamp((unsigned int)gain,
- iq->exposure_min, iq->exposure_max);
+ gain = factor * iqp->exposure * iqp->gain / iqp->gain_min;
+ iqp->exposure = clamp((unsigned int)gain,
+ iqp->exposure_min, iqp->exposure_max);
- gain = gain / iq->exposure * iq->gain_min;
- iq->gain = clamp((unsigned int)gain,
- iq->gain_min, iq->gain_max);
+ gain = gain / iqp->exposure * iqp->gain_min;
+ iqp->gain = clamp((unsigned int)gain, iqp->gain_min, iqp->gain_max);
printf("AE: factor %.4f exposure %u sensor gain %u\n",
- factor, iq->exposure, iq->gain);
+ factor, iqp->exposure, iqp->gain);
- omap3_isp_sensor_set_exposure(iq->isp, iq->exposure);
- omap3_isp_sensor_set_gain(iq->isp, iq->gain);
+ omap3_isp_sensor_set_exposure(iq->isp, iqp->exposure);
+ omap3_isp_sensor_set_gain(iq->isp, iqp->gain);
}
-struct iq_tuning *iq_init(struct omap3_isp_device *isp)
+/**
+ * iq_params_init - Initialize IQ parameters
+ * @params: IQ parameters
+ *
+ * Fill the passed params structure with the default IQ parameters.
+ */
+void iq_params_init(struct iq_params *params)
+{
+ params->mean_level = 0.15;
+ params->exposure = 1000;
+ params->exposure_min = 10;
+ params->exposure_max = 2000;
+ params->gain = 8;
+ params->gain_min = 8;
+ params->gain_max = 1024;
+ params->black_level = 64;
+}
+
+/**
+ * iq_params_parse - Parse an IQ parameter string
+ * @params: IQ parameters
+ * @arg: Parameter string
+ *
+ * Parse the given parameter string and store the parameter value in the params
+ * structure. The parameter string must have the form
+ *
+ * name=value
+ *
+ * Return 0 on success or a negative error code otherwise:
+ *
+ * -EINVAL: The string format or the parameter name is invalid
+ * -ERANGE: The parameter value is out of range for the given parameter
+ */
+int iq_params_parse(struct iq_params *params, const char *arg)
+{
+ unsigned int *val_uint;
+ const char *value;
+ unsigned int size;
+ char *endp;
+
+ value = strchr(arg, '=');
+ if (value == NULL)
+ return -EINVAL;
+
+ size = value - arg;
+ value++;
+
+ if (strncmp(arg, "mean-level", size) == 0) {
+ params->mean_level = strtof(value, &endp);
+ if (*endp != '\0')
+ return -EINVAL;
+
+ if (params->mean_level <= 0 || params-> mean_level >= 1)
+ return -ERANGE;
+
+ return 0;
+ }
+
+ if (strncmp(arg, "exposure-def", size) == 0)
+ val_uint = &params->exposure;
+ else if (strncmp(arg, "exposure-min", size) == 0)
+ val_uint = &params->exposure_min;
+ else if (strncmp(arg, "exposure-max", size) == 0)
+ val_uint = &params->exposure_max;
+ else if (strncmp(arg, "gain-def", size) == 0)
+ val_uint = &params->gain;
+ else if (strncmp(arg, "gain-min", size) == 0)
+ val_uint = &params->gain_min;
+ else if (strncmp(arg, "gain-max", size) == 0)
+ val_uint = &params->gain_max;
+ else
+ return -EINVAL;
+
+ *val_uint = strtoul(value, &endp, 10);
+ if (*endp != '\0')
+ return -EINVAL;
+
+ return 0;
+}
+
+struct iq_tuning *iq_init(struct omap3_isp_device *isp,
+ const struct iq_params *params)
{
struct v4l2_mbus_framefmt format;
struct v4l2_rect window;
@@ -107,18 +179,12 @@ struct iq_tuning *iq_init(struct omap3_isp_device *isp)
iq->isp = isp;
iq->frame_count = 0;
iq->pix_max = (1 << 10) - 1;
- iq->mean_level = 0.15;
- iq->exposure = 1000;
- iq->exposure_min = 10;
- iq->exposure_max = 2000;
- iq->gain = 8;
- iq->gain_min = 8;
- iq->gain_max = 1024;
- iq->black_level = 64;
-
- omap3_isp_sensor_set_gain(isp, iq->gain);
- omap3_isp_sensor_set_exposure(isp, iq->exposure);
- omap3_isp_ccdc_set_black_level(isp, iq->black_level);
+
+ iq->params = *params;
+
+ omap3_isp_sensor_set_gain(isp, iq->params.gain);
+ omap3_isp_sensor_set_exposure(isp, iq->params.exposure);
+ omap3_isp_ccdc_set_black_level(isp, iq->params.black_level);
omap3_isp_stats_get_format(isp, &format);
window.left = 0;
@@ -126,7 +192,7 @@ struct iq_tuning *iq_init(struct omap3_isp_device *isp)
window.width = format.width;
window.height = format.height;
- omap3_isp_aewb_configure(isp, &window, iq->pix_max - iq->black_level - 1);
+ omap3_isp_aewb_configure(isp, &window, iq->pix_max - iq->params.black_level - 1);
omap3_isp_stats_enable(isp, true);
return iq;
diff --git a/iq.h b/iq.h
index aeb29de..2b043a8 100644
--- a/iq.h
+++ b/iq.h
@@ -27,9 +27,39 @@ struct iq_tuning;
struct omap3_isp_device;
struct omap3_isp_aewb_stats;
+/**
+ * struct iq_params - Image quality tuning parameters
+ * @mean_level: Target mean luminance level (fraction of the maximum)
+ * @exposure: Initial exposure value (sensor-specific units)
+ * @exposure_min: Minimum exposure value
+ * @exposure_max: Maximum exposure value
+ * @gain: Initial gain value (sensor-specific units)
+ * @gain_min: Minimum gain value
+ * @gain_max: Maximum gain value
+ * @black_level: Black level offset
+ */
+struct iq_params {
+ float mean_level;
+
+ unsigned int exposure;
+ unsigned int exposure_min;
+ unsigned int exposure_max;
+
+ unsigned int gain;
+ unsigned int gain_min;
+ unsigned int gain_max;
+
+ unsigned int black_level;
+};
+
void iq_aewb_process(struct iq_tuning *iq,
const struct omap3_isp_aewb_stats *stats);
-struct iq_tuning *iq_init(struct omap3_isp_device *isp);
+
+void iq_params_init(struct iq_params *params);
+int iq_params_parse(struct iq_params *params, const char *arg);
+
+struct iq_tuning *iq_init(struct omap3_isp_device *isp,
+ const struct iq_params *params);
void iq_cleanup(struct iq_tuning *iq);
#endif
diff --git a/live.c b/live.c
index 0144372..68b9b42 100644
--- a/live.c
+++ b/live.c
@@ -325,9 +325,21 @@ static void usage(const char *argv0)
printf("-b, --buffers n Use n display buffers\n");
printf("-h, --help Show this help screen\n");
printf("-s, --skip n Skip display of n frames out of n+1\n");
+ printf(" --aewb param=value Set AEWB algorithm parameter 'param' to 'value'\n");
+ printf("\nSupported AEWB parameters are:\n");
+ printf("- exposure-def Exposure time default value\n");
+ printf("- exposure-min Exposure time minimum value\n");
+ printf("- exposure-max Exposure time maximum value\n");
+ printf("- gain-def Sensor gain default value\n");
+ printf("- gain-min Sensor gain minimum value\n");
+ printf("- gain-max Sensor gain maximum value\n");
+ printf("- mean-level Mean luminance target level (float [0-1])\n");
}
+#define OPT_AEWB_PARAM 256
+
static struct option opts[] = {
+ { "aewb", 1, 0, OPT_AEWB_PARAM },
{ "help", 0, 0, 'h' },
{ "skip", 1, 0, 's' },
{ 0, 0, 0, 0 }
@@ -339,6 +351,7 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu
struct v4l2_buffers_pool *pool = NULL;
struct v4l2_pix_format format;
struct timespec start, end;
+ struct iq_params iq_params;
unsigned int buffers = 3;
struct v4l2_rect rect;
int exit_code = EXIT_FAILURE;
@@ -347,6 +360,8 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu
int ret;
int c;
+ iq_params_init(&iq_params);
+
while ((c = getopt_long(argc, argv, "b:hs:", opts, NULL)) != -1) {
switch (c) {
case 'b':
@@ -358,6 +373,15 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu
case 's':
frame_skip = atoi(optarg);
break;
+ case OPT_AEWB_PARAM:
+ ret = iq_params_parse(&iq_params, optarg);
+ if (ret < 0) {
+ printf("%s AEWB argument %s.\n",
+ ret == -ERANGE ? "out-of-range" : "invalid",
+ optarg);
+ return 1;
+ }
+ break;
default:
printf("Invalid option -%c\n", c);
printf("Run %s -h for help.\n", argv[0]);
@@ -401,7 +425,7 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu
printf("viewfinder configured for %04x %ux%u\n",
view_format.code, view_format.width, view_format.height);
- iq = iq_init(isp);
+ iq = iq_init(isp, &iq_params);
if (iq == NULL) {
printf("error: unable to initialize image quality tuning\n");
goto cleanup;
diff --git a/snapshot.c b/snapshot.c
index 59da5b5..6b5d84e 100644
--- a/snapshot.c
+++ b/snapshot.c
@@ -400,9 +400,21 @@ static void usage(const char *argv0)
printf("-S, --save Save snapshots to disk\n");
printf("-s, --size wxh Set the snapshot capture size\n");
printf("-v, --view Enable viewfinder\n");
+ printf(" --aewb param=value Set AEWB algorithm parameter 'param' to 'value'\n");
+ printf("\nSupported AEWB parameters are:\n");
+ printf("- exposure-def Exposure time default value\n");
+ printf("- exposure-min Exposure time minimum value\n");
+ printf("- exposure-max Exposure time maximum value\n");
+ printf("- gain-def Sensor gain default value\n");
+ printf("- gain-min Sensor gain minimum value\n");
+ printf("- gain-max Sensor gain maximum value\n");
+ printf("- mean-level Mean luminance target level (float [0-1])\n");
}
+#define OPT_AEWB_PARAM 256
+
static struct option opts[] = {
+ { "aewb", 1, 0, OPT_AEWB_PARAM },
{ "crop", 1, 0, 'c' },
{ "format", 1, 0, 'f' },
{ "help", 0, 0, 'h' },
@@ -421,6 +433,7 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu
struct omap3_isp_device *isp = NULL;
struct omap3_isp_operations ops;
struct timespec start, end;
+ struct iq_params iq_params;
int exit_code = EXIT_FAILURE;
float fps;
int ret;
@@ -430,6 +443,8 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu
snap.format.width = SNAPSHOT_WIDTH;
snap.format.height = SNAPSHOT_HEIGHT;
+ iq_params_init(&iq_params);
+
while ((c = getopt_long(argc, argv, "c:f:hi:k:N:n:Ss:v", opts, NULL)) != -1) {
switch (c) {
case 'c':
@@ -485,6 +500,15 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu
vf.enabled = true;
snap.trigger = SNAPSHOT_TRIGGER_MANUAL;
break;
+ case OPT_AEWB_PARAM:
+ ret = iq_params_parse(&iq_params, optarg);
+ if (ret < 0) {
+ printf("%s AEWB argument %s.\n",
+ ret == -ERANGE ? "out-of-range" : "invalid",
+ optarg);
+ return 1;
+ }
+ break;
default:
printf("Invalid option -%c\n", c);
printf("Run %s -h for help.\n", argv[0]);
@@ -524,7 +548,7 @@ int main(int argc __attribute__((__unused__)), char *argv[] __attribute__((__unu
if (ret < 0)
goto cleanup;
- iq = iq_init(isp);
+ iq = iq_init(isp, &iq_params);
if (iq == NULL) {
printf("error: unable to initialize image quality tuning\n");
goto cleanup;