Finish painful bytes/sec -> bits/sec conversion.

This commit is contained in:
Oliver Woodman 2014-08-01 15:51:21 +01:00
parent 0f57a5f1cf
commit ad26085e5c
5 changed files with 38 additions and 49 deletions

View File

@ -80,9 +80,9 @@ public class EventLogger implements DemoPlayer.Listener, DemoPlayer.InfoListener
// DemoPlayer.InfoListener
@Override
public void onBandwidthSample(int elapsedMs, long bytes, long bandwidthEstimate) {
public void onBandwidthSample(int elapsedMs, long bytes, long bitrateEstimate) {
Log.d(TAG, "bandwidth [" + getSessionTimeString() + ", " + bytes +
", " + getTimeString(elapsedMs) + ", " + bandwidthEstimate + "]");
", " + getTimeString(elapsedMs) + ", " + bitrateEstimate + "]");
}
@Override

View File

@ -121,7 +121,7 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
void onVideoFormatEnabled(String formatId, int trigger, int mediaTimeMs);
void onAudioFormatEnabled(String formatId, int trigger, int mediaTimeMs);
void onDroppedFrames(int count, long elapsed);
void onBandwidthSample(int elapsedMs, long bytes, long bandwidthEstimate);
void onBandwidthSample(int elapsedMs, long bytes, long bitrateEstimate);
void onLoadStarted(int sourceId, String formatId, int trigger, boolean isInitialization,
int mediaStartTimeMs, int mediaEndTimeMs, long totalBytes);
void onLoadCompleted(int sourceId);
@ -391,9 +391,9 @@ public class DemoPlayer implements ExoPlayer.Listener, ChunkSampleSource.EventLi
}
@Override
public void onBandwidthSample(int elapsedMs, long bytes, long bandwidthEstimate) {
public void onBandwidthSample(int elapsedMs, long bytes, long bitrateEstimate) {
if (infoListener != null) {
infoListener.onBandwidthSample(elapsedMs, bytes, bandwidthEstimate);
infoListener.onBandwidthSample(elapsedMs, bytes, bitrateEstimate);
}
}

View File

@ -164,7 +164,7 @@ public interface FormatEvaluator {
*/
public static class AdaptiveEvaluator implements FormatEvaluator {
public static final int DEFAULT_MAX_INITIAL_BYTE_RATE = 100000;
public static final int DEFAULT_MAX_INITIAL_BITRATE = 800000;
public static final int DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS = 10000;
public static final int DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS = 25000;
@ -173,7 +173,7 @@ public interface FormatEvaluator {
private final BandwidthMeter bandwidthMeter;
private final int maxInitialByteRate;
private final int maxInitialBitrate;
private final long minDurationForQualityIncreaseUs;
private final long maxDurationForQualityDecreaseUs;
private final long minDurationToRetainAfterDiscardUs;
@ -183,7 +183,7 @@ public interface FormatEvaluator {
* @param bandwidthMeter Provides an estimate of the currently available bandwidth.
*/
public AdaptiveEvaluator(BandwidthMeter bandwidthMeter) {
this (bandwidthMeter, DEFAULT_MAX_INITIAL_BYTE_RATE,
this (bandwidthMeter, DEFAULT_MAX_INITIAL_BITRATE,
DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS,
DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS,
DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, DEFAULT_BANDWIDTH_FRACTION);
@ -191,7 +191,7 @@ public interface FormatEvaluator {
/**
* @param bandwidthMeter Provides an estimate of the currently available bandwidth.
* @param maxInitialByteRate The maximum bandwidth in bytes per second that should be assumed
* @param maxInitialBitrate The maximum bitrate in bits per second that should be assumed
* when bandwidthMeter cannot provide an estimate due to playback having only just started.
* @param minDurationForQualityIncreaseMs The minimum duration of buffered data required for
* the evaluator to consider switching to a higher quality format.
@ -206,13 +206,13 @@ public interface FormatEvaluator {
* for inaccuracies in the bandwidth estimator.
*/
public AdaptiveEvaluator(BandwidthMeter bandwidthMeter,
int maxInitialByteRate,
int maxInitialBitrate,
int minDurationForQualityIncreaseMs,
int maxDurationForQualityDecreaseMs,
int minDurationToRetainAfterDiscardMs,
float bandwidthFraction) {
this.bandwidthMeter = bandwidthMeter;
this.maxInitialByteRate = maxInitialByteRate;
this.maxInitialBitrate = maxInitialBitrate;
this.minDurationForQualityIncreaseUs = minDurationForQualityIncreaseMs * 1000L;
this.maxDurationForQualityDecreaseUs = maxDurationForQualityDecreaseMs * 1000L;
this.minDurationToRetainAfterDiscardUs = minDurationToRetainAfterDiscardMs * 1000L;
@ -235,7 +235,7 @@ public interface FormatEvaluator {
long bufferedDurationUs = queue.isEmpty() ? 0
: queue.get(queue.size() - 1).endTimeUs - playbackPositionUs;
Format current = evaluation.format;
Format ideal = determineIdealFormat(formats, bandwidthMeter.getEstimate());
Format ideal = determineIdealFormat(formats, bandwidthMeter.getBitrateEstimate());
boolean isHigher = ideal != null && current != null && ideal.bitrate > current.bitrate;
boolean isLower = ideal != null && current != null && ideal.bitrate < current.bitrate;
if (isHigher) {
@ -276,11 +276,11 @@ public interface FormatEvaluator {
/**
* Compute the ideal format ignoring buffer health.
*/
protected Format determineIdealFormat(Format[] formats, long bandwidthEstimate) {
long effectiveBandwidth = computeEffectiveBandwidthEstimate(bandwidthEstimate);
protected Format determineIdealFormat(Format[] formats, long bitrateEstimate) {
long effectiveBitrate = computeEffectiveBitrateEstimate(bitrateEstimate);
for (int i = 0; i < formats.length; i++) {
Format format = formats[i];
if ((format.bitrate / 8) <= effectiveBandwidth) {
if (format.bitrate <= effectiveBitrate) {
return format;
}
}
@ -291,9 +291,9 @@ public interface FormatEvaluator {
/**
* Apply overhead factor, or default value in absence of estimate.
*/
protected long computeEffectiveBandwidthEstimate(long bandwidthEstimate) {
return bandwidthEstimate == BandwidthMeter.NO_ESTIMATE
? maxInitialByteRate : (long) (bandwidthEstimate * bandwidthFraction);
protected long computeEffectiveBitrateEstimate(long bitrateEstimate) {
return bitrateEstimate == BandwidthMeter.NO_ESTIMATE
? maxInitialBitrate : (long) (bitrateEstimate * bandwidthFraction);
}
}

View File

@ -26,10 +26,10 @@ public interface BandwidthMeter {
final long NO_ESTIMATE = -1;
/**
* Gets the estimated bandwidth.
* Gets the estimated bandwidth, in bits/sec.
*
* @return Estimated bandwidth in bytes/sec, or {@link #NO_ESTIMATE} if no estimate is available.
* @return Estimated bandwidth in bits/sec, or {@link #NO_ESTIMATE} if no estimate is available.
*/
long getEstimate();
long getBitrateEstimate();
}

View File

@ -38,11 +38,11 @@ public class DefaultBandwidthMeter implements BandwidthMeter, TransferListener {
*
* @param elapsedMs The time taken to transfer the bytes, in milliseconds.
* @param bytes The number of bytes transferred.
* @param bandwidthEstimate The estimated bandwidth in bytes/sec, or {@link #NO_ESTIMATE} if no
* estimate is available. Note that this estimate is typically derived from more information
* than {@code bytes} and {@code elapsedMs}.
* @param bitrate The estimated bitrate in bits/sec, or {@link #NO_ESTIMATE} if no estimate
* is available. Note that this estimate is typically derived from more information than
* {@code bytes} and {@code elapsedMs}.
*/
void onBandwidthSample(int elapsedMs, long bytes, long bandwidthEstimate);
void onBandwidthSample(int elapsedMs, long bytes, long bitrate);
}
@ -53,9 +53,9 @@ public class DefaultBandwidthMeter implements BandwidthMeter, TransferListener {
private final Clock clock;
private final SlidingPercentile slidingPercentile;
private long accumulator;
private long bytesAccumulator;
private long startTimeMs;
private long bandwidthEstimate;
private long bitrateEstimate;
private int streamCount;
public DefaultBandwidthMeter() {
@ -80,17 +80,12 @@ public class DefaultBandwidthMeter implements BandwidthMeter, TransferListener {
this.eventListener = eventListener;
this.clock = clock;
this.slidingPercentile = new SlidingPercentile(maxWeight);
bandwidthEstimate = NO_ESTIMATE;
bitrateEstimate = NO_ESTIMATE;
}
/**
* Gets the estimated bandwidth.
*
* @return Estimated bandwidth in bytes/sec, or {@link #NO_ESTIMATE} if no estimate is available.
*/
@Override
public synchronized long getEstimate() {
return bandwidthEstimate;
public synchronized long getBitrateEstimate() {
return bitrateEstimate;
}
@Override
@ -103,7 +98,7 @@ public class DefaultBandwidthMeter implements BandwidthMeter, TransferListener {
@Override
public synchronized void onBytesTransferred(int bytes) {
accumulator += bytes;
bytesAccumulator += bytes;
}
@Override
@ -112,32 +107,26 @@ public class DefaultBandwidthMeter implements BandwidthMeter, TransferListener {
long nowMs = clock.elapsedRealtime();
int elapsedMs = (int) (nowMs - startTimeMs);
if (elapsedMs > 0) {
float bytesPerSecond = accumulator * 1000 / elapsedMs;
slidingPercentile.addSample(computeWeight(accumulator), bytesPerSecond);
float bitsPerSecond = (bytesAccumulator * 8000) / elapsedMs;
slidingPercentile.addSample((int) Math.sqrt(bytesAccumulator), bitsPerSecond);
float bandwidthEstimateFloat = slidingPercentile.getPercentile(0.5f);
bandwidthEstimate = Float.isNaN(bandwidthEstimateFloat) ? NO_ESTIMATE
bitrateEstimate = Float.isNaN(bandwidthEstimateFloat) ? NO_ESTIMATE
: (long) bandwidthEstimateFloat;
notifyBandwidthSample(elapsedMs, accumulator, bandwidthEstimate);
notifyBandwidthSample(elapsedMs, bytesAccumulator, bitrateEstimate);
}
streamCount--;
if (streamCount > 0) {
startTimeMs = nowMs;
}
accumulator = 0;
bytesAccumulator = 0;
}
// TODO: Use media time (bytes / mediaRate) as weight.
private int computeWeight(long mediaBytes) {
return (int) Math.sqrt(mediaBytes);
}
private void notifyBandwidthSample(final int elapsedMs, final long bytes,
final long bandwidthEstimate) {
private void notifyBandwidthSample(final int elapsedMs, final long bytes, final long bitrate) {
if (eventHandler != null && eventListener != null) {
eventHandler.post(new Runnable() {
@Override
public void run() {
eventListener.onBandwidthSample(elapsedMs, bytes, bandwidthEstimate);
eventListener.onBandwidthSample(elapsedMs, bytes, bitrate);
}
});
}