Skip to content
File

Blob: firmware/vendor/str0m/src/pacer/mod.rs

rust165 lines
1use std::time::Instant;
2 
3use crate::Reason;
4use crate::bwe_::ProbeClusterConfig;
5use crate::rtp_::{Bitrate, DataSize, MidRid, TwccClusterId};
6 
7mod control;
8pub(crate) use control::PacerControl;
9 
10mod null;
11use null::NullPacer;
12 
13mod leaky;
14use leaky::LeakyBucketPacer;
15 
16mod queue;
17pub(crate) use queue::{PaddingRequest, QueuePriority, QueueSnapshot, QueueState};
18 
19#[allow(clippy::large_enum_variant)]
20pub(crate) enum PacerImpl {
21 Null(NullPacer),
22 LeakyBucket(LeakyBucketPacer),
23}
24 
25impl PacerImpl {
26 pub fn leaky_bucket(rate: Bitrate) -> PacerImpl {
27 PacerImpl::LeakyBucket(LeakyBucketPacer::new(rate))
28 }
29 
30 pub fn null() -> PacerImpl {
31 PacerImpl::Null(NullPacer::default())
32 }
33 
34 pub fn start_probe(&mut self, config: ProbeClusterConfig) {
35 match self {
36 PacerImpl::Null(_) => {
37 // NullPacer doesn't support probing
38 }
39 PacerImpl::LeakyBucket(v) => v.start_probe(config),
40 }
41 }
42 
43 pub fn check_probe_complete(&mut self, now: Instant) -> Option<TwccClusterId> {
44 match self {
45 PacerImpl::Null(_) => None,
46 PacerImpl::LeakyBucket(v) => v.check_probe_complete(now),
47 }
48 }
49}
50 
51impl Pacer for PacerImpl {
52 fn set_pacing_rate(&mut self, pacing_bitrate: Bitrate) {
53 match self {
54 PacerImpl::Null(v) => v.set_pacing_rate(pacing_bitrate),
55 PacerImpl::LeakyBucket(v) => v.set_pacing_rate(pacing_bitrate),
56 }
57 }
58 
59 fn set_padding_rate(&mut self, padding_bitrate: Bitrate) {
60 match self {
61 PacerImpl::Null(v) => v.set_padding_rate(padding_bitrate),
62 PacerImpl::LeakyBucket(v) => v.set_padding_rate(padding_bitrate),
63 }
64 }
65 
66 fn poll_timeout(&self) -> (Option<Instant>, Reason) {
67 match self {
68 PacerImpl::Null(v) => v.poll_timeout(),
69 PacerImpl::LeakyBucket(v) => v.poll_timeout(),
70 }
71 }
72 
73 fn handle_timeout(
74 &mut self,
75 now: Instant,
76 iter: impl Iterator<Item = QueueState>,
77 ) -> Option<PaddingRequest> {
78 match self {
79 PacerImpl::Null(v) => v.handle_timeout(now, iter),
80 PacerImpl::LeakyBucket(v) => v.handle_timeout(now, iter),
81 }
82 }
83 
84 fn poll_queue(&mut self) -> Option<(MidRid, Option<TwccClusterId>)> {
85 match self {
86 PacerImpl::Null(v) => v.poll_queue(),
87 PacerImpl::LeakyBucket(v) => v.poll_queue(),
88 }
89 }
90 
91 fn register_send(&mut self, now: Instant, packet_size: DataSize, from: MidRid) {
92 match self {
93 PacerImpl::Null(v) => v.register_send(now, packet_size, from),
94 PacerImpl::LeakyBucket(v) => v.register_send(now, packet_size, from),
95 }
96 }
97 
98 fn has_padding_queue(&self) -> bool {
99 match self {
100 PacerImpl::Null(v) => v.has_padding_queue(),
101 PacerImpl::LeakyBucket(v) => v.has_padding_queue(),
102 }
103 }
104}
105 
106/// A packet Pacer.
107///
108/// The pacer is responsible for ensuring correct pacing of packets onto the network at a given
109/// bitrate.
110pub trait Pacer {
111 /// Set the pacing bitrate. The pacing rate can be exceeded if required to drain excessively
112 /// long packet queues.
113 fn set_pacing_rate(&mut self, pacing_bitrate: Bitrate);
114 
115 /// Set the padding bitrate to send when there's no media to send
116 fn set_padding_rate(&mut self, padding_bitrate: Bitrate);
117 
118 /// Poll for a timeout.
119 fn poll_timeout(&self) -> (Option<Instant>, Reason);
120 
121 /// Handle time moving forward, should be called periodically as indicated by [`Pacer::poll_timeout`].
122 fn handle_timeout(
123 &mut self,
124 now: Instant,
125 iter: impl Iterator<Item = QueueState>,
126 ) -> Option<PaddingRequest>;
127 
128 /// Determines which mid to poll, if any.
129 ///
130 /// Returns the MidRid to poll and the probe cluster ID if this packet belongs to a probe.
131 fn poll_queue(&mut self) -> Option<(MidRid, Option<TwccClusterId>)>;
132 
133 /// Register a packet having been sent.
134 ///
135 /// **MUST** be called each time [`Pacer::poll_queue`] produces a mid.
136 fn register_send(&mut self, now: Instant, packet_size: DataSize, from: MidRid);
137 
138 /// Whether we have a queue for padding.
139 fn has_padding_queue(&self) -> bool;
140}
141 
142/// The sub-reason for the [`Reason::Pacer`][crate::Reason::Pacer].
143///
144/// This enum is not considered stable API and may change in minor revisions.
145#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
146#[non_exhaustive]
147pub enum PacerReason {
148 /// Handle to update pacer budgets.
149 Handle,
150 /// First ever call to handle_timeout().
151 FirstEver,
152 /// Unpaced content such as audio.
153 Unpaced,
154 /// BWE probe cluster call 1.
155 Probe1,
156 /// BWE probe cluster call 2.
157 Probe2,
158 /// Regular paced content like video.
159 Paced,
160 /// Padding to inflate used bandwidth.
161 Padding,
162 /// Immediate timeout for state keeping reasons
163 Immediate,
164}