// rtmp_manager.hpp #pragma once #include #include #include #include #include #include #include #include #include #include #include "app_config.hpp" #include "data_manager.hpp" class RTMPManager { public: enum class StreamResult { OK, PIPELINE_ERROR, CONNECTION_FAIL, EOS_RECEIVED, TIMEOUT, UNKNOWN }; struct StreamStatus { bool running{false}; StreamResult last_result{StreamResult::UNKNOWN}; std::string last_error; }; struct StreamResultInfo { int loc{-1}; std::string url; int result{1}; // 0 success, 1 fail std::string reason; }; using StreamCallback = std::function; static void init(); static void set_status_callback(StreamCallback cb); // 单路接口 static StreamResultInfo start_camera(const Camera &cam, StreamType type); static StreamResultInfo stop_camera(const std::string &cam_name, StreamType type); // 批量接口:处理 VideoPushRequest static std::vector process_push_request(const VideoPushRequest &req); static void stop_all(); static bool is_streaming(const std::string &cam_name, StreamType type); static bool is_any_streaming(); static std::string get_stream_url(const std::string &cam_name, StreamType type); private: struct StreamContext { std::atomic running{false}; std::thread thread; StreamStatus status; int retry_count{0}; StreamContext() = default; StreamContext(const StreamContext &) = delete; StreamContext &operator=(const StreamContext &) = delete; }; static std::string make_stream_key(const std::string &cam_name, StreamType type); static GstElement *create_pipeline(const Camera &cam, StreamType type); static void stream_loop(Camera cam, StreamType type, std::promise *status_promise); static void update_status(const std::string &key, const StreamStatus &status); static std::unordered_map> streams; static std::mutex streams_mutex; static StreamCallback status_callback; // 自动重试参数 static constexpr int MAX_RETRIES = 3; static constexpr int RETRY_DELAY_MS = 2000; };