[FFmpeg-cvslog] avformat/hls: support for seeking on event playlists

Vladlen Y. Koshelev git at videolan.org
Sun Apr 6 16:56:44 CEST 2014


ffmpeg | branch: master | Vladlen Y. Koshelev <vlad.kosh at gmail.com> | Sun Jan  5 02:18:12 2014 +0400| [cdbd9e218d44d2bcf14f5e07894fa4f72a4696e2] | committer: Anssi Hannula

avformat/hls: support for seeking on event playlists

This allows clients to seek between first played segment
and the last one in the live stream playlist with #EXT-X-PLAYLIST-TYPE:EVENT attribute.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=cdbd9e218d44d2bcf14f5e07894fa4f72a4696e2
---

 libavformat/hls.c |   29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index e50220b..0b4b58d 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -76,6 +76,12 @@ struct segment {
 
 struct rendition;
 
+enum PlaylistType {
+    PLS_TYPE_UNSPECIFIED,
+    PLS_TYPE_EVENT,
+    PLS_TYPE_VOD
+};
+
 /*
  * Each playlist has its own demuxer. If it currently is active,
  * it has an open AVIOContext too, and potentially an AVPacket
@@ -93,6 +99,7 @@ struct playlist {
     int stream_offset;
 
     int finished;
+    enum PlaylistType type;
     int64_t target_duration;
     int start_seq_no;
     int n_segments;
@@ -528,6 +535,7 @@ static int parse_playlist(HLSContext *c, const char *url,
     if (pls) {
         free_segment_list(pls);
         pls->finished = 0;
+        pls->type = PLS_TYPE_UNSPECIFIED;
     }
     while (!url_feof(in)) {
         read_chomp_line(in, line, sizeof(line));
@@ -564,6 +572,14 @@ static int parse_playlist(HLSContext *c, const char *url,
             if (ret < 0)
                 goto fail;
             pls->start_seq_no = atoi(ptr);
+        } else if (av_strstart(line, "#EXT-X-PLAYLIST-TYPE:", &ptr)) {
+            ret = ensure_playlist(c, &pls, url);
+            if (ret < 0)
+                goto fail;
+            if (!strcmp(ptr, "EVENT"))
+                pls->type = PLS_TYPE_EVENT;
+            else if (!strcmp(ptr, "VOD"))
+                pls->type = PLS_TYPE_VOD;
         } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) {
             if (pls)
                 pls->finished = 1;
@@ -1584,17 +1600,24 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
     HLSContext *c = s->priv_data;
     struct playlist *seek_pls = NULL;
     int i, seq_no;
-    int64_t seek_timestamp;
+    int64_t first_timestamp, seek_timestamp, duration;
 
-    if ((flags & AVSEEK_FLAG_BYTE) || !c->variants[0]->playlists[0]->finished)
+    if ((flags & AVSEEK_FLAG_BYTE) ||
+        !(c->variants[0]->playlists[0]->finished || c->variants[0]->playlists[0]->type == PLS_TYPE_EVENT))
         return AVERROR(ENOSYS);
 
+    first_timestamp = c->first_timestamp == AV_NOPTS_VALUE ?
+                      0 : c->first_timestamp;
+
     seek_timestamp = av_rescale_rnd(timestamp, AV_TIME_BASE,
                                     s->streams[stream_index]->time_base.den,
                                     flags & AVSEEK_FLAG_BACKWARD ?
                                     AV_ROUND_DOWN : AV_ROUND_UP);
 
-    if (s->duration < seek_timestamp)
+    duration = s->duration == AV_NOPTS_VALUE ?
+               0 : s->duration;
+
+    if (0 < duration && duration < seek_timestamp - first_timestamp)
         return AVERROR(EIO);
 
     /* find the playlist with the specified stream */



More information about the ffmpeg-cvslog mailing list