Commit 492a92d4 authored by Jean-Paul Saman's avatar 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.
parent 3ae6e37e
...@@ -92,6 +92,9 @@ typedef struct ...@@ -92,6 +92,9 @@ typedef struct
/* */ /* */
int current; /* current hls_stream */ int current; /* current hls_stream */
int segment; /* current segment for downloading */ 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 */ vlc_array_t *hls_stream;/* bandwidth adaptation */
stream_t *s; stream_t *s;
...@@ -813,9 +816,6 @@ static int parse_HTTPLiveStreaming(stream_t *s) ...@@ -813,9 +816,6 @@ static int parse_HTTPLiveStreaming(stream_t *s)
vlc_mutex_unlock(&hls->lock); vlc_mutex_unlock(&hls->lock);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/* Determine next time to reload playlist */
p_sys->wakeup = p_sys->last + (hls->duration * 2 * (mtime_t)1000000);
} }
/* Stream size (approximate) */ /* Stream size (approximate) */
...@@ -931,8 +931,15 @@ static void* hls_Thread(vlc_object_t *p_this) ...@@ -931,8 +931,15 @@ static void* hls_Thread(vlc_object_t *p_this)
/* Is there a new segment to process? */ /* Is there a new segment to process? */
if (segment == NULL) 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); 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) else if (Download(client->s, hls, segment, &client->current) != VLC_SUCCESS)
{ {
...@@ -940,7 +947,16 @@ static void* hls_Thread(vlc_object_t *p_this) ...@@ -940,7 +947,16 @@ static void* hls_Thread(vlc_object_t *p_this)
} }
/* download succeeded */ /* 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 */ /* FIXME: Reread the m3u8 index file */
if (p_sys->b_live) if (p_sys->b_live)
...@@ -1234,9 +1250,13 @@ static int Open(vlc_object_t *p_this) ...@@ -1234,9 +1250,13 @@ static int Open(vlc_object_t *p_this)
p_sys->thread->current = current; p_sys->thread->current = current;
p_sys->current = current; p_sys->current = current;
p_sys->thread->segment = p_sys->segment; p_sys->thread->segment = p_sys->segment;
p_sys->thread->seek = -1;
p_sys->segment = 0; /* reset to first segment */ p_sys->segment = 0; /* reset to first segment */
p_sys->thread->s = s; 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", if (vlc_thread_create(p_sys->thread, "HTTP Live Streaming client",
hls_Thread, VLC_THREAD_PRIORITY_INPUT)) hls_Thread, VLC_THREAD_PRIORITY_INPUT))
{ {
...@@ -1265,8 +1285,15 @@ static void Close(vlc_object_t *p_this) ...@@ -1265,8 +1285,15 @@ static void Close(vlc_object_t *p_this)
/* */ /* */
if (p_sys->thread) if (p_sys->thread)
{ {
vlc_mutex_lock(&p_sys->thread->lock_wait);
vlc_object_kill(p_sys->thread); 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_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); vlc_object_release(p_sys->thread);
} }
...@@ -1302,8 +1329,8 @@ static segment_t *NextSegment(stream_t *s) ...@@ -1302,8 +1329,8 @@ static segment_t *NextSegment(stream_t *s)
/* This segment is ready? */ /* This segment is ready? */
if (segment->data != NULL) if (segment->data != NULL)
{ {
vlc_mutex_unlock(&hls->lock); vlc_mutex_unlock(&hls->lock);
return segment; return segment;
} }
} }
vlc_mutex_unlock(&hls->lock); vlc_mutex_unlock(&hls->lock);
...@@ -1327,9 +1354,13 @@ static segment_t *NextSegment(stream_t *s) ...@@ -1327,9 +1354,13 @@ static segment_t *NextSegment(stream_t *s)
break; 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? */ /* This segment is ready? */
if ((segment->data != NULL) && if ((segment->data != NULL) &&
(p_sys->segment < p_sys->thread->segment)) (p_sys->segment < i_segment))
goto segment_ok; goto segment_ok;
vlc_mutex_unlock(&hls->lock); vlc_mutex_unlock(&hls->lock);
...@@ -1373,6 +1404,15 @@ static ssize_t hls_Read(stream_t *s, uint8_t *p_read, unsigned int i_read) ...@@ -1373,6 +1404,15 @@ static ssize_t hls_Read(stream_t *s, uint8_t *p_read, unsigned int i_read)
block_Release(segment->data); block_Release(segment->data);
segment->data = NULL; 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++; p_sys->segment++;
vlc_mutex_unlock(&segment->lock); vlc_mutex_unlock(&segment->lock);
continue; continue;
...@@ -1472,7 +1512,8 @@ static bool hls_MaySeek(stream_t *s) ...@@ -1472,7 +1512,8 @@ static bool hls_MaySeek(stream_t *s)
{ {
stream_sys_t *p_sys = s->p_sys; 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; return false;
hls_stream_t *hls = hls_Get(p_sys->hls_stream, p_sys->current); hls_stream_t *hls = hls_Get(p_sys->hls_stream, p_sys->current);
...@@ -1480,12 +1521,14 @@ static bool hls_MaySeek(stream_t *s) ...@@ -1480,12 +1521,14 @@ static bool hls_MaySeek(stream_t *s)
if (p_sys->b_live) if (p_sys->b_live)
{ {
vlc_mutex_lock(&hls->lock); vlc_mutex_lock(&hls->lock);
int count = vlc_array_count(hls->segments); int count = vlc_array_count(hls->segments);
bool may_seek = (p_sys->thread == NULL) ? false : vlc_mutex_unlock(&hls->lock);
(p_sys->thread->segment < count - 2);
vlc_mutex_unlock(&hls->lock); vlc_mutex_lock(&p_sys->thread->lock_wait);
return may_seek; bool may_seek = (p_sys->thread->segment < (count - 2));
vlc_mutex_unlock(&p_sys->thread->lock_wait);
return may_seek;
} }
return true; return true;
} }
...@@ -1524,14 +1567,6 @@ static int segment_Seek(stream_t *s, uint64_t pos) ...@@ -1524,14 +1567,6 @@ static int segment_Seek(stream_t *s, uint64_t pos)
for (int n = 0; n < count; n++) 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); segment_t *segment = vlc_array_item_at_index(hls->segments, n);
if (segment == NULL) if (segment == NULL)
{ {
...@@ -1580,6 +1615,27 @@ static int segment_Seek(stream_t *s, uint64_t pos) ...@@ -1580,6 +1615,27 @@ static int segment_Seek(stream_t *s, uint64_t pos)
} }
} }
vlc_mutex_unlock(&segment->lock); 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); vlc_mutex_unlock(&hls->lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment