diff --git a/libavformat/hls.c b/libavformat/hls.c index 35ece98bb8..1ad08a4d40 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -98,6 +98,7 @@ struct playlist { int index; AVFormatContext *ctx; AVPacket pkt; + int has_noheader_flag; /* main demuxer streams associated with this playlist * indexed by the subdemuxer stream indexes */ @@ -1555,6 +1556,27 @@ static int update_streams_from_subdemuxer(AVFormatContext *s, struct playlist *p return 0; } +static void update_noheader_flag(AVFormatContext *s) +{ + HLSContext *c = s->priv_data; + int flag_needed = 0; + int i; + + for (i = 0; i < c->n_playlists; i++) { + struct playlist *pls = c->playlists[i]; + + if (pls->has_noheader_flag) { + flag_needed = 1; + break; + } + } + + if (flag_needed) + s->ctx_flags |= AVFMTCTX_NOHEADER; + else + s->ctx_flags &= ~AVFMTCTX_NOHEADER; +} + static int hls_read_header(AVFormatContext *s) { void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb; @@ -1725,14 +1747,23 @@ static int hls_read_header(AVFormatContext *s) pls->id3_deferred_extra = NULL; } - pls->ctx->ctx_flags &= ~AVFMTCTX_NOHEADER; - ret = avformat_find_stream_info(pls->ctx, NULL); - if (ret < 0) - goto fail; - if (pls->is_id3_timestamped == -1) av_log(s, AV_LOG_WARNING, "No expected HTTP requests have been made\n"); + /* + * For ID3 timestamped raw audio streams we need to detect the packet + * durations to calculate timestamps in fill_timing_for_id3_timestamped_stream(), + * but for other streams we can rely on our user calling avformat_find_stream_info() + * on us if they want to. + */ + if (pls->is_id3_timestamped) { + ret = avformat_find_stream_info(pls->ctx, NULL); + if (ret < 0) + goto fail; + } + + pls->has_noheader_flag = !!(pls->ctx->ctx_flags & AVFMTCTX_NOHEADER); + /* Create new AVStreams for each stream in this playlist */ ret = update_streams_from_subdemuxer(s, pls); if (ret < 0) @@ -1743,6 +1774,8 @@ static int hls_read_header(AVFormatContext *s) add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_SUBTITLE); } + update_noheader_flag(s); + return 0; fail: free_playlist_list(c); @@ -1914,6 +1947,19 @@ static int hls_read_packet(AVFormatContext *s, AVPacket *pkt) if (minplaylist >= 0) { struct playlist *pls = c->playlists[minplaylist]; + ret = update_streams_from_subdemuxer(s, pls); + if (ret < 0) { + av_packet_unref(&pls->pkt); + reset_packet(&pls->pkt); + return ret; + } + + /* check if noheader flag has been cleared by the subdemuxer */ + if (pls->has_noheader_flag && !(pls->ctx->ctx_flags & AVFMTCTX_NOHEADER)) { + pls->has_noheader_flag = 0; + update_noheader_flag(s); + } + 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);