ff_decode/video/builder/network.rs
1//! Network and image-sequence options for [`VideoDecoderBuilder`].
2
3use ff_format::NetworkOptions;
4
5use super::VideoDecoderBuilder;
6
7impl VideoDecoderBuilder {
8 /// Sets the frame rate for image sequence decoding.
9 ///
10 /// Only used when the path contains `%` (e.g. `"frames/frame%04d.png"`).
11 /// Defaults to 25 fps when not set.
12 ///
13 /// # Examples
14 ///
15 /// ```ignore
16 /// use ff_decode::VideoDecoder;
17 ///
18 /// let decoder = VideoDecoder::open("frames/frame%04d.png")?
19 /// .frame_rate(30)
20 /// .build()?;
21 /// ```
22 #[must_use]
23 pub fn frame_rate(mut self, fps: u32) -> Self {
24 self.frame_rate = Some(fps);
25 self
26 }
27
28 /// Sets network options for URL-based sources.
29 ///
30 /// When set, the builder skips the file-existence check and passes connect
31 /// and read timeouts to `avformat_open_input` via an `AVDictionary`.
32 /// Call this before `.build()` when opening `rtmp://`, `rtsp://`, `http://`,
33 /// `https://`, `udp://`, `srt://`, or `rtp://` URLs.
34 ///
35 /// # HLS / M3U8 Playlists
36 ///
37 /// HLS playlists (`.m3u8`) are detected automatically by `FFmpeg` — no extra
38 /// configuration is required beyond calling `.network()`. Pass the full
39 /// HTTP(S) URL of the master or media playlist:
40 ///
41 /// ```ignore
42 /// use ff_decode::VideoDecoder;
43 /// use ff_format::NetworkOptions;
44 ///
45 /// let decoder = VideoDecoder::open("https://example.com/live/index.m3u8")
46 /// .network(NetworkOptions::default())
47 /// .build()?;
48 /// ```
49 ///
50 /// # DASH / MPD Streams
51 ///
52 /// MPEG-DASH manifests (`.mpd`) are detected automatically by `FFmpeg`'s
53 /// built-in `dash` demuxer. The demuxer downloads the manifest, selects the
54 /// highest-quality representation, and fetches segments automatically:
55 ///
56 /// ```ignore
57 /// use ff_decode::VideoDecoder;
58 /// use ff_format::NetworkOptions;
59 ///
60 /// let decoder = VideoDecoder::open("https://example.com/dash/manifest.mpd")
61 /// .network(NetworkOptions::default())
62 /// .build()?;
63 /// ```
64 ///
65 /// # Examples
66 ///
67 /// ```ignore
68 /// use ff_decode::VideoDecoder;
69 /// use ff_format::NetworkOptions;
70 ///
71 /// let decoder = VideoDecoder::open("rtmp://live.example.com/app/stream_key")
72 /// .network(NetworkOptions::default())
73 /// .build()?;
74 /// ```
75 #[must_use]
76 pub fn network(mut self, opts: NetworkOptions) -> Self {
77 self.network_opts = Some(opts);
78 self
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use std::path::PathBuf;
86
87 #[test]
88 fn builder_frame_rate_should_set_fps() {
89 let builder =
90 VideoDecoderBuilder::new(PathBuf::from("frames/frame%04d.png")).frame_rate(30);
91
92 assert_eq!(builder.frame_rate, Some(30));
93 }
94
95 #[test]
96 fn builder_frame_rate_last_setter_wins() {
97 let builder = VideoDecoderBuilder::new(PathBuf::from("frames/frame%04d.png"))
98 .frame_rate(25)
99 .frame_rate(60);
100
101 assert_eq!(builder.frame_rate, Some(60));
102 }
103
104 #[test]
105 fn builder_network_should_set_network_opts() {
106 let builder = VideoDecoderBuilder::new(PathBuf::from("rtmp://example.com/live/stream"))
107 .network(NetworkOptions::default());
108
109 assert!(builder.network_opts.is_some());
110 }
111
112 #[test]
113 fn builder_frame_rate_default_should_be_none() {
114 let builder = VideoDecoderBuilder::new(PathBuf::from("frames/frame%04d.png"));
115
116 assert!(builder.frame_rate.is_none());
117 }
118}