The bandwidth adaptive algorithm in WEBRTC is divided into two types:
1, the originator bandwidth control, the principle is the RTCP in the packet loss statistics to dynamically increase or decrease the bandwidth, in the reduction of bandwidth using the TFRC algorithm to increase the smoothness.
2, the receiver bandwidth estimation, the principle is and by the receipt of RTP data, the estimated bandwidth, with the Kalman filter, the transmission time and reception time of each frame is analyzed, so as to obtain the network bandwidth utilization, revise the estimated bandwidth.
The two algorithms complement each other, and the receiver sends the estimated bandwidth to the originator, which, in combination with the received bandwidth and packet loss rate, adjusts the transmitted bandwidth.
The following is a detailed analysis of two algorithms:
2, receiver-side bandwidth estimation algorithm analysis
Combined with document HTTP://TOOLS.IETF.ORG/HTML/DRAFT-ALVESTRAND-RTCWEB-CONGESTION-02 and source Webrtc/modules/remote_bitrate_ estimator/overuse_detector.cc for analysis
Bandwidth estimation Model: D (i) = DL (i)/C + W (i) d (i) two frame data transmission time difference, DL (i) two frame data size difference, C for network transmission capability, W (i) is our focus, it is mainly determined by three factors: transmission rate, network routing capability, and network transmission Transmission capacity. W (i) conforms to the Gaussian distribution, as a conclusion: when W (i) is increased, it consumes too much bandwidth (over-using), and when W (i) is reduced, consumes less bandwidth (under-using), and for 0 o'clock, the exact bandwidth is used. So, as long as we can calculate w (i), we can determine the current network usage, thereby increasing or reducing the rate of transmission.
Algorithm principle: That is application kalman-filters
Theta_hat (i) = [1/c_hat (i) m_hat (i)]^t//I The State of the time point is represented by C, M, and Theta_hat (i) is the estimated value at this time
Z (i) = d (i)-H_bar (i) ^t * Theta_hat (i-1)//d (i) is the test value, can be easily calculated, the following can be considered as D (i-1) estimates, so Z (i) is the deviation of D (i), that is, the residual
Theta_hat (i) = Theta_hat (i-1) + Z (i) * K_bar (i)///OK, this is the result we want, the key is the selection of K value, the following two formula is to take the K value, the concrete derivation see the subsequent blog post.
E (i-1) * H_bar (i)
K_bar (i) =--------------------------------------------
Var_v_hat + h_bar (i) ^t * E (i-1) * H_bar (i)
E (i) = (I-k_bar (i) * H_bar (i) ^t) * E (i-1) + Q (i)//h_bar (i) calculated from the packet size of the frame
Thus, we only need to know the current frame length, send time, receive time and the state of the previous frame, you can calculate the network usage.
Next, take a look at the code:
[CPP] View plain copy Void overusedetector::updatekalman (int64_t t_delta, double ts_delta, uint32_t frame_size, uint32_t prev_frame_size) { const Double min_frame_period = updateminframeperiod (Ts_delta); const Double drift&nbSp;= currentdrift (); // Compensate for drift const double t_ts_delta = t_delta - ts_delta / drift; //d (i) double fs_delta = static_cast<double> (frame_size) - prev_frame_size; // update the kalman filter const double scale_factor = min_frame_period / (1000.0 / 30.0); e_[0][0] += process_noise_[0] * scale_factor; E_[1][1] += process_noise_[1] * scale_factor; if ((hypothesis_ == kbwoverusing && offset_ < prev_offset_) | | (hypothesis_ == kbwunderusing && offset_ > prev_offset_)) { e_[1][1] + = 10 * process_noise_[1] * scale_factor; } const double h[2] = {fs_delta, 1.0}; //is h_bar const double Eh[2] = {E_[0][0]*h[0] + E_[0][1]*h[1], E_[1][0]*h[0] + E_[1][1]*h[1]}; const double residual = t_ts_delta - slope_*h[0] - offset_; //is Z (i), slope is 1/c const bool stable_state = (Bwe_min (num_of_deltas_, 60) &NBSP;*&NBSP;FABSF (offset_) &NBSP;<&NBSP;THRESHOLD_); // we try to filter out very late frames. For instance periodic key // frames doesn ' T fit the Gaussian model well. if (FABSF (residual) < 3 &NBSP;*&NBSP;SQRT (var_noise_)) { updatenoiseestimate (residual, min_frame_period, stable_state); } else { updatenoiseestimate (3 * sqrt (var_noise_), min_frame_period, stable_state); } const double denom = var_noise_ + h[0]*Eh[0] + h[1]*Eh[1]; const double k[2] = {Eh[0] / denom, eh[1] / denom}; //is k_bar const double ikh[2][2] = {{1.0 - k[0]*h[0], - k[0]*h[1]}, {-k[1]*h[0], 1.0 - K[1]*h[1]}};