87 lines
2.8 KiB
C++
87 lines
2.8 KiB
C++
#include <atomic>
|
|
#include <chrono>
|
|
#include <iostream>
|
|
#include <thread>
|
|
|
|
#include "node.h"
|
|
|
|
namespace rk3588 {
|
|
|
|
class PublishNode : public INode {
|
|
public:
|
|
std::string Id() const override { return id_; }
|
|
std::string Type() const override { return "publish"; }
|
|
|
|
bool Init(const SimpleJson& config, const NodeContext& ctx) override {
|
|
id_ = config.ValueOr<std::string>("id", "publish");
|
|
input_queue_ = ctx.input_queue;
|
|
codec_ = config.ValueOr<std::string>("codec", "h264");
|
|
fps_ = config.ValueOr<int>("fps", 25);
|
|
gop_ = config.ValueOr<int>("gop", 50);
|
|
bitrate_kbps_ = config.ValueOr<int>("bitrate_kbps", 4000);
|
|
// Outputs array optional; log first entry if present.
|
|
const SimpleJson* outputs = config.Find("outputs");
|
|
if (outputs && outputs->IsArray() && !outputs->AsArray().empty()) {
|
|
const auto& first = outputs->AsArray().front();
|
|
if (first.IsObject()) {
|
|
port_ = first.ValueOr<int>("port", 8554);
|
|
path_ = first.ValueOr<std::string>("path", "/live/cam1");
|
|
}
|
|
}
|
|
if (!input_queue_) {
|
|
std::cerr << "[publish] no input queue for node " << id_ << "\n";
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Start() override {
|
|
if (!input_queue_) return false;
|
|
running_.store(true);
|
|
worker_ = std::thread(&PublishNode::Loop, this);
|
|
std::cout << "[publish] start codec=" << codec_ << " fps=" << fps_ << " gop=" << gop_
|
|
<< " bitrate=" << bitrate_kbps_ << "kbps target rtsp://0.0.0.0:" << port_
|
|
<< path_ << "\n";
|
|
return true;
|
|
}
|
|
|
|
void Stop() override {
|
|
running_.store(false);
|
|
if (input_queue_) input_queue_->Stop();
|
|
if (worker_.joinable()) worker_.join();
|
|
}
|
|
|
|
private:
|
|
void Loop() {
|
|
using namespace std::chrono;
|
|
FramePtr frame;
|
|
while (running_.load()) {
|
|
if (!input_queue_->Pop(frame, milliseconds(200))) {
|
|
continue;
|
|
}
|
|
++encoded_frames_;
|
|
if (encoded_frames_ % 100 == 0 && frame) {
|
|
std::cout << "[publish] encoded frame " << frame->frame_id
|
|
<< " queue=" << input_queue_->Size()
|
|
<< " drops=" << input_queue_->DroppedCount() << "\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string id_;
|
|
std::string codec_ = "h264";
|
|
int fps_ = 25;
|
|
int gop_ = 50;
|
|
int bitrate_kbps_ = 4000;
|
|
int port_ = 8554;
|
|
std::string path_ = "/live/cam1";
|
|
std::atomic<bool> running_{false};
|
|
std::shared_ptr<SpscQueue<FramePtr>> input_queue_;
|
|
std::thread worker_;
|
|
uint64_t encoded_frames_ = 0;
|
|
};
|
|
|
|
REGISTER_NODE(PublishNode, "publish");
|
|
|
|
} // namespace rk3588
|