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:
parent
57503fab4f
commit
445c30ba07
@ -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
|
||||
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
|
||||
Round the duration info in the playlist file segment info to integer
|
||||
values, instead of using floating point.
|
||||
|
@ -63,6 +63,7 @@ typedef enum HLSFlags {
|
||||
HLS_DISCONT_START = (1 << 3),
|
||||
HLS_OMIT_ENDLIST = (1 << 4),
|
||||
HLS_SPLIT_BY_TIME = (1 << 5),
|
||||
HLS_APPEND_LIST = (1 << 6),
|
||||
} HLSFlags;
|
||||
|
||||
typedef enum {
|
||||
@ -265,6 +266,14 @@ static int hls_encryption_start(AVFormatContext *s)
|
||||
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)
|
||||
{
|
||||
HLSContext *hls = s->priv_data;
|
||||
@ -389,6 +398,54 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, double
|
||||
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)
|
||||
{
|
||||
HLSSegment *en;
|
||||
@ -752,6 +809,10 @@ static int hls_write_header(AVFormatContext *s)
|
||||
if ((ret = hls_mux_init(s)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (hls->flags & HLS_APPEND_LIST) {
|
||||
parse_playlist(s, s->filename);
|
||||
}
|
||||
|
||||
if ((ret = hls_start(s)) < 0)
|
||||
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"},
|
||||
{"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"},
|
||||
{"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_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" },
|
||||
|
Loading…
Reference in New Issue
Block a user