Source: lib/util/stats.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.util.Stats');
  7. goog.require('shaka.util.StateHistory');
  8. goog.require('shaka.util.SwitchHistory');
  9. /**
  10. * This class tracks all the various components (some optional) that are used to
  11. * populate |shaka.extern.Stats| which is passed to the app.
  12. *
  13. * @final
  14. */
  15. shaka.util.Stats = class {
  16. /** */
  17. constructor() {
  18. /** @private {number} */
  19. this.width_ = NaN;
  20. /** @private {number} */
  21. this.height_ = NaN;
  22. /** @private {number} */
  23. this.totalDroppedFrames_ = NaN;
  24. /** @private {number} */
  25. this.totalDecodedFrames_ = NaN;
  26. /** @private {number} */
  27. this.totalCorruptedFrames_ = NaN;
  28. /** @private {number} */
  29. this.totalStallsDetected_ = NaN;
  30. /** @private {number} */
  31. this.totalGapsJumped_ = NaN;
  32. /** @private {number} */
  33. this.completionPercent_ = NaN;
  34. /** @private {number} */
  35. this.loadLatencySeconds_ = NaN;
  36. /** @private {number} */
  37. this.manifestTimeSeconds_ = NaN;
  38. /** @private {number} */
  39. this.drmTimeSeconds_ = NaN;
  40. /** @private {number} */
  41. this.licenseTimeSeconds_ = NaN;
  42. /** @private {number} */
  43. this.liveLatencySeconds_ = NaN;
  44. /** @private {number} */
  45. this.maxSegmentDurationSeconds_ = NaN;
  46. /** @private {number} */
  47. this.currentStreamBandwidth_ = NaN;
  48. /** @private {number} */
  49. this.bandwidthEstimate_ = NaN;
  50. /** @private {!shaka.util.StateHistory} */
  51. this.stateHistory_ = new shaka.util.StateHistory();
  52. /** @private {!shaka.util.SwitchHistory} */
  53. this.switchHistory_ = new shaka.util.SwitchHistory();
  54. }
  55. /**
  56. * Update the ratio of dropped frames to total frames. This will replace the
  57. * previous values.
  58. *
  59. * @param {number} dropped
  60. * @param {number} decoded
  61. */
  62. setDroppedFrames(dropped, decoded) {
  63. this.totalDroppedFrames_ = dropped;
  64. this.totalDecodedFrames_ = decoded;
  65. }
  66. /**
  67. * Update corrupted frames. This will replace the previous values.
  68. *
  69. * @param {number} corrupted
  70. */
  71. setCorruptedFrames(corrupted) {
  72. this.totalCorruptedFrames_ = corrupted;
  73. }
  74. /**
  75. * Update number of stalls detected. This will replace the previous value.
  76. *
  77. * @param {number} stallsDetected
  78. */
  79. setStallsDetected(stallsDetected) {
  80. this.totalStallsDetected_ = stallsDetected;
  81. }
  82. /**
  83. * Update number of playback gaps jumped over. This will replace the previous
  84. * value.
  85. *
  86. * @param {number} gapsJumped
  87. */
  88. setGapsJumped(gapsJumped) {
  89. this.totalGapsJumped_ = gapsJumped;
  90. }
  91. /**
  92. * Set the width and height of the video we are currently playing.
  93. *
  94. * @param {number} width
  95. * @param {number} height
  96. */
  97. setResolution(width, height) {
  98. this.width_ = width;
  99. this.height_ = height;
  100. }
  101. /**
  102. * Record the time it took between the user signalling "I want to play this"
  103. * to "I am now seeing this".
  104. *
  105. * @param {number} seconds
  106. */
  107. setLoadLatency(seconds) {
  108. this.loadLatencySeconds_ = seconds;
  109. }
  110. /**
  111. * Record the time it took to download and parse the manifest.
  112. *
  113. * @param {number} seconds
  114. */
  115. setManifestTime(seconds) {
  116. this.manifestTimeSeconds_ = seconds;
  117. }
  118. /**
  119. * Record the current completion percent. This is the "high water mark", so it
  120. * will store the highest provided completion percent.
  121. *
  122. * @param {number} percent
  123. */
  124. setCompletionPercent(percent) {
  125. if (isNaN(this.completionPercent_)) {
  126. this.completionPercent_ = percent;
  127. } else {
  128. this.completionPercent_ = Math.max(this.completionPercent_, percent);
  129. }
  130. }
  131. /**
  132. * Record the time it took to download the first drm key.
  133. *
  134. * @param {number} seconds
  135. */
  136. setDrmTime(seconds) {
  137. this.drmTimeSeconds_ = seconds;
  138. }
  139. /**
  140. * Record the cumulative time spent on license requests during this session.
  141. *
  142. * @param {number} seconds
  143. */
  144. setLicenseTime(seconds) {
  145. this.licenseTimeSeconds_ = seconds;
  146. }
  147. /**
  148. * Record the latency in live streams.
  149. *
  150. * @param {number} seconds
  151. */
  152. setLiveLatency(seconds) {
  153. this.liveLatencySeconds_ = seconds;
  154. }
  155. /**
  156. * Record the presentation's max segment duration.
  157. *
  158. * @param {number} seconds
  159. */
  160. setMaxSegmentDuration(seconds) {
  161. this.maxSegmentDurationSeconds_ = seconds;
  162. }
  163. /**
  164. * @param {number} bandwidth
  165. */
  166. setCurrentStreamBandwidth(bandwidth) {
  167. this.currentStreamBandwidth_ = bandwidth;
  168. }
  169. /**
  170. * @param {number} bandwidth
  171. */
  172. setBandwidthEstimate(bandwidth) {
  173. this.bandwidthEstimate_ = bandwidth;
  174. }
  175. /**
  176. * @return {!shaka.util.StateHistory}
  177. */
  178. getStateHistory() {
  179. return this.stateHistory_;
  180. }
  181. /**
  182. * @return {!shaka.util.SwitchHistory}
  183. */
  184. getSwitchHistory() {
  185. return this.switchHistory_;
  186. }
  187. /**
  188. * Create a stats blob that we can pass up to the app. This blob will not
  189. * reference any internal data.
  190. *
  191. * @return {shaka.extern.Stats}
  192. */
  193. getBlob() {
  194. return {
  195. width: this.width_,
  196. height: this.height_,
  197. streamBandwidth: this.currentStreamBandwidth_,
  198. decodedFrames: this.totalDecodedFrames_,
  199. droppedFrames: this.totalDroppedFrames_,
  200. corruptedFrames: this.totalCorruptedFrames_,
  201. stallsDetected: this.totalStallsDetected_,
  202. gapsJumped: this.totalGapsJumped_,
  203. estimatedBandwidth: this.bandwidthEstimate_,
  204. completionPercent: this.completionPercent_,
  205. loadLatency: this.loadLatencySeconds_,
  206. manifestTimeSeconds: this.manifestTimeSeconds_,
  207. drmTimeSeconds: this.drmTimeSeconds_,
  208. playTime: this.stateHistory_.getTimeSpentIn('playing'),
  209. pauseTime: this.stateHistory_.getTimeSpentIn('paused'),
  210. bufferingTime: this.stateHistory_.getTimeSpentIn('buffering'),
  211. licenseTime: this.licenseTimeSeconds_,
  212. liveLatency: this.liveLatencySeconds_,
  213. maxSegmentDuration: this.maxSegmentDurationSeconds_,
  214. stateHistory: this.stateHistory_.getCopy(),
  215. switchHistory: this.switchHistory_.getCopy(),
  216. };
  217. }
  218. /**
  219. * Create an empty stats blob. This resembles the stats when we are not
  220. * playing any content.
  221. *
  222. * @return {shaka.extern.Stats}
  223. */
  224. static getEmptyBlob() {
  225. return {
  226. width: NaN,
  227. height: NaN,
  228. streamBandwidth: NaN,
  229. decodedFrames: NaN,
  230. droppedFrames: NaN,
  231. corruptedFrames: NaN,
  232. stallsDetected: NaN,
  233. gapsJumped: NaN,
  234. estimatedBandwidth: NaN,
  235. completionPercent: NaN,
  236. loadLatency: NaN,
  237. manifestTimeSeconds: NaN,
  238. drmTimeSeconds: NaN,
  239. playTime: NaN,
  240. pauseTime: NaN,
  241. bufferingTime: NaN,
  242. licenseTime: NaN,
  243. liveLatency: NaN,
  244. maxSegmentDuration: NaN,
  245. switchHistory: [],
  246. stateHistory: [],
  247. };
  248. }
  249. };