ExoPlayer是根據以往的下載速度來估計當前的網速
現介紹一下幾個符號:
采樣數組定義如下:
private final ArrayList<Sample> samples;
上述采樣數組用于存儲歷史采樣點。
采樣點定義如下:
private static class Sample {
public int index;
public int weight;
public float value;
}
index存儲的是當前采樣點在采樣數組的索引,它是用來還原采樣數組順序用的,可以忽略
weight存儲的是每次下載數據大小的平方根,下載數據的單位是byte
value存儲的是每次下載的速度,單位是bit/s(bps)
網速估計的過程
1.采樣點的添加方法
每下載一次數據,生成一個Sample,權重weight為每次下載到的數據的Bytes數的平方根;value為每次下載數據的bps
將Sample按照時間順序加入采樣數組samples里
采樣數組samples的大小定義為totalWeight,totalWeight是所有采樣點Sample中weight的和(注意這里采樣數組大小的定義,不是以往的按照采樣點來定義的),這個大小有個上限定義為maxWeight=2000
當加入當前采樣點后,如果totalWeight>maxWeight,把最先加入采樣數組的sample移除,直到totalWeight<=maxWeight
2.網速估計方法:
將采樣數組按照采樣點中的value值從小到大排序
定義一個desiredWeight,desiredWeight=totalWeight/2
從頭遍歷排序完的采樣數組(從小value開始),依次累加各個樣本的weight值,當累加值大于等于desiredWeight時,此時對應的value值為估計的網速。如果此時累加所有的采樣點的值仍小于desiredWeight時,返回最近采樣點的value值。
原理文檔
其網速估計類名為SlidingPercetile.java,官網給出了該算法的原理鏈接,Wiki: Moving average, Wiki: Selection algorithm
個人理解
其實ExoPlayer的網速估計算法類似于移動平均,但是又不完全相同,沒找到具體的講ExoPlayer網速估計的算法文章了。個人理解,是這樣的,假設每次下載的片段大小時一樣的,那么這時候取的網速其實是所有網速的一個中位數,這樣就去除了大值和小值的影響,這樣預測出來的網速準確性未知,畢竟沒找到相應的文章寫這個算法的網速預測結果。
網速估計獲取
上述Sample中的weight和value在ExoPlayer中按照如下方法計算所得:
- DefaultBandwidthMeter::onTransferStart()用于記錄下載起始時間sampleStartTimeMs。在DefaultHttpDataSource::open()調用(每次下載數據起始)
- DefaultBandwidthMeter::onBytesTransferred()用于記錄下載的總字節(jié)數sampleBytesTransferred。在DefaultHttpDataSource::read()中調用。
- DefaultBandwidthMeter::onTransferEnd(),記錄下載結束時間,同時生成本次下載過程的Sample(權重和bps),加入采樣數組中,并調用上面的算法計算出當前的bitrateEstimate;最后清零sampleBytesTransferred,準備計算下個Sample。在DefaultHttpDataSource::close() 中調用。
注意:播放列表和音視頻數據下載的Sample都會統(tǒng)計到計算中。
這一步完成之后,會得到當前的估計網速,bitrateEstimate。