From 394ec7bc8183ef7223ed91fe8aa0f60a7b4a5277 Mon Sep 17 00:00:00 2001 From: cxh Date: Fri, 17 Oct 2025 16:10:02 +0800 Subject: [PATCH] 1 --- src/rtmp_manager.cpp | 83 ++++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 23 deletions(-) diff --git a/src/rtmp_manager.cpp b/src/rtmp_manager.cpp index d4dba91..bed9aa7 100644 --- a/src/rtmp_manager.cpp +++ b/src/rtmp_manager.cpp @@ -106,6 +106,7 @@ GstElement *RTMPManager::create_pipeline(const Camera &cam) void RTMPManager::stream_loop(Camera cam, StreamContext *ctx) { std::string key = make_key(cam.name); + int consecutive_failures = 0; while (ctx->running) { @@ -116,6 +117,7 @@ void RTMPManager::stream_loop(Camera cam, StreamContext *ctx) ctx->status.running = false; ctx->status.last_error = "Device not found: " + cam.device; LOG_WARN("[RTMP] " + key + " - " + ctx->status.last_error); + consecutive_failures++; std::this_thread::sleep_for(std::chrono::seconds(3)); continue; } @@ -127,6 +129,7 @@ void RTMPManager::stream_loop(Camera cam, StreamContext *ctx) ctx->status.running = false; ctx->status.last_error = "Pipeline creation failed"; LOG_ERROR("[RTMP] " + key + " - " + ctx->status.last_error); + consecutive_failures++; std::this_thread::sleep_for(std::chrono::seconds(3)); continue; } @@ -135,40 +138,70 @@ void RTMPManager::stream_loop(Camera cam, StreamContext *ctx) gst_element_set_state(pipeline, GST_STATE_PLAYING); LOG_INFO("[RTMP] Starting stream: " + key); - ctx->status.running = true; - ctx->status.last_error.clear(); - + bool confirmed_running = false; bool got_frame = false; bool need_restart = false; + auto start_time = std::chrono::steady_clock::now(); + // ======== 等待 pipeline 确认启动 ======== + { + bool got_first_frame = false; + auto check_start = std::chrono::steady_clock::now(); + + while (std::chrono::duration_cast(std::chrono::steady_clock::now() - check_start) + .count() < 2000) + { + GstState state; + gst_element_get_state(pipeline, &state, nullptr, 200 * GST_MSECOND); + if (state == GST_STATE_PLAYING) + { + got_first_frame = true; + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + if (got_first_frame) + { + ctx->status.running = true; + ctx->status.last_error.clear(); + confirmed_running = true; + LOG_INFO("[RTMP] " + key + " confirmed running."); + } + else + { + ctx->status.running = false; + ctx->status.last_error = "Pipeline failed to confirm PLAYING"; + LOG_WARN("[RTMP] " + key + " - " + ctx->status.last_error); + } + } + + if (!confirmed_running) + { + gst_element_set_state(pipeline, GST_STATE_NULL); + if (bus) gst_object_unref(bus); + gst_object_unref(pipeline); + std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_BASE_DELAY_MS)); + continue; + } + + // ======== 主循环监听消息 ======== while (ctx->running) { GstMessage *msg = gst_bus_timed_pop_filtered( bus, 200 * GST_MSECOND, (GstMessageType)(GST_MESSAGE_ERROR | GST_MESSAGE_EOS | GST_MESSAGE_ELEMENT)); - // 检查帧超时:3 秒内没有检测到帧 + // 检查是否超时无帧 auto elapsed = std::chrono::duration_cast(std::chrono::steady_clock::now() - start_time).count(); if (!got_frame && elapsed > 5) { - GstState state; - gst_element_get_state(pipeline, &state, nullptr, 0); - if (state != GST_STATE_PLAYING) - { - ctx->status.running = false; - ctx->status.last_error = "Pipeline failed to reach PLAYING (maybe no device signal)"; - LOG_ERROR("[RTMP] " + key + " - " + ctx->status.last_error); - need_restart = true; - break; - } - else - { - ctx->status.running = true; - ctx->status.last_error.clear(); - LOG_INFO("[RTMP] " + key + " reached PLAYING but no frames yet, assuming OK"); - got_frame = true; - } + ctx->status.running = false; + ctx->status.last_error = "No frames detected (no video signal)"; + LOG_ERROR("[RTMP] " + key + " - " + ctx->status.last_error); + need_restart = true; + break; } if (!msg) continue; @@ -180,6 +213,8 @@ void RTMPManager::stream_loop(Camera cam, StreamContext *ctx) if (gst_message_has_name(msg, "fpsprobe")) { got_frame = true; + ctx->status.running = true; + ctx->status.last_error.clear(); } break; @@ -210,14 +245,16 @@ void RTMPManager::stream_loop(Camera cam, StreamContext *ctx) if (need_restart) break; } - // 清理资源 + // ======== 收尾与重启 ======== gst_element_set_state(pipeline, GST_STATE_NULL); if (bus) gst_object_unref(bus); gst_object_unref(pipeline); if (ctx->running) { - LOG_WARN("[RTMP] Restarting " + key + " in 3s..."); + consecutive_failures++; + LOG_WARN("[RTMP] Restarting " + key + " in 3s... (fail count " + std::to_string(consecutive_failures) + + ")"); std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_BASE_DELAY_MS)); } }