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