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