On Wed, Feb 1, 2017 at 1:23 AM, Steven Liu <lingjiujia...@gmail.com> wrote:
> > > 2017-02-01 4:29 GMT+08:00 Aman Gupta <ffm...@tmm1.net>: > >> From: Aman Gupta <a...@tmm1.net> >> >> Adds a `-hls_flags +temp_file` which will write segment data to >> filename.tmp, and then rename to filename when the segment is complete >> and before the file is added to the m3u8 playlist. >> >> This patch is similar in spirit to one used in Plex's ffmpeg fork, and >> allows a transcoding webserver to ensure incomplete segment files are >> never served up accidentally. >> --- >> libavformat/hlsenc.c | 15 +++++++++++++++ >> 1 file changed, 15 insertions(+) >> >> diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c >> index bd1e684..23b9011 100644 >> --- a/libavformat/hlsenc.c >> +++ b/libavformat/hlsenc.c >> @@ -76,6 +76,7 @@ typedef enum HLSFlags { >> HLS_SECOND_LEVEL_SEGMENT_INDEX = (1 << 8), // include segment index >> in segment filenames when use_localtime e.g.: %%03d >> HLS_SECOND_LEVEL_SEGMENT_DURATION = (1 << 9), // include segment >> duration (microsec) in segment filenames when use_localtime e.g.: %%09t >> HLS_SECOND_LEVEL_SEGMENT_SIZE = (1 << 10), // include segment size >> (bytes) in segment filenames when use_localtime e.g.: %%014s >> + HLS_TEMP_FILE = (1 << 11), >> } HLSFlags; >> >> typedef enum { >> @@ -915,6 +916,10 @@ static int hls_start(AVFormatContext *s) >> >> set_http_options(&options, c); >> >> + if (c->flags & HLS_TEMP_FILE) { >> + av_strlcat(oc->filename, ".tmp", sizeof(oc->filename)); >> + } >> + >> if (c->key_info_file) { >> if ((err = hls_encryption_start(s)) < 0) >> goto fail; >> @@ -1276,6 +1281,15 @@ static int hls_write_packet(AVFormatContext *s, >> AVPacket *pkt) >> >> av_write_frame(oc, NULL); /* Flush any buffered data */ >> >> + if (hls->flags & HLS_TEMP_FILE) { >> + size_t len = strlen(oc->filename); >> + char final_filename[sizeof(oc->filename)]; >> + av_strlcpy(final_filename, oc->filename, len); >> + final_filename[len-4] = '\0'; >> + ff_rename(oc->filename, final_filename, s); >> + oc->filename[len-4] = '\0'; >> + } >> + >> new_start_pos = avio_tell(hls->avf->pb); >> hls->size = new_start_pos - hls->start_pos; >> ret = hls_append_segment(s, hls, hls->duration, hls->start_pos, >> hls->size); >> @@ -1406,6 +1420,7 @@ static const AVOption options[] = { >> {"hls_subtitle_path", "set path of hls subtitles", >> OFFSET(subtitle_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, >> {"hls_flags", "set flags affecting HLS playlist and media file >> generation", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, E, >> "flags"}, >> {"single_file", "generate a single media file indexed with byte >> ranges", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SINGLE_FILE }, 0, UINT_MAX, E, >> "flags"}, >> + {"temp_file", "write segment to temporary file and rename when >> complete", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_TEMP_FILE }, 0, UINT_MAX, E, >> "flags"}, >> {"delete_segments", "delete segment files that are no longer part of >> the playlist", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DELETE_SEGMENTS }, 0, >> UINT_MAX, E, "flags"}, >> {"round_durations", "round durations in m3u8 to whole numbers", 0, >> AV_OPT_TYPE_CONST, {.i64 = HLS_ROUND_DURATIONS }, 0, UINT_MAX, E, >> "flags"}, >> {"discont_start", "start the playlist with a discontinuity tag", 0, >> AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX, E, "flags"}, >> -- >> 2.10.1 (Apple Git-78) >> >> _______________________________________________ >> ffmpeg-devel mailing list >> ffmpeg-devel@ffmpeg.org >> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel >> > > > Why use temp filename? > There have no info in m3u8 list before the segment complete. > Plex and other "on-the-fly" transcoding webservers will create a fake m3u8 with all the segments listed. When segment2.ts is requested but not yet available, it will wait for the file to show up on the disk and then serve it to the client. _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel