From aefc12e40ee0ce2df65977e1cc8f162a618355f3 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 13 Feb 2023 13:13:43 -0800 Subject: [PATCH] media/options: refactor cvar factory completely, ensure correct MIN/MAX order --- src/media/options.cpp | 95 ++++++++++++++++++------------------ src/media/options.hpp | 16 +++--- src/media/options_values.cpp | 36 ++++++-------- 3 files changed, 73 insertions(+), 74 deletions(-) diff --git a/src/media/options.cpp b/src/media/options.cpp index 1a060c847..ae432ddb0 100644 --- a/src/media/options.cpp +++ b/src/media/options.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include @@ -49,60 +49,56 @@ float Options::get(const char* option) const return FixedToFloat(cvar(option).value); } -static consvar_t range_cvar(const char* default_value, int32_t min, int32_t max, int32_t flags = 0) +template +consvar_t Options::values(const char* default_value, const Range range, std::map list) { - return CVAR_INIT( - nullptr, - default_value, - CV_SAVE | flags, - new CV_PossibleValue_t[] {{min, "MIN"}, {max, "MAX"}, {}}, - nullptr - ); -} + constexpr bool is_float = std::is_floating_point_v; -template <> -consvar_t Options::range(const char* default_value, float min, float max) -{ - return range_cvar(default_value, FloatToFixed(min), FloatToFixed(max), CV_FLOAT); -} + const std::size_t min_max_size = (range.min || range.max) ? 2 : 0; + auto* arr = new CV_PossibleValue_t[list.size() + min_max_size + 1]; -template <> -consvar_t Options::range_min(const char* default_value, float min) -{ - return range_cvar(default_value, FloatToFixed(min), INT32_MAX); -} - -template <> -consvar_t Options::range(const char* default_value, int min, int max) -{ - return range_cvar(default_value, min, max); -} - -template <> -consvar_t Options::range_min(const char* default_value, int min) -{ - return range_cvar(default_value, min, INT32_MAX); -} - -template <> -consvar_t Options::value_map(const char* default_value, std::map values) -{ - auto* arr = new CV_PossibleValue_t[values.size() + 1]; - - std::size_t i = 0; - - for (const auto& [k, v] : values) + auto cast = [is_float](T n) { - arr[i].value = v; - arr[i].strvalue = k; + if constexpr (is_float) + { + return FloatToFixed(n); + } + else + { + return n; + } + }; - i++; + if (min_max_size) + { + // Order is very important, MIN then MAX. + arr[0] = {range.min ? cast(*range.min) : INT32_MIN, "MIN"}; + arr[1] = {range.max ? cast(*range.max) : INT32_MAX, "MAX"}; } - arr[i].value = 0; - arr[i].strvalue = nullptr; + { + std::size_t i = min_max_size; - return CVAR_INIT(nullptr, default_value, CV_SAVE, arr, nullptr); + for (const auto& [k, v] : list) + { + arr[i].value = cast(v); + arr[i].strvalue = k.data(); + + i++; + } + + arr[i].value = 0; + arr[i].strvalue = nullptr; + } + + int32_t flags = CV_SAVE; + + if constexpr (is_float) + { + flags |= CV_FLOAT; + } + + return CVAR_INIT(nullptr, default_value, flags, arr, nullptr); } void Options::register_all() @@ -114,3 +110,8 @@ void Options::register_all() cvars_ = {}; } + +// clang-format off +template consvar_t Options::values(const char* default_value, const Range range, std::map list); +template consvar_t Options::values(const char* default_value, const Range range, std::map list); +// clang-format on diff --git a/src/media/options.hpp b/src/media/options.hpp index 5f3022fb6..8aba26e62 100644 --- a/src/media/options.hpp +++ b/src/media/options.hpp @@ -11,7 +11,9 @@ #define __SRB2_MEDIA_OPTIONS_HPP__ #include +#include #include +#include #include #include @@ -25,6 +27,12 @@ class Options public: using map_t = std::unordered_map; + template + struct Range + { + std::optional min, max; + }; + // Registers all options as cvars. static void register_all(); @@ -34,13 +42,7 @@ public: T get(const char* option) const; template - static consvar_t range(const char* default_value, T min, T max); - - template - static consvar_t range_min(const char* default_value, T min); - - template - static consvar_t value_map(const char* default_value, std::map values); + static consvar_t values(const char* default_value, const Range range, std::map list = {}); private: static std::vector cvars_; diff --git a/src/media/options_values.cpp b/src/media/options_values.cpp index 941958633..f6ee474ba 100644 --- a/src/media/options_values.cpp +++ b/src/media/options_values.cpp @@ -26,37 +26,33 @@ std::vector Options::cvars_; // clang-format off const Options VorbisEncoder::options_("vorbis", { - {"quality", Options::range("0", -0.1f, 1.f)}, - {"max_bitrate", Options::range_min("-1", -1)}, - {"nominal_bitrate", Options::range_min("-1", -1)}, - {"min_bitrate", Options::range_min("-1", -1)}, + {"quality", Options::values("0", {-0.1f, 1.f})}, + {"max_bitrate", Options::values("-1", {.min = -1})}, + {"nominal_bitrate", Options::values("-1", {.min = -1})}, + {"min_bitrate", Options::values("-1", {.min = -1})}, }); const Options VP8Encoder::options_("vp8", { - {"quality_mode", Options::value_map("q", { + {"quality_mode", Options::values("q", {}, { {"vbr", VPX_VBR}, {"cbr", VPX_CBR}, {"cq", VPX_CQ}, {"q", VPX_Q}, })}, - {"target_bitrate", Options::range_min("800", 1)}, - {"min_q", Options::range("4", 4, 63)}, - {"max_q", Options::range("55", 4, 63)}, - {"kf_min", Options::range_min("0", 0)}, - {"kf_max", Options::value_map("auto", { + {"target_bitrate", Options::values("800", {.min = 1})}, + {"min_q", Options::values("4", {4, 63})}, + {"max_q", Options::values("55", {4, 63})}, + {"kf_min", Options::values("0", {.min = 0})}, + {"kf_max", Options::values("auto", {.min = 0}, { {"auto", static_cast(KeyFrameOption::kAuto)}, - {"MIN", 0}, - {"MAX", INT32_MAX}, })}, - {"cpu_used", Options::range("0", -16, 16)}, - {"cq_level", Options::range("10", 0, 63)}, - {"deadline", Options::value_map("10", { + {"cpu_used", Options::values("0", {-16, 16})}, + {"cq_level", Options::values("10", {0, 63})}, + {"deadline", Options::values("10", { .min = 1}, { {"infinite", static_cast(DeadlineOption::kInfinite)}, - {"MIN", 1}, - {"MAX", INT32_MAX}, })}, - {"sharpness", Options::range("7", 0, 7)}, - {"token_parts", Options::range("0", 0, 3)}, - {"threads", Options::range_min("1", 1)}, + {"sharpness", Options::values("7", {0, 7})}, + {"token_parts", Options::values("0", {0, 3})}, + {"threads", Options::values("1", {.min = 1})}, }); // clang-format on