GNOME Bugzilla – Bug 753344
hlsdemux: Fix playback of live streams
Last modified: 2015-08-28 18:28:01 UTC
Created attachment 308878 [details] Patch for fix from ruDREAM for problem playing live HLS stream diff -u --recursive --new-file original/ext/hls/m3u8.c new/ext/hls/m3u8.c --- original/ext/hls/m3u8.c 2015-06-07 10:04:45.000000000 +0300 +++ new/ext/hls/m3u8.c 2015-08-06 23:41:02.348000058 +0300 @@ -850,7 +850,6 @@ } if (m3u8->files && self->sequence == -1) { - self->current_file = g_list_first (m3u8->files); if (GST_M3U8_CLIENT_IS_LIVE (self)) { /* for live streams, start GST_M3U8_LIVE_MIN_FRAGMENT_DISTANCE from the end of the playlist. See section 6.3.3 of HLS draft */ @@ -859,8 +858,10 @@ self->sequence = GST_M3U8_MEDIA_FILE (g_list_nth_data (m3u8->files, pos >= 0 ? pos : 0))->sequence; - } else + } else { + self->current_file = g_list_first (m3u8->files); self->sequence = GST_M3U8_MEDIA_FILE (self->current_file->data)->sequence; + } self->sequence_position = 0; GST_DEBUG ("Setting first sequence at %u", (guint) self->sequence); }
Created attachment 308879 [details] [review] fix_hlsdemux_hls_live.patch Patch from the attached zip file. Can you explain what this fixes and why this fix is correct?
Some more info from IRC earlier: <gstreamer984> Hi <gstreamer984> Hls has a bug on live streams from youtube, it goes 4 hours back instead going live. Here is a fix http://forums.openpli.org/topic/38572-problem-playing-live-hls-stream-with-gstreamer/#entry500444 <gstreamer984> Also maybe self->current_file should be g_list_nth_data (m3u8->files, pos >= 0 ? pos : 0)) when live?
I added the info on IRC, but better to add info here. The current_file should point to file where sequence is, right? Currenlty it points to first file for live and vod. Maybe something like the following required. if(live) self->current_file = g_list_nth_data (m3u8->files, pos >= 0 ? pos : 0) else self->current_file = g_list_first (m3u8->files); Because using above patch current_file has no value when live.
For those who do not understand that the changes the patch: Otherwise after using GST_M3U8_CLIENT_IS_LIVE = True: Setting first sequence from the END of the playlist, in gst_m3u8_client_has_next_fragment function in code: if (! client-> current_file) { client-> current_file = find_next_fragment (client, client-> current-> files, forward); } The following function is not executed: find_next_fragment (client-> current_file has already been appointed) as well as the following code not executed too: client-> sequence = file-> sequence; And setting up again the: Setting first sequence from the TOP of the playlist
Debug log do fix: 0:00:12.421533696 987 0x74b1b0 DEBUG fragmented m3u8.c:865:gst_m3u8_client_update: Setting first sequence at 2194818 0:00:12.449049215 987 0x74b1b0 DEBUG fragmented m3u8.c:1021:gst_m3u8_client_get_next_fragment: Looking for fragment 2194818 0:00:12.449157733 987 0x74b1b0 DEBUG fragmented m3u8.c:1038:gst_m3u8_client_get_next_fragment: Got fragment with sequence 2191939 (client sequence 2194818) #ERROR Lowered sequence, but should be increased 0:00:12.452527585 987 0x691800 DEBUG fragmented m3u8.c:1021:gst_m3u8_client_get_next_fragment: Looking for fragment 2191939 0:00:12.452665474 987 0x691800 DEBUG fragmented m3u8.c:1038:gst_m3u8_client_get_next_fragment: Got fragment with sequence 2191939 (client sequence 2191939) 0:00:22.092428876 987 0x5c9920 DEBUG fragmented m3u8.c:1148:gst_m3u8_client_advance_fragment: Advancing from sequence 2191939 Debug log after fix: 0:00:14.934132806 1827 0x79a7b0 DEBUG fragmented m3u8.c:867:gst_m3u8_client_update: Setting first sequence at 2198075 0:00:14.960840954 1827 0x79a7b0 DEBUG fragmented m3u8.c:1028:gst_m3u8_client_get_next_fragment: Looking for fragment 2198075 0:00:15.328647991 1827 0x6e1200 DEBUG fragmented m3u8.c:1047:gst_m3u8_client_get_next_fragment: Got fragment with sequence 2198075 (client sequence 2198075) #OK 0:00:23.860507431 1827 0x61a920 DEBUG fragmented m3u8.c:1163:gst_m3u8_client_advance_fragment: Advancing from sequence 2198075 #OK 0:00:23.891802171 1827 0x6e1200 DEBUG fragmented m3u8.c:1028:gst_m3u8_client_get_next_fragment: Looking for fragment 2198076 #OK sequence increased 0:00:23.891868542 1827 0x6e1200 DEBUG fragmented m3u8.c:1047:gst_m3u8_client_get_next_fragment: Got fragment with sequence 2198076 (client sequence 2198076) forward #OK
@alexvrs, Could you please try one also? diff --git a/ext/hls/m3u8.c b/ext/hls/m3u8.c index 5e78d94..4ca761c 100755 --- a/ext/hls/m3u8.c +++ b/ext/hls/m3u8.c @@ -850,17 +850,20 @@ gst_m3u8_client_update (GstM3U8Client * self, gchar * data) } if (m3u8->files && self->sequence == -1) { - self->current_file = g_list_first (m3u8->files); if (GST_M3U8_CLIENT_IS_LIVE (self)) { /* for live streams, start GST_M3U8_LIVE_MIN_FRAGMENT_DISTANCE from the end of the playlist. See section 6.3.3 of HLS draft */ gint pos = g_list_length (m3u8->files) - GST_M3U8_LIVE_MIN_FRAGMENT_DISTANCE; + self->current_file = g_list_nth (m3u8->files, + pos >= 0 ? pos : 0) self->sequence = GST_M3U8_MEDIA_FILE (g_list_nth_data (m3u8->files, pos >= 0 ? pos : 0))->sequence; - } else + } else { + self->current_file = g_list_first (m3u8->files); self->sequence = GST_M3U8_MEDIA_FILE (self->current_file->data)->sequence; + } self->sequence_position = 0; GST_DEBUG ("Setting first sequence at %u", (guint) self->sequence); } The only difference is that will set current_file to the same file that sequence points. So it will use the last 3 segments from list and then will request the next segment.
@alexvrs, here is a a simplified version (it will set the sequence using current_file). diff --git a/ext/hls/m3u8.c b/ext/hls/m3u8.c index 5e78d94..c080a95 100755 --- a/ext/hls/m3u8.c +++ b/ext/hls/m3u8.c @@ -850,17 +850,16 @@ gst_m3u8_client_update (GstM3U8Client * self, gchar * data) } if (m3u8->files && self->sequence == -1) { - self->current_file = g_list_first (m3u8->files); if (GST_M3U8_CLIENT_IS_LIVE (self)) { /* for live streams, start GST_M3U8_LIVE_MIN_FRAGMENT_DISTANCE from the end of the playlist. See section 6.3.3 of HLS draft */ gint pos = g_list_length (m3u8->files) - GST_M3U8_LIVE_MIN_FRAGMENT_DISTANCE; - self->sequence = - GST_M3U8_MEDIA_FILE (g_list_nth_data (m3u8->files, - pos >= 0 ? pos : 0))->sequence; + self->current_file = g_list_nth (m3u8->files, + pos >= 0 ? pos : 0) } else - self->sequence = GST_M3U8_MEDIA_FILE (self->current_file->data)->sequence; + self->current_file = g_list_first (m3u8->files); + self->sequence = GST_M3U8_MEDIA_FILE (self->current_file->data)->sequence; self->sequence_position = 0; GST_DEBUG ("Setting first sequence at %u", (guint) self->sequence); }
@Athanasios Oikonomou Nice
Can you attach as a git format-patch style format, explain the actual problem and what the fix is (in the commit message)?
@Athanasios Oikonomou small syntax fix: diff --git a/ext/hls/m3u8.c b/ext/hls/m3u8.c index 5e78d94..c080a95 100755 --- a/ext/hls/m3u8.c +++ b/ext/hls/m3u8.c @@ -850,17 +850,16 @@ gst_m3u8_client_update (GstM3U8Client * self, gchar * data) } if (m3u8->files && self->sequence == -1) { - self->current_file = g_list_first (m3u8->files); if (GST_M3U8_CLIENT_IS_LIVE (self)) { /* for live streams, start GST_M3U8_LIVE_MIN_FRAGMENT_DISTANCE from the end of the playlist. See section 6.3.3 of HLS draft */ gint pos = g_list_length (m3u8->files) - GST_M3U8_LIVE_MIN_FRAGMENT_DISTANCE; - self->sequence = - GST_M3U8_MEDIA_FILE (g_list_nth_data (m3u8->files, - pos >= 0 ? pos : 0))->sequence; + self->current_file = g_list_nth (m3u8->files, + pos >= 0 ? pos : 0); } else - self->sequence = GST_M3U8_MEDIA_FILE (self->current_file->data)->sequence; + self->current_file = g_list_first (m3u8->files); + self->sequence = GST_M3U8_MEDIA_FILE (self->current_file->data)->sequence; self->sequence_position = 0; GST_DEBUG ("Setting first sequence at %u", (guint) self->sequence); }
Created attachment 308887 [details] [review] hlsdemux: select correct position for live streams that don't remove fragments
Created attachment 308888 [details] [review] hlsdemux: select correct position for live streams that don't remove fragments Add a missing semicolon. Thanks @alexvrs
Review of attachment 308879 [details] [review]: We need to set the correct fragment to self->current_file for both live and vod streams.
Is it possible to somebody to have a look please? It would be nice to have that problem fixes before 1.6 version released.
commit 22456ce0328a8d06a12997979a143a0103867a49 Author: Athanasios Oikonomou <athoik@gmail.com> Date: Fri Aug 7 12:53:23 2015 +0300 hlsdemux: select correct position for live streams that don't remove fragments Some live streams (eg youtube) don't remove fragments in order to allow seeking back in time (live + vod). When gst_m3u8_client_has_next_fragment is called, we are getting wrong fragment because current_file points in first file of the fragments list resulting in watching the stream from the beginning again. This patch sets current_file to nth fragment for live streams, then on gst_m3u8_client_has_next_fragment will keep up with the live stream. https://bugzilla.gnome.org/show_bug.cgi?id=753344