依據(jù)下載sampleBytesTransferred開方數(shù)作為weight參數(shù)調(diào)用addSample,意味著下載碼率越高weight越大
public synchronized void onTransferEnd(DataSource source, DataSpec dataSpec, boolean isNetwork) {
if (!isNetwork) {
return;
}
Assertions.checkState(streamCount > 0);
long nowMs = clock.elapsedRealtime();
int sampleElapsedTimeMs = (int) (nowMs - sampleStartTimeMs);
totalElapsedTimeMs += sampleElapsedTimeMs;
totalBytesTransferred += sampleBytesTransferred;
if (sampleElapsedTimeMs > 0) {
float bitsPerSecond = (sampleBytesTransferred * 8000) / sampleElapsedTimeMs;
slidingPercentile.addSample((int) Math.sqrt(sampleBytesTransferred), bitsPerSecond);
if (totalElapsedTimeMs >= ELAPSED_MILLIS_FOR_ESTIMATE
|| totalBytesTransferred >= BYTES_TRANSFERRED_FOR_ESTIMATE) {
bitrateEstimate = (long) slidingPercentile.getPercentile(0.5f);
}
}
notifyBandwidthSample(sampleElapsedTimeMs, sampleBytesTransferred, bitrateEstimate);
if (--streamCount > 0) {
sampleStartTimeMs = nowMs;
}
sampleBytesTransferred = 0;
}
按照INDEX插入weight,value,超出weight部分刪除最舊index對應的sample
/**
* Adds a new weighted value.
*
* @param weight The weight of the new observation.
* @param value The value of the new observation.
*/
public void addSample(int weight, float value) {
ensureSortedByIndex();
Sample newSample = recycledSampleCount > 0 ? recycledSamples[--recycledSampleCount]
: new Sample();
newSample.index = nextSampleIndex++;
newSample.weight = weight;
newSample.value = value;
samples.add(newSample);
totalWeight += weight;
for (int i = 0; i < samples.size(); i++) {
Sample currentSample = samples.get(i);
}
while (totalWeight > maxWeight) {
int excessWeight = totalWeight - maxWeight;
Sample oldestSample = samples.get(0);
if (oldestSample.weight <= excessWeight) {
totalWeight -= oldestSample.weight;
samples.remove(0);
if (recycledSampleCount < MAX_RECYCLED_SAMPLES) {
recycledSamples[recycledSampleCount++] = oldestSample;
}
} else {
oldestSample.weight -= excessWeight;
totalWeight -= excessWeight;
}
}
}
獲取當前value時,依據(jù)value排序:
如果weight較小,窗口中累加weight次數(shù)較多,依據(jù)下載速度排序后會選擇value相對較大的sample
如果weight較大,累加weight次數(shù)較少,但在切片均勻的情況下通常weight也跟網(wǎng)速成正比(網(wǎng)速快才會下載更高碼率,sample size也會更大),此時選擇value可能直接就拿第一個sample了
/**
* Computes a percentile by integration.
*
* @param percentile The desired percentile, expressed as a fraction in the range (0,1].
* @return The requested percentile value or {@link Float#NaN} if no samples have been added.
*/
public float getPercentile(float percentile) {
ensureSortedByValue();
float desiredWeight = percentile * totalWeight;
int accumulatedWeight = 0;
for (int i = 0; i < samples.size(); i++) {
Sample currentSample = samples.get(i);
accumulatedWeight += currentSample.weight;
if (accumulatedWeight >= desiredWeight) {
return currentSample.value;
}
}
// Clamp to maximum value or NaN if no values.
return samples.isEmpty() ? Float.NaN : samples.get(samples.size() - 1).value;
}

sample.png