Ctrl K
ComunidadGuías…

server/src/video_policy.cpp

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#include "video_policy.h"

#include <algorithm>
#include <cctype>
#include <numeric>

namespace video::policy {
  namespace {
    bool equals_case_insensitive(std::string_view left, std::string_view right) {
      return left.size() == right.size() && std::equal(
        left.begin(),
        left.end(),
        right.begin(),
        [](const char lhs, const char rhs) {
          return std::tolower(static_cast<unsigned char>(lhs)) ==
                 std::tolower(static_cast<unsigned char>(rhs));
        }
      );
    }
  }  // namespace

  bool may_apply_process_display_preference(const capture_selection_e selection) {
    return selection == capture_selection_e::process_preferred;
  }

  std::optional<std::string> select_manual_display_output(
    const capture_selection_e selection,
    const int requested_index,
    const std::span<const std::string> display_names
  ) {
    if (selection != capture_selection_e::process_preferred ||
        requested_index < 0 || display_names.empty()) {
      return std::nullopt;
    }

    const auto index = std::clamp(requested_index, 0, static_cast<int>(display_names.size()) - 1);
    return display_names[static_cast<std::size_t>(index)];
  }

  std::optional<int> resolve_display_output(
    const std::string_view output_identity,
    const std::span<const std::string> display_names
  ) {
    const auto found = std::find_if(display_names.begin(), display_names.end(), [&](const std::string &name) {
      return equals_case_insensitive(name, output_identity);
    });
    if (found == display_names.end()) {
      return std::nullopt;
    }
    return static_cast<int>(std::distance(display_names.begin(), found));
  }

  std::chrono::milliseconds display_retry_delay(const std::size_t consecutive_failures) {
    constexpr auto initial_delay = std::chrono::milliseconds {50};
    constexpr auto maximum_delay = std::chrono::milliseconds {2000};
    constexpr std::size_t maximum_shift = 6;
    const auto shift = std::min(consecutive_failures, maximum_shift);
    const auto multiplier = static_cast<std::chrono::milliseconds::rep>(std::size_t {1} << shift);
    return std::min(initial_delay * multiplier, maximum_delay);
  }

  bool should_log_display_retry(const std::size_t consecutive_failures) {
    return consecutive_failures == 0 || (consecutive_failures & (consecutive_failures - 1)) == 0;
  }

  rational_t framerate_x100_to_rational(std::int32_t value) {
    if (value % 2997 == 0) return {(value / 2997) * 30000, 1001};
    if (value == 2397 || value == 2398) return {24000, 1001};
    const auto divisor = std::gcd(value, 100);
    return {value / divisor, 100 / divisor};
  }

  std::optional<std::string> select_encoder(
    std::span<const std::string_view> preference,
    encoder_requirements_t requirements,
    const encoder_capability_provider_t &provider
  ) {
    for (const auto name : preference) {
      const auto caps = provider.capabilities(name);
      if (caps.available && (!requirements.hdr || caps.hdr) && (!requirements.yuv444 || caps.yuv444)) {
        return std::string(name);
      }
    }
    return std::nullopt;
  }

  std::optional<std::string> select_preferred_virtual_output(
    std::string_view configured_output,
    std::span<const std::string> active_virtual_outputs,
    std::span<const std::string> all_virtual_outputs
  ) {
    const auto find_configured = [&](std::span<const std::string> outputs) -> std::optional<std::string> {
      if (configured_output.empty()) {
        return std::nullopt;
      }
      const auto found = std::find_if(outputs.begin(), outputs.end(), [&](const std::string &output) {
        return equals_case_insensitive(output, configured_output);
      });
      return found == outputs.end() ? std::nullopt : std::optional<std::string> {*found};
    };

    if (auto configured = find_configured(active_virtual_outputs)) {
      return configured;
    }
    if (auto configured = find_configured(all_virtual_outputs)) {
      return configured;
    }
    if (!active_virtual_outputs.empty()) {
      return active_virtual_outputs.front();
    }
    if (!all_virtual_outputs.empty()) {
      return all_virtual_outputs.front();
    }
    return std::nullopt;
  }
}  // namespace video::policy