[vlc-devel] [PATCH 25/48] hls: Report timing info

Hugo Beauzée-Luyssen beauze.h at gmail.com
Mon Jan 9 16:16:34 CET 2012


From: Luc Saillard <luc.saillard at sfr.com>

---
 include/vlc_stream.h             |    4 +++
 modules/stream_filter/httplive.c |   41 +++++++++++++++++++++++++++++++++++--
 src/input/input.c                |   29 ++++++++++++++++++++++++++
 3 files changed, 71 insertions(+), 3 deletions(-)

diff --git a/include/vlc_stream.h b/include/vlc_stream.h
index 61b1726..6d57c5b 100644
--- a/include/vlc_stream.h
+++ b/include/vlc_stream.h
@@ -97,6 +97,10 @@ enum stream_query_e
 
     STREAM_GET_SIZE,            /**< arg1= uint64_t *     res=cannot fail (0 if no sense)*/
 
+    /* LENGTH/TIME in microsecond, 0 if unknown */
+    STREAM_GET_LENGTH,           /* arg1= int64_t *      res=    */
+    STREAM_GET_TIME,             /* arg1= int64_t *      res=    */
+
     /* Special for direct access control from demuxer.
      * XXX: avoid using it by all means */
     STREAM_CONTROL_ACCESS,  /* arg1= int i_access_query, args   res: can fail
diff --git a/modules/stream_filter/httplive.c b/modules/stream_filter/httplive.c
index 40a124a..44a1409 100644
--- a/modules/stream_filter/httplive.c
+++ b/modules/stream_filter/httplive.c
@@ -69,7 +69,6 @@ typedef struct segment_s
     int         sequence;   /* unique sequence number */
     int         duration;   /* segment duration (seconds) */
     uint64_t    size;       /* segment size in bytes */
-    uint64_t    bandwidth;  /* bandwidth usage of segments (bits per second)*/
 
     char       *uri;
     char       *psz_key_path;         /* url key path */
@@ -89,6 +88,7 @@ typedef struct hls_stream_s
     uint64_t    bandwidth;  /* bandwidth usage of segments (bits per second)*/
     uint64_t    size;       /* stream length is calculated by taking the sum
                                foreach segment of (segment->duration * hls->bandwidth/8) */
+    uint64_t    length;     /* stream length in sec (sum of all segments duration) */
 
     vlc_array_t *segments;  /* list of segments */
     char        *uri;       /* uri to m3u8 */
@@ -126,6 +126,7 @@ struct stream_sys_t
     struct hls_playback_s
     {
         uint64_t    offset;     /* current offset in media */
+        uint64_t    time;       /* current position (us) in media */
         int         stream;     /* current hls_stream  */
         int         segment;    /* current segment for playback */
         vlc_mutex_t lock_wait;  /* protect segment download counter */
@@ -226,6 +227,7 @@ static hls_stream_t *hls_New(vlc_array_t *hls_stream, const int id, const uint64
     hls->bandwidth = bw;
     hls->duration = -1;/* unknown */
     hls->size = 0;
+    hls->length = 0;
     hls->sequence = 0; /* default is 0 */
     hls->version = 1;  /* default protocol version */
     hls->b_cache = true;
@@ -349,9 +351,9 @@ static segment_t *segment_New(hls_stream_t* hls, const int duration, const char
         return NULL;
 
     segment->duration = duration; /* seconds */
+    hls->length += duration;
     segment->size = 0; /* bytes */
     segment->sequence = 0;
-    segment->bandwidth = 0;
     segment->uri = uri?strdup(uri):NULL;
     segment->data = NULL;
     vlc_array_append(hls->segments, segment);
@@ -2014,6 +2016,7 @@ static int OpenWithPlaylist(stream_t *s, const char *m3u8_playlist)
 
     p_sys->download.stream = current;
     p_sys->playback.stream = current;
+    p_sys->playback.time = 0;
     p_sys->download.seek = -1;
 
     vlc_mutex_init(&p_sys->download.lock_wait);
@@ -2327,6 +2330,8 @@ again:
                 }
             }
             p_sys->playback.segment++;
+            /* FIXME: Perhaps we can rescan all previous playlist,
+             * to get a accurate time. */
             vlc_mutex_unlock(&segment->lock);
 
             /* signal download thread */
@@ -2353,6 +2358,10 @@ again:
             segment->data->p_buffer += len;
             copied += len;
             i_read -= len;
+
+            /* Update the playback time from the birate of the segment */
+            double bw = segment->size / segment->duration;
+            s->p_sys->playback.time += (double)(1000000 * len) / bw;
         }
         vlc_mutex_unlock(&segment->lock);
 
@@ -2528,6 +2537,23 @@ static uint64_t GetStreamSize(stream_t *s)
     return size;
 }
 
