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