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 {number} */
  51. this.bytesDownloaded_ = NaN;
  52. /** @private {!shaka.util.StateHistory} */
  53. this.stateHistory_ = new shaka.util.StateHistory();
  54. /** @private {!shaka.util.SwitchHistory} */
  55. this.switchHistory_ = new shaka.util.SwitchHistory();
  56. }
  57. /**
  58. * Update the ratio of dropped frames to total frames. This will replace the
  59. * previous values.
  60. *
  61. * @param {number} dropped
  62. * @param {number} decoded
  63. */
  64. setDroppedFrames(dropped, decoded) {
  65. this.totalDroppedFrames_ = dropped;
  66. this.totalDecodedFrames_ = decoded;
  67. }
  68. /**
  69. * Update corrupted frames. This will replace the previous values.
  70. *
  71. * @param {number} corrupted
  72. */
  73. setCorruptedFrames(corrupted) {
  74. this.totalCorruptedFrames_ = corrupted;
  75. }
  76. /**
  77. * Update number of stalls detected. This will replace the previous value.
  78. *
  79. * @param {number} stallsDetected
  80. */
  81. setStallsDetected(stallsDetected) {
  82. this.totalStallsDetected_ = stallsDetected;
  83. }
  84. /**
  85. * Update number of playback gaps jumped over. This will replace the previous
  86. * value.
  87. *
  88. * @param {number} gapsJumped
  89. */
  90. setGapsJumped(gapsJumped) {
  91. this.totalGapsJumped_ = gapsJumped;
  92. }
  93. /**
  94. * Set the width and height of the video we are currently playing.
  95. *
  96. * @param {number} width
  97. * @param {number} height
  98. */
  99. setResolution(width, height) {
  100. this.width_ = width;
  101. this.height_ = height;
  102. }
  103. /**
  104. * Record the time it took between the user signalling "I want to play this"
  105. * to "I am now seeing this".
  106. *
  107. * @param {number} seconds
  108. */
  109. setLoadLatency(seconds) {
  110. this.loadLatencySeconds_ = seconds;
  111. }
  112. /**
  113. * Record the time it took to download and parse the manifest.
  114. *
  115. * @param {number} seconds
  116. */
  117. setManifestTime(seconds) {
  118. this.manifestTimeSeconds_ = seconds;
  119. }
  120. /**
  121. * Record the current completion percent. This is the "high water mark", so it
  122. * will store the highest provided completion percent.
  123. *
  124. * @param {number} percent
  125. */
  126. setCompletionPercent(percent) {
  127. if (isNaN(this.completionPercent_)) {
  128. this.completionPercent_ = percent;
  129. } else {
  130. this.completionPercent_ = Math.max(this.completionPercent_, percent);
  131. }
  132. }
  133. /**
  134. * Record the time it took to download the first drm key.
  135. *
  136. * @param {number} seconds
  137. */
  138. setDrmTime(seconds) {
  139. this.drmTimeSeconds_ = seconds;
  140. }
  141. /**
  142. * Record the cumulative time spent on license requests during this session.
  143. *
  144. * @param {number} seconds
  145. */
  146. setLicenseTime(seconds) {
  147. this.licenseTimeSeconds_ = seconds;
  148. }
  149. /**
  150. * Record the latency in live streams.
  151. *
  152. * @param {number} seconds
  153. */
  154. setLiveLatency(seconds) {
  155. this.liveLatencySeconds_ = seconds;
  156. }
  157. /**
  158. * Record the presentation's max segment duration.
  159. *
  160. * @param {number} seconds
  161. */
  162. setMaxSegmentDuration(seconds) {
  163. this.maxSegmentDurationSeconds_ = seconds;
  164. }
  165. /**
  166. * @param {number} bandwidth
  167. */
  168. setCurrentStreamBandwidth(bandwidth) {
  169. this.currentStreamBandwidth_ = bandwidth;
  170. }
  171. /**
  172. * @param {number} bandwidth
  173. */
  174. setBandwidthEstimate(bandwidth) {
  175. this.bandwidthEstimate_ = bandwidth;
  176. }
  177. /**
  178. * @param {number} bytesDownloaded
  179. */
  180. addBytesDownloaded(bytesDownloaded) {
  181. if (isNaN(this.bytesDownloaded_)) {
  182. this.bytesDownloaded_ = bytesDownloaded;
  183. } else {
  184. this.bytesDownloaded_ += bytesDownloaded;
  185. }
  186. }
  187. /**
  188. * @return {!shaka.util.StateHistory}
  189. */
  190. getStateHistory() {
  191. return this.stateHistory_;
  192. }
  193. /**
  194. * @return {!shaka.util.SwitchHistory}
  195. */
  196. getSwitchHistory() {
  197. return this.switchHistory_;
  198. }
  199. /**
  200. * Create a stats blob that we can pass up to the app. This blob will not
  201. * reference any internal data.
  202. *
  203. * @return {shaka.extern.Stats}
  204. */
  205. getBlob() {
  206. return {
  207. width: this.width_,
  208. height: this.height_,
  209. streamBandwidth: this.currentStreamBandwidth_,
  210. decodedFrames: this.totalDecodedFrames_,
  211. droppedFrames: this.totalDroppedFrames_,
  212. corruptedFrames: this.totalCorruptedFrames_,
  213. stallsDetected: this.totalStallsDetected_,
  214. gapsJumped: this.totalGapsJumped_,
  215. estimatedBandwidth: this.bandwidthEstimate_,
  216. completionPercent: this.completionPercent_,
  217. loadLatency: this.loadLatencySeconds_,
  218. manifestTimeSeconds: this.manifestTimeSeconds_,
  219. drmTimeSeconds: this.drmTimeSeconds_,
  220. playTime: this.stateHistory_.getTimeSpentIn('playing'),
  221. pauseTime: this.stateHistory_.getTimeSpentIn('paused'),
  222. bufferingTime: this.stateHistory_.getTimeSpentIn('buffering'),
  223. licenseTime: this.licenseTimeSeconds_,
  224. liveLatency: this.liveLatencySeconds_,
  225. maxSegmentDuration: this.maxSegmentDurationSeconds_,
  226. bytesDownloaded: this.bytesDownloaded_,
  227. stateHistory: this.stateHistory_.getCopy(),
  228. switchHistory: this.switchHistory_.getCopy(),
  229. };
  230. }
  231. /**
  232. * Create an empty stats blob. This resembles the stats when we are not
  233. * playing any content.
  234. *
  235. * @return {shaka.extern.Stats}
  236. */
  237. static getEmptyBlob() {
  238. return {
  239. width: NaN,
  240. height: NaN,
  241. streamBandwidth: NaN,
  242. decodedFrames: NaN,
  243. droppedFrames: NaN,
  244. corruptedFrames: NaN,
  245. stallsDetected: NaN,
  246. gapsJumped: NaN,
  247. estimatedBandwidth: NaN,
  248. completionPercent: NaN,
  249. loadLatency: NaN,
  250. manifestTimeSeconds: NaN,
  251. drmTimeSeconds: NaN,
  252. playTime: NaN,
  253. pauseTime: NaN,
  254. bufferingTime: NaN,
  255. licenseTime: NaN,
  256. liveLatency: NaN,
  257. maxSegmentDuration: NaN,
  258. bytesDownloaded: NaN,
  259. switchHistory: [],
  260. stateHistory: [],
  261. };
  262. }
  263. };