[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