diff --git a/include/rtsp_manager.hpp b/include/rtsp_manager.hpp index 409568c..b4aa776 100644 --- a/include/rtsp_manager.hpp +++ b/include/rtsp_manager.hpp @@ -23,6 +23,7 @@ public: private: static GMainLoop *loop; + static GMainContext *main_context; // 新增:保存 loop 的 context static GstRTSPServer *server; // 播放状态表 @@ -30,12 +31,4 @@ private: // 创建 MediaFactory static GstRTSPMediaFactory *create_media_factory(const Camera &cam); - - // --- 新增:在 main loop 中执行挂载/卸载 --- - static gboolean mount_camera_in_main(gpointer data); - static gboolean unmount_camera_in_main(gpointer data); - - // --- 已挂载的 factory 指针表(用于卸载) --- - static std::unordered_map mounted_factories; - static std::mutex mounted_factories_mutex; }; diff --git a/src/rtsp_manager.cpp b/src/rtsp_manager.cpp index 41e6923..fcad1f4 100644 --- a/src/rtsp_manager.cpp +++ b/src/rtsp_manager.cpp @@ -1,14 +1,17 @@ -// rtsp_manager.cpp #include "rtsp_manager.hpp" #include "logger.hpp" #include +#include // 静态变量定义 GMainLoop *RTSPManager::loop = nullptr; +GMainContext *RTSPManager::main_context = nullptr; // 新增 GstRTSPServer *RTSPManager::server = nullptr; -std::unordered_map RTSPManager::streaming_status; -std::unordered_map RTSPManager::mounted_factories; -std::mutex RTSPManager::mounted_factories_mutex; +std::unordered_map RTSPManager::streaming_status; // 播放状态表 + +// 保存已挂载的 factory,方便卸载时找到并释放 +static std::unordered_map mounted_factories; +static std::mutex mounted_factories_mutex; void RTSPManager::init() { @@ -37,15 +40,15 @@ void RTSPManager::start(const std::vector &cameras) server = gst_rtsp_server_new(); gst_rtsp_server_set_service(server, "8554"); - // === 不再在启动时挂载摄像头,由调度指令控制推流 === - + // 不在启动时挂载摄像头,由调度指令控制推流 loop = g_main_loop_new(nullptr, FALSE); + main_context = g_main_loop_get_context(loop); // 保存 context + gst_rtsp_server_attach(server, nullptr); LOG_INFO("[RTSP] Server running on rtsp://localhost:8554"); g_main_loop_run(loop); - // loop 退出后释放资源 if (server) { g_object_unref(server); @@ -59,77 +62,29 @@ void RTSPManager::start(const std::vector &cameras) LOG_INFO("[RTSP] Server stopped."); } -void RTSPManager::stop() -{ - if (loop) - { - // 仅退出 loop,不 unref server - g_main_context_invoke(nullptr, [](gpointer data) -> gboolean - { - GMainLoop *loop = static_cast(data); - g_main_loop_quit(loop); - return G_SOURCE_REMOVE; }, loop); - } -} - -// 公共接口:挂载摄像头(可以被任意线程调用,立即返回) -// 将实际挂载工作派发到 main loop 线程执行,避免跨线程直接调用 GStreamer。 -void RTSPManager::mount_camera(const Camera &cam) -{ - // 通过 new 一个临时 Camera 拷贝,主loop callback 会 delete 它 - Camera *camCopy = new Camera(cam); - // 派发到主线程执行 - g_main_context_invoke(nullptr, [](gpointer data) -> gboolean - { return mount_camera_in_main(data); }, camCopy); -} - -// 公共接口:卸载摄像头(可以被任意线程调用,立即返回) -// 将实际卸载工作派发到 main loop 线程执行。 -void RTSPManager::unmount_camera(const Camera &cam) -{ - Camera *camCopy = new Camera(cam); - g_main_context_invoke(nullptr, [](gpointer data) -> gboolean - { return unmount_camera_in_main(data); }, camCopy); -} - -// 查询播放状态(线程安全) -bool RTSPManager::is_streaming(const std::string &cam_name) -{ - std::lock_guard lock(mounted_factories_mutex); - auto it = streaming_status.find(cam_name); - if (it != streaming_status.end()) - return it->second; - return false; -} - -// -------------------- private static callbacks -------------------- - -gboolean RTSPManager::mount_camera_in_main(gpointer data) +// --- 主线程挂载函数 --- +static gboolean mount_camera_in_main(gpointer data) { Camera *cam = static_cast(data); if (!cam) return G_SOURCE_REMOVE; - - if (!server) + if (!RTSPManager::server) { - LOG_ERROR("[RTSP] mount_camera_in_main: server is null"); delete cam; return G_SOURCE_REMOVE; } - GstRTSPMountPoints *mounts = gst_rtsp_server_get_mount_points(server); + GstRTSPMountPoints *mounts = gst_rtsp_server_get_mount_points(RTSPManager::server); if (!mounts) { - LOG_ERROR("[RTSP] mount_camera_in_main: failed to get mounts"); delete cam; return G_SOURCE_REMOVE; } std::string mount_point = "/" + cam->name; - GstRTSPMediaFactory *factory = create_media_factory(*cam); + GstRTSPMediaFactory *factory = RTSPManager::create_media_factory(*cam); if (!factory) { - LOG_ERROR("[RTSP] mount_camera_in_main: failed to create factory for " + cam->name); g_object_unref(mounts); delete cam; return G_SOURCE_REMOVE; @@ -141,7 +96,7 @@ gboolean RTSPManager::mount_camera_in_main(gpointer data) { std::lock_guard lock(mounted_factories_mutex); mounted_factories[cam->name] = factory; - streaming_status[cam->name] = true; + RTSPManager::streaming_status[cam->name] = true; } LOG_INFO("[RTSP] Camera '" + cam->name + "' mounted at rtsp://localhost:8554" + mount_point); @@ -149,23 +104,21 @@ gboolean RTSPManager::mount_camera_in_main(gpointer data) return G_SOURCE_REMOVE; } -gboolean RTSPManager::unmount_camera_in_main(gpointer data) +// --- 主线程卸载函数 --- +static gboolean unmount_camera_in_main(gpointer data) { Camera *cam = static_cast(data); if (!cam) return G_SOURCE_REMOVE; - - if (!server) + if (!RTSPManager::server) { - LOG_ERROR("[RTSP] unmount_camera_in_main: server is null"); delete cam; return G_SOURCE_REMOVE; } - GstRTSPMountPoints *mounts = gst_rtsp_server_get_mount_points(server); + GstRTSPMountPoints *mounts = gst_rtsp_server_get_mount_points(RTSPManager::server); if (!mounts) { - LOG_ERROR("[RTSP] unmount_camera_in_main: failed to get mounts"); delete cam; return G_SOURCE_REMOVE; } @@ -179,14 +132,51 @@ gboolean RTSPManager::unmount_camera_in_main(gpointer data) auto it = mounted_factories.find(cam->name); if (it != mounted_factories.end()) { - if (it->second) - g_object_unref(it->second); + GstRTSPMediaFactory *factory = it->second; + if (factory) + g_object_unref(factory); mounted_factories.erase(it); } - streaming_status[cam->name] = false; + RTSPManager::streaming_status[cam->name] = false; } LOG_INFO("[RTSP] Camera '" + cam->name + "' unmounted."); delete cam; return G_SOURCE_REMOVE; } + +// 公共接口:挂载摄像头(线程安全) +void RTSPManager::mount_camera(const Camera &cam) +{ + Camera *camCopy = new Camera(cam); + g_main_context_invoke(main_context, [](gpointer data) -> gboolean + { return mount_camera_in_main(data); }, camCopy); +} + +// 公共接口:卸载摄像头(线程安全) +void RTSPManager::unmount_camera(const Camera &cam) +{ + Camera *camCopy = new Camera(cam); + g_main_context_invoke(main_context, [](gpointer data) -> gboolean + { return unmount_camera_in_main(data); }, camCopy); +} + +// 查询播放状态 +bool RTSPManager::is_streaming(const std::string &cam_name) +{ + std::lock_guard lock(mounted_factories_mutex); + auto it = streaming_status.find(cam_name); + return it != streaming_status.end() ? it->second : false; +} + +void RTSPManager::stop() +{ + if (loop) + { + g_main_context_invoke(main_context, [](gpointer data) -> gboolean + { + GMainLoop *loop = static_cast(data); + g_main_loop_quit(loop); + return G_SOURCE_REMOVE; }, loop); + } +}