[FFmpeg-devel] avformat/hlsenc: move init operations from write_header to init

Submitted by Steven Liu on Dec. 4, 2017, 9:48 a.m.

Details

Message ID 20171204094811.17172-1-lq@chinaffmpeg.org
State Accepted
Commit 08d28ee1823a7232541526770657dc49a218ad8f
Headers show

Commit Message

Steven Liu Dec. 4, 2017, 9:48 a.m.
Signed-off-by: Steven Liu <lq@chinaffmpeg.org>
---
 libavformat/hlsenc.c | 681 ++++++++++++++++++++++++++-------------------------
 1 file changed, 345 insertions(+), 336 deletions(-)

Comments

Dixit, Vishwanath Dec. 6, 2017, 5:16 a.m.
>

>

>

>On 12/4/17, 3:20 PM, "Steven Liu" <lq@chinaffmpeg.org> wrote:

>

>

>

>Signed-off-by: Steven Liu <lq@chinaffmpeg.org>

>

>---

>

> libavformat/hlsenc.c | 681 ++++++++++++++++++++++++++-------------------------

>

> 1 file changed, 345 insertions(+), 336 deletions(-)

>

>

>

>diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c

>

>index aeeed5bcd2..852663d28f 100644

>

>--- a/libavformat/hlsenc.c

>

>+++ b/libavformat/hlsenc.c

>

>@@ -1636,329 +1636,12 @@ static int hls_write_header(AVFormatContext *s)

>

> {

>

>     HLSContext *hls = s->priv_data;

>

>     int ret, i, j;

>

>-    char *p = NULL;

>

>-    const char *pattern = "%d.ts";

>

>-    const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt(s);

>

>-    const char *vtt_pattern = "%d.vtt";

>

>     AVDictionary *options = NULL;

>

>-    int basename_size = 0;

>

>-    int vtt_basename_size = 0, m3u8_name_size = 0;

>

>     VariantStream *vs = NULL;

>

>-    int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1;

>

>-

>

>-    ret = update_variant_stream_info(s);

>

>-    if (ret < 0) {

>

>-        av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n",

>

>-                ret);

>

>-        goto fail;

>

>-    }

>

>-

>

>-    //TODO: Updates needed to encryption functionality with periodic re-key when more than one variant streams are present

>

>-    if (hls->nb_varstreams > 1 && hls->flags & HLS_PERIODIC_REKEY) {

>

>-        ret = AVERROR(EINVAL);

>

>-        av_log(s, AV_LOG_ERROR, "Periodic re-key not supported when more than one variant streams are present\n");

>

>-        goto fail;

>

>-    }

>

>-

>

>-    if (hls->master_pl_name) {

>

>-        ret = update_master_pl_info(s);

>

>-        if (ret < 0) {

>

>-            av_log(s, AV_LOG_ERROR, "Master stream info update failed with status %x\n",

>

>-                    ret);

>

>-            goto fail;

>

>-        }

>

>-    }

>

>-

>

>-    if (hls->segment_type == SEGMENT_TYPE_FMP4) {

>

>-        pattern = "%d.m4s";

>

>-    }

>

>-    if ((hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) ||

>

>-        (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME)) {

>

>-        time_t t = time(NULL); // we will need it in either case

>

>-        if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) {

>

>-            hls->start_sequence = (int64_t)t;

>

>-        } else if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME) {

>

>-            char b[15];

>

>-            struct tm *p, tmbuf;

>

>-            if (!(p = localtime_r(&t, &tmbuf)))

>

>-                return AVERROR(ENOMEM);

>

>-            if (!strftime(b, sizeof(b), "%Y%m%d%H%M%S", p))

>

>-                return AVERROR(ENOMEM);

>

>-            hls->start_sequence = strtoll(b, NULL, 10);

>

>-        }

>

>-        av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence);

>

>-    }

>

> 

>

>     for (i = 0; i < hls->nb_varstreams; i++) {

>

>         vs = &hls->var_streams[i];

>

> 

>

>-    vs->sequence       = hls->start_sequence;

>

>-    hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE;

>

>-    vs->start_pts      = AV_NOPTS_VALUE;

>

>-    vs->end_pts      = AV_NOPTS_VALUE;

>

>-    vs->current_segment_final_filename_fmt[0] = '\0';

>

>-

>

>-    if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) {

>

>-        // Independent segments cannot be guaranteed when splitting by time

>

>-        hls->flags &= ~HLS_INDEPENDENT_SEGMENTS;

>

>-        av_log(s, AV_LOG_WARNING,

>

>-               "'split_by_time' and 'independent_segments' cannot be enabled together. "

>

>-               "Disabling 'independent_segments' flag\n");

>

>-    }

>

>-

>

>-    if (hls->flags & HLS_PROGRAM_DATE_TIME) {

>

>-        time_t now0;

>

>-        time(&now0);

>

>-        vs->initial_prog_date_time = now0;

>

>-    }

>

>-

>

>-    if (hls->format_options_str) {

>

>-        ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0);

>

>-        if (ret < 0) {

>

>-            av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n", hls->format_options_str);

>

>-            goto fail;

>

>-        }

>

>-    }

>

>-

>

>-    for (j = 0; j < vs->nb_streams; j++) {

>

>-        vs->has_video +=

>

>-            vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;

>

>-        vs->has_subtitle +=

>

>-            vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE;

>

>-    }

>

>-

>

>-    if (vs->has_video > 1)

>

>-        av_log(s, AV_LOG_WARNING,

>

>-               "More than a single video stream present, "

>

>-               "expect issues decoding it.\n");

>

>-

>

>-    if (hls->segment_type == SEGMENT_TYPE_FMP4) {

>

>-        vs->oformat = av_guess_format("mp4", NULL, NULL);

>

>-    } else {

>

>-        vs->oformat = av_guess_format("mpegts", NULL, NULL);

>

>-    }

>

>-

>

>-    if (!vs->oformat) {

>

>-        ret = AVERROR_MUXER_NOT_FOUND;

>

>-        goto fail;

>

>-    }

>

>-

>

>-    if(vs->has_subtitle) {

>

>-        vs->vtt_oformat = av_guess_format("webvtt", NULL, NULL);

>

>-        if (!vs->oformat) {

>

>-            ret = AVERROR_MUXER_NOT_FOUND;

>

>-            goto fail;

>

>-        }

>

>-    }

>

>-

>

>-    if (hls->segment_filename) {

>

>-        basename_size = strlen(hls->segment_filename) + 1;

>

>-        if (hls->nb_varstreams > 1) {

>

>-            basename_size += strlen(POSTFIX_PATTERN);

>

>-        }

>

>-        vs->basename = av_malloc(basename_size);

>

>-        if (!vs->basename) {

>

>-            ret = AVERROR(ENOMEM);

>

>-            goto fail;

>

>-        }

>

>-

>

>-        av_strlcpy(vs->basename, hls->segment_filename, basename_size);

>

>-    } else {

>

>-        if (hls->flags & HLS_SINGLE_FILE) {

>

>-            if (hls->segment_type == SEGMENT_TYPE_FMP4) {

>

>-                pattern = ".m4s";

>

>-            } else {

>

>-                pattern = ".ts";

>

>-            }

>

>-        }

>

>-

>

>-        if (hls->use_localtime) {

>

>-            basename_size = strlen(s->filename) + strlen(pattern_localtime_fmt) + 1;

>

>-        } else {

>

>-            basename_size = strlen(s->filename) + strlen(pattern) + 1;

>

>-        }

>

>-

>

>-        if (hls->nb_varstreams > 1) {

>

>-            basename_size += strlen(POSTFIX_PATTERN);

>

>-        }

>

>-

>

>-        vs->basename = av_malloc(basename_size);

>

>-        if (!vs->basename) {

>

>-            ret = AVERROR(ENOMEM);

>

>-            goto fail;

>

>-        }

>

>-

>

>-        av_strlcpy(vs->basename, s->filename, basename_size);

>

>-

>

>-        p = strrchr(vs->basename, '.');

>

>-        if (p)

>

>-            *p = '\0';

>

>-        if (hls->use_localtime) {

>

>-            av_strlcat(vs->basename, pattern_localtime_fmt, basename_size);

>

>-        } else {

>

>-            av_strlcat(vs->basename, pattern, basename_size);

>

>-        }

>

>-    }

