Skip to content

Commit

Permalink
Add the possibility to set a new keySystems option on the reload API
Browse files Browse the repository at this point in the history
A majority of the bigger issues we encounter in production is
DRM-related, leading us to either work-around those in the RxPlayer, or
to facilitate a work-around on the application-side through a better
DRM-related API.

Recently, we've seen that many Windows/Edge users (but still a minority
of them) could encounter an issue on the `generateRequest` EME call when
relying on PlayReady SL3000 (hardware-backed decryption and playback,
seen as one the most secure DRM mechanism for OTT contents) which would
lead to a failure to play the content.

When this happens, fallbacking to a different key system like PlayReady
SL2000 (where decryption happens in software) or Widevine usually
(though not always) seems to avoid the issue, even if it might lead to less
protection and thus might lead generally to only lower video qualities (as
higher security requirements are in practice generally just enforced for
the higher video qualities, depending on license policies).

After brainstorming whether this fallback should be done on the
RxPlayer-side, or on the application-side, we're for now implementing the
easier way (for us :p) of just providing here an API allowing to just
let the application replay the last loaded content (whose loading may have
failed due to the aforementioned `generateRequest` error) with
a different `keySystems` configuration, thus allowing an application to
reload the last loaded content after blacklisting the current key system
if the error appears to be linked to that issue.
  • Loading branch information
peaBerberian committed Nov 2, 2023
1 parent 6df87bf commit 4d2d94c
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 1 deletion.
11 changes: 11 additions & 0 deletions doc/api/Basic_Methods/reload.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ The options argument is an object containing :
content was playing the last time it was played and stay in the `"LOADED"`
state (and paused) if it was paused last time it was played.

- _keySystems_ (`Array.<Object> | undefined`): If set, a new configuration will
be set on this reloaded content regarding its decryption.

The value of this property follows the exact same structure than for the
original `loadVideo` call, it is described in the [decryption options
documentation page](../Decryption_Options.md).

You might for example want to update that way the `keySystems` option compared
to the one of the original `loadVideo` call when you suspect that there is a
decryption-related issue with the original `keySystems` given.

Note that despite this method's name, the player will not go through the
`RELOADING` state while reloading the content but through the regular `LOADING`
state - as if `loadVideo` was called on that same content again.
Expand Down
9 changes: 9 additions & 0 deletions src/core/api/option_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,8 @@ function parseConstructorOptions(
*/
function checkReloadOptions(options?: {
reloadAt?: { position?: number; relative?: number };
keySystems?: IKeySystemOption[];
autoPlay?: boolean;
}): void {
if (options === null ||
(typeof options !== "object" && options !== undefined)) {
Expand All @@ -414,6 +416,13 @@ function checkReloadOptions(options?: {
options?.reloadAt?.relative !== undefined) {
throw new Error("API: reload - Invalid 'reloadAt.relative' option format.");
}
if (options?.keySystems === null ||
(!Array.isArray(options?.keySystems) && options?.keySystems !== undefined)) {
throw new Error("API: reload - Invalid 'keySystems' option format.");
}
if (options?.autoPlay !== undefined && typeof options.autoPlay !== "boolean") {
throw new Error("API: reload - Invalid 'autoPlay' option format.");
}
}

/**
Expand Down
14 changes: 13 additions & 1 deletion src/core/api/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import {
IConstructorOptions,
IDecipherabilityUpdateContent,
IKeySystemConfigurationOutput,
IKeySystemOption,
ILoadVideoOptions,
IPeriod,
IPlayerError,
Expand Down Expand Up @@ -577,6 +578,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
*/
reload(reloadOpts?: {
reloadAt?: { position?: number; relative?: number };
keySystems?: IKeySystemOption[];
autoPlay?: boolean;
}): void {
const { options,
Expand Down Expand Up @@ -609,6 +611,13 @@ class Player extends EventEmitter<IPublicAPIEvent> {
autoPlay = !reloadInPause;
}

let keySystems : IKeySystemOption[] | undefined;
if (reloadOpts?.keySystems !== undefined) {
keySystems = reloadOpts.keySystems;
} else if (this._priv_reloadingMetadata.options?.keySystems !== undefined) {
keySystems = this._priv_reloadingMetadata.options.keySystems;
}

const newOptions = { ...options,
initialManifest: manifest };
if (startAt !== undefined) {
Expand All @@ -617,6 +626,9 @@ class Player extends EventEmitter<IPublicAPIEvent> {
if (autoPlay !== undefined) {
newOptions.autoPlay = autoPlay;
}
if (keySystems !== undefined) {
newOptions.keySystems = keySystems;
}
this._priv_initializeContentPlayback(newOptions);
}

Expand All @@ -626,7 +638,7 @@ class Player extends EventEmitter<IPublicAPIEvent> {
if (features.createDebugElement === null) {
throw new Error("Feature `DEBUG_ELEMENT` not added to the RxPlayer");
}
const canceller = new TaskCanceller() ;
const canceller = new TaskCanceller();
features.createDebugElement(element, this, canceller.signal);
return {
dispose() {
Expand Down

0 comments on commit 4d2d94c

Please sign in to comment.