22#include "config_components.h"
50#define DEFAULT_USER_AGENT "Lavf/" AV_STRINGIFY(LIBAVFORMAT_VERSION)
51#define CURL_DEFAULT_BUFFER_SIZE (4 << 20)
55#define CURL_WAIT_US 100000
58#define ICY_MAX_HEADERS 65536
61#define ICY_MAX_BLOCK (255 * 16)
66#define CURL_RETRY_BASE_US 1000000
67#define CURL_RETRY_MAX_US 60000000
197 case CURLE_OK:
return 0;
198 case CURLE_URL_MALFORMAT:
199 case CURLE_UNSUPPORTED_PROTOCOL:
200 case CURLE_BAD_FUNCTION_ARGUMENT:
return AVERROR(EINVAL);
201 case CURLE_UNKNOWN_OPTION:
202 case CURLE_NOT_BUILT_IN:
return AVERROR(ENOSYS);
203 case CURLE_COULDNT_RESOLVE_PROXY:
204 case CURLE_COULDNT_RESOLVE_HOST:
return AVERROR(EHOSTUNREACH);
205 case CURLE_COULDNT_CONNECT:
return AVERROR(ECONNREFUSED);
206 case CURLE_OPERATION_TIMEDOUT:
return AVERROR(ETIMEDOUT);
207 case CURLE_LOGIN_DENIED:
208 case CURLE_REMOTE_ACCESS_DENIED:
return AVERROR(EACCES);
209 case CURLE_OUT_OF_MEMORY:
return AVERROR(ENOMEM);
210 case CURLE_PEER_FAILED_VERIFICATION:
218 if (
code == CURLE_OK)
229 case CURLM_OK:
return 0;
230 case CURLM_UNKNOWN_OPTION:
return AVERROR(EINVAL);
231 case CURLM_OUT_OF_MEMORY:
return AVERROR(ENOMEM);
239 case CURLM_OK:
return CURLE_OK;
240 case CURLM_UNKNOWN_OPTION:
return CURLE_UNKNOWN_OPTION;
241 case CURLM_OUT_OF_MEMORY:
return CURLE_OUT_OF_MEMORY;
242 case CURLM_ABORTED_BY_CALLBACK:
return CURLE_ABORTED_BY_CALLBACK;
243 case CURLM_UNRECOVERABLE_POLL:
return CURLE_UNRECOVERABLE_POLL;
244 default:
return CURLE_FAILED_INIT;
251 case CURLE_RECV_ERROR:
252 case CURLE_SEND_ERROR:
253 case CURLE_PARTIAL_FILE:
254 case CURLE_OPERATION_TIMEDOUT:
255 case CURLE_GOT_NOTHING:
256 case CURLE_COULDNT_CONNECT:
257 case CURLE_COULDNT_RESOLVE_HOST:
259 case CURLE_HTTP2_STREAM:
276 c->curl_status =
code;
282 size_t bytes =
size * nmemb;
287 if (
c->aborted || !
c->stream_ok) {
289 return CURL_WRITEFUNC_ERROR;
292 if (
c->seek_queued) {
298 if (bytes > INT64_MAX -
c->request_start -
c->request_received) {
300 "at offset %"PRId64
"\n",
c->request_start);
301 c->loop->num_errors++;
307 return CURL_WRITEFUNC_ERROR;
315 return CURL_WRITEFUNC_PAUSE;
320 c->request_received += bytes;
347 int64_t start = -1, end = -1, total = -1;
369 if (v[0] || (total < 0 && start < 0))
373 c->hdr_content_start = start;
374 c->hdr_content_end = end;
375 c->hdr_content_total = total;
391 if (v > (INT_MAX - (p[
i] -
'0')) / 10)
393 v = v * 10 + (p[
i] -
'0');
409 const char *colon = memchr(ptr,
':',
len);
410 const char *
val, *end = ptr +
len;
419 while (end >
val && (end[-1] ==
'\r' || end[-1] ==
'\n'))
450 c->icy_metadata_headers =
NULL;
457 if (start < 0 || start != c->request_start) {
459 "with offset %"PRId64
" (expected %"PRId64
")\n",
460 start,
c->request_start);
464 if (end >= 0 && end < start) {
466 "%"PRId64
"-%"PRId64
"\n", start, end);
470 if (total >= 0 && (start >= total || end >= total)) {
472 "%"PRId64
"-%"PRId64
" that exceeds the total size "
473 "%"PRId64
"\n", start, end, total);
477 if (
c->hdr_content_length >= 0 && end >= 0 &&
478 (
c->hdr_content_length - 1 > INT64_MAX - start ||
479 start + (
c->hdr_content_length - 1) != end))
482 "%"PRId64
"-%"PRId64
" that doesn't match the content length "
483 "%"PRId64
"\n", start, end,
c->hdr_content_length);
501 c->hdr_accept_ranges = 0;
502 c->hdr_compressed = 0;
503 c->hdr_content_start = -1;
504 c->hdr_content_end = -1;
505 c->hdr_content_total = -1;
506 c->hdr_content_length = -1;
507 c->hdr_icy_metaint = -1;
512 c->hdr_accept_ranges = !!
av_stristr(ptr + 14,
"bytes");
516 c->hdr_compressed = !
av_stristr(ptr + 17,
"identity");
535 while (n && (ptr[n - 1] ==
'\r' || ptr[n - 1] ==
'\n'))
540 curl_easy_getinfo(
c->easy, CURLINFO_RESPONSE_CODE, &status);
544 if (status < 200 || (status >= 300 && status < 400))
548 if (curl_easy_getinfo(
c->easy, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &cl) == CURLE_OK)
549 c->hdr_content_length = cl >= 0 ? cl : -1;
552 if (status >= 200 && status < 300) {
553 int64_t content_start = status == 206 ?
c->hdr_content_start : 0;
554 int64_t content_end = status == 206 ?
c->hdr_content_end : -1;
555 int64_t content_total = status == 206 ?
c->hdr_content_total :
c->hdr_content_length;
556 if (content_end < 0 && content_total > 0)
557 content_end = content_total - 1;
560 c->loop->num_errors++;
569 if (!
c->hdr_compressed && content_total >= 0)
570 c->content_size = content_total;
572 if (!
c->hdr_compressed) {
574 if (total < 0 && status != 206)
575 total =
c->hdr_content_length;
578 c->content_size = total;
580 content_end =
c->content_size > 0 ?
c->content_size - 1 : -1;
584 c->request_end = content_end;
588 const char *eff =
NULL;
589 if (curl_easy_getinfo(
c->easy, CURLINFO_EFFECTIVE_URL, &eff) == CURLE_OK
603 c->seekable = !
c->hdr_compressed &&
604 (status == 206 ||
c->hdr_accept_ranges);
607 if (
c->seekable_opt >= 0)
608 c->seekable =
c->seekable_opt;
611 if (
c->hdr_icy_metaint > 0) {
612 c->icy_metaint =
c->hdr_icy_metaint;
613 if (
c->seekable_opt > 0)
615 "reply carries in-band ICY metadata\n");
621 c->content_size = -1;
624 c->loop->num_errors++;
636 curl_off_t ultotal, curl_off_t ulnow)
641 aborted =
c->aborted;
651 const char *range_value =
NULL;
655 if (!
c->probed ||
c->seekable) {
658 if (
c->is_initial &&
c->initial_request_size > 0)
664 if (
c->content_size > 0)
665 end =
FFMIN(end,
c->content_size - 1);
667 end =
FFMIN(end,
c->end_off - 1);
668 snprintf(
range,
sizeof(
range),
"%"PRId64
"-%"PRId64, start, end);
670 snprintf(
range,
sizeof(
range),
"%"PRId64
"-", start);
674 cc = curl_easy_setopt(
c->easy, CURLOPT_RANGE, range_value);
676 c->loop->num_errors++;
683 c->loop->num_requests++;
684 c->request_received = 0;
687 CURLMcode res = curl_multi_add_handle(
c->loop->multi,
c->easy);
688 if (res != CURLM_OK) {
690 curl_multi_strerror(res));
704 curl_off_t recv = 0, time = 0;
705 curl_easy_getinfo(e, CURLINFO_SIZE_DOWNLOAD_T, &recv);
706 curl_easy_getinfo(e, CURLINFO_TOTAL_TIME_T, &time);
712 loop->total_bytes += recv;
713 loop->total_time_us += time;
716 long num_conns = 0, num_redirs = 0;
717 curl_easy_getinfo(e, CURLINFO_NUM_CONNECTS, &num_conns);
718 curl_easy_getinfo(e, CURLINFO_REDIRECT_COUNT, &num_redirs);
719 loop->num_connections += (int) num_conns;
720 loop->num_redirects += (int) num_redirs;
730 aborted =
c->aborted;
731 received =
c->request_received;
733 if (received > INT64_MAX -
c->request_start) {
739 c->request_start += received;
740 c->request_received = 0;
749 c->loop->num_errors++;
759 if (
c->seek_queued) {
766 if (
code == CURLE_OK &&
c->stream_ok) {
767 int64_t file_end =
c->content_size > 0 ?
c->content_size - 1 : -1;
769 file_end =
FFMIN(file_end,
c->end_off - 1);
770 if (
c->seekable &&
c->request_end >= 0 &&
c->request_end < file_end) {
777 c->curl_status = CURLE_OK;
785 c->loop->num_errors++;
804 if (
c->short_seek_size <= 0 ||
808 const int64_t last =
c->request_end -
c->request_start;
809 return last -
c->request_received <
c->short_seek_size;
822 curl_multi_remove_handle(
loop->multi,
c->easy);
831 curl_easy_pause(
c->easy, CURLPAUSE_CONT);
836 }
else if (
c->active) {
837 curl_multi_remove_handle(
loop->multi,
c->easy);
842 const int was_paused =
c->paused;
848 c->request_start = cmd->pos;
849 c->request_received = 0;
853 curl_easy_pause(
c->easy, CURLPAUSE_CONT);
870 cmd =
loop->cmd_head;
872 loop->cmd_head = cmd->next;
895 curl_multi_perform(
loop->multi, &running);
897 while ((msg = curl_multi_info_read(
loop->multi, &
left))) {
899 if (msg->msg != CURLMSG_DONE)
901 curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &
c);
902 curl_multi_remove_handle(
loop->multi, msg->easy_handle);
933 loop->cmd_tail->next = cmd;
935 loop->cmd_head = cmd;
936 loop->cmd_tail = cmd;
937 curl_multi_wakeup(
loop->multi);
948 curl_lock_access access,
void *userdata)
975 if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK)
978 loop->multi = curl_multi_init();
981 curl_multi_setopt(
loop->multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
983 loop->share = curl_share_init();
986 curl_share_setopt(
loop->share, CURLSHOPT_USERDATA,
loop);
989 curl_share_setopt(
loop->share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
990 curl_share_setopt(
loop->share, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS);
998 curl_multi_cleanup(
loop->multi);
999 curl_share_cleanup(
loop->share);
1000 curl_global_cleanup();
1013 if (
loop->total_bytes) {
1014 double time =
loop->total_time_us / 1000000.0;
1015 double avg = time ?
loop->total_bytes / time : 0;
1017 "libcurl: Overall %"PRId64
" bytes received in %.0f ms = %.0f kB/s\n",
1018 loop->total_bytes, time * 1e3,
avg / 1e3);
1021 if (
loop->num_connections ||
loop->num_errors) {
1023 "libcurl: %d connections, %d redirects, %d requests, %d errors\n",
1024 loop->num_connections,
loop->num_redirects,
loop->num_requests,
1033 curl_multi_wakeup(
loop->multi);
1039 curl_multi_cleanup(
loop->multi);
1040 curl_share_cleanup(
loop->share);
1046 curl_global_cleanup();
1057 c->private_loop = 1;
1058 return c->loop ? 0 :
AVERROR(ENOMEM);
1069 return c->loop ? 0 :
AVERROR(ENOMEM);
1087 size_t size,
void *userdata)
1093 case CURLINFO_TEXT:
prefix =
"* ";
break;
1094 case CURLINFO_HEADER_IN:
prefix =
"< ";
break;
1095 case CURLINFO_HEADER_OUT:
prefix =
"> ";
break;
1101 const char *nl = memchr(p,
'\n', end - p);
1102 size_t len = (nl ? nl : end) - p;
1103 while (
len && p[
len - 1] ==
'\r')
1115 struct curl_slist *
tmp = curl_slist_append(*list, str);
1125 int user_set_icy = 0, ret = 0;
1127 if (
c->referer &&
c->referer[0]) {
1136 if (
c->headers &&
c->headers[0]) {
1153 if (
c->icy && !user_set_icy)
1160 const char *wl =
c->h->protocol_whitelist;
1161 const char *bl =
c->h->protocol_blacklist;
1169 curl_version_info_data *info = curl_version_info(CURLVERSION_NOW);
1170 for (
const char *
const *p = info->protocols; *p; p++) {
1171 const char *proto = *p;
1195 curl_easy_setopt(
c->easy, CURLOPT_PROTOCOLS_STR, bp.str));
1198 curl_easy_setopt(
c->easy, CURLOPT_REDIR_PROTOCOLS_STR, bp.str));
1206#define CURL_SETOPT(opt, val) \
1208 int ret_ = curl_setopt_checked(c, #opt, \
1209 curl_easy_setopt(e, opt, val)); \
1216 const curl_version_info_data *info = curl_version_info(CURLVERSION_NOW);
1220 const char *url =
c->h->filename;
1246 CURL_SETOPT(CURLOPT_MAXREDIRS, (
long)
c->max_redirects);
1247 CURL_SETOPT(CURLOPT_HTTP_VERSION, (
long)
c->http_version);
1248 CURL_SETOPT(CURLOPT_TCP_KEEPALIVE,
c->multiple_requests ? 1L : 0
L);
1249 CURL_SETOPT(CURLOPT_FORBID_REUSE,
c->multiple_requests ? 0
L : 1L);
1250 if (info->features & CURL_VERSION_HSTS)
1251 CURL_SETOPT(CURLOPT_HSTS_CTRL, (
long)CURLHSTS_ENABLE);
1253 c->off > 0 ||
c->end_off > 0 ?
"identity" :
"");
1254 if (
c->connect_timeout > 0)
1256 (
long)
c->connect_timeout * 1000);
1258 if (
c->user_agent &&
c->user_agent[0])
1260 if (
c->http_proxy &&
c->http_proxy[0])
1263 if (info->features & CURL_VERSION_SSL)
1264 CURL_SETOPT(CURLOPT_SSL_OPTIONS, (
long)CURLSSLOPT_NATIVE_CA);
1265 CURL_SETOPT(CURLOPT_SSL_VERIFYPEER,
c->tls_verify ? 1L : 0
L);
1266 CURL_SETOPT(CURLOPT_SSL_VERIFYHOST,
c->tls_verify ? 2L : 0
L);
1275 cc = curl_easy_setopt(e, CURLOPT_COOKIEFILE,
"");
1276 if ((cc != CURLE_UNKNOWN_OPTION && cc != CURLE_NOT_BUILT_IN) ||
1277 (
c->cookies &&
c->cookies[0])) {
1282 if (
c->cookies &&
c->cookies[0]) {
1295 cc = curl_easy_setopt(e, CURLOPT_COOKIELIST, sc);
1312 if (
c->icy_status) {
1326 struct timespec ts = { .tv_sec = t / 1000000,
1327 .tv_nsec = (t % 1000000) * 1000 };
1339 while (!
c->probed && !
c->status) {
1349 ret =
c->status ?
c->status :
AVERROR(EIO);
1368 const int status =
c->status;
1369 const CURLcode
code =
c->curl_status;
1372 if (!
c->retry_time) {
1373 if (
c->retry_count >=
c->max_retries) {
1384 "after: %s (%s)\n",
c->retry_count,
c->logical_pos,
1386 curl_easy_strerror(
code));
1390 if (sleep_us > 0 && !nonblock) {
1392 }
else if (sleep_us <= 0) {
1413 curl_version_info_data *info = curl_version_info(CURLVERSION_NOW);
1414 if (!(info->features & CURL_VERSION_THREADSAFE))
1418 const char *eff_url =
h->filename;
1422 c->content_size = -1;
1423 c->request_start =
c->off;
1424 c->request_end = -1;
1425 c->logical_pos =
c->off;
1427 c->icy_block_len = -1;
1453 c->easy = curl_easy_init();
1476 h->is_streamed = !
c->seekable;
1490 c->icy_metadata_packet =
av_strdup((
char *)
c->icy_block);
1491 if (!
c->icy_metadata_packet)
1507 if (
c->icy_block_len < 0) {
1510 c->icy_block_len = units * 16;
1511 c->icy_block_filled = 0;
1513 if (!
c->icy_block_len) {
1514 c->icy_block_len = -1;
1515 c->icy_data_read = 0;
1521 n =
FFMIN(avail, (
size_t)(
c->icy_block_len -
c->icy_block_filled));
1523 c->icy_block_filled += n;
1524 if (
c->icy_block_filled <
c->icy_block_len)
1527 c->icy_block[
c->icy_block_len] = 0;
1528 c->icy_block_len = -1;
1529 c->icy_data_read = 0;
1547 if (
c->icy_metaint > 0 &&
c->icy_data_read ==
c->icy_metaint &&
1552 if (
c->icy_metaint > 0)
1553 avail =
FFMIN(avail, (
size_t)(
c->icy_metaint -
c->icy_data_read));
1558 c->icy_data_read += ret;
1559 c->logical_pos += ret;
1570 "Stream ended inside an ICY metadata block\n");
1599 const int64_t content_size =
c->content_size;
1600 const int seekable =
c->seekable;
1604 return content_size >= 0 ? content_size :
AVERROR(ENOSYS);
1614 if (
pos > INT64_MAX -
c->logical_pos)
1616 newpos =
c->logical_pos +
pos;
1619 if (content_size < 0)
1621 if (
pos > INT64_MAX - content_size)
1623 newpos = content_size +
pos;
1631 if (newpos ==
c->logical_pos)
1637 c->logical_pos = newpos;
1652 curl_easy_cleanup(
c->easy);
1656 if (
c->private_loop)
1662 curl_slist_free_all(
c->header_list);
1664 curl_slist_free_all(
c->alias_list);
1676 if (
c->short_seek_size >= 1)
1677 return FFMIN(
c->short_seek_size, INT_MAX);
1681#define OFFSET(x) offsetof(CurlContext, x)
1682#define D AV_OPT_FLAG_DECODING_PARAM
1683#define E AV_OPT_FLAG_ENCODING_PARAM
1687 {
"headers",
"set custom HTTP headers, can override built in default headers",
OFFSET(headers),
AV_OPT_TYPE_STRING, { .str =
NULL }, 0, 0,
D |
E },
1689 {
"cookies",
"set cookies to be sent in applicable future requests, use newline delimited Set-Cookie HTTP field value syntax",
OFFSET(cookies),
AV_OPT_TYPE_STRING, { .str =
NULL }, 0, 0,
D },
1692 {
"end_offset",
"try to limit the request to bytes preceding this offset",
OFFSET(end_off),
AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX,
D },
1693 {
"seekable",
"control seekability of connection",
OFFSET(seekable_opt),
AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1,
D },
1694 {
"tls_verify",
"verify the peer certificate and hostname",
OFFSET(tls_verify),
AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1,
D |
E },
1698 {
"connect_timeout",
"connection timeout in seconds (0 = libcurl default)",
OFFSET(connect_timeout),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX / 1000,
D |
E },
1699 {
"max_redirects",
"maximum number of redirects to follow",
OFFSET(max_redirects),
AV_OPT_TYPE_INT, { .i64 = 16 }, 0, INT_MAX,
D },
1700 {
"multiple_requests",
"reuse the connection across requests (HTTP keep-alive)",
OFFSET(multiple_requests),
AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1,
D |
E },
1701 {
"max_retries",
"maximum number of retries after a recoverable error",
OFFSET(max_retries),
AV_OPT_TYPE_INT, { .i64 = 5 }, 0, INT_MAX,
D },
1703 {
"icy_status",
"accept legacy Shoutcast \"ICY 200 OK\" status lines",
OFFSET(icy_status),
AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1,
D },
1708 {
"request_size",
"split a transfer into ranged requests of at most this many bytes (0 = unlimited)",
OFFSET(
request_size),
AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX,
D },
1709 {
"initial_request_size",
"size (in bytes) of initial requests made during probing / header parsing",
OFFSET(initial_request_size),
AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX,
D },
1710 {
"http_version",
"HTTP version to use",
OFFSET(http_version),
AV_OPT_TYPE_INT, { .i64 = CURL_HTTP_VERSION_NONE }, 0, INT_MAX,
D, .unit =
"http_version" },
1711 {
"auto",
"negotiate the best supported version", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_NONE }, 0, 0,
D, .unit =
"http_version" },
1712 {
"1.0",
"HTTP/1.0", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_1_0 }, 0, 0,
D, .unit =
"http_version" },
1713 {
"1.1",
"HTTP/1.1", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_1_1 }, 0, 0,
D, .unit =
"http_version" },
1714 {
"2",
"HTTP/2", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_2 }, 0, 0,
D, .unit =
"http_version" },
1715 {
"2tls",
"HTTP/2 over TLS only", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_2TLS }, 0, 0,
D, .unit =
"http_version" },
1716 {
"2-prior-knowledge",
"HTTP/2 without an upgrade handshake", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE }, 0, 0,
D, .unit =
"http_version" },
1717 {
"3",
"HTTP/3, fall back to earlier versions", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_3 }, 0, 0,
D, .unit =
"http_version" },
1718 {
"3only",
"HTTP/3 only", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_3ONLY }, 0, 0,
D, .unit =
"http_version" },
1719 {
"short_seek_size",
"threshold to favor readahead over seek",
OFFSET(short_seek_size),
AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX,
D },
1724 .class_name =
"libcurl",
1740 .default_whitelist =
"http,https,libcurl",
static double val(void *priv, double ch)
int ff_check_interrupt(AVIOInterruptCB *cb)
Check if the user has requested to interrupt a blocking function associated with cb.
#define AVSEEK_SIZE
Passing this as the "whence" parameter to a seek function causes it to return the filesize without se...
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
char * av_asprintf(const char *fmt,...)
static int BS_FUNC left(const BSCTX *bc)
Return the number of the bits left in a buffer.
void av_bprintf(AVBPrint *buf, const char *fmt,...)
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
#define AV_BPRINT_SIZE_AUTOMATIC
static int FUNC metadata(CodedBitstreamContext *ctx, RWContext *rw, APVRawMetadata *current)
#define flags(name, subs,...)
#define i(width, name, range_min, range_max)
static void do_exit(VideoState *is)
#define AV_OPT_FLAG_EXPORT
The option is intended for exporting values to the caller.
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
@ AV_OPT_TYPE_INT64
Underlying C type is int64_t.
@ AV_OPT_TYPE_INT
Underlying C type is int.
@ AV_OPT_TYPE_DICT
Underlying C type is AVDictionary*.
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
#define AV_DICT_MULTIKEY
Allow to store several equal keys in the dictionary.
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
#define AV_DICT_DONT_STRDUP_VAL
Take ownership of a value that's been allocated with av_malloc() or another memory allocation functio...
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
#define AV_DICT_DONT_STRDUP_KEY
Take ownership of a key that's been allocated with av_malloc() or another memory allocation function.
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
#define AVERROR_EOF
End of file.
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
void av_fifo_reset2(AVFifo *f)
size_t av_fifo_can_write(const AVFifo *f)
size_t av_fifo_can_read(const AVFifo *f)
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const char * av_default_item_name(void *ptr)
Return the context name.
int av_log_get_level(void)
Get the current log level.
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle.
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
static av_const int av_isdigit(int c)
Locale-independent conversion of ASCII isdigit.
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
int av_match_list(const char *name, const char *list, char separator)
Check if a name is in a list.
int av_stristart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str independent of case.
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
#define LIBAVUTIL_VERSION_INT
static uint64_t request_size(URLContext *h)
#define DEFAULT_USER_AGENT
static void ff_http_parse_icy_packet(void *logctx, AVDictionary **metadata, char *data)
Split an in-band ICY metadata packet into its "Key='Value';" pairs.
static int ff_http_averror(int status_code, int default_averror)
static const int factor[16]
#define AV_MUTEX_INITIALIZER
static int ff_thread_setname(const char *name)
#define CURL_DEFAULT_BUFFER_SIZE
static int setup_protocols(CurlContext *c)
static int curl_setopt_checked(CurlContext *c, const char *name, CURLcode code)
const URLProtocol ff_libcurl_protocol
#define CURL_RETRY_MAX_US
static void execute_command(CurlLoop *loop, CurlCmd *cmd)
static void share_unlock_callback(CURL *handle, curl_lock_data data, void *userdata)
static int curl_loop_attach(CurlContext *c, AVFormatContext *avfc)
static int curlmcode_to_curlcode(CURLMcode code)
static void print_statistics(CurlLoop *loop)
static int wait_for_probe(CurlContext *c)
static int curlmcode_to_averror(CURLMcode code)
static int slist_append(struct curl_slist **list, const char *str)
static void share_lock_callback(CURL *handle, curl_lock_data data, curl_lock_access access, void *userdata)
static void update_statistics(CurlContext *c)
static int is_recoverable(CURLcode code)
static void start_request(CurlContext *c)
static int verify_content_range(CurlContext *c, int64_t start, int64_t end, int64_t total)
static int drain_icy_block(CurlContext *c)
#define CURL_RETRY_BASE_US
static const AVClass libcurl_context_class
static int xferinfo_callback(void *userdata, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
#define CURL_SETOPT(opt, val)
static int debug_callback(CURL *easy, curl_infotype type, char *data, size_t size, void *userdata)
static int libcurl_open(URLContext *h, const char *url, int flags, AVDictionary **options)
static int64_t retry_delay(CurlContext *c)
static void curl_loop_destroy(CurlLoop *loop)
static void curl_cond_wait(CurlContext *c)
static void update_status_locked(CurlContext *c, int status, CURLcode code)
static int parse_offset(const char *str, int64_t *out, const char **ptr)
static int libcurl_close(URLContext *h)
static void store_icy_header(AVDictionary **dict, const char *ptr, size_t len)
void ff_curl_loop_free(struct CurlLoop **loop)
Release a libcurl event loop and set *loop to NULL.
static AVMutex curl_loop_lock
static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
static void parse_content_range(CurlContext *c, const char *v)
static void on_done(CurlContext *c, CURLcode code)
static void commit_icy_headers(CurlContext *c)
static int retry_request_locked(URLContext *h, int nonblock)
static int test_short_seek(CurlContext *c)
static int libcurl_get_short_seek(URLContext *h)
static int build_headers(CurlContext *c)
static CurlLoop * curl_loop_create(AVFormatContext *avfc)
static size_t header_callback(char *ptr, size_t size, size_t nitems, void *userdata)
static void * curl_worker(void *arg)
static int libcurl_read(URLContext *h, unsigned char *buf, int size)
static int64_t libcurl_seek(URLContext *h, int64_t pos, int whence)
static int update_icy_metadata(CurlContext *c)
static int curl_dispatch(CurlLoop *loop, enum cmd_kind kind, CurlContext *c, int64_t pos, int sync)
static int setup_curl(CurlContext *c)
static int curlcode_to_averror(CURLcode code)
static int64_t parse_metaint(const char *p, size_t len)
Utility Preprocessor macros.
Memory handling functions.
static av_always_inline int pthread_cond_broadcast(pthread_cond_t *cond)
static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
static av_always_inline int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
static av_always_inline int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Describe the class of an AVClass context structure.
char * icy_metadata_headers
struct curl_slist * header_list
int64_t initial_request_size
uint8_t icy_block[ICY_MAX_BLOCK+1]
char * icy_metadata_packet
int64_t hdr_content_total
int64_t hdr_content_start
struct curl_slist * alias_list
int64_t hdr_content_length
struct CurlLoop * curl_loop
Shared libcurl event loop, created on demand on the first use.
int av_usleep(unsigned usec)
Sleep for a period of time.
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
int64_t av_gettime(void)
Get the current time in microseconds.
unbuffered private I/O API
#define URL_PROTOCOL_FLAG_NETWORK
static void copy(const float *p1, float *p2, const int length)