|
|
|
@ -118,6 +118,8 @@ struct playlist { |
|
|
|
|
int needed; |
|
|
|
|
int broken; |
|
|
|
|
int cur_seq_no; |
|
|
|
|
int last_seq_no; |
|
|
|
|
int m3u8_hold_counters; |
|
|
|
|
int64_t cur_seg_offset; |
|
|
|
|
int64_t last_load_time; |
|
|
|
|
|
|
|
|
@ -198,6 +200,7 @@ typedef struct HLSContext { |
|
|
|
|
struct rendition **renditions; |
|
|
|
|
|
|
|
|
|
int cur_seq_no; |
|
|
|
|
int m3u8_hold_counters; |
|
|
|
|
int live_start_index; |
|
|
|
|
int first_packet; |
|
|
|
|
int64_t first_timestamp; |
|
|
|
@ -1428,6 +1431,17 @@ reload: |
|
|
|
|
v->start_seq_no - v->cur_seq_no); |
|
|
|
|
v->cur_seq_no = v->start_seq_no; |
|
|
|
|
} |
|
|
|
|
if (v->cur_seq_no > v->last_seq_no) { |
|
|
|
|
v->last_seq_no = v->cur_seq_no; |
|
|
|
|
v->m3u8_hold_counters = 0; |
|
|
|
|
} else if (v->last_seq_no == v->cur_seq_no) { |
|
|
|
|
v->m3u8_hold_counters++; |
|
|
|
|
if (v->m3u8_hold_counters >= c->m3u8_hold_counters) { |
|
|
|
|
return AVERROR_EOF; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
av_log(v->parent, AV_LOG_WARNING, "maybe the m3u8 list sequence have been wraped.\n"); |
|
|
|
|
} |
|
|
|
|
if (v->cur_seq_no >= v->start_seq_no + v->n_segments) { |
|
|
|
|
if (v->finished) |
|
|
|
|
return AVERROR_EOF; |
|
|
|
@ -1816,6 +1830,7 @@ static int hls_read_header(AVFormatContext *s) |
|
|
|
|
if (c->n_playlists > 1 || c->playlists[0]->n_segments == 0) { |
|
|
|
|
for (i = 0; i < c->n_playlists; i++) { |
|
|
|
|
struct playlist *pls = c->playlists[i]; |
|
|
|
|
pls->m3u8_hold_counters = 0; |
|
|
|
|
if ((ret = parse_playlist(c, pls->url, pls, NULL)) < 0) { |
|
|
|
|
av_log(s, AV_LOG_WARNING, "parse_playlist error %s [%s]\n", av_err2str(ret), pls->url); |
|
|
|
|
pls->broken = 1; |
|
|
|
@ -2317,6 +2332,8 @@ static const AVOption hls_options[] = { |
|
|
|
|
INT_MIN, INT_MAX, FLAGS}, |
|
|
|
|
{"max_reload", "Maximum number of times a insufficient list is attempted to be reloaded", |
|
|
|
|
OFFSET(max_reload), AV_OPT_TYPE_INT, {.i64 = 1000}, 0, INT_MAX, FLAGS}, |
|
|
|
|
{"m3u8_hold_counters", "Maximum number of times requests when the m3u8 file not be refresh", |
|
|
|
|
OFFSET(m3u8_hold_counters), AV_OPT_TYPE_INT, {.i64 = 1000}, 0, INT_MAX, FLAGS}, |
|
|
|
|
{"http_persistent", "Use persistent HTTP connections", |
|
|
|
|
OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS }, |
|
|
|
|
{"http_multiple", "Use multiple HTTP connections for fetching segments", |
|
|
|
|