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,
238  h->protocol_whitelist, h->protocol_blacklist, h);
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 */
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 }
307 
308 int ff_http_do_new_request(URLContext *h, const char *uri)
309 {
310  HTTPContext *s = h->priv_data;
312  int ret;
313  char hostname1[1024], hostname2[1024], proto1[10], proto2[10];
314  int port1, port2;
315 
316  if (!h->prot ||
317  !(!strcmp(h->prot->name, "http") ||
318  !strcmp(h->prot->name, "https")))
319  return AVERROR(EINVAL);
320 
321  av_url_split(proto1, sizeof(proto1), NULL, 0,
322  hostname1, sizeof(hostname1), &port1,
323  NULL, 0, s->location);
324  av_url_split(proto2, sizeof(proto2), NULL, 0,
325  hostname2, sizeof(hostname2), &port2,
326  NULL, 0, uri);
327  if (port1 != port2 || strncmp(hostname1, hostname2, sizeof(hostname2)) != 0) {
328  av_log(h, AV_LOG_ERROR, "Cannot reuse HTTP connection for different host: %s:%d != %s:%d\n",
329  hostname1, port1,
330  hostname2, port2
331  );
332  return AVERROR(EINVAL);
333  }
334 
335  if (!s->end_chunked_post) {
336  ret = http_shutdown(h, h->flags);
337  if (ret < 0)
338  return ret;
339  }
340 
341  if (s->willclose)
342  return AVERROR_EOF;
343 
344  s->end_chunked_post = 0;
345  s->chunkend = 0;
346  s->off = 0;
347  s->icy_data_read = 0;
348  av_free(s->location);
349  s->location = av_strdup(uri);
350  if (!s->location)
351  return AVERROR(ENOMEM);
352 
353  av_log(s, AV_LOG_INFO, "Opening \'%s\' for %s\n", uri, h->flags & AVIO_FLAG_WRITE ? "writing" : "reading");
354  ret = http_open_cnx(h, &options);
356  return ret;
357 }
358 
359 int ff_http_averror(int status_code, int default_averror)
360 {
361  switch (status_code) {
362  case 400: return AVERROR_HTTP_BAD_REQUEST;
363  case 401: return AVERROR_HTTP_UNAUTHORIZED;
364  case 403: return AVERROR_HTTP_FORBIDDEN;
365  case 404: return AVERROR_HTTP_NOT_FOUND;
366  default: break;
367  }
368  if (status_code >= 400 && status_code <= 499)
369  return AVERROR_HTTP_OTHER_4XX;
370  else if (status_code >= 500)
372  else
373  return default_averror;
374 }
375 
376 static int http_write_reply(URLContext* h, int status_code)
377 {
378  int ret, body = 0, reply_code, message_len;
379  const char *reply_text, *content_type;
380  HTTPContext *s = h->priv_data;
381  char message[BUFFER_SIZE];
382  content_type = "text/plain";
383 
384  if (status_code < 0)
385  body = 1;
386  switch (status_code) {
388  case 400:
389  reply_code = 400;
390  reply_text = "Bad Request";
391  break;
393  case 403:
394  reply_code = 403;
395  reply_text = "Forbidden";
396  break;
398  case 404:
399  reply_code = 404;
400  reply_text = "Not Found";
401  break;
402  case 200:
403  reply_code = 200;
404  reply_text = "OK";
405  content_type = s->content_type ? s->content_type : "application/octet-stream";
406  break;
408  case 500:
409  reply_code = 500;
410  reply_text = "Internal server error";
411  break;
412  default:
413  return AVERROR(EINVAL);
414  }
415  if (body) {
416  s->chunked_post = 0;
417  message_len = snprintf(message, sizeof(message),
418  "HTTP/1.1 %03d %s\r\n"
419  "Content-Type: %s\r\n"
420  "Content-Length: %"SIZE_SPECIFIER"\r\n"
421  "%s"
422  "\r\n"
423  "%03d %s\r\n",
424  reply_code,
425  reply_text,
426  content_type,
427  strlen(reply_text) + 6, // 3 digit status code + space + \r\n
428  s->headers ? s->headers : "",
429  reply_code,
430  reply_text);
431  } else {
432  s->chunked_post = 1;
433  message_len = snprintf(message, sizeof(message),
434  "HTTP/1.1 %03d %s\r\n"
435  "Content-Type: %s\r\n"
436  "Transfer-Encoding: chunked\r\n"
437  "%s"
438  "\r\n",
439  reply_code,
440  reply_text,
441  content_type,
442  s->headers ? s->headers : "");
443  }
444  av_log(h, AV_LOG_TRACE, "HTTP reply header: \n%s----\n", message);
445  if ((ret = ffurl_write(s->hd, message, message_len)) < 0)
446  return ret;
447  return 0;
448 }
449 
451 {
452  av_assert0(error < 0);
454 }
455 
457 {
458  int ret, err, new_location;
459  HTTPContext *ch = c->priv_data;
460  URLContext *cl = ch->hd;
461  switch (ch->handshake_step) {
462  case LOWER_PROTO:
463  av_log(c, AV_LOG_TRACE, "Lower protocol\n");
464  if ((ret = ffurl_handshake(cl)) > 0)
465  return 2 + ret;
466  if (ret < 0)
467  return ret;
468  ch->handshake_step = READ_HEADERS;
469  ch->is_connected_server = 1;
470  return 2;
471  case READ_HEADERS:
472  av_log(c, AV_LOG_TRACE, "Read headers\n");
473  if ((err = http_read_header(c, &new_location)) < 0) {
474  handle_http_errors(c, err);
475  return err;
476  }
477  ch->handshake_step = WRITE_REPLY_HEADERS;
478  return 1;
479  case WRITE_REPLY_HEADERS:
480  av_log(c, AV_LOG_TRACE, "Reply code: %d\n", ch->reply_code);
481  if ((err = http_write_reply(c, ch->reply_code)) < 0)
482  return err;
483  ch->handshake_step = FINISH;
484  return 1;
485  case FINISH:
486  return 0;
487  }
488  // this should never be reached.
489  return AVERROR(EINVAL);
490 }
491 
492 static int http_listen(URLContext *h, const char *uri, int flags,
493  AVDictionary **options) {
494  HTTPContext *s = h->priv_data;
495  int ret;
496  char hostname[1024], proto[10];
497  char lower_url[100];
498  const char *lower_proto = "tcp";
499  int port;
500  av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
501  NULL, 0, uri);
502  if (!strcmp(proto, "https"))
503  lower_proto = "tls";
504  ff_url_join(lower_url, sizeof(lower_url), lower_proto, NULL, hostname, port,
505  NULL);
506  if ((ret = av_dict_set_int(options, "listen", s->listen, 0)) < 0)
507  goto fail;
508  if ((ret = ffurl_open_whitelist(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
509  &h->interrupt_callback, options,
510  h->protocol_whitelist, h->protocol_blacklist, h
511  )) < 0)
512  goto fail;
513  s->handshake_step = LOWER_PROTO;
514  if (s->listen == HTTP_SINGLE) { /* single client */
515  s->reply_code = 200;
516  while ((ret = http_handshake(h)) > 0);
517  }
518 fail:
519  av_dict_free(&s->chained_options);
520  return ret;
521 }
522 
523 static int http_open(URLContext *h, const char *uri, int flags,
525 {
526  HTTPContext *s = h->priv_data;
527  int ret;
528 
529  if( s->seekable == 1 )
530  h->is_streamed = 0;
531  else
532  h->is_streamed = 1;
533 
534  s->filesize = UINT64_MAX;
535  s->location = av_strdup(uri);
536  if (!s->location)
537  return AVERROR(ENOMEM);
538  if (options)
539  av_dict_copy(&s->chained_options, *options, 0);
540 
541  if (s->headers) {
542  int len = strlen(s->headers);
543  if (len < 2 || strcmp("\r\n", s->headers + len - 2)) {
545  "No trailing CRLF found in HTTP header. Adding it.\n");
546  ret = av_reallocp(&s->headers, len + 3);
547  if (ret < 0)
548  return ret;
549  s->headers[len] = '\r';
550  s->headers[len + 1] = '\n';
551  s->headers[len + 2] = '\0';
552  }
553  }
554 
555  if (s->listen) {
556  return http_listen(h, uri, flags, options);
557  }
559  if (ret < 0)
560  av_dict_free(&s->chained_options);
561  return ret;
562 }
563 
565 {
566  int ret;
567  HTTPContext *sc = s->priv_data;
568  HTTPContext *cc;
569  URLContext *sl = sc->hd;
570  URLContext *cl = NULL;
571 
572  av_assert0(sc->listen);
573  if ((ret = ffurl_alloc(c, s->filename, s->flags, &sl->interrupt_callback)) < 0)
574  goto fail;
575  cc = (*c)->priv_data;
576  if ((ret = ffurl_accept(sl, &cl)) < 0)
577  goto fail;
578  cc->hd = cl;
579  cc->is_multi_client = 1;
580  return 0;
581 fail:
582  if (c) {
583  ffurl_closep(c);
584  }
585  return ret;
586 }
587 
588 static int http_getc(HTTPContext *s)
589 {
590  int len;
591  if (s->buf_ptr >= s->buf_end) {
592  len = ffurl_read(s->hd, s->buffer, BUFFER_SIZE);
593  if (len < 0) {
594  return len;
595  } else if (len == 0) {
596  return AVERROR_EOF;
597  } else {
598  s->buf_ptr = s->buffer;
599  s->buf_end = s->buffer + len;
600  }
601  }
602  return *s->buf_ptr++;
603 }
604 
605 static int http_get_line(HTTPContext *s, char *line, int line_size)
606 {
607  int ch;
608  char *q;
609 
610  q = line;
611  for (;;) {
612  ch = http_getc(s);
613  if (ch < 0)
614  return ch;
615  if (ch == '\n') {
616  /* process line */
617  if (q > line && q[-1] == '\r')
618  q--;
619  *q = '\0';
620 
621  return 0;
622  } else {
623  if ((q - line) < line_size - 1)
624  *q++ = ch;
625  }
626  }
627 }
628 
629 static int check_http_code(URLContext *h, int http_code, const char *end)
630 {
631  HTTPContext *s = h->priv_data;
632  /* error codes are 4xx and 5xx, but regard 401 as a success, so we
633  * don't abort until all headers have been parsed. */
634  if (http_code >= 400 && http_code < 600 &&
635  (http_code != 401 || s->auth_state.auth_type != HTTP_AUTH_NONE) &&
636  (http_code != 407 || s->proxy_auth_state.auth_type != HTTP_AUTH_NONE)) {
637  end += strspn(end, SPACE_CHARS);
638  av_log(h, AV_LOG_WARNING, "HTTP error %d %s\n", http_code, end);
639  return ff_http_averror(http_code, AVERROR(EIO));
640  }
641  return 0;
642 }
643 
644 static int parse_location(HTTPContext *s, const char *p)
645 {
646  char redirected_location[MAX_URL_SIZE], *new_loc;
647  ff_make_absolute_url(redirected_location, sizeof(redirected_location),
648  s->location, p);
649  new_loc = av_strdup(redirected_location);
650  if (!new_loc)
651  return AVERROR(ENOMEM);
652  av_free(s->location);
653  s->location = new_loc;
654  return 0;
655 }
656 
657 /* "bytes $from-$to/$document_size" */
658 static void parse_content_range(URLContext *h, const char *p)
659 {
660  HTTPContext *s = h->priv_data;
661  const char *slash;
662 
663  if (!strncmp(p, "bytes ", 6)) {
664  p += 6;
665  s->off = strtoull(p, NULL, 10);
666  if ((slash = strchr(p, '/')) && strlen(slash) > 0)
667  s->filesize = strtoull(slash + 1, NULL, 10);
668  }
669  if (s->seekable == -1 && (!s->is_akamai || s->filesize != 2147483647))
670  h->is_streamed = 0; /* we _can_ in fact seek */
671 }
672 
673 static int parse_content_encoding(URLContext *h, const char *p)
674 {
675  if (!av_strncasecmp(p, "gzip", 4) ||
676  !av_strncasecmp(p, "deflate", 7)) {
677 #if CONFIG_ZLIB
678  HTTPContext *s = h->priv_data;
679 
680  s->compressed = 1;
681  inflateEnd(&s->inflate_stream);
682  if (inflateInit2(&s->inflate_stream, 32 + 15) != Z_OK) {
683  av_log(h, AV_LOG_WARNING, "Error during zlib initialisation: %s\n",
684  s->inflate_stream.msg);
685  return AVERROR(ENOSYS);
686  }
687  if (zlibCompileFlags() & (1 << 17)) {
689  "Your zlib was compiled without gzip support.\n");
690  return AVERROR(ENOSYS);
691  }
692 #else
694  "Compressed (%s) content, need zlib with gzip support\n", p);
695  return AVERROR(ENOSYS);
696 #endif /* CONFIG_ZLIB */
697  } else if (!av_strncasecmp(p, "identity", 8)) {
698  // The normal, no-encoding case (although servers shouldn't include
699  // the header at all if this is the case).
700  } else {
701  av_log(h, AV_LOG_WARNING, "Unknown content coding: %s\n", p);
702  }
703  return 0;
704 }
705 
706 // Concat all Icy- header lines
707 static int parse_icy(HTTPContext *s, const char *tag, const char *p)
708 {
709  int len = 4 + strlen(p) + strlen(tag);
710  int is_first = !s->icy_metadata_headers;
711  int ret;
712 
713  av_dict_set(&s->metadata, tag, p, 0);
714 
715  if (s->icy_metadata_headers)
716  len += strlen(s->icy_metadata_headers);
717 
718  if ((ret = av_reallocp(&s->icy_metadata_headers, len)) < 0)
719  return ret;
720 
721  if (is_first)
722  *s->icy_metadata_headers = '\0';
723 
724  av_strlcatf(s->icy_metadata_headers, len, "%s: %s\n", tag, p);
725 
726  return 0;
727 }
728 
729 static int parse_set_cookie_expiry_time(const char *exp_str, struct tm *buf)
730 {
731  char exp_buf[MAX_EXPIRY];
732  int i, j, exp_buf_len = MAX_EXPIRY-1;
733  char *expiry;
734 
735  // strip off any punctuation or whitespace
736  for (i = 0, j = 0; exp_str[i] != '\0' && j < exp_buf_len; i++) {
737  if ((exp_str[i] >= '0' && exp_str[i] <= '9') ||
738  (exp_str[i] >= 'A' && exp_str[i] <= 'Z') ||
739  (exp_str[i] >= 'a' && exp_str[i] <= 'z')) {
740  exp_buf[j] = exp_str[i];
741  j++;
742  }
743  }
744  exp_buf[j] = '\0';
745  expiry = exp_buf;
746 
747  // move the string beyond the day of week
748  while ((*expiry < '0' || *expiry > '9') && *expiry != '\0')
749  expiry++;
750 
751  return av_small_strptime(expiry, "%d%b%Y%H%M%S", buf) ? 0 : AVERROR(EINVAL);
752 }
753 
754 static int parse_set_cookie(const char *set_cookie, AVDictionary **dict)
755 {
756  char *param, *next_param, *cstr, *back;
757 
758  if (!set_cookie[0])
759  return 0;
760 
761  if (!(cstr = av_strdup(set_cookie)))
762  return AVERROR(EINVAL);
763 
764  // strip any trailing whitespace
765  back = &cstr[strlen(cstr)-1];
766  while (strchr(WHITESPACES, *back)) {
767  *back='\0';
768  if (back == cstr)
769  break;
770  back--;
771  }
772 
773  next_param = cstr;
774  while ((param = av_strtok(next_param, ";", &next_param))) {
775  char *name, *value;
776  param += strspn(param, WHITESPACES);
777  if ((name = av_strtok(param, "=", &value))) {
778  if (av_dict_set(dict, name, value, 0) < 0) {
779  av_free(cstr);
780  return -1;
781  }
782  }
783  }
784 
785  av_free(cstr);
786  return 0;
787 }
788 
789 static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
790 {
791  AVDictionary *new_params = NULL;
792  AVDictionaryEntry *e, *cookie_entry;
793  char *eql, *name;
794 
795  // ensure the cookie is parsable
796  if (parse_set_cookie(p, &new_params))
797  return -1;
798 
799  // if there is no cookie value there is nothing to parse
800  cookie_entry = av_dict_get(new_params, "", NULL, AV_DICT_IGNORE_SUFFIX);
801  if (!cookie_entry || !cookie_entry->value) {
802  av_dict_free(&new_params);
803  return -1;
804  }
805 
806  // ensure the cookie is not expired or older than an existing value
807  if ((e = av_dict_get(new_params, "expires", NULL, 0)) && e->value) {
808  struct tm new_tm = {0};
809  if (!parse_set_cookie_expiry_time(e->value, &new_tm)) {
810  AVDictionaryEntry *e2;
811 
812  // if the cookie has already expired ignore it
813  if (av_timegm(&new_tm) < av_gettime() / 1000000) {
814  av_dict_free(&new_params);
815  return 0;
816  }
817 
818  // only replace an older cookie with the same name
819  e2 = av_dict_get(*cookies, cookie_entry->key, NULL, 0);
820  if (e2 && e2->value) {
821  AVDictionary *old_params = NULL;
822  if (!parse_set_cookie(p, &old_params)) {
823  e2 = av_dict_get(old_params, "expires", NULL, 0);
824  if (e2 && e2->value) {
825  struct tm old_tm = {0};
826  if (!parse_set_cookie_expiry_time(e->value, &old_tm)) {
827  if (av_timegm(&new_tm) < av_timegm(&old_tm)) {
828  av_dict_free(&new_params);
829  av_dict_free(&old_params);
830  return -1;
831  }
832  }
833  }
834  }
835  av_dict_free(&old_params);
836  }
837  }
838  }
839  av_dict_free(&new_params);
840 
841  // duplicate the cookie name (dict will dupe the value)
842  if (!(eql = strchr(p, '='))) return AVERROR(EINVAL);
843  if (!(name = av_strndup(p, eql - p))) return AVERROR(ENOMEM);
844 
845  // add the cookie to the dictionary
846  av_dict_set(cookies, name, eql, AV_DICT_DONT_STRDUP_KEY);
847 
848  return 0;
849 }
850 
851 static int cookie_string(AVDictionary *dict, char **cookies)
852 {
853  AVDictionaryEntry *e = NULL;
854  int len = 1;
855 
856  // determine how much memory is needed for the cookies string
857  while (e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX))
858  len += strlen(e->key) + strlen(e->value) + 1;
859 
860  // reallocate the cookies
861  e = NULL;
862  if (*cookies) av_free(*cookies);
863  *cookies = av_malloc(len);
864  if (!*cookies) return AVERROR(ENOMEM);
865  *cookies[0] = '\0';
866 
867  // write out the cookies
868  while (e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX))
869  av_strlcatf(*cookies, len, "%s%s\n", e->key, e->value);
870 
871  return 0;
872 }
873 
874 static int process_line(URLContext *h, char *line, int line_count,
875  int *new_location)
876 {
877  HTTPContext *s = h->priv_data;
878  const char *auto_method = h->flags & AVIO_FLAG_READ ? "POST" : "GET";
879  char *tag, *p, *end, *method, *resource, *version;
880  int ret;
881 
882  /* end of header */
883  if (line[0] == '\0') {
884  s->end_header = 1;
885  return 0;
886  }
887 
888  p = line;
889  if (line_count == 0) {
890  if (s->is_connected_server) {
891  // HTTP method
892  method = p;
893  while (*p && !av_isspace(*p))
894  p++;
895  *(p++) = '\0';
896  av_log(h, AV_LOG_TRACE, "Received method: %s\n", method);
897  if (s->method) {
898  if (av_strcasecmp(s->method, method)) {
899  av_log(h, AV_LOG_ERROR, "Received and expected HTTP method do not match. (%s expected, %s received)\n",
900  s->method, method);
901  return ff_http_averror(400, AVERROR(EIO));
902  }
903  } else {
904  // use autodetected HTTP method to expect
905  av_log(h, AV_LOG_TRACE, "Autodetected %s HTTP method\n", auto_method);
906  if (av_strcasecmp(auto_method, method)) {
907  av_log(h, AV_LOG_ERROR, "Received and autodetected HTTP method did not match "
908  "(%s autodetected %s received)\n", auto_method, method);
909  return ff_http_averror(400, AVERROR(EIO));
910  }
911  if (!(s->method = av_strdup(method)))
912  return AVERROR(ENOMEM);
913  }
914 
915  // HTTP resource
916  while (av_isspace(*p))
917  p++;
918  resource = p;
919  while (*p && !av_isspace(*p))
920  p++;
921  *(p++) = '\0';
922  av_log(h, AV_LOG_TRACE, "Requested resource: %s\n", resource);
923  if (!(s->resource = av_strdup(resource)))
924  return AVERROR(ENOMEM);
925 
926  // HTTP version
927  while (av_isspace(*p))
928  p++;
929  version = p;
930  while (*p && !av_isspace(*p))
931  p++;
932  *p = '\0';
933  if (av_strncasecmp(version, "HTTP/", 5)) {
934  av_log(h, AV_LOG_ERROR, "Malformed HTTP version string.\n");
935  return ff_http_averror(400, AVERROR(EIO));
936  }
937  av_log(h, AV_LOG_TRACE, "HTTP version string: %s\n", version);
938  } else {
939  if (av_strncasecmp(p, "HTTP/1.0", 8) == 0)
940  s->willclose = 1;
941  while (*p != '/' && *p != '\0')
942  p++;
943  while (*p == '/')
944  p++;
945  av_freep(&s->http_version);
946  s->http_version = av_strndup(p, 3);
947  while (!av_isspace(*p) && *p != '\0')
948  p++;
949  while (av_isspace(*p))
950  p++;
951  s->http_code = strtol(p, &end, 10);
952 
953  av_log(h, AV_LOG_TRACE, "http_code=%d\n", s->http_code);
954 
955  if ((ret = check_http_code(h, s->http_code, end)) < 0)
956  return ret;
957  }
958  } else {
959  while (*p != '\0' && *p != ':')
960  p++;
961  if (*p != ':')
962  return 1;
963 
964  *p = '\0';
965  tag = line;
966  p++;
967  while (av_isspace(*p))
968  p++;
969  if (!av_strcasecmp(tag, "Location")) {
970  if ((ret = parse_location(s, p)) < 0)
971  return ret;
972  *new_location = 1;
973  } else if (!av_strcasecmp(tag, "Content-Length") &&
974  s->filesize == UINT64_MAX) {
975  s->filesize = strtoull(p, NULL, 10);
976  } else if (!av_strcasecmp(tag, "Content-Range")) {
978  } else if (!av_strcasecmp(tag, "Accept-Ranges") &&
979  !strncmp(p, "bytes", 5) &&
980  s->seekable == -1) {
981  h->is_streamed = 0;
982  } else if (!av_strcasecmp(tag, "Transfer-Encoding") &&
983  !av_strncasecmp(p, "chunked", 7)) {
984  s->filesize = UINT64_MAX;
985  s->chunksize = 0;
986  } else if (!av_strcasecmp(tag, "WWW-Authenticate")) {
987  ff_http_auth_handle_header(&s->auth_state, tag, p);
988  } else if (!av_strcasecmp(tag, "Authentication-Info")) {
989  ff_http_auth_handle_header(&s->auth_state, tag, p);
990  } else if (!av_strcasecmp(tag, "Proxy-Authenticate")) {
991  ff_http_auth_handle_header(&s->proxy_auth_state, tag, p);
992  } else if (!av_strcasecmp(tag, "Connection")) {
993  if (!strcmp(p, "close"))
994  s->willclose = 1;
995  } else if (!av_strcasecmp(tag, "Server")) {
996  if (!av_strcasecmp(p, "AkamaiGHost")) {
997  s->is_akamai = 1;
998  } else if (!av_strncasecmp(p, "MediaGateway", 12)) {
999  s->is_mediagateway = 1;
1000  }
1001  } else if (!av_strcasecmp(tag, "Content-Type")) {
1002  av_free(s->mime_type);
1003  s->mime_type = av_strdup(p);
1004  } else if (!av_strcasecmp(tag, "Set-Cookie")) {
1005  if (parse_cookie(s, p, &s->cookie_dict))
1006  av_log(h, AV_LOG_WARNING, "Unable to parse '%s'\n", p);
1007  } else if (!av_strcasecmp(tag, "Icy-MetaInt")) {
1008  s->icy_metaint = strtoull(p, NULL, 10);
1009  } else if (!av_strncasecmp(tag, "Icy-", 4)) {
1010  if ((ret = parse_icy(s, tag, p)) < 0)
1011  return ret;
1012  } else if (!av_strcasecmp(tag, "Content-Encoding")) {
1013  if ((ret = parse_content_encoding(h, p)) < 0)
1014  return ret;
1015  }
1016  }
1017  return 1;
1018 }
1019 
1020 /**
1021  * Create a string containing cookie values for use as a HTTP cookie header
1022  * field value for a particular path and domain from the cookie values stored in
1023  * the HTTP protocol context. The cookie string is stored in *cookies, and may
1024  * be NULL if there are no valid cookies.
1025  *
1026  * @return a negative value if an error condition occurred, 0 otherwise
1027  */
1028 static int get_cookies(HTTPContext *s, char **cookies, const char *path,
1029  const char *domain)
1030 {
1031  // cookie strings will look like Set-Cookie header field values. Multiple
1032  // Set-Cookie fields will result in multiple values delimited by a newline
1033  int ret = 0;
1034  char *cookie, *set_cookies, *next;
1035 
1036  // destroy any cookies in the dictionary.
1037  av_dict_free(&s->cookie_dict);
1038 
1039  if (!s->cookies)
1040  return 0;
1041 
1042  next = set_cookies = av_strdup(s->cookies);
1043  if (!next)
1044  return AVERROR(ENOMEM);
1045 
1046  *cookies = NULL;
1047  while ((cookie = av_strtok(next, "\n", &next)) && !ret) {
1048  AVDictionary *cookie_params = NULL;
1049  AVDictionaryEntry *cookie_entry, *e;
1050 
1051  // store the cookie in a dict in case it is updated in the response
1052  if (parse_cookie(s, cookie, &s->cookie_dict))
1053  av_log(s, AV_LOG_WARNING, "Unable to parse '%s'\n", cookie);
1054 
1055  // continue on to the next cookie if this one cannot be parsed
1056  if (parse_set_cookie(cookie, &cookie_params))
1057  goto skip_cookie;
1058 
1059  // if the cookie has no value, skip it
1060  cookie_entry = av_dict_get(cookie_params, "", NULL, AV_DICT_IGNORE_SUFFIX);
1061  if (!cookie_entry || !cookie_entry->value)
1062  goto skip_cookie;
1063 
1064  // if the cookie has expired, don't add it
1065  if ((e = av_dict_get(cookie_params, "expires", NULL, 0)) && e->value) {
1066  struct tm tm_buf = {0};
1067  if (!parse_set_cookie_expiry_time(e->value, &tm_buf)) {
1068  if (av_timegm(&tm_buf) < av_gettime() / 1000000)
1069  goto skip_cookie;
1070  }
1071  }
1072 
1073  // if no domain in the cookie assume it appied to this request
1074  if ((e = av_dict_get(cookie_params, "domain", NULL, 0)) && e->value) {
1075  // find the offset comparison is on the min domain (b.com, not a.b.com)
1076  int domain_offset = strlen(domain) - strlen(e->value);
1077  if (domain_offset < 0)
1078  goto skip_cookie;
1079 
1080  // match the cookie domain
1081  if (av_strcasecmp(&domain[domain_offset], e->value))
1082  goto skip_cookie;
1083  }
1084 
1085  // ensure this cookie matches the path
1086  e = av_dict_get(cookie_params, "path", NULL, 0);
1087  if (!e || av_strncasecmp(path, e->value, strlen(e->value)))
1088  goto skip_cookie;
1089 
1090  // cookie parameters match, so copy the value
1091  if (!*cookies) {
1092  *cookies = av_asprintf("%s=%s", cookie_entry->key, cookie_entry->value);
1093  } else {
1094  char *tmp = *cookies;
1095  *cookies = av_asprintf("%s; %s=%s", tmp, cookie_entry->key, cookie_entry->value);
1096  av_free(tmp);
1097  }
1098  if (!*cookies)
1099  ret = AVERROR(ENOMEM);
1100 
1101  skip_cookie:
1102  av_dict_free(&cookie_params);
1103  }
1104 
1105  av_free(set_cookies);
1106 
1107  return ret;
1108 }
1109 
1110 static inline int has_header(const char *str, const char *header)
1111 {
1112  /* header + 2 to skip over CRLF prefix. (make sure you have one!) */
1113  if (!str)
1114  return 0;
1115  return av_stristart(str, header + 2, NULL) || av_stristr(str, header);
1116 }
1117 
1118 static int http_read_header(URLContext *h, int *new_location)
1119 {
1120  HTTPContext *s = h->priv_data;
1121  char line[MAX_URL_SIZE];
1122  int err = 0;
1123 
1124  s->chunksize = UINT64_MAX;
1125 
1126  for (;;) {
1127  if ((err = http_get_line(s, line, sizeof(line))) < 0)
1128  return err;
1129 
1130  av_log(h, AV_LOG_TRACE, "header='%s'\n", line);
1131 
1132  err = process_line(h, line, s->line_count, new_location);
1133  if (err < 0)
1134  return err;
1135  if (err == 0)
1136  break;
1137  s->line_count++;
1138  }
1139 
1140  if (s->seekable == -1 && s->is_mediagateway && s->filesize == 2000000000)
1141  h->is_streamed = 1; /* we can in fact _not_ seek */
1142 
1143  // add any new cookies into the existing cookie string
1144  cookie_string(s->cookie_dict, &s->cookies);
1145  av_dict_free(&s->cookie_dict);
1146 
1147  return err;
1148 }
1149 
1150 static int http_connect(URLContext *h, const char *path, const char *local_path,
1151  const char *hoststr, const char *auth,
1152  const char *proxyauth, int *new_location)
1153 {
1154  HTTPContext *s = h->priv_data;
1155  int post, err;
1156  char headers[HTTP_HEADERS_SIZE] = "";
1157  char *authstr = NULL, *proxyauthstr = NULL;
1158  uint64_t off = s->off;
1159  int len = 0;
1160  const char *method;
1161  int send_expect_100 = 0;
1162  int ret;
1163 
1164  /* send http header */
1165  post = h->flags & AVIO_FLAG_WRITE;
1166 
1167  if (s->post_data) {
1168  /* force POST method and disable chunked encoding when
1169  * custom HTTP post data is set */
1170  post = 1;
1171  s->chunked_post = 0;
1172  }
1173 
1174  if (s->method)
1175  method = s->method;
1176  else
1177  method = post ? "POST" : "GET";
1178 
1179  authstr = ff_http_auth_create_response(&s->auth_state, auth,
1180  local_path, method);
1181  proxyauthstr = ff_http_auth_create_response(&s->proxy_auth_state, proxyauth,
1182  local_path, method);
1183 
1184  if (post && !s->post_data) {
1185  if (s->send_expect_100 != -1) {
1186  send_expect_100 = s->send_expect_100;
1187  } else {
1188  send_expect_100 = 0;
1189  /* The user has supplied authentication but we don't know the auth type,
1190  * send Expect: 100-continue to get the 401 response including the
1191  * WWW-Authenticate header, or an 100 continue if no auth actually
1192  * is needed. */
1193  if (auth && *auth &&
1194  s->auth_state.auth_type == HTTP_AUTH_NONE &&
1195  s->http_code != 401)
1196  send_expect_100 = 1;
1197  }
1198  }
1199 
1200 #if FF_API_HTTP_USER_AGENT
1201  if (strcmp(s->user_agent_deprecated, DEFAULT_USER_AGENT)) {
1202  s->user_agent = av_strdup(s->user_agent_deprecated);
1203  }
1204 #endif
1205  /* set default headers if needed */
1206  if (!has_header(s->headers, "\r\nUser-Agent: "))
1207  len += av_strlcatf(headers + len, sizeof(headers) - len,
1208  "User-Agent: %s\r\n", s->user_agent);
1209  if (s->referer) {
1210  /* set default headers if needed */
1211  if (!has_header(s->headers, "\r\nReferer: "))
1212  len += av_strlcatf(headers + len, sizeof(headers) - len,
1213  "Referer: %s\r\n", s->referer);
1214  }
1215  if (!has_header(s->headers, "\r\nAccept: "))
1216  len += av_strlcpy(headers + len, "Accept: */*\r\n",
1217  sizeof(headers) - len);
1218  // Note: we send this on purpose even when s->off is 0 when we're probing,
1219  // since it allows us to detect more reliably if a (non-conforming)
1220  // server supports seeking by analysing the reply headers.
1221  if (!has_header(s->headers, "\r\nRange: ") && !post && (s->off > 0 || s->end_off || s->seekable == -1)) {
1222  len += av_strlcatf(headers + len, sizeof(headers) - len,
1223  "Range: bytes=%"PRIu64"-", s->off);
1224  if (s->end_off)
1225  len += av_strlcatf(headers + len, sizeof(headers) - len,
1226  "%"PRId64, s->end_off - 1);
1227  len += av_strlcpy(headers + len, "\r\n",
1228  sizeof(headers) - len);
1229  }
1230  if (send_expect_100 && !has_header(s->headers, "\r\nExpect: "))
1231  len += av_strlcatf(headers + len, sizeof(headers) - len,
1232  "Expect: 100-continue\r\n");
1233 
1234  if (!has_header(s->headers, "\r\nConnection: ")) {
1235  if (s->multiple_requests)
1236  len += av_strlcpy(headers + len, "Connection: keep-alive\r\n",
1237  sizeof(headers) - len);
1238  else
1239  len += av_strlcpy(headers + len, "Connection: close\r\n",
1240  sizeof(headers) - len);
1241  }
1242 
1243  if (!has_header(s->headers, "\r\nHost: "))
1244  len += av_strlcatf(headers + len, sizeof(headers) - len,
1245  "Host: %s\r\n", hoststr);
1246  if (!has_header(s->headers, "\r\nContent-Length: ") && s->post_data)
1247  len += av_strlcatf(headers + len, sizeof(headers) - len,
1248  "Content-Length: %d\r\n", s->post_datalen);
1249 
1250  if (!has_header(s->headers, "\r\nContent-Type: ") && s->content_type)
1251  len += av_strlcatf(headers + len, sizeof(headers) - len,
1252  "Content-Type: %s\r\n", s->content_type);
1253  if (!has_header(s->headers, "\r\nCookie: ") && s->cookies) {
1254  char *cookies = NULL;
1255  if (!get_cookies(s, &cookies, path, hoststr) && cookies) {
1256  len += av_strlcatf(headers + len, sizeof(headers) - len,
1257  "Cookie: %s\r\n", cookies);
1258  av_free(cookies);
1259  }
1260  }
1261  if (!has_header(s->headers, "\r\nIcy-MetaData: ") && s->icy)
1262  len += av_strlcatf(headers + len, sizeof(headers) - len,
1263  "Icy-MetaData: %d\r\n", 1);
1264 
1265  /* now add in custom headers */
1266  if (s->headers)
1267  av_strlcpy(headers + len, s->headers, sizeof(headers) - len);
1268 
1269  ret = snprintf(s->buffer, sizeof(s->buffer),
1270  "%s %s HTTP/1.1\r\n"
1271  "%s"
1272  "%s"
1273  "%s"
1274  "%s%s"
1275  "\r\n",
1276  method,
1277  path,
1278  post && s->chunked_post ? "Transfer-Encoding: chunked\r\n" : "",
1279  headers,
1280  authstr ? authstr : "",
1281  proxyauthstr ? "Proxy-" : "", proxyauthstr ? proxyauthstr : "");
1282 
1283  av_log(h, AV_LOG_DEBUG, "request: %s\n", s->buffer);
1284 
1285  if (strlen(headers) + 1 == sizeof(headers) ||
1286  ret >= sizeof(s->buffer)) {
1287  av_log(h, AV_LOG_ERROR, "overlong headers\n");
1288  err = AVERROR(EINVAL);
1289  goto done;
1290  }
1291 
1292 
1293  if ((err = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0)
1294  goto done;
1295 
1296  if (s->post_data)
1297  if ((err = ffurl_write(s->hd, s->post_data, s->post_datalen)) < 0)
1298  goto done;
1299 
1300  /* init input buffer */
1301  s->buf_ptr = s->buffer;
1302  s->buf_end = s->buffer;
1303  s->line_count = 0;
1304  s->off = 0;
1305  s->icy_data_read = 0;
1306  s->filesize = UINT64_MAX;
1307  s->willclose = 0;
1308  s->end_chunked_post = 0;
1309  s->end_header = 0;
1310 #if CONFIG_ZLIB
1311  s->compressed = 0;
1312 #endif
1313  if (post && !s->post_data && !send_expect_100) {
1314  /* Pretend that it did work. We didn't read any header yet, since
1315  * we've still to send the POST data, but the code calling this
1316  * function will check http_code after we return. */
1317  s->http_code = 200;
1318  err = 0;
1319  goto done;
1320  }
1321 
1322  /* wait for header */
1323  err = http_read_header(h, new_location);
1324  if (err < 0)
1325  goto done;
1326 
1327  if (*new_location)
1328  s->off = off;
1329 
1330  err = (off == s->off) ? 0 : -1;
1331 done:
1332  av_freep(&authstr);
1333  av_freep(&proxyauthstr);
1334  return err;
1335 }
1336 
1338 {
1339  HTTPContext *s = h->priv_data;
1340  int len;
1341 
1342  if (s->chunksize != UINT64_MAX) {
1343  if (s->chunkend) {
1344  return AVERROR_EOF;
1345  }
1346  if (!s->chunksize) {
1347  char line[32];
1348  int err;
1349 
1350  do {
1351  if ((err = http_get_line(s, line, sizeof(line))) < 0)
1352  return err;
1353  } while (!*line); /* skip CR LF from last chunk */
1354 
1355  s->chunksize = strtoull(line, NULL, 16);
1356 
1358  "Chunked encoding data size: %"PRIu64"\n",
1359  s->chunksize);
1360 
1361  if (!s->chunksize && s->multiple_requests) {
1362  http_get_line(s, line, sizeof(line)); // read empty chunk
1363  s->chunkend = 1;
1364  return 0;
1365  }
1366  else if (!s->chunksize) {
1367  av_log(h, AV_LOG_DEBUG, "Last chunk received, closing conn\n");
1368  ffurl_closep(&s->hd);
1369  return 0;
1370  }
1371  else if (s->chunksize == UINT64_MAX) {
1372  av_log(h, AV_LOG_ERROR, "Invalid chunk size %"PRIu64"\n",
1373  s->chunksize);
1374  return AVERROR(EINVAL);
1375  }
1376  }
1377  size = FFMIN(size, s->chunksize);
1378  }
1379 
1380  /* read bytes from input buffer first */
1381  len = s->buf_end - s->buf_ptr;
1382  if (len > 0) {
1383  if (len > size)
1384  len = size;
1385  memcpy(buf, s->buf_ptr, len);
1386  s->buf_ptr += len;
1387  } else {
1388  uint64_t target_end = s->end_off ? s->end_off : s->filesize;
1389  if ((!s->willclose || s->chunksize == UINT64_MAX) && s->off >= target_end)
1390  return AVERROR_EOF;
1391  len = ffurl_read(s->hd, buf, size);
1392  if (!len && (!s->willclose || s->chunksize == UINT64_MAX) && s->off < target_end) {
1394  "Stream ends prematurely at %"PRIu64", should be %"PRIu64"\n",
1395  s->off, target_end
1396  );
1397  return AVERROR(EIO);
1398  }
1399  }
1400  if (len > 0) {
1401  s->off += len;
1402  if (s->chunksize > 0 && s->chunksize != UINT64_MAX) {
1403  av_assert0(s->chunksize >= len);
1404  s->chunksize -= len;
1405  }
1406  }
1407  return len;
1408 }
1409 
1410 #if CONFIG_ZLIB
1411 #define DECOMPRESS_BUF_SIZE (256 * 1024)
1412 static int http_buf_read_compressed(URLContext *h, uint8_t *buf, int size)
1413 {
1414  HTTPContext *s = h->priv_data;
1415  int ret;
1416 
1417  if (!s->inflate_buffer) {
1418  s->inflate_buffer = av_malloc(DECOMPRESS_BUF_SIZE);
1419  if (!s->inflate_buffer)
1420  return AVERROR(ENOMEM);
1421  }
1422 
1423  if (s->inflate_stream.avail_in == 0) {
1424  int read = http_buf_read(h, s->inflate_buffer, DECOMPRESS_BUF_SIZE);
1425  if (read <= 0)
1426  return read;
1427  s->inflate_stream.next_in = s->inflate_buffer;
1428  s->inflate_stream.avail_in = read;
1429  }
1430 
1431  s->inflate_stream.avail_out = size;
1432  s->inflate_stream.next_out = buf;
1433 
1434  ret = inflate(&s->inflate_stream, Z_SYNC_FLUSH);
1435  if (ret != Z_OK && ret != Z_STREAM_END)
1436  av_log(h, AV_LOG_WARNING, "inflate return value: %d, %s\n",
1437  ret, s->inflate_stream.msg);
1438 
1439  return size - s->inflate_stream.avail_out;
1440 }
1441 #endif /* CONFIG_ZLIB */
1442 
1443 static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int force_reconnect);
1444 
1446 {
1447  HTTPContext *s = h->priv_data;
1448  int err, new_location, read_ret;
1449  int64_t seek_ret;
1450  int reconnect_delay = 0;
1451 
1452  if (!s->hd)
1453  return AVERROR_EOF;
1454 
1455  if (s->end_chunked_post && !s->end_header) {
1456  err = http_read_header(h, &new_location);
1457  if (err < 0)
1458  return err;
1459  }
1460 
1461 #if CONFIG_ZLIB
1462  if (s->compressed)
1463  return http_buf_read_compressed(h, buf, size);
1464 #endif /* CONFIG_ZLIB */
1465  read_ret = http_buf_read(h, buf, size);
1466  while (read_ret < 0) {
1467  uint64_t target = h->is_streamed ? 0 : s->off;
1468 
1469  if (read_ret == AVERROR_EXIT)
1470  break;
1471 
1472  if (h->is_streamed && !s->reconnect_streamed)
1473  break;
1474 
1475  if (!(s->reconnect && s->filesize > 0 && s->off < s->filesize) &&
1476  !(s->reconnect_at_eof && read_ret == AVERROR_EOF))
1477  break;
1478 
1479  if (reconnect_delay > s->reconnect_delay_max)
1480  return AVERROR(EIO);
1481 
1482  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));
1483  err = ff_network_sleep_interruptible(1000U*1000*reconnect_delay, &h->interrupt_callback);
1484  if (err != AVERROR(ETIMEDOUT))
1485  return err;
1486  reconnect_delay = 1 + 2*reconnect_delay;
1487  seek_ret = http_seek_internal(h, target, SEEK_SET, 1);
1488  if (seek_ret >= 0 && seek_ret != target) {
1489  av_log(h, AV_LOG_ERROR, "Failed to reconnect at %"PRIu64".\n", target);
1490  return read_ret;
1491  }
1492 
1493  read_ret = http_buf_read(h, buf, size);
1494  }
1495 
1496  return read_ret;
1497 }
1498 
1499 // Like http_read_stream(), but no short reads.
1500 // Assumes partial reads are an error.
1502 {
1503  int pos = 0;
1504  while (pos < size) {
1505  int len = http_read_stream(h, buf + pos, size - pos);
1506  if (len < 0)
1507  return len;
1508  pos += len;
1509  }
1510  return pos;
1511 }
1512 
1513 static void update_metadata(URLContext *h, char *data)
1514 {
1515  char *key;
1516  char *val;
1517  char *end;
1518  char *next = data;
1519  HTTPContext *s = h->priv_data;
1520 
1521  while (*next) {
1522  key = next;
1523  val = strstr(key, "='");
1524  if (!val)
1525  break;
1526  end = strstr(val, "';");
1527  if (!end)
1528  break;
1529 
1530  *val = '\0';
1531  *end = '\0';
1532  val += 2;
1533 
1534  av_dict_set(&s->metadata, key, val, 0);
1535  av_log(h, AV_LOG_VERBOSE, "Metadata update for %s: %s\n", key, val);
1536 
1537  next = end + 2;
1538  }
1539 }
1540 
1541 static int store_icy(URLContext *h, int size)
1542 {
1543  HTTPContext *s = h->priv_data;
1544  /* until next metadata packet */
1545  uint64_t remaining;
1546 
1547  if (s->icy_metaint < s->icy_data_read)
1548  return AVERROR_INVALIDDATA;
1549  remaining = s->icy_metaint - s->icy_data_read;
1550 
1551  if (!remaining) {
1552  /* The metadata packet is variable sized. It has a 1 byte header
1553  * which sets the length of the packet (divided by 16). If it's 0,
1554  * the metadata doesn't change. After the packet, icy_metaint bytes
1555  * of normal data follows. */
1556  uint8_t ch;
1557  int len = http_read_stream_all(h, &ch, 1);
1558  if (len < 0)
1559  return len;
1560  if (ch > 0) {
1561  char data[255 * 16 + 1];
1562  int ret;
1563  len = ch * 16;
1565  if (ret < 0)
1566  return ret;
1567  data[len + 1] = 0;
1568  if ((ret = av_opt_set(s, "icy_metadata_packet", data, 0)) < 0)
1569  return ret;
1571  }
1572  s->icy_data_read = 0;
1573  remaining = s->icy_metaint;
1574  }
1575 
1576  return FFMIN(size, remaining);
1577 }
1578 
1579 static int http_read(URLContext *h, uint8_t *buf, int size)
1580 {
1581  HTTPContext *s = h->priv_data;
1582 
1583  if (s->icy_metaint > 0) {
1584  size = store_icy(h, size);
1585  if (size < 0)
1586  return size;
1587  }
1588 
1590  if (size > 0)
1591  s->icy_data_read += size;
1592  return size;
1593 }
1594 
1595 /* used only when posting data */
1596 static int http_write(URLContext *h, const uint8_t *buf, int size)
1597 {
1598  char temp[11] = ""; /* 32-bit hex + CRLF + nul */
1599  int ret;
1600  char crlf[] = "\r\n";
1601  HTTPContext *s = h->priv_data;
1602 
1603  if (!s->chunked_post) {
1604  /* non-chunked data is sent without any special encoding */
1605  return ffurl_write(s->hd, buf, size);
1606  }
1607 
1608  /* silently ignore zero-size data since chunk encoding that would
1609  * signal EOF */
1610  if (size > 0) {
1611  /* upload data using chunked encoding */
1612  snprintf(temp, sizeof(temp), "%x\r\n", size);
1613 
1614  if ((ret = ffurl_write(s->hd, temp, strlen(temp))) < 0 ||
1615  (ret = ffurl_write(s->hd, buf, size)) < 0 ||
1616  (ret = ffurl_write(s->hd, crlf, sizeof(crlf) - 1)) < 0)
1617  return ret;
1618  }
1619  return size;
1620 }
1621 
1622 static int http_shutdown(URLContext *h, int flags)
1623 {
1624  int ret = 0;
1625  char footer[] = "0\r\n\r\n";
1626  HTTPContext *s = h->priv_data;
1627 
1628  /* signal end of chunked encoding if used */
1629  if (((flags & AVIO_FLAG_WRITE) && s->chunked_post) ||
1630  ((flags & AVIO_FLAG_READ) && s->chunked_post && s->listen)) {
1631  ret = ffurl_write(s->hd, footer, sizeof(footer) - 1);
1632  ret = ret > 0 ? 0 : ret;
1633  /* flush the receive buffer when it is write only mode */
1634  if (!(flags & AVIO_FLAG_READ)) {
1635  char buf[1024];
1636  int read_ret;
1637  s->hd->flags |= AVIO_FLAG_NONBLOCK;
1638  read_ret = ffurl_read(s->hd, buf, sizeof(buf));
1639  s->hd->flags &= ~AVIO_FLAG_NONBLOCK;
1640  if (read_ret < 0 && read_ret != AVERROR(EAGAIN)) {
1641  av_log(h, AV_LOG_ERROR, "URL read error: %s\n", av_err2str(read_ret));
1642  ret = read_ret;
1643  }
1644  }
1645  s->end_chunked_post = 1;
1646  }
1647 
1648  return ret;
1649 }
1650 
1652 {
1653  int ret = 0;
1654  HTTPContext *s = h->priv_data;
1655 
1656 #if CONFIG_ZLIB
1657  inflateEnd(&s->inflate_stream);
1658  av_freep(&s->inflate_buffer);
1659 #endif /* CONFIG_ZLIB */
1660 
1661  if (s->hd && !s->end_chunked_post)
1662  /* Close the write direction by sending the end of chunked encoding. */
1663  ret = http_shutdown(h, h->flags);
1664 
1665  if (s->hd)
1666  ffurl_closep(&s->hd);
1667  av_dict_free(&s->chained_options);
1668  return ret;
1669 }
1670 
1671 static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int force_reconnect)
1672 {
1673  HTTPContext *s = h->priv_data;
1674  URLContext *old_hd = s->hd;
1675  uint64_t old_off = s->off;
1676  uint8_t old_buf[BUFFER_SIZE];
1677  int old_buf_size, ret;
1679 
1680  if (whence == AVSEEK_SIZE)
1681  return s->filesize;
1682  else if (!force_reconnect &&
1683  ((whence == SEEK_CUR && off == 0) ||
1684  (whence == SEEK_SET && off == s->off)))
1685  return s->off;
1686  else if ((s->filesize == UINT64_MAX && whence == SEEK_END))
1687  return AVERROR(ENOSYS);
1688 
1689  if (whence == SEEK_CUR)
1690  off += s->off;
1691  else if (whence == SEEK_END)
1692  off += s->filesize;
1693  else if (whence != SEEK_SET)
1694  return AVERROR(EINVAL);
1695  if (off < 0)
1696  return AVERROR(EINVAL);
1697  s->off = off;
1698 
1699  if (s->off && h->is_streamed)
1700  return AVERROR(ENOSYS);
1701 
1702  /* do not try to make a new connection if seeking past the end of the file */
1703  if (s->end_off || s->filesize != UINT64_MAX) {
1704  uint64_t end_pos = s->end_off ? s->end_off : s->filesize;
1705  if (s->off >= end_pos)
1706  return s->off;
1707  }
1708 
1709  /* we save the old context in case the seek fails */
1710  old_buf_size = s->buf_end - s->buf_ptr;
1711  memcpy(old_buf, s->buf_ptr, old_buf_size);
1712  s->hd = NULL;
1713 
1714  /* if it fails, continue on old connection */
1715  if ((ret = http_open_cnx(h, &options)) < 0) {
1717  memcpy(s->buffer, old_buf, old_buf_size);
1718  s->buf_ptr = s->buffer;
1719  s->buf_end = s->buffer + old_buf_size;
1720  s->hd = old_hd;
1721  s->off = old_off;
1722  return ret;
1723  }
1725  ffurl_close(old_hd);
1726  return off;
1727 }
1728 
1729 static int64_t http_seek(URLContext *h, int64_t off, int whence)
1730 {
1731  return http_seek_internal(h, off, whence, 0);
1732 }
1733 
1735 {
1736  HTTPContext *s = h->priv_data;
1737  return ffurl_get_file_handle(s->hd);
1738 }
1739 
1741 {
1742  HTTPContext *s = h->priv_data;
1743  return ffurl_get_short_seek(s->hd);
1744 }
1745 
1746 #define HTTP_CLASS(flavor) \
1747 static const AVClass flavor ## _context_class = { \
1748  .class_name = # flavor, \
1749  .item_name = av_default_item_name, \
1750  .option = options, \
1751  .version = LIBAVUTIL_VERSION_INT, \
1752 }
1753 
1754 #if CONFIG_HTTP_PROTOCOL
1755 HTTP_CLASS(http);
1756 
1757 const URLProtocol ff_http_protocol = {
1758  .name = "http",
1759  .url_open2 = http_open,
1760  .url_accept = http_accept,
1761  .url_handshake = http_handshake,
1762  .url_read = http_read,
1763  .url_write = http_write,
1764  .url_seek = http_seek,
1765  .url_close = http_close,
1766  .url_get_file_handle = http_get_file_handle,
1767  .url_get_short_seek = http_get_short_seek,
1768  .url_shutdown = http_shutdown,
1769  .priv_data_size = sizeof(HTTPContext),
1770  .priv_data_class = &http_context_class,
1772  .default_whitelist = "http,https,tls,rtp,tcp,udp,crypto,httpproxy"
1773 };
1774 #endif /* CONFIG_HTTP_PROTOCOL */
1775 
1776 #if CONFIG_HTTPS_PROTOCOL
1777 HTTP_CLASS(https);
1778 
1780  .name = "https",
1781  .url_open2 = http_open,
1782  .url_read = http_read,
1783  .url_write = http_write,
1784  .url_seek = http_seek,
1785  .url_close = http_close,
1786  .url_get_file_handle = http_get_file_handle,
1787  .url_get_short_seek = http_get_short_seek,
1788  .url_shutdown = http_shutdown,
1789  .priv_data_size = sizeof(HTTPContext),
1790  .priv_data_class = &https_context_class,
1792  .default_whitelist = "http,https,tls,rtp,tcp,udp,crypto,httpproxy"
1793 };
1794 #endif /* CONFIG_HTTPS_PROTOCOL */
1795 
1796 #if CONFIG_HTTPPROXY_PROTOCOL
1797 static int http_proxy_close(URLContext *h)
1798 {
1799  HTTPContext *s = h->priv_data;
1800  if (s->hd)
1801  ffurl_closep(&s->hd);
1802  return 0;
1803 }
1804 
1805 static int http_proxy_open(URLContext *h, const char *uri, int flags)
1806 {
1807  HTTPContext *s = h->priv_data;
1808  char hostname[1024], hoststr[1024];
1809  char auth[1024], pathbuf[1024], *path;
1810  char lower_url[100];
1811  int port, ret = 0, attempts = 0;
1812  HTTPAuthType cur_auth_type;
1813  char *authstr;
1814  int new_loc;
1815 
1816  if( s->seekable == 1 )
1817  h->is_streamed = 0;
1818  else
1819  h->is_streamed = 1;
1820 
1821  av_url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port,
1822  pathbuf, sizeof(pathbuf), uri);
1823  ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL);
1824  path = pathbuf;
1825  if (*path == '/')
1826  path++;
1827 
1828  ff_url_join(lower_url, sizeof(lower_url), "tcp", NULL, hostname, port,
1829  NULL);
1830 redo:
1831  ret = ffurl_open_whitelist(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
1832  &h->interrupt_callback, NULL,
1833  h->protocol_whitelist, h->protocol_blacklist, h);
1834  if (ret < 0)
1835  return ret;
1836 
1837  authstr = ff_http_auth_create_response(&s->proxy_auth_state, auth,
1838  path, "CONNECT");
1839  snprintf(s->buffer, sizeof(s->buffer),
1840  "CONNECT %s HTTP/1.1\r\n"
1841  "Host: %s\r\n"
1842  "Connection: close\r\n"
1843  "%s%s"
1844  "\r\n",
1845  path,
1846  hoststr,
1847  authstr ? "Proxy-" : "", authstr ? authstr : "");
1848  av_freep(&authstr);
1849 
1850  if ((ret = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0)
1851  goto fail;
1852 
1853  s->buf_ptr = s->buffer;
1854  s->buf_end = s->buffer;
1855  s->line_count = 0;
1856  s->filesize = UINT64_MAX;
1857  cur_auth_type = s->proxy_auth_state.auth_type;
1858 
1859  /* Note: This uses buffering, potentially reading more than the
1860  * HTTP header. If tunneling a protocol where the server starts
1861  * the conversation, we might buffer part of that here, too.
1862  * Reading that requires using the proper ffurl_read() function
1863  * on this URLContext, not using the fd directly (as the tls
1864  * protocol does). This shouldn't be an issue for tls though,
1865  * since the client starts the conversation there, so there
1866  * is no extra data that we might buffer up here.
1867  */
1868  ret = http_read_header(h, &new_loc);
1869  if (ret < 0)
1870  goto fail;
1871 
1872  attempts++;
1873  if (s->http_code == 407 &&
1874  (cur_auth_type == HTTP_AUTH_NONE || s->proxy_auth_state.stale) &&
1875  s->proxy_auth_state.auth_type != HTTP_AUTH_NONE && attempts < 2) {
1876  ffurl_closep(&s->hd);
1877  goto redo;
1878  }
1879 
1880  if (s->http_code < 400)
1881  return 0;
1882  ret = ff_http_averror(s->http_code, AVERROR(EIO));
1883 
1884 fail:
1885  http_proxy_close(h);
1886  return ret;
1887 }
1888 
1889 static int http_proxy_write(URLContext *h, const uint8_t *buf, int size)
1890 {
1891  HTTPContext *s = h->priv_data;
1892  return ffurl_write(s->hd, buf, size);
1893 }
1894 
1896  .name = "httpproxy",
1897  .url_open = http_proxy_open,
1898  .url_read = http_buf_read,
1899  .url_write = http_proxy_write,
1900  .url_close = http_proxy_close,
1901  .url_get_file_handle = http_get_file_handle,
1902  .priv_data_size = sizeof(HTTPContext),
1904 };
1905 #endif /* CONFIG_HTTPPROXY_PROTOCOL */
HTTP_AUTH_BASIC
@ HTTP_AUTH_BASIC
HTTP 1.0 Basic auth from RFC 1945 (also in RFC 2617)
Definition: httpauth.h:30
HTTPContext::http_code
int http_code
Definition: http.c:66
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
SPACE_CHARS
#define SPACE_CHARS
Definition: internal.h:354
http_open_cnx
static int http_open_cnx(URLContext *h, AVDictionary **options)
Definition: http.c:252
WHITESPACES
#define WHITESPACES
Definition: http.c:53
AVERROR
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
opt.h
AV_OPT_FLAG_READONLY
#define AV_OPT_FLAG_READONLY
The option may not be set through the AVOptions API, only read.
Definition: opt.h:289
http_write_reply
static int http_write_reply(URLContext *h, int status_code)
Definition: http.c:376
URL_PROTOCOL_FLAG_NETWORK
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:34
AVERROR_HTTP_OTHER_4XX
#define AVERROR_HTTP_OTHER_4XX
Definition: error.h:80
parse_icy
static int parse_icy(HTTPContext *s, const char *tag, const char *p)
Definition: http.c:707
message
Definition: api-threadmessage-test.c:46
HTTPContext::http_proxy
char * http_proxy
Definition: http.c:74
av_stristr
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
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:55
AVIO_FLAG_READ_WRITE
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
Definition: avio.h:656
http_listen
static int http_listen(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition: http.c:492
ch
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/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64, *(const int64_t *) pi *(1.0/(INT64_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 *(INT64_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 *(INT64_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
av_asprintf
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:113
HTTPContext::seekable
int seekable
Control seekability, 0 = disable, 1 = enable, -1 = probe.
Definition: http.c:87
av_strcasecmp
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
av_isspace
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.h:222
end
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
http_read
static int http_read(URLContext *h, uint8_t *buf, int size)
Definition: http.c:1579
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:26
http_seek_internal
static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int force_reconnect)
Definition: http.c:1671
name
const char * name
Definition: avisynth_c.h:867
READ_HEADERS
@ READ_HEADERS
Definition: http.c:56
AVOption
AVOption.
Definition: opt.h:246
AVERROR_HTTP_SERVER_ERROR
#define AVERROR_HTTP_SERVER_ERROR
Definition: error.h:81
AVSEEK_SIZE
#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
data
const char data[16]
Definition: mxf.c:91
WRITE_REPLY_HEADERS
@ WRITE_REPLY_HEADERS
Definition: http.c:57
AV_DICT_IGNORE_SUFFIX
#define AV_DICT_IGNORE_SUFFIX
Return first entry in a dictionary whose first part corresponds to the search key,...
Definition: dict.h:70
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
http_get_line
static int http_get_line(HTTPContext *s, char *line, int line_size)
Definition: http.c:605
ffurl_close
int ffurl_close(URLContext *h)
Definition: avio.c:470
AVDictionary
Definition: dict.c:30
HTTPContext::end_header
int end_header
Definition: http.c:92
HTTPContext::chained_options
AVDictionary * chained_options
Definition: http.c:115
parse_location
static int parse_location(HTTPContext *s, const char *p)
Definition: http.c:644
http_read_stream
static int http_read_stream(URLContext *h, uint8_t *buf, int size)
Definition: http.c:1445
ff_http_auth_create_response
char * ff_http_auth_create_response(HTTPAuthState *state, const char *auth, const char *path, const char *method)
Definition: httpauth.c:245
HTTPContext::chunkend
int chunkend
Definition: http.c:69
av_strlcatf
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
body
static void body(uint32_t ABCD[4], const uint8_t *src, int nblocks)
Definition: md5.c:101
URLProtocol
Definition: url.h:54
os_support.h
HTTPContext::hd
URLContext * hd
Definition: http.c:63
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
HTTPContext::buf_ptr
unsigned char * buf_ptr
Definition: http.c:64
ff_httpproxy_protocol
const URLProtocol ff_httpproxy_protocol
AVERROR_HTTP_UNAUTHORIZED
#define AVERROR_HTTP_UNAUTHORIZED
Definition: error.h:77
HTTPContext::referer
char * referer
Definition: http.c:79
get_cookies
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:1028
HTTPContext::http_version
char * http_version
Definition: http.c:77
AV_OPT_TYPE_BINARY
@ AV_OPT_TYPE_BINARY
offset must point to a pointer immediately followed by an int for the length
Definition: opt.h:229
U
#define U(x)
Definition: vp56_arith.h:37
fail
#define fail()
Definition: checkasm.h:120
check_http_code
static int check_http_code(URLContext *h, int http_code, const char *end)
Definition: http.c:629
HTTPContext::headers
char * headers
Definition: http.c:75
DEFAULT_USER_AGENT
#define DEFAULT_USER_AGENT
Definition: http.c:134
inflate
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:197
cookie_string
static int cookie_string(AVDictionary *dict, char **cookies)
Definition: http.c:851
has_header
static int has_header(const char *str, const char *header)
Definition: http.c:1110
av_timegm
time_t av_timegm(struct tm *tm)
Convert the decomposed UTC time in tm to a time_t value.
Definition: parseutils.c:568
av_opt_set
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:449
process_line
static int process_line(URLContext *h, char *line, int line_count, int *new_location)
Definition: http.c:874
src
#define src
Definition: vp8dsp.c:254
URLContext::priv_data
void * priv_data
Definition: url.h:41
MAX_REDIRECTS
#define MAX_REDIRECTS
Definition: http.c:49
avassert.h
http_connect
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:1150
HTTPContext::listen
int listen
Definition: http.c:123
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:202
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
buf
void * buf
Definition: avisynth_c.h:766
AVERROR_HTTP_NOT_FOUND
#define AVERROR_HTTP_NOT_FOUND
Definition: error.h:79
HTTPContext::is_connected_server
int is_connected_server
Definition: http.c:128
E
#define E
Definition: http.c:133
av_dict_get
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
ffurl_open_whitelist
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:307
s
#define s(width, name)
Definition: cbs_vp9.c:257
HTTPContext::buf_end
unsigned char * buf_end
Definition: http.c:64
HTTPContext::cookies
char * cookies
holds newline ( ) delimited Set-Cookie header field values (without the "Set-Cookie: " field name)
Definition: http.c:99
AVDictionaryEntry::key
char * key
Definition: dict.h:82
BUFFER_SIZE
#define BUFFER_SIZE
Definition: http.c:48
av_strtok
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
ff_url_join
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
AV_OPT_TYPE_INT64
@ AV_OPT_TYPE_INT64
Definition: opt.h:224
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
AVIO_FLAG_WRITE
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:655
HTTPContext::off
uint64_t off
Definition: http.c:70
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
HTTPContext::post_datalen
int post_datalen
Definition: http.c:96
av_stristart
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
key
const char * key
Definition: hwcontext_opencl.c:168
D
#define D
Definition: http.c:132
parse_cookie
static int parse_cookie(HTTPContext *s, const char *p, AVDictionary **cookies)
Definition: http.c:789
HTTPContext::end_chunked_post
int end_chunked_post
Definition: http.c:90
http_read_header
static int http_read_header(URLContext *h, int *new_location)
Definition: http.c:1118
ff_http_match_no_proxy
int ff_http_match_no_proxy(const char *no_proxy, const char *hostname)
Definition: network.c:551
version
int version
Definition: avisynth_c.h:858
ff_http_auth_handle_header
void ff_http_auth_handle_header(HTTPAuthState *state, const char *key, const char *value)
Definition: httpauth.c:90
parse_content_encoding
static int parse_content_encoding(URLContext *h, const char *p)
Definition: http.c:673
handle_http_errors
static void handle_http_errors(URLContext *h, int error)
Definition: http.c:450
HTTPContext::buffer
unsigned char buffer[BUFFER_SIZE]
Definition: http.c:64
ff_http_do_new_request
int ff_http_do_new_request(URLContext *h, const char *uri)
Send a new HTTP request, reusing the old connection.
Definition: http.c:308
ffurl_accept
int ffurl_accept(URLContext *s, URLContext **c)
Accept an URLContext c on an URLContext s.
Definition: avio.c:226
internal.h
http_read_stream_all
static int http_read_stream_all(URLContext *h, uint8_t *buf, int size)
Definition: http.c:1501
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
NULL
#define NULL
Definition: coverity.c:32
http_get_short_seek
static int http_get_short_seek(URLContext *h)
Definition: http.c:1740
HTTPContext::multiple_requests
int multiple_requests
Definition: http.c:94
ff_http_init_auth_state
void ff_http_init_auth_state(URLContext *dest, const URLContext *src)
Initialize the authentication state based on another HTTP URLContext.
Definition: http.c:180
AV_OPT_TYPE_DICT
@ AV_OPT_TYPE_DICT
Definition: opt.h:230
HTTPContext::metadata
AVDictionary * metadata
Definition: http.c:109
parseutils.h
HTTPContext::proxy_auth_state
HTTPAuthState proxy_auth_state
Definition: http.c:73
http_buf_read
static int http_buf_read(URLContext *h, uint8_t *buf, int size)
Definition: http.c:1337
http_shutdown
static int http_shutdown(URLContext *h, int flags)
Definition: http.c:1622
HTTPContext::filesize
uint64_t filesize
Definition: http.c:70
time.h
parse_content_range
static void parse_content_range(URLContext *h, const char *p)
Definition: http.c:658
AVERROR_HTTP_BAD_REQUEST
#define AVERROR_HTTP_BAD_REQUEST
Definition: error.h:76
MAX_EXPIRY
#define MAX_EXPIRY
Definition: http.c:52
c
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
error
static void error(const char *err)
Definition: target_dec_fuzzer.c:61
HTTPContext::line_count
int line_count
Definition: http.c:65
HTTPAuthState
HTTP Authentication state structure.
Definition: httpauth.h:55
http
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
Definition: writing_filters.txt:29
ff_http_averror
int ff_http_averror(int status_code, int default_averror)
Definition: http.c:359
av_strncasecmp
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition: avstring.c:223
HTTPContext::reconnect_streamed
int reconnect_streamed
Definition: http.c:121
HTTPContext::method
char * method
Definition: http.c:118
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:119
size
int size
Definition: twinvq_data.h:11134
av_reallocp
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
URLProtocol::name
const char * name
Definition: url.h:55
http_write
static int http_write(URLContext *h, const uint8_t *buf, int size)
Definition: http.c:1596
HTTPContext::icy_data_read
uint64_t icy_data_read
Definition: http.c:104
val
const char const char void * val
Definition: avisynth_c.h:863
header
static const uint8_t header[24]
Definition: sdr2.c:67
HTTPContext
Definition: http.c:61
HTTP_HEADERS_SIZE
#define HTTP_HEADERS_SIZE
Definition: http.h:27
FFMIN
#define FFMIN(a, b)
Definition: common.h:96
line
Definition: graph2dot.c:48
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:203
av_strstart
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
HTTPContext::icy_metadata_packet
char * icy_metadata_packet
Definition: http.c:108
ff_http_protocol
const URLProtocol ff_http_protocol
HTTPContext::icy
int icy
Definition: http.c:102
parse_set_cookie_expiry_time
static int parse_set_cookie_expiry_time(const char *exp_str, struct tm *buf)
Definition: http.c:729
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
update_metadata
static void update_metadata(URLContext *h, char *data)
Definition: http.c:1513
ffurl_get_short_seek
int ffurl_get_short_seek(URLContext *h)
Return the current short seek threshold value for this URL.
Definition: avio.c:653
ffurl_alloc
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:290
HTTPContext::is_mediagateway
int is_mediagateway
Definition: http.c:98
HTTPContext::reconnect_at_eof
int reconnect_at_eof
Definition: http.c:120
httpauth.h
http_handshake
static int http_handshake(URLContext *c)
Definition: http.c:456
HTTP_AUTH_NONE
@ HTTP_AUTH_NONE
No authentication specified.
Definition: httpauth.h:29
URLContext
Definition: url.h:38
http_open
static int http_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
Definition: http.c:523
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
ff_network_sleep_interruptible
int ff_network_sleep_interruptible(int64_t timeout, AVIOInterruptCB *int_cb)
Waits for up to 'timeout' microseconds.
Definition: network.c:98
parse_set_cookie
static int parse_set_cookie(const char *set_cookie, AVDictionary **dict)
Definition: http.c:754
http_seek
static int64_t http_seek(URLContext *h, int64_t off, int whence)
Definition: http.c:1729
options
static const AVOption options[]
Definition: http.c:136
HTTPContext::end_off
uint64_t end_off
Definition: http.c:70
value
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default value
Definition: writing_filters.txt:86
HTTPContext::mime_type
char * mime_type
Definition: http.c:76
av_url_split
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:4756
http_open_cnx_internal
static int http_open_cnx_internal(URLContext *h, AVDictionary **options)
Definition: http.c:190
url.h
uint8_t
uint8_t
Definition: audio_convert.c:194
headers
FFmpeg currently uses a custom build this text attempts to document some of its obscure features and options Makefile the full command issued by make and its output will be shown on the screen DBG Preprocess x86 external assembler files to a dbg asm file in the object which then gets compiled Helps in developing those assembler files DESTDIR Destination directory for the install useful to prepare packages or install FFmpeg in cross environments GEN Set to ‘1’ to generate the missing or mismatched references Makefile builds all the libraries and the executables fate Run the fate test note that you must have installed it fate list List all fate regression test targets install Install headers
Definition: build_system.txt:34
HTTPContext::icy_metaint
uint64_t icy_metaint
Definition: http.c:106
http_close
static int http_close(URLContext *h)
Definition: http.c:1651
HTTPContext::resource
char * resource
Definition: http.c:124
len
int len
Definition: vorbis_enc_data.h:452
HTTPContext::reconnect
int reconnect
Definition: http.c:119
OFFSET
#define OFFSET(x)
Definition: http.c:131
ffurl_closep
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:447
HTTPContext::handshake_step
HandshakeState handshake_step
Definition: http.c:127
ff_https_protocol
const URLProtocol ff_https_protocol
tag
uint32_t tag
Definition: movenc.c:1496
ret
ret
Definition: filter_design.txt:187
HandshakeState
HandshakeState
Definition: http.c:54
URLContext::interrupt_callback
AVIOInterruptCB interrupt_callback
Definition: url.h:47
avformat.h
network.h
HTTPContext::chunked_post
int chunked_post
Definition: http.c:88
ff_make_absolute_url
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
HTTPContext::cookie_dict
AVDictionary * cookie_dict
Definition: http.c:101
SIZE_SPECIFIER
#define SIZE_SPECIFIER
Definition: internal.h:264
HTTPContext::reconnect_delay_max
int reconnect_delay_max
Definition: http.c:122
av_small_strptime
char * av_small_strptime(const char *p, const char *fmt, struct tm *dt)
Simplified version of strptime.
Definition: parseutils.c:489
HTTPContext::content_type
char * content_type
Definition: http.c:83
MAX_URL_SIZE
#define MAX_URL_SIZE
Definition: internal.h:30
AV_OPT_FLAG_EXPORT
#define AV_OPT_FLAG_EXPORT
The option is intended for exporting values to the caller.
Definition: opt.h:284
HTTPContext::location
char * location
Definition: http.c:71
ffurl_read
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:410
config.h
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:223
AVERROR_HTTP_FORBIDDEN
#define AVERROR_HTTP_FORBIDDEN
Definition: error.h:78
ffurl_write
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:424
HTTP_CLASS
#define HTTP_CLASS(flavor)
Definition: http.c:1746
temp
else temp
Definition: vf_mcdeint.c:256
http_get_file_handle
static int http_get_file_handle(URLContext *h)
Definition: http.c:1734
HTTP_SINGLE
#define HTTP_SINGLE
Definition: http.c:50
HTTPContext::is_akamai
int is_akamai
Definition: http.c:97
https
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
Definition: writing_filters.txt:66
av_gettime
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
av_dict_set_int
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
HTTPAuthType
HTTPAuthType
Authentication types, ordered from weakest to strongest.
Definition: httpauth.h:28
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:654
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
HTTPContext::reply_code
int reply_code
Definition: http.c:125
FINISH
@ FINISH
Definition: http.c:58
HTTPContext::auth_state
HTTPAuthState auth_state
Definition: http.c:72
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
AVDictionaryEntry
Definition: dict.h:81
ffurl_handshake
int ffurl_handshake(URLContext *c)
Perform one step of the protocol handshake to accept a new client.
Definition: avio.c:234
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:240
AVIO_FLAG_NONBLOCK
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition: avio.h:673
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
av_dict_set
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
av_dict_copy
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:217
http_getc
static int http_getc(HTTPContext *s)
Definition: http.c:588
http_accept
static int http_accept(URLContext *s, URLContext **c)
Definition: http.c:564
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:565
HTTPContext::send_expect_100
int send_expect_100
Definition: http.c:117
av_strlcpy
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
LOWER_PROTO
@ LOWER_PROTO
Definition: http.c:55
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
HTTPContext::chunksize
uint64_t chunksize
Definition: http.c:68
h
h
Definition: vp9dsp_template.c:2038
AVERROR_EXIT
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:56
HTTPContext::icy_metadata_headers
char * icy_metadata_headers
Definition: http.c:107
AVDictionaryEntry::value
char * value
Definition: dict.h:83
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:227
av_strndup
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:263
http.h
HTTPContext::willclose
int willclose
Definition: http.c:86
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:232
snprintf
#define snprintf
Definition: snprintf.h:34
HTTPContext::user_agent
char * user_agent
Definition: http.c:78
store_icy
static int store_icy(URLContext *h, int size)
Definition: http.c:1541
ffurl_get_file_handle
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:629
line
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:40
AV_DICT_DONT_STRDUP_KEY
#define AV_DICT_DONT_STRDUP_KEY
Take ownership of a key that's been allocated with av_malloc() or another memory allocation function.
Definition: dict.h:72
HTTPContext::post_data
uint8_t * post_data
Definition: http.c:95
AV_OPT_FLAG_DEPRECATED
#define AV_OPT_FLAG_DEPRECATED
set if option is deprecated, users should refer to AVOption.help text for more information
Definition: opt.h:292
HTTPContext::is_multi_client
int is_multi_client
Definition: http.c:126