diff --git a/cmd/camera-streamer.c b/cmd/camera-streamer.c index 82ca7a0..c405f13 100644 --- a/cmd/camera-streamer.c +++ b/cmd/camera-streamer.c @@ -102,6 +102,7 @@ camera_options_t camera_options = { .auto_reconnect = 0, .auto_focus = true, .options = "", + .list_options = false, .h264 = { .options = "video_bitrate_mode=0" OPTION_VALUE_LIST_SEP @@ -153,30 +154,31 @@ option_value_t camera_type[] = { }; option_t all_options[] = { - DEFINE_OPTION_PTR(camera, path, string), - DEFINE_OPTION(camera, width, uint), - DEFINE_OPTION(camera, height, uint), - DEFINE_OPTION_VALUES(camera, format, camera_formats), - DEFINE_OPTION(camera, nbufs, uint), - DEFINE_OPTION_VALUES(camera, type, camera_type), - DEFINE_OPTION(camera, fps, uint), - DEFINE_OPTION_DEFAULT(camera, allow_dma, bool, "1"), - DEFINE_OPTION(camera, high_res_factor, float), - DEFINE_OPTION(camera, low_res_factor, float), - DEFINE_OPTION_PTR(camera, options, list), - DEFINE_OPTION(camera, auto_reconnect, uint), - DEFINE_OPTION_DEFAULT(camera, auto_focus, bool, "1"), + DEFINE_OPTION_PTR(camera, path, string, "Chooses the camera to use."), + DEFINE_OPTION(camera, width, uint, "Set the camera capture width."), + DEFINE_OPTION(camera, height, uint, "Set the camera capture height."), + DEFINE_OPTION_VALUES(camera, format, camera_formats, "Set the camera capture format."), + DEFINE_OPTION(camera, nbufs, uint, "Set number of capture buffers. Preferred 2 or 3."), + DEFINE_OPTION_VALUES(camera, type, camera_type, "Select camera capture."), + DEFINE_OPTION(camera, fps, uint, "Set the desired capture framerate."), + DEFINE_OPTION_DEFAULT(camera, allow_dma, bool, "1", "Prefer to use DMA access to reduce memory copy."), + DEFINE_OPTION(camera, high_res_factor, float, "Set the desired high resolution output scale factor."), + DEFINE_OPTION(camera, low_res_factor, float, "Set the desired low resolution output scale factor."), + DEFINE_OPTION_PTR(camera, options, list, "Set the camera options. List all available options with `-camera-list_options`."), + DEFINE_OPTION(camera, auto_reconnect, uint, "Set the camera auto-reconnect delay in seconds."), + DEFINE_OPTION_DEFAULT(camera, auto_focus, bool, "1", "Do auto-focus on start-up."), - DEFINE_OPTION_PTR(camera, isp.options, list), - DEFINE_OPTION_PTR(camera, jpeg.options, list), - DEFINE_OPTION_PTR(camera, h264.options, list), + DEFINE_OPTION_PTR(camera, isp.options, list, "Set the ISP processing options. List all available options with `-camera-list_options`."), + DEFINE_OPTION_PTR(camera, jpeg.options, list, "Set the JPEG compression options. List all available options with `-camera-list_options`."), + DEFINE_OPTION_PTR(camera, h264.options, list, "Set the H264 encoding options. List all available options with `-camera-list_options`."), + DEFINE_OPTION_DEFAULT(camera, list_options, bool, "1", "List all available options and exit."), - DEFINE_OPTION(http, port, uint), - DEFINE_OPTION(http, maxcons, uint), + DEFINE_OPTION(http, port, uint, "Set the HTTP web-server port."), + DEFINE_OPTION(http, maxcons, uint, "Set maximum number of concurrent HTTP connections."), - DEFINE_OPTION_DEFAULT(log, debug, bool, "1"), - DEFINE_OPTION_DEFAULT(log, verbose, bool, "1"), - DEFINE_OPTION_PTR(log, filter, list), + DEFINE_OPTION_DEFAULT(log, debug, bool, "1", "Enable debug logging."), + DEFINE_OPTION_DEFAULT(log, verbose, bool, "1", "Enable verbose logging."), + DEFINE_OPTION_PTR(log, filter, list, "Enable debug logging from the given files. Ex.: `-log-filter=buffer.cc`"), {} }; @@ -190,6 +192,18 @@ int main(int argc, char *argv[]) return -1; } + if (camera_options.list_options) { + camera = camera_open(&camera_options); + if (camera) { + printf("\n"); + for (int i = 0; i < MAX_DEVICES; i++) { + device_dump_options(camera->devices[i], stdout); + } + camera_close(&camera); + } + return -1; + } + http_fd = http_server(&http_options, http_methods); if (http_fd < 0) { goto error; diff --git a/device/camera/camera.h b/device/camera/camera.h index 4ceaa67..cbd47a1 100644 --- a/device/camera/camera.h +++ b/device/camera/camera.h @@ -26,6 +26,7 @@ typedef struct camera_options_s { unsigned auto_reconnect; char options[CAMERA_OPTIONS_LENGTH]; + bool list_options; struct { char options[CAMERA_OPTIONS_LENGTH]; diff --git a/opts/opts.c b/opts/opts.c index 7350cb7..c2fd104 100644 --- a/opts/opts.c +++ b/opts/opts.c @@ -5,29 +5,75 @@ #include #include -static void print_help(option_t *options) +#define OPT_LENGTH 30 + +static void print_help(option_t *options, const char *cmd) { + printf("Usage:\n"); + printf("$ %s \n", cmd); + printf("\n"); + + printf("Options:\n"); for (int i = 0; options[i].name; i++) { option_t *option = &options[i]; + int len = 0; - printf("%40s\t", option->name); + len += printf(" -%s", option->name); + if (option->default_value) { + len += printf("[=%s]", option->default_value); + } else if (option->value_mapping) { + len += printf("=arg"); + } else { + len += printf("=%s", option->format); + } + if (len < OPT_LENGTH) { + printf("%*s", OPT_LENGTH-len, " "); + } + + printf("- %s", option->description); + if (option->value_mapping) { + printf(" Values: "); + for (int j = 0; option->value_mapping[j].name; j++) { + if (j > 0) printf(", "); + printf("%s", option->value_mapping[j].name); + } + printf("."); + } + printf("\n"); + } + printf("\n"); + + printf("Configuration:\n"); + for (int i = 0; options[i].name; i++) { + option_t *option = &options[i]; + int len = 0; if (option->value_list) { char *string = option->value_list; char *token; - int tokens = 0; + + if (!*string) + continue; while ((token = strsep(&string, OPTION_VALUE_LIST_SEP)) != NULL) { - if (tokens++ > 0) - printf("\n%40s\t", ""); - printf("%s", token); + len = printf(" -%s=", option->name); + if (len < OPT_LENGTH) { + printf("%*s", OPT_LENGTH-len, " "); + } + printf("%s\n", token); } - - if (!tokens) - printf("(none)"); } else if (option->value_string) { + len += printf(" -%s=", option->name); + if (len < OPT_LENGTH) { + printf("%*s", OPT_LENGTH-len, " "); + } printf(option->format, option->value_string); + printf("\n"); } else { + len += printf(" -%s=", option->name); + if (len < OPT_LENGTH) { + printf("%*s", OPT_LENGTH-len, " "); + } if (option->value_mapping) { for (int j = 0; option->value_mapping[j].name; j++) { if (option->value_mapping[j].value == *option->value) { @@ -39,10 +85,10 @@ static void print_help(option_t *options) unsigned mask = UINT_MAX >> ((sizeof(*option->value) - option->size) * 8); printf(option->format, *option->value & mask); + printf("\n"); } - - printf("\n"); } + printf("\n"); } static int parse_opt(option_t *options, const char *key) @@ -116,7 +162,7 @@ int parse_opts(option_t *options, int argc, char *argv[]) } if (!strcmp(key, "help")) { - print_help(options); + print_help(options, argv[0]); return -1; } diff --git a/opts/opts.h b/opts/opts.h index 265ede5..19c7da0 100644 --- a/opts/opts.h +++ b/opts/opts.h @@ -23,6 +23,7 @@ typedef struct options_s { option_value_t *value_mapping; unsigned size; const char *default_value; + const char *description; } option_t; #define OPTION_VALUE_LIST_SEP ";" @@ -34,38 +35,42 @@ typedef struct options_s { #define OPTION_FORMAT_string "%s" #define OPTION_FORMAT_list "%s" -#define DEFINE_OPTION(_section, _name, _type) \ +#define DEFINE_OPTION(_section, _name, _type, _desc) \ { \ .name = #_section "-" #_name, \ .value_##_type = &_section##_options._name, \ .format = OPTION_FORMAT_##_type, \ .size = sizeof(_section##_options._name), \ + .description = _desc, \ } -#define DEFINE_OPTION_DEFAULT(_section, _name, _type, _default_value) \ +#define DEFINE_OPTION_DEFAULT(_section, _name, _type, _default_value, _desc) \ { \ .name = #_section "-" #_name, \ .value_##_type = &_section##_options._name, \ .format = OPTION_FORMAT_##_type, \ .size = sizeof(_section##_options._name), \ .default_value = _default_value, \ + .description = _desc, \ } -#define DEFINE_OPTION_VALUES(_section, _name, _value_mapping) \ +#define DEFINE_OPTION_VALUES(_section, _name, _value_mapping, _desc) \ { \ .name = #_section "-" #_name, \ .value_hex = &_section##_options._name, \ .format = OPTION_FORMAT_hex, \ .value_mapping = _value_mapping, \ .size = sizeof(_section##_options._name), \ + .description = _desc, \ } -#define DEFINE_OPTION_PTR(_section, _name, _type) \ +#define DEFINE_OPTION_PTR(_section, _name, _type, _desc) \ { \ .name = #_section "-" #_name, \ .value_##_type = _section##_options._name, \ .format = OPTION_FORMAT_##_type, \ .size = sizeof(_section##_options._name), \ + .description = _desc, \ } int parse_opts(option_t *options, int argc, char *argv[]);