56e874ab6d
This commit introduces the full downstream runtime implementation needed to ingest, transform, and publish streams. It preserves the original upstream request boundary by packaging the entire cvmmap-streamer module (build config, public API, protocol and IPC glue, and simulator/tester entrypoints) in one coherent core unit. Keeping this group isolated enables reviewers to validate runtime behavior and correctness without mixing test evidence or process documentation changes. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
85 lines
2.1 KiB
C++
85 lines
2.1 KiB
C++
#pragma once
|
|
|
|
#include "cvmmap_streamer/config/runtime_config.hpp"
|
|
|
|
#include <chrono>
|
|
#include <cstdint>
|
|
#include <expected>
|
|
#include <span>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
namespace cvmmap_streamer::protocol {
|
|
|
|
struct RtmpPublisherStats {
|
|
std::uint64_t access_units{0};
|
|
std::uint64_t access_unit_bytes{0};
|
|
std::uint64_t video_messages{0};
|
|
std::uint64_t bytes_sent{0};
|
|
std::uint64_t send_errors{0};
|
|
std::uint64_t publish_failures{0};
|
|
std::uint64_t reconnect_attempts{0};
|
|
std::uint64_t reconnect_successes{0};
|
|
std::uint64_t reconnect_failures{0};
|
|
};
|
|
|
|
class RtmpPublisher {
|
|
public:
|
|
RtmpPublisher() = default;
|
|
~RtmpPublisher();
|
|
|
|
RtmpPublisher(const RtmpPublisher &) = delete;
|
|
RtmpPublisher &operator=(const RtmpPublisher &) = delete;
|
|
|
|
RtmpPublisher(RtmpPublisher &&other) noexcept;
|
|
RtmpPublisher &operator=(RtmpPublisher &&other) noexcept;
|
|
|
|
[[nodiscard]]
|
|
static std::expected<RtmpPublisher, std::string> create(const RuntimeConfig &config);
|
|
|
|
[[nodiscard]]
|
|
std::expected<void, std::string> publish_access_unit(std::span<const std::uint8_t> access_unit, std::uint64_t pts_ns);
|
|
|
|
[[nodiscard]]
|
|
const RtmpPublisherStats &stats() const;
|
|
|
|
void on_stream_reset();
|
|
|
|
void log_metrics() const;
|
|
|
|
private:
|
|
struct Session {
|
|
std::string original_url{};
|
|
std::string host{};
|
|
std::uint16_t port{1935};
|
|
std::string app{};
|
|
std::string stream{};
|
|
std::string tc_url{};
|
|
int socket_fd{-1};
|
|
std::uint32_t out_chunk_size{128};
|
|
std::uint32_t stream_id{1};
|
|
bool sequence_header_sent{false};
|
|
std::uint32_t reconnect_backoff_ms{250};
|
|
std::uint32_t consecutive_reconnect_failures{0};
|
|
std::chrono::steady_clock::time_point reconnect_due_at{};
|
|
bool in_cooldown{false};
|
|
};
|
|
|
|
[[nodiscard]]
|
|
std::expected<void, std::string> connect_session(Session &session);
|
|
|
|
void schedule_reconnect(Session &session, std::string_view reason, bool startup_path);
|
|
|
|
void close_session(Session &session);
|
|
|
|
CodecType codec_{CodecType::H264};
|
|
RtmpMode mode_{RtmpMode::Enhanced};
|
|
std::vector<Session> sessions_{};
|
|
RtmpPublisherStats stats_{};
|
|
bool had_successful_video_message_{false};
|
|
bool warned_all_sessions_closed_{false};
|
|
};
|
|
|
|
}
|