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