>

>-

>

>-    m3u8_name_size = strlen(s->filename) + 1;

>

>-    if (hls->nb_varstreams > 1) {

>

>-        m3u8_name_size += strlen(POSTFIX_PATTERN);

>

>-    }

>

>-

>

>-    vs->m3u8_name = av_malloc(m3u8_name_size);

>

>-    if (!vs->m3u8_name ) {

>

>-        ret = AVERROR(ENOMEM);

>

>-        goto fail;

>

>-    }

>

>-

>

>-    av_strlcpy(vs->m3u8_name, s->filename, m3u8_name_size);

>

>-

>

>-    if (hls->nb_varstreams > 1) {

>

>-        ret = format_name(vs->basename, basename_size, i);

>

>-        if (ret < 0)

>

>-             goto fail;

>

>-        ret = format_name(vs->m3u8_name, m3u8_name_size, i);

>

>-        if (ret < 0)

>

>-             goto fail;

>

>-    }

>

>-

>

>-    if (hls->segment_type == SEGMENT_TYPE_FMP4) {

>

>-        if (hls->nb_varstreams > 1)

>

>-            fmp4_init_filename_len += strlen(POSTFIX_PATTERN);

>

>-        vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len);

>

>-        if (!vs->fmp4_init_filename ) {

>

>-            ret = AVERROR(ENOMEM);

>

>-            goto fail;

>

>-        }

>

>-        av_strlcpy(vs->fmp4_init_filename, hls->fmp4_init_filename,

>

>-                fmp4_init_filename_len);

>

>-        if (hls->nb_varstreams > 1) {

>

>-            ret = format_name(vs->fmp4_init_filename, fmp4_init_filename_len, i);

>

>-            if (ret < 0)

>

>-                 goto fail;

>

>-        }

>

>-

>

>-        if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) {

>

>-            fmp4_init_filename_len = strlen(vs->fmp4_init_filename) + 1;

>

>-            vs->base_output_dirname = av_malloc(fmp4_init_filename_len);

>

>-            if (!vs->base_output_dirname) {

>

>-                ret = AVERROR(ENOMEM);

>

>-                goto fail;

>

>-            }

>

>-            av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename,

>

>-                    fmp4_init_filename_len);

>

>-        } else {

>

>-            fmp4_init_filename_len = strlen(vs->m3u8_name) +

>

>-                                         strlen(vs->fmp4_init_filename) + 1;

>

>-

>

>-            vs->base_output_dirname = av_malloc(fmp4_init_filename_len);

>

>-            if (!vs->base_output_dirname) {

>

>-                ret = AVERROR(ENOMEM);

>

>-                goto fail;

>

>-            }

>

>-

>

>-            av_strlcpy(vs->base_output_dirname, vs->m3u8_name,

>

>-                    fmp4_init_filename_len);

>

>-            p = strrchr(vs->base_output_dirname, '/');

>

>-            if (p) {

>

>-                *(p + 1) = '\0';

>

>-                av_strlcat(vs->base_output_dirname, vs->fmp4_init_filename,

>

>-                        fmp4_init_filename_len);

>

>-            } else {

>

>-                av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename,

>

>-                        fmp4_init_filename_len);

>

>-            }

>

>-        }

>

>-    }

>

>-

>

>-    if (!hls->use_localtime) {

>

>-        ret = sls_flag_check_duration_size_index(hls);

>

>-        if (ret < 0) {

>

>-             goto fail;

>

>-        }

>

>-    } else {

>

>-        ret = sls_flag_check_duration_size(hls, vs);

>

>-        if (ret < 0) {

>

>-             goto fail;

>

>-        }

>

>-    }

>

>-    if(vs->has_subtitle) {

>

>-

>

>-        if (hls->flags & HLS_SINGLE_FILE)

>

>-            vtt_pattern = ".vtt";

>

>-        vtt_basename_size = strlen(s->filename) + strlen(vtt_pattern) + 1;

>

>-        if (hls->nb_varstreams > 1) {

>

>-            vtt_basename_size += strlen(POSTFIX_PATTERN);

>

>-        }

>

>-

>

>-        vs->vtt_basename = av_malloc(vtt_basename_size);

>

>-        if (!vs->vtt_basename) {

>

>-            ret = AVERROR(ENOMEM);

>

>-            goto fail;

>

>-        }

>

>-        vs->vtt_m3u8_name = av_malloc(vtt_basename_size);

>

>-        if (!vs->vtt_m3u8_name ) {

>

>-            ret = AVERROR(ENOMEM);

>

>-            goto fail;

>

>-        }

>

>-        av_strlcpy(vs->vtt_basename, s->filename, vtt_basename_size);

>

>-        p = strrchr(vs->vtt_basename, '.');

>

>-        if (p)

>

>-            *p = '\0';

>

>-

>

>-        if( hls->subtitle_filename ) {

>

>-            strcpy(vs->vtt_m3u8_name, hls->subtitle_filename);

>

>-        } else {

>

>-            strcpy(vs->vtt_m3u8_name, vs->vtt_basename);

>

>-            av_strlcat(vs->vtt_m3u8_name, "_vtt.m3u8", vtt_basename_size);

>

>-        }

>

>-        av_strlcat(vs->vtt_basename, vtt_pattern, vtt_basename_size);

>

>-

>

>-        if (hls->nb_varstreams > 1) {

>

>-            ret= format_name(vs->vtt_basename, vtt_basename_size, i);

>

>-            if (ret < 0)

>

>-                 goto fail;

>

>-            ret = format_name(vs->vtt_m3u8_name, vtt_basename_size, i);

>

>-            if (ret < 0)

>

>-                 goto fail;

>

>-        }

>

>-    }

>

>-

>

>-    if (hls->baseurl) {

>

>-        vs->baseurl = av_strdup(hls->baseurl);

>

>-        if (!vs->baseurl) {

>

>-            ret = AVERROR(ENOMEM);

>

>-            goto fail;

>

>-        }

>

>-    }

>

>-

>

>-    if ((hls->flags & HLS_SINGLE_FILE) && (hls->segment_type == SEGMENT_TYPE_FMP4)) {

>

>-        vs->fmp4_init_filename  = av_strdup(vs->basename);

>

>-        if (!vs->fmp4_init_filename) {

>

>-            ret = AVERROR(ENOMEM);

>

>-            goto fail;

>

>-        }

>

>-    }

>

>-

>

>-    if ((ret = hls_mux_init(s, vs)) < 0)

>

>-        goto fail;

>

>-

>

