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