| /* |
| * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #ifndef MODULES_PACING_PACED_SENDER_H_ |
| #define MODULES_PACING_PACED_SENDER_H_ |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| #include <memory> |
| |
| #include "absl/types/optional.h" |
| #include "api/transport/network_types.h" |
| #include "modules/pacing/bitrate_prober.h" |
| #include "modules/pacing/interval_budget.h" |
| #include "modules/pacing/pacer.h" |
| #include "modules/pacing/round_robin_packet_queue.h" |
| #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
| #include "modules/utility/include/process_thread.h" |
| #include "rtc_base/criticalsection.h" |
| #include "rtc_base/thread_annotations.h" |
| |
| namespace webrtc { |
| class AlrDetector; |
| class Clock; |
| class RtcEventLog; |
| |
| class PacedSender : public Pacer { |
| public: |
| class PacketSender { |
| public: |
| // Note: packets sent as a result of a callback should not pass by this |
| // module again. |
| // Called when it's time to send a queued packet. |
| // Returns false if packet cannot be sent. |
| virtual bool TimeToSendPacket(uint32_t ssrc, |
| uint16_t sequence_number, |
| int64_t capture_time_ms, |
| bool retransmission, |
| const PacedPacketInfo& cluster_info) = 0; |
| // Called when it's a good time to send a padding data. |
| // Returns the number of bytes sent. |
| virtual size_t TimeToSendPadding(size_t bytes, |
| const PacedPacketInfo& cluster_info) = 0; |
| |
| protected: |
| virtual ~PacketSender() {} |
| }; |
| static constexpr int64_t kNoCongestionWindow = -1; |
| |
| // Expected max pacer delay in ms. If ExpectedQueueTimeMs() is higher than |
| // this value, the packet producers should wait (eg drop frames rather than |
| // encoding them). Bitrate sent may temporarily exceed target set by |
| // UpdateBitrate() so that this limit will be upheld. |
| static const int64_t kMaxQueueLengthMs; |
| // Pacing-rate relative to our target send rate. |
| // Multiplicative factor that is applied to the target bitrate to calculate |
| // the number of bytes that can be transmitted per interval. |
| // Increasing this factor will result in lower delays in cases of bitrate |
| // overshoots from the encoder. |
| static const float kDefaultPaceMultiplier; |
| |
| PacedSender(const Clock* clock, |
| PacketSender* packet_sender, |
| RtcEventLog* event_log); |
| |
| ~PacedSender() override; |
| |
| virtual void CreateProbeCluster(int bitrate_bps); |
| |
| // Temporarily pause all sending. |
| void Pause(); |
| |
| // Resume sending packets. |
| void Resume(); |
| |
| void SetCongestionWindow(int64_t congestion_window_bytes); |
| void UpdateOutstandingData(int64_t outstanding_bytes); |
| |
| // Enable bitrate probing. Enabled by default, mostly here to simplify |
| // testing. Must be called before any packets are being sent to have an |
| // effect. |
| void SetProbingEnabled(bool enabled); |
| |
| // Deprecated, SetPacingRates should be used instead. |
| void SetEstimatedBitrate(uint32_t bitrate_bps) override; |
| // Deprecated, SetPacingRates should be used instead. |
| void SetSendBitrateLimits(int min_send_bitrate_bps, |
| int max_padding_bitrate_bps); |
| |
| // Sets the pacing rates. Must be called once before packets can be sent. |
| void SetPacingRates(uint32_t pacing_rate_bps, |
| uint32_t padding_rate_bps) override; |
| |
| // Returns true if we send the packet now, else it will add the packet |
| // information to the queue and call TimeToSendPacket when it's time to send. |
| void InsertPacket(RtpPacketSender::Priority priority, |
| uint32_t ssrc, |
| uint16_t sequence_number, |
| int64_t capture_time_ms, |
| size_t bytes, |
| bool retransmission) override; |
| |
| // Currently audio traffic is not accounted by pacer and passed through. |
| // With the introduction of audio BWE audio traffic will be accounted for |
| // the pacer budget calculation. The audio traffic still will be injected |
| // at high priority. |
| void SetAccountForAudioPackets(bool account_for_audio) override; |
| |
| // Returns the time since the oldest queued packet was enqueued. |
| virtual int64_t QueueInMs() const; |
| |
| virtual size_t QueueSizePackets() const; |
| |
| // Returns the time when the first packet was sent, or -1 if no packet is |
| // sent. |
| virtual int64_t FirstSentPacketTimeMs() const; |
| |
| // Returns the number of milliseconds it will take to send the current |
| // packets in the queue, given the current size and bitrate, ignoring prio. |
| virtual int64_t ExpectedQueueTimeMs() const; |
| |
| // Deprecated, alr detection will be moved out of the pacer. |
| virtual absl::optional<int64_t> GetApplicationLimitedRegionStartTime(); |
| |
| // Returns the number of milliseconds until the module want a worker thread |
| // to call Process. |
| int64_t TimeUntilNextProcess() override; |
| |
| // Process any pending packets in the queue(s). |
| void Process() override; |
| |
| // Called when the prober is associated with a process thread. |
| void ProcessThreadAttached(ProcessThread* process_thread) override; |
| // Deprecated, SetPacingRates should be used instead. |
| void SetPacingFactor(float pacing_factor); |
| void SetQueueTimeLimit(int limit_ms); |
| |
| private: |
| int64_t UpdateTimeAndGetElapsedMs(int64_t now_us) |
| RTC_EXCLUSIVE_LOCKS_REQUIRED(critsect_); |
| bool ShouldSendKeepalive(int64_t at_time_us) const |
| RTC_EXCLUSIVE_LOCKS_REQUIRED(critsect_); |
| |
| // Updates the number of bytes that can be sent for the next time interval. |
| void UpdateBudgetWithElapsedTime(int64_t delta_time_in_ms) |
| RTC_EXCLUSIVE_LOCKS_REQUIRED(critsect_); |
| void UpdateBudgetWithBytesSent(size_t bytes) |
| RTC_EXCLUSIVE_LOCKS_REQUIRED(critsect_); |
| |
| const RoundRobinPacketQueue::Packet* GetPendingPacket( |
| const PacedPacketInfo& pacing_info) |
| RTC_EXCLUSIVE_LOCKS_REQUIRED(critsect_); |
| void OnPacketSent(const RoundRobinPacketQueue::Packet* packet) |
| RTC_EXCLUSIVE_LOCKS_REQUIRED(critsect_); |
| void OnPaddingSent(size_t padding_sent) |
| RTC_EXCLUSIVE_LOCKS_REQUIRED(critsect_); |
| |
| bool Congested() const RTC_EXCLUSIVE_LOCKS_REQUIRED(critsect_); |
| int64_t TimeMilliseconds() const RTC_EXCLUSIVE_LOCKS_REQUIRED(critsect_); |
| |
| const Clock* const clock_; |
| PacketSender* const packet_sender_; |
| std::unique_ptr<AlrDetector> alr_detector_ RTC_PT_GUARDED_BY(critsect_); |
| |
| const bool drain_large_queues_; |
| const bool send_padding_if_silent_; |
| const bool video_blocks_audio_; |
| |
| rtc::CriticalSection critsect_; |
| // TODO(webrtc:9716): Remove this when we are certain clocks are monotonic. |
| // The last millisecond timestamp returned by |clock_|. |
| mutable int64_t last_timestamp_ms_ RTC_GUARDED_BY(critsect_); |
| bool paused_ RTC_GUARDED_BY(critsect_); |
| // This is the media budget, keeping track of how many bits of media |
| // we can pace out during the current interval. |
| IntervalBudget media_budget_ RTC_GUARDED_BY(critsect_); |
| // This is the padding budget, keeping track of how many bits of padding we're |
| // allowed to send out during the current interval. This budget will be |
| // utilized when there's no media to send. |
| IntervalBudget padding_budget_ RTC_GUARDED_BY(critsect_); |
| |
| BitrateProber prober_ RTC_GUARDED_BY(critsect_); |
| bool probing_send_failure_ RTC_GUARDED_BY(critsect_); |
| // Actual configured bitrates (media_budget_ may temporarily be higher in |
| // order to meet pace time constraint). |
| uint32_t estimated_bitrate_bps_ RTC_GUARDED_BY(critsect_); |
| uint32_t min_send_bitrate_kbps_ RTC_GUARDED_BY(critsect_); |
| uint32_t max_padding_bitrate_kbps_ RTC_GUARDED_BY(critsect_); |
| uint32_t pacing_bitrate_kbps_ RTC_GUARDED_BY(critsect_); |
| |
| int64_t time_last_process_us_ RTC_GUARDED_BY(critsect_); |
| int64_t last_send_time_us_ RTC_GUARDED_BY(critsect_); |
| int64_t first_sent_packet_ms_ RTC_GUARDED_BY(critsect_); |
| |
| RoundRobinPacketQueue packets_ RTC_GUARDED_BY(critsect_); |
| uint64_t packet_counter_ RTC_GUARDED_BY(critsect_); |
| |
| int64_t congestion_window_bytes_ RTC_GUARDED_BY(critsect_) = |
| kNoCongestionWindow; |
| int64_t outstanding_bytes_ RTC_GUARDED_BY(critsect_) = 0; |
| float pacing_factor_ RTC_GUARDED_BY(critsect_); |
| // Lock to avoid race when attaching process thread. This can happen due to |
| // the Call class setting network state on SendSideCongestionController, which |
| // in turn calls Pause/Resume on Pacedsender, before actually starting the |
| // pacer process thread. If SendSideCongestionController is running on a task |
| // queue separate from the thread used by Call, this causes a race. |
| rtc::CriticalSection process_thread_lock_; |
| ProcessThread* process_thread_ RTC_GUARDED_BY(process_thread_lock_) = nullptr; |
| |
| int64_t queue_time_limit RTC_GUARDED_BY(critsect_); |
| bool account_for_audio_ RTC_GUARDED_BY(critsect_); |
| }; |
| } // namespace webrtc |
| #endif // MODULES_PACING_PACED_SENDER_H_ |