新增录像功能开关

This commit is contained in:
cxh 2026-01-22 09:29:10 +08:00
parent 2cdd2d4f4f
commit 7c90feb3f7
4 changed files with 52 additions and 1 deletions

View File

@ -73,6 +73,7 @@ struct MQTTConfig
// ------------------- 总配置 -------------------
struct AppConfig
{
bool record_enabled = true;
std::vector<Camera> cameras;
MQTTConfig mqtt;
@ -90,6 +91,9 @@ struct AppConfig
json j;
ifs >> j;
cfg.record_enabled = j.value("record_enabled", true);
LOG_INFO("[Config] Global record_enabled = " + std::string(cfg.record_enabled ? "true" : "false"));
// 读取摄像头
if (j.contains("cameras"))
{

View File

@ -47,6 +47,8 @@ class RTMPManager
static void set_live_enabled_all(bool enable);
static void set_live_enabled(const std::string& cam_name, bool enable);
static bool g_record_enabled;
private:
struct StreamContext
{
@ -57,6 +59,7 @@ class RTMPManager
std::mutex status_mutex;
GstElement* live_valve{nullptr};
GstElement* record_valve = nullptr;
};
static void stream_loop(Camera cam, StreamContext* ctx);
@ -65,6 +68,7 @@ class RTMPManager
static std::unordered_map<std::string, std::unique_ptr<StreamContext>> streams;
static std::mutex streams_mutex;
static std::atomic<bool> g_live_enabled;
static constexpr int RETRY_BASE_DELAY_MS = 3000;

View File

@ -61,6 +61,8 @@ int main()
// ---------- 初始化 GStreamer ----------
RTMPManager::init();
RTMPManager::g_record_enabled = g_app_config.record_enabled;
// ---------- 自动推流8 路录像守护) ----------
LOG_INFO("[MAIN] Starting all record streams...");
RTMPManager::start_all();

View File

@ -12,6 +12,7 @@
#include <thread>
std::atomic<bool> RTMPManager::g_live_enabled{false};
bool RTMPManager::g_record_enabled = true;
// =======================================================
// 工具函数
@ -89,8 +90,10 @@ GstElement* RTMPManager::create_pipeline(const Camera& cam)
"! h264parse config-interval=1 "
"! tee name=t "
// ===== record永远稳定 =====
// ===== record可开关 =====
"t. ! queue max-size-buffers=8 leaky=downstream "
"! valve name=record_valve drop=true " // ★★ 新增
"! queue max-size-buffers=8 leaky=downstream "
"! flvmux name=rec_mux streamable=true "
"! rtmpsink name=rec_sink location=\"" +
record_rtmp +
@ -173,6 +176,30 @@ void RTMPManager::stream_loop(Camera cam, StreamContext* ctx)
ctx->live_valve = live_valve; // ⚠️ live_valve 引用交给 ctx 管理
}
// 2.x 获取 record_valve
GstElement* record_valve = gst_bin_get_by_name(GST_BIN(pipeline), "record_valve");
if (!record_valve)
{
{
std::lock_guard<std::mutex> lk(ctx->status_mutex);
ctx->status.running = false;
ctx->status.last_error = "record_valve not found";
}
LOG_ERROR("[RTMP] " + key + " - record_valve not found");
gst_object_unref(pipeline);
std::this_thread::sleep_for(std::chrono::seconds(3));
continue;
}
// 保存到 ctx
{
std::lock_guard<std::mutex> lk(ctx->status_mutex);
if (ctx->record_valve) gst_object_unref(ctx->record_valve);
ctx->record_valve = record_valve;
}
g_object_set(G_OBJECT(ctx->record_valve), "drop", g_record_enabled.load() ? FALSE : TRUE, nullptr);
g_object_set(G_OBJECT(ctx->live_valve), "drop", g_live_enabled.load() ? FALSE : TRUE, nullptr);
GstBus* bus = gst_element_get_bus(pipeline);
@ -248,11 +275,18 @@ void RTMPManager::stream_loop(Camera cam, StreamContext* ctx)
cleanup:
{
std::lock_guard<std::mutex> lk(ctx->status_mutex);
if (ctx->live_valve)
{
gst_object_unref(ctx->live_valve);
ctx->live_valve = nullptr;
}
if (ctx->record_valve)
{
gst_object_unref(ctx->record_valve);
ctx->record_valve = nullptr;
}
}
gst_element_set_state(pipeline, GST_STATE_NULL);
@ -317,11 +351,18 @@ void RTMPManager::stop_all()
kv.second->thread_running.store(false);
std::lock_guard<std::mutex> lk(kv.second->status_mutex);
if (kv.second->live_valve)
{
gst_object_unref(kv.second->live_valve);
kv.second->live_valve = nullptr;
}
if (kv.second->record_valve)
{
gst_object_unref(kv.second->record_valve);
kv.second->record_valve = nullptr;
}
}
for (auto& kv : streams)