]> git.sesse.net Git - vlc/blobdiff - modules/stream_filter/httplive.c
stream_filter/httplive.c: do not crash on seeking
[vlc] / modules / stream_filter / httplive.c
index 8f052a41211b9a32c8b3508109809dbafa78da1b..ae4ece2a10bd2320a4a3047fb2e9bbfe3a74d5ce 100644 (file)
@@ -61,7 +61,7 @@ vlc_module_end()
 typedef struct segment_s
 {
     int         sequence;   /* unique sequence number */
-    int         length;     /* segment duration (ms) */
+    int         length;     /* segment duration (seconds) */
     uint64_t    size;       /* segment size in bytes */
 
     vlc_url_t   url;
@@ -232,6 +232,29 @@ static hls_stream_t *hls_GetLast(vlc_array_t *hls_stream)
     return (hls_stream_t *) hls_Get(hls_stream, count);
 }
 
+static int hls_LowestBandwidthStream(vlc_array_t *hls_stream)
+{
+    int count = vlc_array_count(hls_stream);
+    int i_lowest = 0;
+    uint64_t lowest = 0;
+
+    for (int i = 0; i < count; i++)
+    {
+        hls_stream_t *hls = (hls_stream_t *) vlc_array_item_at_index(hls_stream, i);
+        if (lowest == 0)
+        {
+            lowest = hls->bandwidth;
+            i_lowest = i;
+        }
+        else if (hls->bandwidth < lowest)
+        {
+            lowest = hls->bandwidth;
+            i_lowest = i;
+        }
+    }
+    return i_lowest;
+}
+
 /* Segment */
 static segment_t *segment_New(hls_stream_t* hls, int duration, char *uri)
 {
@@ -1158,7 +1181,7 @@ static int Open(vlc_object_t *p_this)
     }
 
     /* */
-    int current = p_sys->current = 0;
+    int current = p_sys->current = hls_LowestBandwidthStream(p_sys->hls_stream);
     p_sys->segment = 0;
 
     if (Prefetch(s, &current) != VLC_SUCCESS)
@@ -1232,11 +1255,12 @@ static segment_t *NextSegment(stream_t *s)
 {
     stream_sys_t *p_sys = s->p_sys;
     segment_t *segment = NULL;
+    int i_stream = 0;
 
     while(vlc_object_alive(s))
     {
         /* Is the next segment ready */
-        hls_stream_t *hls = hls_Get(p_sys->hls_stream, p_sys->current);
+        hls_stream_t *hls = hls_Get(p_sys->hls_stream, i_stream);
         if (hls == NULL) return NULL;
 
         segment = segment_GetSegment(hls, p_sys->segment);
@@ -1249,22 +1273,14 @@ static segment_t *NextSegment(stream_t *s)
         if (!p_sys->b_meta) return NULL;
 
         /* Was the stream changed to another bitrate? */
-        if (p_sys->current != p_sys->thread->current)
-        {
-            /* YES it was */
-            msg_Info(s, "playback is switching from stream %d to %d",
-                     p_sys->current, p_sys->thread->current);
-            p_sys->current = p_sys->thread->current;
-            continue;
-        }
-
+        i_stream++;
+        if (i_stream >= vlc_array_count(p_sys->hls_stream))
+            return NULL;
 #if 0
-        /* Not downloaded yet, do it here */
-        if (Download(s, hls, segment, &p_sys->current) != VLC_SUCCESS)
-            return segment;
-        else
+        msg_Info(s, "playback is switching from stream %d to %d",
+                 p_sys->current, i_stream);
 #endif
-            return NULL;
+        p_sys->current = i_stream;
     }
 
     return segment;
@@ -1459,23 +1475,39 @@ static int segment_Seek(stream_t *s, uint64_t pos)
             return VLC_EGENERIC;
 
         vlc_mutex_lock(&segment->lock);
-        length += segment->size;
-        uint64_t size = segment->size -segment->data->i_buffer;
-        if (size > 0)
+        if (segment->data)
         {
-            segment->data->i_buffer += size;
-            segment->data->p_buffer -= size;
-        }
+            length += segment->size;
+            uint64_t size = segment->size -segment->data->i_buffer;
+            if (size > 0)
+            {
+                segment->data->i_buffer += size;
+                segment->data->p_buffer -= size;
+            }
 
-        if (!b_found && (pos <= length))
+            if (!b_found && (pos <= length))
+            {
+                uint64_t used = length - pos;
+                segment->data->i_buffer -= used;
+                segment->data->p_buffer += used;
+
+                count = p_sys->segment;
+                p_sys->segment = n;
+                b_found = true;
+            }
+        }
+        else
         {
-            uint64_t used = length - pos;
-            segment->data->i_buffer -= used;
-            segment->data->p_buffer += used;
+            /* FIXME: seeking is weird when seeking in segments
+               that have not been downloaded yet */
+            length += segment->length * hls->bandwidth;
 
-            count = p_sys->segment;
-            p_sys->segment = n;
-            b_found = true;
+            if (!b_found && (pos <= length))
+            {
+                count = p_sys->segment;
+                p_sys->segment = n;
+                b_found = true;
+            }
         }
         vlc_mutex_unlock(&segment->lock);
     }