o_sfu_core/engine/media_transport/
build.rs1use std::sync::Arc;
4
5use thiserror::Error;
6
7use super::{
8 MediaTransport, SourcePolicySignal,
9 config::{MediaTransportConfig, MediaTransportDeps},
10 rtc::{RtcWorker, RtpProfile},
11};
12use crate::{MediaWorkerId, RtcUdpIoBackend};
13
14const MEDIA_ID_STRIDE: u64 = 1_000_000_000;
20
21impl MediaTransport {
22 pub fn build(
34 mut config: MediaTransportConfig,
35 deps: MediaTransportDeps,
36 ) -> Result<Self, MediaTransportBuildError> {
37 if config.rtc_udp_io_backend == RtcUdpIoBackend::IoUring && !cfg!(target_os = "linux") {
38 return Err(MediaTransportBuildError::UnsupportedUdpIoBackend {
39 backend: config.rtc_udp_io_backend,
40 });
41 }
42 if config.worker_count == 0 {
43 return Err(MediaTransportBuildError::InvalidWorkerCount);
44 }
45 if config
47 .media_quality_interval
48 .is_some_and(|interval| interval > MediaTransportConfig::MAX_MEDIA_QUALITY_INTERVAL)
49 {
50 return Err(MediaTransportBuildError::InvalidMediaQualityInterval);
51 }
52 config.media_quality_interval = config
53 .media_quality_interval
54 .filter(|value| !value.is_zero());
55 let worker_ranges = config
56 .rtc_port_range
57 .split_for_workers(config.worker_count)
58 .ok_or(MediaTransportBuildError::InvalidPortSplit {
59 worker_count: config.worker_count,
60 port_count: config.rtc_port_range.port_count(),
61 })?;
62 let profile = Arc::new(
63 RtpProfile::compile(config.codec_flags, config.codec_preferences)
64 .map_err(|_error| MediaTransportBuildError::InvalidRtpProfile)?,
65 );
66 let source_policy_signal = SourcePolicySignal::default();
67 let workers: Arc<[_]> = (0_u16..u16::MAX)
68 .zip(worker_ranges)
69 .map(|(worker_index, range)| {
70 RtcWorker::start(
73 &config,
74 Arc::clone(&profile),
75 range,
76 &deps,
77 source_policy_signal.clone(),
78 u64::from(worker_index) * MEDIA_ID_STRIDE,
79 MediaWorkerId::from_raw(usize::from(worker_index)),
80 )
81 .map_err(|_error| MediaTransportBuildError::WorkerStartup {
82 worker_index: usize::from(worker_index),
83 })
84 })
85 .collect::<Result<_, _>>()?;
86 Ok(Self {
87 workers,
88 profile,
89 metrics: deps.metrics,
90 #[cfg(test)]
91 media_control_batches: Arc::default(),
92 #[cfg(any(test, feature = "testing-transport"))]
93 source_diagnostics_requests: Arc::default(),
94 source_policy_signal,
95 })
96 }
97}
98
99#[derive(Debug, Error, Clone, Copy, PartialEq, Eq)]
101pub enum MediaTransportBuildError {
102 #[error("media transport worker count must be at least one")]
104 InvalidWorkerCount,
105 #[error(
107 "media transport cannot split {port_count} UDP ports across {worker_count} media workers"
108 )]
109 InvalidPortSplit {
110 worker_count: usize,
111 port_count: u16,
112 },
113 #[error("media-quality interval must not exceed 24 hours")]
115 InvalidMediaQualityInterval,
116 #[error("rtc UDP I/O backend `{backend}` is not supported on this target")]
118 UnsupportedUdpIoBackend { backend: RtcUdpIoBackend },
119 #[error("media transport RTP profile is invalid")]
121 InvalidRtpProfile,
122 #[error("media transport worker {worker_index} failed to start")]
124 WorkerStartup { worker_index: usize },
125}