rx-player 3.29.0-dev.2022091600 → 3.29.0-dev.2022103100
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/CHANGELOG.md +22 -10
- package/MAINTAINERS.md +2 -1
- package/VERSION +1 -1
- package/dist/_esm5.processed/compat/browser_detection.d.ts +4 -1
- package/dist/_esm5.processed/compat/browser_detection.js +7 -1
- package/dist/_esm5.processed/compat/can_reuse_media_keys.d.ts +12 -0
- package/dist/_esm5.processed/compat/can_reuse_media_keys.js +15 -0
- package/dist/_esm5.processed/compat/enable_audio_track.d.ts +11 -0
- package/dist/_esm5.processed/compat/enable_audio_track.js +26 -0
- package/dist/_esm5.processed/compat/index.d.ts +4 -2
- package/dist/_esm5.processed/compat/index.js +4 -2
- package/dist/_esm5.processed/compat/{should_renew_media_keys.d.ts → should_renew_media_key_system_access.d.ts} +3 -3
- package/dist/_esm5.processed/compat/{should_renew_media_keys.js → should_renew_media_key_system_access.js} +3 -3
- package/dist/_esm5.processed/config.d.ts +1 -0
- package/dist/_esm5.processed/core/api/playback_observer.d.ts +14 -5
- package/dist/_esm5.processed/core/api/playback_observer.js +54 -22
- package/dist/_esm5.processed/core/api/public_api.d.ts +7 -4
- package/dist/_esm5.processed/core/api/public_api.js +79 -61
- package/dist/_esm5.processed/core/api/tracks_management/media_element_track_choice_manager.js +9 -10
- package/dist/_esm5.processed/core/decrypt/__tests__/__global__/utils.js +1 -1
- package/dist/_esm5.processed/core/decrypt/find_key_system.js +3 -3
- package/dist/_esm5.processed/core/decrypt/get_media_keys.js +4 -1
- package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.d.ts +98 -0
- package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.js +173 -0
- package/dist/_esm5.processed/core/fetchers/manifest/manifest_fetcher.js +4 -4
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.d.ts +2 -1
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.js +15 -16
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher_creator.d.ts +3 -1
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher_creator.js +5 -2
- package/dist/_esm5.processed/core/fetchers/utils/schedule_request.d.ts +103 -0
- package/dist/_esm5.processed/core/fetchers/utils/schedule_request.js +414 -0
- package/dist/_esm5.processed/core/init/content_time_boundaries_observer.d.ts +4 -3
- package/dist/_esm5.processed/core/init/content_time_boundaries_observer.js +21 -22
- package/dist/_esm5.processed/core/init/initialize_media_source.d.ts +18 -4
- package/dist/_esm5.processed/core/init/initialize_media_source.js +10 -2
- package/dist/_esm5.processed/core/init/load_on_media_source.js +7 -1
- package/dist/_esm5.processed/core/init/stall_avoider.js +3 -1
- package/dist/_esm5.processed/default_config.d.ts +11 -0
- package/dist/_esm5.processed/default_config.js +11 -0
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +1 -1
- package/dist/_esm5.processed/manifest/manifest.js +11 -2
- package/dist/_esm5.processed/manifest/representation.d.ts +12 -1
- package/dist/_esm5.processed/manifest/representation.js +1 -0
- package/dist/_esm5.processed/manifest/representation_index/static.d.ts +1 -1
- package/dist/_esm5.processed/manifest/representation_index/static.js +2 -2
- package/dist/_esm5.processed/manifest/representation_index/types.d.ts +32 -15
- package/dist/_esm5.processed/manifest/update_period_in_place.js +1 -0
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/base.d.ts +10 -9
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/base.js +11 -11
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/get_init_segment.d.ts +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/get_init_segment.js +3 -3
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/get_segments_from_timeline.d.ts +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/get_segments_from_timeline.js +4 -4
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/list.d.ts +7 -7
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/list.js +12 -8
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/template.d.ts +5 -6
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/template.js +16 -16
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.d.ts +11 -10
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.js +14 -13
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/tokens.d.ts +3 -4
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/tokens.js +4 -12
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_mpd.js +2 -4
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_representation_index.js +1 -3
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_representations.js +6 -2
- package/dist/_esm5.processed/parsers/manifest/dash/common/resolve_base_urls.d.ts +1 -2
- package/dist/_esm5.processed/parsers/manifest/dash/common/resolve_base_urls.js +3 -8
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/node_parsers/BaseURL.d.ts +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/node_parsers/BaseURL.js +2 -20
- package/dist/_esm5.processed/parsers/manifest/dash/node_parser_types.d.ts +0 -6
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/generators/BaseURL.js +0 -11
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/types.d.ts +5 -1
- package/dist/_esm5.processed/parsers/manifest/local/parse_local_manifest.js +2 -1
- package/dist/_esm5.processed/parsers/manifest/local/representation_index.js +2 -2
- package/dist/_esm5.processed/parsers/manifest/metaplaylist/metaplaylist_parser.js +7 -1
- package/dist/_esm5.processed/parsers/manifest/smooth/create_parser.js +17 -11
- package/dist/_esm5.processed/parsers/manifest/smooth/representation_index.js +2 -2
- package/dist/_esm5.processed/parsers/manifest/types.d.ts +24 -0
- package/dist/_esm5.processed/parsers/texttracks/ttml/html/apply_extent.js +8 -1
- package/dist/_esm5.processed/parsers/texttracks/ttml/html/apply_origin.js +9 -1
- package/dist/_esm5.processed/parsers/texttracks/ttml/html/create_element.js +2 -1
- package/dist/_esm5.processed/transports/dash/construct_segment_url.d.ts +18 -0
- package/dist/_esm5.processed/transports/dash/construct_segment_url.js +21 -0
- package/dist/_esm5.processed/transports/dash/image_pipelines.d.ts +3 -2
- package/dist/_esm5.processed/transports/dash/image_pipelines.js +5 -3
- package/dist/_esm5.processed/transports/dash/segment_loader.js +4 -2
- package/dist/_esm5.processed/transports/dash/text_loader.js +4 -2
- package/dist/_esm5.processed/transports/dash/text_parser.js +3 -1
- package/dist/_esm5.processed/transports/local/segment_loader.d.ts +3 -2
- package/dist/_esm5.processed/transports/local/segment_loader.js +2 -2
- package/dist/_esm5.processed/transports/metaplaylist/pipelines.js +8 -8
- package/dist/_esm5.processed/transports/smooth/pipelines.js +11 -7
- package/dist/_esm5.processed/transports/smooth/utils.d.ts +4 -2
- package/dist/_esm5.processed/transports/smooth/utils.js +7 -1
- package/dist/_esm5.processed/transports/types.d.ts +5 -3
- package/dist/_esm5.processed/utils/event_emitter.d.ts +1 -2
- package/dist/_esm5.processed/utils/resolve_url.d.ts +7 -4
- package/dist/_esm5.processed/utils/resolve_url.js +11 -8
- package/dist/mpd-parser.wasm +0 -0
- package/dist/rx-player.js +5656 -13236
- package/dist/rx-player.min.js +1 -1
- package/jest.config.js +28 -23
- package/package.json +29 -29
- package/sonar-project.properties +1 -1
- package/src/compat/__tests__/can_reuse_media_keys.test.ts +54 -0
- package/src/compat/__tests__/enable_audio_track.test.ts +341 -0
- package/src/compat/__tests__/{should_renew_media_keys.test.ts → should_renew_media_key_system_access.test.ts} +7 -5
- package/src/compat/browser_detection.ts +10 -0
- package/src/compat/can_reuse_media_keys.ts +19 -0
- package/src/compat/enable_audio_track.ts +33 -0
- package/src/compat/index.ts +6 -2
- package/src/compat/{should_renew_media_keys.ts → should_renew_media_key_system_access.ts} +3 -3
- package/src/core/api/playback_observer.ts +97 -33
- package/src/core/api/public_api.ts +126 -74
- package/src/core/api/tracks_management/media_element_track_choice_manager.ts +3 -11
- package/src/core/decrypt/__tests__/__global__/media_keys.test.ts +182 -0
- package/src/core/decrypt/__tests__/__global__/utils.ts +2 -0
- package/src/core/decrypt/find_key_system.ts +3 -3
- package/src/core/decrypt/get_media_keys.ts +5 -1
- package/src/core/fetchers/cdn_prioritizer.ts +198 -0
- package/src/core/fetchers/manifest/manifest_fetcher.ts +7 -11
- package/src/core/fetchers/segment/segment_fetcher.ts +12 -10
- package/src/core/fetchers/segment/segment_fetcher_creator.ts +10 -1
- package/src/core/fetchers/utils/schedule_request.ts +482 -0
- package/src/core/init/content_time_boundaries_observer.ts +12 -12
- package/src/core/init/initialize_media_source.ts +31 -4
- package/src/core/init/load_on_media_source.ts +11 -2
- package/src/core/init/stall_avoider.ts +4 -1
- package/src/core/stream/orchestrator/stream_orchestrator.ts +0 -1
- package/src/default_config.ts +12 -0
- package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +1 -0
- package/src/manifest/manifest.ts +11 -2
- package/src/manifest/representation.ts +15 -0
- package/src/manifest/representation_index/__tests__/static.test.ts +1 -1
- package/src/manifest/representation_index/static.ts +3 -3
- package/src/manifest/representation_index/types.ts +33 -15
- package/src/manifest/update_period_in_place.ts +1 -0
- package/src/parsers/manifest/dash/common/indexes/base.ts +22 -23
- package/src/parsers/manifest/dash/common/indexes/get_init_segment.ts +6 -4
- package/src/parsers/manifest/dash/common/indexes/get_segments_from_timeline.ts +5 -5
- package/src/parsers/manifest/dash/common/indexes/list.ts +19 -20
- package/src/parsers/manifest/dash/common/indexes/template.ts +23 -27
- package/src/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.ts +25 -23
- package/src/parsers/manifest/dash/common/indexes/tokens.ts +7 -18
- package/src/parsers/manifest/dash/common/parse_mpd.ts +2 -4
- package/src/parsers/manifest/dash/common/parse_representation_index.ts +1 -6
- package/src/parsers/manifest/dash/common/parse_representations.ts +9 -0
- package/src/parsers/manifest/dash/common/resolve_base_urls.ts +5 -9
- package/src/parsers/manifest/dash/js-parser/node_parsers/BaseURL.ts +2 -29
- package/src/parsers/manifest/dash/js-parser/node_parsers/__tests__/AdaptationSet.test.ts +7 -11
- package/src/parsers/manifest/dash/node_parser_types.ts +0 -7
- package/src/parsers/manifest/dash/wasm-parser/rs/events.rs +3 -1
- package/src/parsers/manifest/dash/wasm-parser/rs/processor/attributes.rs +1 -8
- package/src/parsers/manifest/dash/wasm-parser/ts/generators/BaseURL.ts +0 -13
- package/src/parsers/manifest/dash/wasm-parser/ts/types.ts +8 -0
- package/src/parsers/manifest/local/parse_local_manifest.ts +1 -0
- package/src/parsers/manifest/local/representation_index.ts +2 -2
- package/src/parsers/manifest/metaplaylist/metaplaylist_parser.ts +7 -1
- package/src/parsers/manifest/smooth/create_parser.ts +17 -13
- package/src/parsers/manifest/smooth/representation_index.ts +2 -2
- package/src/parsers/manifest/types.ts +26 -1
- package/src/parsers/manifest/utils/__tests__/get_first_time_from_adaptations.test.ts +15 -0
- package/src/parsers/manifest/utils/__tests__/get_last_time_from_adaptation.test.ts +15 -0
- package/src/parsers/texttracks/ttml/html/apply_extent.ts +8 -1
- package/src/parsers/texttracks/ttml/html/apply_origin.ts +9 -1
- package/src/parsers/texttracks/ttml/html/create_element.ts +2 -2
- package/src/transports/dash/construct_segment_url.ts +28 -0
- package/src/transports/dash/image_pipelines.ts +5 -2
- package/src/transports/dash/segment_loader.ts +5 -2
- package/src/transports/dash/text_loader.ts +5 -2
- package/src/transports/dash/text_parser.ts +3 -1
- package/src/transports/local/segment_loader.ts +3 -2
- package/src/transports/metaplaylist/pipelines.ts +28 -9
- package/src/transports/smooth/pipelines.ts +12 -6
- package/src/transports/smooth/utils.ts +13 -1
- package/src/transports/types.ts +6 -3
- package/src/utils/__tests__/event_emitter.test.ts +72 -67
- package/src/utils/__tests__/initialization_segment_cache.test.ts +7 -7
- package/src/utils/__tests__/resolve_url.test.ts +27 -23
- package/src/utils/event_emitter.ts +1 -3
- package/src/utils/resolve_url.ts +11 -8
- package/dist/_esm5.processed/core/fetchers/utils/try_urls_with_backoff.d.ts +0 -85
- package/dist/_esm5.processed/core/fetchers/utils/try_urls_with_backoff.js +0 -264
- package/dummy +0 -1
- package/src/core/fetchers/utils/try_urls_with_backoff.ts +0 -287
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
import {
|
|
26
26
|
MediaKeysImpl,
|
|
27
|
+
MediaKeySystemAccessImpl,
|
|
27
28
|
mockCompat,
|
|
28
29
|
testContentDecryptorError,
|
|
29
30
|
} from "./utils";
|
|
@@ -104,6 +105,8 @@ describe("core - decrypt - global tests - media key system access", () => {
|
|
|
104
105
|
/* eslint-enable max-len */
|
|
105
106
|
return new Promise<void>((res, rej) => {
|
|
106
107
|
mockCompat({});
|
|
108
|
+
const mockCreateMediaKeys = jest.spyOn(MediaKeySystemAccessImpl.prototype,
|
|
109
|
+
"createMediaKeys");
|
|
107
110
|
const { ContentDecryptorState } = jest.requireActual("../../content_decryptor");
|
|
108
111
|
const ContentDecryptor = jest.requireActual("../../content_decryptor").default;
|
|
109
112
|
const contentDecryptor = new ContentDecryptor(videoElt, ksConfig);
|
|
@@ -112,6 +115,7 @@ describe("core - decrypt - global tests - media key system access", () => {
|
|
|
112
115
|
receivedStateChange++;
|
|
113
116
|
try {
|
|
114
117
|
expect(newState).toEqual(ContentDecryptorState.WaitingForAttachment);
|
|
118
|
+
expect(mockCreateMediaKeys).toHaveBeenCalledTimes(1);
|
|
115
119
|
} catch (err) { rej(err); }
|
|
116
120
|
setTimeout(() => {
|
|
117
121
|
try {
|
|
@@ -126,6 +130,184 @@ describe("core - decrypt - global tests - media key system access", () => {
|
|
|
126
130
|
});
|
|
127
131
|
});
|
|
128
132
|
|
|
133
|
+
/* eslint-disable max-len */
|
|
134
|
+
it("should not call createMediaKeys again if previous one is compatible", () => {
|
|
135
|
+
/* eslint-enable max-len */
|
|
136
|
+
return new Promise<void>((res, rej) => {
|
|
137
|
+
mockCompat({});
|
|
138
|
+
const mockCreateMediaKeys = jest.spyOn(MediaKeySystemAccessImpl.prototype,
|
|
139
|
+
"createMediaKeys");
|
|
140
|
+
const { ContentDecryptorState } = jest.requireActual("../../content_decryptor");
|
|
141
|
+
const ContentDecryptor = jest.requireActual("../../content_decryptor").default;
|
|
142
|
+
|
|
143
|
+
const contentDecryptor1 = new ContentDecryptor(videoElt, ksConfig);
|
|
144
|
+
let receivedStateChange1 = 0;
|
|
145
|
+
contentDecryptor1.addEventListener("error", rej);
|
|
146
|
+
contentDecryptor1.addEventListener("stateChange", (state1: any) => {
|
|
147
|
+
receivedStateChange1++;
|
|
148
|
+
try {
|
|
149
|
+
if (receivedStateChange1 === 2) {
|
|
150
|
+
expect(state1).toEqual(ContentDecryptorState.ReadyForContent);
|
|
151
|
+
return;
|
|
152
|
+
} else if (receivedStateChange1 !== 1) {
|
|
153
|
+
throw new Error("Unexpected stateChange event.");
|
|
154
|
+
}
|
|
155
|
+
expect(state1).toEqual(ContentDecryptorState.WaitingForAttachment);
|
|
156
|
+
expect(mockCreateMediaKeys).toHaveBeenCalledTimes(1);
|
|
157
|
+
contentDecryptor1.attach();
|
|
158
|
+
} catch (err) { rej(err); }
|
|
159
|
+
|
|
160
|
+
setTimeout(() => {
|
|
161
|
+
contentDecryptor1.dispose();
|
|
162
|
+
const contentDecryptor2 = new ContentDecryptor(videoElt, ksConfig);
|
|
163
|
+
let receivedStateChange2 = 0;
|
|
164
|
+
contentDecryptor2.addEventListener("error", rej);
|
|
165
|
+
contentDecryptor2.addEventListener("stateChange", (state2: any) => {
|
|
166
|
+
receivedStateChange2++;
|
|
167
|
+
try {
|
|
168
|
+
if (receivedStateChange2 === 2) {
|
|
169
|
+
expect(state2).toEqual(ContentDecryptorState.ReadyForContent);
|
|
170
|
+
return;
|
|
171
|
+
} else if (receivedStateChange2 !== 1) {
|
|
172
|
+
throw new Error("Unexpected stateChange event.");
|
|
173
|
+
}
|
|
174
|
+
expect(state2).toEqual(ContentDecryptorState.WaitingForAttachment);
|
|
175
|
+
expect(mockCreateMediaKeys).toHaveBeenCalledTimes(1);
|
|
176
|
+
contentDecryptor2.attach();
|
|
177
|
+
setTimeout(() => {
|
|
178
|
+
try {
|
|
179
|
+
contentDecryptor2.dispose();
|
|
180
|
+
expect(mockCreateMediaKeys).toHaveBeenCalledTimes(1);
|
|
181
|
+
res();
|
|
182
|
+
} catch (err) { rej(err); }
|
|
183
|
+
});
|
|
184
|
+
} catch (err) { rej(err); }
|
|
185
|
+
});
|
|
186
|
+
}, 10);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
/* eslint-disable max-len */
|
|
192
|
+
it("should call createMediaKeys again if the platform needs re-creation of the MediaKeys", () => {
|
|
193
|
+
/* eslint-enable max-len */
|
|
194
|
+
return new Promise<void>((res, rej) => {
|
|
195
|
+
mockCompat({
|
|
196
|
+
canReuseMediaKeys: jest.fn(() => false),
|
|
197
|
+
});
|
|
198
|
+
const mockCreateMediaKeys = jest.spyOn(MediaKeySystemAccessImpl.prototype,
|
|
199
|
+
"createMediaKeys");
|
|
200
|
+
const { ContentDecryptorState } = jest.requireActual("../../content_decryptor");
|
|
201
|
+
const ContentDecryptor = jest.requireActual("../../content_decryptor").default;
|
|
202
|
+
|
|
203
|
+
const contentDecryptor1 = new ContentDecryptor(videoElt, ksConfig);
|
|
204
|
+
let receivedStateChange1 = 0;
|
|
205
|
+
contentDecryptor1.addEventListener("error", rej);
|
|
206
|
+
contentDecryptor1.addEventListener("stateChange", (state1: any) => {
|
|
207
|
+
receivedStateChange1++;
|
|
208
|
+
try {
|
|
209
|
+
if (receivedStateChange1 === 2) {
|
|
210
|
+
expect(state1).toEqual(ContentDecryptorState.ReadyForContent);
|
|
211
|
+
return;
|
|
212
|
+
} else if (receivedStateChange1 !== 1) {
|
|
213
|
+
throw new Error("Unexpected stateChange event.");
|
|
214
|
+
}
|
|
215
|
+
expect(state1).toEqual(ContentDecryptorState.WaitingForAttachment);
|
|
216
|
+
expect(mockCreateMediaKeys).toHaveBeenCalledTimes(1);
|
|
217
|
+
contentDecryptor1.attach();
|
|
218
|
+
} catch (err) { rej(err); }
|
|
219
|
+
|
|
220
|
+
setTimeout(() => {
|
|
221
|
+
contentDecryptor1.dispose();
|
|
222
|
+
const contentDecryptor2 = new ContentDecryptor(videoElt, ksConfig);
|
|
223
|
+
let receivedStateChange2 = 0;
|
|
224
|
+
contentDecryptor2.addEventListener("error", rej);
|
|
225
|
+
contentDecryptor2.addEventListener("stateChange", (state2: any) => {
|
|
226
|
+
receivedStateChange2++;
|
|
227
|
+
try {
|
|
228
|
+
if (receivedStateChange2 === 2) {
|
|
229
|
+
expect(state2).toEqual(ContentDecryptorState.ReadyForContent);
|
|
230
|
+
return;
|
|
231
|
+
} else if (receivedStateChange2 !== 1) {
|
|
232
|
+
throw new Error("Unexpected stateChange event.");
|
|
233
|
+
}
|
|
234
|
+
expect(state2).toEqual(ContentDecryptorState.WaitingForAttachment);
|
|
235
|
+
expect(mockCreateMediaKeys).toHaveBeenCalledTimes(2);
|
|
236
|
+
contentDecryptor2.attach();
|
|
237
|
+
setTimeout(() => {
|
|
238
|
+
try {
|
|
239
|
+
contentDecryptor2.dispose();
|
|
240
|
+
expect(mockCreateMediaKeys).toHaveBeenCalledTimes(2);
|
|
241
|
+
res();
|
|
242
|
+
} catch (err) { rej(err); }
|
|
243
|
+
});
|
|
244
|
+
} catch (err) { rej(err); }
|
|
245
|
+
});
|
|
246
|
+
}, 10);
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
/* eslint-disable max-len */
|
|
252
|
+
it("should not call createMediaKeys again if the platform needs MediaKeySystemAccess renewal", () => {
|
|
253
|
+
/* eslint-enable max-len */
|
|
254
|
+
return new Promise<void>((res, rej) => {
|
|
255
|
+
mockCompat({
|
|
256
|
+
shouldRenewMediaKeySystemAccess: jest.fn(() => true),
|
|
257
|
+
});
|
|
258
|
+
const mockCreateMediaKeys = jest.spyOn(MediaKeySystemAccessImpl.prototype,
|
|
259
|
+
"createMediaKeys");
|
|
260
|
+
const { ContentDecryptorState } = jest.requireActual("../../content_decryptor");
|
|
261
|
+
const ContentDecryptor = jest.requireActual("../../content_decryptor").default;
|
|
262
|
+
|
|
263
|
+
const contentDecryptor1 = new ContentDecryptor(videoElt, ksConfig);
|
|
264
|
+
let receivedStateChange1 = 0;
|
|
265
|
+
contentDecryptor1.addEventListener("error", rej);
|
|
266
|
+
contentDecryptor1.addEventListener("stateChange", (state1: any) => {
|
|
267
|
+
receivedStateChange1++;
|
|
268
|
+
try {
|
|
269
|
+
if (receivedStateChange1 === 2) {
|
|
270
|
+
expect(state1).toEqual(ContentDecryptorState.ReadyForContent);
|
|
271
|
+
return;
|
|
272
|
+
} else if (receivedStateChange1 !== 1) {
|
|
273
|
+
throw new Error("Unexpected stateChange event.");
|
|
274
|
+
}
|
|
275
|
+
expect(state1).toEqual(ContentDecryptorState.WaitingForAttachment);
|
|
276
|
+
expect(mockCreateMediaKeys).toHaveBeenCalledTimes(1);
|
|
277
|
+
contentDecryptor1.attach();
|
|
278
|
+
} catch (err) { rej(err); }
|
|
279
|
+
|
|
280
|
+
setTimeout(() => {
|
|
281
|
+
contentDecryptor1.dispose();
|
|
282
|
+
const contentDecryptor2 = new ContentDecryptor(videoElt, ksConfig);
|
|
283
|
+
let receivedStateChange2 = 0;
|
|
284
|
+
contentDecryptor2.addEventListener("error", rej);
|
|
285
|
+
contentDecryptor2.addEventListener("stateChange", (state2: any) => {
|
|
286
|
+
receivedStateChange2++;
|
|
287
|
+
try {
|
|
288
|
+
if (receivedStateChange2 === 2) {
|
|
289
|
+
expect(state2).toEqual(ContentDecryptorState.ReadyForContent);
|
|
290
|
+
return;
|
|
291
|
+
} else if (receivedStateChange2 !== 1) {
|
|
292
|
+
throw new Error("Unexpected stateChange event.");
|
|
293
|
+
}
|
|
294
|
+
expect(state2).toEqual(ContentDecryptorState.WaitingForAttachment);
|
|
295
|
+
expect(mockCreateMediaKeys).toHaveBeenCalledTimes(2);
|
|
296
|
+
contentDecryptor2.attach();
|
|
297
|
+
setTimeout(() => {
|
|
298
|
+
try {
|
|
299
|
+
contentDecryptor2.dispose();
|
|
300
|
+
expect(mockCreateMediaKeys).toHaveBeenCalledTimes(2);
|
|
301
|
+
res();
|
|
302
|
+
} catch (err) { rej(err); }
|
|
303
|
+
});
|
|
304
|
+
} catch (err) { rej(err); }
|
|
305
|
+
});
|
|
306
|
+
}, 10);
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
|
|
129
311
|
/* eslint-disable max-len */
|
|
130
312
|
it("should not create any session if no encrypted event was received", (done) => {
|
|
131
313
|
/* eslint-enable max-len */
|
|
@@ -286,6 +286,8 @@ export function mockCompat(exportedFunctions = {}) {
|
|
|
286
286
|
setMediaKeys: mockSetMediaKeys,
|
|
287
287
|
getInitData: mockGetInitData,
|
|
288
288
|
generateKeyRequest: mockGenerateKeyRequest,
|
|
289
|
+
shouldRenewMediaKeySystemAccess: jest.fn(() => false),
|
|
290
|
+
canReuseMediaKeys: jest.fn(() => true),
|
|
289
291
|
...exportedFunctions }));
|
|
290
292
|
|
|
291
293
|
return { mockEvents,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import {
|
|
18
18
|
ICustomMediaKeySystemAccess,
|
|
19
19
|
requestMediaKeySystemAccess,
|
|
20
|
-
|
|
20
|
+
shouldRenewMediaKeySystemAccess,
|
|
21
21
|
} from "../../compat";
|
|
22
22
|
import config from "../../config";
|
|
23
23
|
import { EncryptedMediaError } from "../../errors";
|
|
@@ -74,7 +74,7 @@ function checkCachedMediaKeySystemAccess(
|
|
|
74
74
|
keySystemAccess: MediaKeySystemAccess|ICustomMediaKeySystemAccess;
|
|
75
75
|
} {
|
|
76
76
|
const mksConfiguration = currentKeySystemAccess.getConfiguration();
|
|
77
|
-
if (
|
|
77
|
+
if (shouldRenewMediaKeySystemAccess() || mksConfiguration == null) {
|
|
78
78
|
return null;
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -187,7 +187,7 @@ function buildKeySystemConfigurations(
|
|
|
187
187
|
// https://www.w3.org/TR/encrypted-media/#get-supported-configuration-and-consent
|
|
188
188
|
|
|
189
189
|
const videoCapabilities: IMediaCapability[] =
|
|
190
|
-
flatMap(
|
|
190
|
+
flatMap(videoRobustnesses, (robustness) =>
|
|
191
191
|
["video/mp4;codecs=\"avc1.4d401e\"",
|
|
192
192
|
"video/mp4;codecs=\"avc1.42e01e\"",
|
|
193
193
|
"video/webm;codecs=\"vp8\""].map(contentType => {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import {
|
|
18
|
+
canReuseMediaKeys,
|
|
18
19
|
ICustomMediaKeys,
|
|
19
20
|
ICustomMediaKeySystemAccess,
|
|
20
21
|
} from "../../compat";
|
|
@@ -95,7 +96,10 @@ export default async function getMediaKeysInfos(
|
|
|
95
96
|
const currentState = MediaKeysInfosStore.getState(mediaElement);
|
|
96
97
|
const persistentSessionsStore = createPersistentSessionsStorage(options);
|
|
97
98
|
|
|
98
|
-
if (
|
|
99
|
+
if (canReuseMediaKeys() &&
|
|
100
|
+
currentState !== null &&
|
|
101
|
+
evt.type === "reuse-media-key-system-access")
|
|
102
|
+
{
|
|
99
103
|
const { mediaKeys, loadedSessionsStore } = currentState;
|
|
100
104
|
|
|
101
105
|
// We might just rely on the currently attached MediaKeys instance.
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2015 CANAL+ Group
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import config from "../../config";
|
|
18
|
+
import { ICdnMetadata } from "../../parsers/manifest";
|
|
19
|
+
import { IPlayerError } from "../../public_types";
|
|
20
|
+
import arrayFindIndex from "../../utils/array_find_index";
|
|
21
|
+
import EventEmitter from "../../utils/event_emitter";
|
|
22
|
+
import { CancellationSignal } from "../../utils/task_canceller";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Class signaling the priority between multiple CDN available for any given
|
|
26
|
+
* resource.
|
|
27
|
+
*
|
|
28
|
+
* This class might perform requests and schedule timeouts by itself to keep its
|
|
29
|
+
* internal list of CDN priority up-to-date.
|
|
30
|
+
* When it is not needed anymore, you should call the `dispose` method to clear
|
|
31
|
+
* all resources.
|
|
32
|
+
*
|
|
33
|
+
* @class CdnPrioritizer
|
|
34
|
+
*/
|
|
35
|
+
export default class CdnPrioritizer extends EventEmitter<ICdnPrioritizerEvents> {
|
|
36
|
+
/**
|
|
37
|
+
* Structure keeping a list of CDN currently downgraded.
|
|
38
|
+
* Downgraded CDN immediately have a lower priority than any non-downgraded
|
|
39
|
+
* CDN for a specific amount of time.
|
|
40
|
+
*/
|
|
41
|
+
private _downgradedCdnList : {
|
|
42
|
+
/**
|
|
43
|
+
* Metadata of downgraded CDN, sorted by the time at which they have
|
|
44
|
+
* been downgraded.
|
|
45
|
+
*/
|
|
46
|
+
metadata : ICdnMetadata[];
|
|
47
|
+
/**
|
|
48
|
+
* Timeout ID (to give to `clearTimeout`) of elements in the `metadata`
|
|
49
|
+
* array, for the element at the same index in the `metadata` array.
|
|
50
|
+
*
|
|
51
|
+
* This structure has been writted as an object of two arrays of the same
|
|
52
|
+
* length, instead of an array of objects, to simplify the usage of the
|
|
53
|
+
* `metadata` array which is used considerably more than the `timeouts`
|
|
54
|
+
* array.
|
|
55
|
+
*/
|
|
56
|
+
timeouts : number[];
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param {Object} destroySignal
|
|
61
|
+
*/
|
|
62
|
+
constructor(destroySignal : CancellationSignal) {
|
|
63
|
+
super();
|
|
64
|
+
this._downgradedCdnList = { metadata: [], timeouts: [] };
|
|
65
|
+
destroySignal.register(() => {
|
|
66
|
+
for (const timeout of this._downgradedCdnList.timeouts) {
|
|
67
|
+
clearTimeout(timeout);
|
|
68
|
+
}
|
|
69
|
+
this._downgradedCdnList = { metadata: [], timeouts: [] };
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* From the list of __ALL__ CDNs available to a resource, return them in the
|
|
75
|
+
* order in which requests should be performed.
|
|
76
|
+
*
|
|
77
|
+
* Note: It is VERY important to include all CDN that are able to reach the
|
|
78
|
+
* wanted resource, even those which will in the end not be used anyway.
|
|
79
|
+
* If some CDN are not communicated, the `CdnPrioritizer` might wrongly
|
|
80
|
+
* consider that the current resource don't have any of the CDN prioritized
|
|
81
|
+
* internally and return other CDN which should have been forbidden if it knew
|
|
82
|
+
* about the other, non-used, ones.
|
|
83
|
+
*
|
|
84
|
+
* @param {Array.<string>} everyCdnForResource - Array of ALL available CDN
|
|
85
|
+
* able to reach the wanted resource - even those which might not be used in
|
|
86
|
+
* the end.
|
|
87
|
+
* @returns {Array.<Object>} - Array of CDN that can be tried to reach the
|
|
88
|
+
* resource, sorted by order of CDN preference, according to the
|
|
89
|
+
* `CdnPrioritizer`'s own list of priorities.
|
|
90
|
+
*/
|
|
91
|
+
public getCdnPreferenceForResource(
|
|
92
|
+
everyCdnForResource : ICdnMetadata[]
|
|
93
|
+
) : ICdnMetadata[] {
|
|
94
|
+
if (everyCdnForResource.length <= 1) {
|
|
95
|
+
// The huge majority of contents have only one CDN available.
|
|
96
|
+
// Here, prioritizing make no sense.
|
|
97
|
+
return everyCdnForResource;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return this._innerGetCdnPreferenceForResource(everyCdnForResource);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Limit usage of the CDN for a configured amount of time.
|
|
105
|
+
* Call this method if you encountered an issue with that CDN which leads you
|
|
106
|
+
* to want to prevent its usage currently.
|
|
107
|
+
*
|
|
108
|
+
* Note that the CDN can still be the preferred one if no other CDN exist for
|
|
109
|
+
* a wanted resource.
|
|
110
|
+
* @param {string} metadata
|
|
111
|
+
*/
|
|
112
|
+
public downgradeCdn(metadata : ICdnMetadata) : void {
|
|
113
|
+
const indexOf = indexOfMetadata(this._downgradedCdnList.metadata, metadata);
|
|
114
|
+
if (indexOf >= 0) {
|
|
115
|
+
this._removeIndexFromDowngradeList(indexOf);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const { DEFAULT_CDN_DOWNGRADE_TIME } = config.getCurrent();
|
|
119
|
+
const downgradeTime = DEFAULT_CDN_DOWNGRADE_TIME;
|
|
120
|
+
this._downgradedCdnList.metadata.push(metadata);
|
|
121
|
+
const timeout = window.setTimeout(() => {
|
|
122
|
+
const newIndex = indexOfMetadata(this._downgradedCdnList.metadata, metadata);
|
|
123
|
+
if (newIndex >= 0) {
|
|
124
|
+
this._removeIndexFromDowngradeList(newIndex);
|
|
125
|
+
}
|
|
126
|
+
this.trigger("priorityChange", null);
|
|
127
|
+
}, downgradeTime);
|
|
128
|
+
this._downgradedCdnList.timeouts.push(timeout);
|
|
129
|
+
this.trigger("priorityChange", null);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* From the list of __ALL__ CDNs available to a resource, return them in the
|
|
134
|
+
* order in which requests should be performed.
|
|
135
|
+
*
|
|
136
|
+
* Note: It is VERY important to include all CDN that are able to reach the
|
|
137
|
+
* wanted resource, even those which will in the end not be used anyway.
|
|
138
|
+
* If some CDN are not communicated, the `CdnPrioritizer` might wrongly
|
|
139
|
+
* consider that the current resource don't have any of the CDN prioritized
|
|
140
|
+
* internally and return other CDN which should have been forbidden if it knew
|
|
141
|
+
* about the other, non-used, ones.
|
|
142
|
+
*
|
|
143
|
+
* @param {Array.<string>} everyCdnForResource - Array of ALL available CDN
|
|
144
|
+
* able to reach the wanted resource - even those which might not be used in
|
|
145
|
+
* the end.
|
|
146
|
+
* @returns {Array.<string>} - Array of CDN that can be tried to reach the
|
|
147
|
+
* resource, sorted by order of CDN preference, according to the
|
|
148
|
+
* `CdnPrioritizer`'s own list of priorities.
|
|
149
|
+
*/
|
|
150
|
+
private _innerGetCdnPreferenceForResource(
|
|
151
|
+
everyCdnForResource : ICdnMetadata[]
|
|
152
|
+
) : ICdnMetadata[] {
|
|
153
|
+
const [allowedInOrder, downgradedInOrder] = everyCdnForResource
|
|
154
|
+
.reduce((acc : [ICdnMetadata[], ICdnMetadata[]], elt : ICdnMetadata) => {
|
|
155
|
+
if (this._downgradedCdnList.metadata.some(c => c.id === elt.id &&
|
|
156
|
+
c.baseUrl === elt.baseUrl))
|
|
157
|
+
{
|
|
158
|
+
acc[1].push(elt);
|
|
159
|
+
} else {
|
|
160
|
+
acc[0].push(elt);
|
|
161
|
+
}
|
|
162
|
+
return acc;
|
|
163
|
+
}, [[], []]);
|
|
164
|
+
return allowedInOrder.concat(downgradedInOrder);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @param {number} index
|
|
169
|
+
*/
|
|
170
|
+
private _removeIndexFromDowngradeList(index : number) : void {
|
|
171
|
+
this._downgradedCdnList.metadata.splice(index, 1);
|
|
172
|
+
const oldTimeout = this._downgradedCdnList.timeouts.splice(index, 1);
|
|
173
|
+
clearTimeout(oldTimeout[0]);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export interface ICdnPrioritizerEvents {
|
|
178
|
+
warnings : IPlayerError[];
|
|
179
|
+
priorityChange : null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Find the index of the given CDN metadata in a CDN metadata array.
|
|
184
|
+
* Returns `-1` if not found.
|
|
185
|
+
* @param {Array.<Object>} arr
|
|
186
|
+
* @param {Object} elt
|
|
187
|
+
* @returns {number}
|
|
188
|
+
*/
|
|
189
|
+
function indexOfMetadata(
|
|
190
|
+
arr : ICdnMetadata[],
|
|
191
|
+
elt : ICdnMetadata
|
|
192
|
+
) : number {
|
|
193
|
+
if (arr.length === 0) {
|
|
194
|
+
return -1;
|
|
195
|
+
}
|
|
196
|
+
return elt.id !== undefined ? arrayFindIndex(arr, m => m.id === elt.id) :
|
|
197
|
+
arrayFindIndex(arr, m => m.baseUrl === elt.baseUrl);
|
|
198
|
+
}
|
|
@@ -33,8 +33,8 @@ import TaskCanceller from "../../../utils/task_canceller";
|
|
|
33
33
|
import errorSelector from "../utils/error_selector";
|
|
34
34
|
import {
|
|
35
35
|
IBackoffSettings,
|
|
36
|
-
|
|
37
|
-
} from "../utils/
|
|
36
|
+
scheduleRequestPromise,
|
|
37
|
+
} from "../utils/schedule_request";
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
/** What will be sent once parsed. */
|
|
@@ -228,9 +228,7 @@ export default class ManifestFetcher {
|
|
|
228
228
|
const { resolveManifestUrl } = pipelines;
|
|
229
229
|
assert(resolveManifestUrl !== undefined);
|
|
230
230
|
const callResolver = () => resolveManifestUrl(resolverUrl, canceller.signal);
|
|
231
|
-
return
|
|
232
|
-
backoffSettings,
|
|
233
|
-
canceller.signal);
|
|
231
|
+
return scheduleRequestPromise(callResolver, backoffSettings, canceller.signal);
|
|
234
232
|
}
|
|
235
233
|
|
|
236
234
|
/**
|
|
@@ -252,9 +250,7 @@ export default class ManifestFetcher {
|
|
|
252
250
|
const callLoader = () => loadManifest(manifestUrl,
|
|
253
251
|
{ timeout: requestTimeout },
|
|
254
252
|
canceller.signal);
|
|
255
|
-
return
|
|
256
|
-
backoffSettings,
|
|
257
|
-
canceller.signal);
|
|
253
|
+
return scheduleRequestPromise(callLoader, backoffSettings, canceller.signal);
|
|
258
254
|
}
|
|
259
255
|
});
|
|
260
256
|
}
|
|
@@ -349,9 +345,9 @@ export default class ManifestFetcher {
|
|
|
349
345
|
performRequest : () => Promise<T>
|
|
350
346
|
) : Promise<T> {
|
|
351
347
|
try {
|
|
352
|
-
const data = await
|
|
353
|
-
|
|
354
|
-
|
|
348
|
+
const data = await scheduleRequestPromise(performRequest,
|
|
349
|
+
backoffSettings,
|
|
350
|
+
canceller.signal);
|
|
355
351
|
return data;
|
|
356
352
|
} catch (err) {
|
|
357
353
|
throw errorSelector(err);
|
|
@@ -24,6 +24,7 @@ import Manifest, {
|
|
|
24
24
|
Period,
|
|
25
25
|
Representation,
|
|
26
26
|
} from "../../../manifest";
|
|
27
|
+
import { ICdnMetadata } from "../../../parsers/manifest";
|
|
27
28
|
import { IPlayerError } from "../../../public_types";
|
|
28
29
|
import {
|
|
29
30
|
IChunkCompleteInformation,
|
|
@@ -49,8 +50,9 @@ import {
|
|
|
49
50
|
IRequestProgressCallbackPayload,
|
|
50
51
|
} from "../../adaptive";
|
|
51
52
|
import { IBufferType } from "../../segment_buffers";
|
|
53
|
+
import CdnPrioritizer from "../cdn_prioritizer";
|
|
52
54
|
import errorSelector from "../utils/error_selector";
|
|
53
|
-
import {
|
|
55
|
+
import { scheduleRequestWithCdns } from "../utils/schedule_request";
|
|
54
56
|
|
|
55
57
|
|
|
56
58
|
/** Allows to generate a unique identifies for each request. */
|
|
@@ -71,6 +73,7 @@ const generateRequestID = idGenerator();
|
|
|
71
73
|
export default function createSegmentFetcher<TLoadedFormat, TSegmentDataType>(
|
|
72
74
|
bufferType : IBufferType,
|
|
73
75
|
pipeline : ISegmentPipeline<TLoadedFormat, TSegmentDataType>,
|
|
76
|
+
cdnPrioritizer : CdnPrioritizer | null,
|
|
74
77
|
lifecycleCallbacks : ISegmentFetcherLifecycleCallbacks,
|
|
75
78
|
options : ISegmentFetcherOptions
|
|
76
79
|
) : ISegmentFetcher<TSegmentDataType> {
|
|
@@ -102,8 +105,6 @@ export default function createSegmentFetcher<TLoadedFormat, TSegmentDataType>(
|
|
|
102
105
|
fetcherCallbacks : ISegmentFetcherCallbacks<TSegmentDataType>,
|
|
103
106
|
cancellationSignal : CancellationSignal
|
|
104
107
|
) : Promise<void> {
|
|
105
|
-
const { segment } = content;
|
|
106
|
-
|
|
107
108
|
// used by logs
|
|
108
109
|
const segmentIdString = getLoggableSegmentId(content);
|
|
109
110
|
const requestId = generateRequestID();
|
|
@@ -193,10 +194,11 @@ export default function createSegmentFetcher<TLoadedFormat, TSegmentDataType>(
|
|
|
193
194
|
});
|
|
194
195
|
|
|
195
196
|
try {
|
|
196
|
-
const res = await
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
197
|
+
const res = await scheduleRequestWithCdns(content.representation.cdnMetadata,
|
|
198
|
+
cdnPrioritizer,
|
|
199
|
+
callLoaderWithUrl,
|
|
200
|
+
objectAssign({ onRetry }, options),
|
|
201
|
+
cancellationSignal);
|
|
200
202
|
|
|
201
203
|
if (res.resultType === "segment-loaded") {
|
|
202
204
|
const loadedData = res.resultData.responseData;
|
|
@@ -236,13 +238,13 @@ export default function createSegmentFetcher<TLoadedFormat, TSegmentDataType>(
|
|
|
236
238
|
|
|
237
239
|
/**
|
|
238
240
|
* Call a segment loader for the given URL with the right arguments.
|
|
239
|
-
* @param {
|
|
241
|
+
* @param {Object|null} cdnMetadata
|
|
240
242
|
* @returns {Promise}
|
|
241
243
|
*/
|
|
242
244
|
function callLoaderWithUrl(
|
|
243
|
-
|
|
245
|
+
cdnMetadata : ICdnMetadata | null
|
|
244
246
|
) : ReturnType<ISegmentLoader<TLoadedFormat>> {
|
|
245
|
-
return loadSegment(
|
|
247
|
+
return loadSegment(cdnMetadata,
|
|
246
248
|
content,
|
|
247
249
|
requestOptions,
|
|
248
250
|
cancellationSignal,
|
|
@@ -19,7 +19,9 @@ import {
|
|
|
19
19
|
ISegmentPipeline,
|
|
20
20
|
ITransportPipelines,
|
|
21
21
|
} from "../../../transports";
|
|
22
|
+
import { CancellationSignal } from "../../../utils/task_canceller";
|
|
22
23
|
import { IBufferType } from "../../segment_buffers";
|
|
24
|
+
import CdnPrioritizer from "../cdn_prioritizer";
|
|
23
25
|
import applyPrioritizerToSegmentFetcher, {
|
|
24
26
|
IPrioritizedSegmentFetcher,
|
|
25
27
|
} from "./prioritized_segment_fetcher";
|
|
@@ -81,13 +83,18 @@ export default class SegmentFetcherCreator {
|
|
|
81
83
|
*/
|
|
82
84
|
private readonly _backoffOptions : ISegmentFetcherCreatorBackoffOptions;
|
|
83
85
|
|
|
86
|
+
private readonly _cdnPrioritizer : CdnPrioritizer;
|
|
87
|
+
|
|
84
88
|
/**
|
|
85
89
|
* @param {Object} transport
|
|
86
90
|
*/
|
|
87
91
|
constructor(
|
|
88
92
|
transport : ITransportPipelines,
|
|
89
|
-
options : ISegmentFetcherCreatorBackoffOptions
|
|
93
|
+
options : ISegmentFetcherCreatorBackoffOptions,
|
|
94
|
+
cancelSignal : CancellationSignal
|
|
90
95
|
) {
|
|
96
|
+
const cdnPrioritizer = new CdnPrioritizer(cancelSignal);
|
|
97
|
+
|
|
91
98
|
const { MIN_CANCELABLE_PRIORITY,
|
|
92
99
|
MAX_HIGH_PRIORITY_LEVEL } = config.getCurrent();
|
|
93
100
|
this._transport = transport;
|
|
@@ -95,6 +102,7 @@ export default class SegmentFetcherCreator {
|
|
|
95
102
|
prioritySteps: { high: MAX_HIGH_PRIORITY_LEVEL,
|
|
96
103
|
low: MIN_CANCELABLE_PRIORITY },
|
|
97
104
|
});
|
|
105
|
+
this._cdnPrioritizer = cdnPrioritizer;
|
|
98
106
|
this._backoffOptions = options;
|
|
99
107
|
}
|
|
100
108
|
|
|
@@ -116,6 +124,7 @@ export default class SegmentFetcherCreator {
|
|
|
116
124
|
const segmentFetcher = createSegmentFetcher<unknown, unknown>(
|
|
117
125
|
bufferType,
|
|
118
126
|
pipelines as ISegmentPipeline<unknown, unknown>,
|
|
127
|
+
this._cdnPrioritizer,
|
|
119
128
|
callbacks,
|
|
120
129
|
backoffOptions
|
|
121
130
|
);
|