From 4d82b59bb3d3c4d41033f263ca45d026c65323a8 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Fri, 10 May 2024 15:25:17 +0200 Subject: [PATCH] parse_bitrate: use also for hd-rum-transcode --- src/hd-rum-translator/hd-rum-translator.cpp | 20 ++--- src/host.cpp | 83 ++++++++++++++++++++- src/host.h | 3 +- src/main.cpp | 55 -------------- 4 files changed, 89 insertions(+), 72 deletions(-) diff --git a/src/hd-rum-translator/hd-rum-translator.cpp b/src/hd-rum-translator/hd-rum-translator.cpp index 309acf553..987ebce80 100644 --- a/src/hd-rum-translator/hd-rum-translator.cpp +++ b/src/hd-rum-translator/hd-rum-translator.cpp @@ -575,7 +575,7 @@ struct host_opts { int mtu; char *compression; char *fec; - int64_t bitrate; + long long int bitrate; int force_ip_version; }; @@ -775,20 +775,10 @@ parse_fmt(int argc, char **argv, parsed->hosts[parsed->host_count].fec = optarg; break; case 'l': - if (strcmp(optarg, "unlimited") == 0) { - parsed->hosts[parsed->host_count].bitrate = - RATE_UNLIMITED; - } else if (strcmp(optarg, "auto") == 0) { - parsed->hosts[parsed->host_count].bitrate = RATE_AUTO; - } else { - parsed->hosts[parsed->host_count].bitrate = - unit_evaluate(optarg, nullptr); - if (parsed->hosts[parsed->host_count].bitrate <= 0) { - MSG(FATAL, - "Error: wrong bitrate - %s\n", - optarg); - return -1; - } + if (!parse_bitrate( + optarg, &parsed->hosts[parsed->host_count] + .bitrate)) { + return -1; } break; case '4': diff --git a/src/host.cpp b/src/host.cpp index 066298dad..17e763de7 100644 --- a/src/host.cpp +++ b/src/host.cpp @@ -6,7 +6,7 @@ * This file contains common external definitions. */ /* - * Copyright (c) 2013-2023 CESNET, z. s. p. o. + * Copyright (c) 2013-2024 CESNET * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -968,6 +968,87 @@ bool parse_params(const char *optarg, bool preinit) return true; } +bool +parse_bitrate(char *optarg, long long int *bitrate) +{ + unordered_map bitrate_spec_map = { + {"auto", RATE_AUTO }, + { "dynamic", RATE_DYNAMIC }, + { "unlimited", RATE_UNLIMITED}, + }; + + if (auto it = bitrate_spec_map.find(optarg); + it != bitrate_spec_map.end()) { + *bitrate = it->second; + return true; + } + if (strcmp(optarg, "help") == 0) { + constexpr char const *NUMERIC_PATTERN = "{1-9}{0-9}*[kMG][!][E]"; + col() + << "Usage:\n" + << "\tuv " << TERM_BOLD "-l [auto | dynamic | unlimited | " + << NUMERIC_PATTERN << "]\n" TERM_RESET + << "where\n" + "\t" + << TBOLD("auto") + << " - spread packets across frame time\n" + "\t" + << TBOLD("dynamic") + << " - similar to \"auto\" but more relaxed - occasional " + "huge frame can spread 1.5x frame time (default)\n" + "\t" + << TBOLD("unlimited") + << " - send packets at a wire speed (in bursts)\n" + "\t" + << SBOLD(NUMERIC_PATTERN) + << " - send packets at most at specified bitrate\n\n" + << TBOLD("Notes: ") + << "Use an exclamation mark to indicate intentionally very " + "low bitrate. 'E' to use the value as a fixed bitrate, " + "not cap /i. e. even the frames that may be sent at " + "lower bitrate are sent at the nominal bitrate)\n" + << "\n"; + return true; + } + bool force = false; + bool fixed = false; + for (int i = 0; i < 2; ++i) { + if (optarg[strlen(optarg) - 1] == '!' || + optarg[strlen(optarg) - 1] == 'E') { + if (optarg[strlen(optarg) - 1] == '!') { + force = true; + optarg[strlen(optarg) - 1] = '\0'; + } + if (optarg[strlen(optarg) - 1] == 'E') { + fixed = true; + optarg[strlen(optarg) - 1] = '\0'; + } + } + } + *bitrate = unit_evaluate(optarg, nullptr); + if (*bitrate <= 0) { + log_msg(LOG_LEVEL_ERROR, "Invalid bitrate %s!\n", optarg); + return false; + } + constexpr long long mb5 = + 5ll * 1000 * + 1000; // it'll take 6.4 sec to send 4 MB frame at 5 Mbps + constexpr long long gb100 = + 100ll * 1000 * 1000 * + 1000; // traffic shaping to eg. 40 Gbps may make sense + if ((*bitrate < mb5 || *bitrate > gb100) && !force) { + log_msg(LOG_LEVEL_WARNING, + "Bitrate %lld bps seems to be too %s, use \"-l %s!\" " + "to force if this is not a mistake.\n", + *bitrate, *bitrate < mb5 ? "low" : "high", optarg); + return false; + } + if (fixed) { + *bitrate |= RATE_FLAG_FIXED_RATE; + } + return true; +} + void print_param_doc() { for (unsigned int i = 0; i < sizeof params / sizeof params[0]; ++i) { diff --git a/src/host.h b/src/host.h index 495d6df56..5d934656b 100644 --- a/src/host.h +++ b/src/host.h @@ -12,7 +12,7 @@ * This file contains common (global) variables and functions. */ /* - * Copyright (c) 2005-2023 CESNET z.s.p.o. + * Copyright (c) 2005-2024, CESNET * * Redistribution and use in source and binary forms, with or without * modification, is permitted provided that the following conditions @@ -150,6 +150,7 @@ bool tok_in_argv(char **argv, const char *tok); int set_audio_capture_format(const char *optarg); int set_pixfmt_conv_policy(const char *optarg); bool parse_params(const char *optarg, bool preinit); +bool parse_bitrate(char *optarg, long long int *bitrate); void print_pixel_formats(void); void print_video_codecs(void); void register_param(const char *param, const char *doc); diff --git a/src/main.cpp b/src/main.cpp index 9ea116178..e68a41c00 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -367,61 +367,6 @@ static void *capture_thread(void *arg) return NULL; } -static bool parse_bitrate(char *optarg, long long int *bitrate) { - map bitrate_spec_map = { - { "auto", RATE_AUTO }, - { "dynamic", RATE_DYNAMIC }, - { "unlimited", RATE_UNLIMITED }, - }; - - if (auto it = bitrate_spec_map.find(optarg); it != bitrate_spec_map.end()) { - *bitrate = it->second; - return true; - } - if (strcmp(optarg, "help") == 0) { -# define NUMERIC_PATTERN "{1-9}{0-9}*[kMG][!][E]" - col() << "Usage:\n" << - "\tuv " << TERM_BOLD "-l [auto | dynamic | unlimited | " << NUMERIC_PATTERN << "]\n" TERM_RESET << - "where\n" - "\t" << TBOLD("auto") << " - spread packets across frame time\n" - "\t" << TBOLD("dynamic") << " - similar to \"auto\" but more relaxed - occasional huge frame can spread 1.5x frame time (default)\n" - "\t" << TBOLD("unlimited") << " - send packets at a wire speed (in bursts)\n" - "\t" << TBOLD(NUMERIC_PATTERN) << " - send packets at most at specified bitrate\n\n" << - TBOLD("Notes: ") << "Use an exclamation mark to indicate intentionally very low bitrate. 'E' to use the value as a fixed bitrate, not cap /i. e. even the frames that may be sent at lower bitrate are sent at the nominal bitrate)\n" << - "\n"; - return true; - } - bool force = false, fixed = false; - for (int i = 0; i < 2; ++i) { - if (optarg[strlen(optarg) - 1] == '!' || - optarg[strlen(optarg) - 1] == 'E') { - if (optarg[strlen(optarg) - 1] == '!') { - force = true; - optarg[strlen(optarg) - 1] = '\0'; - } - if (optarg[strlen(optarg) - 1] == 'E') { - fixed = true; - optarg[strlen(optarg) - 1] = '\0'; - } - } - } - *bitrate = unit_evaluate(optarg, nullptr); - if (*bitrate <= 0) { - log_msg(LOG_LEVEL_ERROR, "Invalid bitrate %s!\n", optarg); - return false; - } - long long mb5 = 5ll * 1000 * 1000, // it'll take 6.4 sec to send 4 MB frame at 5 Mbps - gb100 = 100ll * 1000 * 1000 * 1000; // traffic shaping to eg. 40 Gbps may make sense - if ((*bitrate < mb5 || *bitrate > gb100) && !force) { - log_msg(LOG_LEVEL_WARNING, "Bitrate %lld bps seems to be too %s, use \"-l %s!\" to force if this is not a mistake.\n", *bitrate, *bitrate < mb5 ? "low" : "high", optarg); - return false; - } - if (fixed) { - *bitrate |= RATE_FLAG_FIXED_RATE; - } - return true; -} - /// @retval <0 return code whose absolute value will be returned from main() /// @retval 0 success /// @retval 1 device list was printed