rx-player 4.0.0-beta.1 → 4.0.0-beta.2

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 (169) hide show
  1. package/CHANGELOG.md +40 -0
  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/eme/load_session.js +1 -1
  8. package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.d.ts +21 -0
  9. package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.js +26 -0
  10. package/dist/_esm5.processed/config.d.ts +2 -0
  11. package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +5 -4
  12. package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.d.ts +18 -1
  13. package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.js +106 -25
  14. package/dist/_esm5.processed/core/adaptive/guess_based_chooser.js +6 -6
  15. package/dist/_esm5.processed/core/adaptive/network_analyzer.js +8 -5
  16. package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.d.ts +19 -1
  17. package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.js +1 -1
  18. package/dist/_esm5.processed/core/api/debug/render.js +1 -1
  19. package/dist/_esm5.processed/core/api/playback_observer.js +1 -0
  20. package/dist/_esm5.processed/core/api/public_api.d.ts +54 -1
  21. package/dist/_esm5.processed/core/api/public_api.js +232 -35
  22. package/dist/_esm5.processed/core/api/track_management/media_element_tracks_store.js +10 -1
  23. package/dist/_esm5.processed/core/api/track_management/track_dispatcher.d.ts +13 -1
  24. package/dist/_esm5.processed/core/api/track_management/track_dispatcher.js +30 -15
  25. package/dist/_esm5.processed/core/api/track_management/tracks_store.d.ts +3 -1
  26. package/dist/_esm5.processed/core/api/track_management/tracks_store.js +67 -152
  27. package/dist/_esm5.processed/core/api/utils.d.ts +10 -0
  28. package/dist/_esm5.processed/core/api/utils.js +20 -0
  29. package/dist/_esm5.processed/core/decrypt/session_events_listener.js +7 -1
  30. package/dist/_esm5.processed/core/decrypt/utils/clean_old_loaded_sessions.js +2 -0
  31. package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.js +5 -1
  32. package/dist/_esm5.processed/core/init/directfile_content_initializer.js +1 -1
  33. package/dist/_esm5.processed/core/init/media_source_content_initializer.js +47 -10
  34. package/dist/_esm5.processed/core/init/types.d.ts +9 -1
  35. package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.d.ts +28 -1
  36. package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.js +22 -9
  37. package/dist/_esm5.processed/core/init/utils/media_source_duration_updater.d.ts +58 -0
  38. package/dist/_esm5.processed/core/init/utils/{media_duration_updater.js → media_source_duration_updater.js} +84 -87
  39. package/dist/_esm5.processed/core/init/utils/rebuffering_controller.d.ts +36 -2
  40. package/dist/_esm5.processed/core/init/utils/rebuffering_controller.js +82 -2
  41. package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.d.ts +18 -7
  42. package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +31 -40
  43. package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.d.ts +8 -0
  44. package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +12 -0
  45. package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.d.ts +8 -0
  46. package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.js +12 -0
  47. package/dist/_esm5.processed/core/segment_buffers/implementations/types.d.ts +11 -4
  48. package/dist/_esm5.processed/core/segment_buffers/index.d.ts +2 -2
  49. package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.d.ts +47 -0
  50. package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.js +70 -0
  51. package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +15 -8
  52. package/dist/_esm5.processed/core/stream/period/period_stream.js +1 -1
  53. package/dist/_esm5.processed/core/stream/representation/representation_stream.js +22 -13
  54. package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.d.ts +4 -2
  55. package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.js +2 -2
  56. package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.d.ts +3 -2
  57. package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.js +8 -8
  58. package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.d.ts +2 -2
  59. package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.js +2 -3
  60. package/dist/_esm5.processed/default_config.d.ts +25 -0
  61. package/dist/_esm5.processed/default_config.js +27 -2
  62. package/dist/_esm5.processed/errors/index.d.ts +2 -2
  63. package/dist/_esm5.processed/errors/media_error.d.ts +23 -1
  64. package/dist/_esm5.processed/errors/media_error.js +18 -5
  65. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.d.ts +1 -1
  66. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.js +8 -7
  67. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +17 -9
  68. package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/index.js +0 -2
  69. package/dist/_esm5.processed/manifest/adaptation.d.ts +21 -2
  70. package/dist/_esm5.processed/manifest/adaptation.js +76 -1
  71. package/dist/_esm5.processed/manifest/manifest.js +1 -1
  72. package/dist/_esm5.processed/manifest/period.js +2 -2
  73. package/dist/_esm5.processed/manifest/representation.d.ts +33 -2
  74. package/dist/_esm5.processed/manifest/representation.js +21 -0
  75. package/dist/_esm5.processed/manifest/utils.js +1 -3
  76. package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.d.ts +1 -1
  77. package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.js +1 -1
  78. package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.js +1 -0
  79. package/dist/_esm5.processed/public_types.d.ts +13 -3
  80. package/dist/_esm5.processed/tools/TextTrackRenderer/text_track_renderer.js +1 -1
  81. package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.d.ts +4 -6
  82. package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.js +4 -6
  83. package/dist/_esm5.processed/utils/is_null_or_undefined.d.ts +1 -1
  84. package/dist/_esm5.processed/utils/is_null_or_undefined.js +1 -1
  85. package/dist/mpd-parser.wasm +0 -0
  86. package/dist/rx-player.js +4709 -4218
  87. package/dist/rx-player.min.js +1 -1
  88. package/package.json +42 -36
  89. package/scripts/build/generate_build.js +1 -1
  90. package/scripts/fast_demo_build.js +4 -3
  91. package/scripts/generate_full_demo.js +1 -1
  92. package/sonar-project.properties +1 -1
  93. package/src/compat/browser_detection.ts +7 -1
  94. package/src/compat/eme/load_session.ts +1 -1
  95. package/src/compat/has_issues_with_high_media_source_duration.ts +27 -0
  96. package/src/core/adaptive/__tests__/buffer_based_chooser.test.ts +147 -48
  97. package/src/core/adaptive/adaptive_representation_selector.ts +7 -4
  98. package/src/core/adaptive/buffer_based_chooser.ts +144 -26
  99. package/src/core/adaptive/guess_based_chooser.ts +9 -8
  100. package/src/core/adaptive/network_analyzer.ts +9 -4
  101. package/src/core/adaptive/utils/representation_score_calculator.ts +22 -2
  102. package/src/core/api/debug/render.ts +1 -1
  103. package/src/core/api/playback_observer.ts +1 -0
  104. package/src/core/api/public_api.ts +277 -44
  105. package/src/core/api/track_management/media_element_tracks_store.ts +17 -8
  106. package/src/core/api/track_management/track_dispatcher.ts +37 -14
  107. package/src/core/api/track_management/tracks_store.ts +77 -167
  108. package/src/core/api/utils.ts +26 -0
  109. package/src/core/decrypt/session_events_listener.ts +6 -1
  110. package/src/core/decrypt/utils/clean_old_loaded_sessions.ts +2 -1
  111. package/src/core/decrypt/utils/loaded_sessions_store.ts +8 -1
  112. package/src/core/init/directfile_content_initializer.ts +1 -0
  113. package/src/core/init/media_source_content_initializer.ts +52 -9
  114. package/src/core/init/types.ts +9 -1
  115. package/src/core/init/utils/content_time_boundaries_observer.ts +46 -10
  116. package/src/core/init/utils/{media_duration_updater.ts → media_source_duration_updater.ts} +100 -112
  117. package/src/core/init/utils/rebuffering_controller.ts +114 -3
  118. package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +56 -55
  119. package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +16 -0
  120. package/src/core/segment_buffers/implementations/text/native/native_text_segment_buffer.ts +16 -0
  121. package/src/core/segment_buffers/implementations/types.ts +16 -4
  122. package/src/core/segment_buffers/index.ts +2 -0
  123. package/src/core/stream/adaptation/utils/create_representation_estimator.ts +114 -0
  124. package/src/core/stream/orchestrator/stream_orchestrator.ts +16 -8
  125. package/src/core/stream/period/period_stream.ts +2 -1
  126. package/src/core/stream/representation/representation_stream.ts +34 -22
  127. package/src/core/stream/representation/utils/append_segment_to_buffer.ts +8 -3
  128. package/src/core/stream/representation/utils/push_init_segment.ts +11 -6
  129. package/src/core/stream/representation/utils/push_media_segment.ts +3 -3
  130. package/src/default_config.ts +29 -2
  131. package/src/errors/__tests__/media_error.test.ts +6 -6
  132. package/src/errors/index.ts +4 -1
  133. package/src/errors/media_error.ts +67 -1
  134. package/src/experimental/tools/VideoThumbnailLoader/load_and_push_segment.ts +10 -7
  135. package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +17 -6
  136. package/src/experimental/tools/mediaCapabilitiesProber/index.ts +0 -4
  137. package/src/manifest/__tests__/manifest.test.ts +7 -7
  138. package/src/manifest/__tests__/period.test.ts +90 -45
  139. package/src/manifest/adaptation.ts +89 -1
  140. package/src/manifest/manifest.ts +1 -1
  141. package/src/manifest/period.ts +4 -2
  142. package/src/manifest/representation.ts +67 -1
  143. package/src/manifest/utils.ts +1 -3
  144. package/src/parsers/manifest/dash/js-parser/parse_from_document.ts +1 -1
  145. package/src/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.ts +1 -0
  146. package/src/parsers/texttracks/ttml/parse_ttml.ts +1 -1
  147. package/src/public_types.ts +16 -1
  148. package/src/tools/TextTrackRenderer/text_track_renderer.ts +1 -1
  149. package/src/transports/smooth/isobmff/create_boxes.ts +4 -6
  150. package/src/typings/globals.d.ts +20 -20
  151. package/src/utils/is_null_or_undefined.ts +1 -1
  152. package/dist/_esm5.processed/core/init/utils/media_duration_updater.d.ts +0 -56
  153. package/scripts/doc-generator/construct_table_of_contents.js +0 -76
  154. package/scripts/doc-generator/convert_MD_to_HMTL.js +0 -26
  155. package/scripts/doc-generator/create_documentation.js +0 -331
  156. package/scripts/doc-generator/create_documentation_page.js +0 -209
  157. package/scripts/doc-generator/create_page.js +0 -210
  158. package/scripts/doc-generator/generate_header_html.js +0 -147
  159. package/scripts/doc-generator/generate_page_html.js +0 -115
  160. package/scripts/doc-generator/generate_page_list_html.js +0 -92
  161. package/scripts/doc-generator/generate_sidebar_html.js +0 -85
  162. package/scripts/doc-generator/get_search_data_for_content.js +0 -137
  163. package/scripts/doc-generator/index.js +0 -34
  164. package/scripts/doc-generator/parse_doc_configs.js +0 -327
  165. package/scripts/doc-generator/scripts/lunr.js +0 -10
  166. package/scripts/doc-generator/scripts/script.js +0 -451
  167. package/scripts/doc-generator/styles/code.css +0 -99
  168. package/scripts/doc-generator/styles/style.css +0 -835
  169. 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": "4.0.0-beta.1",
