Dear All,
currently master playlist and subtitle playlist creation does not use
temporary files even when temp_file flag is set. Most of the use cases
it is not a problem because master playlist creation happens once on the
beginning of the whole process. But if master playlist is periodically
re-created because of master_pl_refresh_rate is set, non-atomic playlist
creation may cause problems in case of live streaming. This poblem (i.e
non-atomic playlist
creation) may also apply for subtitle playlist (vtt) creation in live
streaming.
This patch correct this behavior by adding missing functionality.
please review this patch.
thank you in advance,
best regards,
Bela
>From 04e70ba586646b927e1b05a9df3860a635871603 Mon Sep 17 00:00:00 2001
From: Bela Bodecs
Date: Mon, 24 Jun 2019 17:41:49 +0200
Subject: [PATCH] avformat/hlsenc: temp_file usage for master playlist and vtt
playlist
currently master playlist and subtitle playlist creation does not use
temporary files even when temp_file flag is set. Most of the use cases
it is not a problem because master playlist creation happens once on the
beginning of the whole process. But if master playlist is periodically
re-created because of master_pl_refresh_rate is set, non-atomic playlist
creation may cause problems in case of live streaming. This patch
correct this behavior by adding this functionality.
Signed-off-by: Bela Bodecs
---
doc/muxers.texi | 6 +-
libavformat/hlsenc.c | 30 +-
2 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi
index 6c5b4bb637..d969e39fff 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -893,7 +893,11 @@ This will produce segments like this:
@item temp_file
Write segment data to filename.tmp and rename to filename only once the
segment is complete. A webserver
serving up segments can be configured to reject requests to *.tmp to prevent
access to in-progress segments
-before they have been added to the m3u8 playlist.
+before they have been added to the m3u8 playlist. This flag also affects how
m3u8 playlist files are created.
+If this flag is set, all playlist files will written into temporary file and
renamed after they are complete, similarly as segments are handled.
+But playlists with @code{file} protocol and with type
(@code{hls_playlist_type}) other than @code{vod}
+are always written into temporary file regardles of this flag. Master playlist
files (@code{master_pl_name}), if any, with @code{file} protocol,
+are always written into temporary file regardles of this flag if
@code{master_pl_publish_rate} value is other than zero.
@end table
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 9f5eee5491..eaeafcbb6b 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -1260,8 +1260,12 @@ static int create_master_playlist(AVFormatContext *s,
AVDictionary *options = NULL;
unsigned int i, j;
int m3u8_name_size, ret, bandwidth;
-char *m3u8_rel_name, *ccgroup;
+char *m3u8_rel_name = NULL, *ccgroup;
ClosedCaptionsStream *ccs;
+const char *proto = avio_find_protocol_name(hls->master_m3u8_url);
+int is_file_proto = proto && !strcmp(proto, "file");
+int use_temp_file = is_file_proto && ((hls->flags & HLS_TEMP_FILE) ||
hls->master_publish_rate);
+char temp_filename[1024];
input_vs->m3u8_created = 1;
if (!hls->master_m3u8_created) {
@@ -1277,12 +1281,12 @@ static int create_master_playlist(AVFormatContext *s,
}
set_http_options(s, , hls);
-
-ret = hlsenc_io_open(s, >m3u8_out, hls->master_m3u8_url, );
+snprintf(temp_filename, sizeof(temp_filename), use_temp_file ? "%s.tmp" :
"%s", hls->master_m3u8_url);
+ret = hlsenc_io_open(s, >m3u8_out, temp_filename, );
av_dict_free();
if (ret < 0) {
av_log(NULL, AV_LOG_ERROR, "Failed to open master play list file
'%s'\n",
-hls->master_m3u8_url);
+temp_filename);
goto fail;
}
@@ -1413,7 +1417,10 @@ fail:
if(ret >=0)
hls->master_m3u8_created = 1;
av_freep(_rel_name);
-hlsenc_io_close(s, >m3u8_out, hls->master_m3u8_url);
+hlsenc_io_close(s, >m3u8_out, temp_filename);
+if (use_temp_file)
+ff_rename(temp_filename, hls->master_m3u8_url, s);
+
return ret;
}
@@ -1424,6 +1431,7 @@ static int hls_window(AVFormatContext *s, int last,
VariantStream *vs)
int target_duration = 0;
int ret = 0;
char temp_filename[1024];
+char temp_vtt_filename[1024];
int64_t sequence = FFMAX(hls->start_sequence, vs->sequence -
vs->nb_entries);
const char *proto = avio_find_protocol_name(vs->m3u8_name);
int is_file_proto = proto && !strcmp(proto, "file");
@@ -1505,8 +1513,9 @@ static int hls_window(AVFormatContext *s, int last,
VariantStream *vs)
if (last && (hls->flags & HLS_OMIT_ENDLIST)==0)
ff_hls_write_end_list(hls->m3u8_out);
-if( vs->vtt_m3u8_name )