When congestion window is used, two different mechanisms can currently update the outstanding data state in the pacer: * OnPacketSent() withing the pacer itself, when a packet is sent * UpdateOutstandingData(), when RtpTransportControllerSend either: a. Receives an OnPacketSent() callback (increase outstanding data) b. Receives transport feedback (decrease outstanding data) This creates a lot of calls to UpdateOutstandingData(), more than one per sent packet. Each requires locking and/or thread jumps. To avoid that, this CL moves the congestion window state to RtpTransportController send - and we only post a congested flag down the the pacer when the state is changed. The only benefit I can see is of the old way is we prevent sending new packets immedately when the window is full, rather than in some edge cases queue extra packets on the network task queue before the congestion signal is received. That should be rare and benign. I think this simplified logic, which is easier to read and more performant, is a better tradeoff. Bug: webrtc:13417 Change-Id: I326dd88db86dc0d6dc685c61920654ac024e57ef Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/255600 Auto-Submit: Erik Språng <sprang@webrtc.org> Reviewed-by: Henrik Boström <hbos@webrtc.org> Commit-Queue: Henrik Boström <hbos@webrtc.org> Cr-Commit-Position: refs/heads/main@{#36220}
153 lines
5.5 KiB
C++
153 lines
5.5 KiB
C++
/*
|
|
* 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 <atomic>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "absl/types/optional.h"
|
|
#include "api/function_view.h"
|
|
#include "api/transport/field_trial_based_config.h"
|
|
#include "api/transport/network_types.h"
|
|
#include "api/transport/webrtc_key_value_config.h"
|
|
#include "modules/include/module.h"
|
|
#include "modules/pacing/bitrate_prober.h"
|
|
#include "modules/pacing/interval_budget.h"
|
|
#include "modules/pacing/pacing_controller.h"
|
|
#include "modules/pacing/packet_router.h"
|
|
#include "modules/pacing/rtp_packet_pacer.h"
|
|
#include "modules/rtp_rtcp/include/rtp_packet_sender.h"
|
|
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
|
|
#include "modules/utility/include/process_thread.h"
|
|
#include "rtc_base/synchronization/mutex.h"
|
|
#include "rtc_base/thread_annotations.h"
|
|
|
|
namespace webrtc {
|
|
class Clock;
|
|
class RtcEventLog;
|
|
|
|
class PacedSender : public RtpPacketPacer, public RtpPacketSender {
|
|
public:
|
|
// Expected max pacer delay in ms. If ExpectedQueueTime() 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;
|
|
|
|
// TODO(bugs.webrtc.org/10937): Make the `process_thread` argument be non
|
|
// optional once all callers have been updated.
|
|
PacedSender(Clock* clock,
|
|
PacketRouter* packet_router,
|
|
RtcEventLog* event_log,
|
|
const WebRtcKeyValueConfig& field_trials,
|
|
ProcessThread* process_thread = nullptr);
|
|
|
|
~PacedSender() override;
|
|
|
|
// Methods implementing RtpPacketSender.
|
|
|
|
// Adds the packet to the queue and calls PacketRouter::SendPacket() when
|
|
// it's time to send.
|
|
void EnqueuePackets(
|
|
std::vector<std::unique_ptr<RtpPacketToSend>> packet) override;
|
|
|
|
// Methods implementing RtpPacketPacer:
|
|
|
|
void CreateProbeCluster(DataRate bitrate, int cluster_id) override;
|
|
|
|
// Temporarily pause all sending.
|
|
void Pause() override;
|
|
|
|
// Resume sending packets.
|
|
void Resume() override;
|
|
|
|
void SetCongested(bool congested) override;
|
|
|
|
// Sets the pacing rates. Must be called once before packets can be sent.
|
|
void SetPacingRates(DataRate pacing_rate, DataRate padding_rate) 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;
|
|
|
|
void SetIncludeOverhead() override;
|
|
void SetTransportOverhead(DataSize overhead_per_packet) override;
|
|
|
|
// Returns the time since the oldest queued packet was enqueued.
|
|
TimeDelta OldestPacketWaitTime() const override;
|
|
|
|
DataSize QueueSizeData() const override;
|
|
|
|
// Returns the time when the first packet was sent;
|
|
absl::optional<Timestamp> FirstSentPacketTime() const override;
|
|
|
|
// Returns the number of milliseconds it will take to send the current
|
|
// packets in the queue, given the current size and bitrate, ignoring prio.
|
|
TimeDelta ExpectedQueueTime() const override;
|
|
|
|
void SetQueueTimeLimit(TimeDelta limit) override;
|
|
|
|
// Below are methods specific to this implementation, such as things related
|
|
// to module processing thread specifics or methods exposed for test.
|
|
|
|
private:
|
|
// Returns the number of milliseconds until the module want a worker thread
|
|
// to call Process.
|
|
int64_t TimeUntilNextProcess();
|
|
// Called when the prober is associated with a process thread.
|
|
void ProcessThreadAttached(ProcessThread* process_thread);
|
|
// Process any pending packets in the queue(s).
|
|
void Process();
|
|
|
|
// In dynamic process mode, refreshes the next process time.
|
|
void MaybeWakupProcessThread();
|
|
|
|
// Private implementation of Module to not expose those implementation details
|
|
// publicly and control when the class is registered/deregistered.
|
|
class ModuleProxy : public Module {
|
|
public:
|
|
explicit ModuleProxy(PacedSender* delegate) : delegate_(delegate) {}
|
|
|
|
private:
|
|
int64_t TimeUntilNextProcess() override {
|
|
return delegate_->TimeUntilNextProcess();
|
|
}
|
|
void Process() override { return delegate_->Process(); }
|
|
void ProcessThreadAttached(ProcessThread* process_thread) override {
|
|
return delegate_->ProcessThreadAttached(process_thread);
|
|
}
|
|
|
|
PacedSender* const delegate_;
|
|
} module_proxy_{this};
|
|
|
|
mutable Mutex mutex_;
|
|
const PacingController::ProcessMode process_mode_;
|
|
PacingController pacing_controller_ RTC_GUARDED_BY(mutex_);
|
|
|
|
Clock* const clock_;
|
|
ProcessThread* const process_thread_;
|
|
};
|
|
} // namespace webrtc
|
|
#endif // MODULES_PACING_PACED_SENDER_H_
|