rx-player 3.32.0 → 3.32.2-canal.2023110700
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 +10 -1
- package/MAINTAINERS.md +1 -0
- package/VERSION +1 -1
- package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +7 -7
- package/dist/_esm5.processed/core/adaptive/utils/filter_by_width.js +1 -3
- package/dist/_esm5.processed/core/api/public_api.js +2 -2
- package/dist/_esm5.processed/core/api/tracks_management/track_choice_manager.js +2 -2
- package/dist/_esm5.processed/core/init/directfile_content_initializer.js +1 -1
- package/dist/_esm5.processed/core/init/media_source_content_initializer.js +14 -3
- 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/inventory/segment_inventory.js +10 -11
- package/dist/_esm5.processed/experimental/features/index.d.ts +1 -0
- package/dist/_esm5.processed/experimental/features/index.js +1 -0
- package/dist/_esm5.processed/parsers/manifest/smooth/create_parser.js +1 -2
- 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/transports/dash/image_pipelines.js +2 -2
- package/dist/_esm5.processed/transports/dash/segment_parser.js +2 -3
- package/dist/_esm5.processed/transports/dash/text_parser.js +2 -2
- package/dist/_esm5.processed/transports/local/segment_parser.js +2 -3
- package/dist/_esm5.processed/transports/local/text_parser.js +4 -3
- package/dist/rx-player.js +134 -90
- package/dist/rx-player.min.js +1 -1
- package/package.json +1 -1
- package/sonar-project.properties +1 -1
- package/src/compat/README.md +18 -12
- package/src/core/adaptive/adaptive_representation_selector.ts +8 -18
- package/src/core/adaptive/utils/filter_by_width.ts +1 -3
- package/src/core/api/public_api.ts +2 -2
- package/src/core/api/tracks_management/track_choice_manager.ts +1 -3
- package/src/core/init/directfile_content_initializer.ts +1 -0
- package/src/core/init/media_source_content_initializer.ts +14 -1
- package/src/core/init/utils/rebuffering_controller.ts +114 -3
- package/src/core/segment_buffers/inventory/segment_inventory.ts +7 -14
- package/src/experimental/features/__tests__/index.test.ts +19 -0
- package/src/experimental/features/index.ts +1 -0
- package/src/features/list/__tests__/index.test.ts +55 -0
- package/src/parsers/manifest/smooth/create_parser.ts +1 -2
- package/src/parsers/texttracks/ttml/html/apply_extent.ts +8 -1
- package/src/parsers/texttracks/ttml/html/apply_origin.ts +9 -1
- package/src/transports/dash/image_pipelines.ts +1 -2
- package/src/transports/dash/segment_parser.ts +1 -2
- package/src/transports/dash/text_parser.ts +1 -2
- package/src/transports/local/segment_parser.ts +1 -2
- package/src/transports/local/text_parser.ts +2 -3
- package/dist/_esm5.processed/utils/take_first_set.d.ts +0 -25
- package/dist/_esm5.processed/utils/take_first_set.js +0 -32
- package/src/utils/__tests__/take_first_set.test.ts +0 -38
- package/src/utils/take_first_set.ts +0 -53
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## v3.32.
|
|
3
|
+
## v3.32.2-canal.2023110700 (2023-11-07)
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
|
|
7
|
+
- Fix export of the `LOCAL_MANIFEST` experimental feature [#1305]
|
|
8
|
+
- TTML: put saner values for extent and origins when weird ones are found
|
|
9
|
+
- DRM: Reload when playback is unexpectedly frozen with encrypted but only decipherable data in the buffer [#1236]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
## v3.32.1 (2023-10-19)
|
|
4
13
|
|
|
5
14
|
### Features
|
|
6
15
|
|
package/MAINTAINERS.md
CHANGED
|
@@ -16,6 +16,7 @@ RxPlayer-related question or to propose new features.
|
|
|
16
16
|
Here is the list of current maintainers:
|
|
17
17
|
|
|
18
18
|
- Paul Berberian <paul.berberian@canal-plus.com>
|
|
19
|
+
- Florent Bouisset <florent.bouisset@canal-plus.com>
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
## Previous maintainers ########################################################
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.32.
|
|
1
|
+
3.32.2-canal.2023110700
|
|
@@ -18,7 +18,6 @@ import log from "../../log";
|
|
|
18
18
|
import noop from "../../utils/noop";
|
|
19
19
|
import { getLeftSizeOfRange } from "../../utils/ranges";
|
|
20
20
|
import SharedReference from "../../utils/reference";
|
|
21
|
-
import takeFirstSet from "../../utils/take_first_set";
|
|
22
21
|
import TaskCanceller from "../../utils/task_canceller";
|
|
23
22
|
import BufferBasedChooser from "./buffer_based_chooser";
|
|
24
23
|
import GuessBasedChooser from "./guess_based_chooser";
|
|
@@ -69,15 +68,16 @@ export default function createAdaptiveRepresentationSelector(options) {
|
|
|
69
68
|
* @returns {Array.<Object>}
|
|
70
69
|
*/
|
|
71
70
|
return function getEstimates(context, currentRepresentation, representations, playbackObserver, stopAllEstimates) {
|
|
71
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
72
72
|
var type = context.adaptation.type;
|
|
73
73
|
var bandwidthEstimator = _getBandwidthEstimator(type);
|
|
74
|
-
var manualBitrate =
|
|
75
|
-
var minAutoBitrate =
|
|
76
|
-
var maxAutoBitrate =
|
|
77
|
-
var initialBitrate =
|
|
74
|
+
var manualBitrate = (_a = manualBitrates[type]) !== null && _a !== void 0 ? _a : manualBitrateDefaultRef;
|
|
75
|
+
var minAutoBitrate = (_b = minAutoBitrates[type]) !== null && _b !== void 0 ? _b : minAutoBitrateDefaultRef;
|
|
76
|
+
var maxAutoBitrate = (_c = maxAutoBitrates[type]) !== null && _c !== void 0 ? _c : maxAutoBitrateDefaultRef;
|
|
77
|
+
var initialBitrate = (_d = initialBitrates[type]) !== null && _d !== void 0 ? _d : 0;
|
|
78
78
|
var filters = {
|
|
79
|
-
limitWidth:
|
|
80
|
-
throttleBitrate:
|
|
79
|
+
limitWidth: (_e = throttlers.limitWidth[type]) !== null && _e !== void 0 ? _e : limitWidthDefaultRef,
|
|
80
|
+
throttleBitrate: (_g = (_f = throttlers.throttleBitrate[type]) !== null && _f !== void 0 ? _f : throttlers.throttle[type]) !== null && _g !== void 0 ? _g : throttleBitrateDefaultRef,
|
|
81
81
|
};
|
|
82
82
|
return getEstimateReference({ bandwidthEstimator: bandwidthEstimator, context: context, currentRepresentation: currentRepresentation, filters: filters, initialBitrate: initialBitrate, manualBitrate: manualBitrate, minAutoBitrate: minAutoBitrate, maxAutoBitrate: maxAutoBitrate, playbackObserver: playbackObserver, representations: representations, lowLatencyMode: lowLatencyMode }, stopAllEstimates);
|
|
83
83
|
};
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
import arrayFind from "../../../utils/array_find";
|
|
17
|
-
import takeFirstSet from "../../../utils/take_first_set";
|
|
18
17
|
/**
|
|
19
18
|
* Filter representations based on their width:
|
|
20
19
|
* - the highest width considered will be the one linked to the first
|
|
@@ -26,8 +25,7 @@ import takeFirstSet from "../../../utils/take_first_set";
|
|
|
26
25
|
export default function filterByWidth(representations, width) {
|
|
27
26
|
var sortedRepsByWidth = representations
|
|
28
27
|
.slice() // clone
|
|
29
|
-
.sort(function (a, b) { return
|
|
30
|
-
takeFirstSet(b.width, 0); });
|
|
28
|
+
.sort(function (a, b) { var _a, _b; return ((_a = a.width) !== null && _a !== void 0 ? _a : 0) - ((_b = b.width) !== null && _b !== void 0 ? _b : 0); });
|
|
31
29
|
var repWithMaxWidth = arrayFind(sortedRepsByWidth, function (representation) {
|
|
32
30
|
return typeof representation.width === "number" &&
|
|
33
31
|
representation.width >= width;
|
|
@@ -88,7 +88,7 @@ var Player = /** @class */ (function (_super) {
|
|
|
88
88
|
// Workaround to support Firefox autoplay on FF 42.
|
|
89
89
|
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1194624
|
|
90
90
|
videoElement.preload = "auto";
|
|
91
|
-
_this.version = /* PLAYER_VERSION */ "3.32.
|
|
91
|
+
_this.version = /* PLAYER_VERSION */ "3.32.2-canal.2023110700";
|
|
92
92
|
_this.log = log;
|
|
93
93
|
_this.state = "STOPPED";
|
|
94
94
|
_this.videoElement = videoElement;
|
|
@@ -2439,5 +2439,5 @@ var Player = /** @class */ (function (_super) {
|
|
|
2439
2439
|
};
|
|
2440
2440
|
return Player;
|
|
2441
2441
|
}(EventEmitter));
|
|
2442
|
-
Player.version = /* PLAYER_VERSION */ "3.32.
|
|
2442
|
+
Player.version = /* PLAYER_VERSION */ "3.32.2-canal.2023110700";
|
|
2443
2443
|
export default Player;
|
|
@@ -24,7 +24,6 @@ import isNullOrUndefined from "../../../utils/is_null_or_undefined";
|
|
|
24
24
|
import normalizeLanguage from "../../../utils/languages";
|
|
25
25
|
import objectAssign from "../../../utils/object_assign";
|
|
26
26
|
import SortedList from "../../../utils/sorted_list";
|
|
27
|
-
import takeFirstSet from "../../../utils/take_first_set";
|
|
28
27
|
/**
|
|
29
28
|
* Transform an array of IAudioTrackPreference into an array of
|
|
30
29
|
* INormalizedPreferredAudioTrack to be exploited by the TrackChoiceManager.
|
|
@@ -835,7 +834,8 @@ function createTextPreferenceMatcher(preferredTextTrack) {
|
|
|
835
834
|
* @returns {boolean}
|
|
836
835
|
*/
|
|
837
836
|
return function matchTextPreference(textAdaptation) {
|
|
838
|
-
|
|
837
|
+
var _a;
|
|
838
|
+
return ((_a = textAdaptation.normalizedLanguage) !== null && _a !== void 0 ? _a : "") === preferredTextTrack.normalized &&
|
|
839
839
|
(preferredTextTrack.closedCaption ? textAdaptation.isClosedCaption === true :
|
|
840
840
|
textAdaptation.isClosedCaption !== true) &&
|
|
841
841
|
(preferredTextTrack.forced === true ? textAdaptation.isForcedSubtitles === true :
|
|
@@ -98,7 +98,7 @@ var DirectFileContentInitializer = /** @class */ (function (_super) {
|
|
|
98
98
|
* Class trying to avoid various stalling situations, emitting "stalled"
|
|
99
99
|
* events when it cannot, as well as "unstalled" events when it get out of one.
|
|
100
100
|
*/
|
|
101
|
-
var rebufferingController = new RebufferingController(playbackObserver, null, speed);
|
|
101
|
+
var rebufferingController = new RebufferingController(playbackObserver, null, null, speed);
|
|
102
102
|
rebufferingController.addEventListener("stalled", function (evt) {
|
|
103
103
|
return _this.trigger("stalled", evt);
|
|
104
104
|
});
|
|
@@ -352,7 +352,18 @@ var MediaSourceContentInitializer = /** @class */ (function (_super) {
|
|
|
352
352
|
}
|
|
353
353
|
}, { clearSignal: cancelSignal, emitCurrentValue: true });
|
|
354
354
|
var streamObserver = createStreamPlaybackObserver(playbackObserver, { autoPlay: autoPlay, manifest: manifest, initialPlayPerformed: initialPlayPerformed, initialSeekPerformed: initialSeekPerformed, speed: speed, startTime: initialTime }, cancelSignal);
|
|
355
|
-
var rebufferingController = this._createRebufferingController(playbackObserver, manifest, speed, cancelSignal);
|
|
355
|
+
var rebufferingController = this._createRebufferingController(playbackObserver, manifest, segmentBuffersStore, speed, cancelSignal);
|
|
356
|
+
rebufferingController.addEventListener("needsReload", function () {
|
|
357
|
+
// NOTE couldn't both be always calculated at event destination?
|
|
358
|
+
// Maybe there are exceptions?
|
|
359
|
+
var position = initialSeekPerformed.getValue() ?
|
|
360
|
+
playbackObserver.getCurrentTime() :
|
|
361
|
+
initialTime;
|
|
362
|
+
var autoplay = initialPlayPerformed.getValue() ?
|
|
363
|
+
!playbackObserver.getIsPaused() :
|
|
364
|
+
autoPlay;
|
|
365
|
+
onReloadOrder({ position: position, autoPlay: autoplay });
|
|
366
|
+
}, cancelSignal);
|
|
356
367
|
var contentTimeBoundariesObserver = this
|
|
357
368
|
._createContentTimeBoundariesObserver(manifest, mediaSource, streamObserver, segmentBuffersStore, cancelSignal);
|
|
358
369
|
/**
|
|
@@ -609,9 +620,9 @@ var MediaSourceContentInitializer = /** @class */ (function (_super) {
|
|
|
609
620
|
* @param {Object} cancelSignal
|
|
610
621
|
* @returns {Object}
|
|
611
622
|
*/
|
|
612
|
-
MediaSourceContentInitializer.prototype._createRebufferingController = function (playbackObserver, manifest, speed, cancelSignal) {
|
|
623
|
+
MediaSourceContentInitializer.prototype._createRebufferingController = function (playbackObserver, manifest, segmentBuffersStore, speed, cancelSignal) {
|
|
613
624
|
var _this = this;
|
|
614
|
-
var rebufferingController = new RebufferingController(playbackObserver, manifest, speed);
|
|
625
|
+
var rebufferingController = new RebufferingController(playbackObserver, manifest, segmentBuffersStore, speed);
|
|
615
626
|
// Bubble-up events
|
|
616
627
|
rebufferingController.addEventListener("stalled", function (evt) { return _this.trigger("stalled", evt); });
|
|
617
628
|
rebufferingController.addEventListener("unstalled", function () { return _this.trigger("unstalled", null); });
|
|
@@ -18,7 +18,7 @@ import { IPlayerError } from "../../../public_types";
|
|
|
18
18
|
import EventEmitter from "../../../utils/event_emitter";
|
|
19
19
|
import { IReadOnlySharedReference } from "../../../utils/reference";
|
|
20
20
|
import { PlaybackObserver } from "../../api";
|
|
21
|
-
import { IBufferType } from "../../segment_buffers";
|
|
21
|
+
import SegmentBuffersStore, { IBufferType } from "../../segment_buffers";
|
|
22
22
|
import { IStallingSituation } from "../types";
|
|
23
23
|
/**
|
|
24
24
|
* Monitor playback, trying to avoid stalling situation.
|
|
@@ -32,6 +32,7 @@ export default class RebufferingController extends EventEmitter<IRebufferingCont
|
|
|
32
32
|
/** Emit the current playback conditions */
|
|
33
33
|
private _playbackObserver;
|
|
34
34
|
private _manifest;
|
|
35
|
+
private _segmentBuffersStore;
|
|
35
36
|
private _speed;
|
|
36
37
|
private _isStarted;
|
|
37
38
|
/**
|
|
@@ -40,12 +41,23 @@ export default class RebufferingController extends EventEmitter<IRebufferingCont
|
|
|
40
41
|
*/
|
|
41
42
|
private _discontinuitiesStore;
|
|
42
43
|
private _canceller;
|
|
44
|
+
/**
|
|
45
|
+
* If set to something else than `null`, this is the DOMHighResTimestamp as
|
|
46
|
+
* outputed by `performance.now()` when playback begin to seem to not start
|
|
47
|
+
* despite having decipherable data in the buffer(s).
|
|
48
|
+
*
|
|
49
|
+
* If enough time in that condition is spent, special considerations are
|
|
50
|
+
* taken at which point `_currentFreezeTimestamp` is reset to `null`.
|
|
51
|
+
*
|
|
52
|
+
* It is also reset to `null` when and if there is no such issue anymore.
|
|
53
|
+
*/
|
|
54
|
+
private _currentFreezeTimestamp;
|
|
43
55
|
/**
|
|
44
56
|
* @param {object} playbackObserver - emit the current playback conditions.
|
|
45
57
|
* @param {Object} manifest - The Manifest of the currently-played content.
|
|
46
58
|
* @param {Object} speed - The last speed set by the user
|
|
47
59
|
*/
|
|
48
|
-
constructor(playbackObserver: PlaybackObserver, manifest: Manifest | null, speed: IReadOnlySharedReference<number>);
|
|
60
|
+
constructor(playbackObserver: PlaybackObserver, manifest: Manifest | null, segmentBuffersStore: SegmentBuffersStore | null, speed: IReadOnlySharedReference<number>);
|
|
49
61
|
start(): void;
|
|
50
62
|
/**
|
|
51
63
|
* Update information on an upcoming discontinuity for a given buffer type and
|
|
@@ -68,10 +80,32 @@ export default class RebufferingController extends EventEmitter<IRebufferingCont
|
|
|
68
80
|
* forever.
|
|
69
81
|
*/
|
|
70
82
|
destroy(): void;
|
|
83
|
+
/**
|
|
84
|
+
* Support of contents with DRM on all the platforms out there is a pain in
|
|
85
|
+
* the *ss considering all the DRM-related bugs there are.
|
|
86
|
+
*
|
|
87
|
+
* We found out a frequent issue which is to be unable to play despite having
|
|
88
|
+
* all the decryption keys to play what is currently buffered.
|
|
89
|
+
* When this happens, re-creating the buffers from scratch, with a reload, is
|
|
90
|
+
* usually sufficient to unlock the situation.
|
|
91
|
+
*
|
|
92
|
+
* Although we prefer providing more targeted fixes or telling to platform
|
|
93
|
+
* developpers to fix their implementation, it's not always possible.
|
|
94
|
+
* We thus resorted to developping an heuristic which detects such situation
|
|
95
|
+
* and reload in that case.
|
|
96
|
+
*
|
|
97
|
+
* @param {Object} observation - The last playback observation produced, it
|
|
98
|
+
* has to be recent (just triggered for example).
|
|
99
|
+
* @returns {boolean} - Returns `true` if it seems to be such kind of
|
|
100
|
+
* decipherability freeze, in which case this method already performed the
|
|
101
|
+
* right handling steps.
|
|
102
|
+
*/
|
|
103
|
+
private _checkDecipherabilityFreeze;
|
|
71
104
|
}
|
|
72
105
|
export interface IRebufferingControllerEvent {
|
|
73
106
|
stalled: IStallingSituation;
|
|
74
107
|
unstalled: null;
|
|
108
|
+
needsReload: null;
|
|
75
109
|
warning: IPlayerError;
|
|
76
110
|
}
|
|
77
111
|
/**
|
|
@@ -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
|
+
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;
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
import config from "../../../config";
|
|
17
17
|
import log from "../../../log";
|
|
18
18
|
import { areSameContent, } from "../../../manifest";
|
|
19
|
-
import takeFirstSet from "../../../utils/take_first_set";
|
|
20
19
|
import BufferedHistory from "./buffered_history";
|
|
21
20
|
/**
|
|
22
21
|
* Keep track of every chunk downloaded and currently in the linked media
|
|
@@ -52,6 +51,7 @@ var SegmentInventory = /** @class */ (function () {
|
|
|
52
51
|
* @param {TimeRanges} buffered
|
|
53
52
|
*/
|
|
54
53
|
SegmentInventory.prototype.synchronizeBuffered = function (buffered) {
|
|
54
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
55
55
|
var inventory = this._inventory;
|
|
56
56
|
var inventoryIndex = 0; // Current index considered.
|
|
57
57
|
var thisSegment = inventory[0]; // Current segmentInfos considered
|
|
@@ -76,7 +76,7 @@ var SegmentInventory = /** @class */ (function () {
|
|
|
76
76
|
// skip until first segment with at least `MINIMUM_SEGMENT_SIZE` past the
|
|
77
77
|
// start of that range.
|
|
78
78
|
while (thisSegment !== undefined &&
|
|
79
|
-
(
|
|
79
|
+
(((_a = thisSegment.bufferedEnd) !== null && _a !== void 0 ? _a : thisSegment.end)
|
|
80
80
|
- rangeStart) < MINIMUM_SEGMENT_SIZE) {
|
|
81
81
|
thisSegment = inventory[++inventoryIndex];
|
|
82
82
|
}
|
|
@@ -90,7 +90,7 @@ var SegmentInventory = /** @class */ (function () {
|
|
|
90
90
|
var lastDeletedSegment = // last garbage-collected segment
|
|
91
91
|
inventory[indexBefore + numberOfSegmentToDelete - 1];
|
|
92
92
|
lastDeletedSegmentInfos = {
|
|
93
|
-
end:
|
|
93
|
+
end: (_b = lastDeletedSegment.bufferedEnd) !== null && _b !== void 0 ? _b : lastDeletedSegment.end,
|
|
94
94
|
precizeEnd: lastDeletedSegment.precizeEnd,
|
|
95
95
|
};
|
|
96
96
|
log.debug("SI: ".concat(numberOfSegmentToDelete, " segments GCed."), bufferType);
|
|
@@ -108,8 +108,7 @@ var SegmentInventory = /** @class */ (function () {
|
|
|
108
108
|
}
|
|
109
109
|
// If the current segment is actually completely outside that range (it
|
|
110
110
|
// is contained in one of the next one), skip that part.
|
|
111
|
-
if (rangeEnd -
|
|
112
|
-
takeFirstSet(thisSegment.bufferedStart, thisSegment.start)
|
|
111
|
+
if (rangeEnd - ((_c = thisSegment.bufferedStart) !== null && _c !== void 0 ? _c : thisSegment.start)
|
|
113
112
|
>= MINIMUM_SEGMENT_SIZE) {
|
|
114
113
|
guessBufferedStartFromRangeStart(thisSegment, rangeStart, lastDeletedSegmentInfos, bufferType);
|
|
115
114
|
if (inventoryIndex === inventory.length - 1) {
|
|
@@ -120,8 +119,8 @@ var SegmentInventory = /** @class */ (function () {
|
|
|
120
119
|
}
|
|
121
120
|
thisSegment = inventory[++inventoryIndex];
|
|
122
121
|
// Make contiguous until first segment outside that range
|
|
123
|
-
var thisSegmentStart =
|
|
124
|
-
var thisSegmentEnd =
|
|
122
|
+
var thisSegmentStart = (_d = thisSegment.bufferedStart) !== null && _d !== void 0 ? _d : thisSegment.start;
|
|
123
|
+
var thisSegmentEnd = (_e = thisSegment.bufferedEnd) !== null && _e !== void 0 ? _e : thisSegment.end;
|
|
125
124
|
var nextRangeStart = i < rangesLength - 1 ? buffered.start(i + 1) :
|
|
126
125
|
undefined;
|
|
127
126
|
while (thisSegment !== undefined &&
|
|
@@ -139,8 +138,8 @@ var SegmentInventory = /** @class */ (function () {
|
|
|
139
138
|
thisSegment.bufferedStart = prevSegment.bufferedEnd;
|
|
140
139
|
thisSegment = inventory[++inventoryIndex];
|
|
141
140
|
if (thisSegment !== undefined) {
|
|
142
|
-
thisSegmentStart =
|
|
143
|
-
thisSegmentEnd =
|
|
141
|
+
thisSegmentStart = (_f = thisSegment.bufferedStart) !== null && _f !== void 0 ? _f : thisSegment.start;
|
|
142
|
+
thisSegmentEnd = (_g = thisSegment.bufferedEnd) !== null && _g !== void 0 ? _g : thisSegment.end;
|
|
144
143
|
}
|
|
145
144
|
}
|
|
146
145
|
}
|
|
@@ -155,8 +154,8 @@ var SegmentInventory = /** @class */ (function () {
|
|
|
155
154
|
if (thisSegment != null) {
|
|
156
155
|
log.debug("SI: last segments have been GCed", bufferType, inventoryIndex, inventory.length);
|
|
157
156
|
var removed = inventory.splice(inventoryIndex, inventory.length - inventoryIndex);
|
|
158
|
-
for (var
|
|
159
|
-
var seg = removed_2[
|
|
157
|
+
for (var _h = 0, removed_2 = removed; _h < removed_2.length; _h++) {
|
|
158
|
+
var seg = removed_2[_h];
|
|
160
159
|
if (seg.bufferedStart === undefined && seg.bufferedEnd === undefined) {
|
|
161
160
|
this._bufferedHistory.addBufferedSegment(seg.infos, null);
|
|
162
161
|
}
|
|
@@ -22,7 +22,6 @@ import isNonEmptyString from "../../../utils/is_non_empty_string";
|
|
|
22
22
|
import objectAssign from "../../../utils/object_assign";
|
|
23
23
|
import { getFilenameIndexInUrl } from "../../../utils/resolve_url";
|
|
24
24
|
import { hexToBytes } from "../../../utils/string_parsing";
|
|
25
|
-
import takeFirstSet from "../../../utils/take_first_set";
|
|
26
25
|
import { createBox } from "../../containers/isobmff";
|
|
27
26
|
import checkManifestIDs from "../utils/check_manifest_ids";
|
|
28
27
|
import { getAudioCodecs, getVideoCodecs, } from "./get_codecs";
|
|
@@ -168,7 +167,7 @@ function createSmoothStreamingParser(parserOptions) {
|
|
|
168
167
|
parseInt(bitrateAttr, 10);
|
|
169
168
|
return { bitrate: bitrate, customAttributes: customAttributes, mimeType: fourCC !== undefined ? MIME_TYPES[fourCC] :
|
|
170
169
|
fourCC,
|
|
171
|
-
codecPrivateData:
|
|
170
|
+
codecPrivateData: codecPrivateData !== null && codecPrivateData !== void 0 ? codecPrivateData : "" };
|
|
172
171
|
}
|
|
173
172
|
default:
|
|
174
173
|
log.error("Smooth Parser: Unrecognized StreamIndex type: " + streamType);
|
|
@@ -48,7 +48,14 @@ export default function applyExtent(element, extent) {
|
|
|
48
48
|
if (secondExtent[2] === "px" ||
|
|
49
49
|
secondExtent[2] === "%" ||
|
|
50
50
|
secondExtent[2] === "em") {
|
|
51
|
-
|
|
51
|
+
var toNum = Number(secondExtent[1]);
|
|
52
|
+
if (secondExtent[2] === "%" && !isNaN(toNum) &&
|
|
53
|
+
(toNum < 0 || toNum > 100)) {
|
|
54
|
+
element.style.width = "80%";
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
element.style.height = secondExtent[1] + secondExtent[2];
|
|
58
|
+
}
|
|
52
59
|
}
|
|
53
60
|
else if (secondExtent[2] === "c") {
|
|
54
61
|
addClassName(element, "proportional-style");
|
|
@@ -47,7 +47,15 @@ export default function applyOrigin(element, origin) {
|
|
|
47
47
|
if (secondOrigin[2] === "px" ||
|
|
48
48
|
secondOrigin[2] === "%" ||
|
|
49
49
|
secondOrigin[2] === "em") {
|
|
50
|
-
|
|
50
|
+
var toNum = Number(secondOrigin[1]);
|
|
51
|
+
if (secondOrigin[2] === "%" && !isNaN(toNum) &&
|
|
52
|
+
(toNum < 0 || toNum > 100)) {
|
|
53
|
+
element.style.bottom = "5%";
|
|
54
|
+
element.style.left = "10%";
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
element.style.top = secondOrigin[1] + secondOrigin[2];
|
|
58
|
+
}
|
|
51
59
|
}
|
|
52
60
|
else if (secondOrigin[2] === "c") {
|
|
53
61
|
addClassName(element, "proportional-style");
|
|
@@ -51,7 +51,6 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
51
51
|
};
|
|
52
52
|
import features from "../../features";
|
|
53
53
|
import request from "../../utils/request";
|
|
54
|
-
import takeFirstSet from "../../utils/take_first_set";
|
|
55
54
|
import constructSegmentUrl from "./construct_segment_url";
|
|
56
55
|
/**
|
|
57
56
|
* Loads an image segment.
|
|
@@ -92,6 +91,7 @@ export function imageLoader(wantedCdn, content, options, cancelSignal, callbacks
|
|
|
92
91
|
* @returns {Object}
|
|
93
92
|
*/
|
|
94
93
|
export function imageParser(loadedSegment, content) {
|
|
94
|
+
var _a;
|
|
95
95
|
var segment = content.segment, period = content.period;
|
|
96
96
|
var data = loadedSegment.data, isChunked = loadedSegment.isChunked;
|
|
97
97
|
if (content.segment.isInit) { // image init segment has no use
|
|
@@ -104,7 +104,7 @@ export function imageParser(loadedSegment, content) {
|
|
|
104
104
|
if (isChunked) {
|
|
105
105
|
throw new Error("Image data should not be downloaded in chunks");
|
|
106
106
|
}
|
|
107
|
-
var chunkOffset =
|
|
107
|
+
var chunkOffset = (_a = segment.timestampOffset) !== null && _a !== void 0 ? _a : 0;
|
|
108
108
|
// TODO image Parsing should be more on the buffer side, no?
|
|
109
109
|
if (data === null || features.imageParser === null) {
|
|
110
110
|
return { segmentType: "media",
|
|
@@ -18,7 +18,6 @@ import { getKeyIdFromInitSegment, parseEmsgBoxes, } from "../../parsers/containe
|
|
|
18
18
|
import { getSegmentsFromCues, getTimeCodeScale, } from "../../parsers/containers/matroska";
|
|
19
19
|
import { BaseRepresentationIndex } from "../../parsers/manifest/dash";
|
|
20
20
|
import isNullOrUndefined from "../../utils/is_null_or_undefined";
|
|
21
|
-
import takeFirstSet from "../../utils/take_first_set";
|
|
22
21
|
import getISOBMFFTimingInfos from "../utils/get_isobmff_timing_infos";
|
|
23
22
|
import inferSegmentContainer from "../utils/infer_segment_container";
|
|
24
23
|
import getEventsOutOfEMSGs from "./get_events_out_of_emsgs";
|
|
@@ -29,7 +28,7 @@ import getEventsOutOfEMSGs from "./get_events_out_of_emsgs";
|
|
|
29
28
|
export default function generateAudioVideoSegmentParser(_a) {
|
|
30
29
|
var __priv_patchLastSegmentInSidx = _a.__priv_patchLastSegmentInSidx;
|
|
31
30
|
return function audioVideoSegmentParser(loadedSegment, content, initTimescale) {
|
|
32
|
-
var _a;
|
|
31
|
+
var _a, _b;
|
|
33
32
|
var period = content.period, adaptation = content.adaptation, representation = content.representation, segment = content.segment, manifest = content.manifest;
|
|
34
33
|
var data = loadedSegment.data, isChunked = loadedSegment.isChunked;
|
|
35
34
|
var appendWindow = [period.start, period.end];
|
|
@@ -67,7 +66,7 @@ export default function generateAudioVideoSegmentParser(_a) {
|
|
|
67
66
|
if (!segment.isInit) {
|
|
68
67
|
var chunkInfos = seemsToBeMP4 ? getISOBMFFTimingInfos(chunkData, isChunked, segment, initTimescale) :
|
|
69
68
|
null; // TODO extract time info from webm
|
|
70
|
-
var chunkOffset =
|
|
69
|
+
var chunkOffset = (_b = segment.timestampOffset) !== null && _b !== void 0 ? _b : 0;
|
|
71
70
|
if (seemsToBeMP4) {
|
|
72
71
|
var parsedEMSGs = parseEmsgBoxes(chunkData);
|
|
73
72
|
if (parsedEMSGs !== undefined) {
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
import { getMDHDTimescale, getSegmentsFromSidx, } from "../../parsers/containers/isobmff";
|
|
17
17
|
import { BaseRepresentationIndex } from "../../parsers/manifest/dash";
|
|
18
18
|
import { strToUtf8, utf8ToStr, } from "../../utils/string_parsing";
|
|
19
|
-
import takeFirstSet from "../../utils/take_first_set";
|
|
20
19
|
import getISOBMFFTimingInfos from "../utils/get_isobmff_timing_infos";
|
|
21
20
|
import inferSegmentContainer from "../utils/infer_segment_container";
|
|
22
21
|
import { getISOBMFFEmbeddedTextTrackData, getPlainTextTrackData, } from "../utils/parse_text_track";
|
|
@@ -40,6 +39,7 @@ import { getISOBMFFEmbeddedTextTrackData, getPlainTextTrackData, } from "../util
|
|
|
40
39
|
* @returns {Object}
|
|
41
40
|
*/
|
|
42
41
|
function parseISOBMFFEmbeddedTextTrack(data, isChunked, content, initTimescale, __priv_patchLastSegmentInSidx) {
|
|
42
|
+
var _a;
|
|
43
43
|
var period = content.period, representation = content.representation, segment = content.segment;
|
|
44
44
|
var isInit = segment.isInit, indexRange = segment.indexRange;
|
|
45
45
|
var chunkBytes = typeof data === "string" ? strToUtf8(data) :
|
|
@@ -77,7 +77,7 @@ function parseISOBMFFEmbeddedTextTrack(data, isChunked, content, initTimescale,
|
|
|
77
77
|
}
|
|
78
78
|
var chunkInfos = getISOBMFFTimingInfos(chunkBytes, isChunked, segment, initTimescale);
|
|
79
79
|
var chunkData = getISOBMFFEmbeddedTextTrackData(content, chunkBytes, chunkInfos, isChunked);
|
|
80
|
-
var chunkOffset =
|
|
80
|
+
var chunkOffset = (_a = segment.timestampOffset) !== null && _a !== void 0 ? _a : 0;
|
|
81
81
|
return { segmentType: "media", chunkData: chunkData, chunkSize: chunkBytes.length, chunkInfos: chunkInfos, chunkOffset: chunkOffset, protectionDataUpdate: false,
|
|
82
82
|
appendWindow: [period.start, period.end] };
|
|
83
83
|
}
|
|
@@ -16,11 +16,10 @@
|
|
|
16
16
|
import { getMDHDTimescale, takePSSHOut, } from "../../parsers/containers/isobmff";
|
|
17
17
|
import { getKeyIdFromInitSegment } from "../../parsers/containers/isobmff/utils";
|
|
18
18
|
import { getTimeCodeScale } from "../../parsers/containers/matroska";
|
|
19
|
-
import takeFirstSet from "../../utils/take_first_set";
|
|
20
19
|
import getISOBMFFTimingInfos from "../utils/get_isobmff_timing_infos";
|
|
21
20
|
import inferSegmentContainer from "../utils/infer_segment_container";
|
|
22
21
|
export default function segmentParser(loadedSegment, content, initTimescale) {
|
|
23
|
-
var _a;
|
|
22
|
+
var _a, _b;
|
|
24
23
|
var period = content.period, adaptation = content.adaptation, representation = content.representation, segment = content.segment;
|
|
25
24
|
var data = loadedSegment.data;
|
|
26
25
|
var appendWindow = [period.start, period.end];
|
|
@@ -65,6 +64,6 @@ export default function segmentParser(loadedSegment, content, initTimescale) {
|
|
|
65
64
|
}
|
|
66
65
|
var chunkInfos = seemsToBeMP4 ? getISOBMFFTimingInfos(chunkData, false, segment, initTimescale) :
|
|
67
66
|
null; // TODO extract time info from webm
|
|
68
|
-
var chunkOffset =
|
|
67
|
+
var chunkOffset = (_b = segment.timestampOffset) !== null && _b !== void 0 ? _b : 0;
|
|
69
68
|
return { segmentType: "media", chunkData: chunkData, chunkSize: chunkData.length, chunkInfos: chunkInfos, chunkOffset: chunkOffset, protectionDataUpdate: false, appendWindow: appendWindow };
|
|
70
69
|
}
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { getMDHDTimescale } from "../../parsers/containers/isobmff";
|
|
17
17
|
import { strToUtf8, utf8ToStr, } from "../../utils/string_parsing";
|
|
18
|
-
import takeFirstSet from "../../utils/take_first_set";
|
|
19
18
|
import getISOBMFFTimingInfos from "../utils/get_isobmff_timing_infos";
|
|
20
19
|
import inferSegmentContainer from "../utils/infer_segment_container";
|
|
21
20
|
import { getISOBMFFEmbeddedTextTrackData, getPlainTextTrackData, } from "../utils/parse_text_track";
|
|
@@ -35,6 +34,7 @@ import { getISOBMFFEmbeddedTextTrackData, getPlainTextTrackData, } from "../util
|
|
|
35
34
|
* @returns {Object}
|
|
36
35
|
*/
|
|
37
36
|
function parseISOBMFFEmbeddedTextTrack(data, isChunked, content, initTimescale) {
|
|
37
|
+
var _a;
|
|
38
38
|
var period = content.period, segment = content.segment;
|
|
39
39
|
var chunkBytes = typeof data === "string" ? strToUtf8(data) :
|
|
40
40
|
data instanceof Uint8Array ? data :
|
|
@@ -49,7 +49,7 @@ function parseISOBMFFEmbeddedTextTrack(data, isChunked, content, initTimescale)
|
|
|
49
49
|
}
|
|
50
50
|
var chunkInfos = getISOBMFFTimingInfos(chunkBytes, isChunked, segment, initTimescale);
|
|
51
51
|
var chunkData = getISOBMFFEmbeddedTextTrackData(content, chunkBytes, chunkInfos, isChunked);
|
|
52
|
-
var chunkOffset =
|
|
52
|
+
var chunkOffset = (_a = segment.timestampOffset) !== null && _a !== void 0 ? _a : 0;
|
|
53
53
|
return { segmentType: "media", chunkData: chunkData, chunkSize: chunkBytes.length, chunkInfos: chunkInfos, chunkOffset: chunkOffset, protectionDataUpdate: false,
|
|
54
54
|
appendWindow: [period.start, period.end] };
|
|
55
55
|
}
|
|
@@ -64,6 +64,7 @@ function parseISOBMFFEmbeddedTextTrack(data, isChunked, content, initTimescale)
|
|
|
64
64
|
* @returns {Object}
|
|
65
65
|
*/
|
|
66
66
|
function parsePlainTextTrack(data, isChunked, content) {
|
|
67
|
+
var _a;
|
|
67
68
|
var period = content.period, segment = content.segment;
|
|
68
69
|
if (segment.isInit) {
|
|
69
70
|
return { segmentType: "init",
|
|
@@ -84,7 +85,7 @@ function parsePlainTextTrack(data, isChunked, content) {
|
|
|
84
85
|
textTrackData = data;
|
|
85
86
|
}
|
|
86
87
|
var chunkData = getPlainTextTrackData(content, textTrackData, isChunked);
|
|
87
|
-
var chunkOffset =
|
|
88
|
+
var chunkOffset = (_a = segment.timestampOffset) !== null && _a !== void 0 ? _a : 0;
|
|
88
89
|
return { segmentType: "media", chunkData: chunkData, chunkSize: chunkSize, chunkInfos: null, chunkOffset: chunkOffset, protectionDataUpdate: false,
|
|
89
90
|
appendWindow: [period.start, period.end] };
|
|
90
91
|
}
|