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