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.
- package/.eslintrc.js +0 -4
- package/CHANGELOG.md +5 -2
- package/VERSION +1 -1
- package/dist/_esm5.processed/compat/eme/close_session.js +1 -2
- package/dist/_esm5.processed/compat/eme/custom_key_system_access.d.ts +15 -0
- package/dist/_esm5.processed/compat/eme/custom_key_system_access.js +1 -17
- package/dist/_esm5.processed/compat/eme/custom_media_keys/ie11_media_keys.js +6 -7
- package/dist/_esm5.processed/compat/eme/custom_media_keys/index.js +3 -4
- package/dist/_esm5.processed/compat/eme/custom_media_keys/old_webkit_media_keys.js +20 -17
- package/dist/_esm5.processed/compat/eme/custom_media_keys/webkit_media_keys.js +29 -14
- package/dist/_esm5.processed/compat/eme/generate_key_request.d.ts +4 -6
- package/dist/_esm5.processed/compat/eme/generate_key_request.js +4 -6
- package/dist/_esm5.processed/compat/eme/load_session.js +1 -2
- package/dist/_esm5.processed/config.d.ts +0 -3
- package/dist/_esm5.processed/core/api/option_utils.d.ts +3 -2
- package/dist/_esm5.processed/core/api/option_utils.js +2 -1
- package/dist/_esm5.processed/core/api/public_api.js +3 -4
- package/dist/_esm5.processed/core/decrypt/attach_media_keys.js +1 -2
- package/dist/_esm5.processed/core/decrypt/clear_on_stop.js +1 -2
- package/dist/_esm5.processed/core/decrypt/content_decryptor.js +12 -5
- package/dist/_esm5.processed/core/decrypt/create_or_load_session.js +1 -1
- package/dist/_esm5.processed/core/decrypt/create_session.d.ts +3 -1
- package/dist/_esm5.processed/core/decrypt/create_session.js +16 -7
- package/dist/_esm5.processed/core/decrypt/find_key_system.js +1 -2
- package/dist/_esm5.processed/core/decrypt/utils/clean_old_loaded_sessions.js +1 -2
- package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.d.ts +94 -1
- package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.js +238 -98
- package/dist/_esm5.processed/core/fetchers/manifest/manifest_fetcher.js +1 -3
- package/dist/_esm5.processed/core/fetchers/utils/try_urls_with_backoff.js +2 -3
- package/dist/_esm5.processed/core/init/initialize_media_source.d.ts +2 -1
- package/dist/_esm5.processed/core/stream/index.d.ts +1 -0
- package/dist/_esm5.processed/core/stream/period/get_adaptation_switch_strategy.d.ts +15 -11
- package/dist/_esm5.processed/core/stream/period/get_adaptation_switch_strategy.js +5 -2
- package/dist/_esm5.processed/core/stream/period/index.d.ts +1 -0
- package/dist/_esm5.processed/core/stream/period/period_stream.d.ts +3 -11
- package/dist/_esm5.processed/core/stream/representation/append_segment_to_buffer.js +4 -3
- package/dist/_esm5.processed/default_config.d.ts +0 -27
- package/dist/_esm5.processed/default_config.js +0 -27
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/thumbnail_loader.js +5 -6
- package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/api/index.js +2 -3
- package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/api/probeMediaConfiguration.d.ts +15 -0
- package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/api/probeMediaConfiguration.js +1 -2
- package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/probers/DRMInfos.js +2 -3
- package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/probers/HDCPPolicy.js +2 -3
- package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/probers/decodingInfo.js +1 -2
- package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/probers/mediaContentType.js +1 -2
- package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/probers/mediaContentTypeWithFeatures/index.js +1 -2
- package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/probers/mediaDisplayInfos.js +1 -2
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.js +4 -5
- package/dist/_esm5.processed/public_types.d.ts +1 -0
- package/dist/_esm5.processed/transports/dash/add_segment_integrity_checks_to_loader.js +1 -2
- package/dist/_esm5.processed/transports/dash/image_pipelines.d.ts +4 -3
- package/dist/_esm5.processed/transports/dash/image_pipelines.js +57 -11
- package/dist/_esm5.processed/transports/dash/init_segment_loader.js +1 -2
- package/dist/_esm5.processed/transports/dash/manifest_parser.js +2 -3
- package/dist/_esm5.processed/transports/dash/segment_loader.d.ts +1 -1
- package/dist/_esm5.processed/transports/dash/segment_loader.js +3 -4
- package/dist/_esm5.processed/transports/dash/text_loader.js +1 -2
- package/dist/_esm5.processed/transports/local/segment_loader.js +2 -3
- package/dist/_esm5.processed/transports/metaplaylist/pipelines.js +2 -3
- package/dist/_esm5.processed/transports/smooth/pipelines.js +3 -4
- package/dist/_esm5.processed/transports/smooth/segment_loader.js +3 -4
- package/dist/_esm5.processed/transports/utils/call_custom_manifest_loader.js +1 -2
- package/dist/_esm5.processed/utils/cancellable_sleep.js +1 -2
- package/dist/_esm5.processed/utils/cast_to_observable.js +1 -3
- package/dist/_esm5.processed/utils/request/xhr.js +1 -2
- package/dist/rx-player.js +851 -937
- package/dist/rx-player.min.js +1 -1
- package/package.json +1 -2
- package/scripts/update-version +2 -2
- package/sonar-project.properties +1 -1
- package/src/compat/__tests__/play.test.ts +2 -4
- package/src/compat/eme/close_session.ts +1 -2
- package/src/compat/eme/custom_key_system_access.ts +1 -2
- package/src/compat/eme/custom_media_keys/ie11_media_keys.ts +6 -7
- package/src/compat/eme/custom_media_keys/index.ts +3 -4
- package/src/compat/eme/custom_media_keys/old_webkit_media_keys.ts +21 -18
- package/src/compat/eme/custom_media_keys/webkit_media_keys.ts +28 -16
- package/src/compat/eme/generate_key_request.ts +4 -6
- package/src/compat/eme/load_session.ts +1 -2
- package/src/core/api/__tests__/option_utils.test.ts +12 -0
- package/src/core/api/option_utils.ts +5 -3
- package/src/core/api/public_api.ts +3 -4
- package/src/core/decrypt/attach_media_keys.ts +1 -2
- package/src/core/decrypt/clear_on_stop.ts +1 -2
- package/src/core/decrypt/content_decryptor.ts +16 -6
- package/src/core/decrypt/create_or_load_session.ts +4 -1
- package/src/core/decrypt/create_session.ts +25 -12
- package/src/core/decrypt/find_key_system.ts +1 -2
- package/src/core/decrypt/utils/clean_old_loaded_sessions.ts +1 -2
- package/src/core/decrypt/utils/loaded_sessions_store.ts +256 -105
- package/src/core/fetchers/manifest/manifest_fetcher.ts +1 -3
- package/src/core/fetchers/utils/try_urls_with_backoff.ts +2 -3
- package/src/core/init/initialize_media_source.ts +2 -1
- package/src/core/stream/index.ts +1 -0
- package/src/core/stream/period/get_adaptation_switch_strategy.ts +24 -14
- package/src/core/stream/period/index.ts +1 -0
- package/src/core/stream/period/period_stream.ts +5 -14
- package/src/core/stream/representation/append_segment_to_buffer.ts +17 -13
- package/src/default_config.ts +0 -30
- package/src/experimental/tools/VideoThumbnailLoader/thumbnail_loader.ts +5 -6
- package/src/experimental/tools/mediaCapabilitiesProber/__tests__/probers/HDCPPolicy.test.ts +5 -6
- package/src/experimental/tools/mediaCapabilitiesProber/__tests__/probers/decodingInfos.test.ts +2 -4
- package/src/experimental/tools/mediaCapabilitiesProber/api/index.ts +2 -3
- package/src/experimental/tools/mediaCapabilitiesProber/api/probeMediaConfiguration.ts +1 -2
- package/src/experimental/tools/mediaCapabilitiesProber/probers/DRMInfos.ts +2 -3
- package/src/experimental/tools/mediaCapabilitiesProber/probers/HDCPPolicy.ts +2 -3
- package/src/experimental/tools/mediaCapabilitiesProber/probers/decodingInfo.ts +1 -2
- package/src/experimental/tools/mediaCapabilitiesProber/probers/mediaContentType.ts +1 -2
- package/src/experimental/tools/mediaCapabilitiesProber/probers/mediaContentTypeWithFeatures/index.ts +1 -2
- package/src/experimental/tools/mediaCapabilitiesProber/probers/mediaDisplayInfos.ts +1 -2
- package/src/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.ts +4 -5
- package/src/public_types.ts +1 -0
- package/src/transports/dash/add_segment_integrity_checks_to_loader.ts +1 -2
- package/src/transports/dash/image_pipelines.ts +12 -14
- package/src/transports/dash/init_segment_loader.ts +1 -2
- package/src/transports/dash/manifest_parser.ts +2 -3
- package/src/transports/dash/segment_loader.ts +4 -5
- package/src/transports/dash/text_loader.ts +2 -3
- package/src/transports/local/segment_loader.ts +2 -3
- package/src/transports/metaplaylist/pipelines.ts +2 -3
- package/src/transports/smooth/pipelines.ts +4 -5
- package/src/transports/smooth/segment_loader.ts +5 -6
- package/src/transports/utils/call_custom_manifest_loader.ts +1 -2
- package/src/utils/cancellable_sleep.ts +1 -2
- package/src/utils/cast_to_observable.ts +0 -2
- package/src/utils/request/xhr.ts +1 -2
- package/tsconfig.json +0 -1
- package/tsconfig.modules.json +0 -1
- package/dist/_esm5.processed/utils/promise.d.ts +0 -17
- package/dist/_esm5.processed/utils/promise.js +0 -18
- package/src/typings/pinkie.d.ts +0 -19
- package/src/utils/__tests__/promise.test.ts +0 -23
- 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
|
|
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}
|
|
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({
|
|
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 {
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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.
|
|
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.
|
|
180
|
+
log.error("DRM-LSS: generateRequest error. No MediaKeySession found with " +
|
|
153
181
|
"the given initData and initDataType");
|
|
154
|
-
return [2 /*return*/,
|
|
182
|
+
return [2 /*return*/, generateKeyRequest(mediaKeySession, initializationDataType, initializationData)];
|
|
155
183
|
}
|
|
156
|
-
|
|
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 [
|
|
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
|
|
198
|
-
return [4 /*yield*/,
|
|
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
|
|
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
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 ?
|
|
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
|
}));
|