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