4
+ "version": "4.0.0-beta.2",
5
5
  "description": "Canal+ HTML5 Video Player",
6
6
  "main": "./dist/rx-player.js",
7
7
  "keywords": [
@@ -40,12 +40,14 @@
40
40
  "check:appveyor": "npm run check:types && npm run lint && npm run lint:demo && npm run lint:tests && npm run test:appveyor",
41
41
  "check:types": "tsc --noEmit --project .",
42
42
  "check:types:watch": "tsc --noEmit --watch --project .",
43
+ "check:demo": "npm run check:demo:types && npm run lint:demo",
44
+ "check:demo:types": "tsc --noEmit --project demo/full",
43
45
  "demo": "node ./scripts/generate_full_demo.js --production-mode",
44
46
  "demo:min": "node ./scripts/generate_full_demo.js --production-mode --minify",
45
47
  "demo:watch": "node ./scripts/generate_full_demo.js --watch --production-mode",
46
- "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)\"",
47
49
  "lint": "eslint src -c .eslintrc.js",
48
- "lint:demo": "eslint demo/full/scripts",
50
+ "lint:demo": "eslint -c demo/full/.eslintrc.js demo/full/scripts",
49
51
  "lint:tests": "eslint tests/**/*.js --ignore-pattern '/tests/performance/bundle*'",
50
52
  "list": "node scripts/list-npm-scripts.js",
51
53
  "prepublishOnly": "npm run build:modular",
@@ -78,58 +80,59 @@
78
80
  "next-tick": "1.1.0"
79
81
  },
