#pragma once #include #include #include #include "frame/frame.h" #include "utils/simple_json.h" #include "utils/spsc_queue.h" namespace rk3588 { using FramePtr = std::shared_ptr; class IInferBackend; class IImageProcessor; enum class NodeStatus { OK, // Normal processing DROP, // Drop this frame (e.g., condition not met) ERROR // Error occurred, should log }; struct NodeContext { std::string graph_name; // For nodes with upstream input. std::shared_ptr> input_queue; // For nodes that produce downstream outputs (one queue per outgoing edge). std::vector>> output_queues; std::shared_ptr infer_backend; std::shared_ptr image_processor; }; class INode { public: virtual ~INode() = default; virtual std::string Id() const = 0; virtual std::string Type() const = 0; virtual bool Init(const SimpleJson& config, const NodeContext& ctx) = 0; // Initialize resources. // Note: For Source nodes, this should start the capture thread. // For Filter/Sink nodes, this should ONLY allocate resources; the framework will drive Process(). virtual bool Start() = 0; virtual void Stop() = 0; // Process a single frame (driven by GraphMgr for Filter/Sink nodes). // Returns status to indicate if frame was processed or dropped. virtual NodeStatus Process(FramePtr /*frame*/) { return NodeStatus::OK; } // Dynamic config update without restart. Returns true if update succeeded. virtual bool UpdateConfig(const SimpleJson& /*new_config*/) { return false; } // Optional custom metrics for graph-level aggregation/observability. // Return true if out is filled. virtual bool GetCustomMetrics(SimpleJson& /*out*/) const { return false; } // Called before Stop() to flush internal buffers (e.g., finish writing files). virtual void Drain() {} }; // ABI version for dynamic node plugins. // Bump when plugin-required symbols or contracts change. constexpr int kNodeAbiVersion = 3; using CreateNodeFn = INode* (*)(); using DestroyNodeFn = void (*)(INode*); using GetTypeFn = const char* (*)(); using GetAbiFn = int (*)(); struct NodeDeleter { DestroyNodeFn destroy = nullptr; void operator()(INode* p) const noexcept { if (!p) return; if (destroy) { destroy(p); } else { delete p; } } }; using NodePtr = std::unique_ptr; #define REGISTER_NODE(NodeClass, NodeTypeStr) \ extern "C" rk3588::INode* CreateNode() { \ return new NodeClass(); \ } \ extern "C" void DestroyNode(rk3588::INode* p) { \ delete p; \ } \ extern "C" const char* GetNodeType() { \ return NodeTypeStr; \ } \ extern "C" int GetAbiVersion() { \ return rk3588::kNodeAbiVersion; \ } } // namespace rk3588