rx-player 3.30.1-dev.2023032800 → 3.31.0-dev.2023052200

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 (96) hide show
  1. package/CHANGELOG.md +14 -2
  2. package/CONTRIBUTING.md +48 -168
  3. package/FILES.md +40 -92
  4. package/VERSION +1 -1
  5. package/dist/_esm5.processed/compat/browser_detection.d.ts +3 -1
  6. package/dist/_esm5.processed/compat/browser_detection.js +7 -2
  7. package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.d.ts +21 -0
  8. package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.js +26 -0
  9. package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +1 -2
  10. package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.d.ts +18 -1
  11. package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.js +105 -24
  12. package/dist/_esm5.processed/core/adaptive/guess_based_chooser.js +6 -6
  13. package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.d.ts +19 -1
  14. package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.js +1 -1
  15. package/dist/_esm5.processed/core/api/debug/render.js +1 -1
  16. package/dist/_esm5.processed/core/api/public_api.js +2 -2
  17. package/dist/_esm5.processed/core/api/tracks_management/media_element_track_choice_manager.js +10 -1
  18. package/dist/_esm5.processed/core/api/tracks_management/track_choice_manager.js +20 -117
  19. package/dist/_esm5.processed/core/init/media_source_content_initializer.js +28 -3
  20. package/dist/_esm5.processed/core/init/utils/media_source_duration_updater.d.ts +2 -2
  21. package/dist/_esm5.processed/core/init/utils/media_source_duration_updater.js +29 -18
  22. package/dist/_esm5.processed/core/segment_buffers/index.d.ts +2 -2
  23. package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.js +1 -1
  24. package/dist/_esm5.processed/core/stream/period/period_stream.js +1 -1
  25. package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.d.ts +4 -2
  26. package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.js +2 -2
  27. package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.js +6 -2
  28. package/dist/_esm5.processed/errors/index.d.ts +2 -2
  29. package/dist/_esm5.processed/errors/media_error.d.ts +23 -1
  30. package/dist/_esm5.processed/errors/media_error.js +18 -5
  31. package/dist/_esm5.processed/manifest/adaptation.d.ts +17 -2
  32. package/dist/_esm5.processed/manifest/adaptation.js +67 -1
  33. package/dist/_esm5.processed/manifest/manifest.d.ts +1 -1
  34. package/dist/_esm5.processed/manifest/manifest.js +3 -3
  35. package/dist/_esm5.processed/manifest/period.js +1 -1
  36. package/dist/_esm5.processed/manifest/representation.d.ts +11 -1
  37. package/dist/_esm5.processed/manifest/representation.js +16 -0
  38. package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.d.ts +1 -1
  39. package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.js +1 -1
  40. package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.js +1 -0
  41. package/dist/_esm5.processed/public_types.d.ts +6 -5
  42. package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.d.ts +4 -6
  43. package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.js +4 -6
  44. package/dist/rx-player.js +3086 -3024
  45. package/dist/rx-player.min.js +1 -1
  46. package/package.json +25 -26
  47. package/sonar-project.properties +1 -1
  48. package/src/compat/browser_detection.ts +7 -1
  49. package/src/compat/has_issues_with_high_media_source_duration.ts +27 -0
  50. package/src/core/adaptive/__tests__/buffer_based_chooser.test.ts +147 -48
  51. package/src/core/adaptive/adaptive_representation_selector.ts +1 -2
  52. package/src/core/adaptive/buffer_based_chooser.ts +143 -25
  53. package/src/core/adaptive/guess_based_chooser.ts +9 -8
  54. package/src/core/adaptive/utils/representation_score_calculator.ts +22 -2
  55. package/src/core/api/debug/render.ts +1 -1
  56. package/src/core/api/public_api.ts +2 -2
  57. package/src/core/api/tracks_management/media_element_track_choice_manager.ts +17 -8
  58. package/src/core/api/tracks_management/track_choice_manager.ts +20 -132
  59. package/src/core/init/media_source_content_initializer.ts +32 -4
  60. package/src/core/init/utils/media_source_duration_updater.ts +31 -19
  61. package/src/core/segment_buffers/index.ts +2 -0
  62. package/src/core/stream/adaptation/utils/create_representation_estimator.ts +2 -1
  63. package/src/core/stream/period/period_stream.ts +2 -1
  64. package/src/core/stream/representation/utils/append_segment_to_buffer.ts +8 -3
  65. package/src/core/stream/representation/utils/push_init_segment.ts +7 -1
  66. package/src/errors/__tests__/media_error.test.ts +6 -6
  67. package/src/errors/index.ts +4 -1
  68. package/src/errors/media_error.ts +67 -1
  69. package/src/manifest/__tests__/period.test.ts +90 -45
  70. package/src/manifest/adaptation.ts +77 -2
  71. package/src/manifest/manifest.ts +5 -3
  72. package/src/manifest/period.ts +2 -1
  73. package/src/manifest/representation.ts +23 -1
  74. package/src/parsers/manifest/dash/js-parser/parse_from_document.ts +1 -1
  75. package/src/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.ts +1 -0
  76. package/src/parsers/texttracks/ttml/parse_ttml.ts +1 -1
  77. package/src/public_types.ts +8 -3
  78. package/src/transports/smooth/isobmff/create_boxes.ts +4 -6
  79. package/src/typings/globals.d.ts +21 -21
  80. package/scripts/doc-generator/construct_table_of_contents.js +0 -76
  81. package/scripts/doc-generator/convert_MD_to_HMTL.js +0 -26
  82. package/scripts/doc-generator/create_documentation.js +0 -331
  83. package/scripts/doc-generator/create_documentation_page.js +0 -209
  84. package/scripts/doc-generator/create_page.js +0 -210
  85. package/scripts/doc-generator/generate_header_html.js +0 -147
  86. package/scripts/doc-generator/generate_page_html.js +0 -115
  87. package/scripts/doc-generator/generate_page_list_html.js +0 -92
  88. package/scripts/doc-generator/generate_sidebar_html.js +0 -85
  89. package/scripts/doc-generator/get_search_data_for_content.js +0 -137
  90. package/scripts/doc-generator/index.js +0 -34
  91. package/scripts/doc-generator/parse_doc_configs.js +0 -327
  92. package/scripts/doc-generator/scripts/lunr.js +0 -10
  93. package/scripts/doc-generator/scripts/script.js +0 -451
  94. package/scripts/doc-generator/styles/code.css +0 -99
  95. package/scripts/doc-generator/styles/style.css +0 -835
  96. package/scripts/doc-generator/utils.js +0 -74
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rx-player",
3
3
  "author": "Canal+",
