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