80
82
  "devDependencies": {
81
- "@babel/core": "7.21.0",
82
- "@babel/plugin-transform-runtime": "7.21.0",
83
- "@babel/preset-env": "7.20.2",
84
- "@babel/preset-react": "7.18.6",
85
- "@types/chai": "4.3.4",
86
- "@types/jest": "29.4.0",
83
+ "@babel/core": "7.22.5",
84
+ "@babel/plugin-transform-runtime": "7.22.5",
85
+ "@babel/preset-env": "7.22.5",
86
+ "@babel/preset-react": "7.22.5",
87
+ "@types/chai": "4.3.5",
88
+ "@types/jest": "29.5.2",
87
89
  "@types/mocha": "10.0.1",
88
- "@types/node": "18.14.0",
89
- "@types/sinon": "10.0.13",
90
- "@typescript-eslint/eslint-plugin": "5.53.0",
91
- "@typescript-eslint/eslint-plugin-tslint": "5.53.0",
92
- "@typescript-eslint/parser": "5.53.0",
90
+ "@types/node": "20.3.1",
91
+ "@types/react": "18.2.12",
92
+ "@types/react-dom": "18.2.5",
93
+ "@types/sinon": "10.0.15",
94
+ "@typescript-eslint/eslint-plugin": "5.59.11",
95
+ "@typescript-eslint/eslint-plugin-tslint": "5.59.11",
96
+ "@typescript-eslint/parser": "5.59.11",
93
97
  "arraybuffer-loader": "1.0.8",
94
98
  "babel-loader": "9.1.2",
95
99
  "chai": "4.3.7",
96
- "cheerio": "1.0.0-rc.12",
97
- "core-js": "3.28.0",
98
- "esbuild": "0.17.10",
99
- "eslint": "8.34.0",
100
+ "core-js": "3.31.0",
101
+ "docgen.ico": "^0.2.3",
102
+ "esbuild": "0.18.2",
103
+ "eslint": "8.42.0",
100
104
  "eslint-plugin-ban": "1.6.0",
101
105
  "eslint-plugin-import": "2.27.5",
102
- "eslint-plugin-jsdoc": "40.0.0",
106
+ "eslint-plugin-jsdoc": "46.2.6",
103
107
  "eslint-plugin-react": "7.32.2",
104
108
  "esm": "3.2.25",
105
109
  "express": "4.18.2",
106
- "highlight.js": "11.7.0",
107
- "html-entities": "2.3.3",
108
- "jest": "29.4.3",
109
- "jest-environment-jsdom": "29.4.3",
110
- "karma": "6.4.1",
111
- "karma-chrome-launcher": "3.1.1",
110
+ "github-buttons": "2.27.0",
111
+ "html-entities": "2.3.6",
112
+ "jest": "29.5.0",
113
+ "jest-environment-jsdom": "29.5.0",
114
+ "karma": "6.4.2",
115
+ "karma-chrome-launcher": "3.2.0",
112
116
  "karma-firefox-launcher": "2.1.2",
113
117
  "karma-mocha": "2.0.1",
114
118
  "karma-webpack": "5.0.0",
115
- "markdown-it": "13.0.1",
116
119
  "mocha": "10.2.0",
117
120
  "mocha-loader": "5.1.5",
118
121
  "raw-loader": "4.0.2",
119
122
  "react": "18.2.0",
120
123
  "react-dom": "18.2.0",
121
124
  "regenerator-runtime": "0.13.11",
122
- "rimraf": "4.1.2",
123
- "semver": "7.3.8",
124
- "sinon": "15.0.1",
125
- "terser-webpack-plugin": "5.3.6",
126
- "ts-jest": "29.0.5",
127
- "ts-loader": "9.4.2",
125
+ "rimraf": "5.0.1",
126
+ "semver": "7.5.1",
127
+ "sinon": "15.1.2",
128
+ "terser-webpack-plugin": "5.3.9",
129
+ "ts-jest": "29.1.0",
130
+ "ts-loader": "9.4.3",
128
131
  "tslint": "6.1.3",
129
- "typescript": "4.9.5",
130
- "webpack": "5.75.0",
131
- "webpack-bundle-analyzer": "4.8.0",
132
- "webpack-cli": "5.0.1"
132
+ "typescript": "5.1.3",
133
+ "webpack": "5.86.0",
134
+ "webpack-bundle-analyzer": "4.9.0",
135
+ "webpack-cli": "5.1.4"
133
136
  },
