优化日志输出
This commit is contained in:
parent
266fbb040e
commit
116950d2bd
15
Readme.md
15
Readme.md
@ -174,6 +174,12 @@ struct Frame {
|
||||
"size": 128,
|
||||
"policy": "drop_oldest" // drop_oldest / drop_newest / block
|
||||
},
|
||||
"debug": { // 可选:调试/日志开关(生产默认建议关闭)
|
||||
"stats": false, // 各节点的周期性统计日志(processed/queue/drops 等)
|
||||
"stats_interval": 100, // 统计日志间隔(帧数)
|
||||
"detections": false, // 部分 AI 节点的前几帧检测框调试输出
|
||||
"ffmpeg_log_level": "error" // FFmpeg 日志级别(影响 HLS/RTSP mux 的内部日志;默认 error)
|
||||
},
|
||||
"...特定节点参数..."
|
||||
}
|
||||
```
|
||||
@ -181,6 +187,11 @@ struct Frame {
|
||||
- `enable = false`:GraphMgr 构建图时可直接忽略该节点及相关 edges。
|
||||
- `role` 主要用于配置校验(source 不应有上游,sink 不应有下游等)。
|
||||
|
||||
**日志/性能建议:**
|
||||
|
||||
- 生产环境建议:`global.log_level=warn`,并保持各节点 `debug.stats=false`,避免高频 stdout/stderr 造成 CPU 抖动。
|
||||
- 需要定位丢帧/队列积压时,再对目标节点打开 `debug.stats=true`(并把 `stats_interval` 调大,如 500/1000)。
|
||||
|
||||
### 4.2 INode 接口(含 Drain)
|
||||
|
||||
```cpp
|
||||
@ -287,6 +298,10 @@ GraphMgr 负责:
|
||||
}
|
||||
```
|
||||
|
||||
> 说明:`global.log_level` 只控制框架内部 Logger(debug/info/warn/error);
|
||||
> 若启用了 FFmpeg(例如 publish 的 HLS mux),建议通过节点 `debug.ffmpeg_log_level` 将 FFmpeg 内部日志降到 `error`,
|
||||
> 避免出现大量类似 `hls ... Opening ...` 的 info 日志刷屏。
|
||||
|
||||
- **优先方式**:使用 `templates + instances` 快速生成多路通道。
|
||||
- **高级用法**:直接使用 `graphs` 写复杂拓扑(例如:一条流拆成多个完全不同的分支)。
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
|
||||
#include "ai_scheduler.h"
|
||||
#include "node.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
#if defined(RK3588_ENABLE_RKNN)
|
||||
#include "rknn_api.h"
|
||||
@ -273,6 +274,13 @@ public:
|
||||
model_input_h_ = config.ValueOr<int>("model_h", 640);
|
||||
num_classes_ = config.ValueOr<int>("num_classes", 80);
|
||||
|
||||
if (const SimpleJson* dbg = config.Find("debug"); dbg && dbg->IsObject()) {
|
||||
stats_log_ = dbg->ValueOr<bool>("stats", stats_log_);
|
||||
stats_interval_ = std::max<uint64_t>(
|
||||
1, static_cast<uint64_t>(dbg->ValueOr<int>("stats_interval", static_cast<int>(stats_interval_))));
|
||||
debug_det_ = dbg->ValueOr<bool>("detections", debug_det_);
|
||||
}
|
||||
|
||||
// Optional inference throttle. 0 = run every frame.
|
||||
infer_interval_ms_ = std::max<int64_t>(0, static_cast<int64_t>(config.ValueOr<int>("infer_interval_ms", 0)));
|
||||
if (infer_interval_ms_ <= 0) {
|
||||
@ -338,17 +346,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "[ai_yolo] model loaded via AiScheduler: " << model_path_
|
||||
<< " (handle=" << model_handle_ << ", version="
|
||||
<< (yolo_version_ == YoloVersion::V5 ? "v5" : "v8") << ")\n";
|
||||
LogInfo("[ai_yolo] model loaded via AiScheduler: " + model_path_ +
|
||||
" (handle=" + std::to_string(model_handle_) + ", version=" +
|
||||
(yolo_version_ == YoloVersion::V5 ? "v5" : "v8") + ")");
|
||||
#else
|
||||
std::cout << "[ai_yolo] RKNN disabled, will passthrough frames\n";
|
||||
LogWarn("[ai_yolo] RKNN disabled, will passthrough frames");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Start() override {
|
||||
std::cout << "[ai_yolo] started, conf=" << conf_thresh_ << " nms=" << nms_thresh_ << "\n";
|
||||
LogInfo("[ai_yolo] start id=" + id_ + " conf=" + std::to_string(conf_thresh_) +
|
||||
" nms=" + std::to_string(nms_thresh_));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -359,7 +368,7 @@ public:
|
||||
model_handle_ = kInvalidModelHandle;
|
||||
}
|
||||
#endif
|
||||
std::cout << "[ai_yolo] stopped\n";
|
||||
LogInfo("[ai_yolo] stop id=" + id_);
|
||||
}
|
||||
|
||||
NodeStatus Process(FramePtr frame) override {
|
||||
@ -381,8 +390,8 @@ public:
|
||||
PushToDownstream(frame);
|
||||
++processed_;
|
||||
|
||||
if (processed_ % 100 == 0) {
|
||||
std::cout << "[ai_yolo] processed " << processed_ << " frames\n";
|
||||
if (stats_log_ && stats_interval_ > 0 && (processed_ % stats_interval_) == 0) {
|
||||
LogInfo("[ai_yolo] processed=" + std::to_string(processed_) + " id=" + id_);
|
||||
}
|
||||
return NodeStatus::OK;
|
||||
}
|
||||
@ -551,11 +560,12 @@ private:
|
||||
det.bbox.h = static_cast<float>(Clamp(static_cast<int>(h / scale_h), 0, frame->height - static_cast<int>(det.bbox.y)));
|
||||
det.track_id = -1;
|
||||
|
||||
if (det_result->items.size() < 3 && processed_ < 10) {
|
||||
std::cout << "[ai_yolo] det: raw(" << x1 << "," << y1 << "," << w << "," << h
|
||||
<< ") -> bbox(" << det.bbox.x << "," << det.bbox.y << ","
|
||||
<< det.bbox.w << "," << det.bbox.h << ") cls=" << cls_id
|
||||
<< " score=" << det.score << "\n";
|
||||
if (debug_det_ && det_result->items.size() < 3 && processed_ < 10) {
|
||||
LogDebug("[ai_yolo] det: raw(" + std::to_string(x1) + "," + std::to_string(y1) + "," +
|
||||
std::to_string(w) + "," + std::to_string(h) + ") -> bbox(" +
|
||||
std::to_string(det.bbox.x) + "," + std::to_string(det.bbox.y) + "," +
|
||||
std::to_string(det.bbox.w) + "," + std::to_string(det.bbox.h) + ") cls=" +
|
||||
std::to_string(cls_id) + " score=" + std::to_string(det.score));
|
||||
}
|
||||
|
||||
det_result->items.push_back(det);
|
||||
@ -668,11 +678,12 @@ private:
|
||||
det.track_id = -1;
|
||||
|
||||
// Debug output for first few detections
|
||||
if (det_result->items.size() < 3 && processed_ < 10) {
|
||||
std::cout << "[ai_yolo] det: raw(" << x1 << "," << y1 << "," << w << "," << h
|
||||
<< ") -> bbox(" << det.bbox.x << "," << det.bbox.y << ","
|
||||
<< det.bbox.w << "," << det.bbox.h << ") cls=" << cls_id
|
||||
<< " score=" << det.score << "\n";
|
||||
if (debug_det_ && det_result->items.size() < 3 && processed_ < 10) {
|
||||
LogDebug("[ai_yolo] det: raw(" + std::to_string(x1) + "," + std::to_string(y1) + "," +
|
||||
std::to_string(w) + "," + std::to_string(h) + ") -> bbox(" +
|
||||
std::to_string(det.bbox.x) + "," + std::to_string(det.bbox.y) + "," +
|
||||
std::to_string(det.bbox.w) + "," + std::to_string(det.bbox.h) + ") cls=" +
|
||||
std::to_string(cls_id) + " score=" + std::to_string(det.score));
|
||||
}
|
||||
|
||||
det_result->items.push_back(det);
|
||||
@ -697,6 +708,10 @@ private:
|
||||
std::vector<std::shared_ptr<SpscQueue<FramePtr>>> output_queues_;
|
||||
uint64_t processed_ = 0;
|
||||
|
||||
bool stats_log_ = false;
|
||||
uint64_t stats_interval_ = 100;
|
||||
bool debug_det_ = false;
|
||||
|
||||
int64_t infer_interval_ms_ = 0;
|
||||
int64_t last_infer_pts_ms_ = 0;
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#include <atomic>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
@ -12,6 +13,7 @@
|
||||
|
||||
#include "node.h"
|
||||
#include "utils/thread_affinity.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
#if defined(RK3588_ENABLE_MPP)
|
||||
extern "C" {
|
||||
@ -53,6 +55,12 @@ public:
|
||||
reconnect_sec_ = config.ValueOr<int>("reconnect_sec", 5);
|
||||
reconnect_backoff_max_sec_ = config.ValueOr<int>("reconnect_backoff_max_sec", 30);
|
||||
fallback_to_stub_on_fail_ = config.ValueOr<bool>("fallback_to_stub_on_fail", false);
|
||||
|
||||
if (const SimpleJson* dbg = config.Find("debug"); dbg && dbg->IsObject()) {
|
||||
stats_log_ = dbg->ValueOr<bool>("stats", stats_log_);
|
||||
stats_interval_ = std::max<uint64_t>(
|
||||
1, static_cast<uint64_t>(dbg->ValueOr<int>("stats_interval", static_cast<int>(stats_interval_))));
|
||||
}
|
||||
cpu_affinity_ = ParseCpuAffinity(config);
|
||||
if (ctx.output_queues.empty()) {
|
||||
std::cerr << "[input_rtsp] no downstream queue configured for node " << id_ << "\n";
|
||||
@ -86,16 +94,16 @@ public:
|
||||
worker_ = std::thread(&InputRtspNode::LoopStub, this);
|
||||
#endif
|
||||
|
||||
std::cout << "[input_rtsp] start url=" << url_ << " fps=" << fps_;
|
||||
std::string mode;
|
||||
#if defined(RK3588_ENABLE_MPP)
|
||||
if (use_mpp_) std::cout << " (ffmpeg demux + mpp decode)";
|
||||
else if (use_ffmpeg_) std::cout << " (ffmpeg cpu decode" << (ffmpeg_force_tcp_ ? ", tcp" : ", udp") << ")";
|
||||
else std::cout << " (stub)";
|
||||
if (use_mpp_) mode = " (ffmpeg demux + mpp decode)";
|
||||
else if (use_ffmpeg_) mode = std::string(" (ffmpeg cpu decode") + (ffmpeg_force_tcp_ ? ", tcp)" : ", udp)");
|
||||
else mode = " (stub)";
|
||||
#else
|
||||
if (use_ffmpeg_) std::cout << " (ffmpeg cpu decode" << (ffmpeg_force_tcp_ ? ", tcp" : ", udp") << ")";
|
||||
else std::cout << " (stub)";
|
||||
if (use_ffmpeg_) mode = std::string(" (ffmpeg cpu decode") + (ffmpeg_force_tcp_ ? ", tcp)" : ", udp)");
|
||||
else mode = " (stub)";
|
||||
#endif
|
||||
std::cout << "\n";
|
||||
LogInfo("[input_rtsp] start id=" + id_ + " url=" + url_ + " fps=" + std::to_string(fps_) + mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -190,11 +198,10 @@ private:
|
||||
frame->pts = duration_cast<microseconds>(steady_clock::now().time_since_epoch()).count();
|
||||
PushToDownstream(frame);
|
||||
|
||||
if (frame_id_ % 100 == 0) {
|
||||
std::cout << "[input_rtsp] generated frame " << frame_id_ << " queue="
|
||||
<< (out_queues_.empty() ? 0 : out_queues_[0]->Size())
|
||||
<< " drops=" << (out_queues_.empty() ? 0 : out_queues_[0]->DroppedCount())
|
||||
<< "\n";
|
||||
if (stats_log_ && stats_interval_ > 0 && (frame_id_ % stats_interval_) == 0) {
|
||||
LogInfo("[input_rtsp] generated frame=" + std::to_string(frame_id_) +
|
||||
" queue=" + std::to_string(out_queues_.empty() ? 0 : out_queues_[0]->Size()) +
|
||||
" drops=" + std::to_string(out_queues_.empty() ? 0 : out_queues_[0]->DroppedCount()));
|
||||
}
|
||||
std::this_thread::sleep_for(frame_interval);
|
||||
}
|
||||
@ -354,11 +361,10 @@ private:
|
||||
}
|
||||
|
||||
PushToDownstream(frame);
|
||||
if (frame_id_ % 100 == 0) {
|
||||
std::cout << "[input_rtsp] recv frame " << frame->frame_id
|
||||
<< " queue=" << (out_queues_.empty() ? 0 : out_queues_[0]->Size())
|
||||
<< " drops=" << (out_queues_.empty() ? 0 : out_queues_[0]->DroppedCount())
|
||||
<< "\n";
|
||||
if (stats_log_ && stats_interval_ > 0 && (frame_id_ % stats_interval_) == 0) {
|
||||
LogInfo("[input_rtsp] recv frame=" + std::to_string(frame->frame_id) +
|
||||
" queue=" + std::to_string(out_queues_.empty() ? 0 : out_queues_[0]->Size()) +
|
||||
" drops=" + std::to_string(out_queues_.empty() ? 0 : out_queues_[0]->DroppedCount()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -750,9 +756,10 @@ private:
|
||||
}
|
||||
|
||||
if (extra && extra_size > 0) {
|
||||
std::cout << "[input_rtsp] send extra_data size=" << extra_size
|
||||
<< " annexb=" << (IsAnnexB(extra, extra_size) ? 1 : 0)
|
||||
<< "\n";
|
||||
if (stats_log_) {
|
||||
LogInfo("[input_rtsp] send extra_data size=" + std::to_string(extra_size) +
|
||||
" annexb=" + std::to_string(IsAnnexB(extra, extra_size) ? 1 : 0));
|
||||
}
|
||||
if (!dec.SendExtraData(extra, extra_size)) {
|
||||
std::cerr << "[input_rtsp] send extra_data failed\n";
|
||||
}
|
||||
@ -776,8 +783,8 @@ private:
|
||||
const bool is_idr = key_flag || ns.has_idr;
|
||||
if (need_idr && !is_idr) {
|
||||
++dropped_until_idr;
|
||||
if (!announced_wait_idr || dropped_until_idr % 300 == 0) {
|
||||
std::cout << "[input_rtsp] waiting for IDR/keyframe; dropped=" << dropped_until_idr << "\n";
|
||||
if (stats_log_ && (!announced_wait_idr || dropped_until_idr % 300 == 0)) {
|
||||
LogInfo("[input_rtsp] waiting for IDR/keyframe; dropped=" + std::to_string(dropped_until_idr));
|
||||
announced_wait_idr = true;
|
||||
}
|
||||
return;
|
||||
@ -826,32 +833,26 @@ private:
|
||||
last_pts_us = pts_us;
|
||||
have_last_pts = true;
|
||||
|
||||
if (pkt_count <= 3 || pkt_count % 300 == 0) {
|
||||
std::cout << "[input_rtsp] recv pkt#" << pkt_count
|
||||
<< " size=" << pkt->size
|
||||
<< " pts=";
|
||||
if (raw_pts == AV_NOPTS_VALUE) std::cout << "NOPTS";
|
||||
else std::cout << raw_pts;
|
||||
std::cout << " dts=";
|
||||
if (raw_dts == AV_NOPTS_VALUE) std::cout << "NOPTS";
|
||||
else std::cout << raw_dts;
|
||||
std::cout << " pts_us=" << pts_us
|
||||
<< " key=" << ((pkt->flags & AV_PKT_FLAG_KEY) ? 1 : 0)
|
||||
<< "\n";
|
||||
if (stats_log_ && (pkt_count <= 3 || pkt_count % 300 == 0)) {
|
||||
LogInfo("[input_rtsp] recv pkt#" + std::to_string(pkt_count) +
|
||||
" size=" + std::to_string(pkt->size) +
|
||||
" pts=" + (raw_pts == AV_NOPTS_VALUE ? std::string("NOPTS") : std::to_string(raw_pts)) +
|
||||
" dts=" + (raw_dts == AV_NOPTS_VALUE ? std::string("NOPTS") : std::to_string(raw_dts)) +
|
||||
" pts_us=" + std::to_string(pts_us) +
|
||||
" key=" + std::to_string((pkt->flags & AV_PKT_FLAG_KEY) ? 1 : 0));
|
||||
}
|
||||
|
||||
if (IsAnnexB(pkt->data, static_cast<size_t>(pkt->size))) {
|
||||
if (pkt_count <= 10) {
|
||||
if (stats_log_ && pkt_count <= 10) {
|
||||
int sc = GetAnnexBStartCodeSize(pkt->data, static_cast<size_t>(pkt->size));
|
||||
if (sc > 0 && static_cast<size_t>(sc) < static_cast<size_t>(pkt->size)) {
|
||||
uint8_t b0 = pkt->data[sc];
|
||||
int h264_type = b0 & 0x1F;
|
||||
int h265_type = (b0 >> 1) & 0x3F;
|
||||
std::cout << "[input_rtsp] pkt#" << pkt_count
|
||||
<< " nal(h264)=" << h264_type
|
||||
<< " nal(h265)=" << h265_type
|
||||
<< " first_byte=0x" << std::hex << static_cast<int>(b0) << std::dec
|
||||
<< "\n";
|
||||
LogInfo("[input_rtsp] pkt#" + std::to_string(pkt_count) +
|
||||
" nal(h264)=" + std::to_string(h264_type) +
|
||||
" nal(h265)=" + std::to_string(h265_type) +
|
||||
" first_byte=" + std::to_string(static_cast<int>(b0)));
|
||||
}
|
||||
}
|
||||
handle_annexb(pkt->data, static_cast<size_t>(pkt->size),
|
||||
@ -942,11 +943,10 @@ private:
|
||||
|
||||
PushToDownstream(frame);
|
||||
|
||||
if (frame_id_ <= 3 || frame_id_ % 100 == 0) {
|
||||
std::cout << "[input_rtsp] mpp frame " << frame->frame_id
|
||||
<< " queue=" << (out_queues_.empty() ? 0 : out_queues_[0]->Size())
|
||||
<< " drops=" << (out_queues_.empty() ? 0 : out_queues_[0]->DroppedCount())
|
||||
<< "\n";
|
||||
if (stats_log_ && (frame_id_ <= 3 || (stats_interval_ > 0 && (frame_id_ % stats_interval_) == 0))) {
|
||||
LogInfo("[input_rtsp] mpp frame=" + std::to_string(frame->frame_id) +
|
||||
" queue=" + std::to_string(out_queues_.empty() ? 0 : out_queues_[0]->Size()) +
|
||||
" drops=" + std::to_string(out_queues_.empty() ? 0 : out_queues_[0]->DroppedCount()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -968,6 +968,9 @@ private:
|
||||
int reconnect_backoff_max_sec_ = 30;
|
||||
bool fallback_to_stub_on_fail_ = false;
|
||||
std::vector<int> cpu_affinity_;
|
||||
|
||||
bool stats_log_ = false;
|
||||
uint64_t stats_interval_ = 100;
|
||||
};
|
||||
|
||||
REGISTER_NODE(InputRtspNode, "input_rtsp");
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "node.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
namespace rk3588 {
|
||||
|
||||
@ -288,12 +289,18 @@ public:
|
||||
line_width_ = config.ValueOr<int>("line_width", 2);
|
||||
font_scale_ = config.ValueOr<int>("font_scale", 1);
|
||||
|
||||
if (const SimpleJson* dbg = config.Find("debug"); dbg && dbg->IsObject()) {
|
||||
stats_log_ = dbg->ValueOr<bool>("stats", stats_log_);
|
||||
stats_interval_ = std::max<uint64_t>(
|
||||
1, static_cast<uint64_t>(dbg->ValueOr<int>("stats_interval", static_cast<int>(stats_interval_))));
|
||||
}
|
||||
|
||||
// Load custom labels from config
|
||||
if (const SimpleJson* labels = config.Find("labels")) {
|
||||
for (const auto& item : labels->AsArray()) {
|
||||
labels_.push_back(item.AsString(""));
|
||||
}
|
||||
std::cout << "[osd] loaded " << labels_.size() << " custom labels\n";
|
||||
LogInfo("[osd] loaded " + std::to_string(labels_.size()) + " custom labels");
|
||||
}
|
||||
|
||||
input_queue_ = ctx.input_queue;
|
||||
@ -310,12 +317,13 @@ public:
|
||||
}
|
||||
|
||||
bool Start() override {
|
||||
std::cout << "[osd] started, draw_bbox=" << draw_bbox_ << " draw_text=" << draw_text_ << "\n";
|
||||
LogInfo(std::string("[osd] start id=") + id_ + " draw_bbox=" + (draw_bbox_ ? "true" : "false") +
|
||||
" draw_text=" + (draw_text_ ? "true" : "false"));
|
||||
return true;
|
||||
}
|
||||
|
||||
void Stop() override {
|
||||
std::cout << "[osd] stopped\n";
|
||||
LogInfo("[osd] stop id=" + id_);
|
||||
}
|
||||
|
||||
NodeStatus Process(FramePtr frame) override {
|
||||
@ -332,8 +340,8 @@ public:
|
||||
PushToDownstream(out);
|
||||
++processed_;
|
||||
|
||||
if (processed_ % 100 == 0) {
|
||||
std::cout << "[osd] processed " << processed_ << " frames\n";
|
||||
if (stats_log_ && stats_interval_ > 0 && (processed_ % stats_interval_) == 0) {
|
||||
LogInfo("[osd] processed=" + std::to_string(processed_) + " id=" + id_);
|
||||
}
|
||||
return NodeStatus::OK;
|
||||
}
|
||||
@ -437,6 +445,9 @@ private:
|
||||
std::shared_ptr<SpscQueue<FramePtr>> input_queue_;
|
||||
std::vector<std::shared_ptr<SpscQueue<FramePtr>>> output_queues_;
|
||||
uint64_t processed_ = 0;
|
||||
|
||||
bool stats_log_ = false;
|
||||
uint64_t stats_interval_ = 100;
|
||||
};
|
||||
|
||||
REGISTER_NODE(OsdNode, "osd");
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
|
||||
#include "node.h"
|
||||
#include "utils/dma_alloc.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
#if defined(RK3588_ENABLE_RGA)
|
||||
#include "im2d.hpp"
|
||||
@ -260,6 +261,11 @@ public:
|
||||
const bool requested_use_rga = config.ValueOr<bool>("use_rga", true);
|
||||
use_rga_ = requested_use_rga;
|
||||
|
||||
if (const SimpleJson* dbg = config.Find("debug"); dbg && dbg->IsObject()) {
|
||||
stats_log_ = dbg->ValueOr<bool>("stats", stats_log_);
|
||||
stats_interval_ = std::max<uint64_t>(1, static_cast<uint64_t>(dbg->ValueOr<int>("stats_interval", static_cast<int>(stats_interval_))));
|
||||
}
|
||||
|
||||
input_queue_ = ctx.input_queue;
|
||||
if (!input_queue_) {
|
||||
std::cerr << "[preprocess] no input queue for node " << id_ << "\n";
|
||||
@ -288,8 +294,8 @@ public:
|
||||
}
|
||||
|
||||
bool Start() override {
|
||||
std::cout << "[preprocess] start dst=" << dst_w_ << "x" << dst_h_
|
||||
<< (use_rga_ ? " (rga)" : " (swscale)") << "\n";
|
||||
LogInfo("[preprocess] start id=" + id_ + " dst=" + std::to_string(dst_w_) + "x" + std::to_string(dst_h_) +
|
||||
(use_rga_ ? " (rga)" : " (swscale)"));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -331,8 +337,8 @@ private:
|
||||
void ProcessPassthrough(FramePtr frame) {
|
||||
PushToDownstream(frame);
|
||||
++processed_;
|
||||
if (processed_ % 100 == 0) {
|
||||
std::cout << "[preprocess] passthrough frame " << frame->frame_id << "\n";
|
||||
if (stats_log_ && stats_interval_ > 0 && (processed_ % stats_interval_) == 0) {
|
||||
LogInfo("[preprocess] passthrough frame=" + std::to_string(frame->frame_id) + " id=" + id_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -362,9 +368,10 @@ private:
|
||||
if (!need_cvt && !need_resize) {
|
||||
PushToDownstream(frame);
|
||||
++processed_;
|
||||
if (processed_ % 100 == 0) {
|
||||
std::cout << "[preprocess] passthrough frame " << frame->frame_id
|
||||
<< " " << frame->width << "x" << frame->height << " (no change)\n";
|
||||
if (stats_log_ && stats_interval_ > 0 && (processed_ % stats_interval_) == 0) {
|
||||
LogInfo("[preprocess] passthrough frame=" + std::to_string(frame->frame_id) +
|
||||
" " + std::to_string(frame->width) + "x" + std::to_string(frame->height) + " (no change)" +
|
||||
" id=" + id_);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -415,14 +422,19 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (processed_ < 3) {
|
||||
std::cout << "[preprocess] src: " << frame->width << "x" << frame->height
|
||||
<< " fmt=" << static_cast<int>(frame->format) << " rga_fmt=" << src_fmt_rga
|
||||
<< " wstride=" << src_wstride << " hstride=" << src_hstride
|
||||
<< " data_size=" << frame->data_size << "\n";
|
||||
std::cout << "[preprocess] dst: " << out_w << "x" << out_h
|
||||
<< " fmt=" << static_cast<int>(out_fmt) << " rga_fmt=" << dst_fmt_rga
|
||||
<< " wstride=" << dst_wstride << " hstride=" << dst_hstride << "\n";
|
||||
if (stats_log_ && processed_ < 3) {
|
||||
LogInfo("[preprocess] src: " + std::to_string(frame->width) + "x" + std::to_string(frame->height) +
|
||||
" fmt=" + std::to_string(static_cast<int>(frame->format)) +
|
||||
" rga_fmt=" + std::to_string(src_fmt_rga) +
|
||||
" wstride=" + std::to_string(src_wstride) +
|
||||
" hstride=" + std::to_string(src_hstride) +
|
||||
" data_size=" + std::to_string(frame->data_size));
|
||||
LogInfo("[preprocess] dst: " + std::to_string(out_w) + "x" + std::to_string(out_h) +
|
||||
" fmt=" + std::to_string(static_cast<int>(out_fmt)) +
|
||||
" rga_fmt=" + std::to_string(dst_fmt_rga) +
|
||||
" wstride=" + std::to_string(dst_wstride) +
|
||||
" hstride=" + std::to_string(dst_hstride) +
|
||||
" out_size=" + std::to_string(out_size));
|
||||
}
|
||||
|
||||
rga_buffer_t src_buf{};
|
||||
@ -568,10 +580,10 @@ private:
|
||||
PushToDownstream(out_frame);
|
||||
++processed_;
|
||||
|
||||
if (processed_ % 100 == 0) {
|
||||
std::cout << "[preprocess] rga frame " << out_frame->frame_id
|
||||
<< " " << frame->width << "x" << frame->height
|
||||
<< " -> " << out_w << "x" << out_h << "\n";
|
||||
if (stats_log_ && stats_interval_ > 0 && (processed_ % stats_interval_) == 0) {
|
||||
LogInfo("[preprocess] rga frame=" + std::to_string(out_frame->frame_id) +
|
||||
" " + std::to_string(frame->width) + "x" + std::to_string(frame->height) +
|
||||
" -> " + std::to_string(out_w) + "x" + std::to_string(out_h));
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -652,10 +664,11 @@ private:
|
||||
PushToDownstream(out_frame);
|
||||
++processed_;
|
||||
|
||||
if (processed_ % 100 == 0) {
|
||||
std::cout << "[preprocess] swscale frame " << out_frame->frame_id
|
||||
<< " " << frame->width << "x" << frame->height
|
||||
<< " -> " << out_w << "x" << out_h << "\n";
|
||||
if (stats_log_ && stats_interval_ > 0 && (processed_ % stats_interval_) == 0) {
|
||||
LogInfo("[preprocess] swscale frame=" + std::to_string(out_frame->frame_id) +
|
||||
" " + std::to_string(frame->width) + "x" + std::to_string(frame->height) +
|
||||
" -> " + std::to_string(out_w) + "x" + std::to_string(out_h) +
|
||||
" id=" + id_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -770,6 +783,9 @@ private:
|
||||
PixelFormat dst_fmt_ = PixelFormat::UNKNOWN;
|
||||
bool use_rga_ = true;
|
||||
|
||||
bool stats_log_ = false;
|
||||
uint64_t stats_interval_ = 100;
|
||||
|
||||
std::shared_ptr<SpscQueue<FramePtr>> input_queue_;
|
||||
std::vector<std::shared_ptr<SpscQueue<FramePtr>>> output_queues_;
|
||||
uint64_t processed_ = 0;
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
@ -16,6 +18,8 @@
|
||||
#include <unordered_set>
|
||||
#include "node.h"
|
||||
|
||||
#include "utils/logger.h"
|
||||
|
||||
#include "media/encoded_video_meta.h"
|
||||
|
||||
#if defined(RK3588_ENABLE_FFMPEG)
|
||||
@ -43,6 +47,27 @@ namespace rk3588 {
|
||||
|
||||
namespace {
|
||||
inline int Align16(int v) { return (v + 15) & ~15; }
|
||||
|
||||
#if defined(RK3588_ENABLE_FFMPEG)
|
||||
static int FfmpegLogLevelFromString(std::string s) {
|
||||
for (auto& c : s) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
||||
if (s == "quiet" || s == "0") return AV_LOG_QUIET;
|
||||
if (s == "panic" || s == "1") return AV_LOG_PANIC;
|
||||
if (s == "fatal" || s == "2") return AV_LOG_FATAL;
|
||||
if (s == "error" || s == "3") return AV_LOG_ERROR;
|
||||
if (s == "warning" || s == "warn" || s == "4") return AV_LOG_WARNING;
|
||||
if (s == "info" || s == "5") return AV_LOG_INFO;
|
||||
if (s == "verbose" || s == "6") return AV_LOG_VERBOSE;
|
||||
if (s == "debug" || s == "7") return AV_LOG_DEBUG;
|
||||
if (s == "trace" || s == "8") return AV_LOG_TRACE;
|
||||
return AV_LOG_ERROR;
|
||||
}
|
||||
|
||||
static void ApplyFfmpegLogLevel(const std::string& level) {
|
||||
const int lv = FfmpegLogLevelFromString(level);
|
||||
av_log_set_level(lv);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
struct OutputConfig {
|
||||
@ -87,7 +112,7 @@ public:
|
||||
running_ = true;
|
||||
monitor_thread_ = std::thread(&AvMuxer::MonitorLoop, this);
|
||||
|
||||
std::cout << "[publish] Muxer initialized async for " << url_ << "\n";
|
||||
LogInfo("[publish] muxer init async for " + url_);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -148,7 +173,7 @@ private:
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
ready_ = true;
|
||||
warned_ = false;
|
||||
std::cout << "[publish] Server ready: " << url_ << "\n";
|
||||
LogInfo("[publish] muxer server ready: " + url_);
|
||||
}
|
||||
|
||||
// Wait until error occurs or stop requested
|
||||
@ -615,6 +640,20 @@ public:
|
||||
use_ffmpeg_mux_ = config.ValueOr<bool>("use_ffmpeg_mux", true);
|
||||
attach_encoded_meta_ = config.ValueOr<bool>("attach_encoded_meta", !output_queues_.empty());
|
||||
|
||||
if (const SimpleJson* dbg = config.Find("debug"); dbg && dbg->IsObject()) {
|
||||
stats_log_ = dbg->ValueOr<bool>("stats", stats_log_);
|
||||
stats_interval_ = std::max<uint64_t>(
|
||||
1, static_cast<uint64_t>(dbg->ValueOr<int>("stats_interval", static_cast<int>(stats_interval_))));
|
||||
#if defined(RK3588_ENABLE_FFMPEG)
|
||||
ffmpeg_log_level_ = dbg->ValueOr<std::string>("ffmpeg_log_level", ffmpeg_log_level_);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(RK3588_ENABLE_FFMPEG)
|
||||
// Reduce FFmpeg's internal info logs (e.g., HLS "Opening ...") unless explicitly enabled.
|
||||
ApplyFfmpegLogLevel(ffmpeg_log_level_);
|
||||
#endif
|
||||
|
||||
const SimpleJson* outputs = config.Find("outputs");
|
||||
if (outputs && outputs->IsArray()) {
|
||||
for (const auto& o : outputs->AsArray()) {
|
||||
@ -656,9 +695,9 @@ public:
|
||||
}
|
||||
|
||||
bool Start() override {
|
||||
std::cout << "[publish] start codec=" << codec_ << " fps=" << fps_ << " gop=" << gop_
|
||||
<< " bitrate=" << bitrate_kbps_ << "kbps"
|
||||
<< (use_mpp_ ? " (mpp venc)" : " (stub)") << "\n";
|
||||
LogInfo("[publish] start id=" + id_ + " codec=" + codec_ + " fps=" + std::to_string(fps_) +
|
||||
" gop=" + std::to_string(gop_) + " bitrate=" + std::to_string(bitrate_kbps_) + "kbps" +
|
||||
(use_mpp_ ? " (mpp venc)" : " (stub)"));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -864,7 +903,7 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << "[publish] zlm rtsp server ready: rtsp://0.0.0.0:" << port_ << "/" << app_ << "/" << stream_ << "\n";
|
||||
LogInfo("[publish] zlm rtsp server ready: rtsp://0.0.0.0:" + std::to_string(port_) + "/" + app_ + "/" + stream_);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1106,7 +1145,7 @@ private:
|
||||
}
|
||||
if (is_cfg) {
|
||||
self->seen_config_nal_ = true;
|
||||
std::cout << "[publish] zlm saw config nal" << "\n";
|
||||
LogDebug("[publish] zlm saw config nal");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1172,10 +1211,10 @@ private:
|
||||
|
||||
void ProcessStub(FramePtr frame) {
|
||||
++encoded_frames_;
|
||||
if (encoded_frames_ % 100 == 0) {
|
||||
std::cout << "[publish] stub frame " << frame->frame_id
|
||||
<< " queue=" << input_queue_->Size()
|
||||
<< " drops=" << input_queue_->DroppedCount() << "\n";
|
||||
if (stats_log_ && stats_interval_ > 0 && (encoded_frames_ % stats_interval_) == 0) {
|
||||
LogInfo("[publish] stub frame=" + std::to_string(frame->frame_id) +
|
||||
" queue=" + std::to_string(input_queue_->Size()) +
|
||||
" drops=" + std::to_string(input_queue_->DroppedCount()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1232,10 +1271,10 @@ private:
|
||||
frame->user_meta = meta;
|
||||
}
|
||||
++encoded_frames_;
|
||||
if (encoded_frames_ % 100 == 0) {
|
||||
std::cout << "[publish] encoded frame " << encoded_frames_
|
||||
<< " queue=" << input_queue_->Size()
|
||||
<< " drops=" << input_queue_->DroppedCount() << "\n";
|
||||
if (stats_log_ && stats_interval_ > 0 && (encoded_frames_ % stats_interval_) == 0) {
|
||||
LogInfo("[publish] encoded frames=" + std::to_string(encoded_frames_) +
|
||||
" queue=" + std::to_string(input_queue_->Size()) +
|
||||
" drops=" + std::to_string(input_queue_->DroppedCount()));
|
||||
}
|
||||
#if defined(RK3588_ENABLE_FFMPEG)
|
||||
if (use_ffmpeg_mux_ && mux_mgr_) mux_mgr_->Write(pkt);
|
||||
@ -1267,6 +1306,13 @@ private:
|
||||
std::vector<std::shared_ptr<SpscQueue<FramePtr>>> output_queues_;
|
||||
uint64_t encoded_frames_ = 0;
|
||||
|
||||
bool stats_log_ = false;
|
||||
uint64_t stats_interval_ = 100;
|
||||
|
||||
#if defined(RK3588_ENABLE_FFMPEG)
|
||||
std::string ffmpeg_log_level_ = "error";
|
||||
#endif
|
||||
|
||||
mutable std::mutex mu_;
|
||||
|
||||
bool attach_encoded_meta_ = false;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user