From 307749f3934e5c5cb0ced024237cbc34de104522 Mon Sep 17 00:00:00 2001 From: cxh Date: Tue, 9 Sep 2025 09:57:24 +0800 Subject: [PATCH] first commit --- include/mqtt_client_wrapper.hpp | 1 + include/rtsp_manager.hpp | 10 ++++++ src/mqtt_client_wrapper.cpp | 62 +++++++++++++++++++++++++++++++++ src/rtsp_manager.cpp | 57 ++++++++++++++++++++++-------- 4 files changed, 115 insertions(+), 15 deletions(-) diff --git a/include/mqtt_client_wrapper.hpp b/include/mqtt_client_wrapper.hpp index a58cf63..20d10d7 100644 --- a/include/mqtt_client_wrapper.hpp +++ b/include/mqtt_client_wrapper.hpp @@ -4,6 +4,7 @@ #include "app_config.hpp" #include "logger.hpp" #include "mqtt_client.hpp" +#include "rtsp_manager.hpp" #include #include diff --git a/include/rtsp_manager.hpp b/include/rtsp_manager.hpp index a548726..2286156 100644 --- a/include/rtsp_manager.hpp +++ b/include/rtsp_manager.hpp @@ -13,9 +13,19 @@ public: static void start(const std::vector &cameras); static void stop(); + // === 新增方法:按需挂载/卸载摄像头 === + static void mount_camera(const Camera &cam); + static void unmount_camera(const Camera &cam); + + // === 新增方法:查询播放状态 === + static bool is_streaming(const std::string &cam_name); + private: static GMainLoop *loop; static GstRTSPServer *server; + // === 新增:维护每个摄像头的播放状态 === + static std::unordered_map streaming_status; + static GstRTSPMediaFactory *create_media_factory(const Camera &cam); }; diff --git a/src/mqtt_client_wrapper.cpp b/src/mqtt_client_wrapper.cpp index 5d86bff..d7e12d4 100644 --- a/src/mqtt_client_wrapper.cpp +++ b/src/mqtt_client_wrapper.cpp @@ -28,6 +28,68 @@ static void on_mqtt_message_received(const std::string &topic, const std::string try { + if (topic == g_app_config.mqtt.topics.video_down) + { + // 处理 video_down + auto j = nlohmann::json::parse(message); + + if (!j.contains("data") || !j["data"].contains("status")) + { + LOG_WARN("[MQTT] video_down JSON missing data.status"); + return; + } + + int status = j["data"]["status"].get(); + + if (status == 1) + { + // 启动推流:挂载本地配置中 enabled 的摄像头 + for (const auto &cam : g_app_config.cameras) + { + if (!cam.enabled) + continue; + + if (!RTSPManager::is_streaming(cam.name)) + { + RTSPManager::mount_camera(cam); + LOG_INFO("[MQTT] Started streaming: " + cam.name); + } + } + } + else if (status == 0) + { + // 停止推流:卸载本地配置中 enabled 的摄像头 + for (const auto &cam : g_app_config.cameras) + { + if (!cam.enabled) + continue; + + if (RTSPManager::is_streaming(cam.name)) + { + RTSPManager::unmount_camera(cam); + LOG_INFO("[MQTT] Stopped streaming: " + cam.name); + } + } + } + else + { + LOG_WARN("[MQTT] video_down: unknown status value " + std::to_string(status)); + } + } + else if (topic == g_app_config.mqtt.topics.substream_down) + { + // 处理 substream_down + LOG_INFO("[MQTT] substream_down message received (not implemented yet)."); + } + else if (topic == g_app_config.mqtt.topics.reset_down) + { + // 处理 reset_down + LOG_INFO("[MQTT] reset_down message received (not implemented yet)."); + } + else + { + LOG_WARN("[MQTT] Unknown topic: " + topic); + } } catch (const std::exception &e) { diff --git a/src/rtsp_manager.cpp b/src/rtsp_manager.cpp index 81ecc97..39b5e9e 100644 --- a/src/rtsp_manager.cpp +++ b/src/rtsp_manager.cpp @@ -3,8 +3,10 @@ #include "logger.hpp" #include +// 静态变量定义 GMainLoop *RTSPManager::loop = nullptr; GstRTSPServer *RTSPManager::server = nullptr; +std::unordered_map RTSPManager::streaming_status; // 播放状态表 void RTSPManager::init() { @@ -33,21 +35,7 @@ void RTSPManager::start(const std::vector &cameras) server = gst_rtsp_server_new(); gst_rtsp_server_set_service(server, "8554"); - GstRTSPMountPoints *mounts = gst_rtsp_server_get_mount_points(server); - - for (auto &cam : cameras) - { - if (!cam.enabled) - continue; - - auto factory = create_media_factory(cam); - std::string mount_point = "/" + cam.name; - gst_rtsp_mount_points_add_factory(mounts, mount_point.c_str(), factory); - - LOG_INFO("[RTSP] Camera '" + cam.name + "' available at rtsp://localhost:8554" + mount_point); - } - - g_object_unref(mounts); + // === 不再在启动时挂载摄像头,由调度指令控制推流 === loop = g_main_loop_new(nullptr, FALSE); gst_rtsp_server_attach(server, nullptr); @@ -69,6 +57,45 @@ void RTSPManager::start(const std::vector &cameras) LOG_INFO("[RTSP] Server stopped."); } +// === 新增方法:挂载摄像头 === +void RTSPManager::mount_camera(const Camera &cam) +{ + if (!server) + return; + + GstRTSPMountPoints *mounts = gst_rtsp_server_get_mount_points(server); + auto factory = create_media_factory(cam); + std::string mount_point = "/" + cam.name; + gst_rtsp_mount_points_add_factory(mounts, mount_point.c_str(), factory); + g_object_unref(mounts); + + streaming_status[cam.name] = true; // === 更新播放状态 === + LOG_INFO("[RTSP] Camera '" + cam.name + "' mounted at rtsp://localhost:8554" + mount_point); +} + +// === 新增方法:卸载摄像头 === +void RTSPManager::unmount_camera(const Camera &cam) +{ + if (!server) + return; + + GstRTSPMountPoints *mounts = gst_rtsp_server_get_mount_points(server); + std::string mount_point = "/" + cam.name; + gst_rtsp_mount_points_remove_factory(mounts, mount_point.c_str()); + g_object_unref(mounts); + + streaming_status[cam.name] = false; // === 更新播放状态 === + LOG_INFO("[RTSP] Camera '" + cam.name + "' unmounted."); +} + +bool RTSPManager::is_streaming(const std::string &cam_name) +{ + auto it = streaming_status.find(cam_name); + if (it != streaming_status.end()) + return it->second; + return false; // 默认未推流 +} + void RTSPManager::stop() { if (loop)