134
137
  "scripts-list": {
135
138
  "Build a demo page (e.g. to test a code change)": {
@@ -140,6 +143,9 @@
140
143
  "demo": "Build the demo in demo/bundle.js",
141
144
  "demo:min": "Build the demo and minify it in demo/bundle.js",
142
145
  "demo:watch": "Build the demo in demo/bundle.js each times the files update.",
146
+ "check:demo": "Check the validity of the full demo directory by running the type checker and linter on it",
147
+ "check:demo:types": "Check TypeScript types in full demo files",
148
+ "lint:demo": "Run linter on the full demo files",
143
149
  "standalone": "Build and launch the \"standalone\" demo (without any UI) on a local server. Re-build on file updates.",
144
150
  "certificate": "Generate a certificate to be able to use HTTPS locally for the demo pages (`npm run start` and `npm run standalone` will then listen to HTTPS requests through a communicated port)"
145
151
  },
@@ -22,7 +22,7 @@ const { spawn } = require("child_process");
22
22
  const fs = require("fs/promises");
23
23
  const os = require("os");
24
24
  const path = require("path");
25
- const rimraf = require("rimraf");
25
+ const { rimraf } = require("rimraf");
26
26
 
27
27
  const BUILD_DIR_FROM_ROOT = "dist/_esm5.processed";
28
28
 
@@ -66,8 +66,8 @@ function fastDemoBuild(options) {
66
66
  const { errors, warnings } = result;
67
67
  console.log(`\x1b[33m[${getHumanReadableHours()}]\x1b[0m ` +
68
68
  `Demo re-built with ${errors.length} error(s) and ` +
69
- ` ${warnings.length} warning(s) ` +
70
- `(in ${stats.endTime - stats.startTime} ms).`);
69
+ ` ${warnings.length} warning(s) `);
70
+ return;
71
71
  }
