Skip to main content

ff_format/
network.rs

1//! Network configuration types for network-backed sources and outputs.
2//!
3//! This module provides [`NetworkOptions`] — shared connection and reconnect
4//! settings consumed by network-aware decoders (e.g., RTMP, SRT, HLS ingest)
5//! and live streaming outputs.
6//!
7//! # `FFmpeg` key mapping
8//!
9//! | Field             | `FFmpeg` option key | Unit         |
10//! |-------------------|-------------------|--------------|
11//! | `connect_timeout` | `timeout`         | microseconds |
12//! | `read_timeout`    | `rw_timeout`      | microseconds |
13//!
14//! # Examples
15//!
16//! ```
17//! use ff_format::network::NetworkOptions;
18//! use std::time::Duration;
19//!
20//! let opts = NetworkOptions {
21//!     connect_timeout: Duration::from_secs(5),
22//!     read_timeout: Duration::from_secs(15),
23//!     reconnect_on_error: true,
24//!     max_reconnect_attempts: 5,
25//! };
26//! assert_eq!(opts.connect_timeout.as_micros(), 5_000_000);
27//! ```
28
29use std::time::Duration;
30
31/// Shared network configuration for network-backed decoders and live outputs.
32///
33/// These settings map directly to `FFmpeg` `AVFormatContext` options that control
34/// connection and read timeouts, and to application-level reconnection logic.
35///
36/// # `FFmpeg` option keys
37///
38/// Pass the converted microsecond values via `av_dict_set` on the
39/// `AVFormatContext` before opening the stream:
40///
41/// - `connect_timeout` → key `"timeout"`, value `connect_timeout.as_micros()`
42/// - `read_timeout` → key `"rw_timeout"`, value `read_timeout.as_micros()`
43///
44/// # Defaults
45///
46/// ```
47/// use ff_format::network::NetworkOptions;
48/// use std::time::Duration;
49///
50/// let opts = NetworkOptions::default();
51/// assert_eq!(opts.connect_timeout, Duration::from_secs(10));
52/// assert_eq!(opts.read_timeout, Duration::from_secs(30));
53/// assert!(!opts.reconnect_on_error);
54/// assert_eq!(opts.max_reconnect_attempts, 3);
55/// ```
56#[derive(Debug, Clone, PartialEq)]
57pub struct NetworkOptions {
58    /// Maximum time to wait when establishing a connection.
59    ///
60    /// Maps to the `FFmpeg` `"timeout"` option key (value in microseconds).
61    /// Default: 10 seconds.
62    pub connect_timeout: Duration,
63
64    /// Maximum time to wait for data after the connection is open.
65    ///
66    /// Maps to the `FFmpeg` `"rw_timeout"` option key (value in microseconds).
67    /// Default: 30 seconds.
68    pub read_timeout: Duration,
69
70    /// Whether to attempt reconnection when a read error occurs.
71    ///
72    /// When `false`, `max_reconnect_attempts` is ignored.
73    /// Default: `false`.
74    pub reconnect_on_error: bool,
75
76    /// Maximum number of reconnection attempts before giving up.
77    ///
78    /// Ignored when `reconnect_on_error` is `false`.
79    /// Default: `3`.
80    pub max_reconnect_attempts: u32,
81}
82
83impl Default for NetworkOptions {
84    fn default() -> Self {
85        Self {
86            connect_timeout: Duration::from_secs(10),
87            read_timeout: Duration::from_secs(30),
88            reconnect_on_error: false,
89            max_reconnect_attempts: 3,
90        }
91    }
92}
93
94#[cfg(test)]
95mod tests {
96    use super::*;
97
98    #[test]
99    fn default_should_have_correct_timeout_values() {
100        let opts = NetworkOptions::default();
101        assert_eq!(opts.connect_timeout, Duration::from_secs(10));
102        assert_eq!(opts.read_timeout, Duration::from_secs(30));
103    }
104
105    #[test]
106    fn default_should_disable_reconnect() {
107        let opts = NetworkOptions::default();
108        assert!(!opts.reconnect_on_error);
109        assert_eq!(opts.max_reconnect_attempts, 3);
110    }
111
112    #[test]
113    fn connect_timeout_microseconds_should_match_duration() {
114        let opts = NetworkOptions::default();
115        assert_eq!(opts.connect_timeout.as_micros(), 10_000_000);
116    }
117
118    #[test]
119    fn read_timeout_microseconds_should_match_duration() {
120        let opts = NetworkOptions::default();
121        assert_eq!(opts.read_timeout.as_micros(), 30_000_000);
122    }
123}