summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorSteven Liu <lq@chinaffmpeg.org>2017-12-11 11:03:25 +0800
committerSteven Liu <lq@chinaffmpeg.org>2017-12-11 11:03:25 +0800
commit08d28ee1823a7232541526770657dc49a218ad8f (patch)
tree90e5fcea0a96c09a164c7fe2f4766a761368fcd7 /libavformat
parent918de766f545008cb1ab3d62febe71fa064f8ca7 (diff)
avformat/hlsenc: move init operations from write_header to init
Reviewed-by: Vishwanath Dixit <vdixit@akamai.com> Signed-off-by: Steven Liu <lq@chinaffmpeg.org>
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/hlsenc.c681
1 files changed, 345 insertions, 336 deletions
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 7dc8f4237b..dd09739651 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,