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