From f030d07589524d07d5eaf7c2dfff607656889b8b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 16 Mar 2012 15:48:30 +0100 Subject: iq: Make the IQ parameters configurable Signed-off-by: Laurent Pinchart --- iq.c | 134 +++++++++++++++++++++++++++++++++++++++++++++---------------- iq.h | 32 ++++++++++++++- live.c | 26 +++++++++++- snapshot.c | 26 +++++++++++- 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 = ¶ms->exposure; + else if (strncmp(arg, "exposure-min", size) == 0) + val_uint = ¶ms->exposure_min; + else if (strncmp(arg, "exposure-max", size) == 0) + val_uint = ¶ms->exposure_max; + else if (strncmp(arg, "gain-def", size) == 0) + val_uint = ¶ms->gain; + else if (strncmp(arg, "gain-min", size) == 0) + val_uint = ¶ms->gain_min; + else if (strncmp(arg, "gain-max", size) == 0) + val_uint = ¶ms->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; -- cgit v1.2.3