github:https://github.com/bigonelby/webrtcUml/tree/master/latest
这个图展示了webrtc中的transport-CC解析后的核心:trendline预测与码率评估
上张图介绍了,TransportFeedbackAdapter已经将所有的原材料都准备好了,在PacketResult中详细的记录了各个包的接收时间和发送时间,这里就可以进入到核心了,即DelayBasedBwe
DelayBasedBwe由名称就可以知道,是基于延迟进行的带宽评估,这部分原本在接收端,最新的webrtc代码改进了这个行为,将这部分放在了发送端,也方便程序员的调试。那么帧到达的时间,就通过扩展RTCP包返回,即transport-cc。通过tranport-cc可以将包接收情况,包接收的时间返回给发送端。这部分内容前面已经介绍过了。因此,到了DelayBasedBwe,已经准备好了各个包的发送以及接收时间。模块将进行下一步的核心决策
整个决策分为三个部分:分组;过载检测;码率决策
分组模块即InterArrival,为何要分组呢?就是因为单个包的发送接收时间存在一定的偶然性,因此将相临近的包分为一组,模型数据更加可靠。分组的依据是什么呢?就是阈值kTimestampGroupLengthTicks。IntervalArrival模块记录了上一个包组prev_timestamp_group_以及当前包组current_timestamp_group_
记录包组的结构体为TimestampGroup,这个结构体中的size表示了包组的长度;first_timestamp,timestamp分别表示包组第一个包和最后一个包的发送时间;first_arrival_ms,complete_time_ms分别表示了包组第一个包和最后一个包的接收时间
通过InterArrival的NewTimestampGroup方法,判断当前packet是否属于新的包组了,判断的依据就是当前包的timestamp和包组的first_timestamp之差是否超过阈值kTimestampGroupLengthTicks,如果超过,则认为是新的分组,如果没超过,则还属于同一个分组
通过InterArrival模块,包被分成了包组,用包组的发送时间和接收时间,作为过载检测器的输入数据。过载检测器的接口为DelayIncreaseDetectorInterface,继承这个接口的就是TrendlineEstimator。接口有两个方法,其一是Update,即更新数据,即包组的发送和接收的时间;其二就是State,这个方法返回了当前探测出的网络状态,即BandwidthUsage,也就是kBwNormal还是kBwUnderusing亦或是kBwOverusing
如何决策出当前网络状态是正常还是过载还是不足呢?核心就是阈值比较。这里的阈值就是通过最小二乘法决策出的斜率。首先通过Update方法,出入包组相关数据,然后保存在delay_hist_中,这里保存的结构体为PacketTiming,有三个成员arrival_time_ms代表到达时间,raw_delay_ms是原始的延迟时间,即接收时间差减去发送时间差,smoothed_delay_ms是平滑后的延迟时间,是通过指数加权作用在raw_delay_ms,从而得出的数据。Trendline中的横坐标即为当前包组的到达时间 - 首包组到达时间;纵坐标为累积的平滑延迟。我们认为这些数据的关系是线性的,因此可以通过最小二乘法算出斜率。这个计算是通过LinearFitSlope计算出来的。
计算出斜率后,接着进入Detect方法,进行网络状态决策,首先对上一步决策出的斜率trend进行调整,得到modified_trend,再和阈值threshold_做比较,如果modified_trend > threshold_ 则为kBwOverusing;如果modified_trend < - threshold_ 则为kBwUnderUsing;否则即为kBwNormal
最后,通过UpdateThreshold更新阈值
通过以上两个步骤,已经得到了当前网络的状态是 正常 / 过载 / 不足。接下来通过码率控制模块rate_control_决策出具体的码率。这里的rate_control_即为AimdRateControl,所谓Aimd,就是和式增加,积式下降。输入为RateControlInput,这个参数是由DelayBasedBwe构建出来,并出入到Aimd模块的
首先调用Update方法,在这个方法中进一步调用了ChangeBitrate,在这里先调用了ChangeState,即通过上一次的rate_control_state_,结合过载检测器决策出来的BandwidthUsage,决策出当前的rate_control_state_。根据当前的rate_control_state_,决策在当前current_bitrate_的基础上进行和式增加或积式下降。并可以通过方法LastEstimate将决策出的current_bitrate_值返回
最后小结一下:这张图的核心就是DelayBasedBwe,入口就是IncomingPacketFeedbackVector,在这个入口里首先调用了IncomingPacketFeedback,在这个函数里,通过InterArrival模块进行分组,并通过TrendlineEstimator模块进行网络状态评测。之后DelayBasedBwe会通过MaybeUpdateEstimate方法决策是否需要更新码率,如果需要,即调用UpdateEstimate方法,这个方法构建了RateControlInput参数,并交给AimdRateControl模块进行最终的码率决策