diff options
author | Michael Niedermayer <michael@niedermayer.cc> | 2015-08-27 23:40:25 +0200 |
---|---|---|
committer | Michael Niedermayer <michael@niedermayer.cc> | 2015-08-28 00:09:56 +0200 |
commit | e2b19a533dbb4cb0fba85261ea835316381bc907 (patch) | |
tree | f06d9a783e3afd6ce5621ec49275829903ada5c6 | |
parent | 92d378067ee3ed47fb9076e37d5fb7613c6aac5f (diff) | |
download | ffmpeg-e2b19a533dbb4cb0fba85261ea835316381bc907.tar.gz |
avformat/segment: atomically update list if possible
Fixes Ticket4802
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
-rw-r--r-- | libavformat/segment.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/libavformat/segment.c b/libavformat/segment.c index 7f9367c444..36417f2192 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -114,6 +114,9 @@ typedef struct SegmentContext { int reference_stream_index; int break_non_keyframes; + int use_rename; + char temp_list_filename[1024]; + SegmentListEntry cur_entry; SegmentListEntry *segment_list_entries; SegmentListEntry *segment_list_entries_end; @@ -259,7 +262,8 @@ static int segment_list_open(AVFormatContext *s) SegmentContext *seg = s->priv_data; int ret; - ret = avio_open2(&seg->list_pb, seg->list, AVIO_FLAG_WRITE, + snprintf(seg->temp_list_filename, sizeof(seg->temp_list_filename), seg->use_rename ? "%s.tmp" : "%s", seg->list); + ret = avio_open2(&seg->list_pb, seg->temp_list_filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Failed to open segment list '%s'\n", seg->list); @@ -370,6 +374,8 @@ static int segment_end(AVFormatContext *s, int write_trailer, int is_last) if (seg->list_type == LIST_TYPE_M3U8 && is_last) avio_printf(seg->list_pb, "#EXT-X-ENDLIST\n"); avio_closep(&seg->list_pb); + if (seg->use_rename) + ff_rename(seg->temp_list_filename, seg->list, s); } else { segment_list_print_entry(seg->list_pb, seg->list_type, &seg->cur_entry, s); avio_flush(seg->list_pb); @@ -646,9 +652,13 @@ static int seg_write_header(AVFormatContext *s) else if (av_match_ext(seg->list, "ffcat,ffconcat")) seg->list_type = LIST_TYPE_FFCONCAT; else seg->list_type = LIST_TYPE_FLAT; } - if (!seg->list_size && seg->list_type != LIST_TYPE_M3U8) + if (!seg->list_size && seg->list_type != LIST_TYPE_M3U8) { if ((ret = segment_list_open(s)) < 0) goto fail; + } else { + const char *proto = avio_find_protocol_name(s->filename); + seg->use_rename = proto && !strcmp(proto, "file"); + } } if (seg->list_type == LIST_TYPE_EXT) av_log(s, AV_LOG_WARNING, "'ext' list type option is deprecated in favor of 'csv'\n"); |