AVIOInterruptCB *interrupt_callback;
AVDictionary *avio_opts;
char *allowed_extensions;
+ int extension_picky;
int max_reload;
int http_persistent;
int http_multiple;
return ret;
}
+static int test_segment(AVFormatContext *s, const AVInputFormat *in_fmt, struct playlist *pls, struct segment *seg)
+{
+ HLSContext *c = s->priv_data;
+ int matchA = 3;
+ int matchF = 0;
+
+ if (!c->extension_picky)
+ return 0;
+
+ if (strcmp(c->allowed_extensions, "ALL"))
+ matchA = av_match_ext (seg->url, c->allowed_extensions)
+ + 2*(ff_match_url_ext(seg->url, c->allowed_extensions) > 0);
+
+ if (!matchA) {
+ av_log(s, AV_LOG_ERROR, "URL %s is not in allowed_extensions\n", seg->url);
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (in_fmt) {
+ if (in_fmt->extensions) {
+ matchF = av_match_ext( seg->url, in_fmt->extensions)
+ + 2*(ff_match_url_ext(seg->url, in_fmt->extensions) > 0);
+ } else if (!strcmp(in_fmt->name, "mpegts"))
+ matchF = 3;
+
+ if (!(matchA & matchF)) {
+ av_log(s, AV_LOG_ERROR, "detected format extension %s mismatches allowed extensions in url %s\n", in_fmt->extensions ? in_fmt->extensions : "none", seg->url);
+ return AVERROR_INVALIDDATA;
+ }
+ }
+
+ return 0;
+}
+
static int parse_playlist(HLSContext *c, const char *url,
struct playlist *pls, AVIOContext *in)
{
goto fail;
}
+ ret = test_segment(c->ctx, pls->ctx ? pls->ctx->iformat : NULL, pls, seg);
+ if (ret < 0) {
+ av_free(seg->url);
+ av_free(seg->key);
+ av_free(seg);
+ goto fail;
+ }
+
if (duration < 0.001 * AV_TIME_BASE) {
av_log(c->ctx, AV_LOG_WARNING, "Cannot get correct #EXTINF value of segment %s,"
" set to default value to 1ms.\n", seg->url);
pls->ctx->max_analyze_duration = s->max_analyze_duration > 0 ? s->max_analyze_duration : 4 * AV_TIME_BASE;
url = av_strdup(pls->segments[0]->url);
ret = av_probe_input_buffer(&pls->pb, &in_fmt, url, NULL, 0, 0);
+
+ for (int n = 0; n < pls->n_segments; n++)
+ if (ret >= 0)
+ ret = test_segment(s, in_fmt, pls, pls->segments[n]);
+
av_free(url);
if (ret < 0) {
/* Free the ctx - it isn't initialized properly at this point,
OFFSET(allowed_extensions), AV_OPT_TYPE_STRING,
{.str = "3gp,aac,avi,flac,mkv,m3u8,m4a,m4s,m4v,mpg,mov,mp2,mp3,mp4,mpeg,mpegts,ogg,ogv,oga,ts,vob,wav"},
INT_MIN, INT_MAX, FLAGS},
+ {"extension_picky", "Be picky with all extensions matching",
+ OFFSET(extension_picky), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS},
{"max_reload", "Maximum number of times a insufficient list is attempted to be reloaded",
OFFSET(max_reload), AV_OPT_TYPE_INT, {.i64 = 3}, 0, INT_MAX, FLAGS},
{"m3u8_hold_counters", "The maximum number of times to load m3u8 when it refreshes without new segments",