+static uint64_t GetStreamLenght(stream_t *s)
+{
+    stream_sys_t *p_sys = s->p_sys;
+
+    if (p_sys->b_live)
+        return 0;
+
+    hls_stream_t *hls = hls_Get(p_sys->hls_stream, p_sys->playback.stream);
+    if (hls == NULL) return 0;
+
+    vlc_mutex_lock(&hls->lock);
+    uint64_t duration = hls->length;
+    vlc_mutex_unlock(&hls->lock);
+
+    return duration;
+}
+
 static int segment_Seek(stream_t *s, const uint64_t pos)
 {
     stream_sys_t *p_sys = s->p_sys;
@@ -2540,6 +2566,7 @@ static int segment_Seek(stream_t *s, const uint64_t pos)
 
     bool b_found = false;
     uint64_t length = 0;
+    uint64_t time = 0;
     uint64_t size = hls->size;
     int count = vlc_array_count(hls->segments);
 
@@ -2554,6 +2581,7 @@ static int segment_Seek(stream_t *s, const uint64_t pos)
 
         vlc_mutex_lock(&segment->lock);
         length += segment->duration * (hls->bandwidth/8);
+        time += segment->duration;
         vlc_mutex_unlock(&segment->lock);
 
         if (!b_found && (pos <= length))
@@ -2561,6 +2589,7 @@ static int segment_Seek(stream_t *s, const uint64_t pos)
             if (count - n >= 3)
             {
                 p_sys->playback.segment = n;
+                p_sys->playback.time = time * 1000000;
                 b_found = true;
                 break;
             }
@@ -2668,13 +2697,19 @@ static int Control(stream_t *s, int i_query, va_list args)
                 if (segment_Seek(s, pos) == VLC_SUCCESS)
                 {
                     p_sys->playback.offset = pos;
-                    break;
+                    return VLC_SUCCESS;
                 }
             }
             return VLC_EGENERIC;
         case STREAM_GET_SIZE:
             *(va_arg (args, uint64_t *)) = GetStreamSize(s);
             break;
+        case STREAM_GET_LENGTH:
+            *(va_arg (args, uint64_t *)) = GetStreamLenght(s) * 1000000;
+            break;
+        case STREAM_GET_TIME:
+            *(va_arg (args, uint64_t *)) = p_sys->playback.time;
+            break;
         default:
             return VLC_EGENERIC;
     }
diff --git a/src/input/input.c b/src/input/input.c
index 9a8f9ae..2db0ebf 100644
--- a/src/input/input.c
+++ b/src/input/input.c
@@ -689,11 +689,25 @@ static void MainLoopInterface( input_thread_t *p_input )
     if( demux_Control( p_input->p->input.p_demux,
                        DEMUX_GET_TIME, &i_time ) )
         i_time = 0;
+    if (i_time == 0 && p_input->p->input.p_stream)
+    {
+        /* Perhaps is a stream filter, so get the value directly from the
+         * stream, and not from the demux plugin */
+        if( stream_Control( p_input->p->input.p_stream,
+                            STREAM_GET_TIME, &i_time ) )
+          i_time = 0;
+    }
     p_input->p->i_time = i_time;
 
     if( demux_Control( p_input->p->input.p_demux,
                        DEMUX_GET_LENGTH, &i_length ) )
         i_length = 0;
+    if (i_length == 0 && p_input->p->input.p_stream)
+    {
+        /* Perhaps is a stream filter, so get the value directly from the
+         * stream, and not from the demux plugin */
+        stream_Control( p_input->p->input.p_stream, STREAM_GET_LENGTH, &i_length );
+    }
 
     es_out_SetTimes( p_input->p->p_es_out, f_position, i_time, i_length );
 
@@ -1752,6 +1766,21 @@ static bool Control( input_thread_t *p_input,
                                             !p_input->p->b_fast_seek );
                 }
             }
+            if( i_ret && p_input->p->input.p_stream)
+            {
+                int64_t i_length, i_size;
+
+                /* Emulate it with a STREAM_SET_POSITION */
+                if( !stream_Control( p_input->p->input.p_stream,
+                                    STREAM_GET_LENGTH, &i_length ) && i_length > 0
+                 && !stream_Control( p_input->p->input.p_stream,
+                                    STREAM_GET_SIZE, &i_size ) && i_size > 0 )
+                {
+                    int64_t i_pos = ((double)i_time / (double)i_length) * i_size;
+                    i_ret = demux_Control( p_input->p->input.p_stream,
+                                            STREAM_SET_POSITION, i_pos );
+                }
+            }
             if( i_ret )
             {
                 msg_Warn( p_input, "INPUT_CONTROL_SET_TIME(_OFFSET) %"PRId64
-- 
1.7.8.3




More information about the vlc-devel mailing list