rx-player 3.27.0-dev.20220317 → 3.27.0-dev.2022032800

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 (134) hide show
  1. package/.eslintrc.js +0 -4
  2. package/CHANGELOG.md +5 -2
  3. package/VERSION +1 -1
  4. package/dist/_esm5.processed/compat/eme/close_session.js +1 -2
  5. package/dist/_esm5.processed/compat/eme/custom_key_system_access.d.ts +15 -0
  6. package/dist/_esm5.processed/compat/eme/custom_key_system_access.js +1 -17
  7. package/dist/_esm5.processed/compat/eme/custom_media_keys/ie11_media_keys.js +6 -7
  8. package/dist/_esm5.processed/compat/eme/custom_media_keys/index.js +3 -4
  9. package/dist/_esm5.processed/compat/eme/custom_media_keys/old_webkit_media_keys.js +20 -17
  10. package/dist/_esm5.processed/compat/eme/custom_media_keys/webkit_media_keys.js +29 -14
  11. package/dist/_esm5.processed/compat/eme/generate_key_request.d.ts +4 -6
  12. package/dist/_esm5.processed/compat/eme/generate_key_request.js +4 -6
  13. package/dist/_esm5.processed/compat/eme/load_session.js +1 -2
  14. package/dist/_esm5.processed/config.d.ts +0 -3
  15. package/dist/_esm5.processed/core/api/option_utils.d.ts +3 -2
  16. package/dist/_esm5.processed/core/api/option_utils.js +2 -1
  17. package/dist/_esm5.processed/core/api/public_api.js +3 -4
  18. package/dist/_esm5.processed/core/decrypt/attach_media_keys.js +1 -2
  19. package/dist/_esm5.processed/core/decrypt/clear_on_stop.js +1 -2
  20. package/dist/_esm5.processed/core/decrypt/content_decryptor.js +12 -5
  21. package/dist/_esm5.processed/core/decrypt/create_or_load_session.js +1 -1
  22. package/dist/_esm5.processed/core/decrypt/create_session.d.ts +3 -1
  23. package/dist/_esm5.processed/core/decrypt/create_session.js +16 -7
  24. package/dist/_esm5.processed/core/decrypt/find_key_system.js +1 -2
  25. package/dist/_esm5.processed/core/decrypt/utils/clean_old_loaded_sessions.js +1 -2
  26. package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.d.ts +94 -1
  27. package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.js +238 -98
  28. package/dist/_esm5.processed/core/fetchers/manifest/manifest_fetcher.js +1 -3
  29. package/dist/_esm5.processed/core/fetchers/utils/try_urls_with_backoff.js +2 -3
  30. package/dist/_esm5.processed/core/init/initialize_media_source.d.ts +2 -1
  31. package/dist/_esm5.processed/core/stream/index.d.ts +1 -0
  32. package/dist/_esm5.processed/core/stream/period/get_adaptation_switch_strategy.d.ts +15 -11
  33. package/dist/_esm5.processed/core/stream/period/get_adaptation_switch_strategy.js +5 -2
  34. package/dist/_esm5.processed/core/stream/period/index.d.ts +1 -0
  35. package/dist/_esm5.processed/core/stream/period/period_stream.d.ts +3 -11
  36. package/dist/_esm5.processed/core/stream/representation/append_segment_to_buffer.js +4 -3
  37. package/dist/_esm5.processed/default_config.d.ts +0 -27
  38. package/dist/_esm5.processed/default_config.js +0 -27
  39. package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/thumbnail_loader.js +5 -6
  40. package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/api/index.js +2 -3
  41. package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/api/probeMediaConfiguration.d.ts +15 -0
  42. package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/api/probeMediaConfiguration.js +1 -2
  43. package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/probers/DRMInfos.js +2 -3
  44. package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/probers/HDCPPolicy.js +2 -3
  45. package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/probers/decodingInfo.js +1 -2
  46. package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/probers/mediaContentType.js +1 -2
  47. package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/probers/mediaContentTypeWithFeatures/index.js +1 -2
  48. package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/probers/mediaDisplayInfos.js +1 -2
  49. package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.js +4 -5
  50. package/dist/_esm5.processed/public_types.d.ts +1 -0
  51. package/dist/_esm5.processed/transports/dash/add_segment_integrity_checks_to_loader.js +1 -2
  52. package/dist/_esm5.processed/transports/dash/image_pipelines.d.ts +4 -3
  53. package/dist/_esm5.processed/transports/dash/image_pipelines.js +57 -11
  54. package/dist/_esm5.processed/transports/dash/init_segment_loader.js +1 -2
  55. package/dist/_esm5.processed/transports/dash/manifest_parser.js +2 -3
  56. package/dist/_esm5.processed/transports/dash/segment_loader.d.ts +1 -1
  57. package/dist/_esm5.processed/transports/dash/segment_loader.js +3 -4
  58. package/dist/_esm5.processed/transports/dash/text_loader.js +1 -2
  59. package/dist/_esm5.processed/transports/local/segment_loader.js +2 -3
  60. package/dist/_esm5.processed/transports/metaplaylist/pipelines.js +2 -3
  61. package/dist/_esm5.processed/transports/smooth/pipelines.js +3 -4
  62. package/dist/_esm5.processed/transports/smooth/segment_loader.js +3 -4
  63. package/dist/_esm5.processed/transports/utils/call_custom_manifest_loader.js +1 -2
  64. package/dist/_esm5.processed/utils/cancellable_sleep.js +1 -2
  65. package/dist/_esm5.processed/utils/cast_to_observable.js +1 -3
  66. package/dist/_esm5.processed/utils/request/xhr.js +1 -2
  67. package/dist/rx-player.js +851 -937
  68. package/dist/rx-player.min.js +1 -1
  69. package/package.json +1 -2
  70. package/scripts/update-version +2 -2
  71. package/sonar-project.properties +1 -1
  72. package/src/compat/__tests__/play.test.ts +2 -4
  73. package/src/compat/eme/close_session.ts +1 -2
  74. package/src/compat/eme/custom_key_system_access.ts +1 -2
  75. package/src/compat/eme/custom_media_keys/ie11_media_keys.ts +6 -7
  76. package/src/compat/eme/custom_media_keys/index.ts +3 -4
  77. package/src/compat/eme/custom_media_keys/old_webkit_media_keys.ts +21 -18
  78. package/src/compat/eme/custom_media_keys/webkit_media_keys.ts +28 -16
  79. package/src/compat/eme/generate_key_request.ts +4 -6
  80. package/src/compat/eme/load_session.ts +1 -2
  81. package/src/core/api/__tests__/option_utils.test.ts +12 -0
  82. package/src/core/api/option_utils.ts +5 -3
  83. package/src/core/api/public_api.ts +3 -4
  84. package/src/core/decrypt/attach_media_keys.ts +1 -2
  85. package/src/core/decrypt/clear_on_stop.ts +1 -2
  86. package/src/core/decrypt/content_decryptor.ts +16 -6
  87. package/src/core/decrypt/create_or_load_session.ts +4 -1
  88. package/src/core/decrypt/create_session.ts +25 -12
  89. package/src/core/decrypt/find_key_system.ts +1 -2
  90. package/src/core/decrypt/utils/clean_old_loaded_sessions.ts +1 -2
  91. package/src/core/decrypt/utils/loaded_sessions_store.ts +256 -105
  92. package/src/core/fetchers/manifest/manifest_fetcher.ts +1 -3
  93. package/src/core/fetchers/utils/try_urls_with_backoff.ts +2 -3
  94. package/src/core/init/initialize_media_source.ts +2 -1
  95. package/src/core/stream/index.ts +1 -0
  96. package/src/core/stream/period/get_adaptation_switch_strategy.ts +24 -14
  97. package/src/core/stream/period/index.ts +1 -0
  98. package/src/core/stream/period/period_stream.ts +5 -14
  99. package/src/core/stream/representation/append_segment_to_buffer.ts +17 -13
  100. package/src/default_config.ts +0 -30
  101. package/src/experimental/tools/VideoThumbnailLoader/thumbnail_loader.ts +5 -6
  102. package/src/experimental/tools/mediaCapabilitiesProber/__tests__/probers/HDCPPolicy.test.ts +5 -6
  103. package/src/experimental/tools/mediaCapabilitiesProber/__tests__/probers/decodingInfos.test.ts +2 -4
  104. package/src/experimental/tools/mediaCapabilitiesProber/api/index.ts +2 -3
  105. package/src/experimental/tools/mediaCapabilitiesProber/api/probeMediaConfiguration.ts +1 -2
  106. package/src/experimental/tools/mediaCapabilitiesProber/probers/DRMInfos.ts +2 -3
  107. package/src/experimental/tools/mediaCapabilitiesProber/probers/HDCPPolicy.ts +2 -3
  108. package/src/experimental/tools/mediaCapabilitiesProber/probers/decodingInfo.ts +1 -2
  109. package/src/experimental/tools/mediaCapabilitiesProber/probers/mediaContentType.ts +1 -2
  110. package/src/experimental/tools/mediaCapabilitiesProber/probers/mediaContentTypeWithFeatures/index.ts +1 -2
  111. package/src/experimental/tools/mediaCapabilitiesProber/probers/mediaDisplayInfos.ts +1 -2
  112. package/src/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.ts +4 -5
  113. package/src/public_types.ts +1 -0
  114. package/src/transports/dash/add_segment_integrity_checks_to_loader.ts +1 -2
  115. package/src/transports/dash/image_pipelines.ts +12 -14
  116. package/src/transports/dash/init_segment_loader.ts +1 -2
  117. package/src/transports/dash/manifest_parser.ts +2 -3
  118. package/src/transports/dash/segment_loader.ts +4 -5
  119. package/src/transports/dash/text_loader.ts +2 -3
  120. package/src/transports/local/segment_loader.ts +2 -3
  121. package/src/transports/metaplaylist/pipelines.ts +2 -3
  122. package/src/transports/smooth/pipelines.ts +4 -5
  123. package/src/transports/smooth/segment_loader.ts +5 -6
  124. package/src/transports/utils/call_custom_manifest_loader.ts +1 -2
  125. package/src/utils/cancellable_sleep.ts +1 -2
  126. package/src/utils/cast_to_observable.ts +0 -2
  127. package/src/utils/request/xhr.ts +1 -2
  128. package/tsconfig.json +0 -1
  129. package/tsconfig.modules.json +0 -1
  130. package/dist/_esm5.processed/utils/promise.d.ts +0 -17
  131. package/dist/_esm5.processed/utils/promise.js +0 -18
  132. package/src/typings/pinkie.d.ts +0 -19
  133. package/src/utils/__tests__/promise.test.ts +0 -23
  134. package/src/utils/promise.ts +0 -20
