rx-player 3.30.0-dev.2023020100 → 3.30.0-dev.2023030200
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/.eslintrc.js +8 -0
- package/CHANGELOG.md +5 -1
- package/VERSION +1 -1
- package/dist/_esm5.processed/compat/browser_detection.d.ts +23 -12
- package/dist/_esm5.processed/compat/browser_detection.js +80 -38
- package/dist/_esm5.processed/compat/can_reuse_media_keys.js +2 -2
- package/dist/_esm5.processed/compat/eme/close_session.js +2 -2
- package/dist/_esm5.processed/compat/event_listeners.js +1 -1
- package/dist/_esm5.processed/config.d.ts +2 -0
- package/dist/_esm5.processed/core/adaptive/adaptive_representation_selector.js +4 -2
- package/dist/_esm5.processed/core/api/debug/buffer_graph.d.ts +28 -0
- package/dist/_esm5.processed/core/api/debug/buffer_graph.js +175 -0
- package/dist/_esm5.processed/core/api/debug/buffer_size_graph.d.ts +10 -0
- package/dist/_esm5.processed/core/api/debug/buffer_size_graph.js +104 -0
- package/dist/_esm5.processed/core/api/debug/constants.d.ts +2 -0
- package/dist/_esm5.processed/core/api/debug/constants.js +2 -0
- package/dist/_esm5.processed/core/api/debug/index.d.ts +2 -0
- package/dist/_esm5.processed/core/api/debug/index.js +2 -0
- package/dist/_esm5.processed/core/api/debug/modules/general_info.d.ts +3 -0
- package/dist/_esm5.processed/core/api/debug/modules/general_info.js +199 -0
- package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_content.d.ts +4 -0
- package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_content.js +121 -0
- package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_size.d.ts +3 -0
- package/dist/_esm5.processed/core/api/debug/modules/segment_buffer_size.js +35 -0
- package/dist/_esm5.processed/core/api/debug/render.d.ts +3 -0
- package/dist/_esm5.processed/core/api/debug/render.js +32 -0
- package/dist/_esm5.processed/core/api/debug/utils.d.ts +39 -0
- package/dist/_esm5.processed/core/api/debug/utils.js +57 -0
- package/dist/_esm5.processed/core/api/playback_observer.js +3 -2
- package/dist/_esm5.processed/core/api/public_api.d.ts +3 -0
- package/dist/_esm5.processed/core/api/public_api.js +25 -14
- package/dist/_esm5.processed/core/api/utils.js +3 -3
- package/dist/_esm5.processed/core/decrypt/__tests__/__global__/utils.d.ts +32 -13
- package/dist/_esm5.processed/core/decrypt/__tests__/__global__/utils.js +28 -7
- package/dist/_esm5.processed/core/decrypt/attach_media_keys.js +1 -1
- package/dist/_esm5.processed/core/decrypt/content_decryptor.js +1 -1
- package/dist/_esm5.processed/core/decrypt/find_key_system.js +33 -24
- package/dist/_esm5.processed/core/decrypt/session_events_listener.js +54 -50
- package/dist/_esm5.processed/core/decrypt/utils/check_key_statuses.js +4 -0
- package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.d.ts +17 -8
- package/dist/_esm5.processed/core/fetchers/cdn_prioritizer.js +10 -6
- package/dist/_esm5.processed/core/fetchers/manifest/manifest_fetcher.js +5 -4
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.d.ts +22 -5
- package/dist/_esm5.processed/core/fetchers/segment/segment_fetcher.js +37 -21
- package/dist/_esm5.processed/core/fetchers/segment/task_prioritizer.js +21 -23
- package/dist/_esm5.processed/core/fetchers/utils/schedule_request.js +17 -7
- package/dist/_esm5.processed/core/init/directfile_content_initializer.js +1 -1
- package/dist/_esm5.processed/core/init/media_source_content_initializer.js +27 -31
- package/dist/_esm5.processed/core/init/utils/content_time_boundaries_observer.js +2 -2
- package/dist/_esm5.processed/core/init/utils/create_media_source.js +3 -12
- package/dist/_esm5.processed/core/init/utils/end_of_stream.js +6 -3
- package/dist/_esm5.processed/core/init/utils/get_loaded_reference.js +2 -1
- package/dist/_esm5.processed/core/init/utils/initial_seek_and_play.js +9 -5
- package/dist/_esm5.processed/core/init/utils/initialize_content_decryption.js +2 -1
- package/dist/_esm5.processed/core/init/utils/media_duration_updater.js +23 -19
- package/dist/_esm5.processed/core/init/utils/rebuffering_controller.js +1 -1
- package/dist/_esm5.processed/core/init/utils/stream_events_emitter/stream_events_emitter.js +6 -4
- package/dist/_esm5.processed/core/init/utils/throw_on_media_error.js +1 -1
- package/dist/_esm5.processed/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.js +7 -10
- package/dist/_esm5.processed/core/segment_buffers/implementations/text/html/html_text_segment_buffer.js +4 -2
- package/dist/_esm5.processed/core/segment_buffers/segment_buffers_store.js +13 -9
- package/dist/_esm5.processed/core/stream/adaptation/adaptation_stream.js +25 -16
- package/dist/_esm5.processed/core/stream/orchestrator/stream_orchestrator.js +26 -12
- package/dist/_esm5.processed/core/stream/period/period_stream.js +11 -10
- package/dist/_esm5.processed/core/stream/representation/representation_stream.js +15 -15
- package/dist/_esm5.processed/core/stream/representation/utils/append_segment_to_buffer.js +1 -1
- package/dist/_esm5.processed/core/stream/representation/utils/downloading_queue.js +16 -6
- package/dist/_esm5.processed/default_config.d.ts +16 -0
- package/dist/_esm5.processed/default_config.js +19 -0
- package/dist/_esm5.processed/experimental/features/debug_element.d.ts +8 -0
- package/dist/_esm5.processed/experimental/features/debug_element.js +10 -0
- 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/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.js +7 -4
- package/dist/_esm5.processed/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.js +8 -4
- package/dist/_esm5.processed/features/features_object.js +1 -0
- package/dist/_esm5.processed/features/initialize_features.js +13 -10
- package/dist/_esm5.processed/features/types.d.ts +3 -0
- package/dist/_esm5.processed/manifest/adaptation.js +4 -0
- package/dist/_esm5.processed/manifest/manifest.js +2 -0
- package/dist/_esm5.processed/manifest/representation.js +11 -4
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_adaptation_sets.js +105 -137
- package/dist/_esm5.processed/parsers/manifest/dash/common/parse_representations.js +25 -5
- package/dist/_esm5.processed/public_types.d.ts +1 -0
- package/dist/_esm5.processed/transports/dash/add_segment_integrity_checks_to_loader.js +15 -11
- package/dist/_esm5.processed/transports/dash/low_latency_segment_loader.js +2 -2
- package/dist/_esm5.processed/transports/dash/manifest_parser.js +1 -1
- package/dist/_esm5.processed/transports/dash/segment_loader.js +4 -4
- package/dist/_esm5.processed/transports/local/segment_loader.js +13 -26
- package/dist/_esm5.processed/transports/smooth/segment_loader.js +4 -4
- package/dist/_esm5.processed/transports/utils/call_custom_manifest_loader.js +3 -3
- package/dist/_esm5.processed/utils/cancellable_sleep.js +4 -10
- package/dist/_esm5.processed/utils/create_cancellable_promise.d.ts +26 -0
- package/dist/_esm5.processed/utils/create_cancellable_promise.js +52 -0
- package/dist/_esm5.processed/utils/reference.js +6 -0
- package/dist/_esm5.processed/utils/request/xhr.js +1 -1
- package/dist/_esm5.processed/utils/task_canceller.d.ts +34 -15
- package/dist/_esm5.processed/utils/task_canceller.js +55 -22
- package/dist/rx-player.js +880 -677
- package/dist/rx-player.min.js +1 -1
- package/jest.config.js +1 -0
- package/package.json +19 -18
- package/scripts/build/constants.d.ts +1 -0
- package/scripts/report_build_sizes +4 -0
- package/sonar-project.properties +1 -1
- package/src/compat/browser_detection.ts +99 -52
- package/src/compat/can_reuse_media_keys.ts +5 -2
- package/src/compat/eme/close_session.ts +2 -2
- package/src/compat/event_listeners.ts +1 -1
- package/src/core/adaptive/adaptive_representation_selector.ts +4 -2
- package/src/core/api/debug/buffer_graph.ts +247 -0
- package/src/core/api/debug/buffer_size_graph.ts +130 -0
- package/src/core/api/debug/constants.ts +2 -0
- package/src/core/api/debug/index.ts +3 -0
- package/src/core/api/debug/modules/general_info.ts +204 -0
- package/src/core/api/debug/modules/segment_buffer_content.ts +155 -0
- package/src/core/api/debug/modules/segment_buffer_size.ts +48 -0
- package/src/core/api/debug/render.ts +40 -0
- package/src/core/api/debug/utils.ts +103 -0
- package/src/core/api/playback_observer.ts +4 -2
- package/src/core/api/public_api.ts +28 -14
- package/src/core/api/utils.ts +3 -3
- package/src/core/decrypt/__tests__/__global__/utils.ts +61 -40
- package/src/core/decrypt/attach_media_keys.ts +1 -1
- package/src/core/decrypt/content_decryptor.ts +1 -1
- package/src/core/decrypt/find_key_system.ts +36 -35
- package/src/core/decrypt/session_events_listener.ts +57 -56
- package/src/core/decrypt/utils/check_key_statuses.ts +6 -0
- package/src/core/fetchers/cdn_prioritizer.ts +18 -9
- package/src/core/fetchers/manifest/manifest_fetcher.ts +5 -4
- package/src/core/fetchers/segment/segment_fetcher.ts +36 -14
- package/src/core/fetchers/segment/task_prioritizer.ts +25 -30
- package/src/core/fetchers/utils/schedule_request.ts +18 -7
- package/src/core/init/directfile_content_initializer.ts +1 -1
- package/src/core/init/media_source_content_initializer.ts +37 -41
- package/src/core/init/utils/content_time_boundaries_observer.ts +2 -2
- package/src/core/init/utils/create_media_source.ts +4 -16
- package/src/core/init/utils/end_of_stream.ts +6 -3
- package/src/core/init/utils/get_loaded_reference.ts +2 -1
- package/src/core/init/utils/initial_seek_and_play.ts +9 -5
- package/src/core/init/utils/initialize_content_decryption.ts +2 -1
- package/src/core/init/utils/media_duration_updater.ts +25 -20
- package/src/core/init/utils/rebuffering_controller.ts +1 -1
- package/src/core/init/utils/stream_events_emitter/stream_events_emitter.ts +6 -4
- package/src/core/init/utils/throw_on_media_error.ts +1 -1
- package/src/core/segment_buffers/implementations/audio_video/audio_video_segment_buffer.ts +7 -11
- package/src/core/segment_buffers/implementations/text/html/html_text_segment_buffer.ts +4 -2
- package/src/core/segment_buffers/segment_buffers_store.ts +16 -13
- package/src/core/stream/adaptation/adaptation_stream.ts +28 -19
- package/src/core/stream/orchestrator/stream_orchestrator.ts +26 -12
- package/src/core/stream/period/period_stream.ts +11 -10
- package/src/core/stream/representation/representation_stream.ts +15 -15
- package/src/core/stream/representation/utils/append_segment_to_buffer.ts +1 -1
- package/src/core/stream/representation/utils/downloading_queue.ts +16 -4
- package/src/default_config.ts +30 -9
- package/src/experimental/features/__tests__/debug_element.test.ts +26 -0
- package/src/experimental/features/debug_element.ts +13 -0
- package/src/experimental/features/index.ts +1 -0
- package/src/experimental/tools/VideoThumbnailLoader/prepare_source_buffer.ts +7 -4
- package/src/experimental/tools/VideoThumbnailLoader/video_thumbnail_loader.ts +8 -4
- package/src/features/__tests__/initialize_features.test.ts +11 -0
- package/src/features/features_object.ts +1 -0
- package/src/features/initialize_features.ts +15 -10
- package/src/features/types.ts +9 -0
- package/src/manifest/adaptation.ts +7 -0
- package/src/manifest/manifest.ts +4 -0
- package/src/manifest/representation.ts +10 -4
- package/src/parsers/manifest/dash/common/parse_adaptation_sets.ts +116 -151
- package/src/parsers/manifest/dash/common/parse_representations.ts +21 -4
- package/src/public_types.ts +1 -0
- package/src/transports/dash/add_segment_integrity_checks_to_loader.ts +31 -22
- package/src/transports/dash/low_latency_segment_loader.ts +2 -2
- package/src/transports/dash/manifest_parser.ts +1 -1
- package/src/transports/dash/segment_loader.ts +4 -4
- package/src/transports/local/segment_loader.ts +14 -30
- package/src/transports/smooth/segment_loader.ts +4 -4
- package/src/transports/utils/call_custom_manifest_loader.ts +3 -3
- package/src/typings/globals.d.ts +2 -0
- package/src/utils/cancellable_sleep.ts +5 -14
- package/src/utils/create_cancellable_promise.ts +69 -0
- package/src/utils/reference.ts +6 -0
- package/src/utils/request/xhr.ts +1 -1
- package/src/utils/task_canceller.ts +63 -34
|
@@ -217,7 +217,7 @@ export default class PlaybackObserver {
|
|
|
217
217
|
options? : { includeLastObservation? : boolean | undefined;
|
|
218
218
|
clearSignal? : CancellationSignal | undefined; }
|
|
219
219
|
) {
|
|
220
|
-
if (this._canceller.isUsed || options?.clearSignal?.isCancelled === true) {
|
|
220
|
+
if (this._canceller.isUsed() || options?.clearSignal?.isCancelled() === true) {
|
|
221
221
|
return noop;
|
|
222
222
|
}
|
|
223
223
|
this._observationRef.onUpdate(cb, {
|
|
@@ -971,7 +971,9 @@ function generateReadOnlyObserver<TSource, TDest>(
|
|
|
971
971
|
options? : { includeLastObservation? : boolean | undefined;
|
|
972
972
|
clearSignal? : CancellationSignal | undefined; }
|
|
973
973
|
) : void {
|
|
974
|
-
if (cancellationSignal.isCancelled ||
|
|
974
|
+
if (cancellationSignal.isCancelled() ||
|
|
975
|
+
options?.clearSignal?.isCancelled() === true)
|
|
976
|
+
{
|
|
975
977
|
return ;
|
|
976
978
|
}
|
|
977
979
|
mappedRef.onUpdate(cb, {
|
|
@@ -364,7 +364,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
364
364
|
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=1194624
|
|
365
365
|
videoElement.preload = "auto";
|
|
366
366
|
|
|
367
|
-
this.version = /* PLAYER_VERSION */"3.30.0-dev.
|
|
367
|
+
this.version = /* PLAYER_VERSION */"3.30.0-dev.2023030200";
|
|
368
368
|
this.log = log;
|
|
369
369
|
this.state = "STOPPED";
|
|
370
370
|
this.videoElement = videoElement;
|
|
@@ -602,6 +602,21 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
602
602
|
this._priv_initializeContentPlayback(newOptions);
|
|
603
603
|
}
|
|
604
604
|
|
|
605
|
+
public createDebugElement(element : HTMLElement) : {
|
|
606
|
+
dispose() : void;
|
|
607
|
+
} {
|
|
608
|
+
if (features.createDebugElement === null) {
|
|
609
|
+
throw new Error("Feature `DEBUG_ELEMENT` not added to the RxPlayer");
|
|
610
|
+
}
|
|
611
|
+
const canceller = new TaskCanceller() ;
|
|
612
|
+
features.createDebugElement(element, this, canceller.signal);
|
|
613
|
+
return {
|
|
614
|
+
dispose() {
|
|
615
|
+
canceller.cancel();
|
|
616
|
+
},
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
|
|
605
620
|
/**
|
|
606
621
|
* From given options, initialize content playback.
|
|
607
622
|
* @param {Object} options
|
|
@@ -764,7 +779,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
764
779
|
defaultTextTrack,
|
|
765
780
|
currentContentCanceller.signal
|
|
766
781
|
);
|
|
767
|
-
if (currentContentCanceller.isUsed) {
|
|
782
|
+
if (currentContentCanceller.isUsed()) {
|
|
768
783
|
return;
|
|
769
784
|
}
|
|
770
785
|
initializer = new features.directfile.initDirectFile({ autoPlay,
|
|
@@ -943,7 +958,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
943
958
|
updateReloadingMetadata(newState);
|
|
944
959
|
this._priv_setPlayerState(newState);
|
|
945
960
|
|
|
946
|
-
if (currentContentCanceller.isUsed) {
|
|
961
|
+
if (currentContentCanceller.isUsed()) {
|
|
947
962
|
return;
|
|
948
963
|
}
|
|
949
964
|
|
|
@@ -953,9 +968,8 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
953
968
|
seekEventsCanceller = null;
|
|
954
969
|
}
|
|
955
970
|
} else if (isLoadedState(this.state)) {
|
|
956
|
-
seekEventsCanceller = new TaskCanceller(
|
|
957
|
-
|
|
958
|
-
});
|
|
971
|
+
seekEventsCanceller = new TaskCanceller();
|
|
972
|
+
seekEventsCanceller.linkToSignal(currentContentCanceller.signal);
|
|
959
973
|
emitSeekEvents(videoElement,
|
|
960
974
|
playbackObserver,
|
|
961
975
|
() => this.trigger("seeking", null),
|
|
@@ -966,7 +980,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
966
980
|
// Previous call could have performed all kind of side-effects, thus,
|
|
967
981
|
// we re-check the current state associated to the RxPlayer
|
|
968
982
|
if (this.state === PLAYER_STATES.ENDED && this._priv_stopAtEnd) {
|
|
969
|
-
|
|
983
|
+
this.stop();
|
|
970
984
|
}
|
|
971
985
|
}, { emitCurrentValue: true, clearSignal: currentContentCanceller.signal });
|
|
972
986
|
|
|
@@ -2468,20 +2482,20 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2468
2482
|
this._priv_triggerAvailableBitratesChangeEvent("availableAudioBitratesChange",
|
|
2469
2483
|
this.getAvailableAudioBitrates(),
|
|
2470
2484
|
cancelSignal);
|
|
2471
|
-
if (contentInfos.currentContentCanceller.isUsed) {
|
|
2485
|
+
if (contentInfos.currentContentCanceller.isUsed()) {
|
|
2472
2486
|
return;
|
|
2473
2487
|
}
|
|
2474
2488
|
this._priv_triggerAvailableBitratesChangeEvent("availableVideoBitratesChange",
|
|
2475
2489
|
this.getAvailableVideoBitrates(),
|
|
2476
2490
|
cancelSignal);
|
|
2477
|
-
if (contentInfos.currentContentCanceller.isUsed) {
|
|
2491
|
+
if (contentInfos.currentContentCanceller.isUsed()) {
|
|
2478
2492
|
return;
|
|
2479
2493
|
}
|
|
2480
2494
|
const audioBitrate = this._priv_getCurrentRepresentations()?.audio?.bitrate ?? -1;
|
|
2481
2495
|
this._priv_triggerCurrentBitrateChangeEvent("audioBitrateChange",
|
|
2482
2496
|
audioBitrate,
|
|
2483
2497
|
cancelSignal);
|
|
2484
|
-
if (contentInfos.currentContentCanceller.isUsed) {
|
|
2498
|
+
if (contentInfos.currentContentCanceller.isUsed()) {
|
|
2485
2499
|
return;
|
|
2486
2500
|
}
|
|
2487
2501
|
|
|
@@ -2833,7 +2847,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2833
2847
|
currentContentCancelSignal : CancellationSignal
|
|
2834
2848
|
) : void {
|
|
2835
2849
|
const prevVal = this._priv_contentEventsMemory[event];
|
|
2836
|
-
if (!currentContentCancelSignal.isCancelled &&
|
|
2850
|
+
if (!currentContentCancelSignal.isCancelled() &&
|
|
2837
2851
|
(prevVal === undefined || !areArraysOfNumbersEqual(newVal, prevVal)))
|
|
2838
2852
|
{
|
|
2839
2853
|
this._priv_contentEventsMemory[event] = newVal;
|
|
@@ -2853,7 +2867,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2853
2867
|
newVal : number,
|
|
2854
2868
|
currentContentCancelSignal : CancellationSignal
|
|
2855
2869
|
) : void {
|
|
2856
|
-
if (!currentContentCancelSignal.isCancelled &&
|
|
2870
|
+
if (!currentContentCancelSignal.isCancelled() &&
|
|
2857
2871
|
newVal !== this._priv_contentEventsMemory[event])
|
|
2858
2872
|
{
|
|
2859
2873
|
this._priv_contentEventsMemory[event] = newVal;
|
|
@@ -2886,7 +2900,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2886
2900
|
arg : IEventPayload<IPublicAPIEvent, TEventName>,
|
|
2887
2901
|
currentContentCancelSignal : CancellationSignal
|
|
2888
2902
|
) {
|
|
2889
|
-
if (!currentContentCancelSignal.isCancelled) {
|
|
2903
|
+
if (!currentContentCancelSignal.isCancelled()) {
|
|
2890
2904
|
this.trigger(evt, arg);
|
|
2891
2905
|
}
|
|
2892
2906
|
}
|
|
@@ -2971,7 +2985,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
|
|
|
2971
2985
|
return mediaElementTrackChoiceManager;
|
|
2972
2986
|
}
|
|
2973
2987
|
}
|
|
2974
|
-
Player.version = /* PLAYER_VERSION */"3.30.0-dev.
|
|
2988
|
+
Player.version = /* PLAYER_VERSION */"3.30.0-dev.2023030200";
|
|
2975
2989
|
|
|
2976
2990
|
/** Every events sent by the RxPlayer's public API. */
|
|
2977
2991
|
interface IPublicAPIEvent {
|
package/src/core/api/utils.ts
CHANGED
|
@@ -48,14 +48,14 @@ export function emitSeekEvents(
|
|
|
48
48
|
onSeeked: () => void,
|
|
49
49
|
cancelSignal : CancellationSignal
|
|
50
50
|
) : void {
|
|
51
|
-
if (cancelSignal.isCancelled || mediaElement === null) {
|
|
51
|
+
if (cancelSignal.isCancelled() || mediaElement === null) {
|
|
52
52
|
return ;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
let wasSeeking = playbackObserver.getReference().getValue().seeking;
|
|
56
56
|
if (wasSeeking) {
|
|
57
57
|
onSeeking();
|
|
58
|
-
if (cancelSignal.isCancelled) {
|
|
58
|
+
if (cancelSignal.isCancelled()) {
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
61
|
}
|
|
@@ -94,7 +94,7 @@ export function constructPlayerStateReference(
|
|
|
94
94
|
initializer.addEventListener("loaded", () => {
|
|
95
95
|
if (playerStateRef.getValue() === PLAYER_STATES.LOADING) {
|
|
96
96
|
playerStateRef.setValue(PLAYER_STATES.LOADED);
|
|
97
|
-
if (!cancelSignal.isCancelled) {
|
|
97
|
+
if (!cancelSignal.isCancelled()) {
|
|
98
98
|
const newState = getLoadedContentState(mediaElement, null);
|
|
99
99
|
if (newState !== PLAYER_STATES.PAUSED) {
|
|
100
100
|
playerStateRef.setValue(newState);
|
|
@@ -40,48 +40,68 @@ import {
|
|
|
40
40
|
import { CancellationSignal } from "../../../../utils/task_canceller";
|
|
41
41
|
|
|
42
42
|
/** Default MediaKeySystemAccess configuration used by the RxPlayer. */
|
|
43
|
-
export const defaultKSConfig = [
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}]
|
|
43
|
+
export const defaultKSConfig = [
|
|
44
|
+
{
|
|
45
|
+
audioCapabilities: [ { contentType: "audio/mp4;codecs=\"mp4a.40.2\"" },
|
|
46
|
+
{ contentType: "audio/webm;codecs=opus" } ],
|
|
47
|
+
distinctiveIdentifier: "optional" as const,
|
|
48
|
+
initDataTypes: ["cenc"] as const,
|
|
49
|
+
persistentState: "optional" as const,
|
|
50
|
+
sessionTypes: ["temporary"] as const,
|
|
51
|
+
videoCapabilities: [ { contentType: "video/mp4;codecs=\"avc1.4d401e\"" },
|
|
52
|
+
{ contentType: "video/mp4;codecs=\"avc1.42e01e\"" },
|
|
53
|
+
{ contentType: "video/webm;codecs=\"vp8\"" } ],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
audioCapabilities: undefined,
|
|
57
|
+
distinctiveIdentifier: "optional" as const,
|
|
58
|
+
initDataTypes: ["cenc"] as const,
|
|
59
|
+
persistentState: "optional" as const,
|
|
60
|
+
sessionTypes: ["temporary"] as const,
|
|
61
|
+
videoCapabilities: undefined,
|
|
62
|
+
},
|
|
63
|
+
];
|
|
54
64
|
|
|
55
65
|
/**
|
|
56
66
|
* Default "com.microsoft.playready.recommendation" MediaKeySystemAccess
|
|
57
67
|
* configuration used by the RxPlayer.
|
|
58
68
|
*/
|
|
59
|
-
export const defaultPRRecommendationKSConfig = [
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}]
|
|
69
|
+
export const defaultPRRecommendationKSConfig = [
|
|
70
|
+
{
|
|
71
|
+
audioCapabilities: [ { robustness: "3000",
|
|
72
|
+
contentType: "audio/mp4;codecs=\"mp4a.40.2\"" },
|
|
73
|
+
{ robustness: "3000",
|
|
74
|
+
contentType: "audio/webm;codecs=opus" },
|
|
75
|
+
{ robustness: "2000",
|
|
76
|
+
contentType: "audio/mp4;codecs=\"mp4a.40.2\"" },
|
|
77
|
+
{ robustness: "2000",
|
|
78
|
+
contentType: "audio/webm;codecs=opus" } ],
|
|
79
|
+
distinctiveIdentifier: "optional" as const,
|
|
80
|
+
initDataTypes: ["cenc"] as const,
|
|
81
|
+
persistentState: "optional" as const,
|
|
82
|
+
sessionTypes: ["temporary"] as const,
|
|
83
|
+
videoCapabilities: [ { robustness: "3000",
|
|
84
|
+
contentType: "video/mp4;codecs=\"avc1.4d401e\"" },
|
|
85
|
+
{ robustness: "3000",
|
|
86
|
+
contentType: "video/mp4;codecs=\"avc1.42e01e\"" },
|
|
87
|
+
{ robustness: "3000",
|
|
88
|
+
contentType: "video/webm;codecs=\"vp8\"" },
|
|
89
|
+
{ robustness: "2000",
|
|
90
|
+
contentType: "video/mp4;codecs=\"avc1.4d401e\"" },
|
|
91
|
+
{ robustness: "2000",
|
|
92
|
+
contentType: "video/mp4;codecs=\"avc1.42e01e\"" },
|
|
93
|
+
{ robustness: "2000",
|
|
94
|
+
contentType: "video/webm;codecs=\"vp8\"" } ],
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
audioCapabilities: undefined,
|
|
98
|
+
distinctiveIdentifier: "optional" as const,
|
|
99
|
+
initDataTypes: ["cenc"] as const,
|
|
100
|
+
persistentState: "optional" as const,
|
|
101
|
+
sessionTypes: ["temporary"] as const,
|
|
102
|
+
videoCapabilities: undefined,
|
|
103
|
+
},
|
|
104
|
+
];
|
|
85
105
|
|
|
86
106
|
/** Default Widevine MediaKeySystemAccess configuration used by the RxPlayer. */
|
|
87
107
|
export const defaultWidevineConfig = (() => {
|
|
@@ -104,9 +124,10 @@ export const defaultWidevineConfig = (() => {
|
|
|
104
124
|
{ contentType: "audio/webm;codecs=opus",
|
|
105
125
|
robustness } ];
|
|
106
126
|
});
|
|
107
|
-
return
|
|
108
|
-
|
|
109
|
-
|
|
127
|
+
return [
|
|
128
|
+
{ ...defaultKSConfig[0], audioCapabilities, videoCapabilities },
|
|
129
|
+
defaultKSConfig[1],
|
|
130
|
+
];
|
|
110
131
|
})();
|
|
111
132
|
|
|
112
133
|
/**
|
|
@@ -62,7 +62,7 @@ export default async function attachMediaKeys(
|
|
|
62
62
|
|
|
63
63
|
// If this task has been cancelled while we were closing previous sessions,
|
|
64
64
|
// stop now (and thus avoid setting the new media keys);
|
|
65
|
-
if (cancelSignal.isCancelled) {
|
|
65
|
+
if (cancelSignal.isCancelled()) {
|
|
66
66
|
throw cancelSignal.cancellationError;
|
|
67
67
|
}
|
|
68
68
|
|
|
@@ -727,7 +727,7 @@ export default class ContentDecryptor extends EventEmitter<IContentDecryptorEven
|
|
|
727
727
|
* formatted and sent in an "error" event.
|
|
728
728
|
*/
|
|
729
729
|
private _onFatalError(err : unknown) : void {
|
|
730
|
-
if (this._canceller.isUsed) {
|
|
730
|
+
if (this._canceller.isUsed()) {
|
|
731
731
|
return;
|
|
732
732
|
}
|
|
733
733
|
const formattedErr = err instanceof Error ?
|
|
@@ -155,7 +155,9 @@ function buildKeySystemConfigurations(
|
|
|
155
155
|
if (keySystem.distinctiveIdentifierRequired === true) {
|
|
156
156
|
distinctiveIdentifier = "required";
|
|
157
157
|
}
|
|
158
|
-
const {
|
|
158
|
+
const { EME_DEFAULT_AUDIO_CODECS,
|
|
159
|
+
EME_DEFAULT_VIDEO_CODECS,
|
|
160
|
+
EME_DEFAULT_WIDEVINE_ROBUSTNESSES,
|
|
159
161
|
EME_DEFAULT_PLAYREADY_ROBUSTNESSES } = config.getCurrent();
|
|
160
162
|
|
|
161
163
|
// Set robustness, in order of consideration:
|
|
@@ -206,42 +208,41 @@ function buildKeySystemConfigurations(
|
|
|
206
208
|
// https://www.w3.org/TR/encrypted-media/#get-supported-configuration-and-consent
|
|
207
209
|
|
|
208
210
|
const videoCapabilities: IMediaCapability[] =
|
|
209
|
-
flatMap(videoRobustnesses, (robustness) =>
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}));
|
|
211
|
+
flatMap(videoRobustnesses, (robustness) => {
|
|
212
|
+
return EME_DEFAULT_VIDEO_CODECS.map(contentType => {
|
|
213
|
+
return robustness === undefined ? { contentType } :
|
|
214
|
+
{ contentType, robustness };
|
|
215
|
+
});
|
|
216
|
+
});
|
|
216
217
|
|
|
217
218
|
const audioCapabilities: IMediaCapability[] =
|
|
218
|
-
flatMap(audioRobustnesses, (robustness) =>
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
219
|
+
flatMap(audioRobustnesses, (robustness) => {
|
|
220
|
+
return EME_DEFAULT_AUDIO_CODECS.map(contentType => {
|
|
221
|
+
return robustness === undefined ? { contentType } :
|
|
222
|
+
{ contentType, robustness };
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
const wantedMediaKeySystemConfiguration : MediaKeySystemConfiguration = {
|
|
227
|
+
initDataTypes: ["cenc"],
|
|
228
|
+
videoCapabilities,
|
|
229
|
+
audioCapabilities,
|
|
230
|
+
distinctiveIdentifier,
|
|
231
|
+
persistentState,
|
|
232
|
+
sessionTypes,
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
return [
|
|
236
|
+
wantedMediaKeySystemConfiguration,
|
|
237
|
+
|
|
238
|
+
// Some legacy implementations have issues with `audioCapabilities` and
|
|
239
|
+
// `videoCapabilities`, so we're including a supplementary
|
|
240
|
+
// `MediaKeySystemConfiguration` without those properties.
|
|
241
|
+
{ ...wantedMediaKeySystemConfiguration,
|
|
242
|
+
audioCapabilities: undefined ,
|
|
243
|
+
videoCapabilities: undefined,
|
|
244
|
+
} as unknown as MediaKeySystemConfiguration,
|
|
245
|
+
];
|
|
245
246
|
}
|
|
246
247
|
|
|
247
248
|
/**
|
|
@@ -58,13 +58,14 @@ export default function SessionEventsListener(
|
|
|
58
58
|
const { getLicenseConfig = {} } = keySystemOptions;
|
|
59
59
|
|
|
60
60
|
/** Allows to manually cancel everything the `SessionEventsListener` is doing. */
|
|
61
|
-
const manualCanceller = new TaskCanceller(
|
|
61
|
+
const manualCanceller = new TaskCanceller();
|
|
62
|
+
manualCanceller.linkToSignal(cancelSignal);
|
|
62
63
|
|
|
63
64
|
if (!isNullOrUndefined(session.closed)) {
|
|
64
65
|
session.closed
|
|
65
66
|
.then(() => manualCanceller.cancel())
|
|
66
67
|
.catch((err) => { // Should never happen
|
|
67
|
-
if (cancelSignal.isCancelled) {
|
|
68
|
+
if (cancelSignal.isCancelled()) {
|
|
68
69
|
return;
|
|
69
70
|
}
|
|
70
71
|
manualCanceller.cancel();
|
|
@@ -79,8 +80,8 @@ export default function SessionEventsListener(
|
|
|
79
80
|
|
|
80
81
|
onKeyStatusesChange(session, (keyStatusesEvent) => {
|
|
81
82
|
handleKeyStatusesChangeEvent(keyStatusesEvent as Event).catch(error => {
|
|
82
|
-
if (cancelSignal.isCancelled ||
|
|
83
|
-
(manualCanceller.isUsed && error instanceof CancellationSignal))
|
|
83
|
+
if (cancelSignal.isCancelled() ||
|
|
84
|
+
(manualCanceller.isUsed() && error instanceof CancellationSignal))
|
|
84
85
|
{
|
|
85
86
|
return;
|
|
86
87
|
}
|
|
@@ -104,7 +105,7 @@ export default function SessionEventsListener(
|
|
|
104
105
|
backoffOptions,
|
|
105
106
|
manualCanceller.signal)
|
|
106
107
|
.then((licenseObject) => {
|
|
107
|
-
if (manualCanceller.isUsed) {
|
|
108
|
+
if (manualCanceller.isUsed()) {
|
|
108
109
|
return Promise.resolve();
|
|
109
110
|
}
|
|
110
111
|
if (isNullOrUndefined(licenseObject)) {
|
|
@@ -114,7 +115,7 @@ export default function SessionEventsListener(
|
|
|
114
115
|
}
|
|
115
116
|
})
|
|
116
117
|
.catch((err : unknown) => {
|
|
117
|
-
if (manualCanceller.isUsed) {
|
|
118
|
+
if (manualCanceller.isUsed()) {
|
|
118
119
|
return;
|
|
119
120
|
}
|
|
120
121
|
manualCanceller.cancel();
|
|
@@ -133,6 +134,8 @@ export default function SessionEventsListener(
|
|
|
133
134
|
});
|
|
134
135
|
}, manualCanceller.signal);
|
|
135
136
|
|
|
137
|
+
checkAndHandleCurrentKeyStatuses();
|
|
138
|
+
return;
|
|
136
139
|
/**
|
|
137
140
|
* @param {Event} keyStatusesEvent
|
|
138
141
|
* @returns {Promise}
|
|
@@ -144,22 +147,22 @@ export default function SessionEventsListener(
|
|
|
144
147
|
|
|
145
148
|
await Promise.all([
|
|
146
149
|
runOnKeyStatusesChangeCallback(),
|
|
147
|
-
Promise.resolve(
|
|
150
|
+
Promise.resolve(checkAndHandleCurrentKeyStatuses()),
|
|
148
151
|
]);
|
|
149
152
|
|
|
150
153
|
async function runOnKeyStatusesChangeCallback() {
|
|
151
|
-
if (manualCanceller.isUsed) {
|
|
154
|
+
if (manualCanceller.isUsed()) {
|
|
152
155
|
return;
|
|
153
156
|
}
|
|
154
157
|
if (typeof keySystemOptions.onKeyStatusesChange === "function") {
|
|
155
158
|
let ret;
|
|
156
159
|
try {
|
|
157
160
|
ret = await keySystemOptions.onKeyStatusesChange(keyStatusesEvent, session);
|
|
158
|
-
if (manualCanceller.isUsed) {
|
|
161
|
+
if (manualCanceller.isUsed()) {
|
|
159
162
|
return;
|
|
160
163
|
}
|
|
161
164
|
} catch (error) {
|
|
162
|
-
if (cancelSignal.isCancelled) {
|
|
165
|
+
if (cancelSignal.isCancelled()) {
|
|
163
166
|
return;
|
|
164
167
|
}
|
|
165
168
|
const err = new EncryptedMediaError("KEY_STATUS_CHANGE_ERROR",
|
|
@@ -178,67 +181,65 @@ export default function SessionEventsListener(
|
|
|
178
181
|
}
|
|
179
182
|
}
|
|
180
183
|
}
|
|
184
|
+
}
|
|
181
185
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
186
|
+
/**
|
|
187
|
+
* Check current MediaKeyStatus for each key in the given MediaKeySession and:
|
|
188
|
+
* - throw if at least one status is a non-recoverable error
|
|
189
|
+
* - call warning callback for recoverable errors
|
|
190
|
+
* - call onKeyUpdate callback when the MediaKeyStatus of any key is updated
|
|
191
|
+
*/
|
|
192
|
+
function checkAndHandleCurrentKeyStatuses() : void {
|
|
193
|
+
if (manualCanceller.isUsed() || session.keyStatuses.size === 0) {
|
|
194
|
+
return ;
|
|
195
|
+
}
|
|
196
|
+
const { warning, blacklistedKeyIds, whitelistedKeyIds } =
|
|
197
|
+
checkKeyStatuses(session, keySystemOptions, keySystem);
|
|
198
|
+
if (warning !== undefined) {
|
|
199
|
+
callbacks.onWarning(warning);
|
|
200
|
+
if (manualCanceller.isUsed()) {
|
|
201
|
+
return;
|
|
199
202
|
}
|
|
200
|
-
callbacks.onKeyUpdate({ whitelistedKeyIds, blacklistedKeyIds });
|
|
201
203
|
}
|
|
204
|
+
callbacks.onKeyUpdate({ whitelistedKeyIds, blacklistedKeyIds });
|
|
202
205
|
}
|
|
203
206
|
|
|
204
207
|
function runGetLicense(
|
|
205
208
|
message : Uint8Array,
|
|
206
209
|
messageType : MediaKeyMessageType
|
|
207
210
|
) : Promise<BufferSource | null> {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const getLicense = keySystemOptions.getLicense(message, messageType);
|
|
211
|
-
const getLicenseTimeout = isNullOrUndefined(getLicenseConfig.timeout) ?
|
|
212
|
-
10 * 1000 :
|
|
213
|
-
getLicenseConfig.timeout;
|
|
214
|
-
|
|
215
|
-
let timeoutId : number | undefined;
|
|
216
|
-
if (getLicenseTimeout >= 0) {
|
|
217
|
-
timeoutId = setTimeout(() => {
|
|
218
|
-
rej(new GetLicenseTimeoutError(
|
|
219
|
-
`"getLicense" timeout exceeded (${getLicenseTimeout} ms)`
|
|
220
|
-
));
|
|
221
|
-
}, getLicenseTimeout) as unknown as number;
|
|
222
|
-
}
|
|
223
|
-
|
|
211
|
+
let timeoutId : number | undefined;
|
|
212
|
+
return new Promise<BufferSource | null>((res, rej) => {
|
|
224
213
|
try {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
214
|
+
log.debug("DRM: Calling `getLicense`", messageType);
|
|
215
|
+
const getLicense = keySystemOptions.getLicense(message, messageType);
|
|
216
|
+
const getLicenseTimeout = isNullOrUndefined(getLicenseConfig.timeout) ?
|
|
217
|
+
10 * 1000 :
|
|
218
|
+
getLicenseConfig.timeout;
|
|
219
|
+
|
|
220
|
+
if (getLicenseTimeout >= 0) {
|
|
221
|
+
timeoutId = setTimeout(() => {
|
|
222
|
+
rej(new GetLicenseTimeoutError(
|
|
223
|
+
`"getLicense" timeout exceeded (${getLicenseTimeout} ms)`
|
|
224
|
+
));
|
|
225
|
+
}, getLicenseTimeout) as unknown as number;
|
|
226
|
+
}
|
|
227
|
+
Promise.resolve(getLicense)
|
|
228
|
+
.then(clearTimeoutAndResolve, clearTimeoutAndReject);
|
|
234
229
|
} catch (err) {
|
|
235
|
-
|
|
236
|
-
rej(err);
|
|
230
|
+
clearTimeoutAndReject(err);
|
|
237
231
|
}
|
|
238
|
-
function
|
|
232
|
+
function clearTimeoutAndResolve(data : BufferSource | null) {
|
|
239
233
|
if (timeoutId !== undefined) {
|
|
240
234
|
clearTimeout(timeoutId);
|
|
241
235
|
}
|
|
236
|
+
res(data);
|
|
237
|
+
}
|
|
238
|
+
function clearTimeoutAndReject(err : unknown) {
|
|
239
|
+
if (timeoutId !== undefined) {
|
|
240
|
+
clearTimeout(timeoutId);
|
|
241
|
+
}
|
|
242
|
+
rej(err);
|
|
242
243
|
}
|
|
243
244
|
});
|
|
244
245
|
}
|
|
@@ -18,6 +18,7 @@ import { ICustomMediaKeySession } from "../../../compat";
|
|
|
18
18
|
/* eslint-disable-next-line max-len */
|
|
19
19
|
import getUUIDKidFromKeyStatusKID from "../../../compat/eme/get_uuid_kid_from_keystatus_kid";
|
|
20
20
|
import { EncryptedMediaError } from "../../../errors";
|
|
21
|
+
import log from "../../../log";
|
|
21
22
|
import {
|
|
22
23
|
IEncryptedMediaErrorKeyStatusObject,
|
|
23
24
|
IKeySystemOption,
|
|
@@ -109,6 +110,11 @@ export default function checkKeyStatuses(
|
|
|
109
110
|
new Uint8Array(keyStatusKeyId));
|
|
110
111
|
|
|
111
112
|
const keyStatusObj = { keyId: keyId.buffer, keyStatus };
|
|
113
|
+
|
|
114
|
+
if (log.hasLevel("DEBUG")) {
|
|
115
|
+
log.debug(`DRM: key status update (${bytesToHex(keyId)}): ${keyStatus}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
112
118
|
switch (keyStatus) {
|
|
113
119
|
case KEY_STATUSES.EXPIRED: {
|
|
114
120
|
const error = new EncryptedMediaError(
|