diff --git a/include/rtmp_manager.hpp b/include/rtmp_manager.hpp index d27ae56..36d2925 100644 --- a/include/rtmp_manager.hpp +++ b/include/rtmp_manager.hpp @@ -9,18 +9,22 @@ #include #include +enum class StreamType +{ + MAIN, + SUB +}; + class RTMPManager { public: static void init(); - // start/stop 增加 StreamType 参数 static void start_camera(const Camera &cam, StreamType type); static void stop_camera(const std::string &cam_name, StreamType type); static void stop_all(); static bool is_streaming(const std::string &cam_name, StreamType type); static bool is_any_streaming(); - // 获取推流 URL,用于应答 static std::string get_stream_url(const std::string &cam_name, StreamType type); private: @@ -29,16 +33,17 @@ private: std::atomic running; std::thread thread; - StreamContext() : running(false) {} // 确保 atomic 初始化 + StreamContext() : running(false) {} + StreamContext(StreamContext &&) = default; // 允许移动 + StreamContext &operator=(StreamContext &&) = default; + StreamContext(const StreamContext &) = delete; + StreamContext &operator=(const StreamContext &) = delete; }; static std::unordered_map streams; static std::mutex streams_mutex; - // stream loop 接收 StreamType 作为参数 static void stream_loop(Camera cam, StreamType type); static GstElement *create_pipeline(const Camera &cam, StreamType type); - - // 辅助:构建 map key static std::string make_stream_key(const std::string &cam_name, StreamType type); }; diff --git a/src/rtmp_manager.cpp b/src/rtmp_manager.cpp index 0ce6ec8..0cceaa1 100644 --- a/src/rtmp_manager.cpp +++ b/src/rtmp_manager.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include std::unordered_map RTMPManager::streams; std::mutex RTMPManager::streams_mutex; @@ -26,7 +28,6 @@ void RTMPManager::init() GstElement *RTMPManager::create_pipeline(const Camera &cam, StreamType type) { - // 拷贝原始参数 int width = cam.width; int height = cam.height; int fps = cam.fps; @@ -34,15 +35,13 @@ GstElement *RTMPManager::create_pipeline(const Camera &cam, StreamType type) if (type == StreamType::SUB) { - // 简单一刀切策略:分辨率 /2,帧率 /2,码率 /2,临界值保护 width = std::max(160, width / 2); height = std::max(120, height / 2); fps = std::max(10, fps / 2); - bitrate = std::max(300000, bitrate / 2); // 最低 300kbps + bitrate = std::max(300000, bitrate / 2); } - // 构建不同的流名(stream key) - std::string stream_name = cam.name + (type == StreamType::MAIN ? "_main" : "_sub"); + std::string stream_name = cam.name + stream_type_suffix(type); std::string pipeline_str = "v4l2src device=" + cam.device + @@ -99,7 +98,6 @@ void RTMPManager::stream_loop(Camera cam, StreamType type) LOG_INFO("[RTMP] Camera '" + key + "' streaming..."); bool error_occurred = false; - // 简单重连计数(可选):连续失败超过 N 次可以退出 int consecutive_failures = 0; const int MAX_RETRIES = 5; @@ -151,7 +149,6 @@ void RTMPManager::stream_loop(Camera cam, StreamType type) if (consecutive_failures >= MAX_RETRIES) { LOG_ERROR("[RTMP] Max retries reached for '" + key + "'. Stopping reconnection attempts."); - // 可以选择将 running 置为 false,让上层知道失败 std::lock_guard lock(streams_mutex); streams[key].running = false; break; @@ -193,8 +190,6 @@ void RTMPManager::stop_camera(const std::string &cam_name, StreamType type) } it->second.running = false; - LOG_INFO("[RTMP] Stopping camera '" + key + "'..."); - if (it->second.thread.joinable()) it->second.thread.join(); @@ -220,38 +215,31 @@ bool RTMPManager::is_any_streaming() void RTMPManager::stop_all() { - std::vector names; + std::vector keys; { std::lock_guard lock(streams_mutex); for (auto &kv : streams) - names.push_back(kv.first); + keys.push_back(kv.first); } - for (auto &name : names) + for (auto &key : keys) { - // name 中包含后缀,但是 stop_camera 需要 cam_name + StreamType - // 我们可以解析后缀,或新增一个 stop_by_key。为简单起见解析: - if (name.size() > 5 && name.find("_sub") == name.size() - 4) + if (key.size() > 4 && key.find("_sub") == key.size() - 4) { - std::string cam_name = name.substr(0, name.size() - 4); - stop_camera(cam_name, StreamType::SUB); + stop_camera(key.substr(0, key.size() - 4), StreamType::SUB); } - else if (name.size() > 6 && name.find("_main") == name.size() - 5) + else if (key.size() > 5 && key.find("_main") == key.size() - 5) { - std::string cam_name = name.substr(0, name.size() - 5); - stop_camera(cam_name, StreamType::MAIN); + stop_camera(key.substr(0, key.size() - 5), StreamType::MAIN); } else { - // fallback: stop by treating as MAIN - stop_camera(name, StreamType::MAIN); + stop_camera(key, StreamType::MAIN); } } } std::string RTMPManager::get_stream_url(const std::string &cam_name, StreamType type) { - // 根据你本地 RTMP 服务地址组装 URL,和 create_pipeline 的 stream_name 保持一致 - std::string stream_name = cam_name + stream_type_suffix(type); - return std::string("rtmp://127.0.0.1/live/") + stream_name; + return "rtmp://127.0.0.1/live/" + make_stream_key(cam_name, type); }