rx-player 3.28.1-dev.2022083000 → 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/CHANGELOG.md +11 -1
- package/VERSION +1 -1
- 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/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/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 +8 -1
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.js +10 -4
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher_creator.d.ts +7 -0
- 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/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 +7 -3
- 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/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/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 -10
- 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 +8 -6
- package/dist/_esm5.processed/transports/types.d.ts +25 -2
- 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/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 -2
- package/dist/_esm5.processed/utils/task_canceller.js +1 -2
- package/dist/mpd-parser.wasm +0 -0
- package/dist/rx-player.js +1116 -695
- package/dist/rx-player.min.js +1 -1
- package/package.json +7 -7
- package/sonar-project.properties +1 -1
- package/src/compat/event_listeners.ts +86 -1
- package/src/compat/on_height_width_change.ts +48 -49
- package/src/core/api/playback_observer.ts +34 -14
- package/src/core/api/public_api.ts +23 -18
- package/src/core/fetchers/manifest/manifest_fetcher.ts +20 -2
- package/src/core/fetchers/segment/segment_fetcher.ts +23 -3
- package/src/core/fetchers/segment/segment_fetcher_creator.ts +7 -0
- 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/force_garbage_collection.ts +28 -32
- package/src/core/stream/representation/get_buffer_status.ts +7 -3
- 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/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/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 -6
- package/src/transports/smooth/pipelines.ts +17 -9
- package/src/transports/smooth/segment_loader.ts +8 -0
- package/src/transports/types.ts +27 -0
- package/src/transports/utils/call_custom_manifest_loader.ts +8 -2
- package/src/transports/utils/generate_manifest_loader.ts +18 -5
- package/src/utils/request/fetch.ts +7 -8
- package/src/utils/request/xhr.ts +31 -15
- package/src/utils/task_canceller.ts +1 -2
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rx-player",
|
|
3
3
|
"author": "Canal+",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.29.0-dev.2022090500",
|
|
5
5
|
"description": "Canal+ HTML5 Video Player",
|
|
6
6
|
"main": "./dist/rx-player.js",
|
|
7
7
|
"keywords": [
|
|
@@ -88,17 +88,17 @@
|
|
|
88
88
|
"@types/chai": "4.3.3",
|
|
89
89
|
"@types/jest": "28.1.8",
|
|
90
90
|
"@types/mocha": "9.1.1",
|
|
91
|
-
"@types/node": "18.7.
|
|
91
|
+
"@types/node": "18.7.14",
|
|
92
92
|
"@types/sinon": "10.0.13",
|
|
93
|
-
"@typescript-eslint/eslint-plugin": "5.
|
|
94
|
-
"@typescript-eslint/eslint-plugin-tslint": "5.
|
|
95
|
-
"@typescript-eslint/parser": "5.
|
|
93
|
+
"@typescript-eslint/eslint-plugin": "5.36.1",
|
|
94
|
+
"@typescript-eslint/eslint-plugin-tslint": "5.36.1",
|
|
95
|
+
"@typescript-eslint/parser": "5.36.1",
|
|
96
96
|
"arraybuffer-loader": "1.0.8",
|
|
97
97
|
"babel-loader": "8.2.5",
|
|
98
98
|
"chai": "4.3.6",
|
|
99
99
|
"cheerio": "1.0.0-rc.12",
|
|
100
100
|
"core-js": "3.25.0",
|
|
101
|
-
"esbuild": "0.15.
|
|
101
|
+
"esbuild": "0.15.6",
|
|
102
102
|
"eslint": "8.23.0",
|
|
103
103
|
"eslint-plugin-import": "2.26.0",
|
|
104
104
|
"eslint-plugin-jsdoc": "39.3.6",
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
"rimraf": "3.0.2",
|
|
125
125
|
"semver": "7.3.7",
|
|
126
126
|
"sinon": "14.0.0",
|
|
127
|
-
"terser-webpack-plugin": "5.3.
|
|
127
|
+
"terser-webpack-plugin": "5.3.6",
|
|
128
128
|
"ts-jest": "28.0.8",
|
|
129
129
|
"ts-loader": "9.3.1",
|
|
130
130
|
"tslint": "6.1.3",
|
package/sonar-project.properties
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
sonar.projectKey=rx-player
|
|
2
2
|
sonar.organization=rx-player
|
|
3
3
|
sonar.projectName=rx-player
|
|
4
|
-
sonar.projectVersion=3.
|
|
4
|
+
sonar.projectVersion=3.29.0-dev.2022090500
|
|
5
5
|
sonar.sources=./src,./demo,./tests
|
|
6
6
|
sonar.exclusions=demo/full/bundle.js,demo/standalone/lib.js,demo/bundle.js
|
|
7
7
|
sonar.host.url=https://sonarcloud.io
|
|
@@ -107,6 +107,69 @@ export type IEventTargetLike = HTMLElement |
|
|
|
107
107
|
IEventEmitterLike |
|
|
108
108
|
IEventEmitter<unknown>;
|
|
109
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Returns a function allowing to add event listeners for particular event(s)
|
|
112
|
+
* optionally automatically adding browser prefixes if needed.
|
|
113
|
+
* @param {Array.<string>} eventNames - The event(s) to listen to. If multiple
|
|
114
|
+
* events are set, the event listener will be triggered when any of them emits.
|
|
115
|
+
* @returns {Function} - Returns function allowing to easily add a callback to
|
|
116
|
+
* be triggered when that event is emitted on a given event target.
|
|
117
|
+
*/
|
|
118
|
+
function createCompatibleEventListener(
|
|
119
|
+
eventNames : string[]
|
|
120
|
+
) :
|
|
121
|
+
(
|
|
122
|
+
element : IEventTargetLike,
|
|
123
|
+
listener : (event? : unknown) => void,
|
|
124
|
+
cancelSignal: CancellationSignal
|
|
125
|
+
) => void
|
|
126
|
+
{
|
|
127
|
+
let mem : string|undefined;
|
|
128
|
+
const prefixedEvents = eventPrefixed(eventNames);
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
element : IEventTargetLike,
|
|
132
|
+
listener: (event? : unknown) => void,
|
|
133
|
+
cancelSignal: CancellationSignal
|
|
134
|
+
) => {
|
|
135
|
+
if (cancelSignal.isCancelled) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// if the element is a HTMLElement we can detect
|
|
140
|
+
// the supported event, and memoize it in `mem`
|
|
141
|
+
if (element instanceof HTMLElement) {
|
|
142
|
+
if (typeof mem === "undefined") {
|
|
143
|
+
mem = findSupportedEvent(element, prefixedEvents);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (isNonEmptyString(mem)) {
|
|
147
|
+
element.addEventListener(mem, listener);
|
|
148
|
+
cancelSignal.register(() => {
|
|
149
|
+
if (mem !== undefined) {
|
|
150
|
+
element.removeEventListener(mem, listener);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
} else {
|
|
154
|
+
if (__ENVIRONMENT__.CURRENT_ENV === __ENVIRONMENT__.DEV as number) {
|
|
155
|
+
log.warn(`compat: element ${element.tagName}` +
|
|
156
|
+
" does not support any of these events: " +
|
|
157
|
+
prefixedEvents.join(", "));
|
|
158
|
+
}
|
|
159
|
+
return ;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
prefixedEvents.forEach(eventName => {
|
|
164
|
+
(element as IEventEmitterLike).addEventListener(eventName, listener);
|
|
165
|
+
cancelSignal.register(() => {
|
|
166
|
+
(element as IEventEmitterLike).removeEventListener(eventName, listener);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
}
|
|
172
|
+
|
|
110
173
|
/**
|
|
111
174
|
* @param {Array.<string>} eventNames
|
|
112
175
|
* @param {Array.<string>|undefined} prefixes
|
|
@@ -247,7 +310,8 @@ export interface IPictureInPictureEvent {
|
|
|
247
310
|
|
|
248
311
|
/**
|
|
249
312
|
* Emit when video enters and leaves Picture-In-Picture mode.
|
|
250
|
-
* @param {HTMLMediaElement}
|
|
313
|
+
* @param {HTMLMediaElement} elt
|
|
314
|
+
* @param {Object} stopListening
|
|
251
315
|
* @returns {Observable}
|
|
252
316
|
*/
|
|
253
317
|
function getPictureOnPictureStateRef(
|
|
@@ -505,6 +569,24 @@ const onKeyError$ = compatibleListener(["keyerror", "error"]);
|
|
|
505
569
|
*/
|
|
506
570
|
const onKeyStatusesChange$ = compatibleListener(["keystatuseschange"]);
|
|
507
571
|
|
|
572
|
+
/**
|
|
573
|
+
* @param {HTMLMediaElement} mediaElement
|
|
574
|
+
* @returns {Observable}
|
|
575
|
+
*/
|
|
576
|
+
const onSeeking = createCompatibleEventListener(["seeking"]);
|
|
577
|
+
|
|
578
|
+
/**
|
|
579
|
+
* @param {HTMLMediaElement} mediaElement
|
|
580
|
+
* @returns {Observable}
|
|
581
|
+
*/
|
|
582
|
+
const onSeeked = createCompatibleEventListener(["seeked"]);
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* @param {HTMLMediaElement} mediaElement
|
|
586
|
+
* @returns {Observable}
|
|
587
|
+
*/
|
|
588
|
+
const onEnded = createCompatibleEventListener(["ended"]);
|
|
589
|
+
|
|
508
590
|
/**
|
|
509
591
|
* Utilitary function allowing to add an event listener and remove it
|
|
510
592
|
* automatically once the given `CancellationSignal` emits.
|
|
@@ -534,6 +616,7 @@ export {
|
|
|
534
616
|
getVideoVisibilityRef,
|
|
535
617
|
getVideoWidthRef,
|
|
536
618
|
onEncrypted$,
|
|
619
|
+
onEnded,
|
|
537
620
|
onEnded$,
|
|
538
621
|
onFullscreenChange$,
|
|
539
622
|
onKeyAdded$,
|
|
@@ -542,7 +625,9 @@ export {
|
|
|
542
625
|
onKeyStatusesChange$,
|
|
543
626
|
onLoadedMetadata$,
|
|
544
627
|
onRemoveSourceBuffers$,
|
|
628
|
+
onSeeked,
|
|
545
629
|
onSeeked$,
|
|
630
|
+
onSeeking,
|
|
546
631
|
onSeeking$,
|
|
547
632
|
onSourceClose$,
|
|
548
633
|
onSourceEnded$,
|
|
@@ -14,16 +14,11 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
18
|
-
defer as observableDefer,
|
|
19
|
-
distinctUntilChanged,
|
|
20
|
-
interval as observableInterval,
|
|
21
|
-
map,
|
|
22
|
-
Observable,
|
|
23
|
-
Observer,
|
|
24
|
-
startWith,
|
|
25
|
-
} from "rxjs";
|
|
26
17
|
import log from "../log";
|
|
18
|
+
import createSharedReference, {
|
|
19
|
+
IReadOnlySharedReference,
|
|
20
|
+
} from "../utils/reference";
|
|
21
|
+
import { CancellationSignal } from "../utils/task_canceller";
|
|
27
22
|
import isNode from "./is_node";
|
|
28
23
|
|
|
29
24
|
export interface IResolution { width : number;
|
|
@@ -63,8 +58,8 @@ const _ResizeObserver : IResizeObserverConstructor |
|
|
|
63
58
|
/* eslint-enable @typescript-eslint/no-unsafe-assignment */
|
|
64
59
|
|
|
65
60
|
/**
|
|
66
|
-
* Emit the current height and width of the given `element`
|
|
67
|
-
*
|
|
61
|
+
* Emit the current height and width of the given `element` each time it
|
|
62
|
+
* changes.
|
|
68
63
|
*
|
|
69
64
|
* On some browsers, we might not be able to rely on a native API to know when
|
|
70
65
|
* it changes, the `interval` argument allow us to provide us an inverval in
|
|
@@ -75,46 +70,50 @@ const _ResizeObserver : IResizeObserverConstructor |
|
|
|
75
70
|
*/
|
|
76
71
|
export default function onHeightWidthChange(
|
|
77
72
|
element : HTMLElement,
|
|
78
|
-
interval : number
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
log.error("Compat: Resized but no observed element.");
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
73
|
+
interval : number,
|
|
74
|
+
cancellationSignal : CancellationSignal
|
|
75
|
+
) : IReadOnlySharedReference<IResolution> {
|
|
76
|
+
const { height: initHeight, width: initWidth } = element.getBoundingClientRect();
|
|
77
|
+
const ref = createSharedReference<IResolution>({
|
|
78
|
+
height: initHeight,
|
|
79
|
+
width: initWidth,
|
|
80
|
+
});
|
|
81
|
+
let lastHeight : number = initHeight;
|
|
82
|
+
let lastWidth : number = initWidth;
|
|
91
83
|
|
|
92
|
-
|
|
93
|
-
|
|
84
|
+
if (_ResizeObserver !== undefined) {
|
|
85
|
+
const resizeObserver = new _ResizeObserver(entries => {
|
|
86
|
+
if (entries.length === 0) {
|
|
87
|
+
log.error("Compat: Resized but no observed element.");
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
94
90
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
lastWidth = width;
|
|
98
|
-
obs.next({ height, width });
|
|
99
|
-
}
|
|
100
|
-
});
|
|
91
|
+
const entry = entries[0];
|
|
92
|
+
const { height, width } = entry.contentRect;
|
|
101
93
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
}
|
|
94
|
+
if (height !== lastHeight || width !== lastWidth) {
|
|
95
|
+
lastHeight = height;
|
|
96
|
+
lastWidth = width;
|
|
97
|
+
ref.setValue({ height, width });
|
|
98
|
+
}
|
|
99
|
+
});
|
|
108
100
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
101
|
+
resizeObserver.observe(element);
|
|
102
|
+
cancellationSignal.register(() => {
|
|
103
|
+
resizeObserver.disconnect();
|
|
104
|
+
});
|
|
105
|
+
} else {
|
|
106
|
+
const intervalId = setInterval(() => {
|
|
107
|
+
const { height, width } = element.getBoundingClientRect();
|
|
108
|
+
if (height !== lastHeight || width !== lastWidth) {
|
|
109
|
+
lastHeight = height;
|
|
110
|
+
lastWidth = width;
|
|
111
|
+
ref.setValue({ height, width });
|
|
112
|
+
}
|
|
113
|
+
}, interval);
|
|
114
|
+
cancellationSignal.register(() => {
|
|
115
|
+
clearInterval(intervalId);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return ref;
|
|
120
119
|
}
|
|
@@ -82,7 +82,7 @@ export default class PlaybackObserver {
|
|
|
82
82
|
* This allows us to correctly characterize seeking events: if the counter is
|
|
83
83
|
* superior to `0`, it is probably due to an internal "seek".
|
|
84
84
|
*/
|
|
85
|
-
private
|
|
85
|
+
private _internalSeeksIncoming : number[];
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
88
|
* Stores the last playback observation produced by the `PlaybackObserver`.:
|
|
@@ -106,7 +106,7 @@ export default class PlaybackObserver {
|
|
|
106
106
|
* @param {Object} options
|
|
107
107
|
*/
|
|
108
108
|
constructor(mediaElement : HTMLMediaElement, options : IPlaybackObserverOptions) {
|
|
109
|
-
this.
|
|
109
|
+
this._internalSeeksIncoming = [];
|
|
110
110
|
this._mediaElement = mediaElement;
|
|
111
111
|
this._withMediaSource = options.withMediaSource;
|
|
112
112
|
this._lowLatencyMode = options.lowLatencyMode;
|
|
@@ -137,6 +137,14 @@ export default class PlaybackObserver {
|
|
|
137
137
|
return this._mediaElement.currentTime;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Returns the current playback rate advertised by the `HTMLMediaElement`.
|
|
142
|
+
* @returns {number}
|
|
143
|
+
*/
|
|
144
|
+
public getPlaybackRate() : number {
|
|
145
|
+
return this._mediaElement.playbackRate;
|
|
146
|
+
}
|
|
147
|
+
|
|
140
148
|
/**
|
|
141
149
|
* Returns the current `paused` status advertised by the `HTMLMediaElement`.
|
|
142
150
|
*
|
|
@@ -159,7 +167,7 @@ export default class PlaybackObserver {
|
|
|
159
167
|
* @param {number} time
|
|
160
168
|
*/
|
|
161
169
|
public setCurrentTime(time: number) : void {
|
|
162
|
-
this.
|
|
170
|
+
this._internalSeeksIncoming.push(time);
|
|
163
171
|
this._mediaElement.currentTime = time;
|
|
164
172
|
}
|
|
165
173
|
|
|
@@ -250,17 +258,21 @@ export default class PlaybackObserver {
|
|
|
250
258
|
event : IPlaybackObserverEventType
|
|
251
259
|
) : IPlaybackObservation => {
|
|
252
260
|
let tmpEvt: IPlaybackObserverEventType = event;
|
|
253
|
-
|
|
261
|
+
let startedInternalSeekTime : number | undefined;
|
|
262
|
+
if (tmpEvt === "seeking" && this._internalSeeksIncoming.length > 0) {
|
|
254
263
|
tmpEvt = "internal-seeking";
|
|
255
|
-
this.
|
|
264
|
+
startedInternalSeekTime = this._internalSeeksIncoming.shift();
|
|
256
265
|
}
|
|
257
266
|
const _lastObservation = lastObservation ?? this._generateInitialObservation();
|
|
258
267
|
const mediaTimings = getMediaInfos(this._mediaElement, tmpEvt);
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
(
|
|
262
|
-
|
|
263
|
-
|
|
268
|
+
let pendingInternalSeek : number | null = null;
|
|
269
|
+
if (mediaTimings.seeking) {
|
|
270
|
+
if (typeof startedInternalSeekTime === "number") {
|
|
271
|
+
pendingInternalSeek = startedInternalSeekTime;
|
|
272
|
+
} else if (_lastObservation.pendingInternalSeek !== null && event !== "seeking") {
|
|
273
|
+
pendingInternalSeek = _lastObservation.pendingInternalSeek;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
264
276
|
const rebufferingStatus = getRebufferingStatus(
|
|
265
277
|
_lastObservation,
|
|
266
278
|
mediaTimings,
|
|
@@ -272,14 +284,14 @@ export default class PlaybackObserver {
|
|
|
272
284
|
{},
|
|
273
285
|
{ rebuffering: rebufferingStatus,
|
|
274
286
|
freezing: freezingStatus,
|
|
275
|
-
|
|
287
|
+
pendingInternalSeek },
|
|
276
288
|
mediaTimings);
|
|
277
289
|
if (log.hasLevel("DEBUG")) {
|
|
278
290
|
log.debug("API: current media element state tick",
|
|
279
291
|
"event", timings.event,
|
|
280
292
|
"position", timings.position,
|
|
281
293
|
"seeking", timings.seeking,
|
|
282
|
-
"
|
|
294
|
+
"internalSeek", timings.pendingInternalSeek,
|
|
283
295
|
"rebuffering", timings.rebuffering !== null,
|
|
284
296
|
"freezing", timings.freezing !== null,
|
|
285
297
|
"ended", timings.ended,
|
|
@@ -341,7 +353,7 @@ export default class PlaybackObserver {
|
|
|
341
353
|
return objectAssign(getMediaInfos(this._mediaElement, "init"),
|
|
342
354
|
{ rebuffering: null,
|
|
343
355
|
freezing: null,
|
|
344
|
-
|
|
356
|
+
pendingInternalSeek: null });
|
|
345
357
|
}
|
|
346
358
|
}
|
|
347
359
|
|
|
@@ -457,7 +469,7 @@ export interface IPlaybackObservation extends IMediaInfos {
|
|
|
457
469
|
* If `true`, an "internal seek" (a seeking operation triggered by the
|
|
458
470
|
* RxPlayer code) is currently pending.
|
|
459
471
|
*/
|
|
460
|
-
|
|
472
|
+
pendingInternalSeek : number | null;
|
|
461
473
|
}
|
|
462
474
|
|
|
463
475
|
/**
|
|
@@ -475,6 +487,11 @@ export interface IPlaybackObservation extends IMediaInfos {
|
|
|
475
487
|
export interface IReadOnlyPlaybackObserver<TObservationType> {
|
|
476
488
|
/** Get the current playing position, in seconds. */
|
|
477
489
|
getCurrentTime() : number;
|
|
490
|
+
/**
|
|
491
|
+
* Returns the current playback rate advertised by the `HTMLMediaElement`.
|
|
492
|
+
* @returns {number}
|
|
493
|
+
*/
|
|
494
|
+
getPlaybackRate() : number;
|
|
478
495
|
/** Get the HTMLMediaElement's current `readyState`. */
|
|
479
496
|
getReadyState() : number;
|
|
480
497
|
/**
|
|
@@ -859,6 +876,9 @@ function generateReadOnlyObserver<TSource, TDest>(
|
|
|
859
876
|
getReadyState() {
|
|
860
877
|
return src.getReadyState();
|
|
861
878
|
},
|
|
879
|
+
getPlaybackRate() : number {
|
|
880
|
+
return src.getPlaybackRate();
|
|
881
|
+
},
|
|
862
882
|
getIsPaused() {
|
|
863
883
|
return src.getIsPaused();
|
|
864
884
|
},
|
|
@@ -432,7 +432,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
432
432
|
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1194624
|
|
433
433
|
videoElement.preload = "auto";
|
|
434
434
|
|
|
435
|
-
this.version = /* PLAYER_VERSION */"3.
|
|
435
|
+
this.version = /* PLAYER_VERSION */"3.29.0-dev.2022090500";
|
|
436
436
|
this.log = log;
|
|
437
437
|
this.state = "STOPPED";
|
|
438
438
|
this.videoElement = videoElement;
|
|
@@ -741,21 +741,28 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
741
741
|
|
|
742
742
|
const transportPipelines = transportFn(transportOptions);
|
|
743
743
|
|
|
744
|
-
const { offlineRetry,
|
|
744
|
+
const { offlineRetry,
|
|
745
|
+
segmentRetry,
|
|
746
|
+
manifestRetry,
|
|
747
|
+
manifestRequestTimeout,
|
|
748
|
+
segmentRequestTimeout } = networkConfig;
|
|
745
749
|
|
|
746
750
|
/** Interface used to load and refresh the Manifest. */
|
|
747
|
-
const manifestFetcher = new ManifestFetcher(
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
751
|
+
const manifestFetcher = new ManifestFetcher(
|
|
752
|
+
url,
|
|
753
|
+
transportPipelines,
|
|
754
|
+
{ lowLatencyMode,
|
|
755
|
+
maxRetryRegular: manifestRetry,
|
|
756
|
+
maxRetryOffline: offlineRetry,
|
|
757
|
+
requestTimeout: manifestRequestTimeout });
|
|
752
758
|
|
|
753
759
|
/** Interface used to download segments. */
|
|
754
760
|
const segmentFetcherCreator = new SegmentFetcherCreator(
|
|
755
761
|
transportPipelines,
|
|
756
762
|
{ lowLatencyMode,
|
|
757
763
|
maxRetryOffline: offlineRetry,
|
|
758
|
-
maxRetryRegular: segmentRetry
|
|
764
|
+
maxRetryRegular: segmentRetry,
|
|
765
|
+
requestTimeout: segmentRequestTimeout });
|
|
759
766
|
|
|
760
767
|
/** Observable emitting the initial Manifest */
|
|
761
768
|
let manifest$ : Observable<IManifestFetcherParsedResult |
|
|
@@ -1046,16 +1053,14 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1046
1053
|
// Handle state updates
|
|
1047
1054
|
playerState$
|
|
1048
1055
|
.pipe(takeUntil(stoppedContent$))
|
|
1049
|
-
.subscribe(
|
|
1056
|
+
.subscribe(newState => {
|
|
1057
|
+
this._priv_setPlayerState(newState);
|
|
1050
1058
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
.pipe(takeUntil(stoppedContent$))
|
|
1057
|
-
.subscribe(() => {
|
|
1058
|
-
currentContentCanceller.cancel();
|
|
1059
|
+
// Previous call could have performed all kind of side-effects, thus,
|
|
1060
|
+
// we re-check the current state associated to the RxPlayer
|
|
1061
|
+
if (this.state === "ENDED" && this._priv_stopAtEnd) {
|
|
1062
|
+
currentContentCanceller.cancel();
|
|
1063
|
+
}
|
|
1059
1064
|
});
|
|
1060
1065
|
|
|
1061
1066
|
// Link playback events to the corresponding callbacks
|
|
@@ -2943,7 +2948,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2943
2948
|
return activeRepresentations[currentPeriod.id];
|
|
2944
2949
|
}
|
|
2945
2950
|
}
|
|
2946
|
-
Player.version = /* PLAYER_VERSION */"3.
|
|
2951
|
+
Player.version = /* PLAYER_VERSION */"3.29.0-dev.2022090500";
|
|
2947
2952
|
|
|
2948
2953
|
/** Every events sent by the RxPlayer's public API. */
|
|
2949
2954
|
interface IPublicAPIEvent {
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
ITransportPipelines,
|
|
29
29
|
} from "../../../transports";
|
|
30
30
|
import assert from "../../../utils/assert";
|
|
31
|
+
import isNullOrUndefined from "../../../utils/is_null_or_undefined";
|
|
31
32
|
import TaskCanceller from "../../../utils/task_canceller";
|
|
32
33
|
import errorSelector from "../utils/error_selector";
|
|
33
34
|
import {
|
|
@@ -103,6 +104,13 @@ export interface IManifestFetcherSettings {
|
|
|
103
104
|
maxRetryRegular : number | undefined;
|
|
104
105
|
/** Maximum number of time a request be retried when the user is offline. */
|
|
105
106
|
maxRetryOffline : number | undefined;
|
|
107
|
+
/**
|
|
108
|
+
* Timeout after which request are aborted and, depending on other options,
|
|
109
|
+
* retried.
|
|
110
|
+
* To set to `-1` for no timeout.
|
|
111
|
+
* `undefined` will lead to a default, large, timeout being used.
|
|
112
|
+
*/
|
|
113
|
+
requestTimeout : number | undefined;
|
|
106
114
|
}
|
|
107
115
|
|
|
108
116
|
/**
|
|
@@ -164,6 +172,7 @@ export default class ManifestFetcher {
|
|
|
164
172
|
IManifestFetcherWarningEvent>
|
|
165
173
|
{
|
|
166
174
|
return new Observable((obs) => {
|
|
175
|
+
const settings = this._settings;
|
|
167
176
|
const pipelines = this._pipelines;
|
|
168
177
|
const requestUrl = url ?? this._manifestUrl;
|
|
169
178
|
|
|
@@ -228,12 +237,21 @@ export default class ManifestFetcher {
|
|
|
228
237
|
* Call the loader part of the pipeline, retrying if it fails according
|
|
229
238
|
* to the current settings.
|
|
230
239
|
* Returns the Promise of the last attempt.
|
|
231
|
-
* @param {string | undefined}
|
|
240
|
+
* @param {string | undefined} manifestUrl
|
|
232
241
|
* @returns {Promise}
|
|
233
242
|
*/
|
|
234
243
|
function callLoaderWithRetries(manifestUrl : string | undefined) {
|
|
235
244
|
const { loadManifest } = pipelines;
|
|
236
|
-
|
|
245
|
+
let requestTimeout : number | undefined =
|
|
246
|
+
isNullOrUndefined(settings.requestTimeout) ?
|
|
247
|
+
config.getCurrent().DEFAULT_REQUEST_TIMEOUT :
|
|
248
|
+
settings.requestTimeout;
|
|
249
|
+
if (requestTimeout < 0) {
|
|
250
|
+
requestTimeout = undefined;
|
|
251
|
+
}
|
|
252
|
+
const callLoader = () => loadManifest(manifestUrl,
|
|
253
|
+
{ timeout: requestTimeout },
|
|
254
|
+
canceller.signal);
|
|
237
255
|
return tryRequestPromiseWithBackoff(callLoader,
|
|
238
256
|
backoffSettings,
|
|
239
257
|
canceller.signal);
|
|
@@ -72,6 +72,11 @@ export default function createSegmentFetcher<TLoadedFormat, TSegmentDataType>(
|
|
|
72
72
|
callbacks : ISegmentFetcherCreatorCallbacks,
|
|
73
73
|
options : ISegmentFetcherOptions
|
|
74
74
|
) : ISegmentFetcher<TSegmentDataType> {
|
|
75
|
+
const requestOptions = {
|
|
76
|
+
timeout: options.requestTimeout < 0 ? undefined :
|
|
77
|
+
options.requestTimeout,
|
|
78
|
+
};
|
|
79
|
+
|
|
75
80
|
/**
|
|
76
81
|
* Cache audio and video initialization segments.
|
|
77
82
|
* This allows to avoid doing too many requests for what are usually very
|
|
@@ -257,7 +262,11 @@ export default function createSegmentFetcher<TLoadedFormat, TSegmentDataType>(
|
|
|
257
262
|
url : string | null,
|
|
258
263
|
cancellationSignal: CancellationSignal
|
|
259
264
|
) {
|
|
260
|
-
return loadSegment(url,
|
|
265
|
+
return loadSegment(url,
|
|
266
|
+
content,
|
|
267
|
+
requestOptions,
|
|
268
|
+
cancellationSignal,
|
|
269
|
+
loaderCallbacks);
|
|
261
270
|
}
|
|
262
271
|
|
|
263
272
|
/**
|
|
@@ -428,6 +437,12 @@ export interface ISegmentFetcherOptions {
|
|
|
428
437
|
* currently offline.
|
|
429
438
|
*/
|
|
430
439
|
maxRetryOffline : number;
|
|
440
|
+
/**
|
|
441
|
+
* Timeout after which request are aborted and, depending on other options,
|
|
442
|
+
* retried.
|
|
443
|
+
* To set to `-1` for no timeout.
|
|
444
|
+
*/
|
|
445
|
+
requestTimeout : number;
|
|
431
446
|
}
|
|
432
447
|
|
|
433
448
|
/**
|
|
@@ -439,11 +454,14 @@ export function getSegmentFetcherOptions(
|
|
|
439
454
|
bufferType : string,
|
|
440
455
|
{ maxRetryRegular,
|
|
441
456
|
maxRetryOffline,
|
|
442
|
-
lowLatencyMode
|
|
457
|
+
lowLatencyMode,
|
|
458
|
+
requestTimeout } : { maxRetryRegular? : number | undefined;
|
|
443
459
|
maxRetryOffline? : number | undefined;
|
|
460
|
+
requestTimeout? : number | undefined;
|
|
444
461
|
lowLatencyMode : boolean; }
|
|
445
462
|
) : ISegmentFetcherOptions {
|
|
446
463
|
const { DEFAULT_MAX_REQUESTS_RETRY_ON_ERROR,
|
|
464
|
+
DEFAULT_REQUEST_TIMEOUT,
|
|
447
465
|
DEFAULT_MAX_REQUESTS_RETRY_ON_OFFLINE,
|
|
448
466
|
INITIAL_BACKOFF_DELAY_BASE,
|
|
449
467
|
MAX_BACKOFF_DELAY_BASE } = config.getCurrent();
|
|
@@ -453,5 +471,7 @@ export function getSegmentFetcherOptions(
|
|
|
453
471
|
baseDelay: lowLatencyMode ? INITIAL_BACKOFF_DELAY_BASE.LOW_LATENCY :
|
|
454
472
|
INITIAL_BACKOFF_DELAY_BASE.REGULAR,
|
|
455
473
|
maxDelay: lowLatencyMode ? MAX_BACKOFF_DELAY_BASE.LOW_LATENCY :
|
|
456
|
-
MAX_BACKOFF_DELAY_BASE.REGULAR
|
|
474
|
+
MAX_BACKOFF_DELAY_BASE.REGULAR,
|
|
475
|
+
requestTimeout: isNullOrUndefined(requestTimeout) ? DEFAULT_REQUEST_TIMEOUT :
|
|
476
|
+
requestTimeout };
|
|
457
477
|
}
|
|
@@ -135,4 +135,11 @@ export interface ISegmentFetcherCreatorBackoffOptions {
|
|
|
135
135
|
maxRetryRegular : number | undefined;
|
|
136
136
|
/** Maximum number of time a request be retried when the user is offline. */
|
|
137
137
|
maxRetryOffline : number | undefined;
|
|
138
|
+
/**
|
|
139
|
+
* Timeout after which request are aborted and, depending on other options,
|
|
140
|
+
* retried.
|
|
141
|
+
* To set to `-1` for no timeout.
|
|
142
|
+
* `undefined` will lead to a default, large, timeout being used.
|
|
143
|
+
*/
|
|
144
|
+
requestTimeout : number | undefined;
|
|
138
145
|
}
|
|
@@ -170,7 +170,7 @@ export default function initializeDirectfileContent({
|
|
|
170
170
|
* Observable trying to avoid various stalling situations, emitting "stalled"
|
|
171
171
|
* events when it cannot, as well as "unstalled" events when it get out of one.
|
|
172
172
|
*/
|
|
173
|
-
const stallAvoider$ = StallAvoider(playbackObserver, null, EMPTY, EMPTY);
|
|
173
|
+
const stallAvoider$ = StallAvoider(playbackObserver, null, speed, EMPTY, EMPTY);
|
|
174
174
|
|
|
175
175
|
/**
|
|
176
176
|
* Emit a "loaded" events once the initial play has been performed and the
|