Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
| 11 | #ifndef MODULES_PACING_TASK_QUEUE_PACED_SENDER_H_ |
| 12 | #define MODULES_PACING_TASK_QUEUE_PACED_SENDER_H_ |
| 13 | |
| 14 | #include <stddef.h> |
| 15 | #include <stdint.h> |
| 16 | |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 17 | #include <memory> |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 18 | #include <vector> |
| 19 | |
| 20 | #include "absl/types/optional.h" |
Jonas Oreland | e62c2f2 | 2022-03-29 09:04:48 | [diff] [blame] | 21 | #include "api/field_trials_view.h" |
Artem Titov | d15a575 | 2021-02-10 13:31:24 | [diff] [blame] | 22 | #include "api/sequence_checker.h" |
Per K | 8b5bf6d | 2023-04-13 08:08:45 | [diff] [blame] | 23 | #include "api/task_queue/pending_task_safety_flag.h" |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 24 | #include "api/units/data_size.h" |
| 25 | #include "api/units/time_delta.h" |
| 26 | #include "api/units/timestamp.h" |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 27 | #include "modules/pacing/pacing_controller.h" |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 28 | #include "modules/pacing/rtp_packet_pacer.h" |
| 29 | #include "modules/rtp_rtcp/source/rtp_packet_to_send.h" |
Henrik Boström | a768f52 | 2022-04-13 10:37:59 | [diff] [blame] | 30 | #include "rtc_base/experiments/field_trial_parser.h" |
Erik Språng | 0f86c1f | 2021-10-26 14:19:03 | [diff] [blame] | 31 | #include "rtc_base/numerics/exp_filter.h" |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 32 | #include "rtc_base/thread_annotations.h" |
| 33 | |
| 34 | namespace webrtc { |
| 35 | class Clock; |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 36 | |
Erik Språng | ed1fb19 | 2020-06-30 11:53:37 | [diff] [blame] | 37 | class TaskQueuePacedSender : public RtpPacketPacer, public RtpPacketSender { |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 38 | public: |
Jianhui Dai | df59e53 | 2022-03-19 07:38:51 | [diff] [blame] | 39 | static const int kNoPacketHoldback; |
| 40 | |
Henrik Boström | cf2856b | 2022-11-15 08:23:19 | [diff] [blame] | 41 | // The pacer can be configured using `field_trials` or specified parameters. |
| 42 | // |
Artem Titov | ee3e3fd | 2021-07-28 18:28:28 | [diff] [blame] | 43 | // The `hold_back_window` parameter sets a lower bound on time to sleep if |
Erik Språng | 4ab61cb | 2020-05-19 15:40:58 | [diff] [blame] | 44 | // there is currently a pacer queue and packets can't immediately be |
| 45 | // processed. Increasing this reduces thread wakeups at the expense of higher |
| 46 | // latency. |
Henrik Boström | cf2856b | 2022-11-15 08:23:19 | [diff] [blame] | 47 | // |
Per K | 401c14a | 2023-04-11 07:53:48 | [diff] [blame] | 48 | // The taskqueue used when constructing a TaskQueuePacedSender will also be |
| 49 | // used for pacing. |
Per K | b202bc1 | 2023-11-27 15:06:44 | [diff] [blame] | 50 | TaskQueuePacedSender(Clock* clock, |
| 51 | PacingController::PacketSender* packet_sender, |
| 52 | const FieldTrialsView& field_trials, |
| 53 | TimeDelta max_hold_back_window, |
| 54 | int max_hold_back_window_in_packets); |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 55 | |
| 56 | ~TaskQueuePacedSender() override; |
| 57 | |
Per K | b202bc1 | 2023-11-27 15:06:44 | [diff] [blame] | 58 | // The pacer is allowed to send enqued packets in bursts and can build up a |
| 59 | // packet "debt" that correspond to approximately the send rate during |
| 60 | // 'burst_interval'. |
| 61 | void SetSendBurstInterval(TimeDelta burst_interval); |
| 62 | |
Per K | 98db63c | 2024-01-26 11:57:01 | [diff] [blame] | 63 | // A probe may be sent without first waing for a media packet. |
| 64 | void SetAllowProbeWithoutMediaPacket(bool allow); |
| 65 | |
Etienne Pierre-doray | 03bce3f | 2021-03-29 17:36:15 | [diff] [blame] | 66 | // Ensure that necessary delayed tasks are scheduled. |
| 67 | void EnsureStarted(); |
| 68 | |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 69 | // Methods implementing RtpPacketSender. |
| 70 | |
Per Kjellander | f075917 | 2021-04-09 11:41:53 | [diff] [blame] | 71 | // Adds the packet to the queue and calls |
| 72 | // PacingController::PacketSender::SendPacket() when it's time to send. |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 73 | void EnqueuePackets( |
| 74 | std::vector<std::unique_ptr<RtpPacketToSend>> packets) override; |
Erik Språng | 1b11b58 | 2022-12-09 20:38:44 | [diff] [blame] | 75 | // Remove any pending packets matching this SSRC from the packet queue. |
| 76 | void RemovePacketsForSsrc(uint32_t ssrc) override; |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 77 | |
Jianhui Dai | 9445779 | 2021-12-07 11:34:36 | [diff] [blame] | 78 | // Methods implementing RtpPacketPacer. |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 79 | |
Per Kjellander | 88af203 | 2022-05-16 17:58:40 | [diff] [blame] | 80 | void CreateProbeClusters( |
| 81 | std::vector<ProbeClusterConfig> probe_cluster_configs) override; |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 82 | |
| 83 | // Temporarily pause all sending. |
| 84 | void Pause() override; |
| 85 | |
| 86 | // Resume sending packets. |
| 87 | void Resume() override; |
| 88 | |
Erik Språng | 6673437 | 2022-03-16 13:20:49 | [diff] [blame] | 89 | void SetCongested(bool congested) override; |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 90 | |
| 91 | // Sets the pacing rates. Must be called once before packets can be sent. |
| 92 | void SetPacingRates(DataRate pacing_rate, DataRate padding_rate) override; |
| 93 | |
| 94 | // Currently audio traffic is not accounted for by pacer and passed through. |
| 95 | // With the introduction of audio BWE, audio traffic will be accounted for |
| 96 | // in the pacer budget calculation. The audio traffic will still be injected |
| 97 | // at high priority. |
| 98 | void SetAccountForAudioPackets(bool account_for_audio) override; |
| 99 | |
Sebastian Jansson | c3eb9fd | 2020-01-29 16:42:52 | [diff] [blame] | 100 | void SetIncludeOverhead() override; |
Mirko Bonadei | e7bc3a3 | 2020-01-29 18:45:00 | [diff] [blame] | 101 | void SetTransportOverhead(DataSize overhead_per_packet) override; |
| 102 | |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 103 | // Returns the time since the oldest queued packet was enqueued. |
| 104 | TimeDelta OldestPacketWaitTime() const override; |
| 105 | |
| 106 | // Returns total size of all packets in the pacer queue. |
| 107 | DataSize QueueSizeData() const override; |
| 108 | |
| 109 | // Returns the time when the first packet was sent; |
| 110 | absl::optional<Timestamp> FirstSentPacketTime() const override; |
| 111 | |
| 112 | // Returns the number of milliseconds it will take to send the current |
| 113 | // packets in the queue, given the current size and bitrate, ignoring prio. |
| 114 | TimeDelta ExpectedQueueTime() const override; |
| 115 | |
| 116 | // Set the max desired queuing delay, pacer will override the pacing rate |
| 117 | // specified by SetPacingRates() if needed to achieve this goal. |
| 118 | void SetQueueTimeLimit(TimeDelta limit) override; |
| 119 | |
Erik Språng | 998524a | 2020-05-29 14:13:32 | [diff] [blame] | 120 | protected: |
| 121 | // Exposed as protected for test. |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 122 | struct Stats { |
| 123 | Stats() |
Jianhui Dai | 9445779 | 2021-12-07 11:34:36 | [diff] [blame] | 124 | : oldest_packet_enqueue_time(Timestamp::MinusInfinity()), |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 125 | queue_size(DataSize::Zero()), |
| 126 | expected_queue_time(TimeDelta::Zero()) {} |
Jianhui Dai | 9445779 | 2021-12-07 11:34:36 | [diff] [blame] | 127 | Timestamp oldest_packet_enqueue_time; |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 128 | DataSize queue_size; |
| 129 | TimeDelta expected_queue_time; |
| 130 | absl::optional<Timestamp> first_sent_packet_time; |
| 131 | }; |
Jianhui Dai | 9445779 | 2021-12-07 11:34:36 | [diff] [blame] | 132 | void OnStatsUpdated(const Stats& stats); |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 133 | |
Erik Språng | 998524a | 2020-05-29 14:13:32 | [diff] [blame] | 134 | private: |
Markus Handell | e32b622 | 2023-05-08 22:59:46 | [diff] [blame] | 135 | // Call in response to state updates that could warrant sending out packets. |
| 136 | // Protected against re-entry from packet sent receipts. |
| 137 | void MaybeScheduleProcessPackets() RTC_RUN_ON(task_queue_); |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 138 | // Check if it is time to send packets, or schedule a delayed task if not. |
| 139 | // Use Timestamp::MinusInfinity() to indicate that this call has _not_ |
Markus Handell | e32b622 | 2023-05-08 22:59:46 | [diff] [blame] | 140 | // been scheduled by the pacing controller. If this is the case, check if we |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 141 | // can execute immediately otherwise schedule a delay task that calls this |
| 142 | // method again with desired (finite) scheduled process time. |
| 143 | void MaybeProcessPackets(Timestamp scheduled_process_time); |
| 144 | |
Jianhui Dai | 9445779 | 2021-12-07 11:34:36 | [diff] [blame] | 145 | void UpdateStats() RTC_RUN_ON(task_queue_); |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 146 | Stats GetStats() const; |
| 147 | |
| 148 | Clock* const clock_; |
Evan Shrubsole | 262b2d8 | 2023-02-17 09:08:06 | [diff] [blame] | 149 | |
Henrik Boström | 554bb39 | 2022-03-16 09:16:29 | [diff] [blame] | 150 | // The holdback window prevents too frequent delayed MaybeProcessPackets() |
Henrik Boström | a768f52 | 2022-04-13 10:37:59 | [diff] [blame] | 151 | // calls. These are only applicable if `allow_low_precision` is false. |
Erik Språng | 0f86c1f | 2021-10-26 14:19:03 | [diff] [blame] | 152 | const TimeDelta max_hold_back_window_; |
| 153 | const int max_hold_back_window_in_packets_; |
| 154 | |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 155 | PacingController pacing_controller_ RTC_GUARDED_BY(task_queue_); |
| 156 | |
| 157 | // We want only one (valid) delayed process task in flight at a time. |
Artem Titov | ee3e3fd | 2021-07-28 18:28:28 | [diff] [blame] | 158 | // If the value of `next_process_time_` is finite, it is an id for a |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 159 | // delayed task that will call MaybeProcessPackets() with that time |
| 160 | // as parameter. |
| 161 | // Timestamp::MinusInfinity() indicates no valid pending task. |
| 162 | Timestamp next_process_time_ RTC_GUARDED_BY(task_queue_); |
| 163 | |
Etienne Pierre-doray | 03bce3f | 2021-03-29 17:36:15 | [diff] [blame] | 164 | // Indicates if this task queue is started. If not, don't allow |
| 165 | // posting delayed tasks yet. |
Jianhui Dai | 9445779 | 2021-12-07 11:34:36 | [diff] [blame] | 166 | bool is_started_ RTC_GUARDED_BY(task_queue_); |
Etienne Pierre-doray | 03bce3f | 2021-03-29 17:36:15 | [diff] [blame] | 167 | |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 168 | // Indicates if this task queue is shutting down. If so, don't allow |
| 169 | // posting any more delayed tasks as that can cause the task queue to |
| 170 | // never drain. |
| 171 | bool is_shutdown_ RTC_GUARDED_BY(task_queue_); |
| 172 | |
Erik Språng | 0f86c1f | 2021-10-26 14:19:03 | [diff] [blame] | 173 | // Filtered size of enqueued packets, in bytes. |
| 174 | rtc::ExpFilter packet_size_ RTC_GUARDED_BY(task_queue_); |
Jianhui Dai | df59e53 | 2022-03-19 07:38:51 | [diff] [blame] | 175 | bool include_overhead_ RTC_GUARDED_BY(task_queue_); |
Erik Språng | 0f86c1f | 2021-10-26 14:19:03 | [diff] [blame] | 176 | |
Per K | 401c14a | 2023-04-11 07:53:48 | [diff] [blame] | 177 | Stats current_stats_ RTC_GUARDED_BY(task_queue_); |
Markus Handell | e32b622 | 2023-05-08 22:59:46 | [diff] [blame] | 178 | // Protects against ProcessPackets reentry from packet sent receipts. |
| 179 | bool processing_packets_ RTC_GUARDED_BY(task_queue_) = false; |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 180 | |
Per Kjellander | 9dc4305 | 2022-10-04 11:45:09 | [diff] [blame] | 181 | ScopedTaskSafety safety_; |
Per K | 401c14a | 2023-04-11 07:53:48 | [diff] [blame] | 182 | TaskQueueBase* task_queue_; |
Erik Språng | 4314a49 | 2019-11-26 16:48:49 | [diff] [blame] | 183 | }; |
| 184 | } // namespace webrtc |
| 185 | #endif // MODULES_PACING_TASK_QUEUE_PACED_SENDER_H_ |