4
- "version": "3.30.1-dev.2023032800",
4
+ "version": "3.31.0-dev.2023052200",
5
5
  "description": "Canal+ HTML5 Video Player",
6
6
  "main": "./dist/rx-player.js",
7
7
  "keywords": [
@@ -45,7 +45,7 @@
45
45
  "demo": "node ./scripts/generate_full_demo.js --production-mode",
46
46
  "demo:min": "node ./scripts/generate_full_demo.js --production-mode --minify",
47
47
  "demo:watch": "node ./scripts/generate_full_demo.js --watch --production-mode",
48
- "doc": "rm -rf doc/generated; node ./scripts/doc-generator/index.js doc/ doc/generated \"$(cat VERSION)\"",
48
+ "doc": "docgen.ico doc/ doc/generated \"$(cat VERSION)\"",
49
49
  "lint": "eslint src -c .eslintrc.js",
50
50
  "lint:demo": "eslint -c demo/full/.eslintrc.js demo/full/scripts",
51
51
  "lint:tests": "eslint tests/**/*.js --ignore-pattern '/tests/performance/bundle*'",
@@ -80,58 +80,57 @@
80
80
  "next-tick": "1.1.0"
81
81
  },
82
82
  "devDependencies": {
83
- "@babel/core": "7.21.0",
84
- "@babel/plugin-transform-runtime": "7.21.0",
85
- "@babel/preset-env": "7.20.2",
83
+ "@babel/core": "7.21.4",
84
+ "@babel/plugin-transform-runtime": "7.21.4",
85
+ "@babel/preset-env": "7.21.4",
86
86
  "@babel/preset-react": "7.18.6",
87
87
  "@types/chai": "4.3.4",
88
- "@types/jest": "29.4.0",
88
+ "@types/jest": "29.5.0",
89
89
  "@types/mocha": "10.0.1",
90
- "@types/node": "18.14.0",
91
- "@types/react": "18.0.28",
90
+ "@types/node": "18.15.11",
91
+ "@types/react": "18.0.33",
92
92
  "@types/react-dom": "18.0.11",
93
93
  "@types/sinon": "10.0.13",
94
- "@typescript-eslint/eslint-plugin": "5.53.0",
95
- "@typescript-eslint/eslint-plugin-tslint": "5.53.0",
96
- "@typescript-eslint/parser": "5.53.0",
94
+ "@typescript-eslint/eslint-plugin": "5.57.1",
95
+ "@typescript-eslint/eslint-plugin-tslint": "5.57.1",
96
+ "@typescript-eslint/parser": "5.57.1",
97
97
  "arraybuffer-loader": "1.0.8",
98
98
  "babel-loader": "9.1.2",
99
99
  "chai": "4.3.7",
100
- "cheerio": "1.0.0-rc.12",
101
- "core-js": "3.28.0",
102
- "esbuild": "0.17.10",
103
- "eslint": "8.34.0",
100
+ "core-js": "3.30.0",
101
+ "docgen.ico": "^0.2.2",
102
+ "esbuild": "0.17.15",
103
+ "eslint": "8.37.0",
104
104
  "eslint-plugin-ban": "1.6.0",
105
105
  "eslint-plugin-import": "2.27.5",
106
- "eslint-plugin-jsdoc": "40.0.0",
106
+ "eslint-plugin-jsdoc": "40.1.1",
107
107
  "eslint-plugin-react": "7.32.2",
108
108
  "esm": "3.2.25",
109
109
  "express": "4.18.2",
110
- "highlight.js": "11.7.0",
110
+ "github-buttons": "2.27.0",
111
111
  "html-entities": "2.3.3",
112
- "jest": "29.4.3",
113
- "jest-environment-jsdom": "29.4.3",
112
+ "jest": "29.5.0",
113
+ "jest-environment-jsdom": "29.5.0",
114
114
  "karma": "6.4.1",
115
115
  "karma-chrome-launcher": "3.1.1",
116
116
  "karma-firefox-launcher": "2.1.2",
117
117
  "karma-mocha": "2.0.1",
118
118
  "karma-webpack": "5.0.0",
119
- "markdown-it": "13.0.1",
120
119
  "mocha": "10.2.0",
121
120
  "mocha-loader": "5.1.5",
122
121
  "raw-loader": "4.0.2",
123
122
  "react": "18.2.0",
124
123
  "react-dom": "18.2.0",
125
124
  "regenerator-runtime": "0.13.11",
126
- "rimraf": "4.1.2",
125
+ "rimraf": "4.4.1",
127
126
  "semver": "7.3.8",
128
- "sinon": "15.0.1",
129
- "terser-webpack-plugin": "5.3.6",
130
- "ts-jest": "29.0.5",
127
+ "sinon": "15.0.3",
128
+ "terser-webpack-plugin": "5.3.7",
129
+ "ts-jest": "29.1.0",
131
130
  "ts-loader": "9.4.2",
132
131
  "tslint": "6.1.3",
133
- "typescript": "4.9.5",
134
- "webpack": "5.75.0",
132
+ "typescript": "5.0.3",
133
+ "webpack": "5.77.0",
135
134
  "webpack-bundle-analyzer": "4.8.0",
136
135
  "webpack-cli": "5.0.1"
137
136
  },
