rx-player 4.0.0-beta.1 → 4.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/CONTRIBUTING.md +48 -168
- package/FILES.md +40 -92
- package/VERSION +1 -1
- package/dist/_esm5.processed/compat/browser_detection.d.ts +3 -1
- package/dist/_esm5.processed/compat/browser_detection.js +7 -2
- package/dist/_esm5.processed/compat/eme/load_session.js +1 -1
- package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.d.ts +21 -0
- package/dist/_esm5.processed/compat/has_issues_with_high_media_source_duration.js +26 -0
- package/dist/_esm5.processed/config.d.ts +2 -0
- package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +5 -4
- package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.d.ts +18 -1
- package/dist/_esm5.processed/core/adaptive/buffer_based_chooser.js +106 -25
- package/dist/_esm5.processed/core/adaptive/guess_based_chooser.js +6 -6
- package/dist/_esm5.processed/core/adaptive/network_analyzer.js +8 -5
- package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.d.ts +19 -1
- package/dist/_esm5.processed/core/adaptive/utils/representation_score_calculator.js +1 -1
- package/dist/_esm5.processed/core/api/debug/render.js +1 -1
- package/dist/_esm5.processed/core/api/playback_observer.js +1 -0
- package/dist/_esm5.processed/core/api/public_api.d.ts +54 -1
- package/dist/_esm5.processed/core/api/public_api.js +232 -35
- package/dist/_esm5.processed/core/api/track_management/media_element_tracks_store.js +10 -1
- package/dist/_esm5.processed/core/api/track_management/track_dispatcher.d.ts +13 -1
- package/dist/_esm5.processed/core/api/track_management/track_dispatcher.js +30 -15
- package/dist/_esm5.processed/core/api/track_management/tracks_store.d.ts +3 -1
- package/dist/_esm5.processed/core/api/track_management/tracks_store.js +67 -152
- package/dist/_esm5.processed/core/api/utils.d.ts +10 -0
- package/dist/_esm5.processed/core/api/utils.js +20 -0
- package/dist/_esm5.processed/core/decrypt/session_events_listener.js +7 -1
- package/dist/_esm5.processed/core/decrypt/utils/clean_old_loaded_sessions.js +2 -0
- package/dist/_esm5.processed/core/decrypt/utils/loaded_sessions_store.js +5 -1
- package/dist/_esm5.processed/core/init/directfile_content_initializer.js +1 -1
- package/dist/_esm5.processed/core/init/media_source_content_initializer.js +47 -10
- package/dist/_esm5.processed/core/init/types.d.ts +9 -1
- package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.d.ts +28 -1
- package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.js +22 -9
- package/dist/_esm5.processed/core/init/utils/media_source_duration_updater.d.ts +58 -0
- package/dist/_esm5.processed/core/init/utils/{media_duration_updater.js → media_source_duration_updater.js} +84 -87
- package/dist/_esm5.processed/core/init/utils/rebuffering_controller.d.ts +36 -2
- package/dist/_esm5.processed/core/init/utils/rebuffering_controller.js +82 -2
- package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.d.ts +18 -7
- package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +31 -40
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.d.ts +8 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +12 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.d.ts +8 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/native/native_text_segment_buffer.js +12 -0
- package/dist/_esm5.processed/core/segment_buffers/implementations/types.d.ts +11 -4
- package/dist/_esm5.processed/core/segment_buffers/index.d.ts +2 -2
- package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.d.ts +47 -0
- package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.js +70 -0
- package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +15 -8
- package/dist/_esm5.processed/core/stream/period/period_stream.js +1 -1
- package/dist/_esm5.processed/core/stream/representation/representation_stream.js +22 -13
- package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.d.ts +4 -2
- package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.js +2 -2
- package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.d.ts +3 -2
- package/dist/_esm5.processed/core/stream/representation/utils/push_init_segment.js +8 -8
- package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.d.ts +2 -2
- package/dist/_esm5.processed/core/stream/representation/utils/push_media_segment.js +2 -3
- package/dist/_esm5.processed/default_config.d.ts +25 -0
- package/dist/_esm5.processed/default_config.js +27 -2
- package/dist/_esm5.processed/errors/index.d.ts +2 -2
- package/dist/_esm5.processed/errors/media_error.d.ts +23 -1
- package/dist/_esm5.processed/errors/media_error.js +18 -5
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.d.ts +1 -1
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/load_and_push_segment.js +8 -7
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +17 -9
- package/dist/_esm5.processed/experimental/tools/mediaCapabilitiesProber/index.js +0 -2
- package/dist/_esm5.processed/manifest/adaptation.d.ts +21 -2
- package/dist/_esm5.processed/manifest/adaptation.js +76 -1
- package/dist/_esm5.processed/manifest/manifest.js +1 -1
- package/dist/_esm5.processed/manifest/period.js +2 -2
- package/dist/_esm5.processed/manifest/representation.d.ts +33 -2
- package/dist/_esm5.processed/manifest/representation.js +21 -0
- package/dist/_esm5.processed/manifest/utils.js +1 -3
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.d.ts +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/js-parser/parse_from_document.js +1 -1
- package/dist/_esm5.processed/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.js +1 -0
- package/dist/_esm5.processed/public_types.d.ts +13 -3
- package/dist/_esm5.processed/tools/TextTrackRenderer/text_track_renderer.js +1 -1
- package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.d.ts +4 -6
- package/dist/_esm5.processed/transports/smooth/isobmff/create_boxes.js +4 -6
- package/dist/_esm5.processed/utils/is_null_or_undefined.d.ts +1 -1
- package/dist/_esm5.processed/utils/is_null_or_undefined.js +1 -1
- package/dist/mpd-parser.wasm +0 -0
- package/dist/rx-player.js +4709 -4218
- package/dist/rx-player.min.js +1 -1
- package/package.json +42 -36
- package/scripts/build/generate_build.js +1 -1
- package/scripts/fast_demo_build.js +4 -3
- package/scripts/generate_full_demo.js +1 -1
- package/sonar-project.properties +1 -1
- package/src/compat/browser_detection.ts +7 -1
- package/src/compat/eme/load_session.ts +1 -1
- package/src/compat/has_issues_with_high_media_source_duration.ts +27 -0
- package/src/core/adaptive/__tests__/buffer_based_chooser.test.ts +147 -48
- package/src/core/adaptive/adaptive_representation_selector.ts +7 -4
- package/src/core/adaptive/buffer_based_chooser.ts +144 -26
- package/src/core/adaptive/guess_based_chooser.ts +9 -8
- package/src/core/adaptive/network_analyzer.ts +9 -4
- package/src/core/adaptive/utils/representation_score_calculator.ts +22 -2
- package/src/core/api/debug/render.ts +1 -1
- package/src/core/api/playback_observer.ts +1 -0
- package/src/core/api/public_api.ts +277 -44
- package/src/core/api/track_management/media_element_tracks_store.ts +17 -8
- package/src/core/api/track_management/track_dispatcher.ts +37 -14
- package/src/core/api/track_management/tracks_store.ts +77 -167
- package/src/core/api/utils.ts +26 -0
- package/src/core/decrypt/session_events_listener.ts +6 -1
- package/src/core/decrypt/utils/clean_old_loaded_sessions.ts +2 -1
- package/src/core/decrypt/utils/loaded_sessions_store.ts +8 -1
- package/src/core/init/directfile_content_initializer.ts +1 -0
- package/src/core/init/media_source_content_initializer.ts +52 -9
- package/src/core/init/types.ts +9 -1
- package/src/core/init/utils/content_time_boundaries_observer.ts +46 -10
- package/src/core/init/utils/{media_duration_updater.ts → media_source_duration_updater.ts} +100 -112
- package/src/core/init/utils/rebuffering_controller.ts +114 -3
- package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +56 -55
- package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +16 -0
- package/src/core/segment_buffers/implementations/text/native/native_text_segment_buffer.ts +16 -0
- package/src/core/segment_buffers/implementations/types.ts +16 -4
- package/src/core/segment_buffers/index.ts +2 -0
- package/src/core/stream/adaptation/utils/create_representation_estimator.ts +114 -0
- package/src/core/stream/orchestrator/stream_orchestrator.ts +16 -8
- package/src/core/stream/period/period_stream.ts +2 -1
- package/src/core/stream/representation/representation_stream.ts +34 -22
- package/src/core/stream/representation/utils/append_segment_to_buffer.ts +8 -3
- package/src/core/stream/representation/utils/push_init_segment.ts +11 -6
- package/src/core/stream/representation/utils/push_media_segment.ts +3 -3
- package/src/default_config.ts +29 -2
- package/src/errors/__tests__/media_error.test.ts +6 -6
- package/src/errors/index.ts +4 -1
- package/src/errors/media_error.ts +67 -1
- package/src/experimental/tools/VideoThumbnailLoader/load_and_push_segment.ts +10 -7
- package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +17 -6
- package/src/experimental/tools/mediaCapabilitiesProber/index.ts +0 -4
- package/src/manifest/__tests__/manifest.test.ts +7 -7
- package/src/manifest/__tests__/period.test.ts +90 -45
- package/src/manifest/adaptation.ts +89 -1
- package/src/manifest/manifest.ts +1 -1
- package/src/manifest/period.ts +4 -2
- package/src/manifest/representation.ts +67 -1
- package/src/manifest/utils.ts +1 -3
- package/src/parsers/manifest/dash/js-parser/parse_from_document.ts +1 -1
- package/src/parsers/manifest/dash/wasm-parser/ts/dash-wasm-parser.ts +1 -0
- package/src/parsers/texttracks/ttml/parse_ttml.ts +1 -1
- package/src/public_types.ts +16 -1
- package/src/tools/TextTrackRenderer/text_track_renderer.ts +1 -1
- package/src/transports/smooth/isobmff/create_boxes.ts +4 -6
- package/src/typings/globals.d.ts +20 -20
- package/src/utils/is_null_or_undefined.ts +1 -1
- package/dist/_esm5.processed/core/init/utils/media_duration_updater.d.ts +0 -56
- package/scripts/doc-generator/construct_table_of_contents.js +0 -76
- package/scripts/doc-generator/convert_MD_to_HMTL.js +0 -26
- package/scripts/doc-generator/create_documentation.js +0 -331
- package/scripts/doc-generator/create_documentation_page.js +0 -209
- package/scripts/doc-generator/create_page.js +0 -210
- package/scripts/doc-generator/generate_header_html.js +0 -147
- package/scripts/doc-generator/generate_page_html.js +0 -115
- package/scripts/doc-generator/generate_page_list_html.js +0 -92
- package/scripts/doc-generator/generate_sidebar_html.js +0 -85
- package/scripts/doc-generator/get_search_data_for_content.js +0 -137
- package/scripts/doc-generator/index.js +0 -34
- package/scripts/doc-generator/parse_doc_configs.js +0 -327
- package/scripts/doc-generator/scripts/lunr.js +0 -10
- package/scripts/doc-generator/scripts/script.js +0 -451
- package/scripts/doc-generator/styles/code.css +0 -99
- package/scripts/doc-generator/styles/style.css +0 -835
- package/scripts/doc-generator/utils.js +0 -74
|
@@ -55,14 +55,16 @@ var RebufferingController = /** @class */ (function (_super) {
|
|
|
55
55
|
* @param {Object} manifest - The Manifest of the currently-played content.
|
|
56
56
|
* @param {Object} speed - The last speed set by the user
|
|
57
57
|
*/
|
|
58
|
-
function RebufferingController(playbackObserver, manifest, speed) {
|
|
58
|
+
function RebufferingController(playbackObserver, manifest, segmentBuffersStore, speed) {
|
|
59
59
|
var _this = _super.call(this) || this;
|
|
60
60
|
_this._playbackObserver = playbackObserver;
|
|
61
61
|
_this._manifest = manifest;
|
|
62
|
+
_this._segmentBuffersStore = segmentBuffersStore;
|
|
62
63
|
_this._speed = speed;
|
|
63
64
|
_this._discontinuitiesStore = [];
|
|
64
65
|
_this._isStarted = false;
|
|
65
66
|
_this._canceller = new TaskCanceller();
|
|
67
|
+
_this._currentFreezeTimestamp = null;
|
|
66
68
|
return _this;
|
|
67
69
|
}
|
|
68
70
|
RebufferingController.prototype.start = function () {
|
|
@@ -117,6 +119,9 @@ var RebufferingController = /** @class */ (function (_super) {
|
|
|
117
119
|
lastSeekingPosition = observation.seeking ?
|
|
118
120
|
Math.max((_a = observation.pendingInternalSeek) !== null && _a !== void 0 ? _a : 0, observation.position) :
|
|
119
121
|
null;
|
|
122
|
+
if (_this._checkDecipherabilityFreeze(observation)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
120
125
|
if (freezing !== null) {
|
|
121
126
|
var now = performance.now();
|
|
122
127
|
var referenceTimestamp = prevFreezingState === null ?
|
|
@@ -175,7 +180,7 @@ var RebufferingController = /** @class */ (function (_super) {
|
|
|
175
180
|
return;
|
|
176
181
|
}
|
|
177
182
|
else {
|
|
178
|
-
log.warn("Init: ignored stall for too long,
|
|
183
|
+
log.warn("Init: ignored stall for too long, considering it", now - ignoredStallTimeStamp);
|
|
179
184
|
}
|
|
180
185
|
}
|
|
181
186
|
ignoredStallTimeStamp = null;
|
|
@@ -291,6 +296,81 @@ var RebufferingController = /** @class */ (function (_super) {
|
|
|
291
296
|
RebufferingController.prototype.destroy = function () {
|
|
292
297
|
this._canceller.cancel();
|
|
293
298
|
};
|
|
299
|
+
/**
|
|
300
|
+
* Support of contents with DRM on all the platforms out there is a pain in
|
|
301
|
+
* the *ss considering all the DRM-related bugs there are.
|
|
302
|
+
*
|
|
303
|
+
* We found out a frequent issue which is to be unable to play despite having
|
|
304
|
+
* all the decryption keys to play what is currently buffered.
|
|
305
|
+
* When this happens, re-creating the buffers from scratch, with a reload, is
|
|
306
|
+
* usually sufficient to unlock the situation.
|
|
307
|
+
*
|
|
308
|
+
* Although we prefer providing more targeted fixes or telling to platform
|
|
309
|
+
* developpers to fix their implementation, it's not always possible.
|
|
310
|
+
* We thus resorted to developping an heuristic which detects such situation
|
|
311
|
+
* and reload in that case.
|
|
312
|
+
*
|
|
313
|
+
* @param {Object} observation - The last playback observation produced, it
|
|
314
|
+
* has to be recent (just triggered for example).
|
|
315
|
+
* @returns {boolean} - Returns `true` if it seems to be such kind of
|
|
316
|
+
* decipherability freeze, in which case this method already performed the
|
|
317
|
+
* right handling steps.
|
|
318
|
+
*/
|
|
319
|
+
RebufferingController.prototype._checkDecipherabilityFreeze = function (observation) {
|
|
320
|
+
var readyState = observation.readyState, rebuffering = observation.rebuffering, freezing = observation.freezing;
|
|
321
|
+
var bufferGap = observation.bufferGap !== undefined &&
|
|
322
|
+
isFinite(observation.bufferGap) ? observation.bufferGap :
|
|
323
|
+
0;
|
|
324
|
+
if (this._segmentBuffersStore === null ||
|
|
325
|
+
bufferGap < 6 ||
|
|
326
|
+
(rebuffering === null && freezing === null) ||
|
|
327
|
+
readyState > 1) {
|
|
328
|
+
this._currentFreezeTimestamp = null;
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
var now = performance.now();
|
|
332
|
+
if (this._currentFreezeTimestamp === null) {
|
|
333
|
+
this._currentFreezeTimestamp = now;
|
|
334
|
+
}
|
|
335
|
+
var rebufferingForTooLong = rebuffering !== null && now - rebuffering.timestamp > 4000;
|
|
336
|
+
var frozenForTooLong = freezing !== null && now - freezing.timestamp > 4000;
|
|
337
|
+
if ((rebufferingForTooLong || frozenForTooLong) &&
|
|
338
|
+
performance.now() - this._currentFreezeTimestamp > 4000) {
|
|
339
|
+
var statusAudio = this._segmentBuffersStore.getStatus("audio");
|
|
340
|
+
var statusVideo = this._segmentBuffersStore.getStatus("video");
|
|
341
|
+
var hasOnlyDecipherableSegments = true;
|
|
342
|
+
var isClear = true;
|
|
343
|
+
for (var _i = 0, _a = [statusAudio, statusVideo]; _i < _a.length; _i++) {
|
|
344
|
+
var status_1 = _a[_i];
|
|
345
|
+
if (status_1.type === "initialized") {
|
|
346
|
+
for (var _b = 0, _c = status_1.value.getInventory(); _b < _c.length; _b++) {
|
|
347
|
+
var segment = _c[_b];
|
|
348
|
+
var representation = segment.infos.representation;
|
|
349
|
+
if (representation.decipherable === false) {
|
|
350
|
+
log.warn("Init: we have undecipherable segments left in the buffer, reloading");
|
|
351
|
+
this._currentFreezeTimestamp = null;
|
|
352
|
+
this.trigger("needsReload", null);
|
|
353
|
+
return true;
|
|
354
|
+
}
|
|
355
|
+
else if (representation.contentProtections !== undefined) {
|
|
356
|
+
isClear = false;
|
|
357
|
+
if (representation.decipherable !== true) {
|
|
358
|
+
hasOnlyDecipherableSegments = false;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
if (!isClear && hasOnlyDecipherableSegments) {
|
|
365
|
+
log.warn("Init: we are frozen despite only having decipherable " +
|
|
366
|
+
"segments left in the buffer, reloading");
|
|
367
|
+
this._currentFreezeTimestamp = null;
|
|
368
|
+
this.trigger("needsReload", null);
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return false;
|
|
373
|
+
};
|
|
294
374
|
return RebufferingController;
|
|
295
375
|
}(EventEmitter));
|
|
296
376
|
export default RebufferingController;
|
|
@@ -49,16 +49,25 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
|
|
|
49
49
|
*/
|
|
50
50
|
private _pendingTask;
|
|
51
51
|
/**
|
|
52
|
-
* Keep track of the of the latest init segment
|
|
53
|
-
* SourceBuffer.
|
|
52
|
+
* Keep track of the unique identifier of the of the latest init segment
|
|
53
|
+
* pushed to the linked SourceBuffer.
|
|
54
54
|
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
55
|
+
* Such identifiers are first declared through the `declareInitSegment`
|
|
56
|
+
* method and the corresponding initialization segment is then pushed through
|
|
57
|
+
* the `pushChunk` method.
|
|
58
|
+
*
|
|
59
|
+
* Keeping track of this allows to be sure the right initialization segment is
|
|
60
|
+
* pushed before any chunk is.
|
|
57
61
|
*
|
|
58
62
|
* `null` if no initialization segment have been pushed to the
|
|
59
63
|
* `AudioVideoSegmentBuffer` yet.
|
|
60
64
|
*/
|
|
61
|
-
private
|
|
65
|
+
private _lastInitSegmentUniqueId;
|
|
66
|
+
/**
|
|
67
|
+
* Link unique identifiers for initialization segments (as communicated by
|
|
68
|
+
* `declareInitSegment`) to the corresponding initialization data.
|
|
69
|
+
*/
|
|
70
|
+
private _initSegmentsMap;
|
|
62
71
|
/**
|
|
63
72
|
* @constructor
|
|
64
73
|
* @param {string} bufferType
|
|
@@ -66,6 +75,8 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
|
|
|
66
75
|
* @param {MediaSource} mediaSource
|
|
67
76
|
*/
|
|
68
77
|
constructor(bufferType: "audio" | "video", codec: string, mediaSource: MediaSource);
|
|
78
|
+
declareInitSegment(uniqueId: string, initSegmentData: unknown): void;
|
|
79
|
+
freeInitSegment(uniqueId: string): void;
|
|
69
80
|
/**
|
|
70
81
|
* Push a chunk of the media segment given to the attached SourceBuffer, in a
|
|
71
82
|
* FIFO queue.
|
|
@@ -162,9 +173,9 @@ export default class AudioVideoSegmentBuffer extends SegmentBuffer {
|
|
|
162
173
|
*/
|
|
163
174
|
private _preparePushOperation;
|
|
164
175
|
/**
|
|
165
|
-
* Return `true` if the given `
|
|
176
|
+
* Return `true` if the given `uniqueId` is the identifier of the last
|
|
166
177
|
* initialization segment pushed to the `AudioVideoSegmentBuffer`.
|
|
167
|
-
* @param {
|
|
178
|
+
* @param {string} uniqueId
|
|
168
179
|
* @returns {boolean}
|
|
169
180
|
*/
|
|
170
181
|
private _isLastInitSegment;
|
|
@@ -32,11 +32,8 @@ import { tryToChangeSourceBufferType, } from "../../../../compat";
|
|
|
32
32
|
import config from "../../../../config";
|
|
33
33
|
import log from "../../../../log";
|
|
34
34
|
import { getLoggableSegmentId } from "../../../../manifest";
|
|
35
|
-
import areArraysOfNumbersEqual from "../../../../utils/are_arrays_of_numbers_equal";
|
|
36
35
|
import assertUnreachable from "../../../../utils/assert_unreachable";
|
|
37
|
-
import { toUint8Array } from "../../../../utils/byte_parsing";
|
|
38
36
|
import createCancellablePromise from "../../../../utils/create_cancellable_promise";
|
|
39
|
-
import hashBuffer from "../../../../utils/hash_buffer";
|
|
40
37
|
import noop from "../../../../utils/noop";
|
|
41
38
|
import objectAssign from "../../../../utils/object_assign";
|
|
42
39
|
import TaskCanceller, { CancellationError, } from "../../../../utils/task_canceller";
|
|
@@ -68,8 +65,9 @@ var AudioVideoSegmentBuffer = /** @class */ (function (_super) {
|
|
|
68
65
|
_this._sourceBuffer = sourceBuffer;
|
|
69
66
|
_this._queue = [];
|
|
70
67
|
_this._pendingTask = null;
|
|
71
|
-
_this.
|
|
68
|
+
_this._lastInitSegmentUniqueId = null;
|
|
72
69
|
_this.codec = codec;
|
|
70
|
+
_this._initSegmentsMap = new Map();
|
|
73
71
|
var onError = _this._onPendingTaskError.bind(_this);
|
|
74
72
|
var reCheck = _this._flush.bind(_this);
|
|
75
73
|
// Some browsers (happened with firefox 66) sometimes "forget" to send us
|
|
@@ -89,6 +87,13 @@ var AudioVideoSegmentBuffer = /** @class */ (function (_super) {
|
|
|
89
87
|
});
|
|
90
88
|
return _this;
|
|
91
89
|
}
|
|
90
|
+
AudioVideoSegmentBuffer.prototype.declareInitSegment = function (uniqueId, initSegmentData) {
|
|
91
|
+
assertDataIsBufferSource(initSegmentData);
|
|
92
|
+
this._initSegmentsMap.set(uniqueId, initSegmentData);
|
|
93
|
+
};
|
|
94
|
+
AudioVideoSegmentBuffer.prototype.freeInitSegment = function (uniqueId) {
|
|
95
|
+
this._initSegmentsMap.delete(uniqueId);
|
|
96
|
+
};
|
|
92
97
|
/**
|
|
93
98
|
* Push a chunk of the media segment given to the attached SourceBuffer, in a
|
|
94
99
|
* FIFO queue.
|
|
@@ -117,7 +122,7 @@ var AudioVideoSegmentBuffer = /** @class */ (function (_super) {
|
|
|
117
122
|
* @returns {Promise}
|
|
118
123
|
*/
|
|
119
124
|
AudioVideoSegmentBuffer.prototype.pushChunk = function (infos, cancellationSignal) {
|
|
120
|
-
|
|
125
|
+
assertDataIsBufferSource(infos.data.chunk);
|
|
121
126
|
log.debug("AVSB: receiving order to push data to the SourceBuffer", this.bufferType, getLoggableSegmentId(infos.inventoryInfos));
|
|
122
127
|
return this._addToQueue({ type: SegmentBufferOperation.Push,
|
|
123
128
|
value: infos }, cancellationSignal);
|
|
@@ -211,7 +216,7 @@ var AudioVideoSegmentBuffer = /** @class */ (function (_super) {
|
|
|
211
216
|
* @param {Event} err
|
|
212
217
|
*/
|
|
213
218
|
AudioVideoSegmentBuffer.prototype._onPendingTaskError = function (err) {
|
|
214
|
-
this.
|
|
219
|
+
this._lastInitSegmentUniqueId = null; // initialize init segment as a security
|
|
215
220
|
if (this._pendingTask !== null) {
|
|
216
221
|
var error = err instanceof Error ?
|
|
217
222
|
err :
|
|
@@ -304,7 +309,7 @@ var AudioVideoSegmentBuffer = /** @class */ (function (_super) {
|
|
|
304
309
|
var error = e instanceof Error ?
|
|
305
310
|
e :
|
|
306
311
|
new Error("An unknown error occured when preparing a push operation");
|
|
307
|
-
this.
|
|
312
|
+
this._lastInitSegmentUniqueId = null; // initialize init segment as a security
|
|
308
313
|
nextItem.reject(error);
|
|
309
314
|
return;
|
|
310
315
|
}
|
|
@@ -392,14 +397,16 @@ var AudioVideoSegmentBuffer = /** @class */ (function (_super) {
|
|
|
392
397
|
else if (appendWindow[1] !== this._sourceBuffer.appendWindowEnd) {
|
|
393
398
|
this._sourceBuffer.appendWindowEnd = appendWindow[1];
|
|
394
399
|
}
|
|
395
|
-
if (data.
|
|
396
|
-
(hasUpdatedSourceBufferType ||
|
|
400
|
+
if (data.initSegmentUniqueId !== null &&
|
|
401
|
+
(hasUpdatedSourceBufferType ||
|
|
402
|
+
!this._isLastInitSegment(data.initSegmentUniqueId))) {
|
|
397
403
|
// Push initialization segment before the media segment
|
|
398
|
-
var segmentData = data.
|
|
404
|
+
var segmentData = this._initSegmentsMap.get(data.initSegmentUniqueId);
|
|
405
|
+
if (segmentData === undefined) {
|
|
406
|
+
throw new Error("Invalid initialization segment uniqueId");
|
|
407
|
+
}
|
|
399
408
|
dataToPush.push(segmentData);
|
|
400
|
-
|
|
401
|
-
this._lastInitSegment = { data: initU8,
|
|
402
|
-
hash: hashBuffer(initU8) };
|
|
409
|
+
this._lastInitSegmentUniqueId = data.initSegmentUniqueId;
|
|
403
410
|
}
|
|
404
411
|
if (data.chunk !== null) {
|
|
405
412
|
dataToPush.push(data.chunk);
|
|
@@ -407,27 +414,16 @@ var AudioVideoSegmentBuffer = /** @class */ (function (_super) {
|
|
|
407
414
|
return dataToPush;
|
|
408
415
|
};
|
|
409
416
|
/**
|
|
410
|
-
* Return `true` if the given `
|
|
417
|
+
* Return `true` if the given `uniqueId` is the identifier of the last
|
|
411
418
|
* initialization segment pushed to the `AudioVideoSegmentBuffer`.
|
|
412
|
-
* @param {
|
|
419
|
+
* @param {string} uniqueId
|
|
413
420
|
* @returns {boolean}
|
|
414
421
|
*/
|
|
415
|
-
AudioVideoSegmentBuffer.prototype._isLastInitSegment = function (
|
|
416
|
-
if (this.
|
|
422
|
+
AudioVideoSegmentBuffer.prototype._isLastInitSegment = function (uniqueId) {
|
|
423
|
+
if (this._lastInitSegmentUniqueId === null) {
|
|
417
424
|
return false;
|
|
418
425
|
}
|
|
419
|
-
|
|
420
|
-
return true;
|
|
421
|
-
}
|
|
422
|
-
var oldInit = this._lastInitSegment.data;
|
|
423
|
-
if (oldInit.byteLength === segmentData.byteLength) {
|
|
424
|
-
var newInitU8 = toUint8Array(segmentData);
|
|
425
|
-
if (hashBuffer(newInitU8) === this._lastInitSegment.hash &&
|
|
426
|
-
areArraysOfNumbersEqual(oldInit, newInitU8)) {
|
|
427
|
-
return true;
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
return false;
|
|
426
|
+
return this._lastInitSegmentUniqueId === uniqueId;
|
|
431
427
|
};
|
|
432
428
|
return AudioVideoSegmentBuffer;
|
|
433
429
|
}(SegmentBuffer));
|
|
@@ -436,21 +432,16 @@ export default AudioVideoSegmentBuffer;
|
|
|
436
432
|
* Throw if the given input is not in the expected format.
|
|
437
433
|
* Allows to enforce runtime type-checking as compile-time type-checking here is
|
|
438
434
|
* difficult to enforce.
|
|
439
|
-
* @param {Object}
|
|
435
|
+
* @param {Object} data
|
|
440
436
|
*/
|
|
441
|
-
function
|
|
437
|
+
function assertDataIsBufferSource(data) {
|
|
442
438
|
if (0 /* __ENVIRONMENT__.CURRENT_ENV */ === 0 /* __ENVIRONMENT__.PRODUCTION */) {
|
|
443
439
|
return;
|
|
444
440
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
!(chunk instanceof ArrayBuffer) &&
|
|
450
|
-
!(chunk.buffer instanceof ArrayBuffer)) ||
|
|
451
|
-
(initSegment !== null &&
|
|
452
|
-
!(initSegment instanceof ArrayBuffer) &&
|
|
453
|
-
!(initSegment.buffer instanceof ArrayBuffer))) {
|
|
441
|
+
if (typeof data !== "object" ||
|
|
442
|
+
(data !== null &&
|
|
443
|
+
!(data instanceof ArrayBuffer) &&
|
|
444
|
+
!(data.buffer instanceof ArrayBuffer))) {
|
|
454
445
|
throw new Error("Invalid data given to the AudioVideoSegmentBuffer");
|
|
455
446
|
}
|
|
456
447
|
}
|
|
@@ -47,6 +47,14 @@ export default class HTMLTextSegmentBuffer extends SegmentBuffer {
|
|
|
47
47
|
* @param {HTMLElement} textTrackElement
|
|
48
48
|
*/
|
|
49
49
|
constructor(videoElement: HTMLMediaElement, textTrackElement: HTMLElement);
|
|
50
|
+
/**
|
|
51
|
+
* @param {string} uniqueId
|
|
52
|
+
*/
|
|
53
|
+
declareInitSegment(uniqueId: string): void;
|
|
54
|
+
/**
|
|
55
|
+
* @param {string} uniqueId
|
|
56
|
+
*/
|
|
57
|
+
freeInitSegment(uniqueId: string): void;
|
|
50
58
|
/**
|
|
51
59
|
* Push text segment to the HTMLTextSegmentBuffer.
|
|
52
60
|
* @param {Object} infos
|
|
@@ -93,6 +93,18 @@ var HTMLTextSegmentBuffer = /** @class */ (function (_super) {
|
|
|
93
93
|
_this.autoRefreshSubtitles(_this._canceller.signal);
|
|
94
94
|
return _this;
|
|
95
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* @param {string} uniqueId
|
|
98
|
+
*/
|
|
99
|
+
HTMLTextSegmentBuffer.prototype.declareInitSegment = function (uniqueId) {
|
|
100
|
+
log.warn("ISB: Declaring initialization segment for image SegmentBuffer", uniqueId);
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* @param {string} uniqueId
|
|
104
|
+
*/
|
|
105
|
+
HTMLTextSegmentBuffer.prototype.freeInitSegment = function (uniqueId) {
|
|
106
|
+
log.warn("ISB: Freeing initialization segment for image SegmentBuffer", uniqueId);
|
|
107
|
+
};
|
|
96
108
|
/**
|
|
97
109
|
* Push text segment to the HTMLTextSegmentBuffer.
|
|
98
110
|
* @param {Object} infos
|
|
@@ -31,6 +31,14 @@ export default class NativeTextSegmentBuffer extends SegmentBuffer {
|
|
|
31
31
|
* @param {HTMLMediaElement} videoElement
|
|
32
32
|
*/
|
|
33
33
|
constructor(videoElement: HTMLMediaElement);
|
|
34
|
+
/**
|
|
35
|
+
* @param {string} uniqueId
|
|
36
|
+
*/
|
|
37
|
+
declareInitSegment(uniqueId: string): void;
|
|
38
|
+
/**
|
|
39
|
+
* @param {string} uniqueId
|
|
40
|
+
*/
|
|
41
|
+
freeInitSegment(uniqueId: string): void;
|
|
34
42
|
/**
|
|
35
43
|
* @param {Object} infos
|
|
36
44
|
* @returns {Promise}
|
|
@@ -57,6 +57,18 @@ var NativeTextSegmentBuffer = /** @class */ (function (_super) {
|
|
|
57
57
|
_this._trackElement = trackElement;
|
|
58
58
|
return _this;
|
|
59
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* @param {string} uniqueId
|
|
62
|
+
*/
|
|
63
|
+
NativeTextSegmentBuffer.prototype.declareInitSegment = function (uniqueId) {
|
|
64
|
+
log.warn("ISB: Declaring initialization segment for image SegmentBuffer", uniqueId);
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* @param {string} uniqueId
|
|
68
|
+
*/
|
|
69
|
+
NativeTextSegmentBuffer.prototype.freeInitSegment = function (uniqueId) {
|
|
70
|
+
log.warn("ISB: Freeing initialization segment for image SegmentBuffer", uniqueId);
|
|
71
|
+
};
|
|
60
72
|
/**
|
|
61
73
|
* @param {Object} infos
|
|
62
74
|
* @returns {Promise}
|
|
@@ -68,6 +68,8 @@ export declare abstract class SegmentBuffer {
|
|
|
68
68
|
*/
|
|
69
69
|
codec: string | undefined;
|
|
70
70
|
constructor();
|
|
71
|
+
abstract declareInitSegment(uniqueId: string, initSegmentData: unknown): void;
|
|
72
|
+
abstract freeInitSegment(uniqueId: string): void;
|
|
71
73
|
/**
|
|
72
74
|
* Push a chunk of the media segment given to the attached buffer, in a
|
|
73
75
|
* FIFO queue.
|
|
@@ -77,7 +79,8 @@ export declare abstract class SegmentBuffer {
|
|
|
77
79
|
* pushed.
|
|
78
80
|
*
|
|
79
81
|
* Depending on the type of data appended, the pushed chunk might rely on an
|
|
80
|
-
* initialization segment,
|
|
82
|
+
* initialization segment, which had to be previously declared through the
|
|
83
|
+
* `declareInitSegment` method.
|
|
81
84
|
*
|
|
82
85
|
* Such initialization segment will be first pushed to the buffer if the
|
|
83
86
|
* last pushed segment was associated to another initialization segment.
|
|
@@ -87,7 +90,7 @@ export declare abstract class SegmentBuffer {
|
|
|
87
90
|
* reference).
|
|
88
91
|
*
|
|
89
92
|
* If you don't need any initialization segment to push the wanted chunk, you
|
|
90
|
-
* can just set
|
|
93
|
+
* can just set the corresponding property to `null`.
|
|
91
94
|
*
|
|
92
95
|
* You can also only push an initialization segment by setting the
|
|
93
96
|
* `data.chunk` argument to null.
|
|
@@ -177,12 +180,16 @@ export type IBufferType = "audio" | "video" | "text";
|
|
|
177
180
|
*/
|
|
178
181
|
export interface IPushedChunkData<T> {
|
|
179
182
|
/**
|
|
180
|
-
* The
|
|
183
|
+
* The `uniqueId` of the initialization segment linked to the data you want to
|
|
181
184
|
* push.
|
|
185
|
+
*
|
|
186
|
+
* That identifier should previously have been declared through the
|
|
187
|
+
* `declareInitSegment` method and not freed.
|
|
188
|
+
*
|
|
182
189
|
* To set to `null` either if no initialization data is needed, or if you are
|
|
183
190
|
* confident that the last pushed one is compatible.
|
|
184
191
|
*/
|
|
185
|
-
|
|
192
|
+
initSegmentUniqueId: string | null;
|
|
186
193
|
/**
|
|
187
194
|
* Chunk you want to push.
|
|
188
195
|
* This can be the whole decodable segment's data or just a decodable sub-part
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import BufferGarbageCollector from "./garbage_collector";
|
|
17
17
|
import { IBufferType, IEndOfSegmentInfos, IEndOfSegmentOperation, IPushChunkInfos, IPushedChunkData, IPushOperation, IRemoveOperation, ISBOperation, SegmentBuffer, SegmentBufferOperation } from "./implementations";
|
|
18
|
-
import { IBufferedChunk, IChunkContext, getFirstSegmentAfterPeriod, getLastSegmentBeforePeriod } from "./inventory";
|
|
18
|
+
import { IBufferedChunk, IChunkContext, IInsertedChunkInfos, getFirstSegmentAfterPeriod, getLastSegmentBeforePeriod } from "./inventory";
|
|
19
19
|
import SegmentBuffersStore, { ISegmentBufferOptions, ITextTrackSegmentBufferOptions } from "./segment_buffers_store";
|
|
20
20
|
export default SegmentBuffersStore;
|
|
21
|
-
export { BufferGarbageCollector, ISegmentBufferOptions, ITextTrackSegmentBufferOptions, SegmentBuffer, IBufferType, IBufferedChunk, IChunkContext, IPushChunkInfos, IPushedChunkData, IEndOfSegmentInfos, SegmentBufferOperation, ISBOperation, IEndOfSegmentOperation, IPushOperation, IRemoveOperation, getFirstSegmentAfterPeriod, getLastSegmentBeforePeriod, };
|
|
21
|
+
export { BufferGarbageCollector, ISegmentBufferOptions, ITextTrackSegmentBufferOptions, SegmentBuffer, IBufferType, IBufferedChunk, IChunkContext, IInsertedChunkInfos, IPushChunkInfos, IPushedChunkData, IEndOfSegmentInfos, SegmentBufferOperation, ISBOperation, IEndOfSegmentOperation, IPushOperation, IRemoveOperation, getFirstSegmentAfterPeriod, getLastSegmentBeforePeriod, };
|
package/dist/_esm5.processed/core/stream/adaptation/utils/create_representation_estimator.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
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
|
+
import Manifest, { Adaptation, Period, Representation } from "../../../../manifest";
|
|
17
|
+
import { IPlayerError } from "../../../../public_types";
|
|
18
|
+
import { IReadOnlySharedReference } from "../../../../utils/reference";
|
|
19
|
+
import { CancellationSignal } from "../../../../utils/task_canceller";
|
|
20
|
+
import { IABREstimate, IRepresentationEstimatorPlaybackObservation, IRepresentationEstimator, IRepresentationEstimatorCallbacks } from "../../../adaptive";
|
|
21
|
+
import { IReadOnlyPlaybackObserver } from "../../../api";
|
|
22
|
+
/**
|
|
23
|
+
* Produce estimates to know which Representation should be played.
|
|
24
|
+
* @param {Object} content - The Manifest, Period and Adaptation wanted.
|
|
25
|
+
* @param {Object} representationEstimator - `IRepresentationEstimator` which
|
|
26
|
+
* will produce Representation estimates.
|
|
27
|
+
* @param {Object} currentRepresentation - Reference emitting the
|
|
28
|
+
* currently-loaded Representation.
|
|
29
|
+
* @param {Object} playbackObserver - Allows to observe the current playback
|
|
30
|
+
* conditions.
|
|
31
|
+
* @param {Function} onFatalError - Callback called when a fatal error was
|
|
32
|
+
* thrown. Once this callback is called, no estimate will be produced.
|
|
33
|
+
* @param {Object} cancellationSignal - `CancellationSignal` allowing to abort
|
|
34
|
+
* the production of estimates (and clean-up all linked resources).
|
|
35
|
+
* @returns {Object} - Returns an object with the following properties:
|
|
36
|
+
* - `estimateRef`: Reference emitting the last estimate
|
|
37
|
+
* - `abrCallbacks`: Callbacks allowing to report back network and playback
|
|
38
|
+
* activities to improve the estimates given.
|
|
39
|
+
*/
|
|
40
|
+
export default function getRepresentationEstimate(content: {
|
|
41
|
+
manifest: Manifest;
|
|
42
|
+
period: Period;
|
|
43
|
+
adaptation: Adaptation;
|
|
44
|
+
}, representationEstimator: IRepresentationEstimator, currentRepresentation: IReadOnlySharedReference<Representation | null>, playbackObserver: IReadOnlyPlaybackObserver<IRepresentationEstimatorPlaybackObservation>, onFatalError: (err: IPlayerError) => void, cancellationSignal: CancellationSignal): {
|
|
45
|
+
estimateRef: IReadOnlySharedReference<IABREstimate>;
|
|
46
|
+
abrCallbacks: IRepresentationEstimatorCallbacks;
|
|
47
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
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
|
+
import { MediaError } from "../../../../errors";
|
|
17
|
+
import createSharedReference from "../../../../utils/reference";
|
|
18
|
+
/**
|
|
19
|
+
* Produce estimates to know which Representation should be played.
|
|
20
|
+
* @param {Object} content - The Manifest, Period and Adaptation wanted.
|
|
21
|
+
* @param {Object} representationEstimator - `IRepresentationEstimator` which
|
|
22
|
+
* will produce Representation estimates.
|
|
23
|
+
* @param {Object} currentRepresentation - Reference emitting the
|
|
24
|
+
* currently-loaded Representation.
|
|
25
|
+
* @param {Object} playbackObserver - Allows to observe the current playback
|
|
26
|
+
* conditions.
|
|
27
|
+
* @param {Function} onFatalError - Callback called when a fatal error was
|
|
28
|
+
* thrown. Once this callback is called, no estimate will be produced.
|
|
29
|
+
* @param {Object} cancellationSignal - `CancellationSignal` allowing to abort
|
|
30
|
+
* the production of estimates (and clean-up all linked resources).
|
|
31
|
+
* @returns {Object} - Returns an object with the following properties:
|
|
32
|
+
* - `estimateRef`: Reference emitting the last estimate
|
|
33
|
+
* - `abrCallbacks`: Callbacks allowing to report back network and playback
|
|
34
|
+
* activities to improve the estimates given.
|
|
35
|
+
*/
|
|
36
|
+
export default function getRepresentationEstimate(content, representationEstimator, currentRepresentation, playbackObserver, onFatalError, cancellationSignal) {
|
|
37
|
+
var manifest = content.manifest, adaptation = content.adaptation;
|
|
38
|
+
var representations = createSharedReference([], cancellationSignal);
|
|
39
|
+
updateRepresentationsReference();
|
|
40
|
+
manifest.addEventListener("decipherabilityUpdate", updateRepresentationsReference);
|
|
41
|
+
var unregisterCleanUp = cancellationSignal.register(cleanUp);
|
|
42
|
+
var _a = representationEstimator(content, currentRepresentation, representations, playbackObserver, cancellationSignal), estimateRef = _a.estimates, abrCallbacks = _a.callbacks;
|
|
43
|
+
return { abrCallbacks: abrCallbacks, estimateRef: estimateRef };
|
|
44
|
+
function updateRepresentationsReference() {
|
|
45
|
+
/** Representations for which a `RepresentationStream` can be created. */
|
|
46
|
+
var newRepr = adaptation.getPlayableRepresentations();
|
|
47
|
+
if (newRepr.length === 0) {
|
|
48
|
+
var noRepErr = new MediaError("NO_PLAYABLE_REPRESENTATION", "No Representation in the chosen " +
|
|
49
|
+
adaptation.type + " Adaptation can be played", { adaptation: adaptation });
|
|
50
|
+
cleanUp();
|
|
51
|
+
onFatalError(noRepErr);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
var prevRepr = representations.getValue();
|
|
55
|
+
if (prevRepr.length === newRepr.length) {
|
|
56
|
+
if (prevRepr.every(function (r, idx) { return r.id === newRepr[idx].id; })) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
representations.setValue(newRepr);
|
|
61
|
+
}
|
|
62
|
+
/** Clean-up all resources taken here. */
|
|
63
|
+
function cleanUp() {
|
|
64
|
+
manifest.removeEventListener("decipherabilityUpdate", updateRepresentationsReference);
|
|
65
|
+
// check to protect against the case where it is not yet defined.
|
|
66
|
+
if (typeof unregisterCleanUp !== "undefined") {
|
|
67
|
+
unregisterCleanUp();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -201,7 +201,13 @@ export default function StreamOrchestrator(content, playbackObserver, representa
|
|
|
201
201
|
launchConsecutiveStreamsForPeriod(nextPeriod);
|
|
202
202
|
}, { clearSignal: orchestratorCancelSignal, includeLastObservation: true });
|
|
203
203
|
manifest.addEventListener("decipherabilityUpdate", function (evt) {
|
|
204
|
+
if (orchestratorCancelSignal.isCancelled()) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
204
207
|
onDecipherabilityUpdates(evt).catch(function (err) {
|
|
208
|
+
if (orchestratorCancelSignal.isCancelled()) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
205
211
|
currentCanceller.cancel();
|
|
206
212
|
callbacks.error(err);
|
|
207
213
|
});
|
|
@@ -408,12 +414,10 @@ export default function StreamOrchestrator(content, playbackObserver, representa
|
|
|
408
414
|
var periodStreamArgs = { bufferType: bufferType, content: { manifest: manifest, period: basePeriod }, garbageCollectors: garbageCollectors, maxVideoBufferSize: maxVideoBufferSize, segmentFetcherCreator: segmentFetcherCreator, segmentBuffersStore: segmentBuffersStore, options: options, playbackObserver: playbackObserver, representationEstimator: representationEstimator, wantedBufferAhead: wantedBufferAhead };
|
|
409
415
|
var periodStreamCallbacks = __assign(__assign({}, consecutivePeriodStreamCb), { streamStatusUpdate: function (value) {
|
|
410
416
|
if (value.hasFinishedLoading) {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
createNextPeriodStream(nextPeriod);
|
|
416
|
-
}
|
|
417
|
+
var nextPeriod = manifest.getPeriodAfter(basePeriod);
|
|
418
|
+
if (nextPeriod !== null) {
|
|
419
|
+
// current Stream is full, create the next one if not
|
|
420
|
+
checkOrCreateNextPeriodStream(nextPeriod);
|
|
417
421
|
}
|
|
418
422
|
}
|
|
419
423
|
else if (nextStreamInfo !== null) {
|
|
@@ -439,9 +443,12 @@ export default function StreamOrchestrator(content, playbackObserver, representa
|
|
|
439
443
|
* Create `PeriodStream` for the next Period, specified under `nextPeriod`.
|
|
440
444
|
* @param {Object} nextPeriod
|
|
441
445
|
*/
|
|
442
|
-
function
|
|
446
|
+
function checkOrCreateNextPeriodStream(nextPeriod) {
|
|
443
447
|
if (nextStreamInfo !== null) {
|
|
444
|
-
|
|
448
|
+
if (nextStreamInfo.period.id === nextPeriod.id) {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
log.warn("Stream: Creating next `PeriodStream` while one was already created.", bufferType, nextPeriod.id, nextStreamInfo.period.id);
|
|
445
452
|
consecutivePeriodStreamCb.periodStreamCleared({ type: bufferType, manifest: manifest, period: nextStreamInfo.period });
|
|
446
453
|
nextStreamInfo.canceller.cancel();
|
|
447
454
|
}
|
|
@@ -325,7 +325,7 @@ function getFirstDeclaredMimeType(adaptation) {
|
|
|
325
325
|
var representations = adaptation.getPlayableRepresentations();
|
|
326
326
|
if (representations.length === 0) {
|
|
327
327
|
var noRepErr = new MediaError("NO_PLAYABLE_REPRESENTATION", "No Representation in the chosen " +
|
|
328
|
-
adaptation.type + " Adaptation can be played");
|
|
328
|
+
adaptation.type + " Adaptation can be played", { adaptation: adaptation });
|
|
329
329
|
throw noRepErr;
|
|
330
330
|
}
|
|
331
331
|
return representations[0].getMimeTypeString();
|