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