>-    if (hls->flags & HLS_APPEND_LIST) {

>

>-        parse_playlist(s, vs->m3u8_name, vs);

>

>-        vs->discontinuity = 1;

>

>-        if (hls->init_time > 0) {

>

>-            av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time,"

>

>-                   " hls_init_time value will have no effect\n");

>

>-            hls->init_time = 0;

>

>-            hls->recording_time = hls->time * AV_TIME_BASE;

>

>-        }

>

>-    }

>

>-

>

>-    if (hls->segment_type != SEGMENT_TYPE_FMP4 || hls->flags & HLS_SINGLE_FILE) {

>

>-        if ((ret = hls_start(s, vs)) < 0)

>

>-            goto fail;

>

>-    }

>

>-

>

>     av_dict_copy(&options, hls->format_options, 0);

>

>     ret = avformat_write_header(vs->avf, &options);

>

>     if (av_dict_count(options)) {

>

>@@ -1996,25 +1679,6 @@ static int hls_write_header(AVFormatContext *s)

>

>     }

>

> fail:

>

> 

>

>-    if (ret < 0) {

>

>-        av_freep(&hls->key_basename);

>

>-        for (i = 0; i < hls->nb_varstreams && hls->var_streams; i++) {

>

>-            vs = &hls->var_streams[i];

>

>-            av_freep(&vs->basename);

>

>-            av_freep(&vs->vtt_basename);

>

>-            av_freep(&vs->fmp4_init_filename);

>

>-            av_freep(&vs->m3u8_name);

>

>-            av_freep(&vs->vtt_m3u8_name);

>

>-            av_freep(&vs->streams);

>

>-            av_freep(&vs->baseurl);

>

>-            if (vs->avf)

>

>-                avformat_free_context(vs->avf);

>

>-            if (vs->vtt_avf)

>

>-                avformat_free_context(vs->vtt_avf);

>

>-        }

>

>-        av_freep(&hls->var_streams);

>

>-        av_freep(&hls->master_m3u8_url);

>

>-    }

>

>     return ret;

>

> }

>

> 

>

>@@ -2256,6 +1920,350 @@ static int hls_write_trailer(struct AVFormatContext *s)

>

>     return 0;

>

> }

>

> 

>

>+

>

>+static int hls_init(AVFormatContext *s)

>

>+{

>

>+    int ret = 0;

>

>+    int i = 0;

>

>+    int j = 0;

>

>+    HLSContext *hls = s->priv_data;

>

>+    const char *pattern = "%d.ts";

>

>+    VariantStream *vs = NULL;

>

>+    int basename_size = 0;

>

>+    const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt(s);

>

>+    const char *vtt_pattern = "%d.vtt";

>

>+    char *p = NULL;

>

>+    int vtt_basename_size = 0, m3u8_name_size = 0;

>

>+    int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1;

>

>+

>

>+    ret = update_variant_stream_info(s);

>

>+    if (ret < 0) {

>

>+        av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n",

>

>+                ret);

>

>+        goto fail;

>

>+    }

>

>+    //TODO: Updates needed to encryption functionality with periodic re-key when more than one variant streams are present

>

>+    if (hls->nb_varstreams > 1 && hls->flags & HLS_PERIODIC_REKEY) {

>

>+        ret = AVERROR(EINVAL);

>

>+        av_log(s, AV_LOG_ERROR, "Periodic re-key not supported when more than one variant streams are present\n");

>

>+        goto fail;

>

>+    }

>

>+

>

>+    if (hls->master_pl_name) {

>

>+        ret = update_master_pl_info(s);

>

>+        if (ret < 0) {

>

>+            av_log(s, AV_LOG_ERROR, "Master stream info update failed with status %x\n",

>

>+                    ret);

>

>+            goto fail;

>

>+        }

>

>+    }

>

>+

>

>+    if (hls->segment_type == SEGMENT_TYPE_FMP4) {

>

>+        pattern = "%d.m4s";

>

>+    }

>

>+    if ((hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) ||

>

>+        (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME)) {

>

>+        time_t t = time(NULL); // we will need it in either case

>

>+        if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) {

>

>+            hls->start_sequence = (int64_t)t;

>

>+        } else if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME) {

>

>+            char b[15];

>

>+            struct tm *p, tmbuf;

>

>+            if (!(p = localtime_r(&t, &tmbuf)))

>

>+                return AVERROR(ENOMEM);

>

>+            if (!strftime(b, sizeof(b), "%Y%m%d%H%M%S", p))

>

>+                return AVERROR(ENOMEM);

>

>+            hls->start_sequence = strtoll(b, NULL, 10);

>

>+        }

>

>+        av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence);

>

>+    }

>

>+

>

>+    hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE;

>

>+    for (i = 0; i < hls->nb_varstreams; i++) {

>

>+        vs = &hls->var_streams[i];

>

>+        vs->sequence       = hls->start_sequence;

>

>+        vs->start_pts      = AV_NOPTS_VALUE;

>

>+        vs->end_pts      = AV_NOPTS_VALUE;

>

>+        vs->current_segment_final_filename_fmt[0] = '\0';

>

>+

>

>+        if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) {

>

>+            // Independent segments cannot be guaranteed when splitting by time

>

>+            hls->flags &= ~HLS_INDEPENDENT_SEGMENTS;

>

>+            av_log(s, AV_LOG_WARNING,

>

>+                   "'split_by_time' and 'independent_segments' cannot be enabled together. "

>

>+                   "Disabling 'independent_segments' flag\n");

>

>+        }

>

>+

>

>+        if (hls->flags & HLS_PROGRAM_DATE_TIME) {

>

>+            time_t now0;

>

>+            time(&now0);

>

>+            vs->initial_prog_date_time = now0;

>

>+        }

>

>+        if (hls->format_options_str) {

>

>+            ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0);

>

>+            if (ret < 0) {

>

>+                av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n", hls->format_options_str);

>

>+                goto fail;

>

>+            }

>

>+        }

>

>+

>

>+        for (j = 0; j < vs->nb_streams; j++) {

>

>+            vs->has_video += vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;

>

>+            vs->has_subtitle += vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE;

>

>+        }

>

>+

>

>+        if (vs->has_video > 1)

>

>+            av_log(s, AV_LOG_WARNING, "More than a single video stream present, expect issues decoding it.\n");

>

>+        if (hls->segment_type == SEGMENT_TYPE_FMP4) {

>

>+            vs->oformat = av_guess_format("mp4", NULL, NULL);

>

>+        } else {

>

>+            vs->oformat = av_guess_format("mpegts", NULL, NULL);

>

>+        }

>

>+

>

>+        if (!vs->oformat) {

>

>+            ret = AVERROR_MUXER_NOT_FOUND;

>

>+            goto fail;

>

>+        }

>

>+

>

>+        if (vs->has_subtitle) {

>

>+            vs->vtt_oformat = av_guess_format("webvtt", NULL, NULL);

>

>+            if (!vs->oformat) {

>

>+                ret = AVERROR_MUXER_NOT_FOUND;

>

>+                goto fail;

>

>+            }

>

>+        }

>

