temp
This commit is contained in:
parent
516f1d4404
commit
786c4db596
@ -9,18 +9,22 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
|
enum class StreamType
|
||||||
|
{
|
||||||
|
MAIN,
|
||||||
|
SUB
|
||||||
|
};
|
||||||
|
|
||||||
class RTMPManager
|
class RTMPManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void init();
|
static void init();
|
||||||
// start/stop 增加 StreamType 参数
|
|
||||||
static void start_camera(const Camera &cam, StreamType type);
|
static void start_camera(const Camera &cam, StreamType type);
|
||||||
static void stop_camera(const std::string &cam_name, StreamType type);
|
static void stop_camera(const std::string &cam_name, StreamType type);
|
||||||
static void stop_all();
|
static void stop_all();
|
||||||
static bool is_streaming(const std::string &cam_name, StreamType type);
|
static bool is_streaming(const std::string &cam_name, StreamType type);
|
||||||
static bool is_any_streaming();
|
static bool is_any_streaming();
|
||||||
|
|
||||||
// 获取推流 URL,用于应答
|
|
||||||
static std::string get_stream_url(const std::string &cam_name, StreamType type);
|
static std::string get_stream_url(const std::string &cam_name, StreamType type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -29,16 +33,17 @@ private:
|
|||||||
std::atomic<bool> running;
|
std::atomic<bool> running;
|
||||||
std::thread thread;
|
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<std::string, StreamContext> streams;
|
static std::unordered_map<std::string, StreamContext> streams;
|
||||||
static std::mutex streams_mutex;
|
static std::mutex streams_mutex;
|
||||||
|
|
||||||
// stream loop 接收 StreamType 作为参数
|
|
||||||
static void stream_loop(Camera cam, StreamType type);
|
static void stream_loop(Camera cam, StreamType type);
|
||||||
static GstElement *create_pipeline(const 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);
|
static std::string make_stream_key(const std::string &cam_name, StreamType type);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,6 +4,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
std::unordered_map<std::string, RTMPManager::StreamContext> RTMPManager::streams;
|
std::unordered_map<std::string, RTMPManager::StreamContext> RTMPManager::streams;
|
||||||
std::mutex RTMPManager::streams_mutex;
|
std::mutex RTMPManager::streams_mutex;
|
||||||
@ -26,7 +28,6 @@ void RTMPManager::init()
|
|||||||
|
|
||||||
GstElement *RTMPManager::create_pipeline(const Camera &cam, StreamType type)
|
GstElement *RTMPManager::create_pipeline(const Camera &cam, StreamType type)
|
||||||
{
|
{
|
||||||
// 拷贝原始参数
|
|
||||||
int width = cam.width;
|
int width = cam.width;
|
||||||
int height = cam.height;
|
int height = cam.height;
|
||||||
int fps = cam.fps;
|
int fps = cam.fps;
|
||||||
@ -34,15 +35,13 @@ GstElement *RTMPManager::create_pipeline(const Camera &cam, StreamType type)
|
|||||||
|
|
||||||
if (type == StreamType::SUB)
|
if (type == StreamType::SUB)
|
||||||
{
|
{
|
||||||
// 简单一刀切策略:分辨率 /2,帧率 /2,码率 /2,临界值保护
|
|
||||||
width = std::max(160, width / 2);
|
width = std::max(160, width / 2);
|
||||||
height = std::max(120, height / 2);
|
height = std::max(120, height / 2);
|
||||||
fps = std::max(10, fps / 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 + stream_type_suffix(type);
|
||||||
std::string stream_name = cam.name + (type == StreamType::MAIN ? "_main" : "_sub");
|
|
||||||
|
|
||||||
std::string pipeline_str =
|
std::string pipeline_str =
|
||||||
"v4l2src device=" + cam.device +
|
"v4l2src device=" + cam.device +
|
||||||
@ -99,7 +98,6 @@ void RTMPManager::stream_loop(Camera cam, StreamType type)
|
|||||||
LOG_INFO("[RTMP] Camera '" + key + "' streaming...");
|
LOG_INFO("[RTMP] Camera '" + key + "' streaming...");
|
||||||
|
|
||||||
bool error_occurred = false;
|
bool error_occurred = false;
|
||||||
// 简单重连计数(可选):连续失败超过 N 次可以退出
|
|
||||||
int consecutive_failures = 0;
|
int consecutive_failures = 0;
|
||||||
const int MAX_RETRIES = 5;
|
const int MAX_RETRIES = 5;
|
||||||
|
|
||||||
@ -151,7 +149,6 @@ void RTMPManager::stream_loop(Camera cam, StreamType type)
|
|||||||
if (consecutive_failures >= MAX_RETRIES)
|
if (consecutive_failures >= MAX_RETRIES)
|
||||||
{
|
{
|
||||||
LOG_ERROR("[RTMP] Max retries reached for '" + key + "'. Stopping reconnection attempts.");
|
LOG_ERROR("[RTMP] Max retries reached for '" + key + "'. Stopping reconnection attempts.");
|
||||||
// 可以选择将 running 置为 false,让上层知道失败
|
|
||||||
std::lock_guard<std::mutex> lock(streams_mutex);
|
std::lock_guard<std::mutex> lock(streams_mutex);
|
||||||
streams[key].running = false;
|
streams[key].running = false;
|
||||||
break;
|
break;
|
||||||
@ -193,8 +190,6 @@ void RTMPManager::stop_camera(const std::string &cam_name, StreamType type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
it->second.running = false;
|
it->second.running = false;
|
||||||
LOG_INFO("[RTMP] Stopping camera '" + key + "'...");
|
|
||||||
|
|
||||||
if (it->second.thread.joinable())
|
if (it->second.thread.joinable())
|
||||||
it->second.thread.join();
|
it->second.thread.join();
|
||||||
|
|
||||||
@ -220,38 +215,31 @@ bool RTMPManager::is_any_streaming()
|
|||||||
|
|
||||||
void RTMPManager::stop_all()
|
void RTMPManager::stop_all()
|
||||||
{
|
{
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> keys;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(streams_mutex);
|
std::lock_guard<std::mutex> lock(streams_mutex);
|
||||||
for (auto &kv : streams)
|
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
|
if (key.size() > 4 && key.find("_sub") == key.size() - 4)
|
||||||
// 我们可以解析后缀,或新增一个 stop_by_key。为简单起见解析:
|
|
||||||
if (name.size() > 5 && name.find("_sub") == name.size() - 4)
|
|
||||||
{
|
{
|
||||||
std::string cam_name = name.substr(0, name.size() - 4);
|
stop_camera(key.substr(0, key.size() - 4), StreamType::SUB);
|
||||||
stop_camera(cam_name, 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(key.substr(0, key.size() - 5), StreamType::MAIN);
|
||||||
stop_camera(cam_name, StreamType::MAIN);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// fallback: stop by treating as MAIN
|
stop_camera(key, StreamType::MAIN);
|
||||||
stop_camera(name, StreamType::MAIN);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RTMPManager::get_stream_url(const std::string &cam_name, StreamType type)
|
std::string RTMPManager::get_stream_url(const std::string &cam_name, StreamType type)
|
||||||
{
|
{
|
||||||
// 根据你本地 RTMP 服务地址组装 URL,和 create_pipeline 的 stream_name 保持一致
|
return "rtmp://127.0.0.1/live/" + make_stream_key(cam_name, type);
|
||||||
std::string stream_name = cam_name + stream_type_suffix(type);
|
|
||||||
return std::string("rtmp://127.0.0.1/live/") + stream_name;
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user