From 3d67598ec94a17ed9cefbcf7e163670c1d1b84de Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 11 Mar 2016 22:12:25 -0800 Subject: [PATCH] GUAC-236: Parse command-line arguments. --- src/guacenc/Makefile.am | 2 ++ src/guacenc/guacenc.c | 80 ++++++++++++++++++++++++++++++++++------- src/guacenc/parse.c | 72 +++++++++++++++++++++++++++++++++++++ src/guacenc/parse.h | 71 ++++++++++++++++++++++++++++++++++++ 4 files changed, 212 insertions(+), 13 deletions(-) create mode 100644 src/guacenc/parse.c create mode 100644 src/guacenc/parse.h diff --git a/src/guacenc/Makefile.am b/src/guacenc/Makefile.am index 9a9015a5..e22c86fb 100644 --- a/src/guacenc/Makefile.am +++ b/src/guacenc/Makefile.am @@ -34,6 +34,7 @@ noinst_HEADERS = \ jpeg.h \ layer.h \ log.h \ + parse.h \ png.h \ video.h @@ -65,6 +66,7 @@ guacenc_SOURCES = \ jpeg.c \ layer.c \ log.c \ + parse.c \ png.c \ video.c diff --git a/src/guacenc/guacenc.c b/src/guacenc/guacenc.c index 997e7497..1286bbab 100644 --- a/src/guacenc/guacenc.c +++ b/src/guacenc/guacenc.c @@ -25,23 +25,17 @@ #include "encode.h" #include "guacenc.h" #include "log.h" +#include "parse.h" #include +#include +#include + int main(int argc, char* argv[]) { int i; - /* Log start */ - guacenc_log(GUAC_LOG_INFO, "Guacamole video encoder (guacenc) " - "version " VERSION); - - /* Abort if no files given */ - if (argc <= 1) { - guacenc_log(GUAC_LOG_INFO, "No input files specified. Nothing to do."); - return 0; - } - /* Load defaults */ const char* codec = GUACENC_DEFAULT_CODEC; const char* suffix = GUACENC_DEFAULT_SUFFIX; @@ -49,17 +43,65 @@ int main(int argc, char* argv[]) { int height = GUACENC_DEFAULT_HEIGHT; int bitrate = GUACENC_DEFAULT_BITRATE; - /* TODO: Override defaults via command-line arguments */ + /* Parse arguments */ + int opt; + while ((opt = getopt(argc, argv, "V:s:d:r:")) != -1) { + + /* -V: Video codec */ + if (opt == 'V') + codec = optarg; + + /* -s: Output file suffix */ + else if (opt == 's') + suffix = optarg; + + /* -d: Dimensions */ + else if (opt == 'd') { + if (guacenc_parse_dimensions(optarg, &width, &height)) { + guacenc_log(GUAC_LOG_ERROR, "Invalid dimensions."); + goto invalid_options; + } + } + + /* -r: Bitrate (bits per second) */ + else if (opt == 'r') { + if (guacenc_parse_int(optarg, &bitrate)) { + guacenc_log(GUAC_LOG_ERROR, "Invalid bitrate."); + goto invalid_options; + } + } + + /* Invalid option */ + else { + goto invalid_options; + } + + } + + /* Log start */ + guacenc_log(GUAC_LOG_INFO, "Guacamole video encoder (guacenc) " + "version " VERSION); + + guacenc_log(GUAC_LOG_INFO, "Video will be encoded as \"%s\" at %ix%i " + "and %i bps.", codec, width, height, bitrate); + + guacenc_log(GUAC_LOG_INFO, "Output files will end with \".%s\".", suffix); /* Prepare libavcodec */ avcodec_register_all(); /* Track number of overall failures */ - int total_files = argc - 1; + int total_files = argc - optind; int failures = 0; + /* Abort if no files given */ + if (total_files <= 0) { + guacenc_log(GUAC_LOG_INFO, "No input files specified. Nothing to do."); + return 0; + } + /* Encode all input files */ - for (i = 1; i < argc; i++) { + for (i = optind; i < argc; i++) { /* Get current filename */ const char* path = argv[i]; @@ -98,5 +140,17 @@ int main(int argc, char* argv[]) { /* Encoding complete */ return 0; + /* Display usage and exit with error if options are invalid */ +invalid_options: + + fprintf(stderr, "USAGE: %s" + " [-d WIDTHxHEIGHT]" + " [-s SUFFIX]" + " [-V CODEC]" + " [-b BITRATE]" + " [-f]\n", argv[0]); + + return 1; + } diff --git a/src/guacenc/parse.c b/src/guacenc/parse.c new file mode 100644 index 00000000..689ba94e --- /dev/null +++ b/src/guacenc/parse.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2016 Glyptodon, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include +#include + +int guacenc_parse_int(char* arg, int* i) { + + char* end; + + /* Parse string as an integer */ + errno = 0; + long int value = strtol(arg, &end, 10); + + /* Ignore number if invalid / non-positive */ + if (errno != 0 || value <= 0 || value > INT_MAX || *end != '\0') + return 1; + + /* Store value */ + *i = value; + + /* Parsing successful */ + return 0; + +} + +int guacenc_parse_dimensions(char* arg, int* width, int* height) { + + /* Locate the 'x' within the dimensions string */ + char* x = strchr(arg, 'x'); + if (x == NULL) + return 1; + + /* Replace 'x' with a null terminator */ + *x = '\0'; + + /* Parse width and height */ + int w, h; + if (guacenc_parse_int(arg, &w) || guacenc_parse_int(x+1, &h)) + return 1; + + /* Width and height are both valid */ + *width = w; + *height = h; + + return 0; + +} + diff --git a/src/guacenc/parse.h b/src/guacenc/parse.h new file mode 100644 index 00000000..09dc0df8 --- /dev/null +++ b/src/guacenc/parse.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2016 Glyptodon, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef GUACENC_PARSE_H +#define GUACENC_PARSE_H + +#include "config.h" + +/** + * Parses a string into a single integer. Only positive integers are accepted. + * The input string may be modified during parsing. A value will be stored in + * the provided int pointer only if valid. + * + * @param arg + * The string to parse. + * + * @param i + * A pointer to the integer in which the parsed value of the given string + * should be stored. + * + * @return + * Zero if parsing was successful, non-zero if the provided string was + * invalid. + */ +int guacenc_parse_int(char* arg, int* i); + +/** + * Parses a string of the form WIDTHxHEIGHT into individual width and height + * integers. The input string may be modified during parsing. Values will be + * stored in the provided width and height pointers only if the given + * dimensions are valid. + * + * @param arg + * The string to parse. + * + * @param width + * A pointer to the integer in which the parsed width component of the + * given string should be stored. + * + * @param height + * A pointer to the integer in which the parsed height component of the + * given string should be stored. + * + * @return + * Zero if parsing was successful, non-zero if the provided string was + * invalid. + */ +int guacenc_parse_dimensions(char* arg, int* width, int* height); + +#endif + +