>+        if (hls->segment_filename) {

>

>+            basename_size = strlen(hls->segment_filename) + 1;

>

>+            if (hls->nb_varstreams > 1) {

>

>+                basename_size += strlen(POSTFIX_PATTERN);

>

>+            }

>

>+            vs->basename = av_malloc(basename_size);

>

>+            if (!vs->basename) {

>

>+                ret = AVERROR(ENOMEM);

>

>+                goto fail;

>

>+            }

>

>+

>

>+            av_strlcpy(vs->basename, hls->segment_filename, basename_size);

>

>+        } else {

>

>+            if (hls->flags & HLS_SINGLE_FILE) {

>

>+                if (hls->segment_type == SEGMENT_TYPE_FMP4) {

>

>+                    pattern = ".m4s";

>

>+                } else {

>

>+                    pattern = ".ts";

>

>+                }

>

>+            }

>

>+

>

>+            if (hls->use_localtime) {

>

>+                basename_size = strlen(s->filename) + strlen(pattern_localtime_fmt) + 1;

>

>+            } else {

>

>+                basename_size = strlen(s->filename) + strlen(pattern) + 1;

>

>+            }

>

>+

>

>+            if (hls->nb_varstreams > 1) {

>

>+                basename_size += strlen(POSTFIX_PATTERN);

>

>+            }

>

>+

>

>+            vs->basename = av_malloc(basename_size);

>

>+            if (!vs->basename) {

>

>+                ret = AVERROR(ENOMEM);

>

>+                goto fail;

>

>+            }

>

>+

>

>+            av_strlcpy(vs->basename, s->filename, basename_size);

>

>+

>

>+            p = strrchr(vs->basename, '.');

>

>+            if (p)

>

>+                *p = '\0';

>

>+            if (hls->use_localtime) {

>

>+                av_strlcat(vs->basename, pattern_localtime_fmt, basename_size);

>

>+            } else {

>

>+                av_strlcat(vs->basename, pattern, basename_size);

>

>+            }

>

>+        }

>

>+

>

>+        m3u8_name_size = strlen(s->filename) + 1;

>

>+        if (hls->nb_varstreams > 1) {

>

>+            m3u8_name_size += strlen(POSTFIX_PATTERN);

>

>+        }

>

>+

>

>+        vs->m3u8_name = av_malloc(m3u8_name_size);

>

>+        if (!vs->m3u8_name ) {

>

>+            ret = AVERROR(ENOMEM);

>

>+            goto fail;

>

>+        }

>

>+

>

>+        av_strlcpy(vs->m3u8_name, s->filename, m3u8_name_size);

>

>+

>

>+        if (hls->nb_varstreams > 1) {

>

>+            ret = format_name(vs->basename, basename_size, i);

>

>+            if (ret < 0)

>

>+                goto fail;

>

>+            ret = format_name(vs->m3u8_name, m3u8_name_size, i);

>

>+            if (ret < 0)

>

>+                goto fail;

>

>+        }

>

>+

>

>+        if (hls->segment_type == SEGMENT_TYPE_FMP4) {

>

>+            if (hls->nb_varstreams > 1)

>

>+                fmp4_init_filename_len += strlen(POSTFIX_PATTERN);

>

>+            vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len);

>

>+            if (!vs->fmp4_init_filename ) {

>

>+                ret = AVERROR(ENOMEM);

>

>+                goto fail;

>

>+            }

>

>+            av_strlcpy(vs->fmp4_init_filename, hls->fmp4_init_filename,

>

>+                       fmp4_init_filename_len);

>

>+            if (hls->nb_varstreams > 1) {

>

>+                ret = format_name(vs->fmp4_init_filename, fmp4_init_filename_len, i);

>

>+                if (ret < 0)

>

>+                    goto fail;

>

>+            }

>

>+

>

>+            if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) {

>

>+                fmp4_init_filename_len = strlen(vs->fmp4_init_filename) + 1;

>

>+                vs->base_output_dirname = av_malloc(fmp4_init_filename_len);

>

>+                if (!vs->base_output_dirname) {

>

>+                    ret = AVERROR(ENOMEM);

>

>+                    goto fail;

>

>+                }

>

>+                av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename,

>

>+                           fmp4_init_filename_len);

>

>+            } else {

>

>+                fmp4_init_filename_len = strlen(vs->m3u8_name) +

>

>+                    strlen(vs->fmp4_init_filename) + 1;

>

>+

>

>+                vs->base_output_dirname = av_malloc(fmp4_init_filename_len);

>

>+                if (!vs->base_output_dirname) {

>

>+                    ret = AVERROR(ENOMEM);

>

>+                    goto fail;

>

>+                }

>

>+

>

>+                av_strlcpy(vs->base_output_dirname, vs->m3u8_name,

>

>+                           fmp4_init_filename_len);

>

>+                p = strrchr(vs->base_output_dirname, '/');

>

>+                if (p) {

>

>+                    *(p + 1) = '\0';

>

>+                    av_strlcat(vs->base_output_dirname, vs->fmp4_init_filename,

>

>+                               fmp4_init_filename_len);

>

>+                } else {

>

>+                    av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename,

>

>+                               fmp4_init_filename_len);

>

>+                }

>

>+            }

>

>+        }

>

>+

>

>+        if (!hls->use_localtime) {

>

>+            ret = sls_flag_check_duration_size_index(hls);

>

>+            if (ret < 0) {

>

>+                goto fail;

>

>+            }

>

>+        } else {

>

>+            ret = sls_flag_check_duration_size(hls, vs);

>

>+            if (ret < 0) {

>

>+                goto fail;

>

>+            }

>

>+        }

>

>+        if (vs->has_subtitle) {

>

>+

>

>+            if (hls->flags & HLS_SINGLE_FILE)

>

>+                vtt_pattern = ".vtt";

>

>+            vtt_basename_size = strlen(s->filename) + strlen(vtt_pattern) + 1;

>

>+            if (hls->nb_varstreams > 1) {

>

>+                vtt_basename_size += strlen(POSTFIX_PATTERN);

>

>+            }

>

>+

>

>+            vs->vtt_basename = av_malloc(vtt_basename_size);

>

>+            if (!vs->vtt_basename) {

>

>+                ret = AVERROR(ENOMEM);

>

>+                goto fail;

>

>+            }

>

>+            vs->vtt_m3u8_name = av_malloc(vtt_basename_size);

>

>+            if (!vs->vtt_m3u8_name ) {

>

>+                ret = AVERROR(ENOMEM);

>

>+                goto fail;

>

>+            }

>

>+            av_strlcpy(vs->vtt_basename, s->filename, vtt_basename_size);

>

>+            p = strrchr(vs->vtt_basename, '.');

>

>+            if (p)

>

>+                *p = '\0';

>

>+

>

>+            if ( hls->subtitle_filename ) {

>

>+                strcpy(vs->vtt_m3u8_name, hls->subtitle_filename);

>

>+            } else {

>

>+                strcpy(vs->vtt_m3u8_name, vs->vtt_basename);

>

>+                av_strlcat(vs->vtt_m3u8_name, "_vtt.m3u8", vtt_basename_size);

>

>+            }

>

>+            av_strlcat(vs->vtt_basename, vtt_pattern, vtt_basename_size);

>

>+

>

>+            if (hls->nb_varstreams > 1) {

>

>+                ret= format_name(vs->vtt_basename, vtt_basename_size, i);

>

>+                if (ret < 0)

>

>+                    goto fail;

>

>+                ret = format_name(vs->vtt_m3u8_name, vtt_basename_size, i);

>

>+                if (ret < 0)

>

>+                    goto fail;

>

>+            }

>

>+        }

>

>+

>

>+        if (hls->baseurl) {

>

>+            vs->baseurl = av_strdup(hls->baseurl);

>

>+            if (!vs->baseurl) {

>

>+                ret = AVERROR(ENOMEM);

>

>+                goto fail;

>

>+            }

>

>+        }

