From e227a1f5e8de49aaaf2f56db7d88d8e5753f8661 Mon Sep 17 00:00:00 2001 From: cxh Date: Tue, 9 Sep 2025 11:31:11 +0800 Subject: [PATCH] first commit --- include/rtsp_manager.hpp | 5 ++++- src/rtsp_manager.cpp | 48 ++++++++++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/include/rtsp_manager.hpp b/include/rtsp_manager.hpp index db7ecb8..396c6de 100644 --- a/include/rtsp_manager.hpp +++ b/include/rtsp_manager.hpp @@ -32,7 +32,10 @@ private: static gboolean mount_camera_in_main(gpointer data); static gboolean unmount_camera_in_main(gpointer data); - // --- 静态 mutex 和工厂表 --- + // --- 静态 mutex 和工厂表 --- static std::unordered_map mounted_factories; static std::mutex mounted_factories_mutex; + + // 新增:bus 回调处理 EOS + static GstBusSyncReply bus_sync_callback(GstBus *bus, GstMessage *msg, gpointer user_data); }; diff --git a/src/rtsp_manager.cpp b/src/rtsp_manager.cpp index 81fc1d5..9019568 100644 --- a/src/rtsp_manager.cpp +++ b/src/rtsp_manager.cpp @@ -28,6 +28,32 @@ GstRTSPMediaFactory *RTSPManager::create_media_factory(const Camera &cam) GstRTSPMediaFactory *factory = gst_rtsp_media_factory_new(); gst_rtsp_media_factory_set_launch(factory, launch_str.c_str()); gst_rtsp_media_factory_set_shared(factory, TRUE); + + // 为 factory 添加 bus 监听 EOS + GstElement *element = gst_rtsp_media_factory_get_element(factory); + if (element) + { + GstBus *bus = gst_element_get_bus(element); + gst_bus_add_watch(bus, [](GstBus *bus, GstMessage *msg, gpointer data) -> gboolean + { + if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_EOS) + { + std::string cam_name = static_cast(data); + std::lock_guard lock(mounted_factories_mutex); + auto it = mounted_factories.find(cam_name); + if(it != mounted_factories.end() && it->second.pending_unmount) + { + if(it->second.factory) g_object_unref(it->second.factory); + mounted_factories.erase(it); + streaming_status.erase(cam_name); + LOG_INFO("[RTSP] Camera '" + cam_name + "' factory cleaned up after EOS."); + } + delete[] static_cast(data); + } + return TRUE; }, new char[cam.name.size() + 1]{0}); + gst_object_unref(bus); + } + return factory; } @@ -114,22 +140,30 @@ gboolean RTSPManager::unmount_camera_in_main(gpointer data) } std::string mount_point = "/" + cam->name; - gst_rtsp_mount_points_remove_factory(mounts, mount_point.c_str()); - g_object_unref(mounts); { std::lock_guard lock(mounted_factories_mutex); auto it = mounted_factories.find(cam->name); if (it != mounted_factories.end()) { - if (it->second) - g_object_unref(it->second); - mounted_factories.erase(it); + // 发送 EOS,让 pipeline 停止 + GstRTSPMediaFactory *factory = it->second.factory; + if (factory) + { + GstElement *elem = gst_rtsp_media_factory_get_element(factory); + if (elem) + gst_element_send_event(elem, gst_event_new_eos()); + } + // 标记 pending_unmount + it->second.pending_unmount = true; } - streaming_status[cam->name] = false; } - LOG_INFO("[RTSP] Camera '" + cam->name + "' unmounted."); + // 从 mount points 立即移除,让客户端断流,但 factory 还保留 + gst_rtsp_mount_points_remove_factory(mounts, mount_point.c_str()); + g_object_unref(mounts); + + LOG_INFO("[RTSP] Camera '" + cam->name + "' unmount requested (EOS sent)."); delete cam; return G_SOURCE_REMOVE; }