]> git.sesse.net Git - vlc/commitdiff
HLS (httplive.c): fix Peek() function
authorF. Yhuel <fyhuel@viotech.net>
Thu, 4 Aug 2011 14:33:43 +0000 (16:33 +0200)
committerJean-Paul Saman <jean-paul.saman@m2x.nl>
Mon, 8 Aug 2011 09:25:49 +0000 (11:25 +0200)
The new Peek() function now allocates a block (p_sys->peeked) if the
required size (i_peek) is greater than the size of the playback
segment, and then do a copy of one (or several) segment's data block(s) in it.
In the end, p_sys->peeked might be the concatenation of several segment's data
blocks, but usually it will be NULL.

Signed-off-by: Jean-Paul Saman <jean-paul.saman@m2x.nl>
modules/stream_filter/httplive.c

index cc3fe48c755b392037599427fd59332efe132d1a..000a91114e9d7730d36eaacd257e610b7783ca4e 100644 (file)
@@ -92,6 +92,8 @@ struct stream_sys_t
     vlc_thread_t  reload;       /* HLS m3u8 reload thread */
     vlc_thread_t  thread;       /* HLS segment download thread */
 
+    block_t      *peeked;
+
     /* */
     vlc_array_t  *hls_stream;   /* bandwidth adaptation */
     uint64_t      bandwidth;    /* measured bandwidth (bits per second) */
@@ -1662,6 +1664,8 @@ static void Close(vlc_object_t *p_this)
 
     /* */
     vlc_UrlClean(&p_sys->m3u8);
+    if (p_sys->peeked)
+        block_Release (p_sys->peeked);
     free(p_sys);
 }
 
@@ -1850,10 +1854,9 @@ static int Read(stream_t *s, void *buffer, unsigned int i_read)
 static int Peek(stream_t *s, const uint8_t **pp_peek, unsigned int i_peek)
 {
     stream_sys_t *p_sys = s->p_sys;
-    size_t curlen = 0;
     segment_t *segment;
+    unsigned int len = i_peek;
 
-again:
     segment = GetSegment(s);
     if (segment == NULL)
     {
@@ -1864,29 +1867,77 @@ again:
 
     vlc_mutex_lock(&segment->lock);
 
-    /* remember segment to peek */
-    int peek_segment = p_sys->playback.segment;
-    do
+    size_t i_buff = segment->data->i_buffer;
+    uint8_t *p_buff = segment->data->p_buffer;
+
+    if (i_peek < i_buff)
     {
-        if (i_peek < segment->data->i_buffer)
-        {
-            *pp_peek = segment->data->p_buffer;
-            curlen += i_peek;
-        }
-        else
+        *pp_peek = p_buff;
+        vlc_mutex_unlock(&segment->lock);
+        return i_peek;
+    }
+
+    else /* This will seldom be run */
+    {
+        /* remember segment to read */
+        int peek_segment = p_sys->playback.segment;
+        size_t curlen = 0;
+        segment_t *nsegment;
+        p_sys->playback.segment++;
+        block_t *peeked = p_sys->peeked;
+
+        if (peeked == NULL)
+            peeked = block_Alloc (i_peek);
+        else if (peeked->i_buffer < i_peek)
+            peeked = block_Realloc (peeked, 0, i_peek);
+        if (peeked == NULL)
+            return 0;
+
+        memcpy(peeked->p_buffer, p_buff, i_buff);
+        curlen = i_buff;
+        len -= i_buff;
+        vlc_mutex_unlock(&segment->lock);
+
+        i_buff = peeked->i_buffer;
+        p_buff = peeked->p_buffer;
+        *pp_peek = p_buff;
+
+        while ((curlen < i_peek) && vlc_object_alive(s))
         {
-            p_sys->playback.segment++;
-            vlc_mutex_unlock(&segment->lock);
-            goto again;
-        }
-    } while ((curlen < i_peek) && vlc_object_alive(s));
+            nsegment = GetSegment(s);
+            if (nsegment == NULL)
+            {
+                msg_Err(s, "segment %d should have been available (stream %d)",
+                        p_sys->playback.segment, p_sys->playback.stream);
+                /* restore segment to read */
+                p_sys->playback.segment = peek_segment;
+                return curlen; /* eof? */
+            }
 
-    /* restore segment to read */
-    p_sys->playback.segment = peek_segment;
+            vlc_mutex_lock(&nsegment->lock);
 
-    vlc_mutex_unlock(&segment->lock);
+            if (len < nsegment->data->i_buffer)
+            {
+                memcpy(p_buff + curlen, nsegment->data->p_buffer, len);
+                curlen += len;
+            }
+            else
+            {
+                size_t i_nbuff = nsegment->data->i_buffer;
+                memcpy(p_buff + curlen, nsegment->data->p_buffer, i_nbuff);
+                curlen += i_nbuff;
+                len -= i_nbuff;
+
+                p_sys->playback.segment++;
+            }
 
-    return curlen;
+            vlc_mutex_unlock(&nsegment->lock);
+        }
+
+        /* restore segment to read */
+        p_sys->playback.segment = peek_segment;
+        return curlen;
+    }
 }
 
 static bool hls_MaySeek(stream_t *s)