rx-player 3.30.0-dev.2023020100 → 3.30.0-dev.2023022200

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/CHANGELOG.md +2 -1
  2. package/VERSION +1 -1
  3. package/dist/_esm5.processed/compat/eme/close_session.js +2 -2
  4. package/dist/_esm5.processed/compat/event_listeners.js +1 -1
  5. package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +4 -2
  6. package/dist/_esm5.processed/core/api/debug/buffer_graph.d.ts +28 -0
  7. package/dist/_esm5.processed/core/api/debug/buffer_graph.js +175 -0
  8. package/dist/_esm5.processed/core/api/debug/buffer_size_graph.d.ts +10 -0
  9. package/dist/_esm5.processed/core/api/debug/buffer_size_graph.js +105 -0
  10. package/dist/_esm5.processed/core/api/debug/constants.d.ts +2 -0
  11. package/dist/_esm5.processed/core/api/debug/constants.js +2 -0
  12. package/dist/_esm5.processed/core/api/debug/index.d.ts +2 -0
  13. package/dist/_esm5.processed/core/api/debug/index.js +2 -0
  14. package/dist/_esm5.processed/core/api/debug/modules/general_info.d.ts +3 -0
  15. package/dist/_esm5.processed/core/api/debug/modules/general_info.js +199 -0
  16. package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_content.d.ts +4 -0
  17. package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_content.js +121 -0
  18. package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_size.d.ts +3 -0
  19. package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_size.js +35 -0
  20. package/dist/_esm5.processed/core/api/debug/render.d.ts +3 -0
  21. package/dist/_esm5.processed/core/api/debug/render.js +32 -0
  22. package/dist/_esm5.processed/core/api/debug/utils.d.ts +39 -0
  23. package/dist/_esm5.processed/core/api/debug/utils.js +57 -0
  24. package/dist/_esm5.processed/core/api/playback_observer.js +3 -2
  25. package/dist/_esm5.processed/core/api/public_api.d.ts +3 -0
  26. package/dist/_esm5.processed/core/api/public_api.js +24 -13
  27. package/dist/_esm5.processed/core/api/utils.js +3 -3
  28. package/dist/_esm5.processed/core/decrypt/__tests__/__global__/utils.d.ts +5 -5
  29. package/dist/_esm5.processed/core/decrypt/attach_media_keys.js +1 -1
  30. package/dist/_esm5.processed/core/decrypt/content_decryptor.js +1 -1
  31. package/dist/_esm5.processed/core/decrypt/session_events_listener.js +37 -47
  32. package/dist/_esm5.processed/core/decrypt/utils/check_key_statuses.js +4 -0
  33. package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.d.ts +17 -8
  34. package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.js +10 -6
  35. package/dist/_esm5.processed/core/fetchers/manifest/manifest_fetcher.js +5 -4
  36. package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.d.ts +22 -5
  37. package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.js +37 -21
  38. package/dist/_esm5.processed/core/fetchers/segment/task_prioritizer.js +21 -23
  39. package/dist/_esm5.processed/core/fetchers/utils/schedule_request.js +6 -5
  40. package/dist/_esm5.processed/core/init/directfile_content_initializer.js +1 -1
  41. package/dist/_esm5.processed/core/init/media_source_content_initializer.js +27 -31
  42. package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.js +2 -2
  43. package/dist/_esm5.processed/core/init/utils/create_media_source.js +3 -12
  44. package/dist/_esm5.processed/core/init/utils/end_of_stream.js +6 -3
  45. package/dist/_esm5.processed/core/init/utils/get_loaded_reference.js +2 -1
  46. package/dist/_esm5.processed/core/init/utils/initial_seek_and_play.js +9 -5
  47. package/dist/_esm5.processed/core/init/utils/initialize_content_decryption.js +2 -1
  48. package/dist/_esm5.processed/core/init/utils/media_duration_updater.js +23 -19
  49. package/dist/_esm5.processed/core/init/utils/stream_events_emitter/stream_events_emitter.js +6 -4
  50. package/dist/_esm5.processed/core/init/utils/throw_on_media_error.js +1 -1
  51. package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +7 -10
  52. package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +4 -2
  53. package/dist/_esm5.processed/core/segment_buffers/segment_buffers_store.js +13 -9
  54. package/dist/_esm5.processed/core/stream/adaptation/adaptation_stream.js +10 -11
  55. package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +26 -12
  56. package/dist/_esm5.processed/core/stream/period/period_stream.js +11 -10
  57. package/dist/_esm5.processed/core/stream/representation/representation_stream.js +15 -15
  58. package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.js +1 -1
  59. package/dist/_esm5.processed/core/stream/representation/utils/downloading_queue.js +16 -6
  60. package/dist/_esm5.processed/experimental/features/debug_element.d.ts +8 -0
  61. package/dist/_esm5.processed/experimental/features/debug_element.js +10 -0
  62. package/dist/_esm5.processed/experimental/features/index.d.ts +1 -0
  63. package/dist/_esm5.processed/experimental/features/index.js +1 -0
  64. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.js +7 -4
  65. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +5 -4
  66. package/dist/_esm5.processed/features/features_object.js +1 -0
  67. package/dist/_esm5.processed/features/initialize_features.js +13 -10
  68. package/dist/_esm5.processed/features/types.d.ts +3 -0
  69. package/dist/_esm5.processed/manifest/adaptation.js +4 -0
  70. package/dist/_esm5.processed/manifest/manifest.js +2 -0
  71. package/dist/_esm5.processed/manifest/representation.js +11 -4
  72. package/dist/_esm5.processed/parsers/manifest/dash/common/parse_adaptation_sets.js +105 -137
  73. package/dist/_esm5.processed/parsers/manifest/dash/common/parse_representations.js +25 -5
  74. package/dist/_esm5.processed/public_types.d.ts +1 -0
  75. package/dist/_esm5.processed/transports/dash/add_segment_integrity_checks_to_loader.js +13 -12
  76. package/dist/_esm5.processed/transports/dash/low_latency_segment_loader.js +2 -2
  77. package/dist/_esm5.processed/transports/dash/manifest_parser.js +1 -1
  78. package/dist/_esm5.processed/transports/dash/segment_loader.js +4 -4
  79. package/dist/_esm5.processed/transports/local/segment_loader.js +13 -26
  80. package/dist/_esm5.processed/transports/smooth/segment_loader.js +4 -4
  81. package/dist/_esm5.processed/transports/utils/call_custom_manifest_loader.js +3 -3
  82. package/dist/_esm5.processed/utils/cancellable_sleep.js +4 -10
  83. package/dist/_esm5.processed/utils/create_cancellable_promise.d.ts +26 -0
  84. package/dist/_esm5.processed/utils/create_cancellable_promise.js +52 -0
  85. package/dist/_esm5.processed/utils/reference.js +6 -0
  86. package/dist/_esm5.processed/utils/request/xhr.js +1 -1
  87. package/dist/_esm5.processed/utils/task_canceller.d.ts +34 -15
  88. package/dist/_esm5.processed/utils/task_canceller.js +55 -22
  89. package/dist/rx-player.js +739 -626
  90. package/dist/rx-player.min.js +1 -1
  91. package/jest.config.js +1 -0
  92. package/package.json +18 -18
  93. package/scripts/build/constants.d.ts +1 -0
  94. package/scripts/report_build_sizes +4 -0
  95. package/sonar-project.properties +1 -1
  96. package/src/compat/eme/close_session.ts +2 -2
  97. package/src/compat/event_listeners.ts +1 -1
  98. package/src/core/adaptive/adaptive_representation_selector.ts +4 -2
  99. package/src/core/api/debug/buffer_graph.ts +247 -0
  100. package/src/core/api/debug/buffer_size_graph.ts +131 -0
  101. package/src/core/api/debug/constants.ts +2 -0
  102. package/src/core/api/debug/index.ts +3 -0
  103. package/src/core/api/debug/modules/general_info.ts +204 -0
  104. package/src/core/api/debug/modules/segment_buffer_content.ts +155 -0
  105. package/src/core/api/debug/modules/segment_buffer_size.ts +48 -0
  106. package/src/core/api/debug/render.ts +40 -0
  107. package/src/core/api/debug/utils.ts +103 -0
  108. package/src/core/api/playback_observer.ts +4 -2
  109. package/src/core/api/public_api.ts +27 -13
  110. package/src/core/api/utils.ts +3 -3
  111. package/src/core/decrypt/attach_media_keys.ts +1 -1
  112. package/src/core/decrypt/content_decryptor.ts +1 -1
  113. package/src/core/decrypt/session_events_listener.ts +37 -49
  114. package/src/core/decrypt/utils/check_key_statuses.ts +6 -0
  115. package/src/core/fetchers/cdn_prioritizer.ts +18 -9
  116. package/src/core/fetchers/manifest/manifest_fetcher.ts +5 -4
  117. package/src/core/fetchers/segment/segment_fetcher.ts +36 -14
  118. package/src/core/fetchers/segment/task_prioritizer.ts +25 -30
  119. package/src/core/fetchers/utils/schedule_request.ts +6 -5
  120. package/src/core/init/directfile_content_initializer.ts +1 -1
  121. package/src/core/init/media_source_content_initializer.ts +37 -41
  122. package/src/core/init/utils/content_time_boundaries_observer.ts +2 -2
  123. package/src/core/init/utils/create_media_source.ts +4 -16
  124. package/src/core/init/utils/end_of_stream.ts +6 -3
  125. package/src/core/init/utils/get_loaded_reference.ts +2 -1
  126. package/src/core/init/utils/initial_seek_and_play.ts +9 -5
  127. package/src/core/init/utils/initialize_content_decryption.ts +2 -1
  128. package/src/core/init/utils/media_duration_updater.ts +25 -20
  129. package/src/core/init/utils/stream_events_emitter/stream_events_emitter.ts +6 -4
  130. package/src/core/init/utils/throw_on_media_error.ts +1 -1
  131. package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +7 -11
  132. package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +4 -2
  133. package/src/core/segment_buffers/segment_buffers_store.ts +16 -13
  134. package/src/core/stream/adaptation/adaptation_stream.ts +10 -11
  135. package/src/core/stream/orchestrator/stream_orchestrator.ts +26 -12
  136. package/src/core/stream/period/period_stream.ts +11 -10
  137. package/src/core/stream/representation/representation_stream.ts +15 -15
  138. package/src/core/stream/representation/utils/append_segment_to_buffer.ts +1 -1
  139. package/src/core/stream/representation/utils/downloading_queue.ts +16 -4
  140. package/src/experimental/features/__tests__/debug_element.test.ts +26 -0
  141. package/src/experimental/features/debug_element.ts +13 -0
  142. package/src/experimental/features/index.ts +1 -0
  143. package/src/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.ts +7 -4
  144. package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +5 -4
  145. package/src/features/__tests__/initialize_features.test.ts +11 -0
  146. package/src/features/features_object.ts +1 -0
  147. package/src/features/initialize_features.ts +15 -10
  148. package/src/features/types.ts +9 -0
  149. package/src/manifest/adaptation.ts +7 -0
  150. package/src/manifest/manifest.ts +4 -0
  151. package/src/manifest/representation.ts +10 -4
  152. package/src/parsers/manifest/dash/common/parse_adaptation_sets.ts +116 -151
  153. package/src/parsers/manifest/dash/common/parse_representations.ts +21 -4
  154. package/src/public_types.ts +1 -0
  155. package/src/transports/dash/add_segment_integrity_checks_to_loader.ts +30 -24
  156. package/src/transports/dash/low_latency_segment_loader.ts +2 -2
  157. package/src/transports/dash/manifest_parser.ts +1 -1
  158. package/src/transports/dash/segment_loader.ts +4 -4
  159. package/src/transports/local/segment_loader.ts +14 -30
  160. package/src/transports/smooth/segment_loader.ts +4 -4
  161. package/src/transports/utils/call_custom_manifest_loader.ts +3 -3
  162. package/src/typings/globals.d.ts +2 -0
  163. package/src/utils/cancellable_sleep.ts +5 -14
  164. package/src/utils/create_cancellable_promise.ts +69 -0
  165. package/src/utils/reference.ts +6 -0
  166. package/src/utils/request/xhr.ts +1 -1
  167. package/src/utils/task_canceller.ts +63 -34
