diff --git a/src/rtsp_manager.cpp b/src/rtsp_manager.cpp index 63b256e..8b4669b 100644 --- a/src/rtsp_manager.cpp +++ b/src/rtsp_manager.cpp @@ -2,6 +2,7 @@ #include "rtsp_manager.hpp" #include "logger.hpp" #include +#include // 静态变量定义 GMainLoop *RTSPManager::loop = nullptr; @@ -19,6 +20,7 @@ void RTSPManager::init() LOG_INFO("[RTSP] GStreamer initialized."); } +// 创建 media factory GstRTSPMediaFactory *RTSPManager::create_media_factory(const Camera &cam) { std::string launch_str = @@ -32,13 +34,14 @@ GstRTSPMediaFactory *RTSPManager::create_media_factory(const Camera &cam) gst_rtsp_media_factory_set_launch(factory, launch_str.c_str()); gst_rtsp_media_factory_set_shared(factory, TRUE); - // 连接 media-created 信号,跟踪媒体对象 - g_signal_connect_data(factory, "media-created", G_CALLBACK(on_media_created), g_strdup(cam.name.c_str()), - (GClosureNotify)g_free, static_cast(0)); + // 使用 media-configure 信号代替 media-created + g_signal_connect_data(factory, "media-configure", G_CALLBACK(on_media_created), + g_strdup(cam.name.c_str()), (GClosureNotify)g_free, static_cast(0)); return factory; } +// 启动 RTSP server void RTSPManager::start(const std::vector &cameras) { server = gst_rtsp_server_new(); @@ -62,38 +65,44 @@ void RTSPManager::start(const std::vector &cameras) g_main_loop_unref(loop); loop = nullptr; } + LOG_INFO("[RTSP] Server stopped."); } -// 媒体创建信号处理函数 +// media-configure 信号处理 void RTSPManager::on_media_created(GstRTSPMediaFactory *factory, GstRTSPMedia *media, gpointer user_data) { const char *cam_name = static_cast(user_data); - std::lock_guard lock(media_map_mutex); - media_map[cam_name].push_back(media); - g_object_ref(media); // 增加引用计数,防止意外销毁 - // 连接 unprepared 信号,以便在媒体销毁时从列表中移除 + g_object_ref(media); // 增加引用计数,防止被提前销毁 + { + std::lock_guard lock(media_map_mutex); + media_map[cam_name].push_back(media); + } + + // 连接 unprepared 信号,当 pipeline 被销毁时移除 g_signal_connect_data(media, "unprepared", G_CALLBACK(on_media_unprepared), g_strdup(cam_name), (GClosureNotify)g_free, static_cast(0)); } -// 媒体 unprepared 信号处理函数 +// unprepared 信号处理 void RTSPManager::on_media_unprepared(GstRTSPMedia *media, gpointer user_data) { const char *cam_name = static_cast(user_data); - std::lock_guard lock(media_map_mutex); - auto it = media_map.find(cam_name); - if (it != media_map.end()) { - auto &media_list = it->second; - media_list.erase(std::remove(media_list.begin(), media_list.end(), media), media_list.end()); - if (media_list.empty()) + std::lock_guard lock(media_map_mutex); + auto it = media_map.find(cam_name); + if (it != media_map.end()) { - media_map.erase(it); + auto &media_list = it->second; + media_list.erase(std::remove(media_list.begin(), media_list.end(), media), media_list.end()); + if (media_list.empty()) + { + media_map.erase(it); + } } } - g_object_unref(media); // 释放我们在 on_media_created 中增加的引用 + g_object_unref(media); // 释放引用 } // 挂载摄像头 @@ -136,7 +145,7 @@ gboolean RTSPManager::mount_camera_in_main(gpointer data) return G_SOURCE_REMOVE; } -// 卸载摄像头(停止所有媒体会话) +// 卸载摄像头 gboolean RTSPManager::unmount_camera_in_main(gpointer data) { Camera *cam = static_cast(data); @@ -145,11 +154,26 @@ gboolean RTSPManager::unmount_camera_in_main(gpointer data) delete cam; return G_SOURCE_REMOVE; } - std::string cam_name = cam->name; std::string mount_point = "/" + cam_name; - // 卸载 factory(自动断开客户端) + // 停止所有媒体 + { + std::lock_guard lock(media_map_mutex); + auto it = media_map.find(cam_name); + if (it != media_map.end()) + { + for (GstRTSPMedia *media : it->second) + { + gst_element_set_state(gst_rtsp_media_get_element(media), GST_STATE_NULL); + g_object_unref(media); + } + it->second.clear(); + media_map.erase(it); + } + } + + // 卸载 factory GstRTSPMountPoints *mounts = gst_rtsp_server_get_mount_points(server); if (mounts) { @@ -157,13 +181,6 @@ gboolean RTSPManager::unmount_camera_in_main(gpointer data) g_object_unref(mounts); } - // 清理 media_map - { - std::lock_guard lock(media_map_mutex); - media_map.erase(cam_name); - } - - // 释放 factory 对象 { std::lock_guard lock(mounted_factories_mutex); auto it = mounted_factories.find(cam_name); @@ -181,6 +198,7 @@ gboolean RTSPManager::unmount_camera_in_main(gpointer data) return G_SOURCE_REMOVE; } +// 公共挂载/卸载接口 void RTSPManager::mount_camera(const Camera &cam) { Camera *camCopy = new Camera(cam); @@ -195,6 +213,7 @@ void RTSPManager::unmount_camera(const Camera &cam) { return RTSPManager::unmount_camera_in_main(data); }, camCopy); } +// 是否正在流 bool RTSPManager::is_streaming(const std::string &cam_name) { std::lock_guard lock(mounted_factories_mutex); @@ -202,13 +221,14 @@ bool RTSPManager::is_streaming(const std::string &cam_name) return it != streaming_status.end() ? it->second : false; } +// 停止 server void RTSPManager::stop() { if (loop) { g_main_context_invoke(main_context, [](gpointer data) -> gboolean { - g_main_loop_quit(static_cast(data)); - return G_SOURCE_REMOVE; }, loop); + g_main_loop_quit(static_cast(data)); + return G_SOURCE_REMOVE; }, loop); } }