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/random_seed.h"
53 #include "libavutil/parseutils.h"
54 #include "libavutil/opt.h"
55 #include "libavutil/time.h"
56 
57 #include <stdarg.h>
58 #if HAVE_UNISTD_H
59 #include <unistd.h>
60 #endif
61 #include <fcntl.h>
62 #include <sys/ioctl.h>
63 #if HAVE_POLL_H
64 #include <poll.h>
65 #endif
66 #include <errno.h>
67 #include <time.h>
68 #include <sys/wait.h>
69 #include <signal.h>
70 
71 #include "cmdutils.h"
72 #include "ffserver_config.h"
73 
74 #define PATH_LENGTH 1024
75 
76 const char program_name[] = "ffserver";
77 const int program_birth_year = 2000;
78 
79 static const OptionDef options[];
80 
81 enum HTTPState {
85  HTTPSTATE_SEND_DATA, /* sending TCP or UDP data */
88  HTTPSTATE_WAIT_FEED, /* wait for data from the feed */
90 
94 };
95 
96 static const char * const http_state[] = {
97  "HTTP_WAIT_REQUEST",
98  "HTTP_SEND_HEADER",
99 
100  "SEND_DATA_HEADER",
101  "SEND_DATA",
102  "SEND_DATA_TRAILER",
103  "RECEIVE_DATA",
104  "WAIT_FEED",
105  "READY",
106 
107  "RTSP_WAIT_REQUEST",
108  "RTSP_SEND_REPLY",
109  "RTSP_SEND_PACKET",
110 };
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 */
160  /* -1 is invalid stream */
161  int feed_streams[FFSERVER_MAX_STREAMS]; /* index of streams in the feed */
162  int switch_feed_streams[FFSERVER_MAX_STREAMS]; /* index of streams in the feed */
164  AVFormatContext fmt_ctx; /* instance of FFServerStream 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 typedef struct FeedData {
196  long long data_count;
197  float avg_frame_size; /* frame size averaged over last frames with exponential mean */
198 } FeedData;
199 
201 
203  .nb_max_http_connections = 2000,
204  .nb_max_connections = 5,
205  .max_bandwidth = 1000,
206  .use_defaults = 1,
207 };
208 
209 static void new_connection(int server_fd, int is_rtsp);
210 static void close_connection(HTTPContext *c);
211 
212 /* HTTP handling */
213 static int handle_connection(HTTPContext *c);
214 static inline void print_stream_params(AVIOContext *pb, FFServerStream *stream);
215 static void compute_status(HTTPContext *c);
216 static int open_input_stream(HTTPContext *c, const char *info);
217 static int http_parse_request(HTTPContext *c);
218 static int http_send_data(HTTPContext *c);
220 static int http_receive_data(HTTPContext *c);
221 
222 /* RTSP handling */
223 static int rtsp_parse_request(HTTPContext *c);
224 static void rtsp_cmd_describe(HTTPContext *c, const char *url);
225 static void rtsp_cmd_options(HTTPContext *c, const char *url);
226 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
228 static void rtsp_cmd_play(HTTPContext *c, const char *url,
230 static void rtsp_cmd_interrupt(HTTPContext *c, const char *url,
231  RTSPMessageHeader *h, int pause_only);
232 
233 /* SDP handling */
234 static int prepare_sdp_description(FFServerStream *stream, uint8_t **pbuffer,
235  struct in_addr my_ip);
236 
237 /* RTP handling */
238 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
239  FFServerStream *stream,
240  const char *session_id,
241  enum RTSPLowerTransport rtp_protocol);
242 static int rtp_new_av_stream(HTTPContext *c,
243  int stream_index, struct sockaddr_in *dest_addr,
244  HTTPContext *rtsp_c);
245 /* utils */
246 static size_t htmlencode (const char *src, char **dest);
247 static inline void cp_html_entity (char *buffer, const char *entity);
248 static inline int check_codec_match(AVCodecContext *ccf, AVCodecContext *ccs,
249  int stream);
250 
251 static const char *my_program_name;
252 
253 static int no_launch;
255 
256 /* maximum number of simultaneous HTTP connections */
257 static unsigned int nb_connections;
258 
259 static uint64_t current_bandwidth;
260 
261 /* Making this global saves on passing it around everywhere */
262 static int64_t cur_time;
263 
265 
266 static FILE *logfile = NULL;
267 
268 static inline void cp_html_entity (char *buffer, const char *entity) {
269  if (!buffer || !entity)
270  return;
271  while (*entity)
272  *buffer++ = *entity++;
273 }
274 
275 /**
276  * Substitutes known conflicting chars on a text string with
277  * their corresponding HTML entities.
278  *
279  * Returns the number of bytes in the 'encoded' representation
280  * not including the terminating NUL.
281  */
282 static size_t htmlencode (const char *src, char **dest) {
283  const char *amp = "&amp;";
284  const char *lt = "&lt;";
285  const char *gt = "&gt;";
286  const char *start;
287  char *tmp;
288  size_t final_size = 0;
289 
290  if (!src)
291  return 0;
292 
293  start = src;
294 
295  /* Compute needed dest size */
296  while (*src != '\0') {
297  switch(*src) {
298  case 38: /* & */
299  final_size += 5;
300  break;
301  case 60: /* < */
302  case 62: /* > */
303  final_size += 4;
304  break;
305  default:
306  final_size++;
307  }
308  src++;
309  }
310 
311  src = start;
312  *dest = av_mallocz(final_size + 1);
313  if (!*dest)
314  return 0;
315 
316  /* Build dest */
317  tmp = *dest;
318  while (*src != '\0') {
319  switch(*src) {
320  case 38: /* & */
321  cp_html_entity (tmp, amp);
322  tmp += 5;
323  break;
324  case 60: /* < */
325  cp_html_entity (tmp, lt);
326  tmp += 4;
327  break;
328  case 62: /* > */
329  cp_html_entity (tmp, gt);
330  tmp += 4;
331  break;
332  default:
333  *tmp = *src;
334  tmp += 1;
335  }
336  src++;
337  }
338  *tmp = '\0';
339 
340  return final_size;
341 }
342 
343 static int64_t ffm_read_write_index(int fd)
344 {
345  uint8_t buf[8];
346 
347  if (lseek(fd, 8, SEEK_SET) < 0)
348  return AVERROR(EIO);
349  if (read(fd, buf, 8) != 8)
350  return AVERROR(EIO);
351  return AV_RB64(buf);
352 }
353 
354 static int ffm_write_write_index(int fd, int64_t pos)
355 {
356  uint8_t buf[8];
357  int i;
358 
359  for(i=0;i<8;i++)
360  buf[i] = (pos >> (56 - i * 8)) & 0xff;
361  if (lseek(fd, 8, SEEK_SET) < 0)
362  goto bail_eio;
363  if (write(fd, buf, 8) != 8)
364  goto bail_eio;
365 
366  return 8;
367 
368 bail_eio:
369  return AVERROR(EIO);
370 }
371 
372 static void ffm_set_write_index(AVFormatContext *s, int64_t pos,
373  int64_t file_size)
374 {
375  av_opt_set_int(s, "server_attached", 1, AV_OPT_SEARCH_CHILDREN);
376  av_opt_set_int(s, "ffm_write_index", pos, AV_OPT_SEARCH_CHILDREN);
377  av_opt_set_int(s, "ffm_file_size", file_size, AV_OPT_SEARCH_CHILDREN);
378 }
379 
380 static char *ctime1(char *buf2, size_t buf_size)
381 {
382  time_t ti;
383  char *p;
384 
385  ti = time(NULL);
386  p = ctime(&ti);
387  if (!p || !*p) {
388  *buf2 = '\0';
389  return buf2;
390  }
391  av_strlcpy(buf2, p, buf_size);
392  p = buf2 + strlen(buf2) - 1;
393  if (*p == '\n')
394  *p = '\0';
395  return buf2;
396 }
397 
398 static void http_vlog(const char *fmt, va_list vargs)
399 {
400  static int print_prefix = 1;
401  char buf[32];
402 
403  if (!logfile)
404  return;
405 
406  if (print_prefix) {
407  ctime1(buf, sizeof(buf));
408  fprintf(logfile, "%s ", buf);
409  }
410  print_prefix = strstr(fmt, "\n") != NULL;
411  vfprintf(logfile, fmt, vargs);
412  fflush(logfile);
413 }
414 
415 #ifdef __GNUC__
416 __attribute__ ((format (printf, 1, 2)))
417 #endif
418 static void http_log(const char *fmt, ...)
419 {
420  va_list vargs;
421  va_start(vargs, fmt);
422  http_vlog(fmt, vargs);
423  va_end(vargs);
424 }
425 
426 static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
427 {
428  static int print_prefix = 1;
429  AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
430  if (level > av_log_get_level())
431  return;
432  if (print_prefix && avc)
433  http_log("[%s @ %p]", avc->item_name(ptr), ptr);
434  print_prefix = strstr(fmt, "\n") != NULL;
435  http_vlog(fmt, vargs);
436 }
437 
439 {
440  if (c->suppress_log)
441  return;
442 
443  http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
444  inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
445  c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
446 }
447 
448 static void update_datarate(DataRateData *drd, int64_t count)
449 {
450  if (!drd->time1 && !drd->count1) {
451  drd->time1 = drd->time2 = cur_time;
452  drd->count1 = drd->count2 = count;
453  } else if (cur_time - drd->time2 > 5000) {
454  drd->time1 = drd->time2;
455  drd->count1 = drd->count2;
456  drd->time2 = cur_time;
457  drd->count2 = count;
458  }
459 }
460 
461 /* In bytes per second */
462 static int compute_datarate(DataRateData *drd, int64_t count)
463 {
464  if (cur_time == drd->time1)
465  return 0;
466 
467  return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
468 }
469 
470 
471 static void start_children(FFServerStream *feed)
472 {
473  char *pathname;
474  char *slash;
475  int i;
476  size_t cmd_length;
477 
478  if (no_launch)
479  return;
480 
481  cmd_length = strlen(my_program_name);
482 
483  /**
484  * FIXME: WIP Safeguard. Remove after clearing all harcoded
485  * '1024' path lengths
486  */
487  if (cmd_length > PATH_LENGTH - 1) {
488  http_log("Could not start children. Command line: '%s' exceeds "
489  "path length limit (%d)\n", my_program_name, PATH_LENGTH);
490  return;
491  }
492 
493  pathname = av_strdup (my_program_name);
494  if (!pathname) {
495  http_log("Could not allocate memory for children cmd line\n");
496  return;
497  }
498  /* replace "ffserver" with "ffmpeg" in the path of current
499  * program. Ignore user provided path */
500 
501  slash = strrchr(pathname, '/');
502  if (!slash)
503  slash = pathname;
504  else
505  slash++;
506  strcpy(slash, "ffmpeg");
507 
508  for (; feed; feed = feed->next) {
509 
510  if (!feed->child_argv || feed->pid)
511  continue;
512 
513  feed->pid_start = time(0);
514 
515  feed->pid = fork();
516  if (feed->pid < 0) {
517  http_log("Unable to create children: %s\n", strerror(errno));
518  av_free (pathname);
519  exit(EXIT_FAILURE);
520  }
521 
522  if (feed->pid)
523  continue;
524 
525  /* In child */
526 
527  http_log("Launch command line: ");
528  http_log("%s ", pathname);
529 
530  for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
531  http_log("%s ", feed->child_argv[i]);
532  http_log("\n");
533 
534  for (i = 3; i < 256; i++)
535  close(i);
536 
537  if (!config.debug) {
538  if (!freopen("/dev/null", "r", stdin))
539  http_log("failed to redirect STDIN to /dev/null\n;");
540  if (!freopen("/dev/null", "w", stdout))
541  http_log("failed to redirect STDOUT to /dev/null\n;");
542  if (!freopen("/dev/null", "w", stderr))
543  http_log("failed to redirect STDERR to /dev/null\n;");
544  }
545 
546  signal(SIGPIPE, SIG_DFL);
547  execvp(pathname, feed->child_argv);
548  av_free (pathname);
549  _exit(1);
550  }
551  av_free (pathname);
552 }
553 
554 /* open a listening socket */
555 static int socket_open_listen(struct sockaddr_in *my_addr)
556 {
557  int server_fd, tmp;
558 
559  server_fd = socket(AF_INET,SOCK_STREAM,0);
560  if (server_fd < 0) {
561  perror ("socket");
562  return -1;
563  }
564 
565  tmp = 1;
566  if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp)))
567  av_log(NULL, AV_LOG_WARNING, "setsockopt SO_REUSEADDR failed\n");
568 
569  my_addr->sin_family = AF_INET;
570  if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
571  char bindmsg[32];
572  snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)",
573  ntohs(my_addr->sin_port));
574  perror (bindmsg);
575  goto fail;
576  }
577 
578  if (listen (server_fd, 5) < 0) {
579  perror ("listen");
580  goto fail;
581  }
582 
583  if (ff_socket_nonblock(server_fd, 1) < 0)
584  av_log(NULL, AV_LOG_WARNING, "ff_socket_nonblock failed\n");
585 
586  return server_fd;
587 
588 fail:
589  closesocket(server_fd);
590  return -1;
591 }
592 
593 /* start all multicast streams */
594 static void start_multicast(void)
595 {
596  FFServerStream *stream;
597  char session_id[32];
598  HTTPContext *rtp_c;
599  struct sockaddr_in dest_addr = {0};
600  int default_port, stream_index;
601  unsigned int random0, random1;
602 
603  default_port = 6000;
604  for(stream = config.first_stream; stream; stream = stream->next) {
605 
606  if (!stream->is_multicast)
607  continue;
608 
609  random0 = av_lfg_get(&random_state);
610  random1 = av_lfg_get(&random_state);
611 
612  /* open the RTP connection */
613  snprintf(session_id, sizeof(session_id), "%08x%08x", random0, random1);
614 
615  /* choose a port if none given */
616  if (stream->multicast_port == 0) {
617  stream->multicast_port = default_port;
618  default_port += 100;
619  }
620 
621  dest_addr.sin_family = AF_INET;
622  dest_addr.sin_addr = stream->multicast_ip;
623  dest_addr.sin_port = htons(stream->multicast_port);
624 
625  rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
627  if (!rtp_c)
628  continue;
629 
630  if (open_input_stream(rtp_c, "") < 0) {
631  http_log("Could not open input stream for stream '%s'\n",
632  stream->filename);
633  continue;
634  }
635 
636  /* open each RTP stream */
637  for(stream_index = 0; stream_index < stream->nb_streams;
638  stream_index++) {
639  dest_addr.sin_port = htons(stream->multicast_port +
640  2 * stream_index);
641  if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) >= 0)
642  continue;
643 
644  http_log("Could not open output stream '%s/streamid=%d'\n",
645  stream->filename, stream_index);
646  exit(1);
647  }
648 
649  rtp_c->state = HTTPSTATE_SEND_DATA;
650  }
651 }
652 
653 /* main loop of the HTTP server */
654 static int http_server(void)
655 {
656  int server_fd = 0, rtsp_server_fd = 0;
657  int ret, delay;
658  struct pollfd *poll_table, *poll_entry;
659  HTTPContext *c, *c_next;
660 
661  poll_table = av_mallocz_array(config.nb_max_http_connections + 2,
662  sizeof(*poll_table));
663  if(!poll_table) {
664  http_log("Impossible to allocate a poll table handling %d "
665  "connections.\n", config.nb_max_http_connections);
666  return -1;
667  }
668 
669  if (config.http_addr.sin_port) {
670  server_fd = socket_open_listen(&config.http_addr);
671  if (server_fd < 0)
672  goto quit;
673  }
674 
675  if (config.rtsp_addr.sin_port) {
676  rtsp_server_fd = socket_open_listen(&config.rtsp_addr);
677  if (rtsp_server_fd < 0) {
678  closesocket(server_fd);
679  goto quit;
680  }
681  }
682 
683  if (!rtsp_server_fd && !server_fd) {
684  http_log("HTTP and RTSP disabled.\n");
685  goto quit;
686  }
687 
688  http_log("FFserver started.\n");
689 
690  start_children(config.first_feed);
691 
692  start_multicast();
693 
694  for(;;) {
695  poll_entry = poll_table;
696  if (server_fd) {
697  poll_entry->fd = server_fd;
698  poll_entry->events = POLLIN;
699  poll_entry++;
700  }
701  if (rtsp_server_fd) {
702  poll_entry->fd = rtsp_server_fd;
703  poll_entry->events = POLLIN;
704  poll_entry++;
705  }
706 
707  /* wait for events on each HTTP handle */
708  c = first_http_ctx;
709  delay = 1000;
710  while (c) {
711  int fd;
712  fd = c->fd;
713  switch(c->state) {
717  c->poll_entry = poll_entry;
718  poll_entry->fd = fd;
719  poll_entry->events = POLLOUT;
720  poll_entry++;
721  break;
723  case HTTPSTATE_SEND_DATA:
725  if (!c->is_packetized) {
726  /* for TCP, we output as much as we can
727  * (may need to put a limit) */
728  c->poll_entry = poll_entry;
729  poll_entry->fd = fd;
730  poll_entry->events = POLLOUT;
731  poll_entry++;
732  } else {
733  /* when ffserver is doing the timing, we work by
734  * looking at which packet needs to be sent every
735  * 10 ms (one tick wait XXX: 10 ms assumed) */
736  if (delay > 10)
737  delay = 10;
738  }
739  break;
742  case HTTPSTATE_WAIT_FEED:
744  /* need to catch errors */
745  c->poll_entry = poll_entry;
746  poll_entry->fd = fd;
747  poll_entry->events = POLLIN;/* Maybe this will work */
748  poll_entry++;
749  break;
750  default:
751  c->poll_entry = NULL;
752  break;
753  }
754  c = c->next;
755  }
756 
757  /* wait for an event on one connection. We poll at least every
758  * second to handle timeouts */
759  do {
760  ret = poll(poll_table, poll_entry - poll_table, delay);
761  if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) &&
762  ff_neterrno() != AVERROR(EINTR)) {
763  goto quit;
764  }
765  } while (ret < 0);
766 
767  cur_time = av_gettime() / 1000;
768 
771  start_children(config.first_feed);
772  }
773 
774  /* now handle the events */
775  for(c = first_http_ctx; c; c = c_next) {
776  c_next = c->next;
777  if (handle_connection(c) < 0) {
778  log_connection(c);
779  /* close and free the connection */
780  close_connection(c);
781  }
782  }
783 
784  poll_entry = poll_table;
785  if (server_fd) {
786  /* new HTTP connection request ? */
787  if (poll_entry->revents & POLLIN)
788  new_connection(server_fd, 0);
789  poll_entry++;
790  }
791  if (rtsp_server_fd) {
792  /* new RTSP connection request ? */
793  if (poll_entry->revents & POLLIN)
794  new_connection(rtsp_server_fd, 1);
795  }
796  }
797 
798 quit:
799  av_free(poll_table);
800  return -1;
801 }
802 
803 /* start waiting for a new HTTP/RTSP request */
804 static void start_wait_request(HTTPContext *c, int is_rtsp)
805 {
806  c->buffer_ptr = c->buffer;
807  c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */
808 
810  c->timeout = cur_time +
812 }
813 
814 static void http_send_too_busy_reply(int fd)
815 {
816  char buffer[400];
817  int len = snprintf(buffer, sizeof(buffer),
818  "HTTP/1.0 503 Server too busy\r\n"
819  "Content-type: text/html\r\n"
820  "\r\n"
821  "<!DOCTYPE html>\n"
822  "<html><head><title>Too busy</title></head><body>\r\n"
823  "<p>The server is too busy to serve your request at "
824  "this time.</p>\r\n"
825  "<p>The number of current connections is %u, and this "
826  "exceeds the limit of %u.</p>\r\n"
827  "</body></html>\r\n",
829  av_assert0(len < sizeof(buffer));
830  if (send(fd, buffer, len, 0) < len)
832  "Could not send too-busy reply, send() failed\n");
833 }
834 
835 
836 static void new_connection(int server_fd, int is_rtsp)
837 {
838  struct sockaddr_in from_addr;
839  socklen_t len;
840  int fd;
841  HTTPContext *c = NULL;
842 
843  len = sizeof(from_addr);
844  fd = accept(server_fd, (struct sockaddr *)&from_addr,
845  &len);
846  if (fd < 0) {
847  http_log("error during accept %s\n", strerror(errno));
848  return;
849  }
850  if (ff_socket_nonblock(fd, 1) < 0)
851  av_log(NULL, AV_LOG_WARNING, "ff_socket_nonblock failed\n");
852 
853  if (nb_connections >= config.nb_max_connections) {
855  goto fail;
856  }
857 
858  /* add a new connection */
859  c = av_mallocz(sizeof(HTTPContext));
860  if (!c)
861  goto fail;
862 
863  c->fd = fd;
864  c->poll_entry = NULL;
865  c->from_addr = from_addr;
867  c->buffer = av_malloc(c->buffer_size);
868  if (!c->buffer)
869  goto fail;
870 
871  c->next = first_http_ctx;
872  first_http_ctx = c;
873  nb_connections++;
874 
875  start_wait_request(c, is_rtsp);
876 
877  return;
878 
879  fail:
880  if (c) {
881  av_freep(&c->buffer);
882  av_free(c);
883  }
884  closesocket(fd);
885 }
886 
888 {
889  HTTPContext **cp, *c1;
890  int i, nb_streams;
892  AVStream *st;
893 
894  /* remove connection from list */
895  cp = &first_http_ctx;
896  while (*cp) {
897  c1 = *cp;
898  if (c1 == c)
899  *cp = c->next;
900  else
901  cp = &c1->next;
902  }
903 
904  /* remove references, if any (XXX: do it faster) */
905  for(c1 = first_http_ctx; c1; c1 = c1->next) {
906  if (c1->rtsp_c == c)
907  c1->rtsp_c = NULL;
908  }
909 
910  /* remove connection associated resources */
911  if (c->fd >= 0)
912  closesocket(c->fd);
913  if (c->fmt_in) {
914  /* close each frame parser */
915  for(i=0;i<c->fmt_in->nb_streams;i++) {
916  st = c->fmt_in->streams[i];
917  if (st->codec->codec)
918  avcodec_close(st->codec);
919  }
921  }
922 
923  /* free RTP output streams if any */
924  nb_streams = 0;
925  if (c->stream)
926  nb_streams = c->stream->nb_streams;
927 
928  for(i=0;i<nb_streams;i++) {
929  ctx = c->rtp_ctx[i];
930  if (ctx) {
931  av_write_trailer(ctx);
932  av_dict_free(&ctx->metadata);
933  av_freep(&ctx->streams[0]);
934  av_freep(&ctx);
935  }
936  ffurl_close(c->rtp_handles[i]);
937  }
938 
939  ctx = &c->fmt_ctx;
940 
942  /* prepare header */
943  if (ctx->oformat && avio_open_dyn_buf(&ctx->pb) >= 0) {
944  av_write_trailer(ctx);
945  av_freep(&c->pb_buffer);
946  avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
947  }
948  }
949 
950  for(i=0; i<ctx->nb_streams; i++)
951  av_freep(&ctx->streams[i]);
952  av_freep(&ctx->streams);
953  av_freep(&ctx->priv_data);
954 
955  if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
957 
958  /* signal that there is no feed if we are the feeder socket */
959  if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) {
960  c->stream->feed_opened = 0;
961  close(c->feed_fd);
962  }
963 
964  av_freep(&c->pb_buffer);
965  av_freep(&c->packet_buffer);
966  av_freep(&c->buffer);
967  av_free(c);
968  nb_connections--;
969 }
970 
972 {
973  int len, ret;
974  uint8_t *ptr;
975 
976  switch(c->state) {
979  /* timeout ? */
980  if ((c->timeout - cur_time) < 0)
981  return -1;
982  if (c->poll_entry->revents & (POLLERR | POLLHUP))
983  return -1;
984 
985  /* no need to read if no events */
986  if (!(c->poll_entry->revents & POLLIN))
987  return 0;
988  /* read the data */
989  read_loop:
990  if (!(len = recv(c->fd, c->buffer_ptr, 1, 0)))
991  return -1;
992 
993  if (len < 0) {
994  if (ff_neterrno() != AVERROR(EAGAIN) &&
995  ff_neterrno() != AVERROR(EINTR))
996  return -1;
997  break;
998  }
999  /* search for end of request. */
1000  c->buffer_ptr += len;
1001  ptr = c->buffer_ptr;
1002  if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
1003  (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
1004  /* request found : parse it and reply */
1005  if (c->state == HTTPSTATE_WAIT_REQUEST)
1006  ret = http_parse_request(c);
1007  else
1008  ret = rtsp_parse_request(c);
1009 
1010  if (ret < 0)
1011  return -1;
1012  } else if (ptr >= c->buffer_end) {
1013  /* request too long: cannot do anything */
1014  return -1;
1015  } else goto read_loop;
1016 
1017  break;
1018 
1019  case HTTPSTATE_SEND_HEADER:
1020  if (c->poll_entry->revents & (POLLERR | POLLHUP))
1021  return -1;
1022 
1023  /* no need to write if no events */
1024  if (!(c->poll_entry->revents & POLLOUT))
1025  return 0;
1026  len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
1027  if (len < 0) {
1028  if (ff_neterrno() != AVERROR(EAGAIN) &&
1029  ff_neterrno() != AVERROR(EINTR)) {
1030  goto close_connection;
1031  }
1032  break;
1033  }
1034  c->buffer_ptr += len;
1035  if (c->stream)
1036  c->stream->bytes_served += len;
1037  c->data_count += len;
1038  if (c->buffer_ptr >= c->buffer_end) {
1039  av_freep(&c->pb_buffer);
1040  /* if error, exit */
1041  if (c->http_error)
1042  return -1;
1043  /* all the buffer was sent : synchronize to the incoming
1044  * stream */
1046  c->buffer_ptr = c->buffer_end = c->buffer;
1047  }
1048  break;
1049 
1050  case HTTPSTATE_SEND_DATA:
1053  /* for packetized output, we consider we can always write (the
1054  * input streams set the speed). It may be better to verify
1055  * that we do not rely too much on the kernel queues */
1056  if (!c->is_packetized) {
1057  if (c->poll_entry->revents & (POLLERR | POLLHUP))
1058  return -1;
1059 
1060  /* no need to read if no events */
1061  if (!(c->poll_entry->revents & POLLOUT))
1062  return 0;
1063  }
1064  if (http_send_data(c) < 0)
1065  return -1;
1066  /* close connection if trailer sent */
1068  return -1;
1069  /* Check if it is a single jpeg frame 123 */
1070  if (c->stream->single_frame && c->data_count > c->cur_frame_bytes && c->cur_frame_bytes > 0) {
1071  close_connection(c);
1072  }
1073  break;
1075  /* no need to read if no events */
1076  if (c->poll_entry->revents & (POLLERR | POLLHUP))
1077  return -1;
1078  if (!(c->poll_entry->revents & POLLIN))
1079  return 0;
1080  if (http_receive_data(c) < 0)
1081  return -1;
1082  break;
1083  case HTTPSTATE_WAIT_FEED:
1084  /* no need to read if no events */
1085  if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1086  return -1;
1087 
1088  /* nothing to do, we'll be waken up by incoming feed packets */
1089  break;
1090 
1091  case RTSPSTATE_SEND_REPLY:
1092  if (c->poll_entry->revents & (POLLERR | POLLHUP))
1093  goto close_connection;
1094  /* no need to write if no events */
1095  if (!(c->poll_entry->revents & POLLOUT))
1096  return 0;
1097  len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
1098  if (len < 0) {
1099  if (ff_neterrno() != AVERROR(EAGAIN) &&
1100  ff_neterrno() != AVERROR(EINTR)) {
1101  goto close_connection;
1102  }
1103  break;
1104  }
1105  c->buffer_ptr += len;
1106  c->data_count += len;
1107  if (c->buffer_ptr >= c->buffer_end) {
1108  /* all the buffer was sent : wait for a new request */
1109  av_freep(&c->pb_buffer);
1110  start_wait_request(c, 1);
1111  }
1112  break;
1113  case RTSPSTATE_SEND_PACKET:
1114  if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1115  av_freep(&c->packet_buffer);
1116  return -1;
1117  }
1118  /* no need to write if no events */
1119  if (!(c->poll_entry->revents & POLLOUT))
1120  return 0;
1121  len = send(c->fd, c->packet_buffer_ptr,
1123  if (len < 0) {
1124  if (ff_neterrno() != AVERROR(EAGAIN) &&
1125  ff_neterrno() != AVERROR(EINTR)) {
1126  /* error : close connection */
1127  av_freep(&c->packet_buffer);
1128  return -1;
1129  }
1130  break;
1131  }
1132  c->packet_buffer_ptr += len;
1133  if (c->packet_buffer_ptr >= c->packet_buffer_end) {
1134  /* all the buffer was sent : wait for a new request */
1135  av_freep(&c->packet_buffer);
1137  }
1138  break;
1139  case HTTPSTATE_READY:
1140  /* nothing to do */
1141  break;
1142  default:
1143  return -1;
1144  }
1145  return 0;
1146 
1148  av_freep(&c->pb_buffer);
1149  return -1;
1150 }
1151 
1152 static int extract_rates(char *rates, int ratelen, const char *request)
1153 {
1154  const char *p;
1155 
1156  for (p = request; *p && *p != '\r' && *p != '\n'; ) {
1157  if (av_strncasecmp(p, "Pragma:", 7) == 0) {
1158  const char *q = p + 7;
1159 
1160  while (*q && *q != '\n' && av_isspace(*q))
1161  q++;
1162 
1163  if (av_strncasecmp(q, "stream-switch-entry=", 20) == 0) {
1164  int stream_no;
1165  int rate_no;
1166 
1167  q += 20;
1168 
1169  memset(rates, 0xff, ratelen);
1170 
1171  while (1) {
1172  while (*q && *q != '\n' && *q != ':')
1173  q++;
1174 
1175  if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2)
1176  break;
1177 
1178  stream_no--;
1179  if (stream_no < ratelen && stream_no >= 0)
1180  rates[stream_no] = rate_no;
1181 
1182  while (*q && *q != '\n' && !av_isspace(*q))
1183  q++;
1184  }
1185 
1186  return 1;
1187  }
1188  }
1189  p = strchr(p, '\n');
1190  if (!p)
1191  break;
1192 
1193  p++;
1194  }
1195 
1196  return 0;
1197 }
1198 
1200  int bit_rate)
1201 {
1202  int i;
1203  int best_bitrate = 100000000;
1204  int best = -1;
1205 
1206  for (i = 0; i < feed->nb_streams; i++) {
1207  AVCodecContext *feed_codec = feed->streams[i]->codec;
1208 
1209  if (feed_codec->codec_id != codec->codec_id ||
1210  feed_codec->sample_rate != codec->sample_rate ||
1211  feed_codec->width != codec->width ||
1212  feed_codec->height != codec->height)
1213  continue;
1214 
1215  /* Potential stream */
1216 
1217  /* We want the fastest stream less than bit_rate, or the slowest
1218  * faster than bit_rate
1219  */
1220 
1221  if (feed_codec->bit_rate <= bit_rate) {
1222  if (best_bitrate > bit_rate ||
1223  feed_codec->bit_rate > best_bitrate) {
1224  best_bitrate = feed_codec->bit_rate;
1225  best = i;
1226  }
1227  continue;
1228  }
1229  if (feed_codec->bit_rate < best_bitrate) {
1230  best_bitrate = feed_codec->bit_rate;
1231  best = i;
1232  }
1233  }
1234  return best;
1235 }
1236 
1238 {
1239  int i;
1240  FFServerStream *req = c->stream;
1241  int action_required = 0;
1242 
1243  /* Not much we can do for a feed */
1244  if (!req->feed)
1245  return 0;
1246 
1247  for (i = 0; i < req->nb_streams; i++) {
1248  AVCodecContext *codec = req->streams[i]->codec;
1249 
1250  switch(rates[i]) {
1251  case 0:
1252  c->switch_feed_streams[i] = req->feed_streams[i];
1253  break;
1254  case 1:
1255  c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2);
1256  break;
1257  case 2:
1258  /* Wants off or slow */
1259  c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);
1260 #ifdef WANTS_OFF
1261  /* This doesn't work well when it turns off the only stream! */
1262  c->switch_feed_streams[i] = -2;
1263  c->feed_streams[i] = -2;
1264 #endif
1265  break;
1266  }
1267 
1268  if (c->switch_feed_streams[i] >= 0 &&
1269  c->switch_feed_streams[i] != c->feed_streams[i]) {
1270  action_required = 1;
1271  }
1272  }
1273 
1274  return action_required;
1275 }
1276 
1277 static void get_word(char *buf, int buf_size, const char **pp)
1278 {
1279  const char *p;
1280  char *q;
1281 
1282  p = *pp;
1283  p += strspn(p, SPACE_CHARS);
1284  q = buf;
1285  while (!av_isspace(*p) && *p != '\0') {
1286  if ((q - buf) < buf_size - 1)
1287  *q++ = *p;
1288  p++;
1289  }
1290  if (buf_size > 0)
1291  *q = '\0';
1292  *pp = p;
1293 }
1294 
1296  HTTPContext *c)
1297 {
1298  FILE* f;
1299  char line[1024];
1300  char cmd[1024];
1301  FFServerIPAddressACL *acl = NULL;
1302  int line_num = 0;
1303  const char *p;
1304 
1305  f = fopen(stream->dynamic_acl, "r");
1306  if (!f) {
1307  perror(stream->dynamic_acl);
1308  return NULL;
1309  }
1310 
1311  acl = av_mallocz(sizeof(FFServerIPAddressACL));
1312  if (!acl) {
1313  fclose(f);
1314  return NULL;
1315  }
1316 
1317  /* Build ACL */
1318  while (fgets(line, sizeof(line), f)) {
1319  line_num++;
1320  p = line;
1321  while (av_isspace(*p))
1322  p++;
1323  if (*p == '\0' || *p == '#')
1324  continue;
1325  ffserver_get_arg(cmd, sizeof(cmd), &p);
1326 
1327  if (!av_strcasecmp(cmd, "ACL"))
1328  ffserver_parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl,
1329  line_num);
1330  }
1331  fclose(f);
1332  return acl;
1333 }
1334 
1335 
1337 {
1338  FFServerIPAddressACL *pacl, *pacl2;
1339 
1340  pacl = in_acl;
1341  while(pacl) {
1342  pacl2 = pacl;
1343  pacl = pacl->next;
1344  av_freep(pacl2);
1345  }
1346 }
1347 
1349 {
1350  enum FFServerIPAddressAction last_action = IP_DENY;
1351  FFServerIPAddressACL *acl;
1352  struct in_addr *src = &c->from_addr.sin_addr;
1353  unsigned long src_addr = src->s_addr;
1354 
1355  for (acl = in_acl; acl; acl = acl->next) {
1356  if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr)
1357  return (acl->action == IP_ALLOW) ? 1 : 0;
1358  last_action = acl->action;
1359  }
1360 
1361  /* Nothing matched, so return not the last action */
1362  return (last_action == IP_DENY) ? 1 : 0;
1363 }
1364 
1366 {
1367  int ret = 0;
1368  FFServerIPAddressACL *acl;
1369 
1370  /* if stream->acl is null validate_acl_list will return 1 */
1371  ret = validate_acl_list(stream->acl, c);
1372 
1373  if (stream->dynamic_acl[0]) {
1374  acl = parse_dynamic_acl(stream, c);
1375  ret = validate_acl_list(acl, c);
1376  free_acl_list(acl);
1377  }
1378 
1379  return ret;
1380 }
1381 
1382 /**
1383  * compute the real filename of a file by matching it without its
1384  * extensions to all the stream's filenames
1385  */
1386 static void compute_real_filename(char *filename, int max_size)
1387 {
1388  char file1[1024];
1389  char file2[1024];
1390  char *p;
1391  FFServerStream *stream;
1392 
1393  av_strlcpy(file1, filename, sizeof(file1));
1394  p = strrchr(file1, '.');
1395  if (p)
1396  *p = '\0';
1397  for(stream = config.first_stream; stream; stream = stream->next) {
1398  av_strlcpy(file2, stream->filename, sizeof(file2));
1399  p = strrchr(file2, '.');
1400  if (p)
1401  *p = '\0';
1402  if (!strcmp(file1, file2)) {
1403  av_strlcpy(filename, stream->filename, max_size);
1404  break;
1405  }
1406  }
1407 }
1408 
1416 };
1417 
1418 /* parse HTTP request and prepare header */
1420 {
1421  const char *p;
1422  char *p1;
1423  enum RedirType redir_type;
1424  char cmd[32];
1425  char info[1024], filename[1024];
1426  char url[1024], *q;
1427  char protocol[32];
1428  char msg[1024];
1429  char *encoded_msg = NULL;
1430  const char *mime_type;
1431  FFServerStream *stream;
1432  int i;
1433  char ratebuf[32];
1434  const char *useragent = 0;
1435 
1436  p = c->buffer;
1437  get_word(cmd, sizeof(cmd), &p);
1438  av_strlcpy(c->method, cmd, sizeof(c->method));
1439 
1440  if (!strcmp(cmd, "GET"))
1441  c->post = 0;
1442  else if (!strcmp(cmd, "POST"))
1443  c->post = 1;
1444  else
1445  return -1;
1446 
1447  get_word(url, sizeof(url), &p);
1448  av_strlcpy(c->url, url, sizeof(c->url));
1449 
1450  get_word(protocol, sizeof(protocol), (const char **)&p);
1451  if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
1452  return -1;
1453 
1454  av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
1455 
1456  if (config.debug)
1457  http_log("%s - - New connection: %s %s\n",
1458  inet_ntoa(c->from_addr.sin_addr), cmd, url);
1459 
1460  /* find the filename and the optional info string in the request */
1461  p1 = strchr(url, '?');
1462  if (p1) {
1463  av_strlcpy(info, p1, sizeof(info));
1464  *p1 = '\0';
1465  } else
1466  info[0] = '\0';
1467 
1468  av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1);
1469 
1470  for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1471  if (av_strncasecmp(p, "User-Agent:", 11) == 0) {
1472  useragent = p + 11;
1473  if (*useragent && *useragent != '\n' && av_isspace(*useragent))
1474  useragent++;
1475  break;
1476  }
1477  p = strchr(p, '\n');
1478  if (!p)
1479  break;
1480 
1481  p++;
1482  }
1483 
1484  redir_type = REDIR_NONE;
1485  if (av_match_ext(filename, "asx")) {
1486  redir_type = REDIR_ASX;
1487  filename[strlen(filename)-1] = 'f';
1488  } else if (av_match_ext(filename, "asf") &&
1489  (!useragent || av_strncasecmp(useragent, "NSPlayer", 8))) {
1490  /* if this isn't WMP or lookalike, return the redirector file */
1491  redir_type = REDIR_ASF;
1492  } else if (av_match_ext(filename, "rpm,ram")) {
1493  redir_type = REDIR_RAM;
1494  strcpy(filename + strlen(filename)-2, "m");
1495  } else if (av_match_ext(filename, "rtsp")) {
1496  redir_type = REDIR_RTSP;
1497  compute_real_filename(filename, sizeof(filename) - 1);
1498  } else if (av_match_ext(filename, "sdp")) {
1499  redir_type = REDIR_SDP;
1500  compute_real_filename(filename, sizeof(filename) - 1);
1501  }
1502 
1503  /* "redirect" request to index.html */
1504  if (!strlen(filename))
1505  av_strlcpy(filename, "index.html", sizeof(filename) - 1);
1506 
1507  stream = config.first_stream;
1508  while (stream) {
1509  if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
1510  break;
1511  stream = stream->next;
1512  }
1513  if (!stream) {
1514  snprintf(msg, sizeof(msg), "File '%s' not found", url);
1515  http_log("File '%s' not found\n", url);
1516  goto send_error;
1517  }
1518 
1519  c->stream = stream;
1520  memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
1521  memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
1522 
1523  if (stream->stream_type == STREAM_TYPE_REDIRECT) {
1524  c->http_error = 301;
1525  q = c->buffer;
1526  snprintf(q, c->buffer_size,
1527  "HTTP/1.0 301 Moved\r\n"
1528  "Location: %s\r\n"
1529  "Content-type: text/html\r\n"
1530  "\r\n"
1531  "<!DOCTYPE html>\n"
1532  "<html><head><title>Moved</title></head><body>\r\n"
1533  "You should be <a href=\"%s\">redirected</a>.\r\n"
1534  "</body></html>\r\n",
1535  stream->feed_filename, stream->feed_filename);
1536  q += strlen(q);
1537  /* prepare output buffer */
1538  c->buffer_ptr = c->buffer;
1539  c->buffer_end = q;
1541  return 0;
1542  }
1543 
1544  /* If this is WMP, get the rate information */
1545  if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1546  if (modify_current_stream(c, ratebuf)) {
1547  for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) {
1548  if (c->switch_feed_streams[i] >= 0)
1549  c->switch_feed_streams[i] = -1;
1550  }
1551  }
1552  }
1553 
1554  if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
1555  current_bandwidth += stream->bandwidth;
1556 
1557  /* If already streaming this feed, do not let another feeder start */
1558  if (stream->feed_opened) {
1559  snprintf(msg, sizeof(msg), "This feed is already being received.");
1560  http_log("Feed '%s' already being received\n", stream->feed_filename);
1561  goto send_error;
1562  }
1563 
1564  if (c->post == 0 && config.max_bandwidth < current_bandwidth) {
1565  c->http_error = 503;
1566  q = c->buffer;
1567  snprintf(q, c->buffer_size,
1568  "HTTP/1.0 503 Server too busy\r\n"
1569  "Content-type: text/html\r\n"
1570  "\r\n"
1571  "<!DOCTYPE html>\n"
1572  "<html><head><title>Too busy</title></head><body>\r\n"
1573  "<p>The server is too busy to serve your request at "
1574  "this time.</p>\r\n"
1575  "<p>The bandwidth being served (including your stream) "
1576  "is %"PRIu64"kbit/s, and this exceeds the limit of "
1577  "%"PRIu64"kbit/s.</p>\r\n"
1578  "</body></html>\r\n",
1580  q += strlen(q);
1581  /* prepare output buffer */
1582  c->buffer_ptr = c->buffer;
1583  c->buffer_end = q;
1585  return 0;
1586  }
1587 
1588  if (redir_type != REDIR_NONE) {
1589  const char *hostinfo = 0;
1590 
1591  for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1592  if (av_strncasecmp(p, "Host:", 5) == 0) {
1593  hostinfo = p + 5;
1594  break;
1595  }
1596  p = strchr(p, '\n');
1597  if (!p)
1598  break;
1599 
1600  p++;
1601  }
1602 
1603  if (hostinfo) {
1604  char *eoh;
1605  char hostbuf[260];
1606 
1607  while (av_isspace(*hostinfo))
1608  hostinfo++;
1609 
1610  eoh = strchr(hostinfo, '\n');
1611  if (eoh) {
1612  if (eoh[-1] == '\r')
1613  eoh--;
1614 
1615  if (eoh - hostinfo < sizeof(hostbuf) - 1) {
1616  memcpy(hostbuf, hostinfo, eoh - hostinfo);
1617  hostbuf[eoh - hostinfo] = 0;
1618 
1619  c->http_error = 200;
1620  q = c->buffer;
1621  switch(redir_type) {
1622  case REDIR_ASX:
1623  snprintf(q, c->buffer_size,
1624  "HTTP/1.0 200 ASX Follows\r\n"
1625  "Content-type: video/x-ms-asf\r\n"
1626  "\r\n"
1627  "<ASX Version=\"3\">\r\n"
1628  //"<!-- Autogenerated by ffserver -->\r\n"
1629  "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1630  "</ASX>\r\n", hostbuf, filename, info);
1631  q += strlen(q);
1632  break;
1633  case REDIR_RAM:
1634  snprintf(q, c->buffer_size,
1635  "HTTP/1.0 200 RAM Follows\r\n"
1636  "Content-type: audio/x-pn-realaudio\r\n"
1637  "\r\n"
1638  "# Autogenerated by ffserver\r\n"
1639  "http://%s/%s%s\r\n", hostbuf, filename, info);
1640  q += strlen(q);
1641  break;
1642  case REDIR_ASF:
1643  snprintf(q, c->buffer_size,
1644  "HTTP/1.0 200 ASF Redirect follows\r\n"
1645  "Content-type: video/x-ms-asf\r\n"
1646  "\r\n"
1647  "[Reference]\r\n"
1648  "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1649  q += strlen(q);
1650  break;
1651  case REDIR_RTSP:
1652  {
1653  char hostname[256], *p;
1654  /* extract only hostname */
1655  av_strlcpy(hostname, hostbuf, sizeof(hostname));
1656  p = strrchr(hostname, ':');
1657  if (p)
1658  *p = '\0';
1659  snprintf(q, c->buffer_size,
1660  "HTTP/1.0 200 RTSP Redirect follows\r\n"
1661  /* XXX: incorrect MIME type ? */
1662  "Content-type: application/x-rtsp\r\n"
1663  "\r\n"
1664  "rtsp://%s:%d/%s\r\n", hostname, ntohs(config.rtsp_addr.sin_port), filename);
1665  q += strlen(q);
1666  }
1667  break;
1668  case REDIR_SDP:
1669  {
1670  uint8_t *sdp_data;
1671  int sdp_data_size;
1672  socklen_t len;
1673  struct sockaddr_in my_addr;
1674 
1675  snprintf(q, c->buffer_size,
1676  "HTTP/1.0 200 OK\r\n"
1677  "Content-type: application/sdp\r\n"
1678  "\r\n");
1679  q += strlen(q);
1680 
1681  len = sizeof(my_addr);
1682 
1683  /* XXX: Should probably fail? */
1684  if (getsockname(c->fd, (struct sockaddr *)&my_addr, &len))
1685  http_log("getsockname() failed\n");
1686 
1687  /* XXX: should use a dynamic buffer */
1688  sdp_data_size = prepare_sdp_description(stream,
1689  &sdp_data,
1690  my_addr.sin_addr);
1691  if (sdp_data_size > 0) {
1692  memcpy(q, sdp_data, sdp_data_size);
1693  q += sdp_data_size;
1694  *q = '\0';
1695  av_free(sdp_data);
1696  }
1697  }
1698  break;
1699  default:
1700  abort();
1701  break;
1702  }
1703 
1704  /* prepare output buffer */
1705  c->buffer_ptr = c->buffer;
1706  c->buffer_end = q;
1708  return 0;
1709  }
1710  }
1711  }
1712 
1713  snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
1714  goto send_error;
1715  }
1716 
1717  stream->conns_served++;
1718 
1719  /* XXX: add there authenticate and IP match */
1720 
1721  if (c->post) {
1722  /* if post, it means a feed is being sent */
1723  if (!stream->is_feed) {
1724  /* However it might be a status report from WMP! Let us log the
1725  * data as it might come handy one day. */
1726  const char *logline = 0;
1727  int client_id = 0;
1728 
1729  for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1730  if (av_strncasecmp(p, "Pragma: log-line=", 17) == 0) {
1731  logline = p;
1732  break;
1733  }
1734  if (av_strncasecmp(p, "Pragma: client-id=", 18) == 0)
1735  client_id = strtol(p + 18, 0, 10);
1736  p = strchr(p, '\n');
1737  if (!p)
1738  break;
1739 
1740  p++;
1741  }
1742 
1743  if (logline) {
1744  char *eol = strchr(logline, '\n');
1745 
1746  logline += 17;
1747 
1748  if (eol) {
1749  if (eol[-1] == '\r')
1750  eol--;
1751  http_log("%.*s\n", (int) (eol - logline), logline);
1752  c->suppress_log = 1;
1753  }
1754  }
1755 
1756 #ifdef DEBUG
1757  http_log("\nGot request:\n%s\n", c->buffer);
1758 #endif
1759 
1760  if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1761  HTTPContext *wmpc;
1762 
1763  /* Now we have to find the client_id */
1764  for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
1765  if (wmpc->wmp_client_id == client_id)
1766  break;
1767  }
1768 
1769  if (wmpc && modify_current_stream(wmpc, ratebuf))
1770  wmpc->switch_pending = 1;
1771  }
1772 
1773  snprintf(msg, sizeof(msg), "POST command not handled");
1774  c->stream = 0;
1775  goto send_error;
1776  }
1777  if (http_start_receive_data(c) < 0) {
1778  snprintf(msg, sizeof(msg), "could not open feed");
1779  goto send_error;
1780  }
1781  c->http_error = 0;
1783  return 0;
1784  }
1785 
1786 #ifdef DEBUG
1787  if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0)
1788  http_log("\nGot request:\n%s\n", c->buffer);
1789 #endif
1790 
1792  goto send_status;
1793 
1794  /* open input stream */
1795  if (open_input_stream(c, info) < 0) {
1796  snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
1797  goto send_error;
1798  }
1799 
1800  /* prepare HTTP header */
1801  c->buffer[0] = 0;
1802  av_strlcatf(c->buffer, c->buffer_size, "HTTP/1.0 200 OK\r\n");
1803  mime_type = c->stream->fmt->mime_type;
1804  if (!mime_type)
1805  mime_type = "application/x-octet-stream";
1806  av_strlcatf(c->buffer, c->buffer_size, "Pragma: no-cache\r\n");
1807 
1808  /* for asf, we need extra headers */
1809  if (!strcmp(c->stream->fmt->name,"asf_stream")) {
1810  /* Need to allocate a client id */
1811 
1812  c->wmp_client_id = av_lfg_get(&random_state);
1813 
1814  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);
1815  }
1816  av_strlcatf(c->buffer, c->buffer_size, "Content-Type: %s\r\n", mime_type);
1817  av_strlcatf(c->buffer, c->buffer_size, "\r\n");
1818  q = c->buffer + strlen(c->buffer);
1819 
1820  /* prepare output buffer */
1821  c->http_error = 0;
1822  c->buffer_ptr = c->buffer;
1823  c->buffer_end = q;
1825  return 0;
1826  send_error:
1827  c->http_error = 404;
1828  q = c->buffer;
1829  if (!htmlencode(msg, &encoded_msg)) {
1830  http_log("Could not encode filename '%s' as HTML\n", msg);
1831  }
1832  snprintf(q, c->buffer_size,
1833  "HTTP/1.0 404 Not Found\r\n"
1834  "Content-type: text/html\r\n"
1835  "\r\n"
1836  "<!DOCTYPE html>\n"
1837  "<html>\n"
1838  "<head>\n"
1839  "<meta charset=\"UTF-8\">\n"
1840  "<title>404 Not Found</title>\n"
1841  "</head>\n"
1842  "<body>%s</body>\n"
1843  "</html>\n", encoded_msg? encoded_msg : "File not found");
1844  q += strlen(q);
1845  /* prepare output buffer */
1846  c->buffer_ptr = c->buffer;
1847  c->buffer_end = q;
1849  av_freep(&encoded_msg);
1850  return 0;
1851  send_status:
1852  compute_status(c);
1853  /* horrible: we use this value to avoid
1854  * going to the send data state */
1855  c->http_error = 200;
1857  return 0;
1858 }
1859 
1860 static void fmt_bytecount(AVIOContext *pb, int64_t count)
1861 {
1862  static const char suffix[] = " kMGTP";
1863  const char *s;
1864 
1865  for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1866 
1867  avio_printf(pb, "%"PRId64"%c", count, *s);
1868 }
1869 
1870 static inline void print_stream_params(AVIOContext *pb, FFServerStream *stream)
1871 {
1872  int i, stream_no;
1873  const char *type = "unknown";
1874  char parameters[64];
1875  AVStream *st;
1876  AVCodec *codec;
1877 
1878  stream_no = stream->nb_streams;
1879 
1880  avio_printf(pb, "<table cellspacing=0 cellpadding=4><tr><th>Stream<th>"
1881  "type<th>kbit/s<th align=left>codec<th align=left>"
1882  "Parameters\n");
1883 
1884  for (i = 0; i < stream_no; i++) {
1885  st = stream->streams[i];
1886  codec = avcodec_find_encoder(st->codec->codec_id);
1887 
1888  parameters[0] = 0;
1889 
1890  switch(st->codec->codec_type) {
1891  case AVMEDIA_TYPE_AUDIO:
1892  type = "audio";
1893  snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz",
1894  st->codec->channels, st->codec->sample_rate);
1895  break;
1896  case AVMEDIA_TYPE_VIDEO:
1897  type = "video";
1898  snprintf(parameters, sizeof(parameters),
1899  "%dx%d, q=%d-%d, fps=%d", st->codec->width,
1900  st->codec->height, st->codec->qmin, st->codec->qmax,
1901  st->codec->time_base.den / st->codec->time_base.num);
1902  break;
1903  default:
1904  abort();
1905  }
1906 
1907  avio_printf(pb, "<tr><td align=right>%d<td>%s<td align=right>%"PRId64
1908  "<td>%s<td>%s\n",
1909  i, type, (int64_t)st->codec->bit_rate/1000,
1910  codec ? codec->name : "", parameters);
1911  }
1912 
1913  avio_printf(pb, "</table>\n");
1914 }
1915 
1917 {
1918  HTTPContext *c1;
1919  FFServerStream *stream;
1920  char *p;
1921  time_t ti;
1922  int i, len;
1923  AVIOContext *pb;
1924 
1925  if (avio_open_dyn_buf(&pb) < 0) {
1926  /* XXX: return an error ? */
1927  c->buffer_ptr = c->buffer;
1928  c->buffer_end = c->buffer;
1929  return;
1930  }
1931 
1932  avio_printf(pb, "HTTP/1.0 200 OK\r\n");
1933  avio_printf(pb, "Content-type: text/html\r\n");
1934  avio_printf(pb, "Pragma: no-cache\r\n");
1935  avio_printf(pb, "\r\n");
1936 
1937  avio_printf(pb, "<!DOCTYPE html>\n");
1938  avio_printf(pb, "<html><head><title>%s Status</title>\n", program_name);
1939  if (c->stream->feed_filename[0])
1940  avio_printf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n",
1941  c->stream->feed_filename);
1942  avio_printf(pb, "</head>\n<body>");
1943  avio_printf(pb, "<h1>%s Status</h1>\n", program_name);
1944  /* format status */
1945  avio_printf(pb, "<h2>Available Streams</h2>\n");
1946  avio_printf(pb, "<table cellspacing=0 cellpadding=4>\n");
1947  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>kbit/s<th align=left>Video<br>kbit/s<th><br>Codec<th align=left>Audio<br>kbit/s<th><br>Codec<th align=left valign=top>Feed\n");
1948  stream = config.first_stream;
1949  while (stream) {
1950  char sfilename[1024];
1951  char *eosf;
1952 
1953  if (stream->feed == stream) {
1954  stream = stream->next;
1955  continue;
1956  }
1957 
1958  av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
1959  eosf = sfilename + strlen(sfilename);
1960  if (eosf - sfilename >= 4) {
1961  if (strcmp(eosf - 4, ".asf") == 0)
1962  strcpy(eosf - 4, ".asx");
1963  else if (strcmp(eosf - 3, ".rm") == 0)
1964  strcpy(eosf - 3, ".ram");
1965  else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
1966  /* generate a sample RTSP director if
1967  * unicast. Generate an SDP redirector if
1968  * multicast */
1969  eosf = strrchr(sfilename, '.');
1970  if (!eosf)
1971  eosf = sfilename + strlen(sfilename);
1972  if (stream->is_multicast)
1973  strcpy(eosf, ".sdp");
1974  else
1975  strcpy(eosf, ".rtsp");
1976  }
1977  }
1978 
1979  avio_printf(pb, "<tr><td><a href=\"/%s\">%s</a> ",
1980  sfilename, stream->filename);
1981  avio_printf(pb, "<td align=right> %d <td align=right> ",
1982  stream->conns_served);
1983  fmt_bytecount(pb, stream->bytes_served);
1984 
1985  switch(stream->stream_type) {
1986  case STREAM_TYPE_LIVE: {
1987  int audio_bit_rate = 0;
1988  int video_bit_rate = 0;
1989  const char *audio_codec_name = "";
1990  const char *video_codec_name = "";
1991  const char *audio_codec_name_extra = "";
1992  const char *video_codec_name_extra = "";
1993 
1994  for(i=0;i<stream->nb_streams;i++) {
1995  AVStream *st = stream->streams[i];
1996  AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
1997 
1998  switch(st->codec->codec_type) {
1999  case AVMEDIA_TYPE_AUDIO:
2000  audio_bit_rate += st->codec->bit_rate;
2001  if (codec) {
2002  if (*audio_codec_name)
2003  audio_codec_name_extra = "...";
2004  audio_codec_name = codec->name;
2005  }
2006  break;
2007  case AVMEDIA_TYPE_VIDEO:
2008  video_bit_rate += st->codec->bit_rate;
2009  if (codec) {
2010  if (*video_codec_name)
2011  video_codec_name_extra = "...";
2012  video_codec_name = codec->name;
2013  }
2014  break;
2015  case AVMEDIA_TYPE_DATA:
2016  video_bit_rate += st->codec->bit_rate;
2017  break;
2018  default:
2019  abort();
2020  }
2021  }
2022 
2023  avio_printf(pb, "<td align=center> %s <td align=right> %d "
2024  "<td align=right> %d <td> %s %s <td align=right> "
2025  "%d <td> %s %s",
2026  stream->fmt->name, stream->bandwidth,
2027  video_bit_rate / 1000, video_codec_name,
2028  video_codec_name_extra, audio_bit_rate / 1000,
2029  audio_codec_name, audio_codec_name_extra);
2030 
2031  if (stream->feed)
2032  avio_printf(pb, "<td>%s", stream->feed->filename);
2033  else
2034  avio_printf(pb, "<td>%s", stream->feed_filename);
2035  avio_printf(pb, "\n");
2036  }
2037  break;
2038  default:
2039  avio_printf(pb, "<td align=center> - <td align=right> - "
2040  "<td align=right> - <td><td align=right> - <td>\n");
2041  break;
2042  }
2043  stream = stream->next;
2044  }
2045  avio_printf(pb, "</table>\n");
2046 
2047  stream = config.first_stream;
2048  while (stream) {
2049 
2050  if (stream->feed != stream) {
2051  stream = stream->next;
2052  continue;
2053  }
2054 
2055  avio_printf(pb, "<h2>Feed %s</h2>", stream->filename);
2056  if (stream->pid) {
2057  avio_printf(pb, "Running as pid %"PRId64".\n", (int64_t) stream->pid);
2058 
2059 #if defined(linux)
2060  {
2061  FILE *pid_stat;
2062  char ps_cmd[64];
2063 
2064  /* This is somewhat linux specific I guess */
2065  snprintf(ps_cmd, sizeof(ps_cmd),
2066  "ps -o \"%%cpu,cputime\" --no-headers %"PRId64"",
2067  (int64_t) stream->pid);
2068 
2069  pid_stat = popen(ps_cmd, "r");
2070  if (pid_stat) {
2071  char cpuperc[10];
2072  char cpuused[64];
2073 
2074  if (fscanf(pid_stat, "%9s %63s", cpuperc, cpuused) == 2) {
2075  avio_printf(pb, "Currently using %s%% of the cpu. "
2076  "Total time used %s.\n",
2077  cpuperc, cpuused);
2078  }
2079  fclose(pid_stat);
2080  }
2081  }
2082 #endif
2083 
2084  avio_printf(pb, "<p>");
2085  }
2086 
2087  print_stream_params(pb, stream);
2088  stream = stream->next;
2089  }
2090 
2091  /* connection status */
2092  avio_printf(pb, "<h2>Connection Status</h2>\n");
2093 
2094  avio_printf(pb, "Number of connections: %d / %d<br>\n",
2096 
2097  avio_printf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<br>\n",
2099 
2100  avio_printf(pb, "<table>\n");
2101  avio_printf(pb, "<tr><th>#<th>File<th>IP<th>Proto<th>State<th>Target "
2102  "bit/s<th>Actual bit/s<th>Bytes transferred\n");
2103  c1 = first_http_ctx;
2104  i = 0;
2105  while (c1) {
2106  int bitrate;
2107  int j;
2108 
2109  bitrate = 0;
2110  if (c1->stream) {
2111  for (j = 0; j < c1->stream->nb_streams; j++) {
2112  if (!c1->stream->feed)
2113  bitrate += c1->stream->streams[j]->codec->bit_rate;
2114  else if (c1->feed_streams[j] >= 0)
2115  bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
2116  }
2117  }
2118 
2119  i++;
2120  p = inet_ntoa(c1->from_addr.sin_addr);
2121  avio_printf(pb, "<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s"
2122  "<td align=right>",
2123  i, c1->stream ? c1->stream->filename : "",
2124  c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "", p,
2125  c1->protocol, http_state[c1->state]);
2126  fmt_bytecount(pb, bitrate);
2127  avio_printf(pb, "<td align=right>");
2128  fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
2129  avio_printf(pb, "<td align=right>");
2130  fmt_bytecount(pb, c1->data_count);
2131  avio_printf(pb, "\n");
2132  c1 = c1->next;
2133  }
2134  avio_printf(pb, "</table>\n");
2135 
2136  /* date */
2137  ti = time(NULL);
2138  p = ctime(&ti);
2139  avio_printf(pb, "<hr size=1 noshade>Generated at %s", p);
2140  avio_printf(pb, "</body>\n</html>\n");
2141 
2142  len = avio_close_dyn_buf(pb, &c->pb_buffer);
2143  c->buffer_ptr = c->pb_buffer;
2144  c->buffer_end = c->pb_buffer + len;
2145 }
2146 
2147 static int open_input_stream(HTTPContext *c, const char *info)
2148 {
2149  char buf[128];
2150  char input_filename[1024];
2151  AVFormatContext *s = NULL;
2152  int buf_size, i, ret;
2153  int64_t stream_pos;
2154 
2155  /* find file name */
2156  if (c->stream->feed) {
2157  strcpy(input_filename, c->stream->feed->feed_filename);
2158  buf_size = FFM_PACKET_SIZE;
2159  /* compute position (absolute time) */
2160  if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2161  if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0) {
2162  http_log("Invalid date specification '%s' for stream\n", buf);
2163  return ret;
2164  }
2165  } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) {
2166  int prebuffer = strtol(buf, 0, 10);
2167  stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
2168  } else
2169  stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
2170  } else {
2171  strcpy(input_filename, c->stream->feed_filename);
2172  buf_size = 0;
2173  /* compute position (relative time) */
2174  if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2175  if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0) {
2176  http_log("Invalid date specification '%s' for stream\n", buf);
2177  return ret;
2178  }
2179  } else
2180  stream_pos = 0;
2181  }
2182  if (!input_filename[0]) {
2183  http_log("No filename was specified for stream\n");
2184  return AVERROR(EINVAL);
2185  }
2186 
2187  /* open stream */
2188  ret = avformat_open_input(&s, input_filename, c->stream->ifmt,
2189  &c->stream->in_opts);
2190  if (ret < 0) {
2191  http_log("Could not open input '%s': %s\n",
2192  input_filename, av_err2str(ret));
2193  return ret;
2194  }
2195 
2196  /* set buffer size */
2197  if (buf_size > 0) {
2198  ret = ffio_set_buf_size(s->pb, buf_size);
2199  if (ret < 0) {
2200  http_log("Failed to set buffer size\n");
2201  return ret;
2202  }
2203  }
2204 
2205  s->flags |= AVFMT_FLAG_GENPTS;
2206  c->fmt_in = s;
2207  if (strcmp(s->iformat->name, "ffm") &&
2208  (ret = avformat_find_stream_info(c->fmt_in, NULL)) < 0) {
2209  http_log("Could not find stream info for input '%s'\n", input_filename);
2211  return ret;
2212  }
2213 
2214  /* choose stream as clock source (we favor the video stream if
2215  * present) for packet sending */
2216  c->pts_stream_index = 0;
2217  for(i=0;i<c->stream->nb_streams;i++) {
2218  if (c->pts_stream_index == 0 &&
2219  c->stream->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
2220  c->pts_stream_index = i;
2221  }
2222  }
2223 
2224  if (c->fmt_in->iformat->read_seek)
2225  av_seek_frame(c->fmt_in, -1, stream_pos, 0);
2226  /* set the start time (needed for maxtime and RTP packet timing) */
2227  c->start_time = cur_time;
2229  return 0;
2230 }
2231 
2232 /* return the server clock (in us) */
2234 {
2235  /* compute current pts value from system time */
2236  return (cur_time - c->start_time) * 1000;
2237 }
2238 
2239 /* return the estimated time (in us) at which the current packet must be sent */
2241 {
2242  int bytes_left, bytes_sent, frame_bytes;
2243 
2244  frame_bytes = c->cur_frame_bytes;
2245  if (frame_bytes <= 0)
2246  return c->cur_pts;
2247 
2248  bytes_left = c->buffer_end - c->buffer_ptr;
2249  bytes_sent = frame_bytes - bytes_left;
2250  return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
2251 }
2252 
2253 
2255 {
2256  int i, len, ret;
2258 
2259  av_freep(&c->pb_buffer);
2260  switch(c->state) {
2262  ctx = avformat_alloc_context();
2263  if (!ctx)
2264  return AVERROR(ENOMEM);
2265  c->fmt_ctx = *ctx;
2266  av_freep(&ctx);
2267  av_dict_copy(&(c->fmt_ctx.metadata), c->stream->metadata, 0);
2269  sizeof(AVStream *));
2270  if (!c->fmt_ctx.streams)
2271  return AVERROR(ENOMEM);
2272 
2273  for(i=0;i<c->stream->nb_streams;i++) {
2274  AVStream *src;
2275  c->fmt_ctx.streams[i] = av_mallocz(sizeof(AVStream));
2276 
2277  /* if file or feed, then just take streams from FFServerStream
2278  * struct */
2279  if (!c->stream->feed ||
2280  c->stream->feed == c->stream)
2281  src = c->stream->streams[i];
2282  else
2283  src = c->stream->feed->streams[c->stream->feed_streams[i]];
2284 
2285  *(c->fmt_ctx.streams[i]) = *src;
2286  c->fmt_ctx.streams[i]->priv_data = 0;
2287  /* XXX: should be done in AVStream, not in codec */
2288  c->fmt_ctx.streams[i]->codec->frame_number = 0;
2289  }
2290  /* set output format parameters */
2291  c->fmt_ctx.oformat = c->stream->fmt;
2293 
2294  c->got_key_frame = 0;
2295 
2296  /* prepare header and save header data in a stream */
2297  if (avio_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
2298  /* XXX: potential leak */
2299  return -1;
2300  }
2301  c->fmt_ctx.pb->seekable = 0;
2302 
2303  /*
2304  * HACK to avoid MPEG-PS muxer to spit many underflow errors
2305  * Default value from FFmpeg
2306  * Try to set it using configuration option
2307  */
2308  c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
2309 
2310  if ((ret = avformat_write_header(&c->fmt_ctx, NULL)) < 0) {
2311  http_log("Error writing output header for stream '%s': %s\n",
2312  c->stream->filename, av_err2str(ret));
2313  return ret;
2314  }
2316 
2317  len = avio_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
2318  c->buffer_ptr = c->pb_buffer;
2319  c->buffer_end = c->pb_buffer + len;
2320 
2322  c->last_packet_sent = 0;
2323  break;
2324  case HTTPSTATE_SEND_DATA:
2325  /* find a new packet */
2326  /* read a packet from the input stream */
2327  if (c->stream->feed)
2330  c->stream->feed->feed_size);
2331 
2332  if (c->stream->max_time &&
2333  c->stream->max_time + c->start_time - cur_time < 0)
2334  /* We have timed out */
2336  else {
2337  AVPacket pkt;
2338  redo:
2339  ret = av_read_frame(c->fmt_in, &pkt);
2340  if (ret < 0) {
2341  if (c->stream->feed) {
2342  /* if coming from feed, it means we reached the end of the
2343  * ffm file, so must wait for more data */
2345  return 1; /* state changed */
2346  }
2347  if (ret == AVERROR(EAGAIN)) {
2348  /* input not ready, come back later */
2349  return 0;
2350  }
2351  if (c->stream->loop) {
2353  if (open_input_stream(c, "") < 0)
2354  goto no_loop;
2355  goto redo;
2356  } else {
2357  no_loop:
2358  /* must send trailer now because EOF or error */
2360  }
2361  } else {
2362  int source_index = pkt.stream_index;
2363  /* update first pts if needed */
2364  if (c->first_pts == AV_NOPTS_VALUE && pkt.dts != AV_NOPTS_VALUE) {
2366  c->start_time = cur_time;
2367  }
2368  /* send it to the appropriate stream */
2369  if (c->stream->feed) {
2370  /* if coming from a feed, select the right stream */
2371  if (c->switch_pending) {
2372  c->switch_pending = 0;
2373  for(i=0;i<c->stream->nb_streams;i++) {
2374  if (c->switch_feed_streams[i] == pkt.stream_index)
2375  if (pkt.flags & AV_PKT_FLAG_KEY)
2376  c->switch_feed_streams[i] = -1;
2377  if (c->switch_feed_streams[i] >= 0)
2378  c->switch_pending = 1;
2379  }
2380  }
2381  for(i=0;i<c->stream->nb_streams;i++) {
2382  if (c->stream->feed_streams[i] == pkt.stream_index) {
2383  AVStream *st = c->fmt_in->streams[source_index];
2384  pkt.stream_index = i;
2385  if (pkt.flags & AV_PKT_FLAG_KEY &&
2386  (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2387  c->stream->nb_streams == 1))
2388  c->got_key_frame = 1;
2389  if (!c->stream->send_on_key || c->got_key_frame)
2390  goto send_it;
2391  }
2392  }
2393  } else {
2394  AVCodecContext *codec;
2395  AVStream *ist, *ost;
2396  send_it:
2397  ist = c->fmt_in->streams[source_index];
2398  /* specific handling for RTP: we use several
2399  * output streams (one for each RTP connection).
2400  * XXX: need more abstract handling */
2401  if (c->is_packetized) {
2402  /* compute send time and duration */
2403  if (pkt.dts != AV_NOPTS_VALUE) {
2404  c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
2405  c->cur_pts -= c->first_pts;
2406  }
2408  /* find RTP context */
2410  ctx = c->rtp_ctx[c->packet_stream_index];
2411  if(!ctx) {
2412  av_packet_unref(&pkt);
2413  break;
2414  }
2415  codec = ctx->streams[0]->codec;
2416  /* only one stream per RTP connection */
2417  pkt.stream_index = 0;
2418  } else {
2419  ctx = &c->fmt_ctx;
2420  /* Fudge here */
2421  codec = ctx->streams[pkt.stream_index]->codec;
2422  }
2423 
2424  if (c->is_packetized) {
2425  int max_packet_size;
2427  max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2428  else
2429  max_packet_size = c->rtp_handles[c->packet_stream_index]->max_packet_size;
2430  ret = ffio_open_dyn_packet_buf(&ctx->pb,
2431  max_packet_size);
2432  } else
2433  ret = avio_open_dyn_buf(&ctx->pb);
2434 
2435  if (ret < 0) {
2436  /* XXX: potential leak */
2437  return -1;
2438  }
2439  ost = ctx->streams[pkt.stream_index];
2440 
2441  ctx->pb->seekable = 0;
2442  if (pkt.dts != AV_NOPTS_VALUE)
2443  pkt.dts = av_rescale_q(pkt.dts, ist->time_base,
2444  ost->time_base);
2445  if (pkt.pts != AV_NOPTS_VALUE)
2446  pkt.pts = av_rescale_q(pkt.pts, ist->time_base,
2447  ost->time_base);
2448  pkt.duration = av_rescale_q(pkt.duration, ist->time_base,
2449  ost->time_base);
2450  if ((ret = av_write_frame(ctx, &pkt)) < 0) {
2451  http_log("Error writing frame to output for stream '%s': %s\n",
2452  c->stream->filename, av_err2str(ret));
2454  }
2455 
2456  av_freep(&c->pb_buffer);
2457  len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2458  ctx->pb = NULL;
2459  c->cur_frame_bytes = len;
2460  c->buffer_ptr = c->pb_buffer;
2461  c->buffer_end = c->pb_buffer + len;
2462 
2463  codec->frame_number++;
2464  if (len == 0) {
2465  av_packet_unref(&pkt);
2466  goto redo;
2467  }
2468  }
2469  av_packet_unref(&pkt);
2470  }
2471  }
2472  break;
2473  default:
2475  /* last packet test ? */
2476  if (c->last_packet_sent || c->is_packetized)
2477  return -1;
2478  ctx = &c->fmt_ctx;
2479  /* prepare header */
2480  if (avio_open_dyn_buf(&ctx->pb) < 0) {
2481  /* XXX: potential leak */
2482  return -1;
2483  }
2484  c->fmt_ctx.pb->seekable = 0;
2485  av_write_trailer(ctx);
2486  len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2487  c->buffer_ptr = c->pb_buffer;
2488  c->buffer_end = c->pb_buffer + len;
2489 
2490  c->last_packet_sent = 1;
2491  break;
2492  }
2493  return 0;
2494 }
2495 
2496 /* should convert the format at the same time */
2497 /* send data starting at c->buffer_ptr to the output connection
2498  * (either UDP or TCP)
2499  */
2501 {
2502  int len, ret;
2503 
2504  for(;;) {
2505  if (c->buffer_ptr >= c->buffer_end) {
2506  ret = http_prepare_data(c);
2507  if (ret < 0)
2508  return -1;
2509  else if (ret)
2510  /* state change requested */
2511  break;
2512  } else {
2513  if (c->is_packetized) {
2514  /* RTP data output */
2515  len = c->buffer_end - c->buffer_ptr;
2516  if (len < 4) {
2517  /* fail safe - should never happen */
2518  fail1:
2519  c->buffer_ptr = c->buffer_end;
2520  return 0;
2521  }
2522  len = (c->buffer_ptr[0] << 24) |
2523  (c->buffer_ptr[1] << 16) |
2524  (c->buffer_ptr[2] << 8) |
2525  (c->buffer_ptr[3]);
2526  if (len > (c->buffer_end - c->buffer_ptr))
2527  goto fail1;
2528  if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2529  /* nothing to send yet: we can wait */
2530  return 0;
2531  }
2532 
2533  c->data_count += len;
2535  if (c->stream)
2536  c->stream->bytes_served += len;
2537 
2539  /* RTP packets are sent inside the RTSP TCP connection */
2540  AVIOContext *pb;
2541  int interleaved_index, size;
2542  uint8_t header[4];
2543  HTTPContext *rtsp_c;
2544 
2545  rtsp_c = c->rtsp_c;
2546  /* if no RTSP connection left, error */
2547  if (!rtsp_c)
2548  return -1;
2549  /* if already sending something, then wait. */
2550  if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2551  break;
2552  if (avio_open_dyn_buf(&pb) < 0)
2553  goto fail1;
2554  interleaved_index = c->packet_stream_index * 2;
2555  /* RTCP packets are sent at odd indexes */
2556  if (c->buffer_ptr[1] == 200)
2557  interleaved_index++;
2558  /* write RTSP TCP header */
2559  header[0] = '$';
2560  header[1] = interleaved_index;
2561  header[2] = len >> 8;
2562  header[3] = len;
2563  avio_write(pb, header, 4);
2564  /* write RTP packet data */
2565  c->buffer_ptr += 4;
2566  avio_write(pb, c->buffer_ptr, len);
2567  size = avio_close_dyn_buf(pb, &c->packet_buffer);
2568  /* prepare asynchronous TCP sending */
2569  rtsp_c->packet_buffer_ptr = c->packet_buffer;
2570  rtsp_c->packet_buffer_end = c->packet_buffer + size;
2571  c->buffer_ptr += len;
2572 
2573  /* send everything we can NOW */
2574  len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2575  rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2576  if (len > 0)
2577  rtsp_c->packet_buffer_ptr += len;
2578  if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2579  /* if we could not send all the data, we will
2580  * send it later, so a new state is needed to
2581  * "lock" the RTSP TCP connection */
2582  rtsp_c->state = RTSPSTATE_SEND_PACKET;
2583  break;
2584  } else
2585  /* all data has been sent */
2586  av_freep(&c->packet_buffer);
2587  } else {
2588  /* send RTP packet directly in UDP */
2589  c->buffer_ptr += 4;
2591  c->buffer_ptr, len);
2592  c->buffer_ptr += len;
2593  /* here we continue as we can send several packets
2594  * per 10 ms slot */
2595  }
2596  } else {
2597  /* TCP data output */
2598  len = send(c->fd, c->buffer_ptr,
2599  c->buffer_end - c->buffer_ptr, 0);
2600  if (len < 0) {
2601  if (ff_neterrno() != AVERROR(EAGAIN) &&
2602  ff_neterrno() != AVERROR(EINTR))
2603  /* error : close connection */
2604  return -1;
2605  else
2606  return 0;
2607  }
2608  c->buffer_ptr += len;
2609 
2610  c->data_count += len;
2612  if (c->stream)
2613  c->stream->bytes_served += len;
2614  break;
2615  }
2616  }
2617  } /* for(;;) */
2618  return 0;
2619 }
2620 
2622 {
2623  int fd;
2624  int ret;
2625  int64_t ret64;
2626 
2627  if (c->stream->feed_opened) {
2628  http_log("Stream feed '%s' was not opened\n",
2629  c->stream->feed_filename);
2630  return AVERROR(EINVAL);
2631  }
2632 
2633  /* Don't permit writing to this one */
2634  if (c->stream->readonly) {
2635  http_log("Cannot write to read-only file '%s'\n",
2636  c->stream->feed_filename);
2637  return AVERROR(EINVAL);
2638  }
2639 
2640  /* open feed */
2641  fd = open(c->stream->feed_filename, O_RDWR);
2642  if (fd < 0) {
2643  ret = AVERROR(errno);
2644  http_log("Could not open feed file '%s': %s\n",
2645  c->stream->feed_filename, strerror(errno));
2646  return ret;
2647  }
2648  c->feed_fd = fd;
2649 
2650  if (c->stream->truncate) {
2651  /* truncate feed file */
2653  http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2654  if (ftruncate(c->feed_fd, FFM_PACKET_SIZE) < 0) {
2655  ret = AVERROR(errno);
2656  http_log("Error truncating feed file '%s': %s\n",
2657  c->stream->feed_filename, strerror(errno));
2658  return ret;
2659  }
2660  } else {
2661  ret64 = ffm_read_write_index(fd);
2662  if (ret64 < 0) {
2663  http_log("Error reading write index from feed file '%s': %s\n",
2664  c->stream->feed_filename, strerror(errno));
2665  return ret64;
2666  }
2667  c->stream->feed_write_index = ret64;
2668  }
2669 
2671  FFM_PACKET_SIZE);
2672  c->stream->feed_size = lseek(fd, 0, SEEK_END);
2673  lseek(fd, 0, SEEK_SET);
2674 
2675  /* init buffer input */
2676  c->buffer_ptr = c->buffer;
2677  c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2678  c->stream->feed_opened = 1;
2679  c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2680  return 0;
2681 }
2682 
2684 {
2685  HTTPContext *c1;
2686  int len, loop_run = 0;
2687 
2688  while (c->chunked_encoding && !c->chunk_size &&
2689  c->buffer_end > c->buffer_ptr) {
2690  /* read chunk header, if present */
2691  len = recv(c->fd, c->buffer_ptr, 1, 0);
2692 
2693  if (len < 0) {
2694  if (ff_neterrno() != AVERROR(EAGAIN) &&
2695  ff_neterrno() != AVERROR(EINTR))
2696  /* error : close connection */
2697  goto fail;
2698  return 0;
2699  } else if (len == 0) {
2700  /* end of connection : close it */
2701  goto fail;
2702  } else if (c->buffer_ptr - c->buffer >= 2 &&
2703  !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2704  c->chunk_size = strtol(c->buffer, 0, 16);
2705  if (c->chunk_size == 0) // end of stream
2706  goto fail;
2707  c->buffer_ptr = c->buffer;
2708  break;
2709  } else if (++loop_run > 10)
2710  /* no chunk header, abort */
2711  goto fail;
2712  else
2713  c->buffer_ptr++;
2714  }
2715 
2716  if (c->buffer_end > c->buffer_ptr) {
2717  len = recv(c->fd, c->buffer_ptr,
2718  FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2719  if (len < 0) {
2720  if (ff_neterrno() != AVERROR(EAGAIN) &&
2721  ff_neterrno() != AVERROR(EINTR))
2722  /* error : close connection */
2723  goto fail;
2724  } else if (len == 0)
2725  /* end of connection : close it */
2726  goto fail;
2727  else {
2728  c->chunk_size -= len;
2729  c->buffer_ptr += len;
2730  c->data_count += len;
2732  }
2733  }
2734 
2735  if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2736  if (c->buffer[0] != 'f' ||
2737  c->buffer[1] != 'm') {
2738  http_log("Feed stream has become desynchronized -- disconnecting\n");
2739  goto fail;
2740  }
2741  }
2742 
2743  if (c->buffer_ptr >= c->buffer_end) {
2744  FFServerStream *feed = c->stream;
2745  /* a packet has been received : write it in the store, except
2746  * if header */
2747  if (c->data_count > FFM_PACKET_SIZE) {
2748  /* XXX: use llseek or url_seek
2749  * XXX: Should probably fail? */
2750  if (lseek(c->feed_fd, feed->feed_write_index, SEEK_SET) == -1)
2751  http_log("Seek to %"PRId64" failed\n", feed->feed_write_index);
2752 
2753  if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2754  http_log("Error writing to feed file: %s\n", strerror(errno));
2755  goto fail;
2756  }
2757 
2759  /* update file size */
2760  if (feed->feed_write_index > c->stream->feed_size)
2761  feed->feed_size = feed->feed_write_index;
2762 
2763  /* handle wrap around if max file size reached */
2764  if (c->stream->feed_max_size &&
2765  feed->feed_write_index >= c->stream->feed_max_size)
2767 
2768  /* write index */
2769  if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2770  http_log("Error writing index to feed file: %s\n",
2771  strerror(errno));
2772  goto fail;
2773  }
2774 
2775  /* wake up any waiting connections */
2776  for(c1 = first_http_ctx; c1; c1 = c1->next) {
2777  if (c1->state == HTTPSTATE_WAIT_FEED &&
2778  c1->stream->feed == c->stream->feed)
2779  c1->state = HTTPSTATE_SEND_DATA;
2780  }
2781  } else {
2782  /* We have a header in our hands that contains useful data */
2784  AVIOContext *pb;
2785  AVInputFormat *fmt_in;
2786  int i;
2787 
2788  if (!s)
2789  goto fail;
2790 
2791  /* use feed output format name to find corresponding input format */
2792  fmt_in = av_find_input_format(feed->fmt->name);
2793  if (!fmt_in)
2794  goto fail;
2795 
2796  pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
2797  0, NULL, NULL, NULL, NULL);
2798  if (!pb)
2799  goto fail;
2800 
2801  pb->seekable = 0;
2802 
2803  s->pb = pb;
2804  if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) {
2805  av_freep(&pb);
2806  goto fail;
2807  }
2808 
2809  /* Now we have the actual streams */
2810  if (s->nb_streams != feed->nb_streams) {
2812  av_freep(&pb);
2813  http_log("Feed '%s' stream number does not match registered feed\n",
2814  c->stream->feed_filename);
2815  goto fail;
2816  }
2817 
2818  for (i = 0; i < s->nb_streams; i++) {
2819  AVStream *fst = feed->streams[i];
2820  AVStream *st = s->streams[i];
2821  avcodec_copy_context(fst->codec, st->codec);
2822  }
2823 
2825  av_freep(&pb);
2826  }
2827  c->buffer_ptr = c->buffer;
2828  }
2829 
2830  return 0;
2831  fail:
2832  c->stream->feed_opened = 0;
2833  close(c->feed_fd);
2834  /* wake up any waiting connections to stop waiting for feed */
2835  for(c1 = first_http_ctx; c1; c1 = c1->next) {
2836  if (c1->state == HTTPSTATE_WAIT_FEED &&
2837  c1->stream->feed == c->stream->feed)
2839  }
2840  return -1;
2841 }
2842 
2843 /********************************************************************/
2844 /* RTSP handling */
2845 
2846 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2847 {
2848  const char *str;
2849  time_t ti;
2850  struct tm *tm;
2851  char buf2[32];
2852 
2853  str = RTSP_STATUS_CODE2STRING(error_number);
2854  if (!str)
2855  str = "Unknown Error";
2856 
2857  avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2858  avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2859 
2860  /* output GMT time */
2861  ti = time(NULL);
2862  tm = gmtime(&ti);
2863  strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
2864  avio_printf(c->pb, "Date: %s GMT\r\n", buf2);
2865 }
2866 
2867 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2868 {
2869  rtsp_reply_header(c, error_number);
2870  avio_printf(c->pb, "\r\n");
2871 }
2872 
2874 {
2875  const char *p, *p1, *p2;
2876  char cmd[32];
2877  char url[1024];
2878  char protocol[32];
2879  char line[1024];
2880  int len;
2881  RTSPMessageHeader header1 = { 0 }, *header = &header1;
2882 
2883  c->buffer_ptr[0] = '\0';
2884  p = c->buffer;
2885 
2886  get_word(cmd, sizeof(cmd), &p);
2887  get_word(url, sizeof(url), &p);
2888  get_word(protocol, sizeof(protocol), &p);
2889 
2890  av_strlcpy(c->method, cmd, sizeof(c->method));
2891  av_strlcpy(c->url, url, sizeof(c->url));
2892  av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2893 
2894  if (avio_open_dyn_buf(&c->pb) < 0) {
2895  /* XXX: cannot do more */
2896  c->pb = NULL; /* safety */
2897  return -1;
2898  }
2899 
2900  /* check version name */
2901  if (strcmp(protocol, "RTSP/1.0")) {
2903  goto the_end;
2904  }
2905 
2906  /* parse each header line */
2907  /* skip to next line */
2908  while (*p != '\n' && *p != '\0')
2909  p++;
2910  if (*p == '\n')
2911  p++;
2912  while (*p != '\0') {
2913  p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
2914  if (!p1)
2915  break;
2916  p2 = p1;
2917  if (p2 > p && p2[-1] == '\r')
2918  p2--;
2919  /* skip empty line */
2920  if (p2 == p)
2921  break;
2922  len = p2 - p;
2923  if (len > sizeof(line) - 1)
2924  len = sizeof(line) - 1;
2925  memcpy(line, p, len);
2926  line[len] = '\0';
2928  p = p1 + 1;
2929  }
2930 
2931  /* handle sequence number */
2932  c->seq = header->seq;
2933 
2934  if (!strcmp(cmd, "DESCRIBE"))
2935  rtsp_cmd_describe(c, url);
2936  else if (!strcmp(cmd, "OPTIONS"))
2937  rtsp_cmd_options(c, url);
2938  else if (!strcmp(cmd, "SETUP"))
2939  rtsp_cmd_setup(c, url, header);
2940  else if (!strcmp(cmd, "PLAY"))
2941  rtsp_cmd_play(c, url, header);
2942  else if (!strcmp(cmd, "PAUSE"))
2943  rtsp_cmd_interrupt(c, url, header, 1);
2944  else if (!strcmp(cmd, "TEARDOWN"))
2945  rtsp_cmd_interrupt(c, url, header, 0);
2946  else
2948 
2949  the_end:
2950  len = avio_close_dyn_buf(c->pb, &c->pb_buffer);
2951  c->pb = NULL; /* safety */
2952  if (len < 0)
2953  /* XXX: cannot do more */
2954  return -1;
2955 
2956  c->buffer_ptr = c->pb_buffer;
2957  c->buffer_end = c->pb_buffer + len;
2959  return 0;
2960 }
2961 
2962 static int prepare_sdp_description(FFServerStream *stream, uint8_t **pbuffer,
2963  struct in_addr my_ip)
2964 {
2965  AVFormatContext *avc;
2966  AVStream *avs = NULL;
2967  AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);
2968  AVDictionaryEntry *entry = av_dict_get(stream->metadata, "title", NULL, 0);
2969  int i;
2970 
2971  *pbuffer = NULL;
2972 
2973  avc = avformat_alloc_context();
2974  if (!avc || !rtp_format)
2975  return -1;
2976 
2977  avc->oformat = rtp_format;
2978  av_dict_set(&avc->metadata, "title",
2979  entry ? entry->value : "No Title", 0);
2980  avc->nb_streams = stream->nb_streams;
2981  if (stream->is_multicast) {
2982  snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2983  inet_ntoa(stream->multicast_ip),
2984  stream->multicast_port, stream->multicast_ttl);
2985  } else
2986  snprintf(avc->filename, 1024, "rtp://0.0.0.0");
2987 
2988  avc->streams = av_malloc_array(avc->nb_streams, sizeof(*avc->streams));
2989  if (!avc->streams)
2990  goto sdp_done;
2991 
2992  avs = av_malloc_array(avc->nb_streams, sizeof(*avs));
2993  if (!avs)
2994  goto sdp_done;
2995 
2996  for(i = 0; i < stream->nb_streams; i++) {
2997  avc->streams[i] = &avs[i];
2998  avc->streams[i]->codec = stream->streams[i]->codec;
2999  avcodec_parameters_from_context(stream->streams[i]->codecpar, stream->streams[i]->codec);
3000  avc->streams[i]->codecpar = stream->streams[i]->codecpar;
3001  }
3002  *pbuffer = av_mallocz(2048);
3003  if (!*pbuffer)
3004  goto sdp_done;
3005  av_sdp_create(&avc, 1, *pbuffer, 2048);
3006 
3007  sdp_done:
3008  av_freep(&avc->streams);
3009  av_dict_free(&avc->metadata);
3010  av_free(avc);
3011  av_free(avs);
3012 
3013  return *pbuffer ? strlen(*pbuffer) : AVERROR(ENOMEM);
3014 }
3015 
3016 static void rtsp_cmd_options(HTTPContext *c, const char *url)
3017 {
3018  /* rtsp_reply_header(c, RTSP_STATUS_OK); */
3019  avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
3020  avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
3021  avio_printf(c->pb, "Public: %s\r\n",
3022  "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
3023  avio_printf(c->pb, "\r\n");
3024 }
3025 
3026 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
3027 {
3028  FFServerStream *stream;
3029  char path1[1024];
3030  const char *path;
3031  uint8_t *content;
3032  int content_length;
3033  socklen_t len;
3034  struct sockaddr_in my_addr;
3035 
3036  /* find which URL is asked */
3037  av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3038  path = path1;
3039  if (*path == '/')
3040  path++;
3041 
3042  for(stream = config.first_stream; stream; stream = stream->next) {
3043  if (!stream->is_feed &&
3044  stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
3045  !strcmp(path, stream->filename)) {
3046  goto found;
3047  }
3048  }
3049  /* no stream found */
3051  return;
3052 
3053  found:
3054  /* prepare the media description in SDP format */
3055 
3056  /* get the host IP */
3057  len = sizeof(my_addr);
3058  getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
3059  content_length = prepare_sdp_description(stream, &content,
3060  my_addr.sin_addr);
3061  if (content_length < 0) {
3063  return;
3064  }
3066  avio_printf(c->pb, "Content-Base: %s/\r\n", url);
3067  avio_printf(c->pb, "Content-Type: application/sdp\r\n");
3068  avio_printf(c->pb, "Content-Length: %d\r\n", content_length);
3069  avio_printf(c->pb, "\r\n");
3070  avio_write(c->pb, content, content_length);
3071  av_free(content);
3072 }
3073 
3074 static HTTPContext *find_rtp_session(const char *session_id)
3075 {
3076  HTTPContext *c;
3077 
3078  if (session_id[0] == '\0')
3079  return NULL;
3080 
3081  for(c = first_http_ctx; c; c = c->next) {
3082  if (!strcmp(c->session_id, session_id))
3083  return c;
3084  }
3085  return NULL;
3086 }
3087 
3089 {
3091  int i;
3092 
3093  for(i=0;i<h->nb_transports;i++) {
3094  th = &h->transports[i];
3095  if (th->lower_transport == lower_transport)
3096  return th;
3097  }
3098  return NULL;
3099 }
3100 
3101 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3103 {
3104  FFServerStream *stream;
3105  int stream_index, rtp_port, rtcp_port;
3106  char buf[1024];
3107  char path1[1024];
3108  const char *path;
3109  HTTPContext *rtp_c;
3111  struct sockaddr_in dest_addr;
3112  RTSPActionServerSetup setup;
3113 
3114  /* find which URL is asked */
3115  av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3116  path = path1;
3117  if (*path == '/')
3118  path++;
3119 
3120  /* now check each stream */
3121  for(stream = config.first_stream; stream; stream = stream->next) {
3122  if (stream->is_feed || !stream->fmt ||
3123  strcmp(stream->fmt->name, "rtp")) {
3124  continue;
3125  }
3126  /* accept aggregate filenames only if single stream */
3127  if (!strcmp(path, stream->filename)) {
3128  if (stream->nb_streams != 1) {
3130  return;
3131  }
3132  stream_index = 0;
3133  goto found;
3134  }
3135 
3136  for(stream_index = 0; stream_index < stream->nb_streams;
3137  stream_index++) {
3138  snprintf(buf, sizeof(buf), "%s/streamid=%d",
3139  stream->filename, stream_index);
3140  if (!strcmp(path, buf))
3141  goto found;
3142  }
3143  }
3144  /* no stream found */
3145  rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3146  return;
3147  found:
3148 
3149  /* generate session id if needed */
3150  if (h->session_id[0] == '\0') {
3151  unsigned random0 = av_lfg_get(&random_state);
3152  unsigned random1 = av_lfg_get(&random_state);
3153  snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3154  random0, random1);
3155  }
3156 
3157  /* find RTP session, and create it if none found */
3158  rtp_c = find_rtp_session(h->session_id);
3159  if (!rtp_c) {
3160  /* always prefer UDP */
3162  if (!th) {
3164  if (!th) {
3166  return;
3167  }
3168  }
3169 
3170  rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3171  th->lower_transport);
3172  if (!rtp_c) {
3174  return;
3175  }
3176 
3177  /* open input stream */
3178  if (open_input_stream(rtp_c, "") < 0) {
3180  return;
3181  }
3182  }
3183 
3184  /* test if stream is OK (test needed because several SETUP needs
3185  * to be done for a given file) */
3186  if (rtp_c->stream != stream) {
3188  return;
3189  }
3190 
3191  /* test if stream is already set up */
3192  if (rtp_c->rtp_ctx[stream_index]) {
3194  return;
3195  }
3196 
3197  /* check transport */
3198  th = find_transport(h, rtp_c->rtp_protocol);
3199  if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3200  th->client_port_min <= 0)) {
3202  return;
3203  }
3204 
3205  /* setup default options */
3206  setup.transport_option[0] = '\0';
3207  dest_addr = rtp_c->from_addr;
3208  dest_addr.sin_port = htons(th->client_port_min);
3209 
3210  /* setup stream */
3211  if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3213  return;
3214  }
3215 
3216  /* now everything is OK, so we can send the connection parameters */
3218  /* session ID */
3219  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3220 
3221  switch(rtp_c->rtp_protocol) {
3223  rtp_port = ff_rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3224  rtcp_port = ff_rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3225  avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3226  "client_port=%d-%d;server_port=%d-%d",
3228  rtp_port, rtcp_port);
3229  break;
3231  avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3232  stream_index * 2, stream_index * 2 + 1);
3233  break;
3234  default:
3235  break;
3236  }
3237  if (setup.transport_option[0] != '\0')
3238  avio_printf(c->pb, ";%s", setup.transport_option);
3239  avio_printf(c->pb, "\r\n");
3240 
3241 
3242  avio_printf(c->pb, "\r\n");
3243 }
3244 
3245 
3246 /**
3247  * find an RTP connection by using the session ID. Check consistency
3248  * with filename
3249  */
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
3274  * if nb_streams>1? */
3275  return rtp_c;
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,
3311  RTSPMessageHeader *h, int pause_only)
3312 {
3313  HTTPContext *rtp_c;
3314 
3315  rtp_c = find_rtp_session_with_url(url, h->session_id);
3316  if (!rtp_c) {
3318  return;
3319  }
3320 
3321  if (pause_only) {
3322  if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3323  rtp_c->state != HTTPSTATE_WAIT_FEED) {
3325  return;
3326  }
3327  rtp_c->state = HTTPSTATE_READY;
3328  rtp_c->first_pts = AV_NOPTS_VALUE;
3329  }
3330 
3331  /* now everything is OK, so we can send the connection parameters */
3333  /* session ID */
3334  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3335  avio_printf(c->pb, "\r\n");
3336 
3337  if (!pause_only)
3338  close_connection(rtp_c);
3339 }
3340 
3341 /********************************************************************/
3342 /* RTP handling */
3343 
3344 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3345  FFServerStream *stream,
3346  const char *session_id,
3347  enum RTSPLowerTransport rtp_protocol)
3348 {
3349  HTTPContext *c = NULL;
3350  const char *proto_str;
3351 
3352  /* XXX: should output a warning page when coming
3353  * close to the connection limit */
3354  if (nb_connections >= config.nb_max_connections)
3355  goto fail;
3356 
3357  /* add a new connection */
3358  c = av_mallocz(sizeof(HTTPContext));
3359  if (!c)
3360  goto fail;
3361 
3362  c->fd = -1;
3363  c->poll_entry = NULL;
3364  c->from_addr = *from_addr;
3366  c->buffer = av_malloc(c->buffer_size);
3367  if (!c->buffer)
3368  goto fail;
3369  nb_connections++;
3370  c->stream = stream;
3371  av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3372  c->state = HTTPSTATE_READY;
3373  c->is_packetized = 1;
3374  c->rtp_protocol = rtp_protocol;
3375 
3376  /* protocol is shown in statistics */
3377  switch(c->rtp_protocol) {
3379  proto_str = "MCAST";
3380  break;
3382  proto_str = "UDP";
3383  break;
3385  proto_str = "TCP";
3386  break;
3387  default:
3388  proto_str = "???";
3389  break;
3390  }
3391  av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3392  av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3393 
3394  current_bandwidth += stream->bandwidth;
3395 
3396  c->next = first_http_ctx;
3397  first_http_ctx = c;
3398  return c;
3399 
3400  fail:
3401  if (c) {
3402  av_freep(&c->buffer);
3403  av_free(c);
3404  }
3405  return NULL;
3406 }
3407 
3408 /**
3409  * add a new RTP stream in an RTP connection (used in RTSP SETUP
3410  * command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3411  * used.
3412  */
3414  int stream_index, struct sockaddr_in *dest_addr,
3415  HTTPContext *rtsp_c)
3416 {
3418  AVStream *st;
3419  char *ipaddr;
3420  URLContext *h = NULL;
3421  uint8_t *dummy_buf;
3422  int max_packet_size;
3423  void *st_internal;
3424 
3425  /* now we can open the relevant output stream */
3426  ctx = avformat_alloc_context();
3427  if (!ctx)
3428  return -1;
3429  ctx->oformat = av_guess_format("rtp", NULL, NULL);
3430 
3431  st = avformat_new_stream(ctx, NULL);
3432  if (!st)
3433  goto fail;
3434 
3435  av_freep(&st->codec);
3436  av_freep(&st->info);
3437  st_internal = st->internal;
3438 
3439  if (!c->stream->feed ||
3440  c->stream->feed == c->stream)
3441  memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3442  else
3443  memcpy(st,
3444  c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3445  sizeof(AVStream));
3446  st->priv_data = NULL;
3447  st->internal = st_internal;
3448 
3449  /* build destination RTP address */
3450  ipaddr = inet_ntoa(dest_addr->sin_addr);
3451 
3452  switch(c->rtp_protocol) {
3455  /* RTP/UDP case */
3456 
3457  /* XXX: also pass as parameter to function ? */
3458  if (c->stream->is_multicast) {
3459  int ttl;
3460  ttl = c->stream->multicast_ttl;
3461  if (!ttl)
3462  ttl = 16;
3463  snprintf(ctx->filename, sizeof(ctx->filename),
3464  "rtp://%s:%d?multicast=1&ttl=%d",
3465  ipaddr, ntohs(dest_addr->sin_port), ttl);
3466  } else {
3467  snprintf(ctx->filename, sizeof(ctx->filename),
3468  "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3469  }
3470 
3471  if (ffurl_open(&h, ctx->filename, AVIO_FLAG_WRITE, NULL, NULL) < 0)
3472  goto fail;
3473  c->rtp_handles[stream_index] = h;
3474  max_packet_size = h->max_packet_size;
3475  break;
3477  /* RTP/TCP case */
3478  c->rtsp_c = rtsp_c;
3479  max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3480  break;
3481  default:
3482  goto fail;
3483  }
3484 
3485  http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3486  ipaddr, ntohs(dest_addr->sin_port),
3487  c->stream->filename, stream_index, c->protocol);
3488 
3489  /* normally, no packets should be output here, but the packet size may
3490  * be checked */
3491  if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0)
3492  /* XXX: close stream */
3493  goto fail;
3494 
3495  if (avformat_write_header(ctx, NULL) < 0) {
3496  fail:
3497  if (h)
3498  ffurl_close(h);
3499  av_free(st);
3500  av_free(ctx);
3501  return -1;
3502  }
3503  avio_close_dyn_buf(ctx->pb, &dummy_buf);
3504  ctx->pb = NULL;
3505  av_free(dummy_buf);
3506 
3507  c->rtp_ctx[stream_index] = ctx;
3508  return 0;
3509 }
3510 
3511 /********************************************************************/
3512 /* ffserver initialization */
3513 
3514 /* FIXME: This code should use avformat_new_stream() */
3516  AVCodecContext *codec, int copy)
3517 {
3518  AVStream *fst;
3519 
3520  if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams))
3521  return NULL;
3522 
3523  fst = av_mallocz(sizeof(AVStream));
3524  if (!fst)
3525  return NULL;
3526  if (copy) {
3527  fst->codec = avcodec_alloc_context3(codec->codec);
3528  if (!fst->codec) {
3529  av_free(fst);
3530  return NULL;
3531  }
3532  avcodec_copy_context(fst->codec, codec);
3533  } else
3534  /* live streams must use the actual feed's codec since it may be
3535  * updated later to carry extradata needed by them.
3536  */
3537  fst->codec = codec;
3538 
3539  fst->priv_data = av_mallocz(sizeof(FeedData));
3540  fst->internal = av_mallocz(sizeof(*fst->internal));
3543  fst->index = stream->nb_streams;
3544  avpriv_set_pts_info(fst, 33, 1, 90000);
3546  stream->streams[stream->nb_streams++] = fst;
3547  return fst;
3548 }
3549 
3550 /* return the stream number in the feed */
3551 static int add_av_stream(FFServerStream *feed, AVStream *st)
3552 {
3553  AVStream *fst;
3554  AVCodecContext *av, *av1;
3555  int i;
3556 
3557  av = st->codec;
3558  for(i=0;i<feed->nb_streams;i++) {
3559  av1 = feed->streams[i]->codec;
3560  if (av1->codec_id == av->codec_id &&
3561  av1->codec_type == av->codec_type &&
3562  av1->bit_rate == av->bit_rate) {
3563 
3564  switch(av->codec_type) {
3565  case AVMEDIA_TYPE_AUDIO:
3566  if (av1->channels == av->channels &&
3567  av1->sample_rate == av->sample_rate)
3568  return i;
3569  break;
3570  case AVMEDIA_TYPE_VIDEO:
3571  if (av1->width == av->width &&
3572  av1->height == av->height &&
3573  av1->time_base.den == av->time_base.den &&
3574  av1->time_base.num == av->time_base.num &&
3575  av1->gop_size == av->gop_size)
3576  return i;
3577  break;
3578  default:
3579  abort();
3580  }
3581  }
3582  }
3583 
3584  fst = add_av_stream1(feed, av, 0);
3585  if (!fst)
3586  return -1;
3590  return feed->nb_streams - 1;
3591 }
3592 
3593 static void remove_stream(FFServerStream *stream)
3594 {
3595  FFServerStream **ps;
3596  ps = &config.first_stream;
3597  while (*ps) {
3598  if (*ps == stream)
3599  *ps = (*ps)->next;
3600  else
3601  ps = &(*ps)->next;
3602  }
3603 }
3604 
3605 /* specific MPEG4 handling : we extract the raw parameters */
3607 {
3608  int mpeg4_count, i, size;
3609  AVPacket pkt;
3610  AVStream *st;
3611  const uint8_t *p;
3612 
3614 
3615  mpeg4_count = 0;
3616  for(i=0;i<infile->nb_streams;i++) {
3617  st = infile->streams[i];
3618  if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3619  st->codec->extradata_size == 0) {
3620  mpeg4_count++;
3621  }
3622  }
3623  if (!mpeg4_count)
3624  return;
3625 
3626  printf("MPEG4 without extra data: trying to find header in %s\n",
3627  infile->filename);
3628  while (mpeg4_count > 0) {
3629  if (av_read_frame(infile, &pkt) < 0)
3630  break;
3631  st = infile->streams[pkt.stream_index];
3632  if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3633  st->codec->extradata_size == 0) {
3634  av_freep(&st->codec->extradata);
3635  /* fill extradata with the header */
3636  /* XXX: we make hard suppositions here ! */
3637  p = pkt.data;
3638  while (p < pkt.data + pkt.size - 4) {
3639  /* stop when vop header is found */
3640  if (p[0] == 0x00 && p[1] == 0x00 &&
3641  p[2] == 0x01 && p[3] == 0xb6) {
3642  size = p - pkt.data;
3643  st->codec->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE);
3644  st->codec->extradata_size = size;
3645  memcpy(st->codec->extradata, pkt.data, size);
3646  break;
3647  }
3648  p++;
3649  }
3650  mpeg4_count--;
3651  }
3652  av_packet_unref(&pkt);
3653  }
3654 }
3655 
3656 /* compute the needed AVStream for each file */
3657 static void build_file_streams(void)
3658 {
3659  FFServerStream *stream;
3660  AVFormatContext *infile;
3661  int i, ret;
3662 
3663  /* gather all streams */
3664  for(stream = config.first_stream; stream; stream = stream->next) {
3665  infile = NULL;
3666 
3667  if (stream->stream_type != STREAM_TYPE_LIVE || stream->feed)
3668  continue;
3669 
3670  /* the stream comes from a file */
3671  /* try to open the file */
3672  /* open stream */
3673 
3674 
3675  /* specific case: if transport stream output to RTP,
3676  * we use a raw transport stream reader */
3677  if (stream->fmt && !strcmp(stream->fmt->name, "rtp"))
3678  av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0);
3679 
3680  if (!stream->feed_filename[0]) {
3681  http_log("Unspecified feed file for stream '%s'\n",
3682  stream->filename);
3683  goto fail;
3684  }
3685 
3686  http_log("Opening feed file '%s' for stream '%s'\n",
3687  stream->feed_filename, stream->filename);
3688 
3689  ret = avformat_open_input(&infile, stream->feed_filename,
3690  stream->ifmt, &stream->in_opts);
3691  if (ret < 0) {
3692  http_log("Could not open '%s': %s\n", stream->feed_filename,
3693  av_err2str(ret));
3694  /* remove stream (no need to spend more time on it) */
3695  fail:
3696  remove_stream(stream);
3697  } else {
3698  /* find all the AVStreams inside and reference them in
3699  * 'stream' */
3700  if (avformat_find_stream_info(infile, NULL) < 0) {
3701  http_log("Could not find codec parameters from '%s'\n",
3702  stream->feed_filename);
3703  avformat_close_input(&infile);
3704  goto fail;
3705  }
3706  extract_mpeg4_header(infile);
3707 
3708  for(i=0;i<infile->nb_streams;i++)
3709  add_av_stream1(stream, infile->streams[i]->codec, 1);
3710 
3711  avformat_close_input(&infile);
3712  }
3713  }
3714 }
3715 
3716 static inline
3718 {
3719  int matches = 1;
3720 
3721 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3723  http_log("Codecs do not match for stream %d\n", stream);
3724  matches = 0;
3725  } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3726  http_log("Codec bitrates do not match for stream %d\n", stream);
3727  matches = 0;
3728  } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
3729  if (CHECK_CODEC(time_base.den) ||
3730  CHECK_CODEC(time_base.num) ||
3731  CHECK_CODEC(width) ||
3732  CHECK_CODEC(height)) {
3733  http_log("Codec width, height or framerate do not match for stream %d\n", stream);
3734  matches = 0;
3735  }
3736  } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
3737  if (CHECK_CODEC(sample_rate) ||
3738  CHECK_CODEC(channels) ||
3740  http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", stream);
3741  matches = 0;
3742  }
3743  } else {
3744  http_log("Unknown codec type for stream %d\n", stream);
3745  matches = 0;
3746  }
3747 
3748  return matches;
3749 }
3750 
3751 /* compute the needed AVStream for each feed */
3752 static int build_feed_streams(void)
3753 {
3754  FFServerStream *stream, *feed;
3755  int i, fd;
3756 
3757  /* gather all streams */
3758  for(stream = config.first_stream; stream; stream = stream->next) {
3759  feed = stream->feed;
3760  if (!feed)
3761  continue;
3762 
3763  if (stream->is_feed) {
3764  for(i=0;i<stream->nb_streams;i++)
3765  stream->feed_streams[i] = i;
3766  continue;
3767  }
3768  /* we handle a stream coming from a feed */
3769  for(i=0;i<stream->nb_streams;i++)
3770  stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3771  }
3772 
3773  /* create feed files if needed */
3774  for(feed = config.first_feed; feed; feed = feed->next_feed) {
3775 
3776  if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) {
3777  AVFormatContext *s = NULL;
3778  int matches = 0;
3779 
3780  /* See if it matches */
3781 
3782  if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) < 0) {
3783  http_log("Deleting feed file '%s' as it appears "
3784  "to be corrupt\n",
3785  feed->feed_filename);
3786  goto drop;
3787  }
3788 
3789  /* set buffer size */
3790  if (ffio_set_buf_size(s->pb, FFM_PACKET_SIZE) < 0) {
3791  http_log("Failed to set buffer size\n");
3793  goto bail;
3794  }
3795 
3796  /* Now see if it matches */
3797  if (s->nb_streams != feed->nb_streams) {
3798  http_log("Deleting feed file '%s' as stream counts "
3799  "differ (%d != %d)\n",
3800  feed->feed_filename, s->nb_streams, feed->nb_streams);
3801  goto drop;
3802  }
3803 
3804  matches = 1;
3805  for(i=0;i<s->nb_streams;i++) {
3806  AVStream *sf, *ss;
3807 
3808  sf = feed->streams[i];
3809  ss = s->streams[i];
3810 
3811  if (sf->index != ss->index || sf->id != ss->id) {
3812  http_log("Index & Id do not match for stream %d (%s)\n",
3813  i, feed->feed_filename);
3814  matches = 0;
3815  break;
3816  }
3817 
3818  matches = check_codec_match (sf->codec, ss->codec, i);
3819  if (!matches)
3820  break;
3821  }
3822 
3823 drop:
3824  if (s)
3826 
3827  if (!matches) {
3828  if (feed->readonly) {
3829  http_log("Unable to delete read-only feed file '%s'\n",
3830  feed->feed_filename);
3831  goto bail;
3832  }
3833  unlink(feed->feed_filename);
3834  }
3835  }
3836 
3837  if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) {
3839 
3840  if (!s) {
3841  http_log("Failed to allocate context\n");
3842  goto bail;
3843  }
3844 
3845  if (feed->readonly) {
3846  http_log("Unable to create feed file '%s' as it is "
3847  "marked readonly\n",
3848  feed->feed_filename);
3850  goto bail;
3851  }
3852 
3853  /* only write the header of the ffm file */
3854  if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) {
3855  http_log("Could not open output feed file '%s'\n",
3856  feed->feed_filename);
3858  goto bail;
3859  }
3860  s->oformat = feed->fmt;
3861  s->nb_streams = feed->nb_streams;
3862  s->streams = feed->streams;
3863  if (avformat_write_header(s, NULL) < 0) {
3864  http_log("Container doesn't support the required parameters\n");
3865  avio_closep(&s->pb);
3866  s->streams = NULL;
3867  s->nb_streams = 0;
3869  goto bail;
3870  }
3871  /* XXX: need better API */
3872  av_freep(&s->priv_data);
3873  avio_closep(&s->pb);
3874  s->streams = NULL;
3875  s->nb_streams = 0;
3877  }
3878 
3879  /* get feed size and write index */
3880  fd = open(feed->feed_filename, O_RDONLY);
3881  if (fd < 0) {
3882  http_log("Could not open output feed file '%s'\n",
3883  feed->feed_filename);
3884  goto bail;
3885  }
3886 
3888  FFM_PACKET_SIZE);
3889  feed->feed_size = lseek(fd, 0, SEEK_END);
3890  /* ensure that we do not wrap before the end of file */
3891  if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3892  feed->feed_max_size = feed->feed_size;
3893 
3894  close(fd);
3895  }
3896  return 0;
3897 
3898 bail:
3899  return -1;
3900 }
3901 
3902 /* compute the bandwidth used by each stream */
3903 static void compute_bandwidth(void)
3904 {
3905  unsigned bandwidth;
3906  int i;
3907  FFServerStream *stream;
3908 
3909  for(stream = config.first_stream; stream; stream = stream->next) {
3910  bandwidth = 0;
3911  for(i=0;i<stream->nb_streams;i++) {
3912  AVStream *st = stream->streams[i];
3913  switch(st->codec->codec_type) {
3914  case AVMEDIA_TYPE_AUDIO:
3915  case AVMEDIA_TYPE_VIDEO:
3916  bandwidth += st->codec->bit_rate;
3917  break;
3918  default:
3919  break;
3920  }
3921  }
3922  stream->bandwidth = (bandwidth + 999) / 1000;
3923  }
3924 }
3925 
3926 static void handle_child_exit(int sig)
3927 {
3928  pid_t pid;
3929  int status;
3930  time_t uptime;
3931 
3932  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
3933  FFServerStream *feed;
3934 
3935  for (feed = config.first_feed; feed; feed = feed->next) {
3936  if (feed->pid != pid)
3937  continue;
3938 
3939  uptime = time(0) - feed->pid_start;
3940  feed->pid = 0;
3941  fprintf(stderr,
3942  "%s: Pid %"PRId64" exited with status %d after %"PRId64" "
3943  "seconds\n",
3944  feed->filename, (int64_t) pid, status, (int64_t)uptime);
3945 
3946  if (uptime < 30)
3947  /* Turn off any more restarts */
3949  }
3950  }
3951 
3953 }
3954 
3955 static void opt_debug(void)
3956 {
3957  config.debug = 1;
3958  snprintf(config.logfilename, sizeof(config.logfilename), "-");
3959 }
3960 
3961 void show_help_default(const char *opt, const char *arg)
3962 {
3963  printf("usage: ffserver [options]\n"
3964  "Hyper fast multi format Audio/Video streaming server\n");
3965  printf("\n");
3966  show_help_options(options, "Main options:", 0, 0, 0);
3967 }
3968 
3969 static const OptionDef options[] = {
3970 #include "cmdutils_common_opts.h"
3971  { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
3972  { "d", 0, {(void*)opt_debug}, "enable debug mode" },
3973  { "f", HAS_ARG | OPT_STRING, {(void*)&config.filename }, "use configfile instead of /etc/ffserver.conf", "configfile" },
3974  { NULL },
3975 };
3976 
3977 int main(int argc, char **argv)
3978 {
3979  struct sigaction sigact = { { 0 } };
3980  int cfg_parsed;
3981  int ret = EXIT_FAILURE;
3982 
3983 
3984  config.filename = av_strdup("/etc/ffserver.conf");
3985 
3986  parse_loglevel(argc, argv, options);
3987  av_register_all();
3989 
3990  show_banner(argc, argv, options);
3991 
3992  my_program_name = argv[0];
3993 
3994  parse_options(NULL, argc, argv, options, NULL);
3995 
3996  unsetenv("http_proxy"); /* Kill the http_proxy */
3997 
3998  av_lfg_init(&random_state, av_get_random_seed());
3999 
4000  sigact.sa_handler = handle_child_exit;
4001  sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4002  sigaction(SIGCHLD, &sigact, 0);
4003 
4004  if ((cfg_parsed = ffserver_parse_ffconfig(config.filename, &config)) < 0) {
4005  fprintf(stderr, "Error reading configuration file '%s': %s\n",
4006  config.filename, av_err2str(cfg_parsed));
4007  goto bail;
4008  }
4009 
4010  /* open log file if needed */
4011  if (config.logfilename[0] != '\0') {
4012  if (!strcmp(config.logfilename, "-"))
4013  logfile = stdout;
4014  else
4015  logfile = fopen(config.logfilename, "a");
4017  }
4018 
4020 
4021  if (build_feed_streams() < 0) {
4022  http_log("Could not setup feed streams\n");
4023  goto bail;
4024  }
4025 
4027 
4028  /* signal init */
4029  signal(SIGPIPE, SIG_IGN);
4030 
4031  if (http_server() < 0) {
4032  http_log("Could not start server\n");
4033  goto bail;
4034  }
4035 
4036  ret=EXIT_SUCCESS;
4037 
4038 bail:
4039  av_freep (&config.filename);
4041  return ret;
4042 }
Definition: lfg.h:25
int avio_open(AVIOContext **s, const char *url, int flags)
Create and initialize a AVIOContext for accessing the resource indicated by url.
Definition: aviobuf.c:1027
static int rtp_new_av_stream(HTTPContext *c, int stream_index, struct sockaddr_in *dest_addr, HTTPContext *rtsp_c)
add a new RTP stream in an RTP connection (used in RTSP SETUP command).
Definition: ffserver.c:3413
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components.
Definition: utils.c:4307
static int validate_acl(FFServerStream *stream, HTTPContext *c)
Definition: ffserver.c:1365
static const char *const http_state[]
Definition: ffserver.c:96
static HTTPContext * find_rtp_session(const char *session_id)
Definition: ffserver.c:3074
int64_t count1
Definition: ffserver.c:126
#define NULL
Definition: coverity.c:32
const struct AVCodec * codec
Definition: avcodec.h:1658
int ffserver_parse_ffconfig(const char *filename, FFServerConfig *config)
static const char * my_program_name
Definition: ffserver.c:251
const char * s
Definition: avisynth_c.h:631
Bytestream IO Context.
Definition: avio.h:147
enum AVCodecID codec_id
Definition: ffmpeg_vaapi.c:149
static void http_log(const char *fmt,...)
Definition: ffserver.c:418
struct sockaddr_in http_addr
int ff_rtp_get_local_rtp_port(URLContext *h)
Return the local rtp port used by the RTP connection.
Definition: rtpproto.c:573
static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
Definition: ffserver.c:2867
int chunked_encoding
Definition: ffserver.c:140
RTSPLowerTransport
Network layer over which RTP/etc packet data will be transported.
Definition: rtsp.h:37
AVCodec * avcodec_find_encoder(enum AVCodecID id)
Find a registered encoder with a matching codec ID.
Definition: utils.c:3044
static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
Definition: ffserver.c:426
int packet_stream_index
Definition: ffserver.c:175
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1272
FFServerIPAddressACL * acl
int64_t time2
Definition: ffserver.c:127
float avg_frame_size
Definition: ffserver.c:197
static void print_stream_params(AVIOContext *pb, FFServerStream *stream)
Definition: ffserver.c:1870
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:820
static int prepare_sdp_description(FFServerStream *stream, uint8_t **pbuffer, struct in_addr my_ip)
Definition: ffserver.c:2962
const char * fmt
Definition: avisynth_c.h:632
static void build_file_streams(void)
Definition: ffserver.c:3657
unsigned int nb_max_connections
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
int64_t bit_rate
the average bitrate
Definition: avcodec.h:1714
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: utils.c:4427
int av_parse_time(int64_t *timeval, const char *timestr, int duration)
Parse timestr and return in *time a corresponding number of microseconds.
Definition: parseutils.c:559
int ffurl_write(URLContext *h, const unsigned char *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition: avio.c:421
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle...
Definition: avstring.c:56
struct HTTPContext * next
Definition: ffserver.c:142
static FFServerConfig config
Definition: ffserver.c:202
HTTPState
Definition: ffserver.c:81
static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
Definition: ffserver.c:2846
static int64_t cur_time
Definition: ffserver.c:262
static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
Definition: ffserver.c:3284
FFServerIPAddressAction
AVFormatContext * fmt_in
Definition: ffserver.c:148
char protocol[16]
Definition: ffserver.c:169
uint8_t * packet_buffer_end
Definition: ffserver.c:192
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition: avformat.h:943
static int validate_acl_list(FFServerIPAddressACL *in_acl, HTTPContext *c)
Definition: ffserver.c:1348
int num
numerator
Definition: rational.h:44
int index
stream index in AVFormatContext
Definition: avformat.h:877
int size
Definition: avcodec.h:1581
#define AVIO_FLAG_READ
read-only
Definition: avio.h:606
static int rtsp_parse_request(HTTPContext *c)
Definition: ffserver.c:2873
static av_const int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.h:222
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:607
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown) That is the width of a pixel divided by the height of the pixel...
Definition: avcodec.h:2060
AVInputFormat * ifmt
enum AVMediaType codec_type
Definition: rtp.c:37
void show_banner(int argc, char **argv, const OptionDef *options)
Print the program banner to stderr.
Definition: cmdutils.c:1133
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition: avstring.c:223
int64_t timeout
Definition: ffserver.c:136
UDP/unicast.
Definition: rtsp.h:38
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:216
struct pollfd * poll_entry
Definition: ffserver.c:135
void * priv_data
Definition: avformat.h:891
int64_t bytes_served
void show_help_default(const char *opt, const char *arg)
Per-fftool specific help handler.
Definition: ffserver.c:3961
static AVPacket pkt
RedirType
Definition: ffserver.c:1409
static const char * audio_codec_name
Definition: ffplay.c:343
AVCodec.
Definition: avcodec.h:3542
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1260
enum RTSPLowerTransport lower_transport
network layer transport protocol; e.g.
Definition: rtsp.h:121
This describes the server response to each RTSP command.
Definition: rtsp.h:127
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avcodec.h:1786
RTSPTransportField transports[RTSP_MAX_TRANSPORTS]
describes the complete "Transport:" line of the server in response to a SETUP RTSP command by the cli...
Definition: rtsp.h:142
struct FFServerStream * next
const int program_birth_year
program birth year, defined by the program for show_banner()
Definition: ffserver.c:77
Format I/O context.
Definition: avformat.h:1325
#define IOBUFFER_INIT_SIZE
Definition: ffserver.c:112
int avio_check(const char *url, int flags)
Return AVIO_FLAG_* access flags corresponding to the access permissions of the resource in url...
Definition: avio.c:480
static AVStream * add_av_stream1(FFServerStream *stream, AVCodecContext *codec, int copy)
Definition: ffserver.c:3515
#define AVFMT_FLAG_NOPARSE
Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no...
Definition: avformat.h:1442
void ffserver_free_child_args(void *argsp)
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
Public dictionary API.
static void free_acl_list(FFServerIPAddressACL *in_acl)
Definition: ffserver.c:1336
AVOutputFormat * fmt
static void http_vlog(const char *fmt, va_list vargs)
Definition: ffserver.c:398
uint8_t
static int nb_streams
Definition: ffprobe.c:254
char session_id[512]
the "Session:" field.
Definition: rtsp.h:148
#define av_malloc(s)
uint64_t max_bandwidth
Opaque data information usually continuous.
Definition: avutil.h:195
static void opt_debug(void)
Definition: ffserver.c:3955
AVOptions.
uint8_t * packet_buffer_ptr
Definition: ffserver.c:192
#define HAS_ARG
Definition: cmdutils.h:161
AVCodecParameters * avcodec_parameters_alloc(void)
Allocate a new AVCodecParameters and set its fields to default values (unknown/invalid/0).
Definition: utils.c:4038
miscellaneous OS support macros and functions.
char logfilename[1024]
static void compute_real_filename(char *filename, int max_size)
compute the real filename of a file by matching it without its extensions to all the stream's filenam...
Definition: ffserver.c:1386
static unsigned int nb_connections
Definition: ffserver.c:257
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: avcodec.h:1598
const char program_name[]
program name, defined by the program for show_version().
Definition: ffserver.c:76
AVFormatContext * rtp_ctx[FFSERVER_MAX_STREAMS]
Definition: ffserver.c:185
static int http_parse_request(HTTPContext *c)
Definition: ffserver.c:1419
int id
Format-specific stream ID.
Definition: avformat.h:883
#define AVFMT_FLAG_GENPTS
Generate missing pts even if it requires parsing future frames.
Definition: avformat.h:1437
static int http_send_data(HTTPContext *c)
Definition: ffserver.c:2500
static void get_word(char *buf, int buf_size, const char **pp)
Definition: ffserver.c:1277
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4065
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1393
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition: options.c:132
int feed_streams[FFSERVER_MAX_STREAMS]
#define height
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:39
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1436
uint8_t * data
Definition: avcodec.h:1580
static void rtsp_cmd_interrupt(HTTPContext *c, const char *url, RTSPMessageHeader *h, int pause_only)
Definition: ffserver.c:3310
void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, void(*parse_arg_function)(void *, const char *))
Definition: cmdutils.c:365
struct FFServerStream * stream
Definition: ffserver.c:159
static int find_stream_in_feed(FFServerStream *feed, AVCodecContext *codec, int bit_rate)
Definition: ffserver.c:1199
int avformat_network_init(void)
Do global initialization of network components.
Definition: utils.c:4537
static const uint64_t c1
Definition: murmur3.c:49
AVDictionary * metadata
static HTTPContext * find_rtp_session_with_url(const char *url, const char *session_id)
find an RTP connection by using the session ID.
Definition: ffserver.c:3250
int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
Generate an SDP for an RTP session.
Definition: sdp.c:827
int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
Attempt to find a specific tag in a URL.
Definition: parseutils.c:704
int av_match_ext(const char *filename, const char *extensions)
Return a positive value if the given filename has one of the given extensions, 0 otherwise.
Definition: format.c:85
static int http_receive_data(HTTPContext *c)
Definition: ffserver.c:2683
static void copy(LZOContext *c, int cnt)
Copies bytes from input to output buffer with checking.
Definition: lzo.c:85
void parse_loglevel(int argc, char **argv, const OptionDef *options)
Find the '-loglevel' option in the command line args and apply it.
Definition: cmdutils.c:488
ptrdiff_t size
Definition: opengl_enc.c:101
static const uint8_t header[24]
Definition: sdr2.c:67
void show_help_options(const OptionDef *options, const char *msg, int req_flags, int rej_flags, int alt_flags)
Print help for all options matching specified flags.
Definition: cmdutils.c:158
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:204
int chunk_size
Definition: ffserver.c:141
DataRateData datarate
Definition: ffserver.c:167
#define av_log(a,...)
AVStream * streams[FFSERVER_MAX_STREAMS]
int nb_transports
number of items in the 'transports' variable below
Definition: rtsp.h:134
void ff_rtsp_parse_line(AVFormatContext *s, RTSPMessageHeader *reply, const char *buf, RTSPState *rt, const char *method)
static FILE * logfile
Definition: ffserver.c:266
struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1344
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1612
static void http_send_too_busy_reply(int fd)
Definition: ffserver.c:814
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
int64_t feed_max_size
int avcodec_close(AVCodecContext *avctx)
Close a given AVCodecContext and free all the data associated with it (but not the AVCodecContext its...
Definition: utils.c:2959
AVIOContext * avio_alloc_context(unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int(*read_packet)(void *opaque, uint8_t *buf, int buf_size), int(*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t(*seek)(void *opaque, int64_t offset, int whence))
Allocate and initialize an AVIOContext for buffered I/O.
Definition: aviobuf.c:126
int64_t cur_clock
Definition: ffserver.c:157
const char * suffix
Definition: checkasm.c:119
static int extract_rates(char *rates, int ratelen, const char *request)
Definition: ffserver.c:1152
uint8_t * buffer_end
Definition: ffserver.c:137
AVDictionary * metadata
Metadata that applies to the whole file.
Definition: avformat.h:1539
int main(int argc, char **argv)
Definition: ffserver.c:3977
static int handle_connection(HTTPContext *c)
Definition: ffserver.c:971
int last_packet_sent
Definition: ffserver.c:165
int got_key_frame
Definition: ffserver.c:143
int suppress_log
Definition: ffserver.c:166
static int64_t get_server_clock(HTTPContext *c)
Definition: ffserver.c:2233
#define closesocket
Definition: ffserver.c:28
int64_t data_count
Definition: ffserver.c:144
#define AVERROR(e)
Definition: error.h:43
int ffio_set_buf_size(AVIOContext *s, int buf_size)
Definition: aviobuf.c:953
static void rtsp_cmd_options(HTTPContext *c, const char *url)
Definition: ffserver.c:3016
static uint64_t current_bandwidth
Definition: ffserver.c:259
#define FFSERVER_MAX_STREAMS
AVIOContext * pb
Definition: ffserver.c:179
static int add_av_stream(FFServerStream *feed, AVStream *st)
Definition: ffserver.c:3551
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:202
const char * arg
Definition: jacosubdec.c:66
int64_t cur_pts
Definition: ffserver.c:151
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
Definition: opt.c:539
enum FFServerStreamType stream_type
Definition: graph2dot.c:48
char dynamic_acl[1024]
simple assert() macros that are a bit more flexible than ISO C assert().
int av_log_get_level(void)
Get the current log level.
Definition: log.c:386
static int socket_open_listen(struct sockaddr_in *my_addr)
Definition: ffserver.c:555
const char * name
Name of the codec implementation.
Definition: avcodec.h:3549
uint8_t * packet_buffer
Definition: ffserver.c:192
GLsizei count
Definition: opengl_enc.c:109
int buffer_size
Definition: ffserver.c:172
static void start_children(FFServerStream *feed)
Definition: ffserver.c:471
#define FFMAX(a, b)
Definition: common.h:94
static int ffm_write_write_index(int fd, int64_t pos)
Definition: ffserver.c:354
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:83
#define fail()
Definition: checkasm.h:81
int feed_streams[FFSERVER_MAX_STREAMS]
Definition: ffserver.c:161
static size_t htmlencode(const char *src, char **dest)
Substitutes known conflicting chars on a text string with their corresponding HTML entities...
Definition: ffserver.c:282
#define CHECK_CODEC(x)
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1586
AVFormatContext fmt_ctx
Definition: ffserver.c:164
static HTTPContext * first_http_ctx
Definition: ffserver.c:200
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1381
void av_stream_set_recommended_encoder_configuration(AVStream *s, char *configuration)
static int open_input_stream(HTTPContext *c, const char *info)
Definition: ffserver.c:2147
static void log_connection(HTTPContext *c)
Definition: ffserver.c:438
#define th
Definition: regdef.h:75
AVInputFormat * av_find_input_format(const char *short_name)
Find AVInputFormat based on the short name of the input format.
Definition: format.c:164
#define RTSP_REQUEST_TIMEOUT
Definition: ffserver.c:116
char method[16]
Definition: ffserver.c:170
int seekable
A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
Definition: avio.h:243
char feed_filename[1024]
static int modify_current_stream(HTTPContext *c, char *rates)
Definition: ffserver.c:1237
int is_packetized
Definition: ffserver.c:174
char filename[1024]
input or output filename
Definition: avformat.h:1401
static void rtsp_cmd_describe(HTTPContext *c, const char *url)
Definition: ffserver.c:3026
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:246
av_warn_unused_result int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
Definition: mux.c:496
#define FFMIN(a, b)
Definition: common.h:96
int64_t start_time
Definition: ffserver.c:149
struct FFServerStream * next_feed
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
void av_log_set_callback(void(*callback)(void *, int, const char *, va_list))
Set the logging callback.
Definition: log.c:406
struct AVStream::@176 * info
attribute_deprecated int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src)
Copy the settings of the source AVCodecContext into the destination AVCodecContext.
Definition: options.c:190
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
Definition: options.c:156
#define AV_OPT_SEARCH_CHILDREN
Search in possible children of the given object first.
Definition: opt.h:556
#define width
int width
picture width / height.
Definition: avcodec.h:1836
int ffio_open_dyn_packet_buf(AVIOContext **s, int max_packet_size)
Open a write only packetized memory stream with a maximum packet size of 'max_packet_size'.
Definition: aviobuf.c:1265
#define RTSP_TCP_MAX_PACKET_SIZE
Definition: rtsp.h:75
#define ff_neterrno()
Definition: network.h:64
const char * name
Definition: avformat.h:522
void ffserver_get_arg(char *buf, int buf_size, const char **pp)
struct FFServerIPAddressACL * next
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:119
AVFormatContext * ctx
Definition: movenc.c:48
This describes a single item in the "Transport:" line of one stream as negotiated by the SETUP RTSP c...
Definition: rtsp.h:88
int switch_pending
Definition: ffserver.c:163
int64_t feed_write_index
static int need_to_start_children
Definition: ffserver.c:254
struct HTTPContext * rtsp_c
Definition: ffserver.c:191
static AVLFG random_state
Definition: ffserver.c:264
AVOutputFormat * av_guess_format(const char *short_name, const char *filename, const char *mime_type)
Return the output format in the list of registered output formats which best matches the provided par...
Definition: format.c:98
#define src
Definition: vp9dsp.c:530
const char *(* item_name)(void *ctx)
A pointer to a function which returns the name of a context instance ctx associated with the class...
Definition: log.h:78
int ff_socket_nonblock(int socket, int enable)
int cur_frame_bytes
Definition: ffserver.c:153
static const char * input_filename
Definition: ffplay.c:314
#define FF_ARRAY_ELEMS(a)
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
Stream structure.
Definition: avformat.h:876
enum RTSPLowerTransport rtp_protocol
Definition: ffserver.c:183
static int64_t ffm_read_write_index(int fd)
Definition: ffserver.c:343
struct sockaddr_in from_addr
Definition: ffserver.c:134
int avformat_network_deinit(void)
Undo the initialization done by avformat_network_init.
Definition: utils.c:4550
sample_rate
int frame_size
Definition: mxfenc.c:1821
int http_error
Definition: ffserver.c:138
static HTTPContext * rtp_new_connection(struct sockaddr_in *from_addr, FFServerStream *stream, const char *session_id, enum RTSPLowerTransport rtp_protocol)
Definition: ffserver.c:3344
static void compute_status(HTTPContext *c)
Definition: ffserver.c:1916
AVStreamInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1228
enum AVMediaType codec_type
Definition: avcodec.h:1657
int(* read_seek)(struct AVFormatContext *, int stream_index, int64_t timestamp, int flags)
Seek to a given timestamp relative to the frames in stream component stream_index.
Definition: avformat.h:752
static void start_multicast(void)
Definition: ffserver.c:594
enum AVCodecID codec_id
Definition: avcodec.h:1666
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:252
long long data_count
Definition: ffserver.c:196
char * av_strdup(const char *s)
Duplicate the string s.
Definition: mem.c:267
int sample_rate
samples per second
Definition: avcodec.h:2410
AVIOContext * pb
I/O context.
Definition: avformat.h:1367
#define ss
char filename[1024]
main external API structure.
Definition: avcodec.h:1649
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:563
int wmp_client_id
Definition: ffserver.c:168
int64_t time1
Definition: ffserver.c:127
static int compute_datarate(DataRateData *drd, int64_t count)
Definition: ffserver.c:462
struct sockaddr_in rtsp_addr
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition: lfg.h:38
static RTSPTransportField * find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
Definition: ffserver.c:3088
void * buf
Definition: avisynth_c.h:553
Definition: url.h:38
GLint GLenum type
Definition: opengl_enc.c:105
char url[128]
Definition: ffserver.c:171
static void close_connection(HTTPContext *c)
Definition: ffserver.c:887
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:69
int client_port_max
Definition: rtsp.h:101
static int http_server(void)
Definition: ffserver.c:654
static const char * format
Definition: movenc.c:47
Describe the class of an AVClass context structure.
Definition: log.h:67
static void cp_html_entity(char *buffer, const char *entity)
Definition: ffserver.c:268
#define SPACE_CHARS
Definition: internal.h:272
int avcodec_parameters_from_context(AVCodecParameters *par, const AVCodecContext *codec)
Fill the parameters struct based on the values from the supplied codec context.
Definition: utils.c:4077
uint8_t * buffer_ptr
Definition: ffserver.c:137
#define OPT_STRING
Definition: cmdutils.h:164
static void update_datarate(DataRateData *drd, int64_t count)
Definition: ffserver.c:448
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:101
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition: lfg.c:30
int64_t first_pts
Definition: ffserver.c:150
static const OptionDef options[]
Definition: ffserver.c:79
static void start_wait_request(HTTPContext *c, int is_rtsp)
Definition: ffserver.c:804
#define snprintf
Definition: snprintf.h:34
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4001
misc parsing utilities
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition: utils.c:1631
size_t av_strlcat(char *dst, const char *src, size_t size)
Append the string src to the string dst, but to a total length of no more than size - 1 bytes...
Definition: avstring.c:93
unsigned bandwidth
FFServerStream * first_feed
int switch_feed_streams[FFSERVER_MAX_STREAMS]
Definition: ffserver.c:162
AVDictionary * in_opts
static void extract_mpeg4_header(AVFormatContext *infile)
Definition: ffserver.c:3606
static int flags
Definition: cpu.c:47
RTSPStatusCode
RTSP handling.
Definition: rtspcodes.h:31
int ffurl_close(URLContext *h)
Definition: avio.c:467
URLContext * rtp_handles[FFSERVER_MAX_STREAMS]
Definition: ffserver.c:188
uint8_t level
Definition: svq3.c:193
static int64_t get_packet_send_clock(HTTPContext *c)
Definition: ffserver.c:2240
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Seek to the keyframe at timestamp.
Definition: utils.c:2357
struct FFServerStream * feed
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:1862
#define OPT_BOOL
Definition: cmdutils.h:162
char transport_option[512]
Definition: ffserver.c:122
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_RB64
Definition: bytestream.h:87
Main libavformat public API header.
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Definition: avio.c:357
static FFServerIPAddressACL * parse_dynamic_acl(FFServerStream *stream, HTTPContext *c)
Definition: ffserver.c:1295
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
Read packets of a media file to get stream information.
Definition: utils.c:3268
static double c[64]
void ffserver_parse_acl_row(FFServerStream *stream, FFServerStream *feed, FFServerIPAddressACL *ext_acl, const char *p, const char *filename, int line_num)
int den
denominator
Definition: rational.h:45
struct AVInputFormat * iformat
The input container format.
Definition: avformat.h:1337
int64_t count2
Definition: ffserver.c:126
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition: utils.c:4037
int ff_rtp_get_local_rtcp_port(URLContext *h)
Return the local rtcp port used by the RTP connection.
Definition: rtpproto.c:585
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
Definition: avcodec.h:731
#define av_free(p)
static void compute_bandwidth(void)
Definition: ffserver.c:3903
static void ffm_set_write_index(AVFormatContext *s, int64_t pos, int64_t file_size)
Definition: ffserver.c:372
char * value
Definition: dict.h:87
uint8_t * pb_buffer
Definition: ffserver.c:178
TCP; interleaved in RTSP.
Definition: rtsp.h:39
int len
uint8_t * buffer
Definition: ffserver.c:173
int channels
number of audio channels
Definition: avcodec.h:2411
#define PATH_LENGTH
Definition: ffserver.c:74
static int check_codec_match(AVCodecContext *ccf, AVCodecContext *ccs, int stream)
Definition: ffserver.c:3717
static uint8_t tmp[8]
Definition: des.c:38
#define RTSP_STATUS_CODE2STRING(x)
Definition: rtspcodes.h:125
void * priv_data
Format private data.
Definition: avformat.h:1353
int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
Definition: utils.c:471
static void new_connection(int server_fd, int is_rtsp)
Definition: ffserver.c:836
char session_id[32]
Definition: ffserver.c:184
AVCodecContext * avctx
The codec context used by avformat_find_stream_info, the parser, etc.
Definition: internal.h:153
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
Definition: avcodec.h:1579
static void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.h:229
char * av_stream_get_recommended_encoder_configuration(const AVStream *s)
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1184
int frame_number
Frame counter, set by libavcodec.
Definition: avcodec.h:2441
int max_packet_size
if non zero, the stream is packetized with this max packet size
Definition: url.h:44
static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h)
Definition: ffserver.c:3101
static const char * video_codec_name
Definition: ffplay.c:345
#define av_freep(p)
int pts_stream_index
Definition: ffserver.c:156
void INT64 start
Definition: avisynth_c.h:553
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:660
static char * ctime1(char *buf2, size_t buf_size)
Definition: ffserver.c:380
unbuffered private I/O API
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
Definition: random_seed.c:114
struct in_addr multicast_ip
AVCodecParameters * codecpar
Definition: avformat.h:1006
#define av_malloc_array(a, b)
FFServerStream * first_stream
enum HTTPState state
Definition: ffserver.c:132
int stream_index
Definition: avcodec.h:1582
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:913
static const int rates[]
Definition: avresample.c:176
static void handle_child_exit(int sig)
Definition: ffserver.c:3926
const char * mime_type
Definition: avformat.h:529
This structure stores compressed data.
Definition: avcodec.h:1557
void av_register_all(void)
Initialize libavformat and register all the muxers, demuxers and protocols.
Definition: allformats.c:44
int avio_closep(AVIOContext **s)
Close the resource accessed by the AVIOContext *s, free it and set the pointer pointing to it to NULL...
Definition: aviobuf.c:1086
unsigned int nb_max_http_connections
static int build_feed_streams(void)
Definition: ffserver.c:3752
struct in_addr first
#define AVFMT_FLAG_NOFILLIN
Do not infer any values from other values, just return what is stored in the container.
Definition: avformat.h:1441
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:252
static void fmt_bytecount(AVIOContext *pb, int64_t count)
Definition: ffserver.c:1860
enum FFServerIPAddressAction action
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1573
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:240
#define HTTP_REQUEST_TIMEOUT
Definition: ffserver.c:115
GLuint buffer
Definition: opengl_enc.c:102
static int http_prepare_data(HTTPContext *c)
Definition: ffserver.c:2254
int avio_printf(AVIOContext *s, const char *fmt,...) av_printf_format(2
#define FFM_PACKET_SIZE
Definition: ffm.h:31
int client_port_min
UDP client ports; these should be the local ports of the UDP RTP (and RTCP) sockets over which we rec...
Definition: rtsp.h:101
int64_t cur_frame_duration
Definition: ffserver.c:152
static void remove_stream(FFServerStream *stream)
Definition: ffserver.c:3593
static int http_start_receive_data(HTTPContext *c)
Definition: ffserver.c:2621
static int no_launch
Definition: ffserver.c:253
int feed_fd
Definition: ffserver.c:146