package/jest.config.js CHANGED
@@ -54,6 +54,7 @@ module.exports = {
54
54
  HTML_VTT: 1,
55
55
  LOCAL_MANIFEST: 1,
56
56
  METAPLAYLIST: 1,
57
+ DEBUG_ELEMENT: 1,
57
58
  NATIVE_SAMI: 1,
58
59
  NATIVE_SRT: 1,
59
60
  NATIVE_TTML: 1,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rx-player",
3
3
  "author": "Canal+",
4
- "version": "3.30.0-dev.2023020100",
4
+ "version": "3.30.0-dev.2023022200",
5
5
  "description": "Canal+ HTML5 Video Player",
6
6
  "main": "./dist/rx-player.js",
7
7
  "keywords": [
@@ -78,34 +78,34 @@
78
78
  "next-tick": "1.1.0"
79
79
  },
80
80
  "devDependencies": {
81
- "@babel/core": "7.20.12",
82
- "@babel/plugin-transform-runtime": "7.19.6",
81
+ "@babel/core": "7.21.0",
82
+ "@babel/plugin-transform-runtime": "7.21.0",
83
83
  "@babel/preset-env": "7.20.2",
84
84
  "@babel/preset-react": "7.18.6",
85
85
  "@types/chai": "4.3.4",
86
- "@types/jest": "29.2.5",
86
+ "@types/jest": "29.4.0",
87
87
  "@types/mocha": "10.0.1",
88
- "@types/node": "18.11.18",
88
+ "@types/node": "18.14.0",
89
89
  "@types/sinon": "10.0.13",
90
- "@typescript-eslint/eslint-plugin": "5.48.2",
91
- "@typescript-eslint/eslint-plugin-tslint": "5.48.2",
92
- "@typescript-eslint/parser": "5.48.2",
90
+ "@typescript-eslint/eslint-plugin": "5.53.0",
91
+ "@typescript-eslint/eslint-plugin-tslint": "5.53.0",
92
+ "@typescript-eslint/parser": "5.53.0",
93
93
  "arraybuffer-loader": "1.0.8",
94
94
  "babel-loader": "9.1.2",
95
95
  "chai": "4.3.7",
96
96
  "cheerio": "1.0.0-rc.12",
97
- "core-js": "3.27.1",
98
- "esbuild": "0.17.2",
99
- "eslint": "8.32.0",
97
+ "core-js": "3.28.0",
98
+ "esbuild": "0.17.10",
99
+ "eslint": "8.34.0",
100
100
  "eslint-plugin-import": "2.27.5",
101
- "eslint-plugin-jsdoc": "39.6.4",
102
- "eslint-plugin-react": "7.32.1",
101
+ "eslint-plugin-jsdoc": "40.0.0",
102
+ "eslint-plugin-react": "7.32.2",
103
103
  "esm": "3.2.25",
104
104
  "express": "4.18.2",
105
105
  "highlight.js": "11.7.0",
106
106
  "html-entities": "2.3.3",
107
- "jest": "29.3.1",
108
- "jest-environment-jsdom": "29.3.1",
107
+ "jest": "29.4.3",
108
+ "jest-environment-jsdom": "29.4.3",
109
109
  "karma": "6.4.1",
110
110
  "karma-chrome-launcher": "3.1.1",
111
111
  "karma-firefox-launcher": "2.1.2",
@@ -118,16 +118,16 @@
118
118
  "react": "18.2.0",
119
119
  "react-dom": "18.2.0",
120
120
  "regenerator-runtime": "0.13.11",
121
- "rimraf": "4.1.1",
121
+ "rimraf": "4.1.2",
122
122
  "semver": "7.3.8",
123
123
  "sinon": "15.0.1",
124
124
  "terser-webpack-plugin": "5.3.6",
125
125
  "ts-jest": "29.0.5",
126
126
  "ts-loader": "9.4.2",
127
127
  "tslint": "6.1.3",
128
- "typescript": "4.9.4",
128
+ "typescript": "4.9.5",
129
129
  "webpack": "5.75.0",
130
- "webpack-bundle-analyzer": "4.7.0",
130
+ "webpack-bundle-analyzer": "4.8.0",
131
131
  "webpack-cli": "5.0.1"
132
132
  },
133
133
  "scripts-list": {
@@ -42,6 +42,7 @@ declare const enum __FEATURES__ {
42
42
  HTML_VTT = IS_DISABLED,
43
43
  LOCAL_MANIFEST = IS_DISABLED,
44
44
  METAPLAYLIST = IS_DISABLED,
45
+ DEBUG_ELEMENT = IS_DISABLED,
45
46
  NATIVE_SAMI = IS_DISABLED,
46
47
  NATIVE_SRT = IS_DISABLED,
47
48
  NATIVE_TTML = IS_DISABLED,
@@ -87,6 +87,10 @@ RXP_METAPLAYLIST=true npm run build:min
87
87
  echo -n "with METAPLAYLIST: " >> sizes
88
88
  stat -c %s dist/rx-player.min.js >> sizes
89
89
 
90
+ RXP_DEBUG_ELEMENT=true npm run build:min
91
+ echo -n "with DEBUG_ELEMENT: " >> sizes
92
+ stat -c %s dist/rx-player.min.js >> sizes
93
+
90
94
  RXP_LOCAL_MANIFEST=true npm run build:min
91
95
  echo -n "with LOCAL_MANIFEST: " >> sizes
92
96
  stat -c %s dist/rx-player.min.js >> sizes
@@ -1,7 +1,7 @@
1
1
  sonar.projectKey=rx-player
2
2
  sonar.organization=rx-player
3
3
  sonar.projectName=rx-player
4
- sonar.projectVersion=3.30.0-dev.2023020100
4
+ sonar.projectVersion=3.30.0-dev.2023022200
5
5
  sonar.sources=./src,./demo,./tests
6
6
  sonar.exclusions=demo/full/bundle.js,demo/standalone/lib.js,demo/bundle.js
7
7
  sonar.host.url=https://sonarcloud.io
@@ -86,7 +86,7 @@ export default function closeSession(
86
86
  try {
87
87
  await session.update(new Uint8Array(1));
88
88
  } catch (err) {
89
- if (timeoutCanceller.isUsed) { // Reminder: cancelled == session closed
89
+ if (timeoutCanceller.isUsed()) { // Reminder: cancelled == session closed
90
90
  return;
91
91
  }
92
92
 
@@ -102,7 +102,7 @@ export default function closeSession(
102
102
  await cancellableSleep(1000, timeoutCanceller.signal);
103
103
  }
104
104
 
105
- if (timeoutCanceller.isUsed) { // Reminder: cancelled == session closed
105
+ if (timeoutCanceller.isUsed()) { // Reminder: cancelled == session closed
106
106
  return;
107
107
  }
108
108
 
@@ -125,7 +125,7 @@ function createCompatibleEventListener(
125
125
  listener: (event? : unknown) => void,
126
126
  cancelSignal: CancellationSignal
127
127
  ) => {
128
- if (cancelSignal.isCancelled) {
128
+ if (cancelSignal.isCancelled()) {
129
129
  return;
130
130
  }
131
131
 
@@ -215,7 +215,8 @@ function getEstimateReference(
215
215
  * This TaskCanceller is used both for restarting estimates with a new
216
216
  * configuration and to cancel them altogether.
217
217
  */
218
- let currentEstimatesCanceller = new TaskCanceller({ cancelOn: stopAllEstimates });
218
+ let currentEstimatesCanceller = new TaskCanceller();
219
+ currentEstimatesCanceller.linkToSignal(stopAllEstimates);
219
220
 
220
221
  // Create `ISharedReference` on which estimates will be emitted.
221
222
  const estimateRef = createEstimateReference(manualBitrate.getValue(),
@@ -491,7 +492,8 @@ function getEstimateReference(
491
492
  const manualBitrateVal = manualBitrate.getValue();
492
493
  const representations = representationsRef.getValue();
493
494
  currentEstimatesCanceller.cancel();
494
- currentEstimatesCanceller = new TaskCanceller({ cancelOn: stopAllEstimates });
495
+ currentEstimatesCanceller = new TaskCanceller();
496
+ currentEstimatesCanceller.linkToSignal(stopAllEstimates);
495
497
  const newRef = createEstimateReference(
496
498
  manualBitrateVal,
497
499
  representations,
@@ -0,0 +1,247 @@
1
+ import { Representation } from "../../../manifest";
2
+ import { IBufferedChunk } from "../../segment_buffers";
3
+
4
+ const BUFFER_WIDTH_IN_SECONDS = 10000;
5
+
6
+ const COLORS = [
7
+ "#2ab7ca",
8
+ "#fed766",
9
+ "#4dd248",
10
+ "#a22c28",
11
+ "#556b2f", // darkolivegreen
12
+ "#add8e6", // lightblue
13
+ "#90ee90", // lightgreen
14
+ "#444444",
15
+ "#40bfc1",
16
+ "#57557e",
17
+ "#fbe555",
18
+ ];
19
+
20
+ export interface ISegmentBufferGrapUpdateData {
21
+ currentTime : number;
22
+ inventory : IBufferedChunk[];
23
+ width : number;
24
+ height : number;
25
+ minimumPosition : number | undefined;
26
+ maximumPosition : number | undefined;
27
+ }
28
+
29
+ export default class SegmentBufferGraph {
30
+ /** Link buffered Representation to their corresponding color. */
31
+ private readonly _colorMap : WeakMap<Representation, string>;
32
+
33
+ /** Current amount of colors chosen to represent the various Representation. */
34
+ private _currNbColors : number;
35
+
36
+ /** Canvas that will contain the buffer graph itself. */
37
+ private readonly _canvasElt : HTMLCanvasElement;
38
+
39
+ private readonly _canvasCtxt : CanvasRenderingContext2D | null;
40
+
41
+ constructor(canvasElt : HTMLCanvasElement) {
42
+ this._colorMap = new WeakMap();
43
+ this._currNbColors = 0;
44
+ this._canvasElt = canvasElt;
45
+ this._canvasCtxt = this._canvasElt.getContext("2d");
46
+ this.clear();
47
+ }
48
+
49
+ public clear() {
50
+ if (this._canvasCtxt !== null) {
51
+ this._canvasCtxt.clearRect(0, 0, this._canvasElt.width, this._canvasElt.height);
52
+ }
53
+ }
54
+
55
+ public update(data : ISegmentBufferGrapUpdateData) : void {
56
+ if (this._canvasCtxt === null) {
57
+ return;
58
+ }
59
+ const {
60
+ inventory,
61
+ currentTime,
62
+ width,
63
+ height,
64
+ } = data;
65
+ this._canvasElt.style.width = `${width}px`;
66
+ this._canvasElt.style.height = `${height}px`;
67
+ this._canvasElt.width = width;
68
+ this._canvasElt.height = height;
69
+ this.clear();
70
+ let minimumPoint : number;
71
+ if (data.minimumPosition !== undefined) {
72
+ if (inventory.length > 0) {
73
+ minimumPoint = Math.min(data.minimumPosition, inventory[0].start);
74
+ } else {
75
+ minimumPoint = data.minimumPosition;
76
+ }
77
+ } else {
78
+ minimumPoint = inventory[0]?.start ?? 0;
79
+ }
80
+ let maximumPoint : number;
81
+ if (data.maximumPosition !== undefined) {
82
+ if (inventory.length > 0) {
83
+ maximumPoint = Math.max(data.maximumPosition,
84
+ inventory[inventory.length - 1].end);
85
+ } else {
86
+ maximumPoint = data.maximumPosition;
87
+ }
88
+ } else {
89
+ maximumPoint = inventory[inventory.length - 1]?.end ??
90
+ 1000;
91
+ }
92
+ minimumPoint = Math.min(currentTime, minimumPoint);
93
+ maximumPoint = Math.max(currentTime, maximumPoint);
94
+
95
+ let minimumPosition;
96
+ let maximumPosition;
97
+ if (maximumPoint - minimumPoint > BUFFER_WIDTH_IN_SECONDS) {
98
+ if (currentTime === undefined) {
99
+ minimumPosition = minimumPoint;
100
+ maximumPosition = maximumPoint;
101
+ } else if (maximumPoint - currentTime < BUFFER_WIDTH_IN_SECONDS / 2) {
102
+ maximumPosition = maximumPoint;
103
+ minimumPosition = maximumPoint - BUFFER_WIDTH_IN_SECONDS;
104
+ } else if (currentTime - minimumPoint < BUFFER_WIDTH_IN_SECONDS / 2) {
105
+ minimumPosition = minimumPoint;
106
+ maximumPosition = minimumPoint + BUFFER_WIDTH_IN_SECONDS;
107
+ } else {
108
+ minimumPosition = currentTime - BUFFER_WIDTH_IN_SECONDS / 2;
109
+ maximumPosition = currentTime + BUFFER_WIDTH_IN_SECONDS / 2;
110
+ }
111
+ } else {
112
+ minimumPosition = minimumPoint;
113
+ maximumPosition = maximumPoint;
114
+ }
115
+ if (minimumPosition >= maximumPosition) {
116
+ this.clear();
117
+ return;
118
+ }
119
+
120
+ const currentRangesScaled = scaleSegments(inventory,
121
+ minimumPosition,
122
+ maximumPosition);
123
+
124
+ for (let i = 0; i < currentRangesScaled.length; i++) {
125
+ this._paintRange(currentRangesScaled[i], width, height);
126
+ }
127
+
128
+ if (currentTime !== undefined) {
129
+ paintCurrentPosition(currentTime,
130
+ minimumPosition,
131
+ maximumPosition,
132
+ this._canvasCtxt,
133
+ width,
134
+ height);
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Paint a given range in the canvas
140
+ * @param {Object} rangeScaled - Buffered segment information with added
141
+ * "scaling" information to know where it fits in the canvas.
142
+ */
143
+ private _paintRange(
144
+ rangeScaled : IScaledChunk,
145
+ width : number,
146
+ height : number
147
+ ) : void {
148
+ if (this._canvasCtxt === null) {
149
+ return;
150
+ }
151
+ const startX = rangeScaled.scaledStart * width;
152
+ const endX = rangeScaled.scaledEnd * width;
153
+ this._canvasCtxt.fillStyle = this._getColorForRepresentation(
154
+ rangeScaled.info.infos.representation
155
+ );
156
+ this._canvasCtxt.fillRect(
157
+ Math.ceil(startX),
158
+ 0,
159
+ Math.ceil(endX - startX),
160
+ height
161
+ );
162
+ }
163
+
164
+ private _getColorForRepresentation(
165
+ representation : Representation
166
+ ) : string {
167
+ const color = this._colorMap.get(representation);
168
+ if (color !== undefined) {
169
+ return color;
170
+ }
171
+ const newColor = COLORS[this._currNbColors % COLORS.length];
172
+ this._currNbColors++;
173
+ this._colorMap.set(representation, newColor);
174
+ return newColor;
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Represent the current position in the canvas.
180
+ * @param {number|undefined} position - The current position
181
+ * @param {number} minimumPosition - minimum possible position represented in
182
+ * the canvas.
183
+ * @param {number} maximumPosition - maximum possible position represented in
184
+ * the canvas.
185
+ * @param {Object} canvasCtx - The canvas' 2D context
186
+ */
187
+ function paintCurrentPosition(
188
+ position : number,
189
+ minimumPosition : number,
190
+ maximumPosition : number,
191
+ canvasCtx : CanvasRenderingContext2D,
192
+ width : number,
193
+ height : number
194
+ ) {
195
+ if (typeof position === "number" &&
196
+ position >= minimumPosition &&
197
+ position < maximumPosition)
198
+ {
199
+ const lengthCanvas = maximumPosition - minimumPosition;
200
+ canvasCtx.fillStyle = "#FF0000";
201
+ canvasCtx.fillRect(Math.ceil((position - minimumPosition) /
202
+ lengthCanvas * width) - 1,
203
+ 5,
204
+ 5,
205
+ height);
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Scale given bufferedData in terms of percentage between the minimum and
211
+ * maximum position. Filter out ranges which are not part of it.
212
+ * @param {Array.<Object>} bufferedData
213
+ * @param {number} minimumPosition
214
+ * @param {number} maximumPosition
215
+ * @returns {Array.<Object>}
216
+ */
217
+ function scaleSegments(
218
+ bufferedData : IBufferedChunk[],
219
+ minimumPosition : number,
220
+ maximumPosition : number
221
+ ) : IScaledChunk[] {
222
+ const scaledSegments = [];
223
+ const wholeDuration = maximumPosition - minimumPosition;
224
+ for (let i = 0; i < bufferedData.length; i++) {
225
+ const info = bufferedData[i];
226
+ const start = info.bufferedStart === undefined ?
227
+ info.start :
228
+ info.bufferedStart;
229
+ const end = info.bufferedEnd === undefined ?
230
+ info.end :
231
+ info.bufferedEnd;
232
+ if (end > minimumPosition && start < maximumPosition) {
233
+ const startPoint = Math.max(start - minimumPosition, 0);
234
+ const endPoint = Math.min(end - minimumPosition, maximumPosition);
235
+ const scaledStart = startPoint / wholeDuration;
236
+ const scaledEnd = endPoint / wholeDuration;
237
+ scaledSegments.push({ scaledStart, scaledEnd, info });
238
+ }
239
+ }
240
+ return scaledSegments;
241
+ }
242
+
243
+ interface IScaledChunk {
244
+ scaledStart: number;
245
+ scaledEnd: number;
246
+ info: IBufferedChunk;
247
+ }
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Maximum history of the buffer size that will be displayed, in milliseconds.
3
+ * For example, a value of `3000` indicates that we will just show at most the
4
+ * buffer size evolution during the last 3 seconds.
5
+ */
6
+ const TIME_SAMPLES_MS = 30000;
7
+
8
+ /**
9
+ * At minimum, that value will be taken in the chart as a maximum buffer size,
10
+ * in seconds.
11
+ * If samples go higher than this size, the chart will adapt automatically to
12
+ * a higher scale.
13
+ * However if values go below that value, the chart won't scale down more than
14
+ * this.
15
+ */
16
+ const MINIMUM_MAX_BUFFER_SIZE = 20;
17
+
18
+ export default class BufferSizeGraph {
19
+ private _history : IHistoryItem[];
20
+
21
+ /** Canvas that will contain the buffer size graph itself. */
22
+ private readonly _canvasElt : HTMLCanvasElement;
23
+
24
+ private readonly _canvasCtxt : CanvasRenderingContext2D | null;
25
+
26
+ constructor(canvasElt : HTMLCanvasElement) {
27
+ this._canvasElt = canvasElt;
28
+ this._canvasCtxt = this._canvasElt.getContext("2d");
29
+ this._history = [];
30
+ }
31
+
32
+ public pushBufferSize(bufferSize : number) : void {
33
+ const now = performance.now();
34
+ this._history.push({ timestamp: now, bufferSize });
35
+ if (this._history.length > 0) {
36
+ const minimumTime = now - TIME_SAMPLES_MS;
37
+ let i;
38
+ for (i = this._history.length - 1; i >= 1; i--) {
39
+ if (this._history[i].timestamp <= minimumTime) {
40
+ break;
41
+ }
42
+ }
43
+ this._history = this._history.slice(i);
44
+ } else {
45
+ this._history = [];
46
+ }
47
+ }
48
+
49
+ public clear() {
50
+ if (this._canvasCtxt !== null) {
51
+ this._canvasCtxt.clearRect(0, 0, this._canvasElt.width, this._canvasElt.height);
52
+ }
53
+ }
54
+
55
+ public reRender(width : number, height : number) : void {
56
+ this._canvasElt.style.width = `${width}px`;
57
+ this._canvasElt.style.height = `${height}px`;
58
+ this._canvasElt.width = width;
59
+ this._canvasElt.height = height;
60
+ this.clear();
61
+ const history = this._history;
62
+ const canvasCtx = this._canvasCtxt;
63
+
64
+ if (history.length === 0) {
65
+ return;
66
+ }
67
+
68
+ const currentMaxSize = getNewMaxBufferSize();
69
+ const minDate = history[0].timestamp;
70
+
71
+ const gridHeight = height / currentMaxSize;
72
+ const gridWidth = width / TIME_SAMPLES_MS;
73
+
74
+ drawData();
75
+ // drawGrid();
76
+
77
+ /**
78
+ * Get more appropriate maximum buffer size to put on top of the graph
79
+ * according to current history.
80
+ */
81
+ function getNewMaxBufferSize() {
82
+ const maxPoint = Math.max(...history.map(d => d.bufferSize));
83
+ return Math.max(maxPoint + 5, MINIMUM_MAX_BUFFER_SIZE);
84
+ }
85
+
86
+ /**
87
+ * Draw all data contained in `history` in the canvas given.
88
+ */
89
+ function drawData() {
90
+ if (canvasCtx === null) {
91
+ return;
92
+ }
93
+ canvasCtx.beginPath();
94
+ canvasCtx.fillStyle = "rgb(200, 100, 200)";
95
+ for (let i = 1; i < history.length; i++) {
96
+ const diff = dateToX(history[i].timestamp) -
97
+ dateToX(history[i - 1].timestamp);
98
+ const y = height - bufferValueToHeight(history[i].bufferSize);
99
+ canvasCtx.fillRect(
100
+ dateToX(history[i - 1].timestamp),
101
+ y,
102
+ diff,
103
+ height);
104
+ }
105
+ canvasCtx.stroke();
106
+ }
107
+
108
+ /**
109
+ * Convert a value of a given data point, to a u coordinate in the canvas.
110
+ * @param {number} bufferVal - Value to convert
111
+ * @returns {number} - y coordinate
112
+ */
113
+ function bufferValueToHeight(bufferVal : number) : number {
114
+ return height - (currentMaxSize - bufferVal) * gridHeight;
115
+ }
116
+
117
+ /**
118
+ * Convert a date of a given data point, to a x coordinate in the canvas.
119
+ * @param {number} date - Date to convert, in milliseconds
120
+ * @returns {number} - x coordinate
121
+ */
122
+ function dateToX(date : number) : number {
123
+ return (date - minDate) * gridWidth;
124
+ }
125
+ }
126
+ }
127
+
128
+ interface IHistoryItem {
129
+ timestamp : number;
130
+ bufferSize : number;
131
+ }
@@ -0,0 +1,2 @@
1
+ /** Interval at which the various debug metrics will be refreshed. */
2
+ export const DEFAULT_REFRESH_INTERVAL = 1000;
@@ -0,0 +1,3 @@
1
+ import renderDebugElement from "./render";
2
+
3
+ export default renderDebugElement;