options to reset image settings to default

This commit is contained in:
Devaev Maxim
2020-02-19 08:04:50 +03:00
parent dfc98a67f2
commit 9353b3474a
3 changed files with 135 additions and 52 deletions

View File

@@ -77,9 +77,10 @@ static int _device_open_mmap(struct device_t *dev);
static int _device_open_queue_buffers(struct device_t *dev); static int _device_open_queue_buffers(struct device_t *dev);
static void _device_open_alloc_picbufs(struct device_t *dev); static void _device_open_alloc_picbufs(struct device_t *dev);
static int _device_apply_resolution(struct device_t *dev, unsigned width, unsigned height); static int _device_apply_resolution(struct device_t *dev, unsigned width, unsigned height);
static void _device_apply_controls(struct device_t *dev); static void _device_apply_controls(struct device_t *dev);
static int _device_check_control(struct device_t *dev, const char *name, unsigned cid, int value, bool quiet); static int _device_query_control(struct device_t *dev, struct v4l2_queryctrl *query, const char *name, unsigned cid, bool quiet);
static void _device_set_control(struct device_t *dev, const char *name, unsigned cid, int value, bool quiet); static void _device_set_control(struct device_t *dev, struct v4l2_queryctrl *query, const char *name, unsigned cid, int value, bool quiet);
static const char *_format_to_string_fourcc(char *buf, size_t size, unsigned format); static const char *_format_to_string_fourcc(char *buf, size_t size, unsigned format);
static const char *_format_to_string_nullable(unsigned format); static const char *_format_to_string_nullable(unsigned format);
@@ -610,65 +611,81 @@ static int _device_apply_resolution(struct device_t *dev, unsigned width, unsign
} }
static void _device_apply_controls(struct device_t *dev) { static void _device_apply_controls(struct device_t *dev) {
# define SET_CID(_cid, _dest, _value, _quiet) { \ # define SET_CID_VALUE(_cid, _field, _value, _quiet) { \
if (_device_check_control(dev, #_dest, _cid, _value, _quiet) == 0) { \ struct v4l2_queryctrl query; \
_device_set_control(dev, #_dest, _cid, _value, _quiet); \ if (_device_query_control(dev, &query, #_field, _cid, _quiet) == 0) { \
_device_set_control(dev, &query, #_field, _cid, _value, _quiet); \
} \ } \
} }
# define SET_CID_MANUAL(_cid, _dest) { \ # define SET_CID_DEFAULT(_cid, _field, _quiet) { \
if (dev->ctl._dest.value_set) { \ struct v4l2_queryctrl query; \
SET_CID(_cid, _dest, dev->ctl._dest.value, false); \ if (_device_query_control(dev, &query, #_field, _cid, _quiet) == 0) { \
_device_set_control(dev, &query, #_field, _cid, query.default_value, _quiet); \
} \ } \
} }
# define SET_CID_AUTO(_cid_auto, _cid_manual, _dest) { \ # define CONTROL_MANUAL_CID(_cid, _field) { \
if (dev->ctl._dest.value_set || dev->ctl._dest.auto_set) { \ if (dev->ctl._field.value_set) { \
SET_CID(_cid_auto, _dest##_auto, dev->ctl._dest.auto_set, dev->ctl._dest.value_set); \ SET_CID_VALUE(_cid, _field, dev->ctl._field.value, false); \
SET_CID_MANUAL(_cid_manual, _dest); \ } else if (dev->ctl._field.default_set) { \
SET_CID_DEFAULT(_cid, _field, false); \
} \ } \
} }
SET_CID_AUTO (V4L2_CID_AUTOBRIGHTNESS, V4L2_CID_BRIGHTNESS, brightness); # define CONTROL_AUTO_CID(_cid_auto, _cid_manual, _field) { \
SET_CID_MANUAL ( V4L2_CID_CONTRAST, contrast); if (dev->ctl._field.value_set) { \
SET_CID_MANUAL ( V4L2_CID_SATURATION, saturation); SET_CID_VALUE(_cid_auto, _field##_auto, 0, true); \
SET_CID_AUTO (V4L2_CID_HUE_AUTO, V4L2_CID_HUE, hue); SET_CID_VALUE(_cid_manual, _field, dev->ctl._field.value, false); \
SET_CID_MANUAL ( V4L2_CID_GAMMA, gamma); } else if (dev->ctl._field.auto_set) { \
SET_CID_MANUAL ( V4L2_CID_SHARPNESS, sharpness); SET_CID_VALUE(_cid_auto, _field##_auto, 1, false); \
SET_CID_MANUAL ( V4L2_CID_BACKLIGHT_COMPENSATION, backlight_compensation); } else if (dev->ctl._field.default_set) { \
SET_CID_AUTO (V4L2_CID_AUTO_WHITE_BALANCE, V4L2_CID_WHITE_BALANCE_TEMPERATURE, white_balance); SET_CID_VALUE(_cid_auto, _field##_auto, 0, true); /* Reset inactive flag */ \
SET_CID_AUTO (V4L2_CID_AUTOGAIN, V4L2_CID_GAIN, gain); SET_CID_DEFAULT(_cid_manual, _field, false); \
SET_CID_DEFAULT(_cid_auto, _field##_auto, false); \
} \
}
# undef SET_CID_AUTO CONTROL_AUTO_CID (V4L2_CID_AUTOBRIGHTNESS, V4L2_CID_BRIGHTNESS, brightness);
# undef SET_CID_MANUAL CONTROL_MANUAL_CID ( V4L2_CID_CONTRAST, contrast);
# undef SET_CID CONTROL_MANUAL_CID ( V4L2_CID_SATURATION, saturation);
CONTROL_AUTO_CID (V4L2_CID_HUE_AUTO, V4L2_CID_HUE, hue);
CONTROL_MANUAL_CID ( V4L2_CID_GAMMA, gamma);
CONTROL_MANUAL_CID ( V4L2_CID_SHARPNESS, sharpness);
CONTROL_MANUAL_CID ( V4L2_CID_BACKLIGHT_COMPENSATION, backlight_compensation);
CONTROL_AUTO_CID (V4L2_CID_AUTO_WHITE_BALANCE, V4L2_CID_WHITE_BALANCE_TEMPERATURE, white_balance);
CONTROL_AUTO_CID (V4L2_CID_AUTOGAIN, V4L2_CID_GAIN, gain);
# undef CONTROL_AUTO_CID
# undef CONTROL_MANUAL_CID
# undef SET_CID_DEFAULT
# undef SET_CID_VALUE
} }
static int _device_check_control(struct device_t *dev, const char *name, unsigned cid, int value, bool quiet) { static int _device_query_control(struct device_t *dev, struct v4l2_queryctrl *query, const char *name, unsigned cid, bool quiet) {
struct v4l2_queryctrl query; MEMSET_ZERO(*query);
query->id = cid;
MEMSET_ZERO(query); if (xioctl(dev->run->fd, VIDIOC_QUERYCTRL, query) < 0 || query->flags & V4L2_CTRL_FLAG_DISABLED) {
query.id = cid;
if (xioctl(dev->run->fd, VIDIOC_QUERYCTRL, &query) < 0 || query.flags & V4L2_CTRL_FLAG_DISABLED) {
if (!quiet) { if (!quiet) {
LOG_ERROR("Changing control %s is unsupported", name); LOG_ERROR("Changing control %s is unsupported", name);
} }
return -1; return -1;
} }
if (value < query.minimum || value > query.maximum || value % query.step != 0) {
if (!quiet) {
LOG_ERROR("Invalid value %d of control %s: min=%d, max=%d, default=%d, step=%u",
value, name, query.minimum, query.maximum, query.default_value, query.step);
}
return -2;
}
return 0; return 0;
} }
static void _device_set_control(struct device_t *dev, const char *name, unsigned cid, int value, bool quiet) { static void _device_set_control(struct device_t *dev, struct v4l2_queryctrl *query, const char *name, unsigned cid, int value, bool quiet) {
struct v4l2_control ctl; struct v4l2_control ctl;
if (value < query->minimum || value > query->maximum || value % query->step != 0) {
if (!quiet) {
LOG_ERROR("Invalid value %d of control %s: min=%d, max=%d, default=%d, step=%u",
value, name, query->minimum, query->maximum, query->default_value, query->step);
}
return;
}
MEMSET_ZERO(ctl); MEMSET_ZERO(ctl);
ctl.id = cid; ctl.id = cid;
ctl.value = value; ctl.value = value;
@@ -678,7 +695,7 @@ static void _device_set_control(struct device_t *dev, const char *name, unsigned
LOG_PERROR("Can't set control %s", name); LOG_PERROR("Can't set control %s", name);
} }
} else if (!quiet) { } else if (!quiet) {
LOG_INFO("Using control %s: %d", name, ctl.value); LOG_INFO("Applying control %s: %d", name, ctl.value);
} }
} }

