Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat/hls.c')
-rw-r--r--libavformat/hls.c49
1 files changed, 46 insertions, 3 deletions
diff --git a/libavformat/hls.c b/libavformat/hls.c
index e1846ad773..26bf61c805 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -96,6 +96,8 @@ struct playlist {
uint8_t* read_buffer;
AVIOContext *input;
int input_read_done;
+ AVIOContext *input_next;
+ int input_next_requested;
AVFormatContext *parent;
int index;
AVFormatContext *ctx;
@@ -209,6 +211,7 @@ typedef struct HLSContext {
char *allowed_extensions;
int max_reload;
int http_persistent;
+ int http_multiple;
AVIOContext *playlist_pb;
} HLSContext;
@@ -261,6 +264,9 @@ static void free_playlist_list(HLSContext *c)
if (pls->input)
ff_format_io_close(c->ctx, &pls->input);
pls->input_read_done = 0;
+ if (pls->input_next)
+ ff_format_io_close(c->ctx, &pls->input_next);
+ pls->input_next_requested = 0;
if (pls->ctx) {
pls->ctx->pb = NULL;
avformat_close_input(&pls->ctx);
@@ -924,6 +930,14 @@ static struct segment *current_segment(struct playlist *pls)
return pls->segments[pls->cur_seq_no - pls->start_seq_no];
}
+static struct segment *next_segment(struct playlist *pls)
+{
+ int n = pls->cur_seq_no - pls->start_seq_no + 1;
+ if (n >= pls->n_segments)
+ return NULL;
+ return pls->segments[n];
+}
+
enum ReadFromURLMode {
READ_NORMAL,
READ_COMPLETE,
@@ -1365,6 +1379,7 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size)
int ret;
int just_opened = 0;
int reload_count = 0;
+ struct segment *seg;
restart:
if (!v->needed)
@@ -1372,7 +1387,6 @@ restart:
if (!v->input || (c->http_persistent && v->input_read_done)) {
int64_t reload_interval;
- struct segment *seg;
/* Check that the playlist is still needed before opening a new
* segment. */
@@ -1430,11 +1444,18 @@ reload:
if (ret)
return ret;
- ret = open_input(c, v, seg, &v->input);
+ if (c->http_multiple && av_strstart(seg->url, "http", NULL) && v->input_next_requested) {
+ FFSWAP(AVIOContext *, v->input, v->input_next);
+ v->input_next_requested = 0;
+ ret = 0;
+ } else {
+ ret = open_input(c, v, seg, &v->input);
+ }
if (ret < 0) {
if (ff_check_interrupt(c->interrupt_callback))
return AVERROR_EXIT;
- av_log(v->parent, AV_LOG_WARNING, "Failed to open segment of playlist %d\n",
+ av_log(v->parent, AV_LOG_WARNING, "Failed to open segment %d of playlist %d\n",
+ v->cur_seq_no,
v->index);
v->cur_seq_no += 1;
goto reload;
@@ -1442,6 +1463,20 @@ reload:
just_opened = 1;
}
+ seg = next_segment(v);
+ if (c->http_multiple && !v->input_next_requested && seg) {
+ ret = open_input(c, v, seg, &v->input_next);
+ if (ret < 0) {
+ if (ff_check_interrupt(c->interrupt_callback))
+ return AVERROR_EXIT;
+ av_log(v->parent, AV_LOG_WARNING, "Failed to open segment %d of playlist %d\n",
+ v->cur_seq_no + 1,
+ v->index);
+ } else {
+ v->input_next_requested = 1;
+ }
+ }
+
if (v->init_sec_buf_read_offset < v->init_sec_data_len) {
/* Push init section out first before first actual segment */
int copy_size = FFMIN(v->init_sec_data_len - v->init_sec_buf_read_offset, buf_size);
@@ -1964,6 +1999,9 @@ static int recheck_discard_flags(AVFormatContext *s, int first)
if (pls->input)
ff_format_io_close(pls->parent, &pls->input);
pls->input_read_done = 0;
+ if (pls->input_next)
+ ff_format_io_close(pls->parent, &pls->input_next);
+ pls->input_next_requested = 0;
pls->needed = 0;
changed = 1;
av_log(s, AV_LOG_INFO, "No longer receiving playlist %d\n", i);
@@ -2199,6 +2237,9 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
if (pls->input)
ff_format_io_close(pls->parent, &pls->input);
pls->input_read_done = 0;
+ if (pls->input_next)
+ ff_format_io_close(pls->parent, &pls->input_next);
+ pls->input_next_requested = 0;
av_packet_unref(&pls->pkt);
reset_packet(&pls->pkt);
pls->pb.eof_reached = 0;
@@ -2255,6 +2296,8 @@ static const AVOption hls_options[] = {
OFFSET(max_reload), 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",
+ OFFSET(http_multiple), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS},
{NULL}
};