@@ -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.1-dev.2023032800
4
+ sonar.projectVersion=3.31.0-dev.2023052200
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
@@ -60,6 +60,9 @@ let isWebOs2022 = false;
60
60
  /** `true` for Panasonic devices. */
61
61
  let isPanasonic = false;
62
62
 
63
+ /** `true` for the PlayStation 5 game console. */
64
+ let isPlayStation5 = false;
65
+
63
66
  ((function findCurrentBrowser() : void {
64
67
  if (isNode) {
65
68
  return ;
@@ -101,7 +104,9 @@ let isPanasonic = false;
101
104
  isSamsungBrowser = true;
102
105
  }
103
106
 
104
- if (/Tizen/.test(navigator.userAgent)) {
107
+ if (navigator.userAgent.indexOf("PlayStation 5") !== -1) {
108
+ isPlayStation5 = true;
109
+ } else if (/Tizen/.test(navigator.userAgent)) {
105
110
  isTizen = true;
106
111
 
107
112
  // Inspired form: http://webostv.developer.lge.com/discover/specifications/web-engine/
@@ -136,6 +141,7 @@ export {
136
141
  isIEOrEdge,
137
142
  isFirefox,
138
143
  isPanasonic,
144
+ isPlayStation5,
139
145
  isSafariDesktop,
140
146
  isSafariMobile,
141
147
  isSamsungBrowser,
@@ -0,0 +1,27 @@
1
+ import { isPlayStation5 } from "./browser_detection";
2
+
3
+ /**
4
+ * Some platforms have issues when the `MediaSource`'s `duration` property
5
+ * is set to a very high value (playback freezes) but not when setting it
6
+ * to `Infinity`, which is what the HTML spec as of now (2023-05-15) recommends
7
+ * for live contents.
8
+ *
9
+ * However setting the `MediaSource`'s `duration` property to `Infinity` seems
10
+ * more risky, considering all platforms we now support, than setting it at a
11
+ * relatively high ~2**32 value which is what we do generally.
12
+ *
13
+ * Moreover, setting it to `Infinity` require us to use another MSE API,
14
+ * `setLiveSeekableRange` to properly allow seeking. We're used to MSE issues so
15
+ * I'm not too confident of using another MSE API for all platforms directly.
16
+ *
17
+ * So this methods just return `true` based on a whitelist of platform for which
18
+ * it has been detected that high `duration` values cause issues but setting it
19
+ * to Infinity AND playing with `setLiveSeekableRange` does not.
20
+ *
21
+ * @returns {boolean}
22
+ */
23
+ export default function hasIssuesWithHighMediaSourceDuration(): boolean {
24
+ // For now only seen on the Webkit present in the PlayStation 5, for which the
25
+ // alternative is known to work.
26
+ return isPlayStation5;
27
+ }
@@ -14,6 +14,8 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
+ import { ScoreConfidenceLevel } from "../utils/representation_score_calculator";
18
+
17
19
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
18
20
  /* eslint-disable @typescript-eslint/no-unsafe-member-access */
19
21
  /* eslint-disable @typescript-eslint/no-var-requires */
@@ -47,12 +49,25 @@ describe("BufferBasedChooser", () => {
47
49
  bufferGap: 0,
48
50
  speed: 1,
49
51
  currentBitrate: undefined,
50
- currentScore: 4,
52
+ currentScore: { score: 4, confidenceLevel: ScoreConfidenceLevel.LOW },
53
+ })).toEqual(1);
54
+ expect(new BufferBasedChooser([1, 2, 3]).getEstimate({
55
+ bufferGap: 0,
56
+ speed: 1,
57
+ currentBitrate: undefined,
58
+ currentScore: { score: 4, confidenceLevel: ScoreConfidenceLevel.HIGH },
59
+ })).toEqual(1);
60
+ expect(new BufferBasedChooser([1, 2, 3]).getEstimate({
61
+ bufferGap: 0,
62
+ speed: 1,
63
+ currentBitrate: undefined,
64
+ currentScore: { score: 1, confidenceLevel: ScoreConfidenceLevel.LOW },
51
65
  })).toEqual(1);
52
66
  expect(new BufferBasedChooser([1, 2, 3]).getEstimate({
53
67
  bufferGap: 0,
54
68
  speed: 1,
55
- currentScore: 1,
69
+ currentBitrate: undefined,
70
+ currentScore: { score: 1, confidenceLevel: ScoreConfidenceLevel.HIGH },
56
71
  })).toEqual(1);
57
72
  });
58
73
 
@@ -76,7 +91,7 @@ describe("BufferBasedChooser", () => {
76
91
  });
77
92
 
78
93
  /* eslint-disable max-len */
79
- it("should go to the next bitrate if the current one is maintainable and we have more buffer than the next level", () => {
94
+ it("should not go to the next bitrate if we don't have a high enough maintainability score", () => {
80
95
  /* eslint-enable max-len */
81
96
  const logger = { debug: jest.fn() };
82
97
  jest.mock("../../../log", () => ({ __esModule: true as const,
@@ -86,82 +101,82 @@ describe("BufferBasedChooser", () => {
86
101
  bufferGap: 16,
87
102
  speed: 1,
88
103
  currentBitrate: 10,
89
- currentScore: 1.01,
90
- })).toEqual(20);
104
+ currentScore: { score: 1.15, confidenceLevel: ScoreConfidenceLevel.LOW },
105
+ })).toEqual(10);
91
106
  expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
92
107
  bufferGap: 30,
93
108
  speed: 1,
94
109
  currentBitrate: 20,
95
- currentScore: 1.01,
96
- })).toEqual(40);
110
+ currentScore: { score: 1.15, confidenceLevel: ScoreConfidenceLevel.LOW },
111
+ })).toEqual(20);
97
112
  expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
