[FFmpeg-cvslog] avformat/hls: Use an array instead of stream offset for stream mapping

Anssi Hannula git at videolan.org
Sat Aug 6 05:07:26 EEST 2016


ffmpeg | branch: release/3.1 | Anssi Hannula <anssi.hannula at iki.fi> | Wed Jul 27 23:29:16 2016 +0300| [309fa24f361f1c9d357f8d152c3b78718d2f870d] | committer: Michael Niedermayer

avformat/hls: Use an array instead of stream offset for stream mapping

This will be useful when the amount of streams per subdemuxer is not
known at hls_read_header time in a following commit.

(cherry picked from commit 9884f17e343b37aef442fafa05bd0113cdf47087)
Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>

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

 libavformat/hls.c | 59 +++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 38 insertions(+), 21 deletions(-)

diff --git a/libavformat/hls.c b/libavformat/hls.c
index 88402c2..59f5e38 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -98,7 +98,11 @@ struct playlist {
     int index;
     AVFormatContext *ctx;
     AVPacket pkt;
-    int stream_offset;
+
+    /* main demuxer streams associated with this playlist
+     * indexed by the subdemuxer stream indexes */
+    AVStream **main_streams;
+    int n_main_streams;
 
     int finished;
     enum PlaylistType type;
@@ -239,6 +243,7 @@ static void free_playlist_list(HLSContext *c)
         struct playlist *pls = c->playlists[i];
         free_segment_list(pls);
         free_init_section_list(pls);
+        av_freep(&pls->main_streams);
         av_freep(&pls->renditions);
         av_freep(&pls->id3_buf);
         av_dict_free(&pls->id3_initial);
@@ -1248,13 +1253,13 @@ restart:
 
         /* Check that the playlist is still needed before opening a new
          * segment. */
-        if (v->ctx && v->ctx->nb_streams &&
-            v->parent->nb_streams >= v->stream_offset + v->ctx->nb_streams) {
+        if (v->ctx && v->ctx->nb_streams) {
             v->needed = 0;
-            for (i = v->stream_offset; i < v->stream_offset + v->ctx->nb_streams;
-                i++) {
-                if (v->parent->streams[i]->discard < AVDISCARD_ALL)
+            for (i = 0; i < v->n_main_streams; i++) {
+                if (v->main_streams[i]->discard < AVDISCARD_ALL) {
                     v->needed = 1;
+                    break;
+                }
             }
         }
         if (!v->needed) {
@@ -1392,8 +1397,8 @@ static void add_metadata_from_renditions(AVFormatContext *s, struct playlist *pl
     int rend_idx = 0;
     int i;
 
-    for (i = 0; i < pls->ctx->nb_streams; i++) {
-        AVStream *st = s->streams[pls->stream_offset + i];
+    for (i = 0; i < pls->n_main_streams; i++) {
+        AVStream *st = pls->main_streams[i];
 
         if (st->codecpar->codec_type != type)
             continue;
@@ -1519,7 +1524,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 ret = 0, i, j;
     int highest_cur_seq_no = 0;
 
     c->ctx                = s;
@@ -1659,7 +1664,6 @@ static int hls_read_header(AVFormatContext *s)
         }
         pls->ctx->pb       = &pls->pb;
         pls->ctx->io_open  = nested_io_open;
-        pls->stream_offset = stream_offset;
 
         if ((ret = ff_copy_whiteblacklists(pls->ctx, s)) < 0)
             goto fail;
@@ -1699,13 +1703,13 @@ static int hls_read_header(AVFormatContext *s)
                 avpriv_set_pts_info(st, 33, 1, MPEG_TIME_BASE);
             else
                 avpriv_set_pts_info(st, ist->pts_wrap_bits, ist->time_base.num, ist->time_base.den);
+
+            dynarray_add(&pls->main_streams, &pls->n_main_streams, st);
         }
 
         add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_AUDIO);
         add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_VIDEO);
         add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_SUBTITLE);
-
-        stream_offset += pls->ctx->nb_streams;
     }
 
     /* Create a program for each variant */
@@ -1723,10 +1727,10 @@ static int hls_read_header(AVFormatContext *s)
             int is_shared = playlist_in_multiple_variants(c, pls);
             int k;
 
-            for (k = 0; k < pls->ctx->nb_streams; k++) {
-                struct AVStream *st = s->streams[pls->stream_offset + k];
+            for (k = 0; k < pls->n_main_streams; k++) {
+                struct AVStream *st = pls->main_streams[k];
 
-                av_program_add_stream_index(s, i, pls->stream_offset + k);
+                av_program_add_stream_index(s, i, st->index);
 
                 /* Set variant_bitrate for streams unique to this variant */
                 if (!is_shared && v->bandwidth)
@@ -1905,8 +1909,17 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt)
     /* If we got a packet, return it */
     if (minplaylist >= 0) {
         struct playlist *pls = c->playlists[minplaylist];
+
+        if (pls->pkt.stream_index >= pls->n_main_streams) {
+            av_log(s, AV_LOG_ERROR, "stream index inconsistency: index %d, %d main streams, %d subdemuxer streams\n",
+                   pls->pkt.stream_index, pls->n_main_streams, pls->ctx->nb_streams);
+            av_packet_unref(&pls->pkt);
+            reset_packet(&pls->pkt);
+            return AVERROR_BUG;
+        }
+
         *pkt = pls->pkt;
-        pkt->stream_index += pls->stream_offset;
+        pkt->stream_index = pls->main_streams[pls->pkt.stream_index]->index;
         reset_packet(&c->playlists[minplaylist]->pkt);
 
         if (pkt->dts != AV_NOPTS_VALUE)
@@ -1938,6 +1951,8 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
     HLSContext *c = s->priv_data;
     struct playlist *seek_pls = NULL;
     int i, seq_no;
+    int j;
+    int stream_subdemuxer_index;
     int64_t first_timestamp, seek_timestamp, duration;
 
     if ((flags & AVSEEK_FLAG_BYTE) ||
@@ -1961,10 +1976,12 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
     /* find the playlist with the specified stream */
     for (i = 0; i < c->n_playlists; i++) {
         struct playlist *pls = c->playlists[i];
-        if (stream_index >= pls->stream_offset &&
-            stream_index - pls->stream_offset < pls->ctx->nb_streams) {
-            seek_pls = pls;
-            break;
+        for (j = 0; j < pls->n_main_streams; j++) {
+            if (pls->main_streams[j] == s->streams[stream_index]) {
+                seek_pls = pls;
+                stream_subdemuxer_index = j;
+                break;
+            }
         }
     }
     /* check if the timestamp is valid for the playlist with the
@@ -1974,7 +1991,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
 
     /* set segment now so we do not need to search again below */
     seek_pls->cur_seq_no = seq_no;
-    seek_pls->seek_stream_index = stream_index - seek_pls->stream_offset;
+    seek_pls->seek_stream_index = stream_subdemuxer_index;
 
     for (i = 0; i < c->n_playlists; i++) {
         /* Reset reading */



More information about the ffmpeg-cvslog mailing list