avformat/hls: Sync starting segment across variants on live streams
authorAnssi Hannula <anssi.hannula@iki.fi>
Wed, 27 Jul 2016 19:52:44 +0000 (22:52 +0300)
committerAnssi Hannula <anssi.hannula@iki.fi>
Wed, 27 Jul 2016 22:24:57 +0000 (01:24 +0300)
This will avoid a large time difference between variants in the most
common case.

libavformat/hls.c

index 66f4550..88402c2 100644 (file)
@@ -1520,6 +1520,7 @@ static int hls_read_header(AVFormatContext *s)
     void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
     HLSContext *c = s->priv_data;
     int ret = 0, i, j, stream_offset = 0;
+    int highest_cur_seq_no = 0;
 
     c->ctx                = s;
     c->interrupt_callback = &s->interrupt_callback;
@@ -1594,6 +1595,17 @@ static int hls_read_header(AVFormatContext *s)
             add_renditions_to_variant(c, var, AVMEDIA_TYPE_SUBTITLE, var->subtitles_group);
     }
 
+    /* Select the starting segments */
+    for (i = 0; i < c->n_playlists; i++) {
+        struct playlist *pls = c->playlists[i];
+
+        if (pls->n_segments == 0)
+            continue;
+
+        pls->cur_seq_no = select_cur_seq_no(c, pls);
+        highest_cur_seq_no = FFMAX(highest_cur_seq_no, pls->cur_seq_no);
+    }
+
     /* Open the demuxer for each playlist */
     for (i = 0; i < c->n_playlists; i++) {
         struct playlist *pls = c->playlists[i];
@@ -1610,7 +1622,18 @@ static int hls_read_header(AVFormatContext *s)
         pls->index  = i;
         pls->needed = 1;
         pls->parent = s;
-        pls->cur_seq_no = select_cur_seq_no(c, pls);
+
+        /*
+         * If this is a live stream and this playlist looks like it is one segment
+         * behind, try to sync it up so that every substream starts at the same
+         * time position (so e.g. avformat_find_stream_info() will see packets from
+         * all active streams within the first few seconds). This is not very generic,
+         * though, as the sequence numbers are technically independent.
+         */
+        if (!pls->finished && pls->cur_seq_no == highest_cur_seq_no - 1 &&
+            highest_cur_seq_no < pls->start_seq_no + pls->n_segments) {
+            pls->cur_seq_no = highest_cur_seq_no;
+        }
 
         pls->read_buffer = av_malloc(INITIAL_BUFFER_SIZE);
         if (!pls->read_buffer){