-
Notifications
You must be signed in to change notification settings - Fork 516
[LL-HLS] Prevent excessive reloads when CAN-BLOCK-RELOAD=YES
is not respected
#2317
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
base: main
Are you sure you want to change the base?
[LL-HLS] Prevent excessive reloads when CAN-BLOCK-RELOAD=YES
is not respected
#2317
Conversation
Many thanks for your PR. Have you filed a bug against the server that exhibits this behaviour? Can you unveil a bit more about what servers that are so we knwo and we can potentially test against one of these implementations? If you have a content URI for a LL stream exhibiting this behaviour this would be great as well. |
Hi @marcbaechinger, Thank you for your response. To provide further context, the issue was observed on our internal media server, so I'm unable to share the content URI. I appreciate your understanding. At our service, we have implemented a process where requests are held at the CDN layer until the media server updates the playlist, at which point the latest playlist is returned. The issue occurred because blocking wasn't happening as expected, but we have since resolved it. This issue is difficult to detect because normal playback continues even when it is reproduced. I discovered it while analyzing the reported ANR, during which infinite requests were reproduced with the specific stream. |
058db9c
to
758fef9
Compare
Waits for half the part target duration before retrying when the server responds with `CAN-BLOCK-RELOAD=YES` but does not actually block until the playlist updates. Prevents excessive requests in such cases.
758fef9
to
bca1618
Compare
The server behavior is obviously not fully spec compliant, but given the quite severe permanent reloading, it's probably a good idea to have this fallback. Thanks for filing the PR for it, I'll start the internal merge process now. |
@@ -853,6 +853,13 @@ private void processLoadedPlaylist( | |||
playlistSnapshot != oldPlaylist | |||
? playlistSnapshot.targetDurationUs | |||
: (playlistSnapshot.targetDurationUs / 2); | |||
} else if ( | |||
playlistSnapshot == oldPlaylist && playlistSnapshot.partTargetDurationUs != C.TIME_UNSET |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason you only do this if a part target duration is defined? The same should apply to playlists that canBlockReload but are not low-latency I assume.
Related to that: the fallback should probably be to use playlistSnapshot.targetDurationUs / 2 as in the if case above for when canBlockReload is not supported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @tonihei,
First of all, thank you for reviewing the PR positively.
The IETF standard RFC 8216 does not mention CAN-BLOCK-RELOAD
at all. This attribute is introduced in the context of LL-HLS and described in Section 6.2.5.2 of draft-pantos-hls-rfc8216bis. According to the specification, the use of _HLS_msn
and _HLS_part
parameters—required for blocking playlist reload behavior—appears to clearly limit this mechanism to LL-HLS.
6.2.5.2. Blocking Playlist Reload
A Server MAY offer Blocking Playlist Reloads, which enable immediate
client discovery of Playlist updates as an alternative to polling.
A Server advertises support for Blocking Playlist Reload by adding
the CAN-BLOCK-RELOAD=YES attribute to the EXT-X-SERVER-CONTROL tag.
A Client requests a Blocking Playlist Reload using an _HLS_msn
directive with a decimal-integer value M. When the Playlist URI
contains an _HLS_msn directive and no _HLS_part directive, the Server
MUST defer responding to the request until the Playlist contains a
Media Segment with a Media Sequence Number of M or later or it
responds with an error.
That said, I understand and agree with your concern, as this PR handles an edge case where the server does not fully comply with the RFC.
As a refinement, I’d suggest the following logic:
} else if (playlistSnapshot == oldPlaylist) {
// To prevent infinite requests when the server responds with CAN-BLOCK-RELOAD=YES but does
// not actually block until the playlist updates, wait before retrying.
durationUntilNextLoadUs = playlistSnapshot.partTargetDurationUs != C.TIME_UNSET
? playlistSnapshot.partTargetDurationUs / 2
: playlistSnapshot.targetDurationUs / 2;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you have any thoughts or suggestions on this approach, I’d be happy to revise the code accordingly.
Also, would you prefer that I squash the changes into a single commit and force-push, or keep them as separate commits?
In low-latency HLS playback, some servers may respond with
CAN-BLOCK-RELOAD=YES
but return the playlist before it has actually been updated. This can lead to repeated calls toloadPlaylistImmediately()
until a new playlist version becomes available.Although this server behavior is not ideal, the client should still avoid unnecessary polling and redundant requests. This pull request introduces a short wait duration before allowing the next load attempt in such cases, reducing excessive reloads.
The existing behavior—where playlist loading blocks until an update is available—is preserved when the server correctly delays its response, as the logic checks
playlistSnapshot == oldPlaylist
before deferring the next attempt.