yituo_video/src/main.cpp

140 lines
3.7 KiB
C++
Raw Normal View History

2025-09-08 14:55:07 +08:00
// main.cpp
#include "app_config.hpp"
#include "rtsp_manager.hpp"
#include "logger.hpp"
2025-09-08 15:25:59 +08:00
#include "mqtt_client_wrapper.hpp"
#include <thread>
2025-09-08 14:55:07 +08:00
#include <atomic>
#include <csignal>
2025-11-24 14:49:37 +08:00
#include <unistd.h>
2025-09-10 12:49:41 +08:00
#include <chrono>
2025-09-08 14:55:07 +08:00
2025-11-24 14:49:37 +08:00
constexpr bool ENABLE_RTSP_THREAD = true;
constexpr bool ENABLE_MQTT_THREAD = true;
2025-09-10 13:03:16 +08:00
2025-09-08 14:55:07 +08:00
std::atomic<bool> g_running(true);
2025-09-10 12:49:41 +08:00
static void minimal_signal_handler(int signum)
2025-09-08 14:55:07 +08:00
{
2025-09-10 12:49:41 +08:00
g_running.store(false, std::memory_order_relaxed);
const char msg[] = "[MAIN] Signal received, initiating shutdown...\n";
write(STDERR_FILENO, msg, sizeof(msg) - 1);
2025-09-08 14:55:07 +08:00
}
int main()
{
2025-09-10 12:49:41 +08:00
struct sigaction sigAct{};
sigAct.sa_handler = minimal_signal_handler;
sigemptyset(&sigAct.sa_mask);
sigAct.sa_flags = 0;
sigaction(SIGINT, &sigAct, nullptr);
sigaction(SIGTERM, &sigAct, nullptr);
2025-09-08 14:55:07 +08:00
signal(SIGPIPE, SIG_IGN);
2025-09-08 15:32:07 +08:00
Logger::set_log_to_file(get_executable_dir_file_path("app.log"));
2025-09-08 14:55:07 +08:00
try
{
2025-09-08 15:32:07 +08:00
g_app_config = AppConfig::load_from_file(get_executable_dir_file_path("config.json"));
2025-09-08 14:55:07 +08:00
}
catch (const std::exception &e)
{
LOG_ERROR(std::string("Failed to load config: ") + e.what());
return -1;
}
2025-09-10 12:49:41 +08:00
std::atomic<bool> rtsp_thread_exited(false);
std::atomic<bool> mqtt_thread_exited(false);
2025-11-24 14:49:37 +08:00
// 初始化 GStreamer
2025-09-09 11:08:34 +08:00
RTSPManager::init();
2025-09-10 12:55:48 +08:00
std::thread rtsp_thread;
std::thread mqtt_thread;
2025-09-10 12:54:39 +08:00
2025-09-10 13:03:16 +08:00
if (ENABLE_RTSP_THREAD)
{
rtsp_thread = std::thread([&]()
{
RTSPManager::start(g_app_config.cameras);
rtsp_thread_exited.store(true, std::memory_order_relaxed); });
2025-11-24 14:49:37 +08:00
2025-09-10 13:03:16 +08:00
LOG_INFO("[MAIN] RTSP thread started");
}
else
{
2025-11-24 14:49:37 +08:00
LOG_INFO("[MAIN] RTSP thread disabled by toggle");
2025-09-10 13:03:16 +08:00
}
2025-09-10 12:49:41 +08:00
2025-09-10 13:03:16 +08:00
if (ENABLE_MQTT_THREAD)
{
mqtt_thread = std::thread([&]()
{
mqtt_client_thread_func();
mqtt_thread_exited.store(true, std::memory_order_relaxed); });
2025-11-24 14:49:37 +08:00
2025-09-10 13:03:16 +08:00
LOG_INFO("[MAIN] MQTT thread started");
}
else
{
2025-11-24 14:49:37 +08:00
LOG_INFO("[MAIN] MQTT thread disabled by toggle");
2025-09-10 13:03:16 +08:00
}
2025-09-08 15:25:59 +08:00
2025-09-10 12:49:41 +08:00
while (g_running.load(std::memory_order_relaxed))
2025-09-08 15:51:10 +08:00
std::this_thread::sleep_for(std::chrono::milliseconds(200));
2025-09-10 12:49:41 +08:00
LOG_INFO("[MAIN] Shutdown requested, stopping services...");
const auto max_wait = std::chrono::seconds(5);
const auto poll_interval = std::chrono::milliseconds(100);
2025-09-10 13:03:16 +08:00
if (ENABLE_RTSP_THREAD)
2025-09-10 12:49:41 +08:00
{
2025-11-24 14:49:37 +08:00
RTSPManager::stop();
2025-09-10 13:03:16 +08:00
if (rtsp_thread.joinable())
2025-09-10 13:12:27 +08:00
rtsp_thread.join();
2025-11-20 11:06:02 +08:00
LOG_INFO("[MAIN] RTSP thread finished and joined.");
2025-09-10 12:49:41 +08:00
}
2025-11-24 14:49:37 +08:00
auto deadline = std::chrono::steady_clock::now() + max_wait;
2025-09-10 13:03:16 +08:00
if (ENABLE_MQTT_THREAD)
2025-09-10 11:06:42 +08:00
{
2025-09-10 13:03:16 +08:00
while (!mqtt_thread_exited.load(std::memory_order_relaxed) &&
std::chrono::steady_clock::now() < deadline)
2025-09-10 12:49:41 +08:00
{
2025-09-10 13:03:16 +08:00
std::this_thread::sleep_for(poll_interval);
2025-09-10 12:49:41 +08:00
}
2025-09-10 13:03:16 +08:00
if (mqtt_thread.joinable())
2025-09-10 12:49:41 +08:00
{
2025-09-10 13:03:16 +08:00
if (mqtt_thread_exited.load(std::memory_order_relaxed))
{
mqtt_thread.join();
LOG_INFO("[MAIN] MQTT thread finished and joined.");
}
else
{
LOG_WARN("[MAIN] MQTT thread did not exit within timeout.");
}
2025-09-10 12:49:41 +08:00
}
}
2025-09-10 13:03:16 +08:00
bool any_failed = false;
2025-11-24 14:49:37 +08:00
if (ENABLE_RTSP_THREAD && rtsp_thread.joinable() && !rtsp_thread_exited.load())
2025-09-10 13:03:16 +08:00
any_failed = true;
2025-11-24 14:49:37 +08:00
if (ENABLE_MQTT_THREAD && mqtt_thread.joinable() && !mqtt_thread_exited.load())
2025-09-10 13:03:16 +08:00
any_failed = true;
if (any_failed)
2025-09-10 12:49:41 +08:00
{
LOG_ERROR("[MAIN] Threads did not exit in time. Forcing immediate termination.");
2025-09-10 13:03:16 +08:00
_exit(1);
2025-09-10 11:06:42 +08:00
}
2025-09-08 14:55:07 +08:00
2025-09-08 15:45:22 +08:00
LOG_INFO("[MAIN] Program exited cleanly.");
2025-09-08 14:55:07 +08:00
return 0;
2025-11-24 14:49:37 +08:00
}