#include #include #include #include #include "node.h" namespace rk3588 { class InputRtspNode : public INode { public: std::string Id() const override { return id_; } std::string Type() const override { return "input_rtsp"; } bool Init(const SimpleJson& config, const NodeContext& ctx) override { id_ = config.ValueOr("id", "input_rtsp"); url_ = config.ValueOr("url", ""); fps_ = config.ValueOr("fps", 25); width_ = config.ValueOr("width", 1920); height_ = config.ValueOr("height", 1080); if (ctx.output_queues.empty()) { std::cerr << "[input_rtsp] no downstream queue configured for node " << id_ << "\n"; return false; } out_queue_ = ctx.output_queues[0]; return true; } bool Start() override { if (!out_queue_) return false; running_.store(true); worker_ = std::thread(&InputRtspNode::Loop, this); std::cout << "[input_rtsp] start url=" << url_ << " fps=" << fps_ << "\n"; return true; } void Stop() override { running_.store(false); if (out_queue_) out_queue_->Stop(); if (worker_.joinable()) worker_.join(); } private: void Loop() { using namespace std::chrono; auto frame_interval = fps_ > 0 ? milliseconds(1000 / fps_) : milliseconds(40); while (running_.load()) { auto frame = std::make_shared(); frame->width = width_; frame->height = height_; frame->format = PixelFormat::NV12; frame->frame_id = ++frame_id_; frame->pts = duration_cast(steady_clock::now().time_since_epoch()).count(); out_queue_->Push(frame); if (frame_id_ % 100 == 0) { std::cout << "[input_rtsp] generated frame " << frame_id_ << " queue=" << out_queue_->Size() << " drops=" << out_queue_->DroppedCount() << "\n"; } std::this_thread::sleep_for(frame_interval); } } std::string id_; std::string url_; int fps_ = 25; int width_ = 1920; int height_ = 1080; std::atomic running_{false}; std::shared_ptr> out_queue_; std::thread worker_; uint64_t frame_id_ = 0; }; REGISTER_NODE(InputRtspNode, "input_rtsp"); } // namespace rk3588