Source: lib/offline/download_progress_estimator.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.offline.DownloadProgressEstimator');
  7. /**
  8. * The download progress estimator class encapsulates all the logic for tracking
  9. * how much content has been downloaded and estimating its progress.
  10. *
  11. * @final
  12. */
  13. shaka.offline.DownloadProgressEstimator = class {
  14. /** */
  15. constructor() {
  16. /**
  17. * This is the sum of all estimates passed to |open|. This is used as the
  18. * denominator when measuring progress.
  19. *
  20. * @private {number}
  21. */
  22. this.estimatedTotal_ = 0;
  23. /**
  24. * This is the sum of all estimates pass to |open| but only after |close|
  25. * has been called. This is used as the numerator when measuring progress so
  26. * that |estimatedTotal_ == estimatedDownloaded_| after everything is
  27. * downloaded.
  28. *
  29. * @private {number}
  30. */
  31. this.estimatedDownloaded_ = 0;
  32. /**
  33. * This is the total number of bytes actually downloaded. This will most
  34. * likely differ from |estimatedTotal_| after everything is downloaded since
  35. * our estimates will be off.
  36. *
  37. * @private {number}
  38. */
  39. this.actualDownloaded_ = 0;
  40. /**
  41. * This is a map of all pending downloads. This maps their download id (an
  42. * internal id) to the estimate. This will allow us to update
  43. * |estimatedDownloaded_| when |close| is called.
  44. *
  45. * @private {!Map<number, number>}
  46. */
  47. this.pending_ = new Map();
  48. /**
  49. * This number is used to provide unique (to estimator) ids for each
  50. * download. This allows us to track each download in |pending_|.
  51. *
  52. * @private {number}
  53. */
  54. this.nextId_ = 0;
  55. }
  56. /**
  57. * Open a new download in the progress estimator. This will create an entry so
  58. * that we can track the download progress.
  59. *
  60. * This will return an id for the download. This id must be passed to |close|
  61. * in order for the |close| to be paired with this call to |open|.
  62. *
  63. * @param {number} estimate
  64. * @return {number}
  65. */
  66. open(estimate) {
  67. this.estimatedTotal_ += estimate;
  68. const id = this.nextId_;
  69. this.nextId_++;
  70. this.pending_.set(id, estimate);
  71. return id;
  72. }
  73. /**
  74. * Close a download in the estimator. This will signal that we have finished
  75. * downloading a segment and we can update the progress estimate.
  76. *
  77. * @param {number} id
  78. * @param {number} actual
  79. */
  80. close(id, actual) {
  81. if (!this.pending_.has(id)) {
  82. return;
  83. }
  84. const estimate = this.pending_.get(id);
  85. this.pending_.delete(id);
  86. this.estimatedDownloaded_ += estimate;
  87. this.actualDownloaded_ += actual;
  88. }
  89. /**
  90. * Get the current estimate for how much progress we've made downloading the
  91. * content. Progress will be between 0 and 1.
  92. *
  93. * Depending on the order of calls to |open| and |close|,
  94. * |getEstimatedProgress| will fluctuate and is not guaranteed to always be
  95. * increasing.
  96. *
  97. * @return {number}
  98. */
  99. getEstimatedProgress() {
  100. return this.estimatedTotal_ == 0 ?
  101. 0 :
  102. this.estimatedDownloaded_ / this.estimatedTotal_;
  103. }
  104. /**
  105. * Get the total number of bytes that were actually downloaded.
  106. *
  107. * @return {number}
  108. */
  109. getTotalDownloaded() {
  110. return this.actualDownloaded_;
  111. }
  112. };