72
72
  console.log(`\x1b[32m[${getHumanReadableHours()}]\x1b[0m ` +
73
73
  "Demo built!");
@@ -77,8 +77,9 @@ function fastDemoBuild(options) {
77
77
 
78
78
  // Create a context for incremental builds
79
79
  esbuild.context({
80
- entryPoints: [path.join(__dirname, "../demo/full/scripts/index.jsx")],
80
+ entryPoints: [path.join(__dirname, "../demo/full/scripts/index.tsx")],
81
81
  bundle: true,
82
+ target: "es2017",
82
83
  minify,
83
84
  outfile: path.join(__dirname, "../demo/full/bundle.js"),
84
85
  plugins: [consolePlugin],
@@ -60,7 +60,7 @@ function generateFullDemo(options) {
60
60
 
61
61
  const webpackDemoConfig = {
62
62
  mode: isDevMode ? "development" : "production",
63
- entry: path.join(__dirname, "../demo/full/scripts/index.jsx"),
63
+ entry: path.join(__dirname, "../demo/full/scripts/index.tsx"),
64
64
  resolve: {
65
65
  extensions: [".ts", ".tsx", ".js", ".jsx", ".json"],
66
66
  },
@@ -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=4.0.0-beta.1
4
+ sonar.projectVersion=4.0.0-beta.2
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,
@@ -36,7 +36,7 @@ export default async function loadSession(
36
36
  session : MediaKeySession | ICustomMediaKeySession,
37
37
  sessionId : string
38
38
  ) : Promise<boolean> {
39
- log.info("Compat/DRM: Load persisted session", sessionId);
39
+ log.info("DRM: Load persisted session", sessionId);
40
40
  const isLoaded = await session.load(sessionId);
41
41
 
42
42
  if (!isLoaded || session.keyStatuses.size > 0) {
@@ -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
 
@@ -14,6 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
+ import config from "../../config";
17
18
  import log from "../../log";
18
19
  import Manifest, {
19
20
  Adaptation,
@@ -260,8 +261,7 @@ function getEstimateReference(
260
261
  const timeRanges = val.buffered;
261
262
  const bufferGap = getLeftSizeOfRange(timeRanges, position.last);
262
263
  const { representation } = val.content;
263
- const scoreData = scoreCalculator.getEstimate(representation);
264
- const currentScore = scoreData?.[0];
264
+ const currentScore = scoreCalculator.getEstimate(representation);
265
265
  const currentBitrate = representation.bitrate;
266
266
  const observation = { bufferGap, currentBitrate, currentScore, speed };
267
267
  currentBufferBasedEstimate = bufferBasedChooser.getEstimate(observation);
@@ -307,11 +307,14 @@ function getEstimateReference(
307
307
  lastPlaybackObservation.speed :
308
308
  1);
309
309
 
310
- if (allowBufferBasedEstimates && bufferGap <= 5) {
310
+ const { ABR_ENTER_BUFFER_BASED_ALGO,
311
+ ABR_EXIT_BUFFER_BASED_ALGO } = config.getCurrent();
312
+
313
+ if (allowBufferBasedEstimates && bufferGap <= ABR_EXIT_BUFFER_BASED_ALGO) {
311
314
  allowBufferBasedEstimates = false;
312
315
  } else if (!allowBufferBasedEstimates &&
313
316
  isFinite(bufferGap) &&
314
- bufferGap > 10)
317
+ bufferGap >= ABR_ENTER_BUFFER_BASED_ALGO)
315
318
  {
316
319
  allowBufferBasedEstimates = true;
317
320
  }