Source: lib/media/buffering_observer.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.media.BufferingObserver');
  7. /**
  8. * The buffering observer watches how much content has been buffered and raises
  9. * events when the state changes (enough => not enough or vice versa).
  10. *
  11. * @final
  12. */
  13. shaka.media.BufferingObserver = class {
  14. /**
  15. * @param {number} thresholdWhenStarving
  16. * @param {number} thresholdWhenSatisfied
  17. */
  18. constructor(thresholdWhenStarving, thresholdWhenSatisfied) {
  19. const State = shaka.media.BufferingObserver.State;
  20. /** @private {shaka.media.BufferingObserver.State} */
  21. this.previousState_ = State.SATISFIED;
  22. /** @private {!Map.<shaka.media.BufferingObserver.State, number>} */
  23. this.thresholds_ = new Map()
  24. .set(State.SATISFIED, thresholdWhenSatisfied)
  25. .set(State.STARVING, thresholdWhenStarving);
  26. }
  27. /**
  28. * @param {number} thresholdWhenStarving
  29. * @param {number} thresholdWhenSatisfied
  30. */
  31. setThresholds(thresholdWhenStarving, thresholdWhenSatisfied) {
  32. const State = shaka.media.BufferingObserver.State;
  33. this.thresholds_
  34. .set(State.SATISFIED, thresholdWhenSatisfied)
  35. .set(State.STARVING, thresholdWhenStarving);
  36. }
  37. /**
  38. * Update the observer by telling it how much content has been buffered (in
  39. * seconds) and if we are buffered to the end of the presentation. If the
  40. * controller believes the state has changed, it will return |true|.
  41. *
  42. * @param {number} bufferLead
  43. * @param {boolean} bufferedToEnd
  44. * @return {boolean}
  45. */
  46. update(bufferLead, bufferedToEnd) {
  47. const State = shaka.media.BufferingObserver.State;
  48. /**
  49. * Our threshold for how much we need before we declare ourselves as
  50. * starving is based on whether or not we were just starving. If we
  51. * were just starving, we are more likely to starve again, so we require
  52. * more content to be buffered than if we were not just starving.
  53. *
  54. * @type {number}
  55. */
  56. const threshold = this.thresholds_.get(this.previousState_);
  57. const oldState = this.previousState_;
  58. const newState = (bufferedToEnd || bufferLead >= threshold) ?
  59. (State.SATISFIED) :
  60. (State.STARVING);
  61. // Save the new state now so that calls to |getState| from any callbacks
  62. // will be accurate.
  63. this.previousState_ = newState;
  64. // Return |true| only when the state has changed.
  65. return oldState != newState;
  66. }
  67. /**
  68. * Set which state that the observer should think playback was in.
  69. *
  70. * @param {shaka.media.BufferingObserver.State} state
  71. */
  72. setState(state) {
  73. this.previousState_ = state;
  74. }
  75. /**
  76. * Get the state that the observer last thought playback was in.
  77. *
  78. * @return {shaka.media.BufferingObserver.State}
  79. */
  80. getState() {
  81. return this.previousState_;
  82. }
  83. };
  84. /**
  85. * Rather than using booleans to communicate what state we are in, we have this
  86. * enum.
  87. *
  88. * @enum {number}
  89. */
  90. shaka.media.BufferingObserver.State = {
  91. STARVING: 0,
  92. SATISFIED: 1,
  93. };