[vlc-commits] commit: stream_filter/httplive.c: allow seeking for all segments. ( Jean-Paul Saman )
git at videolan.org
git at videolan.org
Wed Dec 22 09:59:12 CET 2010
vlc | branch: master | Jean-Paul Saman <jean-paul.saman at m2x.nl> | Tue Dec 21 09:33:18 2010 +0100| [68f1ff3b4abed6056aa5591f4e28217db1e16588] | committer: Jean-Paul Saman
stream_filter/httplive.c: allow seeking for all segments.
Seeking was only implemented for segments already downloaded. Now seeking
is also allowed for segments not downloaded.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=68f1ff3b4abed6056aa5591f4e28217db1e16588
---
modules/stream_filter/httplive.c | 102 +++++++++++++++++++++++++++++---------
1 files changed, 79 insertions(+), 23 deletions(-)
diff --git a/modules/stream_filter/httplive.c b/modules/stream_filter/httplive.c
index 4bacce6..c0ca84a 100644
--- a/modules/stream_filter/httplive.c
+++ b/modules/stream_filter/httplive.c
@@ -92,6 +92,9 @@ typedef struct
/* */
int current; /* current hls_stream */
int segment; /* current segment for downloading */
+ int seek; /* segment requested by seek (default -1) */
+ vlc_mutex_t lock_wait; /* protect segment download counter */
+ vlc_cond_t wait; /* some condition to wait on */
vlc_array_t *hls_stream;/* bandwidth adaptation */
stream_t *s;
@@ -813,9 +816,6 @@ static int parse_HTTPLiveStreaming(stream_t *s)
vlc_mutex_unlock(&hls->lock);
return VLC_EGENERIC;
}
-
- /* Determine next time to reload playlist */
- p_sys->wakeup = p_sys->last + (hls->duration * 2 * (mtime_t)1000000);
}
/* Stream size (approximate) */
@@ -931,8 +931,15 @@ static void* hls_Thread(vlc_object_t *p_this)
/* Is there a new segment to process? */
if (segment == NULL)
{
- if (!p_sys->b_live) break;
+ if (!p_sys->b_live)
+ {
+ p_sys->last = mdate();
+ p_sys->wakeup = p_sys->last + (2 * (mtime_t)1000000);
+ }
mwait(p_sys->wakeup);
+
+ /* reset download segment to current playback segment */
+ client->segment = p_sys->segment + 1;
}
else if (Download(client->s, hls, segment, &client->current) != VLC_SUCCESS)
{
@@ -940,7 +947,16 @@ static void* hls_Thread(vlc_object_t *p_this)
}
/* download succeeded */
- client->segment++;
+ /* determine next segment to download */
+ vlc_mutex_lock(&client->lock_wait);
+ if (client->seek >= 0)
+ {
+ client->segment = client->seek;
+ client->seek = -1;
+ }
+ else client->segment++;
+ vlc_cond_signal(&client->wait);
+ vlc_mutex_unlock(&client->lock_wait);
/* FIXME: Reread the m3u8 index file */
if (p_sys->b_live)
@@ -1234,9 +1250,13 @@ static int Open(vlc_object_t *p_this)
p_sys->thread->current = current;
p_sys->current = current;
p_sys->thread->segment = p_sys->segment;
+ p_sys->thread->seek = -1;
p_sys->segment = 0; /* reset to first segment */
p_sys->thread->s = s;
+ vlc_mutex_init(&p_sys->thread->lock_wait);
+ vlc_cond_init(&p_sys->thread->wait);
+
if (vlc_thread_create(p_sys->thread, "HTTP Live Streaming client",
hls_Thread, VLC_THREAD_PRIORITY_INPUT))
{
@@ -1265,8 +1285,15 @@ static void Close(vlc_object_t *p_this)
/* */
if (p_sys->thread)
{
+ vlc_mutex_lock(&p_sys->thread->lock_wait);
vlc_object_kill(p_sys->thread);
+ vlc_cond_signal(&p_sys->thread->wait);
+ vlc_mutex_unlock(&p_sys->thread->lock_wait);
+
+ /* */
vlc_thread_join(p_sys->thread);
+ vlc_mutex_destroy(&p_sys->thread->lock_wait);
+ vlc_cond_destroy(&p_sys->thread->wait);
vlc_object_release(p_sys->thread);
}
@@ -1302,8 +1329,8 @@ static segment_t *NextSegment(stream_t *s)
/* This segment is ready? */
if (segment->data != NULL)
{
- vlc_mutex_unlock(&hls->lock);
- return segment;
+ vlc_mutex_unlock(&hls->lock);
+ return segment;
}
}
vlc_mutex_unlock(&hls->lock);
@@ -1327,9 +1354,13 @@ static segment_t *NextSegment(stream_t *s)
break;
}
+ vlc_mutex_lock(&p_sys->thread->lock_wait);
+ int i_segment = p_sys->thread->segment;
+ vlc_mutex_unlock(&p_sys->thread->lock_wait);
+
/* This segment is ready? */
if ((segment->data != NULL) &&
- (p_sys->segment < p_sys->thread->segment))
+ (p_sys->segment < i_segment))
{
p_sys->current = i_stream;
vlc_mutex_unlock(&hls->lock);
@@ -1371,6 +1402,15 @@ static ssize_t hls_Read(stream_t *s, uint8_t *p_read, unsigned int i_read)
block_Release(segment->data);
segment->data = NULL;
}
+ else
+ { /* reset playback pointer to start of buffer */
+ uint64_t size = segment->size - segment->data->i_buffer;
+ if (size > 0)
+ {
+ segment->data->i_buffer += size;
+ segment->data->p_buffer -= size;
+ }
+ }
p_sys->segment++;
vlc_mutex_unlock(&segment->lock);
continue;
@@ -1470,7 +1510,8 @@ static bool hls_MaySeek(stream_t *s)
{
stream_sys_t *p_sys = s->p_sys;
- if (p_sys->hls_stream == NULL)
+ if ((p_sys->hls_stream == NULL) ||
+ (p_sys->thread == NULL))
return false;
hls_stream_t *hls = hls_Get(p_sys->hls_stream, p_sys->current);
@@ -1478,12 +1519,14 @@ static bool hls_MaySeek(stream_t *s)
if (p_sys->b_live)
{
- vlc_mutex_lock(&hls->lock);
- int count = vlc_array_count(hls->segments);
- bool may_seek = (p_sys->thread == NULL) ? false :
- (p_sys->thread->segment < count - 2);
- vlc_mutex_unlock(&hls->lock);
- return may_seek;
+ vlc_mutex_lock(&hls->lock);
+ int count = vlc_array_count(hls->segments);
+ vlc_mutex_unlock(&hls->lock);
+
+ vlc_mutex_lock(&p_sys->thread->lock_wait);
+ bool may_seek = (p_sys->thread->segment < (count - 2));
+ vlc_mutex_unlock(&p_sys->thread->lock_wait);
+ return may_seek;
}
return true;
}
@@ -1522,14 +1565,6 @@ static int segment_Seek(stream_t *s, uint64_t pos)
for (int n = 0; n < count; n++)
{
- /* FIXME: Seeking in segments not dowloaded is not supported. */
- if (n >= p_sys->thread->segment)
- {
- msg_Err(s, "seeking in segment not downloaded yet.");
- vlc_mutex_unlock(&hls->lock);
- return VLC_EGENERIC;
- }
-
segment_t *segment = vlc_array_item_at_index(hls->segments, n);
if (segment == NULL)
{
@@ -1578,6 +1613,27 @@ static int segment_Seek(stream_t *s, uint64_t pos)
}
}
vlc_mutex_unlock(&segment->lock);
+
+ /* start download at current playback segment */
+ if (p_sys->thread)
+ {
+ vlc_mutex_unlock(&hls->lock);
+
+ /* Wait for download to be finished */
+ vlc_mutex_lock(&p_sys->thread->lock_wait);
+ p_sys->thread->seek = p_sys->segment;
+ msg_Info(s, "seek to segment %d", p_sys->segment);
+ while ((p_sys->thread->seek != -1) ||
+ (p_sys->thread->segment - p_sys->segment < 3))
+ {
+ vlc_cond_wait(&p_sys->thread->wait, &p_sys->thread->lock_wait);
+ if (!vlc_object_alive (s) ||
+ s->b_error) break;
+ }
+ vlc_mutex_unlock(&p_sys->thread->lock_wait);
+
+ return VLC_SUCCESS;
+ }
}
vlc_mutex_unlock(&hls->lock);
More information about the vlc-commits
mailing list