rx-player 3.28.0-dev.2022071100 → 3.29.0-dev.2022090500
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/.github/workflows/checks.yml +20 -18
- package/CHANGELOG.md +24 -2
- package/VERSION +1 -1
- package/dist/_esm5.processed/compat/eme/load_session.d.ts +5 -6
- package/dist/_esm5.processed/compat/eme/load_session.js +5 -6
- package/dist/_esm5.processed/compat/event_listeners.d.ts +18 -2
- package/dist/_esm5.processed/compat/event_listeners.js +64 -2
- package/dist/_esm5.processed/compat/on_height_width_change.d.ts +5 -4
- package/dist/_esm5.processed/compat/on_height_width_change.js +43 -34
- package/dist/_esm5.processed/core/api/media_element_track_choice_manager.js +1 -1
- package/dist/_esm5.processed/core/api/playback_observer.d.ts +12 -2
- package/dist/_esm5.processed/core/api/playback_observer.js +27 -12
- package/dist/_esm5.processed/core/api/public_api.js +14 -14
- package/dist/_esm5.processed/core/decrypt/create_session.js +33 -4
- package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.d.ts +14 -0
- package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.js +25 -0
- package/dist/_esm5.processed/core/fetchers/manifest/manifest_fetcher.d.ts +7 -0
- package/dist/_esm5.processed/core/fetchers/manifest/manifest_fetcher.js +10 -2
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.d.ts +9 -2
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.js +11 -5
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher_creator.d.ts +7 -0
- package/dist/_esm5.processed/core/init/content_time_boundaries_observer.js +110 -38
- package/dist/_esm5.processed/core/init/initialize_directfile.js +1 -1
- package/dist/_esm5.processed/core/init/load_on_media_source.js +1 -1
- package/dist/_esm5.processed/core/init/stall_avoider.d.ts +4 -2
- package/dist/_esm5.processed/core/init/stall_avoider.js +32 -26
- package/dist/_esm5.processed/core/segment_buffers/garbage_collector.d.ts +12 -6
- package/dist/_esm5.processed/core/segment_buffers/garbage_collector.js +142 -78
- package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.d.ts +18 -16
- package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +53 -41
- package/dist/_esm5.processed/core/segment_buffers/implementations/image/image_segment_buffer.d.ts +6 -5
- package/dist/_esm5.processed/core/segment_buffers/implementations/image/image_segment_buffer.js +37 -39
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.d.ts +23 -22
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +84 -72
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.d.ts +6 -12
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.js +33 -43
- package/dist/_esm5.processed/core/segment_buffers/implementations/types.d.ts +12 -9
- package/dist/_esm5.processed/core/segment_buffers/segment_buffers_store.d.ts +7 -6
- package/dist/_esm5.processed/core/segment_buffers/segment_buffers_store.js +17 -10
- package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +20 -9
- package/dist/_esm5.processed/core/stream/period/period_stream.js +25 -14
- package/dist/_esm5.processed/core/stream/representation/append_segment_to_buffer.d.ts +4 -7
- package/dist/_esm5.processed/core/stream/representation/append_segment_to_buffer.js +80 -23
- package/dist/_esm5.processed/core/stream/representation/check_for_discontinuity.js +21 -9
- package/dist/_esm5.processed/core/stream/representation/force_garbage_collection.d.ts +5 -4
- package/dist/_esm5.processed/core/stream/representation/force_garbage_collection.js +78 -26
- package/dist/_esm5.processed/core/stream/representation/get_buffer_status.js +28 -32
- package/dist/_esm5.processed/core/stream/representation/push_init_segment.js +7 -1
- package/dist/_esm5.processed/core/stream/representation/push_media_segment.js +7 -1
- package/dist/_esm5.processed/core/stream/representation/representation_stream.js +15 -8
- package/dist/_esm5.processed/default_config.js +1 -1
- package/dist/_esm5.processed/errors/custom_loader_error.d.ts +3 -2
- package/dist/_esm5.processed/errors/custom_loader_error.js +3 -2
- package/dist/_esm5.processed/errors/encrypted_media_error.d.ts +1 -2
- package/dist/_esm5.processed/errors/encrypted_media_error.js +0 -1
- package/dist/_esm5.processed/errors/error_codes.d.ts +6 -1
- package/dist/_esm5.processed/errors/media_error.d.ts +1 -2
- package/dist/_esm5.processed/errors/media_error.js +0 -1
- package/dist/_esm5.processed/errors/network_error.d.ts +1 -2
- package/dist/_esm5.processed/errors/network_error.js +0 -1
- package/dist/_esm5.processed/errors/other_error.d.ts +1 -2
- package/dist/_esm5.processed/errors/other_error.js +0 -1
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/get_initialized_source_buffer.js +5 -2
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/push_data.js +5 -2
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/remove_buffer_around_time.js +9 -2
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/thumbnail_loader.js +3 -1
- package/dist/_esm5.processed/experimental/tools/createMetaplaylist/get_duration_from_manifest.js +4 -3
- package/dist/_esm5.processed/manifest/manifest.d.ts +1 -1
- package/dist/_esm5.processed/manifest/manifest.js +1 -1
- package/dist/_esm5.processed/manifest/representation_index/static.d.ts +21 -6
- package/dist/_esm5.processed/manifest/representation_index/static.js +26 -8
- package/dist/_esm5.processed/manifest/representation_index/types.d.ts +55 -44
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/base.d.ts +21 -8
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/base.js +25 -10
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/list.d.ts +26 -12
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/list.js +26 -13
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/template.d.ts +23 -7
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/template.js +65 -22
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.d.ts +20 -3
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.js +57 -7
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/{is_period_fulfilled.d.ts → utils.d.ts} +3 -6
- package/dist/_esm5.processed/parsers/manifest/dash/common/indexes/{is_period_fulfilled.js → utils.js} +4 -8
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_periods.js +1 -1
- package/dist/_esm5.processed/parsers/manifest/local/parse_local_manifest.js +5 -8
- package/dist/_esm5.processed/parsers/manifest/local/representation_index.d.ts +21 -8
- package/dist/_esm5.processed/parsers/manifest/local/representation_index.js +49 -14
- package/dist/_esm5.processed/parsers/manifest/local/types.d.ts +16 -0
- package/dist/_esm5.processed/parsers/manifest/metaplaylist/representation_index.d.ts +20 -6
- package/dist/_esm5.processed/parsers/manifest/metaplaylist/representation_index.js +28 -10
- package/dist/_esm5.processed/parsers/manifest/smooth/create_parser.js +4 -4
- package/dist/_esm5.processed/parsers/manifest/smooth/representation_index.d.ts +21 -12
- package/dist/_esm5.processed/parsers/manifest/smooth/representation_index.js +39 -14
- package/dist/_esm5.processed/parsers/manifest/utils/get_first_time_from_adaptation.js +1 -1
- package/dist/_esm5.processed/parsers/manifest/utils/get_last_time_from_adaptation.js +1 -1
- package/dist/_esm5.processed/public_types.d.ts +22 -3
- package/dist/_esm5.processed/transports/dash/add_segment_integrity_checks_to_loader.js +2 -2
- package/dist/_esm5.processed/transports/dash/image_pipelines.d.ts +3 -2
- package/dist/_esm5.processed/transports/dash/image_pipelines.js +3 -1
- package/dist/_esm5.processed/transports/dash/init_segment_loader.d.ts +3 -2
- package/dist/_esm5.processed/transports/dash/init_segment_loader.js +12 -6
- package/dist/_esm5.processed/transports/dash/low_latency_segment_loader.d.ts +3 -2
- package/dist/_esm5.processed/transports/dash/low_latency_segment_loader.js +3 -2
- package/dist/_esm5.processed/transports/dash/manifest_parser.js +6 -2
- package/dist/_esm5.processed/transports/dash/segment_loader.d.ts +3 -2
- package/dist/_esm5.processed/transports/dash/segment_loader.js +12 -9
- package/dist/_esm5.processed/transports/dash/text_loader.js +6 -3
- package/dist/_esm5.processed/transports/local/pipelines.d.ts +2 -2
- package/dist/_esm5.processed/transports/local/pipelines.js +6 -6
- package/dist/_esm5.processed/transports/local/segment_loader.d.ts +3 -2
- package/dist/_esm5.processed/transports/local/segment_loader.js +4 -3
- package/dist/_esm5.processed/transports/metaplaylist/manifest_loader.d.ts +2 -2
- package/dist/_esm5.processed/transports/metaplaylist/manifest_loader.js +5 -2
- package/dist/_esm5.processed/transports/metaplaylist/pipelines.js +15 -12
- package/dist/_esm5.processed/transports/smooth/pipelines.d.ts +1 -1
- package/dist/_esm5.processed/transports/smooth/pipelines.js +18 -14
- package/dist/_esm5.processed/transports/smooth/segment_loader.d.ts +2 -2
- package/dist/_esm5.processed/transports/smooth/segment_loader.js +9 -7
- package/dist/_esm5.processed/transports/types.d.ts +26 -3
- package/dist/_esm5.processed/transports/utils/call_custom_manifest_loader.d.ts +2 -2
- package/dist/_esm5.processed/transports/utils/call_custom_manifest_loader.js +3 -3
- package/dist/_esm5.processed/transports/utils/generate_manifest_loader.d.ts +2 -2
- package/dist/_esm5.processed/transports/utils/generate_manifest_loader.js +9 -6
- package/dist/_esm5.processed/utils/deep_merge.d.ts +1 -1
- package/dist/_esm5.processed/utils/deep_merge.js +6 -5
- package/dist/_esm5.processed/utils/request/fetch.js +7 -8
- package/dist/_esm5.processed/utils/request/xhr.d.ts +1 -1
- package/dist/_esm5.processed/utils/request/xhr.js +28 -14
- package/dist/_esm5.processed/utils/task_canceller.d.ts +1 -5
- package/dist/_esm5.processed/utils/task_canceller.js +1 -5
- package/dist/mpd-parser.wasm +0 -0
- package/dist/rx-player.js +2497 -1752
- package/dist/rx-player.min.js +1 -1
- package/jest.config.js +5 -0
- package/package.json +31 -30
- package/sonar-project.properties +1 -1
- package/src/compat/eme/load_session.ts +5 -6
- package/src/compat/event_listeners.ts +86 -1
- package/src/compat/on_height_width_change.ts +48 -49
- package/src/core/api/media_element_track_choice_manager.ts +1 -1
- package/src/core/api/playback_observer.ts +34 -14
- package/src/core/api/public_api.ts +23 -18
- package/src/core/decrypt/create_session.ts +28 -2
- package/src/core/decrypt/utils/loaded_sessions_store.ts +29 -0
- package/src/core/fetchers/manifest/manifest_fetcher.ts +20 -2
- package/src/core/fetchers/segment/segment_fetcher.ts +24 -4
- package/src/core/fetchers/segment/segment_fetcher_creator.ts +7 -0
- package/src/core/init/content_time_boundaries_observer.ts +116 -42
- package/src/core/init/initialize_directfile.ts +1 -1
- package/src/core/init/load_on_media_source.ts +1 -0
- package/src/core/init/stall_avoider.ts +40 -26
- package/src/core/segment_buffers/garbage_collector.ts +55 -47
- package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +92 -70
- package/src/core/segment_buffers/implementations/image/image_segment_buffer.ts +37 -42
- package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +103 -105
- package/src/core/segment_buffers/implementations/text/native/native_text_segment_buffer.ts +35 -46
- package/src/core/segment_buffers/implementations/types.ts +22 -9
- package/src/core/segment_buffers/segment_buffers_store.ts +23 -14
- package/src/core/stream/orchestrator/stream_orchestrator.ts +31 -12
- package/src/core/stream/period/period_stream.ts +31 -18
- package/src/core/stream/representation/append_segment_to_buffer.ts +27 -42
- package/src/core/stream/representation/check_for_discontinuity.ts +28 -10
- package/src/core/stream/representation/force_garbage_collection.ts +28 -32
- package/src/core/stream/representation/get_buffer_status.ts +34 -37
- package/src/core/stream/representation/push_init_segment.ts +12 -6
- package/src/core/stream/representation/push_media_segment.ts +12 -6
- package/src/core/stream/representation/representation_stream.ts +11 -5
- package/src/default_config.ts +17 -17
- package/src/errors/custom_loader_error.ts +3 -2
- package/src/errors/encrypted_media_error.ts +1 -2
- package/src/errors/error_codes.ts +2 -2
- package/src/errors/media_error.ts +1 -2
- package/src/errors/network_error.ts +1 -2
- package/src/errors/other_error.ts +1 -2
- package/src/experimental/tools/VideoThumbnailLoader/get_initialized_source_buffer.ts +7 -2
- package/src/experimental/tools/VideoThumbnailLoader/push_data.ts +6 -2
- package/src/experimental/tools/VideoThumbnailLoader/remove_buffer_around_time.ts +10 -2
- package/src/experimental/tools/VideoThumbnailLoader/thumbnail_loader.ts +3 -1
- package/src/experimental/tools/createMetaplaylist/get_duration_from_manifest.ts +4 -3
- package/src/manifest/__tests__/adaptation.test.ts +4 -3
- package/src/manifest/__tests__/representation.test.ts +4 -3
- package/src/manifest/manifest.ts +1 -1
- package/src/manifest/representation_index/__tests__/static.test.ts +5 -4
- package/src/manifest/representation_index/static.ts +28 -9
- package/src/manifest/representation_index/types.ts +62 -46
- package/src/parsers/manifest/dash/common/indexes/base.ts +27 -11
- package/src/parsers/manifest/dash/common/indexes/list.ts +32 -15
- package/src/parsers/manifest/dash/common/indexes/template.ts +73 -27
- package/src/parsers/manifest/dash/common/indexes/timeline/timeline_representation_index.ts +60 -8
- package/src/parsers/manifest/dash/common/indexes/{is_period_fulfilled.ts → utils.ts} +4 -13
- package/src/parsers/manifest/dash/common/parse_periods.ts +1 -1
- package/src/parsers/manifest/local/parse_local_manifest.ts +8 -20
- package/src/parsers/manifest/local/representation_index.ts +51 -16
- package/src/parsers/manifest/local/types.ts +13 -0
- package/src/parsers/manifest/metaplaylist/representation_index.ts +31 -11
- package/src/parsers/manifest/smooth/create_parser.ts +4 -4
- package/src/parsers/manifest/smooth/representation_index.ts +40 -15
- package/src/parsers/manifest/utils/__tests__/get_first_time_from_adaptations.test.ts +4 -3
- package/src/parsers/manifest/utils/__tests__/get_last_time_from_adaptation.test.ts +4 -3
- package/src/parsers/manifest/utils/get_first_time_from_adaptation.ts +1 -1
- package/src/parsers/manifest/utils/get_last_time_from_adaptation.ts +1 -1
- package/src/public_types.ts +28 -4
- package/src/transports/dash/add_segment_integrity_checks_to_loader.ts +2 -2
- package/src/transports/dash/image_pipelines.ts +4 -0
- package/src/transports/dash/init_segment_loader.ts +8 -0
- package/src/transports/dash/low_latency_segment_loader.ts +4 -0
- package/src/transports/dash/manifest_parser.ts +4 -0
- package/src/transports/dash/segment_loader.ts +21 -5
- package/src/transports/dash/text_loader.ts +7 -2
- package/src/transports/local/pipelines.ts +7 -5
- package/src/transports/local/segment_loader.ts +4 -2
- package/src/transports/metaplaylist/manifest_loader.ts +9 -2
- package/src/transports/metaplaylist/pipelines.ts +16 -8
- package/src/transports/smooth/pipelines.ts +17 -9
- package/src/transports/smooth/segment_loader.ts +9 -1
- package/src/transports/types.ts +28 -1
- package/src/transports/utils/call_custom_manifest_loader.ts +8 -2
- package/src/transports/utils/generate_manifest_loader.ts +18 -5
- package/src/utils/__tests__/initialization_segment_cache.test.ts +7 -0
- package/src/utils/deep_merge.ts +7 -4
- package/src/utils/request/fetch.ts +7 -8
- package/src/utils/request/xhr.ts +31 -15
- package/src/utils/task_canceller.ts +1 -5
|
@@ -110,7 +110,7 @@ function createAndTryToRetrievePersistentSession(loadedSessionsStore, persistent
|
|
|
110
110
|
*/
|
|
111
111
|
function recreatePersistentSession() {
|
|
112
112
|
return __awaiter(this, void 0, void 0, function () {
|
|
113
|
-
var persistentEntry, newEntry;
|
|
113
|
+
var persistentEntry, err_2, newEntry;
|
|
114
114
|
return __generator(this, function (_a) {
|
|
115
115
|
switch (_a.label) {
|
|
116
116
|
case 0:
|
|
@@ -122,9 +122,30 @@ function createAndTryToRetrievePersistentSession(loadedSessionsStore, persistent
|
|
|
122
122
|
if (persistentEntry !== null) {
|
|
123
123
|
persistentSessionsStore.delete(persistentEntry.sessionId);
|
|
124
124
|
}
|
|
125
|
-
|
|
125
|
+
_a.label = 1;
|
|
126
126
|
case 1:
|
|
127
|
+
_a.trys.push([1, 3, , 4]);
|
|
128
|
+
return [4 /*yield*/, loadedSessionsStore.closeSession(entry.mediaKeySession)];
|
|
129
|
+
case 2:
|
|
127
130
|
_a.sent();
|
|
131
|
+
return [3 /*break*/, 4];
|
|
132
|
+
case 3:
|
|
133
|
+
err_2 = _a.sent();
|
|
134
|
+
// From reading the EME specification in details, it seems that a
|
|
135
|
+
// `MediaKeySession`'s ability to be closed is tightly linked to its
|
|
136
|
+
// possession of a "sanitized session ID" set as `sessionId`.
|
|
137
|
+
// This is never clearly stated however and I'm (Paul B.) always afraid of
|
|
138
|
+
// breaking compatibility when it comes to EME code.
|
|
139
|
+
// So we still try to close the `MediaKeySession` in any case, only, if it
|
|
140
|
+
// fails and it didn't had any `sessionId` set, we just ignore the error.
|
|
141
|
+
// Note that trying to close the `MediaKeySession` might incur some delays
|
|
142
|
+
// in those rare cases.
|
|
143
|
+
if (entry.mediaKeySession.sessionId !== "") {
|
|
144
|
+
throw err_2;
|
|
145
|
+
}
|
|
146
|
+
loadedSessionsStore.removeSessionWithoutClosingIt(entry.mediaKeySession);
|
|
147
|
+
return [3 /*break*/, 4];
|
|
148
|
+
case 4:
|
|
128
149
|
if (cancelSignal.cancellationError !== null) {
|
|
129
150
|
throw cancelSignal.cancellationError;
|
|
130
151
|
}
|
|
@@ -135,7 +156,7 @@ function createAndTryToRetrievePersistentSession(loadedSessionsStore, persistent
|
|
|
135
156
|
});
|
|
136
157
|
});
|
|
137
158
|
}
|
|
138
|
-
var entry, storedEntry, hasLoadedSession, err_1;
|
|
159
|
+
var entry, storedEntry, hasLoadedSession, newEntry, err_1;
|
|
139
160
|
return __generator(this, function (_a) {
|
|
140
161
|
switch (_a.label) {
|
|
141
162
|
case 0:
|
|
@@ -158,8 +179,16 @@ function createAndTryToRetrievePersistentSession(loadedSessionsStore, persistent
|
|
|
158
179
|
if (!hasLoadedSession) {
|
|
159
180
|
log.warn("DRM: No data stored for the loaded session");
|
|
160
181
|
persistentSessionsStore.delete(storedEntry.sessionId);
|
|
182
|
+
// The EME specification is kind of implicit about it but it seems from my
|
|
183
|
+
// understanding (Paul B.) that a MediaKeySession on wich a `load` attempt
|
|
184
|
+
// did not succeed due to the loaded session not being found by the
|
|
185
|
+
// browser/CDM, should neither be used anymore nor closed.
|
|
186
|
+
// Thus, we're creating another `"persistent-license"` `MediaKeySession`
|
|
187
|
+
// in that specific case.
|
|
188
|
+
loadedSessionsStore.removeSessionWithoutClosingIt(entry.mediaKeySession);
|
|
189
|
+
newEntry = loadedSessionsStore.createSession(initData, "persistent-license");
|
|
161
190
|
return [2 /*return*/, { type: "created-session" /* MediaKeySessionLoadingType.Created */,
|
|
162
|
-
value:
|
|
191
|
+
value: newEntry }];
|
|
163
192
|
}
|
|
164
193
|
if (hasLoadedSession && isSessionUsable(entry.mediaKeySession)) {
|
|
165
194
|
persistentSessionsStore.add(initData, initData.keyIds, entry.mediaKeySession);
|
|
@@ -106,6 +106,20 @@ export default class LoadedSessionsStore {
|
|
|
106
106
|
* @returns {Promise}
|
|
107
107
|
*/
|
|
108
108
|
closeAllSessions(): Promise<void>;
|
|
109
|
+
/**
|
|
110
|
+
* Find the given `MediaKeySession` in the `LoadedSessionsStore` and removes
|
|
111
|
+
* any reference to it without actually closing it.
|
|
112
|
+
*
|
|
113
|
+
* Returns `true` if the given `mediaKeySession` has been found and removed,
|
|
114
|
+
* `false` otherwise.
|
|
115
|
+
*
|
|
116
|
+
* Note that this may create a `MediaKeySession` leakage in the wrong
|
|
117
|
+
* conditions, cases where this method should be called should be very
|
|
118
|
+
* carefully evaluated.
|
|
119
|
+
* @param {MediaKeySession} mediaKeySession
|
|
120
|
+
* @returns {boolean}
|
|
121
|
+
*/
|
|
122
|
+
removeSessionWithoutClosingIt(mediaKeySession: MediaKeySession | ICustomMediaKeySession): boolean;
|
|
109
123
|
/**
|
|
110
124
|
* Get the index of a stored MediaKeySession entry based on its
|
|
111
125
|
* `KeySessionRecord`.
|
|
@@ -62,6 +62,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
62
62
|
};
|
|
63
63
|
import { closeSession, generateKeyRequest, loadSession, } from "../../../compat";
|
|
64
64
|
import log from "../../../log";
|
|
65
|
+
import assert from "../../../utils/assert";
|
|
65
66
|
import isNullOrUndefined from "../../../utils/is_null_or_undefined";
|
|
66
67
|
import KeySessionRecord from "./key_session_record";
|
|
67
68
|
/**
|
|
@@ -346,6 +347,30 @@ var LoadedSessionsStore = /** @class */ (function () {
|
|
|
346
347
|
});
|
|
347
348
|
});
|
|
348
349
|
};
|
|
350
|
+
/**
|
|
351
|
+
* Find the given `MediaKeySession` in the `LoadedSessionsStore` and removes
|
|
352
|
+
* any reference to it without actually closing it.
|
|
353
|
+
*
|
|
354
|
+
* Returns `true` if the given `mediaKeySession` has been found and removed,
|
|
355
|
+
* `false` otherwise.
|
|
356
|
+
*
|
|
357
|
+
* Note that this may create a `MediaKeySession` leakage in the wrong
|
|
358
|
+
* conditions, cases where this method should be called should be very
|
|
359
|
+
* carefully evaluated.
|
|
360
|
+
* @param {MediaKeySession} mediaKeySession
|
|
361
|
+
* @returns {boolean}
|
|
362
|
+
*/
|
|
363
|
+
LoadedSessionsStore.prototype.removeSessionWithoutClosingIt = function (mediaKeySession) {
|
|
364
|
+
assert(mediaKeySession.sessionId === "", "Initialized `MediaKeySession`s should always be properly closed");
|
|
365
|
+
for (var i = this._storage.length - 1; i >= 0; i--) {
|
|
366
|
+
var stored = this._storage[i];
|
|
367
|
+
if (stored.mediaKeySession === mediaKeySession) {
|
|
368
|
+
this._storage.splice(i, 1);
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return false;
|
|
373
|
+
};
|
|
349
374
|
/**
|
|
350
375
|
* Get the index of a stored MediaKeySession entry based on its
|
|
351
376
|
* `KeySessionRecord`.
|
|
@@ -74,6 +74,13 @@ export interface IManifestFetcherSettings {
|
|
|
74
74
|
maxRetryRegular: number | undefined;
|
|
75
75
|
/** Maximum number of time a request be retried when the user is offline. */
|
|
76
76
|
maxRetryOffline: number | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Timeout after which request are aborted and, depending on other options,
|
|
79
|
+
* retried.
|
|
80
|
+
* To set to `-1` for no timeout.
|
|
81
|
+
* `undefined` will lead to a default, large, timeout being used.
|
|
82
|
+
*/
|
|
83
|
+
requestTimeout: number | undefined;
|
|
77
84
|
}
|
|
78
85
|
/**
|
|
79
86
|
* Class allowing to facilitate the task of loading and parsing a Manifest.
|
|
@@ -54,6 +54,7 @@ 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 isNullOrUndefined from "../../../utils/is_null_or_undefined";
|
|
57
58
|
import TaskCanceller from "../../../utils/task_canceller";
|
|
58
59
|
import errorSelector from "../utils/error_selector";
|
|
59
60
|
import { tryRequestPromiseWithBackoff, } from "../utils/try_urls_with_backoff";
|
|
@@ -106,6 +107,7 @@ var ManifestFetcher = /** @class */ (function () {
|
|
|
106
107
|
ManifestFetcher.prototype.fetch = function (url) {
|
|
107
108
|
var _this = this;
|
|
108
109
|
return new Observable(function (obs) {
|
|
110
|
+
var settings = _this._settings;
|
|
109
111
|
var pipelines = _this._pipelines;
|
|
110
112
|
var requestUrl = url !== null && url !== void 0 ? url : _this._manifestUrl;
|
|
111
113
|
/** `true` if the loading pipeline is already completely executed. */
|
|
@@ -160,12 +162,18 @@ var ManifestFetcher = /** @class */ (function () {
|
|
|
160
162
|
* Call the loader part of the pipeline, retrying if it fails according
|
|
161
163
|
* to the current settings.
|
|
162
164
|
* Returns the Promise of the last attempt.
|
|
163
|
-
* @param {string | undefined}
|
|
165
|
+
* @param {string | undefined} manifestUrl
|
|
164
166
|
* @returns {Promise}
|
|
165
167
|
*/
|
|
166
168
|
function callLoaderWithRetries(manifestUrl) {
|
|
167
169
|
var loadManifest = pipelines.loadManifest;
|
|
168
|
-
var
|
|
170
|
+
var requestTimeout = isNullOrUndefined(settings.requestTimeout) ?
|
|
171
|
+
config.getCurrent().DEFAULT_REQUEST_TIMEOUT :
|
|
172
|
+
settings.requestTimeout;
|
|
173
|
+
if (requestTimeout < 0) {
|
|
174
|
+
requestTimeout = undefined;
|
|
175
|
+
}
|
|
176
|
+
var callLoader = function () { return loadManifest(manifestUrl, { timeout: requestTimeout }, canceller.signal); };
|
|
169
177
|
return tryRequestPromiseWithBackoff(callLoader, backoffSettings, canceller.signal);
|
|
170
178
|
}
|
|
171
179
|
});
|
|
@@ -26,7 +26,7 @@ import { IBufferType } from "../../segment_buffers";
|
|
|
26
26
|
* `options` argument, which may retry a segment request when it fails.
|
|
27
27
|
*
|
|
28
28
|
* @param {string} bufferType
|
|
29
|
-
* @param {Object}
|
|
29
|
+
* @param {Object} pipeline
|
|
30
30
|
* @param {Object} callbacks
|
|
31
31
|
* @param {Object} options
|
|
32
32
|
* @returns {Function}
|
|
@@ -123,14 +123,21 @@ export interface ISegmentFetcherOptions {
|
|
|
123
123
|
* currently offline.
|
|
124
124
|
*/
|
|
125
125
|
maxRetryOffline: number;
|
|
126
|
+
/**
|
|
127
|
+
* Timeout after which request are aborted and, depending on other options,
|
|
128
|
+
* retried.
|
|
129
|
+
* To set to `-1` for no timeout.
|
|
130
|
+
*/
|
|
131
|
+
requestTimeout: number;
|
|
126
132
|
}
|
|
127
133
|
/**
|
|
128
134
|
* @param {string} bufferType
|
|
129
135
|
* @param {Object}
|
|
130
136
|
* @returns {Object}
|
|
131
137
|
*/
|
|
132
|
-
export declare function getSegmentFetcherOptions(bufferType: string, { maxRetryRegular, maxRetryOffline, lowLatencyMode }: {
|
|
138
|
+
export declare function getSegmentFetcherOptions(bufferType: string, { maxRetryRegular, maxRetryOffline, lowLatencyMode, requestTimeout }: {
|
|
133
139
|
maxRetryRegular?: number | undefined;
|
|
134
140
|
maxRetryOffline?: number | undefined;
|
|
141
|
+
requestTimeout?: number | undefined;
|
|
135
142
|
lowLatencyMode: boolean;
|
|
136
143
|
}): ISegmentFetcherOptions;
|
|
@@ -34,12 +34,16 @@ var generateRequestID = idGenerator();
|
|
|
34
34
|
* `options` argument, which may retry a segment request when it fails.
|
|
35
35
|
*
|
|
36
36
|
* @param {string} bufferType
|
|
37
|
-
* @param {Object}
|
|
37
|
+
* @param {Object} pipeline
|
|
38
38
|
* @param {Object} callbacks
|
|
39
39
|
* @param {Object} options
|
|
40
40
|
* @returns {Function}
|
|
41
41
|
*/
|
|
42
42
|
export default function createSegmentFetcher(bufferType, pipeline, callbacks, options) {
|
|
43
|
+
var requestOptions = {
|
|
44
|
+
timeout: options.requestTimeout < 0 ? undefined :
|
|
45
|
+
options.requestTimeout,
|
|
46
|
+
};
|
|
43
47
|
/**
|
|
44
48
|
* Cache audio and video initialization segments.
|
|
45
49
|
* This allows to avoid doing too many requests for what are usually very
|
|
@@ -203,7 +207,7 @@ export default function createSegmentFetcher(bufferType, pipeline, callbacks, op
|
|
|
203
207
|
* @returns {Promise}
|
|
204
208
|
*/
|
|
205
209
|
function callLoaderWithUrl(url, cancellationSignal) {
|
|
206
|
-
return loadSegment(url, content, cancellationSignal, loaderCallbacks);
|
|
210
|
+
return loadSegment(url, content, requestOptions, cancellationSignal, loaderCallbacks);
|
|
207
211
|
}
|
|
208
212
|
/**
|
|
209
213
|
* Generate function allowing to parse a loaded segment.
|
|
@@ -272,13 +276,15 @@ export default function createSegmentFetcher(bufferType, pipeline, callbacks, op
|
|
|
272
276
|
* @returns {Object}
|
|
273
277
|
*/
|
|
274
278
|
export function getSegmentFetcherOptions(bufferType, _a) {
|
|
275
|
-
var maxRetryRegular = _a.maxRetryRegular, maxRetryOffline = _a.maxRetryOffline, lowLatencyMode = _a.lowLatencyMode;
|
|
276
|
-
var _b = config.getCurrent(), DEFAULT_MAX_REQUESTS_RETRY_ON_ERROR = _b.DEFAULT_MAX_REQUESTS_RETRY_ON_ERROR, DEFAULT_MAX_REQUESTS_RETRY_ON_OFFLINE = _b.DEFAULT_MAX_REQUESTS_RETRY_ON_OFFLINE, INITIAL_BACKOFF_DELAY_BASE = _b.INITIAL_BACKOFF_DELAY_BASE, MAX_BACKOFF_DELAY_BASE = _b.MAX_BACKOFF_DELAY_BASE;
|
|
279
|
+
var maxRetryRegular = _a.maxRetryRegular, maxRetryOffline = _a.maxRetryOffline, lowLatencyMode = _a.lowLatencyMode, requestTimeout = _a.requestTimeout;
|
|
280
|
+
var _b = config.getCurrent(), DEFAULT_MAX_REQUESTS_RETRY_ON_ERROR = _b.DEFAULT_MAX_REQUESTS_RETRY_ON_ERROR, DEFAULT_REQUEST_TIMEOUT = _b.DEFAULT_REQUEST_TIMEOUT, DEFAULT_MAX_REQUESTS_RETRY_ON_OFFLINE = _b.DEFAULT_MAX_REQUESTS_RETRY_ON_OFFLINE, INITIAL_BACKOFF_DELAY_BASE = _b.INITIAL_BACKOFF_DELAY_BASE, MAX_BACKOFF_DELAY_BASE = _b.MAX_BACKOFF_DELAY_BASE;
|
|
277
281
|
return { maxRetryRegular: bufferType === "image" ? 0 :
|
|
278
282
|
maxRetryRegular !== null && maxRetryRegular !== void 0 ? maxRetryRegular : DEFAULT_MAX_REQUESTS_RETRY_ON_ERROR,
|
|
279
283
|
maxRetryOffline: maxRetryOffline !== null && maxRetryOffline !== void 0 ? maxRetryOffline : DEFAULT_MAX_REQUESTS_RETRY_ON_OFFLINE,
|
|
280
284
|
baseDelay: lowLatencyMode ? INITIAL_BACKOFF_DELAY_BASE.LOW_LATENCY :
|
|
281
285
|
INITIAL_BACKOFF_DELAY_BASE.REGULAR,
|
|
282
286
|
maxDelay: lowLatencyMode ? MAX_BACKOFF_DELAY_BASE.LOW_LATENCY :
|
|
283
|
-
MAX_BACKOFF_DELAY_BASE.REGULAR
|
|
287
|
+
MAX_BACKOFF_DELAY_BASE.REGULAR,
|
|
288
|
+
requestTimeout: isNullOrUndefined(requestTimeout) ? DEFAULT_REQUEST_TIMEOUT :
|
|
289
|
+
requestTimeout };
|
|
284
290
|
}
|
|
@@ -91,4 +91,11 @@ export interface ISegmentFetcherCreatorBackoffOptions {
|
|
|
91
91
|
maxRetryRegular: number | undefined;
|
|
92
92
|
/** Maximum number of time a request be retried when the user is offline. */
|
|
93
93
|
maxRetryOffline: number | undefined;
|
|
94
|
+
/**
|
|
95
|
+
* Timeout after which request are aborted and, depending on other options,
|
|
96
|
+
* retried.
|
|
97
|
+
* To set to `-1` for no timeout.
|
|
98
|
+
* `undefined` will lead to a default, large, timeout being used.
|
|
99
|
+
*/
|
|
100
|
+
requestTimeout: number | undefined;
|
|
94
101
|
}
|
|
@@ -17,6 +17,7 @@ import { distinctUntilChanged, ignoreElements, map, merge as observableMerge, sk
|
|
|
17
17
|
import { MediaError } from "../../errors";
|
|
18
18
|
import { fromEvent } from "../../utils/event_emitter";
|
|
19
19
|
import filterMap from "../../utils/filter_map";
|
|
20
|
+
import isNullOrUndefined from "../../utils/is_null_or_undefined";
|
|
20
21
|
import createSharedReference from "../../utils/reference";
|
|
21
22
|
import EVENTS from "./events_generators";
|
|
22
23
|
// NOTE As of now (RxJS 7.4.0), RxJS defines `ignoreElements` default
|
|
@@ -54,7 +55,7 @@ export default function ContentTimeBoundariesObserver(manifest, streams, playbac
|
|
|
54
55
|
"earliest time announced in the Manifest.");
|
|
55
56
|
return EVENTS.warning(warning);
|
|
56
57
|
}
|
|
57
|
-
else if (wantedPosition > maximumPositionCalculator.
|
|
58
|
+
else if (wantedPosition > maximumPositionCalculator.getMaximumAvailablePosition()) {
|
|
58
59
|
var warning = new MediaError("MEDIA_TIME_AFTER_MANIFEST", "The current position is after the latest " +
|
|
59
60
|
"time announced in the Manifest.");
|
|
60
61
|
return EVENTS.warning(warning);
|
|
@@ -68,32 +69,31 @@ export default function ContentTimeBoundariesObserver(manifest, streams, playbac
|
|
|
68
69
|
*/
|
|
69
70
|
var contentDuration = createSharedReference(undefined);
|
|
70
71
|
var updateDurationOnManifestUpdate$ = fromEvent(manifest, "manifestUpdate").pipe(startWith(null), tap(function () {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
else {
|
|
76
|
-
// TODO handle finished dynamic contents?
|
|
77
|
-
contentDuration.setValue(undefined);
|
|
78
|
-
}
|
|
72
|
+
var duration = manifest.isDynamic ?
|
|
73
|
+
maximumPositionCalculator.getEndingPosition() :
|
|
74
|
+
maximumPositionCalculator.getMaximumAvailablePosition();
|
|
75
|
+
contentDuration.setValue(duration);
|
|
79
76
|
}), ignoreElements());
|
|
80
77
|
var updateDurationAndTimeBoundsOnTrackChange$ = streams.pipe(tap(function (message) {
|
|
81
78
|
if (message.type === "adaptationChange") {
|
|
79
|
+
if (!manifest.isLastPeriodKnown) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
82
|
var lastPeriod = manifest.periods[manifest.periods.length - 1];
|
|
83
83
|
if (message.value.period.id === (lastPeriod === null || lastPeriod === void 0 ? void 0 : lastPeriod.id)) {
|
|
84
|
-
if (message.value.type === "audio") {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
contentDuration.setValue(maximumPositionCalculator.getCurrentMaximumPosition());
|
|
84
|
+
if (message.value.type === "audio" || message.value.type === "video") {
|
|
85
|
+
if (message.value.type === "audio") {
|
|
86
|
+
maximumPositionCalculator
|
|
87
|
+
.updateLastAudioAdaptation(message.value.adaptation);
|
|
89
88
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
.updateLastVideoAdaptation(message.value.adaptation);
|
|
94
|
-
if (!manifest.isDynamic) {
|
|
95
|
-
contentDuration.setValue(maximumPositionCalculator.getCurrentMaximumPosition());
|
|
89
|
+
else {
|
|
90
|
+
maximumPositionCalculator
|
|
91
|
+
.updateLastVideoAdaptation(message.value.adaptation);
|
|
96
92
|
}
|
|
93
|
+
var newDuration = manifest.isDynamic ?
|
|
94
|
+
maximumPositionCalculator.getMaximumAvailablePosition() :
|
|
95
|
+
maximumPositionCalculator.getEndingPosition();
|
|
96
|
+
contentDuration.setValue(newDuration);
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
}
|
|
@@ -119,7 +119,7 @@ var MaximumPositionCalculator = /** @class */ (function () {
|
|
|
119
119
|
* If no Adaptation has been set, it should be set to `null`.
|
|
120
120
|
*
|
|
121
121
|
* Allows to calculate the maximum position more precizely in
|
|
122
|
-
* `
|
|
122
|
+
* `getMaximumAvailablePosition` and `getEndingPosition`.
|
|
123
123
|
* @param {Object|null} adaptation
|
|
124
124
|
*/
|
|
125
125
|
MaximumPositionCalculator.prototype.updateLastAudioAdaptation = function (adaptation) {
|
|
@@ -130,18 +130,18 @@ var MaximumPositionCalculator = /** @class */ (function () {
|
|
|
130
130
|
* If no Adaptation has been set, it should be set to `null`.
|
|
131
131
|
*
|
|
132
132
|
* Allows to calculate the maximum position more precizely in
|
|
133
|
-
* `
|
|
133
|
+
* `getMaximumAvailablePosition` and `getEndingPosition`.
|
|
134
134
|
* @param {Object|null} adaptation
|
|
135
135
|
*/
|
|
136
136
|
MaximumPositionCalculator.prototype.updateLastVideoAdaptation = function (adaptation) {
|
|
137
137
|
this._lastVideoAdaptation = adaptation;
|
|
138
138
|
};
|
|
139
139
|
/**
|
|
140
|
-
* Returns an estimate of the maximum position reachable
|
|
141
|
-
* circumstances.
|
|
140
|
+
* Returns an estimate of the maximum position currently reachable (i.e.
|
|
141
|
+
* segments are available) under the current circumstances.
|
|
142
142
|
* @returns {number}
|
|
143
143
|
*/
|
|
144
|
-
MaximumPositionCalculator.prototype.
|
|
144
|
+
MaximumPositionCalculator.prototype.getMaximumAvailablePosition = function () {
|
|
145
145
|
var _a;
|
|
146
146
|
if (this._manifest.isDynamic) {
|
|
147
147
|
return (_a = this._manifest.getLivePosition()) !== null && _a !== void 0 ? _a : this._manifest.getMaximumSafePosition();
|
|
@@ -155,7 +155,7 @@ var MaximumPositionCalculator = /** @class */ (function () {
|
|
|
155
155
|
return this._manifest.getMaximumSafePosition();
|
|
156
156
|
}
|
|
157
157
|
else {
|
|
158
|
-
var lastVideoPosition =
|
|
158
|
+
var lastVideoPosition = getLastAvailablePositionFromAdaptation(this._lastVideoAdaptation);
|
|
159
159
|
if (typeof lastVideoPosition !== "number") {
|
|
160
160
|
return this._manifest.getMaximumSafePosition();
|
|
161
161
|
}
|
|
@@ -163,15 +163,15 @@ var MaximumPositionCalculator = /** @class */ (function () {
|
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
165
|
else if (this._lastVideoAdaptation === null) {
|
|
166
|
-
var lastAudioPosition =
|
|
166
|
+
var lastAudioPosition = getLastAvailablePositionFromAdaptation(this._lastAudioAdaptation);
|
|
167
167
|
if (typeof lastAudioPosition !== "number") {
|
|
168
168
|
return this._manifest.getMaximumSafePosition();
|
|
169
169
|
}
|
|
170
170
|
return lastAudioPosition;
|
|
171
171
|
}
|
|
172
172
|
else {
|
|
173
|
-
var lastAudioPosition =
|
|
174
|
-
var lastVideoPosition =
|
|
173
|
+
var lastAudioPosition = getLastAvailablePositionFromAdaptation(this._lastAudioAdaptation);
|
|
174
|
+
var lastVideoPosition = getLastAvailablePositionFromAdaptation(this._lastVideoAdaptation);
|
|
175
175
|
if (typeof lastAudioPosition !== "number" ||
|
|
176
176
|
typeof lastVideoPosition !== "number") {
|
|
177
177
|
return this._manifest.getMaximumSafePosition();
|
|
@@ -181,20 +181,58 @@ var MaximumPositionCalculator = /** @class */ (function () {
|
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
};
|
|
184
|
+
/**
|
|
185
|
+
* Returns an estimate of the actual ending position once
|
|
186
|
+
* the full content is available.
|
|
187
|
+
* Returns `undefined` if that could not be determined, for various reasons.
|
|
188
|
+
* @returns {number|undefined}
|
|
189
|
+
*/
|
|
190
|
+
MaximumPositionCalculator.prototype.getEndingPosition = function () {
|
|
191
|
+
var _a, _b;
|
|
192
|
+
if (!this._manifest.isDynamic) {
|
|
193
|
+
return this.getMaximumAvailablePosition();
|
|
194
|
+
}
|
|
195
|
+
if (this._lastVideoAdaptation === undefined ||
|
|
196
|
+
this._lastAudioAdaptation === undefined) {
|
|
197
|
+
return undefined;
|
|
198
|
+
}
|
|
199
|
+
else if (this._lastAudioAdaptation === null) {
|
|
200
|
+
if (this._lastVideoAdaptation === null) {
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
return (_a = getEndingPositionFromAdaptation(this._lastVideoAdaptation)) !== null && _a !== void 0 ? _a : undefined;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
else if (this._lastVideoAdaptation === null) {
|
|
208
|
+
return (_b = getEndingPositionFromAdaptation(this._lastAudioAdaptation)) !== null && _b !== void 0 ? _b : undefined;
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
var lastAudioPosition = getEndingPositionFromAdaptation(this._lastAudioAdaptation);
|
|
212
|
+
var lastVideoPosition = getEndingPositionFromAdaptation(this._lastVideoAdaptation);
|
|
213
|
+
if (typeof lastAudioPosition !== "number" ||
|
|
214
|
+
typeof lastVideoPosition !== "number") {
|
|
215
|
+
return undefined;
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
return Math.min(lastAudioPosition, lastVideoPosition);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
};
|
|
184
222
|
return MaximumPositionCalculator;
|
|
185
223
|
}());
|
|
186
224
|
/**
|
|
187
|
-
* Returns
|
|
225
|
+
* Returns last currently available position from the Adaptation given.
|
|
188
226
|
* `undefined` if a time could not be found.
|
|
189
|
-
*
|
|
227
|
+
* `null` if the Adaptation has no segments (it could be that it didn't started or
|
|
190
228
|
* that it already finished for example).
|
|
191
229
|
*
|
|
192
|
-
* We consider the earliest last
|
|
193
|
-
*
|
|
230
|
+
* We consider the earliest last available position from every Representation
|
|
231
|
+
* in the given Adaptation.
|
|
194
232
|
* @param {Object} adaptation
|
|
195
233
|
* @returns {Number|undefined|null}
|
|
196
234
|
*/
|
|
197
|
-
function
|
|
235
|
+
function getLastAvailablePositionFromAdaptation(adaptation) {
|
|
198
236
|
var representations = adaptation.representations;
|
|
199
237
|
var min = null;
|
|
200
238
|
/**
|
|
@@ -207,18 +245,52 @@ function getLastPositionFromAdaptation(adaptation) {
|
|
|
207
245
|
for (var i = 0; i < representations.length; i++) {
|
|
208
246
|
if (representations[i].index !== lastIndex) {
|
|
209
247
|
lastIndex = representations[i].index;
|
|
210
|
-
var lastPosition = representations[i].index.
|
|
248
|
+
var lastPosition = representations[i].index.getLastAvailablePosition();
|
|
211
249
|
if (lastPosition === undefined) { // we cannot tell
|
|
212
250
|
return undefined;
|
|
213
251
|
}
|
|
214
252
|
if (lastPosition !== null) {
|
|
215
|
-
min = min
|
|
253
|
+
min = isNullOrUndefined(min) ? lastPosition :
|
|
216
254
|
Math.min(min, lastPosition);
|
|
217
255
|
}
|
|
218
256
|
}
|
|
219
257
|
}
|
|
220
|
-
|
|
221
|
-
|
|
258
|
+
return min;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Returns ending time from the Adaptation given, once all its segments are
|
|
262
|
+
* available.
|
|
263
|
+
* `undefined` if a time could not be found.
|
|
264
|
+
* `null` if the Adaptation has no segments (it could be that it already
|
|
265
|
+
* finished for example).
|
|
266
|
+
*
|
|
267
|
+
* We consider the earliest ending time from every Representation in the given
|
|
268
|
+
* Adaptation.
|
|
269
|
+
* @param {Object} adaptation
|
|
270
|
+
* @returns {Number|undefined|null}
|
|
271
|
+
*/
|
|
272
|
+
function getEndingPositionFromAdaptation(adaptation) {
|
|
273
|
+
var representations = adaptation.representations;
|
|
274
|
+
var min = null;
|
|
275
|
+
/**
|
|
276
|
+
* Some Manifest parsers use the exact same `IRepresentationIndex` reference
|
|
277
|
+
* for each Representation of a given Adaptation, because in the actual source
|
|
278
|
+
* Manifest file, indexing data is often defined at Adaptation-level.
|
|
279
|
+
* This variable allows to optimize the logic here when this is the case.
|
|
280
|
+
*/
|
|
281
|
+
var lastIndex;
|
|
282
|
+
for (var i = 0; i < representations.length; i++) {
|
|
283
|
+
if (representations[i].index !== lastIndex) {
|
|
284
|
+
lastIndex = representations[i].index;
|
|
285
|
+
var lastPosition = representations[i].index.getEnd();
|
|
286
|
+
if (lastPosition === undefined) { // we cannot tell
|
|
287
|
+
return undefined;
|
|
288
|
+
}
|
|
289
|
+
if (lastPosition !== null) {
|
|
290
|
+
min = isNullOrUndefined(min) ? lastPosition :
|
|
291
|
+
Math.min(min, lastPosition);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
222
294
|
}
|
|
223
295
|
return min;
|
|
224
296
|
}
|
|
@@ -108,7 +108,7 @@ export default function initializeDirectfileContent(_a) {
|
|
|
108
108
|
* Observable trying to avoid various stalling situations, emitting "stalled"
|
|
109
109
|
* events when it cannot, as well as "unstalled" events when it get out of one.
|
|
110
110
|
*/
|
|
111
|
-
var stallAvoider$ = StallAvoider(playbackObserver, null, EMPTY, EMPTY);
|
|
111
|
+
var stallAvoider$ = StallAvoider(playbackObserver, null, speed, EMPTY, EMPTY);
|
|
112
112
|
/**
|
|
113
113
|
* Emit a "loaded" events once the initial play has been performed and the
|
|
114
114
|
* media can begin playback.
|
|
@@ -106,7 +106,7 @@ export default function createMediaSourceLoader(_a) {
|
|
|
106
106
|
* Observable trying to avoid various stalling situations, emitting "stalled"
|
|
107
107
|
* events when it cannot, as well as "unstalled" events when it get out of one.
|
|
108
108
|
*/
|
|
109
|
-
var stallAvoider$ = StallAvoider(playbackObserver, manifest, lockedStream$, discontinuityUpdate$);
|
|
109
|
+
var stallAvoider$ = StallAvoider(playbackObserver, manifest, speed, lockedStream$, discontinuityUpdate$);
|
|
110
110
|
/**
|
|
111
111
|
* Emit a "loaded" events once the initial play has been performed and the
|
|
112
112
|
* media can begin playback.
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { Observable } from "rxjs";
|
|
17
17
|
import Manifest, { Period } from "../../manifest";
|
|
18
|
+
import { IReadOnlySharedReference } from "../../utils/reference";
|
|
18
19
|
import { PlaybackObserver } from "../api";
|
|
19
20
|
import { IBufferType } from "../segment_buffers";
|
|
20
21
|
import { IStalledEvent, IUnstalledEvent, IWarningEvent } from "./types";
|
|
@@ -67,9 +68,10 @@ export interface IDiscontinuityTimeInfo {
|
|
|
67
68
|
* encountered and exited.
|
|
68
69
|
* @param {object} playbackObserver - emit the current playback conditions.
|
|
69
70
|
* @param {Object} manifest - The Manifest of the currently-played content.
|
|
71
|
+
* @param {Object} speed - The last speed set by the user
|
|
72
|
+
* @param {Observable} lockedStream$
|
|
70
73
|
* @param {Observable} discontinuityUpdate$ - Observable emitting encountered
|
|
71
74
|
* discontinuities for loaded Period and buffer types.
|
|
72
|
-
* @param {Function} setCurrentTime
|
|
73
75
|
* @returns {Observable}
|
|
74
76
|
*/
|
|
75
|
-
export default function StallAvoider(playbackObserver: PlaybackObserver, manifest: Manifest | null, lockedStream$: Observable<ILockedStreamEvent>, discontinuityUpdate$: Observable<IDiscontinuityEvent>): Observable<IStalledEvent | IUnstalledEvent | IWarningEvent>;
|
|
77
|
+
export default function StallAvoider(playbackObserver: PlaybackObserver, manifest: Manifest | null, speed: IReadOnlySharedReference<number>, lockedStream$: Observable<ILockedStreamEvent>, discontinuityUpdate$: Observable<IDiscontinuityEvent>): Observable<IStalledEvent | IUnstalledEvent | IWarningEvent>;
|