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 * const 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; 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_array(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) {
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; 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) {
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; 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 static void get_word(char *buf, int buf_size, const char **pp)
1262 {
1263  const char *p;
1264  char *q;
1265 
1266  p = *pp;
1267  p += strspn(p, SPACE_CHARS);
1268  q = buf;
1269  while (!av_isspace(*p) && *p != '\0') {
1270  if ((q - buf) < buf_size - 1)
1271  *q++ = *p;
1272  p++;
1273  }
1274  if (buf_size > 0)
1275  *q = '\0';
1276  *pp = p;
1277 }
1278 
1279 static void get_arg(char *buf, int buf_size, const char **pp)
1280 {
1281  const char *p;
1282  char *q;
1283  int quote;
1284 
1285  p = *pp;
1286  while (av_isspace(*p)) p++;
1287  q = buf;
1288  quote = 0;
1289  if (*p == '\"' || *p == '\'')
1290  quote = *p++;
1291  for(;;) {
1292  if (quote) {
1293  if (*p == quote)
1294  break;
1295  } else {
1296  if (av_isspace(*p))
1297  break;
1298  }
1299  if (*p == '\0')
1300  break;
1301  if ((q - buf) < buf_size - 1)
1302  *q++ = *p;
1303  p++;
1304  }
1305  *q = '\0';
1306  if (quote && *p == quote)
1307  p++;
1308  *pp = p;
1309 }
1310 
1311 static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_acl,
1312  const char *p, const char *filename, int line_num)
1313 {
1314  char arg[1024];
1315  IPAddressACL acl;
1316  int errors = 0;
1317 
1318  get_arg(arg, sizeof(arg), &p);
1319  if (av_strcasecmp(arg, "allow") == 0)
1320  acl.action = IP_ALLOW;
1321  else if (av_strcasecmp(arg, "deny") == 0)
1322  acl.action = IP_DENY;
1323  else {
1324  fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1325  filename, line_num, arg);
1326  errors++;
1327  }
1328 
1329  get_arg(arg, sizeof(arg), &p);
1330 
1331  if (resolve_host(&acl.first, arg) != 0) {
1332  fprintf(stderr, "%s:%d: ACL refers to invalid host or IP address '%s'\n",
1333  filename, line_num, arg);
1334  errors++;
1335  } else
1336  acl.last = acl.first;
1337 
1338  get_arg(arg, sizeof(arg), &p);
1339 
1340  if (arg[0]) {
1341  if (resolve_host(&acl.last, arg) != 0) {
1342  fprintf(stderr, "%s:%d: ACL refers to invalid host or IP address '%s'\n",
1343  filename, line_num, arg);
1344  errors++;
1345  }
1346  }
1347 
1348  if (!errors) {
1349  IPAddressACL *nacl = av_mallocz(sizeof(*nacl));
1350  IPAddressACL **naclp = 0;
1351 
1352  acl.next = 0;
1353  *nacl = acl;
1354 
1355  if (stream)
1356  naclp = &stream->acl;
1357  else if (feed)
1358  naclp = &feed->acl;
1359  else if (ext_acl)
1360  naclp = &ext_acl;
1361  else {
1362  fprintf(stderr, "%s:%d: ACL found not in <stream> or <feed>\n",
1363  filename, line_num);
1364  errors++;
1365  }
1366 
1367  if (naclp) {
1368  while (*naclp)
1369  naclp = &(*naclp)->next;
1370 
1371  *naclp = nacl;
1372  } else
1373  av_free(nacl);
1374  }
1375 }
1376 
1377 
1379 {
1380  FILE* f;
1381  char line[1024];
1382  char cmd[1024];
1383  IPAddressACL *acl = NULL;
1384  int line_num = 0;
1385  const char *p;
1386 
1387  f = fopen(stream->dynamic_acl, "r");
1388  if (!f) {
1389  perror(stream->dynamic_acl);
1390  return NULL;
1391  }
1392 
1393  acl = av_mallocz(sizeof(IPAddressACL));
1394 
1395  /* Build ACL */
1396  for(;;) {
1397  if (fgets(line, sizeof(line), f) == NULL)
1398  break;
1399  line_num++;
1400  p = line;
1401  while (av_isspace(*p))
1402  p++;
1403  if (*p == '\0' || *p == '#')
1404  continue;
1405  get_arg(cmd, sizeof(cmd), &p);
1406 
1407  if (!av_strcasecmp(cmd, "ACL"))
1408  parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl, line_num);
1409  }
1410  fclose(f);
1411  return acl;
1412 }
1413 
1414 
1415 static void free_acl_list(IPAddressACL *in_acl)
1416 {
1417  IPAddressACL *pacl,*pacl2;
1418 
1419  pacl = in_acl;
1420  while(pacl) {
1421  pacl2 = pacl;
1422  pacl = pacl->next;
1423  av_freep(pacl2);
1424  }
1425 }
1426 
1428 {
1429  enum IPAddressAction last_action = IP_DENY;
1430  IPAddressACL *acl;
1431  struct in_addr *src = &c->from_addr.sin_addr;
1432  unsigned long src_addr = src->s_addr;
1433 
1434  for (acl = in_acl; acl; acl = acl->next) {
1435  if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr)
1436  return (acl->action == IP_ALLOW) ? 1 : 0;
1437  last_action = acl->action;
1438  }
1439 
1440  /* Nothing matched, so return not the last action */
1441  return (last_action == IP_DENY) ? 1 : 0;
1442 }
1443 
1444 static int validate_acl(FFStream *stream, HTTPContext *c)
1445 {
1446  int ret = 0;
1447  IPAddressACL *acl;
1448 
1449 
1450  /* if stream->acl is null validate_acl_list will return 1 */
1451  ret = validate_acl_list(stream->acl, c);
1452 
1453  if (stream->dynamic_acl[0]) {
1454  acl = parse_dynamic_acl(stream, c);
1455 
1456  ret = validate_acl_list(acl, c);
1457 
1458  free_acl_list(acl);
1459  }
1460 
1461  return ret;
1462 }
1463 
1464 /* compute the real filename of a file by matching it without its
1465  extensions to all the stream's filenames */
1466 static void compute_real_filename(char *filename, int max_size)
1467 {
1468  char file1[1024];
1469  char file2[1024];
1470  char *p;
1471  FFStream *stream;
1472 
1473  /* compute filename by matching without the file extensions */
1474  av_strlcpy(file1, filename, sizeof(file1));
1475  p = strrchr(file1, '.');
1476  if (p)
1477  *p = '\0';
1478  for(stream = first_stream; stream; stream = stream->next) {
1479  av_strlcpy(file2, stream->filename, sizeof(file2));
1480  p = strrchr(file2, '.');
1481  if (p)
1482  *p = '\0';
1483  if (!strcmp(file1, file2)) {
1484  av_strlcpy(filename, stream->filename, max_size);
1485  break;
1486  }
1487  }
1488 }
1489 
1497 };
1498 
1499 /* parse HTTP request and prepare header */
1501 {
1502  const char *p;
1503  char *p1;
1504  enum RedirType redir_type;
1505  char cmd[32];
1506  char info[1024], filename[1024];
1507  char url[1024], *q;
1508  char protocol[32];
1509  char msg[1024];
1510  const char *mime_type;
1511  FFStream *stream;
1512  int i;
1513  char ratebuf[32];
1514  const char *useragent = 0;
1515 
1516  p = c->buffer;
1517  get_word(cmd, sizeof(cmd), &p);
1518  av_strlcpy(c->method, cmd, sizeof(c->method));
1519 
1520  if (!strcmp(cmd, "GET"))
1521  c->post = 0;
1522  else if (!strcmp(cmd, "POST"))
1523  c->post = 1;
1524  else
1525  return -1;
1526 
1527  get_word(url, sizeof(url), &p);
1528  av_strlcpy(c->url, url, sizeof(c->url));
1529 
1530  get_word(protocol, sizeof(protocol), (const char **)&p);
1531  if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
1532  return -1;
1533 
1534  av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
1535 
1536  if (ffserver_debug)
1537  http_log("%s - - New connection: %s %s\n", inet_ntoa(c->from_addr.sin_addr), cmd, url);
1538 
1539  /* find the filename and the optional info string in the request */
1540  p1 = strchr(url, '?');
1541  if (p1) {
1542  av_strlcpy(info, p1, sizeof(info));
1543  *p1 = '\0';
1544  } else
1545  info[0] = '\0';
1546 
1547  av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1);
1548 
1549  for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1550  if (av_strncasecmp(p, "User-Agent:", 11) == 0) {
1551  useragent = p + 11;
1552  if (*useragent && *useragent != '\n' && av_isspace(*useragent))
1553  useragent++;
1554  break;
1555  }
1556  p = strchr(p, '\n');
1557  if (!p)
1558  break;
1559 
1560  p++;
1561  }
1562 
1563  redir_type = REDIR_NONE;
1564  if (av_match_ext(filename, "asx")) {
1565  redir_type = REDIR_ASX;
1566  filename[strlen(filename)-1] = 'f';
1567  } else if (av_match_ext(filename, "asf") &&
1568  (!useragent || av_strncasecmp(useragent, "NSPlayer", 8) != 0)) {
1569  /* if this isn't WMP or lookalike, return the redirector file */
1570  redir_type = REDIR_ASF;
1571  } else if (av_match_ext(filename, "rpm,ram")) {
1572  redir_type = REDIR_RAM;
1573  strcpy(filename + strlen(filename)-2, "m");
1574  } else if (av_match_ext(filename, "rtsp")) {
1575  redir_type = REDIR_RTSP;
1576  compute_real_filename(filename, sizeof(filename) - 1);
1577  } else if (av_match_ext(filename, "sdp")) {
1578  redir_type = REDIR_SDP;
1579  compute_real_filename(filename, sizeof(filename) - 1);
1580  }
1581 
1582  // "redirect" / request to index.html
1583  if (!strlen(filename))
1584  av_strlcpy(filename, "index.html", sizeof(filename) - 1);
1585 
1586  stream = first_stream;
1587  while (stream) {
1588  if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
1589  break;
1590  stream = stream->next;
1591  }
1592  if (!stream) {
1593  snprintf(msg, sizeof(msg), "File '%s' not found", url);
1594  http_log("File '%s' not found\n", url);
1595  goto send_error;
1596  }
1597 
1598  c->stream = stream;
1599  memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
1600  memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
1601 
1602  if (stream->stream_type == STREAM_TYPE_REDIRECT) {
1603  c->http_error = 301;
1604  q = c->buffer;
1605  snprintf(q, c->buffer_size,
1606  "HTTP/1.0 301 Moved\r\n"
1607  "Location: %s\r\n"
1608  "Content-type: text/html\r\n"
1609  "\r\n"
1610  "<html><head><title>Moved</title></head><body>\r\n"
1611  "You should be <a href=\"%s\">redirected</a>.\r\n"
1612  "</body></html>\r\n", stream->feed_filename, stream->feed_filename);
1613  q += strlen(q);
1614  /* prepare output buffer */
1615  c->buffer_ptr = c->buffer;
1616  c->buffer_end = q;
1618  return 0;
1619  }
1620 
1621  /* If this is WMP, get the rate information */
1622  if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1623  if (modify_current_stream(c, ratebuf)) {
1624  for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) {
1625  if (c->switch_feed_streams[i] >= 0)
1626  c->switch_feed_streams[i] = -1;
1627  }
1628  }
1629  }
1630 
1631  if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
1632  current_bandwidth += stream->bandwidth;
1633 
1634  /* If already streaming this feed, do not let start another feeder. */
1635  if (stream->feed_opened) {
1636  snprintf(msg, sizeof(msg), "This feed is already being received.");
1637  http_log("Feed '%s' already being received\n", stream->feed_filename);
1638  goto send_error;
1639  }
1640 
1641  if (c->post == 0 && max_bandwidth < current_bandwidth) {
1642  c->http_error = 503;
1643  q = c->buffer;
1644  snprintf(q, c->buffer_size,
1645  "HTTP/1.0 503 Server too busy\r\n"
1646  "Content-type: text/html\r\n"
1647  "\r\n"
1648  "<html><head><title>Too busy</title></head><body>\r\n"
1649  "<p>The server is too busy to serve your request at this time.</p>\r\n"
1650  "<p>The bandwidth being served (including your stream) is %"PRIu64"kbit/sec, "
1651  "and this exceeds the limit of %"PRIu64"kbit/sec.</p>\r\n"
1652  "</body></html>\r\n", current_bandwidth, max_bandwidth);
1653  q += strlen(q);
1654  /* prepare output buffer */
1655  c->buffer_ptr = c->buffer;
1656  c->buffer_end = q;
1658  return 0;
1659  }
1660 
1661  if (redir_type != REDIR_NONE) {
1662  const char *hostinfo = 0;
1663 
1664  for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1665  if (av_strncasecmp(p, "Host:", 5) == 0) {
1666  hostinfo = p + 5;
1667  break;
1668  }
1669  p = strchr(p, '\n');
1670  if (!p)
1671  break;
1672 
1673  p++;
1674  }
1675 
1676  if (hostinfo) {
1677  char *eoh;
1678  char hostbuf[260];
1679 
1680  while (av_isspace(*hostinfo))
1681  hostinfo++;
1682 
1683  eoh = strchr(hostinfo, '\n');
1684  if (eoh) {
1685  if (eoh[-1] == '\r')
1686  eoh--;
1687 
1688  if (eoh - hostinfo < sizeof(hostbuf) - 1) {
1689  memcpy(hostbuf, hostinfo, eoh - hostinfo);
1690  hostbuf[eoh - hostinfo] = 0;
1691 
1692  c->http_error = 200;
1693  q = c->buffer;
1694  switch(redir_type) {
1695  case REDIR_ASX:
1696  snprintf(q, c->buffer_size,
1697  "HTTP/1.0 200 ASX Follows\r\n"
1698  "Content-type: video/x-ms-asf\r\n"
1699  "\r\n"
1700  "<ASX Version=\"3\">\r\n"
1701  //"<!-- Autogenerated by ffserver -->\r\n"
1702  "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1703  "</ASX>\r\n", hostbuf, filename, info);
1704  q += strlen(q);
1705  break;
1706  case REDIR_RAM:
1707  snprintf(q, c->buffer_size,
1708  "HTTP/1.0 200 RAM Follows\r\n"
1709  "Content-type: audio/x-pn-realaudio\r\n"
1710  "\r\n"
1711  "# Autogenerated by ffserver\r\n"
1712  "http://%s/%s%s\r\n", hostbuf, filename, info);
1713  q += strlen(q);
1714  break;
1715  case REDIR_ASF:
1716  snprintf(q, c->buffer_size,
1717  "HTTP/1.0 200 ASF Redirect follows\r\n"
1718  "Content-type: video/x-ms-asf\r\n"
1719  "\r\n"
1720  "[Reference]\r\n"
1721  "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1722  q += strlen(q);
1723  break;
1724  case REDIR_RTSP:
1725  {
1726  char hostname[256], *p;
1727  /* extract only hostname */
1728  av_strlcpy(hostname, hostbuf, sizeof(hostname));
1729  p = strrchr(hostname, ':');
1730  if (p)
1731  *p = '\0';
1732  snprintf(q, c->buffer_size,
1733  "HTTP/1.0 200 RTSP Redirect follows\r\n"
1734  /* XXX: incorrect MIME type ? */
1735  "Content-type: application/x-rtsp\r\n"
1736  "\r\n"
1737  "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename);
1738  q += strlen(q);
1739  }
1740  break;
1741  case REDIR_SDP:
1742  {
1743  uint8_t *sdp_data;
1744  int sdp_data_size;
1745  socklen_t len;
1746  struct sockaddr_in my_addr;
1747 
1748  snprintf(q, c->buffer_size,
1749  "HTTP/1.0 200 OK\r\n"
1750  "Content-type: application/sdp\r\n"
1751  "\r\n");
1752  q += strlen(q);
1753 
1754  len = sizeof(my_addr);
1755 
1756  /* XXX: Should probably fail? */
1757  if (getsockname(c->fd, (struct sockaddr *)&my_addr, &len))
1758  http_log("getsockname() failed\n");
1759 
1760  /* XXX: should use a dynamic buffer */
1761  sdp_data_size = prepare_sdp_description(stream,
1762  &sdp_data,
1763  my_addr.sin_addr);
1764  if (sdp_data_size > 0) {
1765  memcpy(q, sdp_data, sdp_data_size);
1766  q += sdp_data_size;
1767  *q = '\0';
1768  av_free(sdp_data);
1769  }
1770  }
1771  break;
1772  default:
1773  abort();
1774  break;
1775  }
1776 
1777  /* prepare output buffer */
1778  c->buffer_ptr = c->buffer;
1779  c->buffer_end = q;
1781  return 0;
1782  }
1783  }
1784  }
1785 
1786  snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
1787  goto send_error;
1788  }
1789 
1790  stream->conns_served++;
1791 
1792  /* XXX: add there authenticate and IP match */
1793 
1794  if (c->post) {
1795  /* if post, it means a feed is being sent */
1796  if (!stream->is_feed) {
1797  /* However it might be a status report from WMP! Let us log the
1798  * data as it might come handy one day. */
1799  const char *logline = 0;
1800  int client_id = 0;
1801 
1802  for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1803  if (av_strncasecmp(p, "Pragma: log-line=", 17) == 0) {
1804  logline = p;
1805  break;
1806  }
1807  if (av_strncasecmp(p, "Pragma: client-id=", 18) == 0)
1808  client_id = strtol(p + 18, 0, 10);
1809  p = strchr(p, '\n');
1810  if (!p)
1811  break;
1812 
1813  p++;
1814  }
1815 
1816  if (logline) {
1817  char *eol = strchr(logline, '\n');
1818 
1819  logline += 17;
1820 
1821  if (eol) {
1822  if (eol[-1] == '\r')
1823  eol--;
1824  http_log("%.*s\n", (int) (eol - logline), logline);
1825  c->suppress_log = 1;
1826  }
1827  }
1828 
1829 #ifdef DEBUG
1830  http_log("\nGot request:\n%s\n", c->buffer);
1831 #endif
1832 
1833  if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1834  HTTPContext *wmpc;
1835 
1836  /* Now we have to find the client_id */
1837  for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
1838  if (wmpc->wmp_client_id == client_id)
1839  break;
1840  }
1841 
1842  if (wmpc && modify_current_stream(wmpc, ratebuf))
1843  wmpc->switch_pending = 1;
1844  }
1845 
1846  snprintf(msg, sizeof(msg), "POST command not handled");
1847  c->stream = 0;
1848  goto send_error;
1849  }
1850  if (http_start_receive_data(c) < 0) {
1851  snprintf(msg, sizeof(msg), "could not open feed");
1852  goto send_error;
1853  }
1854  c->http_error = 0;
1856  return 0;
1857  }
1858 
1859 #ifdef DEBUG
1860  if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0)
1861  http_log("\nGot request:\n%s\n", c->buffer);
1862 #endif
1863 
1865  goto send_status;
1866 
1867  /* open input stream */
1868  if (open_input_stream(c, info) < 0) {
1869  snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
1870  goto send_error;
1871  }
1872 
1873  /* prepare HTTP header */
1874  c->buffer[0] = 0;
1875  av_strlcatf(c->buffer, c->buffer_size, "HTTP/1.0 200 OK\r\n");
1876  mime_type = c->stream->fmt->mime_type;
1877  if (!mime_type)
1878  mime_type = "application/x-octet-stream";
1879  av_strlcatf(c->buffer, c->buffer_size, "Pragma: no-cache\r\n");
1880 
1881  /* for asf, we need extra headers */
1882  if (!strcmp(c->stream->fmt->name,"asf_stream")) {
1883  /* Need to allocate a client id */
1884 
1885  c->wmp_client_id = av_lfg_get(&random_state);
1886 
1887  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);
1888  }
1889  av_strlcatf(c->buffer, c->buffer_size, "Content-Type: %s\r\n", mime_type);
1890  av_strlcatf(c->buffer, c->buffer_size, "\r\n");
1891  q = c->buffer + strlen(c->buffer);
1892 
1893  /* prepare output buffer */
1894  c->http_error = 0;
1895  c->buffer_ptr = c->buffer;
1896  c->buffer_end = q;
1898  return 0;
1899  send_error:
1900  c->http_error = 404;
1901  q = c->buffer;
1902  htmlstrip(msg);
1903  snprintf(q, c->buffer_size,
1904  "HTTP/1.0 404 Not Found\r\n"
1905  "Content-type: text/html\r\n"
1906  "\r\n"
1907  "<html>\n"
1908  "<head><title>404 Not Found</title></head>\n"
1909  "<body>%s</body>\n"
1910  "</html>\n", msg);
1911  q += strlen(q);
1912  /* prepare output buffer */
1913  c->buffer_ptr = c->buffer;
1914  c->buffer_end = q;
1916  return 0;
1917  send_status:
1918  compute_status(c);
1919  c->http_error = 200; /* horrible : we use this value to avoid
1920  going to the send data state */
1922  return 0;
1923 }
1924 
1925 static void fmt_bytecount(AVIOContext *pb, int64_t count)
1926 {
1927  static const char suffix[] = " kMGTP";
1928  const char *s;
1929 
1930  for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1931 
1932  avio_printf(pb, "%"PRId64"%c", count, *s);
1933 }
1934 
1936 {
1937  HTTPContext *c1;
1938  FFStream *stream;
1939  char *p;
1940  time_t ti;
1941  int i, len;
1942  AVIOContext *pb;
1943 
1944  if (avio_open_dyn_buf(&pb) < 0) {
1945  /* XXX: return an error ? */
1946  c->buffer_ptr = c->buffer;
1947  c->buffer_end = c->buffer;
1948  return;
1949  }
1950 
1951  avio_printf(pb, "HTTP/1.0 200 OK\r\n");
1952  avio_printf(pb, "Content-type: text/html\r\n");
1953  avio_printf(pb, "Pragma: no-cache\r\n");
1954  avio_printf(pb, "\r\n");
1955 
1956  avio_printf(pb, "<html><head><title>%s Status</title>\n", program_name);
1957  if (c->stream->feed_filename[0])
1958  avio_printf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
1959  avio_printf(pb, "</head>\n<body>");
1960  avio_printf(pb, "<h1>%s Status</h1>\n", program_name);
1961  /* format status */
1962  avio_printf(pb, "<h2>Available Streams</h2>\n");
1963  avio_printf(pb, "<table cellspacing=0 cellpadding=4>\n");
1964  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");
1965  stream = first_stream;
1966  while (stream) {
1967  char sfilename[1024];
1968  char *eosf;
1969 
1970  if (stream->feed != stream) {
1971  av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
1972  eosf = sfilename + strlen(sfilename);
1973  if (eosf - sfilename >= 4) {
1974  if (strcmp(eosf - 4, ".asf") == 0)
1975  strcpy(eosf - 4, ".asx");
1976  else if (strcmp(eosf - 3, ".rm") == 0)
1977  strcpy(eosf - 3, ".ram");
1978  else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
1979  /* generate a sample RTSP director if
1980  unicast. Generate an SDP redirector if
1981  multicast */
1982  eosf = strrchr(sfilename, '.');
1983  if (!eosf)
1984  eosf = sfilename + strlen(sfilename);
1985  if (stream->is_multicast)
1986  strcpy(eosf, ".sdp");
1987  else
1988  strcpy(eosf, ".rtsp");
1989  }
1990  }
1991 
1992  avio_printf(pb, "<tr><td><a href=\"/%s\">%s</a> ",
1993  sfilename, stream->filename);
1994  avio_printf(pb, "<td align=right> %d <td align=right> ",
1995  stream->conns_served);
1996  fmt_bytecount(pb, stream->bytes_served);
1997  switch(stream->stream_type) {
1998  case STREAM_TYPE_LIVE: {
1999  int audio_bit_rate = 0;
2000  int video_bit_rate = 0;
2001  const char *audio_codec_name = "";
2002  const char *video_codec_name = "";
2003  const char *audio_codec_name_extra = "";
2004  const char *video_codec_name_extra = "";
2005 
2006  for(i=0;i<stream->nb_streams;i++) {
2007  AVStream *st = stream->streams[i];
2008  AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
2009  switch(st->codec->codec_type) {
2010  case AVMEDIA_TYPE_AUDIO:
2011  audio_bit_rate += st->codec->bit_rate;
2012  if (codec) {
2013  if (*audio_codec_name)
2014  audio_codec_name_extra = "...";
2015  audio_codec_name = codec->name;
2016  }
2017  break;
2018  case AVMEDIA_TYPE_VIDEO:
2019  video_bit_rate += st->codec->bit_rate;
2020  if (codec) {
2021  if (*video_codec_name)
2022  video_codec_name_extra = "...";
2023  video_codec_name = codec->name;
2024  }
2025  break;
2026  case AVMEDIA_TYPE_DATA:
2027  video_bit_rate += st->codec->bit_rate;
2028  break;
2029  default:
2030  abort();
2031  }
2032  }
2033  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",
2034  stream->fmt->name,
2035  stream->bandwidth,
2036  video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
2037  audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
2038  if (stream->feed)
2039  avio_printf(pb, "<td>%s", stream->feed->filename);
2040  else
2041  avio_printf(pb, "<td>%s", stream->feed_filename);
2042  avio_printf(pb, "\n");
2043  }
2044  break;
2045  default:
2046  avio_printf(pb, "<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
2047  break;
2048  }
2049  }
2050  stream = stream->next;
2051  }
2052  avio_printf(pb, "</table>\n");
2053 
2054  stream = first_stream;
2055  while (stream) {
2056  if (stream->feed == stream) {
2057  avio_printf(pb, "<h2>Feed %s</h2>", stream->filename);
2058  if (stream->pid) {
2059  avio_printf(pb, "Running as pid %d.\n", stream->pid);
2060 
2061 #if defined(linux)
2062  {
2063  FILE *pid_stat;
2064  char ps_cmd[64];
2065 
2066  /* This is somewhat linux specific I guess */
2067  snprintf(ps_cmd, sizeof(ps_cmd),
2068  "ps -o \"%%cpu,cputime\" --no-headers %d",
2069  stream->pid);
2070 
2071  pid_stat = popen(ps_cmd, "r");
2072  if (pid_stat) {
2073  char cpuperc[10];
2074  char cpuused[64];
2075 
2076  if (fscanf(pid_stat, "%9s %63s", cpuperc,
2077  cpuused) == 2) {
2078  avio_printf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
2079  cpuperc, cpuused);
2080  }
2081  fclose(pid_stat);
2082  }
2083  }
2084 #endif
2085 
2086  avio_printf(pb, "<p>");
2087  }
2088  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");
2089 
2090  for (i = 0; i < stream->nb_streams; i++) {
2091  AVStream *st = stream->streams[i];
2092  AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
2093  const char *type = "unknown";
2094  char parameters[64];
2095 
2096  parameters[0] = 0;
2097 
2098  switch(st->codec->codec_type) {
2099  case AVMEDIA_TYPE_AUDIO:
2100  type = "audio";
2101  snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz", st->codec->channels, st->codec->sample_rate);
2102  break;
2103  case AVMEDIA_TYPE_VIDEO:
2104  type = "video";
2105  snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec->width, st->codec->height,
2106  st->codec->qmin, st->codec->qmax, st->codec->time_base.den / st->codec->time_base.num);
2107  break;
2108  default:
2109  abort();
2110  }
2111  avio_printf(pb, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2112  i, type, st->codec->bit_rate/1000, codec ? codec->name : "", parameters);
2113  }
2114  avio_printf(pb, "</table>\n");
2115 
2116  }
2117  stream = stream->next;
2118  }
2119 
2120  /* connection status */
2121  avio_printf(pb, "<h2>Connection Status</h2>\n");
2122 
2123  avio_printf(pb, "Number of connections: %d / %d<br>\n",
2125 
2126  avio_printf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<br>\n",
2128 
2129  avio_printf(pb, "<table>\n");
2130  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");
2131  c1 = first_http_ctx;
2132  i = 0;
2133  while (c1) {
2134  int bitrate;
2135  int j;
2136 
2137  bitrate = 0;
2138  if (c1->stream) {
2139  for (j = 0; j < c1->stream->nb_streams; j++) {
2140  if (!c1->stream->feed)
2141  bitrate += c1->stream->streams[j]->codec->bit_rate;
2142  else if (c1->feed_streams[j] >= 0)
2143  bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
2144  }
2145  }
2146 
2147  i++;
2148  p = inet_ntoa(c1->from_addr.sin_addr);
2149  avio_printf(pb, "<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2150  i,
2151  c1->stream ? c1->stream->filename : "",
2152  c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
2153  p,
2154  c1->protocol,
2155  http_state[c1->state]);
2156  fmt_bytecount(pb, bitrate);
2157  avio_printf(pb, "<td align=right>");
2158  fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
2159  avio_printf(pb, "<td align=right>");
2160  fmt_bytecount(pb, c1->data_count);
2161  avio_printf(pb, "\n");
2162  c1 = c1->next;
2163  }
2164  avio_printf(pb, "</table>\n");
2165 
2166  /* date */
2167  ti = time(NULL);
2168  p = ctime(&ti);
2169  avio_printf(pb, "<hr size=1 noshade>Generated at %s", p);
2170  avio_printf(pb, "</body>\n</html>\n");
2171 
2172  len = avio_close_dyn_buf(pb, &c->pb_buffer);
2173  c->buffer_ptr = c->pb_buffer;
2174  c->buffer_end = c->pb_buffer + len;
2175 }
2176 
2177 static int open_input_stream(HTTPContext *c, const char *info)
2178 {
2179  char buf[128];
2180  char input_filename[1024];
2181  AVFormatContext *s = NULL;
2182  int buf_size, i, ret;
2183  int64_t stream_pos;
2184 
2185  /* find file name */
2186  if (c->stream->feed) {
2187  strcpy(input_filename, c->stream->feed->feed_filename);
2188  buf_size = FFM_PACKET_SIZE;
2189  /* compute position (absolute time) */
2190  if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2191  if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0) {
2192  http_log("Invalid date specification '%s' for stream\n", buf);
2193  return ret;
2194  }
2195  } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) {
2196  int prebuffer = strtol(buf, 0, 10);
2197  stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
2198  } else
2199  stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
2200  } else {
2201  strcpy(input_filename, c->stream->feed_filename);
2202  buf_size = 0;
2203  /* compute position (relative time) */
2204  if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2205  if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0) {
2206  http_log("Invalid date specification '%s' for stream\n", buf);
2207  return ret;
2208  }
2209  } else
2210  stream_pos = 0;
2211  }
2212  if (!input_filename[0]) {
2213  http_log("No filename was specified for stream\n");
2214  return AVERROR(EINVAL);
2215  }
2216 
2217  /* open stream */
2218  if ((ret = avformat_open_input(&s, input_filename, c->stream->ifmt, &c->stream->in_opts)) < 0) {
2219  http_log("Could not open input '%s': %s\n", input_filename, av_err2str(ret));
2220  return ret;
2221  }
2222 
2223  /* set buffer size */
2224  if (buf_size > 0) ffio_set_buf_size(s->pb, buf_size);
2225 
2226  s->flags |= AVFMT_FLAG_GENPTS;
2227  c->fmt_in = s;
2228  if (strcmp(s->iformat->name, "ffm") &&
2229  (ret = avformat_find_stream_info(c->fmt_in, NULL)) < 0) {
2230  http_log("Could not find stream info for input '%s'\n", input_filename);
2232  return ret;
2233  }
2234 
2235  /* choose stream as clock source (we favor the video stream if
2236  * present) for packet sending */
2237  c->pts_stream_index = 0;
2238  for(i=0;i<c->stream->nb_streams;i++) {
2239  if (c->pts_stream_index == 0 &&
2241  c->pts_stream_index = i;
2242  }
2243  }
2244 
2245  if (c->fmt_in->iformat->read_seek)
2246  av_seek_frame(c->fmt_in, -1, stream_pos, 0);
2247  /* set the start time (needed for maxtime and RTP packet timing) */
2248  c->start_time = cur_time;
2250  return 0;
2251 }
2252 
2253 /* return the server clock (in us) */
2255 {
2256  /* compute current pts value from system time */
2257  return (cur_time - c->start_time) * 1000;
2258 }
2259 
2260 /* return the estimated time at which the current packet must be sent
2261  (in us) */
2263 {
2264  int bytes_left, bytes_sent, frame_bytes;
2265 
2266  frame_bytes = c->cur_frame_bytes;
2267  if (frame_bytes <= 0)
2268  return c->cur_pts;
2269  else {
2270  bytes_left = c->buffer_end - c->buffer_ptr;
2271  bytes_sent = frame_bytes - bytes_left;
2272  return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
2273  }
2274 }
2275 
2276 
2278 {
2279  int i, len, ret;
2280  AVFormatContext *ctx;
2281 
2282  av_freep(&c->pb_buffer);
2283  switch(c->state) {
2285  ctx = avformat_alloc_context();
2286  c->fmt_ctx = *ctx;
2287  av_freep(&ctx);
2288  av_dict_copy(&(c->fmt_ctx.metadata), c->stream->metadata, 0);
2290 
2291  for(i=0;i<c->stream->nb_streams;i++) {
2292  AVStream *src;
2293  c->fmt_ctx.streams[i] = av_mallocz(sizeof(AVStream));
2294  /* if file or feed, then just take streams from FFStream struct */
2295  if (!c->stream->feed ||
2296  c->stream->feed == c->stream)
2297  src = c->stream->streams[i];
2298  else
2299  src = c->stream->feed->streams[c->stream->feed_streams[i]];
2300 
2301  *(c->fmt_ctx.streams[i]) = *src;
2302  c->fmt_ctx.streams[i]->priv_data = 0;
2303  /* XXX: should be done in AVStream, not in codec */
2304  c->fmt_ctx.streams[i]->codec->frame_number = 0;
2305  }
2306  /* set output format parameters */
2307  c->fmt_ctx.oformat = c->stream->fmt;
2309 
2310  c->got_key_frame = 0;
2311 
2312  /* prepare header and save header data in a stream */
2313  if (avio_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
2314  /* XXX: potential leak */
2315  return -1;
2316  }
2317  c->fmt_ctx.pb->seekable = 0;
2318 
2319  /*
2320  * HACK to avoid MPEG-PS muxer to spit many underflow errors
2321  * Default value from FFmpeg
2322  * Try to set it using configuration option
2323  */
2324  c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
2325 
2326  if ((ret = avformat_write_header(&c->fmt_ctx, NULL)) < 0) {
2327  http_log("Error writing output header for stream '%s': %s\n",
2328  c->stream->filename, av_err2str(ret));
2329  return ret;
2330  }
2332 
2333  len = avio_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
2334  c->buffer_ptr = c->pb_buffer;
2335  c->buffer_end = c->pb_buffer + len;
2336 
2338  c->last_packet_sent = 0;
2339  break;
2340  case HTTPSTATE_SEND_DATA:
2341  /* find a new packet */
2342  /* read a packet from the input stream */
2343  if (c->stream->feed)
2346  c->stream->feed->feed_size);
2347 
2348  if (c->stream->max_time &&
2349  c->stream->max_time + c->start_time - cur_time < 0)
2350  /* We have timed out */
2352  else {
2353  AVPacket pkt;
2354  redo:
2355  ret = av_read_frame(c->fmt_in, &pkt);
2356  if (ret < 0) {
2357  if (c->stream->feed) {
2358  /* if coming from feed, it means we reached the end of the
2359  ffm file, so must wait for more data */
2361  return 1; /* state changed */
2362  } else if (ret == AVERROR(EAGAIN)) {
2363  /* input not ready, come back later */
2364  return 0;
2365  } else {
2366  if (c->stream->loop) {
2368  if (open_input_stream(c, "") < 0)
2369  goto no_loop;
2370  goto redo;
2371  } else {
2372  no_loop:
2373  /* must send trailer now because EOF or error */
2375  }
2376  }
2377  } else {
2378  int source_index = pkt.stream_index;
2379  /* update first pts if needed */
2380  if (c->first_pts == AV_NOPTS_VALUE) {
2382  c->start_time = cur_time;
2383  }
2384  /* send it to the appropriate stream */
2385  if (c->stream->feed) {
2386  /* if coming from a feed, select the right stream */
2387  if (c->switch_pending) {
2388  c->switch_pending = 0;
2389  for(i=0;i<c->stream->nb_streams;i++) {
2390  if (c->switch_feed_streams[i] == pkt.stream_index)
2391  if (pkt.flags & AV_PKT_FLAG_KEY)
2392  c->switch_feed_streams[i] = -1;
2393  if (c->switch_feed_streams[i] >= 0)
2394  c->switch_pending = 1;
2395  }
2396  }
2397  for(i=0;i<c->stream->nb_streams;i++) {
2398  if (c->stream->feed_streams[i] == pkt.stream_index) {
2399  AVStream *st = c->fmt_in->streams[source_index];
2400  pkt.stream_index = i;
2401  if (pkt.flags & AV_PKT_FLAG_KEY &&
2402  (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2403  c->stream->nb_streams == 1))
2404  c->got_key_frame = 1;
2405  if (!c->stream->send_on_key || c->got_key_frame)
2406  goto send_it;
2407  }
2408  }
2409  } else {
2410  AVCodecContext *codec;
2411  AVStream *ist, *ost;
2412  send_it:
2413  ist = c->fmt_in->streams[source_index];
2414  /* specific handling for RTP: we use several
2415  * output streams (one for each RTP connection).
2416  * XXX: need more abstract handling */
2417  if (c->is_packetized) {
2418  /* compute send time and duration */
2419  c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
2420  c->cur_pts -= c->first_pts;
2422  /* find RTP context */
2424  ctx = c->rtp_ctx[c->packet_stream_index];
2425  if(!ctx) {
2426  av_free_packet(&pkt);
2427  break;
2428  }
2429  codec = ctx->streams[0]->codec;
2430  /* only one stream per RTP connection */
2431  pkt.stream_index = 0;
2432  } else {
2433  ctx = &c->fmt_ctx;
2434  /* Fudge here */
2435  codec = ctx->streams[pkt.stream_index]->codec;
2436  }
2437 
2438  if (c->is_packetized) {
2439  int max_packet_size;
2441  max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2442  else
2443  max_packet_size = c->rtp_handles[c->packet_stream_index]->max_packet_size;
2444  ret = ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size);
2445  } else {
2446  ret = avio_open_dyn_buf(&ctx->pb);
2447  }
2448  if (ret < 0) {
2449  /* XXX: potential leak */
2450  return -1;
2451  }
2452  ost = ctx->streams[pkt.stream_index];
2453 
2454  ctx->pb->seekable = 0;
2455  if (pkt.dts != AV_NOPTS_VALUE)
2456  pkt.dts = av_rescale_q(pkt.dts, ist->time_base, ost->time_base);
2457  if (pkt.pts != AV_NOPTS_VALUE)
2458  pkt.pts = av_rescale_q(pkt.pts, ist->time_base, ost->time_base);
2459  pkt.duration = av_rescale_q(pkt.duration, ist->time_base, ost->time_base);
2460  if ((ret = av_write_frame(ctx, &pkt)) < 0) {
2461  http_log("Error writing frame to output for stream '%s': %s\n",
2462  c->stream->filename, av_err2str(ret));
2464  }
2465 
2466  len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2467  c->cur_frame_bytes = len;
2468  c->buffer_ptr = c->pb_buffer;
2469  c->buffer_end = c->pb_buffer + len;
2470 
2471  codec->frame_number++;
2472  if (len == 0) {
2473  av_free_packet(&pkt);
2474  goto redo;
2475  }
2476  }
2477  av_free_packet(&pkt);
2478  }
2479  }
2480  break;
2481  default:
2483  /* last packet test ? */
2484  if (c->last_packet_sent || c->is_packetized)
2485  return -1;
2486  ctx = &c->fmt_ctx;
2487  /* prepare header */
2488  if (avio_open_dyn_buf(&ctx->pb) < 0) {
2489  /* XXX: potential leak */
2490  return -1;
2491  }
2492  c->fmt_ctx.pb->seekable = 0;
2493  av_write_trailer(ctx);
2494  len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2495  c->buffer_ptr = c->pb_buffer;
2496  c->buffer_end = c->pb_buffer + len;
2497 
2498  c->last_packet_sent = 1;
2499  break;
2500  }
2501  return 0;
2502 }
2503 
2504 /* should convert the format at the same time */
2505 /* send data starting at c->buffer_ptr to the output connection
2506  * (either UDP or TCP) */
2508 {
2509  int len, ret;
2510 
2511  for(;;) {
2512  if (c->buffer_ptr >= c->buffer_end) {
2513  ret = http_prepare_data(c);
2514  if (ret < 0)
2515  return -1;
2516  else if (ret != 0)
2517  /* state change requested */
2518  break;
2519  } else {
2520  if (c->is_packetized) {
2521  /* RTP data output */
2522  len = c->buffer_end - c->buffer_ptr;
2523  if (len < 4) {
2524  /* fail safe - should never happen */
2525  fail1:
2526  c->buffer_ptr = c->buffer_end;
2527  return 0;
2528  }
2529  len = (c->buffer_ptr[0] << 24) |
2530  (c->buffer_ptr[1] << 16) |
2531  (c->buffer_ptr[2] << 8) |
2532  (c->buffer_ptr[3]);
2533  if (len > (c->buffer_end - c->buffer_ptr))
2534  goto fail1;
2535  if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2536  /* nothing to send yet: we can wait */
2537  return 0;
2538  }
2539 
2540  c->data_count += len;
2542  if (c->stream)
2543  c->stream->bytes_served += len;
2544 
2546  /* RTP packets are sent inside the RTSP TCP connection */
2547  AVIOContext *pb;
2548  int interleaved_index, size;
2549  uint8_t header[4];
2550  HTTPContext *rtsp_c;
2551 
2552  rtsp_c = c->rtsp_c;
2553  /* if no RTSP connection left, error */
2554  if (!rtsp_c)
2555  return -1;
2556  /* if already sending something, then wait. */
2557  if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2558  break;
2559  if (avio_open_dyn_buf(&pb) < 0)
2560  goto fail1;
2561  interleaved_index = c->packet_stream_index * 2;
2562  /* RTCP packets are sent at odd indexes */
2563  if (c->buffer_ptr[1] == 200)
2564  interleaved_index++;
2565  /* write RTSP TCP header */
2566  header[0] = '$';
2567  header[1] = interleaved_index;
2568  header[2] = len >> 8;
2569  header[3] = len;
2570  avio_write(pb, header, 4);
2571  /* write RTP packet data */
2572  c->buffer_ptr += 4;
2573  avio_write(pb, c->buffer_ptr, len);
2574  size = avio_close_dyn_buf(pb, &c->packet_buffer);
2575  /* prepare asynchronous TCP sending */
2576  rtsp_c->packet_buffer_ptr = c->packet_buffer;
2577  rtsp_c->packet_buffer_end = c->packet_buffer + size;
2578  c->buffer_ptr += len;
2579 
2580  /* send everything we can NOW */
2581  len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2582  rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2583  if (len > 0)
2584  rtsp_c->packet_buffer_ptr += len;
2585  if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2586  /* if we could not send all the data, we will
2587  send it later, so a new state is needed to
2588  "lock" the RTSP TCP connection */
2589  rtsp_c->state = RTSPSTATE_SEND_PACKET;
2590  break;
2591  } else
2592  /* all data has been sent */
2593  av_freep(&c->packet_buffer);
2594  } else {
2595  /* send RTP packet directly in UDP */
2596  c->buffer_ptr += 4;
2598  c->buffer_ptr, len);
2599  c->buffer_ptr += len;
2600  /* here we continue as we can send several packets per 10 ms slot */
2601  }
2602  } else {
2603  /* TCP data output */
2604  len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2605  if (len < 0) {
2606  if (ff_neterrno() != AVERROR(EAGAIN) &&
2607  ff_neterrno() != AVERROR(EINTR))
2608  /* error : close connection */
2609  return -1;
2610  else
2611  return 0;
2612  } else
2613  c->buffer_ptr += len;
2614 
2615  c->data_count += len;
2617  if (c->stream)
2618  c->stream->bytes_served += len;
2619  break;
2620  }
2621  }
2622  } /* for(;;) */
2623  return 0;
2624 }
2625 
2627 {
2628  int fd;
2629  int ret;
2630 
2631  if (c->stream->feed_opened) {
2632  http_log("Stream feed '%s' was not opened\n", c->stream->feed_filename);
2633  return AVERROR(EINVAL);
2634  }
2635 
2636  /* Don't permit writing to this one */
2637  if (c->stream->readonly) {
2638  http_log("Cannot write to read-only file '%s'\n", c->stream->feed_filename);
2639  return AVERROR(EINVAL);
2640  }
2641 
2642  /* open feed */
2643  fd = open(c->stream->feed_filename, O_RDWR);
2644  if (fd < 0) {
2645  ret = AVERROR(errno);
2646  http_log("Could not open feed file '%s': %s\n",
2647  c->stream->feed_filename, strerror(errno));
2648  return ret;
2649  }
2650  c->feed_fd = fd;
2651 
2652  if (c->stream->truncate) {
2653  /* truncate feed file */
2655  http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2656  if (ftruncate(c->feed_fd, FFM_PACKET_SIZE) < 0) {
2657  ret = AVERROR(errno);
2658  http_log("Error truncating feed file '%s': %s\n",
2659  c->stream->feed_filename, strerror(errno));
2660  return ret;
2661  }
2662  } else {
2663  ret = ffm_read_write_index(fd);
2664  if (ret < 0) {
2665  http_log("Error reading write index from feed file '%s': %s\n",
2666  c->stream->feed_filename, strerror(errno));
2667  return ret;
2668  } else {
2669  c->stream->feed_write_index = ret;
2670  }
2671  }
2672 
2674  c->stream->feed_size = lseek(fd, 0, SEEK_END);
2675  lseek(fd, 0, SEEK_SET);
2676 
2677  /* init buffer input */
2678  c->buffer_ptr = c->buffer;
2679  c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2680  c->stream->feed_opened = 1;
2681  c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2682  return 0;
2683 }
2684 
2686 {
2687  HTTPContext *c1;
2688  int len, loop_run = 0;
2689 
2690  while (c->chunked_encoding && !c->chunk_size &&
2691  c->buffer_end > c->buffer_ptr) {
2692  /* read chunk header, if present */
2693  len = recv(c->fd, c->buffer_ptr, 1, 0);
2694 
2695  if (len < 0) {
2696  if (ff_neterrno() != AVERROR(EAGAIN) &&
2697  ff_neterrno() != AVERROR(EINTR))
2698  /* error : close connection */
2699  goto fail;
2700  return 0;
2701  } else if (len == 0) {
2702  /* end of connection : close it */
2703  goto fail;
2704  } else if (c->buffer_ptr - c->buffer >= 2 &&
2705  !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2706  c->chunk_size = strtol(c->buffer, 0, 16);
2707  if (c->chunk_size == 0) // end of stream
2708  goto fail;
2709  c->buffer_ptr = c->buffer;
2710  break;
2711  } else if (++loop_run > 10) {
2712  /* no chunk header, abort */
2713  goto fail;
2714  } else {
2715  c->buffer_ptr++;
2716  }
2717  }
2718 
2719  if (c->buffer_end > c->buffer_ptr) {
2720  len = recv(c->fd, c->buffer_ptr,
2721  FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2722  if (len < 0) {
2723  if (ff_neterrno() != AVERROR(EAGAIN) &&
2724  ff_neterrno() != AVERROR(EINTR))
2725  /* error : close connection */
2726  goto fail;
2727  } else if (len == 0)
2728  /* end of connection : close it */
2729  goto fail;
2730  else {
2731  c->chunk_size -= len;
2732  c->buffer_ptr += len;
2733  c->data_count += len;
2735  }
2736  }
2737 
2738  if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2739  if (c->buffer[0] != 'f' ||
2740  c->buffer[1] != 'm') {
2741  http_log("Feed stream has become desynchronized -- disconnecting\n");
2742  goto fail;
2743  }
2744  }
2745 
2746  if (c->buffer_ptr >= c->buffer_end) {
2747  FFStream *feed = c->stream;
2748  /* a packet has been received : write it in the store, except
2749  if header */
2750  if (c->data_count > FFM_PACKET_SIZE) {
2751  /* XXX: use llseek or url_seek
2752  * XXX: Should probably fail? */
2753  if (lseek(c->feed_fd, feed->feed_write_index, SEEK_SET) == -1)
2754  http_log("Seek to %"PRId64" failed\n", feed->feed_write_index);
2755 
2756  if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2757  http_log("Error writing to feed file: %s\n", strerror(errno));
2758  goto fail;
2759  }
2760 
2762  /* update file size */
2763  if (feed->feed_write_index > c->stream->feed_size)
2764  feed->feed_size = feed->feed_write_index;
2765 
2766  /* handle wrap around if max file size reached */
2767  if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2769 
2770  /* write index */
2771  if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2772  http_log("Error writing index to feed file: %s\n", strerror(errno));
2773  goto fail;
2774  }
2775 
2776  /* wake up any waiting connections */
2777  for(c1 = first_http_ctx; c1; c1 = c1->next) {
2778  if (c1->state == HTTPSTATE_WAIT_FEED &&
2779  c1->stream->feed == c->stream->feed)
2780  c1->state = HTTPSTATE_SEND_DATA;
2781  }
2782  } else {
2783  /* We have a header in our hands that contains useful data */
2785  AVIOContext *pb;
2786  AVInputFormat *fmt_in;
2787  int i;
2788 
2789  if (!s)
2790  goto fail;
2791 
2792  /* use feed output format name to find corresponding input format */
2793  fmt_in = av_find_input_format(feed->fmt->name);
2794  if (!fmt_in)
2795  goto fail;
2796 
2797  pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
2798  0, NULL, NULL, NULL, NULL);
2799  pb->seekable = 0;
2800 
2801  s->pb = pb;
2802  if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) {
2803  av_free(pb);
2804  goto fail;
2805  }
2806 
2807  /* Now we have the actual streams */
2808  if (s->nb_streams != feed->nb_streams) {
2810  av_free(pb);
2811  http_log("Feed '%s' stream number does not match registered feed\n",
2812  c->stream->feed_filename);
2813  goto fail;
2814  }
2815 
2816  for (i = 0; i < s->nb_streams; i++) {
2817  AVStream *fst = feed->streams[i];
2818  AVStream *st = s->streams[i];
2819  avcodec_copy_context(fst->codec, st->codec);
2820  }
2821 
2823  av_free(pb);
2824  }
2825  c->buffer_ptr = c->buffer;
2826  }
2827 
2828  return 0;
2829  fail:
2830  c->stream->feed_opened = 0;
2831  close(c->feed_fd);
2832  /* wake up any waiting connections to stop waiting for feed */
2833  for(c1 = first_http_ctx; c1; c1 = c1->next) {
2834  if (c1->state == HTTPSTATE_WAIT_FEED &&
2835  c1->stream->feed == c->stream->feed)
2837  }
2838  return -1;
2839 }
2840 
2841 /********************************************************************/
2842 /* RTSP handling */
2843 
2844 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2845 {
2846  const char *str;
2847  time_t ti;
2848  struct tm *tm;
2849  char buf2[32];
2850 
2851  str = RTSP_STATUS_CODE2STRING(error_number);
2852  if (!str)
2853  str = "Unknown Error";
2854 
2855  avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2856  avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2857 
2858  /* output GMT time */
2859  ti = time(NULL);
2860  tm = gmtime(&ti);
2861  strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
2862  avio_printf(c->pb, "Date: %s GMT\r\n", buf2);
2863 }
2864 
2865 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2866 {
2867  rtsp_reply_header(c, error_number);
2868  avio_printf(c->pb, "\r\n");
2869 }
2870 
2872 {
2873  const char *p, *p1, *p2;
2874  char cmd[32];
2875  char url[1024];
2876  char protocol[32];
2877  char line[1024];
2878  int len;
2879  RTSPMessageHeader header1 = { 0 }, *header = &header1;
2880 
2881  c->buffer_ptr[0] = '\0';
2882  p = c->buffer;
2883 
2884  get_word(cmd, sizeof(cmd), &p);
2885  get_word(url, sizeof(url), &p);
2886  get_word(protocol, sizeof(protocol), &p);
2887 
2888  av_strlcpy(c->method, cmd, sizeof(c->method));
2889  av_strlcpy(c->url, url, sizeof(c->url));
2890  av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2891 
2892  if (avio_open_dyn_buf(&c->pb) < 0) {
2893  /* XXX: cannot do more */
2894  c->pb = NULL; /* safety */
2895  return -1;
2896  }
2897 
2898  /* check version name */
2899  if (strcmp(protocol, "RTSP/1.0") != 0) {
2901  goto the_end;
2902  }
2903 
2904  /* parse each header line */
2905  /* skip to next line */
2906  while (*p != '\n' && *p != '\0')
2907  p++;
2908  if (*p == '\n')
2909  p++;
2910  while (*p != '\0') {
2911  p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
2912  if (!p1)
2913  break;
2914  p2 = p1;
2915  if (p2 > p && p2[-1] == '\r')
2916  p2--;
2917  /* skip empty line */
2918  if (p2 == p)
2919  break;
2920  len = p2 - p;
2921  if (len > sizeof(line) - 1)
2922  len = sizeof(line) - 1;
2923  memcpy(line, p, len);
2924  line[len] = '\0';
2925  ff_rtsp_parse_line(header, line, NULL, NULL);
2926  p = p1 + 1;
2927  }
2928 
2929  /* handle sequence number */
2930  c->seq = header->seq;
2931 
2932  if (!strcmp(cmd, "DESCRIBE"))
2933  rtsp_cmd_describe(c, url);
2934  else if (!strcmp(cmd, "OPTIONS"))
2935  rtsp_cmd_options(c, url);
2936  else if (!strcmp(cmd, "SETUP"))
2937  rtsp_cmd_setup(c, url, header);
2938  else if (!strcmp(cmd, "PLAY"))
2939  rtsp_cmd_play(c, url, header);
2940  else if (!strcmp(cmd, "PAUSE"))
2941  rtsp_cmd_interrupt(c, url, header, 1);
2942  else if (!strcmp(cmd, "TEARDOWN"))
2943  rtsp_cmd_interrupt(c, url, header, 0);
2944  else
2946 
2947  the_end:
2948  len = avio_close_dyn_buf(c->pb, &c->pb_buffer);
2949  c->pb = NULL; /* safety */
2950  if (len < 0) {
2951  /* XXX: cannot do more */
2952  return -1;
2953  }
2954  c->buffer_ptr = c->pb_buffer;
2955  c->buffer_end = c->pb_buffer + len;
2957  return 0;
2958 }
2959 
2960 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2961  struct in_addr my_ip)
2962 {
2963  AVFormatContext *avc;
2964  AVStream *avs = NULL;
2965  AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);
2966  AVDictionaryEntry *entry = av_dict_get(stream->metadata, "title", NULL, 0);
2967  int i;
2968 
2969  *pbuffer = NULL;
2970 
2971  avc = avformat_alloc_context();
2972  if (!avc || !rtp_format) {
2973  return -1;
2974  }
2975  avc->oformat = rtp_format;
2976  av_dict_set(&avc->metadata, "title",
2977  entry ? entry->value : "No Title", 0);
2978  avc->nb_streams = stream->nb_streams;
2979  if (stream->is_multicast) {
2980  snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2981  inet_ntoa(stream->multicast_ip),
2982  stream->multicast_port, stream->multicast_ttl);
2983  } else {
2984  snprintf(avc->filename, 1024, "rtp://0.0.0.0");
2985  }
2986 
2987  if (avc->nb_streams >= INT_MAX/sizeof(*avc->streams) ||
2988  !(avc->streams = av_malloc(avc->nb_streams * sizeof(*avc->streams))))
2989  goto sdp_done;
2990  if (avc->nb_streams >= INT_MAX/sizeof(*avs) ||
2991  !(avs = av_malloc(avc->nb_streams * sizeof(*avs))))
2992  goto sdp_done;
2993 
2994  for(i = 0; i < stream->nb_streams; i++) {
2995  avc->streams[i] = &avs[i];
2996  avc->streams[i]->codec = stream->streams[i]->codec;
2997  }
2998  *pbuffer = av_mallocz(2048);
2999  av_sdp_create(&avc, 1, *pbuffer, 2048);
3000 
3001  sdp_done:
3002  av_free(avc->streams);
3003  av_dict_free(&avc->metadata);
3004  av_free(avc);
3005  av_free(avs);
3006 
3007  return *pbuffer ? strlen(*pbuffer) : AVERROR(ENOMEM);
3008 }
3009 
3010 static void rtsp_cmd_options(HTTPContext *c, const char *url)
3011 {
3012 // rtsp_reply_header(c, RTSP_STATUS_OK);
3013  avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
3014  avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
3015  avio_printf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
3016  avio_printf(c->pb, "\r\n");
3017 }
3018 
3019 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
3020 {
3021  FFStream *stream;
3022  char path1[1024];
3023  const char *path;
3024  uint8_t *content;
3025  int content_length;
3026  socklen_t len;
3027  struct sockaddr_in my_addr;
3028 
3029  /* find which URL is asked */
3030  av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3031  path = path1;
3032  if (*path == '/')
3033  path++;
3034 
3035  for(stream = first_stream; stream; stream = stream->next) {
3036  if (!stream->is_feed &&
3037  stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
3038  !strcmp(path, stream->filename)) {
3039  goto found;
3040  }
3041  }
3042  /* no stream found */
3044  return;
3045 
3046  found:
3047  /* prepare the media description in SDP format */
3048 
3049  /* get the host IP */
3050  len = sizeof(my_addr);
3051  getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
3052  content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
3053  if (content_length < 0) {
3055  return;
3056  }
3058  avio_printf(c->pb, "Content-Base: %s/\r\n", url);
3059  avio_printf(c->pb, "Content-Type: application/sdp\r\n");
3060  avio_printf(c->pb, "Content-Length: %d\r\n", content_length);
3061  avio_printf(c->pb, "\r\n");
3062  avio_write(c->pb, content, content_length);
3063  av_free(content);
3064 }
3065 
3066 static HTTPContext *find_rtp_session(const char *session_id)
3067 {
3068  HTTPContext *c;
3069 
3070  if (session_id[0] == '\0')
3071  return NULL;
3072 
3073  for(c = first_http_ctx; c; c = c->next) {
3074  if (!strcmp(c->session_id, session_id))
3075  return c;
3076  }
3077  return NULL;
3078 }
3079 
3081 {
3083  int i;
3084 
3085  for(i=0;i<h->nb_transports;i++) {
3086  th = &h->transports[i];
3087  if (th->lower_transport == lower_transport)
3088  return th;
3089  }
3090  return NULL;
3091 }
3092 
3093 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3094  RTSPMessageHeader *h)
3095 {
3096  FFStream *stream;
3097  int stream_index, rtp_port, rtcp_port;
3098  char buf[1024];
3099  char path1[1024];
3100  const char *path;
3101  HTTPContext *rtp_c;
3103  struct sockaddr_in dest_addr;
3104  RTSPActionServerSetup setup;
3105 
3106  /* find which URL is asked */
3107  av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3108  path = path1;
3109  if (*path == '/')
3110  path++;
3111 
3112  /* now check each stream */
3113  for(stream = first_stream; stream; stream = stream->next) {
3114  if (!stream->is_feed &&
3115  stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3116  /* accept aggregate filenames only if single stream */
3117  if (!strcmp(path, stream->filename)) {
3118  if (stream->nb_streams != 1) {
3120  return;
3121  }
3122  stream_index = 0;
3123  goto found;
3124  }
3125 
3126  for(stream_index = 0; stream_index < stream->nb_streams;
3127  stream_index++) {
3128  snprintf(buf, sizeof(buf), "%s/streamid=%d",
3129  stream->filename, stream_index);
3130  if (!strcmp(path, buf))
3131  goto found;
3132  }
3133  }
3134  }
3135  /* no stream found */
3136  rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3137  return;
3138  found:
3139 
3140  /* generate session id if needed */
3141  if (h->session_id[0] == '\0') {
3142  unsigned random0 = av_lfg_get(&random_state);
3143  unsigned random1 = av_lfg_get(&random_state);
3144  snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3145  random0, random1);
3146  }
3147 
3148  /* find RTP session, and create it if none found */
3149  rtp_c = find_rtp_session(h->session_id);
3150  if (!rtp_c) {
3151  /* always prefer UDP */
3153  if (!th) {
3155  if (!th) {
3157  return;
3158  }
3159  }
3160 
3161  rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3162  th->lower_transport);
3163  if (!rtp_c) {
3165  return;
3166  }
3167 
3168  /* open input stream */
3169  if (open_input_stream(rtp_c, "") < 0) {
3171  return;
3172  }
3173  }
3174 
3175  /* test if stream is OK (test needed because several SETUP needs
3176  to be done for a given file) */
3177  if (rtp_c->stream != stream) {
3179  return;
3180  }
3181 
3182  /* test if stream is already set up */
3183  if (rtp_c->rtp_ctx[stream_index]) {
3185  return;
3186  }
3187 
3188  /* check transport */
3189  th = find_transport(h, rtp_c->rtp_protocol);
3190  if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3191  th->client_port_min <= 0)) {
3193  return;
3194  }
3195 
3196  /* setup default options */
3197  setup.transport_option[0] = '\0';
3198  dest_addr = rtp_c->from_addr;
3199  dest_addr.sin_port = htons(th->client_port_min);
3200 
3201  /* setup stream */
3202  if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3204  return;
3205  }
3206 
3207  /* now everything is OK, so we can send the connection parameters */
3209  /* session ID */
3210  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3211 
3212  switch(rtp_c->rtp_protocol) {
3214  rtp_port = ff_rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3215  rtcp_port = ff_rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3216  avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3217  "client_port=%d-%d;server_port=%d-%d",
3219  rtp_port, rtcp_port);
3220  break;
3222  avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3223  stream_index * 2, stream_index * 2 + 1);
3224  break;
3225  default:
3226  break;
3227  }
3228  if (setup.transport_option[0] != '\0')
3229  avio_printf(c->pb, ";%s", setup.transport_option);
3230  avio_printf(c->pb, "\r\n");
3231 
3232 
3233  avio_printf(c->pb, "\r\n");
3234 }
3235 
3236 
3237 /* find an RTP connection by using the session ID. Check consistency
3238  with filename */
3239 static HTTPContext *find_rtp_session_with_url(const char *url,
3240  const char *session_id)
3241 {
3242  HTTPContext *rtp_c;
3243  char path1[1024];
3244  const char *path;
3245  char buf[1024];
3246  int s, len;
3247 
3248  rtp_c = find_rtp_session(session_id);
3249  if (!rtp_c)
3250  return NULL;
3251 
3252  /* find which URL is asked */
3253  av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3254  path = path1;
3255  if (*path == '/')
3256  path++;
3257  if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
3258  for(s=0; s<rtp_c->stream->nb_streams; ++s) {
3259  snprintf(buf, sizeof(buf), "%s/streamid=%d",
3260  rtp_c->stream->filename, s);
3261  if(!strncmp(path, buf, sizeof(buf))) {
3262  // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
3263  return rtp_c;
3264  }
3265  }
3266  len = strlen(path);
3267  if (len > 0 && path[len - 1] == '/' &&
3268  !strncmp(path, rtp_c->stream->filename, len - 1))
3269  return rtp_c;
3270  return NULL;
3271 }
3272 
3273 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3274 {
3275  HTTPContext *rtp_c;
3276 
3277  rtp_c = find_rtp_session_with_url(url, h->session_id);
3278  if (!rtp_c) {
3280  return;
3281  }
3282 
3283  if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3284  rtp_c->state != HTTPSTATE_WAIT_FEED &&
3285  rtp_c->state != HTTPSTATE_READY) {
3287  return;
3288  }
3289 
3290  rtp_c->state = HTTPSTATE_SEND_DATA;
3291 
3292  /* now everything is OK, so we can send the connection parameters */
3294  /* session ID */
3295  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3296  avio_printf(c->pb, "\r\n");
3297 }
3298 
3299 static void rtsp_cmd_interrupt(HTTPContext *c, const char *url, RTSPMessageHeader *h, int pause_only)
3300 {
3301  HTTPContext *rtp_c;
3302 
3303  rtp_c = find_rtp_session_with_url(url, h->session_id);
3304  if (!rtp_c) {
3306  return;
3307  }
3308 
3309  if (pause_only) {
3310  if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3311  rtp_c->state != HTTPSTATE_WAIT_FEED) {
3313  return;
3314  }
3315  rtp_c->state = HTTPSTATE_READY;
3316  rtp_c->first_pts = AV_NOPTS_VALUE;
3317  }
3318 
3319  /* now everything is OK, so we can send the connection parameters */
3321  /* session ID */
3322  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3323  avio_printf(c->pb, "\r\n");
3324 
3325  if (!pause_only)
3326  close_connection(rtp_c);
3327 }
3328 
3329 /********************************************************************/
3330 /* RTP handling */
3331 
3332 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3333  FFStream *stream, const char *session_id,
3334  enum RTSPLowerTransport rtp_protocol)
3335 {
3336  HTTPContext *c = NULL;
3337  const char *proto_str;
3338 
3339  /* XXX: should output a warning page when coming
3340  close to the connection limit */
3342  goto fail;
3343 
3344  /* add a new connection */
3345  c = av_mallocz(sizeof(HTTPContext));
3346  if (!c)
3347  goto fail;
3348 
3349  c->fd = -1;
3350  c->poll_entry = NULL;
3351  c->from_addr = *from_addr;
3353  c->buffer = av_malloc(c->buffer_size);
3354  if (!c->buffer)
3355  goto fail;
3356  nb_connections++;
3357  c->stream = stream;
3358  av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3359  c->state = HTTPSTATE_READY;
3360  c->is_packetized = 1;
3361  c->rtp_protocol = rtp_protocol;
3362 
3363  /* protocol is shown in statistics */
3364  switch(c->rtp_protocol) {
3366  proto_str = "MCAST";
3367  break;
3369  proto_str = "UDP";
3370  break;
3372  proto_str = "TCP";
3373  break;
3374  default:
3375  proto_str = "???";
3376  break;
3377  }
3378  av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3379  av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3380 
3381  current_bandwidth += stream->bandwidth;
3382 
3383  c->next = first_http_ctx;
3384  first_http_ctx = c;
3385  return c;
3386 
3387  fail:
3388  if (c) {
3389  av_free(c->buffer);
3390  av_free(c);
3391  }
3392  return NULL;
3393 }
3394 
3395 /* add a new RTP stream in an RTP connection (used in RTSP SETUP
3396  command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3397  used. */
3399  int stream_index, struct sockaddr_in *dest_addr,
3400  HTTPContext *rtsp_c)
3401 {
3402  AVFormatContext *ctx;
3403  AVStream *st;
3404  char *ipaddr;
3405  URLContext *h = NULL;
3406  uint8_t *dummy_buf;
3407  int max_packet_size;
3408 
3409  /* now we can open the relevant output stream */
3410  ctx = avformat_alloc_context();
3411  if (!ctx)
3412  return -1;
3413  ctx->oformat = av_guess_format("rtp", NULL, NULL);
3414 
3415  st = av_mallocz(sizeof(AVStream));
3416  if (!st)
3417  goto fail;
3418  ctx->nb_streams = 1;
3419  ctx->streams = av_mallocz_array(ctx->nb_streams, sizeof(AVStream *));
3420  if (!ctx->streams)
3421  goto fail;
3422  ctx->streams[0] = st;
3423 
3424  if (!c->stream->feed ||
3425  c->stream->feed == c->stream)
3426  memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3427  else
3428  memcpy(st,
3429  c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3430  sizeof(AVStream));
3431  st->priv_data = NULL;
3432 
3433  /* build destination RTP address */
3434  ipaddr = inet_ntoa(dest_addr->sin_addr);
3435 
3436  switch(c->rtp_protocol) {
3439  /* RTP/UDP case */
3440 
3441  /* XXX: also pass as parameter to function ? */
3442  if (c->stream->is_multicast) {
3443  int ttl;
3444  ttl = c->stream->multicast_ttl;
3445  if (!ttl)
3446  ttl = 16;
3447  snprintf(ctx->filename, sizeof(ctx->filename),
3448  "rtp://%s:%d?multicast=1&ttl=%d",
3449  ipaddr, ntohs(dest_addr->sin_port), ttl);
3450  } else {
3451  snprintf(ctx->filename, sizeof(ctx->filename),
3452  "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3453  }
3454 
3455  if (ffurl_open(&h, ctx->filename, AVIO_FLAG_WRITE, NULL, NULL) < 0)
3456  goto fail;
3457  c->rtp_handles[stream_index] = h;
3458  max_packet_size = h->max_packet_size;
3459  break;
3461  /* RTP/TCP case */
3462  c->rtsp_c = rtsp_c;
3463  max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3464  break;
3465  default:
3466  goto fail;
3467  }
3468 
3469  http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3470  ipaddr, ntohs(dest_addr->sin_port),
3471  c->stream->filename, stream_index, c->protocol);
3472 
3473  /* normally, no packets should be output here, but the packet size may
3474  * be checked */
3475  if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
3476  /* XXX: close stream */
3477  goto fail;
3478  }
3479  if (avformat_write_header(ctx, NULL) < 0) {
3480  fail:
3481  if (h)
3482  ffurl_close(h);
3483  av_free(st);
3484  av_free(ctx);
3485  return -1;
3486  }
3487  avio_close_dyn_buf(ctx->pb, &dummy_buf);
3488  av_free(dummy_buf);
3489 
3490  c->rtp_ctx[stream_index] = ctx;
3491  return 0;
3492 }
3493 
3494 /********************************************************************/
3495 /* ffserver initialization */
3496 
3497 static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int copy)
3498 {
3499  AVStream *fst;
3500 
3501  if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams))
3502  return NULL;
3503 
3504  fst = av_mallocz(sizeof(AVStream));
3505  if (!fst)
3506  return NULL;
3507  if (copy) {
3508  fst->codec = avcodec_alloc_context3(NULL);
3509  memcpy(fst->codec, codec, sizeof(AVCodecContext));
3510  if (codec->extradata_size) {
3512  memcpy(fst->codec->extradata, codec->extradata,
3513  codec->extradata_size);
3514  }
3515  } else {
3516  /* live streams must use the actual feed's codec since it may be
3517  * updated later to carry extradata needed by them.
3518  */
3519  fst->codec = codec;
3520  }
3521  fst->priv_data = av_mallocz(sizeof(FeedData));
3522  fst->index = stream->nb_streams;
3523  avpriv_set_pts_info(fst, 33, 1, 90000);
3525  stream->streams[stream->nb_streams++] = fst;
3526  return fst;
3527 }
3528 
3529 /* return the stream number in the feed */
3530 static int add_av_stream(FFStream *feed, AVStream *st)
3531 {
3532  AVStream *fst;
3533  AVCodecContext *av, *av1;
3534  int i;
3535 
3536  av = st->codec;
3537  for(i=0;i<feed->nb_streams;i++) {
3538  st = feed->streams[i];
3539  av1 = st->codec;
3540  if (av1->codec_id == av->codec_id &&
3541  av1->codec_type == av->codec_type &&
3542  av1->bit_rate == av->bit_rate) {
3543 
3544  switch(av->codec_type) {
3545  case AVMEDIA_TYPE_AUDIO:
3546  if (av1->channels == av->channels &&
3547  av1->sample_rate == av->sample_rate)
3548  return i;
3549  break;
3550  case AVMEDIA_TYPE_VIDEO:
3551  if (av1->width == av->width &&
3552  av1->height == av->height &&
3553  av1->time_base.den == av->time_base.den &&
3554  av1->time_base.num == av->time_base.num &&
3555  av1->gop_size == av->gop_size)
3556  return i;
3557  break;
3558  default:
3559  abort();
3560  }
3561  }
3562  }
3563 
3564  fst = add_av_stream1(feed, av, 0);
3565  if (!fst)
3566  return -1;
3567  return feed->nb_streams - 1;
3568 }
3569 
3570 static void remove_stream(FFStream *stream)
3571 {
3572  FFStream **ps;
3573  ps = &first_stream;
3574  while (*ps) {
3575  if (*ps == stream)
3576  *ps = (*ps)->next;
3577  else
3578  ps = &(*ps)->next;
3579  }
3580 }
3581 
3582 /* specific MPEG4 handling : we extract the raw parameters */
3584 {
3585  int mpeg4_count, i, size;
3586  AVPacket pkt;
3587  AVStream *st;
3588  const uint8_t *p;
3589 
3591 
3592  mpeg4_count = 0;
3593  for(i=0;i<infile->nb_streams;i++) {
3594  st = infile->streams[i];
3595  if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3596  st->codec->extradata_size == 0) {
3597  mpeg4_count++;
3598  }
3599  }
3600  if (!mpeg4_count)
3601  return;
3602 
3603  printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
3604  while (mpeg4_count > 0) {
3605  if (av_read_frame(infile, &pkt) < 0)
3606  break;
3607  st = infile->streams[pkt.stream_index];
3608  if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3609  st->codec->extradata_size == 0) {
3610  av_freep(&st->codec->extradata);
3611  /* fill extradata with the header */
3612  /* XXX: we make hard suppositions here ! */
3613  p = pkt.data;
3614  while (p < pkt.data + pkt.size - 4) {
3615  /* stop when vop header is found */
3616  if (p[0] == 0x00 && p[1] == 0x00 &&
3617  p[2] == 0x01 && p[3] == 0xb6) {
3618  size = p - pkt.data;
3619  // av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
3621  st->codec->extradata_size = size;
3622  memcpy(st->codec->extradata, pkt.data, size);
3623  break;
3624  }
3625  p++;
3626  }
3627  mpeg4_count--;
3628  }
3629  av_free_packet(&pkt);
3630  }
3631 }
3632 
3633 /* compute the needed AVStream for each file */
3634 static void build_file_streams(void)
3635 {
3636  FFStream *stream, *stream_next;
3637  int i, ret;
3638 
3639  /* gather all streams */
3640  for(stream = first_stream; stream; stream = stream_next) {
3641  AVFormatContext *infile = NULL;
3642  stream_next = stream->next;
3643  if (stream->stream_type == STREAM_TYPE_LIVE &&
3644  !stream->feed) {
3645  /* the stream comes from a file */
3646  /* try to open the file */
3647  /* open stream */
3648  if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3649  /* specific case : if transport stream output to RTP,
3650  we use a raw transport stream reader */
3651  av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0);
3652  }
3653 
3654  if (!stream->feed_filename[0]) {
3655  http_log("Unspecified feed file for stream '%s'\n", stream->filename);
3656  goto fail;
3657  }
3658 
3659  http_log("Opening feed file '%s' for stream '%s'\n", stream->feed_filename, stream->filename);
3660  if ((ret = avformat_open_input(&infile, stream->feed_filename, stream->ifmt, &stream->in_opts)) < 0) {
3661  http_log("Could not open '%s': %s\n", stream->feed_filename, av_err2str(ret));
3662  /* remove stream (no need to spend more time on it) */
3663  fail:
3664  remove_stream(stream);
3665  } else {
3666  /* find all the AVStreams inside and reference them in
3667  'stream' */
3668  if (avformat_find_stream_info(infile, NULL) < 0) {
3669  http_log("Could not find codec parameters from '%s'\n",
3670  stream->feed_filename);
3671  avformat_close_input(&infile);
3672  goto fail;
3673  }
3674  extract_mpeg4_header(infile);
3675 
3676  for(i=0;i<infile->nb_streams;i++)
3677  add_av_stream1(stream, infile->streams[i]->codec, 1);
3678 
3679  avformat_close_input(&infile);
3680  }
3681  }
3682  }
3683 }
3684 
3685 /* compute the needed AVStream for each feed */
3686 static void build_feed_streams(void)
3687 {
3688  FFStream *stream, *feed;
3689  int i;
3690 
3691  /* gather all streams */
3692  for(stream = first_stream; stream; stream = stream->next) {
3693  feed = stream->feed;
3694  if (feed) {
3695  if (stream->is_feed) {
3696  for(i=0;i<stream->nb_streams;i++)
3697  stream->feed_streams[i] = i;
3698  } else {
3699  /* we handle a stream coming from a feed */
3700  for(i=0;i<stream->nb_streams;i++)
3701  stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3702  }
3703  }
3704  }
3705 
3706  /* create feed files if needed */
3707  for(feed = first_feed; feed; feed = feed->next_feed) {
3708  int fd;
3709 
3710  if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) {
3711  /* See if it matches */
3712  AVFormatContext *s = NULL;
3713  int matches = 0;
3714 
3715  if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) >= 0) {
3716  /* set buffer size */
3718  /* Now see if it matches */
3719  if (s->nb_streams == feed->nb_streams) {
3720  matches = 1;
3721  for(i=0;i<s->nb_streams;i++) {
3722  AVStream *sf, *ss;
3723  sf = feed->streams[i];
3724  ss = s->streams[i];
3725 
3726  if (sf->index != ss->index ||
3727  sf->id != ss->id) {
3728  http_log("Index & Id do not match for stream %d (%s)\n",
3729  i, feed->feed_filename);
3730  matches = 0;
3731  } else {
3732  AVCodecContext *ccf, *ccs;
3733 
3734  ccf = sf->codec;
3735  ccs = ss->codec;
3736 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3737 
3739  http_log("Codecs do not match for stream %d\n", i);
3740  matches = 0;
3741  } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3742  http_log("Codec bitrates do not match for stream %d\n", i);
3743  matches = 0;
3744  } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
3745  if (CHECK_CODEC(time_base.den) ||
3746  CHECK_CODEC(time_base.num) ||
3747  CHECK_CODEC(width) ||
3748  CHECK_CODEC(height)) {
3749  http_log("Codec width, height and framerate do not match for stream %d\n", i);
3750  matches = 0;
3751  }
3752  } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
3753  if (CHECK_CODEC(sample_rate) ||
3754  CHECK_CODEC(channels) ||
3756  http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3757  matches = 0;
3758  }
3759  } else {
3760  http_log("Unknown codec type\n");
3761  matches = 0;
3762  }
3763  }
3764  if (!matches)
3765  break;
3766  }
3767  } else
3768  http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3769  feed->feed_filename, s->nb_streams, feed->nb_streams);
3770 
3772  } else
3773  http_log("Deleting feed file '%s' as it appears to be corrupt\n",
3774  feed->feed_filename);
3775 
3776  if (!matches) {
3777  if (feed->readonly) {
3778  http_log("Unable to delete feed file '%s' as it is marked readonly\n",
3779  feed->feed_filename);
3780  exit(1);
3781  }
3782  unlink(feed->feed_filename);
3783  }
3784  }
3785  if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) {
3787 
3788  if (feed->readonly) {
3789  http_log("Unable to create feed file '%s' as it is marked readonly\n",
3790  feed->feed_filename);
3791  exit(1);
3792  }
3793 
3794  /* only write the header of the ffm file */
3795  if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) {
3796  http_log("Could not open output feed file '%s'\n",
3797  feed->feed_filename);
3798  exit(1);
3799  }
3800  s->oformat = feed->fmt;
3801  s->nb_streams = feed->nb_streams;
3802  s->streams = feed->streams;
3803  if (avformat_write_header(s, NULL) < 0) {
3804  http_log("Container doesn't support the required parameters\n");
3805  exit(1);
3806  }
3807  /* XXX: need better API */
3808  av_freep(&s->priv_data);
3809  avio_close(s->pb);
3810  s->streams = NULL;
3811  s->nb_streams = 0;
3813  }
3814  /* get feed size and write index */
3815  fd = open(feed->feed_filename, O_RDONLY);
3816  if (fd < 0) {
3817  http_log("Could not open output feed file '%s'\n",
3818  feed->feed_filename);
3819  exit(1);
3820  }
3821 
3823  feed->feed_size = lseek(fd, 0, SEEK_END);
3824  /* ensure that we do not wrap before the end of file */
3825  if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3826  feed->feed_max_size = feed->feed_size;
3827 
3828  close(fd);
3829  }
3830 }
3831 
3832 /* compute the bandwidth used by each stream */
3833 static void compute_bandwidth(void)
3834 {
3835  unsigned bandwidth;
3836  int i;
3837  FFStream *stream;
3838 
3839  for(stream = first_stream; stream; stream = stream->next) {
3840  bandwidth = 0;
3841  for(i=0;i<stream->nb_streams;i++) {
3842  AVStream *st = stream->streams[i];
3843  switch(st->codec->codec_type) {
3844  case AVMEDIA_TYPE_AUDIO:
3845  case AVMEDIA_TYPE_VIDEO:
3846  bandwidth += st->codec->bit_rate;
3847  break;
3848  default:
3849  break;
3850  }
3851  }
3852  stream->bandwidth = (bandwidth + 999) / 1000;
3853  }
3854 }
3855 
3856 /* add a codec and set the default parameters */
3857 static void add_codec(FFStream *stream, AVCodecContext *av)
3858 {
3859  AVStream *st;
3860 
3861  if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams))
3862  return;
3863 
3864  /* compute default parameters */
3865  switch(av->codec_type) {
3866  case AVMEDIA_TYPE_AUDIO:
3867  if (av->bit_rate == 0)
3868  av->bit_rate = 64000;
3869  if (av->sample_rate == 0)
3870  av->sample_rate = 22050;
3871  if (av->channels == 0)
3872  av->channels = 1;
3873  break;
3874  case AVMEDIA_TYPE_VIDEO:
3875  if (av->bit_rate == 0)
3876  av->bit_rate = 64000;
3877  if (av->time_base.num == 0){
3878  av->time_base.den = 5;
3879  av->time_base.num = 1;
3880  }
3881  if (av->width == 0 || av->height == 0) {
3882  av->width = 160;
3883  av->height = 128;
3884  }
3885  /* Bitrate tolerance is less for streaming */
3886  if (av->bit_rate_tolerance == 0)
3887  av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
3888  (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
3889  if (av->qmin == 0)
3890  av->qmin = 3;
3891  if (av->qmax == 0)
3892  av->qmax = 31;
3893  if (av->max_qdiff == 0)
3894  av->max_qdiff = 3;
3895  av->qcompress = 0.5;
3896  av->qblur = 0.5;
3897 
3898  if (!av->nsse_weight)
3899  av->nsse_weight = 8;
3900 
3902  if (!av->me_method)
3903  av->me_method = ME_EPZS;
3904  av->rc_buffer_aggressivity = 1.0;
3905 
3906  if (!av->rc_eq)
3907  av->rc_eq = av_strdup("tex^qComp");
3908  if (!av->i_quant_factor)
3909  av->i_quant_factor = -0.8;
3910  if (!av->b_quant_factor)
3911  av->b_quant_factor = 1.25;
3912  if (!av->b_quant_offset)
3913  av->b_quant_offset = 1.25;
3914  if (!av->rc_max_rate)
3915  av->rc_max_rate = av->bit_rate * 2;
3916 
3917  if (av->rc_max_rate && !av->rc_buffer_size) {
3918  av->rc_buffer_size = av->rc_max_rate;
3919  }
3920 
3921 
3922  break;
3923  default:
3924  abort();
3925  }
3926 
3927  st = av_mallocz(sizeof(AVStream));
3928  if (!st)
3929  return;
3930  st->codec = avcodec_alloc_context3(NULL);
3931  stream->streams[stream->nb_streams++] = st;
3932  memcpy(st->codec, av, sizeof(AVCodecContext));
3933 }
3934 
3935 static enum AVCodecID opt_codec(const char *name, enum AVMediaType type)
3936 {
3937  AVCodec *codec = avcodec_find_encoder_by_name(name);
3938 
3939  if (!codec || codec->type != type)
3940  return AV_CODEC_ID_NONE;
3941  return codec->id;
3942 }
3943 
3944 static int ffserver_opt_default(const char *opt, const char *arg,
3945  AVCodecContext *avctx, int type)
3946 {
3947  int ret = 0;
3948  const AVOption *o = av_opt_find(avctx, opt, NULL, type, 0);
3949  if(o)
3950  ret = av_opt_set(avctx, opt, arg, 0);
3951  return ret;
3952 }
3953 
3954 static int ffserver_opt_preset(const char *arg,
3955  AVCodecContext *avctx, int type,
3956  enum AVCodecID *audio_id, enum AVCodecID *video_id)
3957 {
3958  FILE *f=NULL;
3959  char filename[1000], tmp[1000], tmp2[1000], line[1000];
3960  int ret = 0;
3961  AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
3962 
3963  if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
3964  codec ? codec->name : NULL))) {
3965  fprintf(stderr, "File for preset '%s' not found\n", arg);
3966  return 1;
3967  }
3968 
3969  while(!feof(f)){
3970  int e= fscanf(f, "%999[^\n]\n", line) - 1;
3971  if(line[0] == '#' && !e)
3972  continue;
3973  e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
3974  if(e){
3975  fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
3976  ret = 1;
3977  break;
3978  }
3979  if(!strcmp(tmp, "acodec")){
3980  *audio_id = opt_codec(tmp2, AVMEDIA_TYPE_AUDIO);
3981  }else if(!strcmp(tmp, "vcodec")){
3982  *video_id = opt_codec(tmp2, AVMEDIA_TYPE_VIDEO);
3983  }else if(!strcmp(tmp, "scodec")){
3984  /* opt_subtitle_codec(tmp2); */
3985  }else if(ffserver_opt_default(tmp, tmp2, avctx, type) < 0){
3986  fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
3987  ret = 1;
3988  break;
3989  }
3990  }
3991 
3992  fclose(f);
3993 
3994  return ret;
3995 }
3996 
3997 static AVOutputFormat *ffserver_guess_format(const char *short_name, const char *filename, const char *mime_type)
3998 {
3999  AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
4000 
4001  if (fmt) {
4002  AVOutputFormat *stream_fmt;
4003  char stream_format_name[64];
4004 
4005  snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
4006  stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
4007 
4008  if (stream_fmt)
4009  fmt = stream_fmt;
4010  }
4011 
4012  return fmt;
4013 }
4014 
4015 static void report_config_error(const char *filename, int line_num, int log_level, int *errors, const char *fmt, ...)
4016 {
4017  va_list vl;
4018  va_start(vl, fmt);
4019  av_log(NULL, log_level, "%s:%d: ", filename, line_num);
4020  av_vlog(NULL, log_level, fmt, vl);
4021  va_end(vl);
4022 
4023  (*errors)++;
4024 }
4025 
4026 static int parse_ffconfig(const char *filename)
4027 {
4028  FILE *f;
4029  char line[1024];
4030  char cmd[64];
4031  char arg[1024], arg2[1024];
4032  const char *p;
4033  int val, errors, warnings, line_num;
4034  FFStream **last_stream, *stream, *redirect;
4035  FFStream **last_feed, *feed, *s;
4036  AVCodecContext audio_enc, video_enc;
4037  enum AVCodecID audio_id, video_id;
4038  int ret = 0;
4039 
4040  f = fopen(filename, "r");
4041  if (!f) {
4042  ret = AVERROR(errno);
4043  av_log(NULL, AV_LOG_ERROR, "Could not open the configuration file '%s'\n", filename);
4044  return ret;
4045  }
4046 
4047  errors = warnings = 0;
4048  line_num = 0;
4049  first_stream = NULL;
4050  last_stream = &first_stream;
4051  first_feed = NULL;
4052  last_feed = &first_feed;
4053  stream = NULL;
4054  feed = NULL;
4055  redirect = NULL;
4056  audio_id = AV_CODEC_ID_NONE;
4057  video_id = AV_CODEC_ID_NONE;
4058 #define ERROR(...) report_config_error(filename, line_num, AV_LOG_ERROR, &errors, __VA_ARGS__)
4059 #define WARNING(...) report_config_error(filename, line_num, AV_LOG_WARNING, &warnings, __VA_ARGS__)
4060 
4061  for(;;) {
4062  if (fgets(line, sizeof(line), f) == NULL)
4063  break;
4064  line_num++;
4065  p = line;
4066  while (av_isspace(*p))
4067  p++;
4068  if (*p == '\0' || *p == '#')
4069  continue;
4070 
4071  get_arg(cmd, sizeof(cmd), &p);
4072 
4073  if (!av_strcasecmp(cmd, "Port") || !av_strcasecmp(cmd, "HTTPPort")) {
4074  if (!av_strcasecmp(cmd, "Port"))
4075  WARNING("Port option is deprecated, use HTTPPort instead\n");
4076  get_arg(arg, sizeof(arg), &p);
4077  val = atoi(arg);
4078  if (val < 1 || val > 65536) {
4079  ERROR("Invalid port: %s\n", arg);
4080  }
4081  if (val < 1024)
4082  WARNING("Trying to use IETF assigned system port: %d\n", val);
4083  my_http_addr.sin_port = htons(val);
4084  } else if (!av_strcasecmp(cmd, "HTTPBindAddress") || !av_strcasecmp(cmd, "BindAddress")) {
4085  if (!av_strcasecmp(cmd, "BindAddress"))
4086  WARNING("BindAddress option is deprecated, use HTTPBindAddress instead\n");
4087  get_arg(arg, sizeof(arg), &p);
4088  if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
4089  ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
4090  }
4091  } else if (!av_strcasecmp(cmd, "NoDaemon")) {
4092  WARNING("NoDaemon option has no effect, you should remove it\n");
4093  } else if (!av_strcasecmp(cmd, "RTSPPort")) {
4094  get_arg(arg, sizeof(arg), &p);
4095  val = atoi(arg);
4096  if (val < 1 || val > 65536) {
4097  ERROR("%s:%d: Invalid port: %s\n", arg);
4098  }
4099  my_rtsp_addr.sin_port = htons(atoi(arg));
4100  } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) {
4101  get_arg(arg, sizeof(arg), &p);
4102  if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
4103  ERROR("Invalid host/IP address: %s\n", arg);
4104  }
4105  } else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) {
4106  get_arg(arg, sizeof(arg), &p);
4107  val = atoi(arg);
4108  if (val < 1 || val > 65536) {
4109  ERROR("Invalid MaxHTTPConnections: %s\n", arg);
4110  }
4112  } else if (!av_strcasecmp(cmd, "MaxClients")) {
4113  get_arg(arg, sizeof(arg), &p);
4114  val = atoi(arg);
4115  if (val < 1 || val > nb_max_http_connections) {
4116  ERROR("Invalid MaxClients: %s\n", arg);
4117  } else {
4119  }
4120  } else if (!av_strcasecmp(cmd, "MaxBandwidth")) {
4121  int64_t llval;
4122  get_arg(arg, sizeof(arg), &p);
4123  llval = strtoll(arg, NULL, 10);
4124  if (llval < 10 || llval > 10000000) {
4125  ERROR("Invalid MaxBandwidth: %s\n", arg);
4126  } else
4127  max_bandwidth = llval;
4128  } else if (!av_strcasecmp(cmd, "CustomLog")) {
4129  if (!ffserver_debug)
4130  get_arg(logfilename, sizeof(logfilename), &p);
4131  } else if (!av_strcasecmp(cmd, "<Feed")) {
4132  /*********************************************/
4133  /* Feed related options */
4134  char *q;
4135  if (stream || feed) {
4136  ERROR("Already in a tag\n");
4137  } else {
4138  feed = av_mallocz(sizeof(FFStream));
4139  if (!feed) {
4140  ret = AVERROR(ENOMEM);
4141  goto end;
4142  }
4143  get_arg(feed->filename, sizeof(feed->filename), &p);
4144  q = strrchr(feed->filename, '>');
4145  if (*q)
4146  *q = '\0';
4147 
4148  for (s = first_feed; s; s = s->next) {
4149  if (!strcmp(feed->filename, s->filename)) {
4150  ERROR("Feed '%s' already registered\n", s->filename);
4151  }
4152  }
4153 
4154  feed->fmt = av_guess_format("ffm", NULL, NULL);
4155  /* default feed file */
4156  snprintf(feed->feed_filename, sizeof(feed->feed_filename),
4157  "/tmp/%s.ffm", feed->filename);
4158  feed->feed_max_size = 5 * 1024 * 1024;
4159  feed->is_feed = 1;
4160  feed->feed = feed; /* self feeding :-) */
4161 
4162  /* add in stream list */
4163  *last_stream = feed;
4164  last_stream = &feed->next;
4165  /* add in feed list */
4166  *last_feed = feed;
4167  last_feed = &feed->next_feed;
4168  }
4169  } else if (!av_strcasecmp(cmd, "Launch")) {
4170  if (feed) {
4171  int i;
4172 
4173  feed->child_argv = av_mallocz(64 * sizeof(char *));
4174  if (!feed->child_argv) {
4175  ret = AVERROR(ENOMEM);
4176  goto end;
4177  }
4178  for (i = 0; i < 62; i++) {
4179  get_arg(arg, sizeof(arg), &p);
4180  if (!arg[0])
4181  break;
4182 
4183  feed->child_argv[i] = av_strdup(arg);
4184  if (!feed->child_argv[i]) {
4185  ret = AVERROR(ENOMEM);
4186  goto end;
4187  }
4188  }
4189 
4190  feed->child_argv[i] =
4191  av_asprintf("http://%s:%d/%s",
4192  (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
4193  inet_ntoa(my_http_addr.sin_addr), ntohs(my_http_addr.sin_port),
4194  feed->filename);
4195  if (!feed->child_argv[i]) {
4196  ret = AVERROR(ENOMEM);
4197  goto end;
4198  }
4199  }
4200  } else if (!av_strcasecmp(cmd, "File") || !av_strcasecmp(cmd, "ReadOnlyFile")) {
4201  if (feed) {
4202  get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4203  feed->readonly = !av_strcasecmp(cmd, "ReadOnlyFile");
4204  } else if (stream) {
4205  get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4206  }
4207  } else if (!av_strcasecmp(cmd, "Truncate")) {
4208  if (feed) {
4209  get_arg(arg, sizeof(arg), &p);
4210  /* assume Truncate is true in case no argument is specified */
4211  if (!arg[0]) {
4212  feed->truncate = 1;
4213  } else {
4214  WARNING("Truncate N syntax in configuration file is deprecated, "
4215  "use Truncate alone with no arguments\n");
4216  feed->truncate = strtod(arg, NULL);
4217  }
4218  }
4219  } else if (!av_strcasecmp(cmd, "FileMaxSize")) {
4220  if (feed) {
4221  char *p1;
4222  double fsize;
4223 
4224  get_arg(arg, sizeof(arg), &p);
4225  p1 = arg;
4226  fsize = strtod(p1, &p1);
4227  switch(av_toupper(*p1)) {
4228  case 'K':
4229  fsize *= 1024;
4230  break;
4231  case 'M':
4232  fsize *= 1024 * 1024;
4233  break;
4234  case 'G':
4235  fsize *= 1024 * 1024 * 1024;
4236  break;
4237  }
4238  feed->feed_max_size = (int64_t)fsize;
4239  if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
4240  ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
4241  }
4242  }
4243  } else if (!av_strcasecmp(cmd, "</Feed>")) {
4244  if (!feed) {
4245  ERROR("No corresponding <Feed> for </Feed>\n");
4246  }
4247  feed = NULL;
4248  } else if (!av_strcasecmp(cmd, "<Stream")) {
4249  /*********************************************/
4250  /* Stream related options */
4251  char *q;
4252  if (stream || feed) {
4253  ERROR("Already in a tag\n");
4254  } else {
4255  FFStream *s;
4256  stream = av_mallocz(sizeof(FFStream));
4257  if (!stream) {
4258  ret = AVERROR(ENOMEM);
4259  goto end;
4260  }
4261  get_arg(stream->filename, sizeof(stream->filename), &p);
4262  q = strrchr(stream->filename, '>');
4263  if (q)
4264  *q = '\0';
4265 
4266  for (s = first_stream; s; s = s->next) {
4267  if (!strcmp(stream->filename, s->filename)) {
4268  ERROR("Stream '%s' already registered\n", s->filename);
4269  }
4270  }
4271 
4272  stream->fmt = ffserver_guess_format(NULL, stream->filename, NULL);
4273  avcodec_get_context_defaults3(&video_enc, NULL);
4274  avcodec_get_context_defaults3(&audio_enc, NULL);
4275 
4276  audio_id = AV_CODEC_ID_NONE;
4277  video_id = AV_CODEC_ID_NONE;
4278  if (stream->fmt) {
4279  audio_id = stream->fmt->audio_codec;
4280  video_id = stream->fmt->video_codec;
4281  }
4282 
4283  *last_stream = stream;
4284  last_stream = &stream->next;
4285  }
4286  } else if (!av_strcasecmp(cmd, "Feed")) {
4287  get_arg(arg, sizeof(arg), &p);
4288  if (stream) {
4289  FFStream *sfeed;
4290 
4291  sfeed = first_feed;
4292  while (sfeed) {
4293  if (!strcmp(sfeed->filename, arg))
4294  break;
4295  sfeed = sfeed->next_feed;
4296  }
4297  if (!sfeed)
4298  ERROR("Feed with name '%s' for stream '%s' is not defined\n", arg, stream->filename);
4299  else
4300  stream->feed = sfeed;
4301  }
4302  } else if (!av_strcasecmp(cmd, "Format")) {
4303  get_arg(arg, sizeof(arg), &p);
4304  if (stream) {
4305  if (!strcmp(arg, "status")) {
4306  stream->stream_type = STREAM_TYPE_STATUS;
4307  stream->fmt = NULL;
4308  } else {
4309  stream->stream_type = STREAM_TYPE_LIVE;
4310  /* JPEG cannot be used here, so use single frame MJPEG */
4311  if (!strcmp(arg, "jpeg"))
4312  strcpy(arg, "mjpeg");
4313  stream->fmt = ffserver_guess_format(arg, NULL, NULL);
4314  if (!stream->fmt) {
4315  ERROR("Unknown Format: %s\n", arg);
4316  }
4317  }
4318  if (stream->fmt) {
4319  audio_id = stream->fmt->audio_codec;
4320  video_id = stream->fmt->video_codec;
4321  }
4322  }
4323  } else if (!av_strcasecmp(cmd, "InputFormat")) {
4324  get_arg(arg, sizeof(arg), &p);
4325  if (stream) {
4326  stream->ifmt = av_find_input_format(arg);
4327  if (!stream->ifmt) {
4328  ERROR("Unknown input format: %s\n", arg);
4329  }
4330  }
4331  } else if (!av_strcasecmp(cmd, "FaviconURL")) {
4332  if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
4333  get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4334  } else {
4335  ERROR("FaviconURL only permitted for status streams\n");
4336  }
4337  } else if (!av_strcasecmp(cmd, "Author") ||
4338  !av_strcasecmp(cmd, "Comment") ||
4339  !av_strcasecmp(cmd, "Copyright") ||
4340  !av_strcasecmp(cmd, "Title")) {
4341  get_arg(arg, sizeof(arg), &p);
4342 
4343  if (stream) {
4344  char key[32];
4345  int i, ret;
4346 
4347  for (i = 0; i < strlen(cmd); i++)
4348  key[i] = av_tolower(cmd[i]);
4349  key[i] = 0;
4350  WARNING("'%s' option in configuration file is deprecated, "
4351  "use 'Metadata %s VALUE' instead\n", cmd, key);
4352  if ((ret = av_dict_set(&stream->metadata, key, arg, 0)) < 0) {
4353  ERROR("Could not set metadata '%s' to value '%s': %s\n",
4354  key, arg, av_err2str(ret));
4355  }
4356  }
4357  } else if (!av_strcasecmp(cmd, "Metadata")) {
4358  get_arg(arg, sizeof(arg), &p);
4359  get_arg(arg2, sizeof(arg2), &p);
4360  if (stream) {
4361  int ret;
4362  if ((ret = av_dict_set(&stream->metadata, arg, arg2, 0)) < 0) {
4363  ERROR("Could not set metadata '%s' to value '%s': %s\n",
4364  arg, arg2, av_err2str(ret));
4365  }
4366  }
4367  } else if (!av_strcasecmp(cmd, "Preroll")) {
4368  get_arg(arg, sizeof(arg), &p);
4369  if (stream)
4370  stream->prebuffer = atof(arg) * 1000;
4371  } else if (!av_strcasecmp(cmd, "StartSendOnKey")) {
4372  if (stream)
4373  stream->send_on_key = 1;
4374  } else if (!av_strcasecmp(cmd, "AudioCodec")) {
4375  get_arg(arg, sizeof(arg), &p);
4376  audio_id = opt_codec(arg, AVMEDIA_TYPE_AUDIO);
4377  if (audio_id == AV_CODEC_ID_NONE) {
4378  ERROR("Unknown AudioCodec: %s\n", arg);
4379  }
4380  } else if (!av_strcasecmp(cmd, "VideoCodec")) {
4381  get_arg(arg, sizeof(arg), &p);
4382  video_id = opt_codec(arg, AVMEDIA_TYPE_VIDEO);
4383  if (video_id == AV_CODEC_ID_NONE) {
4384  ERROR("Unknown VideoCodec: %s\n", arg);
4385  }
4386  } else if (!av_strcasecmp(cmd, "MaxTime")) {
4387  get_arg(arg, sizeof(arg), &p);
4388  if (stream)
4389  stream->max_time = atof(arg) * 1000;
4390  } else if (!av_strcasecmp(cmd, "AudioBitRate")) {
4391  get_arg(arg, sizeof(arg), &p);
4392  if (stream)
4393  audio_enc.bit_rate = lrintf(atof(arg) * 1000);
4394  } else if (!av_strcasecmp(cmd, "AudioChannels")) {
4395  get_arg(arg, sizeof(arg), &p);
4396  if (stream)
4397  audio_enc.channels = atoi(arg);
4398  } else if (!av_strcasecmp(cmd, "AudioSampleRate")) {
4399  get_arg(arg, sizeof(arg), &p);
4400  if (stream)
4401  audio_enc.sample_rate = atoi(arg);
4402  } else if (!av_strcasecmp(cmd, "VideoBitRateRange")) {
4403  if (stream) {
4404  int minrate, maxrate;
4405 
4406  get_arg(arg, sizeof(arg), &p);
4407 
4408  if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
4409  video_enc.rc_min_rate = minrate * 1000;
4410  video_enc.rc_max_rate = maxrate * 1000;
4411  } else {
4412  ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4413  }
4414  }
4415  } else if (!av_strcasecmp(cmd, "Debug")) {
4416  if (stream) {
4417  get_arg(arg, sizeof(arg), &p);
4418  video_enc.debug = strtol(arg,0,0);
4419  }
4420  } else if (!av_strcasecmp(cmd, "Strict")) {
4421  if (stream) {
4422  get_arg(arg, sizeof(arg), &p);
4423  video_enc.strict_std_compliance = atoi(arg);
4424  }
4425  } else if (!av_strcasecmp(cmd, "VideoBufferSize")) {
4426  if (stream) {
4427  get_arg(arg, sizeof(arg), &p);
4428  video_enc.rc_buffer_size = atoi(arg) * 8*1024;
4429  }
4430  } else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) {
4431  if (stream) {
4432  get_arg(arg, sizeof(arg), &p);
4433  video_enc.bit_rate_tolerance = atoi(arg) * 1000;
4434  }
4435  } else if (!av_strcasecmp(cmd, "VideoBitRate")) {
4436  get_arg(arg, sizeof(arg), &p);
4437  if (stream) {
4438  video_enc.bit_rate = atoi(arg) * 1000;
4439  }
4440  } else if (!av_strcasecmp(cmd, "VideoSize")) {
4441  get_arg(arg, sizeof(arg), &p);
4442  if (stream) {
4443  ret = av_parse_video_size(&video_enc.width, &video_enc.height, arg);
4444  if (ret < 0) {
4445  ERROR("Invalid video size '%s'\n", arg);
4446  } else {
4447  if ((video_enc.width % 16) != 0 ||
4448  (video_enc.height % 16) != 0) {
4449  ERROR("Image size must be a multiple of 16\n");
4450  }
4451  }
4452  }
4453  } else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
4454  get_arg(arg, sizeof(arg), &p);
4455  if (stream) {
4456  AVRational frame_rate;
4457  if (av_parse_video_rate(&frame_rate, arg) < 0) {
4458  ERROR("Incorrect frame rate: %s\n", arg);
4459  } else {
4460  video_enc.time_base.num = frame_rate.den;
4461  video_enc.time_base.den = frame_rate.num;
4462  }
4463  }
4464  } else if (!av_strcasecmp(cmd, "PixelFormat")) {
4465  get_arg(arg, sizeof(arg), &p);
4466  if (stream) {
4467  video_enc.pix_fmt = av_get_pix_fmt(arg);
4468  if (video_enc.pix_fmt == AV_PIX_FMT_NONE) {
4469  ERROR("Unknown pixel format: %s\n", arg);
4470  }
4471  }
4472  } else if (!av_strcasecmp(cmd, "VideoGopSize")) {
4473  get_arg(arg, sizeof(arg), &p);
4474  if (stream)
4475  video_enc.gop_size = atoi(arg);
4476  } else if (!av_strcasecmp(cmd, "VideoIntraOnly")) {
4477  if (stream)
4478  video_enc.gop_size = 1;
4479  } else if (!av_strcasecmp(cmd, "VideoHighQuality")) {
4480  if (stream)
4481  video_enc.mb_decision = FF_MB_DECISION_BITS;
4482  } else if (!av_strcasecmp(cmd, "Video4MotionVector")) {
4483  if (stream) {
4484  video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
4485  video_enc.flags |= CODEC_FLAG_4MV;
4486  }
4487  } else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
4488  !av_strcasecmp(cmd, "AVOptionAudio")) {
4489  AVCodecContext *avctx;
4490  int type;
4491  get_arg(arg, sizeof(arg), &p);
4492  get_arg(arg2, sizeof(arg2), &p);
4493  if (!av_strcasecmp(cmd, "AVOptionVideo")) {
4494  avctx = &video_enc;
4495  type = AV_OPT_FLAG_VIDEO_PARAM;
4496  } else {
4497  avctx = &audio_enc;
4498  type = AV_OPT_FLAG_AUDIO_PARAM;
4499  }
4500  if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
4501  ERROR("Error setting %s option to %s %s\n", cmd, arg, arg2);
4502  }
4503  } else if (!av_strcasecmp(cmd, "AVPresetVideo") ||
4504  !av_strcasecmp(cmd, "AVPresetAudio")) {
4505  AVCodecContext *avctx;
4506  int type;
4507  get_arg(arg, sizeof(arg), &p);
4508  if (!av_strcasecmp(cmd, "AVPresetVideo")) {
4509  avctx = &video_enc;
4510  video_enc.codec_id = video_id;
4511  type = AV_OPT_FLAG_VIDEO_PARAM;
4512  } else {
4513  avctx = &audio_enc;
4514  audio_enc.codec_id = audio_id;
4515  type = AV_OPT_FLAG_AUDIO_PARAM;
4516  }
4517  if (ffserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) {
4518  ERROR("AVPreset error: %s\n", arg);
4519  }
4520  } else if (!av_strcasecmp(cmd, "VideoTag")) {
4521  get_arg(arg, sizeof(arg), &p);
4522  if ((strlen(arg) == 4) && stream)
4523  video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
4524  } else if (!av_strcasecmp(cmd, "BitExact")) {
4525  if (stream)
4526  video_enc.flags |= CODEC_FLAG_BITEXACT;
4527  } else if (!av_strcasecmp(cmd, "DctFastint")) {
4528  if (stream)
4529  video_enc.dct_algo = FF_DCT_FASTINT;
4530  } else if (!av_strcasecmp(cmd, "IdctSimple")) {
4531  if (stream)
4532  video_enc.idct_algo = FF_IDCT_SIMPLE;
4533  } else if (!av_strcasecmp(cmd, "Qscale")) {
4534  get_arg(arg, sizeof(arg), &p);
4535  if (stream) {
4536  video_enc.flags |= CODEC_FLAG_QSCALE;
4537  video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
4538  }
4539  } else if (!av_strcasecmp(cmd, "VideoQDiff")) {
4540  get_arg(arg, sizeof(arg), &p);
4541  if (stream) {
4542  video_enc.max_qdiff = atoi(arg);
4543  if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
4544  ERROR("VideoQDiff out of range\n");
4545  }
4546  }
4547  } else if (!av_strcasecmp(cmd, "VideoQMax")) {
4548  get_arg(arg, sizeof(arg), &p);
4549  if (stream) {
4550  video_enc.qmax = atoi(arg);
4551  if (video_enc.qmax < 1 || video_enc.qmax > 31) {
4552  ERROR("VideoQMax out of range\n");
4553  }
4554  }
4555  } else if (!av_strcasecmp(cmd, "VideoQMin")) {
4556  get_arg(arg, sizeof(arg), &p);
4557  if (stream) {
4558  video_enc.qmin = atoi(arg);
4559  if (video_enc.qmin < 1 || video_enc.qmin > 31) {
4560  ERROR("VideoQMin out of range\n");
4561  }
4562  }
4563  } else if (!av_strcasecmp(cmd, "LumiMask")) {
4564  get_arg(arg, sizeof(arg), &p);
4565  if (stream)
4566  video_enc.lumi_masking = atof(arg);
4567  } else if (!av_strcasecmp(cmd, "DarkMask")) {
4568  get_arg(arg, sizeof(arg), &p);
4569  if (stream)
4570  video_enc.dark_masking = atof(arg);
4571  } else if (!av_strcasecmp(cmd, "NoVideo")) {
4572  video_id = AV_CODEC_ID_NONE;
4573  } else if (!av_strcasecmp(cmd, "NoAudio")) {
4574  audio_id = AV_CODEC_ID_NONE;
4575  } else if (!av_strcasecmp(cmd, "ACL")) {
4576  parse_acl_row(stream, feed, NULL, p, filename, line_num);
4577  } else if (!av_strcasecmp(cmd, "DynamicACL")) {
4578  if (stream) {
4579  get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p);
4580  }
4581  } else if (!av_strcasecmp(cmd, "RTSPOption")) {
4582  get_arg(arg, sizeof(arg), &p);
4583  if (stream) {
4584  av_freep(&stream->rtsp_option);
4585  stream->rtsp_option = av_strdup(arg);
4586  }
4587  } else if (!av_strcasecmp(cmd, "MulticastAddress")) {
4588  get_arg(arg, sizeof(arg), &p);
4589  if (stream) {
4590  if (resolve_host(&stream->multicast_ip, arg) != 0) {
4591  ERROR("Invalid host/IP address: %s\n", arg);
4592  }
4593  stream->is_multicast = 1;
4594  stream->loop = 1; /* default is looping */
4595  }
4596  } else if (!av_strcasecmp(cmd, "MulticastPort")) {
4597  get_arg(arg, sizeof(arg), &p);
4598  if (stream)
4599  stream->multicast_port = atoi(arg);
4600  } else if (!av_strcasecmp(cmd, "MulticastTTL")) {
4601  get_arg(arg, sizeof(arg), &p);
4602  if (stream)
4603  stream->multicast_ttl = atoi(arg);
4604  } else if (!av_strcasecmp(cmd, "NoLoop")) {
4605  if (stream)
4606  stream->loop = 0;
4607  } else if (!av_strcasecmp(cmd, "</Stream>")) {
4608  if (!stream) {
4609  ERROR("No corresponding <Stream> for </Stream>\n");
4610  } else {
4611  if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
4612  if (audio_id != AV_CODEC_ID_NONE) {
4613  audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
4614  audio_enc.codec_id = audio_id;
4615  add_codec(stream, &audio_enc);
4616  }
4617  if (video_id != AV_CODEC_ID_NONE) {
4618  video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
4619  video_enc.codec_id = video_id;
4620  add_codec(stream, &video_enc);
4621  }
4622  }
4623  stream = NULL;
4624  }
4625  } else if (!av_strcasecmp(cmd, "<Redirect")) {
4626  /*********************************************/
4627  char *q;
4628  if (stream || feed || redirect) {
4629  ERROR("Already in a tag\n");
4630  } else {
4631  redirect = av_mallocz(sizeof(FFStream));
4632  if (!redirect) {
4633  ret = AVERROR(ENOMEM);
4634  goto end;
4635  }
4636  *last_stream = redirect;
4637  last_stream = &redirect->next;
4638 
4639  get_arg(redirect->filename, sizeof(redirect->filename), &p);
4640  q = strrchr(redirect->filename, '>');
4641  if (*q)
4642  *q = '\0';
4643  redirect->stream_type = STREAM_TYPE_REDIRECT;
4644  }
4645  } else if (!av_strcasecmp(cmd, "URL")) {
4646  if (redirect)
4647  get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
4648  } else if (!av_strcasecmp(cmd, "</Redirect>")) {
4649  if (!redirect) {
4650  ERROR("No corresponding <Redirect> for </Redirect>\n");
4651  } else {
4652  if (!redirect->feed_filename[0]) {
4653  ERROR("No URL found for <Redirect>\n");
4654  }
4655  redirect = NULL;
4656  }
4657  } else if (!av_strcasecmp(cmd, "LoadModule")) {
4658  ERROR("Loadable modules no longer supported\n");
4659  } else {
4660  ERROR("Incorrect keyword: '%s'\n", cmd);
4661  }
4662  }
4663 #undef ERROR
4664 
4665 end:
4666  fclose(f);
4667  if (ret < 0)
4668  return ret;
4669  if (errors)
4670  return AVERROR(EINVAL);
4671  else
4672  return 0;
4673 }
4674 
4675 static void handle_child_exit(int sig)
4676 {
4677  pid_t pid;
4678  int status;
4679 
4680  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4681  FFStream *feed;
4682 
4683  for (feed = first_feed; feed; feed = feed->next) {
4684  if (feed->pid == pid) {
4685  int uptime = time(0) - feed->pid_start;
4686 
4687  feed->pid = 0;
4688  fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
4689 
4690  if (uptime < 30)
4691  /* Turn off any more restarts */
4692  feed->child_argv = 0;
4693  }
4694  }
4695  }
4696 
4698 }
4699 
4700 static void opt_debug(void)
4701 {
4702  ffserver_debug = 1;
4703  logfilename[0] = '-';
4704 }
4705 
4706 void show_help_default(const char *opt, const char *arg)
4707 {
4708  printf("usage: ffserver [options]\n"
4709  "Hyper fast multi format Audio/Video streaming server\n");
4710  printf("\n");
4711  show_help_options(options, "Main options:", 0, 0, 0);
4712 }
4713 
4714 static const OptionDef options[] = {
4715 #include "cmdutils_common_opts.h"
4716  { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
4717  { "d", 0, {(void*)opt_debug}, "enable debug mode" },
4718  { "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/ffserver.conf", "configfile" },
4719  { NULL },
4720 };
4721 
4722 int main(int argc, char **argv)
4723 {
4724  struct sigaction sigact = { { 0 } };
4725  int ret = 0;
4726 
4727  config_filename = av_strdup("/etc/ffserver.conf");
4728 
4729  parse_loglevel(argc, argv, options);
4730  av_register_all();
4732 
4733  show_banner(argc, argv, options);
4734 
4735  my_program_name = argv[0];
4736 
4737  parse_options(NULL, argc, argv, options, NULL);
4738 
4739  unsetenv("http_proxy"); /* Kill the http_proxy */
4740 
4741  av_lfg_init(&random_state, av_get_random_seed());
4742 
4743  sigact.sa_handler = handle_child_exit;
4744  sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4745  sigaction(SIGCHLD, &sigact, 0);
4746 
4747  if ((ret = parse_ffconfig(config_filename)) < 0) {
4748  fprintf(stderr, "Error reading configuration file '%s': %s\n",
4749  config_filename, av_err2str(ret));
4750  exit(1);
4751  }
4753 
4754  /* open log file if needed */
4755  if (logfilename[0] != '\0') {
4756  if (!strcmp(logfilename, "-"))
4757  logfile = stdout;
4758  else
4759  logfile = fopen(logfilename, "a");
4761  }
4762 
4764 
4766 
4768 
4769  /* signal init */
4770  signal(SIGPIPE, SIG_IGN);
4771 
4772  if (http_server() < 0) {
4773  http_log("Could not start server\n");
4774  exit(1);
4775  }
4776 
4777  return 0;
4778 }