98
113
  bufferGap: 30,
99
114
  speed: 1,
100
115
  currentBitrate: 20,
101
- currentScore: 100,
102
- })).toEqual(40);
116
+ currentScore: { score: 100, confidenceLevel: ScoreConfidenceLevel.LOW },
117
+ })).toEqual(20);
103
118
  expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
104
119
  bufferGap: 30,
105
120
  speed: 2,
106
121
  currentBitrate: 20,
107
- currentScore: 2.1,
108
- })).toEqual(40);
122
+ currentScore: { score: 2.30, confidenceLevel: ScoreConfidenceLevel.LOW },
123
+ })).toEqual(20);
109
124
  expect(new BufferBasedChooser([10, 20, 20, 40]).getEstimate({
110
125
  bufferGap: 30,
111
126
  speed: 2,
112
127
  currentBitrate: 20,
113
- currentScore: 2.1,
114
- })).toEqual(40);
128
+ currentScore: { score: 2.30, confidenceLevel: ScoreConfidenceLevel.LOW },
129
+ })).toEqual(20);
115
130
  expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
116
131
  bufferGap: 30,
117
132
  speed: 0, // 0 is a special case
118
133
  currentBitrate: 20,
119
- currentScore: 100,
120
- })).toEqual(40);
134
+ currentScore: { score: 100, confidenceLevel: ScoreConfidenceLevel.LOW },
135
+ })).toEqual(20);
121
136
  });
