|
@@ -86,6 +86,8 @@ struct ChannelState {
|
|
|
std::atomic<uint64_t> disp_seq{0};
|
|
std::atomic<uint64_t> disp_seq{0};
|
|
|
int frame_count = 0;
|
|
int frame_count = 0;
|
|
|
int skip_frames = 3;
|
|
int skip_frames = 3;
|
|
|
|
|
+ int64_t last_display_ms = 0; // 上次生成显示帧时刻(显示降频用)
|
|
|
|
|
+ uint64_t last_cap_seq = 0; // 上次处理的解码帧序号(去重复处理)
|
|
|
bool size_recorded = false;
|
|
bool size_recorded = false;
|
|
|
bool alarm_latched = false; // 报警沿触发: 每次新报警只截一张
|
|
bool alarm_latched = false; // 报警沿触发: 每次新报警只截一张
|
|
|
chrono::steady_clock::time_point last_alarm_ts{};
|
|
chrono::steady_clock::time_point last_alarm_ts{};
|
|
@@ -395,11 +397,15 @@ int main(int argc, char* argv[]) {
|
|
|
bool steel_output = cfg.value("steel_output", true);
|
|
bool steel_output = cfg.value("steel_output", true);
|
|
|
int hdmi_grid_cols = cfg.value("hdmi_grid_cols", 0);
|
|
int hdmi_grid_cols = cfg.value("hdmi_grid_cols", 0);
|
|
|
bool hdmi_fullscreen = cfg.value("hdmi_fullscreen", true);
|
|
bool hdmi_fullscreen = cfg.value("hdmi_fullscreen", true);
|
|
|
|
|
+ // 显示帧生成帧率(所有输出端HDMI/MJPEG/手机最高约10-12fps, 无需每输入帧都生成)
|
|
|
|
|
+ int display_fps = clamp(cfg.value("display_fps", 12), 1, 30);
|
|
|
|
|
+ int display_interval_ms = 1000 / display_fps;
|
|
|
cout << "[Display] 网格输出: " << (grid_output ? "启用" : "禁用")
|
|
cout << "[Display] 网格输出: " << (grid_output ? "启用" : "禁用")
|
|
|
<< " 钢包位输出: " << (steel_output ? "启用" : "禁用")
|
|
<< " 钢包位输出: " << (steel_output ? "启用" : "禁用")
|
|
|
<< " 工位功能: " << (enable_bucket ? "启用" : "禁用")
|
|
<< " 工位功能: " << (enable_bucket ? "启用" : "禁用")
|
|
|
<< " 网格列=" << hdmi_grid_cols
|
|
<< " 网格列=" << hdmi_grid_cols
|
|
|
- << " 全屏=" << (hdmi_fullscreen ? "是" : "否") << endl;
|
|
|
|
|
|
|
+ << " 全屏=" << (hdmi_fullscreen ? "是" : "否")
|
|
|
|
|
+ << " 显示帧率=" << display_fps << "fps" << endl;
|
|
|
|
|
|
|
|
// ========== 姿态识别(跌倒检测) ==========
|
|
// ========== 姿态识别(跌倒检测) ==========
|
|
|
string pose_model_path = cfg.value("pose_model_path",
|
|
string pose_model_path = cfg.value("pose_model_path",
|
|
@@ -2059,6 +2065,12 @@ int main(int argc, char* argv[]) {
|
|
|
ch_snap.push_back(bc);
|
|
ch_snap.push_back(bc);
|
|
|
}
|
|
}
|
|
|
for (auto& ch : ch_snap) {
|
|
for (auto& ch : ch_snap) {
|
|
|
|
|
+ // 只在解码器产出新帧时才处理, 避免主循环高速重复处理同一帧
|
|
|
|
|
+ // (之前每秒重复memcpy/转换同一帧上千次, 是CPU主要浪费)
|
|
|
|
|
+ uint64_t capSeq = ch->capture->framesDecoded();
|
|
|
|
|
+ if (capSeq == ch->last_cap_seq) continue;
|
|
|
|
|
+ ch->last_cap_seq = capSeq;
|
|
|
|
|
+
|
|
|
Nv12Frame nv12;
|
|
Nv12Frame nv12;
|
|
|
if (!ch->capture->grabNv12(nv12)) {
|
|
if (!ch->capture->grabNv12(nv12)) {
|
|
|
if (ch->frame_count == 0 && ch->capture->isRunning())
|
|
if (ch->frame_count == 0 && ch->capture->isRunning())
|
|
@@ -2471,10 +2483,12 @@ int main(int argc, char* argv[]) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 显示帧: 每帧都生成(视频不跳帧), 推理仍按 skip_frames 跳帧
|
|
|
|
|
|
|
+ // 显示帧: 按 display_fps 降频生成(输出端最高10-12fps, 避免每输入帧白做转换)
|
|
|
// 检测框/围栏只在推理帧更新, 非推理帧复用最近一次推理结果
|
|
// 检测框/围栏只在推理帧更新, 非推理帧复用最近一次推理结果
|
|
|
cv::Mat display;
|
|
cv::Mat display;
|
|
|
- {
|
|
|
|
|
|
|
+ bool do_display = (nowMs() - ch->last_display_ms >= display_interval_ms);
|
|
|
|
|
+ if (do_display) {
|
|
|
|
|
+ ch->last_display_ms = nowMs();
|
|
|
std::vector<uint8_t> rgb8;
|
|
std::vector<uint8_t> rgb8;
|
|
|
int out_w, out_h;
|
|
int out_w, out_h;
|
|
|
ch->rga.processToRgb(nv12, rgb8, out_w, out_h);
|
|
ch->rga.processToRgb(nv12, rgb8, out_w, out_h);
|