@@ -13,6 +13,17 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
+ var __assign = (this && this.__assign) || function () {
17
+ __assign = Object.assign || function(t) {
18
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
19
+ s = arguments[i];
20
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
21
+ t[p] = s[p];
22
+ }
23
+ return t;
24
+ };
25
+ return __assign.apply(this, arguments);
26
+ };
16
27
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
17
28
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
18
29
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -49,10 +60,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
49
60
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
50
61
  }
51
62
  };
52
- import PPromise from "pinkie";
53
- import { closeSession, } from "../../../compat";
54
- import { onKeyMessage$, onKeyStatusesChange$, } from "../../../compat/event_listeners";
55
- import config from "../../../config";
63
+ import { closeSession, generateKeyRequest, loadSession, } from "../../../compat";
56
64
  import log from "../../../log";
57
65
  import isNullOrUndefined from "../../../utils/is_null_or_undefined";
58
66
  import KeySessionRecord from "./key_session_record";
@@ -76,7 +84,7 @@ var LoadedSessionsStore = /** @class */ (function () {
76
84
  }
77
85
  /**
78
86
  * Create a new MediaKeySession and store it in this store.
79
- * @param {Object} initializationData
87
+ * @param {Object} initData
80
88
  * @param {string} sessionType
81
89
  * @returns {Object}
82
90
  */
@@ -84,7 +92,9 @@ var LoadedSessionsStore = /** @class */ (function () {
84
92
  var _this = this;
85
93
  var keySessionRecord = new KeySessionRecord(initData);
86
94
  var mediaKeySession = this._mediaKeys.createSession(sessionType);
87
- var entry = { mediaKeySession: mediaKeySession, sessionType: sessionType, keySessionRecord: keySessionRecord };
95
+ var entry = { mediaKeySession: mediaKeySession, sessionType: sessionType, keySessionRecord: keySessionRecord, isGeneratingRequest: false,
96
+ isLoadingPersistentSession: false,
97
+ closingStatus: { type: "none" } };
88
98
  if (!isNullOrUndefined(mediaKeySession.closed)) {
89
99
  mediaKeySession.closed
90
100
  .then(function () {
@@ -100,7 +110,7 @@ var LoadedSessionsStore = /** @class */ (function () {
100
110
  });
101
111
  }
102
112
  log.debug("DRM-LSS: Add MediaKeySession", entry.sessionType);
103
- this._storage.push({ keySessionRecord: keySessionRecord, mediaKeySession: mediaKeySession, sessionType: sessionType });
113
+ this._storage.push(__assign({}, entry));
104
114
  return entry;
105
115
  };
106
116
  /**
@@ -121,23 +131,41 @@ var LoadedSessionsStore = /** @class */ (function () {
121
131
  if (stored.keySessionRecord.isCompatibleWith(initializationData)) {
122
132
  this._storage.splice(i, 1);
123
133
  this._storage.push(stored);
124
- return { keySessionRecord: stored.keySessionRecord,
125
- mediaKeySession: stored.mediaKeySession,
126
- sessionType: stored.sessionType };
134
+ return __assign({}, stored);
127
135
  }
128
136
  }
129
137
  return null;
130
138
  };
131
139
  /**
132
- * Close a MediaKeySession and remove its related stored information from the
140
+ * Get `LoadedSessionsStore`'s entry for a given MediaKeySession.
141
+ * Returns `null` if the given MediaKeySession is not stored in the
133
142
  * `LoadedSessionsStore`.
134
- * Emit when done.
143
+ * @param {MediaKeySession} mediaKeySession
144
+ * @returns {Object|null}
145
+ */
146
+ LoadedSessionsStore.prototype.getEntryForSession = function (mediaKeySession) {
147
+ for (var i = this._storage.length - 1; i >= 0; i--) {
148
+ var stored = this._storage[i];
149
+ if (stored.mediaKeySession === mediaKeySession) {
150
+ return __assign({}, stored);
151
+ }
152
+ }
153
+ return null;
154
+ };
155
+ /**
156
+ * Generate a license request on the given MediaKeySession, while indicating
157
+ * to the LoadedSessionsStore that a license-request is pending so
158
+ * session-closing orders are properly scheduled after it is done.
135
159
  * @param {Object} mediaKeySession
160
+ * @param {string} initializationDataType - Initialization data type given
161
+ * e.g. by the "encrypted" event for the corresponding request.
162
+ * @param {Uint8Array} initializationData - Initialization data given e.g. by
163
+ * the "encrypted" event for the corresponding request.
136
164
  * @returns {Promise}
137
165
  */
138
- LoadedSessionsStore.prototype.closeSession = function (mediaKeySession) {
166
+ LoadedSessionsStore.prototype.generateLicenseRequest = function (mediaKeySession, initializationDataType, initializationData) {
139
167
  return __awaiter(this, void 0, void 0, function () {
140
- var entry, _i, _a, stored;
168
+ var entry, _i, _a, stored, err_1;
141
169
  return __generator(this, function (_b) {
142
170
  switch (_b.label) {
143
171
  case 0:
@@ -149,18 +177,132 @@ var LoadedSessionsStore = /** @class */ (function () {
149
177
  }
150
178
  }
151
179
  if (entry === undefined) {
152
- log.warn("DRM-LSS: No MediaKeySession found with " +
180
+ log.error("DRM-LSS: generateRequest error. No MediaKeySession found with " +
153
181
  "the given initData and initDataType");
154
- return [2 /*return*/, PPromise.resolve(false)];
182
+ return [2 /*return*/, generateKeyRequest(mediaKeySession, initializationDataType, initializationData)];
155
183
  }
156
- return [4 /*yield*/, safelyCloseMediaKeySession(entry.mediaKeySession)];
184
+ entry.isGeneratingRequest = true;
185
+ // Note the `as string` is needed due to TypeScript not understanding that
186
+ // the `closingStatus` might change in the next checks
187
+ if (entry.closingStatus.type !== "none") {
188
+ throw new Error("The `MediaKeySession` is being closed.");
189
+ }
190
+ _b.label = 1;
157
191
  case 1:
192
+ _b.trys.push([1, 3, , 4]);
193
+ return [4 /*yield*/, generateKeyRequest(mediaKeySession, initializationDataType, initializationData)];
194
+ case 2:
158
195
  _b.sent();
159
- return [2 /*return*/, PPromise.resolve(true)];
196
+ return [3 /*break*/, 4];
197
+ case 3:
198
+ err_1 = _b.sent();
199
+ if (entry === undefined) {
200
+ throw err_1;
201
+ }
202
+ entry.isGeneratingRequest = false;
203
+ if (entry.closingStatus.type === "awaiting") {
204
+ entry.closingStatus.start();
205
+ }
206
+ throw err_1;
207
+ case 4:
208
+ if (entry === undefined) {
209
+ return [2 /*return*/, undefined];
210
+ }
211
+ entry.isGeneratingRequest = false;
212
+ if (entry.closingStatus.type === "awaiting") {
213
+ entry.closingStatus.start();
214
+ }
215
+ return [2 /*return*/];
160
216
  }
161
217
  });
162
218
  });
163
219
  };
220
+ /**
221
+ * @param {Object} mediaKeySession
222
+ * @param {string} sessionId
223
+ * @returns {Promise}
224
+ */
225
+ LoadedSessionsStore.prototype.loadPersistentSession = function (mediaKeySession, sessionId) {
226
+ return __awaiter(this, void 0, void 0, function () {
227
+ var entry, _i, _a, stored, ret, err_2;
228
+ return __generator(this, function (_b) {
229
+ switch (_b.label) {
230
+ case 0:
231
+ for (_i = 0, _a = this._storage; _i < _a.length; _i++) {
232
+ stored = _a[_i];
233
+ if (stored.mediaKeySession === mediaKeySession) {
234
+ entry = stored;
235
+ break;
236
+ }
237
+ }
238
+ if (entry === undefined) {
239
+ log.error("DRM-LSS: loadPersistentSession error. No MediaKeySession found with " +
240
+ "the given initData and initDataType");
241
+ return [2 /*return*/, loadSession(mediaKeySession, sessionId)];
242
+ }
243
+ entry.isLoadingPersistentSession = true;
244
+ // Note the `as string` is needed due to TypeScript not understanding that
245
+ // the `closingStatus` might change in the next checks
246
+ if (entry.closingStatus.type !== "none") {
247
+ throw new Error("The `MediaKeySession` is being closed.");
248
+ }
249
+ _b.label = 1;
250
+ case 1:
251
+ _b.trys.push([1, 3, , 4]);
252
+ return [4 /*yield*/, loadSession(mediaKeySession, sessionId)];
253
+ case 2:
254
+ ret = _b.sent();
255
+ return [3 /*break*/, 4];
256
+ case 3:
257
+ err_2 = _b.sent();
258
+ if (entry === undefined) {
259
+ throw err_2;
260
+ }
261
+ entry.isLoadingPersistentSession = false;
262
+ if (entry.closingStatus.type === "awaiting") {
263
+ entry.closingStatus.start();
264
+ }
265
+ throw err_2;
266
+ case 4:
267
+ if (entry === undefined) {
268
+ return [2 /*return*/, ret];
269
+ }
270
+ entry.isLoadingPersistentSession = false;
271
+ if (entry.closingStatus.type === "awaiting") {
272
+ entry.closingStatus.start();
273
+ }
274
+ return [2 /*return*/, ret];
275
+ }
276
+ });
277
+ });
278
+ };
279
+ /**
280
+ * Close a MediaKeySession and remove its related stored information from the
281
+ * `LoadedSessionsStore`.
282
+ * Emit when done.
283
+ * @param {Object} mediaKeySession
284
+ * @returns {Promise}
285
+ */
286
+ LoadedSessionsStore.prototype.closeSession = function (mediaKeySession) {
287
+ return __awaiter(this, void 0, void 0, function () {
288
+ var entry, _i, _a, stored;
289
+ return __generator(this, function (_b) {
290
+ for (_i = 0, _a = this._storage; _i < _a.length; _i++) {
291
+ stored = _a[_i];
292
+ if (stored.mediaKeySession === mediaKeySession) {
293
+ entry = stored;
294
+ break;
295
+ }
296
+ }
297
+ if (entry === undefined) {
298
+ log.warn("DRM-LSS: No MediaKeySession found with " +
299
+ "the given initData and initDataType");
300
+ return [2 /*return*/, Promise.resolve(false)];
301
+ }
302
+ return [2 /*return*/, this._closeEntry(entry)];
303
+ });
304
+ });
305
+ };
164
306
  /**
165
307
  * Returns the number of stored MediaKeySessions in this LoadedSessionsStore.
166
308
  * @returns {number}
@@ -184,6 +326,7 @@ var LoadedSessionsStore = /** @class */ (function () {
184
326
  LoadedSessionsStore.prototype.closeAllSessions = function () {
185
327
  return __awaiter(this, void 0, void 0, function () {
186
328
  var allEntries, closingProms;
329
+ var _this = this;
187
330
  return __generator(this, function (_a) {
188
331
  switch (_a.label) {
189
332
  case 0:
@@ -194,8 +337,8 @@ var LoadedSessionsStore = /** @class */ (function () {
194
337
  // process of removing
195
338
  this._storage = [];
196
339
  closingProms = allEntries
197
- .map(function (entry) { return safelyCloseMediaKeySession(entry.mediaKeySession); });
198
- return [4 /*yield*/, PPromise.all(closingProms)];
340
+ .map(function (entry) { return _this._closeEntry(entry); });
341
+ return [4 /*yield*/, Promise.all(closingProms)];
199
342
  case 1:
200
343
  _a.sent();
201
344
  return [2 /*return*/];
@@ -203,6 +346,13 @@ var LoadedSessionsStore = /** @class */ (function () {
203
346
  });
204
347
  });
205
348
  };
349
+ /**
350
+ * Get the index of a stored MediaKeySession entry based on its
351
+ * `KeySessionRecord`.
352
+ * Returns -1 if not found.
353
+ * @param {Object} record
354
+ * @returns {number}
355
+ */
206
356
  LoadedSessionsStore.prototype.getIndex = function (record) {
207
357
  for (var i = 0; i < this._storage.length; i++) {
208
358
  var stored = this._storage[i];
@@ -212,92 +362,82 @@ var LoadedSessionsStore = /** @class */ (function () {
212
362
  }
213
363
  return -1;
214
364
  };
365
+ /**
366
+ * Prepare the closure of a `MediaKeySession` stored as an entry of the
367
+ * `LoadedSessionsStore`.
368
+ * Allows to postpone the closure action if another MediaKeySession action
369
+ * is already pending.
370
+ * @param {Object} entry
371
+ * @returns {Promise.<boolean>}
372
+ */
373
+ LoadedSessionsStore.prototype._closeEntry = function (entry) {
374
+ return __awaiter(this, void 0, void 0, function () {
375
+ var mediaKeySession;
376
+ return __generator(this, function (_a) {
377
+ mediaKeySession = entry.mediaKeySession;
378
+ return [2 /*return*/, new Promise(function (resolve, reject) {
379
+ if (entry !== undefined &&
380
+ (entry.isLoadingPersistentSession || entry.isGeneratingRequest)) {
381
+ entry.closingStatus = { type: "awaiting",
382
+ start: tryClosingEntryAndResolve };
383
+ }
384
+ else {
385
+ tryClosingEntryAndResolve();
386
+ }
387
+ function tryClosingEntryAndResolve() {
388
+ if (entry !== undefined) {
389
+ entry.closingStatus = { type: "pending" };
390
+ }
391
+ safelyCloseMediaKeySession(mediaKeySession)
392
+ .then(function () {
393
+ if (entry !== undefined) {
394
+ entry.closingStatus = { type: "done" };
395
+ }
396
+ resolve(true);
397
+ })
398
+ .catch(function (err) {
399
+ if (entry !== undefined) {
400
+ entry.closingStatus = { type: "failed" };
401
+ }
402
+ reject(err);
403
+ });
404
+ }
405
+ })];
406
+ });
407
+ });
408
+ };
215
409
  return LoadedSessionsStore;
216
410
  }());
217
411
  export default LoadedSessionsStore;
218
412
  /**
219
- * Close a MediaKeySession with multiple attempts if needed and do not throw if
220
- * this action throws an error.
413
+ * Close a MediaKeySession and just log an error if it fails (while resolving).
221
414
  * Emits then complete when done.
222
415
  * @param {MediaKeySession} mediaKeySession
223
416
  * @returns {Observable}
224
417
  */
225
418
  function safelyCloseMediaKeySession(mediaKeySession) {
226
- return recursivelyTryToCloseMediaKeySession(0);
227
- /**
228
- * Perform a new attempt at closing the MediaKeySession.
229
- * If this operation fails due to a not-"callable" (an EME term)
230
- * MediaKeySession, retry based on either a timer or on MediaKeySession
231
- * events, whichever comes first.
232
- * Emits then complete when done.
233
- * @param {number} retryNb - The attempt number starting at 0.
234
- * @returns {Observable}
235
- */
236
- function recursivelyTryToCloseMediaKeySession(retryNb) {
237
- return __awaiter(this, void 0, void 0, function () {
238
- var err_1, _a, EME_SESSION_CLOSING_MAX_RETRY, EME_SESSION_CLOSING_INITIAL_DELAY, EME_SESSION_CLOSING_MAX_DELAY, nextRetryNb, delay_1, ksChangeSub_1, ksChangeProm, ksMsgSub_1, ksMsgProm, sleepTimer_1, sleepProm;
239
- return __generator(this, function (_b) {
240
- switch (_b.label) {
241
- case 0:
242
- log.debug("DRM: Trying to close a MediaKeySession", mediaKeySession.sessionId, retryNb);
243
- _b.label = 1;
244
- case 1:
245
- _b.trys.push([1, 3, , 5]);
246
- return [4 /*yield*/, closeSession(mediaKeySession)];
247
- case 2:
248
- _b.sent();
249
- log.debug("DRM: Succeeded to close MediaKeySession");
250
- return [2 /*return*/, undefined];
251
- case 3:
252
- err_1 = _b.sent();
253
- // Unitialized MediaKeySession may not close properly until their
254
- // corresponding `generateRequest` or `load` call are handled by the
255
- // browser.
256
- // In that case the EME specification tells us that the browser is
257
- // supposed to reject the `close` call with an InvalidStateError.
258
- if (!(err_1 instanceof Error) || err_1.name !== "InvalidStateError" ||
259
- mediaKeySession.sessionId !== "") {
260
- return [2 /*return*/, failToCloseSession(err_1)];
261
- }
262
- _a = config.getCurrent(), EME_SESSION_CLOSING_MAX_RETRY = _a.EME_SESSION_CLOSING_MAX_RETRY, EME_SESSION_CLOSING_INITIAL_DELAY = _a.EME_SESSION_CLOSING_INITIAL_DELAY, EME_SESSION_CLOSING_MAX_DELAY = _a.EME_SESSION_CLOSING_MAX_DELAY;
263
- nextRetryNb = retryNb + 1;
264
- if (nextRetryNb > EME_SESSION_CLOSING_MAX_RETRY) {
265
- return [2 /*return*/, failToCloseSession(err_1)];
266
- }
267
- delay_1 = Math.min(Math.pow(2, retryNb) * EME_SESSION_CLOSING_INITIAL_DELAY, EME_SESSION_CLOSING_MAX_DELAY);
268
- log.warn("DRM: attempt to close a mediaKeySession failed, " +
269
- "scheduling retry...", delay_1);
270
- ksChangeProm = new Promise(function (res) {
271
- ksChangeSub_1 = onKeyStatusesChange$(mediaKeySession).subscribe(res);
272
- });
273
- ksMsgProm = new Promise(function (res) {
274
- ksMsgSub_1 = onKeyMessage$(mediaKeySession).subscribe(res);
275
- });
276
- sleepProm = new Promise(function (res) {
277
- sleepTimer_1 = window.setTimeout(res, delay_1);
278
- });
279
- return [4 /*yield*/, PPromise.race([ksChangeProm, ksMsgProm, sleepProm])];
280
- case 4:
281
- _b.sent();
282
- ksChangeSub_1 === null || ksChangeSub_1 === void 0 ? void 0 : ksChangeSub_1.unsubscribe();
283
- ksMsgSub_1 === null || ksMsgSub_1 === void 0 ? void 0 : ksMsgSub_1.unsubscribe();
284
- clearTimeout(sleepTimer_1);
285
- return [2 /*return*/, recursivelyTryToCloseMediaKeySession(nextRetryNb)];
286
- case 5: return [2 /*return*/];
287
- }
288
- });
419
+ return __awaiter(this, void 0, void 0, function () {
420
+ var err_3;
421
+ return __generator(this, function (_a) {
422
+ switch (_a.label) {
423
+ case 0:
424
+ log.debug("DRM: Trying to close a MediaKeySession", mediaKeySession.sessionId);
425
+ _a.label = 1;
426
+ case 1:
427
+ _a.trys.push([1, 3, , 4]);
428
+ return [4 /*yield*/, closeSession(mediaKeySession)];
429
+ case 2:
430
+ _a.sent();
431
+ log.debug("DRM: Succeeded to close MediaKeySession");
432
+ return [2 /*return*/];
433
+ case 3:
434
+ err_3 = _a.sent();
435
+ log.error("DRM: Could not close MediaKeySession: " +
436
+ (err_3 instanceof Error ? err_3.toString() :
437
+ "Unknown error"));
438
+ return [2 /*return*/];
439
+ case 4: return [2 /*return*/];
440
+ }
289
441
  });
290
- }
291
- /**
292
- * Log error anouncing that we could not close the MediaKeySession and emits
293
- * then complete through Observable.
294
- * TODO Emit warning?
295
- * @returns {Observable}
296
- */
297
- function failToCloseSession(err) {
298
- log.error("DRM: Could not close MediaKeySession: " +
299
- (err instanceof Error ? err.toString() :
300
- "Unknown error"));
301
- return PPromise.resolve(null);
302
- }
442
+ });
303
443
  }
@@ -54,7 +54,6 @@ import config from "../../../config";
54
54
  import { formatError, } from "../../../errors";
55
55
  import log from "../../../log";
56
56
  import assert from "../../../utils/assert";
57
- import PPromise from "../../../utils/promise";
58
57
  import TaskCanceller from "../../../utils/task_canceller";
59
58
  import errorSelector from "../utils/error_selector";
60
59
  import { tryRequestPromiseWithBackoff, } from "../utils/try_urls_with_backoff";
@@ -337,6 +336,5 @@ export default ManifestFetcher;
337
336
  * @returns {boolean}
338
337
  */
339
338
  function isPromise(val) {
340
- return val instanceof PPromise ||
341
- val instanceof Promise;
339
+ return val instanceof Promise;
342
340
  }
@@ -54,7 +54,6 @@ import { CustomLoaderError, isKnownError, NetworkErrorTypes, RequestError, } fro
54
54
  import log from "../../../log";
55
55
  import cancellableSleep from "../../../utils/cancellable_sleep";
56
56
  import getFuzzedDelay from "../../../utils/get_fuzzed_delay";
57
- import PPromise from "../../../utils/promise";
58
57
  import TaskCanceller from "../../../utils/task_canceller";
59
58
  /**
60
59
  * Called on a loader error.
@@ -159,7 +158,7 @@ function getRequestErrorType(error) {
159
158
  */
160
159
  export function tryURLsWithBackoff(urls, performRequest, options, cancellationSignal) {
161
160
  if (cancellationSignal.isCancelled) {
162
- return PPromise.reject(cancellationSignal.cancellationError);
161
+ return Promise.reject(cancellationSignal.cancellationError);
163
162
  }
164
163
  var baseDelay = options.baseDelay, maxDelay = options.maxDelay, maxRetryRegular = options.maxRetryRegular, maxRetryOffline = options.maxRetryOffline, onRetry = options.onRetry;
165
164
  var retryCount = 0;
@@ -167,7 +166,7 @@ export function tryURLsWithBackoff(urls, performRequest, options, cancellationSi
167
166
  var urlsToTry = urls.slice();
168
167
  if (urlsToTry.length === 0) {
169
168
  log.warn("Fetchers: no URL given to `tryURLsWithBackoff`.");
170
- return PPromise.reject(new Error("No URL to request"));
169
+ return Promise.reject(new Error("No URL to request"));
171
170
  }
172
171
  return tryURLsRecursively(urlsToTry[0], 0);
173
172
  /**
@@ -20,6 +20,7 @@ import { PlaybackObserver } from "../api";
20
20
  import { IKeySystemOption } from "../decrypt";
21
21
  import { IManifestFetcherParsedResult, IManifestFetcherWarningEvent, ManifestFetcher, SegmentFetcherCreator } from "../fetchers";
22
22
  import { ITextTrackSegmentBufferOptions } from "../segment_buffers";
23
+ import { IAudioTrackSwitchingMode } from "../stream";
23
24
  import { IInitialTimeOptions } from "./get_initial_time";
24
25
  import { IInitEvent } from "./types";
25
26
  /** Arguments to give to the `InitializeOnMediaSource` function. */
@@ -46,7 +47,7 @@ export interface IInitializeArguments {
46
47
  */
47
48
  enableFastSwitching: boolean;
48
49
  /** Strategy when switching of audio track. */
49
- audioTrackSwitchingMode: "seamless" | "direct";
50
+ audioTrackSwitchingMode: IAudioTrackSwitchingMode;
50
51
  /** Behavior when a new video and/or audio codec is encountered. */
51
52
  onCodecSwitch: "continue" | "reload";
52
53
  };
@@ -14,6 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import StreamOrchestrator, { IStreamOrchestratorOptions, IStreamOrchestratorPlaybackObservation } from "./orchestrator";
17
+ export { IAudioTrackSwitchingMode } from "./period";
17
18
  export * from "./types";
18
19
  export default StreamOrchestrator;
19
20
  export { IStreamOrchestratorPlaybackObservation, IStreamOrchestratorOptions, };
@@ -35,20 +35,24 @@ export declare type IAdaptationSwitchStrategy = {
35
35
  value: undefined;
36
36
  };
37
37
  export interface IAdaptationSwitchOptions {
38
- /**
39
- * Strategy to adopt when manually switching of audio adaptation.
40
- * Can be either:
41
- * - "seamless": transitions are smooth but could be not immediate.
42
- * - "direct": strategy will be "smart", if the mimetype and the codec,
43
- * change, we will perform a hard reload of the media source, however, if it
44
- * doesn't change, we will just perform a small flush by removing buffered range
45
- * and performing, a small seek on the media element.
46
- * Transitions are faster, but, we could see appear a reloading or seeking state.
47
- */
48
- audioTrackSwitchingMode: "seamless" | "direct";
38
+ /** RxPlayer's behavior when switching the audio track. */
39
+ audioTrackSwitchingMode: IAudioTrackSwitchingMode;
49
40
  /** Behavior when a new video and/or audio codec is encountered. */
50
41
  onCodecSwitch: "continue" | "reload";
51
42
  }
43
+ /**
44
+ * Strategy to adopt when manually switching of audio adaptation.
45
+ * Can be either:
46
+ * - "seamless": transitions are smooth but could be not immediate.
47
+ * - "direct": strategy will be "smart", if the mimetype and the codec,
48
+ * change, we will perform a hard reload of the media source, however, if it
49
+ * doesn't change, we will just perform a small flush by removing buffered range
50
+ * and performing, a small seek on the media element.
51
+ * Transitions are faster, but, we could see appear a BUFFERING state.
52
+ * - "reload": completely reload the content. This allows a direct switch
53
+ * compatible with most device but may necessitate a RELOADING phase.
54
+ */
55
+ export declare type IAudioTrackSwitchingMode = "seamless" | "direct" | "reload";
52
56
  /**
53
57
  * Find out what to do when switching Adaptation, based on the current
54
58
  * situation.
@@ -62,7 +62,10 @@ export default function getAdaptationSwitchStrategy(segmentBuffer, period, adapt
62
62
  return { type: "continue", value: undefined };
63
63
  }
64
64
  var currentTime = playbackInfo.currentTime;
65
- if (adaptation.type === "video" &&
65
+ var audioTrackSwitchingMode = options.audioTrackSwitchingMode;
66
+ var hasReloadSwitchingMode = adaptation.type === "video" ||
67
+ (adaptation.type === "audio" && audioTrackSwitchingMode === "reload");
68
+ if (hasReloadSwitchingMode &&
66
69
  // We're playing the current Period
67
70
  isTimeInRange({ start: start, end: end }, currentTime) &&
68
71
  // There is data for the current position or the codecs are differents
@@ -74,7 +77,7 @@ export default function getAdaptationSwitchStrategy(segmentBuffer, period, adapt
74
77
  }
75
78
  // From here, clean-up data from the previous Adaptation, if one
76
79
  var shouldFlush = adaptation.type === "audio" &&
77
- options.audioTrackSwitchingMode === "direct";
80
+ audioTrackSwitchingMode === "direct";
78
81
  var rangesToExclude = [];
79
82
  // First, we don't want to accidentally remove some segments from the previous
80
83
  // Period (which overlap a little with this one)
@@ -14,5 +14,6 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import PeriodStream, { IPeriodStreamArguments, IPeriodStreamOptions, IPeriodStreamPlaybackObservation } from "./period_stream";
17
+ export { IAudioTrackSwitchingMode } from "./get_adaptation_switch_strategy";
17
18
  export default PeriodStream;
18
19
  export { IPeriodStreamArguments, IPeriodStreamOptions, IPeriodStreamPlaybackObservation, };
@@ -23,6 +23,7 @@ import { SegmentFetcherCreator } from "../../fetchers";
23
23
  import SegmentBuffersStore, { IBufferType, ITextTrackSegmentBufferOptions, SegmentBuffer } from "../../segment_buffers";
24
24
  import { IAdaptationStreamOptions } from "../adaptation";
25
25
  import { IPeriodStreamEvent } from "../types";
26
+ import { IAudioTrackSwitchingMode } from "./get_adaptation_switch_strategy";
26
27
  /** Playback observation required by the `PeriodStream`. */
27
28
  export interface IPeriodStreamPlaybackObservation {
28
29
  /** The position we are in the video in seconds at the time of the observation. */
@@ -64,17 +65,8 @@ export interface IPeriodStreamArguments {
64
65
  }
65
66
  /** Options tweaking the behavior of the PeriodStream. */
66
67
  export declare type IPeriodStreamOptions = IAdaptationStreamOptions & {
67
- /**
68
- * Strategy to adopt when manually switching of audio adaptation.
69
- * Can be either:
70
- * - "seamless": transitions are smooth but could be not immediate.
71
- * - "direct": strategy will be "smart", if the mimetype and the codec,
72
- * change, we will perform a hard reload of the media source, however, if it
73
- * doesn't change, we will just perform a small flush by removing buffered range
74
- * and performing, a small seek on the media element.
75
- * Transitions are faster, but, we could see appear a reloading or seeking state.
76
- */
77
- audioTrackSwitchingMode: "seamless" | "direct";
68
+ /** RxPlayer's behavior when switching the audio track. */
69
+ audioTrackSwitchingMode: IAudioTrackSwitchingMode;
78
70
  /** Behavior when a new video and/or audio codec is encountered. */
79
71
  onCodecSwitch: "continue" | "reload";
80
72
  /** Options specific to the text SegmentBuffer. */
@@ -16,7 +16,7 @@
16
16
  /**
17
17
  * This file allows any Stream to push data to a SegmentBuffer.
18
18
  */
19
- import { catchError, concat as observableConcat, mergeMap, ignoreElements, } from "rxjs";
19
+ import { catchError, concat as observableConcat, mergeMap, ignoreElements, take, } from "rxjs";
20
20
  import { MediaError } from "../../../errors";
21
21
  import forceGarbageCollection from "./force_garbage_collection";
22
22
  /**
@@ -38,10 +38,11 @@ export default function appendSegmentToBuffer(playbackObserver, segmentBuffer, d
38
38
  "An unknown error happened when pushing content";
39
39
  throw new MediaError("BUFFER_APPEND_ERROR", reason);
40
40
  }
41
- return playbackObserver.observe(true).pipe(mergeMap(function (observation) {
41
+ return playbackObserver.observe(true).pipe(take(1), mergeMap(function (observation) {
42
42
  var currentPos = observation.position + observation.wantedTimeOffset;
43
43
  return observableConcat(forceGarbageCollection(currentPos, segmentBuffer).pipe(ignoreElements()), append$).pipe(catchError(function (forcedGCError) {
44
- var reason = forcedGCError instanceof Error ? forcedGCError.toString() :
44
+ var reason = forcedGCError instanceof Error ?
45
+ forcedGCError.toString() :
45
46
  "Could not clean the buffer";
46
47
  throw new MediaError("BUFFER_FULL_ERROR", reason);
47
48
  }));