>

>+

>

>+        if ((hls->flags & HLS_SINGLE_FILE) && (hls->segment_type == SEGMENT_TYPE_FMP4)) {

>

>+            vs->fmp4_init_filename  = av_strdup(vs->basename);

>

>+            if (!vs->fmp4_init_filename) {

>

>+                ret = AVERROR(ENOMEM);

>

>+                goto fail;

>

>+            }

>

>+        }

>

>+        if ((ret = hls_mux_init(s, vs)) < 0)

>

>+            goto fail;

>

>+

>

>+        if (hls->flags & HLS_APPEND_LIST) {

>

>+            parse_playlist(s, vs->m3u8_name, vs);

>

>+            vs->discontinuity = 1;

>

>+            if (hls->init_time > 0) {

>

>+                av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time,"

>

>+                       " hls_init_time value will have no effect\n");

>

>+                hls->init_time = 0;

>

>+                hls->recording_time = hls->time * AV_TIME_BASE;

>

>+            }

>

>+        }

>

>+

>

>+        if (hls->segment_type != SEGMENT_TYPE_FMP4 || hls->flags & HLS_SINGLE_FILE) {

>

>+            if ((ret = hls_start(s, vs)) < 0)

>

>+                goto fail;

>

>+        }

>

>+    }

>

>+

>

>+fail:

>

>+    if (ret < 0) {

>

>+        av_freep(&hls->key_basename);

>

>+        for (i = 0; i < hls->nb_varstreams && hls->var_streams; i++) {

>

>+            vs = &hls->var_streams[i];

>

>+            av_freep(&vs->basename);

>

>+            av_freep(&vs->vtt_basename);

>

>+            av_freep(&vs->fmp4_init_filename);

>

>+            av_freep(&vs->m3u8_name);

>

>+            av_freep(&vs->vtt_m3u8_name);

>

>+            av_freep(&vs->streams);

>

>+            av_freep(&vs->baseurl);

>

>+            if (vs->avf)

>

>+                avformat_free_context(vs->avf);

>

>+            if (vs->vtt_avf)

>

>+                avformat_free_context(vs->vtt_avf);

>

>+        }

>

>+        av_freep(&hls->var_streams);

>

>+        av_freep(&hls->master_m3u8_url);

>

>+    }

>

>+

>

>+    return ret;

>

>+}

>

>+

>

> #define OFFSET(x) offsetof(HLSContext, x)

>

> #define E AV_OPT_FLAG_ENCODING_PARAM

>