122
137
 
123
138
  /* eslint-disable max-len */
124
- it("should go to the next bitrate if the current one is maintainable and we have the buffer corresponding to the next level", () => {
139
+ it("should go to the next bitrate if the current one is maintainable and we have more buffer than the next level", () => {
125
140
  /* eslint-enable max-len */
126
141
  const logger = { debug: jest.fn() };
127
142
  jest.mock("../../../log", () => ({ __esModule: true as const,
128
143
  default: logger }));
129
144
  const BufferBasedChooser = jest.requireActual("../buffer_based_chooser").default;
130
145
  expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
131
- bufferGap: 15,
146
+ bufferGap: 16,
132
147
  speed: 1,
133
148
  currentBitrate: 10,
134
- currentScore: 1.01,
149
+ currentScore: { score: 1.15, confidenceLevel: ScoreConfidenceLevel.HIGH },
135
150
  })).toEqual(20);
136
151
  expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
137
- bufferGap: 20,
152
+ bufferGap: 30,
138
153
  speed: 1,
139
154
  currentBitrate: 20,
140
- currentScore: 1.01,
155
+ currentScore: { score: 1.15, confidenceLevel: ScoreConfidenceLevel.HIGH },
141
156
  })).toEqual(40);
142
157
  expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
143
- bufferGap: 20,
158
+ bufferGap: 30,
144
159
  speed: 1,
