FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ffserver.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
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 /**
22  * @file
23  * multiple format streaming server based on the FFmpeg libraries
24  */
25 
26 #include "config.h"
27 #if !HAVE_CLOSESOCKET
28 #define closesocket close
29 #endif
30 #include <string.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include "libavformat/avformat.h"
34 /* FIXME: those are internal headers, ffserver _really_ shouldn't use them */
35 #include "libavformat/rtpproto.h"
36 #include "libavformat/rtsp.h"
38 #include "libavformat/internal.h"
39 
40 #include "libavutil/avassert.h"
41 #include "libavutil/avstring.h"
42 #include "libavutil/lfg.h"
43 #include "libavutil/dict.h"
44 #include "libavutil/intreadwrite.h"
45 #include "libavutil/mathematics.h"
46 #include "libavutil/random_seed.h"
47 #include "libavutil/rational.h"
48 #include "libavutil/parseutils.h"
49 #include "libavutil/opt.h"
50 #include "libavutil/time.h"
51 
52 #include <stdarg.h>
53 #if HAVE_UNISTD_H
54 #include <unistd.h>
55 #endif
56 #include <fcntl.h>
57 #include <sys/ioctl.h>
58 #if HAVE_POLL_H
59 #include <poll.h>
60 #endif
61 #include <errno.h>
62 #include <time.h>
63 #include <sys/wait.h>
64 #include <signal.h>
65 
66 #include "cmdutils.h"
67 #include "ffserver_config.h"
68 
69 #define PATH_LENGTH 1024
70 
71 const char program_name[] = "ffserver";
72 const int program_birth_year = 2000;
73 
74 static const OptionDef options[];
75 
76 enum HTTPState {
80  HTTPSTATE_SEND_DATA, /* sending TCP or UDP data */
83  HTTPSTATE_WAIT_FEED, /* wait for data from the feed */
85 
89 };
90 
91 static const char * const http_state[] = {
92  "HTTP_WAIT_REQUEST",
93  "HTTP_SEND_HEADER",
94 
95  "SEND_DATA_HEADER",
96  "SEND_DATA",
97  "SEND_DATA_TRAILER",
98  "RECEIVE_DATA",
99  "WAIT_FEED",
100  "READY",
101 
102  "RTSP_WAIT_REQUEST",
103  "RTSP_SEND_REPLY",
104  "RTSP_SEND_PACKET",
105 };
106 
107 #define IOBUFFER_INIT_SIZE 8192
108 
109 /* timeouts are in ms */
110 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
111 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
112 
113 #define SYNC_TIMEOUT (10 * 1000)
114 
115 typedef struct RTSPActionServerSetup {
116  uint32_t ipaddr;
117  char transport_option[512];
119 
120 typedef struct {
121  int64_t count1, count2;
122  int64_t time1, time2;
123 } DataRateData;
124 
125 /* context associated with one connection */
126 typedef struct HTTPContext {
128  int fd; /* socket file descriptor */
129  struct sockaddr_in from_addr; /* origin */
130  struct pollfd *poll_entry; /* used when polling */
131  int64_t timeout;
134  int post;
136  int chunk_size; /* 0 if it needs to be read */
137  struct HTTPContext *next;
138  int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
139  int64_t data_count;
140  /* feed input */
141  int feed_fd;
142  /* input format handling */
144  int64_t start_time; /* In milliseconds - this wraps fairly often */
145  int64_t first_pts; /* initial pts value */
146  int64_t cur_pts; /* current pts value from the stream in us */
147  int64_t cur_frame_duration; /* duration of the current frame in us */
148  int cur_frame_bytes; /* output frame size, needed to compute
149  the time at which we send each
150  packet */
151  int pts_stream_index; /* stream we choose as clock reference */
152  int64_t cur_clock; /* current clock reference value in us */
153  /* output format handling */
155  /* -1 is invalid stream */
156  int feed_streams[FFSERVER_MAX_STREAMS]; /* index of streams in the feed */
157  int switch_feed_streams[FFSERVER_MAX_STREAMS]; /* index of streams in the feed */
159  AVFormatContext *pfmt_ctx; /* instance of FFServerStream for one user */
160  int last_packet_sent; /* true if last data packet was sent */
164  char protocol[16];
165  char method[16];
166  char url[128];
167  char clean_url[128*7];
170  int is_packetized; /* if true, the stream is packetized */
171  int packet_stream_index; /* current stream for output in state machine */
172 
173  /* RTSP state specific */
174  uint8_t *pb_buffer; /* XXX: use that in all the code */
176  int seq; /* RTSP sequence number */
177 
178  /* RTP state specific */
180  char session_id[32]; /* session id */
182 
183  /* RTP/UDP specific */
185 
186  /* RTP/TCP specific */
189 } HTTPContext;
190 
192 
194  .nb_max_http_connections = 2000,
195  .nb_max_connections = 5,
196  .max_bandwidth = 1000,
197  .use_defaults = 1,
198 };
199 
200 static void new_connection(int server_fd, int is_rtsp);
201 static void close_connection(HTTPContext *c);
202 
203 /* HTTP handling */
204 static int handle_connection(HTTPContext *c);
206 static void compute_status(HTTPContext *c);
207 static int open_input_stream(HTTPContext *c, const char *info);
208 static int http_parse_request(HTTPContext *c);
209 static int http_send_data(HTTPContext *c);
211 static int http_receive_data(HTTPContext *c);
212 
213 /* RTSP handling */
214 static int rtsp_parse_request(HTTPContext *c);
215 static void rtsp_cmd_describe(HTTPContext *c, const char *url);
216 static void rtsp_cmd_options(HTTPContext *c, const char *url);
217 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
219 static void rtsp_cmd_play(HTTPContext *c, const char *url,
221 static void rtsp_cmd_interrupt(HTTPContext *c, const char *url,
222  RTSPMessageHeader *h, int pause_only);
223 
224 /* SDP handling */
226  struct in_addr my_ip);
227 
228 /* RTP handling */
229 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
231  const char *session_id,
233 static int rtp_new_av_stream(HTTPContext *c,
234  int stream_index, struct sockaddr_in *dest_addr,
236 /* utils */
237 static size_t htmlencode (const char *src, char **dest);
238 static inline void cp_html_entity (char *buffer, const char *entity);
239 static inline int check_codec_match(LayeredAVStream *ccf, AVStream *ccs, int stream);
240 
241 static const char *my_program_name;
242 
243 static int no_launch;
245 
246 /* maximum number of simultaneous HTTP connections */
247 static unsigned int nb_connections;
248 
249 static uint64_t current_bandwidth;
250 
251 /* Making this global saves on passing it around everywhere */
252 static int64_t cur_time;
253 
255 
256 static FILE *logfile = NULL;
257 
259 {
260  avcodec_free_context(&st->codec);
262 #define COPY(a) st->a = lst->a;
263  COPY(index)
264  COPY(id)
265  COPY(codec)
266  COPY(codecpar)
267  COPY(time_base)
268  COPY(pts_wrap_bits)
269  COPY(sample_aspect_ratio)
270  COPY(recommended_encoder_configuration)
271 }
272 
273 static inline void cp_html_entity (char *buffer, const char *entity) {
274  if (!buffer || !entity)
275  return;
276  while (*entity)
277  *buffer++ = *entity++;
278 }
279 
280 /**
281  * Substitutes known conflicting chars on a text string with
282  * their corresponding HTML entities.
283  *
284  * Returns the number of bytes in the 'encoded' representation
285  * not including the terminating NUL.
286  */
287 static size_t htmlencode (const char *src, char **dest) {
288  const char *amp = "&amp;";
289  const char *lt = "&lt;";
290  const char *gt = "&gt;";
291  const char *start;
292  char *tmp;
293  size_t final_size = 0;
294 
295  if (!src)
296  return 0;
297 
298  start = src;
299 
300  /* Compute needed dest size */
301  while (*src != '\0') {
302  switch(*src) {
303  case 38: /* & */
304  final_size += 5;
305  break;
306  case 60: /* < */
307  case 62: /* > */
308  final_size += 4;
309  break;
310  default:
311  final_size++;
312  }
313  src++;
314  }
315 
316  src = start;
317  *dest = av_mallocz(final_size + 1);
318  if (!*dest)
319  return 0;
320 
321  /* Build dest */
322  tmp = *dest;
323  while (*src != '\0') {
324  switch(*src) {
325  case 38: /* & */
326  cp_html_entity (tmp, amp);
327  tmp += 5;
328  break;
329  case 60: /* < */
330  cp_html_entity (tmp, lt);
331  tmp += 4;
332  break;
333  case 62: /* > */
334  cp_html_entity (tmp, gt);
335  tmp += 4;
336  break;
337  default:
338  *tmp = *src;
339  tmp += 1;
340  }
341  src++;
342  }
343  *tmp = '\0';
344 
345  return final_size;
346 }
347 
348 static int64_t ffm_read_write_index(int fd)
349 {
350  uint8_t buf[8];
351 
352  if (lseek(fd, 8, SEEK_SET) < 0)
353  return AVERROR(EIO);
354  if (read(fd, buf, 8) != 8)
355  return AVERROR(EIO);
356  return AV_RB64(buf);
357 }
358 
359 static int ffm_write_write_index(int fd, int64_t pos)
360 {
361  uint8_t buf[8];
362  int i;
363 
364  for(i=0;i<8;i++)
365  buf[i] = (pos >> (56 - i * 8)) & 0xff;
366  if (lseek(fd, 8, SEEK_SET) < 0)
367  goto bail_eio;
368  if (write(fd, buf, 8) != 8)
369  goto bail_eio;
370 
371  return 8;
372 
373 bail_eio:
374  return AVERROR(EIO);
375 }
376 
377 static void ffm_set_write_index(AVFormatContext *s, int64_t pos,
378  int64_t file_size)
379 {
380  av_opt_set_int(s, "server_attached", 1, AV_OPT_SEARCH_CHILDREN);
381  av_opt_set_int(s, "ffm_write_index", pos, AV_OPT_SEARCH_CHILDREN);
382  av_opt_set_int(s, "ffm_file_size", file_size, AV_OPT_SEARCH_CHILDREN);
383 }
384 
385 static char *ctime1(char *buf2, size_t buf_size)
386 {
387  time_t ti;
388  char *p;
389 
390  ti = time(NULL);
391  p = ctime(&ti);
392  if (!p || !*p) {
393  *buf2 = '\0';
394  return buf2;
395  }
396  av_strlcpy(buf2, p, buf_size);
397  p = buf2 + strlen(buf2) - 1;
398  if (*p == '\n')
399  *p = '\0';
400  return buf2;
401 }
402 
403 static void http_vlog(const char *fmt, va_list vargs)
404 {
405  static int print_prefix = 1;
406  char buf[32];
407 
408  if (!logfile)
409  return;
410 
411  if (print_prefix) {
412  ctime1(buf, sizeof(buf));
413  fprintf(logfile, "%s ", buf);
414  }
415  print_prefix = strstr(fmt, "\n") != NULL;
416  vfprintf(logfile, fmt, vargs);
417  fflush(logfile);
418 }
419 
420 #ifdef __GNUC__
421 __attribute__ ((format (printf, 1, 2)))
422 #endif
423 static void http_log(const char *fmt, ...)
424 {
425  va_list vargs;
426  va_start(vargs, fmt);
427  http_vlog(fmt, vargs);
428  va_end(vargs);
429 }
430 
431 static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
432 {
433  static int print_prefix = 1;
434  AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
435  if (level > av_log_get_level())
436  return;
437  if (print_prefix && avc)
438  http_log("[%s @ %p]", avc->item_name(ptr), ptr);
439  print_prefix = strstr(fmt, "\n") != NULL;
440  http_vlog(fmt, vargs);
441 }
442 
444 {
445  if (c->suppress_log)
446  return;
447 
448  http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
449  inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
450  c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
451 }
452 
453 static void update_datarate(DataRateData *drd, int64_t count)
454 {
455  if (!drd->time1 && !drd->count1) {
456  drd->time1 = drd->time2 = cur_time;
457  drd->count1 = drd->count2 = count;
458  } else if (cur_time - drd->time2 > 5000) {
459  drd->time1 = drd->time2;
460  drd->count1 = drd->count2;
461  drd->time2 = cur_time;
462  drd->count2 = count;
463  }
464 }
465 
466 /* In bytes per second */
467 static int compute_datarate(DataRateData *drd, int64_t count)
468 {
469  if (cur_time == drd->time1)
470  return 0;
471 
472  return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
473 }
474 
475 
476 static void start_children(FFServerStream *feed)
477 {
478  char *pathname;
479  char *slash;
480  int i;
481  size_t cmd_length;
482 
483  if (no_launch)
484  return;
485 
486  cmd_length = strlen(my_program_name);
487 
488  /**
489  * FIXME: WIP Safeguard. Remove after clearing all harcoded
490  * '1024' path lengths
491  */
492  if (cmd_length > PATH_LENGTH - 1) {
493  http_log("Could not start children. Command line: '%s' exceeds "
494  "path length limit (%d)\n", my_program_name, PATH_LENGTH);
495  return;
496  }
497 
498  pathname = av_strdup (my_program_name);
499  if (!pathname) {
500  http_log("Could not allocate memory for children cmd line\n");
501  return;
502  }
503  /* replace "ffserver" with "ffmpeg" in the path of current
504  * program. Ignore user provided path */
505 
506  slash = strrchr(pathname, '/');
507  if (!slash)
508  slash = pathname;
509  else
510  slash++;
511  strcpy(slash, "ffmpeg");
512 
513  for (; feed; feed = feed->next) {
514 
515  if (!feed->child_argv || feed->pid)
516  continue;
517 
518  feed->pid_start = time(0);
519 
520  feed->pid = fork();
521  if (feed->pid < 0) {
522  http_log("Unable to create children: %s\n", strerror(errno));
523  av_free (pathname);
524  exit(EXIT_FAILURE);
525  }
526 
527  if (feed->pid)
528  continue;
529 
530  /* In child */
531 
532  http_log("Launch command line: ");
533  http_log("%s ", pathname);
534 
535  for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
536  http_log("%s ", feed->child_argv[i]);
537  http_log("\n");
538 
539  for (i = 3; i < 256; i++)
540  close(i);
541 
542  if (!config.debug) {
543  if (!freopen("/dev/null", "r", stdin))
544  http_log("failed to redirect STDIN to /dev/null\n;");
545  if (!freopen("/dev/null", "w", stdout))
546  http_log("failed to redirect STDOUT to /dev/null\n;");
547  if (!freopen("/dev/null", "w", stderr))
548  http_log("failed to redirect STDERR to /dev/null\n;");
549  }
550 
551  signal(SIGPIPE, SIG_DFL);
552  execvp(pathname, feed->child_argv);
553  av_free (pathname);
554  _exit(1);
555  }
556  av_free (pathname);
557 }
558 
559 /* open a listening socket */
560 static int socket_open_listen(struct sockaddr_in *my_addr)
561 {
562  int server_fd, tmp;
563 
564  server_fd = socket(AF_INET,SOCK_STREAM,0);
565  if (server_fd < 0) {
566  perror ("socket");
567  return -1;
568  }
569 
570  tmp = 1;
571  if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp)))
572  av_log(NULL, AV_LOG_WARNING, "setsockopt SO_REUSEADDR failed\n");
573 
574  my_addr->sin_family = AF_INET;
575  if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
576  char bindmsg[32];
577  snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)",
578  ntohs(my_addr->sin_port));
579  perror (bindmsg);
580  goto fail;
581  }
582 
583  if (listen (server_fd, 5) < 0) {
584  perror ("listen");
585  goto fail;
586  }
587 
588  if (ff_socket_nonblock(server_fd, 1) < 0)
589  av_log(NULL, AV_LOG_WARNING, "ff_socket_nonblock failed\n");
590 
591  return server_fd;
592 
593 fail:
594  closesocket(server_fd);
595  return -1;
596 }
597 
598 /* start all multicast streams */
599 static void start_multicast(void)
600 {
602  char session_id[32];
603  HTTPContext *rtp_c;
604  struct sockaddr_in dest_addr = {0};
605  int default_port, stream_index;
606  unsigned int random0, random1;
607 
608  default_port = 6000;
609  for(stream = config.first_stream; stream; stream = stream->next) {
610 
611  if (!stream->is_multicast)
612  continue;
613 
614  random0 = av_lfg_get(&random_state);
615  random1 = av_lfg_get(&random_state);
616 
617  /* open the RTP connection */
618  snprintf(session_id, sizeof(session_id), "%08x%08x", random0, random1);
619 
620  /* choose a port if none given */
621  if (stream->multicast_port == 0) {
622  stream->multicast_port = default_port;
623  default_port += 100;
624  }
625 
626  dest_addr.sin_family = AF_INET;
627  dest_addr.sin_addr = stream->multicast_ip;
628  dest_addr.sin_port = htons(stream->multicast_port);
629 
630  rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
632  if (!rtp_c)
633  continue;
634 
635  if (open_input_stream(rtp_c, "") < 0) {
636  http_log("Could not open input stream for stream '%s'\n",
637  stream->filename);
638  continue;
639  }
640 
641  /* open each RTP stream */
642  for(stream_index = 0; stream_index < stream->nb_streams;
643  stream_index++) {
644  dest_addr.sin_port = htons(stream->multicast_port +
645  2 * stream_index);
646  if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) >= 0)
647  continue;
648 
649  http_log("Could not open output stream '%s/streamid=%d'\n",
650  stream->filename, stream_index);
651  exit(1);
652  }
653 
654  rtp_c->state = HTTPSTATE_SEND_DATA;
655  }
656 }
657 
658 /* main loop of the HTTP server */
659 static int http_server(void)
660 {
661  int server_fd = 0, rtsp_server_fd = 0;
662  int ret, delay;
663  struct pollfd *poll_table, *poll_entry;
664  HTTPContext *c, *c_next;
665 
666  poll_table = av_mallocz_array(config.nb_max_http_connections + 2,
667  sizeof(*poll_table));
668  if(!poll_table) {
669  http_log("Impossible to allocate a poll table handling %d "
670  "connections.\n", config.nb_max_http_connections);
671  return -1;
672  }
673 
674  if (config.http_addr.sin_port) {
675  server_fd = socket_open_listen(&config.http_addr);
676  if (server_fd < 0)
677  goto quit;
678  }
679 
680  if (config.rtsp_addr.sin_port) {
681  rtsp_server_fd = socket_open_listen(&config.rtsp_addr);
682  if (rtsp_server_fd < 0) {
683  closesocket(server_fd);
684  goto quit;
685  }
686  }
687 
688  if (!rtsp_server_fd && !server_fd) {
689  http_log("HTTP and RTSP disabled.\n");
690  goto quit;
691  }
692 
693  http_log("FFserver started.\n");
694 
695  start_children(config.first_feed);
696 
697  start_multicast();
698 
699  for(;;) {
700  poll_entry = poll_table;
701  if (server_fd) {
702  poll_entry->fd = server_fd;
703  poll_entry->events = POLLIN;
704  poll_entry++;
705  }
706  if (rtsp_server_fd) {
707  poll_entry->fd = rtsp_server_fd;
708  poll_entry->events = POLLIN;
709  poll_entry++;
710  }
711 
712  /* wait for events on each HTTP handle */
713  c = first_http_ctx;
714  delay = 1000;
715  while (c) {
716  int fd;
717  fd = c->fd;
718  switch(c->state) {
722  c->poll_entry = poll_entry;
723  poll_entry->fd = fd;
724  poll_entry->events = POLLOUT;
725  poll_entry++;
726  break;
728  case HTTPSTATE_SEND_DATA:
730  if (!c->is_packetized) {
731  /* for TCP, we output as much as we can
732  * (may need to put a limit) */
733  c->poll_entry = poll_entry;
734  poll_entry->fd = fd;
735  poll_entry->events = POLLOUT;
736  poll_entry++;
737  } else {
738  /* when ffserver is doing the timing, we work by
739  * looking at which packet needs to be sent every
740  * 10 ms (one tick wait XXX: 10 ms assumed) */
741  if (delay > 10)
742  delay = 10;
743  }
744  break;
747  case HTTPSTATE_WAIT_FEED:
749  /* need to catch errors */
750  c->poll_entry = poll_entry;
751  poll_entry->fd = fd;
752  poll_entry->events = POLLIN;/* Maybe this will work */
753  poll_entry++;
754  break;
755  default:
756  c->poll_entry = NULL;
757  break;
758  }
759  c = c->next;
760  }
761 
762  /* wait for an event on one connection. We poll at least every
763  * second to handle timeouts */
764  do {
765  ret = poll(poll_table, poll_entry - poll_table, delay);
766  if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) &&
767  ff_neterrno() != AVERROR(EINTR)) {
768  goto quit;
769  }
770  } while (ret < 0);
771 
772  cur_time = av_gettime() / 1000;
773 
776  start_children(config.first_feed);
777  }
778 
779  /* now handle the events */
780  for(c = first_http_ctx; c; c = c_next) {
781  c_next = c->next;
782  if (handle_connection(c) < 0) {
783  log_connection(c);
784  /* close and free the connection */
785  close_connection(c);
786  }
787  }
788 
789  poll_entry = poll_table;
790  if (server_fd) {
791  /* new HTTP connection request ? */
792  if (poll_entry->revents & POLLIN)
793  new_connection(server_fd, 0);
794  poll_entry++;
795  }
796  if (rtsp_server_fd) {
797  /* new RTSP connection request ? */
798  if (poll_entry->revents & POLLIN)
799  new_connection(rtsp_server_fd, 1);
800  }
801  }
802 
803 quit:
804  av_free(poll_table);
805  return -1;
806 }
807 
808 /* start waiting for a new HTTP/RTSP request */
809 static void start_wait_request(HTTPContext *c, int is_rtsp)
810 {
811  c->buffer_ptr = c->buffer;
812  c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */
813 
815  c->timeout = cur_time +
817 }
818 
819 static void http_send_too_busy_reply(int fd)
820 {
821  char buffer[400];
822  int len = snprintf(buffer, sizeof(buffer),
823  "HTTP/1.0 503 Server too busy\r\n"
824  "Content-type: text/html\r\n"
825  "\r\n"
826  "<!DOCTYPE html>\n"
827  "<html><head><title>Too busy</title></head><body>\r\n"
828  "<p>The server is too busy to serve your request at "
829  "this time.</p>\r\n"
830  "<p>The number of current connections is %u, and this "
831  "exceeds the limit of %u.</p>\r\n"
832  "</body></html>\r\n",
834  av_assert0(len < sizeof(buffer));
835  if (send(fd, buffer, len, 0) < len)
837  "Could not send too-busy reply, send() failed\n");
838 }
839 
840 
841 static void new_connection(int server_fd, int is_rtsp)
842 {
843  struct sockaddr_in from_addr;
844  socklen_t len;
845  int fd;
846  HTTPContext *c = NULL;
847 
848  len = sizeof(from_addr);
849  fd = accept(server_fd, (struct sockaddr *)&from_addr,
850  &len);
851  if (fd < 0) {
852  http_log("error during accept %s\n", strerror(errno));
853  return;
854  }
855  if (ff_socket_nonblock(fd, 1) < 0)
856  av_log(NULL, AV_LOG_WARNING, "ff_socket_nonblock failed\n");
857 
858  if (nb_connections >= config.nb_max_connections) {
860  goto fail;
861  }
862 
863  /* add a new connection */
864  c = av_mallocz(sizeof(HTTPContext));
865  if (!c)
866  goto fail;
867 
868  c->fd = fd;
869  c->poll_entry = NULL;
870  c->from_addr = from_addr;
872  c->buffer = av_malloc(c->buffer_size);
873  if (!c->buffer)
874  goto fail;
875 
876  c->next = first_http_ctx;
877  first_http_ctx = c;
878  nb_connections++;
879 
880  start_wait_request(c, is_rtsp);
881 
882  return;
883 
884  fail:
885  if (c) {
886  av_freep(&c->buffer);
887  av_free(c);
888  }
889  closesocket(fd);
890 }
891 
893 {
894  HTTPContext **cp, *c1;
895  int i, nb_streams;
897  AVStream *st;
898 
899  /* remove connection from list */
900  cp = &first_http_ctx;
901  while (*cp) {
902  c1 = *cp;
903  if (c1 == c)
904  *cp = c->next;
905  else
906  cp = &c1->next;
907  }
908 
909  /* remove references, if any (XXX: do it faster) */
910  for(c1 = first_http_ctx; c1; c1 = c1->next) {
911  if (c1->rtsp_c == c)
912  c1->rtsp_c = NULL;
913  }
914 
915  /* remove connection associated resources */
916  if (c->fd >= 0)
917  closesocket(c->fd);
918  if (c->fmt_in) {
919  /* close each frame parser */
920  for(i=0;i<c->fmt_in->nb_streams;i++) {
921  st = c->fmt_in->streams[i];
922  if (st->codec->codec)
923  avcodec_close(st->codec);
924  }
926  }
927 
928  /* free RTP output streams if any */
929  nb_streams = 0;
930  if (c->stream)
931  nb_streams = c->stream->nb_streams;
932 
933  for(i=0;i<nb_streams;i++) {
934  ctx = c->rtp_ctx[i];
935  if (ctx) {
936  av_write_trailer(ctx);
937  av_dict_free(&ctx->metadata);
938  av_freep(&ctx->streams[0]);
939  av_freep(&ctx);
940  }
941  ffurl_close(c->rtp_handles[i]);
942  }
943 
944  ctx = c->pfmt_ctx;
945 
946  if (ctx) {
948  /* prepare header */
949  if (ctx->oformat && avio_open_dyn_buf(&ctx->pb) >= 0) {
950  av_write_trailer(ctx);
951  av_freep(&c->pb_buffer);
952  avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
953  }
954  }
955  for(i=0; i<ctx->nb_streams; i++)
956  av_freep(&ctx->streams[i]);
957  av_freep(&ctx->streams);
958  av_freep(&ctx->priv_data);
959  }
960 
961  if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
963 
964  /* signal that there is no feed if we are the feeder socket */
965  if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) {
966  c->stream->feed_opened = 0;
967  close(c->feed_fd);
968  }
969 
970  av_freep(&c->pb_buffer);
971  av_freep(&c->packet_buffer);
972  av_freep(&c->buffer);
973  av_free(c);
974  nb_connections--;
975 }
976 
978 {
979  int len, ret;
980  uint8_t *ptr;
981 
982  switch(c->state) {
985  /* timeout ? */
986  if ((c->timeout - cur_time) < 0)
987  return -1;
988  if (c->poll_entry->revents & (POLLERR | POLLHUP))
989  return -1;
990 
991  /* no need to read if no events */
992  if (!(c->poll_entry->revents & POLLIN))
993  return 0;
994  /* read the data */
995  read_loop:
996  if (!(len = recv(c->fd, c->buffer_ptr, 1, 0)))
997  return -1;
998 
999  if (len < 0) {
1000  if (ff_neterrno() != AVERROR(EAGAIN) &&
1001  ff_neterrno() != AVERROR(EINTR))
1002  return -1;
1003  break;
1004  }
1005  /* search for end of request. */
1006  c->buffer_ptr += len;
1007  ptr = c->buffer_ptr;
1008  if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
1009  (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
1010  /* request found : parse it and reply */
1011  if (c->state == HTTPSTATE_WAIT_REQUEST)
1012  ret = http_parse_request(c);
1013  else
1014  ret = rtsp_parse_request(c);
1015 
1016  if (ret < 0)
1017  return -1;
1018  } else if (ptr >= c->buffer_end) {
1019  /* request too long: cannot do anything */
1020  return -1;
1021  } else goto read_loop;
1022 
1023  break;
1024 
1025  case HTTPSTATE_SEND_HEADER:
1026  if (c->poll_entry->revents & (POLLERR | POLLHUP))
1027  return -1;
1028 
1029  /* no need to write if no events */
1030  if (!(c->poll_entry->revents & POLLOUT))
1031  return 0;
1032  len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
1033  if (len < 0) {
1034  if (ff_neterrno() != AVERROR(EAGAIN) &&
1035  ff_neterrno() != AVERROR(EINTR)) {
1036  goto close_connection;
1037  }
1038  break;
1039  }
1040  c->buffer_ptr += len;
1041  if (c->stream)
1042  c->stream->bytes_served += len;
1043  c->data_count += len;
1044  if (c->buffer_ptr >= c->buffer_end) {
1045  av_freep(&c->pb_buffer);
1046  /* if error, exit */
1047  if (c->http_error)
1048  return -1;
1049  /* all the buffer was sent : synchronize to the incoming
1050  * stream */
1052  c->buffer_ptr = c->buffer_end = c->buffer;
1053  }
1054  break;
1055 
1056  case HTTPSTATE_SEND_DATA:
1059  /* for packetized output, we consider we can always write (the
1060  * input streams set the speed). It may be better to verify
1061  * that we do not rely too much on the kernel queues */
1062  if (!c->is_packetized) {
1063  if (c->poll_entry->revents & (POLLERR | POLLHUP))
1064  return -1;
1065 
1066  /* no need to read if no events */
1067  if (!(c->poll_entry->revents & POLLOUT))
1068  return 0;
1069  }
1070  if (http_send_data(c) < 0)
1071  return -1;
1072  /* close connection if trailer sent */
1074  return -1;
1075  /* Check if it is a single jpeg frame 123 */
1076  if (c->stream->single_frame && c->data_count > c->cur_frame_bytes && c->cur_frame_bytes > 0) {
1077  close_connection(c);
1078  }
1079  break;
1081  /* no need to read if no events */
1082  if (c->poll_entry->revents & (POLLERR | POLLHUP))
1083  return -1;
1084  if (!(c->poll_entry->revents & POLLIN))
1085  return 0;
1086  if (http_receive_data(c) < 0)
1087  return -1;
1088  break;
1089  case HTTPSTATE_WAIT_FEED:
1090  /* no need to read if no events */
1091  if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1092  return -1;
1093 
1094  /* nothing to do, we'll be waken up by incoming feed packets */
1095  break;
1096 
1097  case RTSPSTATE_SEND_REPLY:
1098  if (c->poll_entry->revents & (POLLERR | POLLHUP))
1099  goto close_connection;
1100  /* no need to write if no events */
1101  if (!(c->poll_entry->revents & POLLOUT))
1102  return 0;
1103  len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
1104  if (len < 0) {
1105  if (ff_neterrno() != AVERROR(EAGAIN) &&
1106  ff_neterrno() != AVERROR(EINTR)) {
1107  goto close_connection;
1108  }
1109  break;
1110  }
1111  c->buffer_ptr += len;
1112  c->data_count += len;
1113  if (c->buffer_ptr >= c->buffer_end) {
1114  /* all the buffer was sent : wait for a new request */
1115  av_freep(&c->pb_buffer);
1116  start_wait_request(c, 1);
1117  }
1118  break;
1119  case RTSPSTATE_SEND_PACKET:
1120  if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1121  av_freep(&c->packet_buffer);
1122  return -1;
1123  }
1124  /* no need to write if no events */
1125  if (!(c->poll_entry->revents & POLLOUT))
1126  return 0;
1127  len = send(c->fd, c->packet_buffer_ptr,
1129  if (len < 0) {
1130  if (ff_neterrno() != AVERROR(EAGAIN) &&
1131  ff_neterrno() != AVERROR(EINTR)) {
1132  /* error : close connection */
1133  av_freep(&c->packet_buffer);
1134  return -1;
1135  }
1136  break;
1137  }
1138  c->packet_buffer_ptr += len;
1139  if (c->packet_buffer_ptr >= c->packet_buffer_end) {
1140  /* all the buffer was sent : wait for a new request */
1141  av_freep(&c->packet_buffer);
1143  }
1144  break;
1145  case HTTPSTATE_READY:
1146  /* nothing to do */
1147  break;
1148  default:
1149  return -1;
1150  }
1151  return 0;
1152 
1154  av_freep(&c->pb_buffer);
1155  return -1;
1156 }
1157 
1158 static int extract_rates(char *rates, int ratelen, const char *request)
1159 {
1160  const char *p;
1161 
1162  for (p = request; *p && *p != '\r' && *p != '\n'; ) {
1163  if (av_strncasecmp(p, "Pragma:", 7) == 0) {
1164  const char *q = p + 7;
1165 
1166  while (*q && *q != '\n' && av_isspace(*q))
1167  q++;
1168 
1169  if (av_strncasecmp(q, "stream-switch-entry=", 20) == 0) {
1170  int stream_no;
1171  int rate_no;
1172 
1173  q += 20;
1174 
1175  memset(rates, 0xff, ratelen);
1176 
1177  while (1) {
1178  while (*q && *q != '\n' && *q != ':')
1179  q++;
1180 
1181  if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2)
1182  break;
1183 
1184  stream_no--;
1185  if (stream_no < ratelen && stream_no >= 0)
1186  rates[stream_no] = rate_no;
1187 
1188  while (*q && *q != '\n' && !av_isspace(*q))
1189  q++;
1190  }
1191 
1192  return 1;
1193  }
1194  }
1195  p = strchr(p, '\n');
1196  if (!p)
1197  break;
1198 
1199  p++;
1200  }
1201 
1202  return 0;
1203 }
1204 
1206  int bit_rate)
1207 {
1208  int i;
1209  int best_bitrate = 100000000;
1210  int best = -1;
1211 
1212  for (i = 0; i < feed->nb_streams; i++) {
1213  AVCodecParameters *feed_codec = feed->streams[i]->codecpar;
1214 
1215  if (feed_codec->codec_id != codec->codec_id ||
1216  feed_codec->sample_rate != codec->sample_rate ||
1217  feed_codec->width != codec->width ||
1218  feed_codec->height != codec->height)
1219  continue;
1220 
1221  /* Potential stream */
1222 
1223  /* We want the fastest stream less than bit_rate, or the slowest
1224  * faster than bit_rate
1225  */
1226 
1227  if (feed_codec->bit_rate <= bit_rate) {
1228  if (best_bitrate > bit_rate ||
1229  feed_codec->bit_rate > best_bitrate) {
1230  best_bitrate = feed_codec->bit_rate;
1231  best = i;
1232  }
1233  continue;
1234  }
1235  if (feed_codec->bit_rate < best_bitrate) {
1236  best_bitrate = feed_codec->bit_rate;
1237  best = i;
1238  }
1239  }
1240  return best;
1241 }
1242 
1244 {
1245  int i;
1246  FFServerStream *req = c->stream;
1247  int action_required = 0;
1248 
1249  /* Not much we can do for a feed */
1250  if (!req->feed)
1251  return 0;
1252 
1253  for (i = 0; i < req->nb_streams; i++) {
1254  AVCodecParameters *codec = req->streams[i]->codecpar;
1255 
1256  switch(rates[i]) {
1257  case 0:
1258  c->switch_feed_streams[i] = req->feed_streams[i];
1259  break;
1260  case 1:
1261  c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2);
1262  break;
1263  case 2:
1264  /* Wants off or slow */
1265  c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);
1266 #ifdef WANTS_OFF
1267  /* This doesn't work well when it turns off the only stream! */
1268  c->switch_feed_streams[i] = -2;
1269  c->feed_streams[i] = -2;
1270 #endif
1271  break;
1272  }
1273 
1274  if (c->switch_feed_streams[i] >= 0 &&
1275  c->switch_feed_streams[i] != c->feed_streams[i]) {
1276  action_required = 1;
1277  }
1278  }
1279 
1280  return action_required;
1281 }
1282 
1283 static void get_word(char *buf, int buf_size, const char **pp)
1284 {
1285  const char *p;
1286  char *q;
1287 
1288 #define SPACE_CHARS " \t\r\n"
1289 
1290  p = *pp;
1291  p += strspn(p, SPACE_CHARS);
1292  q = buf;
1293  while (!av_isspace(*p) && *p != '\0') {
1294  if ((q - buf) < buf_size - 1)
1295  *q++ = *p;
1296  p++;
1297  }
1298  if (buf_size > 0)
1299  *q = '\0';
1300  *pp = p;
1301 }
1302 
1304  HTTPContext *c)
1305 {
1306  FILE* f;
1307  char line[1024];
1308  char cmd[1024];
1309  FFServerIPAddressACL *acl = NULL;
1310  int line_num = 0;
1311  const char *p;
1312 
1313  f = fopen(stream->dynamic_acl, "r");
1314  if (!f) {
1315  perror(stream->dynamic_acl);
1316  return NULL;
1317  }
1318 
1319  acl = av_mallocz(sizeof(FFServerIPAddressACL));
1320  if (!acl) {
1321  fclose(f);
1322  return NULL;
1323  }
1324 
1325  /* Build ACL */
1326  while (fgets(line, sizeof(line), f)) {
1327  line_num++;
1328  p = line;
1329  while (av_isspace(*p))
1330  p++;
1331  if (*p == '\0' || *p == '#')
1332  continue;
1333  ffserver_get_arg(cmd, sizeof(cmd), &p);
1334 
1335  if (!av_strcasecmp(cmd, "ACL"))
1336  ffserver_parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl,
1337  line_num);
1338  }
1339  fclose(f);
1340  return acl;
1341 }
1342 
1343 
1345 {
1346  FFServerIPAddressACL *pacl, *pacl2;
1347 
1348  pacl = in_acl;
1349  while(pacl) {
1350  pacl2 = pacl;
1351  pacl = pacl->next;
1352  av_freep(pacl2);
1353  }
1354 }
1355 
1357 {
1358  enum FFServerIPAddressAction last_action = IP_DENY;
1359  FFServerIPAddressACL *acl;
1360  struct in_addr *src = &c->from_addr.sin_addr;
1361  unsigned long src_addr = src->s_addr;
1362 
1363  for (acl = in_acl; acl; acl = acl->next) {
1364  if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr)
1365  return (acl->action == IP_ALLOW) ? 1 : 0;
1366  last_action = acl->action;
1367  }
1368 
1369  /* Nothing matched, so return not the last action */
1370  return (last_action == IP_DENY) ? 1 : 0;
1371 }
1372 
1374 {
1375  int ret = 0;
1376  FFServerIPAddressACL *acl;
1377 
1378  /* if stream->acl is null validate_acl_list will return 1 */
1379  ret = validate_acl_list(stream->acl, c);
1380 
1381  if (stream->dynamic_acl[0]) {
1382  acl = parse_dynamic_acl(stream, c);
1383  ret = validate_acl_list(acl, c);
1384  free_acl_list(acl);
1385  }
1386 
1387  return ret;
1388 }
1389 
1390 /**
1391  * compute the real filename of a file by matching it without its
1392  * extensions to all the stream's filenames
1393  */
1394 static void compute_real_filename(char *filename, int max_size)
1395 {
1396  char file1[1024];
1397  char file2[1024];
1398  char *p;
1399  FFServerStream *stream;
1400 
1401  av_strlcpy(file1, filename, sizeof(file1));
1402  p = strrchr(file1, '.');
1403  if (p)
1404  *p = '\0';
1405  for(stream = config.first_stream; stream; stream = stream->next) {
1406  av_strlcpy(file2, stream->filename, sizeof(file2));
1407  p = strrchr(file2, '.');
1408  if (p)
1409  *p = '\0';
1410  if (!strcmp(file1, file2)) {
1411  av_strlcpy(filename, stream->filename, max_size);
1412  break;
1413  }
1414  }
1415 }
1416 
1424 };
1425 
1426 /* parse HTTP request and prepare header */
1428 {
1429  const char *p;
1430  char *p1;
1431  enum RedirType redir_type;
1432  char cmd[32];
1433  char info[1024], filename[1024];
1434  char url[1024], *q;
1435  char protocol[32];
1436  char msg[1024];
1437  char *encoded_msg = NULL;
1438  const char *mime_type;
1439  FFServerStream *stream;
1440  int i;
1441  char ratebuf[32];
1442  const char *useragent = 0;
1443 
1444  p = c->buffer;
1445  get_word(cmd, sizeof(cmd), &p);
1446  av_strlcpy(c->method, cmd, sizeof(c->method));
1447 
1448  if (!strcmp(cmd, "GET"))
1449  c->post = 0;
1450  else if (!strcmp(cmd, "POST"))
1451  c->post = 1;
1452  else
1453  return -1;
1454 
1455  get_word(url, sizeof(url), &p);
1456  av_strlcpy(c->url, url, sizeof(c->url));
1457 
1458  get_word(protocol, sizeof(protocol), (const char **)&p);
1459  if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
1460  return -1;
1461 
1462  av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
1463 
1464  if (config.debug)
1465  http_log("%s - - New connection: %s %s\n",
1466  inet_ntoa(c->from_addr.sin_addr), cmd, url);
1467 
1468  /* find the filename and the optional info string in the request */
1469  p1 = strchr(url, '?');
1470  if (p1) {
1471  av_strlcpy(info, p1, sizeof(info));
1472  *p1 = '\0';
1473  } else
1474  info[0] = '\0';
1475 
1476  av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1);
1477 
1478  for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1479  if (av_strncasecmp(p, "User-Agent:", 11) == 0) {
1480  useragent = p + 11;
1481  if (*useragent && *useragent != '\n' && av_isspace(*useragent))
1482  useragent++;
1483  break;
1484  }
1485  p = strchr(p, '\n');
1486  if (!p)
1487  break;
1488 
1489  p++;
1490  }
1491 
1492  redir_type = REDIR_NONE;
1493  if (av_match_ext(filename, "asx")) {
1494  redir_type = REDIR_ASX;
1495  filename[strlen(filename)-1] = 'f';
1496  } else if (av_match_ext(filename, "asf") &&
1497  (!useragent || av_strncasecmp(useragent, "NSPlayer", 8))) {
1498  /* if this isn't WMP or lookalike, return the redirector file */
1499  redir_type = REDIR_ASF;
1500  } else if (av_match_ext(filename, "rpm,ram")) {
1501  redir_type = REDIR_RAM;
1502  strcpy(filename + strlen(filename)-2, "m");
1503  } else if (av_match_ext(filename, "rtsp")) {
1504  redir_type = REDIR_RTSP;
1505  compute_real_filename(filename, sizeof(filename) - 1);
1506  } else if (av_match_ext(filename, "sdp")) {
1507  redir_type = REDIR_SDP;
1508  compute_real_filename(filename, sizeof(filename) - 1);
1509  }
1510 
1511  /* "redirect" request to index.html */
1512  if (!strlen(filename))
1513  av_strlcpy(filename, "index.html", sizeof(filename) - 1);
1514 
1515  stream = config.first_stream;
1516  while (stream) {
1517  if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
1518  break;
1519  stream = stream->next;
1520  }
1521  if (!stream) {
1522  snprintf(msg, sizeof(msg), "File '%s' not found", url);
1523  http_log("File '%s' not found\n", url);
1524  goto send_error;
1525  }
1526 
1527  c->stream = stream;
1528  memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
1529  memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
1530 
1531  if (stream->stream_type == STREAM_TYPE_REDIRECT) {
1532  c->http_error = 301;
1533  q = c->buffer;
1534  snprintf(q, c->buffer_size,
1535  "HTTP/1.0 301 Moved\r\n"
1536  "Location: %s\r\n"
1537  "Content-type: text/html\r\n"
1538  "\r\n"
1539  "<!DOCTYPE html>\n"
1540  "<html><head><title>Moved</title></head><body>\r\n"
1541  "You should be <a href=\"%s\">redirected</a>.\r\n"
1542  "</body></html>\r\n",
1543  stream->feed_filename, stream->feed_filename);
1544  q += strlen(q);
1545  /* prepare output buffer */
1546  c->buffer_ptr = c->buffer;
1547  c->buffer_end = q;
1549  return 0;
1550  }
1551 
1552  /* If this is WMP, get the rate information */
1553  if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1554  if (modify_current_stream(c, ratebuf)) {
1555  for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) {
1556  if (c->switch_feed_streams[i] >= 0)
1557  c->switch_feed_streams[i] = -1;
1558  }
1559  }
1560  }
1561 
1562  if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
1563  current_bandwidth += stream->bandwidth;
1564 
1565  /* If already streaming this feed, do not let another feeder start */
1566  if (stream->feed_opened) {
1567  snprintf(msg, sizeof(msg), "This feed is already being received.");
1568  http_log("Feed '%s' already being received\n", stream->feed_filename);
1569  goto send_error;
1570  }
1571 
1572  if (c->post == 0 && config.max_bandwidth < current_bandwidth) {
1573  c->http_error = 503;
1574  q = c->buffer;
1575  snprintf(q, c->buffer_size,
1576  "HTTP/1.0 503 Server too busy\r\n"
1577  "Content-type: text/html\r\n"
1578  "\r\n"
1579  "<!DOCTYPE html>\n"
1580  "<html><head><title>Too busy</title></head><body>\r\n"
1581  "<p>The server is too busy to serve your request at "
1582  "this time.</p>\r\n"
1583  "<p>The bandwidth being served (including your stream) "
1584  "is %"PRIu64"kbit/s, and this exceeds the limit of "
1585  "%"PRIu64"kbit/s.</p>\r\n"
1586  "</body></html>\r\n",
1588  q += strlen(q);
1589  /* prepare output buffer */
1590  c->buffer_ptr = c->buffer;
1591  c->buffer_end = q;
1593  return 0;
1594  }
1595 
1596  if (redir_type != REDIR_NONE) {
1597  const char *hostinfo = 0;
1598 
1599  for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1600  if (av_strncasecmp(p, "Host:", 5) == 0) {
1601  hostinfo = p + 5;
1602  break;
1603  }
1604  p = strchr(p, '\n');
1605  if (!p)
1606  break;
1607 
1608  p++;
1609  }
1610 
1611  if (hostinfo) {
1612  char *eoh;
1613  char hostbuf[260];
1614 
1615  while (av_isspace(*hostinfo))
1616  hostinfo++;
1617 
1618  eoh = strchr(hostinfo, '\n');
1619  if (eoh) {
1620  if (eoh[-1] == '\r')
1621  eoh--;
1622 
1623  if (eoh - hostinfo < sizeof(hostbuf) - 1) {
1624  memcpy(hostbuf, hostinfo, eoh - hostinfo);
1625  hostbuf[eoh - hostinfo] = 0;
1626 
1627  c->http_error = 200;
1628  q = c->buffer;
1629  switch(redir_type) {
1630  case REDIR_ASX:
1631  snprintf(q, c->buffer_size,
1632  "HTTP/1.0 200 ASX Follows\r\n"
1633  "Content-type: video/x-ms-asf\r\n"
1634  "\r\n"
1635  "<ASX Version=\"3\">\r\n"
1636  //"<!-- Autogenerated by ffserver -->\r\n"
1637  "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1638  "</ASX>\r\n", hostbuf, filename, info);
1639  q += strlen(q);
1640  break;
1641  case REDIR_RAM:
1642  snprintf(q, c->buffer_size,
1643  "HTTP/1.0 200 RAM Follows\r\n"
1644  "Content-type: audio/x-pn-realaudio\r\n"
1645  "\r\n"
1646  "# Autogenerated by ffserver\r\n"
1647  "http://%s/%s%s\r\n", hostbuf, filename, info);
1648  q += strlen(q);
1649  break;
1650  case REDIR_ASF:
1651  snprintf(q, c->buffer_size,
1652  "HTTP/1.0 200 ASF Redirect follows\r\n"
1653  "Content-type: video/x-ms-asf\r\n"
1654  "\r\n"
1655  "[Reference]\r\n"
1656  "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1657  q += strlen(q);
1658  break;
1659  case REDIR_RTSP:
1660  {
1661  char hostname[256], *p;
1662  /* extract only hostname */
1663  av_strlcpy(hostname, hostbuf, sizeof(hostname));
1664  p = strrchr(hostname, ':');
1665  if (p)
1666  *p = '\0';
1667  snprintf(q, c->buffer_size,
1668  "HTTP/1.0 200 RTSP Redirect follows\r\n"
1669  /* XXX: incorrect MIME type ? */
1670  "Content-type: application/x-rtsp\r\n"
1671  "\r\n"
1672  "rtsp://%s:%d/%s\r\n", hostname, ntohs(config.rtsp_addr.sin_port), filename);
1673  q += strlen(q);
1674  }
1675  break;
1676  case REDIR_SDP:
1677  {
1678  uint8_t *sdp_data;
1679  int sdp_data_size;
1680  socklen_t len;
1681  struct sockaddr_in my_addr;
1682 
1683  snprintf(q, c->buffer_size,
1684  "HTTP/1.0 200 OK\r\n"
1685  "Content-type: application/sdp\r\n"
1686  "\r\n");
1687  q += strlen(q);
1688 
1689  len = sizeof(my_addr);
1690 
1691  /* XXX: Should probably fail? */
1692  if (getsockname(c->fd, (struct sockaddr *)&my_addr, &len))
1693  http_log("getsockname() failed\n");
1694 
1695  /* XXX: should use a dynamic buffer */
1696  sdp_data_size = prepare_sdp_description(stream,
1697  &sdp_data,
1698  my_addr.sin_addr);
1699  if (sdp_data_size > 0) {
1700  memcpy(q, sdp_data, sdp_data_size);
1701  q += sdp_data_size;
1702  *q = '\0';
1703  av_freep(&sdp_data);
1704  }
1705  }
1706  break;
1707  default:
1708  abort();
1709  break;
1710  }
1711 
1712  /* prepare output buffer */
1713  c->buffer_ptr = c->buffer;
1714  c->buffer_end = q;
1716  return 0;
1717  }
1718  }
1719  }
1720 
1721  snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
1722  goto send_error;
1723  }
1724 
1725  stream->conns_served++;
1726 
1727  /* XXX: add there authenticate and IP match */
1728 
1729  if (c->post) {
1730  /* if post, it means a feed is being sent */
1731  if (!stream->is_feed) {
1732  /* However it might be a status report from WMP! Let us log the
1733  * data as it might come handy one day. */
1734  const char *logline = 0;
1735  int client_id = 0;
1736 
1737  for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1738  if (av_strncasecmp(p, "Pragma: log-line=", 17) == 0) {
1739  logline = p;
1740  break;
1741  }
1742  if (av_strncasecmp(p, "Pragma: client-id=", 18) == 0)
1743  client_id = strtol(p + 18, 0, 10);
1744  p = strchr(p, '\n');
1745  if (!p)
1746  break;
1747 
1748  p++;
1749  }
1750 
1751  if (logline) {
1752  char *eol = strchr(logline, '\n');
1753 
1754  logline += 17;
1755 
1756  if (eol) {
1757  if (eol[-1] == '\r')
1758  eol--;
1759  http_log("%.*s\n", (int) (eol - logline), logline);
1760  c->suppress_log = 1;
1761  }
1762  }
1763 
1764 #ifdef DEBUG
1765  http_log("\nGot request:\n%s\n", c->buffer);
1766 #endif
1767 
1768  if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1769  HTTPContext *wmpc;
1770 
1771  /* Now we have to find the client_id */
1772  for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
1773  if (wmpc->wmp_client_id == client_id)
1774  break;
1775  }
1776 
1777  if (wmpc && modify_current_stream(wmpc, ratebuf))
1778  wmpc->switch_pending = 1;
1779  }
1780 
1781  snprintf(msg, sizeof(msg), "POST command not handled");
1782  c->stream = 0;
1783  goto send_error;
1784  }
1785  if (http_start_receive_data(c) < 0) {
1786  snprintf(msg, sizeof(msg), "could not open feed");
1787  goto send_error;
1788  }
1789  c->http_error = 0;
1791  return 0;
1792  }
1793 
1794 #ifdef DEBUG
1795  if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0)
1796  http_log("\nGot request:\n%s\n", c->buffer);
1797 #endif
1798 
1800  goto send_status;
1801 
1802  /* open input stream */
1803  if (open_input_stream(c, info) < 0) {
1804  snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
1805  goto send_error;
1806  }
1807 
1808  /* prepare HTTP header */
1809  c->buffer[0] = 0;
1810  av_strlcatf(c->buffer, c->buffer_size, "HTTP/1.0 200 OK\r\n");
1811  mime_type = c->stream->fmt->mime_type;
1812  if (!mime_type)
1813  mime_type = "application/x-octet-stream";
1814  av_strlcatf(c->buffer, c->buffer_size, "Pragma: no-cache\r\n");
1815 
1816  /* for asf, we need extra headers */
1817  if (!strcmp(c->stream->fmt->name,"asf_stream")) {
1818  /* Need to allocate a client id */
1819 
1820  c->wmp_client_id = av_lfg_get(&random_state);
1821 
1822  av_strlcatf(c->buffer, c->buffer_size, "Server: Cougar 4.1.0.3923\r\nCache-Control: no-cache\r\nPragma: client-id=%d\r\nPragma: features=\"broadcast\"\r\n", c->wmp_client_id);
1823  }
1824  av_strlcatf(c->buffer, c->buffer_size, "Content-Type: %s\r\n", mime_type);
1825  av_strlcatf(c->buffer, c->buffer_size, "\r\n");
1826  q = c->buffer + strlen(c->buffer);
1827 
1828  /* prepare output buffer */
1829  c->http_error = 0;
1830  c->buffer_ptr = c->buffer;
1831  c->buffer_end = q;
1833  return 0;
1834  send_error:
1835  c->http_error = 404;
1836  q = c->buffer;
1837  if (!htmlencode(msg, &encoded_msg)) {
1838  http_log("Could not encode filename '%s' as HTML\n", msg);
1839  }
1840  snprintf(q, c->buffer_size,
1841  "HTTP/1.0 404 Not Found\r\n"
1842  "Content-type: text/html\r\n"
1843  "\r\n"
1844  "<!DOCTYPE html>\n"
1845  "<html>\n"
1846  "<head>\n"
1847  "<meta charset=\"UTF-8\">\n"
1848  "<title>404 Not Found</title>\n"
1849  "</head>\n"
1850  "<body>%s</body>\n"
1851  "</html>\n", encoded_msg? encoded_msg : "File not found");
1852  q += strlen(q);
1853  /* prepare output buffer */
1854  c->buffer_ptr = c->buffer;
1855  c->buffer_end = q;
1857  av_freep(&encoded_msg);
1858  return 0;
1859  send_status:
1860  compute_status(c);
1861  /* horrible: we use this value to avoid
1862  * going to the send data state */
1863  c->http_error = 200;
1865  return 0;
1866 }
1867 
1868 static void fmt_bytecount(AVIOContext *pb, int64_t count)
1869 {
1870  static const char suffix[] = " kMGTP";
1871  const char *s;
1872 
1873  for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1874 
1875  avio_printf(pb, "%"PRId64"%c", count, *s);
1876 }
1877 
1878 static inline void print_stream_params(AVIOContext *pb, FFServerStream *stream)
1879 {
1880  int i, stream_no;
1881  const char *type = "unknown";
1882  char parameters[64];
1883  LayeredAVStream *st;
1884  AVCodec *codec;
1885 
1886  stream_no = stream->nb_streams;
1887 
1888  avio_printf(pb, "<table><tr><th>Stream<th>"
1889  "type<th>kbit/s<th>codec<th>"
1890  "Parameters\n");
1891 
1892  for (i = 0; i < stream_no; i++) {
1893  st = stream->streams[i];
1894  codec = avcodec_find_encoder(st->codecpar->codec_id);
1895 
1896  parameters[0] = 0;
1897 
1898  switch(st->codecpar->codec_type) {
1899  case AVMEDIA_TYPE_AUDIO:
1900  type = "audio";
1901  snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz",
1902  st->codecpar->channels, st->codecpar->sample_rate);
1903  break;
1904  case AVMEDIA_TYPE_VIDEO:
1905  type = "video";
1906  snprintf(parameters, sizeof(parameters),
1907  "%dx%d, q=%d-%d, fps=%d", st->codecpar->width,
1908  st->codecpar->height, st->codec->qmin, st->codec->qmax,
1909  st->time_base.den / st->time_base.num);
1910  break;
1911  default:
1912  abort();
1913  }
1914 
1915  avio_printf(pb, "<tr><td>%d<td>%s<td>%"PRId64
1916  "<td>%s<td>%s\n",
1917  i, type, (int64_t)st->codecpar->bit_rate/1000,
1918  codec ? codec->name : "", parameters);
1919  }
1920 
1921  avio_printf(pb, "</table>\n");
1922 }
1923 
1924 static void clean_html(char *clean, int clean_len, char *dirty)
1925 {
1926  int i, o;
1927 
1928  for (o = i = 0; o+10 < clean_len && dirty[i];) {
1929  int len = strspn(dirty+i, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$-_.+!*(),?/ :;%");
1930  if (len) {
1931  if (o + len >= clean_len)
1932  break;
1933  memcpy(clean + o, dirty + i, len);
1934  i += len;
1935  o += len;
1936  } else {
1937  int c = dirty[i++];
1938  switch (c) {
1939  case '&': av_strlcat(clean+o, "&amp;" , clean_len - o); break;
1940  case '<': av_strlcat(clean+o, "&lt;" , clean_len - o); break;
1941  case '>': av_strlcat(clean+o, "&gt;" , clean_len - o); break;
1942  case '\'': av_strlcat(clean+o, "&apos;" , clean_len - o); break;
1943  case '\"': av_strlcat(clean+o, "&quot;" , clean_len - o); break;
1944  default: av_strlcat(clean+o, "&#9785;", clean_len - o); break;
1945  }
1946  o += strlen(clean+o);
1947  }
1948  }
1949  clean[o] = 0;
1950 }
1951 
1953 {
1954  HTTPContext *c1;
1955  FFServerStream *stream;
1956  char *p;
1957  time_t ti;
1958  int i, len;
1959  AVIOContext *pb;
1960 
1961  if (avio_open_dyn_buf(&pb) < 0) {
1962  /* XXX: return an error ? */
1963  c->buffer_ptr = c->buffer;
1964  c->buffer_end = c->buffer;
1965  return;
1966  }
1967 
1968  avio_printf(pb, "HTTP/1.0 200 OK\r\n");
1969  avio_printf(pb, "Content-type: text/html\r\n");
1970  avio_printf(pb, "Pragma: no-cache\r\n");
1971  avio_printf(pb, "\r\n");
1972 
1973  avio_printf(pb, "<!DOCTYPE html>\n");
1974  avio_printf(pb, "<html><head><title>%s Status</title>\n", program_name);
1975  if (c->stream->feed_filename[0])
1976  avio_printf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n",
1977  c->stream->feed_filename);
1978  avio_printf(pb, "</head>\n<body>");
1979  avio_printf(pb, "<h1>%s Status</h1>\n", program_name);
1980  /* format status */
1981  avio_printf(pb, "<h2>Available Streams</h2>\n");
1982  avio_printf(pb, "<table>\n");
1983  avio_printf(pb, "<tr><th>Path<th>Served<br>Conns<th><br>bytes<th>Format<th>Bit rate<br>kbit/s<th>Video<br>kbit/s<th><br>Codec<th>Audio<br>kbit/s<th><br>Codec<th>Feed\n");
1984  stream = config.first_stream;
1985  while (stream) {
1986  char sfilename[1024];
1987  char *eosf;
1988 
1989  if (stream->feed == stream) {
1990  stream = stream->next;
1991  continue;
1992  }
1993 
1994  av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
1995  eosf = sfilename + strlen(sfilename);
1996  if (eosf - sfilename >= 4) {
1997  if (strcmp(eosf - 4, ".asf") == 0)
1998  strcpy(eosf - 4, ".asx");
1999  else if (strcmp(eosf - 3, ".rm") == 0)
2000  strcpy(eosf - 3, ".ram");
2001  else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
2002  /* generate a sample RTSP director if
2003  * unicast. Generate an SDP redirector if
2004  * multicast */
2005  eosf = strrchr(sfilename, '.');
2006  if (!eosf)
2007  eosf = sfilename + strlen(sfilename);
2008  if (stream->is_multicast)
2009  strcpy(eosf, ".sdp");
2010  else
2011  strcpy(eosf, ".rtsp");
2012  }
2013  }
2014 
2015  avio_printf(pb, "<tr><td><a href=\"/%s\">%s</a> ",
2016  sfilename, stream->filename);
2017  avio_printf(pb, "<td> %d <td> ",
2018  stream->conns_served);
2019  // TODO: Investigate if we can make http bitexact so it always produces the same count of bytes
2020  if (!config.bitexact)
2021  fmt_bytecount(pb, stream->bytes_served);
2022 
2023  switch(stream->stream_type) {
2024  case STREAM_TYPE_LIVE: {
2025  int audio_bit_rate = 0;
2026  int video_bit_rate = 0;
2027  const char *audio_codec_name = "";
2028  const char *video_codec_name = "";
2029  const char *audio_codec_name_extra = "";
2030  const char *video_codec_name_extra = "";
2031 
2032  for(i=0;i<stream->nb_streams;i++) {
2033  LayeredAVStream *st = stream->streams[i];
2035 
2036  switch(st->codecpar->codec_type) {
2037  case AVMEDIA_TYPE_AUDIO:
2038  audio_bit_rate += st->codecpar->bit_rate;
2039  if (codec) {
2040  if (*audio_codec_name)
2041  audio_codec_name_extra = "...";
2042  audio_codec_name = codec->name;
2043  }
2044  break;
2045  case AVMEDIA_TYPE_VIDEO:
2046  video_bit_rate += st->codecpar->bit_rate;
2047  if (codec) {
2048  if (*video_codec_name)
2049  video_codec_name_extra = "...";
2050  video_codec_name = codec->name;
2051  }
2052  break;
2053  case AVMEDIA_TYPE_DATA:
2054  video_bit_rate += st->codecpar->bit_rate;
2055  break;
2056  default:
2057  abort();
2058  }
2059  }
2060 
2061  avio_printf(pb, "<td> %s <td> %d <td> %d <td> %s %s <td> "
2062  "%d <td> %s %s",
2063  stream->fmt->name, stream->bandwidth,
2064  video_bit_rate / 1000, video_codec_name,
2065  video_codec_name_extra, audio_bit_rate / 1000,
2066  audio_codec_name, audio_codec_name_extra);
2067 
2068  if (stream->feed)
2069  avio_printf(pb, "<td>%s", stream->feed->filename);
2070  else
2071  avio_printf(pb, "<td>%s", stream->feed_filename);
2072  avio_printf(pb, "\n");
2073  }
2074  break;
2075  default:
2076  avio_printf(pb, "<td> - <td> - "
2077  "<td> - <td><td> - <td>\n");
2078  break;
2079  }
2080  stream = stream->next;
2081  }
2082  avio_printf(pb, "</table>\n");
2083 
2084  stream = config.first_stream;
2085  while (stream) {
2086 
2087  if (stream->feed != stream) {
2088  stream = stream->next;
2089  continue;
2090  }
2091 
2092  avio_printf(pb, "<h2>Feed %s</h2>", stream->filename);
2093  if (stream->pid) {
2094  avio_printf(pb, "Running as pid %"PRId64".\n", (int64_t) stream->pid);
2095 
2096 #if defined(linux)
2097  {
2098  FILE *pid_stat;
2099  char ps_cmd[64];
2100 
2101  /* This is somewhat linux specific I guess */
2102  snprintf(ps_cmd, sizeof(ps_cmd),
2103  "ps -o \"%%cpu,cputime\" --no-headers %"PRId64"",
2104  (int64_t) stream->pid);
2105 
2106  pid_stat = popen(ps_cmd, "r");
2107  if (pid_stat) {
2108  char cpuperc[10];
2109  char cpuused[64];
2110 
2111  if (fscanf(pid_stat, "%9s %63s", cpuperc, cpuused) == 2) {
2112  avio_printf(pb, "Currently using %s%% of the cpu. "
2113  "Total time used %s.\n",
2114  cpuperc, cpuused);
2115  }
2116  fclose(pid_stat);
2117  }
2118  }
2119 #endif
2120 
2121  avio_printf(pb, "<p>");
2122  }
2123 
2124  print_stream_params(pb, stream);
2125  stream = stream->next;
2126  }
2127 
2128  /* connection status */
2129  avio_printf(pb, "<h2>Connection Status</h2>\n");
2130 
2131  avio_printf(pb, "Number of connections: %d / %d<br>\n",
2133 
2134  avio_printf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<br>\n",
2136 
2137  avio_printf(pb, "<table>\n");
2138  avio_printf(pb, "<tr><th>#<th>File<th>IP<th>URL<th>Proto<th>State<th>Target "
2139  "bit/s<th>Actual bit/s<th>Bytes transferred\n");
2140  c1 = first_http_ctx;
2141  i = 0;
2142  while (c1) {
2143  int bitrate;
2144  int j;
2145 
2146  bitrate = 0;
2147  if (c1->stream) {
2148  for (j = 0; j < c1->stream->nb_streams; j++) {
2149  if (!c1->stream->feed)
2150  bitrate += c1->stream->streams[j]->codecpar->bit_rate;
2151  else if (c1->feed_streams[j] >= 0)
2152  bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codecpar->bit_rate;
2153  }
2154  }
2155 
2156  i++;
2157  p = inet_ntoa(c1->from_addr.sin_addr);
2158  clean_html(c1->clean_url, sizeof(c1->clean_url), c1->url);
2159  avio_printf(pb, "<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td>%s"
2160  "<td>",
2161  i, c1->stream ? c1->stream->filename : "",
2162  c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
2163  p,
2164  c1->clean_url,
2165  c1->protocol, http_state[c1->state]);
2166  fmt_bytecount(pb, bitrate);
2167  avio_printf(pb, "<td>");
2168  fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
2169  avio_printf(pb, "<td>");
2170  fmt_bytecount(pb, c1->data_count);
2171  avio_printf(pb, "\n");
2172  c1 = c1->next;
2173  }
2174  avio_printf(pb, "</table>\n");
2175 
2176  if (!config.bitexact) {
2177  /* date */
2178  ti = time(NULL);
2179  p = ctime(&ti);
2180  avio_printf(pb, "<hr>Generated at %s", p);
2181  }
2182  avio_printf(pb, "</body>\n</html>\n");
2183 
2184  len = avio_close_dyn_buf(pb, &c->pb_buffer);
2185  c->buffer_ptr = c->pb_buffer;
2186  c->buffer_end = c->pb_buffer + len;
2187 }
2188 
2189 static int open_input_stream(HTTPContext *c, const char *info)
2190 {
2191  char buf[128];
2192  char input_filename[1024];
2193  AVFormatContext *s = NULL;
2194  int buf_size, i, ret;
2195  int64_t stream_pos;
2196 
2197  /* find file name */
2198  if (c->stream->feed) {
2199  strcpy(input_filename, c->stream->feed->feed_filename);
2200  buf_size = FFM_PACKET_SIZE;
2201  /* compute position (absolute time) */
2202  if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2203  if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0) {
2204  http_log("Invalid date specification '%s' for stream\n", buf);
2205  return ret;
2206  }
2207  } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) {
2208  int prebuffer = strtol(buf, 0, 10);
2209  stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
2210  } else
2211  stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
2212  } else {
2213  strcpy(input_filename, c->stream->feed_filename);
2214  buf_size = 0;
2215  /* compute position (relative time) */
2216  if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2217  if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0) {
2218  http_log("Invalid date specification '%s' for stream\n", buf);
2219  return ret;
2220  }
2221  } else
2222  stream_pos = 0;
2223  }
2224  if (!input_filename[0]) {
2225  http_log("No filename was specified for stream\n");
2226  return AVERROR(EINVAL);
2227  }
2228 
2229  /* open stream */
2230  ret = avformat_open_input(&s, input_filename, c->stream->ifmt,
2231  &c->stream->in_opts);
2232  if (ret < 0) {
2233  http_log("Could not open input '%s': %s\n",
2234  input_filename, av_err2str(ret));
2235  return ret;
2236  }
2237 
2238  /* set buffer size */
2239  if (buf_size > 0) {
2240  ret = ffio_set_buf_size(s->pb, buf_size);
2241  if (ret < 0) {
2242  http_log("Failed to set buffer size\n");
2243  return ret;
2244  }
2245  }
2246 
2247  s->flags |= AVFMT_FLAG_GENPTS;
2248  c->fmt_in = s;
2249  if (strcmp(s->iformat->name, "ffm") &&
2250  (ret = avformat_find_stream_info(c->fmt_in, NULL)) < 0) {
2251  http_log("Could not find stream info for input '%s'\n", input_filename);
2253  return ret;
2254  }
2255 
2256  /* choose stream as clock source (we favor the video stream if
2257  * present) for packet sending */
2258  c->pts_stream_index = 0;
2259  for(i=0;i<c->stream->nb_streams;i++) {
2260  if (c->pts_stream_index == 0 &&
2262  c->pts_stream_index = i;
2263  }
2264  }
2265 
2266  if (c->fmt_in->iformat->read_seek)
2267  av_seek_frame(c->fmt_in, -1, stream_pos, 0);
2268  /* set the start time (needed for maxtime and RTP packet timing) */
2269  c->start_time = cur_time;
2271  return 0;
2272 }
2273 
2274 /* return the server clock (in us) */
2276 {
2277  /* compute current pts value from system time */
2278  return (cur_time - c->start_time) * 1000;
2279 }
2280 
2281 /* return the estimated time (in us) at which the current packet must be sent */
2283 {
2284  int bytes_left, bytes_sent, frame_bytes;
2285 
2286  frame_bytes = c->cur_frame_bytes;
2287  if (frame_bytes <= 0)
2288  return c->cur_pts;
2289 
2290  bytes_left = c->buffer_end - c->buffer_ptr;
2291  bytes_sent = frame_bytes - bytes_left;
2292  return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
2293 }
2294 
2295 
2297 {
2298  int i, len, ret;
2300 
2301  av_freep(&c->pb_buffer);
2302  switch(c->state) {
2304  ctx = avformat_alloc_context();
2305  if (!ctx)
2306  return AVERROR(ENOMEM);
2307  c->pfmt_ctx = ctx;
2308  av_dict_copy(&(c->pfmt_ctx->metadata), c->stream->metadata, 0);
2309 
2310  for(i=0;i<c->stream->nb_streams;i++) {
2313  if (!st)
2314  return AVERROR(ENOMEM);
2315 
2316  /* if file or feed, then just take streams from FFServerStream
2317  * struct */
2318  if (!c->stream->feed ||
2319  c->stream->feed == c->stream)
2320  src = c->stream->streams[i];
2321  else
2322  src = c->stream->feed->streams[c->stream->feed_streams[i]];
2323 
2324  unlayer_stream(c->pfmt_ctx->streams[i], src); //TODO we no longer copy st->internal, does this matter?
2326 
2327  if (src->codec->flags & AV_CODEC_FLAG_BITEXACT)
2329  }
2330  /* set output format parameters */
2331  c->pfmt_ctx->oformat = c->stream->fmt;
2333 
2334  c->got_key_frame = 0;
2335 
2336  /* prepare header and save header data in a stream */
2337  if (avio_open_dyn_buf(&c->pfmt_ctx->pb) < 0) {
2338  /* XXX: potential leak */
2339  return -1;
2340  }
2341  c->pfmt_ctx->pb->seekable = 0;
2342 
2343  /*
2344  * HACK to avoid MPEG-PS muxer to spit many underflow errors
2345  * Default value from FFmpeg
2346  * Try to set it using configuration option
2347  */
2348  c->pfmt_ctx->max_delay = (int)(0.7*AV_TIME_BASE);
2349 
2350  if ((ret = avformat_write_header(c->pfmt_ctx, NULL)) < 0) {
2351  http_log("Error writing output header for stream '%s': %s\n",
2352  c->stream->filename, av_err2str(ret));
2353  return ret;
2354  }
2356 
2357  len = avio_close_dyn_buf(c->pfmt_ctx->pb, &c->pb_buffer);
2358  c->buffer_ptr = c->pb_buffer;
2359  c->buffer_end = c->pb_buffer + len;
2360 
2362  c->last_packet_sent = 0;
2363  break;
2364  case HTTPSTATE_SEND_DATA:
2365  /* find a new packet */
2366  /* read a packet from the input stream */
2367  if (c->stream->feed)
2370  c->stream->feed->feed_size);
2371 
2372  if (c->stream->max_time &&
2373  c->stream->max_time + c->start_time - cur_time < 0)
2374  /* We have timed out */
2376  else {
2377  AVPacket pkt;
2378  redo:
2379  ret = av_read_frame(c->fmt_in, &pkt);
2380  if (ret < 0) {
2381  if (c->stream->feed) {
2382  /* if coming from feed, it means we reached the end of the
2383  * ffm file, so must wait for more data */
2385  return 1; /* state changed */
2386  }
2387  if (ret == AVERROR(EAGAIN)) {
2388  /* input not ready, come back later */
2389  return 0;
2390  }
2391  if (c->stream->loop) {
2393  if (open_input_stream(c, "") < 0)
2394  goto no_loop;
2395  goto redo;
2396  } else {
2397  no_loop:
2398  /* must send trailer now because EOF or error */
2400  }
2401  } else {
2402  int source_index = pkt.stream_index;
2403  /* update first pts if needed */
2404  if (c->first_pts == AV_NOPTS_VALUE && pkt.dts != AV_NOPTS_VALUE) {
2406  c->start_time = cur_time;
2407  }
2408  /* send it to the appropriate stream */
2409  if (c->stream->feed) {
2410  /* if coming from a feed, select the right stream */
2411  if (c->switch_pending) {
2412  c->switch_pending = 0;
2413  for(i=0;i<c->stream->nb_streams;i++) {
2414  if (c->switch_feed_streams[i] == pkt.stream_index)
2415  if (pkt.flags & AV_PKT_FLAG_KEY)
2416  c->switch_feed_streams[i] = -1;
2417  if (c->switch_feed_streams[i] >= 0)
2418  c->switch_pending = 1;
2419  }
2420  }
2421  for(i=0;i<c->stream->nb_streams;i++) {
2422  if (c->stream->feed_streams[i] == pkt.stream_index) {
2423  AVStream *st = c->fmt_in->streams[source_index];
2424  pkt.stream_index = i;
2425  if (pkt.flags & AV_PKT_FLAG_KEY &&
2427  c->stream->nb_streams == 1))
2428  c->got_key_frame = 1;
2429  if (!c->stream->send_on_key || c->got_key_frame)
2430  goto send_it;
2431  }
2432  }
2433  } else {
2434  AVStream *ist, *ost;
2435  send_it:
2436  ist = c->fmt_in->streams[source_index];
2437  /* specific handling for RTP: we use several
2438  * output streams (one for each RTP connection).
2439  * XXX: need more abstract handling */
2440  if (c->is_packetized) {
2441  /* compute send time and duration */
2442  if (pkt.dts != AV_NOPTS_VALUE) {
2443  c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
2444  c->cur_pts -= c->first_pts;
2445  }
2447  /* find RTP context */
2449  ctx = c->rtp_ctx[c->packet_stream_index];
2450  if(!ctx) {
2451  av_packet_unref(&pkt);
2452  break;
2453  }
2454  /* only one stream per RTP connection */
2455  pkt.stream_index = 0;
2456  } else {
2457  ctx = c->pfmt_ctx;
2458  /* Fudge here */
2459  }
2460 
2461  if (c->is_packetized) {
2462  int max_packet_size;
2464  max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2465  else
2466  max_packet_size = c->rtp_handles[c->packet_stream_index]->max_packet_size;
2467  ret = ffio_open_dyn_packet_buf(&ctx->pb,
2468  max_packet_size);
2469  } else
2470  ret = avio_open_dyn_buf(&ctx->pb);
2471 
2472  if (ret < 0) {
2473  /* XXX: potential leak */
2474  return -1;
2475  }
2476  ost = ctx->streams[pkt.stream_index];
2477 
2478  ctx->pb->seekable = 0;
2479  if (pkt.dts != AV_NOPTS_VALUE)
2480  pkt.dts = av_rescale_q(pkt.dts, ist->time_base,
2481  ost->time_base);
2482  if (pkt.pts != AV_NOPTS_VALUE)
2483  pkt.pts = av_rescale_q(pkt.pts, ist->time_base,
2484  ost->time_base);
2485  pkt.duration = av_rescale_q(pkt.duration, ist->time_base,
2486  ost->time_base);
2487  if ((ret = av_write_frame(ctx, &pkt)) < 0) {
2488  http_log("Error writing frame to output for stream '%s': %s\n",
2489  c->stream->filename, av_err2str(ret));
2491  }
2492 
2493  av_freep(&c->pb_buffer);
2494  len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2495  ctx->pb = NULL;
2496  c->cur_frame_bytes = len;
2497  c->buffer_ptr = c->pb_buffer;
2498  c->buffer_end = c->pb_buffer + len;
2499 
2500  if (len == 0) {
2501  av_packet_unref(&pkt);
2502  goto redo;
2503  }
2504  }
2505  av_packet_unref(&pkt);
2506  }
2507  }
2508  break;
2509  default:
2511  /* last packet test ? */
2512  if (c->last_packet_sent || c->is_packetized)
2513  return -1;
2514  ctx = c->pfmt_ctx;
2515  /* prepare header */
2516  if (avio_open_dyn_buf(&ctx->pb) < 0) {
2517  /* XXX: potential leak */
2518  return -1;
2519  }
2520  c->pfmt_ctx->pb->seekable = 0;
2521  av_write_trailer(ctx);
2522  len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2523  c->buffer_ptr = c->pb_buffer;
2524  c->buffer_end = c->pb_buffer + len;
2525 
2526  c->last_packet_sent = 1;
2527  break;
2528  }
2529  return 0;
2530 }
2531 
2532 /* should convert the format at the same time */
2533 /* send data starting at c->buffer_ptr to the output connection
2534  * (either UDP or TCP)
2535  */
2537 {
2538  int len, ret;
2539 
2540  for(;;) {
2541  if (c->buffer_ptr >= c->buffer_end) {
2542  ret = http_prepare_data(c);
2543  if (ret < 0)
2544  return -1;
2545  else if (ret)
2546  /* state change requested */
2547  break;
2548  } else {
2549  if (c->is_packetized) {
2550  /* RTP data output */
2551  len = c->buffer_end - c->buffer_ptr;
2552  if (len < 4) {
2553  /* fail safe - should never happen */
2554  fail1:
2555  c->buffer_ptr = c->buffer_end;
2556  return 0;
2557  }
2558  len = (c->buffer_ptr[0] << 24) |
2559  (c->buffer_ptr[1] << 16) |
2560  (c->buffer_ptr[2] << 8) |
2561  (c->buffer_ptr[3]);
2562  if (len > (c->buffer_end - c->buffer_ptr))
2563  goto fail1;
2564  if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2565  /* nothing to send yet: we can wait */
2566  return 0;
2567  }
2568 
2569  c->data_count += len;
2571  if (c->stream)
2572  c->stream->bytes_served += len;
2573 
2575  /* RTP packets are sent inside the RTSP TCP connection */
2576  AVIOContext *pb;
2577  int interleaved_index, size;
2578  uint8_t header[4];
2579  HTTPContext *rtsp_c;
2580 
2581  rtsp_c = c->rtsp_c;
2582  /* if no RTSP connection left, error */
2583  if (!rtsp_c)
2584  return -1;
2585  /* if already sending something, then wait. */
2586  if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2587  break;
2588  if (avio_open_dyn_buf(&pb) < 0)
2589  goto fail1;
2590  interleaved_index = c->packet_stream_index * 2;
2591  /* RTCP packets are sent at odd indexes */
2592  if (c->buffer_ptr[1] == 200)
2593  interleaved_index++;
2594  /* write RTSP TCP header */
2595  header[0] = '$';
2596  header[1] = interleaved_index;
2597  header[2] = len >> 8;
2598  header[3] = len;
2599  avio_write(pb, header, 4);
2600  /* write RTP packet data */
2601  c->buffer_ptr += 4;
2602  avio_write(pb, c->buffer_ptr, len);
2603  size = avio_close_dyn_buf(pb, &c->packet_buffer);
2604  /* prepare asynchronous TCP sending */
2605  rtsp_c->packet_buffer_ptr = c->packet_buffer;
2606  rtsp_c->packet_buffer_end = c->packet_buffer + size;
2607  c->buffer_ptr += len;
2608 
2609  /* send everything we can NOW */
2610  len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2611  rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2612  if (len > 0)
2613  rtsp_c->packet_buffer_ptr += len;
2614  if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2615  /* if we could not send all the data, we will
2616  * send it later, so a new state is needed to
2617  * "lock" the RTSP TCP connection */
2618  rtsp_c->state = RTSPSTATE_SEND_PACKET;
2619  break;
2620  } else
2621  /* all data has been sent */
2622  av_freep(&c->packet_buffer);
2623  } else {
2624  /* send RTP packet directly in UDP */
2625  c->buffer_ptr += 4;
2627  c->buffer_ptr, len);
2628  c->buffer_ptr += len;
2629  /* here we continue as we can send several packets
2630  * per 10 ms slot */
2631  }
2632  } else {
2633  /* TCP data output */
2634  len = send(c->fd, c->buffer_ptr,
2635  c->buffer_end - c->buffer_ptr, 0);
2636  if (len < 0) {
2637  if (ff_neterrno() != AVERROR(EAGAIN) &&
2638  ff_neterrno() != AVERROR(EINTR))
2639  /* error : close connection */
2640  return -1;
2641  else
2642  return 0;
2643  }
2644  c->buffer_ptr += len;
2645 
2646  c->data_count += len;
2648  if (c->stream)
2649  c->stream->bytes_served += len;
2650  break;
2651  }
2652  }
2653  } /* for(;;) */
2654  return 0;
2655 }
2656 
2658 {
2659  int fd;
2660  int ret;
2661  int64_t ret64;
2662 
2663  if (c->stream->feed_opened) {
2664  http_log("Stream feed '%s' was not opened\n",
2665  c->stream->feed_filename);
2666  return AVERROR(EINVAL);
2667  }
2668 
2669  /* Don't permit writing to this one */
2670  if (c->stream->readonly) {
2671  http_log("Cannot write to read-only file '%s'\n",
2672  c->stream->feed_filename);
2673  return AVERROR(EINVAL);
2674  }
2675 
2676  /* open feed */
2677  fd = open(c->stream->feed_filename, O_RDWR);
2678  if (fd < 0) {
2679  ret = AVERROR(errno);
2680  http_log("Could not open feed file '%s': %s\n",
2681  c->stream->feed_filename, strerror(errno));
2682  return ret;
2683  }
2684  c->feed_fd = fd;
2685 
2686  if (c->stream->truncate) {
2687  /* truncate feed file */
2689  http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2690  if (ftruncate(c->feed_fd, FFM_PACKET_SIZE) < 0) {
2691  ret = AVERROR(errno);
2692  http_log("Error truncating feed file '%s': %s\n",
2693  c->stream->feed_filename, strerror(errno));
2694  return ret;
2695  }
2696  } else {
2697  ret64 = ffm_read_write_index(fd);
2698  if (ret64 < 0) {
2699  http_log("Error reading write index from feed file '%s': %s\n",
2700  c->stream->feed_filename, strerror(errno));
2701  return ret64;
2702  }
2703  c->stream->feed_write_index = ret64;
2704  }
2705 
2707  FFM_PACKET_SIZE);
2708  c->stream->feed_size = lseek(fd, 0, SEEK_END);
2709  lseek(fd, 0, SEEK_SET);
2710 
2711  /* init buffer input */
2712  c->buffer_ptr = c->buffer;
2713  c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2714  c->stream->feed_opened = 1;
2715  c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2716  return 0;
2717 }
2718 
2720 {
2721  HTTPContext *c1;
2722  int len, loop_run = 0;
2723 
2724  while (c->chunked_encoding && !c->chunk_size &&
2725  c->buffer_end > c->buffer_ptr) {
2726  /* read chunk header, if present */
2727  len = recv(c->fd, c->buffer_ptr, 1, 0);
2728 
2729  if (len < 0) {
2730  if (ff_neterrno() != AVERROR(EAGAIN) &&
2731  ff_neterrno() != AVERROR(EINTR))
2732  /* error : close connection */
2733  goto fail;
2734  return 0;
2735  } else if (len == 0) {
2736  /* end of connection : close it */
2737  goto fail;
2738  } else if (c->buffer_ptr - c->buffer >= 2 &&
2739  !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2740  c->chunk_size = strtol(c->buffer, 0, 16);
2741  if (c->chunk_size == 0) // end of stream
2742  goto fail;
2743  c->buffer_ptr = c->buffer;
2744  break;
2745  } else if (++loop_run > 10)
2746  /* no chunk header, abort */
2747  goto fail;
2748  else
2749  c->buffer_ptr++;
2750  }
2751 
2752  if (c->buffer_end > c->buffer_ptr) {
2753  len = recv(c->fd, c->buffer_ptr,
2754  FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2755  if (len < 0) {
2756  if (ff_neterrno() != AVERROR(EAGAIN) &&
2757  ff_neterrno() != AVERROR(EINTR))
2758  /* error : close connection */
2759  goto fail;
2760  } else if (len == 0)
2761  /* end of connection : close it */
2762  goto fail;
2763  else {
2764  c->chunk_size -= len;
2765  c->buffer_ptr += len;
2766  c->data_count += len;
2768  }
2769  }
2770 
2771  if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2772  if (c->buffer[0] != 'f' ||
2773  c->buffer[1] != 'm') {
2774  http_log("Feed stream has become desynchronized -- disconnecting\n");
2775  goto fail;
2776  }
2777  }
2778 
2779  if (c->buffer_ptr >= c->buffer_end) {
2780  FFServerStream *feed = c->stream;
2781  /* a packet has been received : write it in the store, except
2782  * if header */
2783  if (c->data_count > FFM_PACKET_SIZE) {
2784  /* XXX: use llseek or url_seek
2785  * XXX: Should probably fail? */
2786  if (lseek(c->feed_fd, feed->feed_write_index, SEEK_SET) == -1)
2787  http_log("Seek to %"PRId64" failed\n", feed->feed_write_index);
2788 
2789  if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2790  http_log("Error writing to feed file: %s\n", strerror(errno));
2791  goto fail;
2792  }
2793 
2795  /* update file size */
2796  if (feed->feed_write_index > c->stream->feed_size)
2797  feed->feed_size = feed->feed_write_index;
2798 
2799  /* handle wrap around if max file size reached */
2800  if (c->stream->feed_max_size &&
2801  feed->feed_write_index >= c->stream->feed_max_size)
2803 
2804  /* write index */
2805  if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2806  http_log("Error writing index to feed file: %s\n",
2807  strerror(errno));
2808  goto fail;
2809  }
2810 
2811  /* wake up any waiting connections */
2812  for(c1 = first_http_ctx; c1; c1 = c1->next) {
2813  if (c1->state == HTTPSTATE_WAIT_FEED &&
2814  c1->stream->feed == c->stream->feed)
2815  c1->state = HTTPSTATE_SEND_DATA;
2816  }
2817  } else {
2818  /* We have a header in our hands that contains useful data */
2820  AVIOContext *pb;
2821  AVInputFormat *fmt_in;
2822  int i;
2823 
2824  if (!s)
2825  goto fail;
2826 
2827  /* use feed output format name to find corresponding input format */
2828  fmt_in = av_find_input_format(feed->fmt->name);
2829  if (!fmt_in)
2830  goto fail;
2831 
2832  pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
2833  0, NULL, NULL, NULL, NULL);
2834  if (!pb)
2835  goto fail;
2836 
2837  pb->seekable = 0;
2838 
2839  s->pb = pb;
2840  if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) {
2841  av_freep(&pb);
2842  goto fail;
2843  }
2844 
2845  /* Now we have the actual streams */
2846  if (s->nb_streams != feed->nb_streams) {
2848  av_freep(&pb);
2849  http_log("Feed '%s' stream number does not match registered feed\n",
2850  c->stream->feed_filename);
2851  goto fail;
2852  }
2853 
2854  for (i = 0; i < s->nb_streams; i++) {
2855  LayeredAVStream *fst = feed->streams[i];
2856  AVStream *st = s->streams[i];
2859  }
2860 
2862  av_freep(&pb);
2863  }
2864  c->buffer_ptr = c->buffer;
2865  }
2866 
2867  return 0;
2868  fail:
2869  c->stream->feed_opened = 0;
2870  close(c->feed_fd);
2871  /* wake up any waiting connections to stop waiting for feed */
2872  for(c1 = first_http_ctx; c1; c1 = c1->next) {
2873  if (c1->state == HTTPSTATE_WAIT_FEED &&
2874  c1->stream->feed == c->stream->feed)
2876  }
2877  return -1;
2878 }
2879 
2880 /********************************************************************/
2881 /* RTSP handling */
2882 
2883 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2884 {
2885  const char *str;
2886  time_t ti;
2887  struct tm *tm;
2888  char buf2[32];
2889 
2890  str = RTSP_STATUS_CODE2STRING(error_number);
2891  if (!str)
2892  str = "Unknown Error";
2893 
2894  avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2895  avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2896 
2897  /* output GMT time */
2898  ti = time(NULL);
2899  tm = gmtime(&ti);
2900  strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
2901  avio_printf(c->pb, "Date: %s GMT\r\n", buf2);
2902 }
2903 
2904 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2905 {
2906  rtsp_reply_header(c, error_number);
2907  avio_printf(c->pb, "\r\n");
2908 }
2909 
2911 {
2912  const char *p, *p1, *p2;
2913  char cmd[32];
2914  char url[1024];
2915  char protocol[32];
2916  char line[1024];
2917  int len;
2918  RTSPMessageHeader header1 = { 0 }, *header = &header1;
2919 
2920  c->buffer_ptr[0] = '\0';
2921  p = c->buffer;
2922 
2923  get_word(cmd, sizeof(cmd), &p);
2924  get_word(url, sizeof(url), &p);
2925  get_word(protocol, sizeof(protocol), &p);
2926 
2927  av_strlcpy(c->method, cmd, sizeof(c->method));
2928  av_strlcpy(c->url, url, sizeof(c->url));
2929  av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2930 
2931  if (avio_open_dyn_buf(&c->pb) < 0) {
2932  /* XXX: cannot do more */
2933  c->pb = NULL; /* safety */
2934  return -1;
2935  }
2936 
2937  /* check version name */
2938  if (strcmp(protocol, "RTSP/1.0")) {
2940  goto the_end;
2941  }
2942 
2943  /* parse each header line */
2944  /* skip to next line */
2945  while (*p != '\n' && *p != '\0')
2946  p++;
2947  if (*p == '\n')
2948  p++;
2949  while (*p != '\0') {
2950  p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
2951  if (!p1)
2952  break;
2953  p2 = p1;
2954  if (p2 > p && p2[-1] == '\r')
2955  p2--;
2956  /* skip empty line */
2957  if (p2 == p)
2958  break;
2959  len = p2 - p;
2960  if (len > sizeof(line) - 1)
2961  len = sizeof(line) - 1;
2962  memcpy(line, p, len);
2963  line[len] = '\0';
2965  p = p1 + 1;
2966  }
2967 
2968  /* handle sequence number */
2969  c->seq = header->seq;
2970 
2971  if (!strcmp(cmd, "DESCRIBE"))
2972  rtsp_cmd_describe(c, url);
2973  else if (!strcmp(cmd, "OPTIONS"))
2974  rtsp_cmd_options(c, url);
2975  else if (!strcmp(cmd, "SETUP"))
2976  rtsp_cmd_setup(c, url, header);
2977  else if (!strcmp(cmd, "PLAY"))
2978  rtsp_cmd_play(c, url, header);
2979  else if (!strcmp(cmd, "PAUSE"))
2980  rtsp_cmd_interrupt(c, url, header, 1);
2981  else if (!strcmp(cmd, "TEARDOWN"))
2982  rtsp_cmd_interrupt(c, url, header, 0);
2983  else
2985 
2986  the_end:
2987  len = avio_close_dyn_buf(c->pb, &c->pb_buffer);
2988  c->pb = NULL; /* safety */
2989  if (len < 0)
2990  /* XXX: cannot do more */
2991  return -1;
2992 
2993  c->buffer_ptr = c->pb_buffer;
2994  c->buffer_end = c->pb_buffer + len;
2996  return 0;
2997 }
2998 
2999 static int prepare_sdp_description(FFServerStream *stream, uint8_t **pbuffer,
3000  struct in_addr my_ip)
3001 {
3002  AVFormatContext *avc;
3003  AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);
3004  AVDictionaryEntry *entry = av_dict_get(stream->metadata, "title", NULL, 0);
3005  int i;
3006 
3007  *pbuffer = NULL;
3008 
3009  avc = avformat_alloc_context();
3010  if (!avc || !rtp_format)
3011  return -1;
3012 
3013  avc->oformat = rtp_format;
3014  av_dict_set(&avc->metadata, "title",
3015  entry ? entry->value : "No Title", 0);
3016  if (stream->is_multicast) {
3017  snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
3018  inet_ntoa(stream->multicast_ip),
3019  stream->multicast_port, stream->multicast_ttl);
3020  } else
3021  snprintf(avc->filename, 1024, "rtp://0.0.0.0");
3022 
3023  for(i = 0; i < stream->nb_streams; i++) {
3024  AVStream *st = avformat_new_stream(avc, NULL);
3025  if (!st)
3026  goto sdp_done;
3027  avcodec_parameters_from_context(stream->streams[i]->codecpar, stream->streams[i]->codec);
3028  unlayer_stream(st, stream->streams[i]);
3029  }
3030 #define PBUFFER_SIZE 2048
3031  *pbuffer = av_mallocz(PBUFFER_SIZE);
3032  if (!*pbuffer)
3033  goto sdp_done;
3034  av_sdp_create(&avc, 1, *pbuffer, PBUFFER_SIZE);
3035 
3036  sdp_done:
3037  av_freep(&avc->streams);
3038  av_dict_free(&avc->metadata);
3039  av_free(avc);
3040 
3041  return *pbuffer ? strlen(*pbuffer) : AVERROR(ENOMEM);
3042 }
3043 
3044 static void rtsp_cmd_options(HTTPContext *c, const char *url)
3045 {
3046  /* rtsp_reply_header(c, RTSP_STATUS_OK); */
3047  avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
3048  avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
3049  avio_printf(c->pb, "Public: %s\r\n",
3050  "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
3051  avio_printf(c->pb, "\r\n");
3052 }
3053 
3054 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
3055 {
3056  FFServerStream *stream;
3057  char path1[1024];
3058  const char *path;
3059  uint8_t *content;
3060  int content_length;
3061  socklen_t len;
3062  struct sockaddr_in my_addr;
3063 
3064  /* find which URL is asked */
3065  av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3066  path = path1;
3067  if (*path == '/')
3068  path++;
3069 
3070  for(stream = config.first_stream; stream; stream = stream->next) {
3071  if (!stream->is_feed &&
3072  stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
3073  !strcmp(path, stream->filename)) {
3074  goto found;
3075  }
3076  }
3077  /* no stream found */
3079  return;
3080 
3081  found:
3082  /* prepare the media description in SDP format */
3083 
3084  /* get the host IP */
3085  len = sizeof(my_addr);
3086  getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
3087  content_length = prepare_sdp_description(stream, &content,
3088  my_addr.sin_addr);
3089  if (content_length < 0) {
3091  return;
3092  }
3094  avio_printf(c->pb, "Content-Base: %s/\r\n", url);
3095  avio_printf(c->pb, "Content-Type: application/sdp\r\n");
3096  avio_printf(c->pb, "Content-Length: %d\r\n", content_length);
3097  avio_printf(c->pb, "\r\n");
3098  avio_write(c->pb, content, content_length);
3099  av_free(content);
3100 }
3101 
3102 static HTTPContext *find_rtp_session(const char *session_id)
3103 {
3104  HTTPContext *c;
3105 
3106  if (session_id[0] == '\0')
3107  return NULL;
3108 
3109  for(c = first_http_ctx; c; c = c->next) {
3110  if (!strcmp(c->session_id, session_id))
3111  return c;
3112  }
3113  return NULL;
3114 }
3115 
3117 {
3119  int i;
3120 
3121  for(i=0;i<h->nb_transports;i++) {
3122  th = &h->transports[i];
3123  if (th->lower_transport == lower_transport)
3124  return th;
3125  }
3126  return NULL;
3127 }
3128 
3129 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3131 {
3132  FFServerStream *stream;
3133  int stream_index, rtp_port, rtcp_port;
3134  char buf[1024];
3135  char path1[1024];
3136  const char *path;
3137  HTTPContext *rtp_c;
3139  struct sockaddr_in dest_addr;
3140  RTSPActionServerSetup setup;
3141 
3142  /* find which URL is asked */
3143  av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3144  path = path1;
3145  if (*path == '/')
3146  path++;
3147 
3148  /* now check each stream */
3149  for(stream = config.first_stream; stream; stream = stream->next) {
3150  if (stream->is_feed || !stream->fmt ||
3151  strcmp(stream->fmt->name, "rtp")) {
3152  continue;
3153  }
3154  /* accept aggregate filenames only if single stream */
3155  if (!strcmp(path, stream->filename)) {
3156  if (stream->nb_streams != 1) {
3158  return;
3159  }
3160  stream_index = 0;
3161  goto found;
3162  }
3163 
3164  for(stream_index = 0; stream_index < stream->nb_streams;
3165  stream_index++) {
3166  snprintf(buf, sizeof(buf), "%s/streamid=%d",
3167  stream->filename, stream_index);
3168  if (!strcmp(path, buf))
3169  goto found;
3170  }
3171  }
3172  /* no stream found */
3173  rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3174  return;
3175  found:
3176 
3177  /* generate session id if needed */
3178  if (h->session_id[0] == '\0') {
3179  unsigned random0 = av_lfg_get(&random_state);
3180  unsigned random1 = av_lfg_get(&random_state);
3181  snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3182  random0, random1);
3183  }
3184 
3185  /* find RTP session, and create it if none found */
3186  rtp_c = find_rtp_session(h->session_id);
3187  if (!rtp_c) {
3188  /* always prefer UDP */
3190  if (!th) {
3192  if (!th) {
3194  return;
3195  }
3196  }
3197 
3198  rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3199  th->lower_transport);
3200  if (!rtp_c) {
3202  return;
3203  }
3204 
3205  /* open input stream */
3206  if (open_input_stream(rtp_c, "") < 0) {
3208  return;
3209  }
3210  }
3211 
3212  /* test if stream is OK (test needed because several SETUP needs
3213  * to be done for a given file) */
3214  if (rtp_c->stream != stream) {
3216  return;
3217  }
3218 
3219  /* test if stream is already set up */
3220  if (rtp_c->rtp_ctx[stream_index]) {
3222  return;
3223  }
3224 
3225  /* check transport */
3226  th = find_transport(h, rtp_c->rtp_protocol);
3227  if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3228  th->client_port_min <= 0)) {
3230  return;
3231  }
3232 
3233  /* setup default options */
3234  setup.transport_option[0] = '\0';
3235  dest_addr = rtp_c->from_addr;
3236  dest_addr.sin_port = htons(th->client_port_min);
3237 
3238  /* setup stream */
3239  if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3241  return;
3242  }
3243 
3244  /* now everything is OK, so we can send the connection parameters */
3246  /* session ID */
3247  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3248 
3249  switch(rtp_c->rtp_protocol) {
3251  rtp_port = ff_rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3252  rtcp_port = ff_rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3253  avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3254  "client_port=%d-%d;server_port=%d-%d",
3256  rtp_port, rtcp_port);
3257  break;
3259  avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3260  stream_index * 2, stream_index * 2 + 1);
3261  break;
3262  default:
3263  break;
3264  }
3265  if (setup.transport_option[0] != '\0')
3266  avio_printf(c->pb, ";%s", setup.transport_option);
3267  avio_printf(c->pb, "\r\n");
3268 
3269 
3270  avio_printf(c->pb, "\r\n");
3271 }
3272 
3273 
3274 /**
3275  * find an RTP connection by using the session ID. Check consistency
3276  * with filename
3277  */
3278 static HTTPContext *find_rtp_session_with_url(const char *url,
3279  const char *session_id)
3280 {
3281  HTTPContext *rtp_c;
3282  char path1[1024];
3283  const char *path;
3284  char buf[1024];
3285  int s, len;
3286 
3287  rtp_c = find_rtp_session(session_id);
3288  if (!rtp_c)
3289  return NULL;
3290 
3291  /* find which URL is asked */
3292  av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3293  path = path1;
3294  if (*path == '/')
3295  path++;
3296  if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
3297  for(s=0; s<rtp_c->stream->nb_streams; ++s) {
3298  snprintf(buf, sizeof(buf), "%s/streamid=%d",
3299  rtp_c->stream->filename, s);
3300  if(!strncmp(path, buf, sizeof(buf)))
3301  /* XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE
3302  * if nb_streams>1? */
3303  return rtp_c;
3304  }
3305  len = strlen(path);
3306  if (len > 0 && path[len - 1] == '/' &&
3307  !strncmp(path, rtp_c->stream->filename, len - 1))
3308  return rtp_c;
3309  return NULL;
3310 }
3311 
3312 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3313 {
3314  HTTPContext *rtp_c;
3315 
3316  rtp_c = find_rtp_session_with_url(url, h->session_id);
3317  if (!rtp_c) {
3319  return;
3320  }
3321 
3322  if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3323  rtp_c->state != HTTPSTATE_WAIT_FEED &&
3324  rtp_c->state != HTTPSTATE_READY) {
3326  return;
3327  }
3328 
3329  rtp_c->state = HTTPSTATE_SEND_DATA;
3330 
3331  /* now everything is OK, so we can send the connection parameters */
3333  /* session ID */
3334  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3335  avio_printf(c->pb, "\r\n");
3336 }
3337 
3338 static void rtsp_cmd_interrupt(HTTPContext *c, const char *url,
3339  RTSPMessageHeader *h, int pause_only)
3340 {
3341  HTTPContext *rtp_c;
3342 
3343  rtp_c = find_rtp_session_with_url(url, h->session_id);
3344  if (!rtp_c) {
3346  return;
3347  }
3348 
3349  if (pause_only) {
3350  if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3351  rtp_c->state != HTTPSTATE_WAIT_FEED) {
3353  return;
3354  }
3355  rtp_c->state = HTTPSTATE_READY;
3356  rtp_c->first_pts = AV_NOPTS_VALUE;
3357  }
3358 
3359  /* now everything is OK, so we can send the connection parameters */
3361  /* session ID */
3362  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3363  avio_printf(c->pb, "\r\n");
3364 
3365  if (!pause_only)
3366  close_connection(rtp_c);
3367 }
3368 
3369 /********************************************************************/
3370 /* RTP handling */
3371 
3372 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3373  FFServerStream *stream,
3374  const char *session_id,
3375  enum RTSPLowerTransport rtp_protocol)
3376 {
3377  HTTPContext *c = NULL;
3378  const char *proto_str;
3379 
3380  /* XXX: should output a warning page when coming
3381  * close to the connection limit */
3382  if (nb_connections >= config.nb_max_connections)
3383  goto fail;
3384 
3385  /* add a new connection */
3386  c = av_mallocz(sizeof(HTTPContext));
3387  if (!c)
3388  goto fail;
3389 
3390  c->fd = -1;
3391  c->poll_entry = NULL;
3392  c->from_addr = *from_addr;
3394  c->buffer = av_malloc(c->buffer_size);
3395  if (!c->buffer)
3396  goto fail;
3397  nb_connections++;
3398  c->stream = stream;
3399  av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3400  c->state = HTTPSTATE_READY;
3401  c->is_packetized = 1;
3402  c->rtp_protocol = rtp_protocol;
3403 
3404  /* protocol is shown in statistics */
3405  switch(c->rtp_protocol) {
3407  proto_str = "MCAST";
3408  break;
3410  proto_str = "UDP";
3411  break;
3413  proto_str = "TCP";
3414  break;
3415  default:
3416  proto_str = "???";
3417  break;
3418  }
3419  av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3420  av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3421 
3422  current_bandwidth += stream->bandwidth;
3423 
3424  c->next = first_http_ctx;
3425  first_http_ctx = c;
3426  return c;
3427 
3428  fail:
3429  if (c) {
3430  av_freep(&c->buffer);
3431  av_free(c);
3432  }
3433  return NULL;
3434 }
3435 
3436 /**
3437  * add a new RTP stream in an RTP connection (used in RTSP SETUP
3438  * command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3439  * used.
3440  */
3442  int stream_index, struct sockaddr_in *dest_addr,
3443  HTTPContext *rtsp_c)
3444 {
3446  AVStream *st;
3447  char *ipaddr;
3448  URLContext *h = NULL;
3449  uint8_t *dummy_buf;
3450  int max_packet_size;
3451  void *st_internal;
3452 
3453  /* now we can open the relevant output stream */
3454  ctx = avformat_alloc_context();
3455  if (!ctx)
3456  return -1;
3457  ctx->oformat = av_guess_format("rtp", NULL, NULL);
3458 
3459  st = avformat_new_stream(ctx, NULL);
3460  if (!st)
3461  goto fail;
3462 
3463  st_internal = st->internal;
3464 
3465  if (!c->stream->feed ||
3466  c->stream->feed == c->stream)
3467  unlayer_stream(st, c->stream->streams[stream_index]);
3468  else
3469  unlayer_stream(st,
3470  c->stream->feed->streams[c->stream->feed_streams[stream_index]]);
3471  av_assert0(st->priv_data == NULL);
3472  av_assert0(st->internal == st_internal);
3473 
3474  /* build destination RTP address */
3475  ipaddr = inet_ntoa(dest_addr->sin_addr);
3476 
3477  switch(c->rtp_protocol) {
3480  /* RTP/UDP case */
3481 
3482  /* XXX: also pass as parameter to function ? */
3483  if (c->stream->is_multicast) {
3484  int ttl;
3485  ttl = c->stream->multicast_ttl;
3486  if (!ttl)
3487  ttl = 16;
3488  snprintf(ctx->filename, sizeof(ctx->filename),
3489  "rtp://%s:%d?multicast=1&ttl=%d",
3490  ipaddr, ntohs(dest_addr->sin_port), ttl);
3491  } else {
3492  snprintf(ctx->filename, sizeof(ctx->filename),
3493  "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3494  }
3495 
3496  if (ffurl_open(&h, ctx->filename, AVIO_FLAG_WRITE, NULL, NULL) < 0)
3497  goto fail;
3498  c->rtp_handles[stream_index] = h;
3499  max_packet_size = h->max_packet_size;
3500  break;
3502  /* RTP/TCP case */
3503  c->rtsp_c = rtsp_c;
3504  max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3505  break;
3506  default:
3507  goto fail;
3508  }
3509 
3510  http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3511  ipaddr, ntohs(dest_addr->sin_port),
3512  c->stream->filename, stream_index, c->protocol);
3513 
3514  /* normally, no packets should be output here, but the packet size may
3515  * be checked */
3516  if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0)
3517  /* XXX: close stream */
3518  goto fail;
3519 
3520  if (avformat_write_header(ctx, NULL) < 0) {
3521  fail:
3522  if (h)
3523  ffurl_close(h);
3524  av_free(st);
3525  av_free(ctx);
3526  return -1;
3527  }
3528  avio_close_dyn_buf(ctx->pb, &dummy_buf);
3529  ctx->pb = NULL;
3530  av_free(dummy_buf);
3531 
3532  c->rtp_ctx[stream_index] = ctx;
3533  return 0;
3534 }
3535 
3536 /********************************************************************/
3537 /* ffserver initialization */
3538 
3539 /* FIXME: This code should use avformat_new_stream() */
3541  AVCodecContext *codec, int copy)
3542 {
3543  LayeredAVStream *fst;
3544 
3545  if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams))
3546  return NULL;
3547 
3548  fst = av_mallocz(sizeof(*fst));
3549  if (!fst)
3550  return NULL;
3551  if (copy) {
3552  fst->codec = avcodec_alloc_context3(codec->codec);
3553  if (!fst->codec) {
3554  av_free(fst);
3555  return NULL;
3556  }
3557  avcodec_copy_context(fst->codec, codec);
3558  } else
3559  /* live streams must use the actual feed's codec since it may be
3560  * updated later to carry extradata needed by them.
3561  */
3562  fst->codec = codec;
3563 
3564  //NOTE we previously allocated internal & internal->avctx, these seemed uneeded though
3566  fst->index = stream->nb_streams;
3567  fst->time_base = codec->time_base;
3568  fst->pts_wrap_bits = 33;
3570  stream->streams[stream->nb_streams++] = fst;
3571  return fst;
3572 }
3573 
3574 /* return the stream number in the feed */
3576 {
3577  LayeredAVStream *fst;
3578  AVCodecContext *av, *av1;
3579  int i;
3580 
3581  av = st->codec;
3582  for(i=0;i<feed->nb_streams;i++) {
3583  av1 = feed->streams[i]->codec;
3584  if (av1->codec_id == av->codec_id &&
3585  av1->codec_type == av->codec_type &&
3586  av1->bit_rate == av->bit_rate) {
3587 
3588  switch(av->codec_type) {
3589  case AVMEDIA_TYPE_AUDIO:
3590  if (av1->channels == av->channels &&
3591  av1->sample_rate == av->sample_rate)
3592  return i;
3593  break;
3594  case AVMEDIA_TYPE_VIDEO:
3595  if (av1->width == av->width &&
3596  av1->height == av->height &&
3597  av1->time_base.den == av->time_base.den &&
3598  av1->time_base.num == av->time_base.num &&
3599  av1->gop_size == av->gop_size)
3600  return i;
3601  break;
3602  default:
3603  abort();
3604  }
3605  }
3606  }
3607 
3608  fst = add_av_stream1(feed, av, 0);
3609  if (!fst)
3610  return -1;
3614  return feed->nb_streams - 1;
3615 }
3616 
3617 static void remove_stream(FFServerStream *stream)
3618 {
3619  FFServerStream **ps;
3620  ps = &config.first_stream;
3621  while (*ps) {
3622  if (*ps == stream)
3623  *ps = (*ps)->next;
3624  else
3625  ps = &(*ps)->next;
3626  }
3627 }
3628 
3629 /* compute the needed AVStream for each file */
3630 static void build_file_streams(void)
3631 {
3632  FFServerStream *stream;
3633  AVFormatContext *infile;
3634  int i, ret;
3635 
3636  /* gather all streams */
3637  for(stream = config.first_stream; stream; stream = stream->next) {
3638  infile = NULL;
3639 
3640  if (stream->stream_type != STREAM_TYPE_LIVE || stream->feed)
3641  continue;
3642 
3643  /* the stream comes from a file */
3644  /* try to open the file */
3645  /* open stream */
3646 
3647 
3648  /* specific case: if transport stream output to RTP,
3649  * we use a raw transport stream reader */
3650  if (stream->fmt && !strcmp(stream->fmt->name, "rtp"))
3651  av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0);
3652 
3653  if (!stream->feed_filename[0]) {
3654  http_log("Unspecified feed file for stream '%s'\n",
3655  stream->filename);
3656  goto fail;
3657  }
3658 
3659  http_log("Opening feed file '%s' for stream '%s'\n",
3660  stream->feed_filename, stream->filename);
3661 
3662  ret = avformat_open_input(&infile, stream->feed_filename,
3663  stream->ifmt, &stream->in_opts);
3664  if (ret < 0) {
3665  http_log("Could not open '%s': %s\n", stream->feed_filename,
3666  av_err2str(ret));
3667  /* remove stream (no need to spend more time on it) */
3668  fail:
3669  remove_stream(stream);
3670  } else {
3671  /* find all the AVStreams inside and reference them in
3672  * 'stream' */
3673  if (avformat_find_stream_info(infile, NULL) < 0) {
3674  http_log("Could not find codec parameters from '%s'\n",
3675  stream->feed_filename);
3676  avformat_close_input(&infile);
3677  goto fail;
3678  }
3679 
3680  for(i=0;i<infile->nb_streams;i++)
3681  add_av_stream1(stream, infile->streams[i]->codec, 1);
3682 
3683  avformat_close_input(&infile);
3684  }
3685  }
3686 }
3687 
3688 static inline
3689 int check_codec_match(LayeredAVStream *ccf, AVStream *ccs, int stream)
3690 {
3691  int matches = 1;
3692 
3693 /* FIXME: Missed check on AVCodecContext.flags */
3694 #define CHECK_CODEC(x) (ccf->codecpar->x != ccs->codecpar->x)
3696  http_log("Codecs do not match for stream %d\n", stream);
3697  matches = 0;
3698  } else if (CHECK_CODEC(bit_rate)) {
3699  http_log("Codec bitrates do not match for stream %d\n", stream);
3700  matches = 0;
3701  } else if (ccf->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
3702  if (av_cmp_q(ccf->time_base, ccs->time_base) ||
3704  http_log("Codec width, height or framerate do not match for stream %d\n", stream);
3705  matches = 0;
3706  }
3707  } else if (ccf->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
3708  if (CHECK_CODEC(sample_rate) ||
3709  CHECK_CODEC(channels) ||
3711  http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", stream);
3712  matches = 0;
3713  }
3714  } else {
3715  http_log("Unknown codec type for stream %d\n", stream);
3716  matches = 0;
3717  }
3718 
3719  return matches;
3720 }
3721 
3722 /* compute the needed AVStream for each feed */
3723 static int build_feed_streams(void)
3724 {
3725  FFServerStream *stream, *feed;
3726  int i, fd;
3727 
3728  /* gather all streams */
3729  for(stream = config.first_stream; stream; stream = stream->next) {
3730  feed = stream->feed;
3731  if (!feed)
3732  continue;
3733 
3734  if (stream->is_feed) {
3735  for(i=0;i<stream->nb_streams;i++)
3736  stream->feed_streams[i] = i;
3737  continue;
3738  }
3739  /* we handle a stream coming from a feed */
3740  for(i=0;i<stream->nb_streams;i++)
3741  stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3742  }
3743 
3744  /* create feed files if needed */
3745  for(feed = config.first_feed; feed; feed = feed->next_feed) {
3746 
3747  if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) {
3748  AVFormatContext *s = NULL;
3749  int matches = 0;
3750 
3751  /* See if it matches */
3752 
3753  if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) < 0) {
3754  http_log("Deleting feed file '%s' as it appears "
3755  "to be corrupt\n",
3756  feed->feed_filename);
3757  goto drop;
3758  }
3759 
3760  /* set buffer size */
3761  if (ffio_set_buf_size(s->pb, FFM_PACKET_SIZE) < 0) {
3762  http_log("Failed to set buffer size\n");
3764  goto bail;
3765  }
3766 
3767  /* Now see if it matches */
3768  if (s->nb_streams != feed->nb_streams) {
3769  http_log("Deleting feed file '%s' as stream counts "
3770  "differ (%d != %d)\n",
3771  feed->feed_filename, s->nb_streams, feed->nb_streams);
3772  goto drop;
3773  }
3774 
3775  matches = 1;
3776  for(i=0;i<s->nb_streams;i++) {
3777  AVStream *ss;
3778  LayeredAVStream *sf;
3779 
3780  sf = feed->streams[i];
3781  ss = s->streams[i];
3782 
3783  if (sf->index != ss->index || sf->id != ss->id) {
3784  http_log("Index & Id do not match for stream %d (%s)\n",
3785  i, feed->feed_filename);
3786  matches = 0;
3787  break;
3788  }
3789 
3790  matches = check_codec_match (sf, ss, i);
3791  if (!matches)
3792  break;
3793  }
3794 
3795 drop:
3796  if (s)
3798 
3799  if (!matches) {
3800  if (feed->readonly) {
3801  http_log("Unable to delete read-only feed file '%s'\n",
3802  feed->feed_filename);
3803  goto bail;
3804  }
3805  unlink(feed->feed_filename);
3806  }
3807  }
3808 
3809  if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) {
3811 
3812  if (!s) {
3813  http_log("Failed to allocate context\n");
3814  goto bail;
3815  }
3816 
3817  if (feed->readonly) {
3818  http_log("Unable to create feed file '%s' as it is "
3819  "marked readonly\n",
3820  feed->feed_filename);
3822  goto bail;
3823  }
3824 
3825  /* only write the header of the ffm file */
3826  if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) {
3827  http_log("Could not open output feed file '%s'\n",
3828  feed->feed_filename);
3830  goto bail;
3831  }
3832  s->oformat = feed->fmt;
3833  for (i = 0; i<feed->nb_streams; i++) {
3834  AVStream *st = avformat_new_stream(s, NULL); // FIXME free this
3835  if (!st) {
3836  http_log("Failed to allocate stream\n");
3837  goto bail;
3838  }
3839  unlayer_stream(st, feed->streams[i]);
3840  }
3841  if (avformat_write_header(s, NULL) < 0) {
3842  http_log("Container doesn't support the required parameters\n");
3843  avio_closep(&s->pb);
3844  s->streams = NULL;
3845  s->nb_streams = 0;
3847  goto bail;
3848  }
3849  /* XXX: need better API */
3850  av_freep(&s->priv_data);
3851  avio_closep(&s->pb);
3852  s->streams = NULL;
3853  s->nb_streams = 0;
3855  }
3856 
3857  /* get feed size and write index */
3858  fd = open(feed->feed_filename, O_RDONLY);
3859  if (fd < 0) {
3860  http_log("Could not open output feed file '%s'\n",
3861  feed->feed_filename);
3862  goto bail;
3863  }
3864 
3866  FFM_PACKET_SIZE);
3867  feed->feed_size = lseek(fd, 0, SEEK_END);
3868  /* ensure that we do not wrap before the end of file */
3869  if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3870  feed->feed_max_size = feed->feed_size;
3871 
3872  close(fd);
3873  }
3874  return 0;
3875 
3876 bail:
3877  return -1;
3878 }
3879 
3880 /* compute the bandwidth used by each stream */
3881 static void compute_bandwidth(void)
3882 {
3883  unsigned bandwidth;
3884  int i;
3885  FFServerStream *stream;
3886 
3887  for(stream = config.first_stream; stream; stream = stream->next) {
3888  bandwidth = 0;
3889  for(i=0;i<stream->nb_streams;i++) {
3890  LayeredAVStream *st = stream->streams[i];
3891  switch(st->codec->codec_type) {
3892  case AVMEDIA_TYPE_AUDIO:
3893  case AVMEDIA_TYPE_VIDEO:
3894  bandwidth += st->codec->bit_rate;
3895  break;
3896  default:
3897  break;
3898  }
3899  }
3900  stream->bandwidth = (bandwidth + 999) / 1000;
3901  }
3902 }
3903 
3904 static void handle_child_exit(int sig)
3905 {
3906  pid_t pid;
3907  int status;
3908  time_t uptime;
3909 
3910  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
3911  FFServerStream *feed;
3912 
3913  for (feed = config.first_feed; feed; feed = feed->next) {
3914  if (feed->pid != pid)
3915  continue;
3916 
3917  uptime = time(0) - feed->pid_start;
3918  feed->pid = 0;
3919  fprintf(stderr,
3920  "%s: Pid %"PRId64" exited with status %d after %"PRId64" "
3921  "seconds\n",
3922  feed->filename, (int64_t) pid, status, (int64_t)uptime);
3923 
3924  if (uptime < 30)
3925  /* Turn off any more restarts */
3927  }
3928  }
3929 
3931 }
3932 
3933 static void opt_debug(void)
3934 {
3935  config.debug = 1;
3936  snprintf(config.logfilename, sizeof(config.logfilename), "-");
3937 }
3938 
3939 void show_help_default(const char *opt, const char *arg)
3940 {
3941  printf("usage: ffserver [options]\n"
3942  "Hyper fast multi format Audio/Video streaming server\n");
3943  printf("\n");
3944  show_help_options(options, "Main options:", 0, 0, 0);
3945 }
3946 
3947 static const OptionDef options[] = {
3948 #include "cmdutils_common_opts.h"
3949  { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
3950  { "d", 0, {(void*)opt_debug}, "enable debug mode" },
3951  { "f", HAS_ARG | OPT_STRING, {(void*)&config.filename }, "use configfile instead of /etc/ffserver.conf", "configfile" },
3952  { NULL },
3953 };
3954 
3955 int main(int argc, char **argv)
3956 {
3957  struct sigaction sigact = { { 0 } };
3958  int cfg_parsed;
3959  int ret = EXIT_FAILURE;
3960 
3961  init_dynload();
3962 
3963  config.filename = av_strdup("/etc/ffserver.conf");
3964 
3965  parse_loglevel(argc, argv, options);
3966  av_register_all();
3968 
3969  show_banner(argc, argv, options);
3970 
3971  my_program_name = argv[0];
3972 
3973  parse_options(NULL, argc, argv, options, NULL);
3974 
3975  unsetenv("http_proxy"); /* Kill the http_proxy */
3976 
3977  av_lfg_init(&random_state, av_get_random_seed());
3978 
3979  sigact.sa_handler = handle_child_exit;
3980  sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
3981  sigaction(SIGCHLD, &sigact, 0);
3982 
3983  if ((cfg_parsed = ffserver_parse_ffconfig(config.filename, &config)) < 0) {
3984  fprintf(stderr, "Error reading configuration file '%s': %s\n",
3985  config.filename, av_err2str(cfg_parsed));
3986  goto bail;
3987  }
3988 
3989  /* open log file if needed */
3990  if (config.logfilename[0] != '\0') {
3991  if (!strcmp(config.logfilename, "-"))
3992  logfile = stdout;
3993  else
3994  logfile = fopen(config.logfilename, "a");
3996  }
3997 
3999 
4000  if (build_feed_streams() < 0) {
4001  http_log("Could not setup feed streams\n");
4002  goto bail;
4003  }
4004 
4006 
4007  /* signal init */
4008  signal(SIGPIPE, SIG_IGN);
4009 
4010  if (http_server() < 0) {
4011  http_log("Could not start server\n");
4012  goto bail;
4013  }
4014 
4015  ret=EXIT_SUCCESS;
4016 
4017 bail:
4018  av_freep (&config.filename);
4020  return ret;
4021 }
Definition: lfg.h:25
int avio_open(AVIOContext **s, const char *url, int flags)
Create and initialize a AVIOContext for accessing the resource indicated by url.
Definition: aviobuf.c:1033
static int rtp_new_av_stream(HTTPContext *c, int stream_index, struct sockaddr_in *dest_addr, HTTPContext *rtsp_c)
add a new RTP stream in an RTP connection (used in RTSP SETUP command).
Definition: ffserver.c:3441
void init_dynload(void)
Initialize dynamic library loading.
Definition: cmdutils.c:119
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:4461
static int validate_acl(FFServerStream *stream, HTTPContext *c)
Definition: ffserver.c:1373
static const char *const http_state[]
Definition: ffserver.c:91
static HTTPContext * find_rtp_session(const char *session_id)
Definition: ffserver.c:3102
int64_t count1
Definition: ffserver.c:121
#define NULL
Definition: coverity.c:32
const struct AVCodec * codec
Definition: avcodec.h:1685
int ffserver_parse_ffconfig(const char *filename, FFServerConfig *config)
static const char * my_program_name
Definition: ffserver.c:241
const char * s
Definition: avisynth_c.h:768
Bytestream IO Context.
Definition: avio.h:147
enum AVCodecID codec_id
Definition: ffmpeg_vaapi.c:149
static void http_log(const char *fmt,...)
Definition: ffserver.c:423
struct sockaddr_in http_addr
int ff_rtp_get_local_rtp_port(URLContext *h)
Return the local rtp port used by the RTP connection.
Definition: rtpproto.c:628
static void copy(const float *p1, float *p2, const int length)
static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
Definition: ffserver.c:2904
int chunked_encoding
Definition: ffserver.c:135
RTSPLowerTransport
Network layer over which RTP/etc packet data will be transported.
Definition: rtsp.h:37
AVCodec * avcodec_find_encoder(enum AVCodecID id)
Find a registered encoder with a matching codec ID.
Definition: utils.c:3108
static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
Definition: ffserver.c:431
int packet_stream_index
Definition: ffserver.c:171
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1280
FFServerIPAddressACL * acl
int64_t time2
Definition: ffserver.c:122
static void print_stream_params(AVIOContext *pb, FFServerStream *stream)
Definition: ffserver.c:1878
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:919
static int prepare_sdp_description(FFServerStream *stream, uint8_t **pbuffer, struct in_addr my_ip)
Definition: ffserver.c:2999
const char * fmt
Definition: avisynth_c.h:769
static void build_file_streams(void)
Definition: ffserver.c:3630
unsigned int nb_max_connections
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
int64_t bit_rate
the average bitrate
Definition: avcodec.h:1741
int av_parse_time(int64_t *timeval, const char *timestr, int duration)
Parse timestr and return in *time a corresponding number of microseconds.
Definition: parseutils.c:559
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:421
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
struct HTTPContext * next
Definition: ffserver.c:137
#define FFM_PACKET_SIZE
static FFServerConfig config
Definition: ffserver.c:193
HTTPState
Definition: ffserver.c:76
static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
Definition: ffserver.c:2883
static int64_t cur_time
Definition: ffserver.c:252
static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
Definition: ffserver.c:3312
FFServerIPAddressAction
AVFormatContext * fmt_in
Definition: ffserver.c:143
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3981
char protocol[16]
Definition: ffserver.c:164
uint8_t * packet_buffer_end
Definition: ffserver.c:188
static int validate_acl_list(FFServerIPAddressACL *in_acl, HTTPContext *c)
Definition: ffserver.c:1356
int num
Numerator.
Definition: rational.h:59
int index
stream index in AVFormatContext
Definition: avformat.h:890
#define AVIO_FLAG_READ
read-only
Definition: avio.h:606
static int rtsp_parse_request(HTTPContext *c)
Definition: ffserver.c:2910
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.h:222
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:607
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown) That is the width of a pixel divided by the height of the pixel...
Definition: avcodec.h:2087
AVInputFormat * ifmt
enum AVMediaType codec_type
Definition: rtp.c:37
void show_banner(int argc, char **argv, const OptionDef *options)
Print the program banner to stderr.
Definition: cmdutils.c:1150
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition: avstring.c:223
int64_t timeout
Definition: ffserver.c:131
UDP/unicast.
Definition: rtsp.h:38
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:217
struct pollfd * poll_entry
Definition: ffserver.c:130
void * priv_data
Definition: avformat.h:904
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:252
void show_help_default(const char *opt, const char *arg)
Per-fftool specific help handler.
Definition: ffserver.c:3939
static AVPacket pkt
RedirType
Definition: ffserver.c:1417
static const char * audio_codec_name
Definition: ffplay.c:340
#define src
Definition: vp8dsp.c:254
AVCodec.
Definition: avcodec.h:3601
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1268
This struct describes the properties of an encoded stream.
Definition: avcodec.h:3973
enum RTSPLowerTransport lower_transport
network layer transport protocol; e.g.
Definition: rtsp.h:121
This describes the server response to each RTSP command.
Definition: rtsp.h:127
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avcodec.h:1813
RTSPTransportField transports[RTSP_MAX_TRANSPORTS]
describes the complete "Transport:" line of the server in response to a SETUP RTSP command by the cli...
Definition: rtsp.h:142
struct FFServerStream * next
const int program_birth_year
program birth year, defined by the program for show_banner()
Definition: ffserver.c:72
Format I/O context.
Definition: avformat.h:1338
#define IOBUFFER_INIT_SIZE
Definition: ffserver.c:107
int avio_check(const char *url, int flags)
Return AVIO_FLAG_* access flags corresponding to the access permissions of the resource in url...
Definition: avio.c:480
void ffserver_free_child_args(void *argsp)
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
Public dictionary API.
static void free_acl_list(FFServerIPAddressACL *in_acl)
Definition: ffserver.c:1344
AVOutputFormat * fmt
static void http_vlog(const char *fmt, va_list vargs)
Definition: ffserver.c:403
AVRational sample_aspect_ratio
uint8_t
static int nb_streams
Definition: ffprobe.c:254
char session_id[512]
the "Session:" field.
Definition: rtsp.h:148
#define av_malloc(s)
uint64_t max_bandwidth
Opaque data information usually continuous.
Definition: avutil.h:197
static void opt_debug(void)
Definition: ffserver.c:3933
int width
Video only.
Definition: avcodec.h:4047
AVCodecParameters * codecpar
AVOptions.
uint8_t * packet_buffer_ptr
Definition: ffserver.c:188
#define HAS_ARG
Definition: cmdutils.h:166
AVCodecParameters * avcodec_parameters_alloc(void)
Allocate a new AVCodecParameters and set its fields to default values (unknown/invalid/0).
Definition: utils.c:4127
char logfilename[1024]
static void compute_real_filename(char *filename, int max_size)
compute the real filename of a file by matching it without its extensions to all the stream's filenam...
Definition: ffserver.c:1394
static unsigned int nb_connections
Definition: ffserver.c:247
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: avcodec.h:1619
const char program_name[]
program name, defined by the program for show_version().
Definition: ffserver.c:71
AVFormatContext * rtp_ctx[FFSERVER_MAX_STREAMS]
Definition: ffserver.c:181
static int http_parse_request(HTTPContext *c)
Definition: ffserver.c:1427
int id
Format-specific stream ID.
Definition: avformat.h:896
#define AVFMT_FLAG_GENPTS
Generate missing pts even if it requires parsing future frames.
Definition: avformat.h:1450
static int http_send_data(HTTPContext *c)
Definition: ffserver.c:2536
static void get_word(char *buf, int buf_size, const char **pp)
Definition: ffserver.c:1283
#define SPACE_CHARS
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4214
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1406
int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par)
Fill the codec context based on the values from the supplied codec parameters.
Definition: utils.c:4223
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:132
int feed_streams[FFSERVER_MAX_STREAMS]
#define height
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:40
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1449
static void rtsp_cmd_interrupt(HTTPContext *c, const char *url, RTSPMessageHeader *h, int pause_only)
Definition: ffserver.c:3338
void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, void(*parse_arg_function)(void *, const char *))
Definition: cmdutils.c:382
struct FFServerStream * stream
Definition: ffserver.c:154
int avformat_network_init(void)
Do global initialization of network components.
Definition: utils.c:4692
static const uint64_t c1
Definition: murmur3.c:49
AVDictionary * metadata
static HTTPContext * find_rtp_session_with_url(const char *url, const char *session_id)
find an RTP connection by using the session ID.
Definition: ffserver.c:3278
int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
Generate an SDP for an RTP session.
Definition: sdp.c:827
int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
Attempt to find a specific tag in a URL.
Definition: parseutils.c:705
int av_match_ext(const char *filename, const char *extensions)
Return a positive value if the given filename has one of the given extensions, 0 otherwise.
Definition: format.c:85
static int http_receive_data(HTTPContext *c)
Definition: ffserver.c:2719
void parse_loglevel(int argc, char **argv, const OptionDef *options)
Find the '-loglevel' option in the command line args and apply it.
Definition: cmdutils.c:505
ptrdiff_t size
Definition: opengl_enc.c:101
static const uint8_t header[24]
Definition: sdr2.c:67
void show_help_options(const OptionDef *options, const char *msg, int req_flags, int rej_flags, int alt_flags)
Print help for all options matching specified flags.
Definition: cmdutils.c:176
char clean_url[128 *7]
Definition: ffserver.c:167
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:204
#define AVFMT_FLAG_BITEXACT
When muxing, try to avoid writing any random/volatile data to the output.
Definition: avformat.h:1466
int chunk_size
Definition: ffserver.c:136
DataRateData datarate
Definition: ffserver.c:162
#define av_log(a,...)
int nb_transports
number of items in the 'transports' variable below
Definition: rtsp.h:134
void ff_rtsp_parse_line(AVFormatContext *s, RTSPMessageHeader *reply, const char *buf, RTSPState *rt, const char *method)
static FILE * logfile
Definition: ffserver.c:256
struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1357
int64_t bit_rate
The average bitrate of the encoded data (in bits per second).
Definition: avcodec.h:4010
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1633
#define COPY(a)
static void http_send_too_busy_reply(int fd)
Definition: ffserver.c:819
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
int avcodec_close(AVCodecContext *avctx)
Close a given AVCodecContext and free all the data associated with it (but not the AVCodecContext its...
Definition: utils.c:3023
AVIOContext * avio_alloc_context(unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int(*read_packet)(void *opaque, uint8_t *buf, int buf_size), int(*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t(*seek)(void *opaque, int64_t offset, int whence))
Allocate and initialize an AVIOContext for buffered I/O.
Definition: aviobuf.c:126
int64_t cur_clock
Definition: ffserver.c:152
const char * suffix
Definition: checkasm.c:125
static int extract_rates(char *rates, int ratelen, const char *request)
Definition: ffserver.c:1158
static LayeredAVStream * add_av_stream1(FFServerStream *stream, AVCodecContext *codec, int copy)
Definition: ffserver.c:3540
uint8_t * buffer_end
Definition: ffserver.c:132
AVDictionary * metadata
Metadata that applies to the whole file.
Definition: avformat.h:1554
int main(int argc, char **argv)
Definition: ffserver.c:3955
static int handle_connection(HTTPContext *c)
Definition: ffserver.c:977
int last_packet_sent
Definition: ffserver.c:160
int got_key_frame
Definition: ffserver.c:138
int suppress_log
Definition: ffserver.c:161
static int64_t get_server_clock(HTTPContext *c)
Definition: ffserver.c:2275
#define closesocket
Definition: ffserver.c:28
int64_t data_count
Definition: ffserver.c:139
#define AVERROR(e)
Definition: error.h:43
int ffio_set_buf_size(AVIOContext *s, int buf_size)
Definition: aviobuf.c:959
static void rtsp_cmd_options(HTTPContext *c, const char *url)
Definition: ffserver.c:3044
static uint64_t current_bandwidth
Definition: ffserver.c:249
int qmax
maximum quantizer
Definition: avcodec.h:2626
#define FFSERVER_MAX_STREAMS
AVIOContext * pb
Definition: ffserver.c:175
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:203
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3977
const char * arg
Definition: jacosubdec.c:66
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:1771
int64_t cur_pts
Definition: ffserver.c:146
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
Definition: opt.c:560
enum FFServerStreamType stream_type
Definition: graph2dot.c:48
char dynamic_acl[1024]
simple assert() macros that are a bit more flexible than ISO C assert().
int av_log_get_level(void)
Get the current log level.
Definition: log.c:386
static int socket_open_listen(struct sockaddr_in *my_addr)
Definition: ffserver.c:560
const char * name
Name of the codec implementation.
Definition: avcodec.h:3608
uint8_t * packet_buffer
Definition: ffserver.c:188
GLsizei count
Definition: opengl_enc.c:109
int buffer_size
Definition: ffserver.c:168
static void start_children(FFServerStream *feed)
Definition: ffserver.c:476
#define FFMAX(a, b)
Definition: common.h:94
static int ffm_write_write_index(int fd, int64_t pos)
Definition: ffserver.c:359
void avcodec_parameters_free(AVCodecParameters **par)
Free an AVCodecParameters instance and everything associated with it and write NULL to the supplied p...
Definition: utils.c:4137
static void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.h:226
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:83
#define fail()
Definition: checkasm.h:84
int feed_streams[FFSERVER_MAX_STREAMS]
Definition: ffserver.c:156
static size_t htmlencode(const char *src, char **dest)
Substitutes known conflicting chars on a text string with their corresponding HTML entities...
Definition: ffserver.c:287
#define CHECK_CODEC(x)
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1607
static HTTPContext * first_http_ctx
Definition: ffserver.c:191
static void clean_html(char *clean, int clean_len, char *dirty)
Definition: ffserver.c:1924
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1394
static int open_input_stream(HTTPContext *c, const char *info)
Definition: ffserver.c:2189
static void log_connection(HTTPContext *c)
Definition: ffserver.c:443
#define th
Definition: regdef.h:75
AVInputFormat * av_find_input_format(const char *short_name)
Find AVInputFormat based on the short name of the input format.
Definition: format.c:164
#define RTSP_REQUEST_TIMEOUT
Definition: ffserver.c:111
char method[16]
Definition: ffserver.c:165
int seekable
A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
Definition: avio.h:243
char feed_filename[1024]
static int modify_current_stream(HTTPContext *c, char *rates)
Definition: ffserver.c:1243
int is_packetized
Definition: ffserver.c:170
#define AV_CODEC_FLAG_BITEXACT
Use only bitexact stuff (except (I)DCT).
Definition: avcodec.h:886
char filename[1024]
input or output filename
Definition: avformat.h:1414
static void rtsp_cmd_describe(HTTPContext *c, const char *url)
Definition: ffserver.c:3054
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:248
av_warn_unused_result int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
Definition: mux.c:521
#define FFMIN(a, b)
Definition: common.h:96
int64_t start_time
Definition: ffserver.c:144
struct FFServerStream * next_feed
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
void av_log_set_callback(void(*callback)(void *, int, const char *, va_list))
Set the logging callback.
Definition: log.c:406
attribute_deprecated int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src)
Copy the settings of the source AVCodecContext into the destination AVCodecContext.
Definition: options.c:190
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
Definition: options.c:156
#define AV_OPT_SEARCH_CHILDREN
Search in possible children of the given object first.
Definition: opt.h:557
#define width
int width
picture width / height.
Definition: avcodec.h:1863
int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size)
Open a write only packetized memory stream with a maximum packet size of 'max_packet_size'.
Definition: aviobuf.c:1273
#define RTSP_TCP_MAX_PACKET_SIZE
Definition: rtsp.h:75
#define ff_neterrno()
Definition: network.h:64
AVCodecContext * codec
const char * name
Definition: avformat.h:524
void ffserver_get_arg(char *buf, int buf_size, const char **pp)
struct FFServerIPAddressACL * next
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:119
AVFormatContext * ctx
Definition: movenc.c:48
This describes a single item in the "Transport:" line of one stream as negotiated by the SETUP RTSP c...
Definition: rtsp.h:88
int switch_pending
Definition: ffserver.c:158
int64_t feed_write_index
static int need_to_start_children
Definition: ffserver.c:244
struct HTTPContext * rtsp_c
Definition: ffserver.c:187
static AVLFG random_state
Definition: ffserver.c:254
AVOutputFormat * av_guess_format(const char *short_name, const char *filename, const char *mime_type)
Return the output format in the list of registered output formats which best matches the provided par...
Definition: format.c:98
const char *(* item_name)(void *ctx)
A pointer to a function which returns the name of a context instance ctx associated with the class...
Definition: log.h:78
int ff_socket_nonblock(int socket, int enable)
static int check_codec_match(LayeredAVStream *ccf, AVStream *ccs, int stream)
Definition: ffserver.c:3689
int cur_frame_bytes
Definition: ffserver.c:148
static const char * input_filename
Definition: ffplay.c:313
#define FF_ARRAY_ELEMS(a)
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
Stream structure.
Definition: avformat.h:889
enum RTSPLowerTransport rtp_protocol
Definition: ffserver.c:179
static int64_t ffm_read_write_index(int fd)
Definition: ffserver.c:348
struct sockaddr_in from_addr
Definition: ffserver.c:129
int avformat_network_deinit(void)
Undo the initialization done by avformat_network_init.
Definition: utils.c:4705
sample_rate
#define PBUFFER_SIZE
int frame_size
Definition: mxfenc.c:1820
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:267
int http_error
Definition: ffserver.c:133
static HTTPContext * rtp_new_connection(struct sockaddr_in *from_addr, FFServerStream *stream, const char *session_id, enum RTSPLowerTransport rtp_protocol)
Definition: ffserver.c:3372
static void compute_status(HTTPContext *c)
Definition: ffserver.c:1952
AVStreamInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1230
enum AVMediaType codec_type
Definition: avcodec.h:1684
int(* read_seek)(struct AVFormatContext *, int stream_index, int64_t timestamp, int flags)
Seek to a given timestamp relative to the frames in stream component stream_index.
Definition: avformat.h:756
void avcodec_free_context(AVCodecContext **avctx)
Free the codec context and everything associated with it and write NULL to the provided pointer...
Definition: options.c:171
static void start_multicast(void)
Definition: ffserver.c:599
enum AVCodecID codec_id
Definition: avcodec.h:1693
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:254
int sample_rate
samples per second
Definition: avcodec.h:2438
AVIOContext * pb
I/O context.
Definition: avformat.h:1380
#define ss
char filename[1024]
main external API structure.
Definition: avcodec.h:1676
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:568
int qmin
minimum quantizer
Definition: avcodec.h:2619
int wmp_client_id
Definition: ffserver.c:163
int64_t time1
Definition: ffserver.c:122
static int compute_datarate(DataRateData *drd, int64_t count)
Definition: ffserver.c:467
struct sockaddr_in rtsp_addr
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition: lfg.h:38
static RTSPTransportField * find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
Definition: ffserver.c:3116
void * buf
Definition: avisynth_c.h:690
Definition: url.h:38
GLint GLenum type
Definition: opengl_enc.c:105
char url[128]
Definition: ffserver.c:166
static void close_connection(HTTPContext *c)
Definition: ffserver.c:892
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:70
int client_port_max
Definition: rtsp.h:101
static int http_server(void)
Definition: ffserver.c:659
static const char * format
Definition: movenc.c:47
Describe the class of an AVClass context structure.
Definition: log.h:67
static void cp_html_entity(char *buffer, const char *entity)
Definition: ffserver.c:273
AVRational time_base
int index
Definition: gxfenc.c:89
int avcodec_parameters_from_context(AVCodecParameters *par, const AVCodecContext *codec)
Fill the parameters struct based on the values from the supplied codec context.
Definition: utils.c:4166
uint8_t * buffer_ptr
Definition: ffserver.c:132
#define OPT_STRING
Definition: cmdutils.h:169
static void update_datarate(DataRateData *drd, int64_t count)
Definition: ffserver.c:453
This holds the stream parameters for an AVStream, it cannot be a AVStream because AVStreams cannot be...
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
LayeredAVStream * streams[FFSERVER_MAX_STREAMS]
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition: lfg.c:30
int64_t first_pts
Definition: ffserver.c:145
static const OptionDef options[]
Definition: ffserver.c:74
static void start_wait_request(HTTPContext *c, int is_rtsp)
Definition: ffserver.c:809
#define snprintf
Definition: snprintf.h:34
static int add_av_stream(FFServerStream *feed, LayeredAVStream *st)
Definition: ffserver.c:3575
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4150
misc parsing utilities
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition: utils.c:1688
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes...
Definition: avstring.c:93
unsigned bandwidth
FFServerStream * first_feed
int switch_feed_streams[FFSERVER_MAX_STREAMS]
Definition: ffserver.c:157
AVDictionary * in_opts
RTSPStatusCode
RTSP handling.
Definition: rtspcodes.h:31
int ffurl_close(URLContext *h)
Definition: avio.c:467
URLContext * rtp_handles[FFSERVER_MAX_STREAMS]
Definition: ffserver.c:184
uint8_t level
Definition: svq3.c:207
static int64_t get_packet_send_clock(HTTPContext *c)
Definition: ffserver.c:2282
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Seek to the keyframe at timestamp.
Definition: utils.c:2424
struct FFServerStream * feed
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:1889
int sample_rate
Audio only.
Definition: avcodec.h:4091
#define OPT_BOOL
Definition: cmdutils.h:167
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition: rational.h:89
char transport_option[512]
Definition: ffserver.c:117
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_RB64
Definition: bytestream.h:87
Main libavformat public API header.
int
Utilties for rational number calculation.
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Definition: avio.c:357
static int find_stream_in_feed(FFServerStream *feed, AVCodecParameters *codec, int bit_rate)
Definition: ffserver.c:1205
static FFServerIPAddressACL * parse_dynamic_acl(FFServerStream *stream, HTTPContext *c)
Definition: ffserver.c:1303
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
Read packets of a media file to get stream information.
Definition: utils.c:3351
void ffserver_parse_acl_row(FFServerStream *stream, FFServerStream *feed, FFServerIPAddressACL *ext_acl, const char *p, const char *filename, int line_num)
int listen
Definition: http.c:117
int den
Denominator.
Definition: rational.h:60
AVFormatContext * pfmt_ctx
Definition: ffserver.c:159
struct AVInputFormat * iformat
The input container format.
Definition: avformat.h:1350
int64_t count2
Definition: ffserver.c:121
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition: utils.c:4186
int ff_rtp_get_local_rtcp_port(URLContext *h)
Return the local rtcp port used by the RTP connection.
Definition: rtpproto.c:640
char * recommended_encoder_configuration
#define av_free(p)
static void compute_bandwidth(void)
Definition: ffserver.c:3881
static void ffm_set_write_index(AVFormatContext *s, int64_t pos, int64_t file_size)
Definition: ffserver.c:377
char * value
Definition: dict.h:87
uint8_t * pb_buffer
Definition: ffserver.c:174
TCP; interleaved in RTSP.
Definition: rtsp.h:39
int len
uint8_t * buffer
Definition: ffserver.c:169
int channels
number of audio channels
Definition: avcodec.h:2439
#define PATH_LENGTH
Definition: ffserver.c:69
static uint8_t tmp[8]
Definition: des.c:38
#define RTSP_STATUS_CODE2STRING(x)
Definition: rtspcodes.h:125
void * priv_data
Format private data.
Definition: avformat.h:1366
static AVCodec * c
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
Definition: utils.c:509
static void new_connection(int server_fd, int is_rtsp)
Definition: ffserver.c:841
int channels
Audio only.
Definition: avcodec.h:4087
char session_id[32]
Definition: ffserver.c:180
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
Definition: avcodec.h:1600
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1294
int max_packet_size
if non zero, the stream is packetized with this max packet size
Definition: url.h:44
static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h)
Definition: ffserver.c:3129
static const char * video_codec_name
Definition: ffplay.c:342
#define av_freep(p)
int pts_stream_index
Definition: ffserver.c:151
void INT64 start
Definition: avisynth_c.h:690
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:664
static char * ctime1(char *buf2, size_t buf_size)
Definition: ffserver.c:385
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
Definition: random_seed.c:114
struct in_addr multicast_ip
AVCodecParameters * codecpar
Definition: avformat.h:1241
FFServerStream * first_stream
enum HTTPState state
Definition: ffserver.c:127
int stream_index
Definition: avcodec.h:1603
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:926
static const int rates[]
Definition: avresample.c:176
static void handle_child_exit(int sig)
Definition: ffserver.c:3904
const char * mime_type
Definition: avformat.h:531
This structure stores compressed data.
Definition: avcodec.h:1578
void av_register_all(void)
Initialize libavformat and register all the muxers, demuxers and protocols.
Definition: allformats.c:44
int avio_closep(AVIOContext **s)
Close the resource accessed by the AVIOContext *s, free it and set the pointer pointing to it to NULL...
Definition: aviobuf.c:1092
static void unlayer_stream(AVStream *st, LayeredAVStream *lst)
Definition: ffserver.c:258
unsigned int nb_max_http_connections
static int build_feed_streams(void)
Definition: ffserver.c:3723
struct in_addr first
static void fmt_bytecount(AVIOContext *pb, int64_t count)
Definition: ffserver.c:1868
enum FFServerIPAddressAction action
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1594
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:242
#define HTTP_REQUEST_TIMEOUT
Definition: ffserver.c:110
GLuint buffer
Definition: opengl_enc.c:102
static int http_prepare_data(HTTPContext *c)
Definition: ffserver.c:2296
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
int client_port_min
UDP client ports; these should be the local ports of the UDP RTP (and RTCP) sockets over which we rec...
Definition: rtsp.h:101
int64_t cur_frame_duration
Definition: ffserver.c:147
static void remove_stream(FFServerStream *stream)
Definition: ffserver.c:3617
static int http_start_receive_data(HTTPContext *c)
Definition: ffserver.c:2657
static int no_launch
Definition: ffserver.c:243
int feed_fd
Definition: ffserver.c:141