FFmpeg
ftp.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Lukasz Marek <lukasz.m.luki@gmail.com>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <string.h>
22 
23 #include "libavutil/avstring.h"
24 #include "libavutil/internal.h"
25 #include "libavutil/parseutils.h"
26 #include "avformat.h"
27 #include "internal.h"
28 #include "url.h"
29 #include "urldecode.h"
30 #include "libavutil/opt.h"
31 #include "libavutil/bprint.h"
32 
33 #define CONTROL_BUFFER_SIZE 1024
34 #define DIR_BUFFER_SIZE 4096
35 
36 typedef enum {
44 } FTPState;
45 
46 typedef enum {
51 
52 typedef struct {
53  const AVClass *class;
54  URLContext *conn_control; /**< Control connection */
55  URLContext *conn_data; /**< Data connection, NULL when not connected */
56  uint8_t control_buffer[CONTROL_BUFFER_SIZE]; /**< Control connection buffer */
57  uint8_t *control_buf_ptr, *control_buf_end;
58  int server_data_port; /**< Data connection port opened by server, -1 on error. */
59  int server_control_port; /**< Control connection port, default is 21 */
60  char *hostname; /**< Server address. */
61  char *user; /**< Server user */
62  char *password; /**< Server user's password */
63  char *path; /**< Path to resource on server. */
64  int64_t filesize; /**< Size of file on server, -1 on error. */
65  int64_t position; /**< Current position, calculated. */
66  int rw_timeout; /**< Network timeout. */
67  const char *anonymous_password; /**< Password to be used for anonymous user. An email should be used. */
68  int write_seekable; /**< Control seekability, 0 = disable, 1 = enable. */
69  FTPState state; /**< State of data connection */
70  FTPListingMethod listing_method; /**< Called listing method */
71  char *features; /**< List of server's features represented as raw response */
72  char *dir_buffer;
75  int utf8;
76  const char *option_user; /**< User to be used if none given in the URL */
77  const char *option_password; /**< Password to be used if none given in the URL */
78 } FTPContext;
79 
80 #define OFFSET(x) offsetof(FTPContext, x)
81 #define D AV_OPT_FLAG_DECODING_PARAM
82 #define E AV_OPT_FLAG_ENCODING_PARAM
83 static const AVOption options[] = {
84  {"timeout", "set timeout of socket I/O operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D|E },
85  {"ftp-write-seekable", "control seekability of connection during encoding", OFFSET(write_seekable), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E },
86  {"ftp-anonymous-password", "password for anonymous login. E-mail address should be used.", OFFSET(anonymous_password), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E },
87  {"ftp-user", "user for FTP login. Overridden by whatever is in the URL.", OFFSET(option_user), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E },
88  {"ftp-password", "password for FTP login. Overridden by whatever is in the URL.", OFFSET(option_password), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E },
89  {NULL}
90 };
91 
92 static const AVClass ftp_context_class = {
93  .class_name = "ftp",
94  .item_name = av_default_item_name,
95  .option = options,
96  .version = LIBAVUTIL_VERSION_INT,
97 };
98 
99 static int ftp_close(URLContext *h);
100 
101 static int ftp_getc(FTPContext *s)
102 {
103  int len;
104  if (s->control_buf_ptr >= s->control_buf_end) {
106  if (len < 0) {
107  return len;
108  } else if (!len) {
109  return -1;
110  } else {
113  }
114  }
115  return *s->control_buf_ptr++;
116 }
117 
118 static int ftp_get_line(FTPContext *s, char *line, int line_size)
119 {
120  int ch;
121  char *q = line;
122 
123  for (;;) {
124  ch = ftp_getc(s);
125  if (ch < 0) {
126  return ch;
127  }
128  if (ch == '\n') {
129  /* process line */
130  if (q > line && q[-1] == '\r')
131  q--;
132  *q = '\0';
133  return 0;
134  } else {
135  if ((q - line) < line_size - 1)
136  *q++ = ch;
137  }
138  }
139 }
140 
141 /*
142  * This routine returns ftp server response code.
143  * Server may send more than one response for a certain command.
144  * First expected code is returned.
145  */
146 static int ftp_status(FTPContext *s, char **line, const int response_codes[])
147 {
148  int err, i, dash = 0, result = 0, code_found = 0, linesize;
149  char buf[CONTROL_BUFFER_SIZE];
150  AVBPrint line_buffer;
151 
152  if (line)
153  av_bprint_init(&line_buffer, 0, AV_BPRINT_SIZE_AUTOMATIC);
154 
155  while (!code_found || dash) {
156  if ((err = ftp_get_line(s, buf, sizeof(buf))) < 0) {
157  if (line)
158  av_bprint_finalize(&line_buffer, NULL);
159  return err;
160  }
161 
162  av_log(s, AV_LOG_DEBUG, "%s\n", buf);
163 
164  linesize = strlen(buf);
165  err = 0;
166  if (linesize >= 3) {
167  for (i = 0; i < 3; ++i) {
168  if (buf[i] < '0' || buf[i] > '9') {
169  err = 0;
170  break;
171  }
172  err *= 10;
173  err += buf[i] - '0';
174  }
175  }
176 
177  if (!code_found) {
178  if (err >= 500) {
179  code_found = 1;
180  result = err;
181  } else
182  for (i = 0; response_codes[i]; ++i) {
183  if (err == response_codes[i]) {
184  code_found = 1;
185  result = err;
186  break;
187  }
188  }
189  }
190  if (code_found) {
191  if (line)
192  av_bprintf(&line_buffer, "%s\r\n", buf);
193  if (linesize >= 4) {
194  if (!dash && buf[3] == '-')
195  dash = err;
196  else if (err == dash && buf[3] == ' ')
197  dash = 0;
198  }
199  }
200  }
201 
202  if (line)
203  av_bprint_finalize(&line_buffer, line);
204  return result;
205 }
206 
207 static int ftp_send_command(FTPContext *s, const char *command,
208  const int response_codes[], char **response)
209 {
210  int err;
211 
212  ff_dlog(s, "%s", command);
213 
214  if (response)
215  *response = NULL;
216 
217  if (!s->conn_control)
218  return AVERROR(EIO);
219 
220  if ((err = ffurl_write(s->conn_control, command, strlen(command))) < 0)
221  return err;
222  if (!err)
223  return -1;
224 
225  /* return status */
226  if (response_codes) {
227  return ftp_status(s, response, response_codes);
228  }
229  return 0;
230 }
231 
233 {
234  ffurl_closep(&s->conn_data);
235  s->state = DISCONNECTED;
236 }
237 
239 {
242 }
243 
244 static int ftp_auth(FTPContext *s)
245 {
246  char buf[CONTROL_BUFFER_SIZE];
247  int err;
248  static const int user_codes[] = {331, 230, 0};
249  static const int pass_codes[] = {230, 0};
250 
251  if (strpbrk(s->user, "\r\n"))
252  return AVERROR(EINVAL);
253  snprintf(buf, sizeof(buf), "USER %s\r\n", s->user);
254  err = ftp_send_command(s, buf, user_codes, NULL);
255  if (err == 331) {
256  if (s->password) {
257  if (strpbrk(s->password, "\r\n"))
258  return AVERROR(EINVAL);
259  snprintf(buf, sizeof(buf), "PASS %s\r\n", s->password);
260  err = ftp_send_command(s, buf, pass_codes, NULL);
261  } else
262  return AVERROR(EACCES);
263  }
264  if (err != 230)
265  return AVERROR(EACCES);
266 
267  return 0;
268 }
269 
271 {
272  char *res = NULL, *start = NULL, *end = NULL;
273  int i;
274  static const char d = '|';
275  static const char *command = "EPSV\r\n";
276  static const int epsv_codes[] = {229, 0};
277 
278  if (ftp_send_command(s, command, epsv_codes, &res) != 229 || !res)
279  goto fail;
280 
281  for (i = 0; res[i]; ++i) {
282  if (res[i] == '(') {
283  start = res + i + 1;
284  } else if (res[i] == ')') {
285  end = res + i;
286  break;
287  }
288  }
289  if (!start || !end)
290  goto fail;
291 
292  *end = '\0';
293  if (strlen(start) < 5)
294  goto fail;
295  if (start[0] != d || start[1] != d || start[2] != d || end[-1] != d)
296  goto fail;
297  start += 3;
298  end[-1] = '\0';
299 
300  s->server_data_port = atoi(start);
301  ff_dlog(s, "Server data port: %d\n", s->server_data_port);
302 
303  av_free(res);
304  return 0;
305 
306  fail:
307  av_free(res);
308  s->server_data_port = -1;
309  return AVERROR(ENOSYS);
310 }
311 
313 {
314  char *res = NULL, *start = NULL, *end = NULL;
315  int i;
316  static const char *command = "PASV\r\n";
317  static const int pasv_codes[] = {227, 0};
318 
319  if (ftp_send_command(s, command, pasv_codes, &res) != 227 || !res)
320  goto fail;
321 
322  for (i = 0; res[i]; ++i) {
323  if (res[i] == '(') {
324  start = res + i + 1;
325  } else if (res[i] == ')') {
326  end = res + i;
327  break;
328  }
329  }
330  if (!start || !end)
331  goto fail;
332 
333  *end = '\0';
334  /* skip ip */
335  if (!av_strtok(start, ",", &end)) goto fail;
336  if (!av_strtok(NULL, ",", &end)) goto fail;
337  if (!av_strtok(NULL, ",", &end)) goto fail;
338  if (!av_strtok(NULL, ",", &end)) goto fail;
339 
340  /* parse port number */
341  start = av_strtok(NULL, ",", &end);
342  if (!start) goto fail;
343  s->server_data_port = atoi(start) * 256;
344  start = av_strtok(NULL, ",", &end);
345  if (!start) goto fail;
346  s->server_data_port += atoi(start);
347  ff_dlog(s, "Server data port: %d\n", s->server_data_port);
348 
349  av_free(res);
350  return 0;
351 
352  fail:
353  av_free(res);
354  s->server_data_port = -1;
355  return AVERROR(EIO);
356 }
357 
359 {
360  char *res = NULL, *start = NULL, *end = NULL;
361  int i;
362  static const char *command = "PWD\r\n";
363  static const int pwd_codes[] = {257, 0};
364 
365  if (ftp_send_command(s, command, pwd_codes, &res) != 257 || !res)
366  goto fail;
367 
368  for (i = 0; res[i]; ++i) {
369  if (res[i] == '"') {
370  if (!start) {
371  start = res + i + 1;
372  continue;
373  }
374  end = res + i;
375  break;
376  }
377  }
378 
379  if (!end)
380  goto fail;
381 
382  *end = '\0';
383  s->path = av_strdup(start);
384 
385  av_free(res);
386 
387  if (!s->path)
388  return AVERROR(ENOMEM);
389  return 0;
390 
391  fail:
392  av_free(res);
393  return AVERROR(EIO);
394 }
395 
397 {
399  char *res = NULL;
400  static const int size_codes[] = {213, 0};
401 
402  snprintf(command, sizeof(command), "SIZE %s\r\n", s->path);
403  if (ftp_send_command(s, command, size_codes, &res) == 213 && res && strlen(res) > 4) {
404  s->filesize = strtoll(&res[4], NULL, 10);
405  } else {
406  s->filesize = -1;
407  av_free(res);
408  return AVERROR(EIO);
409  }
410 
411  av_free(res);
412  return 0;
413 }
414 
416 {
418  static const int retr_codes[] = {150, 125, 0};
419  int resp_code;
420 
421  snprintf(command, sizeof(command), "RETR %s\r\n", s->path);
422  resp_code = ftp_send_command(s, command, retr_codes, NULL);
423  if (resp_code != 125 && resp_code != 150)
424  return AVERROR(EIO);
425 
426  s->state = DOWNLOADING;
427 
428  return 0;
429 }
430 
431 static int ftp_store(FTPContext *s)
432 {
434  static const int stor_codes[] = {150, 125, 0};
435  int resp_code;
436 
437  snprintf(command, sizeof(command), "STOR %s\r\n", s->path);
438  resp_code = ftp_send_command(s, command, stor_codes, NULL);
439  if (resp_code != 125 && resp_code != 150)
440  return AVERROR(EIO);
441 
442  s->state = UPLOADING;
443 
444  return 0;
445 }
446 
447 static int ftp_type(FTPContext *s)
448 {
449  static const char *command = "TYPE I\r\n";
450  static const int type_codes[] = {200, 0};
451 
452  if (ftp_send_command(s, command, type_codes, NULL) != 200)
453  return AVERROR(EIO);
454 
455  return 0;
456 }
457 
458 static int ftp_restart(FTPContext *s, int64_t pos)
459 {
461  static const int rest_codes[] = {350, 0};
462 
463  snprintf(command, sizeof(command), "REST %"PRId64"\r\n", pos);
464  if (ftp_send_command(s, command, rest_codes, NULL) != 350)
465  return AVERROR(EIO);
466 
467  return 0;
468 }
469 
471 {
472  static const int cwd_codes[] = {250, 550, 0}; /* 550 is incorrect code */
473  char command[MAX_URL_SIZE];
474 
475  snprintf(command, sizeof(command), "CWD %s\r\n", s->path);
476  if (ftp_send_command(s, command, cwd_codes, NULL) != 250)
477  return AVERROR(EIO);
478  return 0;
479 }
480 
482 {
483  static const char *command = "MLSD\r\n";
484  static const int mlsd_codes[] = {150, 500, 0}; /* 500 is incorrect code */
485 
486  if (ftp_send_command(s, command, mlsd_codes, NULL) != 150)
487  return AVERROR(ENOSYS);
488  s->listing_method = MLSD;
489  return 0;
490 }
491 
493 {
494  static const char *command = "NLST\r\n";
495  static const int nlst_codes[] = {226, 425, 426, 451, 450, 550, 0};
496 
497  if (ftp_send_command(s, command, nlst_codes, NULL) != 226)
498  return AVERROR(ENOSYS);
499  s->listing_method = NLST;
500  return 0;
501 }
502 
503 static int ftp_list(FTPContext *s)
504 {
505  int ret;
506  s->state = LISTING_DIR;
507 
508  if ((ret = ftp_list_mlsd(s)) < 0)
509  ret = ftp_list_nlst(s);
510 
511  return ret;
512 }
513 
514 static int ftp_has_feature(FTPContext *s, const char *feature_name)
515 {
516  if (!s->features)
517  return 0;
518 
519  return av_stristr(s->features, feature_name) != NULL;
520 }
521 
523 {
524  static const char *feat_command = "FEAT\r\n";
525  static const char *enable_utf8_command = "OPTS UTF8 ON\r\n";
526  static const int feat_codes[] = {211, 0};
527  static const int opts_codes[] = {200, 202, 451, 0};
528 
529  av_freep(&s->features);
530  if (ftp_send_command(s, feat_command, feat_codes, &s->features) != 211) {
531  av_freep(&s->features);
532  }
533 
534  if (ftp_has_feature(s, "UTF8")) {
535  int ret = ftp_send_command(s, enable_utf8_command, opts_codes, NULL);
536  if (ret == 200 || ret == 202)
537  s->utf8 = 1;
538  }
539 
540  return 0;
541 }
542 
544 {
545  char buf[CONTROL_BUFFER_SIZE], *response = NULL;
546  int err;
548  FTPContext *s = h->priv_data;
549  static const int connect_codes[] = {220, 0};
550 
551  if (!s->conn_control) {
552  ff_url_join(buf, sizeof(buf), "tcp", NULL,
554  if (s->rw_timeout != -1) {
555  av_dict_set_int(&opts, "timeout", s->rw_timeout, 0);
556  } /* if option is not given, don't pass it and let tcp use its own default */
558  &h->interrupt_callback, &opts,
560  av_dict_free(&opts);
561  if (err < 0) {
562  av_log(h, AV_LOG_ERROR, "Cannot open control connection\n");
563  return err;
564  }
565 
566  /* check if server is ready */
567  if (ftp_status(s, ((h->flags & AVIO_FLAG_WRITE) ? &response : NULL), connect_codes) != 220) {
568  av_log(h, AV_LOG_ERROR, "FTP server not ready for new users\n");
569  return AVERROR(EACCES);
570  }
571 
572  if ((h->flags & AVIO_FLAG_WRITE) && av_stristr(response, "pure-ftpd")) {
573  av_log(h, AV_LOG_WARNING, "Pure-FTPd server is used as an output protocol. It is known issue this implementation may produce incorrect content and it cannot be fixed at this moment.");
574  }
575  av_free(response);
576 
577  if ((err = ftp_auth(s)) < 0) {
578  av_log(h, AV_LOG_ERROR, "FTP authentication failed\n");
579  return err;
580  }
581 
582  if ((err = ftp_type(s)) < 0) {
583  av_log(h, AV_LOG_ERROR, "Set content type failed\n");
584  return err;
585  }
586 
587  ftp_features(s);
588  }
589  return 0;
590 }
591 
593 {
594  int err;
595  char buf[CONTROL_BUFFER_SIZE];
597  FTPContext *s = h->priv_data;
598 
599  if (!s->conn_data) {
600  /* Enter passive mode */
601  if (ftp_passive_mode_epsv(s) < 0) {
602  /* Use PASV as fallback */
603  if ((err = ftp_passive_mode(s)) < 0)
604  return err;
605  }
606  /* Open data connection */
607  ff_url_join(buf, sizeof(buf), "tcp", NULL, s->hostname, s->server_data_port, NULL);
608  if (s->rw_timeout != -1) {
609  av_dict_set_int(&opts, "timeout", s->rw_timeout, 0);
610  } /* if option is not given, don't pass it and let tcp use its own default */
611  err = ffurl_open_whitelist(&s->conn_data, buf, h->flags,
612  &h->interrupt_callback, &opts,
614  av_dict_free(&opts);
615  if (err < 0)
616  return err;
617 
618  if (s->position)
619  if ((err = ftp_restart(s, s->position)) < 0)
620  return err;
621  }
622  s->state = READY;
623  return 0;
624 }
625 
626 static int ftp_abort(URLContext *h)
627 {
628  static const char *command = "ABOR\r\n";
629  int err;
630  static const int abor_codes[] = {225, 226, 0};
631  FTPContext *s = h->priv_data;
632 
633  /* According to RCF 959:
634  "ABOR command tells the server to abort the previous FTP
635  service command and any associated transfer of data."
636 
637  There are FTP server implementations that don't response
638  to any commands during data transfer in passive mode (including ABOR).
639 
640  This implementation closes data connection by force.
641  */
642 
643  if (ftp_send_command(s, command, NULL, NULL) < 0) {
645  if ((err = ftp_connect_control_connection(h)) < 0) {
646  av_log(h, AV_LOG_ERROR, "Reconnect failed.\n");
647  return err;
648  }
649  } else {
651  if (ftp_status(s, NULL, abor_codes) < 225) {
652  /* wu-ftpd also closes control connection after data connection closing */
654  if ((err = ftp_connect_control_connection(h)) < 0) {
655  av_log(h, AV_LOG_ERROR, "Reconnect failed.\n");
656  return err;
657  }
658  }
659  }
660 
661  return 0;
662 }
663 
664 static int ftp_connect(URLContext *h, const char *url)
665 {
666  char proto[10], path[MAX_URL_SIZE], credentials[MAX_URL_SIZE], hostname[MAX_URL_SIZE];
667  const char *tok_user = NULL, *tok_pass = NULL;
668  char *newpath = NULL;
669  int err;
670  FTPContext *s = h->priv_data;
671 
672  s->state = DISCONNECTED;
674  s->filesize = -1;
675  s->position = 0;
676  s->features = NULL;
677 
678  av_url_split(proto, sizeof(proto),
679  credentials, sizeof(credentials),
680  hostname, sizeof(hostname),
682  path, sizeof(path),
683  url);
684 
685  if (!*credentials) {
686  if (!s->option_user) {
687  tok_user = "anonymous";
688  tok_pass = av_x_if_null(s->anonymous_password, "nopassword");
689  } else {
690  tok_user = s->option_user;
691  tok_pass = s->option_password;
692  }
693  s->user = av_strdup(tok_user);
694  s->password = av_strdup(tok_pass);
695  } else {
696  char *pass = strchr(credentials, ':');
697  if (pass) {
698  *pass++ = '\0';
699  tok_pass = pass;
700  s->password = ff_urldecode(pass, 0);
701  } else {
702  tok_pass = s->option_password;
703  s->password = av_strdup(tok_pass);
704  }
705  s->user = ff_urldecode(credentials, 0);
706  }
707  s->hostname = av_strdup(hostname);
708  if (!s->hostname || !s->user || (tok_pass && !s->password)) {
709  return AVERROR(ENOMEM);
710  }
711 
712  if (s->server_control_port < 0 || s->server_control_port > 65535)
713  s->server_control_port = 21;
714 
715  if ((err = ftp_connect_control_connection(h)) < 0)
716  return err;
717 
718  if ((err = ftp_current_dir(s)) < 0)
719  return err;
720 
721  newpath = av_append_path_component(s->path, path);
722  if (!newpath)
723  return AVERROR(ENOMEM);
724  av_free(s->path);
725  s->path = newpath;
726 
727  return 0;
728 }
729 
730 static int ftp_open(URLContext *h, const char *url, int flags)
731 {
732  FTPContext *s = h->priv_data;
733  int err;
734 
735  ff_dlog(h, "ftp protocol open\n");
736 
737  if ((err = ftp_connect(h, url)) < 0)
738  goto fail;
739 
740  if (ftp_restart(s, 0) < 0) {
741  h->is_streamed = 1;
742  } else {
743  ftp_file_size(s);
744  if (s->write_seekable != 1 && flags & AVIO_FLAG_WRITE)
745  h->is_streamed = 1;
746  }
747 
748  return 0;
749 
750  fail:
751  av_log(h, AV_LOG_ERROR, "FTP open failed\n");
752  ftp_close(h);
753  return err;
754 }
755 
756 static int64_t ftp_seek(URLContext *h, int64_t pos, int whence)
757 {
758  FTPContext *s = h->priv_data;
759  int err;
760  int64_t new_pos;
761 
762  ff_dlog(h, "ftp protocol seek %"PRId64" %d\n", pos, whence);
763 
764  switch(whence) {
765  case AVSEEK_SIZE:
766  return s->filesize;
767  case SEEK_SET:
768  new_pos = pos;
769  break;
770  case SEEK_CUR:
771  new_pos = s->position + pos;
772  break;
773  case SEEK_END:
774  if (s->filesize < 0)
775  return AVERROR(EIO);
776  new_pos = s->filesize + pos;
777  break;
778  default:
779  return AVERROR(EINVAL);
780  }
781 
782  if (h->is_streamed)
783  return AVERROR(EIO);
784 
785  if (new_pos < 0) {
786  av_log(h, AV_LOG_ERROR, "Seeking to nagative position.\n");
787  return AVERROR(EINVAL);
788  }
789 
790  if (new_pos != s->position) {
791  if ((err = ftp_abort(h)) < 0)
792  return err;
793  s->position = new_pos;
794  }
795  return new_pos;
796 }
797 
798 static int ftp_read(URLContext *h, unsigned char *buf, int size)
799 {
800  FTPContext *s = h->priv_data;
801  int read, err, retry_done = 0;
802 
803  ff_dlog(h, "ftp protocol read %d bytes\n", size);
804  retry:
805  if (s->state == ENDOFFILE)
806  return AVERROR_EOF;
807  if (s->state == DISCONNECTED) {
808  if ((err = ftp_connect_data_connection(h)) < 0)
809  return err;
810  }
811  if (s->state == READY) {
812  if ((err = ftp_retrieve(s)) < 0)
813  return err;
814  }
815  if (s->conn_data && s->state == DOWNLOADING) {
816  read = ffurl_read(s->conn_data, buf, size);
817  if (read >= 0) {
818  s->position += read;
819  s->filesize = FFMAX(s->filesize, s->position);
820  }
821  if (read == AVERROR_EOF) {
822  static const int retr_codes[] = {226, 250, 425, 426, 451, 0};
823  char *response = NULL;
824  err = ftp_status(s, &response, retr_codes);
825  if (err == 226) {
827  av_freep(&response);
828  s->state = ENDOFFILE;
829  return AVERROR_EOF;
830  }
831  /* 250 is not allowed, any other status means some kind of error */
832  av_log(h, AV_LOG_ERROR, "FTP transfer failed: %s\n", response ? response : (err < 0 ? av_err2str(err) : "?"));
833  av_freep(&response);
834  read = AVERROR(EIO);
835  }
836  if (read <= 0 && !h->is_streamed) {
837  /* Server closed connection. Probably due to inactivity */
838  av_log(h, AV_LOG_INFO, "Reconnect to FTP server.\n");
839  if ((err = ftp_abort(h)) < 0)
840  return err;
841  if (!retry_done) {
842  retry_done = 1;
843  goto retry;
844  }
845  }
846  return read;
847  }
848 
849  av_log(h, AV_LOG_DEBUG, "FTP read failed\n");
850  return AVERROR(EIO);
851 }
852 
853 static int ftp_write(URLContext *h, const unsigned char *buf, int size)
854 {
855  int err;
856  FTPContext *s = h->priv_data;
857  int written;
858 
859  ff_dlog(h, "ftp protocol write %d bytes\n", size);
860 
861  if (s->state == DISCONNECTED) {
862  if ((err = ftp_connect_data_connection(h)) < 0)
863  return err;
864  }
865  if (s->state == READY) {
866  if ((err = ftp_store(s)) < 0)
867  return err;
868  }
869  if (s->conn_data && s->state == UPLOADING) {
870  written = ffurl_write(s->conn_data, buf, size);
871  if (written > 0) {
872  s->position += written;
873  s->filesize = FFMAX(s->filesize, s->position);
874  }
875  return written;
876  }
877 
878  av_log(h, AV_LOG_ERROR, "FTP write failed\n");
879  return AVERROR(EIO);
880 }
881 
882 static int ftp_close(URLContext *h)
883 {
884  FTPContext *s = h->priv_data;
885 
886  ff_dlog(h, "ftp protocol close\n");
887 
889  av_freep(&s->user);
890  av_freep(&s->password);
891  av_freep(&s->hostname);
892  av_freep(&s->path);
893  av_freep(&s->features);
894 
895  return 0;
896 }
897 
899 {
900  FTPContext *s = h->priv_data;
901 
902  ff_dlog(h, "ftp protocol get_file_handle\n");
903 
904  if (s->conn_data)
905  return ffurl_get_file_handle(s->conn_data);
906 
907  return AVERROR(EIO);
908 }
909 
910 static int ftp_shutdown(URLContext *h, int flags)
911 {
912  FTPContext *s = h->priv_data;
913 
914  ff_dlog(h, "ftp protocol shutdown\n");
915 
916  if (s->conn_data)
917  return ffurl_shutdown(s->conn_data, flags);
918 
919  return AVERROR(EIO);
920 }
921 
922 static int ftp_open_dir(URLContext *h)
923 {
924  FTPContext *s = h->priv_data;
925  int ret;
926 
927  if ((ret = ftp_connect(h, h->filename)) < 0)
928  goto fail;
929  if ((ret = ftp_set_dir(s)) < 0)
930  goto fail;
931  if ((ret = ftp_connect_data_connection(h)) < 0)
932  goto fail;
933  if ((ret = ftp_list(s)) < 0)
934  goto fail;
936  if (!s->dir_buffer) {
937  ret = AVERROR(ENOMEM);
938  goto fail;
939  }
940  s->dir_buffer[0] = 0;
941  if (s->conn_data && s->state == LISTING_DIR)
942  return 0;
943  fail:
945  ffurl_closep(&s->conn_data);
946  return ret;
947 }
948 
949 static int64_t ftp_parse_date(const char *date)
950 {
951  struct tm tv;
952  memset(&tv, 0, sizeof(struct tm));
953  av_small_strptime(date, "%Y%m%d%H%M%S", &tv);
954  return INT64_C(1000000) * av_timegm(&tv);
955 }
956 
957 static int ftp_parse_entry_nlst(char *line, AVIODirEntry *next)
958 {
959  next->name = av_strdup(line);
960  return 0;
961 }
962 
963 static int ftp_parse_entry_mlsd(char *mlsd, AVIODirEntry *next)
964 {
965  char *fact, *value;
966  char *saveptr = NULL, *p = mlsd;
967  ff_dlog(NULL, "%s\n", mlsd);
968  while(fact = av_strtok(p, ";", &saveptr)) {
969  p = NULL;
970  if (fact[0] == ' ') {
971  next->name = av_strdup(&fact[1]);
972  continue;
973  }
974  fact = av_strtok(fact, "=", &value);
975  if (!av_strcasecmp(fact, "type")) {
976  if (!av_strcasecmp(value, "cdir") || !av_strcasecmp(value, "pdir"))
977  return 1;
978  if (!av_strcasecmp(value, "dir"))
979  next->type = AVIO_ENTRY_DIRECTORY;
980  else if (!av_strcasecmp(value, "file"))
981  next->type = AVIO_ENTRY_FILE;
982  else if (!av_strcasecmp(value, "OS.unix=slink:"))
984  } else if (!av_strcasecmp(fact, "modify")) {
985  next->modification_timestamp = ftp_parse_date(value);
986  } else if (!av_strcasecmp(fact, "UNIX.mode")) {
987  next->filemode = strtoumax(value, NULL, 8);
988  } else if (!av_strcasecmp(fact, "UNIX.uid") || !av_strcasecmp(fact, "UNIX.owner"))
989  next->user_id = strtoumax(value, NULL, 10);
990  else if (!av_strcasecmp(fact, "UNIX.gid") || !av_strcasecmp(fact, "UNIX.group"))
991  next->group_id = strtoumax(value, NULL, 10);
992  else if (!av_strcasecmp(fact, "size") || !av_strcasecmp(fact, "sizd"))
993  next->size = strtoll(value, NULL, 10);
994  }
995  return 0;
996 }
997 
998 /**
999  * @return 0 on success, negative on error, positive on entry to discard.
1000  */
1001 static int ftp_parse_entry(URLContext *h, char *line, AVIODirEntry *next)
1002 {
1003  FTPContext *s = h->priv_data;
1004 
1005  switch (s->listing_method) {
1006  case MLSD:
1007  return ftp_parse_entry_mlsd(line, next);
1008  case NLST:
1009  return ftp_parse_entry_nlst(line, next);
1010  case UNKNOWN_METHOD:
1011  default:
1012  return -1;
1013  }
1014 }
1015 
1016 static int ftp_read_dir(URLContext *h, AVIODirEntry **next)
1017 {
1018  FTPContext *s = h->priv_data;
1019  char *start, *found;
1020  int ret, retried;
1021 
1022  do {
1023  retried = 0;
1024  start = s->dir_buffer + s->dir_buffer_offset;
1025  while (!(found = strstr(start, "\n"))) {
1026  if (retried)
1027  return AVERROR(EIO);
1029  s->dir_buffer_offset = 0;
1030  if (s->dir_buffer_size)
1031  memmove(s->dir_buffer, start, s->dir_buffer_size);
1033  if (ret < 0)
1034  return ret;
1035  if (!ret) {
1036  *next = NULL;
1037  return 0;
1038  }
1039  s->dir_buffer_size += ret;
1040  s->dir_buffer[s->dir_buffer_size] = 0;
1041  start = s->dir_buffer;
1042  retried = 1;
1043  }
1044  s->dir_buffer_offset += (found + 1 - start);
1045  found[0] = 0;
1046  if (found > start && found[-1] == '\r')
1047  found[-1] = 0;
1048 
1049  *next = ff_alloc_dir_entry();
1050  if (!*next)
1051  return AVERROR(ENOMEM);
1052  (*next)->utf8 = s->utf8;
1053  ret = ftp_parse_entry(h, start, *next);
1054  if (ret) {
1056  if (ret < 0)
1057  return ret;
1058  }
1059  } while (ret > 0);
1060  return 0;
1061 }
1062 
1064 {
1065  FTPContext *s = h->priv_data;
1066  av_freep(&s->dir_buffer);
1068  ffurl_closep(&s->conn_data);
1069  return 0;
1070 }
1071 
1072 static int ftp_delete(URLContext *h)
1073 {
1074  FTPContext *s = h->priv_data;
1075  char command[MAX_URL_SIZE];
1076  static const int del_codes[] = {250, 421, 450, 500, 501, 502, 530, 550, 0};
1077  static const int rmd_codes[] = {250, 421, 500, 501, 502, 530, 550, 0};
1078  int ret;
1079 
1080  if ((ret = ftp_connect(h, h->filename)) < 0)
1081  goto cleanup;
1082 
1083  snprintf(command, sizeof(command), "DELE %s\r\n", s->path);
1084  if (ftp_send_command(s, command, del_codes, NULL) == 250) {
1085  ret = 0;
1086  goto cleanup;
1087  }
1088 
1089  snprintf(command, sizeof(command), "RMD %s\r\n", s->path);
1090  if (ftp_send_command(s, command, rmd_codes, NULL) == 250)
1091  ret = 0;
1092  else
1093  ret = AVERROR(EIO);
1094 
1095 cleanup:
1096  ftp_close(h);
1097  return ret;
1098 }
1099 
1100 static int ftp_move(URLContext *h_src, URLContext *h_dst)
1101 {
1102  FTPContext *s = h_src->priv_data;
1103  char command[MAX_URL_SIZE], path[MAX_URL_SIZE];
1104  static const int rnfr_codes[] = {350, 421, 450, 500, 501, 502, 503, 530, 0};
1105  static const int rnto_codes[] = {250, 421, 500, 501, 502, 503, 530, 532, 553, 0};
1106  int ret;
1107 
1108  if ((ret = ftp_connect(h_src, h_src->filename)) < 0)
1109  goto cleanup;
1110 
1111  snprintf(command, sizeof(command), "RNFR %s\r\n", s->path);
1112  if (ftp_send_command(s, command, rnfr_codes, NULL) != 350) {
1113  ret = AVERROR(EIO);
1114  goto cleanup;
1115  }
1116 
1117  av_url_split(0, 0, 0, 0, 0, 0, 0,
1118  path, sizeof(path),
1119  h_dst->filename);
1120  snprintf(command, sizeof(command), "RNTO %s\r\n", path);
1121  if (ftp_send_command(s, command, rnto_codes, NULL) == 250)
1122  ret = 0;
1123  else
1124  ret = AVERROR(EIO);
1125 
1126 cleanup:
1127  ftp_close(h_src);
1128  return ret;
1129 }
1130 
1132  .name = "ftp",
1133  .url_open = ftp_open,
1134  .url_read = ftp_read,
1135  .url_write = ftp_write,
1136  .url_seek = ftp_seek,
1137  .url_close = ftp_close,
1138  .url_get_file_handle = ftp_get_file_handle,
1139  .url_shutdown = ftp_shutdown,
1140  .priv_data_size = sizeof(FTPContext),
1141  .priv_data_class = &ftp_context_class,
1142  .url_open_dir = ftp_open_dir,
1143  .url_read_dir = ftp_read_dir,
1144  .url_close_dir = ftp_close_dir,
1145  .url_delete = ftp_delete,
1146  .url_move = ftp_move,
1148  .default_whitelist = "tcp",
1149 };
time_t av_timegm(struct tm *tm)
Convert the decomposed UTC time in tm to a time_t value.
Definition: parseutils.c:568
const URLProtocol ff_ftp_protocol
Definition: ftp.c:1131
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:4792
#define NULL
Definition: coverity.c:32
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:94
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:310
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:34
static int ftp_get_line(FTPContext *s, char *line, int line_size)
Definition: ftp.c:118
char * password
Server user&#39;s password.
Definition: ftp.c:62
AVOption.
Definition: opt.h:248
int64_t filemode
Unix file mode, -1 if unknown.
Definition: avio.h:100
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
static int ftp_list(FTPContext *s)
Definition: ftp.c:503
static int ftp_move(URLContext *h_src, URLContext *h_dst)
Definition: ftp.c:1100
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
static int ftp_file_size(FTPContext *s)
Definition: ftp.c:396
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:423
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle...
Definition: avstring.c:56
int is_streamed
true if streamed (no seek possible), default = false
Definition: url.h:45
AVIOInterruptCB interrupt_callback
Definition: url.h:47
Describes single entry of the directory.
Definition: avio.h:86
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
static int ftp_connect(URLContext *h, const char *url)
Definition: ftp.c:664
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:675
static int ftp_open(URLContext *h, const char *url, int flags)
Definition: ftp.c:730
uint8_t * control_buf_end
Definition: ftp.c:57
size_t dir_buffer_size
Definition: ftp.c:73
const char * option_password
Password to be used if none given in the URL.
Definition: ftp.c:77
int flags
Definition: url.h:43
static int ftp_status(FTPContext *s, char **line, const int response_codes[])
Definition: ftp.c:146
int write_seekable
Control seekability, 0 = disable, 1 = enable.
Definition: ftp.c:68
static int ftp_retrieve(FTPContext *s)
Definition: ftp.c:415
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
int ffurl_shutdown(URLContext *h, int flags)
Signal the URLContext that we are done reading or writing the stream.
Definition: avio.c:659
Definition: ftp.c:37
Definition: ftp.c:40
#define MAX_URL_SIZE
Definition: internal.h:30
int64_t modification_timestamp
Time of last modification in microseconds since unix epoch, -1 if unknown.
Definition: avio.h:92
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
URLContext * conn_control
Control connection.
Definition: ftp.c:54
static int ftp_read_dir(URLContext *h, AVIODirEntry **next)
Definition: ftp.c:1016
static int ftp_connect_data_connection(URLContext *h)
Definition: ftp.c:592
uint8_t
#define av_malloc(s)
static int ftp_set_dir(FTPContext *s)
Definition: ftp.c:470
static int ftp_shutdown(URLContext *h, int flags)
Definition: ftp.c:910
AVOptions.
FTPState
Definition: ftp.c:36
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
#define E
Definition: ftp.c:82
GLsizei GLboolean const GLfloat * value
Definition: opengl_enc.c:108
int64_t filesize
Size of file on server, -1 on error.
Definition: ftp.c:64
char * av_small_strptime(const char *p, const char *fmt, struct tm *dt)
Simplified version of strptime.
Definition: parseutils.c:489
static int ftp_delete(URLContext *h)
Definition: ftp.c:1072
Definition: ftp.c:43
static int ftp_connect_control_connection(URLContext *h)
Definition: ftp.c:543
#define ff_dlog(a,...)
#define DIR_BUFFER_SIZE
Definition: ftp.c:34
#define AVERROR_EOF
End of file.
Definition: error.h:55
uint8_t control_buffer[CONTROL_BUFFER_SIZE]
Control connection buffer.
Definition: ftp.c:56
ptrdiff_t size
Definition: opengl_enc.c:100
static int ftp_current_dir(FTPContext *s)
Definition: ftp.c:358
FTPListingMethod
Definition: ftp.c:46
uint8_t * control_buf_ptr
Definition: ftp.c:57
#define av_log(a,...)
static int ftp_passive_mode(FTPContext *s)
Definition: ftp.c:312
int server_data_port
Data connection port opened by server, -1 on error.
Definition: ftp.c:58
FTPListingMethod listing_method
Called listing method.
Definition: ftp.c:70
char * ff_urldecode(const char *url, int decode_plus_sign)
Decodes an URL from its percent-encoded form back into normal representation.
Definition: urldecode.c:35
static void * av_x_if_null(const void *p, const void *x)
Return x default pointer in case p is NULL.
Definition: avutil.h:308
char * name
Filename.
Definition: avio.h:87
static int ftp_getc(FTPContext *s)
Definition: ftp.c:101
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
Definition: ftp.c:49
const char * anonymous_password
Password to be used for anonymous user.
Definition: ftp.c:67
const char * protocol_whitelist
Definition: url.h:49
static int ftp_abort(URLContext *h)
Definition: ftp.c:626
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
const char * option_user
User to be used if none given in the URL.
Definition: ftp.c:76
unsigned int pos
Definition: spdifenc.c:410
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:203
Definition: graph2dot.c:48
size_t dir_buffer_offset
Definition: ftp.c:74
Definition: ftp.c:38
static int ftp_send_command(FTPContext *s, const char *command, const int response_codes[], char **response)
Definition: ftp.c:207
static void ftp_close_both_connections(FTPContext *s)
Definition: ftp.c:238
static int ftp_passive_mode_epsv(FTPContext *s)
Definition: ftp.c:270
#define FFMAX(a, b)
Definition: common.h:94
#define fail()
Definition: checkasm.h:123
void avio_free_directory_entry(AVIODirEntry **entry)
Free entry allocated by avio_read_dir().
Definition: avio.c:605
#define pass
Definition: fft_template.c:619
int rw_timeout
Network timeout.
Definition: ftp.c:66
common internal API header
static int ftp_parse_entry_nlst(char *line, AVIODirEntry *next)
Definition: ftp.c:957
AVDictionary * opts
Definition: movenc.c:50
static int ftp_read(URLContext *h, unsigned char *buf, int size)
Definition: ftp.c:798
static int ftp_close(URLContext *h)
Definition: ftp.c:882
URLContext * conn_data
Data connection, NULL when not connected.
Definition: ftp.c:55
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
char * user
Server user.
Definition: ftp.c:61
static int ftp_auth(FTPContext *s)
Definition: ftp.c:244
int64_t position
Current position, calculated.
Definition: ftp.c:65
static int ftp_restart(FTPContext *s, int64_t pos)
Definition: ftp.c:458
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:119
char * features
List of server&#39;s features represented as raw response.
Definition: ftp.c:71
static int ftp_has_feature(FTPContext *s, const char *feature_name)
Definition: ftp.c:514
#define s(width, name)
Definition: cbs_vp9.c:257
char * path
Path to resource on server.
Definition: ftp.c:63
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition: avio.c:628
int64_t size
File size in bytes, -1 if unknown.
Definition: avio.h:91
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition: avio.c:446
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:37
static int64_t ftp_seek(URLContext *h, int64_t pos, int whence)
Definition: ftp.c:756
#define AV_LOG_INFO
Standard information.
Definition: log.h:205
#define AV_BPRINT_SIZE_AUTOMATIC
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:253
const char * protocol_blacklist
Definition: url.h:50
static int ftp_close_dir(URLContext *h)
Definition: ftp.c:1063
int type
Type of the entry.
Definition: avio.h:88
static int ftp_get_file_handle(URLContext *h)
Definition: ftp.c:898
static int command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Definition: vf_drawtext.c:871
static const AVOption options[]
Definition: ftp.c:83
Definition: url.h:38
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
Definition: avio.h:676
FTPState state
State of data connection.
Definition: ftp.c:69
Describe the class of an AVClass context structure.
Definition: log.h:67
int64_t group_id
Group ID of owner, -1 if unknown.
Definition: avio.h:99
static void ftp_close_data_connection(FTPContext *s)
Definition: ftp.c:232
static int ftp_features(FTPContext *s)
Definition: ftp.c:522
void * priv_data
Definition: url.h:41
static int ftp_parse_entry_mlsd(char *mlsd, AVIODirEntry *next)
Definition: ftp.c:963
#define snprintf
Definition: snprintf.h:34
#define CONTROL_BUFFER_SIZE
Definition: ftp.c:33
misc parsing utilities
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(const uint8_t *) pi-0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(const int16_t *) pi >>8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(const int16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(const int32_t *) pi >>24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(const int32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(const int64_t *) pi >>56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64,*(const int64_t *) pi *(1.0f/(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64,*(const int64_t *) pi *(1.0/(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(const float *) pi *(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(const double *) pi *(UINT64_C(1)<< 63)))#define FMT_PAIR_FUNC(out, in) static conv_func_type *const fmt_pair_to_conv_functions[AV_SAMPLE_FMT_NB *AV_SAMPLE_FMT_NB]={FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64),};static void cpy1(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, len);}static void cpy2(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 2 *len);}static void cpy4(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 4 *len);}static void cpy8(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 8 *len);}AudioConvert *swri_audio_convert_alloc(enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, const int *ch_map, int flags){AudioConvert *ctx;conv_func_type *f=fmt_pair_to_conv_functions[av_get_packed_sample_fmt(out_fmt)+AV_SAMPLE_FMT_NB *av_get_packed_sample_fmt(in_fmt)];if(!f) return NULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) return NULL;if(channels==1){in_fmt=av_get_planar_sample_fmt(in_fmt);out_fmt=av_get_planar_sample_fmt(out_fmt);}ctx->channels=channels;ctx->conv_f=f;ctx->ch_map=ch_map;if(in_fmt==AV_SAMPLE_FMT_U8||in_fmt==AV_SAMPLE_FMT_U8P) memset(ctx->silence, 0x80, sizeof(ctx->silence));if(out_fmt==in_fmt &&!ch_map){switch(av_get_bytes_per_sample(in_fmt)){case 1:ctx->simd_f=cpy1;break;case 2:ctx->simd_f=cpy2;break;case 4:ctx->simd_f=cpy4;break;case 8:ctx->simd_f=cpy8;break;}}if(HAVE_X86ASM &&1) swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels);if(ARCH_ARM) swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);if(ARCH_AARCH64) swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels);return ctx;}void swri_audio_convert_free(AudioConvert **ctx){av_freep(ctx);}int swri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, int len){int ch;int off=0;const int os=(out->planar?1:out->ch_count)*out->bps;unsigned misaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask){int planes=in->planar?in->ch_count:1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) in->ch[ch];misaligned|=m &ctx->in_simd_align_mask;}if(ctx->out_simd_align_mask){int planes=out->planar?out->ch_count:1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) out->ch[ch];misaligned|=m &ctx->out_simd_align_mask;}if(ctx->simd_f &&!ctx->ch_map &&!misaligned){off=len &~15;av_assert1(off >=0);av_assert1(off<=len);av_assert2(ctx->channels==SWR_CH_MAX||!in->ch[ctx->channels]);if(off >0){if(out->planar==in->planar){int planes=out->planar?out->ch_count:1;for(ch=0;ch< planes;ch++){ctx->simd_f(out-> ch ch
Definition: audioconvert.c:56
const char * name
Definition: url.h:55
#define flags(name, subs,...)
Definition: cbs_av1.c:560
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
Definition: ftp.c:48
Main libavformat public API header.
static int ftp_write(URLContext *h, const unsigned char *buf, int size)
Definition: ftp.c:853
char * av_append_path_component(const char *path, const char *component)
Append path component to the existing path.
Definition: avstring.c:302
The official guide to swscale for confused that consecutive non overlapping rectangles of slice_bottom special converter These generally are unscaled converters of common like for each output line the vertical scaler pulls lines from a ring buffer When the ring buffer does not contain the wanted line
Definition: swscale.txt:33
int utf8
Definition: ftp.c:75
#define OFFSET(x)
Definition: ftp.c:80
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
char * dir_buffer
Definition: ftp.c:72
AVIODirEntry * ff_alloc_dir_entry(void)
Allocate directory entry with default values.
Definition: url.c:223
char * filename
specified URL
Definition: url.h:42
#define AVSEEK_SIZE
ORing this as the "whence" parameter to a seek function causes it to return the filesize without seek...
Definition: avio.h:531
char * hostname
Server address.
Definition: ftp.c:60
static int ftp_store(FTPContext *s)
Definition: ftp.c:431
static int ftp_type(FTPContext *s)
Definition: ftp.c:447
#define D
Definition: ftp.c:81
#define av_free(p)
static int ftp_open_dir(URLContext *h)
Definition: ftp.c:922
int len
int server_control_port
Control connection port, default is 21.
Definition: ftp.c:59
int64_t user_id
User ID of owner, -1 if unknown.
Definition: avio.h:98
static int ftp_list_mlsd(FTPContext *s)
Definition: ftp.c:481
and forward the result(frame or status change) to the corresponding input.If nothing is possible
static const AVClass ftp_context_class
Definition: ftp.c:92
#define av_freep(p)
unbuffered private I/O API
static int64_t ftp_parse_date(const char *date)
Definition: ftp.c:949
Definition: ftp.c:52
static int ftp_parse_entry(URLContext *h, char *line, AVIODirEntry *next)
Definition: ftp.c:1001
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
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:409
int i
Definition: input.c:406
static av_cold void cleanup(FlashSV2Context *s)
Definition: flashsv2enc.c:127
static int ftp_list_nlst(FTPContext *s)
Definition: ftp.c:492