145
160
  currentBitrate: 20,
146
- currentScore: 100,
161
+ currentScore: { score: 100, confidenceLevel: ScoreConfidenceLevel.HIGH },
147
162
  })).toEqual(40);
148
163
  expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
149
- bufferGap: 20,
164
+ bufferGap: 30,
150
165
  speed: 2,
151
166
  currentBitrate: 20,
152
- currentScore: 2.1,
167
+ currentScore: { score: 2.30, confidenceLevel: ScoreConfidenceLevel.HIGH },
153
168
  })).toEqual(40);
154
169
  expect(new BufferBasedChooser([10, 20, 20, 40]).getEstimate({
155
- bufferGap: 20,
170
+ bufferGap: 30,
156
171
  speed: 2,
157
172
  currentBitrate: 20,
158
- currentScore: 2.1,
173
+ currentScore: { score: 2.30, confidenceLevel: ScoreConfidenceLevel.HIGH },
159
174
  })).toEqual(40);
160
175
  expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
161
- bufferGap: 20,
176
+ bufferGap: 30,
162
177
  speed: 0, // 0 is a special case
163
178
  currentBitrate: 20,
164
- currentScore: 100,
179
+ currentScore: { score: 100, confidenceLevel: ScoreConfidenceLevel.HIGH },
165
180
  })).toEqual(40);
166
181
  });
167
182
 
@@ -176,31 +191,31 @@ describe("BufferBasedChooser", () => {
176
191
  bufferGap: 6,
177
192
  speed: 1,
178
193
  currentBitrate: 10,
179
- currentScore: 1.01,
194
+ currentScore: { score: 1.15, confidenceLevel: ScoreConfidenceLevel.HIGH },
180
195
  })).toEqual(10);
181
196
  expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
182
- bufferGap: 10,
197
+ bufferGap: 13,
183
198
  speed: 1,
184
199
  currentBitrate: 20,
185
- currentScore: 1.01,
200
+ currentScore: { score: 1.15, confidenceLevel: ScoreConfidenceLevel.HIGH },
186
201
  })).toEqual(20);
187
202
  expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
188
- bufferGap: 10,
203
+ bufferGap: 13,
189
204
  speed: 1,
190
205
  currentBitrate: 20,
191
- currentScore: 100,
206
+ currentScore: { score: 100, confidenceLevel: ScoreConfidenceLevel.HIGH },
192
207
  })).toEqual(20);
193
208
  expect(new BufferBasedChooser([10, 20, 20, 40]).getEstimate({
194
- bufferGap: 10,
209
+ bufferGap: 13,
195
210
  speed: 1,
196
211
  currentBitrate: 20,
197
- currentScore: 100,
212
+ currentScore: { score: 100, confidenceLevel: ScoreConfidenceLevel.HIGH },
198
213
  })).toEqual(20);
