int64_t first_timestamp;
int64_t cur_timestamp;
AVIOInterruptCB *interrupt_callback;
+ char *referer; ///< holds HTTP referer set as an AVOption to the HTTP protocol context
char *user_agent; ///< holds HTTP user agent set as an AVOption to the HTTP protocol context
char *cookies; ///< holds HTTP cookie values set in either the initial response or as an AVOption to the HTTP protocol context
char *headers; ///< holds HTTP headers set as an AVOption to the HTTP protocol context
av_free(new_url);
if (close_in)
ff_format_io_close(c->ctx, &in);
+ c->ctx->ctx_flags = c->ctx->ctx_flags & ~(unsigned)AVFMTCTX_UNSEEKABLE;
+ if (!c->n_variants || !c->variants[0]->n_playlists ||
+ !(c->variants[0]->playlists[0]->finished ||
+ c->variants[0]->playlists[0]->type == PLS_TYPE_EVENT))
+ c->ctx->ctx_flags |= AVFMTCTX_UNSEEKABLE;
return ret;
}
/* demuxer not yet opened, defer picture attachment */
pls->id3_deferred_extra = extra_meta;
+ ff_id3v2_parse_priv_dict(&metadata, &extra_meta);
av_dict_copy(&pls->ctx->metadata, metadata, 0);
pls->id3_initial = metadata;
// broker prior HTTP options that should be consistent across requests
av_dict_set(&opts, "user_agent", c->user_agent, 0);
+ av_dict_set(&opts, "referer", c->referer, 0);
av_dict_set(&opts, "cookies", c->cookies, 0);
av_dict_set(&opts, "headers", c->headers, 0);
av_dict_set(&opts, "http_proxy", c->http_proxy, 0);
if (!v->finished &&
av_gettime_relative() - v->last_load_time >= reload_interval) {
if ((ret = parse_playlist(c, v->url, v, NULL)) < 0) {
- av_log(v->parent, AV_LOG_WARNING, "Failed to reload playlist %d\n",
- v->index);
+ if (ret != AVERROR_EXIT)
+ av_log(v->parent, AV_LOG_WARNING, "Failed to reload playlist %d\n",
+ v->index);
return ret;
}
/* If we need to reload the playlist again below (if
if (c->http_multiple == -1) {
uint8_t *http_version_opt = NULL;
- av_opt_get(v->input, "http_version", AV_OPT_SEARCH_CHILDREN, &http_version_opt);
- c->http_multiple = http_version_opt && strncmp((const char *)http_version_opt, "1.1", 3) == 0;
+ int r = av_opt_get(v->input, "http_version", AV_OPT_SEARCH_CHILDREN, &http_version_opt);
+ if (r >= 0) {
+ c->http_multiple = strncmp((const char *)http_version_opt, "1.1", 3) == 0;
+ av_freep(&http_version_opt);
+ }
}
seg = next_segment(v);
if (c->http_multiple == 1 && !v->input_next_requested &&
- seg && av_strstart(seg->url, "http", NULL)) {
+ seg && seg->key_type == KEY_NONE && av_strstart(seg->url, "http", NULL)) {
ret = open_input(c, v, seg, &v->input_next);
if (ret < 0) {
if (ff_check_interrupt(c->interrupt_callback))
return ret;
}
- if (c->http_persistent && av_strstart(seg->url, "http", NULL)) {
+ if (c->http_persistent &&
+ seg->key_type == KEY_NONE && av_strstart(seg->url, "http", NULL)) {
v->input_read_done = 1;
} else {
ff_format_io_close(v->parent, &v->input);
{
HLSContext *c = s->priv_data;
static const char * const opts[] = {
- "headers", "http_proxy", "user_agent", "user-agent", "cookies", NULL };
+ "headers", "http_proxy", "user_agent", "user-agent", "cookies", "referer", NULL };
const char * const * opt = opts;
uint8_t *buf;
int ret = 0;
av_log(s, AV_LOG_ERROR,
"A HLS playlist item '%s' referred to an external file '%s'. "
"Opening this file was forbidden for security reasons\n",
- s->filename, url);
+ s->url, url);
return AVERROR(EPERM);
}
update_options(&c->http_proxy, "http_proxy", u);
}
- if ((ret = parse_playlist(c, s->filename, NULL, s->pb)) < 0)
+ if ((ret = parse_playlist(c, s->url, NULL, s->pb)) < 0)
goto fail;
if ((ret = save_avio_options(s)) < 0)
if (pls->id3_deferred_extra && pls->ctx->nb_streams == 1) {
ff_id3v2_parse_apic(pls->ctx, &pls->id3_deferred_extra);
avformat_queue_attached_pictures(pls->ctx);
+ ff_id3v2_parse_priv(pls->ctx, &pls->id3_deferred_extra);
ff_id3v2_free_extra_meta(&pls->id3_deferred_extra);
pls->id3_deferred_extra = NULL;
}
if (ret < 0)
goto fail;
+ /*
+ * Copy any metadata from playlist to main streams, but do not set
+ * event flags.
+ */
+ if (pls->n_main_streams)
+ av_dict_copy(&pls->main_streams[0]->metadata, pls->ctx->metadata, 0);
+
add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_AUDIO);
add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_VIDEO);
add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_SUBTITLE);
return ret;
}
+ // If sub-demuxer reports updated metadata, copy it to the first stream
+ // and set its AVSTREAM_EVENT_FLAG_METADATA_UPDATED flag.
+ if (pls->ctx->event_flags & AVFMT_EVENT_FLAG_METADATA_UPDATED) {
+ if (pls->n_main_streams) {
+ st = pls->main_streams[0];
+ av_dict_copy(&st->metadata, pls->ctx->metadata, 0);
+ st->event_flags |= AVSTREAM_EVENT_FLAG_METADATA_UPDATED;
+ }
+ pls->ctx->event_flags &= ~AVFMT_EVENT_FLAG_METADATA_UPDATED;
+ }
+
/* check if noheader flag has been cleared by the subdemuxer */
if (pls->has_noheader_flag && !(pls->ctx->ctx_flags & AVFMTCTX_NOHEADER)) {
pls->has_noheader_flag = 0;
int stream_subdemuxer_index;
int64_t first_timestamp, seek_timestamp, duration;
- if ((flags & AVSEEK_FLAG_BYTE) ||
- !(c->variants[0]->playlists[0]->finished || c->variants[0]->playlists[0]->type == PLS_TYPE_EVENT))
+ if ((flags & AVSEEK_FLAG_BYTE) || (c->ctx->ctx_flags & AVFMTCTX_UNSEEKABLE))
return AVERROR(ENOSYS);
first_timestamp = c->first_timestamp == AV_NOPTS_VALUE ?
.long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
.priv_class = &hls_class,
.priv_data_size = sizeof(HLSContext),
+ .flags = AVFMT_NOGENSEARCH,
.read_probe = hls_probe,
.read_header = hls_read_header,
.read_packet = hls_read_packet,