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