[FFmpeg-devel] [PATCH] hls demuxer: add option to defer parsing of variants
Rainer Hochecker
rainer.hochecker at googlemail.com
Tue Nov 28 00:23:16 EET 2017
2017-11-27 22:53 GMT+01:00 Anssi Hannula <anssi.hannula at iki.fi>:
> Hi,
>
> Rainer Hochecker kirjoitti 2017-11-26 12:46:
>>
>> fixed mem leak poined out by Steven
>>
>> ---
>> doc/demuxers.texi | 5 +
>> libavformat/hls.c | 304
>> ++++++++++++++++++++++++++++++++++++------------------
>> 2 files changed, 209 insertions(+), 100 deletions(-)
>>
> [...]
>>
>> +
>> + at item load_all_variants
>> +If 0, only the first variant/playlist is loaded on open. All other
>> variants
>> +get disabled and can be enabled by setting discard option in program.
>> +Default value is 1.
>> @end table
>
>
> If playlist download+parsing is indeed taking long enough time that this is
> warranted, I wonder if we should maybe just never read any variant playlists
> in read_header(), and instead set AVFMTCTX_NOHEADER.
> Then the user may discard AVPrograms right after open, before unneeded
> playlists are loaded+parsed.
>
> This would avoid having a separate option/mode for this.
>
> Any thoughts?
I actually tried it like this but somwhow did not like it because this
is different
to all other demuxers/formats. In general you open an input, call
find_stream_info,
and select a program. I did not like selecting the program between open and
find_stream_info.
>
>
>> @section image2
>> diff --git a/libavformat/hls.c b/libavformat/hls.c
>> index 786934af03..c42e0b0f95 100644
>> --- a/libavformat/hls.c
>> +++ b/libavformat/hls.c
>> @@ -112,6 +112,7 @@ struct playlist {
>> int n_segments;
>> struct segment **segments;
>> int needed, cur_needed;
>> + int parsed;
>> int cur_seq_no;
>> int64_t cur_seg_offset;
>> int64_t last_load_time;
>> @@ -206,6 +207,7 @@ typedef struct HLSContext {
>> int strict_std_compliance;
>> char *allowed_extensions;
>> int max_reload;
>> + int load_all_variants;
>> } HLSContext;
>
> [...]
>>
>> @@ -721,6 +726,7 @@ static int parse_playlist(HLSContext *c, const char
>> *url,
>> free_segment_list(pls);
>> pls->finished = 0;
>> pls->type = PLS_TYPE_UNSPECIFIED;
>> + pls->parsed = 1;
>> }
>
>
> That "pls->parsed = 1" is in the "reinit old playlist for re-parse" block,
> is that intentional?
>
> I'd think it should rather be at the end of the function alongside setting
> pls->last_load_time, so it is set to 1 whenever parsing has been done.
>
I put it at the beginning because I wanted to avoid that it gets tried again
on error.
>> while (!avio_feof(in)) {
>> read_chomp_line(in, line, sizeof(line));
>
> [...]
>>
>> @@ -1631,6 +1655,124 @@ static int hls_close(AVFormatContext *s)
>> return 0;
>> }
>>
>> +static int init_playlist(HLSContext *c, struct playlist *pls)
>> +{
>
>
> This init_playlist() seems to be mostly code moved from below, could you
> split the patch so that the first patch moves the code around but does not
> change behavior, and the second patch makes the actual changes (i.e. adds
> the option)?
>
> That would ease e.g. future bisecting.
Sure. At least I can try.
>
> [...]
>>
>> + return 0;
>> +}
>> +
>> static int hls_read_header(AVFormatContext *s)
>> {
>> void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
>> @@ -1663,6 +1805,9 @@ static int hls_read_header(AVFormatContext *s)
>> if ((ret = parse_playlist(c, s->filename, NULL, s->pb)) < 0)
>> goto fail;
>>
>> + /* first playlist was created, set it to parsed */
>> + c->variants[0]->playlists[0]->parsed = 1;
>> +
>
>
> I think parse_playlist() should set this when it parses something.
That was pitfall for my v1. The first playlist gets parsed with no
playlist given as argument.
fate failed because non-master playlists were not set to parsed.
>
>> if ((ret = save_avio_options(s)) < 0)
>> goto fail;
>>
>> @@ -1675,8 +1820,15 @@ static int hls_read_header(AVFormatContext *s)
>> goto fail;
>
> [...]
>>
>>
>> /* Select the starting segments */
>> for (i = 0; i < c->n_playlists; i++) {
>> struct playlist *pls = c->playlists[i];
>>
>> - if (pls->n_segments == 0)
>> + if (pls->n_segments == 0 && !pls->parsed)
>> continue;
>
>
> Why?
playlists not parsed are invalid, right? maybe n_segments is 0 for
not parsed playlists but this was no obvious to me.
>
>> pls->cur_seq_no = select_cur_seq_no(c, pls);
>> @@ -1736,97 +1892,9 @@ static int hls_read_header(AVFormatContext *s)
>> /* Open the demuxer for each playlist */
>> for (i = 0; i < c->n_playlists; i++) {
>> struct playlist *pls = c->playlists[i];
>> - AVInputFormat *in_fmt = NULL;
>> -
>
> [...]
>
> --
> Anssi Hannula
>
More information about the ffmpeg-devel
mailing list