> static const AVOption options[] = {

>

>@@ -2332,6 +2340,7 @@ AVOutputFormat ff_hls_muxer = {

>

>     .video_codec    = AV_CODEC_ID_H264,

>

>     .subtitle_codec = AV_CODEC_ID_WEBVTT,

>

>     .flags          = AVFMT_NOFILE | AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,

>

>+    .init           = hls_init,

>

>     .write_header   = hls_write_header,

>

>     .write_packet   = hls_write_packet,

>

>     .write_trailer  = hls_write_trailer,

>

>-- 

>

>2.13.6 (Apple Git-96)

>

>

>

>

>

>

>

>_______________________________________________

>

>ffmpeg-devel mailing list

>

>ffmpeg-devel@ffmpeg.org

>

>http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

>

>

>

>

LGTM

Patch hide | download patch | download mbox

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index aeeed5bcd2..852663d28f 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -1636,329 +1636,12 @@  static int hls_write_header(AVFormatContext *s)
 {
     HLSContext *hls = s->priv_data;
     int ret, i, j;
-    char *p = NULL;
-    const char *pattern = "%d.ts";
-    const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt(s);
-    const char *vtt_pattern = "%d.vtt";
     AVDictionary *options = NULL;
-    int basename_size = 0;
-    int vtt_basename_size = 0, m3u8_name_size = 0;
     VariantStream *vs = NULL;
-    int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1;
-
-    ret = update_variant_stream_info(s);
-    if (ret < 0) {
-        av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n",
-                ret);
-        goto fail;
-    }
-
-    //TODO: Updates needed to encryption functionality with periodic re-key when more than one variant streams are present
-    if (hls->nb_varstreams > 1 && hls->flags & HLS_PERIODIC_REKEY) {
-        ret = AVERROR(EINVAL);
-        av_log(s, AV_LOG_ERROR, "Periodic re-key not supported when more than one variant streams are present\n");
-        goto fail;
-    }
-
-    if (hls->master_pl_name) {
-        ret = update_master_pl_info(s);
-        if (ret < 0) {
-            av_log(s, AV_LOG_ERROR, "Master stream info update failed with status %x\n",
-                    ret);
-            goto fail;
-        }
-    }
-
-    if (hls->segment_type == SEGMENT_TYPE_FMP4) {
-        pattern = "%d.m4s";
-    }
-    if ((hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) ||
-        (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME)) {
-        time_t t = time(NULL); // we will need it in either case
-        if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) {
-            hls->start_sequence = (int64_t)t;
-        } else if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME) {
-            char b[15];
-            struct tm *p, tmbuf;
-            if (!(p = localtime_r(&t, &tmbuf)))
-                return AVERROR(ENOMEM);
-            if (!strftime(b, sizeof(b), "%Y%m%d%H%M%S", p))
-                return AVERROR(ENOMEM);
-            hls->start_sequence = strtoll(b, NULL, 10);
-        }
-        av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence);
-    }
 
     for (i = 0; i < hls->nb_varstreams; i++) {
         vs = &hls->var_streams[i];
 
-    vs->sequence       = hls->start_sequence;
-    hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE;
-    vs->start_pts      = AV_NOPTS_VALUE;
-    vs->end_pts      = AV_NOPTS_VALUE;
-    vs->current_segment_final_filename_fmt[0] = '\0';
-
-    if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) {
-        // Independent segments cannot be guaranteed when splitting by time
-        hls->flags &= ~HLS_INDEPENDENT_SEGMENTS;
-        av_log(s, AV_LOG_WARNING,
-               "'split_by_time' and 'independent_segments' cannot be enabled together. "
-               "Disabling 'independent_segments' flag\n");
-    }
-
-    if (hls->flags & HLS_PROGRAM_DATE_TIME) {
-        time_t now0;
-        time(&now0);
-        vs->initial_prog_date_time = now0;
-    }
-
-    if (hls->format_options_str) {
-        ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0);
-        if (ret < 0) {
-            av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n", hls->format_options_str);
-            goto fail;
-        }
-    }
-
-    for (j = 0; j < vs->nb_streams; j++) {
-        vs->has_video +=
-            vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;
-        vs->has_subtitle +=
-            vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE;
-    }
-
-    if (vs->has_video > 1)
-        av_log(s, AV_LOG_WARNING,
-               "More than a single video stream present, "
-               "expect issues decoding it.\n");
-
-    if (hls->segment_type == SEGMENT_TYPE_FMP4) {
-        vs->oformat = av_guess_format("mp4", NULL, NULL);
-    } else {
-        vs->oformat = av_guess_format("mpegts", NULL, NULL);
-    }
-
-    if (!vs->oformat) {
-        ret = AVERROR_MUXER_NOT_FOUND;
-        goto fail;
-    }
-
-    if(vs->has_subtitle) {
-        vs->vtt_oformat = av_guess_format("webvtt", NULL, NULL);
-        if (!vs->oformat) {
-            ret = AVERROR_MUXER_NOT_FOUND;
-            goto fail;
-        }
-    }
-
-    if (hls->segment_filename) {
-        basename_size = strlen(hls->segment_filename) + 1;
-        if (hls->nb_varstreams > 1) {
-            basename_size += strlen(POSTFIX_PATTERN);
-        }
-        vs->basename = av_malloc(basename_size);
-        if (!vs->basename) {
-            ret = AVERROR(ENOMEM);
-            goto fail;
-        }
-
-        av_strlcpy(vs->basename, hls->segment_filename, basename_size);
-    } else {
-        if (hls->flags & HLS_SINGLE_FILE) {
-            if (hls->segment_type == SEGMENT_TYPE_FMP4) {
-                pattern = ".m4s";
-            } else {
-                pattern = ".ts";
-            }
-        }
-
-        if (hls->use_localtime) {
-            basename_size = strlen(s->filename) + strlen(pattern_localtime_fmt) + 1;
-        } else {
-            basename_size = strlen(s->filename) + strlen(pattern) + 1;
-        }
-
-        if (hls->nb_varstreams > 1) {
-            basename_size += strlen(POSTFIX_PATTERN);
-        }
-
-        vs->basename = av_malloc(basename_size);
-        if (!vs->basename) {
-            ret = AVERROR(ENOMEM);
-            goto fail;
-        }
-
-        av_strlcpy(vs->basename, s->filename, basename_size);
-
-        p = strrchr(vs->basename, '.');
-        if (p)
-            *p = '\0';
-        if (hls->use_localtime) {
-            av_strlcat(vs->basename, pattern_localtime_fmt, basename_size);
-        } else {
-            av_strlcat(vs->basename, pattern, basename_size);
-        }
-    }
-
-    m3u8_name_size = strlen(s->filename) + 1;
-    if (hls->nb_varstreams > 1) {
-        m3u8_name_size += strlen(POSTFIX_PATTERN);
-    }
-
-    vs->m3u8_name = av_malloc(m3u8_name_size);
-    if (!vs->m3u8_name ) {
-        ret = AVERROR(ENOMEM);
-        goto fail;
-    }
-
-    av_strlcpy(vs->m3u8_name, s->filename, m3u8_name_size);
-
-    if (hls->nb_varstreams > 1) {
-        ret = format_name(vs->basename, basename_size, i);
-        if (ret < 0)
-             goto fail;
-        ret = format_name(vs->m3u8_name, m3u8_name_size, i);
-        if (ret < 0)
-             goto fail;
-    }
-
-    if (hls->segment_type == SEGMENT_TYPE_FMP4) {
-        if (hls->nb_varstreams > 1)
-            fmp4_init_filename_len += strlen(POSTFIX_PATTERN);
-        vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len);
-        if (!vs->fmp4_init_filename ) {
-            ret = AVERROR(ENOMEM);
-            goto fail;
-        }
-        av_strlcpy(vs->fmp4_init_filename, hls->fmp4_init_filename,
-                fmp4_init_filename_len);
-        if (hls->nb_varstreams > 1) {
-            ret = format_name(vs->fmp4_init_filename, fmp4_init_filename_len, i);
-            if (ret < 0)
-                 goto fail;
-        }
-
-        if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) {
-            fmp4_init_filename_len = strlen(vs->fmp4_init_filename) + 1;
-            vs->base_output_dirname = av_malloc(fmp4_init_filename_len);
-            if (!vs->base_output_dirname) {
-                ret = AVERROR(ENOMEM);
-                goto fail;
-            }
-            av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename,
-                    fmp4_init_filename_len);
-        } else {
-            fmp4_init_filename_len = strlen(vs->m3u8_name) +
-                                         strlen(vs->fmp4_init_filename) + 1;
-
-            vs->base_output_dirname = av_malloc(fmp4_init_filename_len);
-            if (!vs->base_output_dirname) {
-                ret = AVERROR(ENOMEM);
-                goto fail;
-            }
-
-            av_strlcpy(vs->base_output_dirname, vs->m3u8_name,
-                    fmp4_init_filename_len);
-            p = strrchr(vs->base_output_dirname, '/');
-            if (p) {
-                *(p + 1) = '\0';
-                av_strlcat(vs->base_output_dirname, vs->fmp4_init_filename,
-                        fmp4_init_filename_len);
-            } else {
-                av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename,
-                        fmp4_init_filename_len);
-            }
-        }
-    }
-
-    if (!hls->use_localtime) {
-        ret = sls_flag_check_duration_size_index(hls);
-        if (ret < 0) {
-             goto fail;
-        }
-    } else {
-        ret = sls_flag_check_duration_size(hls, vs);
-        if (ret < 0) {
-             goto fail;
-        }
-    }
-    if(vs->has_subtitle) {
-
-        if (hls->flags & HLS_SINGLE_FILE)
-            vtt_pattern = ".vtt";
-        vtt_basename_size = strlen(s->filename) + strlen(vtt_pattern) + 1;
-        if (hls->nb_varstreams > 1) {
-            vtt_basename_size += strlen(POSTFIX_PATTERN);
-        }
-
-        vs->vtt_basename = av_malloc(vtt_basename_size);
-        if (!vs->vtt_basename) {
-            ret = AVERROR(ENOMEM);
-            goto fail;
-        }
-        vs->vtt_m3u8_name = av_malloc(vtt_basename_size);
-        if (!vs->vtt_m3u8_name ) {
-            ret = AVERROR(ENOMEM);
-            goto fail;
-        }
-        av_strlcpy(vs->vtt_basename, s->filename, vtt_basename_size);
-        p = strrchr(vs->vtt_basename, '.');
-        if (p)
-            *p = '\0';
-
-        if( hls->subtitle_filename ) {
-            strcpy(vs->vtt_m3u8_name, hls->subtitle_filename);
-        } else {
-            strcpy(vs->vtt_m3u8_name, vs->vtt_basename);
-            av_strlcat(vs->vtt_m3u8_name, "_vtt.m3u8", vtt_basename_size);
-        }
-        av_strlcat(vs->vtt_basename, vtt_pattern, vtt_basename_size);
-
-        if (hls->nb_varstreams > 1) {
-            ret= format_name(vs->vtt_basename, vtt_basename_size, i);
-            if (ret < 0)
-                 goto fail;
-            ret = format_name(vs->vtt_m3u8_name, vtt_basename_size, i);
-            if (ret < 0)
-                 goto fail;
-        }
-    }
-
-    if (hls->baseurl) {
-        vs->baseurl = av_strdup(hls->baseurl);
-        if (!vs->baseurl) {
-            ret = AVERROR(ENOMEM);
-            goto fail;
-        }
-    }
-
-    if ((hls->flags & HLS_SINGLE_FILE) && (hls->segment_type == SEGMENT_TYPE_FMP4)) {
-        vs->fmp4_init_filename  = av_strdup(vs->basename);
-        if (!vs->fmp4_init_filename) {
-            ret = AVERROR(ENOMEM);
-            goto fail;
-        }
-    }
-
-    if ((ret = hls_mux_init(s, vs)) < 0)
-        goto fail;
-
-    if (hls->flags & HLS_APPEND_LIST) {
-        parse_playlist(s, vs->m3u8_name, vs);
-        vs->discontinuity = 1;
-        if (hls->init_time > 0) {
-            av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time,"
-                   " hls_init_time value will have no effect\n");
-            hls->init_time = 0;
-            hls->recording_time = hls->time * AV_TIME_BASE;
-        }
-    }
-
-    if (hls->segment_type != SEGMENT_TYPE_FMP4 || hls->flags & HLS_SINGLE_FILE) {
-        if ((ret = hls_start(s, vs)) < 0)
-            goto fail;
-    }
-
     av_dict_copy(&options, hls->format_options, 0);
     ret = avformat_write_header(vs->avf, &options);
     if (av_dict_count(options)) {
@@ -1996,25 +1679,6 @@  static int hls_write_header(AVFormatContext *s)
     }
 fail:
 
