From b8f0c314558710ac3f49292ebdb5b7f288472c05 Mon Sep 17 00:00:00 2001 From: cxh Date: Fri, 21 Nov 2025 14:52:53 +0800 Subject: [PATCH] 1 --- include/rtsp_manager.hpp | 5 +++++ src/rtsp_manager.cpp | 40 ++++++++++++++++++++++++---------------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/include/rtsp_manager.hpp b/include/rtsp_manager.hpp index f35754d..9bae6c5 100644 --- a/include/rtsp_manager.hpp +++ b/include/rtsp_manager.hpp @@ -45,4 +45,9 @@ private: // 信号处理函数 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 d688faf..6e86520 100644 --- a/src/rtsp_manager.cpp +++ b/src/rtsp_manager.cpp @@ -29,19 +29,6 @@ GstRTSPMediaFactory *RTSPManager::create_media_factory(const Camera &cam) int out_width = cam.width; int out_height = cam.height; - // 构建 pipeline - // std::string launch_str = - // "( v4l2src device=" + cam.device + - // " ! video/x-raw,format=NV12,width=" + std::to_string(out_width) + - // ",height=" + std::to_string(out_height) + - // ",framerate=" + std::to_string(cam.fps) + "/1" - // " ! queue max-size-buffers=1 leaky=downstream" // 最小队列 - // " ! mpph264enc bps=" + - // std::to_string(cam.bitrate) + - // " gop=" + std::to_string(cam.fps) + // GOP 设置为 1 秒 - // " ! h264parse" - // " ! rtph264pay name=pay0 pt=96 config-interval=1 )"; // 每秒发送 SPS/PPS - std::string launch_str = "( v4l2src device=" + cam.device + " ! video/x-raw,format=NV12,width=" + std::to_string(out_width) + @@ -129,6 +116,14 @@ void RTSPManager::on_media_unprepared(GstRTSPMedia *media, gpointer user_data) } } } + + // === ★ 新增:减计数并在最后一个时唤醒等待线程 === + { + std::lock_guard lk(stop_mutex); + if (--stopping_count[cam_name] == 0) + stop_cv.notify_all(); + } + g_object_unref(media); // 释放引用 } @@ -190,6 +185,13 @@ gboolean RTSPManager::unmount_camera_in_main(gpointer data) 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); @@ -199,11 +201,9 @@ 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); } } @@ -236,8 +236,16 @@ gboolean RTSPManager::unmount_camera_in_main(gpointer data) 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); + + // === ★ 新增:等待 on_media_unprepared 全部完成 === + 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; }); } void RTSPManager::unmount_camera(const Camera &cam)