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

HLS media sequence resets make the player get stuck in buffering state #2872

Closed
yueyueniao2012 opened this issue May 27, 2017 · 13 comments
Closed
Assignees

Comments

@yueyueniao2012
Copy link

yueyueniao2012 commented May 27, 2017

Issue description

@AquilesCanta
I meet this issue with this url:
http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8.
This video play stuck buffering in random time and never come back to ready.
This issue will always appear on any device when playing a little bit longer time.Through the analysis of a period of time I find the issue is that sometime this live stream http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8 HlsMediaPlaylist's mediaSequence suddenly change to start from zero.This behavior leads to HlsPlaylistTracker's func getLatestPlaylistSnapshot always return oldPlaylist,so the Exoplayer stuck at buffering.I think in this case the player should continue to play the live stream or throw an exception and not stuck at buffering.

private HlsMediaPlaylist getLatestPlaylistSnapshot(HlsMediaPlaylist oldPlaylist,
      HlsMediaPlaylist loadedPlaylist) {
    if (!loadedPlaylist.isNewerThan(oldPlaylist)) {
      if (loadedPlaylist.hasEndTag) {
        // If the loaded playlist has an end tag but is not newer than the old playlist then we have
        // an inconsistent state. This is typically caused by the server incorrectly resetting the
        // media sequence when appending the end tag. We resolve this case as best we can by
        // returning the old playlist with the end tag appended.
        return oldPlaylist.copyWithEndTag();
      } else {
        return oldPlaylist;
      }
    }
    long startTimeUs = getLoadedPlaylistStartTimeUs(oldPlaylist, loadedPlaylist);
    int discontinuitySequence = getLoadedPlaylistDiscontinuitySequence(oldPlaylist, loadedPlaylist);
    return loadedPlaylist.copyWith(startTimeUs, discontinuitySequence);
  }

Reproduction steps

Play this url http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8 with a little bit longer time.

Version of ExoPlayer being used

latest

@AquilesCanta AquilesCanta changed the title HLS Live Video stuck at buffering and never come back to ready HLS media sequence resets make the player get stuck in buffering state Jun 1, 2017
@parkgrrr
Copy link

parkgrrr commented Jun 11, 2017

Are there any thoughts on what could be causing this? I am seeing similar behavior using the ExoMedia wrapper library which uses ExoPlayer 2.4.0. Here is one stack trace from around the time it happened, but it usually doesn't have any errors.

@AquilesCanta
Copy link
Contributor

@parkgrrr, the cause of the issue described here is clear, I think: The server is resetting the media sequence:

mediaSequence suddenly change to start from zero

A patch is on the way to throw an error when this condition is met, so the application can detect this condition and reset the player.

@AquilesCanta
Copy link
Contributor

If you don't think your issue is related to this, please file a new issue inlcuding all the information requested in the issue template.

@TarifHatoum
Copy link

hi AquilesCanta is there any expected time for the patch concerning this issue?

@yueyueniao2012
Copy link
Author

hi, @AquilesCanta is there any expected time for the patch concerning this issue?

@AquilesCanta
Copy link
Contributor

Still waiting for review. Thanks for your patience.

ojw28 pushed a commit that referenced this issue Jul 5, 2017
This CL aims that the player fails upon:

- Playlist that don't change in a suspiciously long time,
  which might mean there are server side issues.
- Playlist with a media sequence lower that its last snapshot
  and no overlapping segments.

This two error conditions are propagated through the renderer,
but not through MediaSource#maybeThrowSourceInfoRefreshError.

Issue:#2872

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=160899995
@yueyueniao2012
Copy link
Author

I'm really expecting!Thank you very much for your excellent work!

@AquilesCanta
Copy link
Contributor

The new approach will just propagate an exception when the reset condition is met. You will then have to re-prepare the player. In the future we might consider supporting seamless continuation. Please let us know if you run into any problems.

@yueyueniao2012
Copy link
Author

OK!I will if I meet some new issue.Really thank you!

@TarifHatoum
Copy link

hi AquilesCanta i have implemented this but the player tooks a lot of time to play the hls. Is there a way to make to popup an error message to decrease the time of reinitializing the url such as onPlayerError function?

@AquilesCanta
Copy link
Contributor

I don't understand very well. Could you elaborate a bit more on what the issue is?

@TarifHatoum
Copy link

hi AquilesCanta the implementation of the handling issue works greatly but it took a time around 2 minutes or more buffering before continuing playing. So is there a way to detect when server is restarted such as OnplayerError function?

@AquilesCanta
Copy link
Contributor

2 minutes is way too long, so something is not going well. A few notes that might be helpful:

  • ExoPlayer will not propagate the error until it reaches the live edge (i.e. the buffered media is played in its entirety). So, if there are b seconds of buffered media, and the reset happens at time t, the exception is not going to be propagated before t+b. But this means that the player will be in ready state.
  • The condition we use to detect playlist resets is that the sequence number has gone backwards and there are no overlapping chunks. Even though this makes it harder to detect server resets, ExoPlayer also tries to tolerate cases when the playlist, due to load balancing for instance, changes the target server (making the media sequence go backward). The implications of this are that if your playlist has n chunks, then resetting the server before ExoPlayer's snapshot of the player has media sequence n, means the reset condition will never be detected. Also note that the refreshing might take time, so this rule applies to resets that happen after media sequence number slightly higher than n.
  • ExoPlayer uses a best effort approach to detect these kinds of failures/unexpected behaviors. Don't depend on the player handling well situations that are not described in the spec. If you think the spec does define what to do in these cases, let us know. My point of view is that:

the Playlist file MUST contain an EXT-X-SEQUENCE tag. Its value MUST be incremented by 1 for every Media Segment that is removed from the Playlist file; it MUST NOT decrease or wrap.

The conclusion is: The playlist reset condition might not be detected if you reset too often. A workaround for this would be using a media sequence number that is far back in time, to make sure the reset condition is detected. You should add some logging in the playlist tracker and run again to check this. If this is not happening, no propagation mechanism will work.

Finally, two action points:

  1. Before we fix the current implementation, make sure the reset condition is being detected.
  2. You can check server resets yourselves by keeping track of onTimelineChanged. From the manifest you can retrieve the media playlist that acts as live window, and there you will find the EXT-X-SEQUENCE tag. Which will allow you to act even before the player goes into buffering state.

Hope this helps.

ojw28 pushed a commit that referenced this issue Jul 19, 2017
This CL aims that the player fails upon:

- Playlist that don't change in a suspiciously long time,
  which might mean there are server side issues.
- Playlist with a media sequence lower that its last snapshot
  and no overlapping segments.

This two error conditions are propagated through the renderer,
but not through MediaSource#maybeThrowSourceInfoRefreshError.

Issue:#2872

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=160899995
@google google locked and limited conversation to collaborators Nov 4, 2017
AquilesCanta referenced this issue Sep 17, 2020
Issue:#2844
Issue:#2981

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=204718939
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants