From 08d28ee1823a7232541526770657dc49a218ad8f Mon Sep 17 00:00:00 2001 From: Steven Liu Date: Mon, 11 Dec 2017 11:03:25 +0800 Subject: [PATCH] avformat/hlsenc: move init operations from write_header to init Reviewed-by: Vishwanath Dixit Signed-off-by: Steven Liu --- libavformat/hlsenc.c | 681 ++++++++++++++++++++++--------------------- 1 file changed, 345 insertions(+), 336 deletions(-) diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 7dc8f4237b6..dd097396516 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -1640,329 +1640,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)) { @@ -2000,25 +1683,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; } @@ -2260,6 +1924,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[] = { @@ -2336,6 +2344,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.39.5