rx-player 4.2.0-dev.2024081400 → 4.2.0-dev.2024090300
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 +38 -0
- package/VERSION +1 -1
- package/dist/commonjs/__GENERATED_CODE/embedded_worker.d.ts.map +1 -1
- package/dist/commonjs/__GENERATED_CODE/embedded_worker.js +1 -1
- package/dist/commonjs/compat/browser_detection.d.ts +3 -1
- package/dist/commonjs/compat/browser_detection.d.ts.map +1 -1
- package/dist/commonjs/compat/browser_detection.js +8 -1
- package/dist/commonjs/compat/can_reuse_media_keys.d.ts +2 -0
- package/dist/commonjs/compat/can_reuse_media_keys.d.ts.map +1 -1
- package/dist/commonjs/compat/can_reuse_media_keys.js +3 -1
- package/dist/commonjs/compat/eme/custom_media_keys/types.d.ts +3 -0
- package/dist/commonjs/compat/eme/custom_media_keys/types.d.ts.map +1 -1
- package/dist/commonjs/compat/eme/custom_media_keys/webkit_media_keys.d.ts +1 -1
- package/dist/commonjs/compat/eme/custom_media_keys/webkit_media_keys.d.ts.map +1 -1
- package/dist/commonjs/compat/eme/eme-api-implementation.d.ts +2 -2
- package/dist/commonjs/compat/eme/eme-api-implementation.d.ts.map +1 -1
- package/dist/commonjs/compat/eme/eme-api-implementation.js +19 -2
- package/dist/commonjs/compat/eme/get_init_data.d.ts +3 -1
- package/dist/commonjs/compat/eme/get_init_data.d.ts.map +1 -1
- package/dist/commonjs/compat/eme/get_init_data.js +2 -2
- package/dist/commonjs/compat/event_listeners.d.ts +21 -19
- package/dist/commonjs/compat/event_listeners.d.ts.map +1 -1
- package/dist/commonjs/compat/event_listeners.js +0 -11
- package/dist/commonjs/core/cmcd/cmcd_data_builder.js +1 -1
- package/dist/commonjs/core/main/worker/worker_main.js +1 -0
- package/dist/commonjs/core/segment_sinks/inventory/segment_inventory.js +8 -5
- package/dist/commonjs/main_thread/api/public_api.d.ts +22 -10
- package/dist/commonjs/main_thread/api/public_api.d.ts.map +1 -1
- package/dist/commonjs/main_thread/api/public_api.js +68 -28
- package/dist/commonjs/main_thread/decrypt/content_decryptor.d.ts +8 -0
- package/dist/commonjs/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
- package/dist/commonjs/main_thread/decrypt/content_decryptor.js +51 -2
- package/dist/commonjs/main_thread/decrypt/types.d.ts +5 -0
- package/dist/commonjs/main_thread/decrypt/types.d.ts.map +1 -1
- package/dist/commonjs/main_thread/init/media_source_content_initializer.js +3 -3
- package/dist/commonjs/main_thread/tracks_store/tracks_store.d.ts +12 -4
- package/dist/commonjs/main_thread/tracks_store/tracks_store.d.ts.map +1 -1
- package/dist/commonjs/main_thread/tracks_store/tracks_store.js +18 -8
- package/dist/commonjs/manifest/classes/adaptation.d.ts +13 -13
- package/dist/commonjs/manifest/classes/adaptation.d.ts.map +1 -1
- package/dist/commonjs/manifest/classes/adaptation.js +1 -4
- package/dist/commonjs/manifest/classes/representation.d.ts +20 -12
- package/dist/commonjs/manifest/classes/representation.d.ts.map +1 -1
- package/dist/commonjs/manifest/classes/representation.js +8 -8
- package/dist/commonjs/manifest/utils.d.ts +4 -3
- package/dist/commonjs/manifest/utils.d.ts.map +1 -1
- package/dist/commonjs/manifest/utils.js +13 -7
- package/dist/commonjs/parsers/manifest/dash/common/content_protection_parser.js +4 -4
- package/dist/commonjs/parsers/manifest/local/parse_local_manifest.js +1 -1
- package/dist/commonjs/parsers/manifest/smooth/create_parser.d.ts.map +1 -1
- package/dist/commonjs/parsers/manifest/smooth/create_parser.js +1 -4
- package/dist/commonjs/parsers/manifest/types.d.ts +1 -6
- package/dist/commonjs/parsers/manifest/types.d.ts.map +1 -1
- package/dist/commonjs/public_types.d.ts +69 -0
- package/dist/commonjs/public_types.d.ts.map +1 -1
- package/dist/es2017/__GENERATED_CODE/embedded_worker.d.ts.map +1 -1
- package/dist/es2017/__GENERATED_CODE/embedded_worker.js +1 -1
- package/dist/es2017/compat/browser_detection.d.ts +3 -1
- package/dist/es2017/compat/browser_detection.d.ts.map +1 -1
- package/dist/es2017/compat/browser_detection.js +7 -1
- package/dist/es2017/compat/can_reuse_media_keys.d.ts +2 -0
- package/dist/es2017/compat/can_reuse_media_keys.d.ts.map +1 -1
- package/dist/es2017/compat/can_reuse_media_keys.js +4 -2
- package/dist/es2017/compat/eme/custom_media_keys/types.d.ts +3 -0
- package/dist/es2017/compat/eme/custom_media_keys/types.d.ts.map +1 -1
- package/dist/es2017/compat/eme/custom_media_keys/webkit_media_keys.d.ts +1 -1
- package/dist/es2017/compat/eme/custom_media_keys/webkit_media_keys.d.ts.map +1 -1
- package/dist/es2017/compat/eme/eme-api-implementation.d.ts +2 -2
- package/dist/es2017/compat/eme/eme-api-implementation.d.ts.map +1 -1
- package/dist/es2017/compat/eme/eme-api-implementation.js +19 -2
- package/dist/es2017/compat/eme/get_init_data.d.ts +3 -1
- package/dist/es2017/compat/eme/get_init_data.d.ts.map +1 -1
- package/dist/es2017/compat/eme/get_init_data.js +2 -2
- package/dist/es2017/compat/event_listeners.d.ts +21 -19
- package/dist/es2017/compat/event_listeners.d.ts.map +1 -1
- package/dist/es2017/compat/event_listeners.js +0 -11
- package/dist/es2017/core/cmcd/cmcd_data_builder.js +1 -1
- package/dist/es2017/core/main/worker/worker_main.js +1 -0
- package/dist/es2017/core/segment_sinks/inventory/segment_inventory.js +8 -5
- package/dist/es2017/main_thread/api/public_api.d.ts +22 -10
- package/dist/es2017/main_thread/api/public_api.d.ts.map +1 -1
- package/dist/es2017/main_thread/api/public_api.js +64 -24
- package/dist/es2017/main_thread/decrypt/content_decryptor.d.ts +8 -0
- package/dist/es2017/main_thread/decrypt/content_decryptor.d.ts.map +1 -1
- package/dist/es2017/main_thread/decrypt/content_decryptor.js +47 -2
- package/dist/es2017/main_thread/decrypt/types.d.ts +5 -0
- package/dist/es2017/main_thread/decrypt/types.d.ts.map +1 -1
- package/dist/es2017/main_thread/init/media_source_content_initializer.js +3 -3
- package/dist/es2017/main_thread/tracks_store/tracks_store.d.ts +12 -4
- package/dist/es2017/main_thread/tracks_store/tracks_store.d.ts.map +1 -1
- package/dist/es2017/main_thread/tracks_store/tracks_store.js +18 -8
- package/dist/es2017/manifest/classes/adaptation.d.ts +13 -13
- package/dist/es2017/manifest/classes/adaptation.d.ts.map +1 -1
- package/dist/es2017/manifest/classes/adaptation.js +1 -1
- package/dist/es2017/manifest/classes/representation.d.ts +20 -12
- package/dist/es2017/manifest/classes/representation.d.ts.map +1 -1
- package/dist/es2017/manifest/classes/representation.js +8 -8
- package/dist/es2017/manifest/utils.d.ts +4 -3
- package/dist/es2017/manifest/utils.d.ts.map +1 -1
- package/dist/es2017/manifest/utils.js +13 -7
- package/dist/es2017/parsers/manifest/dash/common/content_protection_parser.js +4 -4
- package/dist/es2017/parsers/manifest/local/parse_local_manifest.js +1 -1
- package/dist/es2017/parsers/manifest/smooth/create_parser.d.ts.map +1 -1
- package/dist/es2017/parsers/manifest/smooth/create_parser.js +1 -4
- package/dist/es2017/parsers/manifest/types.d.ts +1 -6
- package/dist/es2017/parsers/manifest/types.d.ts.map +1 -1
- package/dist/es2017/public_types.d.ts +69 -0
- package/dist/es2017/public_types.d.ts.map +1 -1
- package/dist/rx-player.js +18 -18
- package/dist/worker.js +5 -5
- package/package.json +2 -2
- package/src/__GENERATED_CODE/embedded_worker.ts +1 -1
- package/src/compat/__tests__/can_reuse_media_keys.test.ts +33 -2
- package/src/compat/browser_detection.ts +9 -0
- package/src/compat/can_reuse_media_keys.ts +4 -2
- package/src/compat/eme/custom_media_keys/types.ts +4 -0
- package/src/compat/eme/custom_media_keys/webkit_media_keys.ts +1 -1
- package/src/compat/eme/eme-api-implementation.ts +35 -4
- package/src/compat/eme/get_init_data.ts +5 -3
- package/src/compat/event_listeners.ts +30 -5
- package/src/core/cmcd/cmcd_data_builder.ts +1 -1
- package/src/core/main/worker/worker_main.ts +1 -0
- package/src/core/segment_sinks/inventory/segment_inventory.ts +7 -4
- package/src/main_thread/api/public_api.ts +96 -24
- package/src/main_thread/decrypt/content_decryptor.ts +60 -3
- package/src/main_thread/decrypt/types.ts +5 -0
- package/src/main_thread/init/media_source_content_initializer.ts +3 -3
- package/src/main_thread/tracks_store/tracks_store.ts +30 -6
- package/src/manifest/classes/adaptation.ts +14 -16
- package/src/manifest/classes/representation.ts +26 -18
- package/src/manifest/utils.ts +14 -6
- package/src/parsers/manifest/dash/common/content_protection_parser.ts +4 -4
- package/src/parsers/manifest/local/parse_local_manifest.ts +1 -1
- package/src/parsers/manifest/smooth/create_parser.ts +2 -6
- package/src/parsers/manifest/types.ts +1 -7
- package/src/public_types.ts +73 -0
- package/vitest.config.mjs +1 -0
|
@@ -10,9 +10,9 @@ describe("Compat - canReuseMediaKeys", () => {
|
|
|
10
10
|
vi.resetModules();
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
it("should return true on
|
|
13
|
+
it("should return true on most browsers", async () => {
|
|
14
14
|
vi.doMock("../browser_detection", () => {
|
|
15
|
-
return { isWebOs: false, isPanasonic: false };
|
|
15
|
+
return { isWebOs: false, isPhilipsNetTv: false, isPanasonic: false };
|
|
16
16
|
});
|
|
17
17
|
const canReuseMediaKeys = (await vi.importActual(
|
|
18
18
|
"../can_reuse_media_keys.ts",
|
|
@@ -26,6 +26,37 @@ describe("Compat - canReuseMediaKeys", () => {
|
|
|
26
26
|
isWebOs: true,
|
|
27
27
|
isWebOs2022: false,
|
|
28
28
|
isPanasonic: false,
|
|
29
|
+
isPhilipsNetTv: false,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
const canReuseMediaKeys = (await vi.importActual(
|
|
33
|
+
"../can_reuse_media_keys.ts",
|
|
34
|
+
)) as any;
|
|
35
|
+
expect(canReuseMediaKeys.default()).toBe(false);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("should return false on Panasonic", async () => {
|
|
39
|
+
vi.doMock("../browser_detection", () => {
|
|
40
|
+
return {
|
|
41
|
+
isWebOs: false,
|
|
42
|
+
isWebOs2022: false,
|
|
43
|
+
isPanasonic: true,
|
|
44
|
+
isPhilipsNetTv: false,
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
const canReuseMediaKeys = (await vi.importActual(
|
|
48
|
+
"../can_reuse_media_keys.ts",
|
|
49
|
+
)) as any;
|
|
50
|
+
expect(canReuseMediaKeys.default()).toBe(false);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("should return false on Philips' NETTV", async () => {
|
|
54
|
+
vi.doMock("../browser_detection", () => {
|
|
55
|
+
return {
|
|
56
|
+
isWebOs: false,
|
|
57
|
+
isWebOs2022: false,
|
|
58
|
+
isPanasonic: false,
|
|
59
|
+
isPhilipsNetTv: true,
|
|
29
60
|
};
|
|
30
61
|
});
|
|
31
62
|
const canReuseMediaKeys = (await vi.importActual(
|
|
@@ -67,6 +67,9 @@ let isWebOs2022 = false;
|
|
|
67
67
|
/** `true` for Panasonic devices. */
|
|
68
68
|
let isPanasonic = false;
|
|
69
69
|
|
|
70
|
+
/** `true` we're relying on Philips's NetTv browser. */
|
|
71
|
+
let isPhilipsNetTv = false;
|
|
72
|
+
|
|
70
73
|
/** `true` for the PlayStation 4 game console. */
|
|
71
74
|
let isPlayStation4 = false;
|
|
72
75
|
|
|
@@ -155,6 +158,11 @@ let isXbox = false;
|
|
|
155
158
|
) {
|
|
156
159
|
isWebOs2021 = true;
|
|
157
160
|
}
|
|
161
|
+
} else if (
|
|
162
|
+
navigator.userAgent.indexOf("NETTV") !== -1 &&
|
|
163
|
+
navigator.userAgent.indexOf("Philips") !== -1
|
|
164
|
+
) {
|
|
165
|
+
isPhilipsNetTv = true;
|
|
158
166
|
} else if (/[Pp]anasonic/.test(navigator.userAgent)) {
|
|
159
167
|
isPanasonic = true;
|
|
160
168
|
} else if (navigator.userAgent.indexOf("Xbox") !== -1) {
|
|
@@ -168,6 +176,7 @@ export {
|
|
|
168
176
|
isIEOrEdge,
|
|
169
177
|
isFirefox,
|
|
170
178
|
isPanasonic,
|
|
179
|
+
isPhilipsNetTv,
|
|
171
180
|
isPlayStation4,
|
|
172
181
|
isPlayStation5,
|
|
173
182
|
isXbox,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isPanasonic, isWebOs } from "./browser_detection";
|
|
1
|
+
import { isPanasonic, isPhilipsNetTv, isWebOs } from "./browser_detection";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Returns `true` if a `MediaKeys` instance (the `Encrypted Media Extension`
|
|
@@ -9,9 +9,11 @@ import { isPanasonic, isWebOs } from "./browser_detection";
|
|
|
9
9
|
* - (2022-11-21): WebOS (LG TVs), for some encrypted contents, just
|
|
10
10
|
* rebuffered indefinitely when loading a content already-loaded on the
|
|
11
11
|
* HTMLMediaElement.
|
|
12
|
+
* - (2024-08-23): Seen on Philips 2024 and 2023 in:
|
|
13
|
+
* https://github.com/canalplus/rx-player/issues/1464
|
|
12
14
|
*
|
|
13
15
|
* @returns {boolean}
|
|
14
16
|
*/
|
|
15
17
|
export default function canReuseMediaKeys(): boolean {
|
|
16
|
-
return !isWebOs && !isPanasonic;
|
|
18
|
+
return !isWebOs && !isPhilipsNetTv && !isPanasonic;
|
|
17
19
|
}
|
|
@@ -30,7 +30,7 @@ import type { IWebKitMediaKeys } from "./webkit_media_keys_constructor";
|
|
|
30
30
|
import { WebKitMediaKeysConstructor } from "./webkit_media_keys_constructor";
|
|
31
31
|
|
|
32
32
|
export interface ICustomWebKitMediaKeys {
|
|
33
|
-
_setVideo: (videoElement: IMediaElement) =>
|
|
33
|
+
_setVideo: (videoElement: IMediaElement) => Promise<unknown>;
|
|
34
34
|
createSession(mimeType: string, initData: Uint8Array): ICustomMediaKeySession;
|
|
35
35
|
setServerCertificate(setServerCertificate: BufferSource): Promise<void>;
|
|
36
36
|
}
|
|
@@ -3,6 +3,7 @@ import assert from "../../utils/assert";
|
|
|
3
3
|
import globalScope from "../../utils/global_scope";
|
|
4
4
|
import isNode from "../../utils/is_node";
|
|
5
5
|
import isNullOrUndefined from "../../utils/is_null_or_undefined";
|
|
6
|
+
import objectAssign from "../../utils/object_assign";
|
|
6
7
|
import type { CancellationSignal } from "../../utils/task_canceller";
|
|
7
8
|
import type { IMediaElement } from "../browser_compatibility_types";
|
|
8
9
|
import { isIE11 } from "../browser_detection";
|
|
@@ -19,7 +20,10 @@ import getMozMediaKeysCallbacks, {
|
|
|
19
20
|
import getOldKitWebKitMediaKeyCallbacks, {
|
|
20
21
|
isOldWebkitMediaElement,
|
|
21
22
|
} from "./custom_media_keys/old_webkit_media_keys";
|
|
22
|
-
import type {
|
|
23
|
+
import type {
|
|
24
|
+
ICustomMediaEncryptedEvent,
|
|
25
|
+
ICustomMediaKeys,
|
|
26
|
+
} from "./custom_media_keys/types";
|
|
23
27
|
import getWebKitMediaKeysCallbacks from "./custom_media_keys/webkit_media_keys";
|
|
24
28
|
import { WebKitMediaKeysConstructor } from "./custom_media_keys/webkit_media_keys_constructor";
|
|
25
29
|
|
|
@@ -63,7 +67,7 @@ export interface IEmeApiImplementation {
|
|
|
63
67
|
*/
|
|
64
68
|
onEncrypted: (
|
|
65
69
|
target: IEventTargetLike,
|
|
66
|
-
listener: (evt:
|
|
70
|
+
listener: (evt: ICustomMediaEncryptedEvent) => void,
|
|
67
71
|
cancelSignal: CancellationSignal,
|
|
68
72
|
) => void;
|
|
69
73
|
|
|
@@ -143,8 +147,8 @@ function getEmeApiImplementation(
|
|
|
143
147
|
let createCustomMediaKeys: (keyType: string) => ICustomMediaKeys;
|
|
144
148
|
|
|
145
149
|
if (preferredApiType === "webkit" && WebKitMediaKeysConstructor !== undefined) {
|
|
146
|
-
onEncrypted = createCompatibleEventListener(["needkey"]);
|
|
147
150
|
const callbacks = getWebKitMediaKeysCallbacks();
|
|
151
|
+
onEncrypted = createOnEncryptedForWebkit();
|
|
148
152
|
isTypeSupported = callbacks.isTypeSupported;
|
|
149
153
|
createCustomMediaKeys = callbacks.createCustomMediaKeys;
|
|
150
154
|
setMediaKeys = callbacks.setMediaKeys;
|
|
@@ -160,7 +164,7 @@ function getEmeApiImplementation(
|
|
|
160
164
|
implementation = "older-webkit";
|
|
161
165
|
// This is for WebKit with prefixed EME api
|
|
162
166
|
} else if (WebKitMediaKeysConstructor !== undefined) {
|
|
163
|
-
onEncrypted =
|
|
167
|
+
onEncrypted = createOnEncryptedForWebkit();
|
|
164
168
|
const callbacks = getWebKitMediaKeysCallbacks();
|
|
165
169
|
isTypeSupported = callbacks.isTypeSupported;
|
|
166
170
|
createCustomMediaKeys = callbacks.createCustomMediaKeys;
|
|
@@ -274,6 +278,33 @@ function getEmeApiImplementation(
|
|
|
274
278
|
implementation,
|
|
275
279
|
};
|
|
276
280
|
}
|
|
281
|
+
/**
|
|
282
|
+
* Create an event listener for the "webkitneedkey" event
|
|
283
|
+
* @returns
|
|
284
|
+
*/
|
|
285
|
+
function createOnEncryptedForWebkit(): IEmeApiImplementation["onEncrypted"] {
|
|
286
|
+
const compatibleEventListener = createCompatibleEventListener(
|
|
287
|
+
["needkey"],
|
|
288
|
+
undefined /* prefixes */,
|
|
289
|
+
);
|
|
290
|
+
const onEncrypted = (
|
|
291
|
+
target: IEventTargetLike,
|
|
292
|
+
listener: (event: ICustomMediaEncryptedEvent) => void,
|
|
293
|
+
cancelSignal: CancellationSignal,
|
|
294
|
+
) => {
|
|
295
|
+
compatibleEventListener(
|
|
296
|
+
target,
|
|
297
|
+
(event?: Event) => {
|
|
298
|
+
const patchedEvent = objectAssign(event as MediaEncryptedEvent, {
|
|
299
|
+
forceSessionRecreation: true,
|
|
300
|
+
});
|
|
301
|
+
listener(patchedEvent);
|
|
302
|
+
},
|
|
303
|
+
cancelSignal,
|
|
304
|
+
);
|
|
305
|
+
};
|
|
306
|
+
return onEncrypted;
|
|
307
|
+
}
|
|
277
308
|
|
|
278
309
|
/**
|
|
279
310
|
* Set the given MediaKeys on the given HTMLMediaElement.
|
|
@@ -20,6 +20,7 @@ import areArraysOfNumbersEqual from "../../utils/are_arrays_of_numbers_equal";
|
|
|
20
20
|
import { be4toi } from "../../utils/byte_parsing";
|
|
21
21
|
import isNullOrUndefined from "../../utils/is_null_or_undefined";
|
|
22
22
|
import { PSSH_TO_INTEGER } from "./constants";
|
|
23
|
+
import type { ICustomMediaEncryptedEvent } from "./custom_media_keys/types";
|
|
23
24
|
|
|
24
25
|
/** Data recuperated from parsing the payload of an `encrypted` event. */
|
|
25
26
|
export interface IEncryptedEventData {
|
|
@@ -50,6 +51,7 @@ export interface IEncryptedEventData {
|
|
|
50
51
|
*/
|
|
51
52
|
data: Uint8Array;
|
|
52
53
|
}>;
|
|
54
|
+
forceSessionRecreation?: boolean | undefined;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
/**
|
|
@@ -145,9 +147,9 @@ function isPSSHAlreadyEncountered(
|
|
|
145
147
|
* encountered in the given event.
|
|
146
148
|
*/
|
|
147
149
|
export default function getInitData(
|
|
148
|
-
encryptedEvent:
|
|
150
|
+
encryptedEvent: ICustomMediaEncryptedEvent,
|
|
149
151
|
): IEncryptedEventData | null {
|
|
150
|
-
const { initData, initDataType } = encryptedEvent;
|
|
152
|
+
const { initData, initDataType, forceSessionRecreation } = encryptedEvent;
|
|
151
153
|
if (isNullOrUndefined(initData)) {
|
|
152
154
|
log.warn("Compat: No init data found on media encrypted event.");
|
|
153
155
|
return null;
|
|
@@ -155,5 +157,5 @@ export default function getInitData(
|
|
|
155
157
|
|
|
156
158
|
const initDataBytes = new Uint8Array(initData);
|
|
157
159
|
const values = getInitializationDataValues(initDataBytes);
|
|
158
|
-
return { type: initDataType, values };
|
|
160
|
+
return { type: initDataType, values, forceSessionRecreation };
|
|
159
161
|
}
|
|
@@ -30,6 +30,7 @@ import type {
|
|
|
30
30
|
IEventTarget,
|
|
31
31
|
IMediaElement,
|
|
32
32
|
} from "./browser_compatibility_types";
|
|
33
|
+
import type { ICustomMediaEncryptedEvent } from "./eme/custom_media_keys/types";
|
|
33
34
|
|
|
34
35
|
const BROWSER_PREFIXES = ["", "webkit", "moz", "ms"];
|
|
35
36
|
|
|
@@ -82,8 +83,14 @@ function eventPrefixed(eventNames: string[], prefixes?: string[]): string[] {
|
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
export interface IEventEmitterLike {
|
|
85
|
-
addEventListener: (
|
|
86
|
-
|
|
86
|
+
addEventListener: (
|
|
87
|
+
eventName: string,
|
|
88
|
+
handler: EventListenerOrEventListenerObject,
|
|
89
|
+
) => void;
|
|
90
|
+
removeEventListener: (
|
|
91
|
+
eventName: string,
|
|
92
|
+
handler: EventListenerOrEventListenerObject,
|
|
93
|
+
) => void;
|
|
87
94
|
}
|
|
88
95
|
|
|
89
96
|
export type IEventTargetLike = HTMLElement | IEventEmitterLike | IEventEmitter<unknown>;
|
|
@@ -99,12 +106,31 @@ export type IEventTargetLike = HTMLElement | IEventEmitterLike | IEventEmitter<u
|
|
|
99
106
|
* @returns {Function} - Returns function allowing to easily add a callback to
|
|
100
107
|
* be triggered when that event is emitted on a given event target.
|
|
101
108
|
*/
|
|
109
|
+
|
|
110
|
+
function createCompatibleEventListener(
|
|
111
|
+
eventNames: Array<"needkey" | "encrypted">,
|
|
112
|
+
prefixes?: string[],
|
|
113
|
+
): (
|
|
114
|
+
element: IEventTargetLike,
|
|
115
|
+
listener: (event: ICustomMediaEncryptedEvent) => void,
|
|
116
|
+
cancelSignal: CancellationSignal,
|
|
117
|
+
) => void;
|
|
118
|
+
|
|
102
119
|
function createCompatibleEventListener(
|
|
103
120
|
eventNames: string[],
|
|
104
121
|
prefixes?: string[],
|
|
105
122
|
): (
|
|
106
123
|
element: IEventTargetLike,
|
|
107
|
-
listener: (event?:
|
|
124
|
+
listener: (event?: Event) => void,
|
|
125
|
+
cancelSignal: CancellationSignal,
|
|
126
|
+
) => void;
|
|
127
|
+
|
|
128
|
+
function createCompatibleEventListener(
|
|
129
|
+
eventNames: string[] | Array<"needkey" | "encrypted">,
|
|
130
|
+
prefixes?: string[],
|
|
131
|
+
): (
|
|
132
|
+
element: IEventTargetLike,
|
|
133
|
+
listener: (event?: Event | MediaEncryptedEvent) => void,
|
|
108
134
|
cancelSignal: CancellationSignal,
|
|
109
135
|
) => void {
|
|
110
136
|
let mem: string | undefined;
|
|
@@ -112,13 +138,12 @@ function createCompatibleEventListener(
|
|
|
112
138
|
|
|
113
139
|
return (
|
|
114
140
|
element: IEventTargetLike,
|
|
115
|
-
listener: (event?:
|
|
141
|
+
listener: (event?: Event) => void,
|
|
116
142
|
cancelSignal: CancellationSignal,
|
|
117
143
|
) => {
|
|
118
144
|
if (cancelSignal.isCancelled()) {
|
|
119
145
|
return;
|
|
120
146
|
}
|
|
121
|
-
|
|
122
147
|
// if the element is a HTMLElement we can detect
|
|
123
148
|
// the supported event, and memoize it in `mem`
|
|
124
149
|
if (typeof HTMLElement !== "undefined" && element instanceof HTMLElement) {
|
|
@@ -377,8 +377,8 @@ export default class CmcdDataBuilder {
|
|
|
377
377
|
}
|
|
378
378
|
};
|
|
379
379
|
|
|
380
|
-
addNumberProperty("br", "object");
|
|
381
380
|
addNumberProperty("bl", "request");
|
|
381
|
+
addNumberProperty("br", "object");
|
|
382
382
|
addBooleanProperty("bs", "status");
|
|
383
383
|
addStringProperty("cid", "session");
|
|
384
384
|
addNumberProperty("d", "object");
|
|
@@ -744,6 +744,7 @@ function loadOrReloadPreparedContent(
|
|
|
744
744
|
}
|
|
745
745
|
}
|
|
746
746
|
|
|
747
|
+
contentTimeBoundariesObserver.onPeriodCleared(value.type, value.period);
|
|
747
748
|
preparedContent.trackChoiceSetter.removeTrackSetter(value.period.id, value.type);
|
|
748
749
|
sendMessage({
|
|
749
750
|
type: WorkerMessageType.PeriodStreamCleared,
|
|
@@ -1349,11 +1349,14 @@ function prettyPrintInventory(inventory: IBufferedChunk[]): string {
|
|
|
1349
1349
|
if (encounteredPeriod === undefined) {
|
|
1350
1350
|
currentLetter = generateNewLetter(chunk.infos);
|
|
1351
1351
|
encounteredReps[periodId] = { [representationId]: currentLetter };
|
|
1352
|
-
} else if (encounteredPeriod[representationId] === undefined) {
|
|
1353
|
-
currentLetter = generateNewLetter(chunk.infos);
|
|
1354
|
-
encounteredPeriod[representationId] = currentLetter;
|
|
1355
1352
|
} else {
|
|
1356
|
-
|
|
1353
|
+
const previousLetter = encounteredPeriod[representationId];
|
|
1354
|
+
if (previousLetter === undefined) {
|
|
1355
|
+
currentLetter = generateNewLetter(chunk.infos);
|
|
1356
|
+
encounteredPeriod[representationId] = currentLetter;
|
|
1357
|
+
} else {
|
|
1358
|
+
currentLetter = previousLetter;
|
|
1359
|
+
}
|
|
1357
1360
|
}
|
|
1358
1361
|
|
|
1359
1362
|
if (lastChunk === null) {
|
|
@@ -409,7 +409,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
409
409
|
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1194624
|
|
410
410
|
videoElement.preload = "auto";
|
|
411
411
|
|
|
412
|
-
this.version = /* PLAYER_VERSION */ "4.2.0-dev.
|
|
412
|
+
this.version = /* PLAYER_VERSION */ "4.2.0-dev.2024090300";
|
|
413
413
|
this.log = log;
|
|
414
414
|
this.state = "STOPPED";
|
|
415
415
|
this.videoElement = videoElement;
|
|
@@ -1889,10 +1889,18 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1889
1889
|
/**
|
|
1890
1890
|
* Returns every available audio tracks for a given Period - or the current
|
|
1891
1891
|
* one if no `periodId` is given.
|
|
1892
|
-
* @param {string|undefined} [
|
|
1892
|
+
* @param {string|Object|undefined} [arg]
|
|
1893
1893
|
* @returns {Array.<Object>}
|
|
1894
1894
|
*/
|
|
1895
|
-
getAvailableAudioTracks(
|
|
1895
|
+
getAvailableAudioTracks(
|
|
1896
|
+
arg?:
|
|
1897
|
+
| string
|
|
1898
|
+
| undefined
|
|
1899
|
+
| {
|
|
1900
|
+
periodId: string;
|
|
1901
|
+
filterPlayableRepresentations: boolean;
|
|
1902
|
+
},
|
|
1903
|
+
): IAvailableAudioTrack[] {
|
|
1896
1904
|
if (this._priv_contentInfos === null) {
|
|
1897
1905
|
return [];
|
|
1898
1906
|
}
|
|
@@ -1900,10 +1908,20 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1900
1908
|
if (isDirectFile) {
|
|
1901
1909
|
return mediaElementTracksStore?.getAvailableAudioTracks() ?? [];
|
|
1902
1910
|
}
|
|
1911
|
+
|
|
1912
|
+
let periodId: string | undefined;
|
|
1913
|
+
let filterPlayableRepresentations: boolean;
|
|
1914
|
+
if (typeof arg === "string") {
|
|
1915
|
+
periodId = arg;
|
|
1916
|
+
} else {
|
|
1917
|
+
periodId = arg?.periodId;
|
|
1918
|
+
filterPlayableRepresentations = arg?.filterPlayableRepresentations ?? true;
|
|
1919
|
+
}
|
|
1903
1920
|
return this._priv_callTracksStoreGetterSetter(
|
|
1904
1921
|
periodId,
|
|
1905
1922
|
[],
|
|
1906
|
-
(tcm, periodRef) =>
|
|
1923
|
+
(tcm, periodRef) =>
|
|
1924
|
+
tcm.getAvailableAudioTracks(periodRef, filterPlayableRepresentations) ?? [],
|
|
1907
1925
|
);
|
|
1908
1926
|
}
|
|
1909
1927
|
|
|
@@ -1930,10 +1948,18 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1930
1948
|
|
|
1931
1949
|
/**
|
|
1932
1950
|
* Returns every available video tracks for the current Period.
|
|
1933
|
-
* @param {string|undefined} [
|
|
1951
|
+
* @param {string|Object|undefined} [arg]
|
|
1934
1952
|
* @returns {Array.<Object>}
|
|
1935
1953
|
*/
|
|
1936
|
-
getAvailableVideoTracks(
|
|
1954
|
+
getAvailableVideoTracks(
|
|
1955
|
+
arg?:
|
|
1956
|
+
| string
|
|
1957
|
+
| undefined
|
|
1958
|
+
| {
|
|
1959
|
+
periodId: string;
|
|
1960
|
+
filterPlayableRepresentations: boolean;
|
|
1961
|
+
},
|
|
1962
|
+
): IAvailableVideoTrack[] {
|
|
1937
1963
|
if (this._priv_contentInfos === null) {
|
|
1938
1964
|
return [];
|
|
1939
1965
|
}
|
|
@@ -1941,19 +1967,37 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1941
1967
|
if (isDirectFile) {
|
|
1942
1968
|
return mediaElementTracksStore?.getAvailableVideoTracks() ?? [];
|
|
1943
1969
|
}
|
|
1970
|
+
|
|
1971
|
+
let periodId: string | undefined;
|
|
1972
|
+
let filterPlayableRepresentations: boolean;
|
|
1973
|
+
if (typeof arg === "string") {
|
|
1974
|
+
periodId = arg;
|
|
1975
|
+
} else {
|
|
1976
|
+
periodId = arg?.periodId;
|
|
1977
|
+
filterPlayableRepresentations = arg?.filterPlayableRepresentations ?? true;
|
|
1978
|
+
}
|
|
1944
1979
|
return this._priv_callTracksStoreGetterSetter(
|
|
1945
1980
|
periodId,
|
|
1946
1981
|
[],
|
|
1947
|
-
(tcm, periodRef) =>
|
|
1982
|
+
(tcm, periodRef) =>
|
|
1983
|
+
tcm.getAvailableVideoTracks(periodRef, filterPlayableRepresentations) ?? [],
|
|
1948
1984
|
);
|
|
1949
1985
|
}
|
|
1950
1986
|
|
|
1951
1987
|
/**
|
|
1952
1988
|
* Returns currently chosen audio language for the current Period.
|
|
1953
|
-
* @param {string|undefined} [
|
|
1989
|
+
* @param {string|Object|undefined} [arg]
|
|
1954
1990
|
* @returns {Object|null|undefined}
|
|
1955
1991
|
*/
|
|
1956
|
-
getAudioTrack(
|
|
1992
|
+
getAudioTrack(
|
|
1993
|
+
arg?:
|
|
1994
|
+
| string
|
|
1995
|
+
| undefined
|
|
1996
|
+
| {
|
|
1997
|
+
periodId: string;
|
|
1998
|
+
filterPlayableRepresentations: boolean;
|
|
1999
|
+
},
|
|
2000
|
+
): IAudioTrack | null | undefined {
|
|
1957
2001
|
if (this._priv_contentInfos === null) {
|
|
1958
2002
|
return undefined;
|
|
1959
2003
|
}
|
|
@@ -1964,8 +2008,17 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1964
2008
|
}
|
|
1965
2009
|
return mediaElementTracksStore.getChosenAudioTrack();
|
|
1966
2010
|
}
|
|
2011
|
+
|
|
2012
|
+
let periodId: string | undefined;
|
|
2013
|
+
let filterPlayableRepresentations: boolean;
|
|
2014
|
+
if (typeof arg === "string") {
|
|
2015
|
+
periodId = arg;
|
|
2016
|
+
} else {
|
|
2017
|
+
periodId = arg?.periodId;
|
|
2018
|
+
filterPlayableRepresentations = arg?.filterPlayableRepresentations ?? true;
|
|
2019
|
+
}
|
|
1967
2020
|
return this._priv_callTracksStoreGetterSetter(periodId, undefined, (tcm, periodRef) =>
|
|
1968
|
-
tcm.getChosenAudioTrack(periodRef),
|
|
2021
|
+
tcm.getChosenAudioTrack(periodRef, filterPlayableRepresentations),
|
|
1969
2022
|
);
|
|
1970
2023
|
}
|
|
1971
2024
|
|
|
@@ -1992,10 +2045,18 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
1992
2045
|
|
|
1993
2046
|
/**
|
|
1994
2047
|
* Returns currently chosen video track for the current Period.
|
|
1995
|
-
* @param {string|undefined} [
|
|
2048
|
+
* @param {string|Object|undefined} [arg]
|
|
1996
2049
|
* @returns {Object|null|undefined}
|
|
1997
2050
|
*/
|
|
1998
|
-
getVideoTrack(
|
|
2051
|
+
getVideoTrack(
|
|
2052
|
+
arg?:
|
|
2053
|
+
| string
|
|
2054
|
+
| undefined
|
|
2055
|
+
| {
|
|
2056
|
+
periodId: string;
|
|
2057
|
+
filterPlayableRepresentations: boolean;
|
|
2058
|
+
},
|
|
2059
|
+
): IVideoTrack | null | undefined {
|
|
1999
2060
|
if (this._priv_contentInfos === null) {
|
|
2000
2061
|
return undefined;
|
|
2001
2062
|
}
|
|
@@ -2006,8 +2067,17 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2006
2067
|
}
|
|
2007
2068
|
return mediaElementTracksStore.getChosenVideoTrack();
|
|
2008
2069
|
}
|
|
2070
|
+
|
|
2071
|
+
let periodId: string | undefined;
|
|
2072
|
+
let filterPlayableRepresentations: boolean;
|
|
2073
|
+
if (typeof arg === "string") {
|
|
2074
|
+
periodId = arg;
|
|
2075
|
+
} else {
|
|
2076
|
+
periodId = arg?.periodId;
|
|
2077
|
+
filterPlayableRepresentations = arg?.filterPlayableRepresentations ?? true;
|
|
2078
|
+
}
|
|
2009
2079
|
return this._priv_callTracksStoreGetterSetter(periodId, undefined, (tcm, periodRef) =>
|
|
2010
|
-
tcm.getChosenVideoTrack(periodRef),
|
|
2080
|
+
tcm.getChosenVideoTrack(periodRef, filterPlayableRepresentations),
|
|
2011
2081
|
);
|
|
2012
2082
|
}
|
|
2013
2083
|
|
|
@@ -2612,10 +2682,12 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2612
2682
|
}
|
|
2613
2683
|
switch (elt.adaptation.type) {
|
|
2614
2684
|
case "audio":
|
|
2615
|
-
isCurrent =
|
|
2685
|
+
isCurrent =
|
|
2686
|
+
tStore.getChosenAudioTrack(periodRef, false)?.id === elt.adaptation.id;
|
|
2616
2687
|
break;
|
|
2617
2688
|
case "video":
|
|
2618
|
-
isCurrent =
|
|
2689
|
+
isCurrent =
|
|
2690
|
+
tStore.getChosenVideoTrack(periodRef, false)?.id === elt.adaptation.id;
|
|
2619
2691
|
break;
|
|
2620
2692
|
case "text":
|
|
2621
2693
|
isCurrent = tStore.getChosenTextTrack(periodRef)?.id === elt.adaptation.id;
|
|
@@ -2690,11 +2762,11 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2690
2762
|
if (!isNullOrUndefined(tracksStore)) {
|
|
2691
2763
|
const periodRef = tracksStore.getPeriodObjectFromPeriod(period);
|
|
2692
2764
|
if (periodRef) {
|
|
2693
|
-
const audioTrack = tracksStore.getChosenAudioTrack(periodRef);
|
|
2765
|
+
const audioTrack = tracksStore.getChosenAudioTrack(periodRef, true);
|
|
2694
2766
|
this._priv_triggerEventIfNotStopped("audioTrackChange", audioTrack, cancelSignal);
|
|
2695
2767
|
const textTrack = tracksStore.getChosenTextTrack(periodRef);
|
|
2696
2768
|
this._priv_triggerEventIfNotStopped("textTrackChange", textTrack, cancelSignal);
|
|
2697
|
-
const videoTrack = tracksStore.getChosenVideoTrack(periodRef);
|
|
2769
|
+
const videoTrack = tracksStore.getChosenVideoTrack(periodRef, true);
|
|
2698
2770
|
this._priv_triggerEventIfNotStopped("videoTrackChange", videoTrack, cancelSignal);
|
|
2699
2771
|
}
|
|
2700
2772
|
} else {
|
|
@@ -2854,7 +2926,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2854
2926
|
}
|
|
2855
2927
|
switch (type) {
|
|
2856
2928
|
case "audio":
|
|
2857
|
-
const audioTrack = tracksStore.getChosenAudioTrack(periodRef);
|
|
2929
|
+
const audioTrack = tracksStore.getChosenAudioTrack(periodRef, true);
|
|
2858
2930
|
this._priv_triggerEventIfNotStopped(
|
|
2859
2931
|
"audioTrackChange",
|
|
2860
2932
|
audioTrack,
|
|
@@ -2866,7 +2938,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2866
2938
|
this._priv_triggerEventIfNotStopped("textTrackChange", textTrack, cancelSignal);
|
|
2867
2939
|
break;
|
|
2868
2940
|
case "video":
|
|
2869
|
-
const videoTrack = tracksStore.getChosenVideoTrack(periodRef);
|
|
2941
|
+
const videoTrack = tracksStore.getChosenVideoTrack(periodRef, true);
|
|
2870
2942
|
this._priv_triggerEventIfNotStopped(
|
|
2871
2943
|
"videoTrackChange",
|
|
2872
2944
|
videoTrack,
|
|
@@ -3178,7 +3250,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
3178
3250
|
}
|
|
3179
3251
|
switch (trackType) {
|
|
3180
3252
|
case "video":
|
|
3181
|
-
const videoTracks = tracksStore.getAvailableVideoTracks(periodRef);
|
|
3253
|
+
const videoTracks = tracksStore.getAvailableVideoTracks(periodRef, true);
|
|
3182
3254
|
this._priv_triggerEventIfNotStopped(
|
|
3183
3255
|
"availableVideoTracksChange",
|
|
3184
3256
|
videoTracks ?? [],
|
|
@@ -3186,7 +3258,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
3186
3258
|
);
|
|
3187
3259
|
break;
|
|
3188
3260
|
case "audio":
|
|
3189
|
-
const audioTracks = tracksStore.getAvailableAudioTracks(periodRef);
|
|
3261
|
+
const audioTracks = tracksStore.getAvailableAudioTracks(periodRef, true);
|
|
3190
3262
|
this._priv_triggerEventIfNotStopped(
|
|
3191
3263
|
"availableAudioTracksChange",
|
|
3192
3264
|
audioTracks ?? [],
|
|
@@ -3235,7 +3307,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
3235
3307
|
}
|
|
3236
3308
|
}
|
|
3237
3309
|
}
|
|
3238
|
-
Player.version = /* PLAYER_VERSION */ "4.2.0-dev.
|
|
3310
|
+
Player.version = /* PLAYER_VERSION */ "4.2.0-dev.2024090300";
|
|
3239
3311
|
|
|
3240
3312
|
/** Every events sent by the RxPlayer's public API. */
|
|
3241
3313
|
interface IPublicAPIEvent {
|
|
@@ -3244,8 +3316,8 @@ interface IPublicAPIEvent {
|
|
|
3244
3316
|
audioTrackChange: IAudioTrack | null;
|
|
3245
3317
|
textTrackChange: ITextTrack | null;
|
|
3246
3318
|
videoTrackChange: IVideoTrack | null;
|
|
3247
|
-
audioRepresentationChange:
|
|
3248
|
-
videoRepresentationChange:
|
|
3319
|
+
audioRepresentationChange: IAudioRepresentation | null;
|
|
3320
|
+
videoRepresentationChange: IVideoRepresentation | null;
|
|
3249
3321
|
volumeChange: {
|
|
3250
3322
|
volume: number;
|
|
3251
3323
|
muted: boolean;
|