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