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: live dash segment changes should be considered a playlist update #1065

Merged
merged 3 commits into from
Feb 19, 2021

Conversation

brandonocasey
Copy link
Contributor

Description

Currently dash content goes off of the number attribute for segments to determine the mediaSequence. This is problematic as the first segment is almost always listed as 1. So in essence when we request the playlist again the media sequence will be the same, and likely the amount of segments will be the same, so we will determine that this playlist update didn't update anything at all.

You can currently see this issue with the Unified Streaming Live DASH source. Eventually we will get into a state where the playlist isn't seen to be refreshing, even though the underlying segment uri's are changing every request.

const newSidx = media.sidx;

// if sidx changed then the playlists are different.
if (oldSidx && newSidx && (oldSidx.offset !== newSidx.offset || oldSidx.length !== newSidx.length)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now dash playlists can also be listed as changing in cases where:

  1. sidx does not match
  2. playlist segment uris don't match up
  3. playlist segment byterange uris don't match up.

@@ -69,7 +69,7 @@ export const resolveSegmentUris = (segment, baseUri) => {
* master playlist with the updated media playlist merged in, or
* null if the merge produced no change.
*/
export const updateMaster = (master, media) => {
export const updateMaster = (master, media, dash = false) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

It might help separate things a bit if we move the DASH specific check into dash-playlist-loader. Maybe have a method updateAndCheckForChanges that wraps both updatePlaylist and didSegmentsChange or something like that.

Might also make it easier to test the function separately.

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 separate function isPlaylistUnchanged that is passed in as unchangedCheck to this function. Dash passes in it's own version that does all the dash specific things and also calls isPlaylistUnchanged at the top.

src/playlist-loader.js Outdated Show resolved Hide resolved
@gkatsev
Copy link
Member

gkatsev commented Feb 9, 2021

Testing with the US Live DASH stream, it's playing, though, after a bit it will bip bop and then buffer and then bip bop and then buffer, where-as before it would just eventually stall and buffer forever.

@gkatsev
Copy link
Member

gkatsev commented Feb 10, 2021

Here's a quick screen recoding of how it looks for me:

Screen.Recording.2021-02-10.at.15.40.16.mov

@gkatsev
Copy link
Member

gkatsev commented Feb 10, 2021

It does seem to just stop working properly some times too.

@gkatsev
Copy link
Member

gkatsev commented Feb 10, 2021

Seeking seems to fix it getting stuck, but then it gets stuck again. Really weird.

@brandonocasey
Copy link
Contributor Author

Yeah there might be another issue here for that source. I think the behavior is better than it was though.

@gkatsev
Copy link
Member

gkatsev commented Feb 16, 2021

Do we want to get this merged in and then fix other live related stuff in subsequent PRs?

@brandonocasey
Copy link
Contributor Author

I think we do, this fix is ready to go and fixes some streams right now


// if sidx changed then the playlists are different.
if (a.sidx && b.sidx && (a.sidx.offset !== b.sidx.offset || a.sidx.length !== b.sidx.length)) {
return false;
Copy link
Member

Choose a reason for hiding this comment

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

while I don't like returning booleans directly, this does seem like it's more readable than trying to convert all this into a single expression (even if it is possible)

return true;
}

// check segments themselves
Copy link
Member

Choose a reason for hiding this comment

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

maybe worth checking a and b's segment's length first? If it changed, the manifest has updated, no?

Copy link
Member

Choose a reason for hiding this comment

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

Ah, isPlaylistUnchanged does this check.

src/playlist-loader.js Outdated Show resolved Hide resolved
test/manifests/dashByterange.mpd Show resolved Hide resolved
@brandonocasey
Copy link
Contributor Author

I don't have a dash byterange source, I was going off of an example I found where byterange was being used.

Co-authored-by: Gary Katsevman <[email protected]>
@gkatsev gkatsev merged commit 1ce7838 into main Feb 19, 2021
@gkatsev gkatsev deleted the fix/live-dash branch February 19, 2021 16:41
@ziddey
Copy link

ziddey commented Mar 10, 2021

Wouldn't it make sense to just fake the media sequence? We take the uri of the first segment in the new playlist, and find the matching segment in the old playlist. Use its index and the old playlist's media sequence to derive the new media sequence. If the segment isn't found, increase sequence by the number of segments to simulate falling behind the live window. Then isPlaylistUnchanged / updateSegments function properly.

As a test, I added to the start of dashPlaylistUnchanged():

  const seqDelta = a.segments.findIndex(s => s.uri === b.segments[0].uri)
  b.mediaSequence = a.mediaSequence + (seqDelta === -1 ? a.segments.length : seqDelta)

Now the US Live DASH stream and other $Time$-based live manifests work.

We'd need to determine the conditions for applying this delta. Perhaps at least b.mediaSequence === 1 && a.segments && b.segments? Or some other way to not interfere if the manifest does have a startNumber.

Should fix #256

edit: opened PR #1092

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.

4 participants