diff --git a/docs/encoded_passthrough.md b/docs/encoded_passthrough.md index 77eeae1..bb37509 100644 --- a/docs/encoded_passthrough.md +++ b/docs/encoded_passthrough.md @@ -53,6 +53,14 @@ Current assumptions: ## Outputs +### RTP + +RTP output accepts passthrough access units directly. + +- in encoded mode, SDP signaling and RTP packetization follow the codec from SHM metadata +- `config.encoder.codec` is ignored for RTP while passthrough is active +- raw mode still uses the configured local encoder and its codec + ### RTMP RTMP output accepts passthrough access units directly. diff --git a/include/cvmmap_streamer/protocol/rtp_publisher.hpp b/include/cvmmap_streamer/protocol/rtp_publisher.hpp index afe893f..d7044c2 100644 --- a/include/cvmmap_streamer/protocol/rtp_publisher.hpp +++ b/include/cvmmap_streamer/protocol/rtp_publisher.hpp @@ -33,7 +33,7 @@ public: UdpRtpPublisher &operator=(UdpRtpPublisher &&other) noexcept; [[nodiscard]] - static std::expected create(const RuntimeConfig &config); + static std::expected create(const RuntimeConfig &config, CodecType codec); void publish_access_unit(std::span access_unit, std::uint64_t pts_ns); diff --git a/src/pipeline/pipeline_runtime.cpp b/src/pipeline/pipeline_runtime.cpp index 9af9ae3..1e653d2 100644 --- a/src/pipeline/pipeline_runtime.cpp +++ b/src/pipeline/pipeline_runtime.cpp @@ -735,15 +735,6 @@ int run_pipeline(const RuntimeConfig &config) { return exit_code(PipelineExitCode::SubscriberError); } - if (config.outputs.rtp.enabled) { - auto created = protocol::UdpRtpPublisher::create(config); - if (!created) { - spdlog::error("pipeline RTP publisher init failed: {}", created.error()); - return exit_code(PipelineExitCode::InitializationError); - } - rtp_publisher.emplace(std::move(*created)); - } - PipelineStats stats{}; metrics::IngestEmitLatencyTracker latency_tracker{}; bool producer_offline{false}; @@ -775,6 +766,7 @@ int run_pipeline(const RuntimeConfig &config) { warned_unknown_depth_unit = false; using_encoded_input = false; active_stream_info.reset(); + rtp_publisher.reset(); rtmp_output.reset(); }; @@ -792,7 +784,17 @@ int run_pipeline(const RuntimeConfig &config) { const auto start_outputs_from_stream_info = [&](const encode::EncodedStreamInfo &stream_info, const ipc::FrameInfo &target_info) -> Status { + rtp_publisher.reset(); rtmp_output.reset(); + if (config.outputs.rtp.enabled) { + auto created = protocol::UdpRtpPublisher::create(config, stream_info.codec); + if (!created) { + return unexpected_error( + ERR_INTERNAL, + "pipeline RTP publisher init failed: " + created.error()); + } + rtp_publisher.emplace(std::move(*created)); + } if (config.outputs.rtmp.enabled) { auto created = protocol::make_rtmp_output(config, stream_info); if (!created) { @@ -901,6 +903,7 @@ int run_pipeline(const RuntimeConfig &config) { active_stream_info.reset(); using_encoded_input = false; active_info.reset(); + rtp_publisher.reset(); rtmp_output.reset(); break; } diff --git a/src/protocol/rtp_publisher.cpp b/src/protocol/rtp_publisher.cpp index 2c5211a..21c0d19 100644 --- a/src/protocol/rtp_publisher.cpp +++ b/src/protocol/rtp_publisher.cpp @@ -179,7 +179,7 @@ UdpRtpPublisher &UdpRtpPublisher::operator=(UdpRtpPublisher &&other) noexcept { return *this; } -std::expected UdpRtpPublisher::create(const RuntimeConfig &config) { +std::expected UdpRtpPublisher::create(const RuntimeConfig &config, const CodecType codec) { if (!config.outputs.rtp.enabled) { return std::unexpected("invalid RTP publisher init: RTP output disabled"); } @@ -191,7 +191,7 @@ std::expected UdpRtpPublisher::create(const Runtim publisher.destination_host_ = *config.outputs.rtp.host; publisher.destination_port_ = *config.outputs.rtp.port; publisher.payload_type_ = config.outputs.rtp.payload_type; - publisher.codec_ = config.encoder.codec; + publisher.codec_ = codec; publisher.sequence_ = compute_initial_sequence(); publisher.ssrc_ = compute_ssrc( publisher.destination_host_,