View File

@@ -68,6 +68,7 @@ struct control_t {
int value; int value;
bool value_set; bool value_set;
bool auto_set; bool auto_set;
bool default_set;
}; };
struct controls_t { struct controls_t {

View File

@@ -80,19 +80,29 @@ enum _OPT_VALUES {
_O_DEVICE_TIMEOUT = 10000, _O_DEVICE_TIMEOUT = 10000,
_O_DEVICE_ERROR_DELAY, _O_DEVICE_ERROR_DELAY,
_O_IMAGE_DEFAULT,
_O_BRIGHTNESS, _O_BRIGHTNESS,
_O_BRIGHTNESS_AUTO, _O_BRIGHTNESS_AUTO,
_O_BRIGHTNESS_DEFAULT,
_O_CONTRAST, _O_CONTRAST,
_O_CONTRAST_DEFAULT,
_O_SATURATION, _O_SATURATION,
_O_SATURATION_DEFAULT,
_O_HUE, _O_HUE,
_O_HUE_AUTO, _O_HUE_AUTO,
_O_HUE_DEFAULT,
_O_GAMMA, _O_GAMMA,
_O_GAMMA_DEFAULT,
_O_SHARPNESS, _O_SHARPNESS,
_O_SHARPNESS_DEFAULT,
_O_BACKLIGHT_COMPENSATION, _O_BACKLIGHT_COMPENSATION,
_O_BACKLIGHT_COMPENSATION_DEFAULT,
_O_WHITE_BALANCE, _O_WHITE_BALANCE,
_O_WHITE_BALANCE_AUTO, _O_WHITE_BALANCE_AUTO,
_O_WHITE_BALANCE_DEFAULT,
_O_GAIN, _O_GAIN,
_O_GAIN_AUTO, _O_GAIN_AUTO,
_O_GAIN_DEFAULT,
_O_USER, _O_USER,
_O_PASSWD, _O_PASSWD,
@@ -143,19 +153,29 @@ static const struct option _LONG_OPTS[] = {
{"device-timeout", required_argument, NULL, _O_DEVICE_TIMEOUT}, {"device-timeout", required_argument, NULL, _O_DEVICE_TIMEOUT},
{"device-error-delay", required_argument, NULL, _O_DEVICE_ERROR_DELAY}, {"device-error-delay", required_argument, NULL, _O_DEVICE_ERROR_DELAY},
{"image-default", no_argument, NULL, _O_IMAGE_DEFAULT},
{"brightness", required_argument, NULL, _O_BRIGHTNESS}, {"brightness", required_argument, NULL, _O_BRIGHTNESS},
{"brightness-auto", no_argument, NULL, _O_BRIGHTNESS_AUTO}, {"brightness-auto", no_argument, NULL, _O_BRIGHTNESS_AUTO},
{"brightness-default", no_argument, NULL, _O_BRIGHTNESS_DEFAULT},
{"contrast", required_argument, NULL, _O_CONTRAST}, {"contrast", required_argument, NULL, _O_CONTRAST},
{"contrast-default", no_argument, NULL, _O_CONTRAST_DEFAULT},
{"saturation", required_argument, NULL, _O_SATURATION}, {"saturation", required_argument, NULL, _O_SATURATION},
{"saturation-default", no_argument, NULL, _O_SATURATION_DEFAULT},
{"hue", required_argument, NULL, _O_HUE}, {"hue", required_argument, NULL, _O_HUE},
{"hue-auto", no_argument, NULL, _O_HUE_AUTO}, {"hue-auto", no_argument, NULL, _O_HUE_AUTO},
{"hue-default", no_argument, NULL, _O_HUE_DEFAULT},
{"gamma", required_argument, NULL, _O_GAMMA}, {"gamma", required_argument, NULL, _O_GAMMA},
{"gamma-default", no_argument, NULL, _O_GAMMA_DEFAULT},
{"sharpness", required_argument, NULL, _O_SHARPNESS}, {"sharpness", required_argument, NULL, _O_SHARPNESS},
{"sharpness-default", no_argument, NULL, _O_SHARPNESS_DEFAULT},
{"backlight-compensation", required_argument, NULL, _O_BACKLIGHT_COMPENSATION}, {"backlight-compensation", required_argument, NULL, _O_BACKLIGHT_COMPENSATION},
{"backlight-compensation-default", no_argument, NULL, _O_BACKLIGHT_COMPENSATION_DEFAULT},
{"white-balance", required_argument, NULL, _O_WHITE_BALANCE}, {"white-balance", required_argument, NULL, _O_WHITE_BALANCE},
{"white-balance-auto", no_argument, NULL, _O_WHITE_BALANCE_AUTO}, {"white-balance-auto", no_argument, NULL, _O_WHITE_BALANCE_AUTO},
{"white-balance-default", no_argument, NULL, _O_WHITE_BALANCE_DEFAULT},
{"gain", required_argument, NULL, _O_GAIN}, {"gain", required_argument, NULL, _O_GAIN},
{"gain-auto", no_argument, NULL, _O_GAIN_AUTO}, {"gain-auto", no_argument, NULL, _O_GAIN_AUTO},
{"gain-default", no_argument, NULL, _O_GAIN_DEFAULT},
{"host", required_argument, NULL, _O_HOST}, {"host", required_argument, NULL, _O_HOST},
{"port", required_argument, NULL, _O_PORT}, {"port", required_argument, NULL, _O_PORT},
@@ -278,6 +298,7 @@ int options_parse(struct options_t *options, struct device_t *dev, struct encode
# define OPT_CTL(_dest) { \ # define OPT_CTL(_dest) { \
dev->ctl._dest.value_set = true; \ dev->ctl._dest.value_set = true; \
dev->ctl._dest.auto_set = false; \ dev->ctl._dest.auto_set = false; \
dev->ctl._dest.default_set = false; \
OPT_NUMBER("--"#_dest, dev->ctl._dest.value, INT_MIN, INT_MAX, 0); \ OPT_NUMBER("--"#_dest, dev->ctl._dest.value, INT_MIN, INT_MAX, 0); \
break; \ break; \
} }
@@ -285,6 +306,18 @@ int options_parse(struct options_t *options, struct device_t *dev, struct encode
# define OPT_CTL_AUTO(_dest) { \ # define OPT_CTL_AUTO(_dest) { \
dev->ctl._dest.value_set = false; \ dev->ctl._dest.value_set = false; \
dev->ctl._dest.auto_set = true; \ dev->ctl._dest.auto_set = true; \
dev->ctl._dest.default_set = false; \
break; \
}
# define OPT_CTL_DEFAULT_NOBREAK(_dest) { \
dev->ctl._dest.value_set = false; \
dev->ctl._dest.auto_set = false; \
dev->ctl._dest.default_set = true; \
}
# define OPT_CTL_DEFAULT(_dest) { \
OPT_CTL_DEFAULT_NOBREAK(_dest); \
break; \ break; \
} }
@@ -335,19 +368,39 @@ int options_parse(struct options_t *options, struct device_t *dev, struct encode
case _O_DEVICE_TIMEOUT: OPT_NUMBER("--device-timeout", dev->timeout, 1, 60, 0); case _O_DEVICE_TIMEOUT: OPT_NUMBER("--device-timeout", dev->timeout, 1, 60, 0);
case _O_DEVICE_ERROR_DELAY: OPT_NUMBER("--device-error-delay", dev->error_delay, 1, 60, 0); case _O_DEVICE_ERROR_DELAY: OPT_NUMBER("--device-error-delay", dev->error_delay, 1, 60, 0);
case _O_IMAGE_DEFAULT:
OPT_CTL_DEFAULT_NOBREAK(brightness);
OPT_CTL_DEFAULT_NOBREAK(contrast);
OPT_CTL_DEFAULT_NOBREAK(saturation);
OPT_CTL_DEFAULT_NOBREAK(hue);
OPT_CTL_DEFAULT_NOBREAK(gamma);
OPT_CTL_DEFAULT_NOBREAK(sharpness);
OPT_CTL_DEFAULT_NOBREAK(backlight_compensation);
OPT_CTL_DEFAULT_NOBREAK(white_balance);
OPT_CTL_DEFAULT_NOBREAK(gain);
break;
case _O_BRIGHTNESS: OPT_CTL(brightness); case _O_BRIGHTNESS: OPT_CTL(brightness);
case _O_BRIGHTNESS_AUTO: OPT_CTL_AUTO(brightness); case _O_BRIGHTNESS_AUTO: OPT_CTL_AUTO(brightness);
case _O_BRIGHTNESS_DEFAULT: OPT_CTL_DEFAULT(brightness);
case _O_CONTRAST: OPT_CTL(contrast); case _O_CONTRAST: OPT_CTL(contrast);
case _O_CONTRAST_DEFAULT: OPT_CTL_DEFAULT(contrast);
case _O_SATURATION: OPT_CTL(saturation); case _O_SATURATION: OPT_CTL(saturation);
case _O_SATURATION_DEFAULT: OPT_CTL_DEFAULT(saturation);
case _O_HUE: OPT_CTL(hue); case _O_HUE: OPT_CTL(hue);
case _O_HUE_AUTO: OPT_CTL_AUTO(hue); case _O_HUE_AUTO: OPT_CTL_AUTO(hue);
case _O_HUE_DEFAULT: OPT_CTL_DEFAULT(hue);
case _O_GAMMA: OPT_CTL(gamma); case _O_GAMMA: OPT_CTL(gamma);
case _O_GAMMA_DEFAULT: OPT_CTL_DEFAULT(gamma);
case _O_SHARPNESS: OPT_CTL(sharpness); case _O_SHARPNESS: OPT_CTL(sharpness);
case _O_SHARPNESS_DEFAULT: OPT_CTL_DEFAULT(sharpness);
case _O_BACKLIGHT_COMPENSATION: OPT_CTL(backlight_compensation); case _O_BACKLIGHT_COMPENSATION: OPT_CTL(backlight_compensation);
case _O_BACKLIGHT_COMPENSATION_DEFAULT: OPT_CTL_DEFAULT(backlight_compensation);
case _O_WHITE_BALANCE: OPT_CTL(white_balance); case _O_WHITE_BALANCE: OPT_CTL(white_balance);
case _O_WHITE_BALANCE_AUTO: OPT_CTL_AUTO(white_balance); case _O_WHITE_BALANCE_AUTO: OPT_CTL_AUTO(white_balance);
case _O_WHITE_BALANCE_DEFAULT: OPT_CTL_DEFAULT(white_balance);
case _O_GAIN: OPT_CTL(gain); case _O_GAIN: OPT_CTL(gain);
case _O_GAIN_AUTO: OPT_CTL_AUTO(gain); case _O_GAIN_AUTO: OPT_CTL_AUTO(gain);
case _O_GAIN_DEFAULT: OPT_CTL_DEFAULT(gain);
case _O_HOST: OPT_SET(server->host, optarg); case _O_HOST: OPT_SET(server->host, optarg);
case _O_PORT: OPT_NUMBER("--port", server->port, 1, 65535, 0); case _O_PORT: OPT_NUMBER("--port", server->port, 1, 65535, 0);
@@ -404,6 +457,8 @@ int options_parse(struct options_t *options, struct device_t *dev, struct encode
} }
# endif # endif
# undef OPT_CTL_DEFAULT
# undef OPT_CTL_DEFAULT_NOBREAK
# undef OPT_CTL_AUTO # undef OPT_CTL_AUTO
# undef OPT_CTL # undef OPT_CTL
# undef OPT_PARSE # undef OPT_PARSE
@@ -562,19 +617,29 @@ static void _help(struct device_t *dev, struct encoder_t *encoder, struct http_s
printf(" after an error (timeout for example). Default: %u.\n\n", dev->error_delay); printf(" after an error (timeout for example). Default: %u.\n\n", dev->error_delay);
printf("Image control options:\n"); printf("Image control options:\n");
printf("══════════════════════\n"); printf("══════════════════════\n");
printf(" --brightness <N> ───────────── Set brightness. Default: no change.\n\n"); printf(" --image-default ────────────────── Reset all image settings bellow to default. Default: no change.\n\n");
printf(" --brightness-auto ──────────── Enable automatic brightness control. Default: no change.\n\n"); printf(" --brightness <N> ───────────────── Set brightness. Default: no change.\n");
printf(" --contrast <N> ─────────────── Set contrast. Default: no change.\n\n"); printf(" --brightness-auto ──────────────── Enable automatic brightness control. Default: no change.\n");
printf(" --saturation <N> ───────────── Set saturation. Default: no change.\n\n"); printf(" --brightness-default ───────────── Set default brightness. Default: no change.\n\n");
printf(" --hue <N> ─────────────────── Set hue. Default: no change.\n\n"); printf(" --contrast <N> ─────────────────── Set contrast. Default: no change.\n");
printf(" --hue-auto ─────────────────── Enable automatic hue control. Default: no change.\n\n"); printf(" --contrast-default ─────────────── Set default contrast. Default: no change.\n\n");
printf(" --gamma <N> ───────────────── Set gamma. Default: no change.\n\n"); printf(" --saturation <N> ───────────────── Set saturation. Default: no change.\n");
printf(" --sharpness <N> ───────────── Set sharpness. Default: no change.\n\n"); printf(" --saturation-default ───────────── Set default saturation. Default: no change.\n\n");
printf(" --backlight-compensation <N> ─ Set backlight compensation. Default: no change.\n\n"); printf(" --hue <N> ──────────────────────── Set hue. Default: no change.\n");
printf(" --white-balance <N> ────────── Set white balance. Default: no change.\n\n"); printf(" --hue-auto ─────────────────────── Enable automatic hue control. Default: no change.\n");
printf(" --white-balance-auto ───────── Enable automatic white balance control. Default: no change.\n\n"); printf(" --hue-default ──────────────────── Set default hue. Default: no change.\n\n");
printf(" --gain <N> ─────────────────── Set gain. Default: no change.\n\n"); printf(" --gamma <N> ────────────────────── Set gamma. Default: no change.\n");
printf(" --gain-auto ────────────────── Enable automatic gain control. Default: no change.\n\n"); printf(" --gamma-default ────────────────── Set default gamma. Default: no change.\n\n");
printf(" --sharpness <N> ────────────────── Set sharpness. Default: no change.\n");
printf(" --sharpness-default ────────────── Set default sharpness. Default: no change.\n\n");
printf(" --backlight-compensation <N> ───── Set backlight compensation. Default: no change.\n");
printf(" --backlight-compensation-default ─ Set default backlight compensation. Default: no change.\n\n");
printf(" --white-balance <N> ────────────── Set white balance. Default: no change.\n");
printf(" --white-balance-auto ───────────── Enable automatic white balance control. Default: no change.\n");
printf(" --white-balance-default ────────── Set default white balance. Default: no change.\n\n");
printf(" --gain <N> ─────────────────────── Set gain. Default: no change.\n");
printf(" --gain-auto ────────────────────── Enable automatic gain control. Default: no change.\n\n");
printf(" --gain-default ─────────────────── Set default gain. Default: no change.\n\n");
printf("HTTP server options:\n"); printf("HTTP server options:\n");
printf("════════════════════\n"); printf("════════════════════\n");
printf(" -s|--host <address> ──────── Listen on Hostname or IP. Default: %s.\n\n", server->host); printf(" -s|--host <address> ──────── Listen on Hostname or IP. Default: %s.\n\n", server->host);