FFmpeg  1.2.12
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 
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/ffm.h"
36 #include "libavformat/network.h"
37 #include "libavformat/os_support.h"
38 #include "libavformat/rtpdec.h"
39 #include "libavformat/rtsp.h"
41 #include "libavformat/internal.h"
42 #include "libavformat/url.h"
43 
44 #include "libavutil/avassert.h"
45 #include "libavutil/avstring.h"
46 #include "libavutil/lfg.h"
47 #include "libavutil/dict.h"
48 #include "libavutil/intreadwrite.h"
49 #include "libavutil/mathematics.h"
50 #include "libavutil/random_seed.h"
51 #include "libavutil/parseutils.h"
52 #include "libavutil/opt.h"
53 #include "libavutil/time.h"
54 
55 #include <stdarg.h>
56 #include <unistd.h>
57 #include <fcntl.h>
58 #include <sys/ioctl.h>
59 #if HAVE_POLL_H
60 #include <poll.h>
61 #endif
62 #include <errno.h>
63 #include <time.h>
64 #include <sys/wait.h>
65 #include <signal.h>
66 #if HAVE_DLFCN_H
67 #include <dlfcn.h>
68 #endif
69 
70 #include "cmdutils.h"
71 
72 const char program_name[] = "ffserver";
73 const int program_birth_year = 2000;
74 
75 static const OptionDef options[];
76 
77 enum HTTPState {
81  HTTPSTATE_SEND_DATA, /* sending TCP or UDP data */
84  HTTPSTATE_WAIT_FEED, /* wait for data from the feed */
86 
90 };
91 
92 static const char *http_state[] = {
93  "HTTP_WAIT_REQUEST",
94  "HTTP_SEND_HEADER",
95 
96  "SEND_DATA_HEADER",
97  "SEND_DATA",
98  "SEND_DATA_TRAILER",
99  "RECEIVE_DATA",
100  "WAIT_FEED",
101  "READY",
102 
103  "RTSP_WAIT_REQUEST",
104  "RTSP_SEND_REPLY",
105  "RTSP_SEND_PACKET",
106 };
107 
108 #define MAX_STREAMS 20
109 
110 #define IOBUFFER_INIT_SIZE 8192
111 
112 /* timeouts are in ms */
113 #define HTTP_REQUEST_TIMEOUT (15 * 1000)
114 #define RTSP_REQUEST_TIMEOUT (3600 * 24 * 1000)
115 
116 #define SYNC_TIMEOUT (10 * 1000)
117 
118 typedef struct RTSPActionServerSetup {
119  uint32_t ipaddr;
120  char transport_option[512];
122 
123 typedef struct {
124  int64_t count1, count2;
125  int64_t time1, time2;
126 } DataRateData;
127 
128 /* context associated with one connection */
129 typedef struct HTTPContext {
131  int fd; /* socket file descriptor */
132  struct sockaddr_in from_addr; /* origin */
133  struct pollfd *poll_entry; /* used when polling */
134  int64_t timeout;
137  int post;
139  int chunk_size; /* 0 if it needs to be read */
140  struct HTTPContext *next;
141  int got_key_frame; /* stream 0 => 1, stream 1 => 2, stream 2=> 4 */
142  int64_t data_count;
143  /* feed input */
144  int feed_fd;
145  /* input format handling */
147  int64_t start_time; /* In milliseconds - this wraps fairly often */
148  int64_t first_pts; /* initial pts value */
149  int64_t cur_pts; /* current pts value from the stream in us */
150  int64_t cur_frame_duration; /* duration of the current frame in us */
151  int cur_frame_bytes; /* output frame size, needed to compute
152  the time at which we send each
153  packet */
154  int pts_stream_index; /* stream we choose as clock reference */
155  int64_t cur_clock; /* current clock reference value in us */
156  /* output format handling */
157  struct FFStream *stream;
158  /* -1 is invalid stream */
159  int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
160  int switch_feed_streams[MAX_STREAMS]; /* index of streams in the feed */
162  AVFormatContext fmt_ctx; /* instance of FFStream for one user */
163  int last_packet_sent; /* true if last data packet was sent */
167  char protocol[16];
168  char method[16];
169  char url[128];
172  int is_packetized; /* if true, the stream is packetized */
173  int packet_stream_index; /* current stream for output in state machine */
174 
175  /* RTSP state specific */
176  uint8_t *pb_buffer; /* XXX: use that in all the code */
178  int seq; /* RTSP sequence number */
179 
180  /* RTP state specific */
182  char session_id[32]; /* session id */
184 
185  /* RTP/UDP specific */
187 
188  /* RTP/TCP specific */
191 } HTTPContext;
192 
193 /* each generated stream is described here */
198 };
199 
201  IP_ALLOW = 1,
203 };
204 
205 typedef struct IPAddressACL {
208  /* These are in host order */
209  struct in_addr first;
210  struct in_addr last;
211 } IPAddressACL;
212 
213 /* description of each stream of the ffserver.conf file */
214 typedef struct FFStream {
216  char filename[1024]; /* stream filename */
217  struct FFStream *feed; /* feed we are using (can be null if
218  coming from file) */
219  AVDictionary *in_opts; /* input parameters */
220  AVInputFormat *ifmt; /* if non NULL, force input format */
223  char dynamic_acl[1024];
225  int prebuffer; /* Number of millseconds early to start */
226  int64_t max_time; /* Number of milliseconds to run */
229  int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
230  char feed_filename[1024]; /* file name of the feed storage, or
231  input file name for a stream */
232  char author[512];
233  char title[512];
234  char copyright[512];
235  char comment[512];
236  pid_t pid; /* Of ffmpeg process */
237  time_t pid_start; /* Of ffmpeg process */
238  char **child_argv;
239  struct FFStream *next;
240  unsigned bandwidth; /* bandwidth, in kbits/s */
241  /* RTSP options */
242  char *rtsp_option;
243  /* multicast specific */
245  struct in_addr multicast_ip;
246  int multicast_port; /* first port used for multicast */
248  int loop; /* if true, send the stream in loops (only meaningful if file) */
249 
250  /* feed specific */
251  int feed_opened; /* true if someone is writing to the feed */
252  int is_feed; /* true if it is a feed */
253  int readonly; /* True if writing is prohibited to the file */
254  int truncate; /* True if feeder connection truncate the feed file */
256  int64_t bytes_served;
257  int64_t feed_max_size; /* maximum storage size, zero means unlimited */
258  int64_t feed_write_index; /* current write position in feed (it wraps around) */
259  int64_t feed_size; /* current size of feed */
261 } FFStream;
262 
263 typedef struct FeedData {
264  long long data_count;
265  float avg_frame_size; /* frame size averaged over last frames with exponential mean */
266 } FeedData;
267 
268 static struct sockaddr_in my_http_addr;
269 static struct sockaddr_in my_rtsp_addr;
270 
271 static char logfilename[1024];
273 static FFStream *first_feed; /* contains only feeds */
274 static FFStream *first_stream; /* contains all streams, including feeds */
275 
276 static void new_connection(int server_fd, int is_rtsp);
277 static void close_connection(HTTPContext *c);
278 
279 /* HTTP handling */
280 static int handle_connection(HTTPContext *c);
281 static int http_parse_request(HTTPContext *c);
282 static int http_send_data(HTTPContext *c);
283 static void compute_status(HTTPContext *c);
284 static int open_input_stream(HTTPContext *c, const char *info);
286 static int http_receive_data(HTTPContext *c);
287 
288 /* RTSP handling */
289 static int rtsp_parse_request(HTTPContext *c);
290 static void rtsp_cmd_describe(HTTPContext *c, const char *url);
291 static void rtsp_cmd_options(HTTPContext *c, const char *url);
292 static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h);
293 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h);
294 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h);
295 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h);
296 
297 /* SDP handling */
298 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
299  struct in_addr my_ip);
300 
301 /* RTP handling */
302 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
303  FFStream *stream, const char *session_id,
304  enum RTSPLowerTransport rtp_protocol);
305 static int rtp_new_av_stream(HTTPContext *c,
306  int stream_index, struct sockaddr_in *dest_addr,
307  HTTPContext *rtsp_c);
308 
309 static const char *my_program_name;
310 
311 static const char *config_filename = "/etc/ffserver.conf";
312 
313 static int ffserver_debug;
314 static int no_launch;
316 
317 /* maximum number of simultaneous HTTP connections */
318 static unsigned int nb_max_http_connections = 2000;
319 static unsigned int nb_max_connections = 5;
320 static unsigned int nb_connections;
321 
322 static uint64_t max_bandwidth = 1000;
323 static uint64_t current_bandwidth;
324 
325 static int64_t cur_time; // Making this global saves on passing it around everywhere
326 
328 
329 static FILE *logfile = NULL;
330 
331 static void htmlstrip(char *s) {
332  while (s && *s) {
333  s += strspn(s, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,. ");
334  if (*s)
335  *s++ = '?';
336  }
337 }
338 
339 static int64_t ffm_read_write_index(int fd)
340 {
341  uint8_t buf[8];
342 
343  if (lseek(fd, 8, SEEK_SET) < 0)
344  return AVERROR(EIO);
345  if (read(fd, buf, 8) != 8)
346  return AVERROR(EIO);
347  return AV_RB64(buf);
348 }
349 
350 static int ffm_write_write_index(int fd, int64_t pos)
351 {
352  uint8_t buf[8];
353  int i;
354 
355  for(i=0;i<8;i++)
356  buf[i] = (pos >> (56 - i * 8)) & 0xff;
357  if (lseek(fd, 8, SEEK_SET) < 0)
358  return AVERROR(EIO);
359  if (write(fd, buf, 8) != 8)
360  return AVERROR(EIO);
361  return 8;
362 }
363 
364 static void ffm_set_write_index(AVFormatContext *s, int64_t pos,
365  int64_t file_size)
366 {
367  FFMContext *ffm = s->priv_data;
368  ffm->write_index = pos;
369  ffm->file_size = file_size;
370 }
371 
372 /* FIXME: make ffserver work with IPv6 */
373 /* resolve host with also IP address parsing */
374 static int resolve_host(struct in_addr *sin_addr, const char *hostname)
375 {
376 
377  if (!ff_inet_aton(hostname, sin_addr)) {
378 #if HAVE_GETADDRINFO
379  struct addrinfo *ai, *cur;
380  struct addrinfo hints = { 0 };
381  hints.ai_family = AF_INET;
382  if (getaddrinfo(hostname, NULL, &hints, &ai))
383  return -1;
384  /* getaddrinfo returns a linked list of addrinfo structs.
385  * Even if we set ai_family = AF_INET above, make sure
386  * that the returned one actually is of the correct type. */
387  for (cur = ai; cur; cur = cur->ai_next) {
388  if (cur->ai_family == AF_INET) {
389  *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
390  freeaddrinfo(ai);
391  return 0;
392  }
393  }
394  freeaddrinfo(ai);
395  return -1;
396 #else
397  struct hostent *hp;
398  hp = gethostbyname(hostname);
399  if (!hp)
400  return -1;
401  memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
402 #endif
403  }
404  return 0;
405 }
406 
407 static char *ctime1(char *buf2)
408 {
409  time_t ti;
410  char *p;
411 
412  ti = time(NULL);
413  p = ctime(&ti);
414  strcpy(buf2, p);
415  p = buf2 + strlen(p) - 1;
416  if (*p == '\n')
417  *p = '\0';
418  return buf2;
419 }
420 
421 static void http_vlog(const char *fmt, va_list vargs)
422 {
423  static int print_prefix = 1;
424  if (logfile) {
425  if (print_prefix) {
426  char buf[32];
427  ctime1(buf);
428  fprintf(logfile, "%s ", buf);
429  }
430  print_prefix = strstr(fmt, "\n") != NULL;
431  vfprintf(logfile, fmt, vargs);
432  fflush(logfile);
433  }
434 }
435 
436 #ifdef __GNUC__
437 __attribute__ ((format (printf, 1, 2)))
438 #endif
439 static void http_log(const char *fmt, ...)
440 {
441  va_list vargs;
442  va_start(vargs, fmt);
443  http_vlog(fmt, vargs);
444  va_end(vargs);
445 }
446 
447 static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
448 {
449  static int print_prefix = 1;
450  AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
451  if (level > av_log_get_level())
452  return;
453  if (print_prefix && avc)
454  http_log("[%s @ %p]", avc->item_name(ptr), ptr);
455  print_prefix = strstr(fmt, "\n") != NULL;
456  http_vlog(fmt, vargs);
457 }
458 
460 {
461  if (c->suppress_log)
462  return;
463 
464  http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
465  inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
466  c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
467 }
468 
469 static void update_datarate(DataRateData *drd, int64_t count)
470 {
471  if (!drd->time1 && !drd->count1) {
472  drd->time1 = drd->time2 = cur_time;
473  drd->count1 = drd->count2 = count;
474  } else if (cur_time - drd->time2 > 5000) {
475  drd->time1 = drd->time2;
476  drd->count1 = drd->count2;
477  drd->time2 = cur_time;
478  drd->count2 = count;
479  }
480 }
481 
482 /* In bytes per second */
483 static int compute_datarate(DataRateData *drd, int64_t count)
484 {
485  if (cur_time == drd->time1)
486  return 0;
487 
488  return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
489 }
490 
491 
492 static void start_children(FFStream *feed)
493 {
494  if (no_launch)
495  return;
496 
497  for (; feed; feed = feed->next) {
498  if (feed->child_argv && !feed->pid) {
499  feed->pid_start = time(0);
500 
501  feed->pid = fork();
502 
503  if (feed->pid < 0) {
504  http_log("Unable to create children\n");
505  exit(1);
506  }
507  if (!feed->pid) {
508  /* In child */
509  char pathname[1024];
510  char *slash;
511  int i;
512 
513  av_strlcpy(pathname, my_program_name, sizeof(pathname));
514 
515  slash = strrchr(pathname, '/');
516  if (!slash)
517  slash = pathname;
518  else
519  slash++;
520  strcpy(slash, "ffmpeg");
521 
522  http_log("Launch command line: ");
523  http_log("%s ", pathname);
524  for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
525  http_log("%s ", feed->child_argv[i]);
526  http_log("\n");
527 
528  for (i = 3; i < 256; i++)
529  close(i);
530 
531  if (!ffserver_debug) {
532  if (!freopen("/dev/null", "r", stdin))
533  http_log("failed to redirect STDIN to /dev/null\n;");
534  if (!freopen("/dev/null", "w", stdout))
535  http_log("failed to redirect STDOUT to /dev/null\n;");
536  if (!freopen("/dev/null", "w", stderr))
537  http_log("failed to redirect STDERR to /dev/null\n;");
538  }
539 
540  signal(SIGPIPE, SIG_DFL);
541 
542  execvp(pathname, feed->child_argv);
543 
544  _exit(1);
545  }
546  }
547  }
548 }
549 
550 /* open a listening socket */
551 static int socket_open_listen(struct sockaddr_in *my_addr)
552 {
553  int server_fd, tmp;
554 
555  server_fd = socket(AF_INET,SOCK_STREAM,0);
556  if (server_fd < 0) {
557  perror ("socket");
558  return -1;
559  }
560 
561  tmp = 1;
562  setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
563 
564  my_addr->sin_family = AF_INET;
565  if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
566  char bindmsg[32];
567  snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
568  perror (bindmsg);
569  closesocket(server_fd);
570  return -1;
571  }
572 
573  if (listen (server_fd, 5) < 0) {
574  perror ("listen");
575  closesocket(server_fd);
576  return -1;
577  }
578  ff_socket_nonblock(server_fd, 1);
579 
580  return server_fd;
581 }
582 
583 /* start all multicast streams */
584 static void start_multicast(void)
585 {
586  FFStream *stream;
587  char session_id[32];
588  HTTPContext *rtp_c;
589  struct sockaddr_in dest_addr = {0};
590  int default_port, stream_index;
591 
592  default_port = 6000;
593  for(stream = first_stream; stream != NULL; stream = stream->next) {
594  if (stream->is_multicast) {
595  unsigned random0 = av_lfg_get(&random_state);
596  unsigned random1 = av_lfg_get(&random_state);
597  /* open the RTP connection */
598  snprintf(session_id, sizeof(session_id), "%08x%08x",
599  random0, random1);
600 
601  /* choose a port if none given */
602  if (stream->multicast_port == 0) {
603  stream->multicast_port = default_port;
604  default_port += 100;
605  }
606 
607  dest_addr.sin_family = AF_INET;
608  dest_addr.sin_addr = stream->multicast_ip;
609  dest_addr.sin_port = htons(stream->multicast_port);
610 
611  rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
613  if (!rtp_c)
614  continue;
615 
616  if (open_input_stream(rtp_c, "") < 0) {
617  http_log("Could not open input stream for stream '%s'\n",
618  stream->filename);
619  continue;
620  }
621 
622  /* open each RTP stream */
623  for(stream_index = 0; stream_index < stream->nb_streams;
624  stream_index++) {
625  dest_addr.sin_port = htons(stream->multicast_port +
626  2 * stream_index);
627  if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
628  http_log("Could not open output stream '%s/streamid=%d'\n",
629  stream->filename, stream_index);
630  exit(1);
631  }
632  }
633 
634  /* change state to send data */
635  rtp_c->state = HTTPSTATE_SEND_DATA;
636  }
637  }
638 }
639 
640 /* main loop of the http server */
641 static int http_server(void)
642 {
643  int server_fd = 0, rtsp_server_fd = 0;
644  int ret, delay, delay1;
645  struct pollfd *poll_table, *poll_entry;
646  HTTPContext *c, *c_next;
647 
648  if(!(poll_table = av_mallocz((nb_max_http_connections + 2)*sizeof(*poll_table)))) {
649  http_log("Impossible to allocate a poll table handling %d connections.\n", nb_max_http_connections);
650  return -1;
651  }
652 
653  if (my_http_addr.sin_port) {
654  server_fd = socket_open_listen(&my_http_addr);
655  if (server_fd < 0)
656  return -1;
657  }
658 
659  if (my_rtsp_addr.sin_port) {
660  rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
661  if (rtsp_server_fd < 0)
662  return -1;
663  }
664 
665  if (!rtsp_server_fd && !server_fd) {
666  http_log("HTTP and RTSP disabled.\n");
667  return -1;
668  }
669 
670  http_log("FFserver started.\n");
671 
672  start_children(first_feed);
673 
674  start_multicast();
675 
676  for(;;) {
677  poll_entry = poll_table;
678  if (server_fd) {
679  poll_entry->fd = server_fd;
680  poll_entry->events = POLLIN;
681  poll_entry++;
682  }
683  if (rtsp_server_fd) {
684  poll_entry->fd = rtsp_server_fd;
685  poll_entry->events = POLLIN;
686  poll_entry++;
687  }
688 
689  /* wait for events on each HTTP handle */
690  c = first_http_ctx;
691  delay = 1000;
692  while (c != NULL) {
693  int fd;
694  fd = c->fd;
695  switch(c->state) {
699  c->poll_entry = poll_entry;
700  poll_entry->fd = fd;
701  poll_entry->events = POLLOUT;
702  poll_entry++;
703  break;
705  case HTTPSTATE_SEND_DATA:
707  if (!c->is_packetized) {
708  /* for TCP, we output as much as we can (may need to put a limit) */
709  c->poll_entry = poll_entry;
710  poll_entry->fd = fd;
711  poll_entry->events = POLLOUT;
712  poll_entry++;
713  } else {
714  /* when ffserver is doing the timing, we work by
715  looking at which packet need to be sent every
716  10 ms */
717  delay1 = 10; /* one tick wait XXX: 10 ms assumed */
718  if (delay1 < delay)
719  delay = delay1;
720  }
721  break;
724  case HTTPSTATE_WAIT_FEED:
726  /* need to catch errors */
727  c->poll_entry = poll_entry;
728  poll_entry->fd = fd;
729  poll_entry->events = POLLIN;/* Maybe this will work */
730  poll_entry++;
731  break;
732  default:
733  c->poll_entry = NULL;
734  break;
735  }
736  c = c->next;
737  }
738 
739  /* wait for an event on one connection. We poll at least every
740  second to handle timeouts */
741  do {
742  ret = poll(poll_table, poll_entry - poll_table, delay);
743  if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) &&
744  ff_neterrno() != AVERROR(EINTR))
745  return -1;
746  } while (ret < 0);
747 
748  cur_time = av_gettime() / 1000;
749 
752  start_children(first_feed);
753  }
754 
755  /* now handle the events */
756  for(c = first_http_ctx; c != NULL; c = c_next) {
757  c_next = c->next;
758  if (handle_connection(c) < 0) {
759  /* close and free the connection */
760  log_connection(c);
761  close_connection(c);
762  }
763  }
764 
765  poll_entry = poll_table;
766  if (server_fd) {
767  /* new HTTP connection request ? */
768  if (poll_entry->revents & POLLIN)
769  new_connection(server_fd, 0);
770  poll_entry++;
771  }
772  if (rtsp_server_fd) {
773  /* new RTSP connection request ? */
774  if (poll_entry->revents & POLLIN)
775  new_connection(rtsp_server_fd, 1);
776  }
777  }
778 }
779 
780 /* start waiting for a new HTTP/RTSP request */
781 static void start_wait_request(HTTPContext *c, int is_rtsp)
782 {
783  c->buffer_ptr = c->buffer;
784  c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */
785 
786  if (is_rtsp) {
789  } else {
792  }
793 }
794 
795 static void http_send_too_busy_reply(int fd)
796 {
797  char buffer[400];
798  int len = snprintf(buffer, sizeof(buffer),
799  "HTTP/1.0 503 Server too busy\r\n"
800  "Content-type: text/html\r\n"
801  "\r\n"
802  "<html><head><title>Too busy</title></head><body>\r\n"
803  "<p>The server is too busy to serve your request at this time.</p>\r\n"
804  "<p>The number of current connections is %u, and this exceeds the limit of %u.</p>\r\n"
805  "</body></html>\r\n",
807  av_assert0(len < sizeof(buffer));
808  send(fd, buffer, len, 0);
809 }
810 
811 
812 static void new_connection(int server_fd, int is_rtsp)
813 {
814  struct sockaddr_in from_addr;
815  socklen_t len;
816  int fd;
817  HTTPContext *c = NULL;
818 
819  len = sizeof(from_addr);
820  fd = accept(server_fd, (struct sockaddr *)&from_addr,
821  &len);
822  if (fd < 0) {
823  http_log("error during accept %s\n", strerror(errno));
824  return;
825  }
826  ff_socket_nonblock(fd, 1);
827 
830  goto fail;
831  }
832 
833  /* add a new connection */
834  c = av_mallocz(sizeof(HTTPContext));
835  if (!c)
836  goto fail;
837 
838  c->fd = fd;
839  c->poll_entry = NULL;
840  c->from_addr = from_addr;
842  c->buffer = av_malloc(c->buffer_size);
843  if (!c->buffer)
844  goto fail;
845 
846  c->next = first_http_ctx;
847  first_http_ctx = c;
848  nb_connections++;
849 
850  start_wait_request(c, is_rtsp);
851 
852  return;
853 
854  fail:
855  if (c) {
856  av_free(c->buffer);
857  av_free(c);
858  }
859  closesocket(fd);
860 }
861 
863 {
864  HTTPContext **cp, *c1;
865  int i, nb_streams;
866  AVFormatContext *ctx;
867  URLContext *h;
868  AVStream *st;
869 
870  /* remove connection from list */
871  cp = &first_http_ctx;
872  while ((*cp) != NULL) {
873  c1 = *cp;
874  if (c1 == c)
875  *cp = c->next;
876  else
877  cp = &c1->next;
878  }
879 
880  /* remove references, if any (XXX: do it faster) */
881  for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
882  if (c1->rtsp_c == c)
883  c1->rtsp_c = NULL;
884  }
885 
886  /* remove connection associated resources */
887  if (c->fd >= 0)
888  closesocket(c->fd);
889  if (c->fmt_in) {
890  /* close each frame parser */
891  for(i=0;i<c->fmt_in->nb_streams;i++) {
892  st = c->fmt_in->streams[i];
893  if (st->codec->codec)
894  avcodec_close(st->codec);
895  }
897  }
898 
899  /* free RTP output streams if any */
900  nb_streams = 0;
901  if (c->stream)
902  nb_streams = c->stream->nb_streams;
903 
904  for(i=0;i<nb_streams;i++) {
905  ctx = c->rtp_ctx[i];
906  if (ctx) {
907  av_write_trailer(ctx);
908  av_dict_free(&ctx->metadata);
909  av_free(ctx->streams[0]);
910  av_free(ctx);
911  }
912  h = c->rtp_handles[i];
913  if (h)
914  ffurl_close(h);
915  }
916 
917  ctx = &c->fmt_ctx;
918 
920  if (ctx->oformat) {
921  /* prepare header */
922  if (avio_open_dyn_buf(&ctx->pb) >= 0) {
923  av_write_trailer(ctx);
924  av_freep(&c->pb_buffer);
925  avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
926  }
927  }
928  }
929 
930  for(i=0; i<ctx->nb_streams; i++)
931  av_free(ctx->streams[i]);
932  av_freep(&ctx->streams);
933  av_freep(&ctx->priv_data);
934 
935  if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
937 
938  /* signal that there is no feed if we are the feeder socket */
939  if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) {
940  c->stream->feed_opened = 0;
941  close(c->feed_fd);
942  }
943 
944  av_freep(&c->pb_buffer);
945  av_freep(&c->packet_buffer);
946  av_free(c->buffer);
947  av_free(c);
948  nb_connections--;
949 }
950 
952 {
953  int len, ret;
954 
955  switch(c->state) {
958  /* timeout ? */
959  if ((c->timeout - cur_time) < 0)
960  return -1;
961  if (c->poll_entry->revents & (POLLERR | POLLHUP))
962  return -1;
963 
964  /* no need to read if no events */
965  if (!(c->poll_entry->revents & POLLIN))
966  return 0;
967  /* read the data */
968  read_loop:
969  len = recv(c->fd, c->buffer_ptr, 1, 0);
970  if (len < 0) {
971  if (ff_neterrno() != AVERROR(EAGAIN) &&
972  ff_neterrno() != AVERROR(EINTR))
973  return -1;
974  } else if (len == 0) {
975  return -1;
976  } else {
977  /* search for end of request. */
978  uint8_t *ptr;
979  c->buffer_ptr += len;
980  ptr = c->buffer_ptr;
981  if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
982  (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
983  /* request found : parse it and reply */
984  if (c->state == HTTPSTATE_WAIT_REQUEST) {
985  ret = http_parse_request(c);
986  } else {
987  ret = rtsp_parse_request(c);
988  }
989  if (ret < 0)
990  return -1;
991  } else if (ptr >= c->buffer_end) {
992  /* request too long: cannot do anything */
993  return -1;
994  } else goto read_loop;
995  }
996  break;
997 
999  if (c->poll_entry->revents & (POLLERR | POLLHUP))
1000  return -1;
1001 
1002  /* no need to write if no events */
1003  if (!(c->poll_entry->revents & POLLOUT))
1004  return 0;
1005  len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
1006  if (len < 0) {
1007  if (ff_neterrno() != AVERROR(EAGAIN) &&
1008  ff_neterrno() != AVERROR(EINTR)) {
1009  /* error : close connection */
1010  av_freep(&c->pb_buffer);
1011  return -1;
1012  }
1013  } else {
1014  c->buffer_ptr += len;
1015  if (c->stream)
1016  c->stream->bytes_served += len;
1017  c->data_count += len;
1018  if (c->buffer_ptr >= c->buffer_end) {
1019  av_freep(&c->pb_buffer);
1020  /* if error, exit */
1021  if (c->http_error)
1022  return -1;
1023  /* all the buffer was sent : synchronize to the incoming stream */
1025  c->buffer_ptr = c->buffer_end = c->buffer;
1026  }
1027  }
1028  break;
1029 
1030  case HTTPSTATE_SEND_DATA:
1033  /* for packetized output, we consider we can always write (the
1034  input streams sets the speed). It may be better to verify
1035  that we do not rely too much on the kernel queues */
1036  if (!c->is_packetized) {
1037  if (c->poll_entry->revents & (POLLERR | POLLHUP))
1038  return -1;
1039 
1040  /* no need to read if no events */
1041  if (!(c->poll_entry->revents & POLLOUT))
1042  return 0;
1043  }
1044  if (http_send_data(c) < 0)
1045  return -1;
1046  /* close connection if trailer sent */
1048  return -1;
1049  break;
1051  /* no need to read if no events */
1052  if (c->poll_entry->revents & (POLLERR | POLLHUP))
1053  return -1;
1054  if (!(c->poll_entry->revents & POLLIN))
1055  return 0;
1056  if (http_receive_data(c) < 0)
1057  return -1;
1058  break;
1059  case HTTPSTATE_WAIT_FEED:
1060  /* no need to read if no events */
1061  if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1062  return -1;
1063 
1064  /* nothing to do, we'll be waken up by incoming feed packets */
1065  break;
1066 
1067  case RTSPSTATE_SEND_REPLY:
1068  if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1069  av_freep(&c->pb_buffer);
1070  return -1;
1071  }
1072  /* no need to write if no events */
1073  if (!(c->poll_entry->revents & POLLOUT))
1074  return 0;
1075  len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
1076  if (len < 0) {
1077  if (ff_neterrno() != AVERROR(EAGAIN) &&
1078  ff_neterrno() != AVERROR(EINTR)) {
1079  /* error : close connection */
1080  av_freep(&c->pb_buffer);
1081  return -1;
1082  }
1083  } else {
1084  c->buffer_ptr += len;
1085  c->data_count += len;
1086  if (c->buffer_ptr >= c->buffer_end) {
1087  /* all the buffer was sent : wait for a new request */
1088  av_freep(&c->pb_buffer);
1089  start_wait_request(c, 1);
1090  }
1091  }
1092  break;
1093  case RTSPSTATE_SEND_PACKET:
1094  if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1095  av_freep(&c->packet_buffer);
1096  return -1;
1097  }
1098  /* no need to write if no events */
1099  if (!(c->poll_entry->revents & POLLOUT))
1100  return 0;
1101  len = send(c->fd, c->packet_buffer_ptr,
1103  if (len < 0) {
1104  if (ff_neterrno() != AVERROR(EAGAIN) &&
1105  ff_neterrno() != AVERROR(EINTR)) {
1106  /* error : close connection */
1107  av_freep(&c->packet_buffer);
1108  return -1;
1109  }
1110  } else {
1111  c->packet_buffer_ptr += len;
1112  if (c->packet_buffer_ptr >= c->packet_buffer_end) {
1113  /* all the buffer was sent : wait for a new request */
1114  av_freep(&c->packet_buffer);
1116  }
1117  }
1118  break;
1119  case HTTPSTATE_READY:
1120  /* nothing to do */
1121  break;
1122  default:
1123  return -1;
1124  }
1125  return 0;
1126 }
1127 
1128 static int extract_rates(char *rates, int ratelen, const char *request)
1129 {
1130  const char *p;
1131 
1132  for (p = request; *p && *p != '\r' && *p != '\n'; ) {
1133  if (av_strncasecmp(p, "Pragma:", 7) == 0) {
1134  const char *q = p + 7;
1135 
1136  while (*q && *q != '\n' && av_isspace(*q))
1137  q++;
1138 
1139  if (av_strncasecmp(q, "stream-switch-entry=", 20) == 0) {
1140  int stream_no;
1141  int rate_no;
1142 
1143  q += 20;
1144 
1145  memset(rates, 0xff, ratelen);
1146 
1147  while (1) {
1148  while (*q && *q != '\n' && *q != ':')
1149  q++;
1150 
1151  if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2)
1152  break;
1153 
1154  stream_no--;
1155  if (stream_no < ratelen && stream_no >= 0)
1156  rates[stream_no] = rate_no;
1157 
1158  while (*q && *q != '\n' && !av_isspace(*q))
1159  q++;
1160  }
1161 
1162  return 1;
1163  }
1164  }
1165  p = strchr(p, '\n');
1166  if (!p)
1167  break;
1168 
1169  p++;
1170  }
1171 
1172  return 0;
1173 }
1174 
1175 static int find_stream_in_feed(FFStream *feed, AVCodecContext *codec, int bit_rate)
1176 {
1177  int i;
1178  int best_bitrate = 100000000;
1179  int best = -1;
1180 
1181  for (i = 0; i < feed->nb_streams; i++) {
1182  AVCodecContext *feed_codec = feed->streams[i]->codec;
1183 
1184  if (feed_codec->codec_id != codec->codec_id ||
1185  feed_codec->sample_rate != codec->sample_rate ||
1186  feed_codec->width != codec->width ||
1187  feed_codec->height != codec->height)
1188  continue;
1189 
1190  /* Potential stream */
1191 
1192  /* We want the fastest stream less than bit_rate, or the slowest
1193  * faster than bit_rate
1194  */
1195 
1196  if (feed_codec->bit_rate <= bit_rate) {
1197  if (best_bitrate > bit_rate || feed_codec->bit_rate > best_bitrate) {
1198  best_bitrate = feed_codec->bit_rate;
1199  best = i;
1200  }
1201  } else {
1202  if (feed_codec->bit_rate < best_bitrate) {
1203  best_bitrate = feed_codec->bit_rate;
1204  best = i;
1205  }
1206  }
1207  }
1208 
1209  return best;
1210 }
1211 
1213 {
1214  int i;
1215  FFStream *req = c->stream;
1216  int action_required = 0;
1217 
1218  /* Not much we can do for a feed */
1219  if (!req->feed)
1220  return 0;
1221 
1222  for (i = 0; i < req->nb_streams; i++) {
1223  AVCodecContext *codec = req->streams[i]->codec;
1224 
1225  switch(rates[i]) {
1226  case 0:
1227  c->switch_feed_streams[i] = req->feed_streams[i];
1228  break;
1229  case 1:
1230  c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2);
1231  break;
1232  case 2:
1233  /* Wants off or slow */
1234  c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);
1235 #ifdef WANTS_OFF
1236  /* This doesn't work well when it turns off the only stream! */
1237  c->switch_feed_streams[i] = -2;
1238  c->feed_streams[i] = -2;
1239 #endif
1240  break;
1241  }
1242 
1243  if (c->switch_feed_streams[i] >= 0 && c->switch_feed_streams[i] != c->feed_streams[i])
1244  action_required = 1;
1245  }
1246 
1247  return action_required;
1248 }
1249 
1250 /* XXX: factorize in utils.c ? */
1251 /* XXX: take care with different space meaning */
1252 static void skip_spaces(const char **pp)
1253 {
1254  const char *p;
1255  p = *pp;
1256  while (*p == ' ' || *p == '\t')
1257  p++;
1258  *pp = p;
1259 }
1260 
1261 static void get_word(char *buf, int buf_size, const char **pp)
1262 {
1263  const char *p;
1264  char *q;
1265 
1266  p = *pp;
1267  skip_spaces(&p);
1268  q = buf;
1269  while (!av_isspace(*p) && *p != '\0') {
1270  if ((q - buf) < buf_size - 1)
1271  *q++ = *p;
1272  p++;
1273  }
1274  if (buf_size > 0)
1275  *q = '\0';
1276  *pp = p;
1277 }
1278 
1279 static void get_arg(char *buf, int buf_size, const char **pp)
1280 {
1281  const char *p;
1282  char *q;
1283  int quote;
1284 
1285  p = *pp;
1286  while (av_isspace(*p)) p++;
1287  q = buf;
1288  quote = 0;
1289  if (*p == '\"' || *p == '\'')
1290  quote = *p++;
1291  for(;;) {
1292  if (quote) {
1293  if (*p == quote)
1294  break;
1295  } else {
1296  if (av_isspace(*p))
1297  break;
1298  }
1299  if (*p == '\0')
1300  break;
1301  if ((q - buf) < buf_size - 1)
1302  *q++ = *p;
1303  p++;
1304  }
1305  *q = '\0';
1306  if (quote && *p == quote)
1307  p++;
1308  *pp = p;
1309 }
1310 
1311 static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_acl,
1312  const char *p, const char *filename, int line_num)
1313 {
1314  char arg[1024];
1315  IPAddressACL acl;
1316  int errors = 0;
1317 
1318  get_arg(arg, sizeof(arg), &p);
1319  if (av_strcasecmp(arg, "allow") == 0)
1320  acl.action = IP_ALLOW;
1321  else if (av_strcasecmp(arg, "deny") == 0)
1322  acl.action = IP_DENY;
1323  else {
1324  fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1325  filename, line_num, arg);
1326  errors++;
1327  }
1328 
1329  get_arg(arg, sizeof(arg), &p);
1330 
1331  if (resolve_host(&acl.first, arg) != 0) {
1332  fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1333  filename, line_num, arg);
1334  errors++;
1335  } else
1336  acl.last = acl.first;
1337 
1338  get_arg(arg, sizeof(arg), &p);
1339 
1340  if (arg[0]) {
1341  if (resolve_host(&acl.last, arg) != 0) {
1342  fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1343  filename, line_num, arg);
1344  errors++;
1345  }
1346  }
1347 
1348  if (!errors) {
1349  IPAddressACL *nacl = av_mallocz(sizeof(*nacl));
1350  IPAddressACL **naclp = 0;
1351 
1352  acl.next = 0;
1353  *nacl = acl;
1354 
1355  if (stream)
1356  naclp = &stream->acl;
1357  else if (feed)
1358  naclp = &feed->acl;
1359  else if (ext_acl)
1360  naclp = &ext_acl;
1361  else {
1362  fprintf(stderr, "%s:%d: ACL found not in <stream> or <feed>\n",
1363  filename, line_num);
1364  errors++;
1365  }
1366 
1367  if (naclp) {
1368  while (*naclp)
1369  naclp = &(*naclp)->next;
1370 
1371  *naclp = nacl;
1372  }
1373  }
1374 }
1375 
1376 
1378 {
1379  FILE* f;
1380  char line[1024];
1381  char cmd[1024];
1382  IPAddressACL *acl = NULL;
1383  int line_num = 0;
1384  const char *p;
1385 
1386  f = fopen(stream->dynamic_acl, "r");
1387  if (!f) {
1388  perror(stream->dynamic_acl);
1389  return NULL;
1390  }
1391 
1392  acl = av_mallocz(sizeof(IPAddressACL));
1393 
1394  /* Build ACL */
1395  for(;;) {
1396  if (fgets(line, sizeof(line), f) == NULL)
1397  break;
1398  line_num++;
1399  p = line;
1400  while (av_isspace(*p))
1401  p++;
1402  if (*p == '\0' || *p == '#')
1403  continue;
1404  get_arg(cmd, sizeof(cmd), &p);
1405 
1406  if (!av_strcasecmp(cmd, "ACL"))
1407  parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl, line_num);
1408  }
1409  fclose(f);
1410  return acl;
1411 }
1412 
1413 
1414 static void free_acl_list(IPAddressACL *in_acl)
1415 {
1416  IPAddressACL *pacl,*pacl2;
1417 
1418  pacl = in_acl;
1419  while(pacl) {
1420  pacl2 = pacl;
1421  pacl = pacl->next;
1422  av_freep(pacl2);
1423  }
1424 }
1425 
1427 {
1428  enum IPAddressAction last_action = IP_DENY;
1429  IPAddressACL *acl;
1430  struct in_addr *src = &c->from_addr.sin_addr;
1431  unsigned long src_addr = src->s_addr;
1432 
1433  for (acl = in_acl; acl; acl = acl->next) {
1434  if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr)
1435  return (acl->action == IP_ALLOW) ? 1 : 0;
1436  last_action = acl->action;
1437  }
1438 
1439  /* Nothing matched, so return not the last action */
1440  return (last_action == IP_DENY) ? 1 : 0;
1441 }
1442 
1443 static int validate_acl(FFStream *stream, HTTPContext *c)
1444 {
1445  int ret = 0;
1446  IPAddressACL *acl;
1447 
1448 
1449  /* if stream->acl is null validate_acl_list will return 1 */
1450  ret = validate_acl_list(stream->acl, c);
1451 
1452  if (stream->dynamic_acl[0]) {
1453  acl = parse_dynamic_acl(stream, c);
1454 
1455  ret = validate_acl_list(acl, c);
1456 
1457  free_acl_list(acl);
1458  }
1459 
1460  return ret;
1461 }
1462 
1463 /* compute the real filename of a file by matching it without its
1464  extensions to all the stream filenames */
1465 static void compute_real_filename(char *filename, int max_size)
1466 {
1467  char file1[1024];
1468  char file2[1024];
1469  char *p;
1470  FFStream *stream;
1471 
1472  /* compute filename by matching without the file extensions */
1473  av_strlcpy(file1, filename, sizeof(file1));
1474  p = strrchr(file1, '.');
1475  if (p)
1476  *p = '\0';
1477  for(stream = first_stream; stream != NULL; stream = stream->next) {
1478  av_strlcpy(file2, stream->filename, sizeof(file2));
1479  p = strrchr(file2, '.');
1480  if (p)
1481  *p = '\0';
1482  if (!strcmp(file1, file2)) {
1483  av_strlcpy(filename, stream->filename, max_size);
1484  break;
1485  }
1486  }
1487 }
1488 
1496 };
1497 
1498 /* parse http request and prepare header */
1500 {
1501  const char *p;
1502  char *p1;
1503  enum RedirType redir_type;
1504  char cmd[32];
1505  char info[1024], filename[1024];
1506  char url[1024], *q;
1507  char protocol[32];
1508  char msg[1024];
1509  const char *mime_type;
1510  FFStream *stream;
1511  int i;
1512  char ratebuf[32];
1513  const char *useragent = 0;
1514 
1515  p = c->buffer;
1516  get_word(cmd, sizeof(cmd), &p);
1517  av_strlcpy(c->method, cmd, sizeof(c->method));
1518 
1519  if (!strcmp(cmd, "GET"))
1520  c->post = 0;
1521  else if (!strcmp(cmd, "POST"))
1522  c->post = 1;
1523  else
1524  return -1;
1525 
1526  get_word(url, sizeof(url), &p);
1527  av_strlcpy(c->url, url, sizeof(c->url));
1528 
1529  get_word(protocol, sizeof(protocol), (const char **)&p);
1530  if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
1531  return -1;
1532 
1533  av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
1534 
1535  if (ffserver_debug)
1536  http_log("%s - - New connection: %s %s\n", inet_ntoa(c->from_addr.sin_addr), cmd, url);
1537 
1538  /* find the filename and the optional info string in the request */
1539  p1 = strchr(url, '?');
1540  if (p1) {
1541  av_strlcpy(info, p1, sizeof(info));
1542  *p1 = '\0';
1543  } else
1544  info[0] = '\0';
1545 
1546  av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1);
1547 
1548  for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1549  if (av_strncasecmp(p, "User-Agent:", 11) == 0) {
1550  useragent = p + 11;
1551  if (*useragent && *useragent != '\n' && av_isspace(*useragent))
1552  useragent++;
1553  break;
1554  }
1555  p = strchr(p, '\n');
1556  if (!p)
1557  break;
1558 
1559  p++;
1560  }
1561 
1562  redir_type = REDIR_NONE;
1563  if (av_match_ext(filename, "asx")) {
1564  redir_type = REDIR_ASX;
1565  filename[strlen(filename)-1] = 'f';
1566  } else if (av_match_ext(filename, "asf") &&
1567  (!useragent || av_strncasecmp(useragent, "NSPlayer", 8) != 0)) {
1568  /* if this isn't WMP or lookalike, return the redirector file */
1569  redir_type = REDIR_ASF;
1570  } else if (av_match_ext(filename, "rpm,ram")) {
1571  redir_type = REDIR_RAM;
1572  strcpy(filename + strlen(filename)-2, "m");
1573  } else if (av_match_ext(filename, "rtsp")) {
1574  redir_type = REDIR_RTSP;
1575  compute_real_filename(filename, sizeof(filename) - 1);
1576  } else if (av_match_ext(filename, "sdp")) {
1577  redir_type = REDIR_SDP;
1578  compute_real_filename(filename, sizeof(filename) - 1);
1579  }
1580 
1581  // "redirect" / request to index.html
1582  if (!strlen(filename))
1583  av_strlcpy(filename, "index.html", sizeof(filename) - 1);
1584 
1585  stream = first_stream;
1586  while (stream != NULL) {
1587  if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
1588  break;
1589  stream = stream->next;
1590  }
1591  if (stream == NULL) {
1592  snprintf(msg, sizeof(msg), "File '%s' not found", url);
1593  http_log("File '%s' not found\n", url);
1594  goto send_error;
1595  }
1596 
1597  c->stream = stream;
1598  memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
1599  memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
1600 
1601  if (stream->stream_type == STREAM_TYPE_REDIRECT) {
1602  c->http_error = 301;
1603  q = c->buffer;
1604  snprintf(q, c->buffer_size,
1605  "HTTP/1.0 301 Moved\r\n"
1606  "Location: %s\r\n"
1607  "Content-type: text/html\r\n"
1608  "\r\n"
1609  "<html><head><title>Moved</title></head><body>\r\n"
1610  "You should be <a href=\"%s\">redirected</a>.\r\n"
1611  "</body></html>\r\n", stream->feed_filename, stream->feed_filename);
1612  q += strlen(q);
1613  /* prepare output buffer */
1614  c->buffer_ptr = c->buffer;
1615  c->buffer_end = q;
1617  return 0;
1618  }
1619 
1620  /* If this is WMP, get the rate information */
1621  if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1622  if (modify_current_stream(c, ratebuf)) {
1623  for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) {
1624  if (c->switch_feed_streams[i] >= 0)
1625  c->switch_feed_streams[i] = -1;
1626  }
1627  }
1628  }
1629 
1630  if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
1631  current_bandwidth += stream->bandwidth;
1632 
1633  /* If already streaming this feed, do not let start another feeder. */
1634  if (stream->feed_opened) {
1635  snprintf(msg, sizeof(msg), "This feed is already being received.");
1636  http_log("Feed '%s' already being received\n", stream->feed_filename);
1637  goto send_error;
1638  }
1639 
1640  if (c->post == 0 && max_bandwidth < current_bandwidth) {
1641  c->http_error = 503;
1642  q = c->buffer;
1643  snprintf(q, c->buffer_size,
1644  "HTTP/1.0 503 Server too busy\r\n"
1645  "Content-type: text/html\r\n"
1646  "\r\n"
1647  "<html><head><title>Too busy</title></head><body>\r\n"
1648  "<p>The server is too busy to serve your request at this time.</p>\r\n"
1649  "<p>The bandwidth being served (including your stream) is %"PRIu64"kbit/sec, "
1650  "and this exceeds the limit of %"PRIu64"kbit/sec.</p>\r\n"
1651  "</body></html>\r\n", current_bandwidth, max_bandwidth);
1652  q += strlen(q);
1653  /* prepare output buffer */
1654  c->buffer_ptr = c->buffer;
1655  c->buffer_end = q;
1657  return 0;
1658  }
1659 
1660  if (redir_type != REDIR_NONE) {
1661  const char *hostinfo = 0;
1662 
1663  for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1664  if (av_strncasecmp(p, "Host:", 5) == 0) {
1665  hostinfo = p + 5;
1666  break;
1667  }
1668  p = strchr(p, '\n');
1669  if (!p)
1670  break;
1671 
1672  p++;
1673  }
1674 
1675  if (hostinfo) {
1676  char *eoh;
1677  char hostbuf[260];
1678 
1679  while (av_isspace(*hostinfo))
1680  hostinfo++;
1681 
1682  eoh = strchr(hostinfo, '\n');
1683  if (eoh) {
1684  if (eoh[-1] == '\r')
1685  eoh--;
1686 
1687  if (eoh - hostinfo < sizeof(hostbuf) - 1) {
1688  memcpy(hostbuf, hostinfo, eoh - hostinfo);
1689  hostbuf[eoh - hostinfo] = 0;
1690 
1691  c->http_error = 200;
1692  q = c->buffer;
1693  switch(redir_type) {
1694  case REDIR_ASX:
1695  snprintf(q, c->buffer_size,
1696  "HTTP/1.0 200 ASX Follows\r\n"
1697  "Content-type: video/x-ms-asf\r\n"
1698  "\r\n"
1699  "<ASX Version=\"3\">\r\n"
1700  //"<!-- Autogenerated by ffserver -->\r\n"
1701  "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1702  "</ASX>\r\n", hostbuf, filename, info);
1703  q += strlen(q);
1704  break;
1705  case REDIR_RAM:
1706  snprintf(q, c->buffer_size,
1707  "HTTP/1.0 200 RAM Follows\r\n"
1708  "Content-type: audio/x-pn-realaudio\r\n"
1709  "\r\n"
1710  "# Autogenerated by ffserver\r\n"
1711  "http://%s/%s%s\r\n", hostbuf, filename, info);
1712  q += strlen(q);
1713  break;
1714  case REDIR_ASF:
1715  snprintf(q, c->buffer_size,
1716  "HTTP/1.0 200 ASF Redirect follows\r\n"
1717  "Content-type: video/x-ms-asf\r\n"
1718  "\r\n"
1719  "[Reference]\r\n"
1720  "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1721  q += strlen(q);
1722  break;
1723  case REDIR_RTSP:
1724  {
1725  char hostname[256], *p;
1726  /* extract only hostname */
1727  av_strlcpy(hostname, hostbuf, sizeof(hostname));
1728  p = strrchr(hostname, ':');
1729  if (p)
1730  *p = '\0';
1731  snprintf(q, c->buffer_size,
1732  "HTTP/1.0 200 RTSP Redirect follows\r\n"
1733  /* XXX: incorrect mime type ? */
1734  "Content-type: application/x-rtsp\r\n"
1735  "\r\n"
1736  "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename);
1737  q += strlen(q);
1738  }
1739  break;
1740  case REDIR_SDP:
1741  {
1742  uint8_t *sdp_data;
1743  int sdp_data_size;
1744  socklen_t len;
1745  struct sockaddr_in my_addr;
1746 
1747  snprintf(q, c->buffer_size,
1748  "HTTP/1.0 200 OK\r\n"
1749  "Content-type: application/sdp\r\n"
1750  "\r\n");
1751  q += strlen(q);
1752 
1753  len = sizeof(my_addr);
1754  getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
1755 
1756  /* XXX: should use a dynamic buffer */
1757  sdp_data_size = prepare_sdp_description(stream,
1758  &sdp_data,
1759  my_addr.sin_addr);
1760  if (sdp_data_size > 0) {
1761  memcpy(q, sdp_data, sdp_data_size);
1762  q += sdp_data_size;
1763  *q = '\0';
1764  av_free(sdp_data);
1765  }
1766  }
1767  break;
1768  default:
1769  abort();
1770  break;
1771  }
1772 
1773  /* prepare output buffer */
1774  c->buffer_ptr = c->buffer;
1775  c->buffer_end = q;
1777  return 0;
1778  }
1779  }
1780  }
1781 
1782  snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
1783  goto send_error;
1784  }
1785 
1786  stream->conns_served++;
1787 
1788  /* XXX: add there authenticate and IP match */
1789 
1790  if (c->post) {
1791  /* if post, it means a feed is being sent */
1792  if (!stream->is_feed) {
1793  /* However it might be a status report from WMP! Let us log the
1794  * data as it might come in handy one day. */
1795  const char *logline = 0;
1796  int client_id = 0;
1797 
1798  for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1799  if (av_strncasecmp(p, "Pragma: log-line=", 17) == 0) {
1800  logline = p;
1801  break;
1802  }
1803  if (av_strncasecmp(p, "Pragma: client-id=", 18) == 0)
1804  client_id = strtol(p + 18, 0, 10);
1805  p = strchr(p, '\n');
1806  if (!p)
1807  break;
1808 
1809  p++;
1810  }
1811 
1812  if (logline) {
1813  char *eol = strchr(logline, '\n');
1814 
1815  logline += 17;
1816 
1817  if (eol) {
1818  if (eol[-1] == '\r')
1819  eol--;
1820  http_log("%.*s\n", (int) (eol - logline), logline);
1821  c->suppress_log = 1;
1822  }
1823  }
1824 
1825 #ifdef DEBUG
1826  http_log("\nGot request:\n%s\n", c->buffer);
1827 #endif
1828 
1829  if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1830  HTTPContext *wmpc;
1831 
1832  /* Now we have to find the client_id */
1833  for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
1834  if (wmpc->wmp_client_id == client_id)
1835  break;
1836  }
1837 
1838  if (wmpc && modify_current_stream(wmpc, ratebuf))
1839  wmpc->switch_pending = 1;
1840  }
1841 
1842  snprintf(msg, sizeof(msg), "POST command not handled");
1843  c->stream = 0;
1844  goto send_error;
1845  }
1846  if (http_start_receive_data(c) < 0) {
1847  snprintf(msg, sizeof(msg), "could not open feed");
1848  goto send_error;
1849  }
1850  c->http_error = 0;
1852  return 0;
1853  }
1854 
1855 #ifdef DEBUG
1856  if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0)
1857  http_log("\nGot request:\n%s\n", c->buffer);
1858 #endif
1859 
1861  goto send_status;
1862 
1863  /* open input stream */
1864  if (open_input_stream(c, info) < 0) {
1865  snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
1866  goto send_error;
1867  }
1868 
1869  /* prepare http header */
1870  c->buffer[0] = 0;
1871  av_strlcatf(c->buffer, c->buffer_size, "HTTP/1.0 200 OK\r\n");
1872  mime_type = c->stream->fmt->mime_type;
1873  if (!mime_type)
1874  mime_type = "application/x-octet-stream";
1875  av_strlcatf(c->buffer, c->buffer_size, "Pragma: no-cache\r\n");
1876 
1877  /* for asf, we need extra headers */
1878  if (!strcmp(c->stream->fmt->name,"asf_stream")) {
1879  /* Need to allocate a client id */
1880 
1881  c->wmp_client_id = av_lfg_get(&random_state);
1882 
1883  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);
1884  }
1885  av_strlcatf(c->buffer, c->buffer_size, "Content-Type: %s\r\n", mime_type);
1886  av_strlcatf(c->buffer, c->buffer_size, "\r\n");
1887  q = c->buffer + strlen(c->buffer);
1888 
1889  /* prepare output buffer */
1890  c->http_error = 0;
1891  c->buffer_ptr = c->buffer;
1892  c->buffer_end = q;
1894  return 0;
1895  send_error:
1896  c->http_error = 404;
1897  q = c->buffer;
1898  htmlstrip(msg);
1899  snprintf(q, c->buffer_size,
1900  "HTTP/1.0 404 Not Found\r\n"
1901  "Content-type: text/html\r\n"
1902  "\r\n"
1903  "<html>\n"
1904  "<head><title>404 Not Found</title></head>\n"
1905  "<body>%s</body>\n"
1906  "</html>\n", msg);
1907  q += strlen(q);
1908  /* prepare output buffer */
1909  c->buffer_ptr = c->buffer;
1910  c->buffer_end = q;
1912  return 0;
1913  send_status:
1914  compute_status(c);
1915  c->http_error = 200; /* horrible : we use this value to avoid
1916  going to the send data state */
1918  return 0;
1919 }
1920 
1921 static void fmt_bytecount(AVIOContext *pb, int64_t count)
1922 {
1923  static const char suffix[] = " kMGTP";
1924  const char *s;
1925 
1926  for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1927 
1928  avio_printf(pb, "%"PRId64"%c", count, *s);
1929 }
1930 
1932 {
1933  HTTPContext *c1;
1934  FFStream *stream;
1935  char *p;
1936  time_t ti;
1937  int i, len;
1938  AVIOContext *pb;
1939 
1940  if (avio_open_dyn_buf(&pb) < 0) {
1941  /* XXX: return an error ? */
1942  c->buffer_ptr = c->buffer;
1943  c->buffer_end = c->buffer;
1944  return;
1945  }
1946 
1947  avio_printf(pb, "HTTP/1.0 200 OK\r\n");
1948  avio_printf(pb, "Content-type: %s\r\n", "text/html");
1949  avio_printf(pb, "Pragma: no-cache\r\n");
1950  avio_printf(pb, "\r\n");
1951 
1952  avio_printf(pb, "<html><head><title>%s Status</title>\n", program_name);
1953  if (c->stream->feed_filename[0])
1954  avio_printf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
1955  avio_printf(pb, "</head>\n<body>");
1956  avio_printf(pb, "<h1>%s Status</h1>\n", program_name);
1957  /* format status */
1958  avio_printf(pb, "<h2>Available Streams</h2>\n");
1959  avio_printf(pb, "<table cellspacing=0 cellpadding=4>\n");
1960  avio_printf(pb, "<tr><th valign=top>Path<th align=left>Served<br>Conns<th><br>bytes<th valign=top>Format<th>Bit rate<br>kbits/s<th align=left>Video<br>kbits/s<th><br>Codec<th align=left>Audio<br>kbits/s<th><br>Codec<th align=left valign=top>Feed\n");
1961  stream = first_stream;
1962  while (stream != NULL) {
1963  char sfilename[1024];
1964  char *eosf;
1965 
1966  if (stream->feed != stream) {
1967  av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
1968  eosf = sfilename + strlen(sfilename);
1969  if (eosf - sfilename >= 4) {
1970  if (strcmp(eosf - 4, ".asf") == 0)
1971  strcpy(eosf - 4, ".asx");
1972  else if (strcmp(eosf - 3, ".rm") == 0)
1973  strcpy(eosf - 3, ".ram");
1974  else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
1975  /* generate a sample RTSP director if
1976  unicast. Generate an SDP redirector if
1977  multicast */
1978  eosf = strrchr(sfilename, '.');
1979  if (!eosf)
1980  eosf = sfilename + strlen(sfilename);
1981  if (stream->is_multicast)
1982  strcpy(eosf, ".sdp");
1983  else
1984  strcpy(eosf, ".rtsp");
1985  }
1986  }
1987 
1988  avio_printf(pb, "<tr><td><a href=\"/%s\">%s</a> ",
1989  sfilename, stream->filename);
1990  avio_printf(pb, "<td align=right> %d <td align=right> ",
1991  stream->conns_served);
1992  fmt_bytecount(pb, stream->bytes_served);
1993  switch(stream->stream_type) {
1994  case STREAM_TYPE_LIVE: {
1995  int audio_bit_rate = 0;
1996  int video_bit_rate = 0;
1997  const char *audio_codec_name = "";
1998  const char *video_codec_name = "";
1999  const char *audio_codec_name_extra = "";
2000  const char *video_codec_name_extra = "";
2001 
2002  for(i=0;i<stream->nb_streams;i++) {
2003  AVStream *st = stream->streams[i];
2004  AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
2005  switch(st->codec->codec_type) {
2006  case AVMEDIA_TYPE_AUDIO:
2007  audio_bit_rate += st->codec->bit_rate;
2008  if (codec) {
2009  if (*audio_codec_name)
2010  audio_codec_name_extra = "...";
2011  audio_codec_name = codec->name;
2012  }
2013  break;
2014  case AVMEDIA_TYPE_VIDEO:
2015  video_bit_rate += st->codec->bit_rate;
2016  if (codec) {
2017  if (*video_codec_name)
2018  video_codec_name_extra = "...";
2019  video_codec_name = codec->name;
2020  }
2021  break;
2022  case AVMEDIA_TYPE_DATA:
2023  video_bit_rate += st->codec->bit_rate;
2024  break;
2025  default:
2026  abort();
2027  }
2028  }
2029  avio_printf(pb, "<td align=center> %s <td align=right> %d <td align=right> %d <td> %s %s <td align=right> %d <td> %s %s",
2030  stream->fmt->name,
2031  stream->bandwidth,
2032  video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
2033  audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
2034  if (stream->feed)
2035  avio_printf(pb, "<td>%s", stream->feed->filename);
2036  else
2037  avio_printf(pb, "<td>%s", stream->feed_filename);
2038  avio_printf(pb, "\n");
2039  }
2040  break;
2041  default:
2042  avio_printf(pb, "<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
2043  break;
2044  }
2045  }
2046  stream = stream->next;
2047  }
2048  avio_printf(pb, "</table>\n");
2049 
2050  stream = first_stream;
2051  while (stream != NULL) {
2052  if (stream->feed == stream) {
2053  avio_printf(pb, "<h2>Feed %s</h2>", stream->filename);
2054  if (stream->pid) {
2055  avio_printf(pb, "Running as pid %d.\n", stream->pid);
2056 
2057 #if defined(linux)
2058  {
2059  FILE *pid_stat;
2060  char ps_cmd[64];
2061 
2062  /* This is somewhat linux specific I guess */
2063  snprintf(ps_cmd, sizeof(ps_cmd),
2064  "ps -o \"%%cpu,cputime\" --no-headers %d",
2065  stream->pid);
2066 
2067  pid_stat = popen(ps_cmd, "r");
2068  if (pid_stat) {
2069  char cpuperc[10];
2070  char cpuused[64];
2071 
2072  if (fscanf(pid_stat, "%9s %63s", cpuperc,
2073  cpuused) == 2) {
2074  avio_printf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
2075  cpuperc, cpuused);
2076  }
2077  fclose(pid_stat);
2078  }
2079  }
2080 #endif
2081 
2082  avio_printf(pb, "<p>");
2083  }
2084  avio_printf(pb, "<table cellspacing=0 cellpadding=4><tr><th>Stream<th>type<th>kbits/s<th align=left>codec<th align=left>Parameters\n");
2085 
2086  for (i = 0; i < stream->nb_streams; i++) {
2087  AVStream *st = stream->streams[i];
2088  AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
2089  const char *type = "unknown";
2090  char parameters[64];
2091 
2092  parameters[0] = 0;
2093 
2094  switch(st->codec->codec_type) {
2095  case AVMEDIA_TYPE_AUDIO:
2096  type = "audio";
2097  snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz", st->codec->channels, st->codec->sample_rate);
2098  break;
2099  case AVMEDIA_TYPE_VIDEO:
2100  type = "video";
2101  snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec->width, st->codec->height,
2102  st->codec->qmin, st->codec->qmax, st->codec->time_base.den / st->codec->time_base.num);
2103  break;
2104  default:
2105  abort();
2106  }
2107  avio_printf(pb, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2108  i, type, st->codec->bit_rate/1000, codec ? codec->name : "", parameters);
2109  }
2110  avio_printf(pb, "</table>\n");
2111 
2112  }
2113  stream = stream->next;
2114  }
2115 
2116  /* connection status */
2117  avio_printf(pb, "<h2>Connection Status</h2>\n");
2118 
2119  avio_printf(pb, "Number of connections: %d / %d<br>\n",
2121 
2122  avio_printf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<br>\n",
2124 
2125  avio_printf(pb, "<table>\n");
2126  avio_printf(pb, "<tr><th>#<th>File<th>IP<th>Proto<th>State<th>Target bits/sec<th>Actual bits/sec<th>Bytes transferred\n");
2127  c1 = first_http_ctx;
2128  i = 0;
2129  while (c1 != NULL) {
2130  int bitrate;
2131  int j;
2132 
2133  bitrate = 0;
2134  if (c1->stream) {
2135  for (j = 0; j < c1->stream->nb_streams; j++) {
2136  if (!c1->stream->feed)
2137  bitrate += c1->stream->streams[j]->codec->bit_rate;
2138  else if (c1->feed_streams[j] >= 0)
2139  bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
2140  }
2141  }
2142 
2143  i++;
2144  p = inet_ntoa(c1->from_addr.sin_addr);
2145  avio_printf(pb, "<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2146  i,
2147  c1->stream ? c1->stream->filename : "",
2148  c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
2149  p,
2150  c1->protocol,
2151  http_state[c1->state]);
2152  fmt_bytecount(pb, bitrate);
2153  avio_printf(pb, "<td align=right>");
2154  fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
2155  avio_printf(pb, "<td align=right>");
2156  fmt_bytecount(pb, c1->data_count);
2157  avio_printf(pb, "\n");
2158  c1 = c1->next;
2159  }
2160  avio_printf(pb, "</table>\n");
2161 
2162  /* date */
2163  ti = time(NULL);
2164  p = ctime(&ti);
2165  avio_printf(pb, "<hr size=1 noshade>Generated at %s", p);
2166  avio_printf(pb, "</body>\n</html>\n");
2167 
2168  len = avio_close_dyn_buf(pb, &c->pb_buffer);
2169  c->buffer_ptr = c->pb_buffer;
2170  c->buffer_end = c->pb_buffer + len;
2171 }
2172 
2173 static int open_input_stream(HTTPContext *c, const char *info)
2174 {
2175  char buf[128];
2176  char input_filename[1024];
2177  AVFormatContext *s = NULL;
2178  int buf_size, i, ret;
2179  int64_t stream_pos;
2180 
2181  /* find file name */
2182  if (c->stream->feed) {
2183  strcpy(input_filename, c->stream->feed->feed_filename);
2184  buf_size = FFM_PACKET_SIZE;
2185  /* compute position (absolute time) */
2186  if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2187  if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0)
2188  return ret;
2189  } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) {
2190  int prebuffer = strtol(buf, 0, 10);
2191  stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
2192  } else
2193  stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
2194  } else {
2195  strcpy(input_filename, c->stream->feed_filename);
2196  buf_size = 0;
2197  /* compute position (relative time) */
2198  if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2199  if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0)
2200  return ret;
2201  } else
2202  stream_pos = 0;
2203  }
2204  if (input_filename[0] == '\0')
2205  return -1;
2206 
2207  /* open stream */
2208  if ((ret = avformat_open_input(&s, input_filename, c->stream->ifmt, &c->stream->in_opts)) < 0) {
2209  http_log("could not open %s: %d\n", input_filename, ret);
2210  return -1;
2211  }
2212 
2213  /* set buffer size */
2214  if (buf_size > 0) ffio_set_buf_size(s->pb, buf_size);
2215 
2216  s->flags |= AVFMT_FLAG_GENPTS;
2217  c->fmt_in = s;
2218  if (strcmp(s->iformat->name, "ffm") && avformat_find_stream_info(c->fmt_in, NULL) < 0) {
2219  http_log("Could not find stream info '%s'\n", input_filename);
2221  return -1;
2222  }
2223 
2224  /* choose stream as clock source (we favorize video stream if
2225  present) for packet sending */
2226  c->pts_stream_index = 0;
2227  for(i=0;i<c->stream->nb_streams;i++) {
2228  if (c->pts_stream_index == 0 &&
2230  c->pts_stream_index = i;
2231  }
2232  }
2233 
2234  if (c->fmt_in->iformat->read_seek)
2235  av_seek_frame(c->fmt_in, -1, stream_pos, 0);
2236  /* set the start time (needed for maxtime and RTP packet timing) */
2237  c->start_time = cur_time;
2239  return 0;
2240 }
2241 
2242 /* return the server clock (in us) */
2244 {
2245  /* compute current pts value from system time */
2246  return (cur_time - c->start_time) * 1000;
2247 }
2248 
2249 /* return the estimated time at which the current packet must be sent
2250  (in us) */
2252 {
2253  int bytes_left, bytes_sent, frame_bytes;
2254 
2255  frame_bytes = c->cur_frame_bytes;
2256  if (frame_bytes <= 0)
2257  return c->cur_pts;
2258  else {
2259  bytes_left = c->buffer_end - c->buffer_ptr;
2260  bytes_sent = frame_bytes - bytes_left;
2261  return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
2262  }
2263 }
2264 
2265 
2267 {
2268  int i, len, ret;
2269  AVFormatContext *ctx;
2270 
2271  av_freep(&c->pb_buffer);
2272  switch(c->state) {
2274  memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
2275  av_dict_set(&c->fmt_ctx.metadata, "author" , c->stream->author , 0);
2276  av_dict_set(&c->fmt_ctx.metadata, "comment" , c->stream->comment , 0);
2277  av_dict_set(&c->fmt_ctx.metadata, "copyright", c->stream->copyright, 0);
2278  av_dict_set(&c->fmt_ctx.metadata, "title" , c->stream->title , 0);
2279 
2280  c->fmt_ctx.streams = av_mallocz(sizeof(AVStream *) * c->stream->nb_streams);
2281 
2282  for(i=0;i<c->stream->nb_streams;i++) {
2283  AVStream *src;
2284  c->fmt_ctx.streams[i] = av_mallocz(sizeof(AVStream));
2285  /* if file or feed, then just take streams from FFStream struct */
2286  if (!c->stream->feed ||
2287  c->stream->feed == c->stream)
2288  src = c->stream->streams[i];
2289  else
2290  src = c->stream->feed->streams[c->stream->feed_streams[i]];
2291 
2292  *(c->fmt_ctx.streams[i]) = *src;
2293  c->fmt_ctx.streams[i]->priv_data = 0;
2294  c->fmt_ctx.streams[i]->codec->frame_number = 0; /* XXX: should be done in
2295  AVStream, not in codec */
2296  }
2297  /* set output format parameters */
2298  c->fmt_ctx.oformat = c->stream->fmt;
2300 
2301  c->got_key_frame = 0;
2302 
2303  /* prepare header and save header data in a stream */
2304  if (avio_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
2305  /* XXX: potential leak */
2306  return -1;
2307  }
2308  c->fmt_ctx.pb->seekable = 0;
2309 
2310  /*
2311  * HACK to avoid mpeg ps muxer to spit many underflow errors
2312  * Default value from FFmpeg
2313  * Try to set it use configuration option
2314  */
2315  c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
2316 
2317  if (avformat_write_header(&c->fmt_ctx, NULL) < 0) {
2318  http_log("Error writing output header\n");
2319  return -1;
2320  }
2322 
2323  len = avio_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
2324  c->buffer_ptr = c->pb_buffer;
2325  c->buffer_end = c->pb_buffer + len;
2326 
2328  c->last_packet_sent = 0;
2329  break;
2330  case HTTPSTATE_SEND_DATA:
2331  /* find a new packet */
2332  /* read a packet from the input stream */
2333  if (c->stream->feed)
2336  c->stream->feed->feed_size);
2337 
2338  if (c->stream->max_time &&
2339  c->stream->max_time + c->start_time - cur_time < 0)
2340  /* We have timed out */
2342  else {
2343  AVPacket pkt;
2344  redo:
2345  ret = av_read_frame(c->fmt_in, &pkt);
2346  if (ret < 0) {
2347  if (c->stream->feed) {
2348  /* if coming from feed, it means we reached the end of the
2349  ffm file, so must wait for more data */
2351  return 1; /* state changed */
2352  } else if (ret == AVERROR(EAGAIN)) {
2353  /* input not ready, come back later */
2354  return 0;
2355  } else {
2356  if (c->stream->loop) {
2358  if (open_input_stream(c, "") < 0)
2359  goto no_loop;
2360  goto redo;
2361  } else {
2362  no_loop:
2363  /* must send trailer now because eof or error */
2365  }
2366  }
2367  } else {
2368  int source_index = pkt.stream_index;
2369  /* update first pts if needed */
2370  if (c->first_pts == AV_NOPTS_VALUE) {
2372  c->start_time = cur_time;
2373  }
2374  /* send it to the appropriate stream */
2375  if (c->stream->feed) {
2376  /* if coming from a feed, select the right stream */
2377  if (c->switch_pending) {
2378  c->switch_pending = 0;
2379  for(i=0;i<c->stream->nb_streams;i++) {
2380  if (c->switch_feed_streams[i] == pkt.stream_index)
2381  if (pkt.flags & AV_PKT_FLAG_KEY)
2382  c->switch_feed_streams[i] = -1;
2383  if (c->switch_feed_streams[i] >= 0)
2384  c->switch_pending = 1;
2385  }
2386  }
2387  for(i=0;i<c->stream->nb_streams;i++) {
2388  if (c->stream->feed_streams[i] == pkt.stream_index) {
2389  AVStream *st = c->fmt_in->streams[source_index];
2390  pkt.stream_index = i;
2391  if (pkt.flags & AV_PKT_FLAG_KEY &&
2392  (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2393  c->stream->nb_streams == 1))
2394  c->got_key_frame = 1;
2395  if (!c->stream->send_on_key || c->got_key_frame)
2396  goto send_it;
2397  }
2398  }
2399  } else {
2400  AVCodecContext *codec;
2401  AVStream *ist, *ost;
2402  send_it:
2403  ist = c->fmt_in->streams[source_index];
2404  /* specific handling for RTP: we use several
2405  output stream (one for each RTP
2406  connection). XXX: need more abstract handling */
2407  if (c->is_packetized) {
2408  /* compute send time and duration */
2409  c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
2410  c->cur_pts -= c->first_pts;
2412  /* find RTP context */
2414  ctx = c->rtp_ctx[c->packet_stream_index];
2415  if(!ctx) {
2416  av_free_packet(&pkt);
2417  break;
2418  }
2419  codec = ctx->streams[0]->codec;
2420  /* only one stream per RTP connection */
2421  pkt.stream_index = 0;
2422  } else {
2423  ctx = &c->fmt_ctx;
2424  /* Fudge here */
2425  codec = ctx->streams[pkt.stream_index]->codec;
2426  }
2427 
2428  if (c->is_packetized) {
2429  int max_packet_size;
2431  max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2432  else
2433  max_packet_size = c->rtp_handles[c->packet_stream_index]->max_packet_size;
2434  ret = ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size);
2435  } else {
2436  ret = avio_open_dyn_buf(&ctx->pb);
2437  }
2438  if (ret < 0) {
2439  /* XXX: potential leak */
2440  return -1;
2441  }
2442  ost = ctx->streams[pkt.stream_index];
2443 
2444  ctx->pb->seekable = 0;
2445  if (pkt.dts != AV_NOPTS_VALUE)
2446  pkt.dts = av_rescale_q(pkt.dts, ist->time_base, ost->time_base);
2447  if (pkt.pts != AV_NOPTS_VALUE)
2448  pkt.pts = av_rescale_q(pkt.pts, ist->time_base, ost->time_base);
2449  pkt.duration = av_rescale_q(pkt.duration, ist->time_base, ost->time_base);
2450  if (av_write_frame(ctx, &pkt) < 0) {
2451  http_log("Error writing frame to output\n");
2453  }
2454 
2455  len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2456  c->cur_frame_bytes = len;
2457  c->buffer_ptr = c->pb_buffer;
2458  c->buffer_end = c->pb_buffer + len;
2459 
2460  codec->frame_number++;
2461  if (len == 0) {
2462  av_free_packet(&pkt);
2463  goto redo;
2464  }
2465  }
2466  av_free_packet(&pkt);
2467  }
2468  }
2469  break;
2470  default:
2472  /* last packet test ? */
2473  if (c->last_packet_sent || c->is_packetized)
2474  return -1;
2475  ctx = &c->fmt_ctx;
2476  /* prepare header */
2477  if (avio_open_dyn_buf(&ctx->pb) < 0) {
2478  /* XXX: potential leak */
2479  return -1;
2480  }
2481  c->fmt_ctx.pb->seekable = 0;
2482  av_write_trailer(ctx);
2483  len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2484  c->buffer_ptr = c->pb_buffer;
2485  c->buffer_end = c->pb_buffer + len;
2486 
2487  c->last_packet_sent = 1;
2488  break;
2489  }
2490  return 0;
2491 }
2492 
2493 /* should convert the format at the same time */
2494 /* send data starting at c->buffer_ptr to the output connection
2495  (either UDP or TCP connection) */
2497 {
2498  int len, ret;
2499 
2500  for(;;) {
2501  if (c->buffer_ptr >= c->buffer_end) {
2502  ret = http_prepare_data(c);
2503  if (ret < 0)
2504  return -1;
2505  else if (ret != 0)
2506  /* state change requested */
2507  break;
2508  } else {
2509  if (c->is_packetized) {
2510  /* RTP data output */
2511  len = c->buffer_end - c->buffer_ptr;
2512  if (len < 4) {
2513  /* fail safe - should never happen */
2514  fail1:
2515  c->buffer_ptr = c->buffer_end;
2516  return 0;
2517  }
2518  len = (c->buffer_ptr[0] << 24) |
2519  (c->buffer_ptr[1] << 16) |
2520  (c->buffer_ptr[2] << 8) |
2521  (c->buffer_ptr[3]);
2522  if (len > (c->buffer_end - c->buffer_ptr))
2523  goto fail1;
2524  if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2525  /* nothing to send yet: we can wait */
2526  return 0;
2527  }
2528 
2529  c->data_count += len;
2531  if (c->stream)
2532  c->stream->bytes_served += len;
2533 
2535  /* RTP packets are sent inside the RTSP TCP connection */
2536  AVIOContext *pb;
2537  int interleaved_index, size;
2538  uint8_t header[4];
2539  HTTPContext *rtsp_c;
2540 
2541  rtsp_c = c->rtsp_c;
2542  /* if no RTSP connection left, error */
2543  if (!rtsp_c)
2544  return -1;
2545  /* if already sending something, then wait. */
2546  if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2547  break;
2548  if (avio_open_dyn_buf(&pb) < 0)
2549  goto fail1;
2550  interleaved_index = c->packet_stream_index * 2;
2551  /* RTCP packets are sent at odd indexes */
2552  if (c->buffer_ptr[1] == 200)
2553  interleaved_index++;
2554  /* write RTSP TCP header */
2555  header[0] = '$';
2556  header[1] = interleaved_index;
2557  header[2] = len >> 8;
2558  header[3] = len;
2559  avio_write(pb, header, 4);
2560  /* write RTP packet data */
2561  c->buffer_ptr += 4;
2562  avio_write(pb, c->buffer_ptr, len);
2563  size = avio_close_dyn_buf(pb, &c->packet_buffer);
2564  /* prepare asynchronous TCP sending */
2565  rtsp_c->packet_buffer_ptr = c->packet_buffer;
2566  rtsp_c->packet_buffer_end = c->packet_buffer + size;
2567  c->buffer_ptr += len;
2568 
2569  /* send everything we can NOW */
2570  len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2571  rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2572  if (len > 0)
2573  rtsp_c->packet_buffer_ptr += len;
2574  if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2575  /* if we could not send all the data, we will
2576  send it later, so a new state is needed to
2577  "lock" the RTSP TCP connection */
2578  rtsp_c->state = RTSPSTATE_SEND_PACKET;
2579  break;
2580  } else
2581  /* all data has been sent */
2582  av_freep(&c->packet_buffer);
2583  } else {
2584  /* send RTP packet directly in UDP */
2585  c->buffer_ptr += 4;
2587  c->buffer_ptr, len);
2588  c->buffer_ptr += len;
2589  /* here we continue as we can send several packets per 10 ms slot */
2590  }
2591  } else {
2592  /* TCP data output */
2593  len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2594  if (len < 0) {
2595  if (ff_neterrno() != AVERROR(EAGAIN) &&
2596  ff_neterrno() != AVERROR(EINTR))
2597  /* error : close connection */
2598  return -1;
2599  else
2600  return 0;
2601  } else
2602  c->buffer_ptr += len;
2603 
2604  c->data_count += len;
2606  if (c->stream)
2607  c->stream->bytes_served += len;
2608  break;
2609  }
2610  }
2611  } /* for(;;) */
2612  return 0;
2613 }
2614 
2616 {
2617  int fd;
2618 
2619  if (c->stream->feed_opened)
2620  return -1;
2621 
2622  /* Don't permit writing to this one */
2623  if (c->stream->readonly)
2624  return -1;
2625 
2626  /* open feed */
2627  fd = open(c->stream->feed_filename, O_RDWR);
2628  if (fd < 0) {
2629  http_log("Error opening feeder file: %s\n", strerror(errno));
2630  return -1;
2631  }
2632  c->feed_fd = fd;
2633 
2634  if (c->stream->truncate) {
2635  /* truncate feed file */
2637  http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2638  if (ftruncate(c->feed_fd, FFM_PACKET_SIZE) < 0) {
2639  http_log("Error truncating feed file: %s\n", strerror(errno));
2640  return -1;
2641  }
2642  } else {
2643  if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
2644  http_log("Error reading write index from feed file: %s\n", strerror(errno));
2645  return -1;
2646  }
2647  }
2648 
2650  c->stream->feed_size = lseek(fd, 0, SEEK_END);
2651  lseek(fd, 0, SEEK_SET);
2652 
2653  /* init buffer input */
2654  c->buffer_ptr = c->buffer;
2655  c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2656  c->stream->feed_opened = 1;
2657  c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2658  return 0;
2659 }
2660 
2662 {
2663  HTTPContext *c1;
2664  int len, loop_run = 0;
2665 
2666  while (c->chunked_encoding && !c->chunk_size &&
2667  c->buffer_end > c->buffer_ptr) {
2668  /* read chunk header, if present */
2669  len = recv(c->fd, c->buffer_ptr, 1, 0);
2670 
2671  if (len < 0) {
2672  if (ff_neterrno() != AVERROR(EAGAIN) &&
2673  ff_neterrno() != AVERROR(EINTR))
2674  /* error : close connection */
2675  goto fail;
2676  return 0;
2677  } else if (len == 0) {
2678  /* end of connection : close it */
2679  goto fail;
2680  } else if (c->buffer_ptr - c->buffer >= 2 &&
2681  !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2682  c->chunk_size = strtol(c->buffer, 0, 16);
2683  if (c->chunk_size == 0) // end of stream
2684  goto fail;
2685  c->buffer_ptr = c->buffer;
2686  break;
2687  } else if (++loop_run > 10) {
2688  /* no chunk header, abort */
2689  goto fail;
2690  } else {
2691  c->buffer_ptr++;
2692  }
2693  }
2694 
2695  if (c->buffer_end > c->buffer_ptr) {
2696  len = recv(c->fd, c->buffer_ptr,
2697  FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2698  if (len < 0) {
2699  if (ff_neterrno() != AVERROR(EAGAIN) &&
2700  ff_neterrno() != AVERROR(EINTR))
2701  /* error : close connection */
2702  goto fail;
2703  } else if (len == 0)
2704  /* end of connection : close it */
2705  goto fail;
2706  else {
2707  c->chunk_size -= len;
2708  c->buffer_ptr += len;
2709  c->data_count += len;
2711  }
2712  }
2713 
2714  if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2715  if (c->buffer[0] != 'f' ||
2716  c->buffer[1] != 'm') {
2717  http_log("Feed stream has become desynchronized -- disconnecting\n");
2718  goto fail;
2719  }
2720  }
2721 
2722  if (c->buffer_ptr >= c->buffer_end) {
2723  FFStream *feed = c->stream;
2724  /* a packet has been received : write it in the store, except
2725  if header */
2726  if (c->data_count > FFM_PACKET_SIZE) {
2727  /* XXX: use llseek or url_seek */
2728  lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2729  if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2730  http_log("Error writing to feed file: %s\n", strerror(errno));
2731  goto fail;
2732  }
2733 
2735  /* update file size */
2736  if (feed->feed_write_index > c->stream->feed_size)
2737  feed->feed_size = feed->feed_write_index;
2738 
2739  /* handle wrap around if max file size reached */
2740  if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2742 
2743  /* write index */
2744  if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2745  http_log("Error writing index to feed file: %s\n", strerror(errno));
2746  goto fail;
2747  }
2748 
2749  /* wake up any waiting connections */
2750  for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2751  if (c1->state == HTTPSTATE_WAIT_FEED &&
2752  c1->stream->feed == c->stream->feed)
2753  c1->state = HTTPSTATE_SEND_DATA;
2754  }
2755  } else {
2756  /* We have a header in our hands that contains useful data */
2758  AVIOContext *pb;
2759  AVInputFormat *fmt_in;
2760  int i;
2761 
2762  if (!s)
2763  goto fail;
2764 
2765  /* use feed output format name to find corresponding input format */
2766  fmt_in = av_find_input_format(feed->fmt->name);
2767  if (!fmt_in)
2768  goto fail;
2769 
2770  pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
2771  0, NULL, NULL, NULL, NULL);
2772  pb->seekable = 0;
2773 
2774  s->pb = pb;
2775  if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) {
2776  av_free(pb);
2777  goto fail;
2778  }
2779 
2780  /* Now we have the actual streams */
2781  if (s->nb_streams != feed->nb_streams) {
2783  av_free(pb);
2784  http_log("Feed '%s' stream number does not match registered feed\n",
2785  c->stream->feed_filename);
2786  goto fail;
2787  }
2788 
2789  for (i = 0; i < s->nb_streams; i++) {
2790  AVStream *fst = feed->streams[i];
2791  AVStream *st = s->streams[i];
2792  avcodec_copy_context(fst->codec, st->codec);
2793  }
2794 
2796  av_free(pb);
2797  }
2798  c->buffer_ptr = c->buffer;
2799  }
2800 
2801  return 0;
2802  fail:
2803  c->stream->feed_opened = 0;
2804  close(c->feed_fd);
2805  /* wake up any waiting connections to stop waiting for feed */
2806  for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2807  if (c1->state == HTTPSTATE_WAIT_FEED &&
2808  c1->stream->feed == c->stream->feed)
2810  }
2811  return -1;
2812 }
2813 
2814 /********************************************************************/
2815 /* RTSP handling */
2816 
2817 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2818 {
2819  const char *str;
2820  time_t ti;
2821  struct tm *tm;
2822  char buf2[32];
2823 
2824  switch(error_number) {
2825  case RTSP_STATUS_OK:
2826  str = "OK";
2827  break;
2828  case RTSP_STATUS_METHOD:
2829  str = "Method Not Allowed";
2830  break;
2831  case RTSP_STATUS_BANDWIDTH:
2832  str = "Not Enough Bandwidth";
2833  break;
2834  case RTSP_STATUS_SESSION:
2835  str = "Session Not Found";
2836  break;
2837  case RTSP_STATUS_STATE:
2838  str = "Method Not Valid in This State";
2839  break;
2840  case RTSP_STATUS_AGGREGATE:
2841  str = "Aggregate operation not allowed";
2842  break;
2844  str = "Only aggregate operation allowed";
2845  break;
2846  case RTSP_STATUS_TRANSPORT:
2847  str = "Unsupported transport";
2848  break;
2849  case RTSP_STATUS_INTERNAL:
2850  str = "Internal Server Error";
2851  break;
2852  case RTSP_STATUS_SERVICE:
2853  str = "Service Unavailable";
2854  break;
2855  case RTSP_STATUS_VERSION:
2856  str = "RTSP Version not supported";
2857  break;
2858  default:
2859  str = "Unknown Error";
2860  break;
2861  }
2862 
2863  avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2864  avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2865 
2866  /* output GMT time */
2867  ti = time(NULL);
2868  tm = gmtime(&ti);
2869  strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
2870  avio_printf(c->pb, "Date: %s GMT\r\n", buf2);
2871 }
2872 
2873 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2874 {
2875  rtsp_reply_header(c, error_number);
2876  avio_printf(c->pb, "\r\n");
2877 }
2878 
2880 {
2881  const char *p, *p1, *p2;
2882  char cmd[32];
2883  char url[1024];
2884  char protocol[32];
2885  char line[1024];
2886  int len;
2887  RTSPMessageHeader header1 = { 0 }, *header = &header1;
2888 
2889  c->buffer_ptr[0] = '\0';
2890  p = c->buffer;
2891 
2892  get_word(cmd, sizeof(cmd), &p);
2893  get_word(url, sizeof(url), &p);
2894  get_word(protocol, sizeof(protocol), &p);
2895 
2896  av_strlcpy(c->method, cmd, sizeof(c->method));
2897  av_strlcpy(c->url, url, sizeof(c->url));
2898  av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2899 
2900  if (avio_open_dyn_buf(&c->pb) < 0) {
2901  /* XXX: cannot do more */
2902  c->pb = NULL; /* safety */
2903  return -1;
2904  }
2905 
2906  /* check version name */
2907  if (strcmp(protocol, "RTSP/1.0") != 0) {
2909  goto the_end;
2910  }
2911 
2912  /* parse each header line */
2913  /* skip to next line */
2914  while (*p != '\n' && *p != '\0')
2915  p++;
2916  if (*p == '\n')
2917  p++;
2918  while (*p != '\0') {
2919  p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
2920  if (!p1)
2921  break;
2922  p2 = p1;
2923  if (p2 > p && p2[-1] == '\r')
2924  p2--;
2925  /* skip empty line */
2926  if (p2 == p)
2927  break;
2928  len = p2 - p;
2929  if (len > sizeof(line) - 1)
2930  len = sizeof(line) - 1;
2931  memcpy(line, p, len);
2932  line[len] = '\0';
2933  ff_rtsp_parse_line(header, line, NULL, NULL);
2934  p = p1 + 1;
2935  }
2936 
2937  /* handle sequence number */
2938  c->seq = header->seq;
2939 
2940  if (!strcmp(cmd, "DESCRIBE"))
2941  rtsp_cmd_describe(c, url);
2942  else if (!strcmp(cmd, "OPTIONS"))
2943  rtsp_cmd_options(c, url);
2944  else if (!strcmp(cmd, "SETUP"))
2945  rtsp_cmd_setup(c, url, header);
2946  else if (!strcmp(cmd, "PLAY"))
2947  rtsp_cmd_play(c, url, header);
2948  else if (!strcmp(cmd, "PAUSE"))
2949  rtsp_cmd_pause(c, url, header);
2950  else if (!strcmp(cmd, "TEARDOWN"))
2951  rtsp_cmd_teardown(c, url, header);
2952  else
2954 
2955  the_end:
2956  len = avio_close_dyn_buf(c->pb, &c->pb_buffer);
2957  c->pb = NULL; /* safety */
2958  if (len < 0) {
2959  /* XXX: cannot do more */
2960  return -1;
2961  }
2962  c->buffer_ptr = c->pb_buffer;
2963  c->buffer_end = c->pb_buffer + len;
2965  return 0;
2966 }
2967 
2968 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2969  struct in_addr my_ip)
2970 {
2971  AVFormatContext *avc;
2972  AVStream *avs = NULL;
2973  AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);
2974  int i;
2975 
2976  avc = avformat_alloc_context();
2977  if (avc == NULL || !rtp_format) {
2978  return -1;
2979  }
2980  avc->oformat = rtp_format;
2981  av_dict_set(&avc->metadata, "title",
2982  stream->title[0] ? stream->title : "No Title", 0);
2983  avc->nb_streams = stream->nb_streams;
2984  if (stream->is_multicast) {
2985  snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2986  inet_ntoa(stream->multicast_ip),
2987  stream->multicast_port, stream->multicast_ttl);
2988  } else {
2989  snprintf(avc->filename, 1024, "rtp://0.0.0.0");
2990  }
2991 
2992  if (avc->nb_streams >= INT_MAX/sizeof(*avc->streams) ||
2993  !(avc->streams = av_malloc(avc->nb_streams * sizeof(*avc->streams))))
2994  goto sdp_done;
2995  if (avc->nb_streams >= INT_MAX/sizeof(*avs) ||
2996  !(avs = av_malloc(avc->nb_streams * sizeof(*avs))))
2997  goto sdp_done;
2998 
2999  for(i = 0; i < stream->nb_streams; i++) {
3000  avc->streams[i] = &avs[i];
3001  avc->streams[i]->codec = stream->streams[i]->codec;
3002  }
3003  *pbuffer = av_mallocz(2048);
3004  av_sdp_create(&avc, 1, *pbuffer, 2048);
3005 
3006  sdp_done:
3007  av_free(avc->streams);
3008  av_dict_free(&avc->metadata);
3009  av_free(avc);
3010  av_free(avs);
3011 
3012  return strlen(*pbuffer);
3013 }
3014 
3015 static void rtsp_cmd_options(HTTPContext *c, const char *url)
3016 {
3017 // rtsp_reply_header(c, RTSP_STATUS_OK);
3018  avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
3019  avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
3020  avio_printf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
3021  avio_printf(c->pb, "\r\n");
3022 }
3023 
3024 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
3025 {
3026  FFStream *stream;
3027  char path1[1024];
3028  const char *path;
3029  uint8_t *content;
3030  int content_length;
3031  socklen_t len;
3032  struct sockaddr_in my_addr;
3033 
3034  /* find which url is asked */
3035  av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3036  path = path1;
3037  if (*path == '/')
3038  path++;
3039 
3040  for(stream = first_stream; stream != NULL; stream = stream->next) {
3041  if (!stream->is_feed &&
3042  stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
3043  !strcmp(path, stream->filename)) {
3044  goto found;
3045  }
3046  }
3047  /* no stream found */
3048  rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3049  return;
3050 
3051  found:
3052  /* prepare the media description in sdp format */
3053 
3054  /* get the host IP */
3055  len = sizeof(my_addr);
3056  getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
3057  content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
3058  if (content_length < 0) {
3060  return;
3061  }
3063  avio_printf(c->pb, "Content-Base: %s/\r\n", url);
3064  avio_printf(c->pb, "Content-Type: application/sdp\r\n");
3065  avio_printf(c->pb, "Content-Length: %d\r\n", content_length);
3066  avio_printf(c->pb, "\r\n");
3067  avio_write(c->pb, content, content_length);
3068  av_free(content);
3069 }
3070 
3071 static HTTPContext *find_rtp_session(const char *session_id)
3072 {
3073  HTTPContext *c;
3074 
3075  if (session_id[0] == '\0')
3076  return NULL;
3077 
3078  for(c = first_http_ctx; c != NULL; c = c->next) {
3079  if (!strcmp(c->session_id, session_id))
3080  return c;
3081  }
3082  return NULL;
3083 }
3084 
3086 {
3087  RTSPTransportField *th;
3088  int i;
3089 
3090  for(i=0;i<h->nb_transports;i++) {
3091  th = &h->transports[i];
3092  if (th->lower_transport == lower_transport)
3093  return th;
3094  }
3095  return NULL;
3096 }
3097 
3098 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3099  RTSPMessageHeader *h)
3100 {
3101  FFStream *stream;
3102  int stream_index, rtp_port, rtcp_port;
3103  char buf[1024];
3104  char path1[1024];
3105  const char *path;
3106  HTTPContext *rtp_c;
3107  RTSPTransportField *th;
3108  struct sockaddr_in dest_addr;
3109  RTSPActionServerSetup setup;
3110 
3111  /* find which url is asked */
3112  av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3113  path = path1;
3114  if (*path == '/')
3115  path++;
3116 
3117  /* now check each stream */
3118  for(stream = first_stream; stream != NULL; stream = stream->next) {
3119  if (!stream->is_feed &&
3120  stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3121  /* accept aggregate filenames only if single stream */
3122  if (!strcmp(path, stream->filename)) {
3123  if (stream->nb_streams != 1) {
3125  return;
3126  }
3127  stream_index = 0;
3128  goto found;
3129  }
3130 
3131  for(stream_index = 0; stream_index < stream->nb_streams;
3132  stream_index++) {
3133  snprintf(buf, sizeof(buf), "%s/streamid=%d",
3134  stream->filename, stream_index);
3135  if (!strcmp(path, buf))
3136  goto found;
3137  }
3138  }
3139  }
3140  /* no stream found */
3141  rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3142  return;
3143  found:
3144 
3145  /* generate session id if needed */
3146  if (h->session_id[0] == '\0') {
3147  unsigned random0 = av_lfg_get(&random_state);
3148  unsigned random1 = av_lfg_get(&random_state);
3149  snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3150  random0, random1);
3151  }
3152 
3153  /* find rtp session, and create it if none found */
3154  rtp_c = find_rtp_session(h->session_id);
3155  if (!rtp_c) {
3156  /* always prefer UDP */
3158  if (!th) {
3160  if (!th) {
3162  return;
3163  }
3164  }
3165 
3166  rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3167  th->lower_transport);
3168  if (!rtp_c) {
3170  return;
3171  }
3172 
3173  /* open input stream */
3174  if (open_input_stream(rtp_c, "") < 0) {
3176  return;
3177  }
3178  }
3179 
3180  /* test if stream is OK (test needed because several SETUP needs
3181  to be done for a given file) */
3182  if (rtp_c->stream != stream) {
3184  return;
3185  }
3186 
3187  /* test if stream is already set up */
3188  if (rtp_c->rtp_ctx[stream_index]) {
3190  return;
3191  }
3192 
3193  /* check transport */
3194  th = find_transport(h, rtp_c->rtp_protocol);
3195  if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3196  th->client_port_min <= 0)) {
3198  return;
3199  }
3200 
3201  /* setup default options */
3202  setup.transport_option[0] = '\0';
3203  dest_addr = rtp_c->from_addr;
3204  dest_addr.sin_port = htons(th->client_port_min);
3205 
3206  /* setup stream */
3207  if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3209  return;
3210  }
3211 
3212  /* now everything is OK, so we can send the connection parameters */
3214  /* session ID */
3215  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3216 
3217  switch(rtp_c->rtp_protocol) {
3219  rtp_port = ff_rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3220  rtcp_port = ff_rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3221  avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3222  "client_port=%d-%d;server_port=%d-%d",
3224  rtp_port, rtcp_port);
3225  break;
3227  avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3228  stream_index * 2, stream_index * 2 + 1);
3229  break;
3230  default:
3231  break;
3232  }
3233  if (setup.transport_option[0] != '\0')
3234  avio_printf(c->pb, ";%s", setup.transport_option);
3235  avio_printf(c->pb, "\r\n");
3236 
3237 
3238  avio_printf(c->pb, "\r\n");
3239 }
3240 
3241 
3242 /* find an rtp connection by using the session ID. Check consistency
3243  with filename */
3244 static HTTPContext *find_rtp_session_with_url(const char *url,
3245  const char *session_id)
3246 {
3247  HTTPContext *rtp_c;
3248  char path1[1024];
3249  const char *path;
3250  char buf[1024];
3251  int s, len;
3252 
3253  rtp_c = find_rtp_session(session_id);
3254  if (!rtp_c)
3255  return NULL;
3256 
3257  /* find which url is asked */
3258  av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3259  path = path1;
3260  if (*path == '/')
3261  path++;
3262  if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
3263  for(s=0; s<rtp_c->stream->nb_streams; ++s) {
3264  snprintf(buf, sizeof(buf), "%s/streamid=%d",
3265  rtp_c->stream->filename, s);
3266  if(!strncmp(path, buf, sizeof(buf))) {
3267  // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
3268  return rtp_c;
3269  }
3270  }
3271  len = strlen(path);
3272  if (len > 0 && path[len - 1] == '/' &&
3273  !strncmp(path, rtp_c->stream->filename, len - 1))
3274  return rtp_c;
3275  return NULL;
3276 }
3277 
3278 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3279 {
3280  HTTPContext *rtp_c;
3281 
3282  rtp_c = find_rtp_session_with_url(url, h->session_id);
3283  if (!rtp_c) {
3285  return;
3286  }
3287 
3288  if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3289  rtp_c->state != HTTPSTATE_WAIT_FEED &&
3290  rtp_c->state != HTTPSTATE_READY) {
3292  return;
3293  }
3294 
3295  rtp_c->state = HTTPSTATE_SEND_DATA;
3296 
3297  /* now everything is OK, so we can send the connection parameters */
3299  /* session ID */
3300  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3301  avio_printf(c->pb, "\r\n");
3302 }
3303 
3304 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3305 {
3306  HTTPContext *rtp_c;
3307 
3308  rtp_c = find_rtp_session_with_url(url, h->session_id);
3309  if (!rtp_c) {
3311  return;
3312  }
3313 
3314  if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3315  rtp_c->state != HTTPSTATE_WAIT_FEED) {
3317  return;
3318  }
3319 
3320  rtp_c->state = HTTPSTATE_READY;
3321  rtp_c->first_pts = AV_NOPTS_VALUE;
3322  /* now everything is OK, so we can send the connection parameters */
3324  /* session ID */
3325  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3326  avio_printf(c->pb, "\r\n");
3327 }
3328 
3329 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3330 {
3331  HTTPContext *rtp_c;
3332 
3333  rtp_c = find_rtp_session_with_url(url, h->session_id);
3334  if (!rtp_c) {
3336  return;
3337  }
3338 
3339  /* now everything is OK, so we can send the connection parameters */
3341  /* session ID */
3342  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3343  avio_printf(c->pb, "\r\n");
3344 
3345  /* abort the session */
3346  close_connection(rtp_c);
3347 }
3348 
3349 
3350 /********************************************************************/
3351 /* RTP handling */
3352 
3353 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3354  FFStream *stream, const char *session_id,
3355  enum RTSPLowerTransport rtp_protocol)
3356 {
3357  HTTPContext *c = NULL;
3358  const char *proto_str;
3359 
3360  /* XXX: should output a warning page when coming
3361  close to the connection limit */
3363  goto fail;
3364 
3365  /* add a new connection */
3366  c = av_mallocz(sizeof(HTTPContext));
3367  if (!c)
3368  goto fail;
3369 
3370  c->fd = -1;
3371  c->poll_entry = NULL;
3372  c->from_addr = *from_addr;
3374  c->buffer = av_malloc(c->buffer_size);
3375  if (!c->buffer)
3376  goto fail;
3377  nb_connections++;
3378  c->stream = stream;
3379  av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3380  c->state = HTTPSTATE_READY;
3381  c->is_packetized = 1;
3382  c->rtp_protocol = rtp_protocol;
3383 
3384  /* protocol is shown in statistics */
3385  switch(c->rtp_protocol) {
3387  proto_str = "MCAST";
3388  break;
3390  proto_str = "UDP";
3391  break;
3393  proto_str = "TCP";
3394  break;
3395  default:
3396  proto_str = "???";
3397  break;
3398  }
3399  av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3400  av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3401 
3402  current_bandwidth += stream->bandwidth;
3403 
3404  c->next = first_http_ctx;
3405  first_http_ctx = c;
3406  return c;
3407 
3408  fail:
3409  if (c) {
3410  av_free(c->buffer);
3411  av_free(c);
3412  }
3413  return NULL;
3414 }
3415 
3416 /* add a new RTP stream in an RTP connection (used in RTSP SETUP
3417  command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3418  used. */
3420  int stream_index, struct sockaddr_in *dest_addr,
3421  HTTPContext *rtsp_c)
3422 {
3423  AVFormatContext *ctx;
3424  AVStream *st;
3425  char *ipaddr;
3426  URLContext *h = NULL;
3427  uint8_t *dummy_buf;
3428  int max_packet_size;
3429 
3430  /* now we can open the relevant output stream */
3431  ctx = avformat_alloc_context();
3432  if (!ctx)
3433  return -1;
3434  ctx->oformat = av_guess_format("rtp", NULL, NULL);
3435 
3436  st = av_mallocz(sizeof(AVStream));
3437  if (!st)
3438  goto fail;
3439  ctx->nb_streams = 1;
3440  ctx->streams = av_mallocz(sizeof(AVStream *) * ctx->nb_streams);
3441  if (!ctx->streams)
3442  goto fail;
3443  ctx->streams[0] = st;
3444 
3445  if (!c->stream->feed ||
3446  c->stream->feed == c->stream)
3447  memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3448  else
3449  memcpy(st,
3450  c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3451  sizeof(AVStream));
3452  st->priv_data = NULL;
3453 
3454  /* build destination RTP address */
3455  ipaddr = inet_ntoa(dest_addr->sin_addr);
3456 
3457  switch(c->rtp_protocol) {
3460  /* RTP/UDP case */
3461 
3462  /* XXX: also pass as parameter to function ? */
3463  if (c->stream->is_multicast) {
3464  int ttl;
3465  ttl = c->stream->multicast_ttl;
3466  if (!ttl)
3467  ttl = 16;
3468  snprintf(ctx->filename, sizeof(ctx->filename),
3469  "rtp://%s:%d?multicast=1&ttl=%d",
3470  ipaddr, ntohs(dest_addr->sin_port), ttl);
3471  } else {
3472  snprintf(ctx->filename, sizeof(ctx->filename),
3473  "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3474  }
3475 
3476  if (ffurl_open(&h, ctx->filename, AVIO_FLAG_WRITE, NULL, NULL) < 0)
3477  goto fail;
3478  c->rtp_handles[stream_index] = h;
3479  max_packet_size = h->max_packet_size;
3480  break;
3482  /* RTP/TCP case */
3483  c->rtsp_c = rtsp_c;
3484  max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3485  break;
3486  default:
3487  goto fail;
3488  }
3489 
3490  http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3491  ipaddr, ntohs(dest_addr->sin_port),
3492  c->stream->filename, stream_index, c->protocol);
3493 
3494  /* normally, no packets should be output here, but the packet size may be checked */
3495  if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
3496  /* XXX: close stream */
3497  goto fail;
3498  }
3499  if (avformat_write_header(ctx, NULL) < 0) {
3500  fail:
3501  if (h)
3502  ffurl_close(h);
3503  av_free(ctx);
3504  return -1;
3505  }
3506  avio_close_dyn_buf(ctx->pb, &dummy_buf);
3507  av_free(dummy_buf);
3508 
3509  c->rtp_ctx[stream_index] = ctx;
3510  return 0;
3511 }
3512 
3513 /********************************************************************/
3514 /* ffserver initialization */
3515 
3516 static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int copy)
3517 {
3518  AVStream *fst;
3519 
3520  if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams))
3521  return NULL;
3522 
3523  fst = av_mallocz(sizeof(AVStream));
3524  if (!fst)
3525  return NULL;
3526  if (copy) {
3528  memcpy(fst->codec, codec, sizeof(AVCodecContext));
3529  if (codec->extradata_size) {
3531  memcpy(fst->codec->extradata, codec->extradata,
3532  codec->extradata_size);
3533  }
3534  } else {
3535  /* live streams must use the actual feed's codec since it may be
3536  * updated later to carry extradata needed by the streams.
3537  */
3538  fst->codec = codec;
3539  }
3540  fst->priv_data = av_mallocz(sizeof(FeedData));
3541  fst->index = stream->nb_streams;
3542  avpriv_set_pts_info(fst, 33, 1, 90000);
3544  stream->streams[stream->nb_streams++] = fst;
3545  return fst;
3546 }
3547 
3548 /* return the stream number in the feed */
3549 static int add_av_stream(FFStream *feed, AVStream *st)
3550 {
3551  AVStream *fst;
3552  AVCodecContext *av, *av1;
3553  int i;
3554 
3555  av = st->codec;
3556  for(i=0;i<feed->nb_streams;i++) {
3557  st = feed->streams[i];
3558  av1 = st->codec;
3559  if (av1->codec_id == av->codec_id &&
3560  av1->codec_type == av->codec_type &&
3561  av1->bit_rate == av->bit_rate) {
3562 
3563  switch(av->codec_type) {
3564  case AVMEDIA_TYPE_AUDIO:
3565  if (av1->channels == av->channels &&
3566  av1->sample_rate == av->sample_rate)
3567  return i;
3568  break;
3569  case AVMEDIA_TYPE_VIDEO:
3570  if (av1->width == av->width &&
3571  av1->height == av->height &&
3572  av1->time_base.den == av->time_base.den &&
3573  av1->time_base.num == av->time_base.num &&
3574  av1->gop_size == av->gop_size)
3575  return i;
3576  break;
3577  default:
3578  abort();
3579  }
3580  }
3581  }
3582 
3583  fst = add_av_stream1(feed, av, 0);
3584  if (!fst)
3585  return -1;
3586  return feed->nb_streams - 1;
3587 }
3588 
3589 static void remove_stream(FFStream *stream)
3590 {
3591  FFStream **ps;
3592  ps = &first_stream;
3593  while (*ps != NULL) {
3594  if (*ps == stream)
3595  *ps = (*ps)->next;
3596  else
3597  ps = &(*ps)->next;
3598  }
3599 }
3600 
3601 /* specific mpeg4 handling : we extract the raw parameters */
3603 {
3604  int mpeg4_count, i, size;
3605  AVPacket pkt;
3606  AVStream *st;
3607  const uint8_t *p;
3608 
3610 
3611  mpeg4_count = 0;
3612  for(i=0;i<infile->nb_streams;i++) {
3613  st = infile->streams[i];
3614  if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3615  st->codec->extradata_size == 0) {
3616  mpeg4_count++;
3617  }
3618  }
3619  if (!mpeg4_count)
3620  return;
3621 
3622  printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
3623  while (mpeg4_count > 0) {
3624  if (av_read_frame(infile, &pkt) < 0)
3625  break;
3626  st = infile->streams[pkt.stream_index];
3627  if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3628  st->codec->extradata_size == 0) {
3629  av_freep(&st->codec->extradata);
3630  /* fill extradata with the header */
3631  /* XXX: we make hard suppositions here ! */
3632  p = pkt.data;
3633  while (p < pkt.data + pkt.size - 4) {
3634  /* stop when vop header is found */
3635  if (p[0] == 0x00 && p[1] == 0x00 &&
3636  p[2] == 0x01 && p[3] == 0xb6) {
3637  size = p - pkt.data;
3638  // av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
3640  st->codec->extradata_size = size;
3641  memcpy(st->codec->extradata, pkt.data, size);
3642  break;
3643  }
3644  p++;
3645  }
3646  mpeg4_count--;
3647  }
3648  av_free_packet(&pkt);
3649  }
3650 }
3651 
3652 /* compute the needed AVStream for each file */
3653 static void build_file_streams(void)
3654 {
3655  FFStream *stream, *stream_next;
3656  int i, ret;
3657 
3658  /* gather all streams */
3659  for(stream = first_stream; stream != NULL; stream = stream_next) {
3660  AVFormatContext *infile = NULL;
3661  stream_next = stream->next;
3662  if (stream->stream_type == STREAM_TYPE_LIVE &&
3663  !stream->feed) {
3664  /* the stream comes from a file */
3665  /* try to open the file */
3666  /* open stream */
3667  if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3668  /* specific case : if transport stream output to RTP,
3669  we use a raw transport stream reader */
3670  av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0);
3671  }
3672 
3673  http_log("Opening file '%s'\n", stream->feed_filename);
3674  if ((ret = avformat_open_input(&infile, stream->feed_filename, stream->ifmt, &stream->in_opts)) < 0) {
3675  http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
3676  /* remove stream (no need to spend more time on it) */
3677  fail:
3678  remove_stream(stream);
3679  } else {
3680  /* find all the AVStreams inside and reference them in
3681  'stream' */
3682  if (avformat_find_stream_info(infile, NULL) < 0) {
3683  http_log("Could not find codec parameters from '%s'\n",
3684  stream->feed_filename);
3685  avformat_close_input(&infile);
3686  goto fail;
3687  }
3688  extract_mpeg4_header(infile);
3689 
3690  for(i=0;i<infile->nb_streams;i++)
3691  add_av_stream1(stream, infile->streams[i]->codec, 1);
3692 
3693  avformat_close_input(&infile);
3694  }
3695  }
3696  }
3697 }
3698 
3699 /* compute the needed AVStream for each feed */
3700 static void build_feed_streams(void)
3701 {
3702  FFStream *stream, *feed;
3703  int i;
3704 
3705  /* gather all streams */
3706  for(stream = first_stream; stream != NULL; stream = stream->next) {
3707  feed = stream->feed;
3708  if (feed) {
3709  if (stream->is_feed) {
3710  for(i=0;i<stream->nb_streams;i++)
3711  stream->feed_streams[i] = i;
3712  } else {
3713  /* we handle a stream coming from a feed */
3714  for(i=0;i<stream->nb_streams;i++)
3715  stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3716  }
3717  }
3718  }
3719 
3720  /* create feed files if needed */
3721  for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
3722  int fd;
3723 
3724  if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) {
3725  /* See if it matches */
3726  AVFormatContext *s = NULL;
3727  int matches = 0;
3728 
3729  if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) >= 0) {
3730  /* set buffer size */
3732  /* Now see if it matches */
3733  if (s->nb_streams == feed->nb_streams) {
3734  matches = 1;
3735  for(i=0;i<s->nb_streams;i++) {
3736  AVStream *sf, *ss;
3737  sf = feed->streams[i];
3738  ss = s->streams[i];
3739 
3740  if (sf->index != ss->index ||
3741  sf->id != ss->id) {
3742  http_log("Index & Id do not match for stream %d (%s)\n",
3743  i, feed->feed_filename);
3744  matches = 0;
3745  } else {
3746  AVCodecContext *ccf, *ccs;
3747 
3748  ccf = sf->codec;
3749  ccs = ss->codec;
3750 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3751 
3753  http_log("Codecs do not match for stream %d\n", i);
3754  matches = 0;
3755  } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3756  http_log("Codec bitrates do not match for stream %d\n", i);
3757  matches = 0;
3758  } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
3759  if (CHECK_CODEC(time_base.den) ||
3760  CHECK_CODEC(time_base.num) ||
3761  CHECK_CODEC(width) ||
3762  CHECK_CODEC(height)) {
3763  http_log("Codec width, height and framerate do not match for stream %d\n", i);
3764  matches = 0;
3765  }
3766  } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
3767  if (CHECK_CODEC(sample_rate) ||
3768  CHECK_CODEC(channels) ||
3770  http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3771  matches = 0;
3772  }
3773  } else {
3774  http_log("Unknown codec type\n");
3775  matches = 0;
3776  }
3777  }
3778  if (!matches)
3779  break;
3780  }
3781  } else
3782  http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3783  feed->feed_filename, s->nb_streams, feed->nb_streams);
3784 
3786  } else
3787  http_log("Deleting feed file '%s' as it appears to be corrupt\n",
3788  feed->feed_filename);
3789 
3790  if (!matches) {
3791  if (feed->readonly) {
3792  http_log("Unable to delete feed file '%s' as it is marked readonly\n",
3793  feed->feed_filename);
3794  exit(1);
3795  }
3796  unlink(feed->feed_filename);
3797  }
3798  }
3799  if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) {
3800  AVFormatContext s1 = {0}, *s = &s1;
3801 
3802  if (feed->readonly) {
3803  http_log("Unable to create feed file '%s' as it is marked readonly\n",
3804  feed->feed_filename);
3805  exit(1);
3806  }
3807 
3808  /* only write the header of the ffm file */
3809  if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) {
3810  http_log("Could not open output feed file '%s'\n",
3811  feed->feed_filename);
3812  exit(1);
3813  }
3814  s->oformat = feed->fmt;
3815  s->nb_streams = feed->nb_streams;
3816  s->streams = feed->streams;
3817  if (avformat_write_header(s, NULL) < 0) {
3818  http_log("Container doesn't support the required parameters\n");
3819  exit(1);
3820  }
3821  /* XXX: need better api */
3822  av_freep(&s->priv_data);
3823  avio_close(s->pb);
3824  }
3825  /* get feed size and write index */
3826  fd = open(feed->feed_filename, O_RDONLY);
3827  if (fd < 0) {
3828  http_log("Could not open output feed file '%s'\n",
3829  feed->feed_filename);
3830  exit(1);
3831  }
3832 
3834  feed->feed_size = lseek(fd, 0, SEEK_END);
3835  /* ensure that we do not wrap before the end of file */
3836  if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3837  feed->feed_max_size = feed->feed_size;
3838 
3839  close(fd);
3840  }
3841 }
3842 
3843 /* compute the bandwidth used by each stream */
3844 static void compute_bandwidth(void)
3845 {
3846  unsigned bandwidth;
3847  int i;
3848  FFStream *stream;
3849 
3850  for(stream = first_stream; stream != NULL; stream = stream->next) {
3851  bandwidth = 0;
3852  for(i=0;i<stream->nb_streams;i++) {
3853  AVStream *st = stream->streams[i];
3854  switch(st->codec->codec_type) {
3855  case AVMEDIA_TYPE_AUDIO:
3856  case AVMEDIA_TYPE_VIDEO:
3857  bandwidth += st->codec->bit_rate;
3858  break;
3859  default:
3860  break;
3861  }
3862  }
3863  stream->bandwidth = (bandwidth + 999) / 1000;
3864  }
3865 }
3866 
3867 /* add a codec and set the default parameters */
3868 static void add_codec(FFStream *stream, AVCodecContext *av)
3869 {
3870  AVStream *st;
3871 
3872  if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams))
3873  return;
3874 
3875  /* compute default parameters */
3876  switch(av->codec_type) {
3877  case AVMEDIA_TYPE_AUDIO:
3878  if (av->bit_rate == 0)
3879  av->bit_rate = 64000;
3880  if (av->sample_rate == 0)
3881  av->sample_rate = 22050;
3882  if (av->channels == 0)
3883  av->channels = 1;
3884  break;
3885  case AVMEDIA_TYPE_VIDEO:
3886  if (av->bit_rate == 0)
3887  av->bit_rate = 64000;
3888  if (av->time_base.num == 0){
3889  av->time_base.den = 5;
3890  av->time_base.num = 1;
3891  }
3892  if (av->width == 0 || av->height == 0) {
3893  av->width = 160;
3894  av->height = 128;
3895  }
3896  /* Bitrate tolerance is less for streaming */
3897  if (av->bit_rate_tolerance == 0)
3898  av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
3899  (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
3900  if (av->qmin == 0)
3901  av->qmin = 3;
3902  if (av->qmax == 0)
3903  av->qmax = 31;
3904  if (av->max_qdiff == 0)
3905  av->max_qdiff = 3;
3906  av->qcompress = 0.5;
3907  av->qblur = 0.5;
3908 
3909  if (!av->nsse_weight)
3910  av->nsse_weight = 8;
3911 
3913  if (!av->me_method)
3914  av->me_method = ME_EPZS;
3915  av->rc_buffer_aggressivity = 1.0;
3916 
3917  if (!av->rc_eq)
3918  av->rc_eq = "tex^qComp";
3919  if (!av->i_quant_factor)
3920  av->i_quant_factor = -0.8;
3921  if (!av->b_quant_factor)
3922  av->b_quant_factor = 1.25;
3923  if (!av->b_quant_offset)
3924  av->b_quant_offset = 1.25;
3925  if (!av->rc_max_rate)
3926  av->rc_max_rate = av->bit_rate * 2;
3927 
3928  if (av->rc_max_rate && !av->rc_buffer_size) {
3929  av->rc_buffer_size = av->rc_max_rate;
3930  }
3931 
3932 
3933  break;
3934  default:
3935  abort();
3936  }
3937 
3938  st = av_mallocz(sizeof(AVStream));
3939  if (!st)
3940  return;
3942  stream->streams[stream->nb_streams++] = st;
3943  memcpy(st->codec, av, sizeof(AVCodecContext));
3944 }
3945 
3946 static enum AVCodecID opt_audio_codec(const char *arg)
3947 {
3949 
3950  if (p == NULL || p->type != AVMEDIA_TYPE_AUDIO)
3951  return AV_CODEC_ID_NONE;
3952 
3953  return p->id;
3954 }
3955 
3956 static enum AVCodecID opt_video_codec(const char *arg)
3957 {
3959 
3960  if (p == NULL || p->type != AVMEDIA_TYPE_VIDEO)
3961  return AV_CODEC_ID_NONE;
3962 
3963  return p->id;
3964 }
3965 
3966 /* simplistic plugin support */
3967 
3968 #if HAVE_DLOPEN
3969 static void load_module(const char *filename)
3970 {
3971  void *dll;
3972  void (*init_func)(void);
3973  dll = dlopen(filename, RTLD_NOW);
3974  if (!dll) {
3975  fprintf(stderr, "Could not load module '%s' - %s\n",
3976  filename, dlerror());
3977  return;
3978  }
3979 
3980  init_func = dlsym(dll, "ffserver_module_init");
3981  if (!init_func) {
3982  fprintf(stderr,
3983  "%s: init function 'ffserver_module_init()' not found\n",
3984  filename);
3985  dlclose(dll);
3986  }
3987 
3988  init_func();
3989 }
3990 #endif
3991 
3992 static int ffserver_opt_default(const char *opt, const char *arg,
3993  AVCodecContext *avctx, int type)
3994 {
3995  int ret = 0;
3996  const AVOption *o = av_opt_find(avctx, opt, NULL, type, 0);
3997  if(o)
3998  ret = av_opt_set(avctx, opt, arg, 0);
3999  return ret;
4000 }
4001 
4002 static int ffserver_opt_preset(const char *arg,
4003  AVCodecContext *avctx, int type,
4004  enum AVCodecID *audio_id, enum AVCodecID *video_id)
4005 {
4006  FILE *f=NULL;
4007  char filename[1000], tmp[1000], tmp2[1000], line[1000];
4008  int ret = 0;
4009  AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
4010 
4011  if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
4012  codec ? codec->name : NULL))) {
4013  fprintf(stderr, "File for preset '%s' not found\n", arg);
4014  return 1;
4015  }
4016 
4017  while(!feof(f)){
4018  int e= fscanf(f, "%999[^\n]\n", line) - 1;
4019  if(line[0] == '#' && !e)
4020  continue;
4021  e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
4022  if(e){
4023  fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
4024  ret = 1;
4025  break;
4026  }
4027  if(!strcmp(tmp, "acodec")){
4028  *audio_id = opt_audio_codec(tmp2);
4029  }else if(!strcmp(tmp, "vcodec")){
4030  *video_id = opt_video_codec(tmp2);
4031  }else if(!strcmp(tmp, "scodec")){
4032  /* opt_subtitle_codec(tmp2); */
4033  }else if(ffserver_opt_default(tmp, tmp2, avctx, type) < 0){
4034  fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
4035  ret = 1;
4036  break;
4037  }
4038  }
4039 
4040  fclose(f);
4041 
4042  return ret;
4043 }
4044 
4045 static AVOutputFormat *ffserver_guess_format(const char *short_name, const char *filename,
4046  const char *mime_type)
4047 {
4048  AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
4049 
4050  if (fmt) {
4051  AVOutputFormat *stream_fmt;
4052  char stream_format_name[64];
4053 
4054  snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
4055  stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
4056 
4057  if (stream_fmt)
4058  fmt = stream_fmt;
4059  }
4060 
4061  return fmt;
4062 }
4063 
4064 static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
4065 {
4066  va_list vl;
4067  va_start(vl, fmt);
4068  fprintf(stderr, "%s:%d: ", filename, line_num);
4069  vfprintf(stderr, fmt, vl);
4070  va_end(vl);
4071 
4072  (*errors)++;
4073 }
4074 
4075 static int parse_ffconfig(const char *filename)
4076 {
4077  FILE *f;
4078  char line[1024];
4079  char cmd[64];
4080  char arg[1024];
4081  const char *p;
4082  int val, errors, line_num;
4083  FFStream **last_stream, *stream, *redirect;
4084  FFStream **last_feed, *feed, *s;
4085  AVCodecContext audio_enc, video_enc;
4086  enum AVCodecID audio_id, video_id;
4087 
4088  f = fopen(filename, "r");
4089  if (!f) {
4090  perror(filename);
4091  return -1;
4092  }
4093 
4094  errors = 0;
4095  line_num = 0;
4096  first_stream = NULL;
4097  last_stream = &first_stream;
4098  first_feed = NULL;
4099  last_feed = &first_feed;
4100  stream = NULL;
4101  feed = NULL;
4102  redirect = NULL;
4103  audio_id = AV_CODEC_ID_NONE;
4104  video_id = AV_CODEC_ID_NONE;
4105 
4106 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4107  for(;;) {
4108  if (fgets(line, sizeof(line), f) == NULL)
4109  break;
4110  line_num++;
4111  p = line;
4112  while (av_isspace(*p))
4113  p++;
4114  if (*p == '\0' || *p == '#')
4115  continue;
4116 
4117  get_arg(cmd, sizeof(cmd), &p);
4118 
4119  if (!av_strcasecmp(cmd, "Port")) {
4120  get_arg(arg, sizeof(arg), &p);
4121  val = atoi(arg);
4122  if (val < 1 || val > 65536) {
4123  ERROR("Invalid_port: %s\n", arg);
4124  }
4125  my_http_addr.sin_port = htons(val);
4126  } else if (!av_strcasecmp(cmd, "BindAddress")) {
4127  get_arg(arg, sizeof(arg), &p);
4128  if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
4129  ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
4130  }
4131  } else if (!av_strcasecmp(cmd, "NoDaemon")) {
4132  // do nothing here, its the default now
4133  } else if (!av_strcasecmp(cmd, "RTSPPort")) {
4134  get_arg(arg, sizeof(arg), &p);
4135  val = atoi(arg);
4136  if (val < 1 || val > 65536) {
4137  ERROR("%s:%d: Invalid port: %s\n", arg);
4138  }
4139  my_rtsp_addr.sin_port = htons(atoi(arg));
4140  } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) {
4141  get_arg(arg, sizeof(arg), &p);
4142  if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
4143  ERROR("Invalid host/IP address: %s\n", arg);
4144  }
4145  } else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) {
4146  get_arg(arg, sizeof(arg), &p);
4147  val = atoi(arg);
4148  if (val < 1 || val > 65536) {
4149  ERROR("Invalid MaxHTTPConnections: %s\n", arg);
4150  }
4152  } else if (!av_strcasecmp(cmd, "MaxClients")) {
4153  get_arg(arg, sizeof(arg), &p);
4154  val = atoi(arg);
4155  if (val < 1 || val > nb_max_http_connections) {
4156  ERROR("Invalid MaxClients: %s\n", arg);
4157  } else {
4158  nb_max_connections = val;
4159  }
4160  } else if (!av_strcasecmp(cmd, "MaxBandwidth")) {
4161  int64_t llval;
4162  get_arg(arg, sizeof(arg), &p);
4163  llval = atoll(arg);
4164  if (llval < 10 || llval > 10000000) {
4165  ERROR("Invalid MaxBandwidth: %s\n", arg);
4166  } else
4167  max_bandwidth = llval;
4168  } else if (!av_strcasecmp(cmd, "CustomLog")) {
4169  if (!ffserver_debug)
4170  get_arg(logfilename, sizeof(logfilename), &p);
4171  } else if (!av_strcasecmp(cmd, "<Feed")) {
4172  /*********************************************/
4173  /* Feed related options */
4174  char *q;
4175  if (stream || feed) {
4176  ERROR("Already in a tag\n");
4177  } else {
4178  feed = av_mallocz(sizeof(FFStream));
4179  get_arg(feed->filename, sizeof(feed->filename), &p);
4180  q = strrchr(feed->filename, '>');
4181  if (*q)
4182  *q = '\0';
4183 
4184  for (s = first_feed; s; s = s->next) {
4185  if (!strcmp(feed->filename, s->filename)) {
4186  ERROR("Feed '%s' already registered\n", s->filename);
4187  }
4188  }
4189 
4190  feed->fmt = av_guess_format("ffm", NULL, NULL);
4191  /* defaut feed file */
4192  snprintf(feed->feed_filename, sizeof(feed->feed_filename),
4193  "/tmp/%s.ffm", feed->filename);
4194  feed->feed_max_size = 5 * 1024 * 1024;
4195  feed->is_feed = 1;
4196  feed->feed = feed; /* self feeding :-) */
4197 
4198  /* add in stream list */
4199  *last_stream = feed;
4200  last_stream = &feed->next;
4201  /* add in feed list */
4202  *last_feed = feed;
4203  last_feed = &feed->next_feed;
4204  }
4205  } else if (!av_strcasecmp(cmd, "Launch")) {
4206  if (feed) {
4207  int i;
4208 
4209  feed->child_argv = av_mallocz(64 * sizeof(char *));
4210 
4211  for (i = 0; i < 62; i++) {
4212  get_arg(arg, sizeof(arg), &p);
4213  if (!arg[0])
4214  break;
4215 
4216  feed->child_argv[i] = av_strdup(arg);
4217  }
4218 
4219  feed->child_argv[i] = av_asprintf("http://%s:%d/%s",
4220  (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
4221  inet_ntoa(my_http_addr.sin_addr),
4222  ntohs(my_http_addr.sin_port), feed->filename);
4223  }
4224  } else if (!av_strcasecmp(cmd, "ReadOnlyFile")) {
4225  if (feed) {
4226  get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4227  feed->readonly = 1;
4228  } else if (stream) {
4229  get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4230  }
4231  } else if (!av_strcasecmp(cmd, "File")) {
4232  if (feed) {
4233  get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4234  } else if (stream)
4235  get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4236  } else if (!av_strcasecmp(cmd, "Truncate")) {
4237  if (feed) {
4238  get_arg(arg, sizeof(arg), &p);
4239  feed->truncate = strtod(arg, NULL);
4240  }
4241  } else if (!av_strcasecmp(cmd, "FileMaxSize")) {
4242  if (feed) {
4243  char *p1;
4244  double fsize;
4245 
4246  get_arg(arg, sizeof(arg), &p);
4247  p1 = arg;
4248  fsize = strtod(p1, &p1);
4249  switch(av_toupper(*p1)) {
4250  case 'K':
4251  fsize *= 1024;
4252  break;
4253  case 'M':
4254  fsize *= 1024 * 1024;
4255  break;
4256  case 'G':
4257  fsize *= 1024 * 1024 * 1024;
4258  break;
4259  }
4260  feed->feed_max_size = (int64_t)fsize;
4261  if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
4262  ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
4263  }
4264  }
4265  } else if (!av_strcasecmp(cmd, "</Feed>")) {
4266  if (!feed) {
4267  ERROR("No corresponding <Feed> for </Feed>\n");
4268  }
4269  feed = NULL;
4270  } else if (!av_strcasecmp(cmd, "<Stream")) {
4271  /*********************************************/
4272  /* Stream related options */
4273  char *q;
4274  if (stream || feed) {
4275  ERROR("Already in a tag\n");
4276  } else {
4277  FFStream *s;
4278  stream = av_mallocz(sizeof(FFStream));
4279  get_arg(stream->filename, sizeof(stream->filename), &p);
4280  q = strrchr(stream->filename, '>');
4281  if (q)
4282  *q = '\0';
4283 
4284  for (s = first_stream; s; s = s->next) {
4285  if (!strcmp(stream->filename, s->filename)) {
4286  ERROR("Stream '%s' already registered\n", s->filename);
4287  }
4288  }
4289 
4290  stream->fmt = ffserver_guess_format(NULL, stream->filename, NULL);
4291  avcodec_get_context_defaults3(&video_enc, NULL);
4292  avcodec_get_context_defaults3(&audio_enc, NULL);
4293 
4294  audio_id = AV_CODEC_ID_NONE;
4295  video_id = AV_CODEC_ID_NONE;
4296  if (stream->fmt) {
4297  audio_id = stream->fmt->audio_codec;
4298  video_id = stream->fmt->video_codec;
4299  }
4300 
4301  *last_stream = stream;
4302  last_stream = &stream->next;
4303  }
4304  } else if (!av_strcasecmp(cmd, "Feed")) {
4305  get_arg(arg, sizeof(arg), &p);
4306  if (stream) {
4307  FFStream *sfeed;
4308 
4309  sfeed = first_feed;
4310  while (sfeed != NULL) {
4311  if (!strcmp(sfeed->filename, arg))
4312  break;
4313  sfeed = sfeed->next_feed;
4314  }
4315  if (!sfeed)
4316  ERROR("feed '%s' not defined\n", arg);
4317  else
4318  stream->feed = sfeed;
4319  }
4320  } else if (!av_strcasecmp(cmd, "Format")) {
4321  get_arg(arg, sizeof(arg), &p);
4322  if (stream) {
4323  if (!strcmp(arg, "status")) {
4324  stream->stream_type = STREAM_TYPE_STATUS;
4325  stream->fmt = NULL;
4326  } else {
4327  stream->stream_type = STREAM_TYPE_LIVE;
4328  /* jpeg cannot be used here, so use single frame jpeg */
4329  if (!strcmp(arg, "jpeg"))
4330  strcpy(arg, "mjpeg");
4331  stream->fmt = ffserver_guess_format(arg, NULL, NULL);
4332  if (!stream->fmt) {
4333  ERROR("Unknown Format: %s\n", arg);
4334  }
4335  }
4336  if (stream->fmt) {
4337  audio_id = stream->fmt->audio_codec;
4338  video_id = stream->fmt->video_codec;
4339  }
4340  }
4341  } else if (!av_strcasecmp(cmd, "InputFormat")) {
4342  get_arg(arg, sizeof(arg), &p);
4343  if (stream) {
4344  stream->ifmt = av_find_input_format(arg);
4345  if (!stream->ifmt) {
4346  ERROR("Unknown input format: %s\n", arg);
4347  }
4348  }
4349  } else if (!av_strcasecmp(cmd, "FaviconURL")) {
4350  if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
4351  get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4352  } else {
4353  ERROR("FaviconURL only permitted for status streams\n");
4354  }
4355  } else if (!av_strcasecmp(cmd, "Author")) {
4356  if (stream)
4357  get_arg(stream->author, sizeof(stream->author), &p);
4358  } else if (!av_strcasecmp(cmd, "Comment")) {
4359  if (stream)
4360  get_arg(stream->comment, sizeof(stream->comment), &p);
4361  } else if (!av_strcasecmp(cmd, "Copyright")) {
4362  if (stream)
4363  get_arg(stream->copyright, sizeof(stream->copyright), &p);
4364  } else if (!av_strcasecmp(cmd, "Title")) {
4365  if (stream)
4366  get_arg(stream->title, sizeof(stream->title), &p);
4367  } else if (!av_strcasecmp(cmd, "Preroll")) {
4368  get_arg(arg, sizeof(arg), &p);
4369  if (stream)
4370  stream->prebuffer = atof(arg) * 1000;
4371  } else if (!av_strcasecmp(cmd, "StartSendOnKey")) {
4372  if (stream)
4373  stream->send_on_key = 1;
4374  } else if (!av_strcasecmp(cmd, "AudioCodec")) {
4375  get_arg(arg, sizeof(arg), &p);
4376  audio_id = opt_audio_codec(arg);
4377  if (audio_id == AV_CODEC_ID_NONE) {
4378  ERROR("Unknown AudioCodec: %s\n", arg);
4379  }
4380  } else if (!av_strcasecmp(cmd, "VideoCodec")) {
4381  get_arg(arg, sizeof(arg), &p);
4382  video_id = opt_video_codec(arg);
4383  if (video_id == AV_CODEC_ID_NONE) {
4384  ERROR("Unknown VideoCodec: %s\n", arg);
4385  }
4386  } else if (!av_strcasecmp(cmd, "MaxTime")) {
4387  get_arg(arg, sizeof(arg), &p);
4388  if (stream)
4389  stream->max_time = atof(arg) * 1000;
4390  } else if (!av_strcasecmp(cmd, "AudioBitRate")) {
4391  get_arg(arg, sizeof(arg), &p);
4392  if (stream)
4393  audio_enc.bit_rate = lrintf(atof(arg) * 1000);
4394  } else if (!av_strcasecmp(cmd, "AudioChannels")) {
4395  get_arg(arg, sizeof(arg), &p);
4396  if (stream)
4397  audio_enc.channels = atoi(arg);
4398  } else if (!av_strcasecmp(cmd, "AudioSampleRate")) {
4399  get_arg(arg, sizeof(arg), &p);
4400  if (stream)
4401  audio_enc.sample_rate = atoi(arg);
4402  } else if (!av_strcasecmp(cmd, "AudioQuality")) {
4403  get_arg(arg, sizeof(arg), &p);
4404  if (stream) {
4405 // audio_enc.quality = atof(arg) * 1000;
4406  }
4407  } else if (!av_strcasecmp(cmd, "VideoBitRateRange")) {
4408  if (stream) {
4409  int minrate, maxrate;
4410 
4411  get_arg(arg, sizeof(arg), &p);
4412 
4413  if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
4414  video_enc.rc_min_rate = minrate * 1000;
4415  video_enc.rc_max_rate = maxrate * 1000;
4416  } else {
4417  ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4418  }
4419  }
4420  } else if (!av_strcasecmp(cmd, "Debug")) {
4421  if (stream) {
4422  get_arg(arg, sizeof(arg), &p);
4423  video_enc.debug = strtol(arg,0,0);
4424  }
4425  } else if (!av_strcasecmp(cmd, "Strict")) {
4426  if (stream) {
4427  get_arg(arg, sizeof(arg), &p);
4428  video_enc.strict_std_compliance = atoi(arg);
4429  }
4430  } else if (!av_strcasecmp(cmd, "VideoBufferSize")) {
4431  if (stream) {
4432  get_arg(arg, sizeof(arg), &p);
4433  video_enc.rc_buffer_size = atoi(arg) * 8*1024;
4434  }
4435  } else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) {
4436  if (stream) {
4437  get_arg(arg, sizeof(arg), &p);
4438  video_enc.bit_rate_tolerance = atoi(arg) * 1000;
4439  }
4440  } else if (!av_strcasecmp(cmd, "VideoBitRate")) {
4441  get_arg(arg, sizeof(arg), &p);
4442  if (stream) {
4443  video_enc.bit_rate = atoi(arg) * 1000;
4444  }
4445  } else if (!av_strcasecmp(cmd, "VideoSize")) {
4446  get_arg(arg, sizeof(arg), &p);
4447  if (stream) {
4448  av_parse_video_size(&video_enc.width, &video_enc.height, arg);
4449  if ((video_enc.width % 16) != 0 ||
4450  (video_enc.height % 16) != 0) {
4451  ERROR("Image size must be a multiple of 16\n");
4452  }
4453  }
4454  } else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
4455  get_arg(arg, sizeof(arg), &p);
4456  if (stream) {
4457  AVRational frame_rate;
4458  if (av_parse_video_rate(&frame_rate, arg) < 0) {
4459  ERROR("Incorrect frame rate: %s\n", arg);
4460  } else {
4461  video_enc.time_base.num = frame_rate.den;
4462  video_enc.time_base.den = frame_rate.num;
4463  }
4464  }
4465  } else if (!av_strcasecmp(cmd, "VideoGopSize")) {
4466  get_arg(arg, sizeof(arg), &p);
4467  if (stream)
4468  video_enc.gop_size = atoi(arg);
4469  } else if (!av_strcasecmp(cmd, "VideoIntraOnly")) {
4470  if (stream)
4471  video_enc.gop_size = 1;
4472  } else if (!av_strcasecmp(cmd, "VideoHighQuality")) {
4473  if (stream)
4474  video_enc.mb_decision = FF_MB_DECISION_BITS;
4475  } else if (!av_strcasecmp(cmd, "Video4MotionVector")) {
4476  if (stream) {
4477  video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
4478  video_enc.flags |= CODEC_FLAG_4MV;
4479  }
4480  } else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
4481  !av_strcasecmp(cmd, "AVOptionAudio")) {
4482  char arg2[1024];
4483  AVCodecContext *avctx;
4484  int type;
4485  get_arg(arg, sizeof(arg), &p);
4486  get_arg(arg2, sizeof(arg2), &p);
4487  if (!av_strcasecmp(cmd, "AVOptionVideo")) {
4488  avctx = &video_enc;
4489  type = AV_OPT_FLAG_VIDEO_PARAM;
4490  } else {
4491  avctx = &audio_enc;
4492  type = AV_OPT_FLAG_AUDIO_PARAM;
4493  }
4494  if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
4495  ERROR("AVOption error: %s %s\n", arg, arg2);
4496  }
4497  } else if (!av_strcasecmp(cmd, "AVPresetVideo") ||
4498  !av_strcasecmp(cmd, "AVPresetAudio")) {
4499  AVCodecContext *avctx;
4500  int type;
4501  get_arg(arg, sizeof(arg), &p);
4502  if (!av_strcasecmp(cmd, "AVPresetVideo")) {
4503  avctx = &video_enc;
4504  video_enc.codec_id = video_id;
4505  type = AV_OPT_FLAG_VIDEO_PARAM;
4506  } else {
4507  avctx = &audio_enc;
4508  audio_enc.codec_id = audio_id;
4509  type = AV_OPT_FLAG_AUDIO_PARAM;
4510  }
4511  if (ffserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) {
4512  ERROR("AVPreset error: %s\n", arg);
4513  }
4514  } else if (!av_strcasecmp(cmd, "VideoTag")) {
4515  get_arg(arg, sizeof(arg), &p);
4516  if ((strlen(arg) == 4) && stream)
4517  video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
4518  } else if (!av_strcasecmp(cmd, "BitExact")) {
4519  if (stream)
4520  video_enc.flags |= CODEC_FLAG_BITEXACT;
4521  } else if (!av_strcasecmp(cmd, "DctFastint")) {
4522  if (stream)
4523  video_enc.dct_algo = FF_DCT_FASTINT;
4524  } else if (!av_strcasecmp(cmd, "IdctSimple")) {
4525  if (stream)
4526  video_enc.idct_algo = FF_IDCT_SIMPLE;
4527  } else if (!av_strcasecmp(cmd, "Qscale")) {
4528  get_arg(arg, sizeof(arg), &p);
4529  if (stream) {
4530  video_enc.flags |= CODEC_FLAG_QSCALE;
4531  video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
4532  }
4533  } else if (!av_strcasecmp(cmd, "VideoQDiff")) {
4534  get_arg(arg, sizeof(arg), &p);
4535  if (stream) {
4536  video_enc.max_qdiff = atoi(arg);
4537  if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
4538  ERROR("VideoQDiff out of range\n");
4539  }
4540  }
4541  } else if (!av_strcasecmp(cmd, "VideoQMax")) {
4542  get_arg(arg, sizeof(arg), &p);
4543  if (stream) {
4544  video_enc.qmax = atoi(arg);
4545  if (video_enc.qmax < 1 || video_enc.qmax > 31) {
4546  ERROR("VideoQMax out of range\n");
4547  }
4548  }
4549  } else if (!av_strcasecmp(cmd, "VideoQMin")) {
4550  get_arg(arg, sizeof(arg), &p);
4551  if (stream) {
4552  video_enc.qmin = atoi(arg);
4553  if (video_enc.qmin < 1 || video_enc.qmin > 31) {
4554  ERROR("VideoQMin out of range\n");
4555  }
4556  }
4557  } else if (!av_strcasecmp(cmd, "LumaElim")) {
4558  get_arg(arg, sizeof(arg), &p);
4559  if (stream)
4560  video_enc.luma_elim_threshold = atoi(arg);
4561  } else if (!av_strcasecmp(cmd, "ChromaElim")) {
4562  get_arg(arg, sizeof(arg), &p);
4563  if (stream)
4564  video_enc.chroma_elim_threshold = atoi(arg);
4565  } else if (!av_strcasecmp(cmd, "LumiMask")) {
4566  get_arg(arg, sizeof(arg), &p);
4567  if (stream)
4568  video_enc.lumi_masking = atof(arg);
4569  } else if (!av_strcasecmp(cmd, "DarkMask")) {
4570  get_arg(arg, sizeof(arg), &p);
4571  if (stream)
4572  video_enc.dark_masking = atof(arg);
4573  } else if (!av_strcasecmp(cmd, "NoVideo")) {
4574  video_id = AV_CODEC_ID_NONE;
4575  } else if (!av_strcasecmp(cmd, "NoAudio")) {
4576  audio_id = AV_CODEC_ID_NONE;
4577  } else if (!av_strcasecmp(cmd, "ACL")) {
4578  parse_acl_row(stream, feed, NULL, p, filename, line_num);
4579  } else if (!av_strcasecmp(cmd, "DynamicACL")) {
4580  if (stream) {
4581  get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p);
4582  }
4583  } else if (!av_strcasecmp(cmd, "RTSPOption")) {
4584  get_arg(arg, sizeof(arg), &p);
4585  if (stream) {
4586  av_freep(&stream->rtsp_option);
4587  stream->rtsp_option = av_strdup(arg);
4588  }
4589  } else if (!av_strcasecmp(cmd, "MulticastAddress")) {
4590  get_arg(arg, sizeof(arg), &p);
4591  if (stream) {
4592  if (resolve_host(&stream->multicast_ip, arg) != 0) {
4593  ERROR("Invalid host/IP address: %s\n", arg);
4594  }
4595  stream->is_multicast = 1;
4596  stream->loop = 1; /* default is looping */
4597  }
4598  } else if (!av_strcasecmp(cmd, "MulticastPort")) {
4599  get_arg(arg, sizeof(arg), &p);
4600  if (stream)
4601  stream->multicast_port = atoi(arg);
4602  } else if (!av_strcasecmp(cmd, "MulticastTTL")) {
4603  get_arg(arg, sizeof(arg), &p);
4604  if (stream)
4605  stream->multicast_ttl = atoi(arg);
4606  } else if (!av_strcasecmp(cmd, "NoLoop")) {
4607  if (stream)
4608  stream->loop = 0;
4609  } else if (!av_strcasecmp(cmd, "</Stream>")) {
4610  if (!stream) {
4611  ERROR("No corresponding <Stream> for </Stream>\n");
4612  } else {
4613  if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
4614  if (audio_id != AV_CODEC_ID_NONE) {
4615  audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
4616  audio_enc.codec_id = audio_id;
4617  add_codec(stream, &audio_enc);
4618  }
4619  if (video_id != AV_CODEC_ID_NONE) {
4620  video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
4621  video_enc.codec_id = video_id;
4622  add_codec(stream, &video_enc);
4623  }
4624  }
4625  stream = NULL;
4626  }
4627  } else if (!av_strcasecmp(cmd, "<Redirect")) {
4628  /*********************************************/
4629  char *q;
4630  if (stream || feed || redirect) {
4631  ERROR("Already in a tag\n");
4632  } else {
4633  redirect = av_mallocz(sizeof(FFStream));
4634  *last_stream = redirect;
4635  last_stream = &redirect->next;
4636 
4637  get_arg(redirect->filename, sizeof(redirect->filename), &p);
4638  q = strrchr(redirect->filename, '>');
4639  if (*q)
4640  *q = '\0';
4641  redirect->stream_type = STREAM_TYPE_REDIRECT;
4642  }
4643  } else if (!av_strcasecmp(cmd, "URL")) {
4644  if (redirect)
4645  get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
4646  } else if (!av_strcasecmp(cmd, "</Redirect>")) {
4647  if (!redirect) {
4648  ERROR("No corresponding <Redirect> for </Redirect>\n");
4649  } else {
4650  if (!redirect->feed_filename[0]) {
4651  ERROR("No URL found for <Redirect>\n");
4652  }
4653  redirect = NULL;
4654  }
4655  } else if (!av_strcasecmp(cmd, "LoadModule")) {
4656  get_arg(arg, sizeof(arg), &p);
4657 #if HAVE_DLOPEN
4658  load_module(arg);
4659 #else
4660  ERROR("Module support not compiled into this version: '%s'\n", arg);
4661 #endif
4662  } else {
4663  ERROR("Incorrect keyword: '%s'\n", cmd);
4664  }
4665  }
4666 #undef ERROR
4667 
4668  fclose(f);
4669  if (errors)
4670  return -1;
4671  else
4672  return 0;
4673 }
4674 
4675 static void handle_child_exit(int sig)
4676 {
4677  pid_t pid;
4678  int status;
4679 
4680  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4681  FFStream *feed;
4682 
4683  for (feed = first_feed; feed; feed = feed->next) {
4684  if (feed->pid == pid) {
4685  int uptime = time(0) - feed->pid_start;
4686 
4687  feed->pid = 0;
4688  fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
4689 
4690  if (uptime < 30)
4691  /* Turn off any more restarts */
4692  feed->child_argv = 0;
4693  }
4694  }
4695  }
4696 
4698 }
4699 
4700 static void opt_debug(void)
4701 {
4702  ffserver_debug = 1;
4703  logfilename[0] = '-';
4704 }
4705 
4706 void show_help_default(const char *opt, const char *arg)
4707 {
4708  printf("usage: ffserver [options]\n"
4709  "Hyper fast multi format Audio/Video streaming server\n");
4710  printf("\n");
4711  show_help_options(options, "Main options:", 0, 0, 0);
4712 }
4713 
4714 static const OptionDef options[] = {
4715 #include "cmdutils_common_opts.h"
4716  { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
4717  { "d", 0, {(void*)opt_debug}, "enable debug mode" },
4718  { "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/ffserver.conf", "configfile" },
4719  { NULL },
4720 };
4721 
4722 int main(int argc, char **argv)
4723 {
4724  struct sigaction sigact = { { 0 } };
4725 
4726  parse_loglevel(argc, argv, options);
4727  av_register_all();
4729 
4730  show_banner(argc, argv, options);
4731 
4732  my_program_name = argv[0];
4733 
4734  parse_options(NULL, argc, argv, options, NULL);
4735 
4736  unsetenv("http_proxy"); /* Kill the http_proxy */
4737 
4738  av_lfg_init(&random_state, av_get_random_seed());
4739 
4740  sigact.sa_handler = handle_child_exit;
4741  sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4742  sigaction(SIGCHLD, &sigact, 0);
4743 
4744  if (parse_ffconfig(config_filename) < 0) {
4745  fprintf(stderr, "Incorrect config file - exiting.\n");
4746  exit(1);
4747  }
4748 
4749  /* open log file if needed */
4750  if (logfilename[0] != '\0') {
4751  if (!strcmp(logfilename, "-"))
4752  logfile = stdout;
4753  else
4754  logfile = fopen(logfilename, "a");
4756  }
4757 
4759 
4761 
4763 
4764  /* signal init */
4765  signal(SIGPIPE, SIG_IGN);
4766 
4767  if (http_server() < 0) {
4768  http_log("Could not start server\n");
4769  exit(1);
4770  }
4771 
4772  return 0;
4773 }