big controls refactoring

This commit is contained in:
Devaev Maxim
2019-03-12 23:46:19 +03:00
parent 22be6443ef
commit 8a2a0474b2
3 changed files with 158 additions and 125 deletions

View File

@@ -69,7 +69,9 @@ static int _device_open_mmap(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 int _device_apply_resolution(struct device_t *dev, unsigned width, unsigned height);
static void _device_apply_image_settings(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 void _device_set_control(struct device_t *dev, 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_nullable(unsigned format);
@@ -78,11 +80,11 @@ static const char *_standard_to_string(v4l2_std_id standard);
struct device_t *device_init() {
struct image_settings_t *img;
struct controls_t *ctl;
struct device_runtime_t *run;
struct device_t *dev;
A_CALLOC(img, 1);
A_CALLOC(ctl, 1);
A_CALLOC(run, 1);
run->fd = -1;
@@ -97,14 +99,14 @@ struct device_t *device_init() {
dev->n_workers = dev->n_buffers;
dev->timeout = 1;
dev->error_delay = 1;
dev->img = img;
dev->ctl = ctl;
dev->run = run;
return dev;
}
void device_destroy(struct device_t *dev) {
free(dev->run);
free(dev->img);
free(dev->ctl);
free(dev);
}
@@ -149,7 +151,7 @@ int device_open(struct device_t *dev) {
goto error;
}
_device_open_alloc_picbufs(dev);
_device_apply_image_settings(dev);
_device_apply_controls(dev);
LOG_DEBUG("Device fd=%d initialized", dev->run->fd);
return 0;
@@ -460,38 +462,23 @@ static int _device_apply_resolution(struct device_t *dev, unsigned width, unsign
return 0;
}
static void _device_apply_image_settings(struct device_t *dev) {
struct v4l2_queryctrl query;
struct v4l2_control ctl;
# define SET_CID(_cid, _dest) { \
MEMSET_ZERO(query); query.id = _cid; \
if (xioctl(dev->run->fd, VIDIOC_QUERYCTRL, &query) < 0 || query.flags & V4L2_CTRL_FLAG_DISABLED) { \
LOG_INFO("Changing image " #_dest " is unsupported"); \
} else { \
MEMSET_ZERO(ctl); ctl.id = _cid; ctl.value = (int)dev->img->_dest; \
if (ctl.value < query.minimum || ctl.value > query.maximum || ctl.value % query.step != 0) { \
LOG_ERROR("Invalid value %d for image " #_dest ": min=%d, max=%d, default=%d, step=%u", \
ctl.value, query.minimum, query.maximum, query.default_value, query.step); \
} else { \
if (xioctl(dev->run->fd, VIDIOC_S_CTRL, &ctl) < 0) { \
LOG_PERROR("Can't set image " #_dest); \
} else { \
LOG_INFO("Using image " #_dest ": %d (min=%d, max=%d, default=%d, step=%u)", \
ctl.value, query.minimum, query.maximum, query.default_value, query.step); \
} \
} \
static void _device_apply_controls(struct device_t *dev) {
# define SET_CID(_cid, _dest, _value, _quiet) { \
if (_device_check_control(dev, #_dest, _cid, _value, _quiet) == 0) { \
_device_set_control(dev, #_dest, _cid, _value, _quiet); \
} \
}
# define SET_CID_MANUAL(_cid, _dest) { \
if (dev->img->_dest##_set) { SET_CID(_cid, _dest); } \
if (dev->ctl->_dest.value_set) { \
SET_CID(_cid, _dest, dev->ctl->_dest.value, false); \
} \
}
# define SET_CID_AUTO(_cid_auto, _cid_manual, _dest) { \
if (dev->img->_dest##_set) { \
SET_CID(_cid_auto, _dest##_auto); \
if (!dev->img->_dest##_auto) { SET_CID(_cid_manual, _dest); } \
if (dev->ctl->_dest.value_set || dev->ctl->_dest.auto_set) { \
SET_CID(_cid_auto, _dest##_auto, dev->ctl->_dest.auto_set, dev->ctl->_dest.value_set); \
SET_CID_MANUAL(_cid_manual, _dest); \
} \
}
@@ -510,6 +497,44 @@ static void _device_apply_image_settings(struct device_t *dev) {
# undef SET_CID
}
static int _device_check_control(struct device_t *dev, const char *name, unsigned cid, int value, bool quiet) {
struct v4l2_queryctrl query;
MEMSET_ZERO(query);
query.id = cid;
if (xioctl(dev->run->fd, VIDIOC_QUERYCTRL, &query) < 0 || query.flags & V4L2_CTRL_FLAG_DISABLED) {
if (!quiet) {
LOG_ERROR("Changing control %s is unsupported", name);
}
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;
}
static void _device_set_control(struct device_t *dev, const char *name, unsigned cid, int value, bool quiet) {
struct v4l2_control ctl;
MEMSET_ZERO(ctl);
ctl.id = cid;
ctl.value = value;
if (xioctl(dev->run->fd, VIDIOC_S_CTRL, &ctl) < 0) {
if (!quiet) {
LOG_PERROR("Can't set control %s", name);
}
} else if (!quiet) {
LOG_INFO("Using control %s: %d", name, ctl.value);
}
}
static const char *_format_to_string_fourcc(char *buf, size_t size, unsigned format) {
assert(size >= 8);
buf[0] = format & 0x7F;

View File

@@ -69,23 +69,23 @@ struct device_runtime_t {
bool capturing;
};
#define S_MANUAL(_dest) int _dest; bool _dest##_set;
#define S_AUTO(_dest) int _dest; bool _dest##_set; bool _dest##_auto;
struct image_settings_t {
S_AUTO (brightness);
S_MANUAL (contrast);
S_MANUAL (saturation);
S_AUTO (hue);
S_MANUAL (gamma);
S_MANUAL (sharpness);
S_MANUAL (backlight_compensation);
S_AUTO (white_balance);
S_AUTO (gain);
struct control_t {
int value;
bool value_set;
bool auto_set;
};
#undef S_AUTO
#undef S_MANUAL
struct controls_t {
struct control_t brightness;
struct control_t contrast;
struct control_t saturation;
struct control_t hue;
struct control_t gamma;
struct control_t sharpness;
struct control_t backlight_compensation;
struct control_t white_balance;
struct control_t gain;
};
struct device_t {
char *path;
@@ -103,7 +103,7 @@ struct device_t {
unsigned timeout;
unsigned error_delay;
struct image_settings_t *img;
struct controls_t *ctl;
struct device_runtime_t *run;
sig_atomic_t volatile stop;

View File

@@ -43,53 +43,53 @@
static const char _short_opts[] = "d:i:x:y:m:a:f:z:tb:w:q:c:s:p:u:ro:e:h";
static const struct option _long_opts[] = {
{"device", required_argument, NULL, 'd'},
{"input", required_argument, NULL, 'i'},
{"width", required_argument, NULL, 'x'},
{"height", required_argument, NULL, 'y'},
{"format", required_argument, NULL, 'm'},
{"tv-standard", required_argument, NULL, 'a'},
{"desired-fps", required_argument, NULL, 'f'},
{"min-frame-size", required_argument, NULL, 'z'},
{"dv-timings", no_argument, NULL, 't'},
{"buffers", required_argument, NULL, 'b'},
{"workers", required_argument, NULL, 'w'},
{"quality", required_argument, NULL, 'q'},
{"encoder", required_argument, NULL, 'c'},
{"device-timeout", required_argument, NULL, 1000},
{"device-persistent", no_argument, NULL, 1001},
{"device-error-delay", required_argument, NULL, 1002},
{"device", required_argument, NULL, 'd'},
{"input", required_argument, NULL, 'i'},
{"width", required_argument, NULL, 'x'},
{"height", required_argument, NULL, 'y'},
{"format", required_argument, NULL, 'm'},
{"tv-standard", required_argument, NULL, 'a'},
{"desired-fps", required_argument, NULL, 'f'},
{"min-frame-size", required_argument, NULL, 'z'},
{"dv-timings", no_argument, NULL, 't'},
{"buffers", required_argument, NULL, 'b'},
{"workers", required_argument, NULL, 'w'},
{"quality", required_argument, NULL, 'q'},
{"encoder", required_argument, NULL, 'c'},
{"device-timeout", required_argument, NULL, 1000},
{"device-persistent", no_argument, NULL, 1001},
{"device-error-delay", required_argument, NULL, 1002},
{"image-brightness", required_argument, NULL, 2000},
{"image-brightness-auto", no_argument, NULL, 2001},
{"image-contrast", required_argument, NULL, 2002},
{"image-saturation", required_argument, NULL, 2003},
{"image-hue", required_argument, NULL, 2004},
{"image-hue-auto", no_argument, NULL, 2005},
{"image-gamma", required_argument, NULL, 2006},
{"image-sharpness", required_argument, NULL, 2007},
{"image-backlight-compensation", required_argument, NULL, 2008},
{"image-white-balance", required_argument, NULL, 2009},
{"image-white-balance-auto", no_argument, NULL, 2010},
{"image-gain", required_argument, NULL, 2011},
{"image-gain-auto", no_argument, NULL, 2012},
{"brightness", required_argument, NULL, 2000},
{"brightness-auto", no_argument, NULL, 2001},
{"contrast", required_argument, NULL, 2002},
{"saturation", required_argument, NULL, 2003},
{"hue", required_argument, NULL, 2004},
{"hue-auto", no_argument, NULL, 2005},
{"gamma", required_argument, NULL, 2006},
{"sharpness", required_argument, NULL, 2007},
{"backlight-compensation", required_argument, NULL, 2008},
{"white-balance", required_argument, NULL, 2009},
{"white-balance-auto", no_argument, NULL, 2010},
{"gain", required_argument, NULL, 2011},
{"gain-auto", no_argument, NULL, 2012},
{"host", required_argument, NULL, 's'},
{"port", required_argument, NULL, 'p'},
{"unix", required_argument, NULL, 'u'},
{"unix-rm", no_argument, NULL, 'r'},
{"unix-mode", required_argument, NULL, 'o'},
{"drop-same-frames", required_argument, NULL, 'e'},
{"fake-width", required_argument, NULL, 3001},
{"fake-height", required_argument, NULL, 3002},
{"server-timeout", required_argument, NULL, 3003},
{"host", required_argument, NULL, 's'},
{"port", required_argument, NULL, 'p'},
{"unix", required_argument, NULL, 'u'},
{"unix-rm", no_argument, NULL, 'r'},
{"unix-mode", required_argument, NULL, 'o'},
{"drop-same-frames", required_argument, NULL, 'e'},
{"fake-width", required_argument, NULL, 3001},
{"fake-height", required_argument, NULL, 3002},
{"server-timeout", required_argument, NULL, 3003},
{"perf", no_argument, NULL, 5000},
{"verbose", no_argument, NULL, 5001},
{"debug", no_argument, NULL, 5002},
{"log-level", required_argument, NULL, 5010},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 6000},
{"perf", no_argument, NULL, 5000},
{"verbose", no_argument, NULL, 5001},
{"debug", no_argument, NULL, 5002},
{"log-level", required_argument, NULL, 5010},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 6000},
{NULL, 0, NULL, 0},
};
@@ -136,21 +136,21 @@ static void _help(struct device_t *dev, struct encoder_t *encoder, struct http_s
printf(" --device-persistent -- Don't re-initialize device on timeout. Default: disabled.\n\n");
printf(" --device-error-delay <seconds> -- Delay before trying to connect to the device again\n");
printf(" after a timeout. Default: %u\n\n", dev->error_delay);
printf("Image options:\n");
printf("Image control options:\n");
printf("---------------\n");
printf(" --image-brightness <N> -- Set brightness. Default: no change.\n\n");
printf(" --image-brightness-auto -- Enable automatic brightness control. Default: no change.\n\n");
printf(" --image-contrast <N> -- Set contrast. Default: no change.\n\n");
printf(" --image-saturation <N> -- Set saturation. Default: no change.\n\n");
printf(" --image-hue <N> -- Set hue. Default: no change.\n\n");
printf(" --image-hue-auto -- Enable automatic hue control. Default: no change.\n\n");
printf(" --image-gamma <N> -- Set gamma. Default: no change.\n\n");
printf(" --image-sharpness <N> -- Set sharpness. Default: no change.\n\n");
printf(" --image-backlight-compensation <N> -- Set backlight compensation. Default: no change.\n\n");
printf(" --image-white-balance <N> -- Set white balance. Default: no change.\n\n");
printf(" --image-white-balance-auto -- Enable automatic white balance control. Default: no change.\n\n");
printf(" --image-gain <N> -- Set gain. Default: no change.\n\n");
printf(" --image-gain-auto -- Enable automatic gain control. Default: no change.\n\n");
printf(" --brightness <N> -- Set brightness. Default: no change.\n\n");
printf(" --brightness-auto -- Enable automatic brightness control. Default: no change.\n\n");
printf(" --contrast <N> -- Set contrast. Default: no change.\n\n");
printf(" --saturation <N> -- Set saturation. Default: no change.\n\n");
printf(" --hue <N> -- Set hue. Default: no change.\n\n");
printf(" --hue-auto -- Enable automatic hue control. Default: no change.\n\n");
printf(" --gamma <N> -- Set gamma. Default: no change.\n\n");
printf(" --sharpness <N> -- Set sharpness. Default: no change.\n\n");
printf(" --backlight-compensation <N> -- Set backlight compensation. Default: no change.\n\n");
printf(" --white-balance <N> -- Set white balance. Default: no change.\n\n");
printf(" --white-balance-auto -- Enable automatic white balance control. Default: no change.\n\n");
printf(" --gain <N> -- Set gain. Default: no change.\n\n");
printf(" --gain-auto -- Enable automatic gain control. Default: no change.\n\n");
printf("HTTP server options:\n");
printf("--------------------\n");
printf(" -s|--host <address> -- Listen on Hostname or IP. Default: %s\n\n", server->host);
@@ -209,13 +209,21 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct e
break; \
}
# define OPT_CHMOD(_dest, _name) OPT_INT(_dest, _name, 8)
# define OPT_CHMOD(_dest, _name) \
OPT_INT(_dest, _name, 8)
# define OPT_IMG(_dest) \
{ dev->img->_dest##_set = true; OPT_INT(dev->img->_dest, "--image-"#_dest, 10); break; }
# define OPT_CTL(_dest) { \
dev->ctl->_dest.value_set = true; \
dev->ctl->_dest.auto_set = false; \
OPT_INT(dev->ctl->_dest.value, "--"#_dest, 10); \
break; \
}
# define OPT_IMG_AUTO(_dest) \
{ dev->img->_dest##_set = true; dev->img->_dest##_auto = true; break; }
# define OPT_CTL_AUTO(_dest) { \
dev->ctl->_dest.value_set = false; \
dev->ctl->_dest.auto_set = true; \
break; \
}
int index;
int ch;
@@ -243,19 +251,19 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct e
case 1001: OPT_SET(dev->persistent, true);
case 1002: OPT_UNSIGNED(dev->error_delay, "--device-error-delay", 1, 60);
case 2000: OPT_IMG(brightness);
case 2001: OPT_IMG_AUTO(brightness);
case 2002: OPT_IMG(contrast);
case 2003: OPT_IMG(saturation);
case 2004: OPT_IMG(hue);
case 2005: OPT_IMG_AUTO(hue);
case 2006: OPT_IMG(gamma);
case 2007: OPT_IMG(sharpness);
case 2008: OPT_IMG(backlight_compensation);
case 2009: OPT_IMG(white_balance);
case 2010: OPT_IMG_AUTO(white_balance);
case 2011: OPT_IMG(gain);
case 2012: OPT_IMG_AUTO(gain);
case 2000: OPT_CTL(brightness);
case 2001: OPT_CTL_AUTO(brightness);
case 2002: OPT_CTL(contrast);
case 2003: OPT_CTL(saturation);
case 2004: OPT_CTL(hue);
case 2005: OPT_CTL_AUTO(hue);
case 2006: OPT_CTL(gamma);
case 2007: OPT_CTL(sharpness);
case 2008: OPT_CTL(backlight_compensation);
case 2009: OPT_CTL(white_balance);
case 2010: OPT_CTL_AUTO(white_balance);
case 2011: OPT_CTL(gain);
case 2012: OPT_CTL_AUTO(gain);
case 's': OPT_SET(server->host, optarg);
case 'p': OPT_UNSIGNED(server->port, "--port", 1, 65535);
@@ -278,8 +286,8 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct e
}
}
# undef OPT_IMG_AUTO
# undef OPT_IMG
# undef OPT_CTL_AUTO
# undef OPT_CTL
# undef OPT_CHMOD
# undef OPT_INT
# undef OPT_PARSE