-    if (ret < 0) {
-        av_freep(&hls->key_basename);
-        for (i = 0; i < hls->nb_varstreams && hls->var_streams; i++) {
-            vs = &hls->var_streams[i];
-            av_freep(&vs->basename);
-            av_freep(&vs->vtt_basename);
-            av_freep(&vs->fmp4_init_filename);
-            av_freep(&vs->m3u8_name);
-            av_freep(&vs->vtt_m3u8_name);
-            av_freep(&vs->streams);
-            av_freep(&vs->baseurl);
-            if (vs->avf)
-                avformat_free_context(vs->avf);
-            if (vs->vtt_avf)
-                avformat_free_context(vs->vtt_avf);
-        }
-        av_freep(&hls->var_streams);
-        av_freep(&hls->master_m3u8_url);
-    }
     return ret;
 }
 
@@ -2256,6 +1920,350 @@  static int hls_write_trailer(struct AVFormatContext *s)
     return 0;
 }
 
+
+static int hls_init(AVFormatContext *s)
+{
+    int ret = 0;
+    int i = 0;
+    int j = 0;
+    HLSContext *hls = s->priv_data;
+    const char *pattern = "%d.ts";
+    VariantStream *vs = NULL;
+    int basename_size = 0;
+    const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt(s);
+    const char *vtt_pattern = "%d.vtt";
+    char *p = NULL;
+    int vtt_basename_size = 0, m3u8_name_size = 0;
+    int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1;
+
+    ret = update_variant_stream_info(s);
+    if (ret < 0) {
+        av_log(s, AV_LOG_ERROR, "Variant stream info update failed with status %x\n",
+                ret);
+        goto fail;
+    }
+    //TODO: Updates needed to encryption functionality with periodic re-key when more than one variant streams are present
+    if (hls->nb_varstreams > 1 && hls->flags & HLS_PERIODIC_REKEY) {
+        ret = AVERROR(EINVAL);
+        av_log(s, AV_LOG_ERROR, "Periodic re-key not supported when more than one variant streams are present\n");
+        goto fail;
+    }
+
+    if (hls->master_pl_name) {
+        ret = update_master_pl_info(s);
+        if (ret < 0) {
+            av_log(s, AV_LOG_ERROR, "Master stream info update failed with status %x\n",
+                    ret);
+            goto fail;
+        }
+    }
+
+    if (hls->segment_type == SEGMENT_TYPE_FMP4) {
+        pattern = "%d.m4s";
+    }
+    if ((hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) ||
+        (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME)) {
+        time_t t = time(NULL); // we will need it in either case
+        if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) {
+            hls->start_sequence = (int64_t)t;
+        } else if (hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME) {
+            char b[15];
+            struct tm *p, tmbuf;
+            if (!(p = localtime_r(&t, &tmbuf)))
+                return AVERROR(ENOMEM);
+            if (!strftime(b, sizeof(b), "%Y%m%d%H%M%S", p))
+                return AVERROR(ENOMEM);
+            hls->start_sequence = strtoll(b, NULL, 10);
+        }
+        av_log(hls, AV_LOG_DEBUG, "start_number evaluated to %"PRId64"\n", hls->start_sequence);
+    }
+
+    hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE;
+    for (i = 0; i < hls->nb_varstreams; i++) {
+        vs = &hls->var_streams[i];
+        vs->sequence       = hls->start_sequence;
+        vs->start_pts      = AV_NOPTS_VALUE;
+        vs->end_pts      = AV_NOPTS_VALUE;
+        vs->current_segment_final_filename_fmt[0] = '\0';
+
+        if (hls->flags & HLS_SPLIT_BY_TIME && hls->flags & HLS_INDEPENDENT_SEGMENTS) {
+            // Independent segments cannot be guaranteed when splitting by time
+            hls->flags &= ~HLS_INDEPENDENT_SEGMENTS;
+            av_log(s, AV_LOG_WARNING,
+                   "'split_by_time' and 'independent_segments' cannot be enabled together. "
+                   "Disabling 'independent_segments' flag\n");
+        }
+
+        if (hls->flags & HLS_PROGRAM_DATE_TIME) {
+            time_t now0;
+            time(&now0);
+            vs->initial_prog_date_time = now0;
+        }
+        if (hls->format_options_str) {
+            ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0);
+            if (ret < 0) {
+                av_log(s, AV_LOG_ERROR, "Could not parse format options list '%s'\n", hls->format_options_str);
+                goto fail;
+            }
+        }
+
+        for (j = 0; j < vs->nb_streams; j++) {
+            vs->has_video += vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;
+            vs->has_subtitle += vs->streams[j]->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE;
+        }
+
+        if (vs->has_video > 1)
+            av_log(s, AV_LOG_WARNING, "More than a single video stream present, expect issues decoding it.\n");
+        if (hls->segment_type == SEGMENT_TYPE_FMP4) {
+            vs->oformat = av_guess_format("mp4", NULL, NULL);
+        } else {
+            vs->oformat = av_guess_format("mpegts", NULL, NULL);
+        }
+
+        if (!vs->oformat) {
+            ret = AVERROR_MUXER_NOT_FOUND;
+            goto fail;
+        }
+
+        if (vs->has_subtitle) {
+            vs->vtt_oformat = av_guess_format("webvtt", NULL, NULL);
+            if (!vs->oformat) {
+                ret = AVERROR_MUXER_NOT_FOUND;
+                goto fail;
+            }
+        }
+        if (hls->segment_filename) {
+            basename_size = strlen(hls->segment_filename) + 1;
+            if (hls->nb_varstreams > 1) {
+                basename_size += strlen(POSTFIX_PATTERN);
+            }
+            vs->basename = av_malloc(basename_size);
+            if (!vs->basename) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
+
+            av_strlcpy(vs->basename, hls->segment_filename, basename_size);
+        } else {
+            if (hls->flags & HLS_SINGLE_FILE) {
+                if (hls->segment_type == SEGMENT_TYPE_FMP4) {
+                    pattern = ".m4s";
+                } else {
+                    pattern = ".ts";
+                }
+            }
+
+            if (hls->use_localtime) {
+                basename_size = strlen(s->filename) + strlen(pattern_localtime_fmt) + 1;
+            } else {
+                basename_size = strlen(s->filename) + strlen(pattern) + 1;
+            }
+
+            if (hls->nb_varstreams > 1) {
+                basename_size += strlen(POSTFIX_PATTERN);
+            }
+
+            vs->basename = av_malloc(basename_size);
+            if (!vs->basename) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
+
+            av_strlcpy(vs->basename, s->filename, basename_size);
+
+            p = strrchr(vs->basename, '.');
+            if (p)
+                *p = '\0';
+            if (hls->use_localtime) {
+                av_strlcat(vs->basename, pattern_localtime_fmt, basename_size);
+            } else {
+                av_strlcat(vs->basename, pattern, basename_size);
+            }
+        }
+
+        m3u8_name_size = strlen(s->filename) + 1;
+        if (hls->nb_varstreams > 1) {
+            m3u8_name_size += strlen(POSTFIX_PATTERN);
+        }
+
+        vs->m3u8_name = av_malloc(m3u8_name_size);
+        if (!vs->m3u8_name ) {
+            ret = AVERROR(ENOMEM);
+            goto fail;
+        }
+
+        av_strlcpy(vs->m3u8_name, s->filename, m3u8_name_size);
+
+        if (hls->nb_varstreams > 1) {
+            ret = format_name(vs->basename, basename_size, i);
+            if (ret < 0)
+                goto fail;
+            ret = format_name(vs->m3u8_name, m3u8_name_size, i);
+            if (ret < 0)
+                goto fail;
+        }
+
+        if (hls->segment_type == SEGMENT_TYPE_FMP4) {
+            if (hls->nb_varstreams > 1)
+                fmp4_init_filename_len += strlen(POSTFIX_PATTERN);
+            vs->fmp4_init_filename = av_malloc(fmp4_init_filename_len);
+            if (!vs->fmp4_init_filename ) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
+            av_strlcpy(vs->fmp4_init_filename, hls->fmp4_init_filename,
+                       fmp4_init_filename_len);
+            if (hls->nb_varstreams > 1) {
+                ret = format_name(vs->fmp4_init_filename, fmp4_init_filename_len, i);
+                if (ret < 0)
+                    goto fail;
+            }
+
+            if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) {
+                fmp4_init_filename_len = strlen(vs->fmp4_init_filename) + 1;
+                vs->base_output_dirname = av_malloc(fmp4_init_filename_len);
+                if (!vs->base_output_dirname) {
+                    ret = AVERROR(ENOMEM);
+                    goto fail;
+                }
+                av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename,
+                           fmp4_init_filename_len);
+            } else {
+                fmp4_init_filename_len = strlen(vs->m3u8_name) +
+                    strlen(vs->fmp4_init_filename) + 1;
+
+                vs->base_output_dirname = av_malloc(fmp4_init_filename_len);
+                if (!vs->base_output_dirname) {
+                    ret = AVERROR(ENOMEM);
+                    goto fail;
+                }
+
+                av_strlcpy(vs->base_output_dirname, vs->m3u8_name,
+                           fmp4_init_filename_len);
+                p = strrchr(vs->base_output_dirname, '/');
+                if (p) {
+                    *(p + 1) = '\0';
+                    av_strlcat(vs->base_output_dirname, vs->fmp4_init_filename,
+                               fmp4_init_filename_len);
+                } else {
+                    av_strlcpy(vs->base_output_dirname, vs->fmp4_init_filename,
+                               fmp4_init_filename_len);
+                }
+            }
+        }
+
+        if (!hls->use_localtime) {
+            ret = sls_flag_check_duration_size_index(hls);
+            if (ret < 0) {
+                goto fail;
+            }
+        } else {
+            ret = sls_flag_check_duration_size(hls, vs);
+            if (ret < 0) {
+                goto fail;
+            }
+        }
+        if (vs->has_subtitle) {
+
+            if (hls->flags & HLS_SINGLE_FILE)
+                vtt_pattern = ".vtt";
+            vtt_basename_size = strlen(s->filename) + strlen(vtt_pattern) + 1;
+            if (hls->nb_varstreams > 1) {
+                vtt_basename_size += strlen(POSTFIX_PATTERN);
+            }
+
+            vs->vtt_basename = av_malloc(vtt_basename_size);
+            if (!vs->vtt_basename) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
+            vs->vtt_m3u8_name = av_malloc(vtt_basename_size);
+            if (!vs->vtt_m3u8_name ) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
+            av_strlcpy(vs->vtt_basename, s->filename, vtt_basename_size);
+            p = strrchr(vs->vtt_basename, '.');
+            if (p)
+                *p = '\0';
+
+            if ( hls->subtitle_filename ) {
+                strcpy(vs->vtt_m3u8_name, hls->subtitle_filename);
+            } else {
+                strcpy(vs->vtt_m3u8_name, vs->vtt_basename);
+                av_strlcat(vs->vtt_m3u8_name, "_vtt.m3u8", vtt_basename_size);
+            }
+            av_strlcat(vs->vtt_basename, vtt_pattern, vtt_basename_size);
+
+            if (hls->nb_varstreams > 1) {
+                ret= format_name(vs->vtt_basename, vtt_basename_size, i);
+                if (ret < 0)
+                    goto fail;
+                ret = format_name(vs->vtt_m3u8_name, vtt_basename_size, i);
+                if (ret < 0)
+                    goto fail;
+            }
+        }
+
+        if (hls->baseurl) {
+            vs->baseurl = av_strdup(hls->baseurl);
+            if (!vs->baseurl) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
+        }
+
+        if ((hls->flags & HLS_SINGLE_FILE) && (hls->segment_type == SEGMENT_TYPE_FMP4)) {
+            vs->fmp4_init_filename  = av_strdup(vs->basename);
+            if (!vs->fmp4_init_filename) {
+                ret = AVERROR(ENOMEM);
+                goto fail;
+            }
+        }
+        if ((ret = hls_mux_init(s, vs)) < 0)
+            goto fail;
+
+        if (hls->flags & HLS_APPEND_LIST) {
+            parse_playlist(s, vs->m3u8_name, vs);
+            vs->discontinuity = 1;
+            if (hls->init_time > 0) {
+                av_log(s, AV_LOG_WARNING, "append_list mode does not support hls_init_time,"
+                       " hls_init_time value will have no effect\n");
+                hls->init_time = 0;
+                hls->recording_time = hls->time * AV_TIME_BASE;
+            }
+        }
+
+        if (hls->segment_type != SEGMENT_TYPE_FMP4 || hls->flags & HLS_SINGLE_FILE) {
+            if ((ret = hls_start(s, vs)) < 0)
+                goto fail;
+        }
+    }
+
+fail:
+    if (ret < 0) {
+        av_freep(&hls->key_basename);
+        for (i = 0; i < hls->nb_varstreams && hls->var_streams; i++) {
+            vs = &hls->var_streams[i];
+            av_freep(&vs->basename);
+            av_freep(&vs->vtt_basename);
+            av_freep(&vs->fmp4_init_filename);
+            av_freep(&vs->m3u8_name);
+            av_freep(&vs->vtt_m3u8_name);
+            av_freep(&vs->streams);
+            av_freep(&vs->baseurl);
+            if (vs->avf)
+                avformat_free_context(vs->avf);
+            if (vs->vtt_avf)
+                avformat_free_context(vs->vtt_avf);
+        }
+        av_freep(&hls->var_streams);
+        av_freep(&hls->master_m3u8_url);
+    }
+
+    return ret;
+}
+
 #define OFFSET(x) offsetof(HLSContext, x)
 #define E AV_OPT_FLAG_ENCODING_PARAM
 static const AVOption options[] = {
@@ -2332,6 +2340,7 @@  AVOutputFormat ff_hls_muxer = {
     .video_codec    = AV_CODEC_ID_H264,
     .subtitle_codec = AV_CODEC_ID_WEBVTT,
     .flags          = AVFMT_NOFILE | AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH,
+    .init           = hls_init,
     .write_header   = hls_write_header,
     .write_packet   = hls_write_packet,
     .write_trailer  = hls_write_trailer,