199
214
  expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
200
- bufferGap: 10,
215
+ bufferGap: 13,
201
216
  speed: 2,
202
217
  currentBitrate: 20,
203
- currentScore: 2.1,
218
+ currentScore: { score: 2.30, confidenceLevel: ScoreConfidenceLevel.HIGH },
204
219
  })).toEqual(20);
205
220
  });
206
221
 
@@ -216,13 +231,13 @@ describe("BufferBasedChooser", () => {
216
231
  bufferGap: 100000000000,
217
232
  speed: 1,
218
233
  currentBitrate: 40,
219
- currentScore: 1000000,
234
+ currentScore: { score: 1000000, confidenceLevel: ScoreConfidenceLevel.HIGH },
220
235
  })).toEqual(40);
221
236
  expect(new BufferBasedChooser([10, 20, 40, 40]).getEstimate({
222
237
  bufferGap: 100000000000,
223
238
  speed: 1,
224
239
  currentBitrate: 40,
225
- currentScore: 1000000,
240
+ currentScore: { score: 1000000, confidenceLevel: ScoreConfidenceLevel.HIGH },
226
241
  })).toEqual(40);
227
242
  });
228
243
 
@@ -237,31 +252,115 @@ describe("BufferBasedChooser", () => {
237
252
  bufferGap: 15,
238
253
  speed: 2,
239
254
  currentBitrate: 10,
240
- currentScore: 1.01,
255
+ currentScore: { score: 2, confidenceLevel: ScoreConfidenceLevel.HIGH },
241
256
  })).toEqual(10);
242
257
  expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
243
- bufferGap: 20,
258
+ bufferGap: 22,
244
259
  speed: 2,
245
260
  currentBitrate: 20,
246
- currentScore: 1.01,
261
+ currentScore: { score: 2, confidenceLevel: ScoreConfidenceLevel.HIGH },
247
262
  })).toEqual(20);
248
263
  expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
249
- bufferGap: 20,
264
+ bufferGap: 22,
250
265
  speed: 100,
251
266
  currentBitrate: 20,
252
- currentScore: 100,
267
+ currentScore: { score: 100, confidenceLevel: ScoreConfidenceLevel.HIGH },
253
268
  })).toEqual(20);
254
269
  expect(new BufferBasedChooser([10, 20, 20, 40]).getEstimate({
255
- bufferGap: 20,
270
+ bufferGap: 22,
256
271
  speed: 100,
257
272
  currentBitrate: 20,
258
- currentScore: 100,
273
+ currentScore: { score: 100, confidenceLevel: ScoreConfidenceLevel.HIGH },
259
274
  })).toEqual(20);
260
275
  expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
