xref: /aosp_15_r20/external/webrtc/modules/pacing/pacing_controller.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #ifndef MODULES_PACING_PACING_CONTROLLER_H_
12*d9f75844SAndroid Build Coastguard Worker #define MODULES_PACING_PACING_CONTROLLER_H_
13*d9f75844SAndroid Build Coastguard Worker 
14*d9f75844SAndroid Build Coastguard Worker #include <stddef.h>
15*d9f75844SAndroid Build Coastguard Worker #include <stdint.h>
16*d9f75844SAndroid Build Coastguard Worker 
17*d9f75844SAndroid Build Coastguard Worker #include <array>
18*d9f75844SAndroid Build Coastguard Worker #include <atomic>
19*d9f75844SAndroid Build Coastguard Worker #include <memory>
20*d9f75844SAndroid Build Coastguard Worker #include <vector>
21*d9f75844SAndroid Build Coastguard Worker 
22*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
23*d9f75844SAndroid Build Coastguard Worker #include "api/field_trials_view.h"
24*d9f75844SAndroid Build Coastguard Worker #include "api/function_view.h"
25*d9f75844SAndroid Build Coastguard Worker #include "api/transport/field_trial_based_config.h"
26*d9f75844SAndroid Build Coastguard Worker #include "api/transport/network_types.h"
27*d9f75844SAndroid Build Coastguard Worker #include "modules/pacing/bitrate_prober.h"
28*d9f75844SAndroid Build Coastguard Worker #include "modules/pacing/interval_budget.h"
29*d9f75844SAndroid Build Coastguard Worker #include "modules/pacing/prioritized_packet_queue.h"
30*d9f75844SAndroid Build Coastguard Worker #include "modules/pacing/rtp_packet_pacer.h"
31*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/include/rtp_packet_sender.h"
32*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
33*d9f75844SAndroid Build Coastguard Worker #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
34*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/experiments/field_trial_parser.h"
35*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread_annotations.h"
36*d9f75844SAndroid Build Coastguard Worker 
37*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
38*d9f75844SAndroid Build Coastguard Worker 
39*d9f75844SAndroid Build Coastguard Worker // This class implements a leaky-bucket packet pacing algorithm. It handles the
40*d9f75844SAndroid Build Coastguard Worker // logic of determining which packets to send when, but the actual timing of
41*d9f75844SAndroid Build Coastguard Worker // the processing is done externally (e.g. RtpPacketPacer). Furthermore, the
42*d9f75844SAndroid Build Coastguard Worker // forwarding of packets when they are ready to be sent is also handled
43*d9f75844SAndroid Build Coastguard Worker // externally, via the PacingController::PacketSender interface.
44*d9f75844SAndroid Build Coastguard Worker class PacingController {
45*d9f75844SAndroid Build Coastguard Worker  public:
46*d9f75844SAndroid Build Coastguard Worker   class PacketSender {
47*d9f75844SAndroid Build Coastguard Worker    public:
48*d9f75844SAndroid Build Coastguard Worker     virtual ~PacketSender() = default;
49*d9f75844SAndroid Build Coastguard Worker     virtual void SendPacket(std::unique_ptr<RtpPacketToSend> packet,
50*d9f75844SAndroid Build Coastguard Worker                             const PacedPacketInfo& cluster_info) = 0;
51*d9f75844SAndroid Build Coastguard Worker     // Should be called after each call to SendPacket().
52*d9f75844SAndroid Build Coastguard Worker     virtual std::vector<std::unique_ptr<RtpPacketToSend>> FetchFec() = 0;
53*d9f75844SAndroid Build Coastguard Worker     virtual std::vector<std::unique_ptr<RtpPacketToSend>> GeneratePadding(
54*d9f75844SAndroid Build Coastguard Worker         DataSize size) = 0;
55*d9f75844SAndroid Build Coastguard Worker 
56*d9f75844SAndroid Build Coastguard Worker     // TODO(bugs.webrtc.org/11340): Make pure virtual once downstream projects
57*d9f75844SAndroid Build Coastguard Worker     // have been updated.
OnAbortedRetransmissions(uint32_t ssrc,rtc::ArrayView<const uint16_t> sequence_numbers)58*d9f75844SAndroid Build Coastguard Worker     virtual void OnAbortedRetransmissions(
59*d9f75844SAndroid Build Coastguard Worker         uint32_t ssrc,
60*d9f75844SAndroid Build Coastguard Worker         rtc::ArrayView<const uint16_t> sequence_numbers) {}
GetRtxSsrcForMedia(uint32_t ssrc)61*d9f75844SAndroid Build Coastguard Worker     virtual absl::optional<uint32_t> GetRtxSsrcForMedia(uint32_t ssrc) const {
62*d9f75844SAndroid Build Coastguard Worker       return absl::nullopt;
63*d9f75844SAndroid Build Coastguard Worker     }
64*d9f75844SAndroid Build Coastguard Worker   };
65*d9f75844SAndroid Build Coastguard Worker 
66*d9f75844SAndroid Build Coastguard Worker   // Expected max pacer delay. If ExpectedQueueTime() is higher than
67*d9f75844SAndroid Build Coastguard Worker   // this value, the packet producers should wait (eg drop frames rather than
68*d9f75844SAndroid Build Coastguard Worker   // encoding them). Bitrate sent may temporarily exceed target set by
69*d9f75844SAndroid Build Coastguard Worker   // UpdateBitrate() so that this limit will be upheld.
70*d9f75844SAndroid Build Coastguard Worker   static const TimeDelta kMaxExpectedQueueLength;
71*d9f75844SAndroid Build Coastguard Worker   // If no media or paused, wake up at least every `kPausedProcessIntervalMs` in
72*d9f75844SAndroid Build Coastguard Worker   // order to send a keep-alive packet so we don't get stuck in a bad state due
73*d9f75844SAndroid Build Coastguard Worker   // to lack of feedback.
74*d9f75844SAndroid Build Coastguard Worker   static const TimeDelta kPausedProcessInterval;
75*d9f75844SAndroid Build Coastguard Worker   // The default minimum time that should elapse calls to `ProcessPackets()`.
76*d9f75844SAndroid Build Coastguard Worker   static const TimeDelta kMinSleepTime;
77*d9f75844SAndroid Build Coastguard Worker   // When padding should be generated, add packets to the buffer with a size
78*d9f75844SAndroid Build Coastguard Worker   // corresponding to this duration times the current padding rate.
79*d9f75844SAndroid Build Coastguard Worker   static const TimeDelta kTargetPaddingDuration;
80*d9f75844SAndroid Build Coastguard Worker   // The maximum time that the pacer can use when "replaying" passed time where
81*d9f75844SAndroid Build Coastguard Worker   // padding should have been generated.
82*d9f75844SAndroid Build Coastguard Worker   static const TimeDelta kMaxPaddingReplayDuration;
83*d9f75844SAndroid Build Coastguard Worker   // Allow probes to be processed slightly ahead of inteded send time. Currently
84*d9f75844SAndroid Build Coastguard Worker   // set to 1ms as this is intended to allow times be rounded down to the
85*d9f75844SAndroid Build Coastguard Worker   // nearest millisecond.
86*d9f75844SAndroid Build Coastguard Worker   static const TimeDelta kMaxEarlyProbeProcessing;
87*d9f75844SAndroid Build Coastguard Worker 
88*d9f75844SAndroid Build Coastguard Worker   PacingController(Clock* clock,
89*d9f75844SAndroid Build Coastguard Worker                    PacketSender* packet_sender,
90*d9f75844SAndroid Build Coastguard Worker                    const FieldTrialsView& field_trials);
91*d9f75844SAndroid Build Coastguard Worker 
92*d9f75844SAndroid Build Coastguard Worker   ~PacingController();
93*d9f75844SAndroid Build Coastguard Worker 
94*d9f75844SAndroid Build Coastguard Worker   // Adds the packet to the queue and calls PacketRouter::SendPacket() when
95*d9f75844SAndroid Build Coastguard Worker   // it's time to send.
96*d9f75844SAndroid Build Coastguard Worker   void EnqueuePacket(std::unique_ptr<RtpPacketToSend> packet);
97*d9f75844SAndroid Build Coastguard Worker 
98*d9f75844SAndroid Build Coastguard Worker   // ABSL_DEPRECATED("Use CreateProbeClusters instead")
99*d9f75844SAndroid Build Coastguard Worker   void CreateProbeCluster(DataRate bitrate, int cluster_id);
100*d9f75844SAndroid Build Coastguard Worker   void CreateProbeClusters(
101*d9f75844SAndroid Build Coastguard Worker       rtc::ArrayView<const ProbeClusterConfig> probe_cluster_configs);
102*d9f75844SAndroid Build Coastguard Worker 
103*d9f75844SAndroid Build Coastguard Worker   void Pause();   // Temporarily pause all sending.
104*d9f75844SAndroid Build Coastguard Worker   void Resume();  // Resume sending packets.
105*d9f75844SAndroid Build Coastguard Worker   bool IsPaused() const;
106*d9f75844SAndroid Build Coastguard Worker 
107*d9f75844SAndroid Build Coastguard Worker   void SetCongested(bool congested);
108*d9f75844SAndroid Build Coastguard Worker 
109*d9f75844SAndroid Build Coastguard Worker   // Sets the pacing rates. Must be called once before packets can be sent.
110*d9f75844SAndroid Build Coastguard Worker   void SetPacingRates(DataRate pacing_rate, DataRate padding_rate);
pacing_rate()111*d9f75844SAndroid Build Coastguard Worker   DataRate pacing_rate() const { return adjusted_media_rate_; }
112*d9f75844SAndroid Build Coastguard Worker 
113*d9f75844SAndroid Build Coastguard Worker   // Currently audio traffic is not accounted by pacer and passed through.
114*d9f75844SAndroid Build Coastguard Worker   // With the introduction of audio BWE audio traffic will be accounted for
115*d9f75844SAndroid Build Coastguard Worker   // the pacer budget calculation. The audio traffic still will be injected
116*d9f75844SAndroid Build Coastguard Worker   // at high priority.
117*d9f75844SAndroid Build Coastguard Worker   void SetAccountForAudioPackets(bool account_for_audio);
118*d9f75844SAndroid Build Coastguard Worker   void SetIncludeOverhead();
119*d9f75844SAndroid Build Coastguard Worker 
120*d9f75844SAndroid Build Coastguard Worker   void SetTransportOverhead(DataSize overhead_per_packet);
121*d9f75844SAndroid Build Coastguard Worker   // The pacer is allowed to send enqued packets in bursts and can build up a
122*d9f75844SAndroid Build Coastguard Worker   // packet "debt" that correspond to approximately the send rate during
123*d9f75844SAndroid Build Coastguard Worker   // 'burst_interval'.
124*d9f75844SAndroid Build Coastguard Worker   void SetSendBurstInterval(TimeDelta burst_interval);
125*d9f75844SAndroid Build Coastguard Worker 
126*d9f75844SAndroid Build Coastguard Worker   // Returns the time when the oldest packet was queued.
127*d9f75844SAndroid Build Coastguard Worker   Timestamp OldestPacketEnqueueTime() const;
128*d9f75844SAndroid Build Coastguard Worker 
129*d9f75844SAndroid Build Coastguard Worker   // Number of packets in the pacer queue.
130*d9f75844SAndroid Build Coastguard Worker   size_t QueueSizePackets() const;
131*d9f75844SAndroid Build Coastguard Worker   // Number of packets in the pacer queue per media type (RtpPacketMediaType
132*d9f75844SAndroid Build Coastguard Worker   // values are used as lookup index).
133*d9f75844SAndroid Build Coastguard Worker   const std::array<int, kNumMediaTypes>& SizeInPacketsPerRtpPacketMediaType()
134*d9f75844SAndroid Build Coastguard Worker       const;
135*d9f75844SAndroid Build Coastguard Worker   // Totals size of packets in the pacer queue.
136*d9f75844SAndroid Build Coastguard Worker   DataSize QueueSizeData() const;
137*d9f75844SAndroid Build Coastguard Worker 
138*d9f75844SAndroid Build Coastguard Worker   // Current buffer level, i.e. max of media and padding debt.
139*d9f75844SAndroid Build Coastguard Worker   DataSize CurrentBufferLevel() const;
140*d9f75844SAndroid Build Coastguard Worker 
141*d9f75844SAndroid Build Coastguard Worker   // Returns the time when the first packet was sent.
142*d9f75844SAndroid Build Coastguard Worker   absl::optional<Timestamp> FirstSentPacketTime() const;
143*d9f75844SAndroid Build Coastguard Worker 
144*d9f75844SAndroid Build Coastguard Worker   // Returns the number of milliseconds it will take to send the current
145*d9f75844SAndroid Build Coastguard Worker   // packets in the queue, given the current size and bitrate, ignoring prio.
146*d9f75844SAndroid Build Coastguard Worker   TimeDelta ExpectedQueueTime() const;
147*d9f75844SAndroid Build Coastguard Worker 
148*d9f75844SAndroid Build Coastguard Worker   void SetQueueTimeLimit(TimeDelta limit);
149*d9f75844SAndroid Build Coastguard Worker 
150*d9f75844SAndroid Build Coastguard Worker   // Enable bitrate probing. Enabled by default, mostly here to simplify
151*d9f75844SAndroid Build Coastguard Worker   // testing. Must be called before any packets are being sent to have an
152*d9f75844SAndroid Build Coastguard Worker   // effect.
153*d9f75844SAndroid Build Coastguard Worker   void SetProbingEnabled(bool enabled);
154*d9f75844SAndroid Build Coastguard Worker 
155*d9f75844SAndroid Build Coastguard Worker   // Returns the next time we expect ProcessPackets() to be called.
156*d9f75844SAndroid Build Coastguard Worker   Timestamp NextSendTime() const;
157*d9f75844SAndroid Build Coastguard Worker 
158*d9f75844SAndroid Build Coastguard Worker   // Check queue of pending packets and send them or padding packets, if budget
159*d9f75844SAndroid Build Coastguard Worker   // is available.
160*d9f75844SAndroid Build Coastguard Worker   void ProcessPackets();
161*d9f75844SAndroid Build Coastguard Worker 
162*d9f75844SAndroid Build Coastguard Worker   bool IsProbing() const;
163*d9f75844SAndroid Build Coastguard Worker 
164*d9f75844SAndroid Build Coastguard Worker   // Note: Intended for debugging purposes only, will be removed.
165*d9f75844SAndroid Build Coastguard Worker   // Sets the number of iterations of the main loop in `ProcessPackets()` that
166*d9f75844SAndroid Build Coastguard Worker   // is considered erroneous to exceed.
167*d9f75844SAndroid Build Coastguard Worker   void SetCircuitBreakerThreshold(int num_iterations);
168*d9f75844SAndroid Build Coastguard Worker 
169*d9f75844SAndroid Build Coastguard Worker  private:
170*d9f75844SAndroid Build Coastguard Worker   TimeDelta UpdateTimeAndGetElapsed(Timestamp now);
171*d9f75844SAndroid Build Coastguard Worker   bool ShouldSendKeepalive(Timestamp now) const;
172*d9f75844SAndroid Build Coastguard Worker 
173*d9f75844SAndroid Build Coastguard Worker   // Updates the number of bytes that can be sent for the next time interval.
174*d9f75844SAndroid Build Coastguard Worker   void UpdateBudgetWithElapsedTime(TimeDelta delta);
175*d9f75844SAndroid Build Coastguard Worker   void UpdateBudgetWithSentData(DataSize size);
176*d9f75844SAndroid Build Coastguard Worker   void UpdatePaddingBudgetWithSentData(DataSize size);
177*d9f75844SAndroid Build Coastguard Worker 
178*d9f75844SAndroid Build Coastguard Worker   DataSize PaddingToAdd(DataSize recommended_probe_size,
179*d9f75844SAndroid Build Coastguard Worker                         DataSize data_sent) const;
180*d9f75844SAndroid Build Coastguard Worker 
181*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<RtpPacketToSend> GetPendingPacket(
182*d9f75844SAndroid Build Coastguard Worker       const PacedPacketInfo& pacing_info,
183*d9f75844SAndroid Build Coastguard Worker       Timestamp target_send_time,
184*d9f75844SAndroid Build Coastguard Worker       Timestamp now);
185*d9f75844SAndroid Build Coastguard Worker   void OnPacketSent(RtpPacketMediaType packet_type,
186*d9f75844SAndroid Build Coastguard Worker                     DataSize packet_size,
187*d9f75844SAndroid Build Coastguard Worker                     Timestamp send_time);
188*d9f75844SAndroid Build Coastguard Worker   void MaybeUpdateMediaRateDueToLongQueue(Timestamp now);
189*d9f75844SAndroid Build Coastguard Worker 
190*d9f75844SAndroid Build Coastguard Worker   Timestamp CurrentTime() const;
191*d9f75844SAndroid Build Coastguard Worker 
192*d9f75844SAndroid Build Coastguard Worker   // Helper methods for packet that may not be paced. Returns a finite Timestamp
193*d9f75844SAndroid Build Coastguard Worker   // if a packet type is configured to not be paced and the packet queue has at
194*d9f75844SAndroid Build Coastguard Worker   // least one packet of that type. Otherwise returns
195*d9f75844SAndroid Build Coastguard Worker   // Timestamp::MinusInfinity().
196*d9f75844SAndroid Build Coastguard Worker   Timestamp NextUnpacedSendTime() const;
197*d9f75844SAndroid Build Coastguard Worker 
198*d9f75844SAndroid Build Coastguard Worker   Clock* const clock_;
199*d9f75844SAndroid Build Coastguard Worker   PacketSender* const packet_sender_;
200*d9f75844SAndroid Build Coastguard Worker   const FieldTrialsView& field_trials_;
201*d9f75844SAndroid Build Coastguard Worker 
202*d9f75844SAndroid Build Coastguard Worker   const bool drain_large_queues_;
203*d9f75844SAndroid Build Coastguard Worker   const bool send_padding_if_silent_;
204*d9f75844SAndroid Build Coastguard Worker   const bool pace_audio_;
205*d9f75844SAndroid Build Coastguard Worker   const bool ignore_transport_overhead_;
206*d9f75844SAndroid Build Coastguard Worker   const bool fast_retransmissions_;
207*d9f75844SAndroid Build Coastguard Worker 
208*d9f75844SAndroid Build Coastguard Worker   TimeDelta min_packet_limit_;
209*d9f75844SAndroid Build Coastguard Worker   DataSize transport_overhead_per_packet_;
210*d9f75844SAndroid Build Coastguard Worker   TimeDelta send_burst_interval_;
211*d9f75844SAndroid Build Coastguard Worker 
212*d9f75844SAndroid Build Coastguard Worker   // TODO(webrtc:9716): Remove this when we are certain clocks are monotonic.
213*d9f75844SAndroid Build Coastguard Worker   // The last millisecond timestamp returned by `clock_`.
214*d9f75844SAndroid Build Coastguard Worker   mutable Timestamp last_timestamp_;
215*d9f75844SAndroid Build Coastguard Worker   bool paused_;
216*d9f75844SAndroid Build Coastguard Worker 
217*d9f75844SAndroid Build Coastguard Worker   // Amount of outstanding data for media and padding.
218*d9f75844SAndroid Build Coastguard Worker   DataSize media_debt_;
219*d9f75844SAndroid Build Coastguard Worker   DataSize padding_debt_;
220*d9f75844SAndroid Build Coastguard Worker 
221*d9f75844SAndroid Build Coastguard Worker   // The target pacing rate, signaled via SetPacingRates().
222*d9f75844SAndroid Build Coastguard Worker   DataRate pacing_rate_;
223*d9f75844SAndroid Build Coastguard Worker   // The media send rate, which might adjusted from pacing_rate_, e.g. if the
224*d9f75844SAndroid Build Coastguard Worker   // pacing queue is growing too long.
225*d9f75844SAndroid Build Coastguard Worker   DataRate adjusted_media_rate_;
226*d9f75844SAndroid Build Coastguard Worker   // The padding target rate. We aim to fill up to this rate with padding what
227*d9f75844SAndroid Build Coastguard Worker   // is not already used by media.
228*d9f75844SAndroid Build Coastguard Worker   DataRate padding_rate_;
229*d9f75844SAndroid Build Coastguard Worker 
230*d9f75844SAndroid Build Coastguard Worker   BitrateProber prober_;
231*d9f75844SAndroid Build Coastguard Worker   bool probing_send_failure_;
232*d9f75844SAndroid Build Coastguard Worker 
233*d9f75844SAndroid Build Coastguard Worker   Timestamp last_process_time_;
234*d9f75844SAndroid Build Coastguard Worker   Timestamp last_send_time_;
235*d9f75844SAndroid Build Coastguard Worker   absl::optional<Timestamp> first_sent_packet_time_;
236*d9f75844SAndroid Build Coastguard Worker   bool seen_first_packet_;
237*d9f75844SAndroid Build Coastguard Worker 
238*d9f75844SAndroid Build Coastguard Worker   PrioritizedPacketQueue packet_queue_;
239*d9f75844SAndroid Build Coastguard Worker 
240*d9f75844SAndroid Build Coastguard Worker   bool congested_;
241*d9f75844SAndroid Build Coastguard Worker 
242*d9f75844SAndroid Build Coastguard Worker   TimeDelta queue_time_limit_;
243*d9f75844SAndroid Build Coastguard Worker   bool account_for_audio_;
244*d9f75844SAndroid Build Coastguard Worker   bool include_overhead_;
245*d9f75844SAndroid Build Coastguard Worker 
246*d9f75844SAndroid Build Coastguard Worker   int circuit_breaker_threshold_;
247*d9f75844SAndroid Build Coastguard Worker };
248*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
249*d9f75844SAndroid Build Coastguard Worker 
250*d9f75844SAndroid Build Coastguard Worker #endif  // MODULES_PACING_PACING_CONTROLLER_H_
251