rx-player 3.31.0 → 3.31.1-dev.2023062700
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 +8 -0
- package/VERSION +1 -1
- package/dist/_esm5.processed/core/api/public_api.js +5 -2
- package/dist/_esm5.processed/core/init/directfile_content_initializer.d.ts +60 -1
- package/dist/_esm5.processed/core/init/directfile_content_initializer.js +51 -7
- package/dist/_esm5.processed/core/init/utils/initialize_content_decryption.js +2 -2
- package/dist/_esm5.processed/core/stream/representation/utils/get_buffer_status.js +2 -1
- package/dist/rx-player.js +71 -23
- package/dist/rx-player.min.js +1 -1
- package/package.json +1 -1
- package/sonar-project.properties +1 -1
- package/src/core/api/public_api.ts +4 -2
- package/src/core/init/directfile_content_initializer.ts +75 -15
- package/src/core/init/utils/initialize_content_decryption.ts +2 -2
- package/src/core/stream/representation/utils/get_buffer_status.ts +2 -1
package/package.json
CHANGED
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.31.
|
|
4
|
+
sonar.projectVersion=3.31.1-dev.2023062700
|
|
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
|
|
@@ -370,7 +370,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
370
370
|
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1194624
|
|
371
371
|
videoElement.preload = "auto";
|
|
372
372
|
|
|
373
|
-
this.version = /* PLAYER_VERSION */"3.31.
|
|
373
|
+
this.version = /* PLAYER_VERSION */"3.31.1-dev.2023062700";
|
|
374
374
|
this.log = log;
|
|
375
375
|
this.state = "STOPPED";
|
|
376
376
|
this.videoElement = videoElement;
|
|
@@ -781,6 +781,8 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
781
781
|
this.stop();
|
|
782
782
|
this._priv_currentError = null;
|
|
783
783
|
throw new Error("DirectFile feature not activated in your build.");
|
|
784
|
+
} else if (isNullOrUndefined(url)) {
|
|
785
|
+
throw new Error("No URL for a DirectFile content");
|
|
784
786
|
}
|
|
785
787
|
mediaElementTrackChoiceManager =
|
|
786
788
|
this._priv_initializeMediaElementTrackChoiceManager(
|
|
@@ -3088,7 +3090,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
3088
3090
|
return mediaElementTrackChoiceManager;
|
|
3089
3091
|
}
|
|
3090
3092
|
}
|
|
3091
|
-
Player.version = /* PLAYER_VERSION */"3.31.
|
|
3093
|
+
Player.version = /* PLAYER_VERSION */"3.31.1-dev.2023062700";
|
|
3092
3094
|
|
|
3093
3095
|
/** Every events sent by the RxPlayer's public API. */
|
|
3094
3096
|
interface IPublicAPIEvent {
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
IKeySystemOption,
|
|
27
27
|
IPlayerError,
|
|
28
28
|
} from "../../public_types";
|
|
29
|
+
import assert from "../../utils/assert";
|
|
29
30
|
import createSharedReference, {
|
|
30
31
|
IReadOnlySharedReference,
|
|
31
32
|
} from "../../utils/reference";
|
|
@@ -39,35 +40,68 @@ import initializeContentDecryption from "./utils/initialize_content_decryption";
|
|
|
39
40
|
import RebufferingController from "./utils/rebuffering_controller";
|
|
40
41
|
import listenToMediaError from "./utils/throw_on_media_error";
|
|
41
42
|
|
|
43
|
+
/**
|
|
44
|
+
* `ContentIntializer` which will load contents by putting their URL in the
|
|
45
|
+
* `src` attribute of the given HTMLMediaElement.
|
|
46
|
+
*
|
|
47
|
+
* Because such contents are mainly loaded by the browser, those (called
|
|
48
|
+
* "directfile" contents in the RxPlayer) needs a simpler logic in-JS when
|
|
49
|
+
* compared to a content that relies on the MSE API.
|
|
50
|
+
*
|
|
51
|
+
* @class DirectFileContentInitializer
|
|
52
|
+
*/
|
|
42
53
|
export default class DirectFileContentInitializer extends ContentInitializer {
|
|
54
|
+
/**
|
|
55
|
+
* Initial options given to the `DirectFileContentInitializer`.
|
|
56
|
+
*/
|
|
43
57
|
private _settings : IDirectFileOptions;
|
|
58
|
+
/**
|
|
59
|
+
* Allows to abort and clean everything the `DirectFileContentInitializer` is
|
|
60
|
+
* doing.
|
|
61
|
+
*/
|
|
44
62
|
private _initCanceller : TaskCanceller;
|
|
45
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Creates a new `DirectFileContentInitializer` linked to the given settings.
|
|
66
|
+
* @param {Object} settings
|
|
67
|
+
*/
|
|
46
68
|
constructor(settings : IDirectFileOptions) {
|
|
47
69
|
super();
|
|
48
70
|
this._settings = settings;
|
|
49
71
|
this._initCanceller = new TaskCanceller();
|
|
50
72
|
}
|
|
51
73
|
|
|
52
|
-
|
|
74
|
+
/**
|
|
75
|
+
* "Prepare" content so it can later be played by calling `start`.
|
|
76
|
+
*/
|
|
77
|
+
public prepare() : void {
|
|
53
78
|
return; // Directfile contents do not have any preparation
|
|
54
79
|
}
|
|
55
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Start playback of the content linked to this `DirectFileContentInitializer`
|
|
83
|
+
* on the given `HTMLMediaElement` and its associated `PlaybackObserver`.
|
|
84
|
+
* @param {HTMLMediaElement} mediaElement - HTMLMediaElement on which the
|
|
85
|
+
* content will be played.
|
|
86
|
+
* @param {Object} playbackObserver - Object regularly emitting playback
|
|
87
|
+
* information.
|
|
88
|
+
*/
|
|
56
89
|
public start(
|
|
57
90
|
mediaElement : HTMLMediaElement,
|
|
58
91
|
playbackObserver : PlaybackObserver
|
|
59
|
-
): void {
|
|
92
|
+
) : void {
|
|
60
93
|
const cancelSignal = this._initCanceller.signal;
|
|
61
94
|
const { keySystems, speed, url } = this._settings;
|
|
62
95
|
|
|
63
96
|
clearElementSrc(mediaElement);
|
|
64
97
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Create dummy encryption data emitter, as those are not sent from the
|
|
100
|
+
* RxPlayer for directfile contents.
|
|
101
|
+
*/
|
|
69
102
|
const decryptionRef = createSharedReference(null);
|
|
70
103
|
decryptionRef.finish();
|
|
104
|
+
|
|
71
105
|
const drmInitRef =
|
|
72
106
|
initializeContentDecryption(mediaElement, keySystems, decryptionRef, {
|
|
73
107
|
onError: (err) => this._onFatalError(err),
|
|
@@ -99,7 +133,7 @@ export default class DirectFileContentInitializer extends ContentInitializer {
|
|
|
99
133
|
|
|
100
134
|
drmInitRef.onUpdate((evt, stopListeningToDrmUpdates) => {
|
|
101
135
|
if (evt.initializationState.type === "uninitialized") {
|
|
102
|
-
return;
|
|
136
|
+
return; // nothing done yet
|
|
103
137
|
}
|
|
104
138
|
stopListeningToDrmUpdates();
|
|
105
139
|
|
|
@@ -109,39 +143,57 @@ export default class DirectFileContentInitializer extends ContentInitializer {
|
|
|
109
143
|
cancelSignal.register(() => {
|
|
110
144
|
clearElementSrc(mediaElement);
|
|
111
145
|
});
|
|
146
|
+
|
|
112
147
|
if (evt.initializationState.type === "awaiting-media-link") {
|
|
113
148
|
evt.initializationState.value.isMediaLinked.setValue(true);
|
|
114
149
|
drmInitRef.onUpdate((newDrmStatus, stopListeningToDrmUpdatesAgain) => {
|
|
115
150
|
if (newDrmStatus.initializationState.type === "initialized") {
|
|
116
151
|
stopListeningToDrmUpdatesAgain();
|
|
117
152
|
this._seekAndPlay(mediaElement, playbackObserver);
|
|
118
|
-
return;
|
|
119
153
|
}
|
|
120
154
|
}, { emitCurrentValue: true, clearSignal: cancelSignal });
|
|
121
155
|
} else {
|
|
156
|
+
assert(evt.initializationState.type === "initialized");
|
|
122
157
|
this._seekAndPlay(mediaElement, playbackObserver);
|
|
123
|
-
return;
|
|
124
158
|
}
|
|
125
159
|
}, { emitCurrentValue: true, clearSignal: cancelSignal });
|
|
126
160
|
}
|
|
127
161
|
|
|
162
|
+
/**
|
|
163
|
+
* Update URL this `ContentIntializer` depends on.
|
|
164
|
+
* @param {Array.<string>|undefined} _urls
|
|
165
|
+
* @param {boolean} _refreshNow
|
|
166
|
+
*/
|
|
128
167
|
public updateContentUrls(_urls : string[] | undefined, _refreshNow : boolean) : void {
|
|
129
168
|
throw new Error("Cannot update content URL of directfile contents");
|
|
130
169
|
}
|
|
131
170
|
|
|
132
|
-
|
|
171
|
+
/**
|
|
172
|
+
* Stop content and free all resources linked to this `ContentIntializer`.
|
|
173
|
+
*/
|
|
174
|
+
public dispose() : void {
|
|
133
175
|
this._initCanceller.cancel();
|
|
134
176
|
}
|
|
135
177
|
|
|
136
|
-
|
|
178
|
+
/**
|
|
179
|
+
* Logic performed when a fatal error was triggered.
|
|
180
|
+
* @param {*} err - The fatal error in question.
|
|
181
|
+
*/
|
|
182
|
+
private _onFatalError(err : unknown) : void {
|
|
137
183
|
this._initCanceller.cancel();
|
|
138
184
|
this.trigger("error", err);
|
|
139
185
|
}
|
|
140
186
|
|
|
187
|
+
/**
|
|
188
|
+
* Perform the initial seek (to begin playback at an initially-calculated
|
|
189
|
+
* position based on settings) and auto-play if needed when loaded.
|
|
190
|
+
* @param {HTMLMediaElement} mediaElement
|
|
191
|
+
* @param {Object} playbackObserver
|
|
192
|
+
*/
|
|
141
193
|
private _seekAndPlay(
|
|
142
194
|
mediaElement : HTMLMediaElement,
|
|
143
195
|
playbackObserver : PlaybackObserver
|
|
144
|
-
) {
|
|
196
|
+
) : void {
|
|
145
197
|
const cancelSignal = this._initCanceller.signal;
|
|
146
198
|
const { autoPlay, startAt } = this._settings;
|
|
147
199
|
const initialTime = () => {
|
|
@@ -177,7 +229,7 @@ export default class DirectFileContentInitializer extends ContentInitializer {
|
|
|
177
229
|
/**
|
|
178
230
|
* calculate initial time as a position in seconds.
|
|
179
231
|
* @param {HTMLMediaElement} mediaElement
|
|
180
|
-
* @param {Object|undefined} startAt
|
|
232
|
+
* @param {Object|undefined} [startAt]
|
|
181
233
|
* @returns {number}
|
|
182
234
|
*/
|
|
183
235
|
function getDirectFileInitialTime(
|
|
@@ -219,11 +271,19 @@ function getDirectFileInitialTime(
|
|
|
219
271
|
return 0;
|
|
220
272
|
}
|
|
221
273
|
|
|
222
|
-
|
|
274
|
+
/** Options used by the `DirectFileContentInitializer` */
|
|
223
275
|
export interface IDirectFileOptions {
|
|
276
|
+
/** If `true` we will play right after the content is considered "loaded". */
|
|
224
277
|
autoPlay : boolean;
|
|
278
|
+
/**
|
|
279
|
+
* Encryption-related settings. Can be left as an empty array if the content
|
|
280
|
+
* isn't encrypted.
|
|
281
|
+
*/
|
|
225
282
|
keySystems : IKeySystemOption[];
|
|
283
|
+
/** Communicate the playback rate wanted by the user. */
|
|
226
284
|
speed : IReadOnlySharedReference<number>;
|
|
285
|
+
/** Optional initial position to start at. */
|
|
227
286
|
startAt? : IInitialTimeOptions | undefined;
|
|
228
|
-
|
|
287
|
+
/** URL that should be played. */
|
|
288
|
+
url : string;
|
|
229
289
|
}
|
|
@@ -54,9 +54,9 @@ export default function initializeContentDecryption(
|
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
stopListening();
|
|
57
|
-
log.error("Init: Encrypted event but
|
|
57
|
+
log.error("Init: Encrypted event but no `keySystems` given");
|
|
58
58
|
const err = new EncryptedMediaError("MEDIA_IS_ENCRYPTED_ERROR",
|
|
59
|
-
"
|
|
59
|
+
"no `keySystems` given.");
|
|
60
60
|
callbacks.onError(err);
|
|
61
61
|
}, { clearSignal: cancelSignal });
|
|
62
62
|
const ref = createSharedReference({
|
|
@@ -22,7 +22,7 @@ import Manifest, {
|
|
|
22
22
|
} from "../../../../manifest";
|
|
23
23
|
import isNullOrUndefined from "../../../../utils/is_null_or_undefined";
|
|
24
24
|
import { IReadOnlyPlaybackObserver } from "../../../api";
|
|
25
|
-
import {
|
|
25
|
+
import SegmentBuffersStore, {
|
|
26
26
|
IBufferedChunk,
|
|
27
27
|
IEndOfSegmentOperation,
|
|
28
28
|
SegmentBuffer,
|
|
@@ -218,6 +218,7 @@ function getRangeOfNeededSegments(
|
|
|
218
218
|
// avoid ending the last Period - and by extension the content - with a
|
|
219
219
|
// segment which isn't the last one.
|
|
220
220
|
if (!isNullOrUndefined(lastIndexPosition) &&
|
|
221
|
+
SegmentBuffersStore.isNative(content.adaptation.type) &&
|
|
221
222
|
initialWantedTime >= lastIndexPosition &&
|
|
222
223
|
representationIndex.isInitialized() &&
|
|
223
224
|
representationIndex.isFinished() &&
|