261
- bufferGap: 20,
276
+ bufferGap: 22,
277
+ speed: 3,
278
+ currentBitrate: 20,
279
+ currentScore: { score: 3, confidenceLevel: ScoreConfidenceLevel.HIGH },
280
+ })).toEqual(20);
281
+ });
282
+
283
+ /* eslint-disable max-len */
284
+ it("should lower bitrate if the current one is not maintainable due to the speed", () => {
285
+ /* eslint-enable max-len */
286
+ const logger = { debug: jest.fn() };
287
+ jest.mock("../../../log", () => ({ __esModule: true as const,
288
+ default: logger }));
289
+ const BufferBasedChooser = jest.requireActual("../buffer_based_chooser").default;
290
+ expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
291
+ bufferGap: 15,
292
+ speed: 2,
293
+ currentBitrate: 10,
294
+ currentScore: { score: 1.9, confidenceLevel: ScoreConfidenceLevel.HIGH },
295
+ })).toEqual(10);
296
+ expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
297
+ bufferGap: 22,
298
+ speed: 2,
299
+ currentBitrate: 20,
300
+ currentScore: { score: 1.9, confidenceLevel: ScoreConfidenceLevel.HIGH },
301
+ })).toEqual(10);
302
+ expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
303
+ bufferGap: 22,
304
+ speed: 100,
305
+ currentBitrate: 20,
306
+ currentScore: { score: 99, confidenceLevel: ScoreConfidenceLevel.HIGH },
307
+ })).toEqual(10);
308
+ expect(new BufferBasedChooser([10, 20, 20, 40]).getEstimate({
309
+ bufferGap: 22,
310
+ speed: 100,
311
+ currentBitrate: 20,
312
+ currentScore: { score: 99, confidenceLevel: ScoreConfidenceLevel.HIGH },
313
+ })).toEqual(10);
314
+ expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
315
+ bufferGap: 22,
316
+ speed: 3,
317
+ currentBitrate: 20,
318
+ currentScore: { score: 2.5, confidenceLevel: ScoreConfidenceLevel.HIGH },
319
+ })).toEqual(10);
320
+ });
321
+
322
+ /* eslint-disable max-len */
323
+ it("should not lower bitrate if the current one is not maintainable due to the speed but confidence on the score is low", () => {
324
+ /* eslint-enable max-len */
325
+ const logger = { debug: jest.fn() };
326
+ jest.mock("../../../log", () => ({ __esModule: true as const,
327
+ default: logger }));
328
+ const BufferBasedChooser = jest.requireActual("../buffer_based_chooser").default;
329
+ expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
330
+ bufferGap: 15,
331
+ speed: 2,
332
+ currentBitrate: 10,
333
+ currentScore: { score: 1.9, confidenceLevel: ScoreConfidenceLevel.LOW },
334
+ })).toEqual(10);
335
+ expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
336
+ bufferGap: 22,
337
+ speed: 2,
338
+ currentBitrate: 20,
339
+ currentScore: undefined,
340
+ })).toEqual(20);
341
+ expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
342
+ bufferGap: 22,
343
+ speed: 2,
344
+ currentBitrate: 20,
345
+ currentScore: { score: 1.9, confidenceLevel: ScoreConfidenceLevel.LOW },
346
+ })).toEqual(20);
347
+ expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
348
+ bufferGap: 22,
349
+ speed: 100,
350
+ currentBitrate: 20,
351
+ currentScore: { score: 99, confidenceLevel: ScoreConfidenceLevel.LOW },
352
+ })).toEqual(20);
353
+ expect(new BufferBasedChooser([10, 20, 20, 40]).getEstimate({
354
+ bufferGap: 22,
355
+ speed: 100,
356
+ currentBitrate: 20,
357
+ currentScore: { score: 99, confidenceLevel: ScoreConfidenceLevel.LOW },
358
+ })).toEqual(20);
359
+ expect(new BufferBasedChooser([10, 20, 40]).getEstimate({
360
+ bufferGap: 22,
262
361
  speed: 3,
263
362
  currentBitrate: 20,
264
- currentScore: 2.1,
363
+ currentScore: { score: 2.5, confidenceLevel: ScoreConfidenceLevel.LOW },
265
364
  })).toEqual(20);
266
365
  });
267
366
 
@@ -317,8 +317,7 @@ function getEstimateReference(
317
317
  const timeRanges = val.buffered;
318
318
  const bufferGap = getLeftSizeOfRange(timeRanges, position.last);
319
319
  const { representation } = val.content;
320
- const scoreData = scoreCalculator.getEstimate(representation);
321
- const currentScore = scoreData?.[0];
320
+ const currentScore = scoreCalculator.getEstimate(representation);
322
321
  const currentBitrate = representation.bitrate;
323
322
  const observation = { bufferGap, currentBitrate, currentScore, speed };
324
323
  currentBufferBasedEstimate = bufferBasedChooser.getEstimate(observation);