A basic introduction to one of the principles of WebRTC congestion control

1 Basic principles

WebRTC's congestion control module uses a TCP-based congestion control algorithm. It adaptively adjusts the transmission rate based on information such as network bandwidth and delay.
Specifically, this module uses an improved version based on the delay jitter adjustment algorithm in RFC 3550. The basic principle of the implementation of the algorithm is to periodically detect the quality and delay of the network during the transmission process, and adjust the transmission rate adaptively based on this information.

Specific steps are as follows:

  • Regularly measure network latency and bandwidth to understand current network conditions.
  • Calculate the maximum available transmission rate according to the current network conditions.
  • Dynamically adjust the transfer rate based on the current bandwidth and latency conditions.
  • If there is a problem with the network quality, the transmission rate will be reduced immediately.
  • Detect changes in network quality and adjust transmission rates in time.
  • Maintain a balanced transfer rate to maximize the use of available bandwidth.

In short, WebRTC's congestion control module uses an advanced adaptive algorithm to increase the transmission rate as much as possible without affecting the communication quality. This makes WebRTC a very powerful and practical real-time communication technology. The following analysis is based on the [WebRTC source stamp 2022-03-04T04:05:35] version. Compared with the previous version, the biggest improvement of the new version is based on the bandwidth estimation of the receiving end, which does not require the sending end to participate in the bandwidth estimation calculation, so it does not need to rely on the bandwidth estimation of the sending end.

2 overall structure

The congestion control module is located in the congestion_controller module in modules.
include directory: implements the external API of the congestion control module.
goog_cc directory: implements the main functions of Google Congestion Control, provides rich interfaces and data types, and helps developers easily implement efficient congestion control algorithms to provide high-quality real-time video and audio communication services. Google Congestion Control is an open source implementation of congestion control algorithms, the purpose of which is to improve the quality of video and audio transmission in unstable or high-latency network environments.
pcc directory: implements the PCC (Probe Congestion Control) congestion control algorithm, which is a probe-based congestion control algorithm. The PCC algorithm does not need to accurately estimate the network bandwidth, but sends a set of probe packets to detect the status of the network, and then adjusts the transmission rate to achieve congestion control.
rtp directory: implements RTP (Real-time Transport Protocol) congestion control algorithm. RTP is a protocol for real-time transmission of audio and video, which can process data such as grouping and time stamping. The RTP congestion control algorithm realizes data transmission control under different network congestion conditions.

3 Interpretation of external API

The external API is encapsulated in the ReceiveSideCongestionController class. As the name implies, this is a congestion control algorithm based on the receiving end. The constructor of the ReceiveSideCongestionController class is used to create a receiver congestion controller object to ensure the stability and reliability of data transmission. This type of object needs to provide information such as clock, transmission feedback information sending function, REMB message sending function and network state estimator for operations such as congestion control and bit rate adjustment.

class ReceiveSideCongestionController : public CallStatsObserver {
 public:
  // Constructor
  /*
	The parameters of the constructor are as follows:
	clock: A pointer to a Clock class object to get the current timestamp.
	feedback_sender: A function object used to send transport feedback information.
	remb_sender: A function object for sending REMB (Receiver Estimated Maximum Bitrate) messages.
	network_state_estimator: A pointer to a NetworkStateEstimator object used to estimate the state of the network (such as bandwidth, packet loss rate, etc.).
  */
  ReceiveSideCongestionController(
      Clock* clock,
      RemoteEstimatorProxy::TransportFeedbackSender feedback_sender,
      RembThrottler::RembSender remb_sender,
      NetworkStateEstimator* network_state_estimator);
      Clock* clock, // clock
      RemoteEstimatorProxy::TransportFeedbackSender feedback_sender, // remote estimation agent
      RembThrottler::RembSender remb_sender, // REMB transmitter
      NetworkStateEstimator* network_state_estimator); // Network State Estimator

  ~ReceiveSideCongestionController() override {}

  // Callback function when a packet is received
  void OnReceivedPacket(const RtpPacketReceived& packet, MediaType media_type);

  // TODO(perkj, bugs.webrtc.org/14859): Remove all usage. This method is
  // currently not used by PeerConnections.
  virtual void OnReceivedPacket(int64_t arrival_time_ms,
                                size_t payload_size,
                                const RTPHeader& header);
  // Implements CallStatsObserver.
  // Implement the CallStatsObserver interface, called when the RTT is updated
  void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override;

  // This is send bitrate, used to control the rate of feedback messages.
  // This is the send bitrate, used to control the rate of feedback messages.
  void OnBitrateChanged(int bitrate_bps);

  // Ensures the remote party is notified of the receive bitrate no larger than
  // `bitrate` using RTCP REMB.
  // Make sure to use RTCP REMB to inform the remote party that the received bitrate is not greater than `bitrate`.
  void SetMaxDesiredReceiveBitrate(DataRate bitrate);

  // Set transfer overhead
  void SetTransportOverhead(DataSize overhead_per_packet);

  // Returns latest receive side bandwidth estimation.
  // Returns zero if receive side bandwidth estimation is unavailable.
  // Returns the latest receiver bandwidth estimate.
  // Returns zero if the receiver bandwidth estimate is not available.
  DataRate LatestReceiveSideEstimate() const;

  // Removes stream from receive side bandwidth estimation.
  // Noop if receive side bwe is not used or stream doesn't participate in it.
  // Remove streams from sink bandwidth estimation.
  // Does nothing if the sink bwe is not used or the stream is not involved.
  void RemoveStream(uint32_t ssrc);

  // Runs periodic tasks if it is time to run them, returns time until next
  // call to `MaybeProcess` should be non idle.
  // If it's time to run them, run the periodic task, return to the next
  // Call `MaybeProcess` when it should be non-idle.
  TimeDelta MaybeProcess();

 private:
  // Select estimator from head
  void PickEstimatorFromHeader(const RTPHeader& header)
      RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
  // Choose an estimator
  void PickEstimator() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);

  Clock& clock_; // clock
  RembThrottler remb_throttler_; // REMB transmitter
  RemoteEstimatorProxy remote_estimator_proxy_; // remote estimation agent

  mutable Mutex mutex_; // mutex
  std::unique_ptr<RemoteBitrateEstimator> rbe_ RTC_GUARDED_BY(mutex_); // Remote Bitrate Estimator
  bool using_absolute_send_time_ RTC_GUARDED_BY(mutex_); // Whether to use absolute sending time
  uint32_t packets_since_absolute_send_time_ RTC_GUARDED_BY(mutex_); // The number of packets since the absolute send time
};

Tags: network webrtc rtc

Posted by jauson on Wed, 22 Mar 2023 20:28:53 +0530