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