diff options
author | Anssi Hannula <anssi.hannula@iki.fi> | 2016-07-27 23:29:16 +0300 |
---|---|---|
committer | Michael Niedermayer <michael@niedermayer.cc> | 2016-08-06 03:43:50 +0200 |
commit | 309fa24f361f1c9d357f8d152c3b78718d2f870d (patch) | |
tree | df4535b6cfe025dd28113d9575773a4e5fff5a26 | |
parent | 3586c68687035225451f57c4e422673cbe6d4377 (diff) | |
download | ffmpeg-309fa24f361f1c9d357f8d152c3b78718d2f870d.tar.gz |
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@niedermayer.cc>
-rw-r--r-- | libavformat/hls.c | 59 |
1 files changed, 38 insertions, 21 deletions
diff --git a/libavformat/hls.c b/libavformat/hls.c index 88402c2284..59f5e38f9f 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 */ |