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