diff --git a/include/rtsp_manager.hpp b/include/rtsp_manager.hpp index 767ba2d..89099b5 100644 --- a/include/rtsp_manager.hpp +++ b/include/rtsp_manager.hpp @@ -7,7 +7,6 @@ #include #include #include -#include #include class RTSPManager @@ -19,6 +18,7 @@ public: static void mount_camera(const Camera &cam); static void unmount_camera(const Camera &cam); + static bool is_streaming(const std::string &cam_name); static bool is_any_streaming(); @@ -26,29 +26,25 @@ private: static GMainLoop *loop; static GMainContext *main_context; static GstRTSPServer *server; + static std::unordered_map streaming_status; - // 工厂创建函数 + // 工厂创建 static GstRTSPMediaFactory *create_media_factory(const Camera &cam); - // 挂载/卸载函数 + // 挂载/卸载 static gboolean mount_camera_in_main(gpointer data); static gboolean unmount_camera_in_main(gpointer data); - // 静态 mutex 和工厂表 + // factory 管理 static std::unordered_map mounted_factories; static std::mutex mounted_factories_mutex; - // 媒体对象跟踪 + // pipeline/media 管理 static std::unordered_map> media_map; static std::mutex media_map_mutex; - // 信号处理函数 + // gstreamer 信号 static void on_media_created(GstRTSPMediaFactory *factory, GstRTSPMedia *media, gpointer user_data); static void on_media_unprepared(GstRTSPMedia *media, gpointer user_data); - - // === 新增:同步停止用 === - static std::mutex stop_mutex; - static std::condition_variable stop_cv; - static std::unordered_map stopping_count; -}; \ No newline at end of file +}; diff --git a/src/rtsp_manager.cpp b/src/rtsp_manager.cpp index 0ae2183..c07069e 100644 --- a/src/rtsp_manager.cpp +++ b/src/rtsp_manager.cpp @@ -1,6 +1,7 @@ // rtsp_manager.cpp #include "rtsp_manager.hpp" #include "logger.hpp" + #include #include #include @@ -10,14 +11,13 @@ 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::media_map; std::mutex RTSPManager::media_map_mutex; -std::mutex RTSPManager::stop_mutex; -std::condition_variable RTSPManager::stop_cv; -std::unordered_map RTSPManager::stopping_count; void RTSPManager::init() { @@ -25,10 +25,8 @@ void RTSPManager::init() LOG_INFO("[RTSP] GStreamer initialized."); } -// 创建 media factory GstRTSPMediaFactory *RTSPManager::create_media_factory(const Camera &cam) { - // 输出分辨率直接用相机原始分辨率 int out_width = cam.width; int out_height = cam.height; @@ -48,18 +46,18 @@ 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); - gst_rtsp_media_factory_set_suspend_mode(factory, GST_RTSP_SUSPEND_MODE_RESET); - // 使用 media-configure 信号代替 media-created + // 监听 pipeline 创建 g_signal_connect_data(factory, "media-configure", G_CALLBACK(on_media_created), - g_strdup(cam.name.c_str()), (GClosureNotify)g_free, static_cast(0)); + g_strdup(cam.name.c_str()), + (GClosureNotify)g_free, + (GConnectFlags)0); return factory; } -// 启动 RTSP server -void RTSPManager::start(const std::vector &cameras) +void RTSPManager::start(const std::vector &) { server = gst_rtsp_server_new(); gst_rtsp_server_set_service(server, "8554"); @@ -86,51 +84,46 @@ void RTSPManager::start(const std::vector &cameras) LOG_INFO("[RTSP] Server stopped."); } -// media-configure 信号处理 -void RTSPManager::on_media_created(GstRTSPMediaFactory *factory, GstRTSPMedia *media, gpointer user_data) +void RTSPManager::on_media_created(GstRTSPMediaFactory *, GstRTSPMedia *media, gpointer user_data) { const char *cam_name = static_cast(user_data); - g_object_ref(media); // 增加引用计数,防止被提前销毁 + LOG_INFO(std::string("[RTSP] media-configure for camera: ") + cam_name); + + 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)); + g_strdup(cam_name), + (GClosureNotify)g_free, + (GConnectFlags)0); } -// unprepared 信号处理 void RTSPManager::on_media_unprepared(GstRTSPMedia *media, gpointer user_data) { const char *cam_name = static_cast(user_data); + + LOG_INFO(std::string("[RTSP] media-unprepared: ") + cam_name); + { 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()) - { + auto &vec = it->second; + vec.erase(std::remove(vec.begin(), vec.end(), media), vec.end()); + if (vec.empty()) media_map.erase(it); - } } } - // === ★ 新增:减计数并在最后一个时唤醒等待线程 === - { - std::lock_guard lk(stop_mutex); - if (--stopping_count[cam_name] == 0) - stop_cv.notify_all(); - } - - g_object_unref(media); // 释放引用 + g_object_unref(media); } -// 挂载摄像头 gboolean RTSPManager::mount_camera_in_main(gpointer data) { Camera *cam = static_cast(data); @@ -141,20 +134,9 @@ gboolean RTSPManager::mount_camera_in_main(gpointer data) } GstRTSPMountPoints *mounts = gst_rtsp_server_get_mount_points(server); - if (!mounts) - { - delete cam; - return G_SOURCE_REMOVE; - } std::string mount_point = "/" + cam->name; GstRTSPMediaFactory *factory = create_media_factory(*cam); - if (!factory) - { - g_object_unref(mounts); - delete cam; - return G_SOURCE_REMOVE; - } gst_rtsp_mount_points_add_factory(mounts, mount_point.c_str(), factory); g_object_unref(mounts); @@ -166,11 +148,11 @@ gboolean RTSPManager::mount_camera_in_main(gpointer data) } LOG_INFO("[RTSP] Camera '" + cam->name + "' mounted at rtsp://localhost:8554" + mount_point); + delete cam; return G_SOURCE_REMOVE; } -// 卸载摄像头 gboolean RTSPManager::unmount_camera_in_main(gpointer data) { Camera *cam = static_cast(data); @@ -179,22 +161,16 @@ 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; - // 停止所有媒体 + // 停掉 media { std::lock_guard lock(media_map_mutex); auto it = media_map.find(cam_name); if (it != media_map.end()) { - - // === ★ 新增:记录需要等待的 media 数量 === - { - std::lock_guard lk(stop_mutex); - stopping_count[cam_name] = it->second.size(); - } - for (GstRTSPMedia *media : it->second) { GstElement *pipeline = gst_rtsp_media_get_element(media); @@ -204,13 +180,15 @@ gboolean RTSPManager::unmount_camera_in_main(gpointer data) gst_object_unref(pipeline); } - // 这一步会触发 on_media_unprepared 信号 gst_rtsp_media_unprepare(media); } + + it->second.clear(); + media_map.erase(it); } } - // 卸载 factory + // 移除 factory GstRTSPMountPoints *mounts = gst_rtsp_server_get_mount_points(server); if (mounts) { @@ -223,7 +201,7 @@ gboolean RTSPManager::unmount_camera_in_main(gpointer data) auto it = mounted_factories.find(cam_name); if (it != mounted_factories.end()) { - if (it->second && G_IS_OBJECT(it->second)) + if (it->second) g_object_unref(it->second); mounted_factories.erase(it); } @@ -235,11 +213,9 @@ gboolean RTSPManager::unmount_camera_in_main(gpointer data) 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 RTSPManager::mount_camera_in_main(data); }, camCopy); } @@ -247,18 +223,10 @@ void RTSPManager::mount_camera(const Camera &cam) void RTSPManager::unmount_camera(const Camera &cam) { Camera *camCopy = new Camera(cam); - g_main_context_invoke(main_context, [](gpointer data) -> gboolean { return RTSPManager::unmount_camera_in_main(data); }, camCopy); - - std::unique_lock lk(stop_mutex); - stop_cv.wait(lk, [&] - { - auto it = stopping_count.find(cam.name); - return it == stopping_count.end() || it->second == 0; }); } -// 是否正在流 bool RTSPManager::is_streaming(const std::string &cam_name) { std::lock_guard lock(mounted_factories_mutex); @@ -266,32 +234,26 @@ bool RTSPManager::is_streaming(const std::string &cam_name) return it != streaming_status.end() ? it->second : false; } -// 停止 server +bool RTSPManager::is_any_streaming() +{ + std::lock_guard lock(mounted_factories_mutex); + for (auto &kv : streaming_status) + if (kv.second) + return true; + return false; +} + void RTSPManager::stop() { - // Ctrl-C 退出时,不再尝试逐路卸载摄像头, - // 只负责让 g_main_loop_run() 退出,线程自然收尾。 if (loop) { g_main_context_invoke( main_context, [](gpointer data) -> gboolean { - GMainLoop *lp = static_cast(data); - if (lp) - g_main_loop_quit(lp); + g_main_loop_quit(static_cast(data)); return G_SOURCE_REMOVE; }, loop); } } - -// 新增接口:检查是否还有摄像头在流 -bool RTSPManager::is_any_streaming() -{ - std::lock_guard lock(mounted_factories_mutex); - for (const auto &kv : streaming_status) - if (kv.second) - return true; - return false; -}