/*! @license
* Shaka Player
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
goog.provide('shaka.offline.DownloadProgressEstimator');
/**
* The download progress estimator class encapsulates all the logic for tracking
* how much content has been downloaded and estimating its progress.
*
* @final
*/
shaka.offline.DownloadProgressEstimator = class {
/** */
constructor() {
/**
* This is the sum of all estimates passed to |open|. This is used as the
* denominator when measuring progress.
*
* @private {number}
*/
this.estimatedTotal_ = 0;
/**
* This is the sum of all estimates pass to |open| but only after |close|
* has been called. This is used as the numerator when measuring progress so
* that |estimatedTotal_ == estimatedDownloaded_| after everything is
* downloaded.
*
* @private {number}
*/
this.estimatedDownloaded_ = 0;
/**
* This is the total number of bytes actually downloaded. This will most
* likely differ from |estimatedTotal_| after everything is downloaded since
* our estimates will be off.
*
* @private {number}
*/
this.actualDownloaded_ = 0;
/**
* This is a map of all pending downloads. This maps their download id (an
* internal id) to the estimate. This will allow us to update
* |estimatedDownloaded_| when |close| is called.
*
* @private {!Map.<number, number>}
*/
this.pending_ = new Map();
/**
* This number is used to provide unique (to estimator) ids for each
* download. This allows us to track each download in |pending_|.
*
* @private {number}
*/
this.nextId_ = 0;
}
/**
* Open a new download in the progress estimator. This will create an entry so
* that we can track the download progress.
*
* This will return an id for the download. This id must be passed to |close|
* in order for the |close| to be paired with this call to |open|.
*
* @param {number} estimate
* @return {number}
*/
open(estimate) {
this.estimatedTotal_ += estimate;
const id = this.nextId_;
this.nextId_++;
this.pending_.set(id, estimate);
return id;
}
/**
* Close a download in the estimator. This will signal that we have finished
* downloading a segment and we can update the progress estimate.
*
* @param {number} id
* @param {number} actual
*/
close(id, actual) {
if (!this.pending_.has(id)) {
return;
}
const estimate = this.pending_.get(id);
this.pending_.delete(id);
this.estimatedDownloaded_ += estimate;
this.actualDownloaded_ += actual;
}
/**
* Get the current estimate for how much progress we've made downloading the
* content. Progress will be between 0 and 1.
*
* Depending on the order of calls to |open| and |close|,
* |getEstimatedProgress| will fluctuate and is not guaranteed to always be
* increasing.
*
* @return {number}
*/
getEstimatedProgress() {
return this.estimatedTotal_ == 0 ?
0 :
this.estimatedDownloaded_ / this.estimatedTotal_;
}
/**
* Get the total number of bytes that were actually downloaded.
*
* @return {number}
*/
getTotalDownloaded() {
return this.actualDownloaded_;
}
};