1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

lavf/hlsenc: add append_list flag into hlsenc

When ffmpeg exit by exception, start a new ffmpeg will
cover the old segment list, add this flag can continue
append the new segments into old hls segment list

Signed-off-by: LiuQi <liuqi@gosun.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
Steven Liu 2016-08-21 12:55:45 +08:00 committed by Michael Niedermayer
parent 57503fab4f
commit 445c30ba07
2 changed files with 66 additions and 0 deletions

View File

@ -495,6 +495,10 @@ Will produce the playlist, @file{out.m3u8}, and a single segment file,
Segment files removed from the playlist are deleted after a period of time Segment files removed from the playlist are deleted after a period of time
equal to the duration of the segment plus the duration of the playlist. equal to the duration of the segment plus the duration of the playlist.
@item hls_flags append_list
Append new segments into the end of old segment list,
and remove the @code{#EXT-X-ENDLIST} from the old segment list.
@item hls_flags round_durations @item hls_flags round_durations
Round the duration info in the playlist file segment info to integer Round the duration info in the playlist file segment info to integer
values, instead of using floating point. values, instead of using floating point.

View File

@ -63,6 +63,7 @@ typedef enum HLSFlags {
HLS_DISCONT_START = (1 << 3), HLS_DISCONT_START = (1 << 3),
HLS_OMIT_ENDLIST = (1 << 4), HLS_OMIT_ENDLIST = (1 << 4),
HLS_SPLIT_BY_TIME = (1 << 5), HLS_SPLIT_BY_TIME = (1 << 5),
HLS_APPEND_LIST = (1 << 6),
} HLSFlags; } HLSFlags;
typedef enum { typedef enum {
@ -265,6 +266,14 @@ static int hls_encryption_start(AVFormatContext *s)
return 0; return 0;
} }
static int read_chomp_line(AVIOContext *s, char *buf, int maxlen)
{
int len = ff_get_line(s, buf, maxlen);
while (len > 0 && av_isspace(buf[len - 1]))
buf[--len] = '\0';
return len;
}
static int hls_mux_init(AVFormatContext *s) static int hls_mux_init(AVFormatContext *s)
{ {
HLSContext *hls = s->priv_data; HLSContext *hls = s->priv_data;
@ -389,6 +398,54 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, double
return 0; return 0;
} }
static int parse_playlist(AVFormatContext *s, const char *url)
{
HLSContext *hls = s->priv_data;
AVIOContext *in;
int ret = 0, is_segment = 0;
int64_t new_start_pos;
char line[1024];
const char *ptr;
if ((ret = ffio_open_whitelist(&in, url, AVIO_FLAG_READ,
&s->interrupt_callback, NULL,
s->protocol_whitelist, s->protocol_blacklist)) < 0)
return ret;
read_chomp_line(in, line, sizeof(line));
if (strcmp(line, "#EXTM3U")) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
while (!avio_feof(in)) {
read_chomp_line(in, line, sizeof(line));
if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
hls->sequence = atoi(ptr);
} else if (av_strstart(line, "#EXTINF:", &ptr)) {
is_segment = 1;
hls->duration = atof(ptr);
} else if (av_strstart(line, "#", NULL)) {
continue;
} else if (line[0]) {
if (is_segment) {
is_segment = 0;
new_start_pos = avio_tell(hls->avf->pb);
hls->size = new_start_pos - hls->start_pos;
av_strlcpy(hls->avf->filename, line, sizeof(line));
ret = hls_append_segment(s, hls, hls->duration, hls->start_pos, hls->size);
if (ret < 0)
goto fail;
hls->start_pos = new_start_pos;
}
}
}
fail:
avio_close(in);
return ret;
}
static void hls_free_segments(HLSSegment *p) static void hls_free_segments(HLSSegment *p)
{ {
HLSSegment *en; HLSSegment *en;
@ -752,6 +809,10 @@ static int hls_write_header(AVFormatContext *s)
if ((ret = hls_mux_init(s)) < 0) if ((ret = hls_mux_init(s)) < 0)
goto fail; goto fail;
if (hls->flags & HLS_APPEND_LIST) {
parse_playlist(s, s->filename);
}
if ((ret = hls_start(s)) < 0) if ((ret = hls_start(s)) < 0)
goto fail; goto fail;
@ -927,6 +988,7 @@ static const AVOption options[] = {
{"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 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"},
{"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX, E, "flags"}, {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX, E, "flags"},
{"split_by_time", "split the hls segment by time which user set by hls_time", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SPLIT_BY_TIME }, 0, UINT_MAX, E, "flags"}, {"split_by_time", "split the hls segment by time which user set by hls_time", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SPLIT_BY_TIME }, 0, UINT_MAX, E, "flags"},
{"append_list", "append the new segments into old hls segment list", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_APPEND_LIST }, 0, UINT_MAX, E, "flags"},
{"use_localtime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, {"use_localtime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
{"use_localtime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, {"use_localtime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
{"hls_playlist_type", "set the HLS playlist type", OFFSET(pl_type), AV_OPT_TYPE_INT, {.i64 = PLAYLIST_TYPE_NONE }, 0, PLAYLIST_TYPE_NB-1, E, "pl_type" }, {"hls_playlist_type", "set the HLS playlist type", OFFSET(pl_type), AV_OPT_TYPE_INT, {.i64 = PLAYLIST_TYPE_NONE }, 0, PLAYLIST_TYPE_NB-1, E, "pl_type" },