FFmpeg
http.c
Go to the documentation of this file.
1 /*
2  * HTTP protocol for ffmpeg client
3  * Copyright (c) 2000, 2001 Fabrice Bellard
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "config.h"
23 
24 #if CONFIG_ZLIB
25 #include <zlib.h>
26 #endif /* CONFIG_ZLIB */
27 
28 #include "libavutil/avassert.h"
29 #include "libavutil/avstring.h"
30 #include "libavutil/opt.h"
31 #include "libavutil/time.h"
32 #include "libavutil/parseutils.h"
33 
34 #include "avformat.h"
35 #include "http.h"
36 #include "httpauth.h"
37 #include "internal.h"
38 #include "network.h"
39 #include "os_support.h"
40 #include "url.h"
41 
42 /* XXX: POST protocol is not completely implemented because ffmpeg uses
43  * only a subset of it. */
44 
45 /* The IO buffer size is unrelated to the max URL size in itself, but needs
46  * to be large enough to fit the full request headers (including long
47  * path names). */
48 #define BUFFER_SIZE MAX_URL_SIZE
49 #define MAX_REDIRECTS 8
50 #define HTTP_SINGLE 1
51 #define HTTP_MUTLI 2
52 #define MAX_EXPIRY 19
53 #define WHITESPACES " \n\t\r"
54 typedef enum {
60 
61 typedef struct HTTPContext {
62  const AVClass *class;
64  unsigned char buffer[BUFFER_SIZE], *buf_ptr, *buf_end;
66  int http_code;
67  /* Used if "Transfer-Encoding: chunked" otherwise -1. */
68  uint64_t chunksize;
69  int chunkend;
70  uint64_t off, end_off, filesize;
71  char *location;
74  char *http_proxy;
75  char *headers;
76  char *mime_type;
77  char *http_version;
78  char *user_agent;
79  char *referer;
80 #if FF_API_HTTP_USER_AGENT
81  char *user_agent_deprecated;
82 #endif
83  char *content_type;
84  /* Set if the server correctly handles Connection: close and will close
85  * the connection after feeding us the content. */
86  int willclose;
87  int seekable; /**< Control seekability, 0 = disable, 1 = enable, -1 = probe. */
89  /* A flag which indicates if the end of chunked encoding has been sent. */
91  /* A flag which indicates we have finished to read POST reply. */
93  /* A flag which indicates if we use persistent connections. */
97  int is_akamai;
99  char *cookies; ///< holds newline (\n) delimited Set-Cookie header field values (without the "Set-Cookie: " field name)
100  /* A dictionary containing cookies keyed by cookie name */
102  int icy;
103  /* how much data was read since the last ICY metadata packet */
104  uint64_t icy_data_read;
105  /* after how many bytes of read data a new metadata packet will be found */
106  uint64_t icy_metaint;
110 #if CONFIG_ZLIB
111  int compressed;
112  z_stream inflate_stream;
113  uint8_t *inflate_buffer;
114 #endif /* CONFIG_ZLIB */
116  /* -1 = try to send if applicable, 0 = always disabled, 1 = always enabled */
118  char *method;
123  int listen;
124  char *resource;
129 } HTTPContext;
130 
131 #define OFFSET(x) offsetof(HTTPContext, x)
132 #define D AV_OPT_FLAG_DECODING_PARAM
133 #define E AV_OPT_FLAG_ENCODING_PARAM
134 #define DEFAULT_USER_AGENT "Lavf/" AV_STRINGIFY(LIBAVFORMAT_VERSION)
135 
136 static const AVOption options[] = {
137  { "seekable", "control seekability of connection", OFFSET(seekable), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, D },
138  { "chunked_post", "use chunked transfer-encoding for posts", OFFSET(chunked_post), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
139  { "http_proxy", "set HTTP proxy to tunnel through", OFFSET(http_proxy), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D | E },
140  { "headers", "set custom HTTP headers, can override built in default headers", OFFSET(headers), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D | E },
141  { "content_type", "set a specific content type for the POST messages", OFFSET(content_type), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D | E },
142  { "user_agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, { .str = DEFAULT_USER_AGENT }, 0, 0, D },
143  { "referer", "override referer header", OFFSET(referer), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D },
144 #if FF_API_HTTP_USER_AGENT
145  { "user-agent", "use the \"user_agent\" option instead", OFFSET(user_agent_deprecated), AV_OPT_TYPE_STRING, { .str = DEFAULT_USER_AGENT }, 0, 0, D|AV_OPT_FLAG_DEPRECATED },
146 #endif
147  { "multiple_requests", "use persistent connections", OFFSET(multiple_requests), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D | E },
148  { "post_data", "set custom HTTP post data", OFFSET(post_data), AV_OPT_TYPE_BINARY, .flags = D | E },
149  { "mime_type", "export the MIME type", OFFSET(mime_type), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY },
150  { "http_version", "export the http response version", OFFSET(http_version), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_EXPORT | AV_OPT_FLAG_READONLY },
151  { "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 },
152  { "icy", "request ICY metadata", OFFSET(icy), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, D },
153  { "icy_metadata_headers", "return ICY metadata headers", OFFSET(icy_metadata_headers), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_EXPORT },
154  { "icy_metadata_packet", "return current ICY metadata packet", OFFSET(icy_metadata_packet), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_EXPORT },
155  { "metadata", "metadata read from the bitstream", OFFSET(metadata), AV_OPT_TYPE_DICT, {0}, 0, 0, AV_OPT_FLAG_EXPORT },
156  { "auth_type", "HTTP authentication type", OFFSET(auth_state.auth_type), AV_OPT_TYPE_INT, { .i64 = HTTP_AUTH_NONE }, HTTP_AUTH_NONE, HTTP_AUTH_BASIC, D | E, "auth_type"},
157  { "none", "No auth method set, autodetect", 0, AV_OPT_TYPE_CONST, { .i64 = HTTP_AUTH_NONE }, 0, 0, D | E, "auth_type"},
158  { "basic", "HTTP basic authentication", 0, AV_OPT_TYPE_CONST, { .i64 = HTTP_AUTH_BASIC }, 0, 0, D | E, "auth_type"},
159  { "send_expect_100", "Force sending an Expect: 100-continue header for POST", OFFSET(send_expect_100), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, E },
160  { "location", "The actual location of the data received", OFFSET(location), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D | E },
161  { "offset", "initial byte offset", OFFSET(off), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, D },
162  { "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 },
163  { "method", "Override the HTTP method or set the expected HTTP method from a client", OFFSET(method), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D | E },
164  { "reconnect", "auto reconnect after disconnect before EOF", OFFSET(reconnect), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D },
165  { "reconnect_at_eof", "auto reconnect at EOF", OFFSET(reconnect_at_eof), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D },
166  { "reconnect_streamed", "auto reconnect streamed / non seekable streams", OFFSET(reconnect_streamed), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D },
167  { "reconnect_delay_max", "max reconnect delay in seconds after which to give up", OFFSET(reconnect_delay_max), AV_OPT_TYPE_INT, { .i64 = 120 }, 0, UINT_MAX/1000/1000, D },
168  { "listen", "listen on HTTP", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, D | E },
169  { "resource", "The resource requested by a client", OFFSET(resource), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
170  { "reply_code", "The http status code to return to a client", OFFSET(reply_code), AV_OPT_TYPE_INT, { .i64 = 200}, INT_MIN, 599, E},
171  { NULL }
172 };
173 
174 static int http_connect(URLContext *h, const char *path, const char *local_path,
175  const char *hoststr, const char *auth,
176  const char *proxyauth, int *new_location);
177 static int http_read_header(URLContext *h, int *new_location);
178 static int http_shutdown(URLContext *h, int flags);
179 
181 {
182  memcpy(&((HTTPContext *)dest->priv_data)->auth_state,
183  &((HTTPContext *)src->priv_data)->auth_state,
184  sizeof(HTTPAuthState));
185  memcpy(&((HTTPContext *)dest->priv_data)->proxy_auth_state,
186  &((HTTPContext *)src->priv_data)->proxy_auth_state,
187  sizeof(HTTPAuthState));
188 }
189 
191 {
192  const char *path, *proxy_path, *lower_proto = "tcp", *local_path;
193  char hostname[1024], hoststr[1024], proto[10];
194  char auth[1024], proxyauth[1024] = "";
195  char path1[MAX_URL_SIZE];
196  char buf[1024], urlbuf[MAX_URL_SIZE];
197  int port, use_proxy, err, location_changed = 0;
198  HTTPContext *s = h->priv_data;
199 
200  av_url_split(proto, sizeof(proto), auth, sizeof(auth),
201  hostname, sizeof(hostname), &port,
202  path1, sizeof(path1), s->location);
203  ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL);
204 
205  proxy_path = s->http_proxy ? s->http_proxy : getenv("http_proxy");
206  use_proxy = !ff_http_match_no_proxy(getenv("no_proxy"), hostname) &&
207  proxy_path && av_strstart(proxy_path, "http://", NULL);
208 
209  if (!strcmp(proto, "https")) {
210  lower_proto = "tls";
211  use_proxy = 0;
212  if (port < 0)
213  port = 443;
214  }
215  if (port < 0)
216  port = 80;
217 
218  if (path1[0] == '\0')
219  path = "/";
220  else
221  path = path1;
222  local_path = path;
223  if (use_proxy) {
224  /* Reassemble the request URL without auth string - we don't
225  * want to leak the auth to the proxy. */
226  ff_url_join(urlbuf, sizeof(urlbuf), proto, NULL, hostname, port, "%s",
227  path1);
228  path = urlbuf;
229  av_url_split(NULL, 0, proxyauth, sizeof(proxyauth),
230  hostname, sizeof(hostname), &port, NULL, 0, proxy_path);
231  }
232 
233  ff_url_join(buf, sizeof(buf), lower_proto, NULL, hostname, port, NULL);
234 
235  if (!s->hd) {
237  &h->interrupt_callback, options,
239  if (err < 0)
240  return err;
241  }
242 
243  err = http_connect(h, path, local_path, hoststr,
244  auth, proxyauth, &location_changed);
245  if (err < 0)
246  return err;
247 
248  return location_changed;
249 }
250 
251 /* return non zero if error */
252 static int http_open_cnx(URLContext *h, AVDictionary **options)
253 {
254  HTTPAuthType cur_auth_type, cur_proxy_auth_type;
255  HTTPContext *s = h->priv_data;
256  int location_changed, attempts = 0, redirects = 0;
257 redo:
258  av_dict_copy(options, s->chained_options, 0);
259 
260  cur_auth_type = s->auth_state.auth_type;
261  cur_proxy_auth_type = s->auth_state.auth_type;
262 
263  location_changed = http_open_cnx_internal(h, options);
264  if (location_changed < 0)
265  goto fail;
266 
267  attempts++;
268  if (s->http_code == 401) {
269  if ((cur_auth_type == HTTP_AUTH_NONE || s->auth_state.stale) &&
270  s->auth_state.auth_type != HTTP_AUTH_NONE && attempts < 4) {
271  ffurl_closep(&s->hd);
272  goto redo;
273  } else
274  goto fail;
275  }
276  if (s->http_code == 407) {
277  if ((cur_proxy_auth_type == HTTP_AUTH_NONE || s->proxy_auth_state.stale) &&
278  s->proxy_auth_state.auth_type != HTTP_AUTH_NONE && attempts < 4) {
279  ffurl_closep(&s->hd);
280  goto redo;
281  } else
282  goto fail;
283  }
284  if ((s->http_code == 301 || s->http_code == 302 ||
285  s->http_code == 303 || s->http_code == 307) &&
286  location_changed == 1) {
287  /* url moved, get next */
288  ffurl_closep(&s->hd);
289  if (redirects++ >= MAX_REDIRECTS)
290  return AVERROR(EIO);
291  /* Restart the authentication process with the new target, which
292  * might use a different auth mechanism. */
293  memset(&s->auth_state, 0, sizeof(s->auth_state));
294  attempts = 0;
295  location_changed = 0;
296  goto redo;
297  }
298  return 0;
299 
300 fail:
301  if (s->hd)
302  ffurl_closep(&s->hd);
303  if (location_changed < 0)
304  return location_changed;
305  return ff_http_averror(s->http_code, AVERROR(EIO));
306 }
308 {
309  int ret = 0;
310  HTTPContext *s = h->priv_data;
311 
312  /* flush the receive buffer when it is write only mode */
313  char buf[1024];
314  int read_ret;
315  read_ret = ffurl_read(s->hd, buf, sizeof(buf));
316  if (read_ret < 0) {
317  ret = read_ret;
318  }
319 
320  return ret;
321 }
322 
323 int ff_http_do_new_request(URLContext *h, const char *uri) {
324  return ff_http_do_new_request2(h, uri, NULL);
325 }
326 
328 {
329  HTTPContext *s = h->priv_data;
330  AVDictionary *options = NULL;
331  int ret;
332  char hostname1[1024], hostname2[1024], proto1[10], proto2[10];
333  int port1, port2;
334 
335  if (!h->prot ||
336  !(!strcmp(h->prot->name, "http") ||
337  !strcmp(h->prot->name, "https")))
338  return AVERROR(EINVAL);
339 
340  av_url_split(proto1, sizeof(proto1), NULL, 0,
341  hostname1, sizeof(hostname1), &port1,
342  NULL, 0, s->location);
343  av_url_split(proto2, sizeof(proto2), NULL, 0,
344  hostname2, sizeof(hostname2), &port2,
345  NULL, 0, uri);
346  if (port1 != port2 || strncmp(hostname1, hostname2, sizeof(hostname2)) != 0) {
347  av_log(h, AV_LOG_ERROR, "Cannot reuse HTTP connection for different host: %s:%d != %s:%d\n",
348  hostname1, port1,
349  hostname2, port2
350  );
351  return AVERROR(EINVAL);
352  }
353 
354  if (!s->end_chunked_post) {
355  ret = http_shutdown(h, h->flags);
356  if (ret < 0)
357  return ret;
358  }
359 
360  if (s->willclose)
361  return AVERROR_EOF;
362 
363  s->end_chunked_post = 0;
364  s->chunkend = 0;
365  s->off = 0;
366  s->icy_data_read = 0;
367  av_free(s->location);
368  s->location = av_strdup(uri);
369  if (!s->location)
370  return AVERROR(ENOMEM);
371 
372  if ((ret = av_opt_set_dict(s, opts)) < 0)
373  return ret;
374 
375  av_log(s, AV_LOG_INFO, "Opening \'%s\' for %s\n", uri, h->flags & AVIO_FLAG_WRITE ? "writing" : "reading");
376  ret = http_open_cnx(h, &options);
377  av_dict_free(&options);
378  return ret;
379 }
380 
381 int ff_http_averror(int status_code, int default_averror)
382 {
383  switch (status_code) {
384  case 400: return AVERROR_HTTP_BAD_REQUEST;
385  case 401: return AVERROR_HTTP_UNAUTHORIZED;
386  case 403: return AVERROR_HTTP_FORBIDDEN;
387  case 404: return AVERROR_HTTP_NOT_FOUND;
388  default: break;
389  }
390  if (status_code >= 400 && status_code <= 499)
391  return AVERROR_HTTP_OTHER_4XX;
392  else if (status_code >= 500)
394  else
395  return default_averror;
396 }
397 
398 static int http_write_reply(URLContext* h, int status_code)
399 {
400  int ret, body = 0, reply_code, message_len;
401  const char *reply_text, *content_type;
402  HTTPContext *s = h->priv_data;
403  char message[BUFFER_SIZE];
404  content_type = "text/plain";
405 
406  if (status_code < 0)
407  body = 1;
408  switch (status_code) {
410  case 400:
411  reply_code = 400;
412  reply_text = "Bad Request";
413  break;
415  case 403:
416  reply_code = 403;
417  reply_text = "Forbidden";
418  break;
420  case 404:
421  reply_code = 404;
422  reply_text = "Not Found";
423  break;
424  case 200:
425  reply_code = 200;
426  reply_text = "OK";
427  content_type = s->content_type ? s->content_type : "application/octet-stream";
428  break;
430  case 500:
431  reply_code = 500;
432  reply_text = "Internal server error";
433  break;
434  default:
435  return AVERROR(EINVAL);
436  }
437  if (body) {
438  s->chunked_post = 0;
439  message_len = snprintf(message, sizeof(message),
440  "HTTP/1.1 %03d %s\r\n"
441  "Content-Type: %s\r\n"
442  "Content-Length: %"SIZE_SPECIFIER"\r\n"
443  "%s"
444  "\r\n"
445  "%03d %s\r\n",
446  reply_code,
447  reply_text,
448  content_type,
449  strlen(reply_text) + 6, // 3 digit status code + space + \r\n
450  s->headers ? s->headers : "",
451  reply_code,
452  reply_text);
453  } else {
454  s->chunked_post = 1;
455  message_len = snprintf(message, sizeof(message),
456  "HTTP/1.1 %03d %s\r\n"
457  "Content-Type: %s\r\n"
458  "Transfer-Encoding: chunked\r\n"
459  "%s"
460  "\r\n",
461  reply_code,
462  reply_text,
463  content_type,
464  s->headers ? s->headers : "");
465  }
466  av_log(h, AV_LOG_TRACE, "HTTP reply header: \n%s----\n", message);
467  if ((ret = ffurl_write(s->hd, message, message_len)) < 0)
468  return ret;
469  return 0;
470 }
471 
472 static void handle_http_errors(URLContext *h, int error)
473 {
474  av_assert0(error < 0);
475  http_write_reply(h, error);
476 }
477 
479 {
480  int ret, err, new_location;
481  HTTPContext *ch = c->priv_data;
482  URLContext *cl = ch->hd;
483  switch (ch->handshake_step) {
484  case LOWER_PROTO:
485  av_log(c, AV_LOG_TRACE, "Lower protocol\n");
486  if ((ret = ffurl_handshake(cl)) > 0)
487  return 2 + ret;
488  if (ret < 0)
489  return ret;
491  ch->is_connected_server = 1;
492  return 2;
493  case READ_HEADERS:
494  av_log(c, AV_LOG_TRACE, "Read headers\n");
495  if ((err = http_read_header(c, &new_location)) < 0) {
496  handle_http_errors(c, err);
497  return err;
498  }
500  return 1;
501  case WRITE_REPLY_HEADERS:
502  av_log(c, AV_LOG_TRACE, "Reply code: %d\n", ch->reply_code);
503  if ((err = http_write_reply(c, ch->reply_code)) < 0)
504  return err;
505  ch->handshake_step = FINISH;
506  return 1;
507  case FINISH:
508  return 0;
509  }
510  // this should never be reached.
511  return AVERROR(EINVAL);
512 }
513 
514 static int http_listen(URLContext *h, const char *uri, int flags,
515  AVDictionary **options) {
516  HTTPContext *s = h->priv_data;
517  int ret;
518  char hostname[1024], proto[10];
519  char lower_url[100];
520  const char *lower_proto = "tcp";
521  int port;
522  av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
523  NULL, 0, uri);
524  if (!strcmp(proto, "https"))
525  lower_proto = "tls";
526  ff_url_join(lower_url, sizeof(lower_url), lower_proto, NULL, hostname, port,
527  NULL);
528  if ((ret = av_dict_set_int(options, "listen", s->listen, 0)) < 0)
529  goto fail;
530  if ((ret = ffurl_open_whitelist(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
531  &h->interrupt_callback, options,
533  )) < 0)
534  goto fail;
536  if (s->listen == HTTP_SINGLE) { /* single client */
537  s->reply_code = 200;
538  while ((ret = http_handshake(h)) > 0);
539  }
540 fail:
542  return ret;
543 }
544 
545 static int http_open(URLContext *h, const char *uri, int flags,
546  AVDictionary **options)
547 {
548  HTTPContext *s = h->priv_data;
549  int ret;
550 
551  if( s->seekable == 1 )
552  h->is_streamed = 0;
553  else
554  h->is_streamed = 1;
555 
556  s->filesize = UINT64_MAX;
557  s->location = av_strdup(uri);
558  if (!s->location)
559  return AVERROR(ENOMEM);
560  if (options)
561  av_dict_copy(&s->chained_options, *options, 0);
562 
563  if (s->headers) {
564  int len = strlen(s->headers);
565  if (len < 2 || strcmp("\r\n", s->headers + len - 2)) {
567  "No trailing CRLF found in HTTP header. Adding it.\n");
568  ret = av_reallocp(&s->headers, len + 3);
569  if (ret < 0)
570  return ret;
571  s->headers[len] = '\r';
572  s->headers[len + 1] = '\n';
573  s->headers[len + 2] = '\0';
574  }
575  }
576 
577  if (s->listen) {
578  return http_listen(h, uri, flags, options);
579  }
580  ret = http_open_cnx(h, options);
581  if (ret < 0)
583  return ret;
584 }
585 
587 {
588  int ret;
589  HTTPContext *sc = s->priv_data;
590  HTTPContext *cc;
591  URLContext *sl = sc->hd;
592  URLContext *cl = NULL;
593 
594  av_assert0(sc->listen);
595  if ((ret = ffurl_alloc(c, s->filename, s->flags, &sl->interrupt_callback)) < 0)
596  goto fail;
597  cc = (*c)->priv_data;
598  if ((ret = ffurl_accept(sl, &cl)) < 0)
599  goto fail;
600  cc->hd = cl;
601  cc->is_multi_client = 1;
602  return 0;
603 fail:
604  if (c) {
605  ffurl_closep(c);
606  }
607  return ret;
608 }
609 
610 static int http_getc(HTTPContext *s)
611 {
612  int len;
613  if (s->buf_ptr >= s->buf_end) {
614  len = ffurl_read(s->hd, s->buffer, BUFFER_SIZE);
615  if (len < 0) {
616  return len;
617  } else if (len == 0) {
618  return AVERROR_EOF;
619  } else {
620  s->buf_ptr = s->buffer;
621  s->buf_end = s->buffer + len;
622  }
623  }
624  return *s->buf_ptr++;
625 }
626 
627 static int http_get_line(HTTPContext *s, char *line, int line_size)
628 {
629  int ch;
630  char *q;
631 
632  q = line;
633  for (;;) {
634  ch = http_getc(s);
635  if (ch < 0)
636  return ch;
637  if (ch == '\n') {
638  /* process line */
639  if (q > line && q[-1] == '\r')
640  q--;
641  *q = '\0';
642 
643  return 0;
644  } else {
645  if ((q - line) < line_size - 1)
646  *q++ = ch;
647  }
648  }
649 }
650 
651 static int check_http_code(URLContext *h, int http_code, const char *end)
652 {
653  HTTPContext *s = h->priv_data;
654  /* error codes are 4xx and 5xx, but regard 401 as a success, so we
655  * don't abort until all headers have been parsed. */
656  if (http_code >= 400 && http_code < 600 &&
657  (http_code != 401 || s->auth_state.auth_type != HTTP_AUTH_NONE) &&
658  (http_code != 407 || s->proxy_auth_state.auth_type != HTTP_AUTH_NONE)) {
659  end += strspn(end, SPACE_CHARS);
660  av_log(h, AV_LOG_WARNING, "HTTP error %d %s\n", http_code, end);
661  return ff_http_averror(http_code, AVERROR(EIO));
662  }
663  return 0;
664 }
665 
666 static int parse_location(HTTPContext *s, const char *p)
667 {
668  char redirected_location[MAX_URL_SIZE], *new_loc;
669  ff_make_absolute_url(redirected_location, sizeof(redirected_location),
670  s->location, p);
671  new_loc = av_strdup(redirected_location);
672  if (!new_loc)
673  return AVERROR(ENOMEM);
674  av_free(s->location);
675  s->location = new_loc;
676  return 0;
677 }
678 
679 /* "bytes $from-$to/$document_size" */
680 static void parse_content_range(URLContext *h, const char *p)
681 {
682  HTTPContext *s = h->priv_data;
683  const char *slash;
684 
685  if (!strncmp(p, "bytes ", 6)) {
686  p += 6;
687  s->off = strtoull(p, NULL, 10);
688  if ((slash = strchr(p, '/')) && strlen(slash) > 0)
689  s->filesize = strtoull(slash + 1, NULL, 10);
690  }
691  if (s->seekable == -1 && (!s->is_akamai || s->filesize != 2147483647))
692  h->is_streamed = 0; /* we _can_ in fact seek */
693 }
694 
695 static int parse_content_encoding(URLContext *h, const char *p)
696 {
697  if (!av_strncasecmp(p, "gzip", 4) ||
698  !av_strncasecmp(p, "deflate", 7)) {
699 #if CONFIG_ZLIB
700  HTTPContext *s = h->priv_data;
701 
702  s->compressed = 1;
703  inflateEnd(&s->inflate_stream);
704  if (inflateInit2(&s->inflate_stream, 32 + 15) != Z_OK) {
705  av_log(h, AV_LOG_WARNING, "Error during zlib initialisation: %s\n",
706  s->inflate_stream.msg);
707  return AVERROR(ENOSYS);
708  }
709  if (zlibCompileFlags() & (1 << 17)) {
711  "Your zlib was compiled without gzip support.\n");
712  return AVERROR(ENOSYS);
713  }
714 #else
716  "Compressed (%s) content, need zlib with gzip support\n", p);
717  return AVERROR(ENOSYS);
718 #endif /* CONFIG_ZLIB */
719  } else if (!av_strncasecmp(p, "identity", 8)) {
720  // The normal, no-encoding case (although servers shouldn't include
721  // the header at all if this is the case).
722  } else {
723  av_log(h, AV_LOG_WARNING, "Unknown content coding: %s\n", p);
724  }
725  return 0;
726 }
727 
728 // Concat all Icy- header lines
729 static int parse_icy(HTTPContext *s, const char *tag, const char *p)
730 {
731  int len = 4 + strlen(p) + strlen(tag);
732  int is_first = !s->icy_metadata_headers;
733  int ret;
734 
735  av_dict_set(&s->metadata, tag, p, 0);
736 
737  if (s->icy_metadata_headers)
738  len += strlen(s->icy_metadata_headers);
739 
740  if ((ret = av_reallocp(&s->icy_metadata_headers, len)) < 0)
741  return ret;
742 
743  if (is_first)
744  *s->icy_metadata_headers = '\0';
745 
746  av_strlcatf(s->icy_metadata_headers, len, "%s: %s\n", tag, p);
747 
748  return 0;
749 }
750 
751 static int parse_set_cookie_expiry_time(const char *exp_str, struct tm *buf)
752 {
753  char exp_buf[MAX_EXPIRY];
754  int i, j, exp_buf_len = MAX_EXPIRY-1;
755  char *expiry;
756 
757  // strip off any punctuation or whitespace
758  for (i = 0, j = 0; exp_str[i] != '\0' && j < exp_buf_len; i++) {
759  if ((exp_str[i] >= '0' && exp_str[i] <= '9') ||
760  (exp_str[i] >= 'A' && exp_str[i] <= 'Z') ||
761  (exp_str[i] >= 'a' && exp_str[i] <= 'z')) {
762  exp_buf[j] = exp_str[i];
763  j++;
764  }
765  }
766  exp_buf[j] = '\0';
767  expiry = exp_buf;
768 
769  // move the string beyond the day of week
770  while ((*expiry < '0' || *expiry > '9') && *expiry != '\0')
771  expiry++;
772 
773  return av_small_strptime(expiry, "%d%b%Y%H%M%S", buf) ? 0 : AVERROR(EINVAL);
774 }
775 
776 static int parse_set_cookie(const char *set_cookie, AVDictionary **dict)
777 {
778  char *param, *next_param, *cstr, *back;
779 
780  if (!set_cookie[0])
781  return 0;
782 
783  if (!(cstr = av_strdup(set_cookie)))
784  return AVERROR(EINVAL);
785 
786  // strip any trailing whitespace
787  back = &cstr[strlen(cstr)-1];
788  while (strchr(WHITESPACES, *back)) {
789  *back='\0';
790  if (back == cstr)
791  break;
792  back--;
793  }
794 
795  next_param = cstr;
796  while ((param = av_strtok(next_param, ";", &next_param))) {
797  char *name, *value;
798  param += strspn(param, WHITESPACES);
799  if ((name = av_strtok(param, "=", &value))) {
800  if (av_dict_set(dict, name, value, 0) < 0) {
801  av_free(cstr);
802  return -1;
803  }
804  }
805  }
806 
807  av_free(cstr);
808  return 0;
809 }
810 
811 static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
812 {
813  AVDictionary *new_params = NULL;
814  AVDictionaryEntry *e, *cookie_entry;
815  char *eql, *name;
816 
817  // ensure the cookie is parsable
818  if (parse_set_cookie(p, &new_params))
819  return -1;
820 
821  // if there is no cookie value there is nothing to parse
822  cookie_entry = av_dict_get(new_params, "", NULL, AV_DICT_IGNORE_SUFFIX);
823  if (!cookie_entry || !cookie_entry->value) {
824  av_dict_free(&new_params);
825  return -1;
826  }
827 
828  // ensure the cookie is not expired or older than an existing value
829  if ((e = av_dict_get(new_params, "expires", NULL, 0)) && e->value) {
830  struct tm new_tm = {0};
831  if (!parse_set_cookie_expiry_time(e->value, &new_tm)) {
832  AVDictionaryEntry *e2;
833 
834  // if the cookie has already expired ignore it
835  if (av_timegm(&new_tm) < av_gettime() / 1000000) {
836  av_dict_free(&new_params);
837  return 0;
838  }
839 
840  // only replace an older cookie with the same name
841  e2 = av_dict_get(*cookies, cookie_entry->key, NULL, 0);
842  if (e2 && e2->value) {
843  AVDictionary *old_params = NULL;
844  if (!parse_set_cookie(p, &old_params)) {
845  e2 = av_dict_get(old_params, "expires", NULL, 0);
846  if (e2 && e2->value) {
847  struct tm old_tm = {0};
848  if (!parse_set_cookie_expiry_time(e->value, &old_tm)) {
849  if (av_timegm(&new_tm) < av_timegm(&old_tm)) {
850  av_dict_free(&new_params);
851  av_dict_free(&old_params);
852  return -1;
853  }
854  }
855  }
856  }
857  av_dict_free(&old_params);
858  }
859  }
860  }
861  av_dict_free(&new_params);
862 
863  // duplicate the cookie name (dict will dupe the value)
864  if (!(eql = strchr(p, '='))) return AVERROR(EINVAL);
865  if (!(name = av_strndup(p, eql - p))) return AVERROR(ENOMEM);
866 
867  // add the cookie to the dictionary
868  av_dict_set(cookies, name, eql, AV_DICT_DONT_STRDUP_KEY);
869 
870  return 0;
871 }
872 
873 static int cookie_string(AVDictionary *dict, char **cookies)
874 {
875  AVDictionaryEntry *e = NULL;
876  int len = 1;
877 
878  // determine how much memory is needed for the cookies string
879  while (e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX))
880  len += strlen(e->key) + strlen(e->value) + 1;
881 
882  // reallocate the cookies
883  e = NULL;
884  if (*cookies) av_free(*cookies);
885  *cookies = av_malloc(len);
886  if (!*cookies) return AVERROR(ENOMEM);
887  *cookies[0] = '\0';
888 
889  // write out the cookies
890  while (e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX))
891  av_strlcatf(*cookies, len, "%s%s\n", e->key, e->value);
892 
893  return 0;
894 }
895 
896 static int process_line(URLContext *h, char *line, int line_count,
897  int *new_location)
898 {
899  HTTPContext *s = h->priv_data;
900  const char *auto_method = h->flags & AVIO_FLAG_READ ? "POST" : "GET";
901  char *tag, *p, *end, *method, *resource, *version;
902  int ret;
903 
904  /* end of header */
905  if (line[0] == '\0') {
906  s->end_header = 1;
907  return 0;
908  }
909 
910  p = line;
911  if (line_count == 0) {
912  if (s->is_connected_server) {
913  // HTTP method
914  method = p;
915  while (*p && !av_isspace(*p))
916  p++;
917  *(p++) = '\0';
918  av_log(h, AV_LOG_TRACE, "Received method: %s\n", method);
919  if (s->method) {
920  if (av_strcasecmp(s->method, method)) {
921  av_log(h, AV_LOG_ERROR, "Received and expected HTTP method do not match. (%s expected, %s received)\n",
922  s->method, method);
923  return ff_http_averror(400, AVERROR(EIO));
924  }
925  } else {
926  // use autodetected HTTP method to expect
927  av_log(h, AV_LOG_TRACE, "Autodetected %s HTTP method\n", auto_method);
928  if (av_strcasecmp(auto_method, method)) {
929  av_log(h, AV_LOG_ERROR, "Received and autodetected HTTP method did not match "
930  "(%s autodetected %s received)\n", auto_method, method);
931  return ff_http_averror(400, AVERROR(EIO));
932  }
933  if (!(s->method = av_strdup(method)))
934  return AVERROR(ENOMEM);
935  }
936 
937  // HTTP resource
938  while (av_isspace(*p))
939  p++;
940  resource = p;
941  while (*p && !av_isspace(*p))
942  p++;
943  *(p++) = '\0';
944  av_log(h, AV_LOG_TRACE, "Requested resource: %s\n", resource);
945  if (!(s->resource = av_strdup(resource)))
946  return AVERROR(ENOMEM);
947 
948  // HTTP version
949  while (av_isspace(*p))
950  p++;
951  version = p;
952  while (*p && !av_isspace(*p))
953  p++;
954  *p = '\0';
955  if (av_strncasecmp(version, "HTTP/", 5)) {
956  av_log(h, AV_LOG_ERROR, "Malformed HTTP version string.\n");
957  return ff_http_averror(400, AVERROR(EIO));
958  }
959  av_log(h, AV_LOG_TRACE, "HTTP version string: %s\n", version);
960  } else {
961  if (av_strncasecmp(p, "HTTP/1.0", 8) == 0)
962  s->willclose = 1;
963  while (*p != '/' && *p != '\0')
964  p++;
965  while (*p == '/')
966  p++;
967  av_freep(&s->http_version);
968  s->http_version = av_strndup(p, 3);
969  while (!av_isspace(*p) && *p != '\0')
970  p++;
971  while (av_isspace(*p))
972  p++;
973  s->http_code = strtol(p, &end, 10);
974 
975  av_log(h, AV_LOG_TRACE, "http_code=%d\n", s->http_code);
976 
977  if ((ret = check_http_code(h, s->http_code, end)) < 0)
978  return ret;
979  }
980  } else {
981  while (*p != '\0' && *p != ':')
982  p++;
983  if (*p != ':')
984  return 1;
985 
986  *p = '\0';
987  tag = line;
988  p++;
989  while (av_isspace(*p))
990  p++;
991  if (!av_strcasecmp(tag, "Location")) {
992  if ((ret = parse_location(s, p)) < 0)
993  return ret;
994  *new_location = 1;
995  } else if (!av_strcasecmp(tag, "Content-Length") &&
996  s->filesize == UINT64_MAX) {
997  s->filesize = strtoull(p, NULL, 10);
998  } else if (!av_strcasecmp(tag, "Content-Range")) {
999  parse_content_range(h, p);
1000  } else if (!av_strcasecmp(tag, "Accept-Ranges") &&
1001  !strncmp(p, "bytes", 5) &&
1002  s->seekable == -1) {
1003  h->is_streamed = 0;
1004  } else if (!av_strcasecmp(tag, "Transfer-Encoding") &&
1005  !av_strncasecmp(p, "chunked", 7)) {
1006  s->filesize = UINT64_MAX;
1007  s->chunksize = 0;
1008  } else if (!av_strcasecmp(tag, "WWW-Authenticate")) {
1010  } else if (!av_strcasecmp(tag, "Authentication-Info")) {
1012  } else if (!av_strcasecmp(tag, "Proxy-Authenticate")) {
1014  } else if (!av_strcasecmp(tag, "Connection")) {
1015  if (!strcmp(p, "close"))
1016  s->willclose = 1;
1017  } else if (!av_strcasecmp(tag, "Server")) {
1018  if (!av_strcasecmp(p, "AkamaiGHost")) {
1019  s->is_akamai = 1;
1020  } else if (!av_strncasecmp(p, "MediaGateway", 12)) {
1021  s->is_mediagateway = 1;
1022  }
1023  } else if (!av_strcasecmp(tag, "Content-Type")) {
1024  av_free(s->mime_type);
1025  s->mime_type = av_strdup(p);
1026  } else if (!av_strcasecmp(tag, "Set-Cookie")) {
1027  if (parse_cookie(s, p, &s->cookie_dict))
1028  av_log(h, AV_LOG_WARNING, "Unable to parse '%s'\n", p);
1029  } else if (!av_strcasecmp(tag, "Icy-MetaInt")) {
1030  s->icy_metaint = strtoull(p, NULL, 10);
1031  } else if (!av_strncasecmp(tag, "Icy-", 4)) {
1032  if ((ret = parse_icy(s, tag, p)) < 0)
1033  return ret;
1034  } else if (!av_strcasecmp(tag, "Content-Encoding")) {
1035  if ((ret = parse_content_encoding(h, p)) < 0)
1036  return ret;
1037  }
1038  }
1039  return 1;
1040 }
1041 
1042 /**
1043  * Create a string containing cookie values for use as a HTTP cookie header
1044  * field value for a particular path and domain from the cookie values stored in
1045  * the HTTP protocol context. The cookie string is stored in *cookies, and may
1046  * be NULL if there are no valid cookies.
1047  *
1048  * @return a negative value if an error condition occurred, 0 otherwise
1049  */
1050 static int get_cookies(HTTPContext *s, char **cookies, const char *path,
1051  const char *domain)
1052 {
1053  // cookie strings will look like Set-Cookie header field values. Multiple
1054  // Set-Cookie fields will result in multiple values delimited by a newline
1055  int ret = 0;
1056  char *cookie, *set_cookies, *next;
1057 
1058  // destroy any cookies in the dictionary.
1060 
1061  if (!s->cookies)
1062  return 0;
1063 
1064  next = set_cookies = av_strdup(s->cookies);
1065  if (!next)
1066  return AVERROR(ENOMEM);
1067 
1068  *cookies = NULL;
1069  while ((cookie = av_strtok(next, "\n", &next)) && !ret) {
1070  AVDictionary *cookie_params = NULL;
1071  AVDictionaryEntry *cookie_entry, *e;
1072 
1073  // store the cookie in a dict in case it is updated in the response
1074  if (parse_cookie(s, cookie, &s->cookie_dict))
1075  av_log(s, AV_LOG_WARNING, "Unable to parse '%s'\n", cookie);
1076 
1077  // continue on to the next cookie if this one cannot be parsed
1078  if (parse_set_cookie(cookie, &cookie_params))
1079  goto skip_cookie;
1080 
1081  // if the cookie has no value, skip it
1082  cookie_entry = av_dict_get(cookie_params, "", NULL, AV_DICT_IGNORE_SUFFIX);
1083  if (!cookie_entry || !cookie_entry->value)
1084  goto skip_cookie;
1085 
1086  // if the cookie has expired, don't add it
1087  if ((e = av_dict_get(cookie_params, "expires", NULL, 0)) && e->value) {
1088  struct tm tm_buf = {0};
1089  if (!parse_set_cookie_expiry_time(e->value, &tm_buf)) {
1090  if (av_timegm(&tm_buf) < av_gettime() / 1000000)
1091  goto skip_cookie;
1092  }
1093  }
1094 
1095  // if no domain in the cookie assume it appied to this request
1096  if ((e = av_dict_get(cookie_params, "domain", NULL, 0)) && e->value) {
1097  // find the offset comparison is on the min domain (b.com, not a.b.com)
1098  int domain_offset = strlen(domain) - strlen(e->value);
1099  if (domain_offset < 0)
1100  goto skip_cookie;
1101 
1102  // match the cookie domain
1103  if (av_strcasecmp(&domain[domain_offset], e->value))
1104  goto skip_cookie;
1105  }
1106 
1107  // ensure this cookie matches the path
1108  e = av_dict_get(cookie_params, "path", NULL, 0);
1109  if (!e || av_strncasecmp(path, e->value, strlen(e->value)))
1110  goto skip_cookie;
1111 
1112  // cookie parameters match, so copy the value
1113  if (!*cookies) {
1114  *cookies = av_asprintf("%s=%s", cookie_entry->key, cookie_entry->value);
1115  } else {
1116  char *tmp = *cookies;
1117  *cookies = av_asprintf("%s; %s=%s", tmp, cookie_entry->key, cookie_entry->value);
1118  av_free(tmp);
1119  }
1120  if (!*cookies)
1121  ret = AVERROR(ENOMEM);
1122 
1123  skip_cookie:
1124  av_dict_free(&cookie_params);
1125  }
1126 
1127  av_free(set_cookies);
1128 
1129  return ret;
1130 }
1131 
1132 static inline int has_header(const char *str, const char *header)
1133 {
1134  /* header + 2 to skip over CRLF prefix. (make sure you have one!) */
1135  if (!str)
1136  return 0;
1137  return av_stristart(str, header + 2, NULL) || av_stristr(str, header);
1138 }
1139 
1140 static int http_read_header(URLContext *h, int *new_location)
1141 {
1142  HTTPContext *s = h->priv_data;
1143  char line[MAX_URL_SIZE];
1144  int err = 0;
1145 
1146  s->chunksize = UINT64_MAX;
1147 
1148  for (;;) {
1149  if ((err = http_get_line(s, line, sizeof(line))) < 0)
1150  return err;
1151 
1152  av_log(h, AV_LOG_TRACE, "header='%s'\n", line);
1153 
1154  err = process_line(h, line, s->line_count, new_location);
1155  if (err < 0)
1156  return err;
1157  if (err == 0)
1158  break;
1159  s->line_count++;
1160  }
1161 
1162  if (s->seekable == -1 && s->is_mediagateway && s->filesize == 2000000000)
1163  h->is_streamed = 1; /* we can in fact _not_ seek */
1164 
1165  // add any new cookies into the existing cookie string
1168 
1169  return err;
1170 }
1171 
1172 static int http_connect(URLContext *h, const char *path, const char *local_path,
1173  const char *hoststr, const char *auth,
1174  const char *proxyauth, int *new_location)
1175 {
1176  HTTPContext *s = h->priv_data;
1177  int post, err;
1178  char headers[HTTP_HEADERS_SIZE] = "";
1179  char *authstr = NULL, *proxyauthstr = NULL;
1180  uint64_t off = s->off;
1181  int len = 0;
1182  const char *method;
1183  int send_expect_100 = 0;
1184  int ret;
1185 
1186  /* send http header */
1187  post = h->flags & AVIO_FLAG_WRITE;
1188 
1189  if (s->post_data) {
1190  /* force POST method and disable chunked encoding when
1191  * custom HTTP post data is set */
1192  post = 1;
1193  s->chunked_post = 0;
1194  }
1195 
1196  if (s->method)
1197  method = s->method;
1198  else
1199  method = post ? "POST" : "GET";
1200 
1201  authstr = ff_http_auth_create_response(&s->auth_state, auth,
1202  local_path, method);
1203  proxyauthstr = ff_http_auth_create_response(&s->proxy_auth_state, proxyauth,
1204  local_path, method);
1205 
1206  if (post && !s->post_data) {
1207  if (s->send_expect_100 != -1) {
1208  send_expect_100 = s->send_expect_100;
1209  } else {
1210  send_expect_100 = 0;
1211  /* The user has supplied authentication but we don't know the auth type,
1212  * send Expect: 100-continue to get the 401 response including the
1213  * WWW-Authenticate header, or an 100 continue if no auth actually
1214  * is needed. */
1215  if (auth && *auth &&
1217  s->http_code != 401)
1218  send_expect_100 = 1;
1219  }
1220  }
1221 
1222 #if FF_API_HTTP_USER_AGENT
1223  if (strcmp(s->user_agent_deprecated, DEFAULT_USER_AGENT)) {
1224  s->user_agent = av_strdup(s->user_agent_deprecated);
1225  }
1226 #endif
1227  /* set default headers if needed */
1228  if (!has_header(s->headers, "\r\nUser-Agent: "))
1229  len += av_strlcatf(headers + len, sizeof(headers) - len,
1230  "User-Agent: %s\r\n", s->user_agent);
1231  if (s->referer) {
1232  /* set default headers if needed */
1233  if (!has_header(s->headers, "\r\nReferer: "))
1234  len += av_strlcatf(headers + len, sizeof(headers) - len,
1235  "Referer: %s\r\n", s->referer);
1236  }
1237  if (!has_header(s->headers, "\r\nAccept: "))
1238  len += av_strlcpy(headers + len, "Accept: */*\r\n",
1239  sizeof(headers) - len);
1240  // Note: we send this on purpose even when s->off is 0 when we're probing,
1241  // since it allows us to detect more reliably if a (non-conforming)
1242  // server supports seeking by analysing the reply headers.
1243  if (!has_header(s->headers, "\r\nRange: ") && !post && (s->off > 0 || s->end_off || s->seekable == -1)) {
1244  len += av_strlcatf(headers + len, sizeof(headers) - len,
1245  "Range: bytes=%"PRIu64"-", s->off);
1246  if (s->end_off)
1247  len += av_strlcatf(headers + len, sizeof(headers) - len,
1248  "%"PRId64, s->end_off - 1);
1249  len += av_strlcpy(headers + len, "\r\n",
1250  sizeof(headers) - len);
1251  }
1252  if (send_expect_100 && !has_header(s->headers, "\r\nExpect: "))
1253  len += av_strlcatf(headers + len, sizeof(headers) - len,
1254  "Expect: 100-continue\r\n");
1255 
1256  if (!has_header(s->headers, "\r\nConnection: ")) {
1257  if (s->multiple_requests)
1258  len += av_strlcpy(headers + len, "Connection: keep-alive\r\n",
1259  sizeof(headers) - len);
1260  else
1261  len += av_strlcpy(headers + len, "Connection: close\r\n",
1262  sizeof(headers) - len);
1263  }
1264 
1265  if (!has_header(s->headers, "\r\nHost: "))
1266  len += av_strlcatf(headers + len, sizeof(headers) - len,
1267  "Host: %s\r\n", hoststr);
1268  if (!has_header(s->headers, "\r\nContent-Length: ") && s->post_data)
1269  len += av_strlcatf(headers + len, sizeof(headers) - len,
1270  "Content-Length: %d\r\n", s->post_datalen);
1271 
1272  if (!has_header(s->headers, "\r\nContent-Type: ") && s->content_type)
1273  len += av_strlcatf(headers + len, sizeof(headers) - len,
1274  "Content-Type: %s\r\n", s->content_type);
1275  if (!has_header(s->headers, "\r\nCookie: ") && s->cookies) {
1276  char *cookies = NULL;
1277  if (!get_cookies(s, &cookies, path, hoststr) && cookies) {
1278  len += av_strlcatf(headers + len, sizeof(headers) - len,
1279  "Cookie: %s\r\n", cookies);
1280  av_free(cookies);
1281  }
1282  }
1283  if (!has_header(s->headers, "\r\nIcy-MetaData: ") && s->icy)
1284  len += av_strlcatf(headers + len, sizeof(headers) - len,
1285  "Icy-MetaData: %d\r\n", 1);
1286 
1287  /* now add in custom headers */
1288  if (s->headers)
1289  av_strlcpy(headers + len, s->headers, sizeof(headers) - len);
1290 
1291  ret = snprintf(s->buffer, sizeof(s->buffer),
1292  "%s %s HTTP/1.1\r\n"
1293  "%s"
1294  "%s"
1295  "%s"
1296  "%s%s"
1297  "\r\n",
1298  method,
1299  path,
1300  post && s->chunked_post ? "Transfer-Encoding: chunked\r\n" : "",
1301  headers,
1302  authstr ? authstr : "",
1303  proxyauthstr ? "Proxy-" : "", proxyauthstr ? proxyauthstr : "");
1304 
1305  av_log(h, AV_LOG_DEBUG, "request: %s\n", s->buffer);
1306 
1307  if (strlen(headers) + 1 == sizeof(headers) ||
1308  ret >= sizeof(s->buffer)) {
1309  av_log(h, AV_LOG_ERROR, "overlong headers\n");
1310  err = AVERROR(EINVAL);
1311  goto done;
1312  }
1313 
1314 
1315  if ((err = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0)
1316  goto done;
1317 
1318  if (s->post_data)
1319  if ((err = ffurl_write(s->hd, s->post_data, s->post_datalen)) < 0)
1320  goto done;
1321 
1322  /* init input buffer */
1323  s->buf_ptr = s->buffer;
1324  s->buf_end = s->buffer;
1325  s->line_count = 0;
1326  s->off = 0;
1327  s->icy_data_read = 0;
1328  s->filesize = UINT64_MAX;
1329  s->willclose = 0;
1330  s->end_chunked_post = 0;
1331  s->end_header = 0;
1332 #if CONFIG_ZLIB
1333  s->compressed = 0;
1334 #endif
1335  if (post && !s->post_data && !send_expect_100) {
1336  /* Pretend that it did work. We didn't read any header yet, since
1337  * we've still to send the POST data, but the code calling this
1338  * function will check http_code after we return. */
1339  s->http_code = 200;
1340  err = 0;
1341  goto done;
1342  }
1343 
1344  /* wait for header */
1345  err = http_read_header(h, new_location);
1346  if (err < 0)
1347  goto done;
1348 
1349  if (*new_location)
1350  s->off = off;
1351 
1352  err = (off == s->off) ? 0 : -1;
1353 done:
1354  av_freep(&authstr);
1355  av_freep(&proxyauthstr);
1356  return err;
1357 }
1358 
1359 static int http_buf_read(URLContext *h, uint8_t *buf, int size)
1360 {
1361  HTTPContext *s = h->priv_data;
1362  int len;
1363 
1364  if (s->chunksize != UINT64_MAX) {
1365  if (s->chunkend) {
1366  return AVERROR_EOF;
1367  }
1368  if (!s->chunksize) {
1369  char line[32];
1370  int err;
1371 
1372  do {
1373  if ((err = http_get_line(s, line, sizeof(line))) < 0)
1374  return err;
1375  } while (!*line); /* skip CR LF from last chunk */
1376 
1377  s->chunksize = strtoull(line, NULL, 16);
1378 
1379  av_log(h, AV_LOG_TRACE,
1380  "Chunked encoding data size: %"PRIu64"\n",
1381  s->chunksize);
1382 
1383  if (!s->chunksize && s->multiple_requests) {
1384  http_get_line(s, line, sizeof(line)); // read empty chunk
1385  s->chunkend = 1;
1386  return 0;
1387  }
1388  else if (!s->chunksize) {
1389  av_log(h, AV_LOG_DEBUG, "Last chunk received, closing conn\n");
1390  ffurl_closep(&s->hd);
1391  return 0;
1392  }
1393  else if (s->chunksize == UINT64_MAX) {
1394  av_log(h, AV_LOG_ERROR, "Invalid chunk size %"PRIu64"\n",
1395  s->chunksize);
1396  return AVERROR(EINVAL);
1397  }
1398  }
1399  size = FFMIN(size, s->chunksize);
1400  }
1401 
1402  /* read bytes from input buffer first */
1403  len = s->buf_end - s->buf_ptr;
1404  if (len > 0) {
1405  if (len > size)
1406  len = size;
1407  memcpy(buf, s->buf_ptr, len);
1408  s->buf_ptr += len;
1409  } else {
1410  uint64_t target_end = s->end_off ? s->end_off : s->filesize;
1411  if ((!s->willclose || s->chunksize == UINT64_MAX) && s->off >= target_end)
1412  return AVERROR_EOF;
1413  len = ffurl_read(s->hd, buf, size);
1414  if (!len && (!s->willclose || s->chunksize == UINT64_MAX) && s->off < target_end) {
1415  av_log(h, AV_LOG_ERROR,
1416  "Stream ends prematurely at %"PRIu64", should be %"PRIu64"\n",
1417  s->off, target_end
1418  );
1419  return AVERROR(EIO);
1420  }
1421  }
1422  if (len > 0) {
1423  s->off += len;
1424  if (s->chunksize > 0 && s->chunksize != UINT64_MAX) {
1425  av_assert0(s->chunksize >= len);
1426  s->chunksize -= len;
1427  }
1428  }
1429  return len;
1430 }
1431 
1432 #if CONFIG_ZLIB
1433 #define DECOMPRESS_BUF_SIZE (256 * 1024)
1434 static int http_buf_read_compressed(URLContext *h, uint8_t *buf, int size)
1435 {
1436  HTTPContext *s = h->priv_data;
1437  int ret;
1438 
1439  if (!s->inflate_buffer) {
1440  s->inflate_buffer = av_malloc(DECOMPRESS_BUF_SIZE);
1441  if (!s->inflate_buffer)
1442  return AVERROR(ENOMEM);
1443  }
1444 
1445  if (s->inflate_stream.avail_in == 0) {
1446  int read = http_buf_read(h, s->inflate_buffer, DECOMPRESS_BUF_SIZE);
1447  if (read <= 0)
1448  return read;
1449  s->inflate_stream.next_in = s->inflate_buffer;
1450  s->inflate_stream.avail_in = read;
1451  }
1452 
1453  s->inflate_stream.avail_out = size;
1454  s->inflate_stream.next_out = buf;
1455 
1456  ret = inflate(&s->inflate_stream, Z_SYNC_FLUSH);
1457  if (ret != Z_OK && ret != Z_STREAM_END)
1458  av_log(h, AV_LOG_WARNING, "inflate return value: %d, %s\n",
1459  ret, s->inflate_stream.msg);
1460 
1461  return size - s->inflate_stream.avail_out;
1462 }
1463 #endif /* CONFIG_ZLIB */
1464 
1465 static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int force_reconnect);
1466 
1468 {
1469  HTTPContext *s = h->priv_data;
1470  int err, new_location, read_ret;
1471  int64_t seek_ret;
1472  int reconnect_delay = 0;
1473 
1474  if (!s->hd)
1475  return AVERROR_EOF;
1476 
1477  if (s->end_chunked_post && !s->end_header) {
1478  err = http_read_header(h, &new_location);
1479  if (err < 0)
1480  return err;
1481  }
1482 
1483 #if CONFIG_ZLIB
1484  if (s->compressed)
1485  return http_buf_read_compressed(h, buf, size);
1486 #endif /* CONFIG_ZLIB */
1487  read_ret = http_buf_read(h, buf, size);
1488  while (read_ret < 0) {
1489  uint64_t target = h->is_streamed ? 0 : s->off;
1490 
1491  if (read_ret == AVERROR_EXIT)
1492  break;
1493 
1494  if (h->is_streamed && !s->reconnect_streamed)
1495  break;
1496 
1497  if (!(s->reconnect && s->filesize > 0 && s->off < s->filesize) &&
1498  !(s->reconnect_at_eof && read_ret == AVERROR_EOF))
1499  break;
1500 
1501  if (reconnect_delay > s->reconnect_delay_max)
1502  return AVERROR(EIO);
1503 
1504  av_log(h, AV_LOG_WARNING, "Will reconnect at %"PRIu64" in %d second(s), error=%s.\n", s->off, reconnect_delay, av_err2str(read_ret));
1505  err = ff_network_sleep_interruptible(1000U*1000*reconnect_delay, &h->interrupt_callback);
1506  if (err != AVERROR(ETIMEDOUT))
1507  return err;
1508  reconnect_delay = 1 + 2*reconnect_delay;
1509  seek_ret = http_seek_internal(h, target, SEEK_SET, 1);
1510  if (seek_ret >= 0 && seek_ret != target) {
1511  av_log(h, AV_LOG_ERROR, "Failed to reconnect at %"PRIu64".\n", target);
1512  return read_ret;
1513  }
1514 
1515  read_ret = http_buf_read(h, buf, size);
1516  }
1517 
1518  return read_ret;
1519 }
1520 
1521 // Like http_read_stream(), but no short reads.
1522 // Assumes partial reads are an error.
1524 {
1525  int pos = 0;
1526  while (pos < size) {
1527  int len = http_read_stream(h, buf + pos, size - pos);
1528  if (len < 0)
1529  return len;
1530  pos += len;
1531  }
1532  return pos;
1533 }
1534 
1535 static void update_metadata(URLContext *h, char *data)
1536 {
1537  char *key;
1538  char *val;
1539  char *end;
1540  char *next = data;
1541  HTTPContext *s = h->priv_data;
1542 
1543  while (*next) {
1544  key = next;
1545  val = strstr(key, "='");
1546  if (!val)
1547  break;
1548  end = strstr(val, "';");
1549  if (!end)
1550  break;
1551 
1552  *val = '\0';
1553  *end = '\0';
1554  val += 2;
1555 
1556  av_dict_set(&s->metadata, key, val, 0);
1557  av_log(h, AV_LOG_VERBOSE, "Metadata update for %s: %s\n", key, val);
1558 
1559  next = end + 2;
1560  }
1561 }
1562 
1563 static int store_icy(URLContext *h, int size)
1564 {
1565  HTTPContext *s = h->priv_data;
1566  /* until next metadata packet */
1567  uint64_t remaining;
1568 
1569  if (s->icy_metaint < s->icy_data_read)
1570  return AVERROR_INVALIDDATA;
1571  remaining = s->icy_metaint - s->icy_data_read;
1572 
1573  if (!remaining) {
1574  /* The metadata packet is variable sized. It has a 1 byte header
1575  * which sets the length of the packet (divided by 16). If it's 0,
1576  * the metadata doesn't change. After the packet, icy_metaint bytes
1577  * of normal data follows. */
1578  uint8_t ch;
1579  int len = http_read_stream_all(h, &ch, 1);
1580  if (len < 0)
1581  return len;
1582  if (ch > 0) {
1583  char data[255 * 16 + 1];
1584  int ret;
1585  len = ch * 16;
1586  ret = http_read_stream_all(h, data, len);
1587  if (ret < 0)
1588  return ret;
1589  data[len + 1] = 0;
1590  if ((ret = av_opt_set(s, "icy_metadata_packet", data, 0)) < 0)
1591  return ret;
1592  update_metadata(h, data);
1593  }
1594  s->icy_data_read = 0;
1595  remaining = s->icy_metaint;
1596  }
1597 
1598  return FFMIN(size, remaining);
1599 }
1600 
1601 static int http_read(URLContext *h, uint8_t *buf, int size)
1602 {
1603  HTTPContext *s = h->priv_data;
1604 
1605  if (s->icy_metaint > 0) {
1606  size = store_icy(h, size);
1607  if (size < 0)
1608  return size;
1609  }
1610 
1611  size = http_read_stream(h, buf, size);
1612  if (size > 0)
1613  s->icy_data_read += size;
1614  return size;
1615 }
1616 
1617 /* used only when posting data */
1618 static int http_write(URLContext *h, const uint8_t *buf, int size)
1619 {
1620  char temp[11] = ""; /* 32-bit hex + CRLF + nul */
1621  int ret;
1622  char crlf[] = "\r\n";
1623  HTTPContext *s = h->priv_data;
1624 
1625  if (!s->chunked_post) {
1626  /* non-chunked data is sent without any special encoding */
1627  return ffurl_write(s->hd, buf, size);
1628  }
1629 
1630  /* silently ignore zero-size data since chunk encoding that would
1631  * signal EOF */
1632  if (size > 0) {
1633  /* upload data using chunked encoding */
1634  snprintf(temp, sizeof(temp), "%x\r\n", size);
1635 
1636  if ((ret = ffurl_write(s->hd, temp, strlen(temp))) < 0 ||
1637  (ret = ffurl_write(s->hd, buf, size)) < 0 ||
1638  (ret = ffurl_write(s->hd, crlf, sizeof(crlf) - 1)) < 0)
1639  return ret;
1640  }
1641  return size;
1642 }
1643 
1644 static int http_shutdown(URLContext *h, int flags)
1645 {
1646  int ret = 0;
1647  char footer[] = "0\r\n\r\n";
1648  HTTPContext *s = h->priv_data;
1649 
1650  /* signal end of chunked encoding if used */
1651  if (((flags & AVIO_FLAG_WRITE) && s->chunked_post) ||
1652  ((flags & AVIO_FLAG_READ) && s->chunked_post && s->listen)) {
1653  ret = ffurl_write(s->hd, footer, sizeof(footer) - 1);
1654  ret = ret > 0 ? 0 : ret;
1655  /* flush the receive buffer when it is write only mode */
1656  if (!(flags & AVIO_FLAG_READ)) {
1657  char buf[1024];
1658  int read_ret;
1659  s->hd->flags |= AVIO_FLAG_NONBLOCK;
1660  read_ret = ffurl_read(s->hd, buf, sizeof(buf));
1661  s->hd->flags &= ~AVIO_FLAG_NONBLOCK;
1662  if (read_ret < 0 && read_ret != AVERROR(EAGAIN)) {
1663  av_log(h, AV_LOG_ERROR, "URL read error: %s\n", av_err2str(read_ret));
1664  ret = read_ret;
1665  }
1666  }
1667  s->end_chunked_post = 1;
1668  }
1669 
1670  return ret;
1671 }
1672 
1673 static int http_close(URLContext *h)
1674 {
1675  int ret = 0;
1676  HTTPContext *s = h->priv_data;
1677 
1678 #if CONFIG_ZLIB
1679  inflateEnd(&s->inflate_stream);
1680  av_freep(&s->inflate_buffer);
1681 #endif /* CONFIG_ZLIB */
1682 
1683  if (s->hd && !s->end_chunked_post)
1684  /* Close the write direction by sending the end of chunked encoding. */
1685  ret = http_shutdown(h, h->flags);
1686 
1687  if (s->hd)
1688  ffurl_closep(&s->hd);
1690  return ret;
1691 }
1692 
1693 static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int force_reconnect)
1694 {
1695  HTTPContext *s = h->priv_data;
1696  URLContext *old_hd = s->hd;
1697  uint64_t old_off = s->off;
1698  uint8_t old_buf[BUFFER_SIZE];
1699  int old_buf_size, ret;
1700  AVDictionary *options = NULL;
1701 
1702  if (whence == AVSEEK_SIZE)
1703  return s->filesize;
1704  else if (!force_reconnect &&
1705  ((whence == SEEK_CUR && off == 0) ||
1706  (whence == SEEK_SET && off == s->off)))
1707  return s->off;
1708  else if ((s->filesize == UINT64_MAX && whence == SEEK_END))
1709  return AVERROR(ENOSYS);
1710 
1711  if (whence == SEEK_CUR)
1712  off += s->off;
1713  else if (whence == SEEK_END)
1714  off += s->filesize;
1715  else if (whence != SEEK_SET)
1716  return AVERROR(EINVAL);
1717  if (off < 0)
1718  return AVERROR(EINVAL);
1719  s->off = off;
1720 
1721  if (s->off && h->is_streamed)
1722  return AVERROR(ENOSYS);
1723 
1724  /* do not try to make a new connection if seeking past the end of the file */
1725  if (s->end_off || s->filesize != UINT64_MAX) {
1726  uint64_t end_pos = s->end_off ? s->end_off : s->filesize;
1727  if (s->off >= end_pos)
1728  return s->off;
1729  }
1730 
1731  /* we save the old context in case the seek fails */
1732  old_buf_size = s->buf_end - s->buf_ptr;
1733  memcpy(old_buf, s->buf_ptr, old_buf_size);
1734  s->hd = NULL;
1735 
1736  /* if it fails, continue on old connection */
1737  if ((ret = http_open_cnx(h, &options)) < 0) {
1738  av_dict_free(&options);
1739  memcpy(s->buffer, old_buf, old_buf_size);
1740  s->buf_ptr = s->buffer;
1741  s->buf_end = s->buffer + old_buf_size;
1742  s->hd = old_hd;
1743  s->off = old_off;
1744  return ret;
1745  }
1746  av_dict_free(&options);
1747  ffurl_close(old_hd);
1748  return off;
1749 }
1750 
1751 static int64_t http_seek(URLContext *h, int64_t off, int whence)
1752 {
1753  return http_seek_internal(h, off, whence, 0);
1754 }
1755 
1757 {
1758  HTTPContext *s = h->priv_data;
1759  return ffurl_get_file_handle(s->hd);
1760 }
1761 
1763 {
1764  HTTPContext *s = h->priv_data;
1765  return ffurl_get_short_seek(s->hd);
1766 }
1767 
1768 #define HTTP_CLASS(flavor) \
1769 static const AVClass flavor ## _context_class = { \
1770  .class_name = # flavor, \
1771  .item_name = av_default_item_name, \
1772  .option = options, \
1773  .version = LIBAVUTIL_VERSION_INT, \
1774 }
1775 
1776 #if CONFIG_HTTP_PROTOCOL
1777 HTTP_CLASS(http);
1778 
1779 const URLProtocol ff_http_protocol = {
1780  .name = "http",
1781  .url_open2 = http_open,
1782  .url_accept = http_accept,
1783  .url_handshake = http_handshake,
1784  .url_read = http_read,
1785  .url_write = http_write,
1786  .url_seek = http_seek,
1787  .url_close = http_close,
1788  .url_get_file_handle = http_get_file_handle,
1789  .url_get_short_seek = http_get_short_seek,
1790  .url_shutdown = http_shutdown,
1791  .priv_data_size = sizeof(HTTPContext),
1792  .priv_data_class = &http_context_class,
1794  .default_whitelist = "http,https,tls,rtp,tcp,udp,crypto,httpproxy"
1795 };
1796 #endif /* CONFIG_HTTP_PROTOCOL */
1797 
1798 #if CONFIG_HTTPS_PROTOCOL
1799 HTTP_CLASS(https);
1800 
1802  .name = "https",
1803  .url_open2 = http_open,
1804  .url_read = http_read,
1805  .url_write = http_write,
1806  .url_seek = http_seek,
1807  .url_close = http_close,
1808  .url_get_file_handle = http_get_file_handle,
1809  .url_get_short_seek = http_get_short_seek,
1810  .url_shutdown = http_shutdown,
1811  .priv_data_size = sizeof(HTTPContext),
1812  .priv_data_class = &https_context_class,
1814  .default_whitelist = "http,https,tls,rtp,tcp,udp,crypto,httpproxy"
1815 };
1816 #endif /* CONFIG_HTTPS_PROTOCOL */
1817 
1818 #if CONFIG_HTTPPROXY_PROTOCOL
1819 static int http_proxy_close(URLContext *h)
1820 {
1821  HTTPContext *s = h->priv_data;
1822  if (s->hd)
1823  ffurl_closep(&s->hd);
1824  return 0;
1825 }
1826 
1827 static int http_proxy_open(URLContext *h, const char *uri, int flags)
1828 {
1829  HTTPContext *s = h->priv_data;
1830  char hostname[1024], hoststr[1024];
1831  char auth[1024], pathbuf[1024], *path;
1832  char lower_url[100];
1833  int port, ret = 0, attempts = 0;
1834  HTTPAuthType cur_auth_type;
1835  char *authstr;
1836  int new_loc;
1837 
1838  if( s->seekable == 1 )
1839  h->is_streamed = 0;
1840  else
1841  h->is_streamed = 1;
1842 
1843  av_url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port,
1844  pathbuf, sizeof(pathbuf), uri);
1845  ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL);
1846  path = pathbuf;
1847  if (*path == '/')
1848  path++;
1849 
1850  ff_url_join(lower_url, sizeof(lower_url), "tcp", NULL, hostname, port,
1851  NULL);
1852 redo:
1853  ret = ffurl_open_whitelist(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
1854  &h->interrupt_callback, NULL,
1856  if (ret < 0)
1857  return ret;
1858 
1859  authstr = ff_http_auth_create_response(&s->proxy_auth_state, auth,
1860  path, "CONNECT");
1861  snprintf(s->buffer, sizeof(s->buffer),
1862  "CONNECT %s HTTP/1.1\r\n"
1863  "Host: %s\r\n"
1864  "Connection: close\r\n"
1865  "%s%s"
1866  "\r\n",
1867  path,
1868  hoststr,
1869  authstr ? "Proxy-" : "", authstr ? authstr : "");
1870  av_freep(&authstr);
1871 
1872  if ((ret = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0)
1873  goto fail;
1874 
1875  s->buf_ptr = s->buffer;
1876  s->buf_end = s->buffer;
1877  s->line_count = 0;
1878  s->filesize = UINT64_MAX;
1879  cur_auth_type = s->proxy_auth_state.auth_type;
1880 
1881  /* Note: This uses buffering, potentially reading more than the
1882  * HTTP header. If tunneling a protocol where the server starts
1883  * the conversation, we might buffer part of that here, too.
1884  * Reading that requires using the proper ffurl_read() function
1885  * on this URLContext, not using the fd directly (as the tls
1886  * protocol does). This shouldn't be an issue for tls though,
1887  * since the client starts the conversation there, so there
1888  * is no extra data that we might buffer up here.
1889  */
1890  ret = http_read_header(h, &new_loc);
1891  if (ret < 0)
1892  goto fail;
1893 
1894  attempts++;
1895  if (s->http_code == 407 &&
1896  (cur_auth_type == HTTP_AUTH_NONE || s->proxy_auth_state.stale) &&
1897  s->proxy_auth_state.auth_type != HTTP_AUTH_NONE && attempts < 2) {
1898  ffurl_closep(&s->hd);
1899  goto redo;
1900  }
1901 
1902  if (s->http_code < 400)
1903  return 0;
1904  ret = ff_http_averror(s->http_code, AVERROR(EIO));
1905 
1906 fail:
1907  http_proxy_close(h);
1908  return ret;
1909 }
1910 
1911 static int http_proxy_write(URLContext *h, const uint8_t *buf, int size)
1912 {
1913  HTTPContext *s = h->priv_data;
1914  return ffurl_write(s->hd, buf, size);
1915 }
1916 
1918  .name = "httpproxy",
1919  .url_open = http_proxy_open,
1920  .url_read = http_buf_read,
1921  .url_write = http_proxy_write,
1922  .url_close = http_proxy_close,
1923  .url_get_file_handle = http_get_file_handle,
1924  .priv_data_size = sizeof(HTTPContext),
1925  .flags = URL_PROTOCOL_FLAG_NETWORK,
1926 };
1927 #endif /* CONFIG_HTTPPROXY_PROTOCOL */
static int http_get_line(HTTPContext *s, char *line, int line_size)
Definition: http.c:627
time_t av_timegm(struct tm *tm)
Convert the decomposed UTC time in tm to a time_t value.
Definition: parseutils.c:568
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components.
Definition: utils.c:4775
static void update_metadata(URLContext *h, char *data)
Definition: http.c:1535
static void parse_content_range(URLContext *h, const char *p)
Definition: http.c:680
AVDictionary * metadata
Definition: http.c:109
#define NULL
Definition: coverity.c:32
static int http_connect(URLContext *h, const char *path, const char *local_path, const char *hoststr, const char *auth, const char *proxyauth, int *new_location)
Definition: http.c:1172
const char const char void * val
Definition: avisynth_c.h:863
void ff_make_absolute_url(char *buf, int size, const char *base, const char *rel)
Convert a relative url into an absolute url, given a base url.
Definition: url.c:80
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist, URLContext *parent)
Create an URLContext for accessing to the resource indicated by url, and open it. ...
Definition: avio.c:306
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:34
uint8_t * post_data
Definition: http.c:95
AVOption.
Definition: opt.h:246
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
#define AV_OPT_FLAG_EXPORT
The option is intended for exporting values to the caller.
Definition: opt.h:284
#define AV_OPT_FLAG_DEPRECATED
set if option is deprecated, users should refer to AVOption.help text for more information ...
Definition: opt.h:293
HTTPAuthType
Authentication types, ordered from weakest to strongest.
Definition: httpauth.h:28
#define BUFFER_SIZE
Definition: http.c:48
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
static int http_close(URLContext *h)
Definition: http.c:1673
else temp
Definition: vf_mcdeint.c:256
int ffurl_write(URLContext *h, const unsigned char *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition: avio.c:419
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle...
Definition: avstring.c:56
int is_streamed
true if streamed (no seek possible), default = false
Definition: url.h:45
AVIOInterruptCB interrupt_callback
Definition: url.h:47
HTTPAuthState proxy_auth_state
Definition: http.c:73
Definition: http.c:58
#define AVIO_FLAG_READ
read-only
Definition: avio.h:674
char * icy_metadata_headers
Definition: http.c:107
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.h:222
const URLProtocol ff_http_protocol
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:675
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition: avstring.c:223
uint64_t icy_metaint
Definition: http.c:106
#define AVERROR_HTTP_NOT_FOUND
Definition: error.h:79
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:217
int flags
Definition: url.h:43
static int http_listen(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition: http.c:514
char * content_type
Definition: http.c:83
const char * key
uint64_t filesize
Definition: http.c:70
int version
Definition: avisynth_c.h:858
static void error(const char *err)
static int http_getc(HTTPContext *s)
Definition: http.c:610
HTTP Authentication state structure.
Definition: httpauth.h:55
#define src
Definition: vp8dsp.c:254
int auth_type
The currently chosen auth type.
Definition: httpauth.h:59
#define WHITESPACES
Definition: http.c:53
int is_connected_server
Definition: http.c:128
#define AV_DICT_DONT_STRDUP_KEY
Take ownership of a key that&#39;s been allocated with av_malloc() or another memory allocation function...
Definition: dict.h:73
#define HTTP_SINGLE
Definition: http.c:50
#define MAX_URL_SIZE
Definition: internal.h:30
static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
Definition: http.c:811
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
int end_chunked_post
Definition: http.c:90
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.
Definition: avstring.c:45
static int http_get_file_handle(URLContext *h)
Definition: http.c:1756
static int http_buf_read(URLContext *h, uint8_t *buf, int size)
Definition: http.c:1359
uint8_t
#define av_malloc(s)
int post_datalen
Definition: http.c:96
AVOptions.
int ff_http_averror(int status_code, int default_averror)
Definition: http.c:381
miscellaneous OS support macros and functions.
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:202
static int http_read_header(URLContext *h, int *new_location)
Definition: http.c:1140
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:108
#define HTTP_HEADERS_SIZE
Definition: http.h:27
int is_akamai
Definition: http.c:97
static int http_open_cnx(URLContext *h, AVDictionary **options)
Definition: http.c:252
char * av_small_strptime(const char *p, const char *fmt, struct tm *dt)
Simplified version of strptime.
Definition: parseutils.c:489
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:40
uint32_t tag
Definition: movenc.c:1531
#define DEFAULT_USER_AGENT
Definition: http.c:134
#define AVERROR_EOF
End of file.
Definition: error.h:55
void ff_http_init_auth_state(URLContext *dest, const URLContext *src)
Initialize the authentication state based on another HTTP URLContext.
Definition: http.c:180
uint64_t icy_data_read
Definition: http.c:104
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
HTTP 1.0 Basic auth from RFC 1945 (also in RFC 2617)
Definition: httpauth.h:30
ptrdiff_t size
Definition: opengl_enc.c:100
static const uint8_t header[24]
Definition: sdr2.c:67
static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
Definition: http.c:190
int ff_http_do_new_request2(URLContext *h, const char *uri, AVDictionary **opts)
Send a new HTTP request, reusing the old connection.
Definition: http.c:327
int line_count
Definition: http.c:65
#define av_log(a,...)
unsigned char * buf_end
Definition: http.c:64
static void body(uint32_t ABCD[4], const uint8_t *src, int nblocks)
Definition: md5.c:101
#define U(x)
Definition: vp56_arith.h:37
int ff_http_get_shutdown_status(URLContext *h)
Get the HTTP shutdown response status, be used after http_shutdown.
Definition: http.c:307
int is_multi_client
Definition: http.c:126
int chunked_post
Definition: http.c:88
static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int force_reconnect)
Definition: http.c:1693
s EdgeDetect Foobar g libavfilter vf_edgedetect c libavfilter vf_foobar c edit libavfilter and add an entry for foobar following the pattern of the other filters edit libavfilter allfilters and add an entry for foobar following the pattern of the other filters configure make j< whatever > ffmpeg ffmpeg i you should get a foobar png with Lena edge detected That s your new playground is ready Some little details about what s going which in turn will define variables for the build system and the and we are assuming vf_foobar is as well We are also assuming vf_foobar is not an edge detector so you can update the boilerplate with your credits Doxy Next chunk is the Doxygen about the file See https
int ffurl_alloc(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb)
Create a URLContext for accessing to the resource indicated by url, but do not initiate the connectio...
Definition: avio.c:293
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
int reconnect_delay_max
Definition: http.c:122
#define E
Definition: http.c:133
const char * protocol_whitelist
Definition: url.h:49
static int http_write(URLContext *h, const uint8_t *buf, int size)
Definition: http.c:1618
static const AVOption options[]
Definition: http.c:136
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:203
static int http_handshake(URLContext *c)
Definition: http.c:478
Definition: graph2dot.c:48
uint64_t off
Definition: http.c:70
simple assert() macros that are a bit more flexible than ISO C assert().
#define OFFSET(x)
Definition: http.c:131
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:83
#define fail()
Definition: checkasm.h:122
uint64_t chunksize
Definition: http.c:68
AVDictionary * chained_options
Definition: http.c:115
#define AVERROR_HTTP_SERVER_ERROR
Definition: error.h:81
char * referer
Definition: http.c:79
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:113
static int store_icy(URLContext *h, int size)
Definition: http.c:1563
AVDictionary * opts
Definition: movenc.c:50
char * headers
Definition: http.c:75
char * user_agent
Definition: http.c:78
#define AVERROR_HTTP_UNAUTHORIZED
Definition: error.h:77
char * icy_metadata_packet
Definition: http.c:108
int ffurl_get_short_seek(URLContext *h)
Return the current short seek threshold value for this URL.
Definition: avio.c:648
#define FFMIN(a, b)
Definition: common.h:96
static int http_get_short_seek(URLContext *h)
Definition: http.c:1762
const URLProtocol ff_httpproxy_protocol
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
int chunkend
Definition: http.c:69
int send_expect_100
Definition: http.c:117
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:119
int ff_network_sleep_interruptible(int64_t timeout, AVIOInterruptCB *int_cb)
Waits for up to &#39;timeout&#39; microseconds.
Definition: network.c:98
int willclose
Definition: http.c:86
int is_mediagateway
Definition: http.c:98
int ffurl_handshake(URLContext *c)
Perform one step of the protocol handshake to accept a new client.
Definition: avio.c:234
int reconnect
Definition: http.c:119
int ff_http_match_no_proxy(const char *no_proxy, const char *hostname)
Definition: network.c:551
#define s(width, name)
Definition: cbs_vp9.c:257
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:624
int ffurl_accept(URLContext *s, URLContext **c)
Accept an URLContext c on an URLContext s.
Definition: avio.c:226
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:56
AVDictionary * cookie_dict
Definition: http.c:101
int stale
Auth ok, but needs to be resent with a new nonce.
Definition: httpauth.h:71
offset must point to a pointer immediately followed by an int for the length
Definition: opt.h:229
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:442
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...)
Definition: url.c:36
int reconnect_streamed
Definition: http.c:121
static int http_read(URLContext *h, uint8_t *buf, int size)
Definition: http.c:1601
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition: mem.c:163
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
const char * protocol_blacklist
Definition: url.h:50
s EdgeDetect Foobar g libavfilter vf_edgedetect c libavfilter vf_foobar c edit libavfilter and add an entry for foobar following the pattern of the other filters edit libavfilter allfilters and add an entry for foobar following the pattern of the other filters configure make j< whatever > ffmpeg ffmpeg i http
char * http_proxy
Definition: http.c:74
int av_opt_set_dict(void *obj, AVDictionary **options)
Set all the options from a given dictionary on an object.
Definition: opt.c:1626
HandshakeState handshake_step
Definition: http.c:127
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition: avio.h:693
int seekable
Control seekability, 0 = disable, 1 = enable, -1 = probe.
Definition: http.c:87
#define MAX_EXPIRY
Definition: http.c:52
void * buf
Definition: avisynth_c.h:766
Definition: url.h:38
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
Definition: avio.h:676
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:70
unsigned char buffer[BUFFER_SIZE]
Definition: http.c:64
char * http_version
Definition: http.c:77
Describe the class of an AVClass context structure.
Definition: log.h:67
#define SPACE_CHARS
Definition: internal.h:352
static void inflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord, int maxc)
Definition: vf_neighbor.c:198
void * priv_data
Definition: url.h:41
#define AVERROR_HTTP_OTHER_4XX
Definition: error.h:80
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
#define snprintf
Definition: snprintf.h:34
int icy
Definition: http.c:102
misc parsing utilities
char * ff_http_auth_create_response(HTTPAuthState *state, const char *auth, const char *path, const char *method)
Definition: httpauth.c:245
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(const uint8_t *) pi-0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(const int16_t *) pi >>8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(const int16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(const int32_t *) pi >>24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(const int32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(const int64_t *) pi >>56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64,*(const int64_t *) pi *(1.0f/(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64,*(const int64_t *) pi *(1.0/(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(const float *) pi *(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(const double *) pi *(UINT64_C(1)<< 63)))#define FMT_PAIR_FUNC(out, in) static conv_func_type *const fmt_pair_to_conv_functions[AV_SAMPLE_FMT_NB *AV_SAMPLE_FMT_NB]={FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64),};static void cpy1(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, len);}static void cpy2(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 2 *len);}static void cpy4(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 4 *len);}static void cpy8(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 8 *len);}AudioConvert *swri_audio_convert_alloc(enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, const int *ch_map, int flags){AudioConvert *ctx;conv_func_type *f=fmt_pair_to_conv_functions[av_get_packed_sample_fmt(out_fmt)+AV_SAMPLE_FMT_NB *av_get_packed_sample_fmt(in_fmt)];if(!f) return NULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) return NULL;if(channels==1){in_fmt=av_get_planar_sample_fmt(in_fmt);out_fmt=av_get_planar_sample_fmt(out_fmt);}ctx->channels=channels;ctx->conv_f=f;ctx->ch_map=ch_map;if(in_fmt==AV_SAMPLE_FMT_U8||in_fmt==AV_SAMPLE_FMT_U8P) memset(ctx->silence, 0x80, sizeof(ctx->silence));if(out_fmt==in_fmt &&!ch_map){switch(av_get_bytes_per_sample(in_fmt)){case 1:ctx->simd_f=cpy1;break;case 2:ctx->simd_f=cpy2;break;case 4:ctx->simd_f=cpy4;break;case 8:ctx->simd_f=cpy8;break;}}if(HAVE_X86ASM &&1) swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels);if(ARCH_ARM) swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);if(ARCH_AARCH64) swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels);return ctx;}void swri_audio_convert_free(AudioConvert **ctx){av_freep(ctx);}int swri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, int len){int ch;int off=0;const int os=(out->planar?1:out->ch_count)*out->bps;unsigned misaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask){int planes=in->planar?in->ch_count:1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) in->ch[ch];misaligned|=m &ctx->in_simd_align_mask;}if(ctx->out_simd_align_mask){int planes=out->planar?out->ch_count:1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) out->ch[ch];misaligned|=m &ctx->out_simd_align_mask;}if(ctx->simd_f &&!ctx->ch_map &&!misaligned){off=len &~15;av_assert1(off >=0);av_assert1(off<=len);av_assert2(ctx->channels==SWR_CH_MAX||!in->ch[ctx->channels]);if(off >0){if(out->planar==in->planar){int planes=out->planar?out->ch_count:1;for(ch=0;ch< planes;ch++){ctx->simd_f(out-> ch ch
Definition: audioconvert.c:56
const char * name
Definition: url.h:55
URLContext * hd
Definition: http.c:63
static int has_header(const char *str, const char *header)
Definition: http.c:1132
char * mime_type
Definition: http.c:76
#define SIZE_SPECIFIER
Definition: internal.h:262
#define flags(name, subs,...)
Definition: cbs_av1.c:561
#define AVERROR_HTTP_FORBIDDEN
Definition: error.h:78
int ffurl_close(URLContext *h)
Definition: avio.c:465
static int process_line(URLContext *h, char *line, int line_count, int *new_location)
Definition: http.c:896
int ff_http_do_new_request(URLContext *h, const char *uri)
Send a new HTTP request, reusing the old connection.
Definition: http.c:323
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()...
Definition: avstring.c:184
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:34
Main libavformat public API header.
The official guide to swscale for confused that consecutive non overlapping rectangles of slice_bottom special converter These generally are unscaled converters of common like for each output line the vertical scaler pulls lines from a ring buffer When the ring buffer does not contain the wanted line
Definition: swscale.txt:33
char * cookies
holds newline ( ) delimited Set-Cookie header field values (without the "Set-Cookie: " field name) ...
Definition: http.c:99
#define MAX_REDIRECTS
Definition: http.c:49
static int parse_content_encoding(URLContext *h, const char *p)
Definition: http.c:695
const struct URLProtocol * prot
Definition: url.h:40
int reconnect_at_eof
Definition: http.c:120
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set that converts the value to a string and stores it...
Definition: dict.c:147
HandshakeState
Definition: http.c:54
static int get_cookies(HTTPContext *s, char **cookies, const char *path, const char *domain)
Create a string containing cookie values for use as a HTTP cookie header field value for a particular...
Definition: http.c:1050
int http_code
Definition: http.c:66
char * filename
specified URL
Definition: url.h:42
int listen
Definition: http.c:123
static int http_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition: http.c:545
#define AVSEEK_SIZE
ORing this as the "whence" parameter to a seek function causes it to return the filesize without seek...
Definition: avio.h:531
char * key
Definition: dict.h:86
void ff_http_auth_handle_header(HTTPAuthState *state, const char *key, const char *value)
Definition: httpauth.c:90
int multiple_requests
Definition: http.c:94
HTTPAuthState auth_state
Definition: http.c:72
#define av_free(p)
static int cookie_string(AVDictionary *dict, char **cookies)
Definition: http.c:873
char * value
Definition: dict.h:87
const URLProtocol ff_https_protocol
int len
static int parse_location(HTTPContext *s, const char *p)
Definition: http.c:666
char * resource
Definition: http.c:124
char * location
Definition: http.c:71
static int http_shutdown(URLContext *h, int flags)
Definition: http.c:1644
static int http_write_reply(URLContext *h, int status_code)
Definition: http.c:398
#define AV_OPT_FLAG_READONLY
The option may not be set through the AVOptions API, only read.
Definition: opt.h:289
int end_header
Definition: http.c:92
unsigned char * buf_ptr
Definition: http.c:64
#define D
Definition: http.c:132
#define AVERROR_HTTP_BAD_REQUEST
Definition: error.h:76
char * method
Definition: http.c:118
static int parse_icy(HTTPContext *s, const char *tag, const char *p)
Definition: http.c:729
uint64_t end_off
Definition: http.c:70
static int parse_set_cookie_expiry_time(const char *exp_str, struct tm *buf)
Definition: http.c:751
static int http_read_stream(URLContext *h, uint8_t *buf, int size)
Definition: http.c:1467
#define av_freep(p)
static int http_read_stream_all(URLContext *h, uint8_t *buf, int size)
Definition: http.c:1523
#define AV_DICT_IGNORE_SUFFIX
Return first entry in a dictionary whose first part corresponds to the search key, ignoring the suffix of the found key string.
Definition: dict.h:70
unbuffered private I/O API
static void handle_http_errors(URLContext *h, int error)
Definition: http.c:472
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
static int parse_set_cookie(const char *set_cookie, AVDictionary **dict)
Definition: http.c:776
static int64_t http_seek(URLContext *h, int64_t off, int whence)
Definition: http.c:1751
int reply_code
Definition: http.c:125
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:449
int ffurl_read(URLContext *h, unsigned char *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf...
Definition: avio.c:405
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:263
static int http_accept(URLContext *s, URLContext **c)
Definition: http.c:586
GLuint buffer
Definition: opengl_enc.c:101
#define HTTP_CLASS(flavor)
Definition: http.c:1768
No authentication specified.
Definition: httpauth.h:29
static int check_http_code(URLContext *h, int http_code, const char *end)
Definition: http.c:651
const char * name
Definition: opengl_enc.c:102
static uint8_t tmp[11]
Definition: aes_ctr.c:26