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
165 case CURLE_OK:
return 0;
166 case CURLE_URL_MALFORMAT:
167 case CURLE_UNSUPPORTED_PROTOCOL:
return AVERROR(EINVAL);
168 case CURLE_COULDNT_RESOLVE_PROXY:
169 case CURLE_COULDNT_RESOLVE_HOST:
return AVERROR(EHOSTUNREACH);
170 case CURLE_COULDNT_CONNECT:
return AVERROR(ECONNREFUSED);
171 case CURLE_OPERATION_TIMEDOUT:
return AVERROR(ETIMEDOUT);
172 case CURLE_LOGIN_DENIED:
173 case CURLE_REMOTE_ACCESS_DENIED:
return AVERROR(EACCES);
174 case CURLE_OUT_OF_MEMORY:
return AVERROR(ENOMEM);
175 case CURLE_PEER_FAILED_VERIFICATION:
184 case CURLE_RECV_ERROR:
185 case CURLE_SEND_ERROR:
186 case CURLE_PARTIAL_FILE:
187 case CURLE_OPERATION_TIMEDOUT:
188 case CURLE_GOT_NOTHING:
189 case CURLE_COULDNT_CONNECT:
190 case CURLE_COULDNT_RESOLVE_HOST:
192 case CURLE_HTTP2_STREAM:
206 size_t bytes =
size * nmemb;
211 if (
c->aborted || !
c->stream_ok) {
213 return CURL_WRITEFUNC_ERROR;
216 if (
c->seek_queued) {
226 return CURL_WRITEFUNC_PAUSE;
231 c->request_received += bytes;
241 return v < 0 ? -1 : v;
253 const char *
range = v + 6, *end;
254 if (
range[0] !=
'*') {
256 if ((end = strchr(
range,
'-')))
260 const char *slash = strchr(
range,
'/');
261 if (slash && slash[1] !=
'*')
273 c->hdr_accept_ranges = 0;
274 c->hdr_compressed = 0;
275 c->hdr_content_start = -1;
276 c->hdr_content_end = -1;
277 c->hdr_content_total = -1;
281 c->hdr_accept_ranges = !!
av_stristr(ptr + 14,
"bytes");
285 c->hdr_compressed = !
av_stristr(ptr + 17,
"identity");
294 while (n && (ptr[n - 1] ==
'\r' || ptr[n - 1] ==
'\n'))
299 curl_easy_getinfo(
c->easy, CURLINFO_RESPONSE_CODE, &status);
303 if (status < 200 || (status >= 300 && status < 400))
307 if (status >= 200 && status < 300) {
308 int64_t content_start = status == 206 ?
c->hdr_content_start : 0;
312 if ((
c->probed ?
c->seekable :
c->off > 0) &&
313 content_start !=
c->request_start) {
315 "with offset %"PRId64
" (expected %"PRId64
")\n",
316 content_start,
c->request_start);
317 c->loop->num_errors++;
330 const char *eff =
NULL;
331 if (curl_easy_getinfo(
c->easy, CURLINFO_EFFECTIVE_URL, &eff) == CURLE_OK
344 c->seekable = !
c->hdr_compressed &&
345 (status == 206 ||
c->hdr_accept_ranges);
346 if (!
c->hdr_compressed) {
347 int64_t total =
c->hdr_content_total;
348 if (total < 0 && status != 206) {
350 if (curl_easy_getinfo(
c->easy, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T,
351 &cl) == CURLE_OK && cl >= 0)
356 c->content_size = total;
359 if (
c->hdr_content_end >= 0)
360 c->request_end =
c->hdr_content_end;
362 c->request_end =
c->content_size > 0 ?
c->content_size - 1 : -1;
366 if (
c->seekable_opt >= 0)
367 c->seekable =
c->seekable_opt;
369 c->loop->num_errors++;
382 curl_off_t ultotal, curl_off_t ulnow)
387 aborted =
c->aborted;
396 if (!
c->probed ||
c->seekable) {
400 if (
c->is_initial &&
c->initial_request_size > 0)
406 if (
c->content_size > 0)
407 end =
FFMIN(end,
c->content_size - 1);
409 end =
FFMIN(end,
c->end_off - 1);
410 snprintf(
range,
sizeof(
range),
"%"PRId64
"-%"PRId64, start, end);
412 snprintf(
range,
sizeof(
range),
"%"PRId64
"-", start);
414 curl_easy_setopt(
c->easy, CURLOPT_RANGE,
range);
416 curl_easy_setopt(
c->easy, CURLOPT_RANGE,
NULL);
418 c->loop->num_requests++;
419 c->request_received = 0;
422 CURLMcode res = curl_multi_add_handle(
c->loop->multi,
c->easy);
423 if (res != CURLM_OK) {
425 curl_multi_strerror(res));
440 curl_off_t recv = 0, time = 0;
441 curl_easy_getinfo(e, CURLINFO_SIZE_DOWNLOAD_T, &recv);
442 curl_easy_getinfo(e, CURLINFO_TOTAL_TIME_T, &time);
448 loop->total_bytes += recv;
449 loop->total_time_us += time;
452 long num_conns = 0, num_redirs = 0;
453 curl_easy_getinfo(e, CURLINFO_NUM_CONNECTS, &num_conns);
454 curl_easy_getinfo(e, CURLINFO_REDIRECT_COUNT, &num_redirs);
455 loop->num_connections += (int) num_conns;
456 loop->num_redirects += (int) num_redirs;
466 aborted =
c->aborted;
467 received =
c->request_received;
469 if (received > INT64_MAX -
c->request_start) {
476 c->request_start += received;
477 c->request_received = 0;
488 c->loop->num_errors++;
497 if (
c->seek_queued) {
504 if (
code == CURLE_OK &&
c->stream_ok) {
506 int64_t file_end =
c->content_size > 0 ?
c->content_size - 1 : -1;
508 file_end =
FFMIN(file_end,
c->end_off - 1);
509 if (
c->seekable &&
c->request_end >= 0 &&
c->request_end < file_end) {
523 c->loop->num_errors++;
528 c->retry_count <
c->max_retries) {
531 c->retry_count,
c->request_start);
553 if (
c->short_seek_size <= 0 ||
557 const int64_t last =
c->request_end -
c->request_start;
558 return last -
c->request_received <
c->short_seek_size;
571 curl_multi_remove_handle(
loop->multi,
c->easy);
580 curl_easy_pause(
c->easy, CURLPAUSE_CONT);
585 }
else if (
c->active) {
586 curl_multi_remove_handle(
loop->multi,
c->easy);
591 const int was_paused =
c->paused;
595 c->request_start = cmd->pos;
596 c->request_received = 0;
601 curl_easy_pause(
c->easy, CURLPAUSE_CONT);
618 cmd =
loop->cmd_head;
620 loop->cmd_head = cmd->next;
643 curl_multi_perform(
loop->multi, &running);
645 while ((msg = curl_multi_info_read(
loop->multi, &
left))) {
647 if (msg->msg != CURLMSG_DONE)
649 curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &
c);
650 curl_multi_remove_handle(
loop->multi, msg->easy_handle);
681 loop->cmd_tail->next = cmd;
683 loop->cmd_head = cmd;
684 loop->cmd_tail = cmd;
685 curl_multi_wakeup(
loop->multi);
709 if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK)
712 loop->multi = curl_multi_init();
715 curl_multi_setopt(
loop->multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
717 loop->share = curl_share_init();
720 curl_share_setopt(
loop->share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
721 curl_share_setopt(
loop->share, CURLSHOPT_SHARE, CURL_LOCK_DATA_HSTS);
729 curl_multi_cleanup(
loop->multi);
730 curl_share_cleanup(
loop->share);
731 curl_global_cleanup();
744 if (
loop->total_bytes) {
745 double time =
loop->total_time_us / 1000000.0;
746 double avg = time ?
loop->total_bytes / time : 0;
748 "libcurl: Overall %"PRId64
" bytes received in %.0f ms = %.0f kB/s\n",
749 loop->total_bytes, time * 1e3,
avg / 1e3);
752 if (
loop->num_connections ||
loop->num_errors) {
754 "libcurl: %d connections, %d redirects, %d requests, %d errors\n",
755 loop->num_connections,
loop->num_redirects,
loop->num_requests,
764 curl_multi_wakeup(
loop->multi);
770 curl_multi_cleanup(
loop->multi);
771 curl_share_cleanup(
loop->share);
777 curl_global_cleanup();
789 return c->loop ? 0 :
AVERROR(ENOMEM);
800 return c->loop ? 0 :
AVERROR(ENOMEM);
818 size_t size,
void *userdata)
824 case CURLINFO_TEXT:
prefix =
"* ";
break;
825 case CURLINFO_HEADER_IN:
prefix =
"< ";
break;
826 case CURLINFO_HEADER_OUT:
prefix =
"> ";
break;
832 const char *nl = memchr(p,
'\n', end - p);
833 size_t len = (nl ? nl : end) - p;
834 while (
len && p[
len - 1] ==
'\r')
847 struct curl_slist *list =
NULL;
849 if (
c->referer &&
c->referer[0]) {
852 list = curl_slist_append(list,
h);
856 if (
c->headers &&
c->headers[0]) {
862 list = curl_slist_append(list,
line);
871 const char *wl =
c->h->protocol_whitelist;
872 const char *bl =
c->h->protocol_blacklist;
879 curl_version_info_data *info = curl_version_info(CURLVERSION_NOW);
880 for (
const char *
const *p = info->protocols; *p; p++) {
881 const char *proto = *p;
904 curl_easy_setopt(
c->easy, CURLOPT_PROTOCOLS_STR, bp.str);
905 curl_easy_setopt(
c->easy, CURLOPT_REDIR_PROTOCOLS_STR, bp.str);
913 const char *url =
c->h->filename;
918 curl_easy_setopt(e, CURLOPT_URL, url);
919 curl_easy_setopt(e, CURLOPT_PRIVATE,
c);
920 curl_easy_setopt(e, CURLOPT_NOSIGNAL, 1L);
921 curl_easy_setopt(e, CURLOPT_SHARE,
c->loop->share);
924 curl_easy_setopt(e, CURLOPT_WRITEDATA,
c);
926 curl_easy_setopt(e, CURLOPT_HEADERDATA,
c);
928 curl_easy_setopt(e, CURLOPT_NOPROGRESS, 0
L);
930 curl_easy_setopt(e, CURLOPT_XFERINFODATA,
c);
933 curl_easy_setopt(e, CURLOPT_VERBOSE, 1L);
935 curl_easy_setopt(e, CURLOPT_DEBUGDATA,
c);
938 curl_easy_setopt(e, CURLOPT_FOLLOWLOCATION, 1L);
939 curl_easy_setopt(e, CURLOPT_MAXREDIRS, (
long)
c->max_redirects);
940 curl_easy_setopt(e, CURLOPT_HTTP_VERSION, (
long)
c->http_version);
941 curl_easy_setopt(e, CURLOPT_TCP_KEEPALIVE,
c->multiple_requests ? 1L : 0
L);
942 curl_easy_setopt(e, CURLOPT_FORBID_REUSE,
c->multiple_requests ? 0
L : 1L);
943 curl_easy_setopt(e, CURLOPT_HSTS_CTRL, (
long)CURLHSTS_ENABLE);
944 curl_easy_setopt(e, CURLOPT_ACCEPT_ENCODING,
945 c->off > 0 ||
c->end_off > 0 ?
"identity" :
"");
946 if (
c->connect_timeout > 0)
947 curl_easy_setopt(e, CURLOPT_CONNECTTIMEOUT_MS,
948 (
long)
c->connect_timeout * 1000);
950 if (
c->user_agent &&
c->user_agent[0])
951 curl_easy_setopt(e, CURLOPT_USERAGENT,
c->user_agent);
952 if (
c->http_proxy &&
c->http_proxy[0])
953 curl_easy_setopt(e, CURLOPT_PROXY,
c->http_proxy);
955 curl_easy_setopt(e, CURLOPT_SSL_OPTIONS, (
long)CURLSSLOPT_NATIVE_CA);
956 curl_easy_setopt(e, CURLOPT_SSL_VERIFYPEER,
c->tls_verify ? 1L : 0
L);
957 curl_easy_setopt(e, CURLOPT_SSL_VERIFYHOST,
c->tls_verify ? 2L : 0
L);
959 curl_easy_setopt(e, CURLOPT_CAINFO,
c->ca_file);
961 curl_easy_setopt(e, CURLOPT_SSLCERT,
c->cert_file);
963 curl_easy_setopt(e, CURLOPT_SSLKEY,
c->key_file);
965 curl_easy_setopt(e, CURLOPT_COOKIEFILE,
"");
966 if (
c->cookies &&
c->cookies[0]) {
974 curl_easy_setopt(e, CURLOPT_COOKIELIST, sc);
984 curl_easy_setopt(e, CURLOPT_HTTPHEADER,
c->header_list);
990 struct timespec ts = { .tv_sec = t / 1000000,
991 .tv_nsec = (t % 1000000) * 1000 };
1003 while (!
c->probed && !
c->status) {
1013 ret =
c->status ?
c->status :
AVERROR(EIO);
1027 curl_version_info_data *info = curl_version_info(CURLVERSION_NOW);
1028 if (!(info->features & CURL_VERSION_THREADSAFE))
1032 const char *eff_url =
h->filename;
1036 c->content_size = -1;
1037 c->request_start =
c->off;
1038 c->request_end = -1;
1039 c->logical_pos =
c->off;
1066 c->easy = curl_easy_init();
1087 h->is_streamed = !
c->seekable;
1113 c->logical_pos += n;
1142 const int64_t content_size =
c->content_size;
1143 const int seekable =
c->seekable;
1147 return content_size >= 0 ? content_size :
AVERROR(ENOSYS);
1157 if (
pos > INT64_MAX -
c->logical_pos)
1159 newpos =
c->logical_pos +
pos;
1162 if (content_size < 0)
1164 if (
pos > INT64_MAX - content_size)
1166 newpos = content_size +
pos;
1174 if (newpos ==
c->logical_pos)
1180 c->logical_pos = newpos;
1193 curl_easy_cleanup(
c->easy);
1197 if (
c->private_loop)
1203 curl_slist_free_all(
c->header_list);
1214 if (
c->short_seek_size >= 1)
1215 return FFMIN(
c->short_seek_size, INT_MAX);
1219#define OFFSET(x) offsetof(CurlContext, x)
1220#define D AV_OPT_FLAG_DECODING_PARAM
1221#define E AV_OPT_FLAG_ENCODING_PARAM
1225 {
"headers",
"set custom HTTP headers, can override built in default headers",
OFFSET(headers),
AV_OPT_TYPE_STRING, { .str =
NULL }, 0, 0,
D |
E },
1227 {
"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 },
1230 {
"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 },
1231 {
"seekable",
"control seekability of connection",
OFFSET(seekable_opt),
AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1,
D },
1232 {
"tls_verify",
"verify the peer certificate and hostname",
OFFSET(tls_verify),
AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1,
D |
E },
1236 {
"connect_timeout",
"connection timeout in seconds (0 = libcurl default)",
OFFSET(connect_timeout),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX / 1000,
D |
E },
1237 {
"max_redirects",
"maximum number of redirects to follow",
OFFSET(max_redirects),
AV_OPT_TYPE_INT, { .i64 = 16 }, 0, INT_MAX,
D },
1238 {
"multiple_requests",
"reuse the connection across requests (HTTP keep-alive)",
OFFSET(multiple_requests),
AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1,
D |
E },
1239 {
"max_retries",
"maximum number of retries after a recoverable error",
OFFSET(max_retries),
AV_OPT_TYPE_INT, { .i64 = 5 }, 0, INT_MAX,
D },
1241 {
"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 },
1242 {
"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 },
1243 {
"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" },
1244 {
"auto",
"negotiate the best supported version", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_NONE }, 0, 0,
D, .unit =
"http_version" },
1245 {
"1.0",
"HTTP/1.0", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_1_0 }, 0, 0,
D, .unit =
"http_version" },
1246 {
"1.1",
"HTTP/1.1", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_1_1 }, 0, 0,
D, .unit =
"http_version" },
1247 {
"2",
"HTTP/2", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_2 }, 0, 0,
D, .unit =
"http_version" },
1248 {
"2tls",
"HTTP/2 over TLS only", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_2TLS }, 0, 0,
D, .unit =
"http_version" },
1249 {
"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" },
1250 {
"3",
"HTTP/3, fall back to earlier versions", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_3 }, 0, 0,
D, .unit =
"http_version" },
1251 {
"3only",
"HTTP/3 only", 0,
AV_OPT_TYPE_CONST, { .i64 = CURL_HTTP_VERSION_3ONLY }, 0, 0,
D, .unit =
"http_version" },
1252 {
"short_seek_size",
"threshold to favor readahead over seek",
OFFSET(short_seek_size),
AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX,
D },
1257 .class_name =
"libcurl",
1273 .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 int test_short_seek(CurlContext *c)
static int libcurl_get_short_seek(URLContext *h)
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)