22#include "config_components.h"
47#define DEFAULT_USER_AGENT "Lavf/" AV_STRINGIFY(LIBAVFORMAT_VERSION)
48#define CURL_DEFAULT_BUFFER_SIZE (4 << 20)
52#define CURL_WAIT_US 100000
164 case CURLE_OK:
return 0;
165 case CURLE_URL_MALFORMAT:
166 case CURLE_UNSUPPORTED_PROTOCOL:
return AVERROR(EINVAL);
167 case CURLE_COULDNT_RESOLVE_PROXY:
168 case CURLE_COULDNT_RESOLVE_HOST:
return AVERROR(EHOSTUNREACH);
169 case CURLE_COULDNT_CONNECT:
return AVERROR(ECONNREFUSED);
170 case CURLE_OPERATION_TIMEDOUT:
return AVERROR(ETIMEDOUT);
171 case CURLE_LOGIN_DENIED:
172 case CURLE_REMOTE_ACCESS_DENIED:
return AVERROR(EACCES);
173 case CURLE_OUT_OF_MEMORY:
return AVERROR(ENOMEM);
174 case CURLE_PEER_FAILED_VERIFICATION:
183 case CURLE_RECV_ERROR:
184 case CURLE_SEND_ERROR:
185 case CURLE_PARTIAL_FILE:
186 case CURLE_OPERATION_TIMEDOUT:
187 case CURLE_GOT_NOTHING:
188 case CURLE_COULDNT_CONNECT:
189 case CURLE_COULDNT_RESOLVE_HOST:
191 case CURLE_HTTP2_STREAM:
205 size_t bytes =
size * nmemb;
210 if (
c->aborted || !
c->stream_ok) {
212 return CURL_WRITEFUNC_ERROR;
220 return CURL_WRITEFUNC_PAUSE;
225 c->request_received += bytes;
235 return v < 0 ? -1 : v;
247 const char *
range = v + 6, *end;
248 if (
range[0] !=
'*') {
250 if ((end = strchr(
range,
'-')))
254 const char *slash = strchr(
range,
'/');
255 if (slash && slash[1] !=
'*')
267 c->hdr_accept_ranges = 0;
268 c->hdr_compressed = 0;
269 c->hdr_content_start = -1;
270 c->hdr_content_end = -1;
271 c->hdr_content_total = -1;
275 c->hdr_accept_ranges = !!
av_stristr(ptr + 14,
"bytes");
279 c->hdr_compressed = !
av_stristr(ptr + 17,
"identity");
288 while (n && (ptr[n - 1] ==
'\r' || ptr[n - 1] ==
'\n'))
293 curl_easy_getinfo(
c->easy, CURLINFO_RESPONSE_CODE, &status);
297 if (status < 200 || (status >= 300 && status < 400))
301 if (status >= 200 && status < 300) {
302 int64_t content_start = status == 206 ?
c->hdr_content_start : 0;
306 if ((
c->probed ?
c->seekable :
c->off > 0) &&
307 content_start !=
c->request_start) {
309 "with offset %"PRId64
" (expected %"PRId64
")\n",
310 content_start,
c->request_start);
323 const char *eff =
NULL;
324 if (curl_easy_getinfo(
c->easy, CURLINFO_EFFECTIVE_URL, &eff) == CURLE_OK
337 c->seekable = !
c->hdr_compressed &&
338 (status == 206 ||
c->hdr_accept_ranges);
339 if (!
c->hdr_compressed) {
340 int64_t total =
c->hdr_content_total;
341 if (total < 0 && status != 206) {
343 if (curl_easy_getinfo(
c->easy, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T,
344 &cl) == CURLE_OK && cl >= 0)
349 c->content_size = total;
352 if (
c->hdr_content_end >= 0)
353 c->request_end =
c->hdr_content_end;
355 c->request_end =
c->content_size > 0 ?
c->content_size - 1 : -1;
359 if (
c->seekable_opt >= 0)
360 c->seekable =
c->seekable_opt;
374 curl_off_t ultotal, curl_off_t ulnow)
379 aborted =
c->aborted;
388 if (!
c->probed ||
c->seekable) {
392 if (
c->is_initial &&
c->initial_request_size > 0)
398 if (
c->content_size > 0)
399 end =
FFMIN(end,
c->content_size - 1);
401 end =
FFMIN(end,
c->end_off - 1);
406 curl_easy_setopt(
c->easy, CURLOPT_RANGE,
range);
408 curl_easy_setopt(
c->easy, CURLOPT_RANGE,
NULL);
410 c->loop->num_requests++;
411 c->request_received = 0;
414 CURLMcode res = curl_multi_add_handle(
c->loop->multi,
c->easy);
415 if (res != CURLM_OK) {
417 curl_multi_strerror(res));
432 curl_off_t recv = 0, time = 0;
433 curl_easy_getinfo(e, CURLINFO_SIZE_DOWNLOAD_T, &recv);
434 curl_easy_getinfo(e, CURLINFO_TOTAL_TIME_T, &time);
440 loop->total_bytes += recv;
441 loop->total_time_us += time;
444 long num_conns = 0, num_redirs = 0;
445 curl_easy_getinfo(e, CURLINFO_NUM_CONNECTS, &num_conns);
446 curl_easy_getinfo(e, CURLINFO_REDIRECT_COUNT, &num_redirs);
447 loop->num_connections += (int) num_conns;
448 loop->num_redirects += (int) num_redirs;
458 aborted =
c->aborted;
459 received =
c->request_received;
461 if (received > INT64_MAX -
c->request_start) {
468 c->request_start += received;
469 c->request_received = 0;
485 if (
code == CURLE_OK && !aborted &&
c->stream_ok) {
487 int64_t file_end =
c->content_size > 0 ?
c->content_size - 1 : -1;
489 file_end =
FFMIN(file_end,
c->end_off - 1);
490 if (
c->seekable &&
c->request_end >= 0 &&
c->request_end < file_end) {
504 c->retry_count <
c->max_retries) {
506 c->loop->num_retries++;
508 curl_easy_strerror(
code),
c->retry_count,
c->request_start);
536 curl_multi_remove_handle(
loop->multi,
c->easy);
545 curl_easy_pause(
c->easy, CURLPAUSE_CONT);
549 curl_multi_remove_handle(
loop->multi,
c->easy);
558 c->request_start = cmd->pos;
577 cmd =
loop->cmd_head;
579 loop->cmd_head = cmd->next;
602 curl_multi_perform(
loop->multi, &running);
604 while ((msg = curl_multi_info_read(
loop->multi, &
left))) {
606 if (msg->msg != CURLMSG_DONE)
608 curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &
c);
609 curl_multi_remove_handle(
loop->multi, msg->easy_handle);
640 loop->cmd_tail->next = cmd;
642 loop->cmd_head = cmd;
643 loop->cmd_tail = cmd;
644 curl_multi_wakeup(
loop->multi);
668 if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK)
671 loop->multi = curl_multi_init();
674 curl_multi_setopt(
loop->multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
676 loop->share = curl_share_init();
679 curl_share_setopt(
loop->share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
680 curl_share_setopt(
loop->share, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS);
688 curl_multi_cleanup(
loop->multi);
689 curl_share_cleanup(
loop->share);
690 curl_global_cleanup();
702 if (!
loop->total_bytes)
705 double time = (
double)
loop->total_time_us / 1000000.0;
706 double avg = time ?
loop->total_bytes / time : 0;
708 "libcurl: Overall %"PRId64
" bytes received in %.0f ms = %.0f kB/s\n",
709 loop->total_bytes, time * 1e3,
avg / 1e3);
712 "libcurl: %d connections, %d redirects, %d requests, %d retries\n",
713 loop->num_connections,
loop->num_redirects,
loop->num_requests,
loop->num_retries);
720 curl_multi_wakeup(
loop->multi);
726 curl_multi_cleanup(
loop->multi);
727 curl_share_cleanup(
loop->share);
733 curl_global_cleanup();
745 return c->loop ? 0 :
AVERROR(ENOMEM);
756 return c->loop ? 0 :
AVERROR(ENOMEM);
774 size_t size,
void *userdata)
780 case CURLINFO_TEXT:
prefix =
"* ";
break;
781 case CURLINFO_HEADER_IN:
prefix =
"< ";
break;
782 case CURLINFO_HEADER_OUT:
prefix =
"> ";
break;
788 const char *nl = memchr(p,
'\n', end - p);
789 size_t len = (nl ? nl : end) - p;
790 while (
len && p[
len - 1] ==
'\r')
803 struct curl_slist *list =
NULL;
805 if (
c->referer &&
c->referer[0]) {
808 list = curl_slist_append(list,
h);
812 if (
c->headers &&
c->headers[0]) {
818 list = curl_slist_append(list,
line);
827 const char *wl =
c->h->protocol_whitelist;
828 const char *bl =
c->h->protocol_blacklist;
835 curl_version_info_data *info = curl_version_info(CURLVERSION_NOW);
836 for (
const char *
const *p = info->protocols; *p; p++) {
837 const char *proto = *p;
860 curl_easy_setopt(
c->easy, CURLOPT_PROTOCOLS_STR, bp.str);
861 curl_easy_setopt(
c->easy, CURLOPT_REDIR_PROTOCOLS_STR, bp.str);
869 const char *url =
c->h->filename;
874 curl_easy_setopt(e, CURLOPT_URL, url);
875 curl_easy_setopt(e, CURLOPT_PRIVATE,
c);
876 curl_easy_setopt(e, CURLOPT_NOSIGNAL, 1L);
877 curl_easy_setopt(e, CURLOPT_SHARE,
c->loop->share);
880 curl_easy_setopt(e, CURLOPT_WRITEDATA,
c);
882 curl_easy_setopt(e, CURLOPT_HEADERDATA,
c);
884 curl_easy_setopt(e, CURLOPT_NOPROGRESS, 0
L);
886 curl_easy_setopt(e, CURLOPT_XFERINFODATA,
c);
889 curl_easy_setopt(e, CURLOPT_VERBOSE, 1L);
891 curl_easy_setopt(e, CURLOPT_DEBUGDATA,
c);
894 curl_easy_setopt(e, CURLOPT_FOLLOWLOCATION, 1L);
895 curl_easy_setopt(e, CURLOPT_MAXREDIRS, (
long)
c->max_redirects);
896 curl_easy_setopt(e, CURLOPT_HTTP_VERSION, (
long)
c->http_version);
897 curl_easy_setopt(e, CURLOPT_TCP_KEEPALIVE,
c->multiple_requests ? 1L : 0
L);
898 curl_easy_setopt(e, CURLOPT_FORBID_REUSE,
c->multiple_requests ? 0
L : 1L);
899 curl_easy_setopt(e, CURLOPT_HSTS_CTRL, (
long)CURLHSTS_ENABLE);
900 curl_easy_setopt(e, CURLOPT_ACCEPT_ENCODING,
901 c->off > 0 ||
c->end_off > 0 ?
"identity" :
"");
902 if (
c->connect_timeout > 0)
903 curl_easy_setopt(e, CURLOPT_CONNECTTIMEOUT_MS,
904 (
long)
c->connect_timeout * 1000);
906 if (
c->user_agent &&
c->user_agent[0])
907 curl_easy_setopt(e, CURLOPT_USERAGENT,
c->user_agent);
908 if (
c->http_proxy &&
c->http_proxy[0])
909 curl_easy_setopt(e, CURLOPT_PROXY,
c->http_proxy);
911 curl_easy_setopt(e, CURLOPT_SSL_OPTIONS, (
long)CURLSSLOPT_NATIVE_CA);
912 curl_easy_setopt(e, CURLOPT_SSL_VERIFYPEER,
c->tls_verify ? 1L : 0
L);
913 curl_easy_setopt(e, CURLOPT_SSL_VERIFYHOST,
c->tls_verify ? 2L : 0
L);
915 curl_easy_setopt(e, CURLOPT_CAINFO,
c->ca_file);
917 curl_easy_setopt(e, CURLOPT_SSLCERT,
c->cert_file);
919 curl_easy_setopt(e, CURLOPT_SSLKEY,
c->key_file);
921 curl_easy_setopt(e, CURLOPT_COOKIEFILE,
"");
922 if (
c->cookies &&
c->cookies[0]) {
930 curl_easy_setopt(e, CURLOPT_COOKIELIST, sc);
940 curl_easy_setopt(e, CURLOPT_HTTPHEADER,
c->header_list);
946 struct timespec ts = { .tv_sec = t / 1000000,
947 .tv_nsec = (t % 1000000) * 1000 };
959 while (!
c->probed && !
c->error) {
969 ret =
c->error ?
c->error :
AVERROR(EIO);
983 curl_version_info_data *info = curl_version_info(CURLVERSION_NOW);
984 if (!(info->features & CURL_VERSION_THREADSAFE))
988 const char *eff_url =
h->filename;
992 c->content_size = -1;
993 c->request_start =
c->off;
995 c->logical_pos =
c->off;
1022 c->easy = curl_easy_init();
1043 h->is_streamed = !
c->seekable;
1069 c->logical_pos += n;
1102 const int64_t content_size =
c->content_size;
1103 const int seekable =
c->seekable;
1107 return content_size >= 0 ? content_size :
AVERROR(ENOSYS);
1117 if (
pos > INT64_MAX -
c->logical_pos)
1119 newpos =
c->logical_pos +
pos;
1122 if (content_size < 0)
1124 if (
pos > INT64_MAX - content_size)
1126 newpos = content_size +
pos;
1134 if (newpos ==
c->logical_pos)
1140 c->logical_pos = newpos;
1153 curl_easy_cleanup(
c->easy);
1157 if (
c->private_loop)
1163 curl_slist_free_all(
c->header_list);
1171#define OFFSET(x) offsetof(CurlContext, x)
1172#define D AV_OPT_FLAG_DECODING_PARAM
1173#define E AV_OPT_FLAG_ENCODING_PARAM
1177 {
"headers",
"set custom HTTP headers, can override built in default headers",
OFFSET(headers),
AV_OPT_TYPE_STRING, { .str =
NULL }, 0, 0,
D |
E },
1179 {
"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 },
1182 {
"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 },
1183 {
"seekable",
"control seekability of connection",
OFFSET(seekable_opt),
AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1,
D },
1184 {
"tls_verify",
"verify the peer certificate and hostname",
OFFSET(tls_verify),
AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1,
D |
E },
1188 {
"connect_timeout",
"connection timeout in seconds (0 = libcurl default)",
OFFSET(connect_timeout),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX / 1000,
D |
E },
1189 {
"max_redirects",
"maximum number of redirects to follow",
OFFSET(max_redirects),
AV_OPT_TYPE_INT, { .i64 = 16 }, 0, INT_MAX,
D },
1190 {
"multiple_requests",
"reuse the connection across requests (HTTP keep-alive)",
OFFSET(multiple_requests),
AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1,
D |
E },
1191 {
"max_retries",
"maximum number of retries after a recoverable error",
OFFSET(max_retries),
AV_OPT_TYPE_INT, { .i64 = 5 }, 0, INT_MAX,
D },
1193 {
"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 },
1194 {
"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 },
1195 {
"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" },
1196 {
"auto",
"negotiate the best supported version", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_NONE }, 0, 0,
D, .unit =
"http_version" },
1197 {
"1.0",
"HTTP/1.0", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_1_0 }, 0, 0,
D, .unit =
"http_version" },
1198 {
"1.1",
"HTTP/1.1", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_1_1 }, 0, 0,
D, .unit =
"http_version" },
1199 {
"2",
"HTTP/2", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_2 }, 0, 0,
D, .unit =
"http_version" },
1200 {
"2tls",
"HTTP/2 over TLS only", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_2TLS }, 0, 0,
D, .unit =
"http_version" },
1201 {
"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" },
1202 {
"3",
"HTTP/3, fall back to earlier versions", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_3 }, 0, 0,
D, .unit =
"http_version" },
1203 {
"3only",
"HTTP/3 only", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_3ONLY }, 0, 0,
D, .unit =
"http_version" },
1208 .class_name =
"libcurl",
1223 .default_whitelist =
"http,https,libcurl",
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
#define flags(name, subs,...)
static void do_exit(VideoState *is)
@ 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_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 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.
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_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.
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_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 int ff_http_averror(int status_code, int default_averror)
#define AV_MUTEX_INITIALIZER
static int ff_thread_setname(const char *name)
#define CURL_DEFAULT_BUFFER_SIZE
static int setup_protocols(CurlContext *c)
const URLProtocol ff_libcurl_protocol
static void execute_command(CurlLoop *loop, CurlCmd *cmd)
static int curl_loop_attach(CurlContext *c, AVFormatContext *avfc)
static void print_statistics(CurlLoop *loop)
static int wait_for_probe(CurlContext *c)
static int64_t parse_offset(const char *s)
static void update_statistics(CurlContext *c)
static int is_recoverable(CURLcode code)
static void start_request(CurlContext *c)
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)
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 void setup_curl(CurlContext *c)
static void curl_loop_destroy(CurlLoop *loop)
static void curl_cond_wait(CurlContext *c)
static int libcurl_close(URLContext *h)
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 struct curl_slist * 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 curl_dispatch(CurlLoop *loop, enum cmd_kind kind, CurlContext *c, int64_t pos, int sync)
static int curlcode_to_averror(CURLcode code)
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.
struct curl_slist * header_list
int64_t initial_request_size
int64_t hdr_content_total
int64_t hdr_content_start
struct CurlLoop * curl_loop
Shared libcurl event loop, created on demand on the first use.
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)