1
This commit is contained in:
parent
d802f80213
commit
befef76a3e
@ -14,6 +14,12 @@
|
|||||||
|
|
||||||
#include "logger.hpp"
|
#include "logger.hpp"
|
||||||
|
|
||||||
|
static bool device_exists(const std::string &path)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
return (stat(path.c_str(), &st) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
static std::string get_ip_address(const std::string &ifname)
|
static std::string get_ip_address(const std::string &ifname)
|
||||||
{
|
{
|
||||||
struct ifaddrs *ifaddr, *ifa;
|
struct ifaddrs *ifaddr, *ifa;
|
||||||
@ -129,6 +135,14 @@ RTMPManager::StreamResultInfo RTMPManager::start_camera(const Camera &cam, Strea
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 新增:设备节点存在性检查
|
||||||
|
if (!device_exists(cam.device))
|
||||||
|
{
|
||||||
|
res.result = 1;
|
||||||
|
res.reason = "Device not found: " + cam.device;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string key = make_stream_key(cam.name, type);
|
const std::string key = make_stream_key(cam.name, type);
|
||||||
|
|
||||||
std::unique_ptr<StreamContext> ctx;
|
std::unique_ptr<StreamContext> ctx;
|
||||||
@ -139,15 +153,13 @@ RTMPManager::StreamResultInfo RTMPManager::start_camera(const Camera &cam, Strea
|
|||||||
auto it = streams.find(key);
|
auto it = streams.find(key);
|
||||||
if (it != streams.end() && it->second->running.load())
|
if (it != streams.end() && it->second->running.load())
|
||||||
{
|
{
|
||||||
res.result = 0;
|
res.result = 1; // 修改为 1:表示重复启动,不是真成功
|
||||||
res.reason = "Already streaming";
|
res.reason = "Already streaming";
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = std::make_unique<StreamContext>();
|
ctx = std::make_unique<StreamContext>();
|
||||||
ctx->running.store(true);
|
ctx->running.store(true);
|
||||||
|
|
||||||
// 重要:在把 ctx 放入 map 之前,先从 ctx->start_promise 拿到 future
|
|
||||||
status_future = ctx->start_promise.get_future();
|
status_future = ctx->start_promise.get_future();
|
||||||
|
|
||||||
StreamContext *ctx_ptr = ctx.get();
|
StreamContext *ctx_ptr = ctx.get();
|
||||||
@ -202,7 +214,7 @@ RTMPManager::StreamResultInfo RTMPManager::stop_camera(const std::string &cam_na
|
|||||||
streams.erase(it);
|
streams.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool was_running = ctx->status.running; // ✅ 新增:判断是否真的在推流
|
bool was_running = ctx->running.load(); // ✅ 改为使用 running
|
||||||
ctx->running.store(false);
|
ctx->running.store(false);
|
||||||
|
|
||||||
if (ctx->thread.joinable()) ctx->thread.join();
|
if (ctx->thread.joinable()) ctx->thread.join();
|
||||||
@ -262,17 +274,15 @@ void RTMPManager::stream_loop(Camera cam, StreamType type, StreamContext *ctx)
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// 手动停止
|
|
||||||
if (!ctx->running.load())
|
if (!ctx->running.load())
|
||||||
{
|
{
|
||||||
status.running = false;
|
status.running = false;
|
||||||
status.last_result = StreamResult::UNKNOWN;
|
status.last_result = StreamResult::UNKNOWN;
|
||||||
status.last_error = "Stream stopped manually";
|
status.last_error = "Stream stopped manually";
|
||||||
try_set_start(status); // 若启动阶段还没返回,这里补一次
|
try_set_start(status);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 首帧超时(5s)
|
|
||||||
if (!first_frame &&
|
if (!first_frame &&
|
||||||
std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - t0).count() > 5)
|
std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - t0).count() > 5)
|
||||||
{
|
{
|
||||||
@ -301,8 +311,7 @@ void RTMPManager::stream_loop(Camera cam, StreamType type, StreamContext *ctx)
|
|||||||
status.running = true;
|
status.running = true;
|
||||||
ctx->status.running = true;
|
ctx->status.running = true;
|
||||||
status.last_result = StreamResult::OK;
|
status.last_result = StreamResult::OK;
|
||||||
status.last_error.clear();
|
try_set_start(status);
|
||||||
try_set_start(status); // 首帧成功:通知 start_camera
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -331,19 +340,21 @@ void RTMPManager::stream_loop(Camera cam, StreamType type, StreamContext *ctx)
|
|||||||
|
|
||||||
gst_message_unref(msg);
|
gst_message_unref(msg);
|
||||||
|
|
||||||
// 错误/EOS 后退出循环
|
|
||||||
if (status.last_result == StreamResult::CONNECTION_FAIL || status.last_result == StreamResult::EOS_RECEIVED)
|
if (status.last_result == StreamResult::CONNECTION_FAIL || status.last_result == StreamResult::EOS_RECEIVED)
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_element_set_state(pipeline, GST_STATE_NULL);
|
if (pipeline)
|
||||||
if (bus) gst_object_unref(bus);
|
{
|
||||||
gst_object_unref(pipeline);
|
gst_element_set_state(pipeline, GST_STATE_NULL);
|
||||||
|
gst_object_unref(pipeline);
|
||||||
|
}
|
||||||
|
if (bus)
|
||||||
|
{
|
||||||
|
gst_object_unref(bus);
|
||||||
|
}
|
||||||
|
|
||||||
ctx->status.running = false;
|
ctx->status.running = false;
|
||||||
// 线程收尾:这里不要删 map 里的 ctx,stop_camera 已经负责转移并 join
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTMPManager::stop_all()
|
void RTMPManager::stop_all()
|
||||||
@ -400,21 +411,24 @@ std::vector<RTMPManager::StreamResultInfo> RTMPManager::process_push_request(con
|
|||||||
|
|
||||||
for (int ch : item.channels)
|
for (int ch : item.channels)
|
||||||
{
|
{
|
||||||
if (ch < 0 || ch >= static_cast<int>(g_app_config.cameras.size())) continue;
|
if (ch < 0 || ch >= static_cast<int>(g_app_config.cameras.size()))
|
||||||
|
{
|
||||||
|
StreamResultInfo info;
|
||||||
|
info.loc = ch;
|
||||||
|
info.result = 1;
|
||||||
|
info.reason = "Invalid channel index";
|
||||||
|
info.url = "";
|
||||||
|
results.push_back(info);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const auto &cam = g_app_config.cameras[ch];
|
const auto &cam = g_app_config.cameras[ch];
|
||||||
StreamResultInfo info;
|
StreamResultInfo info;
|
||||||
|
|
||||||
if (item.switchVal == 0)
|
if (item.switchVal == 0)
|
||||||
{
|
|
||||||
// 开启推流
|
|
||||||
info = start_camera(cam, type);
|
info = start_camera(cam, type);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
// 停止推流
|
|
||||||
info = stop_camera(cam.name, type);
|
info = stop_camera(cam.name, type);
|
||||||
}
|
|
||||||
|
|
||||||
results.push_back(info);
|
results.push_back(info);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user