From 83db3c84fa72e8d4d864ed796438ebfb2ee4bcc3 Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Thu, 28 Jul 2016 00:00:37 +0300 Subject: [PATCH] avformat/hls: Move stream propagation to a separate function Creation of main demuxer streams from subdemuxer streams is moved to update_streams_from_subdemuxer() which can be called repeatedly. There should be no functional changes. --- libavformat/hls.c | 134 ++++++++++++++++++++++++---------------------- 1 file changed, 69 insertions(+), 65 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 59f5e38f9f0..35ece98bb83 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1348,25 +1348,6 @@ reload: goto restart; } -static int playlist_in_multiple_variants(HLSContext *c, struct playlist *pls) -{ - int variant_count = 0; - int i, j; - - for (i = 0; i < c->n_variants && variant_count < 2; i++) { - struct variant *v = c->variants[i]; - - for (j = 0; j < v->n_playlists; j++) { - if (v->playlists[j] == pls) { - variant_count++; - break; - } - } - } - - return variant_count >= 2; -} - static void add_renditions_to_variant(HLSContext *c, struct variant *var, enum AVMediaType type, const char *group_id) { @@ -1520,11 +1501,65 @@ static int nested_io_open(AVFormatContext *s, AVIOContext **pb, const char *url, return AVERROR(EPERM); } +static void add_stream_to_programs(AVFormatContext *s, struct playlist *pls, AVStream *stream) +{ + HLSContext *c = s->priv_data; + int i, j; + int bandwidth = -1; + + for (i = 0; i < c->n_variants; i++) { + struct variant *v = c->variants[i]; + + for (j = 0; j < v->n_playlists; j++) { + if (v->playlists[j] != pls) + continue; + + av_program_add_stream_index(s, i, stream->index); + + if (bandwidth < 0) + bandwidth = v->bandwidth; + else if (bandwidth != v->bandwidth) + bandwidth = -1; /* stream in multiple variants with different bandwidths */ + } + } + + if (bandwidth >= 0) + av_dict_set_int(&stream->metadata, "variant_bitrate", bandwidth, 0); +} + +/* add new subdemuxer streams to our context, if any */ +static int update_streams_from_subdemuxer(AVFormatContext *s, struct playlist *pls) +{ + while (pls->n_main_streams < pls->ctx->nb_streams) { + int ist_idx = pls->n_main_streams; + AVStream *st = avformat_new_stream(s, NULL); + AVStream *ist = pls->ctx->streams[ist_idx]; + + if (!st) + return AVERROR(ENOMEM); + + st->id = pls->index; + + avcodec_parameters_copy(st->codecpar, ist->codecpar); + + if (pls->is_id3_timestamped) /* custom timestamps via id3 */ + 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_stream_to_programs(s, pls, st); + } + + return 0; +} + 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; + int ret = 0, i; int highest_cur_seq_no = 0; c->ctx = s; @@ -1600,6 +1635,17 @@ static int hls_read_header(AVFormatContext *s) add_renditions_to_variant(c, var, AVMEDIA_TYPE_SUBTITLE, var->subtitles_group); } + /* Create a program for each variant */ + for (i = 0; i < c->n_variants; i++) { + struct variant *v = c->variants[i]; + AVProgram *program; + + program = av_new_program(s, i); + if (!program) + goto fail; + av_dict_set_int(&program->metadata, "variant_bitrate", v->bandwidth, 0); + } + /* Select the starting segments */ for (i = 0; i < c->n_playlists; i++) { struct playlist *pls = c->playlists[i]; @@ -1688,57 +1734,15 @@ static int hls_read_header(AVFormatContext *s) av_log(s, AV_LOG_WARNING, "No expected HTTP requests have been made\n"); /* Create new AVStreams for each stream in this playlist */ - for (j = 0; j < pls->ctx->nb_streams; j++) { - AVStream *st = avformat_new_stream(s, NULL); - AVStream *ist = pls->ctx->streams[j]; - if (!st) { - ret = AVERROR(ENOMEM); - goto fail; - } - st->id = i; - - avcodec_parameters_copy(st->codecpar, pls->ctx->streams[j]->codecpar); - - if (pls->is_id3_timestamped) /* custom timestamps via id3 */ - 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); - } + ret = update_streams_from_subdemuxer(s, pls); + if (ret < 0) + goto fail; 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); } - /* Create a program for each variant */ - for (i = 0; i < c->n_variants; i++) { - struct variant *v = c->variants[i]; - AVProgram *program; - - program = av_new_program(s, i); - if (!program) - goto fail; - av_dict_set_int(&program->metadata, "variant_bitrate", v->bandwidth, 0); - - for (j = 0; j < v->n_playlists; j++) { - struct playlist *pls = v->playlists[j]; - int is_shared = playlist_in_multiple_variants(c, pls); - int k; - - for (k = 0; k < pls->n_main_streams; k++) { - struct AVStream *st = pls->main_streams[k]; - - av_program_add_stream_index(s, i, st->index); - - /* Set variant_bitrate for streams unique to this variant */ - if (!is_shared && v->bandwidth) - av_dict_set_int(&st->metadata, "variant_bitrate", v->bandwidth, 0); - } - } - } - return 0; fail: free_playlist_list(c); -- 2.39.2