streamkit_core/
node_config.rs

1// SPDX-FileCopyrightText: © 2025 StreamKit Contributors
2//
3// SPDX-License-Identifier: MPL-2.0
4
5//! Runtime configuration for internal node buffers.
6//!
7//! This module provides a global configuration mechanism for internal buffer settings
8//! used by codec and container nodes. These settings are typically set once at server
9//! startup and remain constant for the lifetime of the process.
10//!
11//! ## Usage
12//!
13//! Server startup:
14//! ```ignore
15//! use streamkit_core::node_config::{set_node_buffer_config, NodeBufferConfig};
16//!
17//! let config = NodeBufferConfig {
18//!     codec_channel_capacity: 32,
19//!     stream_channel_capacity: 8,
20//!     demuxer_buffer_size: 65536,
21//!     moq_peer_channel_capacity: 100,
22//! };
23//! set_node_buffer_config(config);
24//! ```
25//!
26//! Node implementation:
27//! ```ignore
28//! use streamkit_core::node_config::get_codec_channel_capacity;
29//!
30//! let (tx, rx) = mpsc::channel(get_codec_channel_capacity());
31//! ```
32//!
33//! ## Default Values
34//!
35//! If `set_node_buffer_config` is never called, the getter functions return sensible
36//! defaults based on production experience:
37//!
38//! - `codec_channel_capacity`: 32 packets
39//! - `stream_channel_capacity`: 8 packets
40//! - `demuxer_buffer_size`: 65536 bytes (64KB)
41//! - `moq_peer_channel_capacity`: 100 packets (MoQ transport internal queues)
42
43use std::sync::OnceLock;
44
45/// Default capacity for codec async/blocking handoff channels.
46const DEFAULT_CODEC_CHANNEL_CAPACITY: usize = 32;
47
48/// Default capacity for streaming reader channels (container demuxers).
49const DEFAULT_STREAM_CHANNEL_CAPACITY: usize = 8;
50
51/// Default duplex buffer size for ogg demuxer (64KB).
52const DEFAULT_DEMUXER_BUFFER_SIZE: usize = 64 * 1024;
53
54/// Default capacity for MoQ transport peer internal channels.
55const DEFAULT_MOQ_PEER_CHANNEL_CAPACITY: usize = 100;
56
57/// Runtime configuration for node internal buffers.
58///
59/// These settings affect the async/blocking handoff channels in codec and container nodes.
60/// Most users should not need to modify these values.
61#[derive(Debug, Clone)]
62pub struct NodeBufferConfig {
63    /// Capacity for codec processing channels (e.g. Opus encoder/decoder).
64    /// Used for async/blocking handoff in codec nodes.
65    pub codec_channel_capacity: usize,
66
67    /// Capacity for streaming reader channels (container demuxers).
68    /// Smaller than codec channels because container frames may be larger.
69    pub stream_channel_capacity: usize,
70
71    /// Duplex buffer size for ogg demuxer in bytes.
72    pub demuxer_buffer_size: usize,
73
74    /// Capacity for MoQ transport peer internal channels (packets).
75    ///
76    /// Used by MoQ transport nodes for per-connection send/receive coordination.
77    /// This is not the same as engine graph channel capacities; it only affects the
78    /// internal queueing within the transport node.
79    pub moq_peer_channel_capacity: usize,
80}
81
82impl Default for NodeBufferConfig {
83    fn default() -> Self {
84        Self {
85            codec_channel_capacity: DEFAULT_CODEC_CHANNEL_CAPACITY,
86            stream_channel_capacity: DEFAULT_STREAM_CHANNEL_CAPACITY,
87            demuxer_buffer_size: DEFAULT_DEMUXER_BUFFER_SIZE,
88            moq_peer_channel_capacity: DEFAULT_MOQ_PEER_CHANNEL_CAPACITY,
89        }
90    }
91}
92
93/// Global storage for the node buffer configuration.
94static NODE_BUFFER_CONFIG: OnceLock<NodeBufferConfig> = OnceLock::new();
95
96/// Sets the global node buffer configuration.
97///
98/// This should be called once at server startup, before any nodes are created.
99/// Subsequent calls are ignored (the first configuration wins).
100///
101/// # Example
102///
103/// ```ignore
104/// use streamkit_core::node_config::{set_node_buffer_config, NodeBufferConfig};
105///
106/// set_node_buffer_config(NodeBufferConfig {
107///     codec_channel_capacity: 64,  // Increased for high-throughput scenarios
108///     stream_channel_capacity: 16,
109///     demuxer_buffer_size: 128 * 1024,  // 128KB buffer
110///     moq_peer_channel_capacity: 200,
111/// });
112/// ```
113pub fn set_node_buffer_config(config: NodeBufferConfig) {
114    if NODE_BUFFER_CONFIG.set(config).is_err() {
115        tracing::warn!("Node buffer config already set, ignoring new configuration");
116    }
117}
118
119/// Returns the configured codec channel capacity.
120///
121/// Used by codec nodes that offload CPU work to blocking tasks (e.g. Opus).
122/// Returns the default (32) if no configuration was set.
123#[inline]
124pub fn get_codec_channel_capacity() -> usize {
125    NODE_BUFFER_CONFIG.get().map_or(DEFAULT_CODEC_CHANNEL_CAPACITY, |c| c.codec_channel_capacity)
126}
127
128/// Returns the configured stream channel capacity.
129///
130/// Used by streaming readers that hand off `Bytes` into blocking demux/decode tasks
131/// (container demuxers and some non-Opus codecs).
132/// Returns the default (8) if no configuration was set.
133#[inline]
134pub fn get_stream_channel_capacity() -> usize {
135    NODE_BUFFER_CONFIG.get().map_or(DEFAULT_STREAM_CHANNEL_CAPACITY, |c| c.stream_channel_capacity)
136}
137
138/// Returns the configured demuxer buffer size in bytes.
139///
140/// Used by ogg demuxer for its duplex buffer. Returns the default (64KB)
141/// if no configuration was set.
142#[inline]
143pub fn get_demuxer_buffer_size() -> usize {
144    NODE_BUFFER_CONFIG.get().map_or(DEFAULT_DEMUXER_BUFFER_SIZE, |c| c.demuxer_buffer_size)
145}
146
147/// Returns the configured MoQ peer channel capacity.
148///
149/// Used by MoQ transport peer tasks for per-connection internal buffering.
150/// Returns the default (100) if no configuration was set.
151#[inline]
152pub fn get_moq_peer_channel_capacity() -> usize {
153    NODE_BUFFER_CONFIG
154        .get()
155        .map_or(DEFAULT_MOQ_PEER_CHANNEL_CAPACITY, |c| c.moq_peer_channel_capacity)
156}
157
158#[cfg(test)]
159mod tests {
160    use super::*;
161
162    #[test]
163    fn test_default_values() {
164        // Without setting config, should return defaults
165        // Note: This test may fail if run after other tests that set the config
166        assert_eq!(DEFAULT_CODEC_CHANNEL_CAPACITY, 32);
167        assert_eq!(DEFAULT_STREAM_CHANNEL_CAPACITY, 8);
168        assert_eq!(DEFAULT_DEMUXER_BUFFER_SIZE, 64 * 1024);
169        assert_eq!(DEFAULT_MOQ_PEER_CHANNEL_CAPACITY, 100);
170    }
171}