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/rtsp.h"
41 #include "libavformat/internal.h"
42 #include "libavformat/url.h"
43 
44 #include "libavutil/avassert.h"
45 #include "libavutil/avstring.h"
46 #include "libavutil/lfg.h"
47 #include "libavutil/dict.h"
48 #include "libavutil/intreadwrite.h"
49 #include "libavutil/mathematics.h"
50 #include "libavutil/random_seed.h"
51 #include "libavutil/parseutils.h"
52 #include "libavutil/opt.h"
53 #include "libavutil/time.h"
54 
55 #include <stdarg.h>
56 #include <unistd.h>
57 #include <fcntl.h>
58 #include <sys/ioctl.h>
59 #if HAVE_POLL_H
60 #include <poll.h>
61 #endif
62 #include <errno.h>
63 #include <time.h>
64 #include <sys/wait.h>
65 #include <signal.h>
66 #if HAVE_DLFCN_H
67 #include <dlfcn.h>
68 #endif
69 
70 #include "cmdutils.h"
71 
72 const char program_name[] = "ffserver";
73 const int program_birth_year = 2000;
74 
75 static const OptionDef options[];
76 
77 enum HTTPState {
81  HTTPSTATE_SEND_DATA, /* sending TCP or UDP data */
84  HTTPSTATE_WAIT_FEED, /* wait for data from the feed */
86 
90 };
91 
92 static const char *http_state[] = {
93  "HTTP_WAIT_REQUEST",
94  "HTTP_SEND_HEADER",
95 
96  "SEND_DATA_HEADER",
97  "SEND_DATA",
98  "SEND_DATA_TRAILER",
99  "RECEIVE_DATA",
100  "WAIT_FEED",
101  "READY",
102 
103  "RTSP_WAIT_REQUEST",
104  "RTSP_SEND_REPLY",
105  "RTSP_SEND_PACKET",
106 };
107 
108 #define MAX_STREAMS 20
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;
135  uint8_t *buffer_ptr, *buffer_end;
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 */
157  struct FFStream *stream;
158  /* -1 is invalid stream */
159  int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
160  int switch_feed_streams[MAX_STREAMS]; /* index of streams in the feed */
162  AVFormatContext fmt_ctx; /* instance of FFStream 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 */
181  enum RTSPLowerTransport rtp_protocol;
182  char session_id[32]; /* session id */
184 
185  /* RTP/UDP specific */
186  URLContext *rtp_handles[MAX_STREAMS];
187 
188  /* RTP/TCP specific */
191 } HTTPContext;
192 
193 /* each generated stream is described here */
198 };
199 
201  IP_ALLOW = 1,
203 };
204 
205 typedef struct IPAddressACL {
208  /* These are in host order */
209  struct in_addr first;
210  struct in_addr last;
211 } IPAddressACL;
212 
213 /* description of each stream of the ffserver.conf file */
214 typedef struct FFStream {
215  enum StreamType stream_type;
216  char filename[1024]; /* stream filename */
217  struct FFStream *feed; /* feed we are using (can be null if
218  coming from file) */
219  AVDictionary *in_opts; /* input parameters */
220  AVInputFormat *ifmt; /* if non NULL, force input format */
223  char dynamic_acl[1024];
225  int prebuffer; /* Number of millseconds early to start */
226  int64_t max_time; /* Number of milliseconds to run */
229  int feed_streams[MAX_STREAMS]; /* index of streams in the feed */
230  char feed_filename[1024]; /* file name of the feed storage, or
231  input file name for a stream */
232  char author[512];
233  char title[512];
234  char copyright[512];
235  char comment[512];
236  pid_t pid; /* Of ffmpeg process */
237  time_t pid_start; /* Of ffmpeg process */
238  char **child_argv;
239  struct FFStream *next;
240  unsigned bandwidth; /* bandwidth, in kbits/s */
241  /* RTSP options */
242  char *rtsp_option;
243  /* multicast specific */
245  struct in_addr multicast_ip;
246  int multicast_port; /* first port used for multicast */
248  int loop; /* if true, send the stream in loops (only meaningful if file) */
249 
250  /* feed specific */
251  int feed_opened; /* true if someone is writing to the feed */
252  int is_feed; /* true if it is a feed */
253  int readonly; /* True if writing is prohibited to the file */
254  int truncate; /* True if feeder connection truncate the feed file */
256  int64_t bytes_served;
257  int64_t feed_max_size; /* maximum storage size, zero means unlimited */
258  int64_t feed_write_index; /* current write position in feed (it wraps around) */
259  int64_t feed_size; /* current size of feed */
261 } FFStream;
262 
263 typedef struct FeedData {
264  long long data_count;
265  float avg_frame_size; /* frame size averaged over last frames with exponential mean */
266 } FeedData;
267 
268 static struct sockaddr_in my_http_addr;
269 static struct sockaddr_in my_rtsp_addr;
270 
271 static char logfilename[1024];
273 static FFStream *first_feed; /* contains only feeds */
274 static FFStream *first_stream; /* contains all streams, including feeds */
275 
276 static void new_connection(int server_fd, int is_rtsp);
277 static void close_connection(HTTPContext *c);
278 
279 /* HTTP handling */
280 static int handle_connection(HTTPContext *c);
281 static int http_parse_request(HTTPContext *c);
282 static int http_send_data(HTTPContext *c);
283 static void compute_status(HTTPContext *c);
284 static int open_input_stream(HTTPContext *c, const char *info);
286 static int http_receive_data(HTTPContext *c);
287 
288 /* RTSP handling */
289 static int rtsp_parse_request(HTTPContext *c);
290 static void rtsp_cmd_describe(HTTPContext *c, const char *url);
291 static void rtsp_cmd_options(HTTPContext *c, const char *url);
292 static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h);
293 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h);
294 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h);
295 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h);
296 
297 /* SDP handling */
298 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
299  struct in_addr my_ip);
300 
301 /* RTP handling */
302 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
303  FFStream *stream, const char *session_id,
304  enum RTSPLowerTransport rtp_protocol);
305 static int rtp_new_av_stream(HTTPContext *c,
306  int stream_index, struct sockaddr_in *dest_addr,
307  HTTPContext *rtsp_c);
308 
309 static const char *my_program_name;
310 
311 static const char *config_filename;
312 
313 static int ffserver_debug;
314 static int no_launch;
316 
317 /* maximum number of simultaneous HTTP connections */
318 static unsigned int nb_max_http_connections = 2000;
319 static unsigned int nb_max_connections = 5;
320 static unsigned int nb_connections;
321 
322 static uint64_t max_bandwidth = 1000;
323 static uint64_t current_bandwidth;
324 
325 static int64_t cur_time; // Making this global saves on passing it around everywhere
326 
328 
329 static FILE *logfile = NULL;
330 
331 static int64_t ffm_read_write_index(int fd)
332 {
333  uint8_t buf[8];
334 
335  if (lseek(fd, 8, SEEK_SET) < 0)
336  return AVERROR(EIO);
337  if (read(fd, buf, 8) != 8)
338  return AVERROR(EIO);
339  return AV_RB64(buf);
340 }
341 
342 static int ffm_write_write_index(int fd, int64_t pos)
343 {
344  uint8_t buf[8];
345  int i;
346 
347  for(i=0;i<8;i++)
348  buf[i] = (pos >> (56 - i * 8)) & 0xff;
349  if (lseek(fd, 8, SEEK_SET) < 0)
350  return AVERROR(EIO);
351  if (write(fd, buf, 8) != 8)
352  return AVERROR(EIO);
353  return 8;
354 }
355 
356 static void ffm_set_write_index(AVFormatContext *s, int64_t pos,
357  int64_t file_size)
358 {
359  FFMContext *ffm = s->priv_data;
360  ffm->write_index = pos;
361  ffm->file_size = file_size;
362 }
363 
364 /* FIXME: make ffserver work with IPv6 */
365 /* resolve host with also IP address parsing */
366 static int resolve_host(struct in_addr *sin_addr, const char *hostname)
367 {
368 
369  if (!ff_inet_aton(hostname, sin_addr)) {
370 #if HAVE_GETADDRINFO
371  struct addrinfo *ai, *cur;
372  struct addrinfo hints = { 0 };
373  hints.ai_family = AF_INET;
374  if (getaddrinfo(hostname, NULL, &hints, &ai))
375  return -1;
376  /* getaddrinfo returns a linked list of addrinfo structs.
377  * Even if we set ai_family = AF_INET above, make sure
378  * that the returned one actually is of the correct type. */
379  for (cur = ai; cur; cur = cur->ai_next) {
380  if (cur->ai_family == AF_INET) {
381  *sin_addr = ((struct sockaddr_in *)cur->ai_addr)->sin_addr;
382  freeaddrinfo(ai);
383  return 0;
384  }
385  }
386  freeaddrinfo(ai);
387  return -1;
388 #else
389  struct hostent *hp;
390  hp = gethostbyname(hostname);
391  if (!hp)
392  return -1;
393  memcpy(sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
394 #endif
395  }
396  return 0;
397 }
398 
399 static char *ctime1(char *buf2, int buf_size)
400 {
401  time_t ti;
402  char *p;
403 
404  ti = time(NULL);
405  p = ctime(&ti);
406  av_strlcpy(buf2, p, buf_size);
407  p = buf2 + strlen(p) - 1;
408  if (*p == '\n')
409  *p = '\0';
410  return buf2;
411 }
412 
413 static void http_vlog(const char *fmt, va_list vargs)
414 {
415  static int print_prefix = 1;
416  if (logfile) {
417  if (print_prefix) {
418  char buf[32];
419  ctime1(buf, sizeof(buf));
420  fprintf(logfile, "%s ", buf);
421  }
422  print_prefix = strstr(fmt, "\n") != NULL;
423  vfprintf(logfile, fmt, vargs);
424  fflush(logfile);
425  }
426 }
427 
428 #ifdef __GNUC__
429 __attribute__ ((format (printf, 1, 2)))
430 #endif
431 static void http_log(const char *fmt, ...)
432 {
433  va_list vargs;
434  va_start(vargs, fmt);
435  http_vlog(fmt, vargs);
436  va_end(vargs);
437 }
438 
439 static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
440 {
441  static int print_prefix = 1;
442  AVClass *avc = ptr ? *(AVClass**)ptr : NULL;
443  if (level > av_log_get_level())
444  return;
445  if (print_prefix && avc)
446  http_log("[%s @ %p]", avc->item_name(ptr), ptr);
447  print_prefix = strstr(fmt, "\n") != NULL;
448  http_vlog(fmt, vargs);
449 }
450 
452 {
453  if (c->suppress_log)
454  return;
455 
456  http_log("%s - - [%s] \"%s %s\" %d %"PRId64"\n",
457  inet_ntoa(c->from_addr.sin_addr), c->method, c->url,
458  c->protocol, (c->http_error ? c->http_error : 200), c->data_count);
459 }
460 
461 static void update_datarate(DataRateData *drd, int64_t count)
462 {
463  if (!drd->time1 && !drd->count1) {
464  drd->time1 = drd->time2 = cur_time;
465  drd->count1 = drd->count2 = count;
466  } else if (cur_time - drd->time2 > 5000) {
467  drd->time1 = drd->time2;
468  drd->count1 = drd->count2;
469  drd->time2 = cur_time;
470  drd->count2 = count;
471  }
472 }
473 
474 /* In bytes per second */
475 static int compute_datarate(DataRateData *drd, int64_t count)
476 {
477  if (cur_time == drd->time1)
478  return 0;
479 
480  return ((count - drd->count1) * 1000) / (cur_time - drd->time1);
481 }
482 
483 
484 static void start_children(FFStream *feed)
485 {
486  if (no_launch)
487  return;
488 
489  for (; feed; feed = feed->next) {
490  if (feed->child_argv && !feed->pid) {
491  feed->pid_start = time(0);
492 
493  feed->pid = fork();
494 
495  if (feed->pid < 0) {
496  http_log("Unable to create children\n");
497  exit(1);
498  }
499  if (!feed->pid) {
500  /* In child */
501  char pathname[1024];
502  char *slash;
503  int i;
504 
505  av_strlcpy(pathname, my_program_name, sizeof(pathname));
506 
507  slash = strrchr(pathname, '/');
508  if (!slash)
509  slash = pathname;
510  else
511  slash++;
512  strcpy(slash, "ffmpeg");
513 
514  http_log("Launch command line: ");
515  http_log("%s ", pathname);
516  for (i = 1; feed->child_argv[i] && feed->child_argv[i][0]; i++)
517  http_log("%s ", feed->child_argv[i]);
518  http_log("\n");
519 
520  for (i = 3; i < 256; i++)
521  close(i);
522 
523  if (!ffserver_debug) {
524  if (!freopen("/dev/null", "r", stdin))
525  http_log("failed to redirect STDIN to /dev/null\n;");
526  if (!freopen("/dev/null", "w", stdout))
527  http_log("failed to redirect STDOUT to /dev/null\n;");
528  if (!freopen("/dev/null", "w", stderr))
529  http_log("failed to redirect STDERR to /dev/null\n;");
530  }
531 
532  signal(SIGPIPE, SIG_DFL);
533 
534  execvp(pathname, feed->child_argv);
535 
536  _exit(1);
537  }
538  }
539  }
540 }
541 
542 /* open a listening socket */
543 static int socket_open_listen(struct sockaddr_in *my_addr)
544 {
545  int server_fd, tmp;
546 
547  server_fd = socket(AF_INET,SOCK_STREAM,0);
548  if (server_fd < 0) {
549  perror ("socket");
550  return -1;
551  }
552 
553  tmp = 1;
554  setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));
555 
556  my_addr->sin_family = AF_INET;
557  if (bind (server_fd, (struct sockaddr *) my_addr, sizeof (*my_addr)) < 0) {
558  char bindmsg[32];
559  snprintf(bindmsg, sizeof(bindmsg), "bind(port %d)", ntohs(my_addr->sin_port));
560  perror (bindmsg);
561  closesocket(server_fd);
562  return -1;
563  }
564 
565  if (listen (server_fd, 5) < 0) {
566  perror ("listen");
567  closesocket(server_fd);
568  return -1;
569  }
570  ff_socket_nonblock(server_fd, 1);
571 
572  return server_fd;
573 }
574 
575 /* start all multicast streams */
576 static void start_multicast(void)
577 {
578  FFStream *stream;
579  char session_id[32];
580  HTTPContext *rtp_c;
581  struct sockaddr_in dest_addr = {0};
582  int default_port, stream_index;
583 
584  default_port = 6000;
585  for(stream = first_stream; stream != NULL; stream = stream->next) {
586  if (stream->is_multicast) {
587  unsigned random0 = av_lfg_get(&random_state);
588  unsigned random1 = av_lfg_get(&random_state);
589  /* open the RTP connection */
590  snprintf(session_id, sizeof(session_id), "%08x%08x",
591  random0, random1);
592 
593  /* choose a port if none given */
594  if (stream->multicast_port == 0) {
595  stream->multicast_port = default_port;
596  default_port += 100;
597  }
598 
599  dest_addr.sin_family = AF_INET;
600  dest_addr.sin_addr = stream->multicast_ip;
601  dest_addr.sin_port = htons(stream->multicast_port);
602 
603  rtp_c = rtp_new_connection(&dest_addr, stream, session_id,
605  if (!rtp_c)
606  continue;
607 
608  if (open_input_stream(rtp_c, "") < 0) {
609  http_log("Could not open input stream for stream '%s'\n",
610  stream->filename);
611  continue;
612  }
613 
614  /* open each RTP stream */
615  for(stream_index = 0; stream_index < stream->nb_streams;
616  stream_index++) {
617  dest_addr.sin_port = htons(stream->multicast_port +
618  2 * stream_index);
619  if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, NULL) < 0) {
620  http_log("Could not open output stream '%s/streamid=%d'\n",
621  stream->filename, stream_index);
622  exit(1);
623  }
624  }
625 
626  /* change state to send data */
627  rtp_c->state = HTTPSTATE_SEND_DATA;
628  }
629  }
630 }
631 
632 /* main loop of the http server */
633 static int http_server(void)
634 {
635  int server_fd = 0, rtsp_server_fd = 0;
636  int ret, delay, delay1;
637  struct pollfd *poll_table, *poll_entry;
638  HTTPContext *c, *c_next;
639 
640  if(!(poll_table = av_mallocz((nb_max_http_connections + 2)*sizeof(*poll_table)))) {
641  http_log("Impossible to allocate a poll table handling %d connections.\n", nb_max_http_connections);
642  return -1;
643  }
644 
645  if (my_http_addr.sin_port) {
646  server_fd = socket_open_listen(&my_http_addr);
647  if (server_fd < 0)
648  return -1;
649  }
650 
651  if (my_rtsp_addr.sin_port) {
652  rtsp_server_fd = socket_open_listen(&my_rtsp_addr);
653  if (rtsp_server_fd < 0)
654  return -1;
655  }
656 
657  if (!rtsp_server_fd && !server_fd) {
658  http_log("HTTP and RTSP disabled.\n");
659  return -1;
660  }
661 
662  http_log("FFserver started.\n");
663 
664  start_children(first_feed);
665 
666  start_multicast();
667 
668  for(;;) {
669  poll_entry = poll_table;
670  if (server_fd) {
671  poll_entry->fd = server_fd;
672  poll_entry->events = POLLIN;
673  poll_entry++;
674  }
675  if (rtsp_server_fd) {
676  poll_entry->fd = rtsp_server_fd;
677  poll_entry->events = POLLIN;
678  poll_entry++;
679  }
680 
681  /* wait for events on each HTTP handle */
682  c = first_http_ctx;
683  delay = 1000;
684  while (c != NULL) {
685  int fd;
686  fd = c->fd;
687  switch(c->state) {
691  c->poll_entry = poll_entry;
692  poll_entry->fd = fd;
693  poll_entry->events = POLLOUT;
694  poll_entry++;
695  break;
697  case HTTPSTATE_SEND_DATA:
699  if (!c->is_packetized) {
700  /* for TCP, we output as much as we can (may need to put a limit) */
701  c->poll_entry = poll_entry;
702  poll_entry->fd = fd;
703  poll_entry->events = POLLOUT;
704  poll_entry++;
705  } else {
706  /* when ffserver is doing the timing, we work by
707  looking at which packet need to be sent every
708  10 ms */
709  delay1 = 10; /* one tick wait XXX: 10 ms assumed */
710  if (delay1 < delay)
711  delay = delay1;
712  }
713  break;
716  case HTTPSTATE_WAIT_FEED:
718  /* need to catch errors */
719  c->poll_entry = poll_entry;
720  poll_entry->fd = fd;
721  poll_entry->events = POLLIN;/* Maybe this will work */
722  poll_entry++;
723  break;
724  default:
725  c->poll_entry = NULL;
726  break;
727  }
728  c = c->next;
729  }
730 
731  /* wait for an event on one connection. We poll at least every
732  second to handle timeouts */
733  do {
734  ret = poll(poll_table, poll_entry - poll_table, delay);
735  if (ret < 0 && ff_neterrno() != AVERROR(EAGAIN) &&
736  ff_neterrno() != AVERROR(EINTR))
737  return -1;
738  } while (ret < 0);
739 
740  cur_time = av_gettime() / 1000;
741 
744  start_children(first_feed);
745  }
746 
747  /* now handle the events */
748  for(c = first_http_ctx; c != NULL; c = c_next) {
749  c_next = c->next;
750  if (handle_connection(c) < 0) {
751  /* close and free the connection */
752  log_connection(c);
753  close_connection(c);
754  }
755  }
756 
757  poll_entry = poll_table;
758  if (server_fd) {
759  /* new HTTP connection request ? */
760  if (poll_entry->revents & POLLIN)
761  new_connection(server_fd, 0);
762  poll_entry++;
763  }
764  if (rtsp_server_fd) {
765  /* new RTSP connection request ? */
766  if (poll_entry->revents & POLLIN)
767  new_connection(rtsp_server_fd, 1);
768  }
769  }
770 }
771 
772 /* start waiting for a new HTTP/RTSP request */
773 static void start_wait_request(HTTPContext *c, int is_rtsp)
774 {
775  c->buffer_ptr = c->buffer;
776  c->buffer_end = c->buffer + c->buffer_size - 1; /* leave room for '\0' */
777 
778  if (is_rtsp) {
781  } else {
784  }
785 }
786 
787 static void http_send_too_busy_reply(int fd)
788 {
789  char buffer[400];
790  int len = snprintf(buffer, sizeof(buffer),
791  "HTTP/1.0 503 Server too busy\r\n"
792  "Content-type: text/html\r\n"
793  "\r\n"
794  "<html><head><title>Too busy</title></head><body>\r\n"
795  "<p>The server is too busy to serve your request at this time.</p>\r\n"
796  "<p>The number of current connections is %u, and this exceeds the limit of %u.</p>\r\n"
797  "</body></html>\r\n",
799  av_assert0(len < sizeof(buffer));
800  send(fd, buffer, len, 0);
801 }
802 
803 
804 static void new_connection(int server_fd, int is_rtsp)
805 {
806  struct sockaddr_in from_addr;
807  socklen_t len;
808  int fd;
809  HTTPContext *c = NULL;
810 
811  len = sizeof(from_addr);
812  fd = accept(server_fd, (struct sockaddr *)&from_addr,
813  &len);
814  if (fd < 0) {
815  http_log("error during accept %s\n", strerror(errno));
816  return;
817  }
818  ff_socket_nonblock(fd, 1);
819 
822  goto fail;
823  }
824 
825  /* add a new connection */
826  c = av_mallocz(sizeof(HTTPContext));
827  if (!c)
828  goto fail;
829 
830  c->fd = fd;
831  c->poll_entry = NULL;
832  c->from_addr = from_addr;
834  c->buffer = av_malloc(c->buffer_size);
835  if (!c->buffer)
836  goto fail;
837 
838  c->next = first_http_ctx;
839  first_http_ctx = c;
840  nb_connections++;
841 
842  start_wait_request(c, is_rtsp);
843 
844  return;
845 
846  fail:
847  if (c) {
848  av_free(c->buffer);
849  av_free(c);
850  }
851  closesocket(fd);
852 }
853 
855 {
856  HTTPContext **cp, *c1;
857  int i, nb_streams;
858  AVFormatContext *ctx;
859  URLContext *h;
860  AVStream *st;
861 
862  /* remove connection from list */
863  cp = &first_http_ctx;
864  while ((*cp) != NULL) {
865  c1 = *cp;
866  if (c1 == c)
867  *cp = c->next;
868  else
869  cp = &c1->next;
870  }
871 
872  /* remove references, if any (XXX: do it faster) */
873  for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
874  if (c1->rtsp_c == c)
875  c1->rtsp_c = NULL;
876  }
877 
878  /* remove connection associated resources */
879  if (c->fd >= 0)
880  closesocket(c->fd);
881  if (c->fmt_in) {
882  /* close each frame parser */
883  for(i=0;i<c->fmt_in->nb_streams;i++) {
884  st = c->fmt_in->streams[i];
885  if (st->codec->codec)
886  avcodec_close(st->codec);
887  }
889  }
890 
891  /* free RTP output streams if any */
892  nb_streams = 0;
893  if (c->stream)
894  nb_streams = c->stream->nb_streams;
895 
896  for(i=0;i<nb_streams;i++) {
897  ctx = c->rtp_ctx[i];
898  if (ctx) {
899  av_write_trailer(ctx);
900  av_dict_free(&ctx->metadata);
901  av_free(ctx->streams[0]);
902  av_free(ctx);
903  }
904  h = c->rtp_handles[i];
905  if (h)
906  ffurl_close(h);
907  }
908 
909  ctx = &c->fmt_ctx;
910 
912  if (ctx->oformat) {
913  /* prepare header */
914  if (avio_open_dyn_buf(&ctx->pb) >= 0) {
915  av_write_trailer(ctx);
916  av_freep(&c->pb_buffer);
917  avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
918  }
919  }
920  }
921 
922  for(i=0; i<ctx->nb_streams; i++)
923  av_free(ctx->streams[i]);
924  av_freep(&ctx->streams);
925  av_freep(&ctx->priv_data);
926 
927  if (c->stream && !c->post && c->stream->stream_type == STREAM_TYPE_LIVE)
929 
930  /* signal that there is no feed if we are the feeder socket */
931  if (c->state == HTTPSTATE_RECEIVE_DATA && c->stream) {
932  c->stream->feed_opened = 0;
933  close(c->feed_fd);
934  }
935 
936  av_freep(&c->pb_buffer);
937  av_freep(&c->packet_buffer);
938  av_free(c->buffer);
939  av_free(c);
940  nb_connections--;
941 }
942 
944 {
945  int len, ret;
946 
947  switch(c->state) {
950  /* timeout ? */
951  if ((c->timeout - cur_time) < 0)
952  return -1;
953  if (c->poll_entry->revents & (POLLERR | POLLHUP))
954  return -1;
955 
956  /* no need to read if no events */
957  if (!(c->poll_entry->revents & POLLIN))
958  return 0;
959  /* read the data */
960  read_loop:
961  len = recv(c->fd, c->buffer_ptr, 1, 0);
962  if (len < 0) {
963  if (ff_neterrno() != AVERROR(EAGAIN) &&
964  ff_neterrno() != AVERROR(EINTR))
965  return -1;
966  } else if (len == 0) {
967  return -1;
968  } else {
969  /* search for end of request. */
970  uint8_t *ptr;
971  c->buffer_ptr += len;
972  ptr = c->buffer_ptr;
973  if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) ||
974  (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) {
975  /* request found : parse it and reply */
976  if (c->state == HTTPSTATE_WAIT_REQUEST) {
977  ret = http_parse_request(c);
978  } else {
979  ret = rtsp_parse_request(c);
980  }
981  if (ret < 0)
982  return -1;
983  } else if (ptr >= c->buffer_end) {
984  /* request too long: cannot do anything */
985  return -1;
986  } else goto read_loop;
987  }
988  break;
989 
991  if (c->poll_entry->revents & (POLLERR | POLLHUP))
992  return -1;
993 
994  /* no need to write if no events */
995  if (!(c->poll_entry->revents & POLLOUT))
996  return 0;
997  len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
998  if (len < 0) {
999  if (ff_neterrno() != AVERROR(EAGAIN) &&
1000  ff_neterrno() != AVERROR(EINTR)) {
1001  /* error : close connection */
1002  av_freep(&c->pb_buffer);
1003  return -1;
1004  }
1005  } else {
1006  c->buffer_ptr += len;
1007  if (c->stream)
1008  c->stream->bytes_served += len;
1009  c->data_count += len;
1010  if (c->buffer_ptr >= c->buffer_end) {
1011  av_freep(&c->pb_buffer);
1012  /* if error, exit */
1013  if (c->http_error)
1014  return -1;
1015  /* all the buffer was sent : synchronize to the incoming stream */
1017  c->buffer_ptr = c->buffer_end = c->buffer;
1018  }
1019  }
1020  break;
1021 
1022  case HTTPSTATE_SEND_DATA:
1025  /* for packetized output, we consider we can always write (the
1026  input streams sets the speed). It may be better to verify
1027  that we do not rely too much on the kernel queues */
1028  if (!c->is_packetized) {
1029  if (c->poll_entry->revents & (POLLERR | POLLHUP))
1030  return -1;
1031 
1032  /* no need to read if no events */
1033  if (!(c->poll_entry->revents & POLLOUT))
1034  return 0;
1035  }
1036  if (http_send_data(c) < 0)
1037  return -1;
1038  /* close connection if trailer sent */
1040  return -1;
1041  break;
1043  /* no need to read if no events */
1044  if (c->poll_entry->revents & (POLLERR | POLLHUP))
1045  return -1;
1046  if (!(c->poll_entry->revents & POLLIN))
1047  return 0;
1048  if (http_receive_data(c) < 0)
1049  return -1;
1050  break;
1051  case HTTPSTATE_WAIT_FEED:
1052  /* no need to read if no events */
1053  if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP))
1054  return -1;
1055 
1056  /* nothing to do, we'll be waken up by incoming feed packets */
1057  break;
1058 
1059  case RTSPSTATE_SEND_REPLY:
1060  if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1061  av_freep(&c->pb_buffer);
1062  return -1;
1063  }
1064  /* no need to write if no events */
1065  if (!(c->poll_entry->revents & POLLOUT))
1066  return 0;
1067  len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
1068  if (len < 0) {
1069  if (ff_neterrno() != AVERROR(EAGAIN) &&
1070  ff_neterrno() != AVERROR(EINTR)) {
1071  /* error : close connection */
1072  av_freep(&c->pb_buffer);
1073  return -1;
1074  }
1075  } else {
1076  c->buffer_ptr += len;
1077  c->data_count += len;
1078  if (c->buffer_ptr >= c->buffer_end) {
1079  /* all the buffer was sent : wait for a new request */
1080  av_freep(&c->pb_buffer);
1081  start_wait_request(c, 1);
1082  }
1083  }
1084  break;
1085  case RTSPSTATE_SEND_PACKET:
1086  if (c->poll_entry->revents & (POLLERR | POLLHUP)) {
1087  av_freep(&c->packet_buffer);
1088  return -1;
1089  }
1090  /* no need to write if no events */
1091  if (!(c->poll_entry->revents & POLLOUT))
1092  return 0;
1093  len = send(c->fd, c->packet_buffer_ptr,
1095  if (len < 0) {
1096  if (ff_neterrno() != AVERROR(EAGAIN) &&
1097  ff_neterrno() != AVERROR(EINTR)) {
1098  /* error : close connection */
1099  av_freep(&c->packet_buffer);
1100  return -1;
1101  }
1102  } else {
1103  c->packet_buffer_ptr += len;
1104  if (c->packet_buffer_ptr >= c->packet_buffer_end) {
1105  /* all the buffer was sent : wait for a new request */
1106  av_freep(&c->packet_buffer);
1108  }
1109  }
1110  break;
1111  case HTTPSTATE_READY:
1112  /* nothing to do */
1113  break;
1114  default:
1115  return -1;
1116  }
1117  return 0;
1118 }
1119 
1120 static int extract_rates(char *rates, int ratelen, const char *request)
1121 {
1122  const char *p;
1123 
1124  for (p = request; *p && *p != '\r' && *p != '\n'; ) {
1125  if (av_strncasecmp(p, "Pragma:", 7) == 0) {
1126  const char *q = p + 7;
1127 
1128  while (*q && *q != '\n' && av_isspace(*q))
1129  q++;
1130 
1131  if (av_strncasecmp(q, "stream-switch-entry=", 20) == 0) {
1132  int stream_no;
1133  int rate_no;
1134 
1135  q += 20;
1136 
1137  memset(rates, 0xff, ratelen);
1138 
1139  while (1) {
1140  while (*q && *q != '\n' && *q != ':')
1141  q++;
1142 
1143  if (sscanf(q, ":%d:%d", &stream_no, &rate_no) != 2)
1144  break;
1145 
1146  stream_no--;
1147  if (stream_no < ratelen && stream_no >= 0)
1148  rates[stream_no] = rate_no;
1149 
1150  while (*q && *q != '\n' && !av_isspace(*q))
1151  q++;
1152  }
1153 
1154  return 1;
1155  }
1156  }
1157  p = strchr(p, '\n');
1158  if (!p)
1159  break;
1160 
1161  p++;
1162  }
1163 
1164  return 0;
1165 }
1166 
1167 static int find_stream_in_feed(FFStream *feed, AVCodecContext *codec, int bit_rate)
1168 {
1169  int i;
1170  int best_bitrate = 100000000;
1171  int best = -1;
1172 
1173  for (i = 0; i < feed->nb_streams; i++) {
1174  AVCodecContext *feed_codec = feed->streams[i]->codec;
1175 
1176  if (feed_codec->codec_id != codec->codec_id ||
1177  feed_codec->sample_rate != codec->sample_rate ||
1178  feed_codec->width != codec->width ||
1179  feed_codec->height != codec->height)
1180  continue;
1181 
1182  /* Potential stream */
1183 
1184  /* We want the fastest stream less than bit_rate, or the slowest
1185  * faster than bit_rate
1186  */
1187 
1188  if (feed_codec->bit_rate <= bit_rate) {
1189  if (best_bitrate > bit_rate || feed_codec->bit_rate > best_bitrate) {
1190  best_bitrate = feed_codec->bit_rate;
1191  best = i;
1192  }
1193  } else {
1194  if (feed_codec->bit_rate < best_bitrate) {
1195  best_bitrate = feed_codec->bit_rate;
1196  best = i;
1197  }
1198  }
1199  }
1200 
1201  return best;
1202 }
1203 
1205 {
1206  int i;
1207  FFStream *req = c->stream;
1208  int action_required = 0;
1209 
1210  /* Not much we can do for a feed */
1211  if (!req->feed)
1212  return 0;
1213 
1214  for (i = 0; i < req->nb_streams; i++) {
1215  AVCodecContext *codec = req->streams[i]->codec;
1216 
1217  switch(rates[i]) {
1218  case 0:
1219  c->switch_feed_streams[i] = req->feed_streams[i];
1220  break;
1221  case 1:
1222  c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 2);
1223  break;
1224  case 2:
1225  /* Wants off or slow */
1226  c->switch_feed_streams[i] = find_stream_in_feed(req->feed, codec, codec->bit_rate / 4);
1227 #ifdef WANTS_OFF
1228  /* This doesn't work well when it turns off the only stream! */
1229  c->switch_feed_streams[i] = -2;
1230  c->feed_streams[i] = -2;
1231 #endif
1232  break;
1233  }
1234 
1235  if (c->switch_feed_streams[i] >= 0 && c->switch_feed_streams[i] != c->feed_streams[i])
1236  action_required = 1;
1237  }
1238 
1239  return action_required;
1240 }
1241 
1242 /* XXX: factorize in utils.c ? */
1243 /* XXX: take care with different space meaning */
1244 static void skip_spaces(const char **pp)
1245 {
1246  const char *p;
1247  p = *pp;
1248  while (*p == ' ' || *p == '\t')
1249  p++;
1250  *pp = p;
1251 }
1252 
1253 static void get_word(char *buf, int buf_size, const char **pp)
1254 {
1255  const char *p;
1256  char *q;
1257 
1258  p = *pp;
1259  skip_spaces(&p);
1260  q = buf;
1261  while (!av_isspace(*p) && *p != '\0') {
1262  if ((q - buf) < buf_size - 1)
1263  *q++ = *p;
1264  p++;
1265  }
1266  if (buf_size > 0)
1267  *q = '\0';
1268  *pp = p;
1269 }
1270 
1271 static void get_arg(char *buf, int buf_size, const char **pp)
1272 {
1273  const char *p;
1274  char *q;
1275  int quote;
1276 
1277  p = *pp;
1278  while (av_isspace(*p)) p++;
1279  q = buf;
1280  quote = 0;
1281  if (*p == '\"' || *p == '\'')
1282  quote = *p++;
1283  for(;;) {
1284  if (quote) {
1285  if (*p == quote)
1286  break;
1287  } else {
1288  if (av_isspace(*p))
1289  break;
1290  }
1291  if (*p == '\0')
1292  break;
1293  if ((q - buf) < buf_size - 1)
1294  *q++ = *p;
1295  p++;
1296  }
1297  *q = '\0';
1298  if (quote && *p == quote)
1299  p++;
1300  *pp = p;
1301 }
1302 
1303 static void parse_acl_row(FFStream *stream, FFStream* feed, IPAddressACL *ext_acl,
1304  const char *p, const char *filename, int line_num)
1305 {
1306  char arg[1024];
1307  IPAddressACL acl;
1308  int errors = 0;
1309 
1310  get_arg(arg, sizeof(arg), &p);
1311  if (av_strcasecmp(arg, "allow") == 0)
1312  acl.action = IP_ALLOW;
1313  else if (av_strcasecmp(arg, "deny") == 0)
1314  acl.action = IP_DENY;
1315  else {
1316  fprintf(stderr, "%s:%d: ACL action '%s' is not ALLOW or DENY\n",
1317  filename, line_num, arg);
1318  errors++;
1319  }
1320 
1321  get_arg(arg, sizeof(arg), &p);
1322 
1323  if (resolve_host(&acl.first, arg) != 0) {
1324  fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1325  filename, line_num, arg);
1326  errors++;
1327  } else
1328  acl.last = acl.first;
1329 
1330  get_arg(arg, sizeof(arg), &p);
1331 
1332  if (arg[0]) {
1333  if (resolve_host(&acl.last, arg) != 0) {
1334  fprintf(stderr, "%s:%d: ACL refers to invalid host or ip address '%s'\n",
1335  filename, line_num, arg);
1336  errors++;
1337  }
1338  }
1339 
1340  if (!errors) {
1341  IPAddressACL *nacl = av_mallocz(sizeof(*nacl));
1342  IPAddressACL **naclp = 0;
1343 
1344  acl.next = 0;
1345  *nacl = acl;
1346 
1347  if (stream)
1348  naclp = &stream->acl;
1349  else if (feed)
1350  naclp = &feed->acl;
1351  else if (ext_acl)
1352  naclp = &ext_acl;
1353  else {
1354  fprintf(stderr, "%s:%d: ACL found not in <stream> or <feed>\n",
1355  filename, line_num);
1356  errors++;
1357  }
1358 
1359  if (naclp) {
1360  while (*naclp)
1361  naclp = &(*naclp)->next;
1362 
1363  *naclp = nacl;
1364  }
1365  }
1366 }
1367 
1368 
1370 {
1371  FILE* f;
1372  char line[1024];
1373  char cmd[1024];
1374  IPAddressACL *acl = NULL;
1375  int line_num = 0;
1376  const char *p;
1377 
1378  f = fopen(stream->dynamic_acl, "r");
1379  if (!f) {
1380  perror(stream->dynamic_acl);
1381  return NULL;
1382  }
1383 
1384  acl = av_mallocz(sizeof(IPAddressACL));
1385 
1386  /* Build ACL */
1387  for(;;) {
1388  if (fgets(line, sizeof(line), f) == NULL)
1389  break;
1390  line_num++;
1391  p = line;
1392  while (av_isspace(*p))
1393  p++;
1394  if (*p == '\0' || *p == '#')
1395  continue;
1396  get_arg(cmd, sizeof(cmd), &p);
1397 
1398  if (!av_strcasecmp(cmd, "ACL"))
1399  parse_acl_row(NULL, NULL, acl, p, stream->dynamic_acl, line_num);
1400  }
1401  fclose(f);
1402  return acl;
1403 }
1404 
1405 
1406 static void free_acl_list(IPAddressACL *in_acl)
1407 {
1408  IPAddressACL *pacl,*pacl2;
1409 
1410  pacl = in_acl;
1411  while(pacl) {
1412  pacl2 = pacl;
1413  pacl = pacl->next;
1414  av_freep(pacl2);
1415  }
1416 }
1417 
1419 {
1420  enum IPAddressAction last_action = IP_DENY;
1421  IPAddressACL *acl;
1422  struct in_addr *src = &c->from_addr.sin_addr;
1423  unsigned long src_addr = src->s_addr;
1424 
1425  for (acl = in_acl; acl; acl = acl->next) {
1426  if (src_addr >= acl->first.s_addr && src_addr <= acl->last.s_addr)
1427  return (acl->action == IP_ALLOW) ? 1 : 0;
1428  last_action = acl->action;
1429  }
1430 
1431  /* Nothing matched, so return not the last action */
1432  return (last_action == IP_DENY) ? 1 : 0;
1433 }
1434 
1435 static int validate_acl(FFStream *stream, HTTPContext *c)
1436 {
1437  int ret = 0;
1438  IPAddressACL *acl;
1439 
1440 
1441  /* if stream->acl is null validate_acl_list will return 1 */
1442  ret = validate_acl_list(stream->acl, c);
1443 
1444  if (stream->dynamic_acl[0]) {
1445  acl = parse_dynamic_acl(stream, c);
1446 
1447  ret = validate_acl_list(acl, c);
1448 
1449  free_acl_list(acl);
1450  }
1451 
1452  return ret;
1453 }
1454 
1455 /* compute the real filename of a file by matching it without its
1456  extensions to all the stream filenames */
1457 static void compute_real_filename(char *filename, int max_size)
1458 {
1459  char file1[1024];
1460  char file2[1024];
1461  char *p;
1462  FFStream *stream;
1463 
1464  /* compute filename by matching without the file extensions */
1465  av_strlcpy(file1, filename, sizeof(file1));
1466  p = strrchr(file1, '.');
1467  if (p)
1468  *p = '\0';
1469  for(stream = first_stream; stream != NULL; stream = stream->next) {
1470  av_strlcpy(file2, stream->filename, sizeof(file2));
1471  p = strrchr(file2, '.');
1472  if (p)
1473  *p = '\0';
1474  if (!strcmp(file1, file2)) {
1475  av_strlcpy(filename, stream->filename, max_size);
1476  break;
1477  }
1478  }
1479 }
1480 
1488 };
1489 
1490 /* parse http request and prepare header */
1492 {
1493  const char *p;
1494  char *p1;
1495  enum RedirType redir_type;
1496  char cmd[32];
1497  char info[1024], filename[1024];
1498  char url[1024], *q;
1499  char protocol[32];
1500  char msg[1024];
1501  const char *mime_type;
1502  FFStream *stream;
1503  int i;
1504  char ratebuf[32];
1505  const char *useragent = 0;
1506 
1507  p = c->buffer;
1508  get_word(cmd, sizeof(cmd), &p);
1509  av_strlcpy(c->method, cmd, sizeof(c->method));
1510 
1511  if (!strcmp(cmd, "GET"))
1512  c->post = 0;
1513  else if (!strcmp(cmd, "POST"))
1514  c->post = 1;
1515  else
1516  return -1;
1517 
1518  get_word(url, sizeof(url), &p);
1519  av_strlcpy(c->url, url, sizeof(c->url));
1520 
1521  get_word(protocol, sizeof(protocol), (const char **)&p);
1522  if (strcmp(protocol, "HTTP/1.0") && strcmp(protocol, "HTTP/1.1"))
1523  return -1;
1524 
1525  av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
1526 
1527  if (ffserver_debug)
1528  http_log("%s - - New connection: %s %s\n", inet_ntoa(c->from_addr.sin_addr), cmd, url);
1529 
1530  /* find the filename and the optional info string in the request */
1531  p1 = strchr(url, '?');
1532  if (p1) {
1533  av_strlcpy(info, p1, sizeof(info));
1534  *p1 = '\0';
1535  } else
1536  info[0] = '\0';
1537 
1538  av_strlcpy(filename, url + ((*url == '/') ? 1 : 0), sizeof(filename)-1);
1539 
1540  for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1541  if (av_strncasecmp(p, "User-Agent:", 11) == 0) {
1542  useragent = p + 11;
1543  if (*useragent && *useragent != '\n' && av_isspace(*useragent))
1544  useragent++;
1545  break;
1546  }
1547  p = strchr(p, '\n');
1548  if (!p)
1549  break;
1550 
1551  p++;
1552  }
1553 
1554  redir_type = REDIR_NONE;
1555  if (av_match_ext(filename, "asx")) {
1556  redir_type = REDIR_ASX;
1557  filename[strlen(filename)-1] = 'f';
1558  } else if (av_match_ext(filename, "asf") &&
1559  (!useragent || av_strncasecmp(useragent, "NSPlayer", 8) != 0)) {
1560  /* if this isn't WMP or lookalike, return the redirector file */
1561  redir_type = REDIR_ASF;
1562  } else if (av_match_ext(filename, "rpm,ram")) {
1563  redir_type = REDIR_RAM;
1564  strcpy(filename + strlen(filename)-2, "m");
1565  } else if (av_match_ext(filename, "rtsp")) {
1566  redir_type = REDIR_RTSP;
1567  compute_real_filename(filename, sizeof(filename) - 1);
1568  } else if (av_match_ext(filename, "sdp")) {
1569  redir_type = REDIR_SDP;
1570  compute_real_filename(filename, sizeof(filename) - 1);
1571  }
1572 
1573  // "redirect" / request to index.html
1574  if (!strlen(filename))
1575  av_strlcpy(filename, "index.html", sizeof(filename) - 1);
1576 
1577  stream = first_stream;
1578  while (stream != NULL) {
1579  if (!strcmp(stream->filename, filename) && validate_acl(stream, c))
1580  break;
1581  stream = stream->next;
1582  }
1583  if (stream == NULL) {
1584  snprintf(msg, sizeof(msg), "File '%s' not found", url);
1585  http_log("File '%s' not found\n", url);
1586  goto send_error;
1587  }
1588 
1589  c->stream = stream;
1590  memcpy(c->feed_streams, stream->feed_streams, sizeof(c->feed_streams));
1591  memset(c->switch_feed_streams, -1, sizeof(c->switch_feed_streams));
1592 
1593  if (stream->stream_type == STREAM_TYPE_REDIRECT) {
1594  c->http_error = 301;
1595  q = c->buffer;
1596  snprintf(q, c->buffer_size,
1597  "HTTP/1.0 301 Moved\r\n"
1598  "Location: %s\r\n"
1599  "Content-type: text/html\r\n"
1600  "\r\n"
1601  "<html><head><title>Moved</title></head><body>\r\n"
1602  "You should be <a href=\"%s\">redirected</a>.\r\n"
1603  "</body></html>\r\n", stream->feed_filename, stream->feed_filename);
1604  q += strlen(q);
1605  /* prepare output buffer */
1606  c->buffer_ptr = c->buffer;
1607  c->buffer_end = q;
1609  return 0;
1610  }
1611 
1612  /* If this is WMP, get the rate information */
1613  if (extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1614  if (modify_current_stream(c, ratebuf)) {
1615  for (i = 0; i < FF_ARRAY_ELEMS(c->feed_streams); i++) {
1616  if (c->switch_feed_streams[i] >= 0)
1617  c->switch_feed_streams[i] = -1;
1618  }
1619  }
1620  }
1621 
1622  if (c->post == 0 && stream->stream_type == STREAM_TYPE_LIVE)
1623  current_bandwidth += stream->bandwidth;
1624 
1625  /* If already streaming this feed, do not let start another feeder. */
1626  if (stream->feed_opened) {
1627  snprintf(msg, sizeof(msg), "This feed is already being received.");
1628  http_log("Feed '%s' already being received\n", stream->feed_filename);
1629  goto send_error;
1630  }
1631 
1632  if (c->post == 0 && max_bandwidth < current_bandwidth) {
1633  c->http_error = 503;
1634  q = c->buffer;
1635  snprintf(q, c->buffer_size,
1636  "HTTP/1.0 503 Server too busy\r\n"
1637  "Content-type: text/html\r\n"
1638  "\r\n"
1639  "<html><head><title>Too busy</title></head><body>\r\n"
1640  "<p>The server is too busy to serve your request at this time.</p>\r\n"
1641  "<p>The bandwidth being served (including your stream) is %"PRIu64"kbit/sec, "
1642  "and this exceeds the limit of %"PRIu64"kbit/sec.</p>\r\n"
1643  "</body></html>\r\n", current_bandwidth, max_bandwidth);
1644  q += strlen(q);
1645  /* prepare output buffer */
1646  c->buffer_ptr = c->buffer;
1647  c->buffer_end = q;
1649  return 0;
1650  }
1651 
1652  if (redir_type != REDIR_NONE) {
1653  const char *hostinfo = 0;
1654 
1655  for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1656  if (av_strncasecmp(p, "Host:", 5) == 0) {
1657  hostinfo = p + 5;
1658  break;
1659  }
1660  p = strchr(p, '\n');
1661  if (!p)
1662  break;
1663 
1664  p++;
1665  }
1666 
1667  if (hostinfo) {
1668  char *eoh;
1669  char hostbuf[260];
1670 
1671  while (av_isspace(*hostinfo))
1672  hostinfo++;
1673 
1674  eoh = strchr(hostinfo, '\n');
1675  if (eoh) {
1676  if (eoh[-1] == '\r')
1677  eoh--;
1678 
1679  if (eoh - hostinfo < sizeof(hostbuf) - 1) {
1680  memcpy(hostbuf, hostinfo, eoh - hostinfo);
1681  hostbuf[eoh - hostinfo] = 0;
1682 
1683  c->http_error = 200;
1684  q = c->buffer;
1685  switch(redir_type) {
1686  case REDIR_ASX:
1687  snprintf(q, c->buffer_size,
1688  "HTTP/1.0 200 ASX Follows\r\n"
1689  "Content-type: video/x-ms-asf\r\n"
1690  "\r\n"
1691  "<ASX Version=\"3\">\r\n"
1692  //"<!-- Autogenerated by ffserver -->\r\n"
1693  "<ENTRY><REF HREF=\"http://%s/%s%s\"/></ENTRY>\r\n"
1694  "</ASX>\r\n", hostbuf, filename, info);
1695  q += strlen(q);
1696  break;
1697  case REDIR_RAM:
1698  snprintf(q, c->buffer_size,
1699  "HTTP/1.0 200 RAM Follows\r\n"
1700  "Content-type: audio/x-pn-realaudio\r\n"
1701  "\r\n"
1702  "# Autogenerated by ffserver\r\n"
1703  "http://%s/%s%s\r\n", hostbuf, filename, info);
1704  q += strlen(q);
1705  break;
1706  case REDIR_ASF:
1707  snprintf(q, c->buffer_size,
1708  "HTTP/1.0 200 ASF Redirect follows\r\n"
1709  "Content-type: video/x-ms-asf\r\n"
1710  "\r\n"
1711  "[Reference]\r\n"
1712  "Ref1=http://%s/%s%s\r\n", hostbuf, filename, info);
1713  q += strlen(q);
1714  break;
1715  case REDIR_RTSP:
1716  {
1717  char hostname[256], *p;
1718  /* extract only hostname */
1719  av_strlcpy(hostname, hostbuf, sizeof(hostname));
1720  p = strrchr(hostname, ':');
1721  if (p)
1722  *p = '\0';
1723  snprintf(q, c->buffer_size,
1724  "HTTP/1.0 200 RTSP Redirect follows\r\n"
1725  /* XXX: incorrect mime type ? */
1726  "Content-type: application/x-rtsp\r\n"
1727  "\r\n"
1728  "rtsp://%s:%d/%s\r\n", hostname, ntohs(my_rtsp_addr.sin_port), filename);
1729  q += strlen(q);
1730  }
1731  break;
1732  case REDIR_SDP:
1733  {
1734  uint8_t *sdp_data;
1735  int sdp_data_size;
1736  socklen_t len;
1737  struct sockaddr_in my_addr;
1738 
1739  snprintf(q, c->buffer_size,
1740  "HTTP/1.0 200 OK\r\n"
1741  "Content-type: application/sdp\r\n"
1742  "\r\n");
1743  q += strlen(q);
1744 
1745  len = sizeof(my_addr);
1746  getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
1747 
1748  /* XXX: should use a dynamic buffer */
1749  sdp_data_size = prepare_sdp_description(stream,
1750  &sdp_data,
1751  my_addr.sin_addr);
1752  if (sdp_data_size > 0) {
1753  memcpy(q, sdp_data, sdp_data_size);
1754  q += sdp_data_size;
1755  *q = '\0';
1756  av_free(sdp_data);
1757  }
1758  }
1759  break;
1760  default:
1761  abort();
1762  break;
1763  }
1764 
1765  /* prepare output buffer */
1766  c->buffer_ptr = c->buffer;
1767  c->buffer_end = q;
1769  return 0;
1770  }
1771  }
1772  }
1773 
1774  snprintf(msg, sizeof(msg), "ASX/RAM file not handled");
1775  goto send_error;
1776  }
1777 
1778  stream->conns_served++;
1779 
1780  /* XXX: add there authenticate and IP match */
1781 
1782  if (c->post) {
1783  /* if post, it means a feed is being sent */
1784  if (!stream->is_feed) {
1785  /* However it might be a status report from WMP! Let us log the
1786  * data as it might come in handy one day. */
1787  const char *logline = 0;
1788  int client_id = 0;
1789 
1790  for (p = c->buffer; *p && *p != '\r' && *p != '\n'; ) {
1791  if (av_strncasecmp(p, "Pragma: log-line=", 17) == 0) {
1792  logline = p;
1793  break;
1794  }
1795  if (av_strncasecmp(p, "Pragma: client-id=", 18) == 0)
1796  client_id = strtol(p + 18, 0, 10);
1797  p = strchr(p, '\n');
1798  if (!p)
1799  break;
1800 
1801  p++;
1802  }
1803 
1804  if (logline) {
1805  char *eol = strchr(logline, '\n');
1806 
1807  logline += 17;
1808 
1809  if (eol) {
1810  if (eol[-1] == '\r')
1811  eol--;
1812  http_log("%.*s\n", (int) (eol - logline), logline);
1813  c->suppress_log = 1;
1814  }
1815  }
1816 
1817 #ifdef DEBUG
1818  http_log("\nGot request:\n%s\n", c->buffer);
1819 #endif
1820 
1821  if (client_id && extract_rates(ratebuf, sizeof(ratebuf), c->buffer)) {
1822  HTTPContext *wmpc;
1823 
1824  /* Now we have to find the client_id */
1825  for (wmpc = first_http_ctx; wmpc; wmpc = wmpc->next) {
1826  if (wmpc->wmp_client_id == client_id)
1827  break;
1828  }
1829 
1830  if (wmpc && modify_current_stream(wmpc, ratebuf))
1831  wmpc->switch_pending = 1;
1832  }
1833 
1834  snprintf(msg, sizeof(msg), "POST command not handled");
1835  c->stream = 0;
1836  goto send_error;
1837  }
1838  if (http_start_receive_data(c) < 0) {
1839  snprintf(msg, sizeof(msg), "could not open feed");
1840  goto send_error;
1841  }
1842  c->http_error = 0;
1844  return 0;
1845  }
1846 
1847 #ifdef DEBUG
1848  if (strcmp(stream->filename + strlen(stream->filename) - 4, ".asf") == 0)
1849  http_log("\nGot request:\n%s\n", c->buffer);
1850 #endif
1851 
1853  goto send_status;
1854 
1855  /* open input stream */
1856  if (open_input_stream(c, info) < 0) {
1857  snprintf(msg, sizeof(msg), "Input stream corresponding to '%s' not found", url);
1858  goto send_error;
1859  }
1860 
1861  /* prepare http header */
1862  c->buffer[0] = 0;
1863  av_strlcatf(c->buffer, c->buffer_size, "HTTP/1.0 200 OK\r\n");
1864  mime_type = c->stream->fmt->mime_type;
1865  if (!mime_type)
1866  mime_type = "application/x-octet-stream";
1867  av_strlcatf(c->buffer, c->buffer_size, "Pragma: no-cache\r\n");
1868 
1869  /* for asf, we need extra headers */
1870  if (!strcmp(c->stream->fmt->name,"asf_stream")) {
1871  /* Need to allocate a client id */
1872 
1873  c->wmp_client_id = av_lfg_get(&random_state);
1874 
1875  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);
1876  }
1877  av_strlcatf(c->buffer, c->buffer_size, "Content-Type: %s\r\n", mime_type);
1878  av_strlcatf(c->buffer, c->buffer_size, "\r\n");
1879  q = c->buffer + strlen(c->buffer);
1880 
1881  /* prepare output buffer */
1882  c->http_error = 0;
1883  c->buffer_ptr = c->buffer;
1884  c->buffer_end = q;
1886  return 0;
1887  send_error:
1888  c->http_error = 404;
1889  q = c->buffer;
1890  snprintf(q, c->buffer_size,
1891  "HTTP/1.0 404 Not Found\r\n"
1892  "Content-type: text/html\r\n"
1893  "\r\n"
1894  "<html>\n"
1895  "<head><title>404 Not Found</title></head>\n"
1896  "<body>%s</body>\n"
1897  "</html>\n", msg);
1898  q += strlen(q);
1899  /* prepare output buffer */
1900  c->buffer_ptr = c->buffer;
1901  c->buffer_end = q;
1903  return 0;
1904  send_status:
1905  compute_status(c);
1906  c->http_error = 200; /* horrible : we use this value to avoid
1907  going to the send data state */
1909  return 0;
1910 }
1911 
1912 static void fmt_bytecount(AVIOContext *pb, int64_t count)
1913 {
1914  static const char suffix[] = " kMGTP";
1915  const char *s;
1916 
1917  for (s = suffix; count >= 100000 && s[1]; count /= 1000, s++);
1918 
1919  avio_printf(pb, "%"PRId64"%c", count, *s);
1920 }
1921 
1923 {
1924  HTTPContext *c1;
1925  FFStream *stream;
1926  char *p;
1927  time_t ti;
1928  int i, len;
1929  AVIOContext *pb;
1930 
1931  if (avio_open_dyn_buf(&pb) < 0) {
1932  /* XXX: return an error ? */
1933  c->buffer_ptr = c->buffer;
1934  c->buffer_end = c->buffer;
1935  return;
1936  }
1937 
1938  avio_printf(pb, "HTTP/1.0 200 OK\r\n");
1939  avio_printf(pb, "Content-type: %s\r\n", "text/html");
1940  avio_printf(pb, "Pragma: no-cache\r\n");
1941  avio_printf(pb, "\r\n");
1942 
1943  avio_printf(pb, "<html><head><title>%s Status</title>\n", program_name);
1944  if (c->stream->feed_filename[0])
1945  avio_printf(pb, "<link rel=\"shortcut icon\" href=\"%s\">\n", c->stream->feed_filename);
1946  avio_printf(pb, "</head>\n<body>");
1947  avio_printf(pb, "<h1>%s Status</h1>\n", program_name);
1948  /* format status */
1949  avio_printf(pb, "<h2>Available Streams</h2>\n");
1950  avio_printf(pb, "<table cellspacing=0 cellpadding=4>\n");
1951  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");
1952  stream = first_stream;
1953  while (stream != NULL) {
1954  char sfilename[1024];
1955  char *eosf;
1956 
1957  if (stream->feed != stream) {
1958  av_strlcpy(sfilename, stream->filename, sizeof(sfilename) - 10);
1959  eosf = sfilename + strlen(sfilename);
1960  if (eosf - sfilename >= 4) {
1961  if (strcmp(eosf - 4, ".asf") == 0)
1962  strcpy(eosf - 4, ".asx");
1963  else if (strcmp(eosf - 3, ".rm") == 0)
1964  strcpy(eosf - 3, ".ram");
1965  else if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
1966  /* generate a sample RTSP director if
1967  unicast. Generate an SDP redirector if
1968  multicast */
1969  eosf = strrchr(sfilename, '.');
1970  if (!eosf)
1971  eosf = sfilename + strlen(sfilename);
1972  if (stream->is_multicast)
1973  strcpy(eosf, ".sdp");
1974  else
1975  strcpy(eosf, ".rtsp");
1976  }
1977  }
1978 
1979  avio_printf(pb, "<tr><td><a href=\"/%s\">%s</a> ",
1980  sfilename, stream->filename);
1981  avio_printf(pb, "<td align=right> %d <td align=right> ",
1982  stream->conns_served);
1983  fmt_bytecount(pb, stream->bytes_served);
1984  switch(stream->stream_type) {
1985  case STREAM_TYPE_LIVE: {
1986  int audio_bit_rate = 0;
1987  int video_bit_rate = 0;
1988  const char *audio_codec_name = "";
1989  const char *video_codec_name = "";
1990  const char *audio_codec_name_extra = "";
1991  const char *video_codec_name_extra = "";
1992 
1993  for(i=0;i<stream->nb_streams;i++) {
1994  AVStream *st = stream->streams[i];
1995  AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
1996  switch(st->codec->codec_type) {
1997  case AVMEDIA_TYPE_AUDIO:
1998  audio_bit_rate += st->codec->bit_rate;
1999  if (codec) {
2000  if (*audio_codec_name)
2001  audio_codec_name_extra = "...";
2002  audio_codec_name = codec->name;
2003  }
2004  break;
2005  case AVMEDIA_TYPE_VIDEO:
2006  video_bit_rate += st->codec->bit_rate;
2007  if (codec) {
2008  if (*video_codec_name)
2009  video_codec_name_extra = "...";
2010  video_codec_name = codec->name;
2011  }
2012  break;
2013  case AVMEDIA_TYPE_DATA:
2014  video_bit_rate += st->codec->bit_rate;
2015  break;
2016  default:
2017  abort();
2018  }
2019  }
2020  avio_printf(pb, "<td align=center> %s <td align=right> %d <td align=right> %d <td> %s %s <td align=right> %d <td> %s %s",
2021  stream->fmt->name,
2022  stream->bandwidth,
2023  video_bit_rate / 1000, video_codec_name, video_codec_name_extra,
2024  audio_bit_rate / 1000, audio_codec_name, audio_codec_name_extra);
2025  if (stream->feed)
2026  avio_printf(pb, "<td>%s", stream->feed->filename);
2027  else
2028  avio_printf(pb, "<td>%s", stream->feed_filename);
2029  avio_printf(pb, "\n");
2030  }
2031  break;
2032  default:
2033  avio_printf(pb, "<td align=center> - <td align=right> - <td align=right> - <td><td align=right> - <td>\n");
2034  break;
2035  }
2036  }
2037  stream = stream->next;
2038  }
2039  avio_printf(pb, "</table>\n");
2040 
2041  stream = first_stream;
2042  while (stream != NULL) {
2043  if (stream->feed == stream) {
2044  avio_printf(pb, "<h2>Feed %s</h2>", stream->filename);
2045  if (stream->pid) {
2046  avio_printf(pb, "Running as pid %d.\n", stream->pid);
2047 
2048 #if defined(linux)
2049  {
2050  FILE *pid_stat;
2051  char ps_cmd[64];
2052 
2053  /* This is somewhat linux specific I guess */
2054  snprintf(ps_cmd, sizeof(ps_cmd),
2055  "ps -o \"%%cpu,cputime\" --no-headers %d",
2056  stream->pid);
2057 
2058  pid_stat = popen(ps_cmd, "r");
2059  if (pid_stat) {
2060  char cpuperc[10];
2061  char cpuused[64];
2062 
2063  if (fscanf(pid_stat, "%9s %63s", cpuperc,
2064  cpuused) == 2) {
2065  avio_printf(pb, "Currently using %s%% of the cpu. Total time used %s.\n",
2066  cpuperc, cpuused);
2067  }
2068  fclose(pid_stat);
2069  }
2070  }
2071 #endif
2072 
2073  avio_printf(pb, "<p>");
2074  }
2075  avio_printf(pb, "<table cellspacing=0 cellpadding=4><tr><th>Stream<th>type<th>kbits/s<th align=left>codec<th align=left>Parameters\n");
2076 
2077  for (i = 0; i < stream->nb_streams; i++) {
2078  AVStream *st = stream->streams[i];
2079  AVCodec *codec = avcodec_find_encoder(st->codec->codec_id);
2080  const char *type = "unknown";
2081  char parameters[64];
2082 
2083  parameters[0] = 0;
2084 
2085  switch(st->codec->codec_type) {
2086  case AVMEDIA_TYPE_AUDIO:
2087  type = "audio";
2088  snprintf(parameters, sizeof(parameters), "%d channel(s), %d Hz", st->codec->channels, st->codec->sample_rate);
2089  break;
2090  case AVMEDIA_TYPE_VIDEO:
2091  type = "video";
2092  snprintf(parameters, sizeof(parameters), "%dx%d, q=%d-%d, fps=%d", st->codec->width, st->codec->height,
2093  st->codec->qmin, st->codec->qmax, st->codec->time_base.den / st->codec->time_base.num);
2094  break;
2095  default:
2096  abort();
2097  }
2098  avio_printf(pb, "<tr><td align=right>%d<td>%s<td align=right>%d<td>%s<td>%s\n",
2099  i, type, st->codec->bit_rate/1000, codec ? codec->name : "", parameters);
2100  }
2101  avio_printf(pb, "</table>\n");
2102 
2103  }
2104  stream = stream->next;
2105  }
2106 
2107  /* connection status */
2108  avio_printf(pb, "<h2>Connection Status</h2>\n");
2109 
2110  avio_printf(pb, "Number of connections: %d / %d<br>\n",
2112 
2113  avio_printf(pb, "Bandwidth in use: %"PRIu64"k / %"PRIu64"k<br>\n",
2115 
2116  avio_printf(pb, "<table>\n");
2117  avio_printf(pb, "<tr><th>#<th>File<th>IP<th>Proto<th>State<th>Target bits/sec<th>Actual bits/sec<th>Bytes transferred\n");
2118  c1 = first_http_ctx;
2119  i = 0;
2120  while (c1 != NULL) {
2121  int bitrate;
2122  int j;
2123 
2124  bitrate = 0;
2125  if (c1->stream) {
2126  for (j = 0; j < c1->stream->nb_streams; j++) {
2127  if (!c1->stream->feed)
2128  bitrate += c1->stream->streams[j]->codec->bit_rate;
2129  else if (c1->feed_streams[j] >= 0)
2130  bitrate += c1->stream->feed->streams[c1->feed_streams[j]]->codec->bit_rate;
2131  }
2132  }
2133 
2134  i++;
2135  p = inet_ntoa(c1->from_addr.sin_addr);
2136  avio_printf(pb, "<tr><td><b>%d</b><td>%s%s<td>%s<td>%s<td>%s<td align=right>",
2137  i,
2138  c1->stream ? c1->stream->filename : "",
2139  c1->state == HTTPSTATE_RECEIVE_DATA ? "(input)" : "",
2140  p,
2141  c1->protocol,
2142  http_state[c1->state]);
2143  fmt_bytecount(pb, bitrate);
2144  avio_printf(pb, "<td align=right>");
2145  fmt_bytecount(pb, compute_datarate(&c1->datarate, c1->data_count) * 8);
2146  avio_printf(pb, "<td align=right>");
2147  fmt_bytecount(pb, c1->data_count);
2148  avio_printf(pb, "\n");
2149  c1 = c1->next;
2150  }
2151  avio_printf(pb, "</table>\n");
2152 
2153  /* date */
2154  ti = time(NULL);
2155  p = ctime(&ti);
2156  avio_printf(pb, "<hr size=1 noshade>Generated at %s", p);
2157  avio_printf(pb, "</body>\n</html>\n");
2158 
2159  len = avio_close_dyn_buf(pb, &c->pb_buffer);
2160  c->buffer_ptr = c->pb_buffer;
2161  c->buffer_end = c->pb_buffer + len;
2162 }
2163 
2164 static int open_input_stream(HTTPContext *c, const char *info)
2165 {
2166  char buf[128];
2167  char input_filename[1024];
2168  AVFormatContext *s = NULL;
2169  int buf_size, i, ret;
2170  int64_t stream_pos;
2171 
2172  /* find file name */
2173  if (c->stream->feed) {
2174  strcpy(input_filename, c->stream->feed->feed_filename);
2175  buf_size = FFM_PACKET_SIZE;
2176  /* compute position (absolute time) */
2177  if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2178  if ((ret = av_parse_time(&stream_pos, buf, 0)) < 0)
2179  return ret;
2180  } else if (av_find_info_tag(buf, sizeof(buf), "buffer", info)) {
2181  int prebuffer = strtol(buf, 0, 10);
2182  stream_pos = av_gettime() - prebuffer * (int64_t)1000000;
2183  } else
2184  stream_pos = av_gettime() - c->stream->prebuffer * (int64_t)1000;
2185  } else {
2186  strcpy(input_filename, c->stream->feed_filename);
2187  buf_size = 0;
2188  /* compute position (relative time) */
2189  if (av_find_info_tag(buf, sizeof(buf), "date", info)) {
2190  if ((ret = av_parse_time(&stream_pos, buf, 1)) < 0)
2191  return ret;
2192  } else
2193  stream_pos = 0;
2194  }
2195  if (input_filename[0] == '\0')
2196  return -1;
2197 
2198  /* open stream */
2199  if ((ret = avformat_open_input(&s, input_filename, c->stream->ifmt, &c->stream->in_opts)) < 0) {
2200  http_log("could not open %s: %d\n", input_filename, ret);
2201  return -1;
2202  }
2203 
2204  /* set buffer size */
2205  if (buf_size > 0) ffio_set_buf_size(s->pb, buf_size);
2206 
2207  s->flags |= AVFMT_FLAG_GENPTS;
2208  c->fmt_in = s;
2209  if (strcmp(s->iformat->name, "ffm") && avformat_find_stream_info(c->fmt_in, NULL) < 0) {
2210  http_log("Could not find stream info '%s'\n", input_filename);
2212  return -1;
2213  }
2214 
2215  /* choose stream as clock source (we favorize video stream if
2216  present) for packet sending */
2217  c->pts_stream_index = 0;
2218  for(i=0;i<c->stream->nb_streams;i++) {
2219  if (c->pts_stream_index == 0 &&
2221  c->pts_stream_index = i;
2222  }
2223  }
2224 
2225  if (c->fmt_in->iformat->read_seek)
2226  av_seek_frame(c->fmt_in, -1, stream_pos, 0);
2227  /* set the start time (needed for maxtime and RTP packet timing) */
2228  c->start_time = cur_time;
2230  return 0;
2231 }
2232 
2233 /* return the server clock (in us) */
2235 {
2236  /* compute current pts value from system time */
2237  return (cur_time - c->start_time) * 1000;
2238 }
2239 
2240 /* return the estimated time at which the current packet must be sent
2241  (in us) */
2243 {
2244  int bytes_left, bytes_sent, frame_bytes;
2245 
2246  frame_bytes = c->cur_frame_bytes;
2247  if (frame_bytes <= 0)
2248  return c->cur_pts;
2249  else {
2250  bytes_left = c->buffer_end - c->buffer_ptr;
2251  bytes_sent = frame_bytes - bytes_left;
2252  return c->cur_pts + (c->cur_frame_duration * bytes_sent) / frame_bytes;
2253  }
2254 }
2255 
2256 
2258 {
2259  int i, len, ret;
2260  AVFormatContext *ctx;
2261 
2262  av_freep(&c->pb_buffer);
2263  switch(c->state) {
2265  memset(&c->fmt_ctx, 0, sizeof(c->fmt_ctx));
2266  av_dict_set(&c->fmt_ctx.metadata, "author" , c->stream->author , 0);
2267  av_dict_set(&c->fmt_ctx.metadata, "comment" , c->stream->comment , 0);
2268  av_dict_set(&c->fmt_ctx.metadata, "copyright", c->stream->copyright, 0);
2269  av_dict_set(&c->fmt_ctx.metadata, "title" , c->stream->title , 0);
2270 
2271  c->fmt_ctx.streams = av_mallocz(sizeof(AVStream *) * c->stream->nb_streams);
2272 
2273  for(i=0;i<c->stream->nb_streams;i++) {
2274  AVStream *src;
2275  c->fmt_ctx.streams[i] = av_mallocz(sizeof(AVStream));
2276  /* if file or feed, then just take streams from FFStream struct */
2277  if (!c->stream->feed ||
2278  c->stream->feed == c->stream)
2279  src = c->stream->streams[i];
2280  else
2281  src = c->stream->feed->streams[c->stream->feed_streams[i]];
2282 
2283  *(c->fmt_ctx.streams[i]) = *src;
2284  c->fmt_ctx.streams[i]->priv_data = 0;
2285  c->fmt_ctx.streams[i]->codec->frame_number = 0; /* XXX: should be done in
2286  AVStream, not in codec */
2287  }
2288  /* set output format parameters */
2289  c->fmt_ctx.oformat = c->stream->fmt;
2291 
2292  c->got_key_frame = 0;
2293 
2294  /* prepare header and save header data in a stream */
2295  if (avio_open_dyn_buf(&c->fmt_ctx.pb) < 0) {
2296  /* XXX: potential leak */
2297  return -1;
2298  }
2299  c->fmt_ctx.pb->seekable = 0;
2300 
2301  /*
2302  * HACK to avoid mpeg ps muxer to spit many underflow errors
2303  * Default value from FFmpeg
2304  * Try to set it use configuration option
2305  */
2306  c->fmt_ctx.max_delay = (int)(0.7*AV_TIME_BASE);
2307 
2308  if (avformat_write_header(&c->fmt_ctx, NULL) < 0) {
2309  http_log("Error writing output header\n");
2310  return -1;
2311  }
2313 
2314  len = avio_close_dyn_buf(c->fmt_ctx.pb, &c->pb_buffer);
2315  c->buffer_ptr = c->pb_buffer;
2316  c->buffer_end = c->pb_buffer + len;
2317 
2319  c->last_packet_sent = 0;
2320  break;
2321  case HTTPSTATE_SEND_DATA:
2322  /* find a new packet */
2323  /* read a packet from the input stream */
2324  if (c->stream->feed)
2327  c->stream->feed->feed_size);
2328 
2329  if (c->stream->max_time &&
2330  c->stream->max_time + c->start_time - cur_time < 0)
2331  /* We have timed out */
2333  else {
2334  AVPacket pkt;
2335  redo:
2336  ret = av_read_frame(c->fmt_in, &pkt);
2337  if (ret < 0) {
2338  if (c->stream->feed) {
2339  /* if coming from feed, it means we reached the end of the
2340  ffm file, so must wait for more data */
2342  return 1; /* state changed */
2343  } else if (ret == AVERROR(EAGAIN)) {
2344  /* input not ready, come back later */
2345  return 0;
2346  } else {
2347  if (c->stream->loop) {
2349  if (open_input_stream(c, "") < 0)
2350  goto no_loop;
2351  goto redo;
2352  } else {
2353  no_loop:
2354  /* must send trailer now because eof or error */
2356  }
2357  }
2358  } else {
2359  int source_index = pkt.stream_index;
2360  /* update first pts if needed */
2361  if (c->first_pts == AV_NOPTS_VALUE) {
2363  c->start_time = cur_time;
2364  }
2365  /* send it to the appropriate stream */
2366  if (c->stream->feed) {
2367  /* if coming from a feed, select the right stream */
2368  if (c->switch_pending) {
2369  c->switch_pending = 0;
2370  for(i=0;i<c->stream->nb_streams;i++) {
2371  if (c->switch_feed_streams[i] == pkt.stream_index)
2372  if (pkt.flags & AV_PKT_FLAG_KEY)
2373  c->switch_feed_streams[i] = -1;
2374  if (c->switch_feed_streams[i] >= 0)
2375  c->switch_pending = 1;
2376  }
2377  }
2378  for(i=0;i<c->stream->nb_streams;i++) {
2379  if (c->stream->feed_streams[i] == pkt.stream_index) {
2380  AVStream *st = c->fmt_in->streams[source_index];
2381  pkt.stream_index = i;
2382  if (pkt.flags & AV_PKT_FLAG_KEY &&
2383  (st->codec->codec_type == AVMEDIA_TYPE_VIDEO ||
2384  c->stream->nb_streams == 1))
2385  c->got_key_frame = 1;
2386  if (!c->stream->send_on_key || c->got_key_frame)
2387  goto send_it;
2388  }
2389  }
2390  } else {
2391  AVCodecContext *codec;
2392  AVStream *ist, *ost;
2393  send_it:
2394  ist = c->fmt_in->streams[source_index];
2395  /* specific handling for RTP: we use several
2396  output stream (one for each RTP
2397  connection). XXX: need more abstract handling */
2398  if (c->is_packetized) {
2399  /* compute send time and duration */
2400  c->cur_pts = av_rescale_q(pkt.dts, ist->time_base, AV_TIME_BASE_Q);
2401  c->cur_pts -= c->first_pts;
2403  /* find RTP context */
2405  ctx = c->rtp_ctx[c->packet_stream_index];
2406  if(!ctx) {
2407  av_free_packet(&pkt);
2408  break;
2409  }
2410  codec = ctx->streams[0]->codec;
2411  /* only one stream per RTP connection */
2412  pkt.stream_index = 0;
2413  } else {
2414  ctx = &c->fmt_ctx;
2415  /* Fudge here */
2416  codec = ctx->streams[pkt.stream_index]->codec;
2417  }
2418 
2419  if (c->is_packetized) {
2420  int max_packet_size;
2422  max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
2423  else
2424  max_packet_size = c->rtp_handles[c->packet_stream_index]->max_packet_size;
2425  ret = ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size);
2426  } else {
2427  ret = avio_open_dyn_buf(&ctx->pb);
2428  }
2429  if (ret < 0) {
2430  /* XXX: potential leak */
2431  return -1;
2432  }
2433  ost = ctx->streams[pkt.stream_index];
2434 
2435  ctx->pb->seekable = 0;
2436  if (pkt.dts != AV_NOPTS_VALUE)
2437  pkt.dts = av_rescale_q(pkt.dts, ist->time_base, ost->time_base);
2438  if (pkt.pts != AV_NOPTS_VALUE)
2439  pkt.pts = av_rescale_q(pkt.pts, ist->time_base, ost->time_base);
2440  pkt.duration = av_rescale_q(pkt.duration, ist->time_base, ost->time_base);
2441  if (av_write_frame(ctx, &pkt) < 0) {
2442  http_log("Error writing frame to output\n");
2444  }
2445 
2446  len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2447  c->cur_frame_bytes = len;
2448  c->buffer_ptr = c->pb_buffer;
2449  c->buffer_end = c->pb_buffer + len;
2450 
2451  codec->frame_number++;
2452  if (len == 0) {
2453  av_free_packet(&pkt);
2454  goto redo;
2455  }
2456  }
2457  av_free_packet(&pkt);
2458  }
2459  }
2460  break;
2461  default:
2463  /* last packet test ? */
2464  if (c->last_packet_sent || c->is_packetized)
2465  return -1;
2466  ctx = &c->fmt_ctx;
2467  /* prepare header */
2468  if (avio_open_dyn_buf(&ctx->pb) < 0) {
2469  /* XXX: potential leak */
2470  return -1;
2471  }
2472  c->fmt_ctx.pb->seekable = 0;
2473  av_write_trailer(ctx);
2474  len = avio_close_dyn_buf(ctx->pb, &c->pb_buffer);
2475  c->buffer_ptr = c->pb_buffer;
2476  c->buffer_end = c->pb_buffer + len;
2477 
2478  c->last_packet_sent = 1;
2479  break;
2480  }
2481  return 0;
2482 }
2483 
2484 /* should convert the format at the same time */
2485 /* send data starting at c->buffer_ptr to the output connection
2486  (either UDP or TCP connection) */
2488 {
2489  int len, ret;
2490 
2491  for(;;) {
2492  if (c->buffer_ptr >= c->buffer_end) {
2493  ret = http_prepare_data(c);
2494  if (ret < 0)
2495  return -1;
2496  else if (ret != 0)
2497  /* state change requested */
2498  break;
2499  } else {
2500  if (c->is_packetized) {
2501  /* RTP data output */
2502  len = c->buffer_end - c->buffer_ptr;
2503  if (len < 4) {
2504  /* fail safe - should never happen */
2505  fail1:
2506  c->buffer_ptr = c->buffer_end;
2507  return 0;
2508  }
2509  len = (c->buffer_ptr[0] << 24) |
2510  (c->buffer_ptr[1] << 16) |
2511  (c->buffer_ptr[2] << 8) |
2512  (c->buffer_ptr[3]);
2513  if (len > (c->buffer_end - c->buffer_ptr))
2514  goto fail1;
2515  if ((get_packet_send_clock(c) - get_server_clock(c)) > 0) {
2516  /* nothing to send yet: we can wait */
2517  return 0;
2518  }
2519 
2520  c->data_count += len;
2522  if (c->stream)
2523  c->stream->bytes_served += len;
2524 
2526  /* RTP packets are sent inside the RTSP TCP connection */
2527  AVIOContext *pb;
2528  int interleaved_index, size;
2529  uint8_t header[4];
2530  HTTPContext *rtsp_c;
2531 
2532  rtsp_c = c->rtsp_c;
2533  /* if no RTSP connection left, error */
2534  if (!rtsp_c)
2535  return -1;
2536  /* if already sending something, then wait. */
2537  if (rtsp_c->state != RTSPSTATE_WAIT_REQUEST)
2538  break;
2539  if (avio_open_dyn_buf(&pb) < 0)
2540  goto fail1;
2541  interleaved_index = c->packet_stream_index * 2;
2542  /* RTCP packets are sent at odd indexes */
2543  if (c->buffer_ptr[1] == 200)
2544  interleaved_index++;
2545  /* write RTSP TCP header */
2546  header[0] = '$';
2547  header[1] = interleaved_index;
2548  header[2] = len >> 8;
2549  header[3] = len;
2550  avio_write(pb, header, 4);
2551  /* write RTP packet data */
2552  c->buffer_ptr += 4;
2553  avio_write(pb, c->buffer_ptr, len);
2554  size = avio_close_dyn_buf(pb, &c->packet_buffer);
2555  /* prepare asynchronous TCP sending */
2556  rtsp_c->packet_buffer_ptr = c->packet_buffer;
2557  rtsp_c->packet_buffer_end = c->packet_buffer + size;
2558  c->buffer_ptr += len;
2559 
2560  /* send everything we can NOW */
2561  len = send(rtsp_c->fd, rtsp_c->packet_buffer_ptr,
2562  rtsp_c->packet_buffer_end - rtsp_c->packet_buffer_ptr, 0);
2563  if (len > 0)
2564  rtsp_c->packet_buffer_ptr += len;
2565  if (rtsp_c->packet_buffer_ptr < rtsp_c->packet_buffer_end) {
2566  /* if we could not send all the data, we will
2567  send it later, so a new state is needed to
2568  "lock" the RTSP TCP connection */
2569  rtsp_c->state = RTSPSTATE_SEND_PACKET;
2570  break;
2571  } else
2572  /* all data has been sent */
2573  av_freep(&c->packet_buffer);
2574  } else {
2575  /* send RTP packet directly in UDP */
2576  c->buffer_ptr += 4;
2578  c->buffer_ptr, len);
2579  c->buffer_ptr += len;
2580  /* here we continue as we can send several packets per 10 ms slot */
2581  }
2582  } else {
2583  /* TCP data output */
2584  len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0);
2585  if (len < 0) {
2586  if (ff_neterrno() != AVERROR(EAGAIN) &&
2587  ff_neterrno() != AVERROR(EINTR))
2588  /* error : close connection */
2589  return -1;
2590  else
2591  return 0;
2592  } else
2593  c->buffer_ptr += len;
2594 
2595  c->data_count += len;
2597  if (c->stream)
2598  c->stream->bytes_served += len;
2599  break;
2600  }
2601  }
2602  } /* for(;;) */
2603  return 0;
2604 }
2605 
2607 {
2608  int fd;
2609 
2610  if (c->stream->feed_opened)
2611  return -1;
2612 
2613  /* Don't permit writing to this one */
2614  if (c->stream->readonly)
2615  return -1;
2616 
2617  /* open feed */
2618  fd = open(c->stream->feed_filename, O_RDWR);
2619  if (fd < 0) {
2620  http_log("Error opening feeder file: %s\n", strerror(errno));
2621  return -1;
2622  }
2623  c->feed_fd = fd;
2624 
2625  if (c->stream->truncate) {
2626  /* truncate feed file */
2628  http_log("Truncating feed file '%s'\n", c->stream->feed_filename);
2629  if (ftruncate(c->feed_fd, FFM_PACKET_SIZE) < 0) {
2630  http_log("Error truncating feed file: %s\n", strerror(errno));
2631  return -1;
2632  }
2633  } else {
2634  if ((c->stream->feed_write_index = ffm_read_write_index(fd)) < 0) {
2635  http_log("Error reading write index from feed file: %s\n", strerror(errno));
2636  return -1;
2637  }
2638  }
2639 
2641  c->stream->feed_size = lseek(fd, 0, SEEK_END);
2642  lseek(fd, 0, SEEK_SET);
2643 
2644  /* init buffer input */
2645  c->buffer_ptr = c->buffer;
2646  c->buffer_end = c->buffer + FFM_PACKET_SIZE;
2647  c->stream->feed_opened = 1;
2648  c->chunked_encoding = !!av_stristr(c->buffer, "Transfer-Encoding: chunked");
2649  return 0;
2650 }
2651 
2653 {
2654  HTTPContext *c1;
2655  int len, loop_run = 0;
2656 
2657  while (c->chunked_encoding && !c->chunk_size &&
2658  c->buffer_end > c->buffer_ptr) {
2659  /* read chunk header, if present */
2660  len = recv(c->fd, c->buffer_ptr, 1, 0);
2661 
2662  if (len < 0) {
2663  if (ff_neterrno() != AVERROR(EAGAIN) &&
2664  ff_neterrno() != AVERROR(EINTR))
2665  /* error : close connection */
2666  goto fail;
2667  return 0;
2668  } else if (len == 0) {
2669  /* end of connection : close it */
2670  goto fail;
2671  } else if (c->buffer_ptr - c->buffer >= 2 &&
2672  !memcmp(c->buffer_ptr - 1, "\r\n", 2)) {
2673  c->chunk_size = strtol(c->buffer, 0, 16);
2674  if (c->chunk_size == 0) // end of stream
2675  goto fail;
2676  c->buffer_ptr = c->buffer;
2677  break;
2678  } else if (++loop_run > 10) {
2679  /* no chunk header, abort */
2680  goto fail;
2681  } else {
2682  c->buffer_ptr++;
2683  }
2684  }
2685 
2686  if (c->buffer_end > c->buffer_ptr) {
2687  len = recv(c->fd, c->buffer_ptr,
2688  FFMIN(c->chunk_size, c->buffer_end - c->buffer_ptr), 0);
2689  if (len < 0) {
2690  if (ff_neterrno() != AVERROR(EAGAIN) &&
2691  ff_neterrno() != AVERROR(EINTR))
2692  /* error : close connection */
2693  goto fail;
2694  } else if (len == 0)
2695  /* end of connection : close it */
2696  goto fail;
2697  else {
2698  c->chunk_size -= len;
2699  c->buffer_ptr += len;
2700  c->data_count += len;
2702  }
2703  }
2704 
2705  if (c->buffer_ptr - c->buffer >= 2 && c->data_count > FFM_PACKET_SIZE) {
2706  if (c->buffer[0] != 'f' ||
2707  c->buffer[1] != 'm') {
2708  http_log("Feed stream has become desynchronized -- disconnecting\n");
2709  goto fail;
2710  }
2711  }
2712 
2713  if (c->buffer_ptr >= c->buffer_end) {
2714  FFStream *feed = c->stream;
2715  /* a packet has been received : write it in the store, except
2716  if header */
2717  if (c->data_count > FFM_PACKET_SIZE) {
2718  /* XXX: use llseek or url_seek */
2719  lseek(c->feed_fd, feed->feed_write_index, SEEK_SET);
2720  if (write(c->feed_fd, c->buffer, FFM_PACKET_SIZE) < 0) {
2721  http_log("Error writing to feed file: %s\n", strerror(errno));
2722  goto fail;
2723  }
2724 
2726  /* update file size */
2727  if (feed->feed_write_index > c->stream->feed_size)
2728  feed->feed_size = feed->feed_write_index;
2729 
2730  /* handle wrap around if max file size reached */
2731  if (c->stream->feed_max_size && feed->feed_write_index >= c->stream->feed_max_size)
2733 
2734  /* write index */
2735  if (ffm_write_write_index(c->feed_fd, feed->feed_write_index) < 0) {
2736  http_log("Error writing index to feed file: %s\n", strerror(errno));
2737  goto fail;
2738  }
2739 
2740  /* wake up any waiting connections */
2741  for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2742  if (c1->state == HTTPSTATE_WAIT_FEED &&
2743  c1->stream->feed == c->stream->feed)
2744  c1->state = HTTPSTATE_SEND_DATA;
2745  }
2746  } else {
2747  /* We have a header in our hands that contains useful data */
2749  AVIOContext *pb;
2750  AVInputFormat *fmt_in;
2751  int i;
2752 
2753  if (!s)
2754  goto fail;
2755 
2756  /* use feed output format name to find corresponding input format */
2757  fmt_in = av_find_input_format(feed->fmt->name);
2758  if (!fmt_in)
2759  goto fail;
2760 
2761  pb = avio_alloc_context(c->buffer, c->buffer_end - c->buffer,
2762  0, NULL, NULL, NULL, NULL);
2763  pb->seekable = 0;
2764 
2765  s->pb = pb;
2766  if (avformat_open_input(&s, c->stream->feed_filename, fmt_in, NULL) < 0) {
2767  av_free(pb);
2768  goto fail;
2769  }
2770 
2771  /* Now we have the actual streams */
2772  if (s->nb_streams != feed->nb_streams) {
2774  av_free(pb);
2775  http_log("Feed '%s' stream number does not match registered feed\n",
2776  c->stream->feed_filename);
2777  goto fail;
2778  }
2779 
2780  for (i = 0; i < s->nb_streams; i++) {
2781  AVStream *fst = feed->streams[i];
2782  AVStream *st = s->streams[i];
2783  avcodec_copy_context(fst->codec, st->codec);
2784  }
2785 
2787  av_free(pb);
2788  }
2789  c->buffer_ptr = c->buffer;
2790  }
2791 
2792  return 0;
2793  fail:
2794  c->stream->feed_opened = 0;
2795  close(c->feed_fd);
2796  /* wake up any waiting connections to stop waiting for feed */
2797  for(c1 = first_http_ctx; c1 != NULL; c1 = c1->next) {
2798  if (c1->state == HTTPSTATE_WAIT_FEED &&
2799  c1->stream->feed == c->stream->feed)
2801  }
2802  return -1;
2803 }
2804 
2805 /********************************************************************/
2806 /* RTSP handling */
2807 
2808 static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
2809 {
2810  const char *str;
2811  time_t ti;
2812  struct tm *tm;
2813  char buf2[32];
2814 
2815  switch(error_number) {
2816  case RTSP_STATUS_OK:
2817  str = "OK";
2818  break;
2819  case RTSP_STATUS_METHOD:
2820  str = "Method Not Allowed";
2821  break;
2822  case RTSP_STATUS_BANDWIDTH:
2823  str = "Not Enough Bandwidth";
2824  break;
2825  case RTSP_STATUS_SESSION:
2826  str = "Session Not Found";
2827  break;
2828  case RTSP_STATUS_STATE:
2829  str = "Method Not Valid in This State";
2830  break;
2831  case RTSP_STATUS_AGGREGATE:
2832  str = "Aggregate operation not allowed";
2833  break;
2835  str = "Only aggregate operation allowed";
2836  break;
2837  case RTSP_STATUS_TRANSPORT:
2838  str = "Unsupported transport";
2839  break;
2840  case RTSP_STATUS_INTERNAL:
2841  str = "Internal Server Error";
2842  break;
2843  case RTSP_STATUS_SERVICE:
2844  str = "Service Unavailable";
2845  break;
2846  case RTSP_STATUS_VERSION:
2847  str = "RTSP Version not supported";
2848  break;
2849  default:
2850  str = "Unknown Error";
2851  break;
2852  }
2853 
2854  avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", error_number, str);
2855  avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
2856 
2857  /* output GMT time */
2858  ti = time(NULL);
2859  tm = gmtime(&ti);
2860  strftime(buf2, sizeof(buf2), "%a, %d %b %Y %H:%M:%S", tm);
2861  avio_printf(c->pb, "Date: %s GMT\r\n", buf2);
2862 }
2863 
2864 static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
2865 {
2866  rtsp_reply_header(c, error_number);
2867  avio_printf(c->pb, "\r\n");
2868 }
2869 
2871 {
2872  const char *p, *p1, *p2;
2873  char cmd[32];
2874  char url[1024];
2875  char protocol[32];
2876  char line[1024];
2877  int len;
2878  RTSPMessageHeader header1 = { 0 }, *header = &header1;
2879 
2880  c->buffer_ptr[0] = '\0';
2881  p = c->buffer;
2882 
2883  get_word(cmd, sizeof(cmd), &p);
2884  get_word(url, sizeof(url), &p);
2885  get_word(protocol, sizeof(protocol), &p);
2886 
2887  av_strlcpy(c->method, cmd, sizeof(c->method));
2888  av_strlcpy(c->url, url, sizeof(c->url));
2889  av_strlcpy(c->protocol, protocol, sizeof(c->protocol));
2890 
2891  if (avio_open_dyn_buf(&c->pb) < 0) {
2892  /* XXX: cannot do more */
2893  c->pb = NULL; /* safety */
2894  return -1;
2895  }
2896 
2897  /* check version name */
2898  if (strcmp(protocol, "RTSP/1.0") != 0) {
2900  goto the_end;
2901  }
2902 
2903  /* parse each header line */
2904  /* skip to next line */
2905  while (*p != '\n' && *p != '\0')
2906  p++;
2907  if (*p == '\n')
2908  p++;
2909  while (*p != '\0') {
2910  p1 = memchr(p, '\n', (char *)c->buffer_ptr - p);
2911  if (!p1)
2912  break;
2913  p2 = p1;
2914  if (p2 > p && p2[-1] == '\r')
2915  p2--;
2916  /* skip empty line */
2917  if (p2 == p)
2918  break;
2919  len = p2 - p;
2920  if (len > sizeof(line) - 1)
2921  len = sizeof(line) - 1;
2922  memcpy(line, p, len);
2923  line[len] = '\0';
2924  ff_rtsp_parse_line(header, line, NULL, NULL);
2925  p = p1 + 1;
2926  }
2927 
2928  /* handle sequence number */
2929  c->seq = header->seq;
2930 
2931  if (!strcmp(cmd, "DESCRIBE"))
2932  rtsp_cmd_describe(c, url);
2933  else if (!strcmp(cmd, "OPTIONS"))
2934  rtsp_cmd_options(c, url);
2935  else if (!strcmp(cmd, "SETUP"))
2936  rtsp_cmd_setup(c, url, header);
2937  else if (!strcmp(cmd, "PLAY"))
2938  rtsp_cmd_play(c, url, header);
2939  else if (!strcmp(cmd, "PAUSE"))
2940  rtsp_cmd_pause(c, url, header);
2941  else if (!strcmp(cmd, "TEARDOWN"))
2942  rtsp_cmd_teardown(c, url, header);
2943  else
2945 
2946  the_end:
2947  len = avio_close_dyn_buf(c->pb, &c->pb_buffer);
2948  c->pb = NULL; /* safety */
2949  if (len < 0) {
2950  /* XXX: cannot do more */
2951  return -1;
2952  }
2953  c->buffer_ptr = c->pb_buffer;
2954  c->buffer_end = c->pb_buffer + len;
2956  return 0;
2957 }
2958 
2959 static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer,
2960  struct in_addr my_ip)
2961 {
2962  AVFormatContext *avc;
2963  AVStream *avs = NULL;
2964  AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL);
2965  int i;
2966 
2967  avc = avformat_alloc_context();
2968  if (avc == NULL || !rtp_format) {
2969  return -1;
2970  }
2971  avc->oformat = rtp_format;
2972  av_dict_set(&avc->metadata, "title",
2973  stream->title[0] ? stream->title : "No Title", 0);
2974  avc->nb_streams = stream->nb_streams;
2975  if (stream->is_multicast) {
2976  snprintf(avc->filename, 1024, "rtp://%s:%d?multicast=1?ttl=%d",
2977  inet_ntoa(stream->multicast_ip),
2978  stream->multicast_port, stream->multicast_ttl);
2979  } else {
2980  snprintf(avc->filename, 1024, "rtp://0.0.0.0");
2981  }
2982 
2983  if (avc->nb_streams >= INT_MAX/sizeof(*avc->streams) ||
2984  !(avc->streams = av_malloc(avc->nb_streams * sizeof(*avc->streams))))
2985  goto sdp_done;
2986  if (avc->nb_streams >= INT_MAX/sizeof(*avs) ||
2987  !(avs = av_malloc(avc->nb_streams * sizeof(*avs))))
2988  goto sdp_done;
2989 
2990  for(i = 0; i < stream->nb_streams; i++) {
2991  avc->streams[i] = &avs[i];
2992  avc->streams[i]->codec = stream->streams[i]->codec;
2993  }
2994  *pbuffer = av_mallocz(2048);
2995  av_sdp_create(&avc, 1, *pbuffer, 2048);
2996 
2997  sdp_done:
2998  av_free(avc->streams);
2999  av_dict_free(&avc->metadata);
3000  av_free(avc);
3001  av_free(avs);
3002 
3003  return strlen(*pbuffer);
3004 }
3005 
3006 static void rtsp_cmd_options(HTTPContext *c, const char *url)
3007 {
3008 // rtsp_reply_header(c, RTSP_STATUS_OK);
3009  avio_printf(c->pb, "RTSP/1.0 %d %s\r\n", RTSP_STATUS_OK, "OK");
3010  avio_printf(c->pb, "CSeq: %d\r\n", c->seq);
3011  avio_printf(c->pb, "Public: %s\r\n", "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
3012  avio_printf(c->pb, "\r\n");
3013 }
3014 
3015 static void rtsp_cmd_describe(HTTPContext *c, const char *url)
3016 {
3017  FFStream *stream;
3018  char path1[1024];
3019  const char *path;
3020  uint8_t *content;
3021  int content_length;
3022  socklen_t len;
3023  struct sockaddr_in my_addr;
3024 
3025  /* find which url is asked */
3026  av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3027  path = path1;
3028  if (*path == '/')
3029  path++;
3030 
3031  for(stream = first_stream; stream != NULL; stream = stream->next) {
3032  if (!stream->is_feed &&
3033  stream->fmt && !strcmp(stream->fmt->name, "rtp") &&
3034  !strcmp(path, stream->filename)) {
3035  goto found;
3036  }
3037  }
3038  /* no stream found */
3039  rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3040  return;
3041 
3042  found:
3043  /* prepare the media description in sdp format */
3044 
3045  /* get the host IP */
3046  len = sizeof(my_addr);
3047  getsockname(c->fd, (struct sockaddr *)&my_addr, &len);
3048  content_length = prepare_sdp_description(stream, &content, my_addr.sin_addr);
3049  if (content_length < 0) {
3051  return;
3052  }
3054  avio_printf(c->pb, "Content-Base: %s/\r\n", url);
3055  avio_printf(c->pb, "Content-Type: application/sdp\r\n");
3056  avio_printf(c->pb, "Content-Length: %d\r\n", content_length);
3057  avio_printf(c->pb, "\r\n");
3058  avio_write(c->pb, content, content_length);
3059  av_free(content);
3060 }
3061 
3062 static HTTPContext *find_rtp_session(const char *session_id)
3063 {
3064  HTTPContext *c;
3065 
3066  if (session_id[0] == '\0')
3067  return NULL;
3068 
3069  for(c = first_http_ctx; c != NULL; c = c->next) {
3070  if (!strcmp(c->session_id, session_id))
3071  return c;
3072  }
3073  return NULL;
3074 }
3075 
3077 {
3079  int i;
3080 
3081  for(i=0;i<h->nb_transports;i++) {
3082  th = &h->transports[i];
3083  if (th->lower_transport == lower_transport)
3084  return th;
3085  }
3086  return NULL;
3087 }
3088 
3089 static void rtsp_cmd_setup(HTTPContext *c, const char *url,
3090  RTSPMessageHeader *h)
3091 {
3092  FFStream *stream;
3093  int stream_index, rtp_port, rtcp_port;
3094  char buf[1024];
3095  char path1[1024];
3096  const char *path;
3097  HTTPContext *rtp_c;
3099  struct sockaddr_in dest_addr;
3101 
3102  /* find which url is asked */
3103  av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3104  path = path1;
3105  if (*path == '/')
3106  path++;
3107 
3108  /* now check each stream */
3109  for(stream = first_stream; stream != NULL; stream = stream->next) {
3110  if (!stream->is_feed &&
3111  stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3112  /* accept aggregate filenames only if single stream */
3113  if (!strcmp(path, stream->filename)) {
3114  if (stream->nb_streams != 1) {
3116  return;
3117  }
3118  stream_index = 0;
3119  goto found;
3120  }
3121 
3122  for(stream_index = 0; stream_index < stream->nb_streams;
3123  stream_index++) {
3124  snprintf(buf, sizeof(buf), "%s/streamid=%d",
3125  stream->filename, stream_index);
3126  if (!strcmp(path, buf))
3127  goto found;
3128  }
3129  }
3130  }
3131  /* no stream found */
3132  rtsp_reply_error(c, RTSP_STATUS_SERVICE); /* XXX: right error ? */
3133  return;
3134  found:
3135 
3136  /* generate session id if needed */
3137  if (h->session_id[0] == '\0') {
3138  unsigned random0 = av_lfg_get(&random_state);
3139  unsigned random1 = av_lfg_get(&random_state);
3140  snprintf(h->session_id, sizeof(h->session_id), "%08x%08x",
3141  random0, random1);
3142  }
3143 
3144  /* find rtp session, and create it if none found */
3145  rtp_c = find_rtp_session(h->session_id);
3146  if (!rtp_c) {
3147  /* always prefer UDP */
3149  if (!th) {
3151  if (!th) {
3153  return;
3154  }
3155  }
3156 
3157  rtp_c = rtp_new_connection(&c->from_addr, stream, h->session_id,
3158  th->lower_transport);
3159  if (!rtp_c) {
3161  return;
3162  }
3163 
3164  /* open input stream */
3165  if (open_input_stream(rtp_c, "") < 0) {
3167  return;
3168  }
3169  }
3170 
3171  /* test if stream is OK (test needed because several SETUP needs
3172  to be done for a given file) */
3173  if (rtp_c->stream != stream) {
3175  return;
3176  }
3177 
3178  /* test if stream is already set up */
3179  if (rtp_c->rtp_ctx[stream_index]) {
3181  return;
3182  }
3183 
3184  /* check transport */
3185  th = find_transport(h, rtp_c->rtp_protocol);
3186  if (!th || (th->lower_transport == RTSP_LOWER_TRANSPORT_UDP &&
3187  th->client_port_min <= 0)) {
3189  return;
3190  }
3191 
3192  /* setup default options */
3193  setup.transport_option[0] = '\0';
3194  dest_addr = rtp_c->from_addr;
3195  dest_addr.sin_port = htons(th->client_port_min);
3196 
3197  /* setup stream */
3198  if (rtp_new_av_stream(rtp_c, stream_index, &dest_addr, c) < 0) {
3200  return;
3201  }
3202 
3203  /* now everything is OK, so we can send the connection parameters */
3205  /* session ID */
3206  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3207 
3208  switch(rtp_c->rtp_protocol) {
3210  rtp_port = ff_rtp_get_local_rtp_port(rtp_c->rtp_handles[stream_index]);
3211  rtcp_port = ff_rtp_get_local_rtcp_port(rtp_c->rtp_handles[stream_index]);
3212  avio_printf(c->pb, "Transport: RTP/AVP/UDP;unicast;"
3213  "client_port=%d-%d;server_port=%d-%d",
3215  rtp_port, rtcp_port);
3216  break;
3218  avio_printf(c->pb, "Transport: RTP/AVP/TCP;interleaved=%d-%d",
3219  stream_index * 2, stream_index * 2 + 1);
3220  break;
3221  default:
3222  break;
3223  }
3224  if (setup.transport_option[0] != '\0')
3225  avio_printf(c->pb, ";%s", setup.transport_option);
3226  avio_printf(c->pb, "\r\n");
3227 
3228 
3229  avio_printf(c->pb, "\r\n");
3230 }
3231 
3232 
3233 /* find an rtp connection by using the session ID. Check consistency
3234  with filename */
3236  const char *session_id)
3237 {
3238  HTTPContext *rtp_c;
3239  char path1[1024];
3240  const char *path;
3241  char buf[1024];
3242  int s, len;
3243 
3244  rtp_c = find_rtp_session(session_id);
3245  if (!rtp_c)
3246  return NULL;
3247 
3248  /* find which url is asked */
3249  av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path1, sizeof(path1), url);
3250  path = path1;
3251  if (*path == '/')
3252  path++;
3253  if(!strcmp(path, rtp_c->stream->filename)) return rtp_c;
3254  for(s=0; s<rtp_c->stream->nb_streams; ++s) {
3255  snprintf(buf, sizeof(buf), "%s/streamid=%d",
3256  rtp_c->stream->filename, s);
3257  if(!strncmp(path, buf, sizeof(buf))) {
3258  // XXX: Should we reply with RTSP_STATUS_ONLY_AGGREGATE if nb_streams>1?
3259  return rtp_c;
3260  }
3261  }
3262  len = strlen(path);
3263  if (len > 0 && path[len - 1] == '/' &&
3264  !strncmp(path, rtp_c->stream->filename, len - 1))
3265  return rtp_c;
3266  return NULL;
3267 }
3268 
3269 static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3270 {
3271  HTTPContext *rtp_c;
3272 
3273  rtp_c = find_rtp_session_with_url(url, h->session_id);
3274  if (!rtp_c) {
3276  return;
3277  }
3278 
3279  if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3280  rtp_c->state != HTTPSTATE_WAIT_FEED &&
3281  rtp_c->state != HTTPSTATE_READY) {
3283  return;
3284  }
3285 
3286  rtp_c->state = HTTPSTATE_SEND_DATA;
3287 
3288  /* now everything is OK, so we can send the connection parameters */
3290  /* session ID */
3291  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3292  avio_printf(c->pb, "\r\n");
3293 }
3294 
3295 static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3296 {
3297  HTTPContext *rtp_c;
3298 
3299  rtp_c = find_rtp_session_with_url(url, h->session_id);
3300  if (!rtp_c) {
3302  return;
3303  }
3304 
3305  if (rtp_c->state != HTTPSTATE_SEND_DATA &&
3306  rtp_c->state != HTTPSTATE_WAIT_FEED) {
3308  return;
3309  }
3310 
3311  rtp_c->state = HTTPSTATE_READY;
3312  rtp_c->first_pts = AV_NOPTS_VALUE;
3313  /* now everything is OK, so we can send the connection parameters */
3315  /* session ID */
3316  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3317  avio_printf(c->pb, "\r\n");
3318 }
3319 
3320 static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
3321 {
3322  HTTPContext *rtp_c;
3323 
3324  rtp_c = find_rtp_session_with_url(url, h->session_id);
3325  if (!rtp_c) {
3327  return;
3328  }
3329 
3330  /* now everything is OK, so we can send the connection parameters */
3332  /* session ID */
3333  avio_printf(c->pb, "Session: %s\r\n", rtp_c->session_id);
3334  avio_printf(c->pb, "\r\n");
3335 
3336  /* abort the session */
3337  close_connection(rtp_c);
3338 }
3339 
3340 
3341 /********************************************************************/
3342 /* RTP handling */
3343 
3344 static HTTPContext *rtp_new_connection(struct sockaddr_in *from_addr,
3345  FFStream *stream, const char *session_id,
3346  enum RTSPLowerTransport rtp_protocol)
3347 {
3348  HTTPContext *c = NULL;
3349  const char *proto_str;
3350 
3351  /* XXX: should output a warning page when coming
3352  close to the connection limit */
3354  goto fail;
3355 
3356  /* add a new connection */
3357  c = av_mallocz(sizeof(HTTPContext));
3358  if (!c)
3359  goto fail;
3360 
3361  c->fd = -1;
3362  c->poll_entry = NULL;
3363  c->from_addr = *from_addr;
3365  c->buffer = av_malloc(c->buffer_size);
3366  if (!c->buffer)
3367  goto fail;
3368  nb_connections++;
3369  c->stream = stream;
3370  av_strlcpy(c->session_id, session_id, sizeof(c->session_id));
3371  c->state = HTTPSTATE_READY;
3372  c->is_packetized = 1;
3373  c->rtp_protocol = rtp_protocol;
3374 
3375  /* protocol is shown in statistics */
3376  switch(c->rtp_protocol) {
3378  proto_str = "MCAST";
3379  break;
3381  proto_str = "UDP";
3382  break;
3384  proto_str = "TCP";
3385  break;
3386  default:
3387  proto_str = "???";
3388  break;
3389  }
3390  av_strlcpy(c->protocol, "RTP/", sizeof(c->protocol));
3391  av_strlcat(c->protocol, proto_str, sizeof(c->protocol));
3392 
3393  current_bandwidth += stream->bandwidth;
3394 
3395  c->next = first_http_ctx;
3396  first_http_ctx = c;
3397  return c;
3398 
3399  fail:
3400  if (c) {
3401  av_free(c->buffer);
3402  av_free(c);
3403  }
3404  return NULL;
3405 }
3406 
3407 /* add a new RTP stream in an RTP connection (used in RTSP SETUP
3408  command). If RTP/TCP protocol is used, TCP connection 'rtsp_c' is
3409  used. */
3411  int stream_index, struct sockaddr_in *dest_addr,
3412  HTTPContext *rtsp_c)
3413 {
3414  AVFormatContext *ctx;
3415  AVStream *st;
3416  char *ipaddr;
3417  URLContext *h = NULL;
3418  uint8_t *dummy_buf;
3419  int max_packet_size;
3420 
3421  /* now we can open the relevant output stream */
3422  ctx = avformat_alloc_context();
3423  if (!ctx)
3424  return -1;
3425  ctx->oformat = av_guess_format("rtp", NULL, NULL);
3426 
3427  st = av_mallocz(sizeof(AVStream));
3428  if (!st)
3429  goto fail;
3430  ctx->nb_streams = 1;
3431  ctx->streams = av_mallocz(sizeof(AVStream *) * ctx->nb_streams);
3432  if (!ctx->streams)
3433  goto fail;
3434  ctx->streams[0] = st;
3435 
3436  if (!c->stream->feed ||
3437  c->stream->feed == c->stream)
3438  memcpy(st, c->stream->streams[stream_index], sizeof(AVStream));
3439  else
3440  memcpy(st,
3441  c->stream->feed->streams[c->stream->feed_streams[stream_index]],
3442  sizeof(AVStream));
3443  st->priv_data = NULL;
3444 
3445  /* build destination RTP address */
3446  ipaddr = inet_ntoa(dest_addr->sin_addr);
3447 
3448  switch(c->rtp_protocol) {
3451  /* RTP/UDP case */
3452 
3453  /* XXX: also pass as parameter to function ? */
3454  if (c->stream->is_multicast) {
3455  int ttl;
3456  ttl = c->stream->multicast_ttl;
3457  if (!ttl)
3458  ttl = 16;
3459  snprintf(ctx->filename, sizeof(ctx->filename),
3460  "rtp://%s:%d?multicast=1&ttl=%d",
3461  ipaddr, ntohs(dest_addr->sin_port), ttl);
3462  } else {
3463  snprintf(ctx->filename, sizeof(ctx->filename),
3464  "rtp://%s:%d", ipaddr, ntohs(dest_addr->sin_port));
3465  }
3466 
3467  if (ffurl_open(&h, ctx->filename, AVIO_FLAG_WRITE, NULL, NULL) < 0)
3468  goto fail;
3469  c->rtp_handles[stream_index] = h;
3470  max_packet_size = h->max_packet_size;
3471  break;
3473  /* RTP/TCP case */
3474  c->rtsp_c = rtsp_c;
3475  max_packet_size = RTSP_TCP_MAX_PACKET_SIZE;
3476  break;
3477  default:
3478  goto fail;
3479  }
3480 
3481  http_log("%s:%d - - \"PLAY %s/streamid=%d %s\"\n",
3482  ipaddr, ntohs(dest_addr->sin_port),
3483  c->stream->filename, stream_index, c->protocol);
3484 
3485  /* normally, no packets should be output here, but the packet size may be checked */
3486  if (ffio_open_dyn_packet_buf(&ctx->pb, max_packet_size) < 0) {
3487  /* XXX: close stream */
3488  goto fail;
3489  }
3490  if (avformat_write_header(ctx, NULL) < 0) {
3491  fail:
3492  if (h)
3493  ffurl_close(h);
3494  av_free(ctx);
3495  return -1;
3496  }
3497  avio_close_dyn_buf(ctx->pb, &dummy_buf);
3498  av_free(dummy_buf);
3499 
3500  c->rtp_ctx[stream_index] = ctx;
3501  return 0;
3502 }
3503 
3504 /********************************************************************/
3505 /* ffserver initialization */
3506 
3507 static AVStream *add_av_stream1(FFStream *stream, AVCodecContext *codec, int copy)
3508 {
3509  AVStream *fst;
3510 
3511  if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams))
3512  return NULL;
3513 
3514  fst = av_mallocz(sizeof(AVStream));
3515  if (!fst)
3516  return NULL;
3517  if (copy) {
3519  memcpy(fst->codec, codec, sizeof(AVCodecContext));
3520  if (codec->extradata_size) {
3522  memcpy(fst->codec->extradata, codec->extradata,
3523  codec->extradata_size);
3524  }
3525  } else {
3526  /* live streams must use the actual feed's codec since it may be
3527  * updated later to carry extradata needed by the streams.
3528  */
3529  fst->codec = codec;
3530  }
3531  fst->priv_data = av_mallocz(sizeof(FeedData));
3532  fst->index = stream->nb_streams;
3533  avpriv_set_pts_info(fst, 33, 1, 90000);
3535  stream->streams[stream->nb_streams++] = fst;
3536  return fst;
3537 }
3538 
3539 /* return the stream number in the feed */
3540 static int add_av_stream(FFStream *feed, AVStream *st)
3541 {
3542  AVStream *fst;
3543  AVCodecContext *av, *av1;
3544  int i;
3545 
3546  av = st->codec;
3547  for(i=0;i<feed->nb_streams;i++) {
3548  st = feed->streams[i];
3549  av1 = st->codec;
3550  if (av1->codec_id == av->codec_id &&
3551  av1->codec_type == av->codec_type &&
3552  av1->bit_rate == av->bit_rate) {
3553 
3554  switch(av->codec_type) {
3555  case AVMEDIA_TYPE_AUDIO:
3556  if (av1->channels == av->channels &&
3557  av1->sample_rate == av->sample_rate)
3558  return i;
3559  break;
3560  case AVMEDIA_TYPE_VIDEO:
3561  if (av1->width == av->width &&
3562  av1->height == av->height &&
3563  av1->time_base.den == av->time_base.den &&
3564  av1->time_base.num == av->time_base.num &&
3565  av1->gop_size == av->gop_size)
3566  return i;
3567  break;
3568  default:
3569  abort();
3570  }
3571  }
3572  }
3573 
3574  fst = add_av_stream1(feed, av, 0);
3575  if (!fst)
3576  return -1;
3577  return feed->nb_streams - 1;
3578 }
3579 
3580 static void remove_stream(FFStream *stream)
3581 {
3582  FFStream **ps;
3583  ps = &first_stream;
3584  while (*ps != NULL) {
3585  if (*ps == stream)
3586  *ps = (*ps)->next;
3587  else
3588  ps = &(*ps)->next;
3589  }
3590 }
3591 
3592 /* specific mpeg4 handling : we extract the raw parameters */
3594 {
3595  int mpeg4_count, i, size;
3596  AVPacket pkt;
3597  AVStream *st;
3598  const uint8_t *p;
3599 
3601 
3602  mpeg4_count = 0;
3603  for(i=0;i<infile->nb_streams;i++) {
3604  st = infile->streams[i];
3605  if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3606  st->codec->extradata_size == 0) {
3607  mpeg4_count++;
3608  }
3609  }
3610  if (!mpeg4_count)
3611  return;
3612 
3613  printf("MPEG4 without extra data: trying to find header in %s\n", infile->filename);
3614  while (mpeg4_count > 0) {
3615  if (av_read_frame(infile, &pkt) < 0)
3616  break;
3617  st = infile->streams[pkt.stream_index];
3618  if (st->codec->codec_id == AV_CODEC_ID_MPEG4 &&
3619  st->codec->extradata_size == 0) {
3620  av_freep(&st->codec->extradata);
3621  /* fill extradata with the header */
3622  /* XXX: we make hard suppositions here ! */
3623  p = pkt.data;
3624  while (p < pkt.data + pkt.size - 4) {
3625  /* stop when vop header is found */
3626  if (p[0] == 0x00 && p[1] == 0x00 &&
3627  p[2] == 0x01 && p[3] == 0xb6) {
3628  size = p - pkt.data;
3629  // av_hex_dump_log(infile, AV_LOG_DEBUG, pkt.data, size);
3631  st->codec->extradata_size = size;
3632  memcpy(st->codec->extradata, pkt.data, size);
3633  break;
3634  }
3635  p++;
3636  }
3637  mpeg4_count--;
3638  }
3639  av_free_packet(&pkt);
3640  }
3641 }
3642 
3643 /* compute the needed AVStream for each file */
3644 static void build_file_streams(void)
3645 {
3646  FFStream *stream, *stream_next;
3647  int i, ret;
3648 
3649  /* gather all streams */
3650  for(stream = first_stream; stream != NULL; stream = stream_next) {
3651  AVFormatContext *infile = NULL;
3652  stream_next = stream->next;
3653  if (stream->stream_type == STREAM_TYPE_LIVE &&
3654  !stream->feed) {
3655  /* the stream comes from a file */
3656  /* try to open the file */
3657  /* open stream */
3658  if (stream->fmt && !strcmp(stream->fmt->name, "rtp")) {
3659  /* specific case : if transport stream output to RTP,
3660  we use a raw transport stream reader */
3661  av_dict_set(&stream->in_opts, "mpeg2ts_compute_pcr", "1", 0);
3662  }
3663 
3664  http_log("Opening file '%s'\n", stream->feed_filename);
3665  if ((ret = avformat_open_input(&infile, stream->feed_filename, stream->ifmt, &stream->in_opts)) < 0) {
3666  http_log("Could not open '%s': %d\n", stream->feed_filename, ret);
3667  /* remove stream (no need to spend more time on it) */
3668  fail:
3669  remove_stream(stream);
3670  } else {
3671  /* find all the AVStreams inside and reference them in
3672  'stream' */
3673  if (avformat_find_stream_info(infile, NULL) < 0) {
3674  http_log("Could not find codec parameters from '%s'\n",
3675  stream->feed_filename);
3676  avformat_close_input(&infile);
3677  goto fail;
3678  }
3679  extract_mpeg4_header(infile);
3680 
3681  for(i=0;i<infile->nb_streams;i++)
3682  add_av_stream1(stream, infile->streams[i]->codec, 1);
3683 
3684  avformat_close_input(&infile);
3685  }
3686  }
3687  }
3688 }
3689 
3690 /* compute the needed AVStream for each feed */
3691 static void build_feed_streams(void)
3692 {
3693  FFStream *stream, *feed;
3694  int i;
3695 
3696  /* gather all streams */
3697  for(stream = first_stream; stream != NULL; stream = stream->next) {
3698  feed = stream->feed;
3699  if (feed) {
3700  if (stream->is_feed) {
3701  for(i=0;i<stream->nb_streams;i++)
3702  stream->feed_streams[i] = i;
3703  } else {
3704  /* we handle a stream coming from a feed */
3705  for(i=0;i<stream->nb_streams;i++)
3706  stream->feed_streams[i] = add_av_stream(feed, stream->streams[i]);
3707  }
3708  }
3709  }
3710 
3711  /* create feed files if needed */
3712  for(feed = first_feed; feed != NULL; feed = feed->next_feed) {
3713  int fd;
3714 
3715  if (avio_check(feed->feed_filename, AVIO_FLAG_READ) > 0) {
3716  /* See if it matches */
3717  AVFormatContext *s = NULL;
3718  int matches = 0;
3719 
3720  if (avformat_open_input(&s, feed->feed_filename, NULL, NULL) >= 0) {
3721  /* set buffer size */
3723  /* Now see if it matches */
3724  if (s->nb_streams == feed->nb_streams) {
3725  matches = 1;
3726  for(i=0;i<s->nb_streams;i++) {
3727  AVStream *sf, *ss;
3728  sf = feed->streams[i];
3729  ss = s->streams[i];
3730 
3731  if (sf->index != ss->index ||
3732  sf->id != ss->id) {
3733  http_log("Index & Id do not match for stream %d (%s)\n",
3734  i, feed->feed_filename);
3735  matches = 0;
3736  } else {
3737  AVCodecContext *ccf, *ccs;
3738 
3739  ccf = sf->codec;
3740  ccs = ss->codec;
3741 #define CHECK_CODEC(x) (ccf->x != ccs->x)
3742 
3744  http_log("Codecs do not match for stream %d\n", i);
3745  matches = 0;
3746  } else if (CHECK_CODEC(bit_rate) || CHECK_CODEC(flags)) {
3747  http_log("Codec bitrates do not match for stream %d\n", i);
3748  matches = 0;
3749  } else if (ccf->codec_type == AVMEDIA_TYPE_VIDEO) {
3750  if (CHECK_CODEC(time_base.den) ||
3751  CHECK_CODEC(time_base.num) ||
3752  CHECK_CODEC(width) ||
3753  CHECK_CODEC(height)) {
3754  http_log("Codec width, height and framerate do not match for stream %d\n", i);
3755  matches = 0;
3756  }
3757  } else if (ccf->codec_type == AVMEDIA_TYPE_AUDIO) {
3758  if (CHECK_CODEC(sample_rate) ||
3759  CHECK_CODEC(channels) ||
3761  http_log("Codec sample_rate, channels, frame_size do not match for stream %d\n", i);
3762  matches = 0;
3763  }
3764  } else {
3765  http_log("Unknown codec type\n");
3766  matches = 0;
3767  }
3768  }
3769  if (!matches)
3770  break;
3771  }
3772  } else
3773  http_log("Deleting feed file '%s' as stream counts differ (%d != %d)\n",
3774  feed->feed_filename, s->nb_streams, feed->nb_streams);
3775 
3777  } else
3778  http_log("Deleting feed file '%s' as it appears to be corrupt\n",
3779  feed->feed_filename);
3780 
3781  if (!matches) {
3782  if (feed->readonly) {
3783  http_log("Unable to delete feed file '%s' as it is marked readonly\n",
3784  feed->feed_filename);
3785  exit(1);
3786  }
3787  unlink(feed->feed_filename);
3788  }
3789  }
3790  if (avio_check(feed->feed_filename, AVIO_FLAG_WRITE) <= 0) {
3791  AVFormatContext s1 = {0}, *s = &s1;
3792 
3793  if (feed->readonly) {
3794  http_log("Unable to create feed file '%s' as it is marked readonly\n",
3795  feed->feed_filename);
3796  exit(1);
3797  }
3798 
3799  /* only write the header of the ffm file */
3800  if (avio_open(&s->pb, feed->feed_filename, AVIO_FLAG_WRITE) < 0) {
3801  http_log("Could not open output feed file '%s'\n",
3802  feed->feed_filename);
3803  exit(1);
3804  }
3805  s->oformat = feed->fmt;
3806  s->nb_streams = feed->nb_streams;
3807  s->streams = feed->streams;
3808  if (avformat_write_header(s, NULL) < 0) {
3809  http_log("Container doesn't support the required parameters\n");
3810  exit(1);
3811  }
3812  /* XXX: need better api */
3813  av_freep(&s->priv_data);
3814  avio_close(s->pb);
3815  }
3816  /* get feed size and write index */
3817  fd = open(feed->feed_filename, O_RDONLY);
3818  if (fd < 0) {
3819  http_log("Could not open output feed file '%s'\n",
3820  feed->feed_filename);
3821  exit(1);
3822  }
3823 
3825  feed->feed_size = lseek(fd, 0, SEEK_END);
3826  /* ensure that we do not wrap before the end of file */
3827  if (feed->feed_max_size && feed->feed_max_size < feed->feed_size)
3828  feed->feed_max_size = feed->feed_size;
3829 
3830  close(fd);
3831  }
3832 }
3833 
3834 /* compute the bandwidth used by each stream */
3835 static void compute_bandwidth(void)
3836 {
3837  unsigned bandwidth;
3838  int i;
3839  FFStream *stream;
3840 
3841  for(stream = first_stream; stream != NULL; stream = stream->next) {
3842  bandwidth = 0;
3843  for(i=0;i<stream->nb_streams;i++) {
3844  AVStream *st = stream->streams[i];
3845  switch(st->codec->codec_type) {
3846  case AVMEDIA_TYPE_AUDIO:
3847  case AVMEDIA_TYPE_VIDEO:
3848  bandwidth += st->codec->bit_rate;
3849  break;
3850  default:
3851  break;
3852  }
3853  }
3854  stream->bandwidth = (bandwidth + 999) / 1000;
3855  }
3856 }
3857 
3858 /* add a codec and set the default parameters */
3859 static void add_codec(FFStream *stream, AVCodecContext *av)
3860 {
3861  AVStream *st;
3862 
3863  if(stream->nb_streams >= FF_ARRAY_ELEMS(stream->streams))
3864  return;
3865 
3866  /* compute default parameters */
3867  switch(av->codec_type) {
3868  case AVMEDIA_TYPE_AUDIO:
3869  if (av->bit_rate == 0)
3870  av->bit_rate = 64000;
3871  if (av->sample_rate == 0)
3872  av->sample_rate = 22050;
3873  if (av->channels == 0)
3874  av->channels = 1;
3875  break;
3876  case AVMEDIA_TYPE_VIDEO:
3877  if (av->bit_rate == 0)
3878  av->bit_rate = 64000;
3879  if (av->time_base.num == 0){
3880  av->time_base.den = 5;
3881  av->time_base.num = 1;
3882  }
3883  if (av->width == 0 || av->height == 0) {
3884  av->width = 160;
3885  av->height = 128;
3886  }
3887  /* Bitrate tolerance is less for streaming */
3888  if (av->bit_rate_tolerance == 0)
3889  av->bit_rate_tolerance = FFMAX(av->bit_rate / 4,
3890  (int64_t)av->bit_rate*av->time_base.num/av->time_base.den);
3891  if (av->qmin == 0)
3892  av->qmin = 3;
3893  if (av->qmax == 0)
3894  av->qmax = 31;
3895  if (av->max_qdiff == 0)
3896  av->max_qdiff = 3;
3897  av->qcompress = 0.5;
3898  av->qblur = 0.5;
3899 
3900  if (!av->nsse_weight)
3901  av->nsse_weight = 8;
3902 
3904  if (!av->me_method)
3905  av->me_method = ME_EPZS;
3906  av->rc_buffer_aggressivity = 1.0;
3907 
3908  if (!av->rc_eq)
3909  av->rc_eq = "tex^qComp";
3910  if (!av->i_quant_factor)
3911  av->i_quant_factor = -0.8;
3912  if (!av->b_quant_factor)
3913  av->b_quant_factor = 1.25;
3914  if (!av->b_quant_offset)
3915  av->b_quant_offset = 1.25;
3916  if (!av->rc_max_rate)
3917  av->rc_max_rate = av->bit_rate * 2;
3918 
3919  if (av->rc_max_rate && !av->rc_buffer_size) {
3920  av->rc_buffer_size = av->rc_max_rate;
3921  }
3922 
3923 
3924  break;
3925  default:
3926  abort();
3927  }
3928 
3929  st = av_mallocz(sizeof(AVStream));
3930  if (!st)
3931  return;
3933  stream->streams[stream->nb_streams++] = st;
3934  memcpy(st->codec, av, sizeof(AVCodecContext));
3935 }
3936 
3937 static enum AVCodecID opt_audio_codec(const char *arg)
3938 {
3940 
3941  if (p == NULL || p->type != AVMEDIA_TYPE_AUDIO)
3942  return AV_CODEC_ID_NONE;
3943 
3944  return p->id;
3945 }
3946 
3947 static enum AVCodecID opt_video_codec(const char *arg)
3948 {
3950 
3951  if (p == NULL || p->type != AVMEDIA_TYPE_VIDEO)
3952  return AV_CODEC_ID_NONE;
3953 
3954  return p->id;
3955 }
3956 
3957 /* simplistic plugin support */
3958 
3959 #if HAVE_DLOPEN
3960 static void load_module(const char *filename)
3961 {
3962  void *dll;
3963  void (*init_func)(void);
3964  dll = dlopen(filename, RTLD_NOW);
3965  if (!dll) {
3966  fprintf(stderr, "Could not load module '%s' - %s\n",
3967  filename, dlerror());
3968  return;
3969  }
3970 
3971  init_func = dlsym(dll, "ffserver_module_init");
3972  if (!init_func) {
3973  fprintf(stderr,
3974  "%s: init function 'ffserver_module_init()' not found\n",
3975  filename);
3976  dlclose(dll);
3977  }
3978 
3979  init_func();
3980 }
3981 #endif
3982 
3983 static int ffserver_opt_default(const char *opt, const char *arg,
3984  AVCodecContext *avctx, int type)
3985 {
3986  int ret = 0;
3987  const AVOption *o = av_opt_find(avctx, opt, NULL, type, 0);
3988  if(o)
3989  ret = av_opt_set(avctx, opt, arg, 0);
3990  return ret;
3991 }
3992 
3993 static int ffserver_opt_preset(const char *arg,
3994  AVCodecContext *avctx, int type,
3995  enum AVCodecID *audio_id, enum AVCodecID *video_id)
3996 {
3997  FILE *f=NULL;
3998  char filename[1000], tmp[1000], tmp2[1000], line[1000];
3999  int ret = 0;
4000  AVCodec *codec = avcodec_find_encoder(avctx->codec_id);
4001 
4002  if (!(f = get_preset_file(filename, sizeof(filename), arg, 0,
4003  codec ? codec->name : NULL))) {
4004  fprintf(stderr, "File for preset '%s' not found\n", arg);
4005  return 1;
4006  }
4007 
4008  while(!feof(f)){
4009  int e= fscanf(f, "%999[^\n]\n", line) - 1;
4010  if(line[0] == '#' && !e)
4011  continue;
4012  e|= sscanf(line, "%999[^=]=%999[^\n]\n", tmp, tmp2) - 2;
4013  if(e){
4014  fprintf(stderr, "%s: Invalid syntax: '%s'\n", filename, line);
4015  ret = 1;
4016  break;
4017  }
4018  if(!strcmp(tmp, "acodec")){
4019  *audio_id = opt_audio_codec(tmp2);
4020  }else if(!strcmp(tmp, "vcodec")){
4021  *video_id = opt_video_codec(tmp2);
4022  }else if(!strcmp(tmp, "scodec")){
4023  /* opt_subtitle_codec(tmp2); */
4024  }else if(ffserver_opt_default(tmp, tmp2, avctx, type) < 0){
4025  fprintf(stderr, "%s: Invalid option or argument: '%s', parsed as '%s' = '%s'\n", filename, line, tmp, tmp2);
4026  ret = 1;
4027  break;
4028  }
4029  }
4030 
4031  fclose(f);
4032 
4033  return ret;
4034 }
4035 
4036 static AVOutputFormat *ffserver_guess_format(const char *short_name, const char *filename,
4037  const char *mime_type)
4038 {
4039  AVOutputFormat *fmt = av_guess_format(short_name, filename, mime_type);
4040 
4041  if (fmt) {
4042  AVOutputFormat *stream_fmt;
4043  char stream_format_name[64];
4044 
4045  snprintf(stream_format_name, sizeof(stream_format_name), "%s_stream", fmt->name);
4046  stream_fmt = av_guess_format(stream_format_name, NULL, NULL);
4047 
4048  if (stream_fmt)
4049  fmt = stream_fmt;
4050  }
4051 
4052  return fmt;
4053 }
4054 
4055 static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt, ...)
4056 {
4057  va_list vl;
4058  va_start(vl, fmt);
4059  fprintf(stderr, "%s:%d: ", filename, line_num);
4060  vfprintf(stderr, fmt, vl);
4061  va_end(vl);
4062 
4063  (*errors)++;
4064 }
4065 
4066 static int parse_ffconfig(const char *filename)
4067 {
4068  FILE *f;
4069  char line[1024];
4070  char cmd[64];
4071  char arg[1024];
4072  const char *p;
4073  int val, errors, line_num;
4074  FFStream **last_stream, *stream, *redirect;
4075  FFStream **last_feed, *feed, *s;
4076  AVCodecContext audio_enc, video_enc;
4077  enum AVCodecID audio_id, video_id;
4078 
4079  f = fopen(filename, "r");
4080  if (!f) {
4081  perror(filename);
4082  return -1;
4083  }
4084 
4085  errors = 0;
4086  line_num = 0;
4087  first_stream = NULL;
4088  last_stream = &first_stream;
4089  first_feed = NULL;
4090  last_feed = &first_feed;
4091  stream = NULL;
4092  feed = NULL;
4093  redirect = NULL;
4094  audio_id = AV_CODEC_ID_NONE;
4095  video_id = AV_CODEC_ID_NONE;
4096 
4097 #define ERROR(...) report_config_error(filename, line_num, &errors, __VA_ARGS__)
4098  for(;;) {
4099  if (fgets(line, sizeof(line), f) == NULL)
4100  break;
4101  line_num++;
4102  p = line;
4103  while (av_isspace(*p))
4104  p++;
4105  if (*p == '\0' || *p == '#')
4106  continue;
4107 
4108  get_arg(cmd, sizeof(cmd), &p);
4109 
4110  if (!av_strcasecmp(cmd, "Port")) {
4111  get_arg(arg, sizeof(arg), &p);
4112  val = atoi(arg);
4113  if (val < 1 || val > 65536) {
4114  ERROR("Invalid_port: %s\n", arg);
4115  }
4116  my_http_addr.sin_port = htons(val);
4117  } else if (!av_strcasecmp(cmd, "BindAddress")) {
4118  get_arg(arg, sizeof(arg), &p);
4119  if (resolve_host(&my_http_addr.sin_addr, arg) != 0) {
4120  ERROR("%s:%d: Invalid host/IP address: %s\n", arg);
4121  }
4122  } else if (!av_strcasecmp(cmd, "NoDaemon")) {
4123  // do nothing here, its the default now
4124  } else if (!av_strcasecmp(cmd, "RTSPPort")) {
4125  get_arg(arg, sizeof(arg), &p);
4126  val = atoi(arg);
4127  if (val < 1 || val > 65536) {
4128  ERROR("%s:%d: Invalid port: %s\n", arg);
4129  }
4130  my_rtsp_addr.sin_port = htons(atoi(arg));
4131  } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) {
4132  get_arg(arg, sizeof(arg), &p);
4133  if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) {
4134  ERROR("Invalid host/IP address: %s\n", arg);
4135  }
4136  } else if (!av_strcasecmp(cmd, "MaxHTTPConnections")) {
4137  get_arg(arg, sizeof(arg), &p);
4138  val = atoi(arg);
4139  if (val < 1 || val > 65536) {
4140  ERROR("Invalid MaxHTTPConnections: %s\n", arg);
4141  }
4143  } else if (!av_strcasecmp(cmd, "MaxClients")) {
4144  get_arg(arg, sizeof(arg), &p);
4145  val = atoi(arg);
4146  if (val < 1 || val > nb_max_http_connections) {
4147  ERROR("Invalid MaxClients: %s\n", arg);
4148  } else {
4150  }
4151  } else if (!av_strcasecmp(cmd, "MaxBandwidth")) {
4152  int64_t llval;
4153  get_arg(arg, sizeof(arg), &p);
4154  llval = atoll(arg);
4155  if (llval < 10 || llval > 10000000) {
4156  ERROR("Invalid MaxBandwidth: %s\n", arg);
4157  } else
4158  max_bandwidth = llval;
4159  } else if (!av_strcasecmp(cmd, "CustomLog")) {
4160  if (!ffserver_debug)
4161  get_arg(logfilename, sizeof(logfilename), &p);
4162  } else if (!av_strcasecmp(cmd, "<Feed")) {
4163  /*********************************************/
4164  /* Feed related options */
4165  char *q;
4166  if (stream || feed) {
4167  ERROR("Already in a tag\n");
4168  } else {
4169  feed = av_mallocz(sizeof(FFStream));
4170  get_arg(feed->filename, sizeof(feed->filename), &p);
4171  q = strrchr(feed->filename, '>');
4172  if (*q)
4173  *q = '\0';
4174 
4175  for (s = first_feed; s; s = s->next) {
4176  if (!strcmp(feed->filename, s->filename)) {
4177  ERROR("Feed '%s' already registered\n", s->filename);
4178  }
4179  }
4180 
4181  feed->fmt = av_guess_format("ffm", NULL, NULL);
4182  /* defaut feed file */
4183  snprintf(feed->feed_filename, sizeof(feed->feed_filename),
4184  "/tmp/%s.ffm", feed->filename);
4185  feed->feed_max_size = 5 * 1024 * 1024;
4186  feed->is_feed = 1;
4187  feed->feed = feed; /* self feeding :-) */
4188 
4189  /* add in stream list */
4190  *last_stream = feed;
4191  last_stream = &feed->next;
4192  /* add in feed list */
4193  *last_feed = feed;
4194  last_feed = &feed->next_feed;
4195  }
4196  } else if (!av_strcasecmp(cmd, "Launch")) {
4197  if (feed) {
4198  int i;
4199 
4200  feed->child_argv = av_mallocz(64 * sizeof(char *));
4201 
4202  for (i = 0; i < 62; i++) {
4203  get_arg(arg, sizeof(arg), &p);
4204  if (!arg[0])
4205  break;
4206 
4207  feed->child_argv[i] = av_strdup(arg);
4208  }
4209 
4210  feed->child_argv[i] = av_asprintf("http://%s:%d/%s",
4211  (my_http_addr.sin_addr.s_addr == INADDR_ANY) ? "127.0.0.1" :
4212  inet_ntoa(my_http_addr.sin_addr),
4213  ntohs(my_http_addr.sin_port), feed->filename);
4214  }
4215  } else if (!av_strcasecmp(cmd, "ReadOnlyFile")) {
4216  if (feed) {
4217  get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4218  feed->readonly = 1;
4219  } else if (stream) {
4220  get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4221  }
4222  } else if (!av_strcasecmp(cmd, "File")) {
4223  if (feed) {
4224  get_arg(feed->feed_filename, sizeof(feed->feed_filename), &p);
4225  } else if (stream)
4226  get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4227  } else if (!av_strcasecmp(cmd, "Truncate")) {
4228  if (feed) {
4229  get_arg(arg, sizeof(arg), &p);
4230  feed->truncate = strtod(arg, NULL);
4231  }
4232  } else if (!av_strcasecmp(cmd, "FileMaxSize")) {
4233  if (feed) {
4234  char *p1;
4235  double fsize;
4236 
4237  get_arg(arg, sizeof(arg), &p);
4238  p1 = arg;
4239  fsize = strtod(p1, &p1);
4240  switch(av_toupper(*p1)) {
4241  case 'K':
4242  fsize *= 1024;
4243  break;
4244  case 'M':
4245  fsize *= 1024 * 1024;
4246  break;
4247  case 'G':
4248  fsize *= 1024 * 1024 * 1024;
4249  break;
4250  }
4251  feed->feed_max_size = (int64_t)fsize;
4252  if (feed->feed_max_size < FFM_PACKET_SIZE*4) {
4253  ERROR("Feed max file size is too small, must be at least %d\n", FFM_PACKET_SIZE*4);
4254  }
4255  }
4256  } else if (!av_strcasecmp(cmd, "</Feed>")) {
4257  if (!feed) {
4258  ERROR("No corresponding <Feed> for </Feed>\n");
4259  }
4260  feed = NULL;
4261  } else if (!av_strcasecmp(cmd, "<Stream")) {
4262  /*********************************************/
4263  /* Stream related options */
4264  char *q;
4265  if (stream || feed) {
4266  ERROR("Already in a tag\n");
4267  } else {
4268  FFStream *s;
4269  stream = av_mallocz(sizeof(FFStream));
4270  get_arg(stream->filename, sizeof(stream->filename), &p);
4271  q = strrchr(stream->filename, '>');
4272  if (q)
4273  *q = '\0';
4274 
4275  for (s = first_stream; s; s = s->next) {
4276  if (!strcmp(stream->filename, s->filename)) {
4277  ERROR("Stream '%s' already registered\n", s->filename);
4278  }
4279  }
4280 
4281  stream->fmt = ffserver_guess_format(NULL, stream->filename, NULL);
4282  avcodec_get_context_defaults3(&video_enc, NULL);
4283  avcodec_get_context_defaults3(&audio_enc, NULL);
4284 
4285  audio_id = AV_CODEC_ID_NONE;
4286  video_id = AV_CODEC_ID_NONE;
4287  if (stream->fmt) {
4288  audio_id = stream->fmt->audio_codec;
4289  video_id = stream->fmt->video_codec;
4290  }
4291 
4292  *last_stream = stream;
4293  last_stream = &stream->next;
4294  }
4295  } else if (!av_strcasecmp(cmd, "Feed")) {
4296  get_arg(arg, sizeof(arg), &p);
4297  if (stream) {
4298  FFStream *sfeed;
4299 
4300  sfeed = first_feed;
4301  while (sfeed != NULL) {
4302  if (!strcmp(sfeed->filename, arg))
4303  break;
4304  sfeed = sfeed->next_feed;
4305  }
4306  if (!sfeed)
4307  ERROR("feed '%s' not defined\n", arg);
4308  else
4309  stream->feed = sfeed;
4310  }
4311  } else if (!av_strcasecmp(cmd, "Format")) {
4312  get_arg(arg, sizeof(arg), &p);
4313  if (stream) {
4314  if (!strcmp(arg, "status")) {
4315  stream->stream_type = STREAM_TYPE_STATUS;
4316  stream->fmt = NULL;
4317  } else {
4318  stream->stream_type = STREAM_TYPE_LIVE;
4319  /* jpeg cannot be used here, so use single frame jpeg */
4320  if (!strcmp(arg, "jpeg"))
4321  strcpy(arg, "mjpeg");
4322  stream->fmt = ffserver_guess_format(arg, NULL, NULL);
4323  if (!stream->fmt) {
4324  ERROR("Unknown Format: %s\n", arg);
4325  }
4326  }
4327  if (stream->fmt) {
4328  audio_id = stream->fmt->audio_codec;
4329  video_id = stream->fmt->video_codec;
4330  }
4331  }
4332  } else if (!av_strcasecmp(cmd, "InputFormat")) {
4333  get_arg(arg, sizeof(arg), &p);
4334  if (stream) {
4335  stream->ifmt = av_find_input_format(arg);
4336  if (!stream->ifmt) {
4337  ERROR("Unknown input format: %s\n", arg);
4338  }
4339  }
4340  } else if (!av_strcasecmp(cmd, "FaviconURL")) {
4341  if (stream && stream->stream_type == STREAM_TYPE_STATUS) {
4342  get_arg(stream->feed_filename, sizeof(stream->feed_filename), &p);
4343  } else {
4344  ERROR("FaviconURL only permitted for status streams\n");
4345  }
4346  } else if (!av_strcasecmp(cmd, "Author")) {
4347  if (stream)
4348  get_arg(stream->author, sizeof(stream->author), &p);
4349  } else if (!av_strcasecmp(cmd, "Comment")) {
4350  if (stream)
4351  get_arg(stream->comment, sizeof(stream->comment), &p);
4352  } else if (!av_strcasecmp(cmd, "Copyright")) {
4353  if (stream)
4354  get_arg(stream->copyright, sizeof(stream->copyright), &p);
4355  } else if (!av_strcasecmp(cmd, "Title")) {
4356  if (stream)
4357  get_arg(stream->title, sizeof(stream->title), &p);
4358  } else if (!av_strcasecmp(cmd, "Preroll")) {
4359  get_arg(arg, sizeof(arg), &p);
4360  if (stream)
4361  stream->prebuffer = atof(arg) * 1000;
4362  } else if (!av_strcasecmp(cmd, "StartSendOnKey")) {
4363  if (stream)
4364  stream->send_on_key = 1;
4365  } else if (!av_strcasecmp(cmd, "AudioCodec")) {
4366  get_arg(arg, sizeof(arg), &p);
4367  audio_id = opt_audio_codec(arg);
4368  if (audio_id == AV_CODEC_ID_NONE) {
4369  ERROR("Unknown AudioCodec: %s\n", arg);
4370  }
4371  } else if (!av_strcasecmp(cmd, "VideoCodec")) {
4372  get_arg(arg, sizeof(arg), &p);
4373  video_id = opt_video_codec(arg);
4374  if (video_id == AV_CODEC_ID_NONE) {
4375  ERROR("Unknown VideoCodec: %s\n", arg);
4376  }
4377  } else if (!av_strcasecmp(cmd, "MaxTime")) {
4378  get_arg(arg, sizeof(arg), &p);
4379  if (stream)
4380  stream->max_time = atof(arg) * 1000;
4381  } else if (!av_strcasecmp(cmd, "AudioBitRate")) {
4382  get_arg(arg, sizeof(arg), &p);
4383  if (stream)
4384  audio_enc.bit_rate = lrintf(atof(arg) * 1000);
4385  } else if (!av_strcasecmp(cmd, "AudioChannels")) {
4386  get_arg(arg, sizeof(arg), &p);
4387  if (stream)
4388  audio_enc.channels = atoi(arg);
4389  } else if (!av_strcasecmp(cmd, "AudioSampleRate")) {
4390  get_arg(arg, sizeof(arg), &p);
4391  if (stream)
4392  audio_enc.sample_rate = atoi(arg);
4393  } else if (!av_strcasecmp(cmd, "AudioQuality")) {
4394  get_arg(arg, sizeof(arg), &p);
4395  if (stream) {
4396 // audio_enc.quality = atof(arg) * 1000;
4397  }
4398  } else if (!av_strcasecmp(cmd, "VideoBitRateRange")) {
4399  if (stream) {
4400  int minrate, maxrate;
4401 
4402  get_arg(arg, sizeof(arg), &p);
4403 
4404  if (sscanf(arg, "%d-%d", &minrate, &maxrate) == 2) {
4405  video_enc.rc_min_rate = minrate * 1000;
4406  video_enc.rc_max_rate = maxrate * 1000;
4407  } else {
4408  ERROR("Incorrect format for VideoBitRateRange -- should be <min>-<max>: %s\n", arg);
4409  }
4410  }
4411  } else if (!av_strcasecmp(cmd, "Debug")) {
4412  if (stream) {
4413  get_arg(arg, sizeof(arg), &p);
4414  video_enc.debug = strtol(arg,0,0);
4415  }
4416  } else if (!av_strcasecmp(cmd, "Strict")) {
4417  if (stream) {
4418  get_arg(arg, sizeof(arg), &p);
4419  video_enc.strict_std_compliance = atoi(arg);
4420  }
4421  } else if (!av_strcasecmp(cmd, "VideoBufferSize")) {
4422  if (stream) {
4423  get_arg(arg, sizeof(arg), &p);
4424  video_enc.rc_buffer_size = atoi(arg) * 8*1024;
4425  }
4426  } else if (!av_strcasecmp(cmd, "VideoBitRateTolerance")) {
4427  if (stream) {
4428  get_arg(arg, sizeof(arg), &p);
4429  video_enc.bit_rate_tolerance = atoi(arg) * 1000;
4430  }
4431  } else if (!av_strcasecmp(cmd, "VideoBitRate")) {
4432  get_arg(arg, sizeof(arg), &p);
4433  if (stream) {
4434  video_enc.bit_rate = atoi(arg) * 1000;
4435  }
4436  } else if (!av_strcasecmp(cmd, "VideoSize")) {
4437  get_arg(arg, sizeof(arg), &p);
4438  if (stream) {
4439  av_parse_video_size(&video_enc.width, &video_enc.height, arg);
4440  if ((video_enc.width % 16) != 0 ||
4441  (video_enc.height % 16) != 0) {
4442  ERROR("Image size must be a multiple of 16\n");
4443  }
4444  }
4445  } else if (!av_strcasecmp(cmd, "VideoFrameRate")) {
4446  get_arg(arg, sizeof(arg), &p);
4447  if (stream) {
4448  AVRational frame_rate;
4449  if (av_parse_video_rate(&frame_rate, arg) < 0) {
4450  ERROR("Incorrect frame rate: %s\n", arg);
4451  } else {
4452  video_enc.time_base.num = frame_rate.den;
4453  video_enc.time_base.den = frame_rate.num;
4454  }
4455  }
4456  } else if (!av_strcasecmp(cmd, "VideoGopSize")) {
4457  get_arg(arg, sizeof(arg), &p);
4458  if (stream)
4459  video_enc.gop_size = atoi(arg);
4460  } else if (!av_strcasecmp(cmd, "VideoIntraOnly")) {
4461  if (stream)
4462  video_enc.gop_size = 1;
4463  } else if (!av_strcasecmp(cmd, "VideoHighQuality")) {
4464  if (stream)
4465  video_enc.mb_decision = FF_MB_DECISION_BITS;
4466  } else if (!av_strcasecmp(cmd, "Video4MotionVector")) {
4467  if (stream) {
4468  video_enc.mb_decision = FF_MB_DECISION_BITS; //FIXME remove
4469  video_enc.flags |= CODEC_FLAG_4MV;
4470  }
4471  } else if (!av_strcasecmp(cmd, "AVOptionVideo") ||
4472  !av_strcasecmp(cmd, "AVOptionAudio")) {
4473  char arg2[1024];
4474  AVCodecContext *avctx;
4475  int type;
4476  get_arg(arg, sizeof(arg), &p);
4477  get_arg(arg2, sizeof(arg2), &p);
4478  if (!av_strcasecmp(cmd, "AVOptionVideo")) {
4479  avctx = &video_enc;
4480  type = AV_OPT_FLAG_VIDEO_PARAM;
4481  } else {
4482  avctx = &audio_enc;
4483  type = AV_OPT_FLAG_AUDIO_PARAM;
4484  }
4485  if (ffserver_opt_default(arg, arg2, avctx, type|AV_OPT_FLAG_ENCODING_PARAM)) {
4486  ERROR("AVOption error: %s %s\n", arg, arg2);
4487  }
4488  } else if (!av_strcasecmp(cmd, "AVPresetVideo") ||
4489  !av_strcasecmp(cmd, "AVPresetAudio")) {
4490  AVCodecContext *avctx;
4491  int type;
4492  get_arg(arg, sizeof(arg), &p);
4493  if (!av_strcasecmp(cmd, "AVPresetVideo")) {
4494  avctx = &video_enc;
4495  video_enc.codec_id = video_id;
4496  type = AV_OPT_FLAG_VIDEO_PARAM;
4497  } else {
4498  avctx = &audio_enc;
4499  audio_enc.codec_id = audio_id;
4500  type = AV_OPT_FLAG_AUDIO_PARAM;
4501  }
4502  if (ffserver_opt_preset(arg, avctx, type|AV_OPT_FLAG_ENCODING_PARAM, &audio_id, &video_id)) {
4503  ERROR("AVPreset error: %s\n", arg);
4504  }
4505  } else if (!av_strcasecmp(cmd, "VideoTag")) {
4506  get_arg(arg, sizeof(arg), &p);
4507  if ((strlen(arg) == 4) && stream)
4508  video_enc.codec_tag = MKTAG(arg[0], arg[1], arg[2], arg[3]);
4509  } else if (!av_strcasecmp(cmd, "BitExact")) {
4510  if (stream)
4511  video_enc.flags |= CODEC_FLAG_BITEXACT;
4512  } else if (!av_strcasecmp(cmd, "DctFastint")) {
4513  if (stream)
4514  video_enc.dct_algo = FF_DCT_FASTINT;
4515  } else if (!av_strcasecmp(cmd, "IdctSimple")) {
4516  if (stream)
4517  video_enc.idct_algo = FF_IDCT_SIMPLE;
4518  } else if (!av_strcasecmp(cmd, "Qscale")) {
4519  get_arg(arg, sizeof(arg), &p);
4520  if (stream) {
4521  video_enc.flags |= CODEC_FLAG_QSCALE;
4522  video_enc.global_quality = FF_QP2LAMBDA * atoi(arg);
4523  }
4524  } else if (!av_strcasecmp(cmd, "VideoQDiff")) {
4525  get_arg(arg, sizeof(arg), &p);
4526  if (stream) {
4527  video_enc.max_qdiff = atoi(arg);
4528  if (video_enc.max_qdiff < 1 || video_enc.max_qdiff > 31) {
4529  ERROR("VideoQDiff out of range\n");
4530  }
4531  }
4532  } else if (!av_strcasecmp(cmd, "VideoQMax")) {
4533  get_arg(arg, sizeof(arg), &p);
4534  if (stream) {
4535  video_enc.qmax = atoi(arg);
4536  if (video_enc.qmax < 1 || video_enc.qmax > 31) {
4537  ERROR("VideoQMax out of range\n");
4538  }
4539  }
4540  } else if (!av_strcasecmp(cmd, "VideoQMin")) {
4541  get_arg(arg, sizeof(arg), &p);
4542  if (stream) {
4543  video_enc.qmin = atoi(arg);
4544  if (video_enc.qmin < 1 || video_enc.qmin > 31) {
4545  ERROR("VideoQMin out of range\n");
4546  }
4547  }
4548  } else if (!av_strcasecmp(cmd, "LumiMask")) {
4549  get_arg(arg, sizeof(arg), &p);
4550  if (stream)
4551  video_enc.lumi_masking = atof(arg);
4552  } else if (!av_strcasecmp(cmd, "DarkMask")) {
4553  get_arg(arg, sizeof(arg), &p);
4554  if (stream)
4555  video_enc.dark_masking = atof(arg);
4556  } else if (!av_strcasecmp(cmd, "NoVideo")) {
4557  video_id = AV_CODEC_ID_NONE;
4558  } else if (!av_strcasecmp(cmd, "NoAudio")) {
4559  audio_id = AV_CODEC_ID_NONE;
4560  } else if (!av_strcasecmp(cmd, "ACL")) {
4561  parse_acl_row(stream, feed, NULL, p, filename, line_num);
4562  } else if (!av_strcasecmp(cmd, "DynamicACL")) {
4563  if (stream) {
4564  get_arg(stream->dynamic_acl, sizeof(stream->dynamic_acl), &p);
4565  }
4566  } else if (!av_strcasecmp(cmd, "RTSPOption")) {
4567  get_arg(arg, sizeof(arg), &p);
4568  if (stream) {
4569  av_freep(&stream->rtsp_option);
4570  stream->rtsp_option = av_strdup(arg);
4571  }
4572  } else if (!av_strcasecmp(cmd, "MulticastAddress")) {
4573  get_arg(arg, sizeof(arg), &p);
4574  if (stream) {
4575  if (resolve_host(&stream->multicast_ip, arg) != 0) {
4576  ERROR("Invalid host/IP address: %s\n", arg);
4577  }
4578  stream->is_multicast = 1;
4579  stream->loop = 1; /* default is looping */
4580  }
4581  } else if (!av_strcasecmp(cmd, "MulticastPort")) {
4582  get_arg(arg, sizeof(arg), &p);
4583  if (stream)
4584  stream->multicast_port = atoi(arg);
4585  } else if (!av_strcasecmp(cmd, "MulticastTTL")) {
4586  get_arg(arg, sizeof(arg), &p);
4587  if (stream)
4588  stream->multicast_ttl = atoi(arg);
4589  } else if (!av_strcasecmp(cmd, "NoLoop")) {
4590  if (stream)
4591  stream->loop = 0;
4592  } else if (!av_strcasecmp(cmd, "</Stream>")) {
4593  if (!stream) {
4594  ERROR("No corresponding <Stream> for </Stream>\n");
4595  } else {
4596  if (stream->feed && stream->fmt && strcmp(stream->fmt->name, "ffm") != 0) {
4597  if (audio_id != AV_CODEC_ID_NONE) {
4598  audio_enc.codec_type = AVMEDIA_TYPE_AUDIO;
4599  audio_enc.codec_id = audio_id;
4600  add_codec(stream, &audio_enc);
4601  }
4602  if (video_id != AV_CODEC_ID_NONE) {
4603  video_enc.codec_type = AVMEDIA_TYPE_VIDEO;
4604  video_enc.codec_id = video_id;
4605  add_codec(stream, &video_enc);
4606  }
4607  }
4608  stream = NULL;
4609  }
4610  } else if (!av_strcasecmp(cmd, "<Redirect")) {
4611  /*********************************************/
4612  char *q;
4613  if (stream || feed || redirect) {
4614  ERROR("Already in a tag\n");
4615  } else {
4616  redirect = av_mallocz(sizeof(FFStream));
4617  *last_stream = redirect;
4618  last_stream = &redirect->next;
4619 
4620  get_arg(redirect->filename, sizeof(redirect->filename), &p);
4621  q = strrchr(redirect->filename, '>');
4622  if (*q)
4623  *q = '\0';
4624  redirect->stream_type = STREAM_TYPE_REDIRECT;
4625  }
4626  } else if (!av_strcasecmp(cmd, "URL")) {
4627  if (redirect)
4628  get_arg(redirect->feed_filename, sizeof(redirect->feed_filename), &p);
4629  } else if (!av_strcasecmp(cmd, "</Redirect>")) {
4630  if (!redirect) {
4631  ERROR("No corresponding <Redirect> for </Redirect>\n");
4632  } else {
4633  if (!redirect->feed_filename[0]) {
4634  ERROR("No URL found for <Redirect>\n");
4635  }
4636  redirect = NULL;
4637  }
4638  } else if (!av_strcasecmp(cmd, "LoadModule")) {
4639  get_arg(arg, sizeof(arg), &p);
4640 #if HAVE_DLOPEN
4641  load_module(arg);
4642 #else
4643  ERROR("Module support not compiled into this version: '%s'\n", arg);
4644 #endif
4645  } else {
4646  ERROR("Incorrect keyword: '%s'\n", cmd);
4647  }
4648  }
4649 #undef ERROR
4650 
4651  fclose(f);
4652  if (errors)
4653  return -1;
4654  else
4655  return 0;
4656 }
4657 
4658 static void handle_child_exit(int sig)
4659 {
4660  pid_t pid;
4661  int status;
4662 
4663  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
4664  FFStream *feed;
4665 
4666  for (feed = first_feed; feed; feed = feed->next) {
4667  if (feed->pid == pid) {
4668  int uptime = time(0) - feed->pid_start;
4669 
4670  feed->pid = 0;
4671  fprintf(stderr, "%s: Pid %d exited with status %d after %d seconds\n", feed->filename, pid, status, uptime);
4672 
4673  if (uptime < 30)
4674  /* Turn off any more restarts */
4675  feed->child_argv = 0;
4676  }
4677  }
4678  }
4679 
4681 }
4682 
4683 static void opt_debug(void)
4684 {
4685  ffserver_debug = 1;
4686  logfilename[0] = '-';
4687 }
4688 
4689 void show_help_default(const char *opt, const char *arg)
4690 {
4691  printf("usage: ffserver [options]\n"
4692  "Hyper fast multi format Audio/Video streaming server\n");
4693  printf("\n");
4694  show_help_options(options, "Main options:", 0, 0, 0);
4695 }
4696 
4697 static const OptionDef options[] = {
4698 #include "cmdutils_common_opts.h"
4699  { "n", OPT_BOOL, {(void *)&no_launch }, "enable no-launch mode" },
4700  { "d", 0, {(void*)opt_debug}, "enable debug mode" },
4701  { "f", HAS_ARG | OPT_STRING, {(void*)&config_filename }, "use configfile instead of /etc/ffserver.conf", "configfile" },
4702  { NULL },
4703 };
4704 
4705 int main(int argc, char **argv)
4706 {
4707  struct sigaction sigact = { { 0 } };
4708 
4709  parse_loglevel(argc, argv, options);
4710  av_register_all();
4712 
4713  show_banner(argc, argv, options);
4714 
4715  my_program_name = argv[0];
4716 
4717  parse_options(NULL, argc, argv, options, NULL);
4718 
4719  if (!config_filename)
4720  config_filename = av_strdup("/etc/ffserver.conf");
4721 
4722  unsetenv("http_proxy"); /* Kill the http_proxy */
4723 
4724  av_lfg_init(&random_state, av_get_random_seed());
4725 
4726  sigact.sa_handler = handle_child_exit;
4727  sigact.sa_flags = SA_NOCLDSTOP | SA_RESTART;
4728  sigaction(SIGCHLD, &sigact, 0);
4729 
4730  if (parse_ffconfig(config_filename) < 0) {
4731  fprintf(stderr, "Incorrect config file - exiting.\n");
4732  exit(1);
4733  }
4735 
4736  /* open log file if needed */
4737  if (logfilename[0] != '\0') {
4738  if (!strcmp(logfilename, "-"))
4739  logfile = stdout;
4740  else
4741  logfile = fopen(logfilename, "a");
4743  }
4744 
4746 
4748 
4750 
4751  /* signal init */
4752  signal(SIGPIPE, SIG_IGN);
4753 
4754  if (http_server() < 0) {
4755  http_log("Could not start server\n");
4756  exit(1);
4757  }
4758 
4759  return 0;
4760 }
or the Software in violation of any applicable export control laws in any jurisdiction Except as provided by mandatorily applicable UPF has no obligation to provide you with source code to the Software In the event Software contains any source unless expressly licensed for other it is provided solely for reference purposes pursuant to the terms of this License Source code may not be redistributed unless expressly provided for in this License INTELLECTUAL AND INDUSTRIAL PROPERTY RIGHTS Title to Software and all associated intellectual and industrial property rights is retained by UPF and or its licensors UPF warrants that the copyright in the Software is owned by it or licensed to it and that it has the power and authority to grant the Licence You shall keep intact all copyright
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:799
static int rtp_new_av_stream(HTTPContext *c, int stream_index, struct sockaddr_in *dest_addr, HTTPContext *rtsp_c)
Definition: ffserver.c:3410
int is_multicast
Definition: ffserver.c:244
static int ffserver_opt_default(const char *opt, const char *arg, AVCodecContext *avctx, int type)
Definition: ffserver.c:3983
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.
static HTTPContext * find_rtp_session(const char *session_id)
Definition: ffserver.c:3062
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:205
int64_t count1
Definition: ffserver.c:124
const struct AVCodec * codec
static const char * config_filename
Definition: ffserver.c:311
struct HTTPContext HTTPContext
static const char * my_program_name
Definition: ffserver.c:309
const char * s
Definition: avisynth_c.h:668
char ** child_argv
Definition: ffserver.c:238
Bytestream IO Context.
Definition: avio.h:68
static void http_log(const char *fmt,...)
Definition: ffserver.c:431
static void rtsp_reply_error(HTTPContext *c, enum RTSPStatusCode error_number)
Definition: ffserver.c:2864
void av_free_packet(AVPacket *pkt)
Free a packet.
Definition: avpacket.c:242
int chunked_encoding
Definition: ffserver.c:138
RTSPLowerTransport
Network layer over which RTP/etc packet data will be transported.
Definition: rtsp.h:37
int av_parse_video_rate(AVRational *rate, const char *arg)
Parse str and store the detected values in *rate.
Definition: parseutils.c:162
AVCodec * avcodec_find_encoder(enum AVCodecID id)
Find a registered encoder with a matching codec ID.
static void http_av_log(void *ptr, int level, const char *fmt, va_list vargs)
Definition: ffserver.c:439
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:988
int dct_algo
DCT algorithm, see FF_DCT_* below.
AVOption.
Definition: opt.h:251
static int validate_acl(FFStream *stream, HTTPContext *c)
Definition: ffserver.c:1435
int av_parse_video_size(int *width_ptr, int *height_ptr, const char *str)
Parse str and put in width_ptr and height_ptr the detected values.
Definition: parseutils.c:131
int64_t time2
Definition: ffserver.c:125
struct IPAddressACL IPAddressACL
float avg_frame_size
Definition: ffserver.c:265
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:383
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:504
const char * fmt
Definition: avisynth_c.h:669
static void build_file_streams(void)
Definition: ffserver.c:3644
float qblur
amount of qscale smoothing over time (0.0-1.0)
AVInputFormat * ifmt
Definition: ffserver.c:220
#define AV_RB64
int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
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.
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:530
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:317
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:55
struct HTTPContext * next
Definition: ffserver.c:140
HTTPState
Definition: ffserver.c:77
static void rtsp_reply_header(HTTPContext *c, enum RTSPStatusCode error_number)
Definition: ffserver.c:2808
enum AVCodecID video_codec
default video codec
Definition: avformat.h:389
static int64_t cur_time
Definition: ffserver.c:325
static void rtsp_cmd_play(HTTPContext *c, const char *url, RTSPMessageHeader *h)
Definition: ffserver.c:3269
int multicast_port
Definition: ffserver.c:246
int feed_opened
Definition: ffserver.c:251
struct in_addr last
Definition: ffserver.c:210
AVFormatContext * fmt_in
Definition: ffserver.c:146
static int parse_ffconfig(const char *filename)
Definition: ffserver.c:4066
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:709
static void report_config_error(const char *filename, int line_num, int *errors, const char *fmt,...)
Definition: ffserver.c:4055
int num
numerator
Definition: rational.h:44
#define AV_OPT_FLAG_AUDIO_PARAM
Definition: opt.h:284
int index
stream index in AVFormatContext
Definition: avformat.h:644
title('Sinusoid at 1/4 the Spampling Rate')
#define AVIO_FLAG_READ
read-only
Definition: avio.h:332
enhanced predictive zonal search
static int rtsp_parse_request(HTTPContext *c)
Definition: ffserver.c:2870
int64_t feed_write_index
Definition: ffserver.c:258
Sinusoidal phase f
static void free_acl_list(IPAddressACL *in_acl)
Definition: ffserver.c:1406
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:333
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown) That is the width of a pixel divided by the height of the pixel...
AVOutputFormat * fmt
Definition: ffserver.c:221
enum AVMediaType codec_type
Definition: rtp.c:36
void show_banner(int argc, char **argv, const OptionDef *options)
Print the program banner to stderr.
Definition: cmdutils.c:1055
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition: avstring.c:222
static void parse_acl_row(FFStream *stream, FFStream *feed, IPAddressACL *ext_acl, const char *p, const char *filename, int line_num)
Definition: ffserver.c:1303
struct IPAddressACL * next
Definition: ffserver.c:206
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:663
static void remove_stream(FFStream *stream)
Definition: ffserver.c:3580
enum AVMediaType type
#define FF_ARRAY_ELEMS(a)
#define freeaddrinfo
Definition: network.h:195
void show_help_default(const char *opt, const char *arg)
Per-fftool specific help handler.
Definition: ffserver.c:4689
RedirType
Definition: ffserver.c:1481
void av_log_set_callback(void(*callback)(void *, int, const char *, va_list))
Definition: log.c:279
static const char * audio_codec_name
Definition: ffplay.c:309
int frame_skip_cmp
frame skip comparison function
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:976
int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src)
Copy the settings of the source AVCodecContext into the destination AVCodecContext.
char feed_filename[1024]
Definition: ffserver.c:230
enum RTSPLowerTransport lower_transport
network layer transport protocol; e.g.
Definition: rtsp.h:120
char dynamic_acl[1024]
Definition: ffserver.c:223
This describes the server response to each RTSP command.
Definition: rtsp.h:126
static void build_feed_streams(void)
Definition: ffserver.c:3691
int multicast_ttl
Definition: ffserver.c:247
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
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:141
IPAddressACL * acl
Definition: ffserver.c:222
const int program_birth_year
program birth year, defined by the program for show_banner()
Definition: ffserver.c:73
Format I/O context.
Definition: avformat.h:944
#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:365
#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:1027
static const float even_table[] __attribute__((aligned(8)))
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
int64_t file_size
Definition: ffm.h:46
static int ffserver_debug
Definition: ffserver.c:313
Public dictionary API.
int feed_streams[MAX_STREAMS]
Definition: ffserver.c:159
int bit_rate_tolerance
number of bits the bitstream is allowed to diverge from the reference.
static void http_vlog(const char *fmt, va_list vargs)
Definition: ffserver.c:413
uint8_t
int av_log_get_level(void)
Definition: log.c:264
int feed_streams[MAX_STREAMS]
Definition: ffserver.c:229
char session_id[512]
the "Session:" field.
Definition: rtsp.h:147
Opaque data information usually continuous.
Definition: avutil.h:145
static void opt_debug(void)
Definition: ffserver.c:4683
int64_t bytes_served
Definition: ffserver.c:256
AVOptions.
uint8_t * packet_buffer_ptr
Definition: ffserver.c:190
#define HAS_ARG
Definition: cmdutils.h:147
miscellaneous OS support macros and functions.
static void compute_real_filename(char *filename, int max_size)
Definition: ffserver.c:1457
static unsigned int nb_connections
Definition: ffserver.c:320
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:61
static AVPacket pkt
Definition: demuxing.c:56
const char program_name[]
program name, defined by the program for show_version().
Definition: ffserver.c:72
float b_quant_factor
qscale factor between IP and B-frames If > 0 then the last P-frame quantizer will be used (q= lastp_q...
static int http_parse_request(HTTPContext *c)
Definition: ffserver.c:1491
static void get_arg(char *buf, int buf_size, const char **pp)
Definition: ffserver.c:1271
int id
Format-specific stream ID.
Definition: avformat.h:650
static void start_children(FFStream *feed)
Definition: ffserver.c:484
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But first
void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf, RTSPState *rt, const char *method)
int loop
Definition: ffserver.c:248
static uint64_t max_bandwidth
Definition: ffserver.c:322
#define AVFMT_FLAG_GENPTS
Generate missing pts even if it requires parsing future frames.
Definition: avformat.h:1022
static int http_send_data(HTTPContext *c)
Definition: ffserver.c:2487
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
static void get_word(char *buf, int buf_size, const char **pp)
Definition: ffserver.c:1253
static HTTPContext * rtp_new_connection(struct sockaddr_in *from_addr, FFStream *stream, const char *session_id, enum RTSPLowerTransport rtp_protocol)
Definition: ffserver.c:3344
AVStream ** streams
Definition: avformat.h:992
double strtod(const char *, char **)
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Aggregate operation not allowed.
Definition: rtspcodes.h:32
struct FFStream * next_feed
Definition: ffserver.c:260
Service Unavailable.
Definition: rtspcodes.h:36
uint8_t * data
void parse_options(void *optctx, int argc, char **argv, const OptionDef *options, void(*parse_arg_function)(void *, const char *))
Definition: cmdutils.c:345
static FFStream * first_feed
Definition: ffserver.c:273
int avformat_network_init(void)
Do global initialization of network components.
static HTTPContext * find_rtp_session_with_url(const char *url, const char *session_id)
Definition: ffserver.c:3235
static AVStream * add_av_stream1(FFStream *stream, AVCodecContext *codec, int copy)
Definition: ffserver.c:3507
int ff_rtp_get_local_rtcp_port(URLContext *h)
Return the local rtcp port used by the RTP connection.
Definition: rtpproto.c:304
struct in_addr multicast_ip
Definition: ffserver.c:245
#define lrintf(x)
Definition: libm_mips.h:70
int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
Generate an SDP for an RTP session.
Definition: sdp.c:703
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:647
#define CODEC_FLAG_BITEXACT
Use only bitexact stuff (except (I)DCT).
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.
static int http_receive_data(HTTPContext *c)
Definition: ffserver.c:2652
static void copy(LZOContext *c, int cnt)
Copies bytes from input to output buffer with checking.
Definition: lzo.c:79
void parse_loglevel(int argc, char **argv, const OptionDef *options)
Find the &#39;-loglevel&#39; option in the command line args and apply it.
Definition: cmdutils.c:459
int readonly
Definition: ffserver.c:253
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:147
float lumi_masking
luminance masking (0-> disabled)
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:173
int chunk_size
Definition: ffserver.c:139
int duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
static unsigned int nb_max_http_connections
Definition: ffserver.c:318
DataRateData datarate
Definition: ffserver.c:165
int nb_transports
number of items in the &#39;transports&#39; variable below
Definition: rtsp.h:133
#define AV_OPT_FLAG_ENCODING_PARAM
a generic parameter which can be set by the user for muxing or encoding
Definition: opt.h:281
static FILE * logfile
Definition: ffserver.c:329
Only aggregate operation allowed.
Definition: rtspcodes.h:33
int ff_rtp_get_local_rtp_port(URLContext *h)
Return the local rtp port used by the RTP connection.
Definition: rtpproto.c:292
static const int rates[]
struct AVOutputFormat * oformat
Definition: avformat.h:958
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
AVCodec * avcodec_find_encoder_by_name(const char *name)
Find a registered encoder with the specified name.
static void http_send_too_busy_reply(int fd)
Definition: ffserver.c:787
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:130
static const uint8_t frame_size[4]
Definition: g723_1_data.h:58
int avcodec_close(AVCodecContext *avctx)
Close a given AVCodecContext and free all the data associated with it (but not the AVCodecContext its...
int64_t feed_size
Definition: ffserver.c:259
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:109
int64_t cur_clock
Definition: ffserver.c:155
enum AVCodecID id
struct RTSPActionServerSetup RTSPActionServerSetup
int nb_streams
Definition: ffserver.c:224
static int extract_rates(char *rates, int ratelen, const char *request)
Definition: ffserver.c:1120
AVCodecID
Identify the syntax and semantics of the bitstream.
uint8_t * buffer_end
Definition: ffserver.c:135
AVDictionary * metadata
Definition: avformat.h:1092
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
int main(int argc, char **argv)
Definition: ffserver.c:4705
static int handle_connection(HTTPContext *c)
Definition: ffserver.c:943
int last_packet_sent
Definition: ffserver.c:163
#define FF_MB_DECISION_BITS
chooses the one which needs the fewest bits
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:2234
struct FeedData FeedData
#define closesocket
Definition: ffserver.c:28
int64_t data_count
Definition: ffserver.c:142
int ffio_set_buf_size(AVIOContext *s, int buf_size)
Definition: aviobuf.c:726
static void rtsp_cmd_options(HTTPContext *c, const char *url)
Definition: ffserver.c:3006
static uint64_t current_bandwidth
Definition: ffserver.c:323
int qmax
maximum quantizer
int avio_close(AVIOContext *s)
Close the resource accessed by the AVIOContext s and free it.
Definition: aviobuf.c:821
AVIOContext * pb
Definition: ffserver.c:177
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:162
char copyright[512]
Definition: ffserver.c:234
const char * arg
int flags
CODEC_FLAG_*.
int64_t cur_pts
Definition: ffserver.c:149
Definition: graph2dot.c:48
#define CODEC_FLAG_QSCALE
Use fixed qscale.
int rc_max_rate
maximum bitrate
simple assert() macros that are a bit more flexible than ISO C assert().
static int socket_open_listen(struct sockaddr_in *my_addr)
Definition: ffserver.c:543
static FFStream * first_stream
Definition: ffserver.c:274
const char * name
Name of the codec implementation.
struct in_addr first
Definition: ffserver.c:209
float i_quant_factor
qscale factor between P and I-frames If > 0 then the last p frame quantizer will be used (q= lastp_q*...
const char * rc_eq
rate control equation
uint8_t * packet_buffer
Definition: ffserver.c:190
int av_isspace(int c)
Locale-independent conversion of ASCII isspace.
Definition: avstring.c:298
enum AVCodecID codec_id
Definition: mov_chan.c:433
int buffer_size
Definition: ffserver.c:170
#define FFMAX(a, b)
Definition: common.h:56
static int ffm_write_write_index(int fd, int64_t pos)
Definition: ffserver.c:342
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:82
int size
#define CHECK_CODEC(x)
int flags
A combination of AV_PKT_FLAG values.
static char logfilename[1024]
Definition: ffserver.c:271
#define FF_CMP_DCTMAX
struct FFStream FFStream
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
int rc_buffer_size
decoder bitstream buffer size
AVFormatContext fmt_ctx
Definition: ffserver.c:162
static HTTPContext * first_http_ctx
Definition: ffserver.c:272
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:112
const AVOption * av_opt_find(void *obj, const char *name, const char *unit, int opt_flags, int search_flags)
Look for an option in an object.
Definition: opt.c:1223
#define FF_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
unsigned int nb_streams
A list of all streams in the file.
Definition: avformat.h:991
static int open_input_stream(HTTPContext *c, const char *info)
Definition: ffserver.c:2164
static void log_connection(HTTPContext *c)
Definition: ffserver.c:451
#define th
Definition: regdef.h:75
MIPS optimizations info
Definition: mips.txt:2
AVInputFormat * av_find_input_format(const char *short_name)
Find AVInputFormat based on the short name of the input format.
enum StreamType stream_type
Definition: ffserver.c:215
#define MAX_STREAMS
Definition: ffserver.c:108
#define RTSP_REQUEST_TIMEOUT
Definition: ffserver.c:114
char method[16]
Definition: ffserver.c:168
struct FFStream * feed
Definition: ffserver.c:217
int seekable
A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
Definition: avio.h:117
int bit_rate
the average bitrate
static int modify_current_stream(HTTPContext *c, char *rates)
Definition: ffserver.c:1204
int is_packetized
Definition: ffserver.c:172
char filename[1024]
input or output filename
Definition: avformat.h:994
static void rtsp_cmd_describe(HTTPContext *c, const char *url)
Definition: ffserver.c:3015
#define FF_IDCT_SIMPLE
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:196
#define FFMIN(a, b)
Definition: common.h:58
enum IPAddressAction action
Definition: ffserver.c:207
int64_t start_time
Definition: ffserver.c:147
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:212
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
int ff_inet_aton(const char *str, struct in_addr *add)
ret
Definition: avfilter.c:821
int width
picture width / height.
int idct_algo
IDCT algorithm, see FF_IDCT_* below.
static enum AVCodecID opt_audio_codec(const char *arg)
Definition: ffserver.c:3937
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 &#39;max_packet_size&#39;.
Definition: aviobuf.c:981
#define RTSP_TCP_MAX_PACKET_SIZE
Definition: rtsp.h:74
#define ff_neterrno()
Definition: network.h:63
Method Not Allowed.
Definition: rtspcodes.h:28
#define FF_DCT_FASTINT
const char * name
Definition: avformat.h:378
time_t pid_start
Definition: ffserver.c:237
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate.The lists are not just lists
This describes a single item in the "Transport:" line of one stream as negotiated by the SETUP RTSP c...
Definition: rtsp.h:87
static int validate_acl_list(IPAddressACL *in_acl, HTTPContext *c)
Definition: ffserver.c:1418
int switch_pending
Definition: ffserver.c:161
static int need_to_start_children
Definition: ffserver.c:315
URLContext * rtp_handles[MAX_STREAMS]
Definition: ffserver.c:186
struct HTTPContext * rtsp_c
Definition: ffserver.c:189
static AVLFG random_state
Definition: ffserver.c:327
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...
int mb_decision
macroblock decision mode
int max_qdiff
maximum quantizer difference between frames
FIXME Range Coding of cr are level
Definition: snow.txt:367
int ff_socket_nonblock(int socket, int enable)
int cur_frame_bytes
Definition: ffserver.c:151
static const char * input_filename
Definition: ffplay.c:273
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
Stream structure.
Definition: avformat.h:643
enum RTSPLowerTransport rtp_protocol
Definition: ffserver.c:181
static int64_t ffm_read_write_index(int fd)
Definition: ffserver.c:331
struct sockaddr_in from_addr
Definition: ffserver.c:132
NULL
Definition: eval.c:55
static int width
Definition: tests/utils.c:158
sample_rate
#define ERROR(...)
AVS_Value src
Definition: avisynth_c.h:523
int http_error
Definition: ffserver.c:136
static void compute_status(HTTPContext *c)
Definition: ffserver.c:1922
enum AVMediaType codec_type
typedef void(RENAME(mix_any_func_type))
static void start_multicast(void)
Definition: ffserver.c:576
static const char * http_state[]
Definition: ffserver.c:92
enum AVCodecID codec_id
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:202
long long data_count
Definition: ffserver.c:264
char * av_strdup(const char *s)
Duplicate the string s.
Definition: mem.c:220
int sample_rate
samples per second
AVIOContext * pb
I/O context.
Definition: avformat.h:977
Close file fclose(fid)
Definition: ffm.h:44
#define AV_OPT_FLAG_VIDEO_PARAM
Definition: opt.h:285
main external API structure.
char author[512]
Definition: ffserver.c:232
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:375
int qmin
minimum quantizer
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:475
int send_on_key
Definition: ffserver.c:227
unsigned int codec_tag
fourcc (LSB first, so "ABCD" -> (&#39;D&#39;<<24) + (&#39;C&#39;<<16) + (&#39;B&#39;<<8) + &#39;A&#39;).
int prebuffer
Definition: ffserver.c:225
int64_t max_time
Definition: ffserver.c:226
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition: lfg.h:38
struct FFStream * stream
Definition: ffserver.c:157
static RTSPTransportField * find_transport(RTSPMessageHeader *h, enum RTSPLowerTransport lower_transport)
Definition: ffserver.c:3076
void * buf
Definition: avisynth_c.h:594
Definition: url.h:41
char url[128]
Definition: ffserver.c:169
char filename[1024]
Definition: ffserver.c:216
static void close_connection(HTTPContext *c)
Definition: ffserver.c:854
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:62
BYTE int const BYTE int int int height
Definition: avisynth_c.h:713
FILE * get_preset_file(char *filename, size_t filename_size, const char *preset_name, int is_path, const char *codec_name)
Get a file corresponding to a preset file.
Definition: cmdutils.c:1778
int client_port_max
Definition: rtsp.h:100
static int http_server(void)
Definition: ffserver.c:633
static IPAddressACL * parse_dynamic_acl(FFStream *stream, HTTPContext *c)
Definition: ffserver.c:1369
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
Describe the class of an AVClass context structure.
Definition: log.h:50
synthesis window for stochastic i
rational number numerator/denominator
Definition: rational.h:43
uint8_t * buffer_ptr
Definition: ffserver.c:135
#define OPT_STRING
Definition: cmdutils.h:150
static void update_datarate(DataRateData *drd, int64_t count)
Definition: ffserver.c:461
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition: avstring.c:100
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:75
static void start_wait_request(HTTPContext *c, int is_rtsp)
Definition: ffserver.c:773
#define s1
Definition: regdef.h:38
float b_quant_offset
qscale offset between IP and B-frames
#define snprintf
Definition: snprintf.h:34
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
misc parsing utilities
#define type
float qcompress
amount of qscale change between easy & hard scenes (0.0-1.0)
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
int switch_feed_streams[MAX_STREAMS]
Definition: ffserver.c:160
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:92
static int find_stream_in_feed(FFStream *feed, AVCodecContext *codec, int bit_rate)
Definition: ffserver.c:1167
static struct sockaddr_in my_http_addr
Definition: ffserver.c:268
static enum AVCodecID opt_video_codec(const char *arg)
Definition: ffserver.c:3947
float dark_masking
darkness masking (0-> disabled)
int global_quality
Global quality for codecs which cannot change it per frame.
static uint32_t state
Definition: trasher.c:27
static void extract_mpeg4_header(AVFormatContext *infile)
Definition: ffserver.c:3593
static int flags
Definition: cpu.c:23
RTSPStatusCode
RTSP handling.
Definition: rtspcodes.h:26
int ffurl_close(URLContext *h)
Definition: avio.c:359
static int64_t get_packet_send_clock(HTTPContext *c)
Definition: ffserver.c:2242
pid_t pid
Definition: ffserver.c:236
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Seek to the keyframe at timestamp.
Not Enough Bandwidth.
Definition: rtspcodes.h:29
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
static int av_toupper(int c)
Locale-independent conversion of ASCII characters to uppercase.
Definition: avstring.h:206
int truncate
Definition: ffserver.c:254
static int resolve_host(struct in_addr *sin_addr, const char *hostname)
Definition: ffserver.c:366
#define OPT_BOOL
Definition: cmdutils.h:148
int is_feed
Definition: ffserver.c:252
#define getaddrinfo
Definition: network.h:194
char transport_option[512]
Definition: ffserver.c:120
Main libavformat public API header.
int conns_served
Definition: ffserver.c:255
int64_t feed_max_size
Definition: ffserver.c:257
total errors[f0error, f0index]
Definition: extra/TWM.m:54
static struct sockaddr_in my_rtsp_addr
Definition: ffserver.c:269
static int prepare_sdp_description(FFStream *stream, uint8_t **pbuffer, struct in_addr my_ip)
Definition: ffserver.c:2959
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:247
int nsse_weight
noise vs.
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
Read packets of a media file to get stream information.
static double c[64]
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:546
struct addrinfo * ai_next
Definition: network.h:122
struct FFStream * next
Definition: ffserver.c:239
the buffer and buffer reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFilterBuffer structures They must not be accessed but through references stored in AVFilterBufferRef structures Several references can point to the same buffer
char comment[512]
Definition: ffserver.c:235
int den
denominator
Definition: rational.h:45
int avcodec_get_context_defaults3(AVCodecContext *s, const AVCodec *codec)
Set the fields of the given AVCodecContext to default values corresponding to the given codec (defaul...
struct AVInputFormat * iformat
Can only be iformat or oformat, not both at the same time.
Definition: avformat.h:957
int64_t count2
Definition: ffserver.c:124
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
char title[512]
Definition: ffserver.c:233
static void rtsp_cmd_teardown(HTTPContext *c, const char *url, RTSPMessageHeader *h)
Definition: ffserver.c:3320
static void compute_bandwidth(void)
Definition: ffserver.c:3835
static void ffm_set_write_index(AVFormatContext *s, int64_t pos, int64_t file_size)
Definition: ffserver.c:356
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
enum AVCodecID audio_codec
default audio codec
Definition: avformat.h:388
Unsupported transport.
Definition: rtspcodes.h:34
printf("static const uint8_t my_array[100] = {\n")
IPAddressAction
Definition: ffserver.c:200
void * priv_data
Format private data.
Definition: avformat.h:964
About Git write you should know how to use GIT properly Luckily Git comes with excellent documentation git help man git shows you the available git< command > help man git< command > shows information about the subcommand< command > The most comprehensive manual is the website Git Reference visit they are quite exhaustive You do not need a special username or password All you need is to provide a ssh public key to the Git server admin What follows now is a basic introduction to Git and some FFmpeg specific guidelines Read it at least if you are granted commit privileges to the FFmpeg project you are expected to be familiar with these rules I if not You can get git from etc no matter how small Every one of them has been saved from looking like a fool by this many times It s very easy for stray debug output or cosmetic modifications to slip please avoid problems through this extra level of scrutiny For cosmetics only commits you should e g by running git config global user name My Name git config global user email my email which is either set in your personal configuration file through git config core editor or set by one of the following environment VISUAL or EDITOR Log messages should be concise but descriptive Explain why you made a what you did will be obvious from the changes themselves most of the time Saying just bug fix or is bad Remember that people of varying skill levels look at and educate themselves while reading through your code Don t include filenames in log Git provides that information Possibly make the commit message have a descriptive first line
Definition: git-howto.txt:153
Method Not Valid in This State.
Definition: rtspcodes.h:31
static void load_module(const char *filename)
Definition: ffserver.c:3960
#define FF_QP2LAMBDA
factor to convert from H.263 QP to lambda
Definition: avutil.h:169
static void new_connection(int server_fd, int is_rtsp)
Definition: ffserver.c:804
static char * ctime1(char *buf2, int buf_size)
Definition: ffserver.c:399
char session_id[32]
Definition: ffserver.c:182
including without damages for loss of work computer failure or loss of data or any commercial damage and lost revenue or even if the UPF has been advised of the possibility of such damage the UPF will be liable under statutory product liability laws as far such laws apply to the Software The foregoing limitations will apply even if the above stated warranty disclaimer fails of its essential purpose Some jurisdictions do not allow the exclusion of indirect or consequential so some of the terms above may not be applicable to you AUDIT Upon days written UPF or a professional designated by UPF may audit your use of the Software You agree to cooperate with UPF s audit and provide reasonable assistance and access to information You agree to pay within days of written notification any fees applicable to your use of the Software in breach of your license rights If you do not UPF can end your license You agree that UPF shall not be responsible for any of your costs incurred in cooperating with the audit TERMINATION This Agreement is effective until terminated You may terminate this Agreement at any time by destroying all copies of Software This Agreement will terminate immediately without notice from UPF if you fail to comply with any provision of this Agreement Either party may terminate this Agreement immediately should any Software or in either party s opinion be likely to the subject of a claim of infringement of any intellectual or industrial property right Upon you must destroy all copies of Software Provisions that survive termination or expiration include those relating to limitation of liability limitation and others which by their nature are intended to and apply to both parties respective successors and assignees EXPORT REGULATIONS Software and technical data delivered under this Agreement may be subject to export or import regulations You agree to comply strictly with all such laws and regulations and acknowledge that you have the responsibility to obtain such licenses to re or import as may be required after delivery to you TRADEMARKS This Licence does not grant permission to use the trade service or names of the except as required for reasonable and customary use in describing the origin of the Software and reproducing the content of the copyright notice GOVERNING LAW JURISDICTION Any action related to this Agreement will be governed by Spanish law No choice of law rules of any jurisdiction will apply Any action
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...
static int ffserver_opt_preset(const char *arg, AVCodecContext *avctx, int type, enum AVCodecID *audio_id, enum AVCodecID *video_id)
Definition: ffserver.c:3993
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:769
int frame_number
Frame counter, set by libavcodec.
int max_packet_size
if non zero, the stream is packetized with this max packet size
Definition: url.h:47
AVFormatContext * rtp_ctx[MAX_STREAMS]
Definition: ffserver.c:183
static void rtsp_cmd_setup(HTTPContext *c, const char *url, RTSPMessageHeader *h)
Definition: ffserver.c:3089
static const char * video_codec_name
Definition: ffplay.c:311
static AVOutputFormat * ffserver_guess_format(const char *short_name, const char *filename, const char *mime_type)
Definition: ffserver.c:4036
void INT64 INT64 count
Definition: avisynth_c.h:594
RTSP Version not supported.
Definition: rtspcodes.h:37
int pts_stream_index
Definition: ffserver.c:154
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:461
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:105
static int add_av_stream(FFStream *feed, AVStream *st)
Definition: ffserver.c:3540
unsigned bandwidth
Definition: ffserver.c:240
Internal Server Error.
Definition: rtspcodes.h:35
int me_method
Motion estimation algorithm used for video coding.
enum HTTPState state
Definition: ffserver.c:130
Session Not Found.
Definition: rtspcodes.h:30
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:679
int rc_min_rate
minimum bitrate
AVStream * streams[MAX_STREAMS]
Definition: ffserver.c:228
static void handle_child_exit(int sig)
Definition: ffserver.c:4658
#define MKTAG(a, b, c, d)
Definition: common.h:282
struct sockaddr * ai_addr
Definition: network.h:120
#define CODEC_FLAG_4MV
4 MV per MB allowed / advanced prediction for H.263.
const char * mime_type
Definition: avformat.h:385
This structure stores compressed data.
void av_register_all(void)
Initialize libavformat and register all the muxers, demuxers and protocols.
Definition: allformats.c:52
char * rtsp_option
Definition: ffserver.c:242
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition: opt.c:252
#define AVFMT_FLAG_NOFILLIN
Do not infer any values from other values, just return what is stored in the container.
Definition: avformat.h:1026
static unsigned int nb_max_connections
Definition: ffserver.c:319
int strict_std_compliance
strictly follow the standard (MPEG4, ...).
static void skip_spaces(const char **pp)
Definition: ffserver.c:1244
static void fmt_bytecount(AVIOContext *pb, int64_t count)
Definition: ffserver.c:1912
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
AVDictionary * in_opts
Definition: ffserver.c:219
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:190
#define HTTP_REQUEST_TIMEOUT
Definition: ffserver.c:113
#define c1
Definition: idct_sh4.c:26
static int http_prepare_data(HTTPContext *c)
Definition: ffserver.c:2257
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:100
static void add_codec(FFStream *stream, AVCodecContext *av)
Definition: ffserver.c:3859
int64_t cur_frame_duration
Definition: ffserver.c:150
static void rtsp_cmd_pause(HTTPContext *c, const char *url, RTSPMessageHeader *h)
Definition: ffserver.c:3295
static int http_start_receive_data(HTTPContext *c)
Definition: ffserver.c:2606
static int no_launch
Definition: ffserver.c:314
int feed_fd
Definition: ffserver.c:144
int ai_family
Definition: network.h:116