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}