Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: excessive requests when using HDCP fallback with LDL #225

Merged
merged 15 commits into from
Aug 27, 2024

Conversation

harisha-swaminathan
Copy link
Contributor

@harisha-swaminathan harisha-swaminathan commented Jun 30, 2024

When we have HDCP fallback and short-duration license, there are excessive requests because we're renewing licenses and subsequently fetching new licenses if the renewal fails. This can be avoided by taking an approach similar to Shaka player by not requesting a new license when the old one expires.

The PR also provides an option to limit license renewals when the player is idle (before playback begins, after playback ends and player abandoned in paused state).

  • License is not renewed if it expires before playback begins if limitRenewalsBeforePlay is set to true. New requests are made on 'play'
  • License is not renewed after playback ends by default. New requests are made on 'replay' or 'seek back'
  • License is not renewed if player remains paused for more than a specified duration that's set using limitRenewalsMaxPauseDuration option

@harisha-swaminathan harisha-swaminathan marked this pull request as draft June 30, 2024 18:37
@harisha-swaminathan harisha-swaminathan marked this pull request as ready for review July 2, 2024 03:27
Copy link
Contributor

@adrums86 adrums86 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like this change! License expiration/renewal cannot be effectively used for concurrency enforcement and detection if we attempt a renewal automatically on expiration.
One small thing, boolean flags make me nervous for some irrational reason, could we get a test around that flag and the new 'ended' logic?

src/plugin.js Outdated Show resolved Hide resolved
src/plugin.js Outdated Show resolved Hide resolved
@@ -160,6 +161,10 @@ export const makeNewRequest = (player, requestOptions) => {
return;
}

if (event.messageType === 'license-renewal' && (!player.hasStarted() || player.paused())) {
return;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an attempt to reduce the number of license renewals made when the player is idle (before playback begins) or when the player is paused for too long.

A more ideal solution to this would probably be closing and removing the sessions if the player is abandoned in a paused state and then making a new request when unpaused. Maybe such a behavior should be behind an option where the amount of time to wait (before closing and removing the session) is specified ? But this might introduce some complications.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems the paused check could cause a license to expire mid stream. Has this been tested? Curious if the player can recover the session after playback is resumed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To provide further context to what I'm asking here, I'm curious if the player sits either paused or before starting playback for the duration of a license and it expires, will we request a new license and recover upon resuming playback?

Copy link
Contributor Author

@harisha-swaminathan harisha-swaminathan Aug 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made some changes to the previous logic. I've added an option limitRenewalsOnPauseTime (which probably needs a better name) to define the number of seconds to wait in paused state before rejecting renewals and closing the session.

The player will request new license when playback resumes.

Session is closed when license-renewal is attempted after playback ends. New requests will be made on replay or seek-back

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it should be something like: limitRenewalsMaxPauseDuration

Copy link
Contributor

@adrums86 adrums86 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Just a couple more questions.

src/plugin.js Outdated Show resolved Hide resolved
@@ -160,6 +161,10 @@ export const makeNewRequest = (player, requestOptions) => {
return;
}

if (event.messageType === 'license-renewal' && (!player.hasStarted() || player.paused())) {
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems the paused check could cause a license to expire mid stream. Has this been tested? Curious if the player can recover the session after playback is resumed.

@harisha-swaminathan harisha-swaminathan marked this pull request as draft July 22, 2024 21:22
@harisha-swaminathan harisha-swaminathan marked this pull request as ready for review August 23, 2024 03:54
Copy link
Contributor

@wseymour15 wseymour15 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change looks great! I left a few comments mainly relating to documentation.

handleEncryptedEvent(player, mockEncryptedEvent, getOptions(player), player.eme.sessions, player.tech_, emeError);
};

if (videojs.browser.IS_FIREFOX) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would a comment describing why we are doing this only on Firefox be useful? I guess at first glance it isn't obvious why we are only sending the mock encrypted event in Firefox

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment!

src/eme.js Outdated
let pauseTimer;

player.on('pause', () => {
if (options.limitRenewalsOnPauseTime && typeof options.limitRenewalsOnPauseTime === 'number') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to document the limitRenewalsBeforePlay and limitRenewalsOnPauseTime in the README?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated README in the latest commit!

@@ -231,29 +276,7 @@ export const makeNewRequest = (player, requestOptions) => {
if (expired) {
// Close session and remove it from the session list to ensure that a new
// session can be created.
videojs.log.debug('Session expired, closing the session.');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We removed this debug statement and didn't add it back in closeAndRemoveSession .. should we add something similar?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Added it back in closeAndRemoveSession

src/eme.js Outdated

if (!player.hasStarted() && limitRenewalsBeforePlay ||
(player.paused() && typeof limitRenewalsOnPauseTime === 'number' && timeElapsed >= limitRenewalsOnPauseTime) ||
player.ended()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I would split it into several consts eg:
ignoreLinceRenewal (before playback, max pause duration reached, ended)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@harisha-swaminathan harisha-swaminathan merged